1
0
mirror of https://github.com/gryf/wmaker.git synced 2026-01-08 14:54:13 +01:00

added drag and drop

This commit is contained in:
kojima
2000-04-03 06:08:31 +00:00
parent 60a247f271
commit 567e53c67c
6 changed files with 383 additions and 60 deletions

View File

@@ -56,22 +56,19 @@ Widgets provided by WINGs:
- slider
- scrollable view
- color well
- split view (only 2 subviews)
- split view
- tabbed view
- progress indicator
- selection (make pasteboard like?)
- drag&drop
- input box
- file panel
- color panel
- alert panel
- font panel
Planned:
--------
- selection (pasteboard like)
- drag&drop
If you think you can code the following, please do. They are needed by
WPrefs.app, but the number of other things I have to do is huge.
@@ -84,7 +81,6 @@ Wish list: (I don't have the know-how or time to do them)
- text (with support for RTF)
- matrix (like NSMatrix)
- splitviews with more than 2 subviews
- font manager (like NSFontManager)
- finish other wigets
- optimize list scrolling (XCopyArea() the area that's already drawn)

View File

@@ -612,11 +612,21 @@ Bool WMRequestSelection(WMView *view, Atom selection, Atom target,
/* ....................................................................... */
/*
void WMDragImageFromView(WMView *view, WMPixmap *image, WMPoint atLocation,
WMSize mouseOffset, XEvent *event, Bool slideBack);
*/
void WMSetViewDragSourceProcs(WMView *view, WMDragSourceProcs *procs);
void WMDragImageFromView(WMView *view, WMPixmap *image, char *dataTypes[],
WMPoint atLocation, WMSize mouseOffset, XEvent *event,
Bool slideBack);
void WMRegisterViewForDraggedTypes(WMView *view, char *acceptedTypes[]);
void WMUnregisterViewDraggedTypes(WMView *view);
void WMSetViewDragDestinationProcs(WMView *view, WMDragDestinationProcs *procs);
WMPoint WMGetDraggingInfoImageLocation(WMDraggingInfo *info);
/* ....................................................................... */

View File

@@ -100,7 +100,9 @@ struct W_DraggingInfo {
unsigned sourceOperation;
WMPixmap *image;
WMPoint imageLocation;
char **types;
Time timestamp;
int protocolVersion;

View File

@@ -23,8 +23,8 @@ static void
realizedObserver(void *self, WMNotification *notif)
{
WMView *view = (WMView*)WMGetNotificationObject(notif);
XChangeProperty(W_VIEW_SCREEN(view)->display, W_VIEW_DRAWABLE(view),
XChangeProperty(W_VIEW_SCREEN(view)->display, W_VIEW_DRAWABLE(view),
W_VIEW_SCREEN(view)->xdndAwareAtom,
XA_ATOM, 32, PropModeReplace,
(unsigned char*)&XDNDversion, 1);
@@ -48,10 +48,11 @@ W_SetXdndAwareProperty(WMScreen *scr, WMView *view, Atom *types, int typeCount)
XA_ATOM, 32, PropModeReplace,
(unsigned char*)&XDNDversion, 1);
} else {
WMAddNotificationObserver(realizedObserver, view,
WMViewRealizedNotification,
WMAddNotificationObserver(realizedObserver,
/* just use as an id */
view->dragDestinationProcs);
&view->dragDestinationProcs,
WMViewRealizedNotification,
view);
}
}
}
@@ -161,3 +162,9 @@ WMSetViewDragDestinationProcs(WMView *view, WMDragDestinationProcs *procs)
WMPoint WMGetDraggingInfoImageLocation(WMDraggingInfo *info)
{
return info->imageLocation;
}

View File

@@ -1,8 +1,17 @@
#include "../src/config.h"
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#ifdef SHAPE
#include <X11/extensions/shape.h>
#endif
#include <math.h>
#include "WINGsP.h"
@@ -22,6 +31,27 @@ static Bool _XErrorOccured = False;
static unsigned defDraggingSourceOperation(WMView *self, Bool local)
{
return WDOperationCopy;
}
static void defBeganDragImage(WMView *self, WMPixmap *image, WMPoint point)
{
}
static void defEndedDragImage(WMView *self, WMPixmap *image, WMPoint point,
Bool deposited)
{
}
static WMData* defFetchDragData(WMView *self, char *type)
{
return NULL;
}
void
WMSetViewDragSourceProcs(WMView *view, WMDragSourceProcs *procs)
@@ -31,8 +61,19 @@ WMSetViewDragSourceProcs(WMView *view, WMDragSourceProcs *procs)
view->dragSourceProcs = wmalloc(sizeof(WMDragSourceProcs));
*view->dragSourceProcs = *procs;
/* XXX fill in non-implemented stuffs */
if (procs->draggingSourceOperation == NULL) {
view->dragSourceProcs->draggingSourceOperation = defDraggingSourceOperation;
}
if (procs->beganDragImage == NULL) {
view->dragSourceProcs->beganDragImage = defBeganDragImage;
}
if (procs->endedDragImage == NULL) {
view->dragSourceProcs->endedDragImage = defEndedDragImage;
}
if (procs->fetchDragData == NULL) {
view->dragSourceProcs->fetchDragData = defFetchDragData;
}
}
@@ -90,7 +131,7 @@ makeDragIcon(WMScreen *scr, WMPixmap *pixmap)
#ifdef SHAPE
if (mask) {
XShapeCombineMask(dpy, scr->balloon->window, ShapeBounding, 0, 0, mask,
XShapeCombineMask(scr->display, window, ShapeBounding, 0, 0, mask,
ShapeSet);
}
#endif
@@ -147,15 +188,16 @@ findChildInWindow(Display *dpy, Window toplevel, int x, int y)
&& attr.map_state == IsViewable
&& x >= attr.x && y >= attr.y
&& x < attr.x + attr.width && y < attr.y + attr.height) {
Window child;
Window child, tmp;
child = findChildInWindow(dpy, children[i],
x - attr.x, y - attr.y);
tmp = children[i];
child = findChildInWindow(dpy, tmp, x - attr.x, y - attr.y);
XFree(children);
if (child == None)
return toplevel;
return tmp;
else
return child;
}
@@ -172,11 +214,12 @@ findViewInToplevel(Display *dpy, Window toplevel, int x, int y)
Window child;
child = findChildInWindow(dpy, toplevel, x, y);
if (child != None)
if (child != None) {
return W_GetViewForXWindow(dpy, child);
else
} else {
return NULL;
}
}
@@ -385,29 +428,26 @@ translateCoordinates(WMScreen *scr, Window target, int fromX, int fromY,
static void
updateDraggingInfo(WMScreen *scr, WMDraggingInfo *info,
updateDraggingInfo(WMScreen *scr, WMDraggingInfo *info, WMSize offset,
XEvent *event, Window iconWindow)
{
Window toplevel;
WMSize size;
size = WMGetPixmapSize(info->image);
if (event->type == MotionNotify) {
info->imageLocation.x = event->xmotion.x_root-(int)size.width/2;
info->imageLocation.y = event->xmotion.y_root-(int)size.height/2;
info->imageLocation.x = event->xmotion.x_root-offset.width;
info->imageLocation.y = event->xmotion.y_root-offset.height;
info->location.x = event->xmotion.x_root;
info->location.y = event->xmotion.y_root;
info->timestamp = event->xmotion.time;
/* info->timestamp = event->xmotion.time;*/
} else if (event->type == ButtonRelease) {
info->imageLocation.x = event->xbutton.x_root-(int)size.width/2;
info->imageLocation.y = event->xbutton.y_root-(int)size.height/2;
info->imageLocation.x = event->xbutton.x_root-offset.width;
info->imageLocation.y = event->xbutton.y_root-offset.height;
info->location.x = event->xbutton.x_root;
info->location.y = event->xbutton.y_root;
info->timestamp = event->xbutton.time;
/* info->timestamp = event->xbutton.time;*/
}
toplevel = findToplevelUnderDragPointer(scr,
@@ -500,6 +540,7 @@ selectionLost(WMView *view, Atom selection, void *cdata)
{
if (W_VIEW_SCREEN(view)->dragSourceView == view) {
wwarning("DND selection lost during drag operation...");
W_VIEW_SCREEN(view)->dragSourceView = NULL;
}
}
@@ -573,7 +614,6 @@ WMDragImageFromView(WMView *view, WMPixmap *image, char *dataTypes[],
Display *dpy = scr->display;
Window icon;
XEvent ev;
WMSize size;
WMRect rect = {{0,0},{0,0}};
int ostate = -1;
int state;
@@ -591,7 +631,8 @@ WMDragImageFromView(WMView *view, WMPixmap *image, char *dataTypes[],
};
wassertr(scr->dragSourceView == NULL);
if (scr->dragSourceView != NULL)
return;
wassertr(view->dragSourceProcs != NULL);
@@ -600,12 +641,9 @@ WMDragImageFromView(WMView *view, WMPixmap *image, char *dataTypes[],
if (image == NULL)
image = scr->defaultObjectIcon;
size = WMGetPixmapSize(image);
icon = makeDragIcon(scr, image);
XMoveWindow(dpy, icon, event->xmotion.x_root-(int)size.width/2,
event->xmotion.y_root-(int)size.height/2);
XMoveWindow(dpy, icon, atLocation.x, atLocation.y);
XMapRaised(dpy, icon);
@@ -621,8 +659,8 @@ WMDragImageFromView(WMView *view, WMPixmap *image, char *dataTypes[],
dragInfo.destinationWindow = dragInfo.sourceWindow;
dragInfo.location.x = event->xmotion.x_root;
dragInfo.location.y = event->xmotion.y_root;
dragInfo.location.x = atLocation.x + mouseOffset.width;
dragInfo.location.y = atLocation.y + mouseOffset.height;
dragInfo.imageLocation = atLocation;
@@ -665,7 +703,7 @@ WMDragImageFromView(WMView *view, WMPixmap *image, char *dataTypes[],
oldDragInfo = dragInfo;
updateDraggingInfo(scr, &dragInfo, &ev, icon);
updateDraggingInfo(scr, &dragInfo, mouseOffset, &ev, icon);
XMoveWindow(dpy, icon, dragInfo.imageLocation.x,
dragInfo.imageLocation.y);
@@ -720,11 +758,15 @@ WMDragImageFromView(WMView *view, WMPixmap *image, char *dataTypes[],
oldDragInfo = dragInfo;
updateDraggingInfo(scr, &dragInfo, &ev, icon);
updateDraggingInfo(scr, &dragInfo, mouseOffset, &ev, icon);
XMoveWindow(dpy, icon, dragInfo.imageLocation.x,
dragInfo.imageLocation.y);
if (state == 4 || state == 1) {
dragInfo.destinationWindow = None;
dragInfo.destView = NULL;
}
processMotion(scr, &dragInfo, &oldDragInfo, &rect, action);
dragInfo.timestamp = ev.xbutton.time;
@@ -1042,10 +1084,12 @@ W_HandleDNDClientMessage(WMView *toplevel, XClientMessageEvent *event)
source = scr->dragInfo.sourceWindow;
oldView = scr->dragInfo.destView;
if (event->message_type == scr->xdndFinishedAtom) {
WMView *view = scr->dragSourceView;
WMDeleteSelectionHandler(view, scr->xdndSelectionAtom,
scr->dragInfo.timestamp);
if (view->dragSourceProcs->endedDragImage != NULL) {
view->dragSourceProcs->endedDragImage(view,
scr->dragInfo.image,
@@ -1055,14 +1099,10 @@ W_HandleDNDClientMessage(WMView *toplevel, XClientMessageEvent *event)
scr->dragSourceView = NULL;
WMDeleteSelectionHandler(view, scr->xdndSelectionAtom,
scr->dragInfo.timestamp);
return;
}
if (event->message_type == scr->xdndEnterAtom) {
Window foo, bar;
@@ -1099,14 +1139,16 @@ W_HandleDNDClientMessage(WMView *toplevel, XClientMessageEvent *event)
newView = findViewInToplevel(scr->display,
scr->dragInfo.destinationWindow,
x, y);
scr->dragInfo.destinationWindow,
x, y);
} else if (event->message_type == scr->xdndPositionAtom
&& scr->dragInfo.sourceWindow == event->data.l[0]) {
scr->dragInfo.location.x = event->data.l[2] >> 16;
scr->dragInfo.location.y = event->data.l[2] & 0xffff;
scr->dragInfo.imageLocation = scr->dragInfo.location;
if (scr->dragInfo.protocolVersion >= 1) {
scr->dragInfo.timestamp = event->data.l[3];
@@ -1135,8 +1177,9 @@ W_HandleDNDClientMessage(WMView *toplevel, XClientMessageEvent *event)
&& scr->dragInfo.sourceWindow == event->data.l[0]) {
/* drop */
what = WDrop;
if (oldView != NULL)
what = WDrop;
} else {
return;
}
@@ -1148,7 +1191,7 @@ W_HandleDNDClientMessage(WMView *toplevel, XClientMessageEvent *event)
if (what == WNothing) {
if (IS_DROPPABLE(newView)) {
if (oldView == NULL) { /* entered */
if (!IS_DROPPABLE(oldView)) { /* entered */
what = WEnter;
} else if (oldView == newView) { /* updated */
what = WUpdate;
@@ -1156,7 +1199,7 @@ W_HandleDNDClientMessage(WMView *toplevel, XClientMessageEvent *event)
what = WCross;
}
} else {
if (oldView != NULL) {
if (IS_DROPPABLE(oldView)) {
what = WLeave;
} else {
/* just send rejection msg */

View File

@@ -667,6 +667,267 @@ testSplitView(WMScreen *scr)
WMMapWidget(win);
}
/*******************************************************************/
#include <sys/types.h>
#include <dirent.h>
#include <string.h>
typedef struct {
int x, y;
Bool mouseDown;
char *filename;
} DNDStuff;
WMPixmap*
getImage(WMScreen *scr, char *file)
{
char buffer[1000];
WMPixmap *pix;
sprintf(buffer, "../WindowMaker/Icons/%s", file);
pix = WMCreatePixmapFromFile(scr, buffer);
return pix;
}
static void iconMouseStuff(XEvent *event, void *cdata)
{
WMLabel *label = (WMLabel*)cdata;
DNDStuff *stuff = WMGetHangedData(label);
WMPoint where;
switch (event->type) {
case ButtonPress:
stuff->x = event->xbutton.x_root;
stuff->y = event->xbutton.y_root;
stuff->mouseDown = True;
break;
case ButtonRelease:
stuff->mouseDown = False;
break;
case MotionNotify:
if (!stuff->mouseDown)
break;
if (abs(stuff->x - event->xmotion.x_root)>4
|| abs(stuff->y - event->xmotion.y_root)>4) {
where = WMGetViewScreenPosition(WMWidgetView(label));
WMDragImageFromView(WMWidgetView(label),
WMGetLabelImage(label),
NULL, /* XXX */
where,
wmksize(event->xmotion.x, event->xmotion.y),
event, True);
}
break;
}
}
static void endedDragImage(WMView *self, WMPixmap *image, WMPoint point,
Bool deposited)
{
DNDStuff *stuff = WMGetHangedData(WMWidgetOfView(self));
if (deposited) {
WMDestroyWidget(WMWidgetOfView(self));
}
stuff->mouseDown = False;
}
static WMData* fetchDragData(WMView *self, char *type)
{
DNDStuff *stuff = WMGetHangedData(WMWidgetOfView(self));
return WMCreateDataWithBytes(stuff->filename, strlen(stuff->filename)+1);
}
WMDragSourceProcs dragSourceProcs = {
NULL,
NULL,
endedDragImage,
fetchDragData
};
/************************/
unsigned draggingEntered(WMView *self, WMDraggingInfo *info)
{
return WDOperationCopy;
}
unsigned draggingUpdated(WMView *self, WMDraggingInfo *info)
{
return WDOperationCopy;
}
/*
void (*draggingExited)(WMView *self, WMDraggingInfo *info);
*/
char *prepareForDragOperation(WMView *self, WMDraggingInfo *info)
{
return "application/X-WINGs-Bla";
}
WMLabel *makeDraggableLabel(WMWidget *w, char *file, int x, int y);
Bool performDragOperation(WMView *self, WMDraggingInfo *info,
WMData *data)
{
char *file = (char*)WMDataBytes(data);
WMPoint pos;
pos = WMGetDraggingInfoImageLocation(info);
if (file!=NULL) {
WMLabel *label;
WMPoint pos2 = WMGetViewScreenPosition(self);
label = makeDraggableLabel(WMWidgetOfView(self), file,
pos.x-pos2.x, pos.y-pos2.y);
WMRealizeWidget(label);
WMMapWidget(label);
}
return True;
}
void concludeDragOperation(WMView *self, WMDraggingInfo *info)
{
puts("concluded");
}
WMDragDestinationProcs dragDestProcs = {
draggingEntered,
draggingUpdated,
NULL,
prepareForDragOperation,
performDragOperation,
concludeDragOperation
};
WMLabel*
makeDraggableLabel(WMWidget *w, char *file, int x, int y)
{
DNDStuff *stuff;
WMLabel *label;
WMPixmap *image = getImage(WMWidgetScreen(w), file);
stuff = wmalloc(sizeof(DNDStuff));
stuff->mouseDown = False;
stuff->filename = wstrdup(file);
label = WMCreateLabel(w);
WMResizeWidget(label, 48, 48);
WMMoveWidget(label, x, y);
WMSetViewDragSourceProcs(WMWidgetView(label), &dragSourceProcs);
WMHangData(label, stuff);
WMCreateEventHandler(WMWidgetView(label),
ButtonPressMask|ButtonReleaseMask|ButtonMotionMask,
iconMouseStuff, label);
WMSetLabelImagePosition(label, WIPImageOnly);
WMSetLabelImage(label, image);
WMReleasePixmap(image);
return label;
}
void testDragAndDrop(WMScreen *scr)
{
WMWindow *win;
WMFrame *frame;
WMLabel *label;
int i, j;
DIR *dir;
struct dirent *ent;
char *types[] = {
"application/X-WINGs-Bla",
NULL
};
windowCount++;
win = WMCreateWindow(scr, "dragDrop");
WMResizeWidget(win, 300, 300);
WMSetWindowCloseAction(win, closeAction, NULL);
WMSetWindowTitle(win, "Drag and Drop");
frame = WMCreateFrame(win);
WMSetFrameRelief(frame, WRSunken);
WMResizeWidget(frame, 250, 250);
WMMoveWidget(frame, 25, 25);
WMRegisterViewForDraggedTypes(WMWidgetView(frame), types);
WMSetViewDragDestinationProcs(WMWidgetView(frame), &dragDestProcs);
dir = opendir("../WindowMaker/Icons");
if (!dir) {
perror("../WindowMaker/Icons");
return;
}
for (i = 0, j=0; j < 8; i++) {
ent = readdir(dir);
if (!ent)
break;
if (strstr(ent->d_name, ".xpm")==NULL) {
continue;
}
label = makeDraggableLabel(frame, ent->d_name,4+(j/4)*64, 4+(j%4)*64);
j++;
}
closedir(dir);
WMMapSubwidgets(frame);
WMMapSubwidgets(win);
WMRealizeWidget(win);
WMMapWidget(win);
}
/*******************************************************************/
#include "WUtil.h"
@@ -718,9 +979,13 @@ int main(int argc, char **argv)
* Put the testSomething() function you want to test here.
*/
testDragAndDrop(scr);
testDragAndDrop(scr);
testColorWell(scr);
#if 0
testColorWell(scr);
testTabView(scr);
testFontPanel(scr);