diff --git a/.appveyor.yml b/.appveyor.yml index dd244b8db..50072acd4 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -50,6 +50,7 @@ libXmu-devel,\ libXpm-devel,\ libXrender-devel,\ libXtst-devel,\ +libxcb-composite-devel,\ libxcb-ewmh-devel,\ libxcb-icccm-devel,\ libxcb-image-devel,\ diff --git a/Xi/xipassivegrab.c b/Xi/xipassivegrab.c index 65d5870f6..d30f51f3c 100644 --- a/Xi/xipassivegrab.c +++ b/Xi/xipassivegrab.c @@ -203,8 +203,14 @@ ProcXIPassiveGrabDevice(ClientPtr client) ¶m, XI2, &mask); break; case XIGrabtypeKeycode: - status = GrabKey(client, dev, mod_dev, stuff->detail, - ¶m, XI2, &mask); + /* XI2 allows 32-bit keycodes but thanks to XKB we can never + * implement this. Just return an error for all keycodes that + * cannot work anyway */ + if (stuff->detail > 255) + status = XIAlreadyGrabbed; + else + status = GrabKey(client, dev, mod_dev, stuff->detail, + ¶m, XI2, &mask); break; case XIGrabtypeEnter: case XIGrabtypeFocusIn: diff --git a/config/udev.c b/config/udev.c index 314acba6c..6e11aa3b8 100644 --- a/config/udev.c +++ b/config/udev.c @@ -474,7 +474,7 @@ config_udev_odev_setup_attribs(struct udev_device *udev_device, const char *path config_odev_probe_proc_ptr probe_callback) { struct OdevAttributes *attribs = config_odev_allocate_attributes(); - const char *value; + const char *value, *str; attribs->path = XNFstrdup(path); attribs->syspath = XNFstrdup(syspath); @@ -482,8 +482,8 @@ config_udev_odev_setup_attribs(struct udev_device *udev_device, const char *path attribs->minor = minor; value = udev_device_get_property_value(udev_device, "ID_PATH"); - if (value && !strncmp(value, "pci-", 4)) { - attribs->busid = XNFstrdup(value); + if (value && (str = strstr(value, "pci-"))) { + attribs->busid = XNFstrdup(str); attribs->busid[3] = ':'; } diff --git a/configure.ac b/configure.ac index 5055d271d..9148b94f4 100644 --- a/configure.ac +++ b/configure.ac @@ -159,7 +159,8 @@ dnl Checks for library functions. AC_CHECK_FUNCS([backtrace geteuid getuid issetugid getresuid \ getdtablesize getifaddrs getpeereid getpeerucred getprogname getzoneid \ mmap posix_fallocate seteuid shmctl64 strncasecmp vasprintf vsnprintf \ - walkcontext setitimer poll epoll_create1 mkostemp memfd_create]) + walkcontext setitimer poll epoll_create1 mkostemp memfd_create \ + sigprocmask]) AC_CONFIG_LIBOBJ_DIR([os]) AC_REPLACE_FUNCS([reallocarray strcasecmp strcasestr strlcat strlcpy strndup\ timingsafe_memcmp]) @@ -753,7 +754,7 @@ DAMAGEPROTO="damageproto >= 1.1" XCMISCPROTO="xcmiscproto >= 1.2.0" BIGREQSPROTO="bigreqsproto >= 1.1.0" XTRANS="xtrans >= 1.3.5" -PRESENTPROTO="presentproto >= 1.1" +PRESENTPROTO="presentproto >= 1.2" dnl List of libraries that require a specific version LIBAPPLEWM="applewm >= 1.4" @@ -791,6 +792,11 @@ if test "x$HAVE_RECURSIVE_MUTEX" = "xyes" ; then THREAD_DEFAULT=yes fi +case $host_os in + mingw*) THREAD_DEFAULT=no ;; + *) +esac + AC_ARG_ENABLE(input-thread, AS_HELP_STRING([--enable-input-thread], [Enable input threads]), [INPUTTHREAD=$enableval], [INPUTTHREAD=$THREAD_DEFAULT]) @@ -2075,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]) diff --git a/doc/c-extensions b/doc/c-extensions index e5fde3440..7dc58a215 100644 --- a/doc/c-extensions +++ b/doc/c-extensions @@ -62,7 +62,7 @@ TODO: Solaris. TODO: *BSD. -Windows-dependent code assumes at least NT 5.1. +Windows-dependent code assumes at least NT 6.0. OSX support is generally limited to the most recent version. Currently that means 10.5. diff --git a/glamor/glamor.c b/glamor/glamor.c index eee44c25d..4b935de59 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -99,7 +99,7 @@ glamor_set_pixmap_type(PixmapPtr pixmap, glamor_pixmap_type_t type) glamor_init_pixmap_private_small(pixmap, pixmap_priv); } -_X_EXPORT void +_X_EXPORT Bool glamor_set_pixmap_texture(PixmapPtr pixmap, unsigned int tex) { ScreenPtr screen = pixmap->drawable.pScreen; @@ -121,10 +121,12 @@ glamor_set_pixmap_texture(PixmapPtr pixmap, unsigned int tex) if (fbo == NULL) { ErrorF("XXX fail to create fbo.\n"); - return; + return FALSE; } glamor_pixmap_attach_fbo(pixmap, fbo); + + return TRUE; } uint32_t diff --git a/glamor/glamor.h b/glamor/glamor.h index 8d79597e2..c972694e3 100644 --- a/glamor/glamor.h +++ b/glamor/glamor.h @@ -110,7 +110,7 @@ extern _X_EXPORT Bool glamor_close_screen(ScreenPtr screen); extern _X_EXPORT uint32_t glamor_get_pixmap_texture(PixmapPtr pixmap); -extern _X_EXPORT void glamor_set_pixmap_texture(PixmapPtr pixmap, +extern _X_EXPORT Bool glamor_set_pixmap_texture(PixmapPtr pixmap, unsigned int tex); extern _X_EXPORT void glamor_set_pixmap_type(PixmapPtr pixmap, diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index 69844d4e2..693bee6cf 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -367,8 +367,8 @@ glamor_make_pixmap_exportable(PixmapPtr pixmap, Bool modifiers_ok) return TRUE; } -struct gbm_bo * -glamor_gbm_bo_from_pixmap(ScreenPtr screen, PixmapPtr pixmap) +static struct gbm_bo * +glamor_gbm_bo_from_pixmap_internal(ScreenPtr screen, PixmapPtr pixmap) { struct glamor_egl_screen_private *glamor_egl = glamor_egl_get_screen_private(xf86ScreenToScrn(screen)); @@ -382,6 +382,15 @@ glamor_gbm_bo_from_pixmap(ScreenPtr screen, PixmapPtr pixmap) pixmap_priv->image, 0); } +struct gbm_bo * +glamor_gbm_bo_from_pixmap(ScreenPtr screen, PixmapPtr pixmap) +{ + if (!glamor_make_pixmap_exportable(pixmap, TRUE)) + return NULL; + + return glamor_gbm_bo_from_pixmap_internal(screen, pixmap); +} + int glamor_egl_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds, uint32_t *strides, uint32_t *offsets, @@ -397,7 +406,7 @@ glamor_egl_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds, if (!glamor_make_pixmap_exportable(pixmap, TRUE)) return 0; - bo = glamor_gbm_bo_from_pixmap(screen, pixmap); + bo = glamor_gbm_bo_from_pixmap_internal(screen, pixmap); if (!bo) return 0; @@ -435,7 +444,7 @@ glamor_egl_fd_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, if (!glamor_make_pixmap_exportable(pixmap, FALSE)) return -1; - bo = glamor_gbm_bo_from_pixmap(screen, pixmap); + bo = glamor_gbm_bo_from_pixmap_internal(screen, pixmap); if (!bo) return -1; @@ -464,7 +473,7 @@ glamor_egl_fd_name_from_pixmap(ScreenPtr screen, if (!glamor_make_pixmap_exportable(pixmap, FALSE)) goto failure; - bo = glamor_gbm_bo_from_pixmap(screen, pixmap); + bo = glamor_gbm_bo_from_pixmap_internal(screen, pixmap); if (!bo) goto failure; diff --git a/glamor/glamor_transform.c b/glamor/glamor_transform.c index 348d00be1..11a08f7f6 100644 --- a/glamor/glamor_transform.c +++ b/glamor/glamor_transform.c @@ -158,7 +158,7 @@ glamor_set_solid(PixmapPtr pixmap, return FALSE; } } - glamor_set_color(pixmap, gc->fgPixel, uniform); + glamor_set_color(pixmap, pixel, uniform); return TRUE; } diff --git a/glx/glxcmds.c b/glx/glxcmds.c index 54d452e58..6af050940 100644 --- a/glx/glxcmds.c +++ b/glx/glxcmds.c @@ -765,7 +765,7 @@ __glXDisp_WaitGL(__GLXclientState * cl, GLbyte * pc) glFinish(); } - if (glxc && glxc->drawPriv->waitGL) + if (glxc && glxc->drawPriv && glxc->drawPriv->waitGL) (*glxc->drawPriv->waitGL) (glxc->drawPriv); return Success; @@ -789,7 +789,7 @@ __glXDisp_WaitX(__GLXclientState * cl, GLbyte * pc) return error; } - if (glxc && glxc->drawPriv->waitX) + if (glxc && glxc->drawPriv && glxc->drawPriv->waitX) (*glxc->drawPriv->waitX) (glxc->drawPriv); return Success; diff --git a/glx/vndcmds.c b/glx/vndcmds.c index f0779d14a..21c6fef9e 100644 --- a/glx/vndcmds.c +++ b/glx/vndcmds.c @@ -468,15 +468,24 @@ void GlxDispatchReset(void) int GlxDispatchRequest(ClientPtr client) { REQUEST(xReq); + int result; + if (GlxExtensionEntry->base == 0) return BadRequest; + + GlxSetRequestClient(client); + if (stuff->data < OPCODE_ARRAY_LEN) { if (dispatchFuncs[stuff->data] == NULL) { // Try to find a dispatch stub. dispatchFuncs[stuff->data] = GetVendorDispatchFunc(stuff->data, 0); } - return dispatchFuncs[stuff->data](client); + result = dispatchFuncs[stuff->data](client); } else { - return dispatch_GLXSingle(client); + result = dispatch_GLXSingle(client); } + + GlxSetRequestClient(NULL); + + return result; } diff --git a/glx/vndext.c b/glx/vndext.c index d7936467b..0513733b6 100644 --- a/glx/vndext.c +++ b/glx/vndext.c @@ -139,8 +139,17 @@ GlxGetClientData(ClientPtr client) { GlxClientPriv *cl = xglvGetClientPrivate(client); if (cl == NULL) { - cl = calloc(1, sizeof(GlxClientPriv)); + cl = calloc(1, sizeof(GlxClientPriv) + + screenInfo.numScreens * sizeof(GlxServerVendor *)); if (cl != NULL) { + int i; + + cl->vendors = (GlxServerVendor **) (cl + 1); + for (i=0; ivendors[i] = GlxGetVendorForScreen(NULL, screenInfo.screens[i]); + } + xglvSetClientPrivate(client, cl); } } @@ -295,8 +304,8 @@ GlxFreeServerImports(GlxServerImports *imports) } _X_EXPORT const GlxServerExports glxServer = { - .majorVersion = 0, - .minorVersion = 0, + .majorVersion = GLXSERVER_VENDOR_ABI_MAJOR_VERSION, + .minorVersion = GLXSERVER_VENDOR_ABI_MINOR_VERSION, .extensionInitCallback = &vndInitCallbackListPtr, @@ -315,6 +324,7 @@ _X_EXPORT const GlxServerExports glxServer = { .getContextTagPrivate = GlxGetContextTagPrivate, .getVendorForScreen = GlxGetVendorForScreen, .forwardRequest = GlxForwardRequest, + .setClientScreenVendor = GlxSetClientScreenVendor, }; const GlxServerExports * diff --git a/glx/vndserver.h b/glx/vndserver.h index a175656ae..772b458a1 100644 --- a/glx/vndserver.h +++ b/glx/vndserver.h @@ -57,6 +57,11 @@ typedef struct GlxContextTagInfoRec { typedef struct GlxClientPrivRec { GlxContextTagInfo *contextTags; unsigned int contextTagCount; + + /** + * The vendor handles for each screen. + */ + GlxServerVendor **vendors; } GlxClientPriv; extern int GlxErrorBase; @@ -90,11 +95,19 @@ Bool GlxAddXIDMap(XID id, GlxServerVendor *vendor); GlxServerVendor * GlxGetXIDMap(XID id); void GlxRemoveXIDMap(XID id); +/** + * Records the client that sent the current request. This is needed in + * GlxGetXIDMap to know which client's (screen -> vendor) mapping to use for a + * regular X window. + */ +void GlxSetRequestClient(ClientPtr client); + GlxContextTagInfo *GlxAllocContextTag(ClientPtr client, GlxServerVendor *vendor); GlxContextTagInfo *GlxLookupContextTag(ClientPtr client, GLXContextTag tag); void GlxFreeContextTag(GlxContextTagInfo *tagInfo); Bool GlxSetScreenVendor(ScreenPtr screen, GlxServerVendor *vendor); +Bool GlxSetClientScreenVendor(ClientPtr client, ScreenPtr screen, GlxServerVendor *vendor); GlxScreenPriv *GlxGetScreen(ScreenPtr pScreen); GlxServerVendor *GlxGetVendorForScreen(ClientPtr client, ScreenPtr screen); diff --git a/glx/vndservermapping.c b/glx/vndservermapping.c index fd3be92d9..04788ffbd 100644 --- a/glx/vndservermapping.c +++ b/glx/vndservermapping.c @@ -33,6 +33,13 @@ #include "vndservervendor.h" +static ClientPtr requestClient = NULL; + +void GlxSetRequestClient(ClientPtr client) +{ + requestClient = client; +} + static GlxServerVendor *LookupXIDMapResource(XID id) { void *ptr = NULL; @@ -59,10 +66,7 @@ GlxServerVendor *GlxGetXIDMap(XID id) DixGetAttrAccess); if (rv == Success && ptr != NULL) { DrawablePtr draw = (DrawablePtr) ptr; - GlxScreenPriv *screenPriv = GlxGetScreen(draw->pScreen); - if (screenPriv != NULL) { - vendor = screenPriv->vendor; - } + vendor = GlxGetVendorForScreen(requestClient, draw->pScreen); } } return vendor; @@ -185,12 +189,44 @@ Bool GlxSetScreenVendor(ScreenPtr screen, GlxServerVendor *vendor) return TRUE; } +Bool GlxSetClientScreenVendor(ClientPtr client, ScreenPtr screen, GlxServerVendor *vendor) +{ + GlxClientPriv *cl; + + if (screen == NULL || screen->isGPU) { + return FALSE; + } + + cl = GlxGetClientData(client); + if (cl == NULL) { + return FALSE; + } + + if (vendor != NULL) { + cl->vendors[screen->myNum] = vendor; + } else { + cl->vendors[screen->myNum] = GlxGetVendorForScreen(NULL, screen); + } + return TRUE; +} + GlxServerVendor *GlxGetVendorForScreen(ClientPtr client, ScreenPtr screen) { - GlxScreenPriv *priv = GlxGetScreen(screen); - if (priv != NULL) { - return priv->vendor; + // Note that the client won't be sending GPU screen numbers, so we don't + // need per-client mappings for them. + if (client != NULL && !screen->isGPU) { + GlxClientPriv *cl = GlxGetClientData(client); + if (cl != NULL) { + return cl->vendors[screen->myNum]; + } else { + return NULL; + } } else { - return NULL; + GlxScreenPriv *priv = GlxGetScreen(screen); + if (priv != NULL) { + return priv->vendor; + } else { + return NULL; + } } } diff --git a/hw/xfree86/os-support/linux/lnx_video.c b/hw/xfree86/os-support/linux/lnx_video.c index 04e45092a..a24fce37b 100644 --- a/hw/xfree86/os-support/linux/lnx_video.c +++ b/hw/xfree86/os-support/linux/lnx_video.c @@ -116,16 +116,36 @@ hwDisableIO(void) static Bool hwEnableIO(void) { - if (ioperm(0, 1024, 1) || iopl(3)) { - ErrorF("xf86EnableIOPorts: failed to set IOPL for I/O (%s)\n", + short i; + size_t n=0; + int begin, end; + char *buf=NULL, target[4]; + FILE *fp; + + if (ioperm(0, 1024, 1)) { + ErrorF("xf86EnableIO: failed to enable I/O ports 0000-03ff (%s)\n", strerror(errno)); return FALSE; } + #if !defined(__alpha__) - /* XXX: this is actually not trapping anything because of iopl(3) - * above */ - ioperm(0x40, 4, 0); /* trap access to the timer chip */ - ioperm(0x60, 4, 0); /* trap access to the keyboard controller */ + /* trap access to the keyboard controller(s) and timer chip(s) */ + fp = fopen("/proc/ioports", "r"); + while (getline(&buf, &n, fp) != -1) { + if ((strstr(buf, "keyboard") != NULL) || (strstr(buf, "timer") != NULL)) { + for (i=0; i<4; i++) + target[i] = buf[i+2]; + begin = atoi(target); + + for (i=0; i<4; i++) + target[i] = buf[i+7]; + end = atoi(target); + + ioperm(begin, end-begin+1, 0); + } + } + free(buf); + fclose(fp); #endif return TRUE; diff --git a/hw/xwayland/Makefile.am b/hw/xwayland/Makefile.am index 502879e2a..282da58f9 100644 --- a/hw/xwayland/Makefile.am +++ b/hw/xwayland/Makefile.am @@ -22,6 +22,10 @@ Xwayland_SOURCES = \ $(top_srcdir)/mi/miinitext.c if GLX +Xwayland_SOURCES += \ + xwayland-glx.c +Xwayland_CFLAGS += \ + -I$(top_srcdir)/glx GLXVND_LIB = $(top_builddir)/glx/libglxvnd.la endif diff --git a/hw/xwayland/meson.build b/hw/xwayland/meson.build index 36bf2133a..c8746e591 100644 --- a/hw/xwayland/meson.build +++ b/hw/xwayland/meson.build @@ -54,6 +54,9 @@ xwayland_glamor = [] eglstream_srcs = [] if build_glamor srcs += 'xwayland-glamor.c' + if build_glx + srcs += 'xwayland-glx.c' + endif if gbm_dep.found() srcs += 'xwayland-glamor-gbm.c' endif @@ -80,10 +83,15 @@ if build_glamor xwayland_glamor += glamor endif +wayland_inc = [ inc, ] +if build_glx + wayland_inc += glx_inc +endif + executable( 'Xwayland', srcs, - include_directories: inc, + include_directories: wayland_inc, dependencies: [ common_dep, xwayland_dep, diff --git a/hw/xwayland/xwayland-cursor.c b/hw/xwayland/xwayland-cursor.c index cf8395f1d..66720bcc0 100644 --- a/hw/xwayland/xwayland-cursor.c +++ b/hw/xwayland/xwayland-cursor.c @@ -188,6 +188,8 @@ xwl_tablet_tool_set_cursor(struct xwl_tablet_tool *xwl_tablet_tool) zwp_tablet_tool_v2_set_cursor(xwl_tablet_tool->tool, xwl_tablet_tool->proximity_in_serial, NULL, 0, 0); + clear_cursor_frame_callback(xwl_cursor); + xwl_cursor->needs_update = FALSE; return; } diff --git a/hw/xwayland/xwayland-glamor-gbm.c b/hw/xwayland/xwayland-glamor-gbm.c index a211e0915..538e6204e 100644 --- a/hw/xwayland/xwayland-glamor-gbm.c +++ b/hw/xwayland/xwayland-glamor-gbm.c @@ -169,6 +169,8 @@ xwl_glamor_gbm_create_pixmap_for_bo(ScreenPtr screen, struct gbm_bo *bo, xwl_screen->egl_context, EGL_NATIVE_PIXMAP_KHR, xwl_pixmap->bo, NULL); + if (xwl_pixmap->image == EGL_NO_IMAGE_KHR) + goto error; glGenTextures(1, &xwl_pixmap->texture); glBindTexture(GL_TEXTURE_2D, xwl_pixmap->texture); @@ -176,14 +178,27 @@ xwl_glamor_gbm_create_pixmap_for_bo(ScreenPtr screen, struct gbm_bo *bo, glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, xwl_pixmap->image); + if (eglGetError() != EGL_SUCCESS) + goto error; + glBindTexture(GL_TEXTURE_2D, 0); + if (!glamor_set_pixmap_texture(pixmap, xwl_pixmap->texture)) + goto error; + + glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_DRM); xwl_pixmap_set_private(pixmap, xwl_pixmap); - glamor_set_pixmap_texture(pixmap, xwl_pixmap->texture); - glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_DRM); - return pixmap; + +error: + if (xwl_pixmap->image != EGL_NO_IMAGE_KHR) + eglDestroyImageKHR(xwl_screen->egl_display, xwl_pixmap->image); + if (pixmap) + glamor_destroy_pixmap(pixmap); + free(xwl_pixmap); + + return NULL; } static PixmapPtr @@ -194,6 +209,7 @@ xwl_glamor_gbm_create_pixmap(ScreenPtr screen, struct xwl_screen *xwl_screen = xwl_screen_get(screen); struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen); struct gbm_bo *bo; + PixmapPtr pixmap = NULL; if (width > 0 && height > 0 && depth >= 15 && (hint == 0 || @@ -219,10 +235,16 @@ xwl_glamor_gbm_create_pixmap(ScreenPtr screen, } if (bo) - return xwl_glamor_gbm_create_pixmap_for_bo(screen, bo, depth); + pixmap = xwl_glamor_gbm_create_pixmap_for_bo(screen, bo, depth); + + if (!pixmap) + gbm_bo_destroy(bo); } - return glamor_create_pixmap(screen, width, height, depth, hint); + if (!pixmap) + pixmap = glamor_create_pixmap(screen, width, height, depth, hint); + + return pixmap; } static Bool diff --git a/hw/xwayland/xwayland-glamor.c b/hw/xwayland/xwayland-glamor.c index f4bd561ea..dc07f7933 100644 --- a/hw/xwayland/xwayland-glamor.c +++ b/hw/xwayland/xwayland-glamor.c @@ -30,6 +30,9 @@ #include #include +#ifdef GLXEXT +#include "glx_extinit.h" +#endif static void glamor_egl_make_current(struct glamor_context *glamor_ctx) @@ -264,5 +267,9 @@ xwl_glamor_init(struct xwl_screen *xwl_screen) ErrorF("Failed to initialize glamor Xv extension\n"); #endif +#ifdef GLXEXT + GlxPushProvider(&glamor_provider); +#endif + return TRUE; } diff --git a/hw/xwayland/xwayland-glx.c b/hw/xwayland/xwayland-glx.c new file mode 100644 index 000000000..abf48f71c --- /dev/null +++ b/hw/xwayland/xwayland-glx.c @@ -0,0 +1,367 @@ +/* + * Copyright © 2019 Red Hat, Inc. + * + * 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 (including the next + * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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. + * + * Authors: + * Adam Jackson + */ + +/* + * Sets up GLX capabilities based on the EGL capabilities of the glamor + * renderer for the screen. Without this you will get whatever swrast + * can do, which often does not include things like multisample visuals. + */ + +#include +#include "xwayland.h" +#define MESA_EGL_NO_X11_HEADERS +// #include +#include +#include "glxserver.h" +#include "glxutil.h" +#include "compint.h" +#include +#include "glamor_context.h" +#include "glamor.h" + +/* Can't get these from since it pulls in client headers */ +#define GLX_RGBA_BIT 0x00000001 +#define GLX_WINDOW_BIT 0x00000001 +#define GLX_PIXMAP_BIT 0x00000002 +#define GLX_PBUFFER_BIT 0x00000004 +#define GLX_NONE 0x8000 +#define GLX_SLOW_CONFIG 0x8001 +#define GLX_TRUE_COLOR 0x8002 +#define GLX_DIRECT_COLOR 0x8003 +#define GLX_NON_CONFORMANT_CONFIG 0x800D +#define GLX_DONT_CARE 0xFFFFFFFF +#define GLX_RGBA_FLOAT_BIT_ARB 0x00000004 +#define GLX_SWAP_UNDEFINED_OML 0x8063 + +struct egl_config { + __GLXconfig base; + EGLConfig config; +}; + +struct egl_screen { + __GLXscreen base; + EGLDisplay display; + EGLConfig *configs; +}; + +static void +egl_screen_destroy(__GLXscreen *_screen) +{ + struct egl_screen *screen = (struct egl_screen *)_screen; + + /* XXX do we leak the fbconfig list? */ + + free(screen->configs); + __glXScreenDestroy(_screen); + free(_screen); +} + +static void +egl_drawable_destroy(__GLXdrawable *draw) +{ + free(draw); +} + +static GLboolean +egl_drawable_swap_buffers(ClientPtr client, __GLXdrawable *draw) +{ + return GL_FALSE; +} + +static void +egl_drawable_copy_sub_buffer(__GLXdrawable *draw, int x, int y, int w, int h) +{ +} + +static void +egl_drawable_wait_x(__GLXdrawable *draw) +{ + glamor_block_handler(draw->pDraw->pScreen); +} + +static void +egl_drawable_wait_gl(__GLXdrawable *draw) +{ +} + +static __GLXdrawable * +egl_create_glx_drawable(ClientPtr client, __GLXscreen *screen, + DrawablePtr draw, XID drawid, int type, + XID glxdrawid, __GLXconfig *modes) +{ + __GLXdrawable *ret; + + ret = calloc(1, sizeof *ret); + if (!ret) + return NULL; + + if (!__glXDrawableInit(ret, screen, draw, type, glxdrawid, modes)) { + free(ret); + return NULL; + } + + ret->destroy = egl_drawable_destroy; + ret->swapBuffers = egl_drawable_swap_buffers; + ret->copySubBuffer = egl_drawable_copy_sub_buffer; + ret->waitX = egl_drawable_wait_x; + ret->waitGL = egl_drawable_wait_gl; + + return ret; +} + +/* + * TODO: + * + * - figure out sRGB + * - bindToTextureTargets is suspicious + * - better channel mask setup + * - drawable type masks is suspicious + */ +static struct egl_config * +translate_eglconfig(struct egl_screen *screen, EGLConfig hc, + struct egl_config *chain, Bool direct_color, + Bool double_buffer) +{ + EGLint value; + struct egl_config *c = calloc(1, sizeof *c); + + if (!c) + return chain; + + /* constants. changing these requires (at least) new EGL extensions */ + c->base.stereoMode = GL_FALSE; + c->base.numAuxBuffers = 0; + c->base.level = 0; + c->base.transparentAlpha = 0; + c->base.transparentIndex = 0; + c->base.transparentPixel = GLX_NONE; + c->base.visualSelectGroup = 0; + c->base.indexBits = 0; + c->base.optimalPbufferWidth = 0; + c->base.optimalPbufferHeight = 0; + c->base.bindToMipmapTexture = 0; + c->base.bindToTextureTargets = GLX_DONT_CARE; + c->base.sRGBCapable = 0; + c->base.swapMethod = GLX_SWAP_UNDEFINED_OML; + + /* this is... suspect */ + c->base.drawableType = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT; + + /* hmm */ + c->base.bindToTextureRgb = GL_TRUE; + c->base.bindToTextureRgba = GL_TRUE; + + /* + * glx conformance failure: there's no such thing as accumulation + * buffers in EGL. they should be emulable with shaders and fbos, + * but i'm pretty sure nobody's using this feature since it's + * entirely software. note that glx conformance merely requires + * that an accum buffer _exist_, not a minimum bitness. + */ + c->base.accumRedBits = 0; + c->base.accumGreenBits = 0; + c->base.accumBlueBits = 0; + c->base.accumAlphaBits = 0; + + /* parametric state */ + if (direct_color) + c->base.visualType = GLX_DIRECT_COLOR; + else + c->base.visualType = GLX_TRUE_COLOR; + + if (double_buffer) + c->base.doubleBufferMode = GL_TRUE; + else + c->base.doubleBufferMode = GL_FALSE; + + /* direct-mapped state */ +#define GET(attr, slot) \ + eglGetConfigAttrib(screen->display, hc, attr, &c->base.slot) + GET(EGL_RED_SIZE, redBits); + GET(EGL_GREEN_SIZE, greenBits); + GET(EGL_BLUE_SIZE, blueBits); + GET(EGL_ALPHA_SIZE, alphaBits); + GET(EGL_BUFFER_SIZE, rgbBits); + GET(EGL_DEPTH_SIZE, depthBits); + GET(EGL_STENCIL_SIZE, stencilBits); + GET(EGL_TRANSPARENT_RED_VALUE, transparentRed); + GET(EGL_TRANSPARENT_GREEN_VALUE, transparentGreen); + GET(EGL_TRANSPARENT_BLUE_VALUE, transparentBlue); + GET(EGL_SAMPLE_BUFFERS, sampleBuffers); + GET(EGL_SAMPLES, samples); + if (c->base.renderType & GLX_PBUFFER_BIT) { + GET(EGL_MAX_PBUFFER_WIDTH, maxPbufferWidth); + GET(EGL_MAX_PBUFFER_HEIGHT, maxPbufferHeight); + GET(EGL_MAX_PBUFFER_PIXELS, maxPbufferPixels); + } +#undef GET + + /* derived state: config caveats */ + eglGetConfigAttrib(screen->display, hc, EGL_CONFIG_CAVEAT, &value); + if (value == EGL_NONE) + c->base.visualRating = GLX_NONE; + else if (value == EGL_SLOW_CONFIG) + c->base.visualRating = GLX_SLOW_CONFIG; + else if (value == EGL_NON_CONFORMANT_CONFIG) + c->base.visualRating = GLX_NON_CONFORMANT_CONFIG; + /* else panic */ + + /* derived state: float configs */ + c->base.renderType = GLX_RGBA_BIT; + if (eglGetConfigAttrib(screen->display, hc, EGL_COLOR_COMPONENT_TYPE_EXT, + &value) == EGL_TRUE) { + if (value == EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT) { + c->base.renderType = GLX_RGBA_FLOAT_BIT_ARB; + } + /* else panic */ + } + + /* map to the backend's config */ + c->config = hc; + + /* + * XXX do something less ugly + */ + if (c->base.renderType == GLX_RGBA_BIT) { + if (c->base.redBits == 5 && + (c->base.rgbBits == 15 || c->base.rgbBits == 16)) { + c->base.blueMask = 0x0000001f; + if (c->base.alphaBits) { + c->base.greenMask = 0x000003e0; + c->base.redMask = 0x00007c00; + c->base.alphaMask = 0x00008000; + } else { + c->base.greenMask = 0x000007e0; + c->base.redMask = 0x0000f800; + c->base.alphaMask = 0x00000000; + } + } + else if (c->base.redBits == 8 && + (c->base.rgbBits == 24 || c->base.rgbBits == 32)) { + c->base.blueMask = 0x000000ff; + c->base.greenMask = 0x0000ff00; + c->base.redMask = 0x00ff0000; + if (c->base.alphaBits) + /* assume all remaining bits are alpha */ + c->base.alphaMask = 0xff000000; + } + else if (c->base.redBits == 10 && + (c->base.rgbBits == 30 || c->base.rgbBits == 32)) { + c->base.blueMask = 0x000003ff; + c->base.greenMask = 0x000ffc00; + c->base.redMask = 0x3ff00000; + if (c->base.alphaBits) + /* assume all remaining bits are alpha */ + c->base.alphaMask = 0xc000000; + } + } + + c->base.next = chain ? &chain->base : NULL; + return c; +} + +static __GLXconfig * +egl_mirror_configs(ScreenPtr pScreen, struct egl_screen *screen) +{ + int i, j, k, nconfigs; + struct egl_config *c = NULL; + EGLConfig *host_configs = NULL; + Bool offon[] = { FALSE, TRUE }; + + eglGetConfigs(screen->display, NULL, 0, &nconfigs); + if (!(host_configs = calloc(nconfigs, sizeof *host_configs))) + return NULL; + + eglGetConfigs(screen->display, host_configs, nconfigs, &nconfigs); + + /* We walk the EGL configs backwards to make building the + * ->next chain easier. + */ + for (i = nconfigs - 1; i > 0; i--) + for (j = 0; j < 2; j++) /* direct_color */ + for (k = 0; k < 2; k++) /* direct_color */ + c = translate_eglconfig(screen, host_configs[i], c, + /* direct_color */ offon[j], + /* double_buffer */ offon[k] + ); + + screen->configs = host_configs; + return c ? &c->base : NULL; +} + +static __GLXscreen * +egl_screen_probe(ScreenPtr pScreen) +{ + struct egl_screen *screen; + struct xwl_screen *xwl_screen = xwl_screen_get(pScreen); + __GLXscreen *base; + + if (enableIndirectGLX) + return NULL; /* not implemented */ + + if (!(screen = calloc(1, sizeof *screen))) + return NULL; + + base = &screen->base; + base->destroy = egl_screen_destroy; + base->createDrawable = egl_create_glx_drawable; + /* base.swapInterval = NULL; */ + + screen->display = xwl_screen->glamor_ctx->display; + + __glXInitExtensionEnableBits(screen->base.glx_enable_bits); + __glXEnableExtension(base->glx_enable_bits, "GLX_ARB_context_flush_control"); + __glXEnableExtension(base->glx_enable_bits, "GLX_ARB_create_context"); + __glXEnableExtension(base->glx_enable_bits, "GLX_ARB_create_context_no_error"); + __glXEnableExtension(base->glx_enable_bits, "GLX_ARB_create_context_profile"); + __glXEnableExtension(base->glx_enable_bits, "GLX_ARB_create_context_robustness"); + __glXEnableExtension(base->glx_enable_bits, "GLX_ARB_fbconfig_float"); + __glXEnableExtension(base->glx_enable_bits, "GLX_EXT_create_context_es2_profile"); + __glXEnableExtension(base->glx_enable_bits, "GLX_EXT_create_context_es_profile"); + __glXEnableExtension(base->glx_enable_bits, "GLX_EXT_fbconfig_packed_float"); + __glXEnableExtension(base->glx_enable_bits, "GLX_EXT_framebuffer_sRGB"); + __glXEnableExtension(base->glx_enable_bits, "GLX_EXT_no_config_context"); + __glXEnableExtension(base->glx_enable_bits, "GLX_EXT_texture_from_pixmap"); + __glXEnableExtension(base->glx_enable_bits, "GLX_MESA_copy_sub_buffer"); + // __glXEnableExtension(base->glx_enable_bits, "GLX_SGI_swap_control"); + + base->fbconfigs = egl_mirror_configs(pScreen, screen); + if (!base->fbconfigs) { + free(screen); + return NULL; + } + + __glXScreenInit(base, pScreen); + __glXsetGetProcAddress(eglGetProcAddress); + + return base; +} + +__GLXprovider glamor_provider = { + egl_screen_probe, + "glamor", + NULL +}; diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c index 15fc989bd..2c3482763 100644 --- a/hw/xwayland/xwayland-input.c +++ b/hw/xwayland/xwayland-input.c @@ -2661,6 +2661,7 @@ xwl_pointer_warp_emulator_maybe_lock(struct xwl_pointer_warp_emulator *warp_emul */ if (pointer_grab && !pointer_grab->ownerEvents && + sprite && XYToWindow(sprite, x, y) != xwl_seat->focus_window->window) return; diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c index 739f86cf1..fe8b1abdc 100644 --- a/hw/xwayland/xwayland.c +++ b/hw/xwayland/xwayland.c @@ -98,7 +98,8 @@ ddxUseMsg(void) { ErrorF("-rootless run rootless, requires wm support\n"); ErrorF("-wm fd create X client for wm on given fd\n"); - ErrorF("-listen fd add give fd as a listen socket\n"); + ErrorF("-listenfd fd add give fd as a listen socket\n"); + ErrorF("-listen fd deprecated, use \"-listenfd\" instead\n"); ErrorF("-eglstream use eglstream backend for nvidia GPUs\n"); } @@ -106,6 +107,17 @@ static int wm_fd = -1; static int listen_fds[5] = { -1, -1, -1, -1, -1 }; static int listen_fd_count = 0; +static void +xwl_add_listen_fd(int argc, char *argv[], int i) +{ + NoListenAll = TRUE; + if (listen_fd_count == ARRAY_SIZE(listen_fds)) + FatalError("Too many -listen arguments given, max is %zu\n", + ARRAY_SIZE(listen_fds)); + + listen_fds[listen_fd_count++] = atoi(argv[i + 1]); +} + int ddxProcessArgument(int argc, char *argv[], int i) { @@ -115,12 +127,20 @@ ddxProcessArgument(int argc, char *argv[], int i) else if (strcmp(argv[i], "-listen") == 0) { CHECK_FOR_REQUIRED_ARGUMENTS(1); - NoListenAll = TRUE; - if (listen_fd_count == ARRAY_SIZE(listen_fds)) - FatalError("Too many -listen arguments given, max is %zu\n", - ARRAY_SIZE(listen_fds)); + /* Not an FD */ + if (!isdigit(*argv[i + 1])) + return 0; - listen_fds[listen_fd_count++] = atoi(argv[i + 1]); + LogMessage(X_WARNING, "Option \"-listen\" for file descriptors is deprecated\n" + "Please use \"-listenfd\" instead.\n"); + + xwl_add_listen_fd (argc, argv, i); + return 2; + } + else if (strcmp(argv[i], "-listenfd") == 0) { + CHECK_FOR_REQUIRED_ARGUMENTS(1); + + xwl_add_listen_fd (argc, argv, i); return 2; } else if (strcmp(argv[i], "-wm") == 0) { diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h index 92664e812..85691d9d4 100644 --- a/hw/xwayland/xwayland.h +++ b/hw/xwayland/xwayland.h @@ -485,4 +485,9 @@ static inline void xwl_glamor_init_eglstream(struct xwl_screen *xwl_screen) } #endif +#ifdef GLXEXT +#include "glx_extinit.h" +extern __GLXprovider glamor_provider; +#endif + #endif diff --git a/hw/xwin/InitOutput.c b/hw/xwin/InitOutput.c index ddbf04253..c336820df 100644 --- a/hw/xwin/InitOutput.c +++ b/hw/xwin/InitOutput.c @@ -716,6 +716,13 @@ winUseMsg(void) "\tthe updated region when num_boxes, or more, are in the\n" "\tupdated region.\n"); + ErrorF("-[no]compositealpha\n" + "\tX windows with per-pixel alpha are composited into the Windows desktop.\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"); @@ -798,7 +805,7 @@ winUseMsg(void) "\tSpecify an optional refresh rate to use in fullscreen mode\n" "\twith a DirectDraw engine.\n"); - ErrorF("-resize=none|scrollbars|randr" + ErrorF("-resize=none|scrollbars|randr\n" "\tIn windowed mode, [don't] allow resizing of the window. 'scrollbars'\n" "\tmode gives the window scrollbars as needed, 'randr' mode uses the RANR\n" "\textension to resize the X screen. 'randr' is the default.\n"); @@ -974,8 +981,7 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char *argv[]) for (iMonitor = 1; ; iMonitor++) { struct GetMonitorInfoData data; - QueryMonitor(iMonitor, &data); - if (data.bMonitorSpecifiedExists) + if (QueryMonitor(iMonitor, &data)) { MONITORINFO mi; mi.cbSize = sizeof(MONITORINFO); diff --git a/hw/xwin/Makefile.am b/hw/xwin/Makefile.am index 42fc9dd68..6ef89196a 100644 --- a/hw/xwin/Makefile.am +++ b/hw/xwin/Makefile.am @@ -27,7 +27,7 @@ SRCS_MULTIWINDOW = \ winmultiwindowwndproc.c \ propertystore.h \ winSetAppUserModelID.c -MULTIWINDOW_SYS_LIBS = -lshlwapi -lole32 +MULTIWINDOW_SYS_LIBS = -lshlwapi -lole32 -ldwmapi SRCS_RANDR = \ winrandr.c diff --git a/hw/xwin/man/XWin.man b/hw/xwin/man/XWin.man index 2401f9f09..f9305f592 100644 --- a/hw/xwin/man/XWin.man +++ b/hw/xwin/man/XWin.man @@ -170,6 +170,21 @@ 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. +.TP 8 +.B \-[no]compositealpha +X windows with per-pixel alpha are composited into the \fIWindows\fP desktop +(i.e. a \fIWindows\fP window can be seen through any transparency in an X window +placed over it). + +This option has no effect on Windows 8 and 8.1. +This option has no effect if \fB-compositewm\fP is disabled. +The default is disabled. .SH OPTIONS CONTROLLING WINDOWS INTEGRATION .TP 8 @@ -206,6 +221,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 diff --git a/hw/xwin/meson.build b/hw/xwin/meson.build index 3ec809fef..c1a2917b8 100644 --- a/hw/xwin/meson.build +++ b/hw/xwin/meson.build @@ -44,7 +44,7 @@ srcs_windows += [ 'propertystore.h', 'winSetAppUserModelID.c', ] -xwin_sys_libs += ['-lshlwapi', '-lole32'] +xwin_sys_libs += ['-lshlwapi', '-lole32', '-ldwmapi'] srcs_windows += [ 'winrandr.c', @@ -137,6 +137,7 @@ xwin_dep = [ dependency('xcb-image'), dependency('xcb-ewmh'), dependency('xcb-icccm'), + dependency('xcb-composite'), ] executable( diff --git a/hw/xwin/win.h b/hw/xwin/win.h index 27505caad..8eabeae31 100644 --- a/hw/xwin/win.h +++ b/hw/xwin/win.h @@ -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); @@ -294,11 +296,10 @@ typedef Bool (*winCreateScreenResourcesProc) (ScreenPtr); */ typedef struct { - HDC hdcSelected; HBITMAP hBitmap; - BYTE *pbBits; - DWORD dwScanlineBytes; + void *pbBits; BITMAPINFOHEADER *pbmih; + BOOL owned; } winPrivPixmapRec, *winPrivPixmapPtr; /* @@ -389,6 +390,7 @@ typedef struct { Bool fDecoration; Bool fRootless; Bool fMultiWindow; + Bool fCompositeWM; Bool fMultiMonitorOverride; Bool fMultipleMonitors; Bool fLessPointer; @@ -479,6 +481,7 @@ typedef struct _winPrivScreenRec { winCreateBoundingWindowProcPtr pwinCreateBoundingWindow; winFinishScreenInitProcPtr pwinFinishScreenInit; winBltExposedRegionsProcPtr pwinBltExposedRegions; + winBltExposedWindowRegionProcPtr pwinBltExposedWindowRegion; winActivateAppProcPtr pwinActivateApp; winRedrawScreenProcPtr pwinRedrawScreen; winRealizeInstalledPaletteProcPtr pwinRealizeInstalledPalette; @@ -507,6 +510,7 @@ typedef struct _winPrivScreenRec { ResizeWindowProcPtr ResizeWindow; MoveWindowProcPtr MoveWindow; SetShapeProcPtr SetShape; + ModifyPixmapHeaderProcPtr ModifyPixmapHeader; winCursorRec cursor; @@ -942,6 +946,19 @@ void winCopyWindowMultiWindow(WindowPtr pWin, DDXPointRec oldpt, RegionPtr oldRegion); +PixmapPtr +winCreatePixmapMultiwindow(ScreenPtr pScreen, int width, int height, int depth, + unsigned usage_hint); +Bool +winDestroyPixmapMultiwindow(PixmapPtr pPixmap); + +Bool +winModifyPixmapHeaderMultiwindow(PixmapPtr pPixmap, + int width, + int height, + int depth, + int bitsPerPixel, int devKind, void *pPixData); + XID winGetWindowID(WindowPtr pWin); diff --git a/hw/xwin/winglobals.c b/hw/xwin/winglobals.c index d1a0d4587..3212c6beb 100644 --- a/hw/xwin/winglobals.c +++ b/hw/xwin/winglobals.c @@ -59,6 +59,7 @@ HWND g_hDlgAbout = NULL; const char *g_pszQueryHost = NULL; Bool g_fXdmcpEnabled = FALSE; Bool g_fAuthEnabled = FALSE; +Bool g_fCompositeAlpha = FALSE; HICON g_hIconX = NULL; HICON g_hSmallIconX = NULL; diff --git a/hw/xwin/winglobals.h b/hw/xwin/winglobals.h index 82fc1c5ec..77af6125a 100644 --- a/hw/xwin/winglobals.h +++ b/hw/xwin/winglobals.h @@ -50,6 +50,7 @@ extern Bool g_fLogInited; extern Bool g_fAuthEnabled; extern Bool g_fXdmcpEnabled; +extern Bool g_fCompositeAlpha; extern Bool g_fNoHelpMessageBox; extern Bool g_fNativeGl; diff --git a/hw/xwin/winkeynames.h b/hw/xwin/winkeynames.h index bfed9d427..6159f623e 100644 --- a/hw/xwin/winkeynames.h +++ b/hw/xwin/winkeynames.h @@ -191,8 +191,8 @@ #define KEY_BSlash2 /* \ _ 0xcb */ 203 #define KEY_Mute /* Audio Mute */ 152 -#define KEY_AudioLower /* Audio Lower */ 168 -#define KEY_AudioRaise /* Audio Raise */ 166 +#define KEY_AudioLower /* Audio Lower */ 166 +#define KEY_AudioRaise /* Audio Raise */ 168 #define KEY_NEXTSONG /* Media next */ 145 #define KEY_PLAYPAUSE /* Media play/pause toggle */ 154 diff --git a/hw/xwin/winlayouts.h b/hw/xwin/winlayouts.h index c7905e3c2..904410a2d 100644 --- a/hw/xwin/winlayouts.h +++ b/hw/xwin/winlayouts.h @@ -65,6 +65,7 @@ WinKBLayoutRec winKBLayouts[] = { {0x0000040b, -1, "pc105", "fi", NULL, NULL, "Finnish"}, {0x0000040c, -1, "pc105", "fr", NULL, NULL, "French (Standard)"}, {0x0000080c, -1, "pc105", "be", NULL, NULL, "French (Belgian)"}, + {0x0001080c, -1, "pc105", "be", NULL, NULL, "Belgian (Comma)"}, {0x00000c0c, -1, "pc105", "ca", "fr-legacy", NULL, "French (Canada, Legacy)"}, {0x0000100c, -1, "pc105", "ch", "fr", NULL, "French (Switzerland)"}, @@ -82,6 +83,7 @@ WinKBLayoutRec winKBLayouts[] = { {0x00000416, -1, "pc105", "br", NULL, NULL, "Portuguese (Brazil,ABNT)"}, {0x00010416, -1, "abnt2", "br", NULL, NULL, "Portuguese (Brazil,ABNT2)"}, {0x00000816, -1, "pc105", "pt", NULL, NULL, "Portuguese (Portugal)"}, + {0x00000419, -1, "pc105", "ru", NULL, NULL, "Russian"}, {0x0000041a, -1, "pc105", "hr", NULL, NULL, "Croatian"}, {0x0000041d, -1, "pc105", "se", NULL, NULL, "Swedish (Sweden)"}, {0x0000041f, -1, "pc105", "tr", NULL, NULL, "Turkish (Q)"}, diff --git a/hw/xwin/winmonitors.c b/hw/xwin/winmonitors.c index 955fb9214..5ff565308 100644 --- a/hw/xwin/winmonitors.c +++ b/hw/xwin/winmonitors.c @@ -39,7 +39,7 @@ from The Open Group. */ static - wBOOL CALLBACK +WINBOOL CALLBACK getMonitorInfo(HMONITOR hMonitor, HDC hdc, LPRECT rect, LPARAM _data) { struct GetMonitorInfoData *data = (struct GetMonitorInfoData *) _data; @@ -70,5 +70,5 @@ QueryMonitor(int i, struct GetMonitorInfoData *data) /* query information */ EnumDisplayMonitors(NULL, NULL, getMonitorInfo, (LPARAM) data); - return TRUE; + return data->bMonitorSpecifiedExists; } diff --git a/hw/xwin/winmultiwindowwindow.c b/hw/xwin/winmultiwindowwindow.c index 4ec5634af..4eec72be2 100644 --- a/hw/xwin/winmultiwindowwindow.c +++ b/hw/xwin/winmultiwindowwindow.c @@ -960,3 +960,259 @@ winAdjustXWindow(WindowPtr pWin, HWND hwnd) #undef WIDTH #undef HEIGHT } + +/* + Helper function for creating a DIB to back a pixmap + */ +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); + pPixmapPriv->owned = TRUE; + + 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); + + /* Nothing to do if we don't own the DIB */ + if (!pPixmapPriv->owned) + return TRUE; + + /* 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 = winGetPixmapPriv(pPixmap); + 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->hBitmap = pScreenPriv->hbmpShadow; + pPixmapPriv->pbBits = pScreenInfo->pfb; + pPixmapPriv->pbmih = pScreenPriv->pbmih; + + /* mark these not to get released by DestroyPixmap */ + pPixmapPriv->owned = FALSE; + + return TRUE; + } + } + + /* Otherwise, since creating a DIBSection from arbitrary memory is not + * possible, fallback to normal. If needed, we can create a DIBSection with + * a copy of the bits later (see comment about a potential slow-path in + * winBltExposedWindowRegionShadowGDI()). */ + pPixmapPriv->hBitmap = 0; + pPixmapPriv->pbBits = 0; + pPixmapPriv->pbmih = 0; + pPixmapPriv->owned = FALSE; + + 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; +} diff --git a/hw/xwin/winmultiwindowwm.c b/hw/xwin/winmultiwindowwm.c index 32bc722e2..0734006fc 100644 --- a/hw/xwin/winmultiwindowwm.c +++ b/hw/xwin/winmultiwindowwm.c @@ -49,6 +49,7 @@ #include #include #include +#include #include @@ -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; diff --git a/hw/xwin/winmultiwindowwndproc.c b/hw/xwin/winmultiwindowwndproc.c index 3f47fec65..587884d11 100644 --- a/hw/xwin/winmultiwindowwndproc.c +++ b/hw/xwin/winmultiwindowwndproc.c @@ -35,12 +35,18 @@ #ifdef HAVE_XWIN_CONFIG_H #include #endif + #include "win.h" #include "dixevents.h" #include "winmultiwindowclass.h" #include "winprefs.h" #include "winmsg.h" #include "inputstr.h" +#include + +#ifndef WM_DWMCOMPOSITIONCHANGED +#define WM_DWMCOMPOSITIONCHANGED 0x031e +#endif extern void winUpdateWindowPosition(HWND hWnd, HWND * zstyle); @@ -294,6 +300,113 @@ winStartMousePolling(winPrivScreenPtr s_pScreenPriv) MOUSE_POLLING_INTERVAL, NULL); } +/* Undocumented */ +typedef struct _ACCENTPOLICY +{ + ULONG AccentState; + ULONG AccentFlags; + ULONG GradientColor; + ULONG AnimationId; +} ACCENTPOLICY; + +#define ACCENT_ENABLE_BLURBEHIND 3 + +typedef struct _WINCOMPATTR +{ + DWORD attribute; + PVOID pData; + ULONG dataSize; +} WINCOMPATTR; + +#define WCA_ACCENT_POLICY 19 + +typedef WINBOOL WINAPI (*PFNSETWINDOWCOMPOSITIONATTRIBUTE)(HWND, WINCOMPATTR *); + +static void +CheckForAlpha(HWND hWnd, WindowPtr pWin, winScreenInfo *pScreenInfo) +{ + /* Check (once) which API we should use */ + static Bool doOnce = TRUE; + static PFNSETWINDOWCOMPOSITIONATTRIBUTE pSetWindowCompositionAttribute = NULL; + static Bool useDwmEnableBlurBehindWindow = FALSE; + + if (doOnce) + { + OSVERSIONINFOEX osvi = {0}; + osvi.dwOSVersionInfoSize = sizeof(osvi); + GetVersionEx((LPOSVERSIONINFO)&osvi); + + /* SetWindowCompositionAttribute() exists on Windows 7 and later, + but doesn't work for this purpose, so first check for Windows 10 + or later */ + if (osvi.dwMajorVersion >= 10) + { + HMODULE hUser32 = GetModuleHandle("user32"); + + if (hUser32) + pSetWindowCompositionAttribute = (PFNSETWINDOWCOMPOSITIONATTRIBUTE) GetProcAddress(hUser32, "SetWindowCompositionAttribute"); + winDebug("SetWindowCompositionAttribute %s\n", pSetWindowCompositionAttribute ? "found" : "not found"); + } + /* On Windows 7 and Windows Vista, use DwmEnableBlurBehindWindow() */ + else if ((osvi.dwMajorVersion == 6) && (osvi.dwMinorVersion <= 1)) + { + useDwmEnableBlurBehindWindow = TRUE; + } + /* On Windows 8 and Windows 8.1, using the alpha channel on those + seems near impossible, so we don't do anything. */ + + doOnce = FALSE; + } + + /* alpha-channel use is wanted */ + if (!g_fCompositeAlpha || !pScreenInfo->fCompositeWM) + return; + + /* Image has alpha ... */ + if (pWin->drawable.depth != 32) + return; + + /* ... and we can do something useful with it? */ + if (pSetWindowCompositionAttribute) + { + WINBOOL rc; + /* Use the (undocumented) SetWindowCompositionAttribute, if + available, to turn on alpha channel use on Windows 10. */ + ACCENTPOLICY policy = { ACCENT_ENABLE_BLURBEHIND, 0, 0, 0 } ; + WINCOMPATTR data = { WCA_ACCENT_POLICY, &policy, sizeof(ACCENTPOLICY) }; + + /* This turns on DWM looking at the alpha-channel of this window */ + winDebug("enabling alpha for XID %08x hWnd %p, using SetWindowCompositionAttribute()\n", (unsigned int)pWin->drawable.id, hWnd); + rc = pSetWindowCompositionAttribute(hWnd, &data); + if (!rc) + ErrorF("SetWindowCompositionAttribute failed: %d\n", (int)GetLastError()); + } + else if (useDwmEnableBlurBehindWindow) + { + HRESULT rc; + WINBOOL enabled; + + rc = DwmIsCompositionEnabled(&enabled); + if ((rc == S_OK) && enabled) + { + /* Use DwmEnableBlurBehindWindow, to turn on alpha channel + use on Windows Vista and Windows 7 */ + DWM_BLURBEHIND bbh; + bbh.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION | DWM_BB_TRANSITIONONMAXIMIZED; + bbh.fEnable = TRUE; + bbh.hRgnBlur = NULL; + bbh.fTransitionOnMaximized = TRUE; /* What does this do ??? */ + + /* This terribly-named function actually controls if DWM + looks at the alpha channel of this window */ + winDebug("enabling alpha for XID %08x hWnd %p, using DwmEnableBlurBehindWindow()\n", (unsigned int)pWin->drawable.id, hWnd); + rc = DwmEnableBlurBehindWindow(hWnd, &bbh); + if (rc != S_OK) + ErrorF("DwmEnableBlurBehindWindow failed: %x, %d\n", (int)rc, (int)GetLastError()); + } + } +} + /* * winTopLevelWindowProc - Window procedure for all top-level Windows windows. */ @@ -302,7 +415,6 @@ LRESULT CALLBACK winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { POINT ptMouse; - HDC hdcUpdate; PAINTSTRUCT ps; WindowPtr pWin = NULL; winPrivWinPtr pWinPriv = NULL; @@ -323,6 +435,20 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) lParam); #endif + /* + If this is WM_CREATE, set up the Windows window properties which point to + X window information, before we populate local convenience variables... + */ + if (message == WM_CREATE) { + SetProp(hwnd, + WIN_WINDOW_PROP, + (HANDLE) ((LPCREATESTRUCT) lParam)->lpCreateParams); + SetProp(hwnd, + WIN_WID_PROP, + (HANDLE) (INT_PTR)winGetWindowID(((LPCREATESTRUCT) lParam)-> + lpCreateParams)); + } + /* Check if the Windows window property for our X window pointer is valid */ if ((pWin = GetProp(hwnd, WIN_WINDOW_PROP)) != NULL) { /* Our X window pointer is valid */ @@ -383,18 +509,6 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) /* Branch on message type */ switch (message) { case WM_CREATE: - - /* */ - SetProp(hwnd, - WIN_WINDOW_PROP, - (HANDLE) ((LPCREATESTRUCT) lParam)->lpCreateParams); - - /* */ - SetProp(hwnd, - WIN_WID_PROP, - (HANDLE) (INT_PTR) winGetWindowID(((LPCREATESTRUCT) lParam)-> - lpCreateParams)); - /* * Make X windows' Z orders sync with Windows windows because * there can be AlwaysOnTop windows overlapped on the window @@ -415,6 +529,8 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) XMING_SIGNATURE); + CheckForAlpha(hwnd, pWin, s_pScreenInfo); + return 0; case WM_INIT_SYS_MENU: @@ -457,18 +573,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 +585,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: @@ -1142,6 +1229,12 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) } break; + + case WM_DWMCOMPOSITIONCHANGED: + /* This message is only sent on Vista/W7 */ + CheckForAlpha(hwnd, pWin, s_pScreenInfo); + + return 0; default: break; } diff --git a/hw/xwin/winprocarg.c b/hw/xwin/winprocarg.c index 5dd878c30..cb03b00e0 100644 --- a/hw/xwin/winprocarg.c +++ b/hw/xwin/winprocarg.c @@ -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; @@ -308,11 +309,7 @@ ddxProcessArgument(int argc, char *argv[], int i) if (i + 2 < argc && 1 == sscanf(argv[i + 2], "@%d", (int *) &iMonitor)) { struct GetMonitorInfoData data; - if (!QueryMonitor(iMonitor, &data)) { - ErrorF - ("ddxProcessArgument - screen - Querying monitors failed\n"); - } - else if (data.bMonitorSpecifiedExists == TRUE) { + if (QueryMonitor(iMonitor, &data)) { winErrorFVerb(2, "ddxProcessArgument - screen - Found Valid ``@Monitor'' = %d arg\n", iMonitor); @@ -333,8 +330,7 @@ ddxProcessArgument(int argc, char *argv[], int i) ErrorF ("ddxProcessArgument - screen - Invalid monitor number %d\n", iMonitor); - UseMsg(); - exit(0); + exit(1); return 0; } } @@ -365,11 +361,7 @@ ddxProcessArgument(int argc, char *argv[], int i) (int *) &iMonitor)) { struct GetMonitorInfoData data; - if (!QueryMonitor(iMonitor, &data)) { - ErrorF - ("ddxProcessArgument - screen - Querying monitors failed\n"); - } - else if (data.bMonitorSpecifiedExists == TRUE) { + if (QueryMonitor(iMonitor, &data)) { g_ScreenInfo[nScreenNum].iMonitor = iMonitor; g_ScreenInfo[nScreenNum].hMonitor = data.monitorHandle; g_ScreenInfo[nScreenNum].dwInitialX += @@ -382,11 +374,9 @@ ddxProcessArgument(int argc, char *argv[], int i) ErrorF ("ddxProcessArgument - screen - Invalid monitor number %d\n", iMonitor); - UseMsg(); - exit(0); + exit(1); return 0; } - } } @@ -394,11 +384,7 @@ ddxProcessArgument(int argc, char *argv[], int i) else if (1 == sscanf(argv[i + 2], "%*dx%*d@%d", (int *) &iMonitor)) { struct GetMonitorInfoData data; - if (!QueryMonitor(iMonitor, &data)) { - ErrorF - ("ddxProcessArgument - screen - Querying monitors failed\n"); - } - else if (data.bMonitorSpecifiedExists == TRUE) { + if (QueryMonitor(iMonitor, &data)) { winErrorFVerb(2, "ddxProcessArgument - screen - Found Valid ``@Monitor'' = %d arg\n", iMonitor); @@ -413,11 +399,9 @@ ddxProcessArgument(int argc, char *argv[], int i) ErrorF ("ddxProcessArgument - screen - Invalid monitor number %d\n", iMonitor); - UseMsg(); - exit(0); + exit(1); return 0; } - } } else if (i + 3 < argc && 1 == sscanf(argv[i + 2], "%d", (int *) &iWidth) @@ -571,6 +555,44 @@ 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 '-compositealpha' argument + */ + if (IS_OPTION("-compositealpha")) { + g_fCompositeAlpha = TRUE; + + /* Indicate that we have processed this argument */ + return 1; + } + /* + * Look for the '-nocompositealpha' argument + */ + if (IS_OPTION("-nocompositealpha")) { + g_fCompositeAlpha = FALSE; + + /* Indicate that we have processed this argument */ + return 1; + } + /* * Look for the '-multiplemonitors' argument */ diff --git a/hw/xwin/winrandr.c b/hw/xwin/winrandr.c index 16caea742..038d63bde 100644 --- a/hw/xwin/winrandr.c +++ b/hw/xwin/winrandr.c @@ -42,17 +42,17 @@ static Bool winRandRGetInfo(ScreenPtr pScreen, Rotation * pRotations) { - rrScrPrivPtr pRRScrPriv; - RROutputPtr output; - - pRRScrPriv = rrGetScrPriv(pScreen); - output = pRRScrPriv->outputs[0]; - winDebug("winRandRGetInfo ()\n"); /* Don't support rotations */ *pRotations = RR_Rotate_0; + return TRUE; +} + +static void +winRandRUpdateMode(ScreenPtr pScreen, RROutputPtr output) +{ /* Delete previous mode */ if (output->modes[0]) { @@ -83,8 +83,6 @@ winRandRGetInfo(ScreenPtr pScreen, Rotation * pRotations) mode = RRModeGet(&modeInfo, name); output->crtc->mode = mode; } - - return TRUE; } /* @@ -95,6 +93,7 @@ winDoRandRScreenSetSize(ScreenPtr pScreen, CARD16 width, CARD16 height, CARD32 mmWidth, CARD32 mmHeight) { + rrScrPrivPtr pRRScrPriv; winScreenPriv(pScreen); winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; WindowPtr pRoot = pScreen->root; @@ -136,6 +135,10 @@ winDoRandRScreenSetSize(ScreenPtr pScreen, // and arrange for it to be repainted pScreen->PaintWindow(pRoot, &pRoot->borderClip, PW_BACKGROUND); + // Set mode to current display size + pRRScrPriv = rrGetScrPriv(pScreen); + winRandRUpdateMode(pScreen, pRRScrPriv->primaryOutput); + /* Indicate that a screen size change took place */ RRScreenSizeNotify(pScreen); } @@ -270,6 +273,24 @@ winRandRInit(ScreenPtr pScreen) /* Ensure we have space for exactly one mode */ output->modes = malloc(sizeof(RRModePtr)); output->modes[0] = NULL; + + /* Set mode to current display size */ + winRandRUpdateMode(pScreen, output); + + /* Make up some physical dimensions */ + output->mmWidth = (pScreen->width * 25.4)/monitorResolution; + output->mmHeight = (pScreen->height * 25.4)/monitorResolution; + + /* Allocate and make up a (fixed, linear) gamma ramp */ + { + int i; + RRCrtcGammaSetSize(crtc, 256); + for (i = 0; i < crtc->gammaSize; i++) { + crtc->gammaRed[i] = i << 8; + crtc->gammaBlue[i] = i << 8; + crtc->gammaGreen[i] = i << 8; + } + } } /* diff --git a/hw/xwin/winscrinit.c b/hw/xwin/winscrinit.c index d6a1fedc7..9c0473019 100644 --- a/hw/xwin/winscrinit.c +++ b/hw/xwin/winscrinit.c @@ -258,6 +258,11 @@ winFinishScreenInitFB(int i, ScreenPtr pScreen, int argc, char **argv) return FALSE; } + if ((pScreenInfo->dwBPP == 8) && (pScreenInfo->fCompositeWM)) { + ErrorF("-compositewm disabled due to 8bpp depth\n"); + pScreenInfo->fCompositeWM = FALSE; + } + /* Apparently we need this for the render extension */ miSetPixmapDepths(); @@ -417,6 +422,7 @@ winFinishScreenInitFB(int i, ScreenPtr pScreen, int argc, char **argv) WRAP(MoveWindow); WRAP(CopyWindow); WRAP(SetShape); + WRAP(ModifyPixmapHeader); /* Assign multi-window window procedures to be top level procedures */ pScreen->CreateWindow = winCreateWindowMultiWindow; @@ -432,6 +438,12 @@ winFinishScreenInitFB(int i, ScreenPtr pScreen, int argc, char **argv) pScreen->CopyWindow = winCopyWindowMultiWindow; pScreen->SetShape = winSetShapeMultiWindow; + if (pScreenInfo->fCompositeWM) { + pScreen->CreatePixmap = winCreatePixmapMultiwindow; + pScreen->DestroyPixmap = winDestroyPixmapMultiwindow; + pScreen->ModifyPixmapHeader = winModifyPixmapHeaderMultiwindow; + } + /* Undefine the WRAP macro, as it is not needed elsewhere */ #undef WRAP } @@ -471,7 +483,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; } diff --git a/hw/xwin/winshadddnl.c b/hw/xwin/winshadddnl.c index 4e1fbd15c..290176920 100644 --- a/hw/xwin/winshadddnl.c +++ b/hw/xwin/winshadddnl.c @@ -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 diff --git a/hw/xwin/winshadgdi.c b/hw/xwin/winshadgdi.c index 6d7ebce07..65678962b 100644 --- a/hw/xwin/winshadgdi.c +++ b/hw/xwin/winshadgdi.c @@ -59,6 +59,9 @@ static Bool static Bool winBltExposedRegionsShadowGDI(ScreenPtr pScreen); +static Bool + winBltExposedWindowRegionShadowGDI(ScreenPtr pScreen, WindowPtr pWin); + static Bool winActivateAppShadowGDI(ScreenPtr pScreen); @@ -750,6 +753,12 @@ winBltExposedRegionsShadowGDI(ScreenPtr pScreen) /* BeginPaint gives us an hdc that clips to the invalidated region */ hdcUpdate = BeginPaint(pScreenPriv->hwndScreen, &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(pScreenPriv->hwndScreen, &ps); + return 0; + } /* Realize the palette, if we have one */ if (pScreenPriv->pcmapInstalled != NULL) { @@ -759,11 +768,30 @@ winBltExposedRegionsShadowGDI(ScreenPtr pScreen) RealizePalette(hdcUpdate); } - /* Our BitBlt will be clipped to the invalidated region */ - BitBlt(hdcUpdate, - 0, 0, - pScreenInfo->dwWidth, pScreenInfo->dwHeight, - pScreenPriv->hdcShadow, 0, 0, SRCCOPY); + /* 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, + ps.rcPaint.top, + 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("winBltExposedRegionsShadowGDI - BitBlt failed: %s\n", + (LPSTR) lpMsgBuf); + LocalFree(lpMsgBuf); + } /* EndPaint frees the DC */ EndPaint(pScreenPriv->hwndScreen, &ps); @@ -776,6 +804,128 @@ 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; + } + +#ifdef COMPOSITE + if (pWin->redirectDraw != RedirectDrawNone) { + HBITMAP hBitmap; + HDC hdcPixmap; + PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin); + winPrivPixmapPtr pPixmapPriv = winGetPixmapPriv(pPixmap); + + /* window pixmap format is the same as the screen pixmap */ + assert(pPixmap->drawable.bitsPerPixel > 8); + + /* Get the window bitmap from the pixmap */ + hBitmap = pPixmapPriv->hBitmap; + + /* XXX: There may be a need for a slow-path here: If hBitmap is NULL + (because we couldn't back the pixmap with a Windows DIB), we should + fall-back to creating a Windows DIB from the pixmap, then deleting it + after the BitBlt (as this this code did before the fast-path was + added). */ + if (!hBitmap) { + ErrorF("winBltExposedWindowRegionShadowGDI - slow path unimplemented\n"); + } + + /* 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 DC */ + DeleteDC(hdcPixmap); + } + else +#endif + { + /* 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); + } + } + + /* If part of the invalidated region is outside the window (which can happen + if the native window is being re-sized), fill that area with black */ + if (ps.rcPaint.right > ps.rcPaint.left + pWin->drawable.width) { + BitBlt(hdcUpdate, + ps.rcPaint.left + pWin->drawable.width, + ps.rcPaint.top, + ps.rcPaint.right - (ps.rcPaint.left + pWin->drawable.width), + ps.rcPaint.bottom - ps.rcPaint.top, + NULL, + 0, 0, + BLACKNESS); + } + + if (ps.rcPaint.bottom > ps.rcPaint.top + pWin->drawable.height) { + BitBlt(hdcUpdate, + ps.rcPaint.left, + ps.rcPaint.top + pWin->drawable.height, + ps.rcPaint.right - ps.rcPaint.left, + ps.rcPaint.bottom - (ps.rcPaint.top + pWin->drawable.height), + NULL, + 0, 0, + BLACKNESS); + } + + /* EndPaint frees the DC */ + EndPaint(hWnd, &ps); + + return TRUE; +} + /* * Do any engine-specific appliation-activation processing */ @@ -1119,6 +1269,7 @@ winSetEngineFunctionsShadowGDI(ScreenPtr pScreen) pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowWindowed; pScreenPriv->pwinFinishScreenInit = winFinishScreenInitFB; pScreenPriv->pwinBltExposedRegions = winBltExposedRegionsShadowGDI; + pScreenPriv->pwinBltExposedWindowRegion = winBltExposedWindowRegionShadowGDI; pScreenPriv->pwinActivateApp = winActivateAppShadowGDI; pScreenPriv->pwinRedrawScreen = winRedrawScreenShadowGDI; pScreenPriv->pwinRealizeInstalledPalette = diff --git a/hw/xwin/winvalargs.c b/hw/xwin/winvalargs.c index 585544eab..008c111a6 100644 --- a/hw/xwin/winvalargs.c +++ b/hw/xwin/winvalargs.c @@ -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"); diff --git a/hw/xwin/winwindow.h b/hw/xwin/winwindow.h index 959ce152a..402b9e63c 100644 --- a/hw/xwin/winwindow.h +++ b/hw/xwin/winwindow.h @@ -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); diff --git a/hw/xwin/winwndproc.c b/hw/xwin/winwndproc.c index 16b5f0565..e375be9c1 100644 --- a/hw/xwin/winwndproc.c +++ b/hw/xwin/winwndproc.c @@ -238,7 +238,6 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) struct GetMonitorInfoData data; if (QueryMonitor(s_pScreenInfo->iMonitor, &data)) { - if (data.bMonitorSpecifiedExists == TRUE) { dwWidth = data.monitorWidth; dwHeight = data.monitorHeight; /* @@ -250,7 +249,6 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) ErrorF("Monitor number %d no longer exists!\n", s_pScreenInfo->iMonitor); } - } } /* diff --git a/include/dix-config.h.in b/include/dix-config.h.in index 9eb1a924e..b463a17f3 100644 --- a/include/dix-config.h.in +++ b/include/dix-config.h.in @@ -512,4 +512,7 @@ /* Have header */ #undef HAVE_SYS_SYSMACROS_H +/* Have sigprocmask */ +#undef HAVE_SIGPROCMASK + #endif /* _DIX_CONFIG_H_ */ diff --git a/include/glxvndabi.h b/include/glxvndabi.h index b78306d23..71f36e722 100644 --- a/include/glxvndabi.h +++ b/include/glxvndabi.h @@ -75,7 +75,7 @@ * will still work. */ #define GLXSERVER_VENDOR_ABI_MAJOR_VERSION 0 -#define GLXSERVER_VENDOR_ABI_MINOR_VERSION 0 +#define GLXSERVER_VENDOR_ABI_MINOR_VERSION 1 #if defined(__cplusplus) extern "C" { @@ -236,6 +236,17 @@ typedef struct GlxServerExportsRec { * \param client The client. */ int (* forwardRequest) (GlxServerVendor *vendor, ClientPtr client); + + /** + * Sets the vendor library to use for a screen for a specific client. + * + * This function changes which vendor should handle GLX requests for a + * screen. Unlike \c setScreenVendor, this function can be called at any + * time, and only applies to requests from a single client. + * + * This function is available in GLXVND version 0.1 or later. + */ + Bool (* setClientScreenVendor) (ClientPtr client, ScreenPtr screen, GlxServerVendor *vendor); } GlxServerExports; extern _X_EXPORT const GlxServerExports glxServer; diff --git a/include/meson.build b/include/meson.build index 65781b7a0..2c1b49e06 100644 --- a/include/meson.build +++ b/include/meson.build @@ -60,6 +60,9 @@ else if not enable_input_thread and get_option('input_thread') == 'true' error('Input thread enabled and PTHREAD_MUTEX_RECURSIVE not found') endif + if host_machine.system() == 'windows' and get_option('input_thread') == 'auto' + enable_input_thread = false + endif endif conf_data.set('HAVE_INPUTTHREAD', enable_input_thread) @@ -152,6 +155,7 @@ conf_data.set('HAVE_SETEUID', cc.has_function('seteuid')) conf_data.set('HAVE_SETITIMER', cc.has_function('setitimer')) conf_data.set('HAVE_SHMCTL64', cc.has_function('shmctl64')) conf_data.set('HAVE_SIGACTION', cc.has_function('sigaction')) +conf_data.set('HAVE_SIGPROCMASK', cc.has_function('sigprocmask')) conf_data.set('HAVE_STRCASECMP', cc.has_function('strcasecmp')) conf_data.set('HAVE_STRCASESTR', cc.has_function('strcasestr')) conf_data.set('HAVE_STRLCAT', cc.has_function('strlcat', dependencies: libbsd_dep)) diff --git a/include/os.h b/include/os.h index a1835cd6a..bb3348b18 100644 --- a/include/os.h +++ b/include/os.h @@ -721,6 +721,10 @@ os_move_fd(int fd); #include +#if defined(WIN32) && !defined(__CYGWIN__) +typedef _sigset_t sigset_t; +#endif + extern _X_EXPORT int xthread_sigmask(int how, const sigset_t *set, sigset_t *oldest); diff --git a/mi/mibitblt.c b/mi/mibitblt.c index 4f7e29170..84f8da65a 100644 --- a/mi/mibitblt.c +++ b/mi/mibitblt.c @@ -62,6 +62,10 @@ SOFTWARE. #include #include "servermd.h" +#ifdef __MINGW32__ +#define ffs __builtin_ffs +#endif + /* MICOPYAREA -- public entry for the CopyArea request * For each rectangle in the source region * get the pixels with GetSpans diff --git a/os/inputthread.c b/os/inputthread.c index e6694afda..361d96efa 100644 --- a/os/inputthread.c +++ b/os/inputthread.c @@ -558,7 +558,11 @@ extern int InputThreadUnregisterDev(int fd) int xthread_sigmask(int how, const sigset_t *set, sigset_t *oldset) { +#ifdef HAVE_SIGPROCMASK return sigprocmask(how, set, oldset); +#else + return 0; +#endif } #endif diff --git a/os/utils.c b/os/utils.c index f04bf8045..d1cd07ccc 100644 --- a/os/utils.c +++ b/os/utils.c @@ -1281,7 +1281,7 @@ SmartScheduleInit(void) #endif } -#ifdef SIG_BLOCK +#ifdef HAVE_SIGPROCMASK static sigset_t PreviousSignalMask; static int BlockedSignalCount; #endif @@ -1289,7 +1289,7 @@ static int BlockedSignalCount; void OsBlockSignals(void) { -#ifdef SIG_BLOCK +#ifdef HAVE_SIGPROCMASK if (BlockedSignalCount++ == 0) { sigset_t set; @@ -1311,7 +1311,7 @@ OsBlockSignals(void) void OsReleaseSignals(void) { -#ifdef SIG_BLOCK +#ifdef HAVE_SIGPROCMASK if (--BlockedSignalCount == 0) { xthread_sigmask(SIG_SETMASK, &PreviousSignalMask, 0); } @@ -1321,7 +1321,7 @@ OsReleaseSignals(void) void OsResetSignals(void) { -#ifdef SIG_BLOCK +#ifdef HAVE_SIGPROCMASK while (BlockedSignalCount > 0) OsReleaseSignals(); input_force_unlock(); diff --git a/os/xserver_poll.c b/os/xserver_poll.c index f152cda21..1927dfa10 100644 --- a/os/xserver_poll.c +++ b/os/xserver_poll.c @@ -84,6 +84,10 @@ #include /* string functions */ #include "xserver_poll.h" +#if defined(WIN32) && !defined(__CYGWIN__) +#include +#endif + /*---------------------------------------------------------------------------*\ Macros \*---------------------------------------------------------------------------*/ diff --git a/present/meson.build b/present/meson.build index e316af20d..3dc1fc04b 100644 --- a/present/meson.build +++ b/present/meson.build @@ -22,7 +22,7 @@ libxserver_present = static_library('libxserver_present', include_directories: inc, dependencies: [ common_dep, - dependency('presentproto', version: '>= 1.1') + dependency('presentproto', version: '>= 1.2') ], c_args: '-DHAVE_XORG_CONFIG_H' )