summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Reveman <davidr@novell.com>2008-10-17 15:02:45 -0400
committerDavid Reveman <davidr@novell.com>2008-10-30 03:37:51 -0400
commit6a7948491b282e5345d26eb9fffaee48e426f338 (patch)
treea0f995370c3a2e0731b7f0bd6ae089b4285ea418
parent1df5903f9a4889ef5059438ce3050eacf5f1d90a (diff)
Initial back-end server DND target support.
-rw-r--r--hw/dmx/dmx.h5
-rw-r--r--hw/dmx/dmxdnd.c963
-rw-r--r--hw/dmx/dmxdnd.h6
-rw-r--r--hw/dmx/dmxinput.c34
-rw-r--r--hw/dmx/dmxselection.c12
5 files changed, 923 insertions, 97 deletions
diff --git a/hw/dmx/dmx.h b/hw/dmx/dmx.h
index 6a2aafcac..bdb6205da 100644
--- a/hw/dmx/dmx.h
+++ b/hw/dmx/dmx.h
@@ -143,6 +143,8 @@ typedef struct _DMXInputInfo {
int eventBase;
} DMXInputInfo;
+typedef struct _DMXDnDChild DMXDnDChild;
+
/** Global structure containing information about each backend screen. */
typedef struct _DMXScreenInfo {
DMXInputInfo input;
@@ -273,6 +275,9 @@ typedef struct _DMXScreenInfo {
xcb_get_property_cookie_t getTypeProp;
xcb_get_property_cookie_t getActionListProp;
xcb_get_property_cookie_t getActionDescriptionProp;
+ DMXDnDChild *dndChildren;
+ int dndNChildren;
+ xcb_query_tree_cookie_t queryTree;
/*---------- Other related information ----------*/
diff --git a/hw/dmx/dmxdnd.c b/hw/dmx/dmxdnd.c
index 6927e0435..f7f4d8324 100644
--- a/hw/dmx/dmxdnd.c
+++ b/hw/dmx/dmxdnd.c
@@ -37,8 +37,23 @@
#include "dmxselection.h"
#include "dmxdnd.h"
+#include "selection.h"
+
+#ifdef PANORAMIX
+#include "panoramiX.h"
+#include "panoramiXsrv.h"
+#endif
+
#include <xcb/xinput.h>
+struct _DMXDnDChild {
+ Window target;
+ Window wid;
+ BoxRec box;
+ int map_state;
+ int version;
+};
+
void
dmxBEDnDRootWindowUpdate (ScreenPtr pScreen,
Window window)
@@ -65,6 +80,537 @@ dmxBEDnDRootWindowUpdate (ScreenPtr pScreen,
}
static void
+dmxDnDSendDeclineStatus (void)
+{
+ WindowPtr pWin;
+
+ if (!dmxScreens[0].dndWindow)
+ return;
+
+ if (dixLookupWindow (&pWin,
+ dmxScreens[0].dndWindow,
+ serverClient,
+ DixReadAccess) == Success)
+ {
+ xEvent x;
+
+ x.u.u.type = ClientMessage | 0x80;
+ x.u.u.detail = 32;
+ x.u.clientMessage.window = dmxScreens[0].dndWindow;
+ x.u.clientMessage.u.l.type = dmxScreens[0].xdndStatusAtom;
+ x.u.clientMessage.u.l.longs0 = dmxScreens[0].selectionProxyWid[0];
+ x.u.clientMessage.u.l.longs1 = 0;
+ x.u.clientMessage.u.l.longs2 = 0;
+ x.u.clientMessage.u.l.longs3 = 0;
+ x.u.clientMessage.u.l.longs4 = 0;
+
+ DeliverEventsToWindow (PickPointer (serverClient),
+ pWin,
+ &x,
+ 1,
+ NoEventMask,
+ NullGrab, 0);
+ }
+}
+
+static void
+dmxBEDnDUpdateTarget (ScreenPtr pScreen)
+{
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ Window target = None;
+ Window wid = None;
+ int version = 0;
+
+ if (!dmxScreens[0].dndWindow)
+ return;
+
+ if (dmxScreen->dndStatus)
+ {
+ int n;
+
+ n = dmxScreen->dndNChildren;
+ while (n--)
+ {
+ if (dmxScreen->dndChildren[n].map_state != XCB_MAP_STATE_VIEWABLE)
+ continue;
+
+ if (dmxScreen->dndChildren[n].box.x1 <= dmxScreen->dndX &&
+ dmxScreen->dndChildren[n].box.y1 <= dmxScreen->dndY &&
+ dmxScreen->dndChildren[n].box.x2 > dmxScreen->dndX &&
+ dmxScreen->dndChildren[n].box.y2 > dmxScreen->dndY)
+ break;
+ }
+
+ if (n >= 0 && dmxScreen->dndChildren[n].version >= 3)
+ {
+ target = dmxScreen->dndChildren[n].target;
+ wid = dmxScreen->dndChildren[n].wid;
+ version = dmxScreen->dndChildren[n].version < 5 ?
+ dmxScreen->dndChildren[n].version : 5;
+ }
+ }
+
+ if (target != dmxScreen->dndTarget)
+ {
+ if (dmxScreen->dndTarget)
+ {
+ xcb_client_message_event_t xevent;
+
+ xevent.response_type = XCB_CLIENT_MESSAGE;
+ xevent.format = 32;
+
+ xevent.type = dmxBEAtom (dmxScreen, dmxScreen->xdndLeaveAtom);
+ xevent.window = dmxScreen->dndTarget;
+
+ xevent.data.data32[0] = dmxScreen->dndSource;
+ xevent.data.data32[1] = 0;
+ xevent.data.data32[2] = 0;
+ xevent.data.data32[3] = 0;
+ xevent.data.data32[4] = 0;
+
+ xcb_send_event (dmxScreen->connection,
+ FALSE,
+ dmxScreen->dndWid,
+ 0,
+ (const char *) &xevent);
+ }
+
+ if (target)
+ {
+ xcb_client_message_event_t xevent;
+ int i;
+
+ xevent.response_type = XCB_CLIENT_MESSAGE;
+ xevent.format = 32;
+
+ xevent.type = dmxBEAtom (dmxScreen, dmxScreen->xdndEnterAtom);
+ xevent.window = target;
+
+ xevent.data.data32[0] = dmxScreen->dndSource;
+ xevent.data.data32[1] = version << 24;
+ xevent.data.data32[2] = 0;
+ xevent.data.data32[3] = 0;
+ xevent.data.data32[4] = 0;
+
+ if (dmxScreen->dndHasTypeProp)
+ xevent.data.data32[1] |= 1;
+
+ for (i = 0; i < 3; i++)
+ if (ValidAtom (dmxScreen->dndType[i]))
+ xevent.data.data32[i + 2] =
+ dmxBEAtom (dmxScreen, dmxScreen->dndType[i]);
+
+ xcb_send_event (dmxScreen->connection,
+ FALSE,
+ wid,
+ 0,
+ (const char *) &xevent);
+
+ dmxScreen->dndXPos = -1;
+ dmxScreen->dndYPos = -1;
+ }
+ else if (dmxScreen->dndStatus)
+ {
+ dmxDnDSendDeclineStatus ();
+ }
+
+ dmxScreen->dndTarget = target;
+ dmxScreen->dndWid = wid;
+ }
+
+ if (dmxScreen->dndTarget)
+ {
+ if (dmxScreen->dndX != dmxScreen->dndXPos ||
+ dmxScreen->dndY != dmxScreen->dndYPos)
+ {
+ xcb_client_message_event_t xevent;
+
+ xevent.response_type = XCB_CLIENT_MESSAGE;
+ xevent.format = 32;
+
+ xevent.type = dmxBEAtom (dmxScreen, dmxScreen->xdndPositionAtom);
+ xevent.window = dmxScreen->dndTarget;
+
+ xevent.data.data32[0] = dmxScreen->dndSource;
+ xevent.data.data32[1] = 0;
+ xevent.data.data32[2] = (dmxScreen->dndX << 16) | dmxScreen->dndY;
+ xevent.data.data32[3] = 0; /* XXX: need time stamp */
+ xevent.data.data32[4] = dmxBEAtom (dmxScreen,
+ dmxScreen->dndAction);
+
+ xcb_send_event (dmxScreen->connection,
+ FALSE,
+ dmxScreen->dndWid,
+ 0,
+ (const char *) &xevent);
+
+ dmxScreen->dndXPos = dmxScreen->dndX;
+ dmxScreen->dndYPos = dmxScreen->dndY;
+ }
+ }
+}
+
+static void
+dmxDnDAwarePropertyReply (ScreenPtr pScreen,
+ unsigned int sequence,
+ xcb_generic_reply_t *reply,
+ xcb_generic_error_t *error,
+ void *data)
+{
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ int n = (int) data;
+
+ if (!dmxScreen->dndChildren || n >= dmxScreen->dndNChildren)
+ return;
+
+ if (reply)
+ {
+ xcb_get_property_reply_t *xproperty =
+ (xcb_get_property_reply_t *) reply;
+
+ if (xproperty->format == 32)
+ {
+ uint32_t *data = xcb_get_property_value (xproperty);
+ int length = xcb_get_property_value_length (xproperty);
+
+ if (length)
+ dmxScreen->dndChildren[n].version = *data;
+ }
+ }
+}
+
+static void
+dmxDnDProxyPropertyReply (ScreenPtr pScreen,
+ unsigned int sequence,
+ xcb_generic_reply_t *reply,
+ xcb_generic_error_t *error,
+ void *data)
+{
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ int n = (int) data;
+
+ if (!dmxScreen->dndChildren || n >= dmxScreen->dndNChildren)
+ return;
+
+ if (reply)
+ {
+ xcb_get_property_reply_t *xproperty =
+ (xcb_get_property_reply_t *) reply;
+
+ if (xproperty->format == 32)
+ {
+ uint32_t *data = xcb_get_property_value (xproperty);
+ int length = xcb_get_property_value_length (xproperty);
+
+ if (length)
+ {
+ xcb_get_property_cookie_t prop;
+
+ dmxScreen->dndChildren[n].wid = *data;
+
+ /* ignore previous xdndAware property reply */
+ dmxScreen->dndChildren[n].version = 0;
+
+ prop = xcb_get_property (dmxScreen->connection,
+ xFalse,
+ dmxScreen->dndChildren[n].wid,
+ dmxBEAtom (dmxScreen,
+ dmxScreen->xdndAwareAtom),
+ XCB_GET_PROPERTY_TYPE_ANY,
+ 0,
+ 1);
+ dmxAddRequest (&dmxScreen->request,
+ dmxDnDAwarePropertyReply,
+ prop.sequence,
+ (void *) n);
+ }
+ }
+ }
+}
+
+static void
+dmxDnDGeometryReply (ScreenPtr pScreen,
+ unsigned int sequence,
+ xcb_generic_reply_t *reply,
+ xcb_generic_error_t *error,
+ void *data)
+{
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ int n = (int) data;
+
+ if (!dmxScreen->dndChildren || n >= dmxScreen->dndNChildren)
+ return;
+
+ if (reply)
+ {
+ xcb_get_geometry_reply_t *xgeometry =
+ (xcb_get_geometry_reply_t *) reply;
+
+ dmxScreen->dndChildren[n].box.x1 = xgeometry->x;
+ dmxScreen->dndChildren[n].box.y1 = xgeometry->y;
+ dmxScreen->dndChildren[n].box.x2 = xgeometry->x + xgeometry->width;
+ dmxScreen->dndChildren[n].box.y2 = xgeometry->y + xgeometry->height;
+ }
+}
+
+static void
+dmxDnDWindowAttributesReply (ScreenPtr pScreen,
+ unsigned int sequence,
+ xcb_generic_reply_t *reply,
+ xcb_generic_error_t *error,
+ void *data)
+{
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ int n = (int) data;
+
+ if (!dmxScreen->dndChildren || n >= dmxScreen->dndNChildren)
+ return;
+
+ if (reply)
+ {
+ xcb_get_window_attributes_reply_t *xattrib =
+ (xcb_get_window_attributes_reply_t *) reply;
+
+ dmxScreen->dndChildren[n].map_state = xattrib->map_state;
+
+ if (xattrib->map_state == XCB_MAP_STATE_VIEWABLE)
+ dmxBEDnDUpdateTarget (pScreen);
+ }
+}
+
+/* XXX: back-end server DND target lookup method is efficient but
+ doesn't support reparenting window managers */
+static void
+dmxDnDQueryTreeReply (ScreenPtr pScreen,
+ unsigned int sequence,
+ xcb_generic_reply_t *reply,
+ xcb_generic_error_t *error,
+ void *data)
+{
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+
+ if (sequence != dmxScreen->queryTree.sequence)
+ return;
+
+ assert (!dmxScreen->dndChildren);
+
+ if (reply)
+ {
+ xcb_query_tree_reply_t *xquery = (xcb_query_tree_reply_t *) reply;
+ DMXDnDChild *children;
+ xcb_window_t *c;
+ int n;
+
+ c = xcb_query_tree_children (xquery);
+ n = xcb_query_tree_children_length (xquery);
+
+ children = xalloc (n * sizeof (DMXDnDChild));
+ if (!children)
+ return;
+
+ dmxScreen->dndChildren = children;
+ dmxScreen->dndNChildren = n;
+
+ while (n--)
+ {
+ xcb_get_property_cookie_t prop;
+ xcb_get_geometry_cookie_t geometry;
+ xcb_get_window_attributes_cookie_t attr;
+
+ children[n].box.x1 = 0;
+ children[n].box.y1 = 0;
+ children[n].box.x2 = 0;
+ children[n].box.y2 = 0;
+ children[n].version = 0;
+ children[n].target = c[n];
+ children[n].wid = c[n];
+
+ prop = xcb_get_property (dmxScreen->connection,
+ xFalse,
+ c[n],
+ dmxBEAtom (dmxScreen,
+ dmxScreen->xdndAwareAtom),
+ XCB_GET_PROPERTY_TYPE_ANY,
+ 0,
+ 1);
+ dmxAddRequest (&dmxScreen->request,
+ dmxDnDAwarePropertyReply,
+ prop.sequence,
+ (void *) n);
+
+ prop = xcb_get_property (dmxScreen->connection,
+ xFalse,
+ c[n],
+ dmxBEAtom (dmxScreen,
+ dmxScreen->xdndProxyAtom),
+ XCB_GET_PROPERTY_TYPE_ANY,
+ 0,
+ 1);
+ dmxAddRequest (&dmxScreen->request,
+ dmxDnDProxyPropertyReply,
+ prop.sequence,
+ (void *) n);
+
+ geometry = xcb_get_geometry (dmxScreen->connection, c[n]);
+ dmxAddRequest (&dmxScreen->request,
+ dmxDnDGeometryReply,
+ geometry.sequence,
+ (void *) n);
+
+ attr = xcb_get_window_attributes (dmxScreen->connection, c[n]);
+ dmxAddRequest (&dmxScreen->request,
+ dmxDnDWindowAttributesReply,
+ attr.sequence,
+ (void *) n);
+ }
+ }
+}
+
+static void
+dmxBEDnDUpdatePosition (ScreenPtr pScreen,
+ int x,
+ int y)
+{
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ int i;
+
+ for (i = 0; i < dmxNumScreens; i++)
+ dmxScreens[i].dndStatus = 0;
+
+ dmxScreen->dndX = x;
+ dmxScreen->dndY = y;
+ dmxScreen->dndStatus = 1;
+
+ if (!dmxScreen->dndChildren)
+ {
+ if (!dmxScreen->queryTree.sequence)
+ {
+ Window root = DefaultRootWindow (dmxScreen->beDisplay);
+
+ dmxScreen->queryTree = xcb_query_tree (dmxScreen->connection,
+ root);
+ dmxAddRequest (&dmxScreen->request,
+ dmxDnDQueryTreeReply,
+ dmxScreen->queryTree.sequence,
+ 0);
+ }
+ }
+
+ for (i = 0; i < dmxNumScreens; i++)
+ dmxBEDnDUpdateTarget (screenInfo.screens[i]);
+}
+
+static void
+dmxBEDnDHideProxyWindow (ScreenPtr pScreen)
+{
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ WindowPtr pProxyWin = dmxScreen->pSelectionProxyWin[0];
+
+ if (!pProxyWin->mapped)
+ return;
+
+ dmxScreen->dndStatus = 0;
+ dmxBEDnDUpdateTarget (pScreen);
+
+ UnmapWindow (pProxyWin, FALSE);
+
+ if (dmxScreen->dndChildren)
+ {
+ xfree (dmxScreen->dndChildren);
+
+ dmxScreen->dndChildren = NULL;
+ dmxScreen->dndNChildren = 0;
+ }
+
+ dmxScreen->queryTree.sequence = 0;
+}
+
+void
+dmxBEDnDSpriteUpdate (ScreenPtr pScreen,
+ Window event,
+ int rootX,
+ int rootY)
+{
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ WindowPtr pProxyWin = dmxScreen->pSelectionProxyWin[0];
+
+ if (event != dmxScreen->rootWin)
+ {
+ if (!pProxyWin->mapped)
+ {
+ Selection *pSel;
+ XID vlist[5];
+
+ if (dixLookupSelection (&pSel,
+ dmxScreen->xdndSelectionAtom,
+ serverClient,
+ DixReadAccess) != Success)
+ return;
+
+ if (!pSel->window)
+ return;
+
+ vlist[0] = 0;
+ vlist[1] = 0;
+ vlist[2] = WindowTable[pScreen->myNum]->drawable.width;
+ vlist[3] = WindowTable[pScreen->myNum]->drawable.height;
+ vlist[4] = Above;
+
+#ifdef PANORAMIX
+ if (!noPanoramiXExtension)
+ {
+ int j;
+
+ FOR_NSCREENS_BACKWARD(j) {
+ ConfigureWindow (dmxScreens[j].pSelectionProxyWin[0],
+ CWX | CWY | CWWidth | CWHeight |
+ CWStackMode,
+ vlist,
+ serverClient);
+ MapWindow (dmxScreens[j].pSelectionProxyWin[0],
+ serverClient);
+
+ dmxScreens[j].dndSource = None;
+ dmxScreens[j].dndTarget = None;
+ }
+ }
+ else
+#endif
+
+ {
+ ConfigureWindow (pProxyWin,
+ CWX | CWY | CWWidth | CWHeight | CWStackMode,
+ vlist,
+ serverClient);
+ MapWindow (pProxyWin, serverClient);
+
+ dmxScreen->dndSource = None;
+ dmxScreen->dndTarget = None;
+ }
+ }
+
+ dmxBEDnDUpdatePosition (pScreen, rootX, rootY);
+ }
+ else
+ {
+
+#ifdef PANORAMIX
+ if (!noPanoramiXExtension)
+ {
+ int j;
+
+ FOR_NSCREENS_BACKWARD(j) {
+ dmxBEDnDHideProxyWindow (screenInfo.screens[j]);
+ }
+ }
+ else
+#endif
+
+ dmxBEDnDHideProxyWindow (pScreen);
+ }
+}
+
+static void
dmxDnDUpdatePosition (DMXScreenInfo *dmxScreen,
WindowPtr pWin,
int x,
@@ -301,8 +847,7 @@ dmxDnDTranslateCoordinatesReply (ScreenPtr pScreen,
xevent.data.data32[3] = 0;
xevent.data.data32[4] = 0;
- if (dmxScreen->dndAcceptedAction &&
- ValidAtom (dmxScreen->dndAcceptedAction))
+ if (ValidAtom (dmxScreen->dndAcceptedAction))
xevent.data.data32[4] =
dmxBEAtom (dmxScreen, dmxScreen->dndAcceptedAction);
@@ -627,6 +1172,103 @@ dmxDnDDropMessage (ScreenPtr pScreen,
}
}
+static void
+dmxDnDStatusMessage (ScreenPtr pScreen,
+ Window target,
+ int status,
+ Atom action)
+{
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ WindowPtr pWin;
+
+ if (!dmxScreens[0].dndWindow)
+ return;
+
+ if (!dmxScreen->dndStatus)
+ return;
+
+ if (target != dmxScreen->dndTarget)
+ return;
+
+ if (dixLookupWindow (&pWin,
+ dmxScreens[0].dndWindow,
+ serverClient,
+ DixReadAccess) == Success)
+ {
+ xEvent x;
+
+ x.u.u.type = ClientMessage | 0x80;
+ x.u.u.detail = 32;
+ x.u.clientMessage.window = dmxScreens[0].dndWindow;
+ x.u.clientMessage.u.l.type = dmxScreens[0].xdndStatusAtom;
+ x.u.clientMessage.u.l.longs0 = dmxScreens[0].selectionProxyWid[0];
+ x.u.clientMessage.u.l.longs1 = 0;
+ x.u.clientMessage.u.l.longs2 = 0;
+ x.u.clientMessage.u.l.longs3 = 0;
+ x.u.clientMessage.u.l.longs4 = 0;
+
+ if (status)
+ {
+ x.u.clientMessage.u.l.longs1 = 1;
+ x.u.clientMessage.u.l.longs4 = dmxAtom (dmxScreen, action);
+ }
+
+ DeliverEventsToWindow (PickPointer (serverClient),
+ pWin,
+ &x,
+ 1,
+ NoEventMask,
+ NullGrab, 0);
+ }
+}
+
+static void
+dmxDnDFinishedMessage (ScreenPtr pScreen,
+ Window target,
+ int status,
+ Atom action)
+{
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ WindowPtr pWin;
+
+ if (!dmxScreens[0].dndWindow)
+ return;
+
+ if (target != dmxScreen->dndTarget)
+ return;
+
+ if (dixLookupWindow (&pWin,
+ dmxScreens[0].dndWindow,
+ serverClient,
+ DixReadAccess) == Success)
+ {
+ xEvent x;
+
+ x.u.u.type = ClientMessage | 0x80;
+ x.u.u.detail = 32;
+ x.u.clientMessage.window = dmxScreens[0].dndWindow;
+ x.u.clientMessage.u.l.type = dmxScreens[0].xdndFinishedAtom;
+ x.u.clientMessage.u.l.longs0 = dmxScreens[0].selectionProxyWid[0];
+ x.u.clientMessage.u.l.longs1 = 0;
+ x.u.clientMessage.u.l.longs2 = 0;
+ x.u.clientMessage.u.l.longs3 = 0;
+ x.u.clientMessage.u.l.longs4 = 0;
+
+ if (status)
+ {
+ x.u.clientMessage.u.l.longs1 = 1;
+ x.u.clientMessage.u.l.longs2 = dmxAtom (dmxScreen, action);
+ }
+
+ DeliverEventsToWindow (PickPointer (serverClient),
+ pWin,
+ &x,
+ 1,
+ NoEventMask,
+ NullGrab, 0);
+ }
+}
+
Bool
dmxScreenEventCheckDnD (ScreenPtr pScreen,
xcb_generic_event_t *event)
@@ -669,6 +1311,20 @@ dmxScreenEventCheckDnD (ScreenPtr pScreen,
xclient->data.data32[0],
xclient->data.data32[2]);
}
+ else if (dmxAtom (dmxScreen, type) == dmxScreen->xdndStatusAtom)
+ {
+ dmxDnDStatusMessage (pScreen,
+ xclient->data.data32[0],
+ ((xclient->data.data32[1] & 1) != 0),
+ xclient->data.data32[4]);
+ }
+ else if (dmxAtom (dmxScreen, type) == dmxScreen->xdndFinishedAtom)
+ {
+ dmxDnDFinishedMessage (pScreen,
+ xclient->data.data32[0],
+ ((xclient->data.data32[1] & 1) != 0),
+ xclient->data.data32[2]);
+ }
else
{
return FALSE;
@@ -684,128 +1340,259 @@ dmxScreenEventCheckDnD (ScreenPtr pScreen,
void
dmxDnDClientMessageEvent (xEvent *event)
{
- int i;
+ Atom type = event->u.clientMessage.u.l.type;
+ int i;
for (i = 0; i < dmxNumScreens; i++)
{
DMXScreenInfo *dmxScreen = &dmxScreens[i];
- if (event->u.clientMessage.u.l.longs0 == dmxScreen->dndTarget)
+ if (type == dmxScreens[0].xdndStatusAtom)
{
- Atom type = event->u.clientMessage.u.l.type;
+ int dndStatus = event->u.clientMessage.u.l.longs1 & 1;
+ Atom dndAcceptedAction = event->u.clientMessage.u.l.longs4;
if (!dmxScreen->dndSource)
continue;
- if (type == dmxScreen->xdndStatusAtom)
- {
- int dndStatus = event->u.clientMessage.u.l.longs1 & 1;
- Atom dndAcceptedAction = event->u.clientMessage.u.l.longs4;
+ if (event->u.clientMessage.u.l.longs0 != dmxScreen->dndTarget)
+ continue;
- if (dmxScreen->dndStatus != dndStatus ||
- dmxScreen->dndAcceptedAction != dndAcceptedAction)
- {
- xcb_client_message_event_t xevent;
+ if (dmxScreen->dndStatus != dndStatus ||
+ dmxScreen->dndAcceptedAction != dndAcceptedAction)
+ {
+ xcb_client_message_event_t xevent;
- dmxScreen->dndStatus = dndStatus;
- dmxScreen->dndAcceptedAction = dndAcceptedAction;
+ dmxScreen->dndStatus = dndStatus;
+ dmxScreen->dndAcceptedAction = dndAcceptedAction;
- xevent.response_type = XCB_CLIENT_MESSAGE;
- xevent.format = 32;
+ xevent.response_type = XCB_CLIENT_MESSAGE;
+ xevent.format = 32;
- xevent.type = dmxBEAtom (dmxScreen,
- dmxScreen->xdndStatusAtom);
- xevent.window = dmxScreen->dndSource;
+ xevent.type = dmxBEAtom (dmxScreen,
+ dmxScreen->xdndStatusAtom);
+ xevent.window = dmxScreen->dndSource;
- xevent.data.data32[0] = dmxScreen->dndWid;
- xevent.data.data32[1] = dmxScreen->dndStatus;
- xevent.data.data32[2] = 0;
- xevent.data.data32[3] = 0;
- xevent.data.data32[4] = 0;
+ xevent.data.data32[0] = dmxScreen->dndWid;
+ xevent.data.data32[1] = dmxScreen->dndStatus;
+ xevent.data.data32[2] = 0;
+ xevent.data.data32[3] = 0;
+ xevent.data.data32[4] = 0;
- if (dmxScreen->dndAcceptedAction &&
- ValidAtom (dmxScreen->dndAcceptedAction))
- xevent.data.data32[4] =
- dmxBEAtom (dmxScreen,
- dmxScreen->dndAcceptedAction);
+ if (ValidAtom (dmxScreen->dndAcceptedAction))
+ xevent.data.data32[4] =
+ dmxBEAtom (dmxScreen,
+ dmxScreen->dndAcceptedAction);
- xcb_send_event (dmxScreen->connection,
- FALSE,
- dmxScreen->dndSource,
- 0,
- (const char *) &xevent);
- }
+ xcb_send_event (dmxScreen->connection,
+ FALSE,
+ dmxScreen->dndSource,
+ 0,
+ (const char *) &xevent);
+ }
- REGION_EMPTY (pScreen, &dmxScreen->dndBox);
+ REGION_EMPTY (pScreen, &dmxScreen->dndBox);
- if (dmxScreen->dndStatus & 2)
- {
- BoxRec box;
+ if (dmxScreen->dndStatus & 2)
+ {
+ BoxRec box;
- box.x1 = event->u.clientMessage.u.l.longs2 >> 16;
- box.y1 = event->u.clientMessage.u.l.longs2 & 0xffff;
- box.x2 = box.x1 +
- (event->u.clientMessage.u.l.longs3 >> 16);
- box.y2 = box.y1 +
- (event->u.clientMessage.u.l.longs3 & 0xffff);
+ box.x1 = event->u.clientMessage.u.l.longs2 >> 16;
+ box.y1 = event->u.clientMessage.u.l.longs2 & 0xffff;
+ box.x2 = box.x1 +
+ (event->u.clientMessage.u.l.longs3 >> 16);
+ box.y2 = box.y1 +
+ (event->u.clientMessage.u.l.longs3 & 0xffff);
- REGION_RESET (pScreen, &dmxScreen->dndBox, &box);
- }
+ REGION_RESET (pScreen, &dmxScreen->dndBox, &box);
+ }
- if (dmxScreen->dndX != dmxScreen->dndXPos ||
- dmxScreen->dndY != dmxScreen->dndYPos)
- {
- WindowPtr pWin = WindowTable[i];
+ if (dmxScreen->dndX != dmxScreen->dndXPos ||
+ dmxScreen->dndY != dmxScreen->dndYPos)
+ {
+ WindowPtr pWin = WindowTable[i];
#ifdef PANORAMIX
- if (!noPanoramiXExtension)
- pWin = WindowTable[0];
+ if (!noPanoramiXExtension)
+ pWin = WindowTable[0];
#endif
- dmxDnDUpdatePosition (dmxScreen,
- pWin,
- dmxScreen->dndX,
- dmxScreen->dndY);
- }
+ dmxDnDUpdatePosition (dmxScreen,
+ pWin,
+ dmxScreen->dndX,
+ dmxScreen->dndY);
}
- else if (type == dmxScreen->xdndFinishedAtom)
+ }
+ else if (type == dmxScreen->xdndFinishedAtom)
+ {
+ xcb_client_message_event_t xevent;
+
+ if (!dmxScreen->dndSource)
+ continue;
+
+ if (event->u.clientMessage.u.l.longs0 != dmxScreen->dndTarget)
+ continue;
+
+ xevent.response_type = XCB_CLIENT_MESSAGE;
+ xevent.format = 32;
+
+ xevent.type = dmxBEAtom (dmxScreen, dmxScreen->xdndFinishedAtom);
+ xevent.window = dmxScreen->dndSource;
+
+ xevent.data.data32[0] = dmxScreen->dndWid;
+ xevent.data.data32[1] = 0;
+ xevent.data.data32[2] = 0;
+ xevent.data.data32[3] = 0;
+ xevent.data.data32[4] = 0;
+
+ if (dmxScreen->dndVersion >= 5)
{
- xcb_client_message_event_t xevent;
+ xevent.data.data32[1] = event->u.clientMessage.u.l.longs1 & 1;
+ xevent.data.data32[2] = event->u.clientMessage.u.l.longs2;
+ }
- xevent.response_type = XCB_CLIENT_MESSAGE;
- xevent.format = 32;
+ xcb_send_event (dmxScreen->connection,
+ FALSE,
+ dmxScreen->dndSource,
+ 0,
+ (const char *) &xevent);
- xevent.type = dmxBEAtom (dmxScreen,
- dmxScreen->xdndFinishedAtom);
- xevent.window = dmxScreen->dndSource;
+ dmxScreen->dndTarget = None;
+ dmxScreen->dndWindow = None;
+
+ dmxDnDLeaveMessage (screenInfo.screens[i], dmxScreen->dndSource);
- xevent.data.data32[0] = dmxScreen->dndWid;
- xevent.data.data32[1] = 0;
- xevent.data.data32[2] = 0;
- xevent.data.data32[3] = 0;
- xevent.data.data32[4] = 0;
+ dmxScreen->dndWid = None;
+ dmxScreen->dndSource = None;
+ }
+ else if (type == dmxScreen->xdndEnterAtom)
+ {
+ dmxScreen->dndSource = None;
+ dmxScreen->dndAction = None;
+ dmxScreen->dndType[0] = event->u.clientMessage.u.l.longs2;
+ dmxScreen->dndType[1] = event->u.clientMessage.u.l.longs3;
+ dmxScreen->dndType[2] = event->u.clientMessage.u.l.longs4;
+ dmxScreen->dndHasTypeProp =
+ ((event->u.clientMessage.u.l.longs1 & 1) != 0);
+ }
+ else if (type == dmxScreen->xdndLeaveAtom)
+ {
+ dmxBEDnDHideProxyWindow (screenInfo.screens[i]);
+ }
+ else if (type == dmxScreen->xdndPositionAtom)
+ {
+ WindowPtr pWin = NullWindow;
+ Window dndSource = dmxScreen->dndSource;
+
+#ifdef PANORAMIX
+ PanoramiXRes *win = NULL;
+
+ if (!noPanoramiXExtension)
+ {
+ win = (PanoramiXRes *)
+ SecurityLookupIDByType (serverClient,
+ event->u.clientMessage.u.l.longs0,
+ XRT_WINDOW,
+ DixReadAccess);
+ if (win)
+ dixLookupWindow (&pWin, win->info[i].id,
+ serverClient, DixReadAccess);
+ }
+ else
+#endif
+ dixLookupWindow (&pWin, event->u.clientMessage.u.l.longs0,
+ serverClient, DixReadAccess);
- if (dmxScreen->dndVersion >= 5)
+ if (pWin)
+ dmxScreen->dndSource = DMX_GET_WINDOW_PRIV (pWin)->window;
+
+ dmxScreen->dndWindow = event->u.clientMessage.u.l.longs0;
+
+ if (dmxScreen->dndAction != event->u.clientMessage.u.l.longs4)
+ {
+ dmxScreen->dndAction = event->u.clientMessage.u.l.longs4;
+ dmxScreen->dndXPos = -1;
+ dmxScreen->dndXPos = -1;
+ }
+
+ if (dmxScreen->dndStatus)
+ {
+ dmxBEDnDUpdatePosition (screenInfo.screens[i],
+ dmxScreen->dndX,
+ dmxScreen->dndY);
+
+ if (dmxScreen->dndSource != dndSource)
+ dmxDnDSendDeclineStatus ();
+ }
+ }
+ else if (type == dmxScreen->xdndDropAtom)
+ {
+ Window target = None;
+ int status = 0;
+
+ if (dmxScreen->dndStatus)
+ {
+ if (dmxScreen->dndTarget)
{
- xevent.data.data32[1] =
- event->u.clientMessage.u.l.longs1 & 1;
- xevent.data.data32[2] = event->u.clientMessage.u.l.longs2;
- }
+ xcb_client_message_event_t xevent;
- xcb_send_event (dmxScreen->connection,
- FALSE,
- dmxScreen->dndSource,
- 0,
- (const char *) &xevent);
+ xevent.response_type = XCB_CLIENT_MESSAGE;
+ xevent.format = 32;
- dmxScreen->dndTarget = None;
- dmxScreen->dndWindow = None;
-
- dmxDnDLeaveMessage (screenInfo.screens[i],
- dmxScreen->dndSource);
+ xevent.type = dmxBEAtom (dmxScreen,
+ dmxScreen->xdndDropAtom);
+ xevent.window = dmxScreen->dndTarget;
- dmxScreen->dndWid = None;
- dmxScreen->dndSource = None;
+ xevent.data.data32[0] = dmxScreen->dndSource;
+ xevent.data.data32[1] = 0;
+ xevent.data.data32[2] = 0; /* XXX: need time stamp */
+ xevent.data.data32[3] = 0;
+ xevent.data.data32[4] = 0;
+
+ xcb_send_event (dmxScreen->connection,
+ FALSE,
+ dmxScreen->dndWid,
+ 0,
+ (const char *) &xevent);
+
+ status = 1;
+ target = dmxScreen->dndTarget;
+
+ dmxScreen->dndTarget = None;
+ }
+ else
+ {
+ WindowPtr pWin;
+ xEvent x;
+
+ x.u.u.type = ClientMessage | 0x80;
+ x.u.u.detail = 32;
+ x.u.clientMessage.window = dmxScreens[0].dndWindow;
+ x.u.clientMessage.u.l.type =
+ dmxScreens[0].xdndFinishedAtom;
+ x.u.clientMessage.u.l.longs0 =
+ dmxScreens[0].selectionProxyWid[0];
+ x.u.clientMessage.u.l.longs1 = 0;
+ x.u.clientMessage.u.l.longs2 = 0;
+ x.u.clientMessage.u.l.longs3 = 0;
+ x.u.clientMessage.u.l.longs4 = 0;
+
+ if (dixLookupWindow (&pWin,
+ dmxScreens[0].dndWindow,
+ serverClient,
+ DixReadAccess) == Success)
+ DeliverEventsToWindow (PickPointer (serverClient),
+ pWin,
+ &x,
+ 1,
+ NoEventMask,
+ NullGrab, 0);
+ }
}
+
+ dmxBEDnDHideProxyWindow (screenInfo.screens[i]);
+
+ dmxScreen->dndTarget = target;
+ dmxScreen->dndStatus = status;
}
}
}
diff --git a/hw/dmx/dmxdnd.h b/hw/dmx/dmxdnd.h
index 1bc44cc42..6c6d975eb 100644
--- a/hw/dmx/dmxdnd.h
+++ b/hw/dmx/dmxdnd.h
@@ -32,6 +32,12 @@ void
dmxBEDnDRootWindowUpdate (ScreenPtr pScreen,
Window window);
+void
+dmxBEDnDSpriteUpdate (ScreenPtr pScreen,
+ Window window,
+ int rootX,
+ int rootY);
+
Bool
dmxScreenEventCheckDnD (ScreenPtr pScreen,
xcb_generic_event_t *event);
diff --git a/hw/dmx/dmxinput.c b/hw/dmx/dmxinput.c
index 6066f1cb0..ae8e0e977 100644
--- a/hw/dmx/dmxinput.c
+++ b/hw/dmx/dmxinput.c
@@ -31,6 +31,7 @@
#include "dmxlog.h"
#include "dmxinput.h"
#include "dmxgrab.h"
+#include "dmxdnd.h"
#include "dmxwindow.h"
#include "dmxcursor.h"
#include "dmxscrinit.h"
@@ -577,7 +578,8 @@ dmxDeviceGrabPointer (DeviceIntPtr pDevice,
.device_mode = XCB_GRAB_MODE_ASYNC,
.owner_events = TRUE,
.confine_to = confineTo,
- .cursor = cursor
+ .cursor = cursor,
+ .event_count = 3
};
xcb_protocol_request_t request = {
2,
@@ -685,10 +687,13 @@ static void
dmxUpdateSpriteFromEvent (DeviceIntPtr pDevice,
xcb_window_t event,
int x,
- int y)
+ int y,
+ int rootX,
+ int rootY)
{
dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDevice);
DMXScreenInfo *dmxScreen = (DMXScreenInfo *) pDevPriv->dmxInput;
+ ScreenPtr pScreen = screenInfo.screens[dmxScreen->index];
if (event != dmxScreen->rootWin)
{
@@ -736,6 +741,7 @@ dmxUpdateSpriteFromEvent (DeviceIntPtr pDevice,
}
dmxEndFakeMotion (&dmxScreen->input);
+ dmxBEDnDSpriteUpdate (pScreen, event, rootX, rootY);
dmxUpdateSpritePosition (pDevice, x, y);
}
@@ -757,7 +763,9 @@ dmxDevicePointerEventCheck (DeviceIntPtr pDevice,
dmxUpdateSpriteFromEvent (pButtonDev,
xmotion->event,
xmotion->event_x,
- xmotion->event_y);
+ xmotion->event_y,
+ xmotion->root_x,
+ xmotion->root_y);
} break;
case XCB_BUTTON_PRESS:
case XCB_BUTTON_RELEASE: {
@@ -767,7 +775,9 @@ dmxDevicePointerEventCheck (DeviceIntPtr pDevice,
dmxUpdateSpriteFromEvent (pButtonDev,
xbutton->event,
xbutton->event_x,
- xbutton->event_y);
+ xbutton->event_y,
+ xbutton->root_x,
+ xbutton->root_y);
dmxChangeButtonState (pButtonDev,
xbutton->detail,
type);
@@ -798,7 +808,9 @@ dmxDevicePointerEventCheck (DeviceIntPtr pDevice,
dmxUpdateSpriteFromEvent (pButtonDev,
xmotion->event,
xmotion->event_x,
- xmotion->event_y);
+ xmotion->event_y,
+ xmotion->root_x,
+ xmotion->root_y);
} break;
case XCB_INPUT_DEVICE_BUTTON_PRESS:
case XCB_INPUT_DEVICE_BUTTON_RELEASE: {
@@ -811,7 +823,9 @@ dmxDevicePointerEventCheck (DeviceIntPtr pDevice,
dmxUpdateSpriteFromEvent (pButtonDev,
xbutton->event,
xbutton->event_x,
- xbutton->event_y);
+ xbutton->event_y,
+ xbutton->root_x,
+ xbutton->root_y);
dmxChangeButtonState (pButtonDev,
xbutton->detail, XCB_BUTTON_RELEASE +
(reltype -
@@ -879,7 +893,9 @@ dmxDeviceKeyboardEventCheck (DeviceIntPtr pDevice,
dmxUpdateSpriteFromEvent (pButtonDev,
xkey->event,
xkey->event_x,
- xkey->event_y);
+ xkey->event_y,
+ xkey->root_x,
+ xkey->root_y);
dmxChangeKeyState (pKeyDev,
xkey->detail,
@@ -933,7 +949,9 @@ dmxDeviceKeyboardEventCheck (DeviceIntPtr pDevice,
dmxUpdateSpriteFromEvent (pButtonDev,
xkey->event,
xkey->event_x,
- xkey->event_y);
+ xkey->event_y,
+ xkey->root_x,
+ xkey->root_y);
dmxChangeKeyState (pKeyDev,
xkey->detail, XCB_KEY_PRESS +
diff --git a/hw/dmx/dmxselection.c b/hw/dmx/dmxselection.c
index 223f67f7d..882934f2d 100644
--- a/hw/dmx/dmxselection.c
+++ b/hw/dmx/dmxselection.c
@@ -463,7 +463,7 @@ dmxSelectionPropertyReply (ScreenPtr pScreen,
event.u.selectionNotify.property = None;
- if (reply->response_type)
+ if (reply)
{
Atom type = dmxAtom (dmxScreen, xproperty->type);
uint32_t *data = xcb_get_property_value (xproperty);
@@ -894,6 +894,7 @@ dmxCreateSelectionProxies (void)
XID overrideRedirect = TRUE;
int result;
int i;
+ Atom xdndVersion = 5;
for (i = 0; i < DMX_N_SELECTION_PROXY; i++)
{
@@ -965,6 +966,15 @@ dmxCreateSelectionProxies (void)
}
}
+ ChangeWindowProperty (dmxScreens[0].pSelectionProxyWin[0],
+ dmxScreens[0].xdndAwareAtom,
+ XA_ATOM,
+ 32,
+ PropModeReplace,
+ 1,
+ &xdndVersion,
+ TRUE);
+
return TRUE;
}