diff --git a/include/commands.h b/include/commands.h index 412c9b07..ce55f935 100644 --- a/include/commands.h +++ b/include/commands.h @@ -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 diff --git a/src/commands.c b/src/commands.c index a1187c3c..3f4fcdfb 100644 --- a/src/commands.c +++ b/src/commands.c @@ -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 */ diff --git a/src/handlers.c b/src/handlers.c index 32c4f0ba..343fe077 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -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; + if (button_press_stackwin(conn, event)) + return 1; - 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; - } - - return 1; - } + /* Or on a bar? */ + if (button_press_bar(conn, event)) + return 1; + LOG("Could not handle this button press\n"); return 1; } diff --git a/src/xinerama.c b/src/xinerama.c index 7b1df9a4..8d00eb4c 100644 --- a/src/xinerama.c +++ b/src/xinerama.c @@ -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);