diff options
91 files changed, 5480 insertions, 5710 deletions
diff --git a/.appveyor.yml b/.appveyor.yml index e81261038..8fd7e0315 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -15,7 +15,7 @@ install: - if "%BUILD%"=="i686-pc-cygwin" set SETUP=setup-x86.exe && set CYGWIN_ROOT=C:\cygwin - curl -fsSL https://gist.githubusercontent.com/jon-turney/0338af595313f598bfab15a0ac0df847/raw/bd0eeca6be899e7846aa988fbcf15e4e12f5f842/zp_libtool_cleanlafiles.sh -o %CYGWIN_ROOT%\etc\postinstall\zp_libtool_cleanlafiles.sh - echo Updating Cygwin and installing build prerequisites -- '%CYGWIN_ROOT%\%SETUP% -qnNdO -R "%CYGWIN_ROOT%" -s "%CYGWIN_MIRROR%" -l "%CACHE%" -g -P "meson,binutils,bison,bzip2,diffutils,fileutils,findutils,flex,gawk,gcc-core,make,patch,pkg-config,python3,sed,tar,xorgproto,windowsdriproto,libdmx-devel,libfontenc-devel,libfreetype-devel,libGL-devel,libpixman1-devel,libX11-devel,libXRes-devel,libXau-devel,libXaw-devel,libXdmcp-devel,libXext-devel,libXfont2-devel,libXi-devel,libXinerama-devel,libXmu-devel,libXpm-devel,libXrender-devel,libXtst-devel,libxcb-ewmh-devel,libxcb-icccm-devel,libxcb-image-devel,libxcb-keysyms-devel,libxcb-randr-devel,libxcb-render-devel,libxcb-render-util-devel,libxcb-shape-devel,libxcb-util-devel,libxcb-xkb-devel,libxkbfile-devel,zlib,font-util,khronos-opengl-registry,python3-lxml,xorg-util-macros,xtrans,xkbcomp,xkeyboard-config,libnettle-devel,libepoxy-devel,libtirpc-devel"' +- '%CYGWIN_ROOT%\%SETUP% -qnNdO -R "%CYGWIN_ROOT%" -s "%CYGWIN_MIRROR%" -l "%CACHE%" -g -P "meson,binutils,bison,bzip2,diffutils,fileutils,findutils,flex,gawk,gcc-core,make,patch,pkg-config,python3,sed,tar,xorgproto,windowsdriproto,libdmx-devel,libfontenc-devel,libfreetype-devel,libGL-devel,libpixman1-devel,libX11-devel,libXRes-devel,libXau-devel,libXaw-devel,libXdmcp-devel,libXext-devel,libXfont2-devel,libXi-devel,libXinerama-devel,libXmu-devel,libXpm-devel,libXrender-devel,libXtst-devel,libxcb-ewmh-devel,libxcb-icccm-devel,libxcb-image-devel,libxcb-keysyms-devel,libxcb-randr-devel,libxcb-render-devel,libxcb-render-util-devel,libxcb-shape-devel,libxcb-util-devel,libxcb-xkb-devel,libxkbfile-devel,zlib-devel,font-util,khronos-opengl-registry,python3-lxml,xorg-util-macros,xtrans,xkbcomp,xkeyboard-config,libnettle-devel,libepoxy-devel,libtirpc-devel,libxcb-composite-devel,ImageMagick"' - echo Install done cache: - C:\cache @@ -23,6 +23,7 @@ build_script: - SET PATH=%CYGWIN_ROOT%/bin - '%CYGWIN_ROOT%/bin/bash -lc "cd $APPVEYOR_BUILD_FOLDER; meson setup --prefix=/usr -Dxv=false -Dxf86bigfont=true -Ddmx=true -Dxephyr=true -Dxnest=true -Dxvfb=true -Dxwin=true -Dxorg=true -Dhal=false -Dudev=false -Dpciaccess=false -Dint10=false build"' - '%CYGWIN_ROOT%/bin/bash -lc "cd $APPVEYOR_BUILD_FOLDER; meson configure build"' +- '%CYGWIN_ROOT%/bin/bash -lc "cd $APPVEYOR_BUILD_FOLDER; ninja -C build hw/xwin/X.ico"' - '%CYGWIN_ROOT%/bin/bash -lc "cd $APPVEYOR_BUILD_FOLDER; ninja -C build"' test_script: - '%CYGWIN_ROOT%/bin/bash -lc "cd $APPVEYOR_BUILD_FOLDER; ninja -C build test"' diff --git a/configure.ac b/configure.ac index 2b21667ee..6d2231284 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)' @@ -573,7 +583,6 @@ AC_ARG_ENABLE(xfree86-utils, AS_HELP_STRING([--enable-xfree86-utils], [Build AC_ARG_ENABLE(vgahw, AS_HELP_STRING([--enable-vgahw], [Build Xorg with vga access (default: enabled)]), [VGAHW=$enableval], [VGAHW=yes]) 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]) @@ -739,7 +748,6 @@ DGAPROTO="xf86dgaproto >= 2.0.99.1" GLPROTO="glproto >= 1.4.17" DMXPROTO="dmxproto >= 2.2.99.1" VIDMODEPROTO="xf86vidmodeproto >= 2.2.99.1" -WINDOWSWMPROTO="windowswmproto" APPLEWMPROTO="applewmproto >= 1.4" LIBXSHMFENCE="xshmfence >= 1.1" @@ -2138,16 +2146,7 @@ if test "x$XWIN" = xyes; then AC_DEFINE_UNQUOTED(__VENDORDWEBSUPPORT__, ["$VENDOR_WEB"], [Vendor web address for support]) AC_CHECK_TOOL(WINDRES, windres) - PKG_CHECK_MODULES([XWINMODULES],[x11 xdmcp xau xfixes x11-xcb xcb-aux xcb-image xcb-ewmh xcb-icccm]) - - if test "x$WINDOWSWM" = xauto; then - PKG_CHECK_EXISTS($WINDOWSWMPROTO, [WINDOWSWM=yes], [WINDOWSWM=no]) - fi - if test "x$WINDOWSWM" = xyes ; then - PKG_CHECK_MODULES(WINDOWSWM, $WINDOWSWMPROTO) - XWINMODULES_CFLAGS="$XWINMODULES_CFLAGS $WINDOWSWM_CFLAGS" - AC_DEFINE(ROOTLESS,1,[Build Rootless code]) - fi + PKG_CHECK_MODULES([XWINMODULES],[x11 xau xdmcp xfixes x11-xcb xcb-aux xcb-composite xcb-image xcb-ewmh xcb-icccm]) if test "x$WINDOWSDRI" = xauto; then PKG_CHECK_EXISTS([windowsdriproto], [WINDOWSDRI=yes], [WINDOWSDRI=no]) @@ -2205,7 +2204,6 @@ dnl XWin requires OpenGL spec files in order to generate wrapper code for native fi AM_CONDITIONAL(XWIN, [test "x$XWIN" = xyes]) -AM_CONDITIONAL(XWIN_MULTIWINDOWEXTWM, [test "x$XWIN" = xyes && test "x$WINDOWSWM" = xyes]) AM_CONDITIONAL(XWIN_GLX_WINDOWS, [test "x$XWIN" = xyes && test "x$GLX" = xyes]) AM_CONDITIONAL(XWIN_WINDOWS_DRI, [test "x$XWIN" = xyes && test "x$WINDOWSDRI" = xyes]) @@ -2572,6 +2570,7 @@ 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 176c7a0dd..0befd61c0 100644 --- a/dix/dispatch.c +++ b/dix/dispatch.c @@ -222,8 +222,12 @@ UpdateCurrentTimeIf(void) #define SMART_SCHEDULE_MAX_SLICE 15 #ifdef HAVE_SETITIMER +#if defined(WIN32) || defined(__CYGWIN__) +Bool SmartScheduleSignalEnable = FALSE; +#else Bool SmartScheduleSignalEnable = TRUE; #endif +#endif long SmartScheduleSlice = SMART_SCHEDULE_DEFAULT_INTERVAL; long SmartScheduleInterval = SMART_SCHEDULE_DEFAULT_INTERVAL; 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 55ad4a2af..021eee44f 100644 --- a/glx/rensize.c +++ b/glx/rensize.c @@ -234,6 +234,7 @@ __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: diff --git a/hw/xfree86/meson.build b/hw/xfree86/meson.build index 133c96d89..cacf56d4c 100644 --- a/hw/xfree86/meson.build +++ b/hw/xfree86/meson.build @@ -190,17 +190,19 @@ install_man(configure_file( configuration: manpage_config, )) -install_man(configure_file( - input: 'man/Xorg.wrap.man', - output: 'Xorg.wrap.1', - configuration: manpage_config, -)) - -install_man(configure_file( - input: 'man/Xwrapper.config.man', - output: 'Xwrapper.config.5', - configuration: manpage_config, -)) +if get_option('suid_wrapper') + install_man(configure_file( + input: 'man/Xorg.wrap.man', + output: 'Xorg.wrap.1', + configuration: manpage_config, + )) + + install_man(configure_file( + input: 'man/Xwrapper.config.man', + output: 'Xwrapper.config.5', + configuration: manpage_config, + )) +endif install_man(configure_file( input: 'man/xorg.conf.man', diff --git a/hw/xwin/InitOutput.c b/hw/xwin/InitOutput.c index 9560c5684..bf34466ad 100644 --- a/hw/xwin/InitOutput.c +++ b/hw/xwin/InitOutput.c @@ -35,12 +35,12 @@ from The Open Group. #include "winmsg.h" #include "winconfig.h" #include "winprefs.h" -#include "X11/Xlocale.h" #ifdef DPMSExtension #include "dpmsproc.h" #endif #ifdef __CYGWIN__ #include <mntent.h> +#include <sys/statvfs.h> #endif #if defined(WIN32) #include "xkbsrv.h" @@ -88,6 +88,8 @@ Bool const char *winGetBaseDir(void); #endif +static void winCheckMount(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 @@ -156,6 +158,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) { @@ -167,6 +171,8 @@ main(int argc, char *argv[], char *envp[]) ErrorF("ddxMain - pthread_mutex_lock () failed: %d\n", iReturn); } + winCheckMount(); + return dix_main(argc, argv, envp); } @@ -204,10 +210,6 @@ ddxGiveUp(enum ExitCode error) } #endif - if (!g_fLogInited) { - g_pszLogFile = LogInit(g_pszLogFile, ".old"); - g_fLogInited = TRUE; - } LogClose(error); /* @@ -251,6 +253,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) @@ -275,6 +279,9 @@ winCheckMntOpt(const struct mntent *mnt, const char *opt) return NULL; } +/* + Check mounts and issue warnings/activate workarounds as needed + */ static void winCheckMount(void) { @@ -284,6 +291,7 @@ winCheckMount(void) enum { none = 0, sys_root, user_root, sys_tmp, user_tmp } level = none, curlevel; BOOL binary = TRUE; + struct statvfs buf; mnt = setmntent("/etc/mtab", "r"); if (mnt == NULL) { @@ -331,6 +339,21 @@ winCheckMount(void) if (!binary) winMsg(X_WARNING, "/tmp mounted in textmode\n"); + + /* + Use statvfs(), which on Cygwin passes through the flags returned by + GetVolumeInformation(), to determine if hardlinks are available + + This should use the same LOCK_DIR as LockServer() + */ + if (!statvfs("/tmp", &buf)) { + if (!(buf.f_flag & FILE_SUPPORTS_HARD_LINKS)) { + winMsg(X_WARNING, "/tmp mounted on a filesystem without hardlinks, activating -nolock\n"); + nolock = TRUE; + } + } else { + winMsg(X_WARNING, "statvfs() /tmp failed\n"); + } } #else static void @@ -586,13 +609,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); @@ -623,16 +646,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, ".old"); + 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); @@ -717,6 +740,13 @@ winUseMsg(void) "\tthe updated region when num_boxes, or more, are in the\n" "\tupdated region.\n"); + ErrorF("-[no]compositealpha\n" + "\tX windows with per-pixel alpha are composited into the Windows desktop.\n"); + ErrorF("-[no]compositewm\n" + "\tUse the Composite extension to keep a bitmap image of each top-level\n" + "\tX window, so window contents which are occluded show correctly in\n" + "\ttask bar and task switcher previews.\n"); + #ifdef XWIN_XF86CONFIG ErrorF("-config\n" "\tSpecify a configuration file.\n"); @@ -751,6 +781,8 @@ winUseMsg(void) ErrorF("-[no]hostintitle\n" "\tIn multiwindow mode, add remote host names to window titles.\n"); + ErrorF("-icon icon_specifier\n" "\tSet screen window icon in windowed mode.\n"); + ErrorF("-ignoreinput\n" "\tIgnore keyboard and mouse input.\n"); #ifdef XWIN_XF86CONFIG @@ -784,11 +816,6 @@ winUseMsg(void) ErrorF("-multiwindow\n" "\tRun the server in multi-window mode.\n"); -#ifdef XWIN_MULTIWINDOWEXTWM - ErrorF("-mwextwm\n" - "\tRun the server in multi-window external window manager mode.\n"); -#endif - ErrorF("-nodecoration\n" "\tDo not draw a window border, title bar, etc. Windowed\n" "\tmode only.\n"); @@ -804,7 +831,7 @@ winUseMsg(void) "\tSpecify an optional refresh rate to use in fullscreen mode\n" "\twith a DirectDraw engine.\n"); - ErrorF("-resize=none|scrollbars|randr" + ErrorF("-resize=none|scrollbars|randr\n" "\tIn windowed mode, [don't] allow resizing of the window. 'scrollbars'\n" "\tmode gives the window scrollbars as needed, 'randr' mode uses the RANR\n" "\textension to resize the X screen. 'randr' is the default.\n"); @@ -821,6 +848,11 @@ winUseMsg(void) "\t -screen 0 1024x768@3 ; 3rd monitor size 1024x768\n" "\t -screen 0 @1 ; on 1st monitor using its full resolution (the default)\n"); + ErrorF("-silent-dup-error\n" + "\tIf another instance of " EXECUTABLE_NAME + " with the same display number is running\n" + "\texit silently and don't display any error message.\n"); + ErrorF("-swcursor\n" "\tDisable the usage of the Windows cursor and use the X11 software\n" "\tcursor instead.\n"); @@ -862,24 +894,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, ".old"); - 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 */ @@ -980,8 +995,7 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char *argv[]) for (iMonitor = 1; ; iMonitor++) { struct GetMonitorInfoData data; - QueryMonitor(iMonitor, &data); - if (data.bMonitorSpecifiedExists) + if (QueryMonitor(iMonitor, &data)) { MONITORINFO mi; mi.cbSize = sizeof(MONITORINFO); @@ -1018,14 +1032,6 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char *argv[]) if (g_fXdmcpEnabled || g_fAuthEnabled) winGenerateAuthorization(); - /* Perform some one time initialization */ - if (1 == serverGeneration) { - /* - * setlocale applies to all threads in the current process. - * Apply locale specified in LANG environment variable. - */ - setlocale(LC_ALL, ""); - } #if CYGDEBUG || YES winDebug("InitOutput - Returning.\n"); diff --git a/hw/xwin/Makefile.am b/hw/xwin/Makefile.am index 5f67a6eca..5e1637ab1 100644 --- a/hw/xwin/Makefile.am +++ b/hw/xwin/Makefile.am @@ -27,18 +27,8 @@ SRCS_MULTIWINDOW = \ winmultiwindowwndproc.c \ propertystore.h \ winSetAppUserModelID.c -MULTIWINDOW_SYS_LIBS = -lshlwapi -lole32 - -if XWIN_MULTIWINDOWEXTWM -SRCS_MULTIWINDOWEXTWM = \ - winwin32rootless.c \ - winwin32rootlesswindow.c \ - winwin32rootlesswndproc.c \ - winwindowswm.c -DEFS_MULTIWINDOWEXTWM = -DXWIN_MULTIWINDOWEXTWM -MULTIWINDOWEXTWM_LIBS = $(top_builddir)/miext/rootless/librootless.la -MULTIWINDOWEXTWM_CFLAGS = -I$(top_srcdir)/miext/rootless -endif +MULTIWINDOW_SYS_LIBS = -lshlwapi -lole32 -ldwmapi +MULTIWINDOW_LIBS = $(top_builddir)/hw/xwin/wmutil/libXWinWMUtil.la SRCS_RANDR = \ winrandr.c @@ -83,8 +73,6 @@ SRCS = InitInput.c \ winconfig.h \ win.h \ winglobals.h \ - winkeybd.h \ - winkeynames.h \ winlayouts.h \ winmessages.h \ winmonitors.h \ @@ -101,7 +89,6 @@ SRCS = InitInput.c \ $(top_srcdir)/mi/miinitext.c \ $(SRCS_CLIPBOARD) \ $(SRCS_MULTIWINDOW) \ - $(SRCS_MULTIWINDOWEXTWM) \ $(SRCS_RANDR) DEFS = \ @@ -117,7 +104,7 @@ XWIN_LIBS += \ $(top_builddir)/Xi/libXistubs.la XWin_DEPENDENCIES = \ - $(MULTIWINDOWEXTWM_LIBS) \ + $(MULTIWINDOW_LIBS) \ $(XWIN_GLX_LIBS) \ $(XWIN_LIBS) \ $(CLIPBOARD_LIBS) \ @@ -125,7 +112,7 @@ XWin_DEPENDENCIES = \ XWin_LDADD = \ - $(MULTIWINDOWEXTWM_LIBS) \ + $(MULTIWINDOW_LIBS) \ $(XWIN_GLX_LIBS) \ $(XWIN_LIBS) \ $(CLIPBOARD_LIBS) \ @@ -139,10 +126,13 @@ 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=\"$(host)\" XWin.o: XWin.rc XWin.exe.manifest X.ico +X.ico: X.svg + $(AM_V_GEN)convert -background transparent $(srcdir)/X.svg -trim -define icon:auto-resize X.ico + winprefsyacc.h: winprefsyacc.c winprefslex.c: winprefslex.l winprefsyacc.c winprefsyacc.h @@ -154,7 +144,6 @@ AM_LFLAGS = -i AM_CFLAGS = -DHAVE_XWIN_CONFIG_H $(DIX_CFLAGS) \ $(XWINMODULES_CFLAGS) \ -I$(top_srcdir) \ - $(MULTIWINDOWEXTWM_CFLAGS) \ -Wno-bad-function-cast xwinconfigdir = $(sysconfdir)/X11 @@ -172,5 +161,5 @@ EXTRA_DIST = \ relink: $(AM_V_at)rm -f XWin$(EXEEXT) && $(MAKE) XWin$(EXEEXT) -SUBDIRS = man $(GLX_DIR) winclipboard . -DIST_SUBDIRS = man dri glx winclipboard . +SUBDIRS = man $(GLX_DIR) winclipboard wmutil . +DIST_SUBDIRS = man dri glx winclipboard wmutil . diff --git a/hw/xwin/X.ico b/hw/xwin/X.ico Binary files differdeleted file mode 100644 index 5d69818b5..000000000 --- a/hw/xwin/X.ico +++ /dev/null diff --git a/hw/xwin/X.svg b/hw/xwin/X.svg new file mode 100644 index 000000000..3acf88367 --- /dev/null +++ b/hw/xwin/X.svg @@ -0,0 +1,91 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="431" + height="345" + version="1.1" + id="svg4136" + inkscape:version="0.91 r13725" + sodipodi:docname="X.svg"> + <metadata + id="metadata4158"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1680" + inkscape:window-height="1027" + id="namedview4156" + showgrid="true" + showguides="false" + inkscape:zoom="2.0179613" + inkscape:cx="174.54161" + inkscape:cy="178.21329" + inkscape:window-x="1920" + inkscape:window-y="53" + inkscape:window-maximized="1" + inkscape:current-layer="svg4136"> + <inkscape:grid + type="xygrid" + id="grid4190" /> + </sodipodi:namedview> + <style + type="text/css" + id="style4138"><![CDATA[ +#P1 {fill:url(#LO)} +rect {opacity:.40740739;fill:#000cff;width:.50507629;height:0} +]]></style> + <defs + id="defs4140"> + <linearGradient + id="LO" + gradientUnits="userSpaceOnUse" + x1="319.20822" + y1="235.14877" + x2="657.65295" + y2="269.49396" + gradientTransform="translate(-270.9263,-65.70092)"> + <stop + style="stop-color:#e54c18" + offset="0" + id="stop4143" /> + <stop + style="stop-color:#fec350" + offset="1" + id="stop4145" /> + </linearGradient> + </defs> + <path + style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 54.716797 20 C 92.8921 73.307631 131.06849 126.61448 169.24414 179.92188 C 132.25755 228.28102 95.27244 276.64136 58.285156 325 L 108.53516 325 C 137.10238 287.40883 165.66766 249.81618 194.23438 212.22461 C 221.28032 249.81661 248.32766 287.40759 275.37305 325 L 373.49609 325 C 335.76255 272.13742 298.02719 219.27614 260.29297 166.41406 C 297.59705 117.6094 334.9008 68.804499 372.20508 20 L 322.54102 20 L 235.40625 133.77148 C 207.88404 95.847705 180.36205 57.923771 152.83984 20 L 54.716797 20 z " + id="rect5173" /> + <path + d="M 71.1476,325.00127 182.24488,179.74507 67.86815,20.032093 l 73.51436,0.06108 91.13801,125.582867 -136.27013,179.32523 -25.10279,0 z m 217.44779,0.10271 -90.5088,-125.79846 137.40484,-179.409507 24.48173,0 -111.55067,145.941547 113.68843,159.26642 -73.51553,0 z" + id="path4151" + inkscape:connector-curvature="0" /> + <path + id="P1" + d="m 215.48441,78.12559 c -8.85103,0 -18.30729,0.68536 -26.82011,1.50253 15.16593,19.77999 27.75007,36.52951 42.23287,55.55188 -8.12876,-17.49293 -24.83564,-34.26759 -19.05997,-42.89467 5.71717,-8.53969 16.25107,-7.10232 17.05346,-7.10232 16.88849,0 33.14525,1.90739 48.34375,5.4375 l 3.5625,-4.90625 C 260.5261,80.496 238.50842,78.12559 215.48441,78.12559 Z m 91.46875,15.96367 -3.28125,4.6875 c 46.8258,18.33664 78.5,53.36029 78.5,93.49999 0,59.10603 -68.66485,107.0625 -153.28125,107.0625 -84.6164,-10e-6 -153.3125,-47.95648 -153.3125,-107.0625 1e-5,-32.18776 20.37158,-61.08002 52.59375,-80.71874 l -9.90625,-15.09375 c -50.54614,21.43183 -84.09374,59.04962 -84.09375,101.87499 0,66.63368 81.2225,120.6875 181.3125,120.6875 100.08999,0 181.34374,-54.05381 181.34375,-120.6875 0,-44.43292 -36.12255,-83.29245 -89.875,-104.24999 z" + style="fill:url(#LO)" + inkscape:connector-curvature="0" /> +</svg> diff --git a/hw/xwin/XWin.rc b/hw/xwin/XWin.rc index a54e0fdbb..5e4fc6d16 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 ")", 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/glx/Makefile.am b/hw/xwin/glx/Makefile.am index 1fc57f239..160bef5b0 100644 --- a/hw/xwin/glx/Makefile.am +++ b/hw/xwin/glx/Makefile.am @@ -20,20 +20,13 @@ endif libnativeGLthunk_la_SOURCES = \ glthunk.c -if XWIN_MULTIWINDOWEXTWM -DEFS_MULTIWINDOWEXTWM = -DXWIN_MULTIWINDOWEXTWM -endif - if XWIN_GLX_WINDOWS DEFS_GLX_WINDOWS = -DXWIN_GLX_WINDOWS endif DEFS = \ - $(DEFS_MULTIWINDOWEXTWM) \ $(DEFS_GLX_WINDOWS) -AM_CPPFLAGS = -I$(top_srcdir)/miext/rootless - AM_CFLAGS = -DHAVE_XWIN_CONFIG_H $(DIX_CFLAGS) \ $(XWINMODULES_CFLAGS) \ -I$(top_srcdir) \ diff --git a/hw/xwin/glx/indirect.c b/hw/xwin/glx/indirect.c index 1aaa87d8f..dfce17784 100644 --- a/hw/xwin/glx/indirect.c +++ b/hw/xwin/glx/indirect.c @@ -87,6 +87,7 @@ #include <wgl_ext_api.h> #include <winglobals.h> #include <indirect.h> +#include <setjmp.h> /* Not yet in w32api */ #ifndef PFD_SUPPORT_DIRECTDRAW @@ -100,6 +101,12 @@ #endif +typedef struct { + int notOpenGL; + int unknownPixelType; + int unaccelerated; +} PixelFormatRejectStats; + /* ---------------------------------------------------------------------- */ /* * Various debug helpers @@ -285,23 +292,29 @@ 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 unknown pixel type, %d unaccelerated\n", + rejects->notOpenGL, 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"); + ("pxf vis fb render Ste aux accum MS drawable Group/ sRGB\n"); ErrorF - ("idx ID ID VisualType Depth Lvl RGB CI DB Swap reo R G B A Z S buf AR AG AB AA bufs num W P Pb Float Trans Caveat\n"); + ("idx ID ID VisualType Depth Lvl RGB CI DB Swap reo R G B A Z S buf AR AG AB AA bufs num W P Pb Float Trans Caveat cap \n"); ErrorF - ("-----------------------------------------------------------------------------------------------------------------------------\n"); + ("----------------------------------------------------------------------------------------------------------------------------------\n"); while (c != NULL) { unsigned int i = ((GLXWinConfig *) c)->pixelFormatIndex; + const char *float_col = "."; + if (c->renderType & GLX_RGBA_FLOAT_BIT_ARB) float_col = "s"; + if (c->renderType & GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT) float_col = "u"; + ErrorF("%3d %3x %3x " "%-11s" " %3d %3d %s %s %s %s %s " @@ -313,7 +326,8 @@ fbConfigsDump(unsigned int n, __GLXconfig * c) " %s %s %s " " %s " " %s " - " %d %s" + " %d %s " + " %s" "\n", i, c->visualID, c->fbconfigID, visual_class_name(c->visualType), @@ -332,11 +346,11 @@ fbConfigsDump(unsigned int n, __GLXconfig * c) (c->drawableType & GLX_WINDOW_BIT) ? "y" : ".", (c->drawableType & GLX_PIXMAP_BIT) ? "y" : ".", (c->drawableType & GLX_PBUFFER_BIT) ? "y" : ".", - (c->renderType & (GLX_RGBA_FLOAT_BIT_ARB | - GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT)) ? "y" : ".", + float_col, (c->transparentPixel != GLX_NONE_EXT) ? "y" : ".", c->visualSelectGroup, - (c->visualRating == GLX_SLOW_VISUAL_EXT) ? "*" : " "); + (c->visualRating == GLX_SLOW_VISUAL_EXT) ? "*" : " ", + c->sRGBCapable ? "y" : "."); c = c->next; } @@ -371,7 +385,8 @@ static HDC glxWinMakeDC(__GLXWinContext * gc, __GLXWinDrawable * draw, 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); @@ -466,6 +481,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) @@ -477,6 +516,7 @@ glxWinScreenProbe(ScreenPtr pScreen) HWND hwnd; HDC hdc; HGLRC hglrc; + PixelFormatRejectStats rejects; GLWIN_DEBUG_MSG("glxWinScreenProbe"); @@ -497,8 +537,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" @@ -509,7 +552,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; @@ -524,22 +567,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) @@ -551,6 +651,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 = ""; @@ -560,10 +662,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; } @@ -572,47 +679,68 @@ glxWinScreenProbe(ScreenPtr pScreen) // might have completely different capabilities. Of course, good luck getting // those screens to be accelerated in XP and earlier... + { + int i; + + const struct + { + const char *wglext; + const char *glxext; + Bool mandatory; + } extensionMap[] = { + { "WGL_ARB_make_current_read", "GLX_SGI_make_current_read", 1 }, + { "WGL_EXT_swap_control", "GLX_SGI_swap_control", 0 }, + { "WGL_EXT_swap_control", "GLX_MESA_swap_control", 0 }, + // { "WGL_ARB_render_texture", "GLX_EXT_texture_from_pixmap", 0 }, + // Sufficiently different that it's not obvious if this can be done... + { "WGL_ARB_pbuffer", "GLX_SGIX_pbuffer", 1 }, + { "WGL_ARB_multisample", "GLX_ARB_multisample", 1 }, + { "WGL_ARB_multisample", "GLX_SGIS_multisample", 0 }, + { "WGL_ARB_pixel_format_float", "GLX_ARB_fbconfig_float", 0 }, + { "WGL_EXT_pixel_format_packed_float", "GLX_EXT_fbconfig_packed_float", 0 }, + { "WGL_ARB_create_context", "GLX_ARB_create_context", 0 }, + { "WGL_ARB_create_context_profile", "GLX_ARB_create_context_profile", 0 }, + { "WGL_ARB_create_context_robustness", "GLX_ARB_create_context_robustness", 0 }, + { "WGL_EXT_create_context_es2_profile", "GLX_EXT_create_context_es2_profile", 0 }, + { "WGL_ARB_framebuffer_sRGB", "GLX_ARB_framebuffer_sRGB", 0 }, + }; + // // Based on the WGL extensions available, enable various GLX extensions - // XXX: make this table-driven ? // __glXInitExtensionEnableBits(screen->base.glx_enable_bits); - if (strstr(wgl_extensions, "WGL_ARB_make_current_read")) - screen->has_WGL_ARB_make_current_read = TRUE; - else - LogMessage(X_WARNING, "AIGLX: missing WGL_ARB_make_current_read\n"); + for (i = 0; i < sizeof(extensionMap)/sizeof(extensionMap[0]); i++) { + if (strstr(wgl_extensions, extensionMap[i].wglext)) { + __glXEnableExtension(screen->base.glx_enable_bits, extensionMap[i].glxext); + LogMessage(X_INFO, "GLX: enabled %s\n", extensionMap[i].glxext); + } + else if (extensionMap[i].mandatory) { + LogMessage(X_ERROR, "required WGL extension %s is missing\n", extensionMap[i].wglext); + } + } + // Because it pre-dates WGL_EXT_extensions_string, GL_WIN_swap_hint might + // only be in GL_EXTENSIONS if (strstr(gl_extensions, "GL_WIN_swap_hint")) { __glXEnableExtension(screen->base.glx_enable_bits, "GLX_MESA_copy_sub_buffer"); LogMessage(X_INFO, "AIGLX: enabled GLX_MESA_copy_sub_buffer\n"); } - if (strstr(wgl_extensions, "WGL_EXT_swap_control")) { - __glXEnableExtension(screen->base.glx_enable_bits, - "GLX_SGI_swap_control"); - LogMessage(X_INFO, "AIGLX: enabled GLX_SGI_swap_control\n"); - } - -/* // Hmm? screen->texOffset */ -/* if (strstr(wgl_extensions, "WGL_ARB_render_texture")) */ -/* { */ -/* __glXEnableExtension(screen->base.glx_enable_bits, "GLX_EXT_texture_from_pixmap"); */ -/* LogMessage(X_INFO, "AIGLX: GLX_EXT_texture_from_pixmap backed by buffer objects\n"); */ -/* screen->has_WGL_ARB_render_texture = TRUE; */ -/* } */ + if (strstr(wgl_extensions, "WGL_ARB_make_current_read")) + screen->has_WGL_ARB_make_current_read = TRUE; if (strstr(wgl_extensions, "WGL_ARB_pbuffer")) screen->has_WGL_ARB_pbuffer = TRUE; - else - LogMessage(X_WARNING, "AIGLX: missing WGL_ARB_pbuffer\n"); if (strstr(wgl_extensions, "WGL_ARB_multisample")) screen->has_WGL_ARB_multisample = TRUE; - else - LogMessage(X_WARNING, "AIGLX: missing WGL_ARB_multisample\n"); + + if (strstr(wgl_extensions, "WGL_ARB_framebuffer_sRGB")) { + screen->has_WGL_ARB_framebuffer_sRGB = TRUE; + } screen->base.destroy = glxWinScreenDestroy; screen->base.createContext = glxWinCreateContext; @@ -621,8 +749,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, @@ -635,6 +764,7 @@ glxWinScreenProbe(ScreenPtr pScreen) } if (screen->base.numFBConfigs <= 0) { + memset(&rejects, 0, sizeof(rejects)); glxWinCreateConfigs(hdc, screen); screen->has_WGL_ARB_pixel_format = FALSE; } @@ -643,7 +773,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; @@ -662,7 +791,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; @@ -675,9 +804,17 @@ glxWinScreenProbe(ScreenPtr pScreen) // 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); @@ -1133,7 +1270,30 @@ glxWinSetPixelFormat(HDC hdc, int bppOverride, int drawableTypeOverride, (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; @@ -1169,25 +1329,6 @@ glxWinSetPixelFormat(HDC hdc, int bppOverride, int drawableTypeOverride, return FALSE; } } - else { - int pixelFormat = fbConfigToPixelFormatIndex(hdc, 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; } @@ -1650,13 +1791,34 @@ fbConfigToPixelFormatIndex(HDC hdc, __GLXconfig * mode, int attribList[60]; SET_ATTR_VALUE(WGL_SUPPORT_OPENGL_ARB, TRUE); - SET_ATTR_VALUE(WGL_PIXEL_TYPE_ARB, - (mode->visualType == - GLX_TRUE_COLOR) ? WGL_TYPE_RGBA_ARB : - WGL_TYPE_COLORINDEX_ARB); - SET_ATTR_VALUE(WGL_COLOR_BITS_ARB, - (mode->visualType == - GLX_TRUE_COLOR) ? mode->rgbBits : mode->indexBits); + + switch (mode->renderType) + { + case GLX_COLOR_INDEX_BIT: + case GLX_RGBA_BIT | GLX_COLOR_INDEX_BIT: + SET_ATTR_VALUE(WGL_PIXEL_TYPE_ARB, WGL_TYPE_COLORINDEX_ARB); + SET_ATTR_VALUE(WGL_COLOR_BITS_ARB, mode->indexBits); + break; + + default: + ErrorF("unexpected renderType %x\n", mode->renderType); + /* fall-through */ + case GLX_RGBA_BIT: + SET_ATTR_VALUE(WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB); + SET_ATTR_VALUE(WGL_COLOR_BITS_ARB, mode->rgbBits); + break; + + case GLX_RGBA_FLOAT_BIT_ARB: + SET_ATTR_VALUE(WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_FLOAT_ARB); + SET_ATTR_VALUE(WGL_COLOR_BITS_ARB, mode->rgbBits); + break; + + case GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT: + SET_ATTR_VALUE(WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT); + SET_ATTR_VALUE(WGL_COLOR_BITS_ARB, mode->rgbBits); + break; + } + SET_ATTR_VALUE(WGL_RED_BITS_ARB, mode->redBits); SET_ATTR_VALUE(WGL_GREEN_BITS_ARB, mode->greenBits); SET_ATTR_VALUE(WGL_BLUE_BITS_ARB, mode->blueBits); @@ -1686,6 +1848,11 @@ fbConfigToPixelFormatIndex(HDC hdc, __GLXconfig * mode, if (mode->visualRating == GLX_SLOW_VISUAL_EXT) SET_ATTR_VALUE(WGL_ACCELERATION_ARB, WGL_NO_ACCELERATION_ARB); + if (winScreen->has_WGL_ARB_multisample) { + SET_ATTR_VALUE(WGL_SAMPLE_BUFFERS_ARB, mode->sampleBuffers); + SET_ATTR_VALUE(WGL_SAMPLES_ARB, mode->samples); + } + // must support all the drawable types the mode supports if ((mode->drawableType | drawableTypeOverride) & GLX_WINDOW_BIT) SET_ATTR_VALUE(WGL_DRAW_TO_WINDOW_ARB, TRUE); @@ -1709,6 +1876,9 @@ fbConfigToPixelFormatIndex(HDC hdc, __GLXconfig * mode, SET_ATTR_VALUE(WGL_DRAW_TO_PBUFFER_ARB, TRUE); } + if (winScreen->has_WGL_ARB_framebuffer_sRGB) + SET_ATTR_VALUE(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB, TRUE); + SET_ATTR_VALUE(0, 0); // terminator /* choose the first match */ @@ -1839,6 +2009,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... @@ -1983,7 +2155,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 *first = NULL, *prev = NULL; int i = 0; @@ -2068,6 +2240,11 @@ glxWinCreateConfigsExt(HDC hdc, glxWinScreen * screen) ADD_ATTR(WGL_MAX_PBUFFER_HEIGHT_ARB); } + if (screen->has_WGL_ARB_framebuffer_sRGB) { + // we may not query these attrs if WGL_ARB_framebuffer_sRGB is not offered + ADD_ATTR(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB); + } + /* fill in configs */ for (i = 0; i < numConfigs; i++) { int values[num_attrs]; @@ -2089,6 +2266,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); @@ -2122,26 +2300,46 @@ glxWinCreateConfigsExt(HDC hdc, glxWinScreen * screen) c->base.indexBits = ATTR_VALUE(WGL_COLOR_BITS_ARB, 0); c->base.rgbBits = 0; c->base.visualType = GLX_STATIC_COLOR; + c->base.renderType = GLX_RGBA_BIT | GLX_COLOR_INDEX_BIT; + + /* + Assume RGBA rendering is available on all single-channel visuals + (it is specified to render to red component in single-channel + visuals, if supported, but there doesn't seem to be any mechanism + to check if it is supported) + + Color index rendering is only supported on single-channel visuals + */ + + break; + + case WGL_TYPE_RGBA_ARB: + c->base.indexBits = 0; + c->base.rgbBits = ATTR_VALUE(WGL_COLOR_BITS_ARB, 0); + c->base.visualType = GLX_TRUE_COLOR; + c->base.renderType = GLX_RGBA_BIT; break; case WGL_TYPE_RGBA_FLOAT_ARB: - GLWIN_DEBUG_MSG - ("pixelFormat %d is WGL_TYPE_RGBA_FLOAT_ARB, skipping", i + 1); - continue; + c->base.indexBits = 0; + c->base.rgbBits = ATTR_VALUE(WGL_COLOR_BITS_ARB, 0); + c->base.visualType = GLX_TRUE_COLOR; + c->base.renderType = GLX_RGBA_FLOAT_BIT_ARB; + // assert pbuffer drawable + // assert WGL_ARB_pixel_format_float + break; case WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT: - GLWIN_DEBUG_MSG - ("pixelFormat %d is WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT, skipping", - i + 1); - continue; - - case WGL_TYPE_RGBA_ARB: c->base.indexBits = 0; c->base.rgbBits = ATTR_VALUE(WGL_COLOR_BITS_ARB, 0); c->base.visualType = GLX_TRUE_COLOR; + c->base.renderType = GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT; + // assert pbuffer drawable + // assert WGL_EXT_pixel_format_packed_float break; default: + rejects->unknownPixelType++; ErrorF ("wglGetPixelFormatAttribivARB returned unknown value 0x%x for WGL_PIXEL_TYPE_ARB\n", ATTR_VALUE(WGL_PIXEL_TYPE_ARB, 0)); @@ -2164,7 +2362,7 @@ glxWinCreateConfigsExt(HDC hdc, glxWinScreen * screen) if (layers > 0) { ErrorF - ("pixelFormat %d: has %d overlay, %d underlays which aren't currently handled", + ("pixelFormat %d: has %d overlay, %d underlays which aren't currently handled\n", i, ATTR_VALUE(WGL_NUMBER_OVERLAYS_ARB, 0), ATTR_VALUE(WGL_NUMBER_UNDERLAYS_ARB, 0)); // XXX: need to iterate over layers? @@ -2182,7 +2380,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: @@ -2234,30 +2435,20 @@ glxWinCreateConfigsExt(HDC hdc, glxWinScreen * screen) | (ATTR_VALUE(WGL_DRAW_TO_BITMAP_ARB, 0) ? GLX_PIXMAP_BIT : 0) | (ATTR_VALUE(WGL_DRAW_TO_PBUFFER_ARB, 0) ? GLX_PBUFFER_BIT : 0)); - /* - Assume OpenGL RGBA rendering is available on all visuals - (it is specified to render to red component in single-channel visuals, - if supported, but there doesn't seem to be any mechanism to check if it - is supported) - - Color index rendering is only supported on single-channel visuals - */ - if (c->base.visualType == GLX_STATIC_COLOR) { - c->base.renderType = GLX_RGBA_BIT | GLX_COLOR_INDEX_BIT; - } - else { - c->base.renderType = GLX_RGBA_BIT; - } - c->base.fbconfigID = -1; // will be set by __glXScreenInit() /* 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; @@ -2324,7 +2515,12 @@ glxWinCreateConfigsExt(HDC hdc, glxWinScreen * screen) GLX_TEXTURE_1D_BIT_EXT | GLX_TEXTURE_2D_BIT_EXT | GLX_TEXTURE_RECTANGLE_BIT_EXT; c->base.yInverted = -1; - c->base.sRGBCapable = 0; + + /* WGL_ARB_framebuffer_sRGB */ + if (screen->has_WGL_ARB_framebuffer_sRGB) + c->base.sRGBCapable = ATTR_VALUE(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB, 0); + else + c->base.sRGBCapable = 0; n++; diff --git a/hw/xwin/glx/indirect.h b/hw/xwin/glx/indirect.h index bcdef153a..c32ce7894 100644 --- a/hw/xwin/glx/indirect.h +++ b/hw/xwin/glx/indirect.h @@ -69,6 +69,7 @@ struct __GLXWinScreen { Bool has_WGL_ARB_pbuffer; Bool has_WGL_ARB_render_texture; Bool has_WGL_ARB_make_current_read; + Bool has_WGL_ARB_framebuffer_sRGB; /* wrapped screen functions */ RealizeWindowProcPtr RealizeWindow; diff --git a/hw/xwin/glx/winpriv.c b/hw/xwin/glx/winpriv.c index 8ed93aba3..9efea45c4 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, + (unsigned int)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. @@ -49,7 +84,7 @@ winGetWindowInfo(WindowPtr pWin) } if (pWinPriv->hWnd == NULL) { - winCreateWindowsWindow(pWin); + winCreateWindowsWindowHierarchy(pWin); winDebug("winGetWindowInfo: forcing window to exist\n"); } @@ -63,24 +98,6 @@ winGetWindowInfo(WindowPtr pWin) return hwnd; } -#ifdef XWIN_MULTIWINDOWEXTWM - /* check for multiwindow external wm mode */ - if (pScreenInfo->fMWExtWM) { - win32RootlessWindowPtr pRLWinPriv - = (win32RootlessWindowPtr) RootlessFrameForWindow(pWin, FALSE); - - if (pRLWinPriv == NULL) { - ErrorF("winGetWindowInfo: window has no privates\n"); - return hwnd; - } - - if (pRLWinPriv->hWnd != NULL) { - /* copy window handle */ - hwnd = pRLWinPriv->hWnd; - } - return hwnd; - } -#endif } else { ScreenPtr pScreen = g_ScreenInfo[0].pScreen; @@ -108,11 +125,6 @@ winCheckScreenAiglxIsSupported(ScreenPtr pScreen) if (pScreenInfo->fMultiWindow) return TRUE; -#ifdef XWIN_MULTIWINDOWEXTWM - if (pScreenInfo->fMWExtWM) - return TRUE; -#endif - return FALSE; } diff --git a/hw/xwin/man/XWin.man b/hw/xwin/man/XWin.man index 2081ea1b9..050b4d1b4 100644 --- a/hw/xwin/man/XWin.man +++ b/hw/xwin/man/XWin.man @@ -51,11 +51,6 @@ Also start the integrated \fIWindows\fP-based window manager. Run the server in rootless mode. The X server works on a window covering the whole screen but the root window is hidden from view. -.TP 8 -.B \-mwextwm -Experimental. -The mode combines \fB\-rootless\fP mode drawing with native \fIWindows\fP -window frames managed by the experimental external window manager \fIxwinwm\fP. .PP \fBNOTE:\fP \fI-multiwindow\fP mode uses its own internal window manager. All other modes require an external window manager in order to move, resize, and perform other @@ -113,6 +108,10 @@ The X server window takes the full screen, covering completely the \fIWindows\fP desktop. Currently \fB\-fullscreen\fP may only be applied to one X screen. .TP 8 +.B "\-icon" \fIicon-specifier\fP +Override the window icon for the screen window from the default. +The \fIicon-specifier\fP is as defined in \fIXWinrc(__filemansuffix__)\fP. +.TP 8 .B \-nodecoration Do not give the Cygwin/X window a \fIWindows\fP window border, title bar, etc. @@ -175,6 +174,21 @@ on its own is equivalent to \fB\-resize=randr\fP Add the host name to the window title for X applications which are running on remote hosts, when that information is available and it's useful to do so. The default is enabled. +.TP 8 +.B \-[no]compositewm +Use Composite extension redirection to maintain a bitmap image of each top-level +X window, so window contents which are occluded show correctly in task bar and +task switcher previews. +The default is enabled. +.TP 8 +.B \-[no]compositealpha +X windows with per-pixel alpha are composited into the \fIWindows\fP desktop +(i.e. a \fIWindows\fP window can be seen through any transparency in an X window +placed over it). + +This option has no effect on Windows 8 and 8.1. +This option has no effect if \fB-compositewm\fP is disabled. +The default is disabled. .SH OPTIONS CONTROLLING WINDOWS INTEGRATION .TP 8 @@ -211,6 +225,7 @@ The default is enabled. .TP 8 .B \-swcursor Disable the usage of the \fIWindows\fP cursor and use the X11 software cursor instead. +This option is ignored if \fB-compositewm\fP is also enabled. .TP 8 .B \-[no]trayicon Do not create a tray icon. Default is to create one @@ -306,6 +321,10 @@ and for \fIlevel\fP=3 detailed log information (including trace and debug output) is produced. Bigger values will yield a still more detailed debug output. .TP 8 +.B \-silent-dup-error +If another instance of \fIXWin\fP with the same display number is found running, +exit silently and don't display any error message. +.TP 8 .B "\-xkblayout \fIlayout\fP" .TP 8 .B "\-xkbmodel \fImodel\fP" diff --git a/hw/xwin/man/XWinrc.man b/hw/xwin/man/XWinrc.man index 0cc2d9d44..15eaca652 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. @@ -134,31 +163,34 @@ such items should be included at the start or at the end of the menu. .SH Icon Instructions -When specifying an \fIicon-file\fP in the following commands several different formats are allowed: -.br -\fB"NAME.ICO"\fP\fI of an .ico format file\fP -.br -\t \t ("cygwin.ico", "apple.ico") -.br -\fB"NAME.DLL,nn"\fP\fI of a .DLL and icon index\fP +When specifying an \fIicon-specifier\fP in the following commands several different formats are allowed: +.PP +.IP \fI"NAME.ICO"\fP 16 +filename of an .ico format file .br -\t \t ("c:\\windows\\system32\\shell32.dll,4" is the default folder icon) +(e.g. "cygwin.ico", "apple.ico", "C:\\icons\\cheese.ico", "/usr/share/icons/moon.ico") +.IP \fI"NAME.DLL,nnn"\fP 16 +filename of a DLL with an index into it's ICON resources .br -\fB",nnn"\fP\fI index into XWin.EXE internal ICON resources\fP +(e.g. "c:\\windows\\system32\\shell32.dll,4", the default folder icon, + "/usr/bin/cygicons-0.dll,10", the hippo icon) +.IP \fI",nnn"\fP 16 +index into the XWin executable's internal ICON resources .br -\t \t (",101" is the 1st icon inside \fIXWin.EXE\fP) +(e.g. ",101" is the 1st icon in \fIXWin\fP) .TP 8 .B ICONDIRECTORY \fIWindows-path-to-icon-directory\fP -Defines the default directory to search for \ficon-file\fP files. +Defines the default directory for the file when an \fIicon-specifier\fP doesn't +contain an absolute path. It should be a \fIWindows\fP style path (e.g. C:\\cygwin\\usr\\local\\icons). .TP 8 -.B DEFAULTICON \fIicon-file\fP +.B DEFAULTICON \fIicon-specifier\fP Defines a replacement for the standard X icon for applications without specified icons. .TP 8 .B ICONS { .br - \fIclass-or-name-of-window\fP \fIicon-file\fP + \fIclass-or-name-of-window\fP \fIicon-specifier\fP .br \fI...\fP .br @@ -171,7 +203,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 +248,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/meson.build b/hw/xwin/meson.build index 1bf9891ed..f09c5a435 100644 --- a/hw/xwin/meson.build +++ b/hw/xwin/meson.build @@ -18,6 +18,8 @@ xwin_c_args = [] xwin_c_args += '-DHAVE_XWIN_CONFIG_H' xwin_c_args += '-Wno-bad-function-cast' +subdir('wmutil') + srcs_windows = [ 'winclipboardinit.c', 'winclipboardwrappers.c', @@ -42,7 +44,7 @@ srcs_windows += [ 'propertystore.h', 'winSetAppUserModelID.c', ] -xwin_sys_libs += ['-lshlwapi', '-lole32'] +xwin_sys_libs += ['-lshlwapi', '-lole32', '-ldwmapi'] srcs_windows += [ 'winrandr.c', @@ -87,8 +89,6 @@ srcs_windows += [ 'winconfig.h', 'win.h', 'winglobals.h', - 'winkeybd.h', - 'winkeynames.h', 'winlayouts.h', 'winmessages.h', 'winmonitors.h', @@ -104,7 +104,19 @@ srcs_windows += [ '../../mi/miinitext.c', ] -rsrc = windows.compile_resources('XWin.rc', include_directories: include_directories('../../include/')) +convert = find_program('convert') +custom_target( + 'xlogo-icon', + command: [convert, '-background', 'transparent', '-trim', '-define', 'icon:auto-resize', '@INPUT@', '@OUTPUT@'], + input: 'X.svg', + output: 'X.ico', +) + +rsrc = windows.compile_resources( + 'XWin.rc', + args: ['--use-temp-file', '-DHOST="@0@-@1@"'.format(host_machine.system(), host_machine.cpu_family())], + include_directories: [include_directories('.'), include_directories('../../include/')], +) srcs_windows += rsrc flex = find_program('flex') @@ -135,6 +147,7 @@ xwin_dep = [ dependency('xcb-image'), dependency('xcb-ewmh'), dependency('xcb-icccm'), + dependency('xcb-composite'), ] executable( @@ -146,6 +159,7 @@ executable( xwin_windowsdri, xwin_glx, xwin_clipboard, + xwin_wmutil, libxserver_fb, libxserver, libxserver_glx, @@ -172,3 +186,10 @@ xwin_man = configure_file( configuration: manpage_config, ) install_man(xwin_man) + +xwinrc_man = configure_file( + input: 'man/XWinrc.man', + output: 'XWinrc.5', + configuration: manpage_config, +) +install_man(xwinrc_man) diff --git a/hw/xwin/system.XWinrc b/hw/xwin/system.XWinrc index f0771c610..c2e9ceb9a 100644 --- a/hw/xwin/system.XWinrc +++ b/hw/xwin/system.XWinrc @@ -8,10 +8,6 @@ # Comments begin with "#" or "//" and go to the end-of-line -# Paths to commands are **cygwin** based (i.e. /usr/local/bin/xcalc) - -# Paths to icons are **WINDOWS** based (i.e. c:\windows\icons) - # Menus are defined as... # MENU <name> { # <Menu Text> EXEC <command> @@ -55,15 +51,15 @@ # To define where ICO files live (** Windows path**) # ICONDIRECTORY <windows-path i.e. c:\cygwin\usr\icons> -# NOTE: If you specify a fully qualified path to an ICON below -# (i.e. "c:\xxx" or "d:\xxxx") +# NOTE: If you specify an absolute path in Windows or Cygwin format to an ICON below +# (i.e. "c:\icons\xxx.ico" or "/usr/share/icons/xxx.ico") # this ICONDIRECTORY will not be prepended # To change the taskbar icon use... -# TRAYICON <name-of-windows-ico-file-in-icondirectory> +# TRAYICON <icon-specifier> # To define a replacement for the standard X icon for apps w/o specified icons -# DEFAULTICON <name-of-windows-ico-file-in-icondirectory> +# DEFAULTICON <icon-specifier> # To define substitute icons on a per-window basis use... # ICONS { @@ -81,38 +77,46 @@ // own configuration file. // Make some menus... -menu apps { - xterm exec "xterm" - "Emacs" exec "emacs" - notepad exec notepad - xload exec "xload -display %display%" # Comment -} +# menu apps { +# xterm exec "xterm" +# "Emacs" exec "emacs" +# notepad exec notepad +# xload exec "xload -display %display%" # Comment +# } menu root { +// "Applications" menu apps // Comments fit here, too... - "Reload .XWinrc" RELOAD - "Applications" menu apps - SEParATOR -} +// SEPARATOR -menu aot { - Separator - "Always on Top" alwaysontop -} + 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 -menu xtermspecial { - "Emacs" exec "emacs" - "Always on Top" alwaysontop - SepArAtor + "Reload .XWinrc" RELOAD + SEParATOR } RootMenu root -DefaultSysMenu aot atend - -SysMenu { - "xterm" xtermspecial atstart -} +# menu aot { +# Separator +# "Always on Top" alwaysontop +# } +# +# menu xtermspecial { +# "Emacs" exec "emacs" +# "Always on Top" alwaysontop +# SepArAtor +# } +# +# DefaultSysMenu aot atend +# +# SysMenu { +# "xterm" xtermspecial atstart +# } # IconDirectory "c:\winnt\" diff --git a/hw/xwin/win.h b/hw/xwin/win.h index dda2cb548..9790cbe7e 100644 --- a/hw/xwin/win.h +++ b/hw/xwin/win.h @@ -163,9 +163,6 @@ #include "miline.h" #include "shadow.h" #include "fb.h" -#ifdef XWIN_MULTIWINDOWEXTWM -#include "rootless.h" -#endif #include "mipict.h" #include "picturestr.h" @@ -187,6 +184,7 @@ #define WM_TRAYICON (WM_USER + 1000) #define WM_INIT_SYS_MENU (WM_USER + 1001) #define WM_GIVEUP (WM_USER + 1002) +#define WM_ASYNCMOVE (WM_USER + 1003) /* Local includes */ #include "winwindow.h" @@ -271,6 +269,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); @@ -297,10 +297,8 @@ typedef Bool (*winCreateScreenResourcesProc) (ScreenPtr); */ typedef struct { - HDC hdcSelected; HBITMAP hBitmap; - BYTE *pbBits; - DWORD dwScanlineBytes; + void *pbBits; BITMAPINFOHEADER *pbmih; } winPrivPixmapRec, *winPrivPixmapPtr; @@ -390,11 +388,9 @@ typedef struct { #endif Bool fFullScreen; Bool fDecoration; -#ifdef XWIN_MULTIWINDOWEXTWM - Bool fMWExtWM; -#endif Bool fRootless; Bool fMultiWindow; + Bool fCompositeWM; Bool fMultiMonitorOverride; Bool fMultipleMonitors; Bool fLessPointer; @@ -408,6 +404,10 @@ typedef struct { /* Did the user explicitly set this screen? */ Bool fExplicitScreen; + + /* Icons for screen window */ + HICON hIcon; + HICON hIconSm; } winScreenInfo, *winScreenInfoPtr; /* @@ -464,18 +464,10 @@ typedef struct _winPrivScreenRec { LPDIRECTDRAWCLIPPER pddcPrimary; BOOL fRetryCreateSurface; -#ifdef XWIN_MULTIWINDOWEXTWM - /* Privates used by multi-window external window manager */ - RootlessFrameID widTop; - Bool fRestacking; -#endif - /* Privates used by multi-window */ pthread_t ptWMProc; pthread_t ptXMsgProc; void *pWMInfo; - - /* Privates used by both multi-window and rootless */ Bool fRootWindowShown; /* Privates used for any module running in a seperate thread */ @@ -493,6 +485,7 @@ typedef struct _winPrivScreenRec { winCreateBoundingWindowProcPtr pwinCreateBoundingWindow; winFinishScreenInitProcPtr pwinFinishScreenInit; winBltExposedRegionsProcPtr pwinBltExposedRegions; + winBltExposedWindowRegionProcPtr pwinBltExposedWindowRegion; winActivateAppProcPtr pwinActivateApp; winRedrawScreenProcPtr pwinRedrawScreen; winRealizeInstalledPaletteProcPtr pwinRealizeInstalledPalette; @@ -521,30 +514,13 @@ typedef struct _winPrivScreenRec { ResizeWindowProcPtr ResizeWindow; MoveWindowProcPtr MoveWindow; SetShapeProcPtr SetShape; + ModifyPixmapHeaderProcPtr ModifyPixmapHeader; winCursorRec cursor; Bool fNativeGlActive; } winPrivScreenRec; -#ifdef XWIN_MULTIWINDOWEXTWM -typedef struct { - RootlessWindowPtr pFrame; - HWND hWnd; - int dwWidthBytes; - BITMAPINFOHEADER *pbmihShadow; - HBITMAP hbmpShadow; - HDC hdcShadow; - HDC hdcScreen; - BOOL fResized; - BOOL fRestackingNow; - BOOL fClose; - BOOL fMovingOrSizing; - BOOL fDestroyed; //for debug - char *pfb; -} win32RootlessWindowRec, *win32RootlessWindowPtr; -#endif - typedef struct { void *value; XID id; @@ -794,9 +770,6 @@ void */ int - winTranslateKey(WPARAM wParam, LPARAM lParam); - -int winKeybdProc(DeviceIntPtr pDeviceInt, int iState); void @@ -805,20 +778,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 */ @@ -847,14 +806,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 @@ -974,18 +926,36 @@ void winCopyWindowMultiWindow(WindowPtr pWin, DDXPointRec oldpt, RegionPtr oldRegion); +PixmapPtr +winCreatePixmapMultiwindow(ScreenPtr pScreen, int width, int height, int depth, + unsigned usage_hint); +Bool +winDestroyPixmapMultiwindow(PixmapPtr pPixmap); + +Bool +winModifyPixmapHeaderMultiwindow(PixmapPtr pPixmap, + int width, + int height, + int depth, + int bitsPerPixel, int devKind, void *pPixData); + XID winGetWindowID(WindowPtr pWin); int winAdjustXWindow(WindowPtr pWin, HWND hwnd); +void + winAdjustWindowsWindow(WindowPtr pWin, HWND hwnd); + /* * winmultiwindowwndproc.c */ LRESULT CALLBACK winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); +LRESULT CALLBACK +winChildWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); /* * wintrayicon.c @@ -1009,105 +979,6 @@ winHandleIconMessage(HWND hwnd, UINT message, LRESULT CALLBACK winWindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); -#ifdef XWIN_MULTIWINDOWEXTWM -/* - * winwin32rootless.c - */ - -Bool - -winMWExtWMCreateFrame(RootlessWindowPtr pFrame, ScreenPtr pScreen, - int newX, int newY, RegionPtr pShape); - -void - winMWExtWMDestroyFrame(RootlessFrameID wid); - -void - -winMWExtWMMoveFrame(RootlessFrameID wid, ScreenPtr pScreen, int newX, int newY); - -void - -winMWExtWMResizeFrame(RootlessFrameID wid, ScreenPtr pScreen, - int newX, int newY, unsigned int newW, unsigned int newH, - unsigned int gravity); - -void - winMWExtWMRestackFrame(RootlessFrameID wid, RootlessFrameID nextWid); - -void - winMWExtWMReshapeFrame(RootlessFrameID wid, RegionPtr pShape); - -void - winMWExtWMUnmapFrame(RootlessFrameID wid); - -void - -winMWExtWMStartDrawing(RootlessFrameID wid, char **pixelData, int *bytesPerRow); - -void - winMWExtWMStopDrawing(RootlessFrameID wid, Bool flush); - -void - winMWExtWMUpdateRegion(RootlessFrameID wid, RegionPtr pDamage); - -void - -winMWExtWMDamageRects(RootlessFrameID wid, int count, const BoxRec * rects, - int shift_x, int shift_y); - -void - winMWExtWMRootlessSwitchWindow(RootlessWindowPtr pFrame, WindowPtr oldWin); - -void - -winMWExtWMCopyBytes(unsigned int width, unsigned int height, - const void *src, unsigned int srcRowBytes, - void *dst, unsigned int dstRowBytes); - -void - -winMWExtWMCopyWindow(RootlessFrameID wid, int dstNrects, - const BoxRec * dstRects, int dx, int dy); -#endif - -#ifdef XWIN_MULTIWINDOWEXTWM -/* - * winwin32rootlesswindow.c - */ - -void - winMWExtWMReorderWindows(ScreenPtr pScreen); - -void - winMWExtWMMoveXWindow(WindowPtr pWin, int x, int y); - -void - winMWExtWMResizeXWindow(WindowPtr pWin, int w, int h); - -void - winMWExtWMMoveResizeXWindow(WindowPtr pWin, int x, int y, int w, int h); - -void - -winMWExtWMUpdateWindowDecoration(win32RootlessWindowPtr pRLWinPriv, - winScreenInfoPtr pScreenInfo); - -wBOOL CALLBACK winMWExtWMDecorateWindow(HWND hwnd, LPARAM lParam); - -void - winMWExtWMRestackWindows(ScreenPtr pScreen); -#endif - -#ifdef XWIN_MULTIWINDOWEXTWM -/* - * winwin32rootlesswndproc.c - */ - -LRESULT CALLBACK -winMWExtWMWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); -#endif - /* * winwindowswm.c */ diff --git a/hw/xwin/winclipboard/internal.h b/hw/xwin/winclipboard/internal.h index 2e6b22db3..766a836ae 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. * @@ -38,7 +37,7 @@ /* Windows headers */ #include <X11/Xwindows.h> -#define WIN_XEVENTS_SUCCESS 0 +#define WIN_XEVENTS_SUCCESS 0 // more like 'CONTINUE' #define WIN_XEVENTS_FAILED 1 #define WIN_XEVENTS_NOTIFY_DATA 3 #define WIN_XEVENTS_NOTIFY_TARGETS 4 @@ -77,6 +76,7 @@ typedef struct Atom atomUTF8String; Atom atomCompoundText; Atom atomTargets; + Atom atomIncr; } ClipboardAtoms; /* Modern clipboard API functions */ @@ -111,6 +111,8 @@ typedef struct { Bool fUseUnicode; Atom *targetList; + unsigned char *incr; + unsigned long int incrsize; } ClipboardConversionData; int diff --git a/hw/xwin/winclipboard/meson.build b/hw/xwin/winclipboard/meson.build index dd7b2d20e..0395eb32d 100644 --- a/hw/xwin/winclipboard/meson.build +++ b/hw/xwin/winclipboard/meson.build @@ -30,3 +30,10 @@ executable( dependencies: [dependency('x11')], install: true, ) + +xwinclip_man = configure_file( + input: 'xwinclip.man', + output: 'xwinclip.1', + configuration: manpage_config, +) +install_man(xwinclip_man) diff --git a/hw/xwin/winclipboard/thread.c b/hw/xwin/winclipboard/thread.c index fa57ada80..221776567 100644 --- a/hw/xwin/winclipboard/thread.c +++ b/hw/xwin/winclipboard/thread.c @@ -50,6 +50,7 @@ #include <fcntl.h> #include <setjmp.h> #include <pthread.h> +#include <locale.h> #include <sys/param.h> // for MAX() macro #ifdef HAS_WINSOCK @@ -59,6 +60,7 @@ #endif #include <X11/Xatom.h> +#include <X11/Xlocale.h> #include <X11/extensions/Xfixes.h> #include "winclipboard.h" #include "internal.h" @@ -131,15 +133,28 @@ 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; - } + { + const char *locale; + + /* Allow multiple threads to access Xlib */ + if (XInitThreads() == 0) { + ErrorF("winClipboardProc - XInitThreads failed.\n"); + } + + /* + * setlocale applies to all threads in the current process. + * Apply locale specified in LANG environment variable. + */ + locale = setlocale(LC_ALL, ""); + if (!locale) { + ErrorF("winClipboardProc - setlocale failed.\n"); + } - /* See if X supports the current locale */ - if (XSupportsLocale() == False) { - ErrorF("winClipboardProc - Warning: Locale not supported by X.\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"); + } } g_fpAddClipboardFormatListener = (ADDCLIPBOARDFORMATLISTENERPROC)GetProcAddress(GetModuleHandle("user32"),"AddClipboardFormatListener"); @@ -174,7 +189,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 */ @@ -199,15 +214,16 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay) atoms.atomUTF8String = XInternAtom (pDisplay, "UTF8_STRING", False); atoms.atomCompoundText = XInternAtom (pDisplay, "COMPOUND_TEXT", False); atoms.atomTargets = XInternAtom (pDisplay, "TARGETS", False); + atoms.atomIncr = XInternAtom (pDisplay, "INCR", False); /* 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; @@ -265,6 +281,8 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay) } data.fUseUnicode = fUseUnicode; + data.incr = NULL; + data.incrsize = 0; /* Loop for events */ while (1) { @@ -353,7 +371,6 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay) #endif } - winClipboardProc_Exit: /* broke out of while loop on a shutdown message */ fShutdown = TRUE; @@ -391,7 +408,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 c8d0064bd..ec5543ab6 100644 --- a/hw/xwin/winclipboard/wndproc.c +++ b/hw/xwin/winclipboard/wndproc.c @@ -73,13 +73,12 @@ winProcessXEventsTimeout(HWND hwnd, Window iWindow, Display * pDisplay, int iConnNumber; struct timeval tv; int iReturn; - DWORD dwStopTime = GetTickCount() + iTimeoutSec * 1000; - winDebug("winProcessXEventsTimeout () - pumping X events for %d seconds\n", + winDebug("winProcessXEventsTimeout () - pumping X events, timeout %d seconds\n", iTimeoutSec); /* Get our connection number */ - iConnNumber = ConnectionNumber(pDisplay); + iConnNumber = XConnectionNumber(pDisplay); /* Loop for X events */ while (1) { @@ -104,11 +103,9 @@ winProcessXEventsTimeout(HWND hwnd, Window iWindow, Display * pDisplay, FD_SET(iConnNumber, &fdsRead); /* Adjust timeout */ - remainingTime = dwStopTime - GetTickCount(); + remainingTime = iTimeoutSec * 1000; tv.tv_sec = remainingTime / 1000; tv.tv_usec = (remainingTime % 1000) * 1000; - winDebug("winProcessXEventsTimeout () - %ld milliseconds left\n", - remainingTime); /* Break out if no time left */ if (remainingTime <= 0) @@ -494,6 +491,9 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) /* Process X events */ data.fUseUnicode = fConvertToUnicode; + data.incr = NULL; + data.incrsize = 0; + iReturn = winProcessXEventsTimeout(hwnd, iWindow, pDisplay, @@ -517,10 +517,10 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) struct target_priority target_priority_table[] = { - { atoms->atomCompoundText, 0 }, #ifdef X_HAVE_UTF8_STRING - { atoms->atomUTF8String, 1 }, + { atoms->atomUTF8String, 0 }, #endif + { atoms->atomCompoundText, 1 }, { XA_STRING, 2 }, }; diff --git a/hw/xwin/winclipboard/xevents.c b/hw/xwin/winclipboard/xevents.c index d4ea97fc3..7d55f3d92 100644 --- a/hw/xwin/winclipboard/xevents.c +++ b/hw/xwin/winclipboard/xevents.c @@ -184,6 +184,271 @@ winClipboardSelectionNotifyTargets(HWND hwnd, Window iWindow, Display *pDisplay, return WIN_XEVENTS_NOTIFY_TARGETS; } +static int +winClipboardSelectionNotifyData(HWND hwnd, Window iWindow, Display *pDisplay, ClipboardConversionData *data, ClipboardAtoms *atoms) +{ + Atom encoding; + int format; + unsigned long int nitems; + unsigned long int after; + unsigned char *value; + XTextProperty xtpText = { 0 }; + Bool fSetClipboardData = TRUE; + int iReturn; + char **ppszTextList = NULL; + int iCount; + char *pszReturnData = NULL; + wchar_t *pwszUnicodeStr = NULL; + HGLOBAL hGlobal = NULL; + char *pszConvertData = NULL; + char *pszGlobalData = NULL; + + /* Retrieve the selection data and delete the property */ + iReturn = XGetWindowProperty(pDisplay, + iWindow, + atoms->atomLocalProperty, + 0, + INT_MAX, + True, + AnyPropertyType, + &encoding, + &format, + &nitems, + &after, + &value); + if (iReturn != Success) { + ErrorF("winClipboardFlushXEvents - SelectionNotify - " + "XGetWindowProperty () failed, aborting: %d\n", iReturn); + goto winClipboardFlushXEvents_SelectionNotify_Done; + } + + { + char *pszAtomName = NULL; + + winDebug("SelectionNotify - returned data %lu left %lu\n", nitems, after); + pszAtomName = XGetAtomName(pDisplay, encoding); + winDebug("Notify atom name %s\n", pszAtomName); + XFree(pszAtomName); + pszAtomName = NULL; + } + + /* INCR reply indicates the start of a incremental transfer */ + if (encoding == atoms->atomIncr) { + winDebug("winClipboardSelectionNotifyData: starting INCR, anticipated size %d\n", *(int *)value); + data->incrsize = 0; + data->incr = malloc(*(int *)value); + // XXX: if malloc failed, we have an error + return WIN_XEVENTS_SUCCESS; + } + else if (data->incr) { + /* If an INCR transfer is in progress ... */ + if (nitems == 0) { + winDebug("winClipboardSelectionNotifyData: ending INCR, actual size %ld\n", data->incrsize); + /* a zero-length property indicates the end of the data */ + xtpText.value = data->incr; + xtpText.encoding = encoding; + xtpText.format = format; // XXX: The type of the converted selection is the type of the first partial property. The remaining partial properties must have the same type. + xtpText.nitems = data->incrsize; + } + else { + /* Otherwise, continue appending the INCR data */ + winDebug("winClipboardSelectionNotifyData: INCR, %ld bytes\n", nitems); + data->incr = realloc(data->incr, data->incrsize + nitems); + memcpy(data->incr + data->incrsize, value, nitems); + data->incrsize = data->incrsize + nitems; + return WIN_XEVENTS_SUCCESS; + } + } + else { + /* Otherwise, the data is just contained in the property */ + winDebug("winClipboardSelectionNotifyData: non-INCR, %ld bytes\n", nitems); + xtpText.value = value; + xtpText.encoding = encoding; + xtpText.format = format; + xtpText.nitems = nitems; + } + + if (data->fUseUnicode) { +#ifdef X_HAVE_UTF8_STRING + /* Convert the text property to a text list */ + iReturn = Xutf8TextPropertyToTextList(pDisplay, + &xtpText, + &ppszTextList, &iCount); +#endif + } + else { + iReturn = XmbTextPropertyToTextList(pDisplay, + &xtpText, + &ppszTextList, &iCount); + } + if (iReturn == Success || iReturn > 0) { + /* Conversion succeeded or some unconvertible characters */ + if (ppszTextList != NULL) { + int i; + int iReturnDataLen = 0; + for (i = 0; i < iCount; i++) { + iReturnDataLen += strlen(ppszTextList[i]); + } + pszReturnData = malloc(iReturnDataLen + 1); + pszReturnData[0] = '\0'; + for (i = 0; i < iCount; i++) { + strcat(pszReturnData, ppszTextList[i]); + } + } + else { + ErrorF("winClipboardFlushXEvents - SelectionNotify - " + "X*TextPropertyToTextList list_return is NULL.\n"); + pszReturnData = malloc(1); + pszReturnData[0] = '\0'; + } + } + else { + ErrorF("winClipboardFlushXEvents - SelectionNotify - " + "X*TextPropertyToTextList returned: "); + switch (iReturn) { + case XNoMemory: + ErrorF("XNoMemory\n"); + break; + case XLocaleNotSupported: + ErrorF("XLocaleNotSupported\n"); + break; + case XConverterNotFound: + ErrorF("XConverterNotFound\n"); + break; + default: + ErrorF("%d\n", iReturn); + break; + } + pszReturnData = malloc(1); + pszReturnData[0] = '\0'; + } + + + if (ppszTextList) + XFreeStringList(ppszTextList); + ppszTextList = NULL; + + /* Free the data returned from XGetWindowProperty */ + XFree(value); + value = NULL; + nitems = 0; + + /* Free any INCR data */ + if (data->incr) { + free(data->incr); + data->incr = NULL; + data->incrsize = 0; + } + + /* Convert the X clipboard string to DOS format */ + winClipboardUNIXtoDOS(&pszReturnData, strlen(pszReturnData)); + + if (data->fUseUnicode) { + /* Find out how much space needed to convert MBCS to Unicode */ + int iUnicodeLen = MultiByteToWideChar(CP_UTF8, + 0, + pszReturnData, -1, NULL, 0); + + /* NOTE: iUnicodeLen includes space for null terminator */ + pwszUnicodeStr = malloc(sizeof(wchar_t) * iUnicodeLen); + if (!pwszUnicodeStr) { + ErrorF("winClipboardFlushXEvents - SelectionNotify " + "malloc failed for pwszUnicodeStr, aborting.\n"); + + /* Abort */ + goto winClipboardFlushXEvents_SelectionNotify_Done; + } + + /* Do the actual conversion */ + MultiByteToWideChar(CP_UTF8, + 0, + pszReturnData, + -1, pwszUnicodeStr, iUnicodeLen); + + /* Allocate global memory for the X clipboard data */ + hGlobal = GlobalAlloc(GMEM_MOVEABLE, + sizeof(wchar_t) * iUnicodeLen); + } + else { + int iConvertDataLen = 0; + pszConvertData = strdup(pszReturnData); + iConvertDataLen = strlen(pszConvertData) + 1; + + /* Allocate global memory for the X clipboard data */ + hGlobal = GlobalAlloc(GMEM_MOVEABLE, iConvertDataLen); + } + + free(pszReturnData); + + /* Check that global memory was allocated */ + if (!hGlobal) { + ErrorF("winClipboardFlushXEvents - SelectionNotify " + "GlobalAlloc failed, aborting: %08x\n", (unsigned int)GetLastError()); + + /* Abort */ + goto winClipboardFlushXEvents_SelectionNotify_Done; + } + + /* Obtain a pointer to the global memory */ + pszGlobalData = GlobalLock(hGlobal); + if (pszGlobalData == NULL) { + ErrorF("winClipboardFlushXEvents - Could not lock global " + "memory for clipboard transfer\n"); + + /* Abort */ + goto winClipboardFlushXEvents_SelectionNotify_Done; + } + + /* Copy the returned string into the global memory */ + if (data->fUseUnicode) { + wcscpy((wchar_t *)pszGlobalData, pwszUnicodeStr); + free(pwszUnicodeStr); + pwszUnicodeStr = NULL; + } + else { + strcpy(pszGlobalData, pszConvertData); + free(pszConvertData); + pszConvertData = NULL; + } + + /* Release the pointer to the global memory */ + GlobalUnlock(hGlobal); + pszGlobalData = NULL; + + /* Push the selection data to the Windows clipboard */ + if (data->fUseUnicode) + SetClipboardData(CF_UNICODETEXT, hGlobal); + else + SetClipboardData(CF_TEXT, hGlobal); + + /* Flag that SetClipboardData has been called */ + fSetClipboardData = FALSE; + + /* + * NOTE: Do not try to free pszGlobalData, it is owned by + * Windows after the call to SetClipboardData (). + */ + + winClipboardFlushXEvents_SelectionNotify_Done: + /* Free allocated resources */ + if (ppszTextList) + XFreeStringList(ppszTextList); + if (value) { + XFree(value); + value = NULL; + nitems = 0; + } + free(pszConvertData); + free(pwszUnicodeStr); + if (hGlobal && pszGlobalData) + GlobalUnlock(hGlobal); + if (fSetClipboardData) { + SetClipboardData(CF_UNICODETEXT, NULL); + SetClipboardData(CF_TEXT, NULL); + } + return WIN_XEVENTS_NOTIFY_DATA; +} + /* * Process any pending X events */ @@ -193,7 +458,6 @@ winClipboardFlushXEvents(HWND hwnd, Window iWindow, Display * pDisplay, ClipboardConversionData *data, ClipboardAtoms *atoms) { Atom atomClipboard = atoms->atomClipboard; - Atom atomLocalProperty = atoms->atomLocalProperty; Atom atomUTF8String = atoms->atomUTF8String; Atom atomCompoundText = atoms->atomCompoundText; Atom atomTargets = atoms->atomTargets; @@ -203,20 +467,14 @@ winClipboardFlushXEvents(HWND hwnd, XTextProperty xtpText = { 0 }; XEvent event; XSelectionEvent eventSelection; - unsigned long ulReturnBytesLeft; - char *pszReturnData = NULL; char *pszGlobalData = NULL; int iReturn; HGLOBAL hGlobal = NULL; XICCEncodingStyle xiccesStyle; char *pszConvertData = NULL; char *pszTextList[2] = { NULL }; - int iCount; - char **ppszTextList = NULL; - wchar_t *pwszUnicodeStr = NULL; Bool fAbort = FALSE; Bool fCloseClipboard = FALSE; - Bool fSetClipboardData = TRUE; /* Get the next event - will not block because one is ready */ XNextEvent(pDisplay, &event); @@ -432,6 +690,24 @@ winClipboardFlushXEvents(HWND hwnd, free(pszConvertData); pszConvertData = NULL; + /* data will fit into a single X request (INCR not yet supported) */ + { + long unsigned int maxreqsize = XExtendedMaxRequestSize(pDisplay); + if (maxreqsize == 0) + maxreqsize = XMaxRequestSize(pDisplay); + + /* covert to bytes and allow for allow for X_ChangeProperty request */ + maxreqsize = maxreqsize*4 - 24; + + if (xtpText.nitems > maxreqsize) { + ErrorF("winClipboardFlushXEvents - clipboard data size %lu greater than maximum %lu\n", xtpText.nitems, maxreqsize); + + /* Abort */ + fAbort = TRUE; + goto winClipboardFlushXEvents_SelectionRequest_Done; + } + } + /* Copy the clipboard text to the requesting window */ iReturn = XChangeProperty(pDisplay, event.xselectionrequest.requestor, @@ -569,214 +845,19 @@ winClipboardFlushXEvents(HWND hwnd, return winClipboardSelectionNotifyTargets(hwnd, iWindow, pDisplay, data, atoms); } - /* Retrieve the selection data and delete the property */ - iReturn = XGetWindowProperty(pDisplay, - iWindow, - atomLocalProperty, - 0, - INT_MAX, - True, - AnyPropertyType, - &xtpText.encoding, - &xtpText.format, - &xtpText.nitems, - &ulReturnBytesLeft, &xtpText.value); - if (iReturn != Success) { - ErrorF("winClipboardFlushXEvents - SelectionNotify - " - "XGetWindowProperty () failed, aborting: %d\n", iReturn); - goto winClipboardFlushXEvents_SelectionNotify_Done; - } - - { - char *pszAtomName = NULL; - - winDebug("SelectionNotify - returned data %lu left %lu\n", - xtpText.nitems, ulReturnBytesLeft); - pszAtomName = XGetAtomName(pDisplay, xtpText.encoding); - winDebug("Notify atom name %s\n", pszAtomName); - XFree(pszAtomName); - pszAtomName = NULL; - } - - if (data->fUseUnicode) { -#ifdef X_HAVE_UTF8_STRING - /* Convert the text property to a text list */ - iReturn = Xutf8TextPropertyToTextList(pDisplay, - &xtpText, - &ppszTextList, &iCount); -#endif - } - else { - iReturn = XmbTextPropertyToTextList(pDisplay, - &xtpText, - &ppszTextList, &iCount); - } - if (iReturn == Success || iReturn > 0) { - /* Conversion succeeded or some unconvertible characters */ - if (ppszTextList != NULL) { - int i; - int iReturnDataLen = 0; - for (i = 0; i < iCount; i++) { - iReturnDataLen += strlen(ppszTextList[i]); - } - pszReturnData = malloc(iReturnDataLen + 1); - pszReturnData[0] = '\0'; - for (i = 0; i < iCount; i++) { - strcat(pszReturnData, ppszTextList[i]); - } - } - else { - ErrorF("winClipboardFlushXEvents - SelectionNotify - " - "X*TextPropertyToTextList list_return is NULL.\n"); - pszReturnData = malloc(1); - pszReturnData[0] = '\0'; - } - } - else { - ErrorF("winClipboardFlushXEvents - SelectionNotify - " - "X*TextPropertyToTextList returned: "); - switch (iReturn) { - case XNoMemory: - ErrorF("XNoMemory\n"); - break; - case XLocaleNotSupported: - ErrorF("XLocaleNotSupported\n"); - break; - case XConverterNotFound: - ErrorF("XConverterNotFound\n"); - break; - default: - ErrorF("%d\n", iReturn); - break; - } - pszReturnData = malloc(1); - pszReturnData[0] = '\0'; - } - - /* Free the data returned from XGetWindowProperty */ - if (ppszTextList) - XFreeStringList(ppszTextList); - ppszTextList = NULL; - XFree(xtpText.value); - xtpText.value = NULL; - xtpText.nitems = 0; - - /* Convert the X clipboard string to DOS format */ - winClipboardUNIXtoDOS(&pszReturnData, strlen(pszReturnData)); - - if (data->fUseUnicode) { - /* Find out how much space needed to convert MBCS to Unicode */ - int iUnicodeLen = MultiByteToWideChar(CP_UTF8, - 0, - pszReturnData, -1, NULL, 0); - - /* NOTE: iUnicodeLen includes space for null terminator */ - pwszUnicodeStr = malloc(sizeof(wchar_t) * iUnicodeLen); - if (!pwszUnicodeStr) { - ErrorF("winClipboardFlushXEvents - SelectionNotify " - "malloc failed for pwszUnicodeStr, aborting.\n"); - - /* Abort */ - fAbort = TRUE; - goto winClipboardFlushXEvents_SelectionNotify_Done; - } - - /* Do the actual conversion */ - MultiByteToWideChar(CP_UTF8, - 0, - pszReturnData, - -1, pwszUnicodeStr, iUnicodeLen); - - /* Allocate global memory for the X clipboard data */ - hGlobal = GlobalAlloc(GMEM_MOVEABLE, - sizeof(wchar_t) * iUnicodeLen); - } - else { - int iConvertDataLen = 0; - pszConvertData = strdup(pszReturnData); - iConvertDataLen = strlen(pszConvertData) + 1; - - /* Allocate global memory for the X clipboard data */ - hGlobal = GlobalAlloc(GMEM_MOVEABLE, iConvertDataLen); - } - - free(pszReturnData); - - /* Check that global memory was allocated */ - if (!hGlobal) { - ErrorF("winClipboardFlushXEvents - SelectionNotify " - "GlobalAlloc failed, aborting: %08x\n", (unsigned int)GetLastError()); - - /* Abort */ - fAbort = TRUE; - goto winClipboardFlushXEvents_SelectionNotify_Done; - } - - /* Obtain a pointer to the global memory */ - pszGlobalData = GlobalLock(hGlobal); - if (pszGlobalData == NULL) { - ErrorF("winClipboardFlushXEvents - Could not lock global " - "memory for clipboard transfer\n"); - - /* Abort */ - fAbort = TRUE; - goto winClipboardFlushXEvents_SelectionNotify_Done; - } - - /* Copy the returned string into the global memory */ - if (data->fUseUnicode) { - wcscpy((wchar_t *)pszGlobalData, pwszUnicodeStr); - free(pwszUnicodeStr); - pwszUnicodeStr = NULL; - } - else { - strcpy(pszGlobalData, pszConvertData); - free(pszConvertData); - pszConvertData = NULL; - } - - /* Release the pointer to the global memory */ - GlobalUnlock(hGlobal); - pszGlobalData = NULL; - - /* Push the selection data to the Windows clipboard */ - if (data->fUseUnicode) - SetClipboardData(CF_UNICODETEXT, hGlobal); - else - SetClipboardData(CF_TEXT, hGlobal); - - /* Flag that SetClipboardData has been called */ - fSetClipboardData = FALSE; - - /* - * NOTE: Do not try to free pszGlobalData, it is owned by - * Windows after the call to SetClipboardData (). - */ - - winClipboardFlushXEvents_SelectionNotify_Done: - /* Free allocated resources */ - if (ppszTextList) - XFreeStringList(ppszTextList); - if (xtpText.value) { - XFree(xtpText.value); - xtpText.value = NULL; - xtpText.nitems = 0; - } - free(pszConvertData); - free(pwszUnicodeStr); - if (hGlobal && pszGlobalData) - GlobalUnlock(hGlobal); - if (fSetClipboardData) { - SetClipboardData(CF_UNICODETEXT, NULL); - SetClipboardData(CF_TEXT, NULL); - } - return WIN_XEVENTS_NOTIFY_DATA; + return winClipboardSelectionNotifyData(hwnd, iWindow, pDisplay, data, atoms); case SelectionClear: winDebug("SelectionClear - doing nothing\n"); break; case PropertyNotify: + /* If INCR is in progress, collect the data */ + if (data->incr && + (event.xproperty.atom == atoms->atomLocalProperty) && + (event.xproperty.state == PropertyNewValue)) + return winClipboardSelectionNotifyData(hwnd, iWindow, pDisplay, data, atoms); + break; case MappingNotify: diff --git a/hw/xwin/winclipboard/xwinclip.man b/hw/xwin/winclipboard/xwinclip.man index 73dfc8a94..f9e0d3bfb 100644 --- a/hw/xwin/winclipboard/xwinclip.man +++ b/hw/xwin/winclipboard/xwinclip.man @@ -39,8 +39,8 @@ XWin(1) .SH BUGS Only text clipboard contents are supported. -The INCR (Incrememntal transfer) clipboard protocol for clipboard contents larger than the maximum size of an -X request is not supported. +The INCR (Incremental transfer) clipboard protocol for clipboard contents larger than the maximum size of an X +request (approximately 256K) is only supported for X -> Windows clipboard transfers. Some X clients, notably ones written in Tcl/Tk, do not re-assert ownership of the PRIMARY selection or update it's timestamp when it's contents change, which currently prevents \fIxwinclip\fP from correctly noticing that @@ -49,7 +49,8 @@ the PRIMARY selection's contents have changed. Windows clipboard rendering is synchronous in the WM_RENDER*FORMAT message (that is, we must have placed the contents onto the clipboard by the time we return from processing this message), but we must wait for the X client which owns the selection to convert the selection to our requested format. This is currently achieved -using a fixed timeout of one second. +using a fixed timeout. After requesting conversion of the selection, if no events are received from the X +client which owns the selection for one second, the conversion is assumed to have failed. The XWin(1) server should indicate somehow (by placing an atom on the root window?) that it is running with it's internal clipboard integration enabled, and xwinclip should notice this and exit with an appropriate error. diff --git a/hw/xwin/winconfig.c b/hw/xwin/winconfig.c index 31894d2fb..488171b8a 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 */ 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 daa6daac9..a69c9c643 100644 --- a/hw/xwin/wincreatewnd.c +++ b/hw/xwin/wincreatewnd.c @@ -72,18 +72,12 @@ winCreateBoundingWindowFullScreen(ScreenPtr pScreen) wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = g_hInstance; - wc.hIcon = - (HICON) LoadImage(g_hInstance, MAKEINTRESOURCE(IDI_XWIN), IMAGE_ICON, - GetSystemMetrics(SM_CXICON), - GetSystemMetrics(SM_CYICON), 0); + wc.hIcon = pScreenInfo->hIcon; wc.hCursor = 0; wc.hbrBackground = 0; wc.lpszMenuName = NULL; wc.lpszClassName = WINDOW_CLASS; - wc.hIconSm = - (HICON) LoadImage(g_hInstance, MAKEINTRESOURCE(IDI_XWIN), IMAGE_ICON, - GetSystemMetrics(SM_CXSMICON), - GetSystemMetrics(SM_CYSMICON), LR_DEFAULTSIZE); + wc.hIconSm = pScreenInfo->hIconSm; RegisterClassEx(&wc); /* Set display and screen-specific tooltip text */ @@ -152,9 +146,6 @@ winCreateBoundingWindowWindowed(ScreenPtr pScreen) /* Decorated or undecorated window */ if (pScreenInfo->fDecoration -#ifdef XWIN_MULTIWINDOWEXTWM - && !pScreenInfo->fMWExtWM -#endif && !pScreenInfo->fRootless && !pScreenInfo->fMultiWindow ) { @@ -182,18 +173,12 @@ winCreateBoundingWindowWindowed(ScreenPtr pScreen) wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = g_hInstance; - wc.hIcon = - (HICON) LoadImage(g_hInstance, MAKEINTRESOURCE(IDI_XWIN), IMAGE_ICON, - GetSystemMetrics(SM_CXICON), - GetSystemMetrics(SM_CYICON), 0); + wc.hIcon = pScreenInfo->hIcon; wc.hCursor = 0; wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); wc.lpszMenuName = NULL; wc.lpszClassName = WINDOW_CLASS; - wc.hIconSm = - (HICON) LoadImage(g_hInstance, MAKEINTRESOURCE(IDI_XWIN), IMAGE_ICON, - GetSystemMetrics(SM_CXSMICON), - GetSystemMetrics(SM_CYSMICON), LR_DEFAULTSIZE); + wc.hIconSm = pScreenInfo->hIconSm; RegisterClassEx(&wc); /* Get size of work area */ @@ -214,9 +199,6 @@ winCreateBoundingWindowWindowed(ScreenPtr pScreen) /* Clean up the scrollbars flag, if necessary */ if ((!pScreenInfo->fDecoration -#ifdef XWIN_MULTIWINDOWEXTWM - || pScreenInfo->fMWExtWM -#endif || pScreenInfo->fRootless || pScreenInfo->fMultiWindow ) @@ -235,9 +217,6 @@ winCreateBoundingWindowWindowed(ScreenPtr pScreen) /* Adjust the window width and height for borders and title bar */ if (pScreenInfo->fDecoration -#ifdef XWIN_MULTIWINDOWEXTWM - && !pScreenInfo->fMWExtWM -#endif && !pScreenInfo->fRootless && !pScreenInfo->fMultiWindow ) { @@ -284,9 +263,6 @@ winCreateBoundingWindowWindowed(ScreenPtr pScreen) /* Make sure window is no bigger than work area */ if (TRUE -#ifdef XWIN_MULTIWINDOWEXTWM - && !pScreenInfo->fMWExtWM -#endif && !pScreenInfo->fMultiWindow ) { /* Trim window width to fit work area */ @@ -419,9 +395,6 @@ winCreateBoundingWindowWindowed(ScreenPtr pScreen) /* Show the window */ if (FALSE -#ifdef XWIN_MULTIWINDOWEXTWM - || pScreenInfo->fMWExtWM -#endif || pScreenInfo->fMultiWindow ) { pScreenPriv->fRootWindowShown = FALSE; @@ -436,9 +409,6 @@ winCreateBoundingWindowWindowed(ScreenPtr pScreen) /* Attempt to bring our window to the top of the display */ if (TRUE -#ifdef XWIN_MULTIWINDOWEXTWM - && !pScreenInfo->fMWExtWM -#endif && !pScreenInfo->fRootless && !pScreenInfo->fMultiWindow ) { diff --git a/hw/xwin/wincursor.c b/hw/xwin/wincursor.c index 2afcf9fb5..6ef95047e 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 @@ -126,296 +126,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 2336442c0..29602a594 100644 --- a/hw/xwin/winengine.c +++ b/hw/xwin/winengine.c @@ -54,6 +54,8 @@ static HMODULE g_hmodDirectDraw = NULL; void winDetectSupportedEngines(void) { + ErrorF("winDetectSupportedEngines - RemoteSession: %s\n", GetSystemMetrics(SM_REMOTESESSION) ? "yes" : "no"); + /* Initialize the engine support flags */ g_dwEnginesSupported = WIN_SERVER_SHADOW_GDI; @@ -147,9 +149,6 @@ winSetEngine(ScreenPtr pScreen) /* ShadowGDI is the only engine that supports Multi Window Mode */ if (FALSE -#ifdef XWIN_MULTIWINDOWEXTWM - || pScreenInfo->fMWExtWM -#endif || pScreenInfo->fMultiWindow ) { winErrorFVerb(2, diff --git a/hw/xwin/winerror.c b/hw/xwin/winerror.c index 784772f5f..1191d27b8 100644 --- a/hw/xwin/winerror.c +++ b/hw/xwin/winerror.c @@ -65,14 +65,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, ".old"); - } LogClose(EXIT_ERR_ABORT); /* Format the error message */ diff --git a/hw/xwin/winglobals.c b/hw/xwin/winglobals.c index d1a0d4587..b0086f871 100644 --- a/hw/xwin/winglobals.c +++ b/hw/xwin/winglobals.c @@ -59,23 +59,24 @@ HWND g_hDlgAbout = NULL; const char *g_pszQueryHost = NULL; Bool g_fXdmcpEnabled = FALSE; Bool g_fAuthEnabled = FALSE; +Bool g_fCompositeAlpha = FALSE; HICON g_hIconX = NULL; HICON g_hSmallIconX = NULL; #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; Bool g_fKeyboardHookLL = FALSE; Bool g_fNoHelpMessageBox = FALSE; Bool g_fSoftwareCursor = FALSE; +Bool g_fSilentDupError = FALSE; Bool g_fNativeGl = TRUE; Bool g_fHostInTitle = TRUE; pthread_mutex_t g_pmTerminating = PTHREAD_MUTEX_INITIALIZER; diff --git a/hw/xwin/winglobals.h b/hw/xwin/winglobals.h index 250085fbc..fee507683 100644 --- a/hw/xwin/winglobals.h +++ b/hw/xwin/winglobals.h @@ -40,18 +40,17 @@ 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; +extern Bool g_fCompositeAlpha; extern Bool g_fNoHelpMessageBox; +extern Bool g_fSilentDupError; extern Bool g_fNativeGl; extern Bool g_fHostInTitle; @@ -82,10 +81,6 @@ extern DWORD g_dwCurrentThreadID; extern Bool g_fKeyboardHookLL; extern Bool g_fButton[3]; -#ifdef XWIN_MULTIWINDOWEXTWM -extern Bool g_fNoConfigureWindow; -#endif - extern pthread_mutex_t g_pmTerminating; #endif /* WINGLOBALS_H */ diff --git a/hw/xwin/winkeybd.c b/hw/xwin/winkeybd.c index 00586c25b..3748dc027 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", (int)wParam, (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; -} - /* 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); } /* - * 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); - - winDebug("winSendKeyEvent: dwKey: %u, fDown: %u\n", (unsigned int)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 c7905e3c2..0b02fa446 100644 --- a/hw/xwin/winlayouts.h +++ b/hw/xwin/winlayouts.h @@ -82,6 +82,7 @@ WinKBLayoutRec winKBLayouts[] = { {0x00000416, -1, "pc105", "br", NULL, NULL, "Portuguese (Brazil,ABNT)"}, {0x00010416, -1, "abnt2", "br", NULL, NULL, "Portuguese (Brazil,ABNT2)"}, {0x00000816, -1, "pc105", "pt", NULL, NULL, "Portuguese (Portugal)"}, + {0x00000419, -1, "pc105", "ru", NULL, NULL, "Russian"}, {0x0000041a, -1, "pc105", "hr", NULL, NULL, "Croatian"}, {0x0000041d, -1, "pc105", "se", NULL, NULL, "Swedish (Sweden)"}, {0x0000041f, -1, "pc105", "tr", NULL, NULL, "Turkish (Q)"}, diff --git a/hw/xwin/winmonitors.c b/hw/xwin/winmonitors.c index 955fb9214..5ff565308 100644 --- a/hw/xwin/winmonitors.c +++ b/hw/xwin/winmonitors.c @@ -39,7 +39,7 @@ from The Open Group. */ static - wBOOL CALLBACK +WINBOOL CALLBACK getMonitorInfo(HMONITOR hMonitor, HDC hdc, LPRECT rect, LPARAM _data) { struct GetMonitorInfoData *data = (struct GetMonitorInfoData *) _data; @@ -70,5 +70,5 @@ QueryMonitor(int i, struct GetMonitorInfoData *data) /* query information */ EnumDisplayMonitors(NULL, NULL, getMonitorInfo, (LPARAM) data); - return TRUE; + return data->bMonitorSpecifiedExists; } diff --git a/hw/xwin/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 2ee48ce5a..1d3a387d8 100644 --- a/hw/xwin/winmsg.c +++ b/hw/xwin/winmsg.c @@ -72,6 +72,16 @@ winErrorFVerb(int verb, const char *format, ...) } void +winError(const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + LogVMessageVerb(X_NONE, -1, format, ap); + va_end(ap); +} + +void winDebug(const char *format, ...) { va_list ap; diff --git a/hw/xwin/winmsg.h b/hw/xwin/winmsg.h index 02f672f08..25d887510 100644 --- a/hw/xwin/winmsg.h +++ b/hw/xwin/winmsg.h @@ -60,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/winmultiwindowicons.c b/hw/xwin/winmultiwindowicons.c index c43c29887..5124b88ff 100644 --- a/hw/xwin/winmultiwindowicons.c +++ b/hw/xwin/winmultiwindowicons.c @@ -32,24 +32,14 @@ #include <xwin-config.h> #endif -#ifndef WINVER -#define WINVER 0x0500 -#endif - -#include <limits.h> -#include <stdbool.h> - #include <X11/Xwindows.h> #include <X11/Xlib.h> -#include <xcb/xcb.h> -#include <xcb/xcb_icccm.h> -#include <xcb/xcb_image.h> #include "winresource.h" #include "winprefs.h" -#include "winmsg.h" #include "winmultiwindowicons.h" #include "winglobals.h" +#include "wmutil/icon_convert.h" /* * global variables @@ -57,527 +47,6 @@ extern HINSTANCE g_hInstance; /* - * 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) { - 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); - - 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); -} - -/* - * Attempt to create a custom icon from the WM_HINTS bitmaps - */ - -static -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 0x%x\n", - (unsigned int)id, - (unsigned int)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", - (unsigned int)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; -} - -/* * Change the Windows window icon */ @@ -597,23 +66,33 @@ winUpdateIcon(HWND hWnd, xcb_connection_t *conn, Window id, HICON hIconNew) /* If we still need an icon, try and get the icon from WM_HINTS */ hIcon = winXIconToHICON(conn, id, GetSystemMetrics(SM_CXICON)); hIconSmall = winXIconToHICON(conn, 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/winmultiwindowwindow.c b/hw/xwin/winmultiwindowwindow.c index 4ec5634af..c2d144447 100644 --- a/hw/xwin/winmultiwindowwindow.c +++ b/hw/xwin/winmultiwindowwindow.c @@ -57,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) { @@ -85,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); + } } /* @@ -157,32 +202,16 @@ winDestroyWindowMultiWindow(WindowPtr pWin) /* * PositionWindow - See Porting Layer Definition - p. 37 - * - * This function adjusts the position and size of Windows window - * with respect to the underlying X window. This is the inverse - * of winAdjustXWindow, which adjusts X window to Windows window. */ Bool winPositionWindowMultiWindow(WindowPtr pWin, int x, int y) { Bool fResult = TRUE; - int iX, iY, iWidth, iHeight; ScreenPtr pScreen = pWin->drawable.pScreen; - winWindowPriv(pWin); winScreenPriv(pScreen); - HWND hWnd = pWinPriv->hWnd; - RECT rcNew; - RECT rcOld; - -#if CYGMULTIWINDOW_DEBUG - RECT rcClient; - RECT *lpRc; -#endif - DWORD dwExStyle; - DWORD dwStyle; #if CYGMULTIWINDOW_DEBUG winTrace("winPositionWindowMultiWindow - pWin: %p\n", pWin); @@ -204,6 +233,59 @@ winPositionWindowMultiWindow(WindowPtr pWin, int x, int y) return fResult; } + /* + We can't call MoveWindow() here, because that sends messages and pumps the + message queue, which could re-entrantly call ConfigureWindow(), which + would be bad..., so instead just send a message to cause MoveWindow() to + be called. + */ + PostMessage(hWnd, WM_ASYNCMOVE, 0, 0); + + return fResult; +} + +/* + * This function adjusts the position and size of Windows window + * with respect to the underlying X window. This is the inverse + * of winAdjustXWindow, which adjusts X window to Windows window. + */ +void +winAdjustWindowsWindow(WindowPtr pWin, HWND hWnd) +{ + int iX, iY, iWidth, iHeight; + RECT rcNew; + RECT rcOld; + +#if CYGMULTIWINDOW_DEBUG + RECT rcClient; + RECT *lpRc; +#endif + DWORD dwExStyle; + DWORD dwStyle; + + 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; + } + /* Get the Windows window style and extended style */ dwExStyle = GetWindowLongPtr(hWnd, GWL_EXSTYLE); dwStyle = GetWindowLongPtr(hWnd, GWL_STYLE); @@ -268,11 +350,9 @@ winPositionWindowMultiWindow(WindowPtr pWin, int x, int y) } else { #if CYGMULTIWINDOW_DEBUG - ErrorF("winPositionWindowMultiWindow - Not need to move\n"); + ErrorF("winPositionWindowMultiWindow - No need to move\n"); #endif } - - return fResult; } /* @@ -473,12 +553,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; @@ -519,8 +595,8 @@ winCreateWindowsWindow(WindowPtr pWin) } } - 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) { @@ -534,17 +610,33 @@ winCreateWindowsWindow(WindowPtr pWin) } } 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; @@ -582,11 +674,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,18 +692,113 @@ winCreateWindowsWindow(WindowPtr pWin) /* Adjust the X window to match the window placement we actually got... */ winAdjustXWindow(pWin, hWnd); - /* Make sure it gets the proper system menu for a WS_POPUP, too */ - GetSystemMenu(hWnd, TRUE); - - /* Cause any .XWinrc menus to be added in main WNDPROC */ - PostMessage(hWnd, WM_INIT_SYS_MENU, 0, 0); - SetProp(hWnd, WIN_WID_PROP, (HANDLE) (INT_PTR) winGetWindowID(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 + + 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, + (unsigned int)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, (unsigned int)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, + (unsigned int)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, + (unsigned int)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; /* @@ -624,6 +814,7 @@ winDestroyWindowsWindow(WindowPtr pWin) BOOL oldstate = winInDestroyWindowsWindow; HICON hIcon; HICON hIconSm; + HWND hWnd; winDebug("winDestroyWindowsWindow - pWin:%p XID:0x%x \n", pWin, (unsigned int)pWin->drawable.id); @@ -638,21 +829,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)) { @@ -674,29 +864,43 @@ 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); - } - - /* Display the window without activating it */ - if (pWin->drawable.class != InputOnly) - ShowWindow(pWinPriv->hWnd, SW_SHOWNOACTIVATE); + /* Ignore the root window */ + if (pWin->parent == NULL) + return; - /* Send first paint message */ - UpdateWindow(pWinPriv->hWnd); + /* 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); + } + } + /* 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); + } } - 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); } @@ -883,6 +1087,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"); @@ -960,3 +1172,257 @@ winAdjustXWindow(WindowPtr pWin, HWND hwnd) #undef WIDTH #undef HEIGHT } + +/* + Helper function + */ +static HBITMAP winCreateDIB(ScreenPtr pScreen, int width, int height, int bpp, void **ppvBits, BITMAPINFOHEADER **ppbmih) +{ + winScreenPriv(pScreen); + BITMAPV4HEADER *pbmih = NULL; + HBITMAP hBitmap = NULL; + + /* Allocate bitmap info header */ + pbmih = malloc(sizeof(BITMAPV4HEADER) + 256 * sizeof(RGBQUAD)); + if (pbmih == NULL) { + ErrorF("winCreateDIB: malloc() failed\n"); + return NULL; + } + memset(pbmih, 0, sizeof(BITMAPV4HEADER) + 256 * sizeof(RGBQUAD)); + + /* Describe bitmap to be created */ + pbmih->bV4Size = sizeof(BITMAPV4HEADER); + pbmih->bV4Width = width; + pbmih->bV4Height = -height; /* top-down bitmap */ + pbmih->bV4Planes = 1; + pbmih->bV4BitCount = bpp; + if (bpp == 1) { + RGBQUAD *bmiColors = (RGBQUAD *)((char *)pbmih + sizeof(BITMAPV4HEADER)); + pbmih->bV4V4Compression = BI_RGB; + bmiColors[1].rgbBlue = 255; + bmiColors[1].rgbGreen = 255; + bmiColors[1].rgbRed = 255; + } + else if (bpp == 8) { + pbmih->bV4V4Compression = BI_RGB; + pbmih->bV4ClrUsed = 0; + } + else if (bpp == 16) { + pbmih->bV4V4Compression = BI_RGB; + pbmih->bV4ClrUsed = 0; + } + else if (bpp == 32) { + pbmih->bV4V4Compression = BI_BITFIELDS; + pbmih->bV4RedMask = pScreenPriv->dwRedMask; + pbmih->bV4GreenMask = pScreenPriv->dwGreenMask; + pbmih->bV4BlueMask = pScreenPriv->dwBlueMask; + pbmih->bV4AlphaMask = 0; + } + else { + ErrorF("winCreateDIB: %d bpp unhandled\n", bpp); + } + + /* Create a DIB with a bit pointer */ + hBitmap = CreateDIBSection(NULL, + (BITMAPINFO *) pbmih, + DIB_RGB_COLORS, ppvBits, NULL, 0); + if (hBitmap == NULL) { + ErrorF("winCreateDIB: CreateDIBSection() failed\n"); + return NULL; + } + + /* Store the address of the BMIH in the ppbmih parameter */ + *ppbmih = (BITMAPINFOHEADER *)pbmih; + + winDebug("winCreateDIB: HBITMAP %p pBMIH %p pBits %p\n", hBitmap, pbmih, *ppvBits); + + return hBitmap; +} + + +/* + * CreatePixmap - See Porting Layer Definition + */ +PixmapPtr +winCreatePixmapMultiwindow(ScreenPtr pScreen, int width, int height, int depth, + unsigned usage_hint) +{ + winPrivPixmapPtr pPixmapPriv = NULL; + PixmapPtr pPixmap = NULL; + int bpp, paddedwidth; + + /* allocate Pixmap header and privates */ + pPixmap = AllocatePixmap(pScreen, 0); + if (!pPixmap) + return NullPixmap; + + bpp = BitsPerPixel(depth); + /* + DIBs have 4-byte aligned rows + + paddedwidth is the width in bytes, padded to align + + i.e. round up the number of bits used by a row so it is a multiple of 32, + then convert to bytes + */ + paddedwidth = (((bpp * width) + 31) & ~31)/8; + + /* setup Pixmap header */ + pPixmap->drawable.type = DRAWABLE_PIXMAP; + pPixmap->drawable.class = 0; + pPixmap->drawable.pScreen = pScreen; + pPixmap->drawable.depth = depth; + pPixmap->drawable.bitsPerPixel = bpp; + pPixmap->drawable.id = 0; + pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + pPixmap->drawable.x = 0; + pPixmap->drawable.y = 0; + pPixmap->drawable.width = width; + pPixmap->drawable.height = height; + pPixmap->devKind = paddedwidth; + pPixmap->refcnt = 1; + pPixmap->devPrivate.ptr = NULL; // later set to pbBits + pPixmap->master_pixmap = NULL; +#ifdef COMPOSITE + pPixmap->screen_x = 0; + pPixmap->screen_y = 0; +#endif + pPixmap->usage_hint = usage_hint; + + /* Check for zero width or height pixmaps */ + if (width == 0 || height == 0) { + /* DIBs with a dimension of 0 aren't permitted, so don't try to allocate + a DIB, just set fields and return */ + return pPixmap; + } + + /* Initialize pixmap privates */ + pPixmapPriv = winGetPixmapPriv(pPixmap); + pPixmapPriv->hBitmap = NULL; + pPixmapPriv->pbBits = NULL; + pPixmapPriv->pbmih = NULL; + + /* Create a DIB for the pixmap */ + pPixmapPriv->hBitmap = winCreateDIB(pScreen, width, height, bpp, &pPixmapPriv->pbBits, &pPixmapPriv->pbmih); + + winDebug("winCreatePixmap: pPixmap %p HBITMAP %p pBMIH %p pBits %p\n", pPixmap, pPixmapPriv->hBitmap, pPixmapPriv->pbmih, pPixmapPriv->pbBits); + /* XXX: so why do we need this in privates ??? */ + pPixmap->devPrivate.ptr = pPixmapPriv->pbBits; + + return pPixmap; +} + +/* + * DestroyPixmap - See Porting Layer Definition + */ +Bool +winDestroyPixmapMultiwindow(PixmapPtr pPixmap) +{ + winPrivPixmapPtr pPixmapPriv = NULL; + + /* Bail early if there is not a pixmap to destroy */ + if (pPixmap == NULL) { + return TRUE; + } + + /* Decrement reference count, return if nonzero */ + --pPixmap->refcnt; + if (pPixmap->refcnt != 0) + return TRUE; + + winDebug("winDestroyPixmap: pPixmap %p\n", pPixmap); + + /* Get a handle to the pixmap privates */ + pPixmapPriv = winGetPixmapPriv(pPixmap); + + /* Free GDI bitmap */ + if (pPixmapPriv->hBitmap) + DeleteObject(pPixmapPriv->hBitmap); + + /* Free the bitmap info header memory */ + free(pPixmapPriv->pbmih); + pPixmapPriv->pbmih = NULL; + + /* Free the pixmap memory */ + free(pPixmap); + pPixmap = NULL; + + return TRUE; +} + +/* + * ModifyPixmapHeader - See Porting Layer Definition + */ +Bool +winModifyPixmapHeaderMultiwindow(PixmapPtr pPixmap, + int width, + int height, + int depth, + int bitsPerPixel, int devKind, void *pPixData) +{ + int i; + winPrivPixmapPtr pPixmapPriv = NULL; + Bool fResult; + + /* reinitialize everything */ + pPixmap->drawable.depth = depth; + pPixmap->drawable.bitsPerPixel = bitsPerPixel; + pPixmap->drawable.id = 0; + pPixmap->drawable.x = 0; + pPixmap->drawable.y = 0; + pPixmap->drawable.width = width; + pPixmap->drawable.height = height; + pPixmap->devKind = devKind; + pPixmap->refcnt = 1; + pPixmap->devPrivate.ptr = pPixData; + pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + + /* + This can be used for some out-of-order initialization on the screen + pixmap, which is the only case we can properly support. + */ + + /* Look for which screen this pixmap corresponds to */ + for (i = 0; i < screenInfo.numScreens; i++) { + ScreenPtr pScreen = screenInfo.screens[i]; + winScreenPriv(pScreen); + winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; + + if (pScreenInfo->pfb == pPixData) + { + /* and initialize pixmap privates from screen privates */ + pPixmapPriv = winGetPixmapPriv(pPixmap); + + pPixmapPriv->hBitmap = pScreenPriv->hbmpShadow; + pPixmapPriv->pbBits = pScreenInfo->pfb; + pPixmapPriv->pbmih = pScreenPriv->pbmih; + + /* XXX: need to mark these not to get released in DestroyPixmap */ + + return TRUE; + } + } + + /* Otherwise, since creating a DIBSection from arbitrary memory is not + * possible, fallback to normal. Later we can create a DIBSection with a + * copy of the bits, if needed. */ + { + pPixmapPriv = winGetPixmapPriv(pPixmap); + + pPixmapPriv->hBitmap = 0; + pPixmapPriv->pbBits = 0; + pPixmapPriv->pbmih = 0; + } + + winDebug("winModifyPixmapHeaderMultiwindow: falling back\n"); + + { + ScreenPtr pScreen = pPixmap->drawable.pScreen; + winScreenPriv(pScreen); + WIN_UNWRAP(ModifyPixmapHeader); + fResult = (*pScreen->ModifyPixmapHeader) (pPixmap, width, height, depth, bitsPerPixel, devKind, pPixData); + WIN_WRAP(ModifyPixmapHeader, winModifyPixmapHeaderMultiwindow); + } + + return fResult; +} diff --git a/hw/xwin/winmultiwindowwm.c b/hw/xwin/winmultiwindowwm.c index 32bc722e2..4a28ccb8e 100644 --- a/hw/xwin/winmultiwindowwm.c +++ b/hw/xwin/winmultiwindowwm.c @@ -30,10 +30,26 @@ * Colin Harrison */ +#ifndef WINVER +#define WINVER 0x0500 +#endif + /* X headers */ #ifdef HAVE_XWIN_CONFIG_H #include <xwin-config.h> #endif + +#define ARRAY_SIZE(a) (sizeof((a)) / sizeof((a)[0])) + +/* + * 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> @@ -49,6 +65,7 @@ #include <xcb/xcb_icccm.h> #include <xcb/xcb_ewmh.h> #include <xcb/xcb_aux.h> +#include <xcb/composite.h> #include <X11/Xwindows.h> @@ -57,8 +74,6 @@ #include "winwindow.h" #include "winprefs.h" #include "window.h" -#include "pixmapstr.h" -#include "windowstr.h" #include "winglobals.h" #include "windisplay.h" #include "winmultiwindowicons.h" @@ -75,6 +90,7 @@ extern void winDebug(const char *format, ...); extern void winReshapeMultiWindow(WindowPtr pWin); extern void winUpdateRgnMultiWindow(WindowPtr pWin); extern xcb_auth_info_t *winGetXcbAuthInfo(void); +extern void winUpdateWindowPosition(HWND hWnd, HWND * zstyle); #ifndef CYGDEBUG #define CYGDEBUG NO @@ -90,6 +106,9 @@ extern xcb_auth_info_t *winGetXcbAuthInfo(void); #define WIN_MSG_QUEUE_FNAME "/dev/windows" #endif +#define HINT_MAX (1L<<0) +#define HINT_MIN (1L<<1) + /* * Local structures */ @@ -115,7 +134,12 @@ typedef struct _WMInfo { xcb_atom_t atmPrivMap; xcb_atom_t atmUtf8String; xcb_atom_t atmNetWmName; + xcb_atom_t atmCurrentDesktop; + xcb_atom_t atmNumberDesktops; + xcb_atom_t atmDesktopNames; + xcb_atom_t atmWmState; xcb_ewmh_connection_t ewmh; + Bool fCompositeWM; } WMInfoRec, *WMInfoPtr; typedef struct _WMProcArgRec { @@ -158,6 +182,9 @@ static void *winMultiWindowWMProc(void *pArg); static void *winMultiWindowXMsgProc(void *pArg); static void +winMultiWindowThreadExit(void *arg); + +static void winInitMultiWindowWM(WMInfoPtr pWMInfo, WMProcArgPtr pProcArg); #if 0 @@ -169,10 +196,10 @@ static Bool CheckAnotherWindowManager(xcb_connection_t *conn, DWORD dwScreen); static void - winApplyHints(WMInfoPtr pWMInfo, xcb_window_t iWindow, HWND hWnd, HWND * zstyle); + winApplyHints(WMInfoPtr pWMInfo, xcb_window_t iWindow, HWND hWnd, HWND * zstyle, unsigned long *maxmin); -void - winUpdateWindowPosition(HWND hWnd, HWND * zstyle); +static void + winApplyUrgency(WMInfoPtr pWMInfo, xcb_window_t iWindow, HWND hWnd); /* * Local globals @@ -220,15 +247,18 @@ MessageName(winWMMessagePtr msg) case WM_WM_CHANGE_STATE: return "WM_WM_CHANGE_STATE"; break; - case WM_WM_MAP2: - return "WM_WM_MAP2"; + case WM_WM_MAP_UNMANAGED: + return "WM_WM_MAP_UNMANAGED"; break; - case WM_WM_MAP3: - return "WM_WM_MAP3"; + case WM_WM_MAP_MANAGED: + return "WM_WM_MAP_MANAGED"; break; case WM_WM_HINTS_EVENT: return "WM_WM_HINTS_EVENT"; break; + case WM_WM_CREATE: + return "WM_WM_CREATE"; + break; default: return "Unknown Message"; break; @@ -540,8 +570,10 @@ getHwnd(WMInfoPtr pWMInfo, xcb_window_t iWindow) } /* Some sanity checks */ - if (!hWnd) + if (!hWnd) { + winDebug("getHwnd: no HWND\n"); return NULL; + } if (!IsWindow(hWnd)) return NULL; @@ -679,7 +711,7 @@ UpdateIcon(WMInfoPtr pWMInfo, xcb_window_t iWindow) */ static void -UpdateStyle(WMInfoPtr pWMInfo, xcb_window_t iWindow) +UpdateStyle(WMInfoPtr pWMInfo, xcb_window_t iWindow, unsigned long *maxmin) { HWND hWnd; HWND zstyle = HWND_NOTOPMOST; @@ -689,8 +721,12 @@ UpdateStyle(WMInfoPtr pWMInfo, xcb_window_t iWindow) if (!hWnd) return; + /* If window isn't override-redirect */ + if (IsOverrideRedirect(pWMInfo->conn, iWindow)) + return; + /* Determine the Window style, which determines borders and clipping region... */ - winApplyHints(pWMInfo, iWindow, hWnd, &zstyle); + winApplyHints(pWMInfo, iWindow, hWnd, &zstyle, maxmin); winUpdateWindowPosition(hWnd, &zstyle); /* Apply the updated window style, without changing it's show or activation state */ @@ -711,25 +747,155 @@ UpdateStyle(WMInfoPtr pWMInfo, xcb_window_t iWindow) winShowWindowOnTaskbar(hWnd, (GetWindowLongPtr(hWnd, GWL_EXSTYLE) & WS_EX_APPWINDOW) ? TRUE : FALSE); + + /* Check urgency hint */ + winApplyUrgency(pWMInfo, iWindow, hWnd); } /* * Updates the state of a HWND - * (only minimization supported at the moment) */ static void -UpdateState(WMInfoPtr pWMInfo, xcb_window_t iWindow) +UpdateState(WMInfoPtr pWMInfo, xcb_window_t iWindow, int state) { HWND hWnd; + int current_state = -1; - winDebug("UpdateState: iWindow 0x%08x\n", (int)iWindow); + winDebug("UpdateState: iWindow 0x%08x %d\n", (int)iWindow, state); hWnd = getHwnd(pWMInfo, iWindow); - if (!hWnd) - return; + 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 XCB_ICCCM_WM_STATE_ICONIC: + ShowWindow(hWnd, SW_SHOWMINNOACTIVE); + break; + +#define XCB_ICCCM_WM_STATE_ZOOM 2 + case XCB_ICCCM_WM_STATE_ZOOM: + // There doesn't seem to be a SW_SHOWMAXNOACTIVE. Hopefully + // always activating a maximized window isn't so bad... + ShowWindow(hWnd, SW_SHOWMAXIMIZED); + break; + + case XCB_ICCCM_WM_STATE_NORMAL: + ShowWindow(hWnd, SW_SHOWNOACTIVATE); + break; + + case XCB_ICCCM_WM_STATE_WITHDRAWN: + 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 == XCB_ICCCM_WM_STATE_ZOOM) + icccm_state = XCB_ICCCM_WM_STATE_NORMAL; + + if (icccm_current_state == XCB_ICCCM_WM_STATE_ZOOM) + icccm_current_state = XCB_ICCCM_WM_STATE_NORMAL; + + // 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; + + xcb_change_property(pWMInfo->conn, XCB_PROP_MODE_REPLACE, + iWindow, pWMInfo->atmWmState, + pWMInfo->atmWmState, 32, + sizeof(wmstate)/sizeof(int), + (unsigned char *) &wmstate); + } + } + + // Update _NET_WM_STATE property + if (state == XCB_ICCCM_WM_STATE_WITHDRAWN) { + xcb_delete_property(pWMInfo->conn, iWindow, pWMInfo->ewmh._NET_WM_STATE); + } + else { + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + + cookie = xcb_get_property(pWMInfo->conn, FALSE, iWindow, + pWMInfo->ewmh._NET_WM_STATE, + XCB_ATOM_ATOM, + 0, INT_MAX); + reply = xcb_get_property_reply(pWMInfo->conn, cookie, NULL); + if (reply) { + int nitems = xcb_get_property_value_length(reply)/sizeof(xcb_atom_t); + xcb_atom_t *pAtom = xcb_get_property_value(reply); + unsigned long i, o = 0; + xcb_atom_t 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->ewmh._NET_WM_STATE_HIDDEN) && + (pAtom[i] != pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_VERT) && + (pAtom[i] != pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_HORZ)) + netwmstate[o++] = pAtom[i]; + } + free(reply); + + // if iconized, add _NET_WM_HIDDEN + if (state == XCB_ICCCM_WM_STATE_ICONIC) { + netwmstate[o++] = pWMInfo->ewmh._NET_WM_STATE_HIDDEN; + } + + // if maximized, add _NET_WM_MAXIMIZED_{VERT,HORZ} + if (state == XCB_ICCCM_WM_STATE_ZOOM) { + netwmstate[o++] = pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_VERT; + netwmstate[o++] = pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_HORZ; + } - ShowWindow(hWnd, SW_MINIMIZE); + // 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) + xcb_change_property(pWMInfo->conn, XCB_PROP_MODE_REPLACE, + iWindow, + pWMInfo->ewmh._NET_WM_STATE, + XCB_ATOM_ATOM, 32, + o, (unsigned char *) &netwmstate); + } + } } #if 0 @@ -783,6 +949,8 @@ winMultiWindowWMProc(void *pArg) WMProcArgPtr pProcArg = (WMProcArgPtr) pArg; WMInfoPtr pWMInfo = pProcArg->pWMInfo; + pthread_cleanup_push(&winMultiWindowThreadExit, NULL); + /* Initialize the Window Manager */ winInitMultiWindowWM(pWMInfo, pProcArg); @@ -804,12 +972,69 @@ winMultiWindowWMProc(void *pArg) } #if CYGMULTIWINDOW_DEBUG - ErrorF("winMultiWindowWMProc - MSG: %s (%d) ID: %d\n", - MessageName(&(pNode->msg)), (int)pNode->msg.msg, (int)pNode->msg.dwID); + ErrorF("winMultiWindowWMProc - MSG: %s (%d) Window: %08x ID: %d\n", + MessageName(&(pNode->msg)), (int)pNode->msg.msg, pNode->msg.iWindow, (int)pNode->msg.dwID); #endif /* Branch on the message type */ switch (pNode->msg.msg) { + case WM_WM_CREATE: + { + unsigned long maxmin = 0; +#if CYGMULTIWINDOW_DEBUG + ErrorF("\tWM_WM_CREATE\n"); +#endif + + /* Put a note as to the HWND associated with this Window */ + xcb_change_property(pWMInfo->conn, XCB_PROP_MODE_REPLACE, + pNode->msg.iWindow, pWMInfo->atmPrivMap, + XCB_ATOM_INTEGER, 32, + sizeof(HWND)/4, &(pNode->msg.hwndWindow)); + + + /* Determine the Window style, which determines borders and clipping region... */ + UpdateStyle(pWMInfo, pNode->msg.iWindow, &maxmin); + + /* Make sure it gets the proper system menu for a WS_POPUP, too */ + GetSystemMenu(pNode->msg.hwndWindow, TRUE); + +#define WM_INIT_SYS_MENU (WM_USER + 1001) + /* Cause any .XWinrc menus to be added in main WNDPROC */ + PostMessage(pNode->msg.hwndWindow, WM_INIT_SYS_MENU, 0, 0); + + /* Display the window without activating it */ + { + xcb_get_window_attributes_cookie_t cookie; + xcb_get_window_attributes_reply_t *reply; + + cookie = xcb_get_window_attributes(pWMInfo->conn, pNode->msg.iWindow); + reply = xcb_get_window_attributes_reply(pWMInfo->conn, cookie, NULL); + + if (reply) { + if (reply->_class != InputOnly) + ShowWindow(pNode->msg.hwndWindow, SW_SHOWNA); + free(reply); + } + } + + /* Send first paint message */ + UpdateWindow(pNode->msg.hwndWindow); + + /* Establish initial state */ + UpdateState(pWMInfo, pNode->msg.iWindow, XCB_ICCCM_WM_STATE_NORMAL); + + /* + It only makes sense to apply minimize/maximize override as the + initial state, otherwise that state can't be changed. + */ + if (maxmin & HINT_MAX) + SendMessage(pNode->msg.hwndWindow, WM_SYSCOMMAND, SC_MAXIMIZE, 0); + else if (maxmin & HINT_MIN) + SendMessage(pNode->msg.hwndWindow, WM_SYSCOMMAND, SC_MINIMIZE, 0); + } + + break; + #if 0 case WM_WM_MOVE: break; @@ -840,26 +1065,16 @@ winMultiWindowWMProc(void *pArg) } break; - case WM_WM_MAP2: - /* Put a note as to the HWND associated with this Window */ - xcb_change_property(pWMInfo->conn, XCB_PROP_MODE_REPLACE, - pNode->msg.iWindow, pWMInfo->atmPrivMap, - XCB_ATOM_INTEGER, 32, - sizeof(HWND)/4, &(pNode->msg.hwndWindow)); - + case WM_WM_MAP_UNMANAGED: break; - case WM_WM_MAP3: - /* Put a note as to the HWND associated with this Window */ - xcb_change_property(pWMInfo->conn, XCB_PROP_MODE_REPLACE, - pNode->msg.iWindow, pWMInfo->atmPrivMap, - XCB_ATOM_INTEGER, 32, - sizeof(HWND)/4, &(pNode->msg.hwndWindow)); + case WM_WM_MAP_MANAGED: + { + unsigned long maxmin = 0; UpdateName(pWMInfo, pNode->msg.iWindow); + UpdateStyle(pWMInfo, pNode->msg.iWindow, &maxmin); UpdateIcon(pWMInfo, pNode->msg.iWindow); - UpdateStyle(pWMInfo, pNode->msg.iWindow); - /* Reshape */ { @@ -870,8 +1085,9 @@ winMultiWindowWMProc(void *pArg) winUpdateRgnMultiWindow(pWin); } } + } - break; + break; case WM_WM_UNMAP: @@ -940,16 +1156,18 @@ winMultiWindowWMProc(void *pArg) case WM_WM_HINTS_EVENT: { + unsigned long maxmin = 0; + /* Don't do anything if this is an override-redirect window */ if (IsOverrideRedirect(pWMInfo->conn, pNode->msg.iWindow)) break; - UpdateStyle(pWMInfo, pNode->msg.iWindow); + UpdateStyle(pWMInfo, pNode->msg.iWindow, &maxmin); } break; case WM_WM_CHANGE_STATE: - UpdateState(pWMInfo, pNode->msg.iWindow); + UpdateState(pWMInfo, pNode->msg.iWindow, pNode->msg.dwID); break; default: @@ -970,10 +1188,10 @@ winMultiWindowWMProc(void *pArg) if (event) { if ((event->response_type & ~0x80) == 0) { xcb_generic_error_t *err = (xcb_generic_error_t *)event; - ErrorF("winMultiWindowWMProc - Error code: %i, ID: 0x%08x, " - "Major opcode: %i, Minor opcode: %i\n", - err->error_code, err->resource_id, - err->major_code, err->minor_code); + winDebug("winMultiWindowWMProc - Error code: %i, ID: 0x%08x, " + "Major opcode: %i, Minor opcode: %i\n", + err->error_code, err->resource_id, + err->major_code, err->minor_code); } } } @@ -983,6 +1201,7 @@ winMultiWindowWMProc(void *pArg) int e = xcb_connection_has_error(pWMInfo->conn); if (e) { ErrorF("winMultiWindowWMProc - Fatal error %d on xcb connection\n", e); + pthread_exit(NULL); break; } } @@ -1000,6 +1219,9 @@ winMultiWindowWMProc(void *pArg) #if CYGMULTIWINDOW_DEBUG ErrorF("-winMultiWindowWMProc ()\n"); #endif + + pthread_cleanup_pop(0); + return NULL; } @@ -1038,6 +1260,10 @@ winMultiWindowXMsgProc(void *pArg) xcb_atom_t atmWindowState, atmMotifWmHints, atmWindowType, atmNormalHints; int iReturn; xcb_auth_info_t *auth_info; + xcb_screen_t *root_screen; + xcb_window_t root_window_id; + + pthread_cleanup_push(&winMultiWindowThreadExit, NULL); winDebug("winMultiWindowXMsgProc - Hello\n"); @@ -1110,11 +1336,11 @@ winMultiWindowXMsgProc(void *pArg) pthread_exit(NULL); } - { - /* Get root window id */ - xcb_screen_t *root_screen = xcb_aux_get_screen(pProcArg->conn, pProcArg->dwScreen); - xcb_window_t root_window_id = root_screen->root; + /* Get root window id */ + root_screen = xcb_aux_get_screen(pProcArg->conn, pProcArg->dwScreen); + root_window_id = root_screen->root; + { /* Set WM_ICON_SIZE property indicating desired icon sizes */ typedef struct { uint32_t min_width, min_height; @@ -1143,14 +1369,39 @@ winMultiWindowXMsgProc(void *pArg) atmNormalHints = intern_atom(pProcArg->conn, "WM_NORMAL_HINTS"); /* - 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 */ - intern_atom(pProcArg->conn, "WM_STATE"); + if (pProcArg->pWMInfo->fCompositeWM) { + const char *extension_name = "Composite"; + xcb_query_extension_cookie_t cookie; + xcb_query_extension_reply_t *reply; + + cookie = xcb_query_extension(pProcArg->conn, strlen(extension_name), extension_name); + reply = xcb_query_extension_reply(pProcArg->conn, cookie, NULL); + + if (reply && (reply->present)) { + xcb_composite_redirect_subwindows(pProcArg->conn, + root_window_id, + XCB_COMPOSITE_REDIRECT_AUTOMATIC); + + /* + We use automatic updating of the root window for two + reasons: + + 1) redirected window contents are mirrored to the root + window so that the root window draws correctly when shown. + + 2) updating the root window causes damage against the + shadow framebuffer, which ultimately causes WM_PAINT to be + sent to the affected window(s) to cause the damage regions + to be redrawn. + */ + + ErrorF("Using Composite redirection\n"); + + free(reply); + } + } /* Loop until we explicitly break out */ while (1) { @@ -1166,6 +1417,7 @@ winMultiWindowXMsgProc(void *pArg) if (!event) { // returns NULL on I/O error int e = xcb_connection_has_error(pProcArg->conn); ErrorF("winMultiWindowXMsgProc - Fatal error %d on xcb connection\n", e); + pthread_exit(NULL); break; } @@ -1177,10 +1429,10 @@ winMultiWindowXMsgProc(void *pArg) /* Branch on event type */ if (type == 0) { xcb_generic_error_t *err = (xcb_generic_error_t *)event; - ErrorF("winMultiWindowXMsgProc - Error code: %i, ID: 0x%08x, " - "Major opcode: %i, Minor opcode: %i\n", - err->error_code, err->resource_id, - err->major_code, err->minor_code); + winDebug("winMultiWindowXMsgProc - Error code: %i, ID: 0x%08x, " + "Major opcode: %i, Minor opcode: %i\n", + err->error_code, err->resource_id, + err->major_code, err->minor_code); } else if (type == XCB_CREATE_NOTIFY) { xcb_create_notify_event_t *notify = (xcb_create_notify_event_t *)event; @@ -1249,6 +1501,16 @@ winMultiWindowXMsgProc(void *pArg) } } } + else if (type == XCB_UNMAP_NOTIFY) { + xcb_unmap_notify_event_t *notify = (xcb_unmap_notify_event_t *)event; + + memset(&msg, 0, sizeof(msg)); + msg.msg = WM_WM_CHANGE_STATE; + msg.iWindow = notify->window; + msg.dwID = XCB_ICCCM_WM_STATE_WITHDRAWN; + + winSendMessageToWM(pProcArg->pWMInfo, &msg); + } else if (type == XCB_CONFIGURE_NOTIFY) { if (!send_event) { /* @@ -1275,6 +1537,15 @@ winMultiWindowXMsgProc(void *pArg) else if (type == XCB_PROPERTY_NOTIFY) { xcb_property_notify_event_t *notify = (xcb_property_notify_event_t *)event; + xcb_get_atom_name_cookie_t cookie = xcb_get_atom_name(pProcArg->conn, notify->atom); + xcb_get_atom_name_reply_t *reply = xcb_get_atom_name_reply(pProcArg->conn, cookie, NULL); + if (reply) { + winDebug("winMultiWindowXMsgProc: PropertyNotify %.*s\n", + xcb_get_atom_name_name_length(reply), + xcb_get_atom_name_name(reply)); + free(reply); + } + if ((notify->atom == atmWmName) || (notify->atom == atmNetWmName)) { memset(&msg, 0, sizeof(msg)); @@ -1317,18 +1588,60 @@ winMultiWindowXMsgProc(void *pArg) } else if (type == XCB_CLIENT_MESSAGE) { xcb_client_message_event_t *client_msg = (xcb_client_message_event_t *)event; + winDebug("winMultiWindowXMsgProc: ClientMessage: type %d window 0x%08x data[0] %d\n", client_msg->type, client_msg->window, client_msg->data.data32[0]); if (client_msg->type == atmWmChange && client_msg->data.data32[0] == XCB_ICCCM_WM_STATE_ICONIC) { ErrorF("winMultiWindowXMsgProc - WM_CHANGE_STATE - IconicState\n"); memset(&msg, 0, sizeof(msg)); - msg.msg = WM_WM_CHANGE_STATE; msg.iWindow = client_msg->window; + msg.dwID = client_msg->data.data32[0]; winSendMessageToWM(pProcArg->pWMInfo, &msg); } + else if (client_msg->type == pProcArg->pWMInfo->ewmh._NET_WM_STATE) { + int action = client_msg->data.data32[0]; + int state = -1; + + if (action == XCB_EWMH_WM_STATE_ADD) { + if ((client_msg->data.data32[1] == pProcArg->pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_VERT) && + (client_msg->data.data32[2] == pProcArg->pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_HORZ)) + state = XCB_ICCCM_WM_STATE_ZOOM; + + if ((client_msg->data.data32[1] == pProcArg->pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_HORZ) && + (client_msg->data.data32[2] == pProcArg->pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_VERT)) + state = XCB_ICCCM_WM_STATE_ZOOM; + + if (client_msg->data.data32[1] == pProcArg->pWMInfo->ewmh._NET_WM_STATE_HIDDEN) + state = XCB_ICCCM_WM_STATE_ICONIC; + } + else if (action == XCB_EWMH_WM_STATE_REMOVE) { + if ((client_msg->data.data32[1] == pProcArg->pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_VERT) && + (client_msg->data.data32[2] == pProcArg->pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_HORZ)) + state = XCB_ICCCM_WM_STATE_NORMAL; + + if ((client_msg->data.data32[1] == pProcArg->pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_HORZ) && + (client_msg->data.data32[2] == pProcArg->pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_VERT)) + state = XCB_ICCCM_WM_STATE_NORMAL; + + if (client_msg->data.data32[1] == pProcArg->pWMInfo->ewmh._NET_WM_STATE_HIDDEN) + state = XCB_ICCCM_WM_STATE_NORMAL; + } + else { + ErrorF("winMultiWindowXMsgProc: ClientMEssage _NET_WM_STATE unsupported action %d\n", action); + } + + if (state != -1) { + memset(&msg, 0, sizeof(msg)); + msg.msg = WM_WM_CHANGE_STATE; + msg.iWindow = client_msg->window; + msg.dwID = state; + + winSendMessageToWM(pProcArg->pWMInfo, &msg); + } + } } /* Free the event */ @@ -1336,7 +1649,7 @@ winMultiWindowXMsgProc(void *pArg) } xcb_disconnect(pProcArg->conn); - pthread_exit(NULL); + pthread_cleanup_pop(0); return NULL; } @@ -1351,7 +1664,7 @@ winInitWM(void **ppWMInfo, pthread_t * ptWMProc, pthread_t * ptXMsgProc, pthread_mutex_t * ppmServerStarted, - int dwScreen, HWND hwndScreen) + int dwScreen, HWND hwndScreen, Bool compositeWM) { WMProcArgPtr pArg = malloc(sizeof(WMProcArgRec)); WMInfoPtr pWMInfo = malloc(sizeof(WMInfoRec)); @@ -1373,6 +1686,7 @@ winInitWM(void **ppWMInfo, /* Set a return pointer to the Window Manager info structure */ *ppWMInfo = pWMInfo; + pWMInfo->fCompositeWM = compositeWM; /* Setup the argument structure for the thread function */ pArg->dwScreen = dwScreen; @@ -1421,6 +1735,8 @@ winInitMultiWindowWM(WMInfoPtr pWMInfo, WMProcArgPtr pProcArg) char pszDisplay[512]; int iReturn; xcb_auth_info_t *auth_info; + xcb_screen_t *root_screen; + xcb_window_t root_window_id; winDebug("winInitMultiWindowWM - Hello\n"); @@ -1490,6 +1806,10 @@ winInitMultiWindowWM(WMInfoPtr pWMInfo, WMProcArgPtr pProcArg) pWMInfo->atmPrivMap = intern_atom(pWMInfo->conn, WINDOWSWM_NATIVE_HWND); pWMInfo->atmUtf8String = intern_atom(pWMInfo->conn, "UTF8_STRING"); pWMInfo->atmNetWmName = intern_atom(pWMInfo->conn, "_NET_WM_NAME"); + pWMInfo->atmCurrentDesktop = intern_atom(pWMInfo->conn, "_NET_CURRENT_DESKTOP"); + pWMInfo->atmNumberDesktops = intern_atom(pWMInfo->conn, "_NET_NUMBER_OF_DESKTOPS"); + pWMInfo->atmDesktopNames = intern_atom(pWMInfo->conn, "__NET_DESKTOP_NAMES"); + pWMInfo->atmWmState = intern_atom(pWMInfo->conn, "WM_STATE"); /* Initialization for the xcb_ewmh and EWMH atoms */ { @@ -1514,6 +1834,8 @@ winInitMultiWindowWM(WMInfoPtr pWMInfo, WMProcArgPtr pProcArg) pWMInfo->ewmh._NET_WM_STATE_ABOVE, pWMInfo->ewmh._NET_WM_STATE_BELOW, pWMInfo->ewmh._NET_WM_STATE_SKIP_TASKBAR, + pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_VERT, + pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_HORZ, }; xcb_ewmh_set_supported(&pWMInfo->ewmh, pProcArg->dwScreen, @@ -1524,6 +1846,32 @@ winInitMultiWindowWM(WMInfoPtr pWMInfo, WMProcArgPtr pProcArg) } } + /* Get root window id */ + root_screen = xcb_aux_get_screen(pWMInfo->conn, pProcArg->dwScreen); + root_window_id = root_screen->root; + + /* + Set root window properties for describing multiple desktops to describe + the one desktop we have + */ + { + int data; + const char buf[] = "Desktop"; + + data = 0; + xcb_change_property(pWMInfo->conn, XCB_PROP_MODE_REPLACE, root_window_id, + pWMInfo->atmCurrentDesktop, XCB_ATOM_CARDINAL, 32, + 1, &data); + data = 1; + xcb_change_property(pWMInfo->conn, XCB_PROP_MODE_REPLACE, root_window_id, + pWMInfo->atmNumberDesktops, XCB_ATOM_CARDINAL, 32, + 1, &data); + + xcb_change_property(pWMInfo->conn, XCB_PROP_MODE_REPLACE, root_window_id, + pWMInfo->atmDesktopNames, pWMInfo->atmUtf8String, 8, + strlen(buf), (unsigned char *) buf); + } + /* Set the root window cursor to left_ptr (this controls the cursor an application gets over it's windows when it doesn't set one) @@ -1537,9 +1885,6 @@ winInitMultiWindowWM(WMInfoPtr pWMInfo, WMProcArgPtr pProcArg) uint32_t mask = XCB_CW_CURSOR; uint32_t value_list = cursor; - xcb_screen_t *root_screen = xcb_aux_get_screen(pWMInfo->conn, pProcArg->dwScreen); - xcb_window_t window = root_screen->root; - static const uint16_t fgred = 0, fggreen = 0, fgblue = 0; static const uint16_t bgred = 0xFFFF, bggreen = 0xFFFF, bgblue = 0xFFFF; @@ -1549,7 +1894,7 @@ winInitMultiWindowWM(WMInfoPtr pWMInfo, WMProcArgPtr pProcArg) shape, shape + 1, fgred, fggreen, fgblue, bgred, bggreen, bgblue); - xcb_change_window_attributes(pWMInfo->conn, window, mask, &value_list); + xcb_change_window_attributes(pWMInfo->conn, root_window_id, mask, &value_list); xcb_free_cursor(pWMInfo->conn, cursor); xcb_close_font(pWMInfo->conn, font); @@ -1566,7 +1911,7 @@ winSendMessageToWM(void *pWMInfo, winWMMessagePtr pMsg) WMMsgNodePtr pNode; #if CYGMULTIWINDOW_DEBUG - ErrorF("winSendMessageToWM %s\n", MessageName(pMsg)); + ErrorF("winSendMessageToWM %s %08x %d\n", MessageName(pMsg), pMsg->iWindow, pMsg->dwID); #endif pNode = malloc(sizeof(WMMsgNodeRec)); @@ -1577,6 +1922,17 @@ winSendMessageToWM(void *pWMInfo, winWMMessagePtr pMsg) } /* + * winMultiWindowThreadExit - Thread exit handler + */ + +static void +winMultiWindowThreadExit(void *arg) +{ + /* multiwindow client thread has exited, stop server as well */ + raise(SIGTERM); +} + +/* * Check if another window manager is running */ @@ -1635,6 +1991,40 @@ winDeinitMultiWindowWM(void) g_shutdown = TRUE; } +static void +winApplyUrgency(WMInfoPtr pWMInfo, xcb_window_t iWindow, HWND hWnd) +{ + xcb_get_property_cookie_t cookie; + xcb_icccm_wm_hints_t hints; + + cookie = xcb_icccm_get_wm_hints(pWMInfo->conn, iWindow); + if (xcb_icccm_get_wm_hints_reply(pWMInfo->conn, cookie, &hints, NULL)) { + FLASHWINFO fwi; + + fwi.cbSize = sizeof(FLASHWINFO); + fwi.hwnd = hWnd; + + winDebug("winApplyUrgency: window 0x%08x has urgency hint %s\n", iWindow, + (hints.flags & XCB_ICCCM_WM_HINT_X_URGENCY) ? "on" : "off"); + + if (hints.flags & XCB_ICCCM_WM_HINT_X_URGENCY) { + 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); + } +} + /* Windows window styles */ #define HINT_NOFRAME (1L<<0) #define HINT_BORDER (1L<<1) @@ -1644,12 +2034,9 @@ winDeinitMultiWindowWM(void) #define HINT_NOMINIMIZE (1L<<5) #define HINT_NOSYSMENU (1L<<6) #define HINT_SKIPTASKBAR (1L<<7) -/* These two are used on their own */ -#define HINT_MAX (1L<<0) -#define HINT_MIN (1L<<1) static void -winApplyHints(WMInfoPtr pWMInfo, xcb_window_t iWindow, HWND hWnd, HWND * zstyle) +winApplyHints(WMInfoPtr pWMInfo, xcb_window_t iWindow, HWND hWnd, HWND * zstyle, unsigned long *maxmin) { xcb_connection_t *conn = pWMInfo->conn; @@ -1659,9 +2046,11 @@ winApplyHints(WMInfoPtr pWMInfo, xcb_window_t iWindow, HWND hWnd, HWND * zstyle) static xcb_atom_t splashType; static int generation; - unsigned long hint = 0, maxmin = 0; + unsigned long hint = HINT_BORDER | HINT_SIZEBOX | HINT_CAPTION; unsigned long style, exStyle; + *maxmin = 0; + if (!hWnd) return; if (!IsWindow(hWnd)) @@ -1686,20 +2075,29 @@ winApplyHints(WMInfoPtr pWMInfo, xcb_window_t iWindow, HWND hWnd, HWND * zstyle) int i; int nitems = xcb_get_property_value_length(reply)/sizeof(xcb_atom_t); xcb_atom_t *pAtom = xcb_get_property_value(reply); + Bool verMax = FALSE; + Bool horMax = FALSE; for (i = 0; i < nitems; i++) { if (pAtom[i] == skiptaskbarState) hint |= HINT_SKIPTASKBAR; if (pAtom[i] == hiddenState) - maxmin |= HINT_MIN; + *maxmin |= HINT_MIN; else if (pAtom[i] == fullscreenState) - maxmin |= HINT_MAX; + *maxmin |= HINT_MAX; if (pAtom[i] == belowState) *zstyle = HWND_BOTTOM; else if (pAtom[i] == aboveState) *zstyle = HWND_TOPMOST; + if (pAtom[i] == pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_VERT) + verMax = TRUE; + if (pAtom[i] == pWMInfo->ewmh._NET_WM_STATE_MAXIMIZED_HORZ) + horMax = TRUE; } + if (verMax && horMax) + *maxmin |= HINT_MAX; + free(reply); } } @@ -1712,15 +2110,17 @@ winApplyHints(WMInfoPtr pWMInfo, xcb_window_t iWindow, HWND hWnd, HWND * zstyle) MwmHints *mwm_hint = xcb_get_property_value(reply); if (mwm_hint && (nitems >= PropMwmHintsElements) && (mwm_hint->flags & MwmHintsDecorations)) { - if (!mwm_hint->decorations) + if (!mwm_hint->decorations) { + hint &= ~(HINT_BORDER | HINT_SIZEBOX | HINT_CAPTION); hint |= (HINT_NOFRAME | HINT_NOSYSMENU | HINT_NOMINIMIZE | HINT_NOMAXIMIZE); + } else if (!(mwm_hint->decorations & MwmDecorAll)) { - if (mwm_hint->decorations & MwmDecorBorder) - hint |= HINT_BORDER; - if (mwm_hint->decorations & MwmDecorHandle) - hint |= HINT_SIZEBOX; - if (mwm_hint->decorations & MwmDecorTitle) - hint |= HINT_CAPTION; + if (!(mwm_hint->decorations & MwmDecorBorder)) + hint &= ~HINT_BORDER; + if (!(mwm_hint->decorations & MwmDecorHandle)) + hint &= ~HINT_SIZEBOX; + if (!(mwm_hint->decorations & MwmDecorTitle)) + hint &= ~HINT_CAPTION; if (!(mwm_hint->decorations & MwmDecorMenu)) hint |= HINT_NOSYSMENU; if (!(mwm_hint->decorations & MwmDecorMinimize)) @@ -1746,11 +2146,13 @@ winApplyHints(WMInfoPtr pWMInfo, xcb_window_t iWindow, HWND hWnd, HWND * zstyle) if (xcb_ewmh_get_wm_window_type_reply(&pWMInfo->ewmh, cookie, &type, NULL)) { for (i = 0; i < type.atoms_len; i++) { if (type.atoms[i] == pWMInfo->ewmh._NET_WM_WINDOW_TYPE_DOCK) { - hint = (hint & ~HINT_NOFRAME) | HINT_SKIPTASKBAR | HINT_SIZEBOX; + hint &= ~(HINT_BORDER | HINT_SIZEBOX | HINT_CAPTION | HINT_NOFRAME); + hint |= (HINT_SKIPTASKBAR | HINT_SIZEBOX); *zstyle = HWND_TOPMOST; } else if ((type.atoms[i] == pWMInfo->ewmh._NET_WM_WINDOW_TYPE_SPLASH) || (type.atoms[i] == splashType)) { + hint &= ~(HINT_BORDER | HINT_SIZEBOX | HINT_CAPTION); hint |= (HINT_SKIPTASKBAR | HINT_NOSYSMENU | HINT_NOMINIMIZE | HINT_NOMAXIMIZE); *zstyle = HWND_TOPMOST; } @@ -1764,22 +2166,31 @@ winApplyHints(WMInfoPtr pWMInfo, xcb_window_t iWindow, HWND hWnd, HWND * zstyle) cookie = xcb_icccm_get_wm_normal_hints(conn, iWindow); if (xcb_icccm_get_wm_normal_hints_reply(conn, cookie, &size_hints, NULL)) { - if (size_hints.flags & XCB_ICCCM_SIZE_HINT_P_MAX_SIZE) { + /* Notwithstanding MwmDecorHandle, if we have a border, and + WM_NORMAL_HINTS indicates the window should be resizeable, let + the window have a resizing border. This is necessary for windows + with gtk3+ 3.14 csd. */ + if (hint & HINT_BORDER) + hint |= HINT_SIZEBOX; + if (size_hints.flags & XCB_ICCCM_SIZE_HINT_P_MAX_SIZE) { /* Not maximizable if a maximum size is specified, and that size is smaller (in either dimension) than the screen size */ if ((size_hints.max_width < GetSystemMetrics(SM_CXVIRTUALSCREEN)) || (size_hints.max_height < GetSystemMetrics(SM_CYVIRTUALSCREEN))) hint |= HINT_NOMAXIMIZE; + if (size_hints.flags & XCB_ICCCM_SIZE_HINT_P_MIN_SIZE) { /* If both minimum size and maximum size are specified and are the same, don't bother with a resizing frame */ if ((size_hints.min_width == size_hints.max_width) - && (size_hints.min_height == size_hints.max_height)) + && (size_hints.min_height == size_hints.max_height)) { + hint |= HINT_NOMAXIMIZE; hint = (hint & ~HINT_SIZEBOX); + } } } } @@ -1821,17 +2232,12 @@ winApplyHints(WMInfoPtr pWMInfo, xcb_window_t iWindow, HWND hWnd, HWND * zstyle) if (style & STYLE_TOPMOST) *zstyle = HWND_TOPMOST; else if (style & STYLE_MAXIMIZE) - maxmin = (hint & ~HINT_MIN) | HINT_MAX; + *maxmin = (hint & ~HINT_MIN) | HINT_MAX; else if (style & STYLE_MINIMIZE) - maxmin = (hint & ~HINT_MAX) | HINT_MIN; + *maxmin = (hint & ~HINT_MAX) | HINT_MIN; else if (style & STYLE_BOTTOM) *zstyle = HWND_BOTTOM; - if (maxmin & HINT_MAX) - SendMessage(hWnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0); - else if (maxmin & HINT_MIN) - SendMessage(hWnd, WM_SYSCOMMAND, SC_MINIMIZE, 0); - if (style & STYLE_NOTITLE) hint = (hint & ~HINT_NOFRAME & ~HINT_BORDER & ~HINT_CAPTION) | @@ -1845,6 +2251,9 @@ winApplyHints(WMInfoPtr pWMInfo, xcb_window_t 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) @@ -1852,6 +2261,11 @@ winApplyHints(WMInfoPtr pWMInfo, xcb_window_t 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 */ @@ -1886,57 +2300,3 @@ winApplyHints(WMInfoPtr pWMInfo, xcb_window_t 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 3f47fec65..ee3d1637e 100644 --- a/hw/xwin/winmultiwindowwndproc.c +++ b/hw/xwin/winmultiwindowwndproc.c @@ -35,12 +35,19 @@ #ifdef HAVE_XWIN_CONFIG_H #include <xwin-config.h> #endif + #include "win.h" #include "dixevents.h" #include "winmultiwindowclass.h" #include "winprefs.h" #include "winmsg.h" #include "inputstr.h" +#include "wmutil/keyboard.h" +#include <dwmapi.h> + +#ifndef WM_DWMCOMPOSITIONCHANGED +#define WM_DWMCOMPOSITIONCHANGED 0x031e +#endif extern void winUpdateWindowPosition(HWND hWnd, HWND * zstyle); @@ -294,6 +301,144 @@ winStartMousePolling(winPrivScreenPtr s_pScreenPriv) MOUSE_POLLING_INTERVAL, NULL); } +static +void +winAdjustXWindowState(winPrivScreenPtr s_pScreenPriv, winWMMessageRec *wmMsg) +{ + /* Do nothing if window has not yet been given initial state */ + if (!GetProp(wmMsg->hwndWindow, WIN_STATE_PROP)) + return; + + 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); + } +} + +/* Undocumented */ +typedef struct _ACCENTPOLICY +{ + ULONG AccentState; + ULONG AccentFlags; + ULONG GradientColor; + ULONG AnimationId; +} ACCENTPOLICY; + +#define ACCENT_ENABLE_BLURBEHIND 3 + +typedef struct _WINCOMPATTR +{ + DWORD attribute; + PVOID pData; + ULONG dataSize; +} WINCOMPATTR; + +#define WCA_ACCENT_POLICY 19 + +typedef WINBOOL WINAPI (*PFNSETWINDOWCOMPOSITIONATTRIBUTE)(HWND, WINCOMPATTR *); + +static void +CheckForAlpha(HWND hWnd, WindowPtr pWin, winScreenInfo *pScreenInfo) +{ + /* Check (once) which API we should use */ + static Bool doOnce = TRUE; + static PFNSETWINDOWCOMPOSITIONATTRIBUTE pSetWindowCompositionAttribute = NULL; + static Bool useDwmEnableBlurBehindWindow = FALSE; + + if (doOnce) + { + /* XXX: when mingw-w64-headers 5.0 is available, just include + versionhelper.h and use the appropriate macros here */ + OSVERSIONINFOEX osvi = {0}; + osvi.dwOSVersionInfoSize = sizeof(osvi); + GetVersionEx((LPOSVERSIONINFO)&osvi); + + /* SetWindowCompositionAttribute() exists on Windows 7 and later, + but doesn't work for this purpose, so first check for Windows 10 + or later */ + if (osvi.dwMajorVersion >= 10) + { + HMODULE hUser32 = GetModuleHandle("user32"); + + if (hUser32) + pSetWindowCompositionAttribute = (PFNSETWINDOWCOMPOSITIONATTRIBUTE) GetProcAddress(hUser32, "SetWindowCompositionAttribute"); + winDebug("SetWindowCompositionAttribute %s\n", pSetWindowCompositionAttribute ? "found" : "not found"); + } + /* On Windows 7 and Windows Vista, use DwmEnableBlurBehindWindow() */ + else if ((osvi.dwMajorVersion == 6) && (osvi.dwMinorVersion <= 1)) + { + useDwmEnableBlurBehindWindow = TRUE; + } + /* On Windows 8 and Windows 8.1, using the alpha channel on those + seems near impossible, so we don't do anything. */ + + doOnce = FALSE; + } + + /* alpha-channel use is wanted */ + if (!g_fCompositeAlpha || !pScreenInfo->fCompositeWM) + return; + + /* Image has alpha ... */ + if (pWin->drawable.depth != 32) + return; + + /* ... and we can do something useful with it? */ + if (pSetWindowCompositionAttribute) + { + WINBOOL rc; + /* Use the (undocumented) SetWindowCompositionAttribute, if + available, to turn on alpha channel use on Windows 10. */ + ACCENTPOLICY policy = { ACCENT_ENABLE_BLURBEHIND, 0, 0, 0 } ; + WINCOMPATTR data = { WCA_ACCENT_POLICY, &policy, sizeof(ACCENTPOLICY) }; + + /* This turns on DWM looking at the alpha-channel of this window */ + winDebug("enabling alpha for XID %08x hWnd %p, using SetWindowCompositionAttribute()\n", (unsigned int)pWin->drawable.id, hWnd); + rc = pSetWindowCompositionAttribute(hWnd, &data); + if (!rc) + ErrorF("SetWindowCompositionAttribute failed: %d\n", (int)GetLastError()); + } + else if (useDwmEnableBlurBehindWindow) + { + HRESULT rc; + WINBOOL enabled; + + rc = DwmIsCompositionEnabled(&enabled); + if ((rc == S_OK) && enabled) + { + /* Use DwmEnableBlurBehindWindow, to turn on alpha channel + use on Windows Vista and Windows 7 */ + DWM_BLURBEHIND bbh; + bbh.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION | DWM_BB_TRANSITIONONMAXIMIZED; + bbh.fEnable = TRUE; + bbh.hRgnBlur = NULL; + bbh.fTransitionOnMaximized = TRUE; /* What does this do ??? */ + + /* This terribly-named function actually controls if DWM + looks at the alpha channel of this window */ + winDebug("enabling alpha for XID %08x hWnd %p, using DwmEnableBlurBehindWindow()\n", (unsigned int)pWin->drawable.id, hWnd); + rc = DwmEnableBlurBehindWindow(hWnd, &bbh); + if (rc != S_OK) + ErrorF("DwmEnableBlurBehindWindow failed: %x, %d\n", (int)rc, (int)GetLastError()); + } + } +} + /* * winTopLevelWindowProc - Window procedure for all top-level Windows windows. */ @@ -302,7 +447,6 @@ LRESULT CALLBACK winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { POINT ptMouse; - HDC hdcUpdate; PAINTSTRUCT ps; WindowPtr pWin = NULL; winPrivWinPtr pWinPriv = NULL; @@ -323,6 +467,20 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) lParam); #endif + /* + If this is WM_CREATE, set up the Windows window properties which point to X window information, + before we populate other local variables... + */ + if (message == WM_CREATE) { + SetProp(hwnd, + WIN_WINDOW_PROP, + (HANDLE) ((LPCREATESTRUCT) lParam)->lpCreateParams); + SetProp(hwnd, + WIN_WID_PROP, + (HANDLE) (INT_PTR)winGetWindowID(((LPCREATESTRUCT) lParam)-> + lpCreateParams)); + } + /* Check if the Windows window property for our X window pointer is valid */ if ((pWin = GetProp(hwnd, WIN_WINDOW_PROP)) != NULL) { /* Our X window pointer is valid */ @@ -383,18 +541,6 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) /* Branch on message type */ switch (message) { case WM_CREATE: - - /* */ - SetProp(hwnd, - WIN_WINDOW_PROP, - (HANDLE) ((LPCREATESTRUCT) lParam)->lpCreateParams); - - /* */ - SetProp(hwnd, - WIN_WID_PROP, - (HANDLE) (INT_PTR) winGetWindowID(((LPCREATESTRUCT) lParam)-> - lpCreateParams)); - /* * Make X windows' Z orders sync with Windows windows because * there can be AlwaysOnTop windows overlapped on the window @@ -415,6 +561,13 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) XMING_SIGNATURE); + /* Tell our Window Manager thread to style and then show the window */ + wmMsg.msg = WM_WM_CREATE; + if (fWMMsgInitialized) + winSendMessageToWM(s_pScreenPriv->pWMInfo, &wmMsg); + + CheckForAlpha(hwnd, pWin, s_pScreenInfo); + return 0; case WM_INIT_SYS_MENU: @@ -457,18 +610,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 +622,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: @@ -868,6 +992,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 +1003,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 +1055,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 +1133,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: @@ -1044,6 +1163,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 */ @@ -1142,6 +1265,16 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) } break; + case WM_ASYNCMOVE: + winAdjustWindowsWindow(pWin, hwnd); + break; + + case WM_DWMCOMPOSITIONCHANGED: + /* This message is only sent on Vista/W7 */ + CheckForAlpha(hwnd, pWin, s_pScreenInfo); + + return 0; + default: break; } @@ -1155,3 +1288,116 @@ 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) +{ + WindowPtr pWin = NULL; + +#if CYGDEBUG + winDebugWin32Message("winChildWindowProc", hwnd, message, wParam, lParam); +#endif + + /* + If this is WM_CREATE, set up the Windows window properties which point to + X window information + */ + if (message == WM_CREATE) { + SetProp(hwnd, + WIN_WINDOW_PROP, + (HANDLE) ((LPCREATESTRUCT) lParam)->lpCreateParams); + SetProp(hwnd, + WIN_WID_PROP, + (HANDLE) (INT_PTR)winGetWindowID(((LPCREATESTRUCT) lParam)-> + lpCreateParams)); + } + + /* Retrieve the Windows window property for our X window pointer */ + pWin = GetProp(hwnd, WIN_WINDOW_PROP); + + 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? */ + + case WM_ASYNCMOVE: + winAdjustWindowsWindow(pWin, hwnd); + break; + } + + 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", + (int)rcNew.left, (int)rcNew.top, (int)rcNew.right, (int)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", + (int)rcNew.left, (int)rcNew.top, (int)rcNew.right, (int)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/winos.c b/hw/xwin/winos.c index 0d825bb83..4e72daa7f 100644 --- a/hw/xwin/winos.c +++ b/hw/xwin/winos.c @@ -37,19 +37,27 @@ static const char* IsWow64(void) { #ifdef __x86_64__ - return " (64-bit)"; + return " (Win64)"; #else - WINBOOL bIsWow64; + /* Check if we are running under WoW64 */ LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress(GetModuleHandle(TEXT("kernel32")), "IsWow64Process"); if (NULL != fnIsWow64Process) { - if (fnIsWow64Process(GetCurrentProcess(), &bIsWow64)) - return bIsWow64 ? " (WoW64)" : " (32-bit)"; - } + WINBOOL bIsWow64 = FALSE; - /* OS doesn't support IsWow64Process() */ - return ""; + if (fnIsWow64Process(GetCurrentProcess(), &bIsWow64)) { + return bIsWow64 ? " (WoW64)" : " (Win32)"; + } + else { + /* IsWow64Process() failed */ + return " (Unknown)"; + } + } + else { + /* OS doesn't support IsWow64Process() */ + return ""; + } #endif } @@ -61,12 +69,89 @@ 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); - ErrorF("OS: Windows NT %d.%d build %d%s\n", - (int)osvi.dwMajorVersion, (int)osvi.dwMinorVersion, - (int)osvi.dwBuildNumber, IsWow64()); + /* 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 2016"; + } + } + else if (osvi.dwMajorVersion == 6) { + if (osvi.dwMinorVersion == 4) { + if (osvi.wProductType == VER_NT_WORKSTATION) + prodName = "Windows 10"; + else + prodName = "Windows Server 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; + } + + isWow = IsWow64(); + + 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); } diff --git a/hw/xwin/winprefs.c b/hw/xwin/winprefs.c index 0ac5b4fea..1afba3165 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/wait.h> +#include <pthread.h> +#include <sys/cygwin.h> #endif #include "win.h" @@ -59,9 +62,6 @@ extern int parse_file(FILE * fp); /* Currently in use command ID, incremented each new menu item created */ static int g_cmdid = STARTMENUID; -/* Local function to handle comma-ified icon names */ -static HICON LoadImageComma(char *fname, int sx, int sy, int flags); - /* * Creates or appends a menu from a MENUPARSED structure */ @@ -295,6 +295,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. @@ -317,24 +421,17 @@ HandleCustomWM_COMMAND(HWND hwnd, WORD command, winPrivScreenPtr pScreenPriv) 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: @@ -418,8 +515,10 @@ SetupSysMenu(HWND hwnd) pWin = GetProp(hwnd, WIN_WINDOW_PROP); sys = GetSystemMenu(hwnd, FALSE); - if (!sys) + if (!sys) { + ErrorF("SetupSysMenu: GetSystemMenu() failed for HWND %p\n", hwnd); return; + } if (pWin) { /* First see if there's a class match... */ @@ -474,7 +573,7 @@ winOverrideDefaultIcon(int size) HICON hicon; if (pref.defaultIconName[0]) { - hicon = LoadImageComma(pref.defaultIconName, size, size, 0); + hicon = LoadImageComma(pref.defaultIconName, pref.iconDirectory, size, size, 0); if (hicon == NULL) ErrorF("winOverrideDefaultIcon: LoadImageComma(%s) failed\n", pref.defaultIconName); @@ -496,9 +595,12 @@ winTaskbarIcon(void) hicon = 0; /* First try and load an overridden, if success then return it */ if (pref.trayIconName[0]) { - hicon = LoadImageComma(pref.trayIconName, + hicon = LoadImageComma(pref.trayIconName, pref.iconDirectory, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0); + if (hicon == NULL) + ErrorF("winTaskbarIcon: LoadImageComma(%s) failed\n", + pref.trayIconName); } /* Otherwise return the default */ @@ -513,17 +615,18 @@ winTaskbarIcon(void) } /* + * Handle comma-ified icon names + * * Parse a filename to extract an icon: * If fname is exactly ",nnn" then extract icon from our resource * else if it is "file,nnn" then extract icon nnn from that file * else try to load it as an .ico file and if that fails return NULL */ -static HICON -LoadImageComma(char *fname, int sx, int sy, int flags) +HICON +LoadImageComma(char *fname, char *iconDirectory, int sx, int sy, int flags) { HICON hicon; int i; - char file[PATH_MAX + NAME_MAX + 2]; /* Some input error checking */ if (!fname || !fname[0]) @@ -539,31 +642,67 @@ LoadImageComma(char *fname, int sx, int sy, int flags) MAKEINTRESOURCE(i), IMAGE_ICON, sx, sy, flags); } else { + char *file = malloc(PATH_MAX + NAME_MAX + 2); + Bool convert = FALSE; + + if (!file) + return NULL; + file[0] = 0; - /* Prepend path if not given a "X:\" filename */ + + /* If fname starts 'X:\', it's an absolute Windows path, do nothing */ if (!(fname[0] && fname[1] == ':' && fname[2] == '\\')) { - strcpy(file, pref.iconDirectory); - if (pref.iconDirectory[0]) - if (fname[strlen(fname) - 1] != '\\') - strcat(file, "\\"); +#ifdef __CYGWIN__ + /* If fname starts with '/', it's an absolute cygwin path, we'll + need to convert it */ + if (fname[0] == '/') { + convert = TRUE; + } + else +#endif + if (iconDirectory) { + /* Otherwise, prepend the default icon directory, which + currently must be in absolute Windows path form */ + strcpy(file, iconDirectory); + if (iconDirectory[0]) + if (iconDirectory[strlen(iconDirectory) - 1] != '\\') + strcat(file, "\\"); + } } strcat(file, fname); + /* Trim off any ',index' */ if (strrchr(file, ',')) { - /* Specified as <fname>,<index> */ - *(strrchr(file, ',')) = 0; /* End string at comma */ i = atoi(strrchr(fname, ',') + 1); - hicon = ExtractIcon(g_hInstance, file, i); } else { - /* Just an .ico file... */ + i = -1; + } + +#ifdef __CYGWIN__ + /* Convert from Cygwin path to Windows path */ + if (convert) { + char *converted_file = cygwin_create_path(CCP_POSIX_TO_WIN_A | CCP_ABSOLUTE, file); + if (converted_file) { + free(file); + file = converted_file; + } + } +#endif + if (i >= 0) { + /* Specified as <fname>,<index> */ + hicon = ExtractIcon(g_hInstance, file, i); + } + else { + /* Specified as just an .ico file */ hicon = (HICON) LoadImage(NULL, file, IMAGE_ICON, sx, sy, LR_LOADFROMFILE | flags); } + free(file); } return hicon; } @@ -585,7 +724,7 @@ winOverrideIcon(char *res_name, char *res_class, char *wmName) if (pref.icon[i].hicon) return pref.icon[i].hicon; - hicon = LoadImageComma(pref.icon[i].iconFile, 0, 0, LR_DEFAULTSIZE); + hicon = LoadImageComma(pref.icon[i].iconFile, pref.iconDirectory, 0, 0, LR_DEFAULTSIZE); if (hicon == NULL) ErrorF("winOverrideIcon: LoadImageComma(%s) failed\n", pref.icon[i].iconFile); @@ -635,11 +774,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 @@ -670,7 +815,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; @@ -718,6 +863,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 936a42f22..d1fef2ed9 100644 --- a/hw/xwin/winprefs.h +++ b/hw/xwin/winprefs.h @@ -35,9 +35,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 */ @@ -68,6 +65,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 { @@ -175,4 +173,8 @@ unsigned long HICON winTaskbarIcon(void); HICON winOverrideDefaultIcon(int size); + +HICON +LoadImageComma(char *fname, char *iconDirectory, int sx, int sy, int flags); + #endif 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 803e78f93..a69b41853 100644 --- a/hw/xwin/winprocarg.c +++ b/hw/xwin/winprocarg.c @@ -40,6 +40,7 @@ from The Open Group. #include "winconfig.h" #include "winmsg.h" #include "winmonitors.h" +#include "winprefs.h" #include "winclipboard/winclipboard.h" @@ -126,11 +127,9 @@ winInitializeScreenDefaults(void) defaultScreenInfo.pfb = NULL; defaultScreenInfo.fFullScreen = FALSE; defaultScreenInfo.fDecoration = TRUE; -#ifdef XWIN_MULTIWINDOWEXTWM - defaultScreenInfo.fMWExtWM = FALSE; -#endif defaultScreenInfo.fRootless = FALSE; defaultScreenInfo.fMultiWindow = FALSE; + defaultScreenInfo.fCompositeWM = TRUE; defaultScreenInfo.fMultiMonitorOverride = FALSE; defaultScreenInfo.fMultipleMonitors = FALSE; defaultScreenInfo.fLessPointer = FALSE; @@ -141,6 +140,13 @@ winInitializeScreenDefaults(void) defaultScreenInfo.fUseUnixKillKey = WIN_DEFAULT_UNIX_KILL; defaultScreenInfo.fIgnoreInput = FALSE; defaultScreenInfo.fExplicitScreen = FALSE; + defaultScreenInfo.hIcon = (HICON) + LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_XWIN), IMAGE_ICON, + GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), 0); + defaultScreenInfo.hIconSm = (HICON) + LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_XWIN), IMAGE_ICON, + GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), + LR_DEFAULTSIZE); /* Note that the default screen has been initialized */ fInitializedScreenDefaults = TRUE; @@ -285,6 +291,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; } @@ -311,11 +320,7 @@ ddxProcessArgument(int argc, char *argv[], int i) if (i + 2 < argc && 1 == sscanf(argv[i + 2], "@%d", (int *) &iMonitor)) { struct GetMonitorInfoData data; - if (!QueryMonitor(iMonitor, &data)) { - ErrorF - ("ddxProcessArgument - screen - Querying monitors failed\n"); - } - else if (data.bMonitorSpecifiedExists == TRUE) { + if (QueryMonitor(iMonitor, &data)) { winErrorFVerb(2, "ddxProcessArgument - screen - Found Valid ``@Monitor'' = %d arg\n", iMonitor); @@ -336,8 +341,7 @@ ddxProcessArgument(int argc, char *argv[], int i) ErrorF ("ddxProcessArgument - screen - Invalid monitor number %d\n", iMonitor); - UseMsg(); - exit(0); + exit(1); return 0; } } @@ -368,11 +372,7 @@ ddxProcessArgument(int argc, char *argv[], int i) (int *) &iMonitor)) { struct GetMonitorInfoData data; - if (!QueryMonitor(iMonitor, &data)) { - ErrorF - ("ddxProcessArgument - screen - Querying monitors failed\n"); - } - else if (data.bMonitorSpecifiedExists == TRUE) { + if (QueryMonitor(iMonitor, &data)) { g_ScreenInfo[nScreenNum].iMonitor = iMonitor; g_ScreenInfo[nScreenNum].hMonitor = data.monitorHandle; g_ScreenInfo[nScreenNum].dwInitialX += @@ -385,11 +385,9 @@ ddxProcessArgument(int argc, char *argv[], int i) ErrorF ("ddxProcessArgument - screen - Invalid monitor number %d\n", iMonitor); - UseMsg(); - exit(0); + exit(1); return 0; } - } } @@ -397,11 +395,7 @@ ddxProcessArgument(int argc, char *argv[], int i) else if (1 == sscanf(argv[i + 2], "%*dx%*d@%d", (int *) &iMonitor)) { struct GetMonitorInfoData data; - if (!QueryMonitor(iMonitor, &data)) { - ErrorF - ("ddxProcessArgument - screen - Querying monitors failed\n"); - } - else if (data.bMonitorSpecifiedExists == TRUE) { + if (QueryMonitor(iMonitor, &data)) { winErrorFVerb(2, "ddxProcessArgument - screen - Found Valid ``@Monitor'' = %d arg\n", iMonitor); @@ -416,11 +410,9 @@ ddxProcessArgument(int argc, char *argv[], int i) ErrorF ("ddxProcessArgument - screen - Invalid monitor number %d\n", iMonitor); - UseMsg(); - exit(0); + exit(1); return 0; } - } } else if (i + 3 < argc && 1 == sscanf(argv[i + 2], "%d", (int *) &iWidth) @@ -550,48 +542,63 @@ ddxProcessArgument(int argc, char *argv[], int i) return 1; } -#ifdef XWIN_MULTIWINDOWEXTWM /* - * Look for the '-mwextwm' argument + * Look for the '-rootless' argument */ - if (IS_OPTION("-mwextwm")) { + if (IS_OPTION("-rootless")) { if (!screenInfoPtr->fMultiMonitorOverride) - screenInfoPtr->fMultipleMonitors = TRUE; - screenInfoPtr->fMWExtWM = TRUE; + screenInfoPtr->fMultipleMonitors = FALSE; + screenInfoPtr->fRootless = TRUE; /* Indicate that we have processed this argument */ return 1; } + /* - * Look for the '-internalwm' argument + * Look for the '-multiwindow' argument */ - if (IS_OPTION("-internalwm")) { - ErrorF("Ignoring obsolete -internalwm option\n"); - /* Ignored, but we still accept the arg for backwards compatibility */ + if (IS_OPTION("-multiwindow")) { + if (!screenInfoPtr->fMultiMonitorOverride) + screenInfoPtr->fMultipleMonitors = TRUE; + screenInfoPtr->fMultiWindow = TRUE; + /* Indicate that we have processed this argument */ return 1; } -#endif /* - * Look for the '-rootless' argument + * Look for the '-compositewm' argument */ - if (IS_OPTION("-rootless")) { - if (!screenInfoPtr->fMultiMonitorOverride) - screenInfoPtr->fMultipleMonitors = FALSE; - screenInfoPtr->fRootless = TRUE; + if (IS_OPTION("-compositewm")) { + screenInfoPtr->fCompositeWM = TRUE; + + /* Indicate that we have processed this argument */ + return 1; + } + /* + * Look for the '-nocompositewm' argument + */ + if (IS_OPTION("-nocompositewm")) { + screenInfoPtr->fCompositeWM = FALSE; /* Indicate that we have processed this argument */ return 1; } /* - * Look for the '-multiwindow' argument + * Look for the '-compositealpha' argument */ - if (IS_OPTION("-multiwindow")) { - if (!screenInfoPtr->fMultiMonitorOverride) - screenInfoPtr->fMultipleMonitors = TRUE; - screenInfoPtr->fMultiWindow = TRUE; + if (IS_OPTION("-compositealpha")) { + g_fCompositeAlpha = TRUE; + + /* Indicate that we have processed this argument */ + return 1; + } + /* + * Look for the '-nocompositealpha' argument + */ + if (IS_OPTION("-nocompositealpha")) { + g_fCompositeAlpha = FALSE; /* Indicate that we have processed this argument */ return 1; @@ -931,6 +938,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") @@ -985,9 +1000,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; } @@ -1050,6 +1062,11 @@ ddxProcessArgument(int argc, char *argv[], int i) return 1; } + if (IS_OPTION("-silent-dup-error")) { + g_fSilentDupError = TRUE; + return 1; + } + if (IS_OPTION("-wgl")) { g_fNativeGl = TRUE; return 1; @@ -1070,6 +1087,30 @@ ddxProcessArgument(int argc, char *argv[], int i) return 1; } + if (IS_OPTION("-icon")) { + char *iconspec; + CHECK_ARGS(1); + iconspec = argv[++i]; + screenInfoPtr->hIcon = LoadImageComma(iconspec, NULL, + GetSystemMetrics(SM_CXICON), + GetSystemMetrics(SM_CYICON), + 0); + screenInfoPtr->hIconSm = LoadImageComma(iconspec, NULL, + GetSystemMetrics(SM_CXSMICON), + GetSystemMetrics(SM_CYSMICON), + LR_DEFAULTSIZE); + if ((screenInfoPtr->hIcon == NULL) || + (screenInfoPtr->hIconSm == NULL)) { + ErrorF("ddxProcessArgument - icon - Invalid icon specification %s\n", + iconspec); + exit(1); + return 0; + } + + /* Indicate that we have processed the argument */ + return 2; + } + return 0; } @@ -1170,6 +1211,5 @@ winLogVersionInfo(void) 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 3e084221e..038d63bde 100644 --- a/hw/xwin/winrandr.c +++ b/hw/xwin/winrandr.c @@ -42,17 +42,17 @@ static Bool winRandRGetInfo(ScreenPtr pScreen, Rotation * pRotations) { - rrScrPrivPtr pRRScrPriv; - RROutputPtr output; - - pRRScrPriv = rrGetScrPriv(pScreen); - output = pRRScrPriv->outputs[0]; - winDebug("winRandRGetInfo ()\n"); /* Don't support rotations */ *pRotations = RR_Rotate_0; + return TRUE; +} + +static void +winRandRUpdateMode(ScreenPtr pScreen, RROutputPtr output) +{ /* Delete previous mode */ if (output->modes[0]) { @@ -83,8 +83,6 @@ winRandRGetInfo(ScreenPtr pScreen, Rotation * pRotations) mode = RRModeGet(&modeInfo, name); output->crtc->mode = mode; } - - return TRUE; } /* @@ -95,6 +93,7 @@ winDoRandRScreenSetSize(ScreenPtr pScreen, CARD16 width, CARD16 height, CARD32 mmWidth, CARD32 mmHeight) { + rrScrPrivPtr pRRScrPriv; winScreenPriv(pScreen); winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; WindowPtr pRoot = pScreen->root; @@ -136,6 +135,10 @@ winDoRandRScreenSetSize(ScreenPtr pScreen, // and arrange for it to be repainted pScreen->PaintWindow(pRoot, &pRoot->borderClip, PW_BACKGROUND); + // Set mode to current display size + pRRScrPriv = rrGetScrPriv(pScreen); + winRandRUpdateMode(pScreen, pRRScrPriv->primaryOutput); + /* Indicate that a screen size change took place */ RRScreenSizeNotify(pScreen); } @@ -170,9 +173,6 @@ winRandRScreenSetSize(ScreenPtr pScreen, resize the native display size */ if (FALSE -#ifdef XWIN_MULTIWINDOWEXTWM - || pScreenInfo->fMWExtWM -#endif || pScreenInfo->fRootless || pScreenInfo->fMultiWindow ) { @@ -273,6 +273,24 @@ winRandRInit(ScreenPtr pScreen) /* Ensure we have space for exactly one mode */ output->modes = malloc(sizeof(RRModePtr)); output->modes[0] = NULL; + + /* Set mode to current display size */ + winRandRUpdateMode(pScreen, output); + + /* Make up some physical dimensions */ + output->mmWidth = (pScreen->width * 25.4)/monitorResolution; + output->mmHeight = (pScreen->height * 25.4)/monitorResolution; + + /* Allocate and make up a (fixed, linear) gamma ramp */ + { + int i; + RRCrtcGammaSetSize(crtc, 256); + for (i = 0; i < crtc->gammaSize; i++) { + crtc->gammaRed[i] = i << 8; + crtc->gammaBlue[i] = i << 8; + crtc->gammaGreen[i] = i << 8; + } + } } /* diff --git a/hw/xwin/winscrinit.c b/hw/xwin/winscrinit.c index a44e21fbd..33dcf70ac 100644 --- a/hw/xwin/winscrinit.c +++ b/hw/xwin/winscrinit.c @@ -38,31 +38,6 @@ #include "win.h" #include "winmsg.h" -#ifdef XWIN_MULTIWINDOWEXTWM -static RootlessFrameProcsRec winMWExtWMProcs = { - winMWExtWMCreateFrame, - winMWExtWMDestroyFrame, - - winMWExtWMMoveFrame, - winMWExtWMResizeFrame, - winMWExtWMRestackFrame, - winMWExtWMReshapeFrame, - winMWExtWMUnmapFrame, - - winMWExtWMStartDrawing, - winMWExtWMStopDrawing, - winMWExtWMUpdateRegion, - winMWExtWMDamageRects, - winMWExtWMRootlessSwitchWindow, - NULL, //winMWExtWMDoReorderWindow, - NULL, //winMWExtWMHideWindow, - NULL, //winMWExtWMUpdateColorMap, - - NULL, //winMWExtWMCopyBytes, - winMWExtWMCopyWindow -}; -#endif - /* * Prototypes */ @@ -294,6 +269,11 @@ winFinishScreenInitFB(int i, ScreenPtr pScreen, int argc, char **argv) return FALSE; } + if ((pScreenInfo->dwBPP == 8) && (pScreenInfo->fCompositeWM)) { + ErrorF("-compositewm disabled due to 8bpp depth\n"); + pScreenInfo->fCompositeWM = FALSE; + } + /* Apparently we need this for the render extension */ miSetPixmapDepths(); @@ -384,11 +364,7 @@ winFinishScreenInitFB(int i, ScreenPtr pScreen, int argc, char **argv) /* Initialize the shadow framebuffer layer */ if ((pScreenInfo->dwEngine == WIN_SERVER_SHADOW_GDI - || pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DDNL) -#ifdef XWIN_MULTIWINDOWEXTWM - && !pScreenInfo->fMWExtWM -#endif - ) { + || pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DDNL)) { #if CYGDEBUG winDebug("winFinishScreenInitFB - Calling shadowSetup ()\n"); #endif @@ -403,23 +379,6 @@ winFinishScreenInitFB(int i, ScreenPtr pScreen, int argc, char **argv) pScreen->CreateScreenResources = winCreateScreenResources; } -#ifdef XWIN_MULTIWINDOWEXTWM - /* Handle multi-window external window manager mode */ - if (pScreenInfo->fMWExtWM) { - winDebug("winScreenInit - MultiWindowExtWM - Calling RootlessInit\n"); - - RootlessInit(pScreen, &winMWExtWMProcs); - - winDebug("winScreenInit - MultiWindowExtWM - RootlessInit returned\n"); - - rootless_CopyBytes_threshold = 0; - /* FIXME: How many? Profiling needed? */ - rootless_CopyWindow_threshold = 1; - - winWindowsWMExtensionInit(); - } -#endif - /* Handle rootless mode */ if (pScreenInfo->fRootless) { /* Define the WRAP macro temporarily for local use */ @@ -477,6 +436,7 @@ winFinishScreenInitFB(int i, ScreenPtr pScreen, int argc, char **argv) WRAP(MoveWindow); WRAP(CopyWindow); WRAP(SetShape); + WRAP(ModifyPixmapHeader); /* Assign multi-window window procedures to be top level procedures */ pScreen->CreateWindow = winCreateWindowMultiWindow; @@ -492,6 +452,12 @@ winFinishScreenInitFB(int i, ScreenPtr pScreen, int argc, char **argv) pScreen->CopyWindow = winCopyWindowMultiWindow; pScreen->SetShape = winSetShapeMultiWindow; + if (pScreenInfo->fCompositeWM) { + pScreen->CreatePixmap = winCreatePixmapMultiwindow; + pScreen->DestroyPixmap = winDestroyPixmapMultiwindow; + pScreen->ModifyPixmapHeader = winModifyPixmapHeaderMultiwindow; + } + /* Undefine the WRAP macro, as it is not needed elsewhere */ #undef WRAP } @@ -519,9 +485,6 @@ winFinishScreenInitFB(int i, ScreenPtr pScreen, int argc, char **argv) /* Set the ServerStarted flag to false */ pScreenPriv->fServerStarted = FALSE; -#ifdef XWIN_MULTIWINDOWEXTWM - pScreenPriv->fRestacking = FALSE; -#endif if (pScreenInfo->fMultiWindow) { #if CYGDEBUG || YES @@ -534,7 +497,8 @@ winFinishScreenInitFB(int i, ScreenPtr pScreen, int argc, char **argv) &pScreenPriv->ptXMsgProc, &pScreenPriv->pmServerStarted, pScreenInfo->dwScreen, - (HWND) &pScreenPriv->hwndScreen)) { + (HWND) &pScreenPriv->hwndScreen, + pScreenInfo->fCompositeWM)) { ErrorF("winFinishScreenInitFB - winInitWM () failed.\n"); return FALSE; } diff --git a/hw/xwin/winshadddnl.c b/hw/xwin/winshadddnl.c index 4e1fbd15c..290176920 100644 --- a/hw/xwin/winshadddnl.c +++ b/hw/xwin/winshadddnl.c @@ -1201,6 +1201,7 @@ winSetEngineFunctionsShadowDDNL(ScreenPtr pScreen) pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowWindowed; pScreenPriv->pwinFinishScreenInit = winFinishScreenInitFB; pScreenPriv->pwinBltExposedRegions = winBltExposedRegionsShadowDDNL; + pScreenPriv->pwinBltExposedWindowRegion = NULL; pScreenPriv->pwinActivateApp = winActivateAppShadowDDNL; pScreenPriv->pwinRedrawScreen = winRedrawScreenShadowDDNL; pScreenPriv->pwinRealizeInstalledPalette diff --git a/hw/xwin/winshadgdi.c b/hw/xwin/winshadgdi.c index 6d7ebce07..ab602ba04 100644 --- a/hw/xwin/winshadgdi.c +++ b/hw/xwin/winshadgdi.c @@ -60,6 +60,9 @@ static Bool winBltExposedRegionsShadowGDI(ScreenPtr pScreen); static Bool + winBltExposedWindowRegionShadowGDI(ScreenPtr pScreen, WindowPtr pWin); + +static Bool winActivateAppShadowGDI(ScreenPtr pScreen); static Bool @@ -750,6 +753,12 @@ winBltExposedRegionsShadowGDI(ScreenPtr pScreen) /* BeginPaint gives us an hdc that clips to the invalidated region */ hdcUpdate = BeginPaint(pScreenPriv->hwndScreen, &ps); + /* Avoid the BitBlt if the PAINTSTRUCT region is bogus */ + if (ps.rcPaint.right == 0 && ps.rcPaint.bottom == 0 && + ps.rcPaint.left == 0 && ps.rcPaint.top == 0) { + EndPaint(pScreenPriv->hwndScreen, &ps); + return 0; + } /* Realize the palette, if we have one */ if (pScreenPriv->pcmapInstalled != NULL) { @@ -759,11 +768,30 @@ winBltExposedRegionsShadowGDI(ScreenPtr pScreen) RealizePalette(hdcUpdate); } - /* Our BitBlt will be clipped to the invalidated region */ - BitBlt(hdcUpdate, - 0, 0, - pScreenInfo->dwWidth, pScreenInfo->dwHeight, - pScreenPriv->hdcShadow, 0, 0, SRCCOPY); + /* Try to copy from the shadow buffer to the invalidated region */ + if (!BitBlt(hdcUpdate, + ps.rcPaint.left, ps.rcPaint.top, + ps.rcPaint.right - ps.rcPaint.left, + ps.rcPaint.bottom - ps.rcPaint.top, + pScreenPriv->hdcShadow, + ps.rcPaint.left, + ps.rcPaint.top, + SRCCOPY)) { + LPVOID lpMsgBuf; + + /* Display an error message */ + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, 0, NULL); + + ErrorF("winBltExposedRegionsShadowGDI - BitBlt failed: %s\n", + (LPSTR) lpMsgBuf); + LocalFree(lpMsgBuf); + } /* EndPaint frees the DC */ EndPaint(pScreenPriv->hwndScreen, &ps); @@ -777,6 +805,124 @@ 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); + winPrivPixmapPtr pPixmapPriv = winGetPixmapPriv(pPixmap); + + /* window pixmap format is the same as the screen pixmap */ + assert(pPixmap->drawable.bitsPerPixel > 8); + + /* Get the window bitmap from the pixmap */ + hBitmap = pPixmapPriv->hBitmap; + + /* XXX: There may be a need for a slow-path here: If hBitmap is NULL, we + should fall-back to creating a Windows DIB from the pixmap, then + deleting it after the BitBlt. */ + + /* 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", + (unsigned int)GetLastError()); + + /* Release DC */ + DeleteDC(hdcPixmap); + } + 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 */ @@ -1119,6 +1265,7 @@ winSetEngineFunctionsShadowGDI(ScreenPtr pScreen) pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowWindowed; pScreenPriv->pwinFinishScreenInit = winFinishScreenInitFB; pScreenPriv->pwinBltExposedRegions = winBltExposedRegionsShadowGDI; + pScreenPriv->pwinBltExposedWindowRegion = winBltExposedWindowRegionShadowGDI; pScreenPriv->pwinActivateApp = winActivateAppShadowGDI; pScreenPriv->pwinRedrawScreen = winRedrawScreenShadowGDI; pScreenPriv->pwinRealizeInstalledPalette = diff --git a/hw/xwin/wintrayicon.c b/hw/xwin/wintrayicon.c index a22ca24f2..5d1e6aefa 100644 --- a/hw/xwin/wintrayicon.c +++ b/hw/xwin/wintrayicon.c @@ -115,11 +115,6 @@ winHandleIconMessage(HWND hwnd, UINT message, case WM_LBUTTONUP: /* Restack and bring all windows to top */ SetForegroundWindow (pScreenPriv->hwndScreen); - -#ifdef XWIN_MULTIWINDOWEXTWM - if (pScreenInfo->fMWExtWM) - winMWExtWMRestackWindows(pScreenInfo->pScreen); -#endif break; case WM_LBUTTONDBLCLK: diff --git a/hw/xwin/winvalargs.c b/hw/xwin/winvalargs.c index 50587d4b3..008c111a6 100644 --- a/hw/xwin/winvalargs.c +++ b/hw/xwin/winvalargs.c @@ -80,7 +80,7 @@ winValidateArgs(void) for (i = 0; i < g_iNumScreens; ++i) { /* * Check for any combination of - * -multiwindow, -mwextwm, and -rootless. + * -multiwindow and -rootless. */ { int iCount = 0; @@ -88,10 +88,7 @@ winValidateArgs(void) /* Count conflicting options */ if (g_ScreenInfo[i].fMultiWindow) ++iCount; -#ifdef XWIN_MULTIWINDOWEXTWM - if (g_ScreenInfo[i].fMWExtWM) - ++iCount; -#endif + if (g_ScreenInfo[i].fRootless) ++iCount; @@ -101,52 +98,42 @@ winValidateArgs(void) /* Fail if two or more conflicting options */ if (iCount > 1) { - ErrorF("winValidateArgs - Only one of -multiwindow, -mwextwm, " + ErrorF("winValidateArgs - Only one of -multiwindow " "and -rootless can be specific at a time.\n"); return FALSE; } } - /* Check for -multiwindow or -mwextwm and Xdmcp */ + /* Check for -multiwindow and Xdmcp */ /* allow xdmcp if screen 0 is normal. */ if (g_fXdmcpEnabled && !fHasNormalScreen0 && (FALSE || g_ScreenInfo[i]. fMultiWindow -#ifdef XWIN_MULTIWINDOWEXTWM - || g_ScreenInfo[i]. - fMWExtWM -#endif ) ) { ErrorF("winValidateArgs - Xdmcp (-query, -broadcast, or -indirect) " - "is invalid with -multiwindow or -mwextwm.\n"); + "is invalid with -multiwindow.\n"); return FALSE; } - /* Check for -multiwindow, -mwextwm, or -rootless and -fullscreen */ + /* Check for -multiwindow or -rootless and -fullscreen */ if (g_ScreenInfo[i].fFullScreen && (FALSE || g_ScreenInfo[i].fMultiWindow -#ifdef XWIN_MULTIWINDOWEXTWM - || g_ScreenInfo[i].fMWExtWM -#endif || g_ScreenInfo[i].fRootless) ) { ErrorF("winValidateArgs - -fullscreen is invalid with " - "-multiwindow, -mwextwm, or -rootless.\n"); + "-multiwindow or -rootless.\n"); return FALSE; } - /* Check for -multiwindow, -mwextwm, or -rootless and -nodecoration */ + /* Check for -multiwindow or -rootless and -nodecoration */ if (!g_ScreenInfo[i].fDecoration && (FALSE || g_ScreenInfo[i].fMultiWindow -#ifdef XWIN_MULTIWINDOWEXTWM - || g_ScreenInfo[i].fMWExtWM -#endif || g_ScreenInfo[i].fRootless) ) { ErrorF("winValidateArgs - -nodecoration is invalid with " - "-multiwindow, -mwextwm, or -rootless.\n"); + "-multiwindow or -rootless.\n"); return FALSE; } @@ -168,6 +155,14 @@ winValidateArgs(void) "-scrollbars, -resize, -nodecoration, or -lesspointer.\n"); return FALSE; } + + /* Ignore -swcursor if -multiwindow -compositewm is requested */ + if (g_ScreenInfo[i].fMultiWindow && g_ScreenInfo[i].fCompositeWM) { + if (g_fSoftwareCursor) { + g_fSoftwareCursor = FALSE; + winMsg(X_WARNING, "Ignoring -swcursor due to -compositewm\n"); + } + } } winDebug("winValidateArgs - Returning.\n"); diff --git a/hw/xwin/winwin32rootless.c b/hw/xwin/winwin32rootless.c deleted file mode 100644 index 52806887f..000000000 --- a/hw/xwin/winwin32rootless.c +++ /dev/null @@ -1,965 +0,0 @@ -/* - *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: Kensuke Matsuzaki - * Earle F. Philhower, III - * Harold L Hunt II - */ -/* - * Look at hw/darwin/quartz/xpr/xprFrame.c and hw/darwin/quartz/cr/crFrame.c - */ -#ifdef HAVE_XWIN_CONFIG_H -#include <xwin-config.h> -#endif -#include "win.h" -#include <winuser.h> -#define _WINDOWSWM_SERVER_ -#include <X11/extensions/windowswmstr.h> -#include "winmultiwindowclass.h" -#include "winmultiwindowicons.h" -#include <X11/Xatom.h> - -/* - * Constant defines - */ - -#ifndef ULW_COLORKEY -#define ULW_COLORKEY 0x00000001 -#endif -#ifndef ULW_ALPHA -#define ULW_ALPHA 0x00000002 -#endif -#ifndef ULW_OPAQUE -#define ULW_OPAQUE 0x00000004 -#endif -#define AC_SRC_ALPHA 0x01 - -/* - * Local function - */ - -DEFINE_ATOM_HELPER(AtmWindowsWmNativeHwnd, WINDOWSWM_NATIVE_HWND) -static void -winMWExtWMSetNativeProperty(RootlessWindowPtr pFrame); - -/* - * Global variables - */ - -Bool g_fNoConfigureWindow = FALSE; - -/* - * Internal function to get the DIB format that is compatible with the screen - * Fixme: Share code with winshadgdi.c - */ - -static -Bool -winMWExtWMQueryDIBFormat(win32RootlessWindowPtr pRLWinPriv, - BITMAPINFOHEADER * pbmih) -{ - HBITMAP hbmp; - -#if CYGMULTIWINDOW_DEBUG - LPDWORD pdw = NULL; -#endif - - /* Create a memory bitmap compatible with the screen */ - hbmp = CreateCompatibleBitmap(pRLWinPriv->hdcScreen, 1, 1); - if (hbmp == NULL) { - ErrorF("winMWExtWMQueryDIBFormat - CreateCompatibleBitmap failed\n"); - return FALSE; - } - - /* Initialize our bitmap info header */ - ZeroMemory(pbmih, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)); - pbmih->biSize = sizeof(BITMAPINFOHEADER); - - /* Get the biBitCount */ - if (!GetDIBits(pRLWinPriv->hdcScreen, - hbmp, 0, 1, NULL, (BITMAPINFO *) pbmih, DIB_RGB_COLORS)) { - ErrorF("winMWExtWMQueryDIBFormat - First call to GetDIBits failed\n"); - DeleteObject(hbmp); - return FALSE; - } - -#if CYGMULTIWINDOW_DEBUG - /* Get a pointer to bitfields */ - pdw = (DWORD *) ((CARD8 *) pbmih + sizeof(BITMAPINFOHEADER)); - - winDebug("winMWExtWMQueryDIBFormat - First call masks: %08x %08x %08x\n", - (unsigned int) pdw[0], (unsigned int) pdw[1], - (unsigned int) pdw[2]); -#endif - - /* Get optimal color table, or the optimal bitfields */ - if (!GetDIBits(pRLWinPriv->hdcScreen, - hbmp, 0, 1, NULL, (BITMAPINFO *) pbmih, DIB_RGB_COLORS)) { - ErrorF("winMWExtWMQueryDIBFormat - Second call to GetDIBits " - "failed\n"); - DeleteObject(hbmp); - return FALSE; - } - - /* Free memory */ - DeleteObject(hbmp); - - return TRUE; -} - -static HRGN -winMWExtWMCreateRgnFromRegion(RegionPtr pShape) -{ - int nRects; - BoxPtr pRects, pEnd; - HRGN hRgn, hRgnRect; - - if (pShape == NULL) - return NULL; - - nRects = RegionNumRects(pShape); - pRects = RegionRects(pShape); - - hRgn = CreateRectRgn(0, 0, 0, 0); - if (hRgn == NULL) { - ErrorF("winReshape - Initial CreateRectRgn (%d, %d, %d, %d) " - "failed: %d\n", 0, 0, 0, 0, (int) GetLastError()); - } - - /* Loop through all rectangles in the X region */ - for (pEnd = pRects + nRects; pRects < pEnd; pRects++) { - /* Create a Windows region for the X rectangle */ - hRgnRect = CreateRectRgn(pRects->x1, - pRects->y1, pRects->x2, pRects->y2); - if (hRgnRect == NULL) { - ErrorF("winReshape - Loop CreateRectRgn (%d, %d, %d, %d) " - "failed: %d\n", - pRects->x1, - pRects->y1, pRects->x2, pRects->y2, (int) GetLastError()); - } - - /* Merge the Windows region with the accumulated region */ - if (CombineRgn(hRgn, hRgn, hRgnRect, RGN_OR) == ERROR) { - ErrorF("winReshape - CombineRgn () failed: %d\n", - (int) GetLastError()); - } - - /* Delete the temporary Windows region */ - DeleteObject(hRgnRect); - } - - return hRgn; -} - -static void -InitWin32RootlessEngine(win32RootlessWindowPtr pRLWinPriv) -{ - pRLWinPriv->hdcScreen = GetDC(pRLWinPriv->hWnd); - pRLWinPriv->hdcShadow = CreateCompatibleDC(pRLWinPriv->hdcScreen); - pRLWinPriv->hbmpShadow = NULL; - - /* Allocate bitmap info header */ - pRLWinPriv->pbmihShadow = - malloc(sizeof(BITMAPINFOHEADER) - + 256 * sizeof(RGBQUAD)); - if (pRLWinPriv->pbmihShadow == NULL) { - ErrorF("InitWin32RootlessEngine - malloc () failed\n"); - return; - } - - /* Query the screen format */ - winMWExtWMQueryDIBFormat(pRLWinPriv, pRLWinPriv->pbmihShadow); -} - -Bool -winMWExtWMCreateFrame(RootlessWindowPtr pFrame, ScreenPtr pScreen, - int newX, int newY, RegionPtr pShape) -{ -#define CLASS_NAME_LENGTH 512 - Bool fResult = TRUE; - win32RootlessWindowPtr pRLWinPriv; - WNDCLASSEX wc; - char pszClass[CLASS_NAME_LENGTH], pszWindowID[12]; - HICON hIcon; - HICON hIconSmall; - char *res_name, *res_class, *res_role; - static int s_iWindowID = 0; - -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMCreateFrame %d %d - %d %d\n", - newX, newY, pFrame->width, pFrame->height); -#endif - - pRLWinPriv = malloc(sizeof(win32RootlessWindowRec)); - pRLWinPriv->pFrame = pFrame; - pRLWinPriv->pfb = NULL; - pRLWinPriv->hbmpShadow = NULL; - pRLWinPriv->hdcShadow = NULL; - pRLWinPriv->hdcScreen = NULL; - pRLWinPriv->pbmihShadow = NULL; - pRLWinPriv->fResized = TRUE; - pRLWinPriv->fClose = FALSE; - pRLWinPriv->fRestackingNow = FALSE; - pRLWinPriv->fDestroyed = FALSE; - pRLWinPriv->fMovingOrSizing = FALSE; - - // Store the implementation private frame ID - pFrame->wid = (RootlessFrameID) pRLWinPriv; - - winSelectIcons(&hIcon, &hIconSmall); - - /* Set standard class name prefix so we can identify window easily */ - strncpy(pszClass, WINDOW_CLASS_X, sizeof(pszClass)); - - if (winMultiWindowGetClassHint(pFrame->win, &res_name, &res_class)) { - strncat(pszClass, "-", 1); - strncat(pszClass, res_name, CLASS_NAME_LENGTH - strlen(pszClass)); - strncat(pszClass, "-", 1); - strncat(pszClass, res_class, CLASS_NAME_LENGTH - strlen(pszClass)); - - /* Check if a window class is provided by the WM_WINDOW_ROLE property, - * if not use the WM_CLASS information. - * For further information see: - * http://tronche.com/gui/x/icccm/sec-5.html - */ - if (winMultiWindowGetWindowRole(pFrame->win, &res_role)) { - strcat(pszClass, "-"); - strcat(pszClass, res_role); - free(res_role); - } - - free(res_name); - free(res_class); - } - - /* Add incrementing window ID to make unique class name */ - snprintf(pszWindowID, sizeof(pszWindowID), "-%x", s_iWindowID++); - pszWindowID[sizeof(pszWindowID) - 1] = 0; - strcat(pszClass, pszWindowID); - -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMCreateFrame - Creating class: %s\n", pszClass); -#endif - - /* Setup our window class */ - wc.cbSize = sizeof(wc); - wc.style = CS_HREDRAW | CS_VREDRAW; - wc.lpfnWndProc = winMWExtWMWindowProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = g_hInstance; - wc.hIcon = hIcon; - wc.hIconSm = hIconSmall; - wc.hCursor = 0; - wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); - wc.lpszMenuName = NULL; - wc.lpszClassName = pszClass; - RegisterClassEx(&wc); - - /* Create the window */ - g_fNoConfigureWindow = TRUE; - pRLWinPriv->hWnd = CreateWindowExA(WS_EX_TOOLWINDOW, /* Extended styles */ - pszClass, /* Class name */ - WINDOW_TITLE_X, /* Window name */ - WS_POPUP | WS_CLIPCHILDREN, newX, /* Horizontal position */ - newY, /* Vertical position */ - pFrame->width, /* Right edge */ - pFrame->height, /* Bottom edge */ - (HWND) NULL, /* No parent or owner window */ - (HMENU) NULL, /* No menu */ - GetModuleHandle(NULL), /* Instance handle */ - pRLWinPriv); /* ScreenPrivates */ - if (pRLWinPriv->hWnd == NULL) { - ErrorF("winMWExtWMCreateFrame - CreateWindowExA () failed: %d\n", - (int) GetLastError()); - fResult = FALSE; - } - -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMCreateFrame - ShowWindow\n"); -#endif - - //ShowWindow (pRLWinPriv->hWnd, SW_SHOWNOACTIVATE); - g_fNoConfigureWindow = FALSE; - - if (pShape != NULL) { - winMWExtWMReshapeFrame(pFrame->wid, pShape); - } - -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMCreateFrame - (%p) %p\n", - pFrame->wid, pRLWinPriv->hWnd); -#if 0 - { - WindowPtr pWin2 = NULL; - win32RootlessWindowPtr pRLWinPriv2 = NULL; - - /* Check if the Windows window property for our X window pointer is valid */ - if ((pWin2 = - (WindowPtr) GetProp(pRLWinPriv->hWnd, WIN_WINDOW_PROP)) != NULL) { - pRLWinPriv2 = - (win32RootlessWindowPtr) RootlessFrameForWindow(pWin2, FALSE); - } - winDebug("winMWExtWMCreateFrame2 (%08x) %08x\n", - pRLWinPriv2, pRLWinPriv2->hWnd); - if (pRLWinPriv != pRLWinPriv2 || pRLWinPriv->hWnd != pRLWinPriv2->hWnd) { - winDebug("Error param missmatch\n"); - } - } -#endif -#endif - - winMWExtWMSetNativeProperty(pFrame); - - return fResult; -} - -void -winMWExtWMDestroyFrame(RootlessFrameID wid) -{ - win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) wid; - HICON hIcon; - HICON hIconSm; - HMODULE hInstance; - int iReturn; - char pszClass[CLASS_NAME_LENGTH]; - -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMDestroyFrame (%p) %p\n", - pRLWinPriv, pRLWinPriv->hWnd); -#if 0 - { - WindowPtr pWin2 = NULL; - win32RootlessWindowPtr pRLWinPriv2 = NULL; - - /* Check if the Windows window property for our X window pointer is valid */ - if ((pWin2 = - (WindowPtr) GetProp(pRLWinPriv->hWnd, WIN_WINDOW_PROP)) != NULL) { - pRLWinPriv2 = - (win32RootlessWindowPtr) RootlessFrameForWindow(pWin2, FALSE); - } - winDebug("winMWExtWMDestroyFrame2 (%08x) %08x\n", - pRLWinPriv2, pRLWinPriv2->hWnd); - if (pRLWinPriv != pRLWinPriv2 || pRLWinPriv->hWnd != pRLWinPriv2->hWnd) { - winDebug("Error param missmatch\n"); - *(int *) 0 = 1; //raise exseption - } - } -#endif -#endif - - /* Store the info we need to destroy after this window is gone */ - hInstance = (HINSTANCE) GetClassLongPtr(pRLWinPriv->hWnd, GCLP_HMODULE); - hIcon = (HICON) SendMessage(pRLWinPriv->hWnd, WM_GETICON, ICON_BIG, 0); - hIconSm = (HICON) SendMessage(pRLWinPriv->hWnd, WM_GETICON, ICON_SMALL, 0); - iReturn = GetClassName(pRLWinPriv->hWnd, pszClass, CLASS_NAME_LENGTH); - - pRLWinPriv->fClose = TRUE; - pRLWinPriv->fDestroyed = TRUE; - - /* Destroy the Windows window */ - DestroyWindow(pRLWinPriv->hWnd); - - /* Only if we were able to get the name */ - if (iReturn) { -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMDestroyFrame - Unregistering %s: ", pszClass); -#endif - iReturn = UnregisterClass(pszClass, hInstance); - } - -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMDestroyFramew - Deleting Icon\n"); -#endif - - winDestroyIcon(hIcon); - winDestroyIcon(hIconSm); - -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMDestroyFrame - done\n"); -#endif -} - -void -winMWExtWMMoveFrame(RootlessFrameID wid, ScreenPtr pScreen, int iNewX, - int iNewY) -{ - win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) wid; - RECT rcNew; - DWORD dwExStyle; - DWORD dwStyle; - int iX, iY, iWidth, iHeight; - -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMMoveFrame (%p) (%d %d)\n", pRLWinPriv, iNewX, - iNewY); -#endif - - /* Get the Windows window style and extended style */ - dwExStyle = GetWindowLongPtr(pRLWinPriv->hWnd, GWL_EXSTYLE); - dwStyle = GetWindowLongPtr(pRLWinPriv->hWnd, GWL_STYLE); - - /* Get the X and Y location of the X window */ - iX = iNewX + GetSystemMetrics(SM_XVIRTUALSCREEN); - iY = iNewY + GetSystemMetrics(SM_YVIRTUALSCREEN); - - /* Get the height and width of the X window */ - iWidth = pRLWinPriv->pFrame->width; - iHeight = pRLWinPriv->pFrame->height; - - /* Store the origin, height, and width in a rectangle structure */ - SetRect(&rcNew, iX, iY, iX + iWidth, iY + iHeight); - -#ifdef CYGMULTIWINDOW_DEBUG - winDebug("\tWindow {%d, %d, %d, %d}, {%d, %d}\n", - rcNew.left, rcNew.top, rcNew.right, rcNew.bottom, - rcNew.right - rcNew.left, rcNew.bottom - rcNew.top); -#endif - /* - * Calculate the required size of the Windows window rectangle, - * given the size of the Windows window client area. - */ - AdjustWindowRectEx(&rcNew, dwStyle, FALSE, dwExStyle); - -#ifdef CYGMULTIWINDOW_DEBUG - winDebug("\tAdjusted {%d, %d, %d, %d}, {%d, %d}\n", - rcNew.left, rcNew.top, rcNew.right, rcNew.bottom, - rcNew.right - rcNew.left, rcNew.bottom - rcNew.top); -#endif - g_fNoConfigureWindow = TRUE; - SetWindowPos(pRLWinPriv->hWnd, NULL, rcNew.left, rcNew.top, 0, 0, - SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER); - g_fNoConfigureWindow = FALSE; -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMMoveFrame (%p) done\n", pRLWinPriv); -#endif -} - -void -winMWExtWMResizeFrame(RootlessFrameID wid, ScreenPtr pScreen, - int iNewX, int iNewY, - unsigned int uiNewWidth, unsigned int uiNewHeight, - unsigned int uiGravity) -{ - win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) wid; - RECT rcNew; - RECT rcOld; - DWORD dwExStyle; - DWORD dwStyle; - int iX, iY; - -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMResizeFrame (%p) (%d %d)-(%d %d)\n", - pRLWinPriv, iNewX, iNewY, uiNewWidth, uiNewHeight); -#endif - - pRLWinPriv->fResized = TRUE; - - /* Get the Windows window style and extended style */ - dwExStyle = GetWindowLongPtr(pRLWinPriv->hWnd, GWL_EXSTYLE); - dwStyle = GetWindowLongPtr(pRLWinPriv->hWnd, GWL_STYLE); - - /* Get the X and Y location of the X window */ - iX = iNewX + GetSystemMetrics(SM_XVIRTUALSCREEN); - iY = iNewY + GetSystemMetrics(SM_YVIRTUALSCREEN); - - /* Store the origin, height, and width in a rectangle structure */ - SetRect(&rcNew, iX, iY, iX + uiNewWidth, iY + uiNewHeight); - - /* - * Calculate the required size of the Windows window rectangle, - * given the size of the Windows window client area. - */ - AdjustWindowRectEx(&rcNew, dwStyle, FALSE, dwExStyle); - - /* Get a rectangle describing the old Windows window */ - GetWindowRect(pRLWinPriv->hWnd, &rcOld); - - /* Check if the old rectangle and new rectangle are the same */ - if (!EqualRect(&rcNew, &rcOld)) { - - g_fNoConfigureWindow = TRUE; - MoveWindow(pRLWinPriv->hWnd, - rcNew.left, rcNew.top, - rcNew.right - rcNew.left, rcNew.bottom - rcNew.top, TRUE); - g_fNoConfigureWindow = FALSE; - } -} - -void -winMWExtWMRestackFrame(RootlessFrameID wid, RootlessFrameID nextWid) -{ - win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) wid; - win32RootlessWindowPtr pRLNextWinPriv = (win32RootlessWindowPtr) nextWid; - - winScreenPriv(pRLWinPriv->pFrame->win->drawable.pScreen); - -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMRestackFrame (%p)\n", pRLWinPriv); -#endif - - if (pScreenPriv && pScreenPriv->fRestacking) - return; - - pRLWinPriv->fRestackingNow = TRUE; - - /* Show window */ - if (!IsWindowVisible(pRLWinPriv->hWnd)) - ShowWindow(pRLWinPriv->hWnd, SW_SHOWNOACTIVATE); - - if (pRLNextWinPriv == NULL) { -#if CYGMULTIWINDOW_DEBUG - winDebug("Win %p is top\n", pRLWinPriv); -#endif - pScreenPriv->widTop = wid; - SetWindowPos(pRLWinPriv->hWnd, HWND_TOP, - 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); - } - else { - /* using general wm like twm, wmaker etc. - Interleave X window and Windows window will cause problem. */ - SetWindowPos(pRLWinPriv->hWnd, pRLNextWinPriv->hWnd, - 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); - } -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMRestackFrame - done (%p)\n", pRLWinPriv); -#endif - - pRLWinPriv->fRestackingNow = FALSE; -} - -void -winMWExtWMReshapeFrame(RootlessFrameID wid, RegionPtr pShape) -{ - win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) wid; - HRGN hRgn, hRgnWindow, hRgnClient; - RECT rcWindow, rcClient; - -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMReshapeFrame (%p)\n", pRLWinPriv); -#endif - - hRgn = winMWExtWMCreateRgnFromRegion(pShape); - - /* Create region for non-client area */ - GetWindowRect(pRLWinPriv->hWnd, &rcWindow); - GetClientRect(pRLWinPriv->hWnd, &rcClient); - MapWindowPoints(pRLWinPriv->hWnd, HWND_DESKTOP, (LPPOINT) &rcClient, 2); - OffsetRgn(hRgn, rcClient.left - rcWindow.left, rcClient.top - rcWindow.top); - OffsetRect(&rcClient, -rcWindow.left, -rcWindow.top); - OffsetRect(&rcWindow, -rcWindow.left, -rcWindow.top); - hRgnWindow = CreateRectRgnIndirect(&rcWindow); - hRgnClient = CreateRectRgnIndirect(&rcClient); - CombineRgn(hRgnWindow, hRgnWindow, hRgnClient, RGN_DIFF); - CombineRgn(hRgn, hRgnWindow, hRgn, RGN_OR); - - SetWindowRgn(pRLWinPriv->hWnd, hRgn, TRUE); - - DeleteObject(hRgnWindow); - DeleteObject(hRgnClient); -} - -void -winMWExtWMUnmapFrame(RootlessFrameID wid) -{ - win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) wid; - -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMUnmapFrame (%p)\n", pRLWinPriv); -#endif - - g_fNoConfigureWindow = TRUE; - //ShowWindow (pRLWinPriv->hWnd, SW_MINIMIZE); - ShowWindow(pRLWinPriv->hWnd, SW_HIDE); - g_fNoConfigureWindow = FALSE; -} - -/* - * Fixme: Code sharing with winshadgdi.c and other engine support - */ -void -winMWExtWMStartDrawing(RootlessFrameID wid, char **pixelData, int *bytesPerRow) -{ - win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) wid; - winPrivScreenPtr pScreenPriv = NULL; - winScreenInfo *pScreenInfo = NULL; - ScreenPtr pScreen = NULL; - DIBSECTION dibsection; - Bool fReturn = TRUE; - HDC hdcNew; - HBITMAP hbmpNew; - -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMStartDrawing (%p) %08x\n", pRLWinPriv, - pRLWinPriv->fDestroyed); -#endif - - if (!pRLWinPriv->fDestroyed) { - pScreen = pRLWinPriv->pFrame->win->drawable.pScreen; - if (pScreen) - pScreenPriv = winGetScreenPriv(pScreen); - if (pScreenPriv) - pScreenInfo = pScreenPriv->pScreenInfo; - -#if CYGMULTIWINDOW_DEBUG - winDebug("\tpScreenPriv %p\n", pScreenPriv); - winDebug("\tpScreenInfo %p\n", pScreenInfo); - winDebug("\t(%d, %d)\n", (int) pRLWinPriv->pFrame->width, - (int) pRLWinPriv->pFrame->height); -#endif - if (pRLWinPriv->hdcScreen == NULL) { - InitWin32RootlessEngine(pRLWinPriv); - } - - if (pRLWinPriv->fResized) { - /* width * bpp must be multiple of 4 to match 32bit alignment */ - int stridesize; - int misalignment; - - pRLWinPriv->pbmihShadow->biWidth = pRLWinPriv->pFrame->width; - pRLWinPriv->pbmihShadow->biHeight = -pRLWinPriv->pFrame->height; - - stridesize = pRLWinPriv->pFrame->width * (pScreenInfo->dwBPP >> 3); - misalignment = stridesize & 3; - if (misalignment != 0) { - stridesize += 4 - misalignment; - pRLWinPriv->pbmihShadow->biWidth = - stridesize / (pScreenInfo->dwBPP >> 3); - winDebug("\tresizing to %d (was %d)\n", - pRLWinPriv->pbmihShadow->biWidth, - pRLWinPriv->pFrame->width); - } - - hdcNew = CreateCompatibleDC(pRLWinPriv->hdcScreen); - /* Create a DI shadow bitmap with a bit pointer */ - hbmpNew = CreateDIBSection(pRLWinPriv->hdcScreen, - (BITMAPINFO *) pRLWinPriv->pbmihShadow, - DIB_RGB_COLORS, - (VOID **) &pRLWinPriv->pfb, NULL, 0); - if (hbmpNew == NULL || pRLWinPriv->pfb == NULL) { - ErrorF("winMWExtWMStartDrawing - CreateDIBSection failed\n"); - //return FALSE; - } - else { -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMStartDrawing - Shadow buffer allocated\n"); -#endif - } - - /* Get information about the bitmap that was allocated */ - GetObject(hbmpNew, sizeof(dibsection), &dibsection); - -#if CYGMULTIWINDOW_DEBUG - /* Print information about bitmap allocated */ - winDebug("winMWExtWMStartDrawing - Dibsection width: %d height: %d " - "depth: %d size image: %d\n", - (unsigned int) dibsection.dsBmih.biWidth, - (unsigned int) dibsection.dsBmih.biHeight, - (unsigned int) dibsection.dsBmih.biBitCount, - (unsigned int) dibsection.dsBmih.biSizeImage); -#endif - - /* Select the shadow bitmap into the shadow DC */ - SelectObject(hdcNew, hbmpNew); - -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMStartDrawing - Attempting a shadow blit\n"); -#endif - - /* Blit from the old shadow to the new shadow */ - fReturn = BitBlt(hdcNew, - 0, 0, - pRLWinPriv->pFrame->width, - pRLWinPriv->pFrame->height, pRLWinPriv->hdcShadow, - 0, 0, SRCCOPY); - if (fReturn) { -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMStartDrawing - Shadow blit success\n"); -#endif - } - else { - ErrorF("winMWExtWMStartDrawing - Shadow blit failure\n"); - } - - /* Look for height weirdness */ - if (dibsection.dsBmih.biHeight < 0) { - /* FIXME: Figure out why biHeight is sometimes negative */ - ErrorF("winMWExtWMStartDrawing - WEIRDNESS - " - "biHeight still negative: %d\n", - (int) dibsection.dsBmih.biHeight); - ErrorF("winMWExtWMStartDrawing - WEIRDNESS - " - "Flipping biHeight sign\n"); - dibsection.dsBmih.biHeight = -dibsection.dsBmih.biHeight; - } - - pRLWinPriv->dwWidthBytes = dibsection.dsBm.bmWidthBytes; - -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMStartDrawing - bytesPerRow: %d\n", - (unsigned int) dibsection.dsBm.bmWidthBytes); -#endif - - /* Free the old shadow bitmap */ - DeleteObject(pRLWinPriv->hdcShadow); - DeleteObject(pRLWinPriv->hbmpShadow); - - pRLWinPriv->hdcShadow = hdcNew; - pRLWinPriv->hbmpShadow = hbmpNew; - - pRLWinPriv->fResized = FALSE; -#if CYGMULTIWINDOW_DEBUG && FALSE - winDebug("winMWExtWMStartDrawing - 0x%08x %d\n", - (unsigned int) pRLWinPriv->pfb, - (unsigned int) dibsection.dsBm.bmWidthBytes); -#endif - } - } - else { - ErrorF("winMWExtWMStartDrawing - Already window was destroyed \n"); - } -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMStartDrawing - done (%p) %p %d\n", - pRLWinPriv, - pRLWinPriv->pfb, - (unsigned int) pRLWinPriv->dwWidthBytes); -#endif - *pixelData = pRLWinPriv->pfb; - *bytesPerRow = pRLWinPriv->dwWidthBytes; -} - -void -winMWExtWMStopDrawing(RootlessFrameID wid, Bool fFlush) -{ -#if 0 - win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) wid; - BLENDFUNCTION bfBlend; - SIZE szWin; - POINT ptSrc; - -#if CYGMULTIWINDOW_DEBUG || TRUE - winDebug("winMWExtWMStopDrawing (%08x)\n", pRLWinPriv); -#endif - szWin.cx = pRLWinPriv->dwWidth; - szWin.cy = pRLWinPriv->dwHeight; - ptSrc.x = 0; - ptSrc.y = 0; - bfBlend.BlendOp = AC_SRC_OVER; - bfBlend.BlendFlags = 0; - bfBlend.SourceConstantAlpha = 255; - bfBlend.AlphaFormat = AC_SRC_ALPHA; - - if (!UpdateLayeredWindow(pRLWinPriv->hWnd, - NULL, NULL, &szWin, - pRLWinPriv->hdcShadow, &ptSrc, - 0, &bfBlend, ULW_ALPHA)) { - ErrorF("winMWExtWMStopDrawing - UpdateLayeredWindow failed\n"); - } -#endif -} - -void -winMWExtWMUpdateRegion(RootlessFrameID wid, RegionPtr pDamage) -{ - win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) wid; - -#if 0 - BLENDFUNCTION bfBlend; - SIZE szWin; - POINT ptSrc; -#endif -#if CYGMULTIWINDOW_DEBUG && 0 - winDebug("winMWExtWMUpdateRegion (%08x)\n", pRLWinPriv); -#endif -#if 0 - szWin.cx = pRLWinPriv->dwWidth; - szWin.cy = pRLWinPriv->dwHeight; - ptSrc.x = 0; - ptSrc.y = 0; - bfBlend.BlendOp = AC_SRC_OVER; - bfBlend.BlendFlags = 0; - bfBlend.SourceConstantAlpha = 255; - bfBlend.AlphaFormat = AC_SRC_ALPHA; - - if (!UpdateLayeredWindow(pRLWinPriv->hWnd, - NULL, NULL, &szWin, - pRLWinPriv->hdcShadow, &ptSrc, - 0, &bfBlend, ULW_ALPHA)) { - 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("winMWExtWMUpdateRegion - UpdateLayeredWindow failed: %s\n", - (LPSTR) lpMsgBuf); - LocalFree(lpMsgBuf); - } -#endif - if (!g_fNoConfigureWindow) - UpdateWindow(pRLWinPriv->hWnd); -} - -void -winMWExtWMDamageRects(RootlessFrameID wid, int nCount, const BoxRec * pRects, - int shift_x, int shift_y) -{ - win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) wid; - const BoxRec *pEnd; - -#if CYGMULTIWINDOW_DEBUG && 0 - winDebug("winMWExtWMDamageRects (%08x, %d, %08x, %d, %d)\n", - pRLWinPriv, nCount, pRects, shift_x, shift_y); -#endif - - for (pEnd = pRects + nCount; pRects < pEnd; pRects++) { - RECT rcDmg; - - rcDmg.left = pRects->x1 + shift_x; - rcDmg.top = pRects->y1 + shift_y; - rcDmg.right = pRects->x2 + shift_x; - rcDmg.bottom = pRects->y2 + shift_y; - - InvalidateRect(pRLWinPriv->hWnd, &rcDmg, FALSE); - } -} - -void -winMWExtWMRootlessSwitchWindow(RootlessWindowPtr pFrame, WindowPtr oldWin) -{ - win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) pFrame->wid; - -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMRootlessSwitchWindow (%p) %p\n", - pRLWinPriv, pRLWinPriv->hWnd); -#endif - pRLWinPriv->pFrame = pFrame; - pRLWinPriv->fResized = TRUE; - - /* Set the window extended style flags */ - SetWindowLongPtr(pRLWinPriv->hWnd, GWL_EXSTYLE, WS_EX_TOOLWINDOW); - - /* Set the window standard style flags */ - SetWindowLongPtr(pRLWinPriv->hWnd, GWL_STYLE, WS_POPUP | WS_CLIPCHILDREN); - - DeleteProperty(serverClient, oldWin, AtmWindowsWmNativeHwnd()); - winMWExtWMSetNativeProperty(pFrame); -#if CYGMULTIWINDOW_DEBUG -#if 0 - { - WindowPtr pWin2 = NULL; - win32RootlessWindowPtr pRLWinPriv2 = NULL; - - /* Check if the Windows window property for our X window pointer is valid */ - if ((pWin2 = - (WindowPtr) GetProp(pRLWinPriv->hWnd, WIN_WINDOW_PROP)) != NULL) { - pRLWinPriv2 = - (win32RootlessWindowPtr) RootlessFrameForWindow(pWin2, FALSE); - } - winDebug("winMWExtWMSwitchFrame2 (%08x) %08x\n", - pRLWinPriv2, pRLWinPriv2->hWnd); - if (pRLWinPriv != pRLWinPriv2 || pRLWinPriv->hWnd != pRLWinPriv2->hWnd) { - winDebug("Error param missmatch\n"); - } - } -#endif -#endif -} - -void -winMWExtWMCopyBytes(unsigned int width, unsigned int height, - const void *src, unsigned int srcRowBytes, - void *dst, unsigned int dstRowBytes) -{ -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMCopyBytes - Not implemented\n"); -#endif -} - -void -winMWExtWMCopyWindow(RootlessFrameID wid, int nDstRects, - const BoxRec * pDstRects, int nDx, int nDy) -{ - win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) wid; - const BoxRec *pEnd; - RECT rcDmg; - -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMCopyWindow (%p, %d, %p, %d, %d)\n", - pRLWinPriv, nDstRects, pDstRects, nDx, nDy); -#endif - - for (pEnd = pDstRects + nDstRects; pDstRects < pEnd; pDstRects++) { -#if CYGMULTIWINDOW_DEBUG - winDebug("BitBlt (%d, %d, %d, %d) (%d, %d)\n", - pDstRects->x1, pDstRects->y1, - pDstRects->x2 - pDstRects->x1, - pDstRects->y2 - pDstRects->y1, - pDstRects->x1 + nDx, pDstRects->y1 + nDy); -#endif - - if (!BitBlt(pRLWinPriv->hdcShadow, - pDstRects->x1, pDstRects->y1, - pDstRects->x2 - pDstRects->x1, - pDstRects->y2 - pDstRects->y1, - pRLWinPriv->hdcShadow, - pDstRects->x1 + nDx, pDstRects->y1 + nDy, SRCCOPY)) { - ErrorF("winMWExtWMCopyWindow - BitBlt failed.\n"); - } - - rcDmg.left = pDstRects->x1; - rcDmg.top = pDstRects->y1; - rcDmg.right = pDstRects->x2; - rcDmg.bottom = pDstRects->y2; - - InvalidateRect(pRLWinPriv->hWnd, &rcDmg, FALSE); - } -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMCopyWindow - done\n"); -#endif -} - -/* - * winMWExtWMSetNativeProperty - */ - -static void -winMWExtWMSetNativeProperty(RootlessWindowPtr pFrame) -{ - win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) pFrame->wid; - long lData; - - /* FIXME: move this to WindowsWM extension */ - - lData = (long) pRLWinPriv->hWnd; - dixChangeWindowProperty(serverClient, pFrame->win, AtmWindowsWmNativeHwnd(), - XA_INTEGER, 32, PropModeReplace, 1, &lData, TRUE); -} diff --git a/hw/xwin/winwin32rootlesswindow.c b/hw/xwin/winwin32rootlesswindow.c deleted file mode 100644 index 817cd093e..000000000 --- a/hw/xwin/winwin32rootlesswindow.c +++ /dev/null @@ -1,420 +0,0 @@ -/* - *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: Kensuke Matsuzaki - * Earle F. Philhower, III - * Harold L Hunt II - */ - -#ifdef HAVE_XWIN_CONFIG_H -#include <xwin-config.h> -#endif -#include "win.h" -#include "winprefs.h" - -#if 0 -/* - * winMWExtWMReorderWindows - */ - -void -winMWExtWMReorderWindows(ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - HWND hwnd = NULL; - win32RootlessWindowPtr pRLWin = NULL; - win32RootlessWindowPtr pRLWinSib = NULL; - DWORD dwCurrentProcessID = GetCurrentProcessId(); - DWORD dwWindowProcessID = 0; - XID vlist[2]; - -#if CYGMULTIWINDOW_DEBUG && FALSE - winDebug("winMWExtWMReorderWindows\n"); -#endif - - pScreenPriv->fRestacking = TRUE; - - if (pScreenPriv->fWindowOrderChanged) { -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMReorderWindows - Need to restack\n"); -#endif - hwnd = GetTopWindow(NULL); - - while (hwnd) { - GetWindowThreadProcessId(hwnd, &dwWindowProcessID); - - if ((dwWindowProcessID == dwCurrentProcessID) - && GetProp(hwnd, WIN_WINDOW_PROP)) { - pRLWinSib = pRLWin; - pRLWin = - (win32RootlessWindowPtr) GetProp(hwnd, WIN_WINDOW_PROP); - - if (pRLWinSib) { - vlist[0] = pRLWinSib->pFrame->win->drawable.id; - vlist[1] = Below; - - ConfigureWindow(pRLWin->pFrame->win, - CWSibling | CWStackMode, vlist, - wClient(pRLWin->pFrame->win)); - } - else { - /* 1st window - raise to the top */ - vlist[0] = Above; - - ConfigureWindow(pRLWin->pFrame->win, CWStackMode, - vlist, wClient(pRLWin->pFrame->win)); - } - } - hwnd = GetNextWindow(hwnd, GW_HWNDNEXT); - } - } - - pScreenPriv->fRestacking = FALSE; - pScreenPriv->fWindowOrderChanged = FALSE; -} -#endif - -/* - * winMWExtWMMoveXWindow - */ - -void -winMWExtWMMoveXWindow(WindowPtr pWin, int x, int y) -{ - CARD32 *vlist = malloc(sizeof(CARD32) * 2); - - vlist[0] = x; - vlist[1] = y; - ConfigureWindow(pWin, CWX | CWY, vlist, wClient(pWin)); - free(vlist); -} - -/* - * winMWExtWMResizeXWindow - */ - -void -winMWExtWMResizeXWindow(WindowPtr pWin, int w, int h) -{ - CARD32 *vlist = malloc(sizeof(CARD32) * 2); - - vlist[0] = w; - vlist[1] = h; - ConfigureWindow(pWin, CWWidth | CWHeight, vlist, wClient(pWin)); - free(vlist); -} - -/* - * winMWExtWMMoveResizeXWindow - */ - -void -winMWExtWMMoveResizeXWindow(WindowPtr pWin, int x, int y, int w, int h) -{ - CARD32 *vlist = malloc(sizeof(long) * 4); - - vlist[0] = x; - vlist[1] = y; - vlist[2] = w; - vlist[3] = h; - - ConfigureWindow(pWin, CWX | CWY | CWWidth | CWHeight, vlist, wClient(pWin)); - free(vlist); -} - -/* - - - * winMWExtWMDecorateWindow - Update window style. Called by EnumWindows. - */ - -wBOOL CALLBACK -winMWExtWMDecorateWindow(HWND hwnd, LPARAM lParam) -{ - win32RootlessWindowPtr pRLWinPriv = NULL; - ScreenPtr pScreen = NULL; - winPrivScreenPtr pScreenPriv = NULL; - winScreenInfo *pScreenInfo = NULL; - - /* Check if the Windows window property for our X window pointer is valid */ - if ((pRLWinPriv = - (win32RootlessWindowPtr) GetProp(hwnd, WIN_WINDOW_PROP)) != NULL) { - if (pRLWinPriv != NULL && pRLWinPriv->pFrame != NULL && - pRLWinPriv->pFrame->win != NULL) - pScreen = pRLWinPriv->pFrame->win->drawable.pScreen; - if (pScreen) - pScreenPriv = winGetScreenPriv(pScreen); - if (pScreenPriv) - pScreenInfo = pScreenPriv->pScreenInfo; - if (pRLWinPriv && pScreenInfo) - winMWExtWMUpdateWindowDecoration(pRLWinPriv, pScreenInfo); - } - return TRUE; -} - -/* - * winMWExtWMUpdateWindowDecoration - Update window style. - */ - -void -winMWExtWMUpdateWindowDecoration(win32RootlessWindowPtr pRLWinPriv, - winScreenInfoPtr pScreenInfo) -{ - Bool fDecorate = FALSE; - DWORD dwExStyle = 0; - WINDOWPLACEMENT wndPlace; - UINT showCmd = 0; - - wndPlace.length = sizeof(WINDOWPLACEMENT); - - /* Get current window placement */ - GetWindowPlacement(pRLWinPriv->hWnd, &wndPlace); - -#if 0 - if (wndPlace.showCmd == SW_HIDE) - return; //showCmd = SWP_HIDEWINDOW; - else - showCmd = SWP_SHOWWINDOW; -#else - if (wndPlace.showCmd == SW_HIDE) - return; - - if (IsWindowVisible(pRLWinPriv->hWnd)) - showCmd = SWP_SHOWWINDOW; -#endif - - showCmd |= SWP_NOMOVE | SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOZORDER; - - winDebug("winMWExtWMUpdateWindowDecoration %p %s\n", - pRLWinPriv, fDecorate ? "Decorate" : "Bare"); - - /* Get the extended window style information */ - dwExStyle = GetWindowLongPtr(pRLWinPriv->hWnd, GWL_EXSTYLE); - - if (fDecorate) { - RECT rcNew; - int iDx, iDy; - winWMMessageRec wmMsg; - - winScreenPriv(pScreenInfo->pScreen); - - /* */ - if (!(dwExStyle & WS_EX_APPWINDOW)) { - winDebug("\tBare=>Decorate\n"); - /* Setup a rectangle with the X window position and size */ - SetRect(&rcNew, - pRLWinPriv->pFrame->x, - pRLWinPriv->pFrame->y, - pRLWinPriv->pFrame->x + pRLWinPriv->pFrame->width, - pRLWinPriv->pFrame->y + pRLWinPriv->pFrame->height); - -#ifdef CYGMULTIWINDOW_DEBUG - winDebug("\tWindow extend {%d, %d, %d, %d}, {%d, %d}\n", - rcNew.left, rcNew.top, rcNew.right, rcNew.bottom, - rcNew.right - rcNew.left, rcNew.bottom - rcNew.top); -#endif - /* */ - AdjustWindowRectEx(&rcNew, - WS_POPUP | WS_SIZEBOX | WS_OVERLAPPEDWINDOW, - FALSE, WS_EX_APPWINDOW); - -#ifdef CYGMULTIWINDOW_DEBUG - winDebug("\tAdjusted {%d, %d, %d, %d}, {%d, %d}\n", - rcNew.left, rcNew.top, rcNew.right, rcNew.bottom, - rcNew.right - rcNew.left, rcNew.bottom - rcNew.top); -#endif - /* Calculate position deltas */ - iDx = pRLWinPriv->pFrame->x - rcNew.left; - iDy = pRLWinPriv->pFrame->y - rcNew.top; - - /* Calculate new rectangle */ - rcNew.left += iDx; - rcNew.right += iDx; - rcNew.top += iDy; - rcNew.bottom += iDy; - - /* Set the window extended style flags */ - SetWindowLongPtr(pRLWinPriv->hWnd, GWL_EXSTYLE, WS_EX_APPWINDOW); - - /* Set the window standard style flags */ - SetWindowLongPtr(pRLWinPriv->hWnd, GWL_STYLE, - WS_POPUP | WS_SIZEBOX | WS_OVERLAPPEDWINDOW); - -#ifdef CYGMULTIWINDOW_DEBUG - winDebug("\tWindowStyle: %08x %08x\n", - WS_POPUP | WS_SIZEBOX | WS_OVERLAPPEDWINDOW, - WS_EX_APPWINDOW); -#endif - /* Position the Windows window */ -#ifdef CYGMULTIWINDOW_DEBUG - winDebug("\tMoved {%d, %d, %d, %d}, {%d, %d}\n", - rcNew.left, rcNew.top, rcNew.right, rcNew.bottom, - rcNew.right - rcNew.left, rcNew.bottom - rcNew.top); -#endif - SetWindowPos(pRLWinPriv->hWnd, NULL, - rcNew.left, rcNew.top, - rcNew.right - rcNew.left, rcNew.bottom - rcNew.top, - showCmd); - - wmMsg.hwndWindow = pRLWinPriv->hWnd; - wmMsg.iWindow = (Window) pRLWinPriv->pFrame->win->drawable.id; - wmMsg.msg = WM_WM_NAME_EVENT; - winSendMessageToWM(pScreenPriv->pWMInfo, &wmMsg); - - winMWExtWMReshapeFrame((RootlessFrameID) pRLWinPriv, - wBoundingShape(pRLWinPriv->pFrame->win)); - } - } - else { - RECT rcNew; - - /* */ - if (dwExStyle & WS_EX_APPWINDOW) { - winDebug("\tDecorate=>Bare\n"); - /* Setup a rectangle with the X window position and size */ - SetRect(&rcNew, - pRLWinPriv->pFrame->x, - pRLWinPriv->pFrame->y, - pRLWinPriv->pFrame->x + pRLWinPriv->pFrame->width, - pRLWinPriv->pFrame->y + pRLWinPriv->pFrame->height); -#if 0 - /* */ - AdjustWindowRectEx(&rcNew, - WS_POPUP | WS_CLIPCHILDREN, - FALSE, WS_EX_TOOLWINDOW); - - /* Calculate position deltas */ - iDx = pRLWinPriv->pFrame->x - rcNew.left; - iDy = pRLWinPriv->pFrame->y - rcNew.top; - - /* Calculate new rectangle */ - rcNew.left += iDx; - rcNew.right += iDx; - rcNew.top += iDy; - rcNew.bottom += iDy; -#endif - - /* Hide window temporary to remove from taskbar. */ - ShowWindow(pRLWinPriv->hWnd, SW_HIDE); - - /* Set the window extended style flags */ - SetWindowLongPtr(pRLWinPriv->hWnd, GWL_EXSTYLE, WS_EX_TOOLWINDOW); - - /* Set the window standard style flags */ - SetWindowLongPtr(pRLWinPriv->hWnd, GWL_STYLE, - WS_POPUP | WS_CLIPCHILDREN); - - /* Position the Windows window */ - SetWindowPos(pRLWinPriv->hWnd, NULL, - rcNew.left, rcNew.top, - rcNew.right - rcNew.left, rcNew.bottom - rcNew.top, - showCmd); - - winMWExtWMReshapeFrame((RootlessFrameID) pRLWinPriv, - wBoundingShape(pRLWinPriv->pFrame->win)); - } - } -} - -/* - * winMWExtWMRestackWindows - */ - -void -winMWExtWMRestackWindows(ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - WindowPtr pRoot = pScreen->root; - WindowPtr pWin = NULL; - WindowPtr pWinPrev = NULL; - win32RootlessWindowPtr pRLWin = NULL; - win32RootlessWindowPtr pRLWinPrev = NULL; - int nWindow = 0; - HDWP hWinPosInfo = NULL; - -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMRestackWindows\n"); -#endif - - pScreenPriv->fRestacking = TRUE; - - if (pRoot != NULL) { - for (pWin = pRoot->firstChild; pWin; pWin = pWin->nextSib) - nWindow++; - - hWinPosInfo = BeginDeferWindowPos(nWindow); - - for (pWin = pRoot->firstChild; pWin; pWin = pWin->nextSib) { - if (pWin->realized) { - UINT uFlags; - - pRLWin = - (win32RootlessWindowPtr) RootlessFrameForWindow(pWin, - FALSE); - if (pRLWin == NULL) - continue; - - if (pWinPrev) - pRLWinPrev = - (win32RootlessWindowPtr) - RootlessFrameForWindow(pWinPrev, FALSE); - - uFlags = SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW; - if (pRLWinPrev != NULL) - uFlags |= SWP_NOACTIVATE; - -#if CYGMULTIWINDOW_DEBUG - winDebug - ("winMWExtWMRestackWindows - DeferWindowPos (%p, %p)\n", - pRLWin->hWnd, pRLWinPrev ? pRLWinPrev->hWnd : HWND_TOP); -#endif - hWinPosInfo = DeferWindowPos(hWinPosInfo, pRLWin->hWnd, - pRLWinPrev ? pRLWinPrev-> - hWnd : HWND_TOP, 0, 0, 0, 0, - uFlags); - if (hWinPosInfo == NULL) { - ErrorF - ("winMWExtWMRestackWindows - DeferWindowPos () failed: %d\n", - (int) GetLastError()); - return; - } - pWinPrev = pWin; - } - } - if (!EndDeferWindowPos(hWinPosInfo)) { - ErrorF - ("winMWExtWMRestackWindows - EndDeferWindowPos () failed: %d\n", - (int) GetLastError()); - return; - } - } - -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMRestackWindows - done\n"); -#endif - pScreenPriv->fRestacking = FALSE; -} diff --git a/hw/xwin/winwin32rootlesswndproc.c b/hw/xwin/winwin32rootlesswndproc.c deleted file mode 100644 index 5575f4ba8..000000000 --- a/hw/xwin/winwin32rootlesswndproc.c +++ /dev/null @@ -1,1080 +0,0 @@ -/* - *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: Kensuke Matsuzaki - * Earle F. Philhower, III - * Harold L Hunt II - */ -#ifdef HAVE_XWIN_CONFIG_H -#include <xwin-config.h> -#endif -#include "win.h" -#include <winuser.h> -#define _WINDOWSWM_SERVER_ -#include <X11/extensions/windowswmstr.h> -#include "dixevents.h" -#include "propertyst.h" -#include <X11/Xatom.h> -#include "winmultiwindowclass.h" -#include "winmsg.h" -#include "inputstr.h" - -/* - * Constant defines - */ - -#define MOUSE_ACTIVATE_DEFAULT TRUE -#define RAISE_ON_CLICK_DEFAULT FALSE - -/* - * Local globals - */ - -static UINT_PTR g_uipMousePollingTimerID = 0; - -/* - * Local function - */ - -DEFINE_ATOM_HELPER(AtmWindowsWMMouseActivate, WINDOWSWM_MOUSE_ACTIVATE) -/* DEFINE_ATOM_HELPER(AtmWindowsWMClientWindow, WINDOWSWM_CLIENT_WINDOW) */ - -/* - * ConstrainSize - Taken from TWM sources - Respects hints for sizing - */ -#define makemult(a,b) ((b==1) ? (a) : (((int)((a)/(b))) * (b)) ) -static void -ConstrainSize(WinXSizeHints hints, int *widthp, int *heightp) -{ - int minWidth, minHeight, maxWidth, maxHeight, xinc, yinc, delta; - int baseWidth, baseHeight; - int dwidth = *widthp, dheight = *heightp; - - if (hints.flags & PMinSize) { - minWidth = hints.min_width; - minHeight = hints.min_height; - } - else if (hints.flags & PBaseSize) { - minWidth = hints.base_width; - minHeight = hints.base_height; - } - else - minWidth = minHeight = 1; - - if (hints.flags & PBaseSize) { - baseWidth = hints.base_width; - baseHeight = hints.base_height; - } - else if (hints.flags & PMinSize) { - baseWidth = hints.min_width; - baseHeight = hints.min_height; - } - else - baseWidth = baseHeight = 0; - - if (hints.flags & PMaxSize) { - maxWidth = hints.max_width; - maxHeight = hints.max_height; - } - else { - maxWidth = MAXINT; - maxHeight = MAXINT; - } - - if (hints.flags & PResizeInc) { - xinc = hints.width_inc; - yinc = hints.height_inc; - } - else - xinc = yinc = 1; - - /* - * First, clamp to min and max values - */ - if (dwidth < minWidth) - dwidth = minWidth; - if (dheight < minHeight) - dheight = minHeight; - - if (dwidth > maxWidth) - dwidth = maxWidth; - if (dheight > maxHeight) - dheight = maxHeight; - - /* - * Second, fit to base + N * inc - */ - dwidth = ((dwidth - baseWidth) / xinc * xinc) + baseWidth; - dheight = ((dheight - baseHeight) / yinc * yinc) + baseHeight; - - /* - * Third, adjust for aspect ratio - */ - - /* - * The math looks like this: - * - * minAspectX dwidth maxAspectX - * ---------- <= ------- <= ---------- - * minAspectY dheight maxAspectY - * - * If that is multiplied out, then the width and height are - * invalid in the following situations: - * - * minAspectX * dheight > minAspectY * dwidth - * maxAspectX * dheight < maxAspectY * dwidth - * - */ - - if (hints.flags & PAspect) { - if (hints.min_aspect.x * dheight > hints.min_aspect.y * dwidth) { - delta = - makemult(hints.min_aspect.x * dheight / hints.min_aspect.y - - dwidth, xinc); - if (dwidth + delta <= maxWidth) - dwidth += delta; - else { - delta = - makemult(dheight - - dwidth * hints.min_aspect.y / hints.min_aspect.x, - yinc); - if (dheight - delta >= minHeight) - dheight -= delta; - } - } - - if (hints.max_aspect.x * dheight < hints.max_aspect.y * dwidth) { - delta = - makemult(dwidth * hints.max_aspect.y / hints.max_aspect.x - - dheight, yinc); - if (dheight + delta <= maxHeight) - dheight += delta; - else { - delta = - makemult(dwidth - - hints.max_aspect.x * dheight / hints.max_aspect.y, - xinc); - if (dwidth - delta >= minWidth) - dwidth -= delta; - } - } - } - - /* Return computed values */ - *widthp = dwidth; - *heightp = dheight; -} - -#undef makemult - -/* - * ValidateSizing - Ensures size request respects hints - */ -static int -ValidateSizing(HWND hwnd, WindowPtr pWin, WPARAM wParam, LPARAM lParam) -{ - WinXSizeHints sizeHints; - RECT *rect; - int iWidth, iHeight, iTopBorder; - POINT pt; - - /* Invalid input checking */ - if (pWin == NULL || lParam == 0) { - ErrorF("Invalid input checking\n"); - return FALSE; - } - - /* No size hints, no checking */ - if (!winMultiWindowGetWMNormalHints(pWin, &sizeHints)) { - ErrorF("No size hints, no checking\n"); - return FALSE; - } - - /* Avoid divide-by-zero */ - if (sizeHints.flags & PResizeInc) { - if (sizeHints.width_inc == 0) - sizeHints.width_inc = 1; - if (sizeHints.height_inc == 0) - sizeHints.height_inc = 1; - } - - rect = (RECT *) lParam; - - iWidth = rect->right - rect->left; - iHeight = rect->bottom - rect->top; - - /* Get title bar height, there must be an easier way?! */ - pt.x = pt.y = 0; - ClientToScreen(hwnd, &pt); - iTopBorder = pt.y - rect->top; - - /* Now remove size of any borders */ - iWidth -= 2 * GetSystemMetrics(SM_CXSIZEFRAME); - iHeight -= GetSystemMetrics(SM_CYSIZEFRAME) + iTopBorder; - - /* Constrain the size to legal values */ - ConstrainSize(sizeHints, &iWidth, &iHeight); - - /* Add back the borders */ - iWidth += 2 * GetSystemMetrics(SM_CXSIZEFRAME); - iHeight += GetSystemMetrics(SM_CYSIZEFRAME) + iTopBorder; - - /* Adjust size according to where we're dragging from */ - switch (wParam) { - case WMSZ_TOP: - case WMSZ_TOPRIGHT: - case WMSZ_BOTTOM: - case WMSZ_BOTTOMRIGHT: - case WMSZ_RIGHT: - rect->right = rect->left + iWidth; - break; - default: - rect->left = rect->right - iWidth; - break; - } - switch (wParam) { - case WMSZ_BOTTOM: - case WMSZ_BOTTOMRIGHT: - case WMSZ_BOTTOMLEFT: - case WMSZ_RIGHT: - case WMSZ_LEFT: - rect->bottom = rect->top + iHeight; - break; - default: - rect->top = rect->bottom - iHeight; - break; - } - return TRUE; -} - -/* - * IsMouseActive - */ - -static Bool -IsMouseActive(WindowPtr pWin) -{ - - struct _Window *pwin; - struct _Property *prop; - - /* XXX We're getting inputInfo.poniter here, but this might be really wrong. - * Which pointer's current window do we want? */ - WindowPtr pRoot = GetCurrentRootWindow(inputInfo.pointer); - - if (!pWin) { - ErrorF("IsMouseActive - pWin was NULL use default value:%d\n", - MOUSE_ACTIVATE_DEFAULT); - return MOUSE_ACTIVATE_DEFAULT; - } - - pwin = (struct _Window *) pWin; - - if (pwin->optional) - prop = (struct _Property *) pwin->optional->userProps; - else - prop = NULL; - - while (prop) { - if (prop->propertyName == AtmWindowsWMMouseActivate() - && prop->type == XA_INTEGER && prop->format == 32) { - return *(int *) prop->data; - } - else - prop = prop->next; - } - - if (pWin != pRoot) { - return IsMouseActive(pRoot); - } - else { -#if CYGMULTIWINDOW_DEBUG - winDebug("IsMouseActive - no prop use default value:%d\n", - MOUSE_ACTIVATE_DEFAULT); -#endif - return MOUSE_ACTIVATE_DEFAULT; - } -} - -/* - * winMWExtWMWindowProc - Window procedure - */ - -LRESULT CALLBACK -winMWExtWMWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - WindowPtr pWin = NULL; - win32RootlessWindowPtr pRLWinPriv = NULL; - ScreenPtr pScreen = NULL; - winPrivScreenPtr pScreenPriv = NULL; - winScreenInfo *pScreenInfo = NULL; - HWND hwndScreen = NULL; - POINT ptMouse; - static Bool s_fTracking = FALSE; - HDC hdcUpdate; - PAINTSTRUCT ps; - LPWINDOWPOS pWinPos = NULL; - RECT rcClient; - - /* Check if the Windows window property for our X window pointer is valid */ - if ((pRLWinPriv = - (win32RootlessWindowPtr) GetProp(hwnd, WIN_WINDOW_PROP)) != NULL) { - pWin = pRLWinPriv->pFrame->win; - pScreen = pWin->drawable.pScreen; - if (pScreen) - pScreenPriv = winGetScreenPriv(pScreen); - if (pScreenPriv) - pScreenInfo = pScreenPriv->pScreenInfo; - if (pScreenPriv) - hwndScreen = pScreenPriv->hwndScreen; - -#if CYGDEBUG - winDebugWin32Message("winMWExtWMWindowProc", hwnd, message, wParam, - lParam); - - winDebug("\thWnd %p\n", hwnd); - winDebug("\tpScreenPriv %p\n", pScreenPriv); - winDebug("\tpScreenInfo %p\n", pScreenInfo); - winDebug("\thwndScreen %p\n", hwndScreen); - winDebug("winMWExtWMWindowProc (%p) %08x %08x %08x\n", - pRLWinPriv, message, (int)wParam, (int)lParam); -#endif - } - /* Branch on message type */ - switch (message) { - case WM_CREATE: -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMWindowProc - WM_CREATE\n"); -#endif - /* */ - SetProp(hwnd, - WIN_WINDOW_PROP, - (HANDLE) ((LPCREATESTRUCT) lParam)->lpCreateParams); - return 0; - - case WM_CLOSE: -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMWindowProc - WM_CLOSE %d\n", pRLWinPriv->fClose); -#endif - /* Tell window-manager to close window */ - if (pRLWinPriv->fClose) { - DestroyWindow(hwnd); - } - else { - winWindowsWMSendEvent(WindowsWMControllerNotify, - WindowsWMControllerNotifyMask, - 1, - WindowsWMCloseWindow, - pWin->drawable.id, 0, 0, 0, 0); - } - return 0; - - case WM_DESTROY: -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMWindowProc - WM_DESTROY\n"); -#endif - /* Free the shaodw DC; which allows the bitmap to be freed */ - DeleteDC(pRLWinPriv->hdcShadow); - pRLWinPriv->hdcShadow = NULL; - - /* Free the shadow bitmap */ - DeleteObject(pRLWinPriv->hbmpShadow); - pRLWinPriv->hbmpShadow = NULL; - - /* Free the screen DC */ - ReleaseDC(pRLWinPriv->hWnd, pRLWinPriv->hdcScreen); - pRLWinPriv->hdcScreen = NULL; - - /* Free shadow buffer info header */ - free(pRLWinPriv->pbmihShadow); - pRLWinPriv->pbmihShadow = NULL; - - pRLWinPriv->fResized = FALSE; - pRLWinPriv->pfb = NULL; - free(pRLWinPriv); - RemoveProp(hwnd, WIN_WINDOW_PROP); - break; - - case WM_MOUSEMOVE: -#if CYGMULTIWINDOW_DEBUG && 0 - winDebug("winMWExtWMWindowProc - WM_MOUSEMOVE\n"); -#endif - /* Unpack the client area mouse coordinates */ - ptMouse.x = GET_X_LPARAM(lParam); - ptMouse.y = GET_Y_LPARAM(lParam); - - /* Translate the client area mouse coordinates to screen coordinates */ - ClientToScreen(hwnd, &ptMouse); - - /* Screen Coords from (-X, -Y) -> Root Window (0, 0) */ - ptMouse.x -= GetSystemMetrics(SM_XVIRTUALSCREEN); - ptMouse.y -= GetSystemMetrics(SM_YVIRTUALSCREEN); - - /* We can't do anything without privates */ - if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput) - break; - - /* Has the mouse pointer crossed screens? */ - if (pScreen != miPointerGetScreen(inputInfo.pointer)) - miPointerSetScreen(inputInfo.pointer, pScreenInfo->dwScreen, - ptMouse.x - pScreenInfo->dwXOffset, - ptMouse.y - pScreenInfo->dwYOffset); - - /* Are we tracking yet? */ - if (!s_fTracking) { - TRACKMOUSEEVENT tme; - - /* Setup data structure */ - ZeroMemory(&tme, sizeof(tme)); - tme.cbSize = sizeof(tme); - tme.dwFlags = TME_LEAVE; - tme.hwndTrack = hwnd; - - /* Call the tracking function */ - if (!TrackMouseEvent(&tme)) - ErrorF("winMWExtWMWindowProc - TrackMouseEvent failed\n"); - - /* Flag that we are tracking now */ - s_fTracking = TRUE; - } - - /* Kill the timer used to poll mouse events */ - if (g_uipMousePollingTimerID != 0) { - KillTimer(pScreenPriv->hwndScreen, WIN_POLLING_MOUSE_TIMER_ID); - g_uipMousePollingTimerID = 0; - } - - /* Deliver absolute cursor position to X Server */ - winEnqueueMotion(ptMouse.x - pScreenInfo->dwXOffset, - ptMouse.y - pScreenInfo->dwYOffset); - - return 0; - - case WM_NCMOUSEMOVE: -#if CYGMULTIWINDOW_DEBUG && 0 - winDebug("winMWExtWMWindowProc - WM_NCMOUSEMOVE\n"); -#endif - /* - * We break instead of returning 0 since we need to call - * DefWindowProc to get the mouse cursor changes - * and min/max/close button highlighting in Windows XP. - * The Platform SDK says that you should return 0 if you - * process this message, but it fails to mention that you - * will give up any default functionality if you do return 0. - */ - - /* We can't do anything without privates */ - if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput) - break; - - /* - * Timer to poll mouse events. This is needed to make - * programs like xeyes follow the mouse properly. - */ - if (g_uipMousePollingTimerID == 0) - g_uipMousePollingTimerID = SetTimer(pScreenPriv->hwndScreen, - WIN_POLLING_MOUSE_TIMER_ID, - MOUSE_POLLING_INTERVAL, NULL); - break; - - case WM_MOUSELEAVE: -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMWindowProc - WM_MOUSELEAVE\n"); -#endif - /* Mouse has left our client area */ - - /* Flag that we are no longer tracking */ - s_fTracking = FALSE; - - /* - * Timer to poll mouse events. This is needed to make - * programs like xeyes follow the mouse properly. - */ - if (g_uipMousePollingTimerID == 0) - g_uipMousePollingTimerID = SetTimer(pScreenPriv->hwndScreen, - WIN_POLLING_MOUSE_TIMER_ID, - MOUSE_POLLING_INTERVAL, NULL); - return 0; - - case WM_LBUTTONDBLCLK: - case WM_LBUTTONDOWN: -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMWindowProc - WM_LBUTTONDBLCLK\n"); -#endif - if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput) - break; - SetCapture(hwnd); - return winMouseButtonsHandle(pScreen, ButtonPress, Button1, wParam); - - case WM_LBUTTONUP: -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMWindowProc - WM_LBUTTONUP\n"); -#endif - if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput) - break; - ReleaseCapture(); - return winMouseButtonsHandle(pScreen, ButtonRelease, Button1, wParam); - - case WM_MBUTTONDBLCLK: - case WM_MBUTTONDOWN: -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMWindowProc - WM_MBUTTONDBLCLK\n"); -#endif - if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput) - break; - SetCapture(hwnd); - return winMouseButtonsHandle(pScreen, ButtonPress, Button2, wParam); - - case WM_MBUTTONUP: -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMWindowProc - WM_MBUTTONUP\n"); -#endif - if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput) - break; - ReleaseCapture(); - return winMouseButtonsHandle(pScreen, ButtonRelease, Button2, wParam); - - case WM_RBUTTONDBLCLK: - case WM_RBUTTONDOWN: -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMWindowProc - WM_RBUTTONDBLCLK\n"); -#endif - if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput) - break; - SetCapture(hwnd); - return winMouseButtonsHandle(pScreen, ButtonPress, Button3, wParam); - - case WM_RBUTTONUP: -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMWindowProc - WM_RBUTTONUP\n"); -#endif - if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput) - break; - ReleaseCapture(); - return winMouseButtonsHandle(pScreen, ButtonRelease, Button3, wParam); - - case WM_XBUTTONDBLCLK: - case WM_XBUTTONDOWN: - if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput) - break; - SetCapture(hwnd); - return winMouseButtonsHandle(pScreen, ButtonPress, HIWORD(wParam) + 7, - wParam); - case WM_XBUTTONUP: - if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput) - break; - ReleaseCapture(); - return winMouseButtonsHandle(pScreen, ButtonRelease, HIWORD(wParam) + 7, - wParam); - - case WM_MOUSEWHEEL: -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMWindowProc - WM_MOUSEWHEEL\n"); -#endif - - /* Pass the message to the root window */ - SendMessage(hwndScreen, message, wParam, lParam); - return 0; - - case WM_MOUSEHWHEEL: -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMWindowProc - WM_MOUSEHWHEEL\n"); -#endif - - /* Pass the message to the root window */ - SendMessage(hwndScreen, message, wParam, lParam); - return 0; - - case WM_MOUSEACTIVATE: -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMWindowProc - WM_MOUSEACTIVATE\n"); -#endif - if (!IsMouseActive(pWin)) - return MA_NOACTIVATE; - - break; - - case WM_KILLFOCUS: - /* Pop any pressed keys since we are losing keyboard focus */ - winKeybdReleaseKeys(); - return 0; - - case WM_SYSDEADCHAR: - case WM_DEADCHAR: - /* - * NOTE: We do nothing with WM_*CHAR messages, - * nor does the root window, so we can just toss these messages. - */ - return 0; - - case WM_SYSKEYDOWN: - case WM_KEYDOWN: -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMWindowProc - WM_*KEYDOWN\n"); -#endif - - /* - * Don't pass Alt-F4 key combo to root window, - * let Windows translate to WM_CLOSE and close this top-level window. - * - * NOTE: We purposely don't check the fUseWinKillKey setting because - * it should only apply to the key handling for the root window, - * not for top-level window-manager windows. - * - * ALSO NOTE: We do pass Ctrl-Alt-Backspace to the root window - * because that is a key combo that no X app should be expecting to - * receive, since it has historically been used to shutdown the X server. - * Passing Ctrl-Alt-Backspace to the root window preserves that - * behavior, assuming that -unixkill has been passed as a parameter. - */ - if (wParam == VK_F4 && (GetKeyState(VK_MENU) & 0x8000)) - break; - - /* Pass the message to the root window */ - SendMessage(hwndScreen, message, wParam, lParam); - return 0; - - case WM_SYSKEYUP: - case WM_KEYUP: - -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMWindowProc - WM_*KEYUP\n"); -#endif - - /* Pass the message to the root window */ - SendMessage(hwndScreen, message, wParam, lParam); - return 0; - - case WM_HOTKEY: -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMWindowProc - WM_HOTKEY\n"); -#endif - - /* Pass the message to the root window */ - SendMessage(hwndScreen, message, wParam, lParam); - return 0; - - case WM_ERASEBKGND: -#if CYGDEBUG - winDebug("winMWExtWMWindowProc - WM_ERASEBKGND\n"); -#endif - /* - * Pretend that we did erase the background but we don't care, - * since we repaint the entire region anyhow - * This avoids some flickering when resizing. - */ - return TRUE; - - case WM_PAINT: - - /* BeginPaint gives us an hdc that clips to the invalidated region */ - hdcUpdate = BeginPaint(hwnd, &ps); - - /* 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, - pRLWinPriv->hdcShadow, - ps.rcPaint.left, ps.rcPaint.top, 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("winMWExtWMWindowProc - BitBlt failed: %s\n", - (LPSTR) lpMsgBuf); - LocalFree(lpMsgBuf); - } - - /* EndPaint frees the DC */ - EndPaint(hwnd, &ps); - break; - - case WM_ACTIVATE: -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMWindowProc - WM_ACTIVATE\n"); -#endif - if (LOWORD(wParam) != WA_INACTIVE) { - winWindowsWMSendEvent(WindowsWMControllerNotify, - WindowsWMControllerNotifyMask, - 1, - WindowsWMActivateWindow, - pWin->drawable.id, 0, 0, 0, 0); - } - return 0; - -#if 1 - case WM_WINDOWPOSCHANGING: - pWinPos = (LPWINDOWPOS) lParam; - if (!(pWinPos->flags & SWP_NOZORDER)) { - if (pRLWinPriv->fRestackingNow || pScreenPriv->fRestacking) { -#if CYGMULTIWINDOW_DEBUG - winDebug("Win %p is now restacking.\n", - pRLWinPriv); -#endif - break; - } - -#if CYGMULTIWINDOW_DEBUG - winDebug("Win %p forbid to change z order (%p).\n", - pRLWinPriv, - pWinPos->hwndInsertAfter); -#endif - pWinPos->flags |= SWP_NOZORDER; - } - break; -#endif - - case WM_MOVE: -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMWindowProc - WM_MOVE\n"); -#endif - if (g_fNoConfigureWindow) - break; -#if 0 - /* Bail if Windows window is not actually moving */ - if (pRLWinPriv->dwX == (short) LOWORD(lParam) - && pRLWinPriv->dwY == (short) HIWORD(lParam)) - break; - - /* Also bail if we're maximizing, we'll do the whole thing in WM_SIZE */ - { - WINDOWPLACEMENT windPlace; - - windPlace.length = sizeof(WINDOWPLACEMENT); - - /* Get current window placement */ - GetWindowPlacement(hwnd, &windPlace); - - /* Bail if maximizing */ - if (windPlace.showCmd == SW_MAXIMIZE - || windPlace.showCmd == SW_SHOWMAXIMIZED) - break; - } -#endif - -#if CYGMULTIWINDOW_DEBUG - winDebug("\t(%d, %d)\n", (short) LOWORD(lParam), - (short) HIWORD(lParam)); -#endif - if (!pRLWinPriv->fMovingOrSizing) { - winMWExtWMMoveXWindow(pWin, (LOWORD(lParam) - wBorderWidth(pWin) - - GetSystemMetrics(SM_XVIRTUALSCREEN)), - (HIWORD(lParam) - wBorderWidth(pWin) - - GetSystemMetrics(SM_YVIRTUALSCREEN))); - } - return 0; - - case WM_SHOWWINDOW: -#if CYGMULTIWINDOW_DEBUG || TRUE - winDebug("winMWExtWMWindowProc - WM_SHOWWINDOW\n"); -#endif - /* Bail out if the window is being hidden */ - if (!wParam) - return 0; - - winMWExtWMUpdateWindowDecoration(pRLWinPriv, pScreenInfo); - - break; - - case WM_SIZING: - /* Need to legalize the size according to WM_NORMAL_HINTS */ - /* for applications like xterm */ - return ValidateSizing(hwnd, pWin, wParam, lParam); - - case WM_WINDOWPOSCHANGED: - { - pWinPos = (LPWINDOWPOS) lParam; -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMWindowProc - WM_WINDOWPOSCHANGED\n"); - winDebug("\tflags: %s%s%s%s%s%s%s%s%s%s%s%s\n", - (pWinPos->flags & SWP_DRAWFRAME) ? "SWP_DRAWFRAME " : "", - (pWinPos->flags & SWP_FRAMECHANGED) ? "SWP_FRAMECHANGED " : "", - (pWinPos->flags & SWP_HIDEWINDOW) ? "SWP_HIDEWINDOW " : "", - (pWinPos->flags & SWP_NOACTIVATE) ? "SWP_NOACTIVATE " : "", - (pWinPos->flags & SWP_NOCOPYBITS) ? "SWP_NOCOPYBITS " : "", - (pWinPos->flags & SWP_NOMOVE) ? "SWP_NOMOVE " : "", - (pWinPos-> - flags & SWP_NOOWNERZORDER) ? "SWP_NOOWNERZORDER " : "", - (pWinPos->flags & SWP_NOSIZE) ? "SWP_NOSIZE " : "", - (pWinPos->flags & SWP_NOREDRAW) ? "SWP_NOREDRAW " : "", - (pWinPos-> - flags & SWP_NOSENDCHANGING) ? "SWP_NOSENDCHANGING " : "", - (pWinPos->flags & SWP_NOZORDER) ? "SWP_NOZORDER " : "", - (pWinPos->flags & SWP_SHOWWINDOW) ? "SWP_SHOWWINDOW " : ""); - winDebug("\tno_configure: %s\n", (g_fNoConfigureWindow ? "Yes" : "No")); - winDebug("\textend: (%d, %d, %d, %d)\n", - pWinPos->x, pWinPos->y, pWinPos->cx, pWinPos->cy); - -#endif - if (pWinPos->flags & SWP_HIDEWINDOW) - break; - - if (!(pWinPos->flags & SWP_NOSIZE)) { - if (IsIconic(hwnd)) { -#if CYGMULTIWINDOW_DEBUG - winDebug("\tIconic -> MINIMIZED\n"); -#endif - - winWindowsWMSendEvent(WindowsWMControllerNotify, - WindowsWMControllerNotifyMask, - 1, - WindowsWMMinimizeWindow, - pWin->drawable.id, 0, 0, 0, 0); - } - else if (IsZoomed(hwnd)) { -#if CYGMULTIWINDOW_DEBUG - winDebug("\tZoomed -> MAXIMIZED\n"); -#endif - winWindowsWMSendEvent(WindowsWMControllerNotify, - WindowsWMControllerNotifyMask, - 1, - WindowsWMMaximizeWindow, - pWin->drawable.id, 0, 0, 0, 0); - } - else { -#if CYGMULTIWINDOW_DEBUG - winDebug("\tnone -> RESTORED\n"); -#endif - winWindowsWMSendEvent(WindowsWMControllerNotify, - WindowsWMControllerNotifyMask, - 1, - WindowsWMRestoreWindow, - pWin->drawable.id, 0, 0, 0, 0); - } - } - if (!g_fNoConfigureWindow) { - - if (!pRLWinPriv->fMovingOrSizing - /*&& (pWinPos->flags & SWP_SHOWWINDOW) */ ) { - GetClientRect(hwnd, &rcClient); - MapWindowPoints(hwnd, HWND_DESKTOP, (LPPOINT) &rcClient, 2); - - if (!(pWinPos->flags & SWP_NOMOVE) - && !(pWinPos->flags & SWP_NOSIZE)) { -#if CYGMULTIWINDOW_DEBUG - winDebug("\tmove & resize\n"); -#endif - - winMWExtWMMoveResizeXWindow(pWin, - rcClient.left - - wBorderWidth(pWin) - - - GetSystemMetrics - (SM_XVIRTUALSCREEN), - rcClient.top - - wBorderWidth(pWin) - - - GetSystemMetrics - (SM_YVIRTUALSCREEN), - rcClient.right - rcClient.left - - wBorderWidth(pWin) * 2, - rcClient.bottom - rcClient.top - - wBorderWidth(pWin) * 2); - } - else if (!(pWinPos->flags & SWP_NOMOVE)) { -#if CYGMULTIWINDOW_DEBUG - winDebug("\tmove\n"); -#endif - - winMWExtWMMoveResizeXWindow(pWin, - rcClient.left - - wBorderWidth(pWin) - - - GetSystemMetrics - (SM_XVIRTUALSCREEN), - rcClient.top - - wBorderWidth(pWin) - - - GetSystemMetrics - (SM_YVIRTUALSCREEN), - rcClient.right - rcClient.left - - wBorderWidth(pWin) * 2, - rcClient.bottom - rcClient.top - - wBorderWidth(pWin) * 2); - } - else if (!(pWinPos->flags & SWP_NOMOVE)) { -#if CYGMULTIWINDOW_DEBUG - winDebug("\tmove\n"); -#endif - - winMWExtWMMoveXWindow(pWin, - rcClient.left - wBorderWidth(pWin) - - GetSystemMetrics(SM_XVIRTUALSCREEN), - rcClient.top - wBorderWidth(pWin) - - - GetSystemMetrics(SM_YVIRTUALSCREEN)); - } - else if (!(pWinPos->flags & SWP_NOSIZE)) { -#if CYGMULTIWINDOW_DEBUG - winDebug("\tresize\n"); -#endif - - winMWExtWMResizeXWindow(pWin, - rcClient.right - rcClient.left - - wBorderWidth(pWin) * 2, - rcClient.bottom - rcClient.top - - wBorderWidth(pWin) * 2); - } - } - } - } -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMWindowProc - WM_WINDOWPOSCHANGED - done.\n"); -#endif - return 0; - - case WM_SIZE: - /* see dix/window.c */ - /* FIXME: Maximize/Restore? */ -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMWindowProc - WM_SIZE\n"); -#endif -#if CYGMULTIWINDOW_DEBUG - winDebug("\t(%d, %d) %d\n", (short) LOWORD(lParam), - (short) HIWORD(lParam), g_fNoConfigureWindow); -#endif - if (g_fNoConfigureWindow) - break; - - /* Branch on type of resizing occurring */ - switch (wParam) { - case SIZE_MINIMIZED: -#if CYGMULTIWINDOW_DEBUG - winDebug("\tSIZE_MINIMIZED\n"); -#endif - - winWindowsWMSendEvent(WindowsWMControllerNotify, - WindowsWMControllerNotifyMask, - 1, - WindowsWMMinimizeWindow, - pWin->drawable.id, - 0, 0, LOWORD(lParam), HIWORD(lParam)); - break; - - case SIZE_RESTORED: -#if CYGMULTIWINDOW_DEBUG - winDebug("\tSIZE_RESTORED\n"); -#endif - winWindowsWMSendEvent(WindowsWMControllerNotify, - WindowsWMControllerNotifyMask, - 1, - WindowsWMRestoreWindow, - pWin->drawable.id, - 0, 0, LOWORD(lParam), HIWORD(lParam)); - break; - - case SIZE_MAXIMIZED: -#if CYGMULTIWINDOW_DEBUG - winDebug("\tSIZE_MAXIMIZED\n"); -#endif - winWindowsWMSendEvent(WindowsWMControllerNotify, - WindowsWMControllerNotifyMask, - 1, - WindowsWMMaximizeWindow, - pWin->drawable.id, - 0, 0, LOWORD(lParam), HIWORD(lParam)); - break; - } - - /* Perform the resize and notify the X client */ - if (!pRLWinPriv->fMovingOrSizing) { - winMWExtWMResizeXWindow(pWin, (short) LOWORD(lParam) - - wBorderWidth(pWin) * 2, - (short) HIWORD(lParam) - - wBorderWidth(pWin) * 2); - } - break; - - case WM_ACTIVATEAPP: -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMWindowProc - WM_ACTIVATEAPP\n"); -#endif - if (wParam) { - winWindowsWMSendEvent(WindowsWMActivationNotify, - WindowsWMActivationNotifyMask, - 1, - WindowsWMIsActive, - pWin->drawable.id, 0, 0, 0, 0); - } - else { - winWindowsWMSendEvent(WindowsWMActivationNotify, - WindowsWMActivationNotifyMask, - 1, - WindowsWMIsInactive, - pWin->drawable.id, 0, 0, 0, 0); - } - break; - - case WM_SETCURSOR: - if (LOWORD(lParam) == HTCLIENT) { - if (!g_fSoftwareCursor) - SetCursor(pScreenPriv->cursor.handle); - return TRUE; - } - break; - - case WM_ENTERSIZEMOVE: -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMWindowProc - WM_ENTERSIZEMOVE\n"); -#endif - pRLWinPriv->fMovingOrSizing = TRUE; - break; - - case WM_EXITSIZEMOVE: -#if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMWindowProc - WM_EXITSIZEMOVE\n"); -#endif - pRLWinPriv->fMovingOrSizing = FALSE; - - GetClientRect(hwnd, &rcClient); - - MapWindowPoints(hwnd, HWND_DESKTOP, (LPPOINT) &rcClient, 2); - - winMWExtWMMoveResizeXWindow(pWin, rcClient.left - wBorderWidth(pWin) - - GetSystemMetrics(SM_XVIRTUALSCREEN), - rcClient.top - wBorderWidth(pWin) - - GetSystemMetrics(SM_YVIRTUALSCREEN), - rcClient.right - rcClient.left - - wBorderWidth(pWin) * 2, - rcClient.bottom - rcClient.top - - wBorderWidth(pWin) * 2); - break; - - default: - break; - } - - return DefWindowProc(hwnd, message, wParam, lParam); -} diff --git a/hw/xwin/winwindow.h b/hw/xwin/winwindow.h index 959ce152a..e73098838 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 @@ -107,9 +109,10 @@ 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_WM_CREATE (WM_USER + 15) #define MwmHintsDecorations (1L << 1) @@ -144,7 +147,7 @@ winInitWM(void **ppWMInfo, pthread_t * ptWMProc, pthread_t * ptXMsgProc, pthread_mutex_t * ppmServerStarted, - int dwScreen, HWND hwndScreen); + int dwScreen, HWND hwndScreen, Bool compositeWM); void winDeinitMultiWindowWM(void); diff --git a/hw/xwin/winwindowswm.c b/hw/xwin/winwindowswm.c deleted file mode 100644 index b9399fae3..000000000 --- a/hw/xwin/winwindowswm.c +++ /dev/null @@ -1,596 +0,0 @@ -/* WindowsWM extension is based on AppleWM extension */ -/************************************************************************** - -Copyright (c) 2002 Apple Computer, Inc. All Rights Reserved. -Copyright (c) 2003 Torrey T. Lyons. 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, sub license, 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 NON-INFRINGEMENT. -IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS 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 "win.h" - -#include "misc.h" -#include "dixstruct.h" -#include "extnsionst.h" -#include "colormapst.h" -#include "cursorstr.h" -#include "scrnintstr.h" -#include "servermd.h" -#include "swaprep.h" -#define _WINDOWSWM_SERVER_ -#include <X11/extensions/windowswmstr.h> -#include "protocol-versions.h" - -static int WMErrorBase; -static unsigned char WMReqCode = 0; -static int WMEventBase = 0; - -static RESTYPE ClientType, eventResourceType; /* resource types for event masks */ -static XID eventResource; - -/* Currently selected events */ -static unsigned int eventMask = 0; - -static int WMFreeClient(void *data, XID id); -static int WMFreeEvents(void *data, XID id); -static void SNotifyEvent(xWindowsWMNotifyEvent * from, - xWindowsWMNotifyEvent * to); - -typedef struct _WMEvent *WMEventPtr; -typedef struct _WMEvent { - WMEventPtr next; - ClientPtr client; - XID clientResource; - unsigned int mask; -} WMEventRec; - -static int -ProcWindowsWMQueryVersion(ClientPtr client) -{ - xWindowsWMQueryVersionReply rep; - - REQUEST_SIZE_MATCH(xWindowsWMQueryVersionReq); - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.majorVersion = SERVER_WINDOWSWM_MAJOR_VERSION; - rep.minorVersion = SERVER_WINDOWSWM_MINOR_VERSION; - rep.patchVersion = SERVER_WINDOWSWM_PATCH_VERSION; - if (client->swapped) { - swaps(&rep.sequenceNumber); - swapl(&rep.length); - } - WriteToClient(client, sizeof(xWindowsWMQueryVersionReply), &rep); - return Success; -} - -/* events */ - -static inline void -updateEventMask(WMEventPtr * pHead) -{ - WMEventPtr pCur; - - eventMask = 0; - for (pCur = *pHead; pCur != NULL; pCur = pCur->next) - eventMask |= pCur->mask; -} - - /*ARGSUSED*/ static int -WMFreeClient(void *data, XID id) -{ - WMEventPtr pEvent; - WMEventPtr *pHead, pCur, pPrev; - - pEvent = (WMEventPtr) data; - dixLookupResourceByType((void *) &pHead, eventResource, eventResourceType, - NullClient, DixUnknownAccess); - if (pHead) { - pPrev = 0; - for (pCur = *pHead; pCur && pCur != pEvent; pCur = pCur->next) - pPrev = pCur; - if (pCur) { - if (pPrev) - pPrev->next = pEvent->next; - else - *pHead = pEvent->next; - } - updateEventMask(pHead); - } - free((void *) pEvent); - return 1; -} - - /*ARGSUSED*/ static int -WMFreeEvents(void *data, XID id) -{ - WMEventPtr *pHead, pCur, pNext; - - pHead = (WMEventPtr *) data; - for (pCur = *pHead; pCur; pCur = pNext) { - pNext = pCur->next; - FreeResource(pCur->clientResource, ClientType); - free((void *) pCur); - } - free((void *) pHead); - eventMask = 0; - return 1; -} - -static int -ProcWindowsWMSelectInput(ClientPtr client) -{ - REQUEST(xWindowsWMSelectInputReq); - WMEventPtr pEvent, pNewEvent, *pHead; - XID clientResource; - - REQUEST_SIZE_MATCH(xWindowsWMSelectInputReq); - dixLookupResourceByType((void *) &pHead, eventResource, eventResourceType, - client, DixWriteAccess); - if (stuff->mask != 0) { - if (pHead) { - /* check for existing entry. */ - for (pEvent = *pHead; pEvent; pEvent = pEvent->next) { - if (pEvent->client == client) { - pEvent->mask = stuff->mask; - updateEventMask(pHead); - return Success; - } - } - } - - /* build the entry */ - pNewEvent = malloc(sizeof(WMEventRec)); - if (!pNewEvent) - return BadAlloc; - pNewEvent->next = 0; - pNewEvent->client = client; - pNewEvent->mask = stuff->mask; - /* - * add a resource that will be deleted when - * the client goes away - */ - clientResource = FakeClientID(client->index); - pNewEvent->clientResource = clientResource; - if (!AddResource(clientResource, ClientType, (void *) pNewEvent)) - return BadAlloc; - /* - * create a resource to contain a pointer to the list - * of clients selecting input. This must be indirect as - * the list may be arbitrarily rearranged which cannot be - * done through the resource database. - */ - if (!pHead) { - pHead = malloc(sizeof(WMEventPtr)); - if (!pHead || - !AddResource(eventResource, eventResourceType, (void *) pHead)) - { - FreeResource(clientResource, RT_NONE); - return BadAlloc; - } - *pHead = 0; - } - pNewEvent->next = *pHead; - *pHead = pNewEvent; - updateEventMask(pHead); - } - else if (stuff->mask == 0) { - /* delete the interest */ - if (pHead) { - pNewEvent = 0; - for (pEvent = *pHead; pEvent; pEvent = pEvent->next) { - if (pEvent->client == client) - break; - pNewEvent = pEvent; - } - if (pEvent) { - FreeResource(pEvent->clientResource, ClientType); - if (pNewEvent) - pNewEvent->next = pEvent->next; - else - *pHead = pEvent->next; - free(pEvent); - updateEventMask(pHead); - } - } - } - else { - client->errorValue = stuff->mask; - return BadValue; - } - return Success; -} - -/* - * deliver the event - */ - -void -winWindowsWMSendEvent(int type, unsigned int mask, int which, int arg, - Window window, int x, int y, int w, int h) -{ - WMEventPtr *pHead, pEvent; - ClientPtr client; - xWindowsWMNotifyEvent se; - -#if CYGMULTIWINDOW_DEBUG - ErrorF("winWindowsWMSendEvent %d %d %d %d, %d %d - %d %d\n", - type, mask, which, arg, x, y, w, h); -#endif - dixLookupResourceByType((void *) &pHead, eventResource, eventResourceType, - NullClient, DixUnknownAccess); - if (!pHead) - return; - for (pEvent = *pHead; pEvent; pEvent = pEvent->next) { - client = pEvent->client; -#if CYGMULTIWINDOW_DEBUG - ErrorF("winWindowsWMSendEvent - %p\n", client); -#endif - if ((pEvent->mask & mask) == 0) { - continue; - } -#if CYGMULTIWINDOW_DEBUG - ErrorF("winWindowsWMSendEvent - send\n"); -#endif - se.type = type + WMEventBase; - se.kind = which; - se.window = window; - se.arg = arg; - se.x = x; - se.y = y; - se.w = w; - se.h = h; - se.time = currentTime.milliseconds; - WriteEventsToClient(client, 1, (xEvent *) &se); - } -} - -/* general utility functions */ - -static int -ProcWindowsWMDisableUpdate(ClientPtr client) -{ - REQUEST_SIZE_MATCH(xWindowsWMDisableUpdateReq); - - //winDisableUpdate(); - - return Success; -} - -static int -ProcWindowsWMReenableUpdate(ClientPtr client) -{ - REQUEST_SIZE_MATCH(xWindowsWMReenableUpdateReq); - - //winEnableUpdate(); - - return Success; -} - -/* window functions */ - -static int -ProcWindowsWMSetFrontProcess(ClientPtr client) -{ - REQUEST_SIZE_MATCH(xWindowsWMSetFrontProcessReq); - - //QuartzMessageMainThread(kWindowsSetFrontProcess, NULL, 0); - - return Success; -} - -/* frame functions */ - -static int -ProcWindowsWMFrameGetRect(ClientPtr client) -{ - xWindowsWMFrameGetRectReply rep; - RECT rcNew; - - REQUEST(xWindowsWMFrameGetRectReq); - -#if CYGMULTIWINDOW_DEBUG - ErrorF("ProcWindowsWMFrameGetRect %zu %d\n", - (sizeof(xWindowsWMFrameGetRectReq) >> 2), (int) client->req_len); -#endif - - REQUEST_SIZE_MATCH(xWindowsWMFrameGetRectReq); - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - - if (stuff->frame_rect != 0) { - ErrorF("ProcWindowsWMFrameGetRect - stuff->frame_rect != 0\n"); - return BadValue; - } - - /* Store the origin, height, and width in a rectangle structure */ - SetRect(&rcNew, stuff->ix, stuff->iy, - stuff->ix + stuff->iw, stuff->iy + stuff->ih); - -#if CYGMULTIWINDOW_DEBUG - ErrorF("ProcWindowsWMFrameGetRect - %d %d %d %d\n", - stuff->ix, stuff->iy, stuff->ix + stuff->iw, stuff->iy + stuff->ih); -#endif - - /* - * Calculate the required size of the Windows window rectangle, - * given the size of the Windows window client area. - */ - AdjustWindowRectEx(&rcNew, stuff->frame_style, FALSE, - stuff->frame_style_ex); - rep.x = rcNew.left; - rep.y = rcNew.top; - rep.w = rcNew.right - rcNew.left; - rep.h = rcNew.bottom - rcNew.top; -#if CYGMULTIWINDOW_DEBUG - ErrorF("ProcWindowsWMFrameGetRect - %d %d %d %d\n", - rep.x, rep.y, rep.w, rep.h); -#endif - - WriteToClient(client, sizeof(xWindowsWMFrameGetRectReply), &rep); - return Success; -} - -static int -ProcWindowsWMFrameDraw(ClientPtr client) -{ - REQUEST(xWindowsWMFrameDrawReq); - WindowPtr pWin; - win32RootlessWindowPtr pRLWinPriv; - RECT rcNew; - int nCmdShow, rc; - RegionRec newShape; - - REQUEST_SIZE_MATCH(xWindowsWMFrameDrawReq); - -#if CYGMULTIWINDOW_DEBUG - ErrorF("ProcWindowsWMFrameDraw\n"); -#endif - rc = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess); - if (rc != Success) - return rc; -#if CYGMULTIWINDOW_DEBUG - ErrorF("ProcWindowsWMFrameDraw - Window found\n"); -#endif - - pRLWinPriv = (win32RootlessWindowPtr) RootlessFrameForWindow(pWin, TRUE); - if (pRLWinPriv == 0) - return BadWindow; - -#if CYGMULTIWINDOW_DEBUG - ErrorF("ProcWindowsWMFrameDraw - HWND %p 0x%08x 0x%08x\n", - pRLWinPriv->hWnd, (int) stuff->frame_style, - (int) stuff->frame_style_ex); - ErrorF("ProcWindowsWMFrameDraw - %d %d %d %d\n", - stuff->ix, stuff->iy, stuff->iw, stuff->ih); -#endif - - /* Store the origin, height, and width in a rectangle structure */ - SetRect(&rcNew, stuff->ix, stuff->iy, - stuff->ix + stuff->iw, stuff->iy + stuff->ih); - - /* - * Calculate the required size of the Windows window rectangle, - * given the size of the Windows window client area. - */ - AdjustWindowRectEx(&rcNew, stuff->frame_style, FALSE, - stuff->frame_style_ex); - - /* Set the window extended style flags */ - if (!SetWindowLongPtr(pRLWinPriv->hWnd, GWL_EXSTYLE, stuff->frame_style_ex)) { - return BadValue; - } - - /* Set the window standard style flags */ - if (!SetWindowLongPtr(pRLWinPriv->hWnd, GWL_STYLE, stuff->frame_style)) { - return BadValue; - } - - /* Flush the window style */ - if (!SetWindowPos(pRLWinPriv->hWnd, NULL, - rcNew.left, rcNew.top, - rcNew.right - rcNew.left, rcNew.bottom - rcNew.top, - SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOACTIVATE)) { - return BadValue; - } - if (!IsWindowVisible(pRLWinPriv->hWnd)) - nCmdShow = SW_HIDE; - else - nCmdShow = SW_SHOWNA; - - ShowWindow(pRLWinPriv->hWnd, nCmdShow); - - if (wBoundingShape(pWin) != NULL) { - /* wBoundingShape is relative to *inner* origin of window. - Translate by borderWidth to get the outside-relative position. */ - - RegionNull(&newShape); - RegionCopy(&newShape, wBoundingShape(pWin)); - RegionTranslate(&newShape, pWin->borderWidth, pWin->borderWidth); - winMWExtWMReshapeFrame(pRLWinPriv, &newShape); - RegionUninit(&newShape); - } -#if CYGMULTIWINDOW_DEBUG - ErrorF("ProcWindowsWMFrameDraw - done\n"); -#endif - - return Success; -} - -static int -ProcWindowsWMFrameSetTitle(ClientPtr client) -{ - unsigned int title_length, title_max; - char *title_bytes; - - REQUEST(xWindowsWMFrameSetTitleReq); - WindowPtr pWin; - win32RootlessWindowPtr pRLWinPriv; - int rc; - -#if CYGMULTIWINDOW_DEBUG - ErrorF("ProcWindowsWMFrameSetTitle\n"); -#endif - - REQUEST_AT_LEAST_SIZE(xWindowsWMFrameSetTitleReq); - - rc = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess); - if (rc != Success) - return rc; -#if CYGMULTIWINDOW_DEBUG - ErrorF("ProcWindowsWMFrameSetTitle - Window found\n"); -#endif - - title_length = stuff->title_length; - title_max = (stuff->length << 2) - sizeof(xWindowsWMFrameSetTitleReq); - - if (title_max < title_length) - return BadValue; - -#if CYGMULTIWINDOW_DEBUG - ErrorF("ProcWindowsWMFrameSetTitle - length is valid\n"); -#endif - - title_bytes = malloc(title_length + 1); - strncpy(title_bytes, (char *) &stuff[1], title_length); - title_bytes[title_length] = '\0'; - - pRLWinPriv = (win32RootlessWindowPtr) RootlessFrameForWindow(pWin, FALSE); - - if (pRLWinPriv == 0) { - free(title_bytes); - return BadWindow; - } - - /* Flush the window style */ - SetWindowText(pRLWinPriv->hWnd, title_bytes); - - free(title_bytes); - -#if CYGMULTIWINDOW_DEBUG - ErrorF("ProcWindowsWMFrameSetTitle - done\n"); -#endif - - return Success; -} - -/* dispatch */ - -static int -ProcWindowsWMDispatch(ClientPtr client) -{ - REQUEST(xReq); - - switch (stuff->data) { - case X_WindowsWMQueryVersion: - return ProcWindowsWMQueryVersion(client); - } - - if (!client->local) - return WMErrorBase + WindowsWMClientNotLocal; - - switch (stuff->data) { - case X_WindowsWMSelectInput: - return ProcWindowsWMSelectInput(client); - case X_WindowsWMDisableUpdate: - return ProcWindowsWMDisableUpdate(client); - case X_WindowsWMReenableUpdate: - return ProcWindowsWMReenableUpdate(client); - case X_WindowsWMSetFrontProcess: - return ProcWindowsWMSetFrontProcess(client); - case X_WindowsWMFrameGetRect: - return ProcWindowsWMFrameGetRect(client); - case X_WindowsWMFrameDraw: - return ProcWindowsWMFrameDraw(client); - case X_WindowsWMFrameSetTitle: - return ProcWindowsWMFrameSetTitle(client); - default: - return BadRequest; - } -} - -static void -SNotifyEvent(xWindowsWMNotifyEvent * from, xWindowsWMNotifyEvent * to) -{ - to->type = from->type; - to->kind = from->kind; - cpswaps(from->sequenceNumber, to->sequenceNumber); - cpswapl(from->window, to->window); - cpswapl(from->time, to->time); - cpswapl(from->arg, to->arg); -} - -static int -SProcWindowsWMQueryVersion(ClientPtr client) -{ - REQUEST(xWindowsWMQueryVersionReq); - swaps(&stuff->length); - return ProcWindowsWMQueryVersion(client); -} - -static int -SProcWindowsWMDispatch(ClientPtr client) -{ - REQUEST(xReq); - - /* It is bound to be non-local when there is byte swapping */ - if (!client->local) - return WMErrorBase + WindowsWMClientNotLocal; - - /* only local clients are allowed WM access */ - switch (stuff->data) { - case X_WindowsWMQueryVersion: - return SProcWindowsWMQueryVersion(client); - default: - return BadRequest; - } -} - -void -winWindowsWMExtensionInit(void) -{ - ExtensionEntry *extEntry; - - ClientType = CreateNewResourceType(WMFreeClient, "WMClient"); - eventResourceType = CreateNewResourceType(WMFreeEvents, "WMEvent"); - eventResource = FakeClientID(0); - - if (ClientType && eventResourceType && - (extEntry = AddExtension(WINDOWSWMNAME, - WindowsWMNumberEvents, - WindowsWMNumberErrors, - ProcWindowsWMDispatch, - SProcWindowsWMDispatch, - NULL, StandardMinorOpcode))) { - size_t i; - - WMReqCode = (unsigned char) extEntry->base; - WMErrorBase = extEntry->errorBase; - WMEventBase = extEntry->eventBase; - for (i = 0; i < WindowsWMNumberEvents; i++) - EventSwapVector[WMEventBase + i] = (EventSwapPtr) SNotifyEvent; - } -} diff --git a/hw/xwin/winwndproc.c b/hw/xwin/winwndproc.c index 02186b13e..4a2d4bd37 100644 --- a/hw/xwin/winwndproc.c +++ b/hw/xwin/winwndproc.c @@ -43,6 +43,8 @@ #include "winmonitors.h" #include "inputstr.h" #include "winclipboard/winclipboard.h" +#include "wmutil/mouse.h" +#include "wmutil/keyboard.h" /* * Global variables @@ -168,6 +170,8 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) "new height: %d new bpp: %d\n", LOWORD(lParam), HIWORD(lParam), (int)wParam); + ErrorF("winWindowProc - RemoteSession: %s\n", GetSystemMetrics(SM_REMOTESESSION) ? "yes" : "no"); + /* 0 bpp has no defined meaning, ignore this message */ if (wParam == 0) break; @@ -220,14 +224,7 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) use RandR to resize the X screen */ if ((!s_pScreenInfo->fUserGaveHeightAndWidth) && - (s_pScreenInfo->iResizeMode == resizeWithRandr) && (FALSE -#ifdef XWIN_MULTIWINDOWEXTWM - || - s_pScreenInfo-> - fMWExtWM -#endif - || - s_pScreenInfo-> + (s_pScreenInfo->iResizeMode == resizeWithRandr) && (s_pScreenInfo-> fRootless || s_pScreenInfo-> @@ -245,7 +242,6 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) struct GetMonitorInfoData data; if (QueryMonitor(s_pScreenInfo->iMonitor, &data)) { - if (data.bMonitorSpecifiedExists == TRUE) { dwWidth = data.monitorWidth; dwHeight = data.monitorHeight; /* @@ -257,7 +253,6 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) ErrorF("Monitor number %d no longer exists!\n", s_pScreenInfo->iMonitor); } - } } /* @@ -315,9 +310,6 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) /* Break if we do not allow resizing */ if ((s_pScreenInfo->iResizeMode == resizeNotAllowed) || !s_pScreenInfo->fDecoration -#ifdef XWIN_MULTIWINDOWEXTWM - || s_pScreenInfo->fMWExtWM -#endif || s_pScreenInfo->fRootless || s_pScreenInfo->fMultiWindow || s_pScreenInfo->fFullScreen) @@ -616,9 +608,6 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) if (s_pScreenInfo == NULL || (s_pScreenInfo->iResizeMode != resizeWithScrollbars) || s_pScreenInfo->fFullScreen || !s_pScreenInfo->fDecoration -#ifdef XWIN_MULTIWINDOWEXTWM - || s_pScreenInfo->fMWExtWM -#endif || s_pScreenInfo->fRootless || s_pScreenInfo->fMultiWindow ) @@ -799,22 +788,14 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) case WM_LBUTTONDOWN: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; - if (s_pScreenInfo->fRootless -#ifdef XWIN_MULTIWINDOWEXTWM - || s_pScreenInfo->fMWExtWM -#endif - ) + if (s_pScreenInfo->fRootless) SetCapture(hwnd); return winMouseButtonsHandle(s_pScreen, ButtonPress, Button1, wParam); case WM_LBUTTONUP: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; - if (s_pScreenInfo->fRootless -#ifdef XWIN_MULTIWINDOWEXTWM - || s_pScreenInfo->fMWExtWM -#endif - ) + if (s_pScreenInfo->fRootless) ReleaseCapture(); return winMouseButtonsHandle(s_pScreen, ButtonRelease, Button1, wParam); @@ -822,22 +803,14 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) case WM_MBUTTONDOWN: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; - if (s_pScreenInfo->fRootless -#ifdef XWIN_MULTIWINDOWEXTWM - || s_pScreenInfo->fMWExtWM -#endif - ) + if (s_pScreenInfo->fRootless) SetCapture(hwnd); return winMouseButtonsHandle(s_pScreen, ButtonPress, Button2, wParam); case WM_MBUTTONUP: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; - if (s_pScreenInfo->fRootless -#ifdef XWIN_MULTIWINDOWEXTWM - || s_pScreenInfo->fMWExtWM -#endif - ) + if (s_pScreenInfo->fRootless) ReleaseCapture(); return winMouseButtonsHandle(s_pScreen, ButtonRelease, Button2, wParam); @@ -845,22 +818,14 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) case WM_RBUTTONDOWN: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; - if (s_pScreenInfo->fRootless -#ifdef XWIN_MULTIWINDOWEXTWM - || s_pScreenInfo->fMWExtWM -#endif - ) + if (s_pScreenInfo->fRootless) SetCapture(hwnd); return winMouseButtonsHandle(s_pScreen, ButtonPress, Button3, wParam); case WM_RBUTTONUP: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; - if (s_pScreenInfo->fRootless -#ifdef XWIN_MULTIWINDOWEXTWM - || s_pScreenInfo->fMWExtWM -#endif - ) + if (s_pScreenInfo->fRootless) ReleaseCapture(); return winMouseButtonsHandle(s_pScreen, ButtonRelease, Button3, wParam); @@ -868,22 +833,14 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) case WM_XBUTTONDOWN: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; - if (s_pScreenInfo->fRootless -#ifdef XWIN_MULTIWINDOWEXTWM - || s_pScreenInfo->fMWExtWM -#endif - ) + if (s_pScreenInfo->fRootless) SetCapture(hwnd); return winMouseButtonsHandle(s_pScreen, ButtonPress, HIWORD(wParam) + 7, wParam); case WM_XBUTTONUP: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; - if (s_pScreenInfo->fRootless -#ifdef XWIN_MULTIWINDOWEXTWM - || s_pScreenInfo->fMWExtWM -#endif - ) + if (s_pScreenInfo->fRootless) ReleaseCapture(); return winMouseButtonsHandle(s_pScreen, ButtonRelease, HIWORD(wParam) + 7, wParam); @@ -896,7 +853,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 */ @@ -1166,14 +1123,6 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) /* Call engine specific screen activation/deactivation function */ (*s_pScreenPriv->pwinActivateApp) (s_pScreen); -#ifdef XWIN_MULTIWINDOWEXTWM - if (s_pScreenPriv->fActive) { - /* Restack all window unless using built-in wm. */ - if (s_pScreenInfo->fMWExtWM) - winMWExtWMRestackWindows(s_pScreen); - } -#endif - return 0; case WM_COMMAND: diff --git a/hw/xwin/wmutil/Makefile.am b/hw/xwin/wmutil/Makefile.am new file mode 100644 index 000000000..22d1b46ec --- /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$(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..7143832b6 --- /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", (unsigned int)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", (unsigned int)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", (unsigned int)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..be9f4e027 --- /dev/null +++ b/hw/xwin/wmutil/icon_convert.c @@ -0,0 +1,572 @@ +/* + *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 0x%x\n", + (unsigned int)id, + (unsigned int)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", + (unsigned int)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..78a92a6dc --- /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", (int)wParam, (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: %u, fDown: %u\n", (unsigned int)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/meson.build b/hw/xwin/wmutil/meson.build new file mode 100644 index 000000000..d6d2f4d28 --- /dev/null +++ b/hw/xwin/wmutil/meson.build @@ -0,0 +1,28 @@ +srcs_wmutil = [ + 'cursor_convert.c', + 'icon_convert.c', + 'keyboard.c', + 'mouse.c', + 'scancodes.h', + 'winvkmap.h', +] + +headers_wmutil = [ + 'cursor_convert.h', + 'icon_convert.h', + 'keyboard.h', + 'mouse.h', +] + +install_headers( + headers_wmutil, + subdir: 'XWinWMUtil') + +xwin_wmutil = static_library( + 'XWinWMUtil', + srcs_wmutil, + c_args: '-DHAVE_XWIN_CONFIG_H', + include_directories: [inc, include_directories('../')], + dependencies: pixman_dep, + install: true, +) 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..e1c9f2bdf 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) @@ -191,8 +179,8 @@ #define KEY_BSlash2 /* \ _ 0xcb */ 203 #define KEY_Mute /* Audio Mute */ 152 -#define KEY_AudioLower /* Audio Lower */ 168 -#define KEY_AudioRaise /* Audio Raise */ 166 +#define KEY_AudioLower /* Audio Lower */ 166 +#define KEY_AudioRaise /* Audio Raise */ 168 #define KEY_NEXTSONG /* Media next */ 145 #define KEY_PLAYPAUSE /* Media play/pause toggle */ 154 @@ -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/os.h b/include/os.h index 3646194a0..439b28661 100644 --- a/include/os.h +++ b/include/os.h @@ -61,6 +61,8 @@ SOFTWARE. #include <bsd/string.h> /* for strlcpy, strlcat */ #endif +#include <signal.h> + #define SCREEN_SAVER_ON 0 #define SCREEN_SAVER_OFF 1 #define SCREEN_SAVER_FORCER 2 @@ -354,6 +356,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 * @@ -711,6 +717,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/man/Xserver.man b/man/Xserver.man index 31ffb8cff..106aa902b 100644 --- a/man/Xserver.man +++ b/man/Xserver.man @@ -592,9 +592,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/meson.build b/meson.build index c8df31b3b..ff661f9d1 100644 --- a/meson.build +++ b/meson.build @@ -82,7 +82,6 @@ dri3proto_dep = dependency('dri3proto', version: '>= 1.2', required: get_option( xineramaproto_dep = dependency('xineramaproto') xf86bigfontproto_dep = dependency('xf86bigfontproto', version: '>= 1.2.0') xf86vidmodeproto_dep = dependency('xf86vidmodeproto', version: '>= 2.2.99.1', required: false) -windowswmproto_dep = dependency('windowswmproto', required: false) applewmproto_dep = dependency('applewmproto', version: '>= 1.4', required: false) xshmfence_dep = dependency('xshmfence', version: '>= 1.1', required: false) @@ -469,7 +468,6 @@ common_dep = [ xf86bigfontproto_dep, xf86dgaproto_dep, xf86vidmodeproto_dep, - windowswmproto_dep, applewmproto_dep, pixman_dep, @@ -507,8 +505,8 @@ top_srcdir_inc = include_directories('.') serverconfigdir = join_paths(get_option('libdir'), 'xorg') manpage_config = configuration_data() -manpage_config.set('vendorversion', 'PACKAGE_STRING XORG_MAN_PAGE') -manpage_config.set('xorgversion', 'PACKAGE_STRING XORG_MAN_PAGE') +manpage_config.set('vendorversion', '"xorg-server @0@" "X Version 11"'.format(meson.project_version())) +manpage_config.set('xorgversion', '"xorg-server @0@" "X Version 11"'.format(meson.project_version())) manpage_config.set('xservername', 'Xorg') manpage_config.set('xconfigfile', 'xorg.conf') manpage_config.set('projectroot', get_option('prefix')) diff --git a/os/Makefile.am b/os/Makefile.am index c6e78cb99..673d4b04f 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 @@ -208,11 +208,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 619bf145e..5964aa41d 100644 --- a/os/backtrace.c +++ b/os/backtrace.c @@ -223,10 +223,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]; @@ -234,7 +249,7 @@ xorg_backtrace_pstack(void) return -1; } - kidpid = fork1(); + kidpid = fork(); if (kidpid == -1) { /* ERROR */ @@ -247,11 +262,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 { @@ -264,23 +281,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) @@ -317,7 +366,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 229bbe745..b09595d42 100644 --- a/os/connection.c +++ b/os/connection.c @@ -261,12 +261,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"); @@ -985,9 +985,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); @@ -1006,7 +1006,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/meson.build b/os/meson.build index eb8fcf55d..f9b19d7a0 100644 --- a/os/meson.build +++ b/os/meson.build @@ -75,6 +75,7 @@ endif libxserver_os = static_library('libxserver_os', srcs_os, + c_args: '-DBINDIR="@0@"'.format(join_paths(get_option('prefix'), get_option('bindir'))), include_directories: inc, dependencies: [ common_dep, diff --git a/os/osinit.c b/os/osinit.c index 8575319ff..25e0f2163 100644 --- a/os/osinit.c +++ b/os/osinit.c @@ -70,9 +70,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 #ifdef RLIMIT_DATA @@ -84,6 +86,7 @@ int limitStackSpace = -1; #ifdef RLIMIT_NOFILE int limitNoFile = -1; #endif +extern Bool install_os_signal_handler; /* The actual user defined max number of clients */ int LimitClients = LIMITCLIENTS; @@ -107,7 +110,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 @@ -131,8 +134,9 @@ OsSigHandler(int signo) } } - /* log, cleanup, and abort */ - xorg_backtrace(); +#if defined(WIN32) || defined(__CYGWIN__) + ErrorFSigSafe("Fatal signal received in thread %p [0x%x]\n", pthread_self(), (unsigned int)GetCurrentThreadId()); +#endif #ifdef SA_SIGINFO if (sip->si_code == SI_USER) { @@ -153,6 +157,13 @@ OsSigHandler(int signo) if (signo != SIGQUIT) CoreDump = TRUE; + /* log, cleanup, and abort */ + xorg_backtrace(); + +#if defined(__CYGWIN__) + xorg_crashreport(signo, sip, sigcontext); +#endif + FatalError("Caught signal %d (%s). Server aborting\n", signo, strsignal(signo)); } @@ -171,31 +182,34 @@ OsInit(void) if (!been_here) { #if !defined(WIN32) || defined(__CYGWIN__) - struct sigaction act, oact; - int i; + if (install_os_signal_handler) { + struct sigaction act, oact; + int i; - int siglist[] = { SIGSEGV, SIGQUIT, SIGILL, SIGFPE, SIGBUS, + int siglist[] = { SIGSEGV, SIGQUIT, SIGILL, SIGFPE, SIGBUS, SIGABRT, - SIGSYS, - SIGXCPU, - SIGXFSZ, + 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__ */ @@ -230,41 +244,6 @@ OsInit(void) } #endif -#if !defined(XQUARTZ) /* STDIN is already /dev/null and STDOUT/STDERR is managed by console_redirect.c */ - /* - * 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__) if (getpgrp() == 0) diff --git a/os/utils.c b/os/utils.c index 6e3c16869..a04cc7da7 100644 --- a/os/utils.c +++ b/os/utils.c @@ -110,6 +110,8 @@ __stdcall unsigned long GetTickCount(void); #include "picture.h" +Bool install_os_signal_handler = TRUE; + Bool noTestExtensions; #ifdef COMPOSITE @@ -248,7 +250,7 @@ UnlockServer(void) #else /* LOCK_SERVER */ static Bool StillLocking = FALSE; static char LockFile[PATH_MAX]; -static Bool nolock = FALSE; +Bool nolock = FALSE; /* * LockServer -- @@ -541,6 +543,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 @@ -838,6 +841,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__) @@ -1002,6 +1008,9 @@ ProcessCommandLine(int argc, char *argv[]) } else if (strcmp(argv[i], "-schedInterval") == 0) { if (++i < argc) { +#ifdef HAVE_SETITIMER + SmartScheduleSignalEnable = TRUE; +#endif SmartScheduleInterval = atoi(argv[i]); SmartScheduleSlice = SmartScheduleInterval; } @@ -1010,6 +1019,9 @@ ProcessCommandLine(int argc, char *argv[]) } else if (strcmp(argv[i], "-schedMax") == 0) { if (++i < argc) { +#ifdef HAVE_SETITIMER + SmartScheduleSignalEnable = TRUE; +#endif SmartScheduleMaxSlice = atoi(argv[i]); } else @@ -1361,6 +1373,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) { @@ -1403,6 +1435,7 @@ System(const char *command) return p == -1 ? -1 : status; } +#endif static struct pid { struct pid *next; @@ -1717,6 +1750,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 Bool diff --git a/xkb/ddxLoad.c b/xkb/ddxLoad.c index a8b8368a6..fbdefc3e4 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" #define PRE_ERROR_MSG "\"The XKEYBOARD keymap compiler (xkbcomp) reports:\"" #define ERROR_PREFIX "\"> \"" @@ -101,11 +102,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 @@ -114,10 +119,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) { @@ -155,41 +163,64 @@ 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) executing '%s'\n", keymap, buf); + } -#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); |