diff options
Diffstat (limited to 'hw/xwin/winmultiwindowwindow.c')
-rw-r--r-- | hw/xwin/winmultiwindowwindow.c | 604 |
1 files changed, 535 insertions, 69 deletions
diff --git a/hw/xwin/winmultiwindowwindow.c b/hw/xwin/winmultiwindowwindow.c index 4ec5634af..c2d144447 100644 --- a/hw/xwin/winmultiwindowwindow.c +++ b/hw/xwin/winmultiwindowwindow.c @@ -57,11 +57,27 @@ static void static void winFindWindow(void *value, XID id, void *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) { @@ -85,11 +101,40 @@ winInitMultiWindowClass(void) wcx.hIconSm = hIconSmall; #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) { + HICON hIcon, hIconSmall; + + /* Load the default icons */ + winSelectIcons(&hIcon, &hIconSmall); + + /* 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 = hIcon; + wcx.hCursor = 0; + wcx.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); + wcx.lpszMenuName = NULL; + wcx.lpszClassName = WINDOW_CLASS_X_CHILD; + wcx.hIconSm = hIconSmall; + +#if CYGMULTIWINDOW_DEBUG + ErrorF("winInitMultiWindowClass - Creating class: %s\n", + WINDOW_CLASS_X_CHILD); +#endif + + atomXWinChildClass = RegisterClassEx(&wcx); + } } /* @@ -157,32 +202,16 @@ winDestroyWindowMultiWindow(WindowPtr pWin) /* * PositionWindow - See Porting Layer Definition - p. 37 - * - * This function adjusts the position and size of Windows window - * with respect to the underlying X window. This is the inverse - * of winAdjustXWindow, which adjusts X window to Windows window. */ Bool winPositionWindowMultiWindow(WindowPtr pWin, int x, int y) { Bool fResult = TRUE; - int iX, iY, iWidth, iHeight; ScreenPtr pScreen = pWin->drawable.pScreen; - winWindowPriv(pWin); winScreenPriv(pScreen); - HWND hWnd = pWinPriv->hWnd; - RECT rcNew; - RECT rcOld; - -#if CYGMULTIWINDOW_DEBUG - RECT rcClient; - RECT *lpRc; -#endif - DWORD dwExStyle; - DWORD dwStyle; #if CYGMULTIWINDOW_DEBUG winTrace("winPositionWindowMultiWindow - pWin: %p\n", pWin); @@ -204,6 +233,59 @@ winPositionWindowMultiWindow(WindowPtr pWin, int x, int y) return fResult; } + /* + We can't call MoveWindow() here, because that sends messages and pumps the + message queue, which could re-entrantly call ConfigureWindow(), which + would be bad..., so instead just send a message to cause MoveWindow() to + be called. + */ + PostMessage(hWnd, WM_ASYNCMOVE, 0, 0); + + return fResult; +} + +/* + * This function adjusts the position and size of Windows window + * with respect to the underlying X window. This is the inverse + * of winAdjustXWindow, which adjusts X window to Windows window. + */ +void +winAdjustWindowsWindow(WindowPtr pWin, HWND hWnd) +{ + int iX, iY, iWidth, iHeight; + RECT rcNew; + RECT rcOld; + +#if CYGMULTIWINDOW_DEBUG + RECT rcClient; + RECT *lpRc; +#endif + DWORD dwExStyle; + DWORD dwStyle; + + 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; + } + /* Get the Windows window style and extended style */ dwExStyle = GetWindowLongPtr(hWnd, GWL_EXSTYLE); dwStyle = GetWindowLongPtr(hWnd, GWL_STYLE); @@ -268,11 +350,9 @@ winPositionWindowMultiWindow(WindowPtr pWin, int x, int y) } else { #if CYGMULTIWINDOW_DEBUG - ErrorF("winPositionWindowMultiWindow - Not need to move\n"); + ErrorF("winPositionWindowMultiWindow - No need to move\n"); #endif } - - return fResult; } /* @@ -473,12 +553,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; @@ -519,8 +595,8 @@ winCreateWindowsWindow(WindowPtr pWin) } } - 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, &daddyId)) { if (daddyId) { @@ -534,17 +610,33 @@ winCreateWindowsWindow(WindowPtr pWin) } } else { - /* Default positions if none specified */ - if (!winMultiWindowGetWMNormalHints(pWin, &hints)) - hints.flags = 0; - if (!(hints.flags & (USPosition | PPosition)) && - !pWin->overrideRedirect) { - iX = CW_USEDEFAULT; - iY = CW_USEDEFAULT; + if (!pWin->overrideRedirect) { + /* Default positions if none specified */ + if (!winMultiWindowGetWMNormalHints(pWin, &hints)) + hints.flags = 0; + + if ((hints.flags & USPosition) || + ((hints.flags & PPosition) && + ((pWin->drawable.x - pWin->borderWidth != 0) || + (pWin->drawable.y - pWin->borderWidth != 0)))) { + /* + Always respect user specified position, respect program + specified position if it's not the origin + */ + } + else { + /* Use default position */ + iX = CW_USEDEFAULT; + iY = CW_USEDEFAULT; + } } } - /* Make it WS_OVERLAPPED in create call since WS_POPUP doesn't support */ + winDebug("winCreateWindowsTopLevelWindow - %dx%d @ %dx%d\n", iWidth, + iHeight, iX, iY); + + /* Create the window */ + /* Make it OVERLAPPED in create call since WS_POPUP doesn't support */ /* CW_USEDEFAULT, change back to popup after creation */ dwStyle = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS; dwExStyle = WS_EX_TOOLWINDOW; @@ -582,11 +674,14 @@ winCreateWindowsWindow(WindowPtr pWin) GetModuleHandle(NULL), /* Instance handle */ pWin); /* ScreenPrivates */ if (hWnd == NULL) { - ErrorF("winCreateWindowsWindow - CreateWindowExA () failed: %d\n", - (int) GetLastError()); + ErrorF + ("winCreateWindowsTopLevelWindow - CreateWindowExA () failed: %d\n", + (int) GetLastError()); } pWinPriv->hWnd = hWnd; + winDebug("winCreateWindowsTopLevelWindow - hwnd 0x%p\n", hWnd); + /* Change style back to popup, already placed... */ SetWindowLongPtr(hWnd, GWL_STYLE, WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS); @@ -597,18 +692,113 @@ winCreateWindowsWindow(WindowPtr pWin) /* Adjust the X window to match the window placement we actually got... */ winAdjustXWindow(pWin, hWnd); - /* Make sure it gets the proper system menu for a WS_POPUP, too */ - GetSystemMenu(hWnd, TRUE); - - /* Cause any .XWinrc menus to be added in main WNDPROC */ - PostMessage(hWnd, WM_INIT_SYS_MENU, 0, 0); - SetProp(hWnd, WIN_WID_PROP, (HANDLE) (INT_PTR) winGetWindowID(pWin)); /* Flag that this Windows window handles its own activation */ SetProp(hWnd, WIN_NEEDMANAGE_PROP, (HANDLE) 0); } +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:%p XID:0x%x\n", pWin, + (unsigned int)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:%p XID:0x%08x hWnd:0x%p\n", + pParent, (unsigned int)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%p\n", hWnd); + pWinPriv->hWnd = hWnd; + + SetProp(hWnd, WIN_WID_PROP, (HANDLE) (INT_PTR) winGetWindowID(pWin)); +} + +/* + * winCreateWindowsWindow - Create a Windows window associated with an X window + */ + +void +winCreateWindowsWindow(WindowPtr pWin) +{ + winDebug("winCreateWindowsWindow - pWin:%p XID:0x%x \n", pWin, + (unsigned int)pWin->drawable.id); + + if (isToplevelWindow(pWin)) { + winCreateWindowsTopLevelWindow(pWin); + } + else { + winCreateWindowsChildWindow(pWin); + } +} + +static int +winDestroyChildWindowsWindow(WindowPtr pWin, void *data) +{ + winWindowPriv(pWin); + + winDebug("winDestroyChildWindowsWindow - pWin:%p XID:0x%x \n", pWin, + (unsigned int)pWin->drawable.id); + + /* Null our handle to the Window so referencing it will cause an error */ + pWinPriv->hWnd = NULL; + +#ifdef XWIN_GLX_WINDOWS + /* No longer note WGL used on this window */ + pWinPriv->fWglUsed = FALSE; +#endif + + return WT_WALKCHILDREN; /* continue enumeration */ +} + Bool winInDestroyWindowsWindow = FALSE; /* @@ -624,6 +814,7 @@ winDestroyWindowsWindow(WindowPtr pWin) BOOL oldstate = winInDestroyWindowsWindow; HICON hIcon; HICON hIconSm; + HWND hWnd; winDebug("winDestroyWindowsWindow - pWin:%p XID:0x%x \n", pWin, (unsigned int)pWin->drawable.id); @@ -638,21 +829,20 @@ winDestroyWindowsWindow(WindowPtr pWin) hIcon = (HICON) SendMessage(pWinPriv->hWnd, WM_GETICON, ICON_BIG, 0); hIconSm = (HICON) SendMessage(pWinPriv->hWnd, WM_GETICON, ICON_SMALL, 0); - /* Destroy the Windows window */ - DestroyWindow(pWinPriv->hWnd); + hWnd = pWinPriv->hWnd; - /* Null our handle to the Window so referencing it will cause an error */ - pWinPriv->hWnd = NULL; + /* DestroyWindow() implicitly destroys all child windows, + so first walk over the child tree of this window, clearing + any hWnds */ + TraverseTree(pWin, winDestroyChildWindowsWindow, 0); + + /* Destroy the Windows window */ + DestroyWindow(hWnd); /* Destroy any icons we created for this window */ winDestroyIcon(hIcon); winDestroyIcon(hIconSm); -#ifdef XWIN_GLX_WINDOWS - /* No longer note WGL used on this window */ - pWinPriv->fWglUsed = FALSE; -#endif - /* Process all messages on our queue */ while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if (g_hDlgDepthChange == 0 || !IsDialogMessage(g_hDlgDepthChange, &msg)) { @@ -674,29 +864,43 @@ 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); + /* If it's mapped */ + if (pWin->mapped) { + /* 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); + } } - else if (hWnd != NULL) { - /* Destroy the Windows window if its parents are destroyed */ + else if (pWinPriv->hWnd != NULL) { + /* If it's been reparented to an unmapped window when previously mapped, destroy the Windows window */ winDestroyWindowsWindow(pWin); assert(pWinPriv->hWnd == NULL); } @@ -883,6 +1087,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 ErrorF("\timmediately return because the window is iconized\n"); @@ -960,3 +1172,257 @@ winAdjustXWindow(WindowPtr pWin, HWND hwnd) #undef WIDTH #undef HEIGHT } + +/* + Helper function + */ +static HBITMAP winCreateDIB(ScreenPtr pScreen, int width, int height, int bpp, void **ppvBits, BITMAPINFOHEADER **ppbmih) +{ + winScreenPriv(pScreen); + BITMAPV4HEADER *pbmih = NULL; + HBITMAP hBitmap = NULL; + + /* Allocate bitmap info header */ + pbmih = malloc(sizeof(BITMAPV4HEADER) + 256 * sizeof(RGBQUAD)); + if (pbmih == NULL) { + ErrorF("winCreateDIB: malloc() failed\n"); + return NULL; + } + memset(pbmih, 0, sizeof(BITMAPV4HEADER) + 256 * sizeof(RGBQUAD)); + + /* Describe bitmap to be created */ + pbmih->bV4Size = sizeof(BITMAPV4HEADER); + pbmih->bV4Width = width; + pbmih->bV4Height = -height; /* top-down bitmap */ + pbmih->bV4Planes = 1; + pbmih->bV4BitCount = bpp; + if (bpp == 1) { + RGBQUAD *bmiColors = (RGBQUAD *)((char *)pbmih + sizeof(BITMAPV4HEADER)); + pbmih->bV4V4Compression = BI_RGB; + bmiColors[1].rgbBlue = 255; + bmiColors[1].rgbGreen = 255; + bmiColors[1].rgbRed = 255; + } + else if (bpp == 8) { + pbmih->bV4V4Compression = BI_RGB; + pbmih->bV4ClrUsed = 0; + } + else if (bpp == 16) { + pbmih->bV4V4Compression = BI_RGB; + pbmih->bV4ClrUsed = 0; + } + else if (bpp == 32) { + pbmih->bV4V4Compression = BI_BITFIELDS; + pbmih->bV4RedMask = pScreenPriv->dwRedMask; + pbmih->bV4GreenMask = pScreenPriv->dwGreenMask; + pbmih->bV4BlueMask = pScreenPriv->dwBlueMask; + pbmih->bV4AlphaMask = 0; + } + else { + ErrorF("winCreateDIB: %d bpp unhandled\n", bpp); + } + + /* Create a DIB with a bit pointer */ + hBitmap = CreateDIBSection(NULL, + (BITMAPINFO *) pbmih, + DIB_RGB_COLORS, ppvBits, NULL, 0); + if (hBitmap == NULL) { + ErrorF("winCreateDIB: CreateDIBSection() failed\n"); + return NULL; + } + + /* Store the address of the BMIH in the ppbmih parameter */ + *ppbmih = (BITMAPINFOHEADER *)pbmih; + + winDebug("winCreateDIB: HBITMAP %p pBMIH %p pBits %p\n", hBitmap, pbmih, *ppvBits); + + return hBitmap; +} + + +/* + * CreatePixmap - See Porting Layer Definition + */ +PixmapPtr +winCreatePixmapMultiwindow(ScreenPtr pScreen, int width, int height, int depth, + unsigned usage_hint) +{ + winPrivPixmapPtr pPixmapPriv = NULL; + PixmapPtr pPixmap = NULL; + int bpp, paddedwidth; + + /* allocate Pixmap header and privates */ + pPixmap = AllocatePixmap(pScreen, 0); + if (!pPixmap) + return NullPixmap; + + bpp = BitsPerPixel(depth); + /* + DIBs have 4-byte aligned rows + + paddedwidth is the width in bytes, padded to align + + i.e. round up the number of bits used by a row so it is a multiple of 32, + then convert to bytes + */ + paddedwidth = (((bpp * width) + 31) & ~31)/8; + + /* setup Pixmap header */ + pPixmap->drawable.type = DRAWABLE_PIXMAP; + pPixmap->drawable.class = 0; + pPixmap->drawable.pScreen = pScreen; + pPixmap->drawable.depth = depth; + pPixmap->drawable.bitsPerPixel = bpp; + pPixmap->drawable.id = 0; + pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + pPixmap->drawable.x = 0; + pPixmap->drawable.y = 0; + pPixmap->drawable.width = width; + pPixmap->drawable.height = height; + pPixmap->devKind = paddedwidth; + pPixmap->refcnt = 1; + pPixmap->devPrivate.ptr = NULL; // later set to pbBits + pPixmap->master_pixmap = NULL; +#ifdef COMPOSITE + pPixmap->screen_x = 0; + pPixmap->screen_y = 0; +#endif + pPixmap->usage_hint = usage_hint; + + /* Check for zero width or height pixmaps */ + if (width == 0 || height == 0) { + /* DIBs with a dimension of 0 aren't permitted, so don't try to allocate + a DIB, just set fields and return */ + return pPixmap; + } + + /* Initialize pixmap privates */ + pPixmapPriv = winGetPixmapPriv(pPixmap); + pPixmapPriv->hBitmap = NULL; + pPixmapPriv->pbBits = NULL; + pPixmapPriv->pbmih = NULL; + + /* Create a DIB for the pixmap */ + pPixmapPriv->hBitmap = winCreateDIB(pScreen, width, height, bpp, &pPixmapPriv->pbBits, &pPixmapPriv->pbmih); + + winDebug("winCreatePixmap: pPixmap %p HBITMAP %p pBMIH %p pBits %p\n", pPixmap, pPixmapPriv->hBitmap, pPixmapPriv->pbmih, pPixmapPriv->pbBits); + /* XXX: so why do we need this in privates ??? */ + pPixmap->devPrivate.ptr = pPixmapPriv->pbBits; + + return pPixmap; +} + +/* + * DestroyPixmap - See Porting Layer Definition + */ +Bool +winDestroyPixmapMultiwindow(PixmapPtr pPixmap) +{ + winPrivPixmapPtr pPixmapPriv = NULL; + + /* Bail early if there is not a pixmap to destroy */ + if (pPixmap == NULL) { + return TRUE; + } + + /* Decrement reference count, return if nonzero */ + --pPixmap->refcnt; + if (pPixmap->refcnt != 0) + return TRUE; + + winDebug("winDestroyPixmap: pPixmap %p\n", pPixmap); + + /* Get a handle to the pixmap privates */ + pPixmapPriv = winGetPixmapPriv(pPixmap); + + /* Free GDI bitmap */ + if (pPixmapPriv->hBitmap) + DeleteObject(pPixmapPriv->hBitmap); + + /* Free the bitmap info header memory */ + free(pPixmapPriv->pbmih); + pPixmapPriv->pbmih = NULL; + + /* Free the pixmap memory */ + free(pPixmap); + pPixmap = NULL; + + return TRUE; +} + +/* + * ModifyPixmapHeader - See Porting Layer Definition + */ +Bool +winModifyPixmapHeaderMultiwindow(PixmapPtr pPixmap, + int width, + int height, + int depth, + int bitsPerPixel, int devKind, void *pPixData) +{ + int i; + winPrivPixmapPtr pPixmapPriv = NULL; + Bool fResult; + + /* reinitialize everything */ + pPixmap->drawable.depth = depth; + pPixmap->drawable.bitsPerPixel = bitsPerPixel; + pPixmap->drawable.id = 0; + pPixmap->drawable.x = 0; + pPixmap->drawable.y = 0; + pPixmap->drawable.width = width; + pPixmap->drawable.height = height; + pPixmap->devKind = devKind; + pPixmap->refcnt = 1; + pPixmap->devPrivate.ptr = pPixData; + pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + + /* + This can be used for some out-of-order initialization on the screen + pixmap, which is the only case we can properly support. + */ + + /* Look for which screen this pixmap corresponds to */ + for (i = 0; i < screenInfo.numScreens; i++) { + ScreenPtr pScreen = screenInfo.screens[i]; + winScreenPriv(pScreen); + winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; + + if (pScreenInfo->pfb == pPixData) + { + /* and initialize pixmap privates from screen privates */ + pPixmapPriv = winGetPixmapPriv(pPixmap); + + pPixmapPriv->hBitmap = pScreenPriv->hbmpShadow; + pPixmapPriv->pbBits = pScreenInfo->pfb; + pPixmapPriv->pbmih = pScreenPriv->pbmih; + + /* XXX: need to mark these not to get released in DestroyPixmap */ + + return TRUE; + } + } + + /* Otherwise, since creating a DIBSection from arbitrary memory is not + * possible, fallback to normal. Later we can create a DIBSection with a + * copy of the bits, if needed. */ + { + pPixmapPriv = winGetPixmapPriv(pPixmap); + + pPixmapPriv->hBitmap = 0; + pPixmapPriv->pbBits = 0; + pPixmapPriv->pbmih = 0; + } + + winDebug("winModifyPixmapHeaderMultiwindow: falling back\n"); + + { + ScreenPtr pScreen = pPixmap->drawable.pScreen; + winScreenPriv(pScreen); + WIN_UNWRAP(ModifyPixmapHeader); + fResult = (*pScreen->ModifyPixmapHeader) (pPixmap, width, height, depth, bitsPerPixel, devKind, pPixData); + WIN_WRAP(ModifyPixmapHeader, winModifyPixmapHeaderMultiwindow); + } + + return fResult; +} |