00001
00002
00003 #ifdef HAVE_CONFIG_H
00004 # include "../config.h"
00005 #endif
00006
00007 #include "display.hh"
00008 #include "screeninfo.hh"
00009 #include "rendercontrol.hh"
00010 #include "util.hh"
00011
00012 extern "C" {
00013 #include <X11/keysym.h>
00014
00015 #ifdef XKB
00016 #include <X11/XKBlib.h>
00017 #endif // XKB
00018
00019 #ifdef SHAPE
00020 #include <X11/extensions/shape.h>
00021 #endif // SHAPE
00022
00023 #ifdef XINERAMA
00024 #include <X11/extensions/Xinerama.h>
00025 #endif // XINERAMA
00026
00027 #ifdef HAVE_STDIO_H
00028 # include <stdio.h>
00029 #endif // HAVE_STDIO_H
00030
00031 #ifdef HAVE_SIGNAL_H
00032 # include <signal.h>
00033 #endif // HAVE_SIGNAL_H
00034
00035 #ifdef HAVE_FCNTL_H
00036 # include <fcntl.h>
00037 #endif // HAVE_FCNTL_H
00038
00039 #ifdef HAVE_UNISTD_H
00040 # include <sys/types.h>
00041 # include <unistd.h>
00042 #endif // HAVE_UNISTD_H
00043
00044 #include "../src/gettext.h"
00045 #define _(str) gettext(str)
00046 }
00047
00048 namespace otk {
00049
00050
00051 Display *display = (Display*) 0;
00052
00053 static int xerrorHandler(::Display *d, XErrorEvent *e)
00054 {
00055 if (!display->ignoreErrors()) {
00056 #ifdef DEBUG
00057 char errtxt[128];
00058
00059
00060 {
00061 XGetErrorText(d, e->error_code, errtxt, 127);
00062 printf("X Error: %s\n", errtxt);
00063 if (e->error_code != BadWindow)
00064 abort();
00065 }
00066 #else
00067 (void)d;
00068 (void)e;
00069 #endif
00070 }
00071 return false;
00072 }
00073
00074
00075 Display::Display()
00076 : _display(0),
00077 _xkb(false),
00078 _xkb_event_basep(0),
00079 _shape(false),
00080 _shape_event_basep(0),
00081 _xinerama(false),
00082 _xinerama_event_basep(0),
00083 _mask_list(),
00084 _num_lock_mask(0),
00085 _scroll_lock_mask(0),
00086 _grab_count(0),
00087 _screeninfo_list(0),
00088 _rendercontrol_list(0)
00089 {
00090 int junk;
00091 (void)junk;
00092
00093 display = this;
00094
00095
00096 if (!(_display = XOpenDisplay(NULL))) {
00097 printf(_("Unable to open connection to the X server. Please set the \n\
00098 DISPLAY environment variable approriately.\n\n"));
00099 ::exit(1);
00100 }
00101 if (fcntl(ConnectionNumber(_display), F_SETFD, 1) == -1) {
00102 printf(_("Couldn't mark display connection as close-on-exec.\n\n"));
00103 ::exit(1);
00104 }
00105 if (!XSupportsLocale())
00106 printf(_("X server does not support locale.\n"));
00107 if (!XSetLocaleModifiers(""))
00108 printf(_("Cannot set locale modifiers for the X server.\n"));
00109
00110
00111 XSetErrorHandler(xerrorHandler);
00112
00113
00114
00115 putenv(std::string("DISPLAY=") + DisplayString(_display));
00116
00117
00118 #ifdef XKB
00119 _xkb = XkbQueryExtension(_display, &junk, &_xkb_event_basep, &junk, NULL,
00120 NULL);
00121 #endif
00122
00123 #ifdef SHAPE
00124 _shape = XShapeQueryExtension(_display, &_shape_event_basep, &junk);
00125 #endif
00126
00127 #ifdef XINERAMA
00128 _xinerama = XineramaQueryExtension(_display, &_xinerama_event_basep, &junk);
00129 #endif // XINERAMA
00130
00131
00132 _modmap = XGetModifierMapping(_display);
00133 assert(_modmap);
00134 if (_modmap && _modmap->max_keypermod > 0) {
00135 const int mask_table[] = {
00136 ShiftMask, LockMask, ControlMask, Mod1Mask,
00137 Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask
00138 };
00139 const size_t size = (sizeof(mask_table) / sizeof(mask_table[0])) *
00140 _modmap->max_keypermod;
00141
00142
00143
00144 const KeyCode num_lock = XKeysymToKeycode(_display, XK_Num_Lock);
00145 const KeyCode scroll_lock = XKeysymToKeycode(_display, XK_Scroll_Lock);
00146
00147 for (size_t cnt = 0; cnt < size; ++cnt) {
00148 if (! _modmap->modifiermap[cnt]) continue;
00149
00150 if (num_lock == _modmap->modifiermap[cnt])
00151 _num_lock_mask = mask_table[cnt / _modmap->max_keypermod];
00152 if (scroll_lock == _modmap->modifiermap[cnt])
00153 _scroll_lock_mask = mask_table[cnt / _modmap->max_keypermod];
00154 }
00155 }
00156
00157 _mask_list[0] = 0;
00158 _mask_list[1] = LockMask;
00159 _mask_list[2] = _num_lock_mask;
00160 _mask_list[3] = LockMask | _num_lock_mask;
00161 _mask_list[4] = _scroll_lock_mask;
00162 _mask_list[5] = _scroll_lock_mask | LockMask;
00163 _mask_list[6] = _scroll_lock_mask | _num_lock_mask;
00164 _mask_list[7] = _scroll_lock_mask | LockMask | _num_lock_mask;
00165
00166
00167
00168 _screeninfo_list = new ScreenInfo*[ScreenCount(_display)];
00169 _rendercontrol_list = new RenderControl*[ScreenCount(_display)];
00170 for (int i = 0; i < ScreenCount(_display); ++i) {
00171 _screeninfo_list[i] = new ScreenInfo(i);
00172 _rendercontrol_list[i] = RenderControl::getRenderControl(i);
00173 }
00174 }
00175
00176
00177 Display::~Display()
00178 {
00179 while (_grab_count > 0)
00180 ungrab();
00181
00182 XFreeModifiermap(_modmap);
00183
00184 for (int i = 0; i < ScreenCount(_display); ++i) {
00185 delete _rendercontrol_list[i];
00186 delete _screeninfo_list[i];
00187 }
00188 delete [] _rendercontrol_list;
00189 delete [] _screeninfo_list;
00190
00191 XCloseDisplay(_display);
00192 }
00193
00194
00195 const ScreenInfo* Display::screenInfo(int snum) const
00196 {
00197 assert(snum >= 0);
00198 assert(snum < (signed) ScreenCount(_display));
00199 return _screeninfo_list[snum];
00200 }
00201
00202
00203 const ScreenInfo* Display::findScreen(Window root) const
00204 {
00205 for (int i = 0; i < ScreenCount(_display); ++i)
00206 if (_screeninfo_list[i]->rootWindow() == root)
00207 return _screeninfo_list[i];
00208 return 0;
00209 }
00210
00211
00212 const RenderControl *Display::renderControl(int snum) const
00213 {
00214 assert(snum >= 0);
00215 assert(snum < (signed) ScreenCount(_display));
00216 return _rendercontrol_list[snum];
00217 }
00218
00219
00220 void Display::setIgnoreErrors(bool t)
00221 {
00222 _ignore_errors = t;
00223
00224 XSync(_display, false);
00225 }
00226
00227 void Display::grab()
00228 {
00229 if (_grab_count == 0) {
00230 XGrabServer(_display);
00231 XSync(_display, false);
00232 }
00233 _grab_count++;
00234 }
00235
00236
00237 void Display::ungrab()
00238 {
00239 if (_grab_count == 0) return;
00240 _grab_count--;
00241 if (_grab_count == 0) {
00242 XUngrabServer(_display);
00243 XFlush(_display);
00244 }
00245 }
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260 void Display::grabButton(unsigned int button, unsigned int modifiers,
00261 Window grab_window, bool owner_events,
00262 unsigned int event_mask, int pointer_mode,
00263 int keyboard_mode, Window confine_to,
00264 Cursor cursor, bool allow_scroll_lock) const
00265 {
00266 unsigned int length = (allow_scroll_lock) ? 8 / 2:
00267 8;
00268 for (size_t cnt = 0; cnt < length; ++cnt)
00269 XGrabButton(_display, button, modifiers | _mask_list[cnt],
00270 grab_window, owner_events, event_mask, pointer_mode,
00271 keyboard_mode, confine_to, cursor);
00272 }
00273
00274
00275
00276
00277
00278
00279 void Display::ungrabButton(unsigned int button, unsigned int modifiers,
00280 Window grab_window) const
00281 {
00282 for (size_t cnt = 0; cnt < 8; ++cnt)
00283 XUngrabButton(_display, button, modifiers | _mask_list[cnt],
00284 grab_window);
00285 }
00286
00287 void Display::grabKey(unsigned int keycode, unsigned int modifiers,
00288 Window grab_window, bool owner_events,
00289 int pointer_mode, int keyboard_mode,
00290 bool allow_scroll_lock) const
00291 {
00292 unsigned int length = (allow_scroll_lock) ? 8 / 2:
00293 8;
00294 for (size_t cnt = 0; cnt < length; ++cnt)
00295 XGrabKey(_display, keycode, modifiers | _mask_list[cnt],
00296 grab_window, owner_events, pointer_mode, keyboard_mode);
00297 }
00298
00299 void Display::ungrabKey(unsigned int keycode, unsigned int modifiers,
00300 Window grab_window) const
00301 {
00302 for (size_t cnt = 0; cnt < 8; ++cnt)
00303 XUngrabKey(_display, keycode, modifiers | _mask_list[cnt],
00304 grab_window);
00305 }
00306
00307 }