]> git.sur5r.net Git - i3/i3/blobdiff - src/manage.c
Implement modes. Modes allow you to use different keybindings and switch between...
[i3/i3] / src / manage.c
index 14c058fd26c5fd5ecf854079d95687c89c605741..5dcb837c1144538f2abf3ad64bc45c85256b9ff0 100644 (file)
@@ -68,7 +68,6 @@ void manage_existing_windows(xcb_connection_t *conn, xcb_property_handlers_t *pr
 void manage_window(xcb_property_handlers_t *prophs, xcb_connection_t *conn,
                    xcb_window_t window, xcb_get_window_attributes_cookie_t cookie,
                    bool needs_to_be_mapped) {
-        LOG("managing window.\n");
         xcb_drawable_t d = { window };
         xcb_get_geometry_cookie_t geomc;
         xcb_get_geometry_reply_t *geom;
@@ -83,16 +82,12 @@ void manage_window(xcb_property_handlers_t *prophs, xcb_connection_t *conn,
                 return;
         }
 
-        if (needs_to_be_mapped && attr->map_state != XCB_MAP_STATE_VIEWABLE) {
-                LOG("Window not mapped, not managing\n");
+        if (needs_to_be_mapped && attr->map_state != XCB_MAP_STATE_VIEWABLE)
                 goto out;
-        }
 
         /* Don’t manage clients with the override_redirect flag */
-        if (attr->override_redirect) {
-                LOG("override_redirect set, not managing\n");
+        if (attr->override_redirect)
                 goto out;
-        }
 
         /* Check if the window is already managed */
         if (table_get(&by_child, window))
@@ -104,12 +99,14 @@ void manage_window(xcb_property_handlers_t *prophs, xcb_connection_t *conn,
 
         /* Reparent the window and add it to our list of managed windows */
         reparent_window(conn, window, attr->visual, geom->root, geom->depth,
-                        geom->x, geom->y, geom->width, geom->height);
+                        geom->x, geom->y, geom->width, geom->height,
+                        geom->border_width);
 
         /* Generate callback events for every property we watch */
         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_HINTS);
         xcb_property_changed(prophs, XCB_PROPERTY_NEW_VALUE, window, WM_TRANSIENT_FOR);
         xcb_property_changed(prophs, XCB_PROPERTY_NEW_VALUE, window, atoms[WM_CLIENT_LEADER]);
         xcb_property_changed(prophs, XCB_PROPERTY_NEW_VALUE, window, atoms[_NET_WM_NAME]);
@@ -129,7 +126,8 @@ out:
  */
 void reparent_window(xcb_connection_t *conn, xcb_window_t child,
                      xcb_visualid_t visual, xcb_window_t root, uint8_t depth,
-                     int16_t x, int16_t y, uint16_t width, uint16_t height) {
+                     int16_t x, int16_t y, uint16_t width, uint16_t height,
+                     uint32_t border_width) {
 
         xcb_get_property_cookie_t wm_type_cookie, strut_cookie, state_cookie,
                                   utf8_title_cookie, title_cookie,
@@ -158,7 +156,7 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child,
         /* Events for already managed windows should already be filtered in manage_window() */
         assert(new == NULL);
 
-        LOG("reparenting new client\n");
+        LOG("Reparenting window 0x%08x\n", child);
         LOG("x = %d, y = %d, width = %d, height = %d\n", x, y, width, height);
         new = calloc(sizeof(Client), 1);
         new->force_reconfigure = true;
@@ -177,6 +175,9 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child,
         new->child = child;
         new->rect.width = width;
         new->rect.height = height;
+        new->width_increment = 1;
+        new->height_increment = 1;
+        new->border_width = border_width;
         /* Pre-initialize the values for floating */
         new->floating_rect.x = -1;
         new->floating_rect.width = width;
@@ -192,8 +193,6 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child,
         mask |= XCB_CW_EVENT_MASK;
         values[1] = FRAME_EVENT_MASK;
 
-        LOG("Reparenting 0x%08x under 0x%08x.\n", child, new->frame);
-
         i3Font *font = load_font(conn, config.font);
         width = min(width, c_ws->rect.x + c_ws->rect.width);
         height = min(height, c_ws->rect.y + c_ws->rect.height);
@@ -205,11 +204,6 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child,
         /* Yo dawg, I heard you like windows, so I create a window around your window… */
         new->frame = create_window(conn, framerect, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_CURSOR_LEFT_PTR, false, mask, values);
 
-        /* Set WM_STATE_NORMAL because GTK applications don’t want to drag & drop if we don’t.
-         * Also, xprop(1) needs that to work. */
-        long data[] = { XCB_WM_STATE_NORMAL, XCB_NONE };
-        xcb_change_property(conn, XCB_PROP_MODE_REPLACE, new->child, atoms[WM_STATE], atoms[WM_STATE], 32, 2, data);
-
         /* Put the client inside the save set. Upon termination (whether killed or normal exit
            does not matter) of the window manager, these clients will be correctly reparented
            to their most closest living ancestor (= cleanup) */
@@ -241,7 +235,8 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child,
 
         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);
+                        3 /* right mouse button */,
+                        XCB_BUTTON_MASK_ANY /* don’t filter for any modifiers */);
 
         /* Get _NET_WM_WINDOW_TYPE (to see if it’s a dock) */
         xcb_atom_t *atom;
@@ -318,7 +313,6 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child,
                 preply = xcb_get_property_reply(conn, leader_cookie, NULL);
                 handle_clientleader_change(NULL, conn, 0, new->child, atoms[WM_CLIENT_LEADER], preply);
 
-                LOG("DEBUG: should have all infos now\n");
                 struct Assignment *assign;
                 TAILQ_FOREACH(assign, &assignments, assignments) {
                         if (get_matching_client(conn, assign->windowclass_title, new) == NULL)
@@ -341,7 +335,7 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child,
                         }
 
                         LOG("Changing container/workspace and unmapping the client\n");
-                        Workspace *t_ws = &(workspaces[assign->workspace-1]);
+                        Workspace *t_ws = workspace_get(assign->workspace-1);
                         workspace_initialize(t_ws, c_ws->screen);
 
                         new->container = t_ws->table[t_ws->current_col][t_ws->current_row];
@@ -433,20 +427,20 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child,
                            and don’t event bother to redraw the layout – that would not change
                            anything anyways */
                         client_toggle_fullscreen(conn, new);
-                        return;
+                        goto map;
                 }
 
         render_layout(conn);
 
+map:
         /* Map the window first to avoid flickering */
         xcb_map_window(conn, child);
-        if (map_frame) {
-                LOG("Mapping client\n");
-                xcb_map_window(conn, new->frame);
-        }
-        if (CUR_CELL->workspace->fullscreen_client == NULL && !new->dock) {
+        if (map_frame)
+                client_map(conn, new);
+
+        if ((CUR_CELL->workspace->fullscreen_client == NULL || new->fullscreen) && !new->dock) {
                 /* Focus the new window if we’re not in fullscreen mode and if it is not a dock window */
-                if (new->workspace->fullscreen_client == NULL) {
+                if ((new->workspace->fullscreen_client == NULL) || new->fullscreen) {
                         if (!client_is_floating(new))
                                 new->container->currently_focused = new;
                         if (new->container == CUR_CELL || client_is_floating(new))