diff options
author | David Reveman <davidr@novell.com> | 2008-10-17 15:02:45 -0400 |
---|---|---|
committer | David Reveman <davidr@novell.com> | 2008-10-30 03:37:51 -0400 |
commit | 6a7948491b282e5345d26eb9fffaee48e426f338 (patch) | |
tree | a0f995370c3a2e0731b7f0bd6ae089b4285ea418 | |
parent | 1df5903f9a4889ef5059438ce3050eacf5f1d90a (diff) |
Initial back-end server DND target support.
-rw-r--r-- | hw/dmx/dmx.h | 5 | ||||
-rw-r--r-- | hw/dmx/dmxdnd.c | 963 | ||||
-rw-r--r-- | hw/dmx/dmxdnd.h | 6 | ||||
-rw-r--r-- | hw/dmx/dmxinput.c | 34 | ||||
-rw-r--r-- | hw/dmx/dmxselection.c | 12 |
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; } |