hw/xwin: A simpleminded attempt at composition
Rather than drawing the window contents from the shadow framebuffer, use Composite extension redirection to cause the server to maintain a bitmap image of each top-level X window, and draw the window contents from that, so that window contents which are occluded in the framebuffer show correctly in the task bar and task switcher previews. v2: Fix incorrect use of memset() found by gcc5 hw/xwin/winshadgdi.c: In function ‘winBltExposedWindowRegionShadowGDI’: hw/xwin/winshadgdi.c:861:9: warning: ‘memset’ used with constant zero length parameter; this could be due to transposed parameters [-Wmemset-transposed-args] v3: Turn on -compositewm by default v4: Ignore -swcursor if -compositewm -swcursor is not compatible with -compositewm (because the window contents are drawn from an off-screen pixmap, not from the screen pixmap, where the software cursor will be drawn). v5: Update meson.build also Add -compositewm option to help output Update CI to install prerequisites
This commit is contained in:
parent
adebc376b9
commit
ebcea16e71
|
@ -50,6 +50,7 @@ libXmu-devel,\
|
|||
libXpm-devel,\
|
||||
libXrender-devel,\
|
||||
libXtst-devel,\
|
||||
libxcb-composite-devel,\
|
||||
libxcb-ewmh-devel,\
|
||||
libxcb-icccm-devel,\
|
||||
libxcb-image-devel,\
|
||||
|
|
|
@ -2081,7 +2081,7 @@ if test "x$XWIN" = xyes; then
|
|||
AC_DEFINE_UNQUOTED(__VENDORDWEBSUPPORT__, ["$VENDOR_WEB"], [Vendor web address for support])
|
||||
AC_CHECK_TOOL(WINDRES, windres)
|
||||
|
||||
PKG_CHECK_MODULES([XWINMODULES],[x11 xdmcp xau xfixes x11-xcb xcb-aux xcb-image xcb-ewmh xcb-icccm])
|
||||
PKG_CHECK_MODULES([XWINMODULES],[x11 xau xdmcp xfixes x11-xcb xcb-aux xcb-composite xcb-image xcb-ewmh xcb-icccm])
|
||||
|
||||
if test "x$WINDOWSDRI" = xauto; then
|
||||
PKG_CHECK_EXISTS([windowsdriproto], [WINDOWSDRI=yes], [WINDOWSDRI=no])
|
||||
|
|
|
@ -716,6 +716,11 @@ winUseMsg(void)
|
|||
"\tthe updated region when num_boxes, or more, are in the\n"
|
||||
"\tupdated region.\n");
|
||||
|
||||
ErrorF("-[no]compositewm\n"
|
||||
"\tUse the Composite extension to keep a bitmap image of each top-level\n"
|
||||
"\tX window, so window contents which are occluded show correctly in\n"
|
||||
"\ttask bar and task switcher previews.\n");
|
||||
|
||||
#ifdef XWIN_XF86CONFIG
|
||||
ErrorF("-config\n" "\tSpecify a configuration file.\n");
|
||||
|
||||
|
|
|
@ -170,6 +170,12 @@ on its own is equivalent to \fB\-resize=randr\fP
|
|||
Add the host name to the window title for X applications which are running
|
||||
on remote hosts, when that information is available and it's useful to do so.
|
||||
The default is enabled.
|
||||
.TP 8
|
||||
.B \-[no]compositewm
|
||||
Use Composite extension redirection to maintain a bitmap image of each top-level
|
||||
X window, so window contents which are occluded show correctly in task bar and
|
||||
task switcher previews.
|
||||
The default is enabled.
|
||||
|
||||
.SH OPTIONS CONTROLLING WINDOWS INTEGRATION
|
||||
.TP 8
|
||||
|
@ -206,6 +212,7 @@ The default is enabled.
|
|||
.TP 8
|
||||
.B \-swcursor
|
||||
Disable the usage of the \fIWindows\fP cursor and use the X11 software cursor instead.
|
||||
This option is ignored if \fB-compositewm\fP is also enabled.
|
||||
.TP 8
|
||||
.B \-[no]trayicon
|
||||
Do not create a tray icon. Default is to create one
|
||||
|
|
|
@ -137,6 +137,7 @@ xwin_dep = [
|
|||
dependency('xcb-image'),
|
||||
dependency('xcb-ewmh'),
|
||||
dependency('xcb-icccm'),
|
||||
dependency('xcb-composite'),
|
||||
]
|
||||
|
||||
executable(
|
||||
|
|
|
@ -391,6 +391,7 @@ typedef struct {
|
|||
Bool fDecoration;
|
||||
Bool fRootless;
|
||||
Bool fMultiWindow;
|
||||
Bool fCompositeWM;
|
||||
Bool fMultiMonitorOverride;
|
||||
Bool fMultipleMonitors;
|
||||
Bool fLessPointer;
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include <xcb/xcb_icccm.h>
|
||||
#include <xcb/xcb_ewmh.h>
|
||||
#include <xcb/xcb_aux.h>
|
||||
#include <xcb/composite.h>
|
||||
|
||||
#include <X11/Xwindows.h>
|
||||
|
||||
|
@ -116,6 +117,7 @@ typedef struct _WMInfo {
|
|||
xcb_atom_t atmUtf8String;
|
||||
xcb_atom_t atmNetWmName;
|
||||
xcb_ewmh_connection_t ewmh;
|
||||
Bool fCompositeWM;
|
||||
} WMInfoRec, *WMInfoPtr;
|
||||
|
||||
typedef struct _WMProcArgRec {
|
||||
|
@ -1038,6 +1040,8 @@ winMultiWindowXMsgProc(void *pArg)
|
|||
xcb_atom_t atmWindowState, atmMotifWmHints, atmWindowType, atmNormalHints;
|
||||
int iReturn;
|
||||
xcb_auth_info_t *auth_info;
|
||||
xcb_screen_t *root_screen;
|
||||
xcb_window_t root_window_id;
|
||||
|
||||
winDebug("winMultiWindowXMsgProc - Hello\n");
|
||||
|
||||
|
@ -1110,11 +1114,11 @@ winMultiWindowXMsgProc(void *pArg)
|
|||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
{
|
||||
/* Get root window id */
|
||||
xcb_screen_t *root_screen = xcb_aux_get_screen(pProcArg->conn, pProcArg->dwScreen);
|
||||
xcb_window_t root_window_id = root_screen->root;
|
||||
/* Get root window id */
|
||||
root_screen = xcb_aux_get_screen(pProcArg->conn, pProcArg->dwScreen);
|
||||
root_window_id = root_screen->root;
|
||||
|
||||
{
|
||||
/* Set WM_ICON_SIZE property indicating desired icon sizes */
|
||||
typedef struct {
|
||||
uint32_t min_width, min_height;
|
||||
|
@ -1152,6 +1156,41 @@ winMultiWindowXMsgProc(void *pArg)
|
|||
*/
|
||||
intern_atom(pProcArg->conn, "WM_STATE");
|
||||
|
||||
/*
|
||||
Enable Composite extension and redirect subwindows of the root window
|
||||
*/
|
||||
if (pProcArg->pWMInfo->fCompositeWM) {
|
||||
const char *extension_name = "Composite";
|
||||
xcb_query_extension_cookie_t cookie;
|
||||
xcb_query_extension_reply_t *reply;
|
||||
|
||||
cookie = xcb_query_extension(pProcArg->conn, strlen(extension_name), extension_name);
|
||||
reply = xcb_query_extension_reply(pProcArg->conn, cookie, NULL);
|
||||
|
||||
if (reply && (reply->present)) {
|
||||
xcb_composite_redirect_subwindows(pProcArg->conn,
|
||||
root_window_id,
|
||||
XCB_COMPOSITE_REDIRECT_AUTOMATIC);
|
||||
|
||||
/*
|
||||
We use automatic updating of the root window for two
|
||||
reasons:
|
||||
|
||||
1) redirected window contents are mirrored to the root
|
||||
window so that the root window draws correctly when shown.
|
||||
|
||||
2) updating the root window causes damage against the
|
||||
shadow framebuffer, which ultimately causes WM_PAINT to be
|
||||
sent to the affected window(s) to cause the damage regions
|
||||
to be redrawn.
|
||||
*/
|
||||
|
||||
ErrorF("Using Composite redirection\n");
|
||||
|
||||
free(reply);
|
||||
}
|
||||
}
|
||||
|
||||
/* Loop until we explicitly break out */
|
||||
while (1) {
|
||||
xcb_generic_event_t *event;
|
||||
|
@ -1351,7 +1390,7 @@ winInitWM(void **ppWMInfo,
|
|||
pthread_t * ptWMProc,
|
||||
pthread_t * ptXMsgProc,
|
||||
pthread_mutex_t * ppmServerStarted,
|
||||
int dwScreen, HWND hwndScreen)
|
||||
int dwScreen, HWND hwndScreen, Bool compositeWM)
|
||||
{
|
||||
WMProcArgPtr pArg = malloc(sizeof(WMProcArgRec));
|
||||
WMInfoPtr pWMInfo = malloc(sizeof(WMInfoRec));
|
||||
|
@ -1373,6 +1412,7 @@ winInitWM(void **ppWMInfo,
|
|||
|
||||
/* Set a return pointer to the Window Manager info structure */
|
||||
*ppWMInfo = pWMInfo;
|
||||
pWMInfo->fCompositeWM = compositeWM;
|
||||
|
||||
/* Setup the argument structure for the thread function */
|
||||
pArg->dwScreen = dwScreen;
|
||||
|
|
|
@ -128,6 +128,7 @@ winInitializeScreenDefaults(void)
|
|||
defaultScreenInfo.fDecoration = TRUE;
|
||||
defaultScreenInfo.fRootless = FALSE;
|
||||
defaultScreenInfo.fMultiWindow = FALSE;
|
||||
defaultScreenInfo.fCompositeWM = TRUE;
|
||||
defaultScreenInfo.fMultiMonitorOverride = FALSE;
|
||||
defaultScreenInfo.fMultipleMonitors = FALSE;
|
||||
defaultScreenInfo.fLessPointer = FALSE;
|
||||
|
@ -571,6 +572,25 @@ ddxProcessArgument(int argc, char *argv[], int i)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look for the '-compositewm' argument
|
||||
*/
|
||||
if (IS_OPTION("-compositewm")) {
|
||||
screenInfoPtr->fCompositeWM = TRUE;
|
||||
|
||||
/* Indicate that we have processed this argument */
|
||||
return 1;
|
||||
}
|
||||
/*
|
||||
* Look for the '-nocompositewm' argument
|
||||
*/
|
||||
if (IS_OPTION("-nocompositewm")) {
|
||||
screenInfoPtr->fCompositeWM = FALSE;
|
||||
|
||||
/* Indicate that we have processed this argument */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look for the '-multiplemonitors' argument
|
||||
*/
|
||||
|
|
|
@ -461,6 +461,11 @@ winFinishScreenInitFB(int i, ScreenPtr pScreen, int argc, char **argv)
|
|||
|
||||
|
||||
if (pScreenInfo->fMultiWindow) {
|
||||
if ((pScreenInfo->dwBPP == 8) && (pScreenInfo->fCompositeWM)) {
|
||||
ErrorF("-compositewm disabled due to 8bpp depth\n");
|
||||
pScreenInfo->fCompositeWM = FALSE;
|
||||
}
|
||||
|
||||
#if CYGDEBUG || YES
|
||||
winDebug("winFinishScreenInitFB - Calling winInitWM.\n");
|
||||
#endif
|
||||
|
@ -471,7 +476,8 @@ winFinishScreenInitFB(int i, ScreenPtr pScreen, int argc, char **argv)
|
|||
&pScreenPriv->ptXMsgProc,
|
||||
&pScreenPriv->pmServerStarted,
|
||||
pScreenInfo->dwScreen,
|
||||
(HWND) &pScreenPriv->hwndScreen)) {
|
||||
(HWND) &pScreenPriv->hwndScreen,
|
||||
pScreenInfo->fCompositeWM)) {
|
||||
ErrorF("winFinishScreenInitFB - winInitWM () failed.\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
|
|
@ -826,6 +826,70 @@ winBltExposedWindowRegionShadowGDI(ScreenPtr pScreen, WindowPtr pWin)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef COMPOSITE
|
||||
if (pWin->redirectDraw != RedirectDrawNone) {
|
||||
HBITMAP hBitmap;
|
||||
HDC hdcPixmap;
|
||||
PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin);
|
||||
|
||||
/*
|
||||
This is kind of clunky, and possibly not very efficient.
|
||||
|
||||
Would it be more efficient to only create the DIB bitmap when the
|
||||
composite bitmap is realloced and store it in a window private?
|
||||
|
||||
But we still end up copying and converting all the bits from the
|
||||
window pixmap into a DDB for every update.
|
||||
|
||||
Perhaps better still would be to wrap the screen CreatePixmap routine
|
||||
so it uses CreateDIBSection()?
|
||||
*/
|
||||
|
||||
BITMAPV4HEADER bmih;
|
||||
memset(&bmih, 0, sizeof(bmih));
|
||||
bmih.bV4Size = sizeof(BITMAPV4HEADER);
|
||||
bmih.bV4Width = pPixmap->drawable.width;
|
||||
bmih.bV4Height = -pPixmap->drawable.height; /* top-down bitmap */
|
||||
bmih.bV4Planes = 1;
|
||||
bmih.bV4BitCount = pPixmap->drawable.bitsPerPixel;
|
||||
bmih.bV4SizeImage = 0;
|
||||
/* window pixmap format is the same as the screen pixmap */
|
||||
assert(pPixmap->drawable.bitsPerPixel > 8);
|
||||
bmih.bV4V4Compression = BI_BITFIELDS;
|
||||
bmih.bV4RedMask = pScreenPriv->dwRedMask;
|
||||
bmih.bV4GreenMask = pScreenPriv->dwGreenMask;
|
||||
bmih.bV4BlueMask = pScreenPriv->dwBlueMask;
|
||||
bmih.bV4AlphaMask = 0;
|
||||
|
||||
/* Create the window bitmap from the pixmap */
|
||||
hBitmap = CreateDIBitmap(pScreenPriv->hdcScreen,
|
||||
(BITMAPINFOHEADER *)&bmih, CBM_INIT,
|
||||
pPixmap->devPrivate.ptr, (BITMAPINFO *)&bmih,
|
||||
DIB_RGB_COLORS);
|
||||
|
||||
/* Select the window bitmap into a screen-compatible DC */
|
||||
hdcPixmap = CreateCompatibleDC(pScreenPriv->hdcScreen);
|
||||
SelectObject(hdcPixmap, hBitmap);
|
||||
|
||||
/* Blt from the window bitmap 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,
|
||||
hdcPixmap,
|
||||
ps.rcPaint.left + pWin->borderWidth,
|
||||
ps.rcPaint.top + pWin->borderWidth,
|
||||
SRCCOPY))
|
||||
ErrorF("winBltExposedWindowRegionShadowGDI - BitBlt failed: 0x%08x\n",
|
||||
GetLastError());
|
||||
|
||||
/* Release */
|
||||
DeleteDC(hdcPixmap);
|
||||
DeleteObject(hBitmap);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* Try to copy from the shadow buffer to the invalidated region */
|
||||
if (!BitBlt(hdcUpdate,
|
||||
ps.rcPaint.left, ps.rcPaint.top,
|
||||
|
@ -850,6 +914,7 @@ winBltExposedWindowRegionShadowGDI(ScreenPtr pScreen, WindowPtr pWin)
|
|||
(LPSTR) lpMsgBuf);
|
||||
LocalFree(lpMsgBuf);
|
||||
}
|
||||
}
|
||||
|
||||
/* EndPaint frees the DC */
|
||||
EndPaint(hWnd, &ps);
|
||||
|
|
|
@ -155,6 +155,14 @@ winValidateArgs(void)
|
|||
"-scrollbars, -resize, -nodecoration, or -lesspointer.\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Ignore -swcursor if -multiwindow -compositewm is requested */
|
||||
if (g_ScreenInfo[i].fMultiWindow && g_ScreenInfo[i].fCompositeWM) {
|
||||
if (g_fSoftwareCursor) {
|
||||
g_fSoftwareCursor = FALSE;
|
||||
winMsg(X_WARNING, "Ignoring -swcursor due to -compositewm\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
winDebug("winValidateArgs - Returning.\n");
|
||||
|
|
|
@ -144,7 +144,7 @@ winInitWM(void **ppWMInfo,
|
|||
pthread_t * ptWMProc,
|
||||
pthread_t * ptXMsgProc,
|
||||
pthread_mutex_t * ppmServerStarted,
|
||||
int dwScreen, HWND hwndScreen);
|
||||
int dwScreen, HWND hwndScreen, Bool compositeWM);
|
||||
|
||||
void
|
||||
winDeinitMultiWindowWM(void);
|
||||
|
|
Loading…
Reference in New Issue