2 * vim:ts=4:sw=4:expandtab
4 * i3 - an improved dynamic tiling window manager
5 * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
7 * scratchpad.c: Moving windows to the scratchpad and making them visible again.
13 * Moves the specified window to the __i3_scratch workspace, making it floating
14 * and setting the appropriate scratchpad_state.
16 * Gets called upon the command 'move scratchpad'.
19 void scratchpad_move(Con *con) {
20 DLOG("should move con %p to __i3_scratch\n", con);
22 Con *__i3_scratch = workspace_get("__i3_scratch", NULL);
23 if (con_get_workspace(con) == __i3_scratch) {
24 DLOG("This window is already on __i3_scratch.\n");
28 /* 1: Ensure the window is floating. From now on, we deal with the
29 * CT_FLOATING_CON. We use automatic == false because the user made the
30 * choice that this window should be a scratchpad (and floating). */
31 floating_enable(con, false);
34 /* 2: Send the window to the __i3_scratch workspace, mainting its
35 * coordinates and not warping the pointer. */
36 Con *focus_next = con_next_focused(con);
37 con_move_to_workspace(con, __i3_scratch, true, true);
39 /* 3: If this is the first time this window is used as a scratchpad, we set
40 * the scratchpad_state to SCRATCHPAD_FRESH. The window will then be
41 * adjusted in size according to what the user specifies. */
42 if (con->scratchpad_state == SCRATCHPAD_NONE) {
43 DLOG("This window was never used as a scratchpad before.\n");
44 con->scratchpad_state = SCRATCHPAD_FRESH;
47 /* 4: Fix focus. Normally, when moving a window to a different output, the
48 * destination output gets focused. In this case, we don’t want that. */
49 con_focus(focus_next);
53 * Either shows the top-most scratchpad window (con == NULL) or shows the
54 * specified con (if it is scratchpad window).
56 * When called with con == NULL and the currently focused window is a
57 * scratchpad window, this serves as a shortcut to hide it again (so the user
58 * can press the same key to quickly look something up).
61 void scratchpad_show(Con *con) {
62 DLOG("should show scratchpad window %p\n", con);
63 Con *__i3_scratch = workspace_get("__i3_scratch", NULL);
66 /* If this was 'scratchpad show' without criteria, we check if the
67 * currently focused window is a scratchpad window and should be hidden
70 (floating = con_inside_floating(focused)) &&
71 floating->scratchpad_state != SCRATCHPAD_NONE) {
72 DLOG("Focused window is a scratchpad window, hiding it.\n");
73 scratchpad_move(focused);
77 /* If this was 'scratchpad show' with criteria, we check if it matches a
78 * currently visible scratchpad window and hide it. */
80 (floating = con_inside_floating(con)) &&
81 floating->scratchpad_state != SCRATCHPAD_NONE &&
82 con_get_workspace(con) != __i3_scratch) {
83 DLOG("Window is a scratchpad window, hiding it.\n");
88 Con *ws = con_get_workspace(focused);
90 /* Use the container on __i3_scratch which is highest in the focus
91 * stack. When moving windows to __i3_scratch, they get inserted at the
92 * bottom of the stack. */
93 con = TAILQ_FIRST(&(__i3_scratch->floating_head));
96 LOG("You don't have any scratchpad windows yet.\n");
97 LOG("Use 'move scratchpad' to move a window to the scratchpad.\n");
102 /* 1: Move the window from __i3_scratch to the current workspace. */
103 con_move_to_workspace(con, ws, true, false);
105 /* 2: Adjust the size if this window was not adjusted yet. */
106 if (con->scratchpad_state == SCRATCHPAD_FRESH) {
107 DLOG("Adjusting size of this window.\n");
108 Con *output = con_get_output(con);
109 con->rect.width = output->rect.width * 0.5;
110 con->rect.height = output->rect.height * 0.75;
111 con->rect.x = (output->rect.width / 2.0) - (con->rect.width / 2.0);
112 con->rect.y = (output->rect.height / 2.0) - (con->rect.height / 2.0);
113 con->scratchpad_state = SCRATCHPAD_CHANGED;
116 con_focus(con_descend_focused(con));