From 5133f50f309707ae2e6b229bc95adcc907f8a7d9 Mon Sep 17 00:00:00 2001 From: Istvan Petres Date: Sun, 9 Jun 2024 19:57:29 +0300 Subject: [PATCH] Add -transient-window mode (#1988) * Add -transient-window mode This will add a new mode for the rofi window so when you run it with -transient-window instead of -normal-window it will get the currently focused window and then use that as the parent window and set itself as transient of that window. It is useful so that when you use a keyboard shortcut to start rofi it will always popup on the window you are working on and so it doesn't make you refocus/move your head on large monitors :) * Fixed other windows to be focusable in transient mode and added print_help_msg for this new -transient-window option. * Added -transient-window option to doc too --- doc/rofi.1.markdown | 6 ++++++ include/view.h | 2 ++ source/rofi.c | 6 ++++++ source/view.c | 20 +++++++++++++++++++- source/xcb.c | 2 +- 5 files changed, 34 insertions(+), 2 deletions(-) diff --git a/doc/rofi.1.markdown b/doc/rofi.1.markdown index f2db1d65..1193646c 100644 --- a/doc/rofi.1.markdown +++ b/doc/rofi.1.markdown @@ -302,6 +302,12 @@ Use Pango markup to format output wherever possible. Make **rofi** react like a normal application window. Useful for scripts like Clerk that are basically an application. +`-transient-window` + +Make **rofi** react like a modal dialog that is transient to the currently +focused window. Useful when you use a keyboard shortcut to run and show +on the window you are working with. + `-[no-]steal-focus` Make rofi steal focus on launch and restore close to window that held it when diff --git a/include/view.h b/include/view.h index 783d6f4a..cef073e1 100644 --- a/include/view.h +++ b/include/view.h @@ -56,6 +56,8 @@ typedef enum { MENU_NORMAL_WINDOW = 2, /** ERROR dialog */ MENU_ERROR_DIALOG = 4, + /** Create transient window. */ + MENU_TRANSIENT_WINDOW = 8, } MenuFlags; /** diff --git a/source/rofi.c b/source/rofi.c index 3d6917f8..9ebe28df 100644 --- a/source/rofi.c +++ b/source/rofi.c @@ -326,6 +326,9 @@ static void print_main_application_options(int is_term) { is_term); print_help_msg("-normal-window", "", "Behave as a normal window. (experimental)", NULL, is_term); + print_help_msg("-transient-window", "", + "Behave as a modal dialog that is transient to the currently " + "focused window. (experimental)", NULL, is_term); print_help_msg("-show", "[mode]", "Show the mode 'mode' and exit. The mode has to be enabled.", NULL, is_term); @@ -768,6 +771,9 @@ static gboolean startup(G_GNUC_UNUSED gpointer data) { if (find_arg("-normal-window") >= 0) { window_flags |= MENU_NORMAL_WINDOW; } + if (find_arg("-transient-window") >= 0) { + window_flags |= MENU_TRANSIENT_WINDOW; + } TICK_N("Grab keyboard"); __create_window(window_flags); TICK_N("Create Window"); diff --git a/source/view.c b/source/view.c index aac8c22e..712f1aa7 100644 --- a/source/view.c +++ b/source/view.c @@ -1120,7 +1120,25 @@ void __create_window(MenuFlags menu_flags) { TICK_N("textbox setup"); // // make it an unmanaged window - if (((menu_flags & MENU_NORMAL_WINDOW) == 0)) { + if (((menu_flags & MENU_TRANSIENT_WINDOW) != 0)) { + xcb_atom_t atoms[] = {xcb->ewmh._NET_WM_STATE_MODAL}; + + window_set_atom_prop(box_window, xcb->ewmh._NET_WM_STATE, atoms, + sizeof(atoms) / sizeof(xcb_atom_t)); + window_set_atom_prop (box_window, xcb->ewmh._NET_WM_WINDOW_TYPE, + &(xcb->ewmh._NET_WM_WINDOW_TYPE_UTILITY), 1); + x11_disable_decoration(box_window); + + xcb_window_t active_window; + xcb_get_property_cookie_t awc; + awc = xcb_ewmh_get_active_window (&xcb->ewmh, xcb->screen_nbr); + + if (xcb_ewmh_get_active_window_reply(&xcb->ewmh, awc, &active_window, NULL)) { + xcb_change_property(xcb->connection, XCB_PROP_MODE_REPLACE, box_window, + XCB_ATOM_WM_TRANSIENT_FOR, XCB_ATOM_WINDOW, 32, + 1, &active_window); + } + } else if (((menu_flags & MENU_NORMAL_WINDOW) == 0)) { window_set_atom_prop(box_window, xcb->ewmh._NET_WM_STATE, &(xcb->ewmh._NET_WM_STATE_ABOVE), 1); uint32_t values[] = {1}; diff --git a/source/xcb.c b/source/xcb.c index 2b50ccb0..6ad34b53 100644 --- a/source/xcb.c +++ b/source/xcb.c @@ -1898,7 +1898,7 @@ gboolean display_late_setup(void) { // Try to grab the keyboard as early as possible. // We grab this using the rootwindow (as dmenu does it). // this seems to result in the smallest delay for most people. - if (find_arg("-normal-window") >= 0) { + if (find_arg("-normal-window") >= 0 || find_arg("-transient-window") >= 0) { return TRUE; } if (find_arg("-no-lazy-grab") >= 0) {