Posted to tcl by patthoyts at Mon Dec 07 15:27:53 GMT 2009view raw
- Fix extended window manager hints for Tk menus
- Also add a 'wm attributes . -type' option to apply a type hint to any
- Tk window from script. This is needed for tooltip windows, combobox
- dropdown windows and splash screens and probably others.
- Not quite complete yet. Reading the hints back from the window
- need to do the reverse lookup still.
- diff --git a/unix/tkUnixWm.c b/unix/tkUnixWm.c
- index c4ec9af..fcdcac1 100644
- --- a/unix/tkUnixWm.c
- +++ b/unix/tkUnixWm.c
- @@ -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 *);
- @@ -1277,6 +1279,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)) {
- @@ -1330,6 +1336,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;
- }
- @@ -5325,6 +5333,108 @@ UpdateHints(
- XSetWMHints(winPtr->display, wmPtr->wrapperPtr->window, &wmPtr->hints);
- }
- +struct ExwmhLookup {
- + const char *name;
- + const char *hint;
- +};
- +struct ExwmhLookup exwmh_map[] = {
- + { "desktop", "_NET_WM_WINDOW_TYPE_DESKTOP" },
- + { "dock", "_NET_WM_WINDOW_TYPE_DOCK" },
- + { "toolbar", "_NET_WM_WINDOW_TYPE_TOOLBAR" },
- + { "menu", "_NET_WM_WINDOW_TYPE_MENU" },
- + { "utility", "_NET_WM_WINDOW_TYPE_UTILITY" },
- + { "splash", "_NET_WM_WINDOW_TYPE_SPLASH" },
- + { "dialog", "_NET_WM_WINDOW_TYPE_DIALOG" },
- + { "dropdown", "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU" },
- + { "popup", "_NET_WM_WINDOW_TYPE_POPUP_MENU" },
- + { "tooltip", "_NET_WM_WINDOW_TYPE_TOOLTIP" },
- + { "notification", "_NET_WM_WINDOW_TYPE_NOTIFICATION" },
- + { "combo", "_NET_WM_WINDOW_TYPE_COMBO" },
- + { "dnd", "_NET_WM_WINDOW_TYPE_DND" },
- + { "normal", "_NET_WM_WINDOW_TYPE_NORMAL" },
- + { NULL, NULL }
- +};
- +
- +int
- +SetNetWmType(TkWindow *winPtr, Tcl_Obj *typePtr)
- +{
- + Atom typeAtom, *atoms;
- + WmInfo *wmPtr;
- + TkWindow *wrapperPtr;
- + Tcl_Obj **objv;
- + int objc, n, index;
- + 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 (objc == 0) {
- + return TCL_OK;
- + }
- +
- + if (!Tk_HasWrapper(tkwin)) {
- + return TCL_OK; /* error?? */
- + }
- +
- + atoms = (Atom *)ckalloc(sizeof(Atom) * objc);
- +
- + for (n = 0; n < objc; ++n) {
- + if (TCL_OK != Tcl_GetIndexFromObjStruct(interp, objv[n], exwmh_map,
- + sizeof(exwmh_map[0]), "type", 0, &index)) {
- + ckfree((char *)atoms);
- + return TCL_ERROR;
- + }
- + atoms[n] = Tk_InternAtom(tkwin, exwmh_map[index].hint);
- + }
- +
- + 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;
- +}
- +
- +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 = winPtr->wmInfoPtr->wrapperPtr;
- + Tcl_Obj *typePtr;
- + Tcl_Interp *interp;
- +
- + interp = Tk_Interp(tkwin);
- + typePtr = Tcl_NewListObj(0, NULL);
- +
- + 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) {
- + Tcl_ListObjAppendElement(interp, typePtr,
- + Tcl_NewStringObj(Tk_GetAtomName(tkwin, atoms[n]), -1));
- + }
- + XFree(propertyValue);
- + }
- +
- + return typePtr;
- +}
- +
- /*
- *--------------------------------------------------------------
- *
- @@ -6599,6 +6709,19 @@ GetMaxSize(
- }
- }
- +void
- +TkSetTransientFor(Tk_Window tkwin, Tk_Window parent)
- +{
- + if (parent == NULL) {
- + parent = Tk_Parent(tkwin);
- + while (!Tk_IsTopLevel(parent))
- + parent = Tk_Parent(tkwin);
- + }
- + XSetTransientForHint(Tk_Display(tkwin),
- + ((TkWindow *)tkwin)->wmInfoPtr->wrapperPtr->window,
- + ((TkWindow *)parent)->wmInfoPtr->wrapperPtr->window);
- +}
- +
- /*
- *----------------------------------------------------------------------
- *
- @@ -6628,6 +6751,7 @@ TkpMakeMenuWindow(
- WmInfo *wmPtr;
- XSetWindowAttributes atts;
- TkWindow *wrapperPtr;
- + Atom atom;
- if (!Tk_HasWrapper(tkwin)) {
- return;
- @@ -6640,10 +6764,17 @@ TkpMakeMenuWindow(
- if (transient) {
- atts.override_redirect = True;
- atts.save_under = True;
- + atom = Tk_InternAtom((Tk_Window) tkwin, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU");
- } else {
- atts.override_redirect = False;
- atts.save_under = False;
- + atom = Tk_InternAtom((Tk_Window) tkwin, "_NET_WM_WINDOW_TYPE_MENU");
- + TkSetTransientFor(tkwin, NULL);
- }
- + XChangeProperty(Tk_Display(tkwin), wrapperPtr->window,
- + Tk_InternAtom((Tk_Window) tkwin, "_NET_WM_WINDOW_TYPE"),
- + XA_ATOM, 32, PropModeReplace,
- + (unsigned char *) &atom, 1);
- /*
- * The override-redirect and save-under bits must be set on the wrapper