xcb_property_changed(prophs, XCB_PROPERTY_NEW_VALUE, window, WM_CLASS);
xcb_property_changed(prophs, XCB_PROPERTY_NEW_VALUE, window, WM_NAME);
xcb_property_changed(prophs, XCB_PROPERTY_NEW_VALUE, window, WM_NORMAL_HINTS);
+ xcb_property_changed(prophs, XCB_PROPERTY_NEW_VALUE, window, WM_TRANSIENT_FOR);
xcb_property_changed(prophs, XCB_PROPERTY_NEW_VALUE, window, atoms[_NET_WM_NAME]);
free(geom);
utf8_title_cookie, title_cookie, class_cookie;
uint32_t mask = 0;
uint32_t values[3];
+ uint16_t original_height = height;
/* We are interested in property changes */
mask = XCB_CW_EVENT_MASK;
new->container = CUR_CELL;
new->workspace = new->container->workspace;
+ /* Minimum useful size for managed windows is 75x50 (primarily affects floating) */
+ width = max(width, 75);
+ height = max(height, 50);
+
new->frame = xcb_generate_id(conn);
new->child = child;
new->rect.width = width;
1 /* left mouse button */,
XCB_BUTTON_MASK_ANY /* don’t filter for any modifiers */);
+ xcb_grab_button(conn, false, child, XCB_EVENT_MASK_BUTTON_PRESS,
+ XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC, root, XCB_NONE,
+ 1 /* left mouse button */, XCB_MOD_MASK_1);
+
/* Get _NET_WM_WINDOW_TYPE (to see if it’s a dock) */
xcb_atom_t *atom;
xcb_get_property_reply_t *preply = xcb_get_property_reply(conn, wm_type_cookie, NULL);
if (preply != NULL && preply->value_len > 0 && (atom = xcb_get_property_value(preply))) {
- for (int i = 0; i < xcb_get_property_value_length(preply); i++) {
- if (atom[i] != atoms[_NET_WM_WINDOW_TYPE_DOCK])
- continue;
- LOG("Window is a dock.\n");
- new->dock = true;
- new->titlebar_position = TITLEBAR_OFF;
- new->force_reconfigure = true;
- new->container = NULL;
- SLIST_INSERT_HEAD(&(c_ws->screen->dock_clients), new, dock_clients);
- }
+ for (int i = 0; i < xcb_get_property_value_length(preply); i++)
+ if (atom[i] == atoms[_NET_WM_WINDOW_TYPE_DOCK]) {
+ LOG("Window is a dock.\n");
+ new->dock = true;
+ new->titlebar_position = TITLEBAR_OFF;
+ new->force_reconfigure = true;
+ new->container = NULL;
+ SLIST_INSERT_HEAD(&(c_ws->screen->dock_clients), new, dock_clients);
+ /* If it’s a dock we can’t make it float, so we break */
+ break;
+ } else if (atom[i] == atoms[_NET_WM_WINDOW_TYPE_DIALOG] ||
+ atom[i] == atoms[_NET_WM_WINDOW_TYPE_UTILITY] ||
+ atom[i] == atoms[_NET_WM_WINDOW_TYPE_TOOLBAR] ||
+ atom[i] == atoms[_NET_WM_WINDOW_TYPE_SPLASH]) {
+ /* Set the dialog window to automatically floating, will be used below */
+ new->floating = FLOATING_AUTO_ON;
+ LOG("dialog/utility/toolbar/splash window, automatically floating\n");
+ }
+ }
+
+ if (new->workspace->auto_float) {
+ new->floating = FLOATING_AUTO_ON;
+ LOG("workspace is in autofloat mode, setting floating\n");
}
if (new->dock) {
TODO: bars at the top */
new->desired_height = strut[3];
if (new->desired_height == 0) {
- LOG("Client wanted to be 0 pixels high, using the window's height (%d)\n", height);
- new->desired_height = height;
+ LOG("Client wanted to be 0 pixels high, using the window's height (%d)\n", original_height);
+ new->desired_height = original_height;
}
LOG("the client wants to be %d pixels high\n", new->desired_height);
} else {
- LOG("The client didn't specify space to reserve at the screen edge, using its height (%d)\n", height);
- new->desired_height = height;
+ LOG("The client didn't specify space to reserve at the screen edge, using its height (%d)\n", original_height);
+ new->desired_height = original_height;
}
} else {
/* If it’s not a dock, we can check on which workspace we should put it. */
if (get_matching_client(conn, assign->windowclass_title, new) == NULL)
continue;
+ if (assign->floating) {
+ new->floating = FLOATING_AUTO_ON;
+ LOG("Assignment matches, putting client into floating mode\n");
+ break;
+ }
+
LOG("Assignment \"%s\" matches, so putting it on workspace %d\n",
assign->windowclass_title, assign->workspace);
new->container = t_ws->table[t_ws->current_col][t_ws->current_row];
new->workspace = t_ws;
+ old_focused = new->container->currently_focused;
+
xcb_unmap_window(conn, new->frame);
break;
}
} else if (!new->dock) {
/* Focus the new window if we’re not in fullscreen mode and if it is not a dock window */
if (new->container->workspace->fullscreen_client == NULL) {
- new->container->currently_focused = new;
+ if (new->floating <= FLOATING_USER_OFF)
+ new->container->currently_focused = new;
if (new->container == CUR_CELL)
xcb_set_input_focus(conn, XCB_INPUT_FOCUS_POINTER_ROOT, new->child, XCB_CURRENT_TIME);
}
}
/* Insert into the currently active container, if it’s not a dock window */
- if (!new->dock) {
+ if (!new->dock && new->floating <= FLOATING_USER_OFF) {
/* Insert after the old active client, if existing. If it does not exist, the
container is empty and it does not matter, where we insert it */
if (old_focused != NULL && !old_focused->dock)
SLIST_INSERT_HEAD(&(new->container->workspace->focus_stack), new, focus_clients);
- /* Ensure that it is below all floating clients */
- Client *first_floating;
- SLIST_FOREACH(first_floating, &(new->container->workspace->focus_stack), focus_clients)
- if (first_floating->floating >= FLOATING_AUTO_ON)
- break;
+ client_set_below_floating(conn, new);
+ }
- if (first_floating != SLIST_END(&(new->container->workspace->focus_stack))) {
- LOG("Setting below floating\n");
- uint32_t values[] = { first_floating->frame, XCB_STACK_MODE_BELOW };
- xcb_configure_window(conn, new->frame, XCB_CONFIG_WINDOW_SIBLING | XCB_CONFIG_WINDOW_STACK_MODE, values);
- }
+ if (new->floating >= FLOATING_AUTO_ON) {
+ SLIST_INSERT_HEAD(&(new->workspace->focus_stack), new, focus_clients);
+
+ /* Add the client to the list of floating clients for its workspace */
+ TAILQ_INSERT_TAIL(&(new->workspace->floating_clients), new, floating_clients);
+
+ new->container = NULL;
+
+ new->floating_rect.x = new->rect.x = x;
+ new->floating_rect.y = new->rect.y = y;
+ LOG("copying size from tiling (%d, %d) size (%d, %d)\n",
+ new->floating_rect.x, new->floating_rect.y,
+ new->floating_rect.width, new->floating_rect.height);
+
+ /* Make sure it is on top of the other windows */
+ xcb_raise_window(conn, new->frame);
+ reposition_client(conn, new);
+ resize_client(conn, new);
+ /* redecorate_window flushes */
+ redecorate_window(conn, new);
}
new->initialized = true;