Skip to content

Commit

Permalink
Move shuffle and Maximize grow more options.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
somiaj authored and ThomasAdam committed Nov 29, 2024
1 parent 9a0b764 commit 27ffd68
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 36 deletions.
49 changes: 32 additions & 17 deletions doc/fvwm3_manpage_source.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -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_,
Expand All @@ -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:
+

....
Expand All @@ -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).
Expand Down Expand Up @@ -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.
+
Expand Down
97 changes: 78 additions & 19 deletions fvwm/move_resize.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 *);

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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:
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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:
Expand Down Expand Up @@ -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;

Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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)
{
Expand All @@ -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)
{
Expand Down

0 comments on commit 27ffd68

Please sign in to comment.