]> git.sur5r.net Git - i3/i3/blobdiff - src/handlers.c
Store aspect_ratio instead of weird proportional_{width,height} (Thanks phillip)
[i3/i3] / src / handlers.c
index 048d3a3a17992008326f6994bc57a99421ab7202..6be2a5b1f81ae0bfbbaab867c1a708956bc82e13 100644 (file)
@@ -1,3 +1,5 @@
+#undef I3__FILE__
+#define I3__FILE__ "handlers.c"
 /*
  * vim:ts=4:sw=4:expandtab
  *
@@ -156,7 +158,7 @@ static void handle_enter_notify(xcb_enter_notify_event_t *event) {
     }
 
     /* see if the user entered the window on a certain window decoration */
-    int layout = (enter_child ? con->parent->layout : con->layout);
+    layout_t layout = (enter_child ? con->parent->layout : con->layout);
     if (layout == L_DEFAULT) {
         Con *child;
         TAILQ_FOREACH(child, &(con->nodes_head), nodes)
@@ -211,6 +213,7 @@ static void handle_motion_notify(xcb_motion_notify_event_t *event) {
 
     Con *con;
     if ((con = con_by_frame_id(event->event)) == NULL) {
+        DLOG("MotionNotify for an unknown container, checking if it crosses screen boundaries.\n");
         check_crossing_screen_boundary(event->root_x, event->root_y);
         return;
     }
@@ -322,9 +325,21 @@ static void handle_configure_request(xcb_configure_request_event_t *event) {
     }
 
     DLOG("Configure request!\n");
-    if (con_is_floating(con) && con_is_leaf(con)) {
+
+    Con *workspace = con_get_workspace(con),
+        *fullscreen = NULL;
+
+    /* There might not be a corresponding workspace for dock cons, therefore we
+     * have to be careful here. */
+    if (workspace) {
+        fullscreen = con_get_fullscreen_con(workspace, CF_OUTPUT);
+        if (!fullscreen)
+            fullscreen = con_get_fullscreen_con(workspace, CF_GLOBAL);
+    }
+
+    if (fullscreen != con && con_is_floating(con) && con_is_leaf(con)) {
         /* find the height for the decorations */
-        int deco_height = config.font.height + 5;
+        int deco_height = con->deco_rect.height;
         /* we actually need to apply the size/position changes to the *parent*
          * container */
         Rect bsr = con_border_style_rect(con);
@@ -334,6 +349,11 @@ static void handle_configure_request(xcb_configure_request_event_t *event) {
         }
         Con *floatingcon = con->parent;
 
+        if (strcmp(con_get_workspace(floatingcon)->name, "__i3_scratch") == 0) {
+            DLOG("This is a scratchpad container, ignoring ConfigureRequest\n");
+            return;
+        }
+
         Rect newrect = floatingcon->rect;
 
         if (event->value_mask & XCB_CONFIG_WINDOW_X) {
@@ -404,6 +424,8 @@ static void handle_screen_change(xcb_generic_event_t *e) {
 
     randr_query_outputs();
 
+    scratchpad_fix_resolution();
+
     ipc_send_event("output", I3_IPC_EVENT_OUTPUT, "{\"change\":\"unspecified\"}");
 
     return;
@@ -597,10 +619,10 @@ static void handle_client_message(xcb_client_message_event_t *event) {
 
     LOG("ClientMessage for window 0x%08x\n", event->window);
     if (event->type == A__NET_WM_STATE) {
-        if (event->format != 32 || event->data.data32[1] != A__NET_WM_STATE_FULLSCREEN) {
-            DLOG("atom in clientmessage is %d, fullscreen is %d\n",
-                    event->data.data32[1], A__NET_WM_STATE_FULLSCREEN);
-            DLOG("not about fullscreen atom\n");
+        if (event->format != 32 ||
+            (event->data.data32[1] != A__NET_WM_STATE_FULLSCREEN &&
+             event->data.data32[1] != A__NET_WM_STATE_DEMANDS_ATTENTION)) {
+            DLOG("Unknown atom in clientmessage of type %d\n", event->data.data32[1]);
             return;
         }
 
@@ -610,24 +632,51 @@ static void handle_client_message(xcb_client_message_event_t *event) {
             return;
         }
 
-        /* Check if the fullscreen state should be toggled */
-        if ((con->fullscreen_mode != CF_NONE &&
-             (event->data.data32[0] == _NET_WM_STATE_REMOVE ||
-              event->data.data32[0] == _NET_WM_STATE_TOGGLE)) ||
-            (con->fullscreen_mode == CF_NONE &&
-             (event->data.data32[0] == _NET_WM_STATE_ADD ||
-              event->data.data32[0] == _NET_WM_STATE_TOGGLE))) {
-            DLOG("toggling fullscreen\n");
-            con_toggle_fullscreen(con, CF_OUTPUT);
+        if (event->data.data32[1] == A__NET_WM_STATE_FULLSCREEN) {
+            /* Check if the fullscreen state should be toggled */
+            if ((con->fullscreen_mode != CF_NONE &&
+                 (event->data.data32[0] == _NET_WM_STATE_REMOVE ||
+                  event->data.data32[0] == _NET_WM_STATE_TOGGLE)) ||
+                (con->fullscreen_mode == CF_NONE &&
+                 (event->data.data32[0] == _NET_WM_STATE_ADD ||
+                  event->data.data32[0] == _NET_WM_STATE_TOGGLE))) {
+                DLOG("toggling fullscreen\n");
+                con_toggle_fullscreen(con, CF_OUTPUT);
+            }
+        } else if (event->data.data32[1] == A__NET_WM_STATE_DEMANDS_ATTENTION) {
+            /* Check if the urgent flag must be set or not */
+            if (event->data.data32[0] == _NET_WM_STATE_ADD)
+                con_set_urgency(con, true);
+            else if (event->data.data32[0] == _NET_WM_STATE_REMOVE)
+                con_set_urgency(con, false);
+            else if (event->data.data32[0] == _NET_WM_STATE_TOGGLE)
+                con_set_urgency(con, !con->urgent);
         }
 
         tree_render();
-        x_push_changes(croot);
+    } else if (event->type == A__NET_ACTIVE_WINDOW) {
+        DLOG("_NET_ACTIVE_WINDOW: Window 0x%08x should be activated\n", event->window);
+        Con *con = con_by_window_id(event->window);
+        if (con == NULL) {
+            DLOG("Could not get window for client message\n");
+            return;
+        }
+
+        Con *ws = con_get_workspace(con);
+        if (!workspace_is_visible(ws)) {
+            DLOG("Workspace not visible, ignoring _NET_ACTIVE_WINDOW\n");
+            return;
+        }
+
+        if (ws != con_get_workspace(focused))
+            workspace_show(ws);
+
+        con_focus(con);
+        tree_render();
     } else if (event->type == A_I3_SYNC) {
-        DLOG("i3 sync, yay\n");
         xcb_window_t window = event->data.data32[0];
         uint32_t rnd = event->data.data32[1];
-        DLOG("Sending random value %d back to X11 window 0x%08x\n", rnd, window);
+        DLOG("[i3 sync protocol] Sending random value %d back to X11 window 0x%08x\n", rnd, window);
 
         void *reply = scalloc(32);
         xcb_client_message_event_t *ev = reply;
@@ -750,22 +799,18 @@ static bool handle_normal_hints(void *data, xcb_connection_t *conn, uint8_t stat
         goto render_and_return;
 
     /* Check if we need to set proportional_* variables using the correct ratio */
+    double aspect_ratio = 0.0;
     if ((width / height) < min_aspect) {
-        if (con->proportional_width != width ||
-            con->proportional_height != (width / min_aspect)) {
-            con->proportional_width = width;
-            con->proportional_height = width / min_aspect;
-            changed = true;
-        }
+        aspect_ratio = min_aspect;
     } else if ((width / height) > max_aspect) {
-        if (con->proportional_width != width ||
-            con->proportional_height != (width / max_aspect)) {
-            con->proportional_width = width;
-            con->proportional_height = width / max_aspect;
-            changed = true;
-        }
+        aspect_ratio = max_aspect;
     } else goto render_and_return;
 
+    if (fabs(con->aspect_ratio - aspect_ratio) > DBL_EPSILON) {
+        con->aspect_ratio = aspect_ratio;
+        changed = true;
+    }
+
 render_and_return:
     if (changed)
         tree_render();
@@ -794,35 +839,12 @@ static bool handle_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_
     if (!xcb_icccm_get_wm_hints_from_reply(&hints, reply))
         return false;
 
-    if (!con->urgent && focused == con) {
-        DLOG("Ignoring urgency flag for current client\n");
-        con->window->urgent.tv_sec = 0;
-        con->window->urgent.tv_usec = 0;
-        goto end;
-    }
-
     /* Update the flag on the client directly */
-    con->urgent = (xcb_icccm_wm_hints_get_urgency(&hints) != 0);
-    //CLIENT_LOG(con);
-    if (con->window) {
-        if (con->urgent) {
-            gettimeofday(&con->window->urgent, NULL);
-        } else {
-            con->window->urgent.tv_sec = 0;
-            con->window->urgent.tv_usec = 0;
-        }
-    }
-    LOG("Urgency flag changed to %d\n", con->urgent);
-
-    Con *ws;
-    /* Set the urgency flag on the workspace, if a workspace could be found
-     * (for dock clients, that is not the case). */
-    if ((ws = con_get_workspace(con)) != NULL)
-        workspace_update_urgent_flag(ws);
+    bool hint_urgent = (xcb_icccm_wm_hints_get_urgency(&hints) != 0);
+    con_set_urgency(con, hint_urgent);
 
     tree_render();
 
-end:
     if (con->window)
         window_update_hints(con->window, reply);
     else free(reply);
@@ -1011,6 +1033,7 @@ void handle_event(int type, xcb_generic_event_t *event) {
 
     switch (type) {
         case XCB_KEY_PRESS:
+        case XCB_KEY_RELEASE:
             handle_key_press((xcb_key_press_event_t*)event);
             break;
 
@@ -1045,7 +1068,7 @@ void handle_event(int type, xcb_generic_event_t *event) {
 
         /* Client message are sent to the root window. The only interesting
          * client message for us is _NET_WM_STATE, we honour
-         * _NET_WM_STATE_FULLSCREEN */
+         * _NET_WM_STATE_FULLSCREEN and _NET_WM_STATE_DEMANDS_ATTENTION */
         case XCB_CLIENT_MESSAGE:
             handle_client_message((xcb_client_message_event_t*)event);
             break;