From cee753bd3cc2f96743e8771d0cd82beee32fcd2e Mon Sep 17 00:00:00 2001 From: Dave Davenport Date: Fri, 10 Mar 2017 23:39:29 +0100 Subject: [PATCH] Zeltakmadness (#572) * Allow modi to set extra pango attributes on displayed rows * Fix some documentation, only highlight the mode name with color. * Small rename. --- include/mode-private.h | 5 +++-- include/mode.h | 4 ++-- include/theme.h | 28 ++++++++++++++++++++++++++++ source/dialogs/combi.c | 27 ++++++++++++++++++++++----- source/dialogs/dmenu.c | 2 +- source/dialogs/drun.c | 2 +- source/dialogs/help-keys.c | 2 +- source/dialogs/run.c | 2 +- source/dialogs/script.c | 2 +- source/dialogs/ssh.c | 2 +- source/dialogs/window.c | 2 +- source/mode.c | 6 +++--- source/theme.c | 4 ++-- source/view.c | 27 ++++++++++++++++----------- source/widgets/textbox.c | 3 +-- 15 files changed, 84 insertions(+), 34 deletions(-) diff --git a/include/mode-private.h b/include/mode-private.h index 04e0ea9d..633065f0 100644 --- a/include/mode-private.h +++ b/include/mode-private.h @@ -2,7 +2,7 @@ #define ROFI_MODE_PRIVATE_H #include -#define ABI_VERSION 0x00000003 +#define ABI_VERSION 0x00000004 /** * @param data Pointer to #Mode object. @@ -15,13 +15,14 @@ typedef void ( *_mode_free )( Mode *data ); * @param sw The #Mode pointer * @param selected_line The selected line * @param state The state to display [out] + * @param attribute_list List of extra (pango) attribute to apply when displaying. [out][null] * @param get_entry if it should only return the state * * Get the value for displaying. * * @return the string and state for displaying. */ -typedef char * ( *_mode_get_display_value )( const Mode *sw, unsigned int selected_line, int *state, int get_entry ); +typedef char * ( *_mode_get_display_value )( const Mode *sw, unsigned int selected_line, int *state, GList **attribute_list, int get_entry ); /** * @param sw The #Mode pointer diff --git a/include/mode.h b/include/mode.h index 0dbef79c..f56a935b 100644 --- a/include/mode.h +++ b/include/mode.h @@ -1,6 +1,5 @@ #ifndef ROFI_MODE_H #define ROFI_MODE_H - /** * @defgroup MODE Mode * @@ -85,13 +84,14 @@ unsigned int mode_get_num_entries ( const Mode *sw ); * @param mode The mode to query * @param selected_line The entry to query * @param state The state of the entry [out] + * @param attribute_list List of extra (pango) attribute to apply when displaying. [out][null] * @param get_entry If the should be returned. * * Returns the string as it should be displayed for the entry and the state of how it should be displayed. * * @returns allocated new string and state when get_entry is TRUE otherwise just the state. */ -char * mode_get_display_value ( const Mode *mode, unsigned int selected_line, int *state, int get_entry ); +char * mode_get_display_value ( const Mode *mode, unsigned int selected_line, int *state, GList **attribute_list, int get_entry ); /** * @param mode The mode to query diff --git a/include/theme.h b/include/theme.h index 37cdf29c..ae1fdf5d 100644 --- a/include/theme.h +++ b/include/theme.h @@ -382,4 +382,32 @@ void distance_get_linestyle ( Distance d, cairo_t *draw ); */ void rofi_theme_convert_old_theme ( void ); #endif + +/** + * Low-level functions. + * These can be used by non-widgets to obtain values. + */ +/** + * @param name The name of the element to find. + * @param state The state of the element. + * @param exact If the match should be exact, or parent can be included. + * + * Find the theme element. If not exact, the closest specified element is returned. + * + * @returns the ThemeWidget if found, otherwise NULL. + */ +ThemeWidget *rofi_theme_find_widget ( const char *name, const char *state, gboolean exact ); + +/** + * @param widget The widget to find the property on. + * @param type The %PropertyType to find. + * @param property The property to find. + * @param exact If the property should only be found on this widget, or on parents if not found. + * + * Find the property on the widget. If not exact, the parents are searched recursively until match is found. + * + * @returns the Property if found, otherwise NULL. + */ +Property *rofi_theme_find_property ( ThemeWidget *widget, PropertyType type, const char *property, gboolean exact ); + #endif diff --git a/source/dialogs/combi.c b/source/dialogs/combi.c index 3d408712..4da67f31 100644 --- a/source/dialogs/combi.c +++ b/source/dialogs/combi.c @@ -32,6 +32,9 @@ #include "helper.h" #include +#include +#include "mode-private.h" +#include /** * Combi Mode @@ -187,13 +190,13 @@ static int combi_mode_match ( const Mode *sw, GRegex **tokens, unsigned int inde } return 0; } -static char * combi_mgrv ( const Mode *sw, unsigned int selected_line, int *state, int get_entry ) +static char * combi_mgrv ( const Mode *sw, unsigned int selected_line, int *state, GList **attr_list, int get_entry ) { CombiModePrivateData *pd = mode_get_private_data ( sw ); if ( !get_entry ) { for ( unsigned i = 0; i < pd->num_switchers; i++ ) { if ( selected_line >= pd->starts[i] && selected_line < ( pd->starts[i] + pd->lengths[i] ) ) { - mode_get_display_value ( pd->switchers[i].mode, selected_line - pd->starts[i], state, FALSE ); + mode_get_display_value ( pd->switchers[i].mode, selected_line - pd->starts[i], state, attr_list, FALSE ); return NULL; } } @@ -201,9 +204,24 @@ static char * combi_mgrv ( const Mode *sw, unsigned int selected_line, int *stat } for ( unsigned i = 0; i < pd->num_switchers; i++ ) { if ( selected_line >= pd->starts[i] && selected_line < ( pd->starts[i] + pd->lengths[i] ) ) { - char * str = mode_get_display_value ( pd->switchers[i].mode, selected_line - pd->starts[i], state, TRUE ); - char * retv = g_strdup_printf ( "%s %s", mode_get_display_name ( pd->switchers[i].mode ), str ); + char * str = mode_get_display_value ( pd->switchers[i].mode, selected_line - pd->starts[i], state, attr_list, TRUE ); + const char *dname = mode_get_display_name ( pd->switchers[i].mode ); + char * retv = g_strdup_printf ( "%s %s", dname, str ); g_free ( str ); + + if ( attr_list != NULL ) { + ThemeWidget *wid = rofi_theme_find_widget ( sw->name, NULL, TRUE); + Property *p = rofi_theme_find_property ( wid, P_COLOR, pd->switchers[i].mode->name, TRUE); + if ( p != NULL ) { + PangoAttribute *pa = pango_attr_foreground_new ( + p->value.color.red * 65535, + p->value.color.green * 65535, + p->value.color.blue * 65535 ); + pa->start_index = PANGO_ATTR_INDEX_FROM_TEXT_BEGINNING; + pa->end_index = strlen(dname); + *attr_list = g_list_append ( *attr_list, pa ); + } + } return retv; } } @@ -253,7 +271,6 @@ static char * combi_preprocess_input ( Mode *sw, const char *input ) return g_strdup ( input ); } -#include "mode-private.h" Mode combi_mode = { .name = "combi", diff --git a/source/dialogs/dmenu.c b/source/dialogs/dmenu.c index 85bf850a..fecf4c6a 100644 --- a/source/dialogs/dmenu.c +++ b/source/dialogs/dmenu.c @@ -271,7 +271,7 @@ static gchar * dmenu_format_output_string ( const DmenuModePrivateData *pd, cons return retv ? retv : g_strdup ( "" ); } -static char *get_display_data ( const Mode *data, unsigned int index, int *state, int get_entry ) +static char *get_display_data ( const Mode *data, unsigned int index, int *state, G_GNUC_UNUSED GList **list, int get_entry ) { Mode *sw = (Mode *) data; DmenuModePrivateData *pd = (DmenuModePrivateData *) mode_get_private_data ( sw ); diff --git a/source/dialogs/drun.c b/source/dialogs/drun.c index 03c842c2..1553efb4 100644 --- a/source/dialogs/drun.c +++ b/source/dialogs/drun.c @@ -460,7 +460,7 @@ static void drun_mode_destroy ( Mode *sw ) } } -static char *_get_display_value ( const Mode *sw, unsigned int selected_line, int *state, int get_entry ) +static char *_get_display_value ( const Mode *sw, unsigned int selected_line, int *state, G_GNUC_UNUSED GList **list, int get_entry ) { DRunModePrivateData *pd = (DRunModePrivateData *) mode_get_private_data ( sw ); *state |= MARKUP; diff --git a/source/dialogs/help-keys.c b/source/dialogs/help-keys.c index 2e0a3101..a550f559 100644 --- a/source/dialogs/help-keys.c +++ b/source/dialogs/help-keys.c @@ -93,7 +93,7 @@ static void help_keys_mode_destroy ( Mode *sw ) } } -static char *_get_display_value ( const Mode *sw, unsigned int selected_line, int *state, int get_entry ) +static char *_get_display_value ( const Mode *sw, unsigned int selected_line, int *state, G_GNUC_UNUSED GList **list, int get_entry ) { KeysHelpModePrivateData *pd = (KeysHelpModePrivateData *) mode_get_private_data ( sw ); *state |= MARKUP; diff --git a/source/dialogs/run.c b/source/dialogs/run.c index 96ddd352..816f0a41 100644 --- a/source/dialogs/run.c +++ b/source/dialogs/run.c @@ -390,7 +390,7 @@ static ModeMode run_mode_result ( Mode *sw, int mretv, char **input, unsigned in return retv; } -static char *_get_display_value ( const Mode *sw, unsigned int selected_line, G_GNUC_UNUSED int *state, int get_entry ) +static char *_get_display_value ( const Mode *sw, unsigned int selected_line, G_GNUC_UNUSED int *state, G_GNUC_UNUSED GList **list, int get_entry ) { const RunModePrivateData *rmpd = (const RunModePrivateData *) sw->private_data; return get_entry ? g_strdup ( rmpd->cmd_list[selected_line] ) : NULL; diff --git a/source/dialogs/script.c b/source/dialogs/script.c index f653d719..72594a67 100644 --- a/source/dialogs/script.c +++ b/source/dialogs/script.c @@ -158,7 +158,7 @@ static void script_mode_destroy ( Mode *sw ) sw->private_data = NULL; } } -static char *_get_display_value ( const Mode *sw, unsigned int selected_line, G_GNUC_UNUSED int *state, int get_entry ) +static char *_get_display_value ( const Mode *sw, unsigned int selected_line, G_GNUC_UNUSED int *state, G_GNUC_UNUSED GList **list, int get_entry ) { ScriptModePrivateData *rmpd = sw->private_data; return get_entry ? g_strdup ( rmpd->cmd_list[selected_line] ) : NULL; diff --git a/source/dialogs/ssh.c b/source/dialogs/ssh.c index c74f4000..6411b823 100644 --- a/source/dialogs/ssh.c +++ b/source/dialogs/ssh.c @@ -505,7 +505,7 @@ static void ssh_mode_destroy ( Mode *sw ) * * @return the string as it should be displayed and the display state. */ -static char *_get_display_value ( const Mode *sw, unsigned int selected_line, G_GNUC_UNUSED int *state, int get_entry ) +static char *_get_display_value ( const Mode *sw, unsigned int selected_line, G_GNUC_UNUSED int *state, G_GNUC_UNUSED GList **list, int get_entry ) { SSHModePrivateData *rmpd = (SSHModePrivateData *) mode_get_private_data ( sw ); return get_entry ? g_strdup ( rmpd->hosts_list[selected_line] ) : NULL; diff --git a/source/dialogs/window.c b/source/dialogs/window.c index 304b6a11..71cd70e0 100644 --- a/source/dialogs/window.c +++ b/source/dialogs/window.c @@ -709,7 +709,7 @@ static char * _generate_display_string ( const ModeModePrivateData *pd, client * return g_strchomp ( res ); } -static char *_get_display_value ( const Mode *sw, unsigned int selected_line, int *state, int get_entry ) +static char *_get_display_value ( const Mode *sw, unsigned int selected_line, int *state, G_GNUC_UNUSED GList **list, int get_entry ) { ModeModePrivateData *rmpd = mode_get_private_data ( sw ); client *c = window_client ( rmpd, rmpd->ids->array[selected_line] ); diff --git a/source/mode.c b/source/mode.c index 53daf88c..ed15ff1b 100644 --- a/source/mode.c +++ b/source/mode.c @@ -35,13 +35,13 @@ unsigned int mode_get_num_entries ( const Mode *mode ) return mode->_get_num_entries ( mode ); } -char * mode_get_display_value ( const Mode *mode, unsigned int selected_line, int *state, int get_entry ) +char * mode_get_display_value ( const Mode *mode, unsigned int selected_line, int *state, GList **list, int get_entry ) { g_assert ( mode != NULL ); g_assert ( state != NULL ); g_assert ( mode->_get_display_value != NULL ); - return mode->_get_display_value ( mode, selected_line, state, get_entry ); + return mode->_get_display_value ( mode, selected_line, state, list, get_entry ); } char * mode_get_completion ( const Mode *mode, unsigned int selected_line ) @@ -53,7 +53,7 @@ char * mode_get_completion ( const Mode *mode, unsigned int selected_line ) else { int state; g_assert ( mode->_get_display_value != NULL ); - return mode->_get_display_value ( mode, selected_line, &state, TRUE ); + return mode->_get_display_value ( mode, selected_line, &state,NULL, TRUE ); } } diff --git a/source/theme.c b/source/theme.c index 0d540f97..4e33a9a1 100644 --- a/source/theme.c +++ b/source/theme.c @@ -365,7 +365,7 @@ static void rofi_theme_resolve_link_property ( Property *p, int depth ) p->value.link.ref = p; } -static Property *rofi_theme_find_property ( ThemeWidget *widget, PropertyType type, const char *property, gboolean exact ) +Property *rofi_theme_find_property ( ThemeWidget *widget, PropertyType type, const char *property, gboolean exact ) { while ( widget ) { if ( widget->properties && g_hash_table_contains ( widget->properties, property ) ) { @@ -394,7 +394,7 @@ static Property *rofi_theme_find_property ( ThemeWidget *widget, PropertyType ty } return NULL; } -static ThemeWidget *rofi_theme_find_widget ( const char *name, const char *state, gboolean exact ) +ThemeWidget *rofi_theme_find_widget ( const char *name, const char *state, gboolean exact ) { // First find exact match based on name. ThemeWidget *widget = rofi_theme_find ( rofi_theme, name, exact ); diff --git a/source/view.c b/source/view.c index f036abaa..63d269b5 100644 --- a/source/view.c +++ b/source/view.c @@ -878,32 +878,37 @@ static void update_callback ( textbox *t, unsigned int index, void *udata, TextB { RofiViewState *state = (RofiViewState *) udata; if ( full ) { + GList *add_list = NULL; int fstate = 0; - char *text = mode_get_display_value ( state->sw, state->line_map[index], &fstate, TRUE ); + char *text = mode_get_display_value ( state->sw, state->line_map[index], &fstate, &add_list, TRUE ); type |= fstate; textbox_font ( t, type ); // Move into list view. textbox_text ( t, text ); + PangoAttrList *list = textbox_get_pango_attributes ( t ); + if ( list != NULL ) { + pango_attr_list_ref ( list ); + } + else{ + list = pango_attr_list_new (); + } if ( state->tokens && config.show_match ) { - PangoAttrList *list = textbox_get_pango_attributes ( t ); - if ( list != NULL ) { - pango_attr_list_ref ( list ); - } - else{ - list = pango_attr_list_new (); - } ThemeHighlight th = { HL_BOLD | HL_UNDERLINE, { 0.0, 0.0, 0.0, 0.0 } }; th = rofi_theme_get_highlight ( WIDGET ( t ), "highlight", th ); helper_token_match_get_pango_attr ( th, state->tokens, textbox_get_visible_text ( t ), list ); - textbox_set_pango_attributes ( t, list ); - pango_attr_list_unref ( list ); } + for ( GList *iter = g_list_first ( add_list ); iter != NULL ; iter = g_list_next(iter) ) { + pango_attr_list_insert ( list, (PangoAttribute *)(iter->data)); + } + textbox_set_pango_attributes ( t, list ); + pango_attr_list_unref ( list ); + g_list_free( add_list); g_free ( text ); } else { int fstate = 0; - mode_get_display_value ( state->sw, state->line_map[index], &fstate, FALSE ); + mode_get_display_value ( state->sw, state->line_map[index], &fstate, NULL, FALSE ); type |= fstate; textbox_font ( t, type ); } diff --git a/source/widgets/textbox.c b/source/widgets/textbox.c index ed9cfef4..cb30e624 100644 --- a/source/widgets/textbox.c +++ b/source/widgets/textbox.c @@ -213,19 +213,18 @@ void textbox_font ( textbox *tb, TextBoxFontType tbft ) */ static void __textbox_update_pango_text ( textbox *tb ) { + pango_layout_set_attributes ( tb->layout, NULL ); if ( ( tb->flags & TB_PASSWORD ) == TB_PASSWORD ) { size_t l = g_utf8_strlen ( tb->text, -1 ); char string [l + 1]; memset ( string, '*', l ); string[l] = '\0'; - pango_layout_set_attributes ( tb->layout, NULL ); pango_layout_set_text ( tb->layout, string, l ); } else if ( tb->flags & TB_MARKUP || tb->tbft & MARKUP ) { pango_layout_set_markup ( tb->layout, tb->text, -1 ); } else { - pango_layout_set_attributes ( tb->layout, NULL ); pango_layout_set_text ( tb->layout, tb->text, -1 ); } }