From 34343bb20bdb3dc94fe426f69e5db16315353d57 Mon Sep 17 00:00:00 2001
From: Mathias Gumz <akira at fluxbox dot org>
Date: Wed, 6 Feb 2013 13:47:11 +0100
Subject: Feature #3602124: 'LHalf' and 'RHalf' buttons to the titlebar

First draft of feature request of #3602124: Having 2 buttons in the titlebar
which allow quick positioning of a Window into the left or right half of the
current monitor.
---
 src/Resources.cc      | 10 ++++++++++
 src/WinButton.cc      | 35 ++++++++++++++++++++---------------
 src/WinButton.hh      | 14 ++++++++++++--
 src/WinButtonTheme.cc |  6 ++++++
 src/WinButtonTheme.hh | 12 ++++++++++--
 src/Window.cc         | 27 +++++++++++++++++++++++++++
 6 files changed, 85 insertions(+), 19 deletions(-)

diff --git a/src/Resources.cc b/src/Resources.cc
index 2e07725..128eedd 100644
--- a/src/Resources.cc
+++ b/src/Resources.cc
@@ -108,6 +108,12 @@ getString() const {
         case WinButton::MENUICON:
             retval.append("MenuIcon");
             break;
+        case WinButton::LEFT_HALF:
+            retval.append("LHalf");
+            break;
+        case WinButton::RIGHT_HALF:
+            retval.append("RHalf");
+            break;
         default:
             break;
         }
@@ -142,6 +148,10 @@ setFromString(char const *strval) {
             m_value.push_back(WinButton::MENUICON);
         else if (v == "close")
             m_value.push_back(WinButton::CLOSE);
+        else if (v == "lhalf")
+            m_value.push_back(WinButton::LEFT_HALF);
+        else if (v == "rhalf")
+            m_value.push_back(WinButton::RIGHT_HALF);
     }
 }
 
diff --git a/src/WinButton.cc b/src/WinButton.cc
index e1b79a2..bb841fb 100644
--- a/src/WinButton.cc
+++ b/src/WinButton.cc
@@ -137,6 +137,10 @@ Pixmap WinButton::getPixmap(const FbTk::ThemeProxy<WinButtonTheme> &theme) const
             return theme->titlePixmap().pixmap().drawable();
         else
             return theme->menuiconPixmap().pixmap().drawable();
+    case LEFT_HALF:
+        return theme->leftHalfPixmap().pixmap().drawable();
+    case RIGHT_HALF:
+        return theme->rightHalfPixmap().pixmap().drawable();
     default:
         return None;
     }
@@ -160,18 +164,14 @@ void WinButton::drawType() {
     // otherwise draw old style imagery
     switch (m_type) {
     case MAXIMIZE:
-        // if no pixmap was used, use old style
-        if (gc() == 0) // must have valid graphic context
-            return;
-
-        drawRectangle(gc(),
-                      2, 2, width() - 5, height() - 5);
-        drawLine(gc(),
-                 2, 3, width() - 3, 3);
+        drawRectangle(gc(), 2, 2, width() - 5, height() - 5);
+        drawLine(gc(), 2, 3, width() - 3, 3);
         break;
+
     case MINIMIZE:
         drawRectangle(gc(), 2, height() - 5, width() - 5, 2);
         break;
+
     case STICK:
         // width/4 != width/2, so we use /4*2 so that it's properly centred
         if (m_listen_to.isStuck()) {
@@ -184,6 +184,7 @@ void WinButton::drawType() {
                           width()/10*2 + oddW, height()/10*2 + oddH);
         }
         break;
+
     case CLOSE:
         drawLine(gc(),
                  2, 2,
@@ -199,15 +200,12 @@ void WinButton::drawType() {
         // XFree86 Version 4.3.0.1 (Debian 4.3.0.dfsg.1-1 20040428170728)
         // (X Protocol Version 11, Revision 0, Release 6.6)
 
-        drawLine(gc(),
-                 2, height() - 3,
-                 width() - 3, 2);
+        drawLine(gc(), 2, height() - 3, width() - 3, 2);
         break;
-    case SHADE:
 
+    case SHADE:
     {
         int size = width() - 5 - oddW;
-
         drawRectangle(gc(), 2, 2, size, 2);
 
         // draw a one-quarter triangle below the rectangle
@@ -220,6 +218,7 @@ void WinButton::drawType() {
 
         break;
     }
+
     case MENUICON:
         if (m_icon_pixmap.drawable()) {
 
@@ -242,10 +241,16 @@ void WinButton::drawType() {
             for (unsigned int y = height()/3; y <= height() - height()/3; y+=3) {
                 drawLine(gc(), width()/4, y, width() - width()/4 - oddW - 1, y);
             }
-            drawRectangle(gc(),
-                      2, 2, width() - 5, height() - 5);
+            drawRectangle(gc(), 2, 2, width() - 5, height() - 5);
         }
         break;
+
+    case LEFT_HALF:
+        fillRectangle(gc(), 2, 2, (width() / 2) - oddW, height() - 4);
+        break;
+    case RIGHT_HALF:
+        fillRectangle(gc(), width() / 2, 2, (width() / 2) - 2 + oddW, height() - 4);
+        break;
     }
 }
 
diff --git a/src/WinButton.hh b/src/WinButton.hh
index 3912a1a..f64342e 100644
--- a/src/WinButton.hh
+++ b/src/WinButton.hh
@@ -38,7 +38,17 @@ template <class T> class ThemeProxy;
 class WinButton:public FbTk::Button, public FbTk::SignalTracker {
 public:
     /// draw type for the button
-    enum Type {MAXIMIZE, MINIMIZE, SHADE, STICK, CLOSE, MENUICON};
+    enum Type {
+        MAXIMIZE,
+        MINIMIZE,
+        SHADE,
+        STICK,
+        CLOSE,
+        MENUICON,
+        LEFT_HALF,
+        RIGHT_HALF
+    };
+
     WinButton(FluxboxWindow &listen_to, 
               FbTk::ThemeProxy<WinButtonTheme> &theme,
               FbTk::ThemeProxy<WinButtonTheme> &pressed,
@@ -66,7 +76,7 @@ private:
 
     FbTk::FbPixmap m_icon_pixmap;
     FbTk::FbPixmap m_icon_mask;
-    
+
     bool overrode_bg, overrode_pressed;
 };
 
diff --git a/src/WinButtonTheme.cc b/src/WinButtonTheme.cc
index c6e6ddf..aa043b1 100644
--- a/src/WinButtonTheme.cc
+++ b/src/WinButtonTheme.cc
@@ -52,6 +52,10 @@ WinButtonTheme::WinButtonTheme(int screen_num,
                "Window.Stick" + altextra + ".Pixmap"),
     m_stuck_pm(*this, "window.stuck" + extra + ".pixmap",
                "Window.Stuck" + altextra + ".Pixmap"),
+    m_lefthalf_pm(*this, "window.lhalf" + extra + ".pixmap",
+               "Window.LHalf" + altextra + ".Pixmap"),
+    m_righthalf_pm(*this, "window.rhalf" + extra + ".pixmap",
+               "Window.RHalf" + altextra + ".Pixmap"),
     m_frame_theme(frame_theme) {
 
     FbTk::ThemeManager::instance().loadTheme(*this);
@@ -82,5 +86,7 @@ void WinButtonTheme::reconfigTheme() {
     m_title_pm->scale(size, size);
     m_stick_pm->scale(size, size);
     m_stuck_pm->scale(size, size);
+    m_lefthalf_pm->scale(size, size);
+    m_righthalf_pm->scale(size, size);
 }
 
diff --git a/src/WinButtonTheme.hh b/src/WinButtonTheme.hh
index 224fc6c..9e3c5ed 100644
--- a/src/WinButtonTheme.hh
+++ b/src/WinButtonTheme.hh
@@ -62,10 +62,18 @@ public:
 
     const FbTk::PixmapWithMask &menuiconPixmap() const { return *m_menuicon_pm; }
     FbTk::PixmapWithMask &menuiconPixmap() { return *m_menuicon_pm; }
-    
+
     FbTk::PixmapWithMask &titlePixmap() { return *m_title_pm; }
     const FbTk::PixmapWithMask &titlePixmap() const { return *m_title_pm; }
 
+
+    FbTk::PixmapWithMask &leftHalfPixmap() { return *m_lefthalf_pm; }
+    const FbTk::PixmapWithMask &leftHalfPixmap() const { return *m_lefthalf_pm; }
+
+    FbTk::PixmapWithMask &rightHalfPixmap() { return *m_righthalf_pm; }
+    const FbTk::PixmapWithMask &rightHalfPixmap() const { return *m_righthalf_pm; }
+
+
     virtual FbTk::Signal<> &reconfigSig() { return FbTk::Theme::reconfigSig(); }
 
     virtual WinButtonTheme &operator *() { return *this; }
@@ -75,7 +83,7 @@ private:
 
     FbTk::ThemeItem<FbTk::PixmapWithMask> m_close_pm, m_maximize_pm,
             m_iconify_pm, m_shade_pm, m_unshade_pm, m_menuicon_pm, m_title_pm,
-            m_stick_pm, m_stuck_pm;
+            m_stick_pm, m_stuck_pm, m_lefthalf_pm, m_righthalf_pm;
 
     FbTk::ThemeProxy<FbWinFrameTheme> &m_frame_theme;
 };
diff --git a/src/Window.cc b/src/Window.cc
index 1ee8853..98486be 100644
--- a/src/Window.cc
+++ b/src/Window.cc
@@ -48,6 +48,7 @@
 
 #include "FbTk/StringUtil.hh"
 #include "FbTk/Compose.hh"
+#include "FbTk/CommandParser.hh"
 #include "FbTk/EventManager.hh"
 #include "FbTk/KeyUtil.hh"
 #include "FbTk/SimpleCommand.hh"
@@ -3600,6 +3601,32 @@ void FluxboxWindow::updateButtons() {
                     winbtn->setOnClick(show_menu_cmd);
                 }
                 break;
+
+            case WinButton::LEFT_HALF:
+                {
+                    winbtn = new WinButton(*this, m_button_theme,
+                                screen().pressedWinButtonTheme(),
+                                dir[i],
+                                frame().titlebar(),
+                                0, 0, 10, 10);
+
+                    CommandRef lhalf_cmd(FbTk::CommandParser<void>::instance().parse("MacroCmd {MoveTo 0 0} {ResizeTo 50% 100%}"));
+                    winbtn->setOnClick(lhalf_cmd);
+                }
+                break;
+
+            case WinButton::RIGHT_HALF:
+                {
+                    winbtn = new WinButton(*this, m_button_theme,
+                                screen().pressedWinButtonTheme(),
+                                dir[i],
+                                frame().titlebar(),
+                                0, 0, 10, 10);
+                    CommandRef rhalf_cmd(FbTk::CommandParser<void>::instance().parse("MacroCmd {MoveTo 50% 0} {ResizeTo 50% 100%}"));
+                    winbtn->setOnClick(rhalf_cmd);
+                }
+                break;
+
             }
 
 
-- 
cgit v0.11.2