Bitmap buttons patch

Scott Moynes smoynes at nexus.carleton.ca
Fri Aug 30 00:49:28 EDT 2002


Here is my bitmap button patch, or as I like to call it bubby-buttons.

It is quite rough, and there's some things I'd like to fix up, but I
wanted some feedback.

Here's how it works:
 - new style/rcfile options have been added
       window.button.{close,max,icon,stick}_mask: filename
   Right now the filename has to be specified absolutely, but that
   will change. I don't know whether we should just use expandTilde()
   or make the filename relative to the style location.
- the files must be xbm files, which gimp can easily create, or if you
  really want to can be created with a simple text editor. I have a
  sample set at
  http://nexus.carleton.ca/~smoynes/{close,icon,stick,max}.xbm
  If there is any problem loading the file the old images are
  used. This allows users to override the stile with something like
  window.button.close_mask: false
  and they don't have to put up with some lame matrix theme buttons
- The images won't scale. Let me repeat that. The images won't
  scale. Nor are they likely ever going to. In my experimentation, I
  found the difference in size between the smallest title bar I'd ever
  consider using and the largest to be pretty small. It might be a
  problem across different machines, but it isn't difficult to scale
  them yourself with an image editor.

Here's a quick screenshot.
       http://nexus.carleton.ca/~smoynes/bubby-buttons.png
       
Any questions, comments or patches are welcome.
  
-- 
Scott Moynes
"Computer science is as much about computers
as astronomy is about telescopes." -- Dijkstra
-------------- next part --------------
? sticky-button-1.diff
Index: src/Screen.cc
===================================================================
RCS file: /cvs/cvsroot/openbox/src/Screen.cc,v
retrieving revision 1.138
diff -p -u -r1.138 Screen.cc
--- src/Screen.cc	2002/08/27 10:57:15	1.138
+++ src/Screen.cc	2002/08/30 04:45:48
@@ -339,6 +339,24 @@ BScreen::~BScreen(void) {
   if (resource.tstyle.font)
     delete resource.tstyle.font;
 
+  if (resource.wstyle.close_button.mask != None) {
+    XFreePixmap(blackbox->getXDisplay(), resource.wstyle.close_button.mask);
+  }
+  if (resource.wstyle.max_button.mask != None) {
+    XFreePixmap(blackbox->getXDisplay(), resource.wstyle.max_button.mask);
+  }
+  if (resource.wstyle.icon_button.mask != None) {
+    XFreePixmap(blackbox->getXDisplay(), resource.wstyle.icon_button.mask);
+  }
+  if (resource.wstyle.stick_button.mask != None) {
+    XFreePixmap(blackbox->getXDisplay(), resource.wstyle.stick_button.mask);
+  }
+
+  
+  resource.wstyle.max_button.mask = resource.wstyle.close_button.mask =
+    resource.wstyle.icon_button.mask =
+    resource.wstyle.stick_button.mask = None;
+
   XFreeGC(blackbox->getXDisplay(), opGC);
 }
 
@@ -975,6 +993,28 @@ void BScreen::LoadStyle(void) {
   resource.wstyle.b_pressed =
     readDatabaseTexture("window.button.pressed", "black", style);
 
+  if (resource.wstyle.close_button.mask != None)
+    XFreePixmap(blackbox->getXDisplay(), resource.wstyle.close_button.mask);
+  if (resource.wstyle.max_button.mask != None)
+    XFreePixmap(blackbox->getXDisplay(), resource.wstyle.max_button.mask);
+  if (resource.wstyle.icon_button.mask != None)
+    XFreePixmap(blackbox->getXDisplay(), resource.wstyle.icon_button.mask);
+  if (resource.wstyle.stick_button.mask != None)
+    XFreePixmap(blackbox->getXDisplay(), resource.wstyle.stick_button.mask);
+
+  resource.wstyle.close_button.mask = resource.wstyle.max_button.mask =
+    resource.wstyle.icon_button.mask =
+    resource.wstyle.icon_button.mask = None;
+  
+  readDatabaseMask("window.button.close_mask", resource.wstyle.close_button,
+                   style);
+  readDatabaseMask("window.button.max_mask", resource.wstyle.max_button,
+                   style);
+  readDatabaseMask("window.button.icon_mask", resource.wstyle.icon_button,
+                   style);
+  readDatabaseMask("window.button.stick_mask", resource.wstyle.stick_button,
+                   style);
+
   // we create the window.frame texture by hand because it exists only to
   // make the code cleaner and is not actually used for display
   BColor color = readDatabaseColor("window.frame.focusColor", "white", style);
@@ -2501,6 +2541,23 @@ void BScreen::toggleFocusModel(FocusMode
                 std::mem_fun(&BlackboxWindow::grabButtons));
 }
 
+void BScreen::readDatabaseMask(const string &rname, PixmapMask &pixmapMask,
+                               const Configuration &style) {
+  string s;
+  int hx, hy; //ignored
+  int ret;
+  if (style.getValue(rname, s))
+  {
+    ret = XReadBitmapFile(blackbox->getXDisplay(), getRootWindow(),
+                          s.c_str(), &pixmapMask.w, &pixmapMask.h,
+                          &pixmapMask.mask, &hx, &hy);
+    if (ret == BitmapSuccess)
+      return;
+  }
+
+  pixmapMask.mask = None;
+  pixmapMask.w = pixmapMask.h = 0;
+}
 
 BTexture BScreen::readDatabaseTexture(const string &rname,
                                       const string &default_color,
Index: src/Screen.hh
===================================================================
RCS file: /cvs/cvsroot/openbox/src/Screen.hh,v
retrieving revision 1.34
diff -p -u -r1.34 Screen.hh
--- src/Screen.hh	2002/08/22 03:46:45	1.34
+++ src/Screen.hh	2002/08/30 04:45:49
@@ -61,12 +61,19 @@ struct Strut;
 
 enum TextJustify { LeftJustify = 1, RightJustify, CenterJustify };
 
+struct PixmapMask {
+  Pixmap mask;
+  unsigned int w, h;
+};
+
 struct WindowStyle {
   BColor l_text_focus, l_text_unfocus, b_pic_focus,
     b_pic_unfocus;
   BTexture f_focus, f_unfocus, t_focus, t_unfocus, l_focus, l_unfocus,
     h_focus, h_unfocus, b_focus, b_unfocus, b_pressed, g_focus, g_unfocus;
 
+  PixmapMask close_button, max_button, icon_button, stick_button;
+
   BFont *font;
 
   TextJustify justify;
@@ -178,6 +185,9 @@ private:
 
   bool parseMenuFile(FILE *file, Rootmenu *menu);
 
+  void readDatabaseMask(const string &rname,
+                        PixmapMask &pixmapMask,
+                        const Configuration &style);
   BTexture readDatabaseTexture(const std::string &rname,
                                const std::string &default_color,
                                const Configuration &style);
Index: src/Window.cc
===================================================================
RCS file: /cvs/cvsroot/openbox/src/Window.cc,v
retrieving revision 1.168
diff -p -u -r1.168 Window.cc
--- src/Window.cc	2002/08/29 00:07:53	1.168
+++ src/Window.cc	2002/08/30 04:45:56
@@ -722,7 +722,7 @@ void BlackboxWindow::destroyTitlebar(voi
 
   if (frame.stick_button)
     destroyStickyButton();
-  
+
   if (frame.ftitle)
     screen->getImageControl()->removeImage(frame.ftitle);
 
@@ -2608,12 +2608,29 @@ void BlackboxWindow::redrawIconifyButton
       XSetWindowBackground(blackbox->getXDisplay(),
                            frame.iconify_button, frame.pbutton_pixel);
   }
-  XClearWindow(blackbox->getXDisplay(), frame.iconify_button);
 
+  XClearWindow(blackbox->getXDisplay(), frame.iconify_button);
   BPen pen((flags.focused) ? screen->getWindowStyle()->b_pic_focus :
-           screen->getWindowStyle()->b_pic_unfocus);
-  XDrawRectangle(blackbox->getXDisplay(), frame.iconify_button, pen.gc(),
-                 2, (frame.button_w - 5), (frame.button_w - 5), 2);
+             screen->getWindowStyle()->b_pic_unfocus);
+
+  PixmapMask pm = screen->getWindowStyle()->icon_button;
+  
+  if (screen->getWindowStyle()->icon_button.mask != None) {
+    XSetClipMask(blackbox->getXDisplay(), pen.gc(), pm.mask);
+    XSetClipOrigin(blackbox->getXDisplay(), pen.gc(),
+                   (frame.button_w - pm.w)/2, (frame.button_w - pm.h)/2);
+
+    XFillRectangle(blackbox->getXDisplay(), frame.iconify_button, pen.gc(),
+                   (frame.button_w - pm.w)/2, (frame.button_w - pm.h)/2,
+                   (frame.button_w + pm.w)/2, (frame.button_w + pm.h)/2);
+
+    XSetClipMask(blackbox->getXDisplay(), pen.gc(), None);
+    XSetClipOrigin(blackbox->getXDisplay(), pen.gc(), 0, 0);
+  } else {
+
+    XDrawRectangle(blackbox->getXDisplay(), frame.iconify_button, pen.gc(),
+                   2, (frame.button_w - 5), (frame.button_w - 5), 2);
+  }
 }
 
 
@@ -2646,10 +2663,26 @@ void BlackboxWindow::redrawMaximizeButto
 
   BPen pen((flags.focused) ? screen->getWindowStyle()->b_pic_focus :
            screen->getWindowStyle()->b_pic_unfocus);
-  XDrawRectangle(blackbox->getXDisplay(), frame.maximize_button, pen.gc(),
-                 2, 2, (frame.button_w - 5), (frame.button_w - 5));
-  XDrawLine(blackbox->getXDisplay(), frame.maximize_button, pen.gc(),
-            2, 3, (frame.button_w - 3), 3);
+
+  PixmapMask pm = screen->getWindowStyle()->max_button;
+    
+  if (pm.mask != None) {
+    XSetClipMask(blackbox->getXDisplay(), pen.gc(), pm.mask);
+    XSetClipOrigin(blackbox->getXDisplay(), pen.gc(),
+                   (frame.button_w - pm.w)/2, (frame.button_w - pm.h)/2);
+
+    XFillRectangle(blackbox->getXDisplay(), frame.maximize_button, pen.gc(),
+                   (frame.button_w - pm.w)/2, (frame.button_w - pm.h)/2,
+                   (frame.button_w + pm.w)/2, (frame.button_w + pm.h)/2);
+    
+    XSetClipOrigin(blackbox->getXDisplay(), pen.gc(), 0, 0 );
+    XSetClipMask( blackbox->getXDisplay(), pen.gc(), None );
+  } else {
+    XDrawRectangle(blackbox->getXDisplay(), frame.maximize_button, pen.gc(),
+                   2, 2, (frame.button_w - 5), (frame.button_w - 5));
+    XDrawLine(blackbox->getXDisplay(), frame.maximize_button, pen.gc(),
+              2, 3, (frame.button_w - 3), 3);
+  }
 }
 
 
@@ -2657,8 +2690,8 @@ void BlackboxWindow::redrawCloseButton(b
   if (! pressed) {
     if (flags.focused) {
       if (frame.fbutton)
-        XSetWindowBackgroundPixmap(blackbox->getXDisplay(), frame.close_button,
-                                   frame.fbutton);
+        XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
+                                   frame.close_button, frame.fbutton);
       else
         XSetWindowBackground(blackbox->getXDisplay(), frame.close_button,
                              frame.fbutton_pixel);
@@ -2681,14 +2714,31 @@ void BlackboxWindow::redrawCloseButton(b
   XClearWindow(blackbox->getXDisplay(), frame.close_button);
 
   BPen pen((flags.focused) ? screen->getWindowStyle()->b_pic_focus :
-           screen->getWindowStyle()->b_pic_unfocus, 0, 2);
-  XDrawLine(blackbox->getXDisplay(), frame.close_button, pen.gc(),
-            2, 2, (frame.button_w - 3), (frame.button_w - 3));
-  XDrawLine(blackbox->getXDisplay(), frame.close_button, pen.gc(),
-            2, (frame.button_w - 3), (frame.button_w - 3), 2);
-}
+           screen->getWindowStyle()->b_pic_unfocus);
 
+  PixmapMask pm = screen->getWindowStyle()->close_button;
+
+  if (pm.mask != None) {
+    XSetClipMask(blackbox->getXDisplay(), pen.gc(), pm.mask);
+    XSetClipOrigin(blackbox->getXDisplay(), pen.gc(),
+                   (frame.button_w - pm.w)/2, (frame.button_w - pm.h)/2);
+    
+    XFillRectangle(blackbox->getXDisplay(), frame.close_button, pen.gc(),
+                   (frame.button_w - pm.w)/2, (frame.button_w - pm.h)/2,
+                   (frame.button_w + pm.w)/2, (frame.button_w + pm.h)/2);
 
+  
+    XSetClipOrigin(blackbox->getXDisplay(), pen.gc(), 0, 0 );
+    XSetClipMask( blackbox->getXDisplay(), pen.gc(), None );
+  } else {
+    
+    XDrawLine(blackbox->getXDisplay(), frame.close_button, pen.gc(),
+              2, 2, (frame.button_w - 3), (frame.button_w - 3));
+    XDrawLine(blackbox->getXDisplay(), frame.close_button, pen.gc(),
+              2, (frame.button_w - 3), (frame.button_w - 3), 2);
+  }
+}
+
 void BlackboxWindow::redrawStickyButton(bool pressed) const {
   if (! pressed) {
     if (flags.focused) {
@@ -2718,9 +2768,25 @@ void BlackboxWindow::redrawStickyButton(
 
   BPen pen((flags.focused) ? screen->getWindowStyle()->b_pic_focus :
            screen->getWindowStyle()->b_pic_unfocus);
+
+  PixmapMask pm = screen->getWindowStyle()->stick_button;
+
+  if (pm.mask != None) {
+    XSetClipMask(blackbox->getXDisplay(), pen.gc(), pm.mask);
+    XSetClipOrigin(blackbox->getXDisplay(), pen.gc(),
+                   (frame.button_w - pm.w)/2, (frame.button_w - pm.h)/2);
+    
+    XFillRectangle(blackbox->getXDisplay(), frame.stick_button, pen.gc(),
+                   (frame.button_w - pm.w)/2, (frame.button_w - pm.h)/2,
+                   (frame.button_w + pm.w)/2, (frame.button_w + pm.h)/2);
+
   
-  XFillRectangle(blackbox->getXDisplay(), frame.stick_button, pen.gc(),
-                 frame.button_w/2 - 1, frame.button_w/2 -1, 2, 2 );
+    XSetClipOrigin(blackbox->getXDisplay(), pen.gc(), 0, 0 );
+    XSetClipMask( blackbox->getXDisplay(), pen.gc(), None );
+  } else {
+    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) {
-------------- 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/20020830/86ca18e3/attachment.pgp>


More information about the openbox mailing list