wmii

git clone git://oldgit.suckless.org/wmii/
Log | Files | Refs | README | LICENSE

xembed.c (3033B)


      1 /* Copyright ©2010 Kris Maglione <maglione.k at Gmail>
      2  * See LICENSE file for license details.
      3  */
      4 #include "dat.h"
      5 #include "fns.h"
      6 
      7 #define DEAD ~0UL
      8 
      9 enum { XEmbedVersion = 0 };
     10 
     11 enum XEmbedMessage {
     12 	XEmbedEmbeddedNotify,
     13 	XEmbedWindowActivate,
     14 	XEmbedWindowDeactivate,
     15 	XEmbedRequestFocus,
     16 	XEmbedFocusIn,
     17 	XEmbedFocusOut,
     18 	XEmbedFocusNext,
     19 	XEmbedFocusPrev,
     20 	XEmbedModalityOn = 10,
     21 	XEmbedModalityOff,
     22 	XEmbedRegisterAccelerator,
     23 	XEmbedUnregisterAccelerator,
     24 	XEmbedActivateAccelerator,
     25 };
     26 
     27 enum XEmbedFocusDetail {
     28 	XEmbedFocusCurrent,
     29 	XEmbedFocusFirst,
     30 	XEmbedFocusLast,
     31 };
     32 
     33 static Handlers	handlers;
     34 
     35 static void	xembed_updateinfo(XEmbed*);
     36 static void	xembed_sendmessage(XEmbed*, long, long, long, long);
     37 
     38 XEmbed*
     39 xembed_swallow(Window *parent, Window *client, void (*cleanup)(XEmbed*)) {
     40 	XEmbed *xembed;
     41 
     42 	xembed = emallocz(sizeof *xembed);
     43 	xembed->w = client;
     44 	xembed->owner = parent;
     45 	xembed->cleanup = cleanup;
     46 	selectinput(client, client->eventmask | PropertyChangeMask | StructureNotifyMask);
     47 	pushhandler(client, &handlers, xembed);
     48 
     49 	reparentwindow(client, parent, ZP);
     50 	xembed_updateinfo(xembed);
     51 	xembed_sendmessage(xembed, XEmbedEmbeddedNotify, 0, parent->xid, min(XEmbedVersion, xembed->version));
     52 	return xembed;
     53 }
     54 
     55 void
     56 xembed_disown(XEmbed *xembed) {
     57 
     58 	pophandler(xembed->w, &handlers);
     59 	if(xembed->flags != DEAD) {
     60 		reparentwindow(xembed->w, &scr.root, ZP);
     61 		unmapwin(xembed->w);
     62 	}
     63 	if(xembed->cleanup)
     64 		xembed->cleanup(xembed);
     65 	free(xembed);
     66 }
     67 
     68 static void
     69 xembed_updateinfo(XEmbed *xembed) {
     70 	ulong *res;
     71 	int n;
     72 
     73 	n = getprop_ulong(xembed->w, "_XEMBED_INFO", "_XEMBED_INFO", 0, &res, 2);
     74 	xembed->flags = 0UL;
     75 	if(n >= 2) {
     76 		xembed->version = res[0];
     77 		xembed->flags = res[1];
     78 	}
     79 	else {
     80 		/* Deal with a Qt system tray replacement bug. */
     81 		xembed->flags = XEmbedMapped;
     82 	}
     83 	free(res);
     84 
     85 	Dprint("xembed_updateinfo(0x%ulx) XEmbedMapped=%s\n",
     86 	       xembed->w,
     87 	       xembed->flags & XEmbedMapped ? "true" : "false");
     88 
     89 	if(xembed->flags & XEmbedMapped)
     90 		mapwin(xembed->w);
     91 	else
     92 		unmapwin(xembed->w);
     93 }
     94 
     95 static void
     96 xembed_sendmessage(XEmbed *xembed, long message, long detail, long data1, long data2) {
     97 
     98 	traperrors(true);
     99 	sendmessage(xembed->w, "_XEMBED", event_xtime, message, detail, data1, data2);
    100 	traperrors(false);
    101 }
    102 
    103 static bool
    104 destroy_event(Window *w, void *aux, XDestroyWindowEvent *ev) {
    105 	XEmbed *xembed;
    106 
    107 	xembed = aux;
    108 	xembed->flags = DEAD;
    109 	xembed_disown(xembed);
    110 	return false;
    111 }
    112 
    113 static bool
    114 property_event(Window *w, void *aux, XPropertyEvent *ev) {
    115 	XEmbed *xembed;
    116 
    117 	Dprint("property_event(%W, %p, %A)\n",
    118 	       w, aux, ev->atom);
    119 	xembed = aux;
    120 	if(ev->atom == xatom("_XEMBED_INFO"))
    121 		xembed_updateinfo(xembed);
    122 	return false;
    123 }
    124 
    125 static bool
    126 reparent_event(Window *w, void *aux, XReparentEvent *ev) {
    127 	XEmbed *xembed;
    128 
    129 	xembed = aux;
    130 	if(ev->parent != xembed->owner->xid) {
    131 		xembed->flags = DEAD;
    132 		xembed_disown(xembed);
    133 	}
    134 	return false;
    135 }
    136 
    137 static Handlers handlers = {
    138 	.destroy = destroy_event,
    139 	.property = property_event,
    140 	.reparent = reparent_event,
    141 };