]> Dogcows Code - chaz/openbox/blob - otk/display.cc
merge the C branch into HEAD
[chaz/openbox] / otk / display.cc
1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2
3 #include "config.h"
4
5 #include "display.hh"
6 #include "util.hh"
7
8 extern "C" {
9 #include <X11/keysym.h>
10
11 #ifdef XKB
12 #include <X11/XKBlib.h>
13 #endif // XKB
14
15 #ifdef SHAPE
16 #include <X11/extensions/shape.h>
17 #endif // SHAPE
18
19 #ifdef XINERAMA
20 #include <X11/extensions/Xinerama.h>
21 #endif // XINERAMA
22
23 #ifdef HAVE_SIGNAL_H
24 # include <signal.h>
25 #endif // HAVE_SIGNAL_H
26
27 #ifdef HAVE_FCNTL_H
28 # include <fcntl.h>
29 #endif // HAVE_FCNTL_H
30
31 #ifdef HAVE_UNISTD_H
32 # include <sys/types.h>
33 # include <unistd.h>
34 #endif // HAVE_UNISTD_H
35
36 #include "../src/gettext.h"
37 #define _(str) gettext(str)
38 }
39
40 #include <cstdio>
41
42 namespace otk {
43
44
45 Display *display = (Display*) 0;
46
47 static int xerrorHandler(::Display *d, XErrorEvent *e)
48 {
49 if (!display->ignoreErrors()) {
50 #ifdef DEBUG
51 char errtxt[128];
52
53 //if (e->error_code != BadWindow)
54 {
55 XGetErrorText(d, e->error_code, errtxt, 127);
56 printf("X Error: %s\n", errtxt);
57 if (e->error_code != BadWindow)
58 abort();
59 }
60 #else
61 (void)d;
62 (void)e;
63 #endif
64 }
65 return false;
66 }
67
68
69 Display::Display(::Display *d)
70 : _display(d),
71 _xkb(false),
72 _xkb_event_basep(0),
73 _shape(false),
74 _shape_event_basep(0),
75 _xinerama(false),
76 _xinerama_event_basep(0),
77 _mask_list(),
78 _num_lock_mask(0),
79 _scroll_lock_mask(0),
80 _grab_count(0)
81 {
82 int junk;
83 (void)junk;
84
85 assert(_display);
86
87 display = this;
88
89 if (fcntl(ConnectionNumber(_display), F_SETFD, 1) == -1) {
90 printf(_("Couldn't mark display connection as close-on-exec.\n\n"));
91 ::exit(1);
92 }
93 if (!XSupportsLocale())
94 printf(_("X server does not support locale.\n"));
95 if (!XSetLocaleModifiers(""))
96 printf(_("Cannot set locale modifiers for the X server.\n"));
97
98 // set our error handler for X errors
99 XSetErrorHandler(xerrorHandler);
100
101 // set the DISPLAY environment variable for any lauched children, to the
102 // display we're using, so they open in the right place.
103 putenv(std::string("DISPLAY=") + DisplayString(_display));
104
105 // find the availability of X extensions we like to use
106 #ifdef XKB
107 _xkb = XkbQueryExtension(_display, &junk, &_xkb_event_basep, &junk, NULL,
108 NULL);
109 #endif
110
111 #ifdef SHAPE
112 _shape = XShapeQueryExtension(_display, &_shape_event_basep, &junk);
113 #endif
114
115 #ifdef XINERAMA
116 _xinerama = XineramaQueryExtension(_display, &_xinerama_event_basep, &junk);
117 #endif // XINERAMA
118
119 // get lock masks that are defined by the display (not constant)
120 _modmap = XGetModifierMapping(_display);
121 assert(_modmap);
122 if (_modmap && _modmap->max_keypermod > 0) {
123 const int mask_table[] = {
124 ShiftMask, LockMask, ControlMask, Mod1Mask,
125 Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask
126 };
127 const size_t size = (sizeof(mask_table) / sizeof(mask_table[0])) *
128 _modmap->max_keypermod;
129 // get the values of the keyboard lock modifiers
130 // Note: Caps lock is not retrieved the same way as Scroll and Num lock
131 // since it doesn't need to be.
132 const KeyCode num_lock = XKeysymToKeycode(_display, XK_Num_Lock);
133 const KeyCode scroll_lock = XKeysymToKeycode(_display, XK_Scroll_Lock);
134
135 for (size_t cnt = 0; cnt < size; ++cnt) {
136 if (! _modmap->modifiermap[cnt]) continue;
137
138 if (num_lock == _modmap->modifiermap[cnt])
139 _num_lock_mask = mask_table[cnt / _modmap->max_keypermod];
140 if (scroll_lock == _modmap->modifiermap[cnt])
141 _scroll_lock_mask = mask_table[cnt / _modmap->max_keypermod];
142 }
143 }
144
145 _mask_list[0] = 0;
146 _mask_list[1] = LockMask;
147 _mask_list[2] = _num_lock_mask;
148 _mask_list[3] = LockMask | _num_lock_mask;
149 _mask_list[4] = _scroll_lock_mask;
150 _mask_list[5] = _scroll_lock_mask | LockMask;
151 _mask_list[6] = _scroll_lock_mask | _num_lock_mask;
152 _mask_list[7] = _scroll_lock_mask | LockMask | _num_lock_mask;
153
154 /*
155 If the default depth is at least 8 we will use that,
156 otherwise we try to find the largest TrueColor visual.
157 Preference is given to 24 bit over larger depths if 24 bit is an option.
158 */
159
160 int screen = DefaultScreen(_display);
161 _depth = DefaultDepth(_display, screen);
162 _visual = DefaultVisual(_display, screen);
163 _colormap = DefaultColormap(_display, screen);
164
165 if (_depth < 8) {
166 // search for a TrueColor Visual... if we can't find one...
167 // we will use the default visual for the screen
168 XVisualInfo vinfo_template, *vinfo_return;
169 int vinfo_nitems;
170 int best = -1;
171
172 vinfo_template.screen = screen;
173 vinfo_template.c_class = TrueColor;
174
175 vinfo_return = XGetVisualInfo(_display,
176 VisualScreenMask | VisualClassMask,
177 &vinfo_template, &vinfo_nitems);
178 if (vinfo_return) {
179 int max_depth = 1;
180 for (int i = 0; i < vinfo_nitems; ++i) {
181 if (vinfo_return[i].depth > max_depth) {
182 if (max_depth == 24 && vinfo_return[i].depth > 24)
183 break; // prefer 24 bit over 32
184 max_depth = vinfo_return[i].depth;
185 best = i;
186 }
187 }
188 if (max_depth < _depth) best = -1;
189 }
190
191 if (best != -1) {
192 _depth = vinfo_return[best].depth;
193 _visual = vinfo_return[best].visual;
194 _colormap = XCreateColormap(_display, RootWindow(_display, screen),
195 _visual, AllocNone);
196 }
197
198 XFree(vinfo_return);
199 }
200 }
201
202
203 Display::~Display()
204 {
205 while (_grab_count > 0)
206 ungrab();
207
208 XFreeModifiermap(_modmap);
209
210 XCloseDisplay(_display);
211 }
212
213
214 void Display::setIgnoreErrors(bool t)
215 {
216 // sync up so that anything already sent is/isn't ignored!
217 XSync(_display, false);
218 _ignore_errors = t;
219 }
220
221 void Display::grab()
222 {
223 if (_grab_count == 0) {
224 XGrabServer(_display);
225 XSync(_display, false); // make sure it kicks in
226 }
227 _grab_count++;
228 }
229
230
231 void Display::ungrab()
232 {
233 if (_grab_count == 0) return;
234 _grab_count--;
235 if (_grab_count == 0) {
236 XUngrabServer(_display);
237 XFlush(_display); // ungrab as soon as possible
238 }
239 }
240
241
242
243
244
245
246
247 /*
248 * Grabs a button, but also grabs the button in every possible combination
249 * with the keyboard lock keys, so that they do not cancel out the event.
250
251 * if allow_scroll_lock is true then only the top half of the lock mask
252 * table is used and scroll lock is ignored. This value defaults to false.
253 */
254 void Display::grabButton(unsigned int button, unsigned int modifiers,
255 Window grab_window, bool owner_events,
256 unsigned int event_mask, int pointer_mode,
257 int keyboard_mode, Window confine_to,
258 Cursor cursor, bool allow_scroll_lock) const
259 {
260 unsigned int length = (allow_scroll_lock) ? 8 / 2:
261 8;
262 for (size_t cnt = 0; cnt < length; ++cnt)
263 XGrabButton(_display, button, modifiers | _mask_list[cnt],
264 grab_window, owner_events, event_mask, pointer_mode,
265 keyboard_mode, confine_to, cursor);
266 }
267
268
269 /*
270 * Releases the grab on a button, and ungrabs all possible combinations of the
271 * keyboard lock keys.
272 */
273 void Display::ungrabButton(unsigned int button, unsigned int modifiers,
274 Window grab_window) const
275 {
276 for (size_t cnt = 0; cnt < 8; ++cnt)
277 XUngrabButton(_display, button, modifiers | _mask_list[cnt],
278 grab_window);
279 }
280
281 void Display::grabKey(unsigned int keycode, unsigned int modifiers,
282 Window grab_window, bool owner_events,
283 int pointer_mode, int keyboard_mode,
284 bool allow_scroll_lock) const
285 {
286 unsigned int length = (allow_scroll_lock) ? 8 / 2:
287 8;
288 for (size_t cnt = 0; cnt < length; ++cnt)
289 XGrabKey(_display, keycode, modifiers | _mask_list[cnt],
290 grab_window, owner_events, pointer_mode, keyboard_mode);
291 }
292
293 void Display::ungrabKey(unsigned int keycode, unsigned int modifiers,
294 Window grab_window) const
295 {
296 for (size_t cnt = 0; cnt < 8; ++cnt)
297 XUngrabKey(_display, keycode, modifiers | _mask_list[cnt],
298 grab_window);
299 }
300
301 void Display::ungrabAllKeys(Window grab_window) const
302 {
303 XUngrabKey(_display, AnyKey, AnyModifier, grab_window);
304 }
305
306 }
This page took 0.044107 seconds and 4 git commands to generate.