Attachment "ewmh.patch" to
ticket [2918731f]
added by
dkf
2009-12-21 22:25:04.
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