diff options
118 files changed, 5709 insertions, 2572 deletions
diff --git a/composite/compwindow.c b/composite/compwindow.c index 77bdfa23c..96a8971c2 100644 --- a/composite/compwindow.c +++ b/composite/compwindow.c @@ -104,7 +104,7 @@ compRepaintBorder(ClientPtr pClient, void *closure) RegionNull(&exposed); RegionSubtract(&exposed, &pWindow->borderClip, &pWindow->winSize); - miPaintWindow(pWindow, &exposed, PW_BORDER); + (*pWindow->drawable.pScreen->PaintWindow)(pWindow, &exposed, PW_BORDER); RegionUninit(&exposed); } return TRUE; diff --git a/configure.ac b/configure.ac index 16832c2c8..cb6df31bd 100644 --- a/configure.ac +++ b/configure.ac @@ -83,6 +83,16 @@ AC_PROG_YACC AC_SYS_LARGEFILE XORG_PROG_RAWCPP +dnl we really need yacc and lex to build tarballs made by cygport directly from a git tag not 'make dist' +AC_PATH_PROG(YACC_INST, $YACC) +if test -z "$YACC_INST"; then + AC_MSG_ERROR([yacc not found]) +fi +AC_PATH_PROG(LEX_INST, $LEX) +if test -z "$LEX_INST"; then + AC_MSG_ERROR([lex not found]) +fi + # Quoted so that make will expand $(CWARNFLAGS) in makefiles to allow # easier overrides at build time. XSERVER_CFLAGS='$(CWARNFLAGS)' @@ -609,6 +619,7 @@ AC_ARG_ENABLE(vgahw, AS_HELP_STRING([--enable-vgahw], [Build Xorg with AC_ARG_ENABLE(vbe, AS_HELP_STRING([--enable-vbe], [Build Xorg with VBE module (default: enabled)]), [VBE=$enableval], [VBE=yes]) AC_ARG_ENABLE(int10-module, AS_HELP_STRING([--enable-int10-module], [Build Xorg with int10 module (default: enabled)]), [INT10MODULE=$enableval], [INT10MODULE=yes]) AC_ARG_ENABLE(windowswm, AS_HELP_STRING([--enable-windowswm], [Build XWin with WindowsWM extension (default: no)]), [WINDOWSWM=$enableval], [WINDOWSWM=no]) +AC_ARG_ENABLE(windowsdri, AS_HELP_STRING([--enable-windowsdri], [Build XWin with WindowsDRI extension (default: auto)]), [WINDOWSDRI=$enableval], [WINDOWSDRI=auto]) AC_ARG_ENABLE(libdrm, AS_HELP_STRING([--enable-libdrm], [Build Xorg with libdrm support (default: enabled)]), [DRM=$enableval],[DRM=yes]) AC_ARG_ENABLE(clientids, AS_HELP_STRING([--disable-clientids], [Build Xorg with client ID tracking (default: enabled)]), [CLIENTIDS=$enableval], [CLIENTIDS=yes]) AC_ARG_ENABLE(pciaccess, AS_HELP_STRING([--enable-pciaccess], [Build Xorg with pciaccess library (default: enabled)]), [PCI=$enableval], [PCI=yes]) @@ -2147,7 +2158,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]) + PKG_CHECK_MODULES([XWINMODULES],[x11 xdmcp xau xfixes x11-xcb xcb-image xcb-icccm xcomposite]) if test "x$WINDOWSWM" = xauto; then PKG_CHECK_EXISTS($WINDOWSWMPROTO, [WINDOWSWM=yes], [WINDOWSWM=no]) @@ -2158,6 +2169,10 @@ if test "x$XWIN" = xyes; then AC_DEFINE(ROOTLESS,1,[Build Rootless code]) fi + if test "x$WINDOWSDRI" = xauto; then + PKG_CHECK_EXISTS([windowsdriproto], [WINDOWSDRI=yes], [WINDOWSDRI=no]) + fi + case $host_os in cygwin*) XWIN_SERVER_NAME=XWin @@ -2211,6 +2226,7 @@ AM_CONDITIONAL(XWIN_MULTIWINDOW, [test "x$XWIN" = xyes]) AM_CONDITIONAL(XWIN_MULTIWINDOWEXTWM, [test "x$XWIN" = xyes && test "x$WINDOWSWM" = xyes]) AM_CONDITIONAL(XWIN_CLIPBOARD, [test "x$XWIN" = xyes]) AM_CONDITIONAL(XWIN_GLX_WINDOWS, [test "x$XWIN" = xyes && test "x$AIGLX" = xyes]) +AM_CONDITIONAL(XWIN_WINDOWS_DRI, [test "x$XWIN" = xyes && test "x$WINDOWSDRI" = xyes]) AM_CONDITIONAL(XWIN_RANDR, [test "x$XWIN" = xyes]) AM_CONDITIONAL(XWIN_XV, [test "x$XWIN" = xyes && test "x$XV" = xyes]) @@ -2604,9 +2620,11 @@ hw/vfb/man/Makefile hw/xnest/Makefile hw/xnest/man/Makefile hw/xwin/Makefile +hw/xwin/dri/Makefile hw/xwin/glx/Makefile hw/xwin/man/Makefile hw/xwin/winclipboard/Makefile +hw/xwin/wmutil/Makefile hw/xquartz/Makefile hw/xquartz/GL/Makefile hw/xquartz/bundle/Makefile diff --git a/dix/dispatch.c b/dix/dispatch.c index 17fa75e19..d77d37c4e 100644 --- a/dix/dispatch.c +++ b/dix/dispatch.c @@ -221,7 +221,7 @@ UpdateCurrentTimeIf(void) #define SMART_SCHEDULE_DEFAULT_INTERVAL 5 #define SMART_SCHEDULE_MAX_SLICE 15 -#if defined(WIN32) && !defined(__CYGWIN__) +#if defined(WIN32) || defined(__CYGWIN__) Bool SmartScheduleDisable = TRUE; #else Bool SmartScheduleDisable = FALSE; diff --git a/dix/window.c b/dix/window.c index d49276c98..4e37795de 100644 --- a/dix/window.c +++ b/dix/window.c @@ -122,7 +122,6 @@ Equipment Corporation. #endif #include "dixevents.h" #include "globals.h" -#include "mi.h" /* miPaintWindow */ #ifdef COMPOSITE #include "compint.h" #endif @@ -1470,7 +1469,7 @@ ChangeWindowAttributes(WindowPtr pWin, Mask vmask, XID *vlist, ClientPtr client) RegionNull(&exposed); RegionSubtract(&exposed, &pWin->borderClip, &pWin->winSize); - miPaintWindow(pWin, &exposed, PW_BORDER); + (*pWin->drawable.pScreen->PaintWindow)(pWin, &exposed, PW_BORDER); RegionUninit(&exposed); } return error; diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index 6160032f0..3bed1920b 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -673,7 +673,7 @@ glamor_egl_screen_init(ScreenPtr screen, struct glamor_context *glamor_ctx) #ifdef DRI3 if (glamor_egl->dri3_capable) { - glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); /* Tell the core that we have the interfaces for import/export * of pixmaps. */ diff --git a/glx/glxcmds.c b/glx/glxcmds.c index 0416dac09..1247cf0f5 100644 --- a/glx/glxcmds.c +++ b/glx/glxcmds.c @@ -145,7 +145,7 @@ validGlxContext(ClientPtr client, XID id, int access_mode, return TRUE; } -static int +int validGlxDrawable(ClientPtr client, XID id, int type, int access_mode, __GLXdrawable ** drawable, int *err) { diff --git a/glx/glxdriswrast.c b/glx/glxdriswrast.c index e8e53bfdb..503f2a122 100644 --- a/glx/glxdriswrast.c +++ b/glx/glxdriswrast.c @@ -415,7 +415,17 @@ initializeExtensions(__GLXDRIscreen * screen) extensions = screen->core->getExtensions(screen->driScreen); + /* GLX_MESA_copy_sub_buffer is always enabled. */ + __glXEnableExtension(screen->glx_enable_bits, "GLX_MESA_copy_sub_buffer"); + for (i = 0; extensions[i]; i++) { + if (strcmp(extensions[i]->name, __DRI_READ_DRAWABLE) == 0) { + __glXEnableExtension(screen->glx_enable_bits, + "GLX_SGI_make_current_read"); + + LogMessage(X_INFO, "AIGLX: enabled GLX_SGI_make_current_read\n"); + } + if (strcmp(extensions[i]->name, __DRI_COPY_SUB_BUFFER) == 0) { screen->copySubBuffer = (const __DRIcopySubBufferExtension *) extensions[i]; @@ -424,6 +434,7 @@ initializeExtensions(__GLXDRIscreen * screen) if (strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0) { screen->texBuffer = (const __DRItexBufferExtension *) extensions[i]; /* GLX_EXT_texture_from_pixmap is always enabled. */ + LogMessage(X_INFO, "AIGLX: enabled GLX_EXT_texture_from_pixmap\n"); } #ifdef __DRI2_FLUSH_CONTROL diff --git a/glx/glxscreens.c b/glx/glxscreens.c index b0ad3b7bc..288a0be88 100644 --- a/glx/glxscreens.c +++ b/glx/glxscreens.c @@ -160,20 +160,6 @@ static const char GLServerExtensions[] = */ unsigned glxMajorVersion = SERVER_GLX_MAJOR_VERSION; unsigned glxMinorVersion = SERVER_GLX_MINOR_VERSION; -static char GLXServerExtensions[] = - "GLX_ARB_multisample " - "GLX_EXT_visual_info " - "GLX_EXT_visual_rating " - "GLX_EXT_import_context " - "GLX_EXT_texture_from_pixmap " - "GLX_OML_swap_method " - "GLX_SGI_make_current_read " -#ifndef __APPLE__ - "GLX_SGIS_multisample " -#endif - "GLX_SGIX_fbconfig " - "GLX_SGIX_pbuffer " - "GLX_MESA_copy_sub_buffer "; static Bool glxCloseScreen(ScreenPtr pScreen) @@ -329,7 +315,7 @@ __glXScreenInit(__GLXscreen * pGlxScreen, ScreenPtr pScreen) pGlxScreen->pScreen = pScreen; pGlxScreen->GLextensions = strdup(GLServerExtensions); - pGlxScreen->GLXextensions = strdup(GLXServerExtensions); + pGlxScreen->GLXextensions = strdup(""); /* All GLX providers must support all of the functionality required for at * least GLX 1.2. If the provider supports a higher version, the GLXminor diff --git a/glx/indirect_dispatch.c b/glx/indirect_dispatch.c index 24784e693..b5e00e1ab 100644 --- a/glx/indirect_dispatch.c +++ b/glx/indirect_dispatch.c @@ -4035,6 +4035,99 @@ __glXDisp_DrawBuffers(GLbyte * pc) DrawBuffers(n, (const GLenum *) (pc + 4)); } +int +__glXDisp_GetVertexAttribdv(__GLXclientState * cl, GLbyte * pc) +{ + PFNGLGETVERTEXATTRIBDVPROC GetVertexAttribdv = + __glGetProcAddress("glGetVertexAttribdv"); + xGLXVendorPrivateReq *const req = (xGLXVendorPrivateReq *) pc; + int error; + __GLXcontext *const cx = __glXForceCurrent(cl, req->contextTag, &error); + + pc += __GLX_VENDPRIV_HDR_SIZE; + if (cx != NULL) { + const GLenum pname = *(GLenum *) (pc + 4); + + const GLuint compsize = __glGetVertexAttribdv_size(pname); + GLdouble answerBuffer[200]; + GLdouble *params = + __glXGetAnswerBuffer(cl, compsize * 8, answerBuffer, + sizeof(answerBuffer), 8); + + if (params == NULL) + return BadAlloc; + __glXClearErrorOccured(); + + GetVertexAttribdv(*(GLuint *) (pc + 0), pname, params); + __glXSendReply(cl->client, params, compsize, 8, GL_FALSE, 0); + error = Success; + } + + return error; +} + +int +__glXDisp_GetVertexAttribfv(__GLXclientState * cl, GLbyte * pc) +{ + PFNGLGETVERTEXATTRIBFVPROC GetVertexAttribfv = + __glGetProcAddress("glGetVertexAttribfv"); + xGLXVendorPrivateReq *const req = (xGLXVendorPrivateReq *) pc; + int error; + __GLXcontext *const cx = __glXForceCurrent(cl, req->contextTag, &error); + + pc += __GLX_VENDPRIV_HDR_SIZE; + if (cx != NULL) { + const GLenum pname = *(GLenum *) (pc + 4); + + const GLuint compsize = __glGetVertexAttribfv_size(pname); + GLfloat answerBuffer[200]; + GLfloat *params = + __glXGetAnswerBuffer(cl, compsize * 4, answerBuffer, + sizeof(answerBuffer), 4); + + if (params == NULL) + return BadAlloc; + __glXClearErrorOccured(); + + GetVertexAttribfv(*(GLuint *) (pc + 0), pname, params); + __glXSendReply(cl->client, params, compsize, 4, GL_FALSE, 0); + error = Success; + } + + return error; +} + +int +__glXDisp_GetVertexAttribiv(__GLXclientState * cl, GLbyte * pc) +{ + PFNGLGETVERTEXATTRIBIVPROC GetVertexAttribiv = + __glGetProcAddress("glGetVertexAttribiv"); + xGLXVendorPrivateReq *const req = (xGLXVendorPrivateReq *) pc; + int error; + __GLXcontext *const cx = __glXForceCurrent(cl, req->contextTag, &error); + + pc += __GLX_VENDPRIV_HDR_SIZE; + if (cx != NULL) { + const GLenum pname = *(GLenum *) (pc + 4); + + const GLuint compsize = __glGetVertexAttribiv_size(pname); + GLint answerBuffer[200]; + GLint *params = + __glXGetAnswerBuffer(cl, compsize * 4, answerBuffer, + sizeof(answerBuffer), 4); + + if (params == NULL) + return BadAlloc; + __glXClearErrorOccured(); + + GetVertexAttribiv(*(GLuint *) (pc + 0), pname, params); + __glXSendReply(cl->client, params, compsize, 4, GL_FALSE, 0); + error = Success; + } + + return error; +} + void __glXDisp_VertexAttrib1dv(GLbyte * pc) { @@ -5125,3 +5218,19 @@ __glXDisp_ActiveStencilFaceEXT(GLbyte * pc) __glGetProcAddress("glActiveStencilFaceEXT"); ActiveStencilFaceEXT(*(GLenum *) (pc + 0)); } + +void +__glXDisp_BindFramebufferEXT(GLbyte * pc) +{ + PFNGLBINDFRAMEBUFFEREXTPROC BindFramebufferEXT = + __glGetProcAddress("glBindFramebufferEXT"); + BindFramebufferEXT(*(GLenum *) (pc + 0), *(GLuint *) (pc + 4)); +} + +void +__glXDisp_BindRenderbufferEXT(GLbyte * pc) +{ + PFNGLBINDRENDERBUFFEREXTPROC BindRenderbufferEXT = + __glGetProcAddress("glBindRenderbufferEXT"); + BindRenderbufferEXT(*(GLenum *) (pc + 0), *(GLuint *) (pc + 4)); +} diff --git a/glx/indirect_dispatch.h b/glx/indirect_dispatch.h index 536be60ac..8f8b5ae22 100644 --- a/glx/indirect_dispatch.h +++ b/glx/indirect_dispatch.h @@ -116,6 +116,10 @@ extern _X_HIDDEN void __glXDisp_LightModeliv(GLbyte * pc); extern _X_HIDDEN void __glXDispSwap_LightModeliv(GLbyte * pc); extern _X_HIDDEN void __glXDisp_VertexAttribs1dvNV(GLbyte * pc); extern _X_HIDDEN void __glXDispSwap_VertexAttribs1dvNV(GLbyte * pc); +extern _X_HIDDEN int __glXDisp_GetVertexAttribfv(struct __GLXclientStateRec *, + GLbyte *); +extern _X_HIDDEN int __glXDispSwap_GetVertexAttribfv(struct __GLXclientStateRec + *, GLbyte *); extern _X_HIDDEN void __glXDisp_Normal3bv(GLbyte * pc); extern _X_HIDDEN void __glXDispSwap_Normal3bv(GLbyte * pc); extern _X_HIDDEN int __glXDisp_VendorPrivate(struct __GLXclientStateRec *, @@ -413,6 +417,10 @@ extern _X_HIDDEN void __glXDisp_TexGenfv(GLbyte * pc); extern _X_HIDDEN void __glXDispSwap_TexGenfv(GLbyte * pc); extern _X_HIDDEN void __glXDisp_VertexAttrib4dvNV(GLbyte * pc); extern _X_HIDDEN void __glXDispSwap_VertexAttrib4dvNV(GLbyte * pc); +extern _X_HIDDEN int __glXDisp_GetVertexAttribiv(struct __GLXclientStateRec *, + GLbyte *); +extern _X_HIDDEN int __glXDispSwap_GetVertexAttribiv(struct __GLXclientStateRec + *, GLbyte *); extern _X_HIDDEN void __glXDisp_DrawBuffers(GLbyte * pc); extern _X_HIDDEN void __glXDispSwap_DrawBuffers(GLbyte * pc); extern _X_HIDDEN int __glXDisp_CreateContextWithConfigSGIX(struct @@ -552,6 +560,8 @@ extern _X_HIDDEN void __glXDisp_MultiTexCoord1sv(GLbyte * pc); extern _X_HIDDEN void __glXDispSwap_MultiTexCoord1sv(GLbyte * pc); extern _X_HIDDEN void __glXDisp_RasterPos3sv(GLbyte * pc); extern _X_HIDDEN void __glXDispSwap_RasterPos3sv(GLbyte * pc); +extern _X_HIDDEN void __glXDisp_BindFramebufferEXT(GLbyte * pc); +extern _X_HIDDEN void __glXDispSwap_BindFramebufferEXT(GLbyte * pc); extern _X_HIDDEN void __glXDisp_PushAttrib(GLbyte * pc); extern _X_HIDDEN void __glXDispSwap_PushAttrib(GLbyte * pc); extern _X_HIDDEN int __glXDisp_DestroyPbuffer(struct __GLXclientStateRec *, @@ -676,6 +686,8 @@ extern _X_HIDDEN int __glXDisp_GetTexParameteriv(struct __GLXclientStateRec *, GLbyte *); extern _X_HIDDEN int __glXDispSwap_GetTexParameteriv(struct __GLXclientStateRec *, GLbyte *); +extern _X_HIDDEN void __glXDisp_VertexAttribs4dvNV(GLbyte * pc); +extern _X_HIDDEN void __glXDispSwap_VertexAttribs4dvNV(GLbyte * pc); extern _X_HIDDEN void __glXDisp_VertexAttrib3sv(GLbyte * pc); extern _X_HIDDEN void __glXDispSwap_VertexAttrib3sv(GLbyte * pc); extern _X_HIDDEN int __glXDisp_IsQuery(struct __GLXclientStateRec *, GLbyte *); @@ -776,8 +788,6 @@ extern _X_HIDDEN void __glXDisp_ColorMaterial(GLbyte * pc); extern _X_HIDDEN void __glXDispSwap_ColorMaterial(GLbyte * pc); extern _X_HIDDEN void __glXDisp_VertexAttribs1svNV(GLbyte * pc); extern _X_HIDDEN void __glXDispSwap_VertexAttribs1svNV(GLbyte * pc); -extern _X_HIDDEN void __glXDisp_VertexAttrib1fvNV(GLbyte * pc); -extern _X_HIDDEN void __glXDispSwap_VertexAttrib1fvNV(GLbyte * pc); extern _X_HIDDEN int __glXDisp_GetSeparableFilter(struct __GLXclientStateRec *, GLbyte *); extern _X_HIDDEN int __glXDispSwap_GetSeparableFilter(struct __GLXclientStateRec @@ -803,6 +813,10 @@ extern _X_HIDDEN int __glXDispSwap_RenderLarge(struct __GLXclientStateRec *, GLbyte *); extern _X_HIDDEN void __glXDisp_PolygonOffset(GLbyte * pc); extern _X_HIDDEN void __glXDispSwap_PolygonOffset(GLbyte * pc); +extern _X_HIDDEN int __glXDisp_GetVertexAttribdv(struct __GLXclientStateRec *, + GLbyte *); +extern _X_HIDDEN int __glXDispSwap_GetVertexAttribdv(struct __GLXclientStateRec + *, GLbyte *); extern _X_HIDDEN void __glXDisp_Normal3dv(GLbyte * pc); extern _X_HIDDEN void __glXDispSwap_Normal3dv(GLbyte * pc); extern _X_HIDDEN void __glXDisp_Lightf(GLbyte * pc); @@ -960,6 +974,8 @@ extern _X_HIDDEN void __glXDisp_CopyTexImage1D(GLbyte * pc); extern _X_HIDDEN void __glXDispSwap_CopyTexImage1D(GLbyte * pc); extern _X_HIDDEN void __glXDisp_RasterPos2dv(GLbyte * pc); extern _X_HIDDEN void __glXDispSwap_RasterPos2dv(GLbyte * pc); +extern _X_HIDDEN void __glXDisp_VertexAttrib1fvNV(GLbyte * pc); +extern _X_HIDDEN void __glXDispSwap_VertexAttrib1fvNV(GLbyte * pc); extern _X_HIDDEN void __glXDisp_Fogiv(GLbyte * pc); extern _X_HIDDEN void __glXDispSwap_Fogiv(GLbyte * pc); extern _X_HIDDEN void __glXDisp_EndQuery(GLbyte * pc); @@ -1010,6 +1026,8 @@ extern _X_HIDDEN void __glXDisp_MultiTexCoord1iv(GLbyte * pc); extern _X_HIDDEN void __glXDispSwap_MultiTexCoord1iv(GLbyte * pc); extern _X_HIDDEN void __glXDisp_Vertex2fv(GLbyte * pc); extern _X_HIDDEN void __glXDispSwap_Vertex2fv(GLbyte * pc); +extern _X_HIDDEN void __glXDisp_BindRenderbufferEXT(GLbyte * pc); +extern _X_HIDDEN void __glXDispSwap_BindRenderbufferEXT(GLbyte * pc); extern _X_HIDDEN void __glXDisp_Vertex3sv(GLbyte * pc); extern _X_HIDDEN void __glXDispSwap_Vertex3sv(GLbyte * pc); extern _X_HIDDEN int __glXDisp_GetQueryObjectiv(struct __GLXclientStateRec *, @@ -1156,8 +1174,6 @@ extern _X_HIDDEN int __glXDisp_GetConvolutionFilterEXT(struct extern _X_HIDDEN int __glXDispSwap_GetConvolutionFilterEXT(struct __GLXclientStateRec *, GLbyte *); -extern _X_HIDDEN void __glXDisp_VertexAttribs4dvNV(GLbyte * pc); -extern _X_HIDDEN void __glXDispSwap_VertexAttribs4dvNV(GLbyte * pc); extern _X_HIDDEN int __glXDisp_GetTexGenfv(struct __GLXclientStateRec *, GLbyte *); extern _X_HIDDEN int __glXDispSwap_GetTexGenfv(struct __GLXclientStateRec *, diff --git a/glx/indirect_dispatch_swap.c b/glx/indirect_dispatch_swap.c index 7ebcc6330..b2c0b39e4 100644 --- a/glx/indirect_dispatch_swap.c +++ b/glx/indirect_dispatch_swap.c @@ -3847,8 +3847,8 @@ __glXDispSwap_MultiTexCoord1dv(GLbyte * pc) #endif glMultiTexCoord1dvARB((GLenum) bswap_ENUM(pc + 8), - (const GLdouble *) bswap_64_array((uint64_t *) (pc + 0), - 1)); + (const GLdouble *) + bswap_64_array((uint64_t *) (pc + 0), 1)); } void @@ -3871,8 +3871,8 @@ void __glXDispSwap_MultiTexCoord1sv(GLbyte * pc) { glMultiTexCoord1svARB((GLenum) bswap_ENUM(pc + 0), - (const GLshort *) bswap_16_array((uint16_t *) (pc + 4), - 1)); + (const GLshort *) + bswap_16_array((uint16_t *) (pc + 4), 1)); } void @@ -3886,8 +3886,8 @@ __glXDispSwap_MultiTexCoord2dv(GLbyte * pc) #endif glMultiTexCoord2dvARB((GLenum) bswap_ENUM(pc + 16), - (const GLdouble *) bswap_64_array((uint64_t *) (pc + 0), - 2)); + (const GLdouble *) + bswap_64_array((uint64_t *) (pc + 0), 2)); } void @@ -3910,8 +3910,8 @@ void __glXDispSwap_MultiTexCoord2sv(GLbyte * pc) { glMultiTexCoord2svARB((GLenum) bswap_ENUM(pc + 0), - (const GLshort *) bswap_16_array((uint16_t *) (pc + 4), - 2)); + (const GLshort *) + bswap_16_array((uint16_t *) (pc + 4), 2)); } void @@ -3925,8 +3925,8 @@ __glXDispSwap_MultiTexCoord3dv(GLbyte * pc) #endif glMultiTexCoord3dvARB((GLenum) bswap_ENUM(pc + 24), - (const GLdouble *) bswap_64_array((uint64_t *) (pc + 0), - 3)); + (const GLdouble *) + bswap_64_array((uint64_t *) (pc + 0), 3)); } void @@ -3949,8 +3949,8 @@ void __glXDispSwap_MultiTexCoord3sv(GLbyte * pc) { glMultiTexCoord3svARB((GLenum) bswap_ENUM(pc + 0), - (const GLshort *) bswap_16_array((uint16_t *) (pc + 4), - 3)); + (const GLshort *) + bswap_16_array((uint16_t *) (pc + 4), 3)); } void @@ -3964,8 +3964,8 @@ __glXDispSwap_MultiTexCoord4dv(GLbyte * pc) #endif glMultiTexCoord4dvARB((GLenum) bswap_ENUM(pc + 32), - (const GLdouble *) bswap_64_array((uint64_t *) (pc + 0), - 4)); + (const GLdouble *) + bswap_64_array((uint64_t *) (pc + 0), 4)); } void @@ -3988,8 +3988,8 @@ void __glXDispSwap_MultiTexCoord4sv(GLbyte * pc) { glMultiTexCoord4svARB((GLenum) bswap_ENUM(pc + 0), - (const GLshort *) bswap_16_array((uint16_t *) (pc + 4), - 4)); + (const GLshort *) + bswap_16_array((uint16_t *) (pc + 4), 4)); } void @@ -4451,6 +4451,105 @@ __glXDispSwap_DrawBuffers(GLbyte * pc) DrawBuffers(n, (const GLenum *) bswap_32_array((uint32_t *) (pc + 4), 0)); } +int +__glXDispSwap_GetVertexAttribdv(__GLXclientState * cl, GLbyte * pc) +{ + PFNGLGETVERTEXATTRIBDVPROC GetVertexAttribdv = + __glGetProcAddress("glGetVertexAttribdv"); + xGLXVendorPrivateReq *const req = (xGLXVendorPrivateReq *) pc; + int error; + __GLXcontext *const cx = + __glXForceCurrent(cl, bswap_CARD32(&req->contextTag), &error); + + pc += __GLX_VENDPRIV_HDR_SIZE; + if (cx != NULL) { + const GLenum pname = (GLenum) bswap_ENUM(pc + 4); + + const GLuint compsize = __glGetVertexAttribdv_size(pname); + GLdouble answerBuffer[200]; + GLdouble *params = + __glXGetAnswerBuffer(cl, compsize * 8, answerBuffer, + sizeof(answerBuffer), 8); + + if (params == NULL) + return BadAlloc; + __glXClearErrorOccured(); + + GetVertexAttribdv((GLuint) bswap_CARD32(pc + 0), pname, params); + (void) bswap_64_array((uint64_t *) params, compsize); + __glXSendReplySwap(cl->client, params, compsize, 8, GL_FALSE, 0); + error = Success; + } + + return error; +} + +int +__glXDispSwap_GetVertexAttribfv(__GLXclientState * cl, GLbyte * pc) +{ + PFNGLGETVERTEXATTRIBFVPROC GetVertexAttribfv = + __glGetProcAddress("glGetVertexAttribfv"); + xGLXVendorPrivateReq *const req = (xGLXVendorPrivateReq *) pc; + int error; + __GLXcontext *const cx = + __glXForceCurrent(cl, bswap_CARD32(&req->contextTag), &error); + + pc += __GLX_VENDPRIV_HDR_SIZE; + if (cx != NULL) { + const GLenum pname = (GLenum) bswap_ENUM(pc + 4); + + const GLuint compsize = __glGetVertexAttribfv_size(pname); + GLfloat answerBuffer[200]; + GLfloat *params = + __glXGetAnswerBuffer(cl, compsize * 4, answerBuffer, + sizeof(answerBuffer), 4); + + if (params == NULL) + return BadAlloc; + __glXClearErrorOccured(); + + GetVertexAttribfv((GLuint) bswap_CARD32(pc + 0), pname, params); + (void) bswap_32_array((uint32_t *) params, compsize); + __glXSendReplySwap(cl->client, params, compsize, 4, GL_FALSE, 0); + error = Success; + } + + return error; +} + +int +__glXDispSwap_GetVertexAttribiv(__GLXclientState * cl, GLbyte * pc) +{ + PFNGLGETVERTEXATTRIBIVPROC GetVertexAttribiv = + __glGetProcAddress("glGetVertexAttribiv"); + xGLXVendorPrivateReq *const req = (xGLXVendorPrivateReq *) pc; + int error; + __GLXcontext *const cx = + __glXForceCurrent(cl, bswap_CARD32(&req->contextTag), &error); + + pc += __GLX_VENDPRIV_HDR_SIZE; + if (cx != NULL) { + const GLenum pname = (GLenum) bswap_ENUM(pc + 4); + + const GLuint compsize = __glGetVertexAttribiv_size(pname); + GLint answerBuffer[200]; + GLint *params = + __glXGetAnswerBuffer(cl, compsize * 4, answerBuffer, + sizeof(answerBuffer), 4); + + if (params == NULL) + return BadAlloc; + __glXClearErrorOccured(); + + GetVertexAttribiv((GLuint) bswap_CARD32(pc + 0), pname, params); + (void) bswap_32_array((uint32_t *) params, compsize); + __glXSendReplySwap(cl->client, params, compsize, 4, GL_FALSE, 0); + error = Success; + } + + return error; +} + void __glXDispSwap_VertexAttrib1dv(GLbyte * pc) { @@ -5695,3 +5794,21 @@ __glXDispSwap_ActiveStencilFaceEXT(GLbyte * pc) __glGetProcAddress("glActiveStencilFaceEXT"); ActiveStencilFaceEXT((GLenum) bswap_ENUM(pc + 0)); } + +void +__glXDispSwap_BindFramebufferEXT(GLbyte * pc) +{ + PFNGLBINDFRAMEBUFFEREXTPROC BindFramebufferEXT = + __glGetProcAddress("glBindFramebufferEXT"); + BindFramebufferEXT((GLenum) bswap_ENUM(pc + 0), + (GLuint) bswap_CARD32(pc + 4)); +} + +void +__glXDispSwap_BindRenderbufferEXT(GLbyte * pc) +{ + PFNGLBINDRENDERBUFFEREXTPROC BindRenderbufferEXT = + __glGetProcAddress("glBindRenderbufferEXT"); + BindRenderbufferEXT((GLenum) bswap_ENUM(pc + 0), + (GLuint) bswap_CARD32(pc + 4)); +} diff --git a/glx/indirect_size_get.c b/glx/indirect_size_get.c index 7e81e6288..d3ab42999 100644 --- a/glx/indirect_size_get.c +++ b/glx/indirect_size_get.c @@ -603,7 +603,11 @@ __glGetBooleanv_size(GLenum e) case GL_OCCLUSION_TEST_RESULT_HP: case GL_LIGHT_MODEL_COLOR_CONTROL: case GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_ARB: +/* case GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH:*/ case GL_RESET_NOTIFICATION_STRATEGY_ARB: +/* case GL_MAX_DEBUG_GROUP_STACK_DEPTH: */ +/* case GL_DEBUG_GROUP_STACK_DEPTH: */ +/* case GL_MAX_LABEL_LENGTH: */ case GL_CURRENT_FOG_COORD: case GL_FOG_COORDINATE_ARRAY_TYPE: case GL_FOG_COORDINATE_ARRAY_STRIDE: @@ -749,8 +753,11 @@ __glGetBooleanv_size(GLenum e) /* case GL_MAX_SAMPLES_EXT:*/ case GL_MAX_SERVER_WAIT_TIMEOUT: case GL_MAX_DEBUG_MESSAGE_LENGTH_ARB: +/* case GL_MAX_DEBUG_MESSAGE_LENGTH:*/ case GL_MAX_DEBUG_LOGGED_MESSAGES_ARB: +/* case GL_MAX_DEBUG_LOGGED_MESSAGES:*/ case GL_DEBUG_LOGGED_MESSAGES_ARB: +/* case GL_DEBUG_LOGGED_MESSAGES:*/ case GL_RASTER_POSITION_UNCLIPPED_IBM: return 1; case GL_SMOOTH_POINT_SIZE_RANGE: @@ -928,7 +935,9 @@ __glGetPointerv_size(GLenum e) { switch (e) { case GL_DEBUG_CALLBACK_FUNCTION_ARB: +/* case GL_DEBUG_CALLBACK_FUNCTION:*/ case GL_DEBUG_CALLBACK_USER_PARAM_ARB: +/* case GL_DEBUG_CALLBACK_USER_PARAM:*/ return 1; default: return 0; @@ -1105,6 +1114,23 @@ __glGetQueryiv_size(GLenum e) } _X_INTERNAL PURE FASTCALL GLint +__glGetVertexAttribdv_size(GLenum e) +{ + switch (e) { + case GL_VERTEX_PROGRAM_ARB: + case GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB: + case GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB: + case GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB: + case GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB: + case GL_CURRENT_VERTEX_ATTRIB_ARB: + case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB: + return 1; + default: + return 0; + } +} + +_X_INTERNAL PURE FASTCALL GLint __glGetProgramivARB_size(GLenum e) { switch (e) { @@ -1216,5 +1242,7 @@ ALIAS(Fogiv, Fogfv) ALIAS(GetMinmaxParameteriv, GetMinmaxParameterfv) ALIAS(PointParameteriv, PointParameterfv) ALIAS(GetQueryObjectuiv, GetQueryObjectiv) + ALIAS(GetVertexAttribfv, GetVertexAttribdv) + ALIAS(GetVertexAttribiv, GetVertexAttribdv) #undef PURE #undef FASTCALL diff --git a/glx/indirect_size_get.h b/glx/indirect_size_get.h index 5af11d378..e6d010f49 100644 --- a/glx/indirect_size_get.h +++ b/glx/indirect_size_get.h @@ -83,6 +83,9 @@ extern _X_INTERNAL PURE FASTCALL GLint __glGetMinmaxParameteriv_size(GLenum); extern _X_INTERNAL PURE FASTCALL GLint __glGetQueryObjectiv_size(GLenum); extern _X_INTERNAL PURE FASTCALL GLint __glGetQueryObjectuiv_size(GLenum); extern _X_INTERNAL PURE FASTCALL GLint __glGetQueryiv_size(GLenum); +extern _X_INTERNAL PURE FASTCALL GLint __glGetVertexAttribdv_size(GLenum); +extern _X_INTERNAL PURE FASTCALL GLint __glGetVertexAttribfv_size(GLenum); +extern _X_INTERNAL PURE FASTCALL GLint __glGetVertexAttribiv_size(GLenum); extern _X_INTERNAL PURE FASTCALL GLint __glGetProgramivARB_size(GLenum); extern _X_INTERNAL PURE FASTCALL GLint __glGetFramebufferAttachmentParameteriv_size(GLenum); diff --git a/glx/indirect_table.c b/glx/indirect_table.c index f0f0b83c8..b500e39b3 100644 --- a/glx/indirect_table.c +++ b/glx/indirect_table.c @@ -636,8 +636,10 @@ static const void *Render_function_table[408][2] = { /* [ 232] = 232 */ {__glXDisp_EndQuery, __glXDispSwap_EndQuery}, /* [ 233] = 233 */ {__glXDisp_DrawBuffers, __glXDispSwap_DrawBuffers}, /* [ 234] = 234 */ {__glXDisp_ClampColor, __glXDispSwap_ClampColor}, - /* [ 235] = 235 */ {NULL, NULL}, - /* [ 236] = 236 */ {NULL, NULL}, + /* [ 235] = 235 */ {__glXDisp_BindRenderbuffer, + __glXDispSwap_BindRenderbuffer}, + /* [ 236] = 236 */ {__glXDisp_BindFramebuffer, + __glXDispSwap_BindFramebuffer}, /* [ 237] = 237 */ {__glXDisp_FramebufferTextureLayer, __glXDispSwap_FramebufferTextureLayer}, /* [ 238] = 238 */ {NULL, NULL}, @@ -903,14 +905,14 @@ static const void *Render_function_table[408][2] = { /* [ 401] = 4313 */ {NULL, NULL}, /* [ 402] = 4314 */ {NULL, NULL}, /* [ 403] = 4315 */ {NULL, NULL}, - /* [ 404] = 4316 */ {__glXDisp_BindRenderbuffer, - __glXDispSwap_BindRenderbuffer}, + /* [ 404] = 4316 */ {__glXDisp_BindRenderbufferEXT, + __glXDispSwap_BindRenderbufferEXT}, /* [ 405] = 4317 */ {__glXDisp_DeleteRenderbuffers, __glXDispSwap_DeleteRenderbuffers}, /* [ 406] = 4318 */ {__glXDisp_RenderbufferStorage, __glXDispSwap_RenderbufferStorage}, - /* [ 407] = 4319 */ {__glXDisp_BindFramebuffer, - __glXDispSwap_BindFramebuffer}, + /* [ 407] = 4319 */ {__glXDisp_BindFramebufferEXT, + __glXDispSwap_BindFramebufferEXT}, }; static const int_fast16_t Render_size_table[408][2] = { @@ -1149,8 +1151,8 @@ static const int_fast16_t Render_size_table[408][2] = { /* [232] = 232 */ {8, ~0}, /* [233] = 233 */ {8, 36}, /* [234] = 234 */ {12, ~0}, - /* [235] = 235 */ {0, ~0}, - /* [236] = 236 */ {0, ~0}, + /* [235] = 235 */ {12, ~0}, + /* [236] = 236 */ {12, ~0}, /* [237] = 237 */ {24, ~0}, /* [238] = 238 */ {0, ~0}, /* [239] = 239 */ {0, ~0}, @@ -1697,9 +1699,12 @@ static const void *VendorPriv_function_table[104][2] = { /* [ 26] = 1298 */ {NULL, NULL}, /* [ 27] = 1299 */ {NULL, NULL}, /* [ 28] = 1300 */ {NULL, NULL}, - /* [ 29] = 1301 */ {NULL, NULL}, - /* [ 30] = 1302 */ {NULL, NULL}, - /* [ 31] = 1303 */ {NULL, NULL}, + /* [ 29] = 1301 */ {__glXDisp_GetVertexAttribdv, + __glXDispSwap_GetVertexAttribdv}, + /* [ 30] = 1302 */ {__glXDisp_GetVertexAttribfv, + __glXDispSwap_GetVertexAttribfv}, + /* [ 31] = 1303 */ {__glXDisp_GetVertexAttribiv, + __glXDispSwap_GetVertexAttribiv}, /* [ 32] = 1304 */ {__glXDisp_IsProgramARB, __glXDispSwap_IsProgramARB}, /* [ 33] = 1305 */ {__glXDisp_GetProgramLocalParameterfvARB, __glXDispSwap_GetProgramLocalParameterfvARB}, diff --git a/glx/rensize.c b/glx/rensize.c index 6bfe99b2a..021eee44f 100644 --- a/glx/rensize.c +++ b/glx/rensize.c @@ -234,12 +234,14 @@ __glXImageSize(GLenum format, GLenum type, GLenum target, case GL_LUMINANCE_INTEGER_EXT: elementsPerGroup = 1; break; + case GL_RG: case GL_422_EXT: case GL_422_REV_EXT: case GL_422_AVERAGE_EXT: case GL_422_REV_AVERAGE_EXT: case GL_DEPTH_STENCIL_NV: case GL_DEPTH_STENCIL_MESA: + case GL_YCBCR_422_APPLE: case GL_YCBCR_MESA: case GL_LUMINANCE_ALPHA: case GL_LUMINANCE_ALPHA_INTEGER_EXT: diff --git a/hw/dmx/doc/dmx.xml b/hw/dmx/doc/dmx.xml index 6d7df4133..c6c8544ff 100644 --- a/hw/dmx/doc/dmx.xml +++ b/hw/dmx/doc/dmx.xml @@ -1268,7 +1268,7 @@ default routine is chosen during GC validation. <para>Note that some pointers to functions that draw to the screen are stored in the Screen structure. They include GetImage(), GetSpans(), -CopyWindow() and RestoreAreas(). +PaintWindow(), CopyWindow() and RestoreAreas(). </para> </sect3> diff --git a/hw/xfree86/os-support/shared/posix_tty.c b/hw/xfree86/os-support/shared/posix_tty.c index 6e2af001a..8e561430b 100644 --- a/hw/xfree86/os-support/shared/posix_tty.c +++ b/hw/xfree86/os-support/shared/posix_tty.c @@ -56,6 +56,7 @@ #include <xorg-config.h> #endif +#include <sys/select.h> #include <X11/X.h> #include "xf86.h" #include "xf86Priv.h" diff --git a/hw/xfree86/os-support/shared/sigio.c b/hw/xfree86/os-support/shared/sigio.c index c746d02fc..d4f09e56c 100644 --- a/hw/xfree86/os-support/shared/sigio.c +++ b/hw/xfree86/os-support/shared/sigio.c @@ -56,6 +56,7 @@ #include <xorg-config.h> #endif +#include <sys/select.h> #include <X11/X.h> #include "xf86.h" #include "xf86Priv.h" diff --git a/hw/xfree86/sdksyms.sh b/hw/xfree86/sdksyms.sh index 05ac41096..530d6f548 100755 --- a/hw/xfree86/sdksyms.sh +++ b/hw/xfree86/sdksyms.sh @@ -313,8 +313,8 @@ topdir=$1 shift LC_ALL=C export LC_ALL -${CPP:-cpp} "$@" sdksyms.c > /dev/null || exit $? -${CPP:-cpp} "$@" sdksyms.c | ${AWK:-awk} -v topdir=$topdir ' +${CPP:-cpp} "$@" -DSDKSYMS sdksyms.c > /dev/null || exit $? +${CPP:-cpp} "$@" -DSDKSYMS sdksyms.c | ${AWK:-awk} -v topdir=$topdir ' BEGIN { sdk = 0; print("/*"); diff --git a/hw/xquartz/quartz.c b/hw/xquartz/quartz.c index d7229cecb..b0d42b7da 100644 --- a/hw/xquartz/quartz.c +++ b/hw/xquartz/quartz.c @@ -300,7 +300,7 @@ QuartzUpdateScreens(void) quartzProcs->UpdateScreen(pScreen); /* miPaintWindow needs to be called after RootlessUpdateScreenPixmap (from xprUpdateScreen) */ - miPaintWindow(pRoot, &pRoot->borderClip, PW_BACKGROUND); + pScreen->PaintWindow(pRoot, &pRoot->borderClip, PW_BACKGROUND); /* Tell RandR about the new size, so new connections get the correct info */ RRScreenSizeNotify(pScreen); diff --git a/hw/xwin/InitOutput.c b/hw/xwin/InitOutput.c index 654c58c14..029a3d7cd 100644 --- a/hw/xwin/InitOutput.c +++ b/hw/xwin/InitOutput.c @@ -35,12 +35,10 @@ from The Open Group. #include "winmsg.h" #include "winconfig.h" #include "winprefs.h" -#ifdef XWIN_CLIPBOARD -#include "X11/Xlocale.h" -#endif #ifdef DPMSExtension #include "dpmsproc.h" #endif +#include <locale.h> #ifdef __CYGWIN__ #include <mntent.h> #endif @@ -58,22 +56,25 @@ typedef WINAPI HRESULT(*SHGETFOLDERPATHPROC) (HWND hwndOwner, HANDLE hToken, DWORD dwFlags, LPTSTR pszPath); #endif +#include "winmonitors.h" +#include "pseudoramiX/pseudoramiX.h" + #include "glx_extinit.h" #ifdef XWIN_GLX_WINDOWS #include "glx/glwindows.h" +#include "dri/windowsdri.h" #endif /* * References to external symbols */ +extern Bool noRRXineramaExtension; + /* * Function prototypes */ -static Bool - winCheckDisplayNumber(void); - void winLogCommandLine(int argc, char *argv[]); @@ -87,6 +88,11 @@ Bool const char *winGetBaseDir(void); #endif +static void winCheckMount(void); + +extern Bool XSupportsLocale(void); +extern Status XInitThreads(void); + /* * For the depth 24 pixmap we default to 32 bits per pixel, but * we change this pixmap format later if we detect that the display @@ -115,6 +121,9 @@ const int NUMFORMATS = sizeof(g_PixmapFormats) / sizeof(g_PixmapFormats[0]); static const ExtensionModule xwinExtensions[] = { #ifdef GLXEXT { GlxExtensionInit, "GLX", &noGlxExtension }, +#ifdef XWIN_WINDOWS_DRI + { WindowsDRIExtensionInit, "Windows-DRI", &noDriExtension }, +#endif #endif }; @@ -157,6 +166,8 @@ main(int argc, char *argv[], char *envp[]) { int iReturn; + xorg_crashreport_init(NULL); + /* Create & acquire the termination mutex */ iReturn = pthread_mutex_init(&g_pmTerminating, NULL); if (iReturn != 0) { @@ -168,6 +179,8 @@ main(int argc, char *argv[], char *envp[]) ErrorF("ddxMain - pthread_mutex_lock () failed: %d\n", iReturn); } + winCheckMount(); + return dix_main(argc, argv, envp); } @@ -207,10 +220,6 @@ ddxGiveUp(enum ExitCode error) } #endif - if (!g_fLogInited) { - g_pszLogFile = LogInit(g_pszLogFile, NULL); - g_fLogInited = TRUE; - } LogClose(error); /* @@ -254,6 +263,8 @@ AbortDDX(enum ExitCode error) } #ifdef __CYGWIN__ +extern Bool nolock; + /* hasmntopt is currently not implemented for cygwin */ static const char * winCheckMntOpt(const struct mntent *mnt, const char *opt) @@ -278,6 +289,9 @@ winCheckMntOpt(const struct mntent *mnt, const char *opt) return NULL; } +/* + Check mounts and issue warnings/activate workarounds as needed + */ static void winCheckMount(void) { @@ -287,6 +301,7 @@ winCheckMount(void) enum { none = 0, sys_root, user_root, sys_tmp, user_tmp } level = none, curlevel; BOOL binary = TRUE; + BOOL fat = TRUE; mnt = setmntent("/etc/mtab", "r"); if (mnt == NULL) { @@ -325,6 +340,12 @@ winCheckMount(void) binary = FALSE; else binary = TRUE; + + if ((strcmp(ent->mnt_type, "vfat") == 0) || + (strcmp(ent->mnt_type, "exfat") == 0)) + fat = TRUE; + else + fat = FALSE; } if (endmntent(mnt) != 1) { @@ -334,6 +355,12 @@ winCheckMount(void) if (!binary) winMsg(X_WARNING, "/tmp mounted in textmode\n"); + + if (fat) { + winMsg(X_WARNING, + "/tmp mounted on FAT filesystem, activating -nolock\n"); + nolock = TRUE; + } } #else static void @@ -589,13 +616,13 @@ winFixupPaths(void) winMsg(X_ERROR, "Can not determine HOME directory\n"); } } - if (!g_fLogFileChanged) { + if (!g_fLogFile) { static char buffer[MAX_PATH]; DWORD size = GetTempPath(sizeof(buffer), buffer); if (size && size < sizeof(buffer)) { snprintf(buffer + size, sizeof(buffer) - size, - "XWin.%s.log", display); + g_pszLogFileFormat, display); buffer[sizeof(buffer) - 1] = 0; g_pszLogFile = buffer; winMsg(X_DEFAULT, "Logfile set to \"%s\"\n", g_pszLogFile); @@ -626,15 +653,16 @@ OsVendorInit(void) OsVendorVErrorFProc = OsVendorVErrorF; #endif - if (!g_fLogInited) { - /* keep this order. If LogInit fails it calls Abort which then calls - * ddxGiveUp where LogInit is called again and creates an infinite - * recursion. If we set g_fLogInited to TRUE before the init we - * avoid the second call - */ - g_fLogInited = TRUE; - g_pszLogFile = LogInit(g_pszLogFile, NULL); + if (serverGeneration == 1) { + if (g_pszLogFile) + g_pszLogFile = LogInit(g_pszLogFile, ".old"); + else + g_pszLogFile = LogInit(g_pszLogFileFormat, ".old"); + + /* Tell crashreporter logfile name */ + xorg_crashreport_init(g_pszLogFile); } + LogSetParameter(XLOG_FLUSH, 1); LogSetParameter(XLOG_VERBOSITY, g_iLogVerbose); LogSetParameter(XLOG_FILE_VERBOSITY, g_iLogVerbose); @@ -687,6 +715,20 @@ OsVendorInit(void) } } } + + /* Work out what the default resize setting should be, and apply it if it + was not explicitly specified */ + { + int j; + for (j = 0; j < g_iNumScreens; j++) { + if (g_ScreenInfo[j].iResizeMode == resizeDefault) { + if (g_ScreenInfo[j].fFullScreen) + g_ScreenInfo[j].iResizeMode = resizeNotAllowed; + else + g_ScreenInfo[j].iResizeMode = resizeWithRandr; + } + } + } } static void @@ -733,13 +775,13 @@ winUseMsg(void) ErrorF("-engine engine_type_id\n" "\tOverride the server's automatically selected engine type:\n" "\t\t1 - Shadow GDI\n" - "\t\t2 - Shadow DirectDraw\n" + "\t\t2 - Shadow DirectDraw - obsolete\n" "\t\t4 - Shadow DirectDraw4 Non-Locking\n" ); ErrorF("-fullscreen\n" "\tRun the server in fullscreen mode.\n"); - ErrorF("-hostintitle\n" + ErrorF("-[no]hostintitle\n" "\tIn multiwindow mode, add remote host names to window titles.\n"); ErrorF("-ignoreinput\n" "\tIgnore keyboard and mouse input.\n"); @@ -866,24 +908,7 @@ winUseMsg(void) void ddxUseMsg(void) { - /* Set a flag so that FatalError won't give duplicate warning message */ - g_fSilentFatalError = TRUE; - winUseMsg(); - - /* Log file will not be opened for UseMsg unless we open it now */ - if (!g_fLogInited) { - g_pszLogFile = LogInit(g_pszLogFile, NULL); - g_fLogInited = TRUE; - } - LogClose(EXIT_NO_ERROR); - - /* Notify user where UseMsg text can be found. */ - if (!g_fNoHelpMessageBox) - winMessageBoxF("The " PROJECT_NAME " help text has been printed to " - "%s.\n" - "Please open %s to read the help text.\n", - MB_ICONINFORMATION, g_pszLogFile, g_pszLogFile); } /* See Porting Layer Definition - p. 20 */ @@ -914,14 +939,6 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char *argv[]) "Exiting.\n"); } - /* Check for duplicate invocation on same display number. */ - if (serverGeneration == 1 && !winCheckDisplayNumber()) { - if (g_fSilentDupError) - g_fSilentFatalError = TRUE; - FatalError("InitOutput - Duplicate invocation on display " - "number: %s. Exiting.\n", display); - } - #ifdef XWIN_XF86CONFIG /* Try to read the xorg.conf-style configuration file */ if (!winReadConfigfile()) @@ -973,6 +990,61 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char *argv[]) } } + /* + Unless full xinerama has been explicitly enabled, register all native screens with pseudoramiX + */ + if (!noPanoramiXExtension) + noPseudoramiXExtension = TRUE; + + if ((g_ScreenInfo[0].fMultipleMonitors) && !noPseudoramiXExtension) + { + int pass; + + noRRXineramaExtension = TRUE; + + PseudoramiXExtensionInit(); + + /* Add primary monitor on pass 0, other monitors on pass 1, to ensure + the primary monitor is first in XINERAMA list */ + for (pass = 0; pass < 2; pass++) + { + int iMonitor; + + for (iMonitor = 1; ; iMonitor++) + { + struct GetMonitorInfoData data; + QueryMonitor(iMonitor, &data); + if (data.bMonitorSpecifiedExists) + { + MONITORINFO mi; + mi.cbSize = sizeof(MONITORINFO); + + if (GetMonitorInfo(data.monitorHandle, &mi)) + { + /* pass == 1 XOR primary monitor flags is set */ + if ((!(pass == 1)) != (!(mi.dwFlags & MONITORINFOF_PRIMARY))) + { + /* + Note the screen origin in a normalized coordinate space where (0,0) is at the top left + of the native virtual desktop area + */ + data.monitorOffsetX = data.monitorOffsetX - GetSystemMetrics(SM_XVIRTUALSCREEN); + data.monitorOffsetY = data.monitorOffsetY - GetSystemMetrics(SM_YVIRTUALSCREEN); + + winDebug ("InitOutput - screen %d added at virtual desktop coordinate (%d,%d) (pseudoramiX) \n", + iMonitor-1, data.monitorOffsetX, data.monitorOffsetY); + + PseudoramiXAddScreen(data.monitorOffsetX, data.monitorOffsetY, + data.monitorWidth, data.monitorHeight); + } + } + } + else + break; + } + } + } + #if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW) /* Generate a cookie used by internal clients for authorization */ @@ -981,11 +1053,27 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char *argv[]) /* Perform some one time initialization */ if (1 == serverGeneration) { + const char *locale; + + /* Allow multiple threads to access Xlib */ + if (XInitThreads() == 0) { + ErrorF("XInitThreads failed.\n"); + } + /* * setlocale applies to all threads in the current process. * Apply locale specified in LANG environment variable. */ - setlocale(LC_ALL, ""); + locale = setlocale(LC_ALL, ""); + if (!locale) { + ErrorF("setlocale failed.\n"); + } + + /* See if X supports the current locale */ + if (XSupportsLocale() == FALSE) { + ErrorF("Warning: Locale '%s' not supported by X, falling back to 'C' locale.\n", locale); + setlocale(LC_ALL, "C"); + } } #endif @@ -993,70 +1081,3 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char *argv[]) winDebug("InitOutput - Returning.\n"); #endif } - -/* - * winCheckDisplayNumber - Check if another instance of Cygwin/X is - * already running on the same display number. If no one exists, - * make a mutex to prevent new instances from running on the same display. - * - * return FALSE if the display number is already used. - */ - -static Bool -winCheckDisplayNumber(void) -{ - int nDisp; - HANDLE mutex; - char name[MAX_PATH]; - const char *pszPrefix = '\0'; - OSVERSIONINFO osvi = { 0 }; - - /* Check display range */ - nDisp = atoi(display); - if (nDisp < 0 || nDisp > 65535) { - ErrorF("winCheckDisplayNumber - Bad display number: %d\n", nDisp); - return FALSE; - } - - /* Set first character of mutex name to null */ - name[0] = '\0'; - - /* Get operating system version information */ - osvi.dwOSVersionInfoSize = sizeof(osvi); - GetVersionEx(&osvi); - - /* Want a mutex shared among all terminals on NT > 4.0 */ - if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT && osvi.dwMajorVersion >= 5) { - pszPrefix = "Global\\"; - } - - /* Setup Cygwin/X specific part of name */ - snprintf(name, sizeof(name), "%sCYGWINX_DISPLAY:%d", pszPrefix, nDisp); - - /* Windows automatically releases the mutex when this process exits */ - mutex = CreateMutex(NULL, FALSE, name); - if (!mutex) { - LPVOID lpMsgBuf; - - /* 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("winCheckDisplayNumber - CreateMutex failed: %s\n", - (LPSTR) lpMsgBuf); - LocalFree(lpMsgBuf); - - return FALSE; - } - if (GetLastError() == ERROR_ALREADY_EXISTS) { - ErrorF("winCheckDisplayNumber - " - PROJECT_NAME " is already running on display %d\n", nDisp); - return FALSE; - } - - return TRUE; -} diff --git a/hw/xwin/Makefile.am b/hw/xwin/Makefile.am index 0ea8ba769..27e26d0fc 100644 --- a/hw/xwin/Makefile.am +++ b/hw/xwin/Makefile.am @@ -9,9 +9,17 @@ CLIPBOARD_LIBS = $(top_builddir)/hw/xwin/winclipboard/libXWinclipboard.la endif if XWIN_GLX_WINDOWS -GLX_DIR = glx -DEFS_GLX_WINDOWS = -DXWIN_GLX_WINDOWS -XWIN_GLX_LIBS = $(top_builddir)/hw/xwin/glx/libXwinGLX.la +GLX_DIR = +DEFS_GLX_WINDOWS = +XWIN_GLX_LIBS = +if XWIN_WINDOWS_DRI +GLX_DIR += dri +DEFS_GLX_WINDOWS += -DXWIN_WINDOWS_DRI +XWIN_GLX_LIBS += $(top_builddir)/hw/xwin/dri/libWindowsDRI.la +endif +GLX_DIR += glx +DEFS_GLX_WINDOWS += -DXWIN_GLX_WINDOWS +XWIN_GLX_LIBS += $(top_builddir)/hw/xwin/glx/libXwinGLX.la XWIN_GLX_SYS_LIBS = -lopengl32 endif @@ -25,6 +33,7 @@ SRCS_MULTIWINDOW = \ winSetAppUserModelID.c DEFS_MULTIWINDOW = -DXWIN_MULTIWINDOW MULTIWINDOW_SYS_LIBS = -lshlwapi -lole32 +MULTIWINDOW_LIBS = $(top_builddir)/hw/xwin/wmutil/libXWinWMUtil.la endif if XWIN_MULTIWINDOWEXTWM @@ -89,8 +98,6 @@ SRCS = InitInput.c \ winconfig.h \ win.h \ winglobals.h \ - winkeybd.h \ - winkeynames.h \ winlayouts.h \ winmessages.h \ winmonitors.h \ @@ -134,6 +141,7 @@ XWIN_LIBS += \ $(top_builddir)/Xi/libXistubs.la XWin_DEPENDENCIES = \ + $(MULTIWINDOW_LIBS) \ $(MULTIWINDOWEXTWM_LIBS) \ $(XWIN_GLX_LIBS) \ $(XWIN_LIBS) \ @@ -142,6 +150,7 @@ XWin_DEPENDENCIES = \ XWin_LDADD = \ + $(MULTIWINDOW_LIBS) \ $(MULTIWINDOWEXTWM_LIBS) \ $(XWIN_GLX_LIBS) \ $(XWIN_LIBS) \ @@ -156,7 +165,7 @@ XWin_LDFLAGS = -mwindows -Wl,--disable-stdcall-fixup $(LD_EXPORT_SYMBOLS_FLAG) .rc.o: - $(AM_V_GEN)$(WINDRES) --use-temp-file -i $< --input-format=rc -o $@ -O coff -I $(top_builddir)/include + $(AM_V_GEN)$(WINDRES) --use-temp-file -i $< --input-format=rc -o $@ -O coff -I $(top_builddir)/include -DHOST_TRIPLET=\"$(host)\" XWin.o: XWin.rc XWin.exe.manifest X.ico @@ -188,5 +197,5 @@ EXTRA_DIST = \ relink: $(AM_V_at)rm -f XWin$(EXEEXT) && $(MAKE) XWin$(EXEEXT) -SUBDIRS = man $(GLX_DIR) winclipboard . -DIST_SUBDIRS = man glx winclipboard . +SUBDIRS = man $(GLX_DIR) winclipboard wmutil . +DIST_SUBDIRS = man glx winclipboard wmutil . diff --git a/hw/xwin/XWin.exe.manifest b/hw/xwin/XWin.exe.manifest index 477334fb3..bd44b1066 100755 --- a/hw/xwin/XWin.exe.manifest +++ b/hw/xwin/XWin.exe.manifest @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> - <description>The XWin X Windows server for Cygwin.</description> + <description>The XWin X Windows server</description> <dependency> <dependentAssembly> <assemblyIdentity @@ -18,4 +18,18 @@ <dpiAware>true</dpiAware> </asmv3:windowsSettings> </asmv3:application> + <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> + <application> + <!-- Windows Vista --> + <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/> + <!-- Windows 7 --> + <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/> + <!-- Windows 8 --> + <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/> + <!-- Windows 8.1 --> + <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/> + <!-- Windows 10 --> + <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/> + </application> + </compatibility> </assembly> diff --git a/hw/xwin/XWin.rc b/hw/xwin/XWin.rc index a54e0fdbb..e74a9a5ef 100644 --- a/hw/xwin/XWin.rc +++ b/hw/xwin/XWin.rc @@ -46,7 +46,7 @@ FONT 8, "MS Shell Dlg 2" BEGIN CONTROL IDI_XWIN, IDC_STATIC, "Static", SS_ICON, 8, 8, 32, 32 LTEXT XVENDORNAMESHORT " X Server ", IDC_STATIC, 36, 8, 220, 8 - LTEXT VENDOR_MAN_VERSION, IDC_STATIC, 36, 18, 220, 8 + LTEXT VENDOR_MAN_VERSION " (" HOST_TRIPLET ")", IDC_STATIC, 36, 18, 220, 8 LTEXT BUILDERSTRING, IDC_STATIC, 36, 28, 220, 8 LTEXT "This software is licensed under the terms of the MIT/X11 License.", IDC_STATIC, 36, 48, 220, 20 CONTROL __VENDORDWEBSUPPORT__, ID_ABOUT_WEBSITE, "Button", diff --git a/hw/xwin/dri/Makefile.am b/hw/xwin/dri/Makefile.am new file mode 100644 index 000000000..bdcd48aae --- /dev/null +++ b/hw/xwin/dri/Makefile.am @@ -0,0 +1,8 @@ +noinst_LTLIBRARIES = libWindowsDRI.la + +libWindowsDRI_la_SOURCES = \ + windowsdri.c \ + windowsdri.h + +AM_CFLAGS = $(DIX_CFLAGS) \ + -I$(top_srcdir)/hw/xwin/ diff --git a/hw/xwin/dri/windowsdri.c b/hw/xwin/dri/windowsdri.c new file mode 100644 index 000000000..ab18a4691 --- /dev/null +++ b/hw/xwin/dri/windowsdri.c @@ -0,0 +1,274 @@ +/* + * Copyright © 2014 Jon TURNEY + * + * 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. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/extensions/windowsdristr.h> + +#include "dixstruct.h" +#include "extnsionst.h" +#include "scrnintstr.h" +#include "swaprep.h" +#include "protocol-versions.h" +#include "windowsdri.h" +#include "glx/dri_helpers.h" + +static int WindowsDRIErrorBase = 0; +static unsigned char WindowsDRIReqCode = 0; +static int WindowsDRIEventBase = 0; + +static void +WindowsDRIResetProc(ExtensionEntry* extEntry) +{ +} + +static int +ProcWindowsDRIQueryVersion(ClientPtr client) +{ + xWindowsDRIQueryVersionReply rep; + + REQUEST_SIZE_MATCH(xWindowsDRIQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = SERVER_WINDOWSDRI_MAJOR_VERSION; + rep.minorVersion = SERVER_WINDOWSDRI_MINOR_VERSION; + rep.patchVersion = SERVER_WINDOWSDRI_PATCH_VERSION; + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swaps(&rep.majorVersion); + swaps(&rep.minorVersion); + swapl(&rep.patchVersion); + } + WriteToClient(client, sizeof(xWindowsDRIQueryVersionReply), &rep); + return Success; +} + +static int +ProcWindowsDRIQueryDirectRenderingCapable(ClientPtr client) +{ + xWindowsDRIQueryDirectRenderingCapableReply rep; + + REQUEST(xWindowsDRIQueryDirectRenderingCapableReq); + REQUEST_SIZE_MATCH(xWindowsDRIQueryDirectRenderingCapableReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + if (!client->local) + rep.isCapable = 0; + else + rep.isCapable = glxWinGetScreenAiglxIsActive(screenInfo.screens[stuff->screen]); + + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + } + + WriteToClient(client, + sizeof(xWindowsDRIQueryDirectRenderingCapableReply), + &rep); + return Success; +} + +static int +ProcWindowsDRIQueryDrawable(ClientPtr client) +{ + xWindowsDRIQueryDrawableReply rep; + int rc; + + REQUEST(xWindowsDRIQueryDrawableReq); + REQUEST_SIZE_MATCH(xWindowsDRIQueryDrawableReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + rc = glxWinQueryDrawable(client, stuff->drawable, &(rep.drawable_type), &(rep.handle)); + + if (rc) + return rc; + + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swapl(&rep.handle); + swapl(&rep.drawable_type); + } + + WriteToClient(client, sizeof(xWindowsDRIQueryDrawableReply), &rep); + return Success; +} + +static int +ProcWindowsDRIFBConfigToPixelFormat(ClientPtr client) +{ + xWindowsDRIFBConfigToPixelFormatReply rep; + + REQUEST(xWindowsDRIFBConfigToPixelFormatReq); + REQUEST_SIZE_MATCH(xWindowsDRIFBConfigToPixelFormatReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + rep.pixelFormatIndex = glxWinFBConfigIDToPixelFormatIndex(stuff->screen, stuff->fbConfigID); + + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swapl(&rep.pixelFormatIndex); + } + + WriteToClient(client, sizeof(xWindowsDRIFBConfigToPixelFormatReply), &rep); + return Success; +} + +/* dispatch */ + +static int +ProcWindowsDRIDispatch(ClientPtr client) +{ + REQUEST(xReq); + + switch (stuff->data) { + case X_WindowsDRIQueryVersion: + return ProcWindowsDRIQueryVersion(client); + + case X_WindowsDRIQueryDirectRenderingCapable: + return ProcWindowsDRIQueryDirectRenderingCapable(client); + } + + if (!client->local) + return WindowsDRIErrorBase + WindowsDRIClientNotLocal; + + switch (stuff->data) { + case X_WindowsDRIQueryDrawable: + return ProcWindowsDRIQueryDrawable(client); + + case X_WindowsDRIFBConfigToPixelFormat: + return ProcWindowsDRIFBConfigToPixelFormat(client); + + default: + return BadRequest; + } +} + +static void +SNotifyEvent(xWindowsDRINotifyEvent *from, + xWindowsDRINotifyEvent *to) +{ + to->type = from->type; + to->kind = from->kind; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->time, to->time); +} + +static int +SProcWindowsDRIQueryVersion(ClientPtr client) +{ + REQUEST(xWindowsDRIQueryVersionReq); + swaps(&stuff->length); + return ProcWindowsDRIQueryVersion(client); +} + +static int +SProcWindowsDRIQueryDirectRenderingCapable(ClientPtr client) +{ + REQUEST(xWindowsDRIQueryDirectRenderingCapableReq); + swaps(&stuff->length); + swapl(&stuff->screen); + return ProcWindowsDRIQueryDirectRenderingCapable(client); +} + +static int +SProcWindowsDRIQueryDrawable(ClientPtr client) +{ + REQUEST(xWindowsDRIQueryDrawableReq); + swaps(&stuff->length); + swapl(&stuff->screen); + swapl(&stuff->drawable); + return ProcWindowsDRIQueryDrawable(client); +} + +static int +SProcWindowsDRIFBConfigToPixelFormat(ClientPtr client) +{ + REQUEST(xWindowsDRIFBConfigToPixelFormatReq); + swaps(&stuff->length); + swapl(&stuff->screen); + swapl(&stuff->fbConfigID); + return ProcWindowsDRIFBConfigToPixelFormat(client); +} + +static int +SProcWindowsDRIDispatch(ClientPtr client) +{ + REQUEST(xReq); + + switch (stuff->data) { + case X_WindowsDRIQueryVersion: + return SProcWindowsDRIQueryVersion(client); + + case X_WindowsDRIQueryDirectRenderingCapable: + return SProcWindowsDRIQueryDirectRenderingCapable(client); + } + + if (!client->local) + return WindowsDRIErrorBase + WindowsDRIClientNotLocal; + + switch (stuff->data) { + case X_WindowsDRIQueryDrawable: + return SProcWindowsDRIQueryDrawable(client); + + case X_WindowsDRIFBConfigToPixelFormat: + return SProcWindowsDRIFBConfigToPixelFormat(client); + + default: + return BadRequest; + } +} + +void +WindowsDRIExtensionInit(void) +{ + ExtensionEntry* extEntry; + + if ((extEntry = AddExtension(WINDOWSDRINAME, + WindowsDRINumberEvents, + WindowsDRINumberErrors, + ProcWindowsDRIDispatch, + SProcWindowsDRIDispatch, + WindowsDRIResetProc, + StandardMinorOpcode))) { + size_t i; + WindowsDRIReqCode = (unsigned char)extEntry->base; + WindowsDRIErrorBase = extEntry->errorBase; + WindowsDRIEventBase = extEntry->eventBase; + for (i = 0; i < WindowsDRINumberEvents; i++) + EventSwapVector[WindowsDRIEventBase + i] = (EventSwapPtr)SNotifyEvent; + } +} diff --git a/hw/xwin/dri/windowsdri.h b/hw/xwin/dri/windowsdri.h new file mode 100644 index 000000000..a48c72b04 --- /dev/null +++ b/hw/xwin/dri/windowsdri.h @@ -0,0 +1,30 @@ +/* + * Copyright © 2014 Jon TURNEY + * + * 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. + */ + +#ifndef windowsdri_h +#define windowsdri_h + +void WindowsDRIExtensionInit(void); +Bool noDriExtension; + +#endif /* windowsdri_h */ diff --git a/hw/xwin/glx/Makefile.am b/hw/xwin/glx/Makefile.am index f2dffbffb..599ec37cc 100644 --- a/hw/xwin/glx/Makefile.am +++ b/hw/xwin/glx/Makefile.am @@ -7,9 +7,16 @@ libXwinGLX_la_SOURCES = \ glwindows.h \ glshim.c \ indirect.c \ + indirect.h \ wgl_ext_api.c \ wgl_ext_api.h +if XWIN_WINDOWS_DRI +libXwinGLX_la_SOURCES += \ + dri_helpers.c \ + dri_helpers.h +endif + libnativeGLthunk_la_SOURCES = \ glthunk.c diff --git a/hw/xwin/glx/dri_helpers.c b/hw/xwin/glx/dri_helpers.c new file mode 100644 index 000000000..7ed9c9532 --- /dev/null +++ b/hw/xwin/glx/dri_helpers.c @@ -0,0 +1,119 @@ +/* + * Copyright © 2014 Jon TURNEY + * + * 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. + */ + +#ifdef HAVE_XWIN_CONFIG_H +#include <xwin-config.h> +#endif + +#include <glx/glxserver.h> +#include <glx/glxutil.h> +#include <X11/extensions/windowsdriconst.h> + +#include "indirect.h" +#include "winpriv.h" +#include "dri_helpers.h" +#include "win.h" + +extern int validGlxDrawable(ClientPtr client, XID id, int type, int access_mode, + __GLXdrawable ** drawable, int *err); + +int +glxWinQueryDrawable(ClientPtr client, XID drawId, unsigned int *type, unsigned int *handle) +{ + __GLXWinDrawable *pDrawable; + int err; + + if (validGlxDrawable(client, drawId, GLX_DRAWABLE_ANY, + DixReadAccess, (__GLXdrawable **)&pDrawable, &err)) { + + switch (pDrawable->base.type) + { + case GLX_DRAWABLE_WINDOW: + { + HWND h = winGetWindowInfo((WindowPtr)(pDrawable->base.pDraw)); + *handle = (uintptr_t)h; + *type = WindowsDRIDrawableWindow; + } + break; + + case GLX_DRAWABLE_PIXMAP: + glxWinDeferredCreateDrawable(pDrawable, pDrawable->base.config); + *handle = pDrawable->base.pDraw->id; + // XXX: We could use DuplicateHandle to make pDrawble->hSection + // available to the requesting process... ? + *type = WindowsDRIDrawablePixmap; + break; + + case GLX_DRAWABLE_PBUFFER: + glxWinDeferredCreateDrawable(pDrawable, pDrawable->base.config); + *handle = (uintptr_t)(pDrawable->hPbuffer); + *type = WindowsDRIDrawablePbuffer; + break; + + default: + assert(FALSE); + *handle = 0; + } + } + else { + HWND h; + /* The drawId XID doesn't identify a GLX drawable. The only other valid + alternative is that it is the XID of a window drawable that is being + used by the pre-GLX 1.3 interface */ + DrawablePtr pDraw; + int rc = dixLookupDrawable(&pDraw, drawId, client, 0, DixGetAttrAccess); + if (rc != Success || pDraw->type != DRAWABLE_WINDOW) { + return err; + } + + h = winGetWindowInfo((WindowPtr)(pDraw)); + *handle = (uintptr_t)h; + *type = WindowsDRIDrawableWindow; + } + + winDebug("glxWinQueryDrawable: type %d, handle %p\n", *type, (void *)(uintptr_t)*handle); + return Success; +} + +int +glxWinFBConfigIDToPixelFormatIndex(int scr, int fbConfigID) +{ + __GLXscreen *screen = glxGetScreen(screenInfo.screens[scr]); + __GLXconfig *c; + + for (c = screen->fbconfigs; + c != NULL; + c = c->next) { + if (c->fbconfigID == fbConfigID) + return ((GLXWinConfig *)c)->pixelFormatIndex; + } + + return 0; +} + +Bool +glxWinGetScreenAiglxIsActive(ScreenPtr pScreen) +{ + winPrivScreenPtr pWinScreen = winGetScreenPriv(pScreen); + return pWinScreen->fNativeGlActive; +} diff --git a/hw/xwin/glx/dri_helpers.h b/hw/xwin/glx/dri_helpers.h new file mode 100644 index 000000000..05bc9bc93 --- /dev/null +++ b/hw/xwin/glx/dri_helpers.h @@ -0,0 +1,38 @@ +/* + * Copyright © 2014 Jon TURNEY + * + * 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. + */ + +#ifndef dri_helpers_h +#define dri_helpers_h + +#include "dixstruct.h" + +int +glxWinQueryDrawable(ClientPtr client, XID drawId, unsigned int *type, unsigned int *handle); + +int +glxWinFBConfigIDToPixelFormatIndex(int scr, int fbConfigID); + +Bool +glxWinGetScreenAiglxIsActive(ScreenPtr pScreen); + +#endif /* dri_helpers_h */ diff --git a/hw/xwin/glx/gen_gl_wrappers.py b/hw/xwin/glx/gen_gl_wrappers.py index b9e8dda75..5f4526b9d 100755 --- a/hw/xwin/glx/gen_gl_wrappers.py +++ b/hw/xwin/glx/gen_gl_wrappers.py @@ -124,17 +124,17 @@ else: diag = open(diagFilename, 'w') def ParseCmdRettype(cmd): - proto=noneStr(cmd.elem.find('proto')) - rettype=noneStr(proto.text) - if rettype.lower()!="void ": + proto = noneStr(cmd.elem.find('proto')) + rettype = noneStr(proto.text) + if rettype.lower() != "void ": plist = ([t for t in proto.itertext()]) rettype = ''.join(plist[:-1]) - rettype=rettype.strip() + rettype = rettype.strip() return rettype def ParseCmdParams(cmd): params = cmd.elem.findall('param') - plist=[] + plist = [] for param in params: # construct the formal parameter definition from ptype and name # elements, also using any text found around these in the @@ -150,7 +150,9 @@ def ParseCmdParams(cmd): paramtype = paramtype + ' ' + paramname if t.tail is not None: paramtype = paramtype + t.tail.strip() + plist.append((paramtype, paramname)) + return plist class PreResolveOutputGenerator(OutputGenerator): @@ -209,11 +211,12 @@ class WrapperOutputGenerator(OutputGenerator): if prefix == 'wgl' and not name in used_wgl_ext_fns: return - rettype=ParseCmdRettype(cmd) + rettype = ParseCmdRettype(cmd) + plist = ParseCmdParams(cmd) if staticwrappers: self.outFile.write("static ") self.outFile.write("%s %sWrapper("%(rettype, name)) - plist=ParseCmdParams(cmd) + Comma="" if len(plist): for ptype, pname in plist: @@ -290,10 +293,10 @@ class ThunkOutputGenerator(OutputGenerator): def genCmd(self, cmd, name): OutputGenerator.genCmd(self, cmd, name) - rettype=ParseCmdRettype(cmd) - self.outFile.write("%s %sWrapper("%(rettype, name)) - plist=ParseCmdParams(cmd) + rettype = ParseCmdRettype(cmd) + plist = ParseCmdParams(cmd) + self.outFile.write("%s %sWrapper("%(rettype, name)) Comma="" if len(plist): for ptype, pname in plist: @@ -378,14 +381,14 @@ class ShimOutputGenerator(OutputGenerator): def genCmd(self, cmd, name): OutputGenerator.genCmd(self, cmd, name) + # for GL functions which are in the ABI, generate a shim which calls the function via GetProcAddress if not self.OldVersion: return - # for GL functions which are in the ABI, generate a shim which calls the function via GetProcAddress - rettype=ParseCmdRettype(cmd) - self.outFile.write("%s %s("%(rettype, name)) - plist=ParseCmdParams(cmd) + rettype = ParseCmdRettype(cmd) + plist = ParseCmdParams(cmd) + self.outFile.write("%s %s("%(rettype, name)) Comma="" if len(plist): for ptype, pname in plist: diff --git a/hw/xwin/glx/indirect.c b/hw/xwin/glx/indirect.c index 93cdb29d6..b9881426c 100644 --- a/hw/xwin/glx/indirect.c +++ b/hw/xwin/glx/indirect.c @@ -81,12 +81,13 @@ #include "glwindows.h" #include <glx/glxserver.h> #include <glx/glxutil.h> -#include <glx/extension_string.h> #include <GL/glxtokens.h> #include <winpriv.h> #include <wgl_ext_api.h> #include <winglobals.h> +#include <indirect.h> +#include <setjmp.h> #define NUM_ELEMENTS(x) (sizeof(x)/ sizeof(x[1])) @@ -101,59 +102,13 @@ #define PFD_SUPPORT_COMPOSITION 0x00008000 #endif -/* ---------------------------------------------------------------------- */ -/* - * structure definitions - */ - -typedef struct __GLXWinContext __GLXWinContext; -typedef struct __GLXWinDrawable __GLXWinDrawable; -typedef struct __GLXWinScreen glxWinScreen; -typedef struct __GLXWinConfig GLXWinConfig; - -struct __GLXWinContext { - __GLXcontext base; - HGLRC ctx; /* Windows GL Context */ - __GLXWinContext *shareContext; /* Context with which we will share display lists and textures */ - HWND hwnd; /* For detecting when HWND has changed */ -}; - -struct __GLXWinDrawable { - __GLXdrawable base; - __GLXWinContext *drawContext; - __GLXWinContext *readContext; - - /* If this drawable is GLX_DRAWABLE_PBUFFER */ - HPBUFFERARB hPbuffer; - - /* If this drawable is GLX_DRAWABLE_PIXMAP */ - HDC dibDC; - HBITMAP hDIB; - HBITMAP hOldDIB; /* original DIB for DC */ - void *pOldBits; /* original pBits for this drawable's pixmap */ -}; - -struct __GLXWinScreen { - __GLXscreen base; - - /* Supported GLX extensions */ - unsigned char glx_enable_bits[__GLX_EXT_BYTES]; - - Bool has_WGL_ARB_multisample; - Bool has_WGL_ARB_pixel_format; - Bool has_WGL_ARB_pbuffer; - Bool has_WGL_ARB_render_texture; - - /* wrapped screen functions */ - RealizeWindowProcPtr RealizeWindow; - UnrealizeWindowProcPtr UnrealizeWindow; - CopyWindowProcPtr CopyWindow; -}; - -struct __GLXWinConfig { - __GLXconfig base; - int pixelFormatIndex; -}; +typedef struct { + int notOpenGL; + int rgbaFloat; + int unsignedRgbaFloat; + int unknownPixelType; + int unaccelerated; +} PixelFormatRejectStats; /* ---------------------------------------------------------------------- */ /* @@ -253,7 +208,7 @@ pfdOut(const PIXELFORMATDESCRIPTOR * pfd) ErrorF("PIXELFORMATDESCRIPTOR:\n"); ErrorF("nSize = %u\n", pfd->nSize); ErrorF("nVersion = %u\n", pfd->nVersion); - ErrorF("dwFlags = %lu = {", pfd->dwFlags); + ErrorF("dwFlags = %u = {", (unsigned int)pfd->dwFlags); DUMP_PFD_FLAG(PFD_DOUBLEBUFFER); DUMP_PFD_FLAG(PFD_STEREO); DUMP_PFD_FLAG(PFD_DRAW_TO_WINDOW); @@ -297,9 +252,9 @@ pfdOut(const PIXELFORMATDESCRIPTOR * pfd) ErrorF("cAuxBuffers = %hhu\n", pfd->cAuxBuffers); ErrorF("iLayerType = %hhu\n", pfd->iLayerType); ErrorF("bReserved = %hhu\n", pfd->bReserved); - ErrorF("dwLayerMask = %lu\n", pfd->dwLayerMask); - ErrorF("dwVisibleMask = %lu\n", pfd->dwVisibleMask); - ErrorF("dwDamageMask = %lu\n", pfd->dwDamageMask); + ErrorF("dwLayerMask = %u\n", (unsigned int)pfd->dwLayerMask); + ErrorF("dwVisibleMask = %u\n", (unsigned int)pfd->dwVisibleMask); + ErrorF("dwDamageMask = %u\n", (unsigned int)pfd->dwDamageMask); ErrorF("\n"); } @@ -340,13 +295,16 @@ swap_method_name(int mthd) } static void -fbConfigsDump(unsigned int n, __GLXconfig * c) +fbConfigsDump(unsigned int n, __GLXconfig * c, PixelFormatRejectStats *rejects) { LogMessage(X_INFO, "%d fbConfigs\n", n); + LogMessage(X_INFO, "ignored pixel formats: %d not OpenGL, %d RBGA float, %d RGBA unsigned float, %d unknown pixel type, %d unaccelerated\n", + rejects->notOpenGL, rejects->rgbaFloat, rejects->unsignedRgbaFloat, + rejects->unknownPixelType, rejects->unaccelerated); if (g_iLogVerbose < 3) return; - ErrorF("%d fbConfigs\n", n); + ErrorF ("pxf vis fb render Ste aux accum MS drawable Group/\n"); ErrorF @@ -419,13 +377,15 @@ static Bool glxWinRealizeWindow(WindowPtr pWin); static Bool glxWinUnrealizeWindow(WindowPtr pWin); static void glxWinCopyWindow(WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc); - +static Bool glxWinSetPixelFormat(HDC hdc, int bppOverride, int drawableTypeOverride, + __GLXscreen *screen, __GLXconfig *config); static HDC glxWinMakeDC(__GLXWinContext * gc, __GLXWinDrawable * draw, HDC * hdc, HWND * hwnd); static void glxWinReleaseDC(HWND hwnd, HDC hdc, __GLXWinDrawable * draw); static void glxWinCreateConfigs(HDC dc, glxWinScreen * screen); -static void glxWinCreateConfigsExt(HDC hdc, glxWinScreen * screen); +static void glxWinCreateConfigsExt(HDC hdc, glxWinScreen * screen, + PixelFormatRejectStats * rejects); static int fbConfigToPixelFormat(__GLXconfig * mode, PIXELFORMATDESCRIPTOR * pfdret, int drawableTypeOverride); @@ -520,6 +480,30 @@ glxLogExtensions(const char *prefix, const char *extensions) free(str); } +static jmp_buf jmp_sig; +static struct sigaction old_act; +extern Bool install_os_signal_handler; + +static void +glxWinScreenProbeSigHandler(int signo, siginfo_t * sip, void *context) +{ + // log a message + ErrorFSigSafe("segfault in WGL during glxWinScreenProbe()\n"); + + // show a messagebox + MessageBox(NULL, + "Windows OpenGL has been disabled as a crash occurred during initialization.\n" + "\n" + "Please try updating the display driver.\n" + "\n" + "You can disable the use of Windows OpenGL by starting the X server using the -nowgl option.", + XVENDORNAMESHORT, + MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_SETFOREGROUND); + + // continue via longjmp() + longjmp(jmp_sig, 1); +} + /* This is called by GlxExtensionInit() asking the GLX provider if it can handle the screen... */ static __GLXscreen * glxWinScreenProbe(ScreenPtr pScreen) @@ -531,6 +515,7 @@ glxWinScreenProbe(ScreenPtr pScreen) HWND hwnd; HDC hdc; HGLRC hglrc; + PixelFormatRejectStats rejects; GLWIN_DEBUG_MSG("glxWinScreenProbe"); @@ -551,8 +536,11 @@ glxWinScreenProbe(ScreenPtr pScreen) return NULL; // Select the native GL implementation (WGL) - if (glWinSelectImplementation(1)) + if (glWinSelectImplementation(1)) { + LogMessage(X_ERROR, "AIGLX: WGL not available\n"); + free(screen); return NULL; + } // create window class #define WIN_GL_TEST_WINDOW_CLASS "XWinGLTest" @@ -563,7 +551,7 @@ glxWinScreenProbe(ScreenPtr pScreen) WNDCLASSEX wc; wc.cbSize = sizeof(WNDCLASSEX); - wc.style = CS_HREDRAW | CS_VREDRAW; + wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; wc.lpfnWndProc = DefWindowProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; @@ -578,22 +566,79 @@ glxWinScreenProbe(ScreenPtr pScreen) } } + // The following tests seem particularly prone to crashing somewhere in the + // display driver's OpenGL implementation. So temporarily install a special + // SIGSEGV handler so can catch that and offer some remedial advice... + if (install_os_signal_handler) + { + struct sigaction act; + sigemptyset(&act.sa_mask); + act.sa_sigaction = glxWinScreenProbeSigHandler; + act.sa_flags = SA_SIGINFO; + sigaction(SIGSEGV, &act, &old_act); + + if (setjmp(jmp_sig)) { + LogMessage(X_ERROR, "AIGLX: Not using WGL due to SEGV\n"); + goto error; + } + } + // create an invisible window for a scratch DC hwnd = CreateWindowExA(0, WIN_GL_TEST_WINDOW_CLASS, "XWin GL Renderer Capabilities Test Window", 0, 0, 0, 0, 0, NULL, NULL, GetModuleHandle(NULL), NULL); - if (hwnd == NULL) + if (hwnd == NULL) { LogMessage(X_ERROR, "AIGLX: Couldn't create a window for render capabilities testing\n"); + goto error; + } hdc = GetDC(hwnd); + if (!hdc) { + LogMessage(X_ERROR, "AIGLX: Couldn't create a DC for render capabilities testing\n"); + goto error; + } + + // we must set a pixel format before we can create a context + { + PIXELFORMATDESCRIPTOR pfd = { + sizeof(PIXELFORMATDESCRIPTOR), + 1, + PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DEPTH_DONTCARE | PFD_DOUBLEBUFFER_DONTCARE | PFD_STEREO_DONTCARE, + PFD_TYPE_RGBA, + 24, + 0, 0, 0, 0, 0, 0, + 0, + 0, + 0, + 0, 0, 0, 0, + 0, + 0, + 0, + PFD_MAIN_PLANE, + 0, + 0, 0, 0 + }; + int iPixelFormat = ChoosePixelFormat(hdc, &pfd); + if (iPixelFormat == 0) { + LogMessage(X_ERROR, "AIGLX: ChoosePixelFormat failed\n"); + goto error; + } + + if (!SetPixelFormat(hdc, iPixelFormat, NULL)) { + LogMessage(X_ERROR, "AIGLX: SetPixelFormat %d failed\n", iPixelFormat); + goto error; + } + LogMessage(X_INFO, "AIGLX: Testing pixelFormatIndex %d\n",iPixelFormat); + } - // we must set a pixel format before we can create a context, just use the first one... - SetPixelFormat(hdc, 1, NULL); hglrc = wglCreateContext(hdc); - wglMakeCurrent(hdc, hglrc); + if (!wglMakeCurrent(hdc, hglrc)) { + ErrorF("glxWinScreenProbe: wglMakeCurrent error: %08x dc %p ctx %p\n", + (unsigned)GetLastError(), hdc, hglrc); + } // initialize wgl extension proc pointers (don't call them before here...) // (but we need to have a current context for them to be resolvable) @@ -605,6 +650,8 @@ glxWinScreenProbe(ScreenPtr pScreen) gl_renderer = (const char *) glGetString(GL_RENDERER); ErrorF("GL_RENDERER: %s\n", gl_renderer); gl_extensions = (const char *) glGetString(GL_EXTENSIONS); + if (!gl_extensions) + gl_extensions = ""; wgl_extensions = wglGetExtensionsStringARBWrapper(hdc); if (!wgl_extensions) wgl_extensions = ""; @@ -614,10 +661,15 @@ glxWinScreenProbe(ScreenPtr pScreen) glxLogExtensions("WGL_EXTENSIONS: ", wgl_extensions); } + if (!gl_renderer) { + LogMessage(X_ERROR, + "AIGLX: Native renderer not identified\n"); + goto error; + } + if (strcasecmp(gl_renderer, "GDI Generic") == 0) { - free(screen); LogMessage(X_ERROR, - "AIGLX: Won't use generic native renderer as it is not accelerated\n"); + "AIGLX: Won't use the generic native renderer as it is not accelerated\n"); goto error; } @@ -704,8 +756,9 @@ glxWinScreenProbe(ScreenPtr pScreen) screen->base.pScreen = pScreen; // Creating the fbConfigs initializes screen->base.fbconfigs and screen->base.numFBConfigs + memset(&rejects, 0, sizeof(rejects)); if (strstr(wgl_extensions, "WGL_ARB_pixel_format")) { - glxWinCreateConfigsExt(hdc, screen); + glxWinCreateConfigsExt(hdc, screen, &rejects); /* Some graphics drivers appear to advertise WGL_ARB_pixel_format, @@ -718,6 +771,7 @@ glxWinScreenProbe(ScreenPtr pScreen) } if (screen->base.numFBConfigs <= 0) { + memset(&rejects, 0, sizeof(rejects)); glxWinCreateConfigs(hdc, screen); screen->has_WGL_ARB_pixel_format = FALSE; } @@ -726,7 +780,6 @@ glxWinScreenProbe(ScreenPtr pScreen) If we still didn't get any fbConfigs, we can't provide GLX for this screen */ if (screen->base.numFBConfigs <= 0) { - free(screen); LogMessage(X_ERROR, "AIGLX: No fbConfigs could be made from native OpenGL pixel formats\n"); goto error; @@ -778,7 +831,7 @@ glxWinScreenProbe(ScreenPtr pScreen) DestroyWindow(hwnd); // dump out fbConfigs now fbConfigIds and visualIDs have been assigned - fbConfigsDump(screen->base.numFBConfigs, screen->base.fbconfigs); + fbConfigsDump(screen->base.numFBConfigs, screen->base.fbconfigs, &rejects); /* Wrap RealizeWindow, UnrealizeWindow and CopyWindow on this screen */ screen->RealizeWindow = pScreen->RealizeWindow; @@ -788,9 +841,20 @@ glxWinScreenProbe(ScreenPtr pScreen) screen->CopyWindow = pScreen->CopyWindow; pScreen->CopyWindow = glxWinCopyWindow; + // Note that WGL is active on this screen + winSetScreenAiglxIsActive(pScreen); + + // Restore the previous sighandler + sigaction(SIGSEGV, &old_act, NULL); + return &screen->base; error: + // Restore the previous sighandler + sigaction(SIGSEGV, &old_act, NULL); + + free(screen); + // Something went wrong and we can't use the native GL implementation // so make sure the mesa GL implementation is selected instead glWinSelectImplementation(0); @@ -934,6 +998,10 @@ glxWinDrawableDestroy(__GLXdrawable * base) } if (glxPriv->hDIB) { + if (!CloseHandle(glxPriv->hSection)) { + ErrorF("CloseHandle failed: %s\n", glxWinErrorMessage()); + } + if (!DeleteObject(glxPriv->hDIB)) { ErrorF("DeleteObject failed: %s\n", glxWinErrorMessage()); } @@ -977,6 +1045,179 @@ glxWinCreateDrawable(ClientPtr client, return &glxPriv->base; } +void +glxWinDeferredCreateDrawable(__GLXWinDrawable *draw, __GLXconfig *config) +{ + switch (draw->base.type) { + case GLX_DRAWABLE_WINDOW: + { + WindowPtr pWin = (WindowPtr) draw->base.pDraw; + + if (!(config->drawableType & GLX_WINDOW_BIT)) { + ErrorF + ("glxWinDeferredCreateDrawable: tried to create a GLX_DRAWABLE_WINDOW drawable with a fbConfig which doesn't have drawableType GLX_WINDOW_BIT\n"); + } + + if (pWin == NULL) { + GLWIN_DEBUG_MSG("Deferring until X window is created"); + return; + } + + GLWIN_DEBUG_MSG("glxWinDeferredCreateDrawable: pWin %p", pWin); + + if (winGetWindowInfo(pWin) == NULL) { + GLWIN_DEBUG_MSG("Deferring until native window is created"); + return; + } + } + break; + + case GLX_DRAWABLE_PBUFFER: + { + if (draw->hPbuffer == NULL) { + __GLXscreen *screen; + glxWinScreen *winScreen; + int pixelFormat; + + // XXX: which DC are we supposed to use??? + HDC screenDC = GetDC(NULL); + + if (!(config->drawableType & GLX_PBUFFER_BIT)) { + ErrorF + ("glxWinDeferredCreateDrawable: tried to create a GLX_DRAWABLE_PBUFFER drawable with a fbConfig which doesn't have drawableType GLX_PBUFFER_BIT\n"); + } + + screen = glxGetScreen(screenInfo.screens[draw->base.pDraw->pScreen->myNum]); + winScreen = (glxWinScreen *) screen; + + pixelFormat = + fbConfigToPixelFormatIndex(screenDC, config, + GLX_PBUFFER_BIT, winScreen); + if (pixelFormat == 0) { + return; + } + + draw->hPbuffer = + wglCreatePbufferARBWrapper(screenDC, pixelFormat, + draw->base.pDraw->width, + draw->base.pDraw->height, NULL); + ReleaseDC(NULL, screenDC); + + if (draw->hPbuffer == NULL) { + ErrorF("wglCreatePbufferARBWrapper error: %s\n", + glxWinErrorMessage()); + return; + } + + GLWIN_DEBUG_MSG + ("glxWinDeferredCreateDrawable: pBuffer %p created for drawable %p", + draw->hPbuffer, draw); + } + } + break; + + case GLX_DRAWABLE_PIXMAP: + { + if (draw->dibDC == NULL) { + BITMAPINFOHEADER bmpHeader; + void *pBits; + __GLXscreen *screen; + DWORD size; + char name[MAX_PATH]; + + memset(&bmpHeader, 0, sizeof(BITMAPINFOHEADER)); + bmpHeader.biSize = sizeof(BITMAPINFOHEADER); + bmpHeader.biWidth = draw->base.pDraw->width; + bmpHeader.biHeight = draw->base.pDraw->height; + bmpHeader.biPlanes = 1; + bmpHeader.biBitCount = draw->base.pDraw->bitsPerPixel; + bmpHeader.biCompression = BI_RGB; + + if (!(config->drawableType & GLX_PIXMAP_BIT)) { + ErrorF + ("glxWinDeferredCreateDrawable: tried to create a GLX_DRAWABLE_PIXMAP drawable with a fbConfig which doesn't have drawableType GLX_PIXMAP_BIT\n"); + } + + draw->dibDC = CreateCompatibleDC(NULL); + if (draw->dibDC == NULL) { + ErrorF("CreateCompatibleDC error: %s\n", glxWinErrorMessage()); + return; + } + +#define RASTERWIDTHBYTES(bmi) (((((bmi)->biWidth*(bmi)->biBitCount)+31)&~31)>>3) + size = bmpHeader.biHeight * RASTERWIDTHBYTES(&bmpHeader); + ErrorF("shared memory region size %zu + %u\n", sizeof(BITMAPINFOHEADER), size); + + // Create unique name for mapping based on XID + // + // XXX: not quite unique as potentially this name could be used in + // another server instance. Not sure how to deal with that. + snprintf(name, sizeof(name), "Local\\CYGWINX_WINDOWSDRI_%08x", draw->base.pDraw->id); + ErrorF("shared memory region name %s\n", name); + + // Create a file mapping backed by the pagefile + draw->hSection = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, + PAGE_READWRITE, 0, sizeof(BITMAPINFOHEADER) + size, name); + if (draw->hSection == NULL) { + ErrorF("CreateFileMapping error: %s\n", glxWinErrorMessage()); + return; + } + + draw->hDIB = + CreateDIBSection(draw->dibDC, (BITMAPINFO *) &bmpHeader, + DIB_RGB_COLORS, &pBits, draw->hSection, sizeof(BITMAPINFOHEADER)); + if (draw->dibDC == NULL) { + ErrorF("CreateDIBSection error: %s\n", glxWinErrorMessage()); + return; + } + + // Store a copy of the BITMAPINFOHEADER at the start of the shared + // memory for the information of the receiving process + { + LPVOID pData = MapViewOfFile(draw->hSection, FILE_MAP_WRITE, 0, 0, 0); + memcpy(pData, (void *)&bmpHeader, sizeof(BITMAPINFOHEADER)); + UnmapViewOfFile(pData); + } + + // XXX: CreateDIBSection insists on allocating the bitmap memory for us, so we're going to + // need some jiggery pokery to point the underlying X Drawable's bitmap at the same set of bits + // so that they can be read with XGetImage as well as glReadPixels, assuming the formats are + // even compatible ... + draw->pOldBits = ((PixmapPtr) draw->base.pDraw)->devPrivate.ptr; + ((PixmapPtr) draw->base.pDraw)->devPrivate.ptr = pBits; + + // Select the DIB into the DC + draw->hOldDIB = SelectObject(draw->dibDC, draw->hDIB); + if (!draw->hOldDIB) { + ErrorF("SelectObject error: %s\n", glxWinErrorMessage()); + } + + screen = glxGetScreen(screenInfo.screens[draw->base.pDraw->pScreen->myNum]); + + // Set the pixel format of the bitmap + glxWinSetPixelFormat(draw->dibDC, + draw->base.pDraw->bitsPerPixel, + GLX_PIXMAP_BIT, + screen, + config); + + GLWIN_DEBUG_MSG + ("glxWinDeferredCreateDrawable: DIB bitmap %p created for drawable %p", + draw->hDIB, draw); + } + } + break; + + default: + { + ErrorF + ("glxWinDeferredCreateDrawable: tried to attach unhandled drawable type %d\n", + draw->base.type); + return; + } + } +} + /* ---------------------------------------------------------------------- */ /* * Texture functions @@ -1020,13 +1261,10 @@ glxWinReleaseTexImage(__GLXcontext * baseContext, */ static Bool -glxWinSetPixelFormat(__GLXWinContext * gc, HDC hdc, int bppOverride, - int drawableTypeOverride) +glxWinSetPixelFormat(HDC hdc, int bppOverride, int drawableTypeOverride, + __GLXscreen *screen, __GLXconfig *config) { - __GLXscreen *screen = gc->base.pGlxScreen; glxWinScreen *winScreen = (glxWinScreen *) screen; - - __GLXconfig *config = gc->base.config; GLXWinConfig *winConfig = (GLXWinConfig *) config; GLWIN_DEBUG_MSG("glxWinSetPixelFormat: pixelFormatIndex %d", @@ -1072,12 +1310,35 @@ glxWinSetPixelFormat(__GLXWinContext * gc, HDC hdc, int bppOverride, (config->redBits + config->greenBits + config->blueBits), bppOverride, config->drawableType, drawableTypeOverride); - if (!winScreen->has_WGL_ARB_pixel_format) { + if (winScreen->has_WGL_ARB_pixel_format) { + int pixelFormat = + fbConfigToPixelFormatIndex(hdc, config, + drawableTypeOverride, winScreen); + if (pixelFormat != 0) { + GLWIN_DEBUG_MSG("wglChoosePixelFormat: chose pixelFormatIndex %d", + pixelFormat); + ErrorF + ("wglChoosePixelFormat: chose pixelFormatIndex %d (rather than %d as originally planned)\n", + pixelFormat, winConfig->pixelFormatIndex); + + if (!SetPixelFormat(hdc, pixelFormat, NULL)) { + ErrorF("SetPixelFormat error: %s\n", glxWinErrorMessage()); + return FALSE; + } + } + } + + /* + For some drivers, wglChoosePixelFormatARB() can fail when the provided + DC doesn't belong to the driver (e.g. it's a compatible DC for a bitmap, + so allow fallback to ChoosePixelFormat() + */ + { PIXELFORMATDESCRIPTOR pfd; int pixelFormat; /* convert fbConfig to PFD */ - if (fbConfigToPixelFormat(gc->base.config, &pfd, drawableTypeOverride)) { + if (fbConfigToPixelFormat(config, &pfd, drawableTypeOverride)) { ErrorF("glxWinSetPixelFormat: fbConfigToPixelFormat failed\n"); return FALSE; } @@ -1108,25 +1369,6 @@ glxWinSetPixelFormat(__GLXWinContext * gc, HDC hdc, int bppOverride, return FALSE; } } - else { - int pixelFormat = - fbConfigToPixelFormatIndex(hdc, gc->base.config, - drawableTypeOverride, winScreen); - if (pixelFormat == 0) { - return FALSE; - } - - GLWIN_DEBUG_MSG("wglChoosePixelFormat: chose pixelFormatIndex %d", - pixelFormat); - ErrorF - ("wglChoosePixelFormat: chose pixelFormatIndex %d (rather than %d as originally planned)\n", - pixelFormat, winConfig->pixelFormatIndex); - - if (!SetPixelFormat(hdc, pixelFormat, NULL)) { - ErrorF("SetPixelFormat error: %s\n", glxWinErrorMessage()); - return FALSE; - } - } return TRUE; } @@ -1178,7 +1420,7 @@ glxWinMakeDC(__GLXWinContext * gc, __GLXWinDrawable * draw, HDC * hdc, gc->hwnd = *hwnd; /* We must select a pixelformat, but SetPixelFormat can only be called once for a window... */ - if (!glxWinSetPixelFormat(gc, *hdc, 0, GLX_WINDOW_BIT)) { + if (!glxWinSetPixelFormat(*hdc, 0, GLX_WINDOW_BIT, gc->base.pGlxScreen, gc->base.config)) { ErrorF("glxWinSetPixelFormat error: %s\n", glxWinErrorMessage()); ReleaseDC(*hwnd, *hdc); @@ -1264,140 +1506,7 @@ glxWinDeferredCreateContext(__GLXWinContext * gc, __GLXWinDrawable * draw) ("glxWinDeferredCreateContext: attach context %p to drawable %p", gc, draw); - switch (draw->base.type) { - case GLX_DRAWABLE_WINDOW: - { - WindowPtr pWin = (WindowPtr) draw->base.pDraw; - - if (!(gc->base.config->drawableType & GLX_WINDOW_BIT)) { - ErrorF - ("glxWinDeferredCreateContext: tried to attach a context whose fbConfig doesn't have drawableType GLX_WINDOW_BIT to a GLX_DRAWABLE_WINDOW drawable\n"); - } - - if (pWin == NULL) { - GLWIN_DEBUG_MSG("Deferring until X window is created"); - return; - } - - GLWIN_DEBUG_MSG("glxWinDeferredCreateContext: pWin %p", pWin); - - if (winGetWindowInfo(pWin) == NULL) { - GLWIN_DEBUG_MSG("Deferring until native window is created"); - return; - } - } - break; - - case GLX_DRAWABLE_PBUFFER: - { - if (draw->hPbuffer == NULL) { - __GLXscreen *screen; - glxWinScreen *winScreen; - int pixelFormat; - - // XXX: which DC are we supposed to use??? - HDC screenDC = GetDC(NULL); - - if (!(gc->base.config->drawableType & GLX_PBUFFER_BIT)) { - ErrorF - ("glxWinDeferredCreateContext: tried to attach a context whose fbConfig doesn't have drawableType GLX_PBUFFER_BIT to a GLX_DRAWABLE_PBUFFER drawable\n"); - } - - screen = gc->base.pGlxScreen; - winScreen = (glxWinScreen *) screen; - - pixelFormat = - fbConfigToPixelFormatIndex(screenDC, gc->base.config, - GLX_PBUFFER_BIT, winScreen); - if (pixelFormat == 0) { - return; - } - - draw->hPbuffer = - wglCreatePbufferARBWrapper(screenDC, pixelFormat, - draw->base.pDraw->width, - draw->base.pDraw->height, NULL); - ReleaseDC(NULL, screenDC); - - if (draw->hPbuffer == NULL) { - ErrorF("wglCreatePbufferARBWrapper error: %s\n", - glxWinErrorMessage()); - return; - } - - GLWIN_DEBUG_MSG - ("glxWinDeferredCreateContext: pBuffer %p created for drawable %p", - draw->hPbuffer, draw); - } - } - break; - - case GLX_DRAWABLE_PIXMAP: - { - if (draw->dibDC == NULL) { - BITMAPINFOHEADER bmpHeader; - void *pBits; - - memset(&bmpHeader, 0, sizeof(BITMAPINFOHEADER)); - bmpHeader.biSize = sizeof(BITMAPINFOHEADER); - bmpHeader.biWidth = draw->base.pDraw->width; - bmpHeader.biHeight = draw->base.pDraw->height; - bmpHeader.biPlanes = 1; - bmpHeader.biBitCount = draw->base.pDraw->bitsPerPixel; - bmpHeader.biCompression = BI_RGB; - - if (!(gc->base.config->drawableType & GLX_PIXMAP_BIT)) { - ErrorF - ("glxWinDeferredCreateContext: tried to attach a context whose fbConfig doesn't have drawableType GLX_PIXMAP_BIT to a GLX_DRAWABLE_PIXMAP drawable\n"); - } - - draw->dibDC = CreateCompatibleDC(NULL); - if (draw->dibDC == NULL) { - ErrorF("CreateCompatibleDC error: %s\n", glxWinErrorMessage()); - return; - } - - draw->hDIB = - CreateDIBSection(draw->dibDC, (BITMAPINFO *) &bmpHeader, - DIB_RGB_COLORS, &pBits, 0, 0); - if (draw->dibDC == NULL) { - ErrorF("CreateDIBSection error: %s\n", glxWinErrorMessage()); - return; - } - - // XXX: CreateDIBSection insists on allocating the bitmap memory for us, so we're going to - // need some jiggery pokery to point the underlying X Drawable's bitmap at the same set of bits - // so that they can be read with XGetImage as well as glReadPixels, assuming the formats are - // even compatible ... - draw->pOldBits = ((PixmapPtr) draw->base.pDraw)->devPrivate.ptr; - ((PixmapPtr) draw->base.pDraw)->devPrivate.ptr = pBits; - - // Select the DIB into the DC - draw->hOldDIB = SelectObject(draw->dibDC, draw->hDIB); - if (!draw->hOldDIB) { - ErrorF("SelectObject error: %s\n", glxWinErrorMessage()); - } - - // Set the pixel format of the bitmap - glxWinSetPixelFormat(gc, draw->dibDC, - draw->base.pDraw->bitsPerPixel, - GLX_PIXMAP_BIT); - - GLWIN_DEBUG_MSG - ("glxWinDeferredCreateContext: DIB bitmap %p created for drawable %p", - draw->hDIB, draw); - } - } - break; - - default: - { - ErrorF - ("glxWinDeferredCreateContext: tried to attach unhandled drawable type %d\n", - draw->base.type); - return; - } - } + glxWinDeferredCreateDrawable(draw, gc->base.config); dc = glxWinMakeDC(gc, draw, &dc, &hwnd); gc->ctx = wglCreateContext(dc); @@ -1862,8 +1971,8 @@ glxWinCreateConfigs(HDC hdc, glxWinScreen * screen) if (!(pfd.dwFlags & (PFD_DRAW_TO_WINDOW | PFD_DRAW_TO_BITMAP)) || !(pfd.dwFlags & PFD_SUPPORT_OPENGL)) { GLWIN_DEBUG_MSG - ("pixelFormat %d has unsuitable flags 0x%08lx, skipping", i + 1, - pfd.dwFlags); + ("pixelFormat %d has unsuitable flags 0x%08x, skipping", i + 1, + (unsigned int)pfd.dwFlags); continue; } @@ -1913,6 +2022,8 @@ glxWinCreateConfigs(HDC hdc, glxWinScreen * screen) /* EXT_visual_rating / GLX 1.2 */ if (pfd.dwFlags & PFD_GENERIC_FORMAT) { c->base.visualRating = GLX_SLOW_VISUAL_EXT; + GLWIN_DEBUG_MSG("pixelFormat %d is un-accelerated, skipping", i + 1); + continue; } else { // PFD_GENERIC_ACCELERATED is not considered, so this may be MCD or ICD acclerated... @@ -2047,7 +2158,7 @@ getAttrValue(const int attrs[], int values[], unsigned int num, int attr, // Create the GLXconfigs using wglGetPixelFormatAttribfvARB() extension // static void -glxWinCreateConfigsExt(HDC hdc, glxWinScreen * screen) +glxWinCreateConfigsExt(HDC hdc, glxWinScreen * screen, PixelFormatRejectStats * rejects) { GLXWinConfig *c, *result, *prev = NULL; int i = 0; @@ -2159,6 +2270,7 @@ glxWinCreateConfigsExt(HDC hdc, glxWinScreen * screen) #define ATTR_VALUE(a, d) getAttrValue(attrs, values, num_attrs, (a), (d)) if (!ATTR_VALUE(WGL_SUPPORT_OPENGL_ARB, 0)) { + rejects->notOpenGL++; GLWIN_DEBUG_MSG ("pixelFormat %d isn't WGL_SUPPORT_OPENGL_ARB, skipping", i + 1); @@ -2195,11 +2307,13 @@ glxWinCreateConfigsExt(HDC hdc, glxWinScreen * screen) break; case WGL_TYPE_RGBA_FLOAT_ARB: + rejects->rgbaFloat++; GLWIN_DEBUG_MSG ("pixelFormat %d is WGL_TYPE_RGBA_FLOAT_ARB, skipping", i + 1); continue; case WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT: + rejects->unsignedRgbaFloat++; GLWIN_DEBUG_MSG ("pixelFormat %d is WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT, skipping", i + 1); @@ -2212,6 +2326,7 @@ glxWinCreateConfigsExt(HDC hdc, glxWinScreen * screen) break; default: + rejects->unknownPixelType++; ErrorF ("wglGetPixelFormatAttribivARB returned unknown value 0x%x for WGL_PIXEL_TYPE_ARB\n", ATTR_VALUE(WGL_PIXEL_TYPE_ARB, 0)); @@ -2252,7 +2367,10 @@ glxWinCreateConfigsExt(HDC hdc, glxWinScreen * screen) ATTR_VALUE(WGL_ACCELERATION_ARB, 0)); case WGL_NO_ACCELERATION_ARB: + rejects->unaccelerated++; c->base.visualRating = GLX_SLOW_VISUAL_EXT; + GLWIN_DEBUG_MSG("pixelFormat %d is un-accelerated, skipping", i + 1); + continue; break; case WGL_GENERIC_ACCELERATION_ARB: @@ -2324,11 +2442,16 @@ glxWinCreateConfigsExt(HDC hdc, glxWinScreen * screen) /* SGIX_pbuffer / GLX 1.3 */ if (screen->has_WGL_ARB_pbuffer) { - c->base.maxPbufferWidth = ATTR_VALUE(WGL_MAX_PBUFFER_WIDTH_ARB, -1); - c->base.maxPbufferHeight = - ATTR_VALUE(WGL_MAX_PBUFFER_HEIGHT_ARB, -1); - c->base.maxPbufferPixels = - ATTR_VALUE(WGL_MAX_PBUFFER_PIXELS_ARB, -1); + // mesa libGL "can't handle the truth" about max pbuffer size. + // We must report 0, which exactly matches what it expects + // + // ATTR_VALUE(WGL_MAX_PBUFFER_WIDTH_ARB, -1); + // ATTR_VALUE(WGL_MAX_PBUFFER_PIXELS_ARB, -1); + // ATTR_VALUE(WGL_MAX_PBUFFER_HEIGHT_ARB, -1); + // + c->base.maxPbufferWidth = 0; + c->base.maxPbufferHeight = 0; + c->base.maxPbufferPixels = 0; } else { c->base.maxPbufferWidth = -1; diff --git a/hw/xwin/glx/indirect.h b/hw/xwin/glx/indirect.h new file mode 100644 index 000000000..163375556 --- /dev/null +++ b/hw/xwin/glx/indirect.h @@ -0,0 +1,94 @@ +/* + * Copyright © 2014 Jon TURNEY + * + * 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. + */ + +#ifndef indirect_h +#define indirect_h + +#include <X11/Xwindows.h> +#include <GL/wglext.h> +#include <glx/extension_string.h> + +/* ---------------------------------------------------------------------- */ +/* + * structure definitions + */ + +typedef struct __GLXWinContext __GLXWinContext; +typedef struct __GLXWinDrawable __GLXWinDrawable; +typedef struct __GLXWinScreen glxWinScreen; +typedef struct __GLXWinConfig GLXWinConfig; + +struct __GLXWinContext { + __GLXcontext base; + HGLRC ctx; /* Windows GL Context */ + __GLXWinContext *shareContext; /* Context with which we will share display lists and textures */ + HWND hwnd; /* For detecting when HWND has changed */ +}; + +struct __GLXWinDrawable { + __GLXdrawable base; + __GLXWinContext *drawContext; + __GLXWinContext *readContext; + + /* If this drawable is GLX_DRAWABLE_PBUFFER */ + HPBUFFERARB hPbuffer; + + /* If this drawable is GLX_DRAWABLE_PIXMAP */ + HDC dibDC; + HANDLE hSection; /* file mapping handle */ + HBITMAP hDIB; + HBITMAP hOldDIB; /* original DIB for DC */ + void *pOldBits; /* original pBits for this drawable's pixmap */ +}; + +struct __GLXWinScreen { + __GLXscreen base; + + /* Supported GLX extensions */ + unsigned char glx_enable_bits[__GLX_EXT_BYTES]; + + Bool has_WGL_ARB_multisample; + Bool has_WGL_ARB_pixel_format; + Bool has_WGL_ARB_pbuffer; + Bool has_WGL_ARB_render_texture; + + /* wrapped screen functions */ + RealizeWindowProcPtr RealizeWindow; + UnrealizeWindowProcPtr UnrealizeWindow; + CopyWindowProcPtr CopyWindow; +}; + +struct __GLXWinConfig { + __GLXconfig base; + int pixelFormatIndex; +}; + +/* ---------------------------------------------------------------------- */ +/* + * function prototypes + */ + +void +glxWinDeferredCreateDrawable(__GLXWinDrawable *draw, __GLXconfig *config); + +#endif /* indirect_h */ diff --git a/hw/xwin/glx/winpriv.c b/hw/xwin/glx/winpriv.c index 9b4baf381..5418f8455 100644 --- a/hw/xwin/glx/winpriv.c +++ b/hw/xwin/glx/winpriv.c @@ -14,6 +14,41 @@ void winCreateWindowsWindow(WindowPtr pWin); +static void +winCreateWindowsWindowHierarchy(WindowPtr pWin) +{ + winWindowPriv(pWin); + + winDebug("winCreateWindowsWindowHierarchy - pWin:%p XID:0x%x \n", pWin, + pWin->drawable.id); + + if (!pWin) + return; + + /* stop recursion at root window */ + if (pWin == pWin->drawable.pScreen->root) + return; + + /* recursively ensure parent window exists */ + if (pWin->parent) + winCreateWindowsWindowHierarchy(pWin->parent); + + /* ensure this window exists */ + if (pWinPriv->hWnd == NULL) { + winCreateWindowsWindow(pWin); + + /* ... and if it's already been mapped, make sure it's visible */ + if (pWin->mapped) { + /* Display the window without activating it */ + if (pWin->drawable.class != InputOnly) + ShowWindow(pWinPriv->hWnd, SW_SHOWNOACTIVATE); + + /* Send first paint message */ + UpdateWindow(pWinPriv->hWnd); + } + } +} + /** * Return size and handles of a window. * If pWin is NULL, then the information for the root window is requested. @@ -50,7 +85,7 @@ winGetWindowInfo(WindowPtr pWin) } if (pWinPriv->hWnd == NULL) { - winCreateWindowsWindow(pWin); + winCreateWindowsWindowHierarchy(pWin); winDebug("winGetWindowInfo: forcing window to exist\n"); } @@ -119,3 +154,10 @@ winCheckScreenAiglxIsSupported(ScreenPtr pScreen) return FALSE; } + +void +winSetScreenAiglxIsActive(ScreenPtr pScreen) +{ + winPrivScreenPtr pWinScreen = winGetScreenPriv(pScreen); + pWinScreen->fNativeGlActive = TRUE; +} diff --git a/hw/xwin/glx/winpriv.h b/hw/xwin/glx/winpriv.h index dce1edf48..6f695a971 100644 --- a/hw/xwin/glx/winpriv.h +++ b/hw/xwin/glx/winpriv.h @@ -9,3 +9,4 @@ HWND winGetWindowInfo(WindowPtr pWin); Bool winCheckScreenAiglxIsSupported(ScreenPtr pScreen); +void winSetScreenAiglxIsActive(ScreenPtr pScreen); diff --git a/hw/xwin/layout_mapping_check.c b/hw/xwin/layout_mapping_check.c new file mode 100644 index 000000000..429be9821 --- /dev/null +++ b/hw/xwin/layout_mapping_check.c @@ -0,0 +1,51 @@ +/* + * Copyright © 2015 Jon TURNEY + * + * 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. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include "winlayouts.h" + +int main() +{ + WinKBLayoutPtr pLayout; + for (pLayout = winKBLayouts; pLayout->winlayout != -1; pLayout++) { + char cmd[1024]; + strcpy(cmd, "setxkbmap "); + strcat(cmd, "-layout "); + strcat(cmd, pLayout->xkblayout); + strcat(cmd, " -model "); + strcat(cmd, pLayout->xkbmodel); + if (pLayout->xkbvariant) { + strcat(cmd, " -variant "); + strcat(cmd, pLayout->xkbvariant); + } + if (pLayout->xkboptions) { + strcat(cmd, " -options "); + strcat(cmd, pLayout->xkboptions); + } + if (system(cmd)) { + printf("'%s' failed\n", cmd); + } + } +} diff --git a/hw/xwin/man/XWin.man b/hw/xwin/man/XWin.man index 15a57db02..589b0815e 100644 --- a/hw/xwin/man/XWin.man +++ b/hw/xwin/man/XWin.man @@ -76,6 +76,9 @@ preceeding \fB\-screen\fP parameter. .B \-[no]multimonitors or \-[no]multiplemonitors Create a screen 0 that covers all monitors [the primary monitor] on a system with multiple monitors. +Fake XINERAMA data is created describing the individual monitors, +(This is similar to the 'merged framebuffer' or 'pseudo-xinerama' mode provided by +some drivers for the xorg X server). This option is currently enabled by default in \fB\-multiwindow\fP mode. .TP 8 .B "\-screen \fIscreen_number\fP [\fIW\fP \fIH\fP [\fIX\fP \fIY\fP] | [[\fIW\fPx\fIH\fP[+\fIX\fP+\fIY\fP]][@\fIM\fP]] ] " @@ -121,7 +124,8 @@ Alternative name for \fB\-resize=scrollbars\fP. .SH OPTIONS CONTROLLING RESIZE BEHAVIOUR .TP 8 .B \-resize[=none|scrollbars|randr] -Select the resize mode of an X screen. The default is randr. +Select the resize mode of an X screen. +The default is \fBnone\fP if \fB\-fullscreen\fP is used, \fBrandr\fP otherwise. .RS .IP \fB\-resize=none\fP 8 @@ -167,9 +171,16 @@ on its own is equivalent to \fB\-resize=randr\fP .SH OPTIONS FOR MULTIWINDOW MODE .TP 8 -.B \-hostintitle +.B \-[no]hostintitle 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 \-compositewm +Experimental. +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. .SH OPTIONS CONTROLLING WINDOWS INTEGRATION .TP 8 @@ -239,14 +250,12 @@ clipping region is then used to do a single bit block transfer that is constrained to the updated area by the clipping region. There is some overhead involved in creating, installing, destroying, and removing the clipping region, thus there may not be much benefit for a small -number of boxes (less than 10). It is even possible that this +number of boxes. It is even possible that this functionality does not provide a benefit at any number of boxes; we can only determine the usefulness of this feature through testing. This option probably has limited effect on current \fIWindows\fP versions as they already perform GDI batching. -This parameter works in conjunction with engines 1, 2, and 4 (Shadow -GDI, Shadow DirectDraw, and Shadow DirectDraw Non-Locking, -respectively). +This parameter only has any effect when a Shadow drawing engine is selected. .TP 8 .B "\-engine \fIengine_type_id\fP" This option, which is intended for Cygwin/X developers, @@ -262,7 +271,7 @@ The engine type ids are: .IP 1 4 Shadow GDI .IP 2 4 -Shadow DirectDraw +Shadow DirectDraw (obsolete, disabled) .IP 4 4 Shadow DirectDraw Non-Locking .RE diff --git a/hw/xwin/man/XWinrc.man b/hw/xwin/man/XWinrc.man index 71d8dad23..60b8ce1ec 100644 --- a/hw/xwin/man/XWinrc.man +++ b/hw/xwin/man/XWinrc.man @@ -54,6 +54,35 @@ There are four kinds of instructions: miscellaneous, menu, icon and style. .SH Miscellaneous instruction .TP 8 +.B DPI \fIresolution\fP +Sets the resolution for all screens, in dots per inch. To be used when +the server cannot determine the screen size(s) from the hardware. + +.TP 8 +.B XKBLayout \fIlayout\fP +.TP 8 +.B XKBModel \fImodel\fP +.TP 8 +.B XKBOptions \fIoption\fP +.TP 8 +.B XKBRules \fIrule\fP +.TP 8 +.B XKBVariant \fIvariant\fp +These options configure the xkeyboard extension to load a particular +keyboard map as the X server starts. The behavior is similar to the +\fIsetxkbmap\fP(1) program. + +See the \fIxkeyboard-config\fP(__miscmansuffix__) manual page for a list of +keyboard configurations. + +Alternatively, you can use \fIsetxkbmap\fP(1) program after \fIXWin\fP +is running. + +The default is to select a keyboard configuration matching your current +layout as reported by \fIWindows\fP, if known, or the default X server +configuration if no matching keyboard configuration was found. + +.TP 8 .B DEBUG \fIString\fP The \fIString\fP is printed to the XWin log file. @@ -171,7 +200,7 @@ will be used. .SH Style Instructions .TP 8 .B STYLES { -\fIclass-or-name-of-window\fP \fIstyle-keyword-1\fP \fIstyle-keyword-2\fP +\fIclass-or-name-of-window\fP \fIstyle-keyword-1\fP \fIstyle-keyword-2\fP \fIstyle-keyword-3\fP .br \fI...\fP .br @@ -216,8 +245,14 @@ No Windows title bar and just a thin-line border, for the class or name. .br No Windows title bar or border, for the class or name. -One keyword in \fIstyle-keyword-1\fP can be used with one keyword in \fIstyle-keyword-2\fP, -or any keyword can be used singly. +\fIstyle-keyword-3\fP + +\fBSKIPTASKBAR\fP +.br +Omit the class or name from being listed in the Windows taskbar. + +Up to one keyword from each of these three groups can be used. Not all +groups need be used, and the keywords can be given in any order. .SH EXAMPLE diff --git a/hw/xwin/system.XWinrc b/hw/xwin/system.XWinrc index f0771c610..f572bf301 100644 --- a/hw/xwin/system.XWinrc +++ b/hw/xwin/system.XWinrc @@ -89,9 +89,17 @@ menu apps { } menu root { + "Applications" menu apps // Comments fit here, too... + + SEPARATOR + FAQ EXEC "cygstart http://x.cygwin.com/docs/faq/cygwin-x-faq.html" + "User's Guide" EXEC "cygstart http://x.cygwin.com/docs/ug/cygwin-x-ug.html" + SEPARATOR + "View logfile" EXEC "xterm -title $XWINLOGFILE -e less +F $XWINLOGFILE" + SEPARATOR + "Reload .XWinrc" RELOAD - "Applications" menu apps SEParATOR } diff --git a/hw/xwin/win.h b/hw/xwin/win.h index b7d20ca73..911415b8c 100644 --- a/hw/xwin/win.h +++ b/hw/xwin/win.h @@ -163,7 +163,6 @@ #include "mipointer.h" #include "X11/keysym.h" #include "micoord.h" -#include "dix.h" #include "miline.h" #include "shadow.h" #include "fb.h" @@ -273,6 +272,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); @@ -288,38 +289,13 @@ typedef Bool (*winCreateColormapProcPtr) (ColormapPtr pColormap); typedef Bool (*winDestroyColormapProcPtr) (ColormapPtr pColormap); -typedef Bool (*winHotKeyAltTabProcPtr) (ScreenPtr); - typedef Bool (*winCreatePrimarySurfaceProcPtr) (ScreenPtr); typedef Bool (*winReleasePrimarySurfaceProcPtr) (ScreenPtr); -typedef Bool (*winFinishCreateWindowsWindowProcPtr) (WindowPtr pWin); - typedef Bool (*winCreateScreenResourcesProc) (ScreenPtr); /* - * GC (graphics context) privates - */ - -typedef struct { - HDC hdc; - HDC hdcMem; -} winPrivGCRec, *winPrivGCPtr; - -/* - * Pixmap privates - */ - -typedef struct { - HDC hdcSelected; - HBITMAP hBitmap; - BYTE *pbBits; - DWORD dwScanlineBytes; - BITMAPINFOHEADER *pbmih; -} winPrivPixmapRec, *winPrivPixmapPtr; - -/* * Colormap privates */ @@ -330,6 +306,7 @@ typedef struct { PALETTEENTRY peColors[WIN_NUM_PALETTE_ENTRIES]; } winPrivCmapRec, *winPrivCmapPtr; + /* * Windows Cursor handling. */ @@ -349,7 +326,8 @@ typedef struct { * Resize modes */ typedef enum { - notAllowed, + resizeDefault = -1, + resizeNotAllowed, resizeWithScrollbars, resizeWithRandr } winResizeMode; @@ -411,6 +389,7 @@ typedef struct { Bool fRootless; #ifdef XWIN_MULTIWINDOW Bool fMultiWindow; + Bool fCompositeWM; #endif #if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM) Bool fMultiMonitorOverride; @@ -533,6 +512,7 @@ typedef struct _winPrivScreenRec { winCreateBoundingWindowProcPtr pwinCreateBoundingWindow; winFinishScreenInitProcPtr pwinFinishScreenInit; winBltExposedRegionsProcPtr pwinBltExposedRegions; + winBltExposedWindowRegionProcPtr pwinBltExposedWindowRegion; winActivateAppProcPtr pwinActivateApp; winRedrawScreenProcPtr pwinRedrawScreen; winRealizeInstalledPaletteProcPtr pwinRealizeInstalledPalette; @@ -540,17 +520,10 @@ typedef struct _winPrivScreenRec { winStoreColorsProcPtr pwinStoreColors; winCreateColormapProcPtr pwinCreateColormap; winDestroyColormapProcPtr pwinDestroyColormap; - winHotKeyAltTabProcPtr pwinHotKeyAltTab; winCreatePrimarySurfaceProcPtr pwinCreatePrimarySurface; winReleasePrimarySurfaceProcPtr pwinReleasePrimarySurface; - winCreateScreenResourcesProc pwinCreateScreenResources; -#ifdef XWIN_MULTIWINDOW - /* Window Procedures for MultiWindow mode */ - winFinishCreateWindowsWindowProcPtr pwinFinishCreateWindowsWindow; -#endif - /* Window Procedures for Rootless mode */ CreateWindowProcPtr CreateWindow; DestroyWindowProcPtr DestroyWindow; @@ -570,6 +543,8 @@ typedef struct _winPrivScreenRec { SetShapeProcPtr SetShape; winCursorRec cursor; + + Bool fNativeGlActive; } winPrivScreenRec; #ifdef XWIN_MULTIWINDOWEXTWM @@ -844,9 +819,6 @@ void */ int - winTranslateKey(WPARAM wParam, LPARAM lParam); - -int winKeybdProc(DeviceIntPtr pDeviceInt, int iState); void @@ -855,20 +827,6 @@ void void winRestoreModeKeyStates(void); -Bool - winIsFakeCtrl_L(UINT message, WPARAM wParam, LPARAM lParam); - -void - winKeybdReleaseKeys(void); - -void - winSendKeyEvent(DWORD dwKey, Bool fDown); - -BOOL winCheckKeyPressed(WPARAM wParam, LPARAM lParam); - -void - winFixShiftKeys(int iScanCode); - /* * winkeyhook.c */ @@ -897,14 +855,7 @@ int winMouseProc(DeviceIntPtr pDeviceInt, int iState); int - winMouseWheel(int *iTotalDeltaZ, int iDeltaZ, int iButtonUp, int iButtonDown); - -void - winMouseButtonsSendEvent(int iEventType, int iButton); - -int - -winMouseButtonsHandle(ScreenPtr pScreen, + winMouseButtonsHandle(ScreenPtr pScreen, int iEventType, int iButton, WPARAM wParam); void @@ -1050,6 +1001,8 @@ int LRESULT CALLBACK winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); +LRESULT CALLBACK +winChildWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); #endif /* diff --git a/hw/xwin/winallpriv.c b/hw/xwin/winallpriv.c index 629af92c9..d73fc96cd 100644 --- a/hw/xwin/winallpriv.c +++ b/hw/xwin/winallpriv.c @@ -48,8 +48,8 @@ winAllocatePrivates(ScreenPtr pScreen) winPrivScreenPtr pScreenPriv; #if CYGDEBUG - winDebug("winAllocateScreenPrivates - g_ulServerGeneration: %d " - "serverGeneration: %d\n", g_ulServerGeneration, serverGeneration); + winDebug("winAllocateScreenPrivates - g_ulServerGeneration: %lu " + "serverGeneration: %lu\n", g_ulServerGeneration, serverGeneration); #endif /* We need a new slot for our privates if the screen gen has changed */ @@ -79,20 +79,6 @@ winAllocatePrivates(ScreenPtr pScreen) /* Save the screen private pointer */ winSetScreenPriv(pScreen, pScreenPriv); - /* Reserve GC memory for our privates */ - if (!dixRegisterPrivateKey - (g_iGCPrivateKey, PRIVATE_GC, sizeof(winPrivGCRec))) { - ErrorF("winAllocatePrivates - AllocateGCPrivate () failed\n"); - return FALSE; - } - - /* Reserve Pixmap memory for our privates */ - if (!dixRegisterPrivateKey - (g_iPixmapPrivateKey, PRIVATE_PIXMAP, sizeof(winPrivPixmapRec))) { - ErrorF("winAllocatePrivates - AllocatePixmapPrivates () failed\n"); - return FALSE; - } - /* Reserve Window memory for our privates */ if (!dixRegisterPrivateKey (g_iWindowPrivateKey, PRIVATE_WINDOW, sizeof(winPrivWinRec))) { diff --git a/hw/xwin/winauth.c b/hw/xwin/winauth.c index 7efa1c00f..c75228c9f 100644 --- a/hw/xwin/winauth.c +++ b/hw/xwin/winauth.c @@ -38,6 +38,15 @@ #include "securitysrv.h" #include "os/osdep.h" +/* Need to get this from Xlib.h */ +extern void XSetAuthorization( + const char * /* name */, + int /* namelen */, + const char * /* data */, + int /* datalen */ +); + + /* * Constants */ diff --git a/hw/xwin/winblock.c b/hw/xwin/winblock.c index 07e907828..8b846520c 100644 --- a/hw/xwin/winblock.c +++ b/hw/xwin/winblock.c @@ -70,7 +70,7 @@ winBlockHandler(ScreenPtr pScreen, if (pScreenPriv != NULL && !pScreenPriv->fServerStarted) { int iReturn; - ErrorF("winBlockHandler - pthread_mutex_unlock()\n"); + winDebug("winBlockHandler - pthread_mutex_unlock()\n"); /* Flag that modules are to be started */ pScreenPriv->fServerStarted = TRUE; diff --git a/hw/xwin/winclipboard/debug.c b/hw/xwin/winclipboard/debug.c index 78ab6d902..9f2023d02 100644 --- a/hw/xwin/winclipboard/debug.c +++ b/hw/xwin/winclipboard/debug.c @@ -25,6 +25,7 @@ #include <stdarg.h> #include <stdio.h> +#include <windows.h> #if 1 int @@ -50,3 +51,8 @@ ErrorF(const char *format, ...) va_end(ap); return count; } + +void winDebugWin32Message(const char *function, HWND hwnd, UINT message, + WPARAM wParam, LPARAM lParam) +{ +} diff --git a/hw/xwin/winclipboard/internal.h b/hw/xwin/winclipboard/internal.h index c6bde84af..20754e72e 100644 --- a/hw/xwin/winclipboard/internal.h +++ b/hw/xwin/winclipboard/internal.h @@ -1,4 +1,3 @@ - /* *Copyright (C) 2003-2004 Harold L Hunt II All Rights Reserved. * @@ -50,8 +49,10 @@ * References to external symbols */ -extern void winDebug(const char *format, ...); -extern void ErrorF(const char *format, ...); +extern void winDebug(const char *format, ...) _X_ATTRIBUTE_PRINTF(1, 2); +extern void ErrorF(const char *format, ...) _X_ATTRIBUTE_PRINTF(1, 2); +extern void winDebugWin32Message(const char *function, HWND hwnd, UINT message, + WPARAM wParam, LPARAM lParam); /* * winclipboardtextconv.c @@ -77,6 +78,14 @@ typedef struct Atom atomTargets; } ClipboardAtoms; +/* Modern clipboard API functions */ +typedef wBOOL WINAPI (*ADDCLIPBOARDFORMATLISTENERPROC)(HWND hwnd); +typedef wBOOL WINAPI (*REMOVECLIPBOARDFORMATLISTENERPROC)(HWND hwnd); + +extern Bool g_fHasModernClipboardApi; +extern ADDCLIPBOARDFORMATLISTENERPROC g_fpAddClipboardFormatListener; +extern REMOVECLIPBOARDFORMATLISTENERPROC g_fpRemoveClipboardFormatListener; + /* * winclipboardwndproc.c */ diff --git a/hw/xwin/winclipboard/textconv.c b/hw/xwin/winclipboard/textconv.c index 9c9cb3529..2870a9b8a 100644 --- a/hw/xwin/winclipboard/textconv.c +++ b/hw/xwin/winclipboard/textconv.c @@ -52,11 +52,14 @@ */ void -winClipboardDOStoUNIX(char *pszSrc, int iLength) +winClipboardDOStoUNIX(char *pszData, int iLength) { + char *pszSrc = pszData; char *pszDest = pszSrc; char *pszEnd = pszSrc + iLength; + winDebug("DOXtoUNIX() - Original data:'%s'\n", pszData); + /* Loop until the last character */ while (pszSrc < pszEnd) { /* Copy the current source character to current destination character */ @@ -72,6 +75,8 @@ winClipboardDOStoUNIX(char *pszSrc, int iLength) /* Move the terminating null */ *pszDest = '\0'; + + winDebug("DOStoUNIX() - Final string:'%s'\n", pszData); } /* @@ -105,8 +110,10 @@ winClipboardUNIXtoDOS(char **ppszData, int iLength) } /* Return if no naked \n's */ - if (iNewlineCount == 0) + if (iNewlineCount == 0) { + winDebug("UNIXtoDOS () - no conversion necessary\n"); return; + } /* Allocate a new string */ pszDestBegin = pszDest = malloc(iLength + iNewlineCount + 1); diff --git a/hw/xwin/winclipboard/thread.c b/hw/xwin/winclipboard/thread.c index 50e1e8cb5..aa0a98b91 100644 --- a/hw/xwin/winclipboard/thread.c +++ b/hw/xwin/winclipboard/thread.c @@ -55,6 +55,7 @@ #ifdef HAS_WINSOCK #include <X11/Xwinsock.h> #else +#include <sys/select.h> #include <errno.h> #endif @@ -84,6 +85,10 @@ static pthread_t g_winClipboardProcThread; int xfixes_event_base; int xfixes_error_base; +Bool g_fHasModernClipboardApi = FALSE; +ADDCLIPBOARDFORMATLISTENERPROC g_fpAddClipboardFormatListener; +REMOVECLIPBOARDFORMATLISTENERPROC g_fpRemoveClipboardFormatListener; + /* * Local function prototypes */ @@ -127,16 +132,10 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay) winDebug("winClipboardProc - Hello\n"); - /* Allow multiple threads to access Xlib */ - if (XInitThreads() == 0) { - ErrorF("winClipboardProc - XInitThreads failed.\n"); - goto winClipboardProc_Exit; - } - - /* See if X supports the current locale */ - if (XSupportsLocale() == False) { - ErrorF("winClipboardProc - Warning: Locale not supported by X.\n"); - } + g_fpAddClipboardFormatListener = (ADDCLIPBOARDFORMATLISTENERPROC)GetProcAddress(GetModuleHandle("user32"),"AddClipboardFormatListener"); + g_fpRemoveClipboardFormatListener = (REMOVECLIPBOARDFORMATLISTENERPROC)GetProcAddress(GetModuleHandle("user32"),"RemoveClipboardFormatListener"); + g_fHasModernClipboardApi = g_fpAddClipboardFormatListener && g_fpRemoveClipboardFormatListener; + ErrorF("OS maintains clipboard viewer chain: %s\n", g_fHasModernClipboardApi ? "yes" : "no"); g_winClipboardProcThread = pthread_self(); @@ -165,7 +164,7 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay) "successfully opened the display.\n"); /* Get our connection number */ - iConnectionNumber = ConnectionNumber(pDisplay); + iConnectionNumber = XConnectionNumber(pDisplay); #ifdef HAS_DEVWINDOWS /* Open a file descriptor for the windows message queue */ @@ -193,12 +192,12 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay) /* Create a messaging window */ iWindow = XCreateSimpleWindow(pDisplay, - DefaultRootWindow(pDisplay), + XDefaultRootWindow(pDisplay), 1, 1, 500, 500, 0, - BlackPixel(pDisplay, 0), - BlackPixel(pDisplay, 0)); + XBlackPixel(pDisplay, 0), + XBlackPixel(pDisplay, 0)); if (iWindow == 0) { ErrorF("winClipboardProc - Could not create an X window.\n"); goto winClipboardProc_Done; @@ -289,6 +288,8 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay) tvTimeout.tv_usec = 100; #endif + winDebug("winClipboardProc - Waiting in select\n"); + /* Wait for a Windows event or an X event */ iReturn = select(iMaxDescriptor, /* Highest fds number */ &fdsRead, /* Read mask */ @@ -320,6 +321,8 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay) break; } + winDebug("winClipboardProc - select returned %d\n", iReturn); + if (FD_ISSET(iConnectionNumber, &fdsRead)) { winDebug ("winClipboardProc - X connection ready, pumping X event queue\n"); @@ -344,7 +347,6 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay) #endif } - winClipboardProc_Exit: /* broke out of while loop on a shutdown message */ fShutdown = TRUE; @@ -382,7 +384,7 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay) XSync(pDisplay, TRUE); /* Select event types to watch */ - XSelectInput(pDisplay, DefaultRootWindow(pDisplay), None); + XSelectInput(pDisplay, XDefaultRootWindow(pDisplay), None); /* Close our X display */ if (pDisplay) { diff --git a/hw/xwin/winclipboard/wndproc.c b/hw/xwin/winclipboard/wndproc.c index 1ea5bc6b7..a3a512ff7 100644 --- a/hw/xwin/winclipboard/wndproc.c +++ b/hw/xwin/winclipboard/wndproc.c @@ -45,6 +45,7 @@ #include <sys/types.h> #include <sys/time.h> +#include <sys/select.h> #include <limits.h> #include <X11/Xatom.h> @@ -58,6 +59,9 @@ #define WIN_POLL_TIMEOUT 1 +#ifndef WM_CLIPBOARDUPDATE +#define WM_CLIPBOARDUPDATE 0x031D +#endif /* * Process X events up to specified timeout @@ -76,7 +80,7 @@ winProcessXEventsTimeout(HWND hwnd, Window iWindow, Display * pDisplay, iTimeoutSec); /* Get our connection number */ - iConnNumber = ConnectionNumber(pDisplay); + iConnNumber = XConnectionNumber(pDisplay); /* Loop for X events */ while (1) { @@ -104,7 +108,7 @@ winProcessXEventsTimeout(HWND hwnd, Window iWindow, Display * pDisplay, remainingTime = dwStopTime - GetTickCount(); tv.tv_sec = remainingTime / 1000; tv.tv_usec = (remainingTime % 1000) * 1000; - winDebug("winProcessXEventsTimeout () - %d milliseconds left\n", + winDebug("winProcessXEventsTimeout () - %ld milliseconds left\n", remainingTime); /* Break out if no time left */ @@ -145,14 +149,27 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) static ClipboardAtoms *atoms; static Bool fRunning; +#if CYGDEBUG + winDebugWin32Message("winClipboardWindowProc", hwnd, message, wParam, + lParam); +#endif + /* Branch on message type */ switch (message) { case WM_DESTROY: { winDebug("winClipboardWindowProc - WM_DESTROY\n"); - /* Remove ourselves from the clipboard chain */ - ChangeClipboardChain(hwnd, s_hwndNextViewer); + if (g_fHasModernClipboardApi) + { + /* Remove clipboard listener */ + g_fpRemoveClipboardFormatListener(hwnd); + } + else + { + /* Remove ourselves from the clipboard chain */ + ChangeClipboardChain(hwnd, s_hwndNextViewer); + } s_hwndNextViewer = NULL; } @@ -168,8 +185,6 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) case WM_CREATE: { - HWND first, next; - DWORD error_code = 0; ClipboardWindowCreationParams *cwcp = (ClipboardWindowCreationParams *)((CREATESTRUCT *)lParam)->lpCreateParams; winDebug("winClipboardWindowProc - WM_CREATE\n"); @@ -179,24 +194,34 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) atoms = cwcp->atoms; fRunning = TRUE; - first = GetClipboardViewer(); /* Get handle to first viewer in chain. */ - if (first == hwnd) - return 0; /* Make sure it's not us! */ - /* Add ourselves to the clipboard viewer chain */ - next = SetClipboardViewer(hwnd); - error_code = GetLastError(); - if (SUCCEEDED(error_code) && (next == first)) /* SetClipboardViewer must have succeeded, and the handle */ - s_hwndNextViewer = next; /* it returned must have been the first window in the chain */ + if (g_fHasModernClipboardApi) + { + g_fpAddClipboardFormatListener(hwnd); + } else - s_fCBCInitialized = FALSE; + { + HWND first, next; + DWORD error_code = 0; + + first = GetClipboardViewer(); /* Get handle to first viewer in chain. */ + if (first == hwnd) + return 0; /* Make sure it's not us! */ + /* Add ourselves to the clipboard viewer chain */ + next = SetClipboardViewer(hwnd); + error_code = GetLastError(); + if (SUCCEEDED(error_code) && (next == first)) /* SetClipboardViewer must have succeeded, and the handle */ + s_hwndNextViewer = next; /* it returned must have been the first window in the chain */ + else + s_fCBCInitialized = FALSE; + } } return 0; case WM_CHANGECBCHAIN: { winDebug("winClipboardWindowProc - WM_CHANGECBCHAIN: wParam(%x) " - "lParam(%x) s_hwndNextViewer(%x)\n", - wParam, lParam, s_hwndNextViewer); + "lParam(%x) s_hwndNextViewer(%p)\n", + (int)wParam, (int)lParam, s_hwndNextViewer); if ((HWND) wParam == s_hwndNextViewer) { s_hwndNextViewer = (HWND) lParam; @@ -233,10 +258,15 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) winDebug("winClipboardWindowProc - WM_WM_REINIT: Enter\n"); + if (g_fHasModernClipboardApi) + { + return 0; + } + first = GetClipboardViewer(); /* Get handle to first viewer in chain. */ if (first == hwnd) return 0; /* Make sure it's not us! */ - winDebug(" WM_WM_REINIT: Replacing us(%x) with %x at head " + winDebug(" WM_WM_REINIT: Replacing us(%p) with %p at head " "of chain\n", hwnd, s_hwndNextViewer); s_fCBCInitialized = FALSE; ChangeClipboardChain(hwnd, s_hwndNextViewer); @@ -257,38 +287,45 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) return 0; case WM_DRAWCLIPBOARD: + case WM_CLIPBOARDUPDATE: { static Bool s_fProcessingDrawClipboard = FALSE; int iReturn; - winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Enter\n"); + if (message == WM_DRAWCLIPBOARD) + winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Enter\n"); + else + winDebug("winClipboardWindowProc - WM_CLIPBOARDUPDATE: Enter\n"); - /* - * We've occasionally seen a loop in the clipboard chain. - * Try and fix it on the first hint of recursion. - */ - if (!s_fProcessingDrawClipboard) { - s_fProcessingDrawClipboard = TRUE; - } - else { - /* Attempt to break the nesting by getting out of the chain, twice?, and then fix and bail */ - s_fCBCInitialized = FALSE; - ChangeClipboardChain(hwnd, s_hwndNextViewer); - winFixClipboardChain(); - ErrorF("winClipboardWindowProc - WM_DRAWCLIPBOARD - " - "Nested calls detected. Re-initing.\n"); - winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n"); - s_fProcessingDrawClipboard = FALSE; - return 0; - } + if (!g_fHasModernClipboardApi) + { + /* + * We've occasionally seen a loop in the clipboard chain. + * Try and fix it on the first hint of recursion. + */ + if (!s_fProcessingDrawClipboard) { + s_fProcessingDrawClipboard = TRUE; + } + else { + /* Attempt to break the nesting by getting out of the chain, twice?, and then fix and bail */ + s_fCBCInitialized = FALSE; + ChangeClipboardChain(hwnd, s_hwndNextViewer); + winFixClipboardChain(); + ErrorF("winClipboardWindowProc - WM_DRAWCLIPBOARD - " + "Nested calls detected. Re-initing.\n"); + winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n"); + s_fProcessingDrawClipboard = FALSE; + return 0; + } - /* Bail on first message */ - if (!s_fCBCInitialized) { - s_fCBCInitialized = TRUE; - s_fProcessingDrawClipboard = FALSE; - winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n"); - return 0; - } + /* Bail on first message */ + if (!s_fCBCInitialized) { + s_fCBCInitialized = TRUE; + s_fProcessingDrawClipboard = FALSE; + winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n"); + return 0; + } + } /* * NOTE: We cannot bail out when NULL == GetClipboardOwner () @@ -326,6 +363,36 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) "Clipboard does not contain CF_TEXT nor " "CF_UNICODETEXT.\n"); + winDebug("winClipboardWindowProc: %d formats\n", + CountClipboardFormats()); + + if (OpenClipboard(hwnd)) { + unsigned int format = 0; + + do { + format = EnumClipboardFormats(format); + if (GetLastError() != ERROR_SUCCESS) { + winDebug + ("winClipboardWindowProc: EnumClipboardFormats failed %x\n", + GetLastError()); + } + if (format > 0xc000) { + char buff[256]; + + GetClipboardFormatName(format, buff, 256); + winDebug("winClipboardWindowProc: %d %s\n", format, + buff); + } + else if (format > 0) + winDebug("winClipboardWindowProc: %d\n", format); + } while (format != 0); + CloseClipboard(); + } + else { + winDebug + ("WindowProc: could not open clipboard to enumerate formats\n"); + } + /* * We need to make sure that the X Server has processed * previous XSetSelectionOwner messages. @@ -338,7 +405,7 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) iReturn = XGetSelectionOwner(pDisplay, XA_PRIMARY); if (iReturn == iWindow) { winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - " - "PRIMARY selection is owned by us.\n"); + "PRIMARY selection is owned by us, releasing\n"); XSetSelectionOwner(pDisplay, XA_PRIMARY, None, CurrentTime); } else if (BadWindow == iReturn || BadAtom == iReturn) @@ -441,7 +508,7 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) int best_target = 0; winDebug("winClipboardWindowProc - WM_RENDERFORMAT %d - Hello.\n", - wParam); + (int)wParam); /* Flag whether to convert to Unicode or not */ fConvertToUnicode = (CF_UNICODETEXT == wParam); @@ -472,7 +539,7 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) if (WIN_XEVENTS_NOTIFY_TARGETS != iReturn) { ErrorF - ("winClipboardWindowProc - timed out waiting for WIN_XEVENTS_NOTIFY_TARGETS\n"); + ("winClipboardWindowProc - failed waiting for WIN_XEVENTS_NOTIFY_TARGETS\n"); goto fake_paste; } diff --git a/hw/xwin/winclipboard/xevents.c b/hw/xwin/winclipboard/xevents.c index 835195b52..be01b76c5 100644 --- a/hw/xwin/winclipboard/xevents.c +++ b/hw/xwin/winclipboard/xevents.c @@ -78,6 +78,18 @@ static const char *szSelectionNames[CLIP_NUM_SELECTIONS] = static unsigned int lastOwnedSelectionIndex = CLIP_OWN_NONE; +static const char * +GetWindowName(HWND hWnd) +{ + static char *pBuf = NULL; + int len = GetWindowTextLength(hWnd); + len++; + pBuf = realloc(pBuf, len + 1); + GetWindowText(hWnd, pBuf, len); + pBuf[len] = 0; + return pBuf; +} + static void MonitorSelection(XFixesSelectionNotifyEvent * e, unsigned int i) { @@ -107,7 +119,7 @@ MonitorSelection(XFixesSelectionNotifyEvent * e, unsigned int i) /* Save new selection owner or None */ s_iOwners[i] = e->owner; - winDebug("MonitorSelection - %s - Now owned by XID %x\n", + winDebug("MonitorSelection - %s - Now owned by XID %lx\n", szSelectionNames[i], e->owner); } @@ -117,6 +129,8 @@ winClipboardGetLastOwnedSelectionAtom(ClipboardAtoms *atoms) if (lastOwnedSelectionIndex == CLIP_OWN_NONE) return None; + winDebug("GetLastOwnedSelectionAtom: selection %s owned by XID %lx\n", szSelectionNames[lastOwnedSelectionIndex], s_iOwners[lastOwnedSelectionIndex]); + if (lastOwnedSelectionIndex == CLIP_OWN_PRIMARY) return XA_PRIMARY; @@ -172,7 +186,7 @@ winClipboardSelectionNotifyTargets(HWND hwnd, Window iWindow, Display *pDisplay, Atom atom = prop[i]; char *pszAtomName = XGetAtomName(pDisplay, atom); data->targetList[i] = atom; - winDebug("winClipboardFlushXEvents - SelectionNotify - target[%d] %d = %s\n", i, atom, pszAtomName); + winDebug("winClipboardFlushXEvents - SelectionNotify - target[%d] %ld = %s\n", i, atom, pszAtomName); XFree(pszAtomName); } @@ -231,12 +245,14 @@ winClipboardFlushXEvents(HWND hwnd, { char *pszAtomName = NULL; - winDebug("SelectionRequest - target %d\n", - event.xselectionrequest.target); + pszAtomName = XGetAtomName(pDisplay, + event.xselectionrequest.selection); + winDebug("winClipboardFlushXEvents - SelectionRequest - Selection %ld = %s\n", event.xselectionrequest.selection, pszAtomName); + XFree(pszAtomName); pszAtomName = XGetAtomName(pDisplay, event.xselectionrequest.target); - winDebug("SelectionRequest - Target atom name %s\n", pszAtomName); + winDebug("winClipboardFlushXEvents - SelectionRequest - Target %ld = %s\n", event.xselectionrequest.target, pszAtomName); XFree(pszAtomName); pszAtomName = NULL; } @@ -258,6 +274,7 @@ winClipboardFlushXEvents(HWND hwnd, atomUTF8String, XA_STRING }; + winDebug("winClipboardFlushXEvents - SelectionRequest - populating targets\n"); /* Try to change the property */ iReturn = XChangeProperty(pDisplay, @@ -309,7 +326,7 @@ winClipboardFlushXEvents(HWND hwnd, /* Access the clipboard */ if (!OpenClipboard(hwnd)) { ErrorF("winClipboardFlushXEvents - SelectionRequest - " - "OpenClipboard () failed: %08lx\n", GetLastError()); + "OpenClipboard () failed: %08x owner %p '%s'\n", (unsigned int)GetLastError(), GetClipboardOwner(), GetWindowName(GetClipboardOwner())); /* Abort */ fAbort = TRUE; @@ -368,8 +385,28 @@ winClipboardFlushXEvents(HWND hwnd, hGlobal = GetClipboardData(CF_TEXT); } if (!hGlobal) { + unsigned int format = 0; + ErrorF("winClipboardFlushXEvents - SelectionRequest - " - "GetClipboardData () failed: %08lx\n", GetLastError()); + "GetClipboardData () failed: %08x\n", (unsigned int)GetLastError()); + + do { + format = EnumClipboardFormats(format); + if (GetLastError() != ERROR_SUCCESS) { + winDebug + ("winClipboardFlushXEvents - SelectionRequest - EnumClipboardFormats failed %x\n", + GetLastError()); + } + if (format > 0xc000) { + char buff[256]; + + GetClipboardFormatName(format, buff, 256); + winDebug("winClipboardFlushXEvents - SelectionRequest - %d %s\n", format, + buff); + } + else if (format > 0) + winDebug("winClipboardFlushXEvents - SelectionRequest - %d\n", format); + } while (format != 0); /* Abort */ fAbort = TRUE; @@ -502,6 +539,7 @@ winClipboardFlushXEvents(HWND hwnd, * client when we abort. */ if (fAbort) { + winDebug("winClipboardFlushXEvents - SelectionRequest - aborting\n"); /* Setup selection notify event */ eventSelection.type = SelectionNotify; eventSelection.send_event = True; @@ -560,9 +598,11 @@ winClipboardFlushXEvents(HWND hwnd, not be performed or server errors prevented the conversion data being returned */ if (event.xselection.property == None) { + char *pszAtomName = XGetAtomName(pDisplay, event.xselection.target); ErrorF("winClipboardFlushXEvents - SelectionNotify - " - "Conversion to format %d refused.\n", - event.xselection.target); + "Conversion to format %s %ld refused.\n", + pszAtomName, event.xselection.target); + XFree(pszAtomName); return WIN_XEVENTS_FAILED; } @@ -591,10 +631,11 @@ winClipboardFlushXEvents(HWND hwnd, { char *pszAtomName = NULL; - winDebug("SelectionNotify - returned data %d left %d\n", + winDebug("SelectionNotify - returned data %lu left %lu\n", xtpText.nitems, ulReturnBytesLeft); pszAtomName = XGetAtomName(pDisplay, xtpText.encoding); - winDebug("Notify atom name %s\n", pszAtomName); + winDebug("SelectionNotify - encoding atom name %s\n", + pszAtomName); XFree(pszAtomName); pszAtomName = NULL; } @@ -706,7 +747,7 @@ winClipboardFlushXEvents(HWND hwnd, /* Check that global memory was allocated */ if (!hGlobal) { ErrorF("winClipboardFlushXEvents - SelectionNotify " - "GlobalAlloc failed, aborting: %ld\n", GetLastError()); + "GlobalAlloc failed, aborting: %08x\n", (unsigned int)GetLastError()); /* Abort */ fAbort = TRUE; @@ -774,10 +815,19 @@ winClipboardFlushXEvents(HWND hwnd, return WIN_XEVENTS_NOTIFY_DATA; case SelectionClear: - winDebug("SelectionClear - doing nothing\n"); + winDebug("winClipboardFlushXEvents - SelectionClear - doing nothing\n"); break; case PropertyNotify: + { + char *pszAtomName; + + pszAtomName = XGetAtomName(pDisplay, event.xproperty.atom); + winDebug("winClipboardFlushXEvents - PropertyNotify - ATOM: %s %s\n", + pszAtomName, + event.xproperty.state == PropertyNewValue ? "PropertyNewValue" : "PropertyDelete"); + XFree(pszAtomName); + } break; case MappingNotify: @@ -827,8 +877,8 @@ winClipboardFlushXEvents(HWND hwnd, /* Access the Windows clipboard */ if (!OpenClipboard(hwnd)) { - ErrorF("winClipboardFlushXEvents - OpenClipboard () failed: %08x\n", - (int) GetLastError()); + ErrorF("winClipboardFlushXEvents - OpenClipboard () failed: %08x Owner %p '%s'\n", + (int) GetLastError(), GetClipboardOwner(), GetWindowName(GetClipboardOwner())); break; } diff --git a/hw/xwin/wincmap.c b/hw/xwin/wincmap.c index 1bdc7df70..318bfac11 100644 --- a/hw/xwin/wincmap.c +++ b/hw/xwin/wincmap.c @@ -515,7 +515,7 @@ winCreateDefColormap(ScreenPtr pScreen) */ #if CYGDEBUG - winDebug("winCreateDefColormap - defColormap: %d\n", pScreen->defColormap); + winDebug("winCreateDefColormap - defColormap: %lu\n", pScreen->defColormap); #endif /* Allocate an X colormap, owned by client 0 */ diff --git a/hw/xwin/winconfig.c b/hw/xwin/winconfig.c index 321dfeed2..db1454182 100644 --- a/hw/xwin/winconfig.c +++ b/hw/xwin/winconfig.c @@ -70,6 +70,7 @@ WinCmdlineRec g_cmdline = { #ifdef XWIN_XF86CONFIG NULL, /* keyboard */ #endif + FALSE, /* customDPI */ NULL, /* xkbRules */ NULL, /* xkbModel */ NULL, /* xkbLayout */ @@ -224,7 +225,8 @@ winConfigKeyboard(DeviceIntPtr pDevice) { char layoutName[KL_NAMELENGTH]; unsigned char layoutFriendlyName[256]; - static unsigned int layoutNum = 0; + unsigned int layoutNum = 0; + unsigned int deviceIdentifier = 0; int keyboardType; #ifdef XWIN_XF86CONFIG @@ -263,7 +265,7 @@ winConfigKeyboard(DeviceIntPtr pDevice) break; } g_winInfo.keyboard.rate = (kbd_speed > 0) ? kbd_speed : 1; - winMsgVerb(X_PROBED, 1, "Setting autorepeat to delay=%d, rate=%d\n", + winMsg(X_PROBED, "Setting autorepeat to delay=%ld, rate=%ld\n", g_winInfo.keyboard.delay, g_winInfo.keyboard.rate); } } @@ -272,15 +274,10 @@ winConfigKeyboard(DeviceIntPtr pDevice) if (keyboardType > 0 && GetKeyboardLayoutName(layoutName)) { WinKBLayoutPtr pLayout; Bool bfound = FALSE; + int pass; - if (!layoutNum) - layoutNum = strtoul(layoutName, (char **) NULL, 16); + layoutNum = strtoul(layoutName, (char **) NULL, 16); if ((layoutNum & 0xffff) == 0x411) { - /* The japanese layouts know a lot of different IMEs which all have - different layout numbers set. Map them to a single entry. - Same might apply for chinese, korean and other symbol languages - too */ - layoutNum = (layoutNum & 0xffff); if (keyboardType == 7) { /* Japanese layouts have problems with key event messages such as the lack of WM_KEYUP for Caps Lock key. @@ -318,31 +315,47 @@ winConfigKeyboard(DeviceIntPtr pDevice) "Windows keyboard layout: \"%s\" (%08x) \"%s\", type %d\n", layoutName, layoutNum, layoutFriendlyName, keyboardType); - for (pLayout = winKBLayouts; pLayout->winlayout != -1; pLayout++) { - if (pLayout->winlayout != layoutNum) - continue; - if (pLayout->winkbtype > 0 && pLayout->winkbtype != keyboardType) - continue; - - bfound = TRUE; - winMsg(X_PROBED, - "Found matching XKB configuration \"%s\"\n", - pLayout->layoutname); - - winMsg(X_PROBED, - "Model = \"%s\" Layout = \"%s\"" - " Variant = \"%s\" Options = \"%s\"\n", - pLayout->xkbmodel ? pLayout->xkbmodel : "none", - pLayout->xkblayout ? pLayout->xkblayout : "none", - pLayout->xkbvariant ? pLayout->xkbvariant : "none", - pLayout->xkboptions ? pLayout->xkboptions : "none"); + deviceIdentifier = layoutNum >> 16; + for (pass = 0; pass < 2; pass++) { + /* If we didn't find an exact match for the input locale identifer, + try to find an match on the language identifier part only */ + if (pass == 1) + layoutNum = (layoutNum & 0xffff); + + for (pLayout = winKBLayouts; pLayout->winlayout != -1; pLayout++) { + if (pLayout->winlayout != layoutNum) + continue; + if (pLayout->winkbtype > 0 && pLayout->winkbtype != keyboardType) + continue; + + bfound = TRUE; + winMsg(X_PROBED, + "Found matching XKB configuration \"%s\"\n", + pLayout->layoutname); + + winMsg(X_PROBED, + "Model = \"%s\" Layout = \"%s\"" + " Variant = \"%s\" Options = \"%s\"\n", + pLayout->xkbmodel ? pLayout->xkbmodel : "none", + pLayout->xkblayout ? pLayout->xkblayout : "none", + pLayout->xkbvariant ? pLayout->xkbvariant : "none", + pLayout->xkboptions ? pLayout->xkboptions : "none"); + + g_winInfo.xkb.model = pLayout->xkbmodel; + g_winInfo.xkb.layout = pLayout->xkblayout; + g_winInfo.xkb.variant = pLayout->xkbvariant; + g_winInfo.xkb.options = pLayout->xkboptions; + + if (deviceIdentifier == 0xa000) { + winMsg(X_PROBED, "Windows keyboard layout device identifier indicates Macintosh, setting Model = \"macintosh\""); + g_winInfo.xkb.model = "macintosh"; + } - g_winInfo.xkb.model = pLayout->xkbmodel; - g_winInfo.xkb.layout = pLayout->xkblayout; - g_winInfo.xkb.variant = pLayout->xkbvariant; - g_winInfo.xkb.options = pLayout->xkboptions; + break; + } - break; + if (bfound) + break; } if (!bfound) { diff --git a/hw/xwin/winconfig.h b/hw/xwin/winconfig.h index f079368c7..2edaf4df2 100644 --- a/hw/xwin/winconfig.h +++ b/hw/xwin/winconfig.h @@ -159,6 +159,7 @@ typedef struct { #ifdef XWIN_XF86CONFIG char *keyboard; #endif + Bool customDPI; char *xkbRules; char *xkbModel; char *xkbLayout; @@ -199,7 +200,7 @@ typedef union { unsigned long num; char *str; double realnum; - Bool bool; + Bool bool_; OptFrequency freq; } ValueUnion; diff --git a/hw/xwin/wincreatewnd.c b/hw/xwin/wincreatewnd.c index 6c5b21dfa..c2851ada1 100644 --- a/hw/xwin/wincreatewnd.c +++ b/hw/xwin/wincreatewnd.c @@ -171,7 +171,7 @@ winCreateBoundingWindowWindowed(ScreenPtr pScreen) fForceShowWindow = TRUE; } dwWindowStyle |= WS_CAPTION; - if (pScreenInfo->iResizeMode != notAllowed) + if (pScreenInfo->iResizeMode != resizeNotAllowed) dwWindowStyle |= WS_THICKFRAME | WS_MAXIMIZEBOX; } else @@ -226,7 +226,7 @@ winCreateBoundingWindowWindowed(ScreenPtr pScreen) ) && (pScreenInfo->iResizeMode == resizeWithScrollbars)) { /* We cannot have scrollbars if we do not have a window border */ - pScreenInfo->iResizeMode = notAllowed; + pScreenInfo->iResizeMode = resizeNotAllowed; } /* Did the user specify a height and width? */ @@ -253,7 +253,7 @@ winCreateBoundingWindowWindowed(ScreenPtr pScreen) #endif /* Are we resizable */ - if (pScreenInfo->iResizeMode != notAllowed) { + if (pScreenInfo->iResizeMode != resizeNotAllowed) { #if CYGDEBUG winDebug ("winCreateBoundingWindowWindowed - Window is resizable\n"); @@ -357,7 +357,7 @@ winCreateBoundingWindowWindowed(ScreenPtr pScreen) } winDebug("winCreateBoundingWindowWindowed - WindowClient " - "w %ld h %ld r %ld l %ld b %ld t %ld\n", + "w %d h %d r %d l %d b %d t %d\n", rcClient.right - rcClient.left, rcClient.bottom - rcClient.top, rcClient.right, rcClient.left, rcClient.bottom, rcClient.top); diff --git a/hw/xwin/wincursor.c b/hw/xwin/wincursor.c index bddd6b7ed..285da3b6f 100644 --- a/hw/xwin/wincursor.c +++ b/hw/xwin/wincursor.c @@ -34,14 +34,14 @@ #ifdef HAVE_XWIN_CONFIG_H #include <xwin-config.h> #endif + #include "win.h" #include "winmsg.h" #include <cursorstr.h> #include <mipointrst.h> #include <servermd.h> #include "misc.h" - -#define BRIGHTNESS(x) (x##Red * 0.299 + x##Green * 0.587 + x##Blue * 0.114) +#include "wmutil/cursor_convert.h" #if 0 #define WIN_DEBUG_MSG winDebug @@ -128,296 +128,30 @@ winCrossScreen(ScreenPtr pScreen, Bool fEntering) { } -static unsigned char -reverse(unsigned char c) -{ - int i; - unsigned char ret = 0; - - for (i = 0; i < 8; ++i) { - ret |= ((c >> i) & 1) << (7 - i); - } - return ret; -} - /* * Convert X cursor to Windows cursor - * FIXME: Perhaps there are more smart code */ static HCURSOR winLoadCursor(ScreenPtr pScreen, CursorPtr pCursor, int screen) { - winScreenPriv(pScreen); - HCURSOR hCursor = NULL; - unsigned char *pAnd; - unsigned char *pXor; - int nCX, nCY; - int nBytes; - double dForeY, dBackY; - BOOL fReverse; - HBITMAP hAnd, hXor; - ICONINFO ii; - unsigned char *pCur; - unsigned char bit; - HDC hDC; - BITMAPV4HEADER bi; - BITMAPINFO *pbmi; - uint32_t *lpBits; - - WIN_DEBUG_MSG("winLoadCursor: Win32: %dx%d X11: %dx%d hotspot: %d,%d\n", - pScreenPriv->cursor.sm_cx, pScreenPriv->cursor.sm_cy, - pCursor->bits->width, pCursor->bits->height, - pCursor->bits->xhot, pCursor->bits->yhot); - - /* We can use only White and Black, so calc brightness of color - * Also check if the cursor is inverted */ - dForeY = BRIGHTNESS(pCursor->fore); - dBackY = BRIGHTNESS(pCursor->back); - fReverse = dForeY < dBackY; - - /* Check wether the X11 cursor is bigger than the win32 cursor */ - if (pScreenPriv->cursor.sm_cx < pCursor->bits->width || - pScreenPriv->cursor.sm_cy < pCursor->bits->height) { - winErrorFVerb(3, - "winLoadCursor - Windows requires %dx%d cursor but X requires %dx%d\n", - pScreenPriv->cursor.sm_cx, pScreenPriv->cursor.sm_cy, - pCursor->bits->width, pCursor->bits->height); - } - - /* Get the number of bytes required to store the whole cursor image - * This is roughly (sm_cx * sm_cy) / 8 - * round up to 8 pixel boundary so we can convert whole bytes */ - nBytes = - bits_to_bytes(pScreenPriv->cursor.sm_cx) * pScreenPriv->cursor.sm_cy; - - /* Get the effective width and height */ - nCX = min(pScreenPriv->cursor.sm_cx, pCursor->bits->width); - nCY = min(pScreenPriv->cursor.sm_cy, pCursor->bits->height); - - /* Allocate memory for the bitmaps */ - pAnd = malloc(nBytes); - memset(pAnd, 0xFF, nBytes); - pXor = calloc(1, nBytes); - - /* Convert the X11 bitmap to a win32 bitmap - * The first is for an empty mask */ - if (pCursor->bits->emptyMask) { - int x, y, xmax = bits_to_bytes(nCX); - - for (y = 0; y < nCY; ++y) - for (x = 0; x < xmax; ++x) { - int nWinPix = bits_to_bytes(pScreenPriv->cursor.sm_cx) * y + x; - int nXPix = BitmapBytePad(pCursor->bits->width) * y + x; - - pAnd[nWinPix] = 0; - if (fReverse) - pXor[nWinPix] = reverse(~pCursor->bits->source[nXPix]); - else - pXor[nWinPix] = reverse(pCursor->bits->source[nXPix]); - } - } - else { - int x, y, xmax = bits_to_bytes(nCX); - - for (y = 0; y < nCY; ++y) - for (x = 0; x < xmax; ++x) { - int nWinPix = bits_to_bytes(pScreenPriv->cursor.sm_cx) * y + x; - int nXPix = BitmapBytePad(pCursor->bits->width) * y + x; - - unsigned char mask = pCursor->bits->mask[nXPix]; - - pAnd[nWinPix] = reverse(~mask); - if (fReverse) - pXor[nWinPix] = - reverse(~pCursor->bits->source[nXPix] & mask); - else - pXor[nWinPix] = - reverse(pCursor->bits->source[nXPix] & mask); - } - } - - /* prepare the pointers */ - hCursor = NULL; - lpBits = NULL; - - /* We have a truecolor alpha-blended cursor and can use it! */ - if (pCursor->bits->argb) { - WIN_DEBUG_MSG("winLoadCursor: Trying truecolor alphablended cursor\n"); - memset(&bi, 0, sizeof(BITMAPV4HEADER)); - bi.bV4Size = sizeof(BITMAPV4HEADER); - bi.bV4Width = pScreenPriv->cursor.sm_cx; - bi.bV4Height = -(pScreenPriv->cursor.sm_cy); /* right-side up */ - bi.bV4Planes = 1; - bi.bV4BitCount = 32; - bi.bV4V4Compression = BI_BITFIELDS; - bi.bV4RedMask = 0x00FF0000; - bi.bV4GreenMask = 0x0000FF00; - bi.bV4BlueMask = 0x000000FF; - bi.bV4AlphaMask = 0xFF000000; - - lpBits = calloc(pScreenPriv->cursor.sm_cx * pScreenPriv->cursor.sm_cy, - sizeof(uint32_t)); - - if (lpBits) { - int y; - for (y = 0; y < nCY; y++) { - void *src, *dst; - src = &(pCursor->bits->argb[y * pCursor->bits->width]); - dst = &(lpBits[y * pScreenPriv->cursor.sm_cx]); - memcpy(dst, src, 4 * nCX); - } - } - } /* End if-truecolor-icon */ - - if (!lpBits) { - RGBQUAD *pbmiColors; - /* Bicolor, use a palettized DIB */ - WIN_DEBUG_MSG("winLoadCursor: Trying two color cursor\n"); - pbmi = (BITMAPINFO *) &bi; - pbmiColors = &(pbmi->bmiColors[0]); - - memset(pbmi, 0, sizeof(BITMAPINFOHEADER)); - pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - pbmi->bmiHeader.biWidth = pScreenPriv->cursor.sm_cx; - pbmi->bmiHeader.biHeight = -abs(pScreenPriv->cursor.sm_cy); /* right-side up */ - pbmi->bmiHeader.biPlanes = 1; - pbmi->bmiHeader.biBitCount = 8; - pbmi->bmiHeader.biCompression = BI_RGB; - pbmi->bmiHeader.biSizeImage = 0; - pbmi->bmiHeader.biClrUsed = 3; - pbmi->bmiHeader.biClrImportant = 3; - - pbmiColors[0].rgbRed = 0; /* Empty */ - pbmiColors[0].rgbGreen = 0; - pbmiColors[0].rgbBlue = 0; - pbmiColors[0].rgbReserved = 0; - pbmiColors[1].rgbRed = pCursor->backRed >> 8; /* Background */ - pbmiColors[1].rgbGreen = pCursor->backGreen >> 8; - pbmiColors[1].rgbBlue = pCursor->backBlue >> 8; - pbmiColors[1].rgbReserved = 0; - pbmiColors[2].rgbRed = pCursor->foreRed >> 8; /* Foreground */ - pbmiColors[2].rgbGreen = pCursor->foreGreen >> 8; - pbmiColors[2].rgbBlue = pCursor->foreBlue >> 8; - pbmiColors[2].rgbReserved = 0; - - lpBits = calloc(pScreenPriv->cursor.sm_cx * pScreenPriv->cursor.sm_cy, 1); - - pCur = (unsigned char *) lpBits; - if (lpBits) { - int x, y; - for (y = 0; y < pScreenPriv->cursor.sm_cy; y++) { - for (x = 0; x < pScreenPriv->cursor.sm_cx; x++) { - if (x >= nCX || y >= nCY) /* Outside of X11 icon bounds */ - (*pCur++) = 0; - else { /* Within X11 icon bounds */ - - int nWinPix = - bits_to_bytes(pScreenPriv->cursor.sm_cx) * y + - (x / 8); - - bit = pAnd[nWinPix]; - bit = bit & (1 << (7 - (x & 7))); - if (!bit) { /* Within the cursor mask? */ - int nXPix = - BitmapBytePad(pCursor->bits->width) * y + - (x / 8); - bit = - ~reverse(~pCursor->bits-> - source[nXPix] & pCursor->bits-> - mask[nXPix]); - bit = bit & (1 << (7 - (x & 7))); - if (bit) /* Draw foreground */ - (*pCur++) = 2; - else /* Draw background */ - (*pCur++) = 1; - } - else /* Outside the cursor mask */ - (*pCur++) = 0; - } - } /* end for (x) */ - } /* end for (y) */ - } /* end if (lpbits) */ - } - - /* If one of the previous two methods gave us the bitmap we need, make a cursor */ - if (lpBits) { - WIN_DEBUG_MSG("winLoadCursor: Creating bitmap cursor: hotspot %d,%d\n", - pCursor->bits->xhot, pCursor->bits->yhot); - - hAnd = NULL; - hXor = NULL; - - hAnd = - CreateBitmap(pScreenPriv->cursor.sm_cx, pScreenPriv->cursor.sm_cy, - 1, 1, pAnd); - - hDC = GetDC(NULL); - if (hDC) { - hXor = - CreateCompatibleBitmap(hDC, pScreenPriv->cursor.sm_cx, - pScreenPriv->cursor.sm_cy); - SetDIBits(hDC, hXor, 0, pScreenPriv->cursor.sm_cy, lpBits, - (BITMAPINFO *) &bi, DIB_RGB_COLORS); - ReleaseDC(NULL, hDC); - } - free(lpBits); - - if (hAnd && hXor) { - ii.fIcon = FALSE; - ii.xHotspot = pCursor->bits->xhot; - ii.yHotspot = pCursor->bits->yhot; - ii.hbmMask = hAnd; - ii.hbmColor = hXor; - hCursor = (HCURSOR) CreateIconIndirect(&ii); - - if (hCursor == NULL) - winW32Error(2, "winLoadCursor - CreateIconIndirect failed:"); - else { - if (GetIconInfo(hCursor, &ii)) { - if (ii.fIcon) { - WIN_DEBUG_MSG - ("winLoadCursor: CreateIconIndirect returned no cursor. Trying again.\n"); - - DestroyCursor(hCursor); - - ii.fIcon = FALSE; - ii.xHotspot = pCursor->bits->xhot; - ii.yHotspot = pCursor->bits->yhot; - hCursor = (HCURSOR) CreateIconIndirect(&ii); - - if (hCursor == NULL) - winW32Error(2, - "winLoadCursor - CreateIconIndirect failed:"); - } - /* GetIconInfo creates new bitmaps. Destroy them again */ - if (ii.hbmMask) - DeleteObject(ii.hbmMask); - if (ii.hbmColor) - DeleteObject(ii.hbmColor); - } - } - } - - if (hAnd) - DeleteObject(hAnd); - if (hXor) - DeleteObject(hXor); - } - - if (!hCursor) { - /* We couldn't make a color cursor for this screen, use - black and white instead */ - hCursor = CreateCursor(g_hInstance, - pCursor->bits->xhot, pCursor->bits->yhot, - pScreenPriv->cursor.sm_cx, - pScreenPriv->cursor.sm_cy, pAnd, pXor); - if (hCursor == NULL) - winW32Error(2, "winLoadCursor - CreateCursor failed:"); - } - free(pAnd); - free(pXor); - - return hCursor; + WMUTIL_CURSOR cursor; + + cursor.width = pCursor->bits->width; + cursor.height = pCursor->bits->height; + cursor.xhot = pCursor->bits->xhot; + cursor.yhot = pCursor->bits->yhot; + cursor.argb = (uint32_t *)pCursor->bits->argb; + cursor.source = pCursor->bits->source; + cursor.mask = pCursor->bits->mask; + cursor.emptyMask = pCursor->bits->emptyMask; + cursor.foreRed = pCursor->foreRed; + cursor.foreGreen = pCursor->foreGreen; + cursor.foreBlue = pCursor->foreBlue; + cursor.backRed = pCursor->backRed; + cursor.backGreen = pCursor->backGreen; + cursor.backBlue = pCursor->backBlue; + + return winXCursorToHCURSOR(&cursor); } /* diff --git a/hw/xwin/winengine.c b/hw/xwin/winengine.c index b473b3ac0..55dc0d079 100644 --- a/hw/xwin/winengine.c +++ b/hw/xwin/winengine.c @@ -85,12 +85,6 @@ winDetectSupportedEngines(void) "winDetectSupportedEngines - DirectDraw not installed\n"); return; } - else { - /* We have DirectDraw */ - winErrorFVerb(2, - "winDetectSupportedEngines - DirectDraw installed, allowing ShadowDD\n"); - g_dwEnginesSupported |= WIN_SERVER_SHADOW_DD; - } /* Try to query for DirectDraw4 interface */ ddrval = IDirectDraw_QueryInterface(lpdd, @@ -229,7 +223,7 @@ winSetEngine(ScreenPtr pScreen) return TRUE; } - return TRUE; + return FALSE; } /* diff --git a/hw/xwin/winerror.c b/hw/xwin/winerror.c index 1318b0f36..09b8dda0c 100644 --- a/hw/xwin/winerror.c +++ b/hw/xwin/winerror.c @@ -69,14 +69,20 @@ OsVendorFatalError(const char *f, va_list args) { char errormsg[1024] = ""; - /* Don't give duplicate warning if UseMsg was called */ + /* If we want to silence it, + * detect if we are going to abort due to duplication error */ + if (g_fSilentDupError) { + if ((strcmp(f, "InitOutput - Duplicate invocation on display number: %s. Exiting.\n") == 0) + || (strcmp(f, "Server is already active for display %s\n%s %s\n%s\n") == 0) + || (strcmp(f, "MakeAllCOTSServerListeners: server already running\n") == 0)) { + g_fSilentFatalError = TRUE; + } + } + + /* Don't give warning if it's been silenced */ if (g_fSilentFatalError) return; - if (!g_fLogInited) { - g_fLogInited = TRUE; - g_pszLogFile = LogInit(g_pszLogFile, NULL); - } LogClose(EXIT_ERR_ABORT); /* Format the error message */ diff --git a/hw/xwin/winglobals.c b/hw/xwin/winglobals.c index ad82b83f6..8a699f236 100644 --- a/hw/xwin/winglobals.c +++ b/hw/xwin/winglobals.c @@ -63,13 +63,12 @@ HICON g_hIconX = NULL; HICON g_hSmallIconX = NULL; #ifndef RELOCATE_PROJECTROOT -const char *g_pszLogFile = DEFAULT_LOGDIR "/XWin.%s.log"; +const char *g_pszLogFileFormat = DEFAULT_LOGDIR "/XWin.%s.log"; #else -const char *g_pszLogFile = "XWin.log"; -Bool g_fLogFileChanged = FALSE; +const char *g_pszLogFileFormat = "XWin.%s.log"; #endif +const char *g_pszLogFile = NULL; int g_iLogVerbose = 2; -Bool g_fLogInited = FALSE; char *g_pszCommandLine = NULL; Bool g_fSilentFatalError = FALSE; DWORD g_dwCurrentThreadID = 0; @@ -78,7 +77,7 @@ Bool g_fNoHelpMessageBox = FALSE; Bool g_fSoftwareCursor = FALSE; Bool g_fSilentDupError = FALSE; Bool g_fNativeGl = TRUE; -Bool g_fHostInTitle = FALSE; +Bool g_fHostInTitle = TRUE; pthread_mutex_t g_pmTerminating = PTHREAD_MUTEX_INITIALIZER; #ifdef XWIN_CLIPBOARD diff --git a/hw/xwin/winglobals.h b/hw/xwin/winglobals.h index d7b813dbb..a20f266c2 100644 --- a/hw/xwin/winglobals.h +++ b/hw/xwin/winglobals.h @@ -40,13 +40,10 @@ extern int g_iNumScreens; extern int g_iLastScreen; extern char *g_pszCommandLine; extern Bool g_fSilentFatalError; +extern const char *g_pszLogFileFormat; extern const char *g_pszLogFile; -#ifdef RELOCATE_PROJECTROOT -extern Bool g_fLogFileChanged; -#endif extern int g_iLogVerbose; -extern Bool g_fLogInited; extern Bool g_fAuthEnabled; extern Bool g_fXdmcpEnabled; diff --git a/hw/xwin/winkeybd.c b/hw/xwin/winkeybd.c index 3a75ab268..403157090 100644 --- a/hw/xwin/winkeybd.c +++ b/hw/xwin/winkeybd.c @@ -34,17 +34,24 @@ #ifdef HAVE_XWIN_CONFIG_H #include <xwin-config.h> #endif + #include "win.h" -#include "winkeybd.h" +#include "wmutil/scancodes.h" +#include "wmutil/keyboard.h" #include "winconfig.h" #include "winmsg.h" #include "xkbsrv.h" +#include "dixgrabs.h" /* C does not have a logical XOR operator, so we use a macro instead */ #define LOGICAL_XOR(a,b) ((!(a) && (b)) || ((a) && !(b))) -static Bool g_winKeyState[NUM_KEYCODES]; +#define AltMask Mod1Mask +#define NumLockMask Mod2Mask +#define AltLangMask Mod3Mask +#define KanaMask Mod4Mask +#define ScrollLockMask Mod5Mask /* * Local prototypes @@ -56,68 +63,6 @@ static void static void winKeybdCtrl(DeviceIntPtr pDevice, KeybdCtrl * pCtrl); -/* - * Translate a Windows WM_[SYS]KEY(UP/DOWN) message - * into an ASCII scan code. - * - * We do this ourselves, rather than letting Windows handle it, - * because Windows tends to munge the handling of special keys, - * like AltGr on European keyboards. - */ - -int -winTranslateKey(WPARAM wParam, LPARAM lParam) -{ - int iKeyFixup = g_iKeyMap[wParam * WIN_KEYMAP_COLS + 1]; - int iKeyFixupEx = g_iKeyMap[wParam * WIN_KEYMAP_COLS + 2]; - int iParam = HIWORD(lParam); - int iParamScanCode = LOBYTE(iParam); - int iScanCode; - - winDebug("winTranslateKey: wParam %08x lParam %08x\n", wParam, lParam); - -/* WM_ key messages faked by Vista speech recognition (WSR) don't have a - * scan code. - * - * Vocola 3 (Rick Mohr's supplement to WSR) uses - * System.Windows.Forms.SendKeys.SendWait(), which appears always to give a - * scan code of 1 - */ - if (iParamScanCode <= 1) { - if (VK_PRIOR <= wParam && wParam <= VK_DOWN) - /* Trigger special case table to translate to extended - * keycode, otherwise if num_lock is on, we can get keypad - * numbers instead of navigation keys. */ - iParam |= KF_EXTENDED; - else - iParamScanCode = MapVirtualKeyEx(wParam, - /*MAPVK_VK_TO_VSC */ 0, - GetKeyboardLayout(0)); - } - - /* Branch on special extended, special non-extended, or normal key */ - if ((iParam & KF_EXTENDED) && iKeyFixupEx) - iScanCode = iKeyFixupEx; - else if (iKeyFixup) - iScanCode = iKeyFixup; - else if (wParam == 0 && iParamScanCode == 0x70) - iScanCode = KEY_HKTG; - else - switch (iParamScanCode) { - case 0x70: - iScanCode = KEY_HKTG; - break; - case 0x73: - iScanCode = KEY_BSlash2; - break; - default: - iScanCode = iParamScanCode; - break; - } - - return iScanCode; -} - /* Ring the keyboard bell (system speaker on PCs) */ static void winKeybdBell(int iPercent, DeviceIntPtr pDeviceInt, void *pCtrl, int iClass) @@ -337,209 +282,46 @@ winRestoreModeKeyStates(void) */ } -/* - * Look for the lovely fake Control_L press/release generated by Windows - * when AltGr is pressed/released on a non-U.S. keyboard. - */ - -Bool -winIsFakeCtrl_L(UINT message, WPARAM wParam, LPARAM lParam) -{ - MSG msgNext; - LONG lTime; - Bool fReturn; - - static Bool lastWasControlL = FALSE; - static LONG lastTime; - - /* - * Fake Ctrl_L presses will be followed by an Alt_R press - * with the same timestamp as the Ctrl_L press. - */ - if ((message == WM_KEYDOWN || message == WM_SYSKEYDOWN) - && wParam == VK_CONTROL && (HIWORD(lParam) & KF_EXTENDED) == 0) { - /* Got a Ctrl_L press */ - - /* Get time of current message */ - lTime = GetMessageTime(); - - /* Look for next press message */ - fReturn = PeekMessage(&msgNext, NULL, - WM_KEYDOWN, WM_SYSKEYDOWN, PM_NOREMOVE); - - if (fReturn && msgNext.message != WM_KEYDOWN && - msgNext.message != WM_SYSKEYDOWN) - fReturn = 0; - - if (!fReturn) { - lastWasControlL = TRUE; - lastTime = lTime; - } - else { - lastWasControlL = FALSE; - } - - /* Is next press an Alt_R with the same timestamp? */ - if (fReturn && msgNext.wParam == VK_MENU - && msgNext.time == lTime - && (HIWORD(msgNext.lParam) & KF_EXTENDED)) { - /* - * Next key press is Alt_R with same timestamp as current - * Ctrl_L message. Therefore, this Ctrl_L press is a fake - * event, so discard it. - */ - return TRUE; - } - } - /* - * Sometimes, the Alt_R press message is not yet posted when the - * fake Ctrl_L press message arrives (even though it has the - * same timestamp), so check for an Alt_R press message that has - * arrived since the last Ctrl_L message. - */ - else if ((message == WM_KEYDOWN || message == WM_SYSKEYDOWN) - && wParam == VK_MENU && (HIWORD(lParam) & KF_EXTENDED)) { - /* Got a Alt_R press */ - - if (lastWasControlL) { - lTime = GetMessageTime(); - - if (lastTime == lTime) { - /* Undo the fake Ctrl_L press by sending a fake Ctrl_L release */ - winSendKeyEvent(KEY_LCtrl, FALSE); - } - lastWasControlL = FALSE; - } - } - /* - * Fake Ctrl_L releases will be followed by an Alt_R release - * with the same timestamp as the Ctrl_L release. - */ - else if ((message == WM_KEYUP || message == WM_SYSKEYUP) - && wParam == VK_CONTROL && (HIWORD(lParam) & KF_EXTENDED) == 0) { - /* Got a Ctrl_L release */ - - /* Get time of current message */ - lTime = GetMessageTime(); - - /* Look for next release message */ - fReturn = PeekMessage(&msgNext, NULL, - WM_KEYUP, WM_SYSKEYUP, PM_NOREMOVE); - - if (fReturn && msgNext.message != WM_KEYUP && - msgNext.message != WM_SYSKEYUP) - fReturn = 0; - - lastWasControlL = FALSE; - - /* Is next press an Alt_R with the same timestamp? */ - if (fReturn - && (msgNext.message == WM_KEYUP || msgNext.message == WM_SYSKEYUP) - && msgNext.wParam == VK_MENU - && msgNext.time == lTime - && (HIWORD(msgNext.lParam) & KF_EXTENDED)) { - /* - * Next key release is Alt_R with same timestamp as current - * Ctrl_L message. Therefore, this Ctrl_L release is a fake - * event, so discard it. - */ - return TRUE; - } - } - else { - /* On any other press or release message, we don't have a - potentially fake Ctrl_L to worry about anymore... */ - lastWasControlL = FALSE; - } - - /* Not a fake control left press/release */ - return FALSE; -} - -/* - * Lift any modifier keys that are pressed - */ - void -winKeybdReleaseKeys(void) +winSendKeyEventCallback(DWORD dwKey, bool fDown) { - int i; - #ifdef HAS_DEVWINDOWS /* Verify that the mi input system has been initialized */ if (g_fdMessageQueue == WIN_FD_INVALID) return; #endif - /* Loop through all keys */ - for (i = 0; i < NUM_KEYCODES; ++i) { - /* Pop key if pressed */ - if (g_winKeyState[i]) - winSendKeyEvent(i, FALSE); - - /* Reset pressed flag for keys */ - g_winKeyState[i] = FALSE; - } + QueueKeyboardEvents(g_pwinKeyboard, fDown ? KeyPress : KeyRelease, + dwKey, NULL); } /* - * Take a raw X key code and send an up or down event for it. - * - * Thanks to VNC for inspiration, though it is a simple function. */ - -void -winSendKeyEvent(DWORD dwKey, Bool fDown) -{ - /* - * When alt-tabing between screens we can get phantom key up messages - * Here we only pass them through it we think we should! - */ - if (g_winKeyState[dwKey] == FALSE && fDown == FALSE) - return; - - /* Update the keyState map */ - g_winKeyState[dwKey] = fDown; - - QueueKeyboardEvents(g_pwinKeyboard, fDown ? KeyPress : KeyRelease, - dwKey + MIN_KEYCODE, NULL); - - winDebug("winSendKeyEvent: dwKey: %d, fDown: %d\n", dwKey, fDown); -} - -BOOL -winCheckKeyPressed(WPARAM wParam, LPARAM lParam) +int +XkbDDXPrivate(DeviceIntPtr dev,KeyCode key,XkbAction *act) { - switch (wParam) { - case VK_CONTROL: - if ((lParam & 0x1ff0000) == 0x11d0000 && g_winKeyState[KEY_RCtrl]) - return TRUE; - if ((lParam & 0x1ff0000) == 0x01d0000 && g_winKeyState[KEY_LCtrl]) - return TRUE; - break; - case VK_SHIFT: - if ((lParam & 0x1ff0000) == 0x0360000 && g_winKeyState[KEY_ShiftR]) - return TRUE; - if ((lParam & 0x1ff0000) == 0x02a0000 && g_winKeyState[KEY_ShiftL]) - return TRUE; - break; - default: - return TRUE; + XkbAnyAction *xf86act = &(act->any); + char msgbuf[XkbAnyActionDataSize+1]; + + if (xf86act->type == XkbSA_XFree86Private) + { + memcpy(msgbuf, xf86act->data, XkbAnyActionDataSize); + msgbuf[XkbAnyActionDataSize]= '\0'; + if (strcasecmp(msgbuf, "prgrbs")==0) { + DeviceIntPtr tmp; + winMsg(X_INFO, "Printing all currently active device grabs:\n"); + for (tmp = inputInfo.devices; tmp; tmp = tmp->next) + if (tmp->deviceGrab.grab) + PrintDeviceGrabInfo(tmp); + winMsg(X_INFO, "End list of active device grabs\n"); + } + else if (strcasecmp(msgbuf, "ungrab")==0) + UngrabAllDevices(FALSE); + else if (strcasecmp(msgbuf, "clsgrb")==0) + UngrabAllDevices(TRUE); + else if (strcasecmp(msgbuf, "prwins")==0) + PrintWindowTree(); } - return FALSE; -} - -/* Only one shift release message is sent even if both are pressed. - * Fix this here - */ -void -winFixShiftKeys(int iScanCode) -{ - if (GetKeyState(VK_SHIFT) & 0x8000) - return; - if (iScanCode == KEY_ShiftL && g_winKeyState[KEY_ShiftR]) - winSendKeyEvent(KEY_ShiftR, FALSE); - if (iScanCode == KEY_ShiftR && g_winKeyState[KEY_ShiftL]) - winSendKeyEvent(KEY_ShiftL, FALSE); + return 0; } diff --git a/hw/xwin/winlayouts.h b/hw/xwin/winlayouts.h index a61fd7ac1..c7905e3c2 100644 --- a/hw/xwin/winlayouts.h +++ b/hw/xwin/winlayouts.h @@ -42,7 +42,8 @@ typedef struct { */ WinKBLayoutRec winKBLayouts[] = { - {0x00000404, -1, "pc105", "zh_TW", NULL, NULL, "Chinese (Taiwan)"}, + {0x00000404, -1, "pc105", "cn", NULL, NULL, "Chinese (Traditional)"}, + {0x00000804, -1, "pc105", "cn", NULL, NULL, "Chinese (Simplified)"}, {0x00000405, -1, "pc105", "cz", NULL, NULL, "Czech"}, {0x00010405, -1, "pc105", "cz_qwerty", NULL, NULL, "Czech (QWERTY)"}, {0x00000406, -1, "pc105", "dk", NULL, NULL, "Danish"}, @@ -72,8 +73,8 @@ WinKBLayoutRec winKBLayouts[] = { {0x0000040f, -1, "pc105", "is", NULL, NULL, "Icelandic"}, {0x00000410, -1, "pc105", "it", NULL, NULL, "Italian"}, {0x00010410, -1, "pc105", "it", NULL, NULL, "Italian (142)"}, - {0xa0000410, -1, "macbook79", "it", "mac", NULL, "Italiano (Apple)"}, {0x00000411, 7, "jp106", "jp", NULL, NULL, "Japanese"}, + {0x00000412, -1, "kr106", "kr", NULL, NULL, "Korean"}, {0x00000413, -1, "pc105", "nl", NULL, NULL, "Dutch"}, {0x00000813, -1, "pc105", "be", NULL, NULL, "Dutch (Belgian)"}, {0x00000414, -1, "pc105", "no", NULL, NULL, "Norwegian"}, diff --git a/hw/xwin/winmouse.c b/hw/xwin/winmouse.c index bbe21cba6..59705e655 100644 --- a/hw/xwin/winmouse.c +++ b/hw/xwin/winmouse.c @@ -41,6 +41,8 @@ #include "xserver-properties.h" #include "inpututils.h" +#include "wmutil/mouse.h" + /* Peek the internal button mapping */ static CARD8 const *g_winMouseButtonMap = NULL; @@ -143,86 +145,20 @@ winMouseProc(DeviceIntPtr pDeviceInt, int iState) return Success; } -/* Handle the mouse wheel */ -int -winMouseWheel(int *iTotalDeltaZ, int iDeltaZ, int iButtonUp, int iButtonDown) -{ - int button; - - /* Do we have any previous delta stored? */ - if ((*iTotalDeltaZ > 0 && iDeltaZ > 0) - || (*iTotalDeltaZ < 0 && iDeltaZ < 0)) { - /* Previous delta and of same sign as current delta */ - iDeltaZ += *iTotalDeltaZ; - *iTotalDeltaZ = 0; - } - else { - /* - * Previous delta of different sign, or zero. - * We will set it to zero for either case, - * as blindly setting takes just as much time - * as checking, then setting if necessary :) - */ - *iTotalDeltaZ = 0; - } - - /* - * Only process this message if the wheel has moved further than - * WHEEL_DELTA - */ - if (iDeltaZ >= WHEEL_DELTA || (-1 * iDeltaZ) >= WHEEL_DELTA) { - *iTotalDeltaZ = 0; - - /* Figure out how many whole deltas of the wheel we have */ - iDeltaZ /= WHEEL_DELTA; - } - else { - /* - * Wheel has not moved past WHEEL_DELTA threshold; - * we will store the wheel delta until the threshold - * has been reached. - */ - *iTotalDeltaZ = iDeltaZ; - return 0; - } - - /* Set the button to indicate up or down wheel delta */ - if (iDeltaZ > 0) { - button = iButtonUp; - } - else { - button = iButtonDown; - } - - /* - * Flip iDeltaZ to positive, if negative, - * because always need to generate a *positive* number of - * button clicks for the Z axis. - */ - if (iDeltaZ < 0) { - iDeltaZ *= -1; - } - - /* Generate X input messages for each wheel delta we have seen */ - while (iDeltaZ--) { - /* Push the wheel button */ - winMouseButtonsSendEvent(ButtonPress, button); - - /* Release the wheel button */ - winMouseButtonsSendEvent(ButtonRelease, button); - } - - return 0; -} - /* * Enqueue a mouse button event */ void -winMouseButtonsSendEvent(int iEventType, int iButton) +winMouseButtonsSendEvent(bool bPress, int iButton) { ValuatorMask mask; + int iEventType; + + if (bPress) + iEventType = ButtonPress; + else + iEventType = ButtonRelease; if (g_winMouseButtonMap) iButton = g_winMouseButtonMap[iButton]; @@ -251,7 +187,7 @@ winMouseButtonsHandle(ScreenPtr pScreen, /* Send button events right away if emulate 3 buttons is off */ if (pScreenInfo->iE3BTimeout == WIN_E3B_OFF) { /* Emulate 3 buttons is off, send the button event */ - winMouseButtonsSendEvent(iEventType, iButton); + winMouseButtonsSendEvent((iEventType == ButtonPress), iButton); return 0; } @@ -288,7 +224,7 @@ winMouseButtonsHandle(ScreenPtr pScreen, pScreenPriv->iE3BCachedPress = 0; /* Send fake middle button */ - winMouseButtonsSendEvent(ButtonPress, Button2); + winMouseButtonsSendEvent(TRUE, Button2); /* Indicate that a fake middle button event was sent */ pScreenPriv->fE3BFakeButton2Sent = TRUE; @@ -303,8 +239,8 @@ winMouseButtonsHandle(ScreenPtr pScreen, pScreenPriv->iE3BCachedPress = 0; /* Send cached press, then send release */ - winMouseButtonsSendEvent(ButtonPress, iButton); - winMouseButtonsSendEvent(ButtonRelease, iButton); + winMouseButtonsSendEvent(TRUE, iButton); + winMouseButtonsSendEvent(FALSE, iButton); } else if (iEventType == ButtonRelease && pScreenPriv->fE3BFakeButton2Sent && !(wParam & MK_LBUTTON) @@ -315,7 +251,7 @@ winMouseButtonsHandle(ScreenPtr pScreen, pScreenPriv->fE3BFakeButton2Sent = FALSE; /* Send middle mouse button release */ - winMouseButtonsSendEvent(ButtonRelease, Button2); + winMouseButtonsSendEvent(FALSE, Button2); } else if (iEventType == ButtonRelease && pScreenPriv->iE3BCachedPress == 0 @@ -324,7 +260,7 @@ winMouseButtonsHandle(ScreenPtr pScreen, * Button was release, no button is cached, * and there is no fake button 2 release is pending. */ - winMouseButtonsSendEvent(ButtonRelease, iButton); + winMouseButtonsSendEvent(FALSE, iButton); } return 0; diff --git a/hw/xwin/winmsg.c b/hw/xwin/winmsg.c index 56e7a097c..1d3a387d8 100644 --- a/hw/xwin/winmsg.c +++ b/hw/xwin/winmsg.c @@ -38,17 +38,7 @@ #endif #include <stdarg.h> -void -winVMsg(int, MessageType, int verb, const char *, va_list) -_X_ATTRIBUTE_PRINTF(4, 0); - -void -winVMsg(int scrnIndex, MessageType type, int verb, const char *format, - va_list ap) -{ - LogVMessageVerb(type, verb, format, ap); -} - +#ifdef XWIN_XF86CONFIG void winDrvMsg(int scrnIndex, MessageType type, const char *format, ...) { @@ -60,16 +50,6 @@ winDrvMsg(int scrnIndex, MessageType type, const char *format, ...) } void -winMsg(MessageType type, const char *format, ...) -{ - va_list ap; - - va_start(ap, format); - LogVMessageVerb(type, 1, format, ap); - va_end(ap); -} - -void winDrvMsgVerb(int scrnIndex, MessageType type, int verb, const char *format, ...) { @@ -79,24 +59,25 @@ winDrvMsgVerb(int scrnIndex, MessageType type, int verb, const char *format, LogVMessageVerb(type, verb, format, ap); va_end(ap); } +#endif void -winMsgVerb(MessageType type, int verb, const char *format, ...) +winErrorFVerb(int verb, const char *format, ...) { va_list ap; va_start(ap, format); - LogVMessageVerb(type, verb, format, ap); + LogVMessageVerb(X_NONE, verb, format, ap); va_end(ap); } void -winErrorFVerb(int verb, const char *format, ...) +winError(const char *format, ...) { va_list ap; va_start(ap, format); - LogVMessageVerb(X_NONE, verb, format, ap); + LogVMessageVerb(X_NONE, -1, format, ap); va_end(ap); } @@ -158,8 +139,8 @@ winDebugWin32Message(const char *function, HWND hwnd, UINT message, getenv("WIN_DEBUG_WM_USER")) { winDebug("%s - Message WM_USER + %d\n", function, message - WM_USER); - winDebug("\thwnd 0x%x wParam 0x%x lParam 0x%x\n", hwnd, wParam, - lParam); + winDebug("\thwnd 0x%p wParam 0x%x lParam 0x%x\n", hwnd, (int)wParam, + (int)lParam); } } else if (message < MESSAGE_NAMES_LEN && MESSAGE_NAMES[message]) { @@ -170,8 +151,8 @@ winDebugWin32Message(const char *function, HWND hwnd, UINT message, buffer[63] = 0; if (force || getenv("WIN_DEBUG_MESSAGES") || getenv(buffer)) { winDebug("%s - Message %s\n", function, MESSAGE_NAMES[message]); - winDebug("\thwnd 0x%x wParam 0x%x lParam 0x%x\n", hwnd, wParam, - lParam); + winDebug("\thwnd 0x%p wParam 0x%x lParam 0x%x\n", hwnd, (int)wParam, + (int)lParam); } } } diff --git a/hw/xwin/winmsg.h b/hw/xwin/winmsg.h index 6c96c4070..25d887510 100644 --- a/hw/xwin/winmsg.h +++ b/hw/xwin/winmsg.h @@ -1,5 +1,3 @@ -#ifndef __WIN_MSG_H__ -#define __WIN_MSG_H__ /* *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. * @@ -30,12 +28,17 @@ * Authors: Alexander Gottwald */ +#ifndef __WIN_MSG_H__ +#define __WIN_MSG_H__ + #include <X11/Xwindows.h> +#include <X11/Xfuncproto.h> /* * Function prototypes */ +#ifdef XWIN_XF86CONFIG void winDrvMsgVerb(int scrnIndex, MessageType type, int verb, const char *format, ...) @@ -43,12 +46,10 @@ _X_ATTRIBUTE_PRINTF(4, 5); void winDrvMsg(int scrnIndex, MessageType type, const char *format, ...) _X_ATTRIBUTE_PRINTF(3, 4); -void -winMsgVerb(MessageType type, int verb, const char *format, ...) -_X_ATTRIBUTE_PRINTF(3, 4); -void -winMsg(MessageType type, const char *format, ...) -_X_ATTRIBUTE_PRINTF(2, 3); +#endif + +#define winMsg LogMessage + void winDebug(const char *format, ...) _X_ATTRIBUTE_PRINTF(1, 2); @@ -59,6 +60,10 @@ _X_ATTRIBUTE_PRINTF(1, 2); void winErrorFVerb(int verb, const char *format, ...) _X_ATTRIBUTE_PRINTF(2, 3); +void +winError(const char *format, ...) +_X_ATTRIBUTE_PRINTF(1, 2); + void winW32Error(int verb, const char *message); void winW32ErrorEx(int verb, const char *message, DWORD errorcode); void winDebugWin32Message(const char *function, HWND hwnd, UINT message, diff --git a/hw/xwin/winmultiwindowclass.h b/hw/xwin/winmultiwindowclass.h index 3244f78e3..37ee9fb13 100644 --- a/hw/xwin/winmultiwindowclass.h +++ b/hw/xwin/winmultiwindowclass.h @@ -31,11 +31,24 @@ */ /* + * The next block of definitions are for window manager properties that + * clients and applications use for communication. + */ + +/* * Structures */ +/* + * WM_HINTS structure + * + * NOTE: this structure represents the internal format stored in the property + * after it is marshalled by libX11, converting the flags field from an + * arch-dependent long to a 32-bit int. + */ + typedef struct { - long flags; /* marks which fields in this structure are defined */ + int flags; /* marks which fields in this structure are defined */ Bool input; /* does this application rely on the window manager to get keyboard input? */ int initial_state; /* see below */ @@ -59,11 +72,15 @@ typedef struct { #define AllHints (InputHint|StateHint|IconPixmapHint|IconWindowHint|IconPositionHint|IconMaskHint|WindowGroupHint) /* - * new version containing base_width, base_height, and win_gravity fields; + * ICCCM 1.0 version containing base_width, base_height, and win_gravity fields; * used with WM_NORMAL_HINTS. + * + * NOTE: this structure represents the internal format stored in the property + * after it is marshalled by libX11, converting the flags field from an + * arch-dependent long to a 32-bit int. */ typedef struct { - long flags; /* marks which fields in this structure are defined */ + int flags; /* marks which fields in this structure are defined */ int x, y; /* obsolete for new window mgrs, but clients */ int width, height; /* should set so old wm's don't mess up */ int min_width, min_height; @@ -77,11 +94,6 @@ typedef struct { int win_gravity; /* added by ICCCM version 1 */ } WinXSizeHints; -/* - * The next block of definitions are for window manager properties that - * clients and applications use for communication. - */ - /* flags argument in size hints */ #define USPosition (1L << 0) /* user specified x, y */ #define USSize (1L << 1) /* user specified width, height */ diff --git a/hw/xwin/winmultiwindowicons.c b/hw/xwin/winmultiwindowicons.c index c22e68874..a20e0b892 100644 --- a/hw/xwin/winmultiwindowicons.c +++ b/hw/xwin/winmultiwindowicons.c @@ -32,526 +32,22 @@ #include <xwin-config.h> #endif -#ifndef WINVER -#define WINVER 0x0500 -#endif - #include <X11/Xwindows.h> #include <X11/Xlib.h> -#include <X11/Xutil.h> +#include <X11/Xlib-xcb.h> #include "winresource.h" #include "winprefs.h" -#include "winmsg.h" #include "winmultiwindowicons.h" #include "winglobals.h" -/* - * global variables - */ -extern HINSTANCE g_hInstance; - -/* - * Scale an X icon ZPixmap into a Windoze icon bitmap - */ - -static void -winScaleXImageToWindowsIcon(int iconSize, - int effBPP, - int stride, XImage * pixmap, unsigned char *image) -{ - int row, column, effXBPP, effXDepth; - unsigned char *outPtr; - unsigned char *iconData = 0; - int xStride; - float factX, factY; - int posX, posY; - unsigned char *ptr; - unsigned int zero; - unsigned int color; - - effXBPP = pixmap->bits_per_pixel; - if (pixmap->bits_per_pixel == 15) - effXBPP = 16; - - effXDepth = pixmap->depth; - if (pixmap->depth == 15) - effXDepth = 16; - - xStride = pixmap->bytes_per_line; - if (stride == 0 || xStride == 0) { - ErrorF("winScaleXBitmapToWindows - stride or xStride is zero. " - "Bailing.\n"); - return; - } - - /* Get icon data */ - iconData = (unsigned char *) pixmap->data; - - /* Keep aspect ratio */ - factX = ((float) pixmap->width) / ((float) iconSize); - factY = ((float) pixmap->height) / ((float) iconSize); - if (factX > factY) - factY = factX; - else - factX = factY; - - /* Out-of-bounds, fill icon with zero */ - zero = 0; - - for (row = 0; row < iconSize; row++) { - outPtr = image + stride * row; - for (column = 0; column < iconSize; column++) { - posX = factX * column; - posY = factY * row; - - ptr = (unsigned char *) iconData + posY * xStride; - if (effXBPP == 1) { - ptr += posX / 8; - - /* Out of X icon bounds, leave space blank */ - if (posX >= pixmap->width || posY >= pixmap->height) - ptr = (unsigned char *) &zero; - - if ((*ptr) & (1 << (posX & 7))) - switch (effBPP) { - case 32: - *(outPtr++) = 0; - case 24: - *(outPtr++) = 0; - case 16: - *(outPtr++) = 0; - case 8: - *(outPtr++) = 0; - break; - case 1: - outPtr[column / 8] &= ~(1 << (7 - (column & 7))); - break; - } - else - switch (effBPP) { - case 32: - *(outPtr++) = 255; - *(outPtr++) = 255; - *(outPtr++) = 255; - *(outPtr++) = 0; - break; - case 24: - *(outPtr++) = 255; - case 16: - *(outPtr++) = 255; - case 8: - *(outPtr++) = 255; - break; - case 1: - outPtr[column / 8] |= (1 << (7 - (column & 7))); - break; - } - } - else if (effXDepth == 24 || effXDepth == 32) { - ptr += posX * (effXBPP / 8); - - /* Out of X icon bounds, leave space blank */ - if (posX >= pixmap->width || posY >= pixmap->height) - ptr = (unsigned char *) &zero; - color = (((*ptr) << 16) - + ((*(ptr + 1)) << 8) - + ((*(ptr + 2)) << 0)); - switch (effBPP) { - case 32: - *(outPtr++) = *(ptr++); /* b */ - *(outPtr++) = *(ptr++); /* g */ - *(outPtr++) = *(ptr++); /* r */ - *(outPtr++) = (effXDepth == 32) ? *(ptr++) : 0x0; /* alpha */ - break; - case 24: - *(outPtr++) = *(ptr++); - *(outPtr++) = *(ptr++); - *(outPtr++) = *(ptr++); - break; - case 16: - color = ((((*ptr) >> 2) << 10) - + (((*(ptr + 1)) >> 2) << 5) - + (((*(ptr + 2)) >> 2))); - *(outPtr++) = (color >> 8); - *(outPtr++) = (color & 255); - break; - case 8: - color = (((*ptr))) + (((*(ptr + 1)))) + (((*(ptr + 2)))); - color /= 3; - *(outPtr++) = color; - break; - case 1: - if (color) - outPtr[column / 8] |= (1 << (7 - (column & 7))); - else - outPtr[column / 8] &= ~(1 << (7 - (column & 7))); - } - } - else if (effXDepth == 16) { - ptr += posX * (effXBPP / 8); - - /* Out of X icon bounds, leave space blank */ - if (posX >= pixmap->width || posY >= pixmap->height) - ptr = (unsigned char *) &zero; - color = ((*ptr) << 8) + (*(ptr + 1)); - switch (effBPP) { - case 32: - *(outPtr++) = (color & 31) << 2; - *(outPtr++) = ((color >> 5) & 31) << 2; - *(outPtr++) = ((color >> 10) & 31) << 2; - *(outPtr++) = 0; /* resvd */ - break; - case 24: - *(outPtr++) = (color & 31) << 2; - *(outPtr++) = ((color >> 5) & 31) << 2; - *(outPtr++) = ((color >> 10) & 31) << 2; - break; - case 16: - *(outPtr++) = *(ptr++); - *(outPtr++) = *(ptr++); - break; - case 8: - *(outPtr++) = (((color & 31) - + ((color >> 5) & 31) - + ((color >> 10) & 31)) / 3) << 2; - break; - case 1: - if (color) - outPtr[column / 8] |= (1 << (7 - (column & 7))); - else - outPtr[column / 8] &= ~(1 << (7 - (column & 7))); - break; - } /* end switch(effbpp) */ - } /* end if effxbpp==16) */ - } /* end for column */ - } /* end for row */ -} - -static HICON -NetWMToWinIconAlpha(uint32_t * icon) -{ - int width = icon[0]; - int height = icon[1]; - uint32_t *pixels = &icon[2]; - HICON result; - HDC hdc = GetDC(NULL); - uint32_t *DIB_pixels; - ICONINFO ii; - BITMAPV4HEADER bmh = { sizeof(bmh) }; - - /* Define an ARGB pixel format used for Color+Alpha icons */ - bmh.bV4Width = width; - bmh.bV4Height = -height; /* Invert the image */ - bmh.bV4Planes = 1; - bmh.bV4BitCount = 32; - bmh.bV4V4Compression = BI_BITFIELDS; - bmh.bV4AlphaMask = 0xFF000000; - bmh.bV4RedMask = 0x00FF0000; - bmh.bV4GreenMask = 0x0000FF00; - bmh.bV4BlueMask = 0x000000FF; - - ii.fIcon = TRUE; - ii.xHotspot = 0; /* ignored */ - ii.yHotspot = 0; /* ignored */ - ii.hbmColor = CreateDIBSection(hdc, (BITMAPINFO *) &bmh, - DIB_RGB_COLORS, (void **) &DIB_pixels, NULL, - 0); - ReleaseDC(NULL, hdc); - - if (!ii.hbmColor) - return NULL; - - ii.hbmMask = CreateBitmap(width, height, 1, 1, NULL); - memcpy(DIB_pixels, pixels, height * width * 4); - - /* CreateIconIndirect() traditionally required DDBitmaps */ - /* Systems from WinXP accept 32-bit ARGB DIBitmaps with full 8-bit alpha support */ - /* The icon is created with a DIB + empty DDB mask (an MS example does the same) */ - result = CreateIconIndirect(&ii); - - DeleteObject(ii.hbmColor); - DeleteObject(ii.hbmMask); +#include "wmutil/icon_convert.h" - winDebug("NetWMToWinIconAlpha - %d x %d = %p\n", icon[0], icon[1], result); - return result; -} - -static HICON -NetWMToWinIconThreshold(uint32_t * icon) -{ - int width = icon[0]; - int height = icon[1]; - uint32_t *pixels = &icon[2]; - int row, col; - HICON result; - ICONINFO ii; - - HDC hdc = GetDC(NULL); - HDC xorDC = CreateCompatibleDC(hdc); - HDC andDC = CreateCompatibleDC(hdc); - - ii.fIcon = TRUE; - ii.xHotspot = 0; /* ignored */ - ii.yHotspot = 0; /* ignored */ - ii.hbmColor = CreateCompatibleBitmap(hdc, width, height); - ii.hbmMask = CreateCompatibleBitmap(hdc, width, height); - ReleaseDC(NULL, hdc); - SelectObject(xorDC, ii.hbmColor); - SelectObject(andDC, ii.hbmMask); - - for (row = 0; row < height; row++) { - for (col = 0; col < width; col++) { - if ((*pixels & 0xFF000000) > 31 << 24) { /* 31 alpha threshold, i.e. opaque above, transparent below */ - SetPixelV(xorDC, col, row, - RGB(((char *) pixels)[2], ((char *) pixels)[1], - ((char *) pixels)[0])); - SetPixelV(andDC, col, row, RGB(0, 0, 0)); /* black mask */ - } - else { - SetPixelV(xorDC, col, row, RGB(0, 0, 0)); - SetPixelV(andDC, col, row, RGB(255, 255, 255)); /* white mask */ - } - pixels++; - } - } - DeleteDC(xorDC); - DeleteDC(andDC); - - result = CreateIconIndirect(&ii); - - DeleteObject(ii.hbmColor); - DeleteObject(ii.hbmMask); - - winDebug("NetWMToWinIconThreshold - %d x %d = %p\n", icon[0], icon[1], - result); - return result; -} - -static HICON -NetWMToWinIcon(int bpp, uint32_t * icon) -{ - static Bool hasIconAlphaChannel = FALSE; - static BOOL versionChecked = FALSE; - - if (!versionChecked) { - OSVERSIONINFOEX osvi = { 0 }; - ULONGLONG dwlConditionMask = 0; - - osvi.dwOSVersionInfoSize = sizeof(osvi); - osvi.dwMajorVersion = 5; - osvi.dwMinorVersion = 1; - - /* Windows versions later than XP have icon alpha channel suport, 2000 does not */ - VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, - VER_GREATER_EQUAL); - VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, - VER_GREATER_EQUAL); - hasIconAlphaChannel = - VerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION, - dwlConditionMask); - versionChecked = TRUE; - - ErrorF("OS has icon alpha channel support: %s\n", - hasIconAlphaChannel ? "yes" : "no"); - } - - if (hasIconAlphaChannel && (bpp == 32)) - return NetWMToWinIconAlpha(icon); - else - return NetWMToWinIconThreshold(icon); -} +extern void winUpdateIcon(HWND hWnd, Display * pDisplay, Window id, HICON hIconNew); /* - * Attempt to create a custom icon from the WM_HINTS bitmaps + * global variables */ - -static - HICON -winXIconToHICON(Display * pDisplay, Window id, int iconSize) -{ - unsigned char *mask, *image = NULL, *imageMask; - unsigned char *dst, *src; - int planes, bpp, i; - unsigned int biggest_size = 0; - HDC hDC; - ICONINFO ii; - XWMHints *hints; - HICON hIcon = NULL; - uint32_t *biggest_icon = NULL; - static Atom _XA_NET_WM_ICON; - static int generation; - uint32_t *icon, *icon_data = NULL; - unsigned long int size; - Atom type; - int format; - unsigned long int left; - - hDC = GetDC(GetDesktopWindow()); - planes = GetDeviceCaps(hDC, PLANES); - bpp = GetDeviceCaps(hDC, BITSPIXEL); - ReleaseDC(GetDesktopWindow(), hDC); - - /* Always prefer _NET_WM_ICON icons */ - if (generation != serverGeneration) { - generation = serverGeneration; - _XA_NET_WM_ICON = XInternAtom(pDisplay, "_NET_WM_ICON", FALSE); - } - - if ((XGetWindowProperty(pDisplay, id, _XA_NET_WM_ICON, - 0, MAXINT, FALSE, - AnyPropertyType, &type, &format, &size, &left, - (unsigned char **) &icon_data) == Success) && - (icon_data != NULL)) { - for (icon = icon_data; icon < &icon_data[size] && *icon; - icon = &icon[icon[0] * icon[1] + 2]) { - winDebug("winXIconToHICON: %u x %u NetIcon\n", icon[0], icon[1]); - - /* Icon data size will overflow an int and thus is bigger than the - property can possibly be */ - if ((INT_MAX/icon[0]) < icon[1]) { - winDebug("winXIconToHICON: _NET_WM_ICON icon data size overflow\n"); - break; - } - - /* Icon data size is bigger than amount of data remaining */ - if (&icon[icon[0] * icon[1] + 2] > &icon_data[size]) { - winDebug("winXIconToHICON: _NET_WM_ICON data is malformed\n"); - break; - } - - /* Found an exact match to the size we require... */ - if (icon[0] == iconSize && icon[1] == iconSize) { - winDebug("winXIconToHICON: selected %d x %d NetIcon\n", - iconSize, iconSize); - hIcon = NetWMToWinIcon(bpp, icon); - break; - } - /* Otherwise, find the biggest icon and let Windows scale the size */ - else if (biggest_size < icon[0]) { - biggest_icon = icon; - biggest_size = icon[0]; - } - } - - if (!hIcon && biggest_icon) { - winDebug - ("winXIconToHICON: selected %u x %u NetIcon for scaling to %d x %d\n", - biggest_icon[0], biggest_icon[1], iconSize, iconSize); - - hIcon = NetWMToWinIcon(bpp, biggest_icon); - } - - XFree(icon_data); - } - - if (!hIcon) { - winDebug("winXIconToHICON: no suitable NetIcon\n"); - - hints = XGetWMHints(pDisplay, id); - if (hints) { - winDebug("winXIconToHICON: id 0x%x icon_pixmap hint %x\n", id, - hints->icon_pixmap); - - if (hints->icon_pixmap) { - Window root; - int x, y; - unsigned int width, height, border_width, depth; - XImage *xImageIcon; - XImage *xImageMask = NULL; - - XGetGeometry(pDisplay, hints->icon_pixmap, &root, &x, &y, - &width, &height, &border_width, &depth); - - xImageIcon = - XGetImage(pDisplay, hints->icon_pixmap, 0, 0, width, height, - 0xFFFFFFFF, ZPixmap); - winDebug("winXIconToHICON: id 0x%x icon Ximage 0x%p\n", id, - xImageIcon); - - if (hints->icon_mask) - xImageMask = - XGetImage(pDisplay, hints->icon_mask, 0, 0, width, - height, 0xFFFFFFFF, ZPixmap); - - if (xImageIcon) { - int effBPP, stride, maskStride; - - /* 15 BPP is really 16BPP as far as we care */ - if (bpp == 15) - effBPP = 16; - else - effBPP = bpp; - - /* Need 16-bit aligned rows for DDBitmaps */ - stride = ((iconSize * effBPP + 15) & (~15)) / 8; - - /* Mask is 1-bit deep */ - maskStride = ((iconSize * 1 + 15) & (~15)) / 8; - - image = malloc(stride * iconSize); - imageMask = malloc(stride * iconSize); - mask = malloc(maskStride * iconSize); - - /* Default to a completely black mask */ - memset(imageMask, 0, stride * iconSize); - memset(mask, 0, maskStride * iconSize); - - winScaleXImageToWindowsIcon(iconSize, effBPP, stride, - xImageIcon, image); - - if (xImageMask) { - winScaleXImageToWindowsIcon(iconSize, 1, maskStride, - xImageMask, mask); - winScaleXImageToWindowsIcon(iconSize, effBPP, stride, - xImageMask, imageMask); - } - - /* Now we need to set all bits of the icon which are not masked */ - /* on to 0 because Color is really an XOR, not an OR function */ - dst = image; - src = imageMask; - - for (i = 0; i < (stride * iconSize); i++) - if ((*(src++))) - *(dst++) = 0; - else - dst++; - - ii.fIcon = TRUE; - ii.xHotspot = 0; /* ignored */ - ii.yHotspot = 0; /* ignored */ - - /* Create Win32 mask from pixmap shape */ - ii.hbmMask = - CreateBitmap(iconSize, iconSize, planes, 1, mask); - - /* Create Win32 bitmap from pixmap */ - ii.hbmColor = - CreateBitmap(iconSize, iconSize, planes, bpp, image); - - /* Merge Win32 mask and bitmap into icon */ - hIcon = CreateIconIndirect(&ii); - - /* Release Win32 mask and bitmap */ - DeleteObject(ii.hbmMask); - DeleteObject(ii.hbmColor); - - /* Free X mask and bitmap */ - free(mask); - free(image); - free(imageMask); - - if (xImageMask) - XDestroyImage(xImageMask); - - XDestroyImage(xImageIcon); - } - } - XFree(hints); - } - } - return hIcon; -} +extern HINSTANCE g_hInstance; /* * Change the Windows window icon @@ -563,32 +59,46 @@ winUpdateIcon(HWND hWnd, Display * pDisplay, Window id, HICON hIconNew) { HICON hIcon, hIconSmall = NULL, hIconOld; - /* Start with the icon from preferences, if any */ - hIcon = hIconNew; - hIconSmall = hIconNew; + if (hIconNew) + { + /* Start with the icon from preferences, if any */ + hIcon = hIconNew; + hIconSmall = hIconNew; + } + else + { + /* If we still need an icon, try and get the icon from WM_HINTS */ + xcb_connection_t *conn = XGetXCBConnection(pDisplay); + + hIcon = winXIconToHICON(conn, id, GetSystemMetrics(SM_CXICON)); + hIconSmall = winXIconToHICON(conn, id, GetSystemMetrics(SM_CXSMICON)); - /* If we still need an icon, try and get the icon from WM_HINTS */ - if (!hIcon) - hIcon = winXIconToHICON(pDisplay, id, GetSystemMetrics(SM_CXICON)); - if (!hIconSmall) - hIconSmall = - winXIconToHICON(pDisplay, id, GetSystemMetrics(SM_CXSMICON)); + /* If we got the small, but not the large one swap them */ + if (!hIcon && hIconSmall) { + hIcon = hIconSmall; + hIconSmall = NULL; + } + } - /* If we got the small, but not the large one swap them */ - if (!hIcon && hIconSmall) { - hIcon = hIconSmall; - hIconSmall = NULL; + /* If we still need an icon, use the default one */ + if (!hIcon) { + hIcon = g_hIconX; + hIconSmall = g_hSmallIconX; } - /* Set the large icon */ - hIconOld = (HICON) SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM) hIcon); - /* Delete the old icon if its not the default */ - winDestroyIcon(hIconOld); + if (hIcon) { + /* Set the large icon */ + hIconOld = (HICON) SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM) hIcon); + /* Delete the old icon if its not the default */ + winDestroyIcon(hIconOld); + } - /* Same for the small icon */ - hIconOld = - (HICON) SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM) hIconSmall); - winDestroyIcon(hIconOld); + if (hIconSmall) { + /* Same for the small icon */ + hIconOld = + (HICON) SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM) hIconSmall); + winDestroyIcon(hIconOld); + } } void diff --git a/hw/xwin/winmultiwindowicons.h b/hw/xwin/winmultiwindowicons.h index bf7f6eda7..5e0873ab9 100644 --- a/hw/xwin/winmultiwindowicons.h +++ b/hw/xwin/winmultiwindowicons.h @@ -27,8 +27,8 @@ #ifndef WINMULTIWINDOWICONS_H #define WINMULTIWINDOWICONS_H -void - winUpdateIcon(HWND hWnd, Display * pDisplay, Window id, HICON hIconNew); +//void +// winUpdateIcon(HWND hWnd, Display * pDisplay, Window id, HICON hIconNew); void winInitGlobalIcons(void); diff --git a/hw/xwin/winmultiwindowwindow.c b/hw/xwin/winmultiwindowwindow.c index c22d69074..c3f4feda2 100644 --- a/hw/xwin/winmultiwindowwindow.c +++ b/hw/xwin/winmultiwindowwindow.c @@ -35,9 +35,11 @@ #ifdef HAVE_XWIN_CONFIG_H #include <xwin-config.h> #endif + #include "win.h" #include "dixevents.h" #include "winmultiwindowclass.h" +#include "winmultiwindowicons.h" /* * Prototypes for local functions @@ -55,11 +57,27 @@ static void static void winFindWindow(void *value, XID id, void *cdata); +static Bool +isToplevelWindow(WindowPtr pWin) +{ + assert(pWin->parent); /* root window isn't expected here */ + + /* If the immediate parent is the root window, this is a top-level window */ + if ((pWin->parent) && (pWin->parent->parent == NULL)) { + assert(pWin->parent == pWin->drawable.pScreen->root); + return TRUE; + } + + /* otherwise, a child window */ + return FALSE; +} + static void winInitMultiWindowClass(void) { static wATOM atomXWinClass = 0; + static wATOM atomXWinChildClass = 0; WNDCLASSEX wcx; if (atomXWinClass == 0) { @@ -83,11 +101,40 @@ winInitMultiWindowClass(void) wcx.hIconSm = hIconSmall; #if CYGMULTIWINDOW_DEBUG - ErrorF("winCreateWindowsWindow - Creating class: %s\n", WINDOW_CLASS_X); + ErrorF("winInitMultiWindowClass - Creating class: %s\n", + WINDOW_CLASS_X); #endif atomXWinClass = RegisterClassEx(&wcx); } + + if (atomXWinChildClass == 0) { + HICON hIcon, hIconSmall; + + /* Load the default icons */ + winSelectIcons(&hIcon, &hIconSmall); + + /* Setup our window class */ + wcx.cbSize = sizeof(WNDCLASSEX); + wcx.style = CS_HREDRAW | CS_VREDRAW | (g_fNativeGl ? CS_OWNDC : 0); + wcx.lpfnWndProc = winChildWindowProc; + wcx.cbClsExtra = 0; + wcx.cbWndExtra = 0; + wcx.hInstance = g_hInstance; + wcx.hIcon = hIcon; + wcx.hCursor = 0; + wcx.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); + wcx.lpszMenuName = NULL; + wcx.lpszClassName = WINDOW_CLASS_X_CHILD; + wcx.hIconSm = hIconSmall; + +#if CYGMULTIWINDOW_DEBUG + ErrorF("winInitMultiWindowClass - Creating class: %s\n", + WINDOW_CLASS_X_CHILD); +#endif + + atomXWinChildClass = RegisterClassEx(&wcx); + } } /* @@ -202,6 +249,29 @@ winPositionWindowMultiWindow(WindowPtr pWin, int x, int y) return fResult; } + if (!isToplevelWindow(pWin)) { + POINT parentOrigin; + + /* Get the X and Y location of the X window */ + iX = pWin->drawable.x + GetSystemMetrics(SM_XVIRTUALSCREEN); + iY = pWin->drawable.y + GetSystemMetrics(SM_YVIRTUALSCREEN); + + /* Get the height and width of the X window */ + iWidth = pWin->drawable.width; + iHeight = pWin->drawable.height; + + /* Convert screen coordinates into client area co-ordinates of the parent */ + parentOrigin.x = 0; + parentOrigin.y = 0; + ClientToScreen(GetParent(hWnd), &parentOrigin); + + MoveWindow(hWnd, + iX - parentOrigin.x, iY - parentOrigin.y, iWidth, iHeight, + TRUE); + + return fResult; + } + /* Get the Windows window style and extended style */ dwExStyle = GetWindowLongPtr(hWnd, GWL_EXSTYLE); dwStyle = GetWindowLongPtr(hWnd, GWL_STYLE); @@ -256,7 +326,7 @@ winPositionWindowMultiWindow(WindowPtr pWin, int x, int y) #endif #if CYGWINDOWING_DEBUG - ErrorF("\tMoveWindow to (%ld, %ld) - %ldx%ld\n", rcNew.left, rcNew.top, + ErrorF("\tMoveWindow to (%d, %d) - %dx%d\n", rcNew.left, rcNew.top, rcNew.right - rcNew.left, rcNew.bottom - rcNew.top); #endif /* Change the position and dimensions of the Windows window */ @@ -470,12 +540,8 @@ winRestackWindowMultiWindow(WindowPtr pWin, WindowPtr pOldNextSib) #endif } -/* - * winCreateWindowsWindow - Create a Windows window associated with an X window - */ - -void -winCreateWindowsWindow(WindowPtr pWin) +static void +winCreateWindowsTopLevelWindow(WindowPtr pWin) { int iX, iY; int iWidth; @@ -484,7 +550,6 @@ winCreateWindowsWindow(WindowPtr pWin) HWND hFore = NULL; winWindowPriv(pWin); - winPrivScreenPtr pScreenPriv = pWinPriv->pScreenPriv; WinXSizeHints hints; Window daddyId; DWORD dwStyle, dwExStyle; @@ -502,39 +567,63 @@ winCreateWindowsWindow(WindowPtr pWin) iHeight = pWin->drawable.height; /* If it's an InputOutput window, and so is going to end up being made visible, - make sure the window actually ends up somewhere where it will be visible */ - if (pWin->drawable.class != InputOnly) { - if ((iX < GetSystemMetrics(SM_XVIRTUALSCREEN)) || - (iX > GetSystemMetrics(SM_CXVIRTUALSCREEN))) - iX = CW_USEDEFAULT; + make sure the window actually ends up somewhere where it will be visible - if ((iY < GetSystemMetrics(SM_YVIRTUALSCREEN)) || - (iY > GetSystemMetrics(SM_CYVIRTUALSCREEN))) - iY = CW_USEDEFAULT; + To handle arrangements of monitors which form a non-rectangular virtual + desktop, check if the window will end up with it's top-left corner on any + monitor + */ + if (pWin->drawable.class != InputOnly) { + POINT pt = { iX, iY }; + if (MonitorFromPoint(pt, MONITOR_DEFAULTTONULL) == NULL) + { + iX = CW_USEDEFAULT; + iY = CW_USEDEFAULT; + } } - winDebug("winCreateWindowsWindow - %dx%d @ %dx%d\n", iWidth, iHeight, iX, - iY); + winDebug("winCreateWindowsTopLevelWindow - %dx%d @ %dx%d\n", iWidth, + iHeight, iX, iY); if (winMultiWindowGetTransientFor(pWin, &daddyId)) { if (daddyId) { - hFore = GetForegroundWindow(); - if (hFore && (daddyId != (Window) (INT_PTR) GetProp(hFore, WIN_WID_PROP))) - hFore = NULL; + WindowPtr pParent; + int res = dixLookupWindow(&pParent, daddyId, serverClient, DixReadAccess); + if (res == Success) + { + winPrivWinPtr pParentPriv = winGetWindowPriv(pParent); + hFore = pParentPriv->hWnd; + } } } else { - /* Default positions if none specified */ - if (!winMultiWindowGetWMNormalHints(pWin, &hints)) - hints.flags = 0; - if (!(hints.flags & (USPosition | PPosition)) && - !pWin->overrideRedirect) { - iX = CW_USEDEFAULT; - iY = CW_USEDEFAULT; + if (!pWin->overrideRedirect) { + /* Default positions if none specified */ + if (!winMultiWindowGetWMNormalHints(pWin, &hints)) + hints.flags = 0; + + if ((hints.flags & USPosition) || + ((hints.flags & PPosition) && + ((pWin->drawable.x - pWin->borderWidth != 0) || + (pWin->drawable.y - pWin->borderWidth != 0)))) { + /* + Always respect user specified position, respect program + specified position if it's not the origin + */ + } + else { + /* Use default position */ + iX = CW_USEDEFAULT; + iY = CW_USEDEFAULT; + } } } - /* Make it WS_OVERLAPPED in create call since WS_POPUP doesn't support */ + winDebug("winCreateWindowsTopLevelWindow - %dx%d @ %dx%d\n", iWidth, + iHeight, iX, iY); + + /* Create the window */ + /* Make it OVERLAPPED in create call since WS_POPUP doesn't support */ /* CW_USEDEFAULT, change back to popup after creation */ dwStyle = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS; dwExStyle = WS_EX_TOOLWINDOW; @@ -572,11 +661,14 @@ winCreateWindowsWindow(WindowPtr pWin) GetModuleHandle(NULL), /* Instance handle */ pWin); /* ScreenPrivates */ if (hWnd == NULL) { - ErrorF("winCreateWindowsWindow - CreateWindowExA () failed: %d\n", - (int) GetLastError()); + ErrorF + ("winCreateWindowsTopLevelWindow - CreateWindowExA () failed: %d\n", + (int) GetLastError()); } pWinPriv->hWnd = hWnd; + winDebug("winCreateWindowsTopLevelWindow - hwnd 0x%p\n", hWnd); + /* Change style back to popup, already placed... */ SetWindowLongPtr(hWnd, GWL_STYLE, WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS); @@ -597,9 +689,107 @@ winCreateWindowsWindow(WindowPtr pWin) /* Flag that this Windows window handles its own activation */ SetProp(hWnd, WIN_NEEDMANAGE_PROP, (HANDLE) 0); +} + +static void +winCreateWindowsChildWindow(WindowPtr pWin) +{ + int iX, iY, iWidth, iHeight; + HWND hWnd; + WindowPtr pParent = pWin->parent; + DWORD dwStyle = WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_DISABLED; + DWORD dwExStyle = WS_EX_TRANSPARENT; + + /* + WS_DISABLED means child window never gains the input focus, so only the + top-level window needs deal with passing input to the X server - /* Call engine-specific create window procedure */ - (*pScreenPriv->pwinFinishCreateWindowsWindow) (pWin); + WS_EX_TRANSPARENT ensures that the contents of the top-level + Windows window (which will contain all non-OpenGL drawing for the hierarchy) + can be seen through any intermediate child windows which have nothing + drawn to them + */ + winPrivWinPtr pParentPriv, pWinPriv; + + winDebug("winCreateWindowsChildWindow - pWin:%p XID:0x%x\n", pWin, + pWin->drawable.id); + + winInitMultiWindowClass(); + + assert(pParent); + + pParentPriv = winGetWindowPriv(pParent); + pWinPriv = winGetWindowPriv(pWin); + + iX = pWin->drawable.x - pParent->drawable.x; + iY = pWin->drawable.y - pParent->drawable.y; + iWidth = pWin->drawable.width; + iHeight = pWin->drawable.height; + + winDebug + ("winCreateWindowsChildWindow - parent pWin:%p XID:0x%08x hWnd:0x%p\n", + pParent, pParent->drawable.id, pParentPriv->hWnd); + winDebug("winCreateWindowsChildWindow - %dx%d @ %dx%d\n", iWidth, iHeight, + iX, iY); + + /* Create the window */ + hWnd = CreateWindowExA(dwExStyle, /* Extended styles */ + WINDOW_CLASS_X_CHILD, /* Class name */ + WINDOW_TITLE_X, /* Window name */ + dwStyle, /* Styles */ + iX, /* Horizontal position */ + iY, /* Vertical position */ + iWidth, /* Right edge */ + iHeight, /* Bottom edge */ + pParentPriv->hWnd, /* parent window */ + (HMENU) NULL, /* No menu */ + GetModuleHandle(NULL), /* Instance handle */ + pWin); /* ScreenPrivates */ + if (hWnd == NULL) { + ErrorF("winCreateWindowsChildWindow - CreateWindowExA () failed: %d\n", + (int) GetLastError()); + } + winDebug("winCreateWindowsChildWindow - hwnd 0x%p\n", hWnd); + pWinPriv->hWnd = hWnd; + + SetProp(hWnd, WIN_WID_PROP, (HANDLE) (INT_PTR) winGetWindowID(pWin)); +} + +/* + * winCreateWindowsWindow - Create a Windows window associated with an X window + */ + +void +winCreateWindowsWindow(WindowPtr pWin) +{ + winDebug("winCreateWindowsWindow - pWin:%p XID:0x%x \n", pWin, + pWin->drawable.id); + + if (isToplevelWindow(pWin)) { + winCreateWindowsTopLevelWindow(pWin); + } + else { + winCreateWindowsChildWindow(pWin); + } +} + +static int +winDestroyChildWindowsWindow(WindowPtr pWin, void *data) +{ + winWindowPriv(pWin); + + winDebug("winDestroyChildWindowsWindow - pWin:%p XID:0x%x \n", pWin, + pWin->drawable.id); + + /* Null our handle to the Window so referencing it will cause an error */ + pWinPriv->hWnd = NULL; + +#ifdef XWIN_GLX_WINDOWS + /* No longer note WGL used on this window */ + pWinPriv->fWglUsed = FALSE; +#endif + + return WT_WALKCHILDREN; /* continue enumeration */ } Bool winInDestroyWindowsWindow = FALSE; @@ -617,6 +807,7 @@ winDestroyWindowsWindow(WindowPtr pWin) BOOL oldstate = winInDestroyWindowsWindow; HICON hIcon; HICON hIconSm; + HWND hWnd; winDebug("winDestroyWindowsWindow - pWin:%p XID:0x%x \n", pWin, pWin->drawable.id); @@ -631,21 +822,20 @@ winDestroyWindowsWindow(WindowPtr pWin) hIcon = (HICON) SendMessage(pWinPriv->hWnd, WM_GETICON, ICON_BIG, 0); hIconSm = (HICON) SendMessage(pWinPriv->hWnd, WM_GETICON, ICON_SMALL, 0); - /* Destroy the Windows window */ - DestroyWindow(pWinPriv->hWnd); + hWnd = pWinPriv->hWnd; - /* Null our handle to the Window so referencing it will cause an error */ - pWinPriv->hWnd = NULL; + /* DestroyWindow() implicitly destroys all child windows, + so first walk over the child tree of this window, clearing + any hWnds */ + TraverseTree(pWin, winDestroyChildWindowsWindow, 0); + + /* Destroy the Windows window */ + DestroyWindow(hWnd); /* Destroy any icons we created for this window */ winDestroyIcon(hIcon); winDestroyIcon(hIconSm); -#ifdef XWIN_GLX_WINDOWS - /* No longer note WGL used on this window */ - pWinPriv->fWglUsed = FALSE; -#endif - /* Process all messages on our queue */ while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if (g_hDlgDepthChange == 0 || !IsDialogMessage(g_hDlgDepthChange, &msg)) { @@ -667,29 +857,58 @@ static void winUpdateWindowsWindow(WindowPtr pWin) { winWindowPriv(pWin); - HWND hWnd = pWinPriv->hWnd; #if CYGMULTIWINDOW_DEBUG ErrorF("winUpdateWindowsWindow\n"); #endif - /* Check if the Windows window's parents have been destroyed */ - if (pWin->parent != NULL && pWin->parent->parent == NULL && pWin->mapped) { - /* Create the Windows window if it has been destroyed */ - if (hWnd == NULL) { - winCreateWindowsWindow(pWin); - assert(pWinPriv->hWnd != NULL); + /* Ignore the root window */ + if (pWin->parent == NULL) + return; + + /* If it's mapped */ + if (pWin->mapped) { + /* If it's a top-level window */ + if (isToplevelWindow(pWin)) { + /* Create the Windows window if needed */ + if (pWinPriv->hWnd == NULL) { + winCreateWindowsWindow(pWin); + assert(pWinPriv->hWnd != NULL); + } + + /* Display the window without activating it */ + if (pWin->drawable.class != InputOnly) + ShowWindow(pWinPriv->hWnd, SW_SHOWNOACTIVATE); + + } + /* It's not a top-level window, but we created a window for GLX */ + else if (pWinPriv->hWnd) { + winPrivWinPtr pParentPriv = winGetWindowPriv(pWin->parent); + + /* XXX: This really belongs in winReparentWindow ??? */ + /* XXX: this assumes parent window has been made to exist */ + assert(pParentPriv->hWnd); + + /* Ensure we have the correct parent and position if reparented */ + SetParent(pWinPriv->hWnd, pParentPriv->hWnd); + SetWindowPos(pWinPriv->hWnd, NULL, + pWin->drawable.x - pWin->parent->drawable.x, + pWin->drawable.y - pWin->parent->drawable.y, 0, 0, + SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW); } - /* Display the window without activating it */ - if (pWin->drawable.class != InputOnly) - ShowWindow(pWinPriv->hWnd, SW_SHOWNOACTIVATE); + /* If it's top level, or a GLX window which has already been created getting mapped, show it */ + if (pWinPriv->hWnd != NULL) { + /* Display the window without activating it */ + if (pWin->drawable.class != InputOnly) + ShowWindow(pWinPriv->hWnd, SW_SHOWNOACTIVATE); - /* Send first paint message */ - UpdateWindow(pWinPriv->hWnd); + /* Send first paint message */ + UpdateWindow(pWinPriv->hWnd); + } } - else if (hWnd != NULL) { - /* Destroy the Windows window if its parents are destroyed */ + else if (pWinPriv->hWnd != NULL) { + /* If it's been reparented to an unmapped window when previously mapped, destroy the Windows window */ winDestroyWindowsWindow(pWin); assert(pWinPriv->hWnd == NULL); } @@ -793,56 +1012,6 @@ winReorderWindowsMultiWindow(void) } /* - * winMinimizeWindow - Minimize in response to WM_CHANGE_STATE - */ - -void -winMinimizeWindow(Window id) -{ - WindowPtr pWin; - winPrivWinPtr pWinPriv; - -#ifdef XWIN_MULTIWINDOWEXTWM - win32RootlessWindowPtr pRLWinPriv; -#endif - HWND hWnd; - ScreenPtr pScreen = NULL; - winPrivScreenPtr pScreenPriv = NULL; - -#if CYGWINDOWING_DEBUG - ErrorF("winMinimizeWindow\n"); -#endif - - dixLookupResourceByType((void *) &pWin, id, RT_WINDOW, NullClient, - DixUnknownAccess); - if (!pWin) { - ErrorF("%s: NULL pWin. Leaving\n", __FUNCTION__); - return; - } - - pScreen = pWin->drawable.pScreen; - if (pScreen) - pScreenPriv = winGetScreenPriv(pScreen); - -#ifdef XWIN_MULTIWINDOWEXTWM - if (pScreenPriv && pScreenPriv->pScreenInfo->fInternalWM) { - pRLWinPriv = - (win32RootlessWindowPtr) RootlessFrameForWindow(pWin, FALSE); - hWnd = pRLWinPriv->hWnd; - } - else -#else - if (pScreenPriv) -#endif - { - pWinPriv = winGetWindowPriv(pWin); - hWnd = pWinPriv->hWnd; - } - - ShowWindow(hWnd, SW_MINIMIZE); -} - -/* * CopyWindow - See Porting Layer Definition - p. 39 */ void @@ -926,6 +1095,14 @@ winAdjustXWindow(WindowPtr pWin, HWND hwnd) ErrorF("winAdjustXWindow\n"); #endif + if (!isToplevelWindow(pWin)) { +#if 1 + ErrorF + ("winAdjustXWindow - immediately return because not a top-level window\n"); +#endif + return 0; + } + if (IsIconic(hwnd)) { #if CYGWINDOWING_DEBUG ErrorF("\timmediately return because the window is iconized\n"); @@ -993,8 +1170,9 @@ winAdjustXWindow(WindowPtr pWin, HWND hwnd) vlist[2] = pDraw->width + dW; vlist[3] = pDraw->height + dH; #if CYGWINDOWING_DEBUG - ErrorF("\tConfigureWindow to (%ld, %ld) - %ldx%ld\n", vlist[0], vlist[1], - vlist[2], vlist[3]); + ErrorF("\tConfigureWindow to (%u, %u) - %ux%u\n", + (unsigned int)vlist[0], (unsigned int)vlist[1], + (unsigned int)vlist[2], (unsigned int)vlist[3]); #endif return ConfigureWindow(pWin, CWX | CWY | CWWidth | CWHeight, vlist, wClient(pWin)); diff --git a/hw/xwin/winmultiwindowwm.c b/hw/xwin/winmultiwindowwm.c index 6599dfba8..860df9ac9 100644 --- a/hw/xwin/winmultiwindowwm.c +++ b/hw/xwin/winmultiwindowwm.c @@ -30,10 +30,24 @@ * Colin Harrison */ +#ifndef WINVER +#define WINVER 0x0500 +#endif + /* X headers */ #ifdef HAVE_XWIN_CONFIG_H #include <xwin-config.h> #endif + +/* + * Including any server header might define the macro _XSERVER64 on 64 bit machines. + * That macro must _NOT_ be defined for Xlib client code, otherwise bad things happen. + * So let's undef that macro if necessary. + */ +#ifdef _XSERVER64 +#undef _XSERVER64 +#endif + #include <stdio.h> #include <stdlib.h> #include <unistd.h> @@ -48,20 +62,19 @@ #include <X11/X.h> #include <X11/Xatom.h> #include <X11/Xlib.h> -#include <X11/Xlocale.h> #include <X11/Xproto.h> #include <X11/Xutil.h> #include <X11/cursorfont.h> +#include <X11/extensions/Xcomposite.h> #include <X11/Xwindows.h> /* Local headers */ #include "winwindow.h" #include "winprefs.h" #include "window.h" -#include "pixmapstr.h" -#include "windowstr.h" #include "winglobals.h" #include "windisplay.h" +#include "winmultiwindowicons.h" #ifdef XWIN_MULTIWINDOWEXTWM #include <X11/extensions/windowswmstr.h> @@ -78,6 +91,9 @@ extern void winDebug(const char *format, ...); extern void winReshapeMultiWindow(WindowPtr pWin); extern void winUpdateRgnMultiWindow(WindowPtr pWin); +extern void winUpdateIcon(HWND hWnd, Display * pDisplay, Window id, HICON hIconNew); +extern void winSetAuthorization(void); +extern void winUpdateWindowPosition(HWND hWnd, HWND * zstyle); #ifndef CYGDEBUG #define CYGDEBUG NO @@ -115,11 +131,22 @@ typedef struct _WMMsgQueueRec { typedef struct _WMInfo { Display *pDisplay; WMMsgQueueRec wmMsgQueue; + Atom atmUTF8String; Atom atmWmProtos; Atom atmWmDelete; Atom atmWmTakeFocus; Atom atmPrivMap; + Atom atmNetWmName; + Atom atmCurrentDesktop; + Atom atmNumberDesktops; + Atom atmDesktopNames; + Atom atmWmState; + Atom atmNetWmState; + Atom atmHiddenState; + Atom atmVertMaxState; + Atom atmHorzMaxState; Bool fAllowOtherWM; + Bool fCompositeWM; } WMInfoRec, *WMInfoPtr; typedef struct _WMProcArgRec { @@ -149,7 +176,7 @@ static Bool InitQueue(WMMsgQueuePtr pQueue); static void - GetWindowName(Display * pDpy, Window iWin, char **ppWindowName); + GetWindowName(Display * pDpy, Window iWin, char **ppWindowName, Atom atmNetWmName); static int SendXMessage(Display * pDisplay, Window iWin, Atom atmType, long nData); @@ -173,6 +200,9 @@ static int static int winMultiWindowXMsgProcIOErrorHandler(Display * pDisplay); +static void +winMultiWindowThreadExit(void *arg); + static int winRedirectErrorHandler(Display * pDisplay, XErrorEvent * pErr); @@ -190,10 +220,10 @@ CheckAnotherWindowManager(Display * pDisplay, DWORD dwScreen, Bool fAllowOtherWM); static void - winApplyHints(Display * pDisplay, Window iWindow, HWND hWnd, HWND * zstyle); + winApplyUrgency(Display * pDisplay, Window iWindow, HWND hWnd); -void - winUpdateWindowPosition(HWND hWnd, HWND * zstyle); +static void + winApplyHints(WMInfoPtr pWMInfo, Window iWindow, HWND hWnd, HWND * zstyle, Bool onCreate); /* * Local globals @@ -210,6 +240,64 @@ static Bool redirectError = FALSE; static Bool g_fAnotherWMRunning = FALSE; /* + * Translate msg id to text, for debug purposes + */ + +static const char * +MessageName(winWMMessagePtr msg) +{ + switch (msg->msg) + { + case WM_WM_MOVE: + return "WM_WM_MOVE"; + break; + case WM_WM_SIZE: + return "WM_WM_SIZE"; + break; + case WM_WM_RAISE: + return "WM_WM_RAISE"; + break; + case WM_WM_LOWER: + return "WM_WM_LOWER"; + break; + case WM_WM_UNMAP: + return "WM_WM_UNMAP"; + break; + case WM_WM_KILL: + return "WM_WM_KILL"; + break; + case WM_WM_ACTIVATE: + return "WM_WM_ACTIVATE"; + break; + case WM_WM_NAME_EVENT: + return "WM_WM_NAME_EVENT"; + break; + case WM_WM_ICON_EVENT: + return "WM_WM_ICON_EVENT"; + break; + case WM_WM_CHANGE_STATE: + return "WM_WM_CHANGE_STATE"; + break; + case WM_WM_MAP: + return "WM_WM_MAP"; + break; + case WM_WM_MAP_UNMANAGED: + return "WM_WM_MAP_UNMANAGED"; + break; + case WM_WM_MAP_MANAGED: + return "WM_WM_MAP_MANAGED"; + break; + case WM_WM_HINTS_EVENT: + return "WM_WM_HINTS_EVENT"; + break; + default: + return "Unknown Message"; + break; + } +} + + +/* * PushMessage - Push a message onto the queue */ @@ -231,44 +319,6 @@ PushMessage(WMMsgQueuePtr pQueue, WMMsgNodePtr pNode) pQueue->pHead = pNode; } -#if 0 - switch (pNode->msg.msg) { - case WM_WM_MOVE: - ErrorF("\tWM_WM_MOVE\n"); - break; - case WM_WM_SIZE: - ErrorF("\tWM_WM_SIZE\n"); - break; - case WM_WM_RAISE: - ErrorF("\tWM_WM_RAISE\n"); - break; - case WM_WM_LOWER: - ErrorF("\tWM_WM_LOWER\n"); - break; - case WM_WM_MAP: - ErrorF("\tWM_WM_MAP\n"); - break; - case WM_WM_MAP2: - ErrorF("\tWM_WM_MAP2\n"); - break; - case WM_WM_MAP3: - ErrorF("\tWM_WM_MAP3\n"); - break; - case WM_WM_UNMAP: - ErrorF("\tWM_WM_UNMAP\n"); - break; - case WM_WM_KILL: - ErrorF("\tWM_WM_KILL\n"); - break; - case WM_WM_ACTIVATE: - ErrorF("\tWM_WM_ACTIVATE\n"); - break; - default: - ErrorF("\tUnknown Message.\n"); - break; - } -#endif - /* Increase the count of elements in the queue by one */ ++(pQueue->nQueueSize); @@ -432,14 +482,10 @@ Xutf8TextPropertyToString(Display * pDisplay, XTextProperty * xtp) */ static void -GetWindowName(Display * pDisplay, Window iWin, char **ppWindowName) +GetWindowName(Display * pDisplay, Window iWin, char **ppWindowName, Atom atmNetWmName) { int nResult; - XTextProperty xtpWindowName; - XTextProperty xtpClientMachine; - char *pszWindowName; - char *pszClientMachine; - char hostname[HOST_NAME_MAX + 1]; + char *pszWindowName = NULL; #if CYGMULTIWINDOW_DEBUG ErrorF("GetWindowName\n"); @@ -448,35 +494,75 @@ GetWindowName(Display * pDisplay, Window iWin, char **ppWindowName) /* Intialize ppWindowName to NULL */ *ppWindowName = NULL; - /* Try to get window name */ - nResult = XGetWMName(pDisplay, iWin, &xtpWindowName); - if (!nResult || !xtpWindowName.value || !xtpWindowName.nitems) { + /* Try to get window name from _NET_WM_NAME */ + { + char *utf8WindowName; + Atom type; + int format; + unsigned long nitems, after; + + nResult = XGetWindowProperty(pDisplay, iWin, atmNetWmName, + 0, INT_MAX, False, + AnyPropertyType, &type, &format, + &nitems, &after, + (unsigned char **)&utf8WindowName); + if ((nResult == Success) && (type != None)) + { + pszWindowName = strdup(utf8WindowName); + XFree(utf8WindowName); + } + } + + /* Otherwise, try to get window name from WM_NAME */ + if (!pszWindowName) + { + XTextProperty xtpWindowName; + + nResult = XGetWMName(pDisplay, iWin, &xtpWindowName); + if (!nResult || !xtpWindowName.value || !xtpWindowName.nitems) { #if CYGMULTIWINDOW_DEBUG - ErrorF("GetWindowName - XGetWMName failed. No name.\n"); + ErrorF("GetWindowName - XGetWMName failed. No name.\n"); #endif - return; - } + return; + } + + pszWindowName = Xutf8TextPropertyToString(pDisplay, &xtpWindowName); + XFree(xtpWindowName.value); + } - pszWindowName = Xutf8TextPropertyToString(pDisplay, &xtpWindowName); - XFree(xtpWindowName.value); + /* return the window name, unless... */ + *ppWindowName = pszWindowName; if (g_fHostInTitle) { + XTextProperty xtpClientMachine; + /* Try to get client machine name */ nResult = XGetWMClientMachine(pDisplay, iWin, &xtpClientMachine); if (nResult && xtpClientMachine.value && xtpClientMachine.nitems) { + char *pszClientMachine; + char *pszClientHostname; + char *dot; + char hostname[HOST_NAME_MAX + 1]; + pszClientMachine = Xutf8TextPropertyToString(pDisplay, &xtpClientMachine); XFree(xtpClientMachine.value); + /* If client machine name looks like a FQDN, find the hostname */ + pszClientHostname = strdup(pszClientMachine); + dot = strchr(pszClientHostname, '.'); + if (dot) + *dot = '\0'; + /* - If we have a client machine name - and it's not the local host name + If we have a client machine hostname + and it's not the local hostname and it's not already in the window title... */ - if (strlen(pszClientMachine) && + if (strlen(pszClientHostname) && !gethostname(hostname, HOST_NAME_MAX + 1) && - strcmp(hostname, pszClientMachine) && - (strstr(pszWindowName, pszClientMachine) == 0)) { + strcmp(hostname, pszClientHostname) && + (strstr(pszWindowName, pszClientHostname) == 0)) { /* ... add '@<clientmachine>' to end of window name */ *ppWindowName = malloc(strlen(pszWindowName) + @@ -486,15 +572,12 @@ GetWindowName(Display * pDisplay, Window iWin, char **ppWindowName) strcat(*ppWindowName, pszClientMachine); free(pszWindowName); - free(pszClientMachine); - - return; } + + free(pszClientMachine); + free(pszClientHostname); } } - - /* otherwise just return the window name */ - *ppWindowName = pszWindowName; } /* @@ -528,6 +611,7 @@ SendXMessage(Display * pDisplay, Window iWin, Atom atmType, long nData) XEvent e; /* Prepare the X event structure */ + memset(&e, 0, sizeof(e)); e.type = ClientMessage; e.xclient.window = iWin; e.xclient.message_type = atmType; @@ -596,7 +680,7 @@ UpdateName(WMInfoPtr pWMInfo, Window iWindow) char *pszWindowName; /* Get the X windows window name */ - GetWindowName(pWMInfo->pDisplay, iWindow, &pszWindowName); + GetWindowName(pWMInfo->pDisplay, iWindow, &pszWindowName, pWMInfo->atmNetWmName); if (pszWindowName) { /* Convert from UTF-8 to wide char */ @@ -661,7 +745,7 @@ UpdateIcon(WMInfoPtr pWMInfo, Window iWindow) */ static void -UpdateStyle(WMInfoPtr pWMInfo, Window iWindow) +UpdateStyle(WMInfoPtr pWMInfo, Window iWindow, Bool onCreate) { HWND hWnd; HWND zstyle = HWND_NOTOPMOST; @@ -672,7 +756,7 @@ UpdateStyle(WMInfoPtr pWMInfo, Window iWindow) return; /* Determine the Window style, which determines borders and clipping region... */ - winApplyHints(pWMInfo->pDisplay, iWindow, hWnd, &zstyle); + winApplyHints(pWMInfo, iWindow, hWnd, &zstyle, onCreate); winUpdateWindowPosition(hWnd, &zstyle); /* Apply the updated window style, without changing it's show or activation state */ @@ -693,6 +777,151 @@ UpdateStyle(WMInfoPtr pWMInfo, Window iWindow) winShowWindowOnTaskbar(hWnd, (GetWindowLongPtr(hWnd, GWL_EXSTYLE) & WS_EX_APPWINDOW) ? TRUE : FALSE); + + /* Check urgency hint */ + winApplyUrgency(pWMInfo->pDisplay, iWindow, hWnd); +} + +/* + * Updates the state of a HWND + */ + +static void +UpdateState(WMInfoPtr pWMInfo, Window iWindow, int state) +{ + HWND hWnd; + int current_state = -1; + + winDebug("UpdateState: iWindow 0x%08x %d\n", (int)iWindow, state); + + hWnd = getHwnd(pWMInfo, iWindow); + if (hWnd) + { + // Keep track of the Window state, do nothing if it's not changing + current_state = (intptr_t)GetProp(hWnd, WIN_STATE_PROP); + + if (current_state == state) + return; + + SetProp(hWnd, WIN_STATE_PROP, (HANDLE)(intptr_t)state); + + switch (state) + { + case IconicState: + ShowWindow(hWnd, SW_SHOWMINNOACTIVE); + break; + + case ZoomState: + // ZoomState should only come internally, not from a client + // There doesn't seem to be a SW_SHOWMAXNOACTIVE, but Window should + // already displayed correctly. + break; + + case NormalState: + ShowWindow(hWnd, SW_SHOWNA); + break; + + case WithdrawnState: + ShowWindow(hWnd, SW_HIDE); + break; + } + } + + // Update WM_STATE property + { + // ZoomState is obsolete in ICCCM, so map it to NormalState + int icccm_state = state; + int icccm_current_state = current_state; + + if (icccm_state == ZoomState) + icccm_state = NormalState; + + if (icccm_current_state == ZoomState) + icccm_current_state = NormalState; + + // Don't change property unnecessarily + // + // (Note that we do not take notice of WM_STATE PropertyNotify, only + // WM_CHANGE_STATE ClientMessage, so this should not cause the state to + // change itself) + if (icccm_current_state != icccm_state) + { + struct + { + CARD32 state; + XID icon; + } wmstate; + + wmstate.state = icccm_state; + wmstate.icon = None; + + XChangeProperty(pWMInfo->pDisplay, iWindow, pWMInfo->atmWmState, + pWMInfo->atmWmState, 32, PropModeReplace, + (unsigned char *) &wmstate, + sizeof(wmstate)/sizeof(int)); + } + } + + // Update _NET_WM_STATE property + if (state == WithdrawnState) { + XDeleteProperty(pWMInfo->pDisplay, iWindow, pWMInfo->atmNetWmState); + } + else { + Atom type, *pAtom = NULL; + int format; + unsigned long nitems = 0, left; + + XGetWindowProperty(pWMInfo->pDisplay, iWindow, + pWMInfo->atmNetWmState, 0L, + MAXINT, False, XA_ATOM, &type, &format, + &nitems, &left, + (unsigned char **) &pAtom); + { + unsigned long i, o = 0; + Atom netwmstate[nitems + 2]; + Bool changed = FALSE; + + // Make a copy with _NET_WM_HIDDEN, _NET_WM_MAXIMIZED_{VERT,HORZ} + // removed + for (i = 0; i < nitems; i++) { + if ((pAtom[i] != pWMInfo->atmHiddenState) && + (pAtom[i] != pWMInfo->atmVertMaxState) && + (pAtom[i] != pWMInfo->atmHorzMaxState)) + netwmstate[o++] = pAtom[i]; + } + XFree(pAtom); + + // if iconized, add _NET_WM_HIDDEN + if (state == IconicState) { + netwmstate[o++] = pWMInfo->atmHiddenState; + } + + // if maximized, add _NET_WM_MAXIMIZED_{VERT,HORZ} + if (state == ZoomState) { + netwmstate[o++] = pWMInfo->atmVertMaxState; + netwmstate[o++] = pWMInfo->atmHorzMaxState; + } + + // Don't change property unnecessarily + if (nitems != o) + changed = TRUE; + else + for (i = 0; i < nitems; i++) + { + if (pAtom[i] != netwmstate[i]) + { + changed = TRUE; + break; + } + } + + if (changed) + XChangeProperty(pWMInfo->pDisplay, iWindow, + pWMInfo->atmNetWmState, XA_ATOM, 32, + PropModeReplace, (unsigned char *) &netwmstate, + o); + } + } } #if 0 @@ -746,6 +975,8 @@ winMultiWindowWMProc(void *pArg) WMProcArgPtr pProcArg = (WMProcArgPtr) pArg; WMInfoPtr pWMInfo = pProcArg->pWMInfo; + pthread_cleanup_push(&winMultiWindowThreadExit, NULL); + /* Initialize the Window Manager */ winInitMultiWindowWM(pWMInfo, pProcArg); @@ -772,26 +1003,21 @@ winMultiWindowWMProc(void *pArg) } #if CYGMULTIWINDOW_DEBUG - ErrorF("winMultiWindowWMProc - %d ms MSG: %d ID: %d\n", - GetTickCount(), (int) pNode->msg.msg, (int) pNode->msg.dwID); + ErrorF("winMultiWindowWMProc - MSG: %s (%d) ID: %d\n", + MessageName(&(pNode->msg)), (int)pNode->msg.msg, (int)pNode->msg.dwID); #endif /* Branch on the message type */ switch (pNode->msg.msg) { #if 0 case WM_WM_MOVE: - ErrorF("\tWM_WM_MOVE\n"); break; case WM_WM_SIZE: - ErrorF("\tWM_WM_SIZE\n"); break; #endif case WM_WM_RAISE: -#if CYGMULTIWINDOW_DEBUG - ErrorF("\tWM_WM_RAISE\n"); -#endif /* Raise the window */ XRaiseWindow(pWMInfo->pDisplay, pNode->msg.iWindow); #if 0 @@ -800,18 +1026,12 @@ winMultiWindowWMProc(void *pArg) break; case WM_WM_LOWER: -#if CYGMULTIWINDOW_DEBUG - ErrorF("\tWM_WM_LOWER\n"); -#endif /* Lower the window */ XLowerWindow(pWMInfo->pDisplay, pNode->msg.iWindow); break; case WM_WM_MAP: -#if CYGMULTIWINDOW_DEBUG - ErrorF("\tWM_WM_MAP\n"); -#endif /* Put a note as to the HWND associated with this Window */ XChangeProperty(pWMInfo->pDisplay, pNode->msg.iWindow, pWMInfo->atmPrivMap, XA_INTEGER, 32, @@ -821,28 +1041,22 @@ winMultiWindowWMProc(void *pArg) UpdateIcon(pWMInfo, pNode->msg.iWindow); break; - case WM_WM_MAP2: -#if CYGMULTIWINDOW_DEBUG - ErrorF("\tWM_WM_MAP2\n"); -#endif + case WM_WM_MAP_UNMANAGED: XChangeProperty(pWMInfo->pDisplay, pNode->msg.iWindow, pWMInfo->atmPrivMap, XA_INTEGER, 32, PropModeReplace, (unsigned char *) &(pNode->msg.hwndWindow), sizeof(HWND)/4); break; - case WM_WM_MAP3: -#if CYGMULTIWINDOW_DEBUG - ErrorF("\tWM_WM_MAP3\n"); -#endif + case WM_WM_MAP_MANAGED: /* Put a note as to the HWND associated with this Window */ XChangeProperty(pWMInfo->pDisplay, pNode->msg.iWindow, pWMInfo->atmPrivMap, XA_INTEGER, 32, PropModeReplace, (unsigned char *) &(pNode->msg.hwndWindow), sizeof(HWND)/4); UpdateName(pWMInfo, pNode->msg.iWindow); + UpdateStyle(pWMInfo, pNode->msg.iWindow, TRUE); UpdateIcon(pWMInfo, pNode->msg.iWindow); - UpdateStyle(pWMInfo, pNode->msg.iWindow); /* Reshape */ @@ -858,18 +1072,12 @@ winMultiWindowWMProc(void *pArg) break; case WM_WM_UNMAP: -#if CYGMULTIWINDOW_DEBUG - ErrorF("\tWM_WM_UNMAP\n"); -#endif /* Unmap the window */ XUnmapWindow(pWMInfo->pDisplay, pNode->msg.iWindow); break; case WM_WM_KILL: -#if CYGMULTIWINDOW_DEBUG - ErrorF("\tWM_WM_KILL\n"); -#endif { /* --- */ if (IsWmProtocolAvailable(pWMInfo->pDisplay, @@ -884,9 +1092,6 @@ winMultiWindowWMProc(void *pArg) break; case WM_WM_ACTIVATE: -#if CYGMULTIWINDOW_DEBUG - ErrorF("\tWM_WM_ACTIVATE\n"); -#endif /* Set the input focus */ /* @@ -939,13 +1144,12 @@ winMultiWindowWMProc(void *pArg) if (attr.override_redirect) break; - UpdateStyle(pWMInfo, pNode->msg.iWindow); + UpdateStyle(pWMInfo, pNode->msg.iWindow, FALSE); } break; case WM_WM_CHANGE_STATE: - /* Minimize the window in Windows */ - winMinimizeWindow(pNode->msg.iWindow); + UpdateState(pWMInfo, pNode->msg.iWindow, pNode->msg.dwID); break; default: @@ -973,6 +1177,9 @@ winMultiWindowWMProc(void *pArg) #if CYGMULTIWINDOW_DEBUG ErrorF("-winMultiWindowWMProc ()\n"); #endif + + pthread_cleanup_pop(0); + return NULL; } @@ -989,6 +1196,7 @@ winMultiWindowXMsgProc(void *pArg) int iRetries; XEvent event; Atom atmWmName; + Atom atmNetWmName; Atom atmWmHints; Atom atmWmChange; Atom atmNetWmIcon; @@ -996,6 +1204,8 @@ winMultiWindowXMsgProc(void *pArg) int iReturn; XIconSize *xis; + pthread_cleanup_push(&winMultiWindowThreadExit, NULL); + winDebug("winMultiWindowXMsgProc - Hello\n"); /* Check that argument pointer is not invalid */ @@ -1004,7 +1214,7 @@ winMultiWindowXMsgProc(void *pArg) pthread_exit(NULL); } - ErrorF("winMultiWindowXMsgProc - Calling pthread_mutex_lock ()\n"); + winDebug("winMultiWindowXMsgProc - Calling pthread_mutex_lock ()\n"); /* Grab the server started mutex - pause until we get it */ iReturn = pthread_mutex_lock(pProcArg->ppmServerStarted); @@ -1014,23 +1224,12 @@ winMultiWindowXMsgProc(void *pArg) pthread_exit(NULL); } - ErrorF("winMultiWindowXMsgProc - pthread_mutex_lock () returned.\n"); - - /* Allow multiple threads to access Xlib */ - if (XInitThreads() == 0) { - ErrorF("winMultiWindowXMsgProc - XInitThreads () failed. Exiting.\n"); - pthread_exit(NULL); - } - - /* See if X supports the current locale */ - if (XSupportsLocale() == False) { - ErrorF("winMultiWindowXMsgProc - Warning: locale not supported by X\n"); - } + winDebug("winMultiWindowXMsgProc - pthread_mutex_lock () returned.\n"); /* Release the server started mutex */ pthread_mutex_unlock(pProcArg->ppmServerStarted); - ErrorF("winMultiWindowXMsgProc - pthread_mutex_unlock () returned.\n"); + winDebug("winMultiWindowXMsgProc - pthread_mutex_unlock () returned.\n"); /* Install our error handler */ XSetErrorHandler(winMultiWindowXMsgProcErrorHandler); @@ -1109,12 +1308,13 @@ winMultiWindowXMsgProc(void *pArg) xis->max_width = xis->max_height = 48; xis->width_inc = xis->height_inc = 16; XSetIconSizes(pProcArg->pDisplay, - RootWindow(pProcArg->pDisplay, pProcArg->dwScreen), + XRootWindow(pProcArg->pDisplay, pProcArg->dwScreen), xis, 1); XFree(xis); } atmWmName = XInternAtom(pProcArg->pDisplay, "WM_NAME", False); + atmNetWmName = XInternAtom(pProcArg->pDisplay, "_NET_WM_NAME", False); atmWmHints = XInternAtom(pProcArg->pDisplay, "WM_HINTS", False); atmWmChange = XInternAtom(pProcArg->pDisplay, "WM_CHANGE_STATE", False); atmNetWmIcon = XInternAtom(pProcArg->pDisplay, "_NET_WM_ICON", False); @@ -1124,14 +1324,36 @@ winMultiWindowXMsgProc(void *pArg) atmNormalHints = XInternAtom(pProcArg->pDisplay, "WM_NORMAL_HINTS", False); /* - iiimxcf had a bug until 2009-04-27, assuming that the - WM_STATE atom exists, causing clients to fail with - a BadAtom X error if it doesn't. - - Since this is on in the default Solaris 10 install, - workaround this by making sure it does exist... + Enable Composite extension and redirect subwindows of the root window */ - XInternAtom(pProcArg->pDisplay, "WM_STATE", 0); + if (pProcArg->pWMInfo->fCompositeWM) + { + int composite_event_base, composite_error_base; + if (XCompositeQueryExtension(pProcArg->pDisplay, + &composite_event_base, + &composite_error_base)) + { + XCompositeRedirectSubwindows(pProcArg->pDisplay, + XRootWindow(pProcArg->pDisplay, + pProcArg->dwScreen), + CompositeRedirectAutomatic); + + /* + 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"); + } + } /* Loop until we explicitly break out */ while (1) { @@ -1225,6 +1447,13 @@ winMultiWindowXMsgProc(void *pArg) } } } + else if (event.type == UnmapNotify) { + msg.msg = WM_WM_CHANGE_STATE; + msg.iWindow = event.xunmap.window; + msg.dwID = WithdrawnState; + + winSendMessageToWM(pProcArg->pWMInfo, &msg); + } else if (event.type == ConfigureNotify) { if (!event.xconfigure.send_event) { /* @@ -1248,7 +1477,12 @@ winMultiWindowXMsgProc(void *pArg) } } else if (event.type == PropertyNotify) { - if (event.xproperty.atom == atmWmName) { + char *atomName = + XGetAtomName(pProcArg->pDisplay, event.xproperty.atom); + winDebug("winMultiWindowXMsgProc: PropertyNotify %s\n", atomName); + XFree(atomName); + if ((event.xproperty.atom == atmWmName) || + (event.xproperty.atom == atmNetWmName)) { memset(&msg, 0, sizeof(msg)); msg.msg = WM_WM_NAME_EVENT; @@ -1296,13 +1530,14 @@ winMultiWindowXMsgProc(void *pArg) msg.msg = WM_WM_CHANGE_STATE; msg.iWindow = event.xclient.window; + msg.dwID = event.xclient.data.l[0]; winSendMessageToWM(pProcArg->pWMInfo, &msg); } } XCloseDisplay(pProcArg->pDisplay); - pthread_exit(NULL); + pthread_cleanup_pop(0); return NULL; } @@ -1317,7 +1552,7 @@ winInitWM(void **ppWMInfo, pthread_t * ptWMProc, pthread_t * ptXMsgProc, pthread_mutex_t * ppmServerStarted, - int dwScreen, HWND hwndScreen, BOOL allowOtherWM) + int dwScreen, HWND hwndScreen, BOOL allowOtherWM, BOOL compositeWM) { WMProcArgPtr pArg = malloc(sizeof(WMProcArgRec)); WMInfoPtr pWMInfo = malloc(sizeof(WMInfoRec)); @@ -1340,6 +1575,7 @@ winInitWM(void **ppWMInfo, /* Set a return pointer to the Window Manager info structure */ *ppWMInfo = pWMInfo; pWMInfo->fAllowOtherWM = allowOtherWM; + pWMInfo->fCompositeWM = compositeWM; /* Setup the argument structure for the thread function */ pArg->dwScreen = dwScreen; @@ -1387,6 +1623,8 @@ winInitMultiWindowWM(WMInfoPtr pWMInfo, WMProcArgPtr pProcArg) int iRetries = 0; char pszDisplay[512]; int iReturn; + int data; + const char buf[] = "Desktop"; winDebug("winInitMultiWindowWM - Hello\n"); @@ -1396,7 +1634,7 @@ winInitMultiWindowWM(WMInfoPtr pWMInfo, WMProcArgPtr pProcArg) pthread_exit(NULL); } - ErrorF("winInitMultiWindowWM - Calling pthread_mutex_lock ()\n"); + winDebug("winInitMultiWindowWM - Calling pthread_mutex_lock ()\n"); /* Grab our garbage mutex to satisfy pthread_cond_wait */ iReturn = pthread_mutex_lock(pProcArg->ppmServerStarted); @@ -1406,23 +1644,12 @@ winInitMultiWindowWM(WMInfoPtr pWMInfo, WMProcArgPtr pProcArg) pthread_exit(NULL); } - ErrorF("winInitMultiWindowWM - pthread_mutex_lock () returned.\n"); - - /* Allow multiple threads to access Xlib */ - if (XInitThreads() == 0) { - ErrorF("winInitMultiWindowWM - XInitThreads () failed. Exiting.\n"); - pthread_exit(NULL); - } - - /* See if X supports the current locale */ - if (XSupportsLocale() == False) { - ErrorF("winInitMultiWindowWM - Warning: Locale not supported by X.\n"); - } + winDebug("winInitMultiWindowWM - pthread_mutex_lock () returned.\n"); /* Release the server started mutex */ pthread_mutex_unlock(pProcArg->ppmServerStarted); - ErrorF("winInitMultiWindowWM - pthread_mutex_unlock () returned.\n"); + winDebug("winInitMultiWindowWM - pthread_mutex_unlock () returned.\n"); /* Install our error handler */ XSetErrorHandler(winMultiWindowWMErrorHandler); @@ -1481,22 +1708,59 @@ winInitMultiWindowWM(WMInfoPtr pWMInfo, WMProcArgPtr pProcArg) "successfully opened the display.\n"); /* Create some atoms */ + pWMInfo->atmUTF8String = XInternAtom(pWMInfo->pDisplay, + "UTF8_STRING", False); pWMInfo->atmWmProtos = XInternAtom(pWMInfo->pDisplay, "WM_PROTOCOLS", False); pWMInfo->atmWmDelete = XInternAtom(pWMInfo->pDisplay, "WM_DELETE_WINDOW", False); pWMInfo->atmWmTakeFocus = XInternAtom(pWMInfo->pDisplay, "WM_TAKE_FOCUS", False); - pWMInfo->atmPrivMap = XInternAtom(pWMInfo->pDisplay, WINDOWSWM_NATIVE_HWND, False); + pWMInfo->atmNetWmName = XInternAtom(pWMInfo->pDisplay, + "_NET_WM_NAME", False); + pWMInfo->atmCurrentDesktop = XInternAtom(pWMInfo->pDisplay, + "_NET_CURRENT_DESKTOP", False); + pWMInfo->atmNumberDesktops = XInternAtom(pWMInfo->pDisplay, + "_NET_NUMBER_OF_DESKTOPS", False); + pWMInfo->atmDesktopNames = XInternAtom(pWMInfo->pDisplay, + "_NET_DESKTOP_NAMES", False); + pWMInfo->atmWmState = XInternAtom(pWMInfo->pDisplay, + "WM_STATE", False); + pWMInfo->atmNetWmState = XInternAtom(pWMInfo->pDisplay, + "_NET_WM_STATE", False); + pWMInfo->atmHiddenState = XInternAtom(pWMInfo->pDisplay, + "_NET_WM_STATE_HIDDEN", False); + pWMInfo->atmVertMaxState = XInternAtom(pWMInfo->pDisplay, + "_NET_WM_STATE_MAXIMIZED_VERT", False); + pWMInfo->atmHorzMaxState = XInternAtom(pWMInfo->pDisplay, + "_NET_WM_STATE_MAXIMIZED_HORZ", False); + + /* + Set root window properties for describing multiple desktops to describe + the one desktop we have + */ + data = 0; + XChangeProperty(pWMInfo->pDisplay, XDefaultRootWindow(pWMInfo->pDisplay), + pWMInfo->atmCurrentDesktop, XA_CARDINAL, 32, + PropModeReplace, (unsigned char *) &data, 1); + + data = 1; + XChangeProperty(pWMInfo->pDisplay, XDefaultRootWindow(pWMInfo->pDisplay), + pWMInfo->atmNumberDesktops, XA_CARDINAL, 32, + PropModeReplace, (unsigned char *) &data, 1); + + XChangeProperty(pWMInfo->pDisplay, XDefaultRootWindow(pWMInfo->pDisplay), + pWMInfo->atmDesktopNames, pWMInfo->atmUTF8String, 8, + PropModeReplace, (unsigned char *) buf, strlen(buf)); if (1) { Cursor cursor = XCreateFontCursor(pWMInfo->pDisplay, XC_left_ptr); if (cursor) { XDefineCursor(pWMInfo->pDisplay, - DefaultRootWindow(pWMInfo->pDisplay), cursor); + XDefaultRootWindow(pWMInfo->pDisplay), cursor); XFreeCursor(pWMInfo->pDisplay, cursor); } } @@ -1512,7 +1776,7 @@ winSendMessageToWM(void *pWMInfo, winWMMessagePtr pMsg) WMMsgNodePtr pNode; #if CYGMULTIWINDOW_DEBUG - ErrorF("winSendMessageToWM ()\n"); + ErrorF("winSendMessageToWM %s\n", MessageName(pMsg)); #endif pNode = malloc(sizeof(WMMsgNodeRec)); @@ -1577,9 +1841,7 @@ winMultiWindowXMsgProcErrorHandler(Display * pDisplay, XErrorEvent * pErr) char pszErrorMsg[100]; XGetErrorText(pDisplay, pErr->error_code, pszErrorMsg, sizeof(pszErrorMsg)); -#if CYGMULTIWINDOW_DEBUG ErrorF("winMultiWindowXMsgProcErrorHandler - ERROR: %s\n", pszErrorMsg); -#endif return 0; } @@ -1605,6 +1867,17 @@ winMultiWindowXMsgProcIOErrorHandler(Display * pDisplay) } /* + * winMultiWindowThreadExit - Thread exit handler + */ + +static void +winMultiWindowThreadExit(void *arg) +{ + /* multiwindow client thread has exited, stop server as well */ + raise(SIGTERM); +} + +/* * Catch RedirectError to detect other window manager running */ @@ -1629,7 +1902,7 @@ CheckAnotherWindowManager(Display * pDisplay, DWORD dwScreen, */ redirectError = FALSE; XSetErrorHandler(winRedirectErrorHandler); - XSelectInput(pDisplay, RootWindow(pDisplay, dwScreen), + XSelectInput(pDisplay, XRootWindow(pDisplay, dwScreen), ResizeRedirectMask | SubstructureRedirectMask | ButtonPressMask); XSync(pDisplay, 0); @@ -1641,7 +1914,7 @@ CheckAnotherWindowManager(Display * pDisplay, DWORD dwScreen, If other WMs are not allowed, also select one of the events which only one client at a time is allowed to select, so other window managers won't start... */ - XSelectInput(pDisplay, RootWindow(pDisplay, dwScreen), + XSelectInput(pDisplay, XRootWindow(pDisplay, dwScreen), SubstructureNotifyMask | (!fAllowOtherWM ? ButtonPressMask : 0)); XSync(pDisplay, 0); @@ -1659,6 +1932,40 @@ winDeinitMultiWindowWM(void) g_shutdown = TRUE; } +static void +winApplyUrgency(Display * pDisplay, Window iWindow, HWND hWnd) +{ + XWMHints *hints = XGetWMHints(pDisplay, iWindow); + + if (hints) { + FLASHWINFO fwi; + + fwi.cbSize = sizeof(FLASHWINFO); + fwi.hwnd = hWnd; + + winDebug("winApplyUrgency: window 0x%08x has urgency hint %s\n", + iWindow, (hints->flags & XUrgencyHint) ? "on" : "off"); + + if (hints->flags & XUrgencyHint) { + DWORD count = 3; + + SystemParametersInfo(SPI_GETFOREGROUNDFLASHCOUNT, 0, &count, 0); + fwi.dwFlags = FLASHW_TRAY; + fwi.uCount = count; + fwi.dwTimeout = 0; + } + else { + fwi.dwFlags = FLASHW_STOP; + fwi.uCount = 0; + fwi.dwTimeout = 0; + } + + FlashWindowEx(&fwi); + + XFree(hints); + } +} + /* Windows window styles */ #define HINT_NOFRAME (1L<<0) #define HINT_BORDER (1L<<1) @@ -1673,18 +1980,18 @@ winDeinitMultiWindowWM(void) #define HINT_MIN (1L<<1) static void -winApplyHints(Display * pDisplay, Window iWindow, HWND hWnd, HWND * zstyle) +winApplyHints(WMInfoPtr pWMInfo, Window iWindow, HWND hWnd, HWND * zstyle, Bool onCreate) { - static Atom windowState, motif_wm_hints, windowType; - static Atom hiddenState, fullscreenState, belowState, aboveState, - skiptaskbarState; - static Atom dockWindow; + static Atom motif_wm_hints, windowType; + static Atom fullscreenState, belowState, aboveState, skiptaskbarState; + static Atom dockWindow, splashWindow; static int generation; Atom type, *pAtom = NULL; int format; unsigned long hint = 0, maxmin = 0, nitems = 0, left = 0; unsigned long style, exStyle; MwmHints *mwm_hint = NULL; + Display *pDisplay = pWMInfo->pDisplay; if (!hWnd) return; @@ -1693,30 +2000,32 @@ winApplyHints(Display * pDisplay, Window iWindow, HWND hWnd, HWND * zstyle) if (generation != serverGeneration) { generation = serverGeneration; - windowState = XInternAtom(pDisplay, "_NET_WM_STATE", False); motif_wm_hints = XInternAtom(pDisplay, "_MOTIF_WM_HINTS", False); windowType = XInternAtom(pDisplay, "_NET_WM_WINDOW_TYPE", False); - hiddenState = XInternAtom(pDisplay, "_NET_WM_STATE_HIDDEN", False); fullscreenState = XInternAtom(pDisplay, "_NET_WM_STATE_FULLSCREEN", False); belowState = XInternAtom(pDisplay, "_NET_WM_STATE_BELOW", False); aboveState = XInternAtom(pDisplay, "_NET_WM_STATE_ABOVE", False); dockWindow = XInternAtom(pDisplay, "_NET_WM_WINDOW_TYPE_DOCK", False); + splashWindow = XInternAtom(pDisplay, "_NET_WM_WINDOW_TYPE_SPLASH", False); skiptaskbarState = XInternAtom(pDisplay, "_NET_WM_STATE_SKIP_TASKBAR", False); } - if (XGetWindowProperty(pDisplay, iWindow, windowState, 0L, + if (XGetWindowProperty(pDisplay, iWindow, pWMInfo->atmNetWmState, 0L, MAXINT, False, XA_ATOM, &type, &format, &nitems, &left, (unsigned char **) &pAtom) == Success) { + Bool verMax = FALSE; + Bool horMax = FALSE; + if (pAtom ) { unsigned long i; for (i = 0; i < nitems; i++) { if (pAtom[i] == skiptaskbarState) hint |= HINT_SKIPTASKBAR; - if (pAtom[i] == hiddenState) + if (pAtom[i] == pWMInfo->atmHiddenState) maxmin |= HINT_MIN; else if (pAtom[i] == fullscreenState) maxmin |= HINT_MAX; @@ -1724,8 +2033,15 @@ winApplyHints(Display * pDisplay, Window iWindow, HWND hWnd, HWND * zstyle) *zstyle = HWND_BOTTOM; else if (pAtom[i] == aboveState) *zstyle = HWND_TOPMOST; + if (pAtom[i] == pWMInfo->atmVertMaxState) + verMax = TRUE; + if (pAtom[i] == pWMInfo->atmHorzMaxState) + horMax = TRUE; } + if (verMax && horMax) + maxmin |= HINT_MAX; + XFree(pAtom); } } @@ -1738,7 +2054,7 @@ winApplyHints(Display * pDisplay, Window iWindow, HWND hWnd, HWND * zstyle) if (mwm_hint && nitems == PropMwmHintsElements && (mwm_hint->flags & MwmHintsDecorations)) { if (!mwm_hint->decorations) - hint |= HINT_NOFRAME; + hint |= (HINT_NOFRAME | HINT_NOSYSMENU | HINT_NOMINIMIZE | HINT_NOMAXIMIZE); else if (!(mwm_hint->decorations & MwmDecorAll)) { if (mwm_hint->decorations & MwmDecorBorder) hint |= HINT_BORDER; @@ -1772,7 +2088,11 @@ winApplyHints(Display * pDisplay, Window iWindow, HWND hWnd, HWND * zstyle) (unsigned char **) &pAtom) == Success) { if (pAtom && nitems == 1) { if (*pAtom == dockWindow) { - hint = (hint & ~HINT_NOFRAME) | HINT_SIZEBOX; /* Xming puts a sizebox on dock windows */ + hint = (hint & ~HINT_NOFRAME) | HINT_SKIPTASKBAR | HINT_SIZEBOX; /* Xming puts a sizebox on dock windows */ + *zstyle = HWND_TOPMOST; + } + else if (*pAtom == splashWindow) { + hint |= (HINT_SKIPTASKBAR | HINT_NOSYSMENU | HINT_NOMINIMIZE | HINT_NOMAXIMIZE); *zstyle = HWND_TOPMOST; } } @@ -1785,11 +2105,17 @@ winApplyHints(Display * pDisplay, Window iWindow, HWND hWnd, HWND * zstyle) long supplied; if (normal_hint && - (XGetWMNormalHints(pDisplay, iWindow, normal_hint, &supplied) == - Success)) { + XGetWMNormalHints(pDisplay, iWindow, normal_hint, &supplied)) { if (normal_hint->flags & PMaxSize) { - /* Not maximizable if a maximum size is specified */ - hint |= HINT_NOMAXIMIZE; + /* Ensure default style is used if no other styling */ + if (!(hint & ~HINT_SKIPTASKBAR)) + hint |= HINT_BORDER | HINT_SIZEBOX | HINT_CAPTION; + + /* Not maximizable if a maximum size is specified, and that size + is smaller (in either dimension) than the screen size */ + if ((normal_hint->max_width < GetSystemMetrics(SM_CXVIRTUALSCREEN)) + || (normal_hint->max_height < GetSystemMetrics(SM_CYVIRTUALSCREEN))) + hint |= HINT_NOMAXIMIZE; if (normal_hint->flags & PMinSize) { /* @@ -1841,6 +2167,13 @@ winApplyHints(Display * pDisplay, Window iWindow, HWND hWnd, HWND * zstyle) free(application_id); if (window_name) XFree(window_name); + + /* + It only makes sense to apply minimize/maximize override when the + window is mapped, as otherwise the state can't be changed. + */ + if (!onCreate) + style &= ~(STYLE_MAXIMIZE | STYLE_MINIMIZE); } else { style = STYLE_NONE; @@ -1874,6 +2207,9 @@ winApplyHints(Display * pDisplay, Window iWindow, HWND hWnd, HWND * zstyle) (hint & ~HINT_BORDER & ~HINT_CAPTION & ~HINT_SIZEBOX) | HINT_NOFRAME; + if (style & STYLE_SKIPTASKBAR) + hint |= HINT_SKIPTASKBAR; + /* Now apply styles to window */ style = GetWindowLongPtr(hWnd, GWL_STYLE); if (!style) @@ -1881,6 +2217,11 @@ winApplyHints(Display * pDisplay, Window iWindow, HWND hWnd, HWND * zstyle) style &= ~WS_CAPTION & ~WS_SIZEBOX; /* Just in case */ + if (GetParent(hWnd)) + style |= WS_SYSMENU; + else + style |= WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX; + if (!(hint & ~HINT_SKIPTASKBAR)) /* No hints, default */ style = style | WS_CAPTION | WS_SIZEBOX; else if (hint & HINT_NOFRAME) /* No frame, no decorations */ @@ -1915,57 +2256,3 @@ winApplyHints(Display * pDisplay, Window iWindow, HWND hWnd, HWND * zstyle) ("winApplyHints: iWindow 0x%08x hints 0x%08x style 0x%08x exstyle 0x%08x\n", iWindow, hint, style, exStyle); } - -void -winUpdateWindowPosition(HWND hWnd, HWND * zstyle) -{ - int iX, iY, iWidth, iHeight; - int iDx, iDy; - RECT rcNew; - WindowPtr pWin = GetProp(hWnd, WIN_WINDOW_PROP); - DrawablePtr pDraw = NULL; - - if (!pWin) - return; - pDraw = &pWin->drawable; - if (!pDraw) - return; - - /* Get the X and Y location of the X window */ - iX = pWin->drawable.x + GetSystemMetrics(SM_XVIRTUALSCREEN); - iY = pWin->drawable.y + GetSystemMetrics(SM_YVIRTUALSCREEN); - - /* Get the height and width of the X window */ - iWidth = pWin->drawable.width; - iHeight = pWin->drawable.height; - - /* Setup a rectangle with the X window position and size */ - SetRect(&rcNew, iX, iY, iX + iWidth, iY + iHeight); - - winDebug("winUpdateWindowPosition - drawable extent (%d, %d)-(%d, %d)\n", - rcNew.left, rcNew.top, rcNew.right, rcNew.bottom); - - AdjustWindowRectEx(&rcNew, GetWindowLongPtr(hWnd, GWL_STYLE), FALSE, - GetWindowLongPtr(hWnd, GWL_EXSTYLE)); - - /* Don't allow window decoration to disappear off to top-left as a result of this adjustment */ - if (rcNew.left < GetSystemMetrics(SM_XVIRTUALSCREEN)) { - iDx = GetSystemMetrics(SM_XVIRTUALSCREEN) - rcNew.left; - rcNew.left += iDx; - rcNew.right += iDx; - } - - if (rcNew.top < GetSystemMetrics(SM_YVIRTUALSCREEN)) { - iDy = GetSystemMetrics(SM_YVIRTUALSCREEN) - rcNew.top; - rcNew.top += iDy; - rcNew.bottom += iDy; - } - - winDebug("winUpdateWindowPosition - Window extent (%d, %d)-(%d, %d)\n", - rcNew.left, rcNew.top, rcNew.right, rcNew.bottom); - - /* Position the Windows window */ - SetWindowPos(hWnd, *zstyle, rcNew.left, rcNew.top, - rcNew.right - rcNew.left, rcNew.bottom - rcNew.top, 0); - -} diff --git a/hw/xwin/winmultiwindowwndproc.c b/hw/xwin/winmultiwindowwndproc.c index d296f0f0c..55c4d80c5 100644 --- a/hw/xwin/winmultiwindowwndproc.c +++ b/hw/xwin/winmultiwindowwndproc.c @@ -41,6 +41,7 @@ #include "winprefs.h" #include "winmsg.h" #include "inputstr.h" +#include "wmutil/keyboard.h" extern void winUpdateWindowPosition(HWND hWnd, HWND * zstyle); @@ -294,6 +295,31 @@ winStartMousePolling(winPrivScreenPtr s_pScreenPriv) MOUSE_POLLING_INTERVAL, NULL); } +static +void +winAdjustXWindowState(winPrivScreenPtr s_pScreenPriv, winWMMessageRec *wmMsg) +{ + wmMsg->msg = WM_WM_CHANGE_STATE; + if (IsIconic(wmMsg->hwndWindow)) { + wmMsg->dwID = 3; // IconicState + winSendMessageToWM(s_pScreenPriv->pWMInfo, wmMsg); + } + else if (IsZoomed(wmMsg->hwndWindow)) { + wmMsg->dwID = 2; // ZoomState + winSendMessageToWM(s_pScreenPriv->pWMInfo, wmMsg); + } + else if (IsWindowVisible(wmMsg->hwndWindow)) { + wmMsg->dwID = 1; // NormalState + winSendMessageToWM(s_pScreenPriv->pWMInfo, wmMsg); + } + else { + /* Only the client, not the user can Withdraw windows, so it doesn't make + much sense to handle that state here, and anything else is an + unanticapted state. */ + ErrorF("winAdjustXWindowState - Unknown state for %p\n", wmMsg->hwndWindow); + } +} + /* * winTopLevelWindowProc - Window procedure for all top-level Windows windows. */ @@ -302,7 +328,6 @@ LRESULT CALLBACK winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { POINT ptMouse; - HDC hdcUpdate; PAINTSTRUCT ps; WindowPtr pWin = NULL; winPrivWinPtr pWinPriv = NULL; @@ -457,18 +482,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 +494,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; - - /* 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); - } + /* Call the engine dependent repainter */ + if (*s_pScreenPriv->pwinBltExposedWindowRegion) + (*s_pScreenPriv->pwinBltExposedWindowRegion) (s_pScreen, pWin); - /* EndPaint frees the DC */ - EndPaint(hwnd, &ps); return 0; case WM_MOUSEMOVE: @@ -770,18 +766,18 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) ErrorF("\nCYGWINDOWING Dump:\n" "\tdrawable: (%hd, %hd) - %hdx%hd\n", pDraw->x, pDraw->y, pDraw->width, pDraw->height); - ErrorF("\twindPlace: (%ld, %ld) - %ldx%ld\n", pRect->left, + ErrorF("\twindPlace: (%d, %d) - %dx%d\n", pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top); if (GetClientRect(hwnd, &rc)) { pRect = &rc; - ErrorF("\tClientRect: (%ld, %ld) - %ldx%ld\n", pRect->left, + ErrorF("\tClientRect: (%d, %d) - %dx%d\n", pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top); } if (GetWindowRect(hwnd, &rc)) { pRect = &rc; - ErrorF("\tWindowRect: (%ld, %ld) - %ldx%ld\n", pRect->left, + ErrorF("\tWindowRect: (%d, %d) - %dx%d\n", pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top); } @@ -868,6 +864,7 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) RemoveProp(hwnd, WIN_WINDOW_PROP); RemoveProp(hwnd, WIN_WID_PROP); RemoveProp(hwnd, WIN_NEEDMANAGE_PROP); + RemoveProp(hwnd, WIN_STATE_PROP); break; @@ -878,77 +875,6 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) /* else: Wait for WM_EXITSIZEMOVE */ return 0; - case WM_SHOWWINDOW: - /* Bail out if the window is being hidden */ - if (!wParam) - return 0; - - /* */ - if (!pWin->overrideRedirect) { - HWND zstyle = HWND_NOTOPMOST; - - /* Flag that this window needs to be made active when clicked */ - SetProp(hwnd, WIN_NEEDMANAGE_PROP, (HANDLE) 1); - - /* Set the transient style flags */ - if (GetParent(hwnd)) - SetWindowLongPtr(hwnd, GWL_STYLE, - WS_POPUP | WS_OVERLAPPED | WS_SYSMENU | - WS_CLIPCHILDREN | WS_CLIPSIBLINGS); - /* Set the window standard style flags */ - else - SetWindowLongPtr(hwnd, GWL_STYLE, - (WS_POPUP | WS_OVERLAPPEDWINDOW | - WS_CLIPCHILDREN | WS_CLIPSIBLINGS) - & ~WS_CAPTION & ~WS_SIZEBOX); - - winUpdateWindowPosition(hwnd, &zstyle); - - { - WinXWMHints hints; - - if (winMultiWindowGetWMHints(pWin, &hints)) { - /* - Give the window focus, unless it has an InputHint - which is FALSE (this is used by e.g. glean to - avoid every test window grabbing the focus) - */ - if (!((hints.flags & InputHint) && (!hints.input))) { - SetForegroundWindow(hwnd); - } - } - } - wmMsg.msg = WM_WM_MAP3; - } - else { /* It is an overridden window so make it top of Z stack */ - - HWND forHwnd = GetForegroundWindow(); - -#if CYGWINDOWING_DEBUG - ErrorF("overridden window is shown\n"); -#endif - if (forHwnd != NULL) { - if (GetWindowLongPtr(forHwnd, GWLP_USERDATA) & (LONG_PTR) - XMING_SIGNATURE) { - if (GetWindowLongPtr(forHwnd, GWL_EXSTYLE) & WS_EX_TOPMOST) - SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, - SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); - else - SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, - SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); - } - } - wmMsg.msg = WM_WM_MAP2; - } - - /* Tell our Window Manager thread to map the window */ - if (fWMMsgInitialized) - winSendMessageToWM(s_pScreenPriv->pWMInfo, &wmMsg); - - winStartMousePolling(s_pScreenPriv); - - return 0; - case WM_SIZING: /* Need to legalize the size according to WM_NORMAL_HINTS */ /* for applications like xterm */ @@ -1001,12 +927,75 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) } } } + + /* Window is being shown */ + if (pWinPos->flags & SWP_SHOWWINDOW) { + if (!pWin->overrideRedirect) { + HWND zstyle = HWND_NOTOPMOST; + + /* Flag that this window needs to be made active when clicked */ + SetProp(hwnd, WIN_NEEDMANAGE_PROP, (HANDLE) 1); + + winUpdateWindowPosition(hwnd, &zstyle); + + { + WinXWMHints hints; + + if (winMultiWindowGetWMHints(pWin, &hints)) { + /* + Give the window focus, unless it has an InputHint + which is FALSE (this is used by e.g. glean to + avoid every test window grabbing the focus) + */ + if (!((hints.flags & InputHint) && (!hints.input))) { + SetForegroundWindow(hwnd); + } + } + } + wmMsg.msg = WM_WM_MAP_MANAGED; + } + else { /* It is an overridden window so make it top of Z stack */ + HWND forHwnd = GetForegroundWindow(); + + if (forHwnd != NULL) { + if (GetWindowLongPtr(forHwnd, GWLP_USERDATA) & (LONG_PTR) + XMING_SIGNATURE) { + if (GetWindowLongPtr(forHwnd, GWL_EXSTYLE) & WS_EX_TOPMOST) + SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, + SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); + else + SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, + SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); + } + } + wmMsg.msg = WM_WM_MAP_UNMANAGED; + } + + /* Tell our Window Manager thread to map the window */ + if (fWMMsgInitialized) + winSendMessageToWM(s_pScreenPriv->pWMInfo, &wmMsg); + + winStartMousePolling(s_pScreenPriv); + } + + /* + We don't react to SWP_HIDEWINDOW indicating window is being hidden in + a symmetrical way (i.e. by sending WM_WM_UNMAP) + + If the cause of the window being hidden is the X windows being unmapped, + (WM_STATE has changed to WithdrawnState), then the window has already + been unmapped. + + Virtual desktop software (like VirtuaWin or Dexpot) uses SWP_HIDEWINDOW + to hide windows on other desktops. We mustn't unmap the X window in + that situation, as it becomes inaccessible. + */ } - /* - * Pass the message to DefWindowProc to let the function - * break down WM_WINDOWPOSCHANGED to WM_MOVE and WM_SIZE. - */ - break; + /* + * Pass the message to DefWindowProc to let the function + * break down WM_WINDOWPOSCHANGED to WM_MOVE and WM_SIZE. + */ + break; case WM_ENTERSIZEMOVE: hasEnteredSizeMove = TRUE; @@ -1016,6 +1005,8 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) /* Adjust the X Window to the moved Windows window */ hasEnteredSizeMove = FALSE; winAdjustXWindow(pWin, hwnd); + if (fWMMsgInitialized) + winAdjustXWindowState(s_pScreenPriv, &wmMsg); return 0; case WM_SIZE: @@ -1045,6 +1036,10 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) if (!hasEnteredSizeMove) { /* Adjust the X Window to the moved Windows window */ winAdjustXWindow(pWin, hwnd); + if (fWMMsgInitialized) + winAdjustXWindowState(s_pScreenPriv, &wmMsg); + if (wParam == SIZE_MINIMIZED) + winReorderWindowsMultiWindow(); } /* else: wait for WM_EXITSIZEMOVE */ return 0; /* end of WM_SIZE handler */ @@ -1156,3 +1151,93 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) winReorderWindowsMultiWindow(); return ret; } + +/* + * winChildWindowProc - Window procedure for all top-level Windows windows. + */ + +LRESULT CALLBACK +winChildWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ +#if CYGDEBUG + winDebugWin32Message("winChildWindowProc", hwnd, message, wParam, lParam); +#endif + + switch (message) { + case WM_ERASEBKGND: + return TRUE; + + case WM_PAINT: + /* + We don't have the bits to draw into the window, they went straight into the OpenGL + surface + + 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... + */ + { + PAINTSTRUCT ps; + BeginPaint(hwnd, &ps); + ValidateRect(hwnd, &(ps.rcPaint)); + EndPaint(hwnd, &ps); + return 0; + } + /* XXX: this is exactly what DefWindowProc does? */ + } + + return DefWindowProc(hwnd, message, wParam, lParam); +} + +void +winUpdateWindowPosition(HWND hWnd, HWND * zstyle) +{ + int iX, iY, iWidth, iHeight; + int iDx, iDy; + RECT rcNew; + WindowPtr pWin = GetProp(hWnd, WIN_WINDOW_PROP); + DrawablePtr pDraw = NULL; + + if (!pWin) + return; + pDraw = &pWin->drawable; + if (!pDraw) + return; + + /* Get the X and Y location of the X window */ + iX = pWin->drawable.x + GetSystemMetrics(SM_XVIRTUALSCREEN); + iY = pWin->drawable.y + GetSystemMetrics(SM_YVIRTUALSCREEN); + + /* Get the height and width of the X window */ + iWidth = pWin->drawable.width; + iHeight = pWin->drawable.height; + + /* Setup a rectangle with the X window position and size */ + SetRect(&rcNew, iX, iY, iX + iWidth, iY + iHeight); + + winDebug("winUpdateWindowPosition - drawable extent (%d, %d)-(%d, %d)\n", + rcNew.left, rcNew.top, rcNew.right, rcNew.bottom); + + AdjustWindowRectEx(&rcNew, GetWindowLongPtr(hWnd, GWL_STYLE), FALSE, + GetWindowLongPtr(hWnd, GWL_EXSTYLE)); + + /* Don't allow window decoration to disappear off to top-left as a result of this adjustment */ + if (rcNew.left < GetSystemMetrics(SM_XVIRTUALSCREEN)) { + iDx = GetSystemMetrics(SM_XVIRTUALSCREEN) - rcNew.left; + rcNew.left += iDx; + rcNew.right += iDx; + } + + if (rcNew.top < GetSystemMetrics(SM_YVIRTUALSCREEN)) { + iDy = GetSystemMetrics(SM_YVIRTUALSCREEN) - rcNew.top; + rcNew.top += iDy; + rcNew.bottom += iDy; + } + + winDebug("winUpdateWindowPosition - Window extent (%d, %d)-(%d, %d)\n", + rcNew.left, rcNew.top, rcNew.right, rcNew.bottom); + + /* Position the Windows window */ + SetWindowPos(hWnd, *zstyle, rcNew.left, rcNew.top, + rcNew.right - rcNew.left, rcNew.bottom - rcNew.top, 0); + +} diff --git a/hw/xwin/winprefs.c b/hw/xwin/winprefs.c index 505292714..9f1e9b1b7 100644 --- a/hw/xwin/winprefs.c +++ b/hw/xwin/winprefs.c @@ -37,6 +37,9 @@ #include <stdlib.h> #ifdef __CYGWIN__ #include <sys/resource.h> +#include <sys/select.h> +#include <sys/wait.h> +#include <pthread.h> #endif #include "win.h" @@ -46,6 +49,7 @@ #include "winprefs.h" #include "windisplay.h" #include "winmultiwindowclass.h" +#include "winmultiwindowicons.h" /* Where will the custom menu commands start counting from? */ #define STARTMENUID WM_USER @@ -297,6 +301,110 @@ HandleCustomWM_INITMENU(HWND hwnd, HMENU hmenu) } +#ifdef __CYGWIN__ +static void +LogLineFromFd(int fd, const char *fdname, int pid) +{ +#define BUFSIZE 512 /* must be less than internal buffer size used in LogVWrite */ + char buf[BUFSIZE]; + char *bufptr = buf; + + /* read from fd until eof, newline or our buffer is full */ + while ((read(fd, bufptr, 1) > 0) && (bufptr < &(buf[BUFSIZE - 1]))) { + if (*bufptr == '\n') + break; + bufptr++; + } + + /* null terminate and log */ + *bufptr = 0; + if (strlen(buf)) + ErrorF("(pid %d %s) %s\n", pid, fdname, buf); +} + +static void * +ExecAndLogThread(void *cmd) +{ + int pid; + int stdout_filedes[2]; + int stderr_filedes[2]; + int status; + + /* Create a pair of pipes */ + pipe(stdout_filedes); + pipe(stderr_filedes); + + switch (pid = fork()) { + case 0: /* child */ + { + struct rlimit rl; + unsigned int fd; + + /* dup write end of pipes onto stderr and stdout */ + close(STDOUT_FILENO); + close(STDERR_FILENO); + + dup2(stdout_filedes[1], STDOUT_FILENO); + dup2(stderr_filedes[1], STDERR_FILENO); + + /* Close any open descriptors except for STD* */ + getrlimit(RLIMIT_NOFILE, &rl); + for (fd = STDERR_FILENO + 1; fd < rl.rlim_cur; fd++) + close(fd); + + /* Disassociate any TTYs */ + setsid(); + + execl("/bin/sh", "/bin/sh", "-c", cmd, NULL); + perror("execl failed"); + exit(127); + } + break; + + default: /* parent */ + { + close(stdout_filedes[1]); + close(stderr_filedes[1]); + + ErrorF("executing '%s', pid %d\n", (char *) cmd, pid); + + /* read from pipes, write to log, until both are closed */ + while (TRUE) { + fd_set readfds, errorfds; + int nfds = max(stdout_filedes[0], stderr_filedes[0]) + 1; + + FD_ZERO(&readfds); + FD_SET(stdout_filedes[0], &readfds); + FD_SET(stderr_filedes[0], &readfds); + errorfds = readfds; + + if (select(nfds, &readfds, NULL, &errorfds, NULL) > 0) { + if (FD_ISSET(stdout_filedes[0], &readfds)) + LogLineFromFd(stdout_filedes[0], "stdout", pid); + if (FD_ISSET(stderr_filedes[0], &readfds)) + LogLineFromFd(stderr_filedes[0], "stderr", pid); + + if (FD_ISSET(stdout_filedes[0], &errorfds) && + FD_ISSET(stderr_filedes[0], &errorfds)) + break; + } + else { + break; + } + } + + waitpid(pid, &status, 0); + } + break; + + case -1: /* error */ + ErrorF("fork() to run command failed\n"); + } + + return (void *) (intptr_t) status; +} +#endif + /* * Searches for the custom WM_COMMAND command ID and performs action. * Return TRUE if command is proccessed, FALSE otherwise. @@ -319,24 +427,17 @@ HandleCustomWM_COMMAND(HWND hwnd, int command) switch (m->menuItem[j].cmd) { #ifdef __CYGWIN__ case CMD_EXEC: - if (fork() == 0) { - struct rlimit rl; - int fd; - - /* Close any open descriptors except for STD* */ - getrlimit(RLIMIT_NOFILE, &rl); - for (fd = STDERR_FILENO + 1; fd < rl.rlim_cur; fd++) - close(fd); - - /* Disassociate any TTYs */ - setsid(); + { + pthread_t t; - execl("/bin/sh", - "/bin/sh", "-c", m->menuItem[j].param, NULL); - exit(0); - } + if (!pthread_create + (&t, NULL, ExecAndLogThread, m->menuItem[j].param)) + pthread_detach(t); else - return TRUE; + ErrorF + ("Creating command output logging thread failed\n"); + } + return TRUE; break; #else case CMD_EXEC: @@ -637,11 +738,17 @@ winPrefsLoadPreferences(const char *path) "MENU rmenu {\n" " \"How to customize this menu\" EXEC \"xterm +tb -e man XWinrc\"\n" " \"Launch xterm\" EXEC xterm\n" - " \"Load .XWinrc\" RELOAD\n" + " SEPARATOR\n" + " FAQ EXEC \"cygstart http://x.cygwin.com/docs/faq/cygwin-x-faq.html\"\n" + " \"User's Guide\" EXEC \"cygstart http://x.cygwin.com/docs/ug/cygwin-x-ug.html\"\n" + " SEPARATOR\n" + " \"Reload .XWinrc\" RELOAD\n" " SEPARATOR\n" "}\n" "\n" "ROOTMENU rmenu\n"; path = "built-in default"; prefFile = fmemopen(defaultPrefs, strlen(defaultPrefs), "r"); + + } #endif @@ -672,7 +779,7 @@ LoadPreferences(void) char *home; char fname[PATH_MAX + NAME_MAX + 2]; char szDisplay[512]; - char *szEnvDisplay; + char *szEnvDisplay, *szEnvLogFile; int i, j; char param[PARAM_MAX + 1]; char *srcParam, *dstParam; @@ -720,6 +827,11 @@ LoadPreferences(void) putenv(szEnvDisplay); } + /* Setup XWINLOGFILE environment variable */ + szEnvLogFile = (char *) (malloc(strlen(g_pszLogFile) + strlen("XWINLOGFILE=") + 1)); + snprintf(szEnvLogFile, 512, "XWINLOGFILE=%s", g_pszLogFile); + putenv(szEnvLogFile); + /* Replace any "%display%" in menu commands with display string */ for (i = 0; i < pref.menuItems; i++) { for (j = 0; j < pref.menu[i].menuItems; j++) { diff --git a/hw/xwin/winprefs.h b/hw/xwin/winprefs.h index 8f4eb0807..c41710419 100644 --- a/hw/xwin/winprefs.h +++ b/hw/xwin/winprefs.h @@ -34,9 +34,6 @@ /* Need Bool */ #include <X11/Xdefs.h> -/* Need TRUE */ -#include "misc.h" - /* Need to know how long paths can be... */ #include <limits.h> /* Xwindows redefines PATH_MAX to at least 1024 */ @@ -65,6 +62,7 @@ typedef enum MENUCOMMANDTYPE { #define STYLE_MAXIMIZE (1L<<4) /* Open a window maximized */ #define STYLE_MINIMIZE (1L<<5) /* Open a window minimized */ #define STYLE_BOTTOM (1L<<6) /* Open a window at the bottom of the Z order */ +#define STYLE_SKIPTASKBAR (1L<<7) /* Omit from taskbar */ /* Where to place a system menu */ typedef enum MENUPOSITION { diff --git a/hw/xwin/winprefslex.l b/hw/xwin/winprefslex.l index 9e6f0d6d4..e7547729c 100644 --- a/hw/xwin/winprefslex.l +++ b/hw/xwin/winprefslex.l @@ -77,6 +77,7 @@ BOTTOM { return BOTTOM; } NOTITLE { return NOTITLE; } OUTLINE { return OUTLINE; } NOFRAME { return NOFRAME; } +SKIPTASKBAR { return SKIPTASKBAR; } ROOTMENU { return ROOTMENU; } DEFAULTSYSMENU { return DEFAULTSYSMENU; } SYSMENU { return SYSMENU; } @@ -90,6 +91,12 @@ RELOAD { return RELOAD; } TRAYICON { return TRAYICON; } FORCEEXIT { return FORCEEXIT; } SILENTEXIT { return SILENTEXIT; } +DPI { return DPI; } +XKBLAYOUT { return XKBLAYOUT; } +XKBMODEL { return XKBMODEL; } +XKBOPTIONS { return XKBOPTIONS; } +XKBRULES { return XKBRULES; } +XKBVARIANT { return XKBVARIANT; } "{" { return LB; } "}" { return RB; } "\""[^\"\r\n]+"\"" { yylval.sVal = makestr(yytext+1); \ diff --git a/hw/xwin/winprefsyacc.y b/hw/xwin/winprefsyacc.y index 9bb28ae92..e4e305a0f 100644 --- a/hw/xwin/winprefsyacc.y +++ b/hw/xwin/winprefsyacc.y @@ -39,6 +39,8 @@ #include <stdlib.h> #define _STDLIB_H 1 /* bison checks this to know if stdlib has been included */ #include <string.h> +#include "globals.h" +#include "winconfig.h" #include "winprefs.h" /* The following give better error messages in bison at the cost of a few KB */ @@ -57,6 +59,13 @@ static MENUPARSED menu; /* Functions for parsing the tokens into out structure */ /* Defined at the end section of this file */ +static void SetDPI (char *dpi); +static void SetXKBLayout (char *layout); +static void SetXKBModel (char *model); +static void SetXKBOptions (char *options); +static void SetXKBRules (char *rules); +static void SetXKBVariant (char *variant); + static void SetIconDirectory (char *path); static void SetDefaultIcon (char *fname); static void SetRootMenu (char *menu); @@ -108,6 +117,7 @@ extern int yylex(void); %token NOTITLE %token OUTLINE %token NOFRAME +%token SKIPTASKBAR %token DEFAULTSYSMENU %token SYSMENU %token ROOTMENU @@ -121,10 +131,17 @@ extern int yylex(void); %token TRAYICON %token FORCEEXIT %token SILENTEXIT +%token DPI +%token XKBLAYOUT +%token XKBMODEL +%token XKBOPTIONS +%token XKBRULES +%token XKBVARIANT %token <sVal> STRING %type <uVal> group1 %type <uVal> group2 +%type <uVal> group3 %type <uVal> stylecombo %type <iVal> atspot @@ -155,6 +172,30 @@ command: defaulticon | trayicon | forceexit | silentexit + | dpi + | xkblayout + | xkbmodel + | xkboptions + | xkbrules + | xkbvariant + ; + +dpi: DPI STRING NEWLINE { SetDPI($2); free($2); } + ; + +xkblayout: XKBLAYOUT STRING NEWLINE { SetXKBLayout($2); } + ; + +xkbmodel: XKBMODEL STRING NEWLINE { SetXKBModel($2); } + ; + +xkboptions: XKBOPTIONS STRING NEWLINE { SetXKBOptions($2); } + ; + +xkbrules: XKBRULES STRING NEWLINE { SetXKBRules($2); } + ; + +xkbvariant: XKBVARIANT STRING NEWLINE { SetXKBVariant($2); } ; trayicon: TRAYICON STRING NEWLINE { SetTrayIcon($2); free($2); } @@ -207,10 +248,24 @@ group2: NOTITLE { $$=STYLE_NOTITLE; } | NOFRAME { $$=STYLE_NOFRAME; } ; +group3: SKIPTASKBAR { $$=STYLE_SKIPTASKBAR; } + ; + stylecombo: group1 { $$=$1; } | group2 { $$=$1; } + | group3 { $$=$1; } | group1 group2 { $$=$1|$2; } + | group1 group3 { $$=$1|$2; } | group2 group1 { $$=$1|$2; } + | group2 group3 { $$=$1|$2; } + | group3 group1 { $$=$1|$2; } + | group3 group2 { $$=$1|$2; } + | group1 group2 group3 { $$=$1|$2|$3; } + | group1 group3 group2 { $$=$1|$2|$3; } + | group2 group1 group3 { $$=$1|$2|$3; } + | group2 group3 group1 { $$=$1|$2|$3; } + | group3 group1 group2 { $$=$1|$2|$3; } + | group3 group2 group1 { $$=$1|$2|$3; } ; styleline: STRING stylecombo NEWLINE newline_or_nada { AddStyleLine($1, $2); free($1); } @@ -259,6 +314,58 @@ yyerror (const char *s) return 1; } +static void +SetDPI (char *dpi) +{ + if (!g_cmdline.customDPI) + monitorResolution = atoi (dpi); +} + +static void +SetXKBLayout (char *layout) +{ + if (!g_cmdline.xkbLayout) + g_cmdline.xkbLayout = layout; + else + free (layout); +} + +static void +SetXKBModel (char *model) +{ + if (!g_cmdline.xkbModel) + g_cmdline.xkbModel = model; + else + free (model); +} + +static void +SetXKBOptions (char *options) +{ + if (!g_cmdline.xkbOptions) + g_cmdline.xkbOptions = options; + else + free (options); +} + +static void +SetXKBRules (char *rules) +{ + if (!g_cmdline.xkbRules) + g_cmdline.xkbRules = rules; + else + free (rules); +} + +static void +SetXKBVariant (char *variant) +{ + if (!g_cmdline.xkbVariant) + g_cmdline.xkbVariant = variant; + else + free (variant); +} + /* Miscellaneous functions to store TOKENs into the structure */ static void SetIconDirectory (char *path) diff --git a/hw/xwin/winprocarg.c b/hw/xwin/winprocarg.c index 837cdb2f4..8deac9d8a 100644 --- a/hw/xwin/winprocarg.c +++ b/hw/xwin/winprocarg.c @@ -135,13 +135,14 @@ winInitializeScreenDefaults(void) defaultScreenInfo.fRootless = FALSE; #ifdef XWIN_MULTIWINDOW defaultScreenInfo.fMultiWindow = FALSE; + defaultScreenInfo.fCompositeWM = FALSE; #endif #if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM) defaultScreenInfo.fMultiMonitorOverride = FALSE; #endif defaultScreenInfo.fMultipleMonitors = FALSE; defaultScreenInfo.fLessPointer = FALSE; - defaultScreenInfo.iResizeMode = resizeWithRandr; + defaultScreenInfo.iResizeMode = resizeDefault; defaultScreenInfo.fNoTrayIcon = FALSE; defaultScreenInfo.iE3BTimeout = WIN_E3B_DEFAULT; defaultScreenInfo.fUseWinKillKey = WIN_DEFAULT_WIN_KILL; @@ -247,7 +248,7 @@ ddxProcessArgument(int argc, char *argv[], int i) * OsVendorInit () gets called, otherwise we will overwrite * settings changed by parameters such as -fullscreen, etc. */ - winErrorFVerb(2, "ddxProcessArgument - Initializing default " + winErrorFVerb(3, "ddxProcessArgument - Initializing default " "screens\n"); winInitializeScreenDefaults(); } @@ -292,6 +293,9 @@ ddxProcessArgument(int argc, char *argv[], int i) /* Display the usage message if the argument is malformed */ if (i + 1 >= argc) { + ErrorF("ddxProcessArgument - screen - Missing screen number\n"); + UseMsg(); + FatalError("-screen missing screen number\n"); return 0; } @@ -615,6 +619,16 @@ ddxProcessArgument(int argc, char *argv[], int i) /* Indicate that we have processed this argument */ return 1; } + + /* + * Look for the '-compositewm' argument + */ + if (IS_OPTION("-compositewm")) { + screenInfoPtr->fCompositeWM = TRUE; + + /* Indicate that we have processed this argument */ + return 1; + } #endif /* @@ -666,7 +680,7 @@ ddxProcessArgument(int argc, char *argv[], int i) if (IS_OPTION("-resize")) mode = resizeWithRandr; else if (IS_OPTION("-noresize")) - mode = notAllowed; + mode = resizeNotAllowed; else if (strncmp(argv[i], "-resize=", strlen("-resize=")) == 0) { char *option = argv[i] + strlen("-resize="); @@ -675,7 +689,7 @@ ddxProcessArgument(int argc, char *argv[], int i) else if (strcmp(option, "scrollbars") == 0) mode = resizeWithScrollbars; else if (strcmp(option, "none") == 0) - mode = notAllowed; + mode = resizeNotAllowed; else { ErrorF("ddxProcessArgument - resize - Invalid resize mode %s\n", option); @@ -957,6 +971,14 @@ ddxProcessArgument(int argc, char *argv[], int i) } /* + * Look for the '-dpi' argument + */ + if (IS_OPTION("-dpi")) { + g_cmdline.customDPI = TRUE; + return 0; /* Let DIX parse this again */ + } + + /* * Look for the '-config' argument */ if (IS_OPTION("-config") @@ -1011,9 +1033,6 @@ ddxProcessArgument(int argc, char *argv[], int i) if (IS_OPTION("-logfile")) { CHECK_ARGS(1); g_pszLogFile = argv[++i]; -#ifdef RELOCATE_PROJECTROOT - g_fLogFileChanged = TRUE; -#endif return 2; } @@ -1098,6 +1117,11 @@ ddxProcessArgument(int argc, char *argv[], int i) return 1; } + if (IS_OPTION("-nohostintitle")) { + g_fHostInTitle = FALSE; + return 1; + } + return 0; } @@ -1169,6 +1193,129 @@ winLogCommandLine(int argc, char *argv[]) } /* + * Detect the OS + */ + +typedef BOOL(WINAPI * LPFN_ISWOW64PROCESS) (HANDLE, PBOOL); + +static void +winOS(void) +{ + OSVERSIONINFOEX osvi = { 0 }; + const char *windowstype = "Unknown"; + const char *prodName = "Unknown"; + const char *isWow = "Unknown"; + + /* Get operating system version information */ + osvi.dwOSVersionInfoSize = sizeof(osvi); + GetVersionEx((LPOSVERSIONINFO) & osvi); + + /* Branch on platform ID */ + switch (osvi.dwPlatformId) { + case VER_PLATFORM_WIN32_NT: + windowstype = "Windows NT"; + + if (osvi.dwMajorVersion <= 4) + prodName = "Windows NT"; + else if (osvi.dwMajorVersion == 10) { + if (osvi.dwMinorVersion == 0) { + if (osvi.wProductType == VER_NT_WORKSTATION) + prodName = "Windows 10"; + else + prodName = "Windows Server 10"; // or 2016??? + } + } + else if (osvi.dwMajorVersion == 6) { + if (osvi.dwMinorVersion == 4) { + if (osvi.wProductType == VER_NT_WORKSTATION) + prodName = "Windows 10"; + else + prodName = "Windows Server 10"; // or 2016??? + } + if (osvi.dwMinorVersion == 3) { + if (osvi.wProductType == VER_NT_WORKSTATION) + prodName = "Windows 8.1"; + else + prodName = "Windows Server 2012 R2"; + } + if (osvi.dwMinorVersion == 2) { + if (osvi.wProductType == VER_NT_WORKSTATION) + prodName = "Windows 8"; + else + prodName = "Windows Server 2012"; + } + else if (osvi.dwMinorVersion == 1) { + if (osvi.wProductType == VER_NT_WORKSTATION) + prodName = "Windows 7"; + else + prodName = "Windows Server 2008 R2"; + } + else if (osvi.dwMinorVersion == 0) { + if (osvi.wProductType == VER_NT_WORKSTATION) + prodName = "Windows Vista"; + else + prodName = "Windows Server 2008"; + } + } + else if (osvi.dwMajorVersion == 5) { + if (osvi.dwMinorVersion == 2) { + if (osvi.wProductType == VER_NT_WORKSTATION) + prodName = "Windows XP x64 Edition"; + else if (GetSystemMetrics(SM_SERVERR2)) + prodName = "Windows Server 2003 R2"; + else + prodName = "Windows Server 2003"; + } + else if (osvi.dwMinorVersion == 1) + prodName = "Windows XP"; + else if (osvi.dwMinorVersion == 0) { + prodName = "Windows 2000"; + break; + } + } + + break; + + case VER_PLATFORM_WIN32_WINDOWS: + windowstype = "Windows"; + break; + } + +#ifdef __x86_64__ + isWow = " (Win64)"; +#else + { + /* Check if we are running under WoW64 */ + LPFN_ISWOW64PROCESS fnIsWow64Process; + + fnIsWow64Process = + (LPFN_ISWOW64PROCESS) GetProcAddress(GetModuleHandle("kernel32"), + "IsWow64Process"); + if (NULL != fnIsWow64Process) { + wBOOL bIsWow64 = FALSE; + + if (fnIsWow64Process(GetCurrentProcess(), &bIsWow64)) { + isWow = bIsWow64 ? " (WoW64)" : " (Win32)"; + } + else { + /* IsWow64Process() failed */ + isWow = " (WoWUnknown)"; + } + } + else { + /* OS doesn't support IsWow64Process() */ + isWow = ""; + } + } +#endif + + ErrorF("OS: %s %s [%s %d.%d build %d]%s\n", + prodName, osvi.szCSDVersion, + windowstype, (int)osvi.dwMajorVersion, (int)osvi.dwMinorVersion, + (int)osvi.dwBuildNumber, isWow); +} + +/* * winLogVersionInfo - Log version information */ @@ -1195,8 +1342,8 @@ winLogVersionInfo(void) } } #endif + winOS(); if (strlen(BUILDERSTRING)) ErrorF("%s\n", BUILDERSTRING); - ErrorF("Contact: %s\n", BUILDERADDR); ErrorF("\n"); } diff --git a/hw/xwin/winrandr.c b/hw/xwin/winrandr.c index 1b340850c..b6ac74074 100644 --- a/hw/xwin/winrandr.c +++ b/hw/xwin/winrandr.c @@ -34,11 +34,6 @@ #include <xwin-config.h> #endif #include "win.h" -#include "mivalidate.h" // for union _Validate used by windowstr.h - -#ifndef RANDR_12_INTERFACE -#error X server must have RandR 1.2 interface -#endif /* * Answer queries about the RandR features supported. @@ -47,17 +42,47 @@ 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; - /* - The screen doesn't have to be limited to the actual - monitor size (we can have scrollbars :-), so what is - the upper limit? - */ - RRScreenSetSizeRange(pScreen, 0, 0, 4096, 4096); + /* Delete previous mode */ + if (output->modes[0]) + { + RRModeDestroy(output->modes[0]); + RRModeDestroy(output->crtc->mode); + } + + /* Register current mode */ + { + xRRModeInfo modeInfo; + RRModePtr mode; + char name[100]; + + memset(&modeInfo, '\0', sizeof(modeInfo)); + snprintf(name, sizeof(name), "%dx%d", pScreen->width, pScreen->height); + + modeInfo.width = pScreen->width; + modeInfo.height = pScreen->height; + modeInfo.hTotal = pScreen->width; + modeInfo.vTotal = pScreen->height; + modeInfo.dotClock = 0; + modeInfo.nameLength = strlen(name); + mode = RRModeGet(&modeInfo, name); + + output->modes[0] = mode; + output->numModes = 1; + + mode = RRModeGet(&modeInfo, name); + output->crtc->mode = mode; + } return TRUE; } @@ -74,6 +99,11 @@ winDoRandRScreenSetSize(ScreenPtr pScreen, winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; WindowPtr pRoot = pScreen->root; + /* Ignore changes which do nothing */ + if ((pScreen->width == width) && (pScreen->height == height) && + (pScreen->mmWidth == mmWidth) && (pScreen->mmHeight == mmHeight)) + return; + // Prevent screen updates while we change things around SetRootClip(pScreen, FALSE); @@ -104,7 +134,7 @@ winDoRandRScreenSetSize(ScreenPtr pScreen, SetRootClip(pScreen, TRUE); // and arrange for it to be repainted - miPaintWindow(pRoot, &pRoot->borderClip, PW_BACKGROUND); + pScreen->PaintWindow(pRoot, &pRoot->borderClip, PW_BACKGROUND); /* Indicate that a screen size change took place */ RRScreenSizeNotify(pScreen); @@ -178,7 +208,7 @@ winRandRScreenSetSize(ScreenPtr pScreen, */ AdjustWindowRectEx(&rcClient, dwStyle, FALSE, dwExStyle); - ErrorF("winRandRScreenSetSize new window area w: %ld h: %ld\n", + ErrorF("winRandRScreenSetSize new window area w: %d h: %d\n", rcClient.right - rcClient.left, rcClient.bottom - rcClient.top); SetWindowPos(pScreenPriv->hwndScreen, NULL, @@ -213,5 +243,45 @@ winRandRInit(ScreenPtr pScreen) pRRScrPriv->rrCrtcSet = NULL; pRRScrPriv->rrCrtcSetGamma = NULL; + /* Create a CRTC and an output for the screen, and hook them together */ + { + RRCrtcPtr crtc; + RROutputPtr output; + + crtc = RRCrtcCreate(pScreen, NULL); + if (!crtc) + return FALSE; + + crtc->rotations = RR_Rotate_0; + + output = RROutputCreate(pScreen, "default", 7, NULL); + if (!output) + return FALSE; + + RROutputSetCrtcs(output, &crtc, 1); + RROutputSetConnection(output, RR_Connected); + RROutputSetSubpixelOrder(output, PictureGetSubpixelOrder(pScreen)); + + output->crtc = crtc; + + /* Set crtc outputs (should use RRCrtcNotify?) */ + crtc->outputs = malloc(sizeof(RROutputPtr)); + crtc->outputs[0] = output; + crtc->numOutputs = 1; + + pRRScrPriv->primaryOutput = output; + + /* Ensure we have space for exactly one mode */ + output->modes = malloc(sizeof(RRModePtr)); + output->modes[0] = NULL; + } + + /* + The screen doesn't have to be limited to the actual + monitor size (we can have scrollbars :-), so what is + the upper limit? + */ + RRScreenSetSizeRange(pScreen, 0, 0, 4096, 4096); + return TRUE; } diff --git a/hw/xwin/winscrinit.c b/hw/xwin/winscrinit.c index ce0aada31..84df00d08 100644 --- a/hw/xwin/winscrinit.c +++ b/hw/xwin/winscrinit.c @@ -89,8 +89,8 @@ winScreenInit(ScreenPtr pScreen, int argc, char **argv) DWORD dwInitialBPP; #if CYGDEBUG || YES - winDebug("winScreenInit - dwWidth: %ld dwHeight: %ld\n", - pScreenInfo->dwWidth, pScreenInfo->dwHeight); + winDebug("winScreenInit - dwWidth: %d dwHeight: %d\n", + (unsigned int)pScreenInfo->dwWidth, (unsigned int)pScreenInfo->dwHeight); #endif /* Allocate privates for this screen */ @@ -216,15 +216,19 @@ winScreenInit(ScreenPtr pScreen, int argc, char **argv) else winErrorFVerb(2, "winScreenInit - Using software cursor\n"); - /* - Note the screen origin in a normalized coordinate space where (0,0) is at the top left - of the native virtual desktop area - */ - pScreen->x = pScreenInfo->dwInitialX - GetSystemMetrics(SM_XVIRTUALSCREEN); - pScreen->y = pScreenInfo->dwInitialY - GetSystemMetrics(SM_YVIRTUALSCREEN); + if (!noPanoramiXExtension) { + /* + Note the screen origin in a normalized coordinate space where (0,0) is at the top left + of the native virtual desktop area + */ + pScreen->x = + pScreenInfo->dwInitialX - GetSystemMetrics(SM_XVIRTUALSCREEN); + pScreen->y = + pScreenInfo->dwInitialY - GetSystemMetrics(SM_YVIRTUALSCREEN); - ErrorF("Screen %d added at virtual desktop coordinate (%d,%d).\n", - pScreen->myNum, pScreen->x, pScreen->y); + ErrorF("Screen %d added at virtual desktop coordinate (%d,%d).\n", + pScreen->myNum, pScreen->x, pScreen->y); + } #if CYGDEBUG || YES winDebug("winScreenInit - returning\n"); @@ -537,6 +541,11 @@ winFinishScreenInitFB(int i, ScreenPtr pScreen, int argc, char **argv) || pScreenInfo->fInternalWM #endif ) { + 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 @@ -550,7 +559,9 @@ winFinishScreenInitFB(int i, ScreenPtr pScreen, int argc, char **argv) #ifdef XWIN_MULTIWINDOWEXTWM pScreenInfo->fInternalWM || #endif - FALSE)) { + FALSE, + pScreenInfo->fCompositeWM + )) { ErrorF("winFinishScreenInitFB - winInitWM () failed.\n"); return FALSE; } diff --git a/hw/xwin/winshaddd.c b/hw/xwin/winshaddd.c index 4904eb440..fd40fa680 100644 --- a/hw/xwin/winshaddd.c +++ b/hw/xwin/winshaddd.c @@ -1208,14 +1208,8 @@ winSetEngineFunctionsShadowDD(ScreenPtr pScreen) pScreenPriv->pwinStoreColors = winStoreColorsShadowDD; pScreenPriv->pwinCreateColormap = winCreateColormapShadowDD; pScreenPriv->pwinDestroyColormap = winDestroyColormapShadowDD; - pScreenPriv->pwinHotKeyAltTab = - (winHotKeyAltTabProcPtr) (void (*)(void)) NoopDDA; pScreenPriv->pwinCreatePrimarySurface = winCreatePrimarySurfaceShadowDD; pScreenPriv->pwinReleasePrimarySurface = winReleasePrimarySurfaceShadowDD; -#ifdef XWIN_MULTIWINDOW - pScreenPriv->pwinFinishCreateWindowsWindow = - (winFinishCreateWindowsWindowProcPtr) (void (*)(void)) NoopDDA; -#endif return TRUE; } diff --git a/hw/xwin/winshadddnl.c b/hw/xwin/winshadddnl.c index 48599b266..43e80358e 100644 --- a/hw/xwin/winshadddnl.c +++ b/hw/xwin/winshadddnl.c @@ -1200,6 +1200,7 @@ winSetEngineFunctionsShadowDDNL(ScreenPtr pScreen) pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowWindowed; pScreenPriv->pwinFinishScreenInit = winFinishScreenInitFB; pScreenPriv->pwinBltExposedRegions = winBltExposedRegionsShadowDDNL; + pScreenPriv->pwinBltExposedWindowRegion = NULL; pScreenPriv->pwinActivateApp = winActivateAppShadowDDNL; pScreenPriv->pwinRedrawScreen = winRedrawScreenShadowDDNL; pScreenPriv->pwinRealizeInstalledPalette @@ -1208,14 +1209,8 @@ winSetEngineFunctionsShadowDDNL(ScreenPtr pScreen) pScreenPriv->pwinStoreColors = winStoreColorsShadowDDNL; pScreenPriv->pwinCreateColormap = winCreateColormapShadowDDNL; pScreenPriv->pwinDestroyColormap = winDestroyColormapShadowDDNL; - pScreenPriv->pwinHotKeyAltTab = - (winHotKeyAltTabProcPtr) (void (*)(void)) NoopDDA; pScreenPriv->pwinCreatePrimarySurface = winCreatePrimarySurfaceShadowDDNL; pScreenPriv->pwinReleasePrimarySurface = winReleasePrimarySurfaceShadowDDNL; -#ifdef XWIN_MULTIWINDOW - pScreenPriv->pwinFinishCreateWindowsWindow - = (winFinishCreateWindowsWindowProcPtr) (void (*)(void)) NoopDDA; -#endif return TRUE; } diff --git a/hw/xwin/winshadgdi.c b/hw/xwin/winshadgdi.c index 3d222ad4b..5f06a448e 100644 --- a/hw/xwin/winshadgdi.c +++ b/hw/xwin/winshadgdi.c @@ -62,6 +62,9 @@ static Bool winBltExposedRegionsShadowGDI(ScreenPtr pScreen); static Bool + winBltExposedWindowRegionShadowGDI(ScreenPtr pScreen, WindowPtr pWin); + +static Bool winActivateAppShadowGDI(ScreenPtr pScreen); static Bool @@ -760,6 +763,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) { @@ -769,11 +778,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); @@ -789,6 +817,149 @@ winBltExposedRegionsShadowGDI(ScreenPtr pScreen) } /* + * 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); + + /* + 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, sizeof(bmih), 0); + 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 */ + /* XXX: looks like those coordinates should get transformed ??? */ + 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 */ @@ -1135,6 +1306,7 @@ winSetEngineFunctionsShadowGDI(ScreenPtr pScreen) pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowWindowed; pScreenPriv->pwinFinishScreenInit = winFinishScreenInitFB; pScreenPriv->pwinBltExposedRegions = winBltExposedRegionsShadowGDI; + pScreenPriv->pwinBltExposedWindowRegion = winBltExposedWindowRegionShadowGDI; pScreenPriv->pwinActivateApp = winActivateAppShadowGDI; pScreenPriv->pwinRedrawScreen = winRedrawScreenShadowGDI; pScreenPriv->pwinRealizeInstalledPalette = @@ -1143,16 +1315,8 @@ winSetEngineFunctionsShadowGDI(ScreenPtr pScreen) pScreenPriv->pwinStoreColors = winStoreColorsShadowGDI; pScreenPriv->pwinCreateColormap = winCreateColormapShadowGDI; pScreenPriv->pwinDestroyColormap = winDestroyColormapShadowGDI; - pScreenPriv->pwinHotKeyAltTab = - (winHotKeyAltTabProcPtr) (void (*)(void)) NoopDDA; - pScreenPriv->pwinCreatePrimarySurface = - (winCreatePrimarySurfaceProcPtr) (void (*)(void)) NoopDDA; - pScreenPriv->pwinReleasePrimarySurface = - (winReleasePrimarySurfaceProcPtr) (void (*)(void)) NoopDDA; -#ifdef XWIN_MULTIWINDOW - pScreenPriv->pwinFinishCreateWindowsWindow = - (winFinishCreateWindowsWindowProcPtr) (void (*)(void)) NoopDDA; -#endif + pScreenPriv->pwinCreatePrimarySurface = NULL; + pScreenPriv->pwinReleasePrimarySurface = NULL; return TRUE; } diff --git a/hw/xwin/winvalargs.c b/hw/xwin/winvalargs.c index edfd71f72..f93872419 100644 --- a/hw/xwin/winvalargs.c +++ b/hw/xwin/winvalargs.c @@ -127,7 +127,7 @@ winValidateArgs(void) return FALSE; } - /* Check for -multiwindow, -mwextwm, or -rootless and fullscreen */ + /* Check for -multiwindow, -mwextwm, or -rootless and -fullscreen */ if (g_ScreenInfo[i].fFullScreen && (FALSE #ifdef XWIN_MULTIWINDOW || g_ScreenInfo[i].fMultiWindow @@ -142,6 +142,21 @@ winValidateArgs(void) return FALSE; } + /* Check for -multiwindow, -mwextwm, or -rootless and -nodecoration */ + if (!g_ScreenInfo[i].fDecoration && (FALSE +#ifdef XWIN_MULTIWINDOW + || g_ScreenInfo[i].fMultiWindow +#endif +#ifdef XWIN_MULTIWINDOWEXTWM + || g_ScreenInfo[i].fMWExtWM +#endif + || g_ScreenInfo[i].fRootless) + ) { + ErrorF("winValidateArgs - -nodecoration is invalid with " + "-multiwindow, -mwextwm, or -rootless.\n"); + return FALSE; + } + /* Check for !fullscreen and any fullscreen-only parameters */ if (!g_ScreenInfo[i].fFullScreen && (g_ScreenInfo[i].dwRefreshRate != WIN_DEFAULT_REFRESH @@ -153,7 +168,7 @@ winValidateArgs(void) /* Check for fullscreen and any non-fullscreen parameters */ if (g_ScreenInfo[i].fFullScreen - && ((g_ScreenInfo[i].iResizeMode != notAllowed) + && ((g_ScreenInfo[i].iResizeMode != resizeNotAllowed) || !g_ScreenInfo[i].fDecoration || g_ScreenInfo[i].fLessPointer)) { ErrorF("winValidateArgs - -fullscreen is invalid with " diff --git a/hw/xwin/winwin32rootless.c b/hw/xwin/winwin32rootless.c index 660a78f2d..9d0bab531 100644 --- a/hw/xwin/winwin32rootless.c +++ b/hw/xwin/winwin32rootless.c @@ -40,6 +40,7 @@ #define _WINDOWSWM_SERVER_ #include <X11/extensions/windowswmstr.h> #include "winmultiwindowclass.h" +#include "winmultiwindowicons.h" #include <X11/Xatom.h> /* diff --git a/hw/xwin/winwin32rootlesswndproc.c b/hw/xwin/winwin32rootlesswndproc.c index f65811c9a..2ad96bcaf 100644 --- a/hw/xwin/winwin32rootlesswndproc.c +++ b/hw/xwin/winwin32rootlesswndproc.c @@ -42,6 +42,7 @@ #include "winmultiwindowclass.h" #include "winmsg.h" #include "inputstr.h" +#include "wmutil/keyboard.h" /* * Constant defines diff --git a/hw/xwin/winwindow.h b/hw/xwin/winwindow.h index 7e6bd565c..e3e1fb972 100644 --- a/hw/xwin/winwindow.h +++ b/hw/xwin/winwindow.h @@ -50,6 +50,7 @@ #define WIN_SCR_PROP "cyg_screen_prop rl" #define WINDOW_CLASS_X "cygwin/x X rl" #define WINDOW_CLASS_X_MSG "cygwin/x X msg" +#define WINDOW_CLASS_X_CHILD "cygwin/x X child" #define WINDOW_TITLE_X PROJECT_NAME " X" #define WIN_WINDOW_PROP "cyg_window_prop_rl" #ifdef HAS_DEVWINDOWS @@ -57,6 +58,7 @@ #endif #define WIN_WID_PROP "cyg_wid_prop_rl" #define WIN_NEEDMANAGE_PROP "cyg_override_redirect_prop_rl" +#define WIN_STATE_PROP "cyg_state_prop_rl" #ifndef CYGMULTIWINDOW_DEBUG #define CYGMULTIWINDOW_DEBUG NO #endif @@ -109,8 +111,8 @@ typedef struct _winWMMessageRec { #define WM_WM_NAME_EVENT (WM_USER + 9) #define WM_WM_ICON_EVENT (WM_USER + 10) #define WM_WM_CHANGE_STATE (WM_USER + 11) -#define WM_WM_MAP2 (WM_USER + 12) -#define WM_WM_MAP3 (WM_USER + 13) +#define WM_WM_MAP_UNMANAGED (WM_USER + 12) +#define WM_WM_MAP_MANAGED (WM_USER + 13) #define WM_WM_HINTS_EVENT (WM_USER + 14) #define WM_MANAGE (WM_USER + 100) #define WM_UNMANAGE (WM_USER + 102) @@ -142,15 +144,12 @@ winInitWM(void **ppWMInfo, pthread_t * ptWMProc, pthread_t * ptXMsgProc, pthread_mutex_t * ppmServerStarted, - int dwScreen, HWND hwndScreen, BOOL allowOtherWM); + int dwScreen, HWND hwndScreen, BOOL allowOtherWM, BOOL compositeWM); void winDeinitMultiWindowWM(void); void - winMinimizeWindow(Window id); - -void winPropertyStoreInit(void); void diff --git a/hw/xwin/winwndproc.c b/hw/xwin/winwndproc.c index 1bf3f5cde..fa94c8d21 100644 --- a/hw/xwin/winwndproc.c +++ b/hw/xwin/winwndproc.c @@ -45,6 +45,8 @@ #ifdef XWIN_CLIPBOARD #include "winclipboard/winclipboard.h" #endif +#include "wmutil/mouse.h" +#include "wmutil/keyboard.h" /* * Global variables @@ -169,7 +171,7 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) ErrorF("winWindowProc - WM_DISPLAYCHANGE - new width: %d " "new height: %d new bpp: %d\n", - LOWORD(lParam), HIWORD(lParam), wParam); + LOWORD(lParam), HIWORD(lParam), (int)wParam); /* 0 bpp has no defined meaning, ignore this message */ if (wParam == 0) @@ -292,22 +294,16 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) * the display dimensions change. */ - /* - * NOTE: The non-DirectDraw engines set the ReleasePrimarySurface - * and CreatePrimarySurface function pointers to point - * to the no operation function, NoopDDA. This allows us - * to blindly call these functions, even if they are not - * relevant to the current engine (e.g., Shadow GDI). - */ - winDebug ("winWindowProc - WM_DISPLAYCHANGE - Releasing and recreating primary surface\n"); /* Release the old primary surface */ - (*s_pScreenPriv->pwinReleasePrimarySurface) (s_pScreen); + if (*s_pScreenPriv->pwinReleasePrimarySurface) + (*s_pScreenPriv->pwinReleasePrimarySurface) (s_pScreen); /* Create the new primary surface */ - (*s_pScreenPriv->pwinCreatePrimarySurface) (s_pScreen); + if (*s_pScreenPriv->pwinCreatePrimarySurface) + (*s_pScreenPriv->pwinCreatePrimarySurface) (s_pScreen); } } @@ -324,7 +320,7 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) #endif /* Break if we do not allow resizing */ - if ((s_pScreenInfo->iResizeMode == notAllowed) + if ((s_pScreenInfo->iResizeMode == resizeNotAllowed) || !s_pScreenInfo->fDecoration #ifdef XWIN_MULTIWINDOWEXTWM || s_pScreenInfo->fMWExtWM @@ -911,7 +907,7 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) switch (wParam) { case WIN_E3B_TIMER_ID: /* Send delayed button press */ - winMouseButtonsSendEvent(ButtonPress, + winMouseButtonsSendEvent(TRUE, s_pScreenPriv->iE3BCachedPress); /* Kill this timer */ @@ -1109,14 +1105,6 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) winFixShiftKeys(iScanCode); return 0; - case WM_HOTKEY: - if (s_pScreenPriv == NULL) - break; - - /* Call the engine-specific hot key handler */ - (*s_pScreenPriv->pwinHotKeyAltTab) (s_pScreen); - return 0; - case WM_ACTIVATE: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; diff --git a/hw/xwin/wmutil/Makefile.am b/hw/xwin/wmutil/Makefile.am new file mode 100644 index 000000000..d4e213b7f --- /dev/null +++ b/hw/xwin/wmutil/Makefile.am @@ -0,0 +1,24 @@ +lib_LTLIBRARIES = libXWinWMUtil.la + +library_includedir=$(includedir)/XWinWMUtil + +library_include_HEADERS = \ + icon_convert.h \ + cursor_convert.h \ + mouse.h \ + keyboard.h + +libXWinWMUtil_la_SOURCES = \ + icon_convert.c \ + cursor_convert.c \ + mouse.c \ + keyboard.c \ + winvkmap.h \ + scancodes.h + +AM_CFLAGS = -DHAVE_XWIN_CONFIG_H \ + $(DIX_CFLAGS) \ + $(XWINMODULES_CFLAGS) \ + -I$(top_srcdir) -I$(top_srcdir)/miext/rootless -I$(srcdir)/.. + +libXWinWMUtil_la_LDFLAGS = -static -no-undefined diff --git a/hw/xwin/wmutil/cursor_convert.c b/hw/xwin/wmutil/cursor_convert.c new file mode 100644 index 000000000..b91200478 --- /dev/null +++ b/hw/xwin/wmutil/cursor_convert.c @@ -0,0 +1,351 @@ +/* + *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. + * + *Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + *"Software"), to deal in the Software without restriction, including + *without limitation the rights to use, copy, modify, merge, publish, + *distribute, sublicense, and/or sell copies of the Software, and to + *permit persons to whom the Software is furnished to do so, subject to + *the following conditions: + * + *The above copyright notice and this permission notice shall be + *included in all copies or substantial portions of the Software. + * + *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR + *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + *Except as contained in this notice, the name of the XFree86 Project + *shall not be used in advertising or otherwise to promote the sale, use + *or other dealings in this Software without prior written authorization + *from the XFree86 Project. + * + * Authors: Dakshinamurthy Karra + * Suhaib M Siddiqi + * Peter Busch + * Harold L Hunt II + */ + +#ifdef HAVE_XWIN_CONFIG_H +#include <xwin-config.h> +#endif + +#include <X11/Xwindows.h> + +#include "win.h" +#include "winmsg.h" +#include <cursorstr.h> + +#include "cursor_convert.h" + +#define BRIGHTNESS(x) (x##Red * 0.299 + x##Green * 0.587 + x##Blue * 0.114) + +#if 1 +#define WIN_DEBUG_MSG winDebug +#else +#define WIN_DEBUG_MSG(...) +#endif + +static unsigned char +reverse(unsigned char c) +{ + int i; + unsigned char ret = 0; + + for (i = 0; i < 8; ++i) { + ret |= ((c >> i) & 1) << (7 - i); + } + return ret; +} + +/* + * Convert X cursor to Windows cursor + * FIXME: Perhaps there are more smart code + */ +HCURSOR +winXCursorToHCURSOR(WMUTIL_CURSOR *pCursor) +{ + HCURSOR hCursor = NULL; + unsigned char *pAnd; + unsigned char *pXor; + int nCX, nCY; + int nBytes; + double dForeY, dBackY; + BOOL fReverse; + HBITMAP hAnd, hXor; + ICONINFO ii; + unsigned char *pCur; + unsigned char bit; + HDC hDC; + BITMAPV4HEADER bi; + BITMAPINFO *pbmi; + uint32_t *lpBits; + + int sm_cx = GetSystemMetrics(SM_CXCURSOR); + int sm_cy = GetSystemMetrics(SM_CYCURSOR); + + WIN_DEBUG_MSG("winXCursorToHCURSOR: Win32 size: %dx%d X11 size: %dx%d hotspot: %d,%d\n", + sm_cx, sm_cy, + pCursor->width, pCursor->height, + pCursor->xhot, pCursor->yhot); + + /* We can use only White and Black, so calc brightness of color + * Also check if the cursor is inverted */ + dForeY = BRIGHTNESS(pCursor->fore); + dBackY = BRIGHTNESS(pCursor->back); + fReverse = dForeY < dBackY; + + /* Check whether the X11 cursor is bigger than the win32 cursor */ + if (sm_cx < pCursor->width || + sm_cy < pCursor->height) { + winError("winXCursorToHCURSOR - Windows requires %dx%d cursor but X requires %dx%d\n", + sm_cx, sm_cy, + pCursor->width, pCursor->height); + } + + /* Get the number of bytes required to store the whole cursor image + * This is roughly (sm_cx * sm_cy) / 8 + * round up to 8 pixel boundary so we can convert whole bytes */ + nBytes = + bits_to_bytes(sm_cx) * sm_cy; + + /* Get the effective width and height */ + nCX = min(sm_cx, pCursor->width); + nCY = min(sm_cy, pCursor->height); + + /* Allocate memory for the bitmaps */ + pAnd = malloc(nBytes); + memset(pAnd, 0xFF, nBytes); + pXor = calloc(1, nBytes); + memset(pXor, 0x00, nBytes); + + /* prepare the pointers */ + hCursor = NULL; + lpBits = NULL; + + /* We have a truecolor alpha-blended cursor and can use it! */ + if (pCursor->argb) { + WIN_DEBUG_MSG("winXCursorToHCURSOR: Trying truecolor alphablended cursor\n"); + memset(&bi, 0, sizeof(BITMAPV4HEADER)); + bi.bV4Size = sizeof(BITMAPV4HEADER); + bi.bV4Width = sm_cx; + bi.bV4Height = -(sm_cy); /* right-side up */ + bi.bV4Planes = 1; + bi.bV4BitCount = 32; + bi.bV4V4Compression = BI_BITFIELDS; + bi.bV4RedMask = 0x00FF0000; + bi.bV4GreenMask = 0x0000FF00; + bi.bV4BlueMask = 0x000000FF; + bi.bV4AlphaMask = 0xFF000000; + + lpBits = calloc(sm_cx * sm_cy, sizeof(uint32_t)); + + if (lpBits) { + int y; + for (y = 0; y < nCY; y++) { + void *src, *dst; + src = &(pCursor->argb[y * pCursor->width]); + dst = &(lpBits[y * sm_cx]); + memcpy(dst, src, 4 * nCX); + } + } + } /* End if-truecolor-icon */ + else + { + /* Convert the X11 bitmap to a win32 bitmap + * The first is for an empty mask */ + if (pCursor->emptyMask) { + int x, y, xmax = bits_to_bytes(nCX); + + for (y = 0; y < nCY; ++y) + for (x = 0; x < xmax; ++x) { + int nWinPix = bits_to_bytes(sm_cx) * y + x; + int nXPix = BitmapBytePad(pCursor->width) * y + x; + + pAnd[nWinPix] = 0; + if (fReverse) + pXor[nWinPix] = reverse(~pCursor->source[nXPix]); + else + pXor[nWinPix] = reverse(pCursor->source[nXPix]); + } + } + else { + int x, y, xmax = bits_to_bytes(nCX); + + for (y = 0; y < nCY; ++y) + for (x = 0; x < xmax; ++x) { + int nWinPix = bits_to_bytes(sm_cx) * y + x; + int nXPix = BitmapBytePad(pCursor->width) * y + x; + + unsigned char mask = pCursor->mask[nXPix]; + + pAnd[nWinPix] = reverse(~mask); + if (fReverse) + pXor[nWinPix] = + reverse(~pCursor->source[nXPix] & mask); + else + pXor[nWinPix] = + reverse(pCursor->source[nXPix] & mask); + } + } + } + + if (!lpBits) { + RGBQUAD *pbmiColors; + /* Bicolor, use a palettized DIB */ + WIN_DEBUG_MSG("winXCursorToHCURSOR: Trying two color cursor\n"); + pbmi = (BITMAPINFO *) &bi; + pbmiColors = &(pbmi->bmiColors[0]); + + memset(pbmi, 0, sizeof(BITMAPINFOHEADER)); + pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + pbmi->bmiHeader.biWidth = sm_cx; + pbmi->bmiHeader.biHeight = -abs(sm_cy); /* right-side up */ + pbmi->bmiHeader.biPlanes = 1; + pbmi->bmiHeader.biBitCount = 8; + pbmi->bmiHeader.biCompression = BI_RGB; + pbmi->bmiHeader.biSizeImage = 0; + pbmi->bmiHeader.biClrUsed = 3; + pbmi->bmiHeader.biClrImportant = 3; + + pbmiColors[0].rgbRed = 0; /* Empty */ + pbmiColors[0].rgbGreen = 0; + pbmiColors[0].rgbBlue = 0; + pbmiColors[0].rgbReserved = 0; + pbmiColors[1].rgbRed = pCursor->backRed >> 8; /* Background */ + pbmiColors[1].rgbGreen = pCursor->backGreen >> 8; + pbmiColors[1].rgbBlue = pCursor->backBlue >> 8; + pbmiColors[1].rgbReserved = 0; + pbmiColors[2].rgbRed = pCursor->foreRed >> 8; /* Foreground */ + pbmiColors[2].rgbGreen = pCursor->foreGreen >> 8; + pbmiColors[2].rgbBlue = pCursor->foreBlue >> 8; + pbmiColors[2].rgbReserved = 0; + + lpBits = calloc(sm_cx * sm_cy, 1); + + pCur = (unsigned char *) lpBits; + if (lpBits) { + int x, y; + for (y = 0; y < sm_cy; y++) { + for (x = 0; x < sm_cx; x++) { + if (x >= nCX || y >= nCY) /* Outside of X11 icon bounds */ + (*pCur++) = 0; + else { /* Within X11 icon bounds */ + + int nWinPix = + bits_to_bytes(sm_cx) * y + + (x / 8); + + bit = pAnd[nWinPix]; + bit = bit & (1 << (7 - (x & 7))); + if (!bit) { /* Within the cursor mask? */ + int nXPix = + BitmapBytePad(pCursor->width) * y + + (x / 8); + bit = + ~reverse(~pCursor-> + source[nXPix] & pCursor-> + mask[nXPix]); + bit = bit & (1 << (7 - (x & 7))); + if (bit) /* Draw foreground */ + (*pCur++) = 2; + else /* Draw background */ + (*pCur++) = 1; + } + else /* Outside the cursor mask */ + (*pCur++) = 0; + } + } /* end for (x) */ + } /* end for (y) */ + } /* end if (lpbits) */ + } + + /* If one of the previous two methods gave us the bitmap we need, make a cursor */ + if (lpBits) { + WIN_DEBUG_MSG("winXCursorToHCURSOR: Creating bitmap cursor\n"); + + hAnd = NULL; + hXor = NULL; + + hAnd = + CreateBitmap(sm_cx, sm_cy, + 1, 1, pAnd); + + hDC = GetDC(NULL); + if (hDC) { + hXor = + CreateCompatibleBitmap(hDC, sm_cx, + sm_cy); + SetDIBits(hDC, hXor, 0, sm_cy, lpBits, + (BITMAPINFO *) &bi, DIB_RGB_COLORS); + ReleaseDC(NULL, hDC); + } + free(lpBits); + + if (hAnd && hXor) { + ii.fIcon = FALSE; + ii.xHotspot = pCursor->xhot; + ii.yHotspot = pCursor->yhot; + ii.hbmMask = hAnd; + ii.hbmColor = hXor; + hCursor = (HCURSOR) CreateIconIndirect(&ii); + + if (hCursor == NULL) + winError("winXCursorToHCURSOR - CreateIconIndirect failed: %x", GetLastError()); + else { + /* + Apparently, CreateIconIndirect() sometimes creates an Icon instead of a Cursor. + This breaks the hotspot and makes the cursor unusable. Discard the broken cursor + and revert to simple b&w cursor. (Seen on W2K in 2004...) + */ + if (GetIconInfo(hCursor, &ii)) { + if (ii.fIcon) { + winError + ("winXCursorToHCURSOR: CreateIconIndirect made an icon, not a cursor. Trying again.\n"); + + DestroyCursor(hCursor); + + ii.fIcon = FALSE; + ii.xHotspot = pCursor->xhot; + ii.yHotspot = pCursor->yhot; + hCursor = (HCURSOR) CreateIconIndirect(&ii); + + if (hCursor == NULL) + winError("winXCursorToHCURSOR - CreateIconIndirect failed: %x", GetLastError()); + } + /* GetIconInfo creates new bitmaps. Destroy them again */ + if (ii.hbmMask) + DeleteObject(ii.hbmMask); + if (ii.hbmColor) + DeleteObject(ii.hbmColor); + } + } + } + + if (hAnd) + DeleteObject(hAnd); + if (hXor) + DeleteObject(hXor); + } + + if (!hCursor) { + WIN_DEBUG_MSG("winXCursorToHCURSOR: Creating b&w cursor\n"); + /* We couldn't make a color cursor for this screen, use + black and white instead */ + hCursor = CreateCursor(GetModuleHandle(NULL), + pCursor->xhot, pCursor->yhot, + sm_cx, + sm_cy, pAnd, pXor); + if (hCursor == NULL) + winError("winXCursorToHCURSOR - CreateCursor failed: %x", GetLastError()); + } + free(pAnd); + free(pXor); + + return hCursor; +} diff --git a/hw/xwin/wmutil/cursor_convert.h b/hw/xwin/wmutil/cursor_convert.h new file mode 100644 index 000000000..a5ddba3c2 --- /dev/null +++ b/hw/xwin/wmutil/cursor_convert.h @@ -0,0 +1,54 @@ +/* + * File: cursor_convert.h + * Purpose: interface for X->Windows cursor conversion + * + * Copyright (c) Jon TURNEY 2012 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE ABOVE LISTED COPYRIGHT HOLDER(S) 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. + */ + +#ifndef WMUTILS_CURSOR_H +#define WMUTILS_CURSOR_H + +#include <stdbool.h> +#include <stdint.h> + +typedef struct _WMUTIL_CURSOR +{ + // this is the data for cursor created with RENDER CreateCusor or read + // with XFIXES GetCursorImage + int width; + int height; + int xhot; + int yhot; + uint32_t *argb; + + // for a core CreateCursor, we might need the following... + unsigned char *source; + unsigned char *mask; + bool emptyMask; + unsigned short foreRed, foreGreen, foreBlue; + unsigned short backRed, backGreen, backBlue; + +} WMUTIL_CURSOR; + +HCURSOR +winXCursorToHCURSOR(WMUTIL_CURSOR *cursordata); + +#endif /* WMUTILS_CURSOR_H */ diff --git a/hw/xwin/wmutil/icon_convert.c b/hw/xwin/wmutil/icon_convert.c new file mode 100644 index 000000000..5861a8c7c --- /dev/null +++ b/hw/xwin/wmutil/icon_convert.c @@ -0,0 +1,571 @@ +/* + *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. + * + *Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + *"Software"), to deal in the Software without restriction, including + *without limitation the rights to use, copy, modify, merge, publish, + *distribute, sublicense, and/or sell copies of the Software, and to + *permit persons to whom the Software is furnished to do so, subject to + *the following conditions: + * + *The above copyright notice and this permission notice shall be + *included in all copies or substantial portions of the Software. + * + *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR + *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + *Except as contained in this notice, the name of the XFree86 Project + *shall not be used in advertising or otherwise to promote the sale, use + *or other dealings in this Software without prior written authorization + *from the XFree86 Project. + * + * Authors: Earle F. Philhower, III + */ + +#ifdef HAVE_XWIN_CONFIG_H +#include <xwin-config.h> +#endif + +#ifndef WINVER +#define WINVER 0x0500 +#endif + +#include <xcb/xcb.h> +#include <xcb/xcb_icccm.h> +#include <xcb/xcb_image.h> + +#include <windows.h> + +#include <limits.h> +#include <stdbool.h> + +#include "winmsg.h" + +#include "icon_convert.h" + +extern unsigned long serverGeneration; + +/* + * Scale an X icon ZPixmap into a Windoze icon bitmap + */ + +static void +winScaleXImageToWindowsIcon(int iconSize, + int effBPP, + int stride, xcb_image_t* pixmap, unsigned char *image) +{ + int row, column, effXBPP, effXDepth; + unsigned char *outPtr; + unsigned char *iconData = 0; + int xStride; + float factX, factY; + int posX, posY; + unsigned char *ptr; + unsigned int zero; + unsigned int color; + + effXBPP = pixmap->bpp; + if (pixmap->bpp == 15) + effXBPP = 16; + + effXDepth = pixmap->depth; + if (pixmap->depth == 15) + effXDepth = 16; + + xStride = pixmap->stride; + if (stride == 0 || xStride == 0) { + winError("winScaleXBitmapToWindows - stride or xStride is zero. " + "Bailing.\n"); + return; + } + + /* Get icon data */ + iconData = (unsigned char *) pixmap->data; + + /* Keep aspect ratio */ + factX = ((float) pixmap->width) / ((float) iconSize); + factY = ((float) pixmap->height) / ((float) iconSize); + if (factX > factY) + factY = factX; + else + factX = factY; + + /* Out-of-bounds, fill icon with zero */ + zero = 0; + + for (row = 0; row < iconSize; row++) { + outPtr = image + stride * row; + for (column = 0; column < iconSize; column++) { + posX = factX * column; + posY = factY * row; + + ptr = (unsigned char *) iconData + posY * xStride; + if (effXBPP == 1) { + ptr += posX / 8; + + /* Out of X icon bounds, leave space blank */ + if (posX >= pixmap->width || posY >= pixmap->height) + ptr = (unsigned char *) &zero; + + if ((*ptr) & (1 << (posX & 7))) + switch (effBPP) { + case 32: + *(outPtr++) = 0; + case 24: + *(outPtr++) = 0; + case 16: + *(outPtr++) = 0; + case 8: + *(outPtr++) = 0; + break; + case 1: + outPtr[column / 8] &= ~(1 << (7 - (column & 7))); + break; + } + else + switch (effBPP) { + case 32: + *(outPtr++) = 255; + *(outPtr++) = 255; + *(outPtr++) = 255; + *(outPtr++) = 0; + break; + case 24: + *(outPtr++) = 255; + case 16: + *(outPtr++) = 255; + case 8: + *(outPtr++) = 255; + break; + case 1: + outPtr[column / 8] |= (1 << (7 - (column & 7))); + break; + } + } + else if (effXDepth == 24 || effXDepth == 32) { + ptr += posX * (effXBPP / 8); + + /* Out of X icon bounds, leave space blank */ + if (posX >= pixmap->width || posY >= pixmap->height) + ptr = (unsigned char *) &zero; + color = (((*ptr) << 16) + + ((*(ptr + 1)) << 8) + + ((*(ptr + 2)) << 0)); + switch (effBPP) { + case 32: + *(outPtr++) = *(ptr++); /* b */ + *(outPtr++) = *(ptr++); /* g */ + *(outPtr++) = *(ptr++); /* r */ + *(outPtr++) = (effXDepth == 32) ? *(ptr++) : 0x0; /* alpha */ + break; + case 24: + *(outPtr++) = *(ptr++); + *(outPtr++) = *(ptr++); + *(outPtr++) = *(ptr++); + break; + case 16: + color = ((((*ptr) >> 2) << 10) + + (((*(ptr + 1)) >> 2) << 5) + + (((*(ptr + 2)) >> 2))); + *(outPtr++) = (color >> 8); + *(outPtr++) = (color & 255); + break; + case 8: + color = (((*ptr))) + (((*(ptr + 1)))) + (((*(ptr + 2)))); + color /= 3; + *(outPtr++) = color; + break; + case 1: + if (color) + outPtr[column / 8] |= (1 << (7 - (column & 7))); + else + outPtr[column / 8] &= ~(1 << (7 - (column & 7))); + } + } + else if (effXDepth == 16) { + ptr += posX * (effXBPP / 8); + + /* Out of X icon bounds, leave space blank */ + if (posX >= pixmap->width || posY >= pixmap->height) + ptr = (unsigned char *) &zero; + color = ((*ptr) << 8) + (*(ptr + 1)); + switch (effBPP) { + case 32: + *(outPtr++) = (color & 31) << 2; + *(outPtr++) = ((color >> 5) & 31) << 2; + *(outPtr++) = ((color >> 10) & 31) << 2; + *(outPtr++) = 0; /* resvd */ + break; + case 24: + *(outPtr++) = (color & 31) << 2; + *(outPtr++) = ((color >> 5) & 31) << 2; + *(outPtr++) = ((color >> 10) & 31) << 2; + break; + case 16: + *(outPtr++) = *(ptr++); + *(outPtr++) = *(ptr++); + break; + case 8: + *(outPtr++) = (((color & 31) + + ((color >> 5) & 31) + + ((color >> 10) & 31)) / 3) << 2; + break; + case 1: + if (color) + outPtr[column / 8] |= (1 << (7 - (column & 7))); + else + outPtr[column / 8] &= ~(1 << (7 - (column & 7))); + break; + } /* end switch(effbpp) */ + } /* end if effxbpp==16) */ + } /* end for column */ + } /* end for row */ +} + +static HICON +NetWMToWinIconAlpha(uint32_t * icon) +{ + int width = icon[0]; + int height = icon[1]; + uint32_t *pixels = &icon[2]; + HICON result; + HDC hdc = GetDC(NULL); + uint32_t *DIB_pixels; + ICONINFO ii; + BITMAPV4HEADER bmh = { sizeof(bmh) }; + + /* Define an ARGB pixel format used for Color+Alpha icons */ + bmh.bV4Width = width; + bmh.bV4Height = -height; /* Invert the image */ + bmh.bV4Planes = 1; + bmh.bV4BitCount = 32; + bmh.bV4V4Compression = BI_BITFIELDS; + bmh.bV4AlphaMask = 0xFF000000; + bmh.bV4RedMask = 0x00FF0000; + bmh.bV4GreenMask = 0x0000FF00; + bmh.bV4BlueMask = 0x000000FF; + + ii.fIcon = TRUE; + ii.xHotspot = 0; /* ignored */ + ii.yHotspot = 0; /* ignored */ + ii.hbmColor = CreateDIBSection(hdc, (BITMAPINFO *) &bmh, + DIB_RGB_COLORS, (void **) &DIB_pixels, NULL, + 0); + ReleaseDC(NULL, hdc); + + if (!ii.hbmColor) + return NULL; + + ii.hbmMask = CreateBitmap(width, height, 1, 1, NULL); + memcpy(DIB_pixels, pixels, height * width * 4); + + /* CreateIconIndirect() traditionally required DDBitmaps */ + /* Systems from WinXP accept 32-bit ARGB DIBitmaps with full 8-bit alpha support */ + /* The icon is created with a DIB + empty DDB mask (an MS example does the same) */ + result = CreateIconIndirect(&ii); + + DeleteObject(ii.hbmColor); + DeleteObject(ii.hbmMask); + + winDebug("NetWMToWinIconAlpha - %d x %d = %p\n", icon[0], icon[1], result); + return result; +} + +static HICON +NetWMToWinIconThreshold(uint32_t * icon) +{ + int width = icon[0]; + int height = icon[1]; + uint32_t *pixels = &icon[2]; + int row, col; + HICON result; + ICONINFO ii; + + HDC hdc = GetDC(NULL); + HDC xorDC = CreateCompatibleDC(hdc); + HDC andDC = CreateCompatibleDC(hdc); + + ii.fIcon = TRUE; + ii.xHotspot = 0; /* ignored */ + ii.yHotspot = 0; /* ignored */ + ii.hbmColor = CreateCompatibleBitmap(hdc, width, height); + ii.hbmMask = CreateCompatibleBitmap(hdc, width, height); + ReleaseDC(NULL, hdc); + SelectObject(xorDC, ii.hbmColor); + SelectObject(andDC, ii.hbmMask); + + for (row = 0; row < height; row++) { + for (col = 0; col < width; col++) { + if ((*pixels & 0xFF000000) > 31 << 24) { /* 31 alpha threshold, i.e. opaque above, transparent below */ + SetPixelV(xorDC, col, row, + RGB(((char *) pixels)[2], ((char *) pixels)[1], + ((char *) pixels)[0])); + SetPixelV(andDC, col, row, RGB(0, 0, 0)); /* black mask */ + } + else { + SetPixelV(xorDC, col, row, RGB(0, 0, 0)); + SetPixelV(andDC, col, row, RGB(255, 255, 255)); /* white mask */ + } + pixels++; + } + } + DeleteDC(xorDC); + DeleteDC(andDC); + + result = CreateIconIndirect(&ii); + + DeleteObject(ii.hbmColor); + DeleteObject(ii.hbmMask); + + winDebug("NetWMToWinIconThreshold - %d x %d = %p\n", icon[0], icon[1], + result); + return result; +} + +static HICON +NetWMToWinIcon(int bpp, uint32_t * icon) +{ + static bool hasIconAlphaChannel = FALSE; + static bool versionChecked = FALSE; + + if (!versionChecked) { + OSVERSIONINFOEX osvi = { 0 }; + ULONGLONG dwlConditionMask = 0; + + osvi.dwOSVersionInfoSize = sizeof(osvi); + osvi.dwMajorVersion = 5; + osvi.dwMinorVersion = 1; + + /* Windows versions later than XP have icon alpha channel suport, 2000 does not */ + VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, + VER_GREATER_EQUAL); + VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, + VER_GREATER_EQUAL); + hasIconAlphaChannel = + VerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION, + dwlConditionMask); + versionChecked = TRUE; + + winError("OS has icon alpha channel support: %s\n", + hasIconAlphaChannel ? "yes" : "no"); + } + + if (hasIconAlphaChannel && (bpp == 32)) + return NetWMToWinIconAlpha(icon); + else + return NetWMToWinIconThreshold(icon); +} + +/* + * Attempt to create a custom icon from the WM_HINTS bitmaps + */ + +HICON +winXIconToHICON(xcb_connection_t *conn, xcb_window_t id, int iconSize) +{ + unsigned char *mask, *image = NULL, *imageMask; + unsigned char *dst, *src; + int planes, bpp, i; + unsigned int biggest_size = 0; + HDC hDC; + ICONINFO ii; + xcb_icccm_wm_hints_t hints; + HICON hIcon = NULL; + uint32_t *biggest_icon = NULL; + static xcb_atom_t _XA_NET_WM_ICON; + static int generation; + uint32_t *icon, *icon_data = NULL; + unsigned long int size; + + hDC = GetDC(GetDesktopWindow()); + planes = GetDeviceCaps(hDC, PLANES); + bpp = GetDeviceCaps(hDC, BITSPIXEL); + ReleaseDC(GetDesktopWindow(), hDC); + + /* Always prefer _NET_WM_ICON icons */ + if (generation != serverGeneration) { + xcb_intern_atom_reply_t *atom_reply; + xcb_intern_atom_cookie_t atom_cookie; + const char *atomName = "_NET_WM_ICON"; + + generation = serverGeneration; + + _XA_NET_WM_ICON = XCB_NONE; + + atom_cookie = xcb_intern_atom(conn, 0, strlen(atomName), atomName); + atom_reply = xcb_intern_atom_reply(conn, atom_cookie, NULL); + if (atom_reply) { + _XA_NET_WM_ICON = atom_reply->atom; + free(atom_reply); + } + } + + { + xcb_get_property_cookie_t cookie = xcb_get_property(conn, FALSE, id, _XA_NET_WM_ICON, XCB_ATOM_CARDINAL, 0L, INT_MAX); + xcb_get_property_reply_t *reply = xcb_get_property_reply(conn, cookie, NULL); + + if (reply && + ((icon_data = xcb_get_property_value(reply)) != NULL)) { + size = xcb_get_property_value_length(reply)/sizeof(uint32_t); + for (icon = icon_data; icon < &icon_data[size] && *icon; + icon = &icon[icon[0] * icon[1] + 2]) { + winDebug("winXIconToHICON: %u x %u NetIcon\n", icon[0], icon[1]); + + /* Icon data size will overflow an int and thus is bigger than the + property can possibly be */ + if ((INT_MAX/icon[0]) < icon[1]) { + winDebug("winXIconToHICON: _NET_WM_ICON icon data size overflow\n"); + break; + } + + /* Icon data size is bigger than amount of data remaining */ + if (&icon[icon[0] * icon[1] + 2] > &icon_data[size]) { + winDebug("winXIconToHICON: _NET_WM_ICON data is malformed\n"); + break; + } + + /* Found an exact match to the size we require... */ + if (icon[0] == iconSize && icon[1] == iconSize) { + winDebug("winXIconToHICON: selected %d x %d NetIcon\n", + iconSize, iconSize); + hIcon = NetWMToWinIcon(bpp, icon); + break; + } + /* Otherwise, find the biggest icon and let Windows scale the size */ + else if (biggest_size < icon[0]) { + biggest_icon = icon; + biggest_size = icon[0]; + } + } + + if (!hIcon && biggest_icon) { + winDebug + ("winXIconToHICON: selected %u x %u NetIcon for scaling to %d x %d\n", + biggest_icon[0], biggest_icon[1], iconSize, iconSize); + + hIcon = NetWMToWinIcon(bpp, biggest_icon); + } + + free(reply); + } + } + + if (!hIcon) { + xcb_get_property_cookie_t wm_hints_cookie; + + winDebug("winXIconToHICON: no suitable NetIcon\n"); + + wm_hints_cookie = xcb_icccm_get_wm_hints(conn, id); + if (xcb_icccm_get_wm_hints_reply(conn, wm_hints_cookie, &hints, NULL)) { + winDebug("winXIconToHICON: id 0x%x icon_pixmap hint %x\n", id, + hints.icon_pixmap); + + if (hints.icon_pixmap) { + unsigned int width, height; + xcb_image_t *xImageIcon; + xcb_image_t *xImageMask = NULL; + + xcb_get_geometry_cookie_t geom_cookie = xcb_get_geometry(conn, hints.icon_pixmap); + xcb_get_geometry_reply_t *geom_reply = xcb_get_geometry_reply(conn, geom_cookie, NULL); + + if (geom_reply) { + width = geom_reply->width; + height = geom_reply->height; + + xImageIcon = xcb_image_get(conn, hints.icon_pixmap, + 0, 0, width, height, + 0xFFFFFF, XCB_IMAGE_FORMAT_Z_PIXMAP); + + winDebug("winXIconToHICON: id 0x%x icon Ximage 0x%p\n", id, + xImageIcon); + + if (hints.icon_mask) + xImageMask = xcb_image_get(conn, hints.icon_mask, + 0, 0, width, height, + 0xFFFFFFFF, XCB_IMAGE_FORMAT_Z_PIXMAP); + + if (xImageIcon) { + int effBPP, stride, maskStride; + + /* 15 BPP is really 16BPP as far as we care */ + if (bpp == 15) + effBPP = 16; + else + effBPP = bpp; + + /* Need 16-bit aligned rows for DDBitmaps */ + stride = ((iconSize * effBPP + 15) & (~15)) / 8; + + /* Mask is 1-bit deep */ + maskStride = ((iconSize * 1 + 15) & (~15)) / 8; + + image = malloc(stride * iconSize); + imageMask = malloc(stride * iconSize); + mask = malloc(maskStride * iconSize); + + /* Default to a completely black mask */ + memset(imageMask, 0, stride * iconSize); + memset(mask, 0, maskStride * iconSize); + + winScaleXImageToWindowsIcon(iconSize, effBPP, stride, + xImageIcon, image); + + if (xImageMask) { + winScaleXImageToWindowsIcon(iconSize, 1, maskStride, + xImageMask, mask); + winScaleXImageToWindowsIcon(iconSize, effBPP, stride, + xImageMask, imageMask); + } + + /* Now we need to set all bits of the icon which are not masked */ + /* on to 0 because Color is really an XOR, not an OR function */ + dst = image; + src = imageMask; + + for (i = 0; i < (stride * iconSize); i++) + if ((*(src++))) + *(dst++) = 0; + else + dst++; + + ii.fIcon = TRUE; + ii.xHotspot = 0; /* ignored */ + ii.yHotspot = 0; /* ignored */ + + /* Create Win32 mask from pixmap shape */ + ii.hbmMask = + CreateBitmap(iconSize, iconSize, planes, 1, mask); + + /* Create Win32 bitmap from pixmap */ + ii.hbmColor = + CreateBitmap(iconSize, iconSize, planes, bpp, image); + + /* Merge Win32 mask and bitmap into icon */ + hIcon = CreateIconIndirect(&ii); + + /* Release Win32 mask and bitmap */ + DeleteObject(ii.hbmMask); + DeleteObject(ii.hbmColor); + + /* Free X mask and bitmap */ + free(mask); + free(image); + free(imageMask); + + if (xImageMask) + xcb_image_destroy(xImageMask); + + xcb_image_destroy(xImageIcon); + } + } + } + } + } + return hIcon; +} diff --git a/hw/xwin/wmutil/icon_convert.h b/hw/xwin/wmutil/icon_convert.h new file mode 100644 index 000000000..0065326be --- /dev/null +++ b/hw/xwin/wmutil/icon_convert.h @@ -0,0 +1,34 @@ +/* + * File: icons.h + * Purpose: interface for X->Windows icon conversion + * + * Copyright (c) Jon TURNEY 2012 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE ABOVE LISTED COPYRIGHT HOLDER(S) 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. + */ + +#ifndef WMUTILS_ICONS_H +#define WMUTILS_ICONS_H + +#include <xcb/xcb.h> + +HICON +winXIconToHICON(xcb_connection_t *conn, xcb_window_t id, int iconSize); + +#endif /* WMUTILS_ICONS_H */ diff --git a/hw/xwin/wmutil/keyboard.c b/hw/xwin/wmutil/keyboard.c new file mode 100644 index 000000000..3f785e7d8 --- /dev/null +++ b/hw/xwin/wmutil/keyboard.c @@ -0,0 +1,308 @@ +/* + *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. + * + *Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + *"Software"), to deal in the Software without restriction, including + *without limitation the rights to use, copy, modify, merge, publish, + *distribute, sublicense, and/or sell copies of the Software, and to + *permit persons to whom the Software is furnished to do so, subject to + *the following conditions: + * + *The above copyright notice and this permission notice shall be + *included in all copies or substantial portions of the Software. + * + *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR + *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + *Except as contained in this notice, the name of the XFree86 Project + *shall not be used in advertising or otherwise to promote the sale, use + *or other dealings in this Software without prior written authorization + *from the XFree86 Project. + * + * Authors: Dakshinamurthy Karra + * Suhaib M Siddiqi + * Peter Busch + * Harold L Hunt II + */ + +#ifdef HAVE_XWIN_CONFIG_H +#include <xwin-config.h> +#endif + +#include <X11/Xwindows.h> +#include <X11/Xmd.h> // to provide a BYTE type, since the Windows one is eclipsed + +#include "winvkmap.h" +#include "keyboard.h" + +#include "winmsg.h" + +static bool g_winKeyState[NUM_KEYCODES]; + +/* + * Translate a Windows WM_[SYS]KEY(UP/DOWN) message + * into an ASCII scan code. + * + * We do this ourselves, rather than letting Windows handle it, + * because Windows tends to munge the handling of special keys, + * like AltGr on European keyboards. + */ + +int +winTranslateKey(WPARAM wParam, LPARAM lParam) +{ + int iKeyFixup = g_iKeyMap[wParam * WIN_KEYMAP_COLS + 1]; + int iKeyFixupEx = g_iKeyMap[wParam * WIN_KEYMAP_COLS + 2]; + int iParam = HIWORD(lParam); + int iParamScanCode = LOBYTE(iParam); + int iScanCode; + + winDebug("winTranslateKey: wParam %08x lParam %08x\n", (unsigned int)wParam, (unsigned int)lParam); + +/* WM_ key messages faked by Vista speech recognition (WSR) don't have a + * scan code. + * + * Vocola 3 (Rick Mohr's supplement to WSR) uses + * System.Windows.Forms.SendKeys.SendWait(), which appears always to give a + * scan code of 1 + */ + if (iParamScanCode <= 1) { + if (VK_PRIOR <= wParam && wParam <= VK_DOWN) + /* Trigger special case table to translate to extended + * keycode, otherwise if num_lock is on, we can get keypad + * numbers instead of navigation keys. */ + iParam |= KF_EXTENDED; + else + iParamScanCode = MapVirtualKeyEx(wParam, + /*MAPVK_VK_TO_VSC */ 0, + GetKeyboardLayout(0)); + } + + /* Branch on special extended, special non-extended, or normal key */ + if ((iParam & KF_EXTENDED) && iKeyFixupEx) + iScanCode = iKeyFixupEx; + else if (iKeyFixup) + iScanCode = iKeyFixup; + else if (wParam == 0 && iParamScanCode == 0x70) + iScanCode = KEY_HKTG; + else + switch (iParamScanCode) { + case 0x70: + iScanCode = KEY_HKTG; + break; + case 0x73: + iScanCode = KEY_BSlash2; + break; + default: + iScanCode = iParamScanCode; + break; + } + + return iScanCode; +} + +/* + * Look for the lovely fake Control_L press/release generated by Windows + * when AltGr is pressed/released on a non-U.S. keyboard. + */ + +bool +winIsFakeCtrl_L(UINT message, WPARAM wParam, LPARAM lParam) +{ + MSG msgNext; + LONG lTime; + bool fReturn; + + static bool lastWasControlL = FALSE; + static LONG lastTime; + + /* + * Fake Ctrl_L presses will be followed by an Alt_R press + * with the same timestamp as the Ctrl_L press. + */ + if ((message == WM_KEYDOWN || message == WM_SYSKEYDOWN) + && wParam == VK_CONTROL && (HIWORD(lParam) & KF_EXTENDED) == 0) { + /* Got a Ctrl_L press */ + + /* Get time of current message */ + lTime = GetMessageTime(); + + /* Look for next press message */ + fReturn = PeekMessage(&msgNext, NULL, + WM_KEYDOWN, WM_SYSKEYDOWN, PM_NOREMOVE); + + if (fReturn && msgNext.message != WM_KEYDOWN && + msgNext.message != WM_SYSKEYDOWN) + fReturn = 0; + + if (!fReturn) { + lastWasControlL = TRUE; + lastTime = lTime; + } + else { + lastWasControlL = FALSE; + } + + /* Is next press an Alt_R with the same timestamp? */ + if (fReturn && msgNext.wParam == VK_MENU + && msgNext.time == lTime + && (HIWORD(msgNext.lParam) & KF_EXTENDED)) { + /* + * Next key press is Alt_R with same timestamp as current + * Ctrl_L message. Therefore, this Ctrl_L press is a fake + * event, so discard it. + */ + return TRUE; + } + } + /* + * Sometimes, the Alt_R press message is not yet posted when the + * fake Ctrl_L press message arrives (even though it has the + * same timestamp), so check for an Alt_R press message that has + * arrived since the last Ctrl_L message. + */ + else if ((message == WM_KEYDOWN || message == WM_SYSKEYDOWN) + && wParam == VK_MENU && (HIWORD(lParam) & KF_EXTENDED)) { + /* Got a Alt_R press */ + + if (lastWasControlL) { + lTime = GetMessageTime(); + + if (lastTime == lTime) { + /* Undo the fake Ctrl_L press by sending a fake Ctrl_L release */ + winSendKeyEvent(KEY_LCtrl, FALSE); + } + lastWasControlL = FALSE; + } + } + /* + * Fake Ctrl_L releases will be followed by an Alt_R release + * with the same timestamp as the Ctrl_L release. + */ + else if ((message == WM_KEYUP || message == WM_SYSKEYUP) + && wParam == VK_CONTROL && (HIWORD(lParam) & KF_EXTENDED) == 0) { + /* Got a Ctrl_L release */ + + /* Get time of current message */ + lTime = GetMessageTime(); + + /* Look for next release message */ + fReturn = PeekMessage(&msgNext, NULL, + WM_KEYUP, WM_SYSKEYUP, PM_NOREMOVE); + + if (fReturn && msgNext.message != WM_KEYUP && + msgNext.message != WM_SYSKEYUP) + fReturn = 0; + + lastWasControlL = FALSE; + + /* Is next press an Alt_R with the same timestamp? */ + if (fReturn + && (msgNext.message == WM_KEYUP || msgNext.message == WM_SYSKEYUP) + && msgNext.wParam == VK_MENU + && msgNext.time == lTime + && (HIWORD(msgNext.lParam) & KF_EXTENDED)) { + /* + * Next key release is Alt_R with same timestamp as current + * Ctrl_L message. Therefore, this Ctrl_L release is a fake + * event, so discard it. + */ + return TRUE; + } + } + else { + /* On any other press or release message, we don't have a + potentially fake Ctrl_L to worry about anymore... */ + lastWasControlL = FALSE; + } + + /* Not a fake control left press/release */ + return FALSE; +} + +/* + * Lift any modifier keys that are pressed + */ + +void +winKeybdReleaseKeys(void) +{ + int i; + + /* Loop through all keys */ + for (i = 0; i < NUM_KEYCODES; ++i) { + /* Pop key if pressed */ + if (g_winKeyState[i]) + winSendKeyEvent(i, FALSE); + + /* Reset pressed flag for keys */ + g_winKeyState[i] = FALSE; + } +} + +/* + * Take a raw X key code and send an up or down event for it. + * + * Thanks to VNC for inspiration, though it is a simple function. + */ + +void +winSendKeyEvent(DWORD dwKey, bool fDown) +{ + /* + * When alt-tabing between screens we can get phantom key up messages + * Here we only pass them through it we think we should! + */ + if (g_winKeyState[dwKey] == FALSE && fDown == FALSE) + return; + + /* Update the keyState map */ + g_winKeyState[dwKey] = fDown; + + winSendKeyEventCallback(dwKey + MIN_KEYCODE, fDown); + + winDebug("winSendKeyEvent: dwKey: %d, fDown: %d\n", dwKey, fDown); +} + +bool +winCheckKeyPressed(WPARAM wParam, LPARAM lParam) +{ + switch (wParam) { + case VK_CONTROL: + if ((lParam & 0x1ff0000) == 0x11d0000 && g_winKeyState[KEY_RCtrl]) + return TRUE; + if ((lParam & 0x1ff0000) == 0x01d0000 && g_winKeyState[KEY_LCtrl]) + return TRUE; + break; + case VK_SHIFT: + if ((lParam & 0x1ff0000) == 0x0360000 && g_winKeyState[KEY_ShiftR]) + return TRUE; + if ((lParam & 0x1ff0000) == 0x02a0000 && g_winKeyState[KEY_ShiftL]) + return TRUE; + break; + default: + return TRUE; + } + return FALSE; +} + +/* Only one shift release message is sent even if both are pressed. + * Fix this here + */ +void +winFixShiftKeys(int iScanCode) +{ + if (GetKeyState(VK_SHIFT) & 0x8000) + return; + + if (iScanCode == KEY_ShiftL && g_winKeyState[KEY_ShiftR]) + winSendKeyEvent(KEY_ShiftR, FALSE); + if (iScanCode == KEY_ShiftR && g_winKeyState[KEY_ShiftL]) + winSendKeyEvent(KEY_ShiftL, FALSE); +} diff --git a/hw/xwin/wmutil/keyboard.h b/hw/xwin/wmutil/keyboard.h new file mode 100644 index 000000000..5b229c25c --- /dev/null +++ b/hw/xwin/wmutil/keyboard.h @@ -0,0 +1,39 @@ +/* + * File: keyboard.h + * Purpose: interface for X->Windows keyboard event conversion + * + * Copyright (c) Jon TURNEY 2012 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE ABOVE LISTED COPYRIGHT HOLDER(S) 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. + */ + +#ifndef WMUTILS_KEYBOARD_H +#define WMUTILS_KEYBOARD_H + +#include <stdbool.h> + +void winSendKeyEvent(DWORD dwKey, bool fDown); +void winSendKeyEventCallback(DWORD dwKey, bool fDown); +void winKeybdReleaseKeys(void); +bool winIsFakeCtrl_L(UINT message, WPARAM wParam, LPARAM lParam); +bool winCheckKeyPressed(WPARAM wParam, LPARAM lParam); +int winTranslateKey(WPARAM wParam, LPARAM lParam); +void winFixShiftKeys(int iScanCode); + +#endif /* WMUTILS_KEYBOARD_H */ diff --git a/hw/xwin/wmutil/mouse.c b/hw/xwin/wmutil/mouse.c new file mode 100644 index 000000000..ba58f067a --- /dev/null +++ b/hw/xwin/wmutil/mouse.c @@ -0,0 +1,111 @@ +/* + *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. + * + *Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + *"Software"), to deal in the Software without restriction, including + *without limitation the rights to use, copy, modify, merge, publish, + *distribute, sublicense, and/or sell copies of the Software, and to + *permit persons to whom the Software is furnished to do so, subject to + *the following conditions: + * + *The above copyright notice and this permission notice shall be + *included in all copies or substantial portions of the Software. + * + *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR + *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + *Except as contained in this notice, the name of the XFree86 Project + *shall not be used in advertising or otherwise to promote the sale, use + *or other dealings in this Software without prior written authorization + *from the XFree86 Project. + * + * Authors: Dakshinamurthy Karra + * Suhaib M Siddiqi + * Peter Busch + * Harold L Hunt II + */ + +#ifdef HAVE_XWIN_CONFIG_H +#include <xwin-config.h> +#endif + +#include <X11/Xwindows.h> +#include <X11/X.h> + +#include "mouse.h" + +/* Handle the mouse wheel */ +void +winMouseWheel(int *iTotalDeltaZ, int iDeltaZ, int iButtonUp, int iButtonDown) +{ + int button; + + /* Do we have any previous delta stored? */ + if ((*iTotalDeltaZ > 0 && iDeltaZ > 0) + || (*iTotalDeltaZ < 0 && iDeltaZ < 0)) { + /* Previous delta and of same sign as current delta */ + iDeltaZ += *iTotalDeltaZ; + *iTotalDeltaZ = 0; + } + else { + /* + * Previous delta of different sign, or zero. + * We will set it to zero for either case, + * as blindly setting takes just as much time + * as checking, then setting if necessary :) + */ + *iTotalDeltaZ = 0; + } + + /* + * Only process this message if the wheel has moved further than + * WHEEL_DELTA + */ + if (iDeltaZ >= WHEEL_DELTA || (-1 * iDeltaZ) >= WHEEL_DELTA) { + *iTotalDeltaZ = 0; + + /* Figure out how many whole deltas of the wheel we have */ + iDeltaZ /= WHEEL_DELTA; + } + else { + /* + * Wheel has not moved past WHEEL_DELTA threshold; + * we will store the wheel delta until the threshold + * has been reached. + */ + *iTotalDeltaZ = iDeltaZ; + return; + } + + /* Set the button to indicate up or down wheel delta */ + if (iDeltaZ > 0) { + button = iButtonUp; + } + else { + button = iButtonDown; + } + + /* + * Flip iDeltaZ to positive, if negative, + * because always need to generate a *positive* number of + * button clicks for the Z axis. + */ + if (iDeltaZ < 0) { + iDeltaZ *= -1; + } + + /* Generate X input messages for each wheel delta we have seen */ + while (iDeltaZ--) { + /* Push the wheel button */ + winMouseButtonsSendEvent(TRUE, button); + + /* Release the wheel button */ + winMouseButtonsSendEvent(FALSE, button); + } +} diff --git a/hw/xwin/wmutil/mouse.h b/hw/xwin/wmutil/mouse.h new file mode 100644 index 000000000..8bd6fe9eb --- /dev/null +++ b/hw/xwin/wmutil/mouse.h @@ -0,0 +1,36 @@ +/* + * File: mouse.h + * Purpose: interface for X->Windows mouse event conversion + * + * Copyright (c) Jon TURNEY 2012 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE ABOVE LISTED COPYRIGHT HOLDER(S) 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. + */ + +#ifndef WMUTILS_MOUSE_H +#define WMUTILS_MOUSE_H + +#include <stdbool.h> + +void winMouseWheel(int *iTotalDeltaz, int iDeltaZ, int iButtonUp, int iButtonDown); + +/* Callback for sending mouse button events */ +void winMouseButtonsSendEvent(bool bPress, int iButton); + +#endif /* WMUTILS_MOUSE_H */ diff --git a/hw/xwin/winkeynames.h b/hw/xwin/wmutil/scancodes.h index bfed9d427..3215a4bcb 100644 --- a/hw/xwin/winkeynames.h +++ b/hw/xwin/wmutil/scancodes.h @@ -1,5 +1,3 @@ -#ifndef _WINKEYNAMES_H -#define _WINKEYNAMES_H /* * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. * @@ -23,18 +21,8 @@ * */ -#define GLYPHS_PER_KEY 4 -#define NUM_KEYCODES 248 -#define MIN_KEYCODE 8 -#define MAX_KEYCODE (NUM_KEYCODES + MIN_KEYCODE - 1) - -#define AltMask Mod1Mask -#define NumLockMask Mod2Mask -#define AltLangMask Mod3Mask -#define KanaMask Mod4Mask -#define ScrollLockMask Mod5Mask - -#define ModifierDown(k) ((keyc->state & (k)) == (k)) +#ifndef SCANCODES_H +#define SCANCODES_H /* * NOTE: The AT/MF keyboards can generate (via the 8042) two (MF: three) @@ -203,4 +191,4 @@ #define KEY_NOTUSED 0 #define KEY_UNKNOWN 255 -#endif /* _WINKEYNAMES_H */ +#endif /* SCANCODES_H */ diff --git a/hw/xwin/winkeybd.h b/hw/xwin/wmutil/winvkmap.h index 6701f0959..eff61c7f9 100644 --- a/hw/xwin/winkeybd.h +++ b/hw/xwin/wmutil/winvkmap.h @@ -1,5 +1,3 @@ -#if !defined(WINKEYBD_H) -#define WINKEYBD_H /* *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. * @@ -30,10 +28,17 @@ * Authors: Harold L Hunt II */ +#ifndef WINVKMAP_H +#define WINVKMAP_H + /* * We need symbols for the scan codes of keys. */ -#include "winkeynames.h" +#include "scancodes.h" + +#define NUM_KEYCODES 248 +#define MIN_KEYCODE 8 +#define MAX_KEYCODE (NUM_KEYCODES + MIN_KEYCODE - 1) #define VK_FN 0xFF @@ -268,8 +273,7 @@ const int /* 220 */ 0, 0, 0, /* 221 */ 0, 0, 0, /* 222 */ 0, 0, 0, - /* 223 */ VK_OEM_8, 0, KEY_RCtrl, - /* at least on Canadian Multilingual Standard layout */ + /* 223 */ VK_OEM_8, 0, KEY_RCtrl, /* at least on Canadian Multilingual Standard layout */ /* 224 */ 0, 0, 0, /* 225 */ 0, 0, 0, /* 226 */ 0, 0, 0, @@ -301,8 +305,7 @@ const int /* 252 */ 0, 0, 0, /* 253 */ 0, 0, 0, /* 254 */ 0, 0, 0, - /* 255 */ VK_FN, 0, KEY_Fn - /* Most keyboards don't generate a scancode for Fn, but a few do... */ + /* 255 */ VK_FN, 0, KEY_Fn /* Most keyboards don't generate a scancode for Fn, but a few do... */ }; -#endif /* WINKEYBD_H */ +#endif /* WINVKMAP_H */ diff --git a/include/extinit.h b/include/extinit.h index fa5f29378..10f7b4620 100644 --- a/include/extinit.h +++ b/include/extinit.h @@ -163,7 +163,7 @@ extern void SELinuxExtensionInit(void); extern void XTestExtensionInit(void); #endif -#ifdef INXQUARTZ +#ifndef SDKSYMS extern _X_EXPORT Bool noPseudoramiXExtension; extern void PseudoramiXExtensionInit(void); #endif diff --git a/include/os.h b/include/os.h index 3c3954f8d..da20427fd 100644 --- a/include/os.h +++ b/include/os.h @@ -51,6 +51,7 @@ SOFTWARE. #include <stdarg.h> #include <stdint.h> #include <string.h> +#include <signal.h> #define SCREEN_SAVER_ON 0 #define SCREEN_SAVER_OFF 1 @@ -332,6 +333,10 @@ extern _X_EXPORT void * Fopen(const char *, const char *); extern _X_EXPORT int Fclose(void *); +#if defined(__CYGWIN__) +extern const char * +Win32TempDir(void); +#endif #else extern const char * @@ -665,6 +670,12 @@ LogPrintMarkers(void); extern _X_EXPORT void xorg_backtrace(void); +extern _X_EXPORT void +xorg_crashreport(int signo, siginfo_t *sip, void *sigcontext); + +extern _X_EXPORT void +xorg_crashreport_init(const char *logfile); + extern _X_EXPORT int os_move_fd(int fd); diff --git a/include/protocol-versions.h b/include/protocol-versions.h index fc428c8cf..bce032a74 100644 --- a/include/protocol-versions.h +++ b/include/protocol-versions.h @@ -111,6 +111,11 @@ #define SERVER_SYNC_MAJOR_VERSION 3 #define SERVER_SYNC_MINOR_VERSION 1 +/* Windows DRI */ +#define SERVER_WINDOWSDRI_MAJOR_VERSION 1 +#define SERVER_WINDOWSDRI_MINOR_VERSION 0 +#define SERVER_WINDOWSDRI_PATCH_VERSION 0 + /* Windows WM */ #define SERVER_WINDOWSWM_MAJOR_VERSION 1 #define SERVER_WINDOWSWM_MINOR_VERSION 0 diff --git a/include/scrnintstr.h b/include/scrnintstr.h index faf05630c..efc60d2e3 100644 --- a/include/scrnintstr.h +++ b/include/scrnintstr.h @@ -157,6 +157,10 @@ typedef void (*PostValidateTreeProcPtr) (WindowPtr /*pParent */ , typedef void (*WindowExposuresProcPtr) (WindowPtr /*pWindow */ , RegionPtr /*prgn */); +typedef void (* PaintWindowProcPtr) (WindowPtr /*pWindow*/ , + RegionPtr /*pRegion*/ , + int /*what*/ ); + typedef void (*CopyWindowProcPtr) (WindowPtr /*pWindow */ , DDXPointRec /*ptOldOrg */ , RegionPtr /*prgnSrc */ ); @@ -491,6 +495,7 @@ typedef struct _Screen { ValidateTreeProcPtr ValidateTree; PostValidateTreeProcPtr PostValidateTree; WindowExposuresProcPtr WindowExposures; + PaintWindowProcPtr PaintWindow; CopyWindowProcPtr CopyWindow; ClearToBackgroundProcPtr ClearToBackground; ClipNotifyProcPtr ClipNotify; diff --git a/man/Xserver.man b/man/Xserver.man index bc4c7fc5f..8b8f0af0f 100644 --- a/man/Xserver.man +++ b/man/Xserver.man @@ -578,9 +578,6 @@ Outline font directories .I /tmp/.X11-unix/X\fBn\fP Unix domain socket for display number \fBn\fP .TP 30 -.I /usr/adm/X\fBn\fPmsgs -Error log file for display number \fBn\fP if run from \fIinit\fP(__adminmansuffix__) -.TP 30 .I __projectroot__/lib/X11/xdm/xdm-errors Default error log file if the server is run from \fIxdm\fP(1) .SH "SEE ALSO" diff --git a/mi/miexpose.c b/mi/miexpose.c index 3e49f15f4..b65aaa77f 100644 --- a/mi/miexpose.c +++ b/mi/miexpose.c @@ -271,7 +271,7 @@ miHandleExposures(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, /* miPaintWindow doesn't clip, so we have to */ RegionIntersect(&rgnExposed, &rgnExposed, &pWin->clipList); } - miPaintWindow((WindowPtr) pDstDrawable, &rgnExposed, PW_BACKGROUND); + (*pWin->drawable.pScreen->PaintWindow)(pWin, &rgnExposed, PW_BACKGROUND); if (extents) { RegionReset(&rgnExposed, &expBox); @@ -392,7 +392,7 @@ miWindowExposures(WindowPtr pWin, RegionPtr prgn) /* miPaintWindow doesn't clip, so we have to */ RegionIntersect(prgn, prgn, &pWin->clipList); } - miPaintWindow(pWin, prgn, PW_BACKGROUND); + (*pWin->drawable.pScreen->PaintWindow)(pWin, prgn, PW_BACKGROUND); if (clientInterested) miSendExposures(pWin, exposures, pWin->drawable.x, pWin->drawable.y); @@ -402,14 +402,6 @@ miWindowExposures(WindowPtr pWin, RegionPtr prgn) } } -#ifdef ROOTLESS -/* Ugly, ugly, but we lost our hooks into miPaintWindow... =/ */ -void RootlessSetPixmapOfAncestors(WindowPtr pWin); -void RootlessStartDrawing(WindowPtr pWin); -void RootlessDamageRegion(WindowPtr pWin, RegionPtr prgn); -Bool IsFramedWindow(WindowPtr pWin); -#endif - void miPaintWindow(WindowPtr pWin, RegionPtr prgn, int what) { @@ -437,22 +429,6 @@ miPaintWindow(WindowPtr pWin, RegionPtr prgn, int what) Bool solid = TRUE; DrawablePtr drawable = &pWin->drawable; -#ifdef ROOTLESS - if (!drawable || drawable->type == UNDRAWABLE_WINDOW) - return; - - if (IsFramedWindow(pWin)) { - RootlessStartDrawing(pWin); - RootlessDamageRegion(pWin, prgn); - - if (pWin->backgroundState == ParentRelative) { - if ((what == PW_BACKGROUND) || - (what == PW_BORDER && !pWin->borderIsPixel)) - RootlessSetPixmapOfAncestors(pWin); - } - } -#endif - if (what == PW_BACKGROUND) { while (pWin->backgroundState == ParentRelative) pWin = pWin->parent; diff --git a/mi/mioverlay.c b/mi/mioverlay.c index 2b20fd72f..ad2fa4937 100644 --- a/mi/mioverlay.c +++ b/mi/mioverlay.c @@ -844,8 +844,8 @@ miOverlayHandleExposures(WindowPtr pWin) if ((mival = pTree->valdata)) { if (!((*pPriv->InOverlay) (pTree->pWin))) { if (RegionNotEmpty(&mival->borderExposed)) { - miPaintWindow(pTree->pWin, &mival->borderExposed, - PW_BORDER); + (*pTree->pWin->drawable.pScreen->PaintWindow)(pTree->pWin, &mival->borderExposed, + PW_BORDER); } RegionUninit(&mival->borderExposed); @@ -883,7 +883,7 @@ miOverlayHandleExposures(WindowPtr pWin) } else { if (RegionNotEmpty(&val->after.borderExposed)) { - miPaintWindow(pChild, &val->after.borderExposed, PW_BORDER); + (*pChild->drawable.pScreen->PaintWindow)(pChild, &val->after.borderExposed, PW_BORDER); } (*WindowExposures) (pChild, &val->after.exposed); } @@ -982,6 +982,7 @@ static void miOverlayWindowExposures(WindowPtr pWin, RegionPtr prgn) { RegionPtr exposures = prgn; + ScreenPtr pScreen = pWin->drawable.pScreen; if (prgn && !RegionNil(prgn)) { RegionRec expRec; @@ -1007,7 +1008,7 @@ miOverlayWindowExposures(WindowPtr pWin, RegionPtr prgn) else RegionIntersect(prgn, prgn, &pWin->clipList); } - miPaintWindow(pWin, prgn, PW_BACKGROUND); + (*pScreen->PaintWindow)(pWin, prgn, PW_BACKGROUND); if (clientInterested) miSendExposures(pWin, exposures, pWin->drawable.x, pWin->drawable.y); @@ -1606,7 +1607,7 @@ miOverlayClearToBackground(WindowPtr pWin, if (generateExposures) (*pScreen->WindowExposures) (pWin, ®); else if (pWin->backgroundState != None) - miPaintWindow(pWin, ®, PW_BACKGROUND); + (*pScreen->PaintWindow)(pWin, ®, PW_BACKGROUND); RegionUninit(®); } diff --git a/mi/miscrinit.c b/mi/miscrinit.c index b53c7e41a..b37dd9117 100644 --- a/mi/miscrinit.c +++ b/mi/miscrinit.c @@ -249,6 +249,7 @@ miScreenInit(ScreenPtr pScreen, void *pbits, /* pointer to screen bits */ pScreen->ValidateTree = miValidateTree; pScreen->PostValidateTree = (PostValidateTreeProcPtr) 0; pScreen->WindowExposures = miWindowExposures; + pScreen->PaintWindow = miPaintWindow; /* CopyWindow */ pScreen->ClearToBackground = miClearToBackground; pScreen->ClipNotify = (ClipNotifyProcPtr) 0; diff --git a/mi/miwindow.c b/mi/miwindow.c index a1af3a770..d31e44826 100644 --- a/mi/miwindow.c +++ b/mi/miwindow.c @@ -113,7 +113,7 @@ miClearToBackground(WindowPtr pWin, if (generateExposures) (*pWin->drawable.pScreen->WindowExposures) (pWin, ®); else if (pWin->backgroundState != None) - miPaintWindow(pWin, ®, PW_BACKGROUND); + (*pWin->drawable.pScreen->PaintWindow)(pWin, ®, PW_BACKGROUND); RegionUninit(®); } @@ -219,7 +219,7 @@ miHandleValidateExposures(WindowPtr pWin) while (1) { if ((val = pChild->valdata)) { if (RegionNotEmpty(&val->after.borderExposed)) - miPaintWindow(pChild, &val->after.borderExposed, PW_BORDER); + (*pChild->drawable.pScreen->PaintWindow)(pChild, &val->after.borderExposed, PW_BORDER); RegionUninit(&val->after.borderExposed); (*WindowExposures) (pChild, &val->after.exposed); RegionUninit(&val->after.exposed); diff --git a/miext/rootless/rootlessCommon.h b/miext/rootless/rootlessCommon.h index 7fdea22b3..e147f5ce2 100644 --- a/miext/rootless/rootlessCommon.h +++ b/miext/rootless/rootlessCommon.h @@ -96,6 +96,7 @@ typedef struct _RootlessScreenRec { ChangeWindowAttributesProcPtr ChangeWindowAttributes; CreateGCProcPtr CreateGC; + PaintWindowProcPtr PaintWindow; CopyWindowProcPtr CopyWindow; GetImageProcPtr GetImage; SourceValidateProcPtr SourceValidate; diff --git a/miext/rootless/rootlessScreen.c b/miext/rootless/rootlessScreen.c index 6226ee84a..494ae1a4b 100644 --- a/miext/rootless/rootlessScreen.c +++ b/miext/rootless/rootlessScreen.c @@ -473,7 +473,7 @@ expose_1(WindowPtr pWin) if (!pWin->realized) return; - miPaintWindow(pWin, &pWin->borderClip, PW_BACKGROUND); + (*pWin->drawable.pScreen->PaintWindow)(pWin, &pWin->borderClip, PW_BACKGROUND); /* FIXME: comments in windowstr.h indicate that borderClip doesn't include subwindow visibility. But I'm not so sure.. so we may @@ -668,6 +668,7 @@ RootlessWrap(ScreenPtr pScreen) WRAP(CreateScreenResources); WRAP(CloseScreen); WRAP(CreateGC); + WRAP(PaintWindow); WRAP(CopyWindow); WRAP(GetImage); WRAP(SourceValidate); diff --git a/miext/rootless/rootlessWindow.c b/miext/rootless/rootlessWindow.c index a8f296a39..d782c23b2 100644 --- a/miext/rootless/rootlessWindow.c +++ b/miext/rootless/rootlessWindow.c @@ -1636,3 +1636,38 @@ RootlessSetPixmapOfAncestors(WindowPtr pWin) pScreen->SetWindowPixmap(pWin, topWinRec->pixmap); } } + +/* + * RootlessPaintWindow + * + * Wrapper for miPaintWindow + * + * Returns directly if there is nothing more for miPaintWindow() to do + * + */ +void +RootlessPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what) +{ + DrawablePtr drawable = &pWin->drawable; + + if (!drawable || drawable->type == UNDRAWABLE_WINDOW) + return; + + if (IsFramedWindow(pWin)) { + RootlessStartDrawing(pWin); + RootlessDamageRegion(pWin, pRegion); + + // For ParentRelative windows, if painting background, or with + // tiled borders, we have to make sure the window pixmap is + // set correctly all the way up the ancestor chain. + if (pWin->backgroundState == ParentRelative) { + if ((what == PW_BACKGROUND) || + (what == PW_BORDER && !pWin->borderIsPixel)) + RootlessSetPixmapOfAncestors(pWin); + } + } + + SCREEN_UNWRAP(pWin->drawable.pScreen, PaintWindow); + pWin->drawable.pScreen->PaintWindow(pWin, pRegion, what); + SCREEN_WRAP(pWin->drawable.pScreen, PaintWindow); +} diff --git a/miext/rootless/rootlessWindow.h b/miext/rootless/rootlessWindow.h index d3955fc89..3b7ea42d3 100644 --- a/miext/rootless/rootlessWindow.h +++ b/miext/rootless/rootlessWindow.h @@ -53,6 +53,7 @@ void RootlessMoveWindow(WindowPtr pWin, int x, int y, WindowPtr pSib, void RootlessResizeWindow(WindowPtr pWin, int x, int y, unsigned int w, unsigned int h, WindowPtr pSib); void RootlessReparentWindow(WindowPtr pWin, WindowPtr pPriorParent); +void RootlessPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what); void RootlessChangeBorderWidth(WindowPtr pWin, unsigned int width); #ifdef __APPLE__ diff --git a/os/Makefile.am b/os/Makefile.am index a1bbb4d1e..0b0eb79d1 100644 --- a/os/Makefile.am +++ b/os/Makefile.am @@ -1,6 +1,6 @@ noinst_LTLIBRARIES = libos.la -AM_CFLAGS = $(DIX_CFLAGS) $(SHA1_CFLAGS) +AM_CFLAGS = $(DIX_CFLAGS) $(SHA1_CFLAGS) -DBINDIR=\"$(bindir)\" SECURERPC_SRCS = rpcauth.c XDMCP_SRCS = xdmcp.c @@ -207,11 +207,11 @@ CheckAuthorization(unsigned int name_length, return (*protocols[i].Check) (data_length, data, client, reason); } - *reason = "Protocol not supported by server\n"; + *reason = "Authorization protocol not supported by server\n"; } } else - *reason = "No protocol specified\n"; + *reason = "Authorization required, but no authorization protocol specified\n"; return (XID) ~0L; } diff --git a/os/backtrace.c b/os/backtrace.c index fd129ef21..05f3e678a 100644 --- a/os/backtrace.c +++ b/os/backtrace.c @@ -222,10 +222,25 @@ xorg_backtrace_frame(uintptr_t pc, int signo, void *arg) } #endif /* HAVE_WALKCONTEXT */ -#ifdef HAVE_PSTACK +#include <sys/types.h> +#if !defined(__WIN32__) || defined(__CYGWIN__) +#include <sys/wait.h> +#endif +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +/* + fork/exec a program to create a backtrace + Returns 0 if successful. +*/ static int -xorg_backtrace_pstack(void) +xorg_backtrace_exec_wrapper(const char *path) { +#if defined(WIN32) && !defined(__CYGWIN__) + ErrorFSigSafe("Backtrace not implemented on Windows"); + return -1; +#else pid_t kidpid; int pipefd[2]; @@ -233,7 +248,7 @@ xorg_backtrace_pstack(void) return -1; } - kidpid = fork1(); + kidpid = fork(); if (kidpid == -1) { /* ERROR */ @@ -246,11 +261,13 @@ xorg_backtrace_pstack(void) seteuid(0); close(STDIN_FILENO); close(STDOUT_FILENO); + close(STDERR_FILENO); dup2(pipefd[1], STDOUT_FILENO); - closefrom(STDERR_FILENO); + dup2(pipefd[1], STDERR_FILENO); + close(pipefd[1]); snprintf(parent, sizeof(parent), "%d", getppid()); - execle("/usr/bin/pstack", "pstack", parent, NULL); + execl(path, path, parent, NULL); exit(1); } else { @@ -263,23 +280,55 @@ xorg_backtrace_pstack(void) close(pipefd[1]); while (!done) { - bytesread = read(pipefd[0], btline, sizeof(btline) - 1); + bytesread = 0; + + do + { + int n = read(pipefd[0], &btline[bytesread], 1); + + if (n <= 0) + break; + + bytesread = bytesread + n; + + if (btline[bytesread-1] == '\n') + break; + } + while (bytesread < sizeof(btline)); if (bytesread > 0) { btline[bytesread] = 0; ErrorFSigSafe("%s", btline); } - else if ((bytesread < 0) || ((errno != EINTR) && (errno != EAGAIN))) + else if ((bytesread == 0) || + ((errno != EINTR) && (errno != EAGAIN))) done = 1; } close(pipefd[0]); waitpid(kidpid, &kidstat, 0); - if (kidstat != 0) + if (!(WIFEXITED(kidstat) && WEXITSTATUS(kidstat) == 0)) { + ErrorFSigSafe("%s failed with returncode %d\n", path, + WEXITSTATUS(kidstat)); return -1; + } } return 0; +#endif +} + +#ifdef HAVE_PSTACK +static int +xorg_backtrace_pstack(void) +{ + return xorg_backtrace_exec_wrapper("/usr/bin/pstack"); +} +#endif + +static int +xorg_backtrace_script(void) +{ + return xorg_backtrace_exec_wrapper(BINDIR "/xorg-backtrace"); } -#endif /* HAVE_PSTACK */ #if defined(HAVE_PSTACK) || defined(HAVE_WALKCONTEXT) @@ -316,7 +365,85 @@ xorg_backtrace(void) void xorg_backtrace(void) { - return; + if (xorg_backtrace_script() == 0) + return; +} + +/* Cygwin-specific crash-reporter glue */ + +#include <X11/Xwindows.h> +#include <sys/cygwin.h> + +typedef int (*PFNCYGWINCRASHREPORTERINIT)(const char *, const char *); +typedef void (*PFNCYGWINCRASHREPORTERREPORT)(EXCEPTION_POINTERS *ep); + +PFNCYGWINCRASHREPORTERREPORT crashreporter_report = NULL; + +#define CRASHREPORT_URL "http://www.dronecode.org.uk/cgi-bin/addreport.php" + +void +xorg_crashreport_init(const char *logfile) +{ + /* Initialize crashreporter, if available */ + HMODULE h = LoadLibrary("cygwin-crashreporter-hooks.dll"); + if (h) + { + int result = 0; + PFNCYGWINCRASHREPORTERINIT crashreporter_init = (PFNCYGWINCRASHREPORTERINIT) GetProcAddress (h, "CygwinCrashReporterInit"); + crashreporter_report = (PFNCYGWINCRASHREPORTERREPORT) GetProcAddress (h, "CygwinCrashReporterReport"); + + if (crashreporter_init && crashreporter_report) + { + char *windows_logfile = cygwin_create_path(CCP_POSIX_TO_WIN_A, logfile); + + result = (*crashreporter_init) (CRASHREPORT_URL, windows_logfile); + + if (!result) + ErrorF("Failed to initialize crashreporting\n"); + else + DebugF("crashreporting initialized, status %d\n", result); + + free(windows_logfile); + } + else + { + ErrorF("Could not locate crashreporting functions\n"); + } + + if (!result) + FreeLibrary (h); + } + else + { + DebugF("Could not load crashreporter dll\n"); + } +} + +#ifdef CW_EXCEPTION_RECORD_FROM_SIGINFO_T +#include <ucontext.h> +#endif + +void +xorg_crashreport(int signo, siginfo_t *sip, void *sigcontext) +{ + if (crashreporter_report) + { +#ifdef CW_EXCEPTION_RECORD_FROM_SIGINFO_T + ucontext_t *ucontext = (ucontext_t *)sigcontext; + EXCEPTION_RECORD er; + int res = !cygwin_internal(CW_EXCEPTION_RECORD_FROM_SIGINFO_T, sip, &er); + + if (ucontext && res) + { + EXCEPTION_POINTERS ep; + ep.ExceptionRecord = &er; + ep.ContextRecord = (CONTEXT *)(&ucontext->uc_mcontext); + crashreporter_report(&ep); + } + else +#endif + crashreporter_report(NULL); + } } #endif diff --git a/os/connection.c b/os/connection.c index 7ff44e175..973ed212b 100644 --- a/os/connection.c +++ b/os/connection.c @@ -416,12 +416,14 @@ CreateWellKnownSockets(void) else { /* -displayfd and no explicit display number */ Bool found = 0; for (i = 0; i < 65536 - X_TCP_PORT; i++) { - if (TryCreateSocket(i, &partial) && !partial) { - found = 1; - break; + ErrorF("Trying to create socket for display number %d\n", i); + if (TryCreateSocket(i, &partial) && + (ListenTransCount >= 1)) + if (PartialNetwork || !partial) { + found = 1; + break; } - else - CloseWellKnownConnections(); + CloseWellKnownConnections(); } if (!found) FatalError("Failed to find a socket to listen on"); @@ -915,9 +915,9 @@ FatalError(const char *f, ...) static Bool beenhere = FALSE; if (beenhere) - ErrorFSigSafe("\nFatalError re-entered, aborting\n"); + ErrorFSigSafe("FatalError re-entered, aborting\n"); else - ErrorFSigSafe("\nFatal server error:\n"); + ErrorFSigSafe("Fatal server error:\n"); va_start(args, f); @@ -936,7 +936,8 @@ FatalError(const char *f, ...) #endif VErrorFSigSafe(f, args); va_end(args); - ErrorFSigSafe("\n"); + if (f[strlen(f) - 1] != '\n') + ErrorFSigSafe("\n"); if (!beenhere) OsVendorFatalError(f, args2); va_end(args2); diff --git a/os/osinit.c b/os/osinit.c index 91e3e068c..8e5b0f16b 100644 --- a/os/osinit.c +++ b/os/osinit.c @@ -69,9 +69,11 @@ SOFTWARE. #if !defined(SYSV) && !defined(WIN32) #include <sys/resource.h> #endif +#include <pthread.h> -#ifndef ADMPATH -#define ADMPATH "/usr/adm/X%smsgs" +#if defined(WIN32) || defined(__CYGWIN__) +#define WIN32_LEAN_AND_MEAN +#include <X11/Xwindows.h> #endif extern char *display; @@ -85,6 +87,7 @@ int limitStackSpace = -1; #ifdef RLIMIT_NOFILE int limitNoFile = -1; #endif +extern Bool install_os_signal_handler; static OsSigWrapperPtr OsSigWrapper = NULL; @@ -105,7 +108,7 @@ OsRegisterSigWrapper(OsSigWrapperPtr newSigWrapper) #if !defined(WIN32) || defined(__CYGWIN__) static void #ifdef SA_SIGINFO -OsSigHandler(int signo, siginfo_t * sip, void *unused) +OsSigHandler(int signo, siginfo_t * sip, void *sigcontext) #else OsSigHandler(int signo) #endif @@ -125,8 +128,7 @@ OsSigHandler(int signo) } } - /* log, cleanup, and abort */ - xorg_backtrace(); + ErrorFSigSafe("Fatal signal received in thread 0x%x [0x%x]\n", pthread_self(), GetCurrentThreadId()); #ifdef SA_SIGINFO if (sip->si_code == SI_USER) { @@ -144,6 +146,11 @@ OsSigHandler(int signo) } #endif + /* log, cleanup, and abort */ + xorg_backtrace(); + + xorg_crashreport(signo, sip, sigcontext); + FatalError("Caught signal %d (%s). Server aborting\n", signo, strsignal(signo)); } @@ -160,30 +167,33 @@ OsInit(void) if (!been_here) { #if !defined(WIN32) || defined(__CYGWIN__) - struct sigaction act, oact; - int i; - - int siglist[] = { SIGSEGV, SIGQUIT, SIGILL, SIGFPE, SIGBUS, - SIGSYS, - SIGXCPU, - SIGXFSZ, + if (install_os_signal_handler) { + struct sigaction act, oact; + int i; + + int siglist[] = { SIGSEGV, SIGQUIT, SIGILL, SIGFPE, SIGBUS, + SIGSYS, + SIGXCPU, + SIGXFSZ, #ifdef SIGEMT - SIGEMT, + SIGEMT, #endif - 0 /* must be last */ - }; - sigemptyset(&act.sa_mask); + 0 /* must be last */ + }; + sigemptyset(&act.sa_mask); #ifdef SA_SIGINFO - act.sa_sigaction = OsSigHandler; - act.sa_flags = SA_SIGINFO; + act.sa_sigaction = OsSigHandler; + act.sa_flags = SA_SIGINFO; #else - act.sa_handler = OsSigHandler; - act.sa_flags = 0; + act.sa_handler = OsSigHandler; + act.sa_flags = 0; #endif - for (i = 0; siglist[i] != 0; i++) { - if (sigaction(siglist[i], &act, &oact)) { - ErrorF("failed to install signal handler for signal %d: %s\n", - siglist[i], strerror(errno)); + for (i = 0; siglist[i] != 0; i++) { + if (sigaction(siglist[i], &act, &oact)) { + ErrorF + ("failed to install signal handler for signal %d: %s\n", + siglist[i], strerror(errno)); + } } } #endif /* !WIN32 || __CYGWIN__ */ @@ -226,40 +236,7 @@ OsInit(void) # elif !defined(__CYGWIN__) fclose(stdin); fclose(stdout); -# endif - /* - * If a write of zero bytes to stderr returns non-zero, i.e. -1, - * then writing to stderr failed, and we'll write somewhere else - * instead. (Apparently this never happens in the Real World.) - */ - if (write(2, fname, 0) == -1) { - FILE *err; - - if (strlen(display) + strlen(ADMPATH) + 1 < sizeof fname) - snprintf(fname, sizeof(fname), ADMPATH, display); - else - strcpy(fname, devnull); - /* - * uses stdio to avoid os dependencies here, - * a real os would use - * open (fname, O_WRONLY|O_APPEND|O_CREAT, 0666) - */ - if (!(err = fopen(fname, "a+"))) - err = fopen(devnull, "w"); - if (err && (fileno(err) != 2)) { - dup2(fileno(err), 2); - fclose(err); - } -#if defined(SYSV) || defined(SVR4) || defined(WIN32) || defined(__CYGWIN__) - { - static char buf[BUFSIZ]; - - setvbuf(stderr, buf, _IOLBF, BUFSIZ); - } -#else - setlinebuf(stderr); #endif - } #endif /* !XQUARTZ */ #if !defined(WIN32) || defined(__CYGWIN__) diff --git a/os/utils.c b/os/utils.c index 2b23430a4..6ed927b16 100644 --- a/os/utils.c +++ b/os/utils.c @@ -122,6 +122,8 @@ __stdcall unsigned long GetTickCount(void); #include "picture.h" +Bool install_os_signal_handler = TRUE; + Bool noTestExtensions; #ifdef COMPOSITE @@ -255,7 +257,7 @@ UnlockServer(void) #else /* LOCK_SERVER */ static Bool StillLocking = FALSE; static char LockFile[PATH_MAX]; -static Bool nolock = FALSE; +Bool nolock = FALSE; /* * LockServer -- @@ -553,6 +555,7 @@ UseMsg(void) #ifdef RLIMIT_STACK ErrorF("-ls int limit stack space to N Kb\n"); #endif + ErrorF("-notrapsignals disable catching of fatal signals\n"); #ifdef LOCK_SERVER ErrorF("-nolock disable the locking mechanism\n"); #endif @@ -849,6 +852,9 @@ ProcessCommandLine(int argc, char *argv[]) UseMsg(); } #endif + else if (strcmp(argv[i], "-notrapsignals") == 0) { + install_os_signal_handler = FALSE; + } #ifdef LOCK_SERVER else if (strcmp(argv[i], "-nolock") == 0) { #if !defined(WIN32) && !defined(__CYGWIN__) @@ -996,6 +1002,7 @@ ProcessCommandLine(int argc, char *argv[]) } else if (strcmp(argv[i], "-schedInterval") == 0) { if (++i < argc) { + SmartScheduleDisable = FALSE; SmartScheduleInterval = atoi(argv[i]); SmartScheduleSlice = SmartScheduleInterval; } @@ -1004,6 +1011,7 @@ ProcessCommandLine(int argc, char *argv[]) } else if (strcmp(argv[i], "-schedMax") == 0) { if (++i < argc) { + SmartScheduleDisable = FALSE; SmartScheduleMaxSlice = atoi(argv[i]); } else @@ -1384,6 +1392,26 @@ OsAbort(void) * as well. As it is now, xkbcomp messages don't end up in the log file. */ +#ifdef __CYGWIN__ +#include <process.h> +int +System(const char *command) +{ + int status; + + if (!command) + return 1; + + DebugF("System: `%s'\n", command); + + /* + Use spawnl() rather than execl() to implement System() on cygwin to + avoid fork emulation overhead and brittleness + */ + status = spawnl(_P_WAIT, "/bin/sh", "sh", "-c", command, (char *) NULL); + return status; +} +#else int System(const char *command) { @@ -1426,6 +1454,7 @@ System(const char *command) return p == -1 ? -1 : status; } +#endif static struct pid { struct pid *next; @@ -1734,6 +1763,20 @@ System(const char *cmdline) return dwExitCode; } +#elif defined(__CYGWIN__) +const char* +Win32TempDir(void) +{ + const char *temp = getenv("TEMP"); + if ((temp != NULL) && (access(temp, W_OK | X_OK) == 0)) + return temp; + + temp = getenv("TMP"); + if ((temp != NULL) && (access(temp, W_OK | X_OK) == 0)) + return temp; + + return "/tmp"; +} #endif /* diff --git a/pseudoramiX/pseudoramiX.h b/pseudoramiX/pseudoramiX.h index f063919dd..5393062ee 100644 --- a/pseudoramiX/pseudoramiX.h +++ b/pseudoramiX/pseudoramiX.h @@ -2,8 +2,6 @@ * Minimal implementation of PanoramiX/Xinerama */ -extern int noPseudoramiXExtension; - void PseudoramiXAddScreen(int x, int y, int w, int h); void diff --git a/randr/rrxinerama.c b/randr/rrxinerama.c index b336bd7cd..36632c7c7 100644 --- a/randr/rrxinerama.c +++ b/randr/rrxinerama.c @@ -84,6 +84,8 @@ static int ProcRRXineramaIsActive(ClientPtr client); static int ProcRRXineramaQueryScreens(ClientPtr client); static int SProcRRXineramaDispatch(ClientPtr client); +Bool noRRXineramaExtension = FALSE; + /* Proc */ int @@ -488,6 +490,9 @@ RRXineramaExtensionInit(void) return; #endif + if (noRRXineramaExtension) + return; + /* * Xinerama isn't capable enough to have multiple protocol screens each * with their own output geometry. So if there's more than one protocol diff --git a/xkb/ddxLoad.c b/xkb/ddxLoad.c index f71815aa8..c03fa6079 100644 --- a/xkb/ddxLoad.c +++ b/xkb/ddxLoad.c @@ -44,6 +44,7 @@ THE USE OR PERFORMANCE OF THIS SOFTWARE. #include <xkbsrv.h> #include <X11/extensions/XI.h> #include "xkb.h" +#include "os.h" /* * If XKM_OUTPUT_DIR specifies a path without a leading slash, it is @@ -113,11 +114,15 @@ RunXkbComp(xkbcomp_buffer_callback callback, void *userdata) const char *xkbbindir = emptystring; const char *xkbbindirsep = emptystring; -#ifdef WIN32 +#if defined(WIN32) || defined(__CYGWIN__) + int status; /* WIN32 has no popen. The input must be stored in a file which is used as input for xkbcomp. xkbcomp does not read from stdin. */ char tmpname[PATH_MAX]; const char *xkmfile = tmpname; + /* Temporary file used to hold stdout and stderr from xkbcomp */ + char tmpname2[PATH_MAX]; + const char *stderrfile = tmpname2; #else const char *xkmfile = "-"; #endif @@ -126,10 +131,13 @@ RunXkbComp(xkbcomp_buffer_callback callback, void *userdata) OutputDirectory(xkm_output_dir, sizeof(xkm_output_dir)); -#ifdef WIN32 +#if defined(WIN32) || defined(__CYGWIN__) strcpy(tmpname, Win32TempDir()); - strcat(tmpname, "\\xkb_XXXXXX"); + strcat(tmpname, PATHSEPARATOR "xkb_XXXXXX"); (void) mktemp(tmpname); + strcpy(tmpname2, Win32TempDir()); + strcat(tmpname2, PATHSEPARATOR "xkb_XXXXXX"); + (void) mktemp(tmpname2); #endif if (XkbBaseDirectory != NULL) { @@ -167,39 +175,61 @@ RunXkbComp(xkbcomp_buffer_callback callback, void *userdata) return NULL; } -#ifndef WIN32 +#if !defined(WIN32) && !defined(__CYGWIN__) out = Popen(buf, "w"); #else out = fopen(tmpname, "w"); + + buf = realloc(buf, strlen(buf) + strlen(stderrfile) + 8); + strcat(buf, " >"); + strcat(buf, stderrfile); + strcat(buf, " 2>&1"); #endif if (out != NULL) { /* Now write to xkbcomp */ (*callback)(out, userdata); -#ifndef WIN32 +#if !defined(WIN32) && !defined(__CYGWIN__) if (Pclose(out) == 0) #else - if (fclose(out) == 0 && System(buf) >= 0) + if (fclose(out) == 0 && (status = System(buf)) == 0) #endif { if (xkbDebugFlags) DebugF("[xkb] xkb executes: %s\n", buf); free(buf); -#ifdef WIN32 +#if defined(WIN32) || defined(__CYGWIN__) unlink(tmpname); + unlink(tmpname2); #endif return xnfstrdup(keymap); } else LogMessage(X_ERROR, "Error compiling keymap (%s)\n", keymap); -#ifdef WIN32 +#if defined(WIN32) || defined(__CYGWIN__) + LogMessage(X_ERROR, "xkbcomp exit status 0x%x\n", status); + + { + char *lineptr = NULL; + size_t n = 0; + FILE *in = fopen(tmpname2, "r"); + if (in) + { + while (getline(&lineptr, &n, in) > 0) + LogMessage(X_ERROR, "%s", lineptr); + + fclose(in); + } + } + /* remove the temporary file */ unlink(tmpname); + unlink(tmpname2); #endif } else { -#ifndef WIN32 +#if !defined(WIN32) && !defined(__CYGWIN__) LogMessage(X_ERROR, "XKB: Could not invoke xkbcomp\n"); #else LogMessage(X_ERROR, "Could not open file %s\n", tmpname); |