From 8582c8ae77717ddf56515e8f3c3aa77015ba72ed Mon Sep 17 00:00:00 2001 From: dkf Date: Mon, 11 Dec 2006 13:08:57 +0000 Subject: Support the _NET_WM_PING protocol from EWMH. There's no reason to do anything other than what is implemented, so no need for additional script control over it. --- ChangeLog | 30 +++++++---- unix/tkUnixWm.c | 155 +++++++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 139 insertions(+), 46 deletions(-) diff --git a/ChangeLog b/ChangeLog index 97a00bc..e55d24d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,20 +1,30 @@ +2006-12-11 Donal K. Fellows + + * unix/tkUnixWm.c (TkWmMapWindow, WmClientCmd): Added support for + _NET_WM_PID property from the EWMH spec. This is only installed when + the client machine is set. + (WmProtocolCmd, UpdateWmProtocols, TkWmProtocolEventProc): Added + support for the _NET_WM_PING protocol from the EWMH spec. Note that + the support for this is not exposed to the script level as that would + prevent correct handling. + 2006-12-10 Joe English * generic/ttk/ttkTheme.h, generic/ttk/ttkThemeInt.h, - generic/ttk/ttk.decls, generic/ttk/ttkTheme.c, - generic/ttk/ttkLayout.c, generic/ttk/ttkDecls.h: + * generic/ttk/ttk.decls, generic/ttk/ttkTheme.c, + * generic/ttk/ttkLayout.c, generic/ttk/ttkDecls.h: Rename typedef Ttk_Element => Ttk_ElementImpl. 2006-12-09 Joe English * generic/ttk/ttkButton.c, generic/ttk/ttkImage.c, - generic/ttk/ttkLabel.c, generic/ttk/ttkWidget.h, - generic/ttk/ttkTheme.h, generic/ttk/ttkNotebook.c, - generic/ttk/ttkTreeview.c, doc/ttk_image.n: - Merged duplicate functionality between image element factory, - image element, and -image option processing. Image element - factory now takes an imageSpec argument instead of a separate - image name and -map option. + * generic/ttk/ttkLabel.c, generic/ttk/ttkWidget.h, + * generic/ttk/ttkTheme.h, generic/ttk/ttkNotebook.c, + * generic/ttk/ttkTreeview.c, doc/ttk_image.n: + Merged duplicate functionality between image element factory, image + element, and -image option processing. Image element factory now + takes an imageSpec argument instead of a separate image name and -map + option. * tests/ttk/image.test(image-1.1): Can catch this error earlier now. 2006-12-06 Kevin Kenny @@ -22,7 +32,7 @@ * unix/configure.in: Further changes to avoid attempting to link * unix/configure: against Xft libraries in a non-Xft build [Bug 1609616] (dgp) - + 2006-12-04 Jeff Hobbs * generic/tkListbox.c (ConfigureListboxItem): ListboxWorldChanged not diff --git a/unix/tkUnixWm.c b/unix/tkUnixWm.c index ee43db5..ec4fd20 100644 --- a/unix/tkUnixWm.c +++ b/unix/tkUnixWm.c @@ -12,7 +12,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkUnixWm.c,v 1.51 2006/05/29 22:21:40 hobbs Exp $ + * RCS: @(#) $Id: tkUnixWm.c,v 1.52 2006/12/11 13:08:58 dkf Exp $ */ #include "tkPort.h" @@ -52,8 +52,8 @@ typedef struct { int fullscreen; /* Flag: true=>fullscreen */ } WmAttributes; -typedef enum { - WMATT_ALPHA, WMATT_TOPMOST, WMATT_ZOOMED, WMATT_FULLSCREEN, +typedef enum { + WMATT_ALPHA, WMATT_TOPMOST, WMATT_ZOOMED, WMATT_FULLSCREEN, _WMATT_LAST_ATTRIBUTE } WmAttribute; @@ -686,9 +686,23 @@ TkWmMapWindow( Tcl_UtfToExternalDString(NULL, wmPtr->clientMachine, -1, &ds); if (XStringListToTextProperty(&(Tcl_DStringValue(&ds)), 1, &textProp) != 0) { + unsigned long pid = (unsigned long) getpid(); + XSetWMClientMachine(winPtr->display, wmPtr->wrapperPtr->window, &textProp); XFree((char *) textProp.value); + + /* + * Inform the server (and more particularly any session + * manager) what our process ID is. We only do this when the + * CLIENT_MACHINE property is set since the spec for + * _NET_WM_PID requires that to be set too. + */ + + XChangeProperty(winPtr->display, wmPtr->wrapperPtr->window, + Tk_InternAtom(winPtr->display, "_NET_WM_PID"), + XA_CARDINAL, 32, PropModeReplace, + (unsigned char *) &pid, 1); } Tcl_DStringFree(&ds); } @@ -1444,9 +1458,22 @@ WmClientCmd( Tcl_UtfToExternalDString(NULL, wmPtr->clientMachine, -1, &ds); if (XStringListToTextProperty(&(Tcl_DStringValue(&ds)), 1, &textProp) != 0) { + unsigned long pid = (unsigned long) getpid(); + XSetWMClientMachine(winPtr->display, wmPtr->wrapperPtr->window, &textProp); XFree((char *) textProp.value); + + /* + * Inform the server (and more particularly any session manager) + * what our process ID is. We only do this when the CLIENT_MACHINE + * property is set since the spec for _NET_WM_PID requires that to + * be set too. + */ + + XChangeProperty(winPtr->display, wmPtr->wrapperPtr->window, + Tk_InternAtom(winPtr->display, "_NET_WM_PID"), + XA_CARDINAL,32, PropModeReplace, (unsigned char*)&pid, 1); } Tcl_DStringFree(&ds); } @@ -2836,6 +2863,16 @@ WmProtocolCmd( } /* + * Special case for _NET_WM_PING: that's always handled directly. + */ + + if (strcmp(Tcl_GetString(objv[3]), "_NET_WM_PING") == 0) { + Tcl_SetResult(interp, "may not alter handling of that protocol", + TCL_STATIC); + return TCL_ERROR; + } + + /* * Delete any current protocol handler, then create a new one with the * specified command, unless the command is empty. */ @@ -4098,8 +4135,8 @@ ComputeReparentGeometry( * * PropertyEvent -- * - * Handle PropertyNotify events on wrapper windows. - * The following properties are of interest: + * Handle PropertyNotify events on wrapper windows. The following + * properties are of interest: * * _NET_WM_STATE: * Used to keep wmPtr->attributes up to date. @@ -4114,7 +4151,7 @@ PropertyEvent( { TkWindow *wrapperPtr = wmPtr->wrapperPtr; Atom _NET_WM_STATE = - Tk_InternAtom((Tk_Window)wmPtr->winPtr, "_NET_WM_STATE"); + Tk_InternAtom((Tk_Window)wmPtr->winPtr, "_NET_WM_STATE"); if (eventPtr->atom == _NET_WM_STATE) { Atom actualType; @@ -4126,9 +4163,8 @@ PropertyEvent( if (XGetWindowProperty( wrapperPtr->display, wrapperPtr->window, _NET_WM_STATE, 0l, maxLength, False, XA_ATOM, - &actualType, &actualFormat, &numItems, &bytesAfter, - &propertyValue) == Success - ) { + &actualType, &actualFormat, &numItems, &bytesAfter, + &propertyValue) == Success) { CheckNetWmState(wmPtr, (Atom*)propertyValue, (int)numItems); XFree(propertyValue); } @@ -4153,7 +4189,7 @@ PropertyEvent( *---------------------------------------------------------------------- */ -static const unsigned int WrapperEventMask = +static const unsigned int WrapperEventMask = (StructureNotifyMask | PropertyChangeMask); static void @@ -4754,8 +4790,7 @@ UpdatePhotoIcon( * Sets the specified state property by sending a _NET_WM_STATE * ClientMessage to the root window. * - * Preconditions: - * + * Preconditions: * Wrapper window must be created. * * See also: @@ -4768,7 +4803,11 @@ UpdatePhotoIcon( #define _NET_WM_STATE_ADD 1l #define _NET_WM_STATE_TOGGLE 2l -static void SetNetWmState(TkWindow *winPtr, const char *atomName, int on) +static void +SetNetWmState( + TkWindow *winPtr, + const char *atomName, + int on) { Tk_Window tkwin = (Tk_Window)winPtr; Atom messageType = Tk_InternAtom(tkwin, "_NET_WM_STATE"); @@ -4794,29 +4833,38 @@ static void SetNetWmState(TkWindow *winPtr, const char *atomName, int on) } /* + *---------------------------------------------------------------------- + * * CheckNetWmState -- * - * Updates the window attributes whenever the _NET_WM_STATE - * property changes. + * Updates the window attributes whenever the _NET_WM_STATE property + * changes. * * Notes: - * - * Tk uses a single -zoomed state, while the EWMH spec supports - * separate vertical and horizontal maximization. We consider - * the window to be "zoomed" if _NET_WM_STATE_MAXIMIZED_VERT - * and _NET_WM_STATE_MAXIMIZED_HORZ are both set. + * + * Tk uses a single -zoomed state, while the EWMH spec supports separate + * vertical and horizontal maximization. We consider the window to be + * "zoomed" if _NET_WM_STATE_MAXIMIZED_VERT and + * _NET_WM_STATE_MAXIMIZED_HORZ are both set. + * + *---------------------------------------------------------------------- */ -static void CheckNetWmState(WmInfo *wmPtr, Atom *atoms, int numAtoms) + +static void +CheckNetWmState( + WmInfo *wmPtr, + Atom *atoms, + int numAtoms) { Tk_Window tkwin = (Tk_Window)wmPtr->wrapperPtr; int i; Atom _NET_WM_STATE_ABOVE = Tk_InternAtom(tkwin, "_NET_WM_STATE_ABOVE"), - _NET_WM_STATE_MAXIMIZED_VERT + _NET_WM_STATE_MAXIMIZED_VERT = Tk_InternAtom(tkwin, "_NET_WM_STATE_MAXIMIZED_VERT"), - _NET_WM_STATE_MAXIMIZED_HORZ + _NET_WM_STATE_MAXIMIZED_HORZ = Tk_InternAtom(tkwin, "_NET_WM_STATE_MAXIMIZED_HORZ"), - _NET_WM_STATE_FULLSCREEN + _NET_WM_STATE_FULLSCREEN = Tk_InternAtom(tkwin, "_NET_WM_STATE_FULLSCREEN"); wmPtr->attributes.topmost = 0; @@ -4840,13 +4888,21 @@ static void CheckNetWmState(WmInfo *wmPtr, Atom *atoms, int numAtoms) } /* + *---------------------------------------------------------------------- + * * UpdateNetWmState -- * * Sets the _NET_WM_STATE property to match the requested attribute state * just prior to mapping a withdrawn window. + * + *---------------------------------------------------------------------- */ + #define NET_WM_STATE_MAX_ATOMS 4 -static void UpdateNetWmState(WmInfo *wmPtr) + +static void +UpdateNetWmState( + WmInfo *wmPtr) { Tk_Window tkwin = (Tk_Window)wmPtr->wrapperPtr; Atom atoms[NET_WM_STATE_MAX_ATOMS]; @@ -4858,13 +4914,13 @@ static void UpdateNetWmState(WmInfo *wmPtr) if (wmPtr->reqState.zoomed) { atoms[numAtoms++] = Tk_InternAtom(tkwin,"_NET_WM_STATE_MAXIMIZED_VERT"); atoms[numAtoms++] = Tk_InternAtom(tkwin,"_NET_WM_STATE_MAXIMIZED_HORZ"); - } + } if (wmPtr->reqState.fullscreen) { atoms[numAtoms++] = Tk_InternAtom(tkwin, "_NET_WM_STATE_FULLSCREEN"); } - XChangeProperty(Tk_Display(tkwin), wmPtr->wrapperPtr->window, - Tk_InternAtom(tkwin, "_NET_WM_STATE"), XA_ATOM, 32, + XChangeProperty(Tk_Display(tkwin), wmPtr->wrapperPtr->window, + Tk_InternAtom(tkwin, "_NET_WM_STATE"), XA_ATOM, 32, PropModeReplace, (unsigned char *)atoms, numAtoms); } @@ -5803,7 +5859,7 @@ UpdateWmProtocols( register WmInfo *wmPtr) /* Information about top-level window. */ { register ProtocolHandler *protPtr; - Atom deleteWindowAtom; + Atom deleteWindowAtom, pingAtom; int count; Atom *arrayPtr, *atomPtr; @@ -5811,22 +5867,25 @@ UpdateWmProtocols( * There are only two tricky parts here. First, there could be any number * of atoms for the window, so count them and malloc an array to hold all * of their atoms. Second, we *always* want to respond to the - * WM_DELETE_WINDOW protocol, even if no-one's officially asked. + * WM_DELETE_WINDOW and _NET_WM_PING protocols, even if no-one's + * officially asked. */ - for (protPtr = wmPtr->protPtr, count = 1; protPtr != NULL; + for (protPtr = wmPtr->protPtr, count = 2; protPtr != NULL; protPtr = protPtr->nextPtr, count++) { /* Empty loop body; we're just counting the handlers. */ } arrayPtr = (Atom *) ckalloc((unsigned) (count * sizeof(Atom))); deleteWindowAtom = Tk_InternAtom((Tk_Window) wmPtr->winPtr, "WM_DELETE_WINDOW"); + pingAtom = Tk_InternAtom((Tk_Window) wmPtr->winPtr, "_NET_WM_PING"); arrayPtr[0] = deleteWindowAtom; + arrayPtr[1] = pingAtom; for (protPtr = wmPtr->protPtr, atomPtr = &arrayPtr[1]; protPtr != NULL; protPtr = protPtr->nextPtr) { - if (protPtr->protocol != deleteWindowAtom) { - *atomPtr = protPtr->protocol; - atomPtr++; + if (protPtr->protocol != deleteWindowAtom + && protPtr->protocol != pingAtom) { + *(atomPtr++) = protPtr->protocol; } } XChangeProperty(wmPtr->winPtr->display, wmPtr->wrapperPtr->window, @@ -5866,11 +5925,27 @@ TkWmProtocolEventProc( CONST char *protocolName; Tcl_Interp *interp; + protocol = (Atom) eventPtr->xclient.data.l[0]; + + /* + * If this is a _NET_WM_PING message, send it back to the root window + * immediately. We do that here because scripts *cannot* respond correctly + * to this protocol. + */ + + if (protocol == Tk_InternAtom((Tk_Window) winPtr, "_NET_WM_PING")) { + Window root = XRootWindow(winPtr->display, winPtr->screenNum); + + eventPtr->xclient.window = root; + (void) XSendEvent(winPtr->display, root, False, + (SubstructureNotify|SubstructureRedirect), eventPtr); + return; + } + wmPtr = winPtr->wmInfoPtr; if (wmPtr == NULL) { return; } - protocol = (Atom) eventPtr->xclient.data.l[0]; /* * Note: it's very important to retrieve the protocol name now, before @@ -6571,7 +6646,7 @@ CreateWrapper( * etc.. */ - Tk_CreateEventHandler((Tk_Window) wmPtr->wrapperPtr, + Tk_CreateEventHandler((Tk_Window) wmPtr->wrapperPtr, WrapperEventMask, WrapperEventProc, (ClientData) wmPtr); } @@ -6929,3 +7004,11 @@ TkpWmSetState( return 1; } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ -- cgit v0.12