aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libX11/src/KeyBind.c1
-rw-r--r--mesalib/src/mapi/glapi/gen/Makefile3
-rw-r--r--mesalib/src/mesa/main/get.c14
-rw-r--r--mesalib/src/mesa/main/mtypes.h5
-rw-r--r--mesalib/src/mesa/main/pixel.c2
-rw-r--r--mesalib/src/mesa/main/state.c2
-rw-r--r--mesalib/src/mesa/main/teximage.c10
-rw-r--r--pixman/test/composite.c17
-rw-r--r--pixman/test/stress-test.c37
-rw-r--r--pixman/test/utils.c10
-rw-r--r--pixman/test/utils.h3
-rw-r--r--xorg-server/Xext/panoramiX.c16
-rw-r--r--xorg-server/Xext/panoramiX.h4
-rw-r--r--xorg-server/Xext/panoramiXprocs.c50
-rw-r--r--xorg-server/Xext/panoramiXsrv.h11
-rw-r--r--xorg-server/Xext/shm.c6
-rw-r--r--xorg-server/Xext/xvdisp.c4
-rw-r--r--xorg-server/composite/compext.c5
-rw-r--r--xorg-server/dix/events.c10
-rw-r--r--xorg-server/dix/window.c4
-rw-r--r--xorg-server/hw/dmx/dmxcb.c445
-rw-r--r--xorg-server/hw/dmx/dmxextension.c3240
-rw-r--r--xorg-server/hw/dmx/dmxgcops.c2
-rw-r--r--xorg-server/render/render.c25
-rw-r--r--xorg-server/xkeyboard-config/rules/base.extras.xml.in34
-rw-r--r--xorg-server/xkeyboard-config/rules/base.xml.in4
-rw-r--r--xorg-server/xkeyboard-config/symbols/in2
-rw-r--r--xorg-server/xkeyboard-config/symbols/lk65
-rw-r--r--xorg-server/xkeyboard-config/symbols/lt22
-rw-r--r--xorg-server/xkeyboard-config/symbols/nbsp16
30 files changed, 2064 insertions, 2005 deletions
diff --git a/libX11/src/KeyBind.c b/libX11/src/KeyBind.c
index 6eb84328c..82d85fbe7 100644
--- a/libX11/src/KeyBind.c
+++ b/libX11/src/KeyBind.c
@@ -44,6 +44,7 @@ in this Software without prior written authorization from The Open Group.
#define XK_CAUCASUS
#define XK_VIETNAMESE
#define XK_XKB_KEYS
+#define XK_SINHALA
#include <X11/keysymdef.h>
#include <stdio.h>
diff --git a/mesalib/src/mapi/glapi/gen/Makefile b/mesalib/src/mapi/glapi/gen/Makefile
index 1e4fee6aa..867cc3e29 100644
--- a/mesalib/src/mapi/glapi/gen/Makefile
+++ b/mesalib/src/mapi/glapi/gen/Makefile
@@ -41,8 +41,6 @@ XORG_GLX_DIR = $(XORG_BASE)/glx
XORG_GLAPI_DIR = $(XORG_BASE)/glx
XORG_GLAPI_FILES = \
- $(XORG_GLAPI_DIR)/glapi.h \
- $(XORG_GLAPI_DIR)/glapi.c \
$(XORG_GLAPI_DIR)/glapi_getproc.c \
$(XORG_GLAPI_DIR)/glapi_nop.c \
$(XORG_GLAPI_DIR)/glthread.c \
@@ -50,7 +48,6 @@ XORG_GLAPI_FILES = \
XORG_GLAPI_OUTPUTS = \
$(XORG_GLAPI_DIR)/glprocs.h \
- $(XORG_GLAPI_DIR)/glapitemp.h \
$(XORG_GLAPI_DIR)/glapioffsets.h \
$(XORG_GLAPI_DIR)/glapitable.h \
$(XORG_GLAPI_DIR)/glapidispatch.h
diff --git a/mesalib/src/mesa/main/get.c b/mesalib/src/mesa/main/get.c
index a3cae1cbc..206c66062 100644
--- a/mesalib/src/mesa/main/get.c
+++ b/mesalib/src/mesa/main/get.c
@@ -572,7 +572,7 @@ static const struct value_desc values[] = {
{ GL_VERTEX_ARRAY_SIZE, ARRAY_INT(Vertex.Size), NO_EXTRA },
{ GL_VERTEX_ARRAY_TYPE, ARRAY_ENUM(Vertex.Type), NO_EXTRA },
{ GL_VERTEX_ARRAY_STRIDE, ARRAY_INT(Vertex.Stride), NO_EXTRA },
- { GL_NORMAL_ARRAY, ARRAY_ENUM(Normal.Enabled), NO_EXTRA },
+ { GL_NORMAL_ARRAY, ARRAY_BOOL(Normal.Enabled), NO_EXTRA },
{ GL_NORMAL_ARRAY_TYPE, ARRAY_ENUM(Normal.Type), NO_EXTRA },
{ GL_NORMAL_ARRAY_STRIDE, ARRAY_INT(Normal.Stride), NO_EXTRA },
{ GL_COLOR_ARRAY, ARRAY_BOOL(Color.Enabled), NO_EXTRA },
@@ -582,11 +582,11 @@ static const struct value_desc values[] = {
{ GL_TEXTURE_COORD_ARRAY,
LOC_CUSTOM, TYPE_BOOLEAN, offsetof(struct gl_client_array, Enabled), NO_EXTRA },
{ GL_TEXTURE_COORD_ARRAY_SIZE,
- LOC_CUSTOM, TYPE_BOOLEAN, offsetof(struct gl_client_array, Size), NO_EXTRA },
+ LOC_CUSTOM, TYPE_INT, offsetof(struct gl_client_array, Size), NO_EXTRA },
{ GL_TEXTURE_COORD_ARRAY_TYPE,
- LOC_CUSTOM, TYPE_BOOLEAN, offsetof(struct gl_client_array, Type), NO_EXTRA },
+ LOC_CUSTOM, TYPE_ENUM, offsetof(struct gl_client_array, Type), NO_EXTRA },
{ GL_TEXTURE_COORD_ARRAY_STRIDE,
- LOC_CUSTOM, TYPE_BOOLEAN, offsetof(struct gl_client_array, Stride), NO_EXTRA },
+ LOC_CUSTOM, TYPE_INT, offsetof(struct gl_client_array, Stride), NO_EXTRA },
/* GL_ARB_ES2_compatibility */
{ GL_SHADER_COMPILER, CONST(1), extra_ARB_ES2_compatibility },
@@ -1367,7 +1367,7 @@ void _mesa_init_get_hash(struct gl_context *ctx)
static void
find_custom_value(struct gl_context *ctx, const struct value_desc *d, union value *v)
{
- struct gl_buffer_object *buffer_obj;
+ struct gl_buffer_object **buffer_obj;
struct gl_client_array *array;
GLuint unit, *p;
@@ -1569,9 +1569,9 @@ find_custom_value(struct gl_context *ctx, const struct value_desc *d, union valu
case GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB:
case GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB:
case GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB:
- buffer_obj = (struct gl_buffer_object *)
+ buffer_obj = (struct gl_buffer_object **)
((char *) ctx->Array.ArrayObj + d->offset);
- v->value_int = buffer_obj->Name;
+ v->value_int = (*buffer_obj)->Name;
break;
case GL_ARRAY_BUFFER_BINDING_ARB:
v->value_int = ctx->Array.ArrayBufferObj->Name;
diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h
index c6678b85c..94e449ae8 100644
--- a/mesalib/src/mesa/main/mtypes.h
+++ b/mesalib/src/mesa/main/mtypes.h
@@ -3022,11 +3022,6 @@ struct gl_matrix_stack
_NEW_POINT | \
_NEW_PROGRAM | \
_NEW_MODELVIEW)
-
-#define _MESA_NEW_NEED_NORMALS (_NEW_LIGHT | \
- _NEW_TEXTURE)
-
-#define _MESA_NEW_TRANSFER_STATE (_NEW_PIXEL)
/*@}*/
diff --git a/mesalib/src/mesa/main/pixel.c b/mesalib/src/mesa/main/pixel.c
index 55e368c36..5a14eb2d4 100644
--- a/mesalib/src/mesa/main/pixel.c
+++ b/mesalib/src/mesa/main/pixel.c
@@ -617,7 +617,7 @@ update_image_transfer_state(struct gl_context *ctx)
*/
void _mesa_update_pixel( struct gl_context *ctx, GLuint new_state )
{
- if (new_state & _MESA_NEW_TRANSFER_STATE)
+ if (new_state & _NEW_PIXEL)
update_image_transfer_state(ctx);
}
diff --git a/mesalib/src/mesa/main/state.c b/mesalib/src/mesa/main/state.c
index f50f2af1e..70f8154e8 100644
--- a/mesalib/src/mesa/main/state.c
+++ b/mesalib/src/mesa/main/state.c
@@ -602,7 +602,7 @@ _mesa_update_state_locked( struct gl_context *ctx )
if (new_state & (_NEW_STENCIL | _NEW_BUFFERS))
_mesa_update_stencil( ctx );
- if (new_state & _MESA_NEW_TRANSFER_STATE)
+ if (new_state & _NEW_PIXEL)
_mesa_update_pixel( ctx, new_state );
if (new_state & _DD_NEW_SEPARATE_SPECULAR)
diff --git a/mesalib/src/mesa/main/teximage.c b/mesalib/src/mesa/main/teximage.c
index f4d7a4212..351dccc16 100644
--- a/mesalib/src/mesa/main/teximage.c
+++ b/mesalib/src/mesa/main/teximage.c
@@ -55,9 +55,7 @@
* In particular, we care about pixel transfer state and buffer state
* (such as glReadBuffer to make sure we read from the right renderbuffer).
*/
-#define NEW_COPY_TEX_STATE (_MESA_NEW_TRANSFER_STATE | \
- _NEW_BUFFERS | \
- _NEW_PIXEL)
+#define NEW_COPY_TEX_STATE (_NEW_BUFFERS | _NEW_PIXEL)
@@ -2434,7 +2432,7 @@ teximage(struct gl_context *ctx, GLuint dims,
return; /* error was recorded */
}
- if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
+ if (ctx->NewState & _NEW_PIXEL)
_mesa_update_state(ctx);
texObj = _mesa_get_current_tex_object(ctx, target);
@@ -2580,7 +2578,7 @@ _mesa_EGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image)
return;
}
- if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
+ if (ctx->NewState & _NEW_PIXEL)
_mesa_update_state(ctx);
texObj = _mesa_get_current_tex_object(ctx, target);
@@ -2637,7 +2635,7 @@ texsubimage(struct gl_context *ctx, GLuint dims, GLenum target, GLint level,
return;
}
- if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
+ if (ctx->NewState & _NEW_PIXEL)
_mesa_update_state(ctx);
if (subtexture_error_check(ctx, dims, target, level, xoffset, yoffset, zoffset,
diff --git a/pixman/test/composite.c b/pixman/test/composite.c
index 50a3c0644..5e486708d 100644
--- a/pixman/test/composite.c
+++ b/pixman/test/composite.c
@@ -868,7 +868,7 @@ main (int argc, char **argv)
{
#define N_TESTS (8 * 1024 * 1024)
int result = 0;
- int i;
+ uint32_t i;
if (argc > 1)
{
@@ -890,15 +890,22 @@ main (int argc, char **argv)
}
}
+ uint32_t seed;
+
+ if (getenv ("PIXMAN_RANDOMIZE_TESTS"))
+ seed = get_random_seed();
+ else
+ seed = 1;
+
#ifdef USE_OPENMP
-# pragma omp parallel for default(none) shared(result) shared(argv)
+# pragma omp parallel for default(none) shared(result, argv, seed)
#endif
- for (i = 1; i <= N_TESTS; ++i)
+ for (i = seed; i <= N_TESTS; ++i)
{
if (!result && !run_test (i))
{
- printf ("Test %d failed.\n", i);
-
+ printf ("Test 0x%08X failed.\n", i);
+
result = i;
}
}
diff --git a/pixman/test/stress-test.c b/pixman/test/stress-test.c
index a51737ea0..c694bde8c 100644
--- a/pixman/test/stress-test.c
+++ b/pixman/test/stress-test.c
@@ -1,4 +1,6 @@
+#include <stdio.h>
#include "utils.h"
+#include <sys/types.h>
#if 0
#define fence_malloc malloc
@@ -730,11 +732,17 @@ static const pixman_op_t op_list[] =
};
static void
-run_test (uint32_t seed)
+run_test (uint32_t seed, pixman_bool_t verbose, uint32_t mod)
{
pixman_image_t *source, *mask, *dest;
pixman_op_t op;
+ if (verbose)
+ {
+ if (mod == 0 || (seed % mod) == 0)
+ printf ("Seed 0x%08x\n", seed);
+ }
+
lcg_srand (seed);
source = create_random_image ();
@@ -787,6 +795,7 @@ main (int argc, char **argv)
uint32_t seed = 1;
uint32_t n_tests = 0xffffffff;
uint32_t mod = 0;
+ pixman_bool_t use_threads = TRUE;
uint32_t i;
pixman_disable_out_of_bounds_workaround ();
@@ -811,6 +820,7 @@ main (int argc, char **argv)
else if (strcmp (argv[i], "-s") == 0 && i + 1 < argc)
{
get_int (argv[i + 1], &seed);
+ use_threads = FALSE;
i++;
}
else if (strcmp (argv[i], "-n") == 0 && i + 1 < argc)
@@ -825,7 +835,7 @@ main (int argc, char **argv)
printf ("Options:\n\n"
"-n <number> Number of tests to run\n"
- "-s <seed> Seed of first test\n"
+ "-s <seed> Seed of first test (ignored if PIXMAN_RANDOMIZE_TESTS is set)\n"
"-v Print out seeds\n"
"-v <n> Print out every n'th seed\n\n");
@@ -836,19 +846,24 @@ main (int argc, char **argv)
if (n_tests == 0xffffffff)
n_tests = 8000;
- /* FIXME: seed 2005763 fails in set_lum() with divide by zero */
+ if (getenv ("PIXMAN_RANDOMIZE_TESTS"))
+ {
+ seed = get_random_seed();
+ printf ("First seed: 0x%08x\n", seed);
+ }
+
+ if (use_threads)
+ {
#ifdef USE_OPENMP
# pragma omp parallel for default(none) shared(verbose, n_tests, mod, seed)
#endif
- for (i = seed; i < seed + n_tests; ++i)
+ for (i = seed; i < seed + n_tests; ++i)
+ run_test (i, verbose, mod);
+ }
+ else
{
- if (verbose)
- {
- if (mod == 0 || (i % mod) == 0)
- printf ("Seed %d\n", i);
- }
-
- run_test (i);
+ for (i = seed; i < seed + n_tests; ++i)
+ run_test (i, verbose, mod);
}
return 0;
diff --git a/pixman/test/utils.c b/pixman/test/utils.c
index ee68d272c..2f1565840 100644
--- a/pixman/test/utils.c
+++ b/pixman/test/utils.c
@@ -455,6 +455,16 @@ gettime (void)
#endif
}
+uint32_t
+get_random_seed (void)
+{
+ double d = gettime();
+
+ lcg_srand (*(uint32_t *)&d);
+
+ return lcg_rand_u32 ();
+}
+
static const char *global_msg;
static void
diff --git a/pixman/test/utils.h b/pixman/test/utils.h
index 5643c1228..8f0e0c0e5 100644
--- a/pixman/test/utils.h
+++ b/pixman/test/utils.h
@@ -79,6 +79,9 @@ make_random_bytes (int n_bytes);
double
gettime (void);
+uint32_t
+get_random_seed (void);
+
/* main body of the fuzzer test */
int
fuzzer_test_main (const char *test_name,
diff --git a/xorg-server/Xext/panoramiX.c b/xorg-server/Xext/panoramiX.c
index 309c09cda..27e54e2e4 100644
--- a/xorg-server/Xext/panoramiX.c
+++ b/xorg-server/Xext/panoramiX.c
@@ -393,7 +393,7 @@ static void XineramaInitData(ScreenPtr pScreen)
int i, w, h;
RegionNull(&PanoramiXScreenRegion);
- for (i = 0; i < PanoramiXNumScreens; i++) {
+ FOR_NSCREENS(i) {
BoxRec TheBox;
RegionRec ScreenRegion;
@@ -413,7 +413,7 @@ static void XineramaInitData(ScreenPtr pScreen)
PanoramiXPixWidth = screenInfo.screens[0]->x + screenInfo.screens[0]->width;
PanoramiXPixHeight = screenInfo.screens[0]->y + screenInfo.screens[0]->height;
- for (i = 1; i < PanoramiXNumScreens; i++) {
+ FOR_NSCREENS_FORWARD_SKIP(i) {
pScreen = screenInfo.screens[i];
w = pScreen->x + pScreen->width;
h = pScreen->y + pScreen->height;
@@ -478,7 +478,7 @@ void PanoramiXExtensionInit(int argc, char *argv[])
* run in non-PanoramiXeen mode.
*/
- for (i = 0; i < PanoramiXNumScreens; i++) {
+ FOR_NSCREENS(i) {
pScreen = screenInfo.screens[i];
pScreenPriv = malloc(sizeof(PanoramiXScreenRec));
dixSetPrivate(&pScreen->devPrivates, PanoramiXScreenKey,
@@ -740,7 +740,7 @@ PanoramiXMaybeAddDepth(DepthPtr pDepth)
int j, k;
Bool found = FALSE;
- for (j = 1; j < PanoramiXNumScreens; j++) {
+ FOR_NSCREENS_FORWARD_SKIP(j) {
pScreen = screenInfo.screens[j];
for (k = 0; k < pScreen->numDepths; k++) {
if (pScreen->allowedDepths[k].depth == pDepth->depth) {
@@ -773,7 +773,7 @@ PanoramiXMaybeAddVisual(VisualPtr pVisual)
int j, k;
Bool found = FALSE;
- for (j = 1; j < PanoramiXNumScreens; j++) {
+ FOR_NSCREENS_FORWARD_SKIP(j) {
pScreen = screenInfo.screens[j];
found = FALSE;
@@ -836,7 +836,7 @@ PanoramiXConsolidate(void)
saver = malloc(sizeof(PanoramiXRes));
saver->type = XRT_WINDOW;
- for (i = 0; i < PanoramiXNumScreens; i++) {
+ FOR_NSCREENS(i) {
ScreenPtr pScreen = screenInfo.screens[i];
root->info[i].id = pScreen->root->drawable.id;
root->u.win.class = InputOutput;
@@ -1074,7 +1074,7 @@ ProcXineramaQueryScreens(ClientPtr client)
xXineramaScreenInfo scratch;
int i;
- for(i = 0; i < PanoramiXNumScreens; i++) {
+ FOR_NSCREENS(i) {
scratch.x_org = screenInfo.screens[i]->x;
scratch.y_org = screenInfo.screens[i]->y;
scratch.width = screenInfo.screens[i]->width;
@@ -1179,7 +1179,7 @@ XineramaGetImageData(
depth = (format == XYPixmap) ? 1 : pDraw->depth;
- for(i = 0; i < PanoramiXNumScreens; i++) {
+ FOR_NSCREENS(i) {
BoxRec TheBox;
ScreenPtr pScreen;
pDraw = pDrawables[i];
diff --git a/xorg-server/Xext/panoramiX.h b/xorg-server/Xext/panoramiX.h
index 1bf6194c6..11e93f4fc 100644
--- a/xorg-server/Xext/panoramiX.h
+++ b/xorg-server/Xext/panoramiX.h
@@ -44,7 +44,7 @@ Equipment Corporation.
#include <X11/extensions/panoramiXproto.h>
#undef _PANORAMIX_SERVER
#include "gcstruct.h"
-
+#include "dixstruct.h"
typedef struct _PanoramiXInfo {
XID id ;
@@ -70,9 +70,11 @@ typedef struct {
} PanoramiXRes;
#define FOR_NSCREENS_FORWARD(j) for(j = 0; j < PanoramiXNumScreens; j++)
+#define FOR_NSCREENS_FORWARD_SKIP(j) for(j = 1; j < PanoramiXNumScreens; j++)
#define FOR_NSCREENS_BACKWARD(j) for(j = PanoramiXNumScreens - 1; j >= 0; j--)
#define FOR_NSCREENS(j) FOR_NSCREENS_FORWARD(j)
#define IS_SHARED_PIXMAP(r) (((r)->type == XRT_PIXMAP) && (r)->u.pix.shared)
+#define IS_ROOT_DRAWABLE(d) (((d)->type == XRT_WINDOW) && (d)->u.win.root)
#endif /* _PANORAMIX_H_ */
diff --git a/xorg-server/Xext/panoramiXprocs.c b/xorg-server/Xext/panoramiXprocs.c
index 615246bab..62798fb1d 100644
--- a/xorg-server/Xext/panoramiXprocs.c
+++ b/xorg-server/Xext/panoramiXprocs.c
@@ -120,9 +120,7 @@ int PanoramiXCreateWindow(ClientPtr client)
newWin->u.win.visibility = VisibilityNotViewable;
newWin->u.win.class = stuff->class;
newWin->u.win.root = FALSE;
- newWin->info[0].id = stuff->wid;
- for(j = 1; j < PanoramiXNumScreens; j++)
- newWin->info[j].id = FakeClientID(client->index);
+ panoramix_setup_ids(newWin, client, stuff->wid);
if (stuff->class == InputOnly)
stuff->visual = CopyFromParent;
@@ -663,9 +661,7 @@ int PanoramiXCreatePixmap(ClientPtr client)
newPix->type = XRT_PIXMAP;
newPix->u.pix.shared = FALSE;
- newPix->info[0].id = stuff->pid;
- for(j = 1; j < PanoramiXNumScreens; j++)
- newPix->info[j].id = FakeClientID(client->index);
+ panoramix_setup_ids(newPix, client, stuff->pid);
FOR_NSCREENS_BACKWARD(j) {
stuff->pid = newPix->info[j].id;
@@ -767,9 +763,7 @@ int PanoramiXCreateGC(ClientPtr client)
return BadAlloc;
newGC->type = XRT_GC;
- newGC->info[0].id = stuff->gc;
- for(j = 1; j < PanoramiXNumScreens; j++)
- newGC->info[j].id = FakeClientID(client->index);
+ panoramix_setup_ids(newGC, client, stuff->gc);
FOR_NSCREENS_BACKWARD(j) {
stuff->gc = newGC->info[j].id;
@@ -1334,7 +1328,7 @@ int PanoramiXPolyLine(ClientPtr client)
if (result != Success)
return result;
- isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
+ isRoot = IS_ROOT_DRAWABLE(draw);
npoint = bytes_to_int32((client->req_len << 2) - sizeof(xPolyLineReq));
if (npoint > 0){
origPts = malloc(npoint * sizeof(xPoint));
@@ -1394,7 +1388,7 @@ int PanoramiXPolySegment(ClientPtr client)
if (result != Success)
return result;
- isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
+ isRoot = IS_ROOT_DRAWABLE(draw);
nsegs = (client->req_len << 2) - sizeof(xPolySegmentReq);
if(nsegs & 4) return BadLength;
@@ -1457,7 +1451,7 @@ int PanoramiXPolyRectangle(ClientPtr client)
if (result != Success)
return result;
- isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
+ isRoot = IS_ROOT_DRAWABLE(draw);
nrects = (client->req_len << 2) - sizeof(xPolyRectangleReq);
if(nrects & 4) return BadLength;
@@ -1519,7 +1513,7 @@ int PanoramiXPolyArc(ClientPtr client)
if (result != Success)
return result;
- isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
+ isRoot = IS_ROOT_DRAWABLE(draw);
narcs = (client->req_len << 2) - sizeof(xPolyArcReq);
if(narcs % sizeof(xArc)) return BadLength;
@@ -1579,7 +1573,7 @@ int PanoramiXFillPoly(ClientPtr client)
if (result != Success)
return result;
- isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
+ isRoot = IS_ROOT_DRAWABLE(draw);
count = bytes_to_int32((client->req_len << 2) - sizeof(xFillPolyReq));
if (count > 0){
@@ -1640,7 +1634,7 @@ int PanoramiXPolyFillRectangle(ClientPtr client)
if (result != Success)
return result;
- isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
+ isRoot = IS_ROOT_DRAWABLE(draw);
things = (client->req_len << 2) - sizeof(xPolyFillRectangleReq);
if(things & 4) return BadLength;
@@ -1701,7 +1695,7 @@ int PanoramiXPolyFillArc(ClientPtr client)
if (result != Success)
return result;
- isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
+ isRoot = IS_ROOT_DRAWABLE(draw);
narcs = (client->req_len << 2) - sizeof(xPolyFillArcReq);
if (narcs % sizeof(xArc)) return BadLength;
@@ -1761,7 +1755,7 @@ int PanoramiXPutImage(ClientPtr client)
if (result != Success)
return result;
- isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
+ isRoot = IS_ROOT_DRAWABLE(draw);
orig_x = stuff->dstX;
orig_y = stuff->dstY;
@@ -1824,7 +1818,7 @@ int PanoramiXGetImage(ClientPtr client)
format = stuff->format;
planemask = stuff->planeMask;
- isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
+ isRoot = IS_ROOT_DRAWABLE(draw);
if(isRoot) {
if( /* check for being onscreen */
@@ -1846,7 +1840,7 @@ int PanoramiXGetImage(ClientPtr client)
}
drawables[0] = pDraw;
- for(i = 1; i < PanoramiXNumScreens; i++) {
+ FOR_NSCREENS_FORWARD_SKIP(i) {
rc = dixLookupDrawable(drawables+i, draw->info[i].id, client, 0,
DixGetAttrAccess);
if (rc != Success)
@@ -1962,7 +1956,7 @@ PanoramiXPolyText8(ClientPtr client)
if (result != Success)
return result;
- isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
+ isRoot = IS_ROOT_DRAWABLE(draw);
orig_x = stuff->x;
orig_y = stuff->y;
@@ -2003,7 +1997,7 @@ PanoramiXPolyText16(ClientPtr client)
if (result != Success)
return result;
- isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
+ isRoot = IS_ROOT_DRAWABLE(draw);
orig_x = stuff->x;
orig_y = stuff->y;
@@ -2044,7 +2038,7 @@ int PanoramiXImageText8(ClientPtr client)
if (result != Success)
return result;
- isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
+ isRoot = IS_ROOT_DRAWABLE(draw);
orig_x = stuff->x;
orig_y = stuff->y;
@@ -2085,7 +2079,7 @@ int PanoramiXImageText16(ClientPtr client)
if (result != Success)
return result;
- isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
+ isRoot = IS_ROOT_DRAWABLE(draw);
orig_x = stuff->x;
orig_y = stuff->y;
@@ -2121,9 +2115,7 @@ int PanoramiXCreateColormap(ClientPtr client)
return BadAlloc;
newCmap->type = XRT_COLORMAP;
- newCmap->info[0].id = stuff->mid;
- for(j = 1; j < PanoramiXNumScreens; j++)
- newCmap->info[j].id = FakeClientID(client->index);
+ panoramix_setup_ids(newCmap, client, stuff->mid);
orig_visual = stuff->visual;
FOR_NSCREENS_BACKWARD(j){
@@ -2192,11 +2184,9 @@ PanoramiXCopyColormapAndFree(ClientPtr client)
return BadAlloc;
newCmap->type = XRT_COLORMAP;
- newCmap->info[0].id = stuff->mid;
- for(j = 1; j < PanoramiXNumScreens; j++)
- newCmap->info[j].id = FakeClientID(client->index);
+ panoramix_setup_ids(newCmap, client, stuff->mid);
- FOR_NSCREENS_BACKWARD(j){
+ FOR_NSCREENS_BACKWARD(j) {
stuff->srcCmap = cmap->info[j].id;
stuff->mid = newCmap->info[j].id;
result = (* SavedProcVector[X_CopyColormapAndFree])(client);
diff --git a/xorg-server/Xext/panoramiXsrv.h b/xorg-server/Xext/panoramiXsrv.h
index 21f1b4cb8..d3d54ee14 100644
--- a/xorg-server/Xext/panoramiXsrv.h
+++ b/xorg-server/Xext/panoramiXsrv.h
@@ -51,4 +51,15 @@ extern _X_EXPORT void XineramaGetImageData(
Bool isRoot
);
+static inline void panoramix_setup_ids(PanoramiXRes *resource,
+ ClientPtr client, XID base_id)
+{
+ int j;
+
+ resource->info[0].id = base_id;
+ FOR_NSCREENS_FORWARD_SKIP(j) {
+ resource->info[j].id = FakeClientID(client->index);
+ }
+}
+
#endif /* _PANORAMIXSRV_H_ */
diff --git a/xorg-server/Xext/shm.c b/xorg-server/Xext/shm.c
index 7099e8f36..62d6ebe0c 100644
--- a/xorg-server/Xext/shm.c
+++ b/xorg-server/Xext/shm.c
@@ -867,7 +867,7 @@ ProcPanoramiXShmGetImage(ClientPtr client)
return BadAlloc;
drawables[0] = pDraw;
- for(i = 1; i < PanoramiXNumScreens; i++) {
+ FOR_NSCREENS_FORWARD_SKIP(i) {
rc = dixLookupDrawable(drawables+i, draw->info[i].id, client, 0,
DixReadAccess);
if (rc != Success)
@@ -991,9 +991,7 @@ CreatePmap:
newPix->type = XRT_PIXMAP;
newPix->u.pix.shared = TRUE;
- newPix->info[0].id = stuff->pid;
- for(j = 1; j < PanoramiXNumScreens; j++)
- newPix->info[j].id = FakeClientID(client->index);
+ panoramix_setup_ids(newPix, client, stuff->pid);
result = Success;
diff --git a/xorg-server/Xext/xvdisp.c b/xorg-server/Xext/xvdisp.c
index e723fd84b..d9cedc850 100644
--- a/xorg-server/Xext/xvdisp.c
+++ b/xorg-server/Xext/xvdisp.c
@@ -1918,7 +1918,7 @@ void XineramifyXv(void)
MatchingAdaptors[0] = refAdapt;
isOverlay = hasOverlay(refAdapt);
- for(j = 1; j < PanoramiXNumScreens; j++)
+ FOR_NSCREENS_FORWARD_SKIP(j)
MatchingAdaptors[j] = matchAdaptor(screenInfo.screens[j], refAdapt, isOverlay);
/* now create a resource for each port */
@@ -1927,7 +1927,7 @@ void XineramifyXv(void)
if(!port)
break;
- for(k = 0; k < PanoramiXNumScreens; k++) {
+ FOR_NSCREENS(k) {
if(MatchingAdaptors[k] && (MatchingAdaptors[k]->nPorts > j))
port->info[k].id = MatchingAdaptors[k]->base_id + j;
else
diff --git a/xorg-server/composite/compext.c b/xorg-server/composite/compext.c
index d6f26d688..711236bbf 100644
--- a/xorg-server/composite/compext.c
+++ b/xorg-server/composite/compext.c
@@ -703,10 +703,7 @@ PanoramiXCompositeNameWindowPixmap (ClientPtr client)
newPix->type = XRT_PIXMAP;
newPix->u.pix.shared = FALSE;
- newPix->info[0].id = stuff->pixmap;
-
- for (i = 1; i < PanoramiXNumScreens; i++)
- newPix->info[i].id = FakeClientID (client->index);
+ panoramix_setup_ids(newPix, client, stuff->pixmap);
FOR_NSCREENS(i) {
rc = dixLookupResourceByType ((void **) &pWin, win->info[i].id,
diff --git a/xorg-server/dix/events.c b/xorg-server/dix/events.c
index 0eda63a51..d5ba711e2 100644
--- a/xorg-server/dix/events.c
+++ b/xorg-server/dix/events.c
@@ -558,7 +558,7 @@ XineramaSetWindowPntrs(DeviceIntPtr pDev, WindowPtr pWin)
if(pWin == screenInfo.screens[0]->root) {
int i;
- for (i = 0; i < PanoramiXNumScreens; i++)
+ FOR_NSCREENS(i)
pSprite->windows[i] = screenInfo.screens[i]->root;
} else {
PanoramiXRes *win;
@@ -569,7 +569,7 @@ XineramaSetWindowPntrs(DeviceIntPtr pDev, WindowPtr pWin)
if (rc != Success)
return FALSE;
- for(i = 0; i < PanoramiXNumScreens; i++) {
+ FOR_NSCREENS(i) {
rc = dixLookupWindow(pSprite->windows + i, win->info[i].id,
serverClient, DixReadAccess);
if (rc != Success) /* window is being unmapped */
@@ -2557,7 +2557,7 @@ PointInBorderSize(WindowPtr pWin, int x, int y)
SpritePtr pSprite = inputInfo.pointer->spriteInfo->sprite;
int i;
- for(i = 1; i < PanoramiXNumScreens; i++) {
+ FOR_NSCREENS_FORWARD_SKIP(i) {
if(RegionContainsPoint(&pSprite->windows[i]->borderSize,
x + screenInfo.screens[0]->x - screenInfo.screens[i]->x,
y + screenInfo.screens[0]->y - screenInfo.screens[i]->y,
@@ -3159,7 +3159,7 @@ XineramaPointInWindowIsVisible(
xoff = x + screenInfo.screens[0]->x;
yoff = y + screenInfo.screens[0]->y;
- for(i = 1; i < PanoramiXNumScreens; i++) {
+ FOR_NSCREENS_FORWARD_SKIP(i) {
pWin = inputInfo.pointer->spriteInfo->sprite->windows[i];
x = xoff - screenInfo.screens[i]->x;
y = yoff - screenInfo.screens[i]->y;
@@ -3366,7 +3366,7 @@ BorderSizeNotEmpty(DeviceIntPtr pDev, WindowPtr pWin)
if(!noPanoramiXExtension && XineramaSetWindowPntrs(pDev, pWin)) {
int i;
- for(i = 1; i < PanoramiXNumScreens; i++) {
+ FOR_NSCREENS_FORWARD_SKIP(i) {
if(RegionNotEmpty(&pDev->spriteInfo->sprite->windows[i]->borderSize))
return TRUE;
}
diff --git a/xorg-server/dix/window.c b/xorg-server/dix/window.c
index c2cee9198..821c815f7 100644
--- a/xorg-server/dix/window.c
+++ b/xorg-server/dix/window.c
@@ -3067,7 +3067,7 @@ SendVisibilityNotify(WindowPtr pWin)
switch(visibility) {
case VisibilityUnobscured:
- for(i = 0; i < PanoramiXNumScreens; i++) {
+ FOR_NSCREENS(i) {
if(i == Scrnum) continue;
rc = dixLookupWindow(&pWin2, win->info[i].id, serverClient,
@@ -3089,7 +3089,7 @@ SendVisibilityNotify(WindowPtr pWin)
}
break;
case VisibilityFullyObscured:
- for(i = 0; i < PanoramiXNumScreens; i++) {
+ FOR_NSCREENS(i) {
if(i == Scrnum) continue;
rc = dixLookupWindow(&pWin2, win->info[i].id, serverClient,
diff --git a/xorg-server/hw/dmx/dmxcb.c b/xorg-server/hw/dmx/dmxcb.c
index 4e7279a51..bc3281f56 100644
--- a/xorg-server/hw/dmx/dmxcb.c
+++ b/xorg-server/hw/dmx/dmxcb.c
@@ -1,222 +1,223 @@
-/*
- * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina.
- *
- * 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 on the rights to use, copy, modify, merge,
- * publish, distribute, sublicense, and/or sell copies of the Software,
- * and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial
- * portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR 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.
- */
-
-/*
- * Authors:
- * Rickard E. (Rik) Faith <faith@redhat.com>
- *
- */
-
-/** \file
- * This code queries and modifies the connection block. */
-
-#ifdef HAVE_DMX_CONFIG_H
-#include <dmx-config.h>
-#endif
-
-#include "dmx.h"
-#include "dmxcb.h"
-#include "dmxinput.h"
-#include "dmxlog.h"
-
-extern int connBlockScreenStart;
-
-#ifdef PANORAMIX
-extern int PanoramiXPixWidth;
-extern int PanoramiXPixHeight;
-extern int PanoramiXNumScreens;
-#endif
-
- int dmxGlobalWidth, dmxGlobalHeight;
-
-/** We may want the wall dimensions to be different from the bounding
- * box dimensions that Xinerama computes, so save those and update them
- * here.
- */
-void dmxSetWidthHeight(int width, int height)
-{
- dmxGlobalWidth = width;
- dmxGlobalHeight = height;
-}
-
-/** Computes the global bounding box for DMX. This may be larger than
- * the one computed by Xinerama because of the DMX configuration
- * file. */
-void dmxComputeWidthHeight(DMXRecomputeFlag flag)
-{
- int i;
- DMXScreenInfo *dmxScreen;
- int w = 0;
- int h = 0;
-
- for (i = 0; i < dmxNumScreens; i++) {
- /* Don't use root* here because this is
- * the global bounding box. */
- dmxScreen = &dmxScreens[i];
- if (w < dmxScreen->scrnWidth + dmxScreen->rootXOrigin)
- w = dmxScreen->scrnWidth + dmxScreen->rootXOrigin;
- if (h < dmxScreen->scrnHeight + dmxScreen->rootYOrigin)
- h = dmxScreen->scrnHeight + dmxScreen->rootYOrigin;
- }
- if (!dmxGlobalWidth && !dmxGlobalHeight) {
- dmxLog(dmxInfo, "Using %dx%d as global bounding box\n", w, h);
- } else {
- switch (flag) {
- case DMX_NO_RECOMPUTE_BOUNDING_BOX:
- dmxLog(dmxInfo,
- "Using old bounding box (%dx%d) instead of new (%dx%d)\n",
- dmxGlobalWidth, dmxGlobalHeight, w, h);
- w = dmxGlobalWidth;
- h = dmxGlobalHeight;
- break;
- case DMX_RECOMPUTE_BOUNDING_BOX:
- dmxLog(dmxInfo,
- "Using %dx%d as global bounding box, instead of %dx%d\n",
- w, h, dmxGlobalWidth, dmxGlobalHeight);
- break;
- }
- }
-
- dmxGlobalWidth = w;
- dmxGlobalHeight = h;
-}
-
-/** A callback routine that hooks into Xinerama and provides a
- * convenient place to print summary log information during server
- * startup. This routine does not modify any values. */
-void dmxConnectionBlockCallback(void)
-{
- xWindowRoot *root = (xWindowRoot *)(ConnectionInfo+connBlockScreenStart);
- int offset = connBlockScreenStart + sizeof(xWindowRoot);
- int i;
- Bool *found = NULL;
-
- MAXSCREENSALLOC(found);
- if (!found)
- dmxLog(dmxFatal, "dmxConnectionBlockCallback: out of memory\n");
-
- dmxLog(dmxInfo, "===== Start of Summary =====\n");
-#ifdef PANORAMIX
- if (!noPanoramiXExtension) {
- if (dmxGlobalWidth && dmxGlobalHeight
- && (dmxGlobalWidth != PanoramiXPixWidth
- || dmxGlobalHeight != PanoramiXPixHeight)) {
- dmxLog(dmxInfo,
- "Changing Xinerama dimensions from %d %d to %d %d\n",
- PanoramiXPixWidth, PanoramiXPixHeight,
- dmxGlobalWidth, dmxGlobalHeight);
- PanoramiXPixWidth = root->pixWidth = dmxGlobalWidth;
- PanoramiXPixHeight = root->pixHeight = dmxGlobalHeight;
- } else {
- dmxGlobalWidth = PanoramiXPixWidth;
- dmxGlobalHeight = PanoramiXPixHeight;
- }
- dmxLog(dmxInfo, "%d screens configured with Xinerama (%d %d)\n",
- PanoramiXNumScreens, PanoramiXPixWidth, PanoramiXPixHeight);
- for (i = 0; i < PanoramiXNumScreens; i++) found[i] = FALSE;
- } else {
-#endif
- /* This never happens because we're
- * either called from a Xinerama
- * callback or during reconfiguration
- * (which only works with Xinerama on).
- * In any case, be reasonable. */
- dmxLog(dmxInfo, "%d screens configured (%d %d)\n",
- screenInfo.numScreens, root->pixWidth, root->pixHeight);
-#ifdef PANORAMIX
- }
-#endif
-
- for (i = 0; i < root->nDepths; i++) {
- xDepth *depth = (xDepth *)(ConnectionInfo + offset);
- int voffset = offset + sizeof(xDepth);
- xVisualType *visual = (xVisualType *)(ConnectionInfo + voffset);
- int j;
-
- dmxLog(dmxInfo, "%d visuals at depth %d:\n",
- depth->nVisuals, depth->depth);
- for (j = 0; j < depth->nVisuals; j++, visual++) {
- XVisualInfo vi;
-
- vi.visual = NULL;
- vi.visualid = visual->visualID;
- vi.screen = 0;
- vi.depth = depth->depth;
- vi.class = visual->class;
- vi.red_mask = visual->redMask;
- vi.green_mask = visual->greenMask;
- vi.blue_mask = visual->blueMask;
- vi.colormap_size = visual->colormapEntries;
- vi.bits_per_rgb = visual->bitsPerRGB;
- dmxLogVisual(NULL, &vi, 0);
-
-#ifdef PANORAMIX
- if (!noPanoramiXExtension) {
- int k;
- for (k = 0; k < PanoramiXNumScreens; k++) {
- DMXScreenInfo *dmxScreen = &dmxScreens[k];
-
- if (dmxScreen->beDisplay) {
- XVisualInfo *pvi =
- &dmxScreen->beVisuals[dmxScreen->beDefVisualIndex];
- if (pvi->depth == depth->depth &&
- pvi->class == visual->class)
- found[k] = TRUE;
- } else {
- /* Screen #k is detatched, so it always succeeds */
- found[k] = TRUE;
- }
- }
- }
-#endif
- }
- offset = voffset + depth->nVisuals * sizeof(xVisualType);
- }
-
- dmxInputLogDevices();
- dmxLog(dmxInfo, "===== End of Summary =====\n");
-
-#ifdef PANORAMIX
- if (!noPanoramiXExtension) {
- Bool fatal = FALSE;
- for (i = 0; i < PanoramiXNumScreens; i++) {
- fatal |= !found[i];
- if (!found[i]) {
- dmxLog(dmxError,
- "The default visual for screen #%d does not match "
- "any of the\n", i);
- dmxLog(dmxError,
- "consolidated visuals from Xinerama (listed above)\n");
- }
- }
- if (fatal)
- dmxLog(dmxFatal,
- "dmxConnectionBlockCallback: invalid screen(s) found");
- }
-#endif
- MAXSCREENSFREE(found);
-}
+/*
+ * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina.
+ *
+ * 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 on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR 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.
+ */
+
+/*
+ * Authors:
+ * Rickard E. (Rik) Faith <faith@redhat.com>
+ *
+ */
+
+/** \file
+ * This code queries and modifies the connection block. */
+
+#ifdef HAVE_DMX_CONFIG_H
+#include <dmx-config.h>
+#endif
+
+#include "dmx.h"
+#include "dmxcb.h"
+#include "dmxinput.h"
+#include "dmxlog.h"
+
+extern int connBlockScreenStart;
+
+#ifdef PANORAMIX
+#include "panoramiXsrv.h"
+extern int PanoramiXPixWidth;
+extern int PanoramiXPixHeight;
+extern int PanoramiXNumScreens;
+#endif
+
+ int dmxGlobalWidth, dmxGlobalHeight;
+
+/** We may want the wall dimensions to be different from the bounding
+ * box dimensions that Xinerama computes, so save those and update them
+ * here.
+ */
+void dmxSetWidthHeight(int width, int height)
+{
+ dmxGlobalWidth = width;
+ dmxGlobalHeight = height;
+}
+
+/** Computes the global bounding box for DMX. This may be larger than
+ * the one computed by Xinerama because of the DMX configuration
+ * file. */
+void dmxComputeWidthHeight(DMXRecomputeFlag flag)
+{
+ int i;
+ DMXScreenInfo *dmxScreen;
+ int w = 0;
+ int h = 0;
+
+ for (i = 0; i < dmxNumScreens; i++) {
+ /* Don't use root* here because this is
+ * the global bounding box. */
+ dmxScreen = &dmxScreens[i];
+ if (w < dmxScreen->scrnWidth + dmxScreen->rootXOrigin)
+ w = dmxScreen->scrnWidth + dmxScreen->rootXOrigin;
+ if (h < dmxScreen->scrnHeight + dmxScreen->rootYOrigin)
+ h = dmxScreen->scrnHeight + dmxScreen->rootYOrigin;
+ }
+ if (!dmxGlobalWidth && !dmxGlobalHeight) {
+ dmxLog(dmxInfo, "Using %dx%d as global bounding box\n", w, h);
+ } else {
+ switch (flag) {
+ case DMX_NO_RECOMPUTE_BOUNDING_BOX:
+ dmxLog(dmxInfo,
+ "Using old bounding box (%dx%d) instead of new (%dx%d)\n",
+ dmxGlobalWidth, dmxGlobalHeight, w, h);
+ w = dmxGlobalWidth;
+ h = dmxGlobalHeight;
+ break;
+ case DMX_RECOMPUTE_BOUNDING_BOX:
+ dmxLog(dmxInfo,
+ "Using %dx%d as global bounding box, instead of %dx%d\n",
+ w, h, dmxGlobalWidth, dmxGlobalHeight);
+ break;
+ }
+ }
+
+ dmxGlobalWidth = w;
+ dmxGlobalHeight = h;
+}
+
+/** A callback routine that hooks into Xinerama and provides a
+ * convenient place to print summary log information during server
+ * startup. This routine does not modify any values. */
+void dmxConnectionBlockCallback(void)
+{
+ xWindowRoot *root = (xWindowRoot *)(ConnectionInfo+connBlockScreenStart);
+ int offset = connBlockScreenStart + sizeof(xWindowRoot);
+ int i;
+ Bool *found = NULL;
+
+ MAXSCREENSALLOC(found);
+ if (!found)
+ dmxLog(dmxFatal, "dmxConnectionBlockCallback: out of memory\n");
+
+ dmxLog(dmxInfo, "===== Start of Summary =====\n");
+#ifdef PANORAMIX
+ if (!noPanoramiXExtension) {
+ if (dmxGlobalWidth && dmxGlobalHeight
+ && (dmxGlobalWidth != PanoramiXPixWidth
+ || dmxGlobalHeight != PanoramiXPixHeight)) {
+ dmxLog(dmxInfo,
+ "Changing Xinerama dimensions from %d %d to %d %d\n",
+ PanoramiXPixWidth, PanoramiXPixHeight,
+ dmxGlobalWidth, dmxGlobalHeight);
+ PanoramiXPixWidth = root->pixWidth = dmxGlobalWidth;
+ PanoramiXPixHeight = root->pixHeight = dmxGlobalHeight;
+ } else {
+ dmxGlobalWidth = PanoramiXPixWidth;
+ dmxGlobalHeight = PanoramiXPixHeight;
+ }
+ dmxLog(dmxInfo, "%d screens configured with Xinerama (%d %d)\n",
+ PanoramiXNumScreens, PanoramiXPixWidth, PanoramiXPixHeight);
+ FOR_NSCREENS(i) found[i] = FALSE;
+ } else {
+#endif
+ /* This never happens because we're
+ * either called from a Xinerama
+ * callback or during reconfiguration
+ * (which only works with Xinerama on).
+ * In any case, be reasonable. */
+ dmxLog(dmxInfo, "%d screens configured (%d %d)\n",
+ screenInfo.numScreens, root->pixWidth, root->pixHeight);
+#ifdef PANORAMIX
+ }
+#endif
+
+ for (i = 0; i < root->nDepths; i++) {
+ xDepth *depth = (xDepth *)(ConnectionInfo + offset);
+ int voffset = offset + sizeof(xDepth);
+ xVisualType *visual = (xVisualType *)(ConnectionInfo + voffset);
+ int j;
+
+ dmxLog(dmxInfo, "%d visuals at depth %d:\n",
+ depth->nVisuals, depth->depth);
+ for (j = 0; j < depth->nVisuals; j++, visual++) {
+ XVisualInfo vi;
+
+ vi.visual = NULL;
+ vi.visualid = visual->visualID;
+ vi.screen = 0;
+ vi.depth = depth->depth;
+ vi.class = visual->class;
+ vi.red_mask = visual->redMask;
+ vi.green_mask = visual->greenMask;
+ vi.blue_mask = visual->blueMask;
+ vi.colormap_size = visual->colormapEntries;
+ vi.bits_per_rgb = visual->bitsPerRGB;
+ dmxLogVisual(NULL, &vi, 0);
+
+#ifdef PANORAMIX
+ if (!noPanoramiXExtension) {
+ int k;
+ FOR_NSCREENS(k) {
+ DMXScreenInfo *dmxScreen = &dmxScreens[k];
+
+ if (dmxScreen->beDisplay) {
+ XVisualInfo *pvi =
+ &dmxScreen->beVisuals[dmxScreen->beDefVisualIndex];
+ if (pvi->depth == depth->depth &&
+ pvi->class == visual->class)
+ found[k] = TRUE;
+ } else {
+ /* Screen #k is detatched, so it always succeeds */
+ found[k] = TRUE;
+ }
+ }
+ }
+#endif
+ }
+ offset = voffset + depth->nVisuals * sizeof(xVisualType);
+ }
+
+ dmxInputLogDevices();
+ dmxLog(dmxInfo, "===== End of Summary =====\n");
+
+#ifdef PANORAMIX
+ if (!noPanoramiXExtension) {
+ Bool fatal = FALSE;
+ FOR_NSCREENS(i) {
+ fatal |= !found[i];
+ if (!found[i]) {
+ dmxLog(dmxError,
+ "The default visual for screen #%d does not match "
+ "any of the\n", i);
+ dmxLog(dmxError,
+ "consolidated visuals from Xinerama (listed above)\n");
+ }
+ }
+ if (fatal)
+ dmxLog(dmxFatal,
+ "dmxConnectionBlockCallback: invalid screen(s) found");
+ }
+#endif
+ MAXSCREENSFREE(found);
+}
diff --git a/xorg-server/hw/dmx/dmxextension.c b/xorg-server/hw/dmx/dmxextension.c
index bd326ce2a..00b95a96d 100644
--- a/xorg-server/hw/dmx/dmxextension.c
+++ b/xorg-server/hw/dmx/dmxextension.c
@@ -1,1620 +1,1620 @@
-/*
- * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina.
- *
- * 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 on the rights to use, copy, modify, merge,
- * publish, distribute, sublicense, and/or sell copies of the Software,
- * and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial
- * portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR 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.
- */
-
-/*
- * Author:
- * Rickard E. (Rik) Faith <faith@redhat.com>
- * Kevin E. Martin <kem@redhat.com>
- *
- */
-
-/** \file
- * This file provides the only interface to the X server extension support
- * in programs/Xserver/Xext. Those programs should only include dmxext.h
- */
-
-#ifdef HAVE_DMX_CONFIG_H
-#include <dmx-config.h>
-#endif
-
-#include <stdlib.h>
-
-#include "dmx.h"
-#include "dmxinit.h"
-#include "dmxextension.h"
-#include "dmxwindow.h"
-#include "dmxcb.h"
-#include "dmxcursor.h"
-#include "dmxpixmap.h"
-#include "dmxgc.h"
-#include "dmxfont.h"
-#include "dmxcmap.h"
-#include "dmxpict.h"
-#include "dmxinput.h"
-#include "dmxsync.h"
-#include "dmxscrinit.h"
-#include "input/dmxinputinit.h"
-
-#include "windowstr.h"
-#include "inputstr.h" /* For DeviceIntRec */
-#include <X11/extensions/dmxproto.h> /* For DMX_BAD_* */
-#include "cursorstr.h"
-
-/* The default font is declared in dix/globals.c, but is not included in
- * _any_ header files. */
-extern FontPtr defaultFont;
-
-/** This routine provides information to the DMX protocol extension
- * about a particular screen. */
-Bool dmxGetScreenAttributes(int physical, DMXScreenAttributesPtr attr)
-{
- DMXScreenInfo *dmxScreen;
-
- if (physical < 0 || physical >= dmxNumScreens) return FALSE;
-
- dmxScreen = &dmxScreens[physical];
- attr->displayName = dmxScreen->name;
-#ifdef PANORAMIX
- attr->logicalScreen = noPanoramiXExtension ? dmxScreen->index : 0;
-#else
- attr->logicalScreen = dmxScreen->index;
-#endif
-
- attr->screenWindowWidth = dmxScreen->scrnWidth;
- attr->screenWindowHeight = dmxScreen->scrnHeight;
- attr->screenWindowXoffset = dmxScreen->scrnX;
- attr->screenWindowYoffset = dmxScreen->scrnY;
-
- attr->rootWindowWidth = dmxScreen->rootWidth;
- attr->rootWindowHeight = dmxScreen->rootHeight;
- attr->rootWindowXoffset = dmxScreen->rootX;
- attr->rootWindowYoffset = dmxScreen->rootY;
-
- attr->rootWindowXorigin = dmxScreen->rootXOrigin;
- attr->rootWindowYorigin = dmxScreen->rootYOrigin;
-
- return TRUE;
-}
-
-/** This routine provides information to the DMX protocol extension
- * about a particular window. */
-Bool dmxGetWindowAttributes(WindowPtr pWindow, DMXWindowAttributesPtr attr)
-{
- dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
-
- attr->screen = pWindow->drawable.pScreen->myNum;
- attr->window = pWinPriv->window;
-
- attr->pos.x = pWindow->drawable.x;
- attr->pos.y = pWindow->drawable.y;
- attr->pos.width = pWindow->drawable.width;
- attr->pos.height = pWindow->drawable.height;
-
- if (!pWinPriv->window || pWinPriv->offscreen) {
- attr->vis.x = 0;
- attr->vis.y = 0;
- attr->vis.height = 0;
- attr->vis.width = 0;
- return pWinPriv->window ? TRUE : FALSE;
- }
-
- /* Compute display-relative coordinates */
- attr->vis.x = pWindow->drawable.x;
- attr->vis.y = pWindow->drawable.y;
- attr->vis.width = pWindow->drawable.width;
- attr->vis.height = pWindow->drawable.height;
-
- if (attr->pos.x < 0) {
- attr->vis.x -= attr->pos.x;
- attr->vis.width = attr->pos.x + attr->pos.width - attr->vis.x;
- }
- if (attr->pos.x + attr->pos.width > pWindow->drawable.pScreen->width) {
- if (attr->pos.x < 0)
- attr->vis.width = pWindow->drawable.pScreen->width;
- else
- attr->vis.width = pWindow->drawable.pScreen->width - attr->pos.x;
- }
- if (attr->pos.y < 0) {
- attr->vis.y -= attr->pos.y;
- attr->vis.height = attr->pos.y + attr->pos.height - attr->vis.y;
- }
- if (attr->pos.y + attr->pos.height > pWindow->drawable.pScreen->height) {
- if (attr->pos.y < 0)
- attr->vis.height = pWindow->drawable.pScreen->height;
- else
- attr->vis.height = pWindow->drawable.pScreen->height - attr->pos.y;
- }
-
- /* Convert to window-relative coordinates */
- attr->vis.x -= attr->pos.x;
- attr->vis.y -= attr->pos.y;
-
- return TRUE;
-}
-
-void dmxGetDesktopAttributes(DMXDesktopAttributesPtr attr)
-{
- attr->width = dmxGlobalWidth;
- attr->height = dmxGlobalHeight;
- attr->shiftX = 0; /* NOTE: The upper left hand corner of */
- attr->shiftY = 0; /* the desktop is always <0,0>. */
-}
-
-/** Return the total number of devices, not just #dmxNumInputs. The
- * number returned should be the same as that returned by
- * XListInputDevices. */
-int dmxGetInputCount(void)
-{
- int i, total;
-
- for (total = i = 0; i < dmxNumInputs; i++) total += dmxInputs[i].numDevs;
- return total;
-}
-
-/** Return information about the device with id = \a deviceId. This
- * information is primarily for the #ProcDMXGetInputAttributes()
- * function, which does not have access to the appropriate data
- * structure. */
-int dmxGetInputAttributes(int deviceId, DMXInputAttributesPtr attr)
-{
- int i, j;
- DMXInputInfo *dmxInput;
-
- if (deviceId < 0) return -1;
- for (i = 0; i < dmxNumInputs; i++) {
- dmxInput = &dmxInputs[i];
- for (j = 0; j < dmxInput->numDevs; j++) {
- DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[j];
- if (deviceId != dmxLocal->pDevice->id) continue;
- attr->isCore = !!dmxLocal->isCore;
- attr->sendsCore = !!dmxLocal->sendsCore;
- attr->detached = !!dmxInput->detached;
- attr->physicalScreen = -1;
- attr->physicalId = -1;
- attr->name = NULL;
- switch (dmxLocal->extType) {
- case DMX_LOCAL_TYPE_LOCAL:
- attr->inputType = 0;
- break;
- case DMX_LOCAL_TYPE_CONSOLE:
- attr->inputType = 1;
- attr->name = dmxInput->name;
- attr->physicalId = dmxLocal->deviceId;
- break;
- case DMX_LOCAL_TYPE_BACKEND:
- case DMX_LOCAL_TYPE_COMMON:
- attr->inputType = 2;
- attr->physicalScreen = dmxInput->scrnIdx;
- attr->name = dmxInput->name;
- attr->physicalId = dmxLocal->deviceId;
- break;
- }
- return 0; /* Success */
- }
- }
- return -1; /* Failure */
-}
-
-/** Reinitialized the cursor boundaries. */
-static void dmxAdjustCursorBoundaries(void)
-{
- int i;
-
- dmxReInitOrigins();
- dmxInitOverlap();
- dmxComputeWidthHeight(DMX_NO_RECOMPUTE_BOUNDING_BOX);
- dmxConnectionBlockCallback();
- for (i = 0; i < dmxNumInputs; i++) {
- DMXInputInfo *dmxInput = &dmxInputs[i];
- if (!dmxInput->detached) dmxInputReInit(dmxInput);
- }
-
- dmxCheckCursor();
-
- for (i = 0; i < dmxNumInputs; i++) {
- DMXInputInfo *dmxInput = &dmxInputs[i];
- if (!dmxInput->detached) dmxInputLateReInit(dmxInput);
- }
-}
-
-/** Add an input with the specified attributes. If the input is added,
- * the physical id is returned in \a deviceId. */
-int dmxAddInput(DMXInputAttributesPtr attr, int *id)
-{
- int retcode = BadValue;
-
- if (attr->inputType == 1) /* console */
- retcode = dmxInputAttachConsole(attr->name, attr->sendsCore, id);
- else if (attr->inputType == 2) /* backend */
- retcode = dmxInputAttachBackend(attr->physicalScreen,
- attr->sendsCore,id);
-
- if (retcode == Success) {
- /* Adjust the cursor boundaries */
- dmxAdjustCursorBoundaries();
-
- /* Force completion of the changes */
- dmxSync(NULL, TRUE);
- }
-
- return retcode;
-}
-
-/** Remove the input with physical id \a id. */
-int dmxRemoveInput(int id)
-{
- return dmxInputDetachId(id);
-}
-
-/** Return the value of #dmxNumScreens -- the total number of backend
- * screens in use (these are logical screens and may be larger than the
- * number of backend displays). */
-unsigned long dmxGetNumScreens(void)
-{
- return dmxNumScreens;
-}
-
-/** Make sure that #dmxCreateAndRealizeWindow has been called for \a
- * pWindow. */
-void dmxForceWindowCreation(WindowPtr pWindow)
-{
- dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
- if (!pWinPriv->window) dmxCreateAndRealizeWindow(pWindow, TRUE);
-}
-
-/** Flush pending syncs for all screens. */
-void dmxFlushPendingSyncs(void)
-{
- dmxSync(NULL, TRUE);
-}
-
-/** Update DMX's screen resources to match those of the newly moved
- * and/or resized "root" window. */
-void dmxUpdateScreenResources(ScreenPtr pScreen, int x, int y, int w, int h)
-{
- DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
- WindowPtr pRoot = pScreen->root;
- WindowPtr pChild;
- Bool anyMarked = FALSE;
-
- /* Handle special case where width and/or height are zero */
- if (w == 0 || h == 0) {
- w = 1;
- h = 1;
- }
-
- /* Change screen size */
- pScreen->width = w;
- pScreen->height = h;
-
- /* Reset the root window's drawable's size */
- pRoot->drawable.width = w;
- pRoot->drawable.height = h;
-
- /* Set the root window's new winSize and borderSize */
- pRoot->winSize.extents.x1 = 0;
- pRoot->winSize.extents.y1 = 0;
- pRoot->winSize.extents.x2 = w;
- pRoot->winSize.extents.y2 = h;
-
- pRoot->borderSize.extents.x1 = 0;
- pRoot->borderSize.extents.y1 = 0;
- pRoot->borderSize.extents.x2 = w;
- pRoot->borderSize.extents.y2 = h;
-
- /* Recompute this screen's mmWidth & mmHeight */
- pScreen->mmWidth =
- (w * 254 + dmxScreen->beXDPI * 5) / (dmxScreen->beXDPI * 10);
- pScreen->mmHeight =
- (h * 254 + dmxScreen->beYDPI * 5) / (dmxScreen->beYDPI * 10);
-
- /* Recompute this screen's window's clip rects as follows: */
- /* 1. Mark all of root's children's windows */
- for (pChild = pRoot->firstChild; pChild; pChild = pChild->nextSib)
- anyMarked |= pScreen->MarkOverlappedWindows(pChild, pChild,
- (WindowPtr *)NULL);
-
- /* 2. Set the root window's borderClip */
- pRoot->borderClip.extents.x1 = 0;
- pRoot->borderClip.extents.y1 = 0;
- pRoot->borderClip.extents.x2 = w;
- pRoot->borderClip.extents.y2 = h;
-
- /* 3. Set the root window's clipList */
- if (anyMarked) {
- /* If any windows have been marked, set the root window's
- * clipList to be broken since it will be recalculated in
- * ValidateTree()
- */
- RegionBreak(&pRoot->clipList);
- } else {
- /* Otherwise, we just set it directly since there are no
- * windows visible on this screen
- */
- pRoot->clipList.extents.x1 = 0;
- pRoot->clipList.extents.y1 = 0;
- pRoot->clipList.extents.x2 = w;
- pRoot->clipList.extents.y2 = h;
- }
-
- /* 4. Revalidate all clip rects and generate expose events */
- if (anyMarked) {
- pScreen->ValidateTree(pRoot, NULL, VTBroken);
- pScreen->HandleExposures(pRoot);
- if (pScreen->PostValidateTree)
- pScreen->PostValidateTree(pRoot, NULL, VTBroken);
- }
-}
-
-#ifdef PANORAMIX
-#include "panoramiXsrv.h"
-
-/** Change the "screen" window attributes by resizing the actual window
- * on the back-end display (if necessary). */
-static void dmxConfigureScreenWindow(int idx,
- int x, int y, int w, int h)
-{
- DMXScreenInfo *dmxScreen = &dmxScreens[idx];
- ScreenPtr pScreen = screenInfo.screens[idx];
-
- /* Resize "screen" window */
- if (dmxScreen->scrnX != x ||
- dmxScreen->scrnY != y ||
- dmxScreen->scrnWidth != w ||
- dmxScreen->scrnHeight != h) {
- dmxResizeScreenWindow(pScreen, x, y, w, h);
- }
-
- /* Change "screen" window values */
- dmxScreen->scrnX = x;
- dmxScreen->scrnY = y;
- dmxScreen->scrnWidth = w;
- dmxScreen->scrnHeight = h;
-}
-
-/** Change the "root" window position and size by resizing the actual
- * window on the back-end display (if necessary) and updating all of
- * DMX's resources by calling #dmxUpdateScreenResources. */
-static void dmxConfigureRootWindow(int idx, int x, int y, int w, int h)
-{
- DMXScreenInfo *dmxScreen = &dmxScreens[idx];
- WindowPtr pRoot = screenInfo.screens[idx]->root;
-
- /* NOTE: Either this function or the ones that it calls must handle
- * the case where w == 0 || h == 0. Currently, the functions that
- * this one calls handle that case. */
-
- /* 1. Resize "root" window */
- if (dmxScreen->rootX != x ||
- dmxScreen->rootY != y ||
- dmxScreen->rootWidth != w ||
- dmxScreen->rootHeight != h) {
- dmxResizeRootWindow(pRoot, x, y, w, h);
- }
-
- /* 2. Update all of the screen's resources associated with this root
- * window */
- if (dmxScreen->rootWidth != w ||
- dmxScreen->rootHeight != h) {
- dmxUpdateScreenResources(screenInfo.screens[idx], x, y, w, h);
- }
-
- /* Change "root" window values */
- dmxScreen->rootX = x;
- dmxScreen->rootY = y;
- dmxScreen->rootWidth = w;
- dmxScreen->rootHeight = h;
-}
-
-/** Change the "root" window's origin by updating DMX's internal data
- * structures (dix and Xinerama) to use the new origin and adjust the
- * positions of windows that overlap this "root" window. */
-static void dmxSetRootWindowOrigin(int idx, int x, int y)
-{
- DMXScreenInfo *dmxScreen = &dmxScreens[idx];
- ScreenPtr pScreen = screenInfo.screens[idx];
- WindowPtr pRoot = pScreen->root;
- WindowPtr pChild;
- int xoff;
- int yoff;
-
- /* Change "root" window's origin */
- dmxScreen->rootXOrigin = x;
- dmxScreen->rootYOrigin = y;
-
- /* Compute offsets here in case <x,y> has been changed above */
- xoff = x - pScreen->x;
- yoff = y - pScreen->y;
-
- /* Adjust the root window's position */
- pScreen->x = dmxScreen->rootXOrigin;
- pScreen->y = dmxScreen->rootYOrigin;
-
- /* Recalculate the Xinerama regions and data structs */
- XineramaReinitData(pScreen);
-
- /* Adjust each of the root window's children */
- if (!idx) ReinitializeRootWindow(screenInfo.screens[0]->root, xoff, yoff);
- pChild = pRoot->firstChild;
- while (pChild) {
- /* Adjust child window's position */
- pScreen->MoveWindow(pChild,
- pChild->origin.x - wBorderWidth(pChild) - xoff,
- pChild->origin.y - wBorderWidth(pChild) - yoff,
- pChild->nextSib,
- VTMove);
-
- /* Note that the call to MoveWindow will eventually call
- * dmxPositionWindow which will automatically create a
- * window if it is now exposed on screen (for lazy window
- * creation optimization) and it will properly set the
- * offscreen flag.
- */
-
- pChild = pChild->nextSib;
- }
-}
-
-/** Configure the attributes of each "screen" and "root" window. */
-int dmxConfigureScreenWindows(int nscreens,
- CARD32 *screens,
- DMXScreenAttributesPtr attribs,
- int *errorScreen)
-{
- int i;
-
- for (i = 0; i < nscreens; i++) {
- DMXScreenAttributesPtr attr = &attribs[i];
- int idx = screens[i];
- DMXScreenInfo *dmxScreen = &dmxScreens[idx];
-
- if (errorScreen) *errorScreen = i;
-
- if (!dmxScreen->beDisplay) return DMX_BAD_VALUE;
-
- /* Check for illegal values */
- if (idx < 0 || idx >= dmxNumScreens) return BadValue;
-
- /* The "screen" and "root" windows must have valid sizes */
- if (attr->screenWindowWidth <= 0 || attr->screenWindowHeight <= 0 ||
- attr->rootWindowWidth < 0 || attr->rootWindowHeight < 0)
- return DMX_BAD_VALUE;
-
- /* The "screen" window must fit entirely within the BE display */
- if (attr->screenWindowXoffset < 0 ||
- attr->screenWindowYoffset < 0 ||
- attr->screenWindowXoffset
- + attr->screenWindowWidth > (unsigned)dmxScreen->beWidth ||
- attr->screenWindowYoffset
- + attr->screenWindowHeight > (unsigned)dmxScreen->beHeight)
- return DMX_BAD_VALUE;
-
- /* The "root" window must fit entirely within the "screen" window */
- if (attr->rootWindowXoffset < 0 ||
- attr->rootWindowYoffset < 0 ||
- attr->rootWindowXoffset
- + attr->rootWindowWidth > attr->screenWindowWidth ||
- attr->rootWindowYoffset
- + attr->rootWindowHeight > attr->screenWindowHeight)
- return DMX_BAD_VALUE;
-
- /* The "root" window must not expose unaddressable coordinates */
- if (attr->rootWindowXorigin < 0 ||
- attr->rootWindowYorigin < 0 ||
- attr->rootWindowXorigin + attr->rootWindowWidth > 32767 ||
- attr->rootWindowYorigin + attr->rootWindowHeight > 32767)
- return DMX_BAD_VALUE;
-
- /* The "root" window must fit within the global bounding box */
- if (attr->rootWindowXorigin
- + attr->rootWindowWidth > (unsigned)dmxGlobalWidth ||
- attr->rootWindowYorigin
- + attr->rootWindowHeight > (unsigned)dmxGlobalHeight)
- return DMX_BAD_VALUE;
-
- /* FIXME: Handle the rest of the illegal value checking */
- }
-
- /* No illegal values found */
- if (errorScreen) *errorScreen = 0;
-
- for (i = 0; i < nscreens; i++) {
- DMXScreenAttributesPtr attr = &attribs[i];
- int idx = screens[i];
- DMXScreenInfo *dmxScreen = &dmxScreens[idx];
-
- dmxLog(dmxInfo, "Changing screen #%d attributes "
- "from %dx%d+%d+%d %dx%d+%d+%d +%d+%d "
- "to %dx%d+%d+%d %dx%d+%d+%d +%d+%d\n",
- idx,
- dmxScreen->scrnWidth, dmxScreen->scrnHeight,
- dmxScreen->scrnX, dmxScreen->scrnY,
- dmxScreen->rootWidth, dmxScreen->rootHeight,
- dmxScreen->rootX, dmxScreen->rootY,
- dmxScreen->rootXOrigin, dmxScreen->rootYOrigin,
- attr->screenWindowWidth, attr->screenWindowHeight,
- attr->screenWindowXoffset, attr->screenWindowYoffset,
- attr->rootWindowWidth, attr->rootWindowHeight,
- attr->rootWindowXoffset, attr->rootWindowYoffset,
- attr->rootWindowXorigin, attr->rootWindowYorigin);
-
- /* Configure "screen" window */
- dmxConfigureScreenWindow(idx,
- attr->screenWindowXoffset,
- attr->screenWindowYoffset,
- attr->screenWindowWidth,
- attr->screenWindowHeight);
-
- /* Configure "root" window */
- dmxConfigureRootWindow(idx,
- attr->rootWindowXoffset,
- attr->rootWindowYoffset,
- attr->rootWindowWidth,
- attr->rootWindowHeight);
-
-
- /* Set "root" window's origin */
- dmxSetRootWindowOrigin(idx,
- attr->rootWindowXorigin,
- attr->rootWindowYorigin);
- }
-
- /* Adjust the cursor boundaries */
- dmxAdjustCursorBoundaries();
-
- /* Force completion of the changes */
- dmxSync(NULL, TRUE);
-
- return Success;
-}
-
-/** Configure the attributes of the global desktop. */
-int dmxConfigureDesktop(DMXDesktopAttributesPtr attribs)
-{
- if (attribs->width <= 0 || attribs->width >= 32767 ||
- attribs->height <= 0 || attribs->height >= 32767)
- return DMX_BAD_VALUE;
-
- /* If the desktop is shrinking, adjust the "root" windows on each
- * "screen" window to only show the visible desktop. Also, handle
- * the special case where the desktop shrinks such that the it no
- * longer overlaps an portion of a "screen" window. */
- if (attribs->width < dmxGlobalWidth || attribs->height < dmxGlobalHeight) {
- int i;
- for (i = 0; i < dmxNumScreens; i++) {
- DMXScreenInfo *dmxScreen = &dmxScreens[i];
- if (dmxScreen->rootXOrigin
- + dmxScreen->rootWidth > attribs->width ||
- dmxScreen->rootYOrigin
- + dmxScreen->rootHeight > attribs->height) {
- int w, h;
- if ((w = attribs->width - dmxScreen->rootXOrigin) < 0) w = 0;
- if ((h = attribs->height - dmxScreen->rootYOrigin) < 0) h = 0;
- if (w > dmxScreen->scrnWidth) w = dmxScreen->scrnWidth;
- if (h > dmxScreen->scrnHeight) h = dmxScreen->scrnHeight;
- if (w > dmxScreen->rootWidth) w = dmxScreen->rootWidth;
- if (h > dmxScreen->rootHeight) h = dmxScreen->rootHeight;
- dmxConfigureRootWindow(i,
- dmxScreen->rootX,
- dmxScreen->rootY,
- w, h);
- }
- }
- }
-
- /* Set the global width/height */
- dmxSetWidthHeight(attribs->width, attribs->height);
-
- /* Handle shift[XY] changes */
- if (attribs->shiftX || attribs->shiftY) {
- int i;
- for (i = 0; i < dmxNumScreens; i++) {
- ScreenPtr pScreen = screenInfo.screens[i];
- WindowPtr pChild = pScreen->root->firstChild;
- while (pChild) {
- /* Adjust child window's position */
- pScreen->MoveWindow(pChild,
- pChild->origin.x - wBorderWidth(pChild)
- - attribs->shiftX,
- pChild->origin.y - wBorderWidth(pChild)
- - attribs->shiftY,
- pChild->nextSib,
- VTMove);
-
- /* Note that the call to MoveWindow will eventually call
- * dmxPositionWindow which will automatically create a
- * window if it is now exposed on screen (for lazy
- * window creation optimization) and it will properly
- * set the offscreen flag.
- */
-
- pChild = pChild->nextSib;
- }
- }
- }
-
- /* Update connection block, Xinerama, etc. -- these appears to
- * already be handled in dmxConnectionBlockCallback(), which is
- * called from dmxAdjustCursorBoundaries() [below]. */
-
- /* Adjust the cursor boundaries */
- dmxAdjustCursorBoundaries();
-
- /* Force completion of the changes */
- dmxSync(NULL, TRUE);
-
- return Success;
-}
-#endif
-
-/** Create the scratch GCs per depth. */
-static void dmxBECreateScratchGCs(int scrnNum)
-{
- ScreenPtr pScreen = screenInfo.screens[scrnNum];
- GCPtr *ppGC = pScreen->GCperDepth;
- int i;
-
- for (i = 0; i <= pScreen->numDepths; i++)
- dmxBECreateGC(pScreen, ppGC[i]);
-}
-
-#ifdef PANORAMIX
-static Bool FoundPixImage;
-
-/** Search the Xinerama XRT_PIXMAP resources for the pixmap that needs
- * to have its image restored. When it is found, see if there is
- * another screen with the same image. If so, copy the pixmap image
- * from the existing screen to the newly created pixmap. */
-static void dmxBERestorePixmapImage(pointer value, XID id, RESTYPE type,
- pointer p)
-{
- if ((type & TypeMask) == (XRT_PIXMAP & TypeMask)) {
- PixmapPtr pDst = (PixmapPtr)p;
- int idx = pDst->drawable.pScreen->myNum;
- PanoramiXRes *pXinPix = (PanoramiXRes *)value;
- PixmapPtr pPix;
- int i;
-
- dixLookupResourceByType((pointer*) &pPix, pXinPix->info[idx].id,
- RT_PIXMAP, NullClient, DixUnknownAccess);
- if (pPix != pDst) return; /* Not a match.... Next! */
-
- for (i = 0; i < PanoramiXNumScreens; i++) {
- PixmapPtr pSrc;
- dmxPixPrivPtr pSrcPriv = NULL;
-
- if (i == idx) continue; /* Self replication is bad */
-
- dixLookupResourceByType((pointer*) &pSrc, pXinPix->info[i].id,
- RT_PIXMAP, NullClient, DixUnknownAccess);
- pSrcPriv = DMX_GET_PIXMAP_PRIV(pSrc);
- if (pSrcPriv->pixmap) {
- DMXScreenInfo *dmxSrcScreen = &dmxScreens[i];
- DMXScreenInfo *dmxDstScreen = &dmxScreens[idx];
- dmxPixPrivPtr pDstPriv = DMX_GET_PIXMAP_PRIV(pDst);
- XImage *img;
- int j;
- XlibGC gc = NULL;
-
- /* This should never happen, but just in case.... */
- if (pSrc->drawable.width != pDst->drawable.width ||
- pSrc->drawable.height != pDst->drawable.height)
- return;
-
- /* Copy from src pixmap to dst pixmap */
- img = XGetImage(dmxSrcScreen->beDisplay,
- pSrcPriv->pixmap,
- 0, 0,
- pSrc->drawable.width, pSrc->drawable.height,
- -1,
- ZPixmap);
-
- for (j = 0; j < dmxDstScreen->beNumPixmapFormats; j++) {
- if (dmxDstScreen->bePixmapFormats[j].depth == img->depth) {
- unsigned long m;
- XGCValues v;
-
- m = GCFunction | GCPlaneMask | GCClipMask;
- v.function = GXcopy;
- v.plane_mask = AllPlanes;
- v.clip_mask = None;
-
- gc = XCreateGC(dmxDstScreen->beDisplay,
- dmxDstScreen->scrnDefDrawables[j],
- m, &v);
- break;
- }
- }
-
- if (gc) {
- XPutImage(dmxDstScreen->beDisplay,
- pDstPriv->pixmap,
- gc, img, 0, 0, 0, 0,
- pDst->drawable.width, pDst->drawable.height);
- XFreeGC(dmxDstScreen->beDisplay, gc);
- FoundPixImage = True;
- } else {
- dmxLog(dmxWarning, "Could not create GC\n");
- }
-
- XDestroyImage(img);
- return;
- }
- }
- }
-}
-#endif
-
-/** Restore the pixmap image either from another screen or from an image
- * that was saved when the screen was previously detached. */
-static void dmxBERestorePixmap(PixmapPtr pPixmap)
-{
-#ifdef PANORAMIX
- int i;
-
- /* If Xinerama is not active, there's nothing we can do (see comment
- * in #else below for more info). */
- if (noPanoramiXExtension) {
- dmxLog(dmxWarning, "Cannot restore pixmap image\n");
- return;
- }
-
- FoundPixImage = False;
- for (i = currentMaxClients; --i >= 0; )
- if (clients[i])
- FindAllClientResources(clients[i], dmxBERestorePixmapImage,
- (pointer)pPixmap);
-
- /* No corresponding pixmap image was found on other screens, so we
- * need to copy it from the saved image when the screen was detached
- * (if available). */
- if (!FoundPixImage) {
- dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV(pPixmap);
-
- if (pPixPriv->detachedImage) {
- ScreenPtr pScreen = pPixmap->drawable.pScreen;
- DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
- XlibGC gc = NULL;
-
- for (i = 0; i < dmxScreen->beNumPixmapFormats; i++) {
- if (dmxScreen->bePixmapFormats[i].depth ==
- pPixPriv->detachedImage->depth) {
- unsigned long m;
- XGCValues v;
-
- m = GCFunction | GCPlaneMask | GCClipMask;
- v.function = GXcopy;
- v.plane_mask = AllPlanes;
- v.clip_mask = None;
-
- gc = XCreateGC(dmxScreen->beDisplay,
- dmxScreen->scrnDefDrawables[i],
- m, &v);
- break;
- }
- }
-
- if (gc) {
- XPutImage(dmxScreen->beDisplay,
- pPixPriv->pixmap,
- gc,
- pPixPriv->detachedImage,
- 0, 0, 0, 0,
- pPixmap->drawable.width, pPixmap->drawable.height);
- XFreeGC(dmxScreen->beDisplay, gc);
- } else {
- dmxLog(dmxWarning, "Cannot restore pixmap image\n");
- }
-
- XDestroyImage(pPixPriv->detachedImage);
- pPixPriv->detachedImage = NULL;
- } else {
- dmxLog(dmxWarning, "Cannot restore pixmap image\n");
- }
- }
-#else
- /* If Xinerama is not enabled, then there is no other copy of the
- * pixmap image that we can restore. Saving all pixmap data is not
- * a feasible option since there is no mechanism for updating pixmap
- * data when a screen is detached, which means that the data that
- * was previously saved would most likely be out of date. */
- dmxLog(dmxWarning, "Cannot restore pixmap image\n");
- return;
-#endif
-}
-
-/** Create resources on the back-end server. This function is called
- * from #dmxAttachScreen() via the dix layer's FindAllResources
- * function. It walks all resources, compares them to the screen
- * number passed in as \a n and calls the appropriate DMX function to
- * create the associated resource on the back-end server. */
-static void dmxBECreateResources(pointer value, XID id, RESTYPE type,
- pointer n)
-{
- int scrnNum = (uintptr_t)n;
- ScreenPtr pScreen = screenInfo.screens[scrnNum];
-
- if ((type & TypeMask) == (RT_WINDOW & TypeMask)) {
- /* Window resources are created below in dmxBECreateWindowTree */
- } else if ((type & TypeMask) == (RT_PIXMAP & TypeMask)) {
- PixmapPtr pPix = value;
- if (pPix->drawable.pScreen->myNum == scrnNum) {
- dmxBECreatePixmap(pPix);
- dmxBERestorePixmap(pPix);
- }
- } else if ((type & TypeMask) == (RT_GC & TypeMask)) {
- GCPtr pGC = value;
- if (pGC->pScreen->myNum == scrnNum) {
- /* Create the GC on the back-end server */
- dmxBECreateGC(pScreen, pGC);
- /* Create any pixmaps associated with this GC */
- if (!pGC->tileIsPixel) {
- dmxBECreatePixmap(pGC->tile.pixmap);
- dmxBERestorePixmap(pGC->tile.pixmap);
- }
- if (pGC->stipple != pScreen->PixmapPerDepth[0]) {
- dmxBECreatePixmap(pGC->stipple);
- dmxBERestorePixmap(pGC->stipple);
- }
- if (pGC->font != defaultFont) {
- (void)dmxBELoadFont(pScreen, pGC->font);
- }
- /* Update the GC on the back-end server */
- dmxChangeGC(pGC, -1L);
- }
- } else if ((type & TypeMask) == (RT_FONT & TypeMask)) {
- (void)dmxBELoadFont(pScreen, (FontPtr)value);
- } else if ((type & TypeMask) == (RT_CURSOR & TypeMask)) {
- dmxBECreateCursor(pScreen, (CursorPtr)value);
- } else if ((type & TypeMask) == (RT_COLORMAP & TypeMask)) {
- ColormapPtr pCmap = value;
- if (pCmap->pScreen->myNum == scrnNum)
- (void)dmxBECreateColormap((ColormapPtr)value);
-#if 0
- /* TODO: Recreate Picture and GlyphSet resources */
- } else if ((type & TypeMask) == (PictureType & TypeMask)) {
- /* Picture resources are created when windows are created */
- } else if ((type & TypeMask) == (GlyphSetType & TypeMask)) {
- dmxBEFreeGlyphSet(pScreen, (GlyphSetPtr)value);
-#endif
- } else {
- /* Other resource types??? */
- }
-}
-
-/** Create window hierachy on back-end server. The window tree is
- * created in a special order (bottom most subwindow first) so that the
- * #dmxCreateNonRootWindow() function does not need to recursively call
- * itself to create each window's parents. This is required so that we
- * have the opportunity to create each window's border and background
- * pixmaps (where appropriate) before the window is created. */
-static void dmxBECreateWindowTree(int idx)
-{
- DMXScreenInfo *dmxScreen = &dmxScreens[idx];
- WindowPtr pRoot = screenInfo.screens[idx]->root;
- dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pRoot);
- WindowPtr pWin;
-
- /* Create the pixmaps associated with the root window */
- if (!pRoot->borderIsPixel) {
- dmxBECreatePixmap(pRoot->border.pixmap);
- dmxBERestorePixmap(pRoot->border.pixmap);
- }
- if (pRoot->backgroundState == BackgroundPixmap) {
- dmxBECreatePixmap(pRoot->background.pixmap);
- dmxBERestorePixmap(pRoot->background.pixmap);
- }
-
- /* Create root window first */
- dmxScreen->rootWin = pWinPriv->window = dmxCreateRootWindow(pRoot);
- XMapWindow(dmxScreen->beDisplay, dmxScreen->rootWin);
-
- pWin = pRoot->lastChild;
- while (pWin) {
- pWinPriv = DMX_GET_WINDOW_PRIV(pWin);
-
- /* Create the pixmaps regardless of whether or not the
- * window is created or not due to lazy window creation.
- */
- if (!pWin->borderIsPixel) {
- dmxBECreatePixmap(pWin->border.pixmap);
- dmxBERestorePixmap(pWin->border.pixmap);
- }
- if (pWin->backgroundState == BackgroundPixmap) {
- dmxBECreatePixmap(pWin->background.pixmap);
- dmxBERestorePixmap(pWin->background.pixmap);
- }
-
- /* Reset the window attributes */
- dmxGetDefaultWindowAttributes(pWin,
- &pWinPriv->cmap,
- &pWinPriv->visual);
-
- /* Create the window */
- if (pWinPriv->mapped && !pWinPriv->offscreen)
- dmxCreateAndRealizeWindow(pWin, TRUE);
-
- /* Next, create the bottom-most child */
- if (pWin->lastChild) {
- pWin = pWin->lastChild;
- continue;
- }
-
- /* If the window has no children, move on to the next higher window */
- while (!pWin->prevSib && (pWin != pRoot))
- pWin = pWin->parent;
-
- if (pWin->prevSib) {
- pWin = pWin->prevSib;
- continue;
- }
-
- /* When we reach the root window, we are finished */
- if (pWin == pRoot)
- break;
- }
-}
-
-/* Refresh screen by generating exposure events for all windows */
-static void dmxForceExposures(int idx)
-{
- ScreenPtr pScreen = screenInfo.screens[idx];
- WindowPtr pRoot = pScreen->root;
- Bool anyMarked = FALSE;
- WindowPtr pChild;
-
- for (pChild = pRoot->firstChild; pChild; pChild = pChild->nextSib)
- anyMarked |= pScreen->MarkOverlappedWindows(pChild, pChild,
- (WindowPtr *)NULL);
- if (anyMarked) {
- /* If any windows have been marked, set the root window's
- * clipList to be broken since it will be recalculated in
- * ValidateTree()
- */
- RegionBreak(&pRoot->clipList);
- pScreen->ValidateTree(pRoot, NULL, VTBroken);
- pScreen->HandleExposures(pRoot);
- if (pScreen->PostValidateTree)
- pScreen->PostValidateTree(pRoot, NULL, VTBroken);
- }
-}
-
-/** Compare the new and old screens to see if they are compatible. */
-static Bool dmxCompareScreens(DMXScreenInfo *new, DMXScreenInfo *old)
-{
- int i;
-
- if (new->beWidth != old->beWidth) return FALSE;
- if (new->beHeight != old->beHeight) return FALSE;
- if (new->beDepth != old->beDepth) return FALSE;
- if (new->beBPP != old->beBPP) return FALSE;
-
- if (new->beNumDepths != old->beNumDepths) return FALSE;
- for (i = 0; i < old->beNumDepths; i++)
- if (new->beDepths[i] != old->beDepths[i]) return FALSE;
-
- if (new->beNumPixmapFormats != old->beNumPixmapFormats) return FALSE;
- for (i = 0; i < old->beNumPixmapFormats; i++) {
- if (new->bePixmapFormats[i].depth !=
- old->bePixmapFormats[i].depth) return FALSE;
- if (new->bePixmapFormats[i].bits_per_pixel !=
- old->bePixmapFormats[i].bits_per_pixel) return FALSE;
- if (new->bePixmapFormats[i].scanline_pad !=
- old->bePixmapFormats[i].scanline_pad) return FALSE;
- }
-
- if (new->beNumVisuals != old->beNumVisuals) return FALSE;
- for (i = 0; i < old->beNumVisuals; i++) {
- if (new->beVisuals[i].visualid !=
- old->beVisuals[i].visualid) return FALSE;
- if (new->beVisuals[i].screen !=
- old->beVisuals[i].screen) return FALSE;
- if (new->beVisuals[i].depth !=
- old->beVisuals[i].depth) return FALSE;
- if (new->beVisuals[i].class !=
- old->beVisuals[i].class) return FALSE;
- if (new->beVisuals[i].red_mask !=
- old->beVisuals[i].red_mask) return FALSE;
- if (new->beVisuals[i].green_mask !=
- old->beVisuals[i].green_mask) return FALSE;
- if (new->beVisuals[i].blue_mask !=
- old->beVisuals[i].blue_mask) return FALSE;
- if (new->beVisuals[i].colormap_size !=
- old->beVisuals[i].colormap_size) return FALSE;
- if (new->beVisuals[i].bits_per_rgb !=
- old->beVisuals[i].bits_per_rgb) return FALSE;
- }
-
- if (new->beDefVisualIndex != old->beDefVisualIndex) return FALSE;
-
- return TRUE;
-}
-
-/** Restore Render's picture */
-static void dmxBERestoreRenderPict(pointer value, XID id, pointer n)
-{
- PicturePtr pPicture = value; /* The picture */
- DrawablePtr pDraw = pPicture->pDrawable; /* The picture's drawable */
- int scrnNum = (uintptr_t)n;
-
- if (pDraw->pScreen->myNum != scrnNum) {
- /* Picture not on the screen we are restoring*/
- return;
- }
-
- if (pDraw->type == DRAWABLE_PIXMAP) {
- PixmapPtr pPixmap = (PixmapPtr)pDraw;
-
- /* Create and restore the pixmap drawable */
- dmxBECreatePixmap(pPixmap);
- dmxBERestorePixmap(pPixmap);
- }
-
- dmxBECreatePicture(pPicture);
-}
-
-/** Restore Render's glyphs */
-static void dmxBERestoreRenderGlyph(pointer value, XID id, pointer n)
-{
- GlyphSetPtr glyphSet = value;
- int scrnNum = (uintptr_t)n;
- dmxGlyphPrivPtr glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
- DMXScreenInfo *dmxScreen = &dmxScreens[scrnNum];
- GlyphRefPtr table;
- char *images;
- Glyph *gids;
- XGlyphInfo *glyphs;
- char *pos;
- int beret;
- int len_images = 0;
- int i;
- int ctr;
-
- if (glyphPriv->glyphSets[scrnNum]) {
- /* Only restore glyphs on the screen we are attaching */
- return;
- }
-
- /* First we must create the glyph set on the backend. */
- if ((beret = dmxBECreateGlyphSet(scrnNum, glyphSet)) != Success) {
- dmxLog(dmxWarning,
- "\tdmxBERestoreRenderGlyph failed to create glyphset!\n");
- return;
- }
-
- /* Now for the complex part, restore the glyph data */
- table = glyphSet->hash.table;
-
- /* We need to know how much memory to allocate for this part */
- for (i = 0; i < glyphSet->hash.hashSet->size; i++) {
- GlyphRefPtr gr = &table[i];
- GlyphPtr gl = gr->glyph;
-
- if (!gl || gl == DeletedGlyph) continue;
- len_images += gl->size - sizeof(gl->info);
- }
-
- /* Now allocate the memory we need */
- images = calloc(len_images, sizeof(char));
- gids = malloc(glyphSet->hash.tableEntries*sizeof(Glyph));
- glyphs = malloc(glyphSet->hash.tableEntries*sizeof(XGlyphInfo));
-
- pos = images;
- ctr = 0;
-
- /* Fill the allocated memory with the proper data */
- for (i = 0; i < glyphSet->hash.hashSet->size; i++) {
- GlyphRefPtr gr = &table[i];
- GlyphPtr gl = gr->glyph;
-
- if (!gl || gl == DeletedGlyph) continue;
-
- /* First lets put the data into gids */
- gids[ctr] = gr->signature;
-
- /* Next do the glyphs data structures */
- glyphs[ctr].width = gl->info.width;
- glyphs[ctr].height = gl->info.height;
- glyphs[ctr].x = gl->info.x;
- glyphs[ctr].y = gl->info.y;
- glyphs[ctr].xOff = gl->info.xOff;
- glyphs[ctr].yOff = gl->info.yOff;
-
- /* Copy the images from the DIX's data into the buffer */
- memcpy(pos, gl+1, gl->size - sizeof(gl->info));
- pos += gl->size - sizeof(gl->info);
- ctr++;
- }
-
- /* Now restore the glyph data */
- XRenderAddGlyphs(dmxScreen->beDisplay, glyphPriv->glyphSets[scrnNum],
- gids,glyphs, glyphSet->hash.tableEntries, images,
- len_images);
-
- /* Clean up */
- free(images);
- free(gids);
- free(glyphs);
-}
-
-/** Reattach previously detached back-end screen. */
-int dmxAttachScreen(int idx, DMXScreenAttributesPtr attr)
-{
- ScreenPtr pScreen;
- DMXScreenInfo *dmxScreen;
- CARD32 scrnNum = idx;
- DMXScreenInfo oldDMXScreen;
- int i;
-
- /* Return failure if dynamic addition/removal of screens is disabled */
- if (!dmxAddRemoveScreens) {
- dmxLog(dmxWarning,
- "Attempting to add a screen, but the AddRemoveScreen\n");
- dmxLog(dmxWarning,
- "extension has not been enabled. To enable this extension\n");
- dmxLog(dmxWarning,
- "add the \"-addremovescreens\" option either to the command\n");
- dmxLog(dmxWarning,
- "line or in the configuration file.\n");
- return 1;
- }
-
- /* Cannot add a screen that does not exist */
- if (idx < 0 || idx >= dmxNumScreens) return 1;
- pScreen = screenInfo.screens[idx];
- dmxScreen = &dmxScreens[idx];
-
- /* Cannot attach to a screen that is already opened */
- if (dmxScreen->beDisplay) {
- dmxLog(dmxWarning,
- "Attempting to add screen #%d but a screen already exists\n",
- idx);
- return 1;
- }
-
- dmxLogOutput(dmxScreen, "Attaching screen #%d\n", idx);
-
- /* Save old info */
- oldDMXScreen = *dmxScreen;
-
- /* Copy the name to the new screen */
- dmxScreen->name = strdup(attr->displayName);
-
- /* Open display and get all of the screen info */
- if (!dmxOpenDisplay(dmxScreen)) {
- dmxLog(dmxWarning,
- "dmxOpenDisplay: Unable to open display %s\n",
- dmxScreen->name);
-
- /* Restore the old screen */
- *dmxScreen = oldDMXScreen;
- return 1;
- }
-
- dmxSetErrorHandler(dmxScreen);
- dmxCheckForWM(dmxScreen);
- dmxGetScreenAttribs(dmxScreen);
-
- if (!dmxGetVisualInfo(dmxScreen)) {
- dmxLog(dmxWarning, "dmxGetVisualInfo: No matching visuals found\n");
- XFree(dmxScreen->beVisuals);
- XCloseDisplay(dmxScreen->beDisplay);
-
- /* Restore the old screen */
- *dmxScreen = oldDMXScreen;
- return 1;
- }
-
- dmxGetColormaps(dmxScreen);
- dmxGetPixmapFormats(dmxScreen);
-
- /* Verify that the screen to be added has the same info as the
- * previously added screen. */
- if (!dmxCompareScreens(dmxScreen, &oldDMXScreen)) {
- dmxLog(dmxWarning,
- "New screen data (%s) does not match previously\n",
- dmxScreen->name);
- dmxLog(dmxWarning,
- "attached screen data (%s)\n",
- oldDMXScreen.name);
- dmxLog(dmxWarning,
- "All data must match in order to attach to screen #%d\n",
- idx);
- XFree(dmxScreen->beVisuals);
- XFree(dmxScreen->beDepths);
- XFree(dmxScreen->bePixmapFormats);
- XCloseDisplay(dmxScreen->beDisplay);
-
- /* Restore the old screen */
- *dmxScreen = oldDMXScreen;
- return 1;
- }
-
- /* Initialize the BE screen resources */
- dmxBEScreenInit(idx, screenInfo.screens[idx]);
-
- /* TODO: Handle GLX visual initialization. GLXProxy needs to be
- * updated to handle dynamic addition/removal of screens. */
-
- /* Create default stipple */
- dmxBECreatePixmap(pScreen->PixmapPerDepth[0]);
- dmxBERestorePixmap(pScreen->PixmapPerDepth[0]);
-
- /* Create the scratch GCs */
- dmxBECreateScratchGCs(idx);
-
- /* Create the default font */
- (void)dmxBELoadFont(pScreen, defaultFont);
-
- /* Create all resources that don't depend on windows */
- for (i = currentMaxClients; --i >= 0; )
- if (clients[i])
- FindAllClientResources(clients[i], dmxBECreateResources,
- (pointer)(uintptr_t)idx);
-
- /* Create window hierarchy (top down) */
- dmxBECreateWindowTree(idx);
-
- /* Restore the picture state for RENDER */
- for (i = currentMaxClients; --i >= 0; )
- if (clients[i])
- FindClientResourcesByType(clients[i],PictureType,
- dmxBERestoreRenderPict,
- (pointer)(uintptr_t)idx);
-
- /* Restore the glyph state for RENDER */
- for (i = currentMaxClients; --i >= 0; )
- if (clients[i])
- FindClientResourcesByType(clients[i],GlyphSetType,
- dmxBERestoreRenderGlyph,
- (pointer)(uintptr_t)idx);
-
- /* Refresh screen by generating exposure events for all windows */
- dmxForceExposures(idx);
-
- dmxSync(&dmxScreens[idx], TRUE);
-
- /* We used these to compare the old and new screens. They are no
- * longer needed since we have a newly attached screen, so we can
- * now free the old screen's resources. */
- XFree(oldDMXScreen.beVisuals);
- XFree(oldDMXScreen.beDepths);
- XFree(oldDMXScreen.bePixmapFormats);
- /* TODO: should oldDMXScreen.name be freed?? */
-
-#ifdef PANORAMIX
- if (!noPanoramiXExtension)
- return dmxConfigureScreenWindows(1, &scrnNum, attr, NULL);
- else
-#endif
- return 0; /* Success */
-}
-
-/*
- * Resources that may have state on the BE server and need to be freed:
- *
- * RT_NONE
- * RT_WINDOW
- * RT_PIXMAP
- * RT_GC
- * RT_FONT
- * RT_CURSOR
- * RT_COLORMAP
- * RT_CMAPENTRY
- * RT_OTHERCLIENT
- * RT_PASSIVEGRAB
- * XRT_WINDOW
- * XRT_PIXMAP
- * XRT_GC
- * XRT_COLORMAP
- * XRT_PICTURE
- * PictureType
- * PictFormatType
- * GlyphSetType
- * ClientType
- * EventType
- * RT_INPUTCLIENT
- * XETrapType
- * RTCounter
- * RTAwait
- * RTAlarmClient
- * RT_XKBCLIENT
- * RTContext
- * TagResType
- * StalledResType
- * SecurityAuthorizationResType
- * RTEventClient
- * __glXContextRes
- * __glXClientRes
- * __glXPixmapRes
- * __glXWindowRes
- * __glXPbufferRes
- */
-
-#ifdef PANORAMIX
-/** Search the Xinerama XRT_PIXMAP resources for the pixmap that needs
- * to have its image saved. */
-static void dmxBEFindPixmapImage(pointer value, XID id, RESTYPE type,
- pointer p)
-{
- if ((type & TypeMask) == (XRT_PIXMAP & TypeMask)) {
- PixmapPtr pDst = (PixmapPtr)p;
- int idx = pDst->drawable.pScreen->myNum;
- PanoramiXRes *pXinPix = (PanoramiXRes *)value;
- PixmapPtr pPix;
- int i;
-
- dixLookupResourceByType((pointer*) &pPix, pXinPix->info[idx].id,
- RT_PIXMAP, NullClient, DixUnknownAccess);
- if (pPix != pDst) return; /* Not a match.... Next! */
-
- for (i = 0; i < PanoramiXNumScreens; i++) {
- PixmapPtr pSrc;
- dmxPixPrivPtr pSrcPriv = NULL;
-
- if (i == idx) continue; /* Self replication is bad */
-
- dixLookupResourceByType((pointer*) &pSrc, pXinPix->info[i].id,
- RT_PIXMAP, NullClient, DixUnknownAccess);
- pSrcPriv = DMX_GET_PIXMAP_PRIV(pSrc);
- if (pSrcPriv->pixmap) {
- FoundPixImage = True;
- return;
- }
- }
- }
-}
-#endif
-
-/** Save the pixmap image only when there is not another screen with
- * that pixmap from which the image can be read when the screen is
- * reattached. To do this, we first try to find a pixmap on another
- * screen corresponding to the one we are trying to save. If we find
- * one, then we do not need to save the image data since during
- * reattachment, the image data can be read from that other pixmap.
- * However, if we do not find one, then we need to save the image data.
- * The common case for these are for the default stipple and root
- * tile. */
-static void dmxBESavePixmap(PixmapPtr pPixmap)
-{
-#ifdef PANORAMIX
- int i;
-
- /* If Xinerama is not active, there's nothing we can do (see comment
- * in #else below for more info). */
- if (noPanoramiXExtension) return;
-
- FoundPixImage = False;
- for (i = currentMaxClients; --i >= 0; )
- if (clients[i])
- FindAllClientResources(clients[i], dmxBEFindPixmapImage,
- (pointer)pPixmap);
-
- /* Save the image only if there is no other screens that have a
- * pixmap that corresponds to the one we are trying to save. */
- if (!FoundPixImage) {
- dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV(pPixmap);
-
- if (!pPixPriv->detachedImage) {
- ScreenPtr pScreen = pPixmap->drawable.pScreen;
- DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
-
- pPixPriv->detachedImage = XGetImage(dmxScreen->beDisplay,
- pPixPriv->pixmap,
- 0, 0,
- pPixmap->drawable.width,
- pPixmap->drawable.height,
- -1,
- ZPixmap);
- if (!pPixPriv->detachedImage)
- dmxLog(dmxWarning, "Cannot save pixmap image\n");
- }
- }
-#else
- /* NOTE: The only time there is a pixmap on another screen that
- * corresponds to the one we are trying to save is when Xinerama is
- * active. Otherwise, the pixmap image data is only stored on a
- * single screen, which means that once it is detached, that data is
- * lost. We could save the data here, but then that would require
- * us to implement the ability for Xdmx to keep the pixmap up to
- * date while the screen is detached, which is beyond the scope of
- * the current project. */
- return;
-#endif
-}
-
-/** Destroy resources on the back-end server. This function is called
- * from #dmxDetachScreen() via the dix layer's FindAllResources
- * function. It walks all resources, compares them to the screen
- * number passed in as \a n and calls the appropriate DMX function to
- * free the associated resource on the back-end server. */
-static void dmxBEDestroyResources(pointer value, XID id, RESTYPE type,
- pointer n)
-{
- int scrnNum = (uintptr_t)n;
- ScreenPtr pScreen = screenInfo.screens[scrnNum];
-
- if ((type & TypeMask) == (RT_WINDOW & TypeMask)) {
- /* Window resources are destroyed below in dmxBEDestroyWindowTree */
- } else if ((type & TypeMask) == (RT_PIXMAP & TypeMask)) {
- PixmapPtr pPix = value;
- if (pPix->drawable.pScreen->myNum == scrnNum) {
- dmxBESavePixmap(pPix);
- dmxBEFreePixmap(pPix);
- }
- } else if ((type & TypeMask) == (RT_GC & TypeMask)) {
- GCPtr pGC = value;
- if (pGC->pScreen->myNum == scrnNum)
- dmxBEFreeGC(pGC);
- } else if ((type & TypeMask) == (RT_FONT & TypeMask)) {
- dmxBEFreeFont(pScreen, (FontPtr)value);
- } else if ((type & TypeMask) == (RT_CURSOR & TypeMask)) {
- dmxBEFreeCursor(pScreen, (CursorPtr)value);
- } else if ((type & TypeMask) == (RT_COLORMAP & TypeMask)) {
- ColormapPtr pCmap = value;
- if (pCmap->pScreen->myNum == scrnNum)
- dmxBEFreeColormap((ColormapPtr)value);
- } else if ((type & TypeMask) == (PictureType & TypeMask)) {
- PicturePtr pPict = value;
- if (pPict->pDrawable->pScreen->myNum == scrnNum) {
- /* Free the pixmaps on the backend if needed */
- if (pPict->pDrawable->type == DRAWABLE_PIXMAP) {
- PixmapPtr pPixmap = (PixmapPtr)(pPict->pDrawable);
- dmxBESavePixmap(pPixmap);
- dmxBEFreePixmap(pPixmap);
- }
- dmxBEFreePicture((PicturePtr)value);
- }
- } else if ((type & TypeMask) == (GlyphSetType & TypeMask)) {
- dmxBEFreeGlyphSet(pScreen, (GlyphSetPtr)value);
- } else {
- /* Other resource types??? */
- }
-}
-
-/** Destroy the scratch GCs that are created per depth. */
-static void dmxBEDestroyScratchGCs(int scrnNum)
-{
- ScreenPtr pScreen = screenInfo.screens[scrnNum];
- GCPtr *ppGC = pScreen->GCperDepth;
- int i;
-
- for (i = 0; i <= pScreen->numDepths; i++)
- dmxBEFreeGC(ppGC[i]);
-}
-
-/** Destroy window hierachy on back-end server. To ensure that all
- * XDestroyWindow() calls succeed, they must be performed in a bottom
- * up order so that windows are not destroyed before their children.
- * XDestroyWindow(), which is called from #dmxBEDestroyWindow(), will
- * destroy a window as well as all of it's children. */
-static void dmxBEDestroyWindowTree(int idx)
-{
- WindowPtr pWin = screenInfo.screens[idx]->root;
- WindowPtr pChild = pWin;
-
- while (1) {
- if (pChild->firstChild) {
- pChild = pChild->firstChild;
- continue;
- }
-
- /* Destroy the window */
- dmxBEDestroyWindow(pChild);
-
- /* Make sure we destroy the window's border and background
- * pixmaps if they exist */
- if (!pChild->borderIsPixel) {
- dmxBESavePixmap(pChild->border.pixmap);
- dmxBEFreePixmap(pChild->border.pixmap);
- }
- if (pChild->backgroundState == BackgroundPixmap) {
- dmxBESavePixmap(pChild->background.pixmap);
- dmxBEFreePixmap(pChild->background.pixmap);
- }
-
- while (!pChild->nextSib && (pChild != pWin)) {
- pChild = pChild->parent;
- dmxBEDestroyWindow(pChild);
- if (!pChild->borderIsPixel) {
- dmxBESavePixmap(pChild->border.pixmap);
- dmxBEFreePixmap(pChild->border.pixmap);
- }
- if (pChild->backgroundState == BackgroundPixmap) {
- dmxBESavePixmap(pChild->background.pixmap);
- dmxBEFreePixmap(pChild->background.pixmap);
- }
- }
-
- if (pChild == pWin)
- break;
-
- pChild = pChild->nextSib;
- }
-}
-
-/** Detach back-end screen. */
-int dmxDetachScreen(int idx)
-{
- DMXScreenInfo *dmxScreen = &dmxScreens[idx];
- int i;
-
- /* Return failure if dynamic addition/removal of screens is disabled */
- if (!dmxAddRemoveScreens) {
- dmxLog(dmxWarning,
- "Attempting to remove a screen, but the AddRemoveScreen\n");
- dmxLog(dmxWarning,
- "extension has not been enabled. To enable this extension\n");
- dmxLog(dmxWarning,
- "add the \"-addremovescreens\" option either to the command\n");
- dmxLog(dmxWarning,
- "line or in the configuration file.\n");
- return 1;
- }
-
- /* Cannot remove a screen that does not exist */
- if (idx < 0 || idx >= dmxNumScreens) return 1;
-
- /* Cannot detach from a screen that is not opened */
- if (!dmxScreen->beDisplay) {
- dmxLog(dmxWarning,
- "Attempting to remove screen #%d but it has not been opened\n",
- idx);
- return 1;
- }
-
- dmxLogOutput(dmxScreen, "Detaching screen #%d\n", idx);
-
- /* Detach input */
- dmxInputDetachAll(dmxScreen);
-
- /* Save all relevant state (TODO) */
-
- /* Free all non-window resources related to this screen */
- for (i = currentMaxClients; --i >= 0; )
- if (clients[i])
- FindAllClientResources(clients[i], dmxBEDestroyResources,
- (pointer)(uintptr_t)idx);
-
- /* Free scratch GCs */
- dmxBEDestroyScratchGCs(idx);
-
- /* Free window resources related to this screen */
- dmxBEDestroyWindowTree(idx);
-
- /* Free default stipple */
- dmxBESavePixmap(screenInfo.screens[idx]->PixmapPerDepth[0]);
- dmxBEFreePixmap(screenInfo.screens[idx]->PixmapPerDepth[0]);
-
- /* Free the remaining screen resources and close the screen */
- dmxBECloseScreen(screenInfo.screens[idx]);
-
- /* Adjust the cursor boundaries (paints detached console window) */
- dmxAdjustCursorBoundaries();
-
- return 0; /* Success */
-}
+/*
+ * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina.
+ *
+ * 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 on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR 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.
+ */
+
+/*
+ * Author:
+ * Rickard E. (Rik) Faith <faith@redhat.com>
+ * Kevin E. Martin <kem@redhat.com>
+ *
+ */
+
+/** \file
+ * This file provides the only interface to the X server extension support
+ * in programs/Xserver/Xext. Those programs should only include dmxext.h
+ */
+
+#ifdef HAVE_DMX_CONFIG_H
+#include <dmx-config.h>
+#endif
+
+#include <stdlib.h>
+
+#include "dmx.h"
+#include "dmxinit.h"
+#include "dmxextension.h"
+#include "dmxwindow.h"
+#include "dmxcb.h"
+#include "dmxcursor.h"
+#include "dmxpixmap.h"
+#include "dmxgc.h"
+#include "dmxfont.h"
+#include "dmxcmap.h"
+#include "dmxpict.h"
+#include "dmxinput.h"
+#include "dmxsync.h"
+#include "dmxscrinit.h"
+#include "input/dmxinputinit.h"
+
+#include "windowstr.h"
+#include "inputstr.h" /* For DeviceIntRec */
+#include <X11/extensions/dmxproto.h> /* For DMX_BAD_* */
+#include "cursorstr.h"
+
+/* The default font is declared in dix/globals.c, but is not included in
+ * _any_ header files. */
+extern FontPtr defaultFont;
+
+/** This routine provides information to the DMX protocol extension
+ * about a particular screen. */
+Bool dmxGetScreenAttributes(int physical, DMXScreenAttributesPtr attr)
+{
+ DMXScreenInfo *dmxScreen;
+
+ if (physical < 0 || physical >= dmxNumScreens) return FALSE;
+
+ dmxScreen = &dmxScreens[physical];
+ attr->displayName = dmxScreen->name;
+#ifdef PANORAMIX
+ attr->logicalScreen = noPanoramiXExtension ? dmxScreen->index : 0;
+#else
+ attr->logicalScreen = dmxScreen->index;
+#endif
+
+ attr->screenWindowWidth = dmxScreen->scrnWidth;
+ attr->screenWindowHeight = dmxScreen->scrnHeight;
+ attr->screenWindowXoffset = dmxScreen->scrnX;
+ attr->screenWindowYoffset = dmxScreen->scrnY;
+
+ attr->rootWindowWidth = dmxScreen->rootWidth;
+ attr->rootWindowHeight = dmxScreen->rootHeight;
+ attr->rootWindowXoffset = dmxScreen->rootX;
+ attr->rootWindowYoffset = dmxScreen->rootY;
+
+ attr->rootWindowXorigin = dmxScreen->rootXOrigin;
+ attr->rootWindowYorigin = dmxScreen->rootYOrigin;
+
+ return TRUE;
+}
+
+/** This routine provides information to the DMX protocol extension
+ * about a particular window. */
+Bool dmxGetWindowAttributes(WindowPtr pWindow, DMXWindowAttributesPtr attr)
+{
+ dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
+
+ attr->screen = pWindow->drawable.pScreen->myNum;
+ attr->window = pWinPriv->window;
+
+ attr->pos.x = pWindow->drawable.x;
+ attr->pos.y = pWindow->drawable.y;
+ attr->pos.width = pWindow->drawable.width;
+ attr->pos.height = pWindow->drawable.height;
+
+ if (!pWinPriv->window || pWinPriv->offscreen) {
+ attr->vis.x = 0;
+ attr->vis.y = 0;
+ attr->vis.height = 0;
+ attr->vis.width = 0;
+ return pWinPriv->window ? TRUE : FALSE;
+ }
+
+ /* Compute display-relative coordinates */
+ attr->vis.x = pWindow->drawable.x;
+ attr->vis.y = pWindow->drawable.y;
+ attr->vis.width = pWindow->drawable.width;
+ attr->vis.height = pWindow->drawable.height;
+
+ if (attr->pos.x < 0) {
+ attr->vis.x -= attr->pos.x;
+ attr->vis.width = attr->pos.x + attr->pos.width - attr->vis.x;
+ }
+ if (attr->pos.x + attr->pos.width > pWindow->drawable.pScreen->width) {
+ if (attr->pos.x < 0)
+ attr->vis.width = pWindow->drawable.pScreen->width;
+ else
+ attr->vis.width = pWindow->drawable.pScreen->width - attr->pos.x;
+ }
+ if (attr->pos.y < 0) {
+ attr->vis.y -= attr->pos.y;
+ attr->vis.height = attr->pos.y + attr->pos.height - attr->vis.y;
+ }
+ if (attr->pos.y + attr->pos.height > pWindow->drawable.pScreen->height) {
+ if (attr->pos.y < 0)
+ attr->vis.height = pWindow->drawable.pScreen->height;
+ else
+ attr->vis.height = pWindow->drawable.pScreen->height - attr->pos.y;
+ }
+
+ /* Convert to window-relative coordinates */
+ attr->vis.x -= attr->pos.x;
+ attr->vis.y -= attr->pos.y;
+
+ return TRUE;
+}
+
+void dmxGetDesktopAttributes(DMXDesktopAttributesPtr attr)
+{
+ attr->width = dmxGlobalWidth;
+ attr->height = dmxGlobalHeight;
+ attr->shiftX = 0; /* NOTE: The upper left hand corner of */
+ attr->shiftY = 0; /* the desktop is always <0,0>. */
+}
+
+/** Return the total number of devices, not just #dmxNumInputs. The
+ * number returned should be the same as that returned by
+ * XListInputDevices. */
+int dmxGetInputCount(void)
+{
+ int i, total;
+
+ for (total = i = 0; i < dmxNumInputs; i++) total += dmxInputs[i].numDevs;
+ return total;
+}
+
+/** Return information about the device with id = \a deviceId. This
+ * information is primarily for the #ProcDMXGetInputAttributes()
+ * function, which does not have access to the appropriate data
+ * structure. */
+int dmxGetInputAttributes(int deviceId, DMXInputAttributesPtr attr)
+{
+ int i, j;
+ DMXInputInfo *dmxInput;
+
+ if (deviceId < 0) return -1;
+ for (i = 0; i < dmxNumInputs; i++) {
+ dmxInput = &dmxInputs[i];
+ for (j = 0; j < dmxInput->numDevs; j++) {
+ DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[j];
+ if (deviceId != dmxLocal->pDevice->id) continue;
+ attr->isCore = !!dmxLocal->isCore;
+ attr->sendsCore = !!dmxLocal->sendsCore;
+ attr->detached = !!dmxInput->detached;
+ attr->physicalScreen = -1;
+ attr->physicalId = -1;
+ attr->name = NULL;
+ switch (dmxLocal->extType) {
+ case DMX_LOCAL_TYPE_LOCAL:
+ attr->inputType = 0;
+ break;
+ case DMX_LOCAL_TYPE_CONSOLE:
+ attr->inputType = 1;
+ attr->name = dmxInput->name;
+ attr->physicalId = dmxLocal->deviceId;
+ break;
+ case DMX_LOCAL_TYPE_BACKEND:
+ case DMX_LOCAL_TYPE_COMMON:
+ attr->inputType = 2;
+ attr->physicalScreen = dmxInput->scrnIdx;
+ attr->name = dmxInput->name;
+ attr->physicalId = dmxLocal->deviceId;
+ break;
+ }
+ return 0; /* Success */
+ }
+ }
+ return -1; /* Failure */
+}
+
+/** Reinitialized the cursor boundaries. */
+static void dmxAdjustCursorBoundaries(void)
+{
+ int i;
+
+ dmxReInitOrigins();
+ dmxInitOverlap();
+ dmxComputeWidthHeight(DMX_NO_RECOMPUTE_BOUNDING_BOX);
+ dmxConnectionBlockCallback();
+ for (i = 0; i < dmxNumInputs; i++) {
+ DMXInputInfo *dmxInput = &dmxInputs[i];
+ if (!dmxInput->detached) dmxInputReInit(dmxInput);
+ }
+
+ dmxCheckCursor();
+
+ for (i = 0; i < dmxNumInputs; i++) {
+ DMXInputInfo *dmxInput = &dmxInputs[i];
+ if (!dmxInput->detached) dmxInputLateReInit(dmxInput);
+ }
+}
+
+/** Add an input with the specified attributes. If the input is added,
+ * the physical id is returned in \a deviceId. */
+int dmxAddInput(DMXInputAttributesPtr attr, int *id)
+{
+ int retcode = BadValue;
+
+ if (attr->inputType == 1) /* console */
+ retcode = dmxInputAttachConsole(attr->name, attr->sendsCore, id);
+ else if (attr->inputType == 2) /* backend */
+ retcode = dmxInputAttachBackend(attr->physicalScreen,
+ attr->sendsCore,id);
+
+ if (retcode == Success) {
+ /* Adjust the cursor boundaries */
+ dmxAdjustCursorBoundaries();
+
+ /* Force completion of the changes */
+ dmxSync(NULL, TRUE);
+ }
+
+ return retcode;
+}
+
+/** Remove the input with physical id \a id. */
+int dmxRemoveInput(int id)
+{
+ return dmxInputDetachId(id);
+}
+
+/** Return the value of #dmxNumScreens -- the total number of backend
+ * screens in use (these are logical screens and may be larger than the
+ * number of backend displays). */
+unsigned long dmxGetNumScreens(void)
+{
+ return dmxNumScreens;
+}
+
+/** Make sure that #dmxCreateAndRealizeWindow has been called for \a
+ * pWindow. */
+void dmxForceWindowCreation(WindowPtr pWindow)
+{
+ dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
+ if (!pWinPriv->window) dmxCreateAndRealizeWindow(pWindow, TRUE);
+}
+
+/** Flush pending syncs for all screens. */
+void dmxFlushPendingSyncs(void)
+{
+ dmxSync(NULL, TRUE);
+}
+
+/** Update DMX's screen resources to match those of the newly moved
+ * and/or resized "root" window. */
+void dmxUpdateScreenResources(ScreenPtr pScreen, int x, int y, int w, int h)
+{
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ WindowPtr pRoot = pScreen->root;
+ WindowPtr pChild;
+ Bool anyMarked = FALSE;
+
+ /* Handle special case where width and/or height are zero */
+ if (w == 0 || h == 0) {
+ w = 1;
+ h = 1;
+ }
+
+ /* Change screen size */
+ pScreen->width = w;
+ pScreen->height = h;
+
+ /* Reset the root window's drawable's size */
+ pRoot->drawable.width = w;
+ pRoot->drawable.height = h;
+
+ /* Set the root window's new winSize and borderSize */
+ pRoot->winSize.extents.x1 = 0;
+ pRoot->winSize.extents.y1 = 0;
+ pRoot->winSize.extents.x2 = w;
+ pRoot->winSize.extents.y2 = h;
+
+ pRoot->borderSize.extents.x1 = 0;
+ pRoot->borderSize.extents.y1 = 0;
+ pRoot->borderSize.extents.x2 = w;
+ pRoot->borderSize.extents.y2 = h;
+
+ /* Recompute this screen's mmWidth & mmHeight */
+ pScreen->mmWidth =
+ (w * 254 + dmxScreen->beXDPI * 5) / (dmxScreen->beXDPI * 10);
+ pScreen->mmHeight =
+ (h * 254 + dmxScreen->beYDPI * 5) / (dmxScreen->beYDPI * 10);
+
+ /* Recompute this screen's window's clip rects as follows: */
+ /* 1. Mark all of root's children's windows */
+ for (pChild = pRoot->firstChild; pChild; pChild = pChild->nextSib)
+ anyMarked |= pScreen->MarkOverlappedWindows(pChild, pChild,
+ (WindowPtr *)NULL);
+
+ /* 2. Set the root window's borderClip */
+ pRoot->borderClip.extents.x1 = 0;
+ pRoot->borderClip.extents.y1 = 0;
+ pRoot->borderClip.extents.x2 = w;
+ pRoot->borderClip.extents.y2 = h;
+
+ /* 3. Set the root window's clipList */
+ if (anyMarked) {
+ /* If any windows have been marked, set the root window's
+ * clipList to be broken since it will be recalculated in
+ * ValidateTree()
+ */
+ RegionBreak(&pRoot->clipList);
+ } else {
+ /* Otherwise, we just set it directly since there are no
+ * windows visible on this screen
+ */
+ pRoot->clipList.extents.x1 = 0;
+ pRoot->clipList.extents.y1 = 0;
+ pRoot->clipList.extents.x2 = w;
+ pRoot->clipList.extents.y2 = h;
+ }
+
+ /* 4. Revalidate all clip rects and generate expose events */
+ if (anyMarked) {
+ pScreen->ValidateTree(pRoot, NULL, VTBroken);
+ pScreen->HandleExposures(pRoot);
+ if (pScreen->PostValidateTree)
+ pScreen->PostValidateTree(pRoot, NULL, VTBroken);
+ }
+}
+
+#ifdef PANORAMIX
+#include "panoramiXsrv.h"
+
+/** Change the "screen" window attributes by resizing the actual window
+ * on the back-end display (if necessary). */
+static void dmxConfigureScreenWindow(int idx,
+ int x, int y, int w, int h)
+{
+ DMXScreenInfo *dmxScreen = &dmxScreens[idx];
+ ScreenPtr pScreen = screenInfo.screens[idx];
+
+ /* Resize "screen" window */
+ if (dmxScreen->scrnX != x ||
+ dmxScreen->scrnY != y ||
+ dmxScreen->scrnWidth != w ||
+ dmxScreen->scrnHeight != h) {
+ dmxResizeScreenWindow(pScreen, x, y, w, h);
+ }
+
+ /* Change "screen" window values */
+ dmxScreen->scrnX = x;
+ dmxScreen->scrnY = y;
+ dmxScreen->scrnWidth = w;
+ dmxScreen->scrnHeight = h;
+}
+
+/** Change the "root" window position and size by resizing the actual
+ * window on the back-end display (if necessary) and updating all of
+ * DMX's resources by calling #dmxUpdateScreenResources. */
+static void dmxConfigureRootWindow(int idx, int x, int y, int w, int h)
+{
+ DMXScreenInfo *dmxScreen = &dmxScreens[idx];
+ WindowPtr pRoot = screenInfo.screens[idx]->root;
+
+ /* NOTE: Either this function or the ones that it calls must handle
+ * the case where w == 0 || h == 0. Currently, the functions that
+ * this one calls handle that case. */
+
+ /* 1. Resize "root" window */
+ if (dmxScreen->rootX != x ||
+ dmxScreen->rootY != y ||
+ dmxScreen->rootWidth != w ||
+ dmxScreen->rootHeight != h) {
+ dmxResizeRootWindow(pRoot, x, y, w, h);
+ }
+
+ /* 2. Update all of the screen's resources associated with this root
+ * window */
+ if (dmxScreen->rootWidth != w ||
+ dmxScreen->rootHeight != h) {
+ dmxUpdateScreenResources(screenInfo.screens[idx], x, y, w, h);
+ }
+
+ /* Change "root" window values */
+ dmxScreen->rootX = x;
+ dmxScreen->rootY = y;
+ dmxScreen->rootWidth = w;
+ dmxScreen->rootHeight = h;
+}
+
+/** Change the "root" window's origin by updating DMX's internal data
+ * structures (dix and Xinerama) to use the new origin and adjust the
+ * positions of windows that overlap this "root" window. */
+static void dmxSetRootWindowOrigin(int idx, int x, int y)
+{
+ DMXScreenInfo *dmxScreen = &dmxScreens[idx];
+ ScreenPtr pScreen = screenInfo.screens[idx];
+ WindowPtr pRoot = pScreen->root;
+ WindowPtr pChild;
+ int xoff;
+ int yoff;
+
+ /* Change "root" window's origin */
+ dmxScreen->rootXOrigin = x;
+ dmxScreen->rootYOrigin = y;
+
+ /* Compute offsets here in case <x,y> has been changed above */
+ xoff = x - pScreen->x;
+ yoff = y - pScreen->y;
+
+ /* Adjust the root window's position */
+ pScreen->x = dmxScreen->rootXOrigin;
+ pScreen->y = dmxScreen->rootYOrigin;
+
+ /* Recalculate the Xinerama regions and data structs */
+ XineramaReinitData(pScreen);
+
+ /* Adjust each of the root window's children */
+ if (!idx) ReinitializeRootWindow(screenInfo.screens[0]->root, xoff, yoff);
+ pChild = pRoot->firstChild;
+ while (pChild) {
+ /* Adjust child window's position */
+ pScreen->MoveWindow(pChild,
+ pChild->origin.x - wBorderWidth(pChild) - xoff,
+ pChild->origin.y - wBorderWidth(pChild) - yoff,
+ pChild->nextSib,
+ VTMove);
+
+ /* Note that the call to MoveWindow will eventually call
+ * dmxPositionWindow which will automatically create a
+ * window if it is now exposed on screen (for lazy window
+ * creation optimization) and it will properly set the
+ * offscreen flag.
+ */
+
+ pChild = pChild->nextSib;
+ }
+}
+
+/** Configure the attributes of each "screen" and "root" window. */
+int dmxConfigureScreenWindows(int nscreens,
+ CARD32 *screens,
+ DMXScreenAttributesPtr attribs,
+ int *errorScreen)
+{
+ int i;
+
+ for (i = 0; i < nscreens; i++) {
+ DMXScreenAttributesPtr attr = &attribs[i];
+ int idx = screens[i];
+ DMXScreenInfo *dmxScreen = &dmxScreens[idx];
+
+ if (errorScreen) *errorScreen = i;
+
+ if (!dmxScreen->beDisplay) return DMX_BAD_VALUE;
+
+ /* Check for illegal values */
+ if (idx < 0 || idx >= dmxNumScreens) return BadValue;
+
+ /* The "screen" and "root" windows must have valid sizes */
+ if (attr->screenWindowWidth <= 0 || attr->screenWindowHeight <= 0 ||
+ attr->rootWindowWidth < 0 || attr->rootWindowHeight < 0)
+ return DMX_BAD_VALUE;
+
+ /* The "screen" window must fit entirely within the BE display */
+ if (attr->screenWindowXoffset < 0 ||
+ attr->screenWindowYoffset < 0 ||
+ attr->screenWindowXoffset
+ + attr->screenWindowWidth > (unsigned)dmxScreen->beWidth ||
+ attr->screenWindowYoffset
+ + attr->screenWindowHeight > (unsigned)dmxScreen->beHeight)
+ return DMX_BAD_VALUE;
+
+ /* The "root" window must fit entirely within the "screen" window */
+ if (attr->rootWindowXoffset < 0 ||
+ attr->rootWindowYoffset < 0 ||
+ attr->rootWindowXoffset
+ + attr->rootWindowWidth > attr->screenWindowWidth ||
+ attr->rootWindowYoffset
+ + attr->rootWindowHeight > attr->screenWindowHeight)
+ return DMX_BAD_VALUE;
+
+ /* The "root" window must not expose unaddressable coordinates */
+ if (attr->rootWindowXorigin < 0 ||
+ attr->rootWindowYorigin < 0 ||
+ attr->rootWindowXorigin + attr->rootWindowWidth > 32767 ||
+ attr->rootWindowYorigin + attr->rootWindowHeight > 32767)
+ return DMX_BAD_VALUE;
+
+ /* The "root" window must fit within the global bounding box */
+ if (attr->rootWindowXorigin
+ + attr->rootWindowWidth > (unsigned)dmxGlobalWidth ||
+ attr->rootWindowYorigin
+ + attr->rootWindowHeight > (unsigned)dmxGlobalHeight)
+ return DMX_BAD_VALUE;
+
+ /* FIXME: Handle the rest of the illegal value checking */
+ }
+
+ /* No illegal values found */
+ if (errorScreen) *errorScreen = 0;
+
+ for (i = 0; i < nscreens; i++) {
+ DMXScreenAttributesPtr attr = &attribs[i];
+ int idx = screens[i];
+ DMXScreenInfo *dmxScreen = &dmxScreens[idx];
+
+ dmxLog(dmxInfo, "Changing screen #%d attributes "
+ "from %dx%d+%d+%d %dx%d+%d+%d +%d+%d "
+ "to %dx%d+%d+%d %dx%d+%d+%d +%d+%d\n",
+ idx,
+ dmxScreen->scrnWidth, dmxScreen->scrnHeight,
+ dmxScreen->scrnX, dmxScreen->scrnY,
+ dmxScreen->rootWidth, dmxScreen->rootHeight,
+ dmxScreen->rootX, dmxScreen->rootY,
+ dmxScreen->rootXOrigin, dmxScreen->rootYOrigin,
+ attr->screenWindowWidth, attr->screenWindowHeight,
+ attr->screenWindowXoffset, attr->screenWindowYoffset,
+ attr->rootWindowWidth, attr->rootWindowHeight,
+ attr->rootWindowXoffset, attr->rootWindowYoffset,
+ attr->rootWindowXorigin, attr->rootWindowYorigin);
+
+ /* Configure "screen" window */
+ dmxConfigureScreenWindow(idx,
+ attr->screenWindowXoffset,
+ attr->screenWindowYoffset,
+ attr->screenWindowWidth,
+ attr->screenWindowHeight);
+
+ /* Configure "root" window */
+ dmxConfigureRootWindow(idx,
+ attr->rootWindowXoffset,
+ attr->rootWindowYoffset,
+ attr->rootWindowWidth,
+ attr->rootWindowHeight);
+
+
+ /* Set "root" window's origin */
+ dmxSetRootWindowOrigin(idx,
+ attr->rootWindowXorigin,
+ attr->rootWindowYorigin);
+ }
+
+ /* Adjust the cursor boundaries */
+ dmxAdjustCursorBoundaries();
+
+ /* Force completion of the changes */
+ dmxSync(NULL, TRUE);
+
+ return Success;
+}
+
+/** Configure the attributes of the global desktop. */
+int dmxConfigureDesktop(DMXDesktopAttributesPtr attribs)
+{
+ if (attribs->width <= 0 || attribs->width >= 32767 ||
+ attribs->height <= 0 || attribs->height >= 32767)
+ return DMX_BAD_VALUE;
+
+ /* If the desktop is shrinking, adjust the "root" windows on each
+ * "screen" window to only show the visible desktop. Also, handle
+ * the special case where the desktop shrinks such that the it no
+ * longer overlaps an portion of a "screen" window. */
+ if (attribs->width < dmxGlobalWidth || attribs->height < dmxGlobalHeight) {
+ int i;
+ for (i = 0; i < dmxNumScreens; i++) {
+ DMXScreenInfo *dmxScreen = &dmxScreens[i];
+ if (dmxScreen->rootXOrigin
+ + dmxScreen->rootWidth > attribs->width ||
+ dmxScreen->rootYOrigin
+ + dmxScreen->rootHeight > attribs->height) {
+ int w, h;
+ if ((w = attribs->width - dmxScreen->rootXOrigin) < 0) w = 0;
+ if ((h = attribs->height - dmxScreen->rootYOrigin) < 0) h = 0;
+ if (w > dmxScreen->scrnWidth) w = dmxScreen->scrnWidth;
+ if (h > dmxScreen->scrnHeight) h = dmxScreen->scrnHeight;
+ if (w > dmxScreen->rootWidth) w = dmxScreen->rootWidth;
+ if (h > dmxScreen->rootHeight) h = dmxScreen->rootHeight;
+ dmxConfigureRootWindow(i,
+ dmxScreen->rootX,
+ dmxScreen->rootY,
+ w, h);
+ }
+ }
+ }
+
+ /* Set the global width/height */
+ dmxSetWidthHeight(attribs->width, attribs->height);
+
+ /* Handle shift[XY] changes */
+ if (attribs->shiftX || attribs->shiftY) {
+ int i;
+ for (i = 0; i < dmxNumScreens; i++) {
+ ScreenPtr pScreen = screenInfo.screens[i];
+ WindowPtr pChild = pScreen->root->firstChild;
+ while (pChild) {
+ /* Adjust child window's position */
+ pScreen->MoveWindow(pChild,
+ pChild->origin.x - wBorderWidth(pChild)
+ - attribs->shiftX,
+ pChild->origin.y - wBorderWidth(pChild)
+ - attribs->shiftY,
+ pChild->nextSib,
+ VTMove);
+
+ /* Note that the call to MoveWindow will eventually call
+ * dmxPositionWindow which will automatically create a
+ * window if it is now exposed on screen (for lazy
+ * window creation optimization) and it will properly
+ * set the offscreen flag.
+ */
+
+ pChild = pChild->nextSib;
+ }
+ }
+ }
+
+ /* Update connection block, Xinerama, etc. -- these appears to
+ * already be handled in dmxConnectionBlockCallback(), which is
+ * called from dmxAdjustCursorBoundaries() [below]. */
+
+ /* Adjust the cursor boundaries */
+ dmxAdjustCursorBoundaries();
+
+ /* Force completion of the changes */
+ dmxSync(NULL, TRUE);
+
+ return Success;
+}
+#endif
+
+/** Create the scratch GCs per depth. */
+static void dmxBECreateScratchGCs(int scrnNum)
+{
+ ScreenPtr pScreen = screenInfo.screens[scrnNum];
+ GCPtr *ppGC = pScreen->GCperDepth;
+ int i;
+
+ for (i = 0; i <= pScreen->numDepths; i++)
+ dmxBECreateGC(pScreen, ppGC[i]);
+}
+
+#ifdef PANORAMIX
+static Bool FoundPixImage;
+
+/** Search the Xinerama XRT_PIXMAP resources for the pixmap that needs
+ * to have its image restored. When it is found, see if there is
+ * another screen with the same image. If so, copy the pixmap image
+ * from the existing screen to the newly created pixmap. */
+static void dmxBERestorePixmapImage(pointer value, XID id, RESTYPE type,
+ pointer p)
+{
+ if ((type & TypeMask) == (XRT_PIXMAP & TypeMask)) {
+ PixmapPtr pDst = (PixmapPtr)p;
+ int idx = pDst->drawable.pScreen->myNum;
+ PanoramiXRes *pXinPix = (PanoramiXRes *)value;
+ PixmapPtr pPix;
+ int i;
+
+ dixLookupResourceByType((pointer*) &pPix, pXinPix->info[idx].id,
+ RT_PIXMAP, NullClient, DixUnknownAccess);
+ if (pPix != pDst) return; /* Not a match.... Next! */
+
+ FOR_NSCREENS(i) {
+ PixmapPtr pSrc;
+ dmxPixPrivPtr pSrcPriv = NULL;
+
+ if (i == idx) continue; /* Self replication is bad */
+
+ dixLookupResourceByType((pointer*) &pSrc, pXinPix->info[i].id,
+ RT_PIXMAP, NullClient, DixUnknownAccess);
+ pSrcPriv = DMX_GET_PIXMAP_PRIV(pSrc);
+ if (pSrcPriv->pixmap) {
+ DMXScreenInfo *dmxSrcScreen = &dmxScreens[i];
+ DMXScreenInfo *dmxDstScreen = &dmxScreens[idx];
+ dmxPixPrivPtr pDstPriv = DMX_GET_PIXMAP_PRIV(pDst);
+ XImage *img;
+ int j;
+ XlibGC gc = NULL;
+
+ /* This should never happen, but just in case.... */
+ if (pSrc->drawable.width != pDst->drawable.width ||
+ pSrc->drawable.height != pDst->drawable.height)
+ return;
+
+ /* Copy from src pixmap to dst pixmap */
+ img = XGetImage(dmxSrcScreen->beDisplay,
+ pSrcPriv->pixmap,
+ 0, 0,
+ pSrc->drawable.width, pSrc->drawable.height,
+ -1,
+ ZPixmap);
+
+ for (j = 0; j < dmxDstScreen->beNumPixmapFormats; j++) {
+ if (dmxDstScreen->bePixmapFormats[j].depth == img->depth) {
+ unsigned long m;
+ XGCValues v;
+
+ m = GCFunction | GCPlaneMask | GCClipMask;
+ v.function = GXcopy;
+ v.plane_mask = AllPlanes;
+ v.clip_mask = None;
+
+ gc = XCreateGC(dmxDstScreen->beDisplay,
+ dmxDstScreen->scrnDefDrawables[j],
+ m, &v);
+ break;
+ }
+ }
+
+ if (gc) {
+ XPutImage(dmxDstScreen->beDisplay,
+ pDstPriv->pixmap,
+ gc, img, 0, 0, 0, 0,
+ pDst->drawable.width, pDst->drawable.height);
+ XFreeGC(dmxDstScreen->beDisplay, gc);
+ FoundPixImage = True;
+ } else {
+ dmxLog(dmxWarning, "Could not create GC\n");
+ }
+
+ XDestroyImage(img);
+ return;
+ }
+ }
+ }
+}
+#endif
+
+/** Restore the pixmap image either from another screen or from an image
+ * that was saved when the screen was previously detached. */
+static void dmxBERestorePixmap(PixmapPtr pPixmap)
+{
+#ifdef PANORAMIX
+ int i;
+
+ /* If Xinerama is not active, there's nothing we can do (see comment
+ * in #else below for more info). */
+ if (noPanoramiXExtension) {
+ dmxLog(dmxWarning, "Cannot restore pixmap image\n");
+ return;
+ }
+
+ FoundPixImage = False;
+ for (i = currentMaxClients; --i >= 0; )
+ if (clients[i])
+ FindAllClientResources(clients[i], dmxBERestorePixmapImage,
+ (pointer)pPixmap);
+
+ /* No corresponding pixmap image was found on other screens, so we
+ * need to copy it from the saved image when the screen was detached
+ * (if available). */
+ if (!FoundPixImage) {
+ dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV(pPixmap);
+
+ if (pPixPriv->detachedImage) {
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ XlibGC gc = NULL;
+
+ for (i = 0; i < dmxScreen->beNumPixmapFormats; i++) {
+ if (dmxScreen->bePixmapFormats[i].depth ==
+ pPixPriv->detachedImage->depth) {
+ unsigned long m;
+ XGCValues v;
+
+ m = GCFunction | GCPlaneMask | GCClipMask;
+ v.function = GXcopy;
+ v.plane_mask = AllPlanes;
+ v.clip_mask = None;
+
+ gc = XCreateGC(dmxScreen->beDisplay,
+ dmxScreen->scrnDefDrawables[i],
+ m, &v);
+ break;
+ }
+ }
+
+ if (gc) {
+ XPutImage(dmxScreen->beDisplay,
+ pPixPriv->pixmap,
+ gc,
+ pPixPriv->detachedImage,
+ 0, 0, 0, 0,
+ pPixmap->drawable.width, pPixmap->drawable.height);
+ XFreeGC(dmxScreen->beDisplay, gc);
+ } else {
+ dmxLog(dmxWarning, "Cannot restore pixmap image\n");
+ }
+
+ XDestroyImage(pPixPriv->detachedImage);
+ pPixPriv->detachedImage = NULL;
+ } else {
+ dmxLog(dmxWarning, "Cannot restore pixmap image\n");
+ }
+ }
+#else
+ /* If Xinerama is not enabled, then there is no other copy of the
+ * pixmap image that we can restore. Saving all pixmap data is not
+ * a feasible option since there is no mechanism for updating pixmap
+ * data when a screen is detached, which means that the data that
+ * was previously saved would most likely be out of date. */
+ dmxLog(dmxWarning, "Cannot restore pixmap image\n");
+ return;
+#endif
+}
+
+/** Create resources on the back-end server. This function is called
+ * from #dmxAttachScreen() via the dix layer's FindAllResources
+ * function. It walks all resources, compares them to the screen
+ * number passed in as \a n and calls the appropriate DMX function to
+ * create the associated resource on the back-end server. */
+static void dmxBECreateResources(pointer value, XID id, RESTYPE type,
+ pointer n)
+{
+ int scrnNum = (uintptr_t)n;
+ ScreenPtr pScreen = screenInfo.screens[scrnNum];
+
+ if ((type & TypeMask) == (RT_WINDOW & TypeMask)) {
+ /* Window resources are created below in dmxBECreateWindowTree */
+ } else if ((type & TypeMask) == (RT_PIXMAP & TypeMask)) {
+ PixmapPtr pPix = value;
+ if (pPix->drawable.pScreen->myNum == scrnNum) {
+ dmxBECreatePixmap(pPix);
+ dmxBERestorePixmap(pPix);
+ }
+ } else if ((type & TypeMask) == (RT_GC & TypeMask)) {
+ GCPtr pGC = value;
+ if (pGC->pScreen->myNum == scrnNum) {
+ /* Create the GC on the back-end server */
+ dmxBECreateGC(pScreen, pGC);
+ /* Create any pixmaps associated with this GC */
+ if (!pGC->tileIsPixel) {
+ dmxBECreatePixmap(pGC->tile.pixmap);
+ dmxBERestorePixmap(pGC->tile.pixmap);
+ }
+ if (pGC->stipple != pScreen->PixmapPerDepth[0]) {
+ dmxBECreatePixmap(pGC->stipple);
+ dmxBERestorePixmap(pGC->stipple);
+ }
+ if (pGC->font != defaultFont) {
+ (void)dmxBELoadFont(pScreen, pGC->font);
+ }
+ /* Update the GC on the back-end server */
+ dmxChangeGC(pGC, -1L);
+ }
+ } else if ((type & TypeMask) == (RT_FONT & TypeMask)) {
+ (void)dmxBELoadFont(pScreen, (FontPtr)value);
+ } else if ((type & TypeMask) == (RT_CURSOR & TypeMask)) {
+ dmxBECreateCursor(pScreen, (CursorPtr)value);
+ } else if ((type & TypeMask) == (RT_COLORMAP & TypeMask)) {
+ ColormapPtr pCmap = value;
+ if (pCmap->pScreen->myNum == scrnNum)
+ (void)dmxBECreateColormap((ColormapPtr)value);
+#if 0
+ /* TODO: Recreate Picture and GlyphSet resources */
+ } else if ((type & TypeMask) == (PictureType & TypeMask)) {
+ /* Picture resources are created when windows are created */
+ } else if ((type & TypeMask) == (GlyphSetType & TypeMask)) {
+ dmxBEFreeGlyphSet(pScreen, (GlyphSetPtr)value);
+#endif
+ } else {
+ /* Other resource types??? */
+ }
+}
+
+/** Create window hierachy on back-end server. The window tree is
+ * created in a special order (bottom most subwindow first) so that the
+ * #dmxCreateNonRootWindow() function does not need to recursively call
+ * itself to create each window's parents. This is required so that we
+ * have the opportunity to create each window's border and background
+ * pixmaps (where appropriate) before the window is created. */
+static void dmxBECreateWindowTree(int idx)
+{
+ DMXScreenInfo *dmxScreen = &dmxScreens[idx];
+ WindowPtr pRoot = screenInfo.screens[idx]->root;
+ dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pRoot);
+ WindowPtr pWin;
+
+ /* Create the pixmaps associated with the root window */
+ if (!pRoot->borderIsPixel) {
+ dmxBECreatePixmap(pRoot->border.pixmap);
+ dmxBERestorePixmap(pRoot->border.pixmap);
+ }
+ if (pRoot->backgroundState == BackgroundPixmap) {
+ dmxBECreatePixmap(pRoot->background.pixmap);
+ dmxBERestorePixmap(pRoot->background.pixmap);
+ }
+
+ /* Create root window first */
+ dmxScreen->rootWin = pWinPriv->window = dmxCreateRootWindow(pRoot);
+ XMapWindow(dmxScreen->beDisplay, dmxScreen->rootWin);
+
+ pWin = pRoot->lastChild;
+ while (pWin) {
+ pWinPriv = DMX_GET_WINDOW_PRIV(pWin);
+
+ /* Create the pixmaps regardless of whether or not the
+ * window is created or not due to lazy window creation.
+ */
+ if (!pWin->borderIsPixel) {
+ dmxBECreatePixmap(pWin->border.pixmap);
+ dmxBERestorePixmap(pWin->border.pixmap);
+ }
+ if (pWin->backgroundState == BackgroundPixmap) {
+ dmxBECreatePixmap(pWin->background.pixmap);
+ dmxBERestorePixmap(pWin->background.pixmap);
+ }
+
+ /* Reset the window attributes */
+ dmxGetDefaultWindowAttributes(pWin,
+ &pWinPriv->cmap,
+ &pWinPriv->visual);
+
+ /* Create the window */
+ if (pWinPriv->mapped && !pWinPriv->offscreen)
+ dmxCreateAndRealizeWindow(pWin, TRUE);
+
+ /* Next, create the bottom-most child */
+ if (pWin->lastChild) {
+ pWin = pWin->lastChild;
+ continue;
+ }
+
+ /* If the window has no children, move on to the next higher window */
+ while (!pWin->prevSib && (pWin != pRoot))
+ pWin = pWin->parent;
+
+ if (pWin->prevSib) {
+ pWin = pWin->prevSib;
+ continue;
+ }
+
+ /* When we reach the root window, we are finished */
+ if (pWin == pRoot)
+ break;
+ }
+}
+
+/* Refresh screen by generating exposure events for all windows */
+static void dmxForceExposures(int idx)
+{
+ ScreenPtr pScreen = screenInfo.screens[idx];
+ WindowPtr pRoot = pScreen->root;
+ Bool anyMarked = FALSE;
+ WindowPtr pChild;
+
+ for (pChild = pRoot->firstChild; pChild; pChild = pChild->nextSib)
+ anyMarked |= pScreen->MarkOverlappedWindows(pChild, pChild,
+ (WindowPtr *)NULL);
+ if (anyMarked) {
+ /* If any windows have been marked, set the root window's
+ * clipList to be broken since it will be recalculated in
+ * ValidateTree()
+ */
+ RegionBreak(&pRoot->clipList);
+ pScreen->ValidateTree(pRoot, NULL, VTBroken);
+ pScreen->HandleExposures(pRoot);
+ if (pScreen->PostValidateTree)
+ pScreen->PostValidateTree(pRoot, NULL, VTBroken);
+ }
+}
+
+/** Compare the new and old screens to see if they are compatible. */
+static Bool dmxCompareScreens(DMXScreenInfo *new, DMXScreenInfo *old)
+{
+ int i;
+
+ if (new->beWidth != old->beWidth) return FALSE;
+ if (new->beHeight != old->beHeight) return FALSE;
+ if (new->beDepth != old->beDepth) return FALSE;
+ if (new->beBPP != old->beBPP) return FALSE;
+
+ if (new->beNumDepths != old->beNumDepths) return FALSE;
+ for (i = 0; i < old->beNumDepths; i++)
+ if (new->beDepths[i] != old->beDepths[i]) return FALSE;
+
+ if (new->beNumPixmapFormats != old->beNumPixmapFormats) return FALSE;
+ for (i = 0; i < old->beNumPixmapFormats; i++) {
+ if (new->bePixmapFormats[i].depth !=
+ old->bePixmapFormats[i].depth) return FALSE;
+ if (new->bePixmapFormats[i].bits_per_pixel !=
+ old->bePixmapFormats[i].bits_per_pixel) return FALSE;
+ if (new->bePixmapFormats[i].scanline_pad !=
+ old->bePixmapFormats[i].scanline_pad) return FALSE;
+ }
+
+ if (new->beNumVisuals != old->beNumVisuals) return FALSE;
+ for (i = 0; i < old->beNumVisuals; i++) {
+ if (new->beVisuals[i].visualid !=
+ old->beVisuals[i].visualid) return FALSE;
+ if (new->beVisuals[i].screen !=
+ old->beVisuals[i].screen) return FALSE;
+ if (new->beVisuals[i].depth !=
+ old->beVisuals[i].depth) return FALSE;
+ if (new->beVisuals[i].class !=
+ old->beVisuals[i].class) return FALSE;
+ if (new->beVisuals[i].red_mask !=
+ old->beVisuals[i].red_mask) return FALSE;
+ if (new->beVisuals[i].green_mask !=
+ old->beVisuals[i].green_mask) return FALSE;
+ if (new->beVisuals[i].blue_mask !=
+ old->beVisuals[i].blue_mask) return FALSE;
+ if (new->beVisuals[i].colormap_size !=
+ old->beVisuals[i].colormap_size) return FALSE;
+ if (new->beVisuals[i].bits_per_rgb !=
+ old->beVisuals[i].bits_per_rgb) return FALSE;
+ }
+
+ if (new->beDefVisualIndex != old->beDefVisualIndex) return FALSE;
+
+ return TRUE;
+}
+
+/** Restore Render's picture */
+static void dmxBERestoreRenderPict(pointer value, XID id, pointer n)
+{
+ PicturePtr pPicture = value; /* The picture */
+ DrawablePtr pDraw = pPicture->pDrawable; /* The picture's drawable */
+ int scrnNum = (uintptr_t)n;
+
+ if (pDraw->pScreen->myNum != scrnNum) {
+ /* Picture not on the screen we are restoring*/
+ return;
+ }
+
+ if (pDraw->type == DRAWABLE_PIXMAP) {
+ PixmapPtr pPixmap = (PixmapPtr)pDraw;
+
+ /* Create and restore the pixmap drawable */
+ dmxBECreatePixmap(pPixmap);
+ dmxBERestorePixmap(pPixmap);
+ }
+
+ dmxBECreatePicture(pPicture);
+}
+
+/** Restore Render's glyphs */
+static void dmxBERestoreRenderGlyph(pointer value, XID id, pointer n)
+{
+ GlyphSetPtr glyphSet = value;
+ int scrnNum = (uintptr_t)n;
+ dmxGlyphPrivPtr glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
+ DMXScreenInfo *dmxScreen = &dmxScreens[scrnNum];
+ GlyphRefPtr table;
+ char *images;
+ Glyph *gids;
+ XGlyphInfo *glyphs;
+ char *pos;
+ int beret;
+ int len_images = 0;
+ int i;
+ int ctr;
+
+ if (glyphPriv->glyphSets[scrnNum]) {
+ /* Only restore glyphs on the screen we are attaching */
+ return;
+ }
+
+ /* First we must create the glyph set on the backend. */
+ if ((beret = dmxBECreateGlyphSet(scrnNum, glyphSet)) != Success) {
+ dmxLog(dmxWarning,
+ "\tdmxBERestoreRenderGlyph failed to create glyphset!\n");
+ return;
+ }
+
+ /* Now for the complex part, restore the glyph data */
+ table = glyphSet->hash.table;
+
+ /* We need to know how much memory to allocate for this part */
+ for (i = 0; i < glyphSet->hash.hashSet->size; i++) {
+ GlyphRefPtr gr = &table[i];
+ GlyphPtr gl = gr->glyph;
+
+ if (!gl || gl == DeletedGlyph) continue;
+ len_images += gl->size - sizeof(gl->info);
+ }
+
+ /* Now allocate the memory we need */
+ images = calloc(len_images, sizeof(char));
+ gids = malloc(glyphSet->hash.tableEntries*sizeof(Glyph));
+ glyphs = malloc(glyphSet->hash.tableEntries*sizeof(XGlyphInfo));
+
+ pos = images;
+ ctr = 0;
+
+ /* Fill the allocated memory with the proper data */
+ for (i = 0; i < glyphSet->hash.hashSet->size; i++) {
+ GlyphRefPtr gr = &table[i];
+ GlyphPtr gl = gr->glyph;
+
+ if (!gl || gl == DeletedGlyph) continue;
+
+ /* First lets put the data into gids */
+ gids[ctr] = gr->signature;
+
+ /* Next do the glyphs data structures */
+ glyphs[ctr].width = gl->info.width;
+ glyphs[ctr].height = gl->info.height;
+ glyphs[ctr].x = gl->info.x;
+ glyphs[ctr].y = gl->info.y;
+ glyphs[ctr].xOff = gl->info.xOff;
+ glyphs[ctr].yOff = gl->info.yOff;
+
+ /* Copy the images from the DIX's data into the buffer */
+ memcpy(pos, gl+1, gl->size - sizeof(gl->info));
+ pos += gl->size - sizeof(gl->info);
+ ctr++;
+ }
+
+ /* Now restore the glyph data */
+ XRenderAddGlyphs(dmxScreen->beDisplay, glyphPriv->glyphSets[scrnNum],
+ gids,glyphs, glyphSet->hash.tableEntries, images,
+ len_images);
+
+ /* Clean up */
+ free(images);
+ free(gids);
+ free(glyphs);
+}
+
+/** Reattach previously detached back-end screen. */
+int dmxAttachScreen(int idx, DMXScreenAttributesPtr attr)
+{
+ ScreenPtr pScreen;
+ DMXScreenInfo *dmxScreen;
+ CARD32 scrnNum = idx;
+ DMXScreenInfo oldDMXScreen;
+ int i;
+
+ /* Return failure if dynamic addition/removal of screens is disabled */
+ if (!dmxAddRemoveScreens) {
+ dmxLog(dmxWarning,
+ "Attempting to add a screen, but the AddRemoveScreen\n");
+ dmxLog(dmxWarning,
+ "extension has not been enabled. To enable this extension\n");
+ dmxLog(dmxWarning,
+ "add the \"-addremovescreens\" option either to the command\n");
+ dmxLog(dmxWarning,
+ "line or in the configuration file.\n");
+ return 1;
+ }
+
+ /* Cannot add a screen that does not exist */
+ if (idx < 0 || idx >= dmxNumScreens) return 1;
+ pScreen = screenInfo.screens[idx];
+ dmxScreen = &dmxScreens[idx];
+
+ /* Cannot attach to a screen that is already opened */
+ if (dmxScreen->beDisplay) {
+ dmxLog(dmxWarning,
+ "Attempting to add screen #%d but a screen already exists\n",
+ idx);
+ return 1;
+ }
+
+ dmxLogOutput(dmxScreen, "Attaching screen #%d\n", idx);
+
+ /* Save old info */
+ oldDMXScreen = *dmxScreen;
+
+ /* Copy the name to the new screen */
+ dmxScreen->name = strdup(attr->displayName);
+
+ /* Open display and get all of the screen info */
+ if (!dmxOpenDisplay(dmxScreen)) {
+ dmxLog(dmxWarning,
+ "dmxOpenDisplay: Unable to open display %s\n",
+ dmxScreen->name);
+
+ /* Restore the old screen */
+ *dmxScreen = oldDMXScreen;
+ return 1;
+ }
+
+ dmxSetErrorHandler(dmxScreen);
+ dmxCheckForWM(dmxScreen);
+ dmxGetScreenAttribs(dmxScreen);
+
+ if (!dmxGetVisualInfo(dmxScreen)) {
+ dmxLog(dmxWarning, "dmxGetVisualInfo: No matching visuals found\n");
+ XFree(dmxScreen->beVisuals);
+ XCloseDisplay(dmxScreen->beDisplay);
+
+ /* Restore the old screen */
+ *dmxScreen = oldDMXScreen;
+ return 1;
+ }
+
+ dmxGetColormaps(dmxScreen);
+ dmxGetPixmapFormats(dmxScreen);
+
+ /* Verify that the screen to be added has the same info as the
+ * previously added screen. */
+ if (!dmxCompareScreens(dmxScreen, &oldDMXScreen)) {
+ dmxLog(dmxWarning,
+ "New screen data (%s) does not match previously\n",
+ dmxScreen->name);
+ dmxLog(dmxWarning,
+ "attached screen data (%s)\n",
+ oldDMXScreen.name);
+ dmxLog(dmxWarning,
+ "All data must match in order to attach to screen #%d\n",
+ idx);
+ XFree(dmxScreen->beVisuals);
+ XFree(dmxScreen->beDepths);
+ XFree(dmxScreen->bePixmapFormats);
+ XCloseDisplay(dmxScreen->beDisplay);
+
+ /* Restore the old screen */
+ *dmxScreen = oldDMXScreen;
+ return 1;
+ }
+
+ /* Initialize the BE screen resources */
+ dmxBEScreenInit(idx, screenInfo.screens[idx]);
+
+ /* TODO: Handle GLX visual initialization. GLXProxy needs to be
+ * updated to handle dynamic addition/removal of screens. */
+
+ /* Create default stipple */
+ dmxBECreatePixmap(pScreen->PixmapPerDepth[0]);
+ dmxBERestorePixmap(pScreen->PixmapPerDepth[0]);
+
+ /* Create the scratch GCs */
+ dmxBECreateScratchGCs(idx);
+
+ /* Create the default font */
+ (void)dmxBELoadFont(pScreen, defaultFont);
+
+ /* Create all resources that don't depend on windows */
+ for (i = currentMaxClients; --i >= 0; )
+ if (clients[i])
+ FindAllClientResources(clients[i], dmxBECreateResources,
+ (pointer)(uintptr_t)idx);
+
+ /* Create window hierarchy (top down) */
+ dmxBECreateWindowTree(idx);
+
+ /* Restore the picture state for RENDER */
+ for (i = currentMaxClients; --i >= 0; )
+ if (clients[i])
+ FindClientResourcesByType(clients[i],PictureType,
+ dmxBERestoreRenderPict,
+ (pointer)(uintptr_t)idx);
+
+ /* Restore the glyph state for RENDER */
+ for (i = currentMaxClients; --i >= 0; )
+ if (clients[i])
+ FindClientResourcesByType(clients[i],GlyphSetType,
+ dmxBERestoreRenderGlyph,
+ (pointer)(uintptr_t)idx);
+
+ /* Refresh screen by generating exposure events for all windows */
+ dmxForceExposures(idx);
+
+ dmxSync(&dmxScreens[idx], TRUE);
+
+ /* We used these to compare the old and new screens. They are no
+ * longer needed since we have a newly attached screen, so we can
+ * now free the old screen's resources. */
+ XFree(oldDMXScreen.beVisuals);
+ XFree(oldDMXScreen.beDepths);
+ XFree(oldDMXScreen.bePixmapFormats);
+ /* TODO: should oldDMXScreen.name be freed?? */
+
+#ifdef PANORAMIX
+ if (!noPanoramiXExtension)
+ return dmxConfigureScreenWindows(1, &scrnNum, attr, NULL);
+ else
+#endif
+ return 0; /* Success */
+}
+
+/*
+ * Resources that may have state on the BE server and need to be freed:
+ *
+ * RT_NONE
+ * RT_WINDOW
+ * RT_PIXMAP
+ * RT_GC
+ * RT_FONT
+ * RT_CURSOR
+ * RT_COLORMAP
+ * RT_CMAPENTRY
+ * RT_OTHERCLIENT
+ * RT_PASSIVEGRAB
+ * XRT_WINDOW
+ * XRT_PIXMAP
+ * XRT_GC
+ * XRT_COLORMAP
+ * XRT_PICTURE
+ * PictureType
+ * PictFormatType
+ * GlyphSetType
+ * ClientType
+ * EventType
+ * RT_INPUTCLIENT
+ * XETrapType
+ * RTCounter
+ * RTAwait
+ * RTAlarmClient
+ * RT_XKBCLIENT
+ * RTContext
+ * TagResType
+ * StalledResType
+ * SecurityAuthorizationResType
+ * RTEventClient
+ * __glXContextRes
+ * __glXClientRes
+ * __glXPixmapRes
+ * __glXWindowRes
+ * __glXPbufferRes
+ */
+
+#ifdef PANORAMIX
+/** Search the Xinerama XRT_PIXMAP resources for the pixmap that needs
+ * to have its image saved. */
+static void dmxBEFindPixmapImage(pointer value, XID id, RESTYPE type,
+ pointer p)
+{
+ if ((type & TypeMask) == (XRT_PIXMAP & TypeMask)) {
+ PixmapPtr pDst = (PixmapPtr)p;
+ int idx = pDst->drawable.pScreen->myNum;
+ PanoramiXRes *pXinPix = (PanoramiXRes *)value;
+ PixmapPtr pPix;
+ int i;
+
+ dixLookupResourceByType((pointer*) &pPix, pXinPix->info[idx].id,
+ RT_PIXMAP, NullClient, DixUnknownAccess);
+ if (pPix != pDst) return; /* Not a match.... Next! */
+
+ FOR_NSCREENS(i) {
+ PixmapPtr pSrc;
+ dmxPixPrivPtr pSrcPriv = NULL;
+
+ if (i == idx) continue; /* Self replication is bad */
+
+ dixLookupResourceByType((pointer*) &pSrc, pXinPix->info[i].id,
+ RT_PIXMAP, NullClient, DixUnknownAccess);
+ pSrcPriv = DMX_GET_PIXMAP_PRIV(pSrc);
+ if (pSrcPriv->pixmap) {
+ FoundPixImage = True;
+ return;
+ }
+ }
+ }
+}
+#endif
+
+/** Save the pixmap image only when there is not another screen with
+ * that pixmap from which the image can be read when the screen is
+ * reattached. To do this, we first try to find a pixmap on another
+ * screen corresponding to the one we are trying to save. If we find
+ * one, then we do not need to save the image data since during
+ * reattachment, the image data can be read from that other pixmap.
+ * However, if we do not find one, then we need to save the image data.
+ * The common case for these are for the default stipple and root
+ * tile. */
+static void dmxBESavePixmap(PixmapPtr pPixmap)
+{
+#ifdef PANORAMIX
+ int i;
+
+ /* If Xinerama is not active, there's nothing we can do (see comment
+ * in #else below for more info). */
+ if (noPanoramiXExtension) return;
+
+ FoundPixImage = False;
+ for (i = currentMaxClients; --i >= 0; )
+ if (clients[i])
+ FindAllClientResources(clients[i], dmxBEFindPixmapImage,
+ (pointer)pPixmap);
+
+ /* Save the image only if there is no other screens that have a
+ * pixmap that corresponds to the one we are trying to save. */
+ if (!FoundPixImage) {
+ dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV(pPixmap);
+
+ if (!pPixPriv->detachedImage) {
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+
+ pPixPriv->detachedImage = XGetImage(dmxScreen->beDisplay,
+ pPixPriv->pixmap,
+ 0, 0,
+ pPixmap->drawable.width,
+ pPixmap->drawable.height,
+ -1,
+ ZPixmap);
+ if (!pPixPriv->detachedImage)
+ dmxLog(dmxWarning, "Cannot save pixmap image\n");
+ }
+ }
+#else
+ /* NOTE: The only time there is a pixmap on another screen that
+ * corresponds to the one we are trying to save is when Xinerama is
+ * active. Otherwise, the pixmap image data is only stored on a
+ * single screen, which means that once it is detached, that data is
+ * lost. We could save the data here, but then that would require
+ * us to implement the ability for Xdmx to keep the pixmap up to
+ * date while the screen is detached, which is beyond the scope of
+ * the current project. */
+ return;
+#endif
+}
+
+/** Destroy resources on the back-end server. This function is called
+ * from #dmxDetachScreen() via the dix layer's FindAllResources
+ * function. It walks all resources, compares them to the screen
+ * number passed in as \a n and calls the appropriate DMX function to
+ * free the associated resource on the back-end server. */
+static void dmxBEDestroyResources(pointer value, XID id, RESTYPE type,
+ pointer n)
+{
+ int scrnNum = (uintptr_t)n;
+ ScreenPtr pScreen = screenInfo.screens[scrnNum];
+
+ if ((type & TypeMask) == (RT_WINDOW & TypeMask)) {
+ /* Window resources are destroyed below in dmxBEDestroyWindowTree */
+ } else if ((type & TypeMask) == (RT_PIXMAP & TypeMask)) {
+ PixmapPtr pPix = value;
+ if (pPix->drawable.pScreen->myNum == scrnNum) {
+ dmxBESavePixmap(pPix);
+ dmxBEFreePixmap(pPix);
+ }
+ } else if ((type & TypeMask) == (RT_GC & TypeMask)) {
+ GCPtr pGC = value;
+ if (pGC->pScreen->myNum == scrnNum)
+ dmxBEFreeGC(pGC);
+ } else if ((type & TypeMask) == (RT_FONT & TypeMask)) {
+ dmxBEFreeFont(pScreen, (FontPtr)value);
+ } else if ((type & TypeMask) == (RT_CURSOR & TypeMask)) {
+ dmxBEFreeCursor(pScreen, (CursorPtr)value);
+ } else if ((type & TypeMask) == (RT_COLORMAP & TypeMask)) {
+ ColormapPtr pCmap = value;
+ if (pCmap->pScreen->myNum == scrnNum)
+ dmxBEFreeColormap((ColormapPtr)value);
+ } else if ((type & TypeMask) == (PictureType & TypeMask)) {
+ PicturePtr pPict = value;
+ if (pPict->pDrawable->pScreen->myNum == scrnNum) {
+ /* Free the pixmaps on the backend if needed */
+ if (pPict->pDrawable->type == DRAWABLE_PIXMAP) {
+ PixmapPtr pPixmap = (PixmapPtr)(pPict->pDrawable);
+ dmxBESavePixmap(pPixmap);
+ dmxBEFreePixmap(pPixmap);
+ }
+ dmxBEFreePicture((PicturePtr)value);
+ }
+ } else if ((type & TypeMask) == (GlyphSetType & TypeMask)) {
+ dmxBEFreeGlyphSet(pScreen, (GlyphSetPtr)value);
+ } else {
+ /* Other resource types??? */
+ }
+}
+
+/** Destroy the scratch GCs that are created per depth. */
+static void dmxBEDestroyScratchGCs(int scrnNum)
+{
+ ScreenPtr pScreen = screenInfo.screens[scrnNum];
+ GCPtr *ppGC = pScreen->GCperDepth;
+ int i;
+
+ for (i = 0; i <= pScreen->numDepths; i++)
+ dmxBEFreeGC(ppGC[i]);
+}
+
+/** Destroy window hierachy on back-end server. To ensure that all
+ * XDestroyWindow() calls succeed, they must be performed in a bottom
+ * up order so that windows are not destroyed before their children.
+ * XDestroyWindow(), which is called from #dmxBEDestroyWindow(), will
+ * destroy a window as well as all of it's children. */
+static void dmxBEDestroyWindowTree(int idx)
+{
+ WindowPtr pWin = screenInfo.screens[idx]->root;
+ WindowPtr pChild = pWin;
+
+ while (1) {
+ if (pChild->firstChild) {
+ pChild = pChild->firstChild;
+ continue;
+ }
+
+ /* Destroy the window */
+ dmxBEDestroyWindow(pChild);
+
+ /* Make sure we destroy the window's border and background
+ * pixmaps if they exist */
+ if (!pChild->borderIsPixel) {
+ dmxBESavePixmap(pChild->border.pixmap);
+ dmxBEFreePixmap(pChild->border.pixmap);
+ }
+ if (pChild->backgroundState == BackgroundPixmap) {
+ dmxBESavePixmap(pChild->background.pixmap);
+ dmxBEFreePixmap(pChild->background.pixmap);
+ }
+
+ while (!pChild->nextSib && (pChild != pWin)) {
+ pChild = pChild->parent;
+ dmxBEDestroyWindow(pChild);
+ if (!pChild->borderIsPixel) {
+ dmxBESavePixmap(pChild->border.pixmap);
+ dmxBEFreePixmap(pChild->border.pixmap);
+ }
+ if (pChild->backgroundState == BackgroundPixmap) {
+ dmxBESavePixmap(pChild->background.pixmap);
+ dmxBEFreePixmap(pChild->background.pixmap);
+ }
+ }
+
+ if (pChild == pWin)
+ break;
+
+ pChild = pChild->nextSib;
+ }
+}
+
+/** Detach back-end screen. */
+int dmxDetachScreen(int idx)
+{
+ DMXScreenInfo *dmxScreen = &dmxScreens[idx];
+ int i;
+
+ /* Return failure if dynamic addition/removal of screens is disabled */
+ if (!dmxAddRemoveScreens) {
+ dmxLog(dmxWarning,
+ "Attempting to remove a screen, but the AddRemoveScreen\n");
+ dmxLog(dmxWarning,
+ "extension has not been enabled. To enable this extension\n");
+ dmxLog(dmxWarning,
+ "add the \"-addremovescreens\" option either to the command\n");
+ dmxLog(dmxWarning,
+ "line or in the configuration file.\n");
+ return 1;
+ }
+
+ /* Cannot remove a screen that does not exist */
+ if (idx < 0 || idx >= dmxNumScreens) return 1;
+
+ /* Cannot detach from a screen that is not opened */
+ if (!dmxScreen->beDisplay) {
+ dmxLog(dmxWarning,
+ "Attempting to remove screen #%d but it has not been opened\n",
+ idx);
+ return 1;
+ }
+
+ dmxLogOutput(dmxScreen, "Detaching screen #%d\n", idx);
+
+ /* Detach input */
+ dmxInputDetachAll(dmxScreen);
+
+ /* Save all relevant state (TODO) */
+
+ /* Free all non-window resources related to this screen */
+ for (i = currentMaxClients; --i >= 0; )
+ if (clients[i])
+ FindAllClientResources(clients[i], dmxBEDestroyResources,
+ (pointer)(uintptr_t)idx);
+
+ /* Free scratch GCs */
+ dmxBEDestroyScratchGCs(idx);
+
+ /* Free window resources related to this screen */
+ dmxBEDestroyWindowTree(idx);
+
+ /* Free default stipple */
+ dmxBESavePixmap(screenInfo.screens[idx]->PixmapPerDepth[0]);
+ dmxBEFreePixmap(screenInfo.screens[idx]->PixmapPerDepth[0]);
+
+ /* Free the remaining screen resources and close the screen */
+ dmxBECloseScreen(screenInfo.screens[idx]);
+
+ /* Adjust the cursor boundaries (paints detached console window) */
+ dmxAdjustCursorBoundaries();
+
+ return 0; /* Success */
+}
diff --git a/xorg-server/hw/dmx/dmxgcops.c b/xorg-server/hw/dmx/dmxgcops.c
index 8f4f5c774..07165f731 100644
--- a/xorg-server/hw/dmx/dmxgcops.c
+++ b/xorg-server/hw/dmx/dmxgcops.c
@@ -529,7 +529,7 @@ static DMXScreenInfo *dmxFindAlternatePixmap(DrawablePtr pDrawable, XID *draw)
NullClient, DixUnknownAccess))
return NULL;
- for (i = 1; i < PanoramiXNumScreens; i++) {
+ FOR_NSCREENS_FORWARD_SKIP(i) {
dmxScreen = &dmxScreens[i];
if (dmxScreen->beDisplay) {
PixmapPtr pSrc;
diff --git a/xorg-server/render/render.c b/xorg-server/render/render.c
index 04ae0e122..3f013439c 100644
--- a/xorg-server/render/render.c
+++ b/xorg-server/render/render.c
@@ -2690,7 +2690,7 @@ PanoramiXRenderCreatePicture (ClientPtr client)
if(!(newPict = (PanoramiXRes *) malloc(sizeof(PanoramiXRes))))
return BadAlloc;
newPict->type = XRT_PICTURE;
- newPict->info[0].id = stuff->pid;
+ panoramix_setup_ids(newPict, client, stuff->pid);
if (refDraw->type == XRT_WINDOW &&
stuff->drawable == screenInfo.screens[0]->root->drawable.id)
@@ -2699,9 +2699,6 @@ PanoramiXRenderCreatePicture (ClientPtr client)
}
else
newPict->u.pict.root = FALSE;
-
- for(j = 1; j < PanoramiXNumScreens; j++)
- newPict->info[j].id = FakeClientID(client->index);
FOR_NSCREENS_BACKWARD(j) {
stuff->pid = newPict->info[j].id;
@@ -3225,11 +3222,8 @@ PanoramiXRenderCreateSolidFill (ClientPtr client)
return BadAlloc;
newPict->type = XRT_PICTURE;
- newPict->info[0].id = stuff->pid;
+ panoramix_setup_ids(newPict, client, stuff->pid);
newPict->u.pict.root = FALSE;
-
- for(j = 1; j < PanoramiXNumScreens; j++)
- newPict->info[j].id = FakeClientID(client->index);
FOR_NSCREENS_BACKWARD(j) {
stuff->pid = newPict->info[j].id;
@@ -3258,12 +3252,9 @@ PanoramiXRenderCreateLinearGradient (ClientPtr client)
return BadAlloc;
newPict->type = XRT_PICTURE;
- newPict->info[0].id = stuff->pid;
+ panoramix_setup_ids(newPict, client, stuff->pid);
newPict->u.pict.root = FALSE;
- for(j = 1; j < PanoramiXNumScreens; j++)
- newPict->info[j].id = FakeClientID(client->index);
-
FOR_NSCREENS_BACKWARD(j) {
stuff->pid = newPict->info[j].id;
result = (*PanoramiXSaveRenderVector[X_RenderCreateLinearGradient]) (client);
@@ -3291,12 +3282,9 @@ PanoramiXRenderCreateRadialGradient (ClientPtr client)
return BadAlloc;
newPict->type = XRT_PICTURE;
- newPict->info[0].id = stuff->pid;
+ panoramix_setup_ids(newPict, client, stuff->pid);
newPict->u.pict.root = FALSE;
- for(j = 1; j < PanoramiXNumScreens; j++)
- newPict->info[j].id = FakeClientID(client->index);
-
FOR_NSCREENS_BACKWARD(j) {
stuff->pid = newPict->info[j].id;
result = (*PanoramiXSaveRenderVector[X_RenderCreateRadialGradient]) (client);
@@ -3324,12 +3312,9 @@ PanoramiXRenderCreateConicalGradient (ClientPtr client)
return BadAlloc;
newPict->type = XRT_PICTURE;
- newPict->info[0].id = stuff->pid;
+ panoramix_setup_ids(newPict, client, stuff->pid);
newPict->u.pict.root = FALSE;
- for(j = 1; j < PanoramiXNumScreens; j++)
- newPict->info[j].id = FakeClientID(client->index);
-
FOR_NSCREENS_BACKWARD(j) {
stuff->pid = newPict->info[j].id;
result = (*PanoramiXSaveRenderVector[X_RenderCreateConicalGradient]) (client);
diff --git a/xorg-server/xkeyboard-config/rules/base.extras.xml.in b/xorg-server/xkeyboard-config/rules/base.extras.xml.in
index f72e4cf95..188855ab4 100644
--- a/xorg-server/xkeyboard-config/rules/base.extras.xml.in
+++ b/xorg-server/xkeyboard-config/rules/base.extras.xml.in
@@ -23,7 +23,7 @@
<variant>
<configItem>
<name>ave</name>
- <_description>Iran Avestan</_description>
+ <_description>Iran - Avestan</_description>
<languageList><iso639Id>ave</iso639Id></languageList>
</configItem>
</variant>
@@ -31,6 +31,22 @@
</layout>
<layout>
<configItem>
+ <name>lt</name>
+ <_shortDescription>Ltu</_shortDescription>
+ <_description>Lithuania</_description>
+ <languageList><iso639Id>lit</iso639Id></languageList>
+ </configItem>
+ <variantList>
+ <variant>
+ <configItem>
+ <name>dvorak</name>
+ <_description>Lithuania - Dvorak</_description>
+ </configItem>
+ </variant>
+ </variantList>
+ </layout>
+ <layout>
+ <configItem>
<name>us</name>
<_shortDescription>USA</_shortDescription>
<_description>USA</_description>
@@ -40,26 +56,26 @@
<variant>
<configItem>
<name>intl-unicode</name>
- <_description>USA International (AltGr Unicode combining)</_description>
+ <_description>USA - International (AltGr Unicode combining)</_description>
</configItem>
</variant>
<variant>
<configItem>
<name>alt-intl-unicode</name>
- <_description>USA International (AltGr Unicode combining, alternative)</_description>
+ <_description>USA - International (AltGr Unicode combining, alternative)</_description>
</configItem>
</variant>
<variant>
<configItem>
<name>ats</name>
- <_description>USA Atsina</_description>
+ <_description>USA - Atsina</_description>
<!-- No ISO code in ISO639-2, only draft ISO693-3 -->
</configItem>
</variant>
<variant>
<configItem>
<name>crd</name>
- <_description>USA Couer D'alene Salish</_description>
+ <_description>USA - Couer D'alene Salish</_description>
<languageList><iso639Id>crd</iso639Id></languageList>
</configItem>
</variant>
@@ -76,7 +92,7 @@
<variant>
<configItem>
<name>ergonomic</name>
- <_description>Ergonomic Touchtype</_description>
+ <_description>Romania - Ergonomic Touchtype</_description>
</configItem>
</variant>
</variantList>
@@ -84,7 +100,7 @@
<layout>
<configItem>
<name>rs</name>
- <_shortDescription>SRB</_shortDescription>
+ <_shortDescription>Srb</_shortDescription>
<_description>Serbia</_description>
<languageList><iso639Id>srp</iso639Id></languageList>
</configItem>
@@ -92,7 +108,7 @@
<variant>
<configItem>
<name>combiningkeys</name>
- <_description>Serbia Combining accents instead of dead keys</_description>
+ <_description>Serbia - Combining accents instead of dead keys</_description>
</configItem>
</variant>
</variantList>
@@ -107,7 +123,7 @@
<variant>
<configItem>
<name>chu</name>
- <description>Russia Church Slavonic</description>
+ <description>Russia - Church Slavonic</description>
<languageList><iso639Id>chu</iso639Id></languageList>
</configItem>
</variant>
diff --git a/xorg-server/xkeyboard-config/rules/base.xml.in b/xorg-server/xkeyboard-config/rules/base.xml.in
index 1a3d528d1..e4c79fe77 100644
--- a/xorg-server/xkeyboard-config/rules/base.xml.in
+++ b/xorg-server/xkeyboard-config/rules/base.xml.in
@@ -1778,7 +1778,7 @@
<variant>
<configItem>
<name>mal_enhanced</name>
- <_description>India - Malayalam enhanced INSCRIPT with Rupee Sign</_description>
+ <_description>India - Malayalam enhanced Inscript with Rupee Sign</_description>
<languageList><iso639Id>mal</iso639Id></languageList>
</configItem>
</variant>
@@ -3925,7 +3925,7 @@
<layout>
<configItem>
<name>rs</name>
- <_shortDescription>SRB</_shortDescription>
+ <_shortDescription>Srb</_shortDescription>
<_description>Serbia</_description>
<languageList>
<iso639Id>srp</iso639Id>
diff --git a/xorg-server/xkeyboard-config/symbols/in b/xorg-server/xkeyboard-config/symbols/in
index 10683855b..c46a05373 100644
--- a/xorg-server/xkeyboard-config/symbols/in
+++ b/xorg-server/xkeyboard-config/symbols/in
@@ -1351,7 +1351,7 @@ xkb_symbols "eng" {
partial alphanumeric_keys
xkb_symbols "mal_enhanced" {
- name[Group1] = "India - Malayalam Modified Inscript with Rupee Sign";
+ name[Group1] = "India - Malayalam enhanced Inscript with Rupee Sign";
//From grave to backslash (\)
diff --git a/xorg-server/xkeyboard-config/symbols/lk b/xorg-server/xkeyboard-config/symbols/lk
index 8480607de..fba5b29e1 100644
--- a/xorg-server/xkeyboard-config/symbols/lk
+++ b/xorg-server/xkeyboard-config/symbols/lk
@@ -1,7 +1,7 @@
// X Keyboard Extension file for Sinhala (Sri Lanka) (2004-04-22)
// Maintainer : Harshula Jayasuriya <harshula@gmail.com>
-// Last Updated: 2007-06-29
-// This is a static phonetic mapping for a standard US-English keyboard
+// Last Updated: 2011-03-20
+// This is a phonetic static mapping for a standard US-English keyboard
// (qwerty)
// http://www.nongnu.org/sinhala/doc/keymaps/sinhala-keyboard_3.html
@@ -37,42 +37,42 @@ xkb_symbols "sin_phonetic" {
key.type[Group1] = "FOUR_LEVEL";
// q - p
- key <AD01> { [ 0x01000d8d, 0x01000d8e, 0x01000dd8, 0x01000df2 ] };
- key <AD02> { [ 0x01000d87, 0x01000d88, 0x01000dd0, 0x01000dd1 ] };
- key <AD03> { [ 0x01000d91, 0x01000d92, 0x01000dd9, 0x01000dda ] };
- key <AD04> { [ 0x01000dbb, 0x01000dca, 0x01000dbb, NoSymbol ] };
- key <AD05> { [ 0x01000dad, 0x01000dae, 0x01000da7, 0x01000da8 ] };
- key <AD06> { [ 0x01000dba, 0x01000dca, NoSymbol, NoSymbol ] };
- key <AD07> { [ 0x01000d8b, 0x01000d8c, 0x01000dd4, 0x01000dd6 ] };
- key <AD08> { [ 0x01000d89, 0x01000d8a, 0x01000dd2, 0x01000dd3 ] };
- key <AD09> { [ 0x01000d94, 0x01000d95, 0x01000ddc, 0x01000ddd ] };
- key <AD10> { [ 0x01000db4, 0x01000db5, NoSymbol, NoSymbol ] };
+ key <AD01> { [ Sinh_ri, Sinh_rii, Sinh_ru2, Sinh_ruu2 ] };
+ key <AD02> { [ Sinh_ae, Sinh_aee, Sinh_ae2, Sinh_aee2 ] };
+ key <AD03> { [ Sinh_e, Sinh_ee, Sinh_e2, Sinh_ee2 ] };
+ key <AD04> { [ Sinh_ra, Sinh_al, Sinh_ra, NoSymbol ] };
+ key <AD05> { [ Sinh_tha, Sinh_thha, Sinh_tta, Sinh_ttha ] };
+ key <AD06> { [ Sinh_ya, Sinh_al, NoSymbol, NoSymbol ] };
+ key <AD07> { [ Sinh_u, Sinh_uu, Sinh_u2, Sinh_uu2 ] };
+ key <AD08> { [ Sinh_i, Sinh_ii, Sinh_i2, Sinh_ii2 ] };
+ key <AD09> { [ Sinh_o, Sinh_oo, Sinh_o2, Sinh_oo2 ] };
+ key <AD10> { [ Sinh_pa, Sinh_pha, NoSymbol, NoSymbol ] };
// a - l
- key <AC01> { [ 0x01000d85, 0x01000d86, 0x01000dca, 0x01000dcf ] };
- key <AC02> { [ 0x01000dc3, 0x01000dc1, 0x01000dc2, NoSymbol ] };
- key <AC03> { [ 0x01000daf, 0x01000db0, 0x01000da9, 0x01000daa ] };
- key <AC04> { [ 0x01000dc6, NoSymbol, 0x01000ddb, 0x01000d93 ] };
- key <AC05> { [ 0x01000d9c, 0x01000d9d, 0x01000d9f, NoSymbol ] };
- key <AC06> { [ 0x01000dc4, 0x01000d83, 0x01000dde, 0x01000d96 ] };
- key <AC07> { [ 0x01000da2, 0x01000da3, 0x01000da6, NoSymbol ] };
- key <AC08> { [ 0x01000d9a, 0x01000d9b, 0x01000d8f, 0x01000d90 ] };
- key <AC09> { [ 0x01000dbd, 0x01000dc5, 0x01000ddf, 0x01000df3 ] };
+ key <AC01> { [ Sinh_a, Sinh_aa, Sinh_al, Sinh_aa2 ] };
+ key <AC02> { [ Sinh_sa, Sinh_sha, Sinh_ssha, NoSymbol ] };
+ key <AC03> { [ Sinh_dha, Sinh_dhha, Sinh_dda, Sinh_ddha ] };
+ key <AC04> { [ Sinh_fa, NoSymbol, Sinh_ai2, Sinh_ai ] };
+ key <AC05> { [ Sinh_ga, Sinh_gha, Sinh_nga, NoSymbol ] };
+ key <AC06> { [ Sinh_ha, Sinh_h2, Sinh_au2, Sinh_au ] };
+ key <AC07> { [ Sinh_ja, Sinh_jha, Sinh_nja, NoSymbol ] };
+ key <AC08> { [ Sinh_ka, Sinh_kha, Sinh_lu, Sinh_luu ] };
+ key <AC09> { [ Sinh_la, Sinh_lla, Sinh_lu2, Sinh_luu2 ] };
// z - ?
- key <AB01> { [ 0x01000da4, 0x01000da5, NoSymbol, NoSymbol ] };
- key <AB02> { [ 0x01000db3, 0x01000dac, NoSymbol, NoSymbol ] };
- key <AB03> { [ 0x01000da0, 0x01000da1, NoSymbol, NoSymbol ] };
- key <AB04> { [ 0x01000dc0, NoSymbol, NoSymbol, NoSymbol ] };
- key <AB05> { [ 0x01000db6, 0x01000db7, NoSymbol, NoSymbol ] };
- key <AB06> { [ 0x01000db1, 0x01000dab, 0x01000d82, 0x01000d9e ] };
- key <AB07> { [ 0x01000db8, 0x01000db9, NoSymbol, NoSymbol ] };
- key <AB08> { [ any, any, 0x01000dca, NoSymbol ] };
- key <AB09> { [ any, any, 0x01000df4, NoSymbol ] };
- key <AB10> { [ any, any, 0x0100200d, NoSymbol ] };
+ key <AB01> { [ Sinh_nya, Sinh_jnya, NoSymbol, NoSymbol ] };
+ key <AB02> { [ Sinh_ndha, Sinh_ndda, NoSymbol, NoSymbol ] };
+ key <AB03> { [ Sinh_ca, Sinh_cha, NoSymbol, NoSymbol ] };
+ key <AB04> { [ Sinh_va, NoSymbol, NoSymbol, NoSymbol ] };
+ key <AB05> { [ Sinh_ba, Sinh_bha, NoSymbol, NoSymbol ] };
+ key <AB06> { [ Sinh_na, Sinh_nna, Sinh_ng, Sinh_ng2 ] };
+ key <AB07> { [ Sinh_ma, Sinh_mba, NoSymbol, NoSymbol ] };
+ key <AB08> { [ any, any, Sinh_al, NoSymbol ] };
+ key <AB09> { [ any, any, Sinh_kunddaliya, NoSymbol ] };
+ key <AB10> { [ any, any, 0x100200d, NoSymbol ] };
// Space
- include "nbsp(zwnj2nb3s)"
+ include "nbsp(nb2zwnj3s)"
include "level3(ralt_switch)"
};
@@ -88,3 +88,4 @@ xkb_symbols "tam_TAB" {
include "in(tam_TAB)"
name[Group1]= "Sri Lanka - Tamil TAB Typewriter";
};
+
diff --git a/xorg-server/xkeyboard-config/symbols/lt b/xorg-server/xkeyboard-config/symbols/lt
index 5a19dc265..eaff3c3cc 100644
--- a/xorg-server/xkeyboard-config/symbols/lt
+++ b/xorg-server/xkeyboard-config/symbols/lt
@@ -294,3 +294,25 @@ xkb_symbols "lekpa" {
key <AB09> {[ aogonek, Aogonek, greater ]};
key <AB10> {[ h, H ]};
};
+
+partial alphanumeric_keys modifier_keys
+xkb_symbols "dvorak" {
+
+ include "us(dvorak)"
+
+ name[Group1]="Lithuania - Dvorak";
+
+ key <AE01> { [ aogonek, Aogonek, 1, exclam ] };
+ key <AE02> { [ ccaron, Ccaron, 2, at ] };
+ key <AE03> { [ eogonek, Eogonek, 3, numbersign ] };
+ key <AE04> { [ eabovedot, Eabovedot, 4, dollar ] };
+ key <AE05> { [ iogonek, Iogonek, 5, percent ] };
+ key <AE06> { [ scaron, Scaron, 6, asciicircum ] };
+ key <AE07> { [ uogonek, Uogonek, 7, ampersand ] };
+ key <AE08> { [ umacron, Umacron, 8, asterisk ] };
+ key <AE09> { [doublelowquotemark, parenleft, 9, parenleft ] };
+ key <AE10> { [leftdoublequotemark,parenright, 0, parenright ] };
+ key <AD12> { [ zcaron, Zcaron, equal, plus ] };
+
+ include "level3(ralt_switch)"
+};
diff --git a/xorg-server/xkeyboard-config/symbols/nbsp b/xorg-server/xkeyboard-config/symbols/nbsp
index 220dae460..f6139ed90 100644
--- a/xorg-server/xkeyboard-config/symbols/nbsp
+++ b/xorg-server/xkeyboard-config/symbols/nbsp
@@ -145,9 +145,7 @@ xkb_symbols "zwnj2nb3" {
// ZWNJ on level 2
-// ZWJ on level 3
-// NBSP on level 4
-// Used by lk(sin_phonetic)
+// NBSP on level 3
partial
xkb_symbols "zwnj2nb3s" {
key <SPCE> {
@@ -192,3 +190,15 @@ xkb_symbols "zwnj3zwj4" {
symbols[Group1]= [ space, space, 0x100200c, 0x100200d ]
};
};
+
+
+// NBSP on level 2
+// ZWNJ on level 3
+// Used by lk(sin_phonetic)
+partial
+xkb_symbols "nb2zwnj3s" {
+ key <SPCE> {
+ type[Group1]="FOUR_LEVEL",
+ symbols[Group1]= [ space, nobreakspace, 0x100200c, NoSymbol ]
+ };
+};