From b6690045edb24397333f179080a272f9c2d83869 Mon Sep 17 00:00:00 2001 From: ekarpp Date: Mon, 2 Nov 2020 22:16:48 +0200 Subject: [PATCH] i3-nagbar: add possibility to open bar on focused monitor Closes #3692 i3-nagbar will open by default on the monitor with input focus and using the flag -p on the primary monitor. --- RELEASE-NOTES-next | 3 +- i3-nagbar/main.c | 78 +++++++++++++++++++++++++++++++++++++++------- man/i3-nagbar.man | 6 +++- 3 files changed, 73 insertions(+), 14 deletions(-) diff --git a/RELEASE-NOTES-next b/RELEASE-NOTES-next index c24c82a06..fa7f841b6 100644 --- a/RELEASE-NOTES-next +++ b/RELEASE-NOTES-next @@ -11,7 +11,8 @@ strongly encouraged to upgrade. │ Changes in i3 v4.20 │ └────────────────────────────┘ - • placeholder + • i3-nagbar: position on focused monitor by default + • i3-nagbar: add option to position on primary monitor ┌────────────────────────────┐ │ Bugfixes │ diff --git a/i3-nagbar/main.c b/i3-nagbar/main.c index b13ee1343..7d9c0901f 100644 --- a/i3-nagbar/main.c +++ b/i3-nagbar/main.c @@ -266,13 +266,9 @@ static int handle_expose(xcb_connection_t *conn, xcb_expose_event_t *event) { } /** - * Return the position and size the i3-nagbar window should use. - * This will be the primary output or a fallback if it cannot be determined. + * Tries to position the rectangle on the primary output. */ -static xcb_rectangle_t get_window_position(void) { - /* Default values if we cannot determine the primary output or its CRTC info. */ - xcb_rectangle_t result = (xcb_rectangle_t){50, 50, 500, font.height + 2 * MSG_PADDING + BAR_BORDER}; - +static void set_window_position_primary(xcb_rectangle_t *result) { xcb_randr_get_screen_resources_current_cookie_t rcookie = xcb_randr_get_screen_resources_current(conn, root); xcb_randr_get_output_primary_cookie_t pcookie = xcb_randr_get_output_primary(conn, root); @@ -314,14 +310,61 @@ static xcb_rectangle_t get_window_position(void) { goto free_resources; } - result.x = crtc->x; - result.y = crtc->y; + result->x = crtc->x; + result->y = crtc->y; goto free_resources; free_resources: free(res); free(primary); - return result; +} + +/** + * Tries to position the rectangle on the output with input focus. + * If unsuccessful, try to position on primary output. + */ +static void set_window_position_focus(xcb_rectangle_t *result) { + bool success = false; + xcb_get_input_focus_reply_t *input_focus = NULL; + xcb_get_geometry_reply_t *geometry = NULL; + xcb_translate_coordinates_reply_t *coordinates = NULL; + + /* To avoid the input window disappearing while determining its position */ + xcb_grab_server(conn); + + input_focus = xcb_get_input_focus_reply(conn, xcb_get_input_focus(conn), NULL); + if (input_focus == NULL || input_focus->focus == XCB_NONE) { + LOG("Failed to receive the current input focus or no window has the input focus right now.\n"); + goto free_resources; + } + + geometry = xcb_get_geometry_reply(conn, xcb_get_geometry(conn, input_focus->focus), NULL); + if (geometry == NULL) { + LOG("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) { + LOG("Failed to translate coordinates.\n"); + goto free_resources; + } + + LOG("Found current focus at x = %i / y = %i.\n", coordinates->dst_x, coordinates->dst_y); + result->x = coordinates->dst_x; + result->y = coordinates->dst_y; + success = true; + +free_resources: + xcb_ungrab_server(conn); + free(input_focus); + free(coordinates); + free(geometry); + if (!success) { + LOG("Could not position on focused output, trying to position on primary output.\n"); + set_window_position_primary(result); + } } int main(int argc, char *argv[]) { @@ -360,6 +403,7 @@ int main(int argc, char *argv[]) { argv0 = argv[0]; + bool position_on_primary = false; char *pattern = sstrdup("pango:monospace 8"); int o, option_index = 0; enum { TYPE_ERROR = 0, @@ -373,9 +417,10 @@ int main(int argc, char *argv[]) { {"help", no_argument, 0, 'h'}, {"message", required_argument, 0, 'm'}, {"type", required_argument, 0, 't'}, + {"primary", no_argument, 0, 'p'}, {0, 0, 0, 0}}; - char *options_string = "b:B:f:m:t:vh"; + char *options_string = "b:B:f:m:t:vhp"; prompt = i3string_from_utf8("Please do not run this program."); @@ -399,8 +444,11 @@ int main(int argc, char *argv[]) { case 'h': free(pattern); printf("i3-nagbar " I3_VERSION "\n"); - printf("i3-nagbar [-m ] [-b