Implement scratchpad functionality (see userguide)
This commit is contained in:
parent
311b9e24df
commit
08986a1798
|
@ -1456,6 +1456,40 @@ bindsym mod+Shift+w reload
|
||||||
bindsym mod+Shift+e exit
|
bindsym mod+Shift+e exit
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
|
=== Scratchpad
|
||||||
|
|
||||||
|
There are two commands to use any existing window as scratchpad window. +move
|
||||||
|
scratchpad+ will move a window to the scratchpad workspace. This will make it
|
||||||
|
invisible until you show it again. There is no way to open that workspace.
|
||||||
|
Instead, when using +scratchpad show+, the window will be shown again, as a
|
||||||
|
floating window, centered on your current workspace (using +scratchpad show+ on
|
||||||
|
a visible scratchpad window will make it hidden again, so you can have a
|
||||||
|
keybinding to toggle).
|
||||||
|
|
||||||
|
As the name indicates, this is useful for having a window with your favorite
|
||||||
|
editor always at hand. However, you can also use this for other permanently
|
||||||
|
running applications which you don’t want to see all the time: Your music
|
||||||
|
player, alsamixer, maybe even your mail client…?
|
||||||
|
|
||||||
|
*Syntax*:
|
||||||
|
---------------
|
||||||
|
move scratchpad
|
||||||
|
|
||||||
|
scratchpad show
|
||||||
|
---------------
|
||||||
|
|
||||||
|
*Examples*:
|
||||||
|
------------------------------------------------
|
||||||
|
# Make the currently focused window a scratchpad
|
||||||
|
bindsym mod+Shift+minus move scratchpad
|
||||||
|
|
||||||
|
# Show the first scratchpad window
|
||||||
|
bindsym mod+minus scratchpad show
|
||||||
|
|
||||||
|
# Show the sup-mail scratchpad window, if any.
|
||||||
|
bindsym mod4+s [title="^Sup ::"] scratchpad show
|
||||||
|
------------------------------------------------
|
||||||
|
|
||||||
[[multi_monitor]]
|
[[multi_monitor]]
|
||||||
|
|
||||||
== Multiple monitors
|
== Multiple monitors
|
||||||
|
|
|
@ -72,5 +72,6 @@
|
||||||
#include "regex.h"
|
#include "regex.h"
|
||||||
#include "libi3.h"
|
#include "libi3.h"
|
||||||
#include "startup.h"
|
#include "startup.h"
|
||||||
|
#include "scratchpad.h"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -480,6 +480,12 @@ struct Con {
|
||||||
|
|
||||||
/** callbacks */
|
/** callbacks */
|
||||||
void(*on_remove_child)(Con *);
|
void(*on_remove_child)(Con *);
|
||||||
|
|
||||||
|
enum {
|
||||||
|
SCRATCHPAD_NONE = 0,
|
||||||
|
SCRATCHPAD_FRESH = 1,
|
||||||
|
SCRATCHPAD_CHANGED = 2
|
||||||
|
} scratchpad_state;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -133,6 +133,8 @@ output { WS_STRING; return TOK_OUTPUT; }
|
||||||
focus { return TOK_FOCUS; }
|
focus { return TOK_FOCUS; }
|
||||||
move { return TOK_MOVE; }
|
move { return TOK_MOVE; }
|
||||||
open { return TOK_OPEN; }
|
open { return TOK_OPEN; }
|
||||||
|
scratchpad { return TOK_SCRATCHPAD; }
|
||||||
|
show { return TOK_SHOW; }
|
||||||
split { return TOK_SPLIT; }
|
split { return TOK_SPLIT; }
|
||||||
horizontal { return TOK_HORIZONTAL; }
|
horizontal { return TOK_HORIZONTAL; }
|
||||||
vertical { return TOK_VERTICAL; }
|
vertical { return TOK_VERTICAL; }
|
||||||
|
|
|
@ -155,6 +155,8 @@ bool definitelyGreaterThan(float a, float b, float epsilon) {
|
||||||
%token TOK_OPEN "open"
|
%token TOK_OPEN "open"
|
||||||
%token TOK_NEXT "next"
|
%token TOK_NEXT "next"
|
||||||
%token TOK_PREV "prev"
|
%token TOK_PREV "prev"
|
||||||
|
%token TOK_SCRATCHPAD "scratchpad"
|
||||||
|
%token TOK_SHOW "show"
|
||||||
%token TOK_SPLIT "split"
|
%token TOK_SPLIT "split"
|
||||||
%token TOK_HORIZONTAL "horizontal"
|
%token TOK_HORIZONTAL "horizontal"
|
||||||
%token TOK_VERTICAL "vertical"
|
%token TOK_VERTICAL "vertical"
|
||||||
|
@ -385,6 +387,7 @@ operation:
|
||||||
| mark
|
| mark
|
||||||
| resize
|
| resize
|
||||||
| nop
|
| nop
|
||||||
|
| scratchpad
|
||||||
| mode
|
| mode
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -636,6 +639,11 @@ workspace:
|
||||||
}
|
}
|
||||||
| TOK_WORKSPACE STR
|
| TOK_WORKSPACE STR
|
||||||
{
|
{
|
||||||
|
if (strncasecmp($2, "__i3_", strlen("__i3_")) == 0) {
|
||||||
|
printf("You cannot switch to the i3 internal workspaces.\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
printf("should switch to workspace %s\n", $2);
|
printf("should switch to workspace %s\n", $2);
|
||||||
|
|
||||||
Con *ws = con_get_workspace(focused);
|
Con *ws = con_get_workspace(focused);
|
||||||
|
@ -798,6 +806,11 @@ move:
|
||||||
}
|
}
|
||||||
| TOK_MOVE TOK_WORKSPACE STR
|
| TOK_MOVE TOK_WORKSPACE STR
|
||||||
{
|
{
|
||||||
|
if (strncasecmp($3, "__i3_", strlen("__i3_")) == 0) {
|
||||||
|
printf("You cannot switch to the i3 internal workspaces.\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
owindow *current;
|
owindow *current;
|
||||||
|
|
||||||
/* Error out early to not create a non-existing workspace (in
|
/* Error out early to not create a non-existing workspace (in
|
||||||
|
@ -855,7 +868,7 @@ move:
|
||||||
{
|
{
|
||||||
owindow *current;
|
owindow *current;
|
||||||
|
|
||||||
printf("should move window to output %s", $3);
|
printf("should move window to output %s\n", $3);
|
||||||
|
|
||||||
HANDLE_EMPTY_MATCH;
|
HANDLE_EMPTY_MATCH;
|
||||||
|
|
||||||
|
@ -880,8 +893,10 @@ move:
|
||||||
output = get_output_by_name($3);
|
output = get_output_by_name($3);
|
||||||
free($3);
|
free($3);
|
||||||
|
|
||||||
if (!output)
|
if (!output) {
|
||||||
|
printf("No such output found.\n");
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* get visible workspace on output */
|
/* get visible workspace on output */
|
||||||
Con *ws = NULL;
|
Con *ws = NULL;
|
||||||
|
@ -896,6 +911,20 @@ move:
|
||||||
|
|
||||||
tree_render();
|
tree_render();
|
||||||
}
|
}
|
||||||
|
| TOK_MOVE TOK_SCRATCHPAD
|
||||||
|
{
|
||||||
|
printf("should move window to scratchpad\n");
|
||||||
|
owindow *current;
|
||||||
|
|
||||||
|
HANDLE_EMPTY_MATCH;
|
||||||
|
|
||||||
|
TAILQ_FOREACH(current, &owindows, owindows) {
|
||||||
|
printf("matching: %p / %s\n", current->con, current->con->name);
|
||||||
|
scratchpad_move(current->con);
|
||||||
|
}
|
||||||
|
|
||||||
|
tree_render();
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
append_layout:
|
append_layout:
|
||||||
|
@ -969,6 +998,26 @@ nop:
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
scratchpad:
|
||||||
|
TOK_SCRATCHPAD TOK_SHOW
|
||||||
|
{
|
||||||
|
printf("should show scratchpad window\n");
|
||||||
|
owindow *current;
|
||||||
|
|
||||||
|
if (match_is_empty(¤t_match)) {
|
||||||
|
scratchpad_show(NULL);
|
||||||
|
} else {
|
||||||
|
TAILQ_FOREACH(current, &owindows, owindows) {
|
||||||
|
printf("matching: %p / %s\n", current->con, current->con->name);
|
||||||
|
scratchpad_show(current->con);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tree_render();
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
resize:
|
resize:
|
||||||
TOK_RESIZE resize_way direction resize_px resize_tiling
|
TOK_RESIZE resize_way direction resize_px resize_tiling
|
||||||
{
|
{
|
||||||
|
|
|
@ -657,6 +657,7 @@ void con_move_to_workspace(Con *con, Con *workspace, bool fix_coordinates, bool
|
||||||
|
|
||||||
/* 7: focus the con on the target workspace (the X focus is only updated by
|
/* 7: focus the con on the target workspace (the X focus is only updated by
|
||||||
* calling tree_render(), so for the "real" focus this is a no-op). */
|
* calling tree_render(), so for the "real" focus this is a no-op). */
|
||||||
|
if (workspace->name[0] != '_' || workspace->name[1] != '_')
|
||||||
con_focus(con_descend_focused(con));
|
con_focus(con_descend_focused(con));
|
||||||
|
|
||||||
/* 8: when moving to a visible workspace on a different output, we keep the
|
/* 8: when moving to a visible workspace on a different output, we keep the
|
||||||
|
|
15
src/ipc.c
15
src/ipc.c
|
@ -166,6 +166,19 @@ void dump_node(yajl_gen gen, struct Con *con, bool inplace_restart) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ystr("scratchpad_state");
|
||||||
|
switch (con->scratchpad_state) {
|
||||||
|
case SCRATCHPAD_NONE:
|
||||||
|
ystr("none");
|
||||||
|
break;
|
||||||
|
case SCRATCHPAD_FRESH:
|
||||||
|
ystr("fresh");
|
||||||
|
break;
|
||||||
|
case SCRATCHPAD_CHANGED:
|
||||||
|
ystr("changed");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
ystr("percent");
|
ystr("percent");
|
||||||
if (con->percent == 0.0)
|
if (con->percent == 0.0)
|
||||||
y(null);
|
y(null);
|
||||||
|
@ -330,6 +343,8 @@ IPC_HANDLER(get_workspaces) {
|
||||||
|
|
||||||
Con *output;
|
Con *output;
|
||||||
TAILQ_FOREACH(output, &(croot->nodes_head), nodes) {
|
TAILQ_FOREACH(output, &(croot->nodes_head), nodes) {
|
||||||
|
if (output->name[0] == '_' && output->name[1] == '_')
|
||||||
|
continue;
|
||||||
Con *ws;
|
Con *ws;
|
||||||
TAILQ_FOREACH(ws, &(output_get_content(output)->nodes_head), nodes) {
|
TAILQ_FOREACH(ws, &(output_get_content(output)->nodes_head), nodes) {
|
||||||
assert(ws->type == CT_WORKSPACE);
|
assert(ws->type == CT_WORKSPACE);
|
||||||
|
|
|
@ -221,6 +221,9 @@ void render_con(Con *con, bool render_fullscreen) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (con->layout == L_OUTPUT) {
|
if (con->layout == L_OUTPUT) {
|
||||||
|
/* Skip i3-internal outputs */
|
||||||
|
if (con->name[0] == '_' && con->name[1] == '_')
|
||||||
|
return;
|
||||||
render_l_output(con);
|
render_l_output(con);
|
||||||
} else if (con->type == CT_ROOT) {
|
} else if (con->type == CT_ROOT) {
|
||||||
Con *output;
|
Con *output;
|
||||||
|
@ -234,6 +237,8 @@ void render_con(Con *con, bool render_fullscreen) {
|
||||||
* windows/containers so that they overlap on another output. */
|
* windows/containers so that they overlap on another output. */
|
||||||
DLOG("Rendering floating windows:\n");
|
DLOG("Rendering floating windows:\n");
|
||||||
TAILQ_FOREACH(output, &(con->nodes_head), nodes) {
|
TAILQ_FOREACH(output, &(con->nodes_head), nodes) {
|
||||||
|
if (output->name[0] == '_' && output->name[1] == '_')
|
||||||
|
continue;
|
||||||
/* Get the active workspace of that output */
|
/* Get the active workspace of that output */
|
||||||
Con *content = output_get_content(output);
|
Con *content = output_get_content(output);
|
||||||
Con *workspace = TAILQ_FIRST(&(content->focus_head));
|
Con *workspace = TAILQ_FIRST(&(content->focus_head));
|
||||||
|
|
56
src/tree.c
56
src/tree.c
|
@ -15,7 +15,48 @@ struct Con *focused;
|
||||||
struct all_cons_head all_cons = TAILQ_HEAD_INITIALIZER(all_cons);
|
struct all_cons_head all_cons = TAILQ_HEAD_INITIALIZER(all_cons);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Loads tree from ~/.i3/_restart.json (used for in-place restarts).
|
* Create the pseudo-output __i3. Output-independent workspaces such as
|
||||||
|
* __i3_scratch will live there.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static Con *_create___i3() {
|
||||||
|
Con *__i3 = con_new(croot, NULL);
|
||||||
|
FREE(__i3->name);
|
||||||
|
__i3->name = sstrdup("__i3");
|
||||||
|
__i3->type = CT_OUTPUT;
|
||||||
|
__i3->layout = L_OUTPUT;
|
||||||
|
con_fix_percent(croot);
|
||||||
|
x_set_name(__i3, "[i3 con] pseudo-output __i3");
|
||||||
|
/* For retaining the correct position/size of a scratchpad window, the
|
||||||
|
* dimensions of the real outputs should be multiples of the __i3
|
||||||
|
* pseudo-output. */
|
||||||
|
__i3->rect.width = 1280;
|
||||||
|
__i3->rect.height = 1024;
|
||||||
|
|
||||||
|
/* Add a content container. */
|
||||||
|
DLOG("adding main content container\n");
|
||||||
|
Con *content = con_new(NULL, NULL);
|
||||||
|
content->type = CT_CON;
|
||||||
|
FREE(content->name);
|
||||||
|
content->name = sstrdup("content");
|
||||||
|
|
||||||
|
x_set_name(content, "[i3 con] content __i3");
|
||||||
|
con_attach(content, __i3, false);
|
||||||
|
|
||||||
|
/* Attach the __i3_scratch workspace. */
|
||||||
|
Con *ws = con_new(NULL, NULL);
|
||||||
|
ws->type = CT_WORKSPACE;
|
||||||
|
ws->num = -1;
|
||||||
|
ws->name = sstrdup("__i3_scratch");
|
||||||
|
con_attach(ws, content, false);
|
||||||
|
x_set_name(ws, "[i3 con] workspace __i3_scratch");
|
||||||
|
ws->fullscreen_mode = CF_OUTPUT;
|
||||||
|
|
||||||
|
return __i3;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Loads tree from 'path' (used for in-place restarts).
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
bool tree_restore(const char *path, xcb_get_geometry_reply_t *geometry) {
|
bool tree_restore(const char *path, xcb_get_geometry_reply_t *geometry) {
|
||||||
|
@ -47,6 +88,17 @@ bool tree_restore(const char *path, xcb_get_geometry_reply_t *geometry) {
|
||||||
Con *ws = TAILQ_FIRST(&(out->nodes_head));
|
Con *ws = TAILQ_FIRST(&(out->nodes_head));
|
||||||
printf("ws = %p\n", ws);
|
printf("ws = %p\n", ws);
|
||||||
|
|
||||||
|
/* For in-place restarting into v4.2, we need to make sure the new
|
||||||
|
* pseudo-output __i3 is present. */
|
||||||
|
if (strcmp(out->name, "__i3") != 0) {
|
||||||
|
DLOG("Adding pseudo-output __i3 during inplace restart\n");
|
||||||
|
Con *__i3 = _create___i3();
|
||||||
|
/* Ensure that it is the first output, other places in the code make
|
||||||
|
* that assumption. */
|
||||||
|
TAILQ_REMOVE(&(croot->nodes_head), __i3, nodes);
|
||||||
|
TAILQ_INSERT_HEAD(&(croot->nodes_head), __i3, nodes);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,6 +118,8 @@ void tree_init(xcb_get_geometry_reply_t *geometry) {
|
||||||
geometry->width,
|
geometry->width,
|
||||||
geometry->height
|
geometry->height
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_create___i3();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -185,6 +185,10 @@ static void workspace_reassign_sticky(Con *con) {
|
||||||
static void _workspace_show(Con *workspace, bool changed_num_workspaces) {
|
static void _workspace_show(Con *workspace, bool changed_num_workspaces) {
|
||||||
Con *current, *old = NULL;
|
Con *current, *old = NULL;
|
||||||
|
|
||||||
|
/* safe-guard against showing i3-internal workspaces like __i3_scratch */
|
||||||
|
if (workspace->name[0] == '_' && workspace->name[1] == '_')
|
||||||
|
return;
|
||||||
|
|
||||||
/* disable fullscreen for the other workspaces and get the workspace we are
|
/* disable fullscreen for the other workspaces and get the workspace we are
|
||||||
* currently on. */
|
* currently on. */
|
||||||
TAILQ_FOREACH(current, &(workspace->parent->nodes_head), nodes) {
|
TAILQ_FOREACH(current, &(workspace->parent->nodes_head), nodes) {
|
||||||
|
@ -278,7 +282,10 @@ Con* workspace_next() {
|
||||||
next = TAILQ_NEXT(current, nodes);
|
next = TAILQ_NEXT(current, nodes);
|
||||||
} else {
|
} else {
|
||||||
/* If currently a numbered workspace, find next numbered workspace. */
|
/* If currently a numbered workspace, find next numbered workspace. */
|
||||||
TAILQ_FOREACH(output, &(croot->nodes_head), nodes)
|
TAILQ_FOREACH(output, &(croot->nodes_head), nodes) {
|
||||||
|
/* Skip outputs starting with __, they are internal. */
|
||||||
|
if (output->name[0] == '_' && output->name[1] == '_')
|
||||||
|
continue;
|
||||||
NODES_FOREACH(output_get_content(output)) {
|
NODES_FOREACH(output_get_content(output)) {
|
||||||
if (child->type != CT_WORKSPACE)
|
if (child->type != CT_WORKSPACE)
|
||||||
continue;
|
continue;
|
||||||
|
@ -291,11 +298,15 @@ Con* workspace_next() {
|
||||||
next = child;
|
next = child;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Find next named workspace. */
|
/* Find next named workspace. */
|
||||||
if (!next) {
|
if (!next) {
|
||||||
bool found_current = false;
|
bool found_current = false;
|
||||||
TAILQ_FOREACH(output, &(croot->nodes_head), nodes)
|
TAILQ_FOREACH(output, &(croot->nodes_head), nodes) {
|
||||||
|
/* Skip outputs starting with __, they are internal. */
|
||||||
|
if (output->name[0] == '_' && output->name[1] == '_')
|
||||||
|
continue;
|
||||||
NODES_FOREACH(output_get_content(output)) {
|
NODES_FOREACH(output_get_content(output)) {
|
||||||
if (child->type != CT_WORKSPACE)
|
if (child->type != CT_WORKSPACE)
|
||||||
continue;
|
continue;
|
||||||
|
@ -307,10 +318,14 @@ Con* workspace_next() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Find first workspace. */
|
/* Find first workspace. */
|
||||||
if (!next) {
|
if (!next) {
|
||||||
TAILQ_FOREACH(output, &(croot->nodes_head), nodes)
|
TAILQ_FOREACH(output, &(croot->nodes_head), nodes) {
|
||||||
|
/* Skip outputs starting with __, they are internal. */
|
||||||
|
if (output->name[0] == '_' && output->name[1] == '_')
|
||||||
|
continue;
|
||||||
NODES_FOREACH(output_get_content(output)) {
|
NODES_FOREACH(output_get_content(output)) {
|
||||||
if (child->type != CT_WORKSPACE)
|
if (child->type != CT_WORKSPACE)
|
||||||
continue;
|
continue;
|
||||||
|
@ -318,6 +333,7 @@ Con* workspace_next() {
|
||||||
next = child;
|
next = child;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
workspace_next_end:
|
workspace_next_end:
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
@ -338,7 +354,10 @@ Con* workspace_prev() {
|
||||||
prev = NULL;
|
prev = NULL;
|
||||||
} else {
|
} else {
|
||||||
/* If numbered workspace, find previous numbered workspace. */
|
/* If numbered workspace, find previous numbered workspace. */
|
||||||
TAILQ_FOREACH_REVERSE(output, &(croot->nodes_head), nodes_head, nodes)
|
TAILQ_FOREACH_REVERSE(output, &(croot->nodes_head), nodes_head, nodes) {
|
||||||
|
/* Skip outputs starting with __, they are internal. */
|
||||||
|
if (output->name[0] == '_' && output->name[1] == '_')
|
||||||
|
continue;
|
||||||
NODES_FOREACH_REVERSE(output_get_content(output)) {
|
NODES_FOREACH_REVERSE(output_get_content(output)) {
|
||||||
if (child->type != CT_WORKSPACE || child->num == -1)
|
if (child->type != CT_WORKSPACE || child->num == -1)
|
||||||
continue;
|
continue;
|
||||||
|
@ -349,11 +368,15 @@ Con* workspace_prev() {
|
||||||
prev = child;
|
prev = child;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Find previous named workspace. */
|
/* Find previous named workspace. */
|
||||||
if (!prev) {
|
if (!prev) {
|
||||||
bool found_current = false;
|
bool found_current = false;
|
||||||
TAILQ_FOREACH_REVERSE(output, &(croot->nodes_head), nodes_head, nodes)
|
TAILQ_FOREACH_REVERSE(output, &(croot->nodes_head), nodes_head, nodes) {
|
||||||
|
/* Skip outputs starting with __, they are internal. */
|
||||||
|
if (output->name[0] == '_' && output->name[1] == '_')
|
||||||
|
continue;
|
||||||
NODES_FOREACH_REVERSE(output_get_content(output)) {
|
NODES_FOREACH_REVERSE(output_get_content(output)) {
|
||||||
if (child->type != CT_WORKSPACE)
|
if (child->type != CT_WORKSPACE)
|
||||||
continue;
|
continue;
|
||||||
|
@ -365,10 +388,14 @@ Con* workspace_prev() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Find last workspace. */
|
/* Find last workspace. */
|
||||||
if (!prev) {
|
if (!prev) {
|
||||||
TAILQ_FOREACH_REVERSE(output, &(croot->nodes_head), nodes_head, nodes)
|
TAILQ_FOREACH_REVERSE(output, &(croot->nodes_head), nodes_head, nodes) {
|
||||||
|
/* Skip outputs starting with __, they are internal. */
|
||||||
|
if (output->name[0] == '_' && output->name[1] == '_')
|
||||||
|
continue;
|
||||||
NODES_FOREACH_REVERSE(output_get_content(output)) {
|
NODES_FOREACH_REVERSE(output_get_content(output)) {
|
||||||
if (child->type != CT_WORKSPACE)
|
if (child->type != CT_WORKSPACE)
|
||||||
continue;
|
continue;
|
||||||
|
@ -376,6 +403,7 @@ Con* workspace_prev() {
|
||||||
prev = child;
|
prev = child;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
workspace_prev_end:
|
workspace_prev_end:
|
||||||
return prev;
|
return prev;
|
||||||
|
|
|
@ -256,6 +256,7 @@ sub get_workspace_names {
|
||||||
my @outputs = @{$tree->{nodes}};
|
my @outputs = @{$tree->{nodes}};
|
||||||
my @cons;
|
my @cons;
|
||||||
for my $output (@outputs) {
|
for my $output (@outputs) {
|
||||||
|
next if $output->{name} eq '__i3';
|
||||||
# get the first CT_CON of each output
|
# get the first CT_CON of each output
|
||||||
my $content = first { $_->{type} == 2 } @{$output->{nodes}};
|
my $content = first { $_->{type} == 2 } @{$output->{nodes}};
|
||||||
@cons = (@cons, @{$content->{nodes}});
|
@cons = (@cons, @{$content->{nodes}});
|
||||||
|
@ -336,11 +337,11 @@ sub get_dock_clients {
|
||||||
@{$output->{nodes}});
|
@{$output->{nodes}});
|
||||||
} elsif ($which eq 'top') {
|
} elsif ($which eq 'top') {
|
||||||
my $first = first { $_->{type} == 5 } @{$output->{nodes}};
|
my $first = first { $_->{type} == 5 } @{$output->{nodes}};
|
||||||
@docked = (@docked, @{$first->{nodes}});
|
@docked = (@docked, @{$first->{nodes}}) if defined($first);
|
||||||
} elsif ($which eq 'bottom') {
|
} elsif ($which eq 'bottom') {
|
||||||
my @matching = grep { $_->{type} == 5 } @{$output->{nodes}};
|
my @matching = grep { $_->{type} == 5 } @{$output->{nodes}};
|
||||||
my $last = $matching[-1];
|
my $last = $matching[-1];
|
||||||
@docked = (@docked, @{$last->{nodes}});
|
@docked = (@docked, @{$last->{nodes}}) if defined($last);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return @docked;
|
return @docked;
|
||||||
|
@ -361,6 +362,7 @@ sub focused_ws {
|
||||||
my @outputs = @{$tree->{nodes}};
|
my @outputs = @{$tree->{nodes}};
|
||||||
my @cons;
|
my @cons;
|
||||||
for my $output (@outputs) {
|
for my $output (@outputs) {
|
||||||
|
next if $output->{name} eq '__i3';
|
||||||
# get the first CT_CON of each output
|
# get the first CT_CON of each output
|
||||||
my $content = first { $_->{type} == 2 } @{$output->{nodes}};
|
my $content = first { $_->{type} == 2 } @{$output->{nodes}};
|
||||||
my $first = first { $_->{fullscreen_mode} == 1 } @{$content->{nodes}};
|
my $first = first { $_->{fullscreen_mode} == 1 } @{$content->{nodes}};
|
||||||
|
|
|
@ -46,6 +46,7 @@ my $expected = {
|
||||||
swallows => $ignore,
|
swallows => $ignore,
|
||||||
percent => undef,
|
percent => undef,
|
||||||
layout => 'default',
|
layout => 'default',
|
||||||
|
scratchpad_state => 'none',
|
||||||
focus => $ignore,
|
focus => $ignore,
|
||||||
focused => JSON::XS::false,
|
focused => JSON::XS::false,
|
||||||
urgent => JSON::XS::false,
|
urgent => JSON::XS::false,
|
||||||
|
|
Loading…
Reference in New Issue