X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=i3-input%2Fmain.c;h=b467c4c37d86e867c747486097ce0b9c2761c4ff;hb=c93056b2d892b094926d9536583201f0f90baea6;hp=4e1be78b8a9a770affc8b6440058abcfb777ab07;hpb=47723715ce9278be2ec33d3a3fb0a4404e0074f5;p=i3%2Fi3 diff --git a/i3-input/main.c b/i3-input/main.c index 4e1be78b..b467c4c3 100644 --- a/i3-input/main.c +++ b/i3-input/main.c @@ -80,7 +80,7 @@ void debuglog(char *fmt, ...) { } /* - * Restores the X11 input focus to whereever it was before. + * Restores the X11 input focus to wherever it was before. * This is necessary because i3-input’s window has override_redirect=1 * (→ unmanaged by the window manager) and thus i3-input changes focus itself. * This function is called on exit(). @@ -137,7 +137,7 @@ static int handle_expose(void *data, xcb_connection_t *conn, xcb_expose_event_t xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &inner); /* restore font color */ - set_font_colors(pixmap_gc, get_colorpixel("#FFFFFF"), get_colorpixel("#000000")); + set_font_colors(pixmap_gc, draw_util_hex_to_color("#FFFFFF"), draw_util_hex_to_color("#000000")); /* draw the prompt … */ if (prompt != NULL) { @@ -176,14 +176,14 @@ static int handle_key_release(void *ignored, xcb_connection_t *conn, xcb_key_rel static void finish_input() { char *command = (char *)concat_strings(glyphs_utf8, input_position); - /* count the occurences of %s in the string */ + /* count the occurrences of %s in the string */ int c; int len = strlen(format); int cnt = 0; for (c = 0; c < (len - 1); c++) if (format[c] == '%' && format[c + 1] == 's') cnt++; - printf("occurences = %d\n", cnt); + printf("occurrences = %d\n", cnt); /* allocate space for the output */ int inputlen = strlen(command); @@ -216,10 +216,6 @@ static void finish_input() { free(full); -#if 0 - free(command); - return 1; -#endif exit(0); } @@ -317,10 +313,31 @@ static int handle_key_press(void *ignored, xcb_connection_t *conn, xcb_key_press static xcb_rectangle_t get_window_position(void) { xcb_rectangle_t result = (xcb_rectangle_t){logical_px(50), logical_px(50), logical_px(500), font.height + logical_px(8)}; + xcb_get_property_reply_t *supporting_wm_reply = NULL; xcb_get_input_focus_reply_t *input_focus = NULL; xcb_get_geometry_reply_t *geometry = NULL; + xcb_get_property_reply_t *wm_class = NULL; xcb_translate_coordinates_reply_t *coordinates = NULL; + xcb_atom_t A__NET_SUPPORTING_WM_CHECK; + xcb_intern_atom_cookie_t nswc_cookie = xcb_intern_atom(conn, 0, strlen("_NET_SUPPORTING_WM_CHECK"), "_NET_SUPPORTING_WM_CHECK"); + xcb_intern_atom_reply_t *nswc_reply = xcb_intern_atom_reply(conn, nswc_cookie, NULL); + if (nswc_reply == NULL) { + ELOG("Could not intern atom _NET_SUPPORTING_WM_CHECK\n"); + exit(-1); + } + A__NET_SUPPORTING_WM_CHECK = nswc_reply->atom; + free(nswc_reply); + + supporting_wm_reply = xcb_get_property_reply( + conn, xcb_get_property(conn, false, root, A__NET_SUPPORTING_WM_CHECK, XCB_ATOM_WINDOW, 0, 32), NULL); + xcb_window_t *supporting_wm_win = NULL; + if (supporting_wm_reply == NULL || xcb_get_property_value_length(supporting_wm_reply) == 0) { + DLOG("Could not determine EWMH support window.\n"); + } else { + supporting_wm_win = xcb_get_property_value(supporting_wm_reply); + } + /* In rare cases, the window holding the input focus might disappear while we are figuring out its * position. To avoid this, we grab the server in the meantime. */ xcb_grab_server(conn); @@ -331,29 +348,47 @@ static xcb_rectangle_t get_window_position(void) { goto free_resources; } + /* We need to ignore the EWMH support window to which the focus can be set if there's no suitable window to focus. */ + if (supporting_wm_win != NULL && input_focus->focus == *supporting_wm_win) { + DLOG("Input focus is on the EWMH support window, ignoring.\n"); + goto free_resources; + } + geometry = xcb_get_geometry_reply(conn, xcb_get_geometry(conn, input_focus->focus), NULL); if (geometry == NULL) { DLOG("Failed to received window geometry.\n"); goto free_resources; } - coordinates = xcb_translate_coordinates_reply( - conn, xcb_translate_coordinates(conn, input_focus->focus, root, geometry->x, geometry->y), NULL); - if (coordinates == NULL) { - DLOG("Failed to translate coordinates.\n"); - goto free_resources; - } + wm_class = xcb_get_property_reply( + conn, xcb_get_property(conn, false, input_focus->focus, XCB_ATOM_WM_CLASS, XCB_GET_PROPERTY_TYPE_ANY, 0, 32), NULL); - DLOG("Determined coordinates of window with input focus at x = %i / y = %i.\n", coordinates->dst_x, coordinates->dst_y); - result.x += coordinates->dst_x; - result.y += coordinates->dst_y; + /* We need to find out whether the input focus is on an i3 frame window. If it is, we must not translate the coordinates. */ + if (wm_class == NULL || xcb_get_property_value_length(wm_class) == 0 || strcmp(xcb_get_property_value(wm_class), "i3-frame") != 0) { + coordinates = xcb_translate_coordinates_reply( + conn, xcb_translate_coordinates(conn, input_focus->focus, root, geometry->x, geometry->y), NULL); + if (coordinates == NULL) { + DLOG("Failed to translate coordinates.\n"); + goto free_resources; + } + + DLOG("Determined coordinates of window with input focus at x = %i / y = %i.\n", coordinates->dst_x, coordinates->dst_y); + result.x += coordinates->dst_x; + result.y += coordinates->dst_y; + } else { + DLOG("Determined coordinates of window with input focus at x = %i / y = %i.\n", geometry->x, geometry->y); + result.x += geometry->x; + result.y += geometry->y; + } free_resources: xcb_ungrab_server(conn); xcb_flush(conn); + FREE(supporting_wm_reply); FREE(input_focus); FREE(geometry); + FREE(wm_class); FREE(coordinates); return result; }