summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.am2
-rw-r--r--include/view-internal.h2
-rw-r--r--include/widgets/widget-internal.h9
-rw-r--r--include/widgets/window.h37
-rw-r--r--lexer/theme-lexer.l2
-rw-r--r--source/view.c75
-rw-r--r--source/widgets/box.c9
-rw-r--r--source/widgets/listview.c6
-rw-r--r--source/widgets/widget.c58
-rw-r--r--source/widgets/window.c160
10 files changed, 316 insertions, 44 deletions
diff --git a/Makefile.am b/Makefile.am
index 5b9389ae..e4fd6ecc 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -31,6 +31,7 @@ rofi_SOURCES=\
source/history.c\
source/theme.c\
source/widgets/box.c\
+ source/widgets/window.c\
source/widgets/widget.c\
source/widgets/textbox.c\
source/widgets/listview.c\
@@ -62,6 +63,7 @@ rofi_SOURCES=\
include/history.h\
include/theme.h\
include/widgets/box.h\
+ include/widgets/window.h\
include/widgets/widget.h\
include/widgets/widget-internal.h\
include/widgets/textbox.h\
diff --git a/include/view-internal.h b/include/view-internal.h
index 14f8bb06..9438c22c 100644
--- a/include/view-internal.h
+++ b/include/view-internal.h
@@ -1,5 +1,6 @@
#ifndef ROFI_VIEW_INTERNAL_H
#define ROFI_VIEW_INTERNAL_H
+#include "widgets/window.h"
#include "widgets/widget.h"
#include "widgets/textbox.h"
#include "widgets/separator.h"
@@ -24,6 +25,7 @@ struct RofiViewState
/** Flag indicating if view needs to be refiltered. */
int refilter;
+ window *main_window;
/** Main #box widget holding different elements. */
box *main_box;
/** #box widget packing the input bar widgets. */
diff --git a/include/widgets/widget-internal.h b/include/widgets/widget-internal.h
index 940738fc..efb43f78 100644
--- a/include/widgets/widget-internal.h
+++ b/include/widgets/widget-internal.h
@@ -57,4 +57,13 @@ struct _widget
void widget_init ( widget *widget , const char *name, const char *class_name );
void widget_set_state ( widget *widget, const char *state );
+
+int widget_padding_get_left ( const widget *wid );
+int widget_padding_get_right ( const widget *wid );
+int widget_padding_get_top ( const widget *wid );
+int widget_padding_get_bottom ( const widget *wid );
+int widget_padding_get_remaining_width ( const widget *wid );
+int widget_padding_get_remaining_height ( const widget *wid );
+int widget_padding_get_padding_height ( const widget *wid );
+int widget_padding_get_padding_width ( const widget *wid );
#endif // WIDGET_INTERNAL_H
diff --git a/include/widgets/window.h b/include/widgets/window.h
new file mode 100644
index 00000000..6d8a90a1
--- /dev/null
+++ b/include/widgets/window.h
@@ -0,0 +1,37 @@
+#ifndef ROFI_WINDOW_H
+#define ROFI_WINDOW_H
+
+#include "widget.h"
+
+/**
+ * @defgroup window window
+ * @ingroup widget
+ *
+ *
+ * @{
+ */
+
+/**
+ * Abstract handle to the window widget internal state.
+ */
+typedef struct _window window;
+
+/**
+ * @param name The name of the widget.
+ * @param type The packing direction of the newly created window.
+ *
+ * @returns a newly created window, free with #widget_free
+ */
+window * window_create ( const char *name );
+
+/**
+ * @param window Handle to the window widget.
+ * @param child Handle to the child widget to pack.
+ *
+ * Add a widget to the window.
+ */
+void window_add ( window *window, widget *child );
+
+int window_get_border_width ( const window *window );
+/*@}*/
+#endif // ROFI_WINDOW_H
diff --git a/lexer/theme-lexer.l b/lexer/theme-lexer.l
index 0ae8315f..01732733 100644
--- a/lexer/theme-lexer.l
+++ b/lexer/theme-lexer.l
@@ -23,7 +23,7 @@ WHITESPACE [[:space:]]
WORD [[:alnum:]-]+
STRING [[:print:]]+
HEX [[:xdigit:]]
-NUMBER [[:digit:]]
+NUMBER [[:digit:]-]
%x PROPERTIES
%x NAMESTR
diff --git a/source/view.c b/source/view.c
index 6238b470..bd8c4f2e 100644
--- a/source/view.c
+++ b/source/view.c
@@ -298,9 +298,7 @@ static void rofi_view_window_update_size ( RofiViewState * state )
CacheState.edit_draw = cairo_create ( CacheState.edit_surf );
// Should wrap main window in a widget.
- int width = state->width - 2*state->border - state->pad.left - state->pad.right;
- int height = state->height - 2*state->border - state->pad.top- state->pad.bottom;
- widget_resize ( WIDGET ( state->main_box ), width, height );
+ widget_resize ( WIDGET ( state->main_window ), state->width, state->height );
}
static gboolean rofi_view_reload_idle ( G_GNUC_UNUSED gpointer data )
@@ -388,7 +386,7 @@ void rofi_view_free ( RofiViewState *state )
}
// Do this here?
// Wait for final release?
- widget_free ( WIDGET ( state->main_box ) );
+ widget_free ( WIDGET ( state->main_window ) );
widget_free ( WIDGET ( state->overlay ) );
g_free ( state->line_map );
@@ -775,7 +773,7 @@ static void update_callback ( textbox *t, unsigned int index, void *udata, TextB
void rofi_view_update ( RofiViewState *state )
{
- if ( !widget_need_redraw ( WIDGET ( state->main_box ) ) && !widget_need_redraw ( WIDGET ( state->overlay ) ) ) {
+ if ( !widget_need_redraw ( WIDGET ( state->main_window ) ) && !widget_need_redraw ( WIDGET ( state->overlay ) ) ) {
return;
}
TICK ();
@@ -792,36 +790,17 @@ void rofi_view_update ( RofiViewState *state )
}
cairo_paint ( d );
cairo_set_operator ( d, CAIRO_OPERATOR_OVER );
- color_background ( d );
- rofi_theme_get_color ( "@window" , "window" , NULL, "background", d );
- cairo_paint ( d );
}
else {
- // Paint the background.
- color_background ( d );
- rofi_theme_get_color ( "@window", "window" , NULL, "background", d );
+ // Paint the background transparent.
+ cairo_set_source_rgba ( d, 0,0,0,0.0);
cairo_paint ( d );
}
TICK_N ( "Background" );
- color_border ( d );
- rofi_theme_get_color ( "@window", "window" , NULL, "foreground", d );
-
- int bw = rofi_theme_get_integer ( "@window", "window", NULL, "border-width" , config.menu_bw);
- if ( bw > 0 ) {
- cairo_save ( d );
- cairo_set_line_width ( d, bw );
- cairo_rectangle ( d,
- bw / 2.0,
- bw / 2.0,
- state->width - bw,
- state->height - bw );
- cairo_stroke ( d );
- cairo_restore ( d );
- }
// Always paint as overlay over the background.
cairo_set_operator ( d, CAIRO_OPERATOR_OVER );
- widget_draw ( WIDGET ( state->main_box ), d );
+ widget_draw ( WIDGET ( state->main_window ), d );
if ( state->overlay ) {
widget_draw ( WIDGET ( state->overlay ), d );
@@ -886,7 +865,7 @@ static void rofi_view_mouse_navigation ( RofiViewState *state, xcb_button_press_
xcb_button_press_event_t rel = *xbe;
rel.event_x -= state->pad.left;
rel.event_y -= state->pad.top;
- if ( widget_clicked ( WIDGET ( state->main_box ), &rel ) ) {
+ if ( widget_clicked ( WIDGET ( state->main_window ), &rel ) ) {
return;
}
}
@@ -1278,9 +1257,7 @@ void rofi_view_itterrate ( RofiViewState *state, xcb_generic_event_t *ev, xkb_st
CacheState.edit_surf = cairo_xcb_surface_create ( xcb->connection, CacheState.edit_pixmap, visual, state->width, state->height );
CacheState.edit_draw = cairo_create ( CacheState.edit_surf );
- int width = state->width - 2*state->border - state->pad.left - state->pad.right;
- int height = state->height - 2*state->border - state->pad.top- state->pad.bottom;
- widget_resize ( WIDGET ( state->main_box ), width, height );
+ widget_resize ( WIDGET ( state->main_window ), state->width, state->height );
}
}
break;
@@ -1303,7 +1280,7 @@ void rofi_view_itterrate ( RofiViewState *state, xcb_generic_event_t *ev, xkb_st
xcb_motion_notify_event_t xme = *( (xcb_motion_notify_event_t *) ev );
xme.event_x -= state->pad.left;
xme.event_y -= state->pad.top;
- if ( widget_motion_notify ( WIDGET ( state->main_box ), &xme ) ) {
+ if ( widget_motion_notify ( WIDGET ( state->main_window ), &xme ) ) {
return;
}
break;
@@ -1377,13 +1354,33 @@ static int rofi_view_calculate_height ( RofiViewState *state )
}
if ( state->filtered_lines == 0 && !config.fixed_num_lines ) {
widget_disable ( WIDGET ( state->input_bar_separator ) );
+ widget_disable ( WIDGET ( state->list_view) );
}
else {
widget_enable ( WIDGET ( state->input_bar_separator ) );
+ widget_enable ( WIDGET ( state->list_view) );
}
height = listview_get_desired_height ( state->list_view );
+ // Why not a factor 2 here?
+ height += window_get_border_width ( state->main_window );
height += box_get_fixed_pixels ( state->main_box );
- height += 2 * state->border +state->pad.top+state->pad.bottom;
+ // How to merge this....
+ int perc =0;
+ widget *main_window = WIDGET ( state->main_window );
+ if ( main_window->pad.top >= 0 ){
+ height += main_window->pad.top;
+ } else {
+ perc -= main_window->pad.top;
+ }
+ if ( main_window->pad.bottom >= 0 ){
+ height += main_window->pad.bottom;
+ } else {
+ perc -= main_window->pad.bottom;
+ }
+ if ( perc > 0){
+ height = (100*height)/(100-perc);
+ }
+ printf("listview: %d\n", listview_get_desired_height ( state->list_view ));
return height;
}
@@ -1438,8 +1435,6 @@ RofiViewState *rofi_view_create ( Mode *sw,
state->pad = (Padding){config.padding,config.padding, config.padding, config.padding, FALSE};
state->pad = rofi_theme_get_padding ( "@window", "window", NULL, "padding", state->pad);
- //state->border = rofi_theme_get_integer ("@window", "window", NULL, "padding" , config.padding );
- state->border += rofi_theme_get_integer ("@window", "window", NULL, "border-width" , config.menu_bw);
// Request the lines to show.
state->num_lines = mode_get_num_entries ( sw );
@@ -1449,8 +1444,9 @@ RofiViewState *rofi_view_create ( Mode *sw,
// Get active monitor size.
TICK_N ( "Get active monitor" );
+ state->main_window = window_create ( "window" );
state->main_box = box_create ( "mainbox.box", BOX_VERTICAL );
- widget_move ( WIDGET ( state->main_box ), state->border+state->pad.left, state->border+state->pad.top );
+ window_add ( state->main_window, WIDGET ( state->main_box ) );
// we need this at this point so we can get height.
rofi_view_calculate_window_and_element_width ( state );
@@ -1541,7 +1537,7 @@ RofiViewState *rofi_view_create ( Mode *sw,
rofi_view_update ( state );
xcb_map_window ( xcb->connection, CacheState.main_window );
- widget_queue_redraw ( WIDGET ( state->main_box ) );
+ widget_queue_redraw ( WIDGET ( state->main_window ) );
xcb_flush ( xcb->connection );
if ( xcb->sncontext != NULL ) {
sn_launchee_context_complete ( xcb->sncontext );
@@ -1557,11 +1553,12 @@ int rofi_view_error_dialog ( const char *msg, int markup )
state->finalize = process_result;
state->pad = (Padding){config.padding,config.padding, config.padding, config.padding, FALSE};
state->pad = rofi_theme_get_padding ( "@window", "window", NULL, "padding", state->pad);
- // state->border = rofi_theme_get_integer ( "@window", "window", NULL, "padding" , config.padding );
state->border += rofi_theme_get_integer ( "@window", "window", NULL, "border-width" , config.menu_bw);
rofi_view_calculate_window_and_element_width ( state );
+ state->main_window = window_create ( "window" );
state->main_box = box_create ( "mainbox.box", BOX_VERTICAL);
+ window_add ( state->main_window, WIDGET ( state->main_box ) );
widget_move ( WIDGET ( state->main_box ), state->border+state->pad.left, state->border+state->pad.top );
state->text = textbox_create ( "message", ( TB_AUTOHEIGHT | TB_WRAP ) + ( ( markup ) ? TB_MARKUP : 0 ),
NORMAL, ( msg != NULL ) ? msg : "" );
@@ -1579,7 +1576,7 @@ int rofi_view_error_dialog ( const char *msg, int markup )
// Display it.
xcb_map_window ( xcb->connection, CacheState.main_window );
- widget_queue_redraw ( WIDGET ( state->main_box ) );
+ widget_queue_redraw ( WIDGET ( state->main_window ) );
if ( xcb->sncontext != NULL ) {
sn_launchee_context_complete ( xcb->sncontext );
diff --git a/source/widgets/box.c b/source/widgets/box.c
index e1b8e92a..742926a3 100644
--- a/source/widgets/box.c
+++ b/source/widgets/box.c
@@ -75,7 +75,10 @@ static void vert_calculate_size ( box *b )
}
int rem_width = b->widget.w - b->widget.pad.left-b->widget.pad.right;
int rem_height = b->widget.h - b->widget.pad.top-b->widget.pad.bottom;
- b->max_size += MAX ( 0, ( ( active_widgets - 1 ) * b->spacing ) );
+ if ( active_widgets > 0 ){
+ b->max_size += ( active_widgets - 1 ) * b->spacing;
+ }
+ printf("%d %d\n", rem_height, b->max_size);
if ( b->max_size > rem_height ) {
g_log ( LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Widgets to large (height) for box: %d %d", b->max_size, b->widget.h );
return;
@@ -107,6 +110,7 @@ static void vert_calculate_size ( box *b )
}
rem -= expanding_widgets_size;
index++;
+ b->max_size += widget_padding_get_padding_height ( child);
}
else if ( child->end ) {
bottom -= widget_get_height ( child );
@@ -122,6 +126,7 @@ static void vert_calculate_size ( box *b )
}
}
}
+ b->max_size += b->widget.pad.top+b->widget.pad.bottom;
}
static void hori_calculate_size ( box *b )
{
@@ -175,6 +180,7 @@ static void hori_calculate_size ( box *b )
}
rem -= expanding_widgets_size;
index++;
+ b->max_size += widget_padding_get_padding_width ( child);
}
else if ( child->end ) {
right -= widget_get_width ( child );
@@ -190,6 +196,7 @@ static void hori_calculate_size ( box *b )
}
}
}
+ b->max_size += b->widget.pad.left+b->widget.pad.right;
}
static void box_draw ( widget *wid, cairo_t *draw )
diff --git a/source/widgets/listview.c b/source/widgets/listview.c
index 0e2b24b3..cf245145 100644
--- a/source/widgets/listview.c
+++ b/source/widgets/listview.c
@@ -248,7 +248,7 @@ static void listview_resize ( widget *wid, short w, short h )
listview *lv = (listview *) wid;
lv->widget.w = MAX ( 0, w );
lv->widget.h = MAX ( 0, h );
- int height = lv->widget.h - lv->widget.pad.top-lv->widget.pad.bottom;
+ int height = lv->widget.h - lv->widget.pad.top-lv->widget.pad.bottom;
lv->max_rows = ( lv->spacing + height ) / ( lv->element_height + lv->spacing );
lv->max_elements = lv->max_rows * lv->menu_columns;
@@ -451,7 +451,7 @@ void listview_nav_page_next ( listview *lv )
unsigned int listview_get_desired_height ( listview *lv )
{
- if ( lv == NULL ) {
+ if ( lv == NULL || lv->widget.enabled == FALSE ) {
return 0;
}
int h = lv->menu_lines;
@@ -459,7 +459,7 @@ unsigned int listview_get_desired_height ( listview *lv )
h = MIN ( lv->menu_lines, lv->req_elements );
}
if ( h == 0 ) {
- return 0;
+ return lv->widget.pad.top+lv->widget.pad.bottom;
}
return h * lv->element_height + ( h - 1 ) * lv->spacing+lv->widget.pad.top+lv->widget.pad.bottom;
}
diff --git a/source/widgets/widget.c b/source/widgets/widget.c
index ae6ef06e..66b937ab 100644
--- a/source/widgets/widget.c
+++ b/source/widgets/widget.c
@@ -207,3 +207,61 @@ void widget_set_name ( widget *wid, const char *name )
}
wid->name = g_strdup ( name );
}
+
+int widget_padding_get_left ( const widget *wid )
+{
+ if ( wid->pad.left < 0 ){
+ return (wid->w*-wid->pad.left)/100;
+ }
+ return wid->pad.left;
+}
+int widget_padding_get_right ( const widget *wid )
+{
+ if ( wid->pad.right < 0 ){
+ return (wid->w*-wid->pad.right)/100;
+ }
+ return wid->pad.right;
+}
+int widget_padding_get_top ( const widget *wid )
+{
+ if ( wid->pad.top < 0 ){
+ return (wid->h*-wid->pad.top)/100;
+ }
+ return wid->pad.top;
+}
+int widget_padding_get_bottom ( const widget *wid )
+{
+ if ( wid->pad.bottom < 0 ){
+ return (wid->h*-wid->pad.bottom)/100;
+ }
+ return wid->pad.bottom;
+}
+
+int widget_padding_get_remaining_width ( const widget *wid )
+{
+ int width = wid->w;
+ width -= widget_padding_get_left ( wid );
+ width -= widget_padding_get_right ( wid );
+ return width;
+}
+int widget_padding_get_remaining_height ( const widget *wid )
+{
+ int height = wid->h;
+ height -= widget_padding_get_top ( wid );
+ height -= widget_padding_get_bottom ( wid );
+ return height;
+}
+int widget_padding_get_padding_height ( const widget *wid )
+{
+ int height = 0;
+ height += widget_padding_get_top ( wid );
+ height += widget_padding_get_bottom ( wid );
+ return height;
+}
+int widget_padding_get_padding_width ( const widget *wid )
+{
+ int width = 0;
+ width += widget_padding_get_left ( wid );
+ width += widget_padding_get_right ( wid );
+ return width;
+}
diff --git a/source/widgets/window.c b/source/widgets/window.c
new file mode 100644
index 00000000..3373d4f7
--- /dev/null
+++ b/source/widgets/window.c
@@ -0,0 +1,160 @@
+/**
+ * rofi
+ *
+ * MIT/X11 License
+ * Modified 2016 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 <stdio.h>
+#include "widgets/widget.h"
+#include "widgets/widget-internal.h"
+#include "widgets/window.h"
+#include "theme.h"
+#include "settings.h"
+
+#define LOG_DOMAIN "Widgets.Window"
+const char *WINDOW_CLASS_NAME = "@window";
+
+/**
+ * @param window Handle to the window widget.
+ * @param spacing The spacing to apply.
+ *
+ * Set the spacing to apply between the children in pixels.
+ */
+void window_set_spacing ( window * window, unsigned int spacing );
+
+struct _window
+{
+ widget widget;
+ widget *child;
+ int border_width;
+};
+
+static void window_update ( widget *wid );
+
+
+static void window_draw ( widget *wid, cairo_t *draw )
+{
+ window *b = (window *) wid;
+
+ cairo_save ( draw );
+ rofi_theme_get_color ( "@window", "window" , NULL, "foreground", draw );
+ cairo_set_line_width ( draw, b->border_width );
+ cairo_rectangle ( draw,
+ b->border_width / 2.0,
+ b->border_width / 2.0,
+ wid->w - b->border_width,
+ wid->h - b->border_width );
+ cairo_stroke ( draw );
+ cairo_restore ( draw );
+ widget_draw ( b->child, draw );
+}
+
+static void window_free ( widget *wid )
+{
+ window *b = (window *) wid;
+
+ widget_free ( b->child );
+ g_free ( b );
+}
+
+void window_add ( window *window, widget *child )
+{
+ if ( window == NULL ) {
+ return;
+ }
+ window->child = child;
+ child->parent = WIDGET ( window );
+ widget_update ( WIDGET ( window ) );
+}
+
+static void window_resize ( widget *widget, short w, short h )
+{
+ window *b = (window *) widget;
+ if ( b->widget.w != w || b->widget.h != h ) {
+ b->widget.w = w;
+ b->widget.h = h;
+ widget_update ( widget );
+ }
+}
+
+static gboolean window_clicked ( widget *wid, xcb_button_press_event_t *xbe, G_GNUC_UNUSED void *udata )
+{
+ window *b = (window *) wid;
+ if ( widget_intersect ( b->child, xbe->event_x, xbe->event_y ) ) {
+ xcb_button_press_event_t rel = *xbe;
+ rel.event_x -= b->child->x;
+ rel.event_y -= b->child->y;
+ return widget_clicked ( b->child, &rel );
+ }
+ return FALSE;
+}
+static gboolean window_motion_notify ( widget *wid, xcb_motion_notify_event_t *xme )
+{
+ window *b = (window *) wid;
+ if ( widget_intersect ( b->child, xme->event_x, xme->event_y ) ) {
+ xcb_motion_notify_event_t rel = *xme;
+ rel.event_x -= b->child->x;
+ rel.event_y -= b->child->y;
+ return widget_motion_notify ( b->child, &rel );
+ }
+ return FALSE;
+}
+
+window * window_create ( const char *name )
+{
+ window *b = g_malloc0 ( sizeof ( window ) );
+ // Initialize widget.
+ widget_init ( WIDGET(b), name, WINDOW_CLASS_NAME);
+ b->widget.draw = window_draw;
+ b->widget.free = window_free;
+ b->widget.resize = window_resize;
+ b->widget.update = window_update;
+ b->widget.clicked = window_clicked;
+ b->widget.motion_notify = window_motion_notify;
+ b->widget.enabled = TRUE;
+ b->border_width = rofi_theme_get_integer (
+ b->widget.class_name, b->widget.name, NULL, "border-width" , config.menu_bw);
+
+ return b;
+}
+
+static void window_update ( widget *wid )
+{
+ window *b = (window *) wid;
+ if ( b->child && b->child->enabled ){
+ widget_resize ( WIDGET ( b->child ),
+ widget_padding_get_remaining_width (WIDGET(b))-2*b->border_width,
+ widget_padding_get_remaining_height (WIDGET(b))-2*b->border_width
+ );
+ widget_move ( WIDGET ( b->child ),
+ b->border_width+widget_padding_get_left (WIDGET(b)),
+ b->border_width+widget_padding_get_top (WIDGET(b))
+ );
+ }
+}
+
+int window_get_border_width ( const window *window )
+{
+ return window->border_width*2;
+}