From 95f9c2d6806cf110597a992be45b17a3b13accd7 Mon Sep 17 00:00:00 2001
From: markt <markt>
Date: Sun, 9 Dec 2007 20:47:41 +0000
Subject: added OnTitlebar modifier to keys file

---
 ChangeLog                      | 11 +++++
 src/FbCommandFactory.cc        |  6 +++
 src/Keys.cc                    | 59 +++++++++++++++++++++-----
 src/Keys.hh                    | 11 +++--
 src/Screen.cc                  |  3 +-
 src/Toolbar.cc                 |  2 +-
 src/Window.cc                  | 96 ++++++++++++++----------------------------
 src/fluxbox.cc                 |  2 +-
 util/fluxbox-update_configs.cc | 63 +++++++++++++++++++++------
 9 files changed, 158 insertions(+), 95 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 5971f05..353af01 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
  (Format: Year/Month/Day)
 Changes for 1.0.1:
+*07/12/09:
+   * Added OnTitlebar and Double modifiers to the keys file for clicks on the
+     titlebar and double clicks, respectively (Mark, thanks Matteo Galiazzo)
+     - For example, `OnTitlebar Double Mouse3 :Maximize' will maximize a window
+       when you double click on the titlebar with the right mouse button
+     - Note: if you have commands bound to both a single and double click, the
+       single click command will still be executed on the first half of a double
+       click
+     - Added new key commands ShadeOn and ShadeOff that set whether or not a
+       window is shaded, rather than toggling the current state
+       Window.cc Keys.cc/hh FbCommandFactory.cc
 *07/11/22:
    * Added some new special keys to the keys file: FocusIn, FocusOut, MouseOver,
      MouseOut, ChangeWorkspace (Mark)
diff --git a/src/FbCommandFactory.cc b/src/FbCommandFactory.cc
index 8f5dcf8..902461c 100644
--- a/src/FbCommandFactory.cc
+++ b/src/FbCommandFactory.cc
@@ -257,6 +257,8 @@ FbCommandFactory::FbCommandFactory() {
         "setresourcevalue",
         "setresourcevaluedialog",
         "shade",
+        "shadeon",
+        "shadeoff",
         "shadewindow",
         "showdesktop",
         "startmoving",
@@ -541,6 +543,10 @@ FbTk::Command *FbCommandFactory::stringToCommand(const std::string &command,
         return new WindowListCmd(FbTk::RefCount<FbTk::Command>(new CurrentWindowCmd(&FluxboxWindow::kill)), arguments);
     else if (command == "shade" || command == "shadewindow")
         return new WindowListCmd(FbTk::RefCount<FbTk::Command>(new CurrentWindowCmd(&FluxboxWindow::shade)), arguments);
+    else if (command == "shadeon" )
+        return new WindowListCmd(FbTk::RefCount<FbTk::Command>(new CurrentWindowCmd(&FluxboxWindow::shadeOn)), arguments);
+    else if (command == "shadeoff" )
+        return new WindowListCmd(FbTk::RefCount<FbTk::Command>(new CurrentWindowCmd(&FluxboxWindow::shadeOff)), arguments);
     else if (command == "stick" || command == "stickwindow")
         return new WindowListCmd(FbTk::RefCount<FbTk::Command>(new CurrentWindowCmd(&FluxboxWindow::stick)), arguments);
     else if (command == "toggledecor")
diff --git a/src/Keys.cc b/src/Keys.cc
index f3cd092..06a0d48 100644
--- a/src/Keys.cc
+++ b/src/Keys.cc
@@ -212,7 +212,7 @@ bool Keys::load(const char *filename) {
     // free memory of previous grabs
     deleteTree();
 
-    m_map["default:"] = new t_key(0,0,0,0);
+    m_map["default:"] = new t_key(0,0,0,0,false);
 
     unsigned int current_line = 0; //so we can tell the user where the fault is
 
@@ -245,7 +245,7 @@ void Keys::loadDefaults() {
     cerr<<"Loading default key bindings"<<endl;
 #endif
     deleteTree();
-    m_map["default:"] = new t_key(0,0,0,0);
+    m_map["default:"] = new t_key(0,0,0,0,false);
     addBinding("OnDesktop Mouse1 :HideMenus");
     addBinding("OnDesktop Mouse2 :WorkspaceMenu");
     addBinding("OnDesktop Mouse3 :RootMenu");
@@ -280,6 +280,7 @@ bool Keys::addBinding(const string &linebuffer) {
 
     unsigned int key = 0, mod = 0;
     int type = 0, context = 0;
+    bool isdouble = false;
     size_t argc = 0;
     t_key *current_key=m_map["default:"];
     t_key *first_new_keylist = current_key, *first_new_key=0;
@@ -288,7 +289,7 @@ bool Keys::addBinding(const string &linebuffer) {
         argc++;
         keyspace_t::iterator it = m_map.find(val[0]);
         if (it == m_map.end())
-            m_map[val[0]] = new t_key(0,0,0,0);
+            m_map[val[0]] = new t_key(0,0,0,0,false);
         current_key = m_map[val[0]];
     }
     // for each argument
@@ -305,6 +306,10 @@ bool Keys::addBinding(const string &linebuffer) {
                 context |= ON_TOOLBAR;
             else if (strcasecmp("onwindow", val[argc].c_str()) == 0)
                 context |= ON_WINDOW;
+            else if (strcasecmp("ontitlebar", val[argc].c_str()) == 0)
+                context |= ON_TITLEBAR;
+            else if (strcasecmp("double", val[argc].c_str()) == 0)
+                isdouble = true;
             else if (strcasecmp("NONE",val[argc].c_str())) {
                 // check if it's a mouse button
                 if (strcasecmp("focusin", val[argc].c_str()) == 0) {
@@ -358,16 +363,21 @@ bool Keys::addBinding(const string &linebuffer) {
 
                 if (key == 0 && (type == KeyPress || type == ButtonPress))
                     return false;
+                if (type != ButtonPress)
+                    isdouble = false;
                 if (!first_new_key) {
                     first_new_keylist = current_key;
-                    current_key = current_key->find(type, mod, key, context);
+                    current_key = current_key->find(type, mod, key, context,
+                                                    isdouble);
                     if (!current_key) {
-                        first_new_key = new t_key(type, mod, key, context);
+                        first_new_key = new t_key(type, mod, key, context,
+                                                  isdouble);
                         current_key = first_new_key;
                     } else if (*current_key->m_command) // already being used
                         return false;
                 } else {
-                    t_key *temp_key = new t_key(type, mod, key, context);
+                    t_key *temp_key = new t_key(type, mod, key, context,
+                                                isdouble);
                     current_key->keylist.push_back(temp_key);
                     current_key = temp_key;
                 }
@@ -375,6 +385,7 @@ bool Keys::addBinding(const string &linebuffer) {
                 key = 0;
                 type = 0;
                 context = 0;
+                isdouble = false;
             }
 
         } else { // parse command line
@@ -402,14 +413,40 @@ bool Keys::addBinding(const string &linebuffer) {
 
 // return true if bound to a command, else false
 bool Keys::doAction(int type, unsigned int mods, unsigned int key,
-                    int context) {
+                    int context, Time time) {
+
+    static Time last_button_time = 0;
+    static unsigned int last_button = 0;
+
+    // need to remember whether or not this is a double-click, e.g. when
+    // double-clicking on the titlebar when there's an OnWindow Double command
+    // we just don't update it if timestamp is the same
+    static bool double_click = false;
+
+    // actual value used for searching
+    bool isdouble = false;
+
+    if (type == ButtonPress) {
+        if (time > last_button_time)
+            double_click = (time - last_button_time <
+                Fluxbox::instance()->getDoubleClickInterval()) &&
+                last_button == key;
+        last_button_time = time;
+        last_button = key;
+        isdouble = double_click;
+    }
 
     static t_key* next_key = m_keylist;
     if (!next_key)
         next_key = m_keylist;
 
     mods = FbTk::KeyUtil::instance().cleanMods(mods);
-    t_key *temp_key = next_key->find(type, mods, key, context);
+    t_key *temp_key = next_key->find(type, mods, key, context, isdouble);
+
+    // just because we double-clicked doesn't mean we shouldn't look for single
+    // click commands
+    if (!temp_key && isdouble)
+        temp_key = next_key->find(type, mods, key, context, false);
 
     // need to save this for emacs-style keybindings
     static t_key *saved_keymode = 0;
@@ -506,12 +543,13 @@ void Keys::setKeyMode(t_key *keyMode) {
 }
             
 Keys::t_key::t_key(int type_, unsigned int mod_, unsigned int key_,
-                   int context_, FbTk::RefCount<FbTk::Command> command) {
+                   int context_, bool isdouble_) {
     key = key_;
     mod = mod_;
     type = type_;
     context = context_ ? context_ : GLOBAL;
-    m_command = command;
+    isdouble = isdouble_;
+    m_command = 0;
 }
 
 Keys::t_key::t_key(t_key *k) {
@@ -519,6 +557,7 @@ Keys::t_key::t_key(t_key *k) {
     mod = k->mod;
     type = k->type;
     context = k->context;
+    isdouble = k->isdouble;
     m_command = k->m_command;
 }
 
diff --git a/src/Keys.hh b/src/Keys.hh
index a8684ed..f5c8cea 100644
--- a/src/Keys.hh
+++ b/src/Keys.hh
@@ -79,7 +79,8 @@ public:
     /**
        do action from XKeyEvent; return false if not bound to anything
     */
-    bool doAction(int type, unsigned int mods, unsigned int key, int context);
+    bool doAction(int type, unsigned int mods, unsigned int key, int context,
+                  Time time = 0);
 
     /// register a window so that proper keys/buttons get grabbed on it
     void registerWindow(Window win, FbTk::EventHandler &handler, int context);
@@ -113,18 +114,19 @@ private:
     class t_key {
     public:
         t_key(int type, unsigned int mod, unsigned int key, int context,
-              FbTk::RefCount<FbTk::Command> command = FbTk::RefCount<FbTk::Command>(0));
+              bool isdouble);
         t_key(t_key *k);
         ~t_key();
 
         t_key *find(int type_, unsigned int mod_, unsigned int key_,
-                    int context_) {
+                    int context_, bool isdouble_) {
             // t_key ctor sets context_ of 0 to GLOBAL, so we must here too
             context_ = context_ ? context_ : GLOBAL;
             keylist_t::iterator it = keylist.begin(), it_end = keylist.end();
             for (; it != it_end; it++) {
                 if ((*it)->type == type_ && (*it)->key == key_ &&
-                    ((*it)->context & context_) > 0 && (*it)->mod ==
+                    ((*it)->context & context_) > 0 &&
+                    isdouble_ == (*it)->isdouble && (*it)->mod ==
                     FbTk::KeyUtil::instance().isolateModifierMask(mod_))
                     return *it;
             }
@@ -137,6 +139,7 @@ private:
         int type; // KeyPress or ButtonPress
         unsigned int key; // key code or button number
         unsigned int mod;
+        bool isdouble;
         keylist_t keylist;
     };
 
diff --git a/src/Screen.cc b/src/Screen.cc
index ebcaaed..7682075 100644
--- a/src/Screen.cc
+++ b/src/Screen.cc
@@ -849,7 +849,8 @@ void BScreen::buttonPressEvent(XButtonEvent &be) {
 
     Keys *keys = Fluxbox::instance()->keys();
     WindowCmd<void>::setWindow(FocusControl::focusedFbWindow());
-    keys->doAction(be.type, be.state, be.button, Keys::GLOBAL|Keys::ON_DESKTOP);
+    keys->doAction(be.type, be.state, be.button, Keys::GLOBAL|Keys::ON_DESKTOP,
+                   be.time);
 }
 
 void BScreen::notifyUngrabKeyboard() {
diff --git a/src/Toolbar.cc b/src/Toolbar.cc
index 3639df7..f67311c 100644
--- a/src/Toolbar.cc
+++ b/src/Toolbar.cc
@@ -527,7 +527,7 @@ void Toolbar::reconfigure() {
 void Toolbar::buttonPressEvent(XButtonEvent &be) {
     WindowCmd<void>::setWindow(0);
     if (Fluxbox::instance()->keys()->doAction(be.type, be.state, be.button,
-                                              Keys::ON_TOOLBAR))
+                                              Keys::ON_TOOLBAR, be.time))
         return;
     if (be.button == 1)
         raise();
diff --git a/src/Window.cc b/src/Window.cc
index 6a12664..82bdc5e 100644
--- a/src/Window.cc
+++ b/src/Window.cc
@@ -905,29 +905,27 @@ void FluxboxWindow::moveClientTo(WinClient &win, int x, int y) {
 
 void FluxboxWindow::moveClientLeftOf(WinClient &win, WinClient &dest) {
 
-	frame().moveLabelButtonLeftOf(*m_labelbuttons[&win], *m_labelbuttons[&dest]);
+        frame().moveLabelButtonLeftOf(*m_labelbuttons[&win], *m_labelbuttons[&dest]);
 
-	ClientList::iterator it = find(m_clientlist.begin(),
-                                  m_clientlist.end(),
-                                  &win);
-	ClientList::iterator new_pos = find(m_clientlist.begin(),
-				       m_clientlist.end(),
-				       &dest);
+        ClientList::iterator it = find(m_clientlist.begin(),
+                                       m_clientlist.end(),
+                                       &win);
+        ClientList::iterator new_pos = find(m_clientlist.begin(),
+                                            m_clientlist.end(),
+                                            &dest);
 
-	// make sure we found them
-	if (it == m_clientlist.end() || new_pos==m_clientlist.end()) {
-		return;
-	}
-	//moving a button to the left of itself results in no change
-	if( new_pos == it) {
-		return;
-	}
-	//remove from list
-	m_clientlist.erase(it);
-	//insert on the new place
-	m_clientlist.insert(new_pos, &win);
+        // make sure we found them
+        if (it == m_clientlist.end() || new_pos==m_clientlist.end())
+            return;
+        //moving a button to the left of itself results in no change
+        if (new_pos == it)
+            return;
+        //remove from list
+        m_clientlist.erase(it);
+        //insert on the new place
+        m_clientlist.insert(new_pos, &win);
 
-	updateClientLeftWindow();
+        updateClientLeftWindow();
 }
 
 
@@ -2560,10 +2558,20 @@ void FluxboxWindow::buttonPressEvent(XButtonEvent &be) {
     m_last_button_x = be.x_root;
     m_last_button_y = be.y_root;
 
+    bool onTitlebar = frame().gripLeft().window() != be.window &&
+        frame().gripRight().window() != be.window &&
+        frame().clientArea().window() != be.window &&
+        frame().window() != be.window;
+
+    if (onTitlebar && be.button == 1)
+        raise();
+
     // check keys file first
     WindowCmd<void>::setWindow(this);
-    if (Fluxbox::instance()->keys()->doAction(be.type, be.state, be.button,
-                                              Keys::ON_WINDOW)) {
+    Keys *k = Fluxbox::instance()->keys();
+    if (onTitlebar && k->doAction(be.type, be.state, be.button,
+                                  Keys::ON_TITLEBAR, be.time) ||
+        k->doAction(be.type, be.state, be.button, Keys::ON_WINDOW, be.time)) {
         return;
     }
 
@@ -2572,13 +2580,6 @@ void FluxboxWindow::buttonPressEvent(XButtonEvent &be) {
         if (!m_focused && acceptsFocus()) //check focus
             focus();
 
-        // click on titlebar
-        if (frame().gripLeft().window() != be.window &&
-            frame().gripRight().window() != be.window &&
-            frame().clientArea().window() != be.window &&
-            frame().window() != be.window)
-            raise();
-
         if (frame().window().window() == be.window ||
             frame().tabcontainer().window() == be.window) {
             if (screen().clickRaises())
@@ -2607,43 +2608,8 @@ void FluxboxWindow::buttonReleaseEvent(XButtonEvent &re) {
         stopResizing();
     else if (m_attaching_tab)
         attachTo(re.x_root, re.y_root);
-    else {
+    else
         frame().tabcontainer().tryButtonReleaseEvent(re);
-        if (frame().gripLeft().window() == re.window ||
-            frame().gripRight().window() == re.window ||
-            frame().clientArea().window() == re.window ||
-            frame().handle().window() == re.window ||
-            frame().window() == re.window)
-            return;
-
-        static Time last_release_time = 0;
-        bool double_click = (re.time - last_release_time <=
-            Fluxbox::instance()->getDoubleClickInterval());
-        last_release_time = re.time;
-
-        if (re.button == 1 && double_click)
-            shade();
-        if (re.button == 3)
-            popupMenu();
-        if (re.button == 2)
-            lower();
-
-        unsigned int reverse = (screen().getScrollReverse() ? 1 : 0);
-        if (re.button == 4 || re.button == 5) {
-            if (StringUtil::toLower(screen().getScrollAction()) == "shade") {
-                if (re.button == 5 - reverse)
-                    shadeOn();
-                else
-                    shadeOff();
-            }
-            if (StringUtil::toLower(screen().getScrollAction()) == "nexttab") {
-                if (re.button == 5 - reverse)
-                    nextClient();
-                else
-                    prevClient();
-            }
-        }
-    }
 
 }
 
diff --git a/src/fluxbox.cc b/src/fluxbox.cc
index 3c30c14..7cf165e 100644
--- a/src/fluxbox.cc
+++ b/src/fluxbox.cc
@@ -643,7 +643,7 @@ void Fluxbox::setupConfigFiles() {
     if (create_init)
         FbTk::FileUtil::copyFile(DEFAULT_INITFILE, init_file.c_str());
 
-#define CONFIG_VERSION 5
+#define CONFIG_VERSION 6
     FbTk::Resource<int> config_version(m_resourcemanager, 0,
             "session.configVersion", "Session.ConfigVersion");
     if (*config_version < CONFIG_VERSION) {
diff --git a/util/fluxbox-update_configs.cc b/util/fluxbox-update_configs.cc
index 89b355f..ac1d2a2 100644
--- a/util/fluxbox-update_configs.cc
+++ b/util/fluxbox-update_configs.cc
@@ -34,8 +34,8 @@
 #endif // HAVE_SIGNAL_H
 
 //use GNU extensions
-#ifndef	 _GNU_SOURCE
-#define	 _GNU_SOURCE
+#ifndef         _GNU_SOURCE
+#define         _GNU_SOURCE
 #endif // _GNU_SOURCE
 
 #ifdef HAVE_CSTRING
@@ -81,9 +81,9 @@ int run_updates(int old_version, FbTk::ResourceManager &rm) {
         string new_keyfile = "";
         // let's put our new keybindings first, so they're easy to find
         new_keyfile += "!mouse actions added by fluxbox-update_configs\n";
-        new_keyfile += "OnDesktop Mouse1 :hideMenus\n";
-        new_keyfile += "OnDesktop Mouse2 :workspaceMenu\n";
-        new_keyfile += "OnDesktop Mouse3 :rootMenu\n";
+        new_keyfile += "OnDesktop Mouse1 :HideMenus\n";
+        new_keyfile += "OnDesktop Mouse2 :WorkspaceMenu\n";
+        new_keyfile += "OnDesktop Mouse3 :RootMenu\n";
 
         // scrolling on desktop needs to match user's desktop wheeling settings
         // hmmm, what are the odds that somebody wants this to be different on
@@ -97,11 +97,11 @@ int run_updates(int old_version, FbTk::ResourceManager &rm) {
                                         "Session.Screen0.ReverseWheeling");
         if (*rc_wheeling) {
             if (*rc_reverse) { // if you ask me, this should have been default
-                new_keyfile += "OnDesktop Mouse4 :prevWorkspace\n";
-                new_keyfile += "OnDesktop Mouse5 :nextWorkspace\n";
+                new_keyfile += "OnDesktop Mouse4 :PrevWorkspace\n";
+                new_keyfile += "OnDesktop Mouse5 :NextWorkspace\n";
             } else {
-                new_keyfile += "OnDesktop Mouse4 :nextWorkspace\n";
-                new_keyfile += "OnDesktop Mouse5 :prevWorkspace\n";
+                new_keyfile += "OnDesktop Mouse4 :NextWorkspace\n";
+                new_keyfile += "OnDesktop Mouse5 :PrevWorkspace\n";
             }
         }
         new_keyfile += "\n"; // just for good looks
@@ -167,11 +167,11 @@ int run_updates(int old_version, FbTk::ResourceManager &rm) {
             (strcasecmp((*rc_wheeling).c_str(), "Screen") && *rc_screen)) {
             keep_changes = true;
             if (*rc_reverse) { // if you ask me, this should have been default
-                new_keyfile += "OnToolbar Mouse4 :prevWorkspace\n";
-                new_keyfile += "OnToolbar Mouse5 :nextWorkspace\n";
+                new_keyfile += "OnToolbar Mouse4 :PrevWorkspace\n";
+                new_keyfile += "OnToolbar Mouse5 :NextWorkspace\n";
             } else {
-                new_keyfile += "OnToolbar Mouse4 :nextWorkspace\n";
-                new_keyfile += "OnToolbar Mouse5 :prevWorkspace\n";
+                new_keyfile += "OnToolbar Mouse4 :NextWorkspace\n";
+                new_keyfile += "OnToolbar Mouse5 :PrevWorkspace\n";
             }
         }
         new_keyfile += "\n"; // just for good looks
@@ -239,6 +239,43 @@ int run_updates(int old_version, FbTk::ResourceManager &rm) {
         new_version = 5;
     }
 
+    if (old_version < 6) { // move titlebar actions to keys file
+        string whole_keyfile = read_file(keyfilename);
+        string new_keyfile = "";
+        // let's put our new keybindings first, so they're easy to find
+        new_keyfile += "!mouse actions added by fluxbox-update_configs\n";
+        new_keyfile += "OnTitlebar Double Mouse1 :Shade\n";
+        new_keyfile += "OnTitlebar Mouse3 :Windowmenu\n";
+        new_keyfile += "OnTitlebar Mouse2 :Lower\n";
+
+        FbTk::Resource<bool> rc_reverse(rm, false,"session.screen0.reversewheeling", "Session.Screen0.ReverseWheeling");
+        FbTk::Resource<std::string>  scroll_action(rm, "", "session.screen0.windowScrollAction", "Session.Screen0.WindowScrollAction");
+        if (strcasecmp((*scroll_action).c_str(), "shade") == 0) {
+            if (*rc_reverse) {
+                new_keyfile += "OnTitlebar Mouse5 :ShadeOn\n";
+                new_keyfile += "OnTitlebar Mouse4 :ShadeOff\n";
+            } else {
+                new_keyfile += "OnTitlebar Mouse4 :ShadeOn\n";
+                new_keyfile += "OnTitlebar Mouse5 :ShadeOff\n";
+            }
+        } else if (strcasecmp((*scroll_action).c_str(), "nexttab") == 0) {
+            if (*rc_reverse) {
+                new_keyfile += "OnTitlebar Mouse5 :PrevTab\n";
+                new_keyfile += "OnTitlebar Mouse4 :NextTab\n";
+            } else {
+                new_keyfile += "OnTitlebar Mouse4 :PrevTab\n";
+                new_keyfile += "OnTitlebar Mouse5 :NextTab\n";
+            }
+        }
+
+        new_keyfile += "\n"; // just for good looks
+        new_keyfile += whole_keyfile; // don't forget user's old keybindings
+
+        write_file(keyfilename, new_keyfile);
+
+        new_version = 6;
+    }
+
     return new_version;
 }
 
-- 
cgit v0.11.2