]> Dogcows Code - chaz/openbox/blobdiff - src/XDisplay.cc
missing an include
[chaz/openbox] / src / XDisplay.cc
index 48f19d76ae4caf24334d03e9887fb236fc717f2a..1addb2d5b4d2cf898db68b18e579977dc6968b67 100644 (file)
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 // DEALINGS IN THE SOFTWARE.
 
-#include "Xdisplay.h"
-#include "XScreen.h"
+#ifdef HAVE_CONFIG_H
+# include "../config.h"
+#endif
+
+#ifdef HAVE_UNNISTD_H
+# include <unistd.h>
+#endif
+
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+
+#ifdef SHAPE
+# include <X11/extensions/shape.h>
+#endif
+
+#include "XDisplay.h"
 #include "Util.h"
 #include <iostream>
 #include <algorithm>
 
 using std::cerr;
+using std::endl;
 
-Xdisplay::Xdisplay(const char *dpyname) {
+std::string XDisplay::_app_name;
+Window      XDisplay::_last_bad_window = None;
+  
+/*
+ * X error handler to handle all X errors while the application is
+ * running.
+ */
+int XDisplay::errorHandler(Display *d, XErrorEvent *e) {
+#ifdef DEBUG
+  char errtxt[128];
+  XGetErrorText(d, e->error_code, errtxt, sizeof(errtxt)/sizeof(char));
+  cerr << _app_name.c_str() << ": X error: " << 
+    errtxt << "(" << e->error_code << ") opcodes " <<
+    e->request_code << "/" << e->minor_code << endl;
+  cerr.flags(std::ios_base::hex);
+  cerr << "  resource 0x" << e->resourceid << endl;
+  cerr.flags(std::ios_base::dec);
+#endif
+  
+  if (e->error_code == BadWindow)
+    _last_bad_window = e->resourceid;
+  
+  return False;
+}
+
+
+XDisplay::XDisplay(const std::string &application_name, const char *dpyname) {
+  _app_name = application_name;
   _grabs = 0;
   _hasshape = false;
   
-  _display = XOpenDisplay(dpy_name);
+  _display = XOpenDisplay(dpyname);
   if (_display == NULL) {
     cerr << "Could not open display. Connection to X server failed.\n";
     ::exit(2);
   }
-  if (-1 == fcntl(ConnectionNumber(display), F_SETFD, 1)) {
+  if (-1 == fcntl(ConnectionNumber(_display), F_SETFD, 1)) {
     cerr << "Could not mark display connection as close-on-exec.\n";
     ::exit(2);
   }
   _name = XDisplayName(dpyname);
 
-  XSetErrorHandler(XErrorHandler);
+  XSetErrorHandler(errorHandler);
 
 #ifdef    SHAPE
   int waste;
   _hasshape = XShapeQueryExtension(_display, &_shape_event_base, &waste);
 #endif // SHAPE
 
-  const unsigned int scount = ScreenCount(_display);
-  _screens.reserve(scount);
-  for (unsigned int s = 0; s < scount; s++)
-    _screens.push_back(new XScreen(_display, s));
+#ifndef NOCLOBBER
+  getLockModifiers();
+#endif
 }
 
 
-Xdisplay::~Xdisplay() {
+XDisplay::~XDisplay() {
   std::for_each(_screens.begin(), _screens.end(), PointerAssassin());
   XCloseDisplay(_display);
 }
 
 
-/*
- * Return information about a screen.
- */
-XScreen *Xdisplay::screen(unsigned int s) const {
-  ASSERT(s < _screens.size());
-  return _screens[s];
-}
-
-
 /*
  * Grab the X server
  */
@@ -87,3 +120,141 @@ void XDisplay::ungrab() {
   if (--_grabs == 0)
     XUngrabServer(_display);
 }
+
+
+/*
+ * Gets the next event on the queue from the X server.
+ * 
+ * Returns: true if e contains a new event; false if there is no event to be
+ *          returned.
+ */
+bool XDisplay::nextEvent(XEvent &e) {
+  if(!XPending(_display))
+    return false;
+  XNextEvent(_display, &e);
+  if (_last_bad_window != None) {
+    if (e.xany.window == _last_bad_window) {
+      cerr << "XDisplay::nextEvent(): Removing event for bad window from " <<
+        "event queue\n";
+      return false;
+    } else
+      _last_bad_window = None;
+  }
+  return true;
+}
+
+
+int XDisplay::connectionNumber() const {
+  return ConnectionNumber(_display);
+}
+
+
+/*
+ * Creates a font cursor in the X server and returns it.
+ */
+Cursor createCursor(unsigned int shape) const {
+  return XCreateFontCursor(_display, shape);
+}
+
+
+#ifndef   NOCLOBBER
+void XDisplay::getLockModifers() {
+  NumLockMask = ScrollLockMask = 0;
+
+  const XModifierKeymap* const modmap = XGetModifierMapping(display);
+  if (modmap && modmap->max_keypermod > 0) {
+    const int mask_table[] = {
+      ShiftMask, LockMask, ControlMask, Mod1Mask,
+      Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask
+    };
+    const size_t size = (sizeof(mask_table) / sizeof(mask_table[0])) *
+      modmap->max_keypermod;
+    // get the values of the keyboard lock modifiers
+    // Note: Caps lock is not retrieved the same way as Scroll and Num lock
+    // since it doesn't need to be.
+    const KeyCode num_lock_code = XKeysymToKeycode(display, XK_Num_Lock);
+    const KeyCode scroll_lock_code = XKeysymToKeycode(display, XK_Scroll_Lock);
+
+    for (size_t cnt = 0; cnt < size; ++cnt) {
+      if (! modmap->modifiermap[cnt]) continue;
+
+      if (num_lock_code == modmap->modifiermap[cnt])
+        NumLockMask = mask_table[cnt / modmap->max_keypermod];
+      if (scroll_lock_code == modmap->modifiermap[cnt])
+        ScrollLockMask = mask_table[cnt / modmap->max_keypermod];
+    }
+  }
+
+  MaskList[0] = 0;
+  MaskList[1] = LockMask;
+  MaskList[2] = NumLockMask;
+  MaskList[3] = ScrollLockMask;
+  MaskList[4] = LockMask | NumLockMask;
+  MaskList[5] = NumLockMask  | ScrollLockMask;
+  MaskList[6] = LockMask | ScrollLockMask;
+  MaskList[7] = LockMask | NumLockMask | ScrollLockMask;
+
+  if (modmap) XFreeModifiermap(const_cast<XModifierKeymap*>(modmap));
+}
+#endif // NOCLOBBER
+  
+unsigned int XDisplay::stripModifiers(const unsigned int state) const {
+#ifndef NOCLOBBER
+  return state &= ~(NumLockMask() | ScrollLockMask | LockMask);
+#else
+  return state &= ~LockMask;
+#endif
+}
+
+
+/*
+ * Verifies that a window has not requested to be destroyed/unmapped, so
+ * if it is a valid window or not.
+ * Returns: true if the window is valid; false if it is no longer valid.
+ */
+bool XDisplay::validateWindow(Window window) {
+  XEvent event;
+  if (XCheckTypedWindowEvent(_display, window, DestroyNotify, &event)) {
+    XPutBackEvent(display, &event);
+    return false;
+  }
+  return true;
+}
+
+
+/*
+ * Grabs a button, but also grabs the button in every possible combination with
+ * the keyboard lock keys, so that they do not cancel out the event.
+ */
+void BaseDisplay::grabButton(unsigned int button, unsigned int modifiers,
+                             Window grab_window, Bool owner_events,
+                             unsigned int event_mask, int pointer_mode,
+                             int keybaord_mode, Window confine_to,
+                             Cursor cursor) const
+{
+#ifndef   NOCLOBBER
+  for (size_t cnt = 0; cnt < 8; ++cnt)
+    XGrabButton(_display, button, modifiers | MaskList[cnt], grab_window,
+                owner_events, event_mask, pointer_mode, keybaord_mode,
+                confine_to, cursor);
+#else  // NOCLOBBER
+  XGrabButton(_display, button, modifiers, grab_window,
+              owner_events, event_mask, pointer_mode, keybaord_mode,
+              confine_to, cursor);
+#endif // NOCLOBBER
+}
+
+
+/*
+ * Releases the grab on a button, and ungrabs all possible combinations of the
+ * keyboard lock keys.
+ */
+void BaseDisplay::ungrabButton(unsigned int button, unsigned int modifiers,
+                               Window grab_window) const {
+#ifndef   NOCLOBBER
+  for (size_t cnt = 0; cnt < 8; ++cnt)
+    XUngrabButton(display, button, modifiers | MaskList[cnt], grab_window);
+#else  // NOCLOBBER
+  XUngrabButton(display, button, modifiers, grab_window);
+#endif // NOCLOBBER
+}
This page took 0.023456 seconds and 4 git commands to generate.