~ubuntu-branches/ubuntu/vivid/blackbox/vivid

« back to all changes in this revision

Viewing changes to src/BaseDisplay.cc

  • Committer: Bazaar Package Importer
  • Author(s): Jesus Climent
  • Date: 2003-10-15 15:38:53 UTC
  • Revision ID: james.westby@ubuntu.com-20031015153853-c08p60n6fes52hs1
Tags: 0.65.0-1.2
* Non Maintainer Upload
* Patch by Matt Kraai to solve FTBFS: Closes: #208814.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// -*- mode: C++; indent-tabs-mode: nil; -*-
1
2
// BaseDisplay.cc for Blackbox - an X11 Window manager
2
 
// Copyright (c) 2001 Sean 'Shaleh' Perry <shaleh@debian.org>
 
3
// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh@debian.org>
3
4
// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
4
5
//
5
6
// Permission is hereby granted, free of charge, to any person obtaining a
20
21
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
22
// DEALINGS IN THE SOFTWARE.
22
23
 
23
 
// stupid macros needed to access some functions in version 2 of the GNU C
24
 
// library
25
 
#ifndef   _GNU_SOURCE
26
 
#define   _GNU_SOURCE
27
 
#endif // _GNU_SOURCE
28
 
 
29
24
#ifdef    HAVE_CONFIG_H
30
25
#  include "../config.h"
31
26
#endif // HAVE_CONFIG_H
32
27
 
 
28
extern "C" {
33
29
#include <X11/Xlib.h>
34
30
#include <X11/Xatom.h>
35
31
#include <X11/Xutil.h>
36
 
#include <X11/cursorfont.h>
37
32
#include <X11/keysym.h>
38
33
 
39
34
#ifdef    SHAPE
48
43
#  include <stdio.h>
49
44
#endif // HAVE_STDIO_H
50
45
 
51
 
#ifdef    STDC_HEADERS
 
46
#ifdef HAVE_STDLIB_H
52
47
#  include <stdlib.h>
 
48
#endif // HAVE_STDLIB_H
 
49
 
 
50
#ifdef HAVE_STRING_H
53
51
#  include <string.h>
54
 
#endif // STDC_HEADERS
 
52
#endif // HAVE_STRING_H
55
53
 
56
54
#ifdef    HAVE_UNISTD_H
57
55
#  include <sys/types.h>
78
76
#  include <sys/types.h>
79
77
#  include <sys/wait.h>
80
78
#endif // HAVE_SYS_WAIT_H
 
79
}
81
80
 
82
 
#if defined(HAVE_PROCESS_H) && defined(__EMX__)
83
 
#  include <process.h>
84
 
#endif //   HAVE_PROCESS_H             __EMX__
 
81
#include <string>
 
82
using std::string;
85
83
 
86
84
#include "i18n.hh"
87
85
#include "BaseDisplay.hh"
88
 
#include "LinkedList.hh"
 
86
#include "GCCache.hh"
89
87
#include "Timer.hh"
 
88
#include "Util.hh"
 
89
 
90
90
 
91
91
// X error handler to handle any and all X errors while the application is
92
92
// running
93
 
static Bool internal_error = False;
94
 
static Window last_bad_window = None;
 
93
static bool internal_error = False;
95
94
 
96
95
BaseDisplay *base_display;
97
96
 
100
99
  char errtxt[128];
101
100
 
102
101
  XGetErrorText(d, e->error_code, errtxt, 128);
103
 
  fprintf(stderr, i18n->getMessage(BaseDisplaySet, BaseDisplayXError,
104
 
                     "%s:  X error: %s(%d) opcodes %d/%d\n  resource 0x%lx\n"),
 
102
  fprintf(stderr,
 
103
          i18n(BaseDisplaySet, BaseDisplayXError,
 
104
               "%s:  X error: %s(%d) opcodes %d/%d\n  resource 0x%lx\n"),
105
105
          base_display->getApplicationName(), errtxt, e->error_code,
106
106
          e->request_code, e->minor_code, e->resourceid);
 
107
#else
 
108
  // shutup gcc
 
109
  (void) d;
 
110
  (void) e;
107
111
#endif // DEBUG
108
112
 
109
 
  if (e->error_code == BadWindow) last_bad_window = e->resourceid;
110
113
  if (internal_error) abort();
111
114
 
112
115
  return(False);
146
149
      return;
147
150
    }
148
151
 
149
 
    fprintf(stderr, i18n->getMessage(BaseDisplaySet, BaseDisplaySignalCaught,
150
 
                                     "%s:  signal %d caught\n"),
151
 
            base_display->getApplicationName(), sig);
 
152
    fprintf(stderr, i18n(BaseDisplaySet, BaseDisplaySignalCaught,
 
153
                         "%s:  signal %d caught\n"),
 
154
            base_display->getApplicationName(), sig);
152
155
 
153
156
    if (! base_display->isStartup() && ! re_enter) {
154
157
      internal_error = True;
155
158
 
156
159
      re_enter = 1;
157
 
      fprintf(stderr, i18n->getMessage(BaseDisplaySet, BaseDisplayShuttingDown,
158
 
                                       "shutting down\n"));
 
160
      fprintf(stderr, i18n(BaseDisplaySet, BaseDisplayShuttingDown,
 
161
                           "shutting down\n"));
159
162
      base_display->shutdown();
160
163
    }
161
164
 
162
165
    if (sig != SIGTERM && sig != SIGINT) {
163
 
      fprintf(stderr, i18n->getMessage(BaseDisplaySet, BaseDisplayAborting,
164
 
                                       "aborting... dumping core\n"));
 
166
      fprintf(stderr, i18n(BaseDisplaySet, BaseDisplayAborting,
 
167
                           "aborting... dumping core\n"));
165
168
      abort();
166
169
    }
167
170
 
172
175
}
173
176
 
174
177
 
175
 
// convenience functions
176
 
#ifndef    __EMX__
177
 
void bexec(const char *command, char* displaystring) {
178
 
  if (! fork()) {
179
 
    setsid();
180
 
    putenv(displaystring);
181
 
    execl("/bin/sh", "/bin/sh", "-c", command, NULL);
182
 
    exit(0);
183
 
  }
184
 
}
185
 
#endif // !__EMX__
186
 
 
187
 
char *bstrdup(const char *s) {
188
 
  const int l = strlen(s) + 1;
189
 
  char *n = new char[l];
190
 
  strncpy(n, s, l);
191
 
  return n;
192
 
}
193
 
 
194
 
BaseDisplay::BaseDisplay(char *app_name, char *dpy_name) {
 
178
BaseDisplay::BaseDisplay(const char *app_name, const char *dpy_name) {
195
179
  application_name = app_name;
196
180
 
197
 
  _startup = True;
198
 
  _shutdown = False;
199
 
  server_grabs = 0;
200
 
  last_bad_window = None;
 
181
  run_state = STARTUP;
201
182
 
202
183
  ::base_display = this;
203
184
 
230
211
#endif // HAVE_SIGACTION
231
212
 
232
213
  if (! (display = XOpenDisplay(dpy_name))) {
233
 
    fprintf(stderr, i18n->getMessage(BaseDisplaySet, BaseDisplayXConnectFail,
234
 
               "BaseDisplay::BaseDisplay: connection to X server failed.\n"));
 
214
    fprintf(stderr,
 
215
            i18n(BaseDisplaySet, BaseDisplayXConnectFail,
 
216
               "BaseDisplay::BaseDisplay: connection to X server failed.\n"));
235
217
    ::exit(2);
236
218
  } else if (fcntl(ConnectionNumber(display), F_SETFD, 1) == -1) {
237
219
    fprintf(stderr,
238
 
            i18n->getMessage(BaseDisplaySet, BaseDisplayCloseOnExecFail,
239
 
               "BaseDisplay::BaseDisplay: couldn't mark display connection "
240
 
               "as close-on-exec\n"));
 
220
            i18n(BaseDisplaySet, BaseDisplayCloseOnExecFail,
 
221
                 "BaseDisplay::BaseDisplay: couldn't mark display connection "
 
222
                 "as close-on-exec\n"));
241
223
    ::exit(2);
242
224
  }
243
225
 
244
 
  number_of_screens = ScreenCount(display);
245
226
  display_name = XDisplayName(dpy_name);
246
227
 
247
228
#ifdef    SHAPE
251
232
  shape.extensions = False;
252
233
#endif // SHAPE
253
234
 
254
 
  xa_wm_colormap_windows =
255
 
    XInternAtom(display, "WM_COLORMAP_WINDOWS", False);
256
 
  xa_wm_protocols = XInternAtom(display, "WM_PROTOCOLS", False);
257
 
  xa_wm_state = XInternAtom(display, "WM_STATE", False);
258
 
  xa_wm_change_state = XInternAtom(display, "WM_CHANGE_STATE", False);
259
 
  xa_wm_delete_window = XInternAtom(display, "WM_DELETE_WINDOW", False);
260
 
  xa_wm_take_focus = XInternAtom(display, "WM_TAKE_FOCUS", False);
261
 
  motif_wm_hints = XInternAtom(display, "_MOTIF_WM_HINTS", False);
262
 
 
263
 
  blackbox_hints = XInternAtom(display, "_BLACKBOX_HINTS", False);
264
 
  blackbox_attributes = XInternAtom(display, "_BLACKBOX_ATTRIBUTES", False);
265
 
  blackbox_change_attributes =
266
 
    XInternAtom(display, "_BLACKBOX_CHANGE_ATTRIBUTES", False);
267
 
 
268
 
  blackbox_structure_messages =
269
 
    XInternAtom(display, "_BLACKBOX_STRUCTURE_MESSAGES", False);
270
 
  blackbox_notify_startup =
271
 
    XInternAtom(display, "_BLACKBOX_NOTIFY_STARTUP", False);
272
 
  blackbox_notify_window_add =
273
 
    XInternAtom(display, "_BLACKBOX_NOTIFY_WINDOW_ADD", False);
274
 
  blackbox_notify_window_del =
275
 
    XInternAtom(display, "_BLACKBOX_NOTIFY_WINDOW_DEL", False);
276
 
  blackbox_notify_current_workspace =
277
 
    XInternAtom(display, "_BLACKBOX_NOTIFY_CURRENT_WORKSPACE", False);
278
 
  blackbox_notify_workspace_count =
279
 
    XInternAtom(display, "_BLACKBOX_NOTIFY_WORKSPACE_COUNT", False);
280
 
  blackbox_notify_window_focus =
281
 
    XInternAtom(display, "_BLACKBOX_NOTIFY_WINDOW_FOCUS", False);
282
 
  blackbox_notify_window_raise =
283
 
    XInternAtom(display, "_BLACKBOX_NOTIFY_WINDOW_RAISE", False);
284
 
  blackbox_notify_window_lower =
285
 
    XInternAtom(display, "_BLACKBOX_NOTIFY_WINDOW_LOWER", False);
286
 
 
287
 
  blackbox_change_workspace =
288
 
    XInternAtom(display, "_BLACKBOX_CHANGE_WORKSPACE", False);
289
 
  blackbox_change_window_focus =
290
 
    XInternAtom(display, "_BLACKBOX_CHANGE_WINDOW_FOCUS", False);
291
 
  blackbox_cycle_window_focus =
292
 
    XInternAtom(display, "_BLACKBOX_CYCLE_WINDOW_FOCUS", False);
293
 
 
294
 
#ifdef    NEWWMSPEC
295
 
 
296
 
  net_supported = XInternAtom(display, "_NET_SUPPORTED", False);
297
 
  net_client_list = XInternAtom(display, "_NET_CLIENT_LIST", False);
298
 
  net_client_list_stacking = XInternAtom(display, "_NET_CLIENT_LIST_STACKING", False);
299
 
  net_number_of_desktops = XInternAtom(display, "_NET_NUMBER_OF_DESKTOPS", False);
300
 
  net_desktop_geometry = XInternAtom(display, "_NET_DESKTOP_GEOMETRY", False);
301
 
  net_desktop_viewport = XInternAtom(display, "_NET_DESKTOP_VIEWPORT", False);
302
 
  net_current_desktop = XInternAtom(display, "_NET_CURRENT_DESKTOP", False);
303
 
  net_desktop_names = XInternAtom(display, "_NET_DESKTOP_NAMES", False);
304
 
  net_active_window = XInternAtom(display, "_NET_ACTIVE_WINDOW", False);
305
 
  net_workarea = XInternAtom(display, "_NET_WORKAREA", False);
306
 
  net_supporting_wm_check = XInternAtom(display, "_NET_SUPPORTING_WM_CHECK", False);
307
 
  net_virtual_roots = XInternAtom(display, "_NET_VIRTUAL_ROOTS", False);
308
 
 
309
 
  net_close_window = XInternAtom(display, "_NET_CLOSE_WINDOW", False);
310
 
  net_wm_moveresize = XInternAtom(display, "_NET_WM_MOVERESIZE", False);
311
 
 
312
 
  net_properties = XInternAtom(display, "_NET_PROPERTIES", False);
313
 
  net_wm_name = XInternAtom(display, "_NET_WM_NAME", False);
314
 
  net_wm_desktop = XInternAtom(display, "_NET_WM_DESKTOP", False);
315
 
  net_wm_window_type = XInternAtom(display, "_NET_WM_WINDOW_TYPE", False);
316
 
  net_wm_state = XInternAtom(display, "_NET_WM_STATE", False);
317
 
  net_wm_strut = XInternAtom(display, "_NET_WM_STRUT", False);
318
 
  net_wm_icon_geometry = XInternAtom(display, "_NET_WM_ICON_GEOMETRY", False);
319
 
  net_wm_icon = XInternAtom(display, "_NET_WM_ICON", False);
320
 
  net_wm_pid = XInternAtom(display, "_NET_WM_PID", False);
321
 
  net_wm_handled_icons = XInternAtom(display, "_NET_WM_HANDLED_ICONS", False);
322
 
 
323
 
  net_wm_ping = XInternAtom(display, "_NET_WM_PING", False);
324
 
 
325
 
#endif // NEWWMSPEC
326
 
 
327
 
  cursor.session = XCreateFontCursor(display, XC_left_ptr);
328
 
  cursor.move = XCreateFontCursor(display, XC_fleur);
329
 
  cursor.ll_angle = XCreateFontCursor(display, XC_ll_angle);
330
 
  cursor.lr_angle = XCreateFontCursor(display, XC_lr_angle);
331
 
 
332
235
  XSetErrorHandler((XErrorHandler) handleXErrors);
333
236
 
334
 
  timerList = new LinkedList<BTimer>;
335
 
 
336
 
  screenInfoList = new LinkedList<ScreenInfo>;
337
 
  for (int i = 0; i < number_of_screens; i++) {
338
 
    ScreenInfo *screeninfo = new ScreenInfo(this, i);
339
 
    screenInfoList->insert(screeninfo);
340
 
  }
 
237
  screenInfoList.reserve(ScreenCount(display));
 
238
  for (int i = 0; i < ScreenCount(display); ++i)
 
239
    screenInfoList.push_back(ScreenInfo(this, i));
341
240
 
342
241
  NumLockMask = ScrollLockMask = 0;
343
242
 
352
251
    // get the values of the keyboard lock modifiers
353
252
    // Note: Caps lock is not retrieved the same way as Scroll and Num lock
354
253
    // since it doesn't need to be.
355
 
    const KeyCode num_lock_code = XKeysymToKeycode(display, XK_Num_Lock);
356
 
    const KeyCode scroll_lock_code = XKeysymToKeycode(display, XK_Scroll_Lock);
357
 
    
 
254
    const KeyCode num_lock = XKeysymToKeycode(display, XK_Num_Lock);
 
255
    const KeyCode scroll_lock = XKeysymToKeycode(display, XK_Scroll_Lock);
 
256
 
358
257
    for (size_t cnt = 0; cnt < size; ++cnt) {
359
258
      if (! modmap->modifiermap[cnt]) continue;
360
259
 
361
 
      if (num_lock_code == modmap->modifiermap[cnt])
362
 
        NumLockMask = mask_table[cnt / modmap->max_keypermod];
363
 
      if (scroll_lock_code == modmap->modifiermap[cnt])
364
 
        ScrollLockMask = mask_table[cnt / modmap->max_keypermod];
 
260
      if (num_lock == modmap->modifiermap[cnt])
 
261
        NumLockMask = mask_table[cnt / modmap->max_keypermod];
 
262
      if (scroll_lock == modmap->modifiermap[cnt])
 
263
        ScrollLockMask = mask_table[cnt / modmap->max_keypermod];
365
264
    }
366
265
  }
367
266
 
368
267
  MaskList[0] = 0;
369
268
  MaskList[1] = LockMask;
370
269
  MaskList[2] = NumLockMask;
371
 
  MaskList[3] = ScrollLockMask;
372
 
  MaskList[4] = LockMask | NumLockMask;
373
 
  MaskList[5] = NumLockMask  | ScrollLockMask;
374
 
  MaskList[6] = LockMask | ScrollLockMask;
375
 
  MaskList[7] = LockMask | NumLockMask | ScrollLockMask;
 
270
  MaskList[3] = LockMask | NumLockMask;
 
271
  MaskList[4] = ScrollLockMask;
 
272
  MaskList[5] = ScrollLockMask | LockMask;
 
273
  MaskList[6] = ScrollLockMask | NumLockMask;
 
274
  MaskList[7] = ScrollLockMask | LockMask | NumLockMask;
376
275
  MaskListLength = sizeof(MaskList) / sizeof(MaskList[0]);
377
 
  
 
276
 
378
277
  if (modmap) XFreeModifiermap(const_cast<XModifierKeymap*>(modmap));
 
278
 
 
279
  gccache = (BGCCache*) 0;
379
280
}
380
281
 
381
282
 
382
283
BaseDisplay::~BaseDisplay(void) {
383
 
  while (screenInfoList->count()) {
384
 
    ScreenInfo *si = screenInfoList->first();
385
 
 
386
 
    screenInfoList->remove(si);
387
 
    delete si;
388
 
  }
389
 
 
390
 
  delete screenInfoList;
391
 
 
392
 
  // we don't create the BTimers, we don't delete them
393
 
  while (timerList->count())
394
 
    timerList->remove(0);
395
 
 
396
 
  delete timerList;
 
284
  delete gccache;
397
285
 
398
286
  XCloseDisplay(display);
399
287
}
402
290
void BaseDisplay::eventLoop(void) {
403
291
  run();
404
292
 
405
 
  int xfd = ConnectionNumber(display);
 
293
  const int xfd = ConnectionNumber(display);
406
294
 
407
 
  while ((! _shutdown) && (! internal_error)) {
 
295
  while (run_state == RUNNING && ! internal_error) {
408
296
    if (XPending(display)) {
409
297
      XEvent e;
410
298
      XNextEvent(display, &e);
411
 
 
412
 
      if (last_bad_window != None && e.xany.window == last_bad_window) {
413
 
#ifdef    DEBUG
414
 
      fprintf(stderr, i18n->getMessage(BaseDisplaySet,
415
 
                                       BaseDisplayBadWindowRemove,
416
 
                         "BaseDisplay::eventLoop(): removing bad window "
417
 
                         "from event queue\n"));
418
 
#endif // DEBUG
419
 
      } else {
420
 
        last_bad_window = None;
421
 
        process_event(&e);
422
 
      }
 
299
      process_event(&e);
423
300
    } else {
424
301
      fd_set rfds;
425
302
      timeval now, tm, *timeout = (timeval *) 0;
427
304
      FD_ZERO(&rfds);
428
305
      FD_SET(xfd, &rfds);
429
306
 
430
 
      if (timerList->count()) {
 
307
      if (! timerList.empty()) {
 
308
        const BTimer* const timer = timerList.top();
 
309
 
431
310
        gettimeofday(&now, 0);
432
 
 
433
 
        tm.tv_sec = tm.tv_usec = 0l;
434
 
 
435
 
        BTimer *timer = timerList->first();
436
 
 
437
 
        tm.tv_sec = timer->getStartTime().tv_sec +
438
 
          timer->getTimeout().tv_sec - now.tv_sec;
439
 
        tm.tv_usec = timer->getStartTime().tv_usec +
440
 
          timer->getTimeout().tv_usec - now.tv_usec;
441
 
 
442
 
        while (tm.tv_usec >= 1000000) {
443
 
          tm.tv_sec++;
444
 
          tm.tv_usec -= 1000000;
445
 
        }
446
 
 
447
 
        while (tm.tv_usec < 0) {
448
 
          if (tm.tv_sec > 0) {
449
 
            tm.tv_sec--;
450
 
            tm.tv_usec += 1000000;
451
 
          } else {
452
 
            tm.tv_usec = 0;
453
 
            break;
454
 
          }
455
 
        }
 
311
        tm = timer->timeRemaining(now);
456
312
 
457
313
        timeout = &tm;
458
314
      }
462
318
      // check for timer timeout
463
319
      gettimeofday(&now, 0);
464
320
 
465
 
      LinkedListIterator<BTimer> it(timerList);
466
 
      for(BTimer *timer = it.current(); timer; it++, timer = it.current()) {
467
 
        tm.tv_sec = timer->getStartTime().tv_sec +
468
 
          timer->getTimeout().tv_sec;
469
 
        tm.tv_usec = timer->getStartTime().tv_usec +
470
 
          timer->getTimeout().tv_usec;
471
 
 
472
 
        if ((now.tv_sec < tm.tv_sec) ||
473
 
            (now.tv_sec == tm.tv_sec && now.tv_usec < tm.tv_usec))
 
321
      // there is a small chance for deadlock here:
 
322
      // *IF* the timer list keeps getting refreshed *AND* the time between
 
323
      // timer->start() and timer->shouldFire() is within the timer's period
 
324
      // then the timer will keep firing.  This should be VERY near impossible.
 
325
      while (! timerList.empty()) {
 
326
        BTimer *timer = timerList.top();
 
327
        if (! timer->shouldFire(now))
474
328
          break;
475
329
 
 
330
        timerList.pop();
 
331
 
476
332
        timer->fireTimeout();
477
 
 
478
 
        // restart the current timer so that the start time is updated
479
 
        if (! timer->doOnce()) timer->start();
480
 
        else timer->stop();
 
333
        timer->halt();
 
334
        if (timer->isRecurring())
 
335
          timer->start();
481
336
      }
482
337
    }
483
338
  }
484
339
}
485
340
 
486
341
 
487
 
const Bool BaseDisplay::validateWindow(Window window) {
488
 
  XEvent event;
489
 
  if (XCheckTypedWindowEvent(display, window, DestroyNotify, &event)) {
490
 
    XPutBackEvent(display, &event);
491
 
 
492
 
    return False;
493
 
  }
494
 
 
495
 
  return True;
496
 
}
497
 
 
498
 
 
499
 
void BaseDisplay::grab(void) {
500
 
  if (! server_grabs++)
501
 
    XGrabServer(display);
502
 
}
503
 
 
504
 
 
505
 
void BaseDisplay::ungrab(void) {
506
 
  if (! --server_grabs)
507
 
    XUngrabServer(display);
508
 
 
509
 
  if (server_grabs < 0) server_grabs = 0;
510
 
}
511
 
 
512
 
 
513
342
void BaseDisplay::addTimer(BTimer *timer) {
514
343
  if (! timer) return;
515
344
 
516
 
  LinkedListIterator<BTimer> it(timerList);
517
 
  int index = 0;
518
 
  for (BTimer *tmp = it.current(); tmp; it++, index++, tmp = it.current())
519
 
    if ((tmp->getTimeout().tv_sec > timer->getTimeout().tv_sec) ||
520
 
        ((tmp->getTimeout().tv_sec == timer->getTimeout().tv_sec) &&
521
 
         (tmp->getTimeout().tv_usec >= timer->getTimeout().tv_usec)))
522
 
      break;
523
 
 
524
 
  timerList->insert(timer, index);
 
345
  timerList.push(timer);
525
346
}
526
347
 
527
348
 
528
349
void BaseDisplay::removeTimer(BTimer *timer) {
529
 
  timerList->remove(timer);
 
350
  timerList.release(timer);
530
351
}
531
352
 
532
353
 
533
354
/*
534
 
 * Grabs a button, but also grabs the button in every possible combination with
535
 
 * the keyboard lock keys, so that they do not cancel out the event.
 
355
 * Grabs a button, but also grabs the button in every possible combination
 
356
 * with the keyboard lock keys, so that they do not cancel out the event.
 
357
 
 
358
 * if allow_scroll_lock is true then only the top half of the lock mask
 
359
 * table is used and scroll lock is ignored.  This value defaults to false.
536
360
 */
537
361
void BaseDisplay::grabButton(unsigned int button, unsigned int modifiers,
538
 
                             Window grab_window, Bool owner_events,
539
 
                             unsigned int event_mask, int pointer_mode,
540
 
                             int keybaord_mode, Window confine_to,
541
 
                             Cursor cursor) const
542
 
{
543
 
  for (size_t cnt = 0; cnt < MaskListLength; ++cnt) {
 
362
                             Window grab_window, bool owner_events,
 
363
                             unsigned int event_mask, int pointer_mode,
 
364
                             int keyboard_mode, Window confine_to,
 
365
                             Cursor cursor, bool allow_scroll_lock) const {
 
366
  unsigned int length = (allow_scroll_lock) ? MaskListLength / 2:
 
367
                                              MaskListLength;
 
368
  for (size_t cnt = 0; cnt < length; ++cnt) {
544
369
    XGrabButton(display, button, modifiers | MaskList[cnt], grab_window,
545
 
        owner_events, event_mask, pointer_mode, keybaord_mode, confine_to,
546
 
        cursor);
 
370
                owner_events, event_mask, pointer_mode, keyboard_mode,
 
371
                confine_to, cursor);
547
372
  }
548
373
}
549
374
 
 
375
 
550
376
/*
551
377
 * Releases the grab on a button, and ungrabs all possible combinations of the
552
378
 * keyboard lock keys.
553
379
 */
554
380
void BaseDisplay::ungrabButton(unsigned int button, unsigned int modifiers,
555
 
                               Window grab_window) const {
 
381
                               Window grab_window) const {
556
382
  for (size_t cnt = 0; cnt < MaskListLength; ++cnt) {
557
383
    XUngrabButton(display, button, modifiers | MaskList[cnt], grab_window);
558
384
  }
559
385
}
560
386
 
561
387
 
562
 
ScreenInfo::ScreenInfo(BaseDisplay *d, int num) {
 
388
const ScreenInfo* BaseDisplay::getScreenInfo(unsigned int s) const {
 
389
  if (s < screenInfoList.size())
 
390
    return &screenInfoList[s];
 
391
  return (const ScreenInfo*) 0;
 
392
}
 
393
 
 
394
 
 
395
BGCCache* BaseDisplay::gcCache(void) const {
 
396
  if (! gccache)
 
397
    gccache = new BGCCache(this, screenInfoList.size());
 
398
  
 
399
  return gccache;
 
400
}
 
401
 
 
402
 
 
403
ScreenInfo::ScreenInfo(BaseDisplay *d, unsigned int num) {
563
404
  basedisplay = d;
564
405
  screen_number = num;
565
406
 
566
407
  root_window = RootWindow(basedisplay->getXDisplay(), screen_number);
 
408
 
 
409
  rect.setSize(WidthOfScreen(ScreenOfDisplay(basedisplay->getXDisplay(),
 
410
                                             screen_number)),
 
411
               HeightOfScreen(ScreenOfDisplay(basedisplay->getXDisplay(),
 
412
                                              screen_number)));
 
413
 
 
414
  /*
 
415
    If the default depth is at least 8 we will use that,
 
416
    otherwise we try to find the largest TrueColor visual.
 
417
    Preference is given to 24 bit over larger depths if 24 bit is an option.
 
418
  */
 
419
 
567
420
  depth = DefaultDepth(basedisplay->getXDisplay(), screen_number);
568
 
 
569
 
  width =
570
 
    WidthOfScreen(ScreenOfDisplay(basedisplay->getXDisplay(), screen_number));
571
 
  height =
572
 
    HeightOfScreen(ScreenOfDisplay(basedisplay->getXDisplay(), screen_number));
573
 
 
574
 
  // search for a TrueColor Visual... if we can't find one... we will use the
575
 
  // default visual for the screen
576
 
  XVisualInfo vinfo_template, *vinfo_return;
577
 
  int vinfo_nitems;
578
 
 
579
 
  vinfo_template.screen = screen_number;
580
 
  vinfo_template.c_class = TrueColor;
581
 
 
582
 
  visual = (Visual *) 0;
583
 
 
584
 
  if ((vinfo_return = XGetVisualInfo(basedisplay->getXDisplay(),
585
 
                                     VisualScreenMask | VisualClassMask,
586
 
                                     &vinfo_template, &vinfo_nitems)) &&
587
 
      vinfo_nitems > 0) {
588
 
    for (int i = 0; i < vinfo_nitems; i++) {
589
 
      if (depth < (vinfo_return + i)->depth) {
590
 
        depth = (vinfo_return + i)->depth;
591
 
        visual = (vinfo_return + i)->visual;
 
421
  visual = DefaultVisual(basedisplay->getXDisplay(), screen_number);
 
422
  colormap = DefaultColormap(basedisplay->getXDisplay(), screen_number);
 
423
  
 
424
  if (depth < 8) {
 
425
    // search for a TrueColor Visual... if we can't find one...
 
426
    // we will use the default visual for the screen
 
427
    XVisualInfo vinfo_template, *vinfo_return;
 
428
    int vinfo_nitems;
 
429
    int best = -1;
 
430
 
 
431
    vinfo_template.screen = screen_number;
 
432
    vinfo_template.c_class = TrueColor;
 
433
 
 
434
    vinfo_return = XGetVisualInfo(basedisplay->getXDisplay(),
 
435
                                  VisualScreenMask | VisualClassMask,
 
436
                                  &vinfo_template, &vinfo_nitems);
 
437
    if (vinfo_return) {
 
438
      int max_depth = 1;
 
439
      for (int i = 0; i < vinfo_nitems; ++i) {
 
440
        if (vinfo_return[i].depth > max_depth) {
 
441
          if (max_depth == 24 && vinfo_return[i].depth > 24)
 
442
            break;          // prefer 24 bit over 32
 
443
          max_depth = vinfo_return[i].depth;
 
444
          best = i;
 
445
        }
592
446
      }
 
447
      if (max_depth < depth) best = -1;
 
448
    }
 
449
 
 
450
    if (best != -1) {
 
451
      depth = vinfo_return[best].depth;
 
452
      visual = vinfo_return[best].visual;
 
453
      colormap = XCreateColormap(basedisplay->getXDisplay(), root_window,
 
454
                                 visual, AllocNone);
593
455
    }
594
456
 
595
457
    XFree(vinfo_return);
596
458
  }
597
459
 
598
 
  if (visual) {
599
 
    colormap = XCreateColormap(basedisplay->getXDisplay(), root_window,
600
 
                               visual, AllocNone);
601
 
  } else {
602
 
    visual = DefaultVisual(basedisplay->getXDisplay(), screen_number);
603
 
    colormap = DefaultColormap(basedisplay->getXDisplay(), screen_number);
604
 
  }
 
460
  // get the default display string and strip the screen number
 
461
  string default_string = DisplayString(basedisplay->getXDisplay());
 
462
  const string::size_type pos = default_string.rfind(".");
 
463
  if (pos != string::npos)
 
464
    default_string.resize(pos);
 
465
 
 
466
  display_string = string("DISPLAY=") + default_string + '.' +
 
467
    itostring(static_cast<unsigned long>(screen_number));
605
468
}