]> git.sur5r.net Git - i3/i3/blobdiff - src/handlers.c
i3-nagbar: explicitly set cursor using libxcursor if available
[i3/i3] / src / handlers.c
index 8e92bec98b637607b8b1932cd73f7337cb61d18b..6cbc54f230d0dfc2864be17ed6fcf35e45e73461 100644 (file)
@@ -386,15 +386,35 @@ static void handle_configure_request(xcb_configure_request_event_t *event) {
         return;
     }
 
-    /* Dock windows can be reconfigured in their height */
+    /* Dock windows can be reconfigured in their height and moved to another output. */
     if (con->parent && con->parent->type == CT_DOCKAREA) {
-        DLOG("Dock window, only height reconfiguration allowed\n");
+        DLOG("Reconfiguring dock window (con = %p).\n", con);
         if (event->value_mask & XCB_CONFIG_WINDOW_HEIGHT) {
-            DLOG("Height given, changing\n");
+            DLOG("Dock client wants to change height to %d, we can do that.\n", event->height);
 
             con->geometry.height = event->height;
             tree_render();
         }
+
+        if (event->value_mask & XCB_CONFIG_WINDOW_X || event->value_mask & XCB_CONFIG_WINDOW_Y) {
+            int16_t x = event->value_mask & XCB_CONFIG_WINDOW_X ? event->x : (int16_t)con->geometry.x;
+            int16_t y = event->value_mask & XCB_CONFIG_WINDOW_Y ? event->y : (int16_t)con->geometry.y;
+
+            Con *current_output = con_get_output(con);
+            Output *target = get_output_containing(x, y);
+            if (target != NULL && current_output != target->con) {
+                DLOG("Dock client is requested to be moved to output %s, moving it there.\n", target->name);
+                Match *match;
+                Con *nc = con_for_window(target->con, con->window, &match);
+                DLOG("Dock client will be moved to container %p.\n", nc);
+                con_detach(con);
+                con_attach(con, nc, false);
+
+                tree_render();
+            } else {
+                DLOG("Dock client will not be moved, we only support moving it to another output.\n");
+            }
+        }
     }
 
     fake_absolute_configure_notify(con);
@@ -483,7 +503,7 @@ static void handle_unmap_notify_event(xcb_unmap_notify_event_t *event) {
         goto ignore_end;
     }
 
-    tree_close(con, DONT_KILL_WINDOW, false, false);
+    tree_close_internal(con, DONT_KILL_WINDOW, false, false);
     tree_render();
 
 ignore_end:
@@ -636,15 +656,14 @@ static void handle_expose_event(xcb_expose_event_t *event) {
         return;
     }
 
-    /* Since we render to our pixmap on every change anyways, expose events
+    /* Since we render to our surface on every change anyways, expose events
      * only tell us that the X server lost (parts of) the window contents. We
-     * can handle that by copying the appropriate part from our pixmap to the
+     * can handle that by copying the appropriate part from our surface to the
      * window. */
-    xcb_copy_area(conn, parent->pixmap, parent->frame, parent->pm_gc,
-                  event->x, event->y, event->x, event->y,
-                  event->width, event->height);
+    draw_util_copy_surface(conn, &(parent->frame_buffer), &(parent->frame),
+                           event->x, event->y, event->x, event->y,
+                           event->width, event->height);
     xcb_flush(conn);
-
     return;
 }
 
@@ -675,7 +694,8 @@ static void handle_client_message(xcb_client_message_event_t *event) {
     if (event->type == A__NET_WM_STATE) {
         if (event->format != 32 ||
             (event->data.data32[1] != A__NET_WM_STATE_FULLSCREEN &&
-             event->data.data32[1] != A__NET_WM_STATE_DEMANDS_ATTENTION)) {
+             event->data.data32[1] != A__NET_WM_STATE_DEMANDS_ATTENTION &&
+             event->data.data32[1] != A__NET_WM_STATE_STICKY)) {
             DLOG("Unknown atom in clientmessage of type %d\n", event->data.data32[1]);
             return;
         }
@@ -705,6 +725,17 @@ static void handle_client_message(xcb_client_message_event_t *event) {
                 con_set_urgency(con, false);
             else if (event->data.data32[0] == _NET_WM_STATE_TOGGLE)
                 con_set_urgency(con, !con->urgent);
+        } else if (event->data.data32[1] == A__NET_WM_STATE_STICKY) {
+            DLOG("Received a client message to modify _NET_WM_STATE_STICKY.\n");
+            if (event->data.data32[0] == _NET_WM_STATE_ADD)
+                con->sticky = true;
+            else if (event->data.data32[0] == _NET_WM_STATE_REMOVE)
+                con->sticky = false;
+            else if (event->data.data32[0] == _NET_WM_STATE_TOGGLE)
+                con->sticky = !con->sticky;
+
+            DLOG("New sticky status for con = %p is %i.\n", con, con->sticky);
+            output_push_sticky_windows(focused);
         }
 
         tree_render();
@@ -847,7 +878,7 @@ static void handle_client_message(xcb_client_message_event_t *event) {
             if (event->data.data32[0])
                 last_timestamp = event->data.data32[0];
 
-            tree_close(con, KILL_WINDOW, false, false);
+            tree_close_internal(con, KILL_WINDOW, false, false);
             tree_render();
         } else {
             DLOG("Couldn't find con for _NET_CLOSE_WINDOW request. (window = %d)\n", event->window);
@@ -932,13 +963,13 @@ static bool handle_normal_hints(void *data, xcb_connection_t *conn, uint8_t stat
     bool changed = false;
     if ((size_hints.flags & XCB_ICCCM_SIZE_HINT_P_RESIZE_INC)) {
         if (size_hints.width_inc > 0 && size_hints.width_inc < 0xFFFF)
-            if (con->width_increment != size_hints.width_inc) {
-                con->width_increment = size_hints.width_inc;
+            if (con->window->width_increment != size_hints.width_inc) {
+                con->window->width_increment = size_hints.width_inc;
                 changed = true;
             }
         if (size_hints.height_inc > 0 && size_hints.height_inc < 0xFFFF)
-            if (con->height_increment != size_hints.height_inc) {
-                con->height_increment = size_hints.height_inc;
+            if (con->window->height_increment != size_hints.height_inc) {
+                con->window->height_increment = size_hints.height_inc;
                 changed = true;
             }
 
@@ -999,8 +1030,8 @@ static bool handle_normal_hints(void *data, xcb_connection_t *conn, uint8_t stat
     } else
         goto render_and_return;
 
-    if (fabs(con->aspect_ratio - aspect_ratio) > DBL_EPSILON) {
-        con->aspect_ratio = aspect_ratio;
+    if (fabs(con->window->aspect_ratio - aspect_ratio) > DBL_EPSILON) {
+        con->window->aspect_ratio = aspect_ratio;
         changed = true;
     }
 
@@ -1335,11 +1366,11 @@ void handle_event(int type, xcb_generic_event_t *event) {
             DLOG("xkb new keyboard notify, sequence %d, time %d\n", state->sequence, state->time);
             xcb_key_symbols_free(keysyms);
             keysyms = xcb_key_symbols_alloc(conn);
+            if (((xcb_xkb_new_keyboard_notify_event_t *)event)->changed & XCB_XKB_NKN_DETAIL_KEYCODES)
+                (void)load_keymap();
             ungrab_all_keys(conn);
             translate_keysyms();
             grab_all_keys(conn);
-            if (((xcb_xkb_new_keyboard_notify_event_t *)event)->changed & XCB_XKB_NKN_DETAIL_KEYCODES)
-                (void)load_keymap();
         } else if (state->xkbType == XCB_XKB_MAP_NOTIFY) {
             if (event_is_ignored(event->sequence, type)) {
                 DLOG("Ignoring map notify event for sequence %d.\n", state->sequence);