~ubuntu-branches/ubuntu/gutsy/vnc4/gutsy

« back to all changes in this revision

Viewing changes to unix/xc/programs/Xserver/hw/xfree86/xf86cfg/screen.c

  • Committer: Bazaar Package Importer
  • Author(s): Ola Lundqvist
  • Date: 2006-05-15 20:35:17 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060515203517-l4lre1ku942mn26k
Tags: 4.1.1+X4.3.0-10
* Correction of critical security issue. Thanks to Martin Kogler
  <e9925248@student.tuwien.ac.at> that informed me about the issue,
  and provided the patch.
  This flaw was originally found by Steve Wiseman of intelliadmin.com.
* Applied patch from Javier Kohen <jkohen@users.sourceforge.net> that
  inform the user that only 8 first characters of the password will
  actually be used when typing more than 8 characters, closes:
  #355619.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com)
 
3
 * 
 
4
 * Permission is hereby granted, free of charge, to any person obtaining a
 
5
 * copy of this software and associated documentation files (the "Software"),
 
6
 * to deal in the Software without restriction, including without limitation
 
7
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 
8
 * and/or sell copies of the Software, and to permit persons to whom the
 
9
 * Software is furnished to do so, subject to the following conditions:
 
10
 * 
 
11
 * The above copyright notice and this permission notice shall be included in
 
12
 * all copies or substantial portions of the Software.
 
13
 *  
 
14
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
15
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
16
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 
17
 * CONECTIVA LINUX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 
18
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
 
19
 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 
20
 * SOFTWARE.
 
21
 * 
 
22
 * Except as contained in this notice, the name of Conectiva Linux shall
 
23
 * not be used in advertising or otherwise to promote the sale, use or other
 
24
 * dealings in this Software without prior written authorization from
 
25
 * Conectiva Linux.
 
26
 *
 
27
 * Author: Paulo C�sar Pereira de Andrade <pcpa@conectiva.com.br>
 
28
 *
 
29
 * $XFree86: xc/programs/Xserver/hw/xfree86/xf86cfg/screen.c,v 1.9 2002/06/06 21:03:32 paulo Exp $
 
30
 */
 
31
 
 
32
#include <X11/IntrinsicP.h>
 
33
#include <X11/extensions/shape.h>
 
34
#include <X11/Xaw/Simple.h>
 
35
#include "screen.h"
 
36
 
 
37
#define CW      1
 
38
#define CCW     -1
 
39
 
 
40
/*
 
41
 * Prototypes
 
42
 */
 
43
void ReshapeScreenWidget(xf86cfgScreen*);
 
44
static int qcmp_screen(_Xconst void*, _Xconst void*);
 
45
 
 
46
/*
 
47
 * Initialization
 
48
 */
 
49
extern Widget work;
 
50
 
 
51
static int rows, columns;       /* number of rows/columns of monitors */
 
52
 
 
53
static int mon_width, mon_height;
 
54
static int *mon_widths, *mon_heights;
 
55
 
 
56
/*
 
57
 * Implementation
 
58
 */
 
59
void
 
60
SetScreenRotate(xf86cfgScreen *screen)
 
61
{
 
62
    static char *Rotate = "Rotate", *_CW = "CW", *_CCW = "CCW";
 
63
    int rotate = 0;
 
64
    XF86OptionPtr option, options;
 
65
 
 
66
    /* This is the only place where xf86cfg is intrusive, and deletes options
 
67
     * added by the user directly in the config file. The "Rotate" option
 
68
     * will be kept in the screen section.
 
69
     */
 
70
    if (screen->monitor != NULL) {
 
71
        options = ((XF86ConfMonitorPtr)(screen->monitor->config))->mon_option_lst;
 
72
        if ((option = xf86findOption(options, Rotate)) != NULL) {
 
73
            if (option->opt_val != NULL)
 
74
                rotate = strcasecmp(option->opt_val, _CW) == 0 ? CW :
 
75
                         strcasecmp(option->opt_val, _CCW) == 0 ? CCW : 0;
 
76
            xf86removeOption(&((XF86ConfMonitorPtr)(screen->monitor->config))
 
77
                             ->mon_option_lst, Rotate);
 
78
        }
 
79
    }
 
80
    if (screen->card != NULL) {
 
81
        options = ((XF86ConfDevicePtr)(screen->card->config))->dev_option_lst;
 
82
        if ((option = xf86findOption(options, Rotate)) != NULL) {
 
83
            if (option->opt_val != NULL)
 
84
                rotate += strcasecmp(option->opt_val, _CW) == 0 ? CW :
 
85
                          strcasecmp(option->opt_val, _CCW) == 0 ? CCW : 0;
 
86
            xf86removeOption(&((XF86ConfDevicePtr)(screen->card->config))
 
87
                             ->dev_option_lst, Rotate);
 
88
        }
 
89
    }
 
90
 
 
91
    options = screen->screen->scrn_option_lst;
 
92
    if ((option = xf86findOption(options, Rotate)) != NULL) {
 
93
        if (option->opt_val != NULL)
 
94
            rotate += strcasecmp(option->opt_val, _CW) == 0 ? CW :
 
95
                      strcasecmp(option->opt_val, _CCW) == 0 ? CCW : 0;
 
96
        xf86removeOption(&screen->screen->scrn_option_lst, Rotate);
 
97
    }
 
98
 
 
99
    rotate = rotate > 0 ? CW : rotate < 0 ? CCW : 0;
 
100
    if (rotate)
 
101
        screen->screen->scrn_option_lst =
 
102
            xf86addNewOption(screen->screen->scrn_option_lst,
 
103
                             XtNewString(Rotate),
 
104
                             XtNewString(rotate > 0 ? _CW : _CCW));
 
105
    screen->rotate = rotate;
 
106
}
 
107
 
 
108
void
 
109
CreateScreenWidget(xf86cfgScreen *screen)
 
110
{
 
111
    Widget w = XtCreateWidget("screen", simpleWidgetClass,
 
112
                              XtParent(computer.cpu), NULL, 0);
 
113
 
 
114
    SetScreenRotate(screen);
 
115
    XtRealizeWidget(w);
 
116
    screen->widget = w;
 
117
    screen->column = screen->row = -1;
 
118
 
 
119
    ReshapeScreenWidget(screen);
 
120
}
 
121
 
 
122
void
 
123
ReshapeScreenWidget(xf86cfgScreen *screen)
 
124
{
 
125
    Pixmap pixmap;
 
126
    XGCValues values;
 
127
    GC gc;
 
128
    int x = 0, y = 0, width = screen->rect.width, height = screen->rect.height;
 
129
    Widget w = screen->widget;
 
130
 
 
131
    if (screen->state == USED && screen->row >= 0) {
 
132
        if (screen->column == 0)
 
133
            x = w->core.width - width;
 
134
        else if (screen->column == columns - 1)
 
135
            x = w->core.width - mon_widths[screen->column];
 
136
        else
 
137
            x = (w->core.width - mon_widths[screen->column]) +
 
138
                ((mon_widths[screen->column] - width) >> 1);
 
139
 
 
140
        if (screen->row == 0)
 
141
            y = w->core.height - height;
 
142
        else if (screen->row == rows - 1)
 
143
            y = w->core.height - mon_heights[screen->row];
 
144
        else
 
145
            y = (w->core.height - mon_heights[screen->row]) +
 
146
                ((mon_heights[screen->row] - height) >> 1);
 
147
    }
 
148
    else if (screen->rect.width == 0) {
 
149
        width = w->core.width;
 
150
        height = w->core.height;
 
151
    }
 
152
 
 
153
    screen->rect.x = x;
 
154
    screen->rect.y = y;
 
155
    screen->rect.width = width;
 
156
    screen->rect.height = height;
 
157
    pixmap = XCreatePixmap(XtDisplay(w), XtWindow(w),
 
158
                           w->core.width, w->core.height, 1);
 
159
    values.foreground = 0;
 
160
    values.background = 1;
 
161
    gc = XCreateGC(XtDisplay(w), pixmap, GCForeground | GCBackground, &values);
 
162
    XFillRectangle(XtDisplay(w), pixmap, gc, 0, 0, w->core.width, w->core.height);
 
163
    XSetForeground(XtDisplay(w), gc, 1);
 
164
 
 
165
    DrawScreenMask(XtDisplay(w), pixmap, gc, x, y, x + width, y + height,
 
166
                   screen->rotate);
 
167
    XShapeCombineMask(XtDisplay(w), XtWindow(w), ShapeBounding, 
 
168
                      0, 0, pixmap, ShapeSet);
 
169
 
 
170
    /* Do not call XtSetValues, to avoid all extra code for caching pixmaps */
 
171
    XFreePixmap(XtDisplay(w), pixmap);
 
172
    if (XtIsRealized(w)) {
 
173
        pixmap = XCreatePixmap(XtDisplay(w), XtWindow(w),
 
174
                               w->core.width, w->core.height,
 
175
                               DefaultDepthOfScreen(XtScreen(w)));
 
176
        DrawScreen(XtDisplay(w), pixmap, x, y, x + width, y + height,
 
177
                   screen->state == USED ? True : False, screen->rotate);
 
178
        XSetWindowBackgroundPixmap(XtDisplay(w), XtWindow(w), pixmap);
 
179
        XClearWindow(XtDisplay(w), XtWindow(w));
 
180
        XFreePixmap(XtDisplay(w), pixmap);
 
181
    }
 
182
    XFreeGC(XtDisplay(w), gc);
 
183
}
 
184
 
 
185
void
 
186
AddScreen(xf86cfgDevice *mon, xf86cfgDevice *dev)
 
187
{
 
188
    int nscreens = 0;
 
189
    char screen_name[48];
 
190
    XF86ConfScreenPtr screen = XF86Config->conf_screen_lst;
 
191
    XF86ConfAdjacencyPtr adj;
 
192
 
 
193
    while (screen != NULL) {
 
194
        ++nscreens;
 
195
        screen = (XF86ConfScreenPtr)(screen->list.next);
 
196
    }
 
197
    do {
 
198
        XmuSnprintf(screen_name, sizeof(screen_name), "Screen%d",
 
199
                    nscreens);
 
200
        ++nscreens;
 
201
    } while (xf86findScreen(screen_name,
 
202
             XF86Config->conf_screen_lst) != NULL);
 
203
 
 
204
    screen = (XF86ConfScreenPtr)XtCalloc(1, sizeof(XF86ConfScreenRec));
 
205
    screen->scrn_identifier = XtNewString(screen_name);
 
206
    screen->scrn_device_str = XtNewString(((XF86ConfDevicePtr)(dev->config))->dev_identifier);
 
207
    screen->scrn_device = (XF86ConfDevicePtr)(dev->config);
 
208
    screen->scrn_monitor_str = XtNewString(((XF86ConfMonitorPtr)(mon->config))->mon_identifier);
 
209
    screen->scrn_monitor = (XF86ConfMonitorPtr)(mon->config);
 
210
    XF86Config->conf_screen_lst =
 
211
        xf86addScreen(XF86Config->conf_screen_lst, screen);
 
212
 
 
213
    adj = (XF86ConfAdjacencyPtr)XtCalloc(1, sizeof(XF86ConfAdjacencyRec));
 
214
    adj->adj_screen = screen;
 
215
    adj->adj_screen_str = XtNewString(screen_name);
 
216
    if (computer.layout == NULL)
 
217
        computer.layout = XF86Config->conf_layout_lst = (XF86ConfLayoutPtr)
 
218
            XtCalloc(1, sizeof(XF86ConfLayoutRec));
 
219
    computer.layout->lay_adjacency_lst = (XF86ConfAdjacencyPtr)
 
220
        xf86addListItem((GenericListPtr)computer.layout->lay_adjacency_lst,
 
221
                    (GenericListPtr)adj);
 
222
 
 
223
    computer.screens = (xf86cfgScreen**)
 
224
        XtRealloc((XtPointer)computer.screens, sizeof(xf86cfgScreen*) *
 
225
                  (computer.num_screens + 1));
 
226
    computer.screens[computer.num_screens] =
 
227
        (xf86cfgScreen*)XtCalloc(1, sizeof(xf86cfgScreen));
 
228
    computer.screens[computer.num_screens]->screen = screen;
 
229
    computer.screens[computer.num_screens]->card = dev;
 
230
    computer.screens[computer.num_screens]->monitor = mon;
 
231
 
 
232
    ++dev->refcount;
 
233
    ++mon->refcount;
 
234
 
 
235
    CreateScreenWidget(computer.screens[computer.num_screens]);
 
236
    computer.screens[computer.num_screens]->type = SCREEN;
 
237
    SetTip((xf86cfgDevice*)computer.screens[computer.num_screens]);
 
238
 
 
239
    ++computer.num_screens;
 
240
}
 
241
 
 
242
void
 
243
RemoveScreen(xf86cfgDevice *mon, xf86cfgDevice *dev)
 
244
{
 
245
    XF86ConfScreenPtr screen = XF86Config->conf_screen_lst;
 
246
    int i;
 
247
 
 
248
    mon->state = dev->state = UNUSED;
 
249
    while (screen != NULL) {
 
250
        if ((XtPointer)screen->scrn_monitor == mon->config &&
 
251
            (XtPointer)screen->scrn_device == dev->config)
 
252
            break;
 
253
 
 
254
        screen = (XF86ConfScreenPtr)(screen->list.next);
 
255
    }
 
256
    --mon->refcount;
 
257
    --dev->refcount;
 
258
 
 
259
    for (i = 0; i < computer.num_screens; i++) {
 
260
        if (computer.screens[i]->screen == screen) {
 
261
            XtDestroyWidget(computer.screens[i]->widget);
 
262
            if (i < --computer.num_screens)
 
263
                memmove(&computer.screens[i], &computer.screens[i + 1],
 
264
                        (computer.num_screens - i) * sizeof(xf86cfgScreen*));
 
265
            break;
 
266
        }
 
267
    }
 
268
 
 
269
    xf86removeScreen(XF86Config, screen);
 
270
}
 
271
 
 
272
void
 
273
ChangeScreen(XF86ConfMonitorPtr mon, XF86ConfMonitorPtr oldmon,
 
274
             XF86ConfDevicePtr dev, XF86ConfDevicePtr olddev)
 
275
{
 
276
    int ioldm, im, ioldc, ic;
 
277
 
 
278
    if (mon == oldmon && dev == olddev)
 
279
        return;
 
280
 
 
281
    if (mon != NULL) {
 
282
        for (im = 0; im < computer.num_devices; im++)
 
283
            if (computer.devices[im]->config == (XtPointer)mon)
 
284
                break;
 
285
    }
 
286
    else
 
287
        im = -1;
 
288
    if (oldmon != NULL) {
 
289
        for (ioldm = 0; ioldm < computer.num_devices; ioldm++)
 
290
            if (computer.devices[ioldm]->config == (XtPointer)oldmon)
 
291
                break;
 
292
    }
 
293
    else
 
294
        ioldm = -1;
 
295
 
 
296
    if (dev != NULL) {
 
297
        for (ic = 0; ic < computer.num_devices; ic++)
 
298
            if (computer.devices[ic]->config == (XtPointer)dev)
 
299
                break;
 
300
    }
 
301
    else
 
302
        ic = -1;
 
303
    if (olddev != NULL) {
 
304
        for (ioldc = 0; ioldc < computer.num_devices; ioldc++)
 
305
            if (computer.devices[ioldc]->config == (XtPointer)olddev)
 
306
                break;
 
307
    }
 
308
    else
 
309
        ioldc = -1;
 
310
 
 
311
    if (ioldm >= 0 && ioldc >= 0) {
 
312
        RemoveScreen(computer.devices[ioldm], computer.devices[ioldc]);
 
313
        computer.devices[ioldm]->state = UNUSED;
 
314
/*      computer.devices[ioldc]->state = UNUSED;*/
 
315
    }
 
316
 
 
317
    if (im >= 0 && ic >= 0) {
 
318
        AddScreen(computer.devices[im], computer.devices[ic]);
 
319
        computer.devices[im]->state = USED;
 
320
/*      computer.devices[ic]->state = USED;*/
 
321
    }
 
322
}
 
323
 
 
324
/*
 
325
 
 
326
+------------------------------------------------+
 
327
|                                                |
 
328
|  +------------------------------------------+  |
 
329
|  |                                          |  |
 
330
|  |                                          |  |
 
331
|  |                                          |  |
 
332
|  |                                          |  |
 
333
|  |                                          |  |
 
334
|  |                                          |  |
 
335
|  |                                          |  |
 
336
|  |                                          |  |
 
337
|  |                                          |  |
 
338
|  |                                          |  |
 
339
|  |                                          |  |
 
340
|  |                                          |  |
 
341
|  |                                          |  |
 
342
|  |                                          |  |
 
343
|  +------------------------------------------+  |
 
344
|                                                |
 
345
+------------------------------------------------+
 
346
            |                        |
 
347
    +-------+                        +-------+
 
348
    |                                        |
 
349
    +----------------------------------------+
 
350
 
 
351
 */
 
352
static double oxs = 0.0, oys = 0.0, oxe = 100.0, oye = 70.0;
 
353
static double ixs = 7.0, iys = 7.0, ixe = 93.0, iye = 63.0;
 
354
static double lin[] = { 25.0, 70.0, 25.0, 75.0,  5.0, 75.0,  5.0, 80.0,
 
355
                        95.0, 80.0, 95.0, 75.0, 75.0, 75.0, 75.0, 70.0 };
 
356
 
 
357
void
 
358
DrawScreen(Display *dpy, Drawable win, int xs, int ys, int xe, int ye,
 
359
           Bool active, int rotate)
 
360
{
 
361
    double xfact, yfact;
 
362
    XPoint points[(sizeof(lin) / sizeof(lin[0])) >> 1];
 
363
    int i;
 
364
    static GC gray0, gray1, gray2, black, red;
 
365
 
 
366
    if (black == NULL) {
 
367
        XColor color, exact;
 
368
        XGCValues values;
 
369
 
 
370
        XAllocNamedColor(XtDisplay(toplevel), toplevel->core.colormap, "gray95",
 
371
                         &color, &exact);
 
372
        values.foreground = color.pixel;
 
373
        gray0 = XCreateGC(XtDisplay(toplevel), win, GCForeground, &values);
 
374
        XAllocNamedColor(XtDisplay(toplevel), toplevel->core.colormap, "gray75",
 
375
                         &color, &exact);
 
376
        values.foreground = color.pixel;
 
377
        gray1 = XCreateGC(XtDisplay(toplevel), win, GCForeground, &values);
 
378
 
 
379
        XAllocNamedColor(XtDisplay(toplevel), toplevel->core.colormap, "gray60",
 
380
                         &color, &exact);
 
381
        values.foreground = color.pixel;
 
382
        gray2 = XCreateGC(XtDisplay(toplevel), win, GCForeground, &values);
 
383
 
 
384
        XAllocNamedColor(XtDisplay(toplevel), toplevel->core.colormap, "gray20",
 
385
                         &color, &exact);
 
386
        values.foreground = color.pixel;
 
387
        black = XCreateGC(XtDisplay(toplevel), win, GCForeground, &values);
 
388
 
 
389
        XAllocNamedColor(XtDisplay(toplevel), toplevel->core.colormap, "red",
 
390
                         &color, &exact);
 
391
        values.foreground = color.pixel;
 
392
        values.line_width = 4;
 
393
        values.cap_style = CapButt;
 
394
        red = XCreateGC(XtDisplay(toplevel), win,
 
395
                        GCForeground | GCLineWidth | GCCapStyle, &values);
 
396
    }
 
397
 
 
398
    if (rotate) {
 
399
        xfact = (xe - xs) / 80.0;
 
400
        yfact = (ye - ys) / 100.0;
 
401
        if (rotate == CW) {
 
402
            /* outer rectangle */
 
403
            XFillRectangle(dpy, win, gray1,
 
404
                           oxs * xfact + xs + .5,
 
405
                           oys * yfact + ys + .5,
 
406
                           (oye - oys) * xfact + .5,
 
407
                           (oxe - oxs) * yfact + .5);
 
408
            XDrawLine(dpy, win, gray2,
 
409
                      xs, ye - 1,
 
410
                      70 * xfact + xs - 1 + .5, ye - 1);
 
411
            XDrawLine(dpy, win, gray2,
 
412
                      70 * xfact + xs - 1 + .5, ye - 1,
 
413
                      70 * xfact + xs - 1 + .5, ys);
 
414
            /* inner rectangle */
 
415
            XFillRectangle(dpy, win, black,
 
416
                           ixs * xfact + xs + .5,
 
417
                           iys * yfact + ys + .5,
 
418
                           (iye - iys) * xfact + .5,
 
419
                           (ixe - ixs) * yfact + .5);
 
420
            for (i = 0; i < sizeof(points) / sizeof(points[0]); i++) {
 
421
                points[i].x = lin[(i<<1) + 1] * xfact + xs + .5;
 
422
                points[i].y = lin[(i<<1)] * yfact + ys + .5;
 
423
            }
 
424
            XFillPolygon(dpy, win, gray2, points, i, Convex, CoordModeOrigin);
 
425
            XDrawLine(dpy, win, gray0,
 
426
                      (oxe - 10) * xfact + xs + .5, oys * yfact + ys + .5,
 
427
                      xs, oys * yfact + ys + .5);
 
428
            XDrawLine(dpy, win, gray0,
 
429
                      xs, ys,
 
430
                      xs, xe);
 
431
            XDrawLine(dpy, win, black,
 
432
                      lin[7] * xfact + xs - 1 + .5, lin[6] * yfact + ys + .5,
 
433
                      lin[9] * xfact + xs - 1 + .5, lin[8] * yfact + ys - 1 + .5);
 
434
            XDrawLine(dpy, win, black,
 
435
                      lin[9] * xfact + xs - 1 + .5, lin[8] * yfact + ys - 1 + .5,
 
436
                      lin[11] * xfact + xs + .5, lin[10] * yfact + ys - 1 + .5);
 
437
            XDrawLine(dpy, win, black,
 
438
                      lin[13] * xfact + xs + .5, lin[12] * yfact + ys - 1 + .5,
 
439
                      lin[15] * xfact + xs + .5, lin[14] * yfact + ys - 1 + .5);
 
440
 
 
441
            if (!active) {
 
442
                XDrawLine(dpy, win, red,
 
443
                          iys * xfact, ixs * yfact, iye * xfact, ixe * yfact);
 
444
                XDrawLine(dpy, win, red,
 
445
                          iye * xfact, ixs * yfact, iys * xfact, ixe * yfact);
 
446
            }
 
447
        }
 
448
        else if (rotate == CCW) {
 
449
            /* outer rectangle */
 
450
            XFillRectangle(dpy, win, gray1,
 
451
                           10 * xfact + xs + .5,
 
452
                           oys * yfact + ys + .5,
 
453
                           (oye - oys) * xfact + .5,
 
454
                           (oxe - oxs) * yfact + .5);
 
455
 
 
456
            XDrawLine(dpy, win, gray2,
 
457
                      10 * xfact + xs + .5, ye - 1,
 
458
                      oxe * xfact + xs - 1 + .5, ye - 1);
 
459
            XDrawLine(dpy, win, gray2,
 
460
                      xe - 1, ye - 1,
 
461
                      xe - 1, ys);
 
462
            /* inner rectangle */
 
463
            XFillRectangle(dpy, win, black,
 
464
                           (ixs + 10) * xfact + xs + .5,
 
465
                           iys * yfact + ys + .5,
 
466
                           (iye - iys) * xfact + .5,
 
467
                           (ixe - ixs) * yfact + .5);
 
468
            for (i = 0; i < sizeof(points) / sizeof(points[0]); i++) {
 
469
                points[i].x = (-lin[(i<<1) + 1] + 80.0) * xfact + xs + .5;
 
470
                points[i].y = lin[(i<<1)] * yfact + ys + .5;
 
471
            }
 
472
            XFillPolygon(dpy, win, gray2, points, i, Convex, CoordModeOrigin);
 
473
            XDrawLine(dpy, win, gray0,
 
474
                      oxe * xfact + xs + .5, oys * yfact + ys + .5,
 
475
                      (oxs - 10) * xfact + xs + .5, oys * yfact + ys + .5);
 
476
            XDrawLine(dpy, win, gray0,
 
477
                      (oxs + 10) * xfact + xs + .5, ys,
 
478
                      (oxs + 10) * xfact + xs + .5, xe);
 
479
 
 
480
            XDrawLine(dpy, win, black,
 
481
                      xs, lin[8] * yfact - 1 + ys + .5,
 
482
                      4 * xfact + xs + .5, lin[8] * yfact - 1 + ys + .5);
 
483
            XDrawLine(dpy, win, black,
 
484
                      4 * xfact + xs, lin[8] * yfact - 1 + ys + .5,
 
485
                      4 * xfact + xs, lin[3] * yfact - 1 + ys + .5);
 
486
            XDrawLine(dpy, win, black,
 
487
                      4 * xfact + xs + .5, lin[3] * yfact - 1 + ys + .5,
 
488
                      10 * xfact + xs + .5 - 1, lin[3] * yfact - 1 + ys + .5);
 
489
            XDrawLine(dpy, win, black,
 
490
                      4 * xfact + xs, lin[0] * yfact - 1 + ys + .5,
 
491
                      4 * xfact + xs, lin[4] * yfact - 1 + ys + .5);
 
492
 
 
493
            if (!active) {
 
494
                XDrawLine(dpy, win, red,
 
495
                          (iys + 10) * xfact, ixs * yfact,
 
496
                          (iye + 10) * xfact, ixe * yfact);
 
497
                XDrawLine(dpy, win, red,
 
498
                          (iye + 10) * xfact, ixs * yfact,
 
499
                          (iys + 10) * xfact, ixe * yfact);
 
500
            }
 
501
        }
 
502
    }
 
503
    else {
 
504
        xfact = (xe - xs) / 100.0;
 
505
        yfact = (ye - ys) / 80.0;
 
506
 
 
507
        /* outer rectangle */
 
508
        XFillRectangle(dpy, win, gray1,
 
509
                       oxs * xfact + xs + .5,
 
510
                       oys * yfact + ys + .5,
 
511
                       (oxe - oxs) * xfact + .5,
 
512
                       (oye - oys) * yfact + .5);
 
513
 
 
514
        XDrawLine(dpy, win, gray2,
 
515
                  oxs * xfact + xs + .5, oye * yfact + ys - 1 + .5,
 
516
                  oxe * xfact + xs - 1 + .5, oye * yfact + ys - 1 + .5);
 
517
        XDrawLine(dpy, win, gray2,
 
518
                  oxe * xfact + xs - 1 + .5, oys * yfact + ys + .5,
 
519
                  oxe * xfact + xs - 1 + .5, oye * yfact + ys - 1 + .5);
 
520
 
 
521
        /* inner rectangle */
 
522
        XFillRectangle(dpy, win, black,
 
523
                       ixs * xfact + xs + .5,
 
524
                       iys * yfact + ys + .5,
 
525
                       (ixe - ixs) * xfact + .5,
 
526
                       (iye - iys) * yfact + .5);
 
527
 
 
528
        for (i = 0; i < sizeof(points) / sizeof(points[0]); i++) {
 
529
            points[i].x = lin[i<<1] * xfact + xs + .5;
 
530
            points[i].y = lin[(i<<1) + 1] * yfact + ys + .5;
 
531
        }
 
532
 
 
533
        XFillPolygon(dpy, win, gray2, points, i, Convex, CoordModeOrigin);
 
534
 
 
535
        XDrawLine(dpy, win, black,
 
536
                  lin[6] * xfact + xs + .5, lin[7] * yfact + ys - 1 + .5,
 
537
                  lin[8] * xfact + xs - 1 + .5, lin[9] * yfact + ys - 1 + .5);
 
538
        XDrawLine(dpy, win, black,
 
539
                  lin[8] * xfact + xs - 1 + .5, lin[9] * yfact + ys - 1 + .5,
 
540
                  lin[10] * xfact + xs - 1 + .5, lin[11] * yfact + ys + .5);
 
541
        XDrawLine(dpy, win, black,
 
542
                  lin[12] * xfact + xs - 1 + .5, lin[13] * yfact + ys + .5,
 
543
                  lin[14] * xfact + xs - 1 + .5, lin[15] * yfact + ys + .5);
 
544
 
 
545
        XDrawLine(dpy, win, gray0,
 
546
                  oxe * xfact + xs + .5, oys * yfact + ys + .5,
 
547
                  oxs * xfact + xs + .5, oys * yfact + ys + .5);
 
548
        XDrawLine(dpy, win, gray0,
 
549
                  oxs * xfact + xs + .5, oys * yfact + ys + .5,
 
550
                  oxs * xfact + xs + .5, lin[1] * yfact + ys + .5);
 
551
 
 
552
        if (!active) {
 
553
            XDrawLine(dpy, win, red,
 
554
                      ixs * xfact, iys * yfact, ixe * xfact, iye * yfact);
 
555
            XDrawLine(dpy, win, red,
 
556
                      ixe * xfact, iys * yfact, ixs * xfact, iye * yfact);
 
557
        }
 
558
    }
 
559
}
 
560
 
 
561
void
 
562
DrawScreenMask(Display *dpy, Drawable win, GC gc, int xs, int ys, int xe, int ye,
 
563
               int rotate)
 
564
{
 
565
    double xfact, yfact;
 
566
    XPoint points[(sizeof(lin) / sizeof(lin[0])) >> 1];
 
567
    int i = 0, x = 0, y = 0, width, height;
 
568
 
 
569
    if (rotate) {
 
570
        xfact = (xe - xs) / 80.0;
 
571
        yfact = (ye - ys) / 100.0;
 
572
        width = (oye - oys) * xfact + .5;
 
573
        height = (oxe - oxs) * yfact + .5;
 
574
        if (rotate == CW) {
 
575
            x = oxs * xfact + xs + .5;
 
576
            y = oys * yfact + ys + .5;
 
577
            for (i = 0; i < sizeof(points) / sizeof(points[0]); i++) {
 
578
                points[i].x = lin[(i<<1) + 1] * xfact + xs + .5;
 
579
                points[i].y = lin[(i<<1)] * yfact + ys + .5;
 
580
            }
 
581
        }
 
582
        else if (rotate == CCW) {
 
583
            x = 10 * xfact + xs + .5;
 
584
            y = oys * yfact + ys + .5;
 
585
            for (i = 0; i < sizeof(points) / sizeof(points[0]); i++) {
 
586
                points[i].x = (-lin[(i<<1) + 1] + 80.0) * xfact + xs + .5;
 
587
                points[i].y = lin[(i<<1)] * yfact + ys + .5;
 
588
            }
 
589
        }
 
590
    }
 
591
    else {
 
592
        xfact = (xe - xs) / 100.0;
 
593
        yfact = (ye - ys) / 80.0;
 
594
        x = oxs * xfact + xs + .5;
 
595
        y = oys * yfact + ys + .5;
 
596
        width = (oxe - oxs) * xfact + .5;
 
597
        height = (oye - oys) * yfact + .5;
 
598
        for (i = 0; i < sizeof(points) / sizeof(points[0]); i++) {
 
599
            points[i].x = lin[(i<<1)] * xfact + xs + .5;
 
600
            points[i].y = lin[(i<<1) + 1] * yfact + ys + .5;
 
601
        }
 
602
    }
 
603
 
 
604
    /* rectangle */
 
605
    XFillRectangle(dpy, win, gc, x, y, width, height);
 
606
 
 
607
 
 
608
    XFillPolygon(dpy, win, gc, points, i, Convex, CoordModeOrigin);
 
609
}
 
610
 
 
611
void
 
612
AdjustScreenUI(void)
 
613
{
 
614
    XF86ConfLayoutPtr lay = computer.layout;
 
615
    XF86ConfAdjacencyPtr adj;
 
616
    int i, dx, dy, x, y, w, h, base = -1;
 
617
    double xf, yf;
 
618
 
 
619
    if (lay == NULL)
 
620
        return;
 
621
 
 
622
    adj = lay->lay_adjacency_lst;
 
623
 
 
624
#define USED1   -USED
 
625
 
 
626
    XtFree((XtPointer)mon_widths);
 
627
    XtFree((XtPointer)mon_heights);
 
628
    mon_widths = (int*)XtCalloc(1, sizeof(int) * columns);
 
629
    mon_heights = (int*)XtCalloc(1, sizeof(int) * rows);
 
630
 
 
631
    mon_width = mon_height = 0;
 
632
    for (i = 0; i < computer.num_screens; i++) {
 
633
        if (base == -1 && computer.screens[i]->state == USED)
 
634
            base = i;
 
635
        if (computer.screens[i]->screen->scrn_monitor->mon_width > mon_width)
 
636
            mon_width = computer.screens[i]->screen->scrn_monitor->mon_width;
 
637
        if (computer.screens[i]->screen->scrn_monitor->mon_height > mon_height)
 
638
            mon_height = computer.screens[i]->screen->scrn_monitor->mon_height;
 
639
    }
 
640
    if (base < 0) {
 
641
        for (i = 0; i < computer.num_screens; i++)
 
642
            ReshapeScreenWidget(computer.screens[i]);
 
643
        return;
 
644
    }
 
645
 
 
646
    if (mon_width == 0) {
 
647
        mon_width = 10;
 
648
        mon_height = 8;
 
649
    }
 
650
 
 
651
    XtUnmapWidget(work);
 
652
 
 
653
    while (adj) {
 
654
        xf86cfgScreen *scr = NULL,
 
655
            *topscr = NULL, *botscr = NULL, *lefscr = NULL, *rigscr = NULL;
 
656
 
 
657
        for (i = 0; i < computer.num_screens; i++)
 
658
            if (computer.screens[i]->screen == adj->adj_screen)
 
659
                break;
 
660
        if (i < computer.num_screens)
 
661
            scr = computer.screens[i];
 
662
 
 
663
        if (adj->adj_top != NULL) {
 
664
            for (i = 0; i < computer.num_screens; i++)
 
665
                if (computer.screens[i]->screen == adj->adj_top)
 
666
                    break;
 
667
            if (i < computer.num_screens)
 
668
                topscr = computer.screens[i];
 
669
        }
 
670
 
 
671
        if (adj->adj_bottom != NULL) {
 
672
            for (i = 0; i < computer.num_screens; i++)
 
673
                if (computer.screens[i]->screen == adj->adj_bottom)
 
674
                    break;
 
675
            if (i < computer.num_screens)
 
676
                botscr = computer.screens[i];
 
677
        }
 
678
 
 
679
        if (adj->adj_left != NULL) {
 
680
            for (i = 0; i < computer.num_screens; i++)
 
681
                if (computer.screens[i]->screen == adj->adj_left)
 
682
                    break;
 
683
            if (i < computer.num_screens)
 
684
                lefscr = computer.screens[i];
 
685
        }
 
686
 
 
687
        if (adj->adj_right != NULL) {
 
688
            for (i = 0; i < computer.num_screens; i++)
 
689
                if (computer.screens[i]->screen == adj->adj_right)
 
690
                    break;
 
691
            if (i < computer.num_screens)
 
692
                rigscr = computer.screens[i];
 
693
        }
 
694
 
 
695
        if (lefscr == NULL && rigscr == NULL && topscr == NULL && lefscr == NULL) {
 
696
            XF86ConfScreenPtr s;
 
697
 
 
698
            if (adj->adj_where >= CONF_ADJ_RIGHTOF < adj->adj_where <= CONF_ADJ_BELOW) {
 
699
                s = xf86findScreen(adj->adj_refscreen, XF86Config->conf_screen_lst);
 
700
                for (i = 0; i < computer.num_screens; i++)
 
701
                    if (computer.screens[i]->screen == s)
 
702
                        break;
 
703
                if (i < computer.num_screens) {
 
704
                    switch (adj->adj_where) {
 
705
                        case CONF_ADJ_RIGHTOF:
 
706
                            lefscr = computer.screens[i];
 
707
                            break;
 
708
                        case CONF_ADJ_LEFTOF:
 
709
                            rigscr = computer.screens[i];
 
710
                            break;
 
711
                        case CONF_ADJ_ABOVE:
 
712
                            botscr = computer.screens[i];
 
713
                            break;
 
714
                        case CONF_ADJ_BELOW:
 
715
                            topscr = computer.screens[i];
 
716
                            break;
 
717
                    }
 
718
                }
 
719
            }
 
720
        }
 
721
 
 
722
        XtMoveWidget(scr->widget, 0, 0);
 
723
        scr->state = USED1;
 
724
        if (lefscr != NULL) {
 
725
            if (lefscr->state == USED1)
 
726
                XtMoveWidget(scr->widget,
 
727
                             lefscr->widget->core.x + lefscr->widget->core.width,
 
728
                             lefscr->widget->core.y);
 
729
            else
 
730
                XtMoveWidget(lefscr->widget,
 
731
                             -(int)(lefscr->widget->core.width),
 
732
                             scr->widget->core.y);
 
733
        }
 
734
 
 
735
        if (rigscr != NULL) {
 
736
            if (rigscr->state == USED1) {
 
737
                dx = rigscr->widget->core.x - scr->widget->core.width - scr->widget->core.x;
 
738
                dy = rigscr->widget->core.y - scr->widget->core.y;
 
739
 
 
740
                XtMoveWidget(scr->widget, scr->widget->core.x + dx,
 
741
                             scr->widget->core.y + dy);
 
742
                if (lefscr != NULL && lefscr->state != USED1)
 
743
                    XtMoveWidget(lefscr->widget, lefscr->widget->core.x + dx,
 
744
                                 lefscr->widget->core.y + dy);
 
745
            }
 
746
            else
 
747
                XtMoveWidget(rigscr->widget, scr->widget->core.width,
 
748
                             scr->widget->core.y);
 
749
        }
 
750
 
 
751
        if (topscr != NULL) {
 
752
            if (topscr->state == USED1) {
 
753
                dx = topscr->widget->core.x - scr->widget->core.x;
 
754
                dy = topscr->widget->core.y + topscr->widget->core.height -
 
755
                     scr->widget->core.y;
 
756
 
 
757
                XtMoveWidget(scr->widget, scr->widget->core.x + dx,
 
758
                             scr->widget->core.y + dy);
 
759
                if (lefscr != NULL && lefscr->state != USED1)
 
760
                    XtMoveWidget(lefscr->widget, lefscr->widget->core.x + dx,
 
761
                                 lefscr->widget->core.y + dy);
 
762
                if (rigscr != NULL && rigscr->state != USED1)
 
763
                    XtMoveWidget(rigscr->widget, rigscr->widget->core.x + dx,
 
764
                                 rigscr->widget->core.y + dy);
 
765
            }
 
766
            else
 
767
                XtMoveWidget(topscr->widget, scr->widget->core.x,
 
768
                             scr->widget->core.y - topscr->widget->core.height);
 
769
        }
 
770
 
 
771
        if (botscr != NULL) {
 
772
            if (botscr->state == USED1) {
 
773
                dx = botscr->widget->core.x - scr->widget->core.x;
 
774
                dy = botscr->widget->core.y - scr->widget->core.height - scr->widget->core.y;
 
775
 
 
776
                XtMoveWidget(scr->widget, scr->widget->core.x + dx,
 
777
                             scr->widget->core.y + dy);
 
778
                if (lefscr != NULL && lefscr->state != USED1)
 
779
                    XtMoveWidget(lefscr->widget, lefscr->widget->core.x + dx,
 
780
                                 lefscr->widget->core.y + dy);
 
781
                if (rigscr != NULL && rigscr->state != USED1)
 
782
                    XtMoveWidget(rigscr->widget, rigscr->widget->core.x + dx,
 
783
                                 rigscr->widget->core.y + dy);
 
784
                if (botscr != NULL && botscr->state != USED1)
 
785
                    XtMoveWidget(botscr->widget, botscr->widget->core.x + dx,
 
786
                                 botscr->widget->core.y + dy);
 
787
            }
 
788
            else
 
789
                XtMoveWidget(botscr->widget, scr->widget->core.x,
 
790
                             scr->widget->core.y + scr->widget->core.height);
 
791
        }
 
792
 
 
793
        adj = (XF86ConfAdjacencyPtr)(adj->list.next);
 
794
    }
 
795
 
 
796
    for (i = 0; i < computer.num_screens; i++)
 
797
        if (computer.screens[i]->state == USED1)
 
798
            computer.screens[i]->state = USED;
 
799
        else
 
800
            XLowerWindow(XtDisplay(computer.screens[i]->widget),
 
801
                         XtWindow(computer.screens[i]->widget));
 
802
 
 
803
    w = work->core.width / (columns + 1) - 5;
 
804
    h = work->core.height / (rows + 1) - 5;
 
805
 
 
806
    if (w > h)
 
807
        w = h;
 
808
    else
 
809
        h = w;
 
810
 
 
811
    dx = (work->core.width - (columns * w)) >> 1;
 
812
    dy = (work->core.height - (rows * h)) >> 1;
 
813
 
 
814
    xf = (double)w / (double)computer.screens[0]->widget->core.width;
 
815
    yf = (double)h / (double)computer.screens[0]->widget->core.height;
 
816
 
 
817
    for (i = 0; i < computer.num_screens; i++) {
 
818
        Widget z = computer.screens[i]->widget;
 
819
 
 
820
        if (computer.screens[i]->state == USED)
 
821
            XtConfigureWidget(z, z->core.x * xf + dx,
 
822
                              z->core.y * yf + dy, w, h, 0);
 
823
        else
 
824
            XtConfigureWidget(z, z->core.x, z->core.y, w, h, 0);
 
825
    }
 
826
 
 
827
    if (computer.screens[base]->row >= 0) {
 
828
        double xf, yf;
 
829
        int width, height;
 
830
 
 
831
        for (i = 0; i < computer.num_screens; i++) {
 
832
            width = computer.screens[i]->screen->scrn_monitor->mon_width;
 
833
            height = computer.screens[i]->screen->scrn_monitor->mon_height;
 
834
            if (width <= 0) {
 
835
                width = mon_width;
 
836
                height = mon_height;
 
837
            }
 
838
 
 
839
            if (computer.screens[i]->rotate) {
 
840
                xf = (double)width / (double)mon_width * 8. / 10.;
 
841
                yf = (double)height / (double)mon_height;
 
842
            }
 
843
            else {
 
844
                xf = (double)width / (double)mon_width;
 
845
                yf = (double)height / (double)mon_height * 8. / 10.;
 
846
            }
 
847
            width = computer.screens[i]->widget->core.width * xf;
 
848
            height = computer.screens[i]->widget->core.height * yf;
 
849
            if (computer.screens[i]->state == USED) {
 
850
                if (mon_widths[computer.screens[i]->column] < width)
 
851
                    mon_widths[computer.screens[i]->column] = width;
 
852
                if (mon_heights[computer.screens[i]->row] < height)
 
853
                    mon_heights[computer.screens[i]->row] = height;
 
854
            }
 
855
 
 
856
            /* do it here to avoid recalculation */
 
857
            computer.screens[i]->rect.width = width;
 
858
            computer.screens[i]->rect.height = height;
 
859
        }
 
860
    }
 
861
 
 
862
    for (i = 0; i < computer.num_screens; i++)
 
863
        ReshapeScreenWidget(computer.screens[i]);
 
864
 
 
865
    /* do a new pass, to avoid gaps if the monitors have different
 
866
     * sizes.
 
867
     */
 
868
    if (computer.screens[base]->row >= 0) {
 
869
        x = computer.screens[base]->widget->core.x;
 
870
        y = computer.screens[base]->widget->core.y;
 
871
 
 
872
        /* screens representations are already ordered */
 
873
        for (i = base; i < computer.num_screens; i++) {
 
874
            if (computer.screens[i]->state == UNUSED)
 
875
                continue;
 
876
            if (computer.screens[i]->column != 0)
 
877
                x += mon_widths[computer.screens[i]->column];
 
878
            else {
 
879
                x = computer.screens[base]->widget->core.x;
 
880
                if (i != base)
 
881
                    y += mon_heights[computer.screens[i]->row];
 
882
            }
 
883
            XtMoveWidget(computer.screens[i]->widget, x, y);
 
884
        }
 
885
    }
 
886
    XtMapWidget(work);
 
887
}
 
888
 
 
889
static int
 
890
qcmp_screen(_Xconst void *a, _Xconst void *b)
 
891
{
 
892
    xf86cfgScreen *s1, *s2;
 
893
 
 
894
    s1 = *(xf86cfgScreen**)a;
 
895
    s2 = *(xf86cfgScreen**)b;
 
896
 
 
897
    if (s1->widget->core.x > s2->widget->core.x) {
 
898
        if (s2->widget->core.y >=
 
899
            s1->widget->core.y + (s1->widget->core.height >> 1))
 
900
            return (-1);
 
901
        return (1);
 
902
    }
 
903
    else {
 
904
        if (s1->widget->core.y >=
 
905
            s2->widget->core.y + (s2->widget->core.height >> 1))
 
906
            return (1);
 
907
        return (-1);
 
908
    }
 
909
    /*NOTREACHED*/
 
910
}
 
911
 
 
912
void
 
913
UpdateScreenUI(void)
 
914
{
 
915
    XF86ConfLayoutPtr lay = computer.layout;
 
916
    XF86ConfAdjacencyPtr adj, prev, left, base;
 
917
    int i, p, cols, scrno;
 
918
 
 
919
    if (lay == NULL)
 
920
        return;
 
921
 
 
922
    rows = columns = cols = 1;
 
923
 
 
924
    qsort(computer.screens, computer.num_screens, sizeof(xf86cfgScreen*),
 
925
          qcmp_screen);
 
926
 
 
927
    adj = prev = left = base = NULL;
 
928
    for (i = p = scrno = 0; i < computer.num_screens; i++) {
 
929
        XF86ConfScreenPtr scr = computer.screens[i]->screen;
 
930
 
 
931
        if (computer.screens[i]->state == UNUSED)
 
932
            continue;
 
933
 
 
934
        adj = (XF86ConfAdjacencyPtr)XtCalloc(1, sizeof(XF86ConfAdjacencyRec));
 
935
        adj->adj_scrnum = scrno++;
 
936
        adj->adj_screen = scr;
 
937
        adj->adj_screen_str = XtNewString(scr->scrn_identifier);
 
938
        if (base == NULL) {
 
939
            base = left = adj;
 
940
            computer.screens[i]->row = computer.screens[i]->column = 0;
 
941
        }
 
942
        else {
 
943
            int dy = computer.screens[i]->widget->core.y -
 
944
                     computer.screens[p]->widget->core.y;
 
945
 
 
946
            prev->list.next = adj;
 
947
            if (dy > (computer.screens[i]->widget->core.height >> 1)) {
 
948
                adj->adj_where = CONF_ADJ_BELOW;
 
949
                adj->adj_refscreen = XtNewString(left->adj_screen_str);
 
950
                left = adj;
 
951
                computer.screens[i]->row = rows;
 
952
                computer.screens[i]->column = 0;
 
953
                cols = 1;
 
954
                ++rows;
 
955
            }
 
956
            else {
 
957
                computer.screens[i]->row = rows - 1;
 
958
                computer.screens[i]->column = cols;
 
959
                adj->adj_where = CONF_ADJ_RIGHTOF;
 
960
                if (++cols > columns)
 
961
                    columns = cols;
 
962
                adj->adj_refscreen = XtNewString(prev->adj_screen_str);
 
963
            }
 
964
        }
 
965
        prev = adj;
 
966
        p = i;
 
967
    }
 
968
 
 
969
    adj = lay->lay_adjacency_lst;
 
970
 
 
971
    while (adj != NULL) {
 
972
        prev = adj;
 
973
        adj = (XF86ConfAdjacencyPtr)(adj->list.next);
 
974
        XtFree(prev->adj_screen_str);
 
975
        XtFree(prev->adj_right_str);
 
976
        XtFree(prev->adj_left_str);
 
977
        XtFree(prev->adj_top_str);
 
978
        XtFree(prev->adj_bottom_str);
 
979
        XtFree(prev->adj_refscreen);
 
980
        XtFree((char*)prev);
 
981
    }
 
982
 
 
983
    lay->lay_adjacency_lst = base;
 
984
}