]> Dogcows Code - chaz/openbox/blobdiff - util/epist/window.cc
add manpages for epist and for xftlsfonts
[chaz/openbox] / util / epist / window.cc
index aca644c3630056ea70de6c9d76977b9060817d7e..48df206c989b9c9dc18319fe4ae5e643e666e1bc 100644 (file)
@@ -1,5 +1,5 @@
 // -*- mode: C++; indent-tabs-mode: nil; -*-
-// window.cc for Epistophy - a key handler for NETWM/EWMH window managers.
+// window.cc for Epistrophy - a key handler for NETWM/EWMH window managers.
 // Copyright (c) 2002 - 2002 Ben Jansens <ben at orodu.net>
 //
 // Permission is hereby granted, free of charge, to any person obtaining a
@@ -43,6 +43,10 @@ XWindow::XWindow(epist *epist, screen *screen, Window window)
 
   XSelectInput(_epist->getXDisplay(), _window,
                PropertyChangeMask | StructureNotifyMask);
+
+  updateNormalHints();
+  updateWMHints();
+  updateDimentions();
   updateState();
   updateDesktop();
   updateTitle();
@@ -59,6 +63,58 @@ XWindow::~XWindow() {
 }
 
 
+void XWindow::updateDimentions() {
+  Window root, child;
+  int x, y;
+  unsigned int w, h, b, d;
+
+  if (XGetGeometry(_epist->getXDisplay(), _window, &root, &x, &y, &w, &h,
+                     &b, &d) &&
+      XTranslateCoordinates(_epist->getXDisplay(), _window, root, x, y,
+                            &x, &y, &child))
+    _rect.setRect(x, y, w, h);
+  else
+    _rect.setRect(0, 0, 1, 1);
+}
+
+
+void XWindow::updateNormalHints() {
+  XSizeHints size;
+  long ret;
+
+  // defaults
+  _gravity = NorthWestGravity;
+  _inc_x = _inc_y = 1;
+  _base_x = _base_y = 0;
+  
+  if (XGetWMNormalHints(_epist->getXDisplay(), _window, &size, &ret)) {
+    if (size.flags & PWinGravity)
+      _gravity = size.win_gravity;
+    if (size.flags & PBaseSize) {
+      _base_x = size.base_width;
+      _base_y = size.base_height;
+    }
+    if (size.flags & PResizeInc) {
+      _inc_x = size.width_inc;
+      _inc_y = size.height_inc;
+    }
+  }
+}
+
+
+void XWindow::updateWMHints() {
+  XWMHints *hints;
+
+  if ((hints = XGetWMHints(_epist->getXDisplay(), _window)) != NULL) {
+    _can_focus = hints->input;
+    XFree(hints);
+  } else {
+    // assume a window takes input if it doesnt specify
+    _can_focus = True;
+  }
+}
+
+
 void XWindow::updateState() {
   // set the defaults
   _shaded = _iconic = _max_vert = _max_horz = false;
@@ -123,9 +179,15 @@ void XWindow::processEvent(const XEvent &e) {
   assert(e.xany.window == _window);
 
   switch (e.type) {
+  case ConfigureNotify:
+    updateDimentions();
+    break;
   case PropertyNotify:
-    // a client window
-    if (e.xproperty.atom == _xatom->getAtom(XAtom::net_wm_state))
+    if (e.xproperty.atom == XA_WM_NORMAL_HINTS)
+      updateNormalHints();
+    if (e.xproperty.atom == XA_WM_HINTS)
+      updateWMHints();
+    else if (e.xproperty.atom == _xatom->getAtom(XAtom::net_wm_state))
       updateState();
     else if (e.xproperty.atom == _xatom->getAtom(XAtom::net_wm_desktop))
       updateDesktop();
@@ -143,26 +205,58 @@ void XWindow::processEvent(const XEvent &e) {
 }
 
 
-void XWindow::findFramePosition(int &x, int &y) const {
+void XWindow::shade(const bool sh) const {
+  _xatom->sendClientMessage(_screen->rootWindow(), XAtom::net_wm_state,
+                            _window, (sh ? 1 : 0),
+                            _xatom->getAtom(XAtom::net_wm_state_shaded));
+}
+
+
+void XWindow::close() const {
+  _xatom->sendClientMessage(_screen->rootWindow(), XAtom::net_close_window,
+                            _window);
+}
+
+
+void XWindow::raise() const {
+  XRaiseWindow(_epist->getXDisplay(), _window);
+}
+
+
+void XWindow::lower() const {
+  XLowerWindow(_epist->getXDisplay(), _window);
+}
+
+
+void XWindow::iconify() const {
+  _xatom->sendClientMessage(_screen->rootWindow(), XAtom::wm_change_state,
+                            _window, IconicState);
+}
+
+
+void XWindow::focus() const {
+  // this will cause the window to be uniconified also
+  _xatom->sendClientMessage(_screen->rootWindow(), XAtom::net_active_window,
+                            _window);
+  //XSetInputFocus(_epist->getXDisplay(), _window, None, CurrentTime);
+}
+
+
+void XWindow::sendTo(unsigned int dest) const {
+  _xatom->sendClientMessage(_screen->rootWindow(), XAtom::net_wm_desktop,
+                            _window, dest);
+}
+
+
+void XWindow::move(int x, int y) const {
+  // get the window's decoration sizes (margins)
+  Strut margins;
   Window win = _window, parent, root, last = None;
   Window *children = 0;
   unsigned int nchildren;
-  int gravity, top, bottom, left, right;
   XWindowAttributes wattr;
-  XSizeHints size;
-  long ret;
-  unsigned int cwidth, cheight;
   
-  // get the location, size and gravity of the client window
-  if (! XGetWindowAttributes(_epist->getXDisplay(), _window, &wattr)) return;
-  cwidth = wattr.width;
-  cheight = wattr.height;
-  if (! XGetWMNormalHints(_epist->getXDisplay(), _window, &size, &ret)) return;
-  if (size.flags & PWinGravity)
-    gravity = size.win_gravity;
-  else
-    gravity = NorthWestGravity;
-    
   while (XQueryTree(_epist->getXDisplay(), win, &root, &parent, &children,
                     &nchildren)) {
     if (children && nchildren > 0)
@@ -180,114 +274,101 @@ void XWindow::findFramePosition(int &x, int &y) const {
   }
 
   if (! (XTranslateCoordinates(_epist->getXDisplay(), last, win, 0, 0,
-                               &left, &top, &parent) &&
+                               (int *) &margins.left,
+                               (int *) &margins.top,
+                               &parent) &&
          XGetWindowAttributes(_epist->getXDisplay(), win, &wattr)))
     return;
 
-  right = wattr.width - cwidth - left;
-  bottom = wattr.height - cheight - top;
+  margins.right = wattr.width - _rect.width() - margins.left;
+  margins.bottom = wattr.height - _rect.height() - margins.top;
 
-  left += wattr.border_width;
-  right += wattr.border_width;
-  top += wattr.border_width;
-  bottom += wattr.border_width;
-
-  // find the client's location
-  x = wattr.x + left;
-  y = wattr.y + top;
+  margins.left += wattr.border_width;
+  margins.right += wattr.border_width;
+  margins.top += wattr.border_width;
+  margins.bottom += wattr.border_width;
 
   // this makes things work. why? i don't know. but you need them.
-  right -= 2;
-  bottom -= 2;
-
+  margins.right -= 2;
+  margins.bottom -= 2;
+  
   // find the frame's reference position based on the window's gravity
-  switch (gravity) {
+  switch (_gravity) {
   case NorthWestGravity:
-    x -= left;
-    y -= top;
+    x -= margins.left;
+    y -= margins.top;
     break;
   case NorthGravity:
-    x += (left + right) / 2;
-    y -= top;
+    x += (margins.left + margins.right) / 2;
+    y -= margins.top;
     break;
   case NorthEastGravity:
-    x += right;
-    y -= top;
+    x += margins.right;
+    y -= margins.top;
   case WestGravity:
-    x -= left;
-    y += (top + bottom) / 2;
+    x -= margins.left;
+    y += (margins.top + margins.bottom) / 2;
     break;
   case CenterGravity:
-    x += (left + right) / 2;
-    y += (top + bottom) / 2;
+    x += (margins.left + margins.right) / 2;
+    y += (margins.top + margins.bottom) / 2;
     break;
   case EastGravity:
-    x += right;
-    y += (top + bottom) / 2;
+    x += margins.right;
+    y += (margins.top + margins.bottom) / 2;
   case SouthWestGravity:
-    x -= left;
-    y += bottom;
+    x -= margins.left;
+    y += margins.bottom;
     break;
   case SouthGravity:
-    x += (left + right) / 2;
-    y += bottom;
+    x += (margins.left + margins.right) / 2;
+    y += margins.bottom;
     break;
   case SouthEastGravity:
-    x += right;
-    y += bottom;
+    x += margins.right;
+    y += margins.bottom;
     break;
   default:
     break;
   }
+  
+  XMoveWindow(_epist->getXDisplay(), _window, x, y);
 }
 
 
-void XWindow::shade(const bool sh) const {
-  _xatom->sendClientMessage(_screen->rootWindow(), XAtom::net_wm_state,
-                            _window, (sh ? 1 : 0),
-                            _xatom->getAtom(XAtom::net_wm_state_shaded));
-}
-
-
-void XWindow::close() const {
-  _xatom->sendClientMessage(_screen->rootWindow(), XAtom::net_close_window,
-                            _window);
-}
-
-
-void XWindow::raise() const {
-  XRaiseWindow(_epist->getXDisplay(), _window);
-}
-
-
-void XWindow::lower() const {
-  XLowerWindow(_epist->getXDisplay(), _window);
-}
-
-
-void XWindow::iconify() const {
-  _xatom->sendClientMessage(_screen->rootWindow(), XAtom::wm_change_state,
-                            _window, IconicState);
-}
-
+void XWindow::resizeRel(int dwidth, int dheight) const {
+  // resize in increments if requested by the window
+  unsigned int width = _rect.width(), height = _rect.height();
+  
+  unsigned int wdest = width + (dwidth * _inc_x) / _inc_x * _inc_x + _base_x;
+  unsigned int hdest = height + (dheight * _inc_y) / _inc_y * _inc_y + _base_y;
 
-void XWindow::focus() const {
-  // this will also unshade the window..
-  _xatom->sendClientMessage(_screen->rootWindow(), XAtom::net_active_window,
-                            _window);
+  XResizeWindow(_epist->getXDisplay(), _window, wdest, hdest);
 }
 
 
-void XWindow::sendTo(unsigned int dest) const {
-  _xatom->sendClientMessage(_screen->rootWindow(), XAtom::net_wm_desktop,
-                            _window, dest);
-}
+void XWindow::resizeAbs(unsigned int width, unsigned int height) const {
+  // resize in increments if requested by the window
 
+  unsigned int wdest = width / _inc_x * _inc_x + _base_x;
+  unsigned int hdest = height / _inc_y * _inc_y + _base_y;
 
-void XWindow::move(int x, int y) const {
-  int fx, fy;
-  findFramePosition(fx, fy);
-  XMoveWindow(_epist->getXDisplay(), _window, fx + x, fy + y);
+  if (width > wdest) {
+    while (width > wdest)
+      wdest += _inc_x;
+  } else {
+    while (width < wdest)
+      wdest -= _inc_x;
+  }
+  if (height > hdest) {
+    while (height > hdest)
+      hdest += _inc_y;
+  } else {
+    while (height < hdest)
+      hdest -= _inc_y;
+  }
+  
+  XResizeWindow(_epist->getXDisplay(), _window, wdest, hdest);
 }
 
 
This page took 0.032663 seconds and 4 git commands to generate.