diff options
-rw-r--r-- | ChangeLog | 3 | ||||
-rw-r--r-- | data/init.in | 2 | ||||
-rw-r--r-- | data/keys | 3 | ||||
-rw-r--r-- | src/CurrentWindowCmd.cc | 10 | ||||
-rw-r--r-- | src/CurrentWindowCmd.hh | 8 | ||||
-rw-r--r-- | src/Window.cc | 149 | ||||
-rw-r--r-- | src/Window.hh | 2 | ||||
-rw-r--r-- | src/fluxbox.cc | 2 | ||||
-rw-r--r-- | util/fluxbox-update_configs.cc | 13 |
9 files changed, 114 insertions, 78 deletions
@@ -1,5 +1,8 @@ | |||
1 | (Format: Year/Month/Day) | 1 | (Format: Year/Month/Day) |
2 | Changes for 1.0.1: | 2 | Changes for 1.0.1: |
3 | *07/12/21: | ||
4 | * Added new key command :StartTabbing (Mark) | ||
5 | Window.cc/hh CurrentWindowCmd.cc/hh | ||
3 | *07/12/20: | 6 | *07/12/20: |
4 | * Added new key command :ForEach (or :Map) (Mark) | 7 | * Added new key command :ForEach (or :Map) (Mark) |
5 | - :ForEach {<command>} [{ [{<list opts>}] [<bool command>] }] | 8 | - :ForEach {<command>} [{ [{<list opts>}] [<bool command>] }] |
diff --git a/data/init.in b/data/init.in index c0bb93a..86cfa08 100644 --- a/data/init.in +++ b/data/init.in | |||
@@ -30,4 +30,4 @@ session.colorsPerChannel: 4 | |||
30 | session.doubleClickInterval: 250 | 30 | session.doubleClickInterval: 250 |
31 | session.cacheMax: 200 | 31 | session.cacheMax: 200 |
32 | session.imageDither: True | 32 | session.imageDither: True |
33 | session.configVersion: 6 | 33 | session.configVersion: 7 |
@@ -15,6 +15,9 @@ OnToolbar Mouse5 :PrevWorkspace | |||
15 | OnWindow Mod1 Mouse1 :StartMoving | 15 | OnWindow Mod1 Mouse1 :StartMoving |
16 | OnWindow Mod1 Mouse3 :StartResizing | 16 | OnWindow Mod1 Mouse3 :StartResizing |
17 | 17 | ||
18 | # middle click a window's titlebar and drag to attach windows | ||
19 | OnTitlebar Mouse2 :StartTabbing | ||
20 | |||
18 | # double click on the titlebar to shade | 21 | # double click on the titlebar to shade |
19 | OnTitlebar Double Mouse1 :Shade | 22 | OnTitlebar Double Mouse1 :Shade |
20 | 23 | ||
diff --git a/src/CurrentWindowCmd.cc b/src/CurrentWindowCmd.cc index d7b05ab..072f3c5 100644 --- a/src/CurrentWindowCmd.cc +++ b/src/CurrentWindowCmd.cc | |||
@@ -313,6 +313,16 @@ void StartResizingCmd::real_execute() { | |||
313 | } | 313 | } |
314 | } | 314 | } |
315 | 315 | ||
316 | REGISTER_OBJECT(starttabbing, StartTabbingCmd, Command); | ||
317 | |||
318 | void StartTabbingCmd::real_execute() { | ||
319 | const XEvent &last = Fluxbox::instance()->lastEvent(); | ||
320 | if (last.type == ButtonPress) { | ||
321 | const XButtonEvent &be = last.xbutton; | ||
322 | fbwindow().startTabbing(be); | ||
323 | } | ||
324 | } | ||
325 | |||
316 | FbTk::Command *MoveCmd::parse(const string &command, const string &args, | 326 | FbTk::Command *MoveCmd::parse(const string &command, const string &args, |
317 | bool trusted) { | 327 | bool trusted) { |
318 | FbTk_istringstream is(args.c_str()); | 328 | FbTk_istringstream is(args.c_str()); |
diff --git a/src/CurrentWindowCmd.hh b/src/CurrentWindowCmd.hh index 7ef1184..fdce8d6 100644 --- a/src/CurrentWindowCmd.hh +++ b/src/CurrentWindowCmd.hh | |||
@@ -159,6 +159,14 @@ private: | |||
159 | const FluxboxWindow::ResizeModel m_mode; | 159 | const FluxboxWindow::ResizeModel m_mode; |
160 | }; | 160 | }; |
161 | 161 | ||
162 | // begin tabbing with mouse | ||
163 | class StartTabbingCmd: public WindowHelperCmd { | ||
164 | public: | ||
165 | StartTabbingCmd() { } | ||
166 | protected: | ||
167 | void real_execute(); | ||
168 | }; | ||
169 | |||
162 | // move cmd, relative position | 170 | // move cmd, relative position |
163 | class MoveCmd: public WindowHelperCmd { | 171 | class MoveCmd: public WindowHelperCmd { |
164 | public: | 172 | public: |
diff --git a/src/Window.cc b/src/Window.cc index c9ab1b2..d99d1c1 100644 --- a/src/Window.cc +++ b/src/Window.cc | |||
@@ -2611,11 +2611,10 @@ void FluxboxWindow::motionNotifyEvent(XMotionEvent &me) { | |||
2611 | me.window = frame().window().window(); | 2611 | me.window = frame().window().window(); |
2612 | } | 2612 | } |
2613 | 2613 | ||
2614 | bool inside_titlebar = (frame().titlebar() == me.window | 2614 | bool inside_titlebar = frame().gripLeft().window() != me.window && |
2615 | || frame().label() == me.window | 2615 | frame().gripRight().window() != me.window && |
2616 | || frame().tabcontainer() == me.window | 2616 | frame().clientArea().window() != me.window && |
2617 | || frame().handle() == me.window | 2617 | frame().window() != me.window; |
2618 | || frame().window() == me.window); | ||
2619 | 2618 | ||
2620 | if (Fluxbox::instance()->getIgnoreBorder() && m_attaching_tab == 0 | 2619 | if (Fluxbox::instance()->getIgnoreBorder() && m_attaching_tab == 0 |
2621 | && !(isMoving() || isResizing())) { | 2620 | && !(isMoving() || isResizing())) { |
@@ -2650,24 +2649,8 @@ void FluxboxWindow::motionNotifyEvent(XMotionEvent &me) { | |||
2650 | return; | 2649 | return; |
2651 | } | 2650 | } |
2652 | 2651 | ||
2653 | WinClient *client = 0; | 2652 | if (moving || (me.state & Button1Mask) && functions.move && |
2654 | if (!inside_titlebar) { | 2653 | inside_titlebar && !isResizing() && m_attaching_tab == 0) { |
2655 | // determine if we're in titlebar | ||
2656 | Client2ButtonMap::iterator it = | ||
2657 | find_if(m_labelbuttons.begin(), | ||
2658 | m_labelbuttons.end(), | ||
2659 | Compose(bind2nd(equal_to<Window>(), me.window), | ||
2660 | Compose(mem_fun(&TextButton::window), | ||
2661 | Select2nd<Client2ButtonMap::value_type>()))); | ||
2662 | if (it != m_labelbuttons.end()) { | ||
2663 | inside_titlebar = true; | ||
2664 | client = (*it).first; | ||
2665 | } | ||
2666 | } | ||
2667 | |||
2668 | if ((me.state & Button1Mask) && functions.move && | ||
2669 | inside_titlebar && | ||
2670 | !isResizing()) { | ||
2671 | 2654 | ||
2672 | if (! isMoving()) { | 2655 | if (! isMoving()) { |
2673 | startMoving(me.x_root, me.y_root); | 2656 | startMoving(me.x_root, me.y_root); |
@@ -2741,7 +2724,7 @@ void FluxboxWindow::motionNotifyEvent(XMotionEvent &me) { | |||
2741 | 2724 | ||
2742 | screen().showPosition(dx, dy); | 2725 | screen().showPosition(dx, dy); |
2743 | } // end if moving | 2726 | } // end if moving |
2744 | } else if (functions.resize && | 2727 | } else if (resizing || m_attaching_tab == 0 && functions.resize && |
2745 | (((me.state & Button1Mask) && | 2728 | (((me.state & Button1Mask) && |
2746 | (me.window == frame().gripRight() || | 2729 | (me.window == frame().gripRight() || |
2747 | me.window == frame().gripLeft())) || | 2730 | me.window == frame().gripLeft())) || |
@@ -2833,61 +2816,25 @@ void FluxboxWindow::motionNotifyEvent(XMotionEvent &me) { | |||
2833 | screen().showGeometry(gx, gy); | 2816 | screen().showGeometry(gx, gy); |
2834 | } | 2817 | } |
2835 | } | 2818 | } |
2836 | } else if (functions.tabable && | 2819 | } else if (m_attaching_tab != 0) { |
2837 | (me.state & Button2Mask) && inside_titlebar && (client != 0 || m_attaching_tab != 0)) { | ||
2838 | // | 2820 | // |
2839 | // drag'n'drop code for tabs | 2821 | // drag'n'drop code for tabs |
2840 | // | 2822 | // |
2841 | FbTk::TextButton &active_button = *m_labelbuttons[(m_attaching_tab==0)?client:m_attaching_tab]; | ||
2842 | 2823 | ||
2843 | if (m_attaching_tab == 0) { | 2824 | // we already grabed and started to drag'n'drop tab |
2844 | if (s_num_grabs > 0) | 2825 | // so we update drag'n'drop-rectangle |
2845 | return; | 2826 | int dx = me.x_root - m_button_grab_x, dy = me.y_root - m_button_grab_y; |
2846 | // start drag'n'drop for tab | ||
2847 | m_attaching_tab = client; | ||
2848 | grabPointer(me.window, False, ButtonMotionMask | | ||
2849 | ButtonReleaseMask, GrabModeAsync, GrabModeAsync, | ||
2850 | None, frame(). theme().moveCursor(), CurrentTime); | ||
2851 | // relative position on button | ||
2852 | m_button_grab_x = me.x; | ||
2853 | m_button_grab_y = me.y; | ||
2854 | // last known root mouse position | ||
2855 | m_last_move_x = me.x_root - me.x; | ||
2856 | m_last_move_y = me.y_root - me.y; | ||
2857 | // hijack extra vars for initial grab location | ||
2858 | m_last_resize_x = me.x_root; | ||
2859 | m_last_resize_y = me.y_root; | ||
2860 | |||
2861 | Fluxbox::instance()->grab(); | ||
2862 | |||
2863 | parent().drawRectangle(screen().rootTheme().opGC(), | ||
2864 | m_last_move_x, m_last_move_y, | ||
2865 | active_button.width(), | ||
2866 | active_button.height()); | ||
2867 | |||
2868 | menu().hide(); | ||
2869 | } else { | ||
2870 | // we already grabed and started to drag'n'drop tab | ||
2871 | // so we update drag'n'drop-rectangle | ||
2872 | int dx = me.x_root - m_button_grab_x, dy = me.y_root - m_button_grab_y; | ||
2873 | |||
2874 | //erase rectangle | ||
2875 | parent().drawRectangle(screen().rootTheme().opGC(), | ||
2876 | m_last_move_x, m_last_move_y, | ||
2877 | active_button.width(), | ||
2878 | active_button.height()); | ||
2879 | |||
2880 | |||
2881 | // redraw rectangle at new pos | ||
2882 | m_last_move_x = dx; | ||
2883 | m_last_move_y = dy; | ||
2884 | parent().drawRectangle(screen().rootTheme().opGC(), | ||
2885 | m_last_move_x, m_last_move_y, | ||
2886 | active_button.width(), | ||
2887 | active_button.height()); | ||
2888 | 2827 | ||
2828 | parent().drawRectangle(screen().rootTheme().opGC(), | ||
2829 | m_last_move_x, m_last_move_y, | ||
2830 | m_last_resize_w, m_last_resize_h); | ||
2831 | parent().drawRectangle(screen().rootTheme().opGC(), | ||
2832 | dx, dy, | ||
2833 | m_last_resize_w, m_last_resize_h); | ||
2889 | 2834 | ||
2890 | } | 2835 | // change remembered position of rectangle |
2836 | m_last_move_x = dx; | ||
2837 | m_last_move_y = dy; | ||
2891 | } | 2838 | } |
2892 | 2839 | ||
2893 | } | 2840 | } |
@@ -3116,7 +3063,7 @@ void FluxboxWindow::startMoving(int x, int y) { | |||
3116 | Fluxbox *fluxbox = Fluxbox::instance(); | 3063 | Fluxbox *fluxbox = Fluxbox::instance(); |
3117 | // grabbing (and masking) on the root window allows us to | 3064 | // grabbing (and masking) on the root window allows us to |
3118 | // freely map and unmap the window we're moving. | 3065 | // freely map and unmap the window we're moving. |
3119 | grabPointer(screen().rootWindow().window(), False, Button1MotionMask | | 3066 | grabPointer(screen().rootWindow().window(), False, ButtonMotionMask | |
3120 | ButtonReleaseMask, GrabModeAsync, GrabModeAsync, | 3067 | ButtonReleaseMask, GrabModeAsync, GrabModeAsync, |
3121 | screen().rootWindow().window(), frame().theme().moveCursor(), CurrentTime); | 3068 | screen().rootWindow().window(), frame().theme().moveCursor(), CurrentTime); |
3122 | 3069 | ||
@@ -3467,14 +3414,64 @@ void FluxboxWindow::stopResizing(bool interrupted) { | |||
3467 | ungrabPointer(CurrentTime); | 3414 | ungrabPointer(CurrentTime); |
3468 | } | 3415 | } |
3469 | 3416 | ||
3417 | void FluxboxWindow::startTabbing(const XButtonEvent &be) { | ||
3418 | |||
3419 | if (s_num_grabs > 0) | ||
3420 | return; | ||
3421 | |||
3422 | m_attaching_tab = 0; | ||
3423 | // determine if we're in titlebar | ||
3424 | Client2ButtonMap::iterator it = | ||
3425 | find_if(m_labelbuttons.begin(), | ||
3426 | m_labelbuttons.end(), | ||
3427 | Compose(bind2nd(equal_to<Window>(), be.window), | ||
3428 | Compose(mem_fun(&TextButton::window), | ||
3429 | Select2nd<Client2ButtonMap::value_type>()))); | ||
3430 | if (it != m_labelbuttons.end()) | ||
3431 | m_attaching_tab = it->first; | ||
3432 | |||
3433 | // start drag'n'drop for tab | ||
3434 | grabPointer(be.window, False, ButtonMotionMask | | ||
3435 | ButtonReleaseMask, GrabModeAsync, GrabModeAsync, | ||
3436 | None, frame().theme().moveCursor(), CurrentTime); | ||
3437 | |||
3438 | // relative position on the button | ||
3439 | m_button_grab_x = be.x; | ||
3440 | m_button_grab_y = be.y; | ||
3441 | // position of the button | ||
3442 | m_last_move_x = be.x_root - be.x; | ||
3443 | m_last_move_y = be.y_root - be.y; | ||
3444 | // hijack extra vars for initial grab location | ||
3445 | m_last_resize_x = be.x_root; | ||
3446 | m_last_resize_y = be.y_root; | ||
3447 | |||
3448 | Fluxbox::instance()->grab(); | ||
3449 | |||
3450 | if (m_attaching_tab) { | ||
3451 | FbTk::TextButton &active_button = *m_labelbuttons[m_attaching_tab]; | ||
3452 | m_last_resize_w = active_button.width(); | ||
3453 | m_last_resize_h = active_button.height(); | ||
3454 | } else { | ||
3455 | m_attaching_tab = m_client; | ||
3456 | unsigned int bw = 2*frame().window().borderWidth()-1; | ||
3457 | m_last_resize_w = frame().width() + bw; | ||
3458 | m_last_resize_h = frame().height() + bw; | ||
3459 | } | ||
3460 | |||
3461 | parent().drawRectangle(screen().rootTheme().opGC(), | ||
3462 | m_last_move_x, m_last_move_y, | ||
3463 | m_last_resize_w, m_last_resize_h); | ||
3464 | |||
3465 | menu().hide(); | ||
3466 | } | ||
3467 | |||
3470 | void FluxboxWindow::attachTo(int x, int y, bool interrupted) { | 3468 | void FluxboxWindow::attachTo(int x, int y, bool interrupted) { |
3471 | if (m_attaching_tab == 0) | 3469 | if (m_attaching_tab == 0) |
3472 | return; | 3470 | return; |
3473 | 3471 | ||
3474 | parent().drawRectangle(screen().rootTheme().opGC(), | 3472 | parent().drawRectangle(screen().rootTheme().opGC(), |
3475 | m_last_move_x, m_last_move_y, | 3473 | m_last_move_x, m_last_move_y, |
3476 | m_labelbuttons[m_attaching_tab]->width(), | 3474 | m_last_resize_w, m_last_resize_h); |
3477 | m_labelbuttons[m_attaching_tab]->height()); | ||
3478 | 3475 | ||
3479 | ungrabPointer(CurrentTime); | 3476 | ungrabPointer(CurrentTime); |
3480 | 3477 | ||
diff --git a/src/Window.hh b/src/Window.hh index 821e86a..66c6f2b 100644 --- a/src/Window.hh +++ b/src/Window.hh | |||
@@ -393,6 +393,8 @@ public: | |||
393 | ResizeDirection getResizeDirection(int x, int y, ResizeModel model); | 393 | ResizeDirection getResizeDirection(int x, int y, ResizeModel model); |
394 | /// stops the resizing | 394 | /// stops the resizing |
395 | void stopResizing(bool interrupted = false); | 395 | void stopResizing(bool interrupted = false); |
396 | /// starts tabbing | ||
397 | void startTabbing(const XButtonEvent &be); | ||
396 | 398 | ||
397 | /** | 399 | /** |
398 | @name accessors | 400 | @name accessors |
diff --git a/src/fluxbox.cc b/src/fluxbox.cc index 9deb39b..341fda8 100644 --- a/src/fluxbox.cc +++ b/src/fluxbox.cc | |||
@@ -643,7 +643,7 @@ void Fluxbox::setupConfigFiles() { | |||
643 | if (create_init) | 643 | if (create_init) |
644 | FbTk::FileUtil::copyFile(DEFAULT_INITFILE, init_file.c_str()); | 644 | FbTk::FileUtil::copyFile(DEFAULT_INITFILE, init_file.c_str()); |
645 | 645 | ||
646 | #define CONFIG_VERSION 6 | 646 | #define CONFIG_VERSION 7 |
647 | FbTk::Resource<int> config_version(m_resourcemanager, 0, | 647 | FbTk::Resource<int> config_version(m_resourcemanager, 0, |
648 | "session.configVersion", "Session.ConfigVersion"); | 648 | "session.configVersion", "Session.ConfigVersion"); |
649 | if (*config_version < CONFIG_VERSION) { | 649 | if (*config_version < CONFIG_VERSION) { |
diff --git a/util/fluxbox-update_configs.cc b/util/fluxbox-update_configs.cc index 921530a..75be474 100644 --- a/util/fluxbox-update_configs.cc +++ b/util/fluxbox-update_configs.cc | |||
@@ -275,6 +275,19 @@ int run_updates(int old_version, FbTk::ResourceManager &rm) { | |||
275 | new_version = 6; | 275 | new_version = 6; |
276 | } | 276 | } |
277 | 277 | ||
278 | if (old_version < 7) { // added StartTabbing command | ||
279 | string whole_keyfile = read_file(keyfilename); | ||
280 | string new_keyfile = ""; | ||
281 | // let's put our new keybindings first, so they're easy to find | ||
282 | new_keyfile += "# start tabbing windows together\n"; | ||
283 | new_keyfile += "OnTitlebar Mouse2 :StartTabbing\n\n"; | ||
284 | new_keyfile += whole_keyfile; // don't forget user's old keybindings | ||
285 | |||
286 | write_file(keyfilename, new_keyfile); | ||
287 | |||
288 | new_version = 7; | ||
289 | } | ||
290 | |||
278 | return new_version; | 291 | return new_version; |
279 | } | 292 | } |
280 | 293 | ||