Sticky buttons patch

Scott Moynes smoynes at nexus.carleton.ca
Tue Aug 27 07:26:54 EDT 2002


Here's a patch that allows the user to add a sticky (or omnipresent)
button to their window title bars. It is still really rough and
probably has plenty of bugs in it, so finding those is left as an
exercise for the reader. Please tell me when you find them.

Obligatory screenshot:
http://nexus.carleton.ca/~smoynes/sticky-button.png

-- 
Scott Moynes
"Computer science is as much about computers
as astronomy is about telescopes." -- Dijkstra
-------------- next part --------------
? sticky-button-1.diff
cvs server: Diffing .
cvs server: Diffing autom4te.cache
cvs server: Diffing data
cvs server: Diffing data/styles
cvs server: Diffing doc
cvs server: Diffing nls
cvs server: Diffing nls/C
cvs server: Diffing nls/da_DK
cvs server: Diffing nls/de_DE
cvs server: Diffing nls/es_AR
cvs server: Diffing nls/es_ES
cvs server: Diffing nls/et_EE
cvs server: Diffing nls/fr_FR
cvs server: Diffing nls/hu_HU
cvs server: Diffing nls/it_IT
cvs server: Diffing nls/ja_JP
cvs server: Diffing nls/ko_KR
cvs server: Diffing nls/nl_NL
cvs server: Diffing nls/no_NO
cvs server: Diffing nls/pl_PL
cvs server: Diffing nls/pt_BR
cvs server: Diffing nls/ro_RO
cvs server: Diffing nls/ru_RU
cvs server: Diffing nls/sl_SI
cvs server: Diffing nls/sv_SE
cvs server: Diffing nls/tr_TR
cvs server: Diffing nls/uk_UA
cvs server: Diffing nls/zh_CN
cvs server: Diffing nls/zh_TW
cvs server: Diffing src
Index: src/Window.cc
===================================================================
RCS file: /cvs/cvsroot/openbox/src/Window.cc,v
retrieving revision 1.165
diff -p -u -r1.165 Window.cc
--- src/Window.cc	2002/08/26 23:52:37	1.165
+++ src/Window.cc	2002/08/27 04:08:44
@@ -128,7 +128,8 @@ BlackboxWindow::BlackboxWindow(Blackbox 
 
   frame.border_w = 1;
   frame.window = frame.plate = frame.title = frame.handle = None;
-  frame.close_button = frame.iconify_button = frame.maximize_button = None;
+  frame.close_button = frame.iconify_button = frame.maximize_button =
+    frame.stick_button = None;
   frame.right_grip = frame.left_grip = None;
 
   frame.ulabel_pixel = frame.flabel_pixel = frame.utitle_pixel =
@@ -719,6 +720,9 @@ void BlackboxWindow::destroyTitlebar(voi
   if (frame.maximize_button)
     destroyMaximizeButton();
 
+  if (frame.stick_button)
+    destroyStickyButton();
+  
   if (frame.ftitle)
     screen->getImageControl()->removeImage(frame.ftitle);
 
@@ -802,13 +806,28 @@ void BlackboxWindow::destroyMaximizeButt
   frame.maximize_button = None;
 }
 
+void BlackboxWindow::createStickyButton(void) {
+  if (frame.title != None) {
+    frame.stick_button = createChildWindow(frame.title,
+                                           ButtonPressMask |
+                                           ButtonReleaseMask |
+                                           ButtonMotionMask | ExposureMask);
+    blackbox->saveWindowSearch(frame.stick_button, this);
+  }
+}
+
+void BlackboxWindow::destroyStickyButton(void) {
+  blackbox->removeWindowSearch(frame.stick_button);
+  XDestroyWindow(blackbox->getXDisplay(), frame.stick_button);
+  frame.stick_button = None;
+}
 
 void BlackboxWindow::positionButtons(bool redecorate_label) {
   string layout = blackbox->getTitlebarLayout();
   string parsed;
 
-  bool hasclose, hasiconify, hasmaximize, haslabel;
-  hasclose = hasiconify = hasmaximize = haslabel = false;
+  bool hasclose, hasiconify, hasmaximize, haslabel, hasstick;
+  hasclose = hasiconify = hasmaximize = haslabel = hasstick = false;
 
   string::const_iterator it, end;
   for (it = layout.begin(), end = layout.end(); it != end; ++it) {
@@ -825,6 +844,12 @@ void BlackboxWindow::positionButtons(boo
         parsed += *it;
       }
       break;
+    case 'S':
+      if (!hasstick) {
+        hasstick = true;
+        parsed += *it;
+      }
+      break;
     case 'M':
       if (! hasmaximize && (decorations & Decor_Maximize)) {
         hasmaximize = true;
@@ -836,14 +861,18 @@ void BlackboxWindow::positionButtons(boo
         haslabel = true;
         parsed += *it;
       }
+      break;
     }
   }
+  
   if (! hasclose && frame.close_button)
     destroyCloseButton();
   if (! hasiconify && frame.iconify_button)
     destroyIconifyButton();
   if (! hasmaximize && frame.maximize_button)
     destroyMaximizeButton();
+  if (! hasstick && frame.stick_button)
+    destroyStickyButton();
   if (! haslabel)
     parsed += 'L';      // require that the label be in the layout
 
@@ -869,6 +898,12 @@ void BlackboxWindow::positionButtons(boo
                         frame.button_w, frame.button_w);
       x += frame.button_w + bsep;
       break;
+    case 'S':
+      if (! frame.stick_button) createStickyButton();
+      XMoveResizeWindow(blackbox->getXDisplay(), frame.stick_button, x, by,
+                        frame.button_w, frame.button_w);
+      x += frame.button_w + bsep;
+      break;
     case 'M':
       if (! frame.maximize_button) createMaximizeButton();
       XMoveResizeWindow(blackbox->getXDisplay(), frame.maximize_button, x, by,
@@ -2069,6 +2104,9 @@ void BlackboxWindow::stick(void) {
 
     setState(current_state);
   }
+
+  redrawAllButtons();
+  
   // go up the chain
   if (isTransient() && client.transient_for != (BlackboxWindow *) ~0ul &&
       client.transient_for->isStuck() != flags.stuck)
@@ -2534,6 +2572,7 @@ void BlackboxWindow::redrawAllButtons(vo
   if (frame.iconify_button) redrawIconifyButton(False);
   if (frame.maximize_button) redrawMaximizeButton(flags.maximized);
   if (frame.close_button) redrawCloseButton(False);
+  if (frame.stick_button) redrawStickyButton(flags.stuck);
 }
 
 
@@ -2643,6 +2682,40 @@ void BlackboxWindow::redrawCloseButton(b
 }
 
 
+void BlackboxWindow::redrawStickyButton(bool pressed) const {
+  if (! pressed) {
+    if (flags.focused) {
+      if (frame.fbutton)
+        XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
+                                   frame.stick_button, frame.fbutton);
+      else
+        XSetWindowBackground(blackbox->getXDisplay(), frame.stick_button,
+                             frame.fbutton_pixel);
+    } else {
+      if (frame.ubutton)
+        XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
+                                   frame.stick_button, frame.ubutton);
+      else
+        XSetWindowBackground(blackbox->getXDisplay(), frame.stick_button,
+                             frame.ubutton_pixel);
+    }
+  } else {
+    if (frame.pbutton)
+      XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
+                                 frame.stick_button, frame.pbutton);
+    else
+      XSetWindowBackground(blackbox->getXDisplay(), frame.stick_button,
+                           frame.pbutton_pixel);
+  }
+  XClearWindow(blackbox->getXDisplay(), frame.stick_button);
+
+  BPen pen((flags.focused) ? screen->getWindowStyle()->b_pic_focus :
+           screen->getWindowStyle()->b_pic_unfocus);
+  
+  XFillRectangle(blackbox->getXDisplay(), frame.stick_button, pen.gc(),
+                 frame.button_w/2 - 1, frame.button_w/2 -1, 2, 2 );
+}
+
 void BlackboxWindow::mapRequestEvent(const XMapRequestEvent *re) {
   if (re->window != client.window)
     return;
@@ -2857,6 +2930,8 @@ void BlackboxWindow::exposeEvent(const X
     redrawMaximizeButton(flags.maximized);
   else if (frame.iconify_button == ee->window)
     redrawIconifyButton(False);
+  else if (frame.stick_button == ee->window)
+    redrawStickyButton(flags.stuck);
 }
 
 
@@ -2950,6 +3025,8 @@ void BlackboxWindow::buttonPressEvent(co
       redrawIconifyButton(True);
     } else if (frame.close_button == be->window) {
       redrawCloseButton(True);
+    } else if (frame.stick_button == be->window) {
+      redrawStickyButton(True);
     } else if (frame.plate == be->window) {
       if (windowmenu && windowmenu->isVisible()) windowmenu->hide();
 
@@ -2973,7 +3050,8 @@ void BlackboxWindow::buttonPressEvent(co
       screen->getWorkspace(blackbox_attrib.workspace)->raiseWindow(this);
     }
   } else if (be->button == 2 && (be->window != frame.iconify_button) &&
-             (be->window != frame.close_button)) {
+             (be->window != frame.close_button) &&
+             (be->window != frame.stick_button)) {
     screen->getWorkspace(blackbox_attrib.workspace)->lowerWindow(this);
   } else if (windowmenu && be->button == 3 &&
              (frame.title == be->window || frame.label == be->window ||
@@ -3021,7 +3099,8 @@ void BlackboxWindow::buttonPressEvent(co
          be->window == frame.title ||
          be->window == frame.maximize_button ||
          be->window == frame.iconify_button ||
-         be->window == frame.close_button) &&
+         be->window == frame.close_button ||
+         be->window == frame.stick_button) &&
         ! flags.shaded)
       shade();
   // mouse wheel down
@@ -3030,7 +3109,8 @@ void BlackboxWindow::buttonPressEvent(co
          be->window == frame.title ||
          be->window == frame.maximize_button ||
          be->window == frame.iconify_button ||
-         be->window == frame.close_button) &&
+         be->window == frame.close_button ||
+         be->window == frame.stick_button) &&
         flags.shaded)
       shade();
   }
@@ -3057,6 +3137,13 @@ void BlackboxWindow::buttonReleaseEvent(
       iconify();
     } else {
       redrawIconifyButton(False);
+    }
+  } else if (re->window == frame.stick_button && re->button == 1) {
+    if ((re->x >= 0 && re->x <= static_cast<signed>(frame.button_w)) &&
+        (re->y >= 0 && re->y <= static_cast<signed>(frame.button_w))) {
+      stick();
+    } else {
+      redrawStickyButton(False);
     }
   } else if (re->window == frame.close_button & re->button == 1) {
     if ((re->x >= 0 && re->x <= static_cast<signed>(frame.button_w)) &&
Index: src/Window.hh
===================================================================
RCS file: /cvs/cvsroot/openbox/src/Window.hh,v
retrieving revision 1.24
diff -p -u -r1.24 Window.hh
--- src/Window.hh	2002/08/26 05:27:25	1.24
+++ src/Window.hh	2002/08/27 04:08:45
@@ -230,7 +230,7 @@ private:
       title,
       label,
       handle,
-      close_button, iconify_button, maximize_button,
+      close_button, iconify_button, maximize_button, stick_button,
       right_grip, left_grip;
 
     /*
@@ -285,12 +285,15 @@ private:
   void destroyIconifyButton(void);
   void createMaximizeButton(void);
   void destroyMaximizeButton(void);
+  void createStickyButton(void);
+  void destroyStickyButton(void);
   void redrawWindowFrame(void) const;
   void redrawLabel(void) const;
   void redrawAllButtons(void) const;
   void redrawCloseButton(bool pressed) const;
   void redrawIconifyButton(bool pressed) const;
   void redrawMaximizeButton(bool pressed) const;
+  void redrawStickyButton(bool pressed) const;
   void applyGravity(Rect &r);
   void restoreGravity(Rect &r);
   void setAllowedActions(void);
cvs server: Diffing util
cvs server: Diffing util/epist
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 240 bytes
Desc: not available
URL: <http://icculus.org/pipermail/openbox/attachments/20020827/9b83dcbd/attachment.pgp>


More information about the openbox mailing list