xserver-multidpi/hw/xwin/winwin32rootless.c
Jon TURNEY 527cf13135 hw/xwin: Make winOverrideIcon() thread-safe for icon data access
winOverrideIcon() is called from the internal WM client thread.

Accessing server-internal data structures to get icon data or window hints is
not safe, as there is no lock to ensure we do not collide with these data
structures being updated in the server thread.

Rewrite so the internal client thread uses X client calls to obtain this data
safely

We used to also set the icon inside the server when the window was initially
created.  For simplicity, we simply send a message to the internal WM to update
the icon when the window is created (rather than writing different icon update
code which can work in the server thread for that one case...)

extwm mode used to do the icon update in the server. I'm not sure that actually
made much sense.  Let's assume the external WM client can do it instead...

v2
Make sure that WM_WM_ICON_EVENT does nothing for override-redirect windows

v3
Reinstate check that native window actually has expected properties for an X
window before trying to update it's icon; some auxiliary windows owned by the
XWin process don't, which would cause a crash

v4
Various fixes to pixmap icon conversion:
- remove left-over malloc in winScaleXimageToWindowsIcon causing a memory leak
- don't recalculate DDBitmap stride in winScaleXimageToWindowsIcon, when we already have worked it out
- properly check that XGetWindowProperty(NET_WM_ICON) returned some data
- don't try to retrieve WM_HINTS icon_mask if it isn't set
- restore accidentally dropped calculation of effBpp, stride, maskStride of output DDBitmap
- make sure imageMask is zero-initalized before we use it to mask the DDBitmap

v5
Remove a left-over unused variable

v6
Avoid XDestroyImage(NULL) crash if XGetImage failed for icon_pixmap

Signed-off-by: Jon TURNEY <jon.turney@dronecode.org.uk>
Reviewed-by: Colin Harrison <colin.harrison@virgin.net>
2012-08-03 22:47:42 +01:00

1032 lines
34 KiB
C

/*
*Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
*
*Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
*"Software"), to deal in the Software without restriction, including
*without limitation the rights to use, copy, modify, merge, publish,
*distribute, sublicense, and/or sell copies of the Software, and to
*permit persons to whom the Software is furnished to do so, subject to
*the following conditions:
*
*The above copyright notice and this permission notice shall be
*included in all copies or substantial portions of the Software.
*
*THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
*EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
*MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
*NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
*ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
*CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
*WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*Except as contained in this notice, the name of the XFree86 Project
*shall not be used in advertising or otherwise to promote the sale, use
*or other dealings in this Software without prior written authorization
*from the XFree86 Project.
*
* Authors: Kensuke Matsuzaki
* Earle F. Philhower, III
* Harold L Hunt II
*/
/*
* Look at hw/darwin/quartz/xpr/xprFrame.c and hw/darwin/quartz/cr/crFrame.c
*/
#ifdef HAVE_XWIN_CONFIG_H
#include <xwin-config.h>
#endif
#include "win.h"
#include <winuser.h>
#define _WINDOWSWM_SERVER_
#include <X11/extensions/windowswmstr.h>
#include "dixevents.h"
#include "winmultiwindowclass.h"
#include <X11/Xatom.h>
/*
* Constant defines
*/
#ifndef ULW_COLORKEY
#define ULW_COLORKEY 0x00000001
#endif
#ifndef ULW_ALPHA
#define ULW_ALPHA 0x00000002
#endif
#ifndef ULW_OPAQUE
#define ULW_OPAQUE 0x00000004
#endif
#define AC_SRC_ALPHA 0x01
/*
* Local function
*/
DEFINE_ATOM_HELPER(AtmWindowsWmNativeHwnd, WINDOWSWM_NATIVE_HWND)
static void
winMWExtWMSetNativeProperty(RootlessWindowPtr pFrame);
/*
* Global variables
*/
Bool g_fNoConfigureWindow = FALSE;
/*
* Internal function to get the DIB format that is compatible with the screen
* Fixme: Share code with winshadgdi.c
*/
static
Bool
winMWExtWMQueryDIBFormat(win32RootlessWindowPtr pRLWinPriv,
BITMAPINFOHEADER * pbmih)
{
HBITMAP hbmp;
#if CYGMULTIWINDOW_DEBUG
LPDWORD pdw = NULL;
#endif
/* Create a memory bitmap compatible with the screen */
hbmp = CreateCompatibleBitmap(pRLWinPriv->hdcScreen, 1, 1);
if (hbmp == NULL) {
ErrorF("winMWExtWMQueryDIBFormat - CreateCompatibleBitmap failed\n");
return FALSE;
}
/* Initialize our bitmap info header */
ZeroMemory(pbmih, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
pbmih->biSize = sizeof(BITMAPINFOHEADER);
/* Get the biBitCount */
if (!GetDIBits(pRLWinPriv->hdcScreen,
hbmp, 0, 1, NULL, (BITMAPINFO *) pbmih, DIB_RGB_COLORS)) {
ErrorF("winMWExtWMQueryDIBFormat - First call to GetDIBits failed\n");
DeleteObject(hbmp);
return FALSE;
}
#if CYGMULTIWINDOW_DEBUG
/* Get a pointer to bitfields */
pdw = (DWORD *) ((CARD8 *) pbmih + sizeof(BITMAPINFOHEADER));
winDebug("winMWExtWMQueryDIBFormat - First call masks: %08x %08x %08x\n",
(unsigned int) pdw[0], (unsigned int) pdw[1],
(unsigned int) pdw[2]);
#endif
/* Get optimal color table, or the optimal bitfields */
if (!GetDIBits(pRLWinPriv->hdcScreen,
hbmp, 0, 1, NULL, (BITMAPINFO *) pbmih, DIB_RGB_COLORS)) {
ErrorF("winMWExtWMQueryDIBFormat - Second call to GetDIBits "
"failed\n");
DeleteObject(hbmp);
return FALSE;
}
/* Free memory */
DeleteObject(hbmp);
return TRUE;
}
static HRGN
winMWExtWMCreateRgnFromRegion(RegionPtr pShape)
{
int nRects;
BoxPtr pRects, pEnd;
HRGN hRgn, hRgnRect;
if (pShape == NULL)
return NULL;
nRects = RegionNumRects(pShape);
pRects = RegionRects(pShape);
hRgn = CreateRectRgn(0, 0, 0, 0);
if (hRgn == NULL) {
ErrorF("winReshape - Initial CreateRectRgn (%d, %d, %d, %d) "
"failed: %d\n", 0, 0, 0, 0, (int) GetLastError());
}
/* Loop through all rectangles in the X region */
for (pEnd = pRects + nRects; pRects < pEnd; pRects++) {
/* Create a Windows region for the X rectangle */
hRgnRect = CreateRectRgn(pRects->x1,
pRects->y1, pRects->x2, pRects->y2);
if (hRgnRect == NULL) {
ErrorF("winReshape - Loop CreateRectRgn (%d, %d, %d, %d) "
"failed: %d\n",
pRects->x1,
pRects->y1, pRects->x2, pRects->y2, (int) GetLastError());
}
/* Merge the Windows region with the accumulated region */
if (CombineRgn(hRgn, hRgn, hRgnRect, RGN_OR) == ERROR) {
ErrorF("winReshape - CombineRgn () failed: %d\n",
(int) GetLastError());
}
/* Delete the temporary Windows region */
DeleteObject(hRgnRect);
}
return hRgn;
}
static void
InitWin32RootlessEngine(win32RootlessWindowPtr pRLWinPriv)
{
pRLWinPriv->hdcScreen = GetDC(pRLWinPriv->hWnd);
pRLWinPriv->hdcShadow = CreateCompatibleDC(pRLWinPriv->hdcScreen);
pRLWinPriv->hbmpShadow = NULL;
/* Allocate bitmap info header */
pRLWinPriv->pbmihShadow =
(BITMAPINFOHEADER *) malloc(sizeof(BITMAPINFOHEADER)
+ 256 * sizeof(RGBQUAD));
if (pRLWinPriv->pbmihShadow == NULL) {
ErrorF("InitWin32RootlessEngine - malloc () failed\n");
return;
}
/* Query the screen format */
winMWExtWMQueryDIBFormat(pRLWinPriv, pRLWinPriv->pbmihShadow);
}
Bool
winMWExtWMCreateFrame(RootlessWindowPtr pFrame, ScreenPtr pScreen,
int newX, int newY, RegionPtr pShape)
{
#define CLASS_NAME_LENGTH 512
Bool fResult = TRUE;
win32RootlessWindowPtr pRLWinPriv;
WNDCLASSEX wc;
char pszClass[CLASS_NAME_LENGTH], pszWindowID[12];
HICON hIcon;
HICON hIconSmall;
char *res_name, *res_class, *res_role;
static int s_iWindowID = 0;
#if CYGMULTIWINDOW_DEBUG
winDebug("winMWExtWMCreateFrame %d %d - %d %d\n",
newX, newY, pFrame->width, pFrame->height);
#endif
pRLWinPriv =
(win32RootlessWindowPtr) malloc(sizeof(win32RootlessWindowRec));
pRLWinPriv->pFrame = pFrame;
pRLWinPriv->pfb = NULL;
pRLWinPriv->hbmpShadow = NULL;
pRLWinPriv->hdcShadow = NULL;
pRLWinPriv->hdcScreen = NULL;
pRLWinPriv->pbmihShadow = NULL;
pRLWinPriv->fResized = TRUE;
pRLWinPriv->fClose = FALSE;
pRLWinPriv->fRestackingNow = FALSE;
pRLWinPriv->fDestroyed = FALSE;
pRLWinPriv->fMovingOrSizing = FALSE;
// Store the implementation private frame ID
pFrame->wid = (RootlessFrameID) pRLWinPriv;
winSelectIcons(&hIcon, &hIconSmall);
/* Set standard class name prefix so we can identify window easily */
strncpy(pszClass, WINDOW_CLASS_X, sizeof(pszClass));
if (winMultiWindowGetClassHint(pFrame->win, &res_name, &res_class)) {
strncat(pszClass, "-", 1);
strncat(pszClass, res_name, CLASS_NAME_LENGTH - strlen(pszClass));
strncat(pszClass, "-", 1);
strncat(pszClass, res_class, CLASS_NAME_LENGTH - strlen(pszClass));
/* Check if a window class is provided by the WM_WINDOW_ROLE property,
* if not use the WM_CLASS information.
* For further information see:
* http://tronche.com/gui/x/icccm/sec-5.html
*/
if (winMultiWindowGetWindowRole(pFrame->win, &res_role)) {
strcat(pszClass, "-");
strcat(pszClass, res_role);
free(res_role);
}
free(res_name);
free(res_class);
}
/* Add incrementing window ID to make unique class name */
snprintf(pszWindowID, sizeof(pszWindowID), "-%x", s_iWindowID++);
pszWindowID[sizeof(pszWindowID) - 1] = 0;
strcat(pszClass, pszWindowID);
#if CYGMULTIWINDOW_DEBUG
winDebug("winCreateWindowsWindow - Creating class: %s\n", pszClass);
#endif
/* Setup our window class */
wc.cbSize = sizeof(wc);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = winMWExtWMWindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = g_hInstance;
wc.hIcon = hIcon;
wc.hIconSm = hIconSmall;
wc.hCursor = 0;
wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = pszClass;
RegisterClassEx(&wc);
/* Create the window */
g_fNoConfigureWindow = TRUE;
pRLWinPriv->hWnd = CreateWindowExA(WS_EX_TOOLWINDOW, /* Extended styles */
pszClass, /* Class name */
WINDOW_TITLE_X, /* Window name */
WS_POPUP | WS_CLIPCHILDREN, newX, /* Horizontal position */
newY, /* Vertical position */
pFrame->width, /* Right edge */
pFrame->height, /* Bottom edge */
(HWND) NULL, /* No parent or owner window */
(HMENU) NULL, /* No menu */
GetModuleHandle(NULL), /* Instance handle */
pRLWinPriv); /* ScreenPrivates */
if (pRLWinPriv->hWnd == NULL) {
ErrorF("winMWExtWMCreateFrame - CreateWindowExA () failed: %d\n",
(int) GetLastError());
fResult = FALSE;
}
#if CYGMULTIWINDOW_DEBUG
winDebug("winMWExtWMCreateFrame - ShowWindow\n");
#endif
//ShowWindow (pRLWinPriv->hWnd, SW_SHOWNOACTIVATE);
g_fNoConfigureWindow = FALSE;
if (pShape != NULL) {
winMWExtWMReshapeFrame(pFrame->wid, pShape);
}
#if CYGMULTIWINDOW_DEBUG
winDebug("winMWExtWMCreateFrame - (%08x) %08x\n",
(int) pFrame->wid, (int) pRLWinPriv->hWnd);
#if 0
{
WindowPtr pWin2 = NULL;
win32RootlessWindowPtr pRLWinPriv2 = NULL;
/* Check if the Windows window property for our X window pointer is valid */
if ((pWin2 =
(WindowPtr) GetProp(pRLWinPriv->hWnd, WIN_WINDOW_PROP)) != NULL) {
pRLWinPriv2 =
(win32RootlessWindowPtr) RootlessFrameForWindow(pWin2, FALSE);
}
winDebug("winMWExtWMCreateFrame2 (%08x) %08x\n",
pRLWinPriv2, pRLWinPriv2->hWnd);
if (pRLWinPriv != pRLWinPriv2 || pRLWinPriv->hWnd != pRLWinPriv2->hWnd) {
winDebug("Error param missmatch\n");
}
}
#endif
#endif
winMWExtWMSetNativeProperty(pFrame);
return fResult;
}
void
winMWExtWMDestroyFrame(RootlessFrameID wid)
{
win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) wid;
HICON hIcon;
HICON hIconSm;
HMODULE hInstance;
int iReturn;
char pszClass[CLASS_NAME_LENGTH];
#if CYGMULTIWINDOW_DEBUG
winDebug("winMWExtWMDestroyFrame (%08x) %08x\n",
(int) pRLWinPriv, (int) pRLWinPriv->hWnd);
#if 0
{
WindowPtr pWin2 = NULL;
win32RootlessWindowPtr pRLWinPriv2 = NULL;
/* Check if the Windows window property for our X window pointer is valid */
if ((pWin2 =
(WindowPtr) GetProp(pRLWinPriv->hWnd, WIN_WINDOW_PROP)) != NULL) {
pRLWinPriv2 =
(win32RootlessWindowPtr) RootlessFrameForWindow(pWin2, FALSE);
}
winDebug("winMWExtWMDestroyFrame2 (%08x) %08x\n",
pRLWinPriv2, pRLWinPriv2->hWnd);
if (pRLWinPriv != pRLWinPriv2 || pRLWinPriv->hWnd != pRLWinPriv2->hWnd) {
winDebug("Error param missmatch\n");
*(int *) 0 = 1; //raise exseption
}
}
#endif
#endif
/* Store the info we need to destroy after this window is gone */
hInstance = (HINSTANCE) GetClassLongPtr(pRLWinPriv->hWnd, GCLP_HMODULE);
hIcon = (HICON) SendMessage(pRLWinPriv->hWnd, WM_GETICON, ICON_BIG, 0);
hIconSm = (HICON) SendMessage(pRLWinPriv->hWnd, WM_GETICON, ICON_SMALL, 0);
iReturn = GetClassName(pRLWinPriv->hWnd, pszClass, CLASS_NAME_LENGTH);
pRLWinPriv->fClose = TRUE;
pRLWinPriv->fDestroyed = TRUE;
/* Destroy the Windows window */
DestroyWindow(pRLWinPriv->hWnd);
/* Only if we were able to get the name */
if (iReturn) {
#if CYGMULTIWINDOW_DEBUG
winDebug("winMWExtWMDestroyFrame - Unregistering %s: ", pszClass);
#endif
iReturn = UnregisterClass(pszClass, hInstance);
}
#if CYGMULTIWINDOW_DEBUG
winDebug("winMWExtWMDestroyFramew - Deleting Icon\n");
#endif
winDestroyIcon(hIcon);
winDestroyIcon(hIconSm);
#if CYGMULTIWINDOW_DEBUG
winDebug("winMWExtWMDestroyFrame - done\n");
#endif
}
void
winMWExtWMMoveFrame(RootlessFrameID wid, ScreenPtr pScreen, int iNewX,
int iNewY)
{
win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) wid;
RECT rcNew;
DWORD dwExStyle;
DWORD dwStyle;
int iX, iY, iWidth, iHeight;
#if CYGMULTIWINDOW_DEBUG
winDebug("winMWExtWMMoveFrame (%08x) (%d %d)\n", (int) pRLWinPriv, iNewX,
iNewY);
#endif
/* Get the Windows window style and extended style */
dwExStyle = GetWindowLongPtr(pRLWinPriv->hWnd, GWL_EXSTYLE);
dwStyle = GetWindowLongPtr(pRLWinPriv->hWnd, GWL_STYLE);
/* Get the X and Y location of the X window */
iX = iNewX + GetSystemMetrics(SM_XVIRTUALSCREEN);
iY = iNewY + GetSystemMetrics(SM_YVIRTUALSCREEN);
/* Get the height and width of the X window */
iWidth = pRLWinPriv->pFrame->width;
iHeight = pRLWinPriv->pFrame->height;
/* Store the origin, height, and width in a rectangle structure */
SetRect(&rcNew, iX, iY, iX + iWidth, iY + iHeight);
#ifdef CYGMULTIWINDOW_DEBUG
winDebug("\tWindow {%d, %d, %d, %d}, {%d, %d}\n",
rcNew.left, rcNew.top, rcNew.right, rcNew.bottom,
rcNew.right - rcNew.left, rcNew.bottom - rcNew.top);
#endif
/*
* Calculate the required size of the Windows window rectangle,
* given the size of the Windows window client area.
*/
AdjustWindowRectEx(&rcNew, dwStyle, FALSE, dwExStyle);
#ifdef CYGMULTIWINDOW_DEBUG
winDebug("\tAdjusted {%d, %d, %d, %d}, {%d, %d}\n",
rcNew.left, rcNew.top, rcNew.right, rcNew.bottom,
rcNew.right - rcNew.left, rcNew.bottom - rcNew.top);
#endif
g_fNoConfigureWindow = TRUE;
SetWindowPos(pRLWinPriv->hWnd, NULL, rcNew.left, rcNew.top, 0, 0,
SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER);
g_fNoConfigureWindow = FALSE;
#if CYGMULTIWINDOW_DEBUG
winDebug("winMWExtWMMoveFrame (%08x) done\n", (int) pRLWinPriv);
#endif
}
void
winMWExtWMResizeFrame(RootlessFrameID wid, ScreenPtr pScreen,
int iNewX, int iNewY,
unsigned int uiNewWidth, unsigned int uiNewHeight,
unsigned int uiGravity)
{
win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) wid;
RECT rcNew;
RECT rcOld;
DWORD dwExStyle;
DWORD dwStyle;
int iX, iY;
#if CYGMULTIWINDOW_DEBUG
winDebug("winMWExtWMResizeFrame (%08x) (%d %d)-(%d %d)\n",
(int) pRLWinPriv, iNewX, iNewY, uiNewWidth, uiNewHeight);
#endif
pRLWinPriv->fResized = TRUE;
/* Get the Windows window style and extended style */
dwExStyle = GetWindowLongPtr(pRLWinPriv->hWnd, GWL_EXSTYLE);
dwStyle = GetWindowLongPtr(pRLWinPriv->hWnd, GWL_STYLE);
/* Get the X and Y location of the X window */
iX = iNewX + GetSystemMetrics(SM_XVIRTUALSCREEN);
iY = iNewY + GetSystemMetrics(SM_YVIRTUALSCREEN);
/* Store the origin, height, and width in a rectangle structure */
SetRect(&rcNew, iX, iY, iX + uiNewWidth, iY + uiNewHeight);
/*
* Calculate the required size of the Windows window rectangle,
* given the size of the Windows window client area.
*/
AdjustWindowRectEx(&rcNew, dwStyle, FALSE, dwExStyle);
/* Get a rectangle describing the old Windows window */
GetWindowRect(pRLWinPriv->hWnd, &rcOld);
/* Check if the old rectangle and new rectangle are the same */
if (!EqualRect(&rcNew, &rcOld)) {
g_fNoConfigureWindow = TRUE;
MoveWindow(pRLWinPriv->hWnd,
rcNew.left, rcNew.top,
rcNew.right - rcNew.left, rcNew.bottom - rcNew.top, TRUE);
g_fNoConfigureWindow = FALSE;
}
}
void
winMWExtWMRestackFrame(RootlessFrameID wid, RootlessFrameID nextWid)
{
win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) wid;
win32RootlessWindowPtr pRLNextWinPriv = (win32RootlessWindowPtr) nextWid;
winScreenPriv(pRLWinPriv->pFrame->win->drawable.pScreen);
winScreenInfo *pScreenInfo = NULL;
DWORD dwCurrentProcessID = GetCurrentProcessId();
DWORD dwWindowProcessID = 0;
HWND hWnd;
Bool fFirst = TRUE;
Bool fNeedRestack = TRUE;
#if CYGMULTIWINDOW_DEBUG
winDebug("winMWExtWMRestackFrame (%08x)\n", (int) pRLWinPriv);
#endif
if (pScreenPriv && pScreenPriv->fRestacking)
return;
if (pScreenPriv)
pScreenInfo = pScreenPriv->pScreenInfo;
pRLWinPriv->fRestackingNow = TRUE;
/* Show window */
if (!IsWindowVisible(pRLWinPriv->hWnd))
ShowWindow(pRLWinPriv->hWnd, SW_SHOWNOACTIVATE);
if (pRLNextWinPriv == NULL) {
#if CYGMULTIWINDOW_DEBUG
winDebug("Win %08x is top\n", pRLWinPriv);
#endif
pScreenPriv->widTop = wid;
SetWindowPos(pRLWinPriv->hWnd, HWND_TOP,
0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
}
else if (winIsInternalWMRunning(pScreenInfo)) {
/* using mulwinidow wm */
#if CYGMULTIWINDOW_DEBUG
winDebug("Win %08x is not top\n", pRLWinPriv);
#endif
for (hWnd = GetNextWindow(pRLWinPriv->hWnd, GW_HWNDPREV);
fNeedRestack && hWnd != NULL;
hWnd = GetNextWindow(hWnd, GW_HWNDPREV)) {
GetWindowThreadProcessId(hWnd, &dwWindowProcessID);
if ((dwWindowProcessID == dwCurrentProcessID)
&& GetProp(hWnd, WIN_WINDOW_PROP)) {
if (hWnd == pRLNextWinPriv->hWnd) {
/* Enable interleave X window and Windows window */
if (!fFirst) {
#if CYGMULTIWINDOW_DEBUG
winDebug("raise: Insert after Win %08x\n",
pRLNextWinPriv);
#endif
SetWindowPos(pRLWinPriv->hWnd, pRLNextWinPriv->hWnd,
0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
}
else {
#if CYGMULTIWINDOW_DEBUG
winDebug("No change\n");
#endif
}
fNeedRestack = FALSE;
break;
}
if (fFirst)
fFirst = FALSE;
}
}
for (hWnd = GetNextWindow(pRLWinPriv->hWnd, GW_HWNDNEXT);
fNeedRestack && hWnd != NULL;
hWnd = GetNextWindow(hWnd, GW_HWNDNEXT)) {
GetWindowThreadProcessId(hWnd, &dwWindowProcessID);
if ((dwWindowProcessID == dwCurrentProcessID)
&& GetProp(hWnd, WIN_WINDOW_PROP)) {
if (hWnd == pRLNextWinPriv->hWnd) {
#if CYGMULTIWINDOW_DEBUG
winDebug("lower: Insert after Win %08x\n", pRLNextWinPriv);
#endif
SetWindowPos(pRLWinPriv->hWnd, pRLNextWinPriv->hWnd,
0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
fNeedRestack = FALSE;
break;
}
}
}
}
else {
/* using general wm like twm, wmaker etc.
Interleave X window and Windows window will cause problem. */
SetWindowPos(pRLWinPriv->hWnd, pRLNextWinPriv->hWnd,
0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
}
#if CYGMULTIWINDOW_DEBUG
winDebug("winMWExtWMRestackFrame - done (%08x)\n", (int) pRLWinPriv);
#endif
pRLWinPriv->fRestackingNow = FALSE;
}
void
winMWExtWMReshapeFrame(RootlessFrameID wid, RegionPtr pShape)
{
win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) wid;
HRGN hRgn, hRgnWindow, hRgnClient;
RECT rcWindow, rcClient;
#if CYGMULTIWINDOW_DEBUG
winDebug("winMWExtWMReshapeFrame (%08x)\n", (int) pRLWinPriv);
#endif
hRgn = winMWExtWMCreateRgnFromRegion(pShape);
/* Create region for non-client area */
GetWindowRect(pRLWinPriv->hWnd, &rcWindow);
GetClientRect(pRLWinPriv->hWnd, &rcClient);
MapWindowPoints(pRLWinPriv->hWnd, HWND_DESKTOP, (LPPOINT) & rcClient, 2);
OffsetRgn(hRgn, rcClient.left - rcWindow.left, rcClient.top - rcWindow.top);
OffsetRect(&rcClient, -rcWindow.left, -rcWindow.top);
OffsetRect(&rcWindow, -rcWindow.left, -rcWindow.top);
hRgnWindow = CreateRectRgnIndirect(&rcWindow);
hRgnClient = CreateRectRgnIndirect(&rcClient);
CombineRgn(hRgnWindow, hRgnWindow, hRgnClient, RGN_DIFF);
CombineRgn(hRgn, hRgnWindow, hRgn, RGN_OR);
SetWindowRgn(pRLWinPriv->hWnd, hRgn, TRUE);
DeleteObject(hRgnWindow);
DeleteObject(hRgnClient);
}
void
winMWExtWMUnmapFrame(RootlessFrameID wid)
{
win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) wid;
#if CYGMULTIWINDOW_DEBUG
winDebug("winMWExtWMUnmapFrame (%08x)\n", (int) pRLWinPriv);
#endif
g_fNoConfigureWindow = TRUE;
//ShowWindow (pRLWinPriv->hWnd, SW_MINIMIZE);
ShowWindow(pRLWinPriv->hWnd, SW_HIDE);
g_fNoConfigureWindow = FALSE;
}
/*
* Fixme: Code sharing with winshadgdi.c and other engine support
*/
void
winMWExtWMStartDrawing(RootlessFrameID wid, char **pixelData, int *bytesPerRow)
{
win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) wid;
winPrivScreenPtr pScreenPriv = NULL;
winScreenInfo *pScreenInfo = NULL;
ScreenPtr pScreen = NULL;
DIBSECTION dibsection;
Bool fReturn = TRUE;
HDC hdcNew;
HBITMAP hbmpNew;
#if CYGMULTIWINDOW_DEBUG
winDebug("winMWExtWMStartDrawing (%08x) %08x\n", (int) pRLWinPriv,
pRLWinPriv->fDestroyed);
#endif
if (!pRLWinPriv->fDestroyed) {
pScreen = pRLWinPriv->pFrame->win->drawable.pScreen;
if (pScreen)
pScreenPriv = winGetScreenPriv(pScreen);
if (pScreenPriv)
pScreenInfo = pScreenPriv->pScreenInfo;
#if CYGMULTIWINDOW_DEBUG
winDebug("\tpScreenPriv %08X\n", (int) pScreenPriv);
winDebug("\tpScreenInfo %08X\n", (int) pScreenInfo);
winDebug("\t(%d, %d)\n", (int) pRLWinPriv->pFrame->width,
(int) pRLWinPriv->pFrame->height);
#endif
if (pRLWinPriv->hdcScreen == NULL) {
InitWin32RootlessEngine(pRLWinPriv);
}
if (pRLWinPriv->fResized) {
/* width * bpp must be multiple of 4 to match 32bit alignment */
int stridesize;
int misalignment;
pRLWinPriv->pbmihShadow->biWidth = pRLWinPriv->pFrame->width;
pRLWinPriv->pbmihShadow->biHeight = -pRLWinPriv->pFrame->height;
stridesize = pRLWinPriv->pFrame->width * (pScreenInfo->dwBPP >> 3);
misalignment = stridesize & 3;
if (misalignment != 0) {
stridesize += 4 - misalignment;
pRLWinPriv->pbmihShadow->biWidth =
stridesize / (pScreenInfo->dwBPP >> 3);
winDebug("\tresizing to %d (was %d)\n",
pRLWinPriv->pbmihShadow->biWidth,
pRLWinPriv->pFrame->width);
}
hdcNew = CreateCompatibleDC(pRLWinPriv->hdcScreen);
/* Create a DI shadow bitmap with a bit pointer */
hbmpNew = CreateDIBSection(pRLWinPriv->hdcScreen,
(BITMAPINFO *) pRLWinPriv->pbmihShadow,
DIB_RGB_COLORS,
(VOID **) & pRLWinPriv->pfb, NULL, 0);
if (hbmpNew == NULL || pRLWinPriv->pfb == NULL) {
ErrorF("winMWExtWMStartDrawing - CreateDIBSection failed\n");
//return FALSE;
}
else {
#if CYGMULTIWINDOW_DEBUG
winDebug("winMWExtWMStartDrawing - Shadow buffer allocated\n");
#endif
}
/* Get information about the bitmap that was allocated */
GetObject(hbmpNew, sizeof(dibsection), &dibsection);
#if CYGMULTIWINDOW_DEBUG
/* Print information about bitmap allocated */
winDebug("winMWExtWMStartDrawing - Dibsection width: %d height: %d "
"depth: %d size image: %d\n",
(unsigned int) dibsection.dsBmih.biWidth,
(unsigned int) dibsection.dsBmih.biHeight,
(unsigned int) dibsection.dsBmih.biBitCount,
(unsigned int) dibsection.dsBmih.biSizeImage);
#endif
/* Select the shadow bitmap into the shadow DC */
SelectObject(hdcNew, hbmpNew);
#if CYGMULTIWINDOW_DEBUG
winDebug("winMWExtWMStartDrawing - Attempting a shadow blit\n");
#endif
/* Blit from the old shadow to the new shadow */
fReturn = BitBlt(hdcNew,
0, 0,
pRLWinPriv->pFrame->width,
pRLWinPriv->pFrame->height, pRLWinPriv->hdcShadow,
0, 0, SRCCOPY);
if (fReturn) {
#if CYGMULTIWINDOW_DEBUG
winDebug("winMWExtWMStartDrawing - Shadow blit success\n");
#endif
}
else {
ErrorF("winMWExtWMStartDrawing - Shadow blit failure\n");
}
/* Look for height weirdness */
if (dibsection.dsBmih.biHeight < 0) {
/* FIXME: Figure out why biHeight is sometimes negative */
ErrorF("winMWExtWMStartDrawing - WEIRDNESS - "
"biHeight still negative: %d\n",
(int) dibsection.dsBmih.biHeight);
ErrorF("winMWExtWMStartDrawing - WEIRDNESS - "
"Flipping biHeight sign\n");
dibsection.dsBmih.biHeight = -dibsection.dsBmih.biHeight;
}
pRLWinPriv->dwWidthBytes = dibsection.dsBm.bmWidthBytes;
#if CYGMULTIWINDOW_DEBUG
winDebug("winMWExtWMStartDrawing - bytesPerRow: %d\n",
(unsigned int) dibsection.dsBm.bmWidthBytes);
#endif
/* Free the old shadow bitmap */
DeleteObject(pRLWinPriv->hdcShadow);
DeleteObject(pRLWinPriv->hbmpShadow);
pRLWinPriv->hdcShadow = hdcNew;
pRLWinPriv->hbmpShadow = hbmpNew;
pRLWinPriv->fResized = FALSE;
#if CYGMULTIWINDOW_DEBUG && FALSE
winDebug("winMWExtWMStartDrawing - 0x%08x %d\n",
(unsigned int) pRLWinPriv->pfb,
(unsigned int) dibsection.dsBm.bmWidthBytes);
#endif
}
}
else {
ErrorF("winMWExtWMStartDrawing - Already window was destroyed \n");
}
#if CYGMULTIWINDOW_DEBUG
winDebug("winMWExtWMStartDrawing - done (0x%08x) 0x%08x %d\n",
(int) pRLWinPriv,
(unsigned int) pRLWinPriv->pfb,
(unsigned int) pRLWinPriv->dwWidthBytes);
#endif
*pixelData = pRLWinPriv->pfb;
*bytesPerRow = pRLWinPriv->dwWidthBytes;
}
void
winMWExtWMStopDrawing(RootlessFrameID wid, Bool fFlush)
{
#if 0
win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) wid;
BLENDFUNCTION bfBlend;
SIZE szWin;
POINT ptSrc;
#if CYGMULTIWINDOW_DEBUG || TRUE
winDebug("winMWExtWMStopDrawing (%08x)\n", pRLWinPriv);
#endif
szWin.cx = pRLWinPriv->dwWidth;
szWin.cy = pRLWinPriv->dwHeight;
ptSrc.x = 0;
ptSrc.y = 0;
bfBlend.BlendOp = AC_SRC_OVER;
bfBlend.BlendFlags = 0;
bfBlend.SourceConstantAlpha = 255;
bfBlend.AlphaFormat = AC_SRC_ALPHA;
if (!UpdateLayeredWindow(pRLWinPriv->hWnd,
NULL, NULL, &szWin,
pRLWinPriv->hdcShadow, &ptSrc,
0, &bfBlend, ULW_ALPHA)) {
ErrorF("winMWExtWMStopDrawing - UpdateLayeredWindow failed\n");
}
#endif
}
void
winMWExtWMUpdateRegion(RootlessFrameID wid, RegionPtr pDamage)
{
win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) wid;
#if 0
BLENDFUNCTION bfBlend;
SIZE szWin;
POINT ptSrc;
#endif
#if CYGMULTIWINDOW_DEBUG && 0
winDebug("winMWExtWMUpdateRegion (%08x)\n", pRLWinPriv);
#endif
#if 0
szWin.cx = pRLWinPriv->dwWidth;
szWin.cy = pRLWinPriv->dwHeight;
ptSrc.x = 0;
ptSrc.y = 0;
bfBlend.BlendOp = AC_SRC_OVER;
bfBlend.BlendFlags = 0;
bfBlend.SourceConstantAlpha = 255;
bfBlend.AlphaFormat = AC_SRC_ALPHA;
if (!UpdateLayeredWindow(pRLWinPriv->hWnd,
NULL, NULL, &szWin,
pRLWinPriv->hdcShadow, &ptSrc,
0, &bfBlend, ULW_ALPHA)) {
LPVOID lpMsgBuf;
/* Display a fancy error message */
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) & lpMsgBuf, 0, NULL);
ErrorF("winMWExtWMUpdateRegion - UpdateLayeredWindow failed: %s\n",
(LPSTR) lpMsgBuf);
LocalFree(lpMsgBuf);
}
#endif
if (!g_fNoConfigureWindow)
UpdateWindow(pRLWinPriv->hWnd);
}
void
winMWExtWMDamageRects(RootlessFrameID wid, int nCount, const BoxRec * pRects,
int shift_x, int shift_y)
{
win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) wid;
const BoxRec *pEnd;
#if CYGMULTIWINDOW_DEBUG && 0
winDebug("winMWExtWMDamageRects (%08x, %d, %08x, %d, %d)\n",
pRLWinPriv, nCount, pRects, shift_x, shift_y);
#endif
for (pEnd = pRects + nCount; pRects < pEnd; pRects++) {
RECT rcDmg;
rcDmg.left = pRects->x1 + shift_x;
rcDmg.top = pRects->y1 + shift_y;
rcDmg.right = pRects->x2 + shift_x;
rcDmg.bottom = pRects->y2 + shift_y;
InvalidateRect(pRLWinPriv->hWnd, &rcDmg, FALSE);
}
}
void
winMWExtWMRootlessSwitchWindow(RootlessWindowPtr pFrame, WindowPtr oldWin)
{
win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) pFrame->wid;
#if CYGMULTIWINDOW_DEBUG
winDebug("winMWExtWMRootlessSwitchWindow (%08x) %08x\n",
(int) pRLWinPriv, (int) pRLWinPriv->hWnd);
#endif
pRLWinPriv->pFrame = pFrame;
pRLWinPriv->fResized = TRUE;
/* Set the window extended style flags */
SetWindowLongPtr(pRLWinPriv->hWnd, GWL_EXSTYLE, WS_EX_TOOLWINDOW);
/* Set the window standard style flags */
SetWindowLongPtr(pRLWinPriv->hWnd, GWL_STYLE, WS_POPUP | WS_CLIPCHILDREN);
DeleteProperty(serverClient, oldWin, AtmWindowsWmNativeHwnd());
winMWExtWMSetNativeProperty(pFrame);
#if CYGMULTIWINDOW_DEBUG
#if 0
{
WindowPtr pWin2 = NULL;
win32RootlessWindowPtr pRLWinPriv2 = NULL;
/* Check if the Windows window property for our X window pointer is valid */
if ((pWin2 =
(WindowPtr) GetProp(pRLWinPriv->hWnd, WIN_WINDOW_PROP)) != NULL) {
pRLWinPriv2 =
(win32RootlessWindowPtr) RootlessFrameForWindow(pWin2, FALSE);
}
winDebug("winMWExtWMSwitchFrame2 (%08x) %08x\n",
pRLWinPriv2, pRLWinPriv2->hWnd);
if (pRLWinPriv != pRLWinPriv2 || pRLWinPriv->hWnd != pRLWinPriv2->hWnd) {
winDebug("Error param missmatch\n");
}
}
#endif
#endif
}
void
winMWExtWMCopyBytes(unsigned int width, unsigned int height,
const void *src, unsigned int srcRowBytes,
void *dst, unsigned int dstRowBytes)
{
#if CYGMULTIWINDOW_DEBUG
winDebug("winMWExtWMCopyBytes - Not implemented\n");
#endif
}
void
winMWExtWMCopyWindow(RootlessFrameID wid, int nDstRects,
const BoxRec * pDstRects, int nDx, int nDy)
{
win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) wid;
const BoxRec *pEnd;
RECT rcDmg;
#if CYGMULTIWINDOW_DEBUG
winDebug("winMWExtWMCopyWindow (%08x, %d, %08x, %d, %d)\n",
(int) pRLWinPriv, nDstRects, (int) pDstRects, nDx, nDy);
#endif
for (pEnd = pDstRects + nDstRects; pDstRects < pEnd; pDstRects++) {
#if CYGMULTIWINDOW_DEBUG
winDebug("BitBlt (%d, %d, %d, %d) (%d, %d)\n",
pDstRects->x1, pDstRects->y1,
pDstRects->x2 - pDstRects->x1,
pDstRects->y2 - pDstRects->y1,
pDstRects->x1 + nDx, pDstRects->y1 + nDy);
#endif
if (!BitBlt(pRLWinPriv->hdcShadow,
pDstRects->x1, pDstRects->y1,
pDstRects->x2 - pDstRects->x1,
pDstRects->y2 - pDstRects->y1,
pRLWinPriv->hdcShadow,
pDstRects->x1 + nDx, pDstRects->y1 + nDy, SRCCOPY)) {
ErrorF("winMWExtWMCopyWindow - BitBlt failed.\n");
}
rcDmg.left = pDstRects->x1;
rcDmg.top = pDstRects->y1;
rcDmg.right = pDstRects->x2;
rcDmg.bottom = pDstRects->y2;
InvalidateRect(pRLWinPriv->hWnd, &rcDmg, FALSE);
}
#if CYGMULTIWINDOW_DEBUG
winDebug("winMWExtWMCopyWindow - done\n");
#endif
}
/*
* winMWExtWMSetNativeProperty
*/
static void
winMWExtWMSetNativeProperty(RootlessWindowPtr pFrame)
{
win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) pFrame->wid;
long lData;
/* FIXME: move this to WindowsWM extension */
lData = (long) pRLWinPriv->hWnd;
dixChangeWindowProperty(serverClient, pFrame->win, AtmWindowsWmNativeHwnd(),
XA_INTEGER, 32, PropModeReplace, 1, &lData, TRUE);
}