/*
 *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:	Dakshinamurthy Karra
 *		Suhaib M Siddiqi
 *		Peter Busch
 *		Harold L Hunt II
 */

#ifdef HAVE_XWIN_CONFIG_H
#include <xwin-config.h>
#endif
#include "win.h"

/*
 * Local function prototypes
 */

static Bool
 winAllocateFBPrimaryDD(ScreenPtr pScreen);

static Bool
 winCloseScreenPrimaryDD(int nIndex, ScreenPtr pScreen);

static Bool
 winInitVisualsPrimaryDD(ScreenPtr pScreen);

static Bool
 winAdjustVideoModePrimaryDD(ScreenPtr pScreen);

static Bool
 winActivateAppPrimaryDD(ScreenPtr pScreen);

static Bool
 winHotKeyAltTabPrimaryDD(ScreenPtr pScreen);

/*
 * Create a DirectDraw primary surface 
 */

static Bool
winAllocateFBPrimaryDD(ScreenPtr pScreen)
{
    winScreenPriv(pScreen);
    winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
    HRESULT ddrval = DD_OK;
    DDSURFACEDESC ddsd;
    DDSURFACEDESC *pddsdPrimary = NULL;
    DDSURFACEDESC *pddsdOffscreen = NULL;
    RECT rcClient;

    winDebug ("winAllocateFBPrimaryDD\n");

    /* Get client area location in screen coords */
    GetClientRect(pScreenPriv->hwndScreen, &rcClient);
    MapWindowPoints(pScreenPriv->hwndScreen,
                    HWND_DESKTOP, (LPPOINT) & rcClient, 2);

    /* Create a DirectDraw object, store the address at lpdd */
    ddrval = (*g_fpDirectDrawCreate) (NULL, &pScreenPriv->pdd, NULL);
    if (ddrval != DD_OK)
        FatalError("winAllocateFBPrimaryDD - Could not start DirectDraw\n");

    /* Get a DirectDraw2 interface pointer */
    ddrval = IDirectDraw_QueryInterface(pScreenPriv->pdd,
                                        &IID_IDirectDraw2,
                                        (LPVOID *) & pScreenPriv->pdd2);
    if (FAILED(ddrval)) {
        ErrorF("winAllocateFBShadowDD - Failed DD2 query: %08x\n",
               (unsigned int) ddrval);
        return FALSE;
    }

    winDebug ("winAllocateFBPrimaryDD - Created and initialized DD\n");

    /* Are we windowed or fullscreen? */
    if (pScreenInfo->fFullScreen) {
        /* Full screen mode */
        ddrval = IDirectDraw2_SetCooperativeLevel(pScreenPriv->pdd2,
                                                  pScreenPriv->hwndScreen,
                                                  DDSCL_FULLSCREEN
                                                  | DDSCL_EXCLUSIVE);
        if (FAILED(ddrval))
            FatalError("winAllocateFBPrimaryDD - Could not set "
                       "cooperative level\n");

        /* Change the video mode to the mode requested */
        ddrval = IDirectDraw2_SetDisplayMode(pScreenPriv->pdd2,
                                             pScreenInfo->dwWidth,
                                             pScreenInfo->dwHeight,
                                             pScreenInfo->dwBPP,
                                             pScreenInfo->dwRefreshRate, 0);
        if (FAILED(ddrval))
            FatalError("winAllocateFBPrimaryDD - Could not set "
                       "full screen display mode\n");
    }
    else {
        /* Windowed mode */
        ddrval = IDirectDraw2_SetCooperativeLevel(pScreenPriv->pdd2,
                                                  pScreenPriv->hwndScreen,
                                                  DDSCL_NORMAL);
        if (FAILED(ddrval))
            FatalError("winAllocateFBPrimaryDD - Could not set "
                       "cooperative level\n");
    }

    /* Describe the primary surface */
    ZeroMemory(&ddsd, sizeof(ddsd));
    ddsd.dwSize = sizeof(ddsd);
    ddsd.dwFlags = DDSD_CAPS;
    ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;

    /* Create the primary surface */
    ddrval = IDirectDraw2_CreateSurface(pScreenPriv->pdd2,
                                        &ddsd, &pScreenPriv->pddsPrimary, NULL);
    if (FAILED(ddrval))
        FatalError("winAllocateFBPrimaryDD - Could not create primary "
                   "surface %08x\n", (unsigned int) ddrval);

    winDebug ("winAllocateFBPrimaryDD - Created primary\n");

    /* Allocate a DD surface description for our screen privates */
    pddsdPrimary = pScreenPriv->pddsdPrimary = malloc(sizeof(DDSURFACEDESC));
    if (pddsdPrimary == NULL)
        FatalError("winAllocateFBPrimaryDD - Could not allocate surface "
                   "description memory\n");
    ZeroMemory(pddsdPrimary, sizeof(*pddsdPrimary));
    pddsdPrimary->dwSize = sizeof(*pddsdPrimary);

    /* Describe the offscreen surface to be created */
    /*
     * NOTE: Do not use a DDSCAPS_VIDEOMEMORY surface,
     * as drawing, locking, and unlocking take forever
     * with video memory surfaces.  In addition,
     * video memory is a somewhat scarce resource,
     * so you shouldn't be allocating video memory when
     * you have the option of using system memory instead.
     */
    ZeroMemory(&ddsd, sizeof(ddsd));
    ddsd.dwSize = sizeof(ddsd);
    ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
    ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
    ddsd.dwHeight = pScreenInfo->dwHeight;
    ddsd.dwWidth = pScreenInfo->dwWidth;

    /* Create the shadow surface */
    ddrval = IDirectDraw2_CreateSurface(pScreenPriv->pdd2,
                                        &ddsd,
                                        &pScreenPriv->pddsOffscreen, NULL);
    if (ddrval != DD_OK)
        FatalError("winAllocateFBPrimaryDD - Could not create shadow "
                   "surface\n");

    winDebug ("winAllocateFBPrimaryDD - Created offscreen\n");

    /* Allocate a DD surface description for our screen privates */
    pddsdOffscreen = pScreenPriv->pddsdOffscreen
        = malloc(sizeof(DDSURFACEDESC));
    if (pddsdOffscreen == NULL)
        FatalError("winAllocateFBPrimaryDD - Could not allocate surface "
                   "description memory\n");
    ZeroMemory(pddsdOffscreen, sizeof(*pddsdOffscreen));
    pddsdOffscreen->dwSize = sizeof(*pddsdOffscreen);

    winDebug ("winAllocateFBPrimaryDD - Locking primary\n");

    /* Lock the primary surface */
    ddrval = IDirectDrawSurface2_Lock(pScreenPriv->pddsPrimary,
                                      pScreenInfo->
                                      fFullScreen ? NULL : &rcClient,
                                      pddsdPrimary, DDLOCK_WAIT, NULL);
    if (ddrval != DD_OK || pddsdPrimary->lpSurface == NULL)
        FatalError("winAllocateFBPrimaryDD - Could not lock "
                   "primary surface\n");

    winDebug ("winAllocateFBPrimaryDD - Locked primary\n");

    /* We don't know how to deal with anything other than RGB */
    if (!(pddsdPrimary->ddpfPixelFormat.dwFlags & DDPF_RGB))
        FatalError("winAllocateFBPrimaryDD - Color format other than RGB\n");

    /* Grab the pitch from the surface desc */
    pScreenInfo->dwStride = (pddsdPrimary->u1.lPitch * 8)
        / pScreenInfo->dwBPP;

    /* Save the pointer to our surface memory */
    pScreenInfo->pfb = pddsdPrimary->lpSurface;

    /* Grab the color depth and masks from the surface description */
    pScreenPriv->dwRedMask = pddsdPrimary->ddpfPixelFormat.u2.dwRBitMask;
    pScreenPriv->dwGreenMask = pddsdPrimary->ddpfPixelFormat.u3.dwGBitMask;
    pScreenPriv->dwBlueMask = pddsdPrimary->ddpfPixelFormat.u4.dwBBitMask;

    winDebug ("winAllocateFBPrimaryDD - Returning\n");

    return TRUE;
}

static void
winFreeFBPrimaryDD(ScreenPtr pScreen)
{
    winScreenPriv(pScreen);
    winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;

    /* Free the offscreen surface, if there is one */
    if (pScreenPriv->pddsOffscreen) {
        IDirectDrawSurface2_Unlock(pScreenPriv->pddsOffscreen, NULL);
        IDirectDrawSurface2_Release(pScreenPriv->pddsOffscreen);
        pScreenPriv->pddsOffscreen = NULL;
    }

    /* Release the primary surface, if there is one */
    if (pScreenPriv->pddsPrimary) {
        IDirectDrawSurface2_Unlock(pScreenPriv->pddsPrimary, NULL);
        IDirectDrawSurface2_Release(pScreenPriv->pddsPrimary);
        pScreenPriv->pddsPrimary = NULL;
    }

    /* Free the DirectDraw object, if there is one */
    if (pScreenPriv->pdd) {
        IDirectDraw2_RestoreDisplayMode(pScreenPriv->pdd);
        IDirectDraw2_Release(pScreenPriv->pdd);
        pScreenPriv->pdd = NULL;
    }

    /* Invalidate the ScreenInfo's fb pointer */
    pScreenInfo->pfb = NULL;
}

static Bool
winInitScreenPrimaryDD(ScreenPtr pScreen)
{
    return winAllocateFBPrimaryDD(pScreen);
}

/*
 * Call the wrapped CloseScreen function.
 * 
 * Free our resources and private structures.
 */

static Bool
winCloseScreenPrimaryDD(int nIndex, ScreenPtr pScreen)
{
    winScreenPriv(pScreen);
    winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
    Bool fReturn;

    ErrorF("winCloseScreenPrimaryDD - Freeing screen resources\n");

    /* Flag that the screen is closed */
    pScreenPriv->fClosed = TRUE;
    pScreenPriv->fActive = FALSE;

    /* Call the wrapped CloseScreen procedure */
    WIN_UNWRAP(CloseScreen);
    if (pScreen->CloseScreen)
        fReturn = (*pScreen->CloseScreen) (nIndex, pScreen);

    /* Delete the window property */
    RemoveProp(pScreenPriv->hwndScreen, WIN_SCR_PROP);

    winFreeFBPrimaryDD(pScreen);

    /* Delete tray icon, if we have one */
    if (!pScreenInfo->fNoTrayIcon)
        winDeleteNotifyIcon(pScreenPriv);

    /* Free the exit confirmation dialog box, if it exists */
    if (g_hDlgExit != NULL) {
        DestroyWindow(g_hDlgExit);
        g_hDlgExit = NULL;
    }

    /* Kill our window */
    if (pScreenPriv->hwndScreen) {
        DestroyWindow(pScreenPriv->hwndScreen);
        pScreenPriv->hwndScreen = NULL;
    }

    /* Kill our screeninfo's pointer to the screen */
    pScreenInfo->pScreen = NULL;

    /* Free the screen privates for this screen */
    free((pointer) pScreenPriv);

    return fReturn;
}

/*
 * Tell mi what sort of visuals we need.
 * 
 * Generally we only need one visual, as our screen can only
 * handle one format at a time, I believe.  You may want
 * to verify that last sentence.
 */

static Bool
winInitVisualsPrimaryDD(ScreenPtr pScreen)
{
    winScreenPriv(pScreen);
    winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
    DWORD dwRedBits, dwGreenBits, dwBlueBits;

    /* Count the number of ones in each color mask */
    dwRedBits = winCountBits(pScreenPriv->dwRedMask);
    dwGreenBits = winCountBits(pScreenPriv->dwGreenMask);
    dwBlueBits = winCountBits(pScreenPriv->dwBlueMask);

    /* Store the maximum number of ones in a color mask as the bitsPerRGB */
    if (dwRedBits > dwGreenBits && dwRedBits > dwBlueBits)
        pScreenPriv->dwBitsPerRGB = dwRedBits;
    else if (dwGreenBits > dwRedBits && dwGreenBits > dwBlueBits)
        pScreenPriv->dwBitsPerRGB = dwGreenBits;
    else
        pScreenPriv->dwBitsPerRGB = dwBlueBits;

    winDebug ("winInitVisualsPrimaryDD - Masks: %08x %08x %08x bpRGB: %d\n",
              (unsigned int) pScreenPriv->dwRedMask,
              (unsigned int) pScreenPriv->dwGreenMask,
              (unsigned int) pScreenPriv->dwBlueMask,
              (int) pScreenPriv->dwBitsPerRGB);

    /* Create a single visual according to the Windows screen depth */
    switch (pScreenInfo->dwDepth) {
    case 24:
    case 16:
    case 15:
        if (!miSetVisualTypesAndMasks(pScreenInfo->dwDepth,
                                      TrueColorMask,
                                      pScreenPriv->dwBitsPerRGB,
                                      TrueColor,
                                      pScreenPriv->dwRedMask,
                                      pScreenPriv->dwGreenMask,
                                      pScreenPriv->dwBlueMask)) {
            ErrorF("winInitVisualsPrimaryDD - "
                   "miSetVisualTypesAndMasks failed\n");
            return FALSE;
        }
        break;

    case 8:
        winDebug("winInitVisuals - Calling miSetVisualTypesAndMasks\n");
        if (!miSetVisualTypesAndMasks(pScreenInfo->dwDepth,
                                      PseudoColorMask,
                                      pScreenPriv->dwBitsPerRGB,
                                      PseudoColor,
                                      pScreenPriv->dwRedMask,
                                      pScreenPriv->dwGreenMask,
                                      pScreenPriv->dwBlueMask)) {
            ErrorF("winInitVisualsPrimaryDD - "
                   "miSetVisualTypesAndMasks failed\n");
            return FALSE;
        }
        winDebug("winInitVisualsPrimaryDD - Returned from "
                 "miSetVisualTypesAndMasks\n");
        break;

    default:
        ErrorF("winInitVisualsPrimaryDD - Unknown screen depth\n");
        return FALSE;
    }

    winDebug ("winInitVisualsPrimaryDD - Returning\n");

    return TRUE;
}

static Bool
winAdjustVideoModePrimaryDD(ScreenPtr pScreen)
{
    winScreenPriv(pScreen);
    winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
    HDC hdc = NULL;
    DWORD dwBPP;

    /* We're in serious trouble if we can't get a DC */
    hdc = GetDC(NULL);
    if (hdc == NULL) {
        ErrorF("winAdjustVideoModePrimaryDD - GetDC failed\n");
        return FALSE;
    }

    /* Query GDI for current display depth */
    dwBPP = GetDeviceCaps(hdc, BITSPIXEL);

    /* DirectDraw can only change the depth in fullscreen mode */
    if (!(pScreenInfo->fFullScreen && (pScreenInfo->dwBPP != WIN_DEFAULT_BPP))) {
        /* Otherwise, We'll use GDI's depth */
        pScreenInfo->dwBPP = dwBPP;
    }

    /* Release our DC */
    ReleaseDC(NULL, hdc);

    return TRUE;
}

/*
 * We need to blit our offscreen fb to
 * the screen when we are activated, and we need to point
 * the fb code back to the primary surface memory.
 */

static Bool
winActivateAppPrimaryDD(ScreenPtr pScreen)
{
    winScreenPriv(pScreen);
    RECT rcSrc, rcClient;
    HRESULT ddrval = DD_OK;

    /* Check for errors */
    if (pScreenPriv == NULL
        || pScreenPriv->pScreenInfo == NULL
        || pScreenPriv->pddsPrimary == NULL
        || pScreenPriv->pddsOffscreen == NULL)
        return FALSE;

    /* Check for do-nothing */
    if (!pScreenPriv->fActive)
        return TRUE;

    /* We are activating */
    ddrval = IDirectDrawSurface2_IsLost(pScreenPriv->pddsOffscreen);
    if (ddrval == DD_OK) {
        IDirectDrawSurface2_Unlock(pScreenPriv->pddsOffscreen, NULL);
        /*
         * We don't check for an error from Unlock, because it
         * doesn't matter if the Unlock failed.
         */
    }

    /* Restore both surfaces, just cause I like it that way */
    IDirectDrawSurface2_Restore(pScreenPriv->pddsOffscreen);
    IDirectDrawSurface2_Restore(pScreenPriv->pddsPrimary);

    /* Get client area in screen coords */
    GetClientRect(pScreenPriv->hwndScreen, &rcClient);
    MapWindowPoints(pScreenPriv->hwndScreen,
                    HWND_DESKTOP, (LPPOINT) & rcClient, 2);

    /* Setup a source rectangle */
    rcSrc.left = 0;
    rcSrc.top = 0;
    rcSrc.right = pScreenPriv->pScreenInfo->dwWidth;
    rcSrc.bottom = pScreenPriv->pScreenInfo->dwHeight;

    ddrval = IDirectDrawSurface2_Blt(pScreenPriv->pddsPrimary,
                                     &rcClient,
                                     pScreenPriv->pddsOffscreen,
                                     &rcSrc, DDBLT_WAIT, NULL);
    if (ddrval != DD_OK)
        FatalError("winActivateAppPrimaryDD () - Failed blitting offscreen "
                   "surface to primary surface %08x\n", (unsigned int) ddrval);

    /* Lock the primary surface */
    ddrval = IDirectDrawSurface2_Lock(pScreenPriv->pddsPrimary,
                                      &rcClient,
                                      pScreenPriv->pddsdPrimary,
                                      DDLOCK_WAIT, NULL);
    if (ddrval != DD_OK || pScreenPriv->pddsdPrimary->lpSurface == NULL)
        FatalError("winActivateAppPrimaryDD () - Could not lock "
                   "primary surface\n");

    /* Notify FB of the new memory pointer */
    winUpdateFBPointer(pScreen, pScreenPriv->pddsdPrimary->lpSurface);

    /*
     * Register the Alt-Tab combo as a hotkey so we can copy
     * the primary framebuffer before the display mode changes
     */
    RegisterHotKey(pScreenPriv->hwndScreen, 1, MOD_ALT, 9);

    return TRUE;
}

/*
 * Handle the Alt+Tab hotkey.
 *
 * We need to save the primary fb to an offscreen fb when
 * we get deactivated, and point the fb code at the offscreen
 * fb for the duration of the deactivation.
 */

static Bool
winHotKeyAltTabPrimaryDD(ScreenPtr pScreen)
{
    winScreenPriv(pScreen);
    winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
    RECT rcClient, rcSrc;
    HRESULT ddrval = DD_OK;

    winDebug ("\nwinHotKeyAltTabPrimaryDD\n\n");

    /* Alt+Tab was pressed, we will lose focus very soon */
    pScreenPriv->fActive = FALSE;

    /* Check for error conditions */
    if (pScreenPriv->pddsPrimary == NULL || pScreenPriv->pddsOffscreen == NULL)
        return FALSE;

    /* Get client area in screen coords */
    GetClientRect(pScreenPriv->hwndScreen, &rcClient);
    MapWindowPoints(pScreenPriv->hwndScreen,
                    HWND_DESKTOP, (LPPOINT) & rcClient, 2);

    /* Did we loose the primary surface? */
    ddrval = IDirectDrawSurface2_IsLost(pScreenPriv->pddsPrimary);
    if (ddrval == DD_OK) {
        ddrval = IDirectDrawSurface2_Unlock(pScreenPriv->pddsPrimary, NULL);
        if (FAILED(ddrval))
            FatalError("winHotKeyAltTabPrimaryDD - Failed unlocking primary "
                       "surface\n");
    }

    /* Setup a source rectangle */
    rcSrc.left = 0;
    rcSrc.top = 0;
    rcSrc.right = pScreenInfo->dwWidth;
    rcSrc.bottom = pScreenInfo->dwHeight;

    /* Blit the primary surface to the offscreen surface */
    ddrval = IDirectDrawSurface2_Blt(pScreenPriv->pddsOffscreen, NULL,  /* should be rcDest */
                                     pScreenPriv->pddsPrimary,
                                     NULL, DDBLT_WAIT, NULL);
    if (ddrval == DDERR_SURFACELOST) {
        IDirectDrawSurface2_Restore(pScreenPriv->pddsOffscreen);
        IDirectDrawSurface2_Restore(pScreenPriv->pddsPrimary);

        /* Blit the primary surface to the offscreen surface */
        ddrval = IDirectDrawSurface2_Blt(pScreenPriv->pddsOffscreen,
                                         NULL,
                                         pScreenPriv->pddsPrimary,
                                         NULL, DDBLT_WAIT, NULL);
        if (FAILED(ddrval))
            FatalError("winHotKeyAltTabPrimaryDD - Failed blitting primary "
                       "surface to offscreen surface: %08x\n",
                       (unsigned int) ddrval);
    }
    else {
        FatalError("winHotKeyAltTabPrimaryDD - Unknown error from "
                   "Blt: %08dx\n", (unsigned int) ddrval);
    }

    /* Lock the offscreen surface */
    ddrval = IDirectDrawSurface2_Lock(pScreenPriv->pddsOffscreen,
                                      NULL,
                                      pScreenPriv->pddsdOffscreen,
                                      DDLOCK_WAIT, NULL);
    if (ddrval != DD_OK || pScreenPriv->pddsdPrimary->lpSurface == NULL)
        FatalError("winHotKeyAltTabPrimaryDD - Could not lock "
                   "offscreen surface\n");

    /* Notify FB of the new memory pointer */
    winUpdateFBPointer(pScreen, pScreenPriv->pddsdOffscreen->lpSurface);

    /* Unregister our hotkey */
    UnregisterHotKey(pScreenPriv->hwndScreen, 1);

    return TRUE;
}

/* Set engine specific functions */
Bool
winSetEngineFunctionsPrimaryDD(ScreenPtr pScreen)
{
    winScreenPriv(pScreen);
    winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;

    /* Set our pointers */
    pScreenPriv->pwinAllocateFB = winAllocateFBPrimaryDD;
    pScreenPriv->pwinFreeFB = winFreeFBPrimaryDD;
    pScreenPriv->pwinShadowUpdate =
        (winShadowUpdateProcPtr) (void (*)(void)) NoopDDA;
    pScreenPriv->pwinInitScreen = winInitScreenPrimaryDD;
    pScreenPriv->pwinCloseScreen = winCloseScreenPrimaryDD;
    pScreenPriv->pwinInitVisuals = winInitVisualsPrimaryDD;
    pScreenPriv->pwinAdjustVideoMode = winAdjustVideoModePrimaryDD;
    if (pScreenInfo->fFullScreen)
        pScreenPriv->pwinCreateBoundingWindow =
            winCreateBoundingWindowFullScreen;
    else
        pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowWindowed;
    pScreenPriv->pwinFinishScreenInit = winFinishScreenInitFB;
    pScreenPriv->pwinBltExposedRegions =
        (winBltExposedRegionsProcPtr) (void (*)(void)) NoopDDA;
    pScreenPriv->pwinActivateApp = winActivateAppPrimaryDD;
    pScreenPriv->pwinRedrawScreen = NULL;
    pScreenPriv->pwinRealizeInstalledPalette = NULL;
    pScreenPriv->pwinInstallColormap = NULL;
    pScreenPriv->pwinStoreColors = NULL;
    pScreenPriv->pwinCreateColormap = NULL;
    pScreenPriv->pwinDestroyColormap = NULL;
    pScreenPriv->pwinHotKeyAltTab = winHotKeyAltTabPrimaryDD;
    pScreenPriv->pwinCreatePrimarySurface =
        (winCreatePrimarySurfaceProcPtr) (void (*)(void)) NoopDDA;
    pScreenPriv->pwinReleasePrimarySurface =
        (winReleasePrimarySurfaceProcPtr) (void (*)(void)) NoopDDA;
#ifdef XWIN_MULTIWINDOW
    pScreenPriv->pwinFinishCreateWindowsWindow =
        (winFinishCreateWindowsWindowProcPtr) (void (*)(void)) NoopDDA;
#endif

    return TRUE;
}