summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/theme.c41
-rw-r--r--source/view.c227
-rw-r--r--source/widgets/box.c45
-rw-r--r--source/widgets/listview.c177
-rw-r--r--source/widgets/textbox.c94
-rw-r--r--source/widgets/widget.c19
6 files changed, 496 insertions, 107 deletions
diff --git a/source/theme.c b/source/theme.c
index 1c4711c6..cebe29e3 100644
--- a/source/theme.c
+++ b/source/theme.c
@@ -386,6 +386,8 @@ static ThemeWidget *rofi_theme_find ( ThemeWidget *widget, const char *name, con
if ( f != widget ) {
widget = f;
found = TRUE;
+ } else if ( exact ) {
+ break;
}
}
g_free ( tname );
@@ -503,11 +505,10 @@ int rofi_theme_get_integer_exact ( const widget *widget, const char *property, i
g_debug ( "Theme entry: #%s %s property %s unset.", widget->name, widget->state ? widget->state : "", property );
return def;
}
-
-Distance rofi_theme_get_distance ( const widget *widget, const char *property, int def )
+static Distance _rofi_theme_get_distance ( const widget *widget, const char *property, int def , gboolean exact)
{
- ThemeWidget *wid = rofi_theme_find_widget ( widget->name, widget->state, FALSE );
- Property *p = rofi_theme_find_property ( wid, P_PADDING, property, FALSE );
+ ThemeWidget *wid = rofi_theme_find_widget ( widget->name, widget->state, exact );
+ Property *p = rofi_theme_find_property ( wid, P_PADDING, property, exact );
if ( p ) {
if ( p->type == P_INTEGER ) {
return (Distance){ p->value.i, PW_PX, SOLID };
@@ -520,6 +521,16 @@ Distance rofi_theme_get_distance ( const widget *widget, const char *property, i
return (Distance){ def, PW_PX, SOLID };
}
+
+Distance rofi_theme_get_distance_exact ( const widget *widget, const char *property, int def )
+{
+ return _rofi_theme_get_distance ( widget, property, def , TRUE );
+}
+Distance rofi_theme_get_distance ( const widget *widget, const char *property, int def )
+{
+ return _rofi_theme_get_distance ( widget, property, def , FALSE);
+}
+
int rofi_theme_get_boolean ( const widget *widget, const char *property, int def )
{
ThemeWidget *wid = rofi_theme_find_widget ( widget->name, widget->state, FALSE );
@@ -583,6 +594,28 @@ Padding rofi_theme_get_padding ( const widget *widget, const char *property, Pad
g_debug ( "Theme entry: #%s %s property %s unset.", widget->name, widget->state ? widget->state : "", property );
return pad;
}
+
+GList *rofi_theme_get_list ( const widget *widget, const char * property, const char *defaults )
+{
+ ThemeWidget *wid2 = rofi_theme_find_widget ( widget->name, widget->state, TRUE );
+ Property *p = rofi_theme_find_property ( wid2, P_LIST, property, TRUE);
+ if ( p ) {
+ if ( p->type == P_LIST ){
+ return g_list_copy_deep ( p->value.list, g_strdup, NULL );
+ }
+ }
+ char **r = defaults?g_strsplit (defaults, ",",0):NULL;
+ if ( r ){
+ GList *l = NULL;
+ for ( int i =0; r[i] != NULL; i++){
+ l = g_list_append(l, r[i]);
+ }
+ g_free(r);
+ return l;
+ }
+ return NULL;
+}
+
ThemeHighlight rofi_theme_get_highlight ( widget *widget, const char *property, ThemeHighlight th )
{
ThemeWidget *wid = rofi_theme_find_widget ( widget->name, widget->state, FALSE );
diff --git a/source/view.c b/source/view.c
index 5776d845..824d2300 100644
--- a/source/view.c
+++ b/source/view.c
@@ -650,8 +650,8 @@ void __create_window ( MenuFlags menu_flags )
map
};
- xcb_window_t box = xcb_generate_id ( xcb->connection );
- xcb_void_cookie_t cc = xcb_create_window_checked ( xcb->connection, depth->depth, box, xcb_stuff_get_root_window (),
+ xcb_window_t box_window = xcb_generate_id ( xcb->connection );
+ xcb_void_cookie_t cc = xcb_create_window_checked ( xcb->connection, depth->depth, box_window, xcb_stuff_get_root_window ( ),
0, 0, 200, 100, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT,
visual->visual_id, selmask, selval );
xcb_generic_error_t *error;
@@ -662,7 +662,7 @@ void __create_window ( MenuFlags menu_flags )
}
TICK_N ( "xcb create window" );
CacheState.gc = xcb_generate_id ( xcb->connection );
- xcb_create_gc ( xcb->connection, CacheState.gc, box, 0, 0 );
+ xcb_create_gc ( xcb->connection, CacheState.gc, box_window, 0, 0 );
TICK_N ( "xcb create gc" );
// Create a drawable.
@@ -684,7 +684,7 @@ void __create_window ( MenuFlags menu_flags )
pango_cairo_context_set_font_options ( p, fo );
TICK_N ( "pango cairo font setup" );
- CacheState.main_window = box;
+ CacheState.main_window = box_window;
CacheState.flags = menu_flags;
monitor_active ( &( CacheState.mon ) );
// Setup dpi
@@ -708,7 +708,7 @@ void __create_window ( MenuFlags menu_flags )
}
// Setup font.
// Dummy widget.
- container *win = container_create ( "window.box" );
+ box *win = box_create ( "window.box_window", BOX_HORIZONTAL );
const char *font = rofi_theme_get_string ( WIDGET ( win ), "font", config.menu_font );
if ( font ) {
PangoFontDescription *pfd = pango_font_description_from_string ( font );
@@ -730,13 +730,13 @@ void __create_window ( MenuFlags menu_flags )
TICK_N ( "textbox setup" );
// // make it an unmanaged window
if ( ( ( menu_flags & MENU_NORMAL_WINDOW ) == 0 ) ) {
- window_set_atom_prop ( box, xcb->ewmh._NET_WM_STATE, &( xcb->ewmh._NET_WM_STATE_ABOVE ), 1 );
+ window_set_atom_prop ( box_window, xcb->ewmh._NET_WM_STATE, &( xcb->ewmh._NET_WM_STATE_ABOVE ), 1 );
uint32_t values[] = { 1 };
- xcb_change_window_attributes ( xcb->connection, box, XCB_CW_OVERRIDE_REDIRECT, values );
+ xcb_change_window_attributes ( xcb->connection, box_window, XCB_CW_OVERRIDE_REDIRECT, values );
}
else{
- window_set_atom_prop ( box, xcb->ewmh._NET_WM_WINDOW_TYPE, &( xcb->ewmh._NET_WM_WINDOW_TYPE_NORMAL ), 1 );
- x11_disable_decoration ( box );
+ window_set_atom_prop ( box_window, xcb->ewmh._NET_WM_WINDOW_TYPE, &( xcb->ewmh._NET_WM_WINDOW_TYPE_NORMAL ), 1 );
+ x11_disable_decoration ( box_window );
}
TICK_N ( "setup window attributes" );
@@ -746,16 +746,16 @@ void __create_window ( MenuFlags menu_flags )
xcb->ewmh._NET_WM_STATE_FULLSCREEN,
xcb->ewmh._NET_WM_STATE_ABOVE
};
- window_set_atom_prop ( box, xcb->ewmh._NET_WM_STATE, atoms, sizeof ( atoms ) / sizeof ( xcb_atom_t ) );
+ window_set_atom_prop ( box_window, xcb->ewmh._NET_WM_STATE, atoms, sizeof ( atoms ) / sizeof ( xcb_atom_t ) );
}
TICK_N ( "setup window fullscreen" );
// Set the WM_NAME
- xcb_change_property ( xcb->connection, XCB_PROP_MODE_REPLACE, box, xcb->ewmh._NET_WM_NAME, xcb->ewmh.UTF8_STRING, 8, 4, "rofi" );
- xcb_change_property ( xcb->connection, XCB_PROP_MODE_REPLACE, box, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, 4, "rofi" );
+ xcb_change_property ( xcb->connection, XCB_PROP_MODE_REPLACE, box_window, xcb->ewmh._NET_WM_NAME, xcb->ewmh.UTF8_STRING, 8, 4, "rofi" );
+ xcb_change_property ( xcb->connection, XCB_PROP_MODE_REPLACE, box_window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, 4, "rofi" );
const char wm_class_name[] = "rofi\0Rofi";
- xcb_icccm_set_wm_class ( xcb->connection, box, sizeof ( wm_class_name ), wm_class_name );
+ xcb_icccm_set_wm_class ( xcb->connection, box_window, sizeof ( wm_class_name ), wm_class_name );
TICK_N ( "setup window name and class" );
const char *transparency = rofi_theme_get_string ( WIDGET ( win ), "transparency", NULL );
@@ -994,7 +994,7 @@ static void rofi_view_refilter ( RofiViewState *state )
tokenize_free ( state->tokens );
state->tokens = NULL;
}
- if ( strlen ( state->text->text ) > 0 ) {
+ if ( state->text && strlen ( state->text->text ) > 0 ) {
unsigned int j = 0;
gchar *pattern = mode_preprocess_input ( state->sw, state->text->text );
glong plen = pattern ? g_utf8_strlen ( pattern, -1 ) : 0;
@@ -1484,6 +1484,125 @@ static void rofi_view_listview_mouse_activated_cb ( listview *lv, gboolean custo
state->skip_absorb = TRUE;
}
+
+static void rofi_view_add_widget ( RofiViewState *state, widget *parent_widget, const char *parent, const char *name )
+{
+ char *defaults = NULL;
+ widget *wid = NULL;
+ char *str= g_strjoin ( "." , parent, name, NULL );
+ char *strbox= g_strjoin ( "." , str, "box",NULL );
+
+ /**
+ * MAINBOX
+ */
+ if ( strcmp ( name, "mainbox") == 0 ){
+ wid = (widget *)box_create ( strbox, BOX_VERTICAL );
+ box_add ( (box *)parent_widget, WIDGET ( wid ), TRUE, 0 );
+ defaults = "inputbar,message,listview";
+ }
+ /**
+ * INPUTBAR
+ */
+ else if ( strcmp ( name, "inputbar" ) == 0 ){
+ wid = (widget *)box_create ( strbox, BOX_HORIZONTAL );
+ defaults = "prompt,entry,case-indicator";
+
+ box_add ( (box *)parent_widget, WIDGET ( wid ), FALSE, 0 );
+ }
+ /**
+ * PROMPT
+ */
+ else if ( strcmp ( name, "prompt" ) == 0 ){
+ // Prompt box.
+ state->prompt = textbox_create ( str, TB_AUTOWIDTH | TB_AUTOHEIGHT, NORMAL, "" );
+ rofi_view_update_prompt ( state );
+ box_add ( (box *)parent_widget, WIDGET ( state->prompt ), FALSE, 1 );
+ defaults = NULL;
+ }
+ /**
+ * CASE INDICATOR
+ */
+ else if ( strcmp ( name, "case-indicator") == 0 ){
+ state->case_indicator = textbox_create ( str, TB_AUTOWIDTH | TB_AUTOHEIGHT, NORMAL, "*" );
+ // Add small separator between case indicator and text box.
+ box_add ( (box *)parent_widget, WIDGET ( state->case_indicator ), FALSE, 3 );
+ textbox_text ( state->case_indicator, get_matching_state () );
+ }
+ /**
+ * ENTRY BOX
+ */
+ else if ( strcmp ( name, "entry" ) == 0 ){
+ // Entry box
+ TextboxFlags tfl = TB_EDITABLE;
+ tfl |= ( ( state->menu_flags & MENU_PASSWORD ) == MENU_PASSWORD ) ? TB_PASSWORD : 0;
+ state->text = textbox_create ( str, tfl | TB_AUTOHEIGHT, NORMAL, NULL);
+ box_add ( (box*)parent_widget, WIDGET ( state->text ), TRUE, 2 );
+ }
+ /**
+ * MESSAGE
+ */
+ else if ( strcmp ( name, "message") == 0 ){
+ char *strmsg= g_strjoin ( "." , str, "textbox",NULL );
+ state->mesg_box = container_create ( strbox );
+ state->mesg_tb = textbox_create ( strmsg, TB_AUTOHEIGHT | TB_MARKUP | TB_WRAP, NORMAL, NULL );
+ container_add ( state->mesg_box, WIDGET ( state->mesg_tb ) );
+ rofi_view_reload_message_bar ( state );
+ box_add ( (box*)parent_widget, WIDGET ( state->mesg_box ), FALSE, 2 );
+ g_free(strmsg);
+ }
+ /**
+ * LISTVIEW
+ */
+ else if ( strcmp ( name, "listview" ) == 0 ) {
+ state->list_view = listview_create ( str, update_callback, state, config.element_height, 0);
+ box_add ( (box*)parent_widget, WIDGET ( state->list_view ), TRUE, 3 );
+ // Set configuration
+ listview_set_multi_select ( state->list_view, ( state->menu_flags & MENU_INDICATOR ) == MENU_INDICATOR );
+ listview_set_scroll_type ( state->list_view, config.scroll_method );
+ listview_set_mouse_activated_cb ( state->list_view, rofi_view_listview_mouse_activated_cb, state );
+
+ int lines = rofi_theme_get_integer ( WIDGET ( state->list_view ), "lines", config.menu_lines );
+ listview_set_num_lines ( state->list_view, lines );
+ listview_set_max_lines ( state->list_view, state->num_lines );
+ }
+ /**
+ * SIDEBAR
+ */
+ else if ( strcmp( name, "sidebar" ) == 0 ) {
+ if ( config.sidebar_mode ){
+ state->sidebar_bar = box_create ( strbox, BOX_HORIZONTAL );
+ box_add ( (box*)parent_widget, WIDGET ( state->sidebar_bar ), FALSE, 10 );
+ state->num_modi = rofi_get_num_enabled_modi ();
+ state->modi = g_malloc0 ( state->num_modi * sizeof ( textbox * ) );
+ char *strbutton= g_strjoin ( "." , str, "button",NULL );
+ for ( unsigned int j = 0; j < state->num_modi; j++ ) {
+ const Mode * mode = rofi_get_mode ( j );
+ state->modi[j] = textbox_create ( strbutton, TB_CENTER | TB_AUTOHEIGHT, ( mode == state->sw ) ? HIGHLIGHT : NORMAL,
+ mode_get_display_name ( mode ) );
+ box_add ( state->sidebar_bar, WIDGET ( state->modi[j] ), TRUE, j );
+ //widget_set_clicked_handler ( WIDGET ( state->modi[j] ), rofi_view_modi_clicked_cb, state );
+ }
+ g_free(strbutton);
+ }
+ } else if ( g_ascii_strncasecmp ( name, "textbox", 7) == 0 ){
+ textbox *t = textbox_create ( str, TB_WRAP, NORMAL, "");
+ box_add ( (box *)parent_widget, WIDGET(t), TRUE, 0);
+ } else {
+ wid = box_create ( strbox, BOX_VERTICAL );
+ box_add ( (box *)parent_widget, WIDGET ( wid ), TRUE, 0 );
+ //g_error("The widget %s does not exists. Invalid layout.", name);
+ }
+ if ( wid ) {
+ GList *list = rofi_theme_get_list ( wid, "children",defaults);
+ for ( const GList *iter = list; iter != NULL; iter = g_list_next ( iter )){
+ rofi_view_add_widget ( state, wid, str, (const char *)iter->data );
+ }
+ g_list_free_full ( list, g_free );
+ }
+ g_free(strbox);
+ g_free(str);
+}
+
RofiViewState *rofi_view_create ( Mode *sw,
const char *input,
MenuFlags menu_flags,
@@ -1511,69 +1630,23 @@ RofiViewState *rofi_view_create ( Mode *sw,
// Get active monitor size.
TICK_N ( "Get active monitor" );
- state->main_window = container_create ( "window.box" );
- state->main_box = box_create ( "window.mainbox.box", BOX_VERTICAL );
- container_add ( state->main_window, WIDGET ( state->main_box ) );
-
- state->input_bar = box_create ( "window.mainbox.inputbar.box", BOX_HORIZONTAL );
-
- // Only enable widget when sidebar is enabled.
- if ( config.sidebar_mode ) {
- state->sidebar_bar = box_create ( "window.mainbox.sidebar.box", BOX_HORIZONTAL );
- box_add ( state->main_box, WIDGET ( state->sidebar_bar ), FALSE, 10 );
- state->num_modi = rofi_get_num_enabled_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_full ( WIDGET_TYPE_SIDEBAR_MODI, "window.mainbox.sidebar.button", TB_CENTER | TB_AUTOHEIGHT, ( mode == state->sw ) ? HIGHLIGHT : NORMAL,
- mode_get_display_name ( mode ) );
- box_add ( state->sidebar_bar, WIDGET ( state->modi[j] ), TRUE, j );
- widget_set_trigger_action_handler ( WIDGET ( state->modi[j] ), textbox_sidebar_modi_trigger_action, state );
- }
- }
-
- int location = rofi_theme_get_position ( WIDGET ( state->main_window ), "location", config.location );
- int end = ( location == WL_SOUTH_EAST || location == WL_SOUTH || location == WL_SOUTH_WEST );
- box_add ( state->main_box, WIDGET ( state->input_bar ), FALSE, end ? 9 : 0 );
-
- state->case_indicator = textbox_create ( "window.mainbox.inputbar.case-indicator", TB_AUTOWIDTH | TB_AUTOHEIGHT, NORMAL, "*" );
- // Add small separator between case indicator and text box.
- box_add ( state->input_bar, WIDGET ( state->case_indicator ), FALSE, 3 );
-
- // Prompt box.
- state->prompt = textbox_create ( "window.mainbox.inputbar.prompt", TB_AUTOWIDTH | TB_AUTOHEIGHT, NORMAL, "" );
- rofi_view_update_prompt ( state );
- box_add ( state->input_bar, WIDGET ( state->prompt ), FALSE, 1 );
-
- // Entry box
- TextboxFlags tfl = TB_EDITABLE;
- tfl |= ( ( menu_flags & MENU_PASSWORD ) == MENU_PASSWORD ) ? TB_PASSWORD : 0;
- state->text = textbox_create_full ( WIDGET_TYPE_EDITBOX, "window.mainbox.inputbar.entry", tfl | TB_AUTOHEIGHT, NORMAL, input );
- box_add ( state->input_bar, WIDGET ( state->text ), TRUE, 2 );
+ state->main_window = box_create ( "window.box", BOX_VERTICAL );
+ // Get children.
+ GList *list = rofi_theme_get_list ( WIDGET(state->main_window), "children", "mainbox");
+ for ( const GList *iter = list; iter != NULL; iter = g_list_next ( iter )){
+ rofi_view_add_widget ( state, WIDGET(state->main_window), "window", (const char *)iter->data );
+ }
+ g_list_free_full ( list, g_free );
- textbox_text ( state->case_indicator, get_matching_state () );
- state->mesg_box = container_create ( "window.mainbox.message.box" );
- state->mesg_tb = textbox_create ( "window.mainbox.message.textbox", TB_AUTOHEIGHT | TB_MARKUP | TB_WRAP, NORMAL, NULL );
- container_add ( state->mesg_box, WIDGET ( state->mesg_tb ) );
- rofi_view_reload_message_bar ( state );
- box_add ( state->main_box, WIDGET ( state->mesg_box ), FALSE, end ? 8 : 2 );
+ if ( state->text && input) {
+ textbox_text ( state->text, input );
+ }
state->overlay = textbox_create ( "window.overlay", TB_AUTOWIDTH | TB_AUTOHEIGHT, URGENT, "blaat" );
state->overlay->widget.parent = WIDGET ( state->main_window );
widget_disable ( WIDGET ( state->overlay ) );
- state->list_view = listview_create ( "window.mainbox.listview", update_callback, state, config.element_height, end );
- // Set configuration
- listview_set_multi_select ( state->list_view, ( state->menu_flags & MENU_INDICATOR ) == MENU_INDICATOR );
- listview_set_scroll_type ( state->list_view, config.scroll_method );
- listview_set_mouse_activated_cb ( state->list_view, rofi_view_listview_mouse_activated_cb, state );
-
- int lines = rofi_theme_get_integer ( WIDGET ( state->list_view ), "lines", config.menu_lines );
- listview_set_num_lines ( state->list_view, lines );
- listview_set_max_lines ( state->list_view, state->num_lines );
-
- box_add ( state->main_box, WIDGET ( state->list_view ), TRUE, 3 );
// filtered list
state->line_map = g_malloc0_n ( state->num_lines, sizeof ( unsigned int ) );
@@ -1609,12 +1682,12 @@ int rofi_view_error_dialog ( const char *msg, int markup )
state->menu_flags = MENU_ERROR_DIALOG;
state->finalize = process_result;
- state->main_window = container_create ( "window.box" );
- state->main_box = box_create ( "window.mainbox.message.box", BOX_VERTICAL );
- container_add ( state->main_window, WIDGET ( state->main_box ) );
+ state->main_window = box_create ( "window.box", BOX_VERTICAL );
+ box *box = box_create ( "window.mainbox.message.box", BOX_VERTICAL );
+ box_add ( state->main_window, WIDGET ( box ), TRUE, 0 );
state->text = textbox_create ( "window.mainbox.message.textbox", ( TB_AUTOHEIGHT | TB_WRAP ) + ( ( markup ) ? TB_MARKUP : 0 ),
NORMAL, ( msg != NULL ) ? msg : "" );
- box_add ( state->main_box, WIDGET ( state->text ), TRUE, 1 );
+ box_add ( box, WIDGET ( state->text ), TRUE, 1 );
// Make sure we enable fixed num lines when in normal window mode.
if ( ( CacheState.flags & MENU_NORMAL_WINDOW ) == MENU_NORMAL_WINDOW ) {
@@ -1745,12 +1818,12 @@ void rofi_view_set_overlay ( RofiViewState *state, const char *text )
// Within padding of window.
x_offset -= widget_padding_get_right ( WIDGET ( state->main_window ) );
// Within the border of widget.
- x_offset -= widget_padding_get_right ( WIDGET ( state->main_box ) );
- x_offset -= widget_padding_get_right ( WIDGET ( state->input_bar ) );
+ //x_offset -= widget_padding_get_right ( WIDGET ( state->main_box ) );
+ //x_offset -= widget_padding_get_right ( WIDGET ( state->input_bar ) );
x_offset -= widget_get_width ( WIDGET ( state->case_indicator ) );
x_offset -= widget_get_width ( WIDGET ( state->overlay ) );
int top_offset = widget_padding_get_top ( WIDGET ( state->main_window ) );
- top_offset += widget_padding_get_top ( WIDGET ( state->main_box ) );
+ //top_offset += widget_padding_get_top ( WIDGET ( state->main_box ) );
widget_move ( WIDGET ( state->overlay ), x_offset, top_offset );
// We want to queue a repaint.
rofi_view_queue_redraw ( );
diff --git a/source/widgets/box.c b/source/widgets/box.c
index a2fc6a95..f781f3db 100644
--- a/source/widgets/box.c
+++ b/source/widgets/box.c
@@ -50,6 +50,42 @@ struct _box
static void box_update ( widget *wid );
+
+static int box_get_desired_width ( widget *wid )
+{
+ box *b = (box *) wid;
+ int spacing = distance_get_pixel ( b->spacing, b->type == BOX_VERTICAL ? ORIENTATION_VERTICAL : ORIENTATION_HORIZONTAL );
+ int width = 0;
+ if ( b->type == BOX_HORIZONTAL ) {
+ int active_widgets = 0;
+ for ( GList *iter = g_list_first ( b->children ); iter != NULL; iter = g_list_next ( iter ) ) {
+ widget * child = (widget *) iter->data;
+ if ( !child->enabled ) {
+ continue;
+ }
+ active_widgets++;
+ if ( child->expand == TRUE ) {
+ width += widget_get_desired_width ( child );
+ continue;
+ }
+ width += widget_get_desired_width ( child );
+ }
+ if ( active_widgets > 0 ) {
+ width += ( active_widgets - 1 ) * spacing;
+ }
+ }
+ else {
+ for ( GList *iter = g_list_first ( b->children ); iter != NULL; iter = g_list_next ( iter ) ) {
+ widget * child = (widget *) iter->data;
+ if ( !child->enabled ) {
+ continue;
+ }
+ width = MAX ( widget_get_desired_width ( child ), width );
+ }
+ }
+ width += widget_padding_get_padding_width ( wid );
+ return width;
+}
static int box_get_desired_height ( widget *wid )
{
box *b = (box *) wid;
@@ -160,7 +196,9 @@ static void hori_calculate_size ( box *b )
for ( GList *iter = g_list_first ( b->children ); iter != NULL; iter = g_list_next ( iter ) ) {
widget * child = (widget *) iter->data;
if ( child->enabled && child->expand == FALSE ) {
- widget_resize ( child, child->w, rem_height );
+ widget_resize ( child,
+ widget_get_desired_width ( child ), //child->w,
+ rem_height );
}
}
b->max_size = 0;
@@ -263,7 +301,7 @@ void box_add ( box *box, widget *child, gboolean expand, int index )
child->index = rofi_theme_get_integer_exact ( child, "index", index );
child->parent = WIDGET ( box );
box->children = g_list_append ( box->children, (void *) child );
- box->children = g_list_sort ( box->children, box_sort_children );
+ //box->children = g_list_sort ( box->children, box_sort_children );
widget_update ( WIDGET ( box ) );
}
@@ -309,8 +347,11 @@ box * box_create ( const char *name, boxType type )
b->widget.update = box_update;
b->widget.find_mouse_target = box_find_mouse_target;
b->widget.get_desired_height = box_get_desired_height;
+ b->widget.get_desired_width = box_get_desired_width;
b->widget.enabled = rofi_theme_get_boolean ( WIDGET ( b ), "enabled", TRUE );
+ b->type = rofi_theme_get_boolean ( WIDGET (b), "vertical",b->type );
+
b->spacing = rofi_theme_get_distance ( WIDGET ( b ), "spacing", DEFAULT_SPACING );
return b;
}
diff --git a/source/widgets/listview.c b/source/widgets/listview.c
index 427a53c2..3398429a 100644
--- a/source/widgets/listview.c
+++ b/source/widgets/listview.c
@@ -37,9 +37,22 @@
#define DEFAULT_SPACING 2
+typedef enum {
+ LISTVIEW = 0,
+ BARVIEW = 1,
+} ViewType;
+
+typedef enum {
+ LEFT_TO_RIGHT = 0,
+ RIGHT_TO_LEFT = 1
+} MoveDirection;
+
struct _listview
{
widget widget;
+
+ ViewType type;
+
// RChanged
// Text needs to be repainted.
unsigned int rchanged;
@@ -78,11 +91,19 @@ struct _listview
listview_update_callback callback;
void *udata;
+ gboolean scrollbar_scroll;
+
xcb_timestamp_t last_click;
listview_mouse_activated_cb mouse_activated;
void *mouse_activated_data;
char *listview_name;
+
+ /** Barview */
+ struct {
+ MoveDirection direction;
+ unsigned int cur_visible;
+ } barview;
};
static int listview_get_desired_height ( widget *wid );
@@ -99,6 +120,22 @@ static void listview_free ( widget *wid )
widget_free ( WIDGET ( lv->scrollbar ) );
g_free ( lv );
}
+static unsigned int scroll_per_page_barview ( listview *lv )
+{
+ unsigned int offset = lv->last_offset;
+
+ // selected row is always visible.
+ // If selected is visible do not scroll.
+ if ( lv->selected < lv->last_offset ) {
+ offset = lv->selected;
+ lv->rchanged = TRUE;
+ } else if ( lv->selected >= (lv->last_offset + lv->barview.cur_visible ) ) {
+ offset = lv->selected;
+ lv->rchanged = TRUE;
+ }
+ return offset;
+
+}
static unsigned int scroll_per_page ( listview * lv )
{
int offset = 0;
@@ -154,6 +191,84 @@ static void update_element ( listview *lv, unsigned int tb, unsigned int index,
}
}
+static void barview_draw ( widget *wid, cairo_t *draw )
+{
+ unsigned int offset = 0;
+ listview *lv = (listview *) wid;
+ offset = scroll_per_page_barview ( lv );
+ lv->last_offset = offset;
+ int spacing_hori = distance_get_pixel ( lv->spacing, ORIENTATION_HORIZONTAL );
+
+ int left_offset = widget_padding_get_left ( wid );
+ int right_offset = lv->widget.w - widget_padding_get_right( wid );
+ int top_offset = widget_padding_get_top ( wid );
+ if ( lv->cur_elements > 0 ) {
+ // Set new x/y possition.
+ unsigned int max = MIN ( lv->cur_elements, lv->req_elements - offset );
+ if ( lv->rchanged ) {
+ int first = TRUE;
+ int width = lv->widget.w;
+ lv->barview.cur_visible = 0;
+ width -= widget_padding_get_padding_width ( wid );
+ if ( lv->barview.direction == LEFT_TO_RIGHT ) {
+ for ( unsigned int i = 0; i < max&& width > 0; i++ ) {
+ update_element ( lv, i, i + offset, TRUE );
+ int twidth = textbox_get_desired_width ( WIDGET(lv->boxes[i]));
+ if ( twidth >= width ) {
+ if ( ! first ) {
+ break;
+ }
+ twidth = width;
+ }
+ textbox_moveresize ( lv->boxes[i], left_offset, top_offset, twidth, lv->element_height );
+
+ widget_draw ( WIDGET ( lv->boxes[i] ), draw );
+ width -= twidth + spacing_hori;
+ left_offset += twidth + spacing_hori;
+ first = FALSE;
+ lv->barview.cur_visible++ ;
+ }
+ } else {
+ for ( unsigned int i = 0; i < lv->cur_elements && width > 0 && i <= offset; i++ ) {
+ update_element ( lv, i, offset-i, TRUE );
+ int twidth = textbox_get_desired_width ( WIDGET ( lv->boxes[i] ));
+ if ( twidth >= width ) {
+ if ( ! first ) {
+ break;
+ }
+ twidth = width;
+ }
+ right_offset -= twidth;
+ textbox_moveresize ( lv->boxes[i], right_offset, top_offset, twidth, lv->element_height );
+
+ widget_draw ( WIDGET ( lv->boxes[i] ), draw );
+ width -= twidth + spacing_hori;
+ right_offset -= spacing_hori;
+ first = FALSE;
+ lv->barview.cur_visible++ ;
+ }
+ offset -= lv->barview.cur_visible-1;
+ lv->last_offset = offset;
+ for ( unsigned int i = 0; i < (lv->barview.cur_visible/2); i++)
+ {
+ void * temp = lv->boxes[i];
+ int sw = lv->barview.cur_visible-i-1;
+ lv->boxes[i] = lv->boxes[sw];
+ lv->boxes[sw] = temp;
+ }
+
+ }
+ lv->rchanged = FALSE;
+ }
+ else {
+ for ( unsigned int i = 0; i < lv->barview.cur_visible; i++ ) {
+ update_element ( lv, i, i + offset, FALSE );
+ widget_draw ( WIDGET ( lv->boxes[i] ), draw );
+ }
+ }
+ }
+}
+
static void listview_draw ( widget *wid, cairo_t *draw )
{
unsigned int offset = 0;
@@ -218,9 +333,18 @@ static void listview_draw ( widget *wid, cairo_t *draw )
}
widget_draw ( WIDGET ( lv->scrollbar ), draw );
}
-
static WidgetTriggerActionResult listview_element_trigger_action ( widget *wid, MouseBindingListviewElementAction action, gint x, gint y, void *user_data );
+static void _listview_draw ( widget *wid, cairo_t *draw )
+{
+ listview *lv = (listview *)wid;
+ if ( lv->type == LISTVIEW )
+ {
+ listview_draw ( wid, draw );
+ } else {
+ barview_draw ( wid, draw );
+ }
+}
static void listview_recompute_elements ( listview *lv )
{
unsigned int newne = 0;
@@ -255,6 +379,9 @@ static void listview_recompute_elements ( listview *lv )
void listview_set_num_elements ( listview *lv, unsigned int rows )
{
+ if ( lv == NULL ) {
+ return;
+ }
lv->req_elements = rows;
listview_set_selected ( lv, lv->selected );
listview_recompute_elements ( lv );
@@ -273,6 +400,7 @@ void listview_set_selected ( listview *lv, unsigned int selected )
{
if ( lv && lv->req_elements > 0 ) {
lv->selected = MIN ( selected, lv->req_elements - 1 );
+ lv->barview.direction = LEFT_TO_RIGHT;
widget_queue_redraw ( WIDGET ( lv ) );
}
}
@@ -299,6 +427,10 @@ static void listview_resize ( widget *wid, short w, short h )
}
widget_resize ( WIDGET ( lv->scrollbar ), widget_get_width ( WIDGET ( lv->scrollbar ) ), height );
+ if ( lv->type == BARVIEW ) {
+ lv->max_elements = lv->menu_lines;
+ }
+
listview_recompute_elements ( lv );
widget_queue_redraw ( wid );
}
@@ -385,7 +517,7 @@ listview *listview_create ( const char *name, listview_update_callback cb, void
lv->listview_name = g_strdup ( name );
lv->widget.free = listview_free;
lv->widget.resize = listview_resize;
- lv->widget.draw = listview_draw;
+ lv->widget.draw = _listview_draw;
lv->widget.find_mouse_target = listview_find_mouse_target;
lv->widget.trigger_action = listview_trigger_action;
lv->widget.get_desired_height = listview_get_desired_height;
@@ -415,9 +547,14 @@ listview *listview_create ( const char *name, listview_update_callback cb, void
lv->fixed_num_lines = rofi_theme_get_boolean ( WIDGET ( lv ), "fixed-height", config.fixed_num_lines );
lv->dynamic = rofi_theme_get_boolean ( WIDGET ( lv ), "dynamic", TRUE );
lv->reverse = rofi_theme_get_boolean ( WIDGET ( lv ), "reverse", reverse );
- listview_set_show_scrollbar ( lv, rofi_theme_get_boolean ( WIDGET ( lv ), "scrollbar", FALSE ) );
lv->cycle = rofi_theme_get_boolean ( WIDGET ( lv ), "cycle", config.cycle );
+ lv->type = rofi_theme_get_boolean ( WIDGET (lv) , "barview", FALSE );
+ if ( lv->type == LISTVIEW ) {
+ listview_set_show_scrollbar ( lv, rofi_theme_get_boolean ( WIDGET ( lv ), "scrollbar", FALSE ) );
+ } else {
+ listview_set_show_scrollbar ( lv, FALSE );
+ }
return lv;
}
@@ -437,6 +574,7 @@ static void listview_nav_up_int ( listview *lv )
lv->selected = lv->req_elements;
}
lv->selected--;
+ lv->barview.direction = RIGHT_TO_LEFT;
widget_queue_redraw ( WIDGET ( lv ) );
}
static void listview_nav_down_int ( listview *lv )
@@ -448,7 +586,7 @@ static void listview_nav_down_int ( listview *lv )
return;
}
lv->selected = lv->selected < lv->req_elements - 1 ? MIN ( lv->req_elements - 1, lv->selected + 1 ) : 0;
-
+ lv->barview.direction = LEFT_TO_RIGHT;
widget_queue_redraw ( WIDGET ( lv ) );
}
@@ -482,6 +620,10 @@ void listview_nav_left ( listview *lv )
if ( lv == NULL ) {
return;
}
+ if ( lv->type == BARVIEW ){
+ listview_nav_up_int(lv);
+ return;
+ }
if ( lv->selected >= lv->max_rows ) {
lv->selected -= lv->max_rows;
widget_queue_redraw ( WIDGET ( lv ) );
@@ -492,6 +634,10 @@ void listview_nav_right ( listview *lv )
if ( lv == NULL ) {
return;
}
+ if ( lv->type == BARVIEW ){
+ listview_nav_down_int(lv);
+ return;
+ }
if ( ( lv->selected + lv->max_rows ) < lv->req_elements ) {
lv->selected += lv->max_rows;
widget_queue_redraw ( WIDGET ( lv ) );
@@ -516,6 +662,18 @@ static void listview_nav_page_prev_int ( listview *lv )
if ( lv == NULL ) {
return;
}
+ if ( lv->type == BARVIEW ){
+
+ if ( lv->last_offset == 0 ){
+ lv->selected = 0;
+ } else {
+ lv->selected = lv->last_offset-1;
+ }
+ lv->barview.direction = RIGHT_TO_LEFT;
+ widget_queue_redraw ( WIDGET ( lv ) );
+ return;
+ }
+
if ( lv->selected < lv->max_elements ) {
lv->selected = 0;
}
@@ -532,6 +690,14 @@ static void listview_nav_page_next_int ( listview *lv )
if ( lv->req_elements == 0 ) {
return;
}
+ if ( lv->type == BARVIEW ) {
+ unsigned int new = lv->last_offset+lv->barview.cur_visible;
+ lv->selected = MIN ( new, lv->req_elements-1);
+ lv->barview.direction = LEFT_TO_RIGHT;
+
+ widget_queue_redraw ( WIDGET ( lv ) );
+ return;
+ }
lv->selected += ( lv->max_elements );
if ( lv->selected >= lv->req_elements ) {
lv->selected = lv->req_elements - 1;
@@ -580,6 +746,9 @@ static int listview_get_desired_height ( widget *wid )
h = MIN ( lv->menu_lines, lv->max_displayed_lines );
}
}
+ if ( lv->type == BARVIEW ){
+ h = MIN ( h, 1 );
+ }
if ( h == 0 ) {
if ( lv->dynamic && !lv->fixed_num_lines ) {
// Hide widget fully.
diff --git a/source/widgets/textbox.c b/source/widgets/textbox.c
index ea6c4824..6c978b12 100644
--- a/source/widgets/textbox.c
+++ b/source/widgets/textbox.c
@@ -137,6 +137,7 @@ textbox* textbox_create_full ( WidgetType type, const char *name, TextboxFlags f
tb->widget.get_width = textbox_get_width;
tb->widget.get_height = _textbox_get_height;
tb->widget.get_desired_height = textbox_get_desired_height;
+ tb->widget.get_desired_width = textbox_get_desired_width;
tb->flags = flags;
tb->changed = FALSE;
@@ -175,7 +176,9 @@ textbox* textbox_creat