From cdf6850c95cc490dd4d1de96d18a8db7eb13fb97 Mon Sep 17 00:00:00 2001 From: Jaimos Skriletz Date: Wed, 27 Nov 2024 23:46:39 -0700 Subject: [PATCH] Move shuffle and Maximize grow more options. When using Move shuffle or Maximize grow, add the `all_windows` and `both_sides` options to give more configurability of which windows and boundaries are considered for finding the next closest edge to move or grow to. `all_windows` will consider all windows on the same monitor instead of just the windows in the path the window is moving/growing in. This can be used to move or grow a window to the boundary of a window it is next to, but not in the direct path. `both_sides` will consider both sides of a window when moving or growing. By default only the closest side of a window is considered. This option allows a window to move to the far side of a window vs keep going. This used with `all_windows` can allow one to move a window next to an existing window. This option with Maximize grow can allow a window that is in the interior of another window grow to its same size. --- doc/fvwm3_manpage_source.adoc | 49 ++++++++++++------ fvwm/move_resize.c | 97 ++++++++++++++++++++++++++++------- 2 files changed, 110 insertions(+), 36 deletions(-) diff --git a/doc/fvwm3_manpage_source.adoc b/doc/fvwm3_manpage_source.adoc index 7bd8bc2a7..0fec83a0d 100644 --- a/doc/fvwm3_manpage_source.adoc +++ b/doc/fvwm3_manpage_source.adoc @@ -3864,7 +3864,7 @@ To move a window in a given direction until it hits another window, icon, or screen boundary use: + .... -Move shuffle [Warp] [ewmhiwa] [snap _type_] [layers _min_ _max_] _direction_(s) +Move shuffle [options] _direction_(s) .... + The _direction_ can be _North_/_N_/_Up_/_U_, _East_/_E_/_Right_/_R_, @@ -3880,11 +3880,18 @@ multiple _direction_(s) are given, the window will move the directions in the order of the sequence stated. + The literal option _Warp_ will warp the mouse pointer to the window. +The literal option _all_windows_ will consider all windows on the same +monitor instead of just the windows in the path the window is moving. +This allows moving to the boundary of a window it is next too. The literal +option _both_sides_ will consider both the close side and the far side of +the window (by default only the close side is considered). ++ If the literal option _snap_ followed by a snap _type_ of _windows_, _icons_, or _same_ is given, then the window will only stop if it hits another window, icon, or the same type. If the literal option _layers_ -followed by a _min_ layer and _max_ layer is given, then only windows on -the layers between _min_ and _max_ layers will stop the window. For example: +followed by two integers specifying a _min_ layer and _max_ layer is given, +then only windows on the layers between _min_ and _max_ layers will stop +the window. For example: + .... @@ -3902,7 +3909,8 @@ Move shuffle Up Left Move can be used to moved a window to a specified position: + .... -Move [screen _S_] [desk _N_] [w | m | v]_x_[p | w] [w | m | v]_y_[p | w] [Warp] [ewmhiwa] +Move [screen _S_] [desk _N_] [w | m | v]_x_[p | w] \ + [w | m | v]_y_[p | w] [Warp] [ewmhiwa] .... + This will move the window to the _x_ and _y_ position (see below). @@ -4518,19 +4526,26 @@ until finding any obstacle. The vertical resizing is similar. If both horizontal and vertical values are "grow", it expands vertically first, then horizontally to find space. Instead of the horizontal "grow" argument, "_growleft_" or "_growright_" can be used -respectively "_growup_" and "_growdown_". The optional _flags_ -argument is a space separated list containing the following key words: -_fullscreen_, _ewmhiwa_, _growonwindowlayer_, _growonlayers_, _keepgrowing_, -and _screen_. _fullscreen_ causes the window to become fullscreened if the -appropriate EWMH hint is set. _ewmhiwa_ causes fvwm to ignore the EWMH -working area. _growonwindowlayer_ causes the various grow methods to -ignore windows with a layer other than the current layer of the window -which is maximized. The _growonlayers_ option must have two integer -arguments. The first one is the minimum layer and the second one the -maximum layer to use. Windows that are outside of this range of layers -are ignored by the grow methods. A negative value as the first or -second argument means to assume no minimum or maximum layer. _keepgrowing_ -will allow the window to keep growing beyond any window it is currently +respectively "_growup_" and "_growdown_". ++ +The optional _flags_ argument is a space separated list containing the +following key words: _fullscreen_, _ewmhiwa_, _growonwindowlayer_, +_growonlayers_, _keepgrowing_, _all_windows_, _both_sides_, and _screen_. +_fullscreen_ causes the window to become fullscreened if the appropriate +EWMH hint is set. _ewmhiwa_ causes fvwm to ignore the EWMH working area. +_growonwindowlayer_ causes the various grow methods to ignore windows with +a layer other than the current layer of the window which is maximized. The +_growonlayers_ option must have two integer arguments. The first one is +the minimum layer and the second one the maximum layer to use. Windows that +are outside of this range of layers are ignored by the grow methods. A +negative value as the first or second argument means to assume no minimum +or maximum layer. The _all_windows_ option will consider all windows on the +same monitor in the direction the window is growing. This can be used to +grow a window to the edge of a window it is next to. The option _both_sides_ +will consider both sides of other windows when growing (by default only the +close side is considered). This can be used to grow a window to the +boundaries of a window it is currently inside of. _keepgrowing_ will allow +the window to keep growing beyond any window boundary it is currently touching until it grows into the next closest window boundary. _screen_ must have an argument which specifies the screen on which to operate. + diff --git a/fvwm/move_resize.c b/fvwm/move_resize.c index ec6cc621e..3cc1fe25b 100644 --- a/fvwm/move_resize.c +++ b/fvwm/move_resize.c @@ -103,8 +103,8 @@ static int move_drag_finish_button_mask = extern Window PressedW; -static void grow_to_closest_type(FvwmWindow *, rectangle *, rectangle, int *, - int, bool); +static void grow_to_closest_type(FvwmWindow *, rectangle *, rectangle, + rectangle, int *, int, bool, bool); static void set_geom_win_visible_val(char *, bool); static bool set_geom_win_position_val(char *, int *, bool *, bool *); @@ -364,6 +364,8 @@ static void shuffle_win_to_closest( int snap = SNAP_NONE; int layers[2] = { -1, -1 }; bool ewmh = true; + bool use_both_sides = false; + bool use_all_win = false; cwin = fw->g.frame; get_page_offset_check_visible(&page.x, &page.y, fw); @@ -401,6 +403,14 @@ static void shuffle_win_to_closest( { ewmh = false; } + else if (StrEquals(token, "both_sides")) + { + use_both_sides = true; + } + else if (StrEquals(token, "all_windows")) + { + use_all_win = true; + } else { break; @@ -446,8 +456,9 @@ static void shuffle_win_to_closest( cwin.y = wa.y + wa.height - cwin.height; break; } - grow_to_closest_type(fw, &cwin, bound, layers, - snap, false); + grow_to_closest_type(fw, &cwin, bound, + use_all_win ? wa : cwin, layers, + snap, use_both_sides, false); cwin.height = fw->g.frame.height; break; case DIR_E: @@ -465,8 +476,9 @@ static void shuffle_win_to_closest( cwin.x = wa.x; break; } - grow_to_closest_type(fw, &cwin, bound, layers, - snap, false); + grow_to_closest_type(fw, &cwin, bound, + use_all_win ? wa : cwin, layers, + snap, use_both_sides, false); cwin.x = cwin.x + cwin.width - fw->g.frame.width; cwin.width = fw->g.frame.width; break; @@ -485,8 +497,9 @@ static void shuffle_win_to_closest( cwin.y = wa.y; break; } - grow_to_closest_type(fw, &cwin, bound, layers, - snap, false); + grow_to_closest_type(fw, &cwin, bound, + use_all_win ? wa : cwin, layers, + snap, use_both_sides, false); cwin.y = cwin.y + cwin.height - fw->g.frame.height; cwin.height = fw->g.frame.height; break; @@ -505,8 +518,9 @@ static void shuffle_win_to_closest( cwin.x = wa.x + wa.width - cwin.width; break; } - grow_to_closest_type(fw, &cwin, bound, layers, - snap, false); + grow_to_closest_type(fw, &cwin, bound, + use_all_win ? wa : cwin, layers, + snap, use_both_sides, false); cwin.width = fw->g.frame.width; break; case DIR_NONE: @@ -4903,19 +4917,21 @@ static void move_sticky_window_to_same_page( * on snap type, layers = { min_layer, max_layer }, or the boundary rectangle. */ static void grow_to_closest_type( - FvwmWindow *fw, rectangle *win_r, rectangle bound, int *layers, - int type, bool consider_touching) + FvwmWindow *fw, rectangle *win_r, rectangle bound, rectangle bound2, + int *layers, int type, bool both_sides, bool consider_touching) { FvwmWindow *twin; rectangle other; int maskout = (SNAP_SCREEN | SNAP_SCREEN_WINDOWS | SNAP_SCREEN_ICONS | SNAP_SCREEN_ALL); - /* window coordinates for original window, other, and new */ + /* window coordinates for original window, other, bound, and new */ position pw1; position pw2; position po1; position po2; + position bw1; + position bw2; position new1; position new2; @@ -4924,6 +4940,11 @@ static void grow_to_closest_type( pw1.y = win_r->y; pw2.y = pw1.y + win_r->height; + bw1.x = bound2.x; + bw2.x = bound2.x + bound2.width; + bw1.y = bound2.y; + bw2.y = bound2.y + bound2.height; + new1.x = bound.x; new2.x = new1.x + bound.width; new1.y = bound.y; @@ -4982,32 +5003,56 @@ static void grow_to_closest_type( } /* Shrink left/right edges */ - if (po1.y < pw2.y && po2.y > pw1.y) + if (po1.y < bw2.y && po2.y > bw1.y) { if (new1.x < po2.x && (pw1.x > po2.x || (consider_touching && pw1.x == po2.x))) { new1.x = po2.x; } + else if (both_sides && new1.x < po1.x && + (pw1.x > po1.x || (consider_touching && + pw1.x == po1.x))) + { + new1.x = po1.x; + } if (new2.x > po1.x && (pw2.x < po1.x || (consider_touching && pw2.x == po1.x))) { new2.x = po1.x; } + else if (both_sides && new2.x > po2.x && + (pw2.x < po2.x || (consider_touching && + pw2.x == po2.x))) + { + new2.x = po2.x; + } } /* Shrink top/bottom edges */ - if (po1.x < pw2.x && po2.x > pw1.x) + if (po1.x < bw2.x && po2.x > bw1.x) { if (new1.y < po2.y && (pw1.y > po2.y || (consider_touching && pw1.y == po2.y))) { new1.y = po2.y; } + else if (both_sides && new1.y < po1.y && + (pw1.y > po1.y || (consider_touching && + pw1.y == po1.y))) + { + new1.y = po1.y; + } if (new2.y > po1.y && (pw2.y < po1.y || (consider_touching && pw2.y == po1.y))) { new2.y = po1.y; } + else if (both_sides && new2.y > po2.y && + (pw2.y < po2.y || (consider_touching && + pw2.y == po2.y))) + { + new2.y = po2.y; + } } } win_r->x = new1.x; @@ -5151,6 +5196,8 @@ void CMD_Maximize(F_CMD_ARGS) Bool ignore_working_area = False; Bool do_fullscreen = False; bool consider_touching = true; + bool use_both_sides = false; + bool use_all_win = false; int layers[2] = { -1, -1 }; Bool global_flag_parsed = False; rectangle scr; @@ -5214,6 +5261,16 @@ void CMD_Maximize(F_CMD_ARGS) consider_touching = false; action = taction; } + else if (StrEquals(token, "both_sides")) + { + use_both_sides = true; + action = taction; + } + else if (StrEquals(token, "all_windows")) + { + use_all_win = true; + action = taction; + } else if (StrEquals(token, "fullscreen")) { do_fullscreen = True; @@ -5431,8 +5488,9 @@ void CMD_Maximize(F_CMD_ARGS) bound.height = page.y + scr.y + scr.height - bound.y; } - grow_to_closest_type(fw, &new_g, bound, layers, - SNAP_NONE, consider_touching); + grow_to_closest_type(fw, &new_g, bound, + use_all_win ? scr : new_g, layers, + SNAP_NONE, use_both_sides, consider_touching); } else if (val2 > 0) { @@ -5452,8 +5510,9 @@ void CMD_Maximize(F_CMD_ARGS) bound.width = page.x + scr.x + scr.width - bound.x; } - grow_to_closest_type(fw, &new_g, bound, layers, - SNAP_NONE, consider_touching); + grow_to_closest_type(fw, &new_g, bound, + use_all_win ? scr : new_g, layers, + SNAP_NONE, use_both_sides, consider_touching); } else if (val1 >0) {