diff options
author | marha <marha@users.sourceforge.net> | 2011-04-28 11:14:32 +0000 |
---|---|---|
committer | marha <marha@users.sourceforge.net> | 2011-04-28 11:14:32 +0000 |
commit | 1840c5631682e0a69ed11487a23a43d45f2d15e1 (patch) | |
tree | fe954636044c0057b9f08e76d19489493ff09745 /xorg-server/hw | |
parent | 2ab09dc03e4ecc726ee7b5528306b0fe3e5b1837 (diff) | |
parent | 57a879849643e79d9674198a3a77c59532fb79b4 (diff) | |
download | vcxsrv-1840c5631682e0a69ed11487a23a43d45f2d15e1.tar.gz vcxsrv-1840c5631682e0a69ed11487a23a43d45f2d15e1.tar.bz2 vcxsrv-1840c5631682e0a69ed11487a23a43d45f2d15e1.zip |
svn merge ^/branches/released .
Diffstat (limited to 'xorg-server/hw')
53 files changed, 11279 insertions, 11444 deletions
diff --git a/xorg-server/hw/xfree86/ddc/ddcProperty.c b/xorg-server/hw/xfree86/ddc/ddcProperty.c index d4ae1006d..36ade8a5f 100644 --- a/xorg-server/hw/xfree86/ddc/ddcProperty.c +++ b/xorg-server/hw/xfree86/ddc/ddcProperty.c @@ -30,7 +30,6 @@ #include <X11/Xatom.h>
#include "property.h"
#include "propertyst.h"
-#include "xf86DDC.h"
#include <string.h>
#define EDID1_ATOM_NAME "XFree86_DDC_EDID1_RAWDATA"
diff --git a/xorg-server/hw/xfree86/dri/dri.c b/xorg-server/hw/xfree86/dri/dri.c index 17bf51c0e..cf83c002e 100644 --- a/xorg-server/hw/xfree86/dri/dri.c +++ b/xorg-server/hw/xfree86/dri/dri.c @@ -63,8 +63,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "dri.h"
#include "sarea.h"
#include "dristruct.h"
-#include "xf86.h"
-#include "xf86drm.h"
#include "mi.h"
#include "mipointer.h"
#include "xf86_OSproc.h"
diff --git a/xorg-server/hw/xfree86/dri/xf86dri.c b/xorg-server/hw/xfree86/dri/xf86dri.c index cd1085b36..ba9d5a1e4 100644 --- a/xorg-server/hw/xfree86/dri/xf86dri.c +++ b/xorg-server/hw/xfree86/dri/xf86dri.c @@ -58,7 +58,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "dri.h"
#include "sarea.h"
#include "dristruct.h"
-#include "xf86.h"
#include "xf86drm.h"
#include "protocol-versions.h"
diff --git a/xorg-server/hw/xfree86/fbdevhw/fbdevhw.c b/xorg-server/hw/xfree86/fbdevhw/fbdevhw.c index ef69d58bc..d98c40be9 100644 --- a/xorg-server/hw/xfree86/fbdevhw/fbdevhw.c +++ b/xorg-server/hw/xfree86/fbdevhw/fbdevhw.c @@ -48,7 +48,6 @@ _X_EXPORT XF86ModuleData fbdevhwModuleData = { #include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
-#include <string.h>
/* -------------------------------------------------------------------- */
/* our private data, and two functions to allocate/free this */
diff --git a/xorg-server/hw/xfree86/modes/xf86RandR12.c b/xorg-server/hw/xfree86/modes/xf86RandR12.c index bd8421713..6d676363b 100644 --- a/xorg-server/hw/xfree86/modes/xf86RandR12.c +++ b/xorg-server/hw/xfree86/modes/xf86RandR12.c @@ -31,7 +31,6 @@ #include "xf86.h"
#include "os.h"
#include "globals.h"
-#include "xf86.h"
#include "xf86Priv.h"
#include "xf86DDC.h"
#include "mipointer.h"
diff --git a/xorg-server/hw/xnest/Pixmap.c b/xorg-server/hw/xnest/Pixmap.c index da81a1d06..acbe1a7cb 100644 --- a/xorg-server/hw/xnest/Pixmap.c +++ b/xorg-server/hw/xnest/Pixmap.c @@ -21,7 +21,6 @@ is" without express or implied warranty. #include "regionstr.h"
#include "pixmapstr.h"
#include "scrnintstr.h"
-#include "regionstr.h"
#include "gc.h"
#include "servermd.h"
#include "privates.h"
diff --git a/xorg-server/hw/xquartz/GL/capabilities.c b/xorg-server/hw/xquartz/GL/capabilities.c index fc7dd57dd..da52cc7c4 100644 --- a/xorg-server/hw/xquartz/GL/capabilities.c +++ b/xorg-server/hw/xquartz/GL/capabilities.c @@ -1,543 +1,543 @@ -/* - * Copyright (c) 2008 Apple Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice 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. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <assert.h> -#include <OpenGL/OpenGL.h> -#include <OpenGL/gl.h> -#include <OpenGL/glu.h> -#include <OpenGL/glext.h> -#include <ApplicationServices/ApplicationServices.h> - -#include "capabilities.h" - -#define Cursor X_Cursor -#include "os.h" -#undef Cursor - -static void handleBufferModes(struct glCapabilitiesConfig *c, GLint bufferModes) { - if(bufferModes & kCGLStereoscopicBit) { - c->stereo = true; - } - - if(bufferModes & kCGLDoubleBufferBit) { - c->buffers = 2; - } else { - c->buffers = 1; - } -} - -static void handleStencilModes(struct glCapabilitiesConfig *c, GLint smodes) { - int offset = 0; - - if(kCGL0Bit & smodes) - c->stencil_bit_depths[offset++] = 0; - - if(kCGL1Bit & smodes) - c->stencil_bit_depths[offset++] = 1; - - if(kCGL2Bit & smodes) - c->stencil_bit_depths[offset++] = 2; - - if(kCGL3Bit & smodes) - c->stencil_bit_depths[offset++] = 3; - - if(kCGL4Bit & smodes) - c->stencil_bit_depths[offset++] = 4; - - if(kCGL5Bit & smodes) - c->stencil_bit_depths[offset++] = 5; - - if(kCGL6Bit & smodes) - c->stencil_bit_depths[offset++] = 6; - - if(kCGL8Bit & smodes) - c->stencil_bit_depths[offset++] = 8; - - if(kCGL10Bit & smodes) - c->stencil_bit_depths[offset++] = 10; - - if(kCGL12Bit & smodes) - c->stencil_bit_depths[offset++] = 12; - - if(kCGL16Bit & smodes) - c->stencil_bit_depths[offset++] = 16; - - if(kCGL24Bit & smodes) - c->stencil_bit_depths[offset++] = 24; - - if(kCGL32Bit & smodes) - c->stencil_bit_depths[offset++] = 32; - - if(kCGL48Bit & smodes) - c->stencil_bit_depths[offset++] = 48; - - if(kCGL64Bit & smodes) - c->stencil_bit_depths[offset++] = 64; - - if(kCGL96Bit & smodes) - c->stencil_bit_depths[offset++] = 96; - - if(kCGL128Bit & smodes) - c->stencil_bit_depths[offset++] = 128; - - assert(offset < GLCAPS_STENCIL_BIT_DEPTH_BUFFERS); - - c->total_stencil_bit_depths = offset; -} - -static int handleColorAndAccumulation(struct glColorBufCapabilities *c, - GLint cmodes, int forAccum) { - int offset = 0; - - /*1*/ - if(kCGLRGB444Bit & cmodes) { - c[offset].r = 4; - c[offset].g = 4; - c[offset].b = 4; - ++offset; - } - - /*2*/ - if(kCGLARGB4444Bit & cmodes) { - c[offset].a = 4; - c[offset].r = 4; - c[offset].g = 4; - c[offset].b = 4; - c[offset].is_argb = true; - ++offset; - } - - /*3*/ - if(kCGLRGB444A8Bit & cmodes) { - c[offset].r = 4; - c[offset].g = 4; - c[offset].b = 4; - c[offset].a = 8; - ++offset; - } - - /*4*/ - if(kCGLRGB555Bit & cmodes) { - c[offset].r = 5; - c[offset].g = 5; - c[offset].b = 5; - ++offset; - } - - /*5*/ - if(kCGLARGB1555Bit & cmodes) { - c[offset].a = 1; - c[offset].r = 5; - c[offset].g = 5; - c[offset].b = 5; - c[offset].is_argb = true; - ++offset; - } - - /*6*/ - if(kCGLRGB555A8Bit & cmodes) { - c[offset].r = 5; - c[offset].g = 5; - c[offset].b = 5; - c[offset].a = 8; - ++offset; - } - - /*7*/ - if(kCGLRGB565Bit & cmodes) { - c[offset].r = 5; - c[offset].g = 6; - c[offset].b = 5; - ++offset; - } - - /*8*/ - if(kCGLRGB565A8Bit & cmodes) { - c[offset].r = 5; - c[offset].g = 6; - c[offset].b = 5; - c[offset].a = 8; - ++offset; - } - - /*9*/ - if(kCGLRGB888Bit & cmodes) { - c[offset].r = 8; - c[offset].g = 8; - c[offset].b = 8; - ++offset; - } - - /*10*/ - if(kCGLARGB8888Bit & cmodes) { - c[offset].a = 8; - c[offset].r = 8; - c[offset].g = 8; - c[offset].b = 8; - c[offset].is_argb = true; - ++offset; - } - - /*11*/ - if(kCGLRGB888A8Bit & cmodes) { - c[offset].r = 8; - c[offset].g = 8; - c[offset].b = 8; - c[offset].a = 8; - ++offset; - } - - if(forAccum) { -//#if 0 - /* FIXME - * Disable this path, because some part of libGL, X, or Xplugin - * doesn't work with sizes greater than 8. - * When this is enabled and visuals are chosen using depths - * such as 16, the result is that the windows don't redraw - * and are often white, until a resize. - */ - - /*12*/ - if(kCGLRGB101010Bit & cmodes) { - c[offset].r = 10; - c[offset].g = 10; - c[offset].b = 10; - ++offset; - } - - /*13*/ - if(kCGLARGB2101010Bit & cmodes) { - c[offset].a = 2; - c[offset].r = 10; - c[offset].g = 10; - c[offset].b = 10; - c[offset].is_argb = true; - ++offset; - } - - /*14*/ - if(kCGLRGB101010_A8Bit & cmodes) { - c[offset].r = 10; - c[offset].g = 10; - c[offset].b = 10; - c[offset].a = 8; - ++offset; - } - - /*15*/ - if(kCGLRGB121212Bit & cmodes) { - c[offset].r = 12; - c[offset].g = 12; - c[offset].b = 12; - ++offset; - } - - /*16*/ - if(kCGLARGB12121212Bit & cmodes) { - c[offset].a = 12; - c[offset].r = 12; - c[offset].g = 12; - c[offset].b = 12; - c[offset].is_argb = true; - ++offset; - } - - /*17*/ - if(kCGLRGB161616Bit & cmodes) { - c[offset].r = 16; - c[offset].g = 16; - c[offset].b = 16; - ++offset; - } - - /*18*/ - if(kCGLRGBA16161616Bit & cmodes) { - c[offset].r = 16; - c[offset].g = 16; - c[offset].b = 16; - c[offset].a = 16; - ++offset; - } - } -//#endif - - /* FIXME should we handle the floating point color modes, and if so, how? */ - - return offset; -} - - -static void handleColorModes(struct glCapabilitiesConfig *c, GLint cmodes) { - c->total_color_buffers = handleColorAndAccumulation(c->color_buffers, - cmodes, 0); - - assert(c->total_color_buffers < GLCAPS_COLOR_BUFFERS); -} - -static void handleAccumulationModes(struct glCapabilitiesConfig *c, GLint cmodes) { - c->total_accum_buffers = handleColorAndAccumulation(c->accum_buffers, - cmodes, 1); - assert(c->total_accum_buffers < GLCAPS_COLOR_BUFFERS); -} - -static void handleDepthModes(struct glCapabilitiesConfig *c, GLint dmodes) { - int offset = 0; -#define DEPTH(flag,value) do { \ - if(dmodes & flag) { \ - c->depth_buffers[offset++] = value; \ - } \ - } while(0) - - /*1*/ - DEPTH(kCGL0Bit, 0); - /*2*/ - DEPTH(kCGL1Bit, 1); - /*3*/ - DEPTH(kCGL2Bit, 2); - /*4*/ - DEPTH(kCGL3Bit, 3); - /*5*/ - DEPTH(kCGL4Bit, 4); - /*6*/ - DEPTH(kCGL5Bit, 5); - /*7*/ - DEPTH(kCGL6Bit, 6); - /*8*/ - DEPTH(kCGL8Bit, 8); - /*9*/ - DEPTH(kCGL10Bit, 10); - /*10*/ - DEPTH(kCGL12Bit, 12); - /*11*/ - DEPTH(kCGL16Bit, 16); - /*12*/ - DEPTH(kCGL24Bit, 24); - /*13*/ - DEPTH(kCGL32Bit, 32); - /*14*/ - DEPTH(kCGL48Bit, 48); - /*15*/ - DEPTH(kCGL64Bit, 64); - /*16*/ - DEPTH(kCGL96Bit, 96); - /*17*/ - DEPTH(kCGL128Bit, 128); - -#undef DEPTH - - c->total_depth_buffer_depths = offset; - assert(c->total_depth_buffer_depths < GLCAPS_DEPTH_BUFFERS); -} - -/* Return non-zero if an error occured. */ -static CGLError handleRendererDescriptions(CGLRendererInfoObj info, GLint r, - struct glCapabilitiesConfig *c) { - CGLError err; - GLint accelerated = 0, flags = 0, aux = 0, samplebufs = 0, samples = 0; - - err = CGLDescribeRenderer (info, r, kCGLRPAccelerated, &accelerated); - - if(err) - return err; - - c->accelerated = accelerated; - - /* Buffering modes: single/double, stereo */ - err = CGLDescribeRenderer(info, r, kCGLRPBufferModes, &flags); - - if(err) - return err; - - handleBufferModes(c, flags); - - /* AUX buffers */ - err = CGLDescribeRenderer(info, r, kCGLRPMaxAuxBuffers, &aux); - - if(err) - return err; - - c->aux_buffers = aux; - - - /* Depth buffer size */ - err = CGLDescribeRenderer(info, r, kCGLRPDepthModes, &flags); - - if(err) - return err; - - handleDepthModes(c, flags); - - - /* Multisample buffers */ - err = CGLDescribeRenderer(info, r, kCGLRPMaxSampleBuffers, &samplebufs); - - if(err) - return err; - - c->multisample_buffers = samplebufs; - - - /* Multisample samples per multisample buffer */ - err = CGLDescribeRenderer(info, r, kCGLRPMaxSamples, &samples); - - if(err) - return err; - - c->multisample_samples = samples; - - - /* Stencil bit depths */ - err = CGLDescribeRenderer(info, r, kCGLRPStencilModes, &flags); - - if(err) - return err; - - handleStencilModes(c, flags); - - - /* Color modes (RGB/RGBA depths supported */ - err = CGLDescribeRenderer(info, r, kCGLRPColorModes, &flags); - - if(err) - return err; - - handleColorModes(c, flags); - - err = CGLDescribeRenderer(info, r, kCGLRPAccumModes, &flags); - - if(err) - return err; - - handleAccumulationModes(c, flags); - - return kCGLNoError; -} - -static void initCapabilities(struct glCapabilities *cap) { - cap->configurations = NULL; - cap->total_configurations = 0; -} - -static void initConfig(struct glCapabilitiesConfig *c) { - int i; - - c->accelerated = false; - c->stereo = false; - c->aux_buffers = 0; - c->buffers = 0; - - c->total_depth_buffer_depths = 0; - - for(i = 0; i < GLCAPS_DEPTH_BUFFERS; ++i) { - c->depth_buffers[i] = GLCAPS_INVALID_DEPTH_VALUE; - } - - c->multisample_buffers = 0; - c->multisample_samples = 0; - - c->total_stencil_bit_depths = 0; - - for(i = 0; i < GLCAPS_STENCIL_BIT_DEPTH_BUFFERS; ++i) { - c->stencil_bit_depths[i] = GLCAPS_INVALID_STENCIL_DEPTH; - } - - c->total_color_buffers = 0; - - for(i = 0; i < GLCAPS_COLOR_BUFFERS; ++i) { - c->color_buffers[i].r = c->color_buffers[i].g = - c->color_buffers[i].b = c->color_buffers[i].a = - GLCAPS_COLOR_BUF_INVALID_VALUE; - c->color_buffers[i].is_argb = false; - } - - c->total_accum_buffers = 0; - - for(i = 0; i < GLCAPS_COLOR_BUFFERS; ++i) { - c->accum_buffers[i].r = c->accum_buffers[i].g = - c->accum_buffers[i].b = c->accum_buffers[i].a = - GLCAPS_COLOR_BUF_INVALID_VALUE; - c->accum_buffers[i].is_argb = false; - } - - c->next = NULL; -} - -void freeGlCapabilities(struct glCapabilities *cap) { - struct glCapabilitiesConfig *conf, *next; - - conf = cap->configurations; - - while(conf) { - next = conf->next; - free(conf); - conf = next; - } - - cap->configurations = NULL; -} - -/*Return true if an error occured. */ -bool getGlCapabilities(struct glCapabilities *cap) { - CGLRendererInfoObj info; - CGLError err; - GLint numRenderers = 0, r; - - initCapabilities(cap); - - err = CGLQueryRendererInfo((GLuint)-1, &info, &numRenderers); - if(err) { - fprintf(stderr, "CGLQueryRendererInfo error: %s\n", CGLErrorString(err)); - return err; - } - - for(r = 0; r < numRenderers; r++) { - struct glCapabilitiesConfig tmpconf, *conf; - - initConfig(&tmpconf); - - err = handleRendererDescriptions(info, r, &tmpconf); - if(err) { - fprintf(stderr, "handleRendererDescriptions returned error: %s\n", CGLErrorString(err)); - fprintf(stderr, "trying to continue...\n"); - continue; - } - - conf = malloc(sizeof(*conf)); - if(NULL == conf) { - FatalError("Unable to allocate memory for OpenGL capabilities\n"); - } - - /* Copy the struct. */ - *conf = tmpconf; - - /* Now link the configuration into the list. */ - conf->next = cap->configurations; - cap->configurations = conf; - } - - CGLDestroyRendererInfo(info); - - /* No error occured. We are done. */ - return kCGLNoError; -} +/*
+ * Copyright (c) 2008 Apple Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <OpenGL/OpenGL.h>
+#include <OpenGL/gl.h>
+#include <OpenGL/glu.h>
+#include <OpenGL/glext.h>
+#include <ApplicationServices/ApplicationServices.h>
+
+#include "capabilities.h"
+
+#define Cursor X_Cursor
+#include "os.h"
+#undef Cursor
+
+static void handleBufferModes(struct glCapabilitiesConfig *c, GLint bufferModes) {
+ if(bufferModes & kCGLStereoscopicBit) {
+ c->stereo = true;
+ }
+
+ if(bufferModes & kCGLDoubleBufferBit) {
+ c->buffers = 2;
+ } else {
+ c->buffers = 1;
+ }
+}
+
+static void handleStencilModes(struct glCapabilitiesConfig *c, GLint smodes) {
+ int offset = 0;
+
+ if(kCGL0Bit & smodes)
+ c->stencil_bit_depths[offset++] = 0;
+
+ if(kCGL1Bit & smodes)
+ c->stencil_bit_depths[offset++] = 1;
+
+ if(kCGL2Bit & smodes)
+ c->stencil_bit_depths[offset++] = 2;
+
+ if(kCGL3Bit & smodes)
+ c->stencil_bit_depths[offset++] = 3;
+
+ if(kCGL4Bit & smodes)
+ c->stencil_bit_depths[offset++] = 4;
+
+ if(kCGL5Bit & smodes)
+ c->stencil_bit_depths[offset++] = 5;
+
+ if(kCGL6Bit & smodes)
+ c->stencil_bit_depths[offset++] = 6;
+
+ if(kCGL8Bit & smodes)
+ c->stencil_bit_depths[offset++] = 8;
+
+ if(kCGL10Bit & smodes)
+ c->stencil_bit_depths[offset++] = 10;
+
+ if(kCGL12Bit & smodes)
+ c->stencil_bit_depths[offset++] = 12;
+
+ if(kCGL16Bit & smodes)
+ c->stencil_bit_depths[offset++] = 16;
+
+ if(kCGL24Bit & smodes)
+ c->stencil_bit_depths[offset++] = 24;
+
+ if(kCGL32Bit & smodes)
+ c->stencil_bit_depths[offset++] = 32;
+
+ if(kCGL48Bit & smodes)
+ c->stencil_bit_depths[offset++] = 48;
+
+ if(kCGL64Bit & smodes)
+ c->stencil_bit_depths[offset++] = 64;
+
+ if(kCGL96Bit & smodes)
+ c->stencil_bit_depths[offset++] = 96;
+
+ if(kCGL128Bit & smodes)
+ c->stencil_bit_depths[offset++] = 128;
+
+ assert(offset < GLCAPS_STENCIL_BIT_DEPTH_BUFFERS);
+
+ c->total_stencil_bit_depths = offset;
+}
+
+static int handleColorAndAccumulation(struct glColorBufCapabilities *c,
+ GLint cmodes, int forAccum) {
+ int offset = 0;
+
+ /*1*/
+ if(kCGLRGB444Bit & cmodes) {
+ c[offset].r = 4;
+ c[offset].g = 4;
+ c[offset].b = 4;
+ ++offset;
+ }
+
+ /*2*/
+ if(kCGLARGB4444Bit & cmodes) {
+ c[offset].a = 4;
+ c[offset].r = 4;
+ c[offset].g = 4;
+ c[offset].b = 4;
+ c[offset].is_argb = true;
+ ++offset;
+ }
+
+ /*3*/
+ if(kCGLRGB444A8Bit & cmodes) {
+ c[offset].r = 4;
+ c[offset].g = 4;
+ c[offset].b = 4;
+ c[offset].a = 8;
+ ++offset;
+ }
+
+ /*4*/
+ if(kCGLRGB555Bit & cmodes) {
+ c[offset].r = 5;
+ c[offset].g = 5;
+ c[offset].b = 5;
+ ++offset;
+ }
+
+ /*5*/
+ if(kCGLARGB1555Bit & cmodes) {
+ c[offset].a = 1;
+ c[offset].r = 5;
+ c[offset].g = 5;
+ c[offset].b = 5;
+ c[offset].is_argb = true;
+ ++offset;
+ }
+
+ /*6*/
+ if(kCGLRGB555A8Bit & cmodes) {
+ c[offset].r = 5;
+ c[offset].g = 5;
+ c[offset].b = 5;
+ c[offset].a = 8;
+ ++offset;
+ }
+
+ /*7*/
+ if(kCGLRGB565Bit & cmodes) {
+ c[offset].r = 5;
+ c[offset].g = 6;
+ c[offset].b = 5;
+ ++offset;
+ }
+
+ /*8*/
+ if(kCGLRGB565A8Bit & cmodes) {
+ c[offset].r = 5;
+ c[offset].g = 6;
+ c[offset].b = 5;
+ c[offset].a = 8;
+ ++offset;
+ }
+
+ /*9*/
+ if(kCGLRGB888Bit & cmodes) {
+ c[offset].r = 8;
+ c[offset].g = 8;
+ c[offset].b = 8;
+ ++offset;
+ }
+
+ /*10*/
+ if(kCGLARGB8888Bit & cmodes) {
+ c[offset].a = 8;
+ c[offset].r = 8;
+ c[offset].g = 8;
+ c[offset].b = 8;
+ c[offset].is_argb = true;
+ ++offset;
+ }
+
+ /*11*/
+ if(kCGLRGB888A8Bit & cmodes) {
+ c[offset].r = 8;
+ c[offset].g = 8;
+ c[offset].b = 8;
+ c[offset].a = 8;
+ ++offset;
+ }
+
+ if(forAccum) {
+//#if 0
+ /* FIXME
+ * Disable this path, because some part of libGL, X, or Xplugin
+ * doesn't work with sizes greater than 8.
+ * When this is enabled and visuals are chosen using depths
+ * such as 16, the result is that the windows don't redraw
+ * and are often white, until a resize.
+ */
+
+ /*12*/
+ if(kCGLRGB101010Bit & cmodes) {
+ c[offset].r = 10;
+ c[offset].g = 10;
+ c[offset].b = 10;
+ ++offset;
+ }
+
+ /*13*/
+ if(kCGLARGB2101010Bit & cmodes) {
+ c[offset].a = 2;
+ c[offset].r = 10;
+ c[offset].g = 10;
+ c[offset].b = 10;
+ c[offset].is_argb = true;
+ ++offset;
+ }
+
+ /*14*/
+ if(kCGLRGB101010_A8Bit & cmodes) {
+ c[offset].r = 10;
+ c[offset].g = 10;
+ c[offset].b = 10;
+ c[offset].a = 8;
+ ++offset;
+ }
+
+ /*15*/
+ if(kCGLRGB121212Bit & cmodes) {
+ c[offset].r = 12;
+ c[offset].g = 12;
+ c[offset].b = 12;
+ ++offset;
+ }
+
+ /*16*/
+ if(kCGLARGB12121212Bit & cmodes) {
+ c[offset].a = 12;
+ c[offset].r = 12;
+ c[offset].g = 12;
+ c[offset].b = 12;
+ c[offset].is_argb = true;
+ ++offset;
+ }
+
+ /*17*/
+ if(kCGLRGB161616Bit & cmodes) {
+ c[offset].r = 16;
+ c[offset].g = 16;
+ c[offset].b = 16;
+ ++offset;
+ }
+
+ /*18*/
+ if(kCGLRGBA16161616Bit & cmodes) {
+ c[offset].r = 16;
+ c[offset].g = 16;
+ c[offset].b = 16;
+ c[offset].a = 16;
+ ++offset;
+ }
+ }
+//#endif
+
+ /* FIXME should we handle the floating point color modes, and if so, how? */
+
+ return offset;
+}
+
+
+static void handleColorModes(struct glCapabilitiesConfig *c, GLint cmodes) {
+ c->total_color_buffers = handleColorAndAccumulation(c->color_buffers,
+ cmodes, 0);
+
+ assert(c->total_color_buffers < GLCAPS_COLOR_BUFFERS);
+}
+
+static void handleAccumulationModes(struct glCapabilitiesConfig *c, GLint cmodes) {
+ c->total_accum_buffers = handleColorAndAccumulation(c->accum_buffers,
+ cmodes, 1);
+ assert(c->total_accum_buffers < GLCAPS_COLOR_BUFFERS);
+}
+
+static void handleDepthModes(struct glCapabilitiesConfig *c, GLint dmodes) {
+ int offset = 0;
+#define DEPTH(flag,value) do { \
+ if(dmodes & flag) { \
+ c->depth_buffers[offset++] = value; \
+ } \
+ } while(0)
+
+ /*1*/
+ DEPTH(kCGL0Bit, 0);
+ /*2*/
+ DEPTH(kCGL1Bit, 1);
+ /*3*/
+ DEPTH(kCGL2Bit, 2);
+ /*4*/
+ DEPTH(kCGL3Bit, 3);
+ /*5*/
+ DEPTH(kCGL4Bit, 4);
+ /*6*/
+ DEPTH(kCGL5Bit, 5);
+ /*7*/
+ DEPTH(kCGL6Bit, 6);
+ /*8*/
+ DEPTH(kCGL8Bit, 8);
+ /*9*/
+ DEPTH(kCGL10Bit, 10);
+ /*10*/
+ DEPTH(kCGL12Bit, 12);
+ /*11*/
+ DEPTH(kCGL16Bit, 16);
+ /*12*/
+ DEPTH(kCGL24Bit, 24);
+ /*13*/
+ DEPTH(kCGL32Bit, 32);
+ /*14*/
+ DEPTH(kCGL48Bit, 48);
+ /*15*/
+ DEPTH(kCGL64Bit, 64);
+ /*16*/
+ DEPTH(kCGL96Bit, 96);
+ /*17*/
+ DEPTH(kCGL128Bit, 128);
+
+#undef DEPTH
+
+ c->total_depth_buffer_depths = offset;
+ assert(c->total_depth_buffer_depths < GLCAPS_DEPTH_BUFFERS);
+}
+
+/* Return non-zero if an error occured. */
+static CGLError handleRendererDescriptions(CGLRendererInfoObj info, GLint r,
+ struct glCapabilitiesConfig *c) {
+ CGLError err;
+ GLint accelerated = 0, flags = 0, aux = 0, samplebufs = 0, samples = 0;
+
+ err = CGLDescribeRenderer (info, r, kCGLRPAccelerated, &accelerated);
+
+ if(err)
+ return err;
+
+ c->accelerated = accelerated;
+
+ /* Buffering modes: single/double, stereo */
+ err = CGLDescribeRenderer(info, r, kCGLRPBufferModes, &flags);
+
+ if(err)
+ return err;
+
+ handleBufferModes(c, flags);
+
+ /* AUX buffers */
+ err = CGLDescribeRenderer(info, r, kCGLRPMaxAuxBuffers, &aux);
+
+ if(err)
+ return err;
+
+ c->aux_buffers = aux;
+
+
+ /* Depth buffer size */
+ err = CGLDescribeRenderer(info, r, kCGLRPDepthModes, &flags);
+
+ if(err)
+ return err;
+
+ handleDepthModes(c, flags);
+
+
+ /* Multisample buffers */
+ err = CGLDescribeRenderer(info, r, kCGLRPMaxSampleBuffers, &samplebufs);
+
+ if(err)
+ return err;
+
+ c->multisample_buffers = samplebufs;
+
+
+ /* Multisample samples per multisample buffer */
+ err = CGLDescribeRenderer(info, r, kCGLRPMaxSamples, &samples);
+
+ if(err)
+ return err;
+
+ c->multisample_samples = samples;
+
+
+ /* Stencil bit depths */
+ err = CGLDescribeRenderer(info, r, kCGLRPStencilModes, &flags);
+
+ if(err)
+ return err;
+
+ handleStencilModes(c, flags);
+
+
+ /* Color modes (RGB/RGBA depths supported */
+ err = CGLDescribeRenderer(info, r, kCGLRPColorModes, &flags);
+
+ if(err)
+ return err;
+
+ handleColorModes(c, flags);
+
+ err = CGLDescribeRenderer(info, r, kCGLRPAccumModes, &flags);
+
+ if(err)
+ return err;
+
+ handleAccumulationModes(c, flags);
+
+ return kCGLNoError;
+}
+
+static void initCapabilities(struct glCapabilities *cap) {
+ cap->configurations = NULL;
+ cap->total_configurations = 0;
+}
+
+static void initConfig(struct glCapabilitiesConfig *c) {
+ int i;
+
+ c->accelerated = false;
+ c->stereo = false;
+ c->aux_buffers = 0;
+ c->buffers = 0;
+
+ c->total_depth_buffer_depths = 0;
+
+ for(i = 0; i < GLCAPS_DEPTH_BUFFERS; ++i) {
+ c->depth_buffers[i] = GLCAPS_INVALID_DEPTH_VALUE;
+ }
+
+ c->multisample_buffers = 0;
+ c->multisample_samples = 0;
+
+ c->total_stencil_bit_depths = 0;
+
+ for(i = 0; i < GLCAPS_STENCIL_BIT_DEPTH_BUFFERS; ++i) {
+ c->stencil_bit_depths[i] = GLCAPS_INVALID_STENCIL_DEPTH;
+ }
+
+ c->total_color_buffers = 0;
+
+ for(i = 0; i < GLCAPS_COLOR_BUFFERS; ++i) {
+ c->color_buffers[i].r = c->color_buffers[i].g =
+ c->color_buffers[i].b = c->color_buffers[i].a =
+ GLCAPS_COLOR_BUF_INVALID_VALUE;
+ c->color_buffers[i].is_argb = false;
+ }
+
+ c->total_accum_buffers = 0;
+
+ for(i = 0; i < GLCAPS_COLOR_BUFFERS; ++i) {
+ c->accum_buffers[i].r = c->accum_buffers[i].g =
+ c->accum_buffers[i].b = c->accum_buffers[i].a =
+ GLCAPS_COLOR_BUF_INVALID_VALUE;
+ c->accum_buffers[i].is_argb = false;
+ }
+
+ c->next = NULL;
+}
+
+void freeGlCapabilities(struct glCapabilities *cap) {
+ struct glCapabilitiesConfig *conf, *next;
+
+ conf = cap->configurations;
+
+ while(conf) {
+ next = conf->next;
+ free(conf);
+ conf = next;
+ }
+
+ cap->configurations = NULL;
+}
+
+/*Return true if an error occured. */
+bool getGlCapabilities(struct glCapabilities *cap) {
+ CGLRendererInfoObj info;
+ CGLError err;
+ GLint numRenderers = 0, r;
+
+ initCapabilities(cap);
+
+ err = CGLQueryRendererInfo((GLuint)-1, &info, &numRenderers);
+ if(err) {
+ ErrorF("CGLQueryRendererInfo error: %s\n", CGLErrorString(err));
+ return err;
+ }
+
+ for(r = 0; r < numRenderers; r++) {
+ struct glCapabilitiesConfig tmpconf, *conf;
+
+ initConfig(&tmpconf);
+
+ err = handleRendererDescriptions(info, r, &tmpconf);
+ if(err) {
+ ErrorF("handleRendererDescriptions returned error: %s\n", CGLErrorString(err));
+ ErrorF("trying to continue...\n");
+ continue;
+ }
+
+ conf = malloc(sizeof(*conf));
+ if(NULL == conf) {
+ FatalError("Unable to allocate memory for OpenGL capabilities\n");
+ }
+
+ /* Copy the struct. */
+ *conf = tmpconf;
+
+ /* Now link the configuration into the list. */
+ conf->next = cap->configurations;
+ cap->configurations = conf;
+ }
+
+ CGLDestroyRendererInfo(info);
+
+ /* No error occured. We are done. */
+ return kCGLNoError;
+}
diff --git a/xorg-server/hw/xquartz/GL/indirect.c b/xorg-server/hw/xquartz/GL/indirect.c index b7ee109ed..e7df57326 100644 --- a/xorg-server/hw/xquartz/GL/indirect.c +++ b/xorg-server/hw/xquartz/GL/indirect.c @@ -139,7 +139,6 @@ #include <glxcontext.h>
#include <glxext.h>
#include <glxutil.h>
-#include <glxscreens.h>
#include <GL/internal/glcore.h>
#include "x-hash.h"
#include "x-list.h"
diff --git a/xorg-server/hw/xquartz/GL/visualConfigs.c b/xorg-server/hw/xquartz/GL/visualConfigs.c index 0d5793262..f78b14a6e 100644 --- a/xorg-server/hw/xquartz/GL/visualConfigs.c +++ b/xorg-server/hw/xquartz/GL/visualConfigs.c @@ -51,7 +51,6 @@ #include <glxcontext.h>
#include <glxext.h>
#include <glxutil.h>
-#include <glxscreens.h>
#include <GL/internal/glcore.h>
#include "capabilities.h"
diff --git a/xorg-server/hw/xquartz/Makefile.am b/xorg-server/hw/xquartz/Makefile.am index 61b04e0e1..4daac9017 100644 --- a/xorg-server/hw/xquartz/Makefile.am +++ b/xorg-server/hw/xquartz/Makefile.am @@ -1,54 +1,52 @@ -noinst_LTLIBRARIES = libXquartz.la -AM_CFLAGS = $(DIX_CFLAGS) -AM_OBJCFLAGS = $(DIX_CFLAGS) -AM_CPPFLAGS = \ - -DBUILD_DATE=\"$(BUILD_DATE)\" \ - -DXSERVER_VERSION=\"$(VERSION)\" \ - -DINXQUARTZ \ - -DUSE_NEW_CLUT \ - -DXFree86Server \ - -I$(top_srcdir)/miext/rootless \ - -DX11LIBDIR=\"$(libdir)\" - -if GLX -GL_DIR = GL -endif - -SUBDIRS = bundle . $(GL_DIR) xpr pbproxy mach-startup man - -DIST_SUBDIRS = bundle . GL xpr pbproxy mach-startup man - -libXquartz_la_SOURCES = \ - $(top_srcdir)/fb/fbcmap_mi.c \ - $(top_srcdir)/mi/miinitext.c \ - X11Application.m \ - X11Controller.m \ - applewm.c \ - darwin.c \ - darwinEvents.c \ - darwinXinput.c \ - keysym2ucs.c \ - pseudoramiX.c \ - quartz.c \ - quartzCocoa.m \ - quartzKeyboard.c \ - quartzStartup.c \ - quartzRandR.c \ - threadSafety.c - -EXTRA_DIST = \ - X11Application.h \ - X11Controller.h \ - applewmExt.h \ - darwin.h \ - darwinfb.h \ - darwinEvents.h \ - keysym2ucs.h \ - pseudoramiX.h \ - quartz.h \ - quartzCommon.h \ - quartzKeyboard.h \ - quartzRandR.h \ - sanitizedCarbon.h \ - sanitizedCocoa.h \ - threadSafety.h +noinst_LTLIBRARIES = libXquartz.la
+AM_CFLAGS = $(DIX_CFLAGS)
+AM_OBJCFLAGS = $(DIX_CFLAGS)
+AM_CPPFLAGS = \
+ -DBUILD_DATE=\"$(BUILD_DATE)\" \
+ -DXSERVER_VERSION=\"$(VERSION)\" \
+ -DINXQUARTZ \
+ -DUSE_NEW_CLUT \
+ -DXFree86Server \
+ -I$(top_srcdir)/miext/rootless \
+ -DX11LIBDIR=\"$(libdir)\"
+
+if GLX
+GL_DIR = GL
+endif
+
+SUBDIRS = bundle . $(GL_DIR) xpr pbproxy mach-startup man
+
+DIST_SUBDIRS = bundle . GL xpr pbproxy mach-startup man
+
+libXquartz_la_SOURCES = \
+ $(top_srcdir)/fb/fbcmap_mi.c \
+ $(top_srcdir)/mi/miinitext.c \
+ X11Application.m \
+ X11Controller.m \
+ applewm.c \
+ darwin.c \
+ darwinEvents.c \
+ darwinXinput.c \
+ keysym2ucs.c \
+ pseudoramiX.c \
+ quartz.c \
+ quartzCocoa.m \
+ quartzKeyboard.c \
+ quartzStartup.c \
+ quartzRandR.c
+
+EXTRA_DIST = \
+ X11Application.h \
+ X11Controller.h \
+ applewmExt.h \
+ darwin.h \
+ darwinfb.h \
+ darwinEvents.h \
+ keysym2ucs.h \
+ pseudoramiX.h \
+ quartz.h \
+ quartzCommon.h \
+ quartzKeyboard.h \
+ quartzRandR.h \
+ sanitizedCarbon.h \
+ sanitizedCocoa.h
diff --git a/xorg-server/hw/xquartz/X11Application.m b/xorg-server/hw/xquartz/X11Application.m index 9c2857228..3d845d914 100644 --- a/xorg-server/hw/xquartz/X11Application.m +++ b/xorg-server/hw/xquartz/X11Application.m @@ -41,7 +41,6 @@ #include "quartz.h"
#include "darwinEvents.h"
#include "quartzKeyboard.h"
-#include "quartz.h"
#include <X11/extensions/applewmconst.h>
#include "micmap.h"
#include "exglobals.h"
@@ -237,8 +236,7 @@ static void message_kit_thread (SEL selector, NSObject *arg) { if ([self isActive]) {
[self deactivate];
- if (!_x_active && quartzProcs->IsX11Window([e window],
- [e windowNumber]))
+ if (!_x_active && quartzProcs->IsX11Window([e windowNumber]))
[self activateX:YES];
}
}
@@ -980,7 +978,7 @@ static inline pthread_t create_thread(void *(*func)(void *), void *arg) { static void *xpbproxy_x_thread(void *args) {
xpbproxy_run();
- fprintf(stderr, "xpbproxy thread is terminating unexpectedly.\n");
+ ErrorF("xpbproxy thread is terminating unexpectedly.\n");
return NULL;
}
@@ -1014,7 +1012,7 @@ void X11ApplicationMain (int argc, char **argv, char **envp) { NSMaxY([[NSScreen mainScreen] visibleFrame]);
#ifdef HAVE_LIBDISPATCH
- eventTranslationQueue = dispatch_queue_create(LAUNCHD_ID_PREFIX".X11.NSEventsToX11EventsQueue", NULL);
+ eventTranslationQueue = dispatch_queue_create(BUNDLE_ID_PREFIX".X11.NSEventsToX11EventsQueue", NULL);
assert(eventTranslationQueue != NULL);
#endif
@@ -1023,15 +1021,15 @@ void X11ApplicationMain (int argc, char **argv, char **envp) { last_key_layout = TISCopyCurrentKeyboardLayoutInputSource();
if(!last_key_layout)
- fprintf(stderr, "X11ApplicationMain: Unable to determine TISCopyCurrentKeyboardLayoutInputSource() at startup.\n");
+ ErrorF("X11ApplicationMain: Unable to determine TISCopyCurrentKeyboardLayoutInputSource() at startup.\n");
#else
KLGetCurrentKeyboardLayout(&last_key_layout);
if(!last_key_layout)
- fprintf(stderr, "X11ApplicationMain: Unable to determine KLGetCurrentKeyboardLayout() at startup.\n");
+ ErrorF("X11ApplicationMain: Unable to determine KLGetCurrentKeyboardLayout() at startup.\n");
#endif
if (!QuartsResyncKeymap(FALSE)) {
- fprintf(stderr, "X11ApplicationMain: Could not build a valid keymap.\n");
+ ErrorF("X11ApplicationMain: Could not build a valid keymap.\n");
}
/* Tell the server thread that it can proceed */
@@ -1372,7 +1370,7 @@ static const char *untrusted_str(NSEvent *e) { #endif
/* Update keyInfo */
if (!QuartsResyncKeymap(TRUE)) {
- fprintf(stderr, "sendX11NSEvent: Could not build a valid keymap.\n");
+ ErrorF("sendX11NSEvent: Could not build a valid keymap.\n");
}
}
}
diff --git a/xorg-server/hw/xquartz/applewmExt.h b/xorg-server/hw/xquartz/applewmExt.h index 5ef8b5496..aae5e9169 100644 --- a/xorg-server/hw/xquartz/applewmExt.h +++ b/xorg-server/hw/xquartz/applewmExt.h @@ -1,88 +1,101 @@ -/* - * External interface for the server's AppleWM support - */ -/************************************************************************** - -Copyright (c) 2002 Apple Computer, Inc. All Rights Reserved. -Copyright (c) 2003-2004 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. - -**************************************************************************/ - -#ifndef _APPLEWMEXT_H_ -#define _APPLEWMEXT_H_ - -#include "window.h" - -typedef int (*DisableUpdateProc)(void); -typedef int (*EnableUpdateProc)(void); -typedef int (*SetWindowLevelProc)(WindowPtr pWin, int level); -typedef int (*FrameGetRectProc)(int type, int class, const BoxRec *outer, - const BoxRec *inner, BoxRec *ret); -typedef int (*FrameHitTestProc)(int class, int x, int y, - const BoxRec *outer, - const BoxRec *inner, int *ret); -typedef int (*FrameDrawProc)(WindowPtr pWin, int class, unsigned int attr, - const BoxRec *outer, const BoxRec *inner, - unsigned int title_len, - const unsigned char *title_bytes); -typedef int (*SendPSNProc)(uint32_t hi, uint32_t lo); -typedef int (*AttachTransientProc)(WindowPtr pWinChild, WindowPtr pWinParent); - -/* - * AppleWM implementation function list - */ -typedef struct _AppleWMProcs { - DisableUpdateProc DisableUpdate; - EnableUpdateProc EnableUpdate; - SetWindowLevelProc SetWindowLevel; - FrameGetRectProc FrameGetRect; - FrameHitTestProc FrameHitTest; - FrameDrawProc FrameDraw; - SendPSNProc SendPSN; - AttachTransientProc AttachTransient; -} AppleWMProcsRec, *AppleWMProcsPtr; - -void AppleWMExtensionInit( - AppleWMProcsPtr procsPtr -); - -void AppleWMSetScreenOrigin( - WindowPtr pWin -); - -Bool AppleWMDoReorderWindow( - WindowPtr pWin -); - -void AppleWMSendEvent( - int /* type */, - unsigned int /* mask */, - int /* which */, - int /* arg */ -); - -unsigned int AppleWMSelectedEvents( - void -); - -#endif /* _APPLEWMEXT_H_ */ +/*
+ * External interface for the server's AppleWM support
+ */
+/**************************************************************************
+
+Copyright (c) 2002 Apple Computer, Inc. All Rights Reserved.
+Copyright (c) 2003-2004 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.
+
+**************************************************************************/
+
+#ifndef _APPLEWMEXT_H_
+#define _APPLEWMEXT_H_
+
+#include "window.h"
+#include <Xplugin.h>
+
+typedef int (*DisableUpdateProc)(void);
+typedef int (*EnableUpdateProc)(void);
+typedef int (*SetWindowLevelProc)(WindowPtr pWin, int level);
+#if XPLUGIN_VERSION < 4
+typedef int (*FrameGetRectProc)(int type, int class, const BoxRec *outer,
+ const BoxRec *inner, BoxRec *ret);
+typedef int (*FrameHitTestProc)(int class, int x, int y,
+ const BoxRec *outer,
+ const BoxRec *inner, int *ret);
+typedef int (*FrameDrawProc)(WindowPtr pWin, int class, unsigned int attr,
+ const BoxRec *outer, const BoxRec *inner,
+ unsigned int title_len,
+ const unsigned char *title_bytes);
+#else
+typedef int (*FrameGetRectProc)(xp_frame_rect type, xp_frame_class class, const BoxRec *outer,
+ const BoxRec *inner, BoxRec *ret);
+typedef int (*FrameHitTestProc)(xp_frame_class class, int x, int y,
+ const BoxRec *outer,
+ const BoxRec *inner, int *ret);
+typedef int (*FrameDrawProc)(WindowPtr pWin, xp_frame_class class, xp_frame_attr attr,
+ const BoxRec *outer, const BoxRec *inner,
+ unsigned int title_len,
+ const unsigned char *title_bytes);
+#endif
+typedef int (*SendPSNProc)(uint32_t hi, uint32_t lo);
+typedef int (*AttachTransientProc)(WindowPtr pWinChild, WindowPtr pWinParent);
+
+/*
+ * AppleWM implementation function list
+ */
+typedef struct _AppleWMProcs {
+ DisableUpdateProc DisableUpdate;
+ EnableUpdateProc EnableUpdate;
+ SetWindowLevelProc SetWindowLevel;
+ FrameGetRectProc FrameGetRect;
+ FrameHitTestProc FrameHitTest;
+ FrameDrawProc FrameDraw;
+ SendPSNProc SendPSN;
+ AttachTransientProc AttachTransient;
+} AppleWMProcsRec, *AppleWMProcsPtr;
+
+void AppleWMExtensionInit(
+ AppleWMProcsPtr procsPtr
+);
+
+void AppleWMSetScreenOrigin(
+ WindowPtr pWin
+);
+
+Bool AppleWMDoReorderWindow(
+ WindowPtr pWin
+);
+
+void AppleWMSendEvent(
+ int /* type */,
+ unsigned int /* mask */,
+ int /* which */,
+ int /* arg */
+);
+
+unsigned int AppleWMSelectedEvents(
+ void
+);
+
+#endif /* _APPLEWMEXT_H_ */
diff --git a/xorg-server/hw/xquartz/bundle/Info.plist.cpp b/xorg-server/hw/xquartz/bundle/Info.plist.cpp index a2a22ad64..444400674 100644 --- a/xorg-server/hw/xquartz/bundle/Info.plist.cpp +++ b/xorg-server/hw/xquartz/bundle/Info.plist.cpp @@ -7,11 +7,11 @@ <key>CFBundleExecutable</key>
<string>X11</string>
<key>CFBundleGetInfoString</key>
- <string>LAUNCHD_ID_PREFIX.X11</string>
+ <string>BUNDLE_ID_PREFIX.X11</string>
<key>CFBundleIconFile</key>
<string>X11.icns</string>
<key>CFBundleIdentifier</key>
- <string>LAUNCHD_ID_PREFIX.X11</string>
+ <string>BUNDLE_ID_PREFIX.X11</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
@@ -19,9 +19,9 @@ <key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
- <string>2.6.1</string>
+ <string>2.7.0</string>
<key>CFBundleVersion</key>
- <string>2.6.1</string>
+ <string>2.7.0</string>
<key>CFBundleSignature</key>
<string>x11a</string>
<key>CSResourcesFileMapped</key>
diff --git a/xorg-server/hw/xquartz/bundle/Makefile.am b/xorg-server/hw/xquartz/bundle/Makefile.am index 34598aa6a..a455b147d 100644 --- a/xorg-server/hw/xquartz/bundle/Makefile.am +++ b/xorg-server/hw/xquartz/bundle/Makefile.am @@ -1,7 +1,7 @@ include cpprules.in
CPP_FILES_FLAGS = \
- -DLAUNCHD_ID_PREFIX="$(LAUNCHD_ID_PREFIX)" \
+ -DBUNDLE_ID_PREFIX="$(BUNDLE_ID_PREFIX)" \
-DAPPLE_APPLICATION_NAME="$(APPLE_APPLICATION_NAME)"
if XQUARTZ_SPARKLE
diff --git a/xorg-server/hw/xquartz/darwin.c b/xorg-server/hw/xquartz/darwin.c index cfeacae42..e12d7786b 100644 --- a/xorg-server/hw/xquartz/darwin.c +++ b/xorg-server/hw/xquartz/darwin.c @@ -133,28 +133,12 @@ static PixmapFormatRec formats[] = { };
const int NUMFORMATS = sizeof(formats)/sizeof(formats[0]);
-#ifndef OSNAME
-#define OSNAME " Darwin"
-#endif
-#ifndef OSVENDOR
-#define OSVENDOR ""
-#endif
-#ifndef PRE_RELEASE
-#define PRE_RELEASE XORG_VERSION_SNAP
-#endif
-#ifndef BUILD_DATE
-#define BUILD_DATE ""
-#endif
-#ifndef XORG_RELEASE
-#define XORG_RELEASE "?"
-#endif
-
void
DarwinPrintBanner(void)
{
- // this should change depending on which specific server we are building
ErrorF("Xquartz starting:\n");
- ErrorF("X.Org X Server %s\nBuild Date: %s\n", XSERVER_VERSION, BUILD_DATE );
+ ErrorF("X.Org X Server %s\n", XSERVER_VERSION);
+ ErrorF("Build Date: %s\n", BUILD_DATE );
}
@@ -605,6 +589,13 @@ void OsVendorFatalError( void ) void OsVendorInit(void)
{
if (serverGeneration == 1) {
+ char *lf;
+ char *home = getenv("HOME");
+ assert(home);
+ assert(0 < asprintf(&lf, "%s/Library/Logs/X11.%s.log", home, bundle_id_prefix));
+ LogInit(lf, ".old");
+ free(lf);
+
DarwinPrintBanner();
#ifdef ENABLE_DEBUG_LOG
{
diff --git a/xorg-server/hw/xquartz/darwin.h b/xorg-server/hw/xquartz/darwin.h index ec9d52d97..da53a261d 100644 --- a/xorg-server/hw/xquartz/darwin.h +++ b/xorg-server/hw/xquartz/darwin.h @@ -34,8 +34,6 @@ #include <X11/extensions/XKB.h>
#include <assert.h>
-#include "threadSafety.h"
-
#include "darwinfb.h"
// From darwin.c
@@ -75,12 +73,15 @@ extern int darwinDesiredDepth; extern int darwinMainScreenX;
extern int darwinMainScreenY;
+// bundle-main.c
+extern char *bundle_id_prefix;
+
#define ENABLE_DEBUG_LOG 1
#ifdef ENABLE_DEBUG_LOG
extern FILE *debug_log_fp;
#define DEBUG_LOG_NAME "x11-debug.txt"
-#define DEBUG_LOG(msg, args...) if (debug_log_fp) fprintf(debug_log_fp, "%s:%s:%s:%d " msg, threadSafetyID(pthread_self()), __FILE__, __FUNCTION__, __LINE__, ##args ); fflush(debug_log_fp);
+#define DEBUG_LOG(msg, args...) if (debug_log_fp) fprintf(debug_log_fp, "%s:%s:%d " msg, __FILE__, __FUNCTION__, __LINE__, ##args ); fflush(debug_log_fp);
#else
#define DEBUG_LOG(msg, args...)
#endif
diff --git a/xorg-server/hw/xquartz/darwinEvents.c b/xorg-server/hw/xquartz/darwinEvents.c index b591f7728..185df4a43 100644 --- a/xorg-server/hw/xquartz/darwinEvents.c +++ b/xorg-server/hw/xquartz/darwinEvents.c @@ -113,7 +113,7 @@ void darwinEvents_lock(void) { if((err = pthread_mutex_lock(&mieq_lock))) {
ErrorF("%s:%s:%d: Failed to lock mieq_lock: %d\n",
__FILE__, __FUNCTION__, __LINE__, err);
- spewCallStack();
+ xorg_backtrace();
}
if(darwinEvents == NULL) {
pthread_cond_wait(&mieq_ready_cond, &mieq_lock);
@@ -126,7 +126,7 @@ void darwinEvents_unlock(void) { if((err = pthread_mutex_unlock(&mieq_lock))) {
ErrorF("%s:%s:%d: Failed to unlock mieq_lock: %d\n",
__FILE__, __FUNCTION__, __LINE__, err);
- spewCallStack();
+ xorg_backtrace();
}
}
@@ -197,8 +197,6 @@ static void DarwinUpdateModifiers( static void DarwinEventHandler(int screenNum, InternalEvent *ie, DeviceIntPtr dev) {
XQuartzEvent *e = &(ie->xquartz_event);
- TA_SERVER();
-
switch(e->subtype) {
case kXquartzControllerNotify:
DEBUG_LOG("kXquartzControllerNotify\n");
@@ -381,8 +379,6 @@ void ProcessInputEvents(void) { char nullbyte;
int x = sizeof(nullbyte);
- TA_SERVER();
-
mieqProcessInputEvents();
// Empty the signaling pipe
diff --git a/xorg-server/hw/xquartz/mach-startup/bundle-main.c b/xorg-server/hw/xquartz/mach-startup/bundle-main.c index 774dda664..ddb12741c 100644 --- a/xorg-server/hw/xquartz/mach-startup/bundle-main.c +++ b/xorg-server/hw/xquartz/mach-startup/bundle-main.c @@ -64,6 +64,9 @@ /* From darwinEvents.c ... but don't want to pull in all the server cruft */
void DarwinListenOnOpenFD(int fd);
+/* Ditto, from os/log.c */
+extern void ErrorF(const char *f, ...) _X_ATTRIBUTE_PRINTF(1,2);
+
extern int noPanoramiXExtension;
#define DEFAULT_CLIENT X11BINDIR "/xterm"
@@ -88,7 +91,7 @@ asm (".desc ___crashreporter_info__, 0x10"); static const char *__crashreporter_info__base = "X.Org X Server " XSERVER_VERSION " Build Date: " BUILD_DATE;
-static char *launchd_id_prefix = NULL;
+char *bundle_id_prefix = NULL;
static char *server_bootstrap_name = NULL;
#define DEBUG 1
@@ -134,19 +137,27 @@ static mach_port_t checkin_or_register(char *bname) { /* We probably were not started by launchd or the old mach_init */
kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &mp);
if (kr != KERN_SUCCESS) {
- fprintf(stderr, "mach_port_allocate(): %s\n", mach_error_string(kr));
+ ErrorF("mach_port_allocate(): %s\n", mach_error_string(kr));
exit(EXIT_FAILURE);
}
kr = mach_port_insert_right(mach_task_self(), mp, mp, MACH_MSG_TYPE_MAKE_SEND);
if (kr != KERN_SUCCESS) {
- fprintf(stderr, "mach_port_insert_right(): %s\n", mach_error_string(kr));
+ ErrorF("mach_port_insert_right(): %s\n", mach_error_string(kr));
exit(EXIT_FAILURE);
}
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations" // bootstrap_register
+#endif
kr = bootstrap_register(bootstrap_port, bname, mp);
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
if (kr != KERN_SUCCESS) {
- fprintf(stderr, "bootstrap_register(): %s\n", mach_error_string(kr));
+ ErrorF("bootstrap_register(): %s\n", mach_error_string(kr));
exit(EXIT_FAILURE);
}
@@ -189,7 +200,7 @@ static int accept_fd_handoff(int connected_fd) { *((int*)CMSG_DATA(cmsg)) = -1;
if(recvmsg(connected_fd, &msg, 0) < 0) {
- fprintf(stderr, "X11.app: Error receiving $DISPLAY file descriptor. recvmsg() error: %s\n", strerror(errno));
+ ErrorF("X11.app: Error receiving $DISPLAY file descriptor. recvmsg() error: %s\n", strerror(errno));
return -1;
}
@@ -222,14 +233,14 @@ static void *socket_handoff_thread(void *arg) { while(launchd_fd == -1) {
connected_fd = accept(handoff_data->fd, NULL, NULL);
if(connected_fd == -1) {
- fprintf(stderr, "X11.app: Failed to accept incoming connection on socket (fd=%d): %s\n", handoff_data->fd, strerror(errno));
+ ErrorF("X11.app: Failed to accept incoming connection on socket (fd=%d): %s\n", handoff_data->fd, strerror(errno));
sleep(2);
continue;
}
launchd_fd = accept_fd_handoff(connected_fd);
if(launchd_fd == -1)
- fprintf(stderr, "X11.app: Error receiving $DISPLAY file descriptor, no descriptor received? Waiting for another connection.\n");
+ ErrorF("X11.app: Error receiving $DISPLAY file descriptor, no descriptor received? Waiting for another connection.\n");
close(connected_fd);
}
@@ -238,7 +249,7 @@ static void *socket_handoff_thread(void *arg) { unlink(handoff_data->filename);
free(handoff_data);
- fprintf(stderr, "X11.app Handing off fd to server thread via DarwinListenOnOpenFD(%d)\n", launchd_fd);
+ ErrorF("X11.app Handing off fd to server thread via DarwinListenOnOpenFD(%d)\n", launchd_fd);
DarwinListenOnOpenFD(launchd_fd);
#ifndef HAVE_LIBDISPATCH
@@ -266,24 +277,24 @@ static int create_socket(char *filename_out) { ret_fd = socket(PF_UNIX, SOCK_STREAM, 0);
if(ret_fd == -1) {
- fprintf(stderr, "X11.app: Failed to create socket (try %d / %d): %s - %s\n", (int)try+1, (int)try_max, filename_out, strerror(errno));
+ ErrorF("X11.app: Failed to create socket (try %d / %d): %s - %s\n", (int)try+1, (int)try_max, filename_out, strerror(errno));
continue;
}
if(bind(ret_fd, servaddr, servaddr_len) != 0) {
- fprintf(stderr, "X11.app: Failed to bind socket: %d - %s\n", errno, strerror(errno));
+ ErrorF("X11.app: Failed to bind socket: %d - %s\n", errno, strerror(errno));
close(ret_fd);
return 0;
}
if(listen(ret_fd, 10) != 0) {
- fprintf(stderr, "X11.app: Failed to listen to socket: %s - %d - %s\n", filename_out, errno, strerror(errno));
+ ErrorF("X11.app: Failed to listen to socket: %s - %d - %s\n", filename_out, errno, strerror(errno));
close(ret_fd);
return 0;
}
#ifdef DEBUG
- fprintf(stderr, "X11.app: Listening on socket for fd handoff: (%d) %s\n", ret_fd, filename_out);
+ ErrorF("X11.app: Listening on socket for fd handoff: (%d) %s\n", ret_fd, filename_out);
#endif
return ret_fd;
@@ -301,7 +312,7 @@ kern_return_t do_request_fd_handoff_socket(mach_port_t port, string_t filename) handoff_data = (socket_handoff_t *)calloc(1,sizeof(socket_handoff_t));
if(!handoff_data) {
- fprintf(stderr, "X11.app: Error allocating memory for handoff_data\n");
+ ErrorF("X11.app: Error allocating memory for handoff_data\n");
return KERN_FAILURE;
}
@@ -322,7 +333,7 @@ kern_return_t do_request_fd_handoff_socket(mach_port_t port, string_t filename) #endif
#ifdef DEBUG
- fprintf(stderr, "X11.app: Thread created for handoff. Returning success to tell caller to connect and push the fd.\n");
+ ErrorF("X11.app: Thread created for handoff. Returning success to tell caller to connect and push the fd.\n");
#endif
return KERN_SUCCESS;
@@ -347,7 +358,7 @@ kern_return_t do_start_x11_server(mach_port_t port, string_array_t argv, * unset DISPLAY or we can run into problems with pbproxy
*/
if(!launchd_socket_handed_off) {
- fprintf(stderr, "X11.app: No launchd socket handed off, unsetting DISPLAY\n");
+ ErrorF("X11.app: No launchd socket handed off, unsetting DISPLAY\n");
unsetenv("DISPLAY");
}
@@ -355,10 +366,10 @@ kern_return_t do_start_x11_server(mach_port_t port, string_array_t argv, return KERN_FAILURE;
}
- fprintf(stderr, "X11.app: do_start_x11_server(): argc=%d\n", argvCnt);
+ ErrorF("X11.app: do_start_x11_server(): argc=%d\n", argvCnt);
for(i=0; i < argvCnt; i++) {
_argv[i] = argv[i];
- fprintf(stderr, "\targv[%u] = %s\n", (unsigned)i, argv[i]);
+ ErrorF("\targv[%u] = %s\n", (unsigned)i, argv[i]);
}
_argv[argvCnt] = NULL;
@@ -396,7 +407,7 @@ static int startup_trigger(int argc, char **argv, char **envp) { newenvp = (string_array_t)alloca(envpc * sizeof(string_t));
if(!newargv || !newenvp) {
- fprintf(stderr, "Memory allocation failure\n");
+ ErrorF("Memory allocation failure\n");
exit(EXIT_FAILURE);
}
@@ -410,16 +421,16 @@ static int startup_trigger(int argc, char **argv, char **envp) { kr = bootstrap_look_up(bootstrap_port, server_bootstrap_name, &mp);
if (kr != KERN_SUCCESS) {
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
- fprintf(stderr, "bootstrap_look_up(%s): %s\n", server_bootstrap_name, bootstrap_strerror(kr));
+ ErrorF("bootstrap_look_up(%s): %s\n", server_bootstrap_name, bootstrap_strerror(kr));
#else
- fprintf(stderr, "bootstrap_look_up(%s): %ul\n", server_bootstrap_name, (unsigned long)kr);
+ ErrorF("bootstrap_look_up(%s): %ul\n", server_bootstrap_name, (unsigned long)kr);
#endif
exit(EXIT_FAILURE);
}
kr = start_x11_server(mp, newargv, argc, newenvp, envpc);
if (kr != KERN_SUCCESS) {
- fprintf(stderr, "start_x11_server: %s\n", mach_error_string(kr));
+ ErrorF("start_x11_server: %s\n", mach_error_string(kr));
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
@@ -441,10 +452,10 @@ static int startup_trigger(int argc, char **argv, char **envp) { /* Start the server */
if((s = getenv("DISPLAY"))) {
- fprintf(stderr, "X11.app: Could not connect to server (DISPLAY=\"%s\", unsetting). Starting X server.\n", s);
+ ErrorF("X11.app: Could not connect to server (DISPLAY=\"%s\", unsetting). Starting X server.\n", s);
unsetenv("DISPLAY");
} else {
- fprintf(stderr, "X11.app: Could not connect to server (DISPLAY is not set). Starting X server.\n");
+ ErrorF("X11.app: Could not connect to server (DISPLAY is not set). Starting X server.\n");
}
return execute(command_from_prefs("startx_script", DEFAULT_STARTX));
}
@@ -483,23 +494,23 @@ static void setup_env(void) { /* fallback to hardcoded value if we can't discover it */
if(!pds) {
- pds = LAUNCHD_ID_PREFIX".X11";
+ pds = BUNDLE_ID_PREFIX".X11";
}
server_bootstrap_name = strdup(pds);
if(!server_bootstrap_name) {
- fprintf(stderr, "X11.app: Memory allocation error.\n");
+ ErrorF("X11.app: Memory allocation error.\n");
exit(1);
}
setenv("X11_PREFS_DOMAIN", server_bootstrap_name, 1);
len = strlen(server_bootstrap_name);
- launchd_id_prefix = malloc(sizeof(char) * (len - 3));
- if(!launchd_id_prefix) {
- fprintf(stderr, "X11.app: Memory allocation error.\n");
+ bundle_id_prefix = malloc(sizeof(char) * (len - 3));
+ if(!bundle_id_prefix) {
+ ErrorF("X11.app: Memory allocation error.\n");
exit(1);
}
- strlcpy(launchd_id_prefix, server_bootstrap_name, len - 3);
+ strlcpy(bundle_id_prefix, server_bootstrap_name, len - 3);
/* We need to unset DISPLAY if it is not our socket */
if(disp) {
@@ -511,27 +522,27 @@ static void setup_env(void) { }
if(s && *s) {
- if(strcmp(launchd_id_prefix, "org.x") == 0 && strcmp(s, ":0") == 0) {
- fprintf(stderr, "X11.app: Detected old style launchd DISPLAY, please update xinit.\n");
+ if(strcmp(bundle_id_prefix, "org.x") == 0 && strcmp(s, ":0") == 0) {
+ ErrorF("X11.app: Detected old style launchd DISPLAY, please update xinit.\n");
} else {
temp = (char *)malloc(sizeof(char) * len);
if(!temp) {
- fprintf(stderr, "X11.app: Memory allocation error creating space for socket name test.\n");
+ ErrorF("X11.app: Memory allocation error creating space for socket name test.\n");
exit(1);
}
- strlcpy(temp, launchd_id_prefix, len);
+ strlcpy(temp, bundle_id_prefix, len);
strlcat(temp, ":0", len);
if(strcmp(temp, s) != 0) {
/* If we don't have a match, unset it. */
- fprintf(stderr, "X11.app: DISPLAY (\"%s\") does not match our id (\"%s\"), unsetting.\n", disp, launchd_id_prefix);
+ ErrorF("X11.app: DISPLAY (\"%s\") does not match our id (\"%s\"), unsetting.\n", disp, bundle_id_prefix);
unsetenv("DISPLAY");
}
free(temp);
}
} else {
/* The DISPLAY environment variable is not formatted like a launchd socket, so reset. */
- fprintf(stderr, "X11.app: DISPLAY does not look like a launchd set variable, unsetting.\n");
+ ErrorF("X11.app: DISPLAY does not look like a launchd set variable, unsetting.\n");
unsetenv("DISPLAY");
}
}
@@ -562,9 +573,9 @@ int main(int argc, char **argv, char **envp) { /* Setup the initial crasherporter info */
strlcpy(__crashreporter_info_buff__, __crashreporter_info__base, sizeof(__crashreporter_info_buff__));
- fprintf(stderr, "X11.app: main(): argc=%d\n", argc);
+ ErrorF("X11.app: main(): argc=%d\n", argc);
for(i=0; i < argc; i++) {
- fprintf(stderr, "\targv[%u] = %s\n", (unsigned)i, argv[i]);
+ ErrorF("\targv[%u] = %s\n", (unsigned)i, argv[i]);
if(!strcmp(argv[i], "--listenonly")) {
listenOnly = TRUE;
}
@@ -572,7 +583,7 @@ int main(int argc, char **argv, char **envp) { mp = checkin_or_register(server_bootstrap_name);
if(mp == MACH_PORT_NULL) {
- fprintf(stderr, "NULL mach service: %s", server_bootstrap_name);
+ ErrorF("NULL mach service: %s", server_bootstrap_name);
return EXIT_FAILURE;
}
@@ -621,10 +632,10 @@ int main(int argc, char **argv, char **envp) { }
/* Main event loop */
- fprintf(stderr, "Waiting for startup parameters via Mach IPC.\n");
+ ErrorF("Waiting for startup parameters via Mach IPC.\n");
kr = mach_msg_server(mach_startup_server, mxmsgsz, mp, 0);
if (kr != KERN_SUCCESS) {
- fprintf(stderr, "%s.X11(mp): %s\n", LAUNCHD_ID_PREFIX, mach_error_string(kr));
+ ErrorF("%s.X11(mp): %s\n", BUNDLE_ID_PREFIX, mach_error_string(kr));
return EXIT_FAILURE;
}
@@ -640,9 +651,9 @@ static int execute(const char *command) { newargv[2] = command;
newargv[3] = NULL;
- fprintf(stderr, "X11.app: Launching %s:\n", command);
+ ErrorF("X11.app: Launching %s:\n", command);
for(p=newargv; *p; p++) {
- fprintf(stderr, "\targv[%ld] = %s\n", (long int)(p - newargv), *p);
+ ErrorF("\targv[%ld] = %s\n", (long int)(p - newargv), *p);
}
execvp (newargv[0], (char * const *) newargv);
diff --git a/xorg-server/hw/xquartz/mach-startup/launchd_fd.c b/xorg-server/hw/xquartz/mach-startup/launchd_fd.c index 6dace8ea1..6be4421c2 100644 --- a/xorg-server/hw/xquartz/mach-startup/launchd_fd.c +++ b/xorg-server/hw/xquartz/mach-startup/launchd_fd.c @@ -1,89 +1,89 @@ -/* Copyright (c) 2008 Apple Inc. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice 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. - * - * Except as contained in this notice, the name(s) of the above - * copyright holders shall not be used in advertising or otherwise to - * promote the sale, use or other dealings in this Software without - * prior written authorization. - */ - -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> -#endif - -#include <launch.h> -#include <stdio.h> -#include <errno.h> - -#include "launchd_fd.h" - -int launchd_display_fd(void) { - launch_data_t sockets_dict, checkin_request, checkin_response; - launch_data_t listening_fd_array, listening_fd; - - /* Get launchd fd */ - if ((checkin_request = launch_data_new_string(LAUNCH_KEY_CHECKIN)) == NULL) { - fprintf(stderr,"launch_data_new_string(\"" LAUNCH_KEY_CHECKIN "\") Unable to create string.\n"); - return ERROR_FD; - } - - if ((checkin_response = launch_msg(checkin_request)) == NULL) { - fprintf(stderr,"launch_msg(\"" LAUNCH_KEY_CHECKIN "\") IPC failure: %s\n",strerror(errno)); - return ERROR_FD; - } - - if (LAUNCH_DATA_ERRNO == launch_data_get_type(checkin_response)) { - // ignore EACCES, which is common if we weren't started by launchd - if (launch_data_get_errno(checkin_response) != EACCES) - fprintf(stderr,"launchd check-in failed: %s\n", strerror(launch_data_get_errno(checkin_response))); - return ERROR_FD; - } - - sockets_dict = launch_data_dict_lookup(checkin_response, LAUNCH_JOBKEY_SOCKETS); - if (NULL == sockets_dict) { - fprintf(stderr,"launchd check-in: no sockets found to answer requests on!\n"); - return ERROR_FD; - } - - if (launch_data_dict_get_count(sockets_dict) > 1) { - fprintf(stderr,"launchd check-in: some sockets will be ignored!\n"); - return ERROR_FD; - } - - listening_fd_array = launch_data_dict_lookup(sockets_dict, LAUNCHD_ID_PREFIX":0"); - if (NULL == listening_fd_array) { - listening_fd_array = launch_data_dict_lookup(sockets_dict, ":0"); - if (NULL == listening_fd_array) { - fprintf(stderr,"launchd check-in: No known sockets found to answer requests on! \"%s:0\" and \":0\" failed.\n", LAUNCHD_ID_PREFIX); - return ERROR_FD; - } - } - - if (launch_data_array_get_count(listening_fd_array)!=1) { - fprintf(stderr,"launchd check-in: Expected 1 socket from launchd, got %u)\n", - (unsigned)launch_data_array_get_count(listening_fd_array)); - return ERROR_FD; - } - - listening_fd=launch_data_array_get_index(listening_fd_array, 0); - return launch_data_get_fd(listening_fd); -} +/* Copyright (c) 2008 Apple Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice 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.
+ *
+ * Except as contained in this notice, the name(s) of the above
+ * copyright holders shall not be used in advertising or otherwise to
+ * promote the sale, use or other dealings in this Software without
+ * prior written authorization.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <launch.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include "launchd_fd.h"
+
+int launchd_display_fd(void) {
+ launch_data_t sockets_dict, checkin_request, checkin_response;
+ launch_data_t listening_fd_array, listening_fd;
+
+ /* Get launchd fd */
+ if ((checkin_request = launch_data_new_string(LAUNCH_KEY_CHECKIN)) == NULL) {
+ fprintf(stderr,"launch_data_new_string(\"" LAUNCH_KEY_CHECKIN "\") Unable to create string.\n");
+ return ERROR_FD;
+ }
+
+ if ((checkin_response = launch_msg(checkin_request)) == NULL) {
+ fprintf(stderr,"launch_msg(\"" LAUNCH_KEY_CHECKIN "\") IPC failure: %s\n",strerror(errno));
+ return ERROR_FD;
+ }
+
+ if (LAUNCH_DATA_ERRNO == launch_data_get_type(checkin_response)) {
+ // ignore EACCES, which is common if we weren't started by launchd
+ if (launch_data_get_errno(checkin_response) != EACCES)
+ fprintf(stderr,"launchd check-in failed: %s\n", strerror(launch_data_get_errno(checkin_response)));
+ return ERROR_FD;
+ }
+
+ sockets_dict = launch_data_dict_lookup(checkin_response, LAUNCH_JOBKEY_SOCKETS);
+ if (NULL == sockets_dict) {
+ fprintf(stderr,"launchd check-in: no sockets found to answer requests on!\n");
+ return ERROR_FD;
+ }
+
+ if (launch_data_dict_get_count(sockets_dict) > 1) {
+ fprintf(stderr,"launchd check-in: some sockets will be ignored!\n");
+ return ERROR_FD;
+ }
+
+ listening_fd_array = launch_data_dict_lookup(sockets_dict, BUNDLE_ID_PREFIX":0");
+ if (NULL == listening_fd_array) {
+ listening_fd_array = launch_data_dict_lookup(sockets_dict, ":0");
+ if (NULL == listening_fd_array) {
+ fprintf(stderr,"launchd check-in: No known sockets found to answer requests on! \"%s:0\" and \":0\" failed.\n", BUNDLE_ID_PREFIX);
+ return ERROR_FD;
+ }
+ }
+
+ if (launch_data_array_get_count(listening_fd_array)!=1) {
+ fprintf(stderr,"launchd check-in: Expected 1 socket from launchd, got %u)\n",
+ (unsigned)launch_data_array_get_count(listening_fd_array));
+ return ERROR_FD;
+ }
+
+ listening_fd=launch_data_array_get_index(listening_fd_array, 0);
+ return launch_data_get_fd(listening_fd);
+}
diff --git a/xorg-server/hw/xquartz/mach-startup/stub.c b/xorg-server/hw/xquartz/mach-startup/stub.c index ccf5ab426..8f70eeff7 100644 --- a/xorg-server/hw/xquartz/mach-startup/stub.c +++ b/xorg-server/hw/xquartz/mach-startup/stub.c @@ -1,328 +1,312 @@ -/* Copyright (c) 2008 Apple Inc. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice 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. - * - * Except as contained in this notice, the name(s) of the above - * copyright holders shall not be used in advertising or otherwise to - * promote the sale, use or other dealings in this Software without - * prior written authorization. - */ - -#include <CoreServices/CoreServices.h> - -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> -#endif - -#include <string.h> -#include <stdio.h> -#include <unistd.h> -#include <errno.h> - -#include <sys/socket.h> -#include <sys/un.h> - -#define kX11AppBundleId LAUNCHD_ID_PREFIX".X11" -#define kX11AppBundlePath "/Contents/MacOS/X11" - -static char *server_bootstrap_name = kX11AppBundleId; - -#include <mach/mach.h> -#include <mach/mach_error.h> -#include <servers/bootstrap.h> -#include "mach_startup.h" - -#include <signal.h> - -#include <AvailabilityMacros.h> - -#include "launchd_fd.h" - -#ifndef BUILD_DATE -#define BUILD_DATE "?" -#endif -#ifndef XSERVER_VERSION -#define XSERVER_VERSION "?" -#endif - -#define DEBUG 1 - -static char x11_path[PATH_MAX + 1]; - -static pid_t x11app_pid = 0; - -static void set_x11_path(void) { -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 - - CFURLRef appURL = NULL; - OSStatus osstatus = LSFindApplicationForInfo(kLSUnknownCreator, CFSTR(kX11AppBundleId), nil, nil, &appURL); - - switch (osstatus) { - case noErr: - if (appURL == NULL) { - fprintf(stderr, "Xquartz: Invalid response from LSFindApplicationForInfo(%s)\n", - kX11AppBundleId); - exit(1); - } - - if (!CFURLGetFileSystemRepresentation(appURL, true, (unsigned char *)x11_path, sizeof(x11_path))) { - fprintf(stderr, "Xquartz: Error resolving URL for %s\n", kX11AppBundleId); - exit(3); - } - - strlcat(x11_path, kX11AppBundlePath, sizeof(x11_path)); -#ifdef DEBUG - fprintf(stderr, "Xquartz: X11.app = %s\n", x11_path); -#endif - break; - case kLSApplicationNotFoundErr: - fprintf(stderr, "Xquartz: Unable to find application for %s\n", kX11AppBundleId); - exit(10); - default: - fprintf(stderr, "Xquartz: Unable to find application for %s, error code = %d\n", - kX11AppBundleId, (int)osstatus); - exit(11); - } -#else - /* TODO: Make Tiger smarter... but TBH, this should never get called on Tiger... */ - strlcpy(x11_path, "/Applications/Utilities/X11.app/Contents/MacOS/X11", sizeof(x11_path)); -#endif -} - -static int connect_to_socket(const char *filename) { - struct sockaddr_un servaddr_un; - struct sockaddr *servaddr; - socklen_t servaddr_len; - int ret_fd; - - /* Setup servaddr_un */ - memset (&servaddr_un, 0, sizeof (struct sockaddr_un)); - servaddr_un.sun_family = AF_UNIX; - strlcpy(servaddr_un.sun_path, filename, sizeof(servaddr_un.sun_path)); - - servaddr = (struct sockaddr *) &servaddr_un; - servaddr_len = sizeof(struct sockaddr_un) - sizeof(servaddr_un.sun_path) + strlen(filename); - - ret_fd = socket(PF_UNIX, SOCK_STREAM, 0); - if(ret_fd == -1) { - fprintf(stderr, "Xquartz: Failed to create socket: %s - %s\n", filename, strerror(errno)); - return -1; - } - - if(connect(ret_fd, servaddr, servaddr_len) < 0) { - fprintf(stderr, "Xquartz: Failed to connect to socket: %s - %d - %s\n", filename, errno, strerror(errno)); - close(ret_fd); - return -1; - } - - return ret_fd; -} - -static void send_fd_handoff(int connected_fd, int launchd_fd) { - char databuf[] = "display"; - struct iovec iov[1]; - - union { - struct cmsghdr hdr; - char bytes[CMSG_SPACE(sizeof(int))]; - } buf; - - struct msghdr msg; - struct cmsghdr *cmsg; - - iov[0].iov_base = databuf; - iov[0].iov_len = sizeof(databuf); - - msg.msg_iov = iov; - msg.msg_iovlen = 1; - msg.msg_control = buf.bytes; - msg.msg_controllen = sizeof(buf); - msg.msg_name = 0; - msg.msg_namelen = 0; - msg.msg_flags = 0; - - cmsg = CMSG_FIRSTHDR (&msg); - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - cmsg->cmsg_len = CMSG_LEN(sizeof(int)); - - msg.msg_controllen = cmsg->cmsg_len; - - *((int*)CMSG_DATA(cmsg)) = launchd_fd; - - if(sendmsg(connected_fd, &msg, 0) < 0) { - fprintf(stderr, "Xquartz: Error sending $DISPLAY file descriptor over fd %d: %d -- %s\n", connected_fd, errno, strerror(errno)); - return; - } - -#ifdef DEBUG - fprintf(stderr, "Xquartz: Message sent. Closing handoff fd.\n"); -#endif - - close(connected_fd); -} - -static void signal_handler(int sig) { - if(x11app_pid) - kill(x11app_pid, sig); - _exit(0); -} - -int main(int argc, char **argv, char **envp) { - int envpc; - kern_return_t kr; - mach_port_t mp; - string_array_t newenvp; - string_array_t newargv; - size_t i; - int launchd_fd; - string_t handoff_socket_filename; - sig_t handler; - - if(argc == 2 && !strcmp(argv[1], "-version")) { - fprintf(stderr, "X.org Release 7.5\n"); - fprintf(stderr, "X.Org X Server %s\n", XSERVER_VERSION); - fprintf(stderr, "Build Date: %s\n", BUILD_DATE); - return EXIT_SUCCESS; - } - - if(getenv("X11_PREFS_DOMAIN")) - server_bootstrap_name = getenv("X11_PREFS_DOMAIN"); - - /* We don't have a mechanism in place to handle this interrupt driven - * server-start notification, so just send the signal now, so xinit doesn't - * time out waiting for it and will just poll for the server. - */ - handler = signal(SIGUSR1, SIG_IGN); - if(handler == SIG_IGN) - kill(getppid(), SIGUSR1); - signal(SIGUSR1, handler); - - /* Pass on SIGs to X11.app */ - signal(SIGINT, signal_handler); - signal(SIGTERM, signal_handler); - - /* Get the $DISPLAY FD */ - launchd_fd = launchd_display_fd(); - - kr = bootstrap_look_up(bootstrap_port, server_bootstrap_name, &mp); - if(kr != KERN_SUCCESS) { - pid_t child; - - fprintf(stderr, "Xquartz: Unable to locate waiting server: %s\n", server_bootstrap_name); - set_x11_path(); - - /* This forking is ugly and will be cleaned up later */ - child = fork(); - if(child == -1) { - fprintf(stderr, "Xquartz: Could not fork: %s\n", strerror(errno)); - return EXIT_FAILURE; - } - - if(child == 0) { - char *_argv[3]; - _argv[0] = x11_path; - _argv[1] = "--listenonly"; - _argv[2] = NULL; - fprintf(stderr, "Xquartz: Starting X server: %s --listenonly\n", x11_path); - return execvp(x11_path, _argv); - } - - /* Try connecting for 10 seconds */ - for(i=0; i < 80; i++) { - usleep(250000); - kr = bootstrap_look_up(bootstrap_port, server_bootstrap_name, &mp); - if(kr == KERN_SUCCESS) - break; - } - - if(kr != KERN_SUCCESS) { -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 - fprintf(stderr, "Xquartz: bootstrap_look_up(): %s\n", bootstrap_strerror(kr)); -#else - fprintf(stderr, "Xquartz: bootstrap_look_up(): %ul\n", (unsigned long)kr); -#endif - return EXIT_FAILURE; - } - } - - /* Get X11.app's pid */ - request_pid(mp, &x11app_pid); - - /* Handoff the $DISPLAY FD */ - if(launchd_fd != -1) { - size_t try, try_max; - int handoff_fd = -1; - - for(try=0, try_max=5; try < try_max; try++) { - if(request_fd_handoff_socket(mp, handoff_socket_filename) != KERN_SUCCESS) { - fprintf(stderr, "Xquartz: Failed to request a socket from the server to send the $DISPLAY fd over (try %d of %d)\n", (int)try+1, (int)try_max); - continue; - } - - handoff_fd = connect_to_socket(handoff_socket_filename); - if(handoff_fd == -1) { - fprintf(stderr, "Xquartz: Failed to connect to socket (try %d of %d)\n", (int)try+1, (int)try_max); - continue; - } - -#ifdef DEBUG - fprintf(stderr, "Xquartz: Handoff connection established (try %d of %d) on fd %d, \"%s\". Sending message.\n", (int)try+1, (int)try_max, handoff_fd, handoff_socket_filename); -#endif - - send_fd_handoff(handoff_fd, launchd_fd); - close(handoff_fd); - break; - } - } - - /* Count envp */ - for(envpc=0; envp[envpc]; envpc++); - - /* We have fixed-size string lengths due to limitations in IPC, - * so we need to copy our argv and envp. - */ - newargv = (string_array_t)malloc(argc * sizeof(string_t)); - newenvp = (string_array_t)malloc(envpc * sizeof(string_t)); - - if(!newargv || !newenvp) { - fprintf(stderr, "Xquartz: Memory allocation failure\n"); - return EXIT_FAILURE; - } - - for(i=0; i < argc; i++) { - strlcpy(newargv[i], argv[i], STRING_T_SIZE); - } - for(i=0; i < envpc; i++) { - strlcpy(newenvp[i], envp[i], STRING_T_SIZE); - } - - kr = start_x11_server(mp, newargv, argc, newenvp, envpc); - - free(newargv); - free(newenvp); - - if (kr != KERN_SUCCESS) { - fprintf(stderr, "Xquartz: start_x11_server: %s\n", mach_error_string(kr)); - return EXIT_FAILURE; - } - return EXIT_SUCCESS; -} +/* Copyright (c) 2008 Apple Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice 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.
+ *
+ * Except as contained in this notice, the name(s) of the above
+ * copyright holders shall not be used in advertising or otherwise to
+ * promote the sale, use or other dealings in this Software without
+ * prior written authorization.
+ */
+
+#include <CoreServices/CoreServices.h>
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#define kX11AppBundleId BUNDLE_ID_PREFIX".X11"
+#define kX11AppBundlePath "/Contents/MacOS/X11"
+
+static char *server_bootstrap_name = kX11AppBundleId;
+
+#include <mach/mach.h>
+#include <mach/mach_error.h>
+#include <servers/bootstrap.h>
+#include "mach_startup.h"
+
+#include <signal.h>
+
+#include <AvailabilityMacros.h>
+
+#include "launchd_fd.h"
+
+static char x11_path[PATH_MAX + 1];
+
+static pid_t x11app_pid = 0;
+
+static void set_x11_path(void) {
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
+
+ CFURLRef appURL = NULL;
+ OSStatus osstatus = LSFindApplicationForInfo(kLSUnknownCreator, CFSTR(kX11AppBundleId), nil, nil, &appURL);
+
+ switch (osstatus) {
+ case noErr:
+ if (appURL == NULL) {
+ fprintf(stderr, "Xquartz: Invalid response from LSFindApplicationForInfo(%s)\n",
+ kX11AppBundleId);
+ exit(1);
+ }
+
+ if (!CFURLGetFileSystemRepresentation(appURL, true, (unsigned char *)x11_path, sizeof(x11_path))) {
+ fprintf(stderr, "Xquartz: Error resolving URL for %s\n", kX11AppBundleId);
+ exit(3);
+ }
+
+ strlcat(x11_path, kX11AppBundlePath, sizeof(x11_path));
+#ifdef DEBUG
+ fprintf(stderr, "Xquartz: X11.app = %s\n", x11_path);
+#endif
+ break;
+ case kLSApplicationNotFoundErr:
+ fprintf(stderr, "Xquartz: Unable to find application for %s\n", kX11AppBundleId);
+ exit(10);
+ default:
+ fprintf(stderr, "Xquartz: Unable to find application for %s, error code = %d\n",
+ kX11AppBundleId, (int)osstatus);
+ exit(11);
+ }
+#else
+ /* TODO: Make Tiger smarter... but TBH, this should never get called on Tiger... */
+ strlcpy(x11_path, "/Applications/Utilities/X11.app/Contents/MacOS/X11", sizeof(x11_path));
+#endif
+}
+
+static int connect_to_socket(const char *filename) {
+ struct sockaddr_un servaddr_un;
+ struct sockaddr *servaddr;
+ socklen_t servaddr_len;
+ int ret_fd;
+
+ /* Setup servaddr_un */
+ memset (&servaddr_un, 0, sizeof (struct sockaddr_un));
+ servaddr_un.sun_family = AF_UNIX;
+ strlcpy(servaddr_un.sun_path, filename, sizeof(servaddr_un.sun_path));
+
+ servaddr = (struct sockaddr *) &servaddr_un;
+ servaddr_len = sizeof(struct sockaddr_un) - sizeof(servaddr_un.sun_path) + strlen(filename);
+
+ ret_fd = socket(PF_UNIX, SOCK_STREAM, 0);
+ if(ret_fd == -1) {
+ fprintf(stderr, "Xquartz: Failed to create socket: %s - %s\n", filename, strerror(errno));
+ return -1;
+ }
+
+ if(connect(ret_fd, servaddr, servaddr_len) < 0) {
+ fprintf(stderr, "Xquartz: Failed to connect to socket: %s - %d - %s\n", filename, errno, strerror(errno));
+ close(ret_fd);
+ return -1;
+ }
+
+ return ret_fd;
+}
+
+static void send_fd_handoff(int connected_fd, int launchd_fd) {
+ char databuf[] = "display";
+ struct iovec iov[1];
+
+ union {
+ struct cmsghdr hdr;
+ char bytes[CMSG_SPACE(sizeof(int))];
+ } buf;
+
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+
+ iov[0].iov_base = databuf;
+ iov[0].iov_len = sizeof(databuf);
+
+ msg.msg_iov = iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = buf.bytes;
+ msg.msg_controllen = sizeof(buf);
+ msg.msg_name = 0;
+ msg.msg_namelen = 0;
+ msg.msg_flags = 0;
+
+ cmsg = CMSG_FIRSTHDR (&msg);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(int));
+
+ msg.msg_controllen = cmsg->cmsg_len;
+
+ *((int*)CMSG_DATA(cmsg)) = launchd_fd;
+
+ if(sendmsg(connected_fd, &msg, 0) < 0) {
+ fprintf(stderr, "Xquartz: Error sending $DISPLAY file descriptor over fd %d: %d -- %s\n", connected_fd, errno, strerror(errno));
+ return;
+ }
+
+#ifdef DEBUG
+ fprintf(stderr, "Xquartz: Message sent. Closing handoff fd.\n");
+#endif
+
+ close(connected_fd);
+}
+
+static void signal_handler(int sig) {
+ if(x11app_pid)
+ kill(x11app_pid, sig);
+ _exit(0);
+}
+
+int main(int argc, char **argv, char **envp) {
+ int envpc;
+ kern_return_t kr;
+ mach_port_t mp;
+ string_array_t newenvp;
+ string_array_t newargv;
+ size_t i;
+ int launchd_fd;
+ string_t handoff_socket_filename;
+ sig_t handler;
+
+ if(getenv("X11_PREFS_DOMAIN"))
+ server_bootstrap_name = getenv("X11_PREFS_DOMAIN");
+
+ /* We don't have a mechanism in place to handle this interrupt driven
+ * server-start notification, so just send the signal now, so xinit doesn't
+ * time out waiting for it and will just poll for the server.
+ */
+ handler = signal(SIGUSR1, SIG_IGN);
+ if(handler == SIG_IGN)
+ kill(getppid(), SIGUSR1);
+ signal(SIGUSR1, handler);
+
+ /* Pass on SIGs to X11.app */
+ signal(SIGINT, signal_handler);
+ signal(SIGTERM, signal_handler);
+
+ /* Get the $DISPLAY FD */
+ launchd_fd = launchd_display_fd();
+
+ kr = bootstrap_look_up(bootstrap_port, server_bootstrap_name, &mp);
+ if(kr != KERN_SUCCESS) {
+ pid_t child;
+
+ fprintf(stderr, "Xquartz: Unable to locate waiting server: %s\n", server_bootstrap_name);
+ set_x11_path();
+
+ /* This forking is ugly and will be cleaned up later */
+ child = fork();
+ if(child == -1) {
+ fprintf(stderr, "Xquartz: Could not fork: %s\n", strerror(errno));
+ return EXIT_FAILURE;
+ }
+
+ if(child == 0) {
+ char *_argv[3];
+ _argv[0] = x11_path;
+ _argv[1] = "--listenonly";
+ _argv[2] = NULL;
+ fprintf(stderr, "Xquartz: Starting X server: %s --listenonly\n", x11_path);
+ return execvp(x11_path, _argv);
+ }
+
+ /* Try connecting for 10 seconds */
+ for(i=0; i < 80; i++) {
+ usleep(250000);
+ kr = bootstrap_look_up(bootstrap_port, server_bootstrap_name, &mp);
+ if(kr == KERN_SUCCESS)
+ break;
+ }
+
+ if(kr != KERN_SUCCESS) {
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
+ fprintf(stderr, "Xquartz: bootstrap_look_up(): %s\n", bootstrap_strerror(kr));
+#else
+ fprintf(stderr, "Xquartz: bootstrap_look_up(): %ul\n", (unsigned long)kr);
+#endif
+ return EXIT_FAILURE;
+ }
+ }
+
+ /* Get X11.app's pid */
+ request_pid(mp, &x11app_pid);
+
+ /* Handoff the $DISPLAY FD */
+ if(launchd_fd != -1) {
+ size_t try, try_max;
+ int handoff_fd = -1;
+
+ for(try=0, try_max=5; try < try_max; try++) {
+ if(request_fd_handoff_socket(mp, handoff_socket_filename) != KERN_SUCCESS) {
+ fprintf(stderr, "Xquartz: Failed to request a socket from the server to send the $DISPLAY fd over (try %d of %d)\n", (int)try+1, (int)try_max);
+ continue;
+ }
+
+ handoff_fd = connect_to_socket(handoff_socket_filename);
+ if(handoff_fd == -1) {
+ fprintf(stderr, "Xquartz: Failed to connect to socket (try %d of %d)\n", (int)try+1, (int)try_max);
+ continue;
+ }
+
+#ifdef DEBUG
+ fprintf(stderr, "Xquartz: Handoff connection established (try %d of %d) on fd %d, \"%s\". Sending message.\n", (int)try+1, (int)try_max, handoff_fd, handoff_socket_filename);
+#endif
+
+ send_fd_handoff(handoff_fd, launchd_fd);
+ close(handoff_fd);
+ break;
+ }
+ }
+
+ /* Count envp */
+ for(envpc=0; envp[envpc]; envpc++);
+
+ /* We have fixed-size string lengths due to limitations in IPC,
+ * so we need to copy our argv and envp.
+ */
+ newargv = (string_array_t)calloc((1 + argc), sizeof(string_t));
+ newenvp = (string_array_t)calloc((1 + envpc), sizeof(string_t));
+
+ if(!newargv || !newenvp) {
+ fprintf(stderr, "Xquartz: Memory allocation failure\n");
+ return EXIT_FAILURE;
+ }
+
+ for(i=0; i < argc; i++) {
+ strlcpy(newargv[i], argv[i], STRING_T_SIZE);
+ }
+ for(i=0; i < envpc; i++) {
+ strlcpy(newenvp[i], envp[i], STRING_T_SIZE);
+ }
+
+ kr = start_x11_server(mp, newargv, argc, newenvp, envpc);
+
+ free(newargv);
+ free(newenvp);
+
+ if (kr != KERN_SUCCESS) {
+ fprintf(stderr, "Xquartz: start_x11_server: %s\n", mach_error_string(kr));
+ return EXIT_FAILURE;
+ }
+ return EXIT_SUCCESS;
+}
diff --git a/xorg-server/hw/xquartz/pbproxy/Makefile.am b/xorg-server/hw/xquartz/pbproxy/Makefile.am index 188664259..e3782ac61 100644 --- a/xorg-server/hw/xquartz/pbproxy/Makefile.am +++ b/xorg-server/hw/xquartz/pbproxy/Makefile.am @@ -1,28 +1,28 @@ -AM_CPPFLAGS=-F/System/Library/Frameworks/ApplicationServices.framework/Frameworks \ - -DLAUNCHD_ID_PREFIX=\"$(LAUNCHD_ID_PREFIX)\" - -AM_CFLAGS=$(XPBPROXY_CFLAGS) - -noinst_LTLIBRARIES = libxpbproxy.la -libxpbproxy_la_SOURCES = \ - trick_autotools.c \ - main.m \ - x-input.m \ - x-selection.m - -libxpbproxy_la_LDFLAGS=$(XPBPROXY_LIBS) - -if STANDALONE_XPBPROXY - -bin_PROGRAMS = xpbproxy -xpbproxy_SOURCES = app-main.m -xpbproxy_LDADD = libxpbproxy.la -xpbproxy_LDFLAGS = -Wl,-framework,Cocoa - -AM_CPPFLAGS += -DSTANDALONE_XPBPROXY - -endif - -EXTRA_DIST = \ - pbproxy.h \ - x-selection.h +AM_CPPFLAGS=-F/System/Library/Frameworks/ApplicationServices.framework/Frameworks \
+ -DBUNDLE_ID_PREFIX=\"$(BUNDLE_ID_PREFIX)\"
+
+AM_CFLAGS=$(XPBPROXY_CFLAGS)
+
+noinst_LTLIBRARIES = libxpbproxy.la
+libxpbproxy_la_SOURCES = \
+ trick_autotools.c \
+ main.m \
+ x-input.m \
+ x-selection.m
+
+libxpbproxy_la_LDFLAGS=$(XPBPROXY_LIBS)
+
+if STANDALONE_XPBPROXY
+
+bin_PROGRAMS = xpbproxy
+xpbproxy_SOURCES = app-main.m
+xpbproxy_LDADD = libxpbproxy.la
+xpbproxy_LDFLAGS = -Wl,-framework,Cocoa
+
+AM_CPPFLAGS += -DSTANDALONE_XPBPROXY
+
+endif
+
+EXTRA_DIST = \
+ pbproxy.h \
+ x-selection.h
diff --git a/xorg-server/hw/xquartz/pbproxy/app-main.m b/xorg-server/hw/xquartz/pbproxy/app-main.m index b00e90a6d..4e61c05a3 100644 --- a/xorg-server/hw/xquartz/pbproxy/app-main.m +++ b/xorg-server/hw/xquartz/pbproxy/app-main.m @@ -1,93 +1,103 @@ -/* app-main.m - Copyright (c) 2002, 2008 Apple Computer, 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 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. - - Except as contained in this notice, the name(s) of the above - copyright holders shall not be used in advertising or otherwise to - promote the sale, use or other dealings in this Software without - prior written authorization. - */ - -#include "pbproxy.h" -#import "x-selection.h" - -#include <pthread.h> -#include <unistd.h> /*for getpid*/ -#include <Cocoa/Cocoa.h> - -static const char *app_prefs_domain = LAUNCHD_ID_PREFIX".xpbproxy"; -CFStringRef app_prefs_domain_cfstr; - -/* Stubs */ -char *display = NULL; -BOOL serverInitComplete = YES; -pthread_mutex_t serverInitCompleteMutex = PTHREAD_MUTEX_INITIALIZER; -pthread_cond_t serverInitCompleteCond = PTHREAD_COND_INITIALIZER; - -static void signal_handler (int sig) { - switch(sig) { - case SIGHUP: - xpbproxy_prefs_reload = YES; - break; - default: - _exit(EXIT_SUCCESS); - } -} - -int main (int argc, const char *argv[]) { - const char *s; - int i; - -#ifdef DEBUG - printf("pid: %u\n", getpid()); -#endif - - xpbproxy_is_standalone = YES; - - if((s = getenv("X11_PREFS_DOMAIN"))) - app_prefs_domain = s; - - for (i = 1; i < argc; i++) { - if(strcmp (argv[i], "--prefs-domain") == 0 && i+1 < argc) { - app_prefs_domain = argv[++i]; - } else if (strcmp (argv[i], "--help") == 0) { - printf("usage: xpbproxy OPTIONS\n" - "Pasteboard proxying for X11.\n\n" - "--prefs-domain <domain> Change the domain used for reading preferences\n" - " (default: %s)\n", app_prefs_domain); - return 0; - } else { - fprintf(stderr, "usage: xpbproxy OPTIONS...\n" - "Try 'xpbproxy --help' for more information.\n"); - return 1; - } - } - - app_prefs_domain_cfstr = CFStringCreateWithCString(NULL, app_prefs_domain, kCFStringEncodingUTF8); - - signal (SIGINT, signal_handler); - signal (SIGTERM, signal_handler); - signal (SIGHUP, signal_handler); - signal (SIGPIPE, SIG_IGN); - - return xpbproxy_run(); -} +/* app-main.m
+ Copyright (c) 2002, 2008 Apple Computer, 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 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.
+
+ Except as contained in this notice, the name(s) of the above
+ copyright holders shall not be used in advertising or otherwise to
+ promote the sale, use or other dealings in this Software without
+ prior written authorization.
+ */
+
+#include "pbproxy.h"
+#import "x-selection.h"
+
+#include <pthread.h>
+#include <unistd.h> /*for getpid*/
+#include <Cocoa/Cocoa.h>
+
+static const char *app_prefs_domain = BUNDLE_ID_PREFIX".xpbproxy";
+CFStringRef app_prefs_domain_cfstr;
+
+/* Stubs */
+char *display = NULL;
+BOOL serverInitComplete = YES;
+pthread_mutex_t serverInitCompleteMutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_cond_t serverInitCompleteCond = PTHREAD_COND_INITIALIZER;
+
+static void signal_handler (int sig) {
+ switch(sig) {
+ case SIGHUP:
+ xpbproxy_prefs_reload = YES;
+ break;
+ default:
+ _exit(EXIT_SUCCESS);
+ }
+}
+
+void
+ErrorF(const char * f, ...)
+{
+ va_list args;
+
+ va_start(args, f);
+ vfprintf(stderr, f, args);
+ va_end(args);
+}
+
+int main (int argc, const char *argv[]) {
+ const char *s;
+ int i;
+
+#ifdef DEBUG
+ ErrorF("pid: %u\n", getpid());
+#endif
+
+ xpbproxy_is_standalone = YES;
+
+ if((s = getenv("X11_PREFS_DOMAIN")))
+ app_prefs_domain = s;
+
+ for (i = 1; i < argc; i++) {
+ if(strcmp (argv[i], "--prefs-domain") == 0 && i+1 < argc) {
+ app_prefs_domain = argv[++i];
+ } else if (strcmp (argv[i], "--help") == 0) {
+ ErrorF("usage: xpbproxy OPTIONS\n"
+ "Pasteboard proxying for X11.\n\n"
+ "--prefs-domain <domain> Change the domain used for reading preferences\n"
+ " (default: %s)\n", app_prefs_domain);
+ return 0;
+ } else {
+ ErrorF("usage: xpbproxy OPTIONS...\n"
+ "Try 'xpbproxy --help' for more information.\n");
+ return 1;
+ }
+ }
+
+ app_prefs_domain_cfstr = CFStringCreateWithCString(NULL, app_prefs_domain, kCFStringEncodingUTF8);
+
+ signal (SIGINT, signal_handler);
+ signal (SIGTERM, signal_handler);
+ signal (SIGHUP, signal_handler);
+ signal (SIGPIPE, SIG_IGN);
+
+ return xpbproxy_run();
+}
diff --git a/xorg-server/hw/xquartz/pbproxy/main.m b/xorg-server/hw/xquartz/pbproxy/main.m index cfdc7696d..bae23dada 100644 --- a/xorg-server/hw/xquartz/pbproxy/main.m +++ b/xorg-server/hw/xquartz/pbproxy/main.m @@ -105,7 +105,7 @@ int xpbproxy_run (void) { }
if (xpbproxy_dpy == NULL) {
- fprintf (stderr, "xpbproxy: can't open default display\n");
+ ErrorF("xpbproxy: can't open default display\n");
[pool release];
return EXIT_FAILURE;
}
@@ -115,7 +115,7 @@ int xpbproxy_run (void) { if (!XAppleWMQueryExtension (xpbproxy_dpy, &xpbproxy_apple_wm_event_base,
&xpbproxy_apple_wm_error_base)) {
- fprintf (stderr, "xpbproxy: can't open AppleWM server extension\n");
+ ErrorF("xpbproxy: can't open AppleWM server extension\n");
[pool release];
return EXIT_FAILURE;
}
@@ -147,19 +147,3 @@ Time xpbproxy_current_timestamp (void) { /* FIXME: may want to fetch a timestamp from the server.. */
return CurrentTime;
}
-
-void debug_printf (const char *fmt, ...) {
- static int spew = -1;
-
- if (spew == -1) {
- char *x = getenv ("DEBUG");
- spew = (x != NULL && atoi (x) != 0);
- }
-
- if (spew) {
- va_list args;
- va_start(args, fmt);
- vfprintf (stderr, fmt, args);
- va_end(args);
- }
-}
diff --git a/xorg-server/hw/xquartz/pbproxy/pbproxy.h b/xorg-server/hw/xquartz/pbproxy/pbproxy.h index 013f981d4..3e5c93926 100644 --- a/xorg-server/hw/xquartz/pbproxy/pbproxy.h +++ b/xorg-server/hw/xquartz/pbproxy/pbproxy.h @@ -1,90 +1,92 @@ -/* pbproxy.h - Copyright (c) 2002, 2008 Apple Computer, 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 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. - - Except as contained in this notice, the name(s) of the above - copyright holders shall not be used in advertising or otherwise to - promote the sale, use or other dealings in this Software without - prior written authorization. -*/ - -#ifndef PBPROXY_H -#define PBPROXY_H 1 - -#import <Foundation/Foundation.h> - -#include <AvailabilityMacros.h> -#if MAC_OS_X_VERSION_MIN_REQUIRED < 1050 -#if __LP64__ || NS_BUILD_32_LIKE_64 -typedef long NSInteger; -typedef unsigned long NSUInteger; -#else -typedef int NSInteger; -typedef unsigned int NSUInteger; -#endif -#endif - -#define Cursor X_Cursor -#undef _SHAPE_H_ -#include <X11/Xlib.h> -#include <X11/extensions/shape.h> -#undef Cursor - -#ifdef STANDALONE_XPBPROXY -/* Just used for the standalone to respond to SIGHUP to reload prefs */ -extern BOOL xpbproxy_prefs_reload; - -/* Setting this to YES (for the standalone app) causes us to ignore the - * 'sync_pasteboard' defaults preference since we assume it to be on... this is - * mainly useful for debugging/developing xpbproxy with XQuartz still running. - * Just disable the one in the server with X11's preference pane, then run - * the standalone app. - */ -extern BOOL xpbproxy_is_standalone; -#endif - -/* from main.m */ -extern void xpbproxy_set_is_active (BOOL state); -extern BOOL xpbproxy_get_is_active (void); -extern id xpbproxy_selection_object (void); -extern Time xpbproxy_current_timestamp (void); -extern int xpbproxy_run (void); - -extern Display *xpbproxy_dpy; -extern int xpbproxy_apple_wm_event_base, xpbproxy_apple_wm_error_base; -extern int xpbproxy_xfixes_event_base, xpbproxy_xfixes_error_base; -extern BOOL xpbproxy_have_xfixes; - -/* from x-input.m */ -extern BOOL xpbproxy_input_register (void); - -#ifdef DEBUG -/* BEWARE: this can cause a string memory leak, according to the leaks program. */ -# define DB(msg, args...) debug_printf("%s:%s:%d " msg, __FILE__, __FUNCTION__, __LINE__, ##args) -#else -# define DB(msg, args...) do {} while (0) -#endif - -#define TRACE() DB("TRACE\n") -extern void debug_printf (const char *fmt, ...); - -#endif /* PBPROXY_H */ +/* pbproxy.h
+ Copyright (c) 2002, 2008 Apple Computer, 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 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.
+
+ Except as contained in this notice, the name(s) of the above
+ copyright holders shall not be used in advertising or otherwise to
+ promote the sale, use or other dealings in this Software without
+ prior written authorization.
+*/
+
+#ifndef PBPROXY_H
+#define PBPROXY_H 1
+
+#import <Foundation/Foundation.h>
+
+#include <AvailabilityMacros.h>
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1050
+#if __LP64__ || NS_BUILD_32_LIKE_64
+typedef long NSInteger;
+typedef unsigned long NSUInteger;
+#else
+typedef int NSInteger;
+typedef unsigned int NSUInteger;
+#endif
+#endif
+
+#define Cursor X_Cursor
+#undef _SHAPE_H_
+#include <X11/Xlib.h>
+#include <X11/extensions/shape.h>
+#undef Cursor
+
+#ifdef STANDALONE_XPBPROXY
+/* Just used for the standalone to respond to SIGHUP to reload prefs */
+extern BOOL xpbproxy_prefs_reload;
+
+/* Setting this to YES (for the standalone app) causes us to ignore the
+ * 'sync_pasteboard' defaults preference since we assume it to be on... this is
+ * mainly useful for debugging/developing xpbproxy with XQuartz still running.
+ * Just disable the one in the server with X11's preference pane, then run
+ * the standalone app.
+ */
+extern BOOL xpbproxy_is_standalone;
+#endif
+
+/* from main.m */
+extern void xpbproxy_set_is_active (BOOL state);
+extern BOOL xpbproxy_get_is_active (void);
+extern id xpbproxy_selection_object (void);
+extern Time xpbproxy_current_timestamp (void);
+extern int xpbproxy_run (void);
+
+extern Display *xpbproxy_dpy;
+extern int xpbproxy_apple_wm_event_base, xpbproxy_apple_wm_error_base;
+extern int xpbproxy_xfixes_event_base, xpbproxy_xfixes_error_base;
+extern BOOL xpbproxy_have_xfixes;
+
+/* from x-input.m */
+extern BOOL xpbproxy_input_register (void);
+
+/* os/log.c or app-main.m */
+extern void ErrorF(const char *f, ...) _X_ATTRIBUTE_PRINTF(1,2);
+
+#ifdef DEBUG
+/* BEWARE: this can cause a string memory leak, according to the leaks program. */
+# define DebugF(msg, args...) ErrorF("%s:%s:%d " msg, __FILE__, __FUNCTION__, __LINE__, ##args)
+#else
+# define DebugF(...) /* */
+#endif
+
+#define TRACE() DebugF("TRACE\n")
+
+#endif /* PBPROXY_H */
diff --git a/xorg-server/hw/xquartz/pbproxy/x-input.m b/xorg-server/hw/xquartz/pbproxy/x-input.m index 405ba3c73..7ecc90896 100644 --- a/xorg-server/hw/xquartz/pbproxy/x-input.m +++ b/xorg-server/hw/xquartz/pbproxy/x-input.m @@ -1,173 +1,173 @@ -/* x-input.m -- event handling - Copyright (c) 2002, 2008 Apple Computer, 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 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. - - Except as contained in this notice, the name(s) of the above - copyright holders shall not be used in advertising or otherwise to - promote the sale, use or other dealings in this Software without - prior written authorization. - */ - -#include "pbproxy.h" -#import "x-selection.h" - -#include <CoreFoundation/CFSocket.h> -#include <CoreFoundation/CFRunLoop.h> - -#include <X11/Xatom.h> -#include <X11/keysym.h> -#include <X11/extensions/applewm.h> - -#include <unistd.h> - -static CFRunLoopSourceRef xpbproxy_dpy_source; - -#ifdef STANDALONE_XPBPROXY -BOOL xpbproxy_prefs_reload = NO; -#endif - -/* Timestamp when the X server last told us it's active */ -static Time last_activation_time; - -static void x_event_apple_wm_notify(XAppleWMNotifyEvent *e) { - int type = e->type - xpbproxy_apple_wm_event_base; - int kind = e->kind; - - /* We want to reload prefs even if we're not active */ - if(type == AppleWMActivationNotify && - kind == AppleWMReloadPreferences) - [xpbproxy_selection_object() reload_preferences]; - - if(![xpbproxy_selection_object() is_active]) - return; - - switch (type) { - case AppleWMActivationNotify: - switch (kind) { - case AppleWMIsActive: - last_activation_time = e->time; - [xpbproxy_selection_object() x_active:e->time]; - break; - - case AppleWMIsInactive: - [xpbproxy_selection_object() x_inactive:e->time]; - break; - } - break; - - case AppleWMPasteboardNotify: - switch (kind) { - case AppleWMCopyToPasteboard: - [xpbproxy_selection_object() x_copy:e->time]; - } - break; - } -} - -static void xpbproxy_process_xevents(void) { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - if(pool == nil) { - fprintf(stderr, "unable to allocate/init auto release pool!\n"); - return; - } - - while (XPending(xpbproxy_dpy) != 0) { - XEvent e; - - XNextEvent (xpbproxy_dpy, &e); - - switch (e.type) { - case SelectionClear: - if([xpbproxy_selection_object() is_active]) - [xpbproxy_selection_object () clear_event:&e.xselectionclear]; - break; - - case SelectionRequest: - [xpbproxy_selection_object () request_event:&e.xselectionrequest]; - break; - - case SelectionNotify: - [xpbproxy_selection_object () notify_event:&e.xselection]; - break; - - case PropertyNotify: - [xpbproxy_selection_object () property_event:&e.xproperty]; - break; - - default: - if(e.type >= xpbproxy_apple_wm_event_base && - e.type < xpbproxy_apple_wm_event_base + AppleWMNumberEvents) { - x_event_apple_wm_notify((XAppleWMNotifyEvent *) &e); - } else if(e.type == xpbproxy_xfixes_event_base + XFixesSelectionNotify) { - [xpbproxy_selection_object() xfixes_selection_notify:(XFixesSelectionNotifyEvent *)&e]; - } - break; - } - - XFlush(xpbproxy_dpy); - } - - [pool release]; -} - -static BOOL add_input_socket (int sock, CFOptionFlags callback_types, - CFSocketCallBack callback, const CFSocketContext *ctx, - CFRunLoopSourceRef *cf_source) { - CFSocketRef cf_sock; - - cf_sock = CFSocketCreateWithNative (kCFAllocatorDefault, sock, - callback_types, callback, ctx); - if (cf_sock == NULL) { - close (sock); - return FALSE; - } - - *cf_source = CFSocketCreateRunLoopSource (kCFAllocatorDefault, - cf_sock, 0); - CFRelease (cf_sock); - - if (*cf_source == NULL) - return FALSE; - - CFRunLoopAddSource (CFRunLoopGetCurrent (), - *cf_source, kCFRunLoopDefaultMode); - return TRUE; -} - -static void x_input_callback (CFSocketRef sock, CFSocketCallBackType type, - CFDataRef address, const void *data, void *info) { - -#ifdef STANDALONE_XPBPROXY - if(xpbproxy_prefs_reload) { - [xpbproxy_selection_object() reload_preferences]; - xpbproxy_prefs_reload = NO; - } -#endif - - xpbproxy_process_xevents(); -} - -BOOL xpbproxy_input_register(void) { - return add_input_socket(ConnectionNumber(xpbproxy_dpy), kCFSocketReadCallBack, - x_input_callback, NULL, &xpbproxy_dpy_source); -} +/* x-input.m -- event handling
+ Copyright (c) 2002, 2008 Apple Computer, 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 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.
+
+ Except as contained in this notice, the name(s) of the above
+ copyright holders shall not be used in advertising or otherwise to
+ promote the sale, use or other dealings in this Software without
+ prior written authorization.
+ */
+
+#include "pbproxy.h"
+#import "x-selection.h"
+
+#include <CoreFoundation/CFSocket.h>
+#include <CoreFoundation/CFRunLoop.h>
+
+#include <X11/Xatom.h>
+#include <X11/keysym.h>
+#include <X11/extensions/applewm.h>
+
+#include <unistd.h>
+
+static CFRunLoopSourceRef xpbproxy_dpy_source;
+
+#ifdef STANDALONE_XPBPROXY
+BOOL xpbproxy_prefs_reload = NO;
+#endif
+
+/* Timestamp when the X server last told us it's active */
+static Time last_activation_time;
+
+static void x_event_apple_wm_notify(XAppleWMNotifyEvent *e) {
+ int type = e->type - xpbproxy_apple_wm_event_base;
+ int kind = e->kind;
+
+ /* We want to reload prefs even if we're not active */
+ if(type == AppleWMActivationNotify &&
+ kind == AppleWMReloadPreferences)
+ [xpbproxy_selection_object() reload_preferences];
+
+ if(![xpbproxy_selection_object() is_active])
+ return;
+
+ switch (type) {
+ case AppleWMActivationNotify:
+ switch (kind) {
+ case AppleWMIsActive:
+ last_activation_time = e->time;
+ [xpbproxy_selection_object() x_active:e->time];
+ break;
+
+ case AppleWMIsInactive:
+ [xpbproxy_selection_object() x_inactive:e->time];
+ break;
+ }
+ break;
+
+ case AppleWMPasteboardNotify:
+ switch (kind) {
+ case AppleWMCopyToPasteboard:
+ [xpbproxy_selection_object() x_copy:e->time];
+ }
+ break;
+ }
+}
+
+static void xpbproxy_process_xevents(void) {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ if(pool == nil) {
+ ErrorF("unable to allocate/init auto release pool!\n");
+ return;
+ }
+
+ while (XPending(xpbproxy_dpy) != 0) {
+ XEvent e;
+
+ XNextEvent (xpbproxy_dpy, &e);
+
+ switch (e.type) {
+ case SelectionClear:
+ if([xpbproxy_selection_object() is_active])
+ [xpbproxy_selection_object () clear_event:&e.xselectionclear];
+ break;
+
+ case SelectionRequest:
+ [xpbproxy_selection_object () request_event:&e.xselectionrequest];
+ break;
+
+ case SelectionNotify:
+ [xpbproxy_selection_object () notify_event:&e.xselection];
+ break;
+
+ case PropertyNotify:
+ [xpbproxy_selection_object () property_event:&e.xproperty];
+ break;
+
+ default:
+ if(e.type >= xpbproxy_apple_wm_event_base &&
+ e.type < xpbproxy_apple_wm_event_base + AppleWMNumberEvents) {
+ x_event_apple_wm_notify((XAppleWMNotifyEvent *) &e);
+ } else if(e.type == xpbproxy_xfixes_event_base + XFixesSelectionNotify) {
+ [xpbproxy_selection_object() xfixes_selection_notify:(XFixesSelectionNotifyEvent *)&e];
+ }
+ break;
+ }
+
+ XFlush(xpbproxy_dpy);
+ }
+
+ [pool release];
+}
+
+static BOOL add_input_socket (int sock, CFOptionFlags callback_types,
+ CFSocketCallBack callback, const CFSocketContext *ctx,
+ CFRunLoopSourceRef *cf_source) {
+ CFSocketRef cf_sock;
+
+ cf_sock = CFSocketCreateWithNative (kCFAllocatorDefault, sock,
+ callback_types, callback, ctx);
+ if (cf_sock == NULL) {
+ close (sock);
+ return FALSE;
+ }
+
+ *cf_source = CFSocketCreateRunLoopSource (kCFAllocatorDefault,
+ cf_sock, 0);
+ CFRelease (cf_sock);
+
+ if (*cf_source == NULL)
+ return FALSE;
+
+ CFRunLoopAddSource (CFRunLoopGetCurrent (),
+ *cf_source, kCFRunLoopDefaultMode);
+ return TRUE;
+}
+
+static void x_input_callback (CFSocketRef sock, CFSocketCallBackType type,
+ CFDataRef address, const void *data, void *info) {
+
+#ifdef STANDALONE_XPBPROXY
+ if(xpbproxy_prefs_reload) {
+ [xpbproxy_selection_object() reload_preferences];
+ xpbproxy_prefs_reload = NO;
+ }
+#endif
+
+ xpbproxy_process_xevents();
+}
+
+BOOL xpbproxy_input_register(void) {
+ return add_input_socket(ConnectionNumber(xpbproxy_dpy), kCFSocketReadCallBack,
+ x_input_callback, NULL, &xpbproxy_dpy_source);
+}
diff --git a/xorg-server/hw/xquartz/pbproxy/x-selection.m b/xorg-server/hw/xquartz/pbproxy/x-selection.m index ef84f8bfb..8c099c6c9 100644 --- a/xorg-server/hw/xquartz/pbproxy/x-selection.m +++ b/xorg-server/hw/xquartz/pbproxy/x-selection.m @@ -1,1541 +1,1560 @@ -/* x-selection.m -- proxies between NSPasteboard and X11 selections - - Copyright (c) 2002, 2008 Apple Computer, 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 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. - - Except as contained in this notice, the name(s) of the above - copyright holders shall not be used in advertising or otherwise to - promote the sale, use or other dealings in this Software without - prior written authorization. -*/ - -#import "x-selection.h" - -#include <stdio.h> -#include <stdlib.h> -#include <X11/Xatom.h> -#include <X11/Xutil.h> -#import <AppKit/NSGraphics.h> -#import <AppKit/NSImage.h> -#import <AppKit/NSBitmapImageRep.h> - -/* - * The basic design of the pbproxy code is as follows. - * - * When a client selects text, say from an xterm - we only copy it when the - * X11 Edit->Copy menu item is pressed or the shortcut activated. In this - * case we take the PRIMARY selection, and set it as the NSPasteboard data. - * - * When an X11 client copies something to the CLIPBOARD, pbproxy greedily grabs - * the data, sets it as the NSPasteboard data, and finally sets itself as - * owner of the CLIPBOARD. - * - * When an X11 window is activated we check to see if the NSPasteboard has - * changed. If the NSPasteboard has changed, then we set pbproxy as owner - * of the PRIMARY and CLIPBOARD and respond to requests for text and images. - * - * The behavior is now dynamic since the information above was written. - * The behavior is now dependent on the pbproxy_prefs below. - */ - -/* - * TODO: - * 1. handle MULTIPLE - I need to study the ICCCM further, and find a test app. - * 2. Handle NSPasteboard updates immediately, not on active/inactive - * - Open xterm, run 'cat readme.txt | pbcopy' - */ - -static struct { - BOOL active ; - BOOL primary_on_grab; /* This is provided as an option for people who - * want it and has issues that won't ever be - * addressed to make it *always* work. - */ - BOOL clipboard_to_pasteboard; - BOOL pasteboard_to_primary; - BOOL pasteboard_to_clipboard; -} pbproxy_prefs = { YES, NO, YES, YES, YES }; - -@implementation x_selection - -static struct propdata null_propdata = {NULL, 0, 0}; - -#ifdef DEBUG -static void -dump_prefs (FILE *fp) { - fprintf(fp, - "pbproxy preferences:\n" - "\tactive %u\n" - "\tprimary_on_grab %u\n" - "\tclipboard_to_pasteboard %u\n" - "\tpasteboard_to_primary %u\n" - "\tpasteboard_to_clipboard %u\n", - pbproxy_prefs.active, - pbproxy_prefs.primary_on_grab, - pbproxy_prefs.clipboard_to_pasteboard, - pbproxy_prefs.pasteboard_to_primary, - pbproxy_prefs.pasteboard_to_clipboard); -} -#endif - -extern CFStringRef app_prefs_domain_cfstr; - -static BOOL -prefs_get_bool (CFStringRef key, BOOL defaultValue) { - Boolean value, ok; - - value = CFPreferencesGetAppBooleanValue (key, app_prefs_domain_cfstr, &ok); - - return ok ? (BOOL) value : defaultValue; -} - -static void -init_propdata (struct propdata *pdata) -{ - *pdata = null_propdata; -} - -static void -free_propdata (struct propdata *pdata) -{ - free (pdata->data); - *pdata = null_propdata; -} - -/* - * Return True if an error occurs. Return False if pdata has data - * and we finished. - * The property is only deleted when bytesleft is 0 if delete is True. - */ -static Bool -get_property(Window win, Atom property, struct propdata *pdata, Bool delete, Atom *type) -{ - long offset = 0; - unsigned long numitems, bytesleft = 0; -#ifdef TEST - /* This is used to test the growth handling. */ - unsigned long length = 4UL; -#else - unsigned long length = (100000UL + 3) / 4; -#endif - unsigned char *buf = NULL, *chunk = NULL; - size_t buflen = 0, chunkbytesize = 0; - int format; - - TRACE (); - - if(None == property) - return True; - - do - { - unsigned long newbuflen = 0; - unsigned char *newbuf = NULL; - -#ifdef TEST - printf("bytesleft %lu\n", bytesleft); -#endif - - if (Success != XGetWindowProperty (xpbproxy_dpy, win, property, - offset, length, delete, - AnyPropertyType, - type, &format, &numitems, - &bytesleft, &chunk)) - { - DB ("Error while getting window property.\n"); - *pdata = null_propdata; - free (buf); - return True; - } - -#ifdef TEST - printf("format %d numitems %lu bytesleft %lu\n", - format, numitems, bytesleft); - - printf("type %s\n", XGetAtomName (xpbproxy_dpy, *type)); -#endif - - /* Format is the number of bits. */ - chunkbytesize = numitems * (format / 8); - -#ifdef TEST - printf("chunkbytesize %zu\n", chunkbytesize); -#endif - newbuflen = buflen + chunkbytesize; - if (newbuflen > 0) - { - newbuf = realloc (buf, newbuflen); - - if (NULL == newbuf) - { - XFree (chunk); - free (buf); - return True; - } - - memcpy (newbuf + buflen, chunk, chunkbytesize); - XFree (chunk); - buf = newbuf; - buflen = newbuflen; - /* offset is a multiple of 32 bits*/ - offset += chunkbytesize / 4; - } - else - { - if (chunk) - XFree (chunk); - } - -#ifdef TEST - printf("bytesleft %lu\n", bytesleft); -#endif - } while (bytesleft > 0); - - pdata->data = buf; - pdata->length = buflen; - pdata->format = format; - - return /*success*/ False; -} - - -/* Implementation methods */ - -/* This finds the preferred type from a TARGETS list.*/ -- (Atom) find_preferred:(struct propdata *)pdata -{ - Atom a = None; - size_t i, step; - Bool png = False, jpeg = False, utf8 = False, string = False; - - TRACE (); - - if (pdata->format != 32) - { - fprintf(stderr, "Atom list is expected to be formatted as an array of 32bit values.\n"); - return None; - } - - for (i = 0, step = pdata->format >> 3; i < pdata->length; i += step) - { - a = (Atom)*(uint32_t *)(pdata->data + i); - - if (a == atoms->image_png) - { - png = True; - } - else if (a == atoms->image_jpeg) - { - jpeg = True; - } - else if (a == atoms->utf8_string) - { - utf8 = True; - } - else if (a == atoms->string) - { - string = True; - } - else - { - char *type = XGetAtomName(xpbproxy_dpy, a); - if (type) - { - DB("Unhandled X11 mime type: %s", type); - XFree(type); - } - } - } - - /*We prefer PNG over strings, and UTF8 over a Latin-1 string.*/ - if (png) - return atoms->image_png; - - if (jpeg) - return atoms->image_jpeg; - - if (utf8) - return atoms->utf8_string; - - if (string) - return atoms->string; - - /* This is evidently something we don't know how to handle.*/ - return None; -} - -/* Return True if this is an INCR-style transfer. */ -- (Bool) is_incr_type:(XSelectionEvent *)e -{ - Atom seltype; - int format; - unsigned long numitems = 0UL, bytesleft = 0UL; - unsigned char *chunk; - - TRACE (); - - if (Success != XGetWindowProperty (xpbproxy_dpy, e->requestor, e->property, - /*offset*/ 0L, /*length*/ 4UL, - /*Delete*/ False, - AnyPropertyType, &seltype, &format, - &numitems, &bytesleft, &chunk)) - { - return False; - } - - if(chunk) - XFree(chunk); - - return (seltype == atoms->incr) ? True : False; -} - -/* - * This should be called after a selection has been copied, - * or when the selection is unfinished before a transfer completes. - */ -- (void) release_pending -{ - TRACE (); - - free_propdata (&pending.propdata); - pending.requestor = None; - pending.selection = None; -} - -/* Return True if an error occurs during an append.*/ -/* Return False if the append succeeds. */ -- (Bool) append_to_pending:(struct propdata *)pdata requestor:(Window)requestor -{ - unsigned char *newdata; - size_t newlength; - - TRACE (); - - if (requestor != pending.requestor) - { - [self release_pending]; - pending.requestor = requestor; - } - - newlength = pending.propdata.length + pdata->length; - newdata = realloc(pending.propdata.data, newlength); - - if(NULL == newdata) - { - perror("realloc propdata"); - [self release_pending]; - return True; - } - - memcpy(newdata + pending.propdata.length, pdata->data, pdata->length); - pending.propdata.data = newdata; - pending.propdata.length = newlength; - - return False; -} - - - -/* Called when X11 becomes active (i.e. has key focus) */ -- (void) x_active:(Time)timestamp -{ - static NSInteger changeCount; - NSInteger countNow; - NSPasteboard *pb; - - TRACE (); - - pb = [NSPasteboard generalPasteboard]; - - if (nil == pb) - return; - - countNow = [pb changeCount]; - - if (countNow != changeCount) - { - DB ("changed pasteboard!\n"); - changeCount = countNow; - - if (pbproxy_prefs.pasteboard_to_primary) - { - XSetSelectionOwner (xpbproxy_dpy, atoms->primary, _selection_window, CurrentTime); - } - - if (pbproxy_prefs.pasteboard_to_clipboard) { - [self own_clipboard]; - } - } - -#if 0 - /*gstaplin: we should perhaps investigate something like this branch above...*/ - if ([_pasteboard availableTypeFromArray: _known_types] != nil) - { - /* Pasteboard has data we should proxy; I think it makes - sense to put it on both CLIPBOARD and PRIMARY */ - - XSetSelectionOwner (xpbproxy_dpy, atoms->clipboard, - _selection_window, timestamp); - XSetSelectionOwner (xpbproxy_dpy, atoms->primary, - _selection_window, timestamp); - } -#endif -} - -/* Called when X11 loses key focus */ -- (void) x_inactive:(Time)timestamp -{ - TRACE (); -} - -/* This requests the TARGETS list from the PRIMARY selection owner. */ -- (void) x_copy_request_targets -{ - TRACE (); - - request_atom = atoms->targets; - XConvertSelection (xpbproxy_dpy, atoms->primary, atoms->targets, - atoms->primary, _selection_window, CurrentTime); -} - -/* Called when the Edit/Copy item on the main X11 menubar is selected - * and no appkit window claims it. */ -- (void) x_copy:(Time)timestamp -{ - Window w; - - TRACE (); - - w = XGetSelectionOwner (xpbproxy_dpy, atoms->primary); - - if (None != w) - { - ++pending_copy; - - if (1 == pending_copy) { - /* - * There are no other copy operations in progress, so we - * can proceed safely. Otherwise the copy_completed method - * will see that the pending_copy is > 1, and do another copy. - */ - [self x_copy_request_targets]; - } - } -} - -/* Set pbproxy as owner of the SELECTION_MANAGER selection. - * This prevents tools like xclipboard from causing havoc. - * Returns TRUE on success - */ -- (BOOL) set_clipboard_manager_status:(BOOL)value -{ - TRACE (); - - Window owner = XGetSelectionOwner (xpbproxy_dpy, atoms->clipboard_manager); - - if(value) { - if(owner == _selection_window) - return TRUE; - - if(owner != None) { - fprintf (stderr, "A clipboard manager using window 0x%lx " - "already owns the clipboard selection. " - "pbproxy will not sync clipboard to pasteboard.\n", owner); - return FALSE; - } - - XSetSelectionOwner(xpbproxy_dpy, atoms->clipboard_manager, _selection_window, CurrentTime); - return (_selection_window == XGetSelectionOwner(xpbproxy_dpy, atoms->clipboard_manager)); - } else { - if(owner != _selection_window) - return TRUE; - - XSetSelectionOwner(xpbproxy_dpy, atoms->clipboard_manager, None, CurrentTime); - return(None == XGetSelectionOwner(xpbproxy_dpy, atoms->clipboard_manager)); - } - - return FALSE; -} - -/* - * This occurs when we previously owned a selection, - * and then lost it from another client. - */ -- (void) clear_event:(XSelectionClearEvent *)e -{ - - - TRACE (); - - DB ("e->selection %s\n", XGetAtomName (xpbproxy_dpy, e->selection)); - - if(e->selection == atoms->clipboard) { - /* - * We lost ownership of the CLIPBOARD. - */ - ++pending_clipboard; - - if (1 == pending_clipboard) { - /* Claim the clipboard contents from the new owner. */ - [self claim_clipboard]; - } - } else if(e->selection == atoms->clipboard_manager) { - if(pbproxy_prefs.clipboard_to_pasteboard) { - /* Another CLIPBOARD_MANAGER has set itself as owner. Disable syncing - * to avoid a race. - */ - fprintf(stderr, "Another clipboard manager was started! " - "xpbproxy is disabling syncing with clipboard.\n"); - pbproxy_prefs.clipboard_to_pasteboard = NO; - } - } -} - -/* - * We greedily acquire the clipboard after it changes, and on startup. - */ -- (void) claim_clipboard -{ - Window owner; - - TRACE (); - - if (!pbproxy_prefs.clipboard_to_pasteboard) - return; - - owner = XGetSelectionOwner (xpbproxy_dpy, atoms->clipboard); - if (None == owner) { - /* - * The owner probably died or we are just starting up pbproxy. - * Set pbproxy's _selection_window as the owner, and continue. - */ - DB ("No clipboard owner.\n"); - [self copy_completed:atoms->clipboard]; - return; - } else if (owner == _selection_window) { - [self copy_completed:atoms->clipboard]; - return; - } - - DB ("requesting targets\n"); - - request_atom = atoms->targets; - XConvertSelection (xpbproxy_dpy, atoms->clipboard, atoms->targets, - atoms->clipboard, _selection_window, CurrentTime); - XFlush (xpbproxy_dpy); - /* Now we will get a SelectionNotify event in the future. */ -} - -/* Greedily acquire the clipboard. */ -- (void) own_clipboard -{ - - TRACE (); - - /* We should perhaps have a boundary limit on the number of iterations... */ - do - { - XSetSelectionOwner (xpbproxy_dpy, atoms->clipboard, _selection_window, - CurrentTime); - } while (_selection_window != XGetSelectionOwner (xpbproxy_dpy, - atoms->clipboard)); -} - -- (void) init_reply:(XEvent *)reply request:(XSelectionRequestEvent *)e -{ - reply->xselection.type = SelectionNotify; - reply->xselection.selection = e->selection; - reply->xselection.target = e->target; - reply->xselection.requestor = e->requestor; - reply->xselection.time = e->time; - reply->xselection.property = None; -} - -- (void) send_reply:(XEvent *)reply -{ - /* - * We are supposed to use an empty event mask, and not propagate - * the event, according to the ICCCM. - */ - DB ("reply->xselection.requestor 0x%lx\n", reply->xselection.requestor); - - XSendEvent (xpbproxy_dpy, reply->xselection.requestor, False, 0, reply); - XFlush (xpbproxy_dpy); -} - -/* - * This responds to a TARGETS request. - * The result is a list of a ATOMs that correspond to the types available - * for a selection. - * For instance an application might provide a UTF8_STRING and a STRING - * (in Latin-1 encoding). The requestor can then make the choice based on - * the list. - */ -- (void) send_targets:(XSelectionRequestEvent *)e pasteboard:(NSPasteboard *)pb -{ - XEvent reply; - NSArray *pbtypes; - - [self init_reply:&reply request:e]; - - pbtypes = [pb types]; - if (pbtypes) - { - long list[7]; /* Don't forget to increase this if we handle more types! */ - long count = 0; - - /* - * I'm not sure if this is needed, but some toolkits/clients list - * TARGETS in response to targets. - */ - list[count] = atoms->targets; - ++count; - - if ([pbtypes containsObject:NSStringPboardType]) - { - /* We have a string type that we can convert to UTF8, or Latin-1... */ - DB ("NSStringPboardType\n"); - list[count] = atoms->utf8_string; - ++count; - list[count] = atoms->string; - ++count; - list[count] = atoms->compound_text; - ++count; - } - - /* TODO add the NSPICTPboardType back again, once we have conversion - * functionality in send_image. - */ - - if ([pbtypes containsObject:NSPICTPboardType] - || [pbtypes containsObject:NSTIFFPboardType]) - { - /* We can convert a TIFF to a PNG or JPEG. */ - DB ("NSTIFFPboardType\n"); - list[count] = atoms->image_png; - ++count; - list[count] = atoms->image_jpeg; - ++count; - } - - if (count) - { - /* We have a list of ATOMs to send. */ - XChangeProperty (xpbproxy_dpy, e->requestor, e->property, atoms->atom, 32, - PropModeReplace, (unsigned char *) list, count); - - reply.xselection.property = e->property; - } - } - - [self send_reply:&reply]; -} - - -- (void) send_string:(XSelectionRequestEvent *)e utf8:(BOOL)utf8 pasteboard:(NSPasteboard *)pb -{ - XEvent reply; - NSArray *pbtypes; - NSString *data; - const char *bytes; - NSUInteger length; - - TRACE (); - - [self init_reply:&reply request:e]; - - pbtypes = [pb types]; - - if (![pbtypes containsObject:NSStringPboardType]) - { - [self send_reply:&reply]; - return; - } - - DB ("pbtypes retainCount after containsObject: %u\n", [pbtypes retainCount]); - - data = [pb stringForType:NSStringPboardType]; - - if (nil == data) - { - [self send_reply:&reply]; - return; - } - - if (utf8) - { - bytes = [data UTF8String]; - /* - * We don't want the UTF-8 string length here. - * We want the length in bytes. - */ - length = strlen (bytes); - - if (length < 50) { - DB ("UTF-8: %s\n", bytes); - DB ("UTF-8 length: %u\n", length); - } - } - else - { - DB ("Latin-1\n"); - bytes = [data cStringUsingEncoding:NSISOLatin1StringEncoding]; - /*WARNING: bytes is not NUL-terminated. */ - length = [data lengthOfBytesUsingEncoding:NSISOLatin1StringEncoding]; - } - - DB ("e->target %s\n", XGetAtomName (xpbproxy_dpy, e->target)); - - XChangeProperty (xpbproxy_dpy, e->requestor, e->property, e->target, - 8, PropModeReplace, (unsigned char *) bytes, length); - - reply.xselection.property = e->property; - - [self send_reply:&reply]; -} - -- (void) send_compound_text:(XSelectionRequestEvent *)e pasteboard:(NSPasteboard *)pb -{ - XEvent reply; - NSArray *pbtypes; - - TRACE (); - - [self init_reply:&reply request:e]; - - pbtypes = [pb types]; - - if ([pbtypes containsObject: NSStringPboardType]) - { - NSString *data = [pb stringForType:NSStringPboardType]; - if (nil != data) - { - /* - * Cast to (void *) to avoid a const warning. - * AFAIK Xutf8TextListToTextProperty does not modify the input memory. - */ - void *utf8 = (void *)[data UTF8String]; - char *list[] = { utf8, NULL }; - XTextProperty textprop; - - textprop.value = NULL; - - if (Success == Xutf8TextListToTextProperty (xpbproxy_dpy, list, 1, - XCompoundTextStyle, - &textprop)) - { - - if (8 != textprop.format) - DB ("textprop.format is unexpectedly not 8 - it's %d instead\n", - textprop.format); - - XChangeProperty (xpbproxy_dpy, e->requestor, e->property, - atoms->compound_text, textprop.format, - PropModeReplace, textprop.value, - textprop.nitems); - - reply.xselection.property = e->property; - } - - if (textprop.value) - XFree (textprop.value); - - } - } - - [self send_reply:&reply]; -} - -/* Finding a test application that uses MULTIPLE has proven to be difficult. */ -- (void) send_multiple:(XSelectionRequestEvent *)e -{ - XEvent reply; - - TRACE (); - - [self init_reply:&reply request:e]; - - if (None != e->property) - { - - } - - [self send_reply:&reply]; -} - -/* Return nil if an error occured. */ -/* DO NOT retain the encdata for longer than the length of an event response. - * The autorelease pool will reuse/free it. - */ -- (NSData *) encode_image_data:(NSData *)data type:(NSBitmapImageFileType)enctype -{ - NSBitmapImageRep *bmimage = nil; - NSData *encdata = nil; - NSDictionary *dict = nil; - - bmimage = [[NSBitmapImageRep alloc] initWithData:data]; - - if (nil == bmimage) - return nil; - - dict = [[NSDictionary alloc] init]; - encdata = [bmimage representationUsingType:enctype properties:dict]; - - if (nil == encdata) - { - [dict autorelease]; - [bmimage autorelease]; - return nil; - } - - [dict autorelease]; - [bmimage autorelease]; - - return encdata; -} - -/* Return YES when an error has occured when trying to send the PICT. */ -/* The caller should send a default reponse with a property of None when an error occurs. */ -- (BOOL) send_image_pict_reply:(XSelectionRequestEvent *)e - pasteboard:(NSPasteboard *)pb - type:(NSBitmapImageFileType)imagetype -{ - XEvent reply; - NSImage *img = nil; - NSData *data = nil, *encdata = nil; - NSUInteger length; - const void *bytes = NULL; - - img = [[NSImage alloc] initWithPasteboard:pb]; - - if (nil == img) - { - return YES; - } - - data = [img TIFFRepresentation]; - - if (nil == data) - { - [img autorelease]; - fprintf(stderr, "unable to convert PICT to TIFF!\n"); - return YES; - } - - encdata = [self encode_image_data:data type:imagetype]; - if(nil == encdata) - { - [img autorelease]; - return YES; - } - - [self init_reply:&reply request:e]; - - length = [encdata length]; - bytes = [encdata bytes]; - - XChangeProperty (xpbproxy_dpy, e->requestor, e->property, e->target, - 8, PropModeReplace, bytes, length); - reply.xselection.property = e->property; - - [self send_reply:&reply]; - - [img autorelease]; - - return NO; /*no error*/ -} - -/* Return YES if an error occured. */ -/* The caller should send a reply with a property of None when an error occurs. */ -- (BOOL) send_image_tiff_reply:(XSelectionRequestEvent *)e - pasteboard:(NSPasteboard *)pb - type:(NSBitmapImageFileType)imagetype -{ - XEvent reply; - NSData *data = nil; - NSData *encdata = nil; - NSUInteger length; - const void *bytes = NULL; - - data = [pb dataForType:NSTIFFPboardType]; - - if (nil == data) - return YES; - - encdata = [self encode_image_data:data type:imagetype]; - - if(nil == encdata) - return YES; - - [self init_reply:&reply request:e]; - - length = [encdata length]; - bytes = [encdata bytes]; - - XChangeProperty (xpbproxy_dpy, e->requestor, e->property, e->target, - 8, PropModeReplace, bytes, length); - reply.xselection.property = e->property; - - [self send_reply:&reply]; - - return NO; /*no error*/ -} - -- (void) send_image:(XSelectionRequestEvent *)e pasteboard:(NSPasteboard *)pb -{ - NSArray *pbtypes = nil; - NSBitmapImageFileType imagetype = NSPNGFileType; - - TRACE (); - - if (e->target == atoms->image_png) - imagetype = NSPNGFileType; - else if (e->target == atoms->image_jpeg) - imagetype = NSJPEGFileType; - else - { - fprintf(stderr, "internal failure in xpbproxy! imagetype being sent isn't PNG or JPEG.\n"); - } - - pbtypes = [pb types]; - - if (pbtypes) - { - if ([pbtypes containsObject:NSTIFFPboardType]) - { - if (NO == [self send_image_tiff_reply:e pasteboard:pb type:imagetype]) - return; - } - else if ([pbtypes containsObject:NSPICTPboardType]) - { - if (NO == [self send_image_pict_reply:e pasteboard:pb type:imagetype]) - return; - - /* Fall through intentionally to the send_none: */ - } - } - - [self send_none:e]; -} - -- (void)send_none:(XSelectionRequestEvent *)e -{ - XEvent reply; - - TRACE (); - - [self init_reply:&reply request:e]; - [self send_reply:&reply]; -} - - -/* Another client requested the data or targets of data available from the clipboard. */ -- (void)request_event:(XSelectionRequestEvent *)e -{ - NSPasteboard *pb; - - TRACE (); - - /* TODO We should also keep track of the time of the selection, and - * according to the ICCCM "refuse the request" if the event timestamp - * is before we owned it. - * What should we base the time on? How can we get the current time just - * before an XSetSelectionOwner? Is it the server's time, or the clients? - * According to the XSelectionRequestEvent manual page, the Time value - * may be set to CurrentTime or a time, so that makes it a bit different. - * Perhaps we should just punt and ignore races. - */ - - /*TODO we need a COMPOUND_TEXT test app*/ - /*TODO we need a MULTIPLE test app*/ - - pb = [NSPasteboard generalPasteboard]; - if (nil == pb) - { - [self send_none:e]; - return; - } - - - if (None != e->target) - DB ("e->target %s\n", XGetAtomName (xpbproxy_dpy, e->target)); - - if (e->target == atoms->targets) - { - /* The paste requestor wants to know what TARGETS we support. */ - [self send_targets:e pasteboard:pb]; - } - else if (e->target == atoms->multiple) - { - /* - * This isn't finished, and may never be, unless I can find - * a good test app. - */ - [self send_multiple:e]; - } - else if (e->target == atoms->utf8_string) - { - [self send_string:e utf8:YES pasteboard:pb]; - } - else if (e->target == atoms->string) - { - [self send_string:e utf8:NO pasteboard:pb]; - } - else if (e->target == atoms->compound_text) - { - [self send_compound_text:e pasteboard:pb]; - } - else if (e->target == atoms->multiple) - { - [self send_multiple:e]; - } - else if (e->target == atoms->image_png || e->target == atoms->image_jpeg) - { - [self send_image:e pasteboard:pb]; - } - else - { - [self send_none:e]; - } -} - -/* This handles the events resulting from an XConvertSelection request. */ -- (void) notify_event:(XSelectionEvent *)e -{ - Atom type; - struct propdata pdata; - - TRACE (); - - [self release_pending]; - - if (None == e->property) { - DB ("e->property is None.\n"); - [self copy_completed:e->selection]; - /* Nothing is selected. */ - return; - } - -#if 0 - printf ("e->selection %s\n", XGetAtomName (xpbproxy_dpy, e->selection)); - printf ("e->property %s\n", XGetAtomName (xpbproxy_dpy, e->property)); -#endif - - if ([self is_incr_type:e]) - { - /* - * This is an INCR-style transfer, which means that we - * will get the data after a series of PropertyNotify events. - */ - DB ("is INCR\n"); - - if (get_property (e->requestor, e->property, &pdata, /*Delete*/ True, &type)) - { - /* - * An error occured, so we should invoke the copy_completed:, but - * not handle_selection:type:propdata: - */ - [self copy_completed:e->selection]; - return; - } - - free_propdata (&pdata); - - pending.requestor = e->requestor; - pending.selection = e->selection; - - DB ("set pending.requestor to 0x%lx\n", pending.requestor); - } - else - { - if (get_property (e->requestor, e->property, &pdata, /*Delete*/ True, &type)) - { - [self copy_completed:e->selection]; - return; - } - - /* We have the complete selection data.*/ - [self handle_selection:e->selection type:type propdata:&pdata]; - - DB ("handled selection with the first notify_event\n"); - } -} - -/* This is used for INCR transfers. See the ICCCM for the details. */ -/* This is used to retrieve PRIMARY and CLIPBOARD selections. */ -- (void) property_event:(XPropertyEvent *)e -{ - struct propdata pdata; - Atom type; - - TRACE (); - - if (None != e->atom) - { -#ifdef DEBUG - char *name = XGetAtomName (xpbproxy_dpy, e->atom); - - if (name) - { - DB ("e->atom %s\n", name); - XFree(name); - } -#endif - } - - if (None != pending.requestor && PropertyNewValue == e->state) - { - DB ("pending.requestor 0x%lx\n", pending.requestor); - - if (get_property (e->window, e->atom, &pdata, /*Delete*/ True, &type)) - { - [self copy_completed:pending.selection]; - [self release_pending]; - return; - } - - if (0 == pdata.length) - { - /* - * We completed the transfer. - * handle_selection will call copy_completed: for us. - */ - [self handle_selection:pending.selection type:type propdata:&pending.propdata]; - free_propdata(&pdata); - pending.propdata = null_propdata; - pending.requestor = None; - pending.selection = None; - } - else - { - [self append_to_pending:&pdata requestor:e->window]; - free_propdata (&pdata); - } - } -} - -- (void) xfixes_selection_notify:(XFixesSelectionNotifyEvent *)e { - if(!pbproxy_prefs.active) - return; - - switch(e->subtype) { - case XFixesSetSelectionOwnerNotify: - if(e->selection == atoms->primary && pbproxy_prefs.primary_on_grab) - [self x_copy:e->timestamp]; - break; - - case XFixesSelectionWindowDestroyNotify: - case XFixesSelectionClientCloseNotify: - default: - fprintf(stderr, "Unhandled XFixesSelectionNotifyEvent: subtype=%d\n", e->subtype); - break; - } -} - -- (void) handle_targets: (Atom)selection propdata:(struct propdata *)pdata -{ - /* Find a type we can handle and prefer from the list of ATOMs. */ - Atom preferred; - char *name; - - TRACE (); - - preferred = [self find_preferred:pdata]; - - if (None == preferred) - { - /* - * This isn't required by the ICCCM, but some apps apparently - * don't respond to TARGETS properly. - */ - preferred = atoms->string; - } - - (void)name; /* Avoid a warning with non-debug compiles. */ -#ifdef DEBUG - name = XGetAtomName (xpbproxy_dpy, preferred); - - if (name) - { - DB ("requesting %s\n", name); - } -#endif - request_atom = preferred; - XConvertSelection (xpbproxy_dpy, selection, preferred, selection, - _selection_window, CurrentTime); -} - -/* This handles the image type of selection (typically in CLIPBOARD). */ -/* We convert to a TIFF, so that other applications can paste more easily. */ -- (void) handle_image: (struct propdata *)pdata pasteboard:(NSPasteboard *)pb -{ - NSArray *pbtypes; - NSUInteger length; - NSData *data, *tiff; - NSBitmapImageRep *bmimage; - - TRACE (); - - length = pdata->length; - data = [[NSData alloc] initWithBytes:pdata->data length:length]; - - if (nil == data) - { - DB ("unable to create NSData object!\n"); - return; - } - - DB ("data retainCount before NSBitmapImageRep initWithData: %u\n", - [data retainCount]); - - bmimage = [[NSBitmapImageRep alloc] initWithData:data]; - - if (nil == bmimage) - { - [data autorelease]; - DB ("unable to create NSBitmapImageRep!\n"); - return; - } - - DB ("data retainCount after NSBitmapImageRep initWithData: %u\n", - [data retainCount]); - - @try - { - tiff = [bmimage TIFFRepresentation]; - } - - @catch (NSException *e) - { - DB ("NSTIFFException!\n"); - [data autorelease]; - [bmimage autorelease]; - return; - } - - DB ("bmimage retainCount after TIFFRepresentation %u\n", [bmimage retainCount]); - - pbtypes = [NSArray arrayWithObjects:NSTIFFPboardType, nil]; - - if (nil == pbtypes) - { - [data autorelease]; - [bmimage autorelease]; - return; - } - - [pb declareTypes:pbtypes owner:nil]; - if (YES != [pb setData:tiff forType:NSTIFFPboardType]) - { - DB ("writing pasteboard data failed!\n"); - } - - [data autorelease]; - - DB ("bmimage retainCount before release %u\n", [bmimage retainCount]); - [bmimage autorelease]; -} - -/* This handles the UTF8_STRING type of selection. */ -- (void) handle_utf8_string:(struct propdata *)pdata pasteboard:(NSPasteboard *)pb -{ - NSString *string; - NSArray *pbtypes; - - TRACE (); - - string = [[NSString alloc] initWithBytes:pdata->data length:pdata->length encoding:NSUTF8StringEncoding]; - - if (nil == string) - return; - - pbtypes = [NSArray arrayWithObjects:NSStringPboardType, nil]; - - if (nil == pbtypes) - { - [string autorelease]; - return; - } - - [pb declareTypes:pbtypes owner:nil]; - - if (YES != [pb setString:string forType:NSStringPboardType]) { - fprintf(stderr, "pasteboard setString:forType: failed!\n"); - } - [string autorelease]; - DB ("done handling utf8 string\n"); -} - -/* This handles the STRING type, which should be in Latin-1. */ -- (void) handle_string: (struct propdata *)pdata pasteboard:(NSPasteboard *)pb -{ - NSString *string; - NSArray *pbtypes; - - TRACE (); - - string = [[NSString alloc] initWithBytes:pdata->data length:pdata->length encoding:NSISOLatin1StringEncoding]; - - if (nil == string) - return; - - pbtypes = [NSArray arrayWithObjects:NSStringPboardType, nil]; - - if (nil == pbtypes) - { - [string autorelease]; - return; - } - - [pb declareTypes:pbtypes owner:nil]; - if (YES != [pb setString:string forType:NSStringPboardType]) { - fprintf(stderr, "pasteboard setString:forType failed in handle_string!\n"); - } - [string autorelease]; -} - -/* This is called when the selection is completely retrieved from another client. */ -/* Warning: this frees the propdata. */ -- (void) handle_selection:(Atom)selection type:(Atom)type propdata:(struct propdata *)pdata -{ - NSPasteboard *pb; - - TRACE (); - - pb = [NSPasteboard generalPasteboard]; - - if (nil == pb) - { - [self copy_completed:selection]; - free_propdata (pdata); - return; - } - - /* - * Some apps it seems set the type to TARGETS instead of ATOM, such as Eterm. - * These aren't ICCCM compliant apps, but we need these to work... - */ - if (request_atom == atoms->targets - && (type == atoms->atom || type == atoms->targets)) - { - [self handle_targets:selection propdata:pdata]; - free_propdata(pdata); - return; - } - else if (type == atoms->image_png) - { - [self handle_image:pdata pasteboard:pb]; - } - else if (type == atoms->image_jpeg) - { - [self handle_image:pdata pasteboard:pb]; - } - else if (type == atoms->utf8_string) - { - [self handle_utf8_string:pdata pasteboard:pb]; - } - else if (type == atoms->string) - { - [self handle_string:pdata pasteboard:pb]; - } - - free_propdata(pdata); - - [self copy_completed:selection]; -} - - -- (void) copy_completed:(Atom)selection -{ - TRACE (); - char *name; - - (void)name; /* Avoid warning with non-debug compiles. */ -#ifdef DEBUG - name = XGetAtomName (xpbproxy_dpy, selection); - if (name) - { - DB ("copy_completed: %s\n", name); - XFree (name); - } -#endif - - if (selection == atoms->primary && pending_copy > 0) - { - --pending_copy; - if (pending_copy > 0) - { - /* Copy PRIMARY again. */ - [self x_copy_request_targets]; - return; - } - } - else if (selection == atoms->clipboard && pending_clipboard > 0) - { - --pending_clipboard; - if (pending_clipboard > 0) - { - /* Copy CLIPBOARD. */ - [self claim_clipboard]; - return; - } - else - { - /* We got the final data. Now set pbproxy as the owner. */ - [self own_clipboard]; - return; - } - } - - /* - * We had 1 or more primary in progress, and the clipboard arrived - * while we were busy. - */ - if (pending_clipboard > 0) - { - [self claim_clipboard]; - } -} - -- (void) reload_preferences -{ - /* - * It's uncertain how we could handle the synchronization failing, so cast to void. - * The prefs_get_bool should fall back to defaults if the org.x.X11 plist doesn't exist or is invalid. - */ - (void)CFPreferencesAppSynchronize(app_prefs_domain_cfstr); -#ifdef STANDALONE_XPBPROXY - if(xpbproxy_is_standalone) - pbproxy_prefs.active = YES; - else -#endif - pbproxy_prefs.active = prefs_get_bool(CFSTR("sync_pasteboard"), pbproxy_prefs.active); - pbproxy_prefs.primary_on_grab = prefs_get_bool(CFSTR("sync_primary_on_select"), pbproxy_prefs.primary_on_grab); - pbproxy_prefs.clipboard_to_pasteboard = prefs_get_bool(CFSTR("sync_clipboard_to_pasteboard"), pbproxy_prefs.clipboard_to_pasteboard); - pbproxy_prefs.pasteboard_to_primary = prefs_get_bool(CFSTR("sync_pasteboard_to_primary"), pbproxy_prefs.pasteboard_to_primary); - pbproxy_prefs.pasteboard_to_clipboard = prefs_get_bool(CFSTR("sync_pasteboard_to_clipboard"), pbproxy_prefs.pasteboard_to_clipboard); - - /* This is used for debugging. */ - //dump_prefs(stdout); - - if(pbproxy_prefs.active && pbproxy_prefs.primary_on_grab && !xpbproxy_have_xfixes) { - fprintf(stderr, "Disabling sync_primary_on_select functionality due to missing XFixes extension.\n"); - pbproxy_prefs.primary_on_grab = NO; - } - - /* Claim or release the CLIPBOARD_MANAGER atom */ - if(![self set_clipboard_manager_status:(pbproxy_prefs.active && pbproxy_prefs.clipboard_to_pasteboard)]) - pbproxy_prefs.clipboard_to_pasteboard = NO; - - if(pbproxy_prefs.active && pbproxy_prefs.clipboard_to_pasteboard) - [self claim_clipboard]; -} - -- (BOOL) is_active -{ - return pbproxy_prefs.active; -} - -/* NSPasteboard-required methods */ - -- (void) paste:(id)sender -{ - TRACE (); -} - -- (void) pasteboard:(NSPasteboard *)pb provideDataForType:(NSString *)type -{ - TRACE (); -} - -- (void) pasteboardChangedOwner:(NSPasteboard *)pb -{ - TRACE (); - - /* Right now we don't care with this. */ -} - -/* Allocation */ - -- init -{ - unsigned long pixel; - - self = [super init]; - if (self == nil) - return nil; - - atoms->primary = XInternAtom (xpbproxy_dpy, "PRIMARY", False); - atoms->clipboard = XInternAtom (xpbproxy_dpy, "CLIPBOARD", False); - atoms->text = XInternAtom (xpbproxy_dpy, "TEXT", False); - atoms->utf8_string = XInternAtom (xpbproxy_dpy, "UTF8_STRING", False); - atoms->string = XInternAtom (xpbproxy_dpy, "STRING", False); - atoms->targets = XInternAtom (xpbproxy_dpy, "TARGETS", False); - atoms->multiple = XInternAtom (xpbproxy_dpy, "MULTIPLE", False); - atoms->cstring = XInternAtom (xpbproxy_dpy, "CSTRING", False); - atoms->image_png = XInternAtom (xpbproxy_dpy, "image/png", False); - atoms->image_jpeg = XInternAtom (xpbproxy_dpy, "image/jpeg", False); - atoms->incr = XInternAtom (xpbproxy_dpy, "INCR", False); - atoms->atom = XInternAtom (xpbproxy_dpy, "ATOM", False); - atoms->clipboard_manager = XInternAtom (xpbproxy_dpy, "CLIPBOARD_MANAGER", False); - atoms->compound_text = XInternAtom (xpbproxy_dpy, "COMPOUND_TEXT", False); - atoms->atom_pair = XInternAtom (xpbproxy_dpy, "ATOM_PAIR", False); - - pixel = BlackPixel (xpbproxy_dpy, DefaultScreen (xpbproxy_dpy)); - _selection_window = XCreateSimpleWindow (xpbproxy_dpy, DefaultRootWindow (xpbproxy_dpy), - 0, 0, 1, 1, 0, pixel, pixel); - - /* This is used to get PropertyNotify events when doing INCR transfers. */ - XSelectInput (xpbproxy_dpy, _selection_window, PropertyChangeMask); - - request_atom = None; - - init_propdata (&pending.propdata); - pending.requestor = None; - pending.selection = None; - - pending_copy = 0; - pending_clipboard = 0; - - if(xpbproxy_have_xfixes) - XFixesSelectSelectionInput(xpbproxy_dpy, _selection_window, atoms->primary, - XFixesSetSelectionOwnerNotifyMask); - - [self reload_preferences]; - - return self; -} - -- (void) dealloc -{ - if (None != _selection_window) - { - XDestroyWindow (xpbproxy_dpy, _selection_window); - _selection_window = None; - } - - free_propdata (&pending.propdata); - - [super dealloc]; -} - -@end +/* x-selection.m -- proxies between NSPasteboard and X11 selections
+
+ Copyright (c) 2002, 2008 Apple Computer, 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 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.
+
+ Except as contained in this notice, the name(s) of the above
+ copyright holders shall not be used in advertising or otherwise to
+ promote the sale, use or other dealings in this Software without
+ prior written authorization.
+*/
+
+#import "x-selection.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <X11/Xatom.h>
+#include <X11/Xutil.h>
+#import <AppKit/NSGraphics.h>
+#import <AppKit/NSImage.h>
+#import <AppKit/NSBitmapImageRep.h>
+
+/*
+ * The basic design of the pbproxy code is as follows.
+ *
+ * When a client selects text, say from an xterm - we only copy it when the
+ * X11 Edit->Copy menu item is pressed or the shortcut activated. In this
+ * case we take the PRIMARY selection, and set it as the NSPasteboard data.
+ *
+ * When an X11 client copies something to the CLIPBOARD, pbproxy greedily grabs
+ * the data, sets it as the NSPasteboard data, and finally sets itself as
+ * owner of the CLIPBOARD.
+ *
+ * When an X11 window is activated we check to see if the NSPasteboard has
+ * changed. If the NSPasteboard has changed, then we set pbproxy as owner
+ * of the PRIMARY and CLIPBOARD and respond to requests for text and images.
+ *
+ * The behavior is now dynamic since the information above was written.
+ * The behavior is now dependent on the pbproxy_prefs below.
+ */
+
+/*
+ * TODO:
+ * 1. handle MULTIPLE - I need to study the ICCCM further, and find a test app.
+ * 2. Handle NSPasteboard updates immediately, not on active/inactive
+ * - Open xterm, run 'cat readme.txt | pbcopy'
+ */
+
+static struct {
+ BOOL active ;
+ BOOL primary_on_grab; /* This is provided as an option for people who
+ * want it and has issues that won't ever be
+ * addressed to make it *always* work.
+ */
+ BOOL clipboard_to_pasteboard;
+ BOOL pasteboard_to_primary;
+ BOOL pasteboard_to_clipboard;
+} pbproxy_prefs = { YES, NO, YES, YES, YES };
+
+@implementation x_selection
+
+static struct propdata null_propdata = {NULL, 0, 0};
+
+#ifdef DEBUG
+static void
+dump_prefs() {
+ ErrorF(fp,
+ "pbproxy preferences:\n"
+ "\tactive %u\n"
+ "\tprimary_on_grab %u\n"
+ "\tclipboard_to_pasteboard %u\n"
+ "\tpasteboard_to_primary %u\n"
+ "\tpasteboard_to_clipboard %u\n",
+ pbproxy_prefs.active,
+ pbproxy_prefs.primary_on_grab,
+ pbproxy_prefs.clipboard_to_pasteboard,
+ pbproxy_prefs.pasteboard_to_primary,
+ pbproxy_prefs.pasteboard_to_clipboard);
+}
+#endif
+
+extern CFStringRef app_prefs_domain_cfstr;
+
+static BOOL
+prefs_get_bool (CFStringRef key, BOOL defaultValue) {
+ Boolean value, ok;
+
+ value = CFPreferencesGetAppBooleanValue (key, app_prefs_domain_cfstr, &ok);
+
+ return ok ? (BOOL) value : defaultValue;
+}
+
+static void
+init_propdata (struct propdata *pdata)
+{
+ *pdata = null_propdata;
+}
+
+static void
+free_propdata (struct propdata *pdata)
+{
+ free (pdata->data);
+ *pdata = null_propdata;
+}
+
+/*
+ * Return True if an error occurs. Return False if pdata has data
+ * and we finished.
+ * The property is only deleted when bytesleft is 0 if delete is True.
+ */
+static Bool
+get_property(Window win, Atom property, struct propdata *pdata, Bool delete, Atom *type)
+{
+ long offset = 0;
+ unsigned long numitems, bytesleft = 0;
+#ifdef TEST
+ /* This is used to test the growth handling. */
+ unsigned long length = 4UL;
+#else
+ unsigned long length = (100000UL + 3) / 4;
+#endif
+ unsigned char *buf = NULL, *chunk = NULL;
+ size_t buflen = 0, chunkbytesize = 0;
+ int format;
+
+ TRACE ();
+
+ if(None == property)
+ return True;
+
+ do
+ {
+ unsigned long newbuflen = 0;
+ unsigned char *newbuf = NULL;
+
+#ifdef TEST
+ ErrorF("bytesleft %lu\n", bytesleft);
+#endif
+
+ if (Success != XGetWindowProperty (xpbproxy_dpy, win, property,
+ offset, length, delete,
+ AnyPropertyType,
+ type, &format, &numitems,
+ &bytesleft, &chunk))
+ {
+ DebugF ("Error while getting window property.\n");
+ *pdata = null_propdata;
+ free (buf);
+ return True;
+ }
+
+#ifdef TEST
+ ErrorF("format %d numitems %lu bytesleft %lu\n",
+ format, numitems, bytesleft);
+
+ ErrorF("type %s\n", XGetAtomName (xpbproxy_dpy, *type));
+#endif
+
+ /* Format is the number of bits. */
+ if (format == 8)
+ chunkbytesize = numitems;
+ else if (format == 16)
+ chunkbytesize = numitems * sizeof(short);
+ else if (format == 32)
+ chunkbytesize = numitems * sizeof(long);
+
+#ifdef TEST
+ ErrorF("chunkbytesize %zu\n", chunkbytesize);
+#endif
+ newbuflen = buflen + chunkbytesize;
+ if (newbuflen > 0)
+ {
+ newbuf = realloc (buf, newbuflen);
+
+ if (NULL == newbuf)
+ {
+ XFree (chunk);
+ free (buf);
+ return True;
+ }
+
+ memcpy (newbuf + buflen, chunk, chunkbytesize);
+ XFree (chunk);
+ buf = newbuf;
+ buflen = newbuflen;
+ /* offset is a multiple of 32 bits*/
+ offset += chunkbytesize / 4;
+ }
+ else
+ {
+ if (chunk)
+ XFree (chunk);
+ }
+
+#ifdef TEST
+ ErrorF("bytesleft %lu\n", bytesleft);
+#endif
+ } while (bytesleft > 0);
+
+ pdata->data = buf;
+ pdata->length = buflen;
+ pdata->format = format;
+
+ return /*success*/ False;
+}
+
+
+/* Implementation methods */
+
+/* This finds the preferred type from a TARGETS list.*/
+- (Atom) find_preferred:(struct propdata *)pdata
+{
+ Atom a = None;
+ size_t i, step;
+ Bool png = False, jpeg = False, utf8 = False, string = False;
+
+ TRACE ();
+
+ if (pdata->format != 32)
+ {
+ ErrorF("Atom list is expected to be formatted as an array of 32bit values.\n");
+ return None;
+ }
+
+ for (i = 0, step = sizeof(long); i < pdata->length; i += step)
+ {
+ a = (Atom)*(long *)(pdata->data + i);
+
+ if (a == atoms->image_png)
+ {
+ png = True;
+ }
+ else if (a == atoms->image_jpeg)
+ {
+ jpeg = True;
+ }
+ else if (a == atoms->utf8_string)
+ {
+ utf8 = True;
+ }
+ else if (a == atoms->string)
+ {
+ string = True;
+ }
+ else
+ {
+ char *type = XGetAtomName(xpbproxy_dpy, a);
+ if (type)
+ {
+ DebugF("Unhandled X11 mime type: %s", type);
+ XFree(type);
+ }
+ }
+ }
+
+ /*We prefer PNG over strings, and UTF8 over a Latin-1 string.*/
+ if (png)
+ return atoms->image_png;
+
+ if (jpeg)
+ return atoms->image_jpeg;
+
+ if (utf8)
+ return atoms->utf8_string;
+
+ if (string)
+ return atoms->string;
+
+ /* This is evidently something we don't know how to handle.*/
+ return None;
+}
+
+/* Return True if this is an INCR-style transfer. */
+- (Bool) is_incr_type:(XSelectionEvent *)e
+{
+ Atom seltype;
+ int format;
+ unsigned long numitems = 0UL, bytesleft = 0UL;
+ unsigned char *chunk;
+
+ TRACE ();
+
+ if (Success != XGetWindowProperty (xpbproxy_dpy, e->requestor, e->property,
+ /*offset*/ 0L, /*length*/ 4UL,
+ /*Delete*/ False,
+ AnyPropertyType, &seltype, &format,
+ &numitems, &bytesleft, &chunk))
+ {
+ return False;
+ }
+
+ if(chunk)
+ XFree(chunk);
+
+ return (seltype == atoms->incr) ? True : False;
+}
+
+/*
+ * This should be called after a selection has been copied,
+ * or when the selection is unfinished before a transfer completes.
+ */
+- (void) release_pending
+{
+ TRACE ();
+
+ free_propdata (&pending.propdata);
+ pending.requestor = None;
+ pending.selection = None;
+}
+
+/* Return True if an error occurs during an append.*/
+/* Return False if the append succeeds. */
+- (Bool) append_to_pending:(struct propdata *)pdata requestor:(Window)requestor
+{
+ unsigned char *newdata;
+ size_t newlength;
+
+ TRACE ();
+
+ if (requestor != pending.requestor)
+ {
+ [self release_pending];
+ pending.requestor = requestor;
+ }
+
+ newlength = pending.propdata.length + pdata->length;
+ newdata = realloc(pending.propdata.data, newlength);
+
+ if(NULL == newdata)
+ {
+ perror("realloc propdata");
+ [self release_pending];
+ return True;
+ }
+
+ memcpy(newdata + pending.propdata.length, pdata->data, pdata->length);
+ pending.propdata.data = newdata;
+ pending.propdata.length = newlength;
+
+ return False;
+}
+
+
+
+/* Called when X11 becomes active (i.e. has key focus) */
+- (void) x_active:(Time)timestamp
+{
+ static NSInteger changeCount;
+ NSInteger countNow;
+ NSPasteboard *pb;
+
+ TRACE ();
+
+ pb = [NSPasteboard generalPasteboard];
+
+ if (nil == pb)
+ return;
+
+ countNow = [pb changeCount];
+
+ if (countNow != changeCount)
+ {
+ DebugF ("changed pasteboard!\n");
+ changeCount = countNow;
+
+ if (pbproxy_prefs.pasteboard_to_primary)
+ {
+ XSetSelectionOwner (xpbproxy_dpy, atoms->primary, _selection_window, CurrentTime);
+ }
+
+ if (pbproxy_prefs.pasteboard_to_clipboard) {
+ [self own_clipboard];
+ }
+ }
+
+#if 0
+ /*gstaplin: we should perhaps investigate something like this branch above...*/
+ if ([_pasteboard availableTypeFromArray: _known_types] != nil)
+ {
+ /* Pasteboard has data we should proxy; I think it makes
+ sense to put it on both CLIPBOARD and PRIMARY */
+
+ XSetSelectionOwner (xpbproxy_dpy, atoms->clipboard,
+ _selection_window, timestamp);
+ XSetSelectionOwner (xpbproxy_dpy, atoms->primary,
+ _selection_window, timestamp);
+ }
+#endif
+}
+
+/* Called when X11 loses key focus */
+- (void) x_inactive:(Time)timestamp
+{
+ TRACE ();
+}
+
+/* This requests the TARGETS list from the PRIMARY selection owner. */
+- (void) x_copy_request_targets
+{
+ TRACE ();
+
+ request_atom = atoms->targets;
+ XConvertSelection (xpbproxy_dpy, atoms->primary, atoms->targets,
+ atoms->primary, _selection_window, CurrentTime);
+}
+
+/* Called when the Edit/Copy item on the main X11 menubar is selected
+ * and no appkit window claims it. */
+- (void) x_copy:(Time)timestamp
+{
+ Window w;
+
+ TRACE ();
+
+ w = XGetSelectionOwner (xpbproxy_dpy, atoms->primary);
+
+ if (None != w)
+ {
+ ++pending_copy;
+
+ if (1 == pending_copy) {
+ /*
+ * There are no other copy operations in progress, so we
+ * can proceed safely. Otherwise the copy_completed method
+ * will see that the pending_copy is > 1, and do another copy.
+ */
+ [self x_copy_request_targets];
+ }
+ }
+}
+
+/* Set pbproxy as owner of the SELECTION_MANAGER selection.
+ * This prevents tools like xclipboard from causing havoc.
+ * Returns TRUE on success
+ */
+- (BOOL) set_clipboard_manager_status:(BOOL)value
+{
+ TRACE ();
+
+ Window owner = XGetSelectionOwner (xpbproxy_dpy, atoms->clipboard_manager);
+
+ if(value) {
+ if(owner == _selection_window)
+ return TRUE;
+
+ if(owner != None) {
+ ErrorF("A clipboard manager using window 0x%lx already owns the clipboard selection. "
+ "pbproxy will not sync clipboard to pasteboard.\n", owner);
+ return FALSE;
+ }
+
+ XSetSelectionOwner(xpbproxy_dpy, atoms->clipboard_manager, _selection_window, CurrentTime);
+ return (_selection_window == XGetSelectionOwner(xpbproxy_dpy, atoms->clipboard_manager));
+ } else {
+ if(owner != _selection_window)
+ return TRUE;
+
+ XSetSelectionOwner(xpbproxy_dpy, atoms->clipboard_manager, None, CurrentTime);
+ return(None == XGetSelectionOwner(xpbproxy_dpy, atoms->clipboard_manager));
+ }
+
+ return FALSE;
+}
+
+/*
+ * This occurs when we previously owned a selection,
+ * and then lost it from another client.
+ */
+- (void) clear_event:(XSelectionClearEvent *)e
+{
+
+
+ TRACE ();
+
+ DebugF ("e->selection %s\n", XGetAtomName (xpbproxy_dpy, e->selection));
+
+ if(e->selection == atoms->clipboard) {
+ /*
+ * We lost ownership of the CLIPBOARD.
+ */
+ ++pending_clipboard;
+
+ if (1 == pending_clipboard) {
+ /* Claim the clipboard contents from the new owner. */
+ [self claim_clipboard];
+ }
+ } else if(e->selection == atoms->clipboard_manager) {
+ if(pbproxy_prefs.clipboard_to_pasteboard) {
+ /* Another CLIPBOARD_MANAGER has set itself as owner. Disable syncing
+ * to avoid a race.
+ */
+ ErrorF("Another clipboard manager was started! "
+ "xpbproxy is disabling syncing with clipboard.\n");
+ pbproxy_prefs.clipboard_to_pasteboard = NO;
+ }
+ }
+}
+
+/*
+ * We greedily acquire the clipboard after it changes, and on startup.
+ */
+- (void) claim_clipboard
+{
+ Window owner;
+
+ TRACE ();
+
+ if (!pbproxy_prefs.clipboard_to_pasteboard)
+ return;
+
+ owner = XGetSelectionOwner (xpbproxy_dpy, atoms->clipboard);
+ if (None == owner) {
+ /*
+ * The owner probably died or we are just starting up pbproxy.
+ * Set pbproxy's _selection_window as the owner, and continue.
+ */
+ DebugF ("No clipboard owner.\n");
+ [self copy_completed:atoms->clipboard];
+ return;
+ } else if (owner == _selection_window) {
+ [self copy_completed:atoms->clipboard];
+ return;
+ }
+
+ DebugF ("requesting targets\n");
+
+ request_atom = atoms->targets;
+ XConvertSelection (xpbproxy_dpy, atoms->clipboard, atoms->targets,
+ atoms->clipboard, _selection_window, CurrentTime);
+ XFlush (xpbproxy_dpy);
+ /* Now we will get a SelectionNotify event in the future. */
+}
+
+/* Greedily acquire the clipboard. */
+- (void) own_clipboard
+{
+
+ TRACE ();
+
+ /* We should perhaps have a boundary limit on the number of iterations... */
+ do
+ {
+ XSetSelectionOwner (xpbproxy_dpy, atoms->clipboard, _selection_window,
+ CurrentTime);
+ } while (_selection_window != XGetSelectionOwner (xpbproxy_dpy,
+ atoms->clipboard));
+}
+
+- (void) init_reply:(XEvent *)reply request:(XSelectionRequestEvent *)e
+{
+ reply->xselection.type = SelectionNotify;
+ reply->xselection.selection = e->selection;
+ reply->xselection.target = e->target;
+ reply->xselection.requestor = e->requestor;
+ reply->xselection.time = e->time;
+ reply->xselection.property = None;
+}
+
+- (void) send_reply:(XEvent *)reply
+{
+ /*
+ * We are supposed to use an empty event mask, and not propagate
+ * the event, according to the ICCCM.
+ */
+ DebugF ("reply->xselection.requestor 0x%lx\n", reply->xselection.requestor);
+
+ XSendEvent (xpbproxy_dpy, reply->xselection.requestor, False, 0, reply);
+ XFlush (xpbproxy_dpy);
+}
+
+/*
+ * This responds to a TARGETS request.
+ * The result is a list of a ATOMs that correspond to the types available
+ * for a selection.
+ * For instance an application might provide a UTF8_STRING and a STRING
+ * (in Latin-1 encoding). The requestor can then make the choice based on
+ * the list.
+ */
+- (void) send_targets:(XSelectionRequestEvent *)e pasteboard:(NSPasteboard *)pb
+{
+ XEvent reply;
+ NSArray *pbtypes;
+
+ [self init_reply:&reply request:e];
+
+ pbtypes = [pb types];
+ if (pbtypes)
+ {
+ long list[7]; /* Don't forget to increase this if we handle more types! */
+ long count = 0;
+
+ /*
+ * I'm not sure if this is needed, but some toolkits/clients list
+ * TARGETS in response to targets.
+ */
+ list[count] = atoms->targets;
+ ++count;
+
+ if ([pbtypes containsObject:NSStringPboardType])
+ {
+ /* We have a string type that we can convert to UTF8, or Latin-1... */
+ DebugF ("NSStringPboardType\n");
+ list[count] = atoms->utf8_string;
+ ++count;
+ list[count] = atoms->string;
+ ++count;
+ list[count] = atoms->compound_text;
+ ++count;
+ }
+
+ /* TODO add the NSPICTPboardType back again, once we have conversion
+ * functionality in send_image.
+ */
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations" // NSPICTPboardType
+#endif
+
+ if ([pbtypes containsObject:NSPICTPboardType]
+ || [pbtypes containsObject:NSTIFFPboardType])
+ {
+ /* We can convert a TIFF to a PNG or JPEG. */
+ DebugF ("NSTIFFPboardType\n");
+ list[count] = atoms->image_png;
+ ++count;
+ list[count] = atoms->image_jpeg;
+ ++count;
+ }
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
+ if (count)
+ {
+ /* We have a list of ATOMs to send. */
+ XChangeProperty (xpbproxy_dpy, e->requestor, e->property, atoms->atom, 32,
+ PropModeReplace, (unsigned char *) list, count);
+
+ reply.xselection.property = e->property;
+ }
+ }
+
+ [self send_reply:&reply];
+}
+
+
+- (void) send_string:(XSelectionRequestEvent *)e utf8:(BOOL)utf8 pasteboard:(NSPasteboard *)pb
+{
+ XEvent reply;
+ NSArray *pbtypes;
+ NSString *data;
+ const char *bytes;
+ NSUInteger length;
+
+ TRACE ();
+
+ [self init_reply:&reply request:e];
+
+ pbtypes = [pb types];
+
+ if (![pbtypes containsObject:NSStringPboardType])
+ {
+ [self send_reply:&reply];
+ return;
+ }
+
+ DebugF ("pbtypes retainCount after containsObject: %u\n", [pbtypes retainCount]);
+
+ data = [pb stringForType:NSStringPboardType];
+
+ if (nil == data)
+ {
+ [self send_reply:&reply];
+ return;
+ }
+
+ if (utf8)
+ {
+ bytes = [data UTF8String];
+ /*
+ * We don't want the UTF-8 string length here.
+ * We want the length in bytes.
+ */
+ length = strlen (bytes);
+
+ if (length < 50) {
+ DebugF ("UTF-8: %s\n", bytes);
+ DebugF ("UTF-8 length: %u\n", length);
+ }
+ }
+ else
+ {
+ DebugF ("Latin-1\n");
+ bytes = [data cStringUsingEncoding:NSISOLatin1StringEncoding];
+ /*WARNING: bytes is not NUL-terminated. */
+ length = [data lengthOfBytesUsingEncoding:NSISOLatin1StringEncoding];
+ }
+
+ DebugF ("e->target %s\n", XGetAtomName (xpbproxy_dpy, e->target));
+
+ XChangeProperty (xpbproxy_dpy, e->requestor, e->property, e->target,
+ 8, PropModeReplace, (unsigned char *) bytes, length);
+
+ reply.xselection.property = e->property;
+
+ [self send_reply:&reply];
+}
+
+- (void) send_compound_text:(XSelectionRequestEvent *)e pasteboard:(NSPasteboard *)pb
+{
+ XEvent reply;
+ NSArray *pbtypes;
+
+ TRACE ();
+
+ [self init_reply:&reply request:e];
+
+ pbtypes = [pb types];
+
+ if ([pbtypes containsObject: NSStringPboardType])
+ {
+ NSString *data = [pb stringForType:NSStringPboardType];
+ if (nil != data)
+ {
+ /*
+ * Cast to (void *) to avoid a const warning.
+ * AFAIK Xutf8TextListToTextProperty does not modify the input memory.
+ */
+ void *utf8 = (void *)[data UTF8String];
+ char *list[] = { utf8, NULL };
+ XTextProperty textprop;
+
+ textprop.value = NULL;
+
+ if (Success == Xutf8TextListToTextProperty (xpbproxy_dpy, list, 1,
+ XCompoundTextStyle,
+ &textprop))
+ {
+
+ if (8 != textprop.format)
+ DebugF ("textprop.format is unexpectedly not 8 - it's %d instead\n",
+ textprop.format);
+
+ XChangeProperty (xpbproxy_dpy, e->requestor, e->property,
+ atoms->compound_text, textprop.format,
+ PropModeReplace, textprop.value,
+ textprop.nitems);
+
+ reply.xselection.property = e->property;
+ }
+
+ if (textprop.value)
+ XFree (textprop.value);
+
+ }
+ }
+
+ [self send_reply:&reply];
+}
+
+/* Finding a test application that uses MULTIPLE has proven to be difficult. */
+- (void) send_multiple:(XSelectionRequestEvent *)e
+{
+ XEvent reply;
+
+ TRACE ();
+
+ [self init_reply:&reply request:e];
+
+ if (None != e->property)
+ {
+
+ }
+
+ [self send_reply:&reply];
+}
+
+/* Return nil if an error occured. */
+/* DO NOT retain the encdata for longer than the length of an event response.
+ * The autorelease pool will reuse/free it.
+ */
+- (NSData *) encode_image_data:(NSData *)data type:(NSBitmapImageFileType)enctype
+{
+ NSBitmapImageRep *bmimage = nil;
+ NSData *encdata = nil;
+ NSDictionary *dict = nil;
+
+ bmimage = [[NSBitmapImageRep alloc] initWithData:data];
+
+ if (nil == bmimage)
+ return nil;
+
+ dict = [[NSDictionary alloc] init];
+ encdata = [bmimage representationUsingType:enctype properties:dict];
+
+ if (nil == encdata)
+ {
+ [dict autorelease];
+ [bmimage autorelease];
+ return nil;
+ }
+
+ [dict autorelease];
+ [bmimage autorelease];
+
+ return encdata;
+}
+
+/* Return YES when an error has occured when trying to send the PICT. */
+/* The caller should send a default reponse with a property of None when an error occurs. */
+- (BOOL) send_image_pict_reply:(XSelectionRequestEvent *)e
+ pasteboard:(NSPasteboard *)pb
+ type:(NSBitmapImageFileType)imagetype
+{
+ XEvent reply;
+ NSImage *img = nil;
+ NSData *data = nil, *encdata = nil;
+ NSUInteger length;
+ const void *bytes = NULL;
+
+ img = [[NSImage alloc] initWithPasteboard:pb];
+
+ if (nil == img)
+ {
+ return YES;
+ }
+
+ data = [img TIFFRepresentation];
+
+ if (nil == data)
+ {
+ [img autorelease];
+ ErrorF("unable to convert PICT to TIFF!\n");
+ return YES;
+ }
+
+ encdata = [self encode_image_data:data type:imagetype];
+ if(nil == encdata)
+ {
+ [img autorelease];
+ return YES;
+ }
+
+ [self init_reply:&reply request:e];
+
+ length = [encdata length];
+ bytes = [encdata bytes];
+
+ XChangeProperty (xpbproxy_dpy, e->requestor, e->property, e->target,
+ 8, PropModeReplace, bytes, length);
+ reply.xselection.property = e->property;
+
+ [self send_reply:&reply];
+
+ [img autorelease];
+
+ return NO; /*no error*/
+}
+
+/* Return YES if an error occured. */
+/* The caller should send a reply with a property of None when an error occurs. */
+- (BOOL) send_image_tiff_reply:(XSelectionRequestEvent *)e
+ pasteboard:(NSPasteboard *)pb
+ type:(NSBitmapImageFileType)imagetype
+{
+ XEvent reply;
+ NSData *data = nil;
+ NSData *encdata = nil;
+ NSUInteger length;
+ const void *bytes = NULL;
+
+ data = [pb dataForType:NSTIFFPboardType];
+
+ if (nil == data)
+ return YES;
+
+ encdata = [self encode_image_data:data type:imagetype];
+
+ if(nil == encdata)
+ return YES;
+
+ [self init_reply:&reply request:e];
+
+ length = [encdata length];
+ bytes = [encdata bytes];
+
+ XChangeProperty (xpbproxy_dpy, e->requestor, e->property, e->target,
+ 8, PropModeReplace, bytes, length);
+ reply.xselection.property = e->property;
+
+ [self send_reply:&reply];
+
+ return NO; /*no error*/
+}
+
+- (void) send_image:(XSelectionRequestEvent *)e pasteboard:(NSPasteboard *)pb
+{
+ NSArray *pbtypes = nil;
+ NSBitmapImageFileType imagetype = NSPNGFileType;
+
+ TRACE ();
+
+ if (e->target == atoms->image_png)
+ imagetype = NSPNGFileType;
+ else if (e->target == atoms->image_jpeg)
+ imagetype = NSJPEGFileType;
+ else
+ {
+ ErrorF("internal failure in xpbproxy! imagetype being sent isn't PNG or JPEG.\n");
+ }
+
+ pbtypes = [pb types];
+
+ if (pbtypes)
+ {
+ if ([pbtypes containsObject:NSTIFFPboardType])
+ {
+ if (NO == [self send_image_tiff_reply:e pasteboard:pb type:imagetype])
+ return;
+ }
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations" // NSPICTPboardType
+#endif
+ else if ([pbtypes containsObject:NSPICTPboardType])
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+ {
+ if (NO == [self send_image_pict_reply:e pasteboard:pb type:imagetype])
+ return;
+
+ /* Fall through intentionally to the send_none: */
+ }
+ }
+
+ [self send_none:e];
+}
+
+- (void)send_none:(XSelectionRequestEvent *)e
+{
+ XEvent reply;
+
+ TRACE ();
+
+ [self init_reply:&reply request:e];
+ [self send_reply:&reply];
+}
+
+
+/* Another client requested the data or targets of data available from the clipboard. */
+- (void)request_event:(XSelectionRequestEvent *)e
+{
+ NSPasteboard *pb;
+
+ TRACE ();
+
+ /* TODO We should also keep track of the time of the selection, and
+ * according to the ICCCM "refuse the request" if the event timestamp
+ * is before we owned it.
+ * What should we base the time on? How can we get the current time just
+ * before an XSetSelectionOwner? Is it the server's time, or the clients?
+ * According to the XSelectionRequestEvent manual page, the Time value
+ * may be set to CurrentTime or a time, so that makes it a bit different.
+ * Perhaps we should just punt and ignore races.
+ */
+
+ /*TODO we need a COMPOUND_TEXT test app*/
+ /*TODO we need a MULTIPLE test app*/
+
+ pb = [NSPasteboard generalPasteboard];
+ if (nil == pb)
+ {
+ [self send_none:e];
+ return;
+ }
+
+
+ if (None != e->target)
+ DebugF ("e->target %s\n", XGetAtomName (xpbproxy_dpy, e->target));
+
+ if (e->target == atoms->targets)
+ {
+ /* The paste requestor wants to know what TARGETS we support. */
+ [self send_targets:e pasteboard:pb];
+ }
+ else if (e->target == atoms->multiple)
+ {
+ /*
+ * This isn't finished, and may never be, unless I can find
+ * a good test app.
+ */
+ [self send_multiple:e];
+ }
+ else if (e->target == atoms->utf8_string)
+ {
+ [self send_string:e utf8:YES pasteboard:pb];
+ }
+ else if (e->target == atoms->string)
+ {
+ [self send_string:e utf8:NO pasteboard:pb];
+ }
+ else if (e->target == atoms->compound_text)
+ {
+ [self send_compound_text:e pasteboard:pb];
+ }
+ else if (e->target == atoms->multiple)
+ {
+ [self send_multiple:e];
+ }
+ else if (e->target == atoms->image_png || e->target == atoms->image_jpeg)
+ {
+ [self send_image:e pasteboard:pb];
+ }
+ else
+ {
+ [self send_none:e];
+ }
+}
+
+/* This handles the events resulting from an XConvertSelection request. */
+- (void) notify_event:(XSelectionEvent *)e
+{
+ Atom type;
+ struct propdata pdata;
+
+ TRACE ();
+
+ [self release_pending];
+
+ if (None == e->property) {
+ DebugF ("e->property is None.\n");
+ [self copy_completed:e->selection];
+ /* Nothing is selected. */
+ return;
+ }
+
+#if 0
+ ErrorF("e->selection %s\n", XGetAtomName (xpbproxy_dpy, e->selection));
+ ErrorF("e->property %s\n", XGetAtomName (xpbproxy_dpy, e->property));
+#endif
+
+ if ([self is_incr_type:e])
+ {
+ /*
+ * This is an INCR-style transfer, which means that we
+ * will get the data after a series of PropertyNotify events.
+ */
+ DebugF ("is INCR\n");
+
+ if (get_property (e->requestor, e->property, &pdata, /*Delete*/ True, &type))
+ {
+ /*
+ * An error occured, so we should invoke the copy_completed:, but
+ * not handle_selection:type:propdata:
+ */
+ [self copy_completed:e->selection];
+ return;
+ }
+
+ free_propdata (&pdata);
+
+ pending.requestor = e->requestor;
+ pending.selection = e->selection;
+
+ DebugF ("set pending.requestor to 0x%lx\n", pending.requestor);
+ }
+ else
+ {
+ if (get_property (e->requestor, e->property, &pdata, /*Delete*/ True, &type))
+ {
+ [self copy_completed:e->selection];
+ return;
+ }
+
+ /* We have the complete selection data.*/
+ [self handle_selection:e->selection type:type propdata:&pdata];
+
+ DebugF ("handled selection with the first notify_event\n");
+ }
+}
+
+/* This is used for INCR transfers. See the ICCCM for the details. */
+/* This is used to retrieve PRIMARY and CLIPBOARD selections. */
+- (void) property_event:(XPropertyEvent *)e
+{
+ struct propdata pdata;
+ Atom type;
+
+ TRACE ();
+
+ if (None != e->atom)
+ {
+#ifdef DEBUG
+ char *name = XGetAtomName (xpbproxy_dpy, e->atom);
+
+ if (name)
+ {
+ DebugF ("e->atom %s\n", name);
+ XFree(name);
+ }
+#endif
+ }
+
+ if (None != pending.requestor && PropertyNewValue == e->state)
+ {
+ DebugF ("pending.requestor 0x%lx\n", pending.requestor);
+
+ if (get_property (e->window, e->atom, &pdata, /*Delete*/ True, &type))
+ {
+ [self copy_completed:pending.selection];
+ [self release_pending];
+ return;
+ }
+
+ if (0 == pdata.length)
+ {
+ /*
+ * We completed the transfer.
+ * handle_selection will call copy_completed: for us.
+ */
+ [self handle_selection:pending.selection type:type propdata:&pending.propdata];
+ free_propdata(&pdata);
+ pending.propdata = null_propdata;
+ pending.requestor = None;
+ pending.selection = None;
+ }
+ else
+ {
+ [self append_to_pending:&pdata requestor:e->window];
+ free_propdata (&pdata);
+ }
+ }
+}
+
+- (void) xfixes_selection_notify:(XFixesSelectionNotifyEvent *)e {
+ if(!pbproxy_prefs.active)
+ return;
+
+ switch(e->subtype) {
+ case XFixesSetSelectionOwnerNotify:
+ if(e->selection == atoms->primary && pbproxy_prefs.primary_on_grab)
+ [self x_copy:e->timestamp];
+ break;
+
+ case XFixesSelectionWindowDestroyNotify:
+ case XFixesSelectionClientCloseNotify:
+ default:
+ ErrorF("Unhandled XFixesSelectionNotifyEvent: subtype=%d\n", e->subtype);
+ break;
+ }
+}
+
+- (void) handle_targets: (Atom)selection propdata:(struct propdata *)pdata
+{
+ /* Find a type we can handle and prefer from the list of ATOMs. */
+ Atom preferred;
+ char *name;
+
+ TRACE ();
+
+ preferred = [self find_preferred:pdata];
+
+ if (None == preferred)
+ {
+ /*
+ * This isn't required by the ICCCM, but some apps apparently
+ * don't respond to TARGETS properly.
+ */
+ preferred = atoms->string;
+ }
+
+ (void)name; /* Avoid a warning with non-debug compiles. */
+#ifdef DEBUG
+ name = XGetAtomName (xpbproxy_dpy, preferred);
+
+ if (name)
+ {
+ DebugF ("requesting %s\n", name);
+ }
+#endif
+ request_atom = preferred;
+ XConvertSelection (xpbproxy_dpy, selection, preferred, selection,
+ _selection_window, CurrentTime);
+}
+
+/* This handles the image type of selection (typically in CLIPBOARD). */
+/* We convert to a TIFF, so that other applications can paste more easily. */
+- (void) handle_image: (struct propdata *)pdata pasteboard:(NSPasteboard *)pb
+{
+ NSArray *pbtypes;
+ NSUInteger length;
+ NSData *data, *tiff;
+ NSBitmapImageRep *bmimage;
+
+ TRACE ();
+
+ length = pdata->length;
+ data = [[NSData alloc] initWithBytes:pdata->data length:length];
+
+ if (nil == data)
+ {
+ DebugF ("unable to create NSData object!\n");
+ return;
+ }
+
+ DebugF ("data retainCount before NSBitmapImageRep initWithData: %u\n",
+ [data retainCount]);
+
+ bmimage = [[NSBitmapImageRep alloc] initWithData:data];
+
+ if (nil == bmimage)
+ {
+ [data autorelease];
+ DebugF ("unable to create NSBitmapImageRep!\n");
+ return;
+ }
+
+ DebugF ("data retainCount after NSBitmapImageRep initWithData: %u\n",
+ [data retainCount]);
+
+ @try
+ {
+ tiff = [bmimage TIFFRepresentation];
+ }
+
+ @catch (NSException *e)
+ {
+ DebugF ("NSTIFFException!\n");
+ [data autorelease];
+ [bmimage autorelease];
+ return;
+ }
+
+ DebugF ("bmimage retainCount after TIFFRepresentation %u\n", [bmimage retainCount]);
+
+ pbtypes = [NSArray arrayWithObjects:NSTIFFPboardType, nil];
+
+ if (nil == pbtypes)
+ {
+ [data autorelease];
+ [bmimage autorelease];
+ return;
+ }
+
+ [pb declareTypes:pbtypes owner:nil];
+ if (YES != [pb setData:tiff forType:NSTIFFPboardType])
+ {
+ DebugF ("writing pasteboard data failed!\n");
+ }
+
+ [data autorelease];
+
+ DebugF ("bmimage retainCount before release %u\n", [bmimage retainCount]);
+ [bmimage autorelease];
+}
+
+/* This handles the UTF8_STRING type of selection. */
+- (void) handle_utf8_string:(struct propdata *)pdata pasteboard:(NSPasteboard *)pb
+{
+ NSString *string;
+ NSArray *pbtypes;
+
+ TRACE ();
+
+ string = [[NSString alloc] initWithBytes:pdata->data length:pdata->length encoding:NSUTF8StringEncoding];
+
+ if (nil == string)
+ return;
+
+ pbtypes = [NSArray arrayWithObjects:NSStringPboardType, nil];
+
+ if (nil == pbtypes)
+ {
+ [string autorelease];
+ return;
+ }
+
+ [pb declareTypes:pbtypes owner:nil];
+
+ if (YES != [pb setString:string forType:NSStringPboardType]) {
+ ErrorF("pasteboard setString:forType: failed!\n");
+ }
+ [string autorelease];
+ DebugF ("done handling utf8 string\n");
+}
+
+/* This handles the STRING type, which should be in Latin-1. */
+- (void) handle_string: (struct propdata *)pdata pasteboard:(NSPasteboard *)pb
+{
+ NSString *string;
+ NSArray *pbtypes;
+
+ TRACE ();
+
+ string = [[NSString alloc] initWithBytes:pdata->data length:pdata->length encoding:NSISOLatin1StringEncoding];
+
+ if (nil == string)
+ return;
+
+ pbtypes = [NSArray arrayWithObjects:NSStringPboardType, nil];
+
+ if (nil == pbtypes)
+ {
+ [string autorelease];
+ return;
+ }
+
+ [pb declareTypes:pbtypes owner:nil];
+ if (YES != [pb setString:string forType:NSStringPboardType]) {
+ ErrorF("pasteboard setString:forType failed in handle_string!\n");
+ }
+ [string autorelease];
+}
+
+/* This is called when the selection is completely retrieved from another client. */
+/* Warning: this frees the propdata. */
+- (void) handle_selection:(Atom)selection type:(Atom)type propdata:(struct propdata *)pdata
+{
+ NSPasteboard *pb;
+
+ TRACE ();
+
+ pb = [NSPasteboard generalPasteboard];
+
+ if (nil == pb)
+ {
+ [self copy_completed:selection];
+ free_propdata (pdata);
+ return;
+ }
+
+ /*
+ * Some apps it seems set the type to TARGETS instead of ATOM, such as Eterm.
+ * These aren't ICCCM compliant apps, but we need these to work...
+ */
+ if (request_atom == atoms->targets
+ && (type == atoms->atom || type == atoms->targets))
+ {
+ [self handle_targets:selection propdata:pdata];
+ free_propdata(pdata);
+ return;
+ }
+ else if (type == atoms->image_png)
+ {
+ [self handle_image:pdata pasteboard:pb];
+ }
+ else if (type == atoms->image_jpeg)
+ {
+ [self handle_image:pdata pasteboard:pb];
+ }
+ else if (type == atoms->utf8_string)
+ {
+ [self handle_utf8_string:pdata pasteboard:pb];
+ }
+ else if (type == atoms->string)
+ {
+ [self handle_string:pdata pasteboard:pb];
+ }
+
+ free_propdata(pdata);
+
+ [self copy_completed:selection];
+}
+
+
+- (void) copy_completed:(Atom)selection
+{
+ TRACE ();
+ char *name;
+
+ (void)name; /* Avoid warning with non-debug compiles. */
+#ifdef DEBUG
+ name = XGetAtomName (xpbproxy_dpy, selection);
+ if (name)
+ {
+ DebugF ("copy_completed: %s\n", name);
+ XFree (name);
+ }
+#endif
+
+ if (selection == atoms->primary && pending_copy > 0)
+ {
+ --pending_copy;
+ if (pending_copy > 0)
+ {
+ /* Copy PRIMARY again. */
+ [self x_copy_request_targets];
+ return;
+ }
+ }
+ else if (selection == atoms->clipboard && pending_clipboard > 0)
+ {
+ --pending_clipboard;
+ if (pending_clipboard > 0)
+ {
+ /* Copy CLIPBOARD. */
+ [self claim_clipboard];
+ return;
+ }
+ else
+ {
+ /* We got the final data. Now set pbproxy as the owner. */
+ [self own_clipboard];
+ return;
+ }
+ }
+
+ /*
+ * We had 1 or more primary in progress, and the clipboard arrived
+ * while we were busy.
+ */
+ if (pending_clipboard > 0)
+ {
+ [self claim_clipboard];
+ }
+}
+
+- (void) reload_preferences
+{
+ /*
+ * It's uncertain how we could handle the synchronization failing, so cast to void.
+ * The prefs_get_bool should fall back to defaults if the org.x.X11 plist doesn't exist or is invalid.
+ */
+ (void)CFPreferencesAppSynchronize(app_prefs_domain_cfstr);
+#ifdef STANDALONE_XPBPROXY
+ if(xpbproxy_is_standalone)
+ pbproxy_prefs.active = YES;
+ else
+#endif
+ pbproxy_prefs.active = prefs_get_bool(CFSTR("sync_pasteboard"), pbproxy_prefs.active);
+ pbproxy_prefs.primary_on_grab = prefs_get_bool(CFSTR("sync_primary_on_select"), pbproxy_prefs.primary_on_grab);
+ pbproxy_prefs.clipboard_to_pasteboard = prefs_get_bool(CFSTR("sync_clipboard_to_pasteboard"), pbproxy_prefs.clipboard_to_pasteboard);
+ pbproxy_prefs.pasteboard_to_primary = prefs_get_bool(CFSTR("sync_pasteboard_to_primary"), pbproxy_prefs.pasteboard_to_primary);
+ pbproxy_prefs.pasteboard_to_clipboard = prefs_get_bool(CFSTR("sync_pasteboard_to_clipboard"), pbproxy_prefs.pasteboard_to_clipboard);
+
+ /* This is used for debugging. */
+ //dump_prefs();
+
+ if(pbproxy_prefs.active && pbproxy_prefs.primary_on_grab && !xpbproxy_have_xfixes) {
+ ErrorF("Disabling sync_primary_on_select functionality due to missing XFixes extension.\n");
+ pbproxy_prefs.primary_on_grab = NO;
+ }
+
+ /* Claim or release the CLIPBOARD_MANAGER atom */
+ if(![self set_clipboard_manager_status:(pbproxy_prefs.active && pbproxy_prefs.clipboard_to_pasteboard)])
+ pbproxy_prefs.clipboard_to_pasteboard = NO;
+
+ if(pbproxy_prefs.active && pbproxy_prefs.clipboard_to_pasteboard)
+ [self claim_clipboard];
+}
+
+- (BOOL) is_active
+{
+ return pbproxy_prefs.active;
+}
+
+/* NSPasteboard-required methods */
+
+- (void) paste:(id)sender
+{
+ TRACE ();
+}
+
+- (void) pasteboard:(NSPasteboard *)pb provideDataForType:(NSString *)type
+{
+ TRACE ();
+}
+
+- (void) pasteboardChangedOwner:(NSPasteboard *)pb
+{
+ TRACE ();
+
+ /* Right now we don't care with this. */
+}
+
+/* Allocation */
+
+- init
+{
+ unsigned long pixel;
+
+ self = [super init];
+ if (self == nil)
+ return nil;
+
+ atoms->primary = XInternAtom (xpbproxy_dpy, "PRIMARY", False);
+ atoms->clipboard = XInternAtom (xpbproxy_dpy, "CLIPBOARD", False);
+ atoms->text = XInternAtom (xpbproxy_dpy, "TEXT", False);
+ atoms->utf8_string = XInternAtom (xpbproxy_dpy, "UTF8_STRING", False);
+ atoms->string = XInternAtom (xpbproxy_dpy, "STRING", False);
+ atoms->targets = XInternAtom (xpbproxy_dpy, "TARGETS", False);
+ atoms->multiple = XInternAtom (xpbproxy_dpy, "MULTIPLE", False);
+ atoms->cstring = XInternAtom (xpbproxy_dpy, "CSTRING", False);
+ atoms->image_png = XInternAtom (xpbproxy_dpy, "image/png", False);
+ atoms->image_jpeg = XInternAtom (xpbproxy_dpy, "image/jpeg", False);
+ atoms->incr = XInternAtom (xpbproxy_dpy, "INCR", False);
+ atoms->atom = XInternAtom (xpbproxy_dpy, "ATOM", False);
+ atoms->clipboard_manager = XInternAtom (xpbproxy_dpy, "CLIPBOARD_MANAGER", False);
+ atoms->compound_text = XInternAtom (xpbproxy_dpy, "COMPOUND_TEXT", False);
+ atoms->atom_pair = XInternAtom (xpbproxy_dpy, "ATOM_PAIR", False);
+
+ pixel = BlackPixel (xpbproxy_dpy, DefaultScreen (xpbproxy_dpy));
+ _selection_window = XCreateSimpleWindow (xpbproxy_dpy, DefaultRootWindow (xpbproxy_dpy),
+ 0, 0, 1, 1, 0, pixel, pixel);
+
+ /* This is used to get PropertyNotify events when doing INCR transfers. */
+ XSelectInput (xpbproxy_dpy, _selection_window, PropertyChangeMask);
+
+ request_atom = None;
+
+ init_propdata (&pending.propdata);
+ pending.requestor = None;
+ pending.selection = None;
+
+ pending_copy = 0;
+ pending_clipboard = 0;
+
+ if(xpbproxy_have_xfixes)
+ XFixesSelectSelectionInput(xpbproxy_dpy, _selection_window, atoms->primary,
+ XFixesSetSelectionOwnerNotifyMask);
+
+ [self reload_preferences];
+
+ return self;
+}
+
+- (void) dealloc
+{
+ if (None != _selection_window)
+ {
+ XDestroyWindow (xpbproxy_dpy, _selection_window);
+ _selection_window = None;
+ }
+
+ free_propdata (&pending.propdata);
+
+ [super dealloc];
+}
+
+@end
diff --git a/xorg-server/hw/xquartz/quartz.c b/xorg-server/hw/xquartz/quartz.c index 158656b6a..4fdf40c89 100644 --- a/xorg-server/hw/xquartz/quartz.c +++ b/xorg-server/hw/xquartz/quartz.c @@ -62,7 +62,7 @@ #include <sys/stat.h>
#include <fcntl.h>
#include <IOKit/pwr_mgt/IOPMLib.h>
-#include <pthread.h>
+#include <libkern/OSAtomic.h>
#include <signal.h>
#include <rootlessCommon.h>
@@ -279,10 +279,10 @@ static void pokeActivityCallback(CFRunLoopTimerRef timer, void *info) { static void QuartzScreenSaver(int state) {
static CFRunLoopTimerRef pokeActivityTimer = NULL;
static CFRunLoopTimerContext pokeActivityContext = { 0, NULL, NULL, NULL, NULL };
- static pthread_mutex_t pokeActivityMutex = PTHREAD_MUTEX_INITIALIZER;
+ static OSSpinLock pokeActivitySpinLock = OS_SPINLOCK_INIT;
+
+ OSSpinLockLock(&pokeActivitySpinLock);
- pthread_mutex_lock(&pokeActivityMutex);
-
if(state) {
if(pokeActivityTimer == NULL)
goto QuartzScreenSaverEnd;
@@ -303,7 +303,7 @@ static void QuartzScreenSaver(int state) { CFRunLoopAddTimer(CFRunLoopGetMain(), pokeActivityTimer, kCFRunLoopCommonModes);
}
QuartzScreenSaverEnd:
- pthread_mutex_unlock(&pokeActivityMutex);
+ OSSpinLockUnlock(&pokeActivitySpinLock);
}
void QuartzShowFullscreen(int state) {
diff --git a/xorg-server/hw/xquartz/quartz.h b/xorg-server/hw/xquartz/quartz.h index d520c1dcb..7fa6d431c 100644 --- a/xorg-server/hw/xquartz/quartz.h +++ b/xorg-server/hw/xquartz/quartz.h @@ -70,7 +70,7 @@ typedef void (*UpdateScreenProc)(ScreenPtr pScreen); /*
* Rootless helper functions
*/
-typedef Bool (*IsX11WindowProc)(void *nsWindow, int windowNumber);
+typedef Bool (*IsX11WindowProc)(int windowNumber);
typedef void (*HideWindowsProc)(Bool hide);
/*
diff --git a/xorg-server/hw/xquartz/quartzKeyboard.c b/xorg-server/hw/xquartz/quartzKeyboard.c index 54f709a8b..368b8a66f 100644 --- a/xorg-server/hw/xquartz/quartzKeyboard.c +++ b/xorg-server/hw/xquartz/quartzKeyboard.c @@ -1,857 +1,874 @@ -/* - quartzKeyboard.c: Keyboard support for Xquartz - - Copyright (c) 2003-2008 Apple Inc. - Copyright (c) 2001-2004 Torrey T. Lyons. All Rights Reserved. - Copyright 2004 Kaleb S. KEITHLEY. All Rights Reserved. - - Copyright (C) 1999,2000 by Eric Sunshine <sunshine@sunshineco.com> - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include "sanitizedCarbon.h" - -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> -#endif - -#define HACK_MISSING 1 -#define HACK_KEYPAD 1 -#define HACK_BLACKLIST 1 - -#include <unistd.h> -#include <stdio.h> -#include <stdlib.h> -#include <errno.h> -#include <sys/stat.h> -#include <AvailabilityMacros.h> - -#include "quartz.h" -#include "darwin.h" -#include "darwinEvents.h" - -#include "quartzKeyboard.h" - -#include "X11Application.h" - -#include "threadSafety.h" - -#ifdef NDEBUG -#undef NDEBUG -#include <assert.h> -#define NDEBUG 1 -#else -#include <assert.h> -#endif -#include <pthread.h> - -#include "xkbsrv.h" -#include "exevents.h" -#include "X11/keysym.h" -#include "keysym2ucs.h" - -extern void -CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master); - -enum { - MOD_COMMAND = 256, - MOD_SHIFT = 512, - MOD_OPTION = 2048, - MOD_CONTROL = 4096, -}; - -#define UKEYSYM(u) ((u) | 0x01000000) - -#if HACK_MISSING -/* Table of keycode->keysym mappings we use to fallback on for important - keys that are often not in the Unicode mapping. */ - -const static struct { - unsigned short keycode; - KeySym keysym; -} known_keys[] = { - {55, XK_Meta_L}, - {56, XK_Shift_L}, - {57, XK_Caps_Lock}, - {58, XK_Alt_L}, - {59, XK_Control_L}, - - {60, XK_Shift_R}, - {61, XK_Alt_R}, - {62, XK_Control_R}, - {63, XK_Meta_R}, - - {122, XK_F1}, - {120, XK_F2}, - {99, XK_F3}, - {118, XK_F4}, - {96, XK_F5}, - {97, XK_F6}, - {98, XK_F7}, - {100, XK_F8}, - {101, XK_F9}, - {109, XK_F10}, - {103, XK_F11}, - {111, XK_F12}, - {105, XK_F13}, - {107, XK_F14}, - {113, XK_F15}, -}; -#endif - -#if HACK_KEYPAD -/* Table of keycode->old,new-keysym mappings we use to fixup the numeric - keypad entries. */ - -const static struct { - unsigned short keycode; - KeySym normal, keypad; -} known_numeric_keys[] = { - {65, XK_period, XK_KP_Decimal}, - {67, XK_asterisk, XK_KP_Multiply}, - {69, XK_plus, XK_KP_Add}, - {75, XK_slash, XK_KP_Divide}, - {76, 0x01000003, XK_KP_Enter}, - {78, XK_minus, XK_KP_Subtract}, - {81, XK_equal, XK_KP_Equal}, - {82, XK_0, XK_KP_0}, - {83, XK_1, XK_KP_1}, - {84, XK_2, XK_KP_2}, - {85, XK_3, XK_KP_3}, - {86, XK_4, XK_KP_4}, - {87, XK_5, XK_KP_5}, - {88, XK_6, XK_KP_6}, - {89, XK_7, XK_KP_7}, - {91, XK_8, XK_KP_8}, - {92, XK_9, XK_KP_9}, -}; -#endif - -#if HACK_BLACKLIST -/* <rdar://problem/7824370> wine notepad produces wrong characters on shift+arrow - * http://xquartz.macosforge.org/trac/ticket/295 - * http://developer.apple.com/legacy/mac/library/documentation/mac/Text/Text-579.html - * - * legacy Mac keycodes for arrow keys that shift-modify to math symbols - */ -const static unsigned short keycode_blacklist[] = {66, 70, 72, 77}; -#endif - -/* Table mapping normal keysyms to their dead equivalents. - FIXME: all the unicode keysyms (apart from circumflex) were guessed. */ - -const static struct { - KeySym normal, dead; -} dead_keys[] = { - {XK_grave, XK_dead_grave}, - {XK_apostrophe, XK_dead_acute}, /* US:"=" on a Czech keyboard */ - {XK_acute, XK_dead_acute}, - {UKEYSYM (0x384), XK_dead_acute}, /* US:";" on a Greek keyboard */ -// {XK_Greek_accentdieresis, XK_dead_diaeresis}, /* US:"opt+;" on a Greek keyboard ... replace with dead_accentdieresis if there is one */ - {XK_asciicircum, XK_dead_circumflex}, - {UKEYSYM (0x2c6), XK_dead_circumflex}, /* MODIFIER LETTER CIRCUMFLEX ACCENT */ - {XK_asciitilde, XK_dead_tilde}, - {UKEYSYM (0x2dc), XK_dead_tilde}, /* SMALL TILDE */ - {XK_macron, XK_dead_macron}, - {XK_breve, XK_dead_breve}, - {XK_abovedot, XK_dead_abovedot}, - {XK_diaeresis, XK_dead_diaeresis}, - {UKEYSYM (0x2da), XK_dead_abovering}, /* DOT ABOVE */ - {XK_doubleacute, XK_dead_doubleacute}, - {XK_caron, XK_dead_caron}, - {XK_cedilla, XK_dead_cedilla}, - {XK_ogonek, XK_dead_ogonek}, - {UKEYSYM (0x269), XK_dead_iota}, /* LATIN SMALL LETTER IOTA */ - {UKEYSYM (0x2ec), XK_dead_voiced_sound}, /* MODIFIER LETTER VOICING */ -/* {XK_semivoiced_sound, XK_dead_semivoiced_sound}, */ - {UKEYSYM (0x323), XK_dead_belowdot}, /* COMBINING DOT BELOW */ - {UKEYSYM (0x309), XK_dead_hook}, /* COMBINING HOOK ABOVE */ - {UKEYSYM (0x31b), XK_dead_horn}, /* COMBINING HORN */ -}; - -typedef struct darwinKeyboardInfo_struct { - CARD8 modMap[MAP_LENGTH]; - KeySym keyMap[MAP_LENGTH * GLYPHS_PER_KEY]; - unsigned char modifierKeycodes[32][2]; -} darwinKeyboardInfo; - -darwinKeyboardInfo keyInfo; -pthread_mutex_t keyInfo_mutex = PTHREAD_MUTEX_INITIALIZER; - -static void DarwinChangeKeyboardControl(DeviceIntPtr device, KeybdCtrl *ctrl) { - // FIXME: to be implemented - // keyclick, bell volume / pitch, autorepead, LED's -} - -//----------------------------------------------------------------------------- -// Utility functions to help parse Darwin keymap -//----------------------------------------------------------------------------- - -/* - * DarwinBuildModifierMaps - * Use the keyMap field of keyboard info structure to populate - * the modMap and modifierKeycodes fields. - */ -static void DarwinBuildModifierMaps(darwinKeyboardInfo *info) { - int i; - KeySym *k; - - memset(info->modMap, NoSymbol, sizeof(info->modMap)); - memset(info->modifierKeycodes, 0, sizeof(info->modifierKeycodes)); - - for (i = 0; i < NUM_KEYCODES; i++) { - k = info->keyMap + i * GLYPHS_PER_KEY; - - switch (*k) { - case XK_Shift_L: - info->modifierKeycodes[NX_MODIFIERKEY_SHIFT][0] = i; - info->modMap[MIN_KEYCODE + i] = ShiftMask; - break; - - case XK_Shift_R: -#ifdef NX_MODIFIERKEY_RSHIFT - info->modifierKeycodes[NX_MODIFIERKEY_RSHIFT][0] = i; -#else - info->modifierKeycodes[NX_MODIFIERKEY_SHIFT][0] = i; -#endif - info->modMap[MIN_KEYCODE + i] = ShiftMask; - break; - - case XK_Control_L: - info->modifierKeycodes[NX_MODIFIERKEY_CONTROL][0] = i; - info->modMap[MIN_KEYCODE + i] = ControlMask; - break; - - case XK_Control_R: -#ifdef NX_MODIFIERKEY_RCONTROL - info->modifierKeycodes[NX_MODIFIERKEY_RCONTROL][0] = i; -#else - info->modifierKeycodes[NX_MODIFIERKEY_CONTROL][0] = i; -#endif - info->modMap[MIN_KEYCODE + i] = ControlMask; - break; - - case XK_Caps_Lock: - info->modifierKeycodes[NX_MODIFIERKEY_ALPHALOCK][0] = i; - info->modMap[MIN_KEYCODE + i] = LockMask; - break; - - case XK_Alt_L: - info->modifierKeycodes[NX_MODIFIERKEY_ALTERNATE][0] = i; - info->modMap[MIN_KEYCODE + i] = Mod1Mask; - if(!XQuartzOptionSendsAlt) - *k = XK_Mode_switch; // Yes, this is ugly. This needs to be cleaned up when we integrate quartzKeyboard with this code and refactor. - break; - - case XK_Alt_R: -#ifdef NX_MODIFIERKEY_RALTERNATE - info->modifierKeycodes[NX_MODIFIERKEY_RALTERNATE][0] = i; -#else - info->modifierKeycodes[NX_MODIFIERKEY_ALTERNATE][0] = i; -#endif - if(!XQuartzOptionSendsAlt) - *k = XK_Mode_switch; // Yes, this is ugly. This needs to be cleaned up when we integrate quartzKeyboard with this code and refactor. - info->modMap[MIN_KEYCODE + i] = Mod1Mask; - break; - - case XK_Mode_switch: - ErrorF("DarwinBuildModifierMaps: XK_Mode_switch encountered, unable to determine side.\n"); - info->modifierKeycodes[NX_MODIFIERKEY_ALTERNATE][0] = i; -#ifdef NX_MODIFIERKEY_RALTERNATE - info->modifierKeycodes[NX_MODIFIERKEY_RALTERNATE][0] = i; -#endif - info->modMap[MIN_KEYCODE + i] = Mod1Mask; - break; - - case XK_Meta_L: - info->modifierKeycodes[NX_MODIFIERKEY_COMMAND][0] = i; - info->modMap[MIN_KEYCODE + i] = Mod2Mask; - break; - - case XK_Meta_R: -#ifdef NX_MODIFIERKEY_RCOMMAND - info->modifierKeycodes[NX_MODIFIERKEY_RCOMMAND][0] = i; -#else - info->modifierKeycodes[NX_MODIFIERKEY_COMMAND][0] = i; -#endif - info->modMap[MIN_KEYCODE + i] = Mod2Mask; - break; - - case XK_Num_Lock: - info->modMap[MIN_KEYCODE + i] = Mod3Mask; - break; - } - } -} - -/* - * DarwinKeyboardInit - * Get the Darwin keyboard map and compute an equivalent - * X keyboard map and modifier map. Set the new keyboard - * device structure. - */ -void DarwinKeyboardInit(DeviceIntPtr pDev) { - // Open a shared connection to the HID System. - // Note that the Event Status Driver is really just a wrapper - // for a kIOHIDParamConnectType connection. - assert(darwinParamConnect = NXOpenEventStatus()); - - InitKeyboardDeviceStruct(pDev, NULL, NULL, DarwinChangeKeyboardControl); - - DarwinKeyboardReloadHandler(); - - CopyKeyClass(pDev, inputInfo.keyboard); -} - -/* Set the repeat rates based on global preferences and keycodes for modifiers. - * Precondition: Has the keyInfo_mutex lock. - */ -static void DarwinKeyboardSetRepeat(DeviceIntPtr pDev, int initialKeyRepeatValue, int keyRepeatValue) { - if(initialKeyRepeatValue == 300000) { // off - /* Turn off repeats globally */ - XkbSetRepeatKeys(pDev, -1, AutoRepeatModeOff); - } else { - int i; - XkbControlsPtr ctrl; - XkbControlsRec old; - - /* Turn on repeats globally */ - XkbSetRepeatKeys(pDev, -1, AutoRepeatModeOn); - - /* Setup the bit mask for individual key repeats */ - ctrl = pDev->key->xkbInfo->desc->ctrls; - old= *ctrl; - - ctrl->repeat_delay = initialKeyRepeatValue * 15; - ctrl->repeat_interval = keyRepeatValue * 15; - - /* Turn off key-repeat for modifier keys, on for others */ - /* First set them all on */ - for(i=0; i < XkbPerKeyBitArraySize; i++) - ctrl->per_key_repeat[i] = -1; - - /* Now turn off the modifiers */ - for(i=0; i < 32; i++) { - unsigned char keycode; - - keycode = keyInfo.modifierKeycodes[i][0]; - if(keycode) - ClearBit(ctrl->per_key_repeat, keycode + MIN_KEYCODE); - - keycode = keyInfo.modifierKeycodes[i][1]; - if(keycode) - ClearBit(ctrl->per_key_repeat, keycode + MIN_KEYCODE); - } - - /* Hurray for data duplication */ - if (pDev->kbdfeed) - memcpy(pDev->kbdfeed->ctrl.autoRepeats, ctrl->per_key_repeat, XkbPerKeyBitArraySize); - - //fprintf(stderr, "per_key_repeat =\n"); - //for(i=0; i < XkbPerKeyBitArraySize; i++) - // fprintf(stderr, "%02x%s", ctrl->per_key_repeat[i], (i + 1) & 7 ? "" : "\n"); - - /* And now we notify the puppies about the changes */ - XkbDDXChangeControls(pDev, &old, ctrl); - } -} - -void DarwinKeyboardReloadHandler(void) { - KeySymsRec keySyms; - CFIndex initialKeyRepeatValue, keyRepeatValue; - BOOL ok; - DeviceIntPtr pDev; - const char *xmodmap = PROJECTROOT "/bin/xmodmap"; - const char *sysmodmap = PROJECTROOT "/lib/X11/xinit/.Xmodmap"; - const char *homedir = getenv("HOME"); - char usermodmap[PATH_MAX], cmd[PATH_MAX]; - - DEBUG_LOG("DarwinKeyboardReloadHandler\n"); - - /* Get our key repeat settings from GlobalPreferences */ - (void)CFPreferencesAppSynchronize(CFSTR(".GlobalPreferences")); - - initialKeyRepeatValue = CFPreferencesGetAppIntegerValue(CFSTR("InitialKeyRepeat"), CFSTR(".GlobalPreferences"), &ok); - if(!ok) - initialKeyRepeatValue = 35; - - keyRepeatValue = CFPreferencesGetAppIntegerValue(CFSTR("KeyRepeat"), CFSTR(".GlobalPreferences"), &ok); - if(!ok) - keyRepeatValue = 6; - - pthread_mutex_lock(&keyInfo_mutex); { - /* Initialize our keySyms */ - keySyms.map = keyInfo.keyMap; - keySyms.mapWidth = GLYPHS_PER_KEY; - keySyms.minKeyCode = MIN_KEYCODE; - keySyms.maxKeyCode = MAX_KEYCODE; - - // TODO: We should build the entire XkbDescRec and use XkbCopyKeymap - /* Apply the mappings to darwinKeyboard */ - XkbApplyMappingChange(darwinKeyboard, &keySyms, keySyms.minKeyCode, - keySyms.maxKeyCode - keySyms.minKeyCode + 1, - keyInfo.modMap, serverClient); - DarwinKeyboardSetRepeat(darwinKeyboard, initialKeyRepeatValue, keyRepeatValue); - - /* Apply the mappings to the core keyboard */ - for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { - if ((pDev->coreEvents || pDev == inputInfo.keyboard) && pDev->key) { - XkbApplyMappingChange(pDev, &keySyms, keySyms.minKeyCode, - keySyms.maxKeyCode - keySyms.minKeyCode + 1, - keyInfo.modMap, serverClient); - DarwinKeyboardSetRepeat(pDev, initialKeyRepeatValue, keyRepeatValue); - } - } - } pthread_mutex_unlock(&keyInfo_mutex); - - /* Modify with xmodmap */ - if (access(xmodmap, F_OK) == 0) { - /* Check for system .Xmodmap */ - if (access(sysmodmap, F_OK) == 0) { - if(snprintf (cmd, sizeof(cmd), "%s %s", xmodmap, sysmodmap) < sizeof(cmd)) { - X11ApplicationLaunchClient(cmd); - } else { - ErrorF("X11.app: Unable to create / execute xmodmap command line"); - } - } - - /* Check for user's local .Xmodmap */ - if ((homedir != NULL) && (snprintf (usermodmap, sizeof(usermodmap), "%s/.Xmodmap", homedir) < sizeof(usermodmap))) { - if (access(usermodmap, F_OK) == 0) { - if(snprintf (cmd, sizeof(cmd), "%s %s", xmodmap, usermodmap) < sizeof(cmd)) { - X11ApplicationLaunchClient(cmd); - } else { - ErrorF("X11.app: Unable to create / execute xmodmap command line"); - } - } - } else { - ErrorF("X11.app: Unable to determine path to user's .Xmodmap"); - } - } -} - -//----------------------------------------------------------------------------- -// Modifier translation functions -// -// There are three different ways to specify a Mac modifier key: -// keycode - specifies hardware key, read from keymapping -// key - NX_MODIFIERKEY_*, really an index -// mask - NX_*MASK, mask for modifier flags in event record -// Left and right side have different keycodes but the same key and mask. -//----------------------------------------------------------------------------- - -/* - * DarwinModifierNXKeyToNXKeycode - * Return the keycode for an NX_MODIFIERKEY_* modifier. - * side = 0 for left or 1 for right. - * Returns 0 if key+side is not a known modifier. - */ -int DarwinModifierNXKeyToNXKeycode(int key, int side) { - int retval; - pthread_mutex_lock(&keyInfo_mutex); - retval = keyInfo.modifierKeycodes[key][side]; - pthread_mutex_unlock(&keyInfo_mutex); - - return retval; -} - -/* - * DarwinModifierNXKeycodeToNXKey - * Returns -1 if keycode+side is not a modifier key - * outSide may be NULL, else it gets 0 for left and 1 for right. - */ -int DarwinModifierNXKeycodeToNXKey(unsigned char keycode, int *outSide) { - int key, side; - - keycode += MIN_KEYCODE; - - // search modifierKeycodes for this keycode+side - pthread_mutex_lock(&keyInfo_mutex); - for (key = 0; key < NX_NUMMODIFIERS; key++) { - for (side = 0; side <= 1; side++) { - if (keyInfo.modifierKeycodes[key][side] == keycode) break; - } - } - pthread_mutex_unlock(&keyInfo_mutex); - - if (key == NX_NUMMODIFIERS) { - return -1; - } - if (outSide) *outSide = side; - - return key; -} - -/* - * DarwinModifierNXMaskToNXKey - * Returns -1 if mask is not a known modifier mask. - */ -int DarwinModifierNXMaskToNXKey(int mask) { - switch (mask) { - case NX_ALPHASHIFTMASK: return NX_MODIFIERKEY_ALPHALOCK; - case NX_SHIFTMASK: return NX_MODIFIERKEY_SHIFT; -#ifdef NX_DEVICELSHIFTKEYMASK - case NX_DEVICELSHIFTKEYMASK: return NX_MODIFIERKEY_SHIFT; - case NX_DEVICERSHIFTKEYMASK: return NX_MODIFIERKEY_RSHIFT; -#endif - case NX_CONTROLMASK: return NX_MODIFIERKEY_CONTROL; -#ifdef NX_DEVICELCTLKEYMASK - case NX_DEVICELCTLKEYMASK: return NX_MODIFIERKEY_CONTROL; - case NX_DEVICERCTLKEYMASK: return NX_MODIFIERKEY_RCONTROL; -#endif - case NX_ALTERNATEMASK: return NX_MODIFIERKEY_ALTERNATE; -#ifdef NX_DEVICELALTKEYMASK - case NX_DEVICELALTKEYMASK: return NX_MODIFIERKEY_ALTERNATE; - case NX_DEVICERALTKEYMASK: return NX_MODIFIERKEY_RALTERNATE; -#endif - case NX_COMMANDMASK: return NX_MODIFIERKEY_COMMAND; -#ifdef NX_DEVICELCMDKEYMASK - case NX_DEVICELCMDKEYMASK: return NX_MODIFIERKEY_COMMAND; - case NX_DEVICERCMDKEYMASK: return NX_MODIFIERKEY_RCOMMAND; -#endif - case NX_NUMERICPADMASK: return NX_MODIFIERKEY_NUMERICPAD; - case NX_HELPMASK: return NX_MODIFIERKEY_HELP; - case NX_SECONDARYFNMASK: return NX_MODIFIERKEY_SECONDARYFN; - } - return -1; -} - -/* - * DarwinModifierNXKeyToNXMask - * Returns 0 if key is not a known modifier key. - */ -int DarwinModifierNXKeyToNXMask(int key) { - switch (key) { - case NX_MODIFIERKEY_ALPHALOCK: return NX_ALPHASHIFTMASK; -#ifdef NX_DEVICELSHIFTKEYMASK - case NX_MODIFIERKEY_SHIFT: return NX_DEVICELSHIFTKEYMASK; - case NX_MODIFIERKEY_RSHIFT: return NX_DEVICERSHIFTKEYMASK; - case NX_MODIFIERKEY_CONTROL: return NX_DEVICELCTLKEYMASK; - case NX_MODIFIERKEY_RCONTROL: return NX_DEVICERCTLKEYMASK; - case NX_MODIFIERKEY_ALTERNATE: return NX_DEVICELALTKEYMASK; - case NX_MODIFIERKEY_RALTERNATE: return NX_DEVICERALTKEYMASK; - case NX_MODIFIERKEY_COMMAND: return NX_DEVICELCMDKEYMASK; - case NX_MODIFIERKEY_RCOMMAND: return NX_DEVICERCMDKEYMASK; -#else - case NX_MODIFIERKEY_SHIFT: return NX_SHIFTMASK; - case NX_MODIFIERKEY_CONTROL: return NX_CONTROLMASK; - case NX_MODIFIERKEY_ALTERNATE: return NX_ALTERNATEMASK; - case NX_MODIFIERKEY_COMMAND: return NX_COMMANDMASK; -#endif - case NX_MODIFIERKEY_NUMERICPAD: return NX_NUMERICPADMASK; - case NX_MODIFIERKEY_HELP: return NX_HELPMASK; - case NX_MODIFIERKEY_SECONDARYFN: return NX_SECONDARYFNMASK; - } - return 0; -} - -/* - * DarwinModifierStringToNXMask - * Returns 0 if string is not a known modifier. - */ -int DarwinModifierStringToNXMask(const char *str, int separatelr) { -#ifdef NX_DEVICELSHIFTKEYMASK - if(separatelr) { - if (!strcasecmp(str, "shift")) return NX_DEVICELSHIFTKEYMASK | NX_DEVICERSHIFTKEYMASK; - if (!strcasecmp(str, "control")) return NX_DEVICELCTLKEYMASK | NX_DEVICERCTLKEYMASK; - if (!strcasecmp(str, "option")) return NX_DEVICELALTKEYMASK | NX_DEVICERALTKEYMASK; - if (!strcasecmp(str, "alt")) return NX_DEVICELALTKEYMASK | NX_DEVICERALTKEYMASK; - if (!strcasecmp(str, "command")) return NX_DEVICELCMDKEYMASK | NX_DEVICERCMDKEYMASK; - if (!strcasecmp(str, "lshift")) return NX_DEVICELSHIFTKEYMASK; - if (!strcasecmp(str, "rshift")) return NX_DEVICERSHIFTKEYMASK; - if (!strcasecmp(str, "lcontrol")) return NX_DEVICELCTLKEYMASK; - if (!strcasecmp(str, "rcontrol")) return NX_DEVICERCTLKEYMASK; - if (!strcasecmp(str, "loption")) return NX_DEVICELALTKEYMASK; - if (!strcasecmp(str, "roption")) return NX_DEVICERALTKEYMASK; - if (!strcasecmp(str, "lalt")) return NX_DEVICELALTKEYMASK; - if (!strcasecmp(str, "ralt")) return NX_DEVICERALTKEYMASK; - if (!strcasecmp(str, "lcommand")) return NX_DEVICELCMDKEYMASK; - if (!strcasecmp(str, "rcommand")) return NX_DEVICERCMDKEYMASK; - } else { -#endif - if (!strcasecmp(str, "shift")) return NX_SHIFTMASK; - if (!strcasecmp(str, "control")) return NX_CONTROLMASK; - if (!strcasecmp(str, "option")) return NX_ALTERNATEMASK; - if (!strcasecmp(str, "alt")) return NX_ALTERNATEMASK; - if (!strcasecmp(str, "command")) return NX_COMMANDMASK; - if (!strcasecmp(str, "lshift")) return NX_SHIFTMASK; - if (!strcasecmp(str, "rshift")) return NX_SHIFTMASK; - if (!strcasecmp(str, "lcontrol")) return NX_CONTROLMASK; - if (!strcasecmp(str, "rcontrol")) return NX_CONTROLMASK; - if (!strcasecmp(str, "loption")) return NX_ALTERNATEMASK; - if (!strcasecmp(str, "roption")) return NX_ALTERNATEMASK; - if (!strcasecmp(str, "lalt")) return NX_ALTERNATEMASK; - if (!strcasecmp(str, "ralt")) return NX_ALTERNATEMASK; - if (!strcasecmp(str, "lcommand")) return NX_COMMANDMASK; - if (!strcasecmp(str, "rcommand")) return NX_COMMANDMASK; -#ifdef NX_DEVICELSHIFTKEYMASK - } -#endif - if (!strcasecmp(str, "lock")) return NX_ALPHASHIFTMASK; - if (!strcasecmp(str, "fn")) return NX_SECONDARYFNMASK; - if (!strcasecmp(str, "help")) return NX_HELPMASK; - if (!strcasecmp(str, "numlock")) return NX_NUMERICPADMASK; - return 0; -} - -/* - * LegalModifier - * This allows the ddx layer to prevent some keys from being remapped - * as modifier keys. - */ -Bool LegalModifier(unsigned int key, DeviceIntPtr pDev) -{ - return 1; -} - -static inline UniChar macroman2ucs(unsigned char c) { - /* Precalculated table mapping MacRoman-128 to Unicode. Generated - by creating single element CFStringRefs then extracting the - first character. */ - - static const unsigned short table[128] = { - 0xc4, 0xc5, 0xc7, 0xc9, 0xd1, 0xd6, 0xdc, 0xe1, - 0xe0, 0xe2, 0xe4, 0xe3, 0xe5, 0xe7, 0xe9, 0xe8, - 0xea, 0xeb, 0xed, 0xec, 0xee, 0xef, 0xf1, 0xf3, - 0xf2, 0xf4, 0xf6, 0xf5, 0xfa, 0xf9, 0xfb, 0xfc, - 0x2020, 0xb0, 0xa2, 0xa3, 0xa7, 0x2022, 0xb6, 0xdf, - 0xae, 0xa9, 0x2122, 0xb4, 0xa8, 0x2260, 0xc6, 0xd8, - 0x221e, 0xb1, 0x2264, 0x2265, 0xa5, 0xb5, 0x2202, 0x2211, - 0x220f, 0x3c0, 0x222b, 0xaa, 0xba, 0x3a9, 0xe6, 0xf8, - 0xbf, 0xa1, 0xac, 0x221a, 0x192, 0x2248, 0x2206, 0xab, - 0xbb, 0x2026, 0xa0, 0xc0, 0xc3, 0xd5, 0x152, 0x153, - 0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0xf7, 0x25ca, - 0xff, 0x178, 0x2044, 0x20ac, 0x2039, 0x203a, 0xfb01, 0xfb02, - 0x2021, 0xb7, 0x201a, 0x201e, 0x2030, 0xc2, 0xca, 0xc1, - 0xcb, 0xc8, 0xcd, 0xce, 0xcf, 0xcc, 0xd3, 0xd4, - 0xf8ff, 0xd2, 0xda, 0xdb, 0xd9, 0x131, 0x2c6, 0x2dc, - 0xaf, 0x2d8, 0x2d9, 0x2da, 0xb8, 0x2dd, 0x2db, 0x2c7, - }; - - if (c < 128) return c; - else return table[c - 128]; -} - -static KeySym make_dead_key(KeySym in) { - int i; - - for (i = 0; i < sizeof (dead_keys) / sizeof (dead_keys[0]); i++) - if (dead_keys[i].normal == in) return dead_keys[i].dead; - - return in; -} - -static Bool QuartzReadSystemKeymap(darwinKeyboardInfo *info) { -#if !defined(__LP64__) || MAC_OS_X_VERSION_MIN_REQUIRED < 1050 - KeyboardLayoutRef key_layout; - int is_uchr = 1; -#endif - const void *chr_data = NULL; - int num_keycodes = NUM_KEYCODES; - UInt32 keyboard_type = LMGetKbdType(); - int i, j; - OSStatus err; - KeySym *k; - CFDataRef currentKeyLayoutDataRef = NULL; - -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 - TISInputSourceRef currentKeyLayoutRef = TISCopyCurrentKeyboardLayoutInputSource(); - - if (currentKeyLayoutRef) { - currentKeyLayoutDataRef = (CFDataRef )TISGetInputSourceProperty(currentKeyLayoutRef, kTISPropertyUnicodeKeyLayoutData); - if (currentKeyLayoutDataRef) - chr_data = CFDataGetBytePtr(currentKeyLayoutDataRef); - } -#endif - -#if !defined(__LP64__) || MAC_OS_X_VERSION_MIN_REQUIRED < 1050 - if (chr_data == NULL) { -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 - ErrorF("X11.app: Error detected in determining keyboard layout. If you are using an Apple-provided keyboard layout, please report this error at http://xquartz.macosforge.org and http://bugreport.apple.com\n"); - ErrorF("X11.app: Debug Info: keyboard_type=%u, currentKeyLayoutRef=%p, currentKeyLayoutDataRef=%p, chr_data=%p\n", - (unsigned)keyboard_type, currentKeyLayoutRef, currentKeyLayoutDataRef, chr_data); -#endif - - KLGetCurrentKeyboardLayout (&key_layout); - KLGetKeyboardLayoutProperty (key_layout, kKLuchrData, &chr_data); - -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 - if(chr_data != NULL) { - ErrorF("X11.app: Fallback succeeded, but this is still a bug. Please report the above information.\n"); - } -#endif - } - - if (chr_data == NULL) { - ErrorF("X11.app: Debug Info: kKLuchrData failed, trying kKLKCHRData.\n"); - ErrorF("If you are using a 3rd party keyboard layout, please see http://xquartz.macosforge.org/trac/ticket/154\n"); - KLGetKeyboardLayoutProperty (key_layout, kKLKCHRData, &chr_data); - is_uchr = 0; - num_keycodes = 128; - -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 - if(chr_data != NULL) { - ErrorF("X11.app: Fallback succeeded, but this is still a bug. Please report the above information.\n"); - } -#endif - } -#endif - -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 - if(currentKeyLayoutRef) - CFRelease(currentKeyLayoutRef); -#endif - - if (chr_data == NULL) { - ErrorF ( "Couldn't get uchr or kchr resource\n"); - return FALSE; - } - - /* Scan the keycode range for the Unicode character that each - key produces in the four shift states. Then convert that to - an X11 keysym (which may just the bit that says "this is - Unicode" if it can't find the real symbol.) */ - - /* KeyTranslate is not available on 64-bit platforms; UCKeyTranslate - must be used instead. */ - - for (i = 0; i < num_keycodes; i++) { - static const int mods[4] = {0, MOD_SHIFT, MOD_OPTION, - MOD_OPTION | MOD_SHIFT}; - - k = info->keyMap + i * GLYPHS_PER_KEY; - - for (j = 0; j < 4; j++) { -#if !defined(__LP64__) || MAC_OS_X_VERSION_MIN_REQUIRED < 1050 - if (is_uchr) { -#endif - UniChar s[8]; - UniCharCount len; - UInt32 dead_key_state = 0, extra_dead = 0; - - err = UCKeyTranslate (chr_data, i, kUCKeyActionDown, - mods[j] >> 8, keyboard_type, 0, - &dead_key_state, 8, &len, s); - if (err != noErr) continue; - - if (len == 0 && dead_key_state != 0) { - /* Found a dead key. Work out which one it is, but - remembering that it's dead. */ - err = UCKeyTranslate (chr_data, i, kUCKeyActionDown, - mods[j] >> 8, keyboard_type, - kUCKeyTranslateNoDeadKeysMask, - &extra_dead, 8, &len, s); - if (err != noErr) continue; - } - - /* Not sure why 0x0010 is there. - * 0x0000 - <rdar://problem/7793566> 'Unicode Hex Input' ... - */ - if (len > 0 && s[0] != 0x0010 && s[0] != 0x0000) { - k[j] = ucs2keysym (s[0]); - if (dead_key_state != 0) k[j] = make_dead_key (k[j]); - } -#if !defined(__LP64__) || MAC_OS_X_VERSION_MIN_REQUIRED < 1050 - } else { // kchr - UInt32 c, state = 0, state2 = 0; - UInt16 code; - - code = i | mods[j]; - c = KeyTranslate (chr_data, code, &state); - - /* Dead keys are only processed on key-down, so ask - to translate those events. When we find a dead key, - translating the matching key up event will give - us the actual dead character. */ - - if (state != 0) - c = KeyTranslate (chr_data, code | 128, &state2); - - /* Characters seem to be in MacRoman encoding. */ - - if (c != 0 && c != 0x0010) { - k[j] = ucs2keysym (macroman2ucs (c & 255)); - - if (state != 0) k[j] = make_dead_key (k[j]); - } - } -#endif - } - - if (k[3] == k[2]) k[3] = NoSymbol; - if (k[1] == k[0]) k[1] = NoSymbol; - if (k[0] == k[2] && k[1] == k[3]) k[2] = k[3] = NoSymbol; - if (k[3] == k[0] && k[2] == k[1] && k[2] == NoSymbol) k[3] = NoSymbol; - } - -#if HACK_MISSING - /* Fix up some things that are normally missing.. */ - - for (i = 0; i < sizeof (known_keys) / sizeof (known_keys[0]); i++) { - k = info->keyMap + known_keys[i].keycode * GLYPHS_PER_KEY; - - if ( k[0] == NoSymbol && k[1] == NoSymbol - && k[2] == NoSymbol && k[3] == NoSymbol) - k[0] = known_keys[i].keysym; - } -#endif - -#if HACK_KEYPAD - /* And some more things. We find the right symbols for the numeric - keypad, but not the KP_ keysyms. So try to convert known keycodes. */ - for (i = 0; i < sizeof (known_numeric_keys) / sizeof (known_numeric_keys[0]); i++) { - k = info->keyMap + known_numeric_keys[i].keycode * GLYPHS_PER_KEY; - - if (k[0] == known_numeric_keys[i].normal) - k[0] = known_numeric_keys[i].keypad; - } -#endif - -#if HACK_BLACKLIST - for (i = 0; i < sizeof (keycode_blacklist) / sizeof (keycode_blacklist[0]); i++) { - k = info->keyMap + keycode_blacklist[i] * GLYPHS_PER_KEY; - k[0] = k[1] = k[2] = k[3] = NoSymbol; - } -#endif - - DarwinBuildModifierMaps(info); - - return TRUE; -} - -Bool QuartsResyncKeymap(Bool sendDDXEvent) { - Bool retval; - /* Update keyInfo */ - pthread_mutex_lock(&keyInfo_mutex); - memset(keyInfo.keyMap, 0, sizeof(keyInfo.keyMap)); - retval = QuartzReadSystemKeymap(&keyInfo); - pthread_mutex_unlock(&keyInfo_mutex); - - /* Tell server thread to deal with new keyInfo */ - if(sendDDXEvent) - DarwinSendDDXEvent(kXquartzReloadKeymap, 0); - - return retval; -} +/*
+ quartzKeyboard.c: Keyboard support for Xquartz
+
+ Copyright (c) 2003-2008 Apple Inc.
+ Copyright (c) 2001-2004 Torrey T. Lyons. All Rights Reserved.
+ Copyright 2004 Kaleb S. KEITHLEY. All Rights Reserved.
+
+ Copyright (C) 1999,2000 by Eric Sunshine <sunshine@sunshineco.com>
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "sanitizedCarbon.h"
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#define HACK_MISSING 1
+#define HACK_KEYPAD 1
+#define HACK_BLACKLIST 1
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <AvailabilityMacros.h>
+
+#include "quartz.h"
+#include "darwin.h"
+#include "darwinEvents.h"
+
+#include "quartzKeyboard.h"
+
+#include "X11Application.h"
+
+#ifdef NDEBUG
+#undef NDEBUG
+#include <assert.h>
+#define NDEBUG 1
+#else
+#include <assert.h>
+#endif
+#include <pthread.h>
+
+#include "xkbsrv.h"
+#include "exevents.h"
+#include "X11/keysym.h"
+#include "keysym2ucs.h"
+
+extern void
+CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master);
+
+enum {
+ MOD_COMMAND = 256,
+ MOD_SHIFT = 512,
+ MOD_OPTION = 2048,
+ MOD_CONTROL = 4096,
+};
+
+#define UKEYSYM(u) ((u) | 0x01000000)
+
+#if HACK_MISSING
+/* Table of keycode->keysym mappings we use to fallback on for important
+ keys that are often not in the Unicode mapping. */
+
+const static struct {
+ unsigned short keycode;
+ KeySym keysym;
+} known_keys[] = {
+ {55, XK_Meta_L},
+ {56, XK_Shift_L},
+ {57, XK_Caps_Lock},
+ {58, XK_Alt_L},
+ {59, XK_Control_L},
+
+ {60, XK_Shift_R},
+ {61, XK_Alt_R},
+ {62, XK_Control_R},
+ {63, XK_Meta_R},
+
+ {122, XK_F1},
+ {120, XK_F2},
+ {99, XK_F3},
+ {118, XK_F4},
+ {96, XK_F5},
+ {97, XK_F6},
+ {98, XK_F7},
+ {100, XK_F8},
+ {101, XK_F9},
+ {109, XK_F10},
+ {103, XK_F11},
+ {111, XK_F12},
+ {105, XK_F13},
+ {107, XK_F14},
+ {113, XK_F15},
+};
+#endif
+
+#if HACK_KEYPAD
+/* Table of keycode->old,new-keysym mappings we use to fixup the numeric
+ keypad entries. */
+
+const static struct {
+ unsigned short keycode;
+ KeySym normal, keypad;
+} known_numeric_keys[] = {
+ {65, XK_period, XK_KP_Decimal},
+ {67, XK_asterisk, XK_KP_Multiply},
+ {69, XK_plus, XK_KP_Add},
+ {75, XK_slash, XK_KP_Divide},
+ {76, 0x01000003, XK_KP_Enter},
+ {78, XK_minus, XK_KP_Subtract},
+ {81, XK_equal, XK_KP_Equal},
+ {82, XK_0, XK_KP_0},
+ {83, XK_1, XK_KP_1},
+ {84, XK_2, XK_KP_2},
+ {85, XK_3, XK_KP_3},
+ {86, XK_4, XK_KP_4},
+ {87, XK_5, XK_KP_5},
+ {88, XK_6, XK_KP_6},
+ {89, XK_7, XK_KP_7},
+ {91, XK_8, XK_KP_8},
+ {92, XK_9, XK_KP_9},
+};
+#endif
+
+#if HACK_BLACKLIST
+/* <rdar://problem/7824370> wine notepad produces wrong characters on shift+arrow
+ * http://xquartz.macosforge.org/trac/ticket/295
+ * http://developer.apple.com/legacy/mac/library/documentation/mac/Text/Text-579.html
+ *
+ * legacy Mac keycodes for arrow keys that shift-modify to math symbols
+ */
+const static unsigned short keycode_blacklist[] = {66, 70, 72, 77};
+#endif
+
+/* Table mapping normal keysyms to their dead equivalents.
+ FIXME: all the unicode keysyms (apart from circumflex) were guessed. */
+
+const static struct {
+ KeySym normal, dead;
+} dead_keys[] = {
+ {XK_grave, XK_dead_grave},
+ {XK_apostrophe, XK_dead_acute}, /* US:"=" on a Czech keyboard */
+ {XK_acute, XK_dead_acute},
+ {UKEYSYM (0x384), XK_dead_acute}, /* US:";" on a Greek keyboard */
+// {XK_Greek_accentdieresis, XK_dead_diaeresis}, /* US:"opt+;" on a Greek keyboard ... replace with dead_accentdieresis if there is one */
+ {XK_asciicircum, XK_dead_circumflex},
+ {UKEYSYM (0x2c6), XK_dead_circumflex}, /* MODIFIER LETTER CIRCUMFLEX ACCENT */
+ {XK_asciitilde, XK_dead_tilde},
+ {UKEYSYM (0x2dc), XK_dead_tilde}, /* SMALL TILDE */
+ {XK_macron, XK_dead_macron},
+ {XK_breve, XK_dead_breve},
+ {XK_abovedot, XK_dead_abovedot},
+ {XK_diaeresis, XK_dead_diaeresis},
+ {UKEYSYM (0x2da), XK_dead_abovering}, /* DOT ABOVE */
+ {XK_doubleacute, XK_dead_doubleacute},
+ {XK_caron, XK_dead_caron},
+ {XK_cedilla, XK_dead_cedilla},
+ {XK_ogonek, XK_dead_ogonek},
+ {UKEYSYM (0x269), XK_dead_iota}, /* LATIN SMALL LETTER IOTA */
+ {UKEYSYM (0x2ec), XK_dead_voiced_sound}, /* MODIFIER LETTER VOICING */
+/* {XK_semivoiced_sound, XK_dead_semivoiced_sound}, */
+ {UKEYSYM (0x323), XK_dead_belowdot}, /* COMBINING DOT BELOW */
+ {UKEYSYM (0x309), XK_dead_hook}, /* COMBINING HOOK ABOVE */
+ {UKEYSYM (0x31b), XK_dead_horn}, /* COMBINING HORN */
+};
+
+typedef struct darwinKeyboardInfo_struct {
+ CARD8 modMap[MAP_LENGTH];
+ KeySym keyMap[MAP_LENGTH * GLYPHS_PER_KEY];
+ unsigned char modifierKeycodes[32][2];
+} darwinKeyboardInfo;
+
+darwinKeyboardInfo keyInfo;
+pthread_mutex_t keyInfo_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static void DarwinChangeKeyboardControl(DeviceIntPtr device, KeybdCtrl *ctrl) {
+ // FIXME: to be implemented
+ // keyclick, bell volume / pitch, autorepead, LED's
+}
+
+//-----------------------------------------------------------------------------
+// Utility functions to help parse Darwin keymap
+//-----------------------------------------------------------------------------
+
+/*
+ * DarwinBuildModifierMaps
+ * Use the keyMap field of keyboard info structure to populate
+ * the modMap and modifierKeycodes fields.
+ */
+static void DarwinBuildModifierMaps(darwinKeyboardInfo *info) {
+ int i;
+ KeySym *k;
+
+ memset(info->modMap, NoSymbol, sizeof(info->modMap));
+ memset(info->modifierKeycodes, 0, sizeof(info->modifierKeycodes));
+
+ for (i = 0; i < NUM_KEYCODES; i++) {
+ k = info->keyMap + i * GLYPHS_PER_KEY;
+
+ switch (*k) {
+ case XK_Shift_L:
+ info->modifierKeycodes[NX_MODIFIERKEY_SHIFT][0] = i;
+ info->modMap[MIN_KEYCODE + i] = ShiftMask;
+ break;
+
+ case XK_Shift_R:
+#ifdef NX_MODIFIERKEY_RSHIFT
+ info->modifierKeycodes[NX_MODIFIERKEY_RSHIFT][0] = i;
+#else
+ info->modifierKeycodes[NX_MODIFIERKEY_SHIFT][0] = i;
+#endif
+ info->modMap[MIN_KEYCODE + i] = ShiftMask;
+ break;
+
+ case XK_Control_L:
+ info->modifierKeycodes[NX_MODIFIERKEY_CONTROL][0] = i;
+ info->modMap[MIN_KEYCODE + i] = ControlMask;
+ break;
+
+ case XK_Control_R:
+#ifdef NX_MODIFIERKEY_RCONTROL
+ info->modifierKeycodes[NX_MODIFIERKEY_RCONTROL][0] = i;
+#else
+ info->modifierKeycodes[NX_MODIFIERKEY_CONTROL][0] = i;
+#endif
+ info->modMap[MIN_KEYCODE + i] = ControlMask;
+ break;
+
+ case XK_Caps_Lock:
+ info->modifierKeycodes[NX_MODIFIERKEY_ALPHALOCK][0] = i;
+ info->modMap[MIN_KEYCODE + i] = LockMask;
+ break;
+
+ case XK_Alt_L:
+ info->modifierKeycodes[NX_MODIFIERKEY_ALTERNATE][0] = i;
+ info->modMap[MIN_KEYCODE + i] = Mod1Mask;
+ if(!XQuartzOptionSendsAlt)
+ *k = XK_Mode_switch; // Yes, this is ugly. This needs to be cleaned up when we integrate quartzKeyboard with this code and refactor.
+ break;
+
+ case XK_Alt_R:
+#ifdef NX_MODIFIERKEY_RALTERNATE
+ info->modifierKeycodes[NX_MODIFIERKEY_RALTERNATE][0] = i;
+#else
+ info->modifierKeycodes[NX_MODIFIERKEY_ALTERNATE][0] = i;
+#endif
+ if(!XQuartzOptionSendsAlt)
+ *k = XK_Mode_switch; // Yes, this is ugly. This needs to be cleaned up when we integrate quartzKeyboard with this code and refactor.
+ info->modMap[MIN_KEYCODE + i] = Mod1Mask;
+ break;
+
+ case XK_Mode_switch:
+ ErrorF("DarwinBuildModifierMaps: XK_Mode_switch encountered, unable to determine side.\n");
+ info->modifierKeycodes[NX_MODIFIERKEY_ALTERNATE][0] = i;
+#ifdef NX_MODIFIERKEY_RALTERNATE
+ info->modifierKeycodes[NX_MODIFIERKEY_RALTERNATE][0] = i;
+#endif
+ info->modMap[MIN_KEYCODE + i] = Mod1Mask;
+ break;
+
+ case XK_Meta_L:
+ info->modifierKeycodes[NX_MODIFIERKEY_COMMAND][0] = i;
+ info->modMap[MIN_KEYCODE + i] = Mod2Mask;
+ break;
+
+ case XK_Meta_R:
+#ifdef NX_MODIFIERKEY_RCOMMAND
+ info->modifierKeycodes[NX_MODIFIERKEY_RCOMMAND][0] = i;
+#else
+ info->modifierKeycodes[NX_MODIFIERKEY_COMMAND][0] = i;
+#endif
+ info->modMap[MIN_KEYCODE + i] = Mod2Mask;
+ break;
+
+ case XK_Num_Lock:
+ info->modMap[MIN_KEYCODE + i] = Mod3Mask;
+ break;
+ }
+ }
+}
+
+/*
+ * DarwinKeyboardInit
+ * Get the Darwin keyboard map and compute an equivalent
+ * X keyboard map and modifier map. Set the new keyboard
+ * device structure.
+ */
+void DarwinKeyboardInit(DeviceIntPtr pDev) {
+ // Open a shared connection to the HID System.
+ // Note that the Event Status Driver is really just a wrapper
+ // for a kIOHIDParamConnectType connection.
+ assert(darwinParamConnect = NXOpenEventStatus());
+
+ InitKeyboardDeviceStruct(pDev, NULL, NULL, DarwinChangeKeyboardControl);
+
+ DarwinKeyboardReloadHandler();
+
+ CopyKeyClass(pDev, inputInfo.keyboard);
+}
+
+/* Set the repeat rates based on global preferences and keycodes for modifiers.
+ * Precondition: Has the keyInfo_mutex lock.
+ */
+static void DarwinKeyboardSetRepeat(DeviceIntPtr pDev, int initialKeyRepeatValue, int keyRepeatValue) {
+ if(initialKeyRepeatValue == 300000) { // off
+ /* Turn off repeats globally */
+ XkbSetRepeatKeys(pDev, -1, AutoRepeatModeOff);
+ } else {
+ int i;
+ XkbControlsPtr ctrl;
+ XkbControlsRec old;
+
+ /* Turn on repeats globally */
+ XkbSetRepeatKeys(pDev, -1, AutoRepeatModeOn);
+
+ /* Setup the bit mask for individual key repeats */
+ ctrl = pDev->key->xkbInfo->desc->ctrls;
+ old= *ctrl;
+
+ ctrl->repeat_delay = initialKeyRepeatValue * 15;
+ ctrl->repeat_interval = keyRepeatValue * 15;
+
+ /* Turn off key-repeat for modifier keys, on for others */
+ /* First set them all on */
+ for(i=0; i < XkbPerKeyBitArraySize; i++)
+ ctrl->per_key_repeat[i] = -1;
+
+ /* Now turn off the modifiers */
+ for(i=0; i < 32; i++) {
+ unsigned char keycode;
+
+ keycode = keyInfo.modifierKeycodes[i][0];
+ if(keycode)
+ ClearBit(ctrl->per_key_repeat, keycode + MIN_KEYCODE);
+
+ keycode = keyInfo.modifierKeycodes[i][1];
+ if(keycode)
+ ClearBit(ctrl->per_key_repeat, keycode + MIN_KEYCODE);
+ }
+
+ /* Hurray for data duplication */
+ if (pDev->kbdfeed)
+ memcpy(pDev->kbdfeed->ctrl.autoRepeats, ctrl->per_key_repeat, XkbPerKeyBitArraySize);
+
+ //ErrorF("per_key_repeat =\n");
+ //for(i=0; i < XkbPerKeyBitArraySize; i++)
+ // ErrorF("%02x%s", ctrl->per_key_repeat[i], (i + 1) & 7 ? "" : "\n");
+
+ /* And now we notify the puppies about the changes */
+ XkbDDXChangeControls(pDev, &old, ctrl);
+ }
+}
+
+void DarwinKeyboardReloadHandler(void) {
+ KeySymsRec keySyms;
+ CFIndex initialKeyRepeatValue, keyRepeatValue;
+ BOOL ok;
+ DeviceIntPtr pDev;
+ const char *xmodmap = PROJECTROOT "/bin/xmodmap";
+ const char *sysmodmap = PROJECTROOT "/lib/X11/xinit/.Xmodmap";
+ const char *homedir = getenv("HOME");
+ char usermodmap[PATH_MAX], cmd[PATH_MAX];
+
+ DEBUG_LOG("DarwinKeyboardReloadHandler\n");
+
+ /* Get our key repeat settings from GlobalPreferences */
+ (void)CFPreferencesAppSynchronize(CFSTR(".GlobalPreferences"));
+
+ initialKeyRepeatValue = CFPreferencesGetAppIntegerValue(CFSTR("InitialKeyRepeat"), CFSTR(".GlobalPreferences"), &ok);
+ if(!ok)
+ initialKeyRepeatValue = 35;
+
+ keyRepeatValue = CFPreferencesGetAppIntegerValue(CFSTR("KeyRepeat"), CFSTR(".GlobalPreferences"), &ok);
+ if(!ok)
+ keyRepeatValue = 6;
+
+ pthread_mutex_lock(&keyInfo_mutex); {
+ /* Initialize our keySyms */
+ keySyms.map = keyInfo.keyMap;
+ keySyms.mapWidth = GLYPHS_PER_KEY;
+ keySyms.minKeyCode = MIN_KEYCODE;
+ keySyms.maxKeyCode = MAX_KEYCODE;
+
+ // TODO: We should build the entire XkbDescRec and use XkbCopyKeymap
+ /* Apply the mappings to darwinKeyboard */
+ XkbApplyMappingChange(darwinKeyboard, &keySyms, keySyms.minKeyCode,
+ keySyms.maxKeyCode - keySyms.minKeyCode + 1,
+ keyInfo.modMap, serverClient);
+ DarwinKeyboardSetRepeat(darwinKeyboard, initialKeyRepeatValue, keyRepeatValue);
+
+ /* Apply the mappings to the core keyboard */
+ for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
+ if ((pDev->coreEvents || pDev == inputInfo.keyboard) && pDev->key) {
+ XkbApplyMappingChange(pDev, &keySyms, keySyms.minKeyCode,
+ keySyms.maxKeyCode - keySyms.minKeyCode + 1,
+ keyInfo.modMap, serverClient);
+ DarwinKeyboardSetRepeat(pDev, initialKeyRepeatValue, keyRepeatValue);
+ }
+ }
+ } pthread_mutex_unlock(&keyInfo_mutex);
+
+ /* Modify with xmodmap */
+ if (access(xmodmap, F_OK) == 0) {
+ /* Check for system .Xmodmap */
+ if (access(sysmodmap, F_OK) == 0) {
+ if(snprintf (cmd, sizeof(cmd), "%s %s", xmodmap, sysmodmap) < sizeof(cmd)) {
+ X11ApplicationLaunchClient(cmd);
+ } else {
+ ErrorF("X11.app: Unable to create / execute xmodmap command line");
+ }
+ }
+
+ /* Check for user's local .Xmodmap */
+ if ((homedir != NULL) && (snprintf (usermodmap, sizeof(usermodmap), "%s/.Xmodmap", homedir) < sizeof(usermodmap))) {
+ if (access(usermodmap, F_OK) == 0) {
+ if(snprintf (cmd, sizeof(cmd), "%s %s", xmodmap, usermodmap) < sizeof(cmd)) {
+ X11ApplicationLaunchClient(cmd);
+ } else {
+ ErrorF("X11.app: Unable to create / execute xmodmap command line");
+ }
+ }
+ } else {
+ ErrorF("X11.app: Unable to determine path to user's .Xmodmap");
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Modifier translation functions
+//
+// There are three different ways to specify a Mac modifier key:
+// keycode - specifies hardware key, read from keymapping
+// key - NX_MODIFIERKEY_*, really an index
+// mask - NX_*MASK, mask for modifier flags in event record
+// Left and right side have different keycodes but the same key and mask.
+//-----------------------------------------------------------------------------
+
+/*
+ * DarwinModifierNXKeyToNXKeycode
+ * Return the keycode for an NX_MODIFIERKEY_* modifier.
+ * side = 0 for left or 1 for right.
+ * Returns 0 if key+side is not a known modifier.
+ */
+int DarwinModifierNXKeyToNXKeycode(int key, int side) {
+ int retval;
+ pthread_mutex_lock(&keyInfo_mutex);
+ retval = keyInfo.modifierKeycodes[key][side];
+ pthread_mutex_unlock(&keyInfo_mutex);
+
+ return retval;
+}
+
+/*
+ * DarwinModifierNXKeycodeToNXKey
+ * Returns -1 if keycode+side is not a modifier key
+ * outSide may be NULL, else it gets 0 for left and 1 for right.
+ */
+int DarwinModifierNXKeycodeToNXKey(unsigned char keycode, int *outSide) {
+ int key, side;
+
+ keycode += MIN_KEYCODE;
+
+ // search modifierKeycodes for this keycode+side
+ pthread_mutex_lock(&keyInfo_mutex);
+ for (key = 0; key < NX_NUMMODIFIERS; key++) {
+ for (side = 0; side <= 1; side++) {
+ if (keyInfo.modifierKeycodes[key][side] == keycode) break;
+ }
+ }
+ pthread_mutex_unlock(&keyInfo_mutex);
+
+ if (key == NX_NUMMODIFIERS) {
+ return -1;
+ }
+ if (outSide) *outSide = side;
+
+ return key;
+}
+
+/*
+ * DarwinModifierNXMaskToNXKey
+ * Returns -1 if mask is not a known modifier mask.
+ */
+int DarwinModifierNXMaskToNXKey(int mask) {
+ switch (mask) {
+ case NX_ALPHASHIFTMASK: return NX_MODIFIERKEY_ALPHALOCK;
+ case NX_SHIFTMASK: return NX_MODIFIERKEY_SHIFT;
+#ifdef NX_DEVICELSHIFTKEYMASK
+ case NX_DEVICELSHIFTKEYMASK: return NX_MODIFIERKEY_SHIFT;
+ case NX_DEVICERSHIFTKEYMASK: return NX_MODIFIERKEY_RSHIFT;
+#endif
+ case NX_CONTROLMASK: return NX_MODIFIERKEY_CONTROL;
+#ifdef NX_DEVICELCTLKEYMASK
+ case NX_DEVICELCTLKEYMASK: return NX_MODIFIERKEY_CONTROL;
+ case NX_DEVICERCTLKEYMASK: return NX_MODIFIERKEY_RCONTROL;
+#endif
+ case NX_ALTERNATEMASK: return NX_MODIFIERKEY_ALTERNATE;
+#ifdef NX_DEVICELALTKEYMASK
+ case NX_DEVICELALTKEYMASK: return NX_MODIFIERKEY_ALTERNATE;
+ case NX_DEVICERALTKEYMASK: return NX_MODIFIERKEY_RALTERNATE;
+#endif
+ case NX_COMMANDMASK: return NX_MODIFIERKEY_COMMAND;
+#ifdef NX_DEVICELCMDKEYMASK
+ case NX_DEVICELCMDKEYMASK: return NX_MODIFIERKEY_COMMAND;
+ case NX_DEVICERCMDKEYMASK: return NX_MODIFIERKEY_RCOMMAND;
+#endif
+ case NX_NUMERICPADMASK: return NX_MODIFIERKEY_NUMERICPAD;
+ case NX_HELPMASK: return NX_MODIFIERKEY_HELP;
+ case NX_SECONDARYFNMASK: return NX_MODIFIERKEY_SECONDARYFN;
+ }
+ return -1;
+}
+
+/*
+ * DarwinModifierNXKeyToNXMask
+ * Returns 0 if key is not a known modifier key.
+ */
+int DarwinModifierNXKeyToNXMask(int key) {
+ switch (key) {
+ case NX_MODIFIERKEY_ALPHALOCK: return NX_ALPHASHIFTMASK;
+#ifdef NX_DEVICELSHIFTKEYMASK
+ case NX_MODIFIERKEY_SHIFT: return NX_DEVICELSHIFTKEYMASK;
+ case NX_MODIFIERKEY_RSHIFT: return NX_DEVICERSHIFTKEYMASK;
+ case NX_MODIFIERKEY_CONTROL: return NX_DEVICELCTLKEYMASK;
+ case NX_MODIFIERKEY_RCONTROL: return NX_DEVICERCTLKEYMASK;
+ case NX_MODIFIERKEY_ALTERNATE: return NX_DEVICELALTKEYMASK;
+ case NX_MODIFIERKEY_RALTERNATE: return NX_DEVICERALTKEYMASK;
+ case NX_MODIFIERKEY_COMMAND: return NX_DEVICELCMDKEYMASK;
+ case NX_MODIFIERKEY_RCOMMAND: return NX_DEVICERCMDKEYMASK;
+#else
+ case NX_MODIFIERKEY_SHIFT: return NX_SHIFTMASK;
+ case NX_MODIFIERKEY_CONTROL: return NX_CONTROLMASK;
+ case NX_MODIFIERKEY_ALTERNATE: return NX_ALTERNATEMASK;
+ case NX_MODIFIERKEY_COMMAND: return NX_COMMANDMASK;
+#endif
+ case NX_MODIFIERKEY_NUMERICPAD: return NX_NUMERICPADMASK;
+ case NX_MODIFIERKEY_HELP: return NX_HELPMASK;
+ case NX_MODIFIERKEY_SECONDARYFN: return NX_SECONDARYFNMASK;
+ }
+ return 0;
+}
+
+/*
+ * DarwinModifierStringToNXMask
+ * Returns 0 if string is not a known modifier.
+ */
+int DarwinModifierStringToNXMask(const char *str, int separatelr) {
+#ifdef NX_DEVICELSHIFTKEYMASK
+ if(separatelr) {
+ if (!strcasecmp(str, "shift")) return NX_DEVICELSHIFTKEYMASK | NX_DEVICERSHIFTKEYMASK;
+ if (!strcasecmp(str, "control")) return NX_DEVICELCTLKEYMASK | NX_DEVICERCTLKEYMASK;
+ if (!strcasecmp(str, "option")) return NX_DEVICELALTKEYMASK | NX_DEVICERALTKEYMASK;
+ if (!strcasecmp(str, "alt")) return NX_DEVICELALTKEYMASK | NX_DEVICERALTKEYMASK;
+ if (!strcasecmp(str, "command")) return NX_DEVICELCMDKEYMASK | NX_DEVICERCMDKEYMASK;
+ if (!strcasecmp(str, "lshift")) return NX_DEVICELSHIFTKEYMASK;
+ if (!strcasecmp(str, "rshift")) return NX_DEVICERSHIFTKEYMASK;
+ if (!strcasecmp(str, "lcontrol")) return NX_DEVICELCTLKEYMASK;
+ if (!strcasecmp(str, "rcontrol")) return NX_DEVICERCTLKEYMASK;
+ if (!strcasecmp(str, "loption")) return NX_DEVICELALTKEYMASK;
+ if (!strcasecmp(str, "roption")) return NX_DEVICERALTKEYMASK;
+ if (!strcasecmp(str, "lalt")) return NX_DEVICELALTKEYMASK;
+ if (!strcasecmp(str, "ralt")) return NX_DEVICERALTKEYMASK;
+ if (!strcasecmp(str, "lcommand")) return NX_DEVICELCMDKEYMASK;
+ if (!strcasecmp(str, "rcommand")) return NX_DEVICERCMDKEYMASK;
+ } else {
+#endif
+ if (!strcasecmp(str, "shift")) return NX_SHIFTMASK;
+ if (!strcasecmp(str, "control")) return NX_CONTROLMASK;
+ if (!strcasecmp(str, "option")) return NX_ALTERNATEMASK;
+ if (!strcasecmp(str, "alt")) return NX_ALTERNATEMASK;
+ if (!strcasecmp(str, "command")) return NX_COMMANDMASK;
+ if (!strcasecmp(str, "lshift")) return NX_SHIFTMASK;
+ if (!strcasecmp(str, "rshift")) return NX_SHIFTMASK;
+ if (!strcasecmp(str, "lcontrol")) return NX_CONTROLMASK;
+ if (!strcasecmp(str, "rcontrol")) return NX_CONTROLMASK;
+ if (!strcasecmp(str, "loption")) return NX_ALTERNATEMASK;
+ if (!strcasecmp(str, "roption")) return NX_ALTERNATEMASK;
+ if (!strcasecmp(str, "lalt")) return NX_ALTERNATEMASK;
+ if (!strcasecmp(str, "ralt")) return NX_ALTERNATEMASK;
+ if (!strcasecmp(str, "lcommand")) return NX_COMMANDMASK;
+ if (!strcasecmp(str, "rcommand")) return NX_COMMANDMASK;
+#ifdef NX_DEVICELSHIFTKEYMASK
+ }
+#endif
+ if (!strcasecmp(str, "lock")) return NX_ALPHASHIFTMASK;
+ if (!strcasecmp(str, "fn")) return NX_SECONDARYFNMASK;
+ if (!strcasecmp(str, "help")) return NX_HELPMASK;
+ if (!strcasecmp(str, "numlock")) return NX_NUMERICPADMASK;
+ return 0;
+}
+
+/*
+ * LegalModifier
+ * This allows the ddx layer to prevent some keys from being remapped
+ * as modifier keys.
+ */
+Bool LegalModifier(unsigned int key, DeviceIntPtr pDev)
+{
+ return 1;
+}
+
+static inline UniChar macroman2ucs(unsigned char c) {
+ /* Precalculated table mapping MacRoman-128 to Unicode. Generated
+ by creating single element CFStringRefs then extracting the
+ first character. */
+
+ static const unsigned short table[128] = {
+ 0xc4, 0xc5, 0xc7, 0xc9, 0xd1, 0xd6, 0xdc, 0xe1,
+ 0xe0, 0xe2, 0xe4, 0xe3, 0xe5, 0xe7, 0xe9, 0xe8,
+ 0xea, 0xeb, 0xed, 0xec, 0xee, 0xef, 0xf1, 0xf3,
+ 0xf2, 0xf4, 0xf6, 0xf5, 0xfa, 0xf9, 0xfb, 0xfc,
+ 0x2020, 0xb0, 0xa2, 0xa3, 0xa7, 0x2022, 0xb6, 0xdf,
+ 0xae, 0xa9, 0x2122, 0xb4, 0xa8, 0x2260, 0xc6, 0xd8,
+ 0x221e, 0xb1, 0x2264, 0x2265, 0xa5, 0xb5, 0x2202, 0x2211,
+ 0x220f, 0x3c0, 0x222b, 0xaa, 0xba, 0x3a9, 0xe6, 0xf8,
+ 0xbf, 0xa1, 0xac, 0x221a, 0x192, 0x2248, 0x2206, 0xab,
+ 0xbb, 0x2026, 0xa0, 0xc0, 0xc3, 0xd5, 0x152, 0x153,
+ 0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0xf7, 0x25ca,
+ 0xff, 0x178, 0x2044, 0x20ac, 0x2039, 0x203a, 0xfb01, 0xfb02,
+ 0x2021, 0xb7, 0x201a, 0x201e, 0x2030, 0xc2, 0xca, 0xc1,
+ 0xcb, 0xc8, 0xcd, 0xce, 0xcf, 0xcc, 0xd3, 0xd4,
+ 0xf8ff, 0xd2, 0xda, 0xdb, 0xd9, 0x131, 0x2c6, 0x2dc,
+ 0xaf, 0x2d8, 0x2d9, 0x2da, 0xb8, 0x2dd, 0x2db, 0x2c7,
+ };
+
+ if (c < 128) return c;
+ else return table[c - 128];
+}
+
+static KeySym make_dead_key(KeySym in) {
+ int i;
+
+ for (i = 0; i < sizeof (dead_keys) / sizeof (dead_keys[0]); i++)
+ if (dead_keys[i].normal == in) return dead_keys[i].dead;
+
+ return in;
+}
+
+static Bool QuartzReadSystemKeymap(darwinKeyboardInfo *info) {
+#if !defined(__LP64__) || MAC_OS_X_VERSION_MIN_REQUIRED < 1050
+ KeyboardLayoutRef key_layout;
+ int is_uchr = 1;
+#endif
+ const void *chr_data = NULL;
+ int num_keycodes = NUM_KEYCODES;
+ UInt32 keyboard_type = LMGetKbdType();
+ int i, j;
+ OSStatus err;
+ KeySym *k;
+ CFDataRef currentKeyLayoutDataRef = NULL;
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
+ TISInputSourceRef currentKeyLayoutRef = TISCopyCurrentKeyboardLayoutInputSource();
+
+ if (currentKeyLayoutRef) {
+ currentKeyLayoutDataRef = (CFDataRef )TISGetInputSourceProperty(currentKeyLayoutRef, kTISPropertyUnicodeKeyLayoutData);
+ if (currentKeyLayoutDataRef)
+ chr_data = CFDataGetBytePtr(currentKeyLayoutDataRef);
+ }
+#endif
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations" // KLGetCurrentKeyboardLayout, KLGetKeyboardLayoutProperty
+#endif
+
+#if !defined(__LP64__) || MAC_OS_X_VERSION_MIN_REQUIRED < 1050
+ if (chr_data == NULL) {
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
+ ErrorF("X11.app: Error detected in determining keyboard layout. If you are using an Apple-provided keyboard layout, please report this error at http://xquartz.macosforge.org and http://bugreport.apple.com\n");
+ ErrorF("X11.app: Debug Info: keyboard_type=%u, currentKeyLayoutRef=%p, currentKeyLayoutDataRef=%p, chr_data=%p\n",
+ (unsigned)keyboard_type, currentKeyLayoutRef, currentKeyLayoutDataRef, chr_data);
+#endif
+
+ KLGetCurrentKeyboardLayout (&key_layout);
+ KLGetKeyboardLayoutProperty (key_layout, kKLuchrData, &chr_data);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
+ if(chr_data != NULL) {
+ ErrorF("X11.app: Fallback succeeded, but this is still a bug. Please report the above information.\n");
+ }
+#endif
+ }
+
+ if (chr_data == NULL) {
+ ErrorF("X11.app: Debug Info: kKLuchrData failed, trying kKLKCHRData.\n");
+ ErrorF("If you are using a 3rd party keyboard layout, please see http://xquartz.macosforge.org/trac/ticket/154\n");
+ KLGetKeyboardLayoutProperty (key_layout, kKLKCHRData, &chr_data);
+ is_uchr = 0;
+ num_keycodes = 128;
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
+ if(chr_data != NULL) {
+ ErrorF("X11.app: Fallback succeeded, but this is still a bug. Please report the above information.\n");
+ }
+#endif
+ }
+#endif
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
+ if(currentKeyLayoutRef)
+ CFRelease(currentKeyLayoutRef);
+#endif
+
+ if (chr_data == NULL) {
+ ErrorF ( "Couldn't get uchr or kchr resource\n");
+ return FALSE;
+ }
+
+ /* Scan the keycode range for the Unicode character that each
+ key produces in the four shift states. Then convert that to
+ an X11 keysym (which may just the bit that says "this is
+ Unicode" if it can't find the real symbol.) */
+
+ /* KeyTranslate is not available on 64-bit platforms; UCKeyTranslate
+ must be used instead. */
+
+ for (i = 0; i < num_keycodes; i++) {
+ static const int mods[4] = {0, MOD_SHIFT, MOD_OPTION,
+ MOD_OPTION | MOD_SHIFT};
+
+ k = info->keyMap + i * GLYPHS_PER_KEY;
+
+ for (j = 0; j < 4; j++) {
+#if !defined(__LP64__) || MAC_OS_X_VERSION_MIN_REQUIRED < 1050
+ if (is_uchr) {
+#endif
+ UniChar s[8];
+ UniCharCount len;
+ UInt32 dead_key_state = 0, extra_dead = 0;
+
+ err = UCKeyTranslate (chr_data, i, kUCKeyActionDown,
+ mods[j] >> 8, keyboard_type, 0,
+ &dead_key_state, 8, &len, s);
+ if (err != noErr) continue;
+
+ if (len == 0 && dead_key_state != 0) {
+ /* Found a dead key. Work out which one it is, but
+ remembering that it's dead. */
+ err = UCKeyTranslate (chr_data, i, kUCKeyActionDown,
+ mods[j] >> 8, keyboard_type,
+ kUCKeyTranslateNoDeadKeysMask,
+ &extra_dead, 8, &len, s);
+ if (err != noErr) continue;
+ }
+
+ /* Not sure why 0x0010 is there.
+ * 0x0000 - <rdar://problem/7793566> 'Unicode Hex Input' ...
+ */
+ if (len > 0 && s[0] != 0x0010 && s[0] != 0x0000) {
+ k[j] = ucs2keysym (s[0]);
+ if (dead_key_state != 0) k[j] = make_dead_key (k[j]);
+ }
+#if !defined(__LP64__) || MAC_OS_X_VERSION_MIN_REQUIRED < 1050
+ } else { // kchr
+ UInt32 c, state = 0, state2 = 0;
+ UInt16 code;
+
+ code = i | mods[j];
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations" // KeyTranslate
+#endif
+
+ c = KeyTranslate (chr_data, code, &state);
+
+ /* Dead keys are only processed on key-down, so ask
+ to translate those events. When we find a dead key,
+ translating the matching key up event will give
+ us the actual dead character. */
+
+ if (state != 0)
+ c = KeyTranslate (chr_data, code | 128, &state2);
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
+ /* Characters seem to be in MacRoman encoding. */
+
+ if (c != 0 && c != 0x0010) {
+ k[j] = ucs2keysym (macroman2ucs (c & 255));
+
+ if (state != 0) k[j] = make_dead_key (k[j]);
+ }
+ }
+#endif
+ }
+
+ if (k[3] == k[2]) k[3] = NoSymbol;
+ if (k[1] == k[0]) k[1] = NoSymbol;
+ if (k[0] == k[2] && k[1] == k[3]) k[2] = k[3] = NoSymbol;
+ if (k[3] == k[0] && k[2] == k[1] && k[2] == NoSymbol) k[3] = NoSymbol;
+ }
+
+#if HACK_MISSING
+ /* Fix up some things that are normally missing.. */
+
+ for (i = 0; i < sizeof (known_keys) / sizeof (known_keys[0]); i++) {
+ k = info->keyMap + known_keys[i].keycode * GLYPHS_PER_KEY;
+
+ if ( k[0] == NoSymbol && k[1] == NoSymbol
+ && k[2] == NoSymbol && k[3] == NoSymbol)
+ k[0] = known_keys[i].keysym;
+ }
+#endif
+
+#if HACK_KEYPAD
+ /* And some more things. We find the right symbols for the numeric
+ keypad, but not the KP_ keysyms. So try to convert known keycodes. */
+ for (i = 0; i < sizeof (known_numeric_keys) / sizeof (known_numeric_keys[0]); i++) {
+ k = info->keyMap + known_numeric_keys[i].keycode * GLYPHS_PER_KEY;
+
+ if (k[0] == known_numeric_keys[i].normal)
+ k[0] = known_numeric_keys[i].keypad;
+ }
+#endif
+
+#if HACK_BLACKLIST
+ for (i = 0; i < sizeof (keycode_blacklist) / sizeof (keycode_blacklist[0]); i++) {
+ k = info->keyMap + keycode_blacklist[i] * GLYPHS_PER_KEY;
+ k[0] = k[1] = k[2] = k[3] = NoSymbol;
+ }
+#endif
+
+ DarwinBuildModifierMaps(info);
+
+ return TRUE;
+}
+
+Bool QuartsResyncKeymap(Bool sendDDXEvent) {
+ Bool retval;
+ /* Update keyInfo */
+ pthread_mutex_lock(&keyInfo_mutex);
+ memset(keyInfo.keyMap, 0, sizeof(keyInfo.keyMap));
+ retval = QuartzReadSystemKeymap(&keyInfo);
+ pthread_mutex_unlock(&keyInfo_mutex);
+
+ /* Tell server thread to deal with new keyInfo */
+ if(sendDDXEvent)
+ DarwinSendDDXEvent(kXquartzReloadKeymap, 0);
+
+ return retval;
+}
diff --git a/xorg-server/hw/xquartz/quartzKeyboard.h b/xorg-server/hw/xquartz/quartzKeyboard.h index 1151a0035..bb5e84597 100644 --- a/xorg-server/hw/xquartz/quartzKeyboard.h +++ b/xorg-server/hw/xquartz/quartzKeyboard.h @@ -1,58 +1,56 @@ -/* - * Copyright (c) 2003-2004 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, 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. - * - * Except as contained in this notice, the name(s) of the above copyright - * holders shall not be used in advertising or otherwise to promote the sale, - * use or other dealings in this Software without prior written authorization. - */ - -#ifndef QUARTZ_KEYBOARD_H -#define QUARTZ_KEYBOARD_H 1 - -#define XK_TECHNICAL // needed to get XK_Escape -#define XK_PUBLISHING -#include "X11/keysym.h" -#include "inputstr.h" - -#include <pthread.h> - -// Each key can generate 4 glyphs. They are, in order: -// unshifted, shifted, modeswitch unshifted, modeswitch shifted -#define GLYPHS_PER_KEY 4 -#define NUM_KEYCODES 248 // NX_NUMKEYCODES might be better -#define MIN_KEYCODE XkbMinLegalKeyCode // unfortunately, this isn't 0... -#define MAX_KEYCODE NUM_KEYCODES + MIN_KEYCODE - 1 - -/* These functions need to be implemented by Xquartz, XDarwin, etc. */ -Bool QuartsResyncKeymap(Bool sendDDXEvent); - -/* Provided for darwinEvents.c */ -void DarwinKeyboardReloadHandler(void); -int DarwinModifierNXKeycodeToNXKey(unsigned char keycode, int *outSide); -int DarwinModifierNXKeyToNXKeycode(int key, int side); -int DarwinModifierNXKeyToNXMask(int key); -int DarwinModifierNXMaskToNXKey(int mask); -int DarwinModifierStringToNXMask(const char *string, int separatelr); - -/* Provided for darwin.c */ -void DarwinKeyboardInit(DeviceIntPtr pDev); - -#endif /* QUARTZ_KEYBOARD_H */ +/*
+ * Copyright (c) 2003-2004 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, 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.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written authorization.
+ */
+
+#ifndef QUARTZ_KEYBOARD_H
+#define QUARTZ_KEYBOARD_H 1
+
+#define XK_TECHNICAL // needed to get XK_Escape
+#define XK_PUBLISHING
+#include "X11/keysym.h"
+#include "inputstr.h"
+
+// Each key can generate 4 glyphs. They are, in order:
+// unshifted, shifted, modeswitch unshifted, modeswitch shifted
+#define GLYPHS_PER_KEY 4
+#define NUM_KEYCODES 248 // NX_NUMKEYCODES might be better
+#define MIN_KEYCODE XkbMinLegalKeyCode // unfortunately, this isn't 0...
+#define MAX_KEYCODE NUM_KEYCODES + MIN_KEYCODE - 1
+
+/* These functions need to be implemented by Xquartz, XDarwin, etc. */
+Bool QuartsResyncKeymap(Bool sendDDXEvent);
+
+/* Provided for darwinEvents.c */
+void DarwinKeyboardReloadHandler(void);
+int DarwinModifierNXKeycodeToNXKey(unsigned char keycode, int *outSide);
+int DarwinModifierNXKeyToNXKeycode(int key, int side);
+int DarwinModifierNXKeyToNXMask(int key);
+int DarwinModifierNXMaskToNXKey(int mask);
+int DarwinModifierStringToNXMask(const char *string, int separatelr);
+
+/* Provided for darwin.c */
+void DarwinKeyboardInit(DeviceIntPtr pDev);
+
+#endif /* QUARTZ_KEYBOARD_H */
diff --git a/xorg-server/hw/xquartz/quartzStartup.c b/xorg-server/hw/xquartz/quartzStartup.c index 36c8182ae..bc1aa4f68 100644 --- a/xorg-server/hw/xquartz/quartzStartup.c +++ b/xorg-server/hw/xquartz/quartzStartup.c @@ -1,121 +1,118 @@ -/************************************************************** - * - * Startup code for the Quartz Darwin X Server - * - * Copyright (c) 2001-2004 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, 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. - * - * Except as contained in this notice, the name(s) of the above copyright - * holders shall not be used in advertising or otherwise to promote the sale, - * use or other dealings in this Software without prior written authorization. - */ - -#include "sanitizedCarbon.h" - -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> -#endif - -#include <fcntl.h> -#include <unistd.h> -#include <CoreFoundation/CoreFoundation.h> -#include "quartzCommon.h" -#include "X11Controller.h" -#include "darwin.h" -#include "darwinEvents.h" -#include "quartz.h" -#include "opaque.h" -#include "micmap.h" - -#include <assert.h> - -#include <pthread.h> - -int dix_main(int argc, char **argv, char **envp); - -struct arg { - int argc; - char **argv; - char **envp; -}; - -static void server_thread (void *arg) { - struct arg args = *((struct arg *)arg); - free(arg); - exit (dix_main(args.argc, args.argv, args.envp)); -} - -static pthread_t create_thread (void *func, void *arg) { - pthread_attr_t attr; - pthread_t tid; - - pthread_attr_init (&attr); - pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM); - pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); - pthread_create (&tid, &attr, func, arg); - pthread_attr_destroy (&attr); - - return tid; -} - -void QuartzInitServer(int argc, char **argv, char **envp) { - struct arg *args = (struct arg*)malloc(sizeof(struct arg)); - if(!args) - FatalError("Could not allocate memory.\n"); - - args->argc = argc; - args->argv = argv; - args->envp = envp; - - APPKIT_THREAD_ID = pthread_self(); - SERVER_THREAD_ID = create_thread(server_thread, args); - - if (!SERVER_THREAD_ID) { - FatalError("can't create secondary thread\n"); - } -} - -int server_main(int argc, char **argv, char **envp) { - int i; - int fd[2]; - - /* Unset CFProcessPath, so our children don't inherit this kludge we need - * to load our nib. If an xterm gets this set, then it fails to - * 'open hi.txt' properly. - */ - unsetenv("CFProcessPath"); - - // Make a pipe to pass events - assert( pipe(fd) == 0 ); - darwinEventReadFD = fd[0]; - darwinEventWriteFD = fd[1]; - fcntl(darwinEventReadFD, F_SETFL, O_NONBLOCK); - - for (i = 1; i < argc; i++) { - // Display version info without starting Mac OS X UI if requested - if (!strcmp( argv[i], "-showconfig" ) || !strcmp( argv[i], "-version" )) { - DarwinPrintBanner(); - exit(0); - } - } - - X11ControllerMain(argc, argv, envp); - exit(0); -} +/**************************************************************
+ *
+ * Startup code for the Quartz Darwin X Server
+ *
+ * Copyright (c) 2001-2004 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, 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.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written authorization.
+ */
+
+#include "sanitizedCarbon.h"
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include "quartzCommon.h"
+#include "X11Controller.h"
+#include "darwin.h"
+#include "darwinEvents.h"
+#include "quartz.h"
+#include "opaque.h"
+#include "micmap.h"
+
+#include <assert.h>
+
+#include <pthread.h>
+
+int dix_main(int argc, char **argv, char **envp);
+
+struct arg {
+ int argc;
+ char **argv;
+ char **envp;
+};
+
+static void server_thread (void *arg) {
+ struct arg args = *((struct arg *)arg);
+ free(arg);
+ exit (dix_main(args.argc, args.argv, args.envp));
+}
+
+static pthread_t create_thread (void *func, void *arg) {
+ pthread_attr_t attr;
+ pthread_t tid;
+
+ pthread_attr_init (&attr);
+ pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM);
+ pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
+ pthread_create (&tid, &attr, func, arg);
+ pthread_attr_destroy (&attr);
+
+ return tid;
+}
+
+void QuartzInitServer(int argc, char **argv, char **envp) {
+ struct arg *args = (struct arg*)malloc(sizeof(struct arg));
+ if(!args)
+ FatalError("Could not allocate memory.\n");
+
+ args->argc = argc;
+ args->argv = argv;
+ args->envp = envp;
+
+ if (!create_thread(server_thread, args)) {
+ FatalError("can't create secondary thread\n");
+ }
+}
+
+int server_main(int argc, char **argv, char **envp) {
+ int i;
+ int fd[2];
+
+ /* Unset CFProcessPath, so our children don't inherit this kludge we need
+ * to load our nib. If an xterm gets this set, then it fails to
+ * 'open hi.txt' properly.
+ */
+ unsetenv("CFProcessPath");
+
+ // Make a pipe to pass events
+ assert( pipe(fd) == 0 );
+ darwinEventReadFD = fd[0];
+ darwinEventWriteFD = fd[1];
+ fcntl(darwinEventReadFD, F_SETFL, O_NONBLOCK);
+
+ for (i = 1; i < argc; i++) {
+ // Display version info without starting Mac OS X UI if requested
+ if (!strcmp( argv[i], "-showconfig" ) || !strcmp( argv[i], "-version" )) {
+ DarwinPrintBanner();
+ exit(0);
+ }
+ }
+
+ X11ControllerMain(argc, argv, envp);
+ exit(0);
+}
diff --git a/xorg-server/hw/xquartz/threadSafety.c b/xorg-server/hw/xquartz/threadSafety.c deleted file mode 100644 index 85f85bd0a..000000000 --- a/xorg-server/hw/xquartz/threadSafety.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2008 Apple, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice 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. - * - * Except as contained in this notice, the name(s) of the above copyright - * holders shall not be used in advertising or otherwise to promote the sale, - * use or other dealings in this Software without prior written authorization. - */ - -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> -#endif - -#include "threadSafety.h" -#include "os.h" - -pthread_t APPKIT_THREAD_ID; -pthread_t SERVER_THREAD_ID; - -#include <AvailabilityMacros.h> - -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 -#include <execinfo.h> - -void spewCallStack(void) { - void* callstack[128]; - int i, frames = backtrace(callstack, 128); - char** strs = backtrace_symbols(callstack, frames); - - for (i = 0; i < frames; ++i) { - ErrorF("%s\n", strs[i]); - } - - free(strs); -} -#else -void spewCallStack(void) { - return; -} -#endif - -void _threadSafetyAssert(pthread_t tid, const char *file, const char *fun, int line) { - if(pthread_equal(pthread_self(), tid)) - return; - - /* NOOOO! */ - ErrorF("Thread Assertion Failed: self=%s, expected=%s\n%s:%s:%d\n", - threadSafetyID(pthread_self()), threadSafetyID(tid), - file, fun, line); - spewCallStack(); -} - -const char *threadSafetyID(pthread_t tid) { - if(pthread_equal(tid, APPKIT_THREAD_ID)) { - return "Appkit Thread"; - } else if(pthread_equal(tid, SERVER_THREAD_ID)) { - return "Xserver Thread"; - } else { - return "Unknown Thread"; - } -} diff --git a/xorg-server/hw/xquartz/threadSafety.h b/xorg-server/hw/xquartz/threadSafety.h deleted file mode 100644 index 48602567b..000000000 --- a/xorg-server/hw/xquartz/threadSafety.h +++ /dev/null @@ -1,56 +0,0 @@ -/*
- * Copyright (C) 2008 Apple, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice 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.
- *
- * Except as contained in this notice, the name(s) of the above copyright
- * holders shall not be used in advertising or otherwise to promote the sale,
- * use or other dealings in this Software without prior written authorization.
- */
-
-#ifndef _XQ_THREAD_SAFETY_H_
-#define _XQ_THREAD_SAFETY_H_
-
-#define DEBUG_THREADS 1
-
-#include <pthread.h>
-
-extern pthread_t APPKIT_THREAD_ID;
-extern pthread_t SERVER_THREAD_ID;
-
-/* Dump the call stack */
-void spewCallStack(void);
-
-/* Print message to ErrorF if we're in the wrong thread */
-void _threadSafetyAssert(pthread_t tid, const char *file, const char *fun, int line);
-
-/* Get a string that identifies our thread nicely */
-const char *threadSafetyID(pthread_t tid);
-
-#define threadSafetyAssert(tid) _threadSafetyAssert(tid, __FILE__, __FUNCTION__, __LINE__)
-
-#ifdef DEBUG_THREADS
-#define TA_APPKIT() threadSafetyAssert(APPKIT_THREAD_ID)
-#define TA_SERVER() threadSafetyAssert(SERVER_THREAD_ID)
-#else
-#define TA_SERVER()
-#define TA_APPKIT()
-#endif
-
-#endif /* _XQ_THREAD_SAFETY_H_ */
diff --git a/xorg-server/hw/xquartz/xpr/dri.c b/xorg-server/hw/xquartz/xpr/dri.c index 7b730df8e..cdfe13622 100644 --- a/xorg-server/hw/xquartz/xpr/dri.c +++ b/xorg-server/hw/xquartz/xpr/dri.c @@ -562,7 +562,6 @@ DRIWindowExposures(WindowPtr pWin, RegionPtr prgn, RegionPtr bsreg) (*pScreen->WindowExposures)(pWin, prgn, bsreg);
- pDRIPriv->wrap.WindowExposures = pScreen->WindowExposures;
pScreen->WindowExposures = DRIWindowExposures;
}
@@ -587,7 +586,6 @@ DRICopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) (*pScreen->CopyWindow)(pWin, ptOldOrg, prgnSrc);
/* rewrap */
- pDRIPriv->wrap.CopyWindow = pScreen->CopyWindow;
pScreen->CopyWindow = DRICopyWindow;
}
@@ -605,7 +603,6 @@ DRIValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind) returnValue = (*pScreen->ValidateTree)(pParent, pChild, kind);
/* rewrap */
- pDRIPriv->wrap.ValidateTree = pScreen->ValidateTree;
pScreen->ValidateTree = DRIValidateTree;
return returnValue;
@@ -632,7 +629,6 @@ DRIPostValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind) (*pScreen->PostValidateTree)(pParent, pChild, kind);
/* rewrap */
- pDRIPriv->wrap.PostValidateTree = pScreen->PostValidateTree;
pScreen->PostValidateTree = DRIPostValidateTree;
}
}
@@ -653,7 +649,6 @@ DRIClipNotify(WindowPtr pWin, int dx, int dy) (*pScreen->ClipNotify)(pWin, dx, dy);
- pDRIPriv->wrap.ClipNotify = pScreen->ClipNotify;
pScreen->ClipNotify = DRIClipNotify;
}
}
diff --git a/xorg-server/hw/xquartz/xpr/xpr.h b/xorg-server/hw/xquartz/xpr/xpr.h index af1a90ca0..ea06b7eeb 100644 --- a/xorg-server/hw/xquartz/xpr/xpr.h +++ b/xorg-server/hw/xquartz/xpr/xpr.h @@ -1,64 +1,64 @@ -/* - * Xplugin rootless implementation - * - * 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, 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. - * - * Except as contained in this notice, the name(s) of the above copyright - * holders shall not be used in advertising or otherwise to promote the sale, - * use or other dealings in this Software without prior written authorization. - */ - -#ifndef XPR_H -#define XPR_H - -#include "windowstr.h" -#include "screenint.h" -#include <Xplugin.h> - -Bool QuartzModeBundleInit(void); - -void AppleDRIExtensionInit(void); -void xprAppleWMInit(void); -Bool xprInit(ScreenPtr pScreen); -Bool xprIsX11Window(void *nsWindow, int windowNumber); -WindowPtr xprGetXWindow(xp_window_id wid); - -void xprHideWindows(Bool hide); - -Bool QuartzInitCursor(ScreenPtr pScreen); -void QuartzSuspendXCursor(ScreenPtr pScreen); -void QuartzResumeXCursor(ScreenPtr pScreen); - -/* If we are rooted, we need the root window and desktop levels to be below - * the menubar (24) but above native windows. Normal window level is 0. - * Floating window level is 3. The rest are filled in as appropriate. - * See CGWindowLevel.h - */ - -#include <X11/extensions/applewmconst.h> -static const int normal_window_levels[AppleWMNumWindowLevels+1] = { -0, 3, 4, 5, INT_MIN + 30, INT_MIN + 29, -}; -static const int rooted_window_levels[AppleWMNumWindowLevels+1] = { -20, 21, 22, 23, 19, 18, -}; - -#endif /* XPR_H */ +/*
+ * Xplugin rootless implementation
+ *
+ * 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, 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.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written authorization.
+ */
+
+#ifndef XPR_H
+#define XPR_H
+
+#include "windowstr.h"
+#include "screenint.h"
+#include <Xplugin.h>
+
+Bool QuartzModeBundleInit(void);
+
+void AppleDRIExtensionInit(void);
+void xprAppleWMInit(void);
+Bool xprInit(ScreenPtr pScreen);
+Bool xprIsX11Window(int windowNumber);
+WindowPtr xprGetXWindow(xp_window_id wid);
+
+void xprHideWindows(Bool hide);
+
+Bool QuartzInitCursor(ScreenPtr pScreen);
+void QuartzSuspendXCursor(ScreenPtr pScreen);
+void QuartzResumeXCursor(ScreenPtr pScreen);
+
+/* If we are rooted, we need the root window and desktop levels to be below
+ * the menubar (24) but above native windows. Normal window level is 0.
+ * Floating window level is 3. The rest are filled in as appropriate.
+ * See CGWindowLevel.h
+ */
+
+#include <X11/extensions/applewmconst.h>
+static const int normal_window_levels[AppleWMNumWindowLevels+1] = {
+0, 3, 4, 5, INT_MIN + 30, INT_MIN + 29,
+};
+static const int rooted_window_levels[AppleWMNumWindowLevels+1] = {
+20, 21, 22, 23, 19, 18,
+};
+
+#endif /* XPR_H */
diff --git a/xorg-server/hw/xquartz/xpr/xprAppleWM.c b/xorg-server/hw/xquartz/xpr/xprAppleWM.c index 1e99a07dc..6f501e201 100644 --- a/xorg-server/hw/xquartz/xpr/xprAppleWM.c +++ b/xorg-server/hw/xquartz/xpr/xprAppleWM.c @@ -114,8 +114,8 @@ static int xprAttachTransient(WindowPtr pWinChild, WindowPtr pWinParent) { static int xprFrameDraw(
WindowPtr pWin,
- int class,
- unsigned int attr,
+ xp_frame_class class,
+ xp_frame_attr attr,
const BoxRec *outer,
const BoxRec *inner,
unsigned int title_len,
diff --git a/xorg-server/hw/xquartz/xpr/xprEvent.c b/xorg-server/hw/xquartz/xpr/xprEvent.c index 38952b091..0ea6540f0 100644 --- a/xorg-server/hw/xquartz/xpr/xprEvent.c +++ b/xorg-server/hw/xquartz/xpr/xprEvent.c @@ -57,8 +57,6 @@ #include "xprEvent.h"
Bool QuartzModeEventHandler(int screenNum, XQuartzEvent *e, DeviceIntPtr dev) {
- TA_SERVER();
-
switch(e->subtype) {
case kXquartzWindowState:
DEBUG_LOG("kXquartzWindowState\n");
diff --git a/xorg-server/hw/xquartz/xpr/xprFrame.c b/xorg-server/hw/xquartz/xpr/xprFrame.c index cddec5ce2..e88019c2d 100644 --- a/xorg-server/hw/xquartz/xpr/xprFrame.c +++ b/xorg-server/hw/xquartz/xpr/xprFrame.c @@ -1,7 +1,7 @@ /*
* Xplugin rootless implementation frame functions
*
- * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2002-2011 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
@@ -35,7 +35,6 @@ #include "rootlessCommon.h"
#include <Xplugin.h>
#include "x-hash.h"
-#include "x-list.h"
#include "applewmExt.h"
#include "propertyst.h"
@@ -44,9 +43,11 @@ #include "windowstr.h"
#include "quartz.h"
-#include "threadSafety.h"
-
+#ifdef HAVE_LIBDISPATCH
+#include <dispatch/dispatch.h>
+#else
#include <pthread.h>
+#endif
#define DEFINE_ATOM_HELPER(func,atom_name) \
static Atom func (void) { \
@@ -63,7 +64,13 @@ DEFINE_ATOM_HELPER(xa_native_window_id, "_NATIVE_WINDOW_ID") /* Maps xp_window_id -> RootlessWindowRec */
static x_hash_table *window_hash;
+
+/* Need to guard window_hash since xprIsX11Window can be called from any thread. */
+#ifdef HAVE_LIBDISPATCH
+static dispatch_queue_t window_hash_serial_q;
+#else
static pthread_mutex_t window_hash_mutex;
+#endif
/* Prototypes for static functions */
static Bool xprCreateFrame(RootlessWindowPtr pFrame, ScreenPtr pScreen,
@@ -93,8 +100,6 @@ static inline xp_error xprConfigureWindow(xp_window_id id, unsigned int mask,
const xp_window_changes *values)
{
- TA_SERVER();
-
return xp_configure_window(id, mask, values);
}
@@ -106,8 +111,6 @@ xprSetNativeProperty(RootlessWindowPtr pFrame) unsigned int native_id;
long data;
- TA_SERVER();
-
err = xp_get_native_window(x_cvt_vptr_to_uint(pFrame->wid), &native_id);
if (err == Success)
{
@@ -137,8 +140,6 @@ xprCreateFrame(RootlessWindowPtr pFrame, ScreenPtr pScreen, unsigned int mask = 0;
xp_error err;
- TA_SERVER();
-
wc.x = newX;
wc.y = newY;
wc.width = pFrame->width;
@@ -186,15 +187,15 @@ xprCreateFrame(RootlessWindowPtr pFrame, ScreenPtr pScreen, return FALSE;
}
- if (window_hash == NULL)
- {
- window_hash = x_hash_table_new(NULL, NULL, NULL, NULL);
- pthread_mutex_init(&window_hash_mutex, NULL);
- }
-
+#ifdef HAVE_LIBDISPATCH
+ dispatch_async(window_hash_serial_q, ^{
+ x_hash_table_insert(window_hash, pFrame->wid, pFrame);
+ });
+#else
pthread_mutex_lock(&window_hash_mutex);
x_hash_table_insert(window_hash, pFrame->wid, pFrame);
pthread_mutex_unlock(&window_hash_mutex);
+#endif
xprSetNativeProperty(pFrame);
@@ -209,11 +210,16 @@ static void xprDestroyFrame(RootlessFrameID wid)
{
xp_error err;
- TA_SERVER();
-
+
+#ifdef HAVE_LIBDISPATCH
+ dispatch_async(window_hash_serial_q, ^{
+ x_hash_table_remove(window_hash, wid);
+ });
+#else
pthread_mutex_lock(&window_hash_mutex);
x_hash_table_remove(window_hash, wid);
pthread_mutex_unlock(&window_hash_mutex);
+#endif
err = xp_destroy_window(x_cvt_vptr_to_uint(wid));
if (err != Success)
@@ -229,8 +235,6 @@ xprMoveFrame(RootlessFrameID wid, ScreenPtr pScreen, int newX, int newY) {
xp_window_changes wc;
- TA_SERVER();
-
wc.x = newX;
wc.y = newY;
// ErrorF("xprMoveFrame(%d, %p, %d, %d)\n", wid, pScreen, newX, newY);
@@ -248,8 +252,6 @@ xprResizeFrame(RootlessFrameID wid, ScreenPtr pScreen, {
xp_window_changes wc;
- TA_SERVER();
-
wc.x = newX;
wc.y = newY;
wc.width = newW;
@@ -269,9 +271,11 @@ xprResizeFrame(RootlessFrameID wid, ScreenPtr pScreen, static void xprRestackFrame(RootlessFrameID wid, RootlessFrameID nextWid) {
xp_window_changes wc;
unsigned int mask = XP_STACKING;
+#ifdef HAVE_LIBDISPATCH
+ __block
+#endif
+ RootlessWindowRec *winRec;
- TA_SERVER();
-
/* Stack frame below nextWid it if it exists, or raise
frame above everything otherwise. */
@@ -283,18 +287,24 @@ static void xprRestackFrame(RootlessFrameID wid, RootlessFrameID nextWid) { wc.sibling = x_cvt_vptr_to_uint(nextWid);
}
- if(window_hash) {
- RootlessWindowRec *winRec = x_hash_table_lookup(window_hash, wid, NULL);
-
- if(winRec) {
- if(XQuartzIsRootless)
- wc.window_level = normal_window_levels[winRec->level];
- else if(XQuartzShieldingWindowLevel)
- wc.window_level = XQuartzShieldingWindowLevel + 1;
- else
- wc.window_level = rooted_window_levels[winRec->level];
- mask |= XP_WINDOW_LEVEL;
- }
+#ifdef HAVE_LIBDISPATCH
+ dispatch_sync(window_hash_serial_q, ^{
+ winRec = x_hash_table_lookup(window_hash, wid, NULL);
+ });
+#else
+ pthread_mutex_lock(&window_hash_mutex);
+ winRec = x_hash_table_lookup(window_hash, wid, NULL);
+ pthread_mutex_unlock(&window_hash_mutex);
+#endif
+
+ if(winRec) {
+ if(XQuartzIsRootless)
+ wc.window_level = normal_window_levels[winRec->level];
+ else if(XQuartzShieldingWindowLevel)
+ wc.window_level = XQuartzShieldingWindowLevel + 1;
+ else
+ wc.window_level = rooted_window_levels[winRec->level];
+ mask |= XP_WINDOW_LEVEL;
}
xprConfigureWindow(x_cvt_vptr_to_uint(wid), mask, &wc);
@@ -309,8 +319,6 @@ xprReshapeFrame(RootlessFrameID wid, RegionPtr pShape) {
xp_window_changes wc;
- TA_SERVER();
-
if (pShape != NULL)
{
wc.shape_nrects = RegionNumRects(pShape);
@@ -336,8 +344,6 @@ xprUnmapFrame(RootlessFrameID wid) {
xp_window_changes wc;
- TA_SERVER();
-
wc.stack_mode = XP_UNMAPPED;
wc.sibling = 0;
@@ -356,8 +362,6 @@ xprStartDrawing(RootlessFrameID wid, char **pixelData, int *bytesPerRow) unsigned int rowbytes[2];
xp_error err;
- TA_SERVER();
-
err = xp_lock_window(x_cvt_vptr_to_uint(wid), NULL, NULL, data, rowbytes, NULL);
if (err != Success)
FatalError("Could not lock window %i for drawing.", (int)x_cvt_vptr_to_uint(wid));
@@ -374,8 +378,7 @@ static void xprStopDrawing(RootlessFrameID wid, Bool flush)
{
xp_error err;
- TA_SERVER();
-
+
err = xp_unlock_window(x_cvt_vptr_to_uint(wid), flush);
if(err != Success)
FatalError("Could not unlock window %i after drawing.", (int)x_cvt_vptr_to_uint(wid));
@@ -388,8 +391,6 @@ xprStopDrawing(RootlessFrameID wid, Bool flush) static void
xprUpdateRegion(RootlessFrameID wid, RegionPtr pDamage)
{
- TA_SERVER();
-
xp_flush_window(x_cvt_vptr_to_uint(wid));
}
@@ -401,8 +402,6 @@ static void xprDamageRects(RootlessFrameID wid, int nrects, const BoxRec *rects,
int shift_x, int shift_y)
{
- TA_SERVER();
-
xp_mark_window(x_cvt_vptr_to_uint(wid), nrects, rects, shift_x, shift_y);
}
@@ -416,8 +415,6 @@ xprSwitchWindow(RootlessWindowPtr pFrame, WindowPtr oldWin) {
DeleteProperty(serverClient, oldWin, xa_native_window_id());
- TA_SERVER();
-
xprSetNativeProperty(pFrame);
}
@@ -429,8 +426,6 @@ static Bool xprDoReorderWindow(RootlessWindowPtr pFrame) {
WindowPtr pWin = pFrame->win;
- TA_SERVER();
-
return AppleWMDoReorderWindow(pWin);
}
@@ -443,8 +438,6 @@ static void xprCopyWindow(RootlessFrameID wid, int dstNrects, const BoxRec *dstRects,
int dx, int dy)
{
- TA_SERVER();
-
xp_copy_window(x_cvt_vptr_to_uint(wid), x_cvt_vptr_to_uint(wid),
dstNrects, dstRects, dx, dy);
}
@@ -479,11 +472,16 @@ xprInit(ScreenPtr pScreen) {
RootlessInit(pScreen, &xprRootlessProcs);
- TA_SERVER();
-
rootless_CopyBytes_threshold = xp_copy_bytes_threshold;
rootless_CopyWindow_threshold = xp_scroll_area_threshold;
+ assert((window_hash = x_hash_table_new(NULL, NULL, NULL, NULL)));
+#ifdef HAVE_LIBDISPATCH
+ assert((window_hash_serial_q = dispatch_queue_create(BUNDLE_ID_PREFIX".X11.xpr_window_hash", NULL)));
+#else
+ assert(0 == pthread_mutex_init(&window_hash_mutex, NULL));
+#endif
+
return TRUE;
}
@@ -495,73 +493,36 @@ xprInit(ScreenPtr pScreen) WindowPtr
xprGetXWindow(xp_window_id wid)
{
+#ifdef HAVE_LIBDISPATCH
+ RootlessWindowRec *winRec __block;
+ dispatch_sync(window_hash_serial_q, ^{
+ winRec = x_hash_table_lookup(window_hash, x_cvt_uint_to_vptr(wid), NULL);
+ });
+#else
RootlessWindowRec *winRec;
-
- if (window_hash == NULL)
- return NULL;
-
- winRec = x_hash_table_lookup(window_hash, x_cvt_uint_to_vptr(wid), NULL);
-
- return winRec != NULL ? winRec->win : NULL;
-}
-
-#ifdef UNUSED_CODE
-/*
- * Given the id of a physical window, try to find the top-level (or root)
- * X window that it represents.
- */
-WindowPtr
-xprGetXWindowFromAppKit(int windowNumber)
-{
- RootlessWindowRec *winRec;
- Bool ret;
- xp_window_id wid;
-
- if (window_hash == NULL)
- return FALSE;
-
- /* need to lock, since this function can be called by any thread */
-
pthread_mutex_lock(&window_hash_mutex);
-
- if (xp_lookup_native_window(windowNumber, &wid))
- ret = xprGetXWindow(wid) != NULL;
- else
- ret = FALSE;
-
- pthread_mutex_unlock(&window_hash_mutex);
-
- if (!ret) return NULL;
winRec = x_hash_table_lookup(window_hash, x_cvt_uint_to_vptr(wid), NULL);
+ pthread_mutex_unlock(&window_hash_mutex);
+#endif
return winRec != NULL ? winRec->win : NULL;
}
-#endif
/*
* The windowNumber is an AppKit window number. Returns TRUE if xpr is
* displaying a window with that number.
*/
Bool
-xprIsX11Window(void *nsWindow, int windowNumber)
+xprIsX11Window(int windowNumber)
{
Bool ret;
xp_window_id wid;
- if (window_hash == NULL)
- return FALSE;
-
- /* need to lock, since this function can be called by any thread */
-
- pthread_mutex_lock(&window_hash_mutex);
-
if (xp_lookup_native_window(windowNumber, &wid))
ret = xprGetXWindow(wid) != NULL;
else
ret = FALSE;
- pthread_mutex_unlock(&window_hash_mutex);
-
return ret;
}
@@ -578,8 +539,6 @@ xprHideWindows(Bool hide) int screen;
WindowPtr pRoot, pWin;
- TA_SERVER();
-
for (screen = 0; screen < screenInfo.numScreens; screen++) {
RootlessFrameID prevWid = NULL;
pRoot = screenInfo.screens[screen]->root;
diff --git a/xorg-server/hw/xwin/InitOutput.c b/xorg-server/hw/xwin/InitOutput.c index 725011ea5..ae56c51fa 100644 --- a/xorg-server/hw/xwin/InitOutput.c +++ b/xorg-server/hw/xwin/InitOutput.c @@ -1,1120 +1,1120 @@ - -/* - -Copyright 1993, 1998 The Open Group -Copyright (C) Colin Harrison 2005-2008 - -Permission to use, copy, modify, distribute, and sell this software and its -documentation for any purpose is hereby granted without fee, provided that -the above copyright notice appear in all copies and that both that -copyright notice and this permission notice appear in supporting -documentation. - -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 OPEN GROUP 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 Open Group 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 Open Group. - -*/ - -#ifdef HAVE_XWIN_CONFIG_H -#include <xwin-config.h> -#endif -#include "win.h" -#include "winmsg.h" -#include "winconfig.h" -#include "winprefs.h" -#ifdef DPMSExtension -#include "dpmsproc.h" -#endif -#include <locale.h> -#ifdef __CYGWIN__ -#include <mntent.h> -#endif -#if defined(WIN32) -#include "xkbsrv.h" -#endif -#ifdef RELOCATE_PROJECTROOT -#undef Status -#include <shlobj.h> -typedef HRESULT (__stdcall * SHGETFOLDERPATHPROC)( - HWND hwndOwner, - int nFolder, - HANDLE hToken, - DWORD dwFlags, - LPSTR pszPath -); -#endif - -/* - * References to external symbols - */ -#ifdef XWIN_CLIPBOARD -extern Bool g_fUnicodeClipboard; -extern Bool g_fClipboardLaunched; -extern Bool g_fClipboardStarted; -extern pthread_t g_ptClipboardProc; -extern HWND g_hwndClipboard; -extern Bool g_fClipboard; -#endif - - -/* - module handle for dynamically loaded comctl32 library -*/ -static HMODULE g_hmodCommonControls = NULL; - -/* - * Function prototypes - */ - -#ifdef XWIN_CLIPBOARD -static void -winClipboardShutdown (void); -#endif - -#if defined(DDXOSVERRORF) -void -OsVendorVErrorF (const char *pszFormat, va_list va_args); -#endif - -static Bool -winCheckDisplayNumber (void); - -void -winLogCommandLine (int argc, char *argv[]); - -void -winLogVersionInfo (void); - -Bool -winValidateArgs (void); - -#ifdef RELOCATE_PROJECTROOT -const char * -winGetBaseDir(void); -#endif - -/* - * 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 - * is going to be running at 24 bits per pixel. - * - * FIXME: On second thought, don't DIBs only support 32 bits per pixel? - * DIBs are the underlying bitmap used for DirectDraw surfaces, so it - * seems that all pixmap formats with depth 24 would be 32 bits per pixel. - * Confirm whether depth 24 DIBs can have 24 bits per pixel, then remove/keep - * the bits per pixel adjustment and update this comment to reflect the - * situation. Harold Hunt - 2002/07/02 - */ - -static PixmapFormatRec g_PixmapFormats[] = { - { 1, 1, BITMAP_SCANLINE_PAD }, - { 4, 8, BITMAP_SCANLINE_PAD }, - { 8, 8, BITMAP_SCANLINE_PAD }, - { 15, 16, BITMAP_SCANLINE_PAD }, - { 16, 16, BITMAP_SCANLINE_PAD }, - { 24, 32, BITMAP_SCANLINE_PAD }, - { 32, 32, BITMAP_SCANLINE_PAD } -}; - -const int NUMFORMATS = sizeof (g_PixmapFormats) / sizeof (g_PixmapFormats[0]); - -#ifdef XWIN_CLIPBOARD -static void -winClipboardShutdown (void) -{ - /* Close down clipboard resources */ - if (g_fClipboard && g_fClipboardLaunched && g_fClipboardStarted) - { - /* Synchronously destroy the clipboard window */ - if (g_hwndClipboard != NULL) - { - g_fClipboardStarted=FALSE; /* This is to avoid dead-locls caused by the clipboard thread still doing some stuff */ - SendMessage (g_hwndClipboard, WM_DESTROY, 0, 0); - /* NOTE: g_hwndClipboard is set to NULL in winclipboardthread.c */ - } - else - return; - - /* Wait for the clipboard thread to exit */ - pthread_join (g_ptClipboardProc, NULL); - - winDebug ("winClipboardShutdown - Clipboard thread has exited.\n"); - } -} -#endif - - -#if defined(DDXBEFORERESET) -/* - * Called right before KillAllClients when the server is going to reset, - * allows us to shutdown our seperate threads cleanly. - */ - -void -ddxBeforeReset (void) -{ - winDebug ("ddxBeforeReset - Hello\n"); - -#ifdef XWIN_CLIPBOARD - winClipboardShutdown (); -#endif -} -#endif - - -/* See Porting Layer Definition - p. 57 */ -void -ddxGiveUp (void) -{ - int i; - - winDebug ("ddxGiveUp\n"); - - /* Perform per-screen deinitialization */ - for (i = 0; i < g_iNumScreens; ++i) - { - /* Delete the tray icon */ - if (!g_ScreenInfo[i].fNoTrayIcon && g_ScreenInfo[i].pScreen) - winDeleteNotifyIcon (winGetScreenPriv (g_ScreenInfo[i].pScreen)); - } - -#ifdef XWIN_MULTIWINDOW - /* Notify the worker threads we're exiting */ - winDeinitMultiWindowWM (); -#endif - -#ifdef HAS_DEVWINDOWS - /* Close our handle to our message queue */ - if (g_fdMessageQueue != WIN_FD_INVALID) - { - /* Close /dev/windows */ - close (g_fdMessageQueue); - - /* Set the file handle to invalid */ - g_fdMessageQueue = WIN_FD_INVALID; - } -#endif - - if (!g_fLogInited) { - g_pszLogFile = LogInit (g_pszLogFile, NULL); - g_fLogInited = TRUE; - } - LogClose (); - - /* - * At this point we aren't creating any new screens, so - * we are guaranteed to not need the DirectDraw functions. - */ - winReleaseDDProcAddresses(); - - /* Unload our TrackMouseEvent function pointer */ - if (g_hmodCommonControls != NULL) - { - FreeLibrary (g_hmodCommonControls); - g_hmodCommonControls = NULL; - g_fpTrackMouseEvent = (FARPROC) (void (*)(void))NoopDDA; - } - - /* Free concatenated command line */ - free(g_pszCommandLine); - g_pszCommandLine = NULL; - - /* Remove our keyboard hook if it is installed */ - winRemoveKeyboardHookLL (); - - /* Tell Windows that we want to end the app */ - PostQuitMessage (0); -} - - -/* See Porting Layer Definition - p. 57 */ -void -AbortDDX (void) -{ - winDebug ("AbortDDX\n"); - ddxGiveUp (); -} - -#ifdef __CYGWIN__ -/* hasmntopt is currently not implemented for cygwin */ -static const char *winCheckMntOpt(const struct mntent *mnt, const char *opt) -{ - const char *s; - size_t len; - if (mnt == NULL) - return NULL; - if (opt == NULL) - return NULL; - if (mnt->mnt_opts == NULL) - return NULL; - - len = strlen(opt); - s = strstr(mnt->mnt_opts, opt); - if (s == NULL) - return NULL; - if ((s == mnt->mnt_opts || *(s-1) == ',') && (s[len] == 0 || s[len] == ',')) - return (char *)opt; - return NULL; -} - -static void -winCheckMount(void) -{ - FILE *mnt; - struct mntent *ent; - - enum { none = 0, sys_root, user_root, sys_tmp, user_tmp } - level = none, curlevel; - BOOL binary = TRUE; - - mnt = setmntent("/etc/mtab", "r"); - if (mnt == NULL) - { - ErrorF("setmntent failed"); - return; - } - - while ((ent = getmntent(mnt)) != NULL) - { - BOOL system = (winCheckMntOpt(ent, "user") != NULL); - BOOL root = (strcmp(ent->mnt_dir, "/") == 0); - BOOL tmp = (strcmp(ent->mnt_dir, "/tmp") == 0); - - if (system) - { - if (root) - curlevel = sys_root; - else if (tmp) - curlevel = sys_tmp; - else - continue; - } - else - { - if (root) - curlevel = user_root; - else if (tmp) - curlevel = user_tmp; - else - continue; - } - - if (curlevel <= level) - continue; - level = curlevel; - - if ((winCheckMntOpt(ent, "binary") == NULL) && - (winCheckMntOpt(ent, "binmode") == NULL)) - binary = FALSE; - else - binary = TRUE; - } - - if (endmntent(mnt) != 1) - { - ErrorF("endmntent failed"); - return; - } - -#ifdef WINDBG - if (!binary) - winDebug("/tmp mounted in textmode\n"); -#endif -} -#else -static void -winCheckMount(void) -{ -} -#endif - -#ifdef RELOCATE_PROJECTROOT -const char * -winGetBaseDir(void) -{ - static BOOL inited = FALSE; - static char buffer[MAX_PATH]; - if (!inited) - { - char *fendptr; - HMODULE module = GetModuleHandle(NULL); - DWORD size = GetModuleFileName(module, buffer, sizeof(buffer)); - if (sizeof(buffer) > 0) - buffer[sizeof(buffer)-1] = 0; - - fendptr = buffer + size; - while (fendptr > buffer) - { - if (*fendptr == '\\' || *fendptr == '/') - { - *fendptr = 0; - break; - } - fendptr--; - } - inited = TRUE; - } - return buffer; -} -#endif - -static void -winFixupPaths (void) -{ - BOOL changed_fontpath = FALSE; - MessageType font_from = X_DEFAULT; -#ifdef RELOCATE_PROJECTROOT - const char *basedir = winGetBaseDir(); - size_t basedirlen = strlen(basedir); -#endif - -#ifdef READ_FONTDIRS - { - /* Open fontpath configuration file */ -#if defined WIN32 && defined __MINGW32__ - static Bool once = False; - char buffer[MAX_PATH]; - snprintf(buffer, sizeof(buffer), "%s\\font-dirs", basedir); - buffer[sizeof(buffer)-1] = 0; - FILE *fontdirs = fopen(buffer, "rt"); - if (once) fontdirs = NULL; - else once = True; -#else - FILE *fontdirs = fopen(ETCX11DIR "/font-dirs", "rt"); -#endif - if (fontdirs != NULL) - { - char buffer[256]; - int needs_sep = TRUE; - int comment_block = FALSE; - - /* get default fontpath */ - char *fontpath = strdup(defaultFontPath); - size_t size = strlen(fontpath); - - /* read all lines */ - while (!feof(fontdirs)) - { - size_t blen; - char *hashchar; - char *str; - int has_eol = FALSE; - - /* read one line */ - str = fgets(buffer, sizeof(buffer), fontdirs); - if (str == NULL) /* stop on error or eof */ - break; - - if (strchr(str, '\n') != NULL) - has_eol = TRUE; - - /* check if block is continued comment */ - if (comment_block) - { - /* ignore all input */ - *str = 0; - blen = 0; - if (has_eol) /* check if line ended in this block */ - comment_block = FALSE; - } - else - { - /* find comment character. ignore all trailing input */ - hashchar = strchr(str, '#'); - if (hashchar != NULL) - { - *hashchar = 0; - if (!has_eol) /* mark next block as continued comment */ - comment_block = TRUE; - } - } - - /* strip whitespaces from beginning */ - while (*str == ' ' || *str == '\t') - str++; - - /* get size, strip whitespaces from end */ - blen = strlen(str); - while (blen > 0 && (str[blen-1] == ' ' || - str[blen-1] == '\t' || str[blen-1] == '\n')) - { - str[--blen] = 0; - } - - /* still something left to add? */ - if (blen > 0) - { - size_t newsize = size + blen; - /* reserve one character more for ',' */ - if (needs_sep) - newsize++; - - /* allocate memory */ - if (fontpath == NULL) - fontpath = malloc(newsize+1); - else - fontpath = realloc(fontpath, newsize+1); - - /* add separator */ - if (needs_sep) - { - fontpath[size] = ','; - size++; - needs_sep = FALSE; - } - - /* mark next line as new entry */ - if (has_eol) - needs_sep = TRUE; - - /* add block */ - strncpy(fontpath + size, str, blen); - fontpath[newsize] = 0; - size = newsize; - } - } - - /* cleanup */ - fclose(fontdirs); - defaultFontPath = strdup(fontpath); - free(fontpath); - changed_fontpath = TRUE; - font_from = X_CONFIG; - } - } -#endif /* READ_FONTDIRS */ -#ifdef RELOCATE_PROJECTROOT - { - const char *libx11dir = PROJECTROOT "/lib/X11"; - size_t libx11dir_len = strlen(libx11dir); - char *newfp = NULL; - size_t newfp_len = 0; - const char *endptr, *ptr, *oldptr = defaultFontPath; - - endptr = oldptr + strlen(oldptr); - ptr = strchr(oldptr, ','); - if (ptr == NULL) - ptr = endptr; - while (ptr != NULL) - { - size_t oldfp_len = (ptr - oldptr); - size_t newsize = oldfp_len; - char *newpath = malloc(newsize + 1); - strncpy(newpath, oldptr, newsize); - newpath[newsize] = 0; - - - if (strncmp(libx11dir, newpath, libx11dir_len) == 0) - { - char *compose; - newsize = newsize - libx11dir_len + basedirlen; - compose = malloc(newsize + 1); - strcpy(compose, basedir); - strncat(compose, newpath + libx11dir_len, newsize - basedirlen); - compose[newsize] = 0; - free(newpath); - newpath = compose; - } - - oldfp_len = newfp_len; - if (oldfp_len > 0) - newfp_len ++; /* space for separator */ - newfp_len += newsize; - - if (newfp == NULL) - newfp = malloc(newfp_len + 1); - else - newfp = realloc(newfp, newfp_len + 1); - - if (oldfp_len > 0) - { - strcpy(newfp + oldfp_len, ","); - oldfp_len++; - } - strcpy(newfp + oldfp_len, newpath); - - free(newpath); - - if (*ptr == 0) - { - oldptr = ptr; - ptr = NULL; - } else - { - oldptr = ptr + 1; - ptr = strchr(oldptr, ','); - if (ptr == NULL) - ptr = endptr; - } - } - - defaultFontPath = strdup(newfp); - free(newfp); - changed_fontpath = TRUE; - } -#endif /* RELOCATE_PROJECTROOT */ - if (changed_fontpath) - winDebug ("FontPath set to \"%s\"\n", defaultFontPath); - -#ifdef RELOCATE_PROJECTROOT - if (getenv("XKEYSYMDB") == NULL) - { - char buffer[MAX_PATH]; - snprintf(buffer, sizeof(buffer), "XKEYSYMDB=%s\\XKeysymDB", - basedir); - buffer[sizeof(buffer)-1] = 0; - putenv(buffer); - } - if (getenv("XERRORDB") == NULL) - { - char buffer[MAX_PATH]; - snprintf(buffer, sizeof(buffer), "XERRORDB=%s\\XErrorDB", - basedir); - buffer[sizeof(buffer)-1] = 0; - putenv(buffer); - } - if (getenv("XLOCALEDIR") == NULL) - { - char buffer[MAX_PATH]; - snprintf(buffer, sizeof(buffer), "XLOCALEDIR=%s\\locale", - basedir); - buffer[sizeof(buffer)-1] = 0; - putenv(buffer); - } - if (getenv("XHOSTPREFIX") == NULL) - { - char buffer[MAX_PATH]; - snprintf(buffer, sizeof(buffer), "XHOSTPREFIX=%s\\X", - basedir); - buffer[sizeof(buffer)-1] = 0; - putenv(buffer); - } - if (getenv("HOME") == NULL) - { - HMODULE shfolder; - SHGETFOLDERPATHPROC shgetfolderpath = NULL; - char buffer[MAX_PATH + 5]; - strncpy(buffer, "HOME=", 5); - - /* Try to load SHGetFolderPath from shfolder.dll and shell32.dll */ - - shfolder = LoadLibrary("shfolder.dll"); - /* fallback to shell32.dll */ - if (shfolder == NULL) - shfolder = LoadLibrary("shell32.dll"); - - /* resolve SHGetFolderPath */ - if (shfolder != NULL) - shgetfolderpath = (SHGETFOLDERPATHPROC)GetProcAddress(shfolder, "SHGetFolderPathA"); - - /* query appdata directory */ - if (shgetfolderpath && - shgetfolderpath(NULL, CSIDL_APPDATA|CSIDL_FLAG_CREATE, NULL, 0, - buffer + 5) == 0) - { - putenv(buffer); - } else - { - ErrorF ("Can not determine HOME directory\n"); - } - if (shfolder != NULL) - FreeLibrary(shfolder); - } - if (!g_fLogFileChanged) { - static char buffer[MAX_PATH]; - DWORD size = GetTempPath(sizeof(buffer), buffer); - if (size && size < sizeof(buffer)) - { - snprintf(buffer + size, sizeof(buffer) - size, - "VCXSrv.%s.log", display); - buffer[sizeof(buffer)-1] = 0; - g_pszLogFile = buffer; - GetLongPathName(buffer, buffer, MAX_PATH); - winDebug ("Logfile set to \"%s\"\n", g_pszLogFile); - } - } - { - static char xkbbasedir[MAX_PATH]; - - snprintf(xkbbasedir, sizeof(xkbbasedir), "%s\\xkbdata", basedir); - if (sizeof(xkbbasedir) > 0) - xkbbasedir[sizeof(xkbbasedir)-1] = 0; - XkbBaseDirectory = xkbbasedir; - XkbBinDirectory = basedir; - } -#endif /* RELOCATE_PROJECTROOT */ -} - -void -OsVendorInit (void) -{ - /* Re-initialize global variables on server reset */ - winInitializeGlobals (); - - winFixupPaths(); - -#ifdef DDXOSVERRORF - if (!OsVendorVErrorFProc) - OsVendorVErrorFProc = OsVendorVErrorF; -#endif - - if (!g_fLogInited) { - /* keep this order. If LogInit fails it calls Abort which then calls - * ddxGiveUp where LogInit is called again and creates an infinite - * recursion. If we set g_fLogInited to TRUE before the init we - * avoid the second call - */ - g_fLogInited = TRUE; - g_pszLogFile = LogInit (g_pszLogFile, NULL); - } - LogSetParameter (XLOG_FLUSH, 1); - LogSetParameter (XLOG_VERBOSITY, g_iLogVerbose); - LogSetParameter (XLOG_FILE_VERBOSITY, g_iLogVerbose); - - /* Log the version information */ - if (serverGeneration == 1) - winLogVersionInfo (); - - winCheckMount(); - - /* Add a default screen if no screens were specified */ - if (g_iNumScreens == 0) - { - winDebug ("OsVendorInit - Creating default screen 0\n"); - - /* - * We need to initialize the default screen 0 if no -screen - * arguments were processed. - * - * Add a screen 0 using the defaults set by winInitializeDefaultScreens() - * and any additional default screen parameters given - */ - winInitializeScreens(1); - - /* We have to flag this as an explicit screen, even though it isn't */ - g_ScreenInfo[0].fExplicitScreen = TRUE; - } -} - - -static void -winUseMsg (void) -{ - ErrorF("\n"); - ErrorF("\n"); - ErrorF(EXECUTABLE_NAME " Device Dependent Usage:\n"); - ErrorF("\n"); - -#ifdef XWIN_CLIPBOARD - ErrorF ("-[no]clipboard\n" - "\tEnable [disable] the clipboard integration. Default is enabled.\n"); - ErrorF ("-[no]clipboardprimary\n" - "\t[Do not] map the PRIMARY selection to the windows clipboard.\n" - "\tThe CLIPBOARD selection is always mapped if -clipboard is enabled.\n" - "\tDefault is mapped.\n"); -#endif - - ErrorF ("-clipupdates num_boxes\n" - "\tUse a clipping region to constrain shadow update blits to\n" - "\tthe updated region when num_boxes, or more, are in the\n" - "\tupdated region.\n"); - -#ifdef XWIN_XF86CONFIG - ErrorF ("-config\n" - "\tSpecify a configuration file.\n"); - - ErrorF ("-configdir\n" - "\tSpecify a configuration directory.\n"); -#endif - - ErrorF ("-depth bits_per_pixel\n" - "\tSpecify an optional bitdepth to use in fullscreen mode\n" - "\twith a DirectDraw engine.\n"); - - ErrorF ("-emulate3buttons [timeout]\n" - "\tEmulate 3 button mouse with an optional timeout in\n" - "\tmilliseconds.\n"); - -#ifdef XWIN_EMULATEPSEUDO - ErrorF ("-emulatepseudo\n" - "\tCreate a depth 8 PseudoColor visual when running in\n" - "\tdepths 15, 16, 24, or 32, collectively known as TrueColor\n" - "\tdepths. The PseudoColor visual does not have correct colors,\n" - "\tand it may crash, but it at least allows you to run your\n" - "\tapplication in TrueColor modes.\n"); -#endif - - ErrorF ("-engine engine_type_id\n" - "\tOverride the server's automatically selected engine type:\n" - "\t\t1 - Shadow GDI\n" - "\t\t2 - Shadow DirectDraw\n" - "\t\t4 - Shadow DirectDraw4 Non-Locking\n" -#ifdef XWIN_PRIMARYFB - "\t\t8 - Primary DirectDraw - obsolete\n" -#endif -#ifdef XWIN_NATIVEGDI - "\t\t16 - Native GDI - experimental\n" -#endif - ); - - ErrorF ("-fullscreen\n" - "\tRun the server in fullscreen mode.\n"); - - ErrorF ("-ignoreinput\n" - "\tIgnore keyboard and mouse input.\n"); - -#ifdef XWIN_MULTIWINDOWINTWM - ErrorF ("-internalwm\n" - "\tRun the internal window manager.\n"); -#endif - -#ifdef XWIN_XF86CONFIG - ErrorF ("-keyboard\n" - "\tSpecify a keyboard device from the configuration file.\n"); -#endif - - ErrorF ("-[no]keyhook\n" - "\tGrab special Windows keypresses like Alt-Tab or the Menu " - "key.\n"); - - ErrorF ("-lesspointer\n" - "\tHide the windows mouse pointer when it is over any\n" - "\t" EXECUTABLE_NAME " window. This prevents ghost cursors appearing when\n" - "\tthe Windows cursor is drawn on top of the X cursor\n"); - - ErrorF ("-logfile filename\n" - "\tWrite log messages to <filename>.\n"); - - ErrorF ("-logverbose verbosity\n" - "\tSet the verbosity of log messages. [NOTE: Only a few messages\n" - "\trespect the settings yet]\n" - "\t\t0 - only print fatal error.\n" - "\t\t1 - print additional configuration information.\n" - "\t\t2 - print additional runtime information [default].\n" - "\t\t3 - print debugging and tracing information.\n"); - - ErrorF ("-[no]multimonitors or -[no]multiplemonitors\n" - "\tUse the entire virtual screen if multiple\n" - "\tmonitors are present.\n"); - -#ifdef XWIN_MULTIWINDOW - ErrorF ("-multiwindow\n" - "\tRun the server in multi-window mode.\n"); -#endif - -#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"); - -#ifdef XWIN_CLIPBOARD - ErrorF ("-nounicodeclipboard\n" - "\tDo not use Unicode clipboard even if on a NT-based platform.\n"); -#endif - - ErrorF ("-refresh rate_in_Hz\n" - "\tSpecify an optional refresh rate to use in fullscreen mode\n" - "\twith a DirectDraw engine.\n"); - - ErrorF ("-resize=none|scrollbars|randr" - "\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.\n"); - - ErrorF ("-rootless\n" - "\tRun the server in rootless mode.\n"); - - ErrorF ("-screen scr_num [width height [x y] | [[WxH[+X+Y]][@m]] ]\n" - "\tEnable screen scr_num and optionally specify a width and\n" - "\theight and initial position for that screen. Additionally\n" - "\ta monitor number can be specified to start the server on,\n" - "\tat which point, all coordinates become relative to that\n" - "\tmonitor (Not for Windows NT4 and 95). Examples:\n" - "\t -screen 0 800x600+100+100@2 ; 2nd monitor offset 100,100 size 800x600\n" - "\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"); - - ErrorF ("-[no]trayicon\n" - "\tDo not create a tray icon. Default is to create one\n" - "\ticon per screen. You can globally disable tray icons with\n" - "\t-notrayicon, then enable it for specific screens with\n" - "\t-trayicon for those screens.\n"); - - ErrorF ("-[no]unixkill\n" - "\tCtrl+Alt+Backspace exits the X Server.\n"); - - ErrorF ("-[no]wgl\n" - "\tEnable the GLX extension to use the native Windows WGL interface for accelerated OpenGL\n"); - - ErrorF ("-[no]winkill\n" - "\tAlt+F4 exits the X Server.\n"); - - ErrorF ("-xkblayout XKBLayout\n" - "\tEquivalent to XKBLayout in XF86Config files.\n" - "\tFor example: -xkblayout de\n"); - - ErrorF ("-xkbmodel XKBModel\n" - "\tEquivalent to XKBModel in XF86Config files.\n"); - - ErrorF ("-xkboptions XKBOptions\n" - "\tEquivalent to XKBOptions in XF86Config files.\n"); - - ErrorF ("-xkbrules XKBRules\n" - "\tEquivalent to XKBRules in XF86Config files.\n"); - - ErrorF ("-xkbvariant XKBVariant\n" - "\tEquivalent to XKBVariant in XF86Config files.\n" - "\tFor example: -xkbvariant nodeadkeys\n"); -} - -/* See Porting Layer Definition - p. 57 */ -void -ddxUseMsg(void) -{ - /* Set a flag so that FatalError won't give duplicate warning message */ - g_fSilentFatalError = TRUE; - - winUseMsg(); - - /* Log file will not be opened for UseMsg unless we open it now */ - if (!g_fLogInited) { - g_pszLogFile = LogInit (g_pszLogFile, NULL); - g_fLogInited = TRUE; - } - LogClose (); - - /* 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 */ -/* - * Do any global initialization, then initialize each screen. - * - * NOTE: We use ddxProcessArgument, so we don't need to touch argc and argv - */ - -void -InitOutput (ScreenInfo *screenInfo, int argc, char *argv[]) -{ - int i; - - /* Log the command line */ - winLogCommandLine (argc, argv); - - winDebug ("InitOutput\n"); - - /* Validate command-line arguments */ - if (serverGeneration == 1 && !winValidateArgs ()) - { - FatalError ("InitOutput - Invalid command-line arguments found. " - "Exiting.\n"); - } - - /* Check for duplicate invocation on same display number.*/ - if (serverGeneration == 1 && !winCheckDisplayNumber ()) - { - if (g_fSilentDupError) - g_fSilentFatalError = TRUE; - FatalError ("InitOutput - Duplicate invocation on display " - "number: %s. Exiting.\n", display); - } - -#ifdef XWIN_XF86CONFIG - /* Try to read the xorg.conf-style configuration file */ - if (!winReadConfigfile ()) - ErrorF ("InitOutput - Error reading config file\n"); -#else - winConfigFiles (); -#endif - - /* Load preferences from XWinrc file */ - LoadPreferences(); - - /* Setup global screen info parameters */ - screenInfo->imageByteOrder = IMAGE_BYTE_ORDER; - screenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD; - screenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT; - screenInfo->bitmapBitOrder = BITMAP_BIT_ORDER; - screenInfo->numPixmapFormats = NUMFORMATS; - - /* Describe how we want common pixmap formats padded */ - for (i = 0; i < NUMFORMATS; i++) - { - screenInfo->formats[i] = g_PixmapFormats[i]; - } - - /* Load pointers to DirectDraw functions */ - winGetDDProcAddresses (); - - /* Detect supported engines */ - winDetectSupportedEngines (); - - /* Load common controls library */ - g_hmodCommonControls = LoadLibraryEx ("comctl32.dll", NULL, 0); - - /* Load TrackMouseEvent function pointer */ - g_fpTrackMouseEvent = GetProcAddress (g_hmodCommonControls, - "_TrackMouseEvent"); - if (g_fpTrackMouseEvent == NULL) - { - ErrorF ("InitOutput - Could not get pointer to function\n" - "\t_TrackMouseEvent in comctl32.dll. Try installing\n" - "\tInternet Explorer 3.0 or greater if you have not\n" - "\talready.\n"); - - /* Free the library since we won't need it */ - FreeLibrary (g_hmodCommonControls); - g_hmodCommonControls = NULL; - - /* Set function pointer to point to no operation function */ - g_fpTrackMouseEvent = (FARPROC) (void (*)(void))NoopDDA; - } - - /* Store the instance handle */ - g_hInstance = GetModuleHandle (NULL); - - /* Initialize each screen */ - for (i = 0; i < g_iNumScreens; ++i) - { - /* Initialize the screen */ - if (-1 == AddScreen (winScreenInit, argc, argv)) - { - FatalError ("InitOutput - Couldn't add screen %d", i); - } - } - -#if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW) - - /* Generate a cookie used by internal clients for authorization */ - 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. - */ - if (!setlocale (LC_ALL, "")) - { - ErrorF ("setlocale failed.\n"); - } - - /* See if X supports the current locale */ - if (XSupportsLocale () == FALSE) - { - ErrorF ("Warning: Locale not supported by X, falling back to 'C' locale.\n"); - setlocale(LC_ALL, "C"); - } - - } -#endif - - winDebug ("InitOutput - Returning.\n"); -} - - -/* - * winCheckDisplayNumber - Check if another instance of Cygwin/X is - * already running on the same display number. If no one exists, - * make a mutex to prevent new instances from running on the same display. - * - * return FALSE if the display number is already used. - */ - -static Bool -winCheckDisplayNumber (void) -{ - int nDisp; - HANDLE mutex; - char name[MAX_PATH]; - char * pszPrefix = '\0'; - OSVERSIONINFO osvi = {0}; - - /* Check display range */ - nDisp = atoi (display); - if (nDisp < 0 || nDisp > 59535) - { - ErrorF ("winCheckDisplayNumber - Bad display number: %d\n", nDisp); - return FALSE; - } - - /* Set first character of mutex name to null */ - name[0] = '\0'; - - /* Get operating system version information */ - osvi.dwOSVersionInfoSize = sizeof (osvi); - GetVersionEx (&osvi); - - /* Want a mutex shared among all terminals on NT > 4.0 */ - if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT - && osvi.dwMajorVersion >= 5) - { - pszPrefix = "Global\\"; - } - - /* Setup Cygwin/X specific part of name */ - snprintf (name, sizeof(name), "%sCYGWINX_DISPLAY:%d", pszPrefix, nDisp); - - /* Windows automatically releases the mutex when this process exits */ - mutex = CreateMutex (NULL, FALSE, name); - if (!mutex) - { - LPVOID lpMsgBuf; - - /* Display a fancy error message */ - FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - GetLastError (), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR) &lpMsgBuf, - 0, NULL); - ErrorF ("winCheckDisplayNumber - CreateMutex failed: %s\n", - (LPSTR)lpMsgBuf); - LocalFree (lpMsgBuf); - - return FALSE; - } - if (GetLastError () == ERROR_ALREADY_EXISTS) - { - ErrorF ("winCheckDisplayNumber - " - "VCXsrv, Xming or Cygwin/X is already running on display %d\n", - nDisp); - return FALSE; - } - - return TRUE; -} +
+/*
+
+Copyright 1993, 1998 The Open Group
+Copyright (C) Colin Harrison 2005-2008
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+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 OPEN GROUP 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 Open Group 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 Open Group.
+
+*/
+
+#ifdef HAVE_XWIN_CONFIG_H
+#include <xwin-config.h>
+#endif
+#include "win.h"
+#include "winmsg.h"
+#include "winconfig.h"
+#include "winprefs.h"
+#ifdef DPMSExtension
+#include "dpmsproc.h"
+#endif
+#include <locale.h>
+#ifdef __CYGWIN__
+#include <mntent.h>
+#endif
+#if defined(WIN32)
+#include "xkbsrv.h"
+#endif
+#ifdef RELOCATE_PROJECTROOT
+#undef Status
+#include <shlobj.h>
+typedef HRESULT (__stdcall * SHGETFOLDERPATHPROC)(
+ HWND hwndOwner,
+ int nFolder,
+ HANDLE hToken,
+ DWORD dwFlags,
+ LPSTR pszPath
+);
+#endif
+
+/*
+ * References to external symbols
+ */
+#ifdef XWIN_CLIPBOARD
+extern Bool g_fUnicodeClipboard;
+extern Bool g_fClipboardLaunched;
+extern Bool g_fClipboardStarted;
+extern pthread_t g_ptClipboardProc;
+extern HWND g_hwndClipboard;
+extern Bool g_fClipboard;
+#endif
+
+
+/*
+ module handle for dynamically loaded comctl32 library
+*/
+static HMODULE g_hmodCommonControls = NULL;
+
+/*
+ * Function prototypes
+ */
+
+#ifdef XWIN_CLIPBOARD
+static void
+winClipboardShutdown (void);
+#endif
+
+#if defined(DDXOSVERRORF)
+void
+OsVendorVErrorF (const char *pszFormat, va_list va_args);
+#endif
+
+static Bool
+winCheckDisplayNumber (void);
+
+void
+winLogCommandLine (int argc, char *argv[]);
+
+void
+winLogVersionInfo (void);
+
+Bool
+winValidateArgs (void);
+
+#ifdef RELOCATE_PROJECTROOT
+const char *
+winGetBaseDir(void);
+#endif
+
+/*
+ * 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
+ * is going to be running at 24 bits per pixel.
+ *
+ * FIXME: On second thought, don't DIBs only support 32 bits per pixel?
+ * DIBs are the underlying bitmap used for DirectDraw surfaces, so it
+ * seems that all pixmap formats with depth 24 would be 32 bits per pixel.
+ * Confirm whether depth 24 DIBs can have 24 bits per pixel, then remove/keep
+ * the bits per pixel adjustment and update this comment to reflect the
+ * situation. Harold Hunt - 2002/07/02
+ */
+
+static PixmapFormatRec g_PixmapFormats[] = {
+ { 1, 1, BITMAP_SCANLINE_PAD },
+ { 4, 8, BITMAP_SCANLINE_PAD },
+ { 8, 8, BITMAP_SCANLINE_PAD },
+ { 15, 16, BITMAP_SCANLINE_PAD },
+ { 16, 16, BITMAP_SCANLINE_PAD },
+ { 24, 32, BITMAP_SCANLINE_PAD },
+ { 32, 32, BITMAP_SCANLINE_PAD }
+};
+
+const int NUMFORMATS = sizeof (g_PixmapFormats) / sizeof (g_PixmapFormats[0]);
+
+#ifdef XWIN_CLIPBOARD
+static void
+winClipboardShutdown (void)
+{
+ /* Close down clipboard resources */
+ if (g_fClipboard && g_fClipboardLaunched && g_fClipboardStarted)
+ {
+ /* Synchronously destroy the clipboard window */
+ if (g_hwndClipboard != NULL)
+ {
+ g_fClipboardStarted=FALSE; /* This is to avoid dead-locls caused by the clipboard thread still doing some stuff */
+ SendMessage (g_hwndClipboard, WM_DESTROY, 0, 0);
+ /* NOTE: g_hwndClipboard is set to NULL in winclipboardthread.c */
+ }
+ else
+ return;
+
+ /* Wait for the clipboard thread to exit */
+ pthread_join (g_ptClipboardProc, NULL);
+
+ winDebug ("winClipboardShutdown - Clipboard thread has exited.\n");
+ }
+}
+#endif
+
+
+#if defined(DDXBEFORERESET)
+/*
+ * Called right before KillAllClients when the server is going to reset,
+ * allows us to shutdown our seperate threads cleanly.
+ */
+
+void
+ddxBeforeReset (void)
+{
+ winDebug ("ddxBeforeReset - Hello\n");
+
+#ifdef XWIN_CLIPBOARD
+ winClipboardShutdown ();
+#endif
+}
+#endif
+
+
+/* See Porting Layer Definition - p. 57 */
+void
+ddxGiveUp (void)
+{
+ int i;
+
+ winDebug ("ddxGiveUp\n");
+
+ /* Perform per-screen deinitialization */
+ for (i = 0; i < g_iNumScreens; ++i)
+ {
+ /* Delete the tray icon */
+ if (!g_ScreenInfo[i].fNoTrayIcon && g_ScreenInfo[i].pScreen)
+ winDeleteNotifyIcon (winGetScreenPriv (g_ScreenInfo[i].pScreen));
+ }
+
+#ifdef XWIN_MULTIWINDOW
+ /* Notify the worker threads we're exiting */
+ winDeinitMultiWindowWM ();
+#endif
+
+#ifdef HAS_DEVWINDOWS
+ /* Close our handle to our message queue */
+ if (g_fdMessageQueue != WIN_FD_INVALID)
+ {
+ /* Close /dev/windows */
+ close (g_fdMessageQueue);
+
+ /* Set the file handle to invalid */
+ g_fdMessageQueue = WIN_FD_INVALID;
+ }
+#endif
+
+ if (!g_fLogInited) {
+ g_pszLogFile = LogInit (g_pszLogFile, NULL);
+ g_fLogInited = TRUE;
+ }
+ LogClose ();
+
+ /*
+ * At this point we aren't creating any new screens, so
+ * we are guaranteed to not need the DirectDraw functions.
+ */
+ winReleaseDDProcAddresses();
+
+ /* Unload our TrackMouseEvent function pointer */
+ if (g_hmodCommonControls != NULL)
+ {
+ FreeLibrary (g_hmodCommonControls);
+ g_hmodCommonControls = NULL;
+ g_fpTrackMouseEvent = (FARPROC) (void (*)(void))NoopDDA;
+ }
+
+ /* Free concatenated command line */
+ free(g_pszCommandLine);
+ g_pszCommandLine = NULL;
+
+ /* Remove our keyboard hook if it is installed */
+ winRemoveKeyboardHookLL ();
+
+ /* Tell Windows that we want to end the app */
+ PostQuitMessage (0);
+}
+
+
+/* See Porting Layer Definition - p. 57 */
+void
+AbortDDX (void)
+{
+ winDebug ("AbortDDX\n");
+ ddxGiveUp ();
+}
+
+#ifdef __CYGWIN__
+/* hasmntopt is currently not implemented for cygwin */
+static const char *winCheckMntOpt(const struct mntent *mnt, const char *opt)
+{
+ const char *s;
+ size_t len;
+ if (mnt == NULL)
+ return NULL;
+ if (opt == NULL)
+ return NULL;
+ if (mnt->mnt_opts == NULL)
+ return NULL;
+
+ len = strlen(opt);
+ s = strstr(mnt->mnt_opts, opt);
+ if (s == NULL)
+ return NULL;
+ if ((s == mnt->mnt_opts || *(s-1) == ',') && (s[len] == 0 || s[len] == ','))
+ return (char *)opt;
+ return NULL;
+}
+
+static void
+winCheckMount(void)
+{
+ FILE *mnt;
+ struct mntent *ent;
+
+ enum { none = 0, sys_root, user_root, sys_tmp, user_tmp }
+ level = none, curlevel;
+ BOOL binary = TRUE;
+
+ mnt = setmntent("/etc/mtab", "r");
+ if (mnt == NULL)
+ {
+ ErrorF("setmntent failed");
+ return;
+ }
+
+ while ((ent = getmntent(mnt)) != NULL)
+ {
+ BOOL system = (winCheckMntOpt(ent, "user") != NULL);
+ BOOL root = (strcmp(ent->mnt_dir, "/") == 0);
+ BOOL tmp = (strcmp(ent->mnt_dir, "/tmp") == 0);
+
+ if (system)
+ {
+ if (root)
+ curlevel = sys_root;
+ else if (tmp)
+ curlevel = sys_tmp;
+ else
+ continue;
+ }
+ else
+ {
+ if (root)
+ curlevel = user_root;
+ else if (tmp)
+ curlevel = user_tmp;
+ else
+ continue;
+ }
+
+ if (curlevel <= level)
+ continue;
+ level = curlevel;
+
+ if ((winCheckMntOpt(ent, "binary") == NULL) &&
+ (winCheckMntOpt(ent, "binmode") == NULL))
+ binary = FALSE;
+ else
+ binary = TRUE;
+ }
+
+ if (endmntent(mnt) != 1)
+ {
+ ErrorF("endmntent failed");
+ return;
+ }
+
+#ifdef WINDBG
+ if (!binary)
+ winDebug("/tmp mounted in textmode\n");
+#endif
+}
+#else
+static void
+winCheckMount(void)
+{
+}
+#endif
+
+#ifdef RELOCATE_PROJECTROOT
+const char *
+winGetBaseDir(void)
+{
+ static BOOL inited = FALSE;
+ static char buffer[MAX_PATH];
+ if (!inited)
+ {
+ char *fendptr;
+ HMODULE module = GetModuleHandle(NULL);
+ DWORD size = GetModuleFileName(module, buffer, sizeof(buffer));
+ if (sizeof(buffer) > 0)
+ buffer[sizeof(buffer)-1] = 0;
+
+ fendptr = buffer + size;
+ while (fendptr > buffer)
+ {
+ if (*fendptr == '\\' || *fendptr == '/')
+ {
+ *fendptr = 0;
+ break;
+ }
+ fendptr--;
+ }
+ inited = TRUE;
+ }
+ return buffer;
+}
+#endif
+
+static void
+winFixupPaths (void)
+{
+ BOOL changed_fontpath = FALSE;
+ MessageType font_from = X_DEFAULT;
+#ifdef RELOCATE_PROJECTROOT
+ const char *basedir = winGetBaseDir();
+ size_t basedirlen = strlen(basedir);
+#endif
+
+#ifdef READ_FONTDIRS
+ {
+ /* Open fontpath configuration file */
+#if defined WIN32 && defined __MINGW32__
+ static Bool once = False;
+ char buffer[MAX_PATH];
+ snprintf(buffer, sizeof(buffer), "%s\\font-dirs", basedir);
+ buffer[sizeof(buffer)-1] = 0;
+ FILE *fontdirs = fopen(buffer, "rt");
+ if (once) fontdirs = NULL;
+ else once = True;
+#else
+ FILE *fontdirs = fopen(ETCX11DIR "/font-dirs", "rt");
+#endif
+ if (fontdirs != NULL)
+ {
+ char buffer[256];
+ int needs_sep = TRUE;
+ int comment_block = FALSE;
+
+ /* get default fontpath */
+ char *fontpath = strdup(defaultFontPath);
+ size_t size = strlen(fontpath);
+
+ /* read all lines */
+ while (!feof(fontdirs))
+ {
+ size_t blen;
+ char *hashchar;
+ char *str;
+ int has_eol = FALSE;
+
+ /* read one line */
+ str = fgets(buffer, sizeof(buffer), fontdirs);
+ if (str == NULL) /* stop on error or eof */
+ break;
+
+ if (strchr(str, '\n') != NULL)
+ has_eol = TRUE;
+
+ /* check if block is continued comment */
+ if (comment_block)
+ {
+ /* ignore all input */
+ *str = 0;
+ blen = 0;
+ if (has_eol) /* check if line ended in this block */
+ comment_block = FALSE;
+ }
+ else
+ {
+ /* find comment character. ignore all trailing input */
+ hashchar = strchr(str, '#');
+ if (hashchar != NULL)
+ {
+ *hashchar = 0;
+ if (!has_eol) /* mark next block as continued comment */
+ comment_block = TRUE;
+ }
+ }
+
+ /* strip whitespaces from beginning */
+ while (*str == ' ' || *str == '\t')
+ str++;
+
+ /* get size, strip whitespaces from end */
+ blen = strlen(str);
+ while (blen > 0 && (str[blen-1] == ' ' ||
+ str[blen-1] == '\t' || str[blen-1] == '\n'))
+ {
+ str[--blen] = 0;
+ }
+
+ /* still something left to add? */
+ if (blen > 0)
+ {
+ size_t newsize = size + blen;
+ /* reserve one character more for ',' */
+ if (needs_sep)
+ newsize++;
+
+ /* allocate memory */
+ if (fontpath == NULL)
+ fontpath = malloc(newsize+1);
+ else
+ fontpath = realloc(fontpath, newsize+1);
+
+ /* add separator */
+ if (needs_sep)
+ {
+ fontpath[size] = ',';
+ size++;
+ needs_sep = FALSE;
+ }
+
+ /* mark next line as new entry */
+ if (has_eol)
+ needs_sep = TRUE;
+
+ /* add block */
+ strncpy(fontpath + size, str, blen);
+ fontpath[newsize] = 0;
+ size = newsize;
+ }
+ }
+
+ /* cleanup */
+ fclose(fontdirs);
+ defaultFontPath = strdup(fontpath);
+ free(fontpath);
+ changed_fontpath = TRUE;
+ font_from = X_CONFIG;
+ }
+ }
+#endif /* READ_FONTDIRS */
+#ifdef RELOCATE_PROJECTROOT
+ {
+ const char *libx11dir = PROJECTROOT "/lib/X11";
+ size_t libx11dir_len = strlen(libx11dir);
+ char *newfp = NULL;
+ size_t newfp_len = 0;
+ const char *endptr, *ptr, *oldptr = defaultFontPath;
+
+ endptr = oldptr + strlen(oldptr);
+ ptr = strchr(oldptr, ',');
+ if (ptr == NULL)
+ ptr = endptr;
+ while (ptr != NULL)
+ {
+ size_t oldfp_len = (ptr - oldptr);
+ size_t newsize = oldfp_len;
+ char *newpath = malloc(newsize + 1);
+ strncpy(newpath, oldptr, newsize);
+ newpath[newsize] = 0;
+
+
+ if (strncmp(libx11dir, newpath, libx11dir_len) == 0)
+ {
+ char *compose;
+ newsize = newsize - libx11dir_len + basedirlen;
+ compose = malloc(newsize + 1);
+ strcpy(compose, basedir);
+ strncat(compose, newpath + libx11dir_len, newsize - basedirlen);
+ compose[newsize] = 0;
+ free(newpath);
+ newpath = compose;
+ }
+
+ oldfp_len = newfp_len;
+ if (oldfp_len > 0)
+ newfp_len ++; /* space for separator */
+ newfp_len += newsize;
+
+ if (newfp == NULL)
+ newfp = malloc(newfp_len + 1);
+ else
+ newfp = realloc(newfp, newfp_len + 1);
+
+ if (oldfp_len > 0)
+ {
+ strcpy(newfp + oldfp_len, ",");
+ oldfp_len++;
+ }
+ strcpy(newfp + oldfp_len, newpath);
+
+ free(newpath);
+
+ if (*ptr == 0)
+ {
+ oldptr = ptr;
+ ptr = NULL;
+ } else
+ {
+ oldptr = ptr + 1;
+ ptr = strchr(oldptr, ',');
+ if (ptr == NULL)
+ ptr = endptr;
+ }
+ }
+
+ defaultFontPath = strdup(newfp);
+ free(newfp);
+ changed_fontpath = TRUE;
+ }
+#endif /* RELOCATE_PROJECTROOT */
+ if (changed_fontpath)
+ winDebug ("FontPath set to \"%s\"\n", defaultFontPath);
+
+#ifdef RELOCATE_PROJECTROOT
+ if (getenv("XKEYSYMDB") == NULL)
+ {
+ char buffer[MAX_PATH];
+ snprintf(buffer, sizeof(buffer), "XKEYSYMDB=%s\\XKeysymDB",
+ basedir);
+ buffer[sizeof(buffer)-1] = 0;
+ putenv(buffer);
+ }
+ if (getenv("XERRORDB") == NULL)
+ {
+ char buffer[MAX_PATH];
+ snprintf(buffer, sizeof(buffer), "XERRORDB=%s\\XErrorDB",
+ basedir);
+ buffer[sizeof(buffer)-1] = 0;
+ putenv(buffer);
+ }
+ if (getenv("XLOCALEDIR") == NULL)
+ {
+ char buffer[MAX_PATH];
+ snprintf(buffer, sizeof(buffer), "XLOCALEDIR=%s\\locale",
+ basedir);
+ buffer[sizeof(buffer)-1] = 0;
+ putenv(buffer);
+ }
+ if (getenv("XHOSTPREFIX") == NULL)
+ {
+ char buffer[MAX_PATH];
+ snprintf(buffer, sizeof(buffer), "XHOSTPREFIX=%s\\X",
+ basedir);
+ buffer[sizeof(buffer)-1] = 0;
+ putenv(buffer);
+ }
+ if (getenv("HOME") == NULL)
+ {
+ HMODULE shfolder;
+ SHGETFOLDERPATHPROC shgetfolderpath = NULL;
+ char buffer[MAX_PATH + 5];
+ strncpy(buffer, "HOME=", 5);
+
+ /* Try to load SHGetFolderPath from shfolder.dll and shell32.dll */
+
+ shfolder = LoadLibrary("shfolder.dll");
+ /* fallback to shell32.dll */
+ if (shfolder == NULL)
+ shfolder = LoadLibrary("shell32.dll");
+
+ /* resolve SHGetFolderPath */
+ if (shfolder != NULL)
+ shgetfolderpath = (SHGETFOLDERPATHPROC)GetProcAddress(shfolder, "SHGetFolderPathA");
+
+ /* query appdata directory */
+ if (shgetfolderpath &&
+ shgetfolderpath(NULL, CSIDL_APPDATA|CSIDL_FLAG_CREATE, NULL, 0,
+ buffer + 5) == 0)
+ {
+ putenv(buffer);
+ } else
+ {
+ ErrorF ("Can not determine HOME directory\n");
+ }
+ if (shfolder != NULL)
+ FreeLibrary(shfolder);
+ }
+ if (!g_fLogFileChanged) {
+ static char buffer[MAX_PATH];
+ DWORD size = GetTempPath(sizeof(buffer), buffer);
+ if (size && size < sizeof(buffer))
+ {
+ snprintf(buffer + size, sizeof(buffer) - size,
+ "VCXSrv.%s.log", display);
+ buffer[sizeof(buffer)-1] = 0;
+ g_pszLogFile = buffer;
+ GetLongPathName(buffer, buffer, MAX_PATH);
+ winDebug ("Logfile set to \"%s\"\n", g_pszLogFile);
+ }
+ }
+ {
+ static char xkbbasedir[MAX_PATH];
+
+ snprintf(xkbbasedir, sizeof(xkbbasedir), "%s\\xkbdata", basedir);
+ if (sizeof(xkbbasedir) > 0)
+ xkbbasedir[sizeof(xkbbasedir)-1] = 0;
+ XkbBaseDirectory = xkbbasedir;
+ XkbBinDirectory = basedir;
+ }
+#endif /* RELOCATE_PROJECTROOT */
+}
+
+void
+OsVendorInit (void)
+{
+ /* Re-initialize global variables on server reset */
+ winInitializeGlobals ();
+
+ winFixupPaths();
+
+#ifdef DDXOSVERRORF
+ if (!OsVendorVErrorFProc)
+ OsVendorVErrorFProc = OsVendorVErrorF;
+#endif
+
+ if (!g_fLogInited) {
+ /* keep this order. If LogInit fails it calls Abort which then calls
+ * ddxGiveUp where LogInit is called again and creates an infinite
+ * recursion. If we set g_fLogInited to TRUE before the init we
+ * avoid the second call
+ */
+ g_fLogInited = TRUE;
+ g_pszLogFile = LogInit (g_pszLogFile, NULL);
+ }
+ LogSetParameter (XLOG_FLUSH, 1);
+ LogSetParameter (XLOG_VERBOSITY, g_iLogVerbose);
+ LogSetParameter (XLOG_FILE_VERBOSITY, g_iLogVerbose);
+
+ /* Log the version information */
+ if (serverGeneration == 1)
+ winLogVersionInfo ();
+
+ winCheckMount();
+
+ /* Add a default screen if no screens were specified */
+ if (g_iNumScreens == 0)
+ {
+ winDebug ("OsVendorInit - Creating default screen 0\n");
+
+ /*
+ * We need to initialize the default screen 0 if no -screen
+ * arguments were processed.
+ *
+ * Add a screen 0 using the defaults set by winInitializeDefaultScreens()
+ * and any additional default screen parameters given
+ */
+ winInitializeScreens(1);
+
+ /* We have to flag this as an explicit screen, even though it isn't */
+ g_ScreenInfo[0].fExplicitScreen = TRUE;
+ }
+}
+
+
+static void
+winUseMsg (void)
+{
+ ErrorF("\n");
+ ErrorF("\n");
+ ErrorF(EXECUTABLE_NAME " Device Dependent Usage:\n");
+ ErrorF("\n");
+
+#ifdef XWIN_CLIPBOARD
+ ErrorF ("-[no]clipboard\n"
+ "\tEnable [disable] the clipboard integration. Default is enabled.\n");
+ ErrorF ("-[no]clipboardprimary\n"
+ "\t[Do not] map the PRIMARY selection to the windows clipboard.\n"
+ "\tThe CLIPBOARD selection is always mapped if -clipboard is enabled.\n"
+ "\tDefault is mapped.\n");
+#endif
+
+ ErrorF ("-clipupdates num_boxes\n"
+ "\tUse a clipping region to constrain shadow update blits to\n"
+ "\tthe updated region when num_boxes, or more, are in the\n"
+ "\tupdated region.\n");
+
+#ifdef XWIN_XF86CONFIG
+ ErrorF ("-config\n"
+ "\tSpecify a configuration file.\n");
+
+ ErrorF ("-configdir\n"
+ "\tSpecify a configuration directory.\n");
+#endif
+
+ ErrorF ("-depth bits_per_pixel\n"
+ "\tSpecify an optional bitdepth to use in fullscreen mode\n"
+ "\twith a DirectDraw engine.\n");
+
+ ErrorF ("-emulate3buttons [timeout]\n"
+ "\tEmulate 3 button mouse with an optional timeout in\n"
+ "\tmilliseconds.\n");
+
+#ifdef XWIN_EMULATEPSEUDO
+ ErrorF ("-emulatepseudo\n"
+ "\tCreate a depth 8 PseudoColor visual when running in\n"
+ "\tdepths 15, 16, 24, or 32, collectively known as TrueColor\n"
+ "\tdepths. The PseudoColor visual does not have correct colors,\n"
+ "\tand it may crash, but it at least allows you to run your\n"
+ "\tapplication in TrueColor modes.\n");
+#endif
+
+ ErrorF ("-engine engine_type_id\n"
+ "\tOverride the server's automatically selected engine type:\n"
+ "\t\t1 - Shadow GDI\n"
+ "\t\t2 - Shadow DirectDraw\n"
+ "\t\t4 - Shadow DirectDraw4 Non-Locking\n"
+#ifdef XWIN_PRIMARYFB
+ "\t\t8 - Primary DirectDraw - obsolete\n"
+#endif
+#ifdef XWIN_NATIVEGDI
+ "\t\t16 - Native GDI - experimental\n"
+#endif
+ );
+
+ ErrorF ("-fullscreen\n"
+ "\tRun the server in fullscreen mode.\n");
+
+ ErrorF ("-ignoreinput\n"
+ "\tIgnore keyboard and mouse input.\n");
+
+#ifdef XWIN_MULTIWINDOWINTWM
+ ErrorF ("-internalwm\n"
+ "\tRun the internal window manager.\n");
+#endif
+
+#ifdef XWIN_XF86CONFIG
+ ErrorF ("-keyboard\n"
+ "\tSpecify a keyboard device from the configuration file.\n");
+#endif
+
+ ErrorF ("-[no]keyhook\n"
+ "\tGrab special Windows keypresses like Alt-Tab or the Menu "
+ "key.\n");
+
+ ErrorF ("-lesspointer\n"
+ "\tHide the windows mouse pointer when it is over any\n"
+ "\t" EXECUTABLE_NAME " window. This prevents ghost cursors appearing when\n"
+ "\tthe Windows cursor is drawn on top of the X cursor\n");
+
+ ErrorF ("-logfile filename\n"
+ "\tWrite log messages to <filename>.\n");
+
+ ErrorF ("-logverbose verbosity\n"
+ "\tSet the verbosity of log messages. [NOTE: Only a few messages\n"
+ "\trespect the settings yet]\n"
+ "\t\t0 - only print fatal error.\n"
+ "\t\t1 - print additional configuration information.\n"
+ "\t\t2 - print additional runtime information [default].\n"
+ "\t\t3 - print debugging and tracing information.\n");
+
+ ErrorF ("-[no]multimonitors or -[no]multiplemonitors\n"
+ "\tUse the entire virtual screen if multiple\n"
+ "\tmonitors are present.\n");
+
+#ifdef XWIN_MULTIWINDOW
+ ErrorF ("-multiwindow\n"
+ "\tRun the server in multi-window mode.\n");
+#endif
+
+#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");
+
+#ifdef XWIN_CLIPBOARD
+ ErrorF ("-nounicodeclipboard\n"
+ "\tDo not use Unicode clipboard even if on a NT-based platform.\n");
+#endif
+
+ ErrorF ("-refresh rate_in_Hz\n"
+ "\tSpecify an optional refresh rate to use in fullscreen mode\n"
+ "\twith a DirectDraw engine.\n");
+
+ ErrorF ("-resize=none|scrollbars|randr"
+ "\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.\n");
+
+ ErrorF ("-rootless\n"
+ "\tRun the server in rootless mode.\n");
+
+ ErrorF ("-screen scr_num [width height [x y] | [[WxH[+X+Y]][@m]] ]\n"
+ "\tEnable screen scr_num and optionally specify a width and\n"
+ "\theight and initial position for that screen. Additionally\n"
+ "\ta monitor number can be specified to start the server on,\n"
+ "\tat which point, all coordinates become relative to that\n"
+ "\tmonitor (Not for Windows NT4 and 95). Examples:\n"
+ "\t -screen 0 800x600+100+100@2 ; 2nd monitor offset 100,100 size 800x600\n"
+ "\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");
+
+ ErrorF ("-[no]trayicon\n"
+ "\tDo not create a tray icon. Default is to create one\n"
+ "\ticon per screen. You can globally disable tray icons with\n"
+ "\t-notrayicon, then enable it for specific screens with\n"
+ "\t-trayicon for those screens.\n");
+
+ ErrorF ("-[no]unixkill\n"
+ "\tCtrl+Alt+Backspace exits the X Server.\n");
+
+ ErrorF ("-[no]wgl\n"
+ "\tEnable the GLX extension to use the native Windows WGL interface for accelerated OpenGL\n");
+
+ ErrorF ("-[no]winkill\n"
+ "\tAlt+F4 exits the X Server.\n");
+
+ ErrorF ("-xkblayout XKBLayout\n"
+ "\tEquivalent to XKBLayout in XF86Config files.\n"
+ "\tFor example: -xkblayout de\n");
+
+ ErrorF ("-xkbmodel XKBModel\n"
+ "\tEquivalent to XKBModel in XF86Config files.\n");
+
+ ErrorF ("-xkboptions XKBOptions\n"
+ "\tEquivalent to XKBOptions in XF86Config files.\n");
+
+ ErrorF ("-xkbrules XKBRules\n"
+ "\tEquivalent to XKBRules in XF86Config files.\n");
+
+ ErrorF ("-xkbvariant XKBVariant\n"
+ "\tEquivalent to XKBVariant in XF86Config files.\n"
+ "\tFor example: -xkbvariant nodeadkeys\n");
+}
+
+/* See Porting Layer Definition - p. 57 */
+void
+ddxUseMsg(void)
+{
+ /* Set a flag so that FatalError won't give duplicate warning message */
+ g_fSilentFatalError = TRUE;
+
+ winUseMsg();
+
+ /* Log file will not be opened for UseMsg unless we open it now */
+ if (!g_fLogInited) {
+ g_pszLogFile = LogInit (g_pszLogFile, NULL);
+ g_fLogInited = TRUE;
+ }
+ LogClose ();
+
+ /* 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 */
+/*
+ * Do any global initialization, then initialize each screen.
+ *
+ * NOTE: We use ddxProcessArgument, so we don't need to touch argc and argv
+ */
+
+void
+InitOutput (ScreenInfo *screenInfo, int argc, char *argv[])
+{
+ int i;
+
+ /* Log the command line */
+ winLogCommandLine (argc, argv);
+
+ winDebug ("InitOutput\n");
+
+ /* Validate command-line arguments */
+ if (serverGeneration == 1 && !winValidateArgs ())
+ {
+ FatalError ("InitOutput - Invalid command-line arguments found. "
+ "Exiting.\n");
+ }
+
+ /* Check for duplicate invocation on same display number.*/
+ if (serverGeneration == 1 && !winCheckDisplayNumber ())
+ {
+ if (g_fSilentDupError)
+ g_fSilentFatalError = TRUE;
+ FatalError ("InitOutput - Duplicate invocation on display "
+ "number: %s. Exiting.\n", display);
+ }
+
+#ifdef XWIN_XF86CONFIG
+ /* Try to read the xorg.conf-style configuration file */
+ if (!winReadConfigfile ())
+ ErrorF ("InitOutput - Error reading config file\n");
+#else
+ winConfigFiles ();
+#endif
+
+ /* Load preferences from XWinrc file */
+ LoadPreferences();
+
+ /* Setup global screen info parameters */
+ screenInfo->imageByteOrder = IMAGE_BYTE_ORDER;
+ screenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
+ screenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
+ screenInfo->bitmapBitOrder = BITMAP_BIT_ORDER;
+ screenInfo->numPixmapFormats = NUMFORMATS;
+
+ /* Describe how we want common pixmap formats padded */
+ for (i = 0; i < NUMFORMATS; i++)
+ {
+ screenInfo->formats[i] = g_PixmapFormats[i];
+ }
+
+ /* Load pointers to DirectDraw functions */
+ winGetDDProcAddresses ();
+
+ /* Detect supported engines */
+ winDetectSupportedEngines ();
+
+ /* Load common controls library */
+ g_hmodCommonControls = LoadLibraryEx ("comctl32.dll", NULL, 0);
+
+ /* Load TrackMouseEvent function pointer */
+ g_fpTrackMouseEvent = GetProcAddress (g_hmodCommonControls,
+ "_TrackMouseEvent");
+ if (g_fpTrackMouseEvent == NULL)
+ {
+ ErrorF ("InitOutput - Could not get pointer to function\n"
+ "\t_TrackMouseEvent in comctl32.dll. Try installing\n"
+ "\tInternet Explorer 3.0 or greater if you have not\n"
+ "\talready.\n");
+
+ /* Free the library since we won't need it */
+ FreeLibrary (g_hmodCommonControls);
+ g_hmodCommonControls = NULL;
+
+ /* Set function pointer to point to no operation function */
+ g_fpTrackMouseEvent = (FARPROC) (void (*)(void))NoopDDA;
+ }
+
+ /* Store the instance handle */
+ g_hInstance = GetModuleHandle (NULL);
+
+ /* Initialize each screen */
+ for (i = 0; i < g_iNumScreens; ++i)
+ {
+ /* Initialize the screen */
+ if (-1 == AddScreen (winScreenInit, argc, argv))
+ {
+ FatalError ("InitOutput - Couldn't add screen %d", i);
+ }
+ }
+
+#if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW)
+
+ /* Generate a cookie used by internal clients for authorization */
+ 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.
+ */
+ if (!setlocale (LC_ALL, ""))
+ {
+ ErrorF ("setlocale failed.\n");
+ }
+
+ /* See if X supports the current locale */
+ if (XSupportsLocale () == FALSE)
+ {
+ ErrorF ("Warning: Locale not supported by X, falling back to 'C' locale.\n");
+ setlocale(LC_ALL, "C");
+ }
+
+ }
+#endif
+
+ winDebug ("InitOutput - Returning.\n");
+}
+
+
+/*
+ * winCheckDisplayNumber - Check if another instance of Cygwin/X is
+ * already running on the same display number. If no one exists,
+ * make a mutex to prevent new instances from running on the same display.
+ *
+ * return FALSE if the display number is already used.
+ */
+
+static Bool
+winCheckDisplayNumber (void)
+{
+ int nDisp;
+ HANDLE mutex;
+ char name[MAX_PATH];
+ char * pszPrefix = '\0';
+ OSVERSIONINFO osvi = {0};
+
+ /* Check display range */
+ nDisp = atoi (display);
+ if (nDisp < 0 || nDisp > 59535)
+ {
+ ErrorF ("winCheckDisplayNumber - Bad display number: %d\n", nDisp);
+ return FALSE;
+ }
+
+ /* Set first character of mutex name to null */
+ name[0] = '\0';
+
+ /* Get operating system version information */
+ osvi.dwOSVersionInfoSize = sizeof (osvi);
+ GetVersionEx (&osvi);
+
+ /* Want a mutex shared among all terminals on NT > 4.0 */
+ if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT
+ && osvi.dwMajorVersion >= 5)
+ {
+ pszPrefix = "Global\\";
+ }
+
+ /* Setup Cygwin/X specific part of name */
+ snprintf (name, sizeof(name), "%sCYGWINX_DISPLAY:%d", pszPrefix, nDisp);
+
+ /* Windows automatically releases the mutex when this process exits */
+ mutex = CreateMutex (NULL, FALSE, name);
+ if (!mutex)
+ {
+ LPVOID lpMsgBuf;
+
+ /* Display a fancy error message */
+ FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ GetLastError (),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPTSTR) &lpMsgBuf,
+ 0, NULL);
+ ErrorF ("winCheckDisplayNumber - CreateMutex failed: %s\n",
+ (LPSTR)lpMsgBuf);
+ LocalFree (lpMsgBuf);
+
+ return FALSE;
+ }
+ if (GetLastError () == ERROR_ALREADY_EXISTS)
+ {
+ ErrorF ("winCheckDisplayNumber - "
+ "VCXsrv, Xming or Cygwin/X is already running on display %d\n",
+ nDisp);
+ return FALSE;
+ }
+
+ return TRUE;
+}
diff --git a/xorg-server/hw/xwin/man/XWin.man b/xorg-server/hw/xwin/man/XWin.man index e7933c9c8..8d8b0a9ab 100644 --- a/xorg-server/hw/xwin/man/XWin.man +++ b/xorg-server/hw/xwin/man/XWin.man @@ -1,397 +1,398 @@ -.TH XWIN 1 __vendorversion__ -.SH NAME -XWin \- X Server for the Cygwin environment on Microsoft Windows - - -.SH SYNOPSIS -.B XWin -[ options ] ... - - -.SH DESCRIPTION -\fIXWin\fP is an X Server for the X Window System on the Cygwin environment -running on Microsoft Windows. - - -.SH MODES -\fIXWin\fP can operate in 3 different modes: -.br -* \fISingle Window\fP: This is the default mode. Each X screen -appears as a single \fIWindows\fP window and all X windows are contained -within this window. -(In X terminology, the \fIWindows\fP window contains the root window for -the screen) -.br -* \fIMulti-Window\fP: In this mode \fIXWin\fP uses its own integrated -window manager in order to handle the top-level X windows, in such a -way that they appear as normal \fIWindows\fP windows. -.br -* \fIRootless\fP: In this mode the X server works in a window -containing the whole screen but this root window (traditionally covered with an X hatch -pattern) is hidden from view, so only top-level X windows are seen. - -.SH OPTIONS -In addition to the normal server options described in the \fIXserver(1)\fP -manual page, \fIXWin\fP accepts the following command line switches, -\fIall\fP of which are optional: - -.SH OPTIONS CONTROLLING WINDOWING MODE -Only one of these options may be specified. -.TP 8 -.B (default) -Windowed or rooted mode. -Each X screen appears as a single \fIWindows\fP window and all X windows are -contained within those windows. -.TP 8 -.B \-multiwindow -Each top-level X window appears in its own \fIWindows\fP window. -Also start the integrated \fIWindows\fP-based window manager. -.TP 8 -.B \-rootless -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 -operations on the individual X windows. - -.SH OPTIONS FOR SPECIFYING X SCREENS -An X display may be composed of multiple screens. -The default behaviour is to create a single screen 0 that is roughly the -size of useful area of the primary monitor (allowing for any window -decorations and the task-bar). - -Screen specific parameters, such as \fB\-fullscreen\fP, can be applied as a -default to all screens by placing those screen specific parameters -before any \fB\-screen\fP parameter. Screen specific parameters placed after -the first \fB\-screen\fP parameter will apply only to the immediately -preceeding \fB\-screen\fP parameter. -.TP 8 -.B \-[no]multimonitors or \-[no]multiplemonitors -Create a screen 0 that covers all monitors [the primary monitor] on a system with -multiple monitors. -This option is currently enabled by default in \fB\-multiwindow\fP mode. -.TP 8 -.B "\-screen \fIscreen_number\fP [\fIW\fP \fIH\fP [\fIX\fP \fIY\fP] | [[\fIW\fPx\fIH\fP[+\fIX\fP+\fIY\fP]][@\fIM\fP]] ] " -Create screen number -.I screen_number -and optionally specify it's -.I height, -.I width -and -.I initial position. -Additionally a -.I -monitor number -(which count from 1) can be specified to place the screen on, -at which point, all coordinates become relative to that monitor. -Screen numbers must be contiguous starting from zero and cannot be duplicated. - -Examples: - -.I " -screen 0 @1 ; on 1st monitor using its full resolution (the default)" - -.I " -screen 0 800x600+100+100@2 ; on 2nd monitor offset 100,100 size 800x600" - -.I " -screen 0 1024x768@3 ; on 3rd monitor size 1024x768" - -.SH OPTIONS CONTROLLING THE APPEARANCE OF THE X SCREEN WINDOWS -These parameters only apply to windowed mode screens i.e. not -in \fB-multiwindow\fP or \fB-rootless\fP mode. -.TP 8 -.B "\-fullscreen" -The X server window takes the full screen, covering completely the -\fIWindows\fP desktop. -.TP 8 -.B \-nodecoration -Do not give the Cygwin/X window a \fIWindows\fP window border, title bar, -etc. -This parameter is ignored when the \fB\-fullscreen\fP parameter is specified. -.TP 8 -.B \-scrollbars -Alternative name for \fB\-resize=scrollbars\fP. - -.SH OPTIONS CONTROLLING RESIZE BEHAVIOUR -.TP 8 -.B \-resize[=none|scrollbars|randr] -Select the resize mode of an X screen. - -.RS -.IP \fB\-resize=none\fP 8 -(default). The screen is not resizable. - -In windowed mode, if the window has decorations, a fixed frame is used. - -.IP \fB\-resize=scrollbars\fP 8 -The screen window is resizeable, but the screen is not resizable. - -In windowed mode, if the window has decorations, a resizing frame is used. -Scrollbars are drawn when needed to allow the entire X screen -to viewed by adjusting them. - -This also permits screens bigger than the \fIWindows\fP virtual desktop to be used. - -This parameter is ignored in \fB-multiwindow\fP or \fB-rootless\fP mode. -Alternative name is \fB\-scrollbars\fP. - -.IP \fB\-resize=randr\fP 8 -The screen is resizable and the screen window is resizeable. - -In windowed mode, if the window has decorations, a resizing frame is used. - -Resizing the \fIWindows\fP window will use the RANDR extension to change -the size of the X screen. Likewise, changing the size of -the X screen using the RANDR extension will cause the size -of the \fIWindows\fP window containing the X screen to be changed. - -In \fB-multiwindow\fP or \fB-rootless\fP mode, if the X screen is -of the same dimensions as a Windows monitor or the virtual desktop, -the X server will respond to the WM_DISPLAYCHANGED sent when those -dimensions change by resizing the X screen. Changing the size -of the X screen using the RANDR extension is not permitted. - -The maximum dimensions of the screen are the dimensions of the \fIWindows\fP virtual desktop. - -.IP \fB\--resize\fP 8 -on its own is equivalent to \fB\--resize=randr\fP -.RE - -.SH OPTIONS CONTROLLING WINDOWS INTEGRATION -.TP 8 -.B \-[no]clipboard -Enables [disables] the integration between the Cygwin/X clipboard and -\fIWindows\fP clipboard. The default is enabled. -.TP 8 -.B "\-emulate3buttons [\fItimeout\fP]" -Emulate a three button mouse; pressing both buttons within -.I timeout -milliseconds causes an emulated middle button press. The default -.I timeout -is 50 milliseconds. Note that most mice with scroll wheel have middle -button functionality, usually you will need this option only if you have -a two button mouse without scroll wheel. -.TP 8 -.B \-[no]keyhook -Enable [disable] a low-level keyboard hook for catching -special keypresses like Menu and Alt+Tab and passing them to the X -Server instead of letting \fIWindows\fP handle them. -.TP 8 -.B \-lesspointer -Normally the \fIWindows\fP mouse cursor is hidden when the mouse is -over an active Cygwin/X window. This option causes the mouse cursor -also to be hidden when it is over an inactive Cygwin/X window. This -prevents the \fIWindows\fP mouse cursor from being drawn on top of the X -cursor. -This parameter has no effect unless \fB-swcursor\fP is also specified. -.TP 8 -.B \-swcursor -Disable the usage of the \fIWindows\fP cursor and use the X11 software cursor instead. -.TP 8 -.B \-[no]trayicon -Do not create a tray icon. Default is to create one -icon per screen. You can globally disable tray icons with -\fB\-notrayicon\fP, then enable it for specific screens with -\fB\-trayicon\fP for those screens. -.TP 8 -.B \-nounicodeclipboard -Do not use Unicode clipboard even if on a NT-based platform. -.TP 8 -.B \-[no]unixkill -Enable or disable the \fICtrl-Alt-Backspace\fP key combination as a -signal to exit the X Server. The \fICtrl-Alt-Backspace\fP key combination -is disabled by default. -.TP 8 -.B \-[no]winkill -Enable or disable the \fIAlt-F4\fP key combination as a signal to exit the -X Server. -The \fIAlt-F4\fP key combination is enabled by default. - -.SH DRAWING ENGINE OPTIONS -.TP 8 -.B "\-clipupdates \fInum_boxes\fP" -Specify an optional threshold, above which the regions in a shadow -update operation will be collected into a GDI clipping region. The -clipping region is then used to do a single bit block transfer that is -constrained to the updated area by the clipping region. There is some -overhead involved in creating, installing, destroying, and removing -the clipping region, thus there may not be much benefit for a small -number of boxes (less than 10). It is even possible that this -functionality does not provide a benefit at any number of boxes; we -can only determine the usefulness of this feature through testing. -This option probably has limited effect on current \fIWindows\fP versions -as they already perform GDI batching. -This parameter works in conjunction with engines 1, 2, and 4 (Shadow -GDI, Shadow DirectDraw, and Shadow DirectDraw Non-Locking, -respectively). -.TP 8 -.B "\-engine \fIengine_type_id\fP" -This option, which is intended for Cygwin/X developers, -overrides the server's automatically selected drawing engine type. This -parameter will be ignored if the specified drawing engine type is not -supported on the current system. - -Default behavior is to select the drawing engine with optimum performance that -supports the specified depth and window configuration. - -The engine type ids are: -.RS -.IP 1 4 -Shadow GDI -.IP 2 4 -Shadow DirectDraw -.IP 4 4 -Shadow DirectDraw Non-Locking -.IP 8 4 -Primary DirectDraw (unsupported, obsolete) -.IP 16 4 -Native GDI (unsupported, experimental and barely functional) -.RE - -.SH FULLSCREEN OPTIONS -.TP 8 -.B "\-depth \fIdepth\fP" -Specify the color depth, in bits per pixel, to use when running in -fullscreen with a DirectDraw engine. This parameter is ignored if -\fB\-fullscreen\fP is not specified. -.TP 8 -.B "\-refresh \fIrate_in_Hz\fP" -Specify an optional refresh rate to use when running in -fullscreen with a DirectDraw engine. This parameter is ignored if -\fB\-fullscreen\fP is not specified. - -.SH MISCELLANEOUS OPTIONS -See also the normal server options described in the \fIXserver(1)\fP -manual page - -.TP 8 -.B \-help -Write a help text listing supported command line options and their description to the console. -.TP 8 -.B \-ignoreinput -Ignore keyboard and mouse input. This is usually only used for testing -and debugging purposes. -.TP 8 -.B "\-logfile \fIfilename\fP" -Change the server log file from the default of \fI -__logdir__/XWin.n.log\fP, -where \fIn\fP is the display number of the XWin server, to \fIfilename\fP. -.TP 8 -.B "\-logverbose \fIlevel\fP" -Control the degree of verbosity of the log messages with the integer -parameter \fIlevel\fP. For \fIlevel\fP=0 only fatal errors are -reported, for \fIlevel\fP=1 simple information about -configuration is also given, for \fIlevel\fP=2 (default) -additional runtime information is recorded -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" -.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 program. The layout data is located at \fI -__datadir__/X11/xkb/\fP. Additional information is found in the -README files therein and in the man page of \fIsetxkbmap\fP. For example -in order to load a German layout for a pc105 keyboard one uses -the options: -.br -.I " \-xkblayout de \-xkbmodel pc105" - -Alternatively one may use the \fIsetxkbmap\fP program after \fIXWin\fP is -running. - -The default is to select a 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. - -.SH UNDOCUMENTED OPTIONS -These options are undocumented. Do not use them. - -.TP 8 -.B \-emulatepseudo -Create a depth 8 PseudoColor visual when running in depths 15, 16, 24, -or 32, collectively known as TrueColor depths. -Color map manipulation is not supported, so the PseudoColor visual will -not have the correct colors. -This option is intended to allow applications which only work with a depth 8 -visual to operate in TrueColor modes. -.TP 8 -.B \-internalwm -Run the internal window manager. - -.SH LOG FILE -As it runs \fIXWin\fP writes messages indicating the most relevant events -to the console -from which it was called and to a log file that by default is located at \fI -__logdir__/XWin.0.log\fP. This file is mainly for debugging purposes. - - -.SH PREFERENCES FILE -On startup \fIXWin\fP looks for the file \fI$HOME/.XWinrc\fP or, if -the previous file does not exist, \fI -__sysconfdir__/X11/system.XWinrc\fP. \fI.XWinrc\fP allows setting -preferences for the following: -.br -* To include items into the menu associated with the \fIXWin\fP icon -which is in the \fIWindows\fP system tray. This functions in all -modes that have a tray icon. -.br -* To include items in the system menu which is associated with the \fIWindows\fP -window that \fIXWin -multiwindow\fP produces for each top-level X -window, in both the generic case and for particular programs. -.br -* To change the icon that is associated to the \fIWindows\fP window that -\fIXWin -multiwindow\fP produces for each top-level X-window. -.br -* To change the style that is associated to the \fIWindows\fP window that -\fXWin I-multiwindow\fP produces for each top-level X window. -.PP -The format of the \fI.XWinrc\fP file is given in the man page XWinrc(5). - -.SH EXAMPLES -Need some examples - - -.SH "SEE ALSO" -X(__miscmansuffix__), Xserver(1), xdm(1), xinit(1), XWinrc(__filemansuffix__), setxkbmap(1) - - -.SH BUGS -.I XWin -and this man page still have many limitations. - -The \fIXWin\fP software is continuously developing; it is therefore possible that -this man page is not up to date. It is always prudent to -look also at the output of \fIXWin -help\fP in order to -check the options that are operative. - - -.SH AUTHORS -This list is by no means complete, but direct contributors to the -Cygwin/X project include (in alphabetical order by last name): Stuart -Adamson, Michael Bax, Jehan Bing, Lev Bishop, Dr. Peter Busch, Biju G -C, Robert Collins, Nick Crabtree, Early Ehlinger, Christopher Faylor, -John Fortin, Brian Genisio, Fabrizio Gennari, Alexander Gottwald, Ralf -Habacker, Colin Harrison, Matthieu Herrb, Alan Hourihane, Pierre A -Humblet, Harold L Hunt II, Dakshinamurthy Karra, Joe Krahn, -Paul Loewenstein, Kensuke Matsuzaki, -Takuma Murakami, Earle F. Philhower III, Benjamin Riefenstahl, Yaakov Selkowitz, -Suhaib Siddiqi, Jack Tanner, Jon Turney and Nicholas Wourms. +.TH XWIN 1 __vendorversion__
+.SH NAME
+XWin \- X Server for the Cygwin environment on Microsoft Windows
+
+
+.SH SYNOPSIS
+.B XWin
+[ options ] ...
+
+
+.SH DESCRIPTION
+\fIXWin\fP is an X Server for the X Window System on the Cygwin environment
+running on Microsoft Windows.
+
+
+.SH MODES
+\fIXWin\fP can operate in 3 different modes:
+.br
+* \fISingle Window\fP: This is the default mode. Each X screen
+appears as a single \fIWindows\fP window and all X windows are contained
+within this window.
+(In X terminology, the \fIWindows\fP window contains the root window for
+the screen)
+.br
+* \fIMulti-Window\fP: In this mode \fIXWin\fP uses its own integrated
+window manager in order to handle the top-level X windows, in such a
+way that they appear as normal \fIWindows\fP windows.
+.br
+* \fIRootless\fP: In this mode the X server works in a window
+containing the whole screen but this root window (traditionally covered with an X hatch
+pattern) is hidden from view, so only top-level X windows are seen.
+
+.SH OPTIONS
+In addition to the normal server options described in the \fIXserver(1)\fP
+manual page, \fIXWin\fP accepts the following command line switches,
+\fIall\fP of which are optional:
+
+.SH OPTIONS CONTROLLING WINDOWING MODE
+Only one of these options may be specified.
+.TP 8
+.B (default)
+Windowed or rooted mode.
+Each X screen appears as a single \fIWindows\fP window and all X windows are
+contained within those windows.
+.TP 8
+.B \-multiwindow
+Each top-level X window appears in its own \fIWindows\fP window.
+Also start the integrated \fIWindows\fP-based window manager.
+.TP 8
+.B \-rootless
+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
+operations on the individual X windows.
+
+.SH OPTIONS FOR SPECIFYING X SCREENS
+An X display may be composed of multiple screens.
+The default behaviour is to create a single screen 0 that is roughly the
+size of useful area of the primary monitor (allowing for any window
+decorations and the task-bar).
+
+Screen specific parameters can be applied as a
+default to all screens by placing those screen specific parameters
+before any \fB\-screen\fP parameter. Screen specific parameters placed after
+the first \fB\-screen\fP parameter will apply only to the immediately
+preceeding \fB\-screen\fP parameter.
+.TP 8
+.B \-[no]multimonitors or \-[no]multiplemonitors
+Create a screen 0 that covers all monitors [the primary monitor] on a system with
+multiple monitors.
+This option is currently enabled by default in \fB\-multiwindow\fP mode.
+.TP 8
+.B "\-screen \fIscreen_number\fP [\fIW\fP \fIH\fP [\fIX\fP \fIY\fP] | [[\fIW\fPx\fIH\fP[+\fIX\fP+\fIY\fP]][@\fIM\fP]] ] "
+Create screen number
+.I screen_number
+and optionally specify it's
+.I height,
+.I width
+and
+.I initial position.
+Additionally a
+.I
+monitor number
+(which count from 1) can be specified to place the screen on,
+at which point, all coordinates become relative to that monitor.
+Screen numbers must be contiguous starting from zero and cannot be duplicated.
+
+Examples:
+
+.I " -screen 0 @1 ; on 1st monitor using its full resolution (the default)"
+
+.I " -screen 0 800x600+100+100@2 ; on 2nd monitor offset 100,100 size 800x600"
+
+.I " -screen 0 1024x768@3 ; on 3rd monitor size 1024x768"
+
+.SH OPTIONS CONTROLLING THE APPEARANCE OF THE X SCREEN WINDOWS
+These parameters only apply to windowed mode screens i.e. not
+in \fB-multiwindow\fP or \fB-rootless\fP mode.
+.TP 8
+.B "\-fullscreen"
+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 \-nodecoration
+Do not give the Cygwin/X window a \fIWindows\fP window border, title bar,
+etc.
+This parameter is ignored when the \fB\-fullscreen\fP parameter is specified.
+.TP 8
+.B \-scrollbars
+Alternative name for \fB\-resize=scrollbars\fP.
+
+.SH OPTIONS CONTROLLING RESIZE BEHAVIOUR
+.TP 8
+.B \-resize[=none|scrollbars|randr]
+Select the resize mode of an X screen.
+
+.RS
+.IP \fB\-resize=none\fP 8
+(default). The screen is not resizable.
+
+In windowed mode, if the window has decorations, a fixed frame is used.
+
+.IP \fB\-resize=scrollbars\fP 8
+The screen window is resizeable, but the screen is not resizable.
+
+In windowed mode, if the window has decorations, a resizing frame is used.
+Scrollbars are drawn when needed to allow the entire X screen
+to viewed by adjusting them.
+
+This also permits screens bigger than the \fIWindows\fP virtual desktop to be used.
+
+This parameter is ignored in \fB-multiwindow\fP or \fB-rootless\fP mode.
+Alternative name is \fB\-scrollbars\fP.
+
+.IP \fB\-resize=randr\fP 8
+The screen is resizable and the screen window is resizeable.
+
+In windowed mode, if the window has decorations, a resizing frame is used.
+
+Resizing the \fIWindows\fP window will use the RANDR extension to change
+the size of the X screen. Likewise, changing the size of
+the X screen using the RANDR extension will cause the size
+of the \fIWindows\fP window containing the X screen to be changed.
+
+In \fB-multiwindow\fP or \fB-rootless\fP mode, if the X screen is
+of the same dimensions as a Windows monitor or the virtual desktop,
+the X server will respond to the WM_DISPLAYCHANGED sent when those
+dimensions change by resizing the X screen. Changing the size
+of the X screen using the RANDR extension is not permitted.
+
+The maximum dimensions of the screen are the dimensions of the \fIWindows\fP virtual desktop.
+
+.IP \fB\--resize\fP 8
+on its own is equivalent to \fB\--resize=randr\fP
+.RE
+
+.SH OPTIONS CONTROLLING WINDOWS INTEGRATION
+.TP 8
+.B \-[no]clipboard
+Enables [disables] the integration between the Cygwin/X clipboard and
+\fIWindows\fP clipboard. The default is enabled.
+.TP 8
+.B "\-emulate3buttons [\fItimeout\fP]"
+Emulate a three button mouse; pressing both buttons within
+.I timeout
+milliseconds causes an emulated middle button press. The default
+.I timeout
+is 50 milliseconds. Note that most mice with scroll wheel have middle
+button functionality, usually you will need this option only if you have
+a two button mouse without scroll wheel.
+.TP 8
+.B \-[no]keyhook
+Enable [disable] a low-level keyboard hook for catching
+special keypresses like Menu and Alt+Tab and passing them to the X
+Server instead of letting \fIWindows\fP handle them.
+.TP 8
+.B \-lesspointer
+Normally the \fIWindows\fP mouse cursor is hidden when the mouse is
+over an active Cygwin/X window. This option causes the mouse cursor
+also to be hidden when it is over an inactive Cygwin/X window. This
+prevents the \fIWindows\fP mouse cursor from being drawn on top of the X
+cursor.
+This parameter has no effect unless \fB-swcursor\fP is also specified.
+.TP 8
+.B \-swcursor
+Disable the usage of the \fIWindows\fP cursor and use the X11 software cursor instead.
+.TP 8
+.B \-[no]trayicon
+Do not create a tray icon. Default is to create one
+icon per screen. You can globally disable tray icons with
+\fB\-notrayicon\fP, then enable it for specific screens with
+\fB\-trayicon\fP for those screens.
+.TP 8
+.B \-nounicodeclipboard
+Do not use Unicode clipboard even if on a NT-based platform.
+.TP 8
+.B \-[no]unixkill
+Enable or disable the \fICtrl-Alt-Backspace\fP key combination as a
+signal to exit the X Server. The \fICtrl-Alt-Backspace\fP key combination
+is disabled by default.
+.TP 8
+.B \-[no]winkill
+Enable or disable the \fIAlt-F4\fP key combination as a signal to exit the
+X Server.
+The \fIAlt-F4\fP key combination is enabled by default.
+
+.SH DRAWING ENGINE OPTIONS
+.TP 8
+.B "\-clipupdates \fInum_boxes\fP"
+Specify an optional threshold, above which the regions in a shadow
+update operation will be collected into a GDI clipping region. The
+clipping region is then used to do a single bit block transfer that is
+constrained to the updated area by the clipping region. There is some
+overhead involved in creating, installing, destroying, and removing
+the clipping region, thus there may not be much benefit for a small
+number of boxes (less than 10). It is even possible that this
+functionality does not provide a benefit at any number of boxes; we
+can only determine the usefulness of this feature through testing.
+This option probably has limited effect on current \fIWindows\fP versions
+as they already perform GDI batching.
+This parameter works in conjunction with engines 1, 2, and 4 (Shadow
+GDI, Shadow DirectDraw, and Shadow DirectDraw Non-Locking,
+respectively).
+.TP 8
+.B "\-engine \fIengine_type_id\fP"
+This option, which is intended for Cygwin/X developers,
+overrides the server's automatically selected drawing engine type. This
+parameter will be ignored if the specified drawing engine type is not
+supported on the current system.
+
+Default behavior is to select the drawing engine with optimum performance that
+supports the specified depth and window configuration.
+
+The engine type ids are:
+.RS
+.IP 1 4
+Shadow GDI
+.IP 2 4
+Shadow DirectDraw
+.IP 4 4
+Shadow DirectDraw Non-Locking
+.IP 8 4
+Primary DirectDraw (unsupported, obsolete)
+.IP 16 4
+Native GDI (unsupported, experimental and barely functional)
+.RE
+
+.SH FULLSCREEN OPTIONS
+.TP 8
+.B "\-depth \fIdepth\fP"
+Specify the color depth, in bits per pixel, to use when running in
+fullscreen with a DirectDraw engine. This parameter is ignored if
+\fB\-fullscreen\fP is not specified.
+.TP 8
+.B "\-refresh \fIrate_in_Hz\fP"
+Specify an optional refresh rate to use when running in
+fullscreen with a DirectDraw engine. This parameter is ignored if
+\fB\-fullscreen\fP is not specified.
+
+.SH MISCELLANEOUS OPTIONS
+See also the normal server options described in the \fIXserver(1)\fP
+manual page
+
+.TP 8
+.B \-help
+Write a help text listing supported command line options and their description to the console.
+.TP 8
+.B \-ignoreinput
+Ignore keyboard and mouse input. This is usually only used for testing
+and debugging purposes.
+.TP 8
+.B "\-logfile \fIfilename\fP"
+Change the server log file from the default of \fI
+__logdir__/XWin.n.log\fP,
+where \fIn\fP is the display number of the XWin server, to \fIfilename\fP.
+.TP 8
+.B "\-logverbose \fIlevel\fP"
+Control the degree of verbosity of the log messages with the integer
+parameter \fIlevel\fP. For \fIlevel\fP=0 only fatal errors are
+reported, for \fIlevel\fP=1 simple information about
+configuration is also given, for \fIlevel\fP=2 (default)
+additional runtime information is recorded
+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"
+.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 program. The layout data is located at \fI
+__datadir__/X11/xkb/\fP. Additional information is found in the
+README files therein and in the man page of \fIsetxkbmap\fP. For example
+in order to load a German layout for a pc105 keyboard one uses
+the options:
+.br
+.I " \-xkblayout de \-xkbmodel pc105"
+
+Alternatively one may use the \fIsetxkbmap\fP program after \fIXWin\fP is
+running.
+
+The default is to select a 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.
+
+.SH UNDOCUMENTED OPTIONS
+These options are undocumented. Do not use them.
+
+.TP 8
+.B \-emulatepseudo
+Create a depth 8 PseudoColor visual when running in depths 15, 16, 24,
+or 32, collectively known as TrueColor depths.
+Color map manipulation is not supported, so the PseudoColor visual will
+not have the correct colors.
+This option is intended to allow applications which only work with a depth 8
+visual to operate in TrueColor modes.
+.TP 8
+.B \-internalwm
+Run the internal window manager.
+
+.SH LOG FILE
+As it runs \fIXWin\fP writes messages indicating the most relevant events
+to the console
+from which it was called and to a log file that by default is located at \fI
+__logdir__/XWin.0.log\fP. This file is mainly for debugging purposes.
+
+
+.SH PREFERENCES FILE
+On startup \fIXWin\fP looks for the file \fI$HOME/.XWinrc\fP or, if
+the previous file does not exist, \fI
+__sysconfdir__/X11/system.XWinrc\fP. \fI.XWinrc\fP allows setting
+preferences for the following:
+.br
+* To include items into the menu associated with the \fIXWin\fP icon
+which is in the \fIWindows\fP system tray. This functions in all
+modes that have a tray icon.
+.br
+* To include items in the system menu which is associated with the \fIWindows\fP
+window that \fIXWin -multiwindow\fP produces for each top-level X
+window, in both the generic case and for particular programs.
+.br
+* To change the icon that is associated to the \fIWindows\fP window that
+\fIXWin -multiwindow\fP produces for each top-level X-window.
+.br
+* To change the style that is associated to the \fIWindows\fP window that
+\fXWin I-multiwindow\fP produces for each top-level X window.
+.PP
+The format of the \fI.XWinrc\fP file is given in the man page XWinrc(5).
+
+.SH EXAMPLES
+Need some examples
+
+
+.SH "SEE ALSO"
+X(__miscmansuffix__), Xserver(1), xdm(1), xinit(1), XWinrc(__filemansuffix__), setxkbmap(1)
+
+
+.SH BUGS
+.I XWin
+and this man page still have many limitations.
+
+The \fIXWin\fP software is continuously developing; it is therefore possible that
+this man page is not up to date. It is always prudent to
+look also at the output of \fIXWin -help\fP in order to
+check the options that are operative.
+
+
+.SH AUTHORS
+This list is by no means complete, but direct contributors to the
+Cygwin/X project include (in alphabetical order by last name): Stuart
+Adamson, Michael Bax, Jehan Bing, Lev Bishop, Dr. Peter Busch, Biju G
+C, Robert Collins, Nick Crabtree, Early Ehlinger, Christopher Faylor,
+John Fortin, Brian Genisio, Fabrizio Gennari, Alexander Gottwald, Ralf
+Habacker, Colin Harrison, Matthieu Herrb, Alan Hourihane, Pierre A
+Humblet, Harold L Hunt II, Dakshinamurthy Karra, Joe Krahn,
+Paul Loewenstein, Kensuke Matsuzaki,
+Takuma Murakami, Earle F. Philhower III, Benjamin Riefenstahl, Yaakov Selkowitz,
+Suhaib Siddiqi, Jack Tanner, Jon Turney and Nicholas Wourms.
diff --git a/xorg-server/hw/xwin/win.h b/xorg-server/hw/xwin/win.h index 2dad44778..614c6b23f 100644 --- a/xorg-server/hw/xwin/win.h +++ b/xorg-server/hw/xwin/win.h @@ -170,7 +170,6 @@ typedef int pid_t; #include "input.h"
#include "mipointer.h"
#include "X11/keysym.h"
-#include "mibstore.h"
#include "micoord.h"
#include "dix.h"
#include "miline.h"
diff --git a/xorg-server/hw/xwin/winclipboardxevents.c b/xorg-server/hw/xwin/winclipboardxevents.c index 00bf90a28..b3ed5eba5 100644 --- a/xorg-server/hw/xwin/winclipboardxevents.c +++ b/xorg-server/hw/xwin/winclipboardxevents.c @@ -830,7 +830,7 @@ winClipboardFlushXEvents (HWND hwnd, break;
case MappingNotify:
- XRefreshKeyboardMapping((XMappingEvent *)&event);
+ XRefreshKeyboardMapping((XMappingEvent *)&event);
break;
default:
diff --git a/xorg-server/hw/xwin/winmonitors.c b/xorg-server/hw/xwin/winmonitors.c index 876d23437..f78734b9b 100644 --- a/xorg-server/hw/xwin/winmonitors.c +++ b/xorg-server/hw/xwin/winmonitors.c @@ -1,73 +1,73 @@ -/* - -Copyright 1993, 1998 The Open Group -Copyright (C) Colin Harrison 2005-2008 - -Permission to use, copy, modify, distribute, and sell this software and its -documentation for any purpose is hereby granted without fee, provided that -the above copyright notice appear in all copies and that both that -copyright notice and this permission notice appear in supporting -documentation. - -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 OPEN GROUP 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 Open Group 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 Open Group. - -*/ - -#ifdef HAVE_XWIN_CONFIG_H -#include <xwin-config.h> -#endif - -#include "win.h" -#define COMPILE_MULTIMON_STUBS -#include <multimon.h> -#include "winmonitors.h" - -/* - * getMonitorInfo - callback function used to return information from the enumeration of monitors attached - */ - -static -wBOOL CALLBACK getMonitorInfo(HMONITOR hMonitor, HDC hdc, LPRECT rect, LPARAM _data) -{ - struct GetMonitorInfoData* data = (struct GetMonitorInfoData*)_data; - // only get data for monitor number specified in <data> - data->monitorNum++; - if (data->monitorNum == data->requestedMonitor) - { - data->bMonitorSpecifiedExists = TRUE; - data->monitorOffsetX = rect->left; - data->monitorOffsetY = rect->top; - data->monitorHeight = rect->bottom - rect->top; - data->monitorWidth = rect->right - rect->left; - return FALSE; - } - return TRUE; -} - -Bool QueryMonitor(int index, struct GetMonitorInfoData *data) -{ - /* prepare data */ - if (data == NULL) - return FALSE; - memset(data, 0, sizeof(*data)); - data->requestedMonitor = index; - - /* query information */ - xEnumDisplayMonitors(NULL, NULL, getMonitorInfo, (LPARAM) data); - - return TRUE; -} +/*
+
+Copyright 1993, 1998 The Open Group
+Copyright (C) Colin Harrison 2005-2008
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+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 OPEN GROUP 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 Open Group 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 Open Group.
+
+*/
+
+#ifdef HAVE_XWIN_CONFIG_H
+#include <xwin-config.h>
+#endif
+
+#include "win.h"
+#define COMPILE_MULTIMON_STUBS
+#include <multimon.h>
+#include "winmonitors.h"
+
+/*
+ * getMonitorInfo - callback function used to return information from the enumeration of monitors attached
+ */
+
+static
+wBOOL CALLBACK getMonitorInfo(HMONITOR hMonitor, HDC hdc, LPRECT rect, LPARAM _data)
+{
+ struct GetMonitorInfoData* data = (struct GetMonitorInfoData*)_data;
+ // only get data for monitor number specified in <data>
+ data->monitorNum++;
+ if (data->monitorNum == data->requestedMonitor)
+ {
+ data->bMonitorSpecifiedExists = TRUE;
+ data->monitorOffsetX = rect->left;
+ data->monitorOffsetY = rect->top;
+ data->monitorHeight = rect->bottom - rect->top;
+ data->monitorWidth = rect->right - rect->left;
+ return FALSE;
+ }
+ return TRUE;
+}
+
+Bool QueryMonitor(int index, struct GetMonitorInfoData *data)
+{
+ /* prepare data */
+ if (data == NULL)
+ return FALSE;
+ memset(data, 0, sizeof(*data));
+ data->requestedMonitor = index;
+
+ /* query information */
+ xEnumDisplayMonitors(NULL, NULL, getMonitorInfo, (LPARAM) data);
+
+ return TRUE;
+}
diff --git a/xorg-server/hw/xwin/winmultiwindowicons.c b/xorg-server/hw/xwin/winmultiwindowicons.c index 3186cd7a0..853d63864 100644 --- a/xorg-server/hw/xwin/winmultiwindowicons.c +++ b/xorg-server/hw/xwin/winmultiwindowicons.c @@ -37,8 +37,6 @@ #include "winprefs.h"
#include "propertyst.h"
-
-#include "propertyst.h"
#include "windowstr.h"
@@ -632,6 +630,7 @@ void winSelectIcons(WindowPtr pWin, HICON *pIcon, HICON *pSmallIcon) *pIcon = hIcon;
else
winDestroyIcon(hIcon);
+
if (pSmallIcon)
*pSmallIcon = hSmallIcon;
else
@@ -640,7 +639,7 @@ void winSelectIcons(WindowPtr pWin, HICON *pIcon, HICON *pSmallIcon) void winDestroyIcon(HICON hIcon)
{
- /* Delete the icon if its not the default */
+ /* Delete the icon if its not one of the application defaults or an override */
if (hIcon &&
hIcon != g_hIconX &&
hIcon != g_hSmallIconX &&
diff --git a/xorg-server/hw/xwin/winmultiwindowwindow.c b/xorg-server/hw/xwin/winmultiwindowwindow.c index 1e95fecc4..ceb8dff04 100644 --- a/xorg-server/hw/xwin/winmultiwindowwindow.c +++ b/xorg-server/hw/xwin/winmultiwindowwindow.c @@ -586,7 +586,7 @@ winDestroyWindowsWindow (WindowPtr pWin) BOOL oldstate = winInDestroyWindowsWindow;
HICON hIcon;
HICON hIconSm;
-
+
#if CYGMULTIWINDOW_DEBUG
winDebug ("winDestroyWindowsWindow\n");
#endif
@@ -602,6 +602,7 @@ winDestroyWindowsWindow (WindowPtr pWin) hIconSm = (HICON)SendMessage(pWinPriv->hWnd, WM_GETICON, ICON_SMALL, 0);
SetProp (pWinPriv->hWnd, WIN_WINDOW_PROP, NULL);
+
/* Destroy the Windows window */
DestroyWindow (pWinPriv->hWnd);
diff --git a/xorg-server/hw/xwin/winmultiwindowwm.c b/xorg-server/hw/xwin/winmultiwindowwm.c index f178967e1..fae132329 100644 --- a/xorg-server/hw/xwin/winmultiwindowwm.c +++ b/xorg-server/hw/xwin/winmultiwindowwm.c @@ -1656,6 +1656,7 @@ winApplyHints (Display *pDisplay, Window iWindow, HWND hWnd, HWND *zstyle) style = STYLE_NONE;
}
}
+
if (style & STYLE_TOPMOST) *zstyle = HWND_TOPMOST;
else if (style & STYLE_MAXIMIZE) maxmin = (hint & ~HINT_MIN) | HINT_MAX;
else if (style & STYLE_MINIMIZE) maxmin = (hint & ~HINT_MAX) | HINT_MIN;
diff --git a/xorg-server/hw/xwin/winpfbdd.c b/xorg-server/hw/xwin/winpfbdd.c index c6d0167ca..02f6ffc1f 100644 --- a/xorg-server/hw/xwin/winpfbdd.c +++ b/xorg-server/hw/xwin/winpfbdd.c @@ -1,674 +1,675 @@ -/* - *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 "win.h" - - -/* - * Local function prototypes - */ - -static Bool -winAllocateFBPrimaryDD (ScreenPtr pScreen); - -static Bool -winCloseScreenPrimaryDD (int nIndex, ScreenPtr pScreen); - -static Bool -winInitVisualsPrimaryDD (ScreenPtr pScreen); - -static Bool -winAdjustVideoModePrimaryDD (ScreenPtr pScreen); - -static Bool -winActivateAppPrimaryDD (ScreenPtr pScreen); - -static Bool -winHotKeyAltTabPrimaryDD (ScreenPtr pScreen); - - -/* - * Create a DirectDraw primary surface - */ - -static Bool -winAllocateFBPrimaryDD (ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; - HRESULT ddrval = DD_OK; - DDSURFACEDESC ddsd; - DDSURFACEDESC *pddsdPrimary = NULL; - DDSURFACEDESC *pddsdOffscreen = NULL; - RECT rcClient; - - winDebug ("winAllocateFBPrimaryDD\n"); - - /* Get client area location in screen coords */ - GetClientRect (pScreenPriv->hwndScreen, &rcClient); - MapWindowPoints (pScreenPriv->hwndScreen, - HWND_DESKTOP, - (LPPOINT)&rcClient, 2); - - /* Create a DirectDraw object, store the address at lpdd */ - ddrval = (*g_fpDirectDrawCreate) (NULL, &pScreenPriv->pdd, NULL); - if (ddrval != DD_OK) - FatalError ("winAllocateFBPrimaryDD - Could not start DirectDraw\n"); - - /* Get a DirectDraw2 interface pointer */ - ddrval = IDirectDraw_QueryInterface (pScreenPriv->pdd, - &IID_IDirectDraw2, - (LPVOID*) &pScreenPriv->pdd2); - if (FAILED (ddrval)) - { - ErrorF ("winAllocateFBShadowDD - Failed DD2 query: %08x\n", - (unsigned int) ddrval); - return FALSE; - } - - - winDebug ("winAllocateFBPrimaryDD - Created and initialized DD\n"); - - /* Are we windowed or fullscreen? */ - if (pScreenInfo->fFullScreen) - { - /* Full screen mode */ - ddrval = IDirectDraw2_SetCooperativeLevel (pScreenPriv->pdd2, - pScreenPriv->hwndScreen, - DDSCL_FULLSCREEN - | DDSCL_EXCLUSIVE); - if (FAILED (ddrval)) - FatalError ("winAllocateFBPrimaryDD - Could not set " - "cooperative level\n"); - - /* Change the video mode to the mode requested */ - ddrval = IDirectDraw2_SetDisplayMode (pScreenPriv->pdd2, - pScreenInfo->dwWidth, - pScreenInfo->dwHeight, - pScreenInfo->dwBPP, - pScreenInfo->dwRefreshRate, - 0); - if (FAILED (ddrval)) - FatalError ("winAllocateFBPrimaryDD - Could not set " - "full screen display mode\n"); - } - else - { - /* Windowed mode */ - ddrval = IDirectDraw2_SetCooperativeLevel (pScreenPriv->pdd2, - pScreenPriv->hwndScreen, - DDSCL_NORMAL); - if (FAILED (ddrval)) - FatalError ("winAllocateFBPrimaryDD - Could not set " - "cooperative level\n"); - } - - /* Describe the primary surface */ - ZeroMemory (&ddsd, sizeof (ddsd)); - ddsd.dwSize = sizeof (ddsd); - ddsd.dwFlags = DDSD_CAPS; - ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; - - /* Create the primary surface */ - ddrval = IDirectDraw2_CreateSurface (pScreenPriv->pdd2, - &ddsd, - &pScreenPriv->pddsPrimary, - NULL); - if (FAILED (ddrval)) - FatalError ("winAllocateFBPrimaryDD - Could not create primary " - "surface %08x\n", (unsigned int) ddrval); - - winDebug ("winAllocateFBPrimaryDD - Created primary\n"); - - /* Allocate a DD surface description for our screen privates */ - pddsdPrimary = pScreenPriv->pddsdPrimary - = malloc (sizeof (DDSURFACEDESC)); - if (pddsdPrimary == NULL) - FatalError ("winAllocateFBPrimaryDD - Could not allocate surface " - "description memory\n"); - ZeroMemory (pddsdPrimary, sizeof (*pddsdPrimary)); - pddsdPrimary->dwSize = sizeof (*pddsdPrimary); - - /* Describe the offscreen surface to be created */ - /* - * NOTE: Do not use a DDSCAPS_VIDEOMEMORY surface, - * as drawing, locking, and unlocking take forever - * with video memory surfaces. In addition, - * video memory is a somewhat scarce resource, - * so you shouldn't be allocating video memory when - * you have the option of using system memory instead. - */ - ZeroMemory (&ddsd, sizeof (ddsd)); - ddsd.dwSize = sizeof (ddsd); - ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; - ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; - ddsd.dwHeight = pScreenInfo->dwHeight; - ddsd.dwWidth = pScreenInfo->dwWidth; - - /* Create the shadow surface */ - ddrval = IDirectDraw2_CreateSurface (pScreenPriv->pdd2, - &ddsd, - &pScreenPriv->pddsOffscreen, - NULL); - if (ddrval != DD_OK) - FatalError ("winAllocateFBPrimaryDD - Could not create shadow " - "surface\n"); - - winDebug ("winAllocateFBPrimaryDD - Created offscreen\n"); - - /* Allocate a DD surface description for our screen privates */ - pddsdOffscreen = pScreenPriv->pddsdOffscreen - = malloc (sizeof (DDSURFACEDESC)); - if (pddsdOffscreen == NULL) - FatalError ("winAllocateFBPrimaryDD - Could not allocate surface " - "description memory\n"); - ZeroMemory (pddsdOffscreen, sizeof (*pddsdOffscreen)); - pddsdOffscreen->dwSize = sizeof (*pddsdOffscreen); - - winDebug ("winAllocateFBPrimaryDD - Locking primary\n"); - - /* Lock the primary surface */ - ddrval = IDirectDrawSurface2_Lock (pScreenPriv->pddsPrimary, - pScreenInfo->fFullScreen ? NULL:&rcClient, - pddsdPrimary, - DDLOCK_WAIT, - NULL); - if (ddrval != DD_OK || pddsdPrimary->lpSurface == NULL) - FatalError ("winAllocateFBPrimaryDD - Could not lock " - "primary surface\n"); - - winDebug ("winAllocateFBPrimaryDD - Locked primary\n"); - - /* We don't know how to deal with anything other than RGB */ - if (!(pddsdPrimary->ddpfPixelFormat.dwFlags & DDPF_RGB)) - FatalError ("winAllocateFBPrimaryDD - Color format other than RGB\n"); - - /* Grab the pitch from the surface desc */ - pScreenInfo->dwStride = (pddsdPrimary->u1.lPitch * 8) - / pScreenInfo->dwBPP; - - /* Save the pointer to our surface memory */ - pScreenInfo->pfb = pddsdPrimary->lpSurface; - - /* Grab the color depth and masks from the surface description */ - pScreenPriv->dwRedMask = pddsdPrimary->ddpfPixelFormat.u2.dwRBitMask; - pScreenPriv->dwGreenMask = pddsdPrimary->ddpfPixelFormat.u3.dwGBitMask; - pScreenPriv->dwBlueMask = pddsdPrimary->ddpfPixelFormat.u4.dwBBitMask; - - winDebug ("winAllocateFBPrimaryDD - Returning\n"); - - return TRUE; -} - -static void -winFreeFBPrimaryDD (ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; - - /* Free the offscreen surface, if there is one */ - if (pScreenPriv->pddsOffscreen) - { - IDirectDrawSurface2_Unlock (pScreenPriv->pddsOffscreen, NULL); - IDirectDrawSurface2_Release (pScreenPriv->pddsOffscreen); - pScreenPriv->pddsOffscreen = NULL; - } - - /* Release the primary surface, if there is one */ - if (pScreenPriv->pddsPrimary) - { - IDirectDrawSurface2_Unlock (pScreenPriv->pddsPrimary, NULL); - IDirectDrawSurface2_Release (pScreenPriv->pddsPrimary); - pScreenPriv->pddsPrimary = NULL; - } - - /* Free the DirectDraw object, if there is one */ - if (pScreenPriv->pdd) - { - IDirectDraw2_RestoreDisplayMode (pScreenPriv->pdd); - IDirectDraw2_Release (pScreenPriv->pdd); - pScreenPriv->pdd = NULL; - } - - /* Invalidate the ScreenInfo's fb pointer */ - pScreenInfo->pfb = NULL; -} - -static Bool -winInitScreenPrimaryDD(ScreenPtr pScreen) -{ - return winAllocateFBPrimaryDD(pScreen); -} - -/* - * Call the wrapped CloseScreen function. - * - * Free our resources and private structures. - */ - -static Bool -winCloseScreenPrimaryDD (int nIndex, ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; - Bool fReturn; - - ErrorF ("winCloseScreenPrimaryDD - Freeing screen resources\n"); - - /* Flag that the screen is closed */ - pScreenPriv->fClosed = TRUE; - pScreenPriv->fActive = FALSE; - - /* Call the wrapped CloseScreen procedure */ - WIN_UNWRAP(CloseScreen); - fReturn = (*pScreen->CloseScreen) (nIndex, pScreen); - - /* Delete the window property */ - RemoveProp (pScreenPriv->hwndScreen, WIN_SCR_PROP); - - winFreeFBPrimaryDD(pScreen); - - /* Delete tray icon, if we have one */ - if (!pScreenInfo->fNoTrayIcon) - winDeleteNotifyIcon (pScreenPriv); - - /* Free the exit confirmation dialog box, if it exists */ - if (g_hDlgExit != NULL) - { - DestroyWindow (g_hDlgExit); - g_hDlgExit = NULL; - } - - /* Kill our window */ - if (pScreenPriv->hwndScreen) - { - DestroyWindow (pScreenPriv->hwndScreen); - pScreenPriv->hwndScreen = NULL; - } - - /* Kill our screeninfo's pointer to the screen */ - pScreenInfo->pScreen = NULL; - - /* Free the screen privates for this screen */ - free ((pointer) pScreenPriv); - - return fReturn; -} - - -/* - * Tell mi what sort of visuals we need. - * - * Generally we only need one visual, as our screen can only - * handle one format at a time, I believe. You may want - * to verify that last sentence. - */ - -static Bool -winInitVisualsPrimaryDD (ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; - DWORD dwRedBits, dwGreenBits, dwBlueBits; - - /* Count the number of ones in each color mask */ - dwRedBits = winCountBits (pScreenPriv->dwRedMask); - dwGreenBits = winCountBits (pScreenPriv->dwGreenMask); - dwBlueBits = winCountBits (pScreenPriv->dwBlueMask); - - /* Store the maximum number of ones in a color mask as the bitsPerRGB */ - if (dwRedBits > dwGreenBits && dwRedBits > dwBlueBits) - pScreenPriv->dwBitsPerRGB = dwRedBits; - else if (dwGreenBits > dwRedBits && dwGreenBits > dwBlueBits) - pScreenPriv->dwBitsPerRGB = dwGreenBits; - else - pScreenPriv->dwBitsPerRGB = dwBlueBits; - - winDebug ("winInitVisualsPrimaryDD - Masks: %08x %08x %08x bpRGB: %d\n", - (unsigned int) pScreenPriv->dwRedMask, - (unsigned int) pScreenPriv->dwGreenMask, - (unsigned int) pScreenPriv->dwBlueMask, - (int) pScreenPriv->dwBitsPerRGB); - - /* Create a single visual according to the Windows screen depth */ - switch (pScreenInfo->dwDepth) - { - case 24: - case 16: - case 15: - if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth, - TrueColorMask, - pScreenPriv->dwBitsPerRGB, - TrueColor, - pScreenPriv->dwRedMask, - pScreenPriv->dwGreenMask, - pScreenPriv->dwBlueMask)) - { - ErrorF ("winInitVisualsPrimaryDD - " - "miSetVisualTypesAndMasks failed\n"); - return FALSE; - } - break; - - case 8: - winDebug ("winInitVisuals - Calling miSetVisualTypesAndMasks\n"); - if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth, - PseudoColorMask, - pScreenPriv->dwBitsPerRGB, - PseudoColor, - pScreenPriv->dwRedMask, - pScreenPriv->dwGreenMask, - pScreenPriv->dwBlueMask)) - { - ErrorF ("winInitVisualsPrimaryDD - " - "miSetVisualTypesAndMasks failed\n"); - return FALSE; - } - winDebug ("winInitVisualsPrimaryDD - Returned from " - "miSetVisualTypesAndMasks\n"); - break; - - default: - ErrorF ("winInitVisualsPrimaryDD - Unknown screen depth\n"); - return FALSE; - } - - winDebug ("winInitVisualsPrimaryDD - Returning\n"); - - return TRUE; -} - - -static Bool -winAdjustVideoModePrimaryDD (ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; - HDC hdc = NULL; - DWORD dwBPP; - - /* We're in serious trouble if we can't get a DC */ - hdc = GetDC (NULL); - if (hdc == NULL) - { - ErrorF ("winAdjustVideoModePrimaryDD - GetDC failed\n"); - return FALSE; - } - - /* Query GDI for current display depth */ - dwBPP = GetDeviceCaps (hdc, BITSPIXEL); - - /* DirectDraw can only change the depth in fullscreen mode */ - if (!(pScreenInfo->fFullScreen && - (pScreenInfo->dwBPP != WIN_DEFAULT_BPP))) - { - /* Otherwise, We'll use GDI's depth */ - pScreenInfo->dwBPP = dwBPP; - } - - /* Release our DC */ - ReleaseDC (NULL, hdc); - - return TRUE; -} - - -/* - * We need to blit our offscreen fb to - * the screen when we are activated, and we need to point - * the fb code back to the primary surface memory. - */ - -static Bool -winActivateAppPrimaryDD (ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; - RECT rcSrc, rcClient; - HRESULT ddrval = DD_OK; - - /* Check for errors */ - if (pScreenPriv == NULL - || pScreenPriv->pddsPrimary == NULL - || pScreenPriv->pddsOffscreen == NULL) - return FALSE; - - /* Check for do-nothing */ - if (!pScreenPriv->fActive) - return TRUE; - - /* We are activating */ - ddrval = IDirectDrawSurface2_IsLost (pScreenPriv->pddsOffscreen); - if (ddrval == DD_OK) - { - IDirectDrawSurface2_Unlock (pScreenPriv->pddsOffscreen, - NULL); - /* - * We don't check for an error from Unlock, because it - * doesn't matter if the Unlock failed. - */ - } - - /* Restore both surfaces, just cause I like it that way */ - IDirectDrawSurface2_Restore (pScreenPriv->pddsOffscreen); - IDirectDrawSurface2_Restore (pScreenPriv->pddsPrimary); - - /* Get client area in screen coords */ - GetClientRect (pScreenPriv->hwndScreen, &rcClient); - MapWindowPoints (pScreenPriv->hwndScreen, - HWND_DESKTOP, - (LPPOINT)&rcClient, 2); - - /* Setup a source rectangle */ - rcSrc.left = 0; - rcSrc.top = 0; - rcSrc.right = pScreenInfo->dwWidth; - rcSrc.bottom = pScreenInfo->dwHeight; - - ddrval = IDirectDrawSurface2_Blt (pScreenPriv->pddsPrimary, - &rcClient, - pScreenPriv->pddsOffscreen, - &rcSrc, - DDBLT_WAIT, - NULL); - if (ddrval != DD_OK) - FatalError ("winActivateAppPrimaryDD () - Failed blitting offscreen " - "surface to primary surface %08x\n", (unsigned int) ddrval); - - /* Lock the primary surface */ - ddrval = IDirectDrawSurface2_Lock (pScreenPriv->pddsPrimary, - &rcClient, - pScreenPriv->pddsdPrimary, - DDLOCK_WAIT, - NULL); - if (ddrval != DD_OK - || pScreenPriv->pddsdPrimary->lpSurface == NULL) - FatalError ("winActivateAppPrimaryDD () - Could not lock " - "primary surface\n"); - - /* Notify FB of the new memory pointer */ - winUpdateFBPointer (pScreen, - pScreenPriv->pddsdPrimary->lpSurface); - - /* - * Register the Alt-Tab combo as a hotkey so we can copy - * the primary framebuffer before the display mode changes - */ - RegisterHotKey (pScreenPriv->hwndScreen, 1, MOD_ALT, 9); - - return TRUE; -} - - -/* - * Handle the Alt+Tab hotkey. - * - * We need to save the primary fb to an offscreen fb when - * we get deactivated, and point the fb code at the offscreen - * fb for the duration of the deactivation. - */ - -static Bool -winHotKeyAltTabPrimaryDD (ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; - RECT rcClient, rcSrc; - HRESULT ddrval = DD_OK; - - winDebug ("\nwinHotKeyAltTabPrimaryDD\n\n"); - - /* Alt+Tab was pressed, we will lose focus very soon */ - pScreenPriv->fActive = FALSE; - - /* Check for error conditions */ - if (pScreenPriv->pddsPrimary == NULL - || pScreenPriv->pddsOffscreen == NULL) - return FALSE; - - /* Get client area in screen coords */ - GetClientRect (pScreenPriv->hwndScreen, &rcClient); - MapWindowPoints (pScreenPriv->hwndScreen, - HWND_DESKTOP, - (LPPOINT)&rcClient, 2); - - /* Did we loose the primary surface? */ - ddrval = IDirectDrawSurface2_IsLost (pScreenPriv->pddsPrimary); - if (ddrval == DD_OK) - { - ddrval = IDirectDrawSurface2_Unlock (pScreenPriv->pddsPrimary, - NULL); - if (FAILED (ddrval)) - FatalError ("winHotKeyAltTabPrimaryDD - Failed unlocking primary " - "surface\n"); - } - - /* Setup a source rectangle */ - rcSrc.left = 0; - rcSrc.top = 0; - rcSrc.right = pScreenInfo->dwWidth; - rcSrc.bottom = pScreenInfo->dwHeight; - - /* Blit the primary surface to the offscreen surface */ - ddrval = IDirectDrawSurface2_Blt (pScreenPriv->pddsOffscreen, - NULL, /* should be rcDest */ - pScreenPriv->pddsPrimary, - NULL, - DDBLT_WAIT, - NULL); - if (ddrval == DDERR_SURFACELOST) - { - IDirectDrawSurface2_Restore (pScreenPriv->pddsOffscreen); - IDirectDrawSurface2_Restore (pScreenPriv->pddsPrimary); - - /* Blit the primary surface to the offscreen surface */ - ddrval = IDirectDrawSurface2_Blt (pScreenPriv->pddsOffscreen, - NULL, - pScreenPriv->pddsPrimary, - NULL, - DDBLT_WAIT, - NULL); - if (FAILED (ddrval)) - FatalError ("winHotKeyAltTabPrimaryDD - Failed blitting primary " - "surface to offscreen surface: %08x\n", - (unsigned int) ddrval); - } - else - { - FatalError ("winHotKeyAltTabPrimaryDD - Unknown error from " - "Blt: %08dx\n", (unsigned int) ddrval); - } - - /* Lock the offscreen surface */ - ddrval = IDirectDrawSurface2_Lock (pScreenPriv->pddsOffscreen, - NULL, - pScreenPriv->pddsdOffscreen, - DDLOCK_WAIT, - NULL); - if (ddrval != DD_OK - || pScreenPriv->pddsdPrimary->lpSurface == NULL) - FatalError ("winHotKeyAltTabPrimaryDD - Could not lock " - "offscreen surface\n"); - - /* Notify FB of the new memory pointer */ - winUpdateFBPointer (pScreen, - pScreenPriv->pddsdOffscreen->lpSurface); - - /* Unregister our hotkey */ - UnregisterHotKey (pScreenPriv->hwndScreen, 1); - - return TRUE; -} - - -/* Set engine specific functions */ -Bool -winSetEngineFunctionsPrimaryDD (ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; - - /* Set our pointers */ - pScreenPriv->pwinAllocateFB = winAllocateFBPrimaryDD; - pScreenPriv->pwinFreeFB = winFreeFBPrimaryDD; - pScreenPriv->pwinShadowUpdate = (winShadowUpdateProcPtr) (void (*)(void))NoopDDA; - pScreenPriv->pwinInitScreen = winInitScreenPrimaryDD; - pScreenPriv->pwinCloseScreen = winCloseScreenPrimaryDD; - pScreenPriv->pwinInitVisuals = winInitVisualsPrimaryDD; - pScreenPriv->pwinAdjustVideoMode = winAdjustVideoModePrimaryDD; - if (pScreenInfo->fFullScreen) - pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowFullScreen; - else - pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowWindowed; - pScreenPriv->pwinFinishScreenInit = winFinishScreenInitFB; - pScreenPriv->pwinBltExposedRegions = (winBltExposedRegionsProcPtr) (void (*)(void))NoopDDA; - pScreenPriv->pwinActivateApp = winActivateAppPrimaryDD; - pScreenPriv->pwinRedrawScreen = NULL; - pScreenPriv->pwinRealizeInstalledPalette = NULL; - pScreenPriv->pwinInstallColormap = NULL; - pScreenPriv->pwinStoreColors = NULL; - pScreenPriv->pwinCreateColormap = NULL; - pScreenPriv->pwinDestroyColormap = NULL; - pScreenPriv->pwinHotKeyAltTab = winHotKeyAltTabPrimaryDD; - pScreenPriv->pwinCreatePrimarySurface = (winCreatePrimarySurfaceProcPtr) (void (*)(void))NoopDDA; - pScreenPriv->pwinReleasePrimarySurface = (winReleasePrimarySurfaceProcPtr) (void (*)(void))NoopDDA; -#ifdef XWIN_MULTIWINDOW - pScreenPriv->pwinFinishCreateWindowsWindow = - (winFinishCreateWindowsWindowProcPtr) (void (*)(void))NoopDDA; -#endif - - return TRUE; -} +/*
+ *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 "win.h"
+
+
+/*
+ * Local function prototypes
+ */
+
+static Bool
+winAllocateFBPrimaryDD (ScreenPtr pScreen);
+
+static Bool
+winCloseScreenPrimaryDD (int nIndex, ScreenPtr pScreen);
+
+static Bool
+winInitVisualsPrimaryDD (ScreenPtr pScreen);
+
+static Bool
+winAdjustVideoModePrimaryDD (ScreenPtr pScreen);
+
+static Bool
+winActivateAppPrimaryDD (ScreenPtr pScreen);
+
+static Bool
+winHotKeyAltTabPrimaryDD (ScreenPtr pScreen);
+
+
+/*
+ * Create a DirectDraw primary surface
+ */
+
+static Bool
+winAllocateFBPrimaryDD (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ HRESULT ddrval = DD_OK;
+ DDSURFACEDESC ddsd;
+ DDSURFACEDESC *pddsdPrimary = NULL;
+ DDSURFACEDESC *pddsdOffscreen = NULL;
+ RECT rcClient;
+
+ winDebug ("winAllocateFBPrimaryDD\n");
+
+ /* Get client area location in screen coords */
+ GetClientRect (pScreenPriv->hwndScreen, &rcClient);
+ MapWindowPoints (pScreenPriv->hwndScreen,
+ HWND_DESKTOP,
+ (LPPOINT)&rcClient, 2);
+
+ /* Create a DirectDraw object, store the address at lpdd */
+ ddrval = (*g_fpDirectDrawCreate) (NULL, &pScreenPriv->pdd, NULL);
+ if (ddrval != DD_OK)
+ FatalError ("winAllocateFBPrimaryDD - Could not start DirectDraw\n");
+
+ /* Get a DirectDraw2 interface pointer */
+ ddrval = IDirectDraw_QueryInterface (pScreenPriv->pdd,
+ &IID_IDirectDraw2,
+ (LPVOID*) &pScreenPriv->pdd2);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winAllocateFBShadowDD - Failed DD2 query: %08x\n",
+ (unsigned int) ddrval);
+ return FALSE;
+ }
+
+
+ winDebug ("winAllocateFBPrimaryDD - Created and initialized DD\n");
+
+ /* Are we windowed or fullscreen? */
+ if (pScreenInfo->fFullScreen)
+ {
+ /* Full screen mode */
+ ddrval = IDirectDraw2_SetCooperativeLevel (pScreenPriv->pdd2,
+ pScreenPriv->hwndScreen,
+ DDSCL_FULLSCREEN
+ | DDSCL_EXCLUSIVE);
+ if (FAILED (ddrval))
+ FatalError ("winAllocateFBPrimaryDD - Could not set "
+ "cooperative level\n");
+
+ /* Change the video mode to the mode requested */
+ ddrval = IDirectDraw2_SetDisplayMode (pScreenPriv->pdd2,
+ pScreenInfo->dwWidth,
+ pScreenInfo->dwHeight,
+ pScreenInfo->dwBPP,
+ pScreenInfo->dwRefreshRate,
+ 0);
+ if (FAILED (ddrval))
+ FatalError ("winAllocateFBPrimaryDD - Could not set "
+ "full screen display mode\n");
+ }
+ else
+ {
+ /* Windowed mode */
+ ddrval = IDirectDraw2_SetCooperativeLevel (pScreenPriv->pdd2,
+ pScreenPriv->hwndScreen,
+ DDSCL_NORMAL);
+ if (FAILED (ddrval))
+ FatalError ("winAllocateFBPrimaryDD - Could not set "
+ "cooperative level\n");
+ }
+
+ /* Describe the primary surface */
+ ZeroMemory (&ddsd, sizeof (ddsd));
+ ddsd.dwSize = sizeof (ddsd);
+ ddsd.dwFlags = DDSD_CAPS;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+
+ /* Create the primary surface */
+ ddrval = IDirectDraw2_CreateSurface (pScreenPriv->pdd2,
+ &ddsd,
+ &pScreenPriv->pddsPrimary,
+ NULL);
+ if (FAILED (ddrval))
+ FatalError ("winAllocateFBPrimaryDD - Could not create primary "
+ "surface %08x\n", (unsigned int) ddrval);
+
+ winDebug ("winAllocateFBPrimaryDD - Created primary\n");
+
+ /* Allocate a DD surface description for our screen privates */
+ pddsdPrimary = pScreenPriv->pddsdPrimary
+ = malloc (sizeof (DDSURFACEDESC));
+ if (pddsdPrimary == NULL)
+ FatalError ("winAllocateFBPrimaryDD - Could not allocate surface "
+ "description memory\n");
+ ZeroMemory (pddsdPrimary, sizeof (*pddsdPrimary));
+ pddsdPrimary->dwSize = sizeof (*pddsdPrimary);
+
+ /* Describe the offscreen surface to be created */
+ /*
+ * NOTE: Do not use a DDSCAPS_VIDEOMEMORY surface,
+ * as drawing, locking, and unlocking take forever
+ * with video memory surfaces. In addition,
+ * video memory is a somewhat scarce resource,
+ * so you shouldn't be allocating video memory when
+ * you have the option of using system memory instead.
+ */
+ ZeroMemory (&ddsd, sizeof (ddsd));
+ ddsd.dwSize = sizeof (ddsd);
+ ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
+ ddsd.dwHeight = pScreenInfo->dwHeight;
+ ddsd.dwWidth = pScreenInfo->dwWidth;
+
+ /* Create the shadow surface */
+ ddrval = IDirectDraw2_CreateSurface (pScreenPriv->pdd2,
+ &ddsd,
+ &pScreenPriv->pddsOffscreen,
+ NULL);
+ if (ddrval != DD_OK)
+ FatalError ("winAllocateFBPrimaryDD - Could not create shadow "
+ "surface\n");
+
+ winDebug ("winAllocateFBPrimaryDD - Created offscreen\n");
+
+ /* Allocate a DD surface description for our screen privates */
+ pddsdOffscreen = pScreenPriv->pddsdOffscreen
+ = malloc (sizeof (DDSURFACEDESC));
+ if (pddsdOffscreen == NULL)
+ FatalError ("winAllocateFBPrimaryDD - Could not allocate surface "
+ "description memory\n");
+ ZeroMemory (pddsdOffscreen, sizeof (*pddsdOffscreen));
+ pddsdOffscreen->dwSize = sizeof (*pddsdOffscreen);
+
+ winDebug ("winAllocateFBPrimaryDD - Locking primary\n");
+
+ /* Lock the primary surface */
+ ddrval = IDirectDrawSurface2_Lock (pScreenPriv->pddsPrimary,
+ pScreenInfo->fFullScreen ? NULL:&rcClient,
+ pddsdPrimary,
+ DDLOCK_WAIT,
+ NULL);
+ if (ddrval != DD_OK || pddsdPrimary->lpSurface == NULL)
+ FatalError ("winAllocateFBPrimaryDD - Could not lock "
+ "primary surface\n");
+
+ winDebug ("winAllocateFBPrimaryDD - Locked primary\n");
+
+ /* We don't know how to deal with anything other than RGB */
+ if (!(pddsdPrimary->ddpfPixelFormat.dwFlags & DDPF_RGB))
+ FatalError ("winAllocateFBPrimaryDD - Color format other than RGB\n");
+
+ /* Grab the pitch from the surface desc */
+ pScreenInfo->dwStride = (pddsdPrimary->u1.lPitch * 8)
+ / pScreenInfo->dwBPP;
+
+ /* Save the pointer to our surface memory */
+ pScreenInfo->pfb = pddsdPrimary->lpSurface;
+
+ /* Grab the color depth and masks from the surface description */
+ pScreenPriv->dwRedMask = pddsdPrimary->ddpfPixelFormat.u2.dwRBitMask;
+ pScreenPriv->dwGreenMask = pddsdPrimary->ddpfPixelFormat.u3.dwGBitMask;
+ pScreenPriv->dwBlueMask = pddsdPrimary->ddpfPixelFormat.u4.dwBBitMask;
+
+ winDebug ("winAllocateFBPrimaryDD - Returning\n");
+
+ return TRUE;
+}
+
+static void
+winFreeFBPrimaryDD (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+
+ /* Free the offscreen surface, if there is one */
+ if (pScreenPriv->pddsOffscreen)
+ {
+ IDirectDrawSurface2_Unlock (pScreenPriv->pddsOffscreen, NULL);
+ IDirectDrawSurface2_Release (pScreenPriv->pddsOffscreen);
+ pScreenPriv->pddsOffscreen = NULL;
+ }
+
+ /* Release the primary surface, if there is one */
+ if (pScreenPriv->pddsPrimary)
+ {
+ IDirectDrawSurface2_Unlock (pScreenPriv->pddsPrimary, NULL);
+ IDirectDrawSurface2_Release (pScreenPriv->pddsPrimary);
+ pScreenPriv->pddsPrimary = NULL;
+ }
+
+ /* Free the DirectDraw object, if there is one */
+ if (pScreenPriv->pdd)
+ {
+ IDirectDraw2_RestoreDisplayMode (pScreenPriv->pdd);
+ IDirectDraw2_Release (pScreenPriv->pdd);
+ pScreenPriv->pdd = NULL;
+ }
+
+ /* Invalidate the ScreenInfo's fb pointer */
+ pScreenInfo->pfb = NULL;
+}
+
+static Bool
+winInitScreenPrimaryDD(ScreenPtr pScreen)
+{
+ return winAllocateFBPrimaryDD(pScreen);
+}
+
+/*
+ * Call the wrapped CloseScreen function.
+ *
+ * Free our resources and private structures.
+ */
+
+static Bool
+winCloseScreenPrimaryDD (int nIndex, ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ Bool fReturn;
+
+ ErrorF ("winCloseScreenPrimaryDD - Freeing screen resources\n");
+
+ /* Flag that the screen is closed */
+ pScreenPriv->fClosed = TRUE;
+ pScreenPriv->fActive = FALSE;
+
+ /* Call the wrapped CloseScreen procedure */
+ WIN_UNWRAP(CloseScreen);
+ if (pScreen->CloseScreen)
+ fReturn = (*pScreen->CloseScreen) (nIndex, pScreen);
+
+ /* Delete the window property */
+ RemoveProp (pScreenPriv->hwndScreen, WIN_SCR_PROP);
+
+ winFreeFBPrimaryDD(pScreen);
+
+ /* Delete tray icon, if we have one */
+ if (!pScreenInfo->fNoTrayIcon)
+ winDeleteNotifyIcon (pScreenPriv);
+
+ /* Free the exit confirmation dialog box, if it exists */
+ if (g_hDlgExit != NULL)
+ {
+ DestroyWindow (g_hDlgExit);
+ g_hDlgExit = NULL;
+ }
+
+ /* Kill our window */
+ if (pScreenPriv->hwndScreen)
+ {
+ DestroyWindow (pScreenPriv->hwndScreen);
+ pScreenPriv->hwndScreen = NULL;
+ }
+
+ /* Kill our screeninfo's pointer to the screen */
+ pScreenInfo->pScreen = NULL;
+
+ /* Free the screen privates for this screen */
+ free ((pointer) pScreenPriv);
+
+ return fReturn;
+}
+
+
+/*
+ * Tell mi what sort of visuals we need.
+ *
+ * Generally we only need one visual, as our screen can only
+ * handle one format at a time, I believe. You may want
+ * to verify that last sentence.
+ */
+
+static Bool
+winInitVisualsPrimaryDD (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ DWORD dwRedBits, dwGreenBits, dwBlueBits;
+
+ /* Count the number of ones in each color mask */
+ dwRedBits = winCountBits (pScreenPriv->dwRedMask);
+ dwGreenBits = winCountBits (pScreenPriv->dwGreenMask);
+ dwBlueBits = winCountBits (pScreenPriv->dwBlueMask);
+
+ /* Store the maximum number of ones in a color mask as the bitsPerRGB */
+ if (dwRedBits > dwGreenBits && dwRedBits > dwBlueBits)
+ pScreenPriv->dwBitsPerRGB = dwRedBits;
+ else if (dwGreenBits > dwRedBits && dwGreenBits > dwBlueBits)
+ pScreenPriv->dwBitsPerRGB = dwGreenBits;
+ else
+ pScreenPriv->dwBitsPerRGB = dwBlueBits;
+
+ winDebug ("winInitVisualsPrimaryDD - Masks: %08x %08x %08x bpRGB: %d\n",
+ (unsigned int) pScreenPriv->dwRedMask,
+ (unsigned int) pScreenPriv->dwGreenMask,
+ (unsigned int) pScreenPriv->dwBlueMask,
+ (int) pScreenPriv->dwBitsPerRGB);
+
+ /* Create a single visual according to the Windows screen depth */
+ switch (pScreenInfo->dwDepth)
+ {
+ case 24:
+ case 16:
+ case 15:
+ if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth,
+ TrueColorMask,
+ pScreenPriv->dwBitsPerRGB,
+ TrueColor,
+ pScreenPriv->dwRedMask,
+ pScreenPriv->dwGreenMask,
+ pScreenPriv->dwBlueMask))
+ {
+ ErrorF ("winInitVisualsPrimaryDD - "
+ "miSetVisualTypesAndMasks failed\n");
+ return FALSE;
+ }
+ break;
+
+ case 8:
+ winDebug ("winInitVisuals - Calling miSetVisualTypesAndMasks\n");
+ if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth,
+ PseudoColorMask,
+ pScreenPriv->dwBitsPerRGB,
+ PseudoColor,
+ pScreenPriv->dwRedMask,
+ pScreenPriv->dwGreenMask,
+ pScreenPriv->dwBlueMask))
+ {
+ ErrorF ("winInitVisualsPrimaryDD - "
+ "miSetVisualTypesAndMasks failed\n");
+ return FALSE;
+ }
+ winDebug ("winInitVisualsPrimaryDD - Returned from "
+ "miSetVisualTypesAndMasks\n");
+ break;
+
+ default:
+ ErrorF ("winInitVisualsPrimaryDD - Unknown screen depth\n");
+ return FALSE;
+ }
+
+ winDebug ("winInitVisualsPrimaryDD - Returning\n");
+
+ return TRUE;
+}
+
+
+static Bool
+winAdjustVideoModePrimaryDD (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ HDC hdc = NULL;
+ DWORD dwBPP;
+
+ /* We're in serious trouble if we can't get a DC */
+ hdc = GetDC (NULL);
+ if (hdc == NULL)
+ {
+ ErrorF ("winAdjustVideoModePrimaryDD - GetDC failed\n");
+ return FALSE;
+ }
+
+ /* Query GDI for current display depth */
+ dwBPP = GetDeviceCaps (hdc, BITSPIXEL);
+
+ /* DirectDraw can only change the depth in fullscreen mode */
+ if (!(pScreenInfo->fFullScreen &&
+ (pScreenInfo->dwBPP != WIN_DEFAULT_BPP)))
+ {
+ /* Otherwise, We'll use GDI's depth */
+ pScreenInfo->dwBPP = dwBPP;
+ }
+
+ /* Release our DC */
+ ReleaseDC (NULL, hdc);
+
+ return TRUE;
+}
+
+
+/*
+ * We need to blit our offscreen fb to
+ * the screen when we are activated, and we need to point
+ * the fb code back to the primary surface memory.
+ */
+
+static Bool
+winActivateAppPrimaryDD (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ RECT rcSrc, rcClient;
+ HRESULT ddrval = DD_OK;
+
+ /* Check for errors */
+ if (pScreenPriv == NULL
+ || pScreenPriv->pddsPrimary == NULL
+ || pScreenPriv->pddsOffscreen == NULL)
+ return FALSE;
+
+ /* Check for do-nothing */
+ if (!pScreenPriv->fActive)
+ return TRUE;
+
+ /* We are activating */
+ ddrval = IDirectDrawSurface2_IsLost (pScreenPriv->pddsOffscreen);
+ if (ddrval == DD_OK)
+ {
+ IDirectDrawSurface2_Unlock (pScreenPriv->pddsOffscreen,
+ NULL);
+ /*
+ * We don't check for an error from Unlock, because it
+ * doesn't matter if the Unlock failed.
+ */
+ }
+
+ /* Restore both surfaces, just cause I like it that way */
+ IDirectDrawSurface2_Restore (pScreenPriv->pddsOffscreen);
+ IDirectDrawSurface2_Restore (pScreenPriv->pddsPrimary);
+
+ /* Get client area in screen coords */
+ GetClientRect (pScreenPriv->hwndScreen, &rcClient);
+ MapWindowPoints (pScreenPriv->hwndScreen,
+ HWND_DESKTOP,
+ (LPPOINT)&rcClient, 2);
+
+ /* Setup a source rectangle */
+ rcSrc.left = 0;
+ rcSrc.top = 0;
+ rcSrc.right = pScreenInfo->dwWidth;
+ rcSrc.bottom = pScreenInfo->dwHeight;
+
+ ddrval = IDirectDrawSurface2_Blt (pScreenPriv->pddsPrimary,
+ &rcClient,
+ pScreenPriv->pddsOffscreen,
+ &rcSrc,
+ DDBLT_WAIT,
+ NULL);
+ if (ddrval != DD_OK)
+ FatalError ("winActivateAppPrimaryDD () - Failed blitting offscreen "
+ "surface to primary surface %08x\n", (unsigned int) ddrval);
+
+ /* Lock the primary surface */
+ ddrval = IDirectDrawSurface2_Lock (pScreenPriv->pddsPrimary,
+ &rcClient,
+ pScreenPriv->pddsdPrimary,
+ DDLOCK_WAIT,
+ NULL);
+ if (ddrval != DD_OK
+ || pScreenPriv->pddsdPrimary->lpSurface == NULL)
+ FatalError ("winActivateAppPrimaryDD () - Could not lock "
+ "primary surface\n");
+
+ /* Notify FB of the new memory pointer */
+ winUpdateFBPointer (pScreen,
+ pScreenPriv->pddsdPrimary->lpSurface);
+
+ /*
+ * Register the Alt-Tab combo as a hotkey so we can copy
+ * the primary framebuffer before the display mode changes
+ */
+ RegisterHotKey (pScreenPriv->hwndScreen, 1, MOD_ALT, 9);
+
+ return TRUE;
+}
+
+
+/*
+ * Handle the Alt+Tab hotkey.
+ *
+ * We need to save the primary fb to an offscreen fb when
+ * we get deactivated, and point the fb code at the offscreen
+ * fb for the duration of the deactivation.
+ */
+
+static Bool
+winHotKeyAltTabPrimaryDD (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ RECT rcClient, rcSrc;
+ HRESULT ddrval = DD_OK;
+
+ winDebug ("\nwinHotKeyAltTabPrimaryDD\n\n");
+
+ /* Alt+Tab was pressed, we will lose focus very soon */
+ pScreenPriv->fActive = FALSE;
+
+ /* Check for error conditions */
+ if (pScreenPriv->pddsPrimary == NULL
+ || pScreenPriv->pddsOffscreen == NULL)
+ return FALSE;
+
+ /* Get client area in screen coords */
+ GetClientRect (pScreenPriv->hwndScreen, &rcClient);
+ MapWindowPoints (pScreenPriv->hwndScreen,
+ HWND_DESKTOP,
+ (LPPOINT)&rcClient, 2);
+
+ /* Did we loose the primary surface? */
+ ddrval = IDirectDrawSurface2_IsLost (pScreenPriv->pddsPrimary);
+ if (ddrval == DD_OK)
+ {
+ ddrval = IDirectDrawSurface2_Unlock (pScreenPriv->pddsPrimary,
+ NULL);
+ if (FAILED (ddrval))
+ FatalError ("winHotKeyAltTabPrimaryDD - Failed unlocking primary "
+ "surface\n");
+ }
+
+ /* Setup a source rectangle */
+ rcSrc.left = 0;
+ rcSrc.top = 0;
+ rcSrc.right = pScreenInfo->dwWidth;
+ rcSrc.bottom = pScreenInfo->dwHeight;
+
+ /* Blit the primary surface to the offscreen surface */
+ ddrval = IDirectDrawSurface2_Blt (pScreenPriv->pddsOffscreen,
+ NULL, /* should be rcDest */
+ pScreenPriv->pddsPrimary,
+ NULL,
+ DDBLT_WAIT,
+ NULL);
+ if (ddrval == DDERR_SURFACELOST)
+ {
+ IDirectDrawSurface2_Restore (pScreenPriv->pddsOffscreen);
+ IDirectDrawSurface2_Restore (pScreenPriv->pddsPrimary);
+
+ /* Blit the primary surface to the offscreen surface */
+ ddrval = IDirectDrawSurface2_Blt (pScreenPriv->pddsOffscreen,
+ NULL,
+ pScreenPriv->pddsPrimary,
+ NULL,
+ DDBLT_WAIT,
+ NULL);
+ if (FAILED (ddrval))
+ FatalError ("winHotKeyAltTabPrimaryDD - Failed blitting primary "
+ "surface to offscreen surface: %08x\n",
+ (unsigned int) ddrval);
+ }
+ else
+ {
+ FatalError ("winHotKeyAltTabPrimaryDD - Unknown error from "
+ "Blt: %08dx\n", (unsigned int) ddrval);
+ }
+
+ /* Lock the offscreen surface */
+ ddrval = IDirectDrawSurface2_Lock (pScreenPriv->pddsOffscreen,
+ NULL,
+ pScreenPriv->pddsdOffscreen,
+ DDLOCK_WAIT,
+ NULL);
+ if (ddrval != DD_OK
+ || pScreenPriv->pddsdPrimary->lpSurface == NULL)
+ FatalError ("winHotKeyAltTabPrimaryDD - Could not lock "
+ "offscreen surface\n");
+
+ /* Notify FB of the new memory pointer */
+ winUpdateFBPointer (pScreen,
+ pScreenPriv->pddsdOffscreen->lpSurface);
+
+ /* Unregister our hotkey */
+ UnregisterHotKey (pScreenPriv->hwndScreen, 1);
+
+ return TRUE;
+}
+
+
+/* Set engine specific functions */
+Bool
+winSetEngineFunctionsPrimaryDD (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+
+ /* Set our pointers */
+ pScreenPriv->pwinAllocateFB = winAllocateFBPrimaryDD;
+ pScreenPriv->pwinFreeFB = winFreeFBPrimaryDD;
+ pScreenPriv->pwinShadowUpdate = (winShadowUpdateProcPtr) (void (*)(void))NoopDDA;
+ pScreenPriv->pwinInitScreen = winInitScreenPrimaryDD;
+ pScreenPriv->pwinCloseScreen = winCloseScreenPrimaryDD;
+ pScreenPriv->pwinInitVisuals = winInitVisualsPrimaryDD;
+ pScreenPriv->pwinAdjustVideoMode = winAdjustVideoModePrimaryDD;
+ if (pScreenInfo->fFullScreen)
+ pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowFullScreen;
+ else
+ pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowWindowed;
+ pScreenPriv->pwinFinishScreenInit = winFinishScreenInitFB;
+ pScreenPriv->pwinBltExposedRegions = (winBltExposedRegionsProcPtr) (void (*)(void))NoopDDA;
+ pScreenPriv->pwinActivateApp = winActivateAppPrimaryDD;
+ pScreenPriv->pwinRedrawScreen = NULL;
+ pScreenPriv->pwinRealizeInstalledPalette = NULL;
+ pScreenPriv->pwinInstallColormap = NULL;
+ pScreenPriv->pwinStoreColors = NULL;
+ pScreenPriv->pwinCreateColormap = NULL;
+ pScreenPriv->pwinDestroyColormap = NULL;
+ pScreenPriv->pwinHotKeyAltTab = winHotKeyAltTabPrimaryDD;
+ pScreenPriv->pwinCreatePrimarySurface = (winCreatePrimarySurfaceProcPtr) (void (*)(void))NoopDDA;
+ pScreenPriv->pwinReleasePrimarySurface = (winReleasePrimarySurfaceProcPtr) (void (*)(void))NoopDDA;
+#ifdef XWIN_MULTIWINDOW
+ pScreenPriv->pwinFinishCreateWindowsWindow =
+ (winFinishCreateWindowsWindowProcPtr) (void (*)(void))NoopDDA;
+#endif
+
+ return TRUE;
+}
diff --git a/xorg-server/hw/xwin/winscrinit.c b/xorg-server/hw/xwin/winscrinit.c index c67eb6de8..baa2b7f3a 100644 --- a/xorg-server/hw/xwin/winscrinit.c +++ b/xorg-server/hw/xwin/winscrinit.c @@ -1,756 +1,760 @@ -/* - *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 - * Kensuke Matsuzaki - */ - -#ifdef HAVE_XWIN_CONFIG_H -#include <xwin-config.h> -#endif -#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 - */ - -/* - * Local functions - */ - -static Bool -winSaveScreen (ScreenPtr pScreen, int on); - - -/* - * Determine what type of screen we are initializing - * and call the appropriate procedure to intiailize - * that type of screen. - */ - -Bool -winScreenInit (int index, - ScreenPtr pScreen, - int argc, char **argv) -{ - winScreenInfoPtr pScreenInfo = &g_ScreenInfo[index]; - winPrivScreenPtr pScreenPriv; - HDC hdc; - DWORD dwInitialBPP; - - winDebug ("winScreenInit - dwWidth: %ld dwHeight: %ld\n", - pScreenInfo->dwWidth, pScreenInfo->dwHeight); - - /* Allocate privates for this screen */ - if (!winAllocatePrivates (pScreen)) - { - ErrorF ("winScreenInit - Couldn't allocate screen privates\n"); - return FALSE; - } - - /* Get a pointer to the privates structure that was allocated */ - pScreenPriv = winGetScreenPriv (pScreen); - - /* Save a pointer to this screen in the screen info structure */ - pScreenInfo->pScreen = pScreen; - - /* Save a pointer to the screen info in the screen privates structure */ - /* This allows us to get back to the screen info from a screen pointer */ - pScreenPriv->pScreenInfo = pScreenInfo; - - /* - * Determine which engine to use. - * - * NOTE: This is done once per screen because each screen possibly has - * a preferred engine specified on the command line. - */ - if (!winSetEngine (pScreen)) - { - ErrorF ("winScreenInit - winSetEngine () failed\n"); - return FALSE; - } - - /* Horribly misnamed function: Allow engine to adjust BPP for screen */ - dwInitialBPP = pScreenInfo->dwBPP; - - if (pScreenPriv->pwinAdjustVideoMode && !(*pScreenPriv->pwinAdjustVideoMode) (pScreen)) - { - ErrorF ("winScreenInit - winAdjustVideoMode () failed\n"); - return FALSE; - } - - if (dwInitialBPP == WIN_DEFAULT_BPP) - { - /* No -depth parameter was passed, let the user know the depth being used */ - winDebug ("winScreenInit - Using Windows display depth of %d bits per pixel\n", (int) pScreenInfo->dwBPP); - } - else if (dwInitialBPP != pScreenInfo->dwBPP) - { - /* Warn user if engine forced a depth different to -depth parameter */ - winDebug ("winScreenInit - Command line depth of %d bpp overidden by engine, using %d bpp\n", (int) dwInitialBPP, (int) pScreenInfo->dwBPP); - } - else - { - winDebug ("winScreenInit - Using command line depth of %d bpp\n", (int) pScreenInfo->dwBPP); - } - - /* Check for supported display depth */ - if (!(WIN_SUPPORTED_BPPS & (1 << (pScreenInfo->dwBPP - 1)))) - { - ErrorF ("winScreenInit - Unsupported display depth: %d\n" \ - "Change your Windows display depth to 15, 16, 24, or 32 bits " - "per pixel.\n", - (int) pScreenInfo->dwBPP); - ErrorF ("winScreenInit - Supported depths: %08x\n", - WIN_SUPPORTED_BPPS); -#if WIN_CHECK_DEPTH - return FALSE; -#endif - } - - /* - * Check that all monitors have the same display depth if we are using - * multiple monitors - */ - if (pScreenInfo->fMultipleMonitors - && !GetSystemMetrics (SM_SAMEDISPLAYFORMAT)) - { - ErrorF ("winScreenInit - Monitors do not all have same pixel format / " - "display depth.\n"); - if (pScreenInfo->dwEngine == WIN_SERVER_SHADOW_GDI) - { - ErrorF ("winScreenInit - Performance may suffer off primary display.\n"); - } - else - { - ErrorF ("winScreenInit - Using primary display only.\n"); - pScreenInfo->fMultipleMonitors = FALSE; - } - } - - /* Create display window */ - if (pScreenPriv->pwinCreateBoundingWindow && !(*pScreenPriv->pwinCreateBoundingWindow) (pScreen)) - { - ErrorF ("winScreenInit - pwinCreateBoundingWindow () " - "failed\n"); - return FALSE; - } - - /* Get a device context */ - hdc = GetDC (pScreenPriv->hwndScreen); - - /* Are we using multiple monitors? */ - if (pScreenInfo->fMultipleMonitors) - { - /* - * In this case, some of the defaults set in - * winInitializeScreenDefaults() are not correct ... - */ - if (!pScreenInfo->fUserGaveHeightAndWidth) - { - pScreenInfo->dwWidth = GetSystemMetrics (SM_CXVIRTUALSCREEN); - pScreenInfo->dwHeight = GetSystemMetrics (SM_CYVIRTUALSCREEN); - } - } - - /* Release the device context */ - ReleaseDC (pScreenPriv->hwndScreen, hdc); - - /* Clear the visuals list */ - miClearVisualTypes (); - - /* Call the engine dependent screen initialization procedure */ - if (pScreenPriv->pwinFinishScreenInit && !((*pScreenPriv->pwinFinishScreenInit) (index, pScreen, argc, argv))) - { - ErrorF ("winScreenInit - winFinishScreenInit () failed\n"); - return FALSE; - } - - if (!g_fSoftwareCursor) - winInitCursor(pScreen); -#ifdef WINDBG - else - winDebug("winScreenInit - Using software cursor\n"); -#endif - - /* - Note the screen origin in a normalized coordinate space where (0,0) is at the top left - of the native virtual desktop area - */ - pScreen->x = pScreenInfo->dwInitialX - GetSystemMetrics(SM_XVIRTUALSCREEN); - pScreen->y = pScreenInfo->dwInitialY - GetSystemMetrics(SM_YVIRTUALSCREEN); - - winDebug("Screen %d added at virtual desktop coordinate (%d,%d).\n", - index, pScreen->x, pScreen->y); - winDebug ("winScreenInit - returning\n"); - - return TRUE; -} - -static Bool -winCreateScreenResources(ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - Bool result; - - result = pScreenPriv->pwinCreateScreenResources(pScreen); - - /* Now the screen bitmap has been wrapped in a pixmap, - add that to the Shadow framebuffer */ - if (!shadowAdd(pScreen, pScreen->devPrivate, - pScreenPriv->pwinShadowUpdate, NULL, 0, 0)) - { - ErrorF ("winCreateScreenResources - shadowAdd () failed\n"); - return FALSE; - } - - return result; -} - -/* See Porting Layer Definition - p. 20 */ -Bool -winFinishScreenInitFB (int index, - ScreenPtr pScreen, - int argc, char **argv) -{ - winScreenPriv(pScreen); - winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; - VisualPtr pVisual = NULL; - char *pbits = NULL; -#if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW) - int iReturn; -#endif - - /* Create framebuffer */ - if (!(*pScreenPriv->pwinInitScreen) (pScreen)) - { - ErrorF ("winFinishScreenInitFB - Could not allocate framebuffer\n"); - return FALSE; - } - - /* - * Calculate the number of bits that are used to represent color in each pixel, - * the color depth for the screen - */ - if (pScreenInfo->dwBPP == 8) - pScreenInfo->dwDepth = 8; - else - pScreenInfo->dwDepth = winCountBits (pScreenPriv->dwRedMask) - + winCountBits (pScreenPriv->dwGreenMask) - + winCountBits (pScreenPriv->dwBlueMask); - - winDebug ("winFinishScreenInitFB - Masks: %08x %08x %08x\n", - (unsigned int) pScreenPriv->dwRedMask, - (unsigned int) pScreenPriv->dwGreenMask, - (unsigned int) pScreenPriv->dwBlueMask); - - /* Init visuals */ - if (!(*pScreenPriv->pwinInitVisuals) (pScreen)) - { - ErrorF ("winFinishScreenInitFB - winInitVisuals failed\n"); - return FALSE; - } - - /* Setup a local variable to point to the framebuffer */ - pbits = pScreenInfo->pfb; - - /* Apparently we need this for the render extension */ - miSetPixmapDepths (); - - /* Start fb initialization */ - if (!fbSetupScreen (pScreen, - pScreenInfo->pfb, - pScreenInfo->dwWidth, pScreenInfo->dwHeight, - monitorResolution, monitorResolution, - pScreenInfo->dwStride, - pScreenInfo->dwBPP)) - { - ErrorF ("winFinishScreenInitFB - fbSetupScreen failed\n"); - return FALSE; - } - - /* Override default colormap routines if visual class is dynamic */ - if (pScreenInfo->dwDepth == 8 - && (pScreenInfo->dwEngine == WIN_SERVER_SHADOW_GDI - || (pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DDNL - && pScreenInfo->fFullScreen) - || (pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DD - && pScreenInfo->fFullScreen))) - { - winSetColormapFunctions (pScreen); - - /* - * NOTE: Setting whitePixel to 255 causes Magic 7.1 to allocate its - * own colormap, as it cannot allocate 7 planes in the default - * colormap. Setting whitePixel to 1 allows Magic to get 7 - * planes in the default colormap, so it doesn't create its - * own colormap. This latter situation is highly desireable, - * as it keeps the Magic window viewable when switching to - * other X clients that use the default colormap. - */ - pScreen->blackPixel = 0; - pScreen->whitePixel = 1; - } - - /* Place our save screen function */ - pScreen->SaveScreen = winSaveScreen; - - /* Finish fb initialization */ - if (!fbFinishScreenInit (pScreen, - pScreenInfo->pfb, - pScreenInfo->dwWidth, pScreenInfo->dwHeight, - monitorResolution, monitorResolution, - pScreenInfo->dwStride, - pScreenInfo->dwBPP)) - { - ErrorF ("winFinishScreenInitFB - fbFinishScreenInit failed\n"); - return FALSE; - } - - /* Save a pointer to the root visual */ - for (pVisual = pScreen->visuals; - pVisual->vid != pScreen->rootVisual; - pVisual++); - pScreenPriv->pRootVisual = pVisual; - - /* - * Setup points to the block and wakeup handlers. Pass a pointer - * to the current screen as pWakeupdata. - */ - pScreen->BlockHandler = winBlockHandler; - pScreen->WakeupHandler = winWakeupHandler; - pScreen->blockData = pScreen; - pScreen->wakeupData = pScreen; - - /* Render extension initialization, calls miPictureInit */ - if (!fbPictureInit (pScreen, NULL, 0)) - { - ErrorF ("winFinishScreenInitFB - fbPictureInit () failed\n"); - return FALSE; - } - -#ifdef RANDR - /* Initialize resize and rotate support */ - if (!winRandRInit (pScreen)) - { - ErrorF ("winFinishScreenInitFB - winRandRInit () failed\n"); - return FALSE; - } -#endif - - /* Setup the cursor routines */ - winDebug ("winFinishScreenInitFB - Calling miDCInitialize ()\n"); - miDCInitialize (pScreen, &g_winPointerCursorFuncs); - - /* KDrive does winCreateDefColormap right after miDCInitialize */ - /* Create a default colormap */ - winDebug ("winFinishScreenInitFB - Calling winCreateDefColormap ()\n"); - if (!winCreateDefColormap (pScreen)) - { - ErrorF ("winFinishScreenInitFB - Could not create colormap\n"); - return FALSE; - } - - /* Initialize the shadow framebuffer layer */ - if ((pScreenInfo->dwEngine == WIN_SERVER_SHADOW_GDI - || pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DD - || pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DDNL) -#ifdef XWIN_MULTIWINDOWEXTWM - && !pScreenInfo->fMWExtWM -#endif - ) - { - winDebug ("winFinishScreenInitFB - Calling shadowSetup ()\n"); - if (!shadowSetup(pScreen)) - { - ErrorF ("winFinishScreenInitFB - shadowSetup () failed\n"); - return FALSE; - } - - /* Wrap CreateScreenResources so we can add the screen pixmap - to the Shadow framebuffer after it's been created */ - pScreenPriv->pwinCreateScreenResources = pScreen->CreateScreenResources; - 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 */ -#define WRAP(a) \ - if (pScreen->a) { \ - pScreenPriv->a = pScreen->a; \ - } else { \ - ErrorF("null screen fn " #a "\n"); \ - pScreenPriv->a = NULL; \ - } - - /* Save a pointer to each lower-level window procedure */ - WRAP(CreateWindow); - WRAP(DestroyWindow); - WRAP(RealizeWindow); - WRAP(UnrealizeWindow); - WRAP(PositionWindow); - WRAP(ChangeWindowAttributes); - WRAP(SetShape); - - /* Assign rootless window procedures to be top level procedures */ - pScreen->CreateWindow = winCreateWindowRootless; - pScreen->DestroyWindow = winDestroyWindowRootless; - pScreen->PositionWindow = winPositionWindowRootless; - /*pScreen->ChangeWindowAttributes = winChangeWindowAttributesRootless;*/ - pScreen->RealizeWindow = winMapWindowRootless; - pScreen->UnrealizeWindow = winUnmapWindowRootless; - pScreen->SetShape = winSetShapeRootless; - - /* Undefine the WRAP macro, as it is not needed elsewhere */ -#undef WRAP - } - - -#ifdef XWIN_MULTIWINDOW - /* Handle multi window mode */ - else if (pScreenInfo->fMultiWindow) - { - /* Define the WRAP macro temporarily for local use */ -#define WRAP(a) \ - if (pScreen->a) { \ - pScreenPriv->a = pScreen->a; \ - } else { \ - ErrorF("null screen fn " #a "\n"); \ - pScreenPriv->a = NULL; \ - } - - /* Save a pointer to each lower-level window procedure */ - WRAP(CreateWindow); - WRAP(DestroyWindow); - WRAP(RealizeWindow); - WRAP(UnrealizeWindow); - WRAP(PositionWindow); - WRAP(ChangeWindowAttributes); - WRAP(ReparentWindow); - WRAP(RestackWindow); - WRAP(ResizeWindow); - WRAP(MoveWindow); - WRAP(CopyWindow); - WRAP(SetShape); - - /* Assign multi-window window procedures to be top level procedures */ - pScreen->CreateWindow = winCreateWindowMultiWindow; - pScreen->DestroyWindow = winDestroyWindowMultiWindow; - pScreen->PositionWindow = winPositionWindowMultiWindow; - /*pScreen->ChangeWindowAttributes = winChangeWindowAttributesMultiWindow;*/ - pScreen->RealizeWindow = winMapWindowMultiWindow; - pScreen->UnrealizeWindow = winUnmapWindowMultiWindow; - pScreen->ReparentWindow = winReparentWindowMultiWindow; - pScreen->RestackWindow = winRestackWindowMultiWindow; - pScreen->ResizeWindow = winResizeWindowMultiWindow; - pScreen->MoveWindow = winMoveWindowMultiWindow; - pScreen->CopyWindow = winCopyWindowMultiWindow; - pScreen->SetShape = winSetShapeMultiWindow; - - /* Undefine the WRAP macro, as it is not needed elsewhere */ -#undef WRAP - } -#endif - - /* Wrap either fb's or shadow's CloseScreen with our CloseScreen */ - pScreenPriv->CloseScreen = pScreen->CloseScreen; - pScreen->CloseScreen = pScreenPriv->pwinCloseScreen; - -#if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW) - /* Create a mutex for modules in separate threads to wait for */ - iReturn = pthread_mutex_init (&pScreenPriv->pmServerStarted, NULL); - if (iReturn != 0) - { - ErrorF ("winFinishScreenInitFB - pthread_mutex_init () failed: %d\n", - iReturn); - return FALSE; - } - - /* Own the mutex for modules in separate threads */ - iReturn = pthread_mutex_lock (&pScreenPriv->pmServerStarted); - if (iReturn != 0) - { - ErrorF ("winFinishScreenInitFB - pthread_mutex_lock () failed: %d\n", - iReturn); - return FALSE; - } - - /* Set the ServerStarted flag to false */ - pScreenPriv->fServerStarted = FALSE; -#endif - -#ifdef XWIN_MULTIWINDOWEXTWM - pScreenPriv->fRestacking = FALSE; -#endif - -#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM) - if (FALSE -#ifdef XWIN_MULTIWINDOW - || pScreenInfo->fMultiWindow -#endif -#ifdef XWIN_MULTIWINDOWINTWM - || pScreenInfo->fInternalWM -#endif - ) - { - winDebug ("winFinishScreenInitFB - Calling winInitWM.\n"); - - /* Initialize multi window mode */ - if (!winInitWM (&pScreenPriv->pWMInfo, - &pScreenPriv->ptWMProc, - &pScreenPriv->ptXMsgProc, - &pScreenPriv->pmServerStarted, - pScreenInfo->dwScreen, - (HWND)&pScreenPriv->hwndScreen, -#ifdef XWIN_MULTIWINDOWINTWM - pScreenInfo->fInternalWM || -#endif - FALSE)) - { - ErrorF ("winFinishScreenInitFB - winInitWM () failed.\n"); - return FALSE; - } - } -#endif - - /* Tell the server that we are enabled */ - pScreenPriv->fEnabled = TRUE; - - /* Tell the server that we have a valid depth */ - pScreenPriv->fBadDepth = FALSE; - - winDebug ("winFinishScreenInitFB - returning\n"); - - return TRUE; -} - -#ifdef XWIN_NATIVEGDI -/* See Porting Layer Definition - p. 20 */ - -Bool -winFinishScreenInitNativeGDI (int index, - ScreenPtr pScreen, - int argc, char **argv) -{ - winScreenPriv(pScreen); - winScreenInfoPtr pScreenInfo = &g_ScreenInfo[index]; - VisualPtr pVisuals = NULL; - DepthPtr pDepths = NULL; - VisualID rootVisual = 0; - int nVisuals = 0, nDepths = 0, nRootDepth = 0; - - /* Ignore user input (mouse, keyboard) */ - pScreenInfo->fIgnoreInput = FALSE; - - /* Get device contexts for the screen and shadow bitmap */ - pScreenPriv->hdcScreen = GetDC (pScreenPriv->hwndScreen); - if (pScreenPriv->hdcScreen == NULL) - FatalError ("winFinishScreenInitNativeGDI - Couldn't get a DC\n"); - - /* Init visuals */ - if (!(*pScreenPriv->pwinInitVisuals) (pScreen)) - { - ErrorF ("winFinishScreenInitNativeGDI - pwinInitVisuals failed\n"); - return FALSE; - } - - /* Initialize the mi visuals */ - if (!miInitVisuals (&pVisuals, &pDepths, &nVisuals, &nDepths, &nRootDepth, - &rootVisual, - ((unsigned long)1 << (pScreenInfo->dwDepth - 1)), 8, - TrueColor)) - { - ErrorF ("winFinishScreenInitNativeGDI - miInitVisuals () failed\n"); - return FALSE; - } - - /* Initialize the CloseScreen procedure pointer */ - pScreen->CloseScreen = NULL; - - /* Initialize the mi code */ - if (!miScreenInit (pScreen, - NULL, /* No framebuffer */ - pScreenInfo->dwWidth, pScreenInfo->dwHeight, - monitorResolution, monitorResolution, - pScreenInfo->dwStride, - nRootDepth, nDepths, pDepths, rootVisual, - nVisuals, pVisuals)) - { - ErrorF ("winFinishScreenInitNativeGDI - miScreenInit failed\n"); - return FALSE; - } - - pScreen->defColormap = FakeClientID(0); - - /* - * Register our block and wakeup handlers; these procedures - * process messages in our Windows message queue; specifically, - * they process mouse and keyboard input. - */ - pScreen->BlockHandler = winBlockHandler; - pScreen->WakeupHandler = winWakeupHandler; - pScreen->blockData = pScreen; - pScreen->wakeupData = pScreen; - - /* Place our save screen function */ - pScreen->SaveScreen = winSaveScreen; - - /* Pixmaps */ - pScreen->CreatePixmap = winCreatePixmapNativeGDI; - pScreen->DestroyPixmap = winDestroyPixmapNativeGDI; - - /* Other Screen Routines */ - pScreen->QueryBestSize = winQueryBestSizeNativeGDI; - pScreen->SaveScreen = winSaveScreen; - pScreen->GetImage = miGetImage; - pScreen->GetSpans = winGetSpansNativeGDI; - - /* Window Procedures */ - pScreen->CreateWindow = winCreateWindowNativeGDI; - pScreen->DestroyWindow = winDestroyWindowNativeGDI; - pScreen->PositionWindow = winPositionWindowNativeGDI; - /*pScreen->ChangeWindowAttributes = winChangeWindowAttributesNativeGDI;*/ - pScreen->RealizeWindow = winMapWindowNativeGDI; - pScreen->UnrealizeWindow = winUnmapWindowNativeGDI; - - /* Paint window */ - pScreen->CopyWindow = winCopyWindowNativeGDI; - - /* Fonts */ - pScreen->RealizeFont = winRealizeFontNativeGDI; - pScreen->UnrealizeFont = winUnrealizeFontNativeGDI; - - /* GC */ - pScreen->CreateGC = winCreateGCNativeGDI; - - /* Colormap Routines */ - pScreen->CreateColormap = miInitializeColormap; - pScreen->DestroyColormap = (DestroyColormapProcPtr) (void (*)(void)) NoopDDA; - pScreen->InstallColormap = miInstallColormap; - pScreen->UninstallColormap = miUninstallColormap; - pScreen->ListInstalledColormaps = miListInstalledColormaps; - pScreen->StoreColors = (StoreColorsProcPtr) (void (*)(void)) NoopDDA; - pScreen->ResolveColor = miResolveColor; - - /* Bitmap */ - pScreen->BitmapToRegion = winPixmapToRegionNativeGDI; - - winDebug ("winFinishScreenInitNativeGDI - calling miDCInitialize\n"); - - /* Set the default white and black pixel positions */ - pScreen->whitePixel = pScreen->blackPixel = (Pixel) 0; - - /* Initialize the cursor */ - if (!miDCInitialize (pScreen, &g_winPointerCursorFuncs)) - { - ErrorF ("winFinishScreenInitNativeGDI - miDCInitialize failed\n"); - return FALSE; - } - - /* Create a default colormap */ - if (!miCreateDefColormap (pScreen)) - { - ErrorF ("winFinishScreenInitNativeGDI - miCreateDefColormap () " - "failed\n"); - return FALSE; - } - - winDebug ("winFinishScreenInitNativeGDI - miCreateDefColormap () " - "returned\n"); - - /* mi doesn't use a CloseScreen procedure, so no need to wrap */ - pScreen->CloseScreen = pScreenPriv->pwinCloseScreen; - - /* Tell the server that we are enabled */ - pScreenPriv->fEnabled = TRUE; - - winDebug ("winFinishScreenInitNativeGDI - Successful addition of " - "screen %08x\n", - (unsigned int) pScreen); - - return TRUE; -} -#endif - - -/* See Porting Layer Definition - p. 33 */ -static Bool -winSaveScreen (ScreenPtr pScreen, int on) -{ - return TRUE; -} +/*
+ *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
+ * Kensuke Matsuzaki
+ */
+
+#ifdef HAVE_XWIN_CONFIG_H
+#include <xwin-config.h>
+#endif
+#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
+ */
+
+/*
+ * Local functions
+ */
+
+static Bool
+winSaveScreen (ScreenPtr pScreen, int on);
+
+
+/*
+ * Determine what type of screen we are initializing
+ * and call the appropriate procedure to intiailize
+ * that type of screen.
+ */
+
+Bool
+winScreenInit (int index,
+ ScreenPtr pScreen,
+ int argc, char **argv)
+{
+ winScreenInfoPtr pScreenInfo = &g_ScreenInfo[index];
+ winPrivScreenPtr pScreenPriv;
+ HDC hdc;
+ DWORD dwInitialBPP;
+
+ winDebug ("winScreenInit - dwWidth: %ld dwHeight: %ld\n",
+ pScreenInfo->dwWidth, pScreenInfo->dwHeight);
+
+ /* Allocate privates for this screen */
+ if (!winAllocatePrivates (pScreen))
+ {
+ ErrorF ("winScreenInit - Couldn't allocate screen privates\n");
+ return FALSE;
+ }
+
+ /* Get a pointer to the privates structure that was allocated */
+ pScreenPriv = winGetScreenPriv (pScreen);
+
+ /* Save a pointer to this screen in the screen info structure */
+ pScreenInfo->pScreen = pScreen;
+
+ /* Save a pointer to the screen info in the screen privates structure */
+ /* This allows us to get back to the screen info from a screen pointer */
+ pScreenPriv->pScreenInfo = pScreenInfo;
+
+ /*
+ * Determine which engine to use.
+ *
+ * NOTE: This is done once per screen because each screen possibly has
+ * a preferred engine specified on the command line.
+ */
+ if (!winSetEngine (pScreen))
+ {
+ ErrorF ("winScreenInit - winSetEngine () failed\n");
+ return FALSE;
+ }
+
+ /* Horribly misnamed function: Allow engine to adjust BPP for screen */
+ dwInitialBPP = pScreenInfo->dwBPP;
+
+ if (pScreenPriv->pwinAdjustVideoMode && !(*pScreenPriv->pwinAdjustVideoMode) (pScreen))
+ {
+ ErrorF ("winScreenInit - winAdjustVideoMode () failed\n");
+ return FALSE;
+ }
+
+ if (dwInitialBPP == WIN_DEFAULT_BPP)
+ {
+ /* No -depth parameter was passed, let the user know the depth being used */
+ winDebug ("winScreenInit - Using Windows display depth of %d bits per pixel\n", (int) pScreenInfo->dwBPP);
+ }
+ else if (dwInitialBPP != pScreenInfo->dwBPP)
+ {
+ /* Warn user if engine forced a depth different to -depth parameter */
+ winDebug ("winScreenInit - Command line depth of %d bpp overidden by engine, using %d bpp\n", (int) dwInitialBPP, (int) pScreenInfo->dwBPP);
+ }
+ else
+ {
+ winDebug ("winScreenInit - Using command line depth of %d bpp\n", (int) pScreenInfo->dwBPP);
+ }
+
+ /* Check for supported display depth */
+ if (!(WIN_SUPPORTED_BPPS & (1 << (pScreenInfo->dwBPP - 1))))
+ {
+ ErrorF ("winScreenInit - Unsupported display depth: %d\n" \
+ "Change your Windows display depth to 15, 16, 24, or 32 bits "
+ "per pixel.\n",
+ (int) pScreenInfo->dwBPP);
+ ErrorF ("winScreenInit - Supported depths: %08x\n",
+ WIN_SUPPORTED_BPPS);
+#if WIN_CHECK_DEPTH
+ return FALSE;
+#endif
+ }
+
+ /*
+ * Check that all monitors have the same display depth if we are using
+ * multiple monitors
+ */
+ if (pScreenInfo->fMultipleMonitors
+ && !GetSystemMetrics (SM_SAMEDISPLAYFORMAT))
+ {
+ ErrorF ("winScreenInit - Monitors do not all have same pixel format / "
+ "display depth.\n");
+ if (pScreenInfo->dwEngine == WIN_SERVER_SHADOW_GDI)
+ {
+ ErrorF ("winScreenInit - Performance may suffer off primary display.\n");
+ }
+ else
+ {
+ ErrorF ("winScreenInit - Using primary display only.\n");
+ pScreenInfo->fMultipleMonitors = FALSE;
+ }
+ }
+
+ /* Create display window */
+ if (pScreenPriv->pwinCreateBoundingWindow && !(*pScreenPriv->pwinCreateBoundingWindow) (pScreen))
+ {
+ ErrorF ("winScreenInit - pwinCreateBoundingWindow () "
+ "failed\n");
+ return FALSE;
+ }
+
+ /* Get a device context */
+ hdc = GetDC (pScreenPriv->hwndScreen);
+
+ /* Are we using multiple monitors? */
+ if (pScreenInfo->fMultipleMonitors)
+ {
+ /*
+ * In this case, some of the defaults set in
+ * winInitializeScreenDefaults() are not correct ...
+ */
+ if (!pScreenInfo->fUserGaveHeightAndWidth)
+ {
+ pScreenInfo->dwWidth = GetSystemMetrics (SM_CXVIRTUALSCREEN);
+ pScreenInfo->dwHeight = GetSystemMetrics (SM_CYVIRTUALSCREEN);
+ }
+ }
+
+ /* Release the device context */
+ ReleaseDC (pScreenPriv->hwndScreen, hdc);
+
+ /* Clear the visuals list */
+ miClearVisualTypes ();
+
+ /* Call the engine dependent screen initialization procedure */
+ if (pScreenPriv->pwinFinishScreenInit && !((*pScreenPriv->pwinFinishScreenInit) (index, pScreen, argc, argv)))
+ {
+ ErrorF ("winScreenInit - winFinishScreenInit () failed\n");
+
+ /* call the engine dependent screen close procedure to clean up from a failure */
+ pScreenPriv->pwinCloseScreen(index, pScreen);
+
+ return FALSE;
+ }
+
+ if (!g_fSoftwareCursor)
+ winInitCursor(pScreen);
+#ifdef WINDBG
+ else
+ winDebug("winScreenInit - Using software cursor\n");
+#endif
+
+ /*
+ Note the screen origin in a normalized coordinate space where (0,0) is at the top left
+ of the native virtual desktop area
+ */
+ pScreen->x = pScreenInfo->dwInitialX - GetSystemMetrics(SM_XVIRTUALSCREEN);
+ pScreen->y = pScreenInfo->dwInitialY - GetSystemMetrics(SM_YVIRTUALSCREEN);
+
+ winDebug("Screen %d added at virtual desktop coordinate (%d,%d).\n",
+ index, pScreen->x, pScreen->y);
+ winDebug ("winScreenInit - returning\n");
+
+ return TRUE;
+}
+
+static Bool
+winCreateScreenResources(ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ Bool result;
+
+ result = pScreenPriv->pwinCreateScreenResources(pScreen);
+
+ /* Now the screen bitmap has been wrapped in a pixmap,
+ add that to the Shadow framebuffer */
+ if (!shadowAdd(pScreen, pScreen->devPrivate,
+ pScreenPriv->pwinShadowUpdate, NULL, 0, 0))
+ {
+ ErrorF ("winCreateScreenResources - shadowAdd () failed\n");
+ return FALSE;
+ }
+
+ return result;
+}
+
+/* See Porting Layer Definition - p. 20 */
+Bool
+winFinishScreenInitFB (int index,
+ ScreenPtr pScreen,
+ int argc, char **argv)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ VisualPtr pVisual = NULL;
+ char *pbits = NULL;
+#if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW)
+ int iReturn;
+#endif
+
+ /* Create framebuffer */
+ if (!(*pScreenPriv->pwinInitScreen) (pScreen))
+ {
+ ErrorF ("winFinishScreenInitFB - Could not allocate framebuffer\n");
+ return FALSE;
+ }
+
+ /*
+ * Calculate the number of bits that are used to represent color in each pixel,
+ * the color depth for the screen
+ */
+ if (pScreenInfo->dwBPP == 8)
+ pScreenInfo->dwDepth = 8;
+ else
+ pScreenInfo->dwDepth = winCountBits (pScreenPriv->dwRedMask)
+ + winCountBits (pScreenPriv->dwGreenMask)
+ + winCountBits (pScreenPriv->dwBlueMask);
+
+ winDebug ("winFinishScreenInitFB - Masks: %08x %08x %08x\n",
+ (unsigned int) pScreenPriv->dwRedMask,
+ (unsigned int) pScreenPriv->dwGreenMask,
+ (unsigned int) pScreenPriv->dwBlueMask);
+
+ /* Init visuals */
+ if (!(*pScreenPriv->pwinInitVisuals) (pScreen))
+ {
+ ErrorF ("winFinishScreenInitFB - winInitVisuals failed\n");
+ return FALSE;
+ }
+
+ /* Setup a local variable to point to the framebuffer */
+ pbits = pScreenInfo->pfb;
+
+ /* Apparently we need this for the render extension */
+ miSetPixmapDepths ();
+
+ /* Start fb initialization */
+ if (!fbSetupScreen (pScreen,
+ pScreenInfo->pfb,
+ pScreenInfo->dwWidth, pScreenInfo->dwHeight,
+ monitorResolution, monitorResolution,
+ pScreenInfo->dwStride,
+ pScreenInfo->dwBPP))
+ {
+ ErrorF ("winFinishScreenInitFB - fbSetupScreen failed\n");
+ return FALSE;
+ }
+
+ /* Override default colormap routines if visual class is dynamic */
+ if (pScreenInfo->dwDepth == 8
+ && (pScreenInfo->dwEngine == WIN_SERVER_SHADOW_GDI
+ || (pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DDNL
+ && pScreenInfo->fFullScreen)
+ || (pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DD
+ && pScreenInfo->fFullScreen)))
+ {
+ winSetColormapFunctions (pScreen);
+
+ /*
+ * NOTE: Setting whitePixel to 255 causes Magic 7.1 to allocate its
+ * own colormap, as it cannot allocate 7 planes in the default
+ * colormap. Setting whitePixel to 1 allows Magic to get 7
+ * planes in the default colormap, so it doesn't create its
+ * own colormap. This latter situation is highly desireable,
+ * as it keeps the Magic window viewable when switching to
+ * other X clients that use the default colormap.
+ */
+ pScreen->blackPixel = 0;
+ pScreen->whitePixel = 1;
+ }
+
+ /* Place our save screen function */
+ pScreen->SaveScreen = winSaveScreen;
+
+ /* Finish fb initialization */
+ if (!fbFinishScreenInit (pScreen,
+ pScreenInfo->pfb,
+ pScreenInfo->dwWidth, pScreenInfo->dwHeight,
+ monitorResolution, monitorResolution,
+ pScreenInfo->dwStride,
+ pScreenInfo->dwBPP))
+ {
+ ErrorF ("winFinishScreenInitFB - fbFinishScreenInit failed\n");
+ return FALSE;
+ }
+
+ /* Save a pointer to the root visual */
+ for (pVisual = pScreen->visuals;
+ pVisual->vid != pScreen->rootVisual;
+ pVisual++);
+ pScreenPriv->pRootVisual = pVisual;
+
+ /*
+ * Setup points to the block and wakeup handlers. Pass a pointer
+ * to the current screen as pWakeupdata.
+ */
+ pScreen->BlockHandler = winBlockHandler;
+ pScreen->WakeupHandler = winWakeupHandler;
+ pScreen->blockData = pScreen;
+ pScreen->wakeupData = pScreen;
+
+ /* Render extension initialization, calls miPictureInit */
+ if (!fbPictureInit (pScreen, NULL, 0))
+ {
+ ErrorF ("winFinishScreenInitFB - fbPictureInit () failed\n");
+ return FALSE;
+ }
+
+#ifdef RANDR
+ /* Initialize resize and rotate support */
+ if (!winRandRInit (pScreen))
+ {
+ ErrorF ("winFinishScreenInitFB - winRandRInit () failed\n");
+ return FALSE;
+ }
+#endif
+
+ /* Setup the cursor routines */
+ winDebug ("winFinishScreenInitFB - Calling miDCInitialize ()\n");
+ miDCInitialize (pScreen, &g_winPointerCursorFuncs);
+
+ /* KDrive does winCreateDefColormap right after miDCInitialize */
+ /* Create a default colormap */
+ winDebug ("winFinishScreenInitFB - Calling winCreateDefColormap ()\n");
+ if (!winCreateDefColormap (pScreen))
+ {
+ ErrorF ("winFinishScreenInitFB - Could not create colormap\n");
+ return FALSE;
+ }
+
+ /* Initialize the shadow framebuffer layer */
+ if ((pScreenInfo->dwEngine == WIN_SERVER_SHADOW_GDI
+ || pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DD
+ || pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DDNL)
+#ifdef XWIN_MULTIWINDOWEXTWM
+ && !pScreenInfo->fMWExtWM
+#endif
+ )
+ {
+ winDebug ("winFinishScreenInitFB - Calling shadowSetup ()\n");
+ if (!shadowSetup(pScreen))
+ {
+ ErrorF ("winFinishScreenInitFB - shadowSetup () failed\n");
+ return FALSE;
+ }
+
+ /* Wrap CreateScreenResources so we can add the screen pixmap
+ to the Shadow framebuffer after it's been created */
+ pScreenPriv->pwinCreateScreenResources = pScreen->CreateScreenResources;
+ 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 */
+#define WRAP(a) \
+ if (pScreen->a) { \
+ pScreenPriv->a = pScreen->a; \
+ } else { \
+ ErrorF("null screen fn " #a "\n"); \
+ pScreenPriv->a = NULL; \
+ }
+
+ /* Save a pointer to each lower-level window procedure */
+ WRAP(CreateWindow);
+ WRAP(DestroyWindow);
+ WRAP(RealizeWindow);
+ WRAP(UnrealizeWindow);
+ WRAP(PositionWindow);
+ WRAP(ChangeWindowAttributes);
+ WRAP(SetShape);
+
+ /* Assign rootless window procedures to be top level procedures */
+ pScreen->CreateWindow = winCreateWindowRootless;
+ pScreen->DestroyWindow = winDestroyWindowRootless;
+ pScreen->PositionWindow = winPositionWindowRootless;
+ /*pScreen->ChangeWindowAttributes = winChangeWindowAttributesRootless;*/
+ pScreen->RealizeWindow = winMapWindowRootless;
+ pScreen->UnrealizeWindow = winUnmapWindowRootless;
+ pScreen->SetShape = winSetShapeRootless;
+
+ /* Undefine the WRAP macro, as it is not needed elsewhere */
+#undef WRAP
+ }
+
+
+#ifdef XWIN_MULTIWINDOW
+ /* Handle multi window mode */
+ else if (pScreenInfo->fMultiWindow)
+ {
+ /* Define the WRAP macro temporarily for local use */
+#define WRAP(a) \
+ if (pScreen->a) { \
+ pScreenPriv->a = pScreen->a; \
+ } else { \
+ ErrorF("null screen fn " #a "\n"); \
+ pScreenPriv->a = NULL; \
+ }
+
+ /* Save a pointer to each lower-level window procedure */
+ WRAP(CreateWindow);
+ WRAP(DestroyWindow);
+ WRAP(RealizeWindow);
+ WRAP(UnrealizeWindow);
+ WRAP(PositionWindow);
+ WRAP(ChangeWindowAttributes);
+ WRAP(ReparentWindow);
+ WRAP(RestackWindow);
+ WRAP(ResizeWindow);
+ WRAP(MoveWindow);
+ WRAP(CopyWindow);
+ WRAP(SetShape);
+
+ /* Assign multi-window window procedures to be top level procedures */
+ pScreen->CreateWindow = winCreateWindowMultiWindow;
+ pScreen->DestroyWindow = winDestroyWindowMultiWindow;
+ pScreen->PositionWindow = winPositionWindowMultiWindow;
+ /*pScreen->ChangeWindowAttributes = winChangeWindowAttributesMultiWindow;*/
+ pScreen->RealizeWindow = winMapWindowMultiWindow;
+ pScreen->UnrealizeWindow = winUnmapWindowMultiWindow;
+ pScreen->ReparentWindow = winReparentWindowMultiWindow;
+ pScreen->RestackWindow = winRestackWindowMultiWindow;
+ pScreen->ResizeWindow = winResizeWindowMultiWindow;
+ pScreen->MoveWindow = winMoveWindowMultiWindow;
+ pScreen->CopyWindow = winCopyWindowMultiWindow;
+ pScreen->SetShape = winSetShapeMultiWindow;
+
+ /* Undefine the WRAP macro, as it is not needed elsewhere */
+#undef WRAP
+ }
+#endif
+
+ /* Wrap either fb's or shadow's CloseScreen with our CloseScreen */
+ pScreenPriv->CloseScreen = pScreen->CloseScreen;
+ pScreen->CloseScreen = pScreenPriv->pwinCloseScreen;
+
+#if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW)
+ /* Create a mutex for modules in separate threads to wait for */
+ iReturn = pthread_mutex_init (&pScreenPriv->pmServerStarted, NULL);
+ if (iReturn != 0)
+ {
+ ErrorF ("winFinishScreenInitFB - pthread_mutex_init () failed: %d\n",
+ iReturn);
+ return FALSE;
+ }
+
+ /* Own the mutex for modules in separate threads */
+ iReturn = pthread_mutex_lock (&pScreenPriv->pmServerStarted);
+ if (iReturn != 0)
+ {
+ ErrorF ("winFinishScreenInitFB - pthread_mutex_lock () failed: %d\n",
+ iReturn);
+ return FALSE;
+ }
+
+ /* Set the ServerStarted flag to false */
+ pScreenPriv->fServerStarted = FALSE;
+#endif
+
+#ifdef XWIN_MULTIWINDOWEXTWM
+ pScreenPriv->fRestacking = FALSE;
+#endif
+
+#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM)
+ if (FALSE
+#ifdef XWIN_MULTIWINDOW
+ || pScreenInfo->fMultiWindow
+#endif
+#ifdef XWIN_MULTIWINDOWINTWM
+ || pScreenInfo->fInternalWM
+#endif
+ )
+ {
+ winDebug ("winFinishScreenInitFB - Calling winInitWM.\n");
+
+ /* Initialize multi window mode */
+ if (!winInitWM (&pScreenPriv->pWMInfo,
+ &pScreenPriv->ptWMProc,
+ &pScreenPriv->ptXMsgProc,
+ &pScreenPriv->pmServerStarted,
+ pScreenInfo->dwScreen,
+ (HWND)&pScreenPriv->hwndScreen,
+#ifdef XWIN_MULTIWINDOWINTWM
+ pScreenInfo->fInternalWM ||
+#endif
+ FALSE))
+ {
+ ErrorF ("winFinishScreenInitFB - winInitWM () failed.\n");
+ return FALSE;
+ }
+ }
+#endif
+
+ /* Tell the server that we are enabled */
+ pScreenPriv->fEnabled = TRUE;
+
+ /* Tell the server that we have a valid depth */
+ pScreenPriv->fBadDepth = FALSE;
+
+ winDebug ("winFinishScreenInitFB - returning\n");
+
+ return TRUE;
+}
+
+#ifdef XWIN_NATIVEGDI
+/* See Porting Layer Definition - p. 20 */
+
+Bool
+winFinishScreenInitNativeGDI (int index,
+ ScreenPtr pScreen,
+ int argc, char **argv)
+{
+ winScreenPriv(pScreen);
+ winScreenInfoPtr pScreenInfo = &g_ScreenInfo[index];
+ VisualPtr pVisuals = NULL;
+ DepthPtr pDepths = NULL;
+ VisualID rootVisual = 0;
+ int nVisuals = 0, nDepths = 0, nRootDepth = 0;
+
+ /* Ignore user input (mouse, keyboard) */
+ pScreenInfo->fIgnoreInput = FALSE;
+
+ /* Get device contexts for the screen and shadow bitmap */
+ pScreenPriv->hdcScreen = GetDC (pScreenPriv->hwndScreen);
+ if (pScreenPriv->hdcScreen == NULL)
+ FatalError ("winFinishScreenInitNativeGDI - Couldn't get a DC\n");
+
+ /* Init visuals */
+ if (!(*pScreenPriv->pwinInitVisuals) (pScreen))
+ {
+ ErrorF ("winFinishScreenInitNativeGDI - pwinInitVisuals failed\n");
+ return FALSE;
+ }
+
+ /* Initialize the mi visuals */
+ if (!miInitVisuals (&pVisuals, &pDepths, &nVisuals, &nDepths, &nRootDepth,
+ &rootVisual,
+ ((unsigned long)1 << (pScreenInfo->dwDepth - 1)), 8,
+ TrueColor))
+ {
+ ErrorF ("winFinishScreenInitNativeGDI - miInitVisuals () failed\n");
+ return FALSE;
+ }
+
+ /* Initialize the CloseScreen procedure pointer */
+ pScreen->CloseScreen = NULL;
+
+ /* Initialize the mi code */
+ if (!miScreenInit (pScreen,
+ NULL, /* No framebuffer */
+ pScreenInfo->dwWidth, pScreenInfo->dwHeight,
+ monitorResolution, monitorResolution,
+ pScreenInfo->dwStride,
+ nRootDepth, nDepths, pDepths, rootVisual,
+ nVisuals, pVisuals))
+ {
+ ErrorF ("winFinishScreenInitNativeGDI - miScreenInit failed\n");
+ return FALSE;
+ }
+
+ pScreen->defColormap = FakeClientID(0);
+
+ /*
+ * Register our block and wakeup handlers; these procedures
+ * process messages in our Windows message queue; specifically,
+ * they process mouse and keyboard input.
+ */
+ pScreen->BlockHandler = winBlockHandler;
+ pScreen->WakeupHandler = winWakeupHandler;
+ pScreen->blockData = pScreen;
+ pScreen->wakeupData = pScreen;
+
+ /* Place our save screen function */
+ pScreen->SaveScreen = winSaveScreen;
+
+ /* Pixmaps */
+ pScreen->CreatePixmap = winCreatePixmapNativeGDI;
+ pScreen->DestroyPixmap = winDestroyPixmapNativeGDI;
+
+ /* Other Screen Routines */
+ pScreen->QueryBestSize = winQueryBestSizeNativeGDI;
+ pScreen->SaveScreen = winSaveScreen;
+ pScreen->GetImage = miGetImage;
+ pScreen->GetSpans = winGetSpansNativeGDI;
+
+ /* Window Procedures */
+ pScreen->CreateWindow = winCreateWindowNativeGDI;
+ pScreen->DestroyWindow = winDestroyWindowNativeGDI;
+ pScreen->PositionWindow = winPositionWindowNativeGDI;
+ /*pScreen->ChangeWindowAttributes = winChangeWindowAttributesNativeGDI;*/
+ pScreen->RealizeWindow = winMapWindowNativeGDI;
+ pScreen->UnrealizeWindow = winUnmapWindowNativeGDI;
+
+ /* Paint window */
+ pScreen->CopyWindow = winCopyWindowNativeGDI;
+
+ /* Fonts */
+ pScreen->RealizeFont = winRealizeFontNativeGDI;
+ pScreen->UnrealizeFont = winUnrealizeFontNativeGDI;
+
+ /* GC */
+ pScreen->CreateGC = winCreateGCNativeGDI;
+
+ /* Colormap Routines */
+ pScreen->CreateColormap = miInitializeColormap;
+ pScreen->DestroyColormap = (DestroyColormapProcPtr) (void (*)(void)) NoopDDA;
+ pScreen->InstallColormap = miInstallColormap;
+ pScreen->UninstallColormap = miUninstallColormap;
+ pScreen->ListInstalledColormaps = miListInstalledColormaps;
+ pScreen->StoreColors = (StoreColorsProcPtr) (void (*)(void)) NoopDDA;
+ pScreen->ResolveColor = miResolveColor;
+
+ /* Bitmap */
+ pScreen->BitmapToRegion = winPixmapToRegionNativeGDI;
+
+ winDebug ("winFinishScreenInitNativeGDI - calling miDCInitialize\n");
+
+ /* Set the default white and black pixel positions */
+ pScreen->whitePixel = pScreen->blackPixel = (Pixel) 0;
+
+ /* Initialize the cursor */
+ if (!miDCInitialize (pScreen, &g_winPointerCursorFuncs))
+ {
+ ErrorF ("winFinishScreenInitNativeGDI - miDCInitialize failed\n");
+ return FALSE;
+ }
+
+ /* Create a default colormap */
+ if (!miCreateDefColormap (pScreen))
+ {
+ ErrorF ("winFinishScreenInitNativeGDI - miCreateDefColormap () "
+ "failed\n");
+ return FALSE;
+ }
+
+ winDebug ("winFinishScreenInitNativeGDI - miCreateDefColormap () "
+ "returned\n");
+
+ /* mi doesn't use a CloseScreen procedure, so no need to wrap */
+ pScreen->CloseScreen = pScreenPriv->pwinCloseScreen;
+
+ /* Tell the server that we are enabled */
+ pScreenPriv->fEnabled = TRUE;
+
+ winDebug ("winFinishScreenInitNativeGDI - Successful addition of "
+ "screen %08x\n",
+ (unsigned int) pScreen);
+
+ return TRUE;
+}
+#endif
+
+
+/* See Porting Layer Definition - p. 33 */
+static Bool
+winSaveScreen (ScreenPtr pScreen, int on)
+{
+ return TRUE;
+}
diff --git a/xorg-server/hw/xwin/winshaddd.c b/xorg-server/hw/xwin/winshaddd.c index 59530b1ed..0f6afe2f3 100644 --- a/xorg-server/hw/xwin/winshaddd.c +++ b/xorg-server/hw/xwin/winshaddd.c @@ -1,1325 +1,1326 @@ -/* - *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 "win.h" - - -/* - - -/* - * Local prototypes - */ - -static Bool -winAllocateFBShadowDD (ScreenPtr pScreen); - -static void -winShadowUpdateDD (ScreenPtr pScreen, - shadowBufPtr pBuf); - -static Bool -winCloseScreenShadowDD (int nIndex, ScreenPtr pScreen); - -static Bool -winInitVisualsShadowDD (ScreenPtr pScreen); - -static Bool -winAdjustVideoModeShadowDD (ScreenPtr pScreen); - -static Bool -winBltExposedRegionsShadowDD (ScreenPtr pScreen); - -static Bool -winActivateAppShadowDD (ScreenPtr pScreen); - -static Bool -winRedrawScreenShadowDD (ScreenPtr pScreen); - -static Bool -winRealizeInstalledPaletteShadowDD (ScreenPtr pScreen); - -static Bool -winInstallColormapShadowDD (ColormapPtr pColormap); - -static Bool -winStoreColorsShadowDD (ColormapPtr pmap, - int ndef, - xColorItem *pdefs); - -static Bool -winCreateColormapShadowDD (ColormapPtr pColormap); - -static Bool -winDestroyColormapShadowDD (ColormapPtr pColormap); - -static Bool -winCreatePrimarySurfaceShadowDD (ScreenPtr pScreen); - -static Bool -winReleasePrimarySurfaceShadowDD (ScreenPtr pScreen); - - -/* - * Create the primary surface and attach the clipper. - * Used for both the initial surface creation and during - * WM_DISPLAYCHANGE messages. - */ - -static Bool -winCreatePrimarySurfaceShadowDD (ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - HRESULT ddrval = DD_OK; - DDSURFACEDESC ddsd; - - /* Describe the primary surface */ - ZeroMemory (&ddsd, sizeof (ddsd)); - ddsd.dwSize = sizeof (ddsd); - ddsd.dwFlags = DDSD_CAPS; - ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; - - /* Create the primary surface */ - ddrval = IDirectDraw2_CreateSurface (pScreenPriv->pdd2, - &ddsd, - &pScreenPriv->pddsPrimary, - NULL); - if (FAILED (ddrval)) - { - ErrorF ("winCreatePrimarySurfaceShadowDD - Could not create primary " - "surface: %08x\n", (unsigned int) ddrval); - return FALSE; - } - - winDebug ("winCreatePrimarySurfaceShadowDD - Created primary surface\n"); - - /* - * Attach a clipper to the primary surface that will clip our blits to our - * display window. - */ - ddrval = IDirectDrawSurface2_SetClipper (pScreenPriv->pddsPrimary, - pScreenPriv->pddcPrimary); - if (FAILED (ddrval)) - { - ErrorF ("winCreatePrimarySurfaceShadowDD - Primary attach clipper " - "failed: %08x\n", - (unsigned int) ddrval); - return FALSE; - } - - winDebug ("winCreatePrimarySurfaceShadowDD - Attached clipper to " - "primary surface\n"); - - /* Everything was correct */ - return TRUE; -} - - -/* - * Detach the clipper and release the primary surface. - * Called from WM_DISPLAYCHANGE. - */ - -static Bool -winReleasePrimarySurfaceShadowDD (ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - - winDebug ("winReleasePrimarySurfaceShadowDD - Hello\n"); - - /* Release the primary surface and clipper, if they exist */ - if (pScreenPriv->pddsPrimary) - { - /* - * Detach the clipper from the primary surface. - * NOTE: We do this explicity for clarity. The Clipper is not released. - */ - IDirectDrawSurface2_SetClipper (pScreenPriv->pddsPrimary, - NULL); - - winDebug ("winReleasePrimarySurfaceShadowDD - Detached clipper\n"); - - /* Release the primary surface */ - IDirectDrawSurface2_Release (pScreenPriv->pddsPrimary); - pScreenPriv->pddsPrimary = NULL; - } - - winDebug ("winReleasePrimarySurfaceShadowDD - Released primary surface\n"); - - return TRUE; -} - - -/* - * Create a DirectDraw surface for the shadow framebuffer; also create - * a primary surface object so we can blit to the display. - * - * Install a DirectDraw clipper on our primary surface object - * that clips our blits to the unobscured client area of our display window. - */ - -static Bool -winAllocateFBShadowDD (ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; - HRESULT ddrval = DD_OK; - DDSURFACEDESC ddsd; - DDSURFACEDESC *pddsdShadow = NULL; - - winDebug ("winAllocateFBShadowDD\n"); - - /* Create a clipper */ - ddrval = (*g_fpDirectDrawCreateClipper) (0, - &pScreenPriv->pddcPrimary, - NULL); - if (FAILED (ddrval)) - { - ErrorF ("winAllocateFBShadowDD - Could not create clipper: %08x\n", - (unsigned int) ddrval); - return FALSE; - } - - winDebug ("winAllocateFBShadowDD - Created a clipper\n"); - - /* Attach the clipper to our display window */ - ddrval = IDirectDrawClipper_SetHWnd (pScreenPriv->pddcPrimary, - 0, - pScreenPriv->hwndScreen); - if (FAILED (ddrval)) - { - ErrorF ("winAllocateFBShadowDD - Clipper not attached to " - "window: %08x\n", - (unsigned int) ddrval); - return FALSE; - } - - winDebug ("winAllocateFBShadowDD - Attached clipper to window\n"); - - /* Create a DirectDraw object, store the address at lpdd */ - ddrval = (*g_fpDirectDrawCreate) (NULL, &pScreenPriv->pdd, NULL); - if (FAILED (ddrval)) - { - ErrorF ("winAllocateFBShadowDD - Could not start DirectDraw: %08x\n", - (unsigned int) ddrval); - return FALSE; - } - - winDebug ("winAllocateFBShadowDD () - Created and initialized DD\n"); - - /* Get a DirectDraw2 interface pointer */ - ddrval = IDirectDraw_QueryInterface (pScreenPriv->pdd, - &IID_IDirectDraw2, - (LPVOID*) &pScreenPriv->pdd2); - if (FAILED (ddrval)) - { - ErrorF ("winAllocateFBShadowDD - Failed DD2 query: %08x\n", - (unsigned int) ddrval); - return FALSE; - } - - /* Are we full screen? */ - if (pScreenInfo->fFullScreen) - { - DDSURFACEDESC ddsdCurrent; - DWORD dwRefreshRateCurrent = 0; - HDC hdc = NULL; - - /* Set the cooperative level to full screen */ - ddrval = IDirectDraw2_SetCooperativeLevel (pScreenPriv->pdd2, - pScreenPriv->hwndScreen, - DDSCL_EXCLUSIVE - | DDSCL_FULLSCREEN); - if (FAILED (ddrval)) - { - ErrorF ("winAllocateFBShadowDD - Could not set " - "cooperative level: %08x\n", - (unsigned int) ddrval); - return FALSE; - } - - /* - * We only need to get the current refresh rate for comparison - * if a refresh rate has been passed on the command line. - */ - if (pScreenInfo->dwRefreshRate != 0) - { - ZeroMemory (&ddsdCurrent, sizeof (ddsdCurrent)); - ddsdCurrent.dwSize = sizeof (ddsdCurrent); - - /* Get information about current display settings */ - ddrval = IDirectDraw2_GetDisplayMode (pScreenPriv->pdd2, - &ddsdCurrent); - if (FAILED (ddrval)) - { - ErrorF ("winAllocateFBShadowDD - Could not get current " - "refresh rate: %08x. Continuing.\n", - (unsigned int) ddrval); - dwRefreshRateCurrent = 0; - } - else - { - /* Grab the current refresh rate */ - dwRefreshRateCurrent = ddsdCurrent.u2.dwRefreshRate; - } - } - - /* Clean up the refresh rate */ - if (dwRefreshRateCurrent == pScreenInfo->dwRefreshRate) - { - /* - * Refresh rate is non-specified or equal to current. - */ - pScreenInfo->dwRefreshRate = 0; - } - - /* Grab a device context for the screen */ - hdc = GetDC (NULL); - if (hdc == NULL) - { - ErrorF ("winAllocateFBShadowDD - GetDC () failed\n"); - return FALSE; - } - - /* Only change the video mode when different than current mode */ - if (!pScreenInfo->fMultipleMonitors - && (pScreenInfo->dwWidth != GetSystemMetrics (SM_CXSCREEN) - || pScreenInfo->dwHeight != GetSystemMetrics (SM_CYSCREEN) - || pScreenInfo->dwBPP != GetDeviceCaps (hdc, BITSPIXEL) - || pScreenInfo->dwRefreshRate != 0)) - { - winDebug ("winAllocateFBShadowDD - Changing video mode\n"); - - /* Change the video mode to the mode requested, and use the driver default refresh rate on failure */ - ddrval = IDirectDraw2_SetDisplayMode (pScreenPriv->pdd2, - pScreenInfo->dwWidth, - pScreenInfo->dwHeight, - pScreenInfo->dwBPP, - pScreenInfo->dwRefreshRate, - 0); - if (FAILED (ddrval)) - { - ErrorF ("winAllocateFBShadowDD - Could not set "\ - "full screen display mode: %08x\n", - (unsigned int) ddrval); - ErrorF ("winAllocateFBShadowDD - Using default driver refresh rate\n"); - ddrval = IDirectDraw2_SetDisplayMode (pScreenPriv->pdd2, - pScreenInfo->dwWidth, - pScreenInfo->dwHeight, - pScreenInfo->dwBPP, - 0, - 0); - if (FAILED(ddrval)) - { - ErrorF ("winAllocateFBShadowDD - Could not set default refresh rate " - "full screen display mode: %08x\n", - (unsigned int) ddrval); - return FALSE; - } - } - } - else - { - winDebug ("winAllocateFBShadowDD - Not changing video mode\n"); - } - - /* Release our DC */ - ReleaseDC (NULL, hdc); - hdc = NULL; - } - else - { - /* Set the cooperative level for windowed mode */ - ddrval = IDirectDraw2_SetCooperativeLevel (pScreenPriv->pdd2, - pScreenPriv->hwndScreen, - DDSCL_NORMAL); - if (FAILED (ddrval)) - { - ErrorF ("winAllocateFBShadowDD - Could not set "\ - "cooperative level: %08x\n", - (unsigned int) ddrval); - return FALSE; - } - } - - /* Create the primary surface */ - if (!winCreatePrimarySurfaceShadowDD (pScreen)) - { - ErrorF ("winAllocateFBShadowDD - winCreatePrimarySurfaceShadowDD " - "failed\n"); - return FALSE; - } - - /* Describe the shadow surface to be created */ - /* NOTE: Do not use a DDSCAPS_VIDEOMEMORY surface, - * as drawing, locking, and unlocking take forever - * with video memory surfaces. In addition, - * video memory is a somewhat scarce resource, - * so you shouldn't be allocating video memory when - * you have the option of using system memory instead. - */ - ZeroMemory (&ddsd, sizeof (ddsd)); - ddsd.dwSize = sizeof (ddsd); - ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; - ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; - ddsd.dwHeight = pScreenInfo->dwHeight; - ddsd.dwWidth = pScreenInfo->dwWidth; - - /* Create the shadow surface */ - ddrval = IDirectDraw2_CreateSurface (pScreenPriv->pdd2, - &ddsd, - &pScreenPriv->pddsShadow, - NULL); - if (FAILED (ddrval)) - { - ErrorF ("winAllocateFBShadowDD - Could not create shadow "\ - "surface: %08x\n", (unsigned int) ddrval); - return FALSE; - } - - winDebug ("winAllocateFBShadowDD - Created shadow\n"); - - /* Allocate a DD surface description for our screen privates */ - pddsdShadow = pScreenPriv->pddsdShadow = malloc (sizeof (DDSURFACEDESC)); - if (pddsdShadow == NULL) - { - ErrorF ("winAllocateFBShadowDD - Could not allocate surface "\ - "description memory\n"); - return FALSE; - } - ZeroMemory (pddsdShadow, sizeof (*pddsdShadow)); - pddsdShadow->dwSize = sizeof (*pddsdShadow); - - winDebug ("winAllocateFBShadowDD - Locking shadow\n"); - - /* Lock the shadow surface */ - ddrval = IDirectDrawSurface2_Lock (pScreenPriv->pddsShadow, - NULL, - pddsdShadow, - DDLOCK_WAIT, - NULL); - if (FAILED (ddrval) || pddsdShadow->lpSurface == NULL) - { - ErrorF ("winAllocateFBShadowDD - Could not lock shadow "\ - "surface: %08x\n", (unsigned int) ddrval); - return FALSE; - } - - winDebug ("winAllocateFBShadowDD - Locked shadow\n"); - - /* We don't know how to deal with anything other than RGB */ - if (!(pddsdShadow->ddpfPixelFormat.dwFlags & DDPF_RGB)) - { - ErrorF ("winAllocateFBShadowDD - Color format other than RGB\n"); - return FALSE; - } - - /* Grab the pitch from the surface desc */ - pScreenInfo->dwStride = (pddsdShadow->u1.lPitch * 8) - / pScreenInfo->dwBPP; - - /* Save the pointer to our surface memory */ - pScreenInfo->pfb = pddsdShadow->lpSurface; - - /* Grab the color depth and masks from the surface description */ - pScreenPriv->dwRedMask = pddsdShadow->ddpfPixelFormat.u2.dwRBitMask; - pScreenPriv->dwGreenMask = pddsdShadow->ddpfPixelFormat.u3.dwGBitMask; - pScreenPriv->dwBlueMask = pddsdShadow->ddpfPixelFormat.u4.dwBBitMask; - - winDebug ("winAllocateFBShadowDD - Returning\n"); - - return TRUE; -} - -static void -winFreeFBShadowDD (ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; - - /* Free the shadow surface, if there is one */ - if (pScreenPriv->pddsShadow) - { - IDirectDrawSurface2_Unlock (pScreenPriv->pddsShadow, NULL); - IDirectDrawSurface2_Release (pScreenPriv->pddsShadow); - pScreenPriv->pddsShadow = NULL; - } - - /* Detach the clipper from the primary surface and release the primary surface, if there is one */ - winReleasePrimarySurfaceShadowDD(pScreen); - - /* Release the clipper object */ - if (pScreenPriv->pddcPrimary) - { - IDirectDrawClipper_Release (pScreenPriv->pddcPrimary); - pScreenPriv->pddcPrimary = NULL; - } - - /* Free the DirectDraw2 object, if there is one */ - if (pScreenPriv->pdd2) - { - IDirectDraw2_RestoreDisplayMode (pScreenPriv->pdd2); - IDirectDraw2_Release (pScreenPriv->pdd2); - pScreenPriv->pdd2 = NULL; - } - - /* Free the DirectDraw object, if there is one */ - if (pScreenPriv->pdd) - { - IDirectDraw_Release (pScreenPriv->pdd); - pScreenPriv->pdd = NULL; - } - - /* Invalidate the ScreenInfo's fb pointer */ - pScreenInfo->pfb = NULL; -} - -/* - * Transfer the damaged regions of the shadow framebuffer to the display. - */ - -static void -winShadowUpdateDD (ScreenPtr pScreen, - shadowBufPtr pBuf) -{ - winScreenPriv(pScreen); - winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; - RegionPtr damage = shadowDamage(pBuf); - HRESULT ddrval = DD_OK; - RECT rcDest, rcSrc; - POINT ptOrigin; - DWORD dwBox = RegionNumRects (damage); - BoxPtr pBox = RegionRects (damage); - HRGN hrgnTemp = NULL, hrgnCombined = NULL; - - /* - * Return immediately if the app is not active - * and we are fullscreen, or if we have a bad display depth - */ - if ((!pScreenPriv->fActive && pScreenInfo->fFullScreen) - || pScreenPriv->fBadDepth) return; - - /* Return immediately if we didn't get needed surfaces */ - if (!pScreenPriv->pddsPrimary || !pScreenPriv->pddsShadow) - return; - - /* Get the origin of the window in the screen coords */ - ptOrigin.x = pScreenInfo->dwXOffset; - ptOrigin.y = pScreenInfo->dwYOffset; - MapWindowPoints (pScreenPriv->hwndScreen, - HWND_DESKTOP, - (LPPOINT)&ptOrigin, 1); - - /* Unlock the shadow surface, so we can blit */ - ddrval = IDirectDrawSurface2_Unlock (pScreenPriv->pddsShadow, NULL); - if (FAILED (ddrval)) - { - ErrorF ("winShadowUpdateDD - Unlock failed\n"); - return; - } - - /* - * Handle small regions with multiple blits, - * handle large regions by creating a clipping region and - * doing a single blit constrained to that clipping region. - */ - if (pScreenInfo->dwClipUpdatesNBoxes == 0 - || dwBox < pScreenInfo->dwClipUpdatesNBoxes) - { - /* Loop through all boxes in the damaged region */ - while (dwBox--) - { - /* Assign damage box to source rectangle */ - rcSrc.left = pBox->x1; - rcSrc.top = pBox->y1; - rcSrc.right = pBox->x2; - rcSrc.bottom = pBox->y2; - - /* Calculate destination rectange */ - rcDest.left = ptOrigin.x + rcSrc.left; - rcDest.top = ptOrigin.y + rcSrc.top; - rcDest.right = ptOrigin.x + rcSrc.right; - rcDest.bottom = ptOrigin.y + rcSrc.bottom; - - /* Blit the damaged areas */ - ddrval = IDirectDrawSurface2_Blt (pScreenPriv->pddsPrimary, - &rcDest, - pScreenPriv->pddsShadow, - &rcSrc, - DDBLT_WAIT, - NULL); - - /* Get a pointer to the next box */ - ++pBox; - } - } - else - { - BoxPtr pBoxExtents = RegionExtents(damage); - - /* Compute a GDI region from the damaged region */ - hrgnCombined = CreateRectRgn (pBox->x1, pBox->y1, pBox->x2, pBox->y2); - dwBox--; - pBox++; - while (dwBox--) - { - hrgnTemp = CreateRectRgn (pBox->x1, pBox->y1, pBox->x2, pBox->y2); - CombineRgn (hrgnCombined, hrgnCombined, hrgnTemp, RGN_OR); - DeleteObject (hrgnTemp); - pBox++; - } - - /* Install the GDI region as a clipping region */ - SelectClipRgn (pScreenPriv->hdcScreen, hrgnCombined); - DeleteObject (hrgnCombined); - hrgnCombined = NULL; - - /* Calculating a bounding box for the source is easy */ - rcSrc.left = pBoxExtents->x1; - rcSrc.top = pBoxExtents->y1; - rcSrc.right = pBoxExtents->x2; - rcSrc.bottom = pBoxExtents->y2; - - /* Calculating a bounding box for the destination is trickier */ - rcDest.left = ptOrigin.x + rcSrc.left; - rcDest.top = ptOrigin.y + rcSrc.top; - rcDest.right = ptOrigin.x + rcSrc.right; - rcDest.bottom = ptOrigin.y + rcSrc.bottom; - - /* Our Blt should be clipped to the invalidated region */ - ddrval = IDirectDrawSurface2_Blt (pScreenPriv->pddsPrimary, - &rcDest, - pScreenPriv->pddsShadow, - &rcSrc, - DDBLT_WAIT, - NULL); - - /* Reset the clip region */ - SelectClipRgn (pScreenPriv->hdcScreen, NULL); - } - - /* Relock the shadow surface */ - ddrval = IDirectDrawSurface2_Lock (pScreenPriv->pddsShadow, - NULL, - pScreenPriv->pddsdShadow, - DDLOCK_WAIT, - NULL); - if (FAILED (ddrval)) - { - ErrorF ("winShadowUpdateDD - Lock failed\n"); - return; - } - - /* Has our memory pointer changed? */ - if (pScreenInfo->pfb != pScreenPriv->pddsdShadow->lpSurface) - { - extern const char *g_pszLogFile; - ErrorF ("winShadowUpdateDD - Memory location of the shadow " - "surface has changed, trying to update the root window " - "pixmap header to point to the new address. If you get " - "this message and "PROJECT_NAME" freezes or crashes " - "after this message then send a problem report and your " - "%s file to " BUILDERADDR "\n", g_pszLogFile); - - /* Location of shadow framebuffer has changed */ - winUpdateFBPointer(pScreen, pScreenPriv->pddsdShadow->lpSurface); - } -} - -static Bool -winInitScreenShadowDD (ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - - /* Get a device context for the screen */ - pScreenPriv->hdcScreen = GetDC (pScreenPriv->hwndScreen); - - return winAllocateFBShadowDD(pScreen); -} - -/* - * Call the wrapped CloseScreen function. - * - * Free our resources and private structures. - */ - -static Bool -winCloseScreenShadowDD (int nIndex, ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; - Bool fReturn; - - winDebug ("winCloseScreenShadowDD - Freeing screen resources\n"); - - /* Flag that the screen is closed */ - pScreenPriv->fClosed = TRUE; - pScreenPriv->fActive = FALSE; - - /* Call the wrapped CloseScreen procedure */ - WIN_UNWRAP(CloseScreen); - fReturn = (*pScreen->CloseScreen) (nIndex, pScreen); - - winFreeFBShadowDD(pScreen); - - /* Free the screen DC */ - ReleaseDC (pScreenPriv->hwndScreen, pScreenPriv->hdcScreen); - - /* Delete the window property */ - RemoveProp (pScreenPriv->hwndScreen, WIN_SCR_PROP); - - /* Delete tray icon, if we have one */ - if (!pScreenInfo->fNoTrayIcon) - winDeleteNotifyIcon (pScreenPriv); - - /* Free the exit confirmation dialog box, if it exists */ - if (g_hDlgExit != NULL) - { - DestroyWindow (g_hDlgExit); - g_hDlgExit = NULL; - } - - /* Kill our window */ - if (pScreenPriv->hwndScreen) - { - DestroyWindow (pScreenPriv->hwndScreen); - pScreenPriv->hwndScreen = NULL; - } - -#if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW) - /* Destroy the thread startup mutex */ - pthread_mutex_destroy (&pScreenPriv->pmServerStarted); -#endif - - /* Kill our screeninfo's pointer to the screen */ - pScreenInfo->pScreen = NULL; - - /* Free the screen privates for this screen */ - free ((pointer) pScreenPriv); - - return fReturn; -} - - -/* - * Tell mi what sort of visuals we need. - * - * Generally we only need one visual, as our screen can only - * handle one format at a time, I believe. You may want - * to verify that last sentence. - */ - -static Bool -winInitVisualsShadowDD (ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; - DWORD dwRedBits, dwGreenBits, dwBlueBits; - - /* Count the number of ones in each color mask */ - dwRedBits = winCountBits (pScreenPriv->dwRedMask); - dwGreenBits = winCountBits (pScreenPriv->dwGreenMask); - dwBlueBits = winCountBits (pScreenPriv->dwBlueMask); - - /* Store the maximum number of ones in a color mask as the bitsPerRGB */ - if (dwRedBits == 0 || dwGreenBits == 0 || dwBlueBits == 0) - pScreenPriv->dwBitsPerRGB = 8; - else if (dwRedBits > dwGreenBits && dwRedBits > dwBlueBits) - pScreenPriv->dwBitsPerRGB = dwRedBits; - else if (dwGreenBits > dwRedBits && dwGreenBits > dwBlueBits) - pScreenPriv->dwBitsPerRGB = dwGreenBits; - else - pScreenPriv->dwBitsPerRGB = dwBlueBits; - - winDebug ("winInitVisualsShadowDD - Masks %08x %08x %08x BPRGB %d d %d " - "bpp %d\n", - (unsigned int) pScreenPriv->dwRedMask, - (unsigned int) pScreenPriv->dwGreenMask, - (unsigned int) pScreenPriv->dwBlueMask, - (int) pScreenPriv->dwBitsPerRGB, - (int) pScreenInfo->dwDepth, - (int) pScreenInfo->dwBPP); - - /* Create a single visual according to the Windows screen depth */ - switch (pScreenInfo->dwDepth) - { - case 24: - case 16: - case 15: - /* Create the real visual */ - if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth, - TrueColorMask, - pScreenPriv->dwBitsPerRGB, - TrueColor, - pScreenPriv->dwRedMask, - pScreenPriv->dwGreenMask, - pScreenPriv->dwBlueMask)) - { - ErrorF ("winInitVisualsShadowDD - miSetVisualTypesAndMasks " - "failed for TrueColor\n"); - return FALSE; - } - -#ifdef XWIN_EMULATEPSEUDO - if (!pScreenInfo->fEmulatePseudo) - break; - - /* Setup a pseudocolor visual */ - if (!miSetVisualTypesAndMasks (8, - PseudoColorMask, - 8, - -1, - 0, - 0, - 0)) - { - ErrorF ("winInitVisualsShadowDD - miSetVisualTypesAndMasks " - "failed for PseudoColor\n"); - return FALSE; - } -#endif - break; - - case 8: - if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth, - pScreenInfo->fFullScreen - ? PseudoColorMask : StaticColorMask, - pScreenPriv->dwBitsPerRGB, - pScreenInfo->fFullScreen - ? PseudoColor : StaticColor, - pScreenPriv->dwRedMask, - pScreenPriv->dwGreenMask, - pScreenPriv->dwBlueMask)) - { - ErrorF ("winInitVisualsShadowDD - miSetVisualTypesAndMasks " - "failed\n"); - return FALSE; - } - break; - - default: - ErrorF ("winInitVisualsShadowDD - Unknown screen depth\n"); - return FALSE; - } - - winDebug ("winInitVisualsShadowDD - Returning\n"); - - return TRUE; -} - - -/* - * Adjust the user proposed video mode - */ - -static Bool -winAdjustVideoModeShadowDD (ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; - HDC hdc = NULL; - DWORD dwBPP; - - /* We're in serious trouble if we can't get a DC */ - hdc = GetDC (NULL); - if (hdc == NULL) - { - ErrorF ("winAdjustVideoModeShadowDD - GetDC () failed\n"); - return FALSE; - } - - /* Query GDI for current display depth */ - dwBPP = GetDeviceCaps (hdc, BITSPIXEL); - - /* DirectDraw can only change the depth in fullscreen mode */ - if (!(pScreenInfo->fFullScreen && - (pScreenInfo->dwBPP != WIN_DEFAULT_BPP))) - { - /* Otherwise, We'll use GDI's depth */ - pScreenInfo->dwBPP = dwBPP; - } - - /* Release our DC */ - ReleaseDC (NULL, hdc); - return TRUE; -} - - -/* - * Blt exposed regions to the screen - */ - -static Bool -winBltExposedRegionsShadowDD (ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; - RECT rcSrc, rcDest; - POINT ptOrigin; - HDC hdcUpdate = NULL; - PAINTSTRUCT ps; - HRESULT ddrval = DD_OK; - Bool fReturn = TRUE; - Bool fLocked = TRUE; - int i; - - /* BeginPaint gives us an hdc that clips to the invalidated region */ - hdcUpdate = BeginPaint (pScreenPriv->hwndScreen, &ps); - if (hdcUpdate == NULL) - { - ErrorF ("winBltExposedRegionsShadowDD - BeginPaint () returned " - "a NULL device context handle. Aborting blit attempt.\n"); - return FALSE; - } - - /* Unlock the shadow surface, so we can blit */ - ddrval = IDirectDrawSurface2_Unlock (pScreenPriv->pddsShadow, NULL); - if (FAILED (ddrval)) - { - fReturn = FALSE; - goto winBltExposedRegionsShadowDD_Exit; - } - else - { - /* Flag that we have unlocked the shadow surface */ - fLocked = FALSE; - } - - /* Get the origin of the window in the screen coords */ - ptOrigin.x = pScreenInfo->dwXOffset; - ptOrigin.y = pScreenInfo->dwYOffset; - - MapWindowPoints (pScreenPriv->hwndScreen, - HWND_DESKTOP, - (LPPOINT)&ptOrigin, 1); - rcDest.left = ptOrigin.x; - rcDest.right = ptOrigin.x + pScreenInfo->dwWidth; - rcDest.top = ptOrigin.y; - rcDest.bottom = ptOrigin.y + pScreenInfo->dwHeight; - - /* Source can be enter shadow surface, as Blt should clip */ - rcSrc.left = 0; - rcSrc.top = 0; - rcSrc.right = pScreenInfo->dwWidth; - rcSrc.bottom = pScreenInfo->dwHeight; - - /* Try to regain the primary surface and blit again if we've lost it */ - for (i = 0; i <= WIN_REGAIN_SURFACE_RETRIES; ++i) - { - /* Our Blt should be clipped to the invalidated region */ - ddrval = IDirectDrawSurface2_Blt (pScreenPriv->pddsPrimary, - &rcDest, - pScreenPriv->pddsShadow, - &rcSrc, - DDBLT_WAIT, - NULL); - if (ddrval == DDERR_SURFACELOST) - { - /* Surface was lost */ - ErrorF ("winBltExposedRegionsShadowDD - IDirectDrawSurface2_Blt " - "reported that the primary surface was lost, " - "trying to restore, retry: %d\n", i + 1); - - /* Try to restore the surface, once */ - ddrval = IDirectDrawSurface2_Restore (pScreenPriv->pddsPrimary); - ErrorF ("winBltExposedRegionsShadowDD - " - "IDirectDrawSurface2_Restore returned: "); - if (ddrval == DD_OK) - ErrorF ("DD_OK\n"); - else if (ddrval == DDERR_WRONGMODE) - ErrorF ("DDERR_WRONGMODE\n"); - else if (ddrval == DDERR_INCOMPATIBLEPRIMARY) - ErrorF ("DDERR_INCOMPATIBLEPRIMARY\n"); - else if (ddrval == DDERR_UNSUPPORTED) - ErrorF ("DDERR_UNSUPPORTED\n"); - else if (ddrval == DDERR_INVALIDPARAMS) - ErrorF ("DDERR_INVALIDPARAMS\n"); - else if (ddrval == DDERR_INVALIDOBJECT) - ErrorF ("DDERR_INVALIDOBJECT\n"); - else - ErrorF ("unknown error: %08x\n", (unsigned int) ddrval); - - /* Loop around to try the blit one more time */ - continue; - } - else if (FAILED (ddrval)) - { - fReturn = FALSE; - ErrorF ("winBltExposedRegionsShadowDD - IDirectDrawSurface2_Blt " - "failed, but surface not lost: %08x %d\n", - (unsigned int) ddrval, (int) ddrval); - goto winBltExposedRegionsShadowDD_Exit; - } - else - { - /* Success, stop looping */ - break; - } - } - - /* Relock the shadow surface */ - ddrval = IDirectDrawSurface2_Lock (pScreenPriv->pddsShadow, - NULL, - pScreenPriv->pddsdShadow, - DDLOCK_WAIT, - NULL); - if (FAILED (ddrval)) - { - fReturn = FALSE; - ErrorF ("winBltExposedRegionsShadowDD - IDirectDrawSurface2_Lock " - "failed\n"); - goto winBltExposedRegionsShadowDD_Exit; - } - else - { - /* Indicate that we have relocked the shadow surface */ - fLocked = TRUE; - } - - /* Has our memory pointer changed? */ - if (pScreenInfo->pfb != pScreenPriv->pddsdShadow->lpSurface) - winUpdateFBPointer (pScreen, - pScreenPriv->pddsdShadow->lpSurface); - - winBltExposedRegionsShadowDD_Exit: - /* EndPaint frees the DC */ - if (hdcUpdate != NULL) - EndPaint (pScreenPriv->hwndScreen, &ps); - - /* - * Relock the surface if it is not locked. We don't care if locking fails, - * as it will cause the server to shutdown within a few more operations. - */ - if (!fLocked) - { - IDirectDrawSurface2_Lock (pScreenPriv->pddsShadow, - NULL, - pScreenPriv->pddsdShadow, - DDLOCK_WAIT, - NULL); - - /* Has our memory pointer changed? */ - if (pScreenInfo->pfb != pScreenPriv->pddsdShadow->lpSurface) - winUpdateFBPointer (pScreen, - pScreenPriv->pddsdShadow->lpSurface); - - fLocked = TRUE; - } - return fReturn; -} - - -/* - * Do any engine-specific appliation-activation processing - */ - -static Bool -winActivateAppShadowDD (ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - - /* - * Do we have a surface? - * Are we active? - * Are we fullscreen? - */ - if (pScreenPriv != NULL - && pScreenPriv->pddsPrimary != NULL - && pScreenPriv->fActive) - { - /* Primary surface was lost, restore it */ - IDirectDrawSurface2_Restore (pScreenPriv->pddsPrimary); - } - - return TRUE; -} - - -/* - * Reblit the shadow framebuffer to the screen. - */ - -static Bool -winRedrawScreenShadowDD (ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; - HRESULT ddrval = DD_OK; - RECT rcSrc, rcDest; - POINT ptOrigin; - - /* Get the origin of the window in the screen coords */ - ptOrigin.x = pScreenInfo->dwXOffset; - ptOrigin.y = pScreenInfo->dwYOffset; - MapWindowPoints (pScreenPriv->hwndScreen, - HWND_DESKTOP, - (LPPOINT)&ptOrigin, 1); - rcDest.left = ptOrigin.x; - rcDest.right = ptOrigin.x + pScreenInfo->dwWidth; - rcDest.top = ptOrigin.y; - rcDest.bottom = ptOrigin.y + pScreenInfo->dwHeight; - - /* Source can be entire shadow surface, as Blt should clip for us */ - rcSrc.left = 0; - rcSrc.top = 0; - rcSrc.right = pScreenInfo->dwWidth; - rcSrc.bottom = pScreenInfo->dwHeight; - - /* Redraw the whole window, to take account for the new colors */ - ddrval = IDirectDrawSurface2_Blt (pScreenPriv->pddsPrimary, - &rcDest, - pScreenPriv->pddsShadow, - &rcSrc, - DDBLT_WAIT, - NULL); - if (FAILED (ddrval)) - { - ErrorF ("winRedrawScreenShadowDD - IDirectDrawSurface_Blt () " - "failed: %08x\n", - (unsigned int) ddrval); - } - - return TRUE; -} - - -/* - * Realize the currently installed colormap - */ - -static Bool -winRealizeInstalledPaletteShadowDD (ScreenPtr pScreen) -{ - return TRUE; -} - - -/* - * Install the specified colormap - */ - -static Bool -winInstallColormapShadowDD (ColormapPtr pColormap) -{ - ScreenPtr pScreen = pColormap->pScreen; - winScreenPriv(pScreen); - winCmapPriv(pColormap); - HRESULT ddrval = DD_OK; - - /* Install the DirectDraw palette on the primary surface */ - ddrval = IDirectDrawSurface2_SetPalette (pScreenPriv->pddsPrimary, - pCmapPriv->lpDDPalette); - if (FAILED (ddrval)) - { - ErrorF ("winInstallColormapShadowDD - Failed installing the " - "DirectDraw palette.\n"); - return FALSE; - } - - /* Save a pointer to the newly installed colormap */ - pScreenPriv->pcmapInstalled = pColormap; - - return TRUE; -} - - -/* - * Store the specified colors in the specified colormap - */ - -static Bool -winStoreColorsShadowDD (ColormapPtr pColormap, - int ndef, - xColorItem *pdefs) -{ - ScreenPtr pScreen = pColormap->pScreen; - winScreenPriv(pScreen); - winCmapPriv(pColormap); - ColormapPtr curpmap = pScreenPriv->pcmapInstalled; - HRESULT ddrval = DD_OK; - - /* Put the X colormap entries into the Windows logical palette */ - ddrval = IDirectDrawPalette_SetEntries (pCmapPriv->lpDDPalette, - 0, - pdefs[0].pixel, - ndef, - pCmapPriv->peColors - + pdefs[0].pixel); - if (FAILED (ddrval)) - { - ErrorF ("winStoreColorsShadowDD - SetEntries () failed\n"); - return FALSE; - } - - /* Don't install the DirectDraw palette if the colormap is not installed */ - if (pColormap != curpmap) - { - return TRUE; - } - - if (!winInstallColormapShadowDD (pColormap)) - { - ErrorF ("winStoreColorsShadowDD - Failed installing colormap\n"); - return FALSE; - } - - return TRUE; -} - - -/* - * Colormap initialization procedure - */ - -static Bool -winCreateColormapShadowDD (ColormapPtr pColormap) -{ - HRESULT ddrval = DD_OK; - ScreenPtr pScreen = pColormap->pScreen; - winScreenPriv(pScreen); - winCmapPriv(pColormap); - - /* Create a DirectDraw palette */ - ddrval = IDirectDraw2_CreatePalette (pScreenPriv->pdd, - DDPCAPS_8BIT | DDPCAPS_ALLOW256, - pCmapPriv->peColors, - &pCmapPriv->lpDDPalette, - NULL); - if (FAILED (ddrval)) - { - ErrorF ("winCreateColormapShadowDD - CreatePalette failed\n"); - return FALSE; - } - - return TRUE; -} - - -/* - * Colormap destruction procedure - */ - -static Bool -winDestroyColormapShadowDD (ColormapPtr pColormap) -{ - winScreenPriv(pColormap->pScreen); - winCmapPriv(pColormap); - HRESULT ddrval = DD_OK; - - /* - * Is colormap to be destroyed the default? - * - * Non-default colormaps should have had winUninstallColormap - * called on them before we get here. The default colormap - * will not have had winUninstallColormap called on it. Thus, - * we need to handle the default colormap in a special way. - */ - if (pColormap->flags & IsDefault) - { - winDebug ("winDestroyColormapShadowDD - Destroying default " - "colormap\n"); - - /* - * FIXME: Walk the list of all screens, popping the default - * palette out of each screen device context. - */ - - /* Pop the palette out of the primary surface */ - ddrval = IDirectDrawSurface2_SetPalette (pScreenPriv->pddsPrimary, - NULL); - if (FAILED (ddrval)) - { - ErrorF ("winDestroyColormapShadowDD - Failed freeing the " - "default colormap DirectDraw palette.\n"); - return FALSE; - } - - /* Clear our private installed colormap pointer */ - pScreenPriv->pcmapInstalled = NULL; - } - - /* Release the palette */ - IDirectDrawPalette_Release (pCmapPriv->lpDDPalette); - - /* Invalidate the colormap privates */ - pCmapPriv->lpDDPalette = NULL; - - return TRUE; -} - - -/* - * Set engine specific functions - */ - -Bool -winSetEngineFunctionsShadowDD (ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; - - /* Set our pointers */ - pScreenPriv->pwinAllocateFB = winAllocateFBShadowDD; - pScreenPriv->pwinFreeFB = winFreeFBShadowDD; - pScreenPriv->pwinShadowUpdate = winShadowUpdateDD; - pScreenPriv->pwinInitScreen = winInitScreenShadowDD; - pScreenPriv->pwinCloseScreen = winCloseScreenShadowDD; - pScreenPriv->pwinInitVisuals = winInitVisualsShadowDD; - pScreenPriv->pwinAdjustVideoMode = winAdjustVideoModeShadowDD; - if (pScreenInfo->fFullScreen) - pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowFullScreen; - else - pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowWindowed; - pScreenPriv->pwinFinishScreenInit = winFinishScreenInitFB; - pScreenPriv->pwinBltExposedRegions = winBltExposedRegionsShadowDD; - pScreenPriv->pwinActivateApp = winActivateAppShadowDD; - pScreenPriv->pwinRedrawScreen = winRedrawScreenShadowDD; - pScreenPriv->pwinRealizeInstalledPalette - = winRealizeInstalledPaletteShadowDD; - pScreenPriv->pwinInstallColormap = winInstallColormapShadowDD; - pScreenPriv->pwinStoreColors = winStoreColorsShadowDD; - pScreenPriv->pwinCreateColormap = winCreateColormapShadowDD; - pScreenPriv->pwinDestroyColormap = winDestroyColormapShadowDD; - pScreenPriv->pwinHotKeyAltTab = (winHotKeyAltTabProcPtr) (void (*)(void))NoopDDA; - pScreenPriv->pwinCreatePrimarySurface = winCreatePrimarySurfaceShadowDD; - pScreenPriv->pwinReleasePrimarySurface = winReleasePrimarySurfaceShadowDD; -#ifdef XWIN_MULTIWINDOW - pScreenPriv->pwinFinishCreateWindowsWindow = - (winFinishCreateWindowsWindowProcPtr) (void (*)(void))NoopDDA; -#endif - - return TRUE; -} +/*
+ *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 "win.h"
+
+
+/*
+
+
+/*
+ * Local prototypes
+ */
+
+static Bool
+winAllocateFBShadowDD (ScreenPtr pScreen);
+
+static void
+winShadowUpdateDD (ScreenPtr pScreen,
+ shadowBufPtr pBuf);
+
+static Bool
+winCloseScreenShadowDD (int nIndex, ScreenPtr pScreen);
+
+static Bool
+winInitVisualsShadowDD (ScreenPtr pScreen);
+
+static Bool
+winAdjustVideoModeShadowDD (ScreenPtr pScreen);
+
+static Bool
+winBltExposedRegionsShadowDD (ScreenPtr pScreen);
+
+static Bool
+winActivateAppShadowDD (ScreenPtr pScreen);
+
+static Bool
+winRedrawScreenShadowDD (ScreenPtr pScreen);
+
+static Bool
+winRealizeInstalledPaletteShadowDD (ScreenPtr pScreen);
+
+static Bool
+winInstallColormapShadowDD (ColormapPtr pColormap);
+
+static Bool
+winStoreColorsShadowDD (ColormapPtr pmap,
+ int ndef,
+ xColorItem *pdefs);
+
+static Bool
+winCreateColormapShadowDD (ColormapPtr pColormap);
+
+static Bool
+winDestroyColormapShadowDD (ColormapPtr pColormap);
+
+static Bool
+winCreatePrimarySurfaceShadowDD (ScreenPtr pScreen);
+
+static Bool
+winReleasePrimarySurfaceShadowDD (ScreenPtr pScreen);
+
+
+/*
+ * Create the primary surface and attach the clipper.
+ * Used for both the initial surface creation and during
+ * WM_DISPLAYCHANGE messages.
+ */
+
+static Bool
+winCreatePrimarySurfaceShadowDD (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ HRESULT ddrval = DD_OK;
+ DDSURFACEDESC ddsd;
+
+ /* Describe the primary surface */
+ ZeroMemory (&ddsd, sizeof (ddsd));
+ ddsd.dwSize = sizeof (ddsd);
+ ddsd.dwFlags = DDSD_CAPS;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+
+ /* Create the primary surface */
+ ddrval = IDirectDraw2_CreateSurface (pScreenPriv->pdd2,
+ &ddsd,
+ &pScreenPriv->pddsPrimary,
+ NULL);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winCreatePrimarySurfaceShadowDD - Could not create primary "
+ "surface: %08x\n", (unsigned int) ddrval);
+ return FALSE;
+ }
+
+ winDebug ("winCreatePrimarySurfaceShadowDD - Created primary surface\n");
+
+ /*
+ * Attach a clipper to the primary surface that will clip our blits to our
+ * display window.
+ */
+ ddrval = IDirectDrawSurface2_SetClipper (pScreenPriv->pddsPrimary,
+ pScreenPriv->pddcPrimary);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winCreatePrimarySurfaceShadowDD - Primary attach clipper "
+ "failed: %08x\n",
+ (unsigned int) ddrval);
+ return FALSE;
+ }
+
+ winDebug ("winCreatePrimarySurfaceShadowDD - Attached clipper to "
+ "primary surface\n");
+
+ /* Everything was correct */
+ return TRUE;
+}
+
+
+/*
+ * Detach the clipper and release the primary surface.
+ * Called from WM_DISPLAYCHANGE.
+ */
+
+static Bool
+winReleasePrimarySurfaceShadowDD (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+
+ winDebug ("winReleasePrimarySurfaceShadowDD - Hello\n");
+
+ /* Release the primary surface and clipper, if they exist */
+ if (pScreenPriv->pddsPrimary)
+ {
+ /*
+ * Detach the clipper from the primary surface.
+ * NOTE: We do this explicity for clarity. The Clipper is not released.
+ */
+ IDirectDrawSurface2_SetClipper (pScreenPriv->pddsPrimary,
+ NULL);
+
+ winDebug ("winReleasePrimarySurfaceShadowDD - Detached clipper\n");
+
+ /* Release the primary surface */
+ IDirectDrawSurface2_Release (pScreenPriv->pddsPrimary);
+ pScreenPriv->pddsPrimary = NULL;
+ }
+
+ winDebug ("winReleasePrimarySurfaceShadowDD - Released primary surface\n");
+
+ return TRUE;
+}
+
+
+/*
+ * Create a DirectDraw surface for the shadow framebuffer; also create
+ * a primary surface object so we can blit to the display.
+ *
+ * Install a DirectDraw clipper on our primary surface object
+ * that clips our blits to the unobscured client area of our display window.
+ */
+
+static Bool
+winAllocateFBShadowDD (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ HRESULT ddrval = DD_OK;
+ DDSURFACEDESC ddsd;
+ DDSURFACEDESC *pddsdShadow = NULL;
+
+ winDebug ("winAllocateFBShadowDD\n");
+
+ /* Create a clipper */
+ ddrval = (*g_fpDirectDrawCreateClipper) (0,
+ &pScreenPriv->pddcPrimary,
+ NULL);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winAllocateFBShadowDD - Could not create clipper: %08x\n",
+ (unsigned int) ddrval);
+ return FALSE;
+ }
+
+ winDebug ("winAllocateFBShadowDD - Created a clipper\n");
+
+ /* Attach the clipper to our display window */
+ ddrval = IDirectDrawClipper_SetHWnd (pScreenPriv->pddcPrimary,
+ 0,
+ pScreenPriv->hwndScreen);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winAllocateFBShadowDD - Clipper not attached to "
+ "window: %08x\n",
+ (unsigned int) ddrval);
+ return FALSE;
+ }
+
+ winDebug ("winAllocateFBShadowDD - Attached clipper to window\n");
+
+ /* Create a DirectDraw object, store the address at lpdd */
+ ddrval = (*g_fpDirectDrawCreate) (NULL, &pScreenPriv->pdd, NULL);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winAllocateFBShadowDD - Could not start DirectDraw: %08x\n",
+ (unsigned int) ddrval);
+ return FALSE;
+ }
+
+ winDebug ("winAllocateFBShadowDD () - Created and initialized DD\n");
+
+ /* Get a DirectDraw2 interface pointer */
+ ddrval = IDirectDraw_QueryInterface (pScreenPriv->pdd,
+ &IID_IDirectDraw2,
+ (LPVOID*) &pScreenPriv->pdd2);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winAllocateFBShadowDD - Failed DD2 query: %08x\n",
+ (unsigned int) ddrval);
+ return FALSE;
+ }
+
+ /* Are we full screen? */
+ if (pScreenInfo->fFullScreen)
+ {
+ DDSURFACEDESC ddsdCurrent;
+ DWORD dwRefreshRateCurrent = 0;
+ HDC hdc = NULL;
+
+ /* Set the cooperative level to full screen */
+ ddrval = IDirectDraw2_SetCooperativeLevel (pScreenPriv->pdd2,
+ pScreenPriv->hwndScreen,
+ DDSCL_EXCLUSIVE
+ | DDSCL_FULLSCREEN);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winAllocateFBShadowDD - Could not set "
+ "cooperative level: %08x\n",
+ (unsigned int) ddrval);
+ return FALSE;
+ }
+
+ /*
+ * We only need to get the current refresh rate for comparison
+ * if a refresh rate has been passed on the command line.
+ */
+ if (pScreenInfo->dwRefreshRate != 0)
+ {
+ ZeroMemory (&ddsdCurrent, sizeof (ddsdCurrent));
+ ddsdCurrent.dwSize = sizeof (ddsdCurrent);
+
+ /* Get information about current display settings */
+ ddrval = IDirectDraw2_GetDisplayMode (pScreenPriv->pdd2,
+ &ddsdCurrent);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winAllocateFBShadowDD - Could not get current "
+ "refresh rate: %08x. Continuing.\n",
+ (unsigned int) ddrval);
+ dwRefreshRateCurrent = 0;
+ }
+ else
+ {
+ /* Grab the current refresh rate */
+ dwRefreshRateCurrent = ddsdCurrent.u2.dwRefreshRate;
+ }
+ }
+
+ /* Clean up the refresh rate */
+ if (dwRefreshRateCurrent == pScreenInfo->dwRefreshRate)
+ {
+ /*
+ * Refresh rate is non-specified or equal to current.
+ */
+ pScreenInfo->dwRefreshRate = 0;
+ }
+
+ /* Grab a device context for the screen */
+ hdc = GetDC (NULL);
+ if (hdc == NULL)
+ {
+ ErrorF ("winAllocateFBShadowDD - GetDC () failed\n");
+ return FALSE;
+ }
+
+ /* Only change the video mode when different than current mode */
+ if (!pScreenInfo->fMultipleMonitors
+ && (pScreenInfo->dwWidth != GetSystemMetrics (SM_CXSCREEN)
+ || pScreenInfo->dwHeight != GetSystemMetrics (SM_CYSCREEN)
+ || pScreenInfo->dwBPP != GetDeviceCaps (hdc, BITSPIXEL)
+ || pScreenInfo->dwRefreshRate != 0))
+ {
+ winDebug ("winAllocateFBShadowDD - Changing video mode\n");
+
+ /* Change the video mode to the mode requested, and use the driver default refresh rate on failure */
+ ddrval = IDirectDraw2_SetDisplayMode (pScreenPriv->pdd2,
+ pScreenInfo->dwWidth,
+ pScreenInfo->dwHeight,
+ pScreenInfo->dwBPP,
+ pScreenInfo->dwRefreshRate,
+ 0);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winAllocateFBShadowDD - Could not set "\
+ "full screen display mode: %08x\n",
+ (unsigned int) ddrval);
+ ErrorF ("winAllocateFBShadowDD - Using default driver refresh rate\n");
+ ddrval = IDirectDraw2_SetDisplayMode (pScreenPriv->pdd2,
+ pScreenInfo->dwWidth,
+ pScreenInfo->dwHeight,
+ pScreenInfo->dwBPP,
+ 0,
+ 0);
+ if (FAILED(ddrval))
+ {
+ ErrorF ("winAllocateFBShadowDD - Could not set default refresh rate "
+ "full screen display mode: %08x\n",
+ (unsigned int) ddrval);
+ return FALSE;
+ }
+ }
+ }
+ else
+ {
+ winDebug ("winAllocateFBShadowDD - Not changing video mode\n");
+ }
+
+ /* Release our DC */
+ ReleaseDC (NULL, hdc);
+ hdc = NULL;
+ }
+ else
+ {
+ /* Set the cooperative level for windowed mode */
+ ddrval = IDirectDraw2_SetCooperativeLevel (pScreenPriv->pdd2,
+ pScreenPriv->hwndScreen,
+ DDSCL_NORMAL);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winAllocateFBShadowDD - Could not set "\
+ "cooperative level: %08x\n",
+ (unsigned int) ddrval);
+ return FALSE;
+ }
+ }
+
+ /* Create the primary surface */
+ if (!winCreatePrimarySurfaceShadowDD (pScreen))
+ {
+ ErrorF ("winAllocateFBShadowDD - winCreatePrimarySurfaceShadowDD "
+ "failed\n");
+ return FALSE;
+ }
+
+ /* Describe the shadow surface to be created */
+ /* NOTE: Do not use a DDSCAPS_VIDEOMEMORY surface,
+ * as drawing, locking, and unlocking take forever
+ * with video memory surfaces. In addition,
+ * video memory is a somewhat scarce resource,
+ * so you shouldn't be allocating video memory when
+ * you have the option of using system memory instead.
+ */
+ ZeroMemory (&ddsd, sizeof (ddsd));
+ ddsd.dwSize = sizeof (ddsd);
+ ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
+ ddsd.dwHeight = pScreenInfo->dwHeight;
+ ddsd.dwWidth = pScreenInfo->dwWidth;
+
+ /* Create the shadow surface */
+ ddrval = IDirectDraw2_CreateSurface (pScreenPriv->pdd2,
+ &ddsd,
+ &pScreenPriv->pddsShadow,
+ NULL);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winAllocateFBShadowDD - Could not create shadow "\
+ "surface: %08x\n", (unsigned int) ddrval);
+ return FALSE;
+ }
+
+ winDebug ("winAllocateFBShadowDD - Created shadow\n");
+
+ /* Allocate a DD surface description for our screen privates */
+ pddsdShadow = pScreenPriv->pddsdShadow = malloc (sizeof (DDSURFACEDESC));
+ if (pddsdShadow == NULL)
+ {
+ ErrorF ("winAllocateFBShadowDD - Could not allocate surface "\
+ "description memory\n");
+ return FALSE;
+ }
+ ZeroMemory (pddsdShadow, sizeof (*pddsdShadow));
+ pddsdShadow->dwSize = sizeof (*pddsdShadow);
+
+ winDebug ("winAllocateFBShadowDD - Locking shadow\n");
+
+ /* Lock the shadow surface */
+ ddrval = IDirectDrawSurface2_Lock (pScreenPriv->pddsShadow,
+ NULL,
+ pddsdShadow,
+ DDLOCK_WAIT,
+ NULL);
+ if (FAILED (ddrval) || pddsdShadow->lpSurface == NULL)
+ {
+ ErrorF ("winAllocateFBShadowDD - Could not lock shadow "\
+ "surface: %08x\n", (unsigned int) ddrval);
+ return FALSE;
+ }
+
+ winDebug ("winAllocateFBShadowDD - Locked shadow\n");
+
+ /* We don't know how to deal with anything other than RGB */
+ if (!(pddsdShadow->ddpfPixelFormat.dwFlags & DDPF_RGB))
+ {
+ ErrorF ("winAllocateFBShadowDD - Color format other than RGB\n");
+ return FALSE;
+ }
+
+ /* Grab the pitch from the surface desc */
+ pScreenInfo->dwStride = (pddsdShadow->u1.lPitch * 8)
+ / pScreenInfo->dwBPP;
+
+ /* Save the pointer to our surface memory */
+ pScreenInfo->pfb = pddsdShadow->lpSurface;
+
+ /* Grab the color depth and masks from the surface description */
+ pScreenPriv->dwRedMask = pddsdShadow->ddpfPixelFormat.u2.dwRBitMask;
+ pScreenPriv->dwGreenMask = pddsdShadow->ddpfPixelFormat.u3.dwGBitMask;
+ pScreenPriv->dwBlueMask = pddsdShadow->ddpfPixelFormat.u4.dwBBitMask;
+
+ winDebug ("winAllocateFBShadowDD - Returning\n");
+
+ return TRUE;
+}
+
+static void
+winFreeFBShadowDD (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+
+ /* Free the shadow surface, if there is one */
+ if (pScreenPriv->pddsShadow)
+ {
+ IDirectDrawSurface2_Unlock (pScreenPriv->pddsShadow, NULL);
+ IDirectDrawSurface2_Release (pScreenPriv->pddsShadow);
+ pScreenPriv->pddsShadow = NULL;
+ }
+
+ /* Detach the clipper from the primary surface and release the primary surface, if there is one */
+ winReleasePrimarySurfaceShadowDD(pScreen);
+
+ /* Release the clipper object */
+ if (pScreenPriv->pddcPrimary)
+ {
+ IDirectDrawClipper_Release (pScreenPriv->pddcPrimary);
+ pScreenPriv->pddcPrimary = NULL;
+ }
+
+ /* Free the DirectDraw2 object, if there is one */
+ if (pScreenPriv->pdd2)
+ {
+ IDirectDraw2_RestoreDisplayMode (pScreenPriv->pdd2);
+ IDirectDraw2_Release (pScreenPriv->pdd2);
+ pScreenPriv->pdd2 = NULL;
+ }
+
+ /* Free the DirectDraw object, if there is one */
+ if (pScreenPriv->pdd)
+ {
+ IDirectDraw_Release (pScreenPriv->pdd);
+ pScreenPriv->pdd = NULL;
+ }
+
+ /* Invalidate the ScreenInfo's fb pointer */
+ pScreenInfo->pfb = NULL;
+}
+
+/*
+ * Transfer the damaged regions of the shadow framebuffer to the display.
+ */
+
+static void
+winShadowUpdateDD (ScreenPtr pScreen,
+ shadowBufPtr pBuf)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ RegionPtr damage = shadowDamage(pBuf);
+ HRESULT ddrval = DD_OK;
+ RECT rcDest, rcSrc;
+ POINT ptOrigin;
+ DWORD dwBox = RegionNumRects (damage);
+ BoxPtr pBox = RegionRects (damage);
+ HRGN hrgnTemp = NULL, hrgnCombined = NULL;
+
+ /*
+ * Return immediately if the app is not active
+ * and we are fullscreen, or if we have a bad display depth
+ */
+ if ((!pScreenPriv->fActive && pScreenInfo->fFullScreen)
+ || pScreenPriv->fBadDepth) return;
+
+ /* Return immediately if we didn't get needed surfaces */
+ if (!pScreenPriv->pddsPrimary || !pScreenPriv->pddsShadow)
+ return;
+
+ /* Get the origin of the window in the screen coords */
+ ptOrigin.x = pScreenInfo->dwXOffset;
+ ptOrigin.y = pScreenInfo->dwYOffset;
+ MapWindowPoints (pScreenPriv->hwndScreen,
+ HWND_DESKTOP,
+ (LPPOINT)&ptOrigin, 1);
+
+ /* Unlock the shadow surface, so we can blit */
+ ddrval = IDirectDrawSurface2_Unlock (pScreenPriv->pddsShadow, NULL);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winShadowUpdateDD - Unlock failed\n");
+ return;
+ }
+
+ /*
+ * Handle small regions with multiple blits,
+ * handle large regions by creating a clipping region and
+ * doing a single blit constrained to that clipping region.
+ */
+ if (pScreenInfo->dwClipUpdatesNBoxes == 0
+ || dwBox < pScreenInfo->dwClipUpdatesNBoxes)
+ {
+ /* Loop through all boxes in the damaged region */
+ while (dwBox--)
+ {
+ /* Assign damage box to source rectangle */
+ rcSrc.left = pBox->x1;
+ rcSrc.top = pBox->y1;
+ rcSrc.right = pBox->x2;
+ rcSrc.bottom = pBox->y2;
+
+ /* Calculate destination rectange */
+ rcDest.left = ptOrigin.x + rcSrc.left;
+ rcDest.top = ptOrigin.y + rcSrc.top;
+ rcDest.right = ptOrigin.x + rcSrc.right;
+ rcDest.bottom = ptOrigin.y + rcSrc.bottom;
+
+ /* Blit the damaged areas */
+ ddrval = IDirectDrawSurface2_Blt (pScreenPriv->pddsPrimary,
+ &rcDest,
+ pScreenPriv->pddsShadow,
+ &rcSrc,
+ DDBLT_WAIT,
+ NULL);
+
+ /* Get a pointer to the next box */
+ ++pBox;
+ }
+ }
+ else
+ {
+ BoxPtr pBoxExtents = RegionExtents(damage);
+
+ /* Compute a GDI region from the damaged region */
+ hrgnCombined = CreateRectRgn (pBox->x1, pBox->y1, pBox->x2, pBox->y2);
+ dwBox--;
+ pBox++;
+ while (dwBox--)
+ {
+ hrgnTemp = CreateRectRgn (pBox->x1, pBox->y1, pBox->x2, pBox->y2);
+ CombineRgn (hrgnCombined, hrgnCombined, hrgnTemp, RGN_OR);
+ DeleteObject (hrgnTemp);
+ pBox++;
+ }
+
+ /* Install the GDI region as a clipping region */
+ SelectClipRgn (pScreenPriv->hdcScreen, hrgnCombined);
+ DeleteObject (hrgnCombined);
+ hrgnCombined = NULL;
+
+ /* Calculating a bounding box for the source is easy */
+ rcSrc.left = pBoxExtents->x1;
+ rcSrc.top = pBoxExtents->y1;
+ rcSrc.right = pBoxExtents->x2;
+ rcSrc.bottom = pBoxExtents->y2;
+
+ /* Calculating a bounding box for the destination is trickier */
+ rcDest.left = ptOrigin.x + rcSrc.left;
+ rcDest.top = ptOrigin.y + rcSrc.top;
+ rcDest.right = ptOrigin.x + rcSrc.right;
+ rcDest.bottom = ptOrigin.y + rcSrc.bottom;
+
+ /* Our Blt should be clipped to the invalidated region */
+ ddrval = IDirectDrawSurface2_Blt (pScreenPriv->pddsPrimary,
+ &rcDest,
+ pScreenPriv->pddsShadow,
+ &rcSrc,
+ DDBLT_WAIT,
+ NULL);
+
+ /* Reset the clip region */
+ SelectClipRgn (pScreenPriv->hdcScreen, NULL);
+ }
+
+ /* Relock the shadow surface */
+ ddrval = IDirectDrawSurface2_Lock (pScreenPriv->pddsShadow,
+ NULL,
+ pScreenPriv->pddsdShadow,
+ DDLOCK_WAIT,
+ NULL);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winShadowUpdateDD - Lock failed\n");
+ return;
+ }
+
+ /* Has our memory pointer changed? */
+ if (pScreenInfo->pfb != pScreenPriv->pddsdShadow->lpSurface)
+ {
+ extern const char *g_pszLogFile;
+ ErrorF ("winShadowUpdateDD - Memory location of the shadow "
+ "surface has changed, trying to update the root window "
+ "pixmap header to point to the new address. If you get "
+ "this message and "PROJECT_NAME" freezes or crashes "
+ "after this message then send a problem report and your "
+ "%s file to " BUILDERADDR "\n", g_pszLogFile);
+
+ /* Location of shadow framebuffer has changed */
+ winUpdateFBPointer(pScreen, pScreenPriv->pddsdShadow->lpSurface);
+ }
+}
+
+static Bool
+winInitScreenShadowDD (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+
+ /* Get a device context for the screen */
+ pScreenPriv->hdcScreen = GetDC (pScreenPriv->hwndScreen);
+
+ return winAllocateFBShadowDD(pScreen);
+}
+
+/*
+ * Call the wrapped CloseScreen function.
+ *
+ * Free our resources and private structures.
+ */
+
+static Bool
+winCloseScreenShadowDD (int nIndex, ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ Bool fReturn;
+
+ winDebug ("winCloseScreenShadowDD - Freeing screen resources\n");
+
+ /* Flag that the screen is closed */
+ pScreenPriv->fClosed = TRUE;
+ pScreenPriv->fActive = FALSE;
+
+ /* Call the wrapped CloseScreen procedure */
+ WIN_UNWRAP(CloseScreen);
+ if (pScreen->CloseScreen)
+ fReturn = (*pScreen->CloseScreen) (nIndex, pScreen);
+
+ winFreeFBShadowDD(pScreen);
+
+ /* Free the screen DC */
+ ReleaseDC (pScreenPriv->hwndScreen, pScreenPriv->hdcScreen);
+
+ /* Delete the window property */
+ RemoveProp (pScreenPriv->hwndScreen, WIN_SCR_PROP);
+
+ /* Delete tray icon, if we have one */
+ if (!pScreenInfo->fNoTrayIcon)
+ winDeleteNotifyIcon (pScreenPriv);
+
+ /* Free the exit confirmation dialog box, if it exists */
+ if (g_hDlgExit != NULL)
+ {
+ DestroyWindow (g_hDlgExit);
+ g_hDlgExit = NULL;
+ }
+
+ /* Kill our window */
+ if (pScreenPriv->hwndScreen)
+ {
+ DestroyWindow (pScreenPriv->hwndScreen);
+ pScreenPriv->hwndScreen = NULL;
+ }
+
+#if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW)
+ /* Destroy the thread startup mutex */
+ pthread_mutex_destroy (&pScreenPriv->pmServerStarted);
+#endif
+
+ /* Kill our screeninfo's pointer to the screen */
+ pScreenInfo->pScreen = NULL;
+
+ /* Free the screen privates for this screen */
+ free ((pointer) pScreenPriv);
+
+ return fReturn;
+}
+
+
+/*
+ * Tell mi what sort of visuals we need.
+ *
+ * Generally we only need one visual, as our screen can only
+ * handle one format at a time, I believe. You may want
+ * to verify that last sentence.
+ */
+
+static Bool
+winInitVisualsShadowDD (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ DWORD dwRedBits, dwGreenBits, dwBlueBits;
+
+ /* Count the number of ones in each color mask */
+ dwRedBits = winCountBits (pScreenPriv->dwRedMask);
+ dwGreenBits = winCountBits (pScreenPriv->dwGreenMask);
+ dwBlueBits = winCountBits (pScreenPriv->dwBlueMask);
+
+ /* Store the maximum number of ones in a color mask as the bitsPerRGB */
+ if (dwRedBits == 0 || dwGreenBits == 0 || dwBlueBits == 0)
+ pScreenPriv->dwBitsPerRGB = 8;
+ else if (dwRedBits > dwGreenBits && dwRedBits > dwBlueBits)
+ pScreenPriv->dwBitsPerRGB = dwRedBits;
+ else if (dwGreenBits > dwRedBits && dwGreenBits > dwBlueBits)
+ pScreenPriv->dwBitsPerRGB = dwGreenBits;
+ else
+ pScreenPriv->dwBitsPerRGB = dwBlueBits;
+
+ winDebug ("winInitVisualsShadowDD - Masks %08x %08x %08x BPRGB %d d %d "
+ "bpp %d\n",
+ (unsigned int) pScreenPriv->dwRedMask,
+ (unsigned int) pScreenPriv->dwGreenMask,
+ (unsigned int) pScreenPriv->dwBlueMask,
+ (int) pScreenPriv->dwBitsPerRGB,
+ (int) pScreenInfo->dwDepth,
+ (int) pScreenInfo->dwBPP);
+
+ /* Create a single visual according to the Windows screen depth */
+ switch (pScreenInfo->dwDepth)
+ {
+ case 24:
+ case 16:
+ case 15:
+ /* Create the real visual */
+ if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth,
+ TrueColorMask,
+ pScreenPriv->dwBitsPerRGB,
+ TrueColor,
+ pScreenPriv->dwRedMask,
+ pScreenPriv->dwGreenMask,
+ pScreenPriv->dwBlueMask))
+ {
+ ErrorF ("winInitVisualsShadowDD - miSetVisualTypesAndMasks "
+ "failed for TrueColor\n");
+ return FALSE;
+ }
+
+#ifdef XWIN_EMULATEPSEUDO
+ if (!pScreenInfo->fEmulatePseudo)
+ break;
+
+ /* Setup a pseudocolor visual */
+ if (!miSetVisualTypesAndMasks (8,
+ PseudoColorMask,
+ 8,
+ -1,
+ 0,
+ 0,
+ 0))
+ {
+ ErrorF ("winInitVisualsShadowDD - miSetVisualTypesAndMasks "
+ "failed for PseudoColor\n");
+ return FALSE;
+ }
+#endif
+ break;
+
+ case 8:
+ if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth,
+ pScreenInfo->fFullScreen
+ ? PseudoColorMask : StaticColorMask,
+ pScreenPriv->dwBitsPerRGB,
+ pScreenInfo->fFullScreen
+ ? PseudoColor : StaticColor,
+ pScreenPriv->dwRedMask,
+ pScreenPriv->dwGreenMask,
+ pScreenPriv->dwBlueMask))
+ {
+ ErrorF ("winInitVisualsShadowDD - miSetVisualTypesAndMasks "
+ "failed\n");
+ return FALSE;
+ }
+ break;
+
+ default:
+ ErrorF ("winInitVisualsShadowDD - Unknown screen depth\n");
+ return FALSE;
+ }
+
+ winDebug ("winInitVisualsShadowDD - Returning\n");
+
+ return TRUE;
+}
+
+
+/*
+ * Adjust the user proposed video mode
+ */
+
+static Bool
+winAdjustVideoModeShadowDD (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ HDC hdc = NULL;
+ DWORD dwBPP;
+
+ /* We're in serious trouble if we can't get a DC */
+ hdc = GetDC (NULL);
+ if (hdc == NULL)
+ {
+ ErrorF ("winAdjustVideoModeShadowDD - GetDC () failed\n");
+ return FALSE;
+ }
+
+ /* Query GDI for current display depth */
+ dwBPP = GetDeviceCaps (hdc, BITSPIXEL);
+
+ /* DirectDraw can only change the depth in fullscreen mode */
+ if (!(pScreenInfo->fFullScreen &&
+ (pScreenInfo->dwBPP != WIN_DEFAULT_BPP)))
+ {
+ /* Otherwise, We'll use GDI's depth */
+ pScreenInfo->dwBPP = dwBPP;
+ }
+
+ /* Release our DC */
+ ReleaseDC (NULL, hdc);
+ return TRUE;
+}
+
+
+/*
+ * Blt exposed regions to the screen
+ */
+
+static Bool
+winBltExposedRegionsShadowDD (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ RECT rcSrc, rcDest;
+ POINT ptOrigin;
+ HDC hdcUpdate = NULL;
+ PAINTSTRUCT ps;
+ HRESULT ddrval = DD_OK;
+ Bool fReturn = TRUE;
+ Bool fLocked = TRUE;
+ int i;
+
+ /* BeginPaint gives us an hdc that clips to the invalidated region */
+ hdcUpdate = BeginPaint (pScreenPriv->hwndScreen, &ps);
+ if (hdcUpdate == NULL)
+ {
+ ErrorF ("winBltExposedRegionsShadowDD - BeginPaint () returned "
+ "a NULL device context handle. Aborting blit attempt.\n");
+ return FALSE;
+ }
+
+ /* Unlock the shadow surface, so we can blit */
+ ddrval = IDirectDrawSurface2_Unlock (pScreenPriv->pddsShadow, NULL);
+ if (FAILED (ddrval))
+ {
+ fReturn = FALSE;
+ goto winBltExposedRegionsShadowDD_Exit;
+ }
+ else
+ {
+ /* Flag that we have unlocked the shadow surface */
+ fLocked = FALSE;
+ }
+
+ /* Get the origin of the window in the screen coords */
+ ptOrigin.x = pScreenInfo->dwXOffset;
+ ptOrigin.y = pScreenInfo->dwYOffset;
+
+ MapWindowPoints (pScreenPriv->hwndScreen,
+ HWND_DESKTOP,
+ (LPPOINT)&ptOrigin, 1);
+ rcDest.left = ptOrigin.x;
+ rcDest.right = ptOrigin.x + pScreenInfo->dwWidth;
+ rcDest.top = ptOrigin.y;
+ rcDest.bottom = ptOrigin.y + pScreenInfo->dwHeight;
+
+ /* Source can be enter shadow surface, as Blt should clip */
+ rcSrc.left = 0;
+ rcSrc.top = 0;
+ rcSrc.right = pScreenInfo->dwWidth;
+ rcSrc.bottom = pScreenInfo->dwHeight;
+
+ /* Try to regain the primary surface and blit again if we've lost it */
+ for (i = 0; i <= WIN_REGAIN_SURFACE_RETRIES; ++i)
+ {
+ /* Our Blt should be clipped to the invalidated region */
+ ddrval = IDirectDrawSurface2_Blt (pScreenPriv->pddsPrimary,
+ &rcDest,
+ pScreenPriv->pddsShadow,
+ &rcSrc,
+ DDBLT_WAIT,
+ NULL);
+ if (ddrval == DDERR_SURFACELOST)
+ {
+ /* Surface was lost */
+ ErrorF ("winBltExposedRegionsShadowDD - IDirectDrawSurface2_Blt "
+ "reported that the primary surface was lost, "
+ "trying to restore, retry: %d\n", i + 1);
+
+ /* Try to restore the surface, once */
+ ddrval = IDirectDrawSurface2_Restore (pScreenPriv->pddsPrimary);
+ ErrorF ("winBltExposedRegionsShadowDD - "
+ "IDirectDrawSurface2_Restore returned: ");
+ if (ddrval == DD_OK)
+ ErrorF ("DD_OK\n");
+ else if (ddrval == DDERR_WRONGMODE)
+ ErrorF ("DDERR_WRONGMODE\n");
+ else if (ddrval == DDERR_INCOMPATIBLEPRIMARY)
+ ErrorF ("DDERR_INCOMPATIBLEPRIMARY\n");
+ else if (ddrval == DDERR_UNSUPPORTED)
+ ErrorF ("DDERR_UNSUPPORTED\n");
+ else if (ddrval == DDERR_INVALIDPARAMS)
+ ErrorF ("DDERR_INVALIDPARAMS\n");
+ else if (ddrval == DDERR_INVALIDOBJECT)
+ ErrorF ("DDERR_INVALIDOBJECT\n");
+ else
+ ErrorF ("unknown error: %08x\n", (unsigned int) ddrval);
+
+ /* Loop around to try the blit one more time */
+ continue;
+ }
+ else if (FAILED (ddrval))
+ {
+ fReturn = FALSE;
+ ErrorF ("winBltExposedRegionsShadowDD - IDirectDrawSurface2_Blt "
+ "failed, but surface not lost: %08x %d\n",
+ (unsigned int) ddrval, (int) ddrval);
+ goto winBltExposedRegionsShadowDD_Exit;
+ }
+ else
+ {
+ /* Success, stop looping */
+ break;
+ }
+ }
+
+ /* Relock the shadow surface */
+ ddrval = IDirectDrawSurface2_Lock (pScreenPriv->pddsShadow,
+ NULL,
+ pScreenPriv->pddsdShadow,
+ DDLOCK_WAIT,
+ NULL);
+ if (FAILED (ddrval))
+ {
+ fReturn = FALSE;
+ ErrorF ("winBltExposedRegionsShadowDD - IDirectDrawSurface2_Lock "
+ "failed\n");
+ goto winBltExposedRegionsShadowDD_Exit;
+ }
+ else
+ {
+ /* Indicate that we have relocked the shadow surface */
+ fLocked = TRUE;
+ }
+
+ /* Has our memory pointer changed? */
+ if (pScreenInfo->pfb != pScreenPriv->pddsdShadow->lpSurface)
+ winUpdateFBPointer (pScreen,
+ pScreenPriv->pddsdShadow->lpSurface);
+
+ winBltExposedRegionsShadowDD_Exit:
+ /* EndPaint frees the DC */
+ if (hdcUpdate != NULL)
+ EndPaint (pScreenPriv->hwndScreen, &ps);
+
+ /*
+ * Relock the surface if it is not locked. We don't care if locking fails,
+ * as it will cause the server to shutdown within a few more operations.
+ */
+ if (!fLocked)
+ {
+ IDirectDrawSurface2_Lock (pScreenPriv->pddsShadow,
+ NULL,
+ pScreenPriv->pddsdShadow,
+ DDLOCK_WAIT,
+ NULL);
+
+ /* Has our memory pointer changed? */
+ if (pScreenInfo->pfb != pScreenPriv->pddsdShadow->lpSurface)
+ winUpdateFBPointer (pScreen,
+ pScreenPriv->pddsdShadow->lpSurface);
+
+ fLocked = TRUE;
+ }
+ return fReturn;
+}
+
+
+/*
+ * Do any engine-specific appliation-activation processing
+ */
+
+static Bool
+winActivateAppShadowDD (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+
+ /*
+ * Do we have a surface?
+ * Are we active?
+ * Are we fullscreen?
+ */
+ if (pScreenPriv != NULL
+ && pScreenPriv->pddsPrimary != NULL
+ && pScreenPriv->fActive)
+ {
+ /* Primary surface was lost, restore it */
+ IDirectDrawSurface2_Restore (pScreenPriv->pddsPrimary);
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * Reblit the shadow framebuffer to the screen.
+ */
+
+static Bool
+winRedrawScreenShadowDD (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ HRESULT ddrval = DD_OK;
+ RECT rcSrc, rcDest;
+ POINT ptOrigin;
+
+ /* Get the origin of the window in the screen coords */
+ ptOrigin.x = pScreenInfo->dwXOffset;
+ ptOrigin.y = pScreenInfo->dwYOffset;
+ MapWindowPoints (pScreenPriv->hwndScreen,
+ HWND_DESKTOP,
+ (LPPOINT)&ptOrigin, 1);
+ rcDest.left = ptOrigin.x;
+ rcDest.right = ptOrigin.x + pScreenInfo->dwWidth;
+ rcDest.top = ptOrigin.y;
+ rcDest.bottom = ptOrigin.y + pScreenInfo->dwHeight;
+
+ /* Source can be entire shadow surface, as Blt should clip for us */
+ rcSrc.left = 0;
+ rcSrc.top = 0;
+ rcSrc.right = pScreenInfo->dwWidth;
+ rcSrc.bottom = pScreenInfo->dwHeight;
+
+ /* Redraw the whole window, to take account for the new colors */
+ ddrval = IDirectDrawSurface2_Blt (pScreenPriv->pddsPrimary,
+ &rcDest,
+ pScreenPriv->pddsShadow,
+ &rcSrc,
+ DDBLT_WAIT,
+ NULL);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winRedrawScreenShadowDD - IDirectDrawSurface_Blt () "
+ "failed: %08x\n",
+ (unsigned int) ddrval);
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * Realize the currently installed colormap
+ */
+
+static Bool
+winRealizeInstalledPaletteShadowDD (ScreenPtr pScreen)
+{
+ return TRUE;
+}
+
+
+/*
+ * Install the specified colormap
+ */
+
+static Bool
+winInstallColormapShadowDD (ColormapPtr pColormap)
+{
+ ScreenPtr pScreen = pColormap->pScreen;
+ winScreenPriv(pScreen);
+ winCmapPriv(pColormap);
+ HRESULT ddrval = DD_OK;
+
+ /* Install the DirectDraw palette on the primary surface */
+ ddrval = IDirectDrawSurface2_SetPalette (pScreenPriv->pddsPrimary,
+ pCmapPriv->lpDDPalette);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winInstallColormapShadowDD - Failed installing the "
+ "DirectDraw palette.\n");
+ return FALSE;
+ }
+
+ /* Save a pointer to the newly installed colormap */
+ pScreenPriv->pcmapInstalled = pColormap;
+
+ return TRUE;
+}
+
+
+/*
+ * Store the specified colors in the specified colormap
+ */
+
+static Bool
+winStoreColorsShadowDD (ColormapPtr pColormap,
+ int ndef,
+ xColorItem *pdefs)
+{
+ ScreenPtr pScreen = pColormap->pScreen;
+ winScreenPriv(pScreen);
+ winCmapPriv(pColormap);
+ ColormapPtr curpmap = pScreenPriv->pcmapInstalled;
+ HRESULT ddrval = DD_OK;
+
+ /* Put the X colormap entries into the Windows logical palette */
+ ddrval = IDirectDrawPalette_SetEntries (pCmapPriv->lpDDPalette,
+ 0,
+ pdefs[0].pixel,
+ ndef,
+ pCmapPriv->peColors
+ + pdefs[0].pixel);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winStoreColorsShadowDD - SetEntries () failed\n");
+ return FALSE;
+ }
+
+ /* Don't install the DirectDraw palette if the colormap is not installed */
+ if (pColormap != curpmap)
+ {
+ return TRUE;
+ }
+
+ if (!winInstallColormapShadowDD (pColormap))
+ {
+ ErrorF ("winStoreColorsShadowDD - Failed installing colormap\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * Colormap initialization procedure
+ */
+
+static Bool
+winCreateColormapShadowDD (ColormapPtr pColormap)
+{
+ HRESULT ddrval = DD_OK;
+ ScreenPtr pScreen = pColormap->pScreen;
+ winScreenPriv(pScreen);
+ winCmapPriv(pColormap);
+
+ /* Create a DirectDraw palette */
+ ddrval = IDirectDraw2_CreatePalette (pScreenPriv->pdd,
+ DDPCAPS_8BIT | DDPCAPS_ALLOW256,
+ pCmapPriv->peColors,
+ &pCmapPriv->lpDDPalette,
+ NULL);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winCreateColormapShadowDD - CreatePalette failed\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * Colormap destruction procedure
+ */
+
+static Bool
+winDestroyColormapShadowDD (ColormapPtr pColormap)
+{
+ winScreenPriv(pColormap->pScreen);
+ winCmapPriv(pColormap);
+ HRESULT ddrval = DD_OK;
+
+ /*
+ * Is colormap to be destroyed the default?
+ *
+ * Non-default colormaps should have had winUninstallColormap
+ * called on them before we get here. The default colormap
+ * will not have had winUninstallColormap called on it. Thus,
+ * we need to handle the default colormap in a special way.
+ */
+ if (pColormap->flags & IsDefault)
+ {
+ winDebug ("winDestroyColormapShadowDD - Destroying default "
+ "colormap\n");
+
+ /*
+ * FIXME: Walk the list of all screens, popping the default
+ * palette out of each screen device context.
+ */
+
+ /* Pop the palette out of the primary surface */
+ ddrval = IDirectDrawSurface2_SetPalette (pScreenPriv->pddsPrimary,
+ NULL);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winDestroyColormapShadowDD - Failed freeing the "
+ "default colormap DirectDraw palette.\n");
+ return FALSE;
+ }
+
+ /* Clear our private installed colormap pointer */
+ pScreenPriv->pcmapInstalled = NULL;
+ }
+
+ /* Release the palette */
+ IDirectDrawPalette_Release (pCmapPriv->lpDDPalette);
+
+ /* Invalidate the colormap privates */
+ pCmapPriv->lpDDPalette = NULL;
+
+ return TRUE;
+}
+
+
+/*
+ * Set engine specific functions
+ */
+
+Bool
+winSetEngineFunctionsShadowDD (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+
+ /* Set our pointers */
+ pScreenPriv->pwinAllocateFB = winAllocateFBShadowDD;
+ pScreenPriv->pwinFreeFB = winFreeFBShadowDD;
+ pScreenPriv->pwinShadowUpdate = winShadowUpdateDD;
+ pScreenPriv->pwinInitScreen = winInitScreenShadowDD;
+ pScreenPriv->pwinCloseScreen = winCloseScreenShadowDD;
+ pScreenPriv->pwinInitVisuals = winInitVisualsShadowDD;
+ pScreenPriv->pwinAdjustVideoMode = winAdjustVideoModeShadowDD;
+ if (pScreenInfo->fFullScreen)
+ pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowFullScreen;
+ else
+ pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowWindowed;
+ pScreenPriv->pwinFinishScreenInit = winFinishScreenInitFB;
+ pScreenPriv->pwinBltExposedRegions = winBltExposedRegionsShadowDD;
+ pScreenPriv->pwinActivateApp = winActivateAppShadowDD;
+ pScreenPriv->pwinRedrawScreen = winRedrawScreenShadowDD;
+ pScreenPriv->pwinRealizeInstalledPalette
+ = winRealizeInstalledPaletteShadowDD;
+ pScreenPriv->pwinInstallColormap = winInstallColormapShadowDD;
+ pScreenPriv->pwinStoreColors = winStoreColorsShadowDD;
+ pScreenPriv->pwinCreateColormap = winCreateColormapShadowDD;
+ pScreenPriv->pwinDestroyColormap = winDestroyColormapShadowDD;
+ pScreenPriv->pwinHotKeyAltTab = (winHotKeyAltTabProcPtr) (void (*)(void))NoopDDA;
+ pScreenPriv->pwinCreatePrimarySurface = winCreatePrimarySurfaceShadowDD;
+ pScreenPriv->pwinReleasePrimarySurface = winReleasePrimarySurfaceShadowDD;
+#ifdef XWIN_MULTIWINDOW
+ pScreenPriv->pwinFinishCreateWindowsWindow =
+ (winFinishCreateWindowsWindowProcPtr) (void (*)(void))NoopDDA;
+#endif
+
+ return TRUE;
+}
diff --git a/xorg-server/hw/xwin/winshadddnl.c b/xorg-server/hw/xwin/winshadddnl.c index 4a573470d..da3c56160 100644 --- a/xorg-server/hw/xwin/winshadddnl.c +++ b/xorg-server/hw/xwin/winshadddnl.c @@ -1,1359 +1,1360 @@ -/* - *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 "win.h" - - -/* - * FIXME: Headers are broken, DEFINE_GUID doesn't work correctly, - * so we have to redefine it here. - */ -#ifndef _MSC_VER -#ifdef DEFINE_GUID -#undef DEFINE_GUID -#define DEFINE_GUID(n,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) const GUID n GUID_SECT = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}} -#endif /* DEFINE_GUID */ -#endif - -/* - * FIXME: Headers are broken, IID_IDirectDraw4 has to be defined - * here manually. Should be handled by ddraw.h - */ -#ifndef IID_IDirectDraw4 -DEFINE_GUID( IID_IDirectDraw4, 0x9c59509a,0x39bd,0x11d1,0x8c,0x4a,0x00,0xc0,0x4f,0xd9,0x30,0xc5 ); -#endif /* IID_IDirectDraw4 */ - -#define FAIL_MSG_MAX_BLT 10 - - -/* - * Local prototypes - */ - -static Bool -winAllocateFBShadowDDNL (ScreenPtr pScreen); - -static void -winShadowUpdateDDNL (ScreenPtr pScreen, - shadowBufPtr pBuf); - -static Bool -winCloseScreenShadowDDNL (int nIndex, ScreenPtr pScreen); - -static Bool -winInitVisualsShadowDDNL (ScreenPtr pScreen); - -static Bool -winAdjustVideoModeShadowDDNL (ScreenPtr pScreen); - -static Bool -winBltExposedRegionsShadowDDNL (ScreenPtr pScreen); - -static Bool -winActivateAppShadowDDNL (ScreenPtr pScreen); - -static Bool -winRedrawScreenShadowDDNL (ScreenPtr pScreen); - -static Bool -winRealizeInstalledPaletteShadowDDNL (ScreenPtr pScreen); - -static Bool -winInstallColormapShadowDDNL (ColormapPtr pColormap); - -static Bool -winStoreColorsShadowDDNL (ColormapPtr pmap, - int ndef, - xColorItem *pdefs); - -static Bool -winCreateColormapShadowDDNL (ColormapPtr pColormap); - -static Bool -winDestroyColormapShadowDDNL (ColormapPtr pColormap); - -static Bool -winCreatePrimarySurfaceShadowDDNL (ScreenPtr pScreen); - -static Bool -winReleasePrimarySurfaceShadowDDNL (ScreenPtr pScreen); - -static HRESULT myIDirectDrawSurface4_Blt( ScreenPtr pScreen, RECT *pRect, RECT *prcSrc) -{ - HRESULT ddrval = DD_OK; - unsigned i; - winScreenPriv(pScreen); - - for (i = 0; i < 3; ++i) - { - ddrval = IDirectDrawSurface4_Blt(pScreenPriv->pddsPrimary4, pRect, pScreenPriv->pddsShadow4, prcSrc, DDBLT_WAIT, NULL); - /* Try to regain the primary surface and blit again if we've lost it */ - if (ddrval == DDERR_SURFACELOST) - { - /* Surface was lost */ - ErrorF ("IDirectDrawSurface4_Blt reported that the primary " - "surface was lost, trying to restore, retry: %d\n", i + 1); - - /* Try to restore the surface, once */ - - if (i==1) - { - ErrorF("Recreating DDraw surface because restoring of surface didn't work.\n"); - winAllocateFBShadowDDNL(pScreen); - } - else - { - ddrval = IDirectDraw4_RestoreAllSurfaces (pScreenPriv->pdd4); - ErrorF ("IDirectDraw4_RestoreAllSurfaces returned: "); - if (ddrval == DD_OK) - ErrorF ("DD_OK\n"); - else if (ddrval == DDERR_WRONGMODE) - ErrorF ("DDERR_WRONGMODE\n"); - else if (ddrval == DDERR_INCOMPATIBLEPRIMARY) - ErrorF ("DDERR_INCOMPATIBLEPRIMARY\n"); - else if (ddrval == DDERR_UNSUPPORTED) - ErrorF ("DDERR_UNSUPPORTED\n"); - else if (ddrval == DDERR_INVALIDPARAMS) - ErrorF ("DDERR_INVALIDPARAMS\n"); - else if (ddrval == DDERR_INVALIDOBJECT) - ErrorF ("DDERR_INVALIDOBJECT\n"); - else - ErrorF ("unknown error: %08x\n", ddrval); - } - /* Loop around to try the blit one more time */ - continue; - } - else if (FAILED (ddrval)) - { - ErrorF ("IDirectDrawSurface4_Blt failed, but surface not " - "lost: %08x %d\n", ddrval, ddrval); - } - break; - } - return ddrval; -} - - -/* - * Create the primary surface and attach the clipper. - * Used for both the initial surface creation and during - * WM_DISPLAYCHANGE messages. - */ - -static Bool -winCreatePrimarySurfaceShadowDDNL (ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - HRESULT ddrval = DD_OK; - DDSURFACEDESC2 ddsd; - - winDebug ("winCreatePrimarySurfaceShadowDDNL - Creating primary surface\n"); - - /* Describe the primary surface */ - ZeroMemory (&ddsd, sizeof (ddsd)); - ddsd.dwSize = sizeof (ddsd); - ddsd.dwFlags = DDSD_CAPS; - ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; - - /* Create the primary surface */ - ddrval = IDirectDraw4_CreateSurface (pScreenPriv->pdd4, - &ddsd, - &pScreenPriv->pddsPrimary4, - NULL); - pScreenPriv->fRetryCreateSurface = FALSE; - if (FAILED (ddrval)) - { - if (ddrval == DDERR_NOEXCLUSIVEMODE) - { - /* Recreating the surface failed. Mark screen to retry later */ - pScreenPriv->fRetryCreateSurface = TRUE; - winDebug ("winCreatePrimarySurfaceShadowDDNL - Could not create " - "primary surface: DDERR_NOEXCLUSIVEMODE\n"); - } - else - { - ErrorF ("winCreatePrimarySurfaceShadowDDNL - Could not create " - "primary surface: %08x\n", (unsigned int) ddrval); - } - return FALSE; - } - - winDebug ("winCreatePrimarySurfaceShadowDDNL - Created primary surface\n"); - - /* Attach our clipper to our primary surface handle */ - ddrval = IDirectDrawSurface4_SetClipper (pScreenPriv->pddsPrimary4, - pScreenPriv->pddcPrimary); - if (FAILED (ddrval)) - { - ErrorF ("winCreatePrimarySurfaceShadowDDNL - Primary attach clipper " - "failed: %08x\n", - (unsigned int) ddrval); - return FALSE; - } - - winDebug ("winCreatePrimarySurfaceShadowDDNL - Attached clipper to primary " - "surface\n"); - - /* Everything was correct */ - return TRUE; -} - - -static void ClosePrimarySurfaceShadowDDNL (winPrivScreenPtr pScreenPriv) -{ - /* Release the primary surface and clipper, if they exist */ - if (pScreenPriv->pddsPrimary4) - { - /* - * Detach the clipper from the primary surface. - * NOTE: We do this explicity for clarity. The Clipper is not released. - */ - IDirectDrawSurface4_SetClipper (pScreenPriv->pddsPrimary4, NULL); - - winDebug ("winReleasePrimarySurfaceShadowDDNL - Detached clipper\n"); - - /* Release the primary surface */ - IDirectDrawSurface4_Release (pScreenPriv->pddsPrimary4); - pScreenPriv->pddsPrimary4 = NULL; - } - -} - -static void ReleaseDDNL(winPrivScreenPtr pScreenPriv) -{ - /* Release the clipper object */ - if (pScreenPriv->pddcPrimary) - { - IDirectDrawClipper_Release (pScreenPriv->pddcPrimary); - pScreenPriv->pddcPrimary = NULL; - } - - /* Free the DirectDraw4 object, if there is one */ - if (pScreenPriv->pdd4) - { - IDirectDraw4_RestoreDisplayMode (pScreenPriv->pdd4); - IDirectDraw4_Release (pScreenPriv->pdd4); - pScreenPriv->pdd4 = NULL; - } - - /* Free the DirectDraw object, if there is one */ - if (pScreenPriv->pdd) - { - IDirectDraw_Release (pScreenPriv->pdd); - pScreenPriv->pdd = NULL; - } -} - -/* - * Detach the clipper and release the primary surface. - * Called from WM_DISPLAYCHANGE. - */ - -static Bool -winReleasePrimarySurfaceShadowDDNL (ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - - winDebug ("winReleasePrimarySurfaceShadowDDNL - Hello\n"); - - ClosePrimarySurfaceShadowDDNL(pScreenPriv); - - winDebug ("winReleasePrimarySurfaceShadowDDNL - Released primary surface\n"); - - return TRUE; -} - - -/* - * Create a DirectDraw surface for the shadow framebuffer; also create - * a primary surface object so we can blit to the display. - * - * Install a DirectDraw clipper on our primary surface object - * that clips our blits to the unobscured client area of our display window. - */ - -Bool -winAllocateFBShadowDDNL (ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; - HRESULT ddrval = DD_OK; - DDSURFACEDESC2 ddsdShadow; - char *lpSurface = NULL; - DDPIXELFORMAT ddpfPrimary; - - winDebug ("winAllocateFBShadowDDNL - w %d h %d d %d\n", - pScreenInfo->dwWidth, pScreenInfo->dwHeight, pScreenInfo->dwDepth); - - /* Set the padded screen width */ - pScreenInfo->dwPaddedWidth = PixmapBytePad (pScreenInfo->dwWidth, - pScreenInfo->dwBPP); - - if ( pScreenInfo->pfb) - { - ErrorF("winAllocateFBShadowDDNL calling for the second time, reallocating\n"); - lpSurface=pScreenInfo->pfb; - - if (pScreenPriv->pddsShadow4) - { - IDirectDrawSurface4_Release (pScreenPriv->pddsShadow4); - pScreenPriv->pddsShadow4 = NULL; - } - ClosePrimarySurfaceShadowDDNL(pScreenPriv); - ReleaseDDNL(pScreenPriv); - } - else - { - /* Allocate memory for our shadow surface */ - lpSurface = malloc (pScreenInfo->dwPaddedWidth * pScreenInfo->dwHeight); - if (lpSurface == NULL) - { - ErrorF ("winAllocateFBShadowDDNL - Could not allocate bits\n"); - return FALSE; - } - - /* - * Initialize the framebuffer memory so we don't get a - * strange display at startup - */ - ZeroMemory (lpSurface, pScreenInfo->dwPaddedWidth * pScreenInfo->dwHeight); - } - /* Create a clipper */ - ddrval = (*g_fpDirectDrawCreateClipper) (0, - &pScreenPriv->pddcPrimary, - NULL); - if (FAILED (ddrval)) - { - ErrorF ("winAllocateFBShadowDDNL - Could not attach clipper: %08x\n", - (unsigned int) ddrval); - return FALSE; - } - - winDebug ("winAllocateFBShadowDDNL - Created a clipper\n"); - - /* Attach the clipper to our display window */ - ddrval = IDirectDrawClipper_SetHWnd (pScreenPriv->pddcPrimary, - 0, - pScreenPriv->hwndScreen); - if (FAILED (ddrval)) - { - ErrorF ("winAllocateFBShadowDDNL - Clipper not attached " - "to window: %08x\n", - (unsigned int) ddrval); - return FALSE; - } - - winDebug ("winAllocateFBShadowDDNL - Attached clipper to window\n"); - - /* Create a DirectDraw object, store the address at lpdd */ - ddrval = (*g_fpDirectDrawCreate) (NULL, - (LPDIRECTDRAW*) &pScreenPriv->pdd, - NULL); - if (FAILED (ddrval)) - { - ErrorF ("winAllocateFBShadowDDNL - Could not start " - "DirectDraw: %08x\n", - (unsigned int) ddrval); - return FALSE; - } - - winDebug ("winAllocateFBShadowDDNL - Created and initialized DD\n"); - - /* Get a DirectDraw4 interface pointer */ - ddrval = IDirectDraw_QueryInterface (pScreenPriv->pdd, - &IID_IDirectDraw4, - (LPVOID*) &pScreenPriv->pdd4); - if (FAILED (ddrval)) - { - ErrorF ("winAllocateFBShadowDDNL - Failed DD4 query: %08x\n", - (unsigned int) ddrval); - return FALSE; - } - - /* Are we full screen? */ - if (pScreenInfo->fFullScreen) - { - DDSURFACEDESC2 ddsdCurrent; - DWORD dwRefreshRateCurrent = 0; - HDC hdc = NULL; - - /* Set the cooperative level to full screen */ - ddrval = IDirectDraw4_SetCooperativeLevel (pScreenPriv->pdd4, - pScreenPriv->hwndScreen, - DDSCL_EXCLUSIVE - | DDSCL_FULLSCREEN); - if (FAILED (ddrval)) - { - ErrorF ("winAllocateFBShadowDDNL - Could not set " - "cooperative level: %08x\n", - (unsigned int) ddrval); - return FALSE; - } - - /* - * We only need to get the current refresh rate for comparison - * if a refresh rate has been passed on the command line. - */ - if (pScreenInfo->dwRefreshRate != 0) - { - ZeroMemory (&ddsdCurrent, sizeof (ddsdCurrent)); - ddsdCurrent.dwSize = sizeof (ddsdCurrent); - - /* Get information about current display settings */ - ddrval = IDirectDraw4_GetDisplayMode (pScreenPriv->pdd4, - &ddsdCurrent); - if (FAILED (ddrval)) - { - ErrorF ("winAllocateFBShadowDDNL - Could not get current " - "refresh rate: %08x. Continuing.\n", - (unsigned int) ddrval); - dwRefreshRateCurrent = 0; - } - else - { - /* Grab the current refresh rate */ - dwRefreshRateCurrent = ddsdCurrent.u2.dwRefreshRate; - } - } - - /* Clean up the refresh rate */ - if (dwRefreshRateCurrent == pScreenInfo->dwRefreshRate) - { - /* - * Refresh rate is non-specified or equal to current. - */ - pScreenInfo->dwRefreshRate = 0; - } - - /* Grab a device context for the screen */ - hdc = GetDC (NULL); - if (hdc == NULL) - { - ErrorF ("winAllocateFBShadowDDNL - GetDC () failed\n"); - return FALSE; - } - - /* Only change the video mode when different than current mode */ - if (!pScreenInfo->fMultipleMonitors - && (pScreenInfo->dwWidth != GetSystemMetrics (SM_CXSCREEN) - || pScreenInfo->dwHeight != GetSystemMetrics (SM_CYSCREEN) - || pScreenInfo->dwBPP != GetDeviceCaps (hdc, BITSPIXEL) - || pScreenInfo->dwRefreshRate != 0)) - { - winDebug ("winAllocateFBShadowDDNL - Changing video mode\n"); - - /* Change the video mode to the mode requested, and use the driver default refresh rate on failure */ - ddrval = IDirectDraw4_SetDisplayMode (pScreenPriv->pdd4, - pScreenInfo->dwWidth, - pScreenInfo->dwHeight, - pScreenInfo->dwBPP, - pScreenInfo->dwRefreshRate, - 0); - if (FAILED (ddrval)) - { - ErrorF ("winAllocateFBShadowDDNL - Could not set " - "full screen display mode: %08x\n", - (unsigned int) ddrval); - ErrorF ("winAllocateFBShadowDDNL - Using default driver refresh rate\n"); - ddrval = IDirectDraw4_SetDisplayMode (pScreenPriv->pdd4, - pScreenInfo->dwWidth, - pScreenInfo->dwHeight, - pScreenInfo->dwBPP, - 0, - 0); - if (FAILED(ddrval)) - { - ErrorF ("winAllocateFBShadowDDNL - Could not set default refresh rate " - "full screen display mode: %08x\n", - (unsigned int) ddrval); - return FALSE; - } - } - } - else - { - winDebug ("winAllocateFBShadowDDNL - Not changing video mode\n"); - } - - /* Release our DC */ - ReleaseDC (NULL, hdc); - hdc = NULL; - } - else - { - /* Set the cooperative level for windowed mode */ - ddrval = IDirectDraw4_SetCooperativeLevel (pScreenPriv->pdd4, - pScreenPriv->hwndScreen, - DDSCL_NORMAL); - if (FAILED (ddrval)) - { - ErrorF ("winAllocateFBShadowDDNL - Could not set " - "cooperative level: %08x\n", - (unsigned int) ddrval); - return FALSE; - } - } - - /* Create the primary surface */ - if (!winCreatePrimarySurfaceShadowDDNL (pScreen)) - { - ErrorF ("winAllocateFBShadowDDNL - winCreatePrimarySurfaceShadowDDNL " - "failed\n"); - return FALSE; - } - - /* Get primary surface's pixel format */ - ZeroMemory (&ddpfPrimary, sizeof (ddpfPrimary)); - ddpfPrimary.dwSize = sizeof (ddpfPrimary); - ddrval = IDirectDrawSurface4_GetPixelFormat (pScreenPriv->pddsPrimary4, - &ddpfPrimary); - if (FAILED (ddrval)) - { - ErrorF ("winAllocateFBShadowDDNL - Could not get primary " - "pixformat: %08x\n", - (unsigned int) ddrval); - return FALSE; - } - - winDebug ("winAllocateFBShadowDDNL - Primary masks: %08x %08x %08x " - "dwRGBBitCount: %d\n", - ddpfPrimary.u2.dwRBitMask, - ddpfPrimary.u3.dwGBitMask, - ddpfPrimary.u4.dwBBitMask, - ddpfPrimary.u1.dwRGBBitCount); - - /* Describe the shadow surface to be created */ - /* - * NOTE: Do not use a DDSCAPS_VIDEOMEMORY surface, - * as drawing, locking, and unlocking take forever - * with video memory surfaces. In addition, - * video memory is a somewhat scarce resource, - * so you shouldn't be allocating video memory when - * you have the option of using system memory instead. - */ - ZeroMemory (&ddsdShadow, sizeof (ddsdShadow)); - ddsdShadow.dwSize = sizeof (ddsdShadow); - ddsdShadow.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH - | DDSD_LPSURFACE | DDSD_PITCH | DDSD_PIXELFORMAT; - ddsdShadow.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; - ddsdShadow.dwHeight = pScreenInfo->dwHeight; - ddsdShadow.dwWidth = pScreenInfo->dwWidth; - ddsdShadow.u1.lPitch = pScreenInfo->dwPaddedWidth; - ddsdShadow.lpSurface = lpSurface; - ddsdShadow.u4.ddpfPixelFormat = ddpfPrimary; - - winDebug ("winAllocateFBShadowDDNL - lPitch: %d\n", - (int) pScreenInfo->dwPaddedWidth); - - /* Create the shadow surface */ - ddrval = IDirectDraw4_CreateSurface (pScreenPriv->pdd4, - &ddsdShadow, - &pScreenPriv->pddsShadow4, - NULL); - if (FAILED (ddrval)) - { - ErrorF ("winAllocateFBShadowDDNL - Could not create shadow " - "surface: %08x\n", (unsigned int) ddrval); - return FALSE; - } - - winDebug ("winAllocateFBShadowDDNL - Created shadow pitch: %d\n", - (int) ddsdShadow.u1.lPitch); - - /* Grab the pitch from the surface desc */ - pScreenInfo->dwStride = (ddsdShadow.u1.lPitch * 8) - / pScreenInfo->dwBPP; - - winDebug ("winAllocateFBShadowDDNL - Created shadow stride: %d\n", - (int) pScreenInfo->dwStride); - - /* Save the pointer to our surface memory */ - pScreenInfo->pfb = lpSurface; - - /* Grab the masks from the surface description */ - pScreenPriv->dwRedMask = ddsdShadow.u4.ddpfPixelFormat.u2.dwRBitMask; - pScreenPriv->dwGreenMask = ddsdShadow.u4.ddpfPixelFormat.u3.dwGBitMask; - pScreenPriv->dwBlueMask = ddsdShadow.u4.ddpfPixelFormat.u4.dwBBitMask; - - winDebug ("winAllocateFBShadowDDNL - Returning\n"); - - return TRUE; -} - -static void -winFreeFBShadowDDNL(ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; - - /* Free the shadow surface, if there is one */ - if (pScreenPriv->pddsShadow4) - { - IDirectDrawSurface4_Release (pScreenPriv->pddsShadow4); - free (pScreenInfo->pfb); - pScreenInfo->pfb = NULL; - pScreenPriv->pddsShadow4 = NULL; - } - - /* Detach the clipper from the primary surface and release the primary surface, if there is one */ - winReleasePrimarySurfaceShadowDDNL(pScreen); - - ReleaseDDNL(pScreenPriv); - - /* Invalidate the ScreenInfo's fb pointer */ - pScreenInfo->pfb = NULL; -} - -#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM) -/* - * Create a DirectDraw surface for the new multi-window window - */ - -static -Bool -winFinishCreateWindowsWindowDDNL (WindowPtr pWin) -{ - winWindowPriv(pWin); - winPrivScreenPtr pScreenPriv = pWinPriv->pScreenPriv; - HRESULT ddrval = DD_OK; - DDSURFACEDESC2 ddsd; - int iWidth, iHeight; - int iX, iY; - - winDebug ("winFinishCreateWindowsWindowDDNL!\n\n"); - - iX = pWin->drawable.x + GetSystemMetrics (SM_XVIRTUALSCREEN); - iY = pWin->drawable.y + GetSystemMetrics (SM_YVIRTUALSCREEN); - - iWidth = pWin->drawable.width; - iHeight = pWin->drawable.height; - - /* Describe the primary surface */ - ZeroMemory (&ddsd, sizeof (ddsd)); - ddsd.dwSize = sizeof (ddsd); - ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; - ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; - ddsd.dwHeight = iHeight; - ddsd.dwWidth = iWidth; - - /* Create the primary surface */ - ddrval = IDirectDraw4_CreateSurface (pScreenPriv->pdd4, - &ddsd, - &pWinPriv->pddsPrimary4, - NULL); - if (FAILED (ddrval)) - { - ErrorF ("winFinishCreateWindowsWindowDDNL - Could not create primary " - "surface: %08x\n", - (unsigned int)ddrval); - return FALSE; - } - return TRUE; -} -#endif - - -/* - * Transfer the damaged regions of the shadow framebuffer to the display. - */ - -static void -winShadowUpdateDDNL (ScreenPtr pScreen, - shadowBufPtr pBuf) -{ - winScreenPriv(pScreen); - winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; - RegionPtr damage = shadowDamage(pBuf); - RECT rcDest, rcSrc; - POINT ptOrigin; - DWORD dwBox = RegionNumRects (damage); - BoxPtr pBox = RegionRects (damage); - HRGN hrgnTemp = NULL, hrgnCombined = NULL; - - /* - * Return immediately if the app is not active - * and we are fullscreen, or if we have a bad display depth - */ - if ((!pScreenPriv->fActive && pScreenInfo->fFullScreen) - || pScreenPriv->fBadDepth) return; - - /* Return immediately if we didn't get needed surfaces */ - if (!pScreenPriv->pddsPrimary4 || !pScreenPriv->pddsShadow4) - return; - - /* Get the origin of the window in the screen coords */ - ptOrigin.x = pScreenInfo->dwXOffset; - ptOrigin.y = pScreenInfo->dwYOffset; - MapWindowPoints (pScreenPriv->hwndScreen, - HWND_DESKTOP, - (LPPOINT)&ptOrigin, 1); - - /* - * Handle small regions with multiple blits, - * handle large regions by creating a clipping region and - * doing a single blit constrained to that clipping region. - */ - if (pScreenInfo->dwClipUpdatesNBoxes == 0 - || dwBox < pScreenInfo->dwClipUpdatesNBoxes) - { - /* Loop through all boxes in the damaged region */ - while (dwBox--) - { - /* Assign damage box to source rectangle */ - rcSrc.left = pBox->x1; - rcSrc.top = pBox->y1; - rcSrc.right = pBox->x2; - rcSrc.bottom = pBox->y2; - - /* Calculate destination rectangle */ - rcDest.left = ptOrigin.x + rcSrc.left; - rcDest.top = ptOrigin.y + rcSrc.top; - rcDest.right = ptOrigin.x + rcSrc.right; - rcDest.bottom = ptOrigin.y + rcSrc.bottom; - - /* Blit the damaged areas */ - if (pScreenPriv->pddsPrimary4) - myIDirectDrawSurface4_Blt (pScreen, - &rcDest, - &rcSrc); - - /* Get a pointer to the next box */ - ++pBox; - } - } - else - { - BoxPtr pBoxExtents = RegionExtents(damage); - - /* Compute a GDI region from the damaged region */ - hrgnCombined = CreateRectRgn (pBox->x1, pBox->y1, pBox->x2, pBox->y2); - dwBox--; - pBox++; - while (dwBox--) - { - hrgnTemp = CreateRectRgn (pBox->x1, pBox->y1, pBox->x2, pBox->y2); - CombineRgn (hrgnCombined, hrgnCombined, hrgnTemp, RGN_OR); - DeleteObject (hrgnTemp); - pBox++; - } - - /* Install the GDI region as a clipping region */ - SelectClipRgn (pScreenPriv->hdcScreen, hrgnCombined); - DeleteObject (hrgnCombined); - hrgnCombined = NULL; - - winDebug ("winShadowUpdateDDNL - be x1 %d y1 %d x2 %d y2 %d\n", - pBoxExtents->x1, pBoxExtents->y1, - pBoxExtents->x2, pBoxExtents->y2); - - /* Calculating a bounding box for the source is easy */ - rcSrc.left = pBoxExtents->x1; - rcSrc.top = pBoxExtents->y1; - rcSrc.right = pBoxExtents->x2; - rcSrc.bottom = pBoxExtents->y2; - - /* Calculating a bounding box for the destination is trickier */ - rcDest.left = ptOrigin.x + rcSrc.left; - rcDest.top = ptOrigin.y + rcSrc.top; - rcDest.right = ptOrigin.x + rcSrc.right; - rcDest.bottom = ptOrigin.y + rcSrc.bottom; - - /* Our Blt should be clipped to the invalidated region */ - myIDirectDrawSurface4_Blt (pScreen, &rcDest, &rcSrc); - - /* Reset the clip region */ - SelectClipRgn (pScreenPriv->hdcScreen, NULL); - } -} - -static Bool -winInitScreenShadowDDNL(ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - - /* Get a device context for the screen */ - pScreenPriv->hdcScreen = GetDC (pScreenPriv->hwndScreen); - - return winAllocateFBShadowDDNL(pScreen); -} - -/* - * Call the wrapped CloseScreen function. - * - * Free our resources and private structures. - */ - -static Bool -winCloseScreenShadowDDNL (int nIndex, ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; - Bool fReturn; - - winDebug ("winCloseScreenShadowDDNL - Freeing screen resources\n"); - - /* Flag that the screen is closed */ - pScreenPriv->fClosed = TRUE; - pScreenPriv->fActive = FALSE; - - /* Call the wrapped CloseScreen procedure */ - WIN_UNWRAP(CloseScreen); - fReturn = (*pScreen->CloseScreen) (nIndex, pScreen); - - winFreeFBShadowDDNL(pScreen); - - /* Free the screen DC */ - ReleaseDC (pScreenPriv->hwndScreen, pScreenPriv->hdcScreen); - - /* Delete the window property */ - RemoveProp (pScreenPriv->hwndScreen, WIN_SCR_PROP); - - /* Delete tray icon, if we have one */ - if (!pScreenInfo->fNoTrayIcon) - winDeleteNotifyIcon (pScreenPriv); - - /* Free the exit confirmation dialog box, if it exists */ - if (g_hDlgExit != NULL) - { - DestroyWindow (g_hDlgExit); - g_hDlgExit = NULL; - } - - /* Kill our window */ - if (pScreenPriv->hwndScreen) - { - DestroyWindow (pScreenPriv->hwndScreen); - pScreenPriv->hwndScreen = NULL; - } - -#if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW) - /* Destroy the thread startup mutex */ - pthread_mutex_destroy (&pScreenPriv->pmServerStarted); -#endif - - /* Kill our screeninfo's pointer to the screen */ - pScreenInfo->pScreen = NULL; - - /* Free the screen privates for this screen */ - free ((pointer) pScreenPriv); - - return fReturn; -} - - -/* - * Tell mi what sort of visuals we need. - * - * Generally we only need one visual, as our screen can only - * handle one format at a time, I believe. You may want - * to verify that last sentence. - */ - -static Bool -winInitVisualsShadowDDNL (ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; - DWORD dwRedBits, dwGreenBits, dwBlueBits; - - /* Count the number of ones in each color mask */ - dwRedBits = winCountBits (pScreenPriv->dwRedMask); - dwGreenBits = winCountBits (pScreenPriv->dwGreenMask); - dwBlueBits = winCountBits (pScreenPriv->dwBlueMask); - - /* Store the maximum number of ones in a color mask as the bitsPerRGB */ - if (dwRedBits == 0 || dwGreenBits == 0 || dwBlueBits == 0) - pScreenPriv->dwBitsPerRGB = 8; - else if (dwRedBits > dwGreenBits && dwRedBits > dwBlueBits) - pScreenPriv->dwBitsPerRGB = dwRedBits; - else if (dwGreenBits > dwRedBits && dwGreenBits > dwBlueBits) - pScreenPriv->dwBitsPerRGB = dwGreenBits; - else - pScreenPriv->dwBitsPerRGB = dwBlueBits; - - winDebug ("winInitVisualsShadowDDNL - Masks %08x %08x %08x BPRGB %d d %d " - "bpp %d\n", - (unsigned int) pScreenPriv->dwRedMask, - (unsigned int) pScreenPriv->dwGreenMask, - (unsigned int) pScreenPriv->dwBlueMask, - (int) pScreenPriv->dwBitsPerRGB, - (int) pScreenInfo->dwDepth, - (int) pScreenInfo->dwBPP); - - /* Create a single visual according to the Windows screen depth */ - switch (pScreenInfo->dwDepth) - { - case 24: - case 16: - case 15: - /* Setup the real visual */ - if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth, - TrueColorMask, - pScreenPriv->dwBitsPerRGB, - -1, - pScreenPriv->dwRedMask, - pScreenPriv->dwGreenMask, - pScreenPriv->dwBlueMask)) - { - ErrorF ("winInitVisualsShadowDDNL - miSetVisualTypesAndMasks " - "failed for TrueColor\n"); - return FALSE; - } - -#ifdef XWIN_EMULATEPSEUDO - if (!pScreenInfo->fEmulatePseudo) - break; - - /* Setup a pseudocolor visual */ - if (!miSetVisualTypesAndMasks (8, - PseudoColorMask, - 8, - -1, - 0, - 0, - 0)) - { - ErrorF ("winInitVisualsShadowDDNL - miSetVisualTypesAndMasks " - "failed for PseudoColor\n"); - return FALSE; - } -#endif - break; - - case 8: - if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth, - pScreenInfo->fFullScreen - ? PseudoColorMask : StaticColorMask, - pScreenPriv->dwBitsPerRGB, - pScreenInfo->fFullScreen - ? PseudoColor : StaticColor, - pScreenPriv->dwRedMask, - pScreenPriv->dwGreenMask, - pScreenPriv->dwBlueMask)) - { - ErrorF ("winInitVisualsShadowDDNL - miSetVisualTypesAndMasks " - "failed\n"); - return FALSE; - } - break; - - default: - ErrorF ("winInitVisualsShadowDDNL - Unknown screen depth\n"); - return FALSE; - } - - winDebug ("winInitVisualsShadowDDNL - Returning\n"); - - return TRUE; -} - - -/* - * Adjust the user proposed video mode - */ - -static Bool -winAdjustVideoModeShadowDDNL (ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; - HDC hdc = NULL; - DWORD dwBPP; - - /* We're in serious trouble if we can't get a DC */ - hdc = GetDC (NULL); - if (hdc == NULL) - { - ErrorF ("winAdjustVideoModeShadowDDNL - GetDC () failed\n"); - return FALSE; - } - - /* Query GDI for current display depth */ - dwBPP = GetDeviceCaps (hdc, BITSPIXEL); - - /* DirectDraw can only change the depth in fullscreen mode */ - if (!(pScreenInfo->fFullScreen && - (pScreenInfo->dwBPP != WIN_DEFAULT_BPP))) - { - /* Otherwise, We'll use GDI's depth */ - pScreenInfo->dwBPP = dwBPP; - } - - /* Release our DC */ - ReleaseDC (NULL, hdc); - - return TRUE; -} - - -/* - * Blt exposed regions to the screen - */ - -static Bool -winBltExposedRegionsShadowDDNL (ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; - RECT rcSrc, rcDest; - POINT ptOrigin; - HDC hdcUpdate; - PAINTSTRUCT ps; - HRESULT ddrval = DD_OK; - Bool fReturn = TRUE; - int i; - - /* Quite common case. The primary surface was lost (maybe because of depth - * change). Try to create a new primary surface. Bail out if this fails */ - if (pScreenPriv->pddsPrimary4 == NULL && pScreenPriv->fRetryCreateSurface && - !winCreatePrimarySurfaceShadowDDNL(pScreen)) - { - Sleep(100); - return FALSE; - } - if (pScreenPriv->pddsPrimary4 == NULL) - return FALSE; - - /* BeginPaint gives us an hdc that clips to the invalidated region */ - hdcUpdate = BeginPaint (pScreenPriv->hwndScreen, &ps); - if (hdcUpdate == NULL) - { - fReturn = FALSE; - ErrorF ("winBltExposedRegionsShadowDDNL - BeginPaint () returned " - "a NULL device context handle. Aborting blit attempt.\n"); - goto winBltExposedRegionsShadowDDNL_Exit; - } - - /* Get the origin of the window in the screen coords */ - ptOrigin.x = pScreenInfo->dwXOffset; - ptOrigin.y = pScreenInfo->dwYOffset; - - MapWindowPoints (pScreenPriv->hwndScreen, - HWND_DESKTOP, - (LPPOINT)&ptOrigin, 1); - rcDest.left = ptOrigin.x; - rcDest.right = ptOrigin.x + pScreenInfo->dwWidth; - rcDest.top = ptOrigin.y; - rcDest.bottom = ptOrigin.y + pScreenInfo->dwHeight; - - /* Source can be entire shadow surface, as Blt should clip for us */ - rcSrc.left = 0; - rcSrc.top = 0; - rcSrc.right = pScreenInfo->dwWidth; - rcSrc.bottom = pScreenInfo->dwHeight; - - /* Our Blt should be clipped to the invalidated region */ - ddrval = myIDirectDrawSurface4_Blt (pScreen, &rcDest, &rcSrc); - if (FAILED (ddrval)) - { - fReturn = FALSE; - } - -winBltExposedRegionsShadowDDNL_Exit: - /* EndPaint frees the DC */ - if (hdcUpdate != NULL) - EndPaint (pScreenPriv->hwndScreen, &ps); - return fReturn; -} - - -/* - * Do any engine-specific application-activation processing - */ - -static Bool -winActivateAppShadowDDNL (ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - - /* - * Do we have a surface? - * Are we active? - * Are we full screen? - */ - if (pScreenPriv != NULL - && pScreenPriv->pddsPrimary4 != NULL - && pScreenPriv->fActive) - { - /* Primary surface was lost, restore it */ - IDirectDrawSurface4_Restore (pScreenPriv->pddsPrimary4); - } - - return TRUE; -} - - -/* - * Reblit the shadow framebuffer to the screen. - */ - -static Bool -winRedrawScreenShadowDDNL (ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; - RECT rcSrc, rcDest; - POINT ptOrigin; - - /* Get the origin of the window in the screen coords */ - ptOrigin.x = pScreenInfo->dwXOffset; - ptOrigin.y = pScreenInfo->dwYOffset; - MapWindowPoints (pScreenPriv->hwndScreen, - HWND_DESKTOP, - (LPPOINT)&ptOrigin, 1); - rcDest.left = ptOrigin.x; - rcDest.right = ptOrigin.x + pScreenInfo->dwWidth; - rcDest.top = ptOrigin.y; - rcDest.bottom = ptOrigin.y + pScreenInfo->dwHeight; - - /* Source can be entire shadow surface, as Blt should clip for us */ - rcSrc.left = 0; - rcSrc.top = 0; - rcSrc.right = pScreenInfo->dwWidth; - rcSrc.bottom = pScreenInfo->dwHeight; - - /* Redraw the whole window, to take account for the new colors */ - myIDirectDrawSurface4_Blt (pScreen, &rcDest, &rcSrc); - return TRUE; -} - - -/* - * Realize the currently installed colormap - */ - -static Bool -winRealizeInstalledPaletteShadowDDNL (ScreenPtr pScreen) -{ - return TRUE; -} - - -/* - * Install the specified colormap - */ - -static Bool -winInstallColormapShadowDDNL (ColormapPtr pColormap) -{ - ScreenPtr pScreen = pColormap->pScreen; - winScreenPriv(pScreen); - winCmapPriv(pColormap); - HRESULT ddrval = DD_OK; - - /* Install the DirectDraw palette on the primary surface */ - ddrval = IDirectDrawSurface4_SetPalette (pScreenPriv->pddsPrimary4, - pCmapPriv->lpDDPalette); - if (FAILED (ddrval)) - { - ErrorF ("winInstallColormapShadowDDNL - Failed installing the " - "DirectDraw palette.\n"); - return FALSE; - } - - /* Save a pointer to the newly installed colormap */ - pScreenPriv->pcmapInstalled = pColormap; - - return TRUE; -} - - -/* - * Store the specified colors in the specified colormap - */ - -static Bool -winStoreColorsShadowDDNL (ColormapPtr pColormap, - int ndef, - xColorItem *pdefs) -{ - ScreenPtr pScreen = pColormap->pScreen; - winScreenPriv(pScreen); - winCmapPriv(pColormap); - ColormapPtr curpmap = pScreenPriv->pcmapInstalled; - HRESULT ddrval = DD_OK; - - /* Put the X colormap entries into the Windows logical palette */ - ddrval = IDirectDrawPalette_SetEntries (pCmapPriv->lpDDPalette, - 0, - pdefs[0].pixel, - ndef, - pCmapPriv->peColors - + pdefs[0].pixel); - if (FAILED (ddrval)) - { - ErrorF ("winStoreColorsShadowDDNL - SetEntries () failed: %08x\n", (unsigned int) ddrval); - return FALSE; - } - - /* Don't install the DirectDraw palette if the colormap is not installed */ - if (pColormap != curpmap) - { - return TRUE; - } - - if (!winInstallColormapShadowDDNL (pColormap)) - { - ErrorF ("winStoreColorsShadowDDNL - Failed installing colormap\n"); - return FALSE; - } - - return TRUE; -} - - -/* - * Colormap initialization procedure - */ - -static Bool -winCreateColormapShadowDDNL (ColormapPtr pColormap) -{ - HRESULT ddrval = DD_OK; - ScreenPtr pScreen = pColormap->pScreen; - winScreenPriv(pScreen); - winCmapPriv(pColormap); - - /* Create a DirectDraw palette */ - ddrval = IDirectDraw4_CreatePalette (pScreenPriv->pdd4, - DDPCAPS_8BIT | DDPCAPS_ALLOW256, - pCmapPriv->peColors, - &pCmapPriv->lpDDPalette, - NULL); - if (FAILED (ddrval)) - { - ErrorF ("winCreateColormapShadowDDNL - CreatePalette failed\n"); - return FALSE; - } - - return TRUE; -} - - -/* - * Colormap destruction procedure - */ - -static Bool -winDestroyColormapShadowDDNL (ColormapPtr pColormap) -{ - winScreenPriv(pColormap->pScreen); - winCmapPriv(pColormap); - HRESULT ddrval = DD_OK; - - /* - * Is colormap to be destroyed the default? - * - * Non-default colormaps should have had winUninstallColormap - * called on them before we get here. The default colormap - * will not have had winUninstallColormap called on it. Thus, - * we need to handle the default colormap in a special way. - */ - if (pColormap->flags & IsDefault) - { - winDebug ("winDestroyColormapShadowDDNL - Destroying default colormap\n"); - - /* - * FIXME: Walk the list of all screens, popping the default - * palette out of each screen device context. - */ - - /* Pop the palette out of the primary surface */ - ddrval = IDirectDrawSurface4_SetPalette (pScreenPriv->pddsPrimary4, - NULL); - if (FAILED (ddrval)) - { - ErrorF ("winDestroyColormapShadowDDNL - Failed freeing the " - "default colormap DirectDraw palette.\n"); - return FALSE; - } - - /* Clear our private installed colormap pointer */ - pScreenPriv->pcmapInstalled = NULL; - } - - /* Release the palette */ - IDirectDrawPalette_Release (pCmapPriv->lpDDPalette); - - /* Invalidate the colormap privates */ - pCmapPriv->lpDDPalette = NULL; - - return TRUE; -} - - -/* - * Set pointers to our engine specific functions - */ - -Bool -winSetEngineFunctionsShadowDDNL (ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; - - /* Set our pointers */ - pScreenPriv->pwinAllocateFB = winAllocateFBShadowDDNL; - pScreenPriv->pwinFreeFB = winFreeFBShadowDDNL; - pScreenPriv->pwinShadowUpdate = winShadowUpdateDDNL; - pScreenPriv->pwinInitScreen = winInitScreenShadowDDNL; - pScreenPriv->pwinCloseScreen = winCloseScreenShadowDDNL; - pScreenPriv->pwinInitVisuals = winInitVisualsShadowDDNL; - pScreenPriv->pwinAdjustVideoMode = winAdjustVideoModeShadowDDNL; - if (pScreenInfo->fFullScreen) - pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowFullScreen; - else - pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowWindowed; - pScreenPriv->pwinFinishScreenInit = winFinishScreenInitFB; - pScreenPriv->pwinBltExposedRegions = winBltExposedRegionsShadowDDNL; - pScreenPriv->pwinActivateApp = winActivateAppShadowDDNL; - pScreenPriv->pwinRedrawScreen = winRedrawScreenShadowDDNL; - pScreenPriv->pwinRealizeInstalledPalette - = winRealizeInstalledPaletteShadowDDNL; - pScreenPriv->pwinInstallColormap = winInstallColormapShadowDDNL; - pScreenPriv->pwinStoreColors = winStoreColorsShadowDDNL; - pScreenPriv->pwinCreateColormap = winCreateColormapShadowDDNL; - pScreenPriv->pwinDestroyColormap = winDestroyColormapShadowDDNL; - pScreenPriv->pwinHotKeyAltTab = (winHotKeyAltTabProcPtr) (void (*)(void))NoopDDA; - pScreenPriv->pwinCreatePrimarySurface = winCreatePrimarySurfaceShadowDDNL; - pScreenPriv->pwinReleasePrimarySurface = winReleasePrimarySurfaceShadowDDNL; -#ifdef XWIN_MULTIWINDOW - pScreenPriv->pwinFinishCreateWindowsWindow - = winFinishCreateWindowsWindowDDNL; -#endif - - return TRUE; -} +/*
+ *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 "win.h"
+
+
+/*
+ * FIXME: Headers are broken, DEFINE_GUID doesn't work correctly,
+ * so we have to redefine it here.
+ */
+#ifndef _MSC_VER
+#ifdef DEFINE_GUID
+#undef DEFINE_GUID
+#define DEFINE_GUID(n,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) const GUID n GUID_SECT = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}
+#endif /* DEFINE_GUID */
+#endif
+
+/*
+ * FIXME: Headers are broken, IID_IDirectDraw4 has to be defined
+ * here manually. Should be handled by ddraw.h
+ */
+#ifndef IID_IDirectDraw4
+DEFINE_GUID( IID_IDirectDraw4, 0x9c59509a,0x39bd,0x11d1,0x8c,0x4a,0x00,0xc0,0x4f,0xd9,0x30,0xc5 );
+#endif /* IID_IDirectDraw4 */
+
+#define FAIL_MSG_MAX_BLT 10
+
+
+/*
+ * Local prototypes
+ */
+
+static Bool
+winAllocateFBShadowDDNL (ScreenPtr pScreen);
+
+static void
+winShadowUpdateDDNL (ScreenPtr pScreen,
+ shadowBufPtr pBuf);
+
+static Bool
+winCloseScreenShadowDDNL (int nIndex, ScreenPtr pScreen);
+
+static Bool
+winInitVisualsShadowDDNL (ScreenPtr pScreen);
+
+static Bool
+winAdjustVideoModeShadowDDNL (ScreenPtr pScreen);
+
+static Bool
+winBltExposedRegionsShadowDDNL (ScreenPtr pScreen);
+
+static Bool
+winActivateAppShadowDDNL (ScreenPtr pScreen);
+
+static Bool
+winRedrawScreenShadowDDNL (ScreenPtr pScreen);
+
+static Bool
+winRealizeInstalledPaletteShadowDDNL (ScreenPtr pScreen);
+
+static Bool
+winInstallColormapShadowDDNL (ColormapPtr pColormap);
+
+static Bool
+winStoreColorsShadowDDNL (ColormapPtr pmap,
+ int ndef,
+ xColorItem *pdefs);
+
+static Bool
+winCreateColormapShadowDDNL (ColormapPtr pColormap);
+
+static Bool
+winDestroyColormapShadowDDNL (ColormapPtr pColormap);
+
+static Bool
+winCreatePrimarySurfaceShadowDDNL (ScreenPtr pScreen);
+
+static Bool
+winReleasePrimarySurfaceShadowDDNL (ScreenPtr pScreen);
+
+static HRESULT myIDirectDrawSurface4_Blt( ScreenPtr pScreen, RECT *pRect, RECT *prcSrc)
+{
+ HRESULT ddrval = DD_OK;
+ unsigned i;
+ winScreenPriv(pScreen);
+
+ for (i = 0; i < 3; ++i)
+ {
+ ddrval = IDirectDrawSurface4_Blt(pScreenPriv->pddsPrimary4, pRect, pScreenPriv->pddsShadow4, prcSrc, DDBLT_WAIT, NULL);
+ /* Try to regain the primary surface and blit again if we've lost it */
+ if (ddrval == DDERR_SURFACELOST)
+ {
+ /* Surface was lost */
+ ErrorF ("IDirectDrawSurface4_Blt reported that the primary "
+ "surface was lost, trying to restore, retry: %d\n", i + 1);
+
+ /* Try to restore the surface, once */
+
+ if (i==1)
+ {
+ ErrorF("Recreating DDraw surface because restoring of surface didn't work.\n");
+ winAllocateFBShadowDDNL(pScreen);
+ }
+ else
+ {
+ ddrval = IDirectDraw4_RestoreAllSurfaces (pScreenPriv->pdd4);
+ ErrorF ("IDirectDraw4_RestoreAllSurfaces returned: ");
+ if (ddrval == DD_OK)
+ ErrorF ("DD_OK\n");
+ else if (ddrval == DDERR_WRONGMODE)
+ ErrorF ("DDERR_WRONGMODE\n");
+ else if (ddrval == DDERR_INCOMPATIBLEPRIMARY)
+ ErrorF ("DDERR_INCOMPATIBLEPRIMARY\n");
+ else if (ddrval == DDERR_UNSUPPORTED)
+ ErrorF ("DDERR_UNSUPPORTED\n");
+ else if (ddrval == DDERR_INVALIDPARAMS)
+ ErrorF ("DDERR_INVALIDPARAMS\n");
+ else if (ddrval == DDERR_INVALIDOBJECT)
+ ErrorF ("DDERR_INVALIDOBJECT\n");
+ else
+ ErrorF ("unknown error: %08x\n", ddrval);
+ }
+ /* Loop around to try the blit one more time */
+ continue;
+ }
+ else if (FAILED (ddrval))
+ {
+ ErrorF ("IDirectDrawSurface4_Blt failed, but surface not "
+ "lost: %08x %d\n", ddrval, ddrval);
+ }
+ break;
+ }
+ return ddrval;
+}
+
+
+/*
+ * Create the primary surface and attach the clipper.
+ * Used for both the initial surface creation and during
+ * WM_DISPLAYCHANGE messages.
+ */
+
+static Bool
+winCreatePrimarySurfaceShadowDDNL (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ HRESULT ddrval = DD_OK;
+ DDSURFACEDESC2 ddsd;
+
+ winDebug ("winCreatePrimarySurfaceShadowDDNL - Creating primary surface\n");
+
+ /* Describe the primary surface */
+ ZeroMemory (&ddsd, sizeof (ddsd));
+ ddsd.dwSize = sizeof (ddsd);
+ ddsd.dwFlags = DDSD_CAPS;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+
+ /* Create the primary surface */
+ ddrval = IDirectDraw4_CreateSurface (pScreenPriv->pdd4,
+ &ddsd,
+ &pScreenPriv->pddsPrimary4,
+ NULL);
+ pScreenPriv->fRetryCreateSurface = FALSE;
+ if (FAILED (ddrval))
+ {
+ if (ddrval == DDERR_NOEXCLUSIVEMODE)
+ {
+ /* Recreating the surface failed. Mark screen to retry later */
+ pScreenPriv->fRetryCreateSurface = TRUE;
+ winDebug ("winCreatePrimarySurfaceShadowDDNL - Could not create "
+ "primary surface: DDERR_NOEXCLUSIVEMODE\n");
+ }
+ else
+ {
+ ErrorF ("winCreatePrimarySurfaceShadowDDNL - Could not create "
+ "primary surface: %08x\n", (unsigned int) ddrval);
+ }
+ return FALSE;
+ }
+
+ winDebug ("winCreatePrimarySurfaceShadowDDNL - Created primary surface\n");
+
+ /* Attach our clipper to our primary surface handle */
+ ddrval = IDirectDrawSurface4_SetClipper (pScreenPriv->pddsPrimary4,
+ pScreenPriv->pddcPrimary);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winCreatePrimarySurfaceShadowDDNL - Primary attach clipper "
+ "failed: %08x\n",
+ (unsigned int) ddrval);
+ return FALSE;
+ }
+
+ winDebug ("winCreatePrimarySurfaceShadowDDNL - Attached clipper to primary "
+ "surface\n");
+
+ /* Everything was correct */
+ return TRUE;
+}
+
+
+static void ClosePrimarySurfaceShadowDDNL (winPrivScreenPtr pScreenPriv)
+{
+ /* Release the primary surface and clipper, if they exist */
+ if (pScreenPriv->pddsPrimary4)
+ {
+ /*
+ * Detach the clipper from the primary surface.
+ * NOTE: We do this explicity for clarity. The Clipper is not released.
+ */
+ IDirectDrawSurface4_SetClipper (pScreenPriv->pddsPrimary4, NULL);
+
+ winDebug ("winReleasePrimarySurfaceShadowDDNL - Detached clipper\n");
+
+ /* Release the primary surface */
+ IDirectDrawSurface4_Release (pScreenPriv->pddsPrimary4);
+ pScreenPriv->pddsPrimary4 = NULL;
+ }
+
+}
+
+static void ReleaseDDNL(winPrivScreenPtr pScreenPriv)
+{
+ /* Release the clipper object */
+ if (pScreenPriv->pddcPrimary)
+ {
+ IDirectDrawClipper_Release (pScreenPriv->pddcPrimary);
+ pScreenPriv->pddcPrimary = NULL;
+ }
+
+ /* Free the DirectDraw4 object, if there is one */
+ if (pScreenPriv->pdd4)
+ {
+ IDirectDraw4_RestoreDisplayMode (pScreenPriv->pdd4);
+ IDirectDraw4_Release (pScreenPriv->pdd4);
+ pScreenPriv->pdd4 = NULL;
+ }
+
+ /* Free the DirectDraw object, if there is one */
+ if (pScreenPriv->pdd)
+ {
+ IDirectDraw_Release (pScreenPriv->pdd);
+ pScreenPriv->pdd = NULL;
+ }
+}
+
+/*
+ * Detach the clipper and release the primary surface.
+ * Called from WM_DISPLAYCHANGE.
+ */
+
+static Bool
+winReleasePrimarySurfaceShadowDDNL (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+
+ winDebug ("winReleasePrimarySurfaceShadowDDNL - Hello\n");
+
+ ClosePrimarySurfaceShadowDDNL(pScreenPriv);
+
+ winDebug ("winReleasePrimarySurfaceShadowDDNL - Released primary surface\n");
+
+ return TRUE;
+}
+
+
+/*
+ * Create a DirectDraw surface for the shadow framebuffer; also create
+ * a primary surface object so we can blit to the display.
+ *
+ * Install a DirectDraw clipper on our primary surface object
+ * that clips our blits to the unobscured client area of our display window.
+ */
+
+Bool
+winAllocateFBShadowDDNL (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ HRESULT ddrval = DD_OK;
+ DDSURFACEDESC2 ddsdShadow;
+ char *lpSurface = NULL;
+ DDPIXELFORMAT ddpfPrimary;
+
+ winDebug ("winAllocateFBShadowDDNL - w %d h %d d %d\n",
+ pScreenInfo->dwWidth, pScreenInfo->dwHeight, pScreenInfo->dwDepth);
+
+ /* Set the padded screen width */
+ pScreenInfo->dwPaddedWidth = PixmapBytePad (pScreenInfo->dwWidth,
+ pScreenInfo->dwBPP);
+
+ if ( pScreenInfo->pfb)
+ {
+ ErrorF("winAllocateFBShadowDDNL calling for the second time, reallocating\n");
+ lpSurface=pScreenInfo->pfb;
+
+ if (pScreenPriv->pddsShadow4)
+ {
+ IDirectDrawSurface4_Release (pScreenPriv->pddsShadow4);
+ pScreenPriv->pddsShadow4 = NULL;
+ }
+ ClosePrimarySurfaceShadowDDNL(pScreenPriv);
+ ReleaseDDNL(pScreenPriv);
+ }
+ else
+ {
+ /* Allocate memory for our shadow surface */
+ lpSurface = malloc (pScreenInfo->dwPaddedWidth * pScreenInfo->dwHeight);
+ if (lpSurface == NULL)
+ {
+ ErrorF ("winAllocateFBShadowDDNL - Could not allocate bits\n");
+ return FALSE;
+ }
+
+ /*
+ * Initialize the framebuffer memory so we don't get a
+ * strange display at startup
+ */
+ ZeroMemory (lpSurface, pScreenInfo->dwPaddedWidth * pScreenInfo->dwHeight);
+ }
+ /* Create a clipper */
+ ddrval = (*g_fpDirectDrawCreateClipper) (0,
+ &pScreenPriv->pddcPrimary,
+ NULL);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winAllocateFBShadowDDNL - Could not attach clipper: %08x\n",
+ (unsigned int) ddrval);
+ return FALSE;
+ }
+
+ winDebug ("winAllocateFBShadowDDNL - Created a clipper\n");
+
+ /* Attach the clipper to our display window */
+ ddrval = IDirectDrawClipper_SetHWnd (pScreenPriv->pddcPrimary,
+ 0,
+ pScreenPriv->hwndScreen);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winAllocateFBShadowDDNL - Clipper not attached "
+ "to window: %08x\n",
+ (unsigned int) ddrval);
+ return FALSE;
+ }
+
+ winDebug ("winAllocateFBShadowDDNL - Attached clipper to window\n");
+
+ /* Create a DirectDraw object, store the address at lpdd */
+ ddrval = (*g_fpDirectDrawCreate) (NULL,
+ (LPDIRECTDRAW*) &pScreenPriv->pdd,
+ NULL);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winAllocateFBShadowDDNL - Could not start "
+ "DirectDraw: %08x\n",
+ (unsigned int) ddrval);
+ return FALSE;
+ }
+
+ winDebug ("winAllocateFBShadowDDNL - Created and initialized DD\n");
+
+ /* Get a DirectDraw4 interface pointer */
+ ddrval = IDirectDraw_QueryInterface (pScreenPriv->pdd,
+ &IID_IDirectDraw4,
+ (LPVOID*) &pScreenPriv->pdd4);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winAllocateFBShadowDDNL - Failed DD4 query: %08x\n",
+ (unsigned int) ddrval);
+ return FALSE;
+ }
+
+ /* Are we full screen? */
+ if (pScreenInfo->fFullScreen)
+ {
+ DDSURFACEDESC2 ddsdCurrent;
+ DWORD dwRefreshRateCurrent = 0;
+ HDC hdc = NULL;
+
+ /* Set the cooperative level to full screen */
+ ddrval = IDirectDraw4_SetCooperativeLevel (pScreenPriv->pdd4,
+ pScreenPriv->hwndScreen,
+ DDSCL_EXCLUSIVE
+ | DDSCL_FULLSCREEN);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winAllocateFBShadowDDNL - Could not set "
+ "cooperative level: %08x\n",
+ (unsigned int) ddrval);
+ return FALSE;
+ }
+
+ /*
+ * We only need to get the current refresh rate for comparison
+ * if a refresh rate has been passed on the command line.
+ */
+ if (pScreenInfo->dwRefreshRate != 0)
+ {
+ ZeroMemory (&ddsdCurrent, sizeof (ddsdCurrent));
+ ddsdCurrent.dwSize = sizeof (ddsdCurrent);
+
+ /* Get information about current display settings */
+ ddrval = IDirectDraw4_GetDisplayMode (pScreenPriv->pdd4,
+ &ddsdCurrent);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winAllocateFBShadowDDNL - Could not get current "
+ "refresh rate: %08x. Continuing.\n",
+ (unsigned int) ddrval);
+ dwRefreshRateCurrent = 0;
+ }
+ else
+ {
+ /* Grab the current refresh rate */
+ dwRefreshRateCurrent = ddsdCurrent.u2.dwRefreshRate;
+ }
+ }
+
+ /* Clean up the refresh rate */
+ if (dwRefreshRateCurrent == pScreenInfo->dwRefreshRate)
+ {
+ /*
+ * Refresh rate is non-specified or equal to current.
+ */
+ pScreenInfo->dwRefreshRate = 0;
+ }
+
+ /* Grab a device context for the screen */
+ hdc = GetDC (NULL);
+ if (hdc == NULL)
+ {
+ ErrorF ("winAllocateFBShadowDDNL - GetDC () failed\n");
+ return FALSE;
+ }
+
+ /* Only change the video mode when different than current mode */
+ if (!pScreenInfo->fMultipleMonitors
+ && (pScreenInfo->dwWidth != GetSystemMetrics (SM_CXSCREEN)
+ || pScreenInfo->dwHeight != GetSystemMetrics (SM_CYSCREEN)
+ || pScreenInfo->dwBPP != GetDeviceCaps (hdc, BITSPIXEL)
+ || pScreenInfo->dwRefreshRate != 0))
+ {
+ winDebug ("winAllocateFBShadowDDNL - Changing video mode\n");
+
+ /* Change the video mode to the mode requested, and use the driver default refresh rate on failure */
+ ddrval = IDirectDraw4_SetDisplayMode (pScreenPriv->pdd4,
+ pScreenInfo->dwWidth,
+ pScreenInfo->dwHeight,
+ pScreenInfo->dwBPP,
+ pScreenInfo->dwRefreshRate,
+ 0);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winAllocateFBShadowDDNL - Could not set "
+ "full screen display mode: %08x\n",
+ (unsigned int) ddrval);
+ ErrorF ("winAllocateFBShadowDDNL - Using default driver refresh rate\n");
+ ddrval = IDirectDraw4_SetDisplayMode (pScreenPriv->pdd4,
+ pScreenInfo->dwWidth,
+ pScreenInfo->dwHeight,
+ pScreenInfo->dwBPP,
+ 0,
+ 0);
+ if (FAILED(ddrval))
+ {
+ ErrorF ("winAllocateFBShadowDDNL - Could not set default refresh rate "
+ "full screen display mode: %08x\n",
+ (unsigned int) ddrval);
+ return FALSE;
+ }
+ }
+ }
+ else
+ {
+ winDebug ("winAllocateFBShadowDDNL - Not changing video mode\n");
+ }
+
+ /* Release our DC */
+ ReleaseDC (NULL, hdc);
+ hdc = NULL;
+ }
+ else
+ {
+ /* Set the cooperative level for windowed mode */
+ ddrval = IDirectDraw4_SetCooperativeLevel (pScreenPriv->pdd4,
+ pScreenPriv->hwndScreen,
+ DDSCL_NORMAL);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winAllocateFBShadowDDNL - Could not set "
+ "cooperative level: %08x\n",
+ (unsigned int) ddrval);
+ return FALSE;
+ }
+ }
+
+ /* Create the primary surface */
+ if (!winCreatePrimarySurfaceShadowDDNL (pScreen))
+ {
+ ErrorF ("winAllocateFBShadowDDNL - winCreatePrimarySurfaceShadowDDNL "
+ "failed\n");
+ return FALSE;
+ }
+
+ /* Get primary surface's pixel format */
+ ZeroMemory (&ddpfPrimary, sizeof (ddpfPrimary));
+ ddpfPrimary.dwSize = sizeof (ddpfPrimary);
+ ddrval = IDirectDrawSurface4_GetPixelFormat (pScreenPriv->pddsPrimary4,
+ &ddpfPrimary);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winAllocateFBShadowDDNL - Could not get primary "
+ "pixformat: %08x\n",
+ (unsigned int) ddrval);
+ return FALSE;
+ }
+
+ winDebug ("winAllocateFBShadowDDNL - Primary masks: %08x %08x %08x "
+ "dwRGBBitCount: %d\n",
+ ddpfPrimary.u2.dwRBitMask,
+ ddpfPrimary.u3.dwGBitMask,
+ ddpfPrimary.u4.dwBBitMask,
+ ddpfPrimary.u1.dwRGBBitCount);
+
+ /* Describe the shadow surface to be created */
+ /*
+ * NOTE: Do not use a DDSCAPS_VIDEOMEMORY surface,
+ * as drawing, locking, and unlocking take forever
+ * with video memory surfaces. In addition,
+ * video memory is a somewhat scarce resource,
+ * so you shouldn't be allocating video memory when
+ * you have the option of using system memory instead.
+ */
+ ZeroMemory (&ddsdShadow, sizeof (ddsdShadow));
+ ddsdShadow.dwSize = sizeof (ddsdShadow);
+ ddsdShadow.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH
+ | DDSD_LPSURFACE | DDSD_PITCH | DDSD_PIXELFORMAT;
+ ddsdShadow.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
+ ddsdShadow.dwHeight = pScreenInfo->dwHeight;
+ ddsdShadow.dwWidth = pScreenInfo->dwWidth;
+ ddsdShadow.u1.lPitch = pScreenInfo->dwPaddedWidth;
+ ddsdShadow.lpSurface = lpSurface;
+ ddsdShadow.u4.ddpfPixelFormat = ddpfPrimary;
+
+ winDebug ("winAllocateFBShadowDDNL - lPitch: %d\n",
+ (int) pScreenInfo->dwPaddedWidth);
+
+ /* Create the shadow surface */
+ ddrval = IDirectDraw4_CreateSurface (pScreenPriv->pdd4,
+ &ddsdShadow,
+ &pScreenPriv->pddsShadow4,
+ NULL);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winAllocateFBShadowDDNL - Could not create shadow "
+ "surface: %08x\n", (unsigned int) ddrval);
+ return FALSE;
+ }
+
+ winDebug ("winAllocateFBShadowDDNL - Created shadow pitch: %d\n",
+ (int) ddsdShadow.u1.lPitch);
+
+ /* Grab the pitch from the surface desc */
+ pScreenInfo->dwStride = (ddsdShadow.u1.lPitch * 8)
+ / pScreenInfo->dwBPP;
+
+ winDebug ("winAllocateFBShadowDDNL - Created shadow stride: %d\n",
+ (int) pScreenInfo->dwStride);
+
+ /* Save the pointer to our surface memory */
+ pScreenInfo->pfb = lpSurface;
+
+ /* Grab the masks from the surface description */
+ pScreenPriv->dwRedMask = ddsdShadow.u4.ddpfPixelFormat.u2.dwRBitMask;
+ pScreenPriv->dwGreenMask = ddsdShadow.u4.ddpfPixelFormat.u3.dwGBitMask;
+ pScreenPriv->dwBlueMask = ddsdShadow.u4.ddpfPixelFormat.u4.dwBBitMask;
+
+ winDebug ("winAllocateFBShadowDDNL - Returning\n");
+
+ return TRUE;
+}
+
+static void
+winFreeFBShadowDDNL(ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+
+ /* Free the shadow surface, if there is one */
+ if (pScreenPriv->pddsShadow4)
+ {
+ IDirectDrawSurface4_Release (pScreenPriv->pddsShadow4);
+ free (pScreenInfo->pfb);
+ pScreenInfo->pfb = NULL;
+ pScreenPriv->pddsShadow4 = NULL;
+ }
+
+ /* Detach the clipper from the primary surface and release the primary surface, if there is one */
+ winReleasePrimarySurfaceShadowDDNL(pScreen);
+
+ ReleaseDDNL(pScreenPriv);
+
+ /* Invalidate the ScreenInfo's fb pointer */
+ pScreenInfo->pfb = NULL;
+}
+
+#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM)
+/*
+ * Create a DirectDraw surface for the new multi-window window
+ */
+
+static
+Bool
+winFinishCreateWindowsWindowDDNL (WindowPtr pWin)
+{
+ winWindowPriv(pWin);
+ winPrivScreenPtr pScreenPriv = pWinPriv->pScreenPriv;
+ HRESULT ddrval = DD_OK;
+ DDSURFACEDESC2 ddsd;
+ int iWidth, iHeight;
+ int iX, iY;
+
+ winDebug ("winFinishCreateWindowsWindowDDNL!\n\n");
+
+ iX = pWin->drawable.x + GetSystemMetrics (SM_XVIRTUALSCREEN);
+ iY = pWin->drawable.y + GetSystemMetrics (SM_YVIRTUALSCREEN);
+
+ iWidth = pWin->drawable.width;
+ iHeight = pWin->drawable.height;
+
+ /* Describe the primary surface */
+ ZeroMemory (&ddsd, sizeof (ddsd));
+ ddsd.dwSize = sizeof (ddsd);
+ ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+ ddsd.dwHeight = iHeight;
+ ddsd.dwWidth = iWidth;
+
+ /* Create the primary surface */
+ ddrval = IDirectDraw4_CreateSurface (pScreenPriv->pdd4,
+ &ddsd,
+ &pWinPriv->pddsPrimary4,
+ NULL);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winFinishCreateWindowsWindowDDNL - Could not create primary "
+ "surface: %08x\n",
+ (unsigned int)ddrval);
+ return FALSE;
+ }
+ return TRUE;
+}
+#endif
+
+
+/*
+ * Transfer the damaged regions of the shadow framebuffer to the display.
+ */
+
+static void
+winShadowUpdateDDNL (ScreenPtr pScreen,
+ shadowBufPtr pBuf)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ RegionPtr damage = shadowDamage(pBuf);
+ RECT rcDest, rcSrc;
+ POINT ptOrigin;
+ DWORD dwBox = RegionNumRects (damage);
+ BoxPtr pBox = RegionRects (damage);
+ HRGN hrgnTemp = NULL, hrgnCombined = NULL;
+
+ /*
+ * Return immediately if the app is not active
+ * and we are fullscreen, or if we have a bad display depth
+ */
+ if ((!pScreenPriv->fActive && pScreenInfo->fFullScreen)
+ || pScreenPriv->fBadDepth) return;
+
+ /* Return immediately if we didn't get needed surfaces */
+ if (!pScreenPriv->pddsPrimary4 || !pScreenPriv->pddsShadow4)
+ return;
+
+ /* Get the origin of the window in the screen coords */
+ ptOrigin.x = pScreenInfo->dwXOffset;
+ ptOrigin.y = pScreenInfo->dwYOffset;
+ MapWindowPoints (pScreenPriv->hwndScreen,
+ HWND_DESKTOP,
+ (LPPOINT)&ptOrigin, 1);
+
+ /*
+ * Handle small regions with multiple blits,
+ * handle large regions by creating a clipping region and
+ * doing a single blit constrained to that clipping region.
+ */
+ if (pScreenInfo->dwClipUpdatesNBoxes == 0
+ || dwBox < pScreenInfo->dwClipUpdatesNBoxes)
+ {
+ /* Loop through all boxes in the damaged region */
+ while (dwBox--)
+ {
+ /* Assign damage box to source rectangle */
+ rcSrc.left = pBox->x1;
+ rcSrc.top = pBox->y1;
+ rcSrc.right = pBox->x2;
+ rcSrc.bottom = pBox->y2;
+
+ /* Calculate destination rectangle */
+ rcDest.left = ptOrigin.x + rcSrc.left;
+ rcDest.top = ptOrigin.y + rcSrc.top;
+ rcDest.right = ptOrigin.x + rcSrc.right;
+ rcDest.bottom = ptOrigin.y + rcSrc.bottom;
+
+ /* Blit the damaged areas */
+ if (pScreenPriv->pddsPrimary4)
+ myIDirectDrawSurface4_Blt (pScreen,
+ &rcDest,
+ &rcSrc);
+
+ /* Get a pointer to the next box */
+ ++pBox;
+ }
+ }
+ else
+ {
+ BoxPtr pBoxExtents = RegionExtents(damage);
+
+ /* Compute a GDI region from the damaged region */
+ hrgnCombined = CreateRectRgn (pBox->x1, pBox->y1, pBox->x2, pBox->y2);
+ dwBox--;
+ pBox++;
+ while (dwBox--)
+ {
+ hrgnTemp = CreateRectRgn (pBox->x1, pBox->y1, pBox->x2, pBox->y2);
+ CombineRgn (hrgnCombined, hrgnCombined, hrgnTemp, RGN_OR);
+ DeleteObject (hrgnTemp);
+ pBox++;
+ }
+
+ /* Install the GDI region as a clipping region */
+ SelectClipRgn (pScreenPriv->hdcScreen, hrgnCombined);
+ DeleteObject (hrgnCombined);
+ hrgnCombined = NULL;
+
+ winDebug ("winShadowUpdateDDNL - be x1 %d y1 %d x2 %d y2 %d\n",
+ pBoxExtents->x1, pBoxExtents->y1,
+ pBoxExtents->x2, pBoxExtents->y2);
+
+ /* Calculating a bounding box for the source is easy */
+ rcSrc.left = pBoxExtents->x1;
+ rcSrc.top = pBoxExtents->y1;
+ rcSrc.right = pBoxExtents->x2;
+ rcSrc.bottom = pBoxExtents->y2;
+
+ /* Calculating a bounding box for the destination is trickier */
+ rcDest.left = ptOrigin.x + rcSrc.left;
+ rcDest.top = ptOrigin.y + rcSrc.top;
+ rcDest.right = ptOrigin.x + rcSrc.right;
+ rcDest.bottom = ptOrigin.y + rcSrc.bottom;
+
+ /* Our Blt should be clipped to the invalidated region */
+ myIDirectDrawSurface4_Blt (pScreen, &rcDest, &rcSrc);
+
+ /* Reset the clip region */
+ SelectClipRgn (pScreenPriv->hdcScreen, NULL);
+ }
+}
+
+static Bool
+winInitScreenShadowDDNL(ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+
+ /* Get a device context for the screen */
+ pScreenPriv->hdcScreen = GetDC (pScreenPriv->hwndScreen);
+
+ return winAllocateFBShadowDDNL(pScreen);
+}
+
+/*
+ * Call the wrapped CloseScreen function.
+ *
+ * Free our resources and private structures.
+ */
+
+static Bool
+winCloseScreenShadowDDNL (int nIndex, ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ Bool fReturn;
+
+ winDebug ("winCloseScreenShadowDDNL - Freeing screen resources\n");
+
+ /* Flag that the screen is closed */
+ pScreenPriv->fClosed = TRUE;
+ pScreenPriv->fActive = FALSE;
+
+ /* Call the wrapped CloseScreen procedure */
+ WIN_UNWRAP(CloseScreen);
+ if (pScreen->CloseScreen)
+ fReturn = (*pScreen->CloseScreen) (nIndex, pScreen);
+
+ winFreeFBShadowDDNL(pScreen);
+
+ /* Free the screen DC */
+ ReleaseDC (pScreenPriv->hwndScreen, pScreenPriv->hdcScreen);
+
+ /* Delete the window property */
+ RemoveProp (pScreenPriv->hwndScreen, WIN_SCR_PROP);
+
+ /* Delete tray icon, if we have one */
+ if (!pScreenInfo->fNoTrayIcon)
+ winDeleteNotifyIcon (pScreenPriv);
+
+ /* Free the exit confirmation dialog box, if it exists */
+ if (g_hDlgExit != NULL)
+ {
+ DestroyWindow (g_hDlgExit);
+ g_hDlgExit = NULL;
+ }
+
+ /* Kill our window */
+ if (pScreenPriv->hwndScreen)
+ {
+ DestroyWindow (pScreenPriv->hwndScreen);
+ pScreenPriv->hwndScreen = NULL;
+ }
+
+#if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW)
+ /* Destroy the thread startup mutex */
+ pthread_mutex_destroy (&pScreenPriv->pmServerStarted);
+#endif
+
+ /* Kill our screeninfo's pointer to the screen */
+ pScreenInfo->pScreen = NULL;
+
+ /* Free the screen privates for this screen */
+ free ((pointer) pScreenPriv);
+
+ return fReturn;
+}
+
+
+/*
+ * Tell mi what sort of visuals we need.
+ *
+ * Generally we only need one visual, as our screen can only
+ * handle one format at a time, I believe. You may want
+ * to verify that last sentence.
+ */
+
+static Bool
+winInitVisualsShadowDDNL (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ DWORD dwRedBits, dwGreenBits, dwBlueBits;
+
+ /* Count the number of ones in each color mask */
+ dwRedBits = winCountBits (pScreenPriv->dwRedMask);
+ dwGreenBits = winCountBits (pScreenPriv->dwGreenMask);
+ dwBlueBits = winCountBits (pScreenPriv->dwBlueMask);
+
+ /* Store the maximum number of ones in a color mask as the bitsPerRGB */
+ if (dwRedBits == 0 || dwGreenBits == 0 || dwBlueBits == 0)
+ pScreenPriv->dwBitsPerRGB = 8;
+ else if (dwRedBits > dwGreenBits && dwRedBits > dwBlueBits)
+ pScreenPriv->dwBitsPerRGB = dwRedBits;
+ else if (dwGreenBits > dwRedBits && dwGreenBits > dwBlueBits)
+ pScreenPriv->dwBitsPerRGB = dwGreenBits;
+ else
+ pScreenPriv->dwBitsPerRGB = dwBlueBits;
+
+ winDebug ("winInitVisualsShadowDDNL - Masks %08x %08x %08x BPRGB %d d %d "
+ "bpp %d\n",
+ (unsigned int) pScreenPriv->dwRedMask,
+ (unsigned int) pScreenPriv->dwGreenMask,
+ (unsigned int) pScreenPriv->dwBlueMask,
+ (int) pScreenPriv->dwBitsPerRGB,
+ (int) pScreenInfo->dwDepth,
+ (int) pScreenInfo->dwBPP);
+
+ /* Create a single visual according to the Windows screen depth */
+ switch (pScreenInfo->dwDepth)
+ {
+ case 24:
+ case 16:
+ case 15:
+ /* Setup the real visual */
+ if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth,
+ TrueColorMask,
+ pScreenPriv->dwBitsPerRGB,
+ -1,
+ pScreenPriv->dwRedMask,
+ pScreenPriv->dwGreenMask,
+ pScreenPriv->dwBlueMask))
+ {
+ ErrorF ("winInitVisualsShadowDDNL - miSetVisualTypesAndMasks "
+ "failed for TrueColor\n");
+ return FALSE;
+ }
+
+#ifdef XWIN_EMULATEPSEUDO
+ if (!pScreenInfo->fEmulatePseudo)
+ break;
+
+ /* Setup a pseudocolor visual */
+ if (!miSetVisualTypesAndMasks (8,
+ PseudoColorMask,
+ 8,
+ -1,
+ 0,
+ 0,
+ 0))
+ {
+ ErrorF ("winInitVisualsShadowDDNL - miSetVisualTypesAndMasks "
+ "failed for PseudoColor\n");
+ return FALSE;
+ }
+#endif
+ break;
+
+ case 8:
+ if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth,
+ pScreenInfo->fFullScreen
+ ? PseudoColorMask : StaticColorMask,
+ pScreenPriv->dwBitsPerRGB,
+ pScreenInfo->fFullScreen
+ ? PseudoColor : StaticColor,
+ pScreenPriv->dwRedMask,
+ pScreenPriv->dwGreenMask,
+ pScreenPriv->dwBlueMask))
+ {
+ ErrorF ("winInitVisualsShadowDDNL - miSetVisualTypesAndMasks "
+ "failed\n");
+ return FALSE;
+ }
+ break;
+
+ default:
+ ErrorF ("winInitVisualsShadowDDNL - Unknown screen depth\n");
+ return FALSE;
+ }
+
+ winDebug ("winInitVisualsShadowDDNL - Returning\n");
+
+ return TRUE;
+}
+
+
+/*
+ * Adjust the user proposed video mode
+ */
+
+static Bool
+winAdjustVideoModeShadowDDNL (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ HDC hdc = NULL;
+ DWORD dwBPP;
+
+ /* We're in serious trouble if we can't get a DC */
+ hdc = GetDC (NULL);
+ if (hdc == NULL)
+ {
+ ErrorF ("winAdjustVideoModeShadowDDNL - GetDC () failed\n");
+ return FALSE;
+ }
+
+ /* Query GDI for current display depth */
+ dwBPP = GetDeviceCaps (hdc, BITSPIXEL);
+
+ /* DirectDraw can only change the depth in fullscreen mode */
+ if (!(pScreenInfo->fFullScreen &&
+ (pScreenInfo->dwBPP != WIN_DEFAULT_BPP)))
+ {
+ /* Otherwise, We'll use GDI's depth */
+ pScreenInfo->dwBPP = dwBPP;
+ }
+
+ /* Release our DC */
+ ReleaseDC (NULL, hdc);
+
+ return TRUE;
+}
+
+
+/*
+ * Blt exposed regions to the screen
+ */
+
+static Bool
+winBltExposedRegionsShadowDDNL (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ RECT rcSrc, rcDest;
+ POINT ptOrigin;
+ HDC hdcUpdate;
+ PAINTSTRUCT ps;
+ HRESULT ddrval = DD_OK;
+ Bool fReturn = TRUE;
+ int i;
+
+ /* Quite common case. The primary surface was lost (maybe because of depth
+ * change). Try to create a new primary surface. Bail out if this fails */
+ if (pScreenPriv->pddsPrimary4 == NULL && pScreenPriv->fRetryCreateSurface &&
+ !winCreatePrimarySurfaceShadowDDNL(pScreen))
+ {
+ Sleep(100);
+ return FALSE;
+ }
+ if (pScreenPriv->pddsPrimary4 == NULL)
+ return FALSE;
+
+ /* BeginPaint gives us an hdc that clips to the invalidated region */
+ hdcUpdate = BeginPaint (pScreenPriv->hwndScreen, &ps);
+ if (hdcUpdate == NULL)
+ {
+ fReturn = FALSE;
+ ErrorF ("winBltExposedRegionsShadowDDNL - BeginPaint () returned "
+ "a NULL device context handle. Aborting blit attempt.\n");
+ goto winBltExposedRegionsShadowDDNL_Exit;
+ }
+
+ /* Get the origin of the window in the screen coords */
+ ptOrigin.x = pScreenInfo->dwXOffset;
+ ptOrigin.y = pScreenInfo->dwYOffset;
+
+ MapWindowPoints (pScreenPriv->hwndScreen,
+ HWND_DESKTOP,
+ (LPPOINT)&ptOrigin, 1);
+ rcDest.left = ptOrigin.x;
+ rcDest.right = ptOrigin.x + pScreenInfo->dwWidth;
+ rcDest.top = ptOrigin.y;
+ rcDest.bottom = ptOrigin.y + pScreenInfo->dwHeight;
+
+ /* Source can be entire shadow surface, as Blt should clip for us */
+ rcSrc.left = 0;
+ rcSrc.top = 0;
+ rcSrc.right = pScreenInfo->dwWidth;
+ rcSrc.bottom = pScreenInfo->dwHeight;
+
+ /* Our Blt should be clipped to the invalidated region */
+ ddrval = myIDirectDrawSurface4_Blt (pScreen, &rcDest, &rcSrc);
+ if (FAILED (ddrval))
+ {
+ fReturn = FALSE;
+ }
+
+winBltExposedRegionsShadowDDNL_Exit:
+ /* EndPaint frees the DC */
+ if (hdcUpdate != NULL)
+ EndPaint (pScreenPriv->hwndScreen, &ps);
+ return fReturn;
+}
+
+
+/*
+ * Do any engine-specific application-activation processing
+ */
+
+static Bool
+winActivateAppShadowDDNL (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+
+ /*
+ * Do we have a surface?
+ * Are we active?
+ * Are we full screen?
+ */
+ if (pScreenPriv != NULL
+ && pScreenPriv->pddsPrimary4 != NULL
+ && pScreenPriv->fActive)
+ {
+ /* Primary surface was lost, restore it */
+ IDirectDrawSurface4_Restore (pScreenPriv->pddsPrimary4);
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * Reblit the shadow framebuffer to the screen.
+ */
+
+static Bool
+winRedrawScreenShadowDDNL (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ RECT rcSrc, rcDest;
+ POINT ptOrigin;
+
+ /* Get the origin of the window in the screen coords */
+ ptOrigin.x = pScreenInfo->dwXOffset;
+ ptOrigin.y = pScreenInfo->dwYOffset;
+ MapWindowPoints (pScreenPriv->hwndScreen,
+ HWND_DESKTOP,
+ (LPPOINT)&ptOrigin, 1);
+ rcDest.left = ptOrigin.x;
+ rcDest.right = ptOrigin.x + pScreenInfo->dwWidth;
+ rcDest.top = ptOrigin.y;
+ rcDest.bottom = ptOrigin.y + pScreenInfo->dwHeight;
+
+ /* Source can be entire shadow surface, as Blt should clip for us */
+ rcSrc.left = 0;
+ rcSrc.top = 0;
+ rcSrc.right = pScreenInfo->dwWidth;
+ rcSrc.bottom = pScreenInfo->dwHeight;
+
+ /* Redraw the whole window, to take account for the new colors */
+ myIDirectDrawSurface4_Blt (pScreen, &rcDest, &rcSrc);
+ return TRUE;
+}
+
+
+/*
+ * Realize the currently installed colormap
+ */
+
+static Bool
+winRealizeInstalledPaletteShadowDDNL (ScreenPtr pScreen)
+{
+ return TRUE;
+}
+
+
+/*
+ * Install the specified colormap
+ */
+
+static Bool
+winInstallColormapShadowDDNL (ColormapPtr pColormap)
+{
+ ScreenPtr pScreen = pColormap->pScreen;
+ winScreenPriv(pScreen);
+ winCmapPriv(pColormap);
+ HRESULT ddrval = DD_OK;
+
+ /* Install the DirectDraw palette on the primary surface */
+ ddrval = IDirectDrawSurface4_SetPalette (pScreenPriv->pddsPrimary4,
+ pCmapPriv->lpDDPalette);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winInstallColormapShadowDDNL - Failed installing the "
+ "DirectDraw palette.\n");
+ return FALSE;
+ }
+
+ /* Save a pointer to the newly installed colormap */
+ pScreenPriv->pcmapInstalled = pColormap;
+
+ return TRUE;
+}
+
+
+/*
+ * Store the specified colors in the specified colormap
+ */
+
+static Bool
+winStoreColorsShadowDDNL (ColormapPtr pColormap,
+ int ndef,
+ xColorItem *pdefs)
+{
+ ScreenPtr pScreen = pColormap->pScreen;
+ winScreenPriv(pScreen);
+ winCmapPriv(pColormap);
+ ColormapPtr curpmap = pScreenPriv->pcmapInstalled;
+ HRESULT ddrval = DD_OK;
+
+ /* Put the X colormap entries into the Windows logical palette */
+ ddrval = IDirectDrawPalette_SetEntries (pCmapPriv->lpDDPalette,
+ 0,
+ pdefs[0].pixel,
+ ndef,
+ pCmapPriv->peColors
+ + pdefs[0].pixel);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winStoreColorsShadowDDNL - SetEntries () failed: %08x\n", (unsigned int) ddrval);
+ return FALSE;
+ }
+
+ /* Don't install the DirectDraw palette if the colormap is not installed */
+ if (pColormap != curpmap)
+ {
+ return TRUE;
+ }
+
+ if (!winInstallColormapShadowDDNL (pColormap))
+ {
+ ErrorF ("winStoreColorsShadowDDNL - Failed installing colormap\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * Colormap initialization procedure
+ */
+
+static Bool
+winCreateColormapShadowDDNL (ColormapPtr pColormap)
+{
+ HRESULT ddrval = DD_OK;
+ ScreenPtr pScreen = pColormap->pScreen;
+ winScreenPriv(pScreen);
+ winCmapPriv(pColormap);
+
+ /* Create a DirectDraw palette */
+ ddrval = IDirectDraw4_CreatePalette (pScreenPriv->pdd4,
+ DDPCAPS_8BIT | DDPCAPS_ALLOW256,
+ pCmapPriv->peColors,
+ &pCmapPriv->lpDDPalette,
+ NULL);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winCreateColormapShadowDDNL - CreatePalette failed\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * Colormap destruction procedure
+ */
+
+static Bool
+winDestroyColormapShadowDDNL (ColormapPtr pColormap)
+{
+ winScreenPriv(pColormap->pScreen);
+ winCmapPriv(pColormap);
+ HRESULT ddrval = DD_OK;
+
+ /*
+ * Is colormap to be destroyed the default?
+ *
+ * Non-default colormaps should have had winUninstallColormap
+ * called on them before we get here. The default colormap
+ * will not have had winUninstallColormap called on it. Thus,
+ * we need to handle the default colormap in a special way.
+ */
+ if (pColormap->flags & IsDefault)
+ {
+ winDebug ("winDestroyColormapShadowDDNL - Destroying default colormap\n");
+
+ /*
+ * FIXME: Walk the list of all screens, popping the default
+ * palette out of each screen device context.
+ */
+
+ /* Pop the palette out of the primary surface */
+ ddrval = IDirectDrawSurface4_SetPalette (pScreenPriv->pddsPrimary4,
+ NULL);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winDestroyColormapShadowDDNL - Failed freeing the "
+ "default colormap DirectDraw palette.\n");
+ return FALSE;
+ }
+
+ /* Clear our private installed colormap pointer */
+ pScreenPriv->pcmapInstalled = NULL;
+ }
+
+ /* Release the palette */
+ IDirectDrawPalette_Release (pCmapPriv->lpDDPalette);
+
+ /* Invalidate the colormap privates */
+ pCmapPriv->lpDDPalette = NULL;
+
+ return TRUE;
+}
+
+
+/*
+ * Set pointers to our engine specific functions
+ */
+
+Bool
+winSetEngineFunctionsShadowDDNL (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+
+ /* Set our pointers */
+ pScreenPriv->pwinAllocateFB = winAllocateFBShadowDDNL;
+ pScreenPriv->pwinFreeFB = winFreeFBShadowDDNL;
+ pScreenPriv->pwinShadowUpdate = winShadowUpdateDDNL;
+ pScreenPriv->pwinInitScreen = winInitScreenShadowDDNL;
+ pScreenPriv->pwinCloseScreen = winCloseScreenShadowDDNL;
+ pScreenPriv->pwinInitVisuals = winInitVisualsShadowDDNL;
+ pScreenPriv->pwinAdjustVideoMode = winAdjustVideoModeShadowDDNL;
+ if (pScreenInfo->fFullScreen)
+ pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowFullScreen;
+ else
+ pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowWindowed;
+ pScreenPriv->pwinFinishScreenInit = winFinishScreenInitFB;
+ pScreenPriv->pwinBltExposedRegions = winBltExposedRegionsShadowDDNL;
+ pScreenPriv->pwinActivateApp = winActivateAppShadowDDNL;
+ pScreenPriv->pwinRedrawScreen = winRedrawScreenShadowDDNL;
+ pScreenPriv->pwinRealizeInstalledPalette
+ = winRealizeInstalledPaletteShadowDDNL;
+ pScreenPriv->pwinInstallColormap = winInstallColormapShadowDDNL;
+ pScreenPriv->pwinStoreColors = winStoreColorsShadowDDNL;
+ pScreenPriv->pwinCreateColormap = winCreateColormapShadowDDNL;
+ pScreenPriv->pwinDestroyColormap = winDestroyColormapShadowDDNL;
+ pScreenPriv->pwinHotKeyAltTab = (winHotKeyAltTabProcPtr) (void (*)(void))NoopDDA;
+ pScreenPriv->pwinCreatePrimarySurface = winCreatePrimarySurfaceShadowDDNL;
+ pScreenPriv->pwinReleasePrimarySurface = winReleasePrimarySurfaceShadowDDNL;
+#ifdef XWIN_MULTIWINDOW
+ pScreenPriv->pwinFinishCreateWindowsWindow
+ = winFinishCreateWindowsWindowDDNL;
+#endif
+
+ return TRUE;
+}
diff --git a/xorg-server/hw/xwin/winshadgdi.c b/xorg-server/hw/xwin/winshadgdi.c index 7d53d4969..bcb2051fc 100644 --- a/xorg-server/hw/xwin/winshadgdi.c +++ b/xorg-server/hw/xwin/winshadgdi.c @@ -1,1237 +1,1238 @@ -/* - *Copyright (C) 2001-2004 Harold L Hunt II 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 HAROLD L HUNT II 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 Harold L Hunt II - *shall not be used in advertising or otherwise to promote the sale, use - *or other dealings in this Software without prior written authorization - *from Harold L Hunt II. - * - * Authors: Harold L Hunt II - */ - -#ifdef HAVE_XWIN_CONFIG_H -#include <xwin-config.h> -#endif -#include "win.h" - - -/* - * Local function prototypes - */ - -#ifdef XWIN_MULTIWINDOW -static wBOOL CALLBACK -winRedrawAllProcShadowGDI (HWND hwnd, LPARAM lParam); - -static wBOOL CALLBACK -winRedrawDamagedWindowShadowGDI (HWND hwnd, LPARAM lParam); -#endif - -static Bool -winAllocateFBShadowGDI (ScreenPtr pScreen); - -static void -winShadowUpdateGDI (ScreenPtr pScreen, - shadowBufPtr pBuf); - -static Bool -winCloseScreenShadowGDI (int nIndex, ScreenPtr pScreen); - -static Bool -winInitVisualsShadowGDI (ScreenPtr pScreen); - -static Bool -winAdjustVideoModeShadowGDI (ScreenPtr pScreen); - -static Bool -winBltExposedRegionsShadowGDI (ScreenPtr pScreen); - -static Bool -winActivateAppShadowGDI (ScreenPtr pScreen); - -static Bool -winRedrawScreenShadowGDI (ScreenPtr pScreen); - -static Bool -winRealizeInstalledPaletteShadowGDI (ScreenPtr pScreen); - -static Bool -winInstallColormapShadowGDI (ColormapPtr pColormap); - -static Bool -winStoreColorsShadowGDI (ColormapPtr pmap, - int ndef, - xColorItem *pdefs); - -static Bool -winCreateColormapShadowGDI (ColormapPtr pColormap); - -static Bool -winDestroyColormapShadowGDI (ColormapPtr pColormap); - - -/* - * Internal function to get the DIB format that is compatible with the screen - */ - -static -Bool -winQueryScreenDIBFormat (ScreenPtr pScreen, BITMAPINFOHEADER *pbmih) -{ - winScreenPriv(pScreen); - HBITMAP hbmp; -#ifdef WINDBG - LPDWORD pdw = NULL; -#endif - - /* Create a memory bitmap compatible with the screen */ - hbmp = CreateCompatibleBitmap (pScreenPriv->hdcScreen, 1, 1); - if (hbmp == NULL) - { - ErrorF ("winQueryScreenDIBFormat - 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 (pScreenPriv->hdcScreen, - hbmp, - 0, 1, - NULL, - (BITMAPINFO*) pbmih, - DIB_RGB_COLORS)) - { - ErrorF ("winQueryScreenDIBFormat - First call to GetDIBits failed\n"); - DeleteObject (hbmp); - return FALSE; - } - -#ifdef WINDBG - /* Get a pointer to bitfields */ - pdw = (DWORD*) ((CARD8*)pbmih + sizeof (BITMAPINFOHEADER)); - - winDebug ("winQueryScreenDIBFormat - First call masks: %08x %08x %08x\n", - pdw[0], pdw[1], pdw[2]); -#endif - - /* Get optimal color table, or the optimal bitfields */ - if (!GetDIBits (pScreenPriv->hdcScreen, - hbmp, - 0, 1, - NULL, - (BITMAPINFO*)pbmih, - DIB_RGB_COLORS)) - { - ErrorF ("winQueryScreenDIBFormat - Second call to GetDIBits " - "failed\n"); - DeleteObject (hbmp); - return FALSE; - } - - /* Free memory */ - DeleteObject (hbmp); - - return TRUE; -} - - -/* - * Internal function to determine the GDI bits per rgb and bit masks - */ - -static -Bool -winQueryRGBBitsAndMasks (ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - BITMAPINFOHEADER *pbmih = NULL; - Bool fReturn = TRUE; - LPDWORD pdw = NULL; - DWORD dwRedBits, dwGreenBits, dwBlueBits; - - /* Color masks for 8 bpp are standardized */ - if (GetDeviceCaps (pScreenPriv->hdcScreen, RASTERCAPS) & RC_PALETTE) - { - /* - * RGB BPP for 8 bit palletes is always 8 - * and the color masks are always 0. - */ - pScreenPriv->dwBitsPerRGB = 8; - pScreenPriv->dwRedMask = 0x0L; - pScreenPriv->dwGreenMask = 0x0L; - pScreenPriv->dwBlueMask = 0x0L; - return TRUE; - } - - /* Color masks for 24 bpp are standardized */ - if (GetDeviceCaps (pScreenPriv->hdcScreen, PLANES) - * GetDeviceCaps (pScreenPriv->hdcScreen, BITSPIXEL) == 24) - { - winDebug ("winQueryRGBBitsAndMasks - GetDeviceCaps (BITSPIXEL) " - "returned 24 for the screen. Using default 24bpp masks.\n"); - - /* 8 bits per primary color */ - pScreenPriv->dwBitsPerRGB = 8; - - /* Set screen privates masks */ - pScreenPriv->dwRedMask = WIN_24BPP_MASK_RED; - pScreenPriv->dwGreenMask = WIN_24BPP_MASK_GREEN; - pScreenPriv->dwBlueMask = WIN_24BPP_MASK_BLUE; - - return TRUE; - } - - /* Allocate a bitmap header and color table */ - pbmih = (BITMAPINFOHEADER*) malloc (sizeof (BITMAPINFOHEADER) - + 256 * sizeof (RGBQUAD)); - if (pbmih == NULL) - { - ErrorF ("winQueryRGBBitsAndMasks - malloc failed\n"); - return FALSE; - } - - /* Get screen description */ - if (winQueryScreenDIBFormat (pScreen, pbmih)) - { - /* Get a pointer to bitfields */ - pdw = (DWORD*) ((CARD8*)pbmih + sizeof (BITMAPINFOHEADER)); - -#ifdef WINDBG - winDebug ("%s - Masks: %08x %08x %08x\n", __FUNCTION__, - pdw[0], pdw[1], pdw[2]); - winDebug ("%s - Bitmap: %dx%d %d bpp %d planes\n", __FUNCTION__, - pbmih->biWidth, pbmih->biHeight, pbmih->biBitCount, pbmih->biPlanes); - winDebug ("%s - Compression: %d %s\n", __FUNCTION__, - pbmih->biCompression, - (pbmih->biCompression == BI_RGB?"(BI_RGB)": - (pbmih->biCompression == BI_RLE8?"(BI_RLE8)": - (pbmih->biCompression == BI_RLE4?"(BI_RLE4)": - (pbmih->biCompression == BI_BITFIELDS?"(BI_BITFIELDS)":"" - ))))); -#endif - - /* Handle BI_RGB case, which is returned by Wine */ - if (pbmih->biCompression == BI_RGB) - { - dwRedBits = 5; - dwGreenBits = 5; - dwBlueBits = 5; - - pScreenPriv->dwBitsPerRGB = 5; - - /* Set screen privates masks */ - pScreenPriv->dwRedMask = 0x7c00; - pScreenPriv->dwGreenMask = 0x03e0; - pScreenPriv->dwBlueMask = 0x001f; - } - else - { - /* Count the number of bits in each mask */ - dwRedBits = winCountBits (pdw[0]); - dwGreenBits = winCountBits (pdw[1]); - dwBlueBits = winCountBits (pdw[2]); - - /* Find maximum bits per red, green, blue */ - if (dwRedBits > dwGreenBits && dwRedBits > dwBlueBits) - pScreenPriv->dwBitsPerRGB = dwRedBits; - else if (dwGreenBits > dwRedBits && dwGreenBits > dwBlueBits) - pScreenPriv->dwBitsPerRGB = dwGreenBits; - else - pScreenPriv->dwBitsPerRGB = dwBlueBits; - - /* Set screen privates masks */ - pScreenPriv->dwRedMask = pdw[0]; - pScreenPriv->dwGreenMask = pdw[1]; - pScreenPriv->dwBlueMask = pdw[2]; - } - } - else - { - ErrorF ("winQueryRGBBitsAndMasks - winQueryScreenDIBFormat failed\n"); - free (pbmih); - fReturn = FALSE; - } - - /* Free memory */ - free (pbmih); - - return fReturn; -} - - -#ifdef XWIN_MULTIWINDOW -/* - * Redraw all ---? - */ - -static wBOOL CALLBACK -winRedrawAllProcShadowGDI (HWND hwnd, LPARAM lParam) -{ - if (hwnd == (HWND)lParam) - return TRUE; - InvalidateRect (hwnd, NULL, FALSE); - UpdateWindow (hwnd); - return TRUE; -} - -static wBOOL CALLBACK -winRedrawDamagedWindowShadowGDI (HWND hwnd, LPARAM lParam) -{ - BoxPtr pDamage = (BoxPtr)lParam; - RECT rcClient, rcDamage, rcRedraw; - POINT topLeft, bottomRight; - - if (IsIconic (hwnd)) - return TRUE; /* Don't care minimized windows */ - - /* Convert the damaged area from Screen coords to Client coords */ - topLeft.x = pDamage->x1; topLeft.y = pDamage->y1; - bottomRight.x = pDamage->x2; bottomRight.y = pDamage->y2; - topLeft.x += GetSystemMetrics (SM_XVIRTUALSCREEN); - bottomRight.x += GetSystemMetrics (SM_XVIRTUALSCREEN); - topLeft.y += GetSystemMetrics (SM_YVIRTUALSCREEN); - bottomRight.y += GetSystemMetrics (SM_YVIRTUALSCREEN); - ScreenToClient (hwnd, &topLeft); - ScreenToClient (hwnd, &bottomRight); - SetRect (&rcDamage, topLeft.x, topLeft.y, bottomRight.x, bottomRight.y); - - GetClientRect (hwnd, &rcClient); - - if (IntersectRect (&rcRedraw, &rcClient, &rcDamage)) - { - InvalidateRect (hwnd, &rcRedraw, FALSE); - UpdateWindow (hwnd); - } - return TRUE; -} -#endif - - -/* - * Allocate a DIB for the shadow framebuffer GDI server - */ - -static Bool -winAllocateFBShadowGDI (ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; - DIBSECTION dibsection; - Bool fReturn = TRUE; - - /* Describe shadow bitmap to be created */ - pScreenPriv->pbmih->biWidth = pScreenInfo->dwWidth; - pScreenPriv->pbmih->biHeight = -pScreenInfo->dwHeight; - - winDebug ("winAllocateFBShadowGDI - Creating DIB with width: %d height: %d " - "depth: %d\n", - (int) pScreenPriv->pbmih->biWidth, (int) -pScreenPriv->pbmih->biHeight, pScreenPriv->pbmih->biBitCount); - - /* Create a DI shadow bitmap with a bit pointer */ - pScreenPriv->hbmpShadow = CreateDIBSection (pScreenPriv->hdcScreen, - (BITMAPINFO *) pScreenPriv->pbmih, - DIB_RGB_COLORS, - (VOID**) &pScreenInfo->pfb, - NULL, - 0); - if (pScreenPriv->hbmpShadow == NULL || pScreenInfo->pfb == NULL) - { - winW32Error ("winAllocateFBShadowGDI - CreateDIBSection failed:"); - return FALSE; - } - else - { - winDebug ("winAllocateFBShadowGDI - Shadow buffer allocated\n"); - } - - /* Get information about the bitmap that was allocated */ - GetObject (pScreenPriv->hbmpShadow, - sizeof (dibsection), - &dibsection); - - /* Print information about bitmap allocated */ - winDebug ("winAllocateFBShadowGDI - Dibsection width: %d height: %d " - "depth: %d size image: %d\n", - (int) dibsection.dsBmih.biWidth, (int) dibsection.dsBmih.biHeight, - dibsection.dsBmih.biBitCount, - (int) dibsection.dsBmih.biSizeImage); - - /* Select the shadow bitmap into the shadow DC */ - SelectObject (pScreenPriv->hdcShadow, - pScreenPriv->hbmpShadow); - - winDebug ("winAllocateFBShadowGDI - Attempting a shadow blit\n"); - - /* Do a test blit from the shadow to the screen, I think */ - fReturn = BitBlt (pScreenPriv->hdcScreen, - 0, 0, - pScreenInfo->dwWidth, pScreenInfo->dwHeight, - pScreenPriv->hdcShadow, - 0, 0, - SRCCOPY); - if (fReturn) - { - winDebug ("winAllocateFBShadowGDI - Shadow blit success\n"); - } - else - { - winW32Error ("winAllocateFBShadowGDI - Shadow blit failure\n"); - /* ago: ignore this error. The blit fails with wine, but does not - * cause any problems later. */ - - fReturn = TRUE; - } - - /* Look for height weirdness */ - if (dibsection.dsBmih.biHeight < 0) - { - dibsection.dsBmih.biHeight = -dibsection.dsBmih.biHeight; - } - - /* Set screeninfo stride */ - pScreenInfo->dwStride = ((dibsection.dsBmih.biSizeImage - / dibsection.dsBmih.biHeight) - * 8) / pScreenInfo->dwBPP; - - winDebug ("winAllocateFBShadowGDI - Created shadow stride: %d\n", - (int) pScreenInfo->dwStride); - -#ifdef XWIN_MULTIWINDOW - /* Redraw all windows */ - if (pScreenInfo->fMultiWindow) - EnumThreadWindows (g_dwCurrentThreadID, winRedrawAllProcShadowGDI, 0); -#endif - - return fReturn; -} - -static void -winFreeFBShadowGDI (ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; - - /* Free the shadow bitmap */ - DeleteObject (pScreenPriv->hbmpShadow); - - /* Invalidate the ScreenInfo's fb pointer */ - pScreenInfo->pfb = NULL; -} - -/* - * Blit the damaged regions of the shadow fb to the screen - */ - -static void -winShadowUpdateGDI (ScreenPtr pScreen, - shadowBufPtr pBuf) -{ - winScreenPriv(pScreen); - winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; - RegionPtr damage = shadowDamage(pBuf); - DWORD dwBox = RegionNumRects (damage); - BoxPtr pBox = RegionRects (damage); - int x, y, w, h; - HRGN hrgnTemp = NULL, hrgnCombined = NULL; -#ifdef XWIN_UPDATESTATS - static DWORD s_dwNonUnitRegions = 0; - static DWORD s_dwTotalUpdates = 0; - static DWORD s_dwTotalBoxes = 0; -#endif - BoxPtr pBoxExtents = RegionExtents(damage); - - /* - * Return immediately if the app is not active - * and we are fullscreen, or if we have a bad display depth - */ - if ((!pScreenPriv->fActive && pScreenInfo->fFullScreen) - || pScreenPriv->fBadDepth) return; - -#ifdef XWIN_UPDATESTATS - ++s_dwTotalUpdates; - s_dwTotalBoxes += dwBox; - - if (dwBox != 1) - { - ++s_dwNonUnitRegions; - winDebug ("winShadowUpdatGDI - dwBox: %d\n", dwBox); - } - - if ((s_dwTotalUpdates % 100) == 0) - { - winDebug ("winShadowUpdateGDI - %d%% non-unity regions, avg boxes: %d " - "nu: %d tu: %d\n", - (s_dwNonUnitRegions * 100) / s_dwTotalUpdates, - s_dwTotalBoxes / s_dwTotalUpdates, - s_dwNonUnitRegions, s_dwTotalUpdates); - } -#endif /* XWIN_UPDATESTATS */ - - /* - * Handle small regions with multiple blits, - * handle large regions by creating a clipping region and - * doing a single blit constrained to that clipping region. - */ - if (!pScreenInfo->fMultiWindow && - (pScreenInfo->dwClipUpdatesNBoxes == 0 || - dwBox < pScreenInfo->dwClipUpdatesNBoxes)) - { - /* Loop through all boxes in the damaged region */ - while (dwBox--) - { - /* - * Calculate x offset, y offset, width, and height for - * current damage box - */ - x = pBox->x1; - y = pBox->y1; - w = pBox->x2 - pBox->x1; - h = pBox->y2 - pBox->y1; - - BitBlt (pScreenPriv->hdcScreen, - x, y, - w, h, - pScreenPriv->hdcShadow, - x, y, - SRCCOPY); - - /* Get a pointer to the next box */ - ++pBox; - } - } - else if (!pScreenInfo->fMultiWindow) - { - /* Compute a GDI region from the damaged region */ - hrgnCombined = CreateRectRgn (pBox->x1, pBox->y1, pBox->x2, pBox->y2); - dwBox--; - pBox++; - while (dwBox--) - { - hrgnTemp = CreateRectRgn (pBox->x1, pBox->y1, pBox->x2, pBox->y2); - CombineRgn (hrgnCombined, hrgnCombined, hrgnTemp, RGN_OR); - DeleteObject (hrgnTemp); - pBox++; - } - - /* Install the GDI region as a clipping region */ - SelectClipRgn (pScreenPriv->hdcScreen, hrgnCombined); - DeleteObject (hrgnCombined); - hrgnCombined = NULL; - - /* - * Blit the shadow buffer to the screen, - * constrained to the clipping region. - */ - BitBlt (pScreenPriv->hdcScreen, - pBoxExtents->x1, pBoxExtents->y1, - pBoxExtents->x2 - pBoxExtents->x1, - pBoxExtents->y2 - pBoxExtents->y1, - pScreenPriv->hdcShadow, - pBoxExtents->x1, pBoxExtents->y1, - SRCCOPY); - - /* Reset the clip region */ - SelectClipRgn (pScreenPriv->hdcScreen, NULL); - } - -#ifdef XWIN_MULTIWINDOW - /* Redraw all multiwindow windows */ - if (pScreenInfo->fMultiWindow) - EnumThreadWindows (g_dwCurrentThreadID, - winRedrawDamagedWindowShadowGDI, - (LPARAM)pBoxExtents); -#endif -} - - -static Bool -winInitScreenShadowGDI (ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - - /* Get device contexts for the screen and shadow bitmap */ - pScreenPriv->hdcScreen = GetDC (pScreenPriv->hwndScreen); - pScreenPriv->hdcShadow = CreateCompatibleDC (pScreenPriv->hdcScreen); - - /* Allocate bitmap info header */ - pScreenPriv->pbmih = (BITMAPINFOHEADER*) malloc (sizeof (BITMAPINFOHEADER) - + 256 * sizeof (RGBQUAD)); - if (pScreenPriv->pbmih == NULL) - { - ErrorF ("winInitScreenShadowGDI - malloc () failed\n"); - return FALSE; - } - - /* Query the screen format */ - if (!winQueryScreenDIBFormat (pScreen, pScreenPriv->pbmih)) - { - ErrorF ("winInitScreenShadowGDI - winQueryScreenDIBFormat failed\n"); - return FALSE; - } - - /* Determine our color masks */ - if (!winQueryRGBBitsAndMasks (pScreen)) - { - ErrorF ("winInitScreenShadowGDI - winQueryRGBBitsAndMasks failed\n"); - return FALSE; - } - - return winAllocateFBShadowGDI(pScreen); -} - -/* See Porting Layer Definition - p. 33 */ -/* - * We wrap whatever CloseScreen procedure was specified by fb; - * a pointer to said procedure is stored in our privates. - */ - -static Bool -winCloseScreenShadowGDI (int nIndex, ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; - Bool fReturn; - - winDebug ("winCloseScreenShadowGDI - Freeing screen resources\n"); - - /* Flag that the screen is closed */ - pScreenPriv->fClosed = TRUE; - pScreenPriv->fActive = FALSE; - - /* Call the wrapped CloseScreen procedure */ - WIN_UNWRAP(CloseScreen); - fReturn = (*pScreen->CloseScreen) (nIndex, pScreen); - - /* Delete the window property */ - RemoveProp (pScreenPriv->hwndScreen, WIN_SCR_PROP); - - /* Free the shadow DC; which allows the bitmap to be freed */ - DeleteDC (pScreenPriv->hdcShadow); - - winFreeFBShadowGDI(pScreen); - - /* Free the screen DC */ - ReleaseDC (pScreenPriv->hwndScreen, pScreenPriv->hdcScreen); - - /* Delete tray icon, if we have one */ - if (!pScreenInfo->fNoTrayIcon) - winDeleteNotifyIcon (pScreenPriv); - - /* Free the exit confirmation dialog box, if it exists */ - if (g_hDlgExit != NULL) - { - DestroyWindow (g_hDlgExit); - g_hDlgExit = NULL; - } - - /* Kill our window */ - if (pScreenPriv->hwndScreen) - { - DestroyWindow (pScreenPriv->hwndScreen); - pScreenPriv->hwndScreen = NULL; - } - -#if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW) - /* Destroy the thread startup mutex */ - pthread_mutex_destroy (&pScreenPriv->pmServerStarted); -#endif - - /* Invalidate our screeninfo's pointer to the screen */ - pScreenInfo->pScreen = NULL; - - /* Free the screen privates for this screen */ - free ((pointer) pScreenPriv); - - return fReturn; -} - - -/* - * Tell mi what sort of visuals we need. - * - * Generally we only need one visual, as our screen can only - * handle one format at a time, I believe. You may want - * to verify that last sentence. - */ - -static Bool -winInitVisualsShadowGDI (ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; - - /* Display debugging information */ - winDebug ("winInitVisualsShadowGDI - Masks %08x %08x %08x BPRGB %d d %d " - "bpp %d\n", - (unsigned int) pScreenPriv->dwRedMask, - (unsigned int) pScreenPriv->dwGreenMask, - (unsigned int) pScreenPriv->dwBlueMask, - (int) pScreenPriv->dwBitsPerRGB, - (int) pScreenInfo->dwDepth, - (int) pScreenInfo->dwBPP); - - /* Create a single visual according to the Windows screen depth */ - switch (pScreenInfo->dwDepth) - { - case 24: - case 16: - case 15: - /* Setup the real visual */ - if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth, - TrueColorMask, - pScreenPriv->dwBitsPerRGB, - -1, - pScreenPriv->dwRedMask, - pScreenPriv->dwGreenMask, - pScreenPriv->dwBlueMask)) - { - ErrorF ("winInitVisualsShadowGDI - miSetVisualTypesAndMasks " - "failed\n"); - return FALSE; - } - -#ifdef XWIN_EMULATEPSEUDO - if (!pScreenInfo->fEmulatePseudo) - break; - - /* Setup a pseudocolor visual */ - if (!miSetVisualTypesAndMasks (8, - PseudoColorMask, - 8, - -1, - 0, - 0, - 0)) - { - ErrorF ("winInitVisualsShadowGDI - miSetVisualTypesAndMasks " - "failed for PseudoColor\n"); - return FALSE; - } -#endif - break; - - case 8: - if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth, - PseudoColorMask, - pScreenPriv->dwBitsPerRGB, - PseudoColor, - pScreenPriv->dwRedMask, - pScreenPriv->dwGreenMask, - pScreenPriv->dwBlueMask)) - { - ErrorF ("winInitVisualsShadowGDI - miSetVisualTypesAndMasks " - "failed\n"); - return FALSE; - } - break; - - default: - ErrorF ("winInitVisualsShadowGDI - Unknown screen depth\n"); - return FALSE; - } - - winDebug ("winInitVisualsShadowGDI - Returning\n"); - - return TRUE; -} - - -/* - * Adjust the proposed video mode - */ - -static Bool -winAdjustVideoModeShadowGDI (ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; - HDC hdc; - DWORD dwBPP; - - hdc = GetDC (NULL); - - /* We're in serious trouble if we can't get a DC */ - if (hdc == NULL) - { - ErrorF ("winAdjustVideoModeShadowGDI - GetDC () failed\n"); - return FALSE; - } - - /* Query GDI for current display depth */ - dwBPP = GetDeviceCaps (hdc, BITSPIXEL); - - /* GDI cannot change the screen depth, so always use GDI's depth */ - pScreenInfo->dwBPP = dwBPP; - - /* Release our DC */ - ReleaseDC (NULL, hdc); - hdc = NULL; - - return TRUE; -} - - -/* - * Blt exposed regions to the screen - */ - -static Bool -winBltExposedRegionsShadowGDI (ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; - winPrivCmapPtr pCmapPriv = NULL; - HDC hdcUpdate; - PAINTSTRUCT ps; - - /* BeginPaint gives us an hdc that clips to the invalidated region */ - hdcUpdate = BeginPaint (pScreenPriv->hwndScreen, &ps); - - /* Realize the palette, if we have one */ - if (pScreenPriv->pcmapInstalled != NULL) - { - pCmapPriv = winGetCmapPriv (pScreenPriv->pcmapInstalled); - - SelectPalette (hdcUpdate, pCmapPriv->hPalette, FALSE); - RealizePalette (hdcUpdate); - } - - /* Our BitBlt will be clipped to the invalidated region */ - BitBlt (hdcUpdate, - 0, 0, - pScreenInfo->dwWidth, pScreenInfo->dwHeight, - pScreenPriv->hdcShadow, - 0, 0, - SRCCOPY); - - /* EndPaint frees the DC */ - EndPaint (pScreenPriv->hwndScreen, &ps); - -#ifdef XWIN_MULTIWINDOW - /* Redraw all windows */ - if (pScreenInfo->fMultiWindow) - EnumThreadWindows(g_dwCurrentThreadID, winRedrawAllProcShadowGDI, - (LPARAM)pScreenPriv->hwndScreen); -#endif - - return TRUE; -} - - -/* - * Do any engine-specific appliation-activation processing - */ - -static Bool -winActivateAppShadowGDI (ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; - - /* - * 2004/04/12 - Harold - We perform the restoring or minimizing - * manually for ShadowGDI in fullscreen modes so that this engine - * will perform just like ShadowDD and ShadowDDNL in fullscreen mode; - * if we do not do this then our fullscreen window will appear in the - * z-order when it is deactivated and it can be uncovered by resizing - * or minimizing another window that is on top of it, which is not how - * the DirectDraw engines work. Therefore we keep this code here to - * make sure that all engines work the same in fullscreen mode. - */ - - /* - * Are we active? - * Are we fullscreen? - */ - if (pScreenPriv->fActive - && pScreenInfo->fFullScreen) - { - /* - * Activating, attempt to bring our window - * to the top of the display - */ - ShowWindow (pScreenPriv->hwndScreen, SW_RESTORE); - } - else if (!pScreenPriv->fActive - && pScreenInfo->fFullScreen) - { - /* - * Deactivating, stuff our window onto the - * task bar. - */ - ShowWindow (pScreenPriv->hwndScreen, SW_MINIMIZE); - } - - return TRUE; -} - - -/* - * Reblit the shadow framebuffer to the screen. - */ - -static Bool -winRedrawScreenShadowGDI (ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; - - /* Redraw the whole window, to take account for the new colors */ - BitBlt (pScreenPriv->hdcScreen, - 0, 0, - pScreenInfo->dwWidth, pScreenInfo->dwHeight, - pScreenPriv->hdcShadow, - 0, 0, - SRCCOPY); - -#ifdef XWIN_MULTIWINDOW - /* Redraw all windows */ - if (pScreenInfo->fMultiWindow) - EnumThreadWindows(g_dwCurrentThreadID, winRedrawAllProcShadowGDI, 0); -#endif - - return TRUE; -} - - - -/* - * Realize the currently installed colormap - */ - -static Bool -winRealizeInstalledPaletteShadowGDI (ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - winPrivCmapPtr pCmapPriv = NULL; - - winDebug ("winRealizeInstalledPaletteShadowGDI\n"); - - /* Don't do anything if there is not a colormap */ - if (pScreenPriv->pcmapInstalled == NULL) - { - winDebug ("winRealizeInstalledPaletteShadowGDI - No colormap " - "installed\n"); - return TRUE; - } - - pCmapPriv = winGetCmapPriv (pScreenPriv->pcmapInstalled); - - /* Realize our palette for the screen */ - if (RealizePalette (pScreenPriv->hdcScreen) == GDI_ERROR) - { - ErrorF ("winRealizeInstalledPaletteShadowGDI - RealizePalette () " - "failed\n"); - return FALSE; - } - - /* Set the DIB color table */ - if (SetDIBColorTable (pScreenPriv->hdcShadow, - 0, - WIN_NUM_PALETTE_ENTRIES, - pCmapPriv->rgbColors) == 0) - { - ErrorF ("winRealizeInstalledPaletteShadowGDI - SetDIBColorTable () " - "failed\n"); - return FALSE; - } - - return TRUE; -} - - -/* - * Install the specified colormap - */ - -static Bool -winInstallColormapShadowGDI (ColormapPtr pColormap) -{ - ScreenPtr pScreen = pColormap->pScreen; - winScreenPriv(pScreen); - winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; - winCmapPriv(pColormap); - - /* - * Tell Windows to install the new colormap - */ - if (SelectPalette (pScreenPriv->hdcScreen, - pCmapPriv->hPalette, - FALSE) == NULL) - { - ErrorF ("winInstallColormapShadowGDI - SelectPalette () failed\n"); - return FALSE; - } - - /* Realize the palette */ - if (GDI_ERROR == RealizePalette (pScreenPriv->hdcScreen)) - { - ErrorF ("winInstallColormapShadowGDI - RealizePalette () failed\n"); - return FALSE; - } - - /* Set the DIB color table */ - if (SetDIBColorTable (pScreenPriv->hdcShadow, - 0, - WIN_NUM_PALETTE_ENTRIES, - pCmapPriv->rgbColors) == 0) - { - ErrorF ("winInstallColormapShadowGDI - SetDIBColorTable () failed\n"); - return FALSE; - } - - /* Redraw the whole window, to take account for the new colors */ - BitBlt (pScreenPriv->hdcScreen, - 0, 0, - pScreenInfo->dwWidth, pScreenInfo->dwHeight, - pScreenPriv->hdcShadow, - 0, 0, - SRCCOPY); - - /* Save a pointer to the newly installed colormap */ - pScreenPriv->pcmapInstalled = pColormap; - -#ifdef XWIN_MULTIWINDOW - /* Redraw all windows */ - if (pScreenInfo->fMultiWindow) - EnumThreadWindows (g_dwCurrentThreadID, winRedrawAllProcShadowGDI, 0); -#endif - - return TRUE; -} - - -/* - * Store the specified colors in the specified colormap - */ - -static Bool -winStoreColorsShadowGDI (ColormapPtr pColormap, - int ndef, - xColorItem *pdefs) -{ - ScreenPtr pScreen = pColormap->pScreen; - winScreenPriv(pScreen); - winCmapPriv(pColormap); - ColormapPtr curpmap = pScreenPriv->pcmapInstalled; - - /* Put the X colormap entries into the Windows logical palette */ - if (SetPaletteEntries (pCmapPriv->hPalette, - pdefs[0].pixel, - ndef, - pCmapPriv->peColors + pdefs[0].pixel) == 0) - { - ErrorF ("winStoreColorsShadowGDI - SetPaletteEntries () failed\n"); - return FALSE; - } - - /* Don't install the Windows palette if the colormap is not installed */ - if (pColormap != curpmap) - { - return TRUE; - } - - /* Try to install the newly modified colormap */ - if (!winInstallColormapShadowGDI (pColormap)) - { - ErrorF ("winInstallColormapShadowGDI - winInstallColormapShadowGDI " - "failed\n"); - return FALSE; - } - -#if 0 - /* Tell Windows that the palette has changed */ - RealizePalette (pScreenPriv->hdcScreen); - - /* Set the DIB color table */ - if (SetDIBColorTable (pScreenPriv->hdcShadow, - pdefs[0].pixel, - ndef, - pCmapPriv->rgbColors + pdefs[0].pixel) == 0) - { - ErrorF ("winInstallColormapShadowGDI - SetDIBColorTable () failed\n"); - return FALSE; - } - - /* Save a pointer to the newly installed colormap */ - pScreenPriv->pcmapInstalled = pColormap; -#endif - - return TRUE; -} - - -/* - * Colormap initialization procedure - */ - -static Bool -winCreateColormapShadowGDI (ColormapPtr pColormap) -{ - LPLOGPALETTE lpPaletteNew = NULL; - DWORD dwEntriesMax; - VisualPtr pVisual; - HPALETTE hpalNew = NULL; - winCmapPriv(pColormap); - - /* Get a pointer to the visual that the colormap belongs to */ - pVisual = pColormap->pVisual; - - /* Get the maximum number of palette entries for this visual */ - dwEntriesMax = pVisual->ColormapEntries; - - /* Allocate a Windows logical color palette with max entries */ - lpPaletteNew = malloc (sizeof (LOGPALETTE) - + (dwEntriesMax - 1) * sizeof (PALETTEENTRY)); - if (lpPaletteNew == NULL) - { - ErrorF ("winCreateColormapShadowGDI - Couldn't allocate palette " - "with %d entries\n", - (int) dwEntriesMax); - return FALSE; - } - - /* Zero out the colormap */ - ZeroMemory (lpPaletteNew, sizeof (LOGPALETTE) - + (dwEntriesMax - 1) * sizeof (PALETTEENTRY)); - - /* Set the logical palette structure */ - lpPaletteNew->palVersion = 0x0300; - lpPaletteNew->palNumEntries = dwEntriesMax; - - /* Tell Windows to create the palette */ - hpalNew = CreatePalette (lpPaletteNew); - if (hpalNew == NULL) - { - ErrorF ("winCreateColormapShadowGDI - CreatePalette () failed\n"); - free (lpPaletteNew); - return FALSE; - } - - /* Save the Windows logical palette handle in the X colormaps' privates */ - pCmapPriv->hPalette = hpalNew; - - /* Free the palette initialization memory */ - free (lpPaletteNew); - - return TRUE; -} - - -/* - * Colormap destruction procedure - */ - -static Bool -winDestroyColormapShadowGDI (ColormapPtr pColormap) -{ - winScreenPriv(pColormap->pScreen); - winCmapPriv(pColormap); - - /* - * Is colormap to be destroyed the default? - * - * Non-default colormaps should have had winUninstallColormap - * called on them before we get here. The default colormap - * will not have had winUninstallColormap called on it. Thus, - * we need to handle the default colormap in a special way. - */ - if (pColormap->flags & IsDefault) - { - winDebug ("winDestroyColormapShadowGDI - Destroying default " - "colormap\n"); - - /* - * FIXME: Walk the list of all screens, popping the default - * palette out of each screen device context. - */ - - /* Pop the palette out of the device context */ - SelectPalette (pScreenPriv->hdcScreen, - GetStockObject (DEFAULT_PALETTE), - FALSE); - - /* Clear our private installed colormap pointer */ - pScreenPriv->pcmapInstalled = NULL; - } - - /* Try to delete the logical palette */ - if (DeleteObject (pCmapPriv->hPalette) == 0) - { - ErrorF ("winDestroyColormap - DeleteObject () failed\n"); - return FALSE; - } - - /* Invalidate the colormap privates */ - pCmapPriv->hPalette = NULL; - - return TRUE; -} - - -/* - * Set engine specific funtions - */ - -Bool -winSetEngineFunctionsShadowGDI (ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; - - /* Set our pointers */ - pScreenPriv->pwinAllocateFB = winAllocateFBShadowGDI; - pScreenPriv->pwinFreeFB = winFreeFBShadowGDI; - pScreenPriv->pwinShadowUpdate = winShadowUpdateGDI; - pScreenPriv->pwinInitScreen = winInitScreenShadowGDI; - pScreenPriv->pwinCloseScreen = winCloseScreenShadowGDI; - pScreenPriv->pwinInitVisuals = winInitVisualsShadowGDI; - pScreenPriv->pwinAdjustVideoMode = winAdjustVideoModeShadowGDI; - if (pScreenInfo->fFullScreen) - pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowFullScreen; - else - pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowWindowed; - pScreenPriv->pwinFinishScreenInit = winFinishScreenInitFB; - pScreenPriv->pwinBltExposedRegions = winBltExposedRegionsShadowGDI; - pScreenPriv->pwinActivateApp = winActivateAppShadowGDI; - pScreenPriv->pwinRedrawScreen = winRedrawScreenShadowGDI; - pScreenPriv->pwinRealizeInstalledPalette = - winRealizeInstalledPaletteShadowGDI; - pScreenPriv->pwinInstallColormap = winInstallColormapShadowGDI; - pScreenPriv->pwinStoreColors = winStoreColorsShadowGDI; - pScreenPriv->pwinCreateColormap = winCreateColormapShadowGDI; - pScreenPriv->pwinDestroyColormap = winDestroyColormapShadowGDI; - pScreenPriv->pwinHotKeyAltTab = (winHotKeyAltTabProcPtr) (void (*)(void))NoopDDA; - pScreenPriv->pwinCreatePrimarySurface - = (winCreatePrimarySurfaceProcPtr) (void (*)(void))NoopDDA; - pScreenPriv->pwinReleasePrimarySurface - = (winReleasePrimarySurfaceProcPtr) (void (*)(void))NoopDDA; -#ifdef XWIN_MULTIWINDOW - pScreenPriv->pwinFinishCreateWindowsWindow = - (winFinishCreateWindowsWindowProcPtr) (void (*)(void))NoopDDA; -#endif - - return TRUE; -} +/*
+ *Copyright (C) 2001-2004 Harold L Hunt II 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 HAROLD L HUNT II 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 Harold L Hunt II
+ *shall not be used in advertising or otherwise to promote the sale, use
+ *or other dealings in this Software without prior written authorization
+ *from Harold L Hunt II.
+ *
+ * Authors: Harold L Hunt II
+ */
+
+#ifdef HAVE_XWIN_CONFIG_H
+#include <xwin-config.h>
+#endif
+#include "win.h"
+
+
+/*
+ * Local function prototypes
+ */
+
+#ifdef XWIN_MULTIWINDOW
+static wBOOL CALLBACK
+winRedrawAllProcShadowGDI (HWND hwnd, LPARAM lParam);
+
+static wBOOL CALLBACK
+winRedrawDamagedWindowShadowGDI (HWND hwnd, LPARAM lParam);
+#endif
+
+static Bool
+winAllocateFBShadowGDI (ScreenPtr pScreen);
+
+static void
+winShadowUpdateGDI (ScreenPtr pScreen,
+ shadowBufPtr pBuf);
+
+static Bool
+winCloseScreenShadowGDI (int nIndex, ScreenPtr pScreen);
+
+static Bool
+winInitVisualsShadowGDI (ScreenPtr pScreen);
+
+static Bool
+winAdjustVideoModeShadowGDI (ScreenPtr pScreen);
+
+static Bool
+winBltExposedRegionsShadowGDI (ScreenPtr pScreen);
+
+static Bool
+winActivateAppShadowGDI (ScreenPtr pScreen);
+
+static Bool
+winRedrawScreenShadowGDI (ScreenPtr pScreen);
+
+static Bool
+winRealizeInstalledPaletteShadowGDI (ScreenPtr pScreen);
+
+static Bool
+winInstallColormapShadowGDI (ColormapPtr pColormap);
+
+static Bool
+winStoreColorsShadowGDI (ColormapPtr pmap,
+ int ndef,
+ xColorItem *pdefs);
+
+static Bool
+winCreateColormapShadowGDI (ColormapPtr pColormap);
+
+static Bool
+winDestroyColormapShadowGDI (ColormapPtr pColormap);
+
+
+/*
+ * Internal function to get the DIB format that is compatible with the screen
+ */
+
+static
+Bool
+winQueryScreenDIBFormat (ScreenPtr pScreen, BITMAPINFOHEADER *pbmih)
+{
+ winScreenPriv(pScreen);
+ HBITMAP hbmp;
+#ifdef WINDBG
+ LPDWORD pdw = NULL;
+#endif
+
+ /* Create a memory bitmap compatible with the screen */
+ hbmp = CreateCompatibleBitmap (pScreenPriv->hdcScreen, 1, 1);
+ if (hbmp == NULL)
+ {
+ ErrorF ("winQueryScreenDIBFormat - 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 (pScreenPriv->hdcScreen,
+ hbmp,
+ 0, 1,
+ NULL,
+ (BITMAPINFO*) pbmih,
+ DIB_RGB_COLORS))
+ {
+ ErrorF ("winQueryScreenDIBFormat - First call to GetDIBits failed\n");
+ DeleteObject (hbmp);
+ return FALSE;
+ }
+
+#ifdef WINDBG
+ /* Get a pointer to bitfields */
+ pdw = (DWORD*) ((CARD8*)pbmih + sizeof (BITMAPINFOHEADER));
+
+ winDebug ("winQueryScreenDIBFormat - First call masks: %08x %08x %08x\n",
+ pdw[0], pdw[1], pdw[2]);
+#endif
+
+ /* Get optimal color table, or the optimal bitfields */
+ if (!GetDIBits (pScreenPriv->hdcScreen,
+ hbmp,
+ 0, 1,
+ NULL,
+ (BITMAPINFO*)pbmih,
+ DIB_RGB_COLORS))
+ {
+ ErrorF ("winQueryScreenDIBFormat - Second call to GetDIBits "
+ "failed\n");
+ DeleteObject (hbmp);
+ return FALSE;
+ }
+
+ /* Free memory */
+ DeleteObject (hbmp);
+
+ return TRUE;
+}
+
+
+/*
+ * Internal function to determine the GDI bits per rgb and bit masks
+ */
+
+static
+Bool
+winQueryRGBBitsAndMasks (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ BITMAPINFOHEADER *pbmih = NULL;
+ Bool fReturn = TRUE;
+ LPDWORD pdw = NULL;
+ DWORD dwRedBits, dwGreenBits, dwBlueBits;
+
+ /* Color masks for 8 bpp are standardized */
+ if (GetDeviceCaps (pScreenPriv->hdcScreen, RASTERCAPS) & RC_PALETTE)
+ {
+ /*
+ * RGB BPP for 8 bit palletes is always 8
+ * and the color masks are always 0.
+ */
+ pScreenPriv->dwBitsPerRGB = 8;
+ pScreenPriv->dwRedMask = 0x0L;
+ pScreenPriv->dwGreenMask = 0x0L;
+ pScreenPriv->dwBlueMask = 0x0L;
+ return TRUE;
+ }
+
+ /* Color masks for 24 bpp are standardized */
+ if (GetDeviceCaps (pScreenPriv->hdcScreen, PLANES)
+ * GetDeviceCaps (pScreenPriv->hdcScreen, BITSPIXEL) == 24)
+ {
+ winDebug ("winQueryRGBBitsAndMasks - GetDeviceCaps (BITSPIXEL) "
+ "returned 24 for the screen. Using default 24bpp masks.\n");
+
+ /* 8 bits per primary color */
+ pScreenPriv->dwBitsPerRGB = 8;
+
+ /* Set screen privates masks */
+ pScreenPriv->dwRedMask = WIN_24BPP_MASK_RED;
+ pScreenPriv->dwGreenMask = WIN_24BPP_MASK_GREEN;
+ pScreenPriv->dwBlueMask = WIN_24BPP_MASK_BLUE;
+
+ return TRUE;
+ }
+
+ /* Allocate a bitmap header and color table */
+ pbmih = (BITMAPINFOHEADER*) malloc (sizeof (BITMAPINFOHEADER)
+ + 256 * sizeof (RGBQUAD));
+ if (pbmih == NULL)
+ {
+ ErrorF ("winQueryRGBBitsAndMasks - malloc failed\n");
+ return FALSE;
+ }
+
+ /* Get screen description */
+ if (winQueryScreenDIBFormat (pScreen, pbmih))
+ {
+ /* Get a pointer to bitfields */
+ pdw = (DWORD*) ((CARD8*)pbmih + sizeof (BITMAPINFOHEADER));
+
+#ifdef WINDBG
+ winDebug ("%s - Masks: %08x %08x %08x\n", __FUNCTION__,
+ pdw[0], pdw[1], pdw[2]);
+ winDebug ("%s - Bitmap: %dx%d %d bpp %d planes\n", __FUNCTION__,
+ pbmih->biWidth, pbmih->biHeight, pbmih->biBitCount, pbmih->biPlanes);
+ winDebug ("%s - Compression: %d %s\n", __FUNCTION__,
+ pbmih->biCompression,
+ (pbmih->biCompression == BI_RGB?"(BI_RGB)":
+ (pbmih->biCompression == BI_RLE8?"(BI_RLE8)":
+ (pbmih->biCompression == BI_RLE4?"(BI_RLE4)":
+ (pbmih->biCompression == BI_BITFIELDS?"(BI_BITFIELDS)":""
+ )))));
+#endif
+
+ /* Handle BI_RGB case, which is returned by Wine */
+ if (pbmih->biCompression == BI_RGB)
+ {
+ dwRedBits = 5;
+ dwGreenBits = 5;
+ dwBlueBits = 5;
+
+ pScreenPriv->dwBitsPerRGB = 5;
+
+ /* Set screen privates masks */
+ pScreenPriv->dwRedMask = 0x7c00;
+ pScreenPriv->dwGreenMask = 0x03e0;
+ pScreenPriv->dwBlueMask = 0x001f;
+ }
+ else
+ {
+ /* Count the number of bits in each mask */
+ dwRedBits = winCountBits (pdw[0]);
+ dwGreenBits = winCountBits (pdw[1]);
+ dwBlueBits = winCountBits (pdw[2]);
+
+ /* Find maximum bits per red, green, blue */
+ if (dwRedBits > dwGreenBits && dwRedBits > dwBlueBits)
+ pScreenPriv->dwBitsPerRGB = dwRedBits;
+ else if (dwGreenBits > dwRedBits && dwGreenBits > dwBlueBits)
+ pScreenPriv->dwBitsPerRGB = dwGreenBits;
+ else
+ pScreenPriv->dwBitsPerRGB = dwBlueBits;
+
+ /* Set screen privates masks */
+ pScreenPriv->dwRedMask = pdw[0];
+ pScreenPriv->dwGreenMask = pdw[1];
+ pScreenPriv->dwBlueMask = pdw[2];
+ }
+ }
+ else
+ {
+ ErrorF ("winQueryRGBBitsAndMasks - winQueryScreenDIBFormat failed\n");
+ free (pbmih);
+ fReturn = FALSE;
+ }
+
+ /* Free memory */
+ free (pbmih);
+
+ return fReturn;
+}
+
+
+#ifdef XWIN_MULTIWINDOW
+/*
+ * Redraw all ---?
+ */
+
+static wBOOL CALLBACK
+winRedrawAllProcShadowGDI (HWND hwnd, LPARAM lParam)
+{
+ if (hwnd == (HWND)lParam)
+ return TRUE;
+ InvalidateRect (hwnd, NULL, FALSE);
+ UpdateWindow (hwnd);
+ return TRUE;
+}
+
+static wBOOL CALLBACK
+winRedrawDamagedWindowShadowGDI (HWND hwnd, LPARAM lParam)
+{
+ BoxPtr pDamage = (BoxPtr)lParam;
+ RECT rcClient, rcDamage, rcRedraw;
+ POINT topLeft, bottomRight;
+
+ if (IsIconic (hwnd))
+ return TRUE; /* Don't care minimized windows */
+
+ /* Convert the damaged area from Screen coords to Client coords */
+ topLeft.x = pDamage->x1; topLeft.y = pDamage->y1;
+ bottomRight.x = pDamage->x2; bottomRight.y = pDamage->y2;
+ topLeft.x += GetSystemMetrics (SM_XVIRTUALSCREEN);
+ bottomRight.x += GetSystemMetrics (SM_XVIRTUALSCREEN);
+ topLeft.y += GetSystemMetrics (SM_YVIRTUALSCREEN);
+ bottomRight.y += GetSystemMetrics (SM_YVIRTUALSCREEN);
+ ScreenToClient (hwnd, &topLeft);
+ ScreenToClient (hwnd, &bottomRight);
+ SetRect (&rcDamage, topLeft.x, topLeft.y, bottomRight.x, bottomRight.y);
+
+ GetClientRect (hwnd, &rcClient);
+
+ if (IntersectRect (&rcRedraw, &rcClient, &rcDamage))
+ {
+ InvalidateRect (hwnd, &rcRedraw, FALSE);
+ UpdateWindow (hwnd);
+ }
+ return TRUE;
+}
+#endif
+
+
+/*
+ * Allocate a DIB for the shadow framebuffer GDI server
+ */
+
+static Bool
+winAllocateFBShadowGDI (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ DIBSECTION dibsection;
+ Bool fReturn = TRUE;
+
+ /* Describe shadow bitmap to be created */
+ pScreenPriv->pbmih->biWidth = pScreenInfo->dwWidth;
+ pScreenPriv->pbmih->biHeight = -pScreenInfo->dwHeight;
+
+ winDebug ("winAllocateFBShadowGDI - Creating DIB with width: %d height: %d "
+ "depth: %d\n",
+ (int) pScreenPriv->pbmih->biWidth, (int) -pScreenPriv->pbmih->biHeight, pScreenPriv->pbmih->biBitCount);
+
+ /* Create a DI shadow bitmap with a bit pointer */
+ pScreenPriv->hbmpShadow = CreateDIBSection (pScreenPriv->hdcScreen,
+ (BITMAPINFO *) pScreenPriv->pbmih,
+ DIB_RGB_COLORS,
+ (VOID**) &pScreenInfo->pfb,
+ NULL,
+ 0);
+ if (pScreenPriv->hbmpShadow == NULL || pScreenInfo->pfb == NULL)
+ {
+ winW32Error ("winAllocateFBShadowGDI - CreateDIBSection failed:");
+ return FALSE;
+ }
+ else
+ {
+ winDebug ("winAllocateFBShadowGDI - Shadow buffer allocated\n");
+ }
+
+ /* Get information about the bitmap that was allocated */
+ GetObject (pScreenPriv->hbmpShadow,
+ sizeof (dibsection),
+ &dibsection);
+
+ /* Print information about bitmap allocated */
+ winDebug ("winAllocateFBShadowGDI - Dibsection width: %d height: %d "
+ "depth: %d size image: %d\n",
+ (int) dibsection.dsBmih.biWidth, (int) dibsection.dsBmih.biHeight,
+ dibsection.dsBmih.biBitCount,
+ (int) dibsection.dsBmih.biSizeImage);
+
+ /* Select the shadow bitmap into the shadow DC */
+ SelectObject (pScreenPriv->hdcShadow,
+ pScreenPriv->hbmpShadow);
+
+ winDebug ("winAllocateFBShadowGDI - Attempting a shadow blit\n");
+
+ /* Do a test blit from the shadow to the screen, I think */
+ fReturn = BitBlt (pScreenPriv->hdcScreen,
+ 0, 0,
+ pScreenInfo->dwWidth, pScreenInfo->dwHeight,
+ pScreenPriv->hdcShadow,
+ 0, 0,
+ SRCCOPY);
+ if (fReturn)
+ {
+ winDebug ("winAllocateFBShadowGDI - Shadow blit success\n");
+ }
+ else
+ {
+ winW32Error ("winAllocateFBShadowGDI - Shadow blit failure\n");
+ /* ago: ignore this error. The blit fails with wine, but does not
+ * cause any problems later. */
+
+ fReturn = TRUE;
+ }
+
+ /* Look for height weirdness */
+ if (dibsection.dsBmih.biHeight < 0)
+ {
+ dibsection.dsBmih.biHeight = -dibsection.dsBmih.biHeight;
+ }
+
+ /* Set screeninfo stride */
+ pScreenInfo->dwStride = ((dibsection.dsBmih.biSizeImage
+ / dibsection.dsBmih.biHeight)
+ * 8) / pScreenInfo->dwBPP;
+
+ winDebug ("winAllocateFBShadowGDI - Created shadow stride: %d\n",
+ (int) pScreenInfo->dwStride);
+
+#ifdef XWIN_MULTIWINDOW
+ /* Redraw all windows */
+ if (pScreenInfo->fMultiWindow)
+ EnumThreadWindows (g_dwCurrentThreadID, winRedrawAllProcShadowGDI, 0);
+#endif
+
+ return fReturn;
+}
+
+static void
+winFreeFBShadowGDI (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+
+ /* Free the shadow bitmap */
+ DeleteObject (pScreenPriv->hbmpShadow);
+
+ /* Invalidate the ScreenInfo's fb pointer */
+ pScreenInfo->pfb = NULL;
+}
+
+/*
+ * Blit the damaged regions of the shadow fb to the screen
+ */
+
+static void
+winShadowUpdateGDI (ScreenPtr pScreen,
+ shadowBufPtr pBuf)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ RegionPtr damage = shadowDamage(pBuf);
+ DWORD dwBox = RegionNumRects (damage);
+ BoxPtr pBox = RegionRects (damage);
+ int x, y, w, h;
+ HRGN hrgnTemp = NULL, hrgnCombined = NULL;
+#ifdef XWIN_UPDATESTATS
+ static DWORD s_dwNonUnitRegions = 0;
+ static DWORD s_dwTotalUpdates = 0;
+ static DWORD s_dwTotalBoxes = 0;
+#endif
+ BoxPtr pBoxExtents = RegionExtents(damage);
+
+ /*
+ * Return immediately if the app is not active
+ * and we are fullscreen, or if we have a bad display depth
+ */
+ if ((!pScreenPriv->fActive && pScreenInfo->fFullScreen)
+ || pScreenPriv->fBadDepth) return;
+
+#ifdef XWIN_UPDATESTATS
+ ++s_dwTotalUpdates;
+ s_dwTotalBoxes += dwBox;
+
+ if (dwBox != 1)
+ {
+ ++s_dwNonUnitRegions;
+ winDebug ("winShadowUpdatGDI - dwBox: %d\n", dwBox);
+ }
+
+ if ((s_dwTotalUpdates % 100) == 0)
+ {
+ winDebug ("winShadowUpdateGDI - %d%% non-unity regions, avg boxes: %d "
+ "nu: %d tu: %d\n",
+ (s_dwNonUnitRegions * 100) / s_dwTotalUpdates,
+ s_dwTotalBoxes / s_dwTotalUpdates,
+ s_dwNonUnitRegions, s_dwTotalUpdates);
+ }
+#endif /* XWIN_UPDATESTATS */
+
+ /*
+ * Handle small regions with multiple blits,
+ * handle large regions by creating a clipping region and
+ * doing a single blit constrained to that clipping region.
+ */
+ if (!pScreenInfo->fMultiWindow &&
+ (pScreenInfo->dwClipUpdatesNBoxes == 0 ||
+ dwBox < pScreenInfo->dwClipUpdatesNBoxes))
+ {
+ /* Loop through all boxes in the damaged region */
+ while (dwBox--)
+ {
+ /*
+ * Calculate x offset, y offset, width, and height for
+ * current damage box
+ */
+ x = pBox->x1;
+ y = pBox->y1;
+ w = pBox->x2 - pBox->x1;
+ h = pBox->y2 - pBox->y1;
+
+ BitBlt (pScreenPriv->hdcScreen,
+ x, y,
+ w, h,
+ pScreenPriv->hdcShadow,
+ x, y,
+ SRCCOPY);
+
+ /* Get a pointer to the next box */
+ ++pBox;
+ }
+ }
+ else if (!pScreenInfo->fMultiWindow)
+ {
+ /* Compute a GDI region from the damaged region */
+ hrgnCombined = CreateRectRgn (pBox->x1, pBox->y1, pBox->x2, pBox->y2);
+ dwBox--;
+ pBox++;
+ while (dwBox--)
+ {
+ hrgnTemp = CreateRectRgn (pBox->x1, pBox->y1, pBox->x2, pBox->y2);
+ CombineRgn (hrgnCombined, hrgnCombined, hrgnTemp, RGN_OR);
+ DeleteObject (hrgnTemp);
+ pBox++;
+ }
+
+ /* Install the GDI region as a clipping region */
+ SelectClipRgn (pScreenPriv->hdcScreen, hrgnCombined);
+ DeleteObject (hrgnCombined);
+ hrgnCombined = NULL;
+
+ /*
+ * Blit the shadow buffer to the screen,
+ * constrained to the clipping region.
+ */
+ BitBlt (pScreenPriv->hdcScreen,
+ pBoxExtents->x1, pBoxExtents->y1,
+ pBoxExtents->x2 - pBoxExtents->x1,
+ pBoxExtents->y2 - pBoxExtents->y1,
+ pScreenPriv->hdcShadow,
+ pBoxExtents->x1, pBoxExtents->y1,
+ SRCCOPY);
+
+ /* Reset the clip region */
+ SelectClipRgn (pScreenPriv->hdcScreen, NULL);
+ }
+
+#ifdef XWIN_MULTIWINDOW
+ /* Redraw all multiwindow windows */
+ if (pScreenInfo->fMultiWindow)
+ EnumThreadWindows (g_dwCurrentThreadID,
+ winRedrawDamagedWindowShadowGDI,
+ (LPARAM)pBoxExtents);
+#endif
+}
+
+
+static Bool
+winInitScreenShadowGDI (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+
+ /* Get device contexts for the screen and shadow bitmap */
+ pScreenPriv->hdcScreen = GetDC (pScreenPriv->hwndScreen);
+ pScreenPriv->hdcShadow = CreateCompatibleDC (pScreenPriv->hdcScreen);
+
+ /* Allocate bitmap info header */
+ pScreenPriv->pbmih = (BITMAPINFOHEADER*) malloc (sizeof (BITMAPINFOHEADER)
+ + 256 * sizeof (RGBQUAD));
+ if (pScreenPriv->pbmih == NULL)
+ {
+ ErrorF ("winInitScreenShadowGDI - malloc () failed\n");
+ return FALSE;
+ }
+
+ /* Query the screen format */
+ if (!winQueryScreenDIBFormat (pScreen, pScreenPriv->pbmih))
+ {
+ ErrorF ("winInitScreenShadowGDI - winQueryScreenDIBFormat failed\n");
+ return FALSE;
+ }
+
+ /* Determine our color masks */
+ if (!winQueryRGBBitsAndMasks (pScreen))
+ {
+ ErrorF ("winInitScreenShadowGDI - winQueryRGBBitsAndMasks failed\n");
+ return FALSE;
+ }
+
+ return winAllocateFBShadowGDI(pScreen);
+}
+
+/* See Porting Layer Definition - p. 33 */
+/*
+ * We wrap whatever CloseScreen procedure was specified by fb;
+ * a pointer to said procedure is stored in our privates.
+ */
+
+static Bool
+winCloseScreenShadowGDI (int nIndex, ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ Bool fReturn;
+
+ winDebug ("winCloseScreenShadowGDI - Freeing screen resources\n");
+
+ /* Flag that the screen is closed */
+ pScreenPriv->fClosed = TRUE;
+ pScreenPriv->fActive = FALSE;
+
+ /* Call the wrapped CloseScreen procedure */
+ WIN_UNWRAP(CloseScreen);
+ if (pScreen->CloseScreen)
+ fReturn = (*pScreen->CloseScreen) (nIndex, pScreen);
+
+ /* Delete the window property */
+ RemoveProp (pScreenPriv->hwndScreen, WIN_SCR_PROP);
+
+ /* Free the shadow DC; which allows the bitmap to be freed */
+ DeleteDC (pScreenPriv->hdcShadow);
+
+ winFreeFBShadowGDI(pScreen);
+
+ /* Free the screen DC */
+ ReleaseDC (pScreenPriv->hwndScreen, pScreenPriv->hdcScreen);
+
+ /* Delete tray icon, if we have one */
+ if (!pScreenInfo->fNoTrayIcon)
+ winDeleteNotifyIcon (pScreenPriv);
+
+ /* Free the exit confirmation dialog box, if it exists */
+ if (g_hDlgExit != NULL)
+ {
+ DestroyWindow (g_hDlgExit);
+ g_hDlgExit = NULL;
+ }
+
+ /* Kill our window */
+ if (pScreenPriv->hwndScreen)
+ {
+ DestroyWindow (pScreenPriv->hwndScreen);
+ pScreenPriv->hwndScreen = NULL;
+ }
+
+#if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW)
+ /* Destroy the thread startup mutex */
+ pthread_mutex_destroy (&pScreenPriv->pmServerStarted);
+#endif
+
+ /* Invalidate our screeninfo's pointer to the screen */
+ pScreenInfo->pScreen = NULL;
+
+ /* Free the screen privates for this screen */
+ free ((pointer) pScreenPriv);
+
+ return fReturn;
+}
+
+
+/*
+ * Tell mi what sort of visuals we need.
+ *
+ * Generally we only need one visual, as our screen can only
+ * handle one format at a time, I believe. You may want
+ * to verify that last sentence.
+ */
+
+static Bool
+winInitVisualsShadowGDI (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+
+ /* Display debugging information */
+ winDebug ("winInitVisualsShadowGDI - Masks %08x %08x %08x BPRGB %d d %d "
+ "bpp %d\n",
+ (unsigned int) pScreenPriv->dwRedMask,
+ (unsigned int) pScreenPriv->dwGreenMask,
+ (unsigned int) pScreenPriv->dwBlueMask,
+ (int) pScreenPriv->dwBitsPerRGB,
+ (int) pScreenInfo->dwDepth,
+ (int) pScreenInfo->dwBPP);
+
+ /* Create a single visual according to the Windows screen depth */
+ switch (pScreenInfo->dwDepth)
+ {
+ case 24:
+ case 16:
+ case 15:
+ /* Setup the real visual */
+ if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth,
+ TrueColorMask,
+ pScreenPriv->dwBitsPerRGB,
+ -1,
+ pScreenPriv->dwRedMask,
+ pScreenPriv->dwGreenMask,
+ pScreenPriv->dwBlueMask))
+ {
+ ErrorF ("winInitVisualsShadowGDI - miSetVisualTypesAndMasks "
+ "failed\n");
+ return FALSE;
+ }
+
+#ifdef XWIN_EMULATEPSEUDO
+ if (!pScreenInfo->fEmulatePseudo)
+ break;
+
+ /* Setup a pseudocolor visual */
+ if (!miSetVisualTypesAndMasks (8,
+ PseudoColorMask,
+ 8,
+ -1,
+ 0,
+ 0,
+ 0))
+ {
+ ErrorF ("winInitVisualsShadowGDI - miSetVisualTypesAndMasks "
+ "failed for PseudoColor\n");
+ return FALSE;
+ }
+#endif
+ break;
+
+ case 8:
+ if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth,
+ PseudoColorMask,
+ pScreenPriv->dwBitsPerRGB,
+ PseudoColor,
+ pScreenPriv->dwRedMask,
+ pScreenPriv->dwGreenMask,
+ pScreenPriv->dwBlueMask))
+ {
+ ErrorF ("winInitVisualsShadowGDI - miSetVisualTypesAndMasks "
+ "failed\n");
+ return FALSE;
+ }
+ break;
+
+ default:
+ ErrorF ("winInitVisualsShadowGDI - Unknown screen depth\n");
+ return FALSE;
+ }
+
+ winDebug ("winInitVisualsShadowGDI - Returning\n");
+
+ return TRUE;
+}
+
+
+/*
+ * Adjust the proposed video mode
+ */
+
+static Bool
+winAdjustVideoModeShadowGDI (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ HDC hdc;
+ DWORD dwBPP;
+
+ hdc = GetDC (NULL);
+
+ /* We're in serious trouble if we can't get a DC */
+ if (hdc == NULL)
+ {
+ ErrorF ("winAdjustVideoModeShadowGDI - GetDC () failed\n");
+ return FALSE;
+ }
+
+ /* Query GDI for current display depth */
+ dwBPP = GetDeviceCaps (hdc, BITSPIXEL);
+
+ /* GDI cannot change the screen depth, so always use GDI's depth */
+ pScreenInfo->dwBPP = dwBPP;
+
+ /* Release our DC */
+ ReleaseDC (NULL, hdc);
+ hdc = NULL;
+
+ return TRUE;
+}
+
+
+/*
+ * Blt exposed regions to the screen
+ */
+
+static Bool
+winBltExposedRegionsShadowGDI (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ winPrivCmapPtr pCmapPriv = NULL;
+ HDC hdcUpdate;
+ PAINTSTRUCT ps;
+
+ /* BeginPaint gives us an hdc that clips to the invalidated region */
+ hdcUpdate = BeginPaint (pScreenPriv->hwndScreen, &ps);
+
+ /* Realize the palette, if we have one */
+ if (pScreenPriv->pcmapInstalled != NULL)
+ {
+ pCmapPriv = winGetCmapPriv (pScreenPriv->pcmapInstalled);
+
+ SelectPalette (hdcUpdate, pCmapPriv->hPalette, FALSE);
+ RealizePalette (hdcUpdate);
+ }
+
+ /* Our BitBlt will be clipped to the invalidated region */
+ BitBlt (hdcUpdate,
+ 0, 0,
+ pScreenInfo->dwWidth, pScreenInfo->dwHeight,
+ pScreenPriv->hdcShadow,
+ 0, 0,
+ SRCCOPY);
+
+ /* EndPaint frees the DC */
+ EndPaint (pScreenPriv->hwndScreen, &ps);
+
+#ifdef XWIN_MULTIWINDOW
+ /* Redraw all windows */
+ if (pScreenInfo->fMultiWindow)
+ EnumThreadWindows(g_dwCurrentThreadID, winRedrawAllProcShadowGDI,
+ (LPARAM)pScreenPriv->hwndScreen);
+#endif
+
+ return TRUE;
+}
+
+
+/*
+ * Do any engine-specific appliation-activation processing
+ */
+
+static Bool
+winActivateAppShadowGDI (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+
+ /*
+ * 2004/04/12 - Harold - We perform the restoring or minimizing
+ * manually for ShadowGDI in fullscreen modes so that this engine
+ * will perform just like ShadowDD and ShadowDDNL in fullscreen mode;
+ * if we do not do this then our fullscreen window will appear in the
+ * z-order when it is deactivated and it can be uncovered by resizing
+ * or minimizing another window that is on top of it, which is not how
+ * the DirectDraw engines work. Therefore we keep this code here to
+ * make sure that all engines work the same in fullscreen mode.
+ */
+
+ /*
+ * Are we active?
+ * Are we fullscreen?
+ */
+ if (pScreenPriv->fActive
+ && pScreenInfo->fFullScreen)
+ {
+ /*
+ * Activating, attempt to bring our window
+ * to the top of the display
+ */
+ ShowWindow (pScreenPriv->hwndScreen, SW_RESTORE);
+ }
+ else if (!pScreenPriv->fActive
+ && pScreenInfo->fFullScreen)
+ {
+ /*
+ * Deactivating, stuff our window onto the
+ * task bar.
+ */
+ ShowWindow (pScreenPriv->hwndScreen, SW_MINIMIZE);
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * Reblit the shadow framebuffer to the screen.
+ */
+
+static Bool
+winRedrawScreenShadowGDI (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+
+ /* Redraw the whole window, to take account for the new colors */
+ BitBlt (pScreenPriv->hdcScreen,
+ 0, 0,
+ pScreenInfo->dwWidth, pScreenInfo->dwHeight,
+ pScreenPriv->hdcShadow,
+ 0, 0,
+ SRCCOPY);
+
+#ifdef XWIN_MULTIWINDOW
+ /* Redraw all windows */
+ if (pScreenInfo->fMultiWindow)
+ EnumThreadWindows(g_dwCurrentThreadID, winRedrawAllProcShadowGDI, 0);
+#endif
+
+ return TRUE;
+}
+
+
+
+/*
+ * Realize the currently installed colormap
+ */
+
+static Bool
+winRealizeInstalledPaletteShadowGDI (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winPrivCmapPtr pCmapPriv = NULL;
+
+ winDebug ("winRealizeInstalledPaletteShadowGDI\n");
+
+ /* Don't do anything if there is not a colormap */
+ if (pScreenPriv->pcmapInstalled == NULL)
+ {
+ winDebug ("winRealizeInstalledPaletteShadowGDI - No colormap "
+ "installed\n");
+ return TRUE;
+ }
+
+ pCmapPriv = winGetCmapPriv (pScreenPriv->pcmapInstalled);
+
+ /* Realize our palette for the screen */
+ if (RealizePalette (pScreenPriv->hdcScreen) == GDI_ERROR)
+ {
+ ErrorF ("winRealizeInstalledPaletteShadowGDI - RealizePalette () "
+ "failed\n");
+ return FALSE;
+ }
+
+ /* Set the DIB color table */
+ if (SetDIBColorTable (pScreenPriv->hdcShadow,
+ 0,
+ WIN_NUM_PALETTE_ENTRIES,
+ pCmapPriv->rgbColors) == 0)
+ {
+ ErrorF ("winRealizeInstalledPaletteShadowGDI - SetDIBColorTable () "
+ "failed\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * Install the specified colormap
+ */
+
+static Bool
+winInstallColormapShadowGDI (ColormapPtr pColormap)
+{
+ ScreenPtr pScreen = pColormap->pScreen;
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ winCmapPriv(pColormap);
+
+ /*
+ * Tell Windows to install the new colormap
+ */
+ if (SelectPalette (pScreenPriv->hdcScreen,
+ pCmapPriv->hPalette,
+ FALSE) == NULL)
+ {
+ ErrorF ("winInstallColormapShadowGDI - SelectPalette () failed\n");
+ return FALSE;
+ }
+
+ /* Realize the palette */
+ if (GDI_ERROR == RealizePalette (pScreenPriv->hdcScreen))
+ {
+ ErrorF ("winInstallColormapShadowGDI - RealizePalette () failed\n");
+ return FALSE;
+ }
+
+ /* Set the DIB color table */
+ if (SetDIBColorTable (pScreenPriv->hdcShadow,
+ 0,
+ WIN_NUM_PALETTE_ENTRIES,
+ pCmapPriv->rgbColors) == 0)
+ {
+ ErrorF ("winInstallColormapShadowGDI - SetDIBColorTable () failed\n");
+ return FALSE;
+ }
+
+ /* Redraw the whole window, to take account for the new colors */
+ BitBlt (pScreenPriv->hdcScreen,
+ 0, 0,
+ pScreenInfo->dwWidth, pScreenInfo->dwHeight,
+ pScreenPriv->hdcShadow,
+ 0, 0,
+ SRCCOPY);
+
+ /* Save a pointer to the newly installed colormap */
+ pScreenPriv->pcmapInstalled = pColormap;
+
+#ifdef XWIN_MULTIWINDOW
+ /* Redraw all windows */
+ if (pScreenInfo->fMultiWindow)
+ EnumThreadWindows (g_dwCurrentThreadID, winRedrawAllProcShadowGDI, 0);
+#endif
+
+ return TRUE;
+}
+
+
+/*
+ * Store the specified colors in the specified colormap
+ */
+
+static Bool
+winStoreColorsShadowGDI (ColormapPtr pColormap,
+ int ndef,
+ xColorItem *pdefs)
+{
+ ScreenPtr pScreen = pColormap->pScreen;
+ winScreenPriv(pScreen);
+ winCmapPriv(pColormap);
+ ColormapPtr curpmap = pScreenPriv->pcmapInstalled;
+
+ /* Put the X colormap entries into the Windows logical palette */
+ if (SetPaletteEntries (pCmapPriv->hPalette,
+ pdefs[0].pixel,
+ ndef,
+ pCmapPriv->peColors + pdefs[0].pixel) == 0)
+ {
+ ErrorF ("winStoreColorsShadowGDI - SetPaletteEntries () failed\n");
+ return FALSE;
+ }
+
+ /* Don't install the Windows palette if the colormap is not installed */
+ if (pColormap != curpmap)
+ {
+ return TRUE;
+ }
+
+ /* Try to install the newly modified colormap */
+ if (!winInstallColormapShadowGDI (pColormap))
+ {
+ ErrorF ("winInstallColormapShadowGDI - winInstallColormapShadowGDI "
+ "failed\n");
+ return FALSE;
+ }
+
+#if 0
+ /* Tell Windows that the palette has changed */
+ RealizePalette (pScreenPriv->hdcScreen);
+
+ /* Set the DIB color table */
+ if (SetDIBColorTable (pScreenPriv->hdcShadow,
+ pdefs[0].pixel,
+ ndef,
+ pCmapPriv->rgbColors + pdefs[0].pixel) == 0)
+ {
+ ErrorF ("winInstallColormapShadowGDI - SetDIBColorTable () failed\n");
+ return FALSE;
+ }
+
+ /* Save a pointer to the newly installed colormap */
+ pScreenPriv->pcmapInstalled = pColormap;
+#endif
+
+ return TRUE;
+}
+
+
+/*
+ * Colormap initialization procedure
+ */
+
+static Bool
+winCreateColormapShadowGDI (ColormapPtr pColormap)
+{
+ LPLOGPALETTE lpPaletteNew = NULL;
+ DWORD dwEntriesMax;
+ VisualPtr pVisual;
+ HPALETTE hpalNew = NULL;
+ winCmapPriv(pColormap);
+
+ /* Get a pointer to the visual that the colormap belongs to */
+ pVisual = pColormap->pVisual;
+
+ /* Get the maximum number of palette entries for this visual */
+ dwEntriesMax = pVisual->ColormapEntries;
+
+ /* Allocate a Windows logical color palette with max entries */
+ lpPaletteNew = malloc (sizeof (LOGPALETTE)
+ + (dwEntriesMax - 1) * sizeof (PALETTEENTRY));
+ if (lpPaletteNew == NULL)
+ {
+ ErrorF ("winCreateColormapShadowGDI - Couldn't allocate palette "
+ "with %d entries\n",
+ (int) dwEntriesMax);
+ return FALSE;
+ }
+
+ /* Zero out the colormap */
+ ZeroMemory (lpPaletteNew, sizeof (LOGPALETTE)
+ + (dwEntriesMax - 1) * sizeof (PALETTEENTRY));
+
+ /* Set the logical palette structure */
+ lpPaletteNew->palVersion = 0x0300;
+ lpPaletteNew->palNumEntries = dwEntriesMax;
+
+ /* Tell Windows to create the palette */
+ hpalNew = CreatePalette (lpPaletteNew);
+ if (hpalNew == NULL)
+ {
+ ErrorF ("winCreateColormapShadowGDI - CreatePalette () failed\n");
+ free (lpPaletteNew);
+ return FALSE;
+ }
+
+ /* Save the Windows logical palette handle in the X colormaps' privates */
+ pCmapPriv->hPalette = hpalNew;
+
+ /* Free the palette initialization memory */
+ free (lpPaletteNew);
+
+ return TRUE;
+}
+
+
+/*
+ * Colormap destruction procedure
+ */
+
+static Bool
+winDestroyColormapShadowGDI (ColormapPtr pColormap)
+{
+ winScreenPriv(pColormap->pScreen);
+ winCmapPriv(pColormap);
+
+ /*
+ * Is colormap to be destroyed the default?
+ *
+ * Non-default colormaps should have had winUninstallColormap
+ * called on them before we get here. The default colormap
+ * will not have had winUninstallColormap called on it. Thus,
+ * we need to handle the default colormap in a special way.
+ */
+ if (pColormap->flags & IsDefault)
+ {
+ winDebug ("winDestroyColormapShadowGDI - Destroying default "
+ "colormap\n");
+
+ /*
+ * FIXME: Walk the list of all screens, popping the default
+ * palette out of each screen device context.
+ */
+
+ /* Pop the palette out of the device context */
+ SelectPalette (pScreenPriv->hdcScreen,
+ GetStockObject (DEFAULT_PALETTE),
+ FALSE);
+
+ /* Clear our private installed colormap pointer */
+ pScreenPriv->pcmapInstalled = NULL;
+ }
+
+ /* Try to delete the logical palette */
+ if (DeleteObject (pCmapPriv->hPalette) == 0)
+ {
+ ErrorF ("winDestroyColormap - DeleteObject () failed\n");
+ return FALSE;
+ }
+
+ /* Invalidate the colormap privates */
+ pCmapPriv->hPalette = NULL;
+
+ return TRUE;
+}
+
+
+/*
+ * Set engine specific funtions
+ */
+
+Bool
+winSetEngineFunctionsShadowGDI (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+
+ /* Set our pointers */
+ pScreenPriv->pwinAllocateFB = winAllocateFBShadowGDI;
+ pScreenPriv->pwinFreeFB = winFreeFBShadowGDI;
+ pScreenPriv->pwinShadowUpdate = winShadowUpdateGDI;
+ pScreenPriv->pwinInitScreen = winInitScreenShadowGDI;
+ pScreenPriv->pwinCloseScreen = winCloseScreenShadowGDI;
+ pScreenPriv->pwinInitVisuals = winInitVisualsShadowGDI;
+ pScreenPriv->pwinAdjustVideoMode = winAdjustVideoModeShadowGDI;
+ if (pScreenInfo->fFullScreen)
+ pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowFullScreen;
+ else
+ pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowWindowed;
+ pScreenPriv->pwinFinishScreenInit = winFinishScreenInitFB;
+ pScreenPriv->pwinBltExposedRegions = winBltExposedRegionsShadowGDI;
+ pScreenPriv->pwinActivateApp = winActivateAppShadowGDI;
+ pScreenPriv->pwinRedrawScreen = winRedrawScreenShadowGDI;
+ pScreenPriv->pwinRealizeInstalledPalette =
+ winRealizeInstalledPaletteShadowGDI;
+ pScreenPriv->pwinInstallColormap = winInstallColormapShadowGDI;
+ pScreenPriv->pwinStoreColors = winStoreColorsShadowGDI;
+ pScreenPriv->pwinCreateColormap = winCreateColormapShadowGDI;
+ pScreenPriv->pwinDestroyColormap = winDestroyColormapShadowGDI;
+ pScreenPriv->pwinHotKeyAltTab = (winHotKeyAltTabProcPtr) (void (*)(void))NoopDDA;
+ pScreenPriv->pwinCreatePrimarySurface
+ = (winCreatePrimarySurfaceProcPtr) (void (*)(void))NoopDDA;
+ pScreenPriv->pwinReleasePrimarySurface
+ = (winReleasePrimarySurfaceProcPtr) (void (*)(void))NoopDDA;
+#ifdef XWIN_MULTIWINDOW
+ pScreenPriv->pwinFinishCreateWindowsWindow =
+ (winFinishCreateWindowsWindowProcPtr) (void (*)(void))NoopDDA;
+#endif
+
+ return TRUE;
+}
diff --git a/xorg-server/hw/xwin/winvideo.c b/xorg-server/hw/xwin/winvideo.c index 998a3face..10f48b564 100644 --- a/xorg-server/hw/xwin/winvideo.c +++ b/xorg-server/hw/xwin/winvideo.c @@ -69,8 +69,6 @@ winInitVideo (ScreenPtr pScreen) #include <X11/extensions/Xv.h>
#endif
-#include "win.h"
-
#if 0
diff --git a/xorg-server/hw/xwin/winwin32rootless.c b/xorg-server/hw/xwin/winwin32rootless.c index e1c2da7f4..2f8ace57a 100644 --- a/xorg-server/hw/xwin/winwin32rootless.c +++ b/xorg-server/hw/xwin/winwin32rootless.c @@ -340,8 +340,8 @@ void winMWExtWMDestroyFrame (RootlessFrameID wid)
{
win32RootlessWindowPtr pRLWinPriv = (win32RootlessWindowPtr) wid;
- HICON hiconClass;
- HICON hiconSmClass;
+ HICON hIcon;
+ HICON hIconSm;
HMODULE hInstance;
int iReturn;
char pszClass[CLASS_NAME_LENGTH];
@@ -351,8 +351,8 @@ winMWExtWMDestroyFrame (RootlessFrameID wid) /* Store the info we need to destroy after this window is gone */
hInstance = (HINSTANCE) GetClassLongPtr (pRLWinPriv->hWnd, GCLP_HMODULE);
- hiconClass = (HICON) GetClassLongPtr (pRLWinPriv->hWnd, GCLP_HICON);
- hiconSmClass = (HICON) GetClassLongPtr (pRLWinPriv->hWnd, GCLP_HICONSM);
+ 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;
@@ -367,7 +367,7 @@ winMWExtWMDestroyFrame (RootlessFrameID wid) winDebug ("winMWExtWMDestroyFrame - Unregistering %s: ", pszClass);
iReturn = UnregisterClass (pszClass, hInstance);
- winDebug ("winMWExtWMDestroyFramew - %d Deleting Icon: ", iReturn);
+ winDebug ("winMWExtWMDestroyFramew - Deleting Icon\n");
}
winDestroyIcon(hiconClass);
|