summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Reveman <davidr@novell.com>2008-10-18 18:17:40 -0400
committerDavid Reveman <davidr@novell.com>2008-10-30 03:37:52 -0400
commit4c6c7db6732f6b4ae0474fcacb66420b273ad5f3 (patch)
tree398eab01517134a43728e35fb9dcec6dc7665e41
parent9d27235e932361a76f91558f70252056d06c8526 (diff)
Proper support for selection conversion with MULTIPLE target.
-rw-r--r--hw/dmx/dmx.h4
-rw-r--r--hw/dmx/dmxinit.c13
-rw-r--r--hw/dmx/dmxscrinit.c2
-rw-r--r--hw/dmx/dmxselection.c275
4 files changed, 204 insertions, 90 deletions
diff --git a/hw/dmx/dmx.h b/hw/dmx/dmx.h
index bdb6205da..35bb5f3e8 100644
--- a/hw/dmx/dmx.h
+++ b/hw/dmx/dmx.h
@@ -204,7 +204,7 @@ typedef struct _DMXScreenInfo {
int beShmEventBase;
#endif
- Display *beAttachedDisplay; /**< Disabld X server's display */
+ Display *beAttachedDisplay; /**< Disabled X server's display */
char *authType;
int authTypeLen;
@@ -239,6 +239,8 @@ typedef struct _DMXScreenInfo {
Window getSelectionOwnerResult;
XID selectionProxyWid[DMX_N_SELECTION_PROXY];
WindowPtr pSelectionProxyWin[DMX_N_SELECTION_PROXY];
+ Atom multipleAtom;
+ Atom atomPairAtom;
Atom incrAtom;
/*---------- DnD information ----------*/
diff --git a/hw/dmx/dmxinit.c b/hw/dmx/dmxinit.c
index 6cfbe0cc7..9227bf36a 100644
--- a/hw/dmx/dmxinit.c
+++ b/hw/dmx/dmxinit.c
@@ -1113,11 +1113,14 @@ void OsVendorInit(void)
{
if (!dmxPropTrans)
{
- dmxPropTrans = xalloc (sizeof (DMXPropTrans));
- dmxPropTrans->name = "_COMPIZ_WINDOW_DECOR";
- dmxPropTrans->format = "xP";
- dmxPropTrans->type = 0;
- dmxPropTransNum = 1;
+ dmxPropTrans = xalloc (sizeof (DMXPropTrans) * 2);
+ dmxPropTrans[0].name = "ATOM_PAIR";
+ dmxPropTrans[0].format = "aa..";
+ dmxPropTrans[0].type = 0;
+ dmxPropTrans[1].name = "_COMPIZ_WINDOW_DECOR";
+ dmxPropTrans[1].format = "xP";
+ dmxPropTrans[1].type = 0;
+ dmxPropTransNum = 2;
}
if (!dmxSelectionMap)
diff --git a/hw/dmx/dmxscrinit.c b/hw/dmx/dmxscrinit.c
index c7a3a1951..2b3523825 100644
--- a/hw/dmx/dmxscrinit.c
+++ b/hw/dmx/dmxscrinit.c
@@ -1036,6 +1036,8 @@ Bool dmxScreenInit(int idx, ScreenPtr pScreen, int argc, char *argv[])
dmxScreen->rootEventMask = ExposureMask | StructureNotifyMask |
SubstructureRedirectMask;
+ dmxScreen->multipleAtom = MakeAtom ("MULTIPLE", strlen ("MULTIPLE"), TRUE);
+ dmxScreen->atomPairAtom = MakeAtom ("ATOM_PAIR", strlen ("ATOM_PAIR"), TRUE);
dmxScreen->incrAtom = MakeAtom ("INCR", strlen ("INCR"), TRUE);
if (!dmxInitGC(pScreen)) return FALSE;
diff --git a/hw/dmx/dmxselection.c b/hw/dmx/dmxselection.c
index 882934f2d..fd3a5ecb5 100644
--- a/hw/dmx/dmxselection.c
+++ b/hw/dmx/dmxselection.c
@@ -493,6 +493,9 @@ dmxSelectionPropertyReply (ScreenPtr pScreen,
*/
type = 0;
default:
+ if (type == dmxScreen->atomPairAtom)
+ for (i = 0; i < length; i++)
+ data[i] = dmxAtom (dmxScreen, data[i]);
break;
}
}
@@ -710,21 +713,16 @@ dmxSelectionPropertyNotify (ScreenPtr pScreen,
return TRUE;
}
-void
-dmxSelectionRequest (ScreenPtr pScreen,
- Window owner,
- Window requestor,
- Atom xSelection,
- Atom xTarget,
- Atom xProperty,
- Time xTime)
+static Bool
+dmxConvertSelection (ScreenPtr pScreen,
+ DMXSelection *s,
+ Window owner,
+ int multipleLength,
+ uint32_t *multipleData)
{
- DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
- WindowPtr pChild0, pChildN;
- xcb_selection_notify_event_t xevent;
- Selection *pSel = NULL;
- Atom selection = dmxSelectionAtom (dmxScreen,
- xSelection);
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ WindowPtr pChild0, pChildN;
+ Selection *pSel = NULL;
pChild0 = WindowTable[0];
pChildN = WindowTable[pScreen->myNum];
@@ -735,11 +733,10 @@ dmxSelectionRequest (ScreenPtr pScreen,
if (pWinPriv->window == owner)
{
- if (ValidAtom (selection))
- dixLookupSelection (&pSel,
- selection,
- serverClient,
- DixReadAccess);
+ dixLookupSelection (&pSel,
+ s->selection,
+ serverClient,
+ DixReadAccess);
break;
}
@@ -765,87 +762,197 @@ dmxSelectionRequest (ScreenPtr pScreen,
if (pSel)
{
+ WindowPtr pProxy = NullWindow;
+ int i;
+
+ for (i = 1; i < DMX_N_SELECTION_PROXY; i++)
+ {
+ DMXSelection *r;
+
+ pProxy = dmxScreens[0].pSelectionProxyWin[i];
+
+ for (r = reqHead; pProxy && r; r = r->next)
+ if (r->wid == pProxy->drawable.id)
+ pProxy = NullWindow;
+
+ if (pProxy)
+ break;
+ }
+
+ if (pProxy)
+ {
+ xEvent event;
+
+ event.u.u.type = SelectionRequest;
+ event.u.selectionRequest.owner = pSel->window;
+ event.u.selectionRequest.time = currentTime.milliseconds;
+ event.u.selectionRequest.requestor = pProxy->drawable.id;
+ event.u.selectionRequest.selection = s->selection;
+ event.u.selectionRequest.target = s->target;
+ event.u.selectionRequest.property = s->property;
+
+ if (TryClientEvents (pSel->client, NULL, &event, 1,
+ NoEventMask,
+ NoEventMask /* CantBeFiltered */,
+ NullGrab))
+ {
+ int j;
+
+ s->wid = pProxy->drawable.id;
+
+ for (j = 0; j < dmxNumScreens; j++)
+ {
+ WindowPtr pWin = dmxScreens[j].pSelectionProxyWin[i];
+ dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV (pWin);
+
+ s->value[j].in = pWinPriv->window;
+ }
+
+ if (multipleLength)
+ ChangeWindowProperty (pProxy,
+ s->property,
+ dmxScreen->atomPairAtom,
+ 32,
+ PropModeReplace,
+ multipleLength,
+ multipleData,
+ TRUE);
+
+ dmxAppendSelection (&reqHead, s);
+ return TRUE;
+ }
+ }
+ else
+ {
+ /* TODO: wait for proxy window to become available */
+ dmxLog (dmxWarning,
+ "dmxSelectionRequest: no proxy window available "
+ "for conversion of %s selection\n",
+ NameForAtom (s->selection));
+ }
+ }
+
+ return FALSE;
+}
+
+static void
+dmxMultipleTargetPropertyReply (ScreenPtr pScreen,
+ unsigned int sequence,
+ xcb_generic_reply_t *reply,
+ xcb_generic_error_t *error,
+ void *data)
+{
+ xcb_selection_notify_event_t xevent;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ DMXSelection *s = (DMXSelection *) data;
+
+ 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);
+ int i;
+
+ for (i = 0; i < length; i++)
+ data[i] = dmxAtom (dmxScreen, data[i]);
+
+ if (dmxConvertSelection (pScreen, s, s->wid, length, data))
+ return;
+ }
+ }
+
+ xevent.response_type = XCB_SELECTION_NOTIFY;
+ xevent.pad0 = 0;
+ xevent.sequence = 0;
+ xevent.time = s->time;
+ xevent.requestor = s->requestor;
+ xevent.selection = dmxBESelectionAtom (dmxScreen, s->selection);
+ xevent.target = dmxBEAtom (dmxScreen, s->target);
+ xevent.property = 0;
+
+ xcb_send_event (dmxScreen->connection,
+ FALSE,
+ s->requestor,
+ 0,
+ (const char *) &xevent);
+
+ dmxSync (dmxScreen, FALSE);
+
+ free (s);
+}
+
+void
+dmxSelectionRequest (ScreenPtr pScreen,
+ Window owner,
+ Window requestor,
+ Atom xSelection,
+ Atom xTarget,
+ Atom xProperty,
+ Time xTime)
+{
+ xcb_selection_notify_event_t xevent;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ Atom selection =
+ dmxSelectionAtom (dmxScreen, xSelection);
+
+ if (ValidAtom (selection))
+ {
Atom target = dmxAtom (dmxScreen, xTarget);
Atom property = (xProperty) ? dmxAtom (dmxScreen, xProperty) : None;
if (ValidAtom (target) && ((property == None) || ValidAtom (property)))
{
- WindowPtr pProxy = NullWindow;
DMXSelection *s;
- int i;
- for (i = 1; i < DMX_N_SELECTION_PROXY; i++)
+ s = xalloc (sizeof (DMXSelection));
+ if (s)
{
- pProxy = dmxScreens[0].pSelectionProxyWin[i];
+ s->wid = 0;
+ s->requestor = requestor;
+ s->selection = selection;
+ s->target = target;
+ s->property = property;
+ s->time = xTime;
+ s->next = 0;
+ s->timer = 0;
- for (s = reqHead; pProxy && s; s = s->next)
- if (s->wid == pProxy->drawable.id)
- pProxy = NullWindow;
+ memset (s->value, 0, sizeof (s->value));
- if (pProxy)
- break;
- }
+ s->value[pScreen->myNum].out = requestor;
- if (pProxy)
- {
- xEvent event;
-
- event.u.u.type = SelectionRequest;
- event.u.selectionRequest.owner = pSel->window;
- event.u.selectionRequest.time = currentTime.milliseconds;
- event.u.selectionRequest.requestor = pProxy->drawable.id;
- event.u.selectionRequest.selection = selection;
- event.u.selectionRequest.target = target;
- event.u.selectionRequest.property = property;
-
- s = xalloc (sizeof (DMXSelection));
- if (s)
+ if (target == dmxScreen->multipleAtom)
{
- if (TryClientEvents (pSel->client, NULL, &event, 1,
- NoEventMask,
- NoEventMask /* CantBeFiltered */,
- NullGrab))
+ if (ValidAtom (property))
{
- int j;
-
- s->wid = pProxy->drawable.id;
- s->requestor = requestor;
- s->selection = selection;
- s->target = target;
- s->property = property;
- s->time = xTime;
- s->next = 0;
- s->timer = 0;
-
- memset (s->value, 0, sizeof (s->value));
-
- for (j = 0; j < dmxNumScreens; j++)
- {
- WindowPtr pWin =
- dmxScreens[j].pSelectionProxyWin[i];
- dmxWinPrivPtr pWinPriv =
- DMX_GET_WINDOW_PRIV (pWin);
-
- s->value[j].in = pWinPriv->window;
- if (j == pScreen->myNum)
- s->value[j].out = requestor;
- }
-
- dmxAppendSelection (&reqHead, s);
- return;
+ xcb_get_property_cookie_t prop;
+
+ prop = xcb_get_property (dmxScreen->connection,
+ xFalse,
+ requestor,
+ xProperty,
+ XCB_GET_PROPERTY_TYPE_ANY,
+ 0,
+ 0xffffffff);
+
+ s->wid = owner;
+
+ dmxAddRequest (&dmxScreen->request,
+ dmxMultipleTargetPropertyReply,
+ prop.sequence,
+ (void *) s);
}
-
- xfree (s);
+ }
+ else
+ {
+ if (dmxConvertSelection (pScreen, s, owner, 0, 0))
+ return;
}
}
- else
- {
- /* TODO: wait for proxy window to become available */
- dmxLog (dmxWarning,
- "dmxSelectionRequest: no proxy window available "
- "for conversion of %s selection\n",
- NameForAtom (selection));
- }
+
+ xfree (s);
}
}