1
0
Fork 0
mirror of https://github.com/davatorium/rofi.git synced 2025-04-07 17:33:14 -04:00

Merge pull request from DaveDavenport/scrollbar

Scrollbar
This commit is contained in:
Dave Davenport 2015-09-04 20:58:39 +02:00
commit 465d027c1e
5 changed files with 256 additions and 91 deletions

View file

@ -30,6 +30,7 @@ rofi_SOURCES=\
source/rofi.c\
source/i3-support.c\
source/textbox.c\
source/scrollbar.c\
source/xrmoptions.c\
source/history.c\
config/config.c\
@ -47,6 +48,7 @@ rofi_SOURCES=\
include/xrmoptions.h\
include/history.h\
include/textbox.h\
include/scrollbar.h\
include/helper.h\
include/keyb.h\
include/x11-helper.h\
@ -154,13 +156,21 @@ test: ${bin_PROGRAMS}
.PHONY: test-x
test-x: ${bin_PROGRAMS}
echo "Test 1"
$(top_srcdir)/test/run_test.sh 123 $(top_builddir)/textbox_test $(top_builddir) $(top_srcdir)/doc/example.xresources
echo "Test 2"
$(top_srcdir)/test/run_test.sh 200 $(top_srcdir)/test/run_errormsg_test.sh $(top_builddir) $(top_srcdir)/doc/example.xresources
echo "Test 3"
$(top_srcdir)/test/run_test.sh 201 $(top_srcdir)/test/run_switchdialog_test.sh $(top_builddir) $(top_srcdir)/doc/example.xresources
echo "Test 4"
$(top_srcdir)/test/run_test.sh 202 $(top_srcdir)/test/run_dmenu_test.sh $(top_builddir) $(top_srcdir)/doc/example.xresources
echo "Test 5"
$(top_srcdir)/test/run_test.sh 203 $(top_srcdir)/test/run_dmenu_custom_test.sh $(top_builddir) $(top_srcdir)/doc/example.xresources
echo "Test 6"
$(top_srcdir)/test/run_test.sh 204 $(top_srcdir)/test/run_run_test.sh $(top_builddir) $(top_srcdir)/doc/example.xresources
echo "Test 7"
$(top_srcdir)/test/run_test.sh 205 $(top_srcdir)/test/run_script_test.sh $(top_builddir) $(top_srcdir)/doc/example.xresources
echo "End tests"
.PHONY: indent

93
include/scrollbar.h Normal file
View file

@ -0,0 +1,93 @@
#ifndef ROFI_SCROLLBAR_H
#define ROFI_SCROLLBAR_H
/**
* Internal structure for the scrollbar.
*/
typedef struct _scrollbar
{
Window window, parent;
short x, y, w, h;
GC gc;
unsigned int length;
unsigned int pos;
unsigned int pos_length;
} scrollbar;
/**
* @param parent the parent window
* @param vinfo The XVisualInfo to use when creating new window
* @param map The colormap to use for new window
* @param x The x coordinate (relative to parent) to position the new scrollbar
* @param y The y coordinate (relative to parent) to position the new scrollbar
* @param w The width of the scrollbar
* @param h The height of the scrollbar
*
* Create a new scrollbar
*
* @returns the scrollbar object.
*/
scrollbar *scrollbar_create ( Window parent, XVisualInfo *vinfo, Colormap map,
short x, short y, short w, short h );
/**
* @param sb scrollbar object
*
* Hide (unmap) the scrollbar.
*/
void scrollbar_hide ( scrollbar *sb );
/**
* @param sb scrollbar object
*
* Show (map) the scrollbar.
*/
void scrollbar_show ( scrollbar *sb );
/**
* @param sb scrollbar object
*
* Free the resources used by the scrollbar.
*/
void scrollbar_free ( scrollbar *sb );
/**
* @param sb scrollbar object
* @param pos_length new length
*
* set the length of the handle relative to the max value of bar.
*/
void scrollbar_set_handle_length ( scrollbar *sb, unsigned int pos_length );
/**
* @param sb scrollbar object
* @param pos new position
*
* set the position of the handle relative to the set max value of bar.
*/
void scrollbar_set_handle ( scrollbar *sb, unsigned int pos );
/**
* @param sb scrollbar object
* @param max the new max
*
* set the max value of the bar.
*/
void scrollbar_set_max_value ( scrollbar *sb, unsigned int max );
/**
* @param sb scrollbar object
*
* Draw the scrollbar, used after expose event or update
*/
void scrollbar_draw ( scrollbar *sb );
/**
* @param sb scrollbar object
* @param y clicked position
*
* Calculate the position of the click relative to the max value of bar
*/
unsigned int scrollbar_clicked ( scrollbar *sb, int y );
#endif // ROFI_SCROLLBAR_H

View file

@ -1,6 +1,5 @@
#ifndef ROFI_TEXTBOX_H
#define ROFI_TEXTBOX_H
#include <X11/Xft/Xft.h>
#include <pango/pango.h>
#include <pango/pangoxft.h>
@ -25,13 +24,13 @@ 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_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,
} TextboxFlags;

View file

@ -47,6 +47,7 @@
#include "rofi.h"
#include "helper.h"
#include "textbox.h"
#include "scrollbar.h"
#include "x11-helper.h"
#include "xrmoptions.h"
#include "dialogs/dialogs.h"
@ -128,45 +129,6 @@ static inline MainLoopEvent wait_for_xevent_or_timeout ( Display *display, int x
return ML_XEVENT;
}
static void menu_hide_arrow_text ( int filtered_lines, int selected, int max_elements,
textbox *arrowbox_top, textbox *arrowbox_bottom )
{
if ( arrowbox_top == NULL || arrowbox_bottom == NULL ) {
return;
}
int page = ( filtered_lines > 0 ) ? selected / max_elements : 0;
int npages = ( filtered_lines > 0 ) ? ( ( filtered_lines + max_elements - 1 ) / max_elements ) : 1;
if ( !( page != 0 && npages > 1 ) ) {
textbox_hide ( arrowbox_top );
}
if ( !( ( npages - 1 ) != page && npages > 1 ) ) {
textbox_hide ( arrowbox_bottom );
}
}
static void menu_set_arrow_text ( int filtered_lines, int selected, int max_elements,
textbox *arrowbox_top, textbox *arrowbox_bottom )
{
if ( arrowbox_top == NULL || arrowbox_bottom == NULL ) {
return;
}
if ( filtered_lines == 0 || max_elements == 0 ) {
return;
}
int page = ( filtered_lines > 0 ) ? selected / max_elements : 0;
int npages = ( filtered_lines > 0 ) ? ( ( filtered_lines + max_elements - 1 ) / max_elements ) : 1;
int entry = selected % max_elements;
if ( page != 0 && npages > 1 ) {
textbox_show ( arrowbox_top );
textbox_font ( arrowbox_top, ( entry != 0 ) ? NORMAL : HIGHLIGHT );
textbox_draw ( arrowbox_top );
}
if ( ( npages - 1 ) != page && npages > 1 ) {
textbox_show ( arrowbox_bottom );
textbox_font ( arrowbox_bottom, ( entry != ( max_elements - 1 ) ) ? NORMAL : HIGHLIGHT );
textbox_draw ( arrowbox_bottom );
}
}
/**
* Levenshtein Sorting.
@ -287,9 +249,8 @@ typedef struct MenuState
textbox *prompt_tb;
textbox *message_tb;
textbox *case_indicator;
textbox *arrowbox_top;
textbox *arrowbox_bottom;
textbox **boxes;
scrollbar *scrollbar;
int *distance;
int *line_map;
@ -325,8 +286,7 @@ static void menu_free_state ( MenuState *state )
textbox_free ( state->text );
textbox_free ( state->prompt_tb );
textbox_free ( state->case_indicator );
textbox_free ( state->arrowbox_bottom );
textbox_free ( state->arrowbox_top );
scrollbar_free ( state->scrollbar );
for ( unsigned int i = 0; i < state->max_elements; i++ ) {
textbox_free ( state->boxes[i] );
@ -698,25 +658,12 @@ static void menu_mouse_navigation ( MenuState *state, XButtonEvent *xbe )
}
return;
}
if ( xbe->window == state->arrowbox_top->window ) {
// Page up.
if ( state->selected < state->max_rows ) {
state->selected = 0;
}
else{
state->selected -= state->max_elements;
}
state->update = TRUE;
}
else if ( xbe->window == state->arrowbox_bottom->window ) {
// Page down.
state->selected += state->max_elements;
if ( state->selected >= state->filtered_lines ) {
state->selected = state->filtered_lines - 1;
}
state->update = TRUE;
}
else {
if ( state->scrollbar && state->scrollbar->window == xbe->window ) {
state->selected = scrollbar_clicked ( state->scrollbar, xbe->y );
state->update = TRUE;
return;
}
for ( unsigned int i = 0; config.sidebar_mode == TRUE && i < num_switchers; i++ ) {
if ( switchers[i]->tb->window == ( xbe->window ) ) {
*( state->selected_line ) = 0;
@ -791,6 +738,7 @@ static void menu_refilter ( MenuState *state, char **lines, menu_match_cb mmc, v
state->quit = TRUE;
}
scrollbar_set_max_value ( state->scrollbar, state->filtered_lines );
state->refilter = FALSE;
state->rchanged = TRUE;
}
@ -815,8 +763,9 @@ static void menu_draw ( MenuState *state )
state->cur_page = page;
state->rchanged = TRUE;
}
// Set the position.
scrollbar_set_handle ( state->scrollbar, page * state->max_elements );
}
// Re calculate the boxes and sizes, see if we can move this in the menu_calc*rowscolumns
// Get number of remaining lines to display.
unsigned int a_lines = MIN ( ( state->filtered_lines - offset ), state->max_elements );
@ -826,6 +775,9 @@ static void menu_draw ( MenuState *state )
state->max_rows ) / state->max_rows;
columns = MIN ( columns, state->columns );
// Update the handle length.
scrollbar_set_handle_length ( state->scrollbar, columns * state->max_rows );
scrollbar_draw ( state->scrollbar );
// Element width.
unsigned int element_width = state->w - ( 2 * ( config.padding ) );
if ( columns > 0 ) {
@ -879,9 +831,6 @@ static void menu_draw ( MenuState *state )
static void menu_update ( MenuState *state )
{
menu_hide_arrow_text ( state->filtered_lines, state->selected,
state->max_elements, state->arrowbox_top,
state->arrowbox_bottom );
textbox_draw ( state->case_indicator );
textbox_draw ( state->prompt_tb );
textbox_draw ( state->text );
@ -889,9 +838,6 @@ static void menu_update ( MenuState *state )
textbox_draw ( state->message_tb );
}
menu_draw ( state );
menu_set_arrow_text ( state->filtered_lines, state->selected,
state->max_elements, state->arrowbox_top,
state->arrowbox_bottom );
// Why do we need the special -1?
XDrawLine ( display, main_window, gc, 0,
state->line_height + ( config.padding ) * 1 + config.line_margin + 1,
@ -1076,22 +1022,11 @@ MenuReturn menu ( char **lines, unsigned int num_lines, char **input, char *prom
x_offset, y_offset,
state.element_width, element_height, NORMAL, "" );
}
// Arrows
state.arrowbox_top = textbox_create ( main_window, &vinfo, map, TB_AUTOWIDTH,
( config.padding ), ( config.padding ),
0, element_height, NORMAL,
"" );
state.arrowbox_bottom = textbox_create ( main_window, &vinfo, map, TB_AUTOWIDTH,
( config.padding ), ( config.padding ),
0, element_height, NORMAL,
"" );
textbox_move ( state.arrowbox_top,
state.w - config.padding - state.arrowbox_top->w,
state.top_offset );
textbox_move ( state.arrowbox_bottom,
state.w - config.padding - state.arrowbox_bottom->w,
state.top_offset + ( state.max_rows - 1 ) * ( element_height + config.line_margin ) );
state.scrollbar = scrollbar_create ( main_window, &vinfo, map, state.w - config.padding-config.line_margin- 8, state.top_offset,
config.line_margin+8, ( state.max_rows - 1 ) * ( element_height + config.line_margin ) + element_height );
scrollbar_set_max_value ( state.scrollbar, state.num_lines );
// filtered list
state.line_map = g_malloc0_n ( state.num_lines, sizeof ( int ) );
if ( config.levenshtein_sort ) {
@ -1127,6 +1062,7 @@ MenuReturn menu ( char **lines, unsigned int num_lines, char **input, char *prom
}
}
scrollbar_show ( state.scrollbar );
// Display it.
XMoveResizeWindow ( display, main_window, state.x, state.y, state.w, state.h );
XMapRaised ( display, main_window );

127
source/scrollbar.c Normal file
View file

@ -0,0 +1,127 @@
/**
* MIT/X11 License
* Modified (c) 2015 Qball Cow <qball@gmpclient.org>
*
* 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 <config.h>
#include <X11/X.h>
#include <X11/Xatom.h>
#include <X11/Xlib.h>
#include <X11/Xmd.h>
#include <X11/Xutil.h>
#include <X11/Xproto.h>
#include <X11/Xft/Xft.h>
#include <glib.h>
#include "scrollbar.h"
#include "rofi.h"
#include "x11-helper.h"
extern Display *display;
scrollbar *scrollbar_create ( Window parent, XVisualInfo *vinfo, Colormap map,
short x, short y, short w, short h )
{
scrollbar *sb = g_malloc0 ( sizeof ( scrollbar ) );
sb->parent = parent;
sb->x = x;
sb->y = y;
sb->w = MAX ( 1, w );
sb->h = MAX ( 1, h );
sb->length = 10;
sb->pos = 0;
sb->pos_length = 4;
XSetWindowAttributes attr;
attr.colormap = map;
attr.border_pixel = color_border ( display );
attr.background_pixel = color_background ( display );
sb->window = XCreateWindow ( display, sb->parent, sb->x, sb->y, sb->w, sb->h, 0, vinfo->depth,
InputOutput, vinfo->visual, CWColormap | CWBorderPixel | CWBackPixel, &attr );
XSelectInput ( display, sb->window, ExposureMask | ButtonPressMask );
sb->gc = XCreateGC ( display, sb->window, 0, 0 );
XSetForeground ( display, sb->gc, color_separator ( display ) );
//XSetFillStyle ( display, sb->gc, FillSolid);
// Create GC.
return sb;
}
void scrollbar_show ( scrollbar *sb )
{
XMapWindow ( display, sb->window );
}
void scrollbar_hide ( scrollbar *sb )
{
XUnmapWindow ( display, sb->window );
}
void scrollbar_free ( scrollbar *sb )
{
XFreeGC ( display, sb->gc );
XDestroyWindow ( display, sb->window );
g_free ( sb );
}
void scrollbar_set_max_value ( scrollbar *sb, unsigned int max )
{
sb->length = MAX ( 1, max );
}
void scrollbar_set_handle ( scrollbar *sb, unsigned int pos )
{
sb->pos = MIN ( sb->length, MAX ( 0, pos ) );
}
void scrollbar_set_handle_length ( scrollbar *sb, unsigned int pos_length )
{
sb->pos_length = MIN ( sb->length, MAX ( 1, pos_length ) );
}
void scrollbar_draw ( scrollbar *sb )
{
// Calculate position and size.
const short bh = sb->h - 0;
float sec = ( ( bh ) / (float) sb->length );
short height = sb->pos_length * sec;
short y = sb->pos * sec;
// Set max pos.
y = MIN ( y, bh - 2 );
// Never go out of bar.
height = MAX ( 2, height );
// Cap length;
height = MIN ( bh - y + 1, ( height ) );
// Redraw base window
XClearWindow ( display, sb->window );
// Paint the handle.
XFillRectangle ( display, sb->window, sb->gc, config.line_margin, y, sb->w-config.line_margin, height );
}
unsigned int scrollbar_clicked ( scrollbar *sb, int y )
{
const short bh = sb->h - 2;
float sec = ( ( bh ) / (float) sb->length );
unsigned int sel = y / sec;
return sel;
}