1 /*
2 * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina.
3 *
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation on the rights to use, copy, modify, merge,
10 * publish, distribute, sublicense, and/or sell copies of the Software,
11 * and to permit persons to whom the Software is furnished to do so,
12 * subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial
16 * portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
22 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 * SOFTWARE.
26 */
27
28 /*
29 * Authors:
30 * Rickard E. (Rik) Faith <faith@redhat.com>
31 *
32 */
33
34 /** \file
35 * This code queries and modifies the connection block. */
36
37 #ifdef HAVE_DMX_CONFIG_H
38 #include <dmx-config.h>
39 #endif
40
41 #include "dmx.h"
42 #include "dmxcb.h"
43 #include "dmxinput.h"
44 #include "dmxlog.h"
45
46 extern int connBlockScreenStart;
47
48 #ifdef PANORAMIX
49 #include "panoramiXsrv.h"
50 #endif
51
52 int dmxGlobalWidth, dmxGlobalHeight;
53
54 /** We may want the wall dimensions to be different from the bounding
55 * box dimensions that Xinerama computes, so save those and update them
56 * here.
57 */
58 void
dmxSetWidthHeight(int width,int height)59 dmxSetWidthHeight(int width, int height)
60 {
61 dmxGlobalWidth = width;
62 dmxGlobalHeight = height;
63 }
64
65 /** Computes the global bounding box for DMX. This may be larger than
66 * the one computed by Xinerama because of the DMX configuration
67 * file. */
68 void
dmxComputeWidthHeight(DMXRecomputeFlag flag)69 dmxComputeWidthHeight(DMXRecomputeFlag flag)
70 {
71 int i;
72 DMXScreenInfo *dmxScreen;
73 int w = 0;
74 int h = 0;
75
76 for (i = 0; i < dmxNumScreens; i++) {
77 /* Don't use root* here because this is
78 * the global bounding box. */
79 dmxScreen = &dmxScreens[i];
80 if (w < dmxScreen->scrnWidth + dmxScreen->rootXOrigin)
81 w = dmxScreen->scrnWidth + dmxScreen->rootXOrigin;
82 if (h < dmxScreen->scrnHeight + dmxScreen->rootYOrigin)
83 h = dmxScreen->scrnHeight + dmxScreen->rootYOrigin;
84 }
85 if (!dmxGlobalWidth && !dmxGlobalHeight) {
86 dmxLog(dmxInfo, "Using %dx%d as global bounding box\n", w, h);
87 }
88 else {
89 switch (flag) {
90 case DMX_NO_RECOMPUTE_BOUNDING_BOX:
91 dmxLog(dmxInfo,
92 "Using old bounding box (%dx%d) instead of new (%dx%d)\n",
93 dmxGlobalWidth, dmxGlobalHeight, w, h);
94 w = dmxGlobalWidth;
95 h = dmxGlobalHeight;
96 break;
97 case DMX_RECOMPUTE_BOUNDING_BOX:
98 dmxLog(dmxInfo,
99 "Using %dx%d as global bounding box, instead of %dx%d\n",
100 w, h, dmxGlobalWidth, dmxGlobalHeight);
101 break;
102 }
103 }
104
105 dmxGlobalWidth = w;
106 dmxGlobalHeight = h;
107 }
108
109 /** A callback routine that hooks into Xinerama and provides a
110 * convenient place to print summary log information during server
111 * startup. This routine does not modify any values. */
112 void
dmxConnectionBlockCallback(void)113 dmxConnectionBlockCallback(void)
114 {
115 xWindowRoot *root = (xWindowRoot *) (ConnectionInfo + connBlockScreenStart);
116 int offset = connBlockScreenStart + sizeof(xWindowRoot);
117 int i;
118 Bool *found = NULL;
119
120 MAXSCREENSALLOC(found);
121 if (!found)
122 dmxLog(dmxFatal, "dmxConnectionBlockCallback: out of memory\n");
123
124 dmxLog(dmxInfo, "===== Start of Summary =====\n");
125 #ifdef PANORAMIX
126 if (!noPanoramiXExtension) {
127 if (dmxGlobalWidth && dmxGlobalHeight
128 && (dmxGlobalWidth != PanoramiXPixWidth
129 || dmxGlobalHeight != PanoramiXPixHeight)) {
130 dmxLog(dmxInfo,
131 "Changing Xinerama dimensions from %d %d to %d %d\n",
132 PanoramiXPixWidth, PanoramiXPixHeight,
133 dmxGlobalWidth, dmxGlobalHeight);
134 PanoramiXPixWidth = root->pixWidth = dmxGlobalWidth;
135 PanoramiXPixHeight = root->pixHeight = dmxGlobalHeight;
136 }
137 else {
138 dmxGlobalWidth = PanoramiXPixWidth;
139 dmxGlobalHeight = PanoramiXPixHeight;
140 }
141 dmxLog(dmxInfo, "%d screens configured with Xinerama (%d %d)\n",
142 PanoramiXNumScreens, PanoramiXPixWidth, PanoramiXPixHeight);
143 FOR_NSCREENS(i) found[i] = FALSE;
144 }
145 else {
146 #endif
147 /* This never happens because we're
148 * either called from a Xinerama
149 * callback or during reconfiguration
150 * (which only works with Xinerama on).
151 * In any case, be reasonable. */
152 dmxLog(dmxInfo, "%d screens configured (%d %d)\n",
153 screenInfo.numScreens, root->pixWidth, root->pixHeight);
154 #ifdef PANORAMIX
155 }
156 #endif
157
158 for (i = 0; i < root->nDepths; i++) {
159 xDepth *depth = (xDepth *) (ConnectionInfo + offset);
160 int voffset = offset + sizeof(xDepth);
161 xVisualType *visual = (xVisualType *) (ConnectionInfo + voffset);
162 int j;
163
164 dmxLog(dmxInfo, "%d visuals at depth %d:\n",
165 depth->nVisuals, depth->depth);
166 for (j = 0; j < depth->nVisuals; j++, visual++) {
167 XVisualInfo vi;
168
169 vi.visual = NULL;
170 vi.visualid = visual->visualID;
171 vi.screen = 0;
172 vi.depth = depth->depth;
173 vi.class = visual->class;
174 vi.red_mask = visual->redMask;
175 vi.green_mask = visual->greenMask;
176 vi.blue_mask = visual->blueMask;
177 vi.colormap_size = visual->colormapEntries;
178 vi.bits_per_rgb = visual->bitsPerRGB;
179 dmxLogVisual(NULL, &vi, 0);
180
181 #ifdef PANORAMIX
182 if (!noPanoramiXExtension) {
183 int k;
184
185 FOR_NSCREENS(k) {
186 DMXScreenInfo *dmxScreen = &dmxScreens[k];
187
188 if (dmxScreen->beDisplay) {
189 XVisualInfo *pvi =
190 &dmxScreen->beVisuals[dmxScreen->beDefVisualIndex];
191 if (pvi->depth == depth->depth &&
192 pvi->class == visual->class)
193 found[k] = TRUE;
194 }
195 else {
196 /* Screen #k is detatched, so it always succeeds */
197 found[k] = TRUE;
198 }
199 }
200 }
201 #endif
202 }
203 offset = voffset + depth->nVisuals * sizeof(xVisualType);
204 }
205
206 dmxInputLogDevices();
207 dmxLog(dmxInfo, "===== End of Summary =====\n");
208
209 #ifdef PANORAMIX
210 if (!noPanoramiXExtension) {
211 Bool fatal = FALSE;
212
213 FOR_NSCREENS(i) {
214 fatal |= !found[i];
215 if (!found[i]) {
216 dmxLog(dmxError,
217 "The default visual for screen #%d does not match "
218 "any of the\n", i);
219 dmxLog(dmxError,
220 "consolidated visuals from Xinerama (listed above)\n");
221 }
222 }
223 if (fatal)
224 dmxLog(dmxFatal,
225 "dmxConnectionBlockCallback: invalid screen(s) found");
226 }
227 #endif
228 MAXSCREENSFREE(found);
229 }
230