Skip to content

Commit

Permalink
Add window "stick" and "unstick" commands
Browse files Browse the repository at this point in the history
Marking a window as sticky keeps it in its current frame so it will
never be cycled into another frame via next, prev, or when creating
a new split.  A sticky window can be moved around in the frame
stack, but will always remain in that frame until it is explicitly
moved to another frame via exchange* commands.
  • Loading branch information
jcs committed Apr 29, 2018
1 parent 390fcb1 commit 7b72d24
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 2 deletions.
35 changes: 35 additions & 0 deletions src/actions.c
Original file line number Diff line number Diff line change
Expand Up @@ -265,11 +265,13 @@ static cmdret *cmd_setenv (int interactive, struct cmdarg **args);
static cmdret *cmd_shrink (int interactive, struct cmdarg **args);
static cmdret *cmd_source (int interactive, struct cmdarg **args);
static cmdret *cmd_startup_message (int interactive, struct cmdarg **args);
static cmdret *cmd_stick (int interactive, struct cmdarg **args);
static cmdret *cmd_time (int interactive, struct cmdarg **args);
static cmdret *cmd_tmpwm (int interactive, struct cmdarg **args);
static cmdret *cmd_unalias (int interactive, struct cmdarg **args);
static cmdret *cmd_unmanage (int interactive, struct cmdarg **args);
static cmdret *cmd_unsetenv (int interactive, struct cmdarg **args);
static cmdret *cmd_unstick (int interactive, struct cmdarg **args);
static cmdret *cmd_v_split (int interactive, struct cmdarg **args);
static cmdret *cmd_verbexec (int interactive, struct cmdarg **args);
static cmdret *cmd_version (int interactive, struct cmdarg **args);
Expand Down Expand Up @@ -591,6 +593,7 @@ init_user_commands(void)
"Screen: ", arg_NUMBER);
add_command ("startup_message", cmd_startup_message, 1, 1, 1,
"Startup message: ", arg_STRING);
add_command ("stick", cmd_stick, 0, 0, 0);
add_command ("time", cmd_time, 0, 0, 0);
add_command ("title", cmd_rename, 1, 1, 1,
"Set window's title to: ", arg_REST);
Expand All @@ -602,6 +605,7 @@ init_user_commands(void)
"Unmanage: ", arg_REST);
add_command ("unsetenv", cmd_unsetenv, 1, 1, 1,
"Variable: ", arg_STRING);
add_command ("unstick", cmd_unstick, 0, 0, 0);
add_command ("verbexec", cmd_verbexec, 1, 1, 1,
"/bin/sh -c ", arg_SHELLCMD);
add_command ("version", cmd_version, 0, 0, 0);
Expand Down Expand Up @@ -6656,3 +6660,34 @@ cmd_commands (int interactive UNUSED, struct cmdarg **args UNUSED)
sbuf_free (sb);
return ret;
}

cmdret *
cmd_stick (int interactive UNUSED, struct cmdarg **args UNUSED)
{
rp_window *cur = current_window();
rp_frame *frame;

if (cur)
{
frame = find_windows_frame (cur);
if (frame)
cur->sticky_frame = find_windows_frame(cur)->number;
}
else
return cmdret_new (RET_FAILURE, "%s", MESSAGE_NO_MANAGED_WINDOWS);

return cmdret_new (RET_SUCCESS, NULL);
}

cmdret *
cmd_unstick (int interactive UNUSED, struct cmdarg **args UNUSED)
{
rp_window *cur = current_window();

if (cur)
cur->sticky_frame = EMPTY;
else
return cmdret_new (RET_FAILURE, "%s", MESSAGE_NO_MANAGED_WINDOWS);

return cmdret_new (RET_SUCCESS, NULL);
}
4 changes: 4 additions & 0 deletions src/data.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ struct rp_window
is mapped and this is >0 then use the frame (if it exists). */
int intended_frame_number;

/* Frame in which this window should stay unless explicitly moved, rather
* than be cycled into another frame. */
int sticky_frame;

struct list_head node;
};

Expand Down
18 changes: 17 additions & 1 deletion src/group.c
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ group_last_group (void)
{
if (cur != rp_current_group && cur->last_access > last_access) {
most_recent = cur;
last_access = cur->last_access;
last_access = cur->last_access;
}
}
return most_recent;
Expand Down Expand Up @@ -494,6 +494,8 @@ group_last_window (rp_group *g, rp_screen *s)
if (cur->win->last_access >= last_access
&& cur->win != current_window()
&& !find_windows_frame (cur->win)
&& (cur->win->sticky_frame == EMPTY
|| cur->win->sticky_frame == current_frame()->number)
&& (cur->win->scr == s || rp_have_xrandr))
{
most_recent = cur;
Expand All @@ -511,6 +513,7 @@ rp_window *
group_next_window (rp_group *g, rp_window *win)
{
rp_window_elem *cur, *we;
rp_frame *curframe;

/* If there is no window, then get the last accessed one. */
if (win == NULL)
Expand All @@ -522,6 +525,8 @@ group_next_window (rp_group *g, rp_window *win)
if (we == NULL)
return group_last_window (g, win->scr);

curframe = find_windows_frame (win);

/* The window is in this group, so find the next one in the list
that isn't already displayed. */
for (cur = list_next_entry (we, &g->mapped_windows, node);
Expand All @@ -530,6 +535,10 @@ group_next_window (rp_group *g, rp_window *win)
{
if (!find_windows_frame (cur->win) && (cur->win->scr == win->scr || rp_have_xrandr))
{
if (cur->win->sticky_frame != EMPTY && curframe != NULL
&& cur->win->sticky_frame != curframe->number)
continue;

return cur->win;
}
}
Expand All @@ -541,6 +550,7 @@ rp_window *
group_prev_window (rp_group *g, rp_window *win)
{
rp_window_elem *cur, *we;
rp_frame *curframe;

/* If there is no window, then get the last accessed one. */
if (win == NULL)
Expand All @@ -552,6 +562,8 @@ group_prev_window (rp_group *g, rp_window *win)
if (we == NULL)
return group_last_window (g, win->scr);

curframe = find_windows_frame (win);

/* The window is in this group, so find the previous one in the list
that isn't already displayed. */
for (cur = list_prev_entry (we, &g->mapped_windows, node);
Expand All @@ -560,6 +572,10 @@ group_prev_window (rp_group *g, rp_window *win)
{
if (!find_windows_frame (cur->win) && (cur->win->scr == win->scr || rp_have_xrandr))
{
if (cur->win->sticky_frame != EMPTY && curframe != NULL
&& cur->win->sticky_frame != curframe->number)
continue;

return cur->win;
}
}
Expand Down
5 changes: 4 additions & 1 deletion src/split.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ set_frames_window (rp_frame *frame, rp_window *win)
{
frame->win_number = win->number;
win->frame_number = frame->number;
if (win->sticky_frame >= 0)
win->sticky_frame = frame->number;

/* We need to make sure that win and frame are on the same screen,
* since with Xrandr, windows can move from one screen to another.
Expand Down Expand Up @@ -279,7 +281,8 @@ find_window_for_frame (rp_frame *frame)
&& !find_windows_frame (cur->win)
&& cur->win->last_access >= last_access
&& window_fits_in_frame (cur->win, frame)
&& cur->win->frame_number == EMPTY)
&& cur->win->frame_number == EMPTY
&& (cur->win->sticky_frame == EMPTY || cur->win->sticky_frame == frame->number))
{
most_recent = cur;
last_access = cur->win->last_access;
Expand Down
1 change: 1 addition & 0 deletions src/window.c
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ add_to_window_list (rp_screen *s, Window w)
new_window->hints = XAllocSizeHints ();
new_window->colormap = DefaultColormap (dpy, s->screen_num);
new_window->transient = XGetTransientForHint (dpy, new_window->w, &new_window->transient_for);
new_window->sticky_frame = EMPTY;
PRINT_DEBUG (("transient %d\n", new_window->transient));

update_window_gravity (new_window);
Expand Down

0 comments on commit 7b72d24

Please sign in to comment.