From 3918625804053bec0d98d2519fb86d698cf56a7b Mon Sep 17 00:00:00 2001 From: Dave Davenport Date: Tue, 19 Apr 2016 22:10:34 +0200 Subject: [PATCH] Move teardown to the logic place again (possible with deamon mode removed) --- include/rofi.h | 18 +-- include/textbox.h | 18 +-- include/view-internal.h | 5 - include/view.h | 9 +- source/dialogs/combi.c | 4 +- source/dialogs/dmenu.c | 3 - source/helper.c | 8 +- source/rofi.c | 75 +++++------ source/view.c | 284 +++++++++++++++++++++------------------- source/x11-helper.c | 2 +- 10 files changed, 205 insertions(+), 221 deletions(-) diff --git a/include/rofi.h b/include/rofi.h index fc6c2a1c..5c830db3 100644 --- a/include/rofi.h +++ b/include/rofi.h @@ -38,23 +38,13 @@ const Mode * rofi_get_mode ( unsigned int index ); void rofi_set_return_code ( int code ); /** Reset terminal */ -#define color_reset "\033[0m" +#define color_reset "\033[0m" /** Set terminal text bold */ -#define color_bold "\033[1m" +#define color_bold "\033[1m" /** Set terminal text italic */ -#define color_italic "\033[2m" +#define color_italic "\033[2m" /** Set terminal foreground text green */ -#define color_green "\033[0;32m" - -/** - * @param msg The error message to show. - * @param markup If the message contains pango markup. - * - * Create a dialog showing the msg. - * - * @returns EXIT_FAILURE if failed to create dialog, EXIT_SUCCESS if succesfull - */ -int show_error_message ( const char *msg, int markup ); +#define color_green "\033[0;32m" #define ERROR_MSG( a ) a "\n" \ "If you suspect this is caused by a bug in rofi,\n" \ diff --git a/include/textbox.h b/include/textbox.h index 3d3b8d09..e1d608e1 100644 --- a/include/textbox.h +++ b/include/textbox.h @@ -38,15 +38,15 @@ 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_PASSWORD = 1 << 22, + 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_PASSWORD = 1 << 22, } TextboxFlags; typedef enum diff --git a/include/view-internal.h b/include/view-internal.h index 4e381226..3d89170d 100644 --- a/include/view-internal.h +++ b/include/view-internal.h @@ -20,9 +20,6 @@ struct RofiViewState unsigned int max_rows; unsigned int columns; - // window width,height - unsigned int w, h; - int x, y; unsigned int element_width; int top_offset; @@ -68,8 +65,6 @@ struct RofiViewState textbox **modi; MenuFlags menu_flags; - - xcb_window_t window; // Handlers. void ( *x11_event_loop )( struct RofiViewState *state, xcb_generic_event_t *ev, xkb_stuff *xkb ); void ( *finalize )( struct RofiViewState *state ); diff --git a/include/view.h b/include/view.h index abd0172c..95fb4ad5 100644 --- a/include/view.h +++ b/include/view.h @@ -86,14 +86,6 @@ void rofi_view_restart ( RofiViewState *state ); */ void rofi_view_update ( RofiViewState *state ); -/** - * @param display Connection to the X server. - * @param state The handle to the view - * - * Enables fake transparancy on this view. - */ -void rofi_view_setup_fake_transparency ( RofiViewState *state ); - /** * @param state The handle to the view * @@ -167,5 +159,6 @@ Mode * rofi_view_get_mode ( RofiViewState *state ); void rofi_view_workers_initialize ( void ); void rofi_view_workers_finalize ( void ); +void __create_window ( MenuFlags menu_flags ); /**@}*/ #endif diff --git a/source/dialogs/combi.c b/source/dialogs/combi.c index 2e828bc1..5ab58940 100644 --- a/source/dialogs/combi.c +++ b/source/dialogs/combi.c @@ -246,9 +246,9 @@ static char * combi_get_completion ( const Mode *sw, unsigned int index ) CombiModePrivateData *pd = mode_get_private_data ( sw ); for ( unsigned i = 0; i < pd->num_switchers; i++ ) { if ( index >= pd->starts[i] && index < ( pd->starts[i] + pd->lengths[i] ) ) { - char *comp = mode_get_completion ( pd->switchers[i], index - pd->starts[i] ); + char *comp = mode_get_completion ( pd->switchers[i], index - pd->starts[i] ); char *mcomp = g_strdup_printf ( "!%c %s", mode_get_name ( pd->switchers[i] )[0], comp ); - g_free(comp); + g_free ( comp ); return mcomp; } } diff --git a/source/dialogs/dmenu.c b/source/dialogs/dmenu.c index fff41c98..56f397bf 100644 --- a/source/dialogs/dmenu.c +++ b/source/dialogs/dmenu.c @@ -510,9 +510,6 @@ int dmenu_switcher_dialog ( void ) if ( find_arg ( "-password" ) >= 0 ) { menu_flags |= MENU_PASSWORD; } - if ( find_arg ( "-normal-window" ) >= 0 ) { - menu_flags |= MENU_NORMAL_WINDOW; - } /* copy filter string */ input = g_strdup ( config.filter ); diff --git a/source/helper.c b/source/helper.c index b7de3e5b..a6767c0d 100644 --- a/source/helper.c +++ b/source/helper.c @@ -451,9 +451,9 @@ int execute_generator ( const char * cmd ) if ( error != NULL ) { char *msg = g_strdup_printf ( "Failed to execute: '%s'\nError: '%s'", cmd, error->message ); - fputs(msg,stderr); - fputs("\n", stderr); - // rofi_view_error_dialog ( msg, FALSE ); + fputs ( msg, stderr ); + fputs ( "\n", stderr ); + rofi_view_error_dialog ( msg, FALSE ); g_free ( msg ); // print error. g_error_free ( error ); @@ -591,7 +591,7 @@ int config_sanity_check ( void ) if ( found_error ) { g_string_append ( msg, "Please update your configuration." ); - show_error_message ( msg->str, TRUE ); + rofi_view_error_dialog ( msg->str, TRUE ); return TRUE; } diff --git a/source/rofi.c b/source/rofi.c index 7f708f3b..34af48d1 100644 --- a/source/rofi.c +++ b/source/rofi.c @@ -93,7 +93,6 @@ static int dmenu_mode = FALSE; int return_code = EXIT_SUCCESS; void process_result ( RofiViewState *state ); -void process_result_error ( RofiViewState *state ); void rofi_set_return_code ( int code ) { @@ -159,17 +158,12 @@ static void teardown ( int pfd ) remove_pid_file ( pfd ); } -static int pfd = -1; /** * Start dmenu mode. */ static int run_dmenu () { int ret_state = EXIT_FAILURE; - pfd = setup (); - if ( pfd < 0 ) { - return ret_state; - } // Dmenu modi has a return state. ret_state = dmenu_switcher_dialog (); @@ -181,25 +175,24 @@ static void __run_switcher_internal ( ModeMode mode, char *input ) char *prompt = g_strdup_printf ( "%s:", mode_get_name ( modi[mode] ) ); curr_switcher = mode; RofiViewState * state = rofi_view_create ( modi[mode], input, prompt, NULL, MENU_NORMAL, process_result ); + g_free ( prompt ); if ( state ) { rofi_view_set_active ( state ); } else { - g_main_loop_quit ( main_loop ); + rofi_view_set_active ( NULL ); + + if ( rofi_view_get_active () == NULL ) { + g_main_loop_quit ( main_loop ); + } } - g_free ( prompt ); } static void run_switcher ( ModeMode mode ) { - pfd = setup (); - if ( pfd < 0 ) { - return; - } // Otherwise check if requested mode is enabled. for ( unsigned int i = 0; i < num_modi; i++ ) { if ( !mode_init ( modi[i] ) ) { rofi_view_error_dialog ( ERROR_MSG ( "Failed to initialize all the modi." ), ERROR_MSG_MARKUP ); - teardown ( pfd ); return; } } @@ -210,15 +203,14 @@ static void run_switcher ( ModeMode mode ) void process_result ( RofiViewState *state ) { Mode *sw = state->sw; + rofi_view_set_active ( NULL ); if ( sw != NULL ) { unsigned int selected_line = rofi_view_get_selected_line ( state );; MenuReturn mretv = rofi_view_get_return_value ( state ); char *input = g_strdup ( rofi_view_get_user_input ( state ) ); - rofi_view_set_active ( NULL ); - rofi_view_free ( state ); - ModeMode retv = mode_result ( sw, mretv, &input, selected_line ); + ModeMode retv = mode_result ( sw, mretv, &input, selected_line ); - ModeMode mode = curr_switcher; + ModeMode mode = curr_switcher; // Find next enabled if ( retv == NEXT_DIALOG ) { mode = ( mode + 1 ) % num_modi; @@ -245,31 +237,10 @@ void process_result ( RofiViewState *state ) * Load in the new mode. */ __run_switcher_internal ( mode, input ); - g_free ( input ); - return; } - // Cleanup g_free ( input ); - for ( unsigned int i = 0; i < num_modi; i++ ) { - mode_destroy ( modi[i] ); - } } -} -void process_result_error ( RofiViewState *state ) -{ - rofi_view_set_active ( NULL ); rofi_view_free ( state ); - teardown ( pfd ); - g_main_loop_quit ( main_loop ); -} - -int show_error_message ( const char *msg, int markup ) -{ - int pfd = setup (); - if ( pfd < 0 ) { - return FALSE; - } - return rofi_view_error_dialog ( msg, markup ); } /** @@ -316,6 +287,9 @@ static void help ( G_GNUC_UNUSED int argc, char **argv ) */ static void cleanup () { + for ( unsigned int i = 0; i < num_modi; i++ ) { + mode_destroy ( modi[i] ); + } rofi_view_workers_finalize (); if ( main_loop != NULL ) { if ( main_loop_source ) { @@ -500,7 +474,6 @@ static gboolean main_loop_x11_event_handler ( xcb_generic_event_t *ev, G_GNUC_UN rofi_view_finalize ( state ); // cleanup if ( rofi_view_get_active () == NULL ) { - teardown ( pfd ); g_main_loop_quit ( main_loop ); } } @@ -536,8 +509,19 @@ static gboolean startup ( G_GNUC_UNUSED gpointer data ) { TICK_N ( "Startup" ); // flags to run immediately and exit - char *sname = NULL; - char *msg = NULL; + char *sname = NULL; + char *msg = NULL; + MenuFlags window_flags = MENU_NORMAL; + + if ( find_arg ( "-normal-window" ) >= 0 ) { + window_flags |= MENU_NORMAL_WINDOW; + } + + /** + * Create window (without showing) + */ + __create_window ( window_flags ); + // // Sanity check if ( config_sanity_check ( ) ) { @@ -566,7 +550,7 @@ static gboolean startup ( G_GNUC_UNUSED gpointer data ) if ( find_arg ( "-markup" ) >= 0 ) { markup = TRUE; } - if ( !show_error_message ( msg, markup ) ) { + if ( !rofi_view_error_dialog ( msg, markup ) ) { g_main_loop_quit ( main_loop ); } } @@ -845,8 +829,13 @@ int main ( int argc, char *argv[] ) g_idle_add ( startup, NULL ); + // Pidfile + visuals + int pfd = setup (); + if ( pfd < 0 ) { + return EXIT_FAILURE; + } // Start mainloop. g_main_loop_run ( main_loop ); - + teardown ( pfd ); return return_code; } diff --git a/source/view.c b/source/view.c index e190eab4..23104656 100644 --- a/source/view.c +++ b/source/view.c @@ -69,17 +69,30 @@ GThreadPool *tpool = NULL; RofiViewState *current_active_menu = NULL; +static void rofi_view_resize ( RofiViewState *state ); + struct { xcb_window_t main_window; cairo_surface_t *surface; cairo_surface_t *fake_bg; cairo_t *draw; + MenuFlags flags; + GQueue views; + int width, height; + int x, y; + workarea mon; } CacheState = { .main_window = XCB_WINDOW_NONE, .surface = NULL, .fake_bg = NULL, .draw = NULL, + .flags = MENU_NORMAL, + .views = G_QUEUE_INIT, + .width = 0, + .height = 0, + .x = 0, + .y = 0, }; static char * get_matching_state ( void ) @@ -170,54 +183,54 @@ static void menu_capture_screenshot ( void ) * * Calculates the window poslition */ -static void calculate_window_position ( RofiViewState *state ) +static void calculate_window_position ( void ) { if ( config.fullscreen ) { - state->x = state->mon.x; - state->y = state->mon.y; + CacheState.x = CacheState.mon.x; + CacheState.y = CacheState.mon.y; return; } // Default location is center. - state->y = state->mon.y + ( state->mon.h - state->h ) / 2; - state->x = state->mon.x + ( state->mon.w - state->w ) / 2; + CacheState.y = CacheState.mon.y + ( CacheState.mon.h - CacheState.height ) / 2; + CacheState.x = CacheState.mon.x + ( CacheState.mon.w - CacheState.width ) / 2; // Determine window location switch ( config.location ) { case WL_NORTH_WEST: - state->x = state->mon.x; + CacheState.x = CacheState.mon.x; case WL_NORTH: - state->y = state->mon.y; + CacheState.y = CacheState.mon.y; break; case WL_NORTH_EAST: - state->y = state->mon.y; + CacheState.y = CacheState.mon.y; case WL_EAST: - state->x = state->mon.x + state->mon.w - state->w; + CacheState.x = CacheState.mon.x + CacheState.mon.w - CacheState.width; break; case WL_EAST_SOUTH: - state->x = state->mon.x + state->mon.w - state->w; + CacheState.x = CacheState.mon.x + CacheState.mon.w - CacheState.width; case WL_SOUTH: - state->y = state->mon.y + state->mon.h - state->h; + CacheState.y = CacheState.mon.y + CacheState.mon.h - CacheState.height; break; case WL_SOUTH_WEST: - state->y = state->mon.y + state->mon.h - state->h; + CacheState.y = CacheState.mon.y + CacheState.mon.h - CacheState.height; case WL_WEST: - state->x = state->mon.x; + CacheState.x = CacheState.mon.x; break; case WL_CENTER: default: break; } // Apply offset. - state->x += config.x_offset; - state->y += config.y_offset; + CacheState.x += config.x_offset; + CacheState.y += config.y_offset; } void rofi_view_queue_redraw ( void ) { if ( current_active_menu ) { current_active_menu->update = TRUE; - xcb_clear_area ( xcb->connection, current_active_menu->window, 1, 0, 0, 1, 1 ); + xcb_clear_area ( xcb->connection, CacheState.main_window, 1, 0, 0, 1, 1 ); xcb_flush ( xcb->connection ); } } @@ -235,6 +248,20 @@ RofiViewState * rofi_view_get_active ( void ) void rofi_view_set_active ( RofiViewState *state ) { + if ( current_active_menu != NULL && state != NULL ) { + g_queue_push_head ( &( CacheState.views ), state ); + printf ( "stack view.\n" ); + rofi_view_resize ( current_active_menu ); + rofi_view_queue_redraw (); + return; + } + else if ( state == NULL && !g_queue_is_empty ( &( CacheState.views ) ) ) { + printf ( "pop view\n" ); + current_active_menu = g_queue_pop_head ( &( CacheState.views ) ); + rofi_view_resize ( current_active_menu ); + rofi_view_queue_redraw (); + return; + } g_assert ( ( current_active_menu == NULL && state != NULL ) || ( current_active_menu != NULL && state == NULL ) ); current_active_menu = state; } @@ -252,7 +279,7 @@ void rofi_view_set_selected_line ( RofiViewState *state, unsigned int selected_l } state->update = TRUE; - xcb_clear_area ( xcb->connection, state->window, 1, 0, 0, 1, 1 ); + xcb_clear_area ( xcb->connection, CacheState.main_window, 1, 0, 0, 1, 1 ); xcb_flush ( xcb->connection ); } @@ -314,30 +341,30 @@ static void rofi_view_resize ( RofiViewState *state ) { if ( ( state->menu_flags & MENU_ERROR_DIALOG ) == MENU_ERROR_DIALOG ) { // Resize of error dialog. - int entrybox_width = state->w - ( 2 * ( state->border ) ); + int entrybox_width = CacheState.width - ( 2 * ( state->border ) ); textbox_moveresize ( state->text, state->text->widget.x, state->text->widget.y, entrybox_width, state->line_height ); state->rchanged = TRUE; state->update = TRUE; return; } unsigned int sbw = config.line_margin + 8; - widget_move ( WIDGET ( state->scrollbar ), state->w - state->border - sbw, state->top_offset ); + widget_move ( WIDGET ( state->scrollbar ), CacheState.width - state->border - sbw, state->top_offset ); if ( config.sidebar_mode == TRUE ) { - int width = ( state->w - ( 2 * ( state->border ) + ( state->num_modi - 1 ) * config.line_margin ) ) / state->num_modi; + int width = ( CacheState.width - ( 2 * ( state->border ) + ( state->num_modi - 1 ) * config.line_margin ) ) / state->num_modi; for ( unsigned int j = 0; j < state->num_modi; j++ ) { textbox_moveresize ( state->modi[j], - state->border + j * ( width + config.line_margin ), state->h - state->line_height - state->border, + state->border + j * ( width + config.line_margin ), CacheState.height - state->line_height - state->border, width, state->line_height ); textbox_draw ( state->modi[j], CacheState.draw ); } } - int entrybox_width = state->w - ( 2 * ( state->border ) ); + int entrybox_width = CacheState.width - ( 2 * ( state->border ) ); int offset = 0; int width = textbox_get_width ( state->case_indicator ); entrybox_width -= width + textbox_get_width ( state->prompt_tb ); offset = width; textbox_moveresize ( state->text, state->text->widget.x, state->text->widget.y, entrybox_width, state->line_height ); - widget_move ( WIDGET ( state->case_indicator ), state->w - state->border - offset, state->border ); + widget_move ( WIDGET ( state->case_indicator ), CacheState.width - state->border - offset, state->border ); /** * Resize in Height */ @@ -345,13 +372,16 @@ static void rofi_view_resize ( RofiViewState *state ) unsigned int last_length = state->max_elements; int element_height = state->line_height * config.element_height + config.line_margin; // Calculated new number of boxes. - int h = ( state->h - state->top_offset - config.padding ); + int h = ( CacheState.height - state->top_offset - config.padding ); if ( config.sidebar_mode == TRUE ) { h -= state->line_height + config.line_margin; } if ( h < 0 ) { - fprintf ( stderr, "Current padding %u (on each side) does not fit within visible window %u.\n", config.padding, state->h ); - h = ( state->h - state->top_offset - state->h / 3 ); + fprintf ( stderr, + "Current padding %u (on each side) does not fit within visible window %u.\n", + config.padding, + CacheState.height ); + h = ( CacheState.height - state->top_offset - CacheState.height / 3 ); if ( config.sidebar_mode == TRUE ) { h -= state->line_height + config.line_margin; } @@ -391,16 +421,16 @@ void rofi_view_itterrate ( RofiViewState *state, xcb_generic_event_t *event, xkb case XCB_CONFIGURE_NOTIFY: { xcb_configure_notify_event_t *xce = (xcb_configure_notify_event_t *) event; - if ( xce->window == state->window ) { - if ( state->x != xce->x || state->y != xce->y ) { - state->x = xce->x; - state->y = xce->y; + if ( xce->window == CacheState.main_window ) { + if ( CacheState.x != xce->x || CacheState.y != xce->y ) { + CacheState.x = xce->x; + CacheState.y = xce->y; state->update = TRUE; } - if ( state->w != xce->width || state->h != xce->height ) { - state->w = xce->width; - state->h = xce->height; - cairo_xcb_surface_set_size ( CacheState.surface, state->w, state->h ); + if ( CacheState.width != xce->width || CacheState.height != xce->height ) { + CacheState.width = xce->width; + CacheState.height = xce->height; + cairo_xcb_surface_set_size ( CacheState.surface, CacheState.width, CacheState.height ); rofi_view_resize ( state ); } } @@ -477,7 +507,25 @@ static void check_is_ascii ( thread_state *t, G_GNUC_UNUSED gpointer user_data ) g_mutex_unlock ( t->mutex ); } -static xcb_window_t __create_window ( MenuFlags menu_flags ) +static void rofi_view_setup_fake_transparency ( void ) +{ + if ( CacheState.fake_bg == NULL ) { + cairo_surface_t *s = cairo_xcb_surface_create ( xcb->connection, + xcb_stuff_get_root_window ( xcb ), + root_visual, + xcb->screen->width_in_pixels, + xcb->screen->height_in_pixels ); + + CacheState.fake_bg = cairo_image_surface_create ( CAIRO_FORMAT_ARGB32, CacheState.mon.w, CacheState.mon.h ); + cairo_t *dr = cairo_create ( CacheState.fake_bg ); + cairo_set_source_surface ( dr, s, -CacheState.mon.x, -CacheState.mon.y ); + cairo_paint ( dr ); + cairo_destroy ( dr ); + cairo_surface_destroy ( s ); + TICK_N ( "Fake transparency" ); + } +} +void __create_window ( MenuFlags menu_flags ) { uint32_t selmask = XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL | XCB_CW_EVENT_MASK | XCB_CW_COLORMAP; uint32_t selval[] = { @@ -546,7 +594,15 @@ static xcb_window_t __create_window ( MenuFlags menu_flags ) xcb_change_property ( xcb->connection, XCB_PROP_MODE_REPLACE, box, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, 4, "rofi" ); x11_set_window_opacity ( box, config.window_opacity ); - return box; + CacheState.main_window = box; + CacheState.flags = menu_flags; + monitor_active ( &( CacheState.mon ) ); + if ( config.fake_transparency ) { + rofi_view_setup_fake_transparency (); + } + if ( xcb->sncontext != NULL ) { + sn_launchee_context_setup_window ( xcb->sncontext, CacheState.main_window ); + } } void rofi_view_call_thread ( gpointer data, gpointer user_data ) @@ -598,20 +654,20 @@ static void rofi_view_calculate_rows_columns ( RofiViewState *state ) static void rofi_view_calculate_window_and_element_width ( RofiViewState *state ) { if ( config.fullscreen ) { - state->w = state->mon.w; + CacheState.width = CacheState.mon.w; } else if ( config.menu_width < 0 ) { double fw = textbox_get_estimated_char_width ( ); - state->w = -( fw * config.menu_width ); - state->w += 2 * state->border + 4; // 4 = 2*SIDE_MARGIN + CacheState.width = -( fw * config.menu_width ); + CacheState.width += 2 * state->border + 4; // 4 = 2*SIDE_MARGIN } else{ // Calculate as float to stop silly, big rounding down errors. - state->w = config.menu_width < 101 ? ( state->mon.w / 100.0f ) * ( float ) config.menu_width : config.menu_width; + CacheState.width = config.menu_width < 101 ? ( CacheState.mon.w / 100.0f ) * ( float ) config.menu_width : config.menu_width; } if ( state->columns > 0 ) { - state->element_width = state->w - ( 2 * ( state->border ) ); + state->element_width = CacheState.width - ( 2 * ( state->border ) ); // Divide by the # columns state->element_width = ( state->element_width - ( state->columns - 1 ) * config.line_margin ) / state->columns; } @@ -830,7 +886,7 @@ static void rofi_view_draw ( RofiViewState *state, cairo_t *d ) scrollbar_set_handle_length ( state->scrollbar, columns * state->max_rows ); scrollbar_draw ( state->scrollbar, d ); // Element width. - unsigned int element_width = state->w - ( 2 * ( state->border ) ); + unsigned int element_width = CacheState.width - ( 2 * ( state->border ) ); if ( state->scrollbar != NULL ) { element_width -= state->scrollbar->widget.w; } @@ -881,14 +937,14 @@ void rofi_view_update ( RofiViewState *state ) return; } TICK (); - cairo_surface_t * surf = cairo_image_surface_create ( CAIRO_FORMAT_ARGB32, state->w, state->h ); + cairo_surface_t * surf = cairo_image_surface_create ( CAIRO_FORMAT_ARGB32, CacheState.width, CacheState.height ); cairo_t *d = cairo_create ( surf ); cairo_set_operator ( d, CAIRO_OPERATOR_SOURCE ); if ( config.fake_transparency ) { if ( CacheState.fake_bg != NULL ) { cairo_set_source_surface ( d, CacheState.fake_bg, - -(double) ( state->x - state->mon.x ), - -(double) ( state->y - state->mon.y ) ); + -(double) ( CacheState.x - CacheState.mon.x ), + -(double) ( CacheState.y - CacheState.mon.y ) ); cairo_paint ( d ); cairo_set_operator ( d, CAIRO_OPERATOR_OVER ); color_background ( d ); @@ -909,8 +965,8 @@ void rofi_view_update ( RofiViewState *state ) cairo_rectangle ( d, config.menu_bw / 2.0, config.menu_bw / 2.0, - state->w - config.menu_bw, - state->h - config.menu_bw ); + CacheState.width - config.menu_bw, + CacheState.height - config.menu_bw ); cairo_stroke ( d ); cairo_restore ( d ); } @@ -940,17 +996,19 @@ void rofi_view_update ( RofiViewState *state ) cairo_set_dash ( d, dashes, 1, 0.0 ); } cairo_move_to ( d, state->border, state->line_height + ( state->border ) * 1 + config.line_margin + 1 ); - cairo_line_to ( d, state->w - state->border, state->line_height + ( state->border ) * 1 + config.line_margin + 1 ); + cairo_line_to ( d, CacheState.width - state->border, state->line_height + ( state->border ) * 1 + config.line_margin + 1 ); cairo_stroke ( d ); if ( state->message_tb ) { cairo_move_to ( d, state->border, state->top_offset - ( config.line_margin ) - 1 ); - cairo_line_to ( d, state->w - state->border, state->top_offset - ( config.line_margin ) - 1 ); + cairo_line_to ( d, CacheState.width - state->border, state->top_offset - ( config.line_margin ) - 1 ); cairo_stroke ( d ); } if ( config.sidebar_mode == TRUE ) { - cairo_move_to ( d, state->border, state->h - state->line_height - ( state->border ) * 1 - 1 - config.line_margin ); - cairo_line_to ( d, state->w - state->border, state->h - state->line_height - ( state->border ) * 1 - 1 - config.line_margin ); + cairo_move_to ( d, state->border, CacheState.height - state->line_height - ( state->border ) * 1 - 1 - config.line_margin ); + cairo_line_to ( d, + CacheState.width - state->border, + CacheState.height - state->line_height - ( state->border ) * 1 - 1 - config.line_margin ); cairo_stroke ( d ); } } @@ -988,7 +1046,7 @@ static void rofi_view_paste ( RofiViewState *state, xcb_selection_notify_event_t fprintf ( stderr, "Failed to convert selection\n" ); } else if ( xse->property == xcb->ewmh.UTF8_STRING ) { - gchar *text = window_get_text_prop ( state->window, xcb->ewmh.UTF8_STRING ); + gchar *text = window_get_text_prop ( CacheState.main_window, xcb->ewmh.UTF8_STRING ); if ( text != NULL && text[0] != '\0' ) { unsigned int dl = strlen ( text ); // Strip new line @@ -1240,42 +1298,25 @@ static void rofi_view_refilter ( RofiViewState *state ) * * Check if a finalize function is set, and if sets executes it. */ +void process_result ( RofiViewState *state ); void rofi_view_finalize ( RofiViewState *state ) { - if ( state && state->finalize ) { + if ( state && state->finalize != NULL ) { state->finalize ( state ); } } -void rofi_view_setup_fake_transparency ( RofiViewState *state ) -{ - if ( CacheState.fake_bg == NULL ) { - cairo_surface_t *s = cairo_xcb_surface_create ( xcb->connection, - xcb_stuff_get_root_window ( xcb ), - root_visual, - xcb->screen->width_in_pixels, - xcb->screen->height_in_pixels ); - - CacheState.fake_bg = cairo_image_surface_create ( CAIRO_FORMAT_ARGB32, state->mon.w, state->mon.h ); - cairo_t *dr = cairo_create ( CacheState.fake_bg ); - cairo_set_source_surface ( dr, s, -state->mon.x, -state->mon.y ); - cairo_paint ( dr ); - cairo_destroy ( dr ); - cairo_surface_destroy ( s ); - TICK_N ( "Fake transparency" ); - } -} static void rofi_view_mainloop_iter ( RofiViewState *state, xcb_generic_event_t *ev, xkb_stuff *xkb ) { switch ( ev->response_type & ~0x80 ) { case XCB_FOCUS_IN: - if ( ( state->menu_flags & MENU_NORMAL_WINDOW ) == 0 ) { - take_keyboard ( state->window ); + if ( ( CacheState.flags & MENU_NORMAL_WINDOW ) == 0 ) { + take_keyboard ( CacheState.main_window ); } break; case XCB_FOCUS_OUT: - if ( ( state->menu_flags & MENU_NORMAL_WINDOW ) == 0 ) { + if ( ( CacheState.flags & MENU_NORMAL_WINDOW ) == 0 ) { release_keyboard ( ); } break; @@ -1336,12 +1377,12 @@ static void rofi_view_mainloop_iter ( RofiViewState *state, xcb_generic_event_t if ( key != XKB_KEY_NoSymbol ) { // Handling of paste if ( abe_test_action ( PASTE_PRIMARY, modstate, key ) ) { - xcb_convert_selection ( xcb->connection, state->window, XCB_ATOM_PRIMARY, + xcb_convert_selection ( xcb->connection, CacheState.main_window, XCB_ATOM_PRIMARY, xcb->ewmh.UTF8_STRING, xcb->ewmh.UTF8_STRING, XCB_CURRENT_TIME ); xcb_flush ( xcb->connection ); } else if ( abe_test_action ( PASTE_SECONDARY, modstate, key ) ) { - xcb_convert_selection ( xcb->connection, state->window, XCB_ATOM_SECONDARY, + xcb_convert_selection ( xcb->connection, CacheState.main_window, XCB_ATOM_SECONDARY, xcb->ewmh.UTF8_STRING, xcb->ewmh.UTF8_STRING, XCB_CURRENT_TIME ); xcb_flush ( xcb->connection ); } @@ -1451,7 +1492,7 @@ RofiViewState *rofi_view_create ( Mode *sw, char *prompt, const char *message, MenuFlags menu_flags, - void ( *finalize )( RofiViewState *state ) ) + void ( *finalize )( RofiViewState * ) ) { TICK (); RofiViewState *state = __rofi_view_state_create (); @@ -1475,14 +1516,6 @@ RofiViewState *rofi_view_create ( Mode *sw, state->num_lines = mode_get_num_entries ( sw ); state->lines_not_ascii = g_malloc0_n ( state->num_lines, sizeof ( int ) ); - // main window isn't explicitly destroyed in case we switch modes. Reusing it prevents flicker - if ( CacheState.main_window == XCB_WINDOW_NONE ) { - CacheState.main_window = __create_window ( menu_flags ); - if ( xcb->sncontext != NULL ) { - sn_launchee_context_setup_window ( xcb->sncontext, state->window ); - } - } - state->window = CacheState.main_window; // find out which lines contain non-ascii codepoints, so we can be faster in some cases. if ( state->num_lines > 0 ) { TICK_N ( "Is ASCII start" ); @@ -1525,7 +1558,7 @@ RofiViewState *rofi_view_create ( Mode *sw, // 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 ( ( menu_flags & MENU_NORMAL_WINDOW ) == 0 ) { + if ( ( CacheState.flags & MENU_NORMAL_WINDOW ) == 0 ) { int has_keyboard = take_keyboard ( xcb_stuff_get_root_window ( xcb ) ); if ( !has_keyboard ) { @@ -1537,11 +1570,7 @@ RofiViewState *rofi_view_create ( Mode *sw, } TICK_N ( "Grab keyboard" ); // Get active monitor size. - monitor_active ( &( state->mon ) ); TICK_N ( "Get active monitor" ); - if ( config.fake_transparency ) { - rofi_view_setup_fake_transparency ( state ); - } // we need this at this point so we can get height. state->line_height = textbox_get_estimated_char_height (); @@ -1552,7 +1581,7 @@ RofiViewState *rofi_view_create ( Mode *sw, // Height of a row. if ( config.menu_lines == 0 || config.fullscreen ) { // Autosize it. - int h = state->mon.h - state->top_offset - config.padding; + int h = CacheState.mon.h - state->top_offset - config.padding; if ( config.sidebar_mode == TRUE ) { h -= state->line_height + config.line_margin; } @@ -1569,7 +1598,7 @@ RofiViewState *rofi_view_create ( Mode *sw, state->prompt_tb = textbox_create ( TB_AUTOWIDTH, ( state->border ), ( state->border ), 0, state->line_height, NORMAL, prompt ); // Entry box - int entrybox_width = state->w - ( 2 * ( state->border ) ) - textbox_get_width ( state->prompt_tb ) + int entrybox_width = CacheState.width - ( 2 * ( state->border ) ) - textbox_get_width ( state->prompt_tb ) - textbox_get_width ( state->case_indicator ); TextboxFlags tfl = TB_EDITABLE; tfl |= ( ( menu_flags & MENU_PASSWORD ) == MENU_PASSWORD ) ? TB_PASSWORD : 0; @@ -1585,7 +1614,7 @@ RofiViewState *rofi_view_create ( Mode *sw, state->message_tb = NULL; if ( message ) { state->message_tb = textbox_create ( TB_AUTOHEIGHT | TB_MARKUP | TB_WRAP, - ( state->border ), state->top_offset, state->w - ( 2 * ( state->border ) ), + ( state->border ), state->top_offset, CacheState.width - ( 2 * ( state->border ) ), -1, NORMAL, message ); state->top_offset += textbox_get_height ( state->message_tb ); state->top_offset += config.line_margin * 2 + 2; @@ -1603,7 +1632,7 @@ RofiViewState *rofi_view_create ( Mode *sw, } if ( !config.hide_scrollbar ) { unsigned int sbw = config.line_margin + config.scrollbar_width; - state->scrollbar = scrollbar_create ( state->w - state->border - sbw, state->top_offset, + state->scrollbar = scrollbar_create ( CacheState.width - state->border - sbw, state->top_offset, sbw, ( state->max_rows - 1 ) * ( element_height + config.line_margin ) + element_height ); } @@ -1614,39 +1643,39 @@ RofiViewState *rofi_view_create ( Mode *sw, // resize window vertically to suit // Subtract the margin of the last row. - state->h = state->top_offset + ( element_height + config.line_margin ) * ( state->max_rows ) - config.line_margin; - state->h += state->border; - state->h += 0; + CacheState.height = state->top_offset + ( element_height + config.line_margin ) * ( state->max_rows ) - config.line_margin; + CacheState.height += state->border; + CacheState.height += 0; // Add entry if ( config.sidebar_mode == TRUE ) { - state->h += state->line_height + 2 * config.line_margin + 2; + CacheState.height += state->line_height + 2 * config.line_margin + 2; } // Sidebar or fullscreen mode. if ( config.menu_lines == 0 || config.fullscreen ) { - state->h = state->mon.h; + CacheState.height = CacheState.mon.h; } // Move the window to the correct x,y position. - calculate_window_position ( state ); + calculate_window_position ( ); if ( config.sidebar_mode == TRUE ) { state->num_modi = rofi_get_num_enabled_modi (); - int width = ( state->w - ( 2 * ( state->border ) + ( state->num_modi - 1 ) * config.line_margin ) ) / state->num_modi; + int width = ( CacheState.width - ( 2 * ( state->border ) + ( state->num_modi - 1 ) * config.line_margin ) ) / state->num_modi; state->modi = g_malloc0 ( state->num_modi * sizeof ( textbox * ) ); for ( unsigned int j = 0; j < state->num_modi; j++ ) { const Mode * mode = rofi_get_mode ( j ); state->modi[j] = textbox_create ( TB_CENTER, state->border + j * ( width + config.line_margin ), - state->h - state->line_height - state->border, width, state->line_height, + CacheState.height - state->line_height - state->border, width, state->line_height, ( mode == state->sw ) ? HIGHLIGHT : NORMAL, mode_get_name ( mode ) ); } } uint16_t mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT; - uint32_t vals[] = { state->x, state->y, state->w, state->h }; + uint32_t vals[] = { CacheState.x, CacheState.y, CacheState.width, CacheState.height }; // Display it. - xcb_configure_window ( xcb->connection, state->window, mask, vals ); - cairo_xcb_surface_set_size ( CacheState.surface, state->w, state->h ); + xcb_configure_window ( xcb->connection, CacheState.main_window, mask, vals ); + cairo_xcb_surface_set_size ( CacheState.surface, CacheState.width, CacheState.height ); // if grabbing keyboard failed, fall through state->selected = 0; @@ -1656,11 +1685,12 @@ RofiViewState *rofi_view_create ( Mode *sw, rofi_view_refilter ( state ); rofi_view_update ( state ); - xcb_map_window ( xcb->connection, state->window ); + xcb_map_window ( xcb->connection, CacheState.main_window ); xcb_flush ( xcb->connection ); if ( xcb->sncontext != NULL ) { sn_launchee_context_complete ( xcb->sncontext ); } + // TODO move resize window into the 'active window' part. return state; } static void __error_dialog_event_loop ( RofiViewState *state, xcb_generic_event_t *ev, G_GNUC_UNUSED xkb_stuff *xkb ) @@ -1674,7 +1704,6 @@ static void __error_dialog_event_loop ( RofiViewState *state, xcb_generic_event_ } rofi_view_update ( state ); } -void process_result_error ( RofiViewState *state ); int rofi_view_error_dialog ( const char *msg, int markup ) { RofiViewState *state = __rofi_view_state_create (); @@ -1682,27 +1711,18 @@ int rofi_view_error_dialog ( const char *msg, int markup ) state->update = TRUE; state->border = config.padding + config.menu_bw; state->x11_event_loop = __error_dialog_event_loop; - state->finalize = process_result_error; state->menu_flags = MENU_ERROR_DIALOG; - - // Get active monitor size. - monitor_active ( &( state->mon ) ); - if ( config.fake_transparency ) { - rofi_view_setup_fake_transparency ( state ); - } - // main window isn't explicitly destroyed in case we switch modes. Reusing it prevents flicker - if ( CacheState.main_window == XCB_WINDOW_NONE ) { - CacheState.main_window = __create_window ( MENU_NORMAL ); - } - state->window = CacheState.main_window; + state->finalize = process_result; // 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. - int has_keyboard = take_keyboard ( xcb_stuff_get_root_window ( xcb ) ); - if ( !has_keyboard ) { - fprintf ( stderr, "Failed to grab keyboard, even after %d uS.", 500 * 1000 ); - return FALSE; + if ( ( CacheState.flags & MENU_NORMAL_WINDOW ) == 0 ) { + int has_keyboard = take_keyboard ( xcb_stuff_get_root_window ( xcb ) ); + if ( !has_keyboard ) { + fprintf ( stderr, "Failed to grab keyboard, even after %d uS.", 500 * 1000 ); + return FALSE; + } } rofi_view_calculate_window_and_element_width ( state ); @@ -1710,24 +1730,23 @@ int rofi_view_error_dialog ( const char *msg, int markup ) state->text = textbox_create ( ( TB_AUTOHEIGHT | TB_WRAP ) + ( ( markup ) ? TB_MARKUP : 0 ), ( state->border ), ( state->border ), - ( state->w - ( 2 * ( state->border ) ) ), 1, NORMAL, ( msg != NULL ) ? msg : "" ); + ( CacheState.width - ( 2 * ( state->border ) ) ), 1, NORMAL, ( msg != NULL ) ? msg : "" ); state->line_height = textbox_get_height ( state->text ); // resize window vertically to suit - state->h = state->line_height + ( state->border ) * 2; + CacheState.height = state->line_height + ( state->border ) * 2; // Calculte window position. - calculate_window_position ( state ); + calculate_window_position ( ); // Move the window to the correct x,y position. uint16_t mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT; - uint32_t vals[] = { state->x, state->y, state->w, state->h }; + uint32_t vals[] = { CacheState.x, CacheState.y, CacheState.width, CacheState.height }; - xcb_configure_window ( xcb->connection, state->window, mask, vals ); - calculate_window_position ( state ); - cairo_xcb_surface_set_size ( CacheState.surface, state->w, state->h ); + xcb_configure_window ( xcb->connection, CacheState.main_window, mask, vals ); + cairo_xcb_surface_set_size ( CacheState.surface, CacheState.width, CacheState.height ); // Display it. - xcb_map_window ( xcb->connection, state->window ); + xcb_map_window ( xcb->connection, CacheState.main_window ); if ( xcb->sncontext != NULL ) { sn_launchee_context_complete ( xcb->sncontext ); @@ -1735,6 +1754,7 @@ int rofi_view_error_dialog ( const char *msg, int markup ) // Set it has current window. rofi_view_set_active ( state ); + // TODO move resize window into the 'active window' part. return TRUE; } @@ -1761,6 +1781,7 @@ void rofi_view_cleanup () xcb_free_colormap ( xcb->connection, map ); map = XCB_COLORMAP_NONE; } + g_assert ( g_queue_is_empty ( &( CacheState.views ) ) ); } void rofi_view_workers_initialize ( void ) { @@ -1784,7 +1805,6 @@ void rofi_view_workers_initialize ( void ) // If error occured during setup of pool, tell user and exit. if ( error != NULL ) { char *msg = g_strdup_printf ( "Failed to setup thread pool: '%s'", error->message ); - show_error_message ( msg, FALSE ); g_free ( msg ); g_error_free ( error ); exit ( EXIT_FAILURE ); diff --git a/source/x11-helper.c b/source/x11-helper.c index f56122ab..09306deb 100644 --- a/source/x11-helper.c +++ b/source/x11-helper.c @@ -474,7 +474,7 @@ gboolean x11_parse_key ( char *combo, unsigned int *mod, xkb_keysym_t *key ) } } if ( str->len > 0 ) { - show_error_message ( str->str, TRUE ); + rofi_view_error_dialog ( str->str, TRUE ); g_string_free ( str, TRUE ); return FALSE; }