diff options
33 files changed, 589 insertions, 197 deletions
diff --git a/mesalib/src/gallium/auxiliary/util/u_cpu_detect.c b/mesalib/src/gallium/auxiliary/util/u_cpu_detect.c index b118fc8ae..588fc7c72 100644 --- a/mesalib/src/gallium/auxiliary/util/u_cpu_detect.c +++ b/mesalib/src/gallium/auxiliary/util/u_cpu_detect.c @@ -67,7 +67,7 @@ #if defined(PIPE_OS_WINDOWS) #include <windows.h> -#if defined(MSVC) +#if defined(PIPE_CC_MSVC) #include <intrin.h> #endif #endif @@ -211,6 +211,27 @@ cpuid(uint32_t ax, uint32_t *p) p[3] = 0; #endif } + +static INLINE uint64_t xgetbv(void) +{ +#if defined(PIPE_CC_GCC) + uint32_t eax, edx; + + __asm __volatile ( + ".byte 0x0f, 0x01, 0xd0" // xgetbv isn't supported on gcc < 4.4 + : "=a"(eax), + "=d"(edx) + : "c"(0) + ); + + return ((uint64_t)edx << 32) | eax; +#elif defined(PIPE_CC_MSVC) && defined(_MSC_FULL_VER) && defined(_XCR_XFEATURE_ENABLED_MASK) + return _xgetbv(_XCR_XFEATURE_ENABLED_MASK); +#else + return 0; +#endif + +} #endif /* X86 or X86_64 */ void @@ -284,7 +305,9 @@ util_cpu_detect(void) util_cpu_caps.has_sse4_1 = (regs2[2] >> 19) & 1; util_cpu_caps.has_sse4_2 = (regs2[2] >> 20) & 1; util_cpu_caps.has_popcnt = (regs2[2] >> 23) & 1; - util_cpu_caps.has_avx = (regs2[2] >> 28) & 1; + util_cpu_caps.has_avx = ((regs2[2] >> 28) & 1) && // AVX + ((regs2[2] >> 27) & 1) && // OSXSAVE + ((xgetbv() & 6) == 6); // XMM & YMM util_cpu_caps.has_f16c = (regs2[2] >> 29) & 1; util_cpu_caps.has_mmx2 = util_cpu_caps.has_sse; /* SSE cpus supports mmxext too */ diff --git a/mesalib/src/mesa/drivers/common/meta.c b/mesalib/src/mesa/drivers/common/meta.c index e8484299b..4a3497c9a 100644 --- a/mesalib/src/mesa/drivers/common/meta.c +++ b/mesalib/src/mesa/drivers/common/meta.c @@ -4095,10 +4095,29 @@ _mesa_meta_GetTexImage(struct gl_context *ctx, _mesa_get_format_datatype(texImage->TexFormat) == GL_UNSIGNED_NORMALIZED) { struct gl_texture_object *texObj = texImage->TexObject; - const GLuint slice = 0; /* only 2D compressed textures for now */ + GLuint slice; /* Need to unlock the texture here to prevent deadlock... */ _mesa_unlock_texture(ctx, texObj); - decompress_texture_image(ctx, texImage, slice, format, type, pixels); + for (slice = 0; slice < texImage->Depth; slice++) { + void *dst; + if (texImage->TexObject->Target == GL_TEXTURE_2D_ARRAY) { + /* Setup pixel packing. SkipPixels and SkipRows will be applied + * in the decompress_texture_image() function's call to + * glReadPixels but we need to compute the dest slice's address + * here (according to SkipImages and ImageHeight). + */ + struct gl_pixelstore_attrib packing = ctx->Pack; + packing.SkipPixels = 0; + packing.SkipRows = 0; + dst = _mesa_image_address3d(&packing, pixels, texImage->Width, + texImage->Height, format, type, + slice, 0, 0); + } + else { + dst = pixels; + } + decompress_texture_image(ctx, texImage, slice, format, type, dst); + } /* ... and relock it */ _mesa_lock_texture(ctx, texObj); } diff --git a/mesalib/src/mesa/main/mipmap.c b/mesalib/src/mesa/main/mipmap.c index edf725721..583963232 100644 --- a/mesalib/src/mesa/main/mipmap.c +++ b/mesalib/src/mesa/main/mipmap.c @@ -2020,13 +2020,15 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target, GLuint level; gl_format temp_format; GLint components; - GLuint temp_src_stride; /* in bytes */ + GLuint temp_src_row_stride, temp_src_img_stride; /* in bytes */ GLubyte *temp_src = NULL, *temp_dst = NULL; GLenum temp_datatype; GLenum temp_base_format; + GLubyte **temp_src_slices, **temp_dst_slices; /* only two types of compressed textures at this time */ assert(texObj->Target == GL_TEXTURE_2D || + texObj->Target == GL_TEXTURE_2D_ARRAY || texObj->Target == GL_TEXTURE_CUBE_MAP_ARB); /* @@ -2051,15 +2053,24 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target, /* allocate storage for the temporary, uncompressed image */ - /* 20 extra bytes, just be safe when calling last FetchTexel */ - temp_src_stride = _mesa_format_row_stride(temp_format, srcImage->Width); - temp_src = malloc(temp_src_stride * srcImage->Height + 20); - if (!temp_src) { + temp_src_row_stride = _mesa_format_row_stride(temp_format, srcImage->Width); + temp_src_img_stride = _mesa_format_image_size(temp_format, srcImage->Width, + srcImage->Height, 1); + temp_src = malloc(temp_src_img_stride * srcImage->Depth); + + /* Allocate storage for arrays of slice pointers */ + temp_src_slices = malloc(srcImage->Depth * sizeof(GLubyte *)); + temp_dst_slices = malloc(srcImage->Depth * sizeof(GLubyte *)); + + if (!temp_src || !temp_src_slices || !temp_dst_slices) { + free(temp_src); + free(temp_src_slices); + free(temp_dst_slices); _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps"); return; } - /* decompress base image to the temporary */ + /* decompress base image to the temporary src buffer */ { /* save pixel packing mode */ struct gl_pixelstore_attrib save = ctx->Pack; @@ -2075,7 +2086,6 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target, ctx->Pack = save; } - for (level = texObj->BaseLevel; level < maxLevel; level++) { /* generate image[level+1] from image[level] */ const struct gl_texture_image *srcImage; @@ -2084,7 +2094,8 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target, GLint dstWidth, dstHeight, dstDepth; GLint border; GLboolean nextLevel; - GLuint temp_dst_stride; /* in bytes */ + GLuint temp_dst_row_stride, temp_dst_img_stride; /* in bytes */ + GLuint i; /* get src image parameters */ srcImage = _mesa_select_tex_image(ctx, texObj, target, level); @@ -2100,9 +2111,12 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target, if (!nextLevel) break; - temp_dst_stride = _mesa_format_row_stride(temp_format, dstWidth); + /* Compute dst image strides and alloc memory on first iteration */ + temp_dst_row_stride = _mesa_format_row_stride(temp_format, dstWidth); + temp_dst_img_stride = _mesa_format_image_size(temp_format, dstWidth, + dstHeight, 1); if (!temp_dst) { - temp_dst = malloc(temp_dst_stride * dstHeight); + temp_dst = malloc(temp_dst_img_stride * dstDepth); if (!temp_dst) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps"); break; @@ -2117,13 +2131,23 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target, return; } - /* rescale src image to dest image */ + /* for 2D arrays, setup array[depth] of slice pointers */ + for (i = 0; i < srcDepth; i++) { + temp_src_slices[i] = temp_src + temp_src_img_stride * i; + } + for (i = 0; i < dstDepth; i++) { + temp_dst_slices[i] = temp_dst + temp_dst_img_stride * i; + } + + /* Rescale src image to dest image. + * This will loop over the slices of a 2D array. + */ _mesa_generate_mipmap_level(target, temp_datatype, components, border, srcWidth, srcHeight, srcDepth, - (const GLubyte **) &temp_src, - temp_src_stride, + (const GLubyte **) temp_src_slices, + temp_src_row_stride, dstWidth, dstHeight, dstDepth, - &temp_dst, temp_dst_stride); + temp_dst_slices, temp_dst_row_stride); if (!_mesa_prepare_mipmap_level(ctx, texObj, level + 1, dstWidth, dstHeight, dstDepth, @@ -2135,7 +2159,7 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target, /* The image space was allocated above so use glTexSubImage now */ ctx->Driver.TexSubImage(ctx, 2, dstImage, - 0, 0, 0, dstWidth, dstHeight, 1, + 0, 0, 0, dstWidth, dstHeight, dstDepth, temp_base_format, temp_datatype, temp_dst, &ctx->DefaultPacking); @@ -2144,12 +2168,15 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target, GLubyte *temp = temp_src; temp_src = temp_dst; temp_dst = temp; - temp_src_stride = temp_dst_stride; + temp_src_row_stride = temp_dst_row_stride; + temp_src_img_stride = temp_dst_img_stride; } } /* loop over mipmap levels */ free(temp_src); free(temp_dst); + free(temp_src_slices); + free(temp_dst_slices); } /** diff --git a/mesalib/src/mesa/main/texcompress_rgtc_tmp.h b/mesalib/src/mesa/main/texcompress_rgtc_tmp.h index 277d69b17..5fa9de630 100644 --- a/mesalib/src/mesa/main/texcompress_rgtc_tmp.h +++ b/mesalib/src/mesa/main/texcompress_rgtc_tmp.h @@ -37,9 +37,9 @@ static void TAG(fetch_texel_rgtc)(unsigned srcRowStride, const TYPE *pixdata, const TYPE alpha0 = blksrc[0]; const TYPE alpha1 = blksrc[1]; const char bit_pos = ((j&3) * 4 + (i&3)) * 3; - const TYPE acodelow = blksrc[2 + bit_pos / 8]; - const TYPE acodehigh = (3 + bit_pos / 8) < 8 ? blksrc[3 + bit_pos / 8] : 0; - const TYPE code = (acodelow >> (bit_pos & 0x7) | + const unsigned char acodelow = blksrc[2 + bit_pos / 8]; + const unsigned char acodehigh = (3 + bit_pos / 8) < 8 ? blksrc[3 + bit_pos / 8] : 0; + const unsigned char code = (acodelow >> (bit_pos & 0x7) | (acodehigh << (8 - (bit_pos & 0x7)))) & 0x7; if (code == 0) diff --git a/mesalib/src/mesa/main/texgetimage.c b/mesalib/src/mesa/main/texgetimage.c index 4c672e366..7050f1080 100644 --- a/mesalib/src/mesa/main/texgetimage.c +++ b/mesalib/src/mesa/main/texgetimage.c @@ -233,8 +233,8 @@ get_tex_rgba_compressed(struct gl_context *ctx, GLuint dimensions, const GLuint width = texImage->Width; const GLuint height = texImage->Height; const GLuint depth = texImage->Depth; - GLfloat *tempImage, *srcRow; - GLuint row; + GLfloat *tempImage, *tempSlice, *srcRow; + GLuint row, slice; /* Decompress into temp float buffer, then pack into user buffer */ tempImage = malloc(width * height * depth @@ -244,20 +244,22 @@ get_tex_rgba_compressed(struct gl_context *ctx, GLuint dimensions, return; } - /* Decompress the texture image - results in 'tempImage' */ - { + /* Decompress the texture image slices - results in 'tempImage' */ + for (slice = 0; slice < depth; slice++) { GLubyte *srcMap; GLint srcRowStride; - ctx->Driver.MapTextureImage(ctx, texImage, 0, + tempSlice = tempImage + slice * 4 * width * height; + + ctx->Driver.MapTextureImage(ctx, texImage, slice, 0, 0, width, height, GL_MAP_READ_BIT, &srcMap, &srcRowStride); if (srcMap) { _mesa_decompress_image(texFormat, width, height, - srcMap, srcRowStride, tempImage); + srcMap, srcRowStride, tempSlice); - ctx->Driver.UnmapTextureImage(ctx, texImage, 0); + ctx->Driver.UnmapTextureImage(ctx, texImage, slice); } else { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage"); @@ -294,15 +296,19 @@ get_tex_rgba_compressed(struct gl_context *ctx, GLuint dimensions, rebaseFormat); } - srcRow = tempImage; - for (row = 0; row < height; row++) { - void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels, - width, height, format, type, - 0, row, 0); - - _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) srcRow, - format, type, dest, &ctx->Pack, transferOps); - srcRow += width * 4; + tempSlice = tempImage; + for (slice = 0; slice < depth; slice++) { + srcRow = tempSlice; + for (row = 0; row < height; row++) { + void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels, + width, height, format, type, + slice, row, 0); + + _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) srcRow, + format, type, dest, &ctx->Pack, transferOps); + srcRow += 4 * width; + } + tempSlice += 4 * width * height; } free(tempImage); @@ -616,18 +622,8 @@ _mesa_get_teximage(struct gl_context *ctx, GLenum format, GLenum type, GLvoid *pixels, struct gl_texture_image *texImage) { - GLuint dimensions; - - switch (texImage->TexObject->Target) { - case GL_TEXTURE_1D: - dimensions = 1; - break; - case GL_TEXTURE_3D: - dimensions = 3; - break; - default: - dimensions = 2; - } + const GLuint dimensions = + _mesa_get_texture_dimensions(texImage->TexObject->Target); /* map dest buffer, if PBO */ if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { diff --git a/xorg-server/configure.ac b/xorg-server/configure.ac index 75281f001..c6ecba418 100644 --- a/xorg-server/configure.ac +++ b/xorg-server/configure.ac @@ -1944,6 +1944,10 @@ if test "x$XWIN" = xyes; then dnl XWin with AIGLX requires OpenGL spec files in order to generate wrapper code for native GL functions if [test "x$XWIN" = xyes && test "x$AIGLX" = xyes] ; then + AC_CHECK_PROG(PYTHON, python, python) + if test -z "$PYTHON"; then + AC_MSG_ERROR([python not found]) + fi if test "x$KHRONOS_SPEC_DIR" = "xauto" ; then PKG_CHECK_MODULES([KHRONOS_OPENGL_REGISTRY], [khronos-opengl-registry]) KHRONOS_SPEC_DIR=`pkg-config khronos-opengl-registry --variable=specdir` @@ -1967,7 +1971,7 @@ if test "x$XQUARTZ" = xyes; then AC_DEFINE(XQUARTZ,1,[Have Quartz]) AC_DEFINE(ROOTLESS,1,[Build Rootless code]) - XQUARTZ_LIBS="$MAIN_LIB $FB_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $XPSTUBS_LIB" + XQUARTZ_LIBS="$FB_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $XPSTUBS_LIB" AC_SUBST([XQUARTZ_LIBS]) AC_CHECK_LIB([Xplugin],[xp_init],[:]) diff --git a/xorg-server/dix/Makefile.am b/xorg-server/dix/Makefile.am index b7358aa72..e7ca2369c 100644 --- a/xorg-server/dix/Makefile.am +++ b/xorg-server/dix/Makefile.am @@ -4,7 +4,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/include AM_CFLAGS = $(DIX_CFLAGS) libmain_la_SOURCES = \ - main.c + stubmain.c libdix_la_SOURCES = \ atom.c \ @@ -14,6 +14,7 @@ libdix_la_SOURCES = \ dispatch.c \ dispatch.h \ dixfonts.c \ + main.c \ dixutils.c \ enterleave.c \ enterleave.h \ diff --git a/xorg-server/dix/main.c b/xorg-server/dix/main.c index e69cd931f..05dcbeddd 100644 --- a/xorg-server/dix/main.c +++ b/xorg-server/dix/main.c @@ -125,14 +125,10 @@ BOOL serverRunning = FALSE; pthread_mutex_t serverRunningMutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t serverRunningCond = PTHREAD_COND_INITIALIZER; -int dix_main(int argc, char *argv[], char *envp[]); +#endif int dix_main(int argc, char *argv[], char *envp[]) -#else -int -main(int argc, char *argv[], char *envp[]) -#endif { int i; HWEventQueueType alwaysCheckForInput[2]; diff --git a/xorg-server/dix/stubmain.c b/xorg-server/dix/stubmain.c new file mode 100644 index 000000000..7efb4b8e7 --- /dev/null +++ b/xorg-server/dix/stubmain.c @@ -0,0 +1,35 @@ +/*********************************************************** + +Copyright 2012 Jon TURNEY + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +int dix_main(int argc, char *argv[], char *envp[]); + +/* + A default implementation of main, which can be overridden by the DDX + */ +int +main(int argc, char *argv[], char *envp[]) +{ + return dix_main(argc, argv, envp); +} diff --git a/xorg-server/hw/xwin/InitOutput.c b/xorg-server/hw/xwin/InitOutput.c index 04c17b702..d6b5e4fd9 100644 --- a/xorg-server/hw/xwin/InitOutput.c +++ b/xorg-server/hw/xwin/InitOutput.c @@ -186,6 +186,25 @@ ddxBeforeReset(void) } #endif +int +main(int argc, char *argv[], char *envp[]) +{ + int iReturn; + + /* Create & acquire the termination mutex */ + iReturn = pthread_mutex_init(&g_pmTerminating, NULL); + if (iReturn != 0) { + ErrorF("ddxMain - pthread_mutex_init () failed: %d\n", iReturn); + } + + iReturn = pthread_mutex_lock(&g_pmTerminating); + if (iReturn != 0) { + ErrorF("ddxMain - pthread_mutex_lock () failed: %d\n", iReturn); + } + + return dix_main(argc, argv, envp); +} + /* See Porting Layer Definition - p. 57 */ void ddxGiveUp(enum ExitCode error) @@ -243,6 +262,19 @@ ddxGiveUp(enum ExitCode error) /* Tell Windows that we want to end the app */ PostQuitMessage(0); + + { + winDebug("ddxGiveUp - Releasing termination mutex\n"); + + int iReturn = pthread_mutex_unlock(&g_pmTerminating); + + if (iReturn != 0) { + ErrorF("winMsgWindowProc - pthread_mutex_unlock () failed: %d\n", + iReturn); + } + } + + winDebug("ddxGiveUp - End\n"); } /* See Porting Layer Definition - p. 57 */ @@ -962,6 +994,10 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char *argv[]) /* Store the instance handle */ g_hInstance = GetModuleHandle(NULL); + /* Create the messaging window */ + if (serverGeneration == 1) + winCreateMsgWindowThread(); + /* Initialize each screen */ for (i = 0; i < g_iNumScreens; ++i) { /* Initialize the screen */ diff --git a/xorg-server/hw/xwin/Makefile.am b/xorg-server/hw/xwin/Makefile.am index f13197592..74a4243c2 100644 --- a/xorg-server/hw/xwin/Makefile.am +++ b/xorg-server/hw/xwin/Makefile.am @@ -92,6 +92,7 @@ SRCS = InitInput.c \ winmonitors.c \ winmouse.c \ winmsg.c \ + winmsgwindow.c \ winmultiwindowclass.c \ winmultiwindowicons.c \ winprefs.c \ @@ -153,7 +154,7 @@ INCLUDES = -I$(top_srcdir)/miext/rootless XWIN_SYS_LIBS += -ldxguid -XWin_DEPENDENCIES = $(MULTIWINDOWEXTWM_LIBS) $(XWIN_GLX_LIBS) $(XWIN_LIBS) $(MAIN_LIB) $(XSERVER_LIBS) +XWin_DEPENDENCIES = $(MULTIWINDOWEXTWM_LIBS) $(XWIN_GLX_LIBS) $(XWIN_LIBS) $(XSERVER_LIBS) XWin_LDADD = $(MULTIWINDOW_LIBS) $(MULTIWINDOWEXTWM_LIBS) $(XWIN_GLX_LIBS) $(XWIN_GLX_LINK_FLAGS) $(XWIN_LIBS) $(MAIN_LIB) $(XSERVER_LIBS) $(XSERVER_SYS_LIBS) $(XWIN_SYS_LIBS) XWin_LDFLAGS = -mwindows -static diff --git a/xorg-server/hw/xwin/glx/Makefile.am b/xorg-server/hw/xwin/glx/Makefile.am index 59f6879a7..f969af277 100644 --- a/xorg-server/hw/xwin/glx/Makefile.am +++ b/xorg-server/hw/xwin/glx/Makefile.am @@ -33,10 +33,10 @@ AM_CFLAGS = -DHAVE_XWIN_CONFIG_H $(DIX_CFLAGS) \ if XWIN_GLX_WINDOWS generated_gl_wrappers.c: gen_gl_wrappers.py $(KHRONOS_SPEC_DIR)/gl.spec $(KHRONOS_SPEC_DIR)/gl.tm - $(AM_V_GEN)$(srcdir)/gen_gl_wrappers.py --spec=$(KHRONOS_SPEC_DIR)/gl.spec --typemap=$(KHRONOS_SPEC_DIR)/gl.tm --dispatch-header=$(top_srcdir)/glx/dispatch.h --staticwrappers >generated_gl_wrappers.c + $(AM_V_GEN)$(PYTHON) $(srcdir)/gen_gl_wrappers.py --spec=$(KHRONOS_SPEC_DIR)/gl.spec --typemap=$(KHRONOS_SPEC_DIR)/gl.tm --dispatch-header=$(top_srcdir)/glx/dispatch.h --staticwrappers >generated_gl_wrappers.c generated_wgl_wrappers.c: gen_gl_wrappers.py $(KHRONOS_SPEC_DIR)/wglext.spec $(KHRONOS_SPEC_DIR)/wgl.tm - $(AM_V_GEN)$(srcdir)/gen_gl_wrappers.py --spec=$(KHRONOS_SPEC_DIR)/wglext.spec --typemap=$(KHRONOS_SPEC_DIR)/wgl.tm --prefix=wgl --preresolve >generated_wgl_wrappers.c + $(AM_V_GEN)$(PYTHON) $(srcdir)/gen_gl_wrappers.py --spec=$(KHRONOS_SPEC_DIR)/wglext.spec --typemap=$(KHRONOS_SPEC_DIR)/wgl.tm --prefix=wgl --preresolve >generated_wgl_wrappers.c endif BUILT_SOURCES = generated_gl_wrappers.c generated_wgl_wrappers.c diff --git a/xorg-server/hw/xwin/win.h b/xorg-server/hw/xwin/win.h index fa774bc00..ce89348fe 100644 --- a/xorg-server/hw/xwin/win.h +++ b/xorg-server/hw/xwin/win.h @@ -42,22 +42,16 @@ #define YES 1 #endif +/* We can handle WM_MOUSEHWHEEL even though _WIN32_WINNT < 0x0600 */ +#ifndef WM_MOUSEHWHEEL +#define WM_MOUSEHWHEEL 0x020E +#endif + /* Turn debug messages on or off */ #ifndef CYGDEBUG #define CYGDEBUG NO #endif -/* WM_XBUTTON Messages. They should go into w32api. */ -#ifndef WM_XBUTTONDOWN -#define WM_XBUTTONDOWN 523 -#endif -#ifndef WM_XBUTTONUP -#define WM_XBUTTONUP 524 -#endif -#ifndef WM_XBUTTONDBLCLK -#define WM_XBUTTONDBLCLK 525 -#endif - #define WIN_DEFAULT_BPP 0 #define WIN_DEFAULT_WHITEPIXEL 255 #define WIN_DEFAULT_BLACKPIXEL 0 @@ -460,6 +454,7 @@ typedef struct _winPrivScreenRec { Bool fBadDepth; int iDeltaZ; + int iDeltaV; int iConnectedClients; @@ -921,8 +916,8 @@ void * winkeybd.c */ -void - winTranslateKey(WPARAM wParam, LPARAM lParam, int *piScanCode); +int + winTranslateKey(WPARAM wParam, LPARAM lParam); int winKeybdProc(DeviceIntPtr pDeviceInt, int iState); @@ -986,7 +981,7 @@ int winMouseProc(DeviceIntPtr pDeviceInt, int iState); int - winMouseWheel(ScreenPtr pScreen, int iDeltaZ); + winMouseWheel(int *iTotalDeltaZ, int iDeltaZ, int iButtonUp, int iButtonDown); void winMouseButtonsSendEvent(int iEventType, int iButton); @@ -1403,6 +1398,12 @@ winDoRandRScreenSetSize(ScreenPtr pScreen, CARD16 height, CARD32 mmWidth, CARD32 mmHeight); /* + * winmsgwindow.c + */ +Bool +winCreateMsgWindowThread(void); + +/* * END DDX and DIX Function Prototypes */ diff --git a/xorg-server/hw/xwin/winclipboard.h b/xorg-server/hw/xwin/winclipboard.h index 2cd775d6b..aa7fd4468 100644 --- a/xorg-server/hw/xwin/winclipboard.h +++ b/xorg-server/hw/xwin/winclipboard.h @@ -66,7 +66,6 @@ #define WIN_JMP_ERROR_IO 2 #define WIN_LOCAL_PROPERTY "CYGX_CUT_BUFFER" #define WIN_XEVENTS_SUCCESS 0 -#define WIN_XEVENTS_SHUTDOWN 1 #define WIN_XEVENTS_CONVERT 2 #define WIN_XEVENTS_NOTIFY 3 #define WIN_CLIPBOARD_RETRIES 40 diff --git a/xorg-server/hw/xwin/winclipboardthread.c b/xorg-server/hw/xwin/winclipboardthread.c index 6da9f3b72..33595be7f 100644 --- a/xorg-server/hw/xwin/winclipboardthread.c +++ b/xorg-server/hw/xwin/winclipboardthread.c @@ -325,14 +325,7 @@ winClipboardProc(void *pvNotUsed) /* Branch on which descriptor became active */ if (FD_ISSET(iConnectionNumber, &fdsRead)) { /* Process X events */ - /* Exit when we see that server is shutting down */ - iReturn = winClipboardFlushXEvents(hwnd, - iWindow, pDisplay, fUseUnicode); - if (WIN_XEVENTS_SHUTDOWN == iReturn) { - ErrorF("winClipboardProc - winClipboardFlushXEvents " - "trapped shutdown event, exiting main loop.\n"); - break; - } + winClipboardFlushXEvents(hwnd, iWindow, pDisplay, fUseUnicode); } #ifdef HAS_DEVWINDOWS @@ -460,7 +453,7 @@ winClipboardErrorHandler(Display * pDisplay, XErrorEvent * pErr) static int winClipboardIOErrorHandler(Display * pDisplay) { - ErrorF("winClipboardIOErrorHandler!\n\n"); + ErrorF("winClipboardIOErrorHandler!\n"); if (pthread_equal(pthread_self(), g_winClipboardProcThread)) { /* Restart at the main entry point */ diff --git a/xorg-server/hw/xwin/winfillsp.c b/xorg-server/hw/xwin/winfillsp.c index f2432ed23..bd0a15e8a 100644 --- a/xorg-server/hw/xwin/winfillsp.c +++ b/xorg-server/hw/xwin/winfillsp.c @@ -118,7 +118,7 @@ winFillSpansNativeGDI(DrawablePtr pDrawable, if (hbmpOrig == NULL) FatalError("winFillSpans - DRAWABLE_PIXMAP - " "SelectObject () failed on\n\tpPixmapPriv->hBitmap: " - "%08x\n", (unsigned int) pPixmapPriv->hBitmap); + "%p\n", pPixmapPriv->hBitmap); /* Branch on the fill type */ switch (pGC->fillStyle) { diff --git a/xorg-server/hw/xwin/winglobals.c b/xorg-server/hw/xwin/winglobals.c index b34d1a751..b3ca29592 100644 --- a/xorg-server/hw/xwin/winglobals.c +++ b/xorg-server/hw/xwin/winglobals.c @@ -78,6 +78,7 @@ Bool g_fNoHelpMessageBox = FALSE; Bool g_fSoftwareCursor = FALSE; Bool g_fSilentDupError = FALSE; Bool g_fNativeGl = TRUE; +pthread_mutex_t g_pmTerminating = PTHREAD_MUTEX_INITIALIZER; #ifdef XWIN_CLIPBOARD /* diff --git a/xorg-server/hw/xwin/winglobals.h b/xorg-server/hw/xwin/winglobals.h index d2e2ba2b4..e7e2f7e20 100644 --- a/xorg-server/hw/xwin/winglobals.h +++ b/xorg-server/hw/xwin/winglobals.h @@ -90,4 +90,6 @@ extern Bool g_fButton[3]; extern Bool g_fNoConfigureWindow; #endif +extern pthread_mutex_t g_pmTerminating; + #endif /* WINGLOBALS_H */ diff --git a/xorg-server/hw/xwin/winkeybd.c b/xorg-server/hw/xwin/winkeybd.c index e412f2355..9c5d4e9cd 100644 --- a/xorg-server/hw/xwin/winkeybd.c +++ b/xorg-server/hw/xwin/winkeybd.c @@ -65,13 +65,14 @@ static void * like AltGr on European keyboards. */ -void -winTranslateKey(WPARAM wParam, LPARAM lParam, int *piScanCode) +int +winTranslateKey(WPARAM wParam, LPARAM lParam) { int iKeyFixup = g_iKeyMap[wParam * WIN_KEYMAP_COLS + 1]; int iKeyFixupEx = g_iKeyMap[wParam * WIN_KEYMAP_COLS + 2]; int iParam = HIWORD(lParam); int iParamScanCode = LOBYTE(iParam); + int iScanCode; winDebug("winTranslateKey: wParam %08x lParam %08x\n", wParam, lParam); @@ -96,23 +97,25 @@ winTranslateKey(WPARAM wParam, LPARAM lParam, int *piScanCode) /* Branch on special extended, special non-extended, or normal key */ if ((iParam & KF_EXTENDED) && iKeyFixupEx) - *piScanCode = iKeyFixupEx; + iScanCode = iKeyFixupEx; else if (iKeyFixup) - *piScanCode = iKeyFixup; + iScanCode = iKeyFixup; else if (wParam == 0 && iParamScanCode == 0x70) - *piScanCode = KEY_HKTG; + iScanCode = KEY_HKTG; else switch (iParamScanCode) { case 0x70: - *piScanCode = KEY_HKTG; + iScanCode = KEY_HKTG; break; case 0x73: - *piScanCode = KEY_BSlash2; + iScanCode = KEY_BSlash2; break; default: - *piScanCode = iParamScanCode; + iScanCode = iParamScanCode; break; } + + return iScanCode; } /* Ring the keyboard bell (system speaker on PCs) */ @@ -264,25 +267,38 @@ winRestoreModeKeyStates(void) /* Check if modifier keys are pressed, and if so, fake a press */ { - BOOL ctrl = (GetAsyncKeyState(VK_CONTROL) < 0); - BOOL shift = (GetAsyncKeyState(VK_SHIFT) < 0); + + BOOL lctrl = (GetAsyncKeyState(VK_LCONTROL) < 0); + BOOL rctrl = (GetAsyncKeyState(VK_RCONTROL) < 0); + BOOL lshift = (GetAsyncKeyState(VK_LSHIFT) < 0); + BOOL rshift = (GetAsyncKeyState(VK_RSHIFT) < 0); BOOL alt = (GetAsyncKeyState(VK_LMENU) < 0); BOOL altgr = (GetAsyncKeyState(VK_RMENU) < 0); - if (ctrl && altgr) - ctrl = FALSE; + /* + If AltGr and CtrlL appear to be pressed, assume the + CtrL is a fake one + */ + if (lctrl && altgr) + lctrl = FALSE; + + if (lctrl) + winSendKeyEvent(KEY_LCtrl, TRUE); - if (LOGICAL_XOR(internalKeyStates & ControlMask, ctrl)) - winSendKeyEvent(KEY_LCtrl, ctrl); + if (rctrl) + winSendKeyEvent(KEY_RCtrl, TRUE); - if (LOGICAL_XOR(internalKeyStates & ShiftMask, shift)) - winSendKeyEvent(KEY_ShiftL, shift); + if (lshift) + winSendKeyEvent(KEY_ShiftL, TRUE); - if (LOGICAL_XOR(internalKeyStates & Mod1Mask, alt)) - winSendKeyEvent(KEY_Alt, alt); + if (rshift) + winSendKeyEvent(KEY_ShiftL, TRUE); - if (LOGICAL_XOR(internalKeyStates & Mod5Mask, altgr)) - winSendKeyEvent(KEY_AltLang, altgr); + if (alt) + winSendKeyEvent(KEY_Alt, TRUE); + + if (altgr) + winSendKeyEvent(KEY_AltLang, TRUE); } /* @@ -313,6 +329,12 @@ winRestoreModeKeyStates(void) winSendKeyEvent(KEY_HKTG, TRUE); winSendKeyEvent(KEY_HKTG, FALSE); } + + /* + For strict correctness, we should also press any non-modifier keys + which are already down when we gain focus, but nobody has complained + yet :-) + */ } /* diff --git a/xorg-server/hw/xwin/winmessages.h b/xorg-server/hw/xwin/winmessages.h index 3d3fab274..8282f8b06 100644 --- a/xorg-server/hw/xwin/winmessages.h +++ b/xorg-server/hw/xwin/winmessages.h @@ -529,7 +529,7 @@ static const char *MESSAGE_NAMES[1024] = { "WM_XBUTTONDOWN", "WM_XBUTTONUP", "WM_XBUTTONDBLCLK", - "526", + "WM_MOUSEHWHEEL", "527", "WM_PARENTNOTIFY", "WM_ENTERMENULOOP", diff --git a/xorg-server/hw/xwin/winmouse.c b/xorg-server/hw/xwin/winmouse.c index 9d896c90e..bbe21cba6 100644 --- a/xorg-server/hw/xwin/winmouse.c +++ b/xorg-server/hw/xwin/winmouse.c @@ -65,10 +65,10 @@ int winMouseProc(DeviceIntPtr pDeviceInt, int iState) { int lngMouseButtons, i; - int lngWheelEvents = 2; + int lngWheelEvents = 4; CARD8 *map; DevicePtr pDevice = (DevicePtr) pDeviceInt; - Atom *btn_labels; + Atom btn_labels[9]; Atom axes_labels[2]; switch (iState) { @@ -80,15 +80,23 @@ winMouseProc(DeviceIntPtr pDeviceInt, int iState) /* Mapping of windows events to X events: * LEFT:1 MIDDLE:2 RIGHT:3 * SCROLL_UP:4 SCROLL_DOWN:5 - * XBUTTON 1:6 XBUTTON 2:7 ... + * TILT_LEFT:6 TILT_RIGHT:7 + * XBUTTON 1:8 XBUTTON 2:9 (most commonly 'back' and 'forward') + * ... * + * The current Windows API only defines 2 extra buttons, so we don't + * expect more than 5 buttons to be reported, but more than that + * should be handled correctly + */ + + /* * To map scroll wheel correctly we need at least the 3 normal buttons */ if (lngMouseButtons < 3) lngMouseButtons = 3; - /* allocate memory: - * number of buttons + 2x mouse wheel event + 1 extra (offset for map) + /* allocate memory: + * number of buttons + 4 x mouse wheel event + 1 extra (offset for map) */ map = malloc(sizeof(CARD8) * (lngMouseButtons + lngWheelEvents + 1)); @@ -97,12 +105,15 @@ winMouseProc(DeviceIntPtr pDeviceInt, int iState) for (i = 1; i <= lngMouseButtons + lngWheelEvents; i++) map[i] = i; - btn_labels = calloc((lngMouseButtons + lngWheelEvents), sizeof(Atom)); btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT); btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE); btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT); btn_labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP); btn_labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN); + btn_labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT); + btn_labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT); + btn_labels[7] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_BACK); + btn_labels[8] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_FORWARD); axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X); axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y); @@ -114,7 +125,6 @@ winMouseProc(DeviceIntPtr pDeviceInt, int iState) winMouseCtrl, GetMotionHistorySize(), 2, axes_labels); free(map); - free(btn_labels); g_winMouseButtonMap = pDeviceInt->button->map; break; @@ -135,20 +145,16 @@ winMouseProc(DeviceIntPtr pDeviceInt, int iState) /* Handle the mouse wheel */ int -winMouseWheel(ScreenPtr pScreen, int iDeltaZ) +winMouseWheel(int *iTotalDeltaZ, int iDeltaZ, int iButtonUp, int iButtonDown) { - winScreenPriv(pScreen); - int button; /* Button4 or Button5 */ - - /* Button4 = WheelUp */ - /* Button5 = WheelDown */ + int button; /* Do we have any previous delta stored? */ - if ((pScreenPriv->iDeltaZ > 0 && iDeltaZ > 0) - || (pScreenPriv->iDeltaZ < 0 && iDeltaZ < 0)) { + if ((*iTotalDeltaZ > 0 && iDeltaZ > 0) + || (*iTotalDeltaZ < 0 && iDeltaZ < 0)) { /* Previous delta and of same sign as current delta */ - iDeltaZ += pScreenPriv->iDeltaZ; - pScreenPriv->iDeltaZ = 0; + iDeltaZ += *iTotalDeltaZ; + *iTotalDeltaZ = 0; } else { /* @@ -157,7 +163,7 @@ winMouseWheel(ScreenPtr pScreen, int iDeltaZ) * as blindly setting takes just as much time * as checking, then setting if necessary :) */ - pScreenPriv->iDeltaZ = 0; + *iTotalDeltaZ = 0; } /* @@ -165,7 +171,7 @@ winMouseWheel(ScreenPtr pScreen, int iDeltaZ) * WHEEL_DELTA */ if (iDeltaZ >= WHEEL_DELTA || (-1 * iDeltaZ) >= WHEEL_DELTA) { - pScreenPriv->iDeltaZ = 0; + *iTotalDeltaZ = 0; /* Figure out how many whole deltas of the wheel we have */ iDeltaZ /= WHEEL_DELTA; @@ -176,16 +182,16 @@ winMouseWheel(ScreenPtr pScreen, int iDeltaZ) * we will store the wheel delta until the threshold * has been reached. */ - pScreenPriv->iDeltaZ = iDeltaZ; + *iTotalDeltaZ = iDeltaZ; return 0; } /* Set the button to indicate up or down wheel delta */ if (iDeltaZ > 0) { - button = Button4; + button = iButtonUp; } else { - button = Button5; + button = iButtonDown; } /* diff --git a/xorg-server/hw/xwin/winmsgwindow.c b/xorg-server/hw/xwin/winmsgwindow.c new file mode 100644 index 000000000..8067c693c --- /dev/null +++ b/xorg-server/hw/xwin/winmsgwindow.c @@ -0,0 +1,180 @@ +/* + * Copyright (C) Jon TURNEY 2011 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +#include "win.h" + +/* + * This is the messaging window, a hidden top-level window. We never do anything + * with it, but other programs may send messages to it. + */ + +/* + * winMsgWindowProc - Window procedure for msg window + */ + +static +LRESULT CALLBACK +winMsgWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ +#if CYGDEBUG + winDebugWin32Message("winMsgWindowProc", hwnd, message, wParam, lParam); +#endif + + switch (message) { + case WM_ENDSESSION: + if (!wParam) + return 0; /* shutdown is being cancelled */ + + /* + Send a WM_GIVEUP message to the X server thread so it wakes up if + blocked in select(), performs GiveUp(), and then notices that GiveUp() + has set the DE_TERMINATE flag so exits the msg dispatch loop. + */ + { + ScreenPtr pScreen = screenInfo.screens[0]; + + winScreenPriv(pScreen); + PostMessage(pScreenPriv->hwndScreen, WM_GIVEUP, 0, 0); + } + + /* + This process will be terminated by the system almost immediately + after the last thread with a message queue returns from processing + WM_ENDSESSION, so we cannot rely on any code executing after this + message is processed and need to wait here until ddxGiveUp() is called + and releases the termination mutex to guarantee that the lock file and + unix domain sockets have been removed + + ofc, Microsoft doesn't document this under WM_ENDSESSION, you are supposed + to read the source of CRSS to find out how it works :-) + + http://blogs.msdn.com/b/michen/archive/2008/04/04/application-termination-when-user-logs-off.aspx + */ + { + int iReturn = pthread_mutex_lock(&g_pmTerminating); + + if (iReturn != 0) { + ErrorF("winMsgWindowProc - pthread_mutex_lock () failed: %d\n", + iReturn); + } + winDebug + ("winMsgWindowProc - WM_ENDSESSION termination lock acquired\n"); + } + + return 0; + } + + return DefWindowProc(hwnd, message, wParam, lParam); +} + +static HWND +winCreateMsgWindow(void) +{ + HWND hwndMsg; + wATOM winClass; + + // register window class + { + WNDCLASSEX wcx; + + wcx.cbSize = sizeof(WNDCLASSEX); + wcx.style = CS_HREDRAW | CS_VREDRAW; + wcx.lpfnWndProc = winMsgWindowProc; + wcx.cbClsExtra = 0; + wcx.cbWndExtra = 0; + wcx.hInstance = g_hInstance; + wcx.hIcon = NULL; + wcx.hCursor = 0; + wcx.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); + wcx.lpszMenuName = NULL; + wcx.lpszClassName = WINDOW_CLASS_X_MSG; + wcx.hIconSm = NULL; + winClass = RegisterClassEx(&wcx); + } + + // Create the msg window. + hwndMsg = CreateWindowEx(0, // no extended styles + WINDOW_CLASS_X_MSG, // class name + "XWin Msg Window", // window name + WS_OVERLAPPEDWINDOW, // overlapped window + CW_USEDEFAULT, // default horizontal position + CW_USEDEFAULT, // default vertical position + CW_USEDEFAULT, // default width + CW_USEDEFAULT, // default height + (HWND) NULL, // no parent or owner window + (HMENU) NULL, // class menu used + GetModuleHandle(NULL), // instance handle + NULL); // no window creation data + + if (!hwndMsg) { + ErrorF("winCreateMsgWindow - Create msg window failed\n"); + return NULL; + } + + winDebug("winCreateMsgWindow - Created msg window hwnd 0x%x\n", hwndMsg); + + return hwndMsg; +} + +static void * +winMsgWindowThreadProc(void *arg) +{ + HWND hwndMsg; + + winDebug("winMsgWindowThreadProc - Hello\n"); + + hwndMsg = winCreateMsgWindow(); + if (hwndMsg) { + MSG msg; + + /* Pump the msg window message queue */ + while (GetMessage(&msg, hwndMsg, 0, 0) > 0) { +#if CYGDEBUG + winDebugWin32Message("winMsgWindowThread", msg.hwnd, msg.message, + msg.wParam, msg.lParam); +#endif + DispatchMessage(&msg); + } + } + + winDebug("winMsgWindowThreadProc - Exit\n"); + + return NULL; +} + +Bool +winCreateMsgWindowThread(void) +{ + pthread_t ptMsgWindowThreadProc; + + /* Spawn a thread for the msg window */ + if (pthread_create(&ptMsgWindowThreadProc, + NULL, winMsgWindowThreadProc, NULL)) { + /* Bail if thread creation failed */ + ErrorF("winCreateMsgWindow - pthread_create failed.\n"); + return FALSE; + } + + return TRUE; +} diff --git a/xorg-server/hw/xwin/winmultiwindowclass.c b/xorg-server/hw/xwin/winmultiwindowclass.c index ced8f4554..6787332a3 100644 --- a/xorg-server/hw/xwin/winmultiwindowclass.c +++ b/xorg-server/hw/xwin/winmultiwindowclass.c @@ -68,7 +68,12 @@ winMultiWindowGetClassHint(WindowPtr pWin, char **res_name, char **res_class) while (prop) { if (prop->propertyName == XA_WM_CLASS && prop->type == XA_STRING && prop->format == 8 && prop->data) { + /* + WM_CLASS property should consist of 2 null terminated strings, but we + must handle the cases when one or both is absent or not null terminated + */ len_name = strlen((char *) prop->data); + if (len_name > prop->size) len_name = prop->size; (*res_name) = malloc(len_name + 1); @@ -77,13 +82,13 @@ winMultiWindowGetClassHint(WindowPtr pWin, char **res_name, char **res_class) return 0; } - /* Add one to len_name to allow copying of trailing 0 */ - strncpy((*res_name), prop->data, len_name + 1); + /* Copy name and ensure null terminated */ + strncpy((*res_name), prop->data, len_name); + (*res_name)[len_name] = '\0'; - if (len_name == prop->size) - len_name--; - - len_class = strlen(((char *) prop->data) + 1 + len_name); + /* Compute length of class name, it could be that it is absent or not null terminated */ + len_class = (len_name >= prop->size) ? 0 : (strlen(((char *) prop->data) + 1 + len_name)); + if (len_class > prop->size - 1 - len_name) len_class = prop->size - 1 - len_name; (*res_class) = malloc(len_class + 1); @@ -95,7 +100,9 @@ winMultiWindowGetClassHint(WindowPtr pWin, char **res_name, char **res_class) return 0; } - strcpy((*res_class), ((char *) prop->data) + 1 + len_name); + /* Copy class name and ensure null terminated */ + strncpy((*res_class), ((char *) prop->data) + 1 + len_name, len_class); + (*res_class)[len_class] = '\0'; return 1; } diff --git a/xorg-server/hw/xwin/winmultiwindowicons.c b/xorg-server/hw/xwin/winmultiwindowicons.c index bcc5688df..0531ad6c7 100644 --- a/xorg-server/hw/xwin/winmultiwindowicons.c +++ b/xorg-server/hw/xwin/winmultiwindowicons.c @@ -257,6 +257,10 @@ NetWMToWinIconAlpha(uint32_t * icon) 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); diff --git a/xorg-server/hw/xwin/winmultiwindowwm.c b/xorg-server/hw/xwin/winmultiwindowwm.c index 4f6dec78b..3c44f05e4 100644 --- a/xorg-server/hw/xwin/winmultiwindowwm.c +++ b/xorg-server/hw/xwin/winmultiwindowwm.c @@ -1470,7 +1470,7 @@ winMultiWindowWMErrorHandler(Display * pDisplay, XErrorEvent * pErr) static int winMultiWindowWMIOErrorHandler(Display * pDisplay) { - ErrorF("winMultiWindowWMIOErrorHandler!\n\n"); + ErrorF("winMultiWindowWMIOErrorHandler!\n"); if (pthread_equal(pthread_self(), g_winMultiWindowWMThread)) { if (g_shutdown) @@ -1510,7 +1510,7 @@ winMultiWindowXMsgProcErrorHandler(Display * pDisplay, XErrorEvent * pErr) static int winMultiWindowXMsgProcIOErrorHandler(Display * pDisplay) { - ErrorF("winMultiWindowXMsgProcIOErrorHandler!\n\n"); + ErrorF("winMultiWindowXMsgProcIOErrorHandler!\n"); if (pthread_equal(pthread_self(), g_winMultiWindowXMsgProcThread)) { /* Restart at the main entry point */ @@ -1626,23 +1626,27 @@ winApplyHints(Display * pDisplay, Window iWindow, HWND hWnd, HWND * zstyle) } if (XGetWindowProperty(pDisplay, iWindow, windowState, 0L, - 1L, False, XA_ATOM, &type, &format, + MAXINT, False, XA_ATOM, &type, &format, &nitems, &left, (unsigned char **) &pAtom) == Success) { - if (pAtom && nitems == 1) { - if (*pAtom == skiptaskbarState) - hint |= HINT_SKIPTASKBAR; - if (*pAtom == hiddenState) - maxmin |= HINT_MIN; - else if (*pAtom == fullscreenState) - maxmin |= HINT_MAX; - if (*pAtom == belowState) - *zstyle = HWND_BOTTOM; - else if (*pAtom == aboveState) - *zstyle = HWND_TOPMOST; - } - if (pAtom) + if (pAtom ) { + unsigned long i; + + for (i = 0; i < nitems; i++) { + if (pAtom[i] == skiptaskbarState) + hint |= HINT_SKIPTASKBAR; + if (pAtom[i] == hiddenState) + maxmin |= HINT_MIN; + else if (pAtom[i] == fullscreenState) + maxmin |= HINT_MAX; + if (pAtom[i] == belowState) + *zstyle = HWND_BOTTOM; + else if (pAtom[i] == aboveState) + *zstyle = HWND_TOPMOST; + } + XFree(pAtom); + } } nitems = left = 0; diff --git a/xorg-server/hw/xwin/winmultiwindowwndproc.c b/xorg-server/hw/xwin/winmultiwindowwndproc.c index 381818789..9292e73ca 100644 --- a/xorg-server/hw/xwin/winmultiwindowwndproc.c +++ b/xorg-server/hw/xwin/winmultiwindowwndproc.c @@ -661,7 +661,7 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; SetCapture(hwnd); - return winMouseButtonsHandle(s_pScreen, ButtonPress, HIWORD(wParam) + 5, + return winMouseButtonsHandle(s_pScreen, ButtonPress, HIWORD(wParam) + 7, wParam); case WM_XBUTTONUP: @@ -670,7 +670,7 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) ReleaseCapture(); winStartMousePolling(s_pScreenPriv); return winMouseButtonsHandle(s_pScreen, ButtonRelease, - HIWORD(wParam) + 5, wParam); + HIWORD(wParam) + 7, wParam); case WM_MOUSEWHEEL: if (SendMessage @@ -684,6 +684,18 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) else break; + case WM_MOUSEHWHEEL: + if (SendMessage + (hwnd, WM_NCHITTEST, 0, + MAKELONG(GET_X_LPARAM(lParam), + GET_Y_LPARAM(lParam))) == HTCLIENT) { + /* Pass the message to the root window */ + SendMessage(hwndScreen, message, wParam, lParam); + return 0; + } + else + break; + case WM_SETFOCUS: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) break; diff --git a/xorg-server/hw/xwin/winscrinit.c b/xorg-server/hw/xwin/winscrinit.c index 5623b8881..23152cbd2 100644 --- a/xorg-server/hw/xwin/winscrinit.c +++ b/xorg-server/hw/xwin/winscrinit.c @@ -703,7 +703,7 @@ winFinishScreenInitNativeGDI(int i, pScreenPriv->fEnabled = TRUE; ErrorF("winFinishScreenInitNativeGDI - Successful addition of " - "screen %08x\n", (unsigned int) pScreen); + "screen %p\n", pScreen); return TRUE; } diff --git a/xorg-server/hw/xwin/winwin32rootless.c b/xorg-server/hw/xwin/winwin32rootless.c index 210fea3fa..724976a84 100644 --- a/xorg-server/hw/xwin/winwin32rootless.c +++ b/xorg-server/hw/xwin/winwin32rootless.c @@ -312,8 +312,8 @@ winMWExtWMCreateFrame(RootlessWindowPtr pFrame, ScreenPtr pScreen, } #if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMCreateFrame - (%08x) %08x\n", - (int) pFrame->wid, (int) pRLWinPriv->hWnd); + winDebug("winMWExtWMCreateFrame - (%p) %p\n", + pFrame->wid, pRLWinPriv->hWnd); #if 0 { WindowPtr pWin2 = NULL; @@ -350,8 +350,8 @@ winMWExtWMDestroyFrame(RootlessFrameID wid) char pszClass[CLASS_NAME_LENGTH]; #if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMDestroyFrame (%08x) %08x\n", - (int) pRLWinPriv, (int) pRLWinPriv->hWnd); + winDebug("winMWExtWMDestroyFrame (%p) %p\n", + pRLWinPriv, pRLWinPriv->hWnd); #if 0 { WindowPtr pWin2 = NULL; @@ -416,7 +416,7 @@ winMWExtWMMoveFrame(RootlessFrameID wid, ScreenPtr pScreen, int iNewX, int iX, iY, iWidth, iHeight; #if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMMoveFrame (%08x) (%d %d)\n", (int) pRLWinPriv, iNewX, + winDebug("winMWExtWMMoveFrame (%p) (%d %d)\n", pRLWinPriv, iNewX, iNewY); #endif @@ -456,7 +456,7 @@ winMWExtWMMoveFrame(RootlessFrameID wid, ScreenPtr pScreen, int iNewX, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER); g_fNoConfigureWindow = FALSE; #if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMMoveFrame (%08x) done\n", (int) pRLWinPriv); + winDebug("winMWExtWMMoveFrame (%p) done\n", pRLWinPriv); #endif } @@ -474,8 +474,8 @@ winMWExtWMResizeFrame(RootlessFrameID wid, ScreenPtr pScreen, int iX, iY; #if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMResizeFrame (%08x) (%d %d)-(%d %d)\n", - (int) pRLWinPriv, iNewX, iNewY, uiNewWidth, uiNewHeight); + winDebug("winMWExtWMResizeFrame (%p) (%d %d)-(%d %d)\n", + pRLWinPriv, iNewX, iNewY, uiNewWidth, uiNewHeight); #endif pRLWinPriv->fResized = TRUE; @@ -526,7 +526,7 @@ winMWExtWMRestackFrame(RootlessFrameID wid, RootlessFrameID nextWid) Bool fNeedRestack = TRUE; #if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMRestackFrame (%08x)\n", (int) pRLWinPriv); + winDebug("winMWExtWMRestackFrame (%p)\n", pRLWinPriv); #endif if (pScreenPriv && pScreenPriv->fRestacking) @@ -612,7 +612,7 @@ winMWExtWMRestackFrame(RootlessFrameID wid, RootlessFrameID nextWid) 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); } #if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMRestackFrame - done (%08x)\n", (int) pRLWinPriv); + winDebug("winMWExtWMRestackFrame - done (%p)\n", pRLWinPriv); #endif pRLWinPriv->fRestackingNow = FALSE; @@ -626,7 +626,7 @@ winMWExtWMReshapeFrame(RootlessFrameID wid, RegionPtr pShape) RECT rcWindow, rcClient; #if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMReshapeFrame (%08x)\n", (int) pRLWinPriv); + winDebug("winMWExtWMReshapeFrame (%p)\n", pRLWinPriv); #endif hRgn = winMWExtWMCreateRgnFromRegion(pShape); @@ -655,7 +655,7 @@ winMWExtWMUnmapFrame(RootlessFrameID wid) win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) wid; #if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMUnmapFrame (%08x)\n", (int) pRLWinPriv); + winDebug("winMWExtWMUnmapFrame (%p)\n", pRLWinPriv); #endif g_fNoConfigureWindow = TRUE; @@ -680,7 +680,7 @@ winMWExtWMStartDrawing(RootlessFrameID wid, char **pixelData, int *bytesPerRow) HBITMAP hbmpNew; #if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMStartDrawing (%08x) %08x\n", (int) pRLWinPriv, + winDebug("winMWExtWMStartDrawing (%p) %08x\n", pRLWinPriv, pRLWinPriv->fDestroyed); #endif @@ -692,8 +692,8 @@ winMWExtWMStartDrawing(RootlessFrameID wid, char **pixelData, int *bytesPerRow) pScreenInfo = pScreenPriv->pScreenInfo; #if CYGMULTIWINDOW_DEBUG - winDebug("\tpScreenPriv %08X\n", (int) pScreenPriv); - winDebug("\tpScreenInfo %08X\n", (int) pScreenInfo); + winDebug("\tpScreenPriv %p\n", pScreenPriv); + winDebug("\tpScreenInfo %p\n", pScreenInfo); winDebug("\t(%d, %d)\n", (int) pRLWinPriv->pFrame->width, (int) pRLWinPriv->pFrame->height); #endif @@ -808,9 +808,9 @@ winMWExtWMStartDrawing(RootlessFrameID wid, char **pixelData, int *bytesPerRow) ErrorF("winMWExtWMStartDrawing - Already window was destroyed \n"); } #if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMStartDrawing - done (0x%08x) 0x%08x %d\n", - (int) pRLWinPriv, - (unsigned int) pRLWinPriv->pfb, + winDebug("winMWExtWMStartDrawing - done (%p) %p %d\n", + pRLWinPriv, + pRLWinPriv->pfb, (unsigned int) pRLWinPriv->dwWidthBytes); #endif *pixelData = pRLWinPriv->pfb; @@ -924,8 +924,8 @@ winMWExtWMRootlessSwitchWindow(RootlessWindowPtr pFrame, WindowPtr oldWin) win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) pFrame->wid; #if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMRootlessSwitchWindow (%08x) %08x\n", - (int) pRLWinPriv, (int) pRLWinPriv->hWnd); + winDebug("winMWExtWMRootlessSwitchWindow (%p) %p\n", + pRLWinPriv, pRLWinPriv->hWnd); #endif pRLWinPriv->pFrame = pFrame; pRLWinPriv->fResized = TRUE; @@ -979,8 +979,8 @@ winMWExtWMCopyWindow(RootlessFrameID wid, int nDstRects, RECT rcDmg; #if CYGMULTIWINDOW_DEBUG - winDebug("winMWExtWMCopyWindow (%08x, %d, %08x, %d, %d)\n", - (int) pRLWinPriv, nDstRects, (int) pDstRects, nDx, nDy); + winDebug("winMWExtWMCopyWindow (%p, %d, %p, %d, %d)\n", + pRLWinPriv, nDstRects, pDstRects, nDx, nDy); #endif for (pEnd = pDstRects + nDstRects; pDstRects < pEnd; pDstRects++) { diff --git a/xorg-server/hw/xwin/winwin32rootlesswindow.c b/xorg-server/hw/xwin/winwin32rootlesswindow.c index ce615e692..1faa531df 100644 --- a/xorg-server/hw/xwin/winwin32rootlesswindow.c +++ b/xorg-server/hw/xwin/winwin32rootlesswindow.c @@ -213,8 +213,8 @@ winMWExtWMUpdateWindowDecoration(win32RootlessWindowPtr pRLWinPriv, showCmd |= SWP_NOMOVE | SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOZORDER; - winDebug("winMWExtWMUpdateWindowDecoration %08x %s\n", - (int) pRLWinPriv, fDecorate ? "Decorate" : "Bare"); + winDebug("winMWExtWMUpdateWindowDecoration %p %s\n", + pRLWinPriv, fDecorate ? "Decorate" : "Bare"); /* Get the extended window style information */ dwExStyle = GetWindowLongPtr(pRLWinPriv->hWnd, GWL_EXSTYLE); diff --git a/xorg-server/hw/xwin/winwin32rootlesswndproc.c b/xorg-server/hw/xwin/winwin32rootlesswndproc.c index 13df18677..001d0d2fc 100644 --- a/xorg-server/hw/xwin/winwin32rootlesswndproc.c +++ b/xorg-server/hw/xwin/winwin32rootlesswndproc.c @@ -649,13 +649,13 @@ winMWExtWMWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput) break; SetCapture(hwnd); - return winMouseButtonsHandle(pScreen, ButtonPress, HIWORD(wParam) + 5, + return winMouseButtonsHandle(pScreen, ButtonPress, HIWORD(wParam) + 7, wParam); case WM_XBUTTONUP: if (pScreenPriv == NULL || pScreenInfo->fIgnoreInput) break; ReleaseCapture(); - return winMouseButtonsHandle(pScreen, ButtonRelease, HIWORD(wParam) + 5, + return winMouseButtonsHandle(pScreen, ButtonRelease, HIWORD(wParam) + 7, wParam); case WM_MOUSEWHEEL: @@ -667,6 +667,15 @@ winMWExtWMWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 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"); @@ -823,24 +832,24 @@ winMWExtWMWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) if (!(pWinPos->flags & SWP_NOZORDER)) { if (pRLWinPriv->fRestackingNow || pScreenPriv->fRestacking) { #if CYGMULTIWINDOW_DEBUG - winDebug("Win %08x is now restacking.\n", - (unsigned int) pRLWinPriv); + winDebug("Win %p is now restacking.\n", + pRLWinPriv); #endif break; } if (winIsInternalWMRunning(pScreenInfo) || IsRaiseOnClick(pWin)) { #if CYGMULTIWINDOW_DEBUG - winDebug("Win %08x has WINDOWSWM_RAISE_ON_CLICK.\n", - (unsigned int) pRLWinPriv); + winDebug("Win %p has WINDOWSWM_RAISE_ON_CLICK.\n", + pRLWinPriv); #endif break; } #if CYGMULTIWINDOW_DEBUG - winDebug("Win %08x forbid to change z order (%08x).\n", - (unsigned int) pRLWinPriv, - (unsigned int) pWinPos->hwndInsertAfter); + winDebug("Win %p forbid to change z order (%p).\n", + pRLWinPriv, + pWinPos->hwndInsertAfter); #endif pWinPos->flags |= SWP_NOZORDER; } diff --git a/xorg-server/hw/xwin/winwindow.h b/xorg-server/hw/xwin/winwindow.h index 25826ecc7..7e6bd565c 100644 --- a/xorg-server/hw/xwin/winwindow.h +++ b/xorg-server/hw/xwin/winwindow.h @@ -49,6 +49,7 @@ #define WINDOW_TITLE_XDMCP "%s:%s.%d" #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_TITLE_X PROJECT_NAME " X" #define WIN_WINDOW_PROP "cyg_window_prop_rl" #ifdef HAS_DEVWINDOWS diff --git a/xorg-server/hw/xwin/winwindowswm.c b/xorg-server/hw/xwin/winwindowswm.c index 6e9d63c53..be43265e0 100644 --- a/xorg-server/hw/xwin/winwindowswm.c +++ b/xorg-server/hw/xwin/winwindowswm.c @@ -246,7 +246,7 @@ winWindowsWMSendEvent(int type, unsigned int mask, int which, int arg, for (pEvent = *pHead; pEvent; pEvent = pEvent->next) { client = pEvent->client; #if CYGMULTIWINDOW_DEBUG - ErrorF("winWindowsWMSendEvent - x%08x\n", (int) client); + ErrorF("winWindowsWMSendEvent - %p\n", client); #endif if ((pEvent->mask & mask) == 0) { continue; @@ -381,8 +381,8 @@ ProcWindowsWMFrameDraw(ClientPtr client) return BadWindow; #if CYGMULTIWINDOW_DEBUG - ErrorF("ProcWindowsWMFrameDraw - HWND 0x%08x 0x%08x 0x%08x\n", - (int) pRLWinPriv->hWnd, (int) stuff->frame_style, + 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); diff --git a/xorg-server/hw/xwin/winwndproc.c b/xorg-server/hw/xwin/winwndproc.c index c7509ea19..c73a75c6f 100644 --- a/xorg-server/hw/xwin/winwndproc.c +++ b/xorg-server/hw/xwin/winwndproc.c @@ -894,7 +894,7 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) #endif ) SetCapture(hwnd); - return winMouseButtonsHandle(s_pScreen, ButtonPress, HIWORD(wParam) + 5, + return winMouseButtonsHandle(s_pScreen, ButtonPress, HIWORD(wParam) + 7, wParam); case WM_XBUTTONUP: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) @@ -906,7 +906,7 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) ) ReleaseCapture(); return winMouseButtonsHandle(s_pScreen, ButtonRelease, - HIWORD(wParam) + 5, wParam); + HIWORD(wParam) + 7, wParam); case WM_TIMER: if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) @@ -976,7 +976,20 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) #if CYGDEBUG winDebug("winWindowProc - WM_MOUSEWHEEL\n"); #endif - winMouseWheel(s_pScreen, GET_WHEEL_DELTA_WPARAM(wParam)); + /* Button4 = WheelUp */ + /* Button5 = WheelDown */ + winMouseWheel(&(s_pScreenPriv->iDeltaZ), GET_WHEEL_DELTA_WPARAM(wParam), Button4, Button5); + break; + + case WM_MOUSEHWHEEL: + if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput) + break; +#if CYGDEBUG + winDebug("winWindowProc - WM_MOUSEHWHEEL\n"); +#endif + /* Button7 = TiltRight */ + /* Button6 = TiltLeft */ + winMouseWheel(&(s_pScreenPriv->iDeltaV), GET_WHEEL_DELTA_WPARAM(wParam), 7, 6); break; case WM_SETFOCUS: @@ -1064,7 +1077,7 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) } /* Translate Windows key code to X scan code */ - winTranslateKey(wParam, lParam, &iScanCode); + iScanCode = winTranslateKey(wParam, lParam); /* Ignore repeats for CapsLock */ if (wParam == VK_CAPITAL) @@ -1093,7 +1106,7 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) return 0; /* Enqueue a keyup event */ - winTranslateKey(wParam, lParam, &iScanCode); + iScanCode = winTranslateKey(wParam, lParam); winSendKeyEvent(iScanCode, FALSE); /* Release all pressed shift keys */ @@ -1147,6 +1160,7 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) /* Clear any lingering wheel delta */ s_pScreenPriv->iDeltaZ = 0; + s_pScreenPriv->iDeltaV = 0; /* Reshow the Windows mouse cursor if we are being deactivated */ if (g_fSoftwareCursor && LOWORD(wParam) == WA_INACTIVE && !g_fCursor) { @@ -1221,7 +1235,6 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) } break; - case WM_ENDSESSION: case WM_GIVEUP: /* Tell X that we are giving up */ #ifdef XWIN_MULTIWINDOW |