summaryrefslogtreecommitdiff
path: root/hw/xwin/winmultiwindowwm.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/xwin/winmultiwindowwm.c')
-rw-r--r--hw/xwin/winmultiwindowwm.c644
1 files changed, 501 insertions, 143 deletions
diff --git a/hw/xwin/winmultiwindowwm.c b/hw/xwin/winmultiwindowwm.c
index df7e6d3d5..f3ccfb2fc 100644
--- a/hw/xwin/winmultiwindowwm.c
+++ b/hw/xwin/winmultiwindowwm.c
@@ -30,10 +30,24 @@
* Colin Harrison
*/
+#ifndef WINVER
+#define WINVER 0x0500
+#endif
+
/* X headers */
#ifdef HAVE_XWIN_CONFIG_H
#include <xwin-config.h>
#endif
+
+/*
+ * Including any server header might define the macro _XSERVER64 on 64 bit machines.
+ * That macro must _NOT_ be defined for Xlib client code, otherwise bad things happen.
+ * So let's undef that macro if necessary.
+ */
+#ifdef _XSERVER64
+#undef _XSERVER64
+#endif
+
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@@ -49,6 +63,7 @@
#include <xcb/xcb_icccm.h>
#include <xcb/xcb_ewmh.h>
#include <xcb/xcb_aux.h>
+#include <xcb/composite.h>
#include <X11/Xwindows.h>
@@ -57,8 +72,6 @@
#include "winwindow.h"
#include "winprefs.h"
#include "window.h"
-#include "pixmapstr.h"
-#include "windowstr.h"
#include "winglobals.h"
#include "windisplay.h"
#include "winmultiwindowicons.h"
@@ -75,6 +88,7 @@ extern void winDebug(const char *format, ...);
extern void winReshapeMultiWindow(WindowPtr pWin);
extern void winUpdateRgnMultiWindow(WindowPtr pWin);
extern xcb_auth_info_t *winGetXcbAuthInfo(void);
+extern void winUpdateWindowPosition(HWND hWnd, HWND * zstyle);
#ifndef CYGDEBUG
#define CYGDEBUG NO
@@ -90,6 +104,9 @@ extern xcb_auth_info_t *winGetXcbAuthInfo(void);
#define WIN_MSG_QUEUE_FNAME "/dev/windows"
#endif
+#define HINT_MAX (1L<<0)
+#define HINT_MIN (1L<<1)
+
/*
* Local structures
*/
@@ -115,7 +132,12 @@ typedef struct _WMInfo {
xcb_atom_t atmPrivMap;
xcb_atom_t atmUtf8String;
xcb_atom_t atmNetWmName;
+ xcb_atom_t atmCurrentDesktop;
+ xcb_atom_t atmNumberDesktops;
+ xcb_atom_t atmDesktopNames;
+ xcb_atom_t atmWmState;
xcb_ewmh_connection_t ewmh;
+ Bool fCompositeWM;
} WMInfoRec, *WMInfoPtr;
typedef struct _WMProcArgRec {
@@ -158,6 +180,9 @@ static void *winMultiWindowWMProc(void *pArg);
static void *winMultiWindowXMsgProc(void *pArg);
static void
+winMultiWindowThreadExit(void *arg);
+
+static void
winInitMultiWindowWM(WMInfoPtr pWMInfo, WMProcArgPtr pProcArg);
#if 0
@@ -169,10 +194,10 @@ static Bool
CheckAnotherWindowManager(xcb_connection_t *conn, DWORD dwScreen);
static void
- winApplyHints(WMInfoPtr pWMInfo, xcb_window_t iWindow, HWND hWnd, HWND * zstyle);
+ winApplyHints(WMInfoPtr pWMInfo, xcb_window_t iWindow, HWND hWnd, HWND * zstyle, unsigned long *maxmin);
-void
- winUpdateWindowPosition(HWND hWnd, HWND * zstyle);
+static void
+ winApplyUrgency(WMInfoPtr pWMInfo, xcb_window_t iWindow, HWND hWnd);
/*
* Local globals
@@ -219,15 +244,18 @@ MessageName(winWMMessagePtr msg)
case WM_WM_CHANGE_STATE:
return "WM_WM_CHANGE_STATE";
break;
- case WM_WM_MAP2:
- return "WM_WM_MAP2";
+ case WM_WM_MAP_UNMANAGED:
+ return "WM_WM_MAP_UNMANAGED";
break;
- case WM_WM_MAP3:
- return "WM_WM_MAP3";
+ case WM_WM_MAP_MANAGED:
+ return "WM_WM_MAP_MANAGED";
break;
case WM_WM_HINTS_EVENT:
return "WM_WM_HINTS_EVENT";
break;
+ case WM_WM_CREATE:
+ return "WM_WM_CREATE";
+ break;
default:
return "Unknown Message";
break;
@@ -538,8 +566,10 @@ getHwnd(WMInfoPtr pWMInfo, xcb_window_t iWindow)
}
/* Some sanity checks */
- if (!hWnd)
+ if (!hWnd) {
+ winDebug("getHwnd: no HWND\n");
return NULL;
+ }
if (!IsWindow(hWnd))
return NULL;
@@ -677,7 +707,7 @@ UpdateIcon(WMInfoPtr pWMInfo, xcb_window_t iWindow)
*/
static void
-UpdateStyle(WMInfoPtr pWMInfo, xcb_window_t iWindow)
+UpdateStyle(WMInfoPtr pWMInfo, xcb_window_t iWindow, unsigned long *maxmin)
{
HWND hWnd;
HWND zstyle = HWND_NOTOPMOST;
@@ -687,8 +717,12 @@ UpdateStyle(WMInfoPtr pWMInfo, xcb_window_t iWindow)
if (!hWnd)
return;
+ /* If window isn't override-redirect */
+ if (IsOverrideRedirect(pWMInfo->conn, iWindow))
+ return;
+
/* Determine the Window style, which determines borders and clipping region... */
- winApplyHints(pWMInfo, iWindow, hWnd, &zstyle);
+ winApplyHints(pWMInfo, iWindow, hWnd, &zstyle, maxmin);
winUpdateWindowPosition(hWnd, &zstyle);
/* Apply the updated window style, without changing it's show or activation state */
@@ -709,25 +743,155 @@ UpdateStyle(WMInfoPtr pWMInfo, xcb_window_t iWindow)
winShowWindowOnTaskbar(hWnd,
(GetWindowLongPtr(hWnd, GWL_EXSTYLE) &
WS_EX_APPWINDOW) ? TRUE : FALSE);
+
+ /* Check urgency hint */
+ winApplyUrgency(pWMInfo, iWindow, hWnd);
}
/*
* Updates the state of a HWND
- * (only minimization supported at the moment)
*/
static void
-UpdateState(WMInfoPtr pWMInfo, xcb_window_t iWindow)
+UpdateState(WMInfoPtr pWMInfo, xcb_window_t iWindow, int state)
{
HWND hWnd;
+ int current_state = -1;
- winDebug("UpdateState: iWindow 0x%08x\n", (int)iWindow);
+ winDebug("UpdateState: iWindow 0x%08x %d\n", (int)iWindow, state);
hWnd = getHwnd(pWMInfo, iWindow);
- if (!hWnd)
- return;
+ if (hWnd)
+ {
+ // Keep track of the Window state, do nothing if it's not changing
+ current_state = (intptr_t)GetProp(hWnd, WIN_STATE_PROP);
+
+ if (current_state == state)
+ return;
+
+ SetProp(hWnd, WIN_STATE_PROP, (HANDLE)(intptr_t)state);
+
+ switch (state)
+ {
+ case XCB_ICCCM_WM_STATE_ICONIC:
+ ShowWindow(hWnd, SW_SHOWMINNOACTIVE);
+ break;
+
+#define XCB_ICCCM_WM_STATE_ZOOM 2
+ case XCB_ICCCM_WM_STATE_ZOOM:
+ // There doesn't seem to be a SW_SHOWMAXNOACTIVE. Hopefully
+ // always activating a maximized window isn't so bad...
+ ShowWindow(hWnd, SW_SHOWMAXIMIZED);
+ break;
+
+ case XCB_ICCCM_WM_STATE_NORMAL:
+ ShowWindow(hWnd, SW_SHOWNOACTIVATE);
+ break;
+
+ case XCB_ICCCM_WM_STATE_WITHDRAWN:
+ ShowWindow(hWnd, SW_HIDE);
+ break;
+ }
+ }
+
+ // Update WM_STATE property
+ {
+ // ZoomState is obsolete in ICCCM, so map it to NormalState
+ int icccm_state = state;
+ int icccm_current_state = current_state;
+
+ if (icccm_state == XCB_ICCCM_WM_STATE_ZOOM)
+ icccm_state = XCB_ICCCM_WM_STATE_NORMAL;
+
+ if (icccm_current_state == XCB_ICCCM_WM_STATE_ZOOM)
+ icccm_current_state = XCB_ICCCM_WM_STATE_NORMAL;
+
+ // Don't change property unnecessarily
+ //
+ // (Note that we do not take notice of WM_STATE PropertyNotify, only
+ // WM_CHANGE_STATE ClientMessage, so this should not cause the state to
+ // change itself)
+ if (icccm_current_state != icccm_state)
+ {
+ struct
+ {
+ CARD32 state;
+ XID icon;
+ } wmstate;
+
+ wmstate.state = icccm_state;
+ wmstate.icon = None;
+
+ xcb_change_property(pWMInfo->conn, XCB_PROP_MODE_REPLACE,
+ iWindow, pWMInfo->atmWmState,
+ pWMInfo->atmWmState, 32,
+ sizeof(wmstate)/sizeof(int),
+ (unsigned char *) &wmstate);
+ }
+ }
+
+ // Update _NET_WM_STATE property
+ if (state == XCB_ICCCM_WM_STATE_WITHDRAWN) {
+ xcb_delete_property(pWMInfo->conn, iWindow, pWMInfo->ewmh._NET_WM_STATE);
+ }
+ else {
+ xcb_get_property_cookie_t cookie;
+ xcb_get_property_reply_t *reply;
+
+ cookie = xcb_get_property(pWMInfo->conn, FALSE, iWindow,
+ pWMInfo->ewmh._NET_WM_STATE,
+ XCB_ATOM_ATOM,
+ 0, INT_MAX);
+ reply = xcb_get_property_reply(pWMInfo->conn, cookie, NULL);
+ if (reply) {
+ int nitems = xcb_get_property_value_length(reply)/sizeof(xcb_atom_t);
+ xcb_atom_t *pAtom = xcb_get_property_value(reply);
+ unsigned long i, o = 0;
+ xcb_atom_t netwmstate[nitems + 2];
+ Bool changed = FALSE;
+
+ // Make a copy with _NET_WM_HIDDEN, _NET_WM_MAXIMIZED_{VERT,HORZ}
+ // removed
+ for (i = 0; i < nitems; i++) {
+ if ((pAtom[i] != pWMInfo->ewmh._NET_WM_STATE_HIDDEN) &&
+ (pAtom[i] != pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_VERT) &&
+ (pAtom[i] != pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_HORZ))
+ netwmstate[o++] = pAtom[i];
+ }
+ free(reply);
+
+ // if iconized, add _NET_WM_HIDDEN
+ if (state == XCB_ICCCM_WM_STATE_ICONIC) {
+ netwmstate[o++] = pWMInfo->ewmh._NET_WM_STATE_HIDDEN;
+ }
- ShowWindow(hWnd, SW_MINIMIZE);
+ // if maximized, add _NET_WM_MAXIMIZED_{VERT,HORZ}
+ if (state == XCB_ICCCM_WM_STATE_ZOOM) {
+ netwmstate[o++] = pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_VERT;
+ netwmstate[o++] = pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_HORZ;
+ }
+
+ // Don't change property unnecessarily
+ if (nitems != o)
+ changed = TRUE;
+ else
+ for (i = 0; i < nitems; i++)
+ {
+ if (pAtom[i] != netwmstate[i])
+ {
+ changed = TRUE;
+ break;
+ }
+ }
+
+ if (changed)
+ xcb_change_property(pWMInfo->conn, XCB_PROP_MODE_REPLACE,
+ iWindow,
+ pWMInfo->ewmh._NET_WM_STATE,
+ XCB_ATOM_ATOM, 32,
+ o, (unsigned char *) &netwmstate);
+ }
+ }
}
#if 0
@@ -781,6 +945,8 @@ winMultiWindowWMProc(void *pArg)
WMProcArgPtr pProcArg = (WMProcArgPtr) pArg;
WMInfoPtr pWMInfo = pProcArg->pWMInfo;
+ pthread_cleanup_push(&winMultiWindowThreadExit, NULL);
+
/* Initialize the Window Manager */
winInitMultiWindowWM(pWMInfo, pProcArg);
@@ -802,12 +968,69 @@ winMultiWindowWMProc(void *pArg)
}
#if CYGMULTIWINDOW_DEBUG
- ErrorF("winMultiWindowWMProc - MSG: %s (%d) ID: %d\n",
- MessageName(&(pNode->msg)), (int)pNode->msg.msg, (int)pNode->msg.dwID);
+ ErrorF("winMultiWindowWMProc - MSG: %s (%d) Window: %08x ID: %d\n",
+ MessageName(&(pNode->msg)), (int)pNode->msg.msg, pNode->msg.iWindow, (int)pNode->msg.dwID);
#endif
/* Branch on the message type */
switch (pNode->msg.msg) {
+ case WM_WM_CREATE:
+ {
+ unsigned long maxmin = 0;
+#if CYGMULTIWINDOW_DEBUG
+ ErrorF("\tWM_WM_CREATE\n");
+#endif
+
+ /* Put a note as to the HWND associated with this Window */
+ xcb_change_property(pWMInfo->conn, XCB_PROP_MODE_REPLACE,
+ pNode->msg.iWindow, pWMInfo->atmPrivMap,
+ XCB_ATOM_INTEGER, 32,
+ sizeof(HWND)/4, &(pNode->msg.hwndWindow));
+
+
+ /* Determine the Window style, which determines borders and clipping region... */
+ UpdateStyle(pWMInfo, pNode->msg.iWindow, &maxmin);
+
+ /* Make sure it gets the proper system menu for a WS_POPUP, too */
+ GetSystemMenu(pNode->msg.hwndWindow, TRUE);
+
+#define WM_INIT_SYS_MENU (WM_USER + 1001)
+ /* Cause any .XWinrc menus to be added in main WNDPROC */
+ PostMessage(pNode->msg.hwndWindow, WM_INIT_SYS_MENU, 0, 0);
+
+ /* Display the window without activating it */
+ {
+ xcb_get_window_attributes_cookie_t cookie;
+ xcb_get_window_attributes_reply_t *reply;
+
+ cookie = xcb_get_window_attributes(pWMInfo->conn, pNode->msg.iWindow);
+ reply = xcb_get_window_attributes_reply(pWMInfo->conn, cookie, NULL);
+
+ if (reply) {
+ if (reply->_class != InputOnly)
+ ShowWindow(pNode->msg.hwndWindow, SW_SHOWNA);
+ free(reply);
+ }
+ }
+
+ /* Send first paint message */
+ UpdateWindow(pNode->msg.hwndWindow);
+
+ /* Establish initial state */
+ UpdateState(pWMInfo, pNode->msg.iWindow, XCB_ICCCM_WM_STATE_NORMAL);
+
+ /*
+ It only makes sense to apply minimize/maximize override as the
+ initial state, otherwise that state can't be changed.
+ */
+ if (maxmin & HINT_MAX)
+ SendMessage(pNode->msg.hwndWindow, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
+ else if (maxmin & HINT_MIN)
+ SendMessage(pNode->msg.hwndWindow, WM_SYSCOMMAND, SC_MINIMIZE, 0);
+ }
+
+ break;
+
#if 0
case WM_WM_MOVE:
break;
@@ -838,26 +1061,16 @@ winMultiWindowWMProc(void *pArg)
}
break;
- case WM_WM_MAP2:
- /* Put a note as to the HWND associated with this Window */
- xcb_change_property(pWMInfo->conn, XCB_PROP_MODE_REPLACE,
- pNode->msg.iWindow, pWMInfo->atmPrivMap,
- XCB_ATOM_INTEGER, 32,
- sizeof(HWND)/4, &(pNode->msg.hwndWindow));
-
+ case WM_WM_MAP_UNMANAGED:
break;
- case WM_WM_MAP3:
- /* Put a note as to the HWND associated with this Window */
- xcb_change_property(pWMInfo->conn, XCB_PROP_MODE_REPLACE,
- pNode->msg.iWindow, pWMInfo->atmPrivMap,
- XCB_ATOM_INTEGER, 32,
- sizeof(HWND)/4, &(pNode->msg.hwndWindow));
+ case WM_WM_MAP_MANAGED:
+ {
+ unsigned long maxmin = 0;
UpdateName(pWMInfo, pNode->msg.iWindow);
+ UpdateStyle(pWMInfo, pNode->msg.iWindow, &maxmin);
UpdateIcon(pWMInfo, pNode->msg.iWindow);
- UpdateStyle(pWMInfo, pNode->msg.iWindow);
-
/* Reshape */
{
@@ -868,8 +1081,9 @@ winMultiWindowWMProc(void *pArg)
winUpdateRgnMultiWindow(pWin);
}
}
+ }
- break;
+ break;
case WM_WM_UNMAP:
@@ -938,16 +1152,18 @@ winMultiWindowWMProc(void *pArg)
case WM_WM_HINTS_EVENT:
{
+ unsigned long maxmin = 0;
+
/* Don't do anything if this is an override-redirect window */
if (IsOverrideRedirect(pWMInfo->conn, pNode->msg.iWindow))
break;
- UpdateStyle(pWMInfo, pNode->msg.iWindow);
+ UpdateStyle(pWMInfo, pNode->msg.iWindow, &maxmin);
}
break;
case WM_WM_CHANGE_STATE:
- UpdateState(pWMInfo, pNode->msg.iWindow);
+ UpdateState(pWMInfo, pNode->msg.iWindow, pNode->msg.dwID);
break;
default:
@@ -968,10 +1184,10 @@ winMultiWindowWMProc(void *pArg)
if (event) {
if ((event->response_type & ~0x80) == 0) {
xcb_generic_error_t *err = (xcb_generic_error_t *)event;
- ErrorF("winMultiWindowWMProc - Error code: %i, ID: 0x%08x, "
- "Major opcode: %i, Minor opcode: %i\n",
- err->error_code, err->resource_id,
- err->major_code, err->minor_code);
+ winDebug("winMultiWindowWMProc - Error code: %i, ID: 0x%08x, "
+ "Major opcode: %i, Minor opcode: %i\n",
+ err->error_code, err->resource_id,
+ err->major_code, err->minor_code);
}
}
}
@@ -981,6 +1197,7 @@ winMultiWindowWMProc(void *pArg)
int e = xcb_connection_has_error(pWMInfo->conn);
if (e) {
ErrorF("winMultiWindowWMProc - Fatal error %d on xcb connection\n", e);
+ pthread_exit(NULL);
break;
}
}
@@ -998,6 +1215,9 @@ winMultiWindowWMProc(void *pArg)
#if CYGMULTIWINDOW_DEBUG
ErrorF("-winMultiWindowWMProc ()\n");
#endif
+
+ pthread_cleanup_pop(0);
+
return NULL;
}
@@ -1036,6 +1256,10 @@ winMultiWindowXMsgProc(void *pArg)
xcb_atom_t atmWindowState, atmMotifWmHints, atmWindowType, atmNormalHints;
int iReturn;
xcb_auth_info_t *auth_info;
+ xcb_screen_t *root_screen;
+ xcb_window_t root_window_id;
+
+ pthread_cleanup_push(&winMultiWindowThreadExit, NULL);
winDebug("winMultiWindowXMsgProc - Hello\n");
@@ -1108,11 +1332,11 @@ winMultiWindowXMsgProc(void *pArg)
pthread_exit(NULL);
}
- {
- /* Get root window id */
- xcb_screen_t *root_screen = xcb_aux_get_screen(pProcArg->conn, pProcArg->dwScreen);
- xcb_window_t root_window_id = root_screen->root;
+ /* Get root window id */
+ root_screen = xcb_aux_get_screen(pProcArg->conn, pProcArg->dwScreen);
+ root_window_id = root_screen->root;
+ {
/* Set WM_ICON_SIZE property indicating desired icon sizes */
typedef struct {
uint32_t min_width, min_height;
@@ -1141,14 +1365,39 @@ winMultiWindowXMsgProc(void *pArg)
atmNormalHints = intern_atom(pProcArg->conn, "WM_NORMAL_HINTS");
/*
- iiimxcf had a bug until 2009-04-27, assuming that the
- WM_STATE atom exists, causing clients to fail with
- a BadAtom X error if it doesn't.
-
- Since this is on in the default Solaris 10 install,
- workaround this by making sure it does exist...
+ Enable Composite extension and redirect subwindows of the root window
*/
- intern_atom(pProcArg->conn, "WM_STATE");
+ if (pProcArg->pWMInfo->fCompositeWM) {
+ const char *extension_name = "Composite";
+ xcb_query_extension_cookie_t cookie;
+ xcb_query_extension_reply_t *reply;
+
+ cookie = xcb_query_extension(pProcArg->conn, strlen(extension_name), extension_name);
+ reply = xcb_query_extension_reply(pProcArg->conn, cookie, NULL);
+
+ if (reply && (reply->present)) {
+ xcb_composite_redirect_subwindows(pProcArg->conn,
+ root_window_id,
+ XCB_COMPOSITE_REDIRECT_AUTOMATIC);
+
+ /*
+ We use automatic updating of the root window for two
+ reasons:
+
+ 1) redirected window contents are mirrored to the root
+ window so that the root window draws correctly when shown.
+
+ 2) updating the root window causes damage against the
+ shadow framebuffer, which ultimately causes WM_PAINT to be
+ sent to the affected window(s) to cause the damage regions
+ to be redrawn.
+ */
+
+ ErrorF("Using Composite redirection\n");
+
+ free(reply);
+ }
+ }
/* Loop until we explicitly break out */
while (1) {
@@ -1164,6 +1413,7 @@ winMultiWindowXMsgProc(void *pArg)
if (!event) { // returns NULL on I/O error
int e = xcb_connection_has_error(pProcArg->conn);
ErrorF("winMultiWindowXMsgProc - Fatal error %d on xcb connection\n", e);
+ pthread_exit(NULL);
break;
}
@@ -1175,10 +1425,10 @@ winMultiWindowXMsgProc(void *pArg)
/* Branch on event type */
if (type == 0) {
xcb_generic_error_t *err = (xcb_generic_error_t *)event;
- ErrorF("winMultiWindowXMsgProc - Error code: %i, ID: 0x%08x, "
- "Major opcode: %i, Minor opcode: %i\n",
- err->error_code, err->resource_id,
- err->major_code, err->minor_code);
+ winDebug("winMultiWindowXMsgProc - Error code: %i, ID: 0x%08x, "
+ "Major opcode: %i, Minor opcode: %i\n",
+ err->error_code, err->resource_id,
+ err->major_code, err->minor_code);
}
else if (type == XCB_CREATE_NOTIFY) {
xcb_create_notify_event_t *notify = (xcb_create_notify_event_t *)event;
@@ -1247,6 +1497,16 @@ winMultiWindowXMsgProc(void *pArg)
}
}
}
+ else if (type == XCB_UNMAP_NOTIFY) {
+ xcb_unmap_notify_event_t *notify = (xcb_unmap_notify_event_t *)event;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.msg = WM_WM_CHANGE_STATE;
+ msg.iWindow = notify->window;
+ msg.dwID = XCB_ICCCM_WM_STATE_WITHDRAWN;
+
+ winSendMessageToWM(pProcArg->pWMInfo, &msg);
+ }
else if (type == XCB_CONFIGURE_NOTIFY) {
if (!send_event) {
/*
@@ -1273,6 +1533,15 @@ winMultiWindowXMsgProc(void *pArg)
else if (type == XCB_PROPERTY_NOTIFY) {
xcb_property_notify_event_t *notify = (xcb_property_notify_event_t *)event;
+ xcb_get_atom_name_cookie_t cookie = xcb_get_atom_name(pProcArg->conn, notify->atom);
+ xcb_get_atom_name_reply_t *reply = xcb_get_atom_name_reply(pProcArg->conn, cookie, NULL);
+ if (reply) {
+ winDebug("winMultiWindowXMsgProc: PropertyNotify %.*s\n",
+ xcb_get_atom_name_name_length(reply),
+ xcb_get_atom_name_name(reply));
+ free(reply);
+ }
+
if ((notify->atom == atmWmName) ||
(notify->atom == atmNetWmName)) {
memset(&msg, 0, sizeof(msg));
@@ -1315,18 +1584,60 @@ winMultiWindowXMsgProc(void *pArg)
}
else if (type == XCB_CLIENT_MESSAGE) {
xcb_client_message_event_t *client_msg = (xcb_client_message_event_t *)event;
+ winDebug("winMultiWindowXMsgProc: ClientMessage: type %d window 0x%08x data[0] %d\n", client_msg->type, client_msg->window, client_msg->data.data32[0]);
if (client_msg->type == atmWmChange
&& client_msg->data.data32[0] == XCB_ICCCM_WM_STATE_ICONIC) {
ErrorF("winMultiWindowXMsgProc - WM_CHANGE_STATE - IconicState\n");
memset(&msg, 0, sizeof(msg));
-
msg.msg = WM_WM_CHANGE_STATE;
msg.iWindow = client_msg->window;
+ msg.dwID = client_msg->data.data32[0];
winSendMessageToWM(pProcArg->pWMInfo, &msg);
}
+ else if (client_msg->type == pProcArg->pWMInfo->ewmh._NET_WM_STATE) {
+ int action = client_msg->data.data32[0];
+ int state = -1;
+
+ if (action == XCB_EWMH_WM_STATE_ADD) {
+ if ((client_msg->data.data32[1] == pProcArg->pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_VERT) &&
+ (client_msg->data.data32[2] == pProcArg->pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_HORZ))
+ state = XCB_ICCCM_WM_STATE_ZOOM;
+
+ if ((client_msg->data.data32[1] == pProcArg->pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_HORZ) &&
+ (client_msg->data.data32[2] == pProcArg->pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_VERT))
+ state = XCB_ICCCM_WM_STATE_ZOOM;
+
+ if (client_msg->data.data32[1] == pProcArg->pWMInfo->ewmh._NET_WM_STATE_HIDDEN)
+ state = XCB_ICCCM_WM_STATE_ICONIC;
+ }
+ else if (action == XCB_EWMH_WM_STATE_REMOVE) {
+ if ((client_msg->data.data32[1] == pProcArg->pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_VERT) &&
+ (client_msg->data.data32[2] == pProcArg->pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_HORZ))
+ state = XCB_ICCCM_WM_STATE_NORMAL;
+
+ if ((client_msg->data.data32[1] == pProcArg->pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_HORZ) &&
+ (client_msg->data.data32[2] == pProcArg->pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_VERT))
+ state = XCB_ICCCM_WM_STATE_NORMAL;
+
+ if (client_msg->data.data32[1] == pProcArg->pWMInfo->ewmh._NET_WM_STATE_HIDDEN)
+ state = XCB_ICCCM_WM_STATE_NORMAL;
+ }
+ else {
+ ErrorF("winMultiWindowXMsgProc: ClientMEssage _NET_WM_STATE unsupported action %d\n", action);
+ }
+
+ if (state != -1) {
+ memset(&msg, 0, sizeof(msg));
+ msg.msg = WM_WM_CHANGE_STATE;
+ msg.iWindow = client_msg->window;
+ msg.dwID = state;
+
+ winSendMessageToWM(pProcArg->pWMInfo, &msg);
+ }
+ }
}
/* Free the event */
@@ -1334,7 +1645,7 @@ winMultiWindowXMsgProc(void *pArg)
}
xcb_disconnect(pProcArg->conn);
- pthread_exit(NULL);
+ pthread_cleanup_pop(0);
return NULL;
}
@@ -1349,7 +1660,7 @@ winInitWM(void **ppWMInfo,
pthread_t * ptWMProc,
pthread_t * ptXMsgProc,
pthread_mutex_t * ppmServerStarted,
- int dwScreen, HWND hwndScreen)
+ int dwScreen, HWND hwndScreen, Bool compositeWM)
{
WMProcArgPtr pArg = malloc(sizeof(WMProcArgRec));
WMInfoPtr pWMInfo = malloc(sizeof(WMInfoRec));
@@ -1371,6 +1682,7 @@ winInitWM(void **ppWMInfo,
/* Set a return pointer to the Window Manager info structure */
*ppWMInfo = pWMInfo;
+ pWMInfo->fCompositeWM = compositeWM;
/* Setup the argument structure for the thread function */
pArg->dwScreen = dwScreen;
@@ -1419,6 +1731,8 @@ winInitMultiWindowWM(WMInfoPtr pWMInfo, WMProcArgPtr pProcArg)
char pszDisplay[512];
int iReturn;
xcb_auth_info_t *auth_info;
+ xcb_screen_t *root_screen;
+ xcb_window_t root_window_id;
winDebug("winInitMultiWindowWM - Hello\n");
@@ -1488,6 +1802,10 @@ winInitMultiWindowWM(WMInfoPtr pWMInfo, WMProcArgPtr pProcArg)
pWMInfo->atmPrivMap = intern_atom(pWMInfo->conn, WINDOWSWM_NATIVE_HWND);
pWMInfo->atmUtf8String = intern_atom(pWMInfo->conn, "UTF8_STRING");
pWMInfo->atmNetWmName = intern_atom(pWMInfo->conn, "_NET_WM_NAME");
+ pWMInfo->atmCurrentDesktop = intern_atom(pWMInfo->conn, "_NET_CURRENT_DESKTOP");
+ pWMInfo->atmNumberDesktops = intern_atom(pWMInfo->conn, "_NET_NUMBER_OF_DESKTOPS");
+ pWMInfo->atmDesktopNames = intern_atom(pWMInfo->conn, "__NET_DESKTOP_NAMES");
+ pWMInfo->atmWmState = intern_atom(pWMInfo->conn, "WM_STATE");
/* Initialization for the xcb_ewmh and EWMH atoms */
{
@@ -1512,6 +1830,8 @@ winInitMultiWindowWM(WMInfoPtr pWMInfo, WMProcArgPtr pProcArg)
pWMInfo->ewmh._NET_WM_STATE_ABOVE,
pWMInfo->ewmh._NET_WM_STATE_BELOW,
pWMInfo->ewmh._NET_WM_STATE_SKIP_TASKBAR,
+ pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_VERT,
+ pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_HORZ,
};
xcb_ewmh_set_supported(&pWMInfo->ewmh, pProcArg->dwScreen,
@@ -1522,6 +1842,32 @@ winInitMultiWindowWM(WMInfoPtr pWMInfo, WMProcArgPtr pProcArg)
}
}
+ /* Get root window id */
+ root_screen = xcb_aux_get_screen(pWMInfo->conn, pProcArg->dwScreen);
+ root_window_id = root_screen->root;
+
+ /*
+ Set root window properties for describing multiple desktops to describe
+ the one desktop we have
+ */
+ {
+ int data;
+ const char buf[] = "Desktop";
+
+ data = 0;
+ xcb_change_property(pWMInfo->conn, XCB_PROP_MODE_REPLACE, root_window_id,
+ pWMInfo->atmCurrentDesktop, XCB_ATOM_CARDINAL, 32,
+ 1, &data);
+ data = 1;
+ xcb_change_property(pWMInfo->conn, XCB_PROP_MODE_REPLACE, root_window_id,
+ pWMInfo->atmNumberDesktops, XCB_ATOM_CARDINAL, 32,
+ 1, &data);
+
+ xcb_change_property(pWMInfo->conn, XCB_PROP_MODE_REPLACE, root_window_id,
+ pWMInfo->atmDesktopNames, pWMInfo->atmUtf8String, 8,
+ strlen(buf), (unsigned char *) buf);
+ }
+
/*
Set the root window cursor to left_ptr (this controls the cursor an
application gets over it's windows when it doesn't set one)
@@ -1535,9 +1881,6 @@ winInitMultiWindowWM(WMInfoPtr pWMInfo, WMProcArgPtr pProcArg)
uint32_t mask = XCB_CW_CURSOR;
uint32_t value_list = cursor;
- xcb_screen_t *root_screen = xcb_aux_get_screen(pWMInfo->conn, pProcArg->dwScreen);
- xcb_window_t window = root_screen->root;
-
static const uint16_t fgred = 0, fggreen = 0, fgblue = 0;
static const uint16_t bgred = 0xFFFF, bggreen = 0xFFFF, bgblue = 0xFFFF;
@@ -1547,7 +1890,7 @@ winInitMultiWindowWM(WMInfoPtr pWMInfo, WMProcArgPtr pProcArg)
shape, shape + 1,
fgred, fggreen, fgblue, bgred, bggreen, bgblue);
- xcb_change_window_attributes(pWMInfo->conn, window, mask, &value_list);
+ xcb_change_window_attributes(pWMInfo->conn, root_window_id, mask, &value_list);
xcb_free_cursor(pWMInfo->conn, cursor);
xcb_close_font(pWMInfo->conn, font);
@@ -1564,7 +1907,7 @@ winSendMessageToWM(void *pWMInfo, winWMMessagePtr pMsg)
WMMsgNodePtr pNode;
#if CYGMULTIWINDOW_DEBUG
- ErrorF("winSendMessageToWM %s\n", MessageName(pMsg));
+ ErrorF("winSendMessageToWM %s %08x %d\n", MessageName(pMsg), pMsg->iWindow, pMsg->dwID);
#endif
pNode = malloc(sizeof(WMMsgNodeRec));
@@ -1575,6 +1918,17 @@ winSendMessageToWM(void *pWMInfo, winWMMessagePtr pMsg)
}
/*
+ * winMultiWindowThreadExit - Thread exit handler
+ */
+
+static void
+winMultiWindowThreadExit(void *arg)
+{
+ /* multiwindow client thread has exited, stop server as well */
+ raise(SIGTERM);
+}
+
+/*
* Check if another window manager is running
*/
@@ -1633,6 +1987,40 @@ winDeinitMultiWindowWM(void)
g_shutdown = TRUE;
}
+static void
+winApplyUrgency(WMInfoPtr pWMInfo, xcb_window_t iWindow, HWND hWnd)
+{
+ xcb_get_property_cookie_t cookie;
+ xcb_icccm_wm_hints_t hints;
+
+ cookie = xcb_icccm_get_wm_hints(pWMInfo->conn, iWindow);
+ if (xcb_icccm_get_wm_hints_reply(pWMInfo->conn, cookie, &hints, NULL)) {
+ FLASHWINFO fwi;
+
+ fwi.cbSize = sizeof(FLASHWINFO);
+ fwi.hwnd = hWnd;
+
+ winDebug("winApplyUrgency: window 0x%08x has urgency hint %s\n", iWindow,
+ (hints.flags & XCB_ICCCM_WM_HINT_X_URGENCY) ? "on" : "off");
+
+ if (hints.flags & XCB_ICCCM_WM_HINT_X_URGENCY) {
+ DWORD count = 3;
+
+ SystemParametersInfo(SPI_GETFOREGROUNDFLASHCOUNT, 0, &count, 0);
+ fwi.dwFlags = FLASHW_TRAY;
+ fwi.uCount = count;
+ fwi.dwTimeout = 0;
+ }
+ else {
+ fwi.dwFlags = FLASHW_STOP;
+ fwi.uCount = 0;
+ fwi.dwTimeout = 0;
+ }
+
+ FlashWindowEx(&fwi);
+ }
+}
+
/* Windows window styles */
#define HINT_NOFRAME (1L<<0)
#define HINT_BORDER (1L<<1)
@@ -1642,12 +2030,9 @@ winDeinitMultiWindowWM(void)
#define HINT_NOMINIMIZE (1L<<5)
#define HINT_NOSYSMENU (1L<<6)
#define HINT_SKIPTASKBAR (1L<<7)
-/* These two are used on their own */
-#define HINT_MAX (1L<<0)
-#define HINT_MIN (1L<<1)
static void
-winApplyHints(WMInfoPtr pWMInfo, xcb_window_t iWindow, HWND hWnd, HWND * zstyle)
+winApplyHints(WMInfoPtr pWMInfo, xcb_window_t iWindow, HWND hWnd, HWND * zstyle, unsigned long *maxmin)
{
xcb_connection_t *conn = pWMInfo->conn;
@@ -1657,9 +2042,11 @@ winApplyHints(WMInfoPtr pWMInfo, xcb_window_t iWindow, HWND hWnd, HWND * zstyle)
static xcb_atom_t splashType;
static int generation;
- unsigned long hint = 0, maxmin = 0;
+ unsigned long hint = HINT_BORDER | HINT_SIZEBOX | HINT_CAPTION;
unsigned long style, exStyle;
+ *maxmin = 0;
+
if (!hWnd)
return;
if (!IsWindow(hWnd))
@@ -1684,20 +2071,29 @@ winApplyHints(WMInfoPtr pWMInfo, xcb_window_t iWindow, HWND hWnd, HWND * zstyle)
int i;
int nitems = xcb_get_property_value_length(reply)/sizeof(xcb_atom_t);
xcb_atom_t *pAtom = xcb_get_property_value(reply);
+ Bool verMax = FALSE;
+ Bool horMax = FALSE;
for (i = 0; i < nitems; i++) {
if (pAtom[i] == skiptaskbarState)
hint |= HINT_SKIPTASKBAR;
if (pAtom[i] == hiddenState)
- maxmin |= HINT_MIN;
+ *maxmin |= HINT_MIN;
else if (pAtom[i] == fullscreenState)
- maxmin |= HINT_MAX;
+ *maxmin |= HINT_MAX;
if (pAtom[i] == belowState)
*zstyle = HWND_BOTTOM;
else if (pAtom[i] == aboveState)
*zstyle = HWND_TOPMOST;
+ if (pAtom[i] == pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_VERT)
+ verMax = TRUE;
+ if (pAtom[i] == pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_HORZ)
+ horMax = TRUE;
}
+ if (verMax && horMax)
+ *maxmin |= HINT_MAX;
+
free(reply);
}
}
@@ -1710,15 +2106,17 @@ winApplyHints(WMInfoPtr pWMInfo, xcb_window_t iWindow, HWND hWnd, HWND * zstyle)
MwmHints *mwm_hint = xcb_get_property_value(reply);
if (mwm_hint && (nitems >= PropMwmHintsElements) &&
(mwm_hint->flags & MwmHintsDecorations)) {
- if (!mwm_hint->decorations)
+ if (!mwm_hint->decorations) {
+ hint &= ~(HINT_BORDER | HINT_SIZEBOX | HINT_CAPTION);
hint |= (HINT_NOFRAME | HINT_NOSYSMENU | HINT_NOMINIMIZE | HINT_NOMAXIMIZE);
+ }
else if (!(mwm_hint->decorations & MwmDecorAll)) {
- if (mwm_hint->decorations & MwmDecorBorder)
- hint |= HINT_BORDER;
- if (mwm_hint->decorations & MwmDecorHandle)
- hint |= HINT_SIZEBOX;
- if (mwm_hint->decorations & MwmDecorTitle)
- hint |= HINT_CAPTION;
+ if (!(mwm_hint->decorations & MwmDecorBorder))
+ hint &= ~HINT_BORDER;
+ if (!(mwm_hint->decorations & MwmDecorHandle))
+ hint &= ~HINT_SIZEBOX;
+ if (!(mwm_hint->decorations & MwmDecorTitle))
+ hint &= ~HINT_CAPTION;
if (!(mwm_hint->decorations & MwmDecorMenu))
hint |= HINT_NOSYSMENU;
if (!(mwm_hint->decorations & MwmDecorMinimize))
@@ -1744,11 +2142,13 @@ winApplyHints(WMInfoPtr pWMInfo, xcb_window_t iWindow, HWND hWnd, HWND * zstyle)
if (xcb_ewmh_get_wm_window_type_reply(&pWMInfo->ewmh, cookie, &type, NULL)) {
for (i = 0; i < type.atoms_len; i++) {
if (type.atoms[i] == pWMInfo->ewmh._NET_WM_WINDOW_TYPE_DOCK) {
- hint = (hint & ~HINT_NOFRAME) | HINT_SKIPTASKBAR | HINT_SIZEBOX;
+ hint &= ~(HINT_BORDER | HINT_SIZEBOX | HINT_CAPTION | HINT_NOFRAME);
+ hint |= (HINT_SKIPTASKBAR | HINT_SIZEBOX);
*zstyle = HWND_TOPMOST;
}
else if ((type.atoms[i] == pWMInfo->ewmh._NET_WM_WINDOW_TYPE_SPLASH)
|| (type.atoms[i] == splashType)) {
+ hint &= ~(HINT_BORDER | HINT_SIZEBOX | HINT_CAPTION);
hint |= (HINT_SKIPTASKBAR | HINT_NOSYSMENU | HINT_NOMINIMIZE | HINT_NOMAXIMIZE);
*zstyle = HWND_TOPMOST;
}
@@ -1762,22 +2162,31 @@ winApplyHints(WMInfoPtr pWMInfo, xcb_window_t iWindow, HWND hWnd, HWND * zstyle)
cookie = xcb_icccm_get_wm_normal_hints(conn, iWindow);
if (xcb_icccm_get_wm_normal_hints_reply(conn, cookie, &size_hints, NULL)) {
- if (size_hints.flags & XCB_ICCCM_SIZE_HINT_P_MAX_SIZE) {
+ /* Notwithstanding MwmDecorHandle, if we have a border, and
+ WM_NORMAL_HINTS indicates the window should be resizeable, let
+ the window have a resizing border. This is necessary for windows
+ with gtk3+ 3.14 csd. */
+ if (hint & HINT_BORDER)
+ hint |= HINT_SIZEBOX;
+ if (size_hints.flags & XCB_ICCCM_SIZE_HINT_P_MAX_SIZE) {
/* Not maximizable if a maximum size is specified, and that size
is smaller (in either dimension) than the screen size */
if ((size_hints.max_width < GetSystemMetrics(SM_CXVIRTUALSCREEN))
|| (size_hints.max_height < GetSystemMetrics(SM_CYVIRTUALSCREEN)))
hint |= HINT_NOMAXIMIZE;
+
if (size_hints.flags & XCB_ICCCM_SIZE_HINT_P_MIN_SIZE) {
/*
If both minimum size and maximum size are specified and are the same,
don't bother with a resizing frame
*/
if ((size_hints.min_width == size_hints.max_width)
- && (size_hints.min_height == size_hints.max_height))
+ && (size_hints.min_height == size_hints.max_height)) {
+ hint |= HINT_NOMAXIMIZE;
hint = (hint & ~HINT_SIZEBOX);
+ }
}
}
}
@@ -1819,17 +2228,12 @@ winApplyHints(WMInfoPtr pWMInfo, xcb_window_t iWindow, HWND hWnd, HWND * zstyle)
if (style & STYLE_TOPMOST)
*zstyle = HWND_TOPMOST;
else if (style & STYLE_MAXIMIZE)
- maxmin = (hint & ~HINT_MIN) | HINT_MAX;
+ *maxmin = (hint & ~HINT_MIN) | HINT_MAX;
else if (style & STYLE_MINIMIZE)
- maxmin = (hint & ~HINT_MAX) | HINT_MIN;
+ *maxmin = (hint & ~HINT_MAX) | HINT_MIN;
else if (style & STYLE_BOTTOM)
*zstyle = HWND_BOTTOM;
- if (maxmin & HINT_MAX)
- SendMessage(hWnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
- else if (maxmin & HINT_MIN)
- SendMessage(hWnd, WM_SYSCOMMAND, SC_MINIMIZE, 0);
-
if (style & STYLE_NOTITLE)
hint =
(hint & ~HINT_NOFRAME & ~HINT_BORDER & ~HINT_CAPTION) |
@@ -1843,6 +2247,9 @@ winApplyHints(WMInfoPtr pWMInfo, xcb_window_t iWindow, HWND hWnd, HWND * zstyle)
(hint & ~HINT_BORDER & ~HINT_CAPTION & ~HINT_SIZEBOX) |
HINT_NOFRAME;
+ if (style & STYLE_SKIPTASKBAR)
+ hint |= HINT_SKIPTASKBAR;
+
/* Now apply styles to window */
style = GetWindowLongPtr(hWnd, GWL_STYLE);
if (!style)
@@ -1850,6 +2257,11 @@ winApplyHints(WMInfoPtr pWMInfo, xcb_window_t iWindow, HWND hWnd, HWND * zstyle)
style &= ~WS_CAPTION & ~WS_SIZEBOX; /* Just in case */
+ if (GetParent(hWnd))
+ style |= WS_SYSMENU;
+ else
+ style |= WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX;
+
if (!(hint & ~HINT_SKIPTASKBAR)) /* No hints, default */
style = style | WS_CAPTION | WS_SIZEBOX;
else if (hint & HINT_NOFRAME) /* No frame, no decorations */
@@ -1884,57 +2296,3 @@ winApplyHints(WMInfoPtr pWMInfo, xcb_window_t iWindow, HWND hWnd, HWND * zstyle)
("winApplyHints: iWindow 0x%08x hints 0x%08x style 0x%08x exstyle 0x%08x\n",
iWindow, hint, style, exStyle);
}
-
-void
-winUpdateWindowPosition(HWND hWnd, HWND * zstyle)
-{
- int iX, iY, iWidth, iHeight;
- int iDx, iDy;
- RECT rcNew;
- WindowPtr pWin = GetProp(hWnd, WIN_WINDOW_PROP);
- DrawablePtr pDraw = NULL;
-
- if (!pWin)
- return;
- pDraw = &pWin->drawable;
- if (!pDraw)
- return;
-
- /* Get the X and Y location of the X window */
- iX = pWin->drawable.x + GetSystemMetrics(SM_XVIRTUALSCREEN);
- iY = pWin->drawable.y + GetSystemMetrics(SM_YVIRTUALSCREEN);
-
- /* Get the height and width of the X window */
- iWidth = pWin->drawable.width;
- iHeight = pWin->drawable.height;
-
- /* Setup a rectangle with the X window position and size */
- SetRect(&rcNew, iX, iY, iX + iWidth, iY + iHeight);
-
- winDebug("winUpdateWindowPosition - drawable extent (%d, %d)-(%d, %d)\n",
- rcNew.left, rcNew.top, rcNew.right, rcNew.bottom);
-
- AdjustWindowRectEx(&rcNew, GetWindowLongPtr(hWnd, GWL_STYLE), FALSE,
- GetWindowLongPtr(hWnd, GWL_EXSTYLE));
-
- /* Don't allow window decoration to disappear off to top-left as a result of this adjustment */
- if (rcNew.left < GetSystemMetrics(SM_XVIRTUALSCREEN)) {
- iDx = GetSystemMetrics(SM_XVIRTUALSCREEN) - rcNew.left;
- rcNew.left += iDx;
- rcNew.right += iDx;
- }
-
- if (rcNew.top < GetSystemMetrics(SM_YVIRTUALSCREEN)) {
- iDy = GetSystemMetrics(SM_YVIRTUALSCREEN) - rcNew.top;
- rcNew.top += iDy;
- rcNew.bottom += iDy;
- }
-
- winDebug("winUpdateWindowPosition - Window extent (%d, %d)-(%d, %d)\n",
- rcNew.left, rcNew.top, rcNew.right, rcNew.bottom);
-
- /* Position the Windows window */
- SetWindowPos(hWnd, *zstyle, rcNew.left, rcNew.top,
- rcNew.right - rcNew.left, rcNew.bottom - rcNew.top, 0);
-
-}