1143 lines
		
	
	
		
			37 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			1143 lines
		
	
	
		
			37 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | |
|  *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
 | |
|  *Copyright (C) Colin Harrison 2005-2008
 | |
|  *
 | |
|  *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
 | |
|  *              Colin Harrison
 | |
|  */
 | |
| 
 | |
| #ifdef HAVE_XWIN_CONFIG_H
 | |
| #include <xwin-config.h>
 | |
| #endif
 | |
| #include "win.h"
 | |
| #include "dixevents.h"
 | |
| #include "winmultiwindowclass.h"
 | |
| #include "winprefs.h"
 | |
| #include "winmsg.h"
 | |
| #include "inputstr.h"
 | |
| 
 | |
| extern void winUpdateWindowPosition(HWND hWnd, HWND * zstyle);
 | |
| 
 | |
| /*
 | |
|  * Local globals
 | |
|  */
 | |
| 
 | |
| static UINT_PTR g_uipMousePollingTimerID = 0;
 | |
| 
 | |
| /*
 | |
|  * Constant defines
 | |
|  */
 | |
| 
 | |
| #define WIN_MULTIWINDOW_SHAPE		YES
 | |
| 
 | |
| /*
 | |
|  * ConstrainSize - Taken from TWM sources - Respects hints for sizing
 | |
|  */
 | |
| #define makemult(a,b) ((b==1) ? (a) : (((int)((a)/(b))) * (b)) )
 | |
| static void
 | |
| ConstrainSize(WinXSizeHints hints, int *widthp, int *heightp)
 | |
| {
 | |
|     int minWidth, minHeight, maxWidth, maxHeight, xinc, yinc, delta;
 | |
|     int baseWidth, baseHeight;
 | |
|     int dwidth = *widthp, dheight = *heightp;
 | |
| 
 | |
|     if (hints.flags & PMinSize) {
 | |
|         minWidth = hints.min_width;
 | |
|         minHeight = hints.min_height;
 | |
|     }
 | |
|     else if (hints.flags & PBaseSize) {
 | |
|         minWidth = hints.base_width;
 | |
|         minHeight = hints.base_height;
 | |
|     }
 | |
|     else
 | |
|         minWidth = minHeight = 1;
 | |
| 
 | |
|     if (hints.flags & PBaseSize) {
 | |
|         baseWidth = hints.base_width;
 | |
|         baseHeight = hints.base_height;
 | |
|     }
 | |
|     else if (hints.flags & PMinSize) {
 | |
|         baseWidth = hints.min_width;
 | |
|         baseHeight = hints.min_height;
 | |
|     }
 | |
|     else
 | |
|         baseWidth = baseHeight = 0;
 | |
| 
 | |
|     if (hints.flags & PMaxSize) {
 | |
|         maxWidth = hints.max_width;
 | |
|         maxHeight = hints.max_height;
 | |
|     }
 | |
|     else {
 | |
|         maxWidth = MAXINT;
 | |
|         maxHeight = MAXINT;
 | |
|     }
 | |
| 
 | |
|     if (hints.flags & PResizeInc) {
 | |
|         xinc = hints.width_inc;
 | |
|         yinc = hints.height_inc;
 | |
|     }
 | |
|     else
 | |
|         xinc = yinc = 1;
 | |
| 
 | |
|     /*
 | |
|      * First, clamp to min and max values
 | |
|      */
 | |
|     if (dwidth < minWidth)
 | |
|         dwidth = minWidth;
 | |
|     if (dheight < minHeight)
 | |
|         dheight = minHeight;
 | |
| 
 | |
|     if (dwidth > maxWidth)
 | |
|         dwidth = maxWidth;
 | |
|     if (dheight > maxHeight)
 | |
|         dheight = maxHeight;
 | |
| 
 | |
|     /*
 | |
|      * Second, fit to base + N * inc
 | |
|      */
 | |
|     dwidth = ((dwidth - baseWidth) / xinc * xinc) + baseWidth;
 | |
|     dheight = ((dheight - baseHeight) / yinc * yinc) + baseHeight;
 | |
| 
 | |
|     /*
 | |
|      * Third, adjust for aspect ratio
 | |
|      */
 | |
| 
 | |
|     /*
 | |
|      * The math looks like this:
 | |
|      *
 | |
|      * minAspectX    dwidth     maxAspectX
 | |
|      * ---------- <= ------- <= ----------
 | |
|      * minAspectY    dheight    maxAspectY
 | |
|      *
 | |
|      * If that is multiplied out, then the width and height are
 | |
|      * invalid in the following situations:
 | |
|      *
 | |
|      * minAspectX * dheight > minAspectY * dwidth
 | |
|      * maxAspectX * dheight < maxAspectY * dwidth
 | |
|      * 
 | |
|      */
 | |
| 
 | |
|     if (hints.flags & PAspect) {
 | |
|         if (hints.min_aspect.x * dheight > hints.min_aspect.y * dwidth) {
 | |
|             delta =
 | |
|                 makemult(hints.min_aspect.x * dheight / hints.min_aspect.y -
 | |
|                          dwidth, xinc);
 | |
|             if (dwidth + delta <= maxWidth)
 | |
|                 dwidth += delta;
 | |
|             else {
 | |
|                 delta =
 | |
|                     makemult(dheight -
 | |
|                              dwidth * hints.min_aspect.y / hints.min_aspect.x,
 | |
|                              yinc);
 | |
|                 if (dheight - delta >= minHeight)
 | |
|                     dheight -= delta;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         if (hints.max_aspect.x * dheight < hints.max_aspect.y * dwidth) {
 | |
|             delta =
 | |
|                 makemult(dwidth * hints.max_aspect.y / hints.max_aspect.x -
 | |
|                          dheight, yinc);
 | |
|             if (dheight + delta <= maxHeight)
 | |
|                 dheight += delta;
 | |
|             else {
 | |
|                 delta =
 | |
|                     makemult(dwidth -
 | |
|                              hints.max_aspect.x * dheight / hints.max_aspect.y,
 | |
|                              xinc);
 | |
|                 if (dwidth - delta >= minWidth)
 | |
|                     dwidth -= delta;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /* Return computed values */
 | |
|     *widthp = dwidth;
 | |
|     *heightp = dheight;
 | |
| }
 | |
| 
 | |
| #undef makemult
 | |
| 
 | |
| /*
 | |
|  * ValidateSizing - Ensures size request respects hints
 | |
|  */
 | |
| static int
 | |
| ValidateSizing(HWND hwnd, WindowPtr pWin, WPARAM wParam, LPARAM lParam)
 | |
| {
 | |
|     WinXSizeHints sizeHints;
 | |
|     RECT *rect;
 | |
|     int iWidth, iHeight;
 | |
|     RECT rcClient, rcWindow;
 | |
|     int iBorderWidthX, iBorderWidthY;
 | |
| 
 | |
|     /* Invalid input checking */
 | |
|     if (pWin == NULL || lParam == 0)
 | |
|         return FALSE;
 | |
| 
 | |
|     /* No size hints, no checking */
 | |
|     if (!winMultiWindowGetWMNormalHints(pWin, &sizeHints))
 | |
|         return FALSE;
 | |
| 
 | |
|     /* Avoid divide-by-zero */
 | |
|     if (sizeHints.flags & PResizeInc) {
 | |
|         if (sizeHints.width_inc == 0)
 | |
|             sizeHints.width_inc = 1;
 | |
|         if (sizeHints.height_inc == 0)
 | |
|             sizeHints.height_inc = 1;
 | |
|     }
 | |
| 
 | |
|     rect = (RECT *) lParam;
 | |
| 
 | |
|     iWidth = rect->right - rect->left;
 | |
|     iHeight = rect->bottom - rect->top;
 | |
| 
 | |
|     /* Now remove size of any borders and title bar */
 | |
|     GetClientRect(hwnd, &rcClient);
 | |
|     GetWindowRect(hwnd, &rcWindow);
 | |
|     iBorderWidthX =
 | |
|         (rcWindow.right - rcWindow.left) - (rcClient.right - rcClient.left);
 | |
|     iBorderWidthY =
 | |
|         (rcWindow.bottom - rcWindow.top) - (rcClient.bottom - rcClient.top);
 | |
|     iWidth -= iBorderWidthX;
 | |
|     iHeight -= iBorderWidthY;
 | |
| 
 | |
|     /* Constrain the size to legal values */
 | |
|     ConstrainSize(sizeHints, &iWidth, &iHeight);
 | |
| 
 | |
|     /* Add back the size of borders and title bar */
 | |
|     iWidth += iBorderWidthX;
 | |
|     iHeight += iBorderWidthY;
 | |
| 
 | |
|     /* Adjust size according to where we're dragging from */
 | |
|     switch (wParam) {
 | |
|     case WMSZ_TOP:
 | |
|     case WMSZ_TOPRIGHT:
 | |
|     case WMSZ_BOTTOM:
 | |
|     case WMSZ_BOTTOMRIGHT:
 | |
|     case WMSZ_RIGHT:
 | |
|         rect->right = rect->left + iWidth;
 | |
|         break;
 | |
|     default:
 | |
|         rect->left = rect->right - iWidth;
 | |
|         break;
 | |
|     }
 | |
|     switch (wParam) {
 | |
|     case WMSZ_BOTTOM:
 | |
|     case WMSZ_BOTTOMRIGHT:
 | |
|     case WMSZ_BOTTOMLEFT:
 | |
|     case WMSZ_RIGHT:
 | |
|     case WMSZ_LEFT:
 | |
|         rect->bottom = rect->top + iHeight;
 | |
|         break;
 | |
|     default:
 | |
|         rect->top = rect->bottom - iHeight;
 | |
|         break;
 | |
|     }
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| extern Bool winInDestroyWindowsWindow;
 | |
| static Bool winInRaiseWindow = FALSE;
 | |
| static void
 | |
| winRaiseWindow(WindowPtr pWin)
 | |
| {
 | |
|     if (!winInDestroyWindowsWindow && !winInRaiseWindow) {
 | |
|         BOOL oldstate = winInRaiseWindow;
 | |
|         XID vlist[1] = { 0 };
 | |
|         winInRaiseWindow = TRUE;
 | |
|         /* Call configure window directly to make sure it gets processed 
 | |
|          * in time
 | |
|          */
 | |
|         ConfigureWindow(pWin, CWStackMode, vlist, serverClient);
 | |
|         winInRaiseWindow = oldstate;
 | |
|     }
 | |
| }
 | |
| 
 | |
| static
 | |
|     void
 | |
| winStartMousePolling(winPrivScreenPtr s_pScreenPriv)
 | |
| {
 | |
|     /*
 | |
|      * Timer to poll mouse position.  This is needed to make
 | |
|      * programs like xeyes follow the mouse properly when the
 | |
|      * mouse pointer is outside of any X window.
 | |
|      */
 | |
|     if (g_uipMousePollingTimerID == 0)
 | |
|         g_uipMousePollingTimerID = SetTimer(s_pScreenPriv->hwndScreen,
 | |
|                                             WIN_POLLING_MOUSE_TIMER_ID,
 | |
|                                             MOUSE_POLLING_INTERVAL, NULL);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * winTopLevelWindowProc - Window procedure for all top-level Windows windows.
 | |
|  */
 | |
| 
 | |
| LRESULT CALLBACK
 | |
| winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 | |
| {
 | |
|     POINT ptMouse;
 | |
|     HDC hdcUpdate;
 | |
|     PAINTSTRUCT ps;
 | |
|     WindowPtr pWin = NULL;
 | |
|     winPrivWinPtr pWinPriv = NULL;
 | |
|     ScreenPtr s_pScreen = NULL;
 | |
|     winPrivScreenPtr s_pScreenPriv = NULL;
 | |
|     winScreenInfo *s_pScreenInfo = NULL;
 | |
|     HWND hwndScreen = NULL;
 | |
|     DrawablePtr pDraw = NULL;
 | |
|     winWMMessageRec wmMsg;
 | |
|     Bool fWMMsgInitialized = FALSE;
 | |
|     static Bool s_fTracking = FALSE;
 | |
|     Bool needRestack = FALSE;
 | |
|     LRESULT ret;
 | |
| 
 | |
| #if CYGDEBUG
 | |
|     winDebugWin32Message("winTopLevelWindowProc", hwnd, message, wParam,
 | |
|                          lParam);
 | |
| #endif
 | |
| 
 | |
|     /* Check if the Windows window property for our X window pointer is valid */
 | |
|     if ((pWin = GetProp(hwnd, WIN_WINDOW_PROP)) != NULL) {
 | |
|         /* Our X window pointer is valid */
 | |
| 
 | |
|         /* Get pointers to the drawable and the screen */
 | |
|         pDraw = &pWin->drawable;
 | |
|         s_pScreen = pWin->drawable.pScreen;
 | |
| 
 | |
|         /* Get a pointer to our window privates */
 | |
|         pWinPriv = winGetWindowPriv(pWin);
 | |
| 
 | |
|         /* Get pointers to our screen privates and screen info */
 | |
|         s_pScreenPriv = pWinPriv->pScreenPriv;
 | |
|         s_pScreenInfo = s_pScreenPriv->pScreenInfo;
 | |
| 
 | |
|         /* Get the handle for our screen-sized window */
 | |
|         hwndScreen = s_pScreenPriv->hwndScreen;
 | |
| 
 | |
|         /* */
 | |
|         wmMsg.msg = 0;
 | |
|         wmMsg.hwndWindow = hwnd;
 | |
|         wmMsg.iWindow = (Window) (INT_PTR) GetProp(hwnd, WIN_WID_PROP);
 | |
| 
 | |
|         wmMsg.iX = pDraw->x;
 | |
|         wmMsg.iY = pDraw->y;
 | |
|         wmMsg.iWidth = pDraw->width;
 | |
|         wmMsg.iHeight = pDraw->height;
 | |
| 
 | |
|         fWMMsgInitialized = TRUE;
 | |
| 
 | |
| #if 0
 | |
|         /*
 | |
|          * Print some debugging information
 | |
|          */
 | |
| 
 | |
|         ErrorF("hWnd %08X\n", hwnd);
 | |
|         ErrorF("pWin %08X\n", pWin);
 | |
|         ErrorF("pDraw %08X\n", pDraw);
 | |
|         ErrorF("\ttype %08X\n", pWin->drawable.type);
 | |
|         ErrorF("\tclass %08X\n", pWin->drawable.class);
 | |
|         ErrorF("\tdepth %08X\n", pWin->drawable.depth);
 | |
|         ErrorF("\tbitsPerPixel %08X\n", pWin->drawable.bitsPerPixel);
 | |
|         ErrorF("\tid %08X\n", pWin->drawable.id);
 | |
|         ErrorF("\tx %08X\n", pWin->drawable.x);
 | |
|         ErrorF("\ty %08X\n", pWin->drawable.y);
 | |
|         ErrorF("\twidth %08X\n", pWin->drawable.width);
 | |
|         ErrorF("\thenght %08X\n", pWin->drawable.height);
 | |
|         ErrorF("\tpScreen %08X\n", pWin->drawable.pScreen);
 | |
|         ErrorF("\tserialNumber %08X\n", pWin->drawable.serialNumber);
 | |
|         ErrorF("g_iWindowPrivateKey %p\n", g_iWindowPrivateKey);
 | |
|         ErrorF("pWinPriv %08X\n", pWinPriv);
 | |
|         ErrorF("s_pScreenPriv %08X\n", s_pScreenPriv);
 | |
|         ErrorF("s_pScreenInfo %08X\n", s_pScreenInfo);
 | |
|         ErrorF("hwndScreen %08X\n", hwndScreen);
 | |
| #endif
 | |
|     }
 | |
| 
 | |
|     /* Branch on message type */
 | |
|     switch (message) {
 | |
|     case WM_CREATE:
 | |
| 
 | |
|         /* */
 | |
|         SetProp(hwnd,
 | |
|                 WIN_WINDOW_PROP,
 | |
|                 (HANDLE) ((LPCREATESTRUCT) lParam)->lpCreateParams);
 | |
| 
 | |
|         /* */
 | |
|         SetProp(hwnd,
 | |
|                 WIN_WID_PROP,
 | |
|                 (HANDLE) (INT_PTR) winGetWindowID(((LPCREATESTRUCT) lParam)->
 | |
|                                                   lpCreateParams));
 | |
| 
 | |
|         /*
 | |
|          * Make X windows' Z orders sync with Windows windows because
 | |
|          * there can be AlwaysOnTop windows overlapped on the window
 | |
|          * currently being created.
 | |
|          */
 | |
|         winReorderWindowsMultiWindow();
 | |
| 
 | |
|         /* Fix a 'round title bar corner background should be transparent not black' problem when first painted */
 | |
|         {
 | |
|             RECT rWindow;
 | |
|             HRGN hRgnWindow;
 | |
| 
 | |
|             GetWindowRect(hwnd, &rWindow);
 | |
|             hRgnWindow = CreateRectRgnIndirect(&rWindow);
 | |
|             SetWindowRgn(hwnd, hRgnWindow, TRUE);
 | |
|             DeleteObject(hRgnWindow);
 | |
|         }
 | |
| 
 | |
|         SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) XMING_SIGNATURE);
 | |
| 
 | |
|         return 0;
 | |
| 
 | |
|     case WM_INIT_SYS_MENU:
 | |
|         /*
 | |
|          * Add whatever the setup file wants to for this window
 | |
|          */
 | |
|         SetupSysMenu(hwnd);
 | |
|         return 0;
 | |
| 
 | |
|     case WM_SYSCOMMAND:
 | |
|         /*
 | |
|          * Any window menu items go through here
 | |
|          */
 | |
|         if (HandleCustomWM_COMMAND(hwnd, LOWORD(wParam))) {
 | |
|             /* Don't pass customized menus to DefWindowProc */
 | |
|             return 0;
 | |
|         }
 | |
|         if (wParam == SC_RESTORE || wParam == SC_MAXIMIZE) {
 | |
|             WINDOWPLACEMENT wndpl;
 | |
| 
 | |
|             wndpl.length = sizeof(wndpl);
 | |
|             if (GetWindowPlacement(hwnd, &wndpl) &&
 | |
|                 wndpl.showCmd == SW_SHOWMINIMIZED)
 | |
|                 needRestack = TRUE;
 | |
|         }
 | |
|         break;
 | |
| 
 | |
|     case WM_INITMENU:
 | |
|         /* Checks/Unchecks any menu items before they are displayed */
 | |
|         HandleCustomWM_INITMENU(hwnd, (HMENU)wParam);
 | |
|         break;
 | |
| 
 | |
|     case WM_ERASEBKGND:
 | |
|         /*
 | |
|          * Pretend that we did erase the background but we don't care,
 | |
|          * since we repaint the entire region anyhow
 | |
|          * This avoids some flickering when resizing.
 | |
|          */
 | |
|         return TRUE;
 | |
| 
 | |
|     case WM_PAINT:
 | |
|         /* Only paint if our window handle is valid */
 | |
|         if (hwndScreen == NULL)
 | |
|             break;
 | |
| 
 | |
|         /* BeginPaint gives us an hdc that clips to the invalidated region */
 | |
|         hdcUpdate = BeginPaint(hwnd, &ps);
 | |
|         /* Avoid the BitBlt's if the PAINTSTRUCT is bogus */
 | |
|         if (ps.rcPaint.right == 0 && ps.rcPaint.bottom == 0 &&
 | |
|             ps.rcPaint.left == 0 && ps.rcPaint.top == 0) {
 | |
|             EndPaint(hwnd, &ps);
 | |
|             return 0;
 | |
|         }
 | |
| 
 | |
| #ifdef XWIN_GLX_WINDOWS
 | |
|         if (pWinPriv->fWglUsed) {
 | |
|             /*
 | |
|                For regions which are being drawn by GL, the shadow framebuffer doesn't have the
 | |
|                correct bits, so don't bitblt from the shadow framebuffer
 | |
| 
 | |
|                XXX: For now, just leave it alone, but ideally we want to send an expose event to
 | |
|                the window so it really redraws the affected region...
 | |
|              */
 | |
|             ValidateRect(hwnd, &(ps.rcPaint));
 | |
|         }
 | |
|         else
 | |
| #endif
 | |
|             /* Try to copy from the shadow buffer */
 | |
|         if (!BitBlt(hdcUpdate,
 | |
|                         ps.rcPaint.left, ps.rcPaint.top,
 | |
|                         ps.rcPaint.right - ps.rcPaint.left,
 | |
|                         ps.rcPaint.bottom - ps.rcPaint.top,
 | |
|                         s_pScreenPriv->hdcShadow,
 | |
|                         ps.rcPaint.left + pWin->drawable.x,
 | |
|                         ps.rcPaint.top + pWin->drawable.y, SRCCOPY)) {
 | |
|             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("winTopLevelWindowProc - BitBlt failed: %s\n",
 | |
|                    (LPSTR) lpMsgBuf);
 | |
|             LocalFree(lpMsgBuf);
 | |
|         }
 | |
| 
 | |
|         /* EndPaint frees the DC */
 | |
|         EndPaint(hwnd, &ps);
 | |
|         return 0;
 | |
| 
 | |
|     case WM_MOUSEMOVE:
 | |
|         /* Unpack the client area mouse coordinates */
 | |
|         ptMouse.x = GET_X_LPARAM(lParam);
 | |
|         ptMouse.y = GET_Y_LPARAM(lParam);
 | |
| 
 | |
|         /* Translate the client area mouse coordinates to screen coordinates */
 | |
|         ClientToScreen(hwnd, &ptMouse);
 | |
| 
 | |
|         /* Screen Coords from (-X, -Y) -> Root Window (0, 0) */
 | |
|         ptMouse.x -= GetSystemMetrics(SM_XVIRTUALSCREEN);
 | |
|         ptMouse.y -= GetSystemMetrics(SM_YVIRTUALSCREEN);
 | |
| 
 | |
|         /* We can't do anything without privates */
 | |
|         if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
 | |
|             break;
 | |
| 
 | |
|         /* Has the mouse pointer crossed screens? */
 | |
|         if (s_pScreen != miPointerGetScreen(g_pwinPointer))
 | |
|             miPointerSetScreen(g_pwinPointer, s_pScreenInfo->dwScreen,
 | |
|                                ptMouse.x - s_pScreenInfo->dwXOffset,
 | |
|                                ptMouse.y - s_pScreenInfo->dwYOffset);
 | |
| 
 | |
|         /* Are we tracking yet? */
 | |
|         if (!s_fTracking) {
 | |
|             TRACKMOUSEEVENT tme;
 | |
| 
 | |
|             /* Setup data structure */
 | |
|             ZeroMemory(&tme, sizeof(tme));
 | |
|             tme.cbSize = sizeof(tme);
 | |
|             tme.dwFlags = TME_LEAVE;
 | |
|             tme.hwndTrack = hwnd;
 | |
| 
 | |
|             /* Call the tracking function */
 | |
|             if (!TrackMouseEvent(&tme))
 | |
|                 ErrorF("winTopLevelWindowProc - TrackMouseEvent failed\n");
 | |
| 
 | |
|             /* Flag that we are tracking now */
 | |
|             s_fTracking = TRUE;
 | |
|         }
 | |
| 
 | |
|         /* Hide or show the Windows mouse cursor */
 | |
|         if (g_fSoftwareCursor && g_fCursor) {
 | |
|             /* Hide Windows cursor */
 | |
|             g_fCursor = FALSE;
 | |
|             ShowCursor(FALSE);
 | |
|         }
 | |
| 
 | |
|         /* Kill the timer used to poll mouse events */
 | |
|         if (g_uipMousePollingTimerID != 0) {
 | |
|             KillTimer(s_pScreenPriv->hwndScreen, WIN_POLLING_MOUSE_TIMER_ID);
 | |
|             g_uipMousePollingTimerID = 0;
 | |
|         }
 | |
| 
 | |
|         /* Deliver absolute cursor position to X Server */
 | |
|         winEnqueueMotion(ptMouse.x - s_pScreenInfo->dwXOffset,
 | |
|                          ptMouse.y - s_pScreenInfo->dwYOffset);
 | |
| 
 | |
|         return 0;
 | |
| 
 | |
|     case WM_NCMOUSEMOVE:
 | |
|         /*
 | |
|          * We break instead of returning 0 since we need to call
 | |
|          * DefWindowProc to get the mouse cursor changes
 | |
|          * and min/max/close button highlighting in Windows XP.
 | |
|          * The Platform SDK says that you should return 0 if you
 | |
|          * process this message, but it fails to mention that you
 | |
|          * will give up any default functionality if you do return 0.
 | |
|          */
 | |
| 
 | |
|         /* We can't do anything without privates */
 | |
|         if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
 | |
|             break;
 | |
| 
 | |
|         /* Non-client mouse movement, show Windows cursor */
 | |
|         if (g_fSoftwareCursor && !g_fCursor) {
 | |
|             g_fCursor = TRUE;
 | |
|             ShowCursor(TRUE);
 | |
|         }
 | |
| 
 | |
|         winStartMousePolling(s_pScreenPriv);
 | |
| 
 | |
|         break;
 | |
| 
 | |
|     case WM_MOUSELEAVE:
 | |
|         /* Mouse has left our client area */
 | |
| 
 | |
|         /* Flag that we are no longer tracking */
 | |
|         s_fTracking = FALSE;
 | |
| 
 | |
|         /* Show the mouse cursor, if necessary */
 | |
|         if (g_fSoftwareCursor && !g_fCursor) {
 | |
|             g_fCursor = TRUE;
 | |
|             ShowCursor(TRUE);
 | |
|         }
 | |
| 
 | |
|         winStartMousePolling(s_pScreenPriv);
 | |
| 
 | |
|         return 0;
 | |
| 
 | |
|     case WM_LBUTTONDBLCLK:
 | |
|     case WM_LBUTTONDOWN:
 | |
|         if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
 | |
|             break;
 | |
|         g_fButton[0] = TRUE;
 | |
|         SetCapture(hwnd);
 | |
|         return winMouseButtonsHandle(s_pScreen, ButtonPress, Button1, wParam);
 | |
| 
 | |
|     case WM_LBUTTONUP:
 | |
|         if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
 | |
|             break;
 | |
|         g_fButton[0] = FALSE;
 | |
|         ReleaseCapture();
 | |
|         winStartMousePolling(s_pScreenPriv);
 | |
|         return winMouseButtonsHandle(s_pScreen, ButtonRelease, Button1, wParam);
 | |
| 
 | |
|     case WM_MBUTTONDBLCLK:
 | |
|     case WM_MBUTTONDOWN:
 | |
|         if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
 | |
|             break;
 | |
|         g_fButton[1] = TRUE;
 | |
|         SetCapture(hwnd);
 | |
|         return winMouseButtonsHandle(s_pScreen, ButtonPress, Button2, wParam);
 | |
| 
 | |
|     case WM_MBUTTONUP:
 | |
|         if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
 | |
|             break;
 | |
|         g_fButton[1] = FALSE;
 | |
|         ReleaseCapture();
 | |
|         winStartMousePolling(s_pScreenPriv);
 | |
|         return winMouseButtonsHandle(s_pScreen, ButtonRelease, Button2, wParam);
 | |
| 
 | |
|     case WM_RBUTTONDBLCLK:
 | |
|     case WM_RBUTTONDOWN:
 | |
|         if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
 | |
|             break;
 | |
|         g_fButton[2] = TRUE;
 | |
|         SetCapture(hwnd);
 | |
|         return winMouseButtonsHandle(s_pScreen, ButtonPress, Button3, wParam);
 | |
| 
 | |
|     case WM_RBUTTONUP:
 | |
|         if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
 | |
|             break;
 | |
|         g_fButton[2] = FALSE;
 | |
|         ReleaseCapture();
 | |
|         winStartMousePolling(s_pScreenPriv);
 | |
|         return winMouseButtonsHandle(s_pScreen, ButtonRelease, Button3, wParam);
 | |
| 
 | |
|     case WM_XBUTTONDBLCLK:
 | |
|     case WM_XBUTTONDOWN:
 | |
|         if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
 | |
|             break;
 | |
|         SetCapture(hwnd);
 | |
|         return winMouseButtonsHandle(s_pScreen, ButtonPress, HIWORD(wParam) + 7,
 | |
|                                      wParam);
 | |
| 
 | |
|     case WM_XBUTTONUP:
 | |
|         if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
 | |
|             break;
 | |
|         ReleaseCapture();
 | |
|         winStartMousePolling(s_pScreenPriv);
 | |
|         return winMouseButtonsHandle(s_pScreen, ButtonRelease,
 | |
|                                      HIWORD(wParam) + 7, wParam);
 | |
| 
 | |
|     case WM_MOUSEWHEEL:
 | |
|         if (SendMessage
 | |
|             (hwnd, WM_NCHITTEST, 0,
 | |
|              MAKELONG(GET_X_LPARAM(lParam),
 | |
|                       GET_Y_LPARAM(lParam))) == HTCLIENT) {
 | |
|             /* Pass the message to the root window */
 | |
|             SendMessage(hwndScreen, message, wParam, lParam);
 | |
|             return 0;
 | |
|         }
 | |
|         else
 | |
|             break;
 | |
| 
 | |
|     case WM_MOUSEHWHEEL:
 | |
|         if (SendMessage
 | |
|             (hwnd, WM_NCHITTEST, 0,
 | |
|              MAKELONG(GET_X_LPARAM(lParam),
 | |
|                       GET_Y_LPARAM(lParam))) == HTCLIENT) {
 | |
|             /* Pass the message to the root window */
 | |
|             SendMessage(hwndScreen, message, wParam, lParam);
 | |
|             return 0;
 | |
|         }
 | |
|         else
 | |
|             break;
 | |
| 
 | |
|     case WM_SETFOCUS:
 | |
|         if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
 | |
|             break;
 | |
| 
 | |
|         {
 | |
|             /* Get the parent window for transient handling */
 | |
|             HWND hParent = GetParent(hwnd);
 | |
| 
 | |
|             if (hParent && IsIconic(hParent))
 | |
|                 ShowWindow(hParent, SW_RESTORE);
 | |
|         }
 | |
| 
 | |
|         winRestoreModeKeyStates();
 | |
| 
 | |
|         /* Add the keyboard hook if possible */
 | |
|         if (g_fKeyboardHookLL)
 | |
|             g_fKeyboardHookLL = winInstallKeyboardHookLL();
 | |
|         return 0;
 | |
| 
 | |
|     case WM_KILLFOCUS:
 | |
|         /* Pop any pressed keys since we are losing keyboard focus */
 | |
|         winKeybdReleaseKeys();
 | |
| 
 | |
|         /* Remove our keyboard hook if it is installed */
 | |
|         winRemoveKeyboardHookLL();
 | |
| 
 | |
|         /* Revert the X focus as well, but only if the Windows focus is going to another window */
 | |
|         if (!wParam && pWin)
 | |
|             DeleteWindowFromAnyEvents(pWin, FALSE);
 | |
| 
 | |
|         return 0;
 | |
| 
 | |
|     case WM_SYSDEADCHAR:
 | |
|     case WM_DEADCHAR:
 | |
|         /*
 | |
|          * NOTE: We do nothing with WM_*CHAR messages,
 | |
|          * nor does the root window, so we can just toss these messages.
 | |
|          */
 | |
|         return 0;
 | |
| 
 | |
|     case WM_SYSKEYDOWN:
 | |
|     case WM_KEYDOWN:
 | |
| 
 | |
|         /*
 | |
|          * Don't pass Alt-F4 key combo to root window,
 | |
|          * let Windows translate to WM_CLOSE and close this top-level window.
 | |
|          *
 | |
|          * NOTE: We purposely don't check the fUseWinKillKey setting because
 | |
|          * it should only apply to the key handling for the root window,
 | |
|          * not for top-level window-manager windows.
 | |
|          *
 | |
|          * ALSO NOTE: We do pass Ctrl-Alt-Backspace to the root window
 | |
|          * because that is a key combo that no X app should be expecting to
 | |
|          * receive, since it has historically been used to shutdown the X server.
 | |
|          * Passing Ctrl-Alt-Backspace to the root window preserves that
 | |
|          * behavior, assuming that -unixkill has been passed as a parameter.
 | |
|          */
 | |
|         if (wParam == VK_F4 && (GetKeyState(VK_MENU) & 0x8000))
 | |
|             break;
 | |
| 
 | |
| #if CYGWINDOWING_DEBUG
 | |
|         if (wParam == VK_ESCAPE) {
 | |
|             /* Place for debug: put any tests and dumps here */
 | |
|             WINDOWPLACEMENT windPlace;
 | |
|             RECT rc;
 | |
|             LPRECT pRect;
 | |
| 
 | |
|             windPlace.length = sizeof(WINDOWPLACEMENT);
 | |
|             GetWindowPlacement(hwnd, &windPlace);
 | |
|             pRect = &windPlace.rcNormalPosition;
 | |
|             ErrorF("\nCYGWINDOWING Dump:\n"
 | |
|                    "\tdrawable: (%hd, %hd) - %hdx%hd\n", pDraw->x,
 | |
|                    pDraw->y, pDraw->width, pDraw->height);
 | |
|             ErrorF("\twindPlace: (%ld, %ld) - %ldx%ld\n", pRect->left,
 | |
|                    pRect->top, pRect->right - pRect->left,
 | |
|                    pRect->bottom - pRect->top);
 | |
|             if (GetClientRect(hwnd, &rc)) {
 | |
|                 pRect = &rc;
 | |
|                 ErrorF("\tClientRect: (%ld, %ld) - %ldx%ld\n", pRect->left,
 | |
|                        pRect->top, pRect->right - pRect->left,
 | |
|                        pRect->bottom - pRect->top);
 | |
|             }
 | |
|             if (GetWindowRect(hwnd, &rc)) {
 | |
|                 pRect = &rc;
 | |
|                 ErrorF("\tWindowRect: (%ld, %ld) - %ldx%ld\n", pRect->left,
 | |
|                        pRect->top, pRect->right - pRect->left,
 | |
|                        pRect->bottom - pRect->top);
 | |
|             }
 | |
|             ErrorF("\n");
 | |
|         }
 | |
| #endif
 | |
| 
 | |
|         /* Pass the message to the root window */
 | |
|         return winWindowProc(hwndScreen, message, wParam, lParam);
 | |
| 
 | |
|     case WM_SYSKEYUP:
 | |
|     case WM_KEYUP:
 | |
| 
 | |
|         /* Pass the message to the root window */
 | |
|         return winWindowProc(hwndScreen, message, wParam, lParam);
 | |
| 
 | |
|     case WM_HOTKEY:
 | |
| 
 | |
|         /* Pass the message to the root window */
 | |
|         SendMessage(hwndScreen, message, wParam, lParam);
 | |
|         return 0;
 | |
| 
 | |
|     case WM_ACTIVATE:
 | |
| 
 | |
|         /* Pass the message to the root window */
 | |
|         SendMessage(hwndScreen, message, wParam, lParam);
 | |
| 
 | |
|         if (LOWORD(wParam) != WA_INACTIVE) {
 | |
|             /* Raise the window to the top in Z order */
 | |
|             /* ago: Activate does not mean putting it to front! */
 | |
|             /*
 | |
|                wmMsg.msg = WM_WM_RAISE;
 | |
|                if (fWMMsgInitialized)
 | |
|                winSendMessageToWM (s_pScreenPriv->pWMInfo, &wmMsg);
 | |
|              */
 | |
| 
 | |
|             /* Tell our Window Manager thread to activate the window */
 | |
|             wmMsg.msg = WM_WM_ACTIVATE;
 | |
|             if (fWMMsgInitialized)
 | |
|                 if (!pWin || !pWin->overrideRedirect)   /* for OOo menus */
 | |
|                     winSendMessageToWM(s_pScreenPriv->pWMInfo, &wmMsg);
 | |
|         }
 | |
|         /* Prevent the mouse wheel from stalling when another window is minimized */
 | |
|         if (HIWORD(wParam) == 0 && LOWORD(wParam) == WA_ACTIVE &&
 | |
|             (HWND) lParam != NULL && (HWND) lParam != GetParent(hwnd))
 | |
|             SetFocus(hwnd);
 | |
|         return 0;
 | |
| 
 | |
|     case WM_ACTIVATEAPP:
 | |
|         /*
 | |
|          * This message is also sent to the root window
 | |
|          * so we do nothing for individual multiwindow windows
 | |
|          */
 | |
|         break;
 | |
| 
 | |
|     case WM_CLOSE:
 | |
|         /* Removep AppUserModelID property */
 | |
|         winSetAppUserModelID(hwnd, NULL);
 | |
|         /* Branch on if the window was killed in X already */
 | |
|         if (pWinPriv->fXKilled) {
 | |
|             /* Window was killed, go ahead and destroy the window */
 | |
|             DestroyWindow(hwnd);
 | |
|         }
 | |
|         else {
 | |
|             /* Tell our Window Manager thread to kill the window */
 | |
|             wmMsg.msg = WM_WM_KILL;
 | |
|             if (fWMMsgInitialized)
 | |
|                 winSendMessageToWM(s_pScreenPriv->pWMInfo, &wmMsg);
 | |
|         }
 | |
|         return 0;
 | |
| 
 | |
|     case WM_DESTROY:
 | |
| 
 | |
|         /* Branch on if the window was killed in X already */
 | |
|         if (pWinPriv && !pWinPriv->fXKilled) {
 | |
|             ErrorF("winTopLevelWindowProc - WM_DESTROY - WM_WM_KILL\n");
 | |
| 
 | |
|             /* Tell our Window Manager thread to kill the window */
 | |
|             wmMsg.msg = WM_WM_KILL;
 | |
|             if (fWMMsgInitialized)
 | |
|                 winSendMessageToWM(s_pScreenPriv->pWMInfo, &wmMsg);
 | |
|         }
 | |
| 
 | |
|         RemoveProp(hwnd, WIN_WINDOW_PROP);
 | |
|         RemoveProp(hwnd, WIN_WID_PROP);
 | |
|         RemoveProp(hwnd, WIN_NEEDMANAGE_PROP);
 | |
| 
 | |
|         break;
 | |
| 
 | |
|     case WM_MOVE:
 | |
|         /* Adjust the X Window to the moved Windows window */
 | |
|         winAdjustXWindow(pWin, hwnd);
 | |
|         return 0;
 | |
| 
 | |
|     case WM_SHOWWINDOW:
 | |
|         /* Bail out if the window is being hidden */
 | |
|         if (!wParam)
 | |
|             return 0;
 | |
| 
 | |
|         /* */
 | |
|         if (!pWin->overrideRedirect) {
 | |
|             HWND zstyle = HWND_NOTOPMOST;
 | |
| 
 | |
|             /* Flag that this window needs to be made active when clicked */
 | |
|             SetProp(hwnd, WIN_NEEDMANAGE_PROP, (HANDLE) 1);
 | |
| 
 | |
|             /* 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 */
 | |
|             else
 | |
|                 SetWindowLongPtr(hwnd, GWL_STYLE,
 | |
|                                  (WS_POPUP | WS_OVERLAPPEDWINDOW |
 | |
|                                   WS_CLIPCHILDREN | WS_CLIPSIBLINGS)
 | |
|                                  & ~WS_CAPTION & ~WS_SIZEBOX);
 | |
| 
 | |
|             winUpdateWindowPosition(hwnd, &zstyle);
 | |
| 
 | |
|             {
 | |
|                 WinXWMHints hints;
 | |
| 
 | |
|                 if (winMultiWindowGetWMHints(pWin, &hints)) {
 | |
|                     /*
 | |
|                        Give the window focus, unless it has an InputHint
 | |
|                        which is FALSE (this is used by e.g. glean to
 | |
|                        avoid every test window grabbing the focus)
 | |
|                      */
 | |
|                     if (!((hints.flags & InputHint) && (!hints.input))) {
 | |
|                         SetForegroundWindow(hwnd);
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|             wmMsg.msg = WM_WM_MAP3;
 | |
|         }
 | |
|         else {                  /* It is an overridden window so make it top of Z stack */
 | |
| 
 | |
|             HWND forHwnd = GetForegroundWindow();
 | |
| 
 | |
| #if CYGWINDOWING_DEBUG
 | |
|             ErrorF("overridden window is shown\n");
 | |
| #endif
 | |
|             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;
 | |
|         }
 | |
| 
 | |
|         /* Tell our Window Manager thread to map the window */
 | |
|         if (fWMMsgInitialized)
 | |
|             winSendMessageToWM(s_pScreenPriv->pWMInfo, &wmMsg);
 | |
| 
 | |
|         winStartMousePolling(s_pScreenPriv);
 | |
| 
 | |
|         return 0;
 | |
| 
 | |
|     case WM_SIZING:
 | |
|         /* Need to legalize the size according to WM_NORMAL_HINTS */
 | |
|         /* for applications like xterm */
 | |
|         return ValidateSizing(hwnd, pWin, wParam, lParam);
 | |
| 
 | |
|     case WM_WINDOWPOSCHANGED:
 | |
|     {
 | |
|         LPWINDOWPOS pWinPos = (LPWINDOWPOS) lParam;
 | |
| 
 | |
|         if (!(pWinPos->flags & SWP_NOZORDER)) {
 | |
| #if CYGWINDOWING_DEBUG
 | |
|             winDebug("\twindow z order was changed\n");
 | |
| #endif
 | |
|             if (pWinPos->hwndInsertAfter == HWND_TOP
 | |
|                 || pWinPos->hwndInsertAfter == HWND_TOPMOST
 | |
|                 || pWinPos->hwndInsertAfter == HWND_NOTOPMOST) {
 | |
| #if CYGWINDOWING_DEBUG
 | |
|                 winDebug("\traise to top\n");
 | |
| #endif
 | |
|                 /* Raise the window to the top in Z order */
 | |
|                 winRaiseWindow(pWin);
 | |
|             }
 | |
|             else if (pWinPos->hwndInsertAfter == HWND_BOTTOM) {
 | |
|             }
 | |
|             else {
 | |
|                 /* Check if this window is top of X windows. */
 | |
|                 HWND hWndAbove = NULL;
 | |
|                 DWORD dwCurrentProcessID = GetCurrentProcessId();
 | |
|                 DWORD dwWindowProcessID = 0;
 | |
| 
 | |
|                 for (hWndAbove = pWinPos->hwndInsertAfter;
 | |
|                      hWndAbove != NULL;
 | |
|                      hWndAbove = GetNextWindow(hWndAbove, GW_HWNDPREV)) {
 | |
|                     /* Ignore other XWin process's window */
 | |
|                     GetWindowThreadProcessId(hWndAbove, &dwWindowProcessID);
 | |
| 
 | |
|                     if ((dwWindowProcessID == dwCurrentProcessID)
 | |
|                         && GetProp(hWndAbove, WIN_WINDOW_PROP)
 | |
|                         && !IsWindowVisible(hWndAbove)
 | |
|                         && !IsIconic(hWndAbove))        /* ignore minimized windows */
 | |
|                         break;
 | |
|                 }
 | |
|                 /* If this is top of X windows in Windows stack,
 | |
|                    raise it in X stack. */
 | |
|                 if (hWndAbove == NULL) {
 | |
| #if CYGWINDOWING_DEBUG
 | |
|                     winDebug("\traise to top\n");
 | |
| #endif
 | |
|                     winRaiseWindow(pWin);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|         /*
 | |
|          * Pass the message to DefWindowProc to let the function
 | |
|          * break down WM_WINDOWPOSCHANGED to WM_MOVE and WM_SIZE.
 | |
|          */
 | |
|         break;
 | |
| 
 | |
|     case WM_SIZE:
 | |
|         /* see dix/window.c */
 | |
| #if CYGWINDOWING_DEBUG
 | |
|     {
 | |
|         char buf[64];
 | |
| 
 | |
|         switch (wParam) {
 | |
|         case SIZE_MINIMIZED:
 | |
|             strcpy(buf, "SIZE_MINIMIZED");
 | |
|             break;
 | |
|         case SIZE_MAXIMIZED:
 | |
|             strcpy(buf, "SIZE_MAXIMIZED");
 | |
|             break;
 | |
|         case SIZE_RESTORED:
 | |
|             strcpy(buf, "SIZE_RESTORED");
 | |
|             break;
 | |
|         default:
 | |
|             strcpy(buf, "UNKNOWN_FLAG");
 | |
|         }
 | |
|         ErrorF("winTopLevelWindowProc - WM_SIZE to %dx%d (%s) - %d ms\n",
 | |
|                (int) LOWORD(lParam), (int) HIWORD(lParam), buf,
 | |
|                (int) (GetTickCount()));
 | |
|     }
 | |
| #endif
 | |
|         /* Adjust the X Window to the moved Windows window */
 | |
|         winAdjustXWindow(pWin, hwnd);
 | |
|         return 0;               /* end of WM_SIZE handler */
 | |
| 
 | |
|     case WM_STYLECHANGING:
 | |
|         /*
 | |
|            When the style changes, adjust the Windows window size so the client area remains the same size,
 | |
|            and adjust the Windows window position so that the client area remains in the same place.
 | |
|          */
 | |
|     {
 | |
|         RECT newWinRect;
 | |
|         DWORD dwExStyle;
 | |
|         DWORD dwStyle;
 | |
|         DWORD newStyle = ((STYLESTRUCT *) lParam)->styleNew;
 | |
|         WINDOWINFO wi;
 | |
| 
 | |
|         dwExStyle = GetWindowLongPtr(hwnd, GWL_EXSTYLE);
 | |
|         dwStyle = GetWindowLongPtr(hwnd, GWL_STYLE);
 | |
| 
 | |
|         winDebug("winTopLevelWindowProc - WM_STYLECHANGING from %08x %08x\n",
 | |
|                  dwStyle, dwExStyle);
 | |
| 
 | |
|         if (wParam == GWL_EXSTYLE)
 | |
|             dwExStyle = newStyle;
 | |
| 
 | |
|         if (wParam == GWL_STYLE)
 | |
|             dwStyle = newStyle;
 | |
| 
 | |
|         winDebug("winTopLevelWindowProc - WM_STYLECHANGING to %08x %08x\n",
 | |
|                  dwStyle, dwExStyle);
 | |
| 
 | |
|         /* Get client rect in screen coordinates */
 | |
|         wi.cbSize = sizeof(WINDOWINFO);
 | |
|         GetWindowInfo(hwnd, &wi);
 | |
| 
 | |
|         winDebug
 | |
|             ("winTopLevelWindowProc - WM_STYLECHANGING client area {%d, %d, %d, %d}, {%d x %d}\n",
 | |
|              wi.rcClient.left, wi.rcClient.top, wi.rcClient.right,
 | |
|              wi.rcClient.bottom, wi.rcClient.right - wi.rcClient.left,
 | |
|              wi.rcClient.bottom - wi.rcClient.top);
 | |
| 
 | |
|         newWinRect = wi.rcClient;
 | |
|         if (!AdjustWindowRectEx(&newWinRect, dwStyle, FALSE, dwExStyle))
 | |
|             winDebug
 | |
|                 ("winTopLevelWindowProc - WM_STYLECHANGING AdjustWindowRectEx failed\n");
 | |
| 
 | |
|         winDebug
 | |
|             ("winTopLevelWindowProc - WM_STYLECHANGING window area should be {%d, %d, %d, %d}, {%d x %d}\n",
 | |
|              newWinRect.left, newWinRect.top, newWinRect.right,
 | |
|              newWinRect.bottom, newWinRect.right - newWinRect.left,
 | |
|              newWinRect.bottom - newWinRect.top);
 | |
| 
 | |
|         /*
 | |
|            Style change hasn't happened yet, so we can't adjust the window size yet, as the winAdjustXWindow()
 | |
|            which WM_SIZE does will use the current (unchanged) style.  Instead make a note to change it when
 | |
|            WM_STYLECHANGED is received...
 | |
|          */
 | |
|         pWinPriv->hDwp = BeginDeferWindowPos(1);
 | |
|         pWinPriv->hDwp =
 | |
|             DeferWindowPos(pWinPriv->hDwp, hwnd, NULL, newWinRect.left,
 | |
|                            newWinRect.top, newWinRect.right - newWinRect.left,
 | |
|                            newWinRect.bottom - newWinRect.top,
 | |
|                            SWP_NOACTIVATE | SWP_NOZORDER);
 | |
|     }
 | |
|         return 0;
 | |
| 
 | |
|     case WM_STYLECHANGED:
 | |
|     {
 | |
|         if (pWinPriv->hDwp) {
 | |
|             EndDeferWindowPos(pWinPriv->hDwp);
 | |
|             pWinPriv->hDwp = NULL;
 | |
|         }
 | |
|         winDebug("winTopLevelWindowProc - WM_STYLECHANGED done\n");
 | |
|     }
 | |
|         return 0;
 | |
| 
 | |
|     case WM_MOUSEACTIVATE:
 | |
| 
 | |
|         /* Check if this window needs to be made active when clicked */
 | |
|         if (!GetProp(pWinPriv->hWnd, WIN_NEEDMANAGE_PROP)) {
 | |
| #if CYGMULTIWINDOW_DEBUG
 | |
|             ErrorF("winTopLevelWindowProc - WM_MOUSEACTIVATE - "
 | |
|                    "MA_NOACTIVATE\n");
 | |
| #endif
 | |
| 
 | |
|             /* */
 | |
|             return MA_NOACTIVATE;
 | |
|         }
 | |
|         break;
 | |
| 
 | |
|     case WM_SETCURSOR:
 | |
|         if (LOWORD(lParam) == HTCLIENT) {
 | |
|             if (!g_fSoftwareCursor)
 | |
|                 SetCursor(s_pScreenPriv->cursor.handle);
 | |
|             return TRUE;
 | |
|         }
 | |
|         break;
 | |
| 
 | |
|     default:
 | |
|         break;
 | |
|     }
 | |
| 
 | |
|     ret = DefWindowProc(hwnd, message, wParam, lParam);
 | |
|     /*
 | |
|      * If the window was minized we get the stack change before the window is restored
 | |
|      * and so it gets lost. Ensure there stacking order is correct.
 | |
|      */
 | |
|     if (needRestack)
 | |
|         winReorderWindowsMultiWindow();
 | |
|     return ret;
 | |
| }
 |