hw/xwin: Push multiwindow wndproc WM_PAINT down into drawing engine

Push the multiwindow wndproc WM_PAINT handling down into the drawing
engine.  Only the GDI engine is supported in multiwindow mode currently,
so we only need to do this in the GDI engine.
This commit is contained in:
Jon Turney 2015-08-03 15:59:40 +01:00
parent 065f73353b
commit adebc376b9
4 changed files with 67 additions and 36 deletions

View File

@ -268,6 +268,8 @@ typedef Bool (*winFinishScreenInitProcPtr) (int, ScreenPtr, int, char **);
typedef Bool (*winBltExposedRegionsProcPtr) (ScreenPtr);
typedef Bool (*winBltExposedWindowRegionProcPtr) (ScreenPtr, WindowPtr);
typedef Bool (*winActivateAppProcPtr) (ScreenPtr);
typedef Bool (*winRedrawScreenProcPtr) (ScreenPtr pScreen);
@ -479,6 +481,7 @@ typedef struct _winPrivScreenRec {
winCreateBoundingWindowProcPtr pwinCreateBoundingWindow;
winFinishScreenInitProcPtr pwinFinishScreenInit;
winBltExposedRegionsProcPtr pwinBltExposedRegions;
winBltExposedWindowRegionProcPtr pwinBltExposedWindowRegion;
winActivateAppProcPtr pwinActivateApp;
winRedrawScreenProcPtr pwinRedrawScreen;
winRealizeInstalledPaletteProcPtr pwinRealizeInstalledPalette;

View File

@ -302,7 +302,6 @@ LRESULT CALLBACK
winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
POINT ptMouse;
HDC hdcUpdate;
PAINTSTRUCT ps;
WindowPtr pWin = NULL;
winPrivWinPtr pWinPriv = NULL;
@ -457,18 +456,9 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
case WM_PAINT:
/* Only paint if our window handle is valid */
if (hwndScreen == NULL)
if (hwnd == 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) {
/*
@ -478,36 +468,16 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
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...
*/
BeginPaint(hwnd, &ps);
ValidateRect(hwnd, &(ps.rcPaint));
EndPaint(hwnd, &ps);
}
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;
/* Call the engine dependent repainter */
if (*s_pScreenPriv->pwinBltExposedWindowRegion)
(*s_pScreenPriv->pwinBltExposedWindowRegion) (s_pScreen, pWin);
/* 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:

View File

@ -1201,6 +1201,7 @@ winSetEngineFunctionsShadowDDNL(ScreenPtr pScreen)
pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowWindowed;
pScreenPriv->pwinFinishScreenInit = winFinishScreenInitFB;
pScreenPriv->pwinBltExposedRegions = winBltExposedRegionsShadowDDNL;
pScreenPriv->pwinBltExposedWindowRegion = NULL;
pScreenPriv->pwinActivateApp = winActivateAppShadowDDNL;
pScreenPriv->pwinRedrawScreen = winRedrawScreenShadowDDNL;
pScreenPriv->pwinRealizeInstalledPalette

View File

@ -59,6 +59,9 @@ static Bool
static Bool
winBltExposedRegionsShadowGDI(ScreenPtr pScreen);
static Bool
winBltExposedWindowRegionShadowGDI(ScreenPtr pScreen, WindowPtr pWin);
static Bool
winActivateAppShadowGDI(ScreenPtr pScreen);
@ -801,6 +804,59 @@ winBltExposedRegionsShadowGDI(ScreenPtr pScreen)
return TRUE;
}
/*
* Blt exposed region to the given HWND
*/
static Bool
winBltExposedWindowRegionShadowGDI(ScreenPtr pScreen, WindowPtr pWin)
{
winScreenPriv(pScreen);
winPrivWinPtr pWinPriv = winGetWindowPriv(pWin);
HWND hWnd = pWinPriv->hWnd;
HDC hdcUpdate;
PAINTSTRUCT ps;
hdcUpdate = BeginPaint(hWnd, &ps);
/* Avoid the BitBlt if the PAINTSTRUCT region is bogus */
if (ps.rcPaint.right == 0 && ps.rcPaint.bottom == 0 &&
ps.rcPaint.left == 0 && ps.rcPaint.top == 0) {
EndPaint(hWnd, &ps);
return 0;
}
/* Try to copy from the shadow buffer to the invalidated region */
if (!BitBlt(hdcUpdate,
ps.rcPaint.left, ps.rcPaint.top,
ps.rcPaint.right - ps.rcPaint.left,
ps.rcPaint.bottom - ps.rcPaint.top,
pScreenPriv->hdcShadow,
ps.rcPaint.left + pWin->drawable.x,
ps.rcPaint.top + pWin->drawable.y,
SRCCOPY)) {
LPVOID lpMsgBuf;
/* Display an 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("winBltExposedWindowRegionShadowGDI - BitBlt failed: %s\n",
(LPSTR) lpMsgBuf);
LocalFree(lpMsgBuf);
}
/* EndPaint frees the DC */
EndPaint(hWnd, &ps);
return TRUE;
}
/*
* Do any engine-specific appliation-activation processing
*/
@ -1144,6 +1200,7 @@ winSetEngineFunctionsShadowGDI(ScreenPtr pScreen)
pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowWindowed;
pScreenPriv->pwinFinishScreenInit = winFinishScreenInitFB;
pScreenPriv->pwinBltExposedRegions = winBltExposedRegionsShadowGDI;
pScreenPriv->pwinBltExposedWindowRegion = winBltExposedWindowRegionShadowGDI;
pScreenPriv->pwinActivateApp = winActivateAppShadowGDI;
pScreenPriv->pwinRedrawScreen = winRedrawScreenShadowGDI;
pScreenPriv->pwinRealizeInstalledPalette =