Xming: Apply window style hints in -multiwindow mode

Remove frames from 'dock' windows and make them topmost in -multiwindow mode.
Remove frames from windows with MOTIF_WM_HINTS of no decorations in -multiwindow mode.
Apply some _NET_WM_STATE hints in -multiwindow mode.
Apply window styles overrides from .rc file
Correctly update region of shaped windows when applying styles

Copyright (C) Colin Harrison 2005-2009
http://www.straightrunning.com/XmingNotes/
http://sourceforge.net/projects/xming/
This commit is contained in:
Colin Harrison 2009-06-29 22:55:52 +01:00 committed by Jon TURNEY
parent 17e67c407d
commit a49ae50370
3 changed files with 266 additions and 68 deletions

View File

@ -1,5 +1,6 @@
/*
*Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
*Copyright (C) Colin Harrison 2005-2009
*
*Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -26,6 +27,7 @@
*from the XFree86 Project.
*
* Authors: Kensuke Matsuzaki
* Colin Harrison
*/
/* X headers */
@ -56,6 +58,11 @@
#include "objbase.h"
#include "ddraw.h"
#include "winwindow.h"
#include "winprefs.h"
#include "window.h"
#include "pixmapstr.h"
#include "windowstr.h"
#ifdef XWIN_MULTIWINDOWEXTWM
#include <X11/extensions/windowswmstr.h>
#else
@ -65,6 +72,8 @@
#endif
extern void winDebug(const char *format, ...);
extern void winReshapeMultiWindow(WindowPtr pWin);
extern void winUpdateRgnMultiWindow(WindowPtr pWin);
#ifndef CYGDEBUG
#define CYGDEBUG NO
@ -186,6 +195,11 @@ PreserveWin32Stack(WMInfoPtr pWMInfo, Window iWindow, UINT direction);
static Bool
CheckAnotherWindowManager (Display *pDisplay, DWORD dwScreen);
static void
winApplyHints (Display *pDisplay, Window iWindow, HWND hWnd, HWND *zstyle);
void
winUpdateWindowPosition (HWND hWnd, Bool reshape, HWND *zstyle);
/*
* Local globals
@ -240,6 +254,12 @@ PushMessage (WMMsgQueuePtr pQueue, WMMsgNodePtr pNode)
case WM_WM_MAP:
ErrorF ("\tWM_WM_MAP\n");
break;
case WM_WM_MAP2:
ErrorF ("\tWM_WM_MAP2\n");
break;
case WM_WM_MAP3:
ErrorF ("\tWM_WM_MAP3\n");
break;
case WM_WM_UNMAP:
ErrorF ("\tWM_WM_UNMAP\n");
break;
@ -700,10 +720,42 @@ winMultiWindowWMProc (void *pArg)
1);
UpdateName (pWMInfo, pNode->msg.iWindow);
winUpdateIcon (pNode->msg.iWindow);
#if 0
/* Handles the case where there are AOT windows above it in W32 */
PreserveWin32Stack (pWMInfo, pNode->msg.iWindow, GW_HWNDPREV);
break;
case WM_WM_MAP2:
#if CYGMULTIWINDOW_DEBUG
ErrorF ("\tWM_WM_MAP2\n");
#endif
XChangeProperty (pWMInfo->pDisplay,
pNode->msg.iWindow,
pWMInfo->atmPrivMap,
XA_INTEGER,//pWMInfo->atmPrivMap,
32,
PropModeReplace,
(unsigned char *) &(pNode->msg.hwndWindow),
1);
break;
case WM_WM_MAP3:
#if CYGMULTIWINDOW_DEBUG
ErrorF ("\tWM_WM_MAP3\n");
#endif
/* Put a note as to the HWND associated with this Window */
XChangeProperty (pWMInfo->pDisplay,
pNode->msg.iWindow,
pWMInfo->atmPrivMap,
XA_INTEGER,//pWMInfo->atmPrivMap,
32,
PropModeReplace,
(unsigned char *) &(pNode->msg.hwndWindow),
1);
UpdateName (pWMInfo, pNode->msg.iWindow);
winUpdateIcon (pNode->msg.iWindow);
{
HWND zstyle = HWND_NOTOPMOST;
winApplyHints (pWMInfo->pDisplay, pNode->msg.iWindow, pNode->msg.hwndWindow, &zstyle);
winUpdateWindowPosition (pNode->msg.hwndWindow, TRUE, &zstyle);
}
break;
case WM_WM_UNMAP:
@ -1435,3 +1487,168 @@ winDeinitMultiWindowWM (void)
ErrorF ("winDeinitMultiWindowWM - Noting shutdown in progress\n");
g_shutdown = TRUE;
}
/* Windows window styles */
#define HINT_NOFRAME (1l<<0)
#define HINT_BORDER (1L<<1)
#define HINT_SIZEBOX (1l<<2)
#define HINT_CAPTION (1l<<3)
/* These two are used on their own */
#define HINT_MAX (1L<<0)
#define HINT_MIN (1L<<1)
static void
winApplyHints (Display *pDisplay, Window iWindow, HWND hWnd, HWND *zstyle)
{
static Atom windowState, motif_wm_hints, windowType;
static Atom hiddenState, fullscreenState, belowState, aboveState;
static Atom dockWindow;
static int generation;
Atom type, *pAtom = NULL;
int format;
unsigned long hint = 0, maxmin = 0, style, nitems = 0 , left = 0;
WindowPtr pWin = GetProp (hWnd, WIN_WINDOW_PROP);
if (!hWnd) return;
if (!IsWindow (hWnd)) return;
if (generation != serverGeneration) {
generation = serverGeneration;
windowState = XInternAtom(pDisplay, "_NET_WM_STATE", False);
motif_wm_hints = XInternAtom(pDisplay, "_MOTIF_WM_HINTS", False);
windowType = XInternAtom(pDisplay, "_NET_WM_WINDOW_TYPE", False);
hiddenState = XInternAtom(pDisplay, "_NET_WM_STATE_HIDDEN", False);
fullscreenState = XInternAtom(pDisplay, "_NET_WM_STATE_FULLSCREEN", False);
belowState = XInternAtom(pDisplay, "_NET_WM_STATE_BELOW", False);
aboveState = XInternAtom(pDisplay, "_NET_WM_STATE_ABOVE", False);
dockWindow = XInternAtom(pDisplay, "_NET_WM_WINDOW_TYPE_DOCK", False);
}
if (XGetWindowProperty(pDisplay, iWindow, windowState, 0L,
1L, False, XA_ATOM, &type, &format,
&nitems, &left, (unsigned char **)&pAtom) == Success)
{
if (pAtom && nitems == 1)
{
if (*pAtom == hiddenState) maxmin |= HINT_MIN;
else if (*pAtom == fullscreenState) maxmin |= HINT_MAX;
if (*pAtom == belowState) *zstyle = HWND_BOTTOM;
else if (*pAtom == aboveState) *zstyle = HWND_TOPMOST;
}
if (pAtom) XFree(pAtom);
}
nitems = left = 0;
MwmHints *mwm_hint = NULL;
if (XGetWindowProperty(pDisplay, iWindow, motif_wm_hints, 0L,
PropMwmHintsElements, False, motif_wm_hints, &type, &format,
&nitems, &left, (unsigned char **)&mwm_hint) == Success)
{
if (mwm_hint && nitems == PropMwmHintsElements && (mwm_hint->flags & MwmHintsDecorations))
{
if (!mwm_hint->decorations) hint |= HINT_NOFRAME;
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) XFree(mwm_hint);
}
nitems = left = 0;
pAtom = NULL;
if (XGetWindowProperty(pDisplay, iWindow, windowType, 0L,
1L, False, XA_ATOM, &type, &format,
&nitems, &left, (unsigned char **)&pAtom) == Success)
{
if (pAtom && nitems == 1)
{
if (*pAtom == dockWindow)
{
hint = (hint & ~HINT_NOFRAME) | HINT_SIZEBOX; /* Xming puts a sizebox on dock windows */
*zstyle = HWND_TOPMOST;
}
}
if (pAtom) XFree(pAtom);
}
/* Apply Styles, overriding hint settings from above */
style = winOverrideStyle((unsigned long)pWin);
if (style & STYLE_TOPMOST) *zstyle = HWND_TOPMOST;
else if (style & STYLE_MAXIMIZE) maxmin = (hint & ~HINT_MIN) | HINT_MAX;
else if (style & STYLE_MINIMIZE) 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) | HINT_SIZEBOX;
else if (style & STYLE_OUTLINE)
hint = (hint & ~HINT_NOFRAME & ~HINT_SIZEBOX & ~HINT_CAPTION) | HINT_BORDER;
else if (style & STYLE_NOFRAME)
hint = (hint & ~HINT_BORDER & ~HINT_CAPTION & ~HINT_SIZEBOX) | HINT_NOFRAME;
style = GetWindowLongPtr(hWnd, GWL_STYLE) & ~WS_CAPTION & ~WS_SIZEBOX; /* Just in case */
if (!style) return;
if (!hint) /* All on, but no resize of children is allowed */
style = style | WS_CAPTION | (GetParent(hWnd) ? 0 : WS_SIZEBOX);
else if (hint & HINT_NOFRAME); /* All off, so do nothing */
else style = style | ((hint & HINT_BORDER) ? WS_BORDER : 0) |
((hint & HINT_SIZEBOX) ? (GetParent(hWnd) ? 0 : WS_SIZEBOX) : 0) |
((hint & HINT_CAPTION) ? WS_CAPTION : 0);
SetWindowLongPtr (hWnd, GWL_STYLE, style);
}
void
winUpdateWindowPosition (HWND hWnd, Bool reshape, HWND *zstyle)
{
int iDx, iDy;
RECT rcNew;
WindowPtr pWin = GetProp (hWnd, WIN_WINDOW_PROP);
DrawablePtr pDraw = NULL;
if (!pWin) return;
pDraw = &pWin->drawable;
if (!pDraw) return;
/* Setup a rectangle with the X window position and size */
SetRect (&rcNew, pDraw->x, pDraw->y, pDraw->x + pDraw->width, pDraw->y + pDraw->height);
#if 0
ErrorF ("winUpdateWindowPosition - (%d, %d)-(%d, %d)\n",
rcNew.left, rcNew.top,
rcNew.right, rcNew.bottom);
#endif
AdjustWindowRectEx (&rcNew, GetWindowLongPtr (hWnd, GWL_STYLE), FALSE, WS_EX_APPWINDOW);
/* Calculate position deltas */
iDx = pDraw->x - rcNew.left;
iDy = pDraw->y - rcNew.top;
/* Calculate new rectangle */
rcNew.left += iDx;
rcNew.right += iDx;
rcNew.top += iDy;
rcNew.bottom += iDy;
#if 0
ErrorF ("winUpdateWindowPosition - (%d, %d)-(%d, %d)\n",
rcNew.left, rcNew.top,
rcNew.right, rcNew.bottom);
#endif
/* Position the Windows window */
SetWindowPos (hWnd, *zstyle, rcNew.left, rcNew.top,
rcNew.right - rcNew.left, rcNew.bottom - rcNew.top,
SWP_NOMOVE | ((reshape) ? 0 : SWP_NOREDRAW));
if (reshape)
{
winReshapeMultiWindow(pWin);
winUpdateRgnMultiWindow(pWin);
}
}

View File

@ -51,6 +51,8 @@ extern Bool g_fKeyboardHookLL;
extern Bool g_fSoftwareCursor;
extern Bool g_fButton[3];
extern void winUpdateWindowPosition (HWND hWnd, Bool reshape, HWND *zstyle);
/*
* Local globals
@ -421,6 +423,8 @@ winTopLevelWindowProc (HWND hwnd, UINT message,
SetWindowRgn (hwnd, hRgnWindow, TRUE);
DeleteObject(hRgnWindow);
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)XMING_SIGNATURE);
return 0;
case WM_INIT_SYS_MENU:
@ -865,94 +869,51 @@ winTopLevelWindowProc (HWND hwnd, UINT message,
if (!wParam)
return 0;
/* Tell X to map the window */
MapWindow (pWin, wClient(pWin));
/* */
if (!pWin->overrideRedirect)
{
DWORD dwExStyle;
DWORD dwStyle;
RECT rcNew;
int iDx, iDy;
/* Flag that this window needs to be made active when clicked */
SetProp (hwnd, WIN_NEEDMANAGE_PROP, (HANDLE) 1);
/* Get the standard and extended window style information */
dwExStyle = GetWindowLongPtr (hwnd, GWL_EXSTYLE);
dwStyle = GetWindowLongPtr (hwnd, GWL_STYLE);
/* */
if (dwExStyle != WS_EX_APPWINDOW)
if (!(GetWindowLongPtr (hwnd, GWL_EXSTYLE) & WS_EX_APPWINDOW))
{
/* Setup a rectangle with the X window position and size */
SetRect (&rcNew,
pDraw->x,
pDraw->y,
pDraw->x + pDraw->width,
pDraw->y + pDraw->height);
#if 0
ErrorF ("winTopLevelWindowProc - (%d, %d)-(%d, %d)\n",
rcNew.left, rcNew.top,
rcNew.right, rcNew.bottom);
#endif
/* */
AdjustWindowRectEx (&rcNew,
WS_POPUP | WS_SIZEBOX | WS_OVERLAPPEDWINDOW,
FALSE,
WS_EX_APPWINDOW);
/* Calculate position deltas */
iDx = pDraw->x - rcNew.left;
iDy = pDraw->y - rcNew.top;
/* Calculate new rectangle */
rcNew.left += iDx;
rcNew.right += iDx;
rcNew.top += iDy;
rcNew.bottom += iDy;
#if 0
ErrorF ("winTopLevelWindowProc - (%d, %d)-(%d, %d)\n",
rcNew.left, rcNew.top,
rcNew.right, rcNew.bottom);
#endif
HWND zstyle = HWND_NOTOPMOST;
/* Set the window extended style flags */
SetWindowLongPtr (hwnd, GWL_EXSTYLE, WS_EX_APPWINDOW);
/* Set the transient style flags */
if (GetParent(hwnd)) SetWindowLongPtr (hwnd, GWL_STYLE,
WS_POPUP | WS_OVERLAPPED | WS_SYSMENU | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
/* Set the window standard style flags */
SetWindowLongPtr (hwnd, GWL_STYLE,
WS_POPUP | WS_SIZEBOX | WS_OVERLAPPEDWINDOW);
else SetWindowLongPtr (hwnd, GWL_STYLE,
(WS_POPUP | WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS)
& ~WS_CAPTION & ~WS_SIZEBOX);
/* Position the Windows window */
SetWindowPos (hwnd, HWND_TOP,
rcNew.left, rcNew.top,
rcNew.right - rcNew.left, rcNew.bottom - rcNew.top,
SWP_NOMOVE | SWP_FRAMECHANGED
| SWP_SHOWWINDOW | SWP_NOACTIVATE);
/* Bring the Windows window to the foreground */
winUpdateWindowPosition (hwnd, FALSE, &zstyle);
SetForegroundWindow (hwnd);
}
wmMsg.msg = WM_WM_MAP3;
}
else /* It is an overridden window so make it top of Z stack */
{
#if CYGWINDOWING_DEBUG
ErrorF ("overridden window is shown\n");
#endif
SetWindowPos (hwnd, HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
HWND forHwnd = GetForegroundWindow();
if (forHwnd != NULL)
{
if (GetWindowLongPtr(forHwnd, GWLP_USERDATA) & (LONG_PTR)XMING_SIGNATURE)
{
if (GetWindowLongPtr(forHwnd, GWL_EXSTYLE) & WS_EX_TOPMOST)
SetWindowPos (hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
else
SetWindowPos (hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
}
}
wmMsg.msg = WM_WM_MAP2;
}
/* Setup the Window Manager message */
wmMsg.msg = WM_WM_MAP;
wmMsg.iWidth = pDraw->width;
wmMsg.iHeight = pDraw->height;
/* Tell our Window Manager thread to map the window */
if (fWMMsgInitialized)
winSendMessageToWM (s_pScreenPriv->pWMInfo, &wmMsg);

View File

@ -2,6 +2,7 @@
#define _WINWINDOW_H_
/*
*Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
*Copyright (C) Colin Harrison 2005-2009
*
*Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -28,6 +29,7 @@
*from the XFree86 Project.
*
* Authors: Kensuke Matsuzaki
* Colin Harrison
*/
#ifndef NO
@ -60,6 +62,8 @@
#define CYGWINDOWING_DEBUG NO
#endif
#define XMING_SIGNATURE 0x12345678L
typedef struct _winPrivScreenRec *winPrivScreenPtr;
@ -111,9 +115,25 @@ typedef struct _winWMMessageRec{
#define WM_WM_NAME_EVENT (WM_USER + 9)
#define WM_WM_HINTS_EVENT (WM_USER + 10)
#define WM_WM_CHANGE_STATE (WM_USER + 11)
#define WM_WM_MAP2 (WM_USER + 12)
#define WM_WM_MAP3 (WM_USER + 13)
#define WM_MANAGE (WM_USER + 100)
#define WM_UNMANAGE (WM_USER + 102)
#define MwmHintsDecorations (1L << 1)
#define MwmDecorAll (1l << 0)
#define MwmDecorBorder (1l << 1)
#define MwmDecorHandle (1l << 2)
#define MwmDecorTitle (1l << 3)
/* This structure only contains 3 elements... the Motif 2.0 structure
contains 5... we only need the first 3... so that is all we will define */
typedef struct MwmHints {
unsigned long flags, functions, decorations;
} MwmHints;
#define PropMwmHintsElements 3
void
winSendMessageToWM (void *pWMInfo, winWMMessagePtr msg);