diff options
author | Jon TURNEY <jon.turney@dronecode.org.uk> | 2010-10-30 22:28:42 +0100 |
---|---|---|
committer | Jon TURNEY <jon.turney@dronecode.org.uk> | 2010-10-30 22:53:10 +0100 |
commit | 367a15f9c183467663342be14f8b5b00815bb9c9 (patch) | |
tree | 9d91e99c675d3380206e6ff6862b726f3ed0e705 | |
parent | 0b96fb8a331de08324d8367387b15dc053ea7d05 (diff) |
Make AIGLX work in non-toplevel windowsnontoplevelwin-aiglx
When needed, create a native child windows corresponding to the X
window hierarchy, so OpenGL drawing will take place into an appropriately
placed and sized native window.
Provide a new window class and wndproc for these child windows
(it appears they can't use the same one as toplevel windows for some reason)
Use WS_DISABLED style for these child windows, so they never gain input focus.
Use WS_EX_TRANSPARENT, so they don't obscure non-OpenGL drawing
Add isTopLevelWindow helper to identify when we are working on one of these child windows
When X maps, moves or reparents the child window, update the native window appropriately
-rw-r--r-- | hw/xwin/glx/winpriv.c | 40 | ||||
-rw-r--r-- | hw/xwin/win.h | 3 | ||||
-rw-r--r-- | hw/xwin/winmultiwindowwindow.c | 231 | ||||
-rw-r--r-- | hw/xwin/winmultiwindowwndproc.c | 39 | ||||
-rwxr-xr-x | hw/xwin/winwin32rootless.c | 2 | ||||
-rw-r--r-- | hw/xwin/winwindow.h | 1 |
6 files changed, 278 insertions, 38 deletions
diff --git a/hw/xwin/glx/winpriv.c b/hw/xwin/glx/winpriv.c index f29147b5b..72d65bc14 100644 --- a/hw/xwin/glx/winpriv.c +++ b/hw/xwin/glx/winpriv.c @@ -13,13 +13,47 @@ void winCreateWindowsWindow (WindowPtr pWin); + +static +void +winCreateWindowsWindowHierarchy(WindowPtr pWin) +{ + winWindowPriv(pWin); + + winDebug("winCreateWindowsWindowHierarchy - pWin:%08x XID:0x%x \n", pWin, pWin->drawable.id); + + /* recursively ensure parent window exists if it's not the root window */ + if (pWin->parent) + { + if (pWin->parent != pWin->drawable.pScreen->root) + winCreateWindowsWindowHierarchy(pWin->parent); + } + + /* ensure this window exists */ + if (pWinPriv->hWnd == NULL) + { + winCreateWindowsWindow(pWin); + + /* ... and if it's already been mapped, make sure it's visible */ + if (pWin->mapped) + { + /* Display the window without activating it */ + if (pWin->drawable.class != InputOnly) + ShowWindow (pWinPriv->hWnd, SW_SHOWNOACTIVATE); + + /* Send first paint message */ + UpdateWindow (pWinPriv->hWnd); + } + } +} + /** * Return size and handles of a window. * If pWin is NULL, then the information for the root window is requested. */ HWND winGetWindowInfo(WindowPtr pWin) { - winDebug("%s: pWin %p XID 0x%x\n", __FUNCTION__, pWin, pWin->drawable.id); + winTrace("%s: pWin %p XID 0x%x\n", __FUNCTION__, pWin, pWin->drawable.id); /* a real window was requested */ if (pWin != NULL) @@ -53,8 +87,8 @@ HWND winGetWindowInfo(WindowPtr pWin) if (pWinPriv->hWnd == NULL) { - winCreateWindowsWindow(pWin); - ErrorF("winGetWindowInfo: forcing window to exist...\n"); + ErrorF("winGetWindowInfo: forcing window to exist\n"); + winCreateWindowsWindowHierarchy(pWin); } if (pWinPriv->hWnd != NULL) diff --git a/hw/xwin/win.h b/hw/xwin/win.h index 8d0f41d70..0e8c76c93 100644 --- a/hw/xwin/win.h +++ b/hw/xwin/win.h @@ -1318,6 +1318,9 @@ winAdjustXWindow (WindowPtr pWin, HWND hwnd); LRESULT CALLBACK winTopLevelWindowProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); +LRESULT CALLBACK +winChildWindowProc (HWND hwnd, UINT message, + WPARAM wParam, LPARAM lParam); #endif diff --git a/hw/xwin/winmultiwindowwindow.c b/hw/xwin/winmultiwindowwindow.c index 62193e83f..f6cdf873e 100644 --- a/hw/xwin/winmultiwindowwindow.c +++ b/hw/xwin/winmultiwindowwindow.c @@ -65,10 +65,27 @@ winUpdateWindowsWindow (WindowPtr pWin); static void winFindWindow (pointer value, XID id, pointer cdata); +static Bool +isToplevelWindow(WindowPtr pWin) +{ + assert(pWin->parent); /* root window isn't expected here */ + + /* If the immediate parent is the root window, this is a top-level window */ + if ((pWin->parent) && (pWin->parent->parent == NULL)) + { + assert(pWin->parent == pWin->drawable.pScreen->root); + return TRUE; + } + + /* otherwise, a child window */ + return FALSE; +} + static void winInitMultiWindowClass(void) { static wATOM atomXWinClass=0; + static wATOM atomXWinChildClass = 0; WNDCLASSEX wcx; if (atomXWinClass==0) @@ -88,11 +105,34 @@ void winInitMultiWindowClass(void) wcx.hIconSm = g_hSmallIconX; #if CYGMULTIWINDOW_DEBUG - ErrorF ("winCreateWindowsWindow - Creating class: %s\n", WINDOW_CLASS_X); + ErrorF ("winInitMultiWindowClass - Creating class: %s\n", WINDOW_CLASS_X); #endif atomXWinClass = RegisterClassEx (&wcx); } + + if (atomXWinChildClass==0) + { + /* Setup our window class */ + wcx.cbSize=sizeof(WNDCLASSEX); + wcx.style = CS_HREDRAW | CS_VREDRAW | (g_fNativeGl ? CS_OWNDC : 0); + wcx.lpfnWndProc = winChildWindowProc; + wcx.cbClsExtra = 0; + wcx.cbWndExtra = 0; + wcx.hInstance = g_hInstance; + wcx.hIcon = g_hIconX; + wcx.hCursor = 0; + wcx.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH); + wcx.lpszMenuName = NULL; + wcx.lpszClassName = WINDOW_CLASS_X_CHILD; + wcx.hIconSm = g_hSmallIconX; + +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winInitMultiWindowClass - Creating class: %s\n", WINDOW_CLASS_X_CHILD); +#endif + + atomXWinChildClass = RegisterClassEx (&wcx); + } } /* @@ -207,6 +247,30 @@ winPositionWindowMultiWindow (WindowPtr pWin, int x, int y) return fResult; } + if (!isToplevelWindow(pWin)) + { + POINT parentOrigin; + + /* 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; + + /* Convert screen coordinates into client area co-ordinates of the parent */ + parentOrigin.x = 0; + parentOrigin.y = 0; + ClientToScreen(GetParent(hWnd), &parentOrigin); + + MoveWindow (hWnd, + iX - parentOrigin.x, iY - parentOrigin.y, iWidth, iHeight, + TRUE); + + return fResult; + } + /* Get the Windows window style and extended style */ dwExStyle = GetWindowLongPtr (hWnd, GWL_EXSTYLE); dwStyle = GetWindowLongPtr (hWnd, GWL_STYLE); @@ -487,13 +551,8 @@ winRestackWindowMultiWindow (WindowPtr pWin, WindowPtr pOldNextSib) #endif } - -/* - * winCreateWindowsWindow - Create a Windows window associated with an X window - */ - -void -winCreateWindowsWindow (WindowPtr pWin) +static void +winCreateWindowsTopLevelWindow (WindowPtr pWin) { int iX, iY; int iWidth; @@ -528,7 +587,7 @@ winCreateWindowsWindow (WindowPtr pWin) iY = CW_USEDEFAULT; } - winDebug("winCreateWindowsWindow - %dx%d @ %dx%d\n", iWidth, iHeight, iX, iY); + winDebug("winCreateWindowsTopLevelWindow - %dx%d @ %dx%d\n", iWidth, iHeight, iX, iY); if (winMultiWindowGetTransientFor (pWin, &pDaddy)) { @@ -571,7 +630,7 @@ winCreateWindowsWindow (WindowPtr pWin) iHeight = rc.bottom - rc.top; iWidth = rc.right - rc.left; - winDebug("winCreateWindowsWindow - %dx%d @ %dx%d\n", iWidth, iHeight, iX, iY); + winDebug("winCreateWindowsTopLevelWindow - %dx%d @ %dx%d\n", iWidth, iHeight, iX, iY); /* Create the window */ hWnd = CreateWindowExA (dwExStyle, /* Extended styles */ @@ -588,11 +647,13 @@ winCreateWindowsWindow (WindowPtr pWin) pWin); /* ScreenPrivates */ if (hWnd == NULL) { - ErrorF ("winCreateWindowsWindow - CreateWindowExA () failed: %d\n", + ErrorF ("winCreateWindowsTopLevelWindow - CreateWindowExA () failed: %d\n", (int) GetLastError ()); } pWinPriv->hWnd = hWnd; + winDebug("winCreateWindowsTopLevelWindow - hwnd 0x%08x\n", hWnd); + /* Set application or .XWinrc defined Icons */ winSelectIcons(pWin, &hIcon, &hIconSmall); if (hIcon) SendMessage (hWnd, WM_SETICON, ICON_BIG, (LPARAM) hIcon); @@ -621,6 +682,84 @@ winCreateWindowsWindow (WindowPtr pWin) (*pScreenPriv->pwinFinishCreateWindowsWindow) (pWin); } +static void +winCreateWindowsChildWindow(WindowPtr pWin) +{ + int iX, iY, iWidth, iHeight; + HWND hWnd; + WindowPtr pParent = pWin->parent; + DWORD dwStyle = WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_DISABLED; + DWORD dwExStyle = WS_EX_TRANSPARENT; + /* + WS_DISABLED means child window never gains the input focus, so only the + top-level window needs deal with passing input to the X server + + WS_EX_TRANSPARENT ensures that the contents of the top-level + Windows window (which will contain all non-OpenGL drawing for the hierarchy) + can be seen through any intermediate child windows which have nothing + drawn to them + */ + winPrivWinPtr pParentPriv, pWinPriv; + + winDebug("winCreateWindowsChildWindow - pWin:%08x XID:0x%x \n", pWin, pWin->drawable.id); + + winInitMultiWindowClass(); + + assert(pParent); + + pParentPriv = winGetWindowPriv(pParent); + pWinPriv = winGetWindowPriv(pWin); + + iX = pWin->drawable.x - pParent->drawable.x; + iY = pWin->drawable.y - pParent->drawable.y; + iWidth = pWin->drawable.width; + iHeight = pWin->drawable.height; + + winDebug("winCreateWindowsChildWindow - parent pWin:%08x XID:0x%08x hWnd:0x%08x\n", pParent, pParent->drawable.id, pParentPriv->hWnd); + winDebug("winCreateWindowsChildWindow - %dx%d @ %dx%d\n", iWidth, iHeight, iX, iY); + + /* Create the window */ + hWnd = CreateWindowExA (dwExStyle, /* Extended styles */ + WINDOW_CLASS_X_CHILD, /* Class name */ + WINDOW_TITLE_X, /* Window name */ + dwStyle, /* Styles */ + iX, /* Horizontal position */ + iY, /* Vertical position */ + iWidth, /* Right edge */ + iHeight, /* Bottom edge */ + pParentPriv->hWnd, /* parent window */ + (HMENU) NULL, /* No menu */ + GetModuleHandle(NULL),/* Instance handle */ + pWin); /* ScreenPrivates */ + if (hWnd == NULL) + { + ErrorF ("winCreateWindowsChildWindow - CreateWindowExA () failed: %d\n", + (int) GetLastError ()); + } + winDebug("winCreateWindowsChildWindow - hwnd 0x%08x\n", hWnd); + pWinPriv->hWnd = hWnd; + + SetProp(hWnd, WIN_WID_PROP, (HANDLE) winGetWindowID(pWin)); +} + +/* + * winCreateWindowsWindow - Create a Windows window associated with an X window + */ + +void +winCreateWindowsWindow (WindowPtr pWin) +{ + winDebug("winCreateWindowsWindow - pWin:%08x XID:0x%x \n", pWin, pWin->drawable.id); + + if (isToplevelWindow(pWin)) + { + winCreateWindowsTopLevelWindow(pWin); + } + else + { + winCreateWindowsChildWindow(pWin); + } +} Bool winInDestroyWindowsWindow = FALSE; /* @@ -689,36 +828,52 @@ static void winUpdateWindowsWindow (WindowPtr pWin) { winWindowPriv(pWin); - HWND hWnd = pWinPriv->hWnd; #if CYGMULTIWINDOW_DEBUG ErrorF ("winUpdateWindowsWindow\n"); #endif - /* Check if the Windows window's parents have been destroyed */ - if (pWin->parent != NULL - && pWin->parent->parent == NULL - && pWin->mapped) - { - /* Create the Windows window if it has been destroyed */ - if (hWnd == NULL) - { - winCreateWindowsWindow (pWin); - assert (pWinPriv->hWnd != NULL); - } - - /* Display the window without activating it */ - if (pWin->drawable.class != InputOnly) - ShowWindow (pWinPriv->hWnd, SW_SHOWNOACTIVATE); + /* Ignore the root window */ + if (pWin->parent == NULL) + return; - /* Send first paint message */ - UpdateWindow (pWinPriv->hWnd); - } - else if (hWnd != NULL) + /* If it's mapped */ + if (pWin->mapped) { - /* Destroy the Windows window if its parents are destroyed */ - winDestroyWindowsWindow (pWin); - assert (pWinPriv->hWnd == NULL); + /* If it's a top-level window */ + if (isToplevelWindow(pWin)) + { + /* Create the Windows window if needed */ + if (pWinPriv->hWnd == NULL) + { + winCreateWindowsWindow (pWin); + assert (pWinPriv->hWnd != NULL); + } + } + /* It's not a top-level window, but we created a window for GLX */ + else if (pWinPriv->hWnd) + { + winPrivWinPtr pParentPriv = winGetWindowPriv(pWin->parent); + + /* XXX: This really belongs in winReparentWindow ??? */ + /* XXX: this assumes parent window has been made to exist */ + assert(pParentPriv->hWnd); + + /* Ensure we have the correct parent and position if reparented */ + SetParent(pWinPriv->hWnd, pParentPriv->hWnd); + SetWindowPos(pWinPriv->hWnd, NULL, pWin->drawable.x - pWin->parent->drawable.x, pWin->drawable.y - pWin->parent->drawable.y, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW); + } + + /* If it's top level, or a GLX window which has already been created getting mapped, show it */ + if (pWinPriv->hWnd != NULL) + { + /* Display the window without activating it */ + if (pWin->drawable.class != InputOnly) + ShowWindow (pWinPriv->hWnd, SW_SHOWNOACTIVATE); + + /* Send first paint message */ + UpdateWindow (pWinPriv->hWnd); + } } #if CYGMULTIWINDOW_DEBUG @@ -966,6 +1121,14 @@ winAdjustXWindow (WindowPtr pWin, HWND hwnd) ErrorF ("winAdjustXWindow\n"); #endif + if (!isToplevelWindow(pWin)) + { +#if 1 + ErrorF ("winAdjustXWindow - immediately return because not a top-level window\n"); +#endif + return 0; + } + if (IsIconic (hwnd)) { #if CYGWINDOWING_DEBUG diff --git a/hw/xwin/winmultiwindowwndproc.c b/hw/xwin/winmultiwindowwndproc.c index b271ca7ad..6bdef6b6a 100644 --- a/hw/xwin/winmultiwindowwndproc.c +++ b/hw/xwin/winmultiwindowwndproc.c @@ -1126,3 +1126,42 @@ winTopLevelWindowProc (HWND hwnd, UINT message, winReorderWindowsMultiWindow(); return ret; } + +/* + * winChildWindowProc - Window procedure for all top-level Windows windows. + */ + +LRESULT CALLBACK +winChildWindowProc (HWND hwnd, UINT message, + WPARAM wParam, LPARAM lParam) +{ +#if CYGDEBUG + winDebugWin32Message("winChildWindowProc", hwnd, message, wParam, lParam); +#endif + + switch (message) + { + case WM_ERASEBKGND: + return TRUE; + + case WM_PAINT: + /* + We don't have the bits to draw into the window, they went straight into the OpenGL + surface + + 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... + */ + { + PAINTSTRUCT ps; + HDC hdcUpdate; + hdcUpdate = BeginPaint(hwnd, &ps); + ValidateRect(hwnd, &(ps.rcPaint)); + EndPaint(hwnd, &ps); + return 0; + } + /* XXX: this is exactly what DefWindowProc does? */ + } + + return DefWindowProc (hwnd, message, wParam, lParam); +} diff --git a/hw/xwin/winwin32rootless.c b/hw/xwin/winwin32rootless.c index 6a8d91c1e..f3105265e 100755 --- a/hw/xwin/winwin32rootless.c +++ b/hw/xwin/winwin32rootless.c @@ -284,7 +284,7 @@ winMWExtWMCreateFrame (RootlessWindowPtr pFrame, ScreenPtr pScreen, strcat (pszClass, pszWindowID); #if CYGMULTIWINDOW_DEBUG - winDebug ("winCreateWindowsWindow - Creating class: %s\n", pszClass); + winDebug ("winMWExtWMCreateFrame - Creating class: %s\n", pszClass); #endif /* Setup our window class */ diff --git a/hw/xwin/winwindow.h b/hw/xwin/winwindow.h index a6c8e05dd..d12f1d5ce 100644 --- a/hw/xwin/winwindow.h +++ b/hw/xwin/winwindow.h @@ -49,6 +49,7 @@ #define WINDOW_TITLE_XDMCP "%s:%s.%d" #define WIN_SCR_PROP "cyg_screen_prop rl" #define WINDOW_CLASS_X "cygwin/x X rl" +#define WINDOW_CLASS_X_CHILD "cygwin/x X child" #define WINDOW_TITLE_X PROJECT_NAME " X" #define WIN_WINDOW_PROP "cyg_window_prop_rl" #ifdef HAS_DEVWINDOWS |