i3
|
00001 /* 00002 * vim:ts=4:sw=4:expandtab 00003 * 00004 * i3 - an improved dynamic tiling window manager 00005 * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE) 00006 * 00007 * scratchpad.c: Moving windows to the scratchpad and making them visible again. 00008 * 00009 */ 00010 #include "all.h" 00011 00012 /* 00013 * Moves the specified window to the __i3_scratch workspace, making it floating 00014 * and setting the appropriate scratchpad_state. 00015 * 00016 * Gets called upon the command 'move scratchpad'. 00017 * 00018 */ 00019 void scratchpad_move(Con *con) { 00020 if (con->type == CT_WORKSPACE) { 00021 LOG("'move scratchpad' used on a workspace \"%s\". Calling it " 00022 "recursively on all windows on this workspace.\n", con->name); 00023 Con *current; 00024 current = TAILQ_FIRST(&(con->focus_head)); 00025 while (current) { 00026 Con *next = TAILQ_NEXT(current, focused); 00027 scratchpad_move(current); 00028 current = next; 00029 } 00030 return; 00031 } 00032 DLOG("should move con %p to __i3_scratch\n", con); 00033 00034 Con *__i3_scratch = workspace_get("__i3_scratch", NULL); 00035 if (con_get_workspace(con) == __i3_scratch) { 00036 DLOG("This window is already on __i3_scratch.\n"); 00037 return; 00038 } 00039 00040 /* 1: Ensure the window is floating. From now on, we deal with the 00041 * CT_FLOATING_CON. We use automatic == false because the user made the 00042 * choice that this window should be a scratchpad (and floating). */ 00043 floating_enable(con, false); 00044 con = con->parent; 00045 00046 /* 2: Send the window to the __i3_scratch workspace, mainting its 00047 * coordinates and not warping the pointer. */ 00048 Con *focus_next = con_next_focused(con); 00049 con_move_to_workspace(con, __i3_scratch, true, true); 00050 00051 /* 3: If this is the first time this window is used as a scratchpad, we set 00052 * the scratchpad_state to SCRATCHPAD_FRESH. The window will then be 00053 * adjusted in size according to what the user specifies. */ 00054 if (con->scratchpad_state == SCRATCHPAD_NONE) { 00055 DLOG("This window was never used as a scratchpad before.\n"); 00056 con->scratchpad_state = SCRATCHPAD_FRESH; 00057 } 00058 00059 /* 4: Fix focus. Normally, when moving a window to a different output, the 00060 * destination output gets focused. In this case, we don’t want that. */ 00061 con_focus(focus_next); 00062 } 00063 00064 /* 00065 * Either shows the top-most scratchpad window (con == NULL) or shows the 00066 * specified con (if it is scratchpad window). 00067 * 00068 * When called with con == NULL and the currently focused window is a 00069 * scratchpad window, this serves as a shortcut to hide it again (so the user 00070 * can press the same key to quickly look something up). 00071 * 00072 */ 00073 void scratchpad_show(Con *con) { 00074 DLOG("should show scratchpad window %p\n", con); 00075 Con *__i3_scratch = workspace_get("__i3_scratch", NULL); 00076 Con *floating; 00077 00078 /* If this was 'scratchpad show' without criteria, we check if the 00079 * currently focused window is a scratchpad window and should be hidden 00080 * again. */ 00081 if (!con && 00082 (floating = con_inside_floating(focused)) && 00083 floating->scratchpad_state != SCRATCHPAD_NONE) { 00084 DLOG("Focused window is a scratchpad window, hiding it.\n"); 00085 scratchpad_move(focused); 00086 return; 00087 } 00088 00089 /* If this was 'scratchpad show' with criteria, we check if it matches a 00090 * currently visible scratchpad window and hide it. */ 00091 Con *active = con_get_workspace(focused); 00092 Con *current = con_get_workspace(con); 00093 if (con && 00094 (floating = con_inside_floating(con)) && 00095 floating->scratchpad_state != SCRATCHPAD_NONE && 00096 current != __i3_scratch) { 00097 /* If scratchpad window is on the active workspace, then we should hide 00098 * it, otherwise we should move it to the active workspace. */ 00099 if (current == active) { 00100 DLOG("Window is a scratchpad window, hiding it.\n"); 00101 scratchpad_move(con); 00102 return; 00103 } 00104 } 00105 00106 if (con == NULL) { 00107 /* Use the container on __i3_scratch which is highest in the focus 00108 * stack. When moving windows to __i3_scratch, they get inserted at the 00109 * bottom of the stack. */ 00110 con = TAILQ_FIRST(&(__i3_scratch->floating_head)); 00111 00112 if (!con) { 00113 LOG("You don't have any scratchpad windows yet.\n"); 00114 LOG("Use 'move scratchpad' to move a window to the scratchpad.\n"); 00115 return; 00116 } 00117 } 00118 00119 /* 1: Move the window from __i3_scratch to the current workspace. */ 00120 con_move_to_workspace(con, active, true, false); 00121 00122 /* 2: Adjust the size if this window was not adjusted yet. */ 00123 if (con->scratchpad_state == SCRATCHPAD_FRESH) { 00124 DLOG("Adjusting size of this window.\n"); 00125 Con *output = con_get_output(con); 00126 con->rect.width = output->rect.width * 0.5; 00127 con->rect.height = output->rect.height * 0.75; 00128 con->rect.x = output->rect.x + 00129 ((output->rect.width / 2.0) - (con->rect.width / 2.0)); 00130 con->rect.y = output->rect.y + 00131 ((output->rect.height / 2.0) - (con->rect.height / 2.0)); 00132 con->scratchpad_state = SCRATCHPAD_CHANGED; 00133 } 00134 00135 /* Activate active workspace if window is from another workspace to ensure 00136 * proper focus. */ 00137 if (current != active) { 00138 workspace_show(active); 00139 } 00140 00141 con_focus(con_descend_focused(con)); 00142 }