"Fossies" - the Fresh Open Source Software Archive

Member "bbkeys-0.9.1/src/window.cc" (6 Dec 2007, 15821 Bytes) of package /linux/privat/old/bbkeys-0.9.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "window.cc" see the Fossies "Dox" file reference documentation.

    1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
    2 // window.cc for Epistrophy - a key handler for NETWM/EWMH window managers.
    3 // Copyright (c) 2002 - 2002 Ben Jansens <ben at orodu.net>
    4 //
    5 // Modified for use and inclusion in bbkeys by Jason 'vanRijn' Kasper
    6 //
    7 // Permission is hereby granted, free of charge, to any person obtaining a
    8 // copy of this software and associated documentation files (the "Software"),
    9 // to deal in the Software without restriction, including without limitation
   10 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
   11 // and/or sell copies of the Software, and to permit persons to whom the
   12 // Software is furnished to do so, subject to the following conditions:
   13 //
   14 // The above copyright notice and this permission notice shall be included in
   15 // all copies or substantial portions of the Software.
   16 //
   17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
   20 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   22 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   23 // DEALINGS IN THE SOFTWARE.
   24 
   25 #include <iostream>
   26 
   27 using std::cout;
   28 using std::endl;
   29 
   30 #include "window.hh"
   31 
   32 // defined by black/openbox
   33 const unsigned long XWindow::PropBlackboxAttributesElements;
   34 const unsigned long XWindow::AttribDecoration;
   35 const unsigned long XWindow::DecorNone;
   36 const unsigned long XWindow::DecorNormal;
   37 
   38 
   39 XWindow::XWindow(Window window, Netclient * netclient,
   40                  const bt::ScreenInfo & screenInfo, bt::Application & app)
   41   : _window(window), _netclient(netclient), _screenInfo(screenInfo),
   42     _app(app) {
   43 
   44   _unmapped = false;
   45 
   46   _display=_screenInfo.display().XDisplay();
   47   _root = _screenInfo.rootWindow();
   48 
   49   XSelectInput(_display, _window,
   50                PropertyChangeMask | StructureNotifyMask);
   51 
   52   // add an event handler for our window
   53   _app.insertEventHandler(_window, this);
   54 
   55   updateBlackboxAttributes();
   56   updateNormalHints();
   57   updateWMHints();
   58   updateMotifHints();
   59   updateDimensions();
   60   updateState();
   61   updateDesktop();
   62   updateTitle();
   63   updateClass();
   64 
   65 }
   66 
   67 
   68 XWindow::~XWindow() {
   69   if (! _unmapped)
   70     XSelectInput(_display, _window, None);
   71 
   72   // tell our main app about our death
   73   _app.removeEventHandler( _window );
   74 }
   75 
   76 // Window configure (size, position, stacking, etc.).
   77 void XWindow::configureNotifyEvent(const XConfigureEvent * const e) {
   78   updateDimensions();
   79 }
   80 
   81 // Window property changed/added/deleted.
   82 void XWindow::propertyNotifyEvent(const XPropertyEvent * const e) {
   83 
   84   if (e->atom == XA_WM_NORMAL_HINTS)
   85     updateNormalHints();
   86   else if (e->atom == XA_WM_HINTS)
   87     updateWMHints();
   88   else if (e->atom == _netclient->xaBlackboxAttributes())
   89     updateBlackboxAttributes();
   90   else if (e->atom == _netclient->wmState() )
   91     updateState();
   92   else if (e->atom == _netclient->wmDesktop() )
   93     updateDesktop();
   94   else if (e->atom == _netclient->wmName() ||
   95            e->atom == _netclient->xaWmName() )
   96     updateTitle();
   97   else if (e->atom == _netclient->xaWmClass() )
   98     updateClass();
   99   else if (e->atom == _netclient->xaMotifWmHints() )
  100     updateMotifHints();
  101 }
  102 
  103 // Window hidden.
  104 void XWindow::unmapNotifyEvent(const XUnmapEvent * const e) {
  105   _unmapped = true;
  106 }
  107 
  108 // Window destroyed.
  109 void XWindow::destroyNotifyEvent(const XDestroyWindowEvent * const e) {
  110   _unmapped = true;
  111 }
  112 
  113 void XWindow::updateDimensions(const XConfigureEvent * const e) {
  114   _rect.setRect(e->x, e->y, e->width, e->height);
  115 }
  116 
  117 void XWindow::updateDimensions() {
  118 
  119   XWindowAttributes win_attributes;
  120   Window junkwin;
  121   int rx, ry;
  122 
  123   _rect.setRect(0,0,1,1);
  124 
  125   if (! XGetWindowAttributes(_display, _window, &win_attributes)) {
  126     std::cerr << BBTOOL << ": " << "updateDimensions. couldn't get what I needed, so setting to ridiculously wrong values.\n";
  127     return;
  128   }
  129 
  130   XTranslateCoordinates (_display, _window, win_attributes.root,
  131                          -win_attributes.border_width,
  132                          -win_attributes.border_width,
  133                          &rx, &ry, &junkwin);
  134   _rect.setRect(rx, ry, win_attributes.width, win_attributes.height);
  135 
  136 }
  137 
  138 void XWindow::updateBlackboxAttributes() {
  139   unsigned long *data;
  140   unsigned long num = PropBlackboxAttributesElements;
  141 
  142   _decorated = true;
  143 
  144   if (_netclient->getValue(_window,
  145                            _netclient->xaBlackboxAttributes(),
  146                            _netclient->xaBlackboxAttributes(),
  147                            num, &data)) {
  148     if (num == PropBlackboxAttributesElements)
  149       if (data[0] & AttribDecoration)
  150         _decorated = (data[4] != DecorNone);
  151     delete data;
  152   }
  153 }
  154 
  155 void XWindow::updateNormalHints() {
  156   XSizeHints size;
  157   long ret;
  158 
  159   // defaults
  160   _gravity = NorthWestGravity;
  161   _inc_x = _inc_y = 1;
  162   _base_x = _base_y = 0;
  163 
  164   if (XGetWMNormalHints(_display, _window, &size, &ret)) {
  165     if (size.flags & PWinGravity)
  166       _gravity = size.win_gravity;
  167     if (size.flags & PBaseSize) {
  168       _base_x = size.base_width;
  169       _base_y = size.base_height;
  170     }
  171     if (size.flags & PResizeInc) {
  172       _inc_x = size.width_inc;
  173       _inc_y = size.height_inc;
  174     }
  175   }
  176 }
  177 
  178 
  179 void XWindow::updateMotifHints() {
  180 
  181 // copied straight from blackbox's Window.cc, but hopefully nyz will move
  182 // this somewhere shareable....  =:D
  183 
  184   /*
  185     this structure only contains 3 elements, even though the Motif 2.0
  186     structure contains 5, because we only use the first 3
  187   */
  188   struct PropMotifhints {
  189     unsigned long flags;
  190     unsigned long functions;
  191     unsigned long decorations;
  192   };
  193   static const unsigned int PROP_MWM_HINTS_ELEMENTS = 3u;
  194   enum { // MWM flags
  195     MWM_HINTS_FUNCTIONS   = 1<<0,
  196     MWM_HINTS_DECORATIONS = 1<<1
  197   };
  198   enum { // MWM functions
  199     MWM_FUNC_ALL      = 1<<0,
  200     MWM_FUNC_RESIZE   = 1<<1,
  201     MWM_FUNC_MOVE     = 1<<2,
  202     MWM_FUNC_MINIMIZE = 1<<3,
  203     MWM_FUNC_MAXIMIZE = 1<<4,
  204     MWM_FUNC_CLOSE    = 1<<5
  205   };
  206   enum { // MWM decorations
  207     MWM_DECOR_ALL      = 1<<0,
  208     MWM_DECOR_BORDER   = 1<<1,
  209     MWM_DECOR_RESIZEH  = 1<<2,
  210     MWM_DECOR_TITLE    = 1<<3,
  211     MWM_DECOR_MENU     = 1<<4,
  212     MWM_DECOR_MINIMIZE = 1<<5,
  213     MWM_DECOR_MAXIMIZE = 1<<6
  214   };
  215 
  216   Atom atom_return;
  217   PropMotifhints *prop = 0;
  218   int format;
  219   unsigned long num, len;
  220   int ret = XGetWindowProperty(_display, _window,
  221                                _netclient->xaMotifWmHints(), 0,
  222                                PROP_MWM_HINTS_ELEMENTS, False,
  223                                _netclient->xaMotifWmHints(), &atom_return,
  224                                &format, &num, &len,
  225                                (unsigned char **) &prop);
  226 
  227   if (ret != Success || !prop || num != PROP_MWM_HINTS_ELEMENTS) {
  228     if (prop) XFree(prop);
  229     return;
  230   }
  231 
  232   if (prop->flags & MWM_HINTS_DECORATIONS) {
  233     if (prop->decorations & MWM_DECOR_ALL) {
  234       _decorated = true;
  235     } else {
  236       _decorated = false;
  237     }
  238   }
  239 
  240   XFree(prop);
  241 
  242 
  243 }
  244 
  245 void XWindow::updateWMHints() {
  246   XWMHints *hints;
  247 
  248   // assume a window takes input if it doesnt specify
  249   _can_focus = True;
  250 
  251   if ((hints = XGetWMHints(_display, _window)) != NULL) {
  252     if (hints->flags & InputHint)
  253       _can_focus = hints->input;
  254     XFree(hints);
  255   }
  256 }
  257 
  258 
  259 void XWindow::updateState() {
  260   // set the defaults
  261   _shaded = _skip_pager = _iconic = _max_vert = _max_horz = false;
  262 
  263   unsigned long num = (unsigned) -1;
  264   Atom *state;
  265   if (! _netclient->getValue(_window, _netclient->wmState(), XA_ATOM,
  266                              num, &state))
  267     return;
  268   for (unsigned long i = 0; i < num; ++i) {
  269     if (state[i] == _netclient->wmStateMaximizedVert())
  270       _max_vert = true;
  271     if (state[i] == _netclient->wmStateMaximizedHorz())
  272       _max_horz = true;
  273     if (state[i] == _netclient->wmStateShaded())
  274       _shaded = true;
  275     if (state[i] == _netclient->wmStateHidden())
  276       _iconic = true;
  277     if (state[i] == _netclient->wmStateSkipPager())
  278       _skip_pager = true;
  279   }
  280 
  281   delete [] state;
  282 }
  283 
  284 
  285 void XWindow::updateDesktop() {
  286   unsigned long d = 0ul;
  287   if (! _netclient->getValue(_window, _netclient->wmDesktop(), XA_CARDINAL, d))
  288     d = 0ul;
  289 
  290   _desktop = static_cast<unsigned int>(d);
  291 
  292 }
  293 
  294 
  295 void XWindow::updateTitle() {
  296   _title = bt::toUnicode("");
  297 
  298   // try netwm
  299   std::string s;
  300   if (_netclient->getValue(_window, _netclient->wmName(),
  301                            Netclient::utf8, s)) {
  302     _title = bt::toUtf32(s);
  303   } else {
  304     // try old x stuff
  305     if (_netclient->getValue(_window, XA_WM_NAME, Netclient::ansi, s))
  306       _title = bt::toUnicode(s);
  307   }
  308 
  309   if (_title.empty())
  310     _title = bt::toUnicode("Unnamed");
  311 
  312 }
  313 
  314 
  315 void XWindow::updateClass() {
  316   // set the defaults
  317   _app_name = _app_class = "";
  318 
  319   Netclient::StringVect v;
  320   unsigned long num = 2;
  321 
  322   if (! _netclient->getValue(_window, XA_WM_CLASS, Netclient::ansi, num, v))
  323     return;
  324 
  325   if (num > 0) _app_name = v[0];
  326   if (num > 1) _app_class = v[1];
  327 }
  328 
  329 
  330 
  331 void XWindow::shade(const bool sh) const {
  332   _netclient->sendClientMessage(_root, _netclient->wmState(),
  333                                 _window, (sh ? 1 : 0),
  334                                 _netclient->wmStateShaded());
  335 }
  336 
  337 void XWindow::close() const {
  338   _netclient->sendClientMessage(_root, _netclient->closeWindow(),
  339                                 _window);
  340 }
  341 
  342 
  343 void XWindow::raise() const {
  344   XRaiseWindow(_display, _window);
  345 }
  346 
  347 void XWindow::lower() const {
  348   XLowerWindow(_display, _window);
  349 }
  350 
  351 void XWindow::iconify() const {
  352   _netclient->sendClientMessage(_root, _netclient->xaWmChangeState(),
  353                                 _window, IconicState);
  354 }
  355 
  356 void XWindow::focus(bool raise) const {
  357   // this will cause the window to be uniconified also
  358 
  359   if (raise) {
  360     _netclient->sendClientMessage(_root, _netclient->activeWindow(),
  361                                   _window);
  362   } else {
  363     XSetInputFocus(_display, _window, None, CurrentTime);
  364   }
  365 }
  366 
  367 void XWindow::decorate(bool d) const {
  368 
  369   // YAY trolltech!!!  =:)
  370   // http://lists.trolltech.com/qt-interest/1999-06/thread00047-0.html
  371   long prop[5] = {2, 1, 1, 0, 0};
  372 
  373   if (_decorated)
  374           prop[2] = 0;
  375   else
  376           prop[2] = 1;
  377 
  378   XChangeProperty(_display, _window,
  379     _netclient->xaMotifWmHints(),
  380     _netclient->xaMotifWmHints(),
  381     32, 0, (unsigned char *) prop, 5);
  382 }
  383 
  384 void XWindow::sendTo(unsigned int dest) const {
  385   _netclient->sendClientMessage(_root, _netclient->wmDesktop(),
  386                                 _window, dest);
  387 }
  388 
  389 
  390 void XWindow::move(int x, int y) const {
  391 
  392   XWindowAttributes win_attributes;
  393   Window junkwin;
  394   int rx, ry;
  395 
  396 
  397   if (! XGetWindowAttributes(_display, _window, &win_attributes)) {
  398     std::cerr << BBTOOL << ": " << "move: couldn't get what I needed. not able to move, sorry.\n";
  399     return;
  400   }
  401 
  402   XTranslateCoordinates (_display, _window, win_attributes.root,
  403                          -win_attributes.border_width,
  404                          -win_attributes.border_width,
  405                          &rx, &ry, &junkwin);
  406 
  407   Status status;
  408   int xright, ybelow;
  409   int dw = _screenInfo.width(), dh = _screenInfo.height();
  410 
  411 
  412   /* find our window manager frame, if any */
  413   Window wmframe = _window;
  414 
  415   while (True) {
  416     Window root, parent;
  417     Window *childlist;
  418     unsigned int ujunk;
  419 
  420     status = XQueryTree(_display, wmframe, &root, &parent, &childlist, &ujunk);
  421     if (parent == root || !parent || !status)
  422       break;
  423     wmframe = parent;
  424     if (status && childlist)
  425       XFree((char *)childlist);
  426   }
  427 
  428   if (wmframe != _window) {
  429     /* WM reparented, so find edges of the frame */
  430     /* Only works for ICCCM-compliant WMs, and then only if the
  431        window has corner gravity.  We would need to know the original width
  432        of the window to correctly handle the other gravities. */
  433 
  434     XWindowAttributes frame_attr;
  435 
  436     if (!XGetWindowAttributes(_display, wmframe, &frame_attr)) {
  437       std::cerr << BBTOOL << ": " << "updateDimensions. error. can't get frame attributes.\n";
  438     }
  439 
  440     switch (_gravity) {
  441     case NorthWestGravity: case SouthWestGravity:
  442     case NorthEastGravity: case SouthEastGravity:
  443     case WestGravity:
  444       rx = frame_attr.x;
  445     }
  446     switch (_gravity) {
  447     case NorthWestGravity: case SouthWestGravity:
  448     case NorthEastGravity: case SouthEastGravity:
  449     case EastGravity:
  450       xright = dw - frame_attr.x - frame_attr.width -
  451         2*frame_attr.border_width;
  452     }
  453     switch (_gravity) {
  454     case NorthWestGravity: case SouthWestGravity:
  455     case NorthEastGravity: case SouthEastGravity:
  456     case NorthGravity:
  457       ry = frame_attr.y;
  458     }
  459     switch (_gravity) {
  460     case NorthWestGravity: case SouthWestGravity:
  461     case NorthEastGravity: case SouthEastGravity:
  462     case SouthGravity:
  463       ybelow = dh - frame_attr.y - frame_attr.height -
  464         2*frame_attr.border_width;
  465     }
  466   }
  467 
  468   int destx = rx +x, desty = ry +y;
  469 
  470   XMoveWindow(_display, _window, destx, desty);
  471 
  472 }
  473 
  474 
  475 void XWindow::resizeRel(int dwidth, int dheight) const {
  476   // resize in increments if requested by the window
  477   unsigned int width = _rect.width(), height = _rect.height();
  478 
  479   unsigned int wdest = width + (dwidth * _inc_x) / _inc_x * _inc_x + _base_x;
  480   unsigned int hdest = height + (dheight * _inc_y) / _inc_y * _inc_y + _base_y;
  481 
  482   XResizeWindow(_display, _window, wdest, hdest);
  483 }
  484 
  485 
  486 void XWindow::resizeAbs(unsigned int width, unsigned int height) const {
  487   // resize in increments if requested by the window
  488 
  489   unsigned int wdest = width / _inc_x * _inc_x + _base_x;
  490   unsigned int hdest = height / _inc_y * _inc_y + _base_y;
  491 
  492   if (width > wdest) {
  493     while (width > wdest)
  494       wdest += _inc_x;
  495   } else {
  496     while (width < wdest)
  497       wdest -= _inc_x;
  498   }
  499   if (height > hdest) {
  500     while (height > hdest)
  501       hdest += _inc_y;
  502   } else {
  503     while (height < hdest)
  504       hdest -= _inc_y;
  505   }
  506 
  507   XResizeWindow(_display, _window, wdest, hdest);
  508 }
  509 
  510 
  511 void XWindow::toggleMaximize(Max max) const {
  512   switch (max) {
  513   case Max_Full:
  514     _netclient->
  515       sendClientMessage(_root, _netclient->wmState(),
  516                         _window, (_max_vert == _max_horz ? 2 : 1),
  517                         _netclient->wmStateMaximizedHorz(),
  518                         _netclient->wmStateMaximizedVert());
  519     break;
  520 
  521   case Max_Horz:
  522     _netclient->
  523       sendClientMessage(_root, _netclient->wmState(),
  524                         _window, 2,
  525                         _netclient->wmStateMaximizedHorz());
  526     break;
  527 
  528   case Max_Vert:
  529     _netclient->
  530       sendClientMessage(_root, _netclient->wmState(),
  531                         _window, 2,
  532                         _netclient->wmStateMaximizedVert());
  533     break;
  534 
  535   case Max_None:
  536     assert(false);  // you should not do this. it is pointless and probly a bug
  537     break;
  538   }
  539 }
  540 
  541 
  542 void XWindow::maximize(Max max) const {
  543   switch (max) {
  544   case Max_None:
  545     _netclient->
  546       sendClientMessage(_root, _netclient->wmState(),
  547                         _window, 0,
  548                         _netclient->wmStateMaximizedHorz(),
  549                         _netclient->wmStateMaximizedVert());
  550     break;
  551 
  552   case Max_Full:
  553     _netclient->
  554       sendClientMessage(_root, _netclient->wmState(),
  555                         _window, 1,
  556                         _netclient->wmStateMaximizedHorz(),
  557                         _netclient->wmStateMaximizedVert());
  558     break;
  559 
  560   case Max_Horz:
  561     _netclient->
  562       sendClientMessage(_root, _netclient->wmState(),
  563                         _window, 1,
  564                         _netclient->wmStateMaximizedHorz());
  565     break;
  566 
  567   case Max_Vert:
  568     _netclient->
  569       sendClientMessage(_root, _netclient->wmState(),
  570                         _window, 1,
  571                         _netclient->wmStateMaximizedVert());
  572     break;
  573   }
  574 }
  575