diff options
author | patthoyts <patthoyts@users.sourceforge.net> | 2010-01-20 23:43:50 (GMT) |
---|---|---|
committer | patthoyts <patthoyts@users.sourceforge.net> | 2010-01-20 23:43:50 (GMT) |
commit | 8653f8ec25290721bc6fac2a9c68bbff0a4c4eb3 (patch) | |
tree | 57e880fe1efd95782a3cb841debb5d8e410fd021 /unix | |
parent | 545af346b6b7f4d2e3c1bfa931e01202c6c7808d (diff) | |
download | tk-8653f8ec25290721bc6fac2a9c68bbff0a4c4eb3.zip tk-8653f8ec25290721bc6fac2a9c68bbff0a4c4eb3.tar.gz tk-8653f8ec25290721bc6fac2a9c68bbff0a4c4eb3.tar.bz2 |
TIP #359: Extended window manager hints support for X11.
Diffstat (limited to 'unix')
-rw-r--r-- | unix/tkUnixWm.c | 151 |
1 files changed, 140 insertions, 11 deletions
diff --git a/unix/tkUnixWm.c b/unix/tkUnixWm.c index 680d4f2..4040f4d 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.58.2.6 2010/01/06 09:30:21 dkf Exp $ + * RCS: @(#) $Id: tkUnixWm.c,v 1.58.2.7 2010/01/20 23:43:52 patthoyts Exp $ */ #include "tkUnixInt.h" @@ -52,12 +52,12 @@ typedef struct { typedef enum { WMATT_ALPHA, WMATT_TOPMOST, WMATT_ZOOMED, WMATT_FULLSCREEN, - _WMATT_LAST_ATTRIBUTE + WMATT_TYPE, _WMATT_LAST_ATTRIBUTE } WmAttribute; static const char *WmAttributeNames[] = { "-alpha", "-topmost", "-zoomed", "-fullscreen", - NULL + "-type", NULL }; /* @@ -347,6 +347,8 @@ static void UpdateTitle(TkWindow *winPtr); static void UpdatePhotoIcon(TkWindow *winPtr); static void UpdateVRootGeometry(WmInfo *wmPtr); static void UpdateWmProtocols(WmInfo *wmPtr); +static int SetNetWmType(TkWindow *winPtr, Tcl_Obj *typePtr); +static Tcl_Obj * GetNetWmType(TkWindow *winPtr); static void SetNetWmState(TkWindow*, const char *atomName, int on); static void CheckNetWmState(WmInfo *, Atom *atoms, int numAtoms); static void UpdateNetWmState(WmInfo *); @@ -1281,6 +1283,10 @@ WmSetAttribute( SetNetWmState(winPtr, "_NET_WM_STATE_ABOVE", wmPtr->reqState.topmost); break; + case WMATT_TYPE: + if (TCL_OK != SetNetWmType(winPtr, value)) + return TCL_ERROR; + break; case WMATT_ZOOMED: if (TCL_OK != Tcl_GetBooleanFromObj(interp, value, &wmPtr->reqState.zoomed)) { @@ -1334,6 +1340,8 @@ WmGetAttribute( return Tcl_NewBooleanObj(wmPtr->attributes.zoomed); case WMATT_FULLSCREEN: return Tcl_NewBooleanObj(wmPtr->attributes.fullscreen); + case WMATT_TYPE: + return GetNetWmType(winPtr); case _WMATT_LAST_ATTRIBUTE: /*NOTREACHED*/ break; } @@ -5333,6 +5341,130 @@ UpdateHints( } /* + *---------------------------------------------------------------------- + * + * SetNetWmType -- + * + * Set the extended window manager hints for a toplevel window + * to the types provided. The specification states that this + * may be a list of window types in preferred order. To permit + * for future type definitions, the set of names is unconstrained + * and names are converted to upper-case and appended to + * "_NET_WM_WINDOW_TYPE_" before being converted to an Atom. + * + *---------------------------------------------------------------------- + */ + +static int +SetNetWmType(TkWindow *winPtr, Tcl_Obj *typePtr) +{ + Atom typeAtom, *atoms = NULL; + WmInfo *wmPtr; + TkWindow *wrapperPtr; + Tcl_Obj **objv; + int objc, n; + Tk_Window tkwin = (Tk_Window)winPtr; + Tcl_Interp *interp = Tk_Interp(tkwin); + + if (TCL_OK != Tcl_ListObjGetElements(interp, typePtr, &objc, &objv)) { + return TCL_ERROR; + } + + if (!Tk_HasWrapper(tkwin)) { + return TCL_OK; /* error?? */ + } + + if (objc > 0) { + atoms = (Atom *)ckalloc(sizeof(Atom) * objc); + } + + for (n = 0; n < objc; ++n) { + Tcl_DString ds, dsName; + int len; + char *name = Tcl_GetStringFromObj(objv[n], &len); + Tcl_UtfToUpper(name); + Tcl_UtfToExternalDString(NULL, name, len, &dsName); + Tcl_DStringInit(&ds); + Tcl_DStringAppend(&ds, "_NET_WM_WINDOW_TYPE_", 20); + Tcl_DStringAppend(&ds, Tcl_DStringValue(&dsName), + Tcl_DStringLength(&dsName)); + Tcl_DStringFree(&dsName); + atoms[n] = Tk_InternAtom(tkwin, Tcl_DStringValue(&ds)); + Tcl_DStringFree(&ds); + } + + wmPtr = winPtr->wmInfoPtr; + if (wmPtr->wrapperPtr == NULL) { + CreateWrapper(wmPtr); + } + wrapperPtr = wmPtr->wrapperPtr; + + typeAtom = Tk_InternAtom(tkwin, "_NET_WM_WINDOW_TYPE"); + XChangeProperty(Tk_Display(tkwin), wrapperPtr->window, typeAtom, + XA_ATOM, 32, PropModeReplace, (unsigned char *) atoms, objc); + + ckfree((char *)atoms); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * GetNetWmType -- + * + * Read the extended window manager type hint from a window + * and return as a list of names suitable for use with + * SetNetWmType. + * + *---------------------------------------------------------------------- + */ + +static Tcl_Obj * +GetNetWmType(TkWindow *winPtr) +{ + Atom typeAtom, actualType, *atoms; + int actualFormat; + unsigned long n, count, bytesAfter; + unsigned char *propertyValue = NULL; + long maxLength = 1024; + Tk_Window tkwin = (Tk_Window)winPtr; + TkWindow *wrapperPtr; + Tcl_Obj *typePtr; + Tcl_Interp *interp; + Tcl_DString ds; + + interp = Tk_Interp(tkwin); + typePtr = Tcl_NewListObj(0, NULL); + + if (winPtr->wmInfoPtr->wrapperPtr == NULL) { + CreateWrapper(winPtr->wmInfoPtr); + } + wrapperPtr = winPtr->wmInfoPtr->wrapperPtr; + + typeAtom = Tk_InternAtom(tkwin, "_NET_WM_WINDOW_TYPE"); + if (Success == XGetWindowProperty(wrapperPtr->display, + wrapperPtr->window, typeAtom, 0L, maxLength, False, + XA_ATOM, &actualType, &actualFormat, &count, + &bytesAfter, &propertyValue)) { + atoms = (Atom *)propertyValue; + for (n = 0; n < count; ++n) { + const char *name = Tk_GetAtomName(tkwin, atoms[n]); + if (strncmp("_NET_WM_WINDOW_TYPE_", name, 20) == 0) { + Tcl_ExternalToUtfDString(NULL, name+20, -1, &ds); + Tcl_UtfToLower(Tcl_DStringValue(&ds)); + Tcl_ListObjAppendElement(interp, typePtr, + Tcl_NewStringObj(Tcl_DStringValue(&ds), + Tcl_DStringLength(&ds))); + Tcl_DStringFree(&ds); + } + } + XFree(propertyValue); + } + + return typePtr; +} + +/* *-------------------------------------------------------------- * * ParseGeometry -- @@ -6659,7 +6791,7 @@ TkpMakeMenuWindow( WmInfo *wmPtr; XSetWindowAttributes atts; TkWindow *wrapperPtr; - Atom atom; + Tcl_Obj *typeObj; if (!Tk_HasWrapper(tkwin)) { return; @@ -6672,17 +6804,14 @@ TkpMakeMenuWindow( if (transient) { atts.override_redirect = True; atts.save_under = True; - atom = Tk_InternAtom((Tk_Window) tkwin, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"); + typeObj = Tcl_NewStringObj("dropdown_menu", -1); } else { atts.override_redirect = False; atts.save_under = False; - atom = Tk_InternAtom((Tk_Window) tkwin, "_NET_WM_WINDOW_TYPE_MENU"); - TkSetTransientFor(tkwin, NULL); + typeObj = Tcl_NewStringObj("menu", -1); + TkSetTransientFor(tkwin, None); } - XChangeProperty(Tk_Display(tkwin), wrapperPtr->window, - Tk_InternAtom((Tk_Window) tkwin, "_NET_WM_WINDOW_TYPE"), - XA_ATOM, 32, PropModeReplace, - (unsigned char *) &atom, 1); + SetNetWmType((TkWindow *)tkwin, typeObj); /* * The override-redirect and save-under bits must be set on the wrapper |