diff --git a/include/widgets/textbox.h b/include/widgets/textbox.h index 0a051ff4..2425eca8 100644 --- a/include/widgets/textbox.h +++ b/include/widgets/textbox.h @@ -46,16 +46,16 @@ 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_INDICATOR = 1 << 23, + 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_INDICATOR = 1 << 23, } TextboxFlags; /** * Flags indicating current state of the textbox. diff --git a/include/widgets/widget-internal.h b/include/widgets/widget-internal.h index 9e287cb3..d66a8d05 100644 --- a/include/widgets/widget-internal.h +++ b/include/widgets/widget-internal.h @@ -35,6 +35,8 @@ struct _widget /** update widget implementation function */ void ( *update )( struct _widget * ); + gboolean (*motion_notify)( struct _widget *, xcb_motion_notify_event_t * ); + /** widget clicked callback */ widget_clicked_cb clicked; /** user data for ::clicked callback */ diff --git a/include/widgets/widget.h b/include/widgets/widget.h index 2dd11aa4..4fa4d953 100644 --- a/include/widgets/widget.h +++ b/include/widgets/widget.h @@ -164,5 +164,14 @@ gboolean widget_clicked ( widget *wid, xcb_button_press_event_t *xbe ); */ void widget_set_clicked_handler ( widget *wid, widget_clicked_cb cb, void *udata ); +/** + * @param wid The widget handle + * @param xmd The motion notify object. + * + * Motion notify. + * @TODO make this like clicked with callback. + * returns TRUE when handled. + */ +gboolean widget_motion_notify ( widget *wid, xcb_motion_notify_event_t *xme ); /*@}*/ #endif // ROFI_WIDGET_H diff --git a/source/dialogs/ssh.c b/source/dialogs/ssh.c index 397893dc..f11ba3a1 100644 --- a/source/dialogs/ssh.c +++ b/source/dialogs/ssh.c @@ -198,7 +198,7 @@ static char **read_hosts_file ( char ** retv, unsigned int *length ) // Reading one line per time. while ( getline ( &buffer, &buffer_length, fd ) > 0 ) { // Evaluate one line. - unsigned int index = 0, ti = 0; + unsigned int index = 0, ti = 0; char *token = buffer; // Tokenize it. diff --git a/source/helper.c b/source/helper.c index 7fabbcea..773c8fc3 100644 --- a/source/helper.c +++ b/source/helper.c @@ -194,7 +194,7 @@ static GRegex * create_regex ( const char *input, int case_sensitive ) { #define R( s ) g_regex_new ( s, G_REGEX_OPTIMIZE | ( ( case_sensitive ) ? 0 : G_REGEX_CASELESS ), 0, NULL ) GRegex * retv = NULL; - gchar *r; + gchar *r; switch ( config.matching_method ) { case MM_GLOB: @@ -234,7 +234,7 @@ GRegex **tokenize ( const char *input, int case_sensitive ) } char *saveptr = NULL, *token; - GRegex **retv = NULL; + GRegex **retv = NULL; if ( !config.tokenize ) { retv = g_malloc0 ( sizeof ( GRegex* ) * 2 ); retv[0] = (GRegex *) create_regex ( input, case_sensitive ); diff --git a/source/rofi.c b/source/rofi.c index 391d8f21..46b81ae7 100644 --- a/source/rofi.c +++ b/source/rofi.c @@ -344,7 +344,7 @@ static int add_mode ( const char * token ) } else #endif // WINDOW_MODE - // SSh dialog + // SSh dialog if ( strcasecmp ( token, "ssh" ) == 0 ) { modi[num_modi] = &ssh_mode; num_modi++; diff --git a/source/view.c b/source/view.c index a8d027b7..566f81c0 100644 --- a/source/view.c +++ b/source/view.c @@ -698,7 +698,7 @@ static void update_callback ( textbox *t, unsigned int index, void *udata, TextB // Move into list view. textbox_text ( t, text ); - if ( state->tokens && config.show_match ) { + if ( state->tokens && config.show_match ) { PangoAttrList *list = textbox_get_pango_attributes ( t ); if ( list != NULL ) { pango_attr_list_ref ( list ); @@ -1229,6 +1229,12 @@ static void rofi_view_mainloop_iter ( RofiViewState *state, xcb_generic_event_t // xme->event_x >= state->scrollbar->widget.x && xme->event_x < ( state->scrollbar->widget.x + state->scrollbar->widget.w ) ) { // state->selected = scrollbar_clicked ( state->scrollbar, xme->event_y ); // } + xcb_motion_notify_event_t xme = *( (xcb_motion_notify_event_t *) ev ); + xme.event_x -= config.padding; + xme.event_y -= config.padding; + if ( widget_motion_notify ( WIDGET ( state->main_box ), &xme ) ) { + return; + } break; } case XCB_BUTTON_PRESS: diff --git a/source/widgets/box.c b/source/widgets/box.c index bb36f292..64fed08b 100644 --- a/source/widgets/box.c +++ b/source/widgets/box.c @@ -250,21 +250,39 @@ static gboolean box_clicked ( widget *wid, xcb_button_press_event_t *xbe, G_GNUC } return FALSE; } +static gboolean box_motion_notify ( widget *wid, xcb_motion_notify_event_t *xme ) +{ + box *b = (box *) wid; + for ( GList *iter = g_list_first ( b->children ); iter != NULL; iter = g_list_next ( iter ) ) { + widget * child = (widget *) iter->data; + if ( !child->enabled ) { + continue; + } + if ( widget_intersect ( child, xme->event_x, xme->event_y ) ) { + xcb_motion_notify_event_t rel = *xme; + rel.event_x -= child->x; + rel.event_y -= child->y; + return widget_motion_notify ( child, &rel ); + } + } + return FALSE; +} box * box_create ( boxType type, short x, short y, short w, short h ) { box *b = g_malloc0 ( sizeof ( box ) ); - b->type = type; - b->widget.x = x; - b->widget.y = y; - b->widget.w = w; - b->widget.h = h; - b->widget.draw = box_draw; - b->widget.free = box_free; - b->widget.resize = box_resize; - b->widget.update = box_update; - b->widget.clicked = box_clicked; - b->widget.enabled = TRUE; + b->type = type; + b->widget.x = x; + b->widget.y = y; + b->widget.w = w; + b->widget.h = h; + b->widget.draw = box_draw; + b->widget.free = box_free; + b->widget.resize = box_resize; + b->widget.update = box_update; + b->widget.clicked = box_clicked; + b->widget.motion_notify = box_motion_notify; + b->widget.enabled = TRUE; return b; } diff --git a/source/widgets/listview.c b/source/widgets/listview.c index ce6072e0..d5f0efe0 100644 --- a/source/widgets/listview.c +++ b/source/widgets/listview.c @@ -66,6 +66,8 @@ 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; @@ -100,7 +102,7 @@ static unsigned int scroll_per_page ( listview * lv ) lv->rchanged = TRUE; } // Set the position - scrollbar_set_handle ( lv->scrollbar, page * lv->max_elements ); + //scrollbar_set_handle ( lv->scrollbar, page * lv->max_elements ); } return offset; } @@ -119,7 +121,7 @@ static unsigned int scroll_continious ( listview *lv ) } } if ( offset != lv->cur_page ) { - scrollbar_set_handle ( lv->scrollbar, offset ); + //scrollbar_set_handle ( lv->scrollbar, offset ); lv->cur_page = offset; lv->rchanged = TRUE; } @@ -147,6 +149,7 @@ static void listview_draw ( widget *wid, cairo_t *draw ) else { offset = scroll_per_page ( lv ); } + scrollbar_set_handle ( lv->scrollbar, lv->selected ); lv->last_offset = offset; if ( lv->cur_elements > 0 && lv->max_rows > 0 ) { cairo_save ( draw ); @@ -263,11 +266,13 @@ static gboolean listview_scrollbar_clicked ( widget *sb, xcb_button_press_event_ static gboolean listview_clicked ( widget *wid, xcb_button_press_event_t *xce, G_GNUC_UNUSED void *udata ) { listview *lv = (listview *) wid; + lv->scrollbar_scroll = FALSE; if ( widget_enabled ( WIDGET ( lv->scrollbar ) ) && widget_intersect ( WIDGET ( lv->scrollbar ), xce->event_x, xce->event_y ) ) { // Forward to handler of scrollbar. xcb_button_press_event_t xce2 = *xce; - xce->event_x -= widget_get_x_pos ( WIDGET ( lv->scrollbar ) ); - xce->event_y -= widget_get_y_pos ( WIDGET ( lv->scrollbar ) ); + xce->event_x -= widget_get_x_pos ( WIDGET ( lv->scrollbar ) ); + xce->event_y -= widget_get_y_pos ( WIDGET ( lv->scrollbar ) ); + lv->scrollbar_scroll = TRUE; return widget_clicked ( WIDGET ( lv->scrollbar ), &xce2 ); } // Handle the boxes. @@ -291,14 +296,28 @@ static gboolean listview_clicked ( widget *wid, xcb_button_press_event_t *xce, G return FALSE; } +static gboolean listview_motion_notify ( widget *wid, xcb_motion_notify_event_t *xme ) +{ + listview *lv = (listview *) wid; + if ( widget_enabled ( WIDGET ( lv->scrollbar ) ) && lv->scrollbar_scroll ) { + xcb_motion_notify_event_t xle = *xme; + xle.event_x -= wid->x; + xle.event_y -= wid->y; + widget_motion_notify ( WIDGET ( lv->scrollbar ), &xle ); + return TRUE; + } + + return FALSE; +} listview *listview_create ( listview_update_callback cb, void *udata, unsigned int eh ) { listview *lv = g_malloc0 ( sizeof ( listview ) ); - lv->widget.free = listview_free; - lv->widget.resize = listview_resize; - lv->widget.draw = listview_draw; - lv->widget.clicked = listview_clicked; - lv->widget.enabled = TRUE; + lv->widget.free = listview_free; + lv->widget.resize = listview_resize; + lv->widget.draw = listview_draw; + lv->widget.clicked = listview_clicked; + lv->widget.motion_notify = listview_motion_notify; + lv->widget.enabled = TRUE; lv->scrollbar = scrollbar_create ( 0, 0, 4, 0 ); widget_set_clicked_handler ( WIDGET ( lv->scrollbar ), listview_scrollbar_clicked, lv ); diff --git a/source/widgets/scrollbar.c b/source/widgets/scrollbar.c index 0d06145f..b6f3ab52 100644 --- a/source/widgets/scrollbar.c +++ b/source/widgets/scrollbar.c @@ -31,6 +31,7 @@ static void scrollbar_draw ( widget *, cairo_t * ); static void scrollbar_free ( widget * ); +static gboolean scrollbar_motion_notify ( widget *wid, xcb_motion_notify_event_t *xme ); scrollbar *scrollbar_create ( short x, short y, short w, short h ) { @@ -41,8 +42,9 @@ scrollbar *scrollbar_create ( short x, short y, short w, short h ) sb->widget.w = MAX ( 1, w ); sb->widget.h = MAX ( 1, h ); - sb->widget.draw = scrollbar_draw; - sb->widget.free = scrollbar_free; + sb->widget.draw = scrollbar_draw; + sb->widget.free = scrollbar_free; + sb->widget.motion_notify = scrollbar_motion_notify; sb->length = 10; sb->pos = 0; @@ -84,22 +86,27 @@ static void scrollbar_draw ( widget *wid, cairo_t *draw ) { scrollbar *sb = (scrollbar *) wid; // Calculate position and size. - const short bh = sb->widget.h - 0; - float sec = ( ( bh ) / (float) sb->length ); + const short bh = sb->widget.h; + float sec = ( ( bh ) / (float) ( sb->length + sb->pos_length - 2 ) ); short height = sb->pos_length * sec; short y = sb->pos * sec; // Set max pos. - y = MIN ( y, bh - 2 ); + y = MIN ( y, bh ); // Never go out of bar. height = MAX ( 2, height ); // Cap length; - height = MIN ( bh - y + 1, ( height ) ); - // Redraw base window color_separator ( draw ); cairo_rectangle ( draw, sb->widget.x, sb->widget.y + y, sb->widget.w, height ); cairo_fill ( draw ); } +static gboolean scrollbar_motion_notify ( widget *wid, xcb_motion_notify_event_t *xme ) +{ + xcb_button_press_event_t xle; + xle.event_x = xme->event_x; + xle.event_y = xme->event_y; + return widget_clicked ( WIDGET ( wid ), &xle ); +} // TODO // This should behave more like a real scrollbar. @@ -107,10 +114,12 @@ unsigned int scrollbar_clicked ( const scrollbar *sb, int y ) { if ( sb != NULL ) { if ( y >= sb->widget.y && y <= ( sb->widget.y + sb->widget.h ) ) { - y -= sb->widget.y; - y = MIN ( MAX ( 0, y ), sb->widget.h ); - const short bh = sb->widget.h; - float sec = ( ( bh ) / (float) sb->length ); + const short bh = sb->widget.h; + float sec = ( ( bh ) / (float) ( sb->length + sb->pos_length ) ); + unsigned int half_handle = MAX ( 1, sec * ( sb->pos_length / 2.0 ) ); + y -= sb->widget.y + half_handle; + y = MIN ( MAX ( 0, y ), sb->widget.h - 2 * half_handle ); + unsigned int sel = y / sec; return MIN ( sel, sb->length - 1 ); } diff --git a/source/widgets/widget.c b/source/widgets/widget.c index 0aee2e70..729619e6 100644 --- a/source/widgets/widget.c +++ b/source/widgets/widget.c @@ -154,3 +154,12 @@ void widget_set_clicked_handler ( widget *wid, widget_clicked_cb cb, void *udata wid->clicked_cb_data = udata; } } + +gboolean widget_motion_notify ( widget *wid, xcb_motion_notify_event_t *xme ) +{ + if ( wid && wid->motion_notify ) { + wid->motion_notify ( wid, xme ); + } + + return FALSE; +} diff --git a/test/helper-test.c b/test/helper-test.c index 4ed00128..ad88a0cf 100644 --- a/test/helper-test.c +++ b/test/helper-test.c @@ -82,36 +82,36 @@ int main ( int argc, char ** argv ) * Quick converision check. */ { - char *str = rofi_latin_to_utf8_strdup ( "\xA1\xB5", 2); - TASSERT ( g_utf8_collate ( str, "¡µ") == 0 ); - g_free(str); + char *str = rofi_latin_to_utf8_strdup ( "\xA1\xB5", 2 ); + TASSERT ( g_utf8_collate ( str, "¡µ" ) == 0 ); + g_free ( str ); } - + { - char *str = rofi_force_utf8("Valid utf8", 10); - TASSERT ( g_utf8_collate ( str, "Valid utf8") == 0 ); - g_free(str); + char *str = rofi_force_utf8 ( "Valid utf8", 10 ); + TASSERT ( g_utf8_collate ( str, "Valid utf8" ) == 0 ); + g_free ( str ); char in[] = "Valid utf8 until \xc3\x28 we continue here"; TASSERT ( g_utf8_validate ( in, -1, NULL ) == FALSE ); - str = rofi_force_utf8(in, strlen(in)); + str = rofi_force_utf8 ( in, strlen ( in ) ); TASSERT ( g_utf8_validate ( str, -1, NULL ) == TRUE ); - TASSERT ( g_utf8_collate ( str, "Valid utf8 until �( we continue here") == 0 ); - g_free(str); - } + TASSERT ( g_utf8_collate ( str, "Valid utf8 until �( we continue here" ) == 0 ); + g_free ( str ); + } // Pid test. // Tests basic functionality of writing it, locking, seeing if I can write same again // And close/reopen it again. { - const char *path = "/tmp/rofi-test.pid"; - TASSERT( create_pid_file ( NULL ) == -1 ); - int fd = create_pid_file ( path ); - TASSERT( fd >= 0 ); - int fd2 = create_pid_file ( path ); - TASSERT ( fd2 < 0 ); + const char *path = "/tmp/rofi-test.pid"; + TASSERT ( create_pid_file ( NULL ) == -1 ); + int fd = create_pid_file ( path ); + TASSERT ( fd >= 0 ); + int fd2 = create_pid_file ( path ); + TASSERT ( fd2 < 0 ); remove_pid_file ( fd ); fd = create_pid_file ( path ); - TASSERT( fd >= 0 ); + TASSERT ( fd >= 0 ); remove_pid_file ( fd ); } } diff --git a/test/scrollbar-test.c b/test/scrollbar-test.c index 9511de63..ebdbeac3 100644 --- a/test/scrollbar-test.c +++ b/test/scrollbar-test.c @@ -52,24 +52,24 @@ int main ( G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv ) TASSERTE ( sb->pos_length, 1 ); unsigned int cl = scrollbar_clicked ( sb, 10 ); - TASSERTE ( cl, 1000); + TASSERTE ( cl, 900); cl = scrollbar_clicked ( sb, 20 ); - TASSERTE ( cl, 2000); + TASSERTE ( cl, 1900); cl = scrollbar_clicked ( sb, 0 ); TASSERTE ( cl, 0); cl = scrollbar_clicked ( sb, 99 ); - TASSERTE ( cl, 9900); + TASSERTE ( cl, 9800); scrollbar_set_max_value ( sb, 100 ); - for ( unsigned int i = 0; i < 100; i++ ){ + for ( unsigned int i = 1; i < 99; i++ ){ cl = scrollbar_clicked ( sb, i ); - TASSERTE ( cl, i); + TASSERTE ( cl, i-1); } scrollbar_set_max_value ( sb, 200 ); - for ( unsigned int i = 0; i < 100; i++ ){ + for ( unsigned int i = 1; i < 100; i++ ){ cl = scrollbar_clicked ( sb, i ); - TASSERTE ( cl, i*2); + TASSERTE ( cl, i*2-2); } widget_free( WIDGET (sb ) ); } diff --git a/test/textbox-test.c b/test/textbox-test.c index fc5209ca..3fa33344 100644 --- a/test/textbox-test.c +++ b/test/textbox-test.c @@ -88,9 +88,9 @@ int main ( G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv ) TASSERT ( strcmp ( box->text, "tesb" ) == 0 ); textbox_keybinding ( box, MOVE_CHAR_BACK ); TASSERT ( box->cursor == 3 ); - textbox_keybinding ( box, MOVE_CHAR_FORWARD); + textbox_keybinding ( box, MOVE_CHAR_FORWARD ); TASSERT ( box->cursor == 4 ); - textbox_keybinding ( box, MOVE_CHAR_FORWARD); + textbox_keybinding ( box, MOVE_CHAR_FORWARD ); TASSERT ( box->cursor == 4 ); // Cursor after delete section. textbox_delete ( box, 0, 1 ); @@ -122,32 +122,31 @@ int main ( G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv ) TASSERT ( strcmp ( box->text, "aapmies" ) == 0 ); TASSERT ( box->cursor == 5 ); - - textbox_text ( box, "aap noot mies"); + textbox_text ( box, "aap noot mies" ); textbox_cursor ( box, 8 ); textbox_keybinding ( box, REMOVE_WORD_BACK ); - TASSERT ( box->cursor == 4); - TASSERT ( strcmp ( box->text, "aap mies") == 0 ); + TASSERT ( box->cursor == 4 ); + TASSERT ( strcmp ( box->text, "aap mies" ) == 0 ); textbox_keybinding ( box, REMOVE_TO_EOL ); - TASSERT ( box->cursor == 4); - TASSERT ( strcmp ( box->text, "aap ") == 0 ); - textbox_text ( box, "aap noot mies"); + TASSERT ( box->cursor == 4 ); + TASSERT ( strcmp ( box->text, "aap " ) == 0 ); + textbox_text ( box, "aap noot mies" ); textbox_cursor ( box, 8 ); textbox_keybinding ( box, REMOVE_WORD_FORWARD ); - TASSERT ( strcmp ( box->text, "aap noot") == 0 ); + TASSERT ( strcmp ( box->text, "aap noot" ) == 0 ); textbox_keybinding ( box, MOVE_FRONT ); - TASSERT ( box->cursor == 0); + TASSERT ( box->cursor == 0 ); textbox_keybinding ( box, CLEAR_LINE ); - TASSERT ( strcmp ( box->text, "") == 0 ); - textbox_text ( box, "aap noot mies"); - textbox_keybinding ( box, MOVE_END); + TASSERT ( strcmp ( box->text, "" ) == 0 ); + textbox_text ( box, "aap noot mies" ); + textbox_keybinding ( box, MOVE_END ); textbox_keybinding ( box, MOVE_WORD_BACK ); - TASSERT ( box->cursor == 9); + TASSERT ( box->cursor == 9 ); textbox_keybinding ( box, MOVE_WORD_BACK ); - TASSERT ( box->cursor == 4); + TASSERT ( box->cursor == 4 ); textbox_keybinding ( box, REMOVE_TO_SOL ); - TASSERT ( strcmp ( box->text, "noot mies") == 0 ); - TASSERT ( box->cursor == 0); + TASSERT ( strcmp ( box->text, "noot mies" ) == 0 ); + TASSERT ( box->cursor == 0 ); textbox_font ( box, HIGHLIGHT ); //textbox_draw ( box, draw );