From a7c7cf8159c6fed2c40ee45f25f508b3f1467c9a Mon Sep 17 00:00:00 2001 From: Qball Cow Date: Tue, 20 Oct 2015 18:41:45 +0200 Subject: [PATCH 1/4] Add fake transparency --- config/config.def.c | 7 +-- include/rofi.h | 2 + include/textbox.h | 16 +++--- source/rofi.c | 115 +++++++++++++++++++++++++++++--------------- source/xrmoptions.c | 3 +- 5 files changed, 93 insertions(+), 50 deletions(-) diff --git a/config/config.def.c b/config/config.def.c index fcf2f4cb..701d6cce 100644 --- a/config/config.def.c +++ b/config/config.def.c @@ -141,7 +141,8 @@ Settings config = { /** Separator style: dash/solid */ .separator_style = "dash", /** Hide scrollbar */ - .hide_scrollbar = FALSE, - .markup_rows = FALSE, - .fullscreen = FALSE, + .hide_scrollbar = FALSE, + .markup_rows = FALSE, + .fullscreen = FALSE, + .fake_transparency = FALSE, }; diff --git a/include/rofi.h b/include/rofi.h index 871a676c..ff52b71d 100644 --- a/include/rofi.h +++ b/include/rofi.h @@ -246,6 +246,8 @@ typedef struct _Settings unsigned int markup_rows; /** fullscreen */ unsigned int fullscreen; + /** bg image */ + unsigned int fake_transparency; } Settings; /** Global Settings structure. */ diff --git a/include/textbox.h b/include/textbox.h index 7fb53305..2b2f2e57 100644 --- a/include/textbox.h +++ b/include/textbox.h @@ -33,14 +33,14 @@ typedef struct typedef enum { - TB_AUTOHEIGHT = 1 << 0, - TB_AUTOWIDTH = 1 << 1, - TB_LEFT = 1 << 16, - TB_RIGHT = 1 << 17, - TB_CENTER = 1 << 18, - TB_EDITABLE = 1 << 19, - TB_MARKUP = 1 << 20, - TB_WRAP = 1 << 21, + TB_AUTOHEIGHT = 1 << 0, + TB_AUTOWIDTH = 1 << 1, + TB_LEFT = 1 << 16, + TB_RIGHT = 1 << 17, + TB_CENTER = 1 << 18, + TB_EDITABLE = 1 << 19, + TB_MARKUP = 1 << 20, + TB_WRAP = 1 << 21, } TextboxFlags; typedef enum diff --git a/source/rofi.c b/source/rofi.c index f5b26aec..73b78abf 100644 --- a/source/rofi.c +++ b/source/rofi.c @@ -176,54 +176,55 @@ static int levenshtein ( char *s1, char *s2 ) typedef struct MenuState { - Switcher *sw; - unsigned int menu_lines; - unsigned int max_elements; - unsigned int max_rows; - unsigned int columns; + Switcher *sw; + unsigned int menu_lines; + unsigned int max_elements; + unsigned int max_rows; + unsigned int columns; // window width,height - unsigned int w, h; - int x, y; - unsigned int element_width; - int top_offset; + unsigned int w, h; + int x, y; + unsigned int element_width; + int top_offset; // Update/Refilter list. - int update; - int refilter; - int rchanged; - int cur_page; + int update; + int refilter; + int rchanged; + int cur_page; // Entries - textbox *text; - textbox *prompt_tb; - textbox *message_tb; - textbox *case_indicator; - textbox **boxes; - scrollbar *scrollbar; - int *distance; - unsigned int *line_map; + textbox *text; + textbox *prompt_tb; + textbox *message_tb; + textbox *case_indicator; + textbox **boxes; + scrollbar *scrollbar; + int *distance; + unsigned int *line_map; - unsigned int num_lines; + unsigned int num_lines; // Selected element. - unsigned int selected; - unsigned int filtered_lines; + unsigned int selected; + unsigned int filtered_lines; // Last offset in paginating. - unsigned int last_offset; + unsigned int last_offset; - KeySym prev_key; - Time last_button_press; + KeySym prev_key; + Time last_button_press; - int quit; - int skip_absorb; + int quit; + int skip_absorb; // Return state - unsigned int *selected_line; - MenuReturn retv; - char **lines; - int *lines_not_ascii; - int line_height; - unsigned int border; + unsigned int *selected_line; + MenuReturn retv; + char **lines; + int *lines_not_ascii; + int line_height; + unsigned int border; + cairo_surface_t *bg; }MenuState; static Window create_window ( Display *display ) @@ -285,6 +286,10 @@ static void menu_free_state ( MenuState *state ) textbox_free ( state->prompt_tb ); textbox_free ( state->case_indicator ); scrollbar_free ( state->scrollbar ); + if ( state->bg ) { + cairo_surface_destroy ( state->bg ); + state->bg = NULL; + } for ( unsigned int i = 0; i < state->max_elements; i++ ) { textbox_free ( state->boxes[i] ); @@ -829,9 +834,20 @@ static void menu_update ( MenuState *state ) cairo_surface_t *surf = cairo_image_surface_create ( get_format (), state->w, state->h ); cairo_t *d = cairo_create ( surf ); cairo_set_operator ( d, CAIRO_OPERATOR_SOURCE ); - // Paint the background. - color_background ( display, d ); - cairo_paint ( d ); + if ( config.fake_transparency ) { + if ( state->bg != NULL ) { + cairo_set_source_surface ( d, state->bg, -(double) ( state->x ), -(double) ( state->y ) ); + cairo_paint ( d ); + cairo_set_operator ( d, CAIRO_OPERATOR_OVER ); + color_background ( display, d ); + cairo_paint ( d ); + } + } + else { + // Paint the background. + color_background ( display, d ); + cairo_paint ( d ); + } color_border ( display, d ); if ( config.menu_bw > 0 ) { @@ -1042,6 +1058,24 @@ MenuReturn menu ( Switcher *sw, char **input, char *prompt, unsigned int *select sn_launchee_context_setup_window ( sncontext, main_window ); } } + Window root = DefaultRootWindow ( display ); + if ( config.fake_transparency ) { + cairo_surface_t *s = cairo_xlib_surface_create ( display, + root, + DefaultVisual ( display, DefaultScreen ( display ) ), + DisplayWidth ( display, DefaultScreen ( display ) ), + DisplayHeight ( display, DefaultScreen ( display ) ) ); + + state.bg = cairo_image_surface_create ( get_format (), + DisplayWidth ( display, DefaultScreen ( display ) ), + DisplayHeight ( display, DefaultScreen ( display ) ) ); + cairo_t *dr = cairo_create ( state.bg ); + cairo_set_source_surface ( dr, s, 0, 0 ); + cairo_paint ( dr ); + cairo_destroy ( dr ); + cairo_surface_destroy ( s ); + } + // Get active monitor size. monitor_active ( display, &mon ); @@ -1215,6 +1249,11 @@ MenuReturn menu ( Switcher *sw, char **input, char *prompt, unsigned int *select else if ( ev.type == ConfigureNotify ) { XConfigureEvent xce = ev.xconfigure; if ( xce.window == main_window ) { + if ( state.x != (int ) xce.x || state.y != (int) xce.y ) { + state.x = xce.x; + state.y = xce.y; + state.update = TRUE; + } if ( state.w != (unsigned int) xce.width || state.h != (unsigned int ) xce.height ) { state.w = xce.width; state.h = xce.height; diff --git a/source/xrmoptions.c b/source/xrmoptions.c index 2e090215..ac211585 100644 --- a/source/xrmoptions.c +++ b/source/xrmoptions.c @@ -133,7 +133,8 @@ static XrmOption xrmOptions[] = { { xrm_String, "separator-style", { .str = &config.separator_style }, NULL, "Separator style (none, dash, solid)" }, { xrm_Boolean, "hide-scrollbar", { .num = &config.hide_scrollbar }, NULL, "Hide the scroll-bar" }, { xrm_Boolean, "markup-rows", { .num = &config.markup_rows }, NULL, "Show markup" }, - { xrm_Boolean, "fullscreen", { .num = &config.fullscreen }, NULL, "Fullscreen" } + { xrm_Boolean, "fullscreen", { .num = &config.fullscreen }, NULL, "Fullscreen" }, + { xrm_Boolean, "fake-transparency", { .num = &config.fake_transparency }, NULL, "Fake transparency" } }; // Dynamic options. From f52e73a4f2cde776c3a2f222e99e3957f748e7ae Mon Sep 17 00:00:00 2001 From: Qball Cow Date: Tue, 20 Oct 2015 18:51:29 +0200 Subject: [PATCH 2/4] Only store the monitor we are currently displayed on --- source/rofi.c | 55 ++++++++++++++++++++++++--------------------------- 1 file changed, 26 insertions(+), 29 deletions(-) diff --git a/source/rofi.c b/source/rofi.c index 73b78abf..dcddc1dd 100644 --- a/source/rofi.c +++ b/source/rofi.c @@ -225,6 +225,7 @@ typedef struct MenuState int line_height; unsigned int border; cairo_surface_t *bg; + workarea mon; }MenuState; static Window create_window ( Display *display ) @@ -307,33 +308,33 @@ static void menu_free_state ( MenuState *state ) * * Calculates the window poslition */ -static void calculate_window_position ( MenuState *state, const workarea *mon ) +static void calculate_window_position ( MenuState *state ) { // Default location is center. - state->y = mon->y + ( mon->h - state->h ) / 2; - state->x = mon->x + ( mon->w - state->w ) / 2; + state->y = state->mon.y + ( state->mon.h - state->h ) / 2; + state->x = state->mon.x + ( state->mon.w - state->w ) / 2; // Determine window location switch ( config.location ) { case WL_NORTH_WEST: - state->x = mon->x; + state->x = state->mon.x; case WL_NORTH: - state->y = mon->y; + state->y = state->mon.y; break; case WL_NORTH_EAST: - state->y = mon->y; + state->y = state->mon.y; case WL_EAST: - state->x = mon->x + mon->w - state->w; + state->x = state->mon.x + state->mon.w - state->w; break; case WL_EAST_SOUTH: - state->x = mon->x + mon->w - state->w; + state->x = state->mon.x + state->mon.w - state->w; case WL_SOUTH: - state->y = mon->y + mon->h - state->h; + state->y = state->mon.y + state->mon.h - state->h; break; case WL_SOUTH_WEST: - state->y = mon->y + mon->h - state->h; + state->y = state->mon.y + state->mon.h - state->h; case WL_WEST: - state->x = mon->x; + state->x = state->mon.x; break; case WL_CENTER: default: @@ -836,7 +837,9 @@ static void menu_update ( MenuState *state ) cairo_set_operator ( d, CAIRO_OPERATOR_SOURCE ); if ( config.fake_transparency ) { if ( state->bg != NULL ) { - cairo_set_source_surface ( d, state->bg, -(double) ( state->x ), -(double) ( state->y ) ); + cairo_set_source_surface ( d, state->bg, + -(double) ( state->x - state->mon.x ), + -(double) ( state->y - state->mon.y ) ); cairo_paint ( d ); cairo_set_operator ( d, CAIRO_OPERATOR_OVER ); color_background ( display, d ); @@ -1038,8 +1041,6 @@ MenuReturn menu ( Switcher *sw, char **input, char *prompt, unsigned int *select if ( next_pos ) { *next_pos = *selected_line; } - workarea mon; - // 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. @@ -1058,6 +1059,8 @@ MenuReturn menu ( Switcher *sw, char **input, char *prompt, unsigned int *select sn_launchee_context_setup_window ( sncontext, main_window ); } } + // Get active monitor size. + monitor_active ( display, &( state.mon ) ); Window root = DefaultRootWindow ( display ); if ( config.fake_transparency ) { cairo_surface_t *s = cairo_xlib_surface_create ( display, @@ -1066,19 +1069,14 @@ MenuReturn menu ( Switcher *sw, char **input, char *prompt, unsigned int *select DisplayWidth ( display, DefaultScreen ( display ) ), DisplayHeight ( display, DefaultScreen ( display ) ) ); - state.bg = cairo_image_surface_create ( get_format (), - DisplayWidth ( display, DefaultScreen ( display ) ), - DisplayHeight ( display, DefaultScreen ( display ) ) ); + state.bg = cairo_image_surface_create ( get_format (), state.mon.w, state.mon.h ); cairo_t *dr = cairo_create ( state.bg ); - cairo_set_source_surface ( dr, s, 0, 0 ); + cairo_set_source_surface ( dr, s, -state.mon.x, -state.mon.y ); cairo_paint ( dr ); cairo_destroy ( dr ); cairo_surface_destroy ( s ); } - // Get active monitor size. - monitor_active ( display, &mon ); - // we need this at this point so we can get height. state.line_height = textbox_get_estimated_char_height (); state.case_indicator = textbox_create ( TB_AUTOWIDTH, ( state.border ), ( state.border ), @@ -1086,7 +1084,7 @@ MenuReturn menu ( Switcher *sw, char **input, char *prompt, unsigned int *select // Height of a row. if ( config.menu_lines == 0 ) { // Autosize it. - int h = mon.h - state.border * 2 - config.line_margin; + int h = state.mon.h - state.border * 2 - config.line_margin; int r = ( h ) / ( state.line_height * config.element_height ) - 1 - config.sidebar_mode; state.menu_lines = r; } @@ -1094,7 +1092,7 @@ MenuReturn menu ( Switcher *sw, char **input, char *prompt, unsigned int *select state.menu_lines = config.menu_lines; } menu_calculate_rows_columns ( &state ); - menu_calculate_window_and_element_width ( &state, &mon ); + menu_calculate_window_and_element_width ( &state, &( state.mon ) ); // Prompt box. state.prompt_tb = textbox_create ( TB_AUTOWIDTH, ( state.border ), ( state.border ), @@ -1166,11 +1164,11 @@ MenuReturn menu ( Switcher *sw, char **input, char *prompt, unsigned int *select // Sidebar mode. if ( config.menu_lines == 0 ) { - state.h = mon.h; + state.h = state.mon.h; } // Move the window to the correct x,y position. - calculate_window_position ( &state, &mon ); + calculate_window_position ( &state ); if ( config.sidebar_mode == TRUE ) { int width = ( state.w - ( 2 * ( state.border ) + ( num_switchers - 1 ) * config.line_margin ) ) / num_switchers; @@ -1457,7 +1455,6 @@ void error_dialog ( const char *msg, int markup ) .columns = 0, .update = TRUE, }; - workarea mon; // Try to grab the keyboard as early as possible. // We grab this using the rootwindow (as dmenu does it). @@ -1469,14 +1466,14 @@ void error_dialog ( const char *msg, int markup ) return; } // Get active monitor size. - monitor_active ( display, &mon ); + monitor_active ( display, &( state.mon ) ); // main window isn't explicitly destroyed in case we switch modes. Reusing it prevents flicker XWindowAttributes attr; if ( main_window == None || XGetWindowAttributes ( display, main_window, &attr ) == 0 ) { main_window = create_window ( display ); } - menu_calculate_window_and_element_width ( &state, &mon ); + menu_calculate_window_and_element_width ( &state, &( state.mon ) ); state.max_elements = 0; state.text = textbox_create ( ( TB_AUTOHEIGHT | TB_WRAP ) + ( ( markup ) ? TB_MARKUP : 0 ), @@ -1488,7 +1485,7 @@ void error_dialog ( const char *msg, int markup ) state.h = state.line_height + ( state.border ) * 2; // Move the window to the correct x,y position. - calculate_window_position ( &state, &mon ); + calculate_window_position ( &state ); XMoveResizeWindow ( display, main_window, state.x, state.y, state.w, state.h ); cairo_xlib_surface_set_size ( surface, state.w, state.h ); // Display it. From b4880b36017ea3f33b4d3268b3cba9a79edbe0e6 Mon Sep 17 00:00:00 2001 From: Qball Cow Date: Tue, 20 Oct 2015 18:58:03 +0200 Subject: [PATCH 3/4] Small tweak. --- source/rofi.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/source/rofi.c b/source/rofi.c index dcddc1dd..6ddf217c 100644 --- a/source/rofi.c +++ b/source/rofi.c @@ -1061,13 +1061,14 @@ MenuReturn menu ( Switcher *sw, char **input, char *prompt, unsigned int *select } // Get active monitor size. monitor_active ( display, &( state.mon ) ); - Window root = DefaultRootWindow ( display ); if ( config.fake_transparency ) { - cairo_surface_t *s = cairo_xlib_surface_create ( display, - root, - DefaultVisual ( display, DefaultScreen ( display ) ), - DisplayWidth ( display, DefaultScreen ( display ) ), - DisplayHeight ( display, DefaultScreen ( display ) ) ); + Window root = DefaultRootWindow ( display ); + int screen = DefaultScreen ( display ); + cairo_surface_t *s = cairo_xlib_surface_create ( display, + root, + DefaultVisual ( display, screen ), + DisplayWidth ( display, screen ), + DisplayHeight ( display, screen ) ); state.bg = cairo_image_surface_create ( get_format (), state.mon.w, state.mon.h ); cairo_t *dr = cairo_create ( state.bg ); From fd46ecb3d6a6115de6fbb1cb75817d54c1bafc2b Mon Sep 17 00:00:00 2001 From: QC Date: Wed, 21 Oct 2015 20:31:58 +0200 Subject: [PATCH 4/4] Update manpage --- doc/rofi-manpage.markdown | 6 ++++++ doc/rofi.1 | 10 ++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/doc/rofi-manpage.markdown b/doc/rofi-manpage.markdown index dd24a205..b526dfb9 100644 --- a/doc/rofi-manpage.markdown +++ b/doc/rofi-manpage.markdown @@ -54,6 +54,7 @@ [ -parse-hosts ] [ -combi-modi *mode1,mode2* ] [ -normal-window ] +[ -fake-transparency ] [ -quiet ] ## DESCRIPTION @@ -577,6 +578,11 @@ For more information on supported markup see [here](https://developer.gnome.org/ Make **rofi** reacts like a normal application window. Useful for scripts like Clerk that are basically an application. +`-fake-transparency` + +Enable fake transparency. This only works with transparent background color in the theme, not the opacity setting. + + ### Message dialog `-e` *message* diff --git a/doc/rofi.1 b/doc/rofi.1 index f180f940..507d8a3a 100644 --- a/doc/rofi.1 +++ b/doc/rofi.1 @@ -1,13 +1,13 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "ROFI\-MANPAGE" "" "September 2015" "" "" +.TH "ROFI\-MANPAGE" "" "October 2015" "" "" . .SH "NAME" \fBrofi\fR \- A window switcher, run launcher, ssh dialog and dmenu replacement . .SH "SYNOPSIS" -\fBrofi\fR [ \-width \fIpct_scr\fR ] [ \-lines \fIlines\fR ] [ \-columns \fIcolumns\fR ] [ \-font \fIpangofont\fR ] [ \-fg \fIcolor\fR ] [ \-fg\-urgent \fIcolor\fR ] [ \-fg\-active \fIcolor\fR ] [ \-bg\-urgent \fIcolor\fR ] [ \-bg\-active \fIcolor\fR ] [ \-bg \fIcolor\fR ] [ \-bgalt \fIcolor\fR ] [ \-hlfg \fIcolor\fR ] [ \-hlbg \fIcolor\fR ] [ \-key\-\fBmode\fR \fIcombo\fR ] [ \-terminal \fIterminal\fR ] [ \-location \fIposition\fR ] [ \-fixed\-num\-lines ] [ \-padding \fIpadding\fR ] [ \-opacity \fIopacity%\fR ] [ \-display \fIdisplay\fR ] [ \-bc \fIcolor\fR ] [ \-bw \fIwidth\fR ] [ \-dmenu [ \-p \fIprompt\fR ] [ \-sep \fIseparator\fR ] [ \-l \fIselected line\fR ] [ \-mesg ] [ \-select ] ] [ \-filter \fIfilter\fR ] [ \-ssh\-client \fIclient\fR ] [ \-ssh\-command \fIcommand\fR ] [ \-disable\-history ] [ \-levenshtein\-sort ] [ \-case\-sensitive ] [ \-show \fImode\fR ] [ \-modi \fImode1,mode2\fR ] [ \-eh \fIelement height\fR ] [ \-lazy\-filter\-limit \fIlimit\fR ] [ \-e \fImessage\fR] [ \-a \fIrow\fR ] [ \-u \fIrow\fR ] [ \-pid \fIpath\fR ] [ \-now ] [ \-rnow ] [ \-snow ] [ \-version ] [ \-help] [ \-dump\-xresources ] [ \-auto\-select ] [ \-parse\-hosts ] [ \-combi\-modi \fImode1,mode2\fR ] [ \-normal\-window ] [ \-quiet ] +\fBrofi\fR [ \-width \fIpct_scr\fR ] [ \-lines \fIlines\fR ] [ \-columns \fIcolumns\fR ] [ \-font \fIpangofont\fR ] [ \-fg \fIcolor\fR ] [ \-fg\-urgent \fIcolor\fR ] [ \-fg\-active \fIcolor\fR ] [ \-bg\-urgent \fIcolor\fR ] [ \-bg\-active \fIcolor\fR ] [ \-bg \fIcolor\fR ] [ \-bgalt \fIcolor\fR ] [ \-hlfg \fIcolor\fR ] [ \-hlbg \fIcolor\fR ] [ \-key\-\fBmode\fR \fIcombo\fR ] [ \-terminal \fIterminal\fR ] [ \-location \fIposition\fR ] [ \-fixed\-num\-lines ] [ \-padding \fIpadding\fR ] [ \-opacity \fIopacity%\fR ] [ \-display \fIdisplay\fR ] [ \-bc \fIcolor\fR ] [ \-bw \fIwidth\fR ] [ \-dmenu [ \-p \fIprompt\fR ] [ \-sep \fIseparator\fR ] [ \-l \fIselected line\fR ] [ \-mesg ] [ \-select ] ] [ \-filter \fIfilter\fR ] [ \-ssh\-client \fIclient\fR ] [ \-ssh\-command \fIcommand\fR ] [ \-disable\-history ] [ \-levenshtein\-sort ] [ \-case\-sensitive ] [ \-show \fImode\fR ] [ \-modi \fImode1,mode2\fR ] [ \-eh \fIelement height\fR ] [ \-lazy\-filter\-limit \fIlimit\fR ] [ \-e \fImessage\fR] [ \-a \fIrow\fR ] [ \-u \fIrow\fR ] [ \-pid \fIpath\fR ] [ \-now ] [ \-rnow ] [ \-snow ] [ \-version ] [ \-help] [ \-dump\-xresources ] [ \-auto\-select ] [ \-parse\-hosts ] [ \-combi\-modi \fImode1,mode2\fR ] [ \-normal\-window ] [ \-fake\-transparency ] [ \-quiet ] . .SH "DESCRIPTION" \fBrofi\fR is an X11 popup window switcher, run dialog, dmenu replacement and more\. It focuses on being fast to use and have minimal distraction\. It supports keyboard and mouse navigation, type to filter, tokenized search and more\. @@ -969,6 +969,12 @@ Add a message line below the filter entry box\. Supports pango markup\. For more .P Make \fBrofi\fR reacts like a normal application window\. Useful for scripts like Clerk that are basically an application\. . +.P +\fB\-fake\-transparency\fR +. +.P +Enable fake transparency\. This only works with transparent background color in the theme, not the opacity setting\. +. .SS "Message dialog" \fB\-e\fR \fImessage\fR .