Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

/otk/display.cc

Go to the documentation of this file.
00001 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
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     //if (e->error_code != BadWindow)
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   // Open the X display
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   // set our error handler for X errors
00111   XSetErrorHandler(xerrorHandler);
00112 
00113   // set the DISPLAY environment variable for any lauched children, to the
00114   // display we're using, so they open in the right place.
00115   putenv(std::string("DISPLAY=") + DisplayString(_display));
00116   
00117   // find the availability of X extensions we like to use
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   // get lock masks that are defined by the display (not constant)
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     // get the values of the keyboard lock modifiers
00142     // Note: Caps lock is not retrieved the same way as Scroll and Num lock
00143     // since it doesn't need to be.
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   // Get information on all the screens which are available, and create their
00167   // RenderControl
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   // sync up so that anything already sent is/isn't ignored!
00224   XSync(_display, false);
00225 }
00226 
00227 void Display::grab()
00228 {
00229   if (_grab_count == 0) {
00230     XGrabServer(_display);
00231     XSync(_display, false); // make sure it kicks in
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); // ungrab as soon as possible
00244   }
00245 }
00246 
00247 
00248 
00249 
00250 
00251 
00252 
00253 /*
00254  * Grabs a button, but also grabs the button in every possible combination
00255  * with the keyboard lock keys, so that they do not cancel out the event.
00256 
00257  * if allow_scroll_lock is true then only the top half of the lock mask
00258  * table is used and scroll lock is ignored.  This value defaults to false.
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  * Releases the grab on a button, and ungrabs all possible combinations of the
00277  * keyboard lock keys.
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 }

Generated on Tue Feb 4 22:58:55 2003 for Openbox by doxygen1.3-rc2