1
0
mirror of https://github.com/gryf/wmaker.git synced 2026-01-30 20:35:49 +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 - slider
- scrollable view - scrollable view
- color well - color well
- split view (only 2 subviews) - split view
- tabbed view - tabbed view
- progress indicator - progress indicator
- selection (make pasteboard like?)
- drag&drop
- input box - input box
- file panel - file panel
- color panel - color panel
- alert panel - alert panel
- font panel - font panel
Planned:
--------
- selection (pasteboard like)
- drag&drop
If you think you can code the following, please do. They are needed by 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. 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) - text (with support for RTF)
- matrix (like NSMatrix) - matrix (like NSMatrix)
- splitviews with more than 2 subviews
- font manager (like NSFontManager) - font manager (like NSFontManager)
- finish other wigets - finish other wigets
- optimize list scrolling (XCopyArea() the area that's already drawn) - 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; unsigned sourceOperation;
WMPixmap *image; WMPixmap *image;
WMPoint imageLocation; WMPoint imageLocation;
char **types;
Time timestamp; Time timestamp;
int protocolVersion; int protocolVersion;

View File

@@ -23,8 +23,8 @@ static void
realizedObserver(void *self, WMNotification *notif) realizedObserver(void *self, WMNotification *notif)
{ {
WMView *view = (WMView*)WMGetNotificationObject(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, W_VIEW_SCREEN(view)->xdndAwareAtom,
XA_ATOM, 32, PropModeReplace, XA_ATOM, 32, PropModeReplace,
(unsigned char*)&XDNDversion, 1); (unsigned char*)&XDNDversion, 1);
@@ -48,10 +48,11 @@ W_SetXdndAwareProperty(WMScreen *scr, WMView *view, Atom *types, int typeCount)
XA_ATOM, 32, PropModeReplace, XA_ATOM, 32, PropModeReplace,
(unsigned char*)&XDNDversion, 1); (unsigned char*)&XDNDversion, 1);
} else { } else {
WMAddNotificationObserver(realizedObserver, view, WMAddNotificationObserver(realizedObserver,
WMViewRealizedNotification,
/* just use as an id */ /* 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> #include <X11/Xatom.h>
#ifdef SHAPE
#include <X11/extensions/shape.h>
#endif
#include <math.h> #include <math.h>
#include "WINGsP.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 void
WMSetViewDragSourceProcs(WMView *view, WMDragSourceProcs *procs) WMSetViewDragSourceProcs(WMView *view, WMDragSourceProcs *procs)
@@ -31,8 +61,19 @@ WMSetViewDragSourceProcs(WMView *view, WMDragSourceProcs *procs)
view->dragSourceProcs = wmalloc(sizeof(WMDragSourceProcs)); view->dragSourceProcs = wmalloc(sizeof(WMDragSourceProcs));
*view->dragSourceProcs = *procs; *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 #ifdef SHAPE
if (mask) { if (mask) {
XShapeCombineMask(dpy, scr->balloon->window, ShapeBounding, 0, 0, mask, XShapeCombineMask(scr->display, window, ShapeBounding, 0, 0, mask,
ShapeSet); ShapeSet);
} }
#endif #endif
@@ -147,15 +188,16 @@ findChildInWindow(Display *dpy, Window toplevel, int x, int y)
&& attr.map_state == IsViewable && attr.map_state == IsViewable
&& x >= attr.x && y >= attr.y && x >= attr.x && y >= attr.y
&& x < attr.x + attr.width && y < attr.y + attr.height) { && x < attr.x + attr.width && y < attr.y + attr.height) {
Window child; Window child, tmp;
child = findChildInWindow(dpy, children[i], tmp = children[i];
x - attr.x, y - attr.y);
child = findChildInWindow(dpy, tmp, x - attr.x, y - attr.y);
XFree(children); XFree(children);
if (child == None) if (child == None)
return toplevel; return tmp;
else else
return child; return child;
} }
@@ -172,11 +214,12 @@ findViewInToplevel(Display *dpy, Window toplevel, int x, int y)
Window child; Window child;
child = findChildInWindow(dpy, toplevel, x, y); child = findChildInWindow(dpy, toplevel, x, y);
if (child != None) if (child != None) {
return W_GetViewForXWindow(dpy, child); return W_GetViewForXWindow(dpy, child);
else } else {
return NULL; return NULL;
}
} }
@@ -385,29 +428,26 @@ translateCoordinates(WMScreen *scr, Window target, int fromX, int fromY,
static void static void
updateDraggingInfo(WMScreen *scr, WMDraggingInfo *info, updateDraggingInfo(WMScreen *scr, WMDraggingInfo *info, WMSize offset,
XEvent *event, Window iconWindow) XEvent *event, Window iconWindow)
{ {
Window toplevel; Window toplevel;
WMSize size;
size = WMGetPixmapSize(info->image);
if (event->type == MotionNotify) { if (event->type == MotionNotify) {
info->imageLocation.x = event->xmotion.x_root-(int)size.width/2; info->imageLocation.x = event->xmotion.x_root-offset.width;
info->imageLocation.y = event->xmotion.y_root-(int)size.height/2; info->imageLocation.y = event->xmotion.y_root-offset.height;
info->location.x = event->xmotion.x_root; info->location.x = event->xmotion.x_root;
info->location.y = event->xmotion.y_root; info->location.y = event->xmotion.y_root;
info->timestamp = event->xmotion.time; /* info->timestamp = event->xmotion.time;*/
} else if (event->type == ButtonRelease) { } else if (event->type == ButtonRelease) {
info->imageLocation.x = event->xbutton.x_root-(int)size.width/2; info->imageLocation.x = event->xbutton.x_root-offset.width;
info->imageLocation.y = event->xbutton.y_root-(int)size.height/2; info->imageLocation.y = event->xbutton.y_root-offset.height;
info->location.x = event->xbutton.x_root; info->location.x = event->xbutton.x_root;
info->location.y = event->xbutton.y_root; info->location.y = event->xbutton.y_root;
info->timestamp = event->xbutton.time; /* info->timestamp = event->xbutton.time;*/
} }
toplevel = findToplevelUnderDragPointer(scr, toplevel = findToplevelUnderDragPointer(scr,
@@ -500,6 +540,7 @@ selectionLost(WMView *view, Atom selection, void *cdata)
{ {
if (W_VIEW_SCREEN(view)->dragSourceView == view) { if (W_VIEW_SCREEN(view)->dragSourceView == view) {
wwarning("DND selection lost during drag operation..."); 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; Display *dpy = scr->display;
Window icon; Window icon;
XEvent ev; XEvent ev;
WMSize size;
WMRect rect = {{0,0},{0,0}}; WMRect rect = {{0,0},{0,0}};
int ostate = -1; int ostate = -1;
int state; 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); wassertr(view->dragSourceProcs != NULL);
@@ -600,12 +641,9 @@ WMDragImageFromView(WMView *view, WMPixmap *image, char *dataTypes[],
if (image == NULL) if (image == NULL)
image = scr->defaultObjectIcon; image = scr->defaultObjectIcon;
size = WMGetPixmapSize(image);
icon = makeDragIcon(scr, image); icon = makeDragIcon(scr, image);
XMoveWindow(dpy, icon, event->xmotion.x_root-(int)size.width/2, XMoveWindow(dpy, icon, atLocation.x, atLocation.y);
event->xmotion.y_root-(int)size.height/2);
XMapRaised(dpy, icon); XMapRaised(dpy, icon);
@@ -621,8 +659,8 @@ WMDragImageFromView(WMView *view, WMPixmap *image, char *dataTypes[],
dragInfo.destinationWindow = dragInfo.sourceWindow; dragInfo.destinationWindow = dragInfo.sourceWindow;
dragInfo.location.x = event->xmotion.x_root; dragInfo.location.x = atLocation.x + mouseOffset.width;
dragInfo.location.y = event->xmotion.y_root; dragInfo.location.y = atLocation.y + mouseOffset.height;
dragInfo.imageLocation = atLocation; dragInfo.imageLocation = atLocation;
@@ -665,7 +703,7 @@ WMDragImageFromView(WMView *view, WMPixmap *image, char *dataTypes[],
oldDragInfo = dragInfo; oldDragInfo = dragInfo;
updateDraggingInfo(scr, &dragInfo, &ev, icon); updateDraggingInfo(scr, &dragInfo, mouseOffset, &ev, icon);
XMoveWindow(dpy, icon, dragInfo.imageLocation.x, XMoveWindow(dpy, icon, dragInfo.imageLocation.x,
dragInfo.imageLocation.y); dragInfo.imageLocation.y);
@@ -720,11 +758,15 @@ WMDragImageFromView(WMView *view, WMPixmap *image, char *dataTypes[],
oldDragInfo = dragInfo; oldDragInfo = dragInfo;
updateDraggingInfo(scr, &dragInfo, &ev, icon); updateDraggingInfo(scr, &dragInfo, mouseOffset, &ev, icon);
XMoveWindow(dpy, icon, dragInfo.imageLocation.x, XMoveWindow(dpy, icon, dragInfo.imageLocation.x,
dragInfo.imageLocation.y); dragInfo.imageLocation.y);
if (state == 4 || state == 1) {
dragInfo.destinationWindow = None;
dragInfo.destView = NULL;
}
processMotion(scr, &dragInfo, &oldDragInfo, &rect, action); processMotion(scr, &dragInfo, &oldDragInfo, &rect, action);
dragInfo.timestamp = ev.xbutton.time; dragInfo.timestamp = ev.xbutton.time;
@@ -1042,10 +1084,12 @@ W_HandleDNDClientMessage(WMView *toplevel, XClientMessageEvent *event)
source = scr->dragInfo.sourceWindow; source = scr->dragInfo.sourceWindow;
oldView = scr->dragInfo.destView; oldView = scr->dragInfo.destView;
if (event->message_type == scr->xdndFinishedAtom) { if (event->message_type == scr->xdndFinishedAtom) {
WMView *view = scr->dragSourceView; WMView *view = scr->dragSourceView;
WMDeleteSelectionHandler(view, scr->xdndSelectionAtom,
scr->dragInfo.timestamp);
if (view->dragSourceProcs->endedDragImage != NULL) { if (view->dragSourceProcs->endedDragImage != NULL) {
view->dragSourceProcs->endedDragImage(view, view->dragSourceProcs->endedDragImage(view,
scr->dragInfo.image, scr->dragInfo.image,
@@ -1055,14 +1099,10 @@ W_HandleDNDClientMessage(WMView *toplevel, XClientMessageEvent *event)
scr->dragSourceView = NULL; scr->dragSourceView = NULL;
WMDeleteSelectionHandler(view, scr->xdndSelectionAtom,
scr->dragInfo.timestamp);
return; return;
} }
if (event->message_type == scr->xdndEnterAtom) { if (event->message_type == scr->xdndEnterAtom) {
Window foo, bar; Window foo, bar;
@@ -1099,14 +1139,16 @@ W_HandleDNDClientMessage(WMView *toplevel, XClientMessageEvent *event)
newView = findViewInToplevel(scr->display, newView = findViewInToplevel(scr->display,
scr->dragInfo.destinationWindow, scr->dragInfo.destinationWindow,
x, y); x, y);
} else if (event->message_type == scr->xdndPositionAtom } else if (event->message_type == scr->xdndPositionAtom
&& scr->dragInfo.sourceWindow == event->data.l[0]) { && scr->dragInfo.sourceWindow == event->data.l[0]) {
scr->dragInfo.location.x = event->data.l[2] >> 16; scr->dragInfo.location.x = event->data.l[2] >> 16;
scr->dragInfo.location.y = event->data.l[2] & 0xffff; scr->dragInfo.location.y = event->data.l[2] & 0xffff;
scr->dragInfo.imageLocation = scr->dragInfo.location;
if (scr->dragInfo.protocolVersion >= 1) { if (scr->dragInfo.protocolVersion >= 1) {
scr->dragInfo.timestamp = event->data.l[3]; scr->dragInfo.timestamp = event->data.l[3];
@@ -1135,8 +1177,9 @@ W_HandleDNDClientMessage(WMView *toplevel, XClientMessageEvent *event)
&& scr->dragInfo.sourceWindow == event->data.l[0]) { && scr->dragInfo.sourceWindow == event->data.l[0]) {
/* drop */ /* drop */
what = WDrop; if (oldView != NULL)
what = WDrop;
} else { } else {
return; return;
} }
@@ -1148,7 +1191,7 @@ W_HandleDNDClientMessage(WMView *toplevel, XClientMessageEvent *event)
if (what == WNothing) { if (what == WNothing) {
if (IS_DROPPABLE(newView)) { if (IS_DROPPABLE(newView)) {
if (oldView == NULL) { /* entered */ if (!IS_DROPPABLE(oldView)) { /* entered */
what = WEnter; what = WEnter;
} else if (oldView == newView) { /* updated */ } else if (oldView == newView) { /* updated */
what = WUpdate; what = WUpdate;
@@ -1156,7 +1199,7 @@ W_HandleDNDClientMessage(WMView *toplevel, XClientMessageEvent *event)
what = WCross; what = WCross;
} }
} else { } else {
if (oldView != NULL) { if (IS_DROPPABLE(oldView)) {
what = WLeave; what = WLeave;
} else { } else {
/* just send rejection msg */ /* just send rejection msg */

View File

@@ -667,6 +667,267 @@ testSplitView(WMScreen *scr)
WMMapWidget(win); 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" #include "WUtil.h"
@@ -718,9 +979,13 @@ int main(int argc, char **argv)
* Put the testSomething() function you want to test here. * Put the testSomething() function you want to test here.
*/ */
testDragAndDrop(scr);
testDragAndDrop(scr);
testColorWell(scr);
#if 0 #if 0
testColorWell(scr);
testTabView(scr); testTabView(scr);
testFontPanel(scr); testFontPanel(scr);