Skip to content
This repository has been archived by the owner on Apr 18, 2023. It is now read-only.

Commit

Permalink
Merge pull request #4244 from ekarpp/nagbar
Browse files Browse the repository at this point in the history
i3-nagbar: add possibility to open bar on focused monitor
  • Loading branch information
orestisfl committed Nov 29, 2020
2 parents 37ebd2a + b669004 commit be47908
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 14 deletions.
3 changes: 2 additions & 1 deletion RELEASE-NOTES-next
Expand Up @@ -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 │
Expand Down
78 changes: 66 additions & 12 deletions i3-nagbar/main.c
Expand Up @@ -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);

Expand Down Expand Up @@ -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[]) {
Expand Down Expand Up @@ -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,
Expand All @@ -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.");

Expand All @@ -399,8 +444,11 @@ int main(int argc, char *argv[]) {
case 'h':
free(pattern);
printf("i3-nagbar " I3_VERSION "\n");
printf("i3-nagbar [-m <message>] [-b <button> <action>] [-B <button> <action>] [-t warning|error] [-f <font>] [-v]\n");
printf("i3-nagbar [-m <message>] [-b <button> <action>] [-B <button> <action>] [-t warning|error] [-f <font>] [-v] [-p]\n");
return 0;
case 'p':
position_on_primary = true;
break;
case 'b':
case 'B':
buttons = srealloc(buttons, sizeof(button_t) * (buttoncnt + 1));
Expand Down Expand Up @@ -464,7 +512,13 @@ int main(int argc, char *argv[]) {
err(EXIT_FAILURE, "pledge");
#endif

xcb_rectangle_t win_pos = get_window_position();
/* Default values if we cannot determine the preferred window position. */
xcb_rectangle_t win_pos = (xcb_rectangle_t){50, 50, 500, font.height + 2 * MSG_PADDING + BAR_BORDER};
if (position_on_primary) {
set_window_position_primary(&win_pos);
} else {
set_window_position_focus(&win_pos);
}

xcb_cursor_context_t *cursor_ctx;
if (xcb_cursor_context_new(conn, root_screen, &cursor_ctx) < 0) {
Expand Down
6 changes: 5 additions & 1 deletion man/i3-nagbar.man
Expand Up @@ -9,7 +9,7 @@ i3-nagbar - displays an error bar on top of your screen

== SYNOPSIS

i3-nagbar [-m <message>] [-b <button> <action>] [-B <button> <action>] [-t warning|error] [-f <font>] [-v]
i3-nagbar [-m <message>] [-b <button> <action>] [-B <button> <action>] [-t warning|error] [-f <font>] [-v] [-p]

== OPTIONS

Expand Down Expand Up @@ -39,6 +39,10 @@ i3-sensible-terminal.
Same as above, but will execute the shell commands directly, without launching a
terminal emulator.

*-p, --primary*::
Always opens the i3-nagbar on the primary monitor. By default it opens on the
focused monitor.

== DESCRIPTION

i3-nagbar is used by i3 to tell you about errors in your configuration file
Expand Down

0 comments on commit be47908

Please sign in to comment.