diff --git a/Makefile.am b/Makefile.am index a0a94446..0d54cb79 100644 --- a/Makefile.am +++ b/Makefile.am @@ -32,6 +32,7 @@ AM_CFLAGS=\ rofi_SOURCES=\ source/rofi.c\ + source/view.c\ source/mode.c\ source/keyb.c\ config/config.c\ @@ -57,6 +58,7 @@ rofi_SOURCES=\ include/mode-private.h\ include/settings.h\ include/keyb.h\ + include/view.h\ include/helper.h\ include/timings.h\ include/history.h\ diff --git a/include/rofi.h b/include/rofi.h index 60699674..d6bab116 100644 --- a/include/rofi.h +++ b/include/rofi.h @@ -17,7 +17,7 @@ * Pointer to xdg cache directory. */ extern const char *cache_dir; -typedef struct MenuState MenuState; +typedef struct RofiViewState RofiViewState; /** * @param msg The error message to show. @@ -50,9 +50,9 @@ typedef enum * * @returns The command issued (see MenuReturn) */ -MenuState *menu ( Mode *sw, - char *input, char *prompt, - const char *message, MenuFlags flags ) +RofiViewState *rofi_view_create ( Mode *sw, + char *input, char *prompt, + const char *message, MenuFlags flags ) __attribute__ ( ( nonnull ( 1, 2, 3 ) ) ); /** Reset terminal */ @@ -84,16 +84,16 @@ int show_error_message ( const char *msg, int markup ); " https://github.com/DaveDavenport/rofi/" #define ERROR_MSG_MARKUP TRUE -MenuReturn menu_state_get_return_value ( const MenuState *state ); -unsigned int menu_state_get_selected_line ( const MenuState *state ); -unsigned int menu_state_get_next_position ( const MenuState *state ); -void menu_state_itterrate ( MenuState *state, XEvent *event ); -unsigned int menu_state_get_completed ( const MenuState *state ); -const char * menu_state_get_user_input ( const MenuState *state ); -void menu_state_free ( MenuState *state ); -void menu_state_restart ( MenuState *state ); -void menu_state_set_selected_line ( MenuState *state, unsigned int selected_line ); -void menu_state_queue_redraw ( void ); -void menu_state_set_active ( MenuState *state ); +MenuReturn rofi_view_get_return_value ( const RofiViewState *state ); +unsigned int rofi_view_get_selected_line ( const RofiViewState *state ); +unsigned int rofi_view_get_next_position ( const RofiViewState *state ); +void rofi_view_itterrate ( RofiViewState *state, XEvent *event ); +unsigned int rofi_view_get_completed ( const RofiViewState *state ); +const char * rofi_view_get_user_input ( const RofiViewState *state ); +void rofi_view_free ( RofiViewState *state ); +void rofi_view_restart ( RofiViewState *state ); +void rofi_view_set_selected_line ( RofiViewState *state, unsigned int selected_line ); +void rofi_view_queue_redraw ( void ); +void rofi_view_set_active ( RofiViewState *state ); /*@}*/ #endif diff --git a/include/textbox.h b/include/textbox.h index 757b1c62..c321eb47 100644 --- a/include/textbox.h +++ b/include/textbox.h @@ -42,15 +42,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.h b/include/view.h new file mode 100644 index 00000000..8c7d02bc --- /dev/null +++ b/include/view.h @@ -0,0 +1,69 @@ + +// State of the menu. + +typedef struct RofiViewState +{ + Mode *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; + + // Update/Refilter list. + 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; + + unsigned int num_lines; + + // Selected element. + unsigned int selected; + unsigned int filtered_lines; + // Last offset in paginating. + unsigned int last_offset; + + KeySym prev_key; + Time last_button_press; + + int quit; + int skip_absorb; + // Return state + unsigned int selected_line; + MenuReturn retv; + int *lines_not_ascii; + int line_height; + unsigned int border; + workarea mon; + + ssize_t num_modi; + textbox **modi; + // Handlers. + void ( *x11_event_loop )( struct RofiViewState *state, XEvent *ev ); + void ( *finalize )( struct RofiViewState *state ); +}RofiViewState; + +/** + * @param state The Menu Handle + * + * Check if a finalize function is set, and if sets executes it. + */ +void rofi_view_finalize ( RofiViewState *state ); + +RofiViewState * rofi_view_state_create ( void ); diff --git a/source/dialogs/dmenu.c b/source/dialogs/dmenu.c index 04f54f7b..c2f5f60f 100644 --- a/source/dialogs/dmenu.c +++ b/source/dialogs/dmenu.c @@ -398,27 +398,27 @@ int dmenu_switcher_dialog ( void ) return TRUE; } - MenuState *state = menu ( &dmenu_mode, input, pd->prompt, pd->message, menu_flags ); - menu_state_set_selected_line ( state, pd->selected_line ); + RofiViewState *state = rofi_view_create ( &dmenu_mode, input, pd->prompt, pd->message, menu_flags ); + rofi_view_set_selected_line ( state, pd->selected_line ); while ( XPending ( display ) ) { XEvent ev; XNextEvent ( display, &ev ); - menu_state_itterrate ( state, &ev ); + rofi_view_itterrate ( state, &ev ); } do { retv = FALSE; - menu_state_set_active ( state ); + rofi_view_set_active ( state ); // Enter main loop. - while ( !menu_state_get_completed ( state ) ) { + while ( !rofi_view_get_completed ( state ) ) { g_main_context_iteration ( NULL, TRUE ); } - menu_state_set_active ( NULL ); + rofi_view_set_active ( NULL ); g_free ( input ); - input = g_strdup ( menu_state_get_user_input ( state ) ); - pd->selected_line = menu_state_get_selected_line ( state );; - MenuReturn mretv = menu_state_get_return_value ( state ); - unsigned int next_pos = menu_state_get_next_position ( state ); + input = g_strdup ( rofi_view_get_user_input ( state ) ); + pd->selected_line = rofi_view_get_selected_line ( state );; + MenuReturn mretv = rofi_view_get_return_value ( state ); + unsigned int next_pos = rofi_view_get_next_position ( state ); // Special behavior. // TODO clean this up! @@ -498,12 +498,12 @@ int dmenu_switcher_dialog ( void ) retv = 10 + ( mretv & MENU_LOWER_MASK ); } if ( restart ) { - menu_state_restart ( state ); - menu_state_set_selected_line ( state, pd->selected_line ); + rofi_view_restart ( state ); + rofi_view_set_selected_line ( state, pd->selected_line ); } } while ( restart ); - menu_state_free ( state ); + rofi_view_free ( state ); g_free ( input ); mode_destroy ( &dmenu_mode ); return retv; diff --git a/source/rofi.c b/source/rofi.c index 9d33af19..b94c60da 100644 --- a/source/rofi.c +++ b/source/rofi.c @@ -107,9 +107,9 @@ GThreadPool *tpool = NULL; GMainLoop *main_loop = NULL; GSource *main_loop_source = NULL; gboolean quiet = FALSE; -MenuState *current_active_menu = NULL; +RofiViewState *current_active_menu = NULL; -static void process_result ( MenuState *state ); +static void process_result ( RofiViewState *state ); static char * get_matching_state ( void ) { if ( config.case_sensitive ) { @@ -158,186 +158,7 @@ static int lev_sort ( const void *p1, const void *p2, void *arg ) return distances[*a] - distances[*b]; } -// State of the menu. - -typedef struct MenuState -{ - Mode *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; - - // Update/Refilter list. - 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; - - unsigned int num_lines; - - // Selected element. - unsigned int selected; - unsigned int filtered_lines; - // Last offset in paginating. - unsigned int last_offset; - - KeySym prev_key; - Time last_button_press; - - int quit; - int skip_absorb; - // Return state - unsigned int selected_line; - MenuReturn retv; - int *lines_not_ascii; - int line_height; - unsigned int border; - workarea mon; - // Handlers. - void ( *x11_event_loop )( struct MenuState *state, XEvent *ev ); - void ( *finalize )( struct MenuState *state ); -}MenuState; - -/** - * @param state The Menu Handle - * - * Check if a finalize function is set, and if sets executes it. - */ -static void menu_state_finalize ( MenuState *state ) -{ - if ( state && state->finalize ) { - state->finalize ( state ); - } -} - -void menu_state_queue_redraw ( void ) -{ - if ( current_active_menu ) { - current_active_menu->update = TRUE; - XClearArea ( display, main_window, 0, 0, 1, 1, True ); - XFlush ( display ); - } -} - -/** - * Create a new, 0 initialized MenuState structure. - * - * @returns a new 0 initialized MenuState - */ -static MenuState *menu_state_create ( void ) -{ - return g_malloc0 ( sizeof ( MenuState ) ); -} -void menu_state_restart ( MenuState *state ) -{ - state->quit = FALSE; - state->retv = MENU_CANCEL; -} -void menu_state_set_active ( MenuState *state ) -{ - g_assert ( ( current_active_menu == NULL && state != NULL ) || ( current_active_menu != NULL && state == NULL ) ); - current_active_menu = state; -} - -void menu_state_set_selected_line ( MenuState *state, unsigned int selected_line ) -{ - state->selected_line = selected_line; - // Find the line. - state->selected = 0; - for ( unsigned int i = 0; ( ( state->selected_line ) ) < UINT32_MAX && !state->selected && i < state->filtered_lines; i++ ) { - if ( state->line_map[i] == ( state->selected_line ) ) { - state->selected = i; - break; - } - } - - state->update = TRUE; -} - -void menu_state_free ( MenuState *state ) -{ - // Do this here? - // Wait for final release? - if ( !state->skip_absorb ) { - XEvent ev; - do { - XNextEvent ( display, &ev ); - } while ( ev.type != KeyRelease ); - } - textbox_free ( state->text ); - textbox_free ( state->prompt_tb ); - textbox_free ( state->case_indicator ); - scrollbar_free ( state->scrollbar ); - - for ( unsigned int i = 0; i < state->max_elements; i++ ) { - textbox_free ( state->boxes[i] ); - } - - g_free ( state->boxes ); - g_free ( state->line_map ); - g_free ( state->distance ); - g_free ( state->lines_not_ascii ); - g_free ( state ); - // Free the switcher boxes. - // When state is free'ed we should no longer need these. - if ( config.sidebar_mode == TRUE ) { - for ( unsigned int j = 0; j < num_modi; j++ ) { - textbox_free ( modi[j].tb ); - modi[j].tb = NULL; - } - } -} - -MenuReturn menu_state_get_return_value ( const MenuState *state ) -{ - return state->retv; -} -unsigned int menu_state_get_selected_line ( const MenuState *state ) -{ - return state->selected_line; -} - -unsigned int menu_state_get_next_position ( const MenuState *state ) -{ - unsigned int next_pos = state->selected_line; - if ( ( state->selected + 1 ) < state->num_lines ) { - ( next_pos ) = state->line_map[state->selected + 1]; - } - return next_pos; -} - -unsigned int menu_state_get_completed ( const MenuState *state ) -{ - return state->quit; -} -void menu_state_itterrate ( MenuState *state, XEvent *event ) -{ - state->x11_event_loop ( state, event ); -} -const char * menu_state_get_user_input ( const MenuState *state ) -{ - if ( state->text ) { - return state->text->text; - } - return NULL; -} +#include "view.h" static Window create_window ( Display *display ) { @@ -415,7 +236,7 @@ static Window create_window ( Display *display ) * * Calculates the window poslition */ -static void calculate_window_position ( MenuState *state ) +static void calculate_window_position ( RofiViewState *state ) { // Default location is center. state->y = state->mon.y + ( state->mon.h - state->h ) / 2; @@ -458,7 +279,7 @@ static void calculate_window_position ( MenuState *state ) * Calculate the number of rows, columns and elements to display based on the * configuration and available data. */ -static void menu_calculate_rows_columns ( MenuState *state ) +static void menu_calculate_rows_columns ( RofiViewState *state ) { state->columns = config.menu_columns; state->max_elements = MIN ( state->menu_lines * state->columns, state->num_lines ); @@ -493,7 +314,7 @@ static void menu_calculate_rows_columns ( MenuState *state ) * * Calculate the width of the window and the width of an element. */ -static void menu_calculate_window_and_element_width ( MenuState *state, workarea *mon ) +static void menu_calculate_window_and_element_width ( RofiViewState *state, workarea *mon ) { if ( config.menu_width < 0 ) { double fw = textbox_get_estimated_char_width ( ); @@ -516,13 +337,13 @@ static void menu_calculate_window_and_element_width ( MenuState *state, workarea * Nav helper functions, to avoid duplicate code. */ /** - * @param state The current MenuState + * @param state The current RofiViewState * * Move the selection one page down. * - No wrap around. * - Clip at top/bottom */ -inline static void menu_nav_page_next ( MenuState *state ) +inline static void menu_nav_page_next ( RofiViewState *state ) { // If no lines, do nothing. if ( state->filtered_lines == 0 ) { @@ -535,13 +356,13 @@ inline static void menu_nav_page_next ( MenuState *state ) state->update = TRUE; } /** - * @param state The current MenuState + * @param state The current RofiViewState * * Move the selection one page up. * - No wrap around. * - Clip at top/bottom */ -inline static void menu_nav_page_prev ( MenuState * state ) +inline static void menu_nav_page_prev ( RofiViewState * state ) { if ( state->selected < state->max_elements ) { state->selected = 0; @@ -552,13 +373,13 @@ inline static void menu_nav_page_prev ( MenuState * state ) state->update = TRUE; } /** - * @param state The current MenuState + * @param state The current RofiViewState * * Move the selection one column to the right. * - No wrap around. * - Do not move to top row when at start. */ -inline static void menu_nav_right ( MenuState *state ) +inline static void menu_nav_right ( RofiViewState *state ) { // If no lines, do nothing. if ( state->filtered_lines == 0 ) { @@ -583,12 +404,12 @@ inline static void menu_nav_right ( MenuState *state ) } } /** - * @param state The current MenuState + * @param state The current RofiViewState * * Move the selection one column to the left. * - No wrap around. */ -inline static void menu_nav_left ( MenuState *state ) +inline static void menu_nav_left ( RofiViewState *state ) { if ( state->selected >= state->max_rows ) { state->selected -= state->max_rows; @@ -596,12 +417,12 @@ inline static void menu_nav_left ( MenuState *state ) } } /** - * @param state The current MenuState + * @param state The current RofiViewState * * Move the selection one row up. * - Wrap around. */ -inline static void menu_nav_up ( MenuState *state ) +inline static void menu_nav_up ( RofiViewState *state ) { // Wrap around. if ( state->selected == 0 ) { @@ -614,12 +435,12 @@ inline static void menu_nav_up ( MenuState *state ) state->update = TRUE; } /** - * @param state The current MenuState + * @param state The current RofiViewState * * Move the selection one row down. * - Wrap around. */ -inline static void menu_nav_down ( MenuState *state ) +inline static void menu_nav_down ( RofiViewState *state ) { // If no lines, do nothing. if ( state->filtered_lines == 0 ) { @@ -629,21 +450,21 @@ inline static void menu_nav_down ( MenuState *state ) state->update = TRUE; } /** - * @param state The current MenuState + * @param state The current RofiViewState * * Move the selection to first row. */ -inline static void menu_nav_first ( MenuState * state ) +inline static void menu_nav_first ( RofiViewState * state ) { state->selected = 0; state->update = TRUE; } /** - * @param state The current MenuState + * @param state The current RofiViewState * * Move the selection to last row. */ -inline static void menu_nav_last ( MenuState * state ) +inline static void menu_nav_last ( RofiViewState * state ) { // If no lines, do nothing. if ( state->filtered_lines == 0 ) { @@ -733,7 +554,7 @@ static void menu_capture_screenshot ( void ) * * Keyboard navigation through the elements. */ -static int menu_keyboard_navigation ( MenuState *state, KeySym key, unsigned int modstate ) +static int menu_keyboard_navigation ( RofiViewState *state, KeySym key, unsigned int modstate ) { // pressing one of the global key bindings closes the switcher. This allows fast closing of the // menu if an item is not selected @@ -811,7 +632,7 @@ static int menu_keyboard_navigation ( MenuState *state, KeySym key, unsigned int return 0; } -static void menu_mouse_navigation ( MenuState *state, XButtonEvent *xbe ) +static void menu_mouse_navigation ( RofiViewState *state, XButtonEvent *xbe ) { // Scroll event if ( xbe->button > 3 ) { @@ -836,7 +657,7 @@ static void menu_mouse_navigation ( MenuState *state, XButtonEvent *xbe ) return; } for ( unsigned int i = 0; config.sidebar_mode == TRUE && i < num_modi; i++ ) { - if ( widget_intersect ( &( modi[i].tb->widget ), xbe->x, xbe->y ) ) { + if ( widget_intersect ( &( state->modi[i]->widget ), xbe->x, xbe->y ) ) { ( state->selected_line ) = 0; state->retv = MENU_QUICK_SWITCH | ( i & MENU_LOWER_MASK ); state->quit = TRUE; @@ -869,14 +690,14 @@ static void menu_mouse_navigation ( MenuState *state, XButtonEvent *xbe ) typedef struct _thread_state { - MenuState *state; - char **tokens; - unsigned int start; - unsigned int stop; - unsigned int count; - GCond *cond; - GMutex *mutex; - unsigned int *acount; + RofiViewState *state; + char **tokens; + unsigned int start; + unsigned int stop; + unsigned int count; + GCond *cond; + GMutex *mutex; + unsigned int *acount; void ( *callback )( struct _thread_state *t, gpointer data ); }thread_state; @@ -924,7 +745,7 @@ static void call_thread ( gpointer data, gpointer user_data ) t->callback ( t, user_data ); } -static void menu_refilter ( MenuState *state ) +static void menu_refilter ( RofiViewState *state ) { TICK_N ( "Filter start" ); if ( strlen ( state->text->text ) > 0 ) { @@ -1010,7 +831,7 @@ static void menu_refilter ( MenuState *state ) TICK_N ( "Filter done" ); } -static void menu_draw ( MenuState *state, cairo_t *d ) +static void menu_draw ( RofiViewState *state, cairo_t *d ) { unsigned int i, offset = 0; // selected row is always visible. @@ -1089,7 +910,7 @@ static void menu_draw ( MenuState *state, cairo_t *d ) } } -static void menu_update ( MenuState *state ) +static void menu_update ( RofiViewState *state ) { TICK (); cairo_surface_t * surf = cairo_image_surface_create ( get_format (), state->w, state->h ); @@ -1167,8 +988,8 @@ static void menu_update ( MenuState *state ) } if ( config.sidebar_mode == TRUE ) { for ( unsigned int j = 0; j < num_modi; j++ ) { - if ( modi[j].tb != NULL ) { - textbox_draw ( modi[j].tb, d ); + if ( state->modi[j] != NULL ) { + textbox_draw ( state->modi[j], d ); } } } @@ -1192,7 +1013,7 @@ static void menu_update ( MenuState *state ) * * Handle paste event. */ -static void menu_paste ( MenuState *state, XSelectionEvent *xse ) +static void menu_paste ( RofiViewState *state, XSelectionEvent *xse ) { if ( xse->property == netatoms[UTF8_STRING] ) { gchar *text = window_get_text_prop ( display, main_window, netatoms[UTF8_STRING] ); @@ -1214,17 +1035,17 @@ static void menu_paste ( MenuState *state, XSelectionEvent *xse ) } } -static void menu_resize ( MenuState *state ) +static void menu_resize ( RofiViewState *state ) { unsigned int sbw = config.line_margin + 8; widget_move ( WIDGET ( state->scrollbar ), state->w - state->border - sbw, state->top_offset ); if ( config.sidebar_mode == TRUE ) { int width = ( state->w - ( 2 * ( state->border ) + ( num_modi - 1 ) * config.line_margin ) ) / num_modi; for ( unsigned int j = 0; j < num_modi; j++ ) { - textbox_moveresize ( modi[j].tb, + textbox_moveresize ( state->modi[j], state->border + j * ( width + config.line_margin ), state->h - state->line_height - state->border, width, state->line_height ); - textbox_draw ( modi[j].tb, draw ); + textbox_draw ( state->modi[j], draw ); } } int entrybox_width = state->w - ( 2 * ( state->border ) ) - textbox_get_width ( state->prompt_tb ) @@ -1276,7 +1097,7 @@ static void menu_resize ( MenuState *state ) state->update = TRUE; } -static void menu_setup_fake_transparency ( Display *display, MenuState *state ) +static void menu_setup_fake_transparency ( Display *display, RofiViewState *state ) { if ( fake_bg == NULL ) { Window root = DefaultRootWindow ( display ); @@ -1296,7 +1117,7 @@ static void menu_setup_fake_transparency ( Display *display, MenuState *state ) TICK_N ( "Fake transparency" ); } } -static void menu_mainloop_iter ( MenuState *state, XEvent *ev ) +static void menu_mainloop_iter ( RofiViewState *state, XEvent *ev ) { if ( sndisplay != NULL ) { sn_display_process_event ( sndisplay, ev ); @@ -1491,14 +1312,14 @@ static void menu_mainloop_iter ( MenuState *state, XEvent *ev ) } } -MenuState *menu ( Mode *sw, - char *input, - char *prompt, - const char *message, - MenuFlags menu_flags ) +RofiViewState *rofi_view_create ( Mode *sw, + char *input, + char *prompt, + const char *message, + MenuFlags menu_flags ) { TICK (); - MenuState *state = menu_state_create (); + RofiViewState *state = rofi_view_state_create (); state->sw = sw; state->selected_line = UINT32_MAX; state->retv = MENU_CANCEL; @@ -1563,7 +1384,7 @@ MenuState *menu ( Mode *sw, if ( !has_keyboard ) { fprintf ( stderr, "Failed to grab keyboard, even after %d uS.", 500 * 1000 ); // Break off. - menu_state_free ( state ); + rofi_view_free ( state ); return NULL; } TICK_N ( "Grab keyboard" ); @@ -1673,10 +1494,11 @@ MenuState *menu ( Mode *sw, if ( config.sidebar_mode == TRUE ) { int width = ( state->w - ( 2 * ( state->border ) + ( num_modi - 1 ) * config.line_margin ) ) / num_modi; + state->modi = g_malloc0 ( num_modi * sizeof ( textbox * ) ); for ( unsigned int j = 0; j < num_modi; j++ ) { - modi[j].tb = textbox_create ( TB_CENTER, state->border + j * ( width + config.line_margin ), - state->h - state->line_height - state->border, width, state->line_height, - ( j == curr_switcher ) ? HIGHLIGHT : NORMAL, mode_get_name ( modi[j].sw ) ); + 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, + ( j == curr_switcher ) ? HIGHLIGHT : NORMAL, mode_get_name ( modi[j].sw ) ); } } @@ -1700,7 +1522,7 @@ MenuState *menu ( Mode *sw, return state; } -static void error_dialog_event_loop ( MenuState *state, XEvent *ev ) +static void error_dialog_event_loop ( RofiViewState *state, XEvent *ev ) { // Wait for event. if ( sndisplay != NULL ) { @@ -1726,7 +1548,7 @@ static void error_dialog_event_loop ( MenuState *state, XEvent *ev ) } void error_dialog ( const char *msg, int markup ) { - MenuState *state = menu_state_create (); + RofiViewState *state = rofi_view_state_create (); state->retv = MENU_CANCEL; state->update = TRUE; state->border = config.padding + config.menu_bw; @@ -1774,13 +1596,12 @@ void error_dialog ( const char *msg, int markup ) if ( sncontext != NULL ) { sn_launchee_context_complete ( sncontext ); } - menu_state_set_active ( state ); - while ( !menu_state_get_completed ( state ) ) { + rofi_view_set_active ( state ); + while ( !rofi_view_get_completed ( state ) ) { g_main_context_iteration ( NULL, TRUE ); } - menu_state_set_active ( NULL ); - menu_state_free ( state ); - release_keyboard ( display ); + rofi_view_set_active ( NULL ); + rofi_view_free ( state ); } /** @@ -1868,21 +1689,21 @@ static void run_switcher ( ModeMode mode ) return; } } - char *input = g_strdup ( config.filter ); - char *prompt = g_strdup_printf ( "%s:", mode_get_name ( modi[mode].sw ) ); + char *input = g_strdup ( config.filter ); + char *prompt = g_strdup_printf ( "%s:", mode_get_name ( modi[mode].sw ) ); curr_switcher = mode; - MenuState * state = menu ( modi[mode].sw, input, prompt, NULL, MENU_NORMAL ); + RofiViewState * state = rofi_view_create ( modi[mode].sw, input, prompt, NULL, MENU_NORMAL ); state->finalize = process_result; - menu_state_set_active ( state ); + rofi_view_set_active ( state ); g_free ( prompt ); } -static void process_result ( MenuState *state ) +static void process_result ( RofiViewState *state ) { - unsigned int selected_line = menu_state_get_selected_line ( state );; - MenuReturn mretv = menu_state_get_return_value ( state ); - char *input = g_strdup ( menu_state_get_user_input ( state ) ); - menu_state_set_active ( NULL ); - menu_state_free ( state ); + 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 ( modi[curr_switcher].sw, mretv, &input, selected_line ); ModeMode mode = curr_switcher; @@ -1908,14 +1729,14 @@ static void process_result ( MenuState *state ) mode = retv; } if ( mode != MODE_EXIT ) { - char *prompt = g_strdup_printf ( "%s:", mode_get_name ( modi[mode].sw ) ); + char *prompt = g_strdup_printf ( "%s:", mode_get_name ( modi[mode].sw ) ); curr_switcher = mode; - MenuState * state = menu ( modi[mode].sw, input, prompt, NULL, MENU_NORMAL ); + RofiViewState * state = rofi_view_create ( modi[mode].sw, input, prompt, NULL, MENU_NORMAL ); state->finalize = process_result; g_free ( prompt ); // TODO FIX //g_return_val_if_fail ( state != NULL, MODE_EXIT ); - menu_state_set_active ( state ); + rofi_view_set_active ( state ); g_free ( input ); return; } @@ -2027,7 +1848,7 @@ static void cleanup () tpool = NULL; } if ( main_loop != NULL ) { - if( main_loop_source) { + if ( main_loop_source ) { g_source_destroy ( main_loop_source ); } g_main_loop_unref ( main_loop ); @@ -2214,8 +2035,6 @@ static void reload_configuration () } } - - /** * Process X11 events in the main-loop (gui-thread) of the application. */ @@ -2226,11 +2045,11 @@ static gboolean main_loop_x11_event_handler ( G_GNUC_UNUSED gpointer data ) XEvent ev; // Read event, we know this won't block as we checked with XPending. XNextEvent ( display, &ev ); - menu_state_itterrate ( current_active_menu, &ev ); + rofi_view_itterrate ( current_active_menu, &ev ); } - if ( menu_state_get_completed ( current_active_menu ) ) { + if ( rofi_view_get_completed ( current_active_menu ) ) { // This menu is done. - menu_state_finalize ( current_active_menu ); + rofi_view_finalize ( current_active_menu ); } return G_SOURCE_CONTINUE; } @@ -2305,9 +2124,9 @@ static void error_trap_pop ( G_GNUC_UNUSED SnDisplay *display, Display *xdispl static gboolean delayed_start ( G_GNUC_UNUSED gpointer data ) { // Force some X Events to be handled.. seems the only way to get a reliable startup. - menu_state_queue_redraw (); + rofi_view_queue_redraw (); main_loop_x11_event_handler ( NULL ); - // menu_state_queue_redraw(); + // rofi_view_queue_redraw(); return FALSE; } int main ( int argc, char *argv[] ) diff --git a/source/textbox.c b/source/textbox.c index a9b80899..75102ec6 100644 --- a/source/textbox.c +++ b/source/textbox.c @@ -59,12 +59,13 @@ typedef struct _RowColor RowColor colors[num_states]; PangoContext *p_context = NULL; -static gboolean textbox_blink ( textbox *tb ) +static gboolean textbox_blink ( gpointer data ) { + textbox *tb = (textbox *) data; if ( tb->blink < 2 ) { tb->blink = !tb->blink; tb->update = TRUE; - menu_state_queue_redraw ( ); + rofi_view_queue_redraw ( ); } else { tb->blink--; @@ -103,7 +104,7 @@ textbox* textbox_create ( TextboxFlags flags, short x, short y, short w, short h tb->blink_timeout = 0; tb->blink = 1; if ( ( flags & TB_EDITABLE ) == TB_EDITABLE ) { - tb->blink_timeout = g_timeout_add ( 1200, textbox_blink, tb ); + tb->blink_timeout = g_timeout_add ( 1200, textbox_blink, tb ); } return tb; diff --git a/source/view.c b/source/view.c new file mode 100644 index 00000000..1608c3d7 --- /dev/null +++ b/source/view.c @@ -0,0 +1,199 @@ +/** + * rofi + * + * MIT/X11 License + * Modified 2016 Qball Cow + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#define SN_API_NOT_YET_FROZEN +#include + +#include "settings.h" +#include "mode.h" +#include "rofi.h" +#include "helper.h" +#include "textbox.h" +#include "scrollbar.h" +#include "x11-helper.h" +#include "x11-event-source.h" +#include "xrmoptions.h" +#include "dialogs/dialogs.h" +#include "rofi.h" + +extern RofiViewState *current_active_menu; +extern Display *display; +extern unsigned int num_modi; +extern Window main_window; + +#include "view.h" + +void rofi_view_queue_redraw ( void ) +{ + if ( current_active_menu ) { + current_active_menu->update = TRUE; + XClearArea ( display, main_window, 0, 0, 1, 1, True ); + XFlush ( display ); + } +} + +void rofi_view_restart ( RofiViewState *state ) +{ + state->quit = FALSE; + state->retv = MENU_CANCEL; +} +void rofi_view_set_active ( RofiViewState *state ) +{ + g_assert ( ( current_active_menu == NULL && state != NULL ) || ( current_active_menu != NULL && state == NULL ) ); + current_active_menu = state; +} + +void rofi_view_set_selected_line ( RofiViewState *state, unsigned int selected_line ) +{ + state->selected_line = selected_line; + // Find the line. + state->selected = 0; + for ( unsigned int i = 0; ( ( state->selected_line ) ) < UINT32_MAX && !state->selected && i < state->filtered_lines; i++ ) { + if ( state->line_map[i] == ( state->selected_line ) ) { + state->selected = i; + break; + } + } + + state->update = TRUE; +} + +void rofi_view_free ( RofiViewState *state ) +{ + // Do this here? + // Wait for final release? + if ( !state->skip_absorb ) { + XEvent ev; + do { + XNextEvent ( display, &ev ); + } while ( ev.type != KeyRelease ); + } + textbox_free ( state->text ); + textbox_free ( state->prompt_tb ); + textbox_free ( state->case_indicator ); + scrollbar_free ( state->scrollbar ); + + for ( unsigned int i = 0; i < state->max_elements; i++ ) { + textbox_free ( state->boxes[i] ); + } + + g_free ( state->boxes ); + g_free ( state->line_map ); + g_free ( state->distance ); + g_free ( state->lines_not_ascii ); + g_free ( state ); + // Free the switcher boxes. + // When state is free'ed we should no longer need these. + if ( config.sidebar_mode == TRUE ) { + for ( unsigned int j = 0; j < state->num_modi; j++ ) { + textbox_free ( state->modi[j] ); + state->modi[j] = NULL; + } + g_free ( state->modi ); + state->num_modi = 0; + } +} + +MenuReturn rofi_view_get_return_value ( const RofiViewState *state ) +{ + return state->retv; +} +unsigned int rofi_view_get_selected_line ( const RofiViewState *state ) +{ + return state->selected_line; +} + +unsigned int rofi_view_get_next_position ( const RofiViewState *state ) +{ + unsigned int next_pos = state->selected_line; + if ( ( state->selected + 1 ) < state->num_lines ) { + ( next_pos ) = state->line_map[state->selected + 1]; + } + return next_pos; +} + +unsigned int rofi_view_get_completed ( const RofiViewState *state ) +{ + return state->quit; +} +void rofi_view_itterrate ( RofiViewState *state, XEvent *event ) +{ + state->x11_event_loop ( state, event ); +} +const char * rofi_view_get_user_input ( const RofiViewState *state ) +{ + if ( state->text ) { + return state->text->text; + } + return NULL; +} + +/** + * Create a new, 0 initialized RofiViewState structure. + * + * @returns a new 0 initialized RofiViewState + */ +RofiViewState * rofi_view_state_create ( void ) +{ + return g_malloc0 ( sizeof ( RofiViewState ) ); +} + +/** + * @param state The Menu Handle + * + * Check if a finalize function is set, and if sets executes it. + */ +void rofi_view_finalize ( RofiViewState *state ) +{ + if ( state && state->finalize ) { + state->finalize ( state ); + } +} diff --git a/test/textbox-test.c b/test/textbox-test.c index c7aa58e9..69a769fb 100644 --- a/test/textbox-test.c +++ b/test/textbox-test.c @@ -25,7 +25,7 @@ unsigned int normal_window_mode = 0; Display *display = NULL; Colormap map = None; XVisualInfo vinfo; -void menu_state_queue_redraw () +void rofi_view_queue_redraw () { }