[sawfish] Handle requests for the manager selection.



commit dae27b06562dc82752c4b22df363174e923d69c6
Author: Timo Korvola <tkorvola iki fi>
Date:   Mon Dec 27 15:01:27 2010 +0200

    Handle requests for the manager selection.
    
    The details are rather complicated even for the minimum
    functionality required in the ICCCM.  Checked out how FVWM does it
    and mostly aped that.

 src/events.c |   96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 93 insertions(+), 3 deletions(-)
---
diff --git a/src/events.c b/src/events.c
index 03b7886..4176d52 100644
--- a/src/events.c
+++ b/src/events.c
@@ -69,7 +69,8 @@ static bool pointer_is_grabbed;
 
 static XID event_handler_context;
 
-static Atom xa_sawfish_timestamp;
+static Atom xa_sawfish_timestamp, xa_targets, xa_multiple, xa_timestamp,
+    xa_version, xa_atom_pair;
 
 /* is there xrand support? */
 static int has_randr = FALSE;
@@ -1284,13 +1285,97 @@ selection_clear (XEvent *ev)
 	Fquit ();
 }
 
+static bool
+convert_selection (Window requestor, Atom target, Atom property)
+{
+    if (property == None)
+	return FALSE;
+    if (target == xa_targets)
+    {
+	long targets[4];
+	targets[0] = xa_targets;
+	targets[1] = xa_multiple;
+	targets[2] = xa_timestamp;
+	targets[3] = xa_version;
+	XChangeProperty(dpy, requestor, property, XA_ATOM, 32, PropModeReplace,
+			(unsigned char *)targets, 4);
+	return TRUE;
+    }
+    else if (target == xa_multiple)
+    {
+	Atom act_type;
+	int act_format;
+	bool good = FALSE;
+	unsigned char *pdata;
+	unsigned long n_items, bytes_left;
+	    
+	if (XGetWindowProperty(dpy, requestor, property, 0, 256,
+			       False, xa_atom_pair, &act_type, &act_format,
+			       &n_items, &bytes_left, &pdata) == Success)
+	{
+	    if (act_type == xa_atom_pair && act_format == 32
+		&& bytes_left <= 0 && n_items % 2 == 0)
+	    {
+		long *atoms = (long *) pdata;
+		int i;
+		bool some_failed = FALSE;
+		for (i = 0; i != n_items; i += 2)
+		    if (!convert_selection(requestor, atoms[i], atoms[i + 1]))
+		    {
+			some_failed = TRUE;
+			atoms[i + 1] = None;
+		    }
+		if (some_failed)
+		    XChangeProperty(dpy, requestor, property, xa_atom_pair, 32,
+				    PropModeReplace, pdata, n_items);
+		good = TRUE;
+	    }
+	    XFree(pdata);
+	}
+	return good;
+    }
+    else if (target == xa_timestamp)
+    {
+	long t = startup_time;
+	XChangeProperty(dpy, requestor, property, XA_INTEGER, 32,
+			PropModeReplace, (unsigned char *) &t, 1);
+	return TRUE;
+    }
+    else if (target == xa_version)
+    {
+	long version[2];
+	version[0] = 2;
+	version[1] = 0;
+	XChangeProperty(dpy, requestor, property, XA_INTEGER, 32,
+			PropModeReplace, (unsigned char *) version, 2);
+	return TRUE;
+    }
+    else
+	return FALSE;
+}
+
 static void
 selection_request (XEvent *ev)
 {
-    XSelectionRequestEvent *srev = &ev->xselectionrequest;
-    if (srev->selection == xa_wm_sn)
+    XSelectionRequestEvent *req = &ev->xselectionrequest;
+    XSelectionEvent reply;
+    reply.type = SelectionNotify;
+    reply.requestor = req->requestor;
+    reply.selection = req->selection;
+    reply.target = req->target;
+    /* Refuse by default. */
+    reply.property = None;
+    reply.time = req->time;
+    if (req->selection == xa_wm_sn
+	&& req->owner == no_focus_window && req->time >= startup_time)
     {
+	Atom prop = req->property;
+	if (prop == None && req->target != xa_multiple)
+	    prop = req->target;
+	if (convert_selection(req->requestor, req->target, prop))
+	    reply.property = prop;
     }
+    XSendEvent(dpy, req->requestor, False, 0, (XEvent *) &reply);
 }
 
 static void
@@ -1918,6 +2003,11 @@ events_init (void)
     if(!batch_mode_p ())
     {
 	xa_sawfish_timestamp = XInternAtom (dpy, "_SAWFISH_TIMESTAMP", False);
+	xa_targets = XInternAtom (dpy, "TARGETS", False);
+	xa_multiple = XInternAtom (dpy, "MULTIPLE", False);
+	xa_timestamp = XInternAtom (dpy, "TIMESTAMP", False);
+	xa_version = XInternAtom (dpy, "VERSION", False);
+	xa_atom_pair = XInternAtom (dpy, "ATOM_PAIR", False);
 	last_event_time = get_server_timestamp ();
     }
 }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]