]> git.sur5r.net Git - i3/i3/commitdiff
Implement clicking on the bar to switch workspaces
authorMichael Stapelberg <michael+x200@stapelberg.de>
Sun, 15 Mar 2009 16:49:25 +0000 (17:49 +0100)
committerMichael Stapelberg <michael+x200@stapelberg.de>
Sun, 15 Mar 2009 16:49:25 +0000 (17:49 +0100)
include/commands.h
src/commands.c
src/handlers.c
src/xinerama.c

index 412c9b076d48a4567477534e6f418e85c41ee810..ce55f93589b49fec626b72d3e54887936ab8c6ec 100644 (file)
@@ -13,6 +13,7 @@
 #ifndef _COMMANDS_H
 #define _COMMANDS_H
 
+void show_workspace(xcb_connection_t *conn, int workspace);
 void parse_command(xcb_connection_t *conn, const char *command);
 
 #endif
index a1187c3c472767194effa6a3753cfea602e9fe2f..3f4fcdfb29ed0a0afc71b5295f0e839c05a62f7e 100644 (file)
@@ -447,7 +447,11 @@ static void move_current_window_to_workspace(xcb_connection_t *conn, int workspa
         render_layout(conn);
 }
 
-static void show_workspace(xcb_connection_t *conn, int workspace) {
+/*
+ * Switches to the given workspace
+ *
+ */
+void show_workspace(xcb_connection_t *conn, int workspace) {
         Client *client;
         xcb_window_t root = xcb_setup_roots_iterator(xcb_get_setup(conn)).data->root;
         /* t_ws (to workspace) is just a convenience pointer to the workspace we’re switching to */
index 32c4f0bae2a2cba569b45d99a4307f6e1b9f9df5..343fe077873d0e0c7563b94d9045b8e89f0491a5 100644 (file)
@@ -180,6 +180,63 @@ int handle_enter_notify(void *ignored, xcb_connection_t *conn, xcb_enter_notify_
         return 1;
 }
 
+/*
+ * Checks if the button press was on a stack window, handles focus setting and returns true
+ * if so, or false otherwise.
+ *
+ */
+static bool button_press_stackwin(xcb_connection_t *conn, xcb_button_press_event_t *event) {
+        struct Stack_Window *stack_win;
+        SLIST_FOREACH(stack_win, &stack_wins, stack_windows)
+                if (stack_win->window == event->event) {
+                        /* A stack window was clicked. We calculate the destination client by
+                           dividing the Y position of the event through the height of a window
+                           decoration and then set the focus to this client. */
+                        i3Font *font = load_font(conn, config.font);
+                        int decoration_height = (font->height + 2 + 2);
+                        int destination = (event->event_y / decoration_height),
+                            c = 0;
+                        Client *client;
+
+                        LOG("Click on stack_win for client %d\n", destination);
+                        CIRCLEQ_FOREACH(client, &(stack_win->container->clients), clients)
+                                if (c++ == destination) {
+                                        set_focus(conn, client);
+                                        return true;
+                                }
+
+                        return true;
+                }
+
+        return false;
+}
+
+/*
+ * Checks if the button press was on a bar, switches to the workspace and returns true
+ * if so, or false otherwise.
+ *
+ */
+static bool button_press_bar(xcb_connection_t *conn, xcb_button_press_event_t *event) {
+        i3Screen *screen;
+        TAILQ_FOREACH(screen, virtual_screens, screens)
+                if (screen->bar == event->event) {
+                        LOG("Click on a bar\n");
+                        i3Font *font = load_font(conn, config.font);
+                        int workspace = event->event_x / (font->height + 6),
+                            c = 0;
+                        /* Because workspaces can be on different screens, we need to loop
+                           through all of them and decide to count it based on its ->screen */
+                        for (int i = 0; i < 10; i++)
+                                if ((workspaces[i].screen == screen) && (c++ == workspace)) {
+                                        show_workspace(conn, i+1);
+                                        return true;
+                                }
+                        return true;
+                }
+
+        return false;
+}
+
 int handle_button_press(void *ignored, xcb_connection_t *conn, xcb_button_press_event_t *event) {
         LOG("button press!\n");
         /* This was either a focus for a client’s parent (= titlebar)… */
@@ -191,28 +248,14 @@ int handle_button_press(void *ignored, xcb_connection_t *conn, xcb_button_press_
         }
         if (client == NULL) {
                 /* The client was neither on a client’s titlebar nor on a client itself, maybe on a stack_window? */
-                struct Stack_Window *stack_win;
-                SLIST_FOREACH(stack_win, &stack_wins, stack_windows)
-                        if (stack_win->window == event->event) {
-                                /* A stack window was clicked. We calculate the destination client by
-                                   dividing the Y position of the event through the height of a window
-                                   decoration and then set the focus to this client. */
-                                i3Font *font = load_font(conn, config.font);
-                                int decoration_height = (font->height + 2 + 2);
-                                int destination = (event->event_y / decoration_height),
-                                    c = 0;
-                                Client *client;
-
-                                LOG("Click on stack_win for client %d\n", destination);
-                                CIRCLEQ_FOREACH(client, &(stack_win->container->clients), clients)
-                                        if (c++ == destination) {
-                                                set_focus(conn, client);
-                                                return 1;
-                                        }
+                if (button_press_stackwin(conn, event))
+                        return 1;
 
-                                return 1;
-                        }
+                /* Or on a bar? */
+                if (button_press_bar(conn, event))
+                        return 1;
 
+                LOG("Could not handle this button press\n");
                 return 1;
         }
 
index 7b1df9a4afd84ae269c76978c34deb866bdf0204..8d00eb4cddff02205d7f8a9fee4c6161d5e9fc24 100644 (file)
@@ -177,7 +177,7 @@ static void initialize_screen(xcb_connection_t *conn, i3Screen *screen, Workspac
                          screen->rect.x + screen->rect.width,
                          font->height + 6};
         uint32_t mask = XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK;
-        uint32_t values[] = {1, XCB_EVENT_MASK_EXPOSURE};
+        uint32_t values[] = {1, XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS};
         screen->bar = create_window(conn, bar_rect, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_CURSOR_LEFT_PTR, mask, values);
         screen->bargc = xcb_generate_id(conn);
         xcb_create_gc(conn, screen->bargc, screen->bar, 0, 0);