1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
9 #include <X11/keysym.h>
12 #include <X11/XKBlib.h>
16 #include <X11/extensions/shape.h>
20 #include <X11/extensions/Xinerama.h>
25 #endif // HAVE_SIGNAL_H
29 #endif // HAVE_FCNTL_H
32 # include <sys/types.h>
34 #endif // HAVE_UNISTD_H
36 #include "../src/gettext.h"
37 #define _(str) gettext(str)
45 Display
*display
= (Display
*) 0;
47 static int xerrorHandler(::Display
*d
, XErrorEvent
*e
)
49 if (!display
->ignoreErrors()) {
53 //if (e->error_code != BadWindow)
55 XGetErrorText(d
, e
->error_code
, errtxt
, 127);
56 printf("X Error: %s\n", errtxt
);
57 if (e
->error_code
!= BadWindow
)
69 Display::Display(::Display
*d
)
74 _shape_event_basep(0),
76 _xinerama_event_basep(0),
89 if (fcntl(ConnectionNumber(_display
), F_SETFD
, 1) == -1) {
90 printf(_("Couldn't mark display connection as close-on-exec.\n\n"));
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"));
98 // set our error handler for X errors
99 XSetErrorHandler(xerrorHandler
);
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
));
105 // find the availability of X extensions we like to use
107 _xkb
= XkbQueryExtension(_display
, &junk
, &_xkb_event_basep
, &junk
, NULL
,
112 _shape
= XShapeQueryExtension(_display
, &_shape_event_basep
, &junk
);
116 _xinerama
= XineramaQueryExtension(_display
, &_xinerama_event_basep
, &junk
);
119 // get lock masks that are defined by the display (not constant)
120 _modmap
= XGetModifierMapping(_display
);
122 if (_modmap
&& _modmap
->max_keypermod
> 0) {
123 const int mask_table
[] = {
124 ShiftMask
, LockMask
, ControlMask
, Mod1Mask
,
125 Mod2Mask
, Mod3Mask
, Mod4Mask
, Mod5Mask
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
);
135 for (size_t cnt
= 0; cnt
< size
; ++cnt
) {
136 if (! _modmap
->modifiermap
[cnt
]) continue;
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
];
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
;
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.
160 int screen
= DefaultScreen(_display
);
161 _depth
= DefaultDepth(_display
, screen
);
162 _visual
= DefaultVisual(_display
, screen
);
163 _colormap
= DefaultColormap(_display
, screen
);
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
;
172 vinfo_template
.screen
= screen
;
173 vinfo_template
.c_class
= TrueColor
;
175 vinfo_return
= XGetVisualInfo(_display
,
176 VisualScreenMask
| VisualClassMask
,
177 &vinfo_template
, &vinfo_nitems
);
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
;
188 if (max_depth
< _depth
) best
= -1;
192 _depth
= vinfo_return
[best
].depth
;
193 _visual
= vinfo_return
[best
].visual
;
194 _colormap
= XCreateColormap(_display
, RootWindow(_display
, screen
),
205 while (_grab_count
> 0)
208 XFreeModifiermap(_modmap
);
210 XCloseDisplay(_display
);
214 void Display::setIgnoreErrors(bool t
)
216 // sync up so that anything already sent is/isn't ignored!
217 XSync(_display
, false);
223 if (_grab_count
== 0) {
224 XGrabServer(_display
);
225 XSync(_display
, false); // make sure it kicks in
231 void Display::ungrab()
233 if (_grab_count
== 0) return;
235 if (_grab_count
== 0) {
236 XUngrabServer(_display
);
237 XFlush(_display
); // ungrab as soon as possible
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.
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.
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
260 unsigned int length
= (allow_scroll_lock
) ? 8 / 2:
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
);
270 * Releases the grab on a button, and ungrabs all possible combinations of the
271 * keyboard lock keys.
273 void Display::ungrabButton(unsigned int button
, unsigned int modifiers
,
274 Window grab_window
) const
276 for (size_t cnt
= 0; cnt
< 8; ++cnt
)
277 XUngrabButton(_display
, button
, modifiers
| _mask_list
[cnt
],
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
286 unsigned int length
= (allow_scroll_lock
) ? 8 / 2:
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
);
293 void Display::ungrabKey(unsigned int keycode
, unsigned int modifiers
,
294 Window grab_window
) const
296 for (size_t cnt
= 0; cnt
< 8; ++cnt
)
297 XUngrabKey(_display
, keycode
, modifiers
| _mask_list
[cnt
],
301 void Display::ungrabAllKeys(Window grab_window
) const
303 XUngrabKey(_display
, AnyKey
, AnyModifier
, grab_window
);