X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fmainx.c;h=d3ea967c8db04f41a1be66394a27bcbff5624a58;hb=26944bea991c712adbe6774d822b9cefc785b7d9;hp=a73ea6f93009a9c9749e17487f444d0bbd2d2e0e;hpb=fb4c851e2a72ea29f290dc9dbeda723707a2961c;p=i3%2Fi3 diff --git a/src/mainx.c b/src/mainx.c index a73ea6f9..d3ea967c 100644 --- a/src/mainx.c +++ b/src/mainx.c @@ -17,6 +17,7 @@ #include #include #include +#include #include @@ -39,18 +40,19 @@ #include "debug.h" #include "handlers.h" #include "util.h" +#include "xcb.h" +#include "xinerama.h" #define TERMINAL "/usr/pkg/bin/urxvt" Display *xkbdpy; -TAILQ_HEAD(bindings_head, Binding) bindings; +TAILQ_HEAD(bindings_head, Binding) bindings = TAILQ_HEAD_INITIALIZER(bindings); xcb_event_handlers_t evenths; -/* hm, xcb_wm wants us to implement this. */ -table_t *byChild = 0; -table_t *byParent = 0; xcb_window_t root_win; +xcb_atom_t atoms[6]; + char *pattern = "-misc-fixed-medium-r-normal--13-120-75-75-C-70-iso8859-1"; int num_screens = 0; @@ -128,8 +130,8 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child, new = calloc(sizeof(Client), 1); /* We initialize x and y with the invalid coordinates -1 so that they will get updated at the next render_layout() at any case */ - new->x = -1; - new->y = -1; + new->rect.x = -1; + new->rect.y = -1; } uint32_t mask = 0; uint32_t values[3]; @@ -143,8 +145,8 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child, new->frame = xcb_generate_id(conn); new->child = child; - new->width = width; - new->height = height; + new->rect.width = width; + new->rect.height = height; /* Don’t generate events for our new window, it should *not* be managed */ mask |= XCB_CW_OVERRIDE_REDIRECT; @@ -161,8 +163,11 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child, i3Font *font = load_font(conn, pattern); + height = min(height, c_ws->rect.y + c_ws->rect.height); + width = min(width, c_ws->rect.x + c_ws->rect.width); + /* Yo dawg, I heard you like windows, so I create a window around your window… */ - xcb_create_window(conn, + xcb_void_cookie_t cookie = xcb_create_window_checked(conn, depth, new->frame, root, @@ -172,9 +177,11 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child, height + 2 + 2 + font->height, /* 2 px border plus font’s height */ 0, /* border_width = 0, we draw our own borders */ XCB_WINDOW_CLASS_INPUT_OUTPUT, - visual, + XCB_WINDOW_CLASS_COPY_FROM_PARENT, mask, values); + printf("x = %d, y = %d, width = %d, height = %d\n", x, y, width, height); + check_error(conn, cookie, "Could not create frame"); xcb_change_save_set(conn, XCB_SET_MODE_INSERT, child); /* Map the window on the screen (= make it visible) */ @@ -189,15 +196,17 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child, table_put(byChild, child, new); /* Moves the original window into the new frame we've created for it */ - xcb_reparent_window(conn, child, new->frame, 0, font->height); + new->awaiting_useless_unmap = true; + cookie = xcb_reparent_window_checked(conn, child, new->frame, 0, font->height); + check_error(conn, cookie, "Could not reparent window"); /* We are interested in property changes */ mask = XCB_CW_EVENT_MASK; values[0] = XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_STRUCTURE_NOTIFY | - XCB_EVENT_MASK_ENTER_WINDOW | - XCB_EVENT_MASK_BUTTON_PRESS; - xcb_change_window_attributes(conn, child, mask, values); + XCB_EVENT_MASK_ENTER_WINDOW; + cookie = xcb_change_window_attributes_checked(conn, child, mask, values); + check_error(conn, cookie, "Could not change window attributes"); /* We need to grab the mouse buttons for click to focus */ xcb_grab_button(conn, false, child, XCB_EVENT_MASK_BUTTON_PRESS, @@ -206,7 +215,7 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child, XCB_BUTTON_MASK_ANY /* don’t filter for any modifiers */); /* Focus the new window */ - xcb_set_input_focus(conn, XCB_INPUT_FOCUS_NONE, new->child, XCB_CURRENT_TIME); + xcb_set_input_focus(conn, XCB_INPUT_FOCUS_POINTER_ROOT, new->child, XCB_CURRENT_TIME); render_layout(conn); } @@ -240,44 +249,6 @@ void manage_existing_windows(xcb_connection_t *c, xcb_property_handlers_t *proph free(rep); } -static void initialize_xinerama(xcb_connection_t *conn) { - xcb_xinerama_query_screens_reply_t *reply; - xcb_xinerama_screen_info_t *screen_info; - int screen; - - if (!xcb_get_extension_data(conn, &xcb_xinerama_id)->present) { - printf("Xinerama extension not found, disabling.\n"); - return; - } - - if (!xcb_xinerama_is_active_reply(conn, xcb_xinerama_is_active(conn), NULL)->state) { - printf("Xinerama is not active (in your X-Server), disabling.\n"); - return; - } - - - reply = xcb_xinerama_query_screens_reply(conn, xcb_xinerama_query_screens_unchecked(conn), NULL); - /* TODO: error check */ - screen_info = xcb_xinerama_query_screens_screen_info(reply); - - num_screens = xcb_xinerama_query_screens_screen_info_length(reply); - - /* Just go through each workspace and associate as many screens as we can. */ - for (screen = 0; screen < num_screens; screen++) { - workspaces[screen].x = screen_info[screen].x_org; - workspaces[screen].y = screen_info[screen].y_org; - workspaces[screen].width = screen_info[screen].width; - workspaces[screen].height = screen_info[screen].height; - workspaces[screen].screen_num = screen; - - printf("found Xinerama screen: %d x %d at %d x %d\n", - screen_info[screen].width, screen_info[screen].height, - screen_info[screen].x_org, screen_info[screen].y_org); - } - - free(screen_info); -} - int main(int argc, char *argv[], char *env[]) { int i, screens; xcb_connection_t *c; @@ -293,8 +264,6 @@ int main(int argc, char *argv[], char *env[]) { byChild = alloc_table(); byParent = alloc_table(); - TAILQ_INIT(&bindings); - c = xcb_connect(NULL, &screens); /* TODO: this has to be more beautiful somewhen */ @@ -343,15 +312,42 @@ int main(int argc, char *argv[], char *env[]) { xcb_property_handlers_init(&prophs, &evenths); xcb_event_set_map_notify_handler(&evenths, handle_map_notify_event, &prophs); + xcb_event_set_client_message_handler(&evenths, handle_client_message, 0); + xcb_watch_wm_name(&prophs, 128, handle_windowname_change, 0); root = xcb_aux_get_screen(c, screens)->root; root_win = root; uint32_t mask = XCB_CW_EVENT_MASK; - uint32_t values[] = { XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_PROPERTY_CHANGE }; + uint32_t values[] = { XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_ENTER_WINDOW}; xcb_change_window_attributes(c, root, mask, values); + /* Setup NetWM atoms */ + /* TODO: needs cleanup, needs more xcb (asynchronous), needs more error checking */ +#define GET_ATOM(name) { \ + xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(c, xcb_intern_atom(c, 0, strlen(#name), #name), NULL); \ + if (!reply) { \ + printf("Could not get atom " #name "\n"); \ + exit(-1); \ + } \ + atoms[name] = reply->atom; \ + free(reply); \ +} + + GET_ATOM(_NET_SUPPORTED); + GET_ATOM(_NET_WM_STATE_FULLSCREEN); + GET_ATOM(_NET_SUPPORTING_WM_CHECK); + GET_ATOM(_NET_WM_NAME); + GET_ATOM(UTF8_STRING); + GET_ATOM(_NET_WM_STATE); + + check_error(c, xcb_change_property_checked(c, XCB_PROP_MODE_REPLACE, root, atoms[_NET_SUPPORTED], ATOM, 32, 5, atoms), "Could not set _NET_SUPPORTED"); + + xcb_change_property(c, XCB_PROP_MODE_REPLACE, root, atoms[_NET_SUPPORTING_WM_CHECK], WINDOW, 32, 1, &root); + + xcb_change_property(c, XCB_PROP_MODE_REPLACE, root, atoms[_NET_WM_NAME] , atoms[UTF8_STRING], 8, strlen("i3"), "i3"); + #define BIND(key, modifier, cmd) { \ Binding *new = malloc(sizeof(Binding)); \ new->keycode = key; \ @@ -365,6 +361,8 @@ int main(int argc, char *argv[], char *env[]) { BIND(30, 0, "exec /usr/pkg/bin/urxvt"); + BIND(41, BIND_MOD_1, "f"); + BIND(44, BIND_MOD_1, "h"); BIND(45, BIND_MOD_1, "j"); BIND(46, BIND_MOD_1, "k"); @@ -409,6 +407,24 @@ int main(int argc, char *argv[], char *env[]) { manage_existing_windows(c, &prophs, root); + /* Get pointer position to see on which screen we’re starting */ + xcb_query_pointer_cookie_t pointer_cookie = xcb_query_pointer(c, root); + xcb_query_pointer_reply_t *reply = xcb_query_pointer_reply(c, pointer_cookie, NULL); + if (reply == NULL) { + printf("Could not get pointer position\n"); + return 1; + } + + i3Screen *screen = get_screen_containing(reply->root_x, reply->root_y); + if (screen == NULL) { + printf("ERROR: No such screen\n"); + return 0; + } + if (screen->current_workspace != 0) { + printf("Ok, I need to go to the other workspace\n"); + c_ws = &workspaces[screen->current_workspace]; + } + xcb_event_wait_for_event_loop(&evenths); /* not reached */