]> Dogcows Code - chaz/openbox/blobdiff - src/Window.cc
Take menu file from rc file if it isn't specified on the command line.
[chaz/openbox] / src / Window.cc
index c260818c68ba271e97dce45fe7c89ffca0bede36..680943e214d5eb3c3e8453b8043f4573ad086064 100644 (file)
@@ -40,7 +40,7 @@ extern "C" {
 #endif // DEBUG
 
 #ifdef HAVE_STDLIB_H
-   #include <stdlib.h>
+#  include <stdlib.h>
 #endif // HAVE_STDLIB_H
 }
 
@@ -128,17 +128,17 @@ BlackboxWindow::BlackboxWindow(Blackbox *b, Window w, BScreen *s) {
 
   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 =
   frame.ftitle_pixel = frame.uhandle_pixel = frame.fhandle_pixel =
-    frame.ubutton_pixel = frame.fbutton_pixel = frame.pbutton_pixel =
-    frame.uborder_pixel = frame.fborder_pixel = frame.ugrip_pixel =
-    frame.fgrip_pixel = 0;
+    frame.ubutton_pixel = frame.fbutton_pixel = frame.uborder_pixel =
+    frame.fborder_pixel = frame.ugrip_pixel = frame.fgrip_pixel = 0;
   frame.utitle = frame.ftitle = frame.uhandle = frame.fhandle = None;
   frame.ulabel = frame.flabel = frame.ubutton = frame.fbutton = None;
-  frame.pbutton = frame.ugrip = frame.fgrip = None;
+  frame.ugrip = frame.fgrip = None;
 
   functions = Func_Resize | Func_Move | Func_Iconify | Func_Maximize;
   mwm_decorations = Decor_Titlebar | Decor_Handle | Decor_Border |
@@ -474,7 +474,13 @@ Window BlackboxWindow::createToplevelWindow(void) {
   attrib_create.background_pixmap = None;
   attrib_create.colormap = screen->getColormap();
   attrib_create.override_redirect = True;
-  attrib_create.event_mask = EnterWindowMask | LeaveWindowMask;
+  attrib_create.event_mask = EnterWindowMask | LeaveWindowMask |
+                             ButtonPress;
+  /*
+    We catch button presses because other wise they get passed down to the
+    root window, which will then cause root menus to show when you click the
+    window's frame.
+  */
 
   return XCreateWindow(blackbox->getXDisplay(), screen->getRootWindow(),
                        0, 0, 1, 1, frame.border_w, screen->getDepth(),
@@ -564,11 +570,50 @@ void BlackboxWindow::decorate(void) {
   if (! frame.ubutton)
     frame.ubutton_pixel = texture->color().pixel();
 
-  texture = &(screen->getWindowStyle()->b_pressed);
-  frame.pbutton = texture->render(frame.button_w, frame.button_w,
-                                  frame.pbutton);
-  if (! frame.pbutton)
-    frame.pbutton_pixel = texture->color().pixel();
+  unsigned char needsPressed = 0;
+
+  texture = &(screen->getWindowStyle()->b_pressed_focus);
+  
+  if (texture->texture() != BTexture::NoTexture) {
+    frame.pfbutton = texture->render(frame.button_w, frame.button_w,
+                                     frame.pfbutton);
+    if (! frame.pfbutton)
+      frame.pfbutton_pixel = texture->color().pixel();
+  } else {
+    needsPressed = 0x1;
+  }
+
+  texture = &(screen->getWindowStyle()->b_pressed_unfocus);
+  
+  if (texture->texture() != BTexture::NoTexture) {
+    frame.pubutton = texture->render(frame.button_w, frame.button_w,
+                                     frame.pubutton);
+    if (! frame.pubutton)
+      frame.pubutton = texture->color().pixel();
+  } else {
+    needsPressed |= 0x2;
+  }
+
+  // if we either pressed unfocused, or pressed focused were undefined,
+  // make them inherit from the old resource. It's a hack for sure, but
+  // it allows for some backwards and forwards compatibility.
+  if (needsPressed) {
+    texture = &(screen->getWindowStyle()->b_pressed);
+    
+    if (needsPressed & 0x1) {
+      frame.pfbutton = texture->render(frame.button_w, frame.button_w,
+                                       frame.pfbutton);
+      if (! frame.pfbutton)
+        frame.pfbutton_pixel = texture->color().pixel();
+    }
+    if (needsPressed & 0x2) {
+      frame.pubutton = texture->render(frame.button_w, frame.button_w,
+                                       frame.pubutton);
+      if (! frame.pubutton)
+        frame.pubutton = texture->color().pixel();
+    }
+    
+  }
 
   if (decorations & Decor_Titlebar) {
     texture = &(screen->getWindowStyle()->t_focus);
@@ -719,6 +764,9 @@ void BlackboxWindow::destroyTitlebar(void) {
   if (frame.maximize_button)
     destroyMaximizeButton();
 
+  if (frame.stick_button)
+    destroyStickyButton();
+
   if (frame.ftitle)
     screen->getImageControl()->removeImage(frame.ftitle);
 
@@ -737,9 +785,6 @@ void BlackboxWindow::destroyTitlebar(void) {
   if (frame.ubutton)
     screen->getImageControl()->removeImage(frame.ubutton);
 
-  if (frame.pbutton)
-    screen->getImageControl()->removeImage(frame.pbutton);
-
   blackbox->removeWindowSearch(frame.title);
   blackbox->removeWindowSearch(frame.label);
 
@@ -802,13 +847,28 @@ void BlackboxWindow::destroyMaximizeButton(void) {
   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 +885,12 @@ void BlackboxWindow::positionButtons(bool redecorate_label) {
         parsed += *it;
       }
       break;
+    case 'S':
+      if (!hasstick) {
+        hasstick = true;
+        parsed += *it;
+      }
+      break;
     case 'M':
       if (! hasmaximize && (decorations & Decor_Maximize)) {
         hasmaximize = true;
@@ -836,14 +902,18 @@ void BlackboxWindow::positionButtons(bool redecorate_label) {
         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 +939,12 @@ void BlackboxWindow::positionButtons(bool redecorate_label) {
                         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,
@@ -1090,7 +1166,6 @@ void BlackboxWindow::getWMName(void) {
   xatom->setValue(client.window, XAtom::net_wm_visible_name, XAtom::utf8,
                   client.title);
 
-#define DEBUG_WITH_ID 1
 #ifdef DEBUG_WITH_ID
   // the 16 is the 8 chars of the debug text plus the number
   char *tmp = new char[client.title.length() + 16];
@@ -1631,6 +1706,14 @@ void BlackboxWindow::configureShape(void) {
                           ShapeBounding, 0, 0, xrect, num,
                           ShapeUnion, Unsorted);
 }
+
+
+void BlackboxWindow::clearShape(void) {
+  XShapeCombineMask(blackbox->getXDisplay(), frame.window, ShapeBounding,
+                    frame.margin.left - frame.border_w,
+                    frame.margin.top - frame.border_w,
+                    None, ShapeSet);
+}
 #endif // SHAPE
 
 
@@ -2069,6 +2152,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,114 +2620,189 @@ void BlackboxWindow::redrawAllButtons(void) const {
   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);
 }
 
 
-void BlackboxWindow::redrawIconifyButton(bool pressed) const {
-  if (! pressed) {
+void BlackboxWindow::redrawButton(bool pressed, Window win,
+                                  Pixmap fppix, unsigned long fppixel,
+                                  Pixmap uppix, unsigned long uppixel,
+                                  Pixmap fpix, unsigned long fpixel,
+                                  Pixmap upix, unsigned long upixel) const {
+  Pixmap p;
+  unsigned long pix;
+  
+  if (pressed) {
     if (flags.focused) {
-      if (frame.fbutton)
-        XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
-                                   frame.iconify_button, frame.fbutton);
-      else
-        XSetWindowBackground(blackbox->getXDisplay(),
-                             frame.iconify_button, frame.fbutton_pixel);
+      p = fppix;
+      pix = fppixel;
     } else {
-      if (frame.ubutton)
-        XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
-                                   frame.iconify_button, frame.ubutton);
-      else
-        XSetWindowBackground(blackbox->getXDisplay(), frame.iconify_button,
-                             frame.ubutton_pixel);
+      p = uppix;
+      pix = uppixel;
     }
   } else {
-    if (frame.pbutton)
-      XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
-                                 frame.iconify_button, frame.pbutton);
-    else
-      XSetWindowBackground(blackbox->getXDisplay(),
-                           frame.iconify_button, frame.pbutton_pixel);
+    if (flags.focused) {
+      p = fpix;
+      pix = fpixel;
+    } else {
+      p = upix;
+      pix = upixel;
+    }
   }
-  XClearWindow(blackbox->getXDisplay(), frame.iconify_button);
+  
+  if (p)
+    XSetWindowBackgroundPixmap(blackbox->getXDisplay(), win, p);
+  else
+    XSetWindowBackground(blackbox->getXDisplay(), win, pix);
 
-  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);
 }
 
+void BlackboxWindow::redrawIconifyButton(bool pressed) const {
+  redrawButton(pressed, frame.iconify_button, 
+               frame.pfbutton, frame.pfbutton_pixel,
+               frame.pubutton, frame.pubutton_pixel,
+               frame.fbutton, frame.fbutton_pixel,
+               frame.ubutton, frame.ubutton_pixel);
 
-void BlackboxWindow::redrawMaximizeButton(bool pressed) const {
-  if (! pressed) {
-    if (flags.focused) {
-      if (frame.fbutton)
-        XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
-                                   frame.maximize_button, frame.fbutton);
-      else
-        XSetWindowBackground(blackbox->getXDisplay(), frame.maximize_button,
-                             frame.fbutton_pixel);
-    } else {
-      if (frame.ubutton)
-        XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
-                                   frame.maximize_button, frame.ubutton);
-      else
-        XSetWindowBackground(blackbox->getXDisplay(), frame.maximize_button,
-                             frame.ubutton_pixel);
-    }
+  XClearWindow(blackbox->getXDisplay(), frame.iconify_button);
+  BPen pen((flags.focused) ? screen->getWindowStyle()->b_pic_focus :
+             screen->getWindowStyle()->b_pic_unfocus);
+
+#ifdef    BITMAPBUTTONS
+  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 {
-    if (frame.pbutton)
-      XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
-                                 frame.maximize_button, frame.pbutton);
-    else
-      XSetWindowBackground(blackbox->getXDisplay(), frame.maximize_button,
-                           frame.pbutton_pixel);
+#endif // BITMAPBUTTONS
+    XDrawRectangle(blackbox->getXDisplay(), frame.iconify_button, pen.gc(),
+                   2, (frame.button_w - 5), (frame.button_w - 5), 2);
+#ifdef    BITMAPBUTTONS
   }
+#endif // BITMAPBUTTONS
+}
+
+
+void BlackboxWindow::redrawMaximizeButton(bool pressed) const {
+  redrawButton(pressed, frame.maximize_button, 
+               frame.pfbutton, frame.pfbutton_pixel,
+               frame.pubutton, frame.pubutton_pixel,
+               frame.fbutton, frame.fbutton_pixel,
+               frame.ubutton, frame.ubutton_pixel);
+
   XClearWindow(blackbox->getXDisplay(), frame.maximize_button);
 
   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);
+  
+#ifdef    BITMAPBUTTONS
+  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 {
+#endif // BITMAPBUTTONS
+    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);
+#ifdef    BITMAPBUTTONS
+  }
+#endif // BITMAPBUTTONS
 }
 
 
 void BlackboxWindow::redrawCloseButton(bool pressed) const {
-  if (! pressed) {
-    if (flags.focused) {
-      if (frame.fbutton)
-        XSetWindowBackgroundPixmap(blackbox->getXDisplay(), frame.close_button,
-                                   frame.fbutton);
-      else
-        XSetWindowBackground(blackbox->getXDisplay(), frame.close_button,
-                             frame.fbutton_pixel);
-    } else {
-      if (frame.ubutton)
-        XSetWindowBackgroundPixmap(blackbox->getXDisplay(), frame.close_button,
-                                   frame.ubutton);
-      else
-        XSetWindowBackground(blackbox->getXDisplay(), frame.close_button,
-                             frame.ubutton_pixel);
-    }
-  } else {
-    if (frame.pbutton)
-      XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
-                                 frame.close_button, frame.pbutton);
-    else
-      XSetWindowBackground(blackbox->getXDisplay(),
-                           frame.close_button, frame.pbutton_pixel);
-  }
+  redrawButton(pressed, frame.close_button, 
+               frame.pfbutton, frame.pfbutton_pixel,
+               frame.pubutton, frame.pubutton_pixel,
+               frame.fbutton, frame.fbutton_pixel,
+               frame.ubutton, frame.ubutton_pixel);
+
   XClearWindow(blackbox->getXDisplay(), frame.close_button);
 
   BPen pen((flags.focused) ? screen->getWindowStyle()->b_pic_focus :
            screen->getWindowStyle()->b_pic_unfocus);
-  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);
+  
+#ifdef    BITMAPBUTTONS
+  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 {
+#endif // BITMAPBUTTONS
+    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);
+#ifdef    BITMAPBUTTONS
+  }
+#endif // BITMAPBUTTONS
 }
 
+void BlackboxWindow::redrawStickyButton(bool pressed) const {
+  redrawButton(pressed, frame.stick_button, 
+               frame.pfbutton, frame.pfbutton_pixel,
+               frame.pubutton, frame.pubutton_pixel,
+               frame.fbutton, frame.fbutton_pixel,
+               frame.ubutton, frame.ubutton_pixel);
+
+  XClearWindow(blackbox->getXDisplay(), frame.stick_button);
+
+  BPen pen((flags.focused) ? screen->getWindowStyle()->b_pic_focus :
+           screen->getWindowStyle()->b_pic_unfocus);
+  
+#ifdef    BITMAPBUTTONS
+  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);
+
+  
+    XSetClipOrigin(blackbox->getXDisplay(), pen.gc(), 0, 0 );
+    XSetClipMask( blackbox->getXDisplay(), pen.gc(), None );
+  } else {
+#endif // BITMAPBUTTONS
+    XFillRectangle(blackbox->getXDisplay(), frame.stick_button, pen.gc(),
+                   frame.button_w/2 - 1, frame.button_w/2 -1, 2, 2 );
+#ifdef    BITMAPBUTTONS
+  }
+#endif
+}
 
 void BlackboxWindow::mapRequestEvent(const XMapRequestEvent *re) {
   if (re->window != client.window)
@@ -2656,7 +2817,8 @@ void BlackboxWindow::mapRequestEvent(const XMapRequestEvent *re) {
      Even though the window wants to be shown, if it is not on the current
      workspace, then it isn't going to be shown right now.
   */
-  if (blackbox_attrib.workspace != screen->getCurrentWorkspaceID() &&
+  if (! flags.stuck &&
+      blackbox_attrib.workspace != screen->getCurrentWorkspaceID() &&
       blackbox_attrib.workspace < screen->getWorkspaceCount())
     if (current_state == NormalState) current_state = WithdrawnState;
 
@@ -2857,6 +3019,8 @@ void BlackboxWindow::exposeEvent(const XExposeEvent *ee) {
     redrawMaximizeButton(flags.maximized);
   else if (frame.iconify_button == ee->window)
     redrawIconifyButton(False);
+  else if (frame.stick_button == ee->window)
+    redrawStickyButton(flags.stuck);
 }
 
 
@@ -2889,10 +3053,10 @@ void BlackboxWindow::configureRequestEvent(const XConfigureRequestEvent *cr) {
                                  frame.margin.top + frame.margin.bottom);
 
       /*
-        if a position change ha been specified, then that position will be used
-        instead of determining a position based on the window's gravity.
+        if a position change has been specified, then that position will be
+        used instead of determining a position based on the window's gravity.
       */
-      if (cr->value_mask & (CWX | CWY)) {
+      if (! (cr->value_mask & (CWX | CWY))) {
         Corner corner;
         switch (client.win_gravity) {
         case NorthEastGravity:
@@ -2950,6 +3114,8 @@ void BlackboxWindow::buttonPressEvent(const XButtonEvent *be) {
       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 +3139,8 @@ void BlackboxWindow::buttonPressEvent(const XButtonEvent *be) {
       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 ||
@@ -3002,12 +3169,16 @@ void BlackboxWindow::buttonPressEvent(const XButtonEvent *be) {
 
       if (mx < left_edge)
         mx = left_edge;
-      if (mx > right_edge)
+      else if (mx > right_edge)
         mx = right_edge;
       if (my < top_edge)
         my = top_edge;
-      if (my > bottom_edge)
+      else if (my > bottom_edge)
         my = bottom_edge;
+      
+      if (my + windowmenu->getHeight() > screen->getHeight())
+        my = screen->getHeight() - windowmenu->getHeight() -
+          (screen->getBorderWidth() * 2);
 
       windowmenu->move(mx, my);
       windowmenu->show();
@@ -3021,7 +3192,8 @@ void BlackboxWindow::buttonPressEvent(const XButtonEvent *be) {
          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 +3202,8 @@ void BlackboxWindow::buttonPressEvent(const XButtonEvent *be) {
          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();
   }
@@ -3058,6 +3231,13 @@ void BlackboxWindow::buttonReleaseEvent(const XButtonEvent *re) {
     } 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)) &&
         (re->y >= 0 && re->y <= static_cast<signed>(frame.button_w)))
@@ -3714,11 +3894,14 @@ void BlackboxWindow::motionNotifyEvent(const XMotionEvent *me) {
          frame.handle == me->window || frame.window == me->window)) {
       beginMove(me->x_root, me->y_root);
     } else if ((functions & Func_Resize) &&
-               ((me->state & Button1Mask) && (me->window == frame.right_grip ||
-                                              me->window == frame.left_grip)) ||
+               ((me->state & Button1Mask) &&
+                (me->window == frame.right_grip ||
+                 me->window == frame.left_grip)) ||
                ((me->state & Button3Mask) && (me->state & mod_mask) &&
                 (frame.title == me->window || frame.label == me->window ||
-                 frame.handle == me->window || frame.window == me->window))) {
+                 frame.handle == me->window || frame.window == me->window ||
+                 frame.right_grip == me->window ||
+                 frame.left_grip == me->window))) {
       unsigned int zones = screen->getResizeZones();
       Corner corner;
       
@@ -3765,10 +3948,15 @@ void BlackboxWindow::enterNotifyEvent(const XCrossingEvent* ce) {
       bool success = setInputFocus();
       if (success)    // if focus succeeded install the colormap
         installColormap(True); // XXX: shouldnt we honour no install?
-    }
 
-    if (screen->doAutoRaise())
-      timer->start();
+      /*
+        We only auto-raise when the window wasn't focused because otherwise
+        we run into problems with gtk+ drop-down lists. The window ends up
+        raising over the list.
+      */
+      if (screen->doAutoRaise())
+        timer->start();
+    }
   }
 }
 
@@ -3785,9 +3973,15 @@ void BlackboxWindow::leaveNotifyEvent(const XCrossingEvent*) {
 
 
 #ifdef    SHAPE
-void BlackboxWindow::shapeEvent(XShapeEvent *) {
-  if (blackbox->hasShapeExtensions() && flags.shaped) {
-    configureShape();
+void BlackboxWindow::shapeEvent(XShapeEvent *e) {
+  if (blackbox->hasShapeExtensions()) {
+    if (! e->shaped && flags.shaped) {
+      clearShape();
+      flags.shaped = False;
+    } else if (e->shaped) {
+      configureShape();
+      flags.shaped = True;
+    }
   }
 }
 #endif // SHAPE
@@ -4019,13 +4213,17 @@ void BlackboxWindow::constrain(Corner anchor,
     base_height = (client.base_height) ? client.base_height :
                                          client.min_height;
 
-  // constrain
-  if (dw < client.min_width) dw = client.min_width;
-  if (dh < client.min_height) dh = client.min_height;
-  if (dw > client.max_width) dw = client.max_width;
-  if (dh > client.max_height) dh = client.max_height;
-
-  assert(dw >= base_width && dh >= base_height);
+  // constrain, but only if the min/max are being used. if they aren't, then
+  // this resize is going to be from a ConfigureRequest because the window
+  // isn't allowed to be resized by the user. And in that case, we don't want
+  // to limit what the app can do
+  if (client.max_width > client.min_width ||
+      client.max_height > client.min_height) {
+    if (dw < client.min_width) dw = client.min_width;
+    if (dh < client.min_height) dh = client.min_height;
+    if (dw > client.max_width) dw = client.max_width;
+    if (dh > client.max_height) dh = client.max_height;
+  }
 
   if (client.width_inc > 1) {
     dw -= base_width;
This page took 0.043111 seconds and 4 git commands to generate.