Implement clients going automatically into floating
This commit is contained in:
parent
706c44509e
commit
0cb5d7448d
|
@ -242,6 +242,10 @@ struct Font {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
struct Client {
|
struct Client {
|
||||||
|
/* initialized will be set to true if the client was fully initialized by
|
||||||
|
* manage_window() and all functions can be used normally */
|
||||||
|
bool initialized;
|
||||||
|
|
||||||
/* if you set a client to floating and set it back to managed, it does remember its old
|
/* if you set a client to floating and set it back to managed, it does remember its old
|
||||||
position and *tries* to get back there */
|
position and *tries* to get back there */
|
||||||
Cell old_position;
|
Cell old_position;
|
||||||
|
@ -284,8 +288,11 @@ struct Client {
|
||||||
/* fullscreen is pretty obvious */
|
/* fullscreen is pretty obvious */
|
||||||
bool fullscreen;
|
bool fullscreen;
|
||||||
|
|
||||||
/* floating? (= not in tiling layout) */
|
/* floating? (= not in tiling layout) This cannot be simply a bool because we want to keep track
|
||||||
bool floating;
|
* of whether the status was set by the application (by setting WM_CLASS to tools for example) or
|
||||||
|
* by the user. The user’s choice overwrites automatic mode, of course. The order of the values
|
||||||
|
* is important because we check with >= FLOATING_AUTO_ON if a client is floating. */
|
||||||
|
enum { FLOATING_AUTO_OFF = 0, FLOATING_USER_OFF = 1, FLOATING_AUTO_ON = 2, FLOATING_USER_ON = 3 } floating;
|
||||||
|
|
||||||
/* Ensure TITLEBAR_TOP maps to 0 because we use calloc for initialization later */
|
/* Ensure TITLEBAR_TOP maps to 0 because we use calloc for initialization later */
|
||||||
enum { TITLEBAR_TOP = 0, TITLEBAR_LEFT, TITLEBAR_RIGHT, TITLEBAR_BOTTOM, TITLEBAR_OFF } titlebar_position;
|
enum { TITLEBAR_TOP = 0, TITLEBAR_LEFT, TITLEBAR_RIGHT, TITLEBAR_BOTTOM, TITLEBAR_OFF } titlebar_position;
|
||||||
|
|
|
@ -16,8 +16,11 @@
|
||||||
* Correctly takes care of the position/size (separately stored for tiling/floating mode)
|
* Correctly takes care of the position/size (separately stored for tiling/floating mode)
|
||||||
* and repositions/resizes/redecorates the client.
|
* and repositions/resizes/redecorates the client.
|
||||||
*
|
*
|
||||||
|
* If the automatic flag is set to true, this was an automatic update by a change of the
|
||||||
|
* window class from the application which can be overwritten by the user.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
void toggle_floating_mode(xcb_connection_t *conn, Client *client);
|
void toggle_floating_mode(xcb_connection_t *conn, Client *client, bool automatic);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called whenever the user clicks on a border (not the titlebar!) of a floating window.
|
* Called whenever the user clicks on a border (not the titlebar!) of a floating window.
|
||||||
|
|
|
@ -186,7 +186,7 @@ void client_toggle_fullscreen(xcb_connection_t *conn, Client *client) {
|
||||||
LOG("leaving fullscreen mode\n");
|
LOG("leaving fullscreen mode\n");
|
||||||
client->fullscreen = false;
|
client->fullscreen = false;
|
||||||
workspace->fullscreen_client = NULL;
|
workspace->fullscreen_client = NULL;
|
||||||
if (client->floating) {
|
if (client->floating >= FLOATING_AUTO_ON) {
|
||||||
/* For floating clients it’s enough if we just reconfigure that window (in fact,
|
/* For floating clients it’s enough if we just reconfigure that window (in fact,
|
||||||
* re-rendering the layout will not update the client.) */
|
* re-rendering the layout will not update the client.) */
|
||||||
reposition_client(conn, client);
|
reposition_client(conn, client);
|
||||||
|
|
|
@ -617,7 +617,7 @@ void show_workspace(xcb_connection_t *conn, int workspace) {
|
||||||
|
|
||||||
/* Map all floating clients */
|
/* Map all floating clients */
|
||||||
SLIST_FOREACH(client, &(c_ws->focus_stack), focus_clients) {
|
SLIST_FOREACH(client, &(c_ws->focus_stack), focus_clients) {
|
||||||
if (!client->floating)
|
if (client->floating <= FLOATING_USER_OFF)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
xcb_map_window(conn, client->frame);
|
xcb_map_window(conn, client->frame);
|
||||||
|
@ -836,7 +836,7 @@ void parse_command(xcb_connection_t *conn, const char *command) {
|
||||||
|
|
||||||
/* Is it just 's' for stacking or 'd' for default? */
|
/* Is it just 's' for stacking or 'd' for default? */
|
||||||
if ((command[0] == 's' || command[0] == 'd') && (command[1] == '\0')) {
|
if ((command[0] == 's' || command[0] == 'd') && (command[1] == '\0')) {
|
||||||
if (last_focused == NULL || last_focused->floating) {
|
if (last_focused == NULL || last_focused->floating >= FLOATING_AUTO_ON) {
|
||||||
LOG("not switching, this is a floating client\n");
|
LOG("not switching, this is a floating client\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -852,7 +852,7 @@ void parse_command(xcb_connection_t *conn, const char *command) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
toggle_floating_mode(conn, last_focused);
|
toggle_floating_mode(conn, last_focused, false);
|
||||||
/* delete all empty columns/rows */
|
/* delete all empty columns/rows */
|
||||||
cleanup_table(conn, last_focused->workspace);
|
cleanup_table(conn, last_focused->workspace);
|
||||||
|
|
||||||
|
@ -908,13 +908,13 @@ void parse_command(xcb_connection_t *conn, const char *command) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*rest == '\0') {
|
if (*rest == '\0') {
|
||||||
if (last_focused != NULL && last_focused->floating)
|
if (last_focused != NULL && last_focused->floating >= FLOATING_AUTO_ON)
|
||||||
move_floating_window_to_workspace(conn, last_focused, workspace);
|
move_floating_window_to_workspace(conn, last_focused, workspace);
|
||||||
else move_current_window_to_workspace(conn, workspace);
|
else move_current_window_to_workspace(conn, workspace);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (last_focused == NULL || last_focused->floating) {
|
if (last_focused == NULL || last_focused->floating >= FLOATING_AUTO_ON) {
|
||||||
LOG("Not performing (null or floating) \n");
|
LOG("Not performing (null or floating) \n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,15 +39,18 @@ static void drag_pointer(xcb_connection_t *conn, Client *client, xcb_button_pres
|
||||||
* Correctly takes care of the position/size (separately stored for tiling/floating mode)
|
* Correctly takes care of the position/size (separately stored for tiling/floating mode)
|
||||||
* and repositions/resizes/redecorates the client.
|
* and repositions/resizes/redecorates the client.
|
||||||
*
|
*
|
||||||
|
* If the automatic flag is set to true, this was an automatic update by a change of the
|
||||||
|
* window class from the application which can be overwritten by the user.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
void toggle_floating_mode(xcb_connection_t *conn, Client *client) {
|
void toggle_floating_mode(xcb_connection_t *conn, Client *client, bool automatic) {
|
||||||
Container *con = client->container;
|
Container *con = client->container;
|
||||||
|
|
||||||
if (con == NULL) {
|
if (con == NULL) {
|
||||||
LOG("This client is already in floating (container == NULL), re-inserting\n");
|
LOG("This client is already in floating (container == NULL), re-inserting\n");
|
||||||
Client *next_tiling;
|
Client *next_tiling;
|
||||||
SLIST_FOREACH(next_tiling, &(client->workspace->focus_stack), focus_clients)
|
SLIST_FOREACH(next_tiling, &(client->workspace->focus_stack), focus_clients)
|
||||||
if (!next_tiling->floating)
|
if (next_tiling->floating <= FLOATING_USER_OFF)
|
||||||
break;
|
break;
|
||||||
/* If there are no tiling clients on this workspace, there can only be one
|
/* If there are no tiling clients on this workspace, there can only be one
|
||||||
* container: the first one */
|
* container: the first one */
|
||||||
|
@ -60,7 +63,7 @@ void toggle_floating_mode(xcb_connection_t *conn, Client *client) {
|
||||||
/* Preserve position/size */
|
/* Preserve position/size */
|
||||||
memcpy(&(client->floating_rect), &(client->rect), sizeof(Rect));
|
memcpy(&(client->floating_rect), &(client->rect), sizeof(Rect));
|
||||||
|
|
||||||
client->floating = false;
|
client->floating = FLOATING_USER_OFF;
|
||||||
client->container = con;
|
client->container = con;
|
||||||
|
|
||||||
if (old_focused != NULL && !old_focused->dock)
|
if (old_focused != NULL && !old_focused->dock)
|
||||||
|
@ -88,7 +91,9 @@ void toggle_floating_mode(xcb_connection_t *conn, Client *client) {
|
||||||
con->currently_focused = get_last_focused_client(conn, con, NULL);
|
con->currently_focused = get_last_focused_client(conn, con, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
client->floating = true;
|
if (automatic)
|
||||||
|
client->floating = FLOATING_AUTO_ON;
|
||||||
|
else client->floating = FLOATING_USER_ON;
|
||||||
|
|
||||||
/* Initialize the floating position from the position in tiling mode, if this
|
/* Initialize the floating position from the position in tiling mode, if this
|
||||||
* client never was floating (width == 0) */
|
* client never was floating (width == 0) */
|
||||||
|
|
|
@ -336,7 +336,7 @@ int handle_button_press(void *ignored, xcb_connection_t *conn, xcb_button_press_
|
||||||
LOG("client. done.\n");
|
LOG("client. done.\n");
|
||||||
xcb_allow_events(conn, XCB_ALLOW_REPLAY_POINTER, event->time);
|
xcb_allow_events(conn, XCB_ALLOW_REPLAY_POINTER, event->time);
|
||||||
/* Floating clients should be raised on click */
|
/* Floating clients should be raised on click */
|
||||||
if (client->floating)
|
if (client->floating >= FLOATING_AUTO_ON)
|
||||||
xcb_raise_window(conn, client->frame);
|
xcb_raise_window(conn, client->frame);
|
||||||
xcb_flush(conn);
|
xcb_flush(conn);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -348,7 +348,7 @@ int handle_button_press(void *ignored, xcb_connection_t *conn, xcb_button_press_
|
||||||
LOG("click on titlebar\n");
|
LOG("click on titlebar\n");
|
||||||
|
|
||||||
/* Floating clients can be dragged by grabbing their titlebar */
|
/* Floating clients can be dragged by grabbing their titlebar */
|
||||||
if (client->floating) {
|
if (client->floating >= FLOATING_AUTO_ON) {
|
||||||
/* Firstly, we raise it. Maybe the user just wanted to raise it without grabbing */
|
/* Firstly, we raise it. Maybe the user just wanted to raise it without grabbing */
|
||||||
uint32_t values[] = { XCB_STACK_MODE_ABOVE };
|
uint32_t values[] = { XCB_STACK_MODE_ABOVE };
|
||||||
xcb_configure_window(conn, client->frame, XCB_CONFIG_WINDOW_STACK_MODE, values);
|
xcb_configure_window(conn, client->frame, XCB_CONFIG_WINDOW_STACK_MODE, values);
|
||||||
|
@ -359,7 +359,7 @@ int handle_button_press(void *ignored, xcb_connection_t *conn, xcb_button_press_
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (client->floating)
|
if (client->floating >= FLOATING_AUTO_ON)
|
||||||
return floating_border_click(conn, client, event);
|
return floating_border_click(conn, client, event);
|
||||||
|
|
||||||
if (event->event_y < 2) {
|
if (event->event_y < 2) {
|
||||||
|
@ -542,7 +542,7 @@ int handle_unmap_notify_event(void *data, xcb_connection_t *conn, xcb_unmap_noti
|
||||||
/* Only if this is the active container, we need to really change focus */
|
/* Only if this is the active container, we need to really change focus */
|
||||||
if ((con->currently_focused != NULL) && ((con == CUR_CELL) || client->fullscreen))
|
if ((con->currently_focused != NULL) && ((con == CUR_CELL) || client->fullscreen))
|
||||||
set_focus(conn, con->currently_focused, true);
|
set_focus(conn, con->currently_focused, true);
|
||||||
} else if (client->floating) {
|
} else if (client->floating >= FLOATING_AUTO_ON) {
|
||||||
SLIST_REMOVE(&(client->workspace->focus_stack), client, Client, focus_clients);
|
SLIST_REMOVE(&(client->workspace->focus_stack), client, Client, focus_clients);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -737,6 +737,17 @@ int handle_windowclass_change(void *data, xcb_connection_t *conn, uint8_t state,
|
||||||
client->window_class = new_class;
|
client->window_class = new_class;
|
||||||
FREE(old_class);
|
FREE(old_class);
|
||||||
|
|
||||||
|
if (!client->initialized) {
|
||||||
|
LOG("Client is not yet initialized, not putting it to floating\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(new_class, "tools") == 0) {
|
||||||
|
LOG("tool window, should we put it floating?\n");
|
||||||
|
if (client->floating == FLOATING_AUTO_OFF)
|
||||||
|
toggle_floating_mode(conn, client, true);
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -109,9 +109,9 @@ void decorate_window(xcb_connection_t *conn, Client *client, xcb_drawable_t draw
|
||||||
return;
|
return;
|
||||||
|
|
||||||
LOG("redecorating child %08x\n", client->child);
|
LOG("redecorating child %08x\n", client->child);
|
||||||
if (client->floating || client->container->currently_focused == client) {
|
if (client->floating >= FLOATING_AUTO_ON || client->container->currently_focused == client) {
|
||||||
/* Distinguish if the window is currently focused… */
|
/* Distinguish if the window is currently focused… */
|
||||||
if (client->floating || CUR_CELL->currently_focused == client)
|
if (client->floating >= FLOATING_AUTO_ON || CUR_CELL->currently_focused == client)
|
||||||
background_color = get_colorpixel(conn, config.client.focused.background);
|
background_color = get_colorpixel(conn, config.client.focused.background);
|
||||||
/* …or if it is the focused window in a not focused container */
|
/* …or if it is the focused window in a not focused container */
|
||||||
else background_color = get_colorpixel(conn, config.client.focused_inactive.background);
|
else background_color = get_colorpixel(conn, config.client.focused_inactive.background);
|
||||||
|
|
|
@ -339,7 +339,7 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child,
|
||||||
/* Ensure that it is below all floating clients */
|
/* Ensure that it is below all floating clients */
|
||||||
Client *first_floating;
|
Client *first_floating;
|
||||||
SLIST_FOREACH(first_floating, &(new->container->workspace->focus_stack), focus_clients)
|
SLIST_FOREACH(first_floating, &(new->container->workspace->focus_stack), focus_clients)
|
||||||
if (first_floating->floating)
|
if (first_floating->floating >= FLOATING_AUTO_ON)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (first_floating != SLIST_END(&(new->container->workspace->focus_stack))) {
|
if (first_floating != SLIST_END(&(new->container->workspace->focus_stack))) {
|
||||||
|
@ -349,6 +349,8 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
new->initialized = true;
|
||||||
|
|
||||||
/* Check if the window already got the fullscreen hint set */
|
/* Check if the window already got the fullscreen hint set */
|
||||||
xcb_atom_t *state;
|
xcb_atom_t *state;
|
||||||
if ((preply = xcb_get_property_reply(conn, state_cookie, NULL)) != NULL &&
|
if ((preply = xcb_get_property_reply(conn, state_cookie, NULL)) != NULL &&
|
||||||
|
|
|
@ -264,7 +264,7 @@ void unmap_workspace(xcb_connection_t *conn, Workspace *u_ws) {
|
||||||
|
|
||||||
/* To find floating clients, we traverse the focus stack */
|
/* To find floating clients, we traverse the focus stack */
|
||||||
SLIST_FOREACH(client, &(u_ws->focus_stack), focus_clients) {
|
SLIST_FOREACH(client, &(u_ws->focus_stack), focus_clients) {
|
||||||
if (!client->floating)
|
if (client->floating <= FLOATING_USER_OFF)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
xcb_unmap_window(conn, client->frame);
|
xcb_unmap_window(conn, client->frame);
|
||||||
|
|
Loading…
Reference in New Issue