]> Dogcows Code - chaz/openbox/blobdiff - src/client.cc
blef
[chaz/openbox] / src / client.cc
index 4e44d4bc9358794ec0cb3b6206b8acebd8023a59..b36ba9aff2a6fe9bdf701b5f1de4f848b7396f56 100644 (file)
@@ -47,7 +47,6 @@ Client::Client(int screen, Window window)
   // pick a layer to start from
   _layer = Layer_Normal;
   
-  getGravity();
   getArea();
   getDesktop();
 
@@ -61,6 +60,8 @@ Client::Client(int screen, Window window)
   getShaped();
 
   updateProtocols();
+  getGravity(); // get the attribute gravity
+  updateNormalHints(); // this may override the attribute gravity
   updateWMHints();
   updateTitle();
   updateIconTitle();
@@ -95,13 +96,13 @@ void Client::getGravity()
 {
   XWindowAttributes wattrib;
   Status ret;
-  
+
   ret = XGetWindowAttributes(**otk::display, _window, &wattrib);
   assert(ret != BadWindow);
-
   _gravity = wattrib.win_gravity;
 }
 
+
 void Client::getDesktop()
 {
   // defaults to the current desktop
@@ -167,15 +168,17 @@ void Client::getType()
 
 void Client::setupDecorAndFunctions()
 {
-  // start with everything
+  // start with everything (cept fullscreen)
   _decorations = Decor_Titlebar | Decor_Handle | Decor_Border |
     Decor_Iconify | Decor_Maximize;
-  _functions = Func_Resize | Func_Move | Func_Iconify | Func_Maximize;
+  _functions = Func_Resize | Func_Move | Func_Iconify | Func_Maximize |
+    Func_Shade;
   
   switch (_type) {
   case Type_Normal:
     // normal windows retain all of the possible decorations and
-    // functionality
+    // functionality, and are the only windows that you can fullscreen
+    _functions |= Func_Fullscreen;
 
   case Type_Dialog:
     // dialogs cannot be maximized
@@ -208,8 +211,11 @@ void Client::setupDecorAndFunctions()
         _decorations &= ~Decor_Border;
       if (! (_mwmhints.decorations & MwmDecor_Handle))
         _decorations &= ~Decor_Handle;
-      if (! (_mwmhints.decorations & MwmDecor_Title))
+      if (! (_mwmhints.decorations & MwmDecor_Title)) {
         _decorations &= ~Decor_Titlebar;
+        // if we don't have a titlebar, then we cannot shade!
+        _functions &= ~Func_Shade;
+      }
       if (! (_mwmhints.decorations & MwmDecor_Iconify))
         _decorations &= ~Decor_Iconify;
       if (! (_mwmhints.decorations & MwmDecor_Maximize))
@@ -233,7 +239,7 @@ void Client::setupDecorAndFunctions()
     }
   }
 
-  // XXX: changeAllowedActions();
+  changeAllowedActions();
 }
 
 
@@ -286,10 +292,9 @@ void Client::getState()
     for (unsigned long i = 0; i < num; ++i) {
       if (state[i] == otk::Property::atoms.net_wm_state_modal)
         _modal = true;
-      else if (state[i] == otk::Property::atoms.net_wm_state_shaded) {
+      else if (state[i] == otk::Property::atoms.net_wm_state_shaded)
         _shaded = true;
-        _wmstate = IconicState;
-      } else if (state[i] == otk::Property::atoms.net_wm_state_skip_taskbar)
+      else if (state[i] == otk::Property::atoms.net_wm_state_skip_taskbar)
         _skip_taskbar = true;
       else if (state[i] == otk::Property::atoms.net_wm_state_skip_pager)
         _skip_pager = true;
@@ -656,6 +661,7 @@ void Client::setDesktop(long target)
 void Client::setState(StateAction action, long data1, long data2)
 {
   bool shadestate = _shaded;
+  bool fsstate = _fullscreen;
 
   if (!(action == State_Add || action == State_Remove ||
         action == State_Toggle))
@@ -702,16 +708,13 @@ void Client::setState(StateAction action, long data1, long data2)
         _max_horz = true;
         // XXX: resize the window etc
       } else if (state == otk::Property::atoms.net_wm_state_shaded) {
-        if (_shaded) continue;
-        // shade when we're all thru here
         shadestate = true;
       } else if (state == otk::Property::atoms.net_wm_state_skip_taskbar) {
         _skip_taskbar = true;
       } else if (state == otk::Property::atoms.net_wm_state_skip_pager) {
         _skip_pager = true;
       } else if (state == otk::Property::atoms.net_wm_state_fullscreen) {
-        if (_fullscreen) continue;
-        _fullscreen = true;
+        fsstate = true;
       } else if (state == otk::Property::atoms.net_wm_state_above) {
         if (_above) continue;
         _above = true;
@@ -733,16 +736,13 @@ void Client::setState(StateAction action, long data1, long data2)
         _max_horz = false;
         // XXX: resize the window etc
       } else if (state == otk::Property::atoms.net_wm_state_shaded) {
-        if (!_shaded) continue;
-        // unshade when we're all thru here
         shadestate = false;
       } else if (state == otk::Property::atoms.net_wm_state_skip_taskbar) {
         _skip_taskbar = false;
       } else if (state == otk::Property::atoms.net_wm_state_skip_pager) {
         _skip_pager = false;
       } else if (state == otk::Property::atoms.net_wm_state_fullscreen) {
-        if (!_fullscreen) continue;
-        _fullscreen = false;
+        fsstate = false;
       } else if (state == otk::Property::atoms.net_wm_state_above) {
         if (!_above) continue;
         _above = false;
@@ -752,6 +752,10 @@ void Client::setState(StateAction action, long data1, long data2)
       }
     }
   }
+  // change fullscreen state before shading, as it will affect if the window
+  // can shade or not
+  if (fsstate != _fullscreen)
+    fullscreen(fsstate);
   if (shadestate != _shaded)
     shade(shadestate);
   calcLayer();
@@ -771,9 +775,6 @@ void Client::toggleClientBorder(bool addborder)
   case NorthWestGravity:
   case WestGravity:
   case SouthWestGravity:
-  case NorthGravity:
-  case CenterGravity:
-  case SouthGravity:
     break;
   case NorthEastGravity:
   case EastGravity:
@@ -781,6 +782,9 @@ void Client::toggleClientBorder(bool addborder)
     if (addborder) x -= _border_width * 2;
     else           x += _border_width * 2;
     break;
+  case NorthGravity:
+  case SouthGravity:
+  case CenterGravity:
   case ForgetGravity:
   case StaticGravity:
     if (addborder) x -= _border_width;
@@ -790,11 +794,8 @@ void Client::toggleClientBorder(bool addborder)
   switch(_gravity) {
   default:
   case NorthWestGravity:
-  case WestGravity:
   case NorthGravity:
-  case CenterGravity:
   case NorthEastGravity:
-  case EastGravity:
     break;
   case SouthWestGravity:
   case SouthGravity:
@@ -802,6 +803,9 @@ void Client::toggleClientBorder(bool addborder)
     if (addborder) y -= _border_width * 2;
     else           y += _border_width * 2;
     break;
+  case WestGravity:
+  case EastGravity:
+  case CenterGravity:
   case ForgetGravity:
   case StaticGravity:
     if (addborder) y -= _border_width;
@@ -900,7 +904,14 @@ void Client::shapeHandler(const XShapeEvent &e)
 #endif
 
 
-void Client::resize(Corner anchor, int w, int h, int x, int y)
+void Client::resize(Corner anchor, int w, int h)
+{
+  if (!(_functions & Func_Resize)) return;
+  internal_resize(anchor, w, h);
+}
+
+
+void Client::internal_resize(Corner anchor, int w, int h, int x, int y)
 {
   w -= _base_size.x(); 
   h -= _base_size.y();
@@ -962,11 +973,18 @@ void Client::resize(Corner anchor, int w, int h, int x, int y)
 
   // resize the frame to match the request
   frame->adjustSize();
-  move(x, y);
+  internal_move(x, y);
 }
 
 
 void Client::move(int x, int y)
+{
+  if (!(_functions & Func_Move)) return;
+  internal_move(x, y);
+}
+
+
+void Client::internal_move(int x, int y)
 {
   _area.setPos(x, y);
 
@@ -1057,9 +1075,63 @@ void Client::changeState()
 }
 
 
+void Client::changeAllowedActions(void)
+{
+  Atom actions[9];
+  int num = 0;
+
+  actions[num++] = otk::Property::atoms.net_wm_action_change_desktop;
+
+  if (_functions & Func_Shade)
+    actions[num++] = otk::Property::atoms.net_wm_action_shade;
+  if (_functions & Func_Close)
+    actions[num++] = otk::Property::atoms.net_wm_action_close;
+  if (_functions & Func_Move)
+    actions[num++] = otk::Property::atoms.net_wm_action_move;
+  if (_functions & Func_Iconify)
+    actions[num++] = otk::Property::atoms.net_wm_action_minimize;
+  if (_functions & Func_Resize)
+    actions[num++] = otk::Property::atoms.net_wm_action_resize;
+  if (_functions & Func_Fullscreen)
+    actions[num++] = otk::Property::atoms.net_wm_action_fullscreen;
+  if (_functions & Func_Maximize) {
+    actions[num++] = otk::Property::atoms.net_wm_action_maximize_horz;
+    actions[num++] = otk::Property::atoms.net_wm_action_maximize_vert;
+  }
+
+  otk::Property::set(_window, otk::Property::atoms.net_wm_allowed_actions,
+                     otk::Property::atoms.atom, actions, num);
+}
+
+
+void Client::applyStartupState()
+{
+  // these are in a carefully crafted order..
+  
+  if (_fullscreen) {
+    _fullscreen = false;
+    fullscreen(true);
+  }
+  if (_shaded) {
+    _shaded = false;
+    shade(true);
+  }
+  
+  if (_max_vert); // XXX: incomplete
+  if (_max_horz); // XXX: incomplete
+
+  if (_skip_taskbar); // nothing to do for this
+  if (_skip_pager);   // nothing to do for this
+  if (_modal);        // nothing to do for this
+  if (_above);        // nothing to do for this
+  if (_below);        // nothing to do for this
+}
+
+
 void Client::shade(bool shade)
 {
-  if (shade == _shaded) return; // already done
+  if (!(_functions & Func_Shade) || // can't
+      _shaded == shade) return;     // already done
 
   _wmstate = shade ? IconicState : NormalState;
   _shaded = shade;
@@ -1068,6 +1140,54 @@ void Client::shade(bool shade)
 }
 
 
+void Client::fullscreen(bool fs)
+{
+  static FunctionFlags saved_func;
+  static DecorationFlags saved_decor;
+  static otk::Rect saved_area;
+  static otk::Point saved_logical_size;
+
+  if (!(_functions & Func_Fullscreen) || // can't
+      _fullscreen == fs) return;         // already done
+
+  _fullscreen = fs;
+  changeState(); // change the state hints on the client
+
+  if (fs) {
+    // save the functions and remove them
+    saved_func = _functions;
+    _functions = _functions & (Func_Close | Func_Fullscreen | Func_Iconify);
+    // save the decorations and remove them
+    saved_decor = _decorations;
+    _decorations = 0;
+    // save the area and adjust it (we don't call internal resize here for
+    // constraints on the size, etc, we just make it fullscreen).
+    saved_area = _area;
+    const otk::ScreenInfo *info = otk::display->screenInfo(_screen);
+    _area.setRect(0, 0, info->width(), info->height());
+    saved_logical_size = _logical_size;
+    _logical_size.setPoint((info->width() - _base_size.x()) / _size_inc.x(),
+                           (info->height() - _base_size.y()) / _size_inc.y());
+  } else {
+    _functions = saved_func;
+    _decorations = saved_decor;
+    _area = saved_area;
+    _logical_size = saved_logical_size;
+  }
+  
+  changeAllowedActions();  // based on the new _functions
+  
+  frame->adjustSize();     // drop/replace the decor's and resize
+  frame->adjustPosition(); // get (back) in position!
+
+  // raise (back) into our stacking layer
+  openbox->screen(_screen)->raiseWindow(this);
+
+  // try focus us when we go into fullscreen mode
+  if (fs) focus();
+}
+
+
 bool Client::focus() const
 {
   // won't try focus if the client doesn't want it, or if the window isn't
@@ -1178,13 +1298,13 @@ void Client::configureRequestHandler(const XConfigureRequestEvent &e)
     if (e.value_mask & (CWX | CWY)) {
       int x = (e.value_mask & CWX) ? e.x : _area.x();
       int y = (e.value_mask & CWY) ? e.y : _area.y();
-      resize(corner, w, h, x, y);
+      internal_resize(corner, w, h, x, y);
     } else // if JUST resizing...
-      resize(corner, w, h);
+      internal_resize(corner, w, h);
   } else if (e.value_mask & (CWX | CWY)) { // if JUST moving...
     int x = (e.value_mask & CWX) ? e.x : _area.x();
     int y = (e.value_mask & CWY) ? e.y : _area.y();
-    move(x, y);
+    internal_move(x, y);
   }
 
   if (e.value_mask & CWStackMode) {
This page took 0.028418 seconds and 4 git commands to generate.