mirror of
https://github.com/lbonn/rofi
synced 2024-11-24 04:43:03 +00:00
commit
8fe5ea648a
41 changed files with 3353 additions and 784 deletions
|
@ -4,7 +4,7 @@ before_script:
|
||||||
- add-apt-repository -y 'deb http://debian.jpleau.ca/ jessie-backports main contrib non-free'
|
- add-apt-repository -y 'deb http://debian.jpleau.ca/ jessie-backports main contrib non-free'
|
||||||
- apt-get update -qq
|
- apt-get update -qq
|
||||||
- apt-get install --force-yes -y autoconf automake make libx11-dev libpango1.0-dev libcairo2-dev libstartup-notification0-dev libxcb-icccm4-dev libxcb-util0-dev libxcb-xinerama0-dev libxcb-xkb-dev libx11-xcb-dev
|
- apt-get install --force-yes -y autoconf automake make libx11-dev libpango1.0-dev libcairo2-dev libstartup-notification0-dev libxcb-icccm4-dev libxcb-util0-dev libxcb-xinerama0-dev libxcb-xkb-dev libx11-xcb-dev
|
||||||
- apt-get install --force-yes -y libxcb1-dev xvfb discount xdotool fluxbox libxkbcommon-dev libxkbcommon-x11-dev libxcb-ewmh-dev xutils-dev libtool lcov libxcb-randr0-dev doxygen python
|
- apt-get install --force-yes -y libxcb1-dev xvfb discount xdotool fluxbox libxkbcommon-dev libxkbcommon-x11-dev libxcb-ewmh-dev xutils-dev libtool lcov libxcb-randr0-dev doxygen python flex bison
|
||||||
- git clone --recursive https://github.com/Airblader/xcb-util-xrm.git
|
- git clone --recursive https://github.com/Airblader/xcb-util-xrm.git
|
||||||
- cd xcb-util-xrm
|
- cd xcb-util-xrm
|
||||||
- ./autogen.sh --prefix=/usr
|
- ./autogen.sh --prefix=/usr
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
* autoconf
|
* autoconf
|
||||||
* automake (1.11.3 or up)
|
* automake (1.11.3 or up)
|
||||||
* pkg-config
|
* pkg-config
|
||||||
|
* flex
|
||||||
|
* bison
|
||||||
* Developer packages of the external libraries
|
* Developer packages of the external libraries
|
||||||
|
|
||||||
### External libraries
|
### External libraries
|
||||||
|
|
40
Makefile.am
40
Makefile.am
|
@ -3,9 +3,18 @@ AUTOMAKE_OPTIONS = 1.11.3
|
||||||
|
|
||||||
ACLOCAL_AMFLAGS = -I libgwater ${ACLOCAL_FLAGS}
|
ACLOCAL_AMFLAGS = -I libgwater ${ACLOCAL_FLAGS}
|
||||||
|
|
||||||
|
AM_YFLAGS = -d
|
||||||
|
|
||||||
noinst_LIBRARIES =
|
noinst_LIBRARIES =
|
||||||
include $(top_srcdir)/libgwater-xcb-nolibtool.mk
|
include $(top_srcdir)/libgwater-xcb-nolibtool.mk
|
||||||
|
|
||||||
|
|
||||||
|
BUILT_SOURCES=\
|
||||||
|
lexer/theme-parser.h\
|
||||||
|
lexer/theme-parser.c\
|
||||||
|
lexer/theme-lexer.c
|
||||||
|
|
||||||
|
|
||||||
##
|
##
|
||||||
# Rofi the program
|
# Rofi the program
|
||||||
##
|
##
|
||||||
|
@ -27,12 +36,13 @@ rofi_SOURCES=\
|
||||||
source/helper.c\
|
source/helper.c\
|
||||||
source/timings.c\
|
source/timings.c\
|
||||||
source/history.c\
|
source/history.c\
|
||||||
|
source/theme.c\
|
||||||
source/widgets/box.c\
|
source/widgets/box.c\
|
||||||
|
source/widgets/container.c\
|
||||||
source/widgets/widget.c\
|
source/widgets/widget.c\
|
||||||
source/widgets/textbox.c\
|
source/widgets/textbox.c\
|
||||||
source/widgets/listview.c\
|
source/widgets/listview.c\
|
||||||
source/widgets/scrollbar.c\
|
source/widgets/scrollbar.c\
|
||||||
source/widgets/separator.c\
|
|
||||||
source/xrmoptions.c\
|
source/xrmoptions.c\
|
||||||
source/x11-helper.c\
|
source/x11-helper.c\
|
||||||
source/dialogs/run.c\
|
source/dialogs/run.c\
|
||||||
|
@ -43,6 +53,8 @@ rofi_SOURCES=\
|
||||||
source/dialogs/window.c\
|
source/dialogs/window.c\
|
||||||
source/dialogs/script.c\
|
source/dialogs/script.c\
|
||||||
source/dialogs/help-keys.c\
|
source/dialogs/help-keys.c\
|
||||||
|
lexer/theme-parser.y\
|
||||||
|
lexer/theme-lexer.l\
|
||||||
include/xcb.h\
|
include/xcb.h\
|
||||||
include/xcb-internal.h\
|
include/xcb-internal.h\
|
||||||
include/rofi.h\
|
include/rofi.h\
|
||||||
|
@ -55,13 +67,14 @@ rofi_SOURCES=\
|
||||||
include/helper.h\
|
include/helper.h\
|
||||||
include/timings.h\
|
include/timings.h\
|
||||||
include/history.h\
|
include/history.h\
|
||||||
|
include/theme.h\
|
||||||
include/widgets/box.h\
|
include/widgets/box.h\
|
||||||
|
include/widgets/container.h\
|
||||||
include/widgets/widget.h\
|
include/widgets/widget.h\
|
||||||
include/widgets/widget-internal.h\
|
include/widgets/widget-internal.h\
|
||||||
include/widgets/textbox.h\
|
include/widgets/textbox.h\
|
||||||
include/widgets/listview.h\
|
include/widgets/listview.h\
|
||||||
include/widgets/scrollbar.h\
|
include/widgets/scrollbar.h\
|
||||||
include/widgets/separator.h\
|
|
||||||
include/xrmoptions.h\
|
include/xrmoptions.h\
|
||||||
include/x11-helper.h\
|
include/x11-helper.h\
|
||||||
include/dialogs/ssh.h\
|
include/dialogs/ssh.h\
|
||||||
|
@ -88,7 +101,8 @@ rofi_CFLAGS=\
|
||||||
-I$(top_srcdir)/config/\
|
-I$(top_srcdir)/config/\
|
||||||
-I$(top_builddir)/\
|
-I$(top_builddir)/\
|
||||||
-Werror=missing-prototypes\
|
-Werror=missing-prototypes\
|
||||||
-DSYSCONFDIR=\"$(sysconfdir)\"
|
-DSYSCONFDIR=\"$(sysconfdir)\"\
|
||||||
|
-DTHEME_CONVERTER
|
||||||
|
|
||||||
rofi_LDADD=\
|
rofi_LDADD=\
|
||||||
$(glib_LIBS)\
|
$(glib_LIBS)\
|
||||||
|
@ -259,6 +273,13 @@ widget_test_LDADD=$(textbox_test_LDADD)
|
||||||
widget_test_CFLAGS=$(textbox_test_CFLAGS)
|
widget_test_CFLAGS=$(textbox_test_CFLAGS)
|
||||||
widget_test_SOURCES=\
|
widget_test_SOURCES=\
|
||||||
source/widgets/widget.c\
|
source/widgets/widget.c\
|
||||||
|
source/widgets/textbox.c\
|
||||||
|
source/theme.c\
|
||||||
|
source/helper.c\
|
||||||
|
source/x11-helper.c\
|
||||||
|
config/config.c\
|
||||||
|
lexer/theme-parser.y\
|
||||||
|
lexer/theme-lexer.l\
|
||||||
test/widget-test.c
|
test/widget-test.c
|
||||||
|
|
||||||
box_test_LDADD=$(textbox_test_LDADD)
|
box_test_LDADD=$(textbox_test_LDADD)
|
||||||
|
@ -266,6 +287,10 @@ box_test_CFLAGS=$(textbox_test_CFLAGS)
|
||||||
box_test_SOURCES=\
|
box_test_SOURCES=\
|
||||||
source/widgets/widget.c\
|
source/widgets/widget.c\
|
||||||
source/widgets/box.c\
|
source/widgets/box.c\
|
||||||
|
lexer/theme-parser.y\
|
||||||
|
lexer/theme-lexer.l\
|
||||||
|
source/theme.c\
|
||||||
|
include/theme.h\
|
||||||
test/box-test.c
|
test/box-test.c
|
||||||
|
|
||||||
scrollbar_test_LDADD=$(textbox_test_LDADD)
|
scrollbar_test_LDADD=$(textbox_test_LDADD)
|
||||||
|
@ -273,11 +298,20 @@ scrollbar_test_CFLAGS=$(textbox_test_CFLAGS)
|
||||||
scrollbar_test_SOURCES=\
|
scrollbar_test_SOURCES=\
|
||||||
source/widgets/widget.c\
|
source/widgets/widget.c\
|
||||||
source/widgets/scrollbar.c\
|
source/widgets/scrollbar.c\
|
||||||
|
lexer/theme-parser.y\
|
||||||
|
lexer/theme-lexer.l\
|
||||||
|
source/theme.c\
|
||||||
|
include/theme.h\
|
||||||
test/scrollbar-test.c
|
test/scrollbar-test.c
|
||||||
|
|
||||||
textbox_test_SOURCES=\
|
textbox_test_SOURCES=\
|
||||||
source/widgets/widget.c\
|
source/widgets/widget.c\
|
||||||
source/widgets/textbox.c\
|
source/widgets/textbox.c\
|
||||||
|
lexer/theme-parser.y\
|
||||||
|
lexer/theme-lexer.l\
|
||||||
|
source/theme.c\
|
||||||
|
source/helper.c\
|
||||||
|
source/x11-helper.c\
|
||||||
config/config.c\
|
config/config.c\
|
||||||
include/keyb.h\
|
include/keyb.h\
|
||||||
include/rofi.h\
|
include/rofi.h\
|
||||||
|
|
|
@ -128,4 +128,5 @@ Settings config = {
|
||||||
.window_format = "{w} {c} {t}",
|
.window_format = "{w} {c} {t}",
|
||||||
.click_to_exit = TRUE,
|
.click_to_exit = TRUE,
|
||||||
.show_match = TRUE,
|
.show_match = TRUE,
|
||||||
|
.theme = NULL,
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,6 +3,10 @@ AC_INIT([rofi], [1.3.1], [https://github.com/DaveDavenport/rofi/],[],[https://fo
|
||||||
AC_CONFIG_SRCDIR([source/rofi.c])
|
AC_CONFIG_SRCDIR([source/rofi.c])
|
||||||
AC_CONFIG_HEADER([config.h])
|
AC_CONFIG_HEADER([config.h])
|
||||||
|
|
||||||
|
|
||||||
|
AC_PROG_LEX
|
||||||
|
AC_PROG_YACC
|
||||||
|
|
||||||
dnl ---------------------------------------------------------------------
|
dnl ---------------------------------------------------------------------
|
||||||
dnl Setup automake to be silent and in foreign mode.
|
dnl Setup automake to be silent and in foreign mode.
|
||||||
dnl We want xz distribution
|
dnl We want xz distribution
|
||||||
|
|
|
@ -135,6 +135,8 @@ Global options:
|
||||||
True (Default)
|
True (Default)
|
||||||
-[no-]show-match Indicate how it match by underlining it.
|
-[no-]show-match Indicate how it match by underlining it.
|
||||||
True (Default)
|
True (Default)
|
||||||
|
-theme [string] New style theme file
|
||||||
|
(unset) (Default)
|
||||||
-pid [string] Pidfile location
|
-pid [string] Pidfile location
|
||||||
/tmp/rofi.pid (File)
|
/tmp/rofi.pid (File)
|
||||||
-kb-primary-paste [string] Paste primary selection
|
-kb-primary-paste [string] Paste primary selection
|
||||||
|
|
|
@ -98,6 +98,8 @@ rofi.window-format: w c t
|
||||||
! rofi.click-to-exit: true
|
! rofi.click-to-exit: true
|
||||||
! "Indicate how it match by underlining it." Set from: Default
|
! "Indicate how it match by underlining it." Set from: Default
|
||||||
! rofi.show-match: true
|
! rofi.show-match: true
|
||||||
|
! "New style theme file" Set from: Default
|
||||||
|
! rofi.theme:
|
||||||
! "Pidfile location" Set from: File
|
! "Pidfile location" Set from: File
|
||||||
rofi.pid: /tmp/rofi.pid
|
rofi.pid: /tmp/rofi.pid
|
||||||
! "Paste primary selection" Set from: File
|
! "Paste primary selection" Set from: File
|
||||||
|
|
172
doc/themer.md
Normal file
172
doc/themer.md
Normal file
|
@ -0,0 +1,172 @@
|
||||||
|
# Basic Organization
|
||||||
|
|
||||||
|
Each widget has:
|
||||||
|
|
||||||
|
## Name
|
||||||
|
|
||||||
|
Name: Internal name of the widget.
|
||||||
|
|
||||||
|
Sub-widgets are {Parent}.{Child}.
|
||||||
|
|
||||||
|
Example: window, window.mainbox.listview, window.mainbox.listview.element
|
||||||
|
|
||||||
|
Names are prefixed with a `#`
|
||||||
|
|
||||||
|
List of names in **rofi**:
|
||||||
|
|
||||||
|
* `#window`
|
||||||
|
* `#window.overlay`: The overlay widget.
|
||||||
|
* `#window.mainbox`
|
||||||
|
* `#window.mainbox.box`: The main vertical @box
|
||||||
|
* `#window.mainbox.inputbar`
|
||||||
|
* `#window.mainbox.inputbar.box`: The horizontal @box packing the widgets.
|
||||||
|
* `#window.mainbox.inputbar.case-indicator`: The case/sort indicator @textbox
|
||||||
|
* `#window.mainbox.inputbar.prompt`: The prompt @textbox
|
||||||
|
* `#window.mainbox.inputbar.entry`: The main entry @textbox
|
||||||
|
* `#window.mainbox.listview`
|
||||||
|
* `#window.mainbox.listview.box`: The listview container.
|
||||||
|
* `#window.mainbox.listview.scrollbar`: The listview scrollbar
|
||||||
|
* `#window.mainbox.listview.element`: The entries in the listview
|
||||||
|
* `#window.mainbox.sidebar`
|
||||||
|
* `#window.mainbox.sidebar.box`: The main horizontal @box packing the buttons.
|
||||||
|
* `#window.mainbox.sidebar.button`: The buttons @textbox for each mode.
|
||||||
|
* `#window.mainbox.message`
|
||||||
|
* `#window.mainbox.message.textbox`: The message textbox.
|
||||||
|
* `#window.mainbox.message.box`: The box containing the message.
|
||||||
|
|
||||||
|
## State
|
||||||
|
|
||||||
|
State: State of widget
|
||||||
|
|
||||||
|
Optional flag(s) indicating state.
|
||||||
|
|
||||||
|
These are appended after the name or class of the widget.
|
||||||
|
|
||||||
|
`#window.mainbox.sidebar.button selected.normal { }`
|
||||||
|
|
||||||
|
`#window.mainbox.listview.element selected.urgent { }`
|
||||||
|
|
||||||
|
Currently only the entrybox and scrollbar has states:
|
||||||
|
|
||||||
|
`{visible modifier}.{state}`
|
||||||
|
|
||||||
|
Where `visible modifier` can be:
|
||||||
|
* normal: No modification.
|
||||||
|
* selected: The entry is selected/highlighted by user.
|
||||||
|
* alternate: The entry is at an alternating row. (uneven row)
|
||||||
|
|
||||||
|
Where `state` is:
|
||||||
|
* normal: No modification.
|
||||||
|
* urgent: This entry is marked urgent.
|
||||||
|
* activE: This entry is marked active.
|
||||||
|
|
||||||
|
These can be mixed.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```
|
||||||
|
#name.to.textbox selected.active {
|
||||||
|
background: #003642;
|
||||||
|
foreground: #008ed4;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Sets all selected textboxes marked active to the given foreground and background color.
|
||||||
|
|
||||||
|
The scrollbar when drawing uses the `handle` state when drawing the small scrollbar handle.
|
||||||
|
Allowing overriding of color.
|
||||||
|
|
||||||
|
# File structure
|
||||||
|
|
||||||
|
The file is structured as follows
|
||||||
|
|
||||||
|
```
|
||||||
|
/* Global properties, that apply as default to all widgets. */
|
||||||
|
{list of properties}
|
||||||
|
|
||||||
|
#{name} {optional state} {
|
||||||
|
{list of properties}
|
||||||
|
}
|
||||||
|
#{name}.{optional state} {
|
||||||
|
{list of properties}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The global properties an freeĺy be mixed between entries.
|
||||||
|
Name and state can be separated by a comman, or joined using a dot.
|
||||||
|
|
||||||
|
Each property is constructed like:
|
||||||
|
```
|
||||||
|
{key} : {value} ;
|
||||||
|
```
|
||||||
|
Key is a simple ascii string.
|
||||||
|
Separated from value by a colon ':';
|
||||||
|
Value supports the following formats:
|
||||||
|
|
||||||
|
* string: `"{string}"`
|
||||||
|
* integer: `[0-9]+`
|
||||||
|
* double: `[0-9]+\.[0-9]`
|
||||||
|
* boolean: `true|false`
|
||||||
|
* color:
|
||||||
|
* `#[0-9a-fA-F]{6}`: hexidecimal rgb color.
|
||||||
|
* `#[0-9a-fA-F]{8}`: hexidecimal argb color.
|
||||||
|
* `argb:[0-0a-fA-F]{8}`: Old **rofi** argb color style.
|
||||||
|
* `rgba\([0-9]{1,3},[0-9]{1,3}, [0-9]{1,3}, {double}\)`: css style rgba color.
|
||||||
|
* `rgb\([0-9]{1,3},[0-9]{1,3}, [0-9]{1,3}\)`: css style rgb color.
|
||||||
|
* distance:
|
||||||
|
* `{size}{unit} {line-style}`
|
||||||
|
* unit can be px,em,%. for px `{size}` is an integer number, for %,em it is a positive real.
|
||||||
|
* {line-style} can be `dash` or `solid` and is optional.
|
||||||
|
* padding: `({distance}){1,4}`
|
||||||
|
* position: (center|north|south|east|west|northeast|northwest|southwest|southeast)
|
||||||
|
|
||||||
|
Each property is closed by a semi-colon `;`;
|
||||||
|
|
||||||
|
The following properties are currently supports:
|
||||||
|
|
||||||
|
* all widgets:
|
||||||
|
* padding: distance
|
||||||
|
* margin: distance
|
||||||
|
* border: distance
|
||||||
|
* background: color
|
||||||
|
* foreground: color
|
||||||
|
* end: boolean
|
||||||
|
|
||||||
|
* window:
|
||||||
|
* font: string
|
||||||
|
* transparency: string
|
||||||
|
- real
|
||||||
|
- background
|
||||||
|
- screenshot
|
||||||
|
- Path to png file
|
||||||
|
* position: position
|
||||||
|
The place of the anchor on the monitor.
|
||||||
|
* anchor: anchor
|
||||||
|
The anchor position on the window.
|
||||||
|
|
||||||
|
* scrollbar
|
||||||
|
* foreground: color
|
||||||
|
* handle-width: distance
|
||||||
|
* handle-color: color
|
||||||
|
* foreground: color
|
||||||
|
|
||||||
|
* box
|
||||||
|
* spacing: distance
|
||||||
|
|
||||||
|
* textbox:
|
||||||
|
* background: color
|
||||||
|
* foreground: color
|
||||||
|
|
||||||
|
* listview:
|
||||||
|
* columns: integer
|
||||||
|
* fixed-height: boolean
|
||||||
|
* dynamic: boolean
|
||||||
|
* scrollbar: boolean
|
||||||
|
* scrollbar-width: distance
|
||||||
|
* cycle: boolean
|
||||||
|
* spacing: distance
|
||||||
|
|
||||||
|
|
||||||
|
## Resolving properties
|
||||||
|
|
||||||
|
It tries to find the longest match down the dependency tree.
|
||||||
|
|
|
@ -82,6 +82,14 @@ int find_arg_int ( const char * const key, int *val );
|
||||||
*/
|
*/
|
||||||
int find_arg_str ( const char * const key, char** val );
|
int find_arg_str ( const char * const key, char** val );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param key The key to search for
|
||||||
|
*
|
||||||
|
* Parse all command line options 'key' to string vector.
|
||||||
|
*
|
||||||
|
* @returns str vector. user should free array.
|
||||||
|
*/
|
||||||
|
const char ** find_arg_strv ( const char *const key );
|
||||||
/**
|
/**
|
||||||
* @param key The key to search for
|
* @param key The key to search for
|
||||||
*
|
*
|
||||||
|
|
|
@ -38,7 +38,7 @@ typedef enum
|
||||||
/** Middle right */
|
/** Middle right */
|
||||||
WL_EAST = 4,
|
WL_EAST = 4,
|
||||||
/** Bottom right */
|
/** Bottom right */
|
||||||
WL_EAST_SOUTH = 5,
|
WL_SOUTH_EAST = 5,
|
||||||
/** Bottom middle */
|
/** Bottom middle */
|
||||||
WL_SOUTH = 6,
|
WL_SOUTH = 6,
|
||||||
/** Bottom left */
|
/** Bottom left */
|
||||||
|
@ -149,6 +149,8 @@ typedef struct
|
||||||
/** Click outside the window to exit */
|
/** Click outside the window to exit */
|
||||||
int click_to_exit;
|
int click_to_exit;
|
||||||
gboolean show_match;
|
gboolean show_match;
|
||||||
|
|
||||||
|
char *theme;
|
||||||
} Settings;
|
} Settings;
|
||||||
/** Global Settings structure. */
|
/** Global Settings structure. */
|
||||||
extern Settings config;
|
extern Settings config;
|
||||||
|
|
337
include/theme.h
Normal file
337
include/theme.h
Normal file
|
@ -0,0 +1,337 @@
|
||||||
|
#ifndef THEME_H
|
||||||
|
#define THEME_H
|
||||||
|
#include <glib.h>
|
||||||
|
#include <cairo.h>
|
||||||
|
#include <widgets/widget.h>
|
||||||
|
#include <settings.h>
|
||||||
|
|
||||||
|
/** Style of line */
|
||||||
|
typedef enum {
|
||||||
|
/** Solid line */
|
||||||
|
SOLID,
|
||||||
|
/** Dashed line */
|
||||||
|
DASH
|
||||||
|
} LineStyle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Distance unit type.
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
/** PixelWidth in pixels. */
|
||||||
|
PW_PX,
|
||||||
|
/** PixelWidth in EM. */
|
||||||
|
PW_EM,
|
||||||
|
/** PixelWidget in percentage */
|
||||||
|
PW_PERCENT,
|
||||||
|
} PixelWidth;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Structure representing a distance.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
/** Distance */
|
||||||
|
double distance;
|
||||||
|
/** Unit type of the distance */
|
||||||
|
PixelWidth type;
|
||||||
|
/** Style of the line */
|
||||||
|
LineStyle style;
|
||||||
|
} Distance;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type of orientation.
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
ORIENTATION_VERTICAL,
|
||||||
|
ORIENTATION_HORIZONTAL
|
||||||
|
} Orientation;
|
||||||
|
/**
|
||||||
|
* Type of property
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
/** Integer */
|
||||||
|
P_INTEGER,
|
||||||
|
/** Double */
|
||||||
|
P_DOUBLE,
|
||||||
|
/** String */
|
||||||
|
P_STRING,
|
||||||
|
/** Boolean */
|
||||||
|
P_BOOLEAN,
|
||||||
|
/** Color */
|
||||||
|
P_COLOR,
|
||||||
|
/** Padding */
|
||||||
|
P_PADDING,
|
||||||
|
/** Link to global setting */
|
||||||
|
P_LINK,
|
||||||
|
/** Position */
|
||||||
|
P_POSITION,
|
||||||
|
} PropertyType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represent the color in theme.
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
/** red channel */
|
||||||
|
double red;
|
||||||
|
/** green channel */
|
||||||
|
double green;
|
||||||
|
/** blue channel */
|
||||||
|
double blue;
|
||||||
|
/** alpha channel */
|
||||||
|
double alpha;
|
||||||
|
} ThemeColor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Padding
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Distance top;
|
||||||
|
Distance right;
|
||||||
|
Distance bottom;
|
||||||
|
Distance left;
|
||||||
|
} Padding;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Property structure.
|
||||||
|
*/
|
||||||
|
typedef struct Property {
|
||||||
|
/** Name of property */
|
||||||
|
char *name;
|
||||||
|
/** Type of property. */
|
||||||
|
PropertyType type;
|
||||||
|
/** Value */
|
||||||
|
union {
|
||||||
|
/** integer */
|
||||||
|
int i;
|
||||||
|
/** Double */
|
||||||
|
double f;
|
||||||
|
/** String */
|
||||||
|
char *s;
|
||||||
|
/** boolean */
|
||||||
|
gboolean b;
|
||||||
|
/** Color */
|
||||||
|
ThemeColor color;
|
||||||
|
/** Padding */
|
||||||
|
Padding padding;
|
||||||
|
/** Reference */
|
||||||
|
struct {
|
||||||
|
/** Name */
|
||||||
|
char *name;
|
||||||
|
/** Cached looked up ref */
|
||||||
|
struct Property *ref;
|
||||||
|
} link;
|
||||||
|
} value;
|
||||||
|
} Property;
|
||||||
|
/**
|
||||||
|
* ThemeWidget.
|
||||||
|
*/
|
||||||
|
typedef struct ThemeWidget {
|
||||||
|
int set;
|
||||||
|
char *name;
|
||||||
|
|
||||||
|
unsigned int num_widgets;
|
||||||
|
struct ThemeWidget **widgets;
|
||||||
|
|
||||||
|
GHashTable *properties;
|
||||||
|
|
||||||
|
struct ThemeWidget *parent;
|
||||||
|
} ThemeWidget;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Global pointer to the current active theme.
|
||||||
|
*/
|
||||||
|
extern ThemeWidget *rofi_theme;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param base Handle to the current level in the theme.
|
||||||
|
* @param name Name of the new element.
|
||||||
|
*
|
||||||
|
* Create a new element in the theme structure.
|
||||||
|
*
|
||||||
|
* @returns handle to the new entry.
|
||||||
|
*/
|
||||||
|
ThemeWidget *rofi_theme_find_or_create_name ( ThemeWidget *base, const char *name );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param widget The widget handle.
|
||||||
|
*
|
||||||
|
* Print out the widget to the commandline.
|
||||||
|
*/
|
||||||
|
void rofi_theme_print ( ThemeWidget *widget );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param type The type of the property to create.
|
||||||
|
*
|
||||||
|
* Create a theme property of type.
|
||||||
|
*
|
||||||
|
* @returns a new property.
|
||||||
|
*/
|
||||||
|
Property *rofi_theme_property_create ( PropertyType type );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param p The property to free.
|
||||||
|
*
|
||||||
|
* Free the content of the property.
|
||||||
|
*/
|
||||||
|
void rofi_theme_property_free ( Property *p );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param wid
|
||||||
|
*
|
||||||
|
* Free the widget and alll children.
|
||||||
|
*/
|
||||||
|
void rofi_theme_free ( ThemeWidget *wid );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param file filename to parse.
|
||||||
|
*
|
||||||
|
* Parse the input theme file.
|
||||||
|
*
|
||||||
|
* @returns returns TRUE when error.
|
||||||
|
*/
|
||||||
|
gboolean rofi_theme_parse_file ( const char *file );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string to parse.
|
||||||
|
*
|
||||||
|
* Parse the input string in addition to theme file.
|
||||||
|
*
|
||||||
|
* @returns returns TRUE when error.
|
||||||
|
*/
|
||||||
|
gboolean rofi_theme_parse_string ( const char *string );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param widget The widget handle.
|
||||||
|
* @param table HashTable containing properties set.
|
||||||
|
*
|
||||||
|
* Merge properties with widgets current property.
|
||||||
|
*/
|
||||||
|
void rofi_theme_widget_add_properties ( ThemeWidget *widget, GHashTable *table );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public API
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param widget The widget to query
|
||||||
|
* @param property The property to query.
|
||||||
|
* @param def The default value.
|
||||||
|
*
|
||||||
|
* Obtain the distance of the widget.
|
||||||
|
*
|
||||||
|
* @returns The distance value of this property for this widget.
|
||||||
|
*/
|
||||||
|
Distance rofi_theme_get_distance ( const widget *widget, const char *property, int def );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param widget The widget to query
|
||||||
|
* @param property The property to query.
|
||||||
|
* @param def The default value.
|
||||||
|
*
|
||||||
|
* Obtain the integer of the widget.
|
||||||
|
*
|
||||||
|
* @returns The integer value of this property for this widget.
|
||||||
|
*/
|
||||||
|
int rofi_theme_get_integer ( const widget *widget, const char *property, int def );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param widget The widget to query
|
||||||
|
* @param property The property to query.
|
||||||
|
* @param def The default value.
|
||||||
|
*
|
||||||
|
* Obtain the position of the widget.
|
||||||
|
*
|
||||||
|
* @returns The position value of this property for this widget.
|
||||||
|
*/
|
||||||
|
int rofi_theme_get_position ( const widget *widget, const char *property, int def );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param widget The widget to query
|
||||||
|
* @param property The property to query.
|
||||||
|
* @param def The default value.
|
||||||
|
*
|
||||||
|
* Obtain the integer of the widget.
|
||||||
|
*
|
||||||
|
* @returns The integer value of this property for this widget.
|
||||||
|
*/
|
||||||
|
int rofi_theme_get_integer_exact ( const widget *widget, const char *property, int def );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param widget The widget to query
|
||||||
|
* @param property The property to query.
|
||||||
|
* @param def The default value.
|
||||||
|
*
|
||||||
|
* Obtain the boolean of the widget.
|
||||||
|
*
|
||||||
|
* @returns The boolean value of this property for this widget.
|
||||||
|
*/
|
||||||
|
int rofi_theme_get_boolean ( const widget *widget, const char *property, int def );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param widget The widget to query
|
||||||
|
* @param property The property to query.
|
||||||
|
* @param def The default value.
|
||||||
|
*
|
||||||
|
* Obtain the string of the widget.
|
||||||
|
*
|
||||||
|
* @returns The string value of this property for this widget.
|
||||||
|
*/
|
||||||
|
char *rofi_theme_get_string ( const widget *widget, const char *property, char *def );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param widget The widget to query
|
||||||
|
* @param property The property to query.
|
||||||
|
* @param def The default value.
|
||||||
|
*
|
||||||
|
* Obtain the padding of the widget.
|
||||||
|
*
|
||||||
|
* @returns The double value of this property for this widget.
|
||||||
|
*/
|
||||||
|
double rofi_theme_get_double ( const widget *widget, const char *property, double def );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param widget The widget to query
|
||||||
|
* @param property The property to query.
|
||||||
|
* @param d The drawable to apply color.
|
||||||
|
*
|
||||||
|
* Obtain the color of the widget and applies this to the drawable d.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void rofi_theme_get_color ( const widget *widget, const char *property, cairo_t *d);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param widget The widget to query
|
||||||
|
* @param property The property to query.
|
||||||
|
* @param pad The default value.
|
||||||
|
*
|
||||||
|
* Obtain the padding of the widget.
|
||||||
|
*
|
||||||
|
* @returns The padding of this property for this widget.
|
||||||
|
*/
|
||||||
|
Padding rofi_theme_get_padding ( const widget *widget, const char *property, Padding pad );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param d The distance handle.
|
||||||
|
* @param ori The orientation.
|
||||||
|
*
|
||||||
|
* Convert Distance into pixels.
|
||||||
|
* @returns the number of pixels this distance represents.
|
||||||
|
*/
|
||||||
|
int distance_get_pixel ( Distance d, Orientation ori );
|
||||||
|
/**
|
||||||
|
* @param d The distance handle.
|
||||||
|
* @param draw The cairo drawable.
|
||||||
|
*
|
||||||
|
* Set linestyle.
|
||||||
|
*/
|
||||||
|
void distance_get_linestyle ( Distance d, cairo_t *draw );
|
||||||
|
|
||||||
|
#ifdef THEME_CONVERTER
|
||||||
|
/**
|
||||||
|
* Function to convert old theme into new theme format.
|
||||||
|
*/
|
||||||
|
void rofi_theme_convert_old_theme ( void );
|
||||||
|
#endif
|
||||||
|
#endif
|
|
@ -1,12 +1,13 @@
|
||||||
#ifndef ROFI_VIEW_INTERNAL_H
|
#ifndef ROFI_VIEW_INTERNAL_H
|
||||||
#define ROFI_VIEW_INTERNAL_H
|
#define ROFI_VIEW_INTERNAL_H
|
||||||
|
#include "widgets/container.h"
|
||||||
#include "widgets/widget.h"
|
#include "widgets/widget.h"
|
||||||
#include "widgets/textbox.h"
|
#include "widgets/textbox.h"
|
||||||
#include "widgets/separator.h"
|
|
||||||
#include "widgets/listview.h"
|
#include "widgets/listview.h"
|
||||||
#include "widgets/box.h"
|
#include "widgets/box.h"
|
||||||
#include "keyb.h"
|
#include "keyb.h"
|
||||||
#include "x11-helper.h"
|
#include "x11-helper.h"
|
||||||
|
#include "theme.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup ViewHandle
|
* @ingroup ViewHandle
|
||||||
|
@ -22,7 +23,8 @@ struct RofiViewState
|
||||||
|
|
||||||
/** Flag indicating if view needs to be refiltered. */
|
/** Flag indicating if view needs to be refiltered. */
|
||||||
int refilter;
|
int refilter;
|
||||||
|
/** Widget representing the main container. */
|
||||||
|
container *main_window;
|
||||||
/** Main #box widget holding different elements. */
|
/** Main #box widget holding different elements. */
|
||||||
box *main_box;
|
box *main_box;
|
||||||
/** #box widget packing the input bar widgets. */
|
/** #box widget packing the input bar widgets. */
|
||||||
|
@ -33,8 +35,6 @@ struct RofiViewState
|
||||||
textbox *text;
|
textbox *text;
|
||||||
/** #textbox showing the state of the case sensitive and sortng. */
|
/** #textbox showing the state of the case sensitive and sortng. */
|
||||||
textbox *case_indicator;
|
textbox *case_indicator;
|
||||||
/** #separator widget below the input bar. */
|
|
||||||
separator *input_bar_separator;
|
|
||||||
|
|
||||||
/** #listview holding the displayed elements. */
|
/** #listview holding the displayed elements. */
|
||||||
listview *list_view;
|
listview *list_view;
|
||||||
|
@ -63,8 +63,6 @@ struct RofiViewState
|
||||||
unsigned int selected_line;
|
unsigned int selected_line;
|
||||||
/** The return state of the view */
|
/** The return state of the view */
|
||||||
MenuReturn retv;
|
MenuReturn retv;
|
||||||
/** Calculated border width */
|
|
||||||
unsigned int border;
|
|
||||||
/** Monitor #workarea the view is displayed on */
|
/** Monitor #workarea the view is displayed on */
|
||||||
workarea mon;
|
workarea mon;
|
||||||
|
|
||||||
|
|
|
@ -111,12 +111,6 @@ unsigned int rofi_view_get_selected_line ( const RofiViewState *state );
|
||||||
*/
|
*/
|
||||||
void rofi_view_restart ( RofiViewState *state );
|
void rofi_view_restart ( RofiViewState *state );
|
||||||
|
|
||||||
/**
|
|
||||||
* @param state The handle to the view
|
|
||||||
*
|
|
||||||
* Update the state of the view. This involves filter state.
|
|
||||||
*/
|
|
||||||
void rofi_view_update ( RofiViewState *state );
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param state The handle to the view
|
* @param state The handle to the view
|
||||||
|
@ -254,5 +248,12 @@ void rofi_view_workers_initialize ( void );
|
||||||
* Stop all threads and free the resources used by the threadpool
|
* Stop all threads and free the resources used by the threadpool
|
||||||
*/
|
*/
|
||||||
void rofi_view_workers_finalize ( void );
|
void rofi_view_workers_finalize ( void );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the current monitor workarea.
|
||||||
|
*
|
||||||
|
* @returns the current monitor workarea
|
||||||
|
*/
|
||||||
|
void rofi_view_get_current_monitor ( int *width, int *height );
|
||||||
/**@}*/
|
/**@}*/
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -32,42 +32,31 @@ typedef enum
|
||||||
} boxType;
|
} boxType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param name The name of the widget.
|
||||||
* @param type The packing direction of the newly created box.
|
* @param type The packing direction of the newly created box.
|
||||||
* @param x The x position of the box relative to its parent.
|
|
||||||
* @param y The y position of the box relative to its parent.
|
|
||||||
* @param w The width of the box.
|
|
||||||
* @param h The height of the box.
|
|
||||||
*
|
*
|
||||||
* @returns a newly created box, free with #widget_free
|
* @returns a newly created box, free with #widget_free
|
||||||
*/
|
*/
|
||||||
box * box_create ( boxType type, short x, short y, short w, short h );
|
box * box_create ( const char *name, boxType type );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param box Handle to the box widget.
|
* @param box Handle to the box widget.
|
||||||
* @param child Handle to the child widget to pack.
|
* @param child Handle to the child widget to pack.
|
||||||
* @param expand If the child widget should expand and use all available space.
|
* @param expand If the child widget should expand and use all available space.
|
||||||
* @param end If the child widget should be packed at the end.
|
* @param index The position index.
|
||||||
*
|
*
|
||||||
* Add a widget to the box.
|
* Add a widget to the box.
|
||||||
*/
|
*/
|
||||||
void box_add ( box *box, widget *child, gboolean expand, gboolean end );
|
void box_add ( box *box, widget *child, gboolean expand, int index );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param box Handle to the box widget.
|
* @param box Handle to the box widget.
|
||||||
*
|
*
|
||||||
* Obtains the minimal size required to display all widgets. (expanding widgets are not counted, except for their
|
* Obtains the minimal size required to display all widgets. (expanding widgets are not counted, except for their
|
||||||
* padding)
|
* spacing)
|
||||||
*
|
*
|
||||||
* @returns the minimum size in pixels.
|
* @returns the minimum size in pixels.
|
||||||
*/
|
*/
|
||||||
int box_get_fixed_pixels ( box *box );
|
int box_get_fixed_pixels ( box *box );
|
||||||
|
|
||||||
/**
|
|
||||||
* @param box Handle to the box widget.
|
|
||||||
* @param padding The padding to apply.
|
|
||||||
*
|
|
||||||
* Set the padding to apply between the children in pixels.
|
|
||||||
*/
|
|
||||||
void box_set_padding ( box * box, unsigned int padding );
|
|
||||||
/*@}*/
|
/*@}*/
|
||||||
#endif // ROFI_HBOX_H
|
#endif // ROFI_HBOX_H
|
||||||
|
|
34
include/widgets/container.h
Normal file
34
include/widgets/container.h
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
#ifndef ROFI_CONTAINER_H
|
||||||
|
#define ROFI_CONTAINER_H
|
||||||
|
|
||||||
|
#include "widget.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup container container
|
||||||
|
* @ingroup widget
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract handle to the container widget internal state.
|
||||||
|
*/
|
||||||
|
typedef struct _window container;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param name The name of the widget.
|
||||||
|
*
|
||||||
|
* @returns a newly created container, free with #widget_free
|
||||||
|
*/
|
||||||
|
container * container_create ( const char *name );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param container Handle to the container widget.
|
||||||
|
* @param child Handle to the child widget to pack.
|
||||||
|
*
|
||||||
|
* Add a widget to the container.
|
||||||
|
*/
|
||||||
|
void container_add ( container *container, widget *child );
|
||||||
|
/*@}*/
|
||||||
|
#endif // ROFI_CONTAINER_H
|
|
@ -42,13 +42,15 @@ typedef void ( *listview_update_callback )( textbox *tb, unsigned int entry, voi
|
||||||
typedef void ( *listview_mouse_activated_cb )( listview *, xcb_button_press_event_t *, void * );
|
typedef void ( *listview_mouse_activated_cb )( listview *, xcb_button_press_event_t *, void * );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param name The name of the to be created widget.
|
||||||
* @param cb The update callback.
|
* @param cb The update callback.
|
||||||
* @param udata The user data to pass to the callback
|
* @param udata The user data to pass to the callback
|
||||||
* @param eh The height of one element
|
* @param eh The height of one element
|
||||||
|
* @param reverse Reverse the listview order.
|
||||||
*
|
*
|
||||||
* @returns a new listview
|
* @returns a new listview
|
||||||
*/
|
*/
|
||||||
listview *listview_create ( listview_update_callback cb, void *udata, unsigned int eh );
|
listview *listview_create ( const char *name, listview_update_callback cb, void *udata, unsigned int eh, gboolean reverse );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param lv The listview handle
|
* @param lv The listview handle
|
||||||
|
@ -75,15 +77,6 @@ void listview_set_selected ( listview *lv, unsigned int selected );
|
||||||
*/
|
*/
|
||||||
unsigned int listview_get_selected ( listview *lv );
|
unsigned int listview_get_selected ( listview *lv );
|
||||||
|
|
||||||
/**
|
|
||||||
* @param lv The listview handle
|
|
||||||
*
|
|
||||||
* Get the desired height of the listview widget.
|
|
||||||
*
|
|
||||||
* @returns the desired height.
|
|
||||||
*/
|
|
||||||
unsigned int listview_get_desired_height ( listview *lv );
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param lv The listview handle
|
* @param lv The listview handle
|
||||||
*
|
*
|
||||||
|
@ -131,44 +124,13 @@ void listview_nav_page_next ( listview *lv );
|
||||||
*/
|
*/
|
||||||
void listview_nav_page_prev ( listview *lv );
|
void listview_nav_page_prev ( listview *lv );
|
||||||
|
|
||||||
/**
|
|
||||||
* @param lv Handler to the listview object
|
|
||||||
* @param padding The padding
|
|
||||||
*
|
|
||||||
* Padding on between the widgets.
|
|
||||||
*/
|
|
||||||
void listview_set_padding ( listview *lv, unsigned int padding );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param lv Handler to the listview object
|
|
||||||
* @param lines The maximum number of lines
|
|
||||||
*
|
|
||||||
* Set the maximum number of lines to show.
|
|
||||||
*/
|
|
||||||
void listview_set_max_lines ( listview *lv, unsigned int lines );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param lv Handler to the listview object
|
|
||||||
* @param columns The maximum number of columns
|
|
||||||
*
|
|
||||||
* Set the maximum number of columns to show.
|
|
||||||
*/
|
|
||||||
void listview_set_max_columns ( listview *lv, unsigned int columns );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param lv Handler to the listview object
|
|
||||||
* @param enabled enable
|
|
||||||
*
|
|
||||||
* Set fixed num lines mode.
|
|
||||||
*/
|
|
||||||
void listview_set_fixed_num_lines ( listview *lv, gboolean enabled );
|
|
||||||
/**
|
/**
|
||||||
* @param lv Handler to the listview object
|
* @param lv Handler to the listview object
|
||||||
* @param enabled enable
|
* @param enabled enable
|
||||||
*
|
*
|
||||||
* Hide the scrollbar.
|
* Hide the scrollbar.
|
||||||
*/
|
*/
|
||||||
void listview_set_hide_scrollbar ( listview *lv, gboolean enabled );
|
void listview_set_show_scrollbar ( listview *lv, gboolean enabled );
|
||||||
/**
|
/**
|
||||||
* @param lv Handler to the listview object
|
* @param lv Handler to the listview object
|
||||||
* @param width Width in pixels
|
* @param width Width in pixels
|
||||||
|
@ -207,6 +169,47 @@ void listview_set_mouse_activated_cb ( listview *lv, listview_mouse_activated_cb
|
||||||
* Enable,disable multi-select.
|
* Enable,disable multi-select.
|
||||||
*/
|
*/
|
||||||
void listview_set_multi_select ( listview *lv, gboolean enable );
|
void listview_set_multi_select ( listview *lv, gboolean enable );
|
||||||
|
/**
|
||||||
|
* @param lv Handler to the listview object.
|
||||||
|
* @param num_lines the maximum number of lines to display.
|
||||||
|
*
|
||||||
|
* Set the maximum number of lines to display.
|
||||||
|
*/
|
||||||
|
void listview_set_num_lines ( listview *lv, unsigned int num_lines );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param lv Handler to the listview object.
|
||||||
|
*
|
||||||
|
* Get the maximum number of lines to display.
|
||||||
|
*
|
||||||
|
* @returns get the numger of lines to display.
|
||||||
|
*/
|
||||||
|
unsigned int listview_get_num_lines ( listview *lv );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param lv Handler to the listview object.
|
||||||
|
*
|
||||||
|
* Get the fixed-height property.
|
||||||
|
*
|
||||||
|
* @returns get fixed-height.
|
||||||
|
*/
|
||||||
|
gboolean listview_get_fixed_num_lines ( listview *lv );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param lv Handler to the listview object.
|
||||||
|
*
|
||||||
|
* Set fixed num lines mode.
|
||||||
|
*/
|
||||||
|
void listview_set_fixed_num_lines ( listview *lv );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param lv Handler to the listview object.
|
||||||
|
* @param max_lines the maximum number of lines to display.
|
||||||
|
*
|
||||||
|
* Set the maximum number of lines to display.
|
||||||
|
*/
|
||||||
|
void listview_set_max_lines ( listview *lv, unsigned int max_lines );
|
||||||
|
|
||||||
/* @} */
|
/* @} */
|
||||||
|
|
||||||
#endif // ROFI_LISTVIEW_H
|
#endif // ROFI_LISTVIEW_H
|
||||||
|
|
|
@ -19,19 +19,17 @@ typedef struct _scrollbar
|
||||||
unsigned int length;
|
unsigned int length;
|
||||||
unsigned int pos;
|
unsigned int pos;
|
||||||
unsigned int pos_length;
|
unsigned int pos_length;
|
||||||
|
Distance width;
|
||||||
} scrollbar;
|
} scrollbar;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param x The x coordinate (relative to parent) to position the new scrollbar
|
* @param name The name of the widget.
|
||||||
* @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
|
* Create a new scrollbar
|
||||||
*
|
*
|
||||||
* @returns the scrollbar object.
|
* @returns the scrollbar object.
|
||||||
*/
|
*/
|
||||||
scrollbar *scrollbar_create ( short x, short y, short w, short h );
|
scrollbar *scrollbar_create ( const char *name );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param sb scrollbar object
|
* @param sb scrollbar object
|
||||||
|
|
|
@ -1,65 +0,0 @@
|
||||||
#ifndef ROFI_SEPARATOR_H
|
|
||||||
#define ROFI_SEPARATOR_H
|
|
||||||
#include <cairo.h>
|
|
||||||
#include "widget.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @defgroup separator separator
|
|
||||||
* @ingroup widget
|
|
||||||
*
|
|
||||||
* Displays a horizontal separator line. The height of the widget determines the line width.
|
|
||||||
*
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Abstract handle to the separator widget internal state.
|
|
||||||
*/
|
|
||||||
typedef struct _separator separator;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Direction of the separator.
|
|
||||||
*/
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
S_HORIZONTAL = 0,
|
|
||||||
S_VERTICAL = 1
|
|
||||||
} separator_type;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The style of the separator line.
|
|
||||||
*/
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
S_LINE_NONE,
|
|
||||||
S_LINE_SOLID,
|
|
||||||
S_LINE_DASH
|
|
||||||
} separator_line_style;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param type The type of separator.
|
|
||||||
* @param sw The thickness of the separator.
|
|
||||||
*
|
|
||||||
* Create a horizontal separator with height h.
|
|
||||||
*
|
|
||||||
* @returns a new separator, free with ::widget_free
|
|
||||||
*/
|
|
||||||
separator *separator_create ( separator_type type, short sw );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param sp The separator widget handle.
|
|
||||||
* @param style_str String representation of the style.
|
|
||||||
*
|
|
||||||
* Sets the line style based on the string style_str
|
|
||||||
*/
|
|
||||||
void separator_set_line_style_from_string ( separator *sp, const char *style_str );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param sp The separator widget handle.
|
|
||||||
* @param style The new style.
|
|
||||||
*
|
|
||||||
* Sets the line style.
|
|
||||||
*/
|
|
||||||
void separator_set_line_style ( separator *sp, separator_line_style style );
|
|
||||||
/*@}*/
|
|
||||||
#endif // ROFI_SEPARATOR_H
|
|
|
@ -39,6 +39,8 @@ typedef struct
|
||||||
int update;
|
int update;
|
||||||
int blink;
|
int blink;
|
||||||
guint blink_timeout;
|
guint blink_timeout;
|
||||||
|
//
|
||||||
|
const char *theme_name ;
|
||||||
} textbox;
|
} textbox;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -84,11 +86,8 @@ typedef enum
|
||||||
} TextBoxFontType;
|
} TextBoxFontType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param name The name of the to be created widget.
|
||||||
* @param flags #TextboxFlags indicating the type of textbox.
|
* @param flags #TextboxFlags indicating the type of textbox.
|
||||||
* @param x horizontal positon of textbox
|
|
||||||
* @param y vertical position of textbox
|
|
||||||
* @param w width of textbox
|
|
||||||
* @param h height of textbox
|
|
||||||
* @param tbft #TextBoxFontType current state of textbox.
|
* @param tbft #TextBoxFontType current state of textbox.
|
||||||
* @param text intial text to display.
|
* @param text intial text to display.
|
||||||
*
|
*
|
||||||
|
@ -97,8 +96,7 @@ typedef enum
|
||||||
* free with #widget_free
|
* free with #widget_free
|
||||||
* @returns a new #textbox
|
* @returns a new #textbox
|
||||||
*/
|
*/
|
||||||
textbox* textbox_create ( TextboxFlags flags,
|
textbox* textbox_create ( const char *name, TextboxFlags flags,
|
||||||
short x, short y, short w, short h,
|
|
||||||
TextBoxFontType tbft,
|
TextBoxFontType tbft,
|
||||||
const char *text );
|
const char *text );
|
||||||
/**
|
/**
|
||||||
|
@ -200,6 +198,13 @@ int textbox_get_font_width ( const textbox *tb );
|
||||||
*/
|
*/
|
||||||
double textbox_get_estimated_char_width ( void );
|
double textbox_get_estimated_char_width ( void );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Estimate the height of a character.
|
||||||
|
*
|
||||||
|
* @returns the height of a character in pixels.
|
||||||
|
*/
|
||||||
|
double textbox_get_estimated_char_height ( void );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param tb Handle to the textbox
|
* @param tb Handle to the textbox
|
||||||
* @param pos The start position
|
* @param pos The start position
|
||||||
|
@ -220,12 +225,17 @@ void textbox_delete ( textbox *tb, int pos, int dlen );
|
||||||
* TODO remove for #widget_resize and #widget_move
|
* TODO remove for #widget_resize and #widget_move
|
||||||
*/
|
*/
|
||||||
void textbox_moveresize ( textbox *tb, int x, int y, int w, int h );
|
void textbox_moveresize ( textbox *tb, int x, int y, int w, int h );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param tb Handle to the textbox
|
||||||
|
* @param eh The number of rows to display
|
||||||
|
*
|
||||||
* Get the (estimated) with of a character, can be used to calculate window width.
|
* Get the (estimated) with of a character, can be used to calculate window width.
|
||||||
|
* This includes padding.
|
||||||
*
|
*
|
||||||
* @returns the estimated width of a character.
|
* @returns the estimated width of a character.
|
||||||
*/
|
*/
|
||||||
int textbox_get_estimated_char_height ( void );
|
int textbox_get_estimated_height ( const textbox *tb, int eh );
|
||||||
/**
|
/**
|
||||||
* @param p The new default PangoContext
|
* @param p The new default PangoContext
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#ifndef WIDGET_INTERNAL_H
|
#ifndef WIDGET_INTERNAL_H
|
||||||
#define WIDGET_INTERNAL_H
|
#define WIDGET_INTERNAL_H
|
||||||
|
|
||||||
|
#include "theme.h"
|
||||||
/**
|
/**
|
||||||
* Data structure holding the internal state of the Widget
|
* Data structure holding the internal state of the Widget
|
||||||
*/
|
*/
|
||||||
|
@ -14,10 +15,17 @@ struct _widget
|
||||||
short w;
|
short w;
|
||||||
/** Height of the widget */
|
/** Height of the widget */
|
||||||
short h;
|
short h;
|
||||||
|
/** Padding */
|
||||||
|
Padding margin;
|
||||||
|
Padding padding;
|
||||||
|
Padding border;
|
||||||
|
|
||||||
/** enabled or not */
|
/** enabled or not */
|
||||||
gboolean enabled;
|
gboolean enabled;
|
||||||
/** Expand the widget when packed */
|
/** Expand the widget when packed */
|
||||||
gboolean expand;
|
gboolean expand;
|
||||||
|
/*** The packing index */
|
||||||
|
int index;
|
||||||
/** Place widget at end of parent */
|
/** Place widget at end of parent */
|
||||||
gboolean end;
|
gboolean end;
|
||||||
/** Parent widget */
|
/** Parent widget */
|
||||||
|
@ -38,6 +46,8 @@ struct _widget
|
||||||
/** Handle mouse motion, used for dragging */
|
/** Handle mouse motion, used for dragging */
|
||||||
gboolean ( *motion_notify )( struct _widget *, xcb_motion_notify_event_t * );
|
gboolean ( *motion_notify )( struct _widget *, xcb_motion_notify_event_t * );
|
||||||
|
|
||||||
|
int (*get_desired_height) ( struct _widget * );
|
||||||
|
|
||||||
/** widget clicked callback */
|
/** widget clicked callback */
|
||||||
widget_clicked_cb clicked;
|
widget_clicked_cb clicked;
|
||||||
/** user data for clicked callback */
|
/** user data for clicked callback */
|
||||||
|
@ -45,5 +55,95 @@ struct _widget
|
||||||
|
|
||||||
/** Free widget callback */
|
/** Free widget callback */
|
||||||
void ( *free )( struct _widget *widget );
|
void ( *free )( struct _widget *widget );
|
||||||
|
|
||||||
|
/** Name of widget (used for theming) */
|
||||||
|
char *name;
|
||||||
|
const char *state;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param widget The widget to initialize.
|
||||||
|
* @param name The name of the widget.
|
||||||
|
*
|
||||||
|
* Initializes the widget structure.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void widget_init ( widget *widget , const char *name );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param widget The widget handle.
|
||||||
|
* @param state The state of the widget.
|
||||||
|
*
|
||||||
|
* Set the state of the widget.
|
||||||
|
*/
|
||||||
|
void widget_set_state ( widget *widget, const char *state );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param wid The widget handle.
|
||||||
|
*
|
||||||
|
* Get the left padding of the widget.
|
||||||
|
*
|
||||||
|
* @returns the left padding in pixels.
|
||||||
|
*/
|
||||||
|
int widget_padding_get_left ( const widget *wid );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param wid The widget handle.
|
||||||
|
*
|
||||||
|
* Get the right padding of the widget.
|
||||||
|
*
|
||||||
|
* @returns the right padding in pixels.
|
||||||
|
*/
|
||||||
|
int widget_padding_get_right ( const widget *wid );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param wid The widget handle.
|
||||||
|
*
|
||||||
|
* Get the top padding of the widget.
|
||||||
|
*
|
||||||
|
* @returns the top padding in pixels.
|
||||||
|
*/
|
||||||
|
int widget_padding_get_top ( const widget *wid );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param wid The widget handle.
|
||||||
|
*
|
||||||
|
* Get the bottom padding of the widget.
|
||||||
|
*
|
||||||
|
* @returns the bottom padding in pixels.
|
||||||
|
*/
|
||||||
|
int widget_padding_get_bottom ( const widget *wid );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param wid The widget handle.
|
||||||
|
*
|
||||||
|
* Get width of the content of the widget
|
||||||
|
*
|
||||||
|
* @returns the widget width, excluding padding.
|
||||||
|
*/
|
||||||
|
int widget_padding_get_remaining_width ( const widget *wid );
|
||||||
|
/**
|
||||||
|
* @param wid The widget handle.
|
||||||
|
*
|
||||||
|
* Get height of the content of the widget
|
||||||
|
*
|
||||||
|
* @returns the widget height, excluding padding.
|
||||||
|
*/
|
||||||
|
int widget_padding_get_remaining_height ( const widget *wid );
|
||||||
|
/**
|
||||||
|
* @param wid The widget handle.
|
||||||
|
*
|
||||||
|
* Get the combined top and bottom padding.
|
||||||
|
*
|
||||||
|
* @returns the top and bottom padding of the widget in pixels.
|
||||||
|
*/
|
||||||
|
int widget_padding_get_padding_height ( const widget *wid );
|
||||||
|
/**
|
||||||
|
* @param wid The widget handle.
|
||||||
|
*
|
||||||
|
* Get the combined left and right padding.
|
||||||
|
*
|
||||||
|
* @returns the left and right padding of the widget in pixels.
|
||||||
|
*/
|
||||||
|
int widget_padding_get_padding_width ( const widget *wid );
|
||||||
#endif // WIDGET_INTERNAL_H
|
#endif // WIDGET_INTERNAL_H
|
||||||
|
|
|
@ -173,5 +173,24 @@ void widget_set_clicked_handler ( widget *wid, widget_clicked_cb cb, void *udata
|
||||||
* returns TRUE when handled.
|
* returns TRUE when handled.
|
||||||
*/
|
*/
|
||||||
gboolean widget_motion_notify ( widget *wid, xcb_motion_notify_event_t *xme );
|
gboolean widget_motion_notify ( widget *wid, xcb_motion_notify_event_t *xme );
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param wid The widget handle
|
||||||
|
* @param name The name of the widget.
|
||||||
|
*
|
||||||
|
* Set name on widget.
|
||||||
|
*/
|
||||||
|
void widget_set_name ( widget *wid, const char *name );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param wid The widget handle
|
||||||
|
*
|
||||||
|
* Get the desired height of this widget recursively.
|
||||||
|
*
|
||||||
|
* @returns the desired height of the widget in pixels.
|
||||||
|
*/
|
||||||
|
int widget_get_desired_height ( widget *wid );
|
||||||
|
|
||||||
/*@}*/
|
/*@}*/
|
||||||
#endif // ROFI_WIDGET_H
|
#endif // ROFI_WIDGET_H
|
||||||
|
|
336
lexer/theme-lexer.l
Normal file
336
lexer/theme-lexer.l
Normal file
|
@ -0,0 +1,336 @@
|
||||||
|
%option noyywrap nounput never-interactive
|
||||||
|
%option bison-locations
|
||||||
|
|
||||||
|
%{
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include "lexer/theme-parser.h"
|
||||||
|
int last_state = 0;
|
||||||
|
GQueue *queue = NULL;
|
||||||
|
|
||||||
|
%}
|
||||||
|
%{
|
||||||
|
|
||||||
|
int str_len = 0;
|
||||||
|
char *input_str = NULL;
|
||||||
|
|
||||||
|
#define YY_INPUT(buf,result,max_size) \
|
||||||
|
{\
|
||||||
|
if ( input_str == NULL ) { \
|
||||||
|
errno =0; \
|
||||||
|
while ( (result = (int) fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
|
||||||
|
{ \
|
||||||
|
if( errno != EINTR) \
|
||||||
|
{ \
|
||||||
|
YY_FATAL_ERROR( "input in flex scanner failed" ); \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
errno=0; \
|
||||||
|
clearerr(yyin); \
|
||||||
|
} \
|
||||||
|
} else {\
|
||||||
|
yy_size_t len = MIN (max_size, str_len);\
|
||||||
|
if ( len > 0 ){\
|
||||||
|
memcpy (buf, input_str, len);\
|
||||||
|
input_str+=len;\
|
||||||
|
str_len-=len;\
|
||||||
|
result = len;\
|
||||||
|
} else {\
|
||||||
|
result = YY_NULL;\
|
||||||
|
} \
|
||||||
|
}\
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define YY_USER_ACTION {\
|
||||||
|
yylloc->last_column+= yyleng;\
|
||||||
|
}
|
||||||
|
#define YY_LLOC_START {\
|
||||||
|
yylloc->first_line = yylloc->last_line;\
|
||||||
|
yylloc->first_column = yylloc->last_column;\
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
WHITESPACE [[:blank:]]
|
||||||
|
WORD [[:alnum:]-]+
|
||||||
|
STRING [[:print:]]+
|
||||||
|
HEX [[:xdigit:]]
|
||||||
|
NUMBER [[:digit:]]
|
||||||
|
REAL [[:digit:]]+(\.[[:digit:]]+)?
|
||||||
|
PX (px)
|
||||||
|
EM (em)
|
||||||
|
PERCENT (\%)
|
||||||
|
|
||||||
|
ASTERIX \*
|
||||||
|
|
||||||
|
CENTER "center"
|
||||||
|
NORTH "north"
|
||||||
|
SOUTH "south"
|
||||||
|
EAST "east"
|
||||||
|
WEST "west"
|
||||||
|
|
||||||
|
LS_DASH "dash"
|
||||||
|
LS_SOLID "solid"
|
||||||
|
|
||||||
|
%x PROPERTIES
|
||||||
|
%x NAMESTR
|
||||||
|
%x ENTRY
|
||||||
|
%x DEFAULTS
|
||||||
|
%%
|
||||||
|
|
||||||
|
%{
|
||||||
|
YY_LLOC_START
|
||||||
|
%}
|
||||||
|
%{
|
||||||
|
if ( queue == NULL ){
|
||||||
|
queue = g_queue_new ( );
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
|
||||||
|
<*>"//" {
|
||||||
|
int c;
|
||||||
|
while ((c = input()) != EOF){
|
||||||
|
if (c == '\n') {
|
||||||
|
yylloc->last_column = 1;
|
||||||
|
yylloc->last_line ++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
yylloc->last_column++;
|
||||||
|
}
|
||||||
|
YY_LLOC_START
|
||||||
|
}
|
||||||
|
<*>"/*" {
|
||||||
|
int c = 0, p;
|
||||||
|
int nesting_depth = 1;
|
||||||
|
while (nesting_depth) {
|
||||||
|
p = c;
|
||||||
|
c = input();
|
||||||
|
switch (c) {
|
||||||
|
case '*': yylloc->last_column++; if (p == '/') { c = 0; nesting_depth++; } break;
|
||||||
|
case '/': yylloc->last_column++; if (p == '*') { c = 0; nesting_depth--; } break;
|
||||||
|
case '\n': {
|
||||||
|
yylloc->last_column = 1;
|
||||||
|
yylloc->last_line ++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case EOF: nesting_depth = 0; break;
|
||||||
|
default:
|
||||||
|
yylloc->last_column++;
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
YY_LLOC_START
|
||||||
|
}
|
||||||
|
|
||||||
|
<INITIAL>{ASTERIX} {
|
||||||
|
g_queue_push_head ( queue, GINT_TO_POINTER (YY_START) );
|
||||||
|
BEGIN(DEFAULTS);
|
||||||
|
return PDEFAULTS;
|
||||||
|
}
|
||||||
|
<DEFAULTS>{WHITESPACE} {}
|
||||||
|
<DEFAULTS>"\{" {
|
||||||
|
g_queue_push_head ( queue, GINT_TO_POINTER (YY_START) );
|
||||||
|
BEGIN(ENTRY);
|
||||||
|
return BOPEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Go into parsing an entry */
|
||||||
|
<NAMESTR>"\{" {
|
||||||
|
g_queue_push_head ( queue, GINT_TO_POINTER (YY_START) );
|
||||||
|
BEGIN(ENTRY);
|
||||||
|
return BOPEN;
|
||||||
|
}
|
||||||
|
/* Pop out of parsing an entry. */
|
||||||
|
<ENTRY>"\}" {
|
||||||
|
g_queue_pop_head ( queue );
|
||||||
|
BEGIN(GPOINTER_TO_INT(g_queue_pop_head ( queue )));
|
||||||
|
return BCLOSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
<INITIAL>"#" { g_queue_push_head ( queue, GINT_TO_POINTER (YY_START) ); BEGIN(NAMESTR);return NAME_PREFIX;}
|
||||||
|
<NAMESTR>\.|{WHITESPACE} { return NSEP; }
|
||||||
|
<ENTRY>{WORD} { yylval->sval = g_strdup(yytext); return N_STRING;}
|
||||||
|
<NAMESTR>{WORD} { yylval->sval = g_strdup(yytext); return NAME_ELEMENT;}
|
||||||
|
|
||||||
|
/* After Namestr/Classstr we want to go to state str, then to { */
|
||||||
|
/*<NAMESTR>{WHITESPACE} { BEGIN(GPOINTER_TO_INT (g_queue_pop_head ( queue )));}*/
|
||||||
|
<INITIAL,ENTRY>{WHITESPACE}+ ; // ignore all whitespace
|
||||||
|
<PROPERTIES>{WHITESPACE}+ ; // ignore all whitespace
|
||||||
|
|
||||||
|
<INITIAL,ENTRY>":" { g_queue_push_head ( queue, GINT_TO_POINTER (YY_START) ); BEGIN(PROPERTIES); return PSEP; }
|
||||||
|
<PROPERTIES>";" { BEGIN(GPOINTER_TO_INT ( g_queue_pop_head ( queue ))); return PCLOSE;}
|
||||||
|
<PROPERTIES>(true|false) { yylval->bval= g_strcmp0(yytext, "true") == 0; return T_BOOLEAN;}
|
||||||
|
<PROPERTIES>{NUMBER}+ { yylval->ival = (int)g_ascii_strtoll(yytext, NULL, 10); return T_INT;}
|
||||||
|
<PROPERTIES>{NUMBER}+\.{NUMBER}+ { yylval->fval = g_ascii_strtod(yytext, NULL); return T_DOUBLE;}
|
||||||
|
<PROPERTIES>\"{STRING}\" { yytext[yyleng-1] = '\0'; yylval->sval = g_strdup(&yytext[1]); return T_STRING;}
|
||||||
|
<PROPERTIES>@{WORD} {
|
||||||
|
yylval->sval = g_strdup(yytext);
|
||||||
|
return T_LINK;
|
||||||
|
}
|
||||||
|
|
||||||
|
<PROPERTIES>{REAL}{EM} {
|
||||||
|
yylval->distance.distance = (double)g_ascii_strtod(yytext, NULL);
|
||||||
|
yylval->distance.type = PW_EM;
|
||||||
|
yylval->distance.style = SOLID;
|
||||||
|
return T_PIXEL;
|
||||||
|
}
|
||||||
|
<PROPERTIES>{NUMBER}+{PX} {
|
||||||
|
yylval->distance.distance = (double)g_ascii_strtoll(yytext, NULL, 10);
|
||||||
|
yylval->distance.type = PW_PX;
|
||||||
|
yylval->distance.style = SOLID;
|
||||||
|
return T_PIXEL;
|
||||||
|
}
|
||||||
|
<PROPERTIES>{NUMBER}+{PX}{WHITESPACE}{LS_DASH} {
|
||||||
|
yylval->distance.distance = (double)g_ascii_strtoll(yytext, NULL, 10);
|
||||||
|
yylval->distance.type = PW_PX;
|
||||||
|
yylval->distance.style = DASH;
|
||||||
|
return T_PIXEL;
|
||||||
|
}
|
||||||
|
<PROPERTIES>{NUMBER}+{EM}{WHITESPACE}{LS_DASH} {
|
||||||
|
yylval->distance.distance = (double)g_ascii_strtoll(yytext, NULL, 10);
|
||||||
|
yylval->distance.type = PW_PX;
|
||||||
|
yylval->distance.style = DASH;
|
||||||
|
return T_PIXEL;
|
||||||
|
}
|
||||||
|
<PROPERTIES>{NUMBER}+{PX}{WHITESPACE}{LS_SOLID} {
|
||||||
|
yylval->distance.distance = (double)g_ascii_strtoll(yytext, NULL, 10);
|
||||||
|
yylval->distance.type = PW_PX;
|
||||||
|
yylval->distance.style = SOLID;
|
||||||
|
return T_PIXEL;
|
||||||
|
}
|
||||||
|
<PROPERTIES>{NUMBER}+{EM}{WHITESPACE}{LS_SOLID} {
|
||||||
|
yylval->distance.distance = (double)g_ascii_strtoll(yytext, NULL, 10);
|
||||||
|
yylval->distance.type = PW_PX;
|
||||||
|
yylval->distance.style = SOLID;
|
||||||
|
return T_PIXEL;
|
||||||
|
}
|
||||||
|
<PROPERTIES>{REAL}{PERCENT} {
|
||||||
|
yylval->distance.distance = (double)g_ascii_strtod(yytext, NULL);
|
||||||
|
yylval->distance.type = PW_PERCENT;
|
||||||
|
yylval->distance.style = SOLID;
|
||||||
|
return T_PIXEL;
|
||||||
|
}
|
||||||
|
<PROPERTIES>{REAL}{PERCENT}{WHITESPACE}{LS_SOLID} {
|
||||||
|
yylval->distance.distance = (double)g_ascii_strtod(yytext, NULL);
|
||||||
|
yylval->distance.type = PW_PERCENT;
|
||||||
|
yylval->distance.style = SOLID;
|
||||||
|
return T_PIXEL;
|
||||||
|
}
|
||||||
|
<PROPERTIES>{REAL}{PERCENT}{WHITESPACE}{LS_DASH} {
|
||||||
|
yylval->distance.distance = (double)g_ascii_strtod(yytext, NULL);
|
||||||
|
yylval->distance.type = PW_PERCENT;
|
||||||
|
yylval->distance.style = DASH;
|
||||||
|
return T_PIXEL;
|
||||||
|
}
|
||||||
|
<PROPERTIES>#{HEX}{8} {
|
||||||
|
union { unsigned int val; struct { unsigned char b,g,r,a;};} val;
|
||||||
|
val.val = (unsigned int)strtoull ( &yytext[1], NULL, 16);
|
||||||
|
yylval->colorval.alpha = val.a/255.0;
|
||||||
|
yylval->colorval.red = val.r/255.0;
|
||||||
|
yylval->colorval.green = val.g/255.0;
|
||||||
|
yylval->colorval.blue = val.b/255.0;
|
||||||
|
return T_COLOR;
|
||||||
|
}
|
||||||
|
<PROPERTIES>argb:{HEX}{8} {
|
||||||
|
union { unsigned int val; struct { unsigned char b,g,r,a;};} val;
|
||||||
|
val.val = (unsigned int)strtoull ( &yytext[1], NULL, 16);
|
||||||
|
yylval->colorval.alpha = val.a/255.0;
|
||||||
|
yylval->colorval.red = val.r/255.0;
|
||||||
|
yylval->colorval.green = val.g/255.0;
|
||||||
|
yylval->colorval.blue = val.b/255.0;
|
||||||
|
return T_COLOR;
|
||||||
|
}
|
||||||
|
<PROPERTIES>#{HEX}{6} {
|
||||||
|
union { unsigned int val; struct { unsigned char b,g,r,a;};} val;
|
||||||
|
val.val = (unsigned int)g_ascii_strtoull ( &yytext[1], NULL, 16);
|
||||||
|
yylval->colorval.alpha = 1.0;
|
||||||
|
yylval->colorval.red = val.r/255.0;
|
||||||
|
yylval->colorval.green = val.g/255.0;
|
||||||
|
yylval->colorval.blue = val.b/255.0;
|
||||||
|
return T_COLOR;
|
||||||
|
}
|
||||||
|
<PROPERTIES>rgba\({NUMBER}{1,3},{NUMBER}{1,3},{NUMBER}{1,3},[01](\.{NUMBER}+)?\) {
|
||||||
|
char *endptr = &yytext[5];
|
||||||
|
yylval->colorval.red = g_ascii_strtoull ( endptr, &endptr, 10);
|
||||||
|
yylval->colorval.green= g_ascii_strtoull ( endptr+1, &endptr, 10);
|
||||||
|
yylval->colorval.blue= g_ascii_strtoull ( endptr+1, &endptr, 10);
|
||||||
|
yylval->colorval.alpha= g_ascii_strtod ( endptr+1, NULL);
|
||||||
|
return T_COLOR;
|
||||||
|
}
|
||||||
|
<PROPERTIES>rgb\({NUMBER}{1,3},{NUMBER}{1,3},{NUMBER}{1,3}\) {
|
||||||
|
char *endptr = &yytext[4];
|
||||||
|
yylval->colorval.red = g_ascii_strtoull ( endptr, &endptr, 10);
|
||||||
|
yylval->colorval.green = g_ascii_strtoull ( endptr+1, &endptr, 10);
|
||||||
|
yylval->colorval.blue = g_ascii_strtoull ( endptr+1, &endptr, 10);
|
||||||
|
yylval->colorval.alpha = 1.0;
|
||||||
|
return T_COLOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
<PROPERTIES>{CENTER} {
|
||||||
|
yylval->ival = WL_CENTER;
|
||||||
|
return T_POSITION;
|
||||||
|
}
|
||||||
|
<PROPERTIES>{EAST} {
|
||||||
|
yylval->ival = WL_EAST;
|
||||||
|
return T_POSITION;
|
||||||
|
}
|
||||||
|
<PROPERTIES>{WEST} {
|
||||||
|
yylval->ival = WL_WEST;
|
||||||
|
return T_POSITION;
|
||||||
|
}
|
||||||
|
<PROPERTIES>{SOUTH}{EAST} {
|
||||||
|
yylval->ival = WL_SOUTH_EAST;
|
||||||
|
return T_POSITION;
|
||||||
|
}
|
||||||
|
<PROPERTIES>{SOUTH}{WEST} {
|
||||||
|
yylval->ival = WL_SOUTH_WEST;
|
||||||
|
return T_POSITION;
|
||||||
|
}
|
||||||
|
<PROPERTIES>{SOUTH} {
|
||||||
|
yylval->ival = WL_SOUTH;
|
||||||
|
return T_POSITION;
|
||||||
|
}
|
||||||
|
<PROPERTIES>{NORTH}{EAST} {
|
||||||
|
yylval->ival = WL_NORTH_EAST;
|
||||||
|
return T_POSITION;
|
||||||
|
}
|
||||||
|
<PROPERTIES>{NORTH}{WEST} {
|
||||||
|
yylval->ival = WL_NORTH_WEST;
|
||||||
|
return T_POSITION;
|
||||||
|
}
|
||||||
|
<PROPERTIES>{NORTH} {
|
||||||
|
yylval->ival = WL_NORTH;
|
||||||
|
return T_POSITION;
|
||||||
|
}
|
||||||
|
<PROPERTIES>NORTH {
|
||||||
|
yylval->ival = WL_NORTH;
|
||||||
|
return T_POSITION;
|
||||||
|
}
|
||||||
|
<INITIAL><<EOF>> {
|
||||||
|
g_queue_free ( queue );
|
||||||
|
// Reset pointer to NULL
|
||||||
|
queue = NULL;
|
||||||
|
yyterminate();
|
||||||
|
}
|
||||||
|
|
||||||
|
<*>\n {
|
||||||
|
yylloc->last_column = 1;
|
||||||
|
yylloc->last_line ++;
|
||||||
|
};
|
||||||
|
<*>(\r\n) {
|
||||||
|
yylloc->last_column = 1;
|
||||||
|
yylloc->last_line ++;
|
||||||
|
};
|
||||||
|
<INITIAL>. {
|
||||||
|
const char *error_msg = "Expected 'root' element or a 'named' element.\n"\
|
||||||
|
"Place all global properties in a root element:\n"\
|
||||||
|
" * {\n"\
|
||||||
|
" }\n";
|
||||||
|
YY_FATAL_ERROR( error_msg );
|
||||||
|
}
|
||||||
|
<*>. {
|
||||||
|
fprintf(stderr, "Invalid character: '%c'\n", *yytext);
|
||||||
|
yyterminate();
|
||||||
|
}
|
||||||
|
|
||||||
|
%%
|
185
lexer/theme-parser.y
Normal file
185
lexer/theme-parser.y
Normal file
|
@ -0,0 +1,185 @@
|
||||||
|
%define api.pure
|
||||||
|
%glr-parser
|
||||||
|
%skeleton "glr.c"
|
||||||
|
%locations
|
||||||
|
%debug
|
||||||
|
%error-verbose
|
||||||
|
|
||||||
|
%code requires {
|
||||||
|
#include "theme.h"
|
||||||
|
}
|
||||||
|
%{
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include "lexer/theme-parser.h"
|
||||||
|
ThemeWidget *rofi_theme = NULL;
|
||||||
|
void yyerror(YYLTYPE *yylloc, const char* s);
|
||||||
|
int yylex (YYSTYPE *, YYLTYPE *);
|
||||||
|
%}
|
||||||
|
|
||||||
|
%union {
|
||||||
|
int ival;
|
||||||
|
double fval;
|
||||||
|
char *sval;
|
||||||
|
int bval;
|
||||||
|
ThemeColor colorval;
|
||||||
|
ThemeWidget *theme;
|
||||||
|
GList *name_path;
|
||||||
|
Property *property;
|
||||||
|
GHashTable *property_list;
|
||||||
|
Distance distance;
|
||||||
|
}
|
||||||
|
|
||||||
|
%token <ival> T_INT
|
||||||
|
%token <fval> T_DOUBLE
|
||||||
|
%token <sval> T_STRING
|
||||||
|
%token <sval> N_STRING
|
||||||
|
%token <ival> T_POSITION;
|
||||||
|
%token <sval> NAME_ELEMENT "Element name"
|
||||||
|
%token <bval> T_BOOLEAN
|
||||||
|
%token <colorval> T_COLOR
|
||||||
|
%token <distance> T_PIXEL
|
||||||
|
%token <sval> T_LINK
|
||||||
|
%token <sval> FIRST_NAME
|
||||||
|
|
||||||
|
%token BOPEN "bracket open";
|
||||||
|
%token BCLOSE "bracket close";
|
||||||
|
%token PSEP "property separator";
|
||||||
|
%token PCLOSE "property close";
|
||||||
|
%token NSEP "Name separator";
|
||||||
|
%token NAME_PREFIX "Name prefix";
|
||||||
|
%token WHITESPACE "White space";
|
||||||
|
%token PDEFAULTS "Default settings";
|
||||||
|
|
||||||
|
%type <sval> entry
|
||||||
|
%type <sval> pvalue
|
||||||
|
%type <theme> entries
|
||||||
|
%type <name_path> name_path
|
||||||
|
%type <property> property
|
||||||
|
%type <property_list> property_list
|
||||||
|
%type <property_list> optional_properties
|
||||||
|
%start entries
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
entries:
|
||||||
|
%empty {
|
||||||
|
// There is always a base widget.
|
||||||
|
if (rofi_theme == NULL ){
|
||||||
|
$$ = rofi_theme = (ThemeWidget*)g_malloc0 (sizeof(ThemeWidget));
|
||||||
|
rofi_theme->name = g_strdup ( "Root" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
| entries
|
||||||
|
entry {
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
entry:
|
||||||
|
NAME_PREFIX name_path BOPEN optional_properties BCLOSE
|
||||||
|
{
|
||||||
|
ThemeWidget *widget = rofi_theme;
|
||||||
|
for ( GList *iter = g_list_first ( $2 ); iter ; iter = g_list_next ( iter ) ) {
|
||||||
|
widget = rofi_theme_find_or_create_name ( widget, iter->data );
|
||||||
|
}
|
||||||
|
g_list_foreach ( $2, (GFunc)g_free , NULL );
|
||||||
|
g_list_free ( $2 );
|
||||||
|
widget->set = TRUE;
|
||||||
|
rofi_theme_widget_add_properties ( widget, $4);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
PDEFAULTS BOPEN optional_properties BCLOSE {
|
||||||
|
rofi_theme_widget_add_properties ( rofi_theme, $3);
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* properties
|
||||||
|
*/
|
||||||
|
optional_properties
|
||||||
|
: %empty { $$ = NULL; }
|
||||||
|
| property_list { $$ = $1; }
|
||||||
|
;
|
||||||
|
|
||||||
|
property_list:
|
||||||
|
property {
|
||||||
|
$$ = g_hash_table_new_full ( g_str_hash, g_str_equal, NULL, (GDestroyNotify)rofi_theme_property_free );
|
||||||
|
g_hash_table_replace ( $$, $1->name, $1 );
|
||||||
|
}
|
||||||
|
| property_list property {
|
||||||
|
// Old will be free'ed, and key/value will be replaced.
|
||||||
|
g_hash_table_replace ( $$, $2->name, $2 );
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
property
|
||||||
|
: pvalue PSEP T_INT PCLOSE {
|
||||||
|
$$ = rofi_theme_property_create ( P_INTEGER );
|
||||||
|
$$->name = $1;
|
||||||
|
$$->value.i = $3;
|
||||||
|
}
|
||||||
|
| pvalue PSEP T_DOUBLE PCLOSE {
|
||||||
|
$$ = rofi_theme_property_create ( P_DOUBLE );
|
||||||
|
$$->name = $1;
|
||||||
|
$$->value.f = $3;
|
||||||
|
}
|
||||||
|
| pvalue PSEP T_COLOR PCLOSE {
|
||||||
|
$$ = rofi_theme_property_create ( P_COLOR );
|
||||||
|
$$->name = $1;
|
||||||
|
$$->value.color = $3;
|
||||||
|
}
|
||||||
|
| pvalue PSEP T_STRING PCLOSE {
|
||||||
|
$$ = rofi_theme_property_create ( P_STRING );
|
||||||
|
$$->name = $1;
|
||||||
|
$$->value.s = $3;
|
||||||
|
}
|
||||||
|
| pvalue PSEP T_LINK PCLOSE {
|
||||||
|
$$ = rofi_theme_property_create ( P_LINK );
|
||||||
|
$$->name = $1;
|
||||||
|
$$->value.link.name = $3;
|
||||||
|
}
|
||||||
|
| pvalue PSEP T_BOOLEAN PCLOSE {
|
||||||
|
$$ = rofi_theme_property_create ( P_BOOLEAN );
|
||||||
|
$$->name = $1;
|
||||||
|
$$->value.b = $3;
|
||||||
|
}
|
||||||
|
| pvalue PSEP T_PIXEL PCLOSE {
|
||||||
|
$$ = rofi_theme_property_create ( P_PADDING );
|
||||||
|
$$->name = $1;
|
||||||
|
$$->value.padding = (Padding){ $3, $3, $3, $3 };
|
||||||
|
}
|
||||||
|
| pvalue PSEP T_PIXEL T_PIXEL PCLOSE {
|
||||||
|
$$ = rofi_theme_property_create ( P_PADDING );
|
||||||
|
$$->name = $1;
|
||||||
|
$$->value.padding = (Padding){ $3, $4, $3, $4 };
|
||||||
|
}
|
||||||
|
| pvalue PSEP T_PIXEL T_PIXEL T_PIXEL PCLOSE {
|
||||||
|
$$ = rofi_theme_property_create ( P_PADDING );
|
||||||
|
$$->name = $1;
|
||||||
|
$$->value.padding = (Padding){ $3, $4, $5, $4 };
|
||||||
|
}
|
||||||
|
| pvalue PSEP T_PIXEL T_PIXEL T_PIXEL T_PIXEL PCLOSE {
|
||||||
|
$$ = rofi_theme_property_create ( P_PADDING );
|
||||||
|
$$->name = $1;
|
||||||
|
$$->value.padding = (Padding){ $3, $4, $5, $6 };
|
||||||
|
}
|
||||||
|
| pvalue PSEP T_POSITION PCLOSE{
|
||||||
|
$$ = rofi_theme_property_create ( P_POSITION );
|
||||||
|
$$->name = $1;
|
||||||
|
$$->value.i = $3;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
pvalue: N_STRING { $$ = $1; }
|
||||||
|
|
||||||
|
name_path:
|
||||||
|
NAME_ELEMENT { $$ = g_list_append ( NULL, $1 );}
|
||||||
|
| name_path NSEP NAME_ELEMENT { $$ = g_list_append ( $1, $3);}
|
||||||
|
| name_path NSEP { $$ = $1; }
|
||||||
|
;
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
76
script/rofi-convert-theme.sh
Executable file
76
script/rofi-convert-theme.sh
Executable file
|
@ -0,0 +1,76 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
#
|
||||||
|
# This code is released in public domain by Dave Davenport <qball@gmpclient.org>
|
||||||
|
# This converts from old style theme (< 1.4) to new style theme (>= 1.4)
|
||||||
|
#
|
||||||
|
function update_color ()
|
||||||
|
{
|
||||||
|
var=${1}
|
||||||
|
var="${var#"${var%%[![:space:]]*}"}" # remove leading whitespace characters
|
||||||
|
var="${var%"${var##*[![:space:]]}"}" # remove trailing whitespace characters
|
||||||
|
if [[ ${var} =~ argb:[0-9a-fA-F]{6,8} ]]
|
||||||
|
then
|
||||||
|
echo "#${var:5}"
|
||||||
|
else
|
||||||
|
echo ${var}
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function parse_window_color ()
|
||||||
|
{
|
||||||
|
OLDIFS=${IFS}
|
||||||
|
IFS=","
|
||||||
|
entries=( ${1} )
|
||||||
|
echo "@window {"
|
||||||
|
echo " background: $( update_color ${entries[0]});"
|
||||||
|
echo " foreground: $( update_color ${entries[1]});"
|
||||||
|
echo "}"
|
||||||
|
if [ -n "${entries[2]}" ]
|
||||||
|
then
|
||||||
|
echo "@separator {"
|
||||||
|
echo " foreground: $( update_color ${entries[2]});"
|
||||||
|
echo "}"
|
||||||
|
echo "@scrollbar {"
|
||||||
|
echo " foreground: $( update_color ${entries[2]});"
|
||||||
|
echo "}"
|
||||||
|
fi
|
||||||
|
IFS=${OLDIFS}
|
||||||
|
}
|
||||||
|
|
||||||
|
function parse_color ()
|
||||||
|
{
|
||||||
|
state=$1
|
||||||
|
OLDIFS=${IFS}
|
||||||
|
IFS=","
|
||||||
|
entries=( ${2} )
|
||||||
|
echo "@textbox normal.${state} { "
|
||||||
|
echo " background: $( update_color ${entries[0]});"
|
||||||
|
echo " foreground: $( update_color ${entries[1]});"
|
||||||
|
echo "}"
|
||||||
|
echo "@textbox selected.${state} { "
|
||||||
|
echo " background: $( update_color ${entries[3]});"
|
||||||
|
echo " foreground: $( update_color ${entries[4]});"
|
||||||
|
echo "}"
|
||||||
|
echo "@textbox alternate.${state} { "
|
||||||
|
echo " background: $( update_color ${entries[2]});"
|
||||||
|
echo " foreground: $( update_color ${entries[1]});"
|
||||||
|
echo "}"
|
||||||
|
IFS=${OLDIFS}
|
||||||
|
}
|
||||||
|
|
||||||
|
while read LINE
|
||||||
|
do
|
||||||
|
if [[ ${LINE} =~ ^rofi\.color-normal: ]]
|
||||||
|
then
|
||||||
|
parse_color "normal" "${LINE:18}"
|
||||||
|
elif [[ ${LINE} =~ ^rofi\.color-urgent: ]]
|
||||||
|
then
|
||||||
|
parse_color "urgent" "${LINE:18}"
|
||||||
|
elif [[ ${LINE} =~ ^rofi\.color-active: ]]
|
||||||
|
then
|
||||||
|
parse_color "active" "${LINE:18}"
|
||||||
|
elif [[ ${LINE} =~ ^rofi\.color-window: ]]
|
||||||
|
then
|
||||||
|
parse_window_color "${LINE:18}"
|
||||||
|
fi
|
||||||
|
done
|
|
@ -295,6 +295,27 @@ int find_arg_str ( const char * const key, char** val )
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char ** find_arg_strv ( const char *const key )
|
||||||
|
{
|
||||||
|
const char **retv =NULL;
|
||||||
|
int length = 0;
|
||||||
|
for ( int i = 0; i < stored_argc; i++ ) {
|
||||||
|
if ( strcasecmp ( stored_argv[i], key ) == 0 && i < (stored_argc -1 ) ){
|
||||||
|
length++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( length > 0 ) {
|
||||||
|
retv = g_malloc0((length+1)*sizeof(char*));
|
||||||
|
int index = 0;
|
||||||
|
for ( int i = 0; i < stored_argc; i++ ) {
|
||||||
|
if ( strcasecmp ( stored_argv[i], key ) == 0 && i < (stored_argc -1 ) ){
|
||||||
|
retv[index++] = stored_argv[i+1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return retv;
|
||||||
|
}
|
||||||
|
|
||||||
int find_arg_int ( const char * const key, int *val )
|
int find_arg_int ( const char * const key, int *val )
|
||||||
{
|
{
|
||||||
int i = find_arg ( key );
|
int i = find_arg ( key );
|
||||||
|
|
|
@ -64,6 +64,8 @@
|
||||||
|
|
||||||
#include "gitconfig.h"
|
#include "gitconfig.h"
|
||||||
|
|
||||||
|
#include "theme.h"
|
||||||
|
|
||||||
// Pidfile.
|
// Pidfile.
|
||||||
char *pidfile = NULL;
|
char *pidfile = NULL;
|
||||||
const char *cache_dir = NULL;
|
const char *cache_dir = NULL;
|
||||||
|
@ -576,8 +578,9 @@ static void error_trap_pop ( G_GNUC_UNUSED SnDisplay *display, xcb_connection_t
|
||||||
xcb_flush ( xdisplay );
|
xcb_flush ( xdisplay );
|
||||||
--error_trap_depth;
|
--error_trap_depth;
|
||||||
}
|
}
|
||||||
|
/** Retry count of grabbing keyboard. */
|
||||||
unsigned int lazy_grab_retry_count_kb = 0;
|
unsigned int lazy_grab_retry_count_kb = 0;
|
||||||
|
/** Retry count of grabbing pointer. */
|
||||||
unsigned int lazy_grab_retry_count_pt = 0;
|
unsigned int lazy_grab_retry_count_pt = 0;
|
||||||
static gboolean lazy_grab_pointer ( G_GNUC_UNUSED gpointer data )
|
static gboolean lazy_grab_pointer ( G_GNUC_UNUSED gpointer data )
|
||||||
{
|
{
|
||||||
|
@ -942,6 +945,31 @@ int main ( int argc, char *argv[] )
|
||||||
// Parse command line for settings, independent of other -no-config.
|
// Parse command line for settings, independent of other -no-config.
|
||||||
config_parse_cmd_options_dynamic ( );
|
config_parse_cmd_options_dynamic ( );
|
||||||
|
|
||||||
|
if ( config.theme ) {
|
||||||
|
TICK_N ( "Parse theme" );
|
||||||
|
rofi_theme_parse_file ( config.theme );
|
||||||
|
TICK_N ( "Parsed theme" );
|
||||||
|
} else {
|
||||||
|
rofi_theme_convert_old_theme ( );
|
||||||
|
}
|
||||||
|
|
||||||
|
const char ** theme_str = find_arg_strv ( "-theme-str" );
|
||||||
|
if ( theme_str ) {
|
||||||
|
for ( int index = 0; theme_str && theme_str[index]; index++ ){
|
||||||
|
if ( ! rofi_theme_parse_string ( theme_str[index] ) ){
|
||||||
|
fprintf(stderr, "Failed to parse: %s\n", theme_str[index]);
|
||||||
|
exit ( EXIT_FAILURE );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_free ( theme_str );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if ( find_arg ( "-dump-theme" ) >= 0 ){
|
||||||
|
rofi_theme_print ( rofi_theme );
|
||||||
|
exit (EXIT_SUCCESS);
|
||||||
|
}
|
||||||
// Dump.
|
// Dump.
|
||||||
// catch help request
|
// catch help request
|
||||||
if ( find_arg ( "-h" ) >= 0 || find_arg ( "-help" ) >= 0 || find_arg ( "--help" ) >= 0 ) {
|
if ( find_arg ( "-h" ) >= 0 || find_arg ( "-help" ) >= 0 || find_arg ( "--help" ) >= 0 ) {
|
||||||
|
|
840
source/theme.c
Normal file
840
source/theme.c
Normal file
|
@ -0,0 +1,840 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "theme.h"
|
||||||
|
#include "lexer/theme-parser.h"
|
||||||
|
#include "helper.h"
|
||||||
|
#include "settings.h"
|
||||||
|
#include "widgets/textbox.h"
|
||||||
|
#include "view.h"
|
||||||
|
|
||||||
|
/** Logging domain for theme */
|
||||||
|
#define LOG_DOMAIN "Theme"
|
||||||
|
|
||||||
|
void yyerror ( YYLTYPE *ylloc, const char *);
|
||||||
|
static gboolean distance_compare ( Distance d, Distance e )
|
||||||
|
{
|
||||||
|
return ( d.type == e.type && d.distance == e.distance && d.style == e.style );
|
||||||
|
}
|
||||||
|
|
||||||
|
ThemeWidget *rofi_theme_find_or_create_name ( ThemeWidget *base, const char *name )
|
||||||
|
{
|
||||||
|
for ( unsigned int i = 0; i < base->num_widgets;i++){
|
||||||
|
if ( g_strcmp0(base->widgets[i]->name, name) == 0 ){
|
||||||
|
return base->widgets[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
base->widgets = g_realloc ( base->widgets, sizeof(ThemeWidget*)*(base->num_widgets+1));
|
||||||
|
base->widgets[base->num_widgets] = g_malloc0(sizeof(ThemeWidget));
|
||||||
|
ThemeWidget *retv = base->widgets[base->num_widgets];
|
||||||
|
retv->parent = base;
|
||||||
|
retv->name = g_strdup(name);
|
||||||
|
base->num_widgets++;
|
||||||
|
return retv;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Properties
|
||||||
|
*/
|
||||||
|
Property *rofi_theme_property_create ( PropertyType type )
|
||||||
|
{
|
||||||
|
Property *retv = g_malloc0 ( sizeof(Property) );
|
||||||
|
retv->type = type;
|
||||||
|
return retv;
|
||||||
|
}
|
||||||
|
void rofi_theme_property_free ( Property *p )
|
||||||
|
{
|
||||||
|
if ( p == NULL ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
g_free ( p->name );
|
||||||
|
if ( p->type == P_STRING ) {
|
||||||
|
g_free ( p->value.s );
|
||||||
|
} else if ( p->type == P_LINK ) {
|
||||||
|
g_free ( p->value.link.name );
|
||||||
|
}
|
||||||
|
g_free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rofi_theme_free ( ThemeWidget *widget )
|
||||||
|
{
|
||||||
|
if ( widget == NULL ){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( widget->properties ) {
|
||||||
|
g_hash_table_destroy ( widget->properties );
|
||||||
|
}
|
||||||
|
for ( unsigned int i = 0; i < widget->num_widgets; i++ ){
|
||||||
|
rofi_theme_free ( widget->widgets[i] );
|
||||||
|
}
|
||||||
|
g_free ( widget->widgets );
|
||||||
|
g_free ( widget->name );
|
||||||
|
g_free ( widget );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* print
|
||||||
|
*/
|
||||||
|
static void rofi_theme_print_distance ( Distance d )
|
||||||
|
{
|
||||||
|
if ( d.type == PW_PX ) {
|
||||||
|
printf("%upx ", (int)d.distance );
|
||||||
|
} else if ( d.type == PW_PERCENT ) {
|
||||||
|
printf("%f%% ", d.distance );
|
||||||
|
} else {
|
||||||
|
printf("%fem ", d.distance );
|
||||||
|
}
|
||||||
|
if ( d.style == DASH ) {
|
||||||
|
printf("dash ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/** Textual representation of Window Location */
|
||||||
|
const char const * WindowLocationStr[9] = {
|
||||||
|
"center",
|
||||||
|
"northwest",
|
||||||
|
"north",
|
||||||
|
"northeast",
|
||||||
|
"east",
|
||||||
|
"southeast",
|
||||||
|
"south",
|
||||||
|
"southwest",
|
||||||
|
"west"
|
||||||
|
};
|
||||||
|
|
||||||
|
static void rofi_theme_print_property_index ( size_t pnl, int depth, Property *p )
|
||||||
|
{
|
||||||
|
int pl = strlen ( p->name );
|
||||||
|
printf("%*s%s:%*s ", depth, "", p->name, (int)pnl-pl,"" );
|
||||||
|
switch ( p->type )
|
||||||
|
{
|
||||||
|
case P_POSITION:
|
||||||
|
printf("%s;", WindowLocationStr[p->value.i]);
|
||||||
|
break;
|
||||||
|
case P_STRING:
|
||||||
|
printf("\"%s\";", p->value.s);
|
||||||
|
break;
|
||||||
|
case P_INTEGER:
|
||||||
|
printf("%d;", p->value.i);
|
||||||
|
break;
|
||||||
|
case P_DOUBLE:
|
||||||
|
printf("%.2f;", p->value.f);
|
||||||
|
break;
|
||||||
|
case P_BOOLEAN:
|
||||||
|
printf("%s;", p->value.b?"true":"false");
|
||||||
|
break;
|
||||||
|
case P_COLOR:
|
||||||
|
printf("#%02X%02X%02X%02X;",
|
||||||
|
(unsigned char)(p->value.color.alpha*255.0),
|
||||||
|
(unsigned char)(p->value.color.red*255.0),
|
||||||
|
(unsigned char)(p->value.color.green*255.0),
|
||||||
|
(unsigned char)(p->value.color.blue*255.0));
|
||||||
|
break;
|
||||||
|
case P_PADDING:
|
||||||
|
if ( distance_compare ( p->value.padding.top, p->value.padding.bottom) &&
|
||||||
|
distance_compare ( p->value.padding.left, p->value.padding.right) &&
|
||||||
|
distance_compare ( p->value.padding.left, p->value.padding.top) ) {
|
||||||
|
rofi_theme_print_distance ( p->value.padding.left );
|
||||||
|
} else if ( distance_compare ( p->value.padding.top, p->value.padding.bottom) &&
|
||||||
|
distance_compare ( p->value.padding.left, p->value.padding.right)){
|
||||||
|
rofi_theme_print_distance ( p->value.padding.top );
|
||||||
|
rofi_theme_print_distance ( p->value.padding.left );
|
||||||
|
} else if ( !distance_compare ( p->value.padding.top, p->value.padding.bottom) &&
|
||||||
|
distance_compare ( p->value.padding.left, p->value.padding.right)){
|
||||||
|
rofi_theme_print_distance ( p->value.padding.top );
|
||||||
|
rofi_theme_print_distance ( p->value.padding.left );
|
||||||
|
rofi_theme_print_distance ( p->value.padding.bottom);
|
||||||
|
} else {
|
||||||
|
rofi_theme_print_distance ( p->value.padding.top );
|
||||||
|
rofi_theme_print_distance ( p->value.padding.right );
|
||||||
|
rofi_theme_print_distance ( p->value.padding.bottom);
|
||||||
|
rofi_theme_print_distance ( p->value.padding.left );
|
||||||
|
}
|
||||||
|
printf(";");
|
||||||
|
break;
|
||||||
|
case P_LINK:
|
||||||
|
printf("%s;", p->value.link.name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
putchar ( '\n' );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rofi_theme_print_index ( ThemeWidget *widget )
|
||||||
|
{
|
||||||
|
GHashTableIter iter;
|
||||||
|
gpointer key, value;
|
||||||
|
if ( widget->properties ){
|
||||||
|
int index = 0;
|
||||||
|
GList *list = NULL;
|
||||||
|
ThemeWidget *w = widget;
|
||||||
|
while ( w){
|
||||||
|
if ( g_strcmp0(w->name,"Root") == 0 ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
list = g_list_prepend ( list, w->name );
|
||||||
|
w = w->parent;
|
||||||
|
}
|
||||||
|
if ( g_list_length ( list ) > 0 ) {
|
||||||
|
index = 4;
|
||||||
|
for ( GList *iter = g_list_first ( list ); iter != NULL; iter = g_list_next ( iter ) ) {
|
||||||
|
char *name = (char *)iter->data;
|
||||||
|
if ( iter->prev == NULL ){
|
||||||
|
putchar ( '#' );
|
||||||
|
}
|
||||||
|
fputs(name, stdout);
|
||||||
|
if ( iter->next ) {
|
||||||
|
putchar('.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf(" {\n");
|
||||||
|
} else {
|
||||||
|
index = 4;
|
||||||
|
printf("* {\n");
|
||||||
|
}
|
||||||
|
size_t property_name_length = 0;
|
||||||
|
g_hash_table_iter_init (&iter, widget->properties);
|
||||||
|
while (g_hash_table_iter_next (&iter, &key, &value))
|
||||||
|
{
|
||||||
|
Property *p = (Property*)value;
|
||||||
|
property_name_length = MAX ( strlen (p->name), property_name_length );
|
||||||
|
}
|
||||||
|
g_hash_table_iter_init (&iter, widget->properties);
|
||||||
|
while (g_hash_table_iter_next (&iter, &key, &value))
|
||||||
|
{
|
||||||
|
Property *p = (Property*)value;
|
||||||
|
rofi_theme_print_property_index ( property_name_length, index, p );
|
||||||
|
}
|
||||||
|
printf("}\n");
|
||||||
|
g_list_free ( list );
|
||||||
|
}
|
||||||
|
for ( unsigned int i = 0; i < widget->num_widgets;i++){
|
||||||
|
rofi_theme_print_index ( widget->widgets[i] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void rofi_theme_print ( ThemeWidget *widget )
|
||||||
|
{
|
||||||
|
rofi_theme_print_index ( widget );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main lex parser.
|
||||||
|
*/
|
||||||
|
int yyparse();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy the internal of lex parser.
|
||||||
|
*/
|
||||||
|
void yylex_destroy( void );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Global handle input file to flex parser.
|
||||||
|
*/
|
||||||
|
extern FILE* yyin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param yylloc The file location.
|
||||||
|
* @param s Error message string.
|
||||||
|
*
|
||||||
|
* Error handler for the lex parser.
|
||||||
|
*/
|
||||||
|
void yyerror(YYLTYPE *yylloc, const char* s) {
|
||||||
|
fprintf(stderr, "Parse error: %s\n", s);
|
||||||
|
fprintf(stderr, "From line %d column %d to line %d column %d\n", yylloc->first_line, yylloc->first_column, yylloc->last_line, yylloc->last_column);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean rofi_theme_steal_property_int ( gpointer key, gpointer value, gpointer user_data)
|
||||||
|
{
|
||||||
|
GHashTable *table = (GHashTable*)user_data;
|
||||||
|
g_hash_table_replace ( table, key, value);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
void rofi_theme_widget_add_properties ( ThemeWidget *widget, GHashTable *table )
|
||||||
|
{
|
||||||
|
if ( table == NULL ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( widget->properties == NULL ){
|
||||||
|
widget->properties = table;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
g_hash_table_foreach_steal ( table, rofi_theme_steal_property_int, widget->properties );
|
||||||
|
g_hash_table_destroy ( table );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public API
|
||||||
|
*/
|
||||||
|
|
||||||
|
static ThemeWidget *rofi_theme_find_single ( ThemeWidget *widget, const char *name)
|
||||||
|
{
|
||||||
|
for ( unsigned int j = 0; j < widget->num_widgets;j++){
|
||||||
|
if ( g_strcmp0(widget->widgets[j]->name, name ) == 0 ){
|
||||||
|
return widget->widgets[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return widget;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ThemeWidget *rofi_theme_find ( ThemeWidget *widget , const char *name, const gboolean exact )
|
||||||
|
{
|
||||||
|
if ( widget == NULL || name == NULL ) {
|
||||||
|
return widget;
|
||||||
|
}
|
||||||
|
char **names = g_strsplit ( name, "." , 0 );
|
||||||
|
int found = TRUE;
|
||||||
|
for ( unsigned int i = 0; found && names && names[i]; i++ ){
|
||||||
|
found = FALSE;
|
||||||
|
ThemeWidget *f = rofi_theme_find_single ( widget, names[i]);
|
||||||
|
if ( f != widget ){
|
||||||
|
widget = f;
|
||||||
|
found = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_strfreev(names);
|
||||||
|
if ( !exact || found ){
|
||||||
|
return widget;
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rofi_theme_resolve_link_property ( Property *p, int depth )
|
||||||
|
{
|
||||||
|
// Set name, remove '@' prefix.
|
||||||
|
const char *name = p->value.link.name +1;
|
||||||
|
if ( depth > 20 ){
|
||||||
|
g_log ( LOG_DOMAIN, G_LOG_LEVEL_WARNING, "Found more then 20 redirects for property. Stopping.");
|
||||||
|
p->value.link.ref = p;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( g_hash_table_contains ( rofi_theme->properties, name ) ) {
|
||||||
|
Property *pr = g_hash_table_lookup ( rofi_theme->properties, name );
|
||||||
|
if ( pr->type == P_LINK ) {
|
||||||
|
if ( pr->value.link.ref == NULL ) {
|
||||||
|
rofi_theme_resolve_link_property ( pr, depth+1);
|
||||||
|
}
|
||||||
|
if ( pr->value.link.ref != pr ){
|
||||||
|
p->value.link.ref = pr->value.link.ref;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
p->value.link.ref = pr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No found, set ref to self.
|
||||||
|
p->value.link.ref = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static 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) ) {
|
||||||
|
Property *p = g_hash_table_lookup ( widget->properties, property);
|
||||||
|
if ( p->type == P_LINK ) {
|
||||||
|
if ( p->value.link.ref == NULL ) {
|
||||||
|
// Resolve link.
|
||||||
|
rofi_theme_resolve_link_property ( p, 0 );
|
||||||
|
}
|
||||||
|
if ( p->value.link.ref->type == type ){
|
||||||
|
return p->value.link.ref;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( p->type == type ){
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
// Padding and integer can be converted.
|
||||||
|
if ( p->type == P_INTEGER && type == P_PADDING ){
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( exact ) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
widget = widget->parent;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
static 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 );
|
||||||
|
widget = rofi_theme_find ( widget, state, exact );
|
||||||
|
|
||||||
|
return widget;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rofi_theme_get_position ( const widget *widget, const char *property, int def )
|
||||||
|
{
|
||||||
|
ThemeWidget *wid = rofi_theme_find_widget ( widget->name, widget->state, FALSE );
|
||||||
|
Property *p = rofi_theme_find_property ( wid, P_POSITION, property, FALSE );
|
||||||
|
if ( p ){
|
||||||
|
return p->value.i;
|
||||||
|
}
|
||||||
|
g_log ( LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Theme entry: #%s %s property %s unset.", widget->name, widget->state?widget->state:"", property );
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rofi_theme_get_integer ( const widget *widget, const char *property, int def )
|
||||||
|
{
|
||||||
|
ThemeWidget *wid = rofi_theme_find_widget ( widget->name, widget->state, FALSE );
|
||||||
|
Property *p = rofi_theme_find_property ( wid, P_INTEGER, property, FALSE );
|
||||||
|
if ( p ){
|
||||||
|
return p->value.i;
|
||||||
|
}
|
||||||
|
g_log ( LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Theme entry: #%s %s property %s unset.", widget->name, widget->state?widget->state:"", property );
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
int rofi_theme_get_integer_exact ( const widget *widget, const char *property, int def )
|
||||||
|
{
|
||||||
|
ThemeWidget *wid = rofi_theme_find_widget ( widget->name, widget->state, TRUE );
|
||||||
|
Property *p = rofi_theme_find_property ( wid, P_INTEGER, property, TRUE );
|
||||||
|
if ( p ){
|
||||||
|
return p->value.i;
|
||||||
|
}
|
||||||
|
g_log ( LOG_DOMAIN, G_LOG_LEVEL_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 )
|
||||||
|
{
|
||||||
|
ThemeWidget *wid = rofi_theme_find_widget ( widget->name, widget->state, FALSE );
|
||||||
|
Property *p = rofi_theme_find_property ( wid, P_PADDING, property, FALSE );
|
||||||
|
if ( p ){
|
||||||
|
if ( p->type == P_INTEGER ){
|
||||||
|
return (Distance){p->value.i,PW_PX, SOLID};
|
||||||
|
} else {
|
||||||
|
return p->value.padding.left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_log ( LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Theme entry: #%s %s property %s unset.", widget->name, widget->state?widget->state:"", property );
|
||||||
|
return (Distance){def, PW_PX, SOLID};
|
||||||
|
}
|
||||||
|
|
||||||
|
int rofi_theme_get_boolean ( const widget *widget, const char *property, int def )
|
||||||
|
{
|
||||||
|
ThemeWidget *wid = rofi_theme_find_widget ( widget->name, widget->state, FALSE );
|
||||||
|
Property *p = rofi_theme_find_property ( wid, P_BOOLEAN, property, FALSE );
|
||||||
|
if ( p ){
|
||||||
|
return p->value.b;
|
||||||
|
}
|
||||||
|
g_log ( LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Theme entry: #%s %s property %s unset.", widget->name, widget->state?widget->state:"", property );
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *rofi_theme_get_string ( const widget *widget, const char *property, char *def )
|
||||||
|
{
|
||||||
|
ThemeWidget *wid = rofi_theme_find_widget ( widget->name, widget->state, FALSE );
|
||||||
|
Property *p = rofi_theme_find_property ( wid, P_STRING, property, FALSE );
|
||||||
|
if ( p ){
|
||||||
|
return p->value.s;
|
||||||
|
}
|
||||||
|
g_log ( LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Theme entry: #%s %s property %s unset.", widget->name, widget->state?widget->state:"", property );
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
double rofi_theme_get_double ( const widget *widget, const char *property, double def )
|
||||||
|
{
|
||||||
|
ThemeWidget *wid = rofi_theme_find_widget ( widget->name, widget->state, FALSE );
|
||||||
|
Property *p = rofi_theme_find_property ( wid, P_DOUBLE, property, FALSE );
|
||||||
|
if ( p ){
|
||||||
|
return p->value.b;
|
||||||
|
}
|
||||||
|
g_log ( LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Theme entry: #%s %s property %s unset.", widget->name, widget->state?widget->state:"", property );
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
void rofi_theme_get_color ( const widget *widget, const char *property, cairo_t *d)
|
||||||
|
{
|
||||||
|
ThemeWidget *wid = rofi_theme_find_widget ( widget->name, widget->state, FALSE );
|
||||||
|
Property *p = rofi_theme_find_property ( wid, P_COLOR, property, FALSE );
|
||||||
|
if ( p ){
|
||||||
|
cairo_set_source_rgba ( d,
|
||||||
|
p->value.color.red,
|
||||||
|
p->value.color.green,
|
||||||
|
p->value.color.blue,
|
||||||
|
p->value.color.alpha
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
g_log ( LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Theme entry: #%s %s property %s unset.", widget->name, widget->state?widget->state:"", property );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Padding rofi_theme_get_padding ( const widget *widget, const char *property, Padding pad )
|
||||||
|
{
|
||||||
|
ThemeWidget *wid = rofi_theme_find_widget ( widget->name, widget->state, FALSE );
|
||||||
|
Property *p = rofi_theme_find_property ( wid, P_PADDING, property, FALSE );
|
||||||
|
if ( p ){
|
||||||
|
if ( p->type == P_PADDING ){
|
||||||
|
pad = p->value.padding;
|
||||||
|
} else {
|
||||||
|
Distance d = (Distance){p->value.i, PW_PX, SOLID};
|
||||||
|
return (Padding){d,d,d,d};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_log ( LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Theme entry: #%s %s property %s unset.", widget->name, widget->state?widget->state:"", property );
|
||||||
|
return pad;
|
||||||
|
}
|
||||||
|
int distance_get_pixel ( Distance d, Orientation ori )
|
||||||
|
{
|
||||||
|
if ( d.type == PW_EM ){
|
||||||
|
return d.distance*textbox_get_estimated_char_height();
|
||||||
|
} else if ( d.type == PW_PERCENT ) {
|
||||||
|
if ( ori == ORIENTATION_VERTICAL ){
|
||||||
|
int height = 0;
|
||||||
|
rofi_view_get_current_monitor ( NULL, &height );
|
||||||
|
return (d.distance*height)/(100.0);
|
||||||
|
} else {
|
||||||
|
int width = 0;
|
||||||
|
rofi_view_get_current_monitor ( &width, NULL );
|
||||||
|
return (d.distance*width)/(100.0);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return d.distance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void distance_get_linestyle ( Distance d, cairo_t *draw )
|
||||||
|
{
|
||||||
|
if ( d.style == DASH ){
|
||||||
|
const double dashes[1] = { 4 };
|
||||||
|
cairo_set_dash ( draw, dashes, 1, 0.0 );
|
||||||
|
} else {
|
||||||
|
cairo_set_dash ( draw, NULL, 0, 0.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef THEME_CONVERTER
|
||||||
|
|
||||||
|
static Property* rofi_theme_convert_get_color ( const char *color, const char *name )
|
||||||
|
{
|
||||||
|
Color c = color_get ( color );
|
||||||
|
Property *p = rofi_theme_property_create ( P_COLOR );
|
||||||
|
p->name = g_strdup(name);
|
||||||
|
p->value.color.alpha = c.alpha;
|
||||||
|
p->value.color.red = c.red;
|
||||||
|
p->value.color.green = c.green;
|
||||||
|
p->value.color.blue = c.blue;
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
static void rofi_theme_convert_create_property_ht ( ThemeWidget *widget )
|
||||||
|
{
|
||||||
|
if ( widget->properties == NULL ) {
|
||||||
|
widget->properties = g_hash_table_new_full ( g_str_hash, g_str_equal, NULL, (GDestroyNotify)rofi_theme_property_free );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void rofi_theme_convert_old_theme ( void )
|
||||||
|
{
|
||||||
|
if ( rofi_theme != NULL ){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
rofi_theme = (ThemeWidget*)g_malloc0 ( sizeof ( ThemeWidget ) );
|
||||||
|
rofi_theme->name = g_strdup ( "Root" );
|
||||||
|
rofi_theme_convert_create_property_ht ( rofi_theme );
|
||||||
|
ThemeWidget *window_widget = rofi_theme_find_or_create_name ( rofi_theme , "window" );
|
||||||
|
rofi_theme_convert_create_property_ht ( window_widget );
|
||||||
|
ThemeWidget *mainbox_widget = rofi_theme_find_or_create_name ( window_widget, "mainbox" );
|
||||||
|
rofi_theme_convert_create_property_ht ( mainbox_widget );
|
||||||
|
ThemeWidget *message = rofi_theme_find_or_create_name ( mainbox_widget, "message" );
|
||||||
|
ThemeWidget *message_box = rofi_theme_find_or_create_name ( message, "box" );
|
||||||
|
rofi_theme_convert_create_property_ht ( message_box );
|
||||||
|
ThemeWidget *listview_widget = rofi_theme_find_or_create_name ( mainbox_widget, "listview" );
|
||||||
|
rofi_theme_convert_create_property_ht ( listview_widget );
|
||||||
|
ThemeWidget *sidebar_widget = rofi_theme_find_or_create_name ( mainbox_widget, "sidebar" );
|
||||||
|
ThemeWidget *sidebarbox_widget = rofi_theme_find_or_create_name ( sidebar_widget, "box" );
|
||||||
|
rofi_theme_convert_create_property_ht ( sidebarbox_widget );
|
||||||
|
{
|
||||||
|
Property *p = rofi_theme_property_create ( P_INTEGER );
|
||||||
|
p->name = g_strdup ("border");
|
||||||
|
p->value.i = 0;
|
||||||
|
g_hash_table_replace ( mainbox_widget->properties, p->name, p);
|
||||||
|
|
||||||
|
p = rofi_theme_property_create ( P_INTEGER );
|
||||||
|
p->name = g_strdup ("padding");
|
||||||
|
p->value.i = config.padding;
|
||||||
|
g_hash_table_replace ( window_widget->properties, p->name, p);
|
||||||
|
|
||||||
|
p = rofi_theme_property_create ( P_INTEGER );
|
||||||
|
p->name = g_strdup ("padding");
|
||||||
|
p->value.i = 0;
|
||||||
|
g_hash_table_replace ( mainbox_widget->properties, p->name, p);
|
||||||
|
// Spacing
|
||||||
|
p = rofi_theme_property_create ( P_INTEGER );
|
||||||
|
p->name = g_strdup("spacing");
|
||||||
|
p->value.i = config.line_margin;
|
||||||
|
g_hash_table_replace ( rofi_theme->properties, p->name, p );
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// Background
|
||||||
|
Property *p = rofi_theme_property_create ( P_COLOR );
|
||||||
|
p->name = g_strdup("background");
|
||||||
|
p->value.color.alpha = 0;
|
||||||
|
p->value.color.red = 0;
|
||||||
|
p->value.color.green= 0;
|
||||||
|
p->value.color.blue= 0;
|
||||||
|
g_hash_table_replace ( rofi_theme->properties, p->name, p );
|
||||||
|
|
||||||
|
ThemeWidget *inputbar_widget = rofi_theme_find_or_create_name ( mainbox_widget, "inputbar" );
|
||||||
|
rofi_theme_convert_create_property_ht ( inputbar_widget );
|
||||||
|
p = rofi_theme_property_create ( P_INTEGER );
|
||||||
|
p->name = g_strdup("spacing");
|
||||||
|
p->value.i = 0;
|
||||||
|
g_hash_table_replace ( inputbar_widget->properties, p->name, p );
|
||||||
|
|
||||||
|
|
||||||
|
LineStyle style = (g_strcmp0(config.separator_style,"dash") == 0)?DASH:SOLID;
|
||||||
|
int place_end = ( config.location == WL_SOUTH_EAST || config.location == WL_SOUTH || config.location == WL_SOUTH_WEST );
|
||||||
|
p = rofi_theme_property_create ( P_PADDING );
|
||||||
|
p->name = g_strdup("border");
|
||||||
|
Distance d = (Distance){config.menu_bw, PW_PX, style};
|
||||||
|
if ( place_end ){
|
||||||
|
p->value.padding.bottom= d;
|
||||||
|
} else {
|
||||||
|
p->value.padding.top= d;
|
||||||
|
}
|
||||||
|
g_hash_table_replace ( listview_widget->properties, p->name, p );
|
||||||
|
|
||||||
|
|
||||||
|
p = rofi_theme_property_create ( P_PADDING );
|
||||||
|
p->name = g_strdup("border");
|
||||||
|
d = (Distance){config.menu_bw, PW_PX, style};
|
||||||
|
if ( place_end ){
|
||||||
|
p->value.padding.bottom= d;
|
||||||
|
} else {
|
||||||
|
p->value.padding.top= d;
|
||||||
|
}
|
||||||
|
g_hash_table_replace ( message_box->properties, p->name, p );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sidebar top
|
||||||
|
*/
|
||||||
|
p = rofi_theme_property_create ( P_PADDING );
|
||||||
|
p->name = g_strdup("border");
|
||||||
|
d = (Distance){config.menu_bw, PW_PX, style};
|
||||||
|
p->value.padding.top= d;
|
||||||
|
g_hash_table_replace ( sidebarbox_widget->properties, p->name, p );
|
||||||
|
|
||||||
|
p = rofi_theme_property_create ( P_PADDING );
|
||||||
|
p->name = g_strdup("padding");
|
||||||
|
d = (Distance){config.line_margin, PW_PX, SOLID};
|
||||||
|
if ( place_end ){
|
||||||
|
p->value.padding.bottom= d;
|
||||||
|
} else {
|
||||||
|
p->value.padding.top= d;
|
||||||
|
}
|
||||||
|
g_hash_table_replace ( listview_widget->properties, p->name, p );
|
||||||
|
|
||||||
|
p = rofi_theme_property_create ( P_PADDING );
|
||||||
|
p->name = g_strdup("padding");
|
||||||
|
d = (Distance){config.line_margin, PW_PX, SOLID};
|
||||||
|
if ( place_end ){
|
||||||
|
p->value.padding.bottom= d;
|
||||||
|
} else {
|
||||||
|
p->value.padding.top= d;
|
||||||
|
}
|
||||||
|
g_hash_table_replace ( message_box->properties, p->name, p );
|
||||||
|
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Property *p = rofi_theme_property_create ( P_INTEGER );
|
||||||
|
p->name = g_strdup("columns");
|
||||||
|
p->value.i = config.menu_columns;
|
||||||
|
g_hash_table_replace ( listview_widget->properties, p->name, p );
|
||||||
|
p = rofi_theme_property_create ( P_INTEGER );
|
||||||
|
p->name = g_strdup("fixed-height");
|
||||||
|
p->value.i = !(config.fixed_num_lines);
|
||||||
|
g_hash_table_replace ( listview_widget->properties, p->name, p );
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// Border width.
|
||||||
|
rofi_theme_convert_create_property_ht ( window_widget );
|
||||||
|
// Padding
|
||||||
|
Property *p = rofi_theme_property_create ( P_INTEGER );
|
||||||
|
p->name = g_strdup("padding");
|
||||||
|
p->value.i = config.padding;
|
||||||
|
g_hash_table_replace ( window_widget->properties, p->name, p );
|
||||||
|
|
||||||
|
p = rofi_theme_property_create ( P_INTEGER );
|
||||||
|
p->name = g_strdup("border");
|
||||||
|
p->value.i = config.menu_bw;
|
||||||
|
g_hash_table_replace ( window_widget->properties, p->name, p );
|
||||||
|
}
|
||||||
|
{
|
||||||
|
gchar **vals = g_strsplit ( config.color_window, ",", 3 );
|
||||||
|
if ( vals != NULL ){
|
||||||
|
if ( vals[0] != NULL ) {
|
||||||
|
Property *p = rofi_theme_convert_get_color ( vals[0], "background" );
|
||||||
|
g_hash_table_replace ( window_widget->properties, p->name, p );
|
||||||
|
|
||||||
|
if ( vals[1] != NULL ) {
|
||||||
|
p = rofi_theme_convert_get_color ( vals[1], "foreground" );
|
||||||
|
g_hash_table_replace ( window_widget->properties, p->name, p );
|
||||||
|
|
||||||
|
ThemeWidget *inputbar = rofi_theme_find_or_create_name ( mainbox_widget, "inputbar" );
|
||||||
|
ThemeWidget *widget = rofi_theme_find_or_create_name ( inputbar, "box" );
|
||||||
|
rofi_theme_convert_create_property_ht ( widget );
|
||||||
|
if ( vals[2] != NULL ) {
|
||||||
|
p = rofi_theme_convert_get_color ( vals[2], "foreground" );
|
||||||
|
g_hash_table_replace ( window_widget->properties, p->name, p );
|
||||||
|
} else {
|
||||||
|
p = rofi_theme_convert_get_color ( vals[1], "foreground" );
|
||||||
|
g_hash_table_replace ( window_widget->properties, p->name, p );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_strfreev ( vals );
|
||||||
|
{
|
||||||
|
Property *p = NULL;
|
||||||
|
ThemeWidget *widget = rofi_theme_find_or_create_name ( listview_widget, "element" );
|
||||||
|
ThemeWidget *scrollbar = rofi_theme_find_or_create_name ( listview_widget, "scrollbar" );
|
||||||
|
|
||||||
|
|
||||||
|
ThemeWidget *wnormal = rofi_theme_find_or_create_name ( widget, "normal" );
|
||||||
|
ThemeWidget *wselected = rofi_theme_find_or_create_name ( widget, "selected" );
|
||||||
|
ThemeWidget *walternate = rofi_theme_find_or_create_name ( widget, "alternate" );
|
||||||
|
|
||||||
|
rofi_theme_convert_create_property_ht ( widget );
|
||||||
|
p = rofi_theme_property_create ( P_INTEGER );
|
||||||
|
p->name = g_strdup ("border");
|
||||||
|
p->value.i = 0;
|
||||||
|
g_hash_table_replace ( widget->properties, p->name, p);
|
||||||
|
|
||||||
|
rofi_theme_convert_create_property_ht ( scrollbar );
|
||||||
|
p = rofi_theme_property_create ( P_INTEGER );
|
||||||
|
p->name = g_strdup ("border");
|
||||||
|
p->value.i = 0;
|
||||||
|
g_hash_table_replace ( scrollbar->properties, p->name, p);
|
||||||
|
p = rofi_theme_property_create ( P_INTEGER );
|
||||||
|
p->name = g_strdup ("padding");
|
||||||
|
p->value.i = 0;
|
||||||
|
g_hash_table_replace ( scrollbar->properties, p->name, p);
|
||||||
|
|
||||||
|
|
||||||
|
gchar **vals = g_strsplit ( config.color_normal, ",", 5 );
|
||||||
|
if ( g_strv_length (vals) == 5 ) {
|
||||||
|
ThemeWidget *wnn = rofi_theme_find_or_create_name ( wnormal, "normal" );
|
||||||
|
rofi_theme_convert_create_property_ht ( wnn );
|
||||||
|
p = rofi_theme_convert_get_color ( vals[0], "background" );
|
||||||
|
g_hash_table_replace ( wnn->properties, p->name, p );
|
||||||
|
p = rofi_theme_convert_get_color ( vals[1], "foreground" );
|
||||||
|
g_hash_table_replace ( wnn->properties, p->name, p );
|
||||||
|
|
||||||
|
ThemeWidget *wsl = rofi_theme_find_or_create_name ( wselected, "normal" );
|
||||||
|
rofi_theme_convert_create_property_ht ( wsl );
|
||||||
|
p = rofi_theme_convert_get_color ( vals[3], "background" );
|
||||||
|
g_hash_table_replace ( wsl->properties, p->name, p );
|
||||||
|
p = rofi_theme_convert_get_color ( vals[4], "foreground" );
|
||||||
|
g_hash_table_replace ( wsl->properties, p->name, p );
|
||||||
|
|
||||||
|
ThemeWidget *wal = rofi_theme_find_or_create_name ( walternate, "normal" );
|
||||||
|
rofi_theme_convert_create_property_ht ( wal );
|
||||||
|
p = rofi_theme_convert_get_color ( vals[2], "background" );
|
||||||
|
g_hash_table_replace ( wal->properties, p->name, p );
|
||||||
|
p = rofi_theme_convert_get_color ( vals[1], "foreground" );
|
||||||
|
g_hash_table_replace ( wal->properties, p->name, p );
|
||||||
|
|
||||||
|
ThemeWidget *inputbar = rofi_theme_find_or_create_name ( mainbox_widget, "inputbar" );
|
||||||
|
wnn = rofi_theme_find_or_create_name ( inputbar, "normal" );
|
||||||
|
rofi_theme_convert_create_property_ht ( wnn );
|
||||||
|
p = rofi_theme_convert_get_color ( vals[0], "background" );
|
||||||
|
g_hash_table_replace ( wnn->properties, p->name, p );
|
||||||
|
p = rofi_theme_convert_get_color ( vals[1], "foreground" );
|
||||||
|
g_hash_table_replace ( wnn->properties, p->name, p );
|
||||||
|
|
||||||
|
wnn = rofi_theme_find_or_create_name ( message, "normal" );
|
||||||
|
rofi_theme_convert_create_property_ht ( wnn );
|
||||||
|
p = rofi_theme_convert_get_color ( vals[0], "background" );
|
||||||
|
g_hash_table_replace ( wnn->properties, p->name, p );
|
||||||
|
p = rofi_theme_convert_get_color ( vals[1], "foreground" );
|
||||||
|
g_hash_table_replace ( wnn->properties, p->name, p );
|
||||||
|
}
|
||||||
|
g_strfreev ( vals );
|
||||||
|
|
||||||
|
vals = g_strsplit ( config.color_urgent, ",", 5 );
|
||||||
|
if ( g_strv_length (vals) == 5 ) {
|
||||||
|
ThemeWidget *wnn = rofi_theme_find_or_create_name ( wnormal, "urgent" );
|
||||||
|
rofi_theme_convert_create_property_ht ( wnn );
|
||||||
|
p = rofi_theme_convert_get_color ( vals[0], "background" );
|
||||||
|
g_hash_table_replace ( wnn->properties, p->name, p );
|
||||||
|
p = rofi_theme_convert_get_color ( vals[1], "foreground" );
|
||||||
|
g_hash_table_replace ( wnn->properties, p->name, p );
|
||||||
|
|
||||||
|
ThemeWidget *wsl = rofi_theme_find_or_create_name ( wselected, "urgent" );
|
||||||
|
rofi_theme_convert_create_property_ht ( wsl );
|
||||||
|
p = rofi_theme_convert_get_color ( vals[3], "background" );
|
||||||
|
g_hash_table_replace ( wsl->properties, p->name, p );
|
||||||
|
p = rofi_theme_convert_get_color ( vals[4], "foreground" );
|
||||||
|
g_hash_table_replace ( wsl->properties, p->name, p );
|
||||||
|
|
||||||
|
ThemeWidget *wal = rofi_theme_find_or_create_name ( walternate, "urgent" );
|
||||||
|
rofi_theme_convert_create_property_ht ( wal );
|
||||||
|
p = rofi_theme_convert_get_color ( vals[2], "background" );
|
||||||
|
g_hash_table_replace ( wal->properties, p->name, p );
|
||||||
|
p = rofi_theme_convert_get_color ( vals[1], "foreground" );
|
||||||
|
g_hash_table_replace ( wal->properties, p->name, p );
|
||||||
|
}
|
||||||
|
g_strfreev ( vals );
|
||||||
|
|
||||||
|
vals = g_strsplit ( config.color_active, ",", 5 );
|
||||||
|
if ( g_strv_length (vals) == 5 ) {
|
||||||
|
ThemeWidget *wnn = rofi_theme_find_or_create_name ( wnormal, "active" );
|
||||||
|
rofi_theme_convert_create_property_ht ( wnn );
|
||||||
|
p = rofi_theme_convert_get_color ( vals[0], "background" );
|
||||||
|
g_hash_table_replace ( wnn->properties, p->name, p );
|
||||||
|
p = rofi_theme_convert_get_color ( vals[1], "foreground" );
|
||||||
|
g_hash_table_replace ( wnn->properties, p->name, p );
|
||||||
|
|
||||||
|
ThemeWidget *wsl = rofi_theme_find_or_create_name ( wselected, "active" );
|
||||||
|
rofi_theme_convert_create_property_ht ( wsl );
|
||||||
|
p = rofi_theme_convert_get_color ( vals[3], "background" );
|
||||||
|
g_hash_table_replace ( wsl->properties, p->name, p );
|
||||||
|
p = rofi_theme_convert_get_color ( vals[4], "foreground" );
|
||||||
|
g_hash_table_replace ( wsl->properties, p->name, p );
|
||||||
|
|
||||||
|
ThemeWidget *wal = rofi_theme_find_or_create_name ( walternate, "active" );
|
||||||
|
rofi_theme_convert_create_property_ht ( wal );
|
||||||
|
p = rofi_theme_convert_get_color ( vals[2], "background" );
|
||||||
|
g_hash_table_replace ( wal->properties, p->name, p );
|
||||||
|
p = rofi_theme_convert_get_color ( vals[1], "foreground" );
|
||||||
|
g_hash_table_replace ( wal->properties, p->name, p );
|
||||||
|
}
|
||||||
|
g_strfreev ( vals );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gboolean rofi_theme_parse_file ( const char *file )
|
||||||
|
{
|
||||||
|
char *filename = rofi_expand_path ( file );
|
||||||
|
yyin = fopen ( filename, "rb");
|
||||||
|
if ( yyin == NULL ){
|
||||||
|
fprintf(stderr, "Failed to open file: %s: '%s'\n", filename, strerror ( errno ) );
|
||||||
|
g_free(filename);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
extern int str_len;
|
||||||
|
extern const char*input_str;
|
||||||
|
str_len = 0;
|
||||||
|
input_str = NULL;
|
||||||
|
while ( yyparse() );
|
||||||
|
yylex_destroy();
|
||||||
|
g_free(filename);
|
||||||
|
yyin = NULL;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
gboolean rofi_theme_parse_string ( const char *string )
|
||||||
|
{
|
||||||
|
extern int str_len;
|
||||||
|
extern const char*input_str;
|
||||||
|
yyin = NULL;
|
||||||
|
input_str = string;
|
||||||
|
str_len = strlen ( string );
|
||||||
|
while ( yyparse () );
|
||||||
|
yylex_destroy();
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
#endif
|
368
source/view.c
368
source/view.c
|
@ -58,10 +58,19 @@
|
||||||
#include "view.h"
|
#include "view.h"
|
||||||
#include "view-internal.h"
|
#include "view-internal.h"
|
||||||
|
|
||||||
|
#include "theme.h"
|
||||||
|
|
||||||
/** The Rofi View log domain */
|
/** The Rofi View log domain */
|
||||||
#define LOG_DOMAIN "View"
|
#define LOG_DOMAIN "View"
|
||||||
|
|
||||||
#include "xcb.h"
|
#include "xcb.h"
|
||||||
|
/**
|
||||||
|
* @param state The handle to the view
|
||||||
|
* @param qr Indicate if queue_redraw should be called on changes.
|
||||||
|
*
|
||||||
|
* Update the state of the view. This involves filter state.
|
||||||
|
*/
|
||||||
|
void rofi_view_update ( RofiViewState *state, gboolean qr );
|
||||||
|
|
||||||
static int rofi_view_calculate_height ( RofiViewState *state );
|
static int rofi_view_calculate_height ( RofiViewState *state );
|
||||||
|
|
||||||
|
@ -99,9 +108,11 @@ struct
|
||||||
/** timeout for reloading */
|
/** timeout for reloading */
|
||||||
guint idle_timeout;
|
guint idle_timeout;
|
||||||
/** debug counter for redraws */
|
/** debug counter for redraws */
|
||||||
uint64_t count;
|
unsigned long long count;
|
||||||
/** redraw idle time. */
|
/** redraw idle time. */
|
||||||
guint repaint_source;
|
guint repaint_source;
|
||||||
|
/** Window fullscreen */
|
||||||
|
gboolean fullscreen;
|
||||||
} CacheState = {
|
} CacheState = {
|
||||||
.main_window = XCB_WINDOW_NONE,
|
.main_window = XCB_WINDOW_NONE,
|
||||||
.fake_bg = NULL,
|
.fake_bg = NULL,
|
||||||
|
@ -113,8 +124,18 @@ struct
|
||||||
.idle_timeout = 0,
|
.idle_timeout = 0,
|
||||||
.count = 0L,
|
.count = 0L,
|
||||||
.repaint_source = 0,
|
.repaint_source = 0,
|
||||||
|
.fullscreen = FALSE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void rofi_view_get_current_monitor ( int *width, int *height)
|
||||||
|
{
|
||||||
|
if (width ){
|
||||||
|
*width = CacheState.mon.w;
|
||||||
|
}
|
||||||
|
if (height){
|
||||||
|
*height = CacheState.mon.h;
|
||||||
|
}
|
||||||
|
}
|
||||||
static char * get_matching_state ( void )
|
static char * get_matching_state ( void )
|
||||||
{
|
{
|
||||||
if ( config.case_sensitive ) {
|
if ( config.case_sensitive ) {
|
||||||
|
@ -200,6 +221,10 @@ static void menu_capture_screenshot ( void )
|
||||||
static gboolean rofi_view_repaint ( G_GNUC_UNUSED void * data )
|
static gboolean rofi_view_repaint ( G_GNUC_UNUSED void * data )
|
||||||
{
|
{
|
||||||
if ( current_active_menu ) {
|
if ( current_active_menu ) {
|
||||||
|
// Repaint the view (if needed).
|
||||||
|
// After a resize the edit_pixmap surface might not contain anything anymore.
|
||||||
|
// If we already re-painted, this does nothing.
|
||||||
|
rofi_view_update (current_active_menu, FALSE);
|
||||||
g_log ( LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "expose event" );
|
g_log ( LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "expose event" );
|
||||||
TICK_N ( "Expose" );
|
TICK_N ( "Expose" );
|
||||||
xcb_copy_area ( xcb->connection, CacheState.edit_pixmap, CacheState.main_window, CacheState.gc,
|
xcb_copy_area ( xcb->connection, CacheState.edit_pixmap, CacheState.main_window, CacheState.gc,
|
||||||
|
@ -231,22 +256,29 @@ static void rofi_view_update_prompt ( RofiViewState *state )
|
||||||
*/
|
*/
|
||||||
static void rofi_view_calculate_window_position ( RofiViewState *state )
|
static void rofi_view_calculate_window_position ( RofiViewState *state )
|
||||||
{
|
{
|
||||||
if ( config.fullscreen ) {
|
int location = rofi_theme_get_position ( WIDGET ( state->main_window ), "location", config.location );
|
||||||
|
int anchor = location;
|
||||||
|
if ( !listview_get_fixed_num_lines ( state->list_view ) ) {
|
||||||
|
anchor = location;
|
||||||
|
if ( location == WL_CENTER ) {
|
||||||
|
anchor = WL_NORTH;
|
||||||
|
} else if ( location == WL_EAST ) {
|
||||||
|
anchor = WL_NORTH_EAST;
|
||||||
|
} else if (location == WL_WEST ) {
|
||||||
|
anchor = WL_NORTH_WEST;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
anchor = rofi_theme_get_position ( WIDGET ( state->main_window ), "anchor", anchor );
|
||||||
|
|
||||||
|
if ( CacheState.fullscreen ) {
|
||||||
state->x = CacheState.mon.x;
|
state->x = CacheState.mon.x;
|
||||||
state->y = CacheState.mon.y;
|
state->y = CacheState.mon.y;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
state->y = CacheState.mon.y + ( CacheState.mon.h ) / 2;
|
||||||
if ( !config.fixed_num_lines && ( config.location == WL_CENTER || config.location == WL_EAST || config.location == WL_WEST ) ) {
|
state->x = CacheState.mon.x + ( CacheState.mon.w ) / 2;
|
||||||
state->y = CacheState.mon.y + CacheState.mon.h / 2 - widget_get_height ( WIDGET ( state->input_bar ) );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Default location is center.
|
|
||||||
state->y = CacheState.mon.y + ( CacheState.mon.h - state->height ) / 2;
|
|
||||||
}
|
|
||||||
state->x = CacheState.mon.x + ( CacheState.mon.w - state->width ) / 2;
|
|
||||||
// Determine window location
|
// Determine window location
|
||||||
switch ( config.location )
|
switch ( location )
|
||||||
{
|
{
|
||||||
case WL_NORTH_WEST:
|
case WL_NORTH_WEST:
|
||||||
state->x = CacheState.mon.x;
|
state->x = CacheState.mon.x;
|
||||||
|
@ -256,15 +288,15 @@ static void rofi_view_calculate_window_position ( RofiViewState *state )
|
||||||
case WL_NORTH_EAST:
|
case WL_NORTH_EAST:
|
||||||
state->y = CacheState.mon.y;
|
state->y = CacheState.mon.y;
|
||||||
case WL_EAST:
|
case WL_EAST:
|
||||||
state->x = CacheState.mon.x + CacheState.mon.w - state->width;
|
state->x = CacheState.mon.x + CacheState.mon.w;
|
||||||
break;
|
break;
|
||||||
case WL_EAST_SOUTH:
|
case WL_SOUTH_EAST:
|
||||||
state->x = CacheState.mon.x + CacheState.mon.w - state->width;
|
state->x = CacheState.mon.x + CacheState.mon.w;
|
||||||
case WL_SOUTH:
|
case WL_SOUTH:
|
||||||
state->y = CacheState.mon.y + CacheState.mon.h - state->height;
|
state->y = CacheState.mon.y + CacheState.mon.h;
|
||||||
break;
|
break;
|
||||||
case WL_SOUTH_WEST:
|
case WL_SOUTH_WEST:
|
||||||
state->y = CacheState.mon.y + CacheState.mon.h - state->height;
|
state->y = CacheState.mon.y + CacheState.mon.h;
|
||||||
case WL_WEST:
|
case WL_WEST:
|
||||||
state->x = CacheState.mon.x;
|
state->x = CacheState.mon.x;
|
||||||
break;
|
break;
|
||||||
|
@ -272,6 +304,41 @@ static void rofi_view_calculate_window_position ( RofiViewState *state )
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
switch ( anchor )
|
||||||
|
{
|
||||||
|
case WL_SOUTH_WEST:
|
||||||
|
state->y -= state->height;
|
||||||
|
break;
|
||||||
|
case WL_SOUTH:
|
||||||
|
state->x -= state->width/2;
|
||||||
|
state->y -= state->height;
|
||||||
|
break;
|
||||||
|
case WL_SOUTH_EAST:
|
||||||
|
state->x -= state->width;
|
||||||
|
state->y -= state->height;
|
||||||
|
break;
|
||||||
|
case WL_NORTH_EAST:
|
||||||
|
state->x -= state->width;
|
||||||
|
break;
|
||||||
|
case WL_NORTH_WEST:
|
||||||
|
break;
|
||||||
|
case WL_NORTH:
|
||||||
|
state->x -= state->width/2;
|
||||||
|
break;
|
||||||
|
case WL_EAST:
|
||||||
|
state->x -= state->width;
|
||||||
|
state->y -= state->height/2;
|
||||||
|
break;
|
||||||
|
case WL_WEST:
|
||||||
|
state->y -= state->height/2;
|
||||||
|
break;
|
||||||
|
case WL_CENTER:
|
||||||
|
state->y -= state->height/2;
|
||||||
|
state->x -= state->width/2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
// Apply offset.
|
// Apply offset.
|
||||||
state->x += config.x_offset;
|
state->x += config.x_offset;
|
||||||
state->y += config.y_offset;
|
state->y += config.y_offset;
|
||||||
|
@ -294,7 +361,10 @@ static void rofi_view_window_update_size ( RofiViewState * state )
|
||||||
|
|
||||||
CacheState.edit_surf = cairo_xcb_surface_create ( xcb->connection, CacheState.edit_pixmap, visual, state->width, state->height );
|
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 );
|
CacheState.edit_draw = cairo_create ( CacheState.edit_surf );
|
||||||
widget_resize ( WIDGET ( state->main_box ), state->width - 2 * state->border, state->height - 2 * state->border );
|
|
||||||
|
g_log ( LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Re-size window based internal request: %dx%d.", state->width, state->height );
|
||||||
|
// Should wrap main window in a widget.
|
||||||
|
widget_resize ( WIDGET ( state->main_window ), state->width, state->height );
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean rofi_view_reload_idle ( G_GNUC_UNUSED gpointer data )
|
static gboolean rofi_view_reload_idle ( G_GNUC_UNUSED gpointer data )
|
||||||
|
@ -319,7 +389,7 @@ void rofi_view_queue_redraw ( void )
|
||||||
{
|
{
|
||||||
if ( current_active_menu && CacheState.repaint_source == 0 ) {
|
if ( current_active_menu && CacheState.repaint_source == 0 ) {
|
||||||
CacheState.count++;
|
CacheState.count++;
|
||||||
g_log ( LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "redraw %lu", CacheState.count );
|
g_log ( LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "redraw %llu", CacheState.count );
|
||||||
CacheState.repaint_source = g_idle_add_full ( G_PRIORITY_HIGH_IDLE, rofi_view_repaint, NULL, NULL );
|
CacheState.repaint_source = g_idle_add_full ( G_PRIORITY_HIGH_IDLE, rofi_view_repaint, NULL, NULL );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -382,7 +452,7 @@ void rofi_view_free ( RofiViewState *state )
|
||||||
}
|
}
|
||||||
// Do this here?
|
// Do this here?
|
||||||
// Wait for final release?
|
// Wait for final release?
|
||||||
widget_free ( WIDGET ( state->main_box ) );
|
widget_free ( WIDGET ( state->main_window ) );
|
||||||
widget_free ( WIDGET ( state->overlay ) );
|
widget_free ( WIDGET ( state->overlay ) );
|
||||||
|
|
||||||
g_free ( state->line_map );
|
g_free ( state->line_map );
|
||||||
|
@ -489,23 +559,26 @@ static void filter_elements ( thread_state *t, G_GNUC_UNUSED gpointer user_data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rofi_view_setup_fake_transparency ( void )
|
static void rofi_view_setup_fake_transparency ( const char const *fake_background )
|
||||||
{
|
{
|
||||||
if ( CacheState.fake_bg == NULL ) {
|
if ( CacheState.fake_bg == NULL ) {
|
||||||
cairo_surface_t *s = NULL;
|
cairo_surface_t *s = NULL;
|
||||||
/**
|
/**
|
||||||
* Select Background to use for fake transparency.
|
* Select Background to use for fake transparency.
|
||||||
* Current options: 'screenshot','background'
|
* Current options: 'real', 'screenshot','background'
|
||||||
*/
|
*/
|
||||||
TICK_N ( "Fake start" );
|
TICK_N ( "Fake start" );
|
||||||
if ( g_strcmp0 ( config.fake_background, "screenshot" ) == 0 ) {
|
if ( g_strcmp0 ( fake_background, "real" ) == 0 ){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if ( g_strcmp0 ( fake_background, "screenshot" ) == 0 ) {
|
||||||
s = x11_helper_get_screenshot_surface ();
|
s = x11_helper_get_screenshot_surface ();
|
||||||
}
|
}
|
||||||
else if ( g_strcmp0 ( config.fake_background, "background" ) == 0 ) {
|
else if ( g_strcmp0 ( fake_background, "background" ) == 0 ) {
|
||||||
s = x11_helper_get_bg_surface ();
|
s = x11_helper_get_bg_surface ();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
char *fpath = rofi_expand_path ( config.fake_background );
|
char *fpath = rofi_expand_path ( fake_background );
|
||||||
g_log ( LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Opening %s to use as background.", fpath );
|
g_log ( LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Opening %s to use as background.", fpath );
|
||||||
s = cairo_image_surface_create_from_png ( fpath );
|
s = cairo_image_surface_create_from_png ( fpath );
|
||||||
CacheState.fake_bgrel = TRUE;
|
CacheState.fake_bgrel = TRUE;
|
||||||
|
@ -584,8 +657,11 @@ void __create_window ( MenuFlags menu_flags )
|
||||||
pango_cairo_font_map_set_resolution ( (PangoCairoFontMap *) font_map, (double) config.dpi );
|
pango_cairo_font_map_set_resolution ( (PangoCairoFontMap *) font_map, (double) config.dpi );
|
||||||
}
|
}
|
||||||
// Setup font.
|
// Setup font.
|
||||||
if ( config.menu_font ) {
|
// Dummy widget.
|
||||||
PangoFontDescription *pfd = pango_font_description_from_string ( config.menu_font );
|
container *win = container_create ( "window" );
|
||||||
|
char *font = rofi_theme_get_string ( WIDGET ( win ), "font" , config.menu_font );
|
||||||
|
if ( font ) {
|
||||||
|
PangoFontDescription *pfd = pango_font_description_from_string ( font );
|
||||||
pango_context_set_font_description ( p, pfd );
|
pango_context_set_font_description ( p, pfd );
|
||||||
pango_font_description_free ( pfd );
|
pango_font_description_free ( pfd );
|
||||||
}
|
}
|
||||||
|
@ -605,7 +681,9 @@ void __create_window ( MenuFlags menu_flags )
|
||||||
window_set_atom_prop ( box, xcb->ewmh._NET_WM_WINDOW_TYPE, &( xcb->ewmh._NET_WM_WINDOW_TYPE_NORMAL ), 1 );
|
window_set_atom_prop ( box, xcb->ewmh._NET_WM_WINDOW_TYPE, &( xcb->ewmh._NET_WM_WINDOW_TYPE_NORMAL ), 1 );
|
||||||
x11_disable_decoration ( box );
|
x11_disable_decoration ( box );
|
||||||
}
|
}
|
||||||
if ( config.fullscreen ) {
|
|
||||||
|
CacheState.fullscreen = rofi_theme_get_boolean ( WIDGET (win ), "fullscreen", config.fullscreen );
|
||||||
|
if ( CacheState.fullscreen ) {
|
||||||
xcb_atom_t atoms[] = {
|
xcb_atom_t atoms[] = {
|
||||||
xcb->ewmh._NET_WM_STATE_FULLSCREEN,
|
xcb->ewmh._NET_WM_STATE_FULLSCREEN,
|
||||||
xcb->ewmh._NET_WM_STATE_ABOVE
|
xcb->ewmh._NET_WM_STATE_ABOVE
|
||||||
|
@ -620,12 +698,18 @@ void __create_window ( MenuFlags menu_flags )
|
||||||
CacheState.main_window = box;
|
CacheState.main_window = box;
|
||||||
CacheState.flags = menu_flags;
|
CacheState.flags = menu_flags;
|
||||||
monitor_active ( &( CacheState.mon ) );
|
monitor_active ( &( CacheState.mon ) );
|
||||||
if ( config.fake_transparency ) {
|
|
||||||
rofi_view_setup_fake_transparency ();
|
char *transparency = rofi_theme_get_string ( WIDGET ( win ), "transparency", NULL);
|
||||||
|
if ( transparency == NULL && config.fake_transparency ){
|
||||||
|
transparency = config.fake_background;
|
||||||
|
}
|
||||||
|
if ( transparency ) {
|
||||||
|
rofi_view_setup_fake_transparency ( transparency );
|
||||||
}
|
}
|
||||||
if ( xcb->sncontext != NULL ) {
|
if ( xcb->sncontext != NULL ) {
|
||||||
sn_launchee_context_setup_window ( xcb->sncontext, CacheState.main_window );
|
sn_launchee_context_setup_window ( xcb->sncontext, CacheState.main_window );
|
||||||
}
|
}
|
||||||
|
widget_free ( WIDGET ( win ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -633,20 +717,24 @@ void __create_window ( MenuFlags menu_flags )
|
||||||
*
|
*
|
||||||
* Calculate the width of the window and the width of an element.
|
* Calculate the width of the window and the width of an element.
|
||||||
*/
|
*/
|
||||||
static void rofi_view_calculate_window_and_element_width ( RofiViewState *state )
|
static void rofi_view_calculate_window_width ( RofiViewState *state )
|
||||||
{
|
{
|
||||||
if ( config.fullscreen ) {
|
if ( CacheState.fullscreen ) {
|
||||||
state->width = CacheState.mon.w;
|
state->width = CacheState.mon.w;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else if ( config.menu_width < 0 ) {
|
if ( config.menu_width < 0 ) {
|
||||||
double fw = textbox_get_estimated_char_width ( );
|
double fw = textbox_get_estimated_char_width ( );
|
||||||
state->width = -( fw * config.menu_width );
|
state->width = -( fw * config.menu_width );
|
||||||
state->width += 2 * state->border;
|
state->width += widget_padding_get_padding_width ( WIDGET ( state->main_window ) );
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
// Calculate as float to stop silly, big rounding down errors.
|
// Calculate as float to stop silly, big rounding down errors.
|
||||||
state->width = config.menu_width < 101 ? ( CacheState.mon.w / 100.0f ) * ( float ) config.menu_width : config.menu_width;
|
state->width = config.menu_width < 101 ? ( CacheState.mon.w / 100.0f ) * ( float ) config.menu_width : config.menu_width;
|
||||||
}
|
}
|
||||||
|
// Use theme configured width, if set.
|
||||||
|
Distance width = rofi_theme_get_distance ( WIDGET ( state->main_window ), "width", state->width );
|
||||||
|
state->width = distance_get_pixel ( width, ORIENTATION_HORIZONTAL );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -758,15 +846,16 @@ static void update_callback ( textbox *t, unsigned int index, void *udata, TextB
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void rofi_view_update ( RofiViewState *state )
|
void rofi_view_update ( RofiViewState *state, gboolean qr )
|
||||||
{
|
{
|
||||||
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;
|
return;
|
||||||
}
|
}
|
||||||
|
g_log ( LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Redraw view" );
|
||||||
TICK ();
|
TICK ();
|
||||||
cairo_t *d = CacheState.edit_draw;
|
cairo_t *d = CacheState.edit_draw;
|
||||||
cairo_set_operator ( d, CAIRO_OPERATOR_SOURCE );
|
cairo_set_operator ( d, CAIRO_OPERATOR_SOURCE );
|
||||||
if ( config.fake_transparency && CacheState.fake_bg != NULL ) {
|
if ( CacheState.fake_bg != NULL ) {
|
||||||
if ( CacheState.fake_bgrel ) {
|
if ( CacheState.fake_bgrel ) {
|
||||||
cairo_set_source_surface ( d, CacheState.fake_bg, 0.0, 0.0 );
|
cairo_set_source_surface ( d, CacheState.fake_bg, 0.0, 0.0 );
|
||||||
}
|
}
|
||||||
|
@ -777,39 +866,26 @@ void rofi_view_update ( RofiViewState *state )
|
||||||
}
|
}
|
||||||
cairo_paint ( d );
|
cairo_paint ( d );
|
||||||
cairo_set_operator ( d, CAIRO_OPERATOR_OVER );
|
cairo_set_operator ( d, CAIRO_OPERATOR_OVER );
|
||||||
color_background ( d );
|
|
||||||
cairo_paint ( d );
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Paint the background.
|
// Paint the background transparent.
|
||||||
color_background ( d );
|
cairo_set_source_rgba ( d, 0,0,0,0.0);
|
||||||
cairo_paint ( d );
|
cairo_paint ( d );
|
||||||
}
|
}
|
||||||
TICK_N ( "Background" );
|
TICK_N ( "Background" );
|
||||||
color_border ( d );
|
|
||||||
|
|
||||||
if ( config.menu_bw > 0 ) {
|
|
||||||
cairo_save ( d );
|
|
||||||
cairo_set_line_width ( d, config.menu_bw );
|
|
||||||
cairo_rectangle ( d,
|
|
||||||
config.menu_bw / 2.0,
|
|
||||||
config.menu_bw / 2.0,
|
|
||||||
state->width - config.menu_bw,
|
|
||||||
state->height - config.menu_bw );
|
|
||||||
cairo_stroke ( d );
|
|
||||||
cairo_restore ( d );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Always paint as overlay over the background.
|
// Always paint as overlay over the background.
|
||||||
cairo_set_operator ( d, CAIRO_OPERATOR_OVER );
|
cairo_set_operator ( d, CAIRO_OPERATOR_OVER );
|
||||||
widget_draw ( WIDGET ( state->main_box ), d );
|
widget_draw ( WIDGET ( state->main_window ), d );
|
||||||
|
|
||||||
if ( state->overlay ) {
|
if ( state->overlay ) {
|
||||||
widget_draw ( WIDGET ( state->overlay ), d );
|
widget_draw ( WIDGET ( state->overlay ), d );
|
||||||
}
|
}
|
||||||
TICK_N ( "widgets" );
|
TICK_N ( "widgets" );
|
||||||
cairo_surface_flush ( CacheState.edit_surf );
|
cairo_surface_flush ( CacheState.edit_surf );
|
||||||
|
if ( qr ) {
|
||||||
rofi_view_queue_redraw ();
|
rofi_view_queue_redraw ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -828,9 +904,10 @@ static void rofi_view_paste ( RofiViewState *state, xcb_selection_notify_event_t
|
||||||
if ( text != NULL && text[0] != '\0' ) {
|
if ( text != NULL && text[0] != '\0' ) {
|
||||||
unsigned int dl = strlen ( text );
|
unsigned int dl = strlen ( text );
|
||||||
// Strip new line
|
// Strip new line
|
||||||
while ( dl > 0 && text[dl] == '\n' ) {
|
for ( unsigned int i = 0; i < dl; i++){
|
||||||
text[dl] = '\0';
|
if ( text[i] == '\n' ){
|
||||||
dl--;
|
dl = i;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Insert string move cursor.
|
// Insert string move cursor.
|
||||||
textbox_insert ( state->text, state->text->cursor, text, dl );
|
textbox_insert ( state->text, state->text->cursor, text, dl );
|
||||||
|
@ -865,9 +942,7 @@ static void rofi_view_mouse_navigation ( RofiViewState *state, xcb_button_press_
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
xcb_button_press_event_t rel = *xbe;
|
xcb_button_press_event_t rel = *xbe;
|
||||||
rel.event_x -= config.padding;
|
if ( widget_clicked ( WIDGET ( state->main_window ), &rel ) ) {
|
||||||
rel.event_y -= config.padding;
|
|
||||||
if ( widget_clicked ( WIDGET ( state->main_box ), &rel ) ) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -879,6 +954,7 @@ static void _rofi_view_reload_row ( RofiViewState *state )
|
||||||
state->num_lines = mode_get_num_entries ( state->sw );
|
state->num_lines = mode_get_num_entries ( state->sw );
|
||||||
state->line_map = g_malloc0_n ( state->num_lines, sizeof ( unsigned int ) );
|
state->line_map = g_malloc0_n ( state->num_lines, sizeof ( unsigned int ) );
|
||||||
state->distance = g_malloc0_n ( state->num_lines, sizeof ( int ) );
|
state->distance = g_malloc0_n ( state->num_lines, sizeof ( int ) );
|
||||||
|
listview_set_max_lines ( state->list_view, state->num_lines );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rofi_view_refilter ( RofiViewState *state )
|
static void rofi_view_refilter ( RofiViewState *state )
|
||||||
|
@ -962,7 +1038,9 @@ static void rofi_view_refilter ( RofiViewState *state )
|
||||||
state->retv = MENU_OK;
|
state->retv = MENU_OK;
|
||||||
state->quit = TRUE;
|
state->quit = TRUE;
|
||||||
}
|
}
|
||||||
if ( config.fixed_num_lines == FALSE && ( CacheState.flags & MENU_NORMAL_WINDOW ) == 0 ) {
|
|
||||||
|
// Make sure we enable fixed num lines when in normal window mode.
|
||||||
|
if ( (CacheState.flags&MENU_NORMAL_WINDOW) == 0 ){
|
||||||
int height = rofi_view_calculate_height ( state );
|
int height = rofi_view_calculate_height ( state );
|
||||||
if ( height != state->height ) {
|
if ( height != state->height ) {
|
||||||
state->height = height;
|
state->height = height;
|
||||||
|
@ -1244,6 +1322,7 @@ void rofi_view_itterrate ( RofiViewState *state, xcb_generic_event_t *ev, xkb_st
|
||||||
if ( state->x != xce->x || state->y != xce->y ) {
|
if ( state->x != xce->x || state->y != xce->y ) {
|
||||||
state->x = xce->x;
|
state->x = xce->x;
|
||||||
state->y = xce->y;
|
state->y = xce->y;
|
||||||
|
widget_queue_redraw ( WIDGET ( state->main_window ) );
|
||||||
}
|
}
|
||||||
if ( state->width != xce->width || state->height != xce->height ) {
|
if ( state->width != xce->width || state->height != xce->height ) {
|
||||||
state->width = xce->width;
|
state->width = xce->width;
|
||||||
|
@ -1259,7 +1338,8 @@ 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_surf = cairo_xcb_surface_create ( xcb->connection, CacheState.edit_pixmap, visual, state->width, state->height );
|
||||||
CacheState.edit_draw = cairo_create ( CacheState.edit_surf );
|
CacheState.edit_draw = cairo_create ( CacheState.edit_surf );
|
||||||
widget_resize ( WIDGET ( state->main_box ), state->width - 2 * state->border, state->height - 2 * state->border );
|
g_log ( LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Re-size window based external request: %d %d\n", state->width, state->height);
|
||||||
|
widget_resize ( WIDGET ( state->main_window ), state->width, state->height );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1280,9 +1360,7 @@ void rofi_view_itterrate ( RofiViewState *state, xcb_generic_event_t *ev, xkb_st
|
||||||
state->mouse_seen = TRUE;
|
state->mouse_seen = TRUE;
|
||||||
}
|
}
|
||||||
xcb_motion_notify_event_t xme = *( (xcb_motion_notify_event_t *) ev );
|
xcb_motion_notify_event_t xme = *( (xcb_motion_notify_event_t *) ev );
|
||||||
xme.event_x -= config.padding;
|
if ( widget_motion_notify ( WIDGET ( state->main_window ), &xme ) ) {
|
||||||
xme.event_y -= config.padding;
|
|
||||||
if ( widget_motion_notify ( WIDGET ( state->main_box ), &xme ) ) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1340,7 +1418,7 @@ void rofi_view_itterrate ( RofiViewState *state, xcb_generic_event_t *ev, xkb_st
|
||||||
if ( state->refilter ) {
|
if ( state->refilter ) {
|
||||||
rofi_view_refilter ( state );
|
rofi_view_refilter ( state );
|
||||||
}
|
}
|
||||||
rofi_view_update ( state );
|
rofi_view_update ( state, TRUE );
|
||||||
|
|
||||||
if ( ( ev->response_type & ~0x80 ) == XCB_EXPOSE && CacheState.repaint_source == 0 ) {
|
if ( ( ev->response_type & ~0x80 ) == XCB_EXPOSE && CacheState.repaint_source == 0 ) {
|
||||||
CacheState.repaint_source = g_idle_add_full ( G_PRIORITY_HIGH_IDLE, rofi_view_repaint, NULL, NULL );
|
CacheState.repaint_source = g_idle_add_full ( G_PRIORITY_HIGH_IDLE, rofi_view_repaint, NULL, NULL );
|
||||||
|
@ -1350,19 +1428,13 @@ void rofi_view_itterrate ( RofiViewState *state, xcb_generic_event_t *ev, xkb_st
|
||||||
static int rofi_view_calculate_height ( RofiViewState *state )
|
static int rofi_view_calculate_height ( RofiViewState *state )
|
||||||
{
|
{
|
||||||
unsigned int height = 0;
|
unsigned int height = 0;
|
||||||
if ( config.menu_lines == 0 || config.fullscreen == TRUE ) {
|
if ( listview_get_num_lines ( state->list_view ) == 0 || CacheState.fullscreen == TRUE ) {
|
||||||
height = CacheState.mon.h;
|
height = CacheState.mon.h;
|
||||||
return height;
|
return height;
|
||||||
}
|
}
|
||||||
if ( state->filtered_lines == 0 && !config.fixed_num_lines ) {
|
|
||||||
widget_disable ( WIDGET ( state->input_bar_separator ) );
|
widget *main_window = WIDGET ( state->main_window );
|
||||||
}
|
height = widget_get_desired_height ( main_window );
|
||||||
else {
|
|
||||||
widget_enable ( WIDGET ( state->input_bar_separator ) );
|
|
||||||
}
|
|
||||||
height = listview_get_desired_height ( state->list_view );
|
|
||||||
height += box_get_fixed_pixels ( state->main_box );
|
|
||||||
height += 2 * state->border;
|
|
||||||
return height;
|
return height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1411,7 +1483,6 @@ RofiViewState *rofi_view_create ( Mode *sw,
|
||||||
state->skip_absorb = FALSE;
|
state->skip_absorb = FALSE;
|
||||||
//We want to filter on the first run.
|
//We want to filter on the first run.
|
||||||
state->refilter = TRUE;
|
state->refilter = TRUE;
|
||||||
state->border = config.padding + config.menu_bw;
|
|
||||||
state->finalize = finalize;
|
state->finalize = finalize;
|
||||||
state->mouse_seen = FALSE;
|
state->mouse_seen = FALSE;
|
||||||
|
|
||||||
|
@ -1423,115 +1494,91 @@ RofiViewState *rofi_view_create ( Mode *sw,
|
||||||
// Get active monitor size.
|
// Get active monitor size.
|
||||||
TICK_N ( "Get active monitor" );
|
TICK_N ( "Get active monitor" );
|
||||||
|
|
||||||
state->main_box = box_create ( BOX_VERTICAL,
|
state->main_window = container_create ( "window" );
|
||||||
state->border, state->border,
|
state->main_box = box_create ( "window.mainbox.box", BOX_VERTICAL );
|
||||||
state->width - 2 * state->border, state->height - 2 * state->border );
|
container_add ( state->main_window, WIDGET ( state->main_box ) );
|
||||||
box_set_padding ( state->main_box, config.line_margin );
|
|
||||||
|
|
||||||
// we need this at this point so we can get height.
|
|
||||||
unsigned int line_height = textbox_get_estimated_char_height ();
|
|
||||||
rofi_view_calculate_window_and_element_width ( state );
|
|
||||||
|
|
||||||
state->input_bar = box_create ( BOX_HORIZONTAL, 0, 0, state->width - state->border, line_height );
|
|
||||||
//box_set_padding ( state->input_bar, config.line_margin );
|
|
||||||
state->input_bar_separator = separator_create ( S_HORIZONTAL, 2 );
|
|
||||||
separator_set_line_style_from_string ( state->input_bar_separator, config.separator_style );
|
|
||||||
|
|
||||||
|
state->input_bar = box_create ( "window.mainbox.inputbar.box", BOX_HORIZONTAL );
|
||||||
|
|
||||||
// Only enable widget when sidebar is enabled.
|
// Only enable widget when sidebar is enabled.
|
||||||
if ( config.sidebar_mode ) {
|
if ( config.sidebar_mode ) {
|
||||||
state->sidebar_bar = box_create ( BOX_HORIZONTAL, 0, 0, state->width - 2 * state->border, line_height );
|
state->sidebar_bar = box_create ( "window.mainbox.sidebar.box", BOX_HORIZONTAL );
|
||||||
box_set_padding ( state->sidebar_bar, config.line_margin );
|
box_add ( state->main_box, WIDGET ( state->sidebar_bar ), FALSE, 10 );
|
||||||
separator *sep = separator_create ( S_HORIZONTAL, 2 );
|
|
||||||
separator_set_line_style_from_string ( sep, config.separator_style );
|
|
||||||
box_add ( state->main_box, WIDGET ( state->sidebar_bar ), FALSE, TRUE );
|
|
||||||
box_add ( state->main_box, WIDGET ( sep ), FALSE, TRUE );
|
|
||||||
state->num_modi = rofi_get_num_enabled_modi ();
|
state->num_modi = rofi_get_num_enabled_modi ();
|
||||||
state->modi = g_malloc0 ( state->num_modi * sizeof ( textbox * ) );
|
state->modi = g_malloc0 ( state->num_modi * sizeof ( textbox * ) );
|
||||||
for ( unsigned int j = 0; j < state->num_modi; j++ ) {
|
for ( unsigned int j = 0; j < state->num_modi; j++ ) {
|
||||||
const Mode * mode = rofi_get_mode ( j );
|
const Mode * mode = rofi_get_mode ( j );
|
||||||
state->modi[j] = textbox_create ( TB_CENTER, 0, 0, 0, 0, ( mode == state->sw ) ? HIGHLIGHT : NORMAL,
|
state->modi[j] = textbox_create ( "window.mainbox.sidebar.button", TB_CENTER|TB_AUTOHEIGHT, ( mode == state->sw ) ? HIGHLIGHT : NORMAL,
|
||||||
mode_get_display_name ( mode ) );
|
mode_get_display_name ( mode ) );
|
||||||
box_add ( state->sidebar_bar, WIDGET ( state->modi[j] ), TRUE, FALSE );
|
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 );
|
widget_set_clicked_handler ( WIDGET ( state->modi[j] ), rofi_view_modi_clicked_cb, state );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int end = ( config.location == WL_EAST_SOUTH || config.location == WL_SOUTH || config.location == WL_SOUTH_WEST );
|
int location = rofi_theme_get_position ( WIDGET ( state->main_window ), "location", config.location );
|
||||||
box_add ( state->main_box, WIDGET ( state->input_bar ), FALSE, end );
|
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 ( TB_AUTOWIDTH, 0, 0, 0, line_height, NORMAL, "*" );
|
state->case_indicator = textbox_create ( "window.mainbox.inputbar.case-indicator", TB_AUTOWIDTH|TB_AUTOHEIGHT, NORMAL, "*" );
|
||||||
// Add small separator between case indicator and text box.
|
// Add small separator between case indicator and text box.
|
||||||
box_add ( state->input_bar, WIDGET ( state->case_indicator ), FALSE, TRUE );
|
box_add ( state->input_bar, WIDGET ( state->case_indicator ), FALSE, 3 );
|
||||||
|
|
||||||
// Prompt box.
|
// Prompt box.
|
||||||
state->prompt = textbox_create ( TB_AUTOWIDTH, 0, 0, 0, line_height, NORMAL, "" );
|
state->prompt = textbox_create ( "window.mainbox.inputbar.prompt",TB_AUTOWIDTH|TB_AUTOHEIGHT, NORMAL, "" );
|
||||||
rofi_view_update_prompt ( state );
|
rofi_view_update_prompt ( state );
|
||||||
box_add ( state->input_bar, WIDGET ( state->prompt ), FALSE, FALSE );
|
box_add ( state->input_bar, WIDGET ( state->prompt ), FALSE, 1 );
|
||||||
|
|
||||||
// Entry box
|
// Entry box
|
||||||
TextboxFlags tfl = TB_EDITABLE;
|
TextboxFlags tfl = TB_EDITABLE;
|
||||||
tfl |= ( ( menu_flags & MENU_PASSWORD ) == MENU_PASSWORD ) ? TB_PASSWORD : 0;
|
tfl |= ( ( menu_flags & MENU_PASSWORD ) == MENU_PASSWORD ) ? TB_PASSWORD : 0;
|
||||||
state->text = textbox_create ( tfl, 0, 0, 0, line_height, NORMAL, input );
|
state->text = textbox_create ( "window.mainbox.inputbar.entry", tfl|TB_AUTOHEIGHT, NORMAL, input );
|
||||||
|
|
||||||
box_add ( state->input_bar, WIDGET ( state->text ), TRUE, FALSE );
|
box_add ( state->input_bar, WIDGET ( state->text ), TRUE, 2 );
|
||||||
|
|
||||||
textbox_text ( state->case_indicator, get_matching_state () );
|
textbox_text ( state->case_indicator, get_matching_state () );
|
||||||
if ( message ) {
|
if ( message ) {
|
||||||
textbox *message_tb = textbox_create ( TB_AUTOHEIGHT | TB_MARKUP | TB_WRAP, 0, 0,
|
container *box = container_create ( "window.mainbox.message.box" );
|
||||||
state->width - ( 2 * ( state->border ) ), -1, NORMAL, message );
|
textbox *message_tb = textbox_create ( "window.mainbox.message.textbox", TB_AUTOHEIGHT | TB_MARKUP | TB_WRAP, NORMAL, message );
|
||||||
separator *sep = separator_create ( S_HORIZONTAL, 2 );
|
container_add ( box, WIDGET (message_tb) );
|
||||||
box_add ( state->main_box, WIDGET ( sep ), FALSE, end);
|
box_add ( state->main_box, WIDGET ( box ), FALSE, end?8:2);
|
||||||
box_add ( state->main_box, WIDGET ( message_tb ), FALSE, end);
|
|
||||||
separator_set_line_style_from_string ( sep, config.separator_style );
|
|
||||||
}
|
}
|
||||||
box_add ( state->main_box, WIDGET ( state->input_bar_separator ), FALSE, end );
|
|
||||||
|
|
||||||
state->overlay = textbox_create ( TB_AUTOWIDTH, 0, 0, 20, line_height, URGENT, "blaat" );
|
state->overlay = textbox_create ( "window.overlay", TB_AUTOWIDTH|TB_AUTOHEIGHT, URGENT, "blaat" );
|
||||||
widget_disable ( WIDGET ( state->overlay ) );
|
widget_disable ( WIDGET ( state->overlay ) );
|
||||||
|
|
||||||
state->list_view = listview_create ( update_callback, state, config.element_height );
|
state->list_view = listview_create ( "window.mainbox.listview", update_callback, state, config.element_height, end );
|
||||||
// Set configuration
|
// Set configuration
|
||||||
listview_set_multi_select ( state->list_view, ( state->menu_flags & MENU_INDICATOR ) == MENU_INDICATOR );
|
listview_set_multi_select ( state->list_view, ( state->menu_flags & MENU_INDICATOR ) == MENU_INDICATOR );
|
||||||
listview_set_padding ( state->list_view, config.line_margin );
|
|
||||||
listview_set_max_lines ( state->list_view, config.menu_lines );
|
|
||||||
listview_set_max_columns ( state->list_view, config.menu_columns );
|
|
||||||
listview_set_fixed_num_lines ( state->list_view, config.fixed_num_lines );
|
|
||||||
listview_set_hide_scrollbar ( state->list_view, !config.hide_scrollbar );
|
|
||||||
listview_set_scrollbar_width ( state->list_view, config.scrollbar_width );
|
|
||||||
listview_set_cycle ( state->list_view, config.cycle );
|
|
||||||
listview_set_scroll_type ( state->list_view, config.scroll_method );
|
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 );
|
listview_set_mouse_activated_cb ( state->list_view, rofi_view_listview_mouse_activated_cb, state );
|
||||||
|
|
||||||
box_add ( state->main_box, WIDGET ( state->list_view ), TRUE, FALSE );
|
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);
|
||||||
// Height of a row.
|
|
||||||
if ( config.menu_lines == 0 || config.fullscreen ) {
|
|
||||||
state->height = CacheState.mon.h;
|
|
||||||
// Autosize it.
|
|
||||||
config.fixed_num_lines = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// filtered list
|
// filtered list
|
||||||
state->line_map = g_malloc0_n ( state->num_lines, sizeof ( unsigned int ) );
|
state->line_map = g_malloc0_n ( state->num_lines, sizeof ( unsigned int ) );
|
||||||
state->distance = (int *) g_malloc0_n ( state->num_lines, sizeof ( int ) );
|
state->distance = (int *) g_malloc0_n ( state->num_lines, sizeof ( int ) );
|
||||||
|
|
||||||
state->height = rofi_view_calculate_height ( state );
|
rofi_view_calculate_window_width ( state );
|
||||||
|
// Need to resize otherwise calculated desired height is wrong.
|
||||||
|
widget_resize ( WIDGET ( state->main_window ), state->width, 100);
|
||||||
|
// Only needed when window is fixed size.
|
||||||
|
if (( CacheState.flags & MENU_NORMAL_WINDOW ) == MENU_NORMAL_WINDOW ) {
|
||||||
|
listview_set_fixed_num_lines ( state->list_view );
|
||||||
|
rofi_view_window_update_size ( state );
|
||||||
|
}
|
||||||
// Move the window to the correct x,y position.
|
// Move the window to the correct x,y position.
|
||||||
rofi_view_calculate_window_position ( state );
|
rofi_view_calculate_window_position ( state );
|
||||||
|
|
||||||
rofi_view_window_update_size ( state );
|
|
||||||
// Update.
|
|
||||||
//state->selected = 0;
|
|
||||||
|
|
||||||
state->quit = FALSE;
|
state->quit = FALSE;
|
||||||
rofi_view_refilter ( state );
|
rofi_view_refilter ( state );
|
||||||
|
rofi_view_update ( state, TRUE );
|
||||||
rofi_view_update ( state );
|
|
||||||
xcb_map_window ( xcb->connection, CacheState.main_window );
|
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 );
|
xcb_flush ( xcb->connection );
|
||||||
if ( xcb->sncontext != NULL ) {
|
if ( xcb->sncontext != NULL ) {
|
||||||
sn_launchee_context_complete ( xcb->sncontext );
|
sn_launchee_context_complete ( xcb->sncontext );
|
||||||
|
@ -1543,22 +1590,27 @@ int rofi_view_error_dialog ( const char *msg, int markup )
|
||||||
{
|
{
|
||||||
RofiViewState *state = __rofi_view_state_create ();
|
RofiViewState *state = __rofi_view_state_create ();
|
||||||
state->retv = MENU_CANCEL;
|
state->retv = MENU_CANCEL;
|
||||||
state->border = config.padding + config.menu_bw;
|
|
||||||
state->menu_flags = MENU_ERROR_DIALOG;
|
state->menu_flags = MENU_ERROR_DIALOG;
|
||||||
state->finalize = process_result;
|
state->finalize = process_result;
|
||||||
|
|
||||||
rofi_view_calculate_window_and_element_width ( state );
|
state->main_window = container_create ( "window" );
|
||||||
state->main_box = box_create ( BOX_VERTICAL,
|
state->main_box = box_create ( "window.mainbox.message.box", BOX_VERTICAL);
|
||||||
state->border, state->border,
|
container_add ( state->main_window, WIDGET ( state->main_box ) );
|
||||||
state->width - 2 * state->border, state->height - 2 * state->border );
|
state->text = textbox_create ( "window.mainbox.message.textbox", ( TB_AUTOHEIGHT | TB_WRAP ) + ( ( markup ) ? TB_MARKUP : 0 ),
|
||||||
state->text = textbox_create ( ( TB_AUTOHEIGHT | TB_WRAP ) + ( ( markup ) ? TB_MARKUP : 0 ),
|
NORMAL, ( msg != NULL ) ? msg : "" );
|
||||||
( state->border ), ( state->border ),
|
box_add ( state->main_box, WIDGET ( state->text ), TRUE, 1 );
|
||||||
( state->width - ( 2 * ( state->border ) ) ), 1, NORMAL, ( msg != NULL ) ? msg : "" );
|
|
||||||
box_add ( state->main_box, WIDGET ( state->text ), TRUE, FALSE );
|
|
||||||
unsigned int line_height = textbox_get_height ( state->text );
|
|
||||||
|
|
||||||
|
|
||||||
|
// Make sure we enable fixed num lines when in normal window mode.
|
||||||
|
if ( (CacheState.flags&MENU_NORMAL_WINDOW) == MENU_NORMAL_WINDOW){
|
||||||
|
listview_set_fixed_num_lines ( state->list_view );
|
||||||
|
}
|
||||||
|
rofi_view_calculate_window_width ( state );
|
||||||
|
// Need to resize otherwise calculated desired height is wrong.
|
||||||
|
widget_resize ( WIDGET ( state->main_window ), state->width, 100);
|
||||||
|
unsigned int line_height = textbox_get_height ( state->text );
|
||||||
// resize window vertically to suit
|
// resize window vertically to suit
|
||||||
state->height = line_height + ( state->border ) * 2;
|
state->height = line_height + widget_padding_get_padding_height ( WIDGET(state->main_window) );
|
||||||
|
|
||||||
// Calculte window position.
|
// Calculte window position.
|
||||||
rofi_view_calculate_window_position ( state );
|
rofi_view_calculate_window_position ( state );
|
||||||
|
@ -1568,7 +1620,7 @@ int rofi_view_error_dialog ( const char *msg, int markup )
|
||||||
|
|
||||||
// Display it.
|
// Display it.
|
||||||
xcb_map_window ( xcb->connection, CacheState.main_window );
|
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 ) {
|
if ( xcb->sncontext != NULL ) {
|
||||||
sn_launchee_context_complete ( xcb->sncontext );
|
sn_launchee_context_complete ( xcb->sncontext );
|
||||||
|
@ -1675,9 +1727,17 @@ void rofi_view_set_overlay ( RofiViewState *state, const char *text )
|
||||||
}
|
}
|
||||||
widget_enable ( WIDGET ( state->overlay ) );
|
widget_enable ( WIDGET ( state->overlay ) );
|
||||||
textbox_text ( state->overlay, text );
|
textbox_text ( state->overlay, text );
|
||||||
unsigned int x_offset = state->width - ( 2 * state->border ) - widget_get_width ( WIDGET ( state->case_indicator ) );
|
int x_offset = widget_get_width ( WIDGET(state->main_window) );
|
||||||
|
// 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_get_width ( WIDGET ( state->case_indicator ) );
|
||||||
x_offset -= widget_get_width ( WIDGET ( state->overlay ) );
|
x_offset -= widget_get_width ( WIDGET ( state->overlay ) );
|
||||||
widget_move ( WIDGET ( state->overlay ), x_offset, state->border );
|
int top_offset = widget_padding_get_top ( WIDGET (state->main_window) );
|
||||||
|
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.
|
// We want to queue a repaint.
|
||||||
rofi_view_queue_redraw ( );
|
rofi_view_queue_redraw ( );
|
||||||
}
|
}
|
||||||
|
@ -1707,7 +1767,7 @@ void rofi_view_switch_mode ( RofiViewState *state, Mode *mode )
|
||||||
state->reload = TRUE;
|
state->reload = TRUE;
|
||||||
state->refilter = TRUE;
|
state->refilter = TRUE;
|
||||||
rofi_view_refilter ( state );
|
rofi_view_refilter ( state );
|
||||||
rofi_view_update ( state );
|
rofi_view_update ( state, TRUE );
|
||||||
}
|
}
|
||||||
|
|
||||||
xcb_window_t rofi_view_get_window ( void )
|
xcb_window_t rofi_view_get_window ( void )
|
||||||
|
|
|
@ -29,26 +29,75 @@
|
||||||
#include "widgets/widget.h"
|
#include "widgets/widget.h"
|
||||||
#include "widgets/widget-internal.h"
|
#include "widgets/widget-internal.h"
|
||||||
#include "widgets/box.h"
|
#include "widgets/box.h"
|
||||||
|
#include "theme.h"
|
||||||
|
|
||||||
#define LOG_DOMAIN "Widgets.Box"
|
#define LOG_DOMAIN "Widgets.Box"
|
||||||
|
|
||||||
|
/** Default spacing used in the box*/
|
||||||
|
#define DEFAULT_SPACING 2
|
||||||
|
|
||||||
struct _box
|
struct _box
|
||||||
{
|
{
|
||||||
widget widget;
|
widget widget;
|
||||||
boxType type;
|
boxType type;
|
||||||
int max_size;
|
int max_size;
|
||||||
// Padding between elements
|
// Padding between elements
|
||||||
int padding;
|
Distance spacing;
|
||||||
|
|
||||||
GList *children;
|
GList *children;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void box_update ( widget *wid );
|
static void box_update ( widget *wid );
|
||||||
|
|
||||||
|
static int box_get_desired_height ( widget *wid )
|
||||||
|
{
|
||||||
|
box *b = (box *)wid;
|
||||||
|
int spacing = distance_get_pixel ( b->spacing, b->type == BOX_VERTICAL? ORIENTATION_VERTICAL:ORIENTATION_HORIZONTAL );
|
||||||
|
int active_widgets = 0;
|
||||||
|
int height = 0;
|
||||||
|
if ( b->type == BOX_VERTICAL ){
|
||||||
|
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 ) {
|
||||||
|
height += widget_get_desired_height ( child );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
height += widget_get_desired_height ( child );
|
||||||
|
}
|
||||||
|
if ( active_widgets > 0 ){
|
||||||
|
height += (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;
|
||||||
|
}
|
||||||
|
height = MAX ( widget_get_desired_height ( child ), height );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
height += widget_padding_get_padding_height ( wid );
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void vert_calculate_size ( box *b )
|
static void vert_calculate_size ( box *b )
|
||||||
{
|
{
|
||||||
|
int spacing = distance_get_pixel ( b->spacing, ORIENTATION_VERTICAL );
|
||||||
int expanding_widgets = 0;
|
int expanding_widgets = 0;
|
||||||
int active_widgets = 0;
|
int active_widgets = 0;
|
||||||
|
int rem_width = widget_padding_get_remaining_width ( WIDGET (b) );
|
||||||
|
int rem_height = widget_padding_get_remaining_height ( WIDGET (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, rem_width, widget_get_desired_height (child) );
|
||||||
|
}
|
||||||
|
}
|
||||||
b->max_size = 0;
|
b->max_size = 0;
|
||||||
for ( GList *iter = g_list_first ( b->children ); iter != NULL; iter = g_list_next ( iter ) ) {
|
for ( GList *iter = g_list_first ( b->children ); iter != NULL; iter = g_list_next ( iter ) ) {
|
||||||
widget * child = (widget *) iter->data;
|
widget * child = (widget *) iter->data;
|
||||||
|
@ -60,17 +109,21 @@ static void vert_calculate_size ( box *b )
|
||||||
expanding_widgets++;
|
expanding_widgets++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if ( child->h > 0 ){
|
||||||
b->max_size += child->h;
|
b->max_size += child->h;
|
||||||
}
|
}
|
||||||
b->max_size += MAX ( 0, ( ( active_widgets - 1 ) * b->padding ) );
|
}
|
||||||
if ( b->max_size > b->widget.h ) {
|
if ( active_widgets > 0 ){
|
||||||
|
b->max_size += ( active_widgets - 1 ) * spacing;
|
||||||
|
}
|
||||||
|
if ( b->max_size > rem_height ) {
|
||||||
|
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 );
|
g_log ( LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Widgets to large (height) for box: %d %d", b->max_size, b->widget.h );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ( active_widgets > 0 ) {
|
if ( active_widgets > 0 ) {
|
||||||
int bottom = b->widget.h;
|
int top = widget_padding_get_top ( WIDGET ( b ) );
|
||||||
int top = 0;
|
double rem = rem_height - b->max_size;
|
||||||
double rem = b->widget.h - b->max_size;
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for ( GList *iter = g_list_first ( b->children ); iter != NULL; iter = g_list_next ( iter ) ) {
|
for ( GList *iter = g_list_first ( b->children ); iter != NULL; iter = g_list_next ( iter ) ) {
|
||||||
widget * child = (widget *) iter->data;
|
widget * child = (widget *) iter->data;
|
||||||
|
@ -80,40 +133,35 @@ static void vert_calculate_size ( box *b )
|
||||||
if ( child->expand == TRUE ) {
|
if ( child->expand == TRUE ) {
|
||||||
// Re-calculate to avoid round issues leaving one pixel left.
|
// Re-calculate to avoid round issues leaving one pixel left.
|
||||||
int expanding_widgets_size = ( rem ) / ( expanding_widgets - index );
|
int expanding_widgets_size = ( rem ) / ( expanding_widgets - index );
|
||||||
if ( child->end ) {
|
widget_move ( child, widget_padding_get_left ( WIDGET ( b ) ), top );
|
||||||
bottom -= expanding_widgets_size;
|
|
||||||
widget_move ( child, child->x, bottom );
|
|
||||||
widget_resize ( child, b->widget.w, expanding_widgets_size );
|
|
||||||
bottom -= b->padding;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
widget_move ( child, child->x, top );
|
|
||||||
top += expanding_widgets_size;
|
top += expanding_widgets_size;
|
||||||
widget_resize ( child, b->widget.w, expanding_widgets_size );
|
widget_resize ( child, rem_width, expanding_widgets_size );
|
||||||
top += b->padding;
|
top += spacing;
|
||||||
}
|
|
||||||
rem -= expanding_widgets_size;
|
rem -= expanding_widgets_size;
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
else if ( child->end ) {
|
|
||||||
bottom -= widget_get_height ( child );
|
|
||||||
widget_move ( child, child->x, bottom );
|
|
||||||
widget_resize ( child, b->widget.w, child->h );
|
|
||||||
bottom -= b->padding;
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
widget_move ( child, child->x, top );
|
widget_move ( child, widget_padding_get_left ( WIDGET ( b ) ), top );
|
||||||
top += widget_get_height ( child );
|
top += widget_get_height ( child );
|
||||||
widget_resize ( child, b->widget.w, child->h );
|
top += spacing;
|
||||||
top += b->padding;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
b->max_size += widget_padding_get_padding_height ( WIDGET (b) );
|
||||||
}
|
}
|
||||||
static void hori_calculate_size ( box *b )
|
static void hori_calculate_size ( box *b )
|
||||||
{
|
{
|
||||||
|
int spacing = distance_get_pixel ( b->spacing, ORIENTATION_HORIZONTAL );
|
||||||
int expanding_widgets = 0;
|
int expanding_widgets = 0;
|
||||||
int active_widgets = 0;
|
int active_widgets = 0;
|
||||||
|
int rem_width = widget_padding_get_remaining_width ( WIDGET (b) );
|
||||||
|
int rem_height = widget_padding_get_remaining_height ( WIDGET (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 );
|
||||||
|
}
|
||||||
|
}
|
||||||
b->max_size = 0;
|
b->max_size = 0;
|
||||||
for ( GList *iter = g_list_first ( b->children ); iter != NULL; iter = g_list_next ( iter ) ) {
|
for ( GList *iter = g_list_first ( b->children ); iter != NULL; iter = g_list_next ( iter ) ) {
|
||||||
widget * child = (widget *) iter->data;
|
widget * child = (widget *) iter->data;
|
||||||
|
@ -126,17 +174,19 @@ static void hori_calculate_size ( box *b )
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// Size used by fixed width widgets.
|
// Size used by fixed width widgets.
|
||||||
|
if ( child->h > 0 ){
|
||||||
b->max_size += child->w;
|
b->max_size += child->w;
|
||||||
}
|
}
|
||||||
b->max_size += MAX ( 0, ( ( active_widgets - 1 ) * b->padding ) );
|
}
|
||||||
if ( b->max_size > b->widget.w ) {
|
b->max_size += MAX ( 0, ( ( active_widgets - 1 ) * spacing ) );
|
||||||
|
if ( b->max_size > (rem_width)) {
|
||||||
|
b->max_size = rem_width;
|
||||||
g_log ( LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Widgets to large (width) for box: %d %d", b->max_size, b->widget.w );
|
g_log ( LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Widgets to large (width) for box: %d %d", b->max_size, b->widget.w );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ( active_widgets > 0 ) {
|
if ( active_widgets > 0 ) {
|
||||||
int right = b->widget.w;
|
int left = widget_padding_get_left ( WIDGET (b) );
|
||||||
int left = 0;
|
double rem = rem_width - b->max_size;
|
||||||
double rem = b->widget.w - b->max_size;
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for ( GList *iter = g_list_first ( b->children ); iter != NULL; iter = g_list_next ( iter ) ) {
|
for ( GList *iter = g_list_first ( b->children ); iter != NULL; iter = g_list_next ( iter ) ) {
|
||||||
widget * child = (widget *) iter->data;
|
widget * child = (widget *) iter->data;
|
||||||
|
@ -146,52 +196,30 @@ static void hori_calculate_size ( box *b )
|
||||||
if ( child->expand == TRUE ) {
|
if ( child->expand == TRUE ) {
|
||||||
// Re-calculate to avoid round issues leaving one pixel left.
|
// Re-calculate to avoid round issues leaving one pixel left.
|
||||||
int expanding_widgets_size = ( rem ) / ( expanding_widgets - index );
|
int expanding_widgets_size = ( rem ) / ( expanding_widgets - index );
|
||||||
if ( child->end ) {
|
widget_move ( child, left, widget_padding_get_top ( WIDGET ( b ) ) );
|
||||||
right -= expanding_widgets_size;
|
|
||||||
widget_move ( child, right, child->y );
|
|
||||||
widget_resize ( child, expanding_widgets_size, b->widget.h );
|
|
||||||
right -= b->padding;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
widget_move ( child, left, child->y );
|
|
||||||
left += expanding_widgets_size;
|
left += expanding_widgets_size;
|
||||||
widget_resize ( child, expanding_widgets_size, b->widget.h );
|
widget_resize ( child, expanding_widgets_size, rem_height );
|
||||||
left += b->padding;
|
left += spacing;
|
||||||
}
|
|
||||||
rem -= expanding_widgets_size;
|
rem -= expanding_widgets_size;
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
else if ( child->end ) {
|
|
||||||
right -= widget_get_width ( child );
|
|
||||||
widget_move ( child, right, child->y );
|
|
||||||
widget_resize ( child, child->w, b->widget.h );
|
|
||||||
right -= b->padding;
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
widget_move ( child, left, child->y );
|
widget_move ( child, left, widget_padding_get_top ( WIDGET ( b ) ) );
|
||||||
left += widget_get_width ( child );
|
left += widget_get_width ( child );
|
||||||
widget_resize ( child, child->w, b->widget.h );
|
left += spacing;
|
||||||
left += b->padding;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
b->max_size += widget_padding_get_padding_width ( WIDGET ( b ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void box_draw ( widget *wid, cairo_t *draw )
|
static void box_draw ( widget *wid, cairo_t *draw )
|
||||||
{
|
{
|
||||||
box *b = (box *) wid;
|
box *b = (box *) wid;
|
||||||
// Store current state.
|
|
||||||
cairo_save ( draw );
|
|
||||||
// Define a clipmask so we won't draw outside out widget.
|
|
||||||
cairo_rectangle ( draw, wid->x, wid->y, wid->w, wid->h );
|
|
||||||
cairo_clip ( draw );
|
|
||||||
// Set new x/y possition.
|
|
||||||
cairo_translate ( draw, wid->x, wid->y );
|
|
||||||
for ( GList *iter = g_list_first ( b->children ); iter != NULL; iter = g_list_next ( iter ) ) {
|
for ( GList *iter = g_list_first ( b->children ); iter != NULL; iter = g_list_next ( iter ) ) {
|
||||||
widget * child = (widget *) iter->data;
|
widget * child = (widget *) iter->data;
|
||||||
widget_draw ( child, draw );
|
widget_draw ( child, draw );
|
||||||
}
|
}
|
||||||
cairo_restore ( draw );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void box_free ( widget *wid )
|
static void box_free ( widget *wid )
|
||||||
|
@ -206,15 +234,34 @@ static void box_free ( widget *wid )
|
||||||
g_free ( b );
|
g_free ( b );
|
||||||
}
|
}
|
||||||
|
|
||||||
void box_add ( box *box, widget *child, gboolean expand, gboolean end )
|
static int box_sort_children ( gconstpointer a, gconstpointer b )
|
||||||
|
{
|
||||||
|
widget *child_a = (widget*)a;
|
||||||
|
widget *child_b = (widget*)b;
|
||||||
|
|
||||||
|
return child_a->index - child_b->index;
|
||||||
|
}
|
||||||
|
|
||||||
|
void box_add ( box *box, widget *child, gboolean expand, int index )
|
||||||
{
|
{
|
||||||
if ( box == NULL ) {
|
if ( box == NULL ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
child->expand = expand;
|
// Make sure box is width/heigh enough.
|
||||||
child->end = end;
|
if ( box->type == BOX_VERTICAL){
|
||||||
|
int width=box->widget.w;
|
||||||
|
width = MAX ( width, child->w+widget_padding_get_padding_width ( WIDGET ( box ) ));
|
||||||
|
box->widget.w = width;
|
||||||
|
} else {
|
||||||
|
int height = box->widget.h;
|
||||||
|
height = MAX (height, child->h+widget_padding_get_padding_height ( WIDGET ( box )));
|
||||||
|
box->widget.h = height;
|
||||||
|
}
|
||||||
|
child->expand = rofi_theme_get_boolean ( child, "expand", expand);
|
||||||
|
child->index = rofi_theme_get_integer_exact ( child, "index" , index );
|
||||||
child->parent = WIDGET ( box );
|
child->parent = WIDGET ( box );
|
||||||
box->children = g_list_append ( box->children, (void *) child );
|
box->children = g_list_append ( box->children, (void *) child );
|
||||||
|
box->children = g_list_sort ( box->children, box_sort_children );
|
||||||
widget_update ( WIDGET ( box ) );
|
widget_update ( WIDGET ( box ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,22 +310,22 @@ static gboolean box_motion_notify ( widget *wid, xcb_motion_notify_event_t *xme
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
box * box_create ( boxType type, short x, short y, short w, short h )
|
box * box_create ( const char *name, boxType type )
|
||||||
{
|
{
|
||||||
box *b = g_malloc0 ( sizeof ( box ) );
|
box *b = g_malloc0 ( sizeof ( box ) );
|
||||||
|
// Initialize widget.
|
||||||
|
widget_init ( WIDGET(b), name );
|
||||||
b->type = type;
|
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.draw = box_draw;
|
||||||
b->widget.free = box_free;
|
b->widget.free = box_free;
|
||||||
b->widget.resize = box_resize;
|
b->widget.resize = box_resize;
|
||||||
b->widget.update = box_update;
|
b->widget.update = box_update;
|
||||||
b->widget.clicked = box_clicked;
|
b->widget.clicked = box_clicked;
|
||||||
b->widget.motion_notify = box_motion_notify;
|
b->widget.motion_notify = box_motion_notify;
|
||||||
|
b->widget.get_desired_height = box_get_desired_height;
|
||||||
b->widget.enabled = TRUE;
|
b->widget.enabled = TRUE;
|
||||||
|
|
||||||
|
b->spacing = rofi_theme_get_distance ( WIDGET(b), "spacing", DEFAULT_SPACING );
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -302,11 +349,3 @@ int box_get_fixed_pixels ( box *box )
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void box_set_padding ( box * box, unsigned int padding )
|
|
||||||
{
|
|
||||||
if ( box != NULL ) {
|
|
||||||
box->padding = padding;
|
|
||||||
widget_queue_redraw ( WIDGET ( box ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
148
source/widgets/container.c
Normal file
148
source/widgets/container.c
Normal file
|
@ -0,0 +1,148 @@
|
||||||
|
/**
|
||||||
|
* rofi
|
||||||
|
*
|
||||||
|
* MIT/X11 License
|
||||||
|
* Modified 2016-2017 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/container.h"
|
||||||
|
#include "theme.h"
|
||||||
|
|
||||||
|
#define LOG_DOMAIN "Widgets.Window"
|
||||||
|
|
||||||
|
/** The default border width of the container */
|
||||||
|
#define DEFAULT_BORDER_WIDTH 2
|
||||||
|
|
||||||
|
struct _window
|
||||||
|
{
|
||||||
|
widget widget;
|
||||||
|
widget *child;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void container_update ( widget *wid );
|
||||||
|
|
||||||
|
|
||||||
|
static int container_get_desired_height ( widget *widget )
|
||||||
|
{
|
||||||
|
container *b = (container *) widget;
|
||||||
|
int height = 0;
|
||||||
|
if ( b->child ) {
|
||||||
|
height += widget_get_desired_height ( b->child );
|
||||||
|
}
|
||||||
|
height += widget_padding_get_padding_height ( widget );
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void container_draw ( widget *wid, cairo_t *draw )
|
||||||
|
{
|
||||||
|
container *b = (container *) wid;
|
||||||
|
|
||||||
|
widget_draw ( b->child, draw );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void container_free ( widget *wid )
|
||||||
|
{
|
||||||
|
container *b = (container *) wid;
|
||||||
|
|
||||||
|
widget_free ( b->child );
|
||||||
|
g_free ( b );
|
||||||
|
}
|
||||||
|
|
||||||
|
void container_add ( container *container, widget *child )
|
||||||
|
{
|
||||||
|
if ( container == NULL ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
container->child = child;
|
||||||
|
child->parent = WIDGET ( container );
|
||||||
|
widget_update ( WIDGET ( container ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void container_resize ( widget *widget, short w, short h )
|
||||||
|
{
|
||||||
|
container *b = (container *) widget;
|
||||||
|
if ( b->widget.w != w || b->widget.h != h ) {
|
||||||
|
b->widget.w = w;
|
||||||
|
b->widget.h = h;
|
||||||
|
widget_update ( widget );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean container_clicked ( widget *wid, xcb_button_press_event_t *xbe, G_GNUC_UNUSED void *udata )
|
||||||
|
{
|
||||||
|
container *b = (container *) 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 container_motion_notify ( widget *wid, xcb_motion_notify_event_t *xme )
|
||||||
|
{
|
||||||
|
container *b = (container *) 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
container * container_create ( const char *name )
|
||||||
|
{
|
||||||
|
container *b = g_malloc0 ( sizeof ( container ) );
|
||||||
|
// Initialize widget.
|
||||||
|
widget_init ( WIDGET(b), name );
|
||||||
|
b->widget.draw = container_draw;
|
||||||
|
b->widget.free = container_free;
|
||||||
|
b->widget.resize = container_resize;
|
||||||
|
b->widget.update = container_update;
|
||||||
|
b->widget.clicked = container_clicked;
|
||||||
|
b->widget.motion_notify = container_motion_notify;
|
||||||
|
b->widget.get_desired_height = container_get_desired_height;
|
||||||
|
b->widget.enabled = TRUE;
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void container_update ( widget *wid )
|
||||||
|
{
|
||||||
|
container *b = (container *) wid;
|
||||||
|
if ( b->child && b->child->enabled ){
|
||||||
|
widget_resize ( WIDGET ( b->child ),
|
||||||
|
widget_padding_get_remaining_width (WIDGET(b)),
|
||||||
|
widget_padding_get_remaining_height (WIDGET(b))
|
||||||
|
);
|
||||||
|
widget_move ( WIDGET ( b->child ),
|
||||||
|
widget_padding_get_left (WIDGET(b)),
|
||||||
|
widget_padding_get_top (WIDGET(b))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -29,6 +29,11 @@
|
||||||
#include <widgets/listview.h>
|
#include <widgets/listview.h>
|
||||||
#include <widgets/scrollbar.h>
|
#include <widgets/scrollbar.h>
|
||||||
|
|
||||||
|
#include "settings.h"
|
||||||
|
#include "theme.h"
|
||||||
|
|
||||||
|
#define DEFAULT_SPACING 2
|
||||||
|
|
||||||
struct _listview
|
struct _listview
|
||||||
{
|
{
|
||||||
widget widget;
|
widget widget;
|
||||||
|
@ -51,10 +56,14 @@ struct _listview
|
||||||
unsigned int req_elements;
|
unsigned int req_elements;
|
||||||
unsigned int cur_elements;
|
unsigned int cur_elements;
|
||||||
|
|
||||||
unsigned int padding;
|
Distance spacing;
|
||||||
unsigned int menu_lines;
|
unsigned int menu_lines;
|
||||||
|
unsigned int max_displayed_lines;
|
||||||
unsigned int menu_columns;
|
unsigned int menu_columns;
|
||||||
unsigned int fixed_num_lines;
|
unsigned int fixed_num_lines;
|
||||||
|
unsigned int dynamic;
|
||||||
|
unsigned int eh;
|
||||||
|
unsigned int reverse;
|
||||||
gboolean cycle;
|
gboolean cycle;
|
||||||
gboolean multi_select;
|
gboolean multi_select;
|
||||||
|
|
||||||
|
@ -71,8 +80,13 @@ struct _listview
|
||||||
xcb_timestamp_t last_click;
|
xcb_timestamp_t last_click;
|
||||||
listview_mouse_activated_cb mouse_activated;
|
listview_mouse_activated_cb mouse_activated;
|
||||||
void *mouse_activated_data;
|
void *mouse_activated_data;
|
||||||
|
|
||||||
|
|
||||||
|
char *listview_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int listview_get_desired_height ( widget *wid );
|
||||||
|
|
||||||
static void listview_free ( widget *wid )
|
static void listview_free ( widget *wid )
|
||||||
{
|
{
|
||||||
listview *lv = (listview *) wid;
|
listview *lv = (listview *) wid;
|
||||||
|
@ -81,6 +95,7 @@ static void listview_free ( widget *wid )
|
||||||
}
|
}
|
||||||
g_free ( lv->boxes );
|
g_free ( lv->boxes );
|
||||||
|
|
||||||
|
g_free( lv->listview_name );
|
||||||
widget_free ( WIDGET ( lv->scrollbar ) );
|
widget_free ( WIDGET ( lv->scrollbar ) );
|
||||||
g_free ( lv );
|
g_free ( lv );
|
||||||
}
|
}
|
||||||
|
@ -152,24 +167,40 @@ static void listview_draw ( widget *wid, cairo_t *draw )
|
||||||
// Set these all together to make sure they update consistently.
|
// Set these all together to make sure they update consistently.
|
||||||
scrollbar_set_max_value ( lv->scrollbar, lv->req_elements );
|
scrollbar_set_max_value ( lv->scrollbar, lv->req_elements );
|
||||||
scrollbar_set_handle_length ( lv->scrollbar, lv->cur_columns * lv->max_rows );
|
scrollbar_set_handle_length ( lv->scrollbar, lv->cur_columns * lv->max_rows );
|
||||||
|
if ( lv->reverse ) {
|
||||||
|
scrollbar_set_handle ( lv->scrollbar, lv->req_elements - lv->selected -1 );
|
||||||
|
} else {
|
||||||
scrollbar_set_handle ( lv->scrollbar, lv->selected );
|
scrollbar_set_handle ( lv->scrollbar, lv->selected );
|
||||||
|
}
|
||||||
lv->last_offset = offset;
|
lv->last_offset = offset;
|
||||||
|
int spacing_vert = distance_get_pixel ( lv->spacing, ORIENTATION_VERTICAL );
|
||||||
|
int spacing_hori = distance_get_pixel ( lv->spacing, ORIENTATION_HORIZONTAL );
|
||||||
|
|
||||||
|
int left_offset = widget_padding_get_left ( wid );
|
||||||
|
int top_offset = widget_padding_get_top ( wid );
|
||||||
|
if ( lv->scrollbar->widget.index == 0 ) {
|
||||||
|
left_offset += spacing_hori + lv->scrollbar->widget.w;
|
||||||
|
}
|
||||||
if ( lv->cur_elements > 0 && lv->max_rows > 0 ) {
|
if ( lv->cur_elements > 0 && lv->max_rows > 0 ) {
|
||||||
cairo_save ( draw );
|
|
||||||
// Set new x/y possition.
|
// Set new x/y possition.
|
||||||
cairo_translate ( draw, wid->x, wid->y );
|
|
||||||
unsigned int max = MIN ( lv->cur_elements, lv->req_elements - offset );
|
unsigned int max = MIN ( lv->cur_elements, lv->req_elements - offset );
|
||||||
if ( lv->rchanged ) {
|
if ( lv->rchanged ) {
|
||||||
unsigned int width = lv->widget.w - lv->padding * ( lv->cur_columns - 1 );
|
unsigned int width = lv->widget.w - spacing_hori * ( lv->cur_columns - 1 );
|
||||||
|
width -= widget_padding_get_padding_width ( wid );
|
||||||
if ( widget_enabled ( WIDGET ( lv->scrollbar ) ) ) {
|
if ( widget_enabled ( WIDGET ( lv->scrollbar ) ) ) {
|
||||||
width -= lv->padding;
|
width -= spacing_hori;
|
||||||
width -= widget_get_width ( WIDGET ( lv->scrollbar ) );
|
width -= widget_get_width ( WIDGET ( lv->scrollbar ) );
|
||||||
}
|
}
|
||||||
unsigned int element_width = ( width ) / lv->cur_columns;
|
unsigned int element_width = ( width ) / lv->cur_columns;
|
||||||
for ( unsigned int i = 0; i < max; i++ ) {
|
for ( unsigned int i = 0; i < max; i++ ) {
|
||||||
unsigned int ex = ( ( i ) / lv->max_rows ) * ( element_width + lv->padding );
|
unsigned int ex = left_offset + ( ( i ) / lv->max_rows ) * ( element_width + spacing_hori );
|
||||||
unsigned int ey = ( ( i ) % lv->max_rows ) * ( lv->element_height + lv->padding );
|
if ( lv->reverse ) {
|
||||||
|
unsigned int ey = wid->h-(widget_padding_get_bottom ( wid ) + ( ( i ) % lv->max_rows ) * ( lv->element_height + spacing_vert ))-lv->element_height;
|
||||||
textbox_moveresize ( lv->boxes[i], ex, ey, element_width, lv->element_height );
|
textbox_moveresize ( lv->boxes[i], ex, ey, element_width, lv->element_height );
|
||||||
|
} else {
|
||||||
|
unsigned int ey = top_offset + ( ( i ) % lv->max_rows ) * ( lv->element_height + spacing_vert );
|
||||||
|
textbox_moveresize ( lv->boxes[i], ex, ey, element_width, lv->element_height );
|
||||||
|
}
|
||||||
|
|
||||||
update_element ( lv, i, i + offset, TRUE );
|
update_element ( lv, i, i + offset, TRUE );
|
||||||
widget_draw ( WIDGET ( lv->boxes[i] ), draw );
|
widget_draw ( WIDGET ( lv->boxes[i] ), draw );
|
||||||
|
@ -182,9 +213,8 @@ static void listview_draw ( widget *wid, cairo_t *draw )
|
||||||
widget_draw ( WIDGET ( lv->boxes[i] ), draw );
|
widget_draw ( WIDGET ( lv->boxes[i] ), draw );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
widget_draw ( WIDGET ( lv->scrollbar ), draw );
|
|
||||||
cairo_restore ( draw );
|
|
||||||
}
|
}
|
||||||
|
widget_draw ( WIDGET ( lv->scrollbar ), draw );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void listview_recompute_elements ( listview *lv )
|
static void listview_recompute_elements ( listview *lv )
|
||||||
|
@ -208,7 +238,9 @@ static void listview_recompute_elements ( listview *lv )
|
||||||
if ( newne > 0 ) {
|
if ( newne > 0 ) {
|
||||||
for ( unsigned int i = lv->cur_elements; i < newne; i++ ) {
|
for ( unsigned int i = lv->cur_elements; i < newne; i++ ) {
|
||||||
TextboxFlags flags = ( lv->multi_select ) ? TB_INDICATOR : 0;
|
TextboxFlags flags = ( lv->multi_select ) ? TB_INDICATOR : 0;
|
||||||
lv->boxes[i] = textbox_create ( flags, 0, 0, 0, lv->element_height, NORMAL, "" );
|
char *name = g_strjoin (".", lv->listview_name,"element", NULL);
|
||||||
|
lv->boxes[i] = textbox_create ( name, flags, NORMAL, "" );
|
||||||
|
g_free ( name );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lv->rchanged = TRUE;
|
lv->rchanged = TRUE;
|
||||||
|
@ -244,11 +276,21 @@ static void listview_resize ( widget *wid, short w, short h )
|
||||||
listview *lv = (listview *) wid;
|
listview *lv = (listview *) wid;
|
||||||
lv->widget.w = MAX ( 0, w );
|
lv->widget.w = MAX ( 0, w );
|
||||||
lv->widget.h = MAX ( 0, h );
|
lv->widget.h = MAX ( 0, h );
|
||||||
lv->max_rows = ( lv->padding + lv->widget.h ) / ( lv->element_height + lv->padding );
|
int height = lv->widget.h - widget_padding_get_padding_height ( WIDGET (lv) );
|
||||||
|
int spacing_vert = distance_get_pixel ( lv->spacing, ORIENTATION_VERTICAL );
|
||||||
|
lv->max_rows = ( spacing_vert + height ) / ( lv->element_height + spacing_vert );
|
||||||
lv->max_elements = lv->max_rows * lv->menu_columns;
|
lv->max_elements = lv->max_rows * lv->menu_columns;
|
||||||
|
|
||||||
widget_move ( WIDGET ( lv->scrollbar ), lv->widget.w - widget_get_width ( WIDGET ( lv->scrollbar ) ), 0 );
|
if ( lv->scrollbar->widget.index == 0 ){
|
||||||
widget_resize ( WIDGET ( lv->scrollbar ), widget_get_width ( WIDGET ( lv->scrollbar ) ), h );
|
widget_move ( WIDGET ( lv->scrollbar ),
|
||||||
|
widget_padding_get_left ( WIDGET ( lv ) ),
|
||||||
|
widget_padding_get_top ( WIDGET ( lv ) ) );
|
||||||
|
} else {
|
||||||
|
widget_move ( WIDGET ( lv->scrollbar ),
|
||||||
|
lv->widget.w - widget_padding_get_right ( WIDGET ( lv ) ) - widget_get_width ( WIDGET ( lv->scrollbar ) ),
|
||||||
|
widget_padding_get_top ( WIDGET (lv ) ));
|
||||||
|
}
|
||||||
|
widget_resize ( WIDGET ( lv->scrollbar ), widget_get_width ( WIDGET ( lv->scrollbar ) ), height );
|
||||||
|
|
||||||
listview_recompute_elements ( lv );
|
listview_recompute_elements ( lv );
|
||||||
widget_queue_redraw ( wid );
|
widget_queue_redraw ( wid );
|
||||||
|
@ -310,24 +352,49 @@ static gboolean listview_motion_notify ( widget *wid, xcb_motion_notify_event_t
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
listview *listview_create ( listview_update_callback cb, void *udata, unsigned int eh )
|
listview *listview_create ( const char *name, listview_update_callback cb, void *udata, unsigned int eh, gboolean reverse )
|
||||||
{
|
{
|
||||||
listview *lv = g_malloc0 ( sizeof ( listview ) );
|
listview *lv = g_malloc0 ( sizeof ( listview ) );
|
||||||
|
gchar *box = g_strjoin (".", name, "box", NULL );
|
||||||
|
widget_init ( WIDGET ( lv ), box );
|
||||||
|
g_free(box);
|
||||||
|
lv->listview_name = g_strdup ( name );
|
||||||
lv->widget.free = listview_free;
|
lv->widget.free = listview_free;
|
||||||
lv->widget.resize = listview_resize;
|
lv->widget.resize = listview_resize;
|
||||||
lv->widget.draw = listview_draw;
|
lv->widget.draw = listview_draw;
|
||||||
lv->widget.clicked = listview_clicked;
|
lv->widget.clicked = listview_clicked;
|
||||||
lv->widget.motion_notify = listview_motion_notify;
|
lv->widget.motion_notify = listview_motion_notify;
|
||||||
|
lv->widget.get_desired_height = listview_get_desired_height;
|
||||||
lv->widget.enabled = TRUE;
|
lv->widget.enabled = TRUE;
|
||||||
|
lv->eh = eh;
|
||||||
|
|
||||||
lv->scrollbar = scrollbar_create ( 0, 0, 4, 0 );
|
char *n = g_strjoin(".", lv->listview_name,"scrollbar", NULL);
|
||||||
|
lv->scrollbar = scrollbar_create ( n );
|
||||||
|
// Default position on right.
|
||||||
|
lv->scrollbar->widget.index = rofi_theme_get_integer_exact ( WIDGET (lv->scrollbar), "index", 1);
|
||||||
|
g_free(n);
|
||||||
widget_set_clicked_handler ( WIDGET ( lv->scrollbar ), listview_scrollbar_clicked, lv );
|
widget_set_clicked_handler ( WIDGET ( lv->scrollbar ), listview_scrollbar_clicked, lv );
|
||||||
lv->scrollbar->widget.parent = WIDGET ( lv );
|
lv->scrollbar->widget.parent = WIDGET ( lv );
|
||||||
// Calculate height of an element.
|
// Calculate height of an element.
|
||||||
lv->element_height = textbox_get_estimated_char_height () * eh;
|
//
|
||||||
|
char *tb_name = g_strjoin (".", lv->listview_name,"element", NULL);
|
||||||
|
textbox *tb = textbox_create ( tb_name, 0, NORMAL, "" );
|
||||||
|
lv->element_height = textbox_get_estimated_height (tb, lv->eh);
|
||||||
|
g_free(tb_name);
|
||||||
|
|
||||||
lv->callback = cb;
|
lv->callback = cb;
|
||||||
lv->udata = udata;
|
lv->udata = udata;
|
||||||
|
|
||||||
|
// Some settings.
|
||||||
|
lv->spacing = rofi_theme_get_distance ( WIDGET ( lv ), "spacing", DEFAULT_SPACING );
|
||||||
|
lv->menu_columns = rofi_theme_get_integer ( WIDGET ( lv ), "columns", config.menu_columns );
|
||||||
|
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", !config.hide_scrollbar ));
|
||||||
|
lv->cycle = rofi_theme_get_boolean ( WIDGET ( lv ), "cycle", config.cycle );
|
||||||
|
|
||||||
|
|
||||||
return lv;
|
return lv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,7 +402,7 @@ listview *listview_create ( listview_update_callback cb, void *udata, unsigned i
|
||||||
* Navigation commands.
|
* Navigation commands.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void listview_nav_up ( listview *lv )
|
static void listview_nav_up_int ( listview *lv )
|
||||||
{
|
{
|
||||||
if ( lv == NULL ) {
|
if ( lv == NULL ) {
|
||||||
return;
|
return;
|
||||||
|
@ -349,7 +416,7 @@ void listview_nav_up ( listview *lv )
|
||||||
lv->selected--;
|
lv->selected--;
|
||||||
widget_queue_redraw ( WIDGET ( lv ) );
|
widget_queue_redraw ( WIDGET ( lv ) );
|
||||||
}
|
}
|
||||||
void listview_nav_down ( listview *lv )
|
static void listview_nav_down_int ( listview *lv )
|
||||||
{
|
{
|
||||||
if ( lv == NULL ) {
|
if ( lv == NULL ) {
|
||||||
return;
|
return;
|
||||||
|
@ -362,6 +429,23 @@ void listview_nav_down ( listview *lv )
|
||||||
widget_queue_redraw ( WIDGET ( lv ) );
|
widget_queue_redraw ( WIDGET ( lv ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void listview_nav_up ( listview *lv )
|
||||||
|
{
|
||||||
|
if ( lv->reverse ) {
|
||||||
|
listview_nav_down_int ( lv );
|
||||||
|
} else {
|
||||||
|
listview_nav_up_int ( lv );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void listview_nav_down ( listview *lv )
|
||||||
|
{
|
||||||
|
if ( lv->reverse ) {
|
||||||
|
listview_nav_up_int ( lv );
|
||||||
|
} else {
|
||||||
|
listview_nav_down_int ( lv );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void listview_nav_left ( listview *lv )
|
void listview_nav_left ( listview *lv )
|
||||||
{
|
{
|
||||||
if ( lv == NULL ) {
|
if ( lv == NULL ) {
|
||||||
|
@ -396,7 +480,7 @@ void listview_nav_right ( listview *lv )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void listview_nav_page_prev ( listview *lv )
|
static void listview_nav_page_prev_int ( listview *lv )
|
||||||
{
|
{
|
||||||
if ( lv == NULL ) {
|
if ( lv == NULL ) {
|
||||||
return;
|
return;
|
||||||
|
@ -409,7 +493,7 @@ void listview_nav_page_prev ( listview *lv )
|
||||||
}
|
}
|
||||||
widget_queue_redraw ( WIDGET ( lv ) );
|
widget_queue_redraw ( WIDGET ( lv ) );
|
||||||
}
|
}
|
||||||
void listview_nav_page_next ( listview *lv )
|
static void listview_nav_page_next_int ( listview *lv )
|
||||||
{
|
{
|
||||||
if ( lv == NULL ) {
|
if ( lv == NULL ) {
|
||||||
return;
|
return;
|
||||||
|
@ -424,50 +508,51 @@ void listview_nav_page_next ( listview *lv )
|
||||||
widget_queue_redraw ( WIDGET ( lv ) );
|
widget_queue_redraw ( WIDGET ( lv ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int listview_get_desired_height ( listview *lv )
|
void listview_nav_page_prev ( listview *lv )
|
||||||
{
|
{
|
||||||
if ( lv == NULL ) {
|
if ( lv->reverse ){
|
||||||
|
listview_nav_page_next_int ( lv );
|
||||||
|
} else {
|
||||||
|
listview_nav_page_prev_int ( lv );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void listview_nav_page_next ( listview *lv )
|
||||||
|
{
|
||||||
|
if ( lv->reverse ){
|
||||||
|
listview_nav_page_prev_int ( lv );
|
||||||
|
} else {
|
||||||
|
listview_nav_page_next_int ( lv );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int listview_get_desired_height ( widget *wid )
|
||||||
|
{
|
||||||
|
listview *lv = (listview *)wid;
|
||||||
|
int spacing = distance_get_pixel ( lv->spacing, ORIENTATION_VERTICAL );
|
||||||
|
if ( lv == NULL || lv->widget.enabled == FALSE ) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int h = lv->menu_lines;
|
int h = lv->menu_lines;
|
||||||
if ( !( lv->fixed_num_lines ) ) {
|
if ( !( lv->fixed_num_lines ) ) {
|
||||||
|
if ( lv->dynamic ) {
|
||||||
h = MIN ( lv->menu_lines, lv->req_elements );
|
h = MIN ( lv->menu_lines, lv->req_elements );
|
||||||
|
} else {
|
||||||
|
h = MIN ( lv->menu_lines, lv->max_displayed_lines );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ( h == 0 ) {
|
if ( h == 0 ) {
|
||||||
|
if ( lv->dynamic && !lv->fixed_num_lines ){
|
||||||
|
// Hide widget fully.
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return h * lv->element_height + ( h - 1 ) * lv->padding;
|
return widget_padding_get_padding_height ( WIDGET (lv) );
|
||||||
|
}
|
||||||
|
int height = widget_padding_get_padding_height ( WIDGET (lv) );
|
||||||
|
height += h*(lv->element_height+spacing) - spacing;
|
||||||
|
return height;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
void listview_set_show_scrollbar ( listview *lv, gboolean enabled )
|
||||||
* Configure the widget!
|
|
||||||
*/
|
|
||||||
void listview_set_padding ( listview *lv, unsigned int padding )
|
|
||||||
{
|
|
||||||
if ( lv ) {
|
|
||||||
lv->padding = padding;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void listview_set_max_lines ( listview *lv, unsigned int lines )
|
|
||||||
{
|
|
||||||
if ( lv ) {
|
|
||||||
lv->menu_lines = lines;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void listview_set_max_columns ( listview *lv, unsigned int columns )
|
|
||||||
{
|
|
||||||
if ( lv ) {
|
|
||||||
lv->menu_columns = columns;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void listview_set_fixed_num_lines ( listview *lv, gboolean enabled )
|
|
||||||
{
|
|
||||||
if ( lv ) {
|
|
||||||
lv->fixed_num_lines = enabled;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void listview_set_hide_scrollbar ( listview *lv, gboolean enabled )
|
|
||||||
{
|
{
|
||||||
if ( lv ) {
|
if ( lv ) {
|
||||||
if ( enabled ) {
|
if ( enabled ) {
|
||||||
|
@ -479,19 +564,7 @@ void listview_set_hide_scrollbar ( listview *lv, gboolean enabled )
|
||||||
listview_recompute_elements ( lv );
|
listview_recompute_elements ( lv );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void listview_set_scrollbar_width ( listview *lv, unsigned int width )
|
|
||||||
{
|
|
||||||
if ( lv ) {
|
|
||||||
widget_resize ( WIDGET ( lv->scrollbar ), width, widget_get_height ( WIDGET ( lv->scrollbar ) ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void listview_set_cycle ( listview *lv, gboolean cycle )
|
|
||||||
{
|
|
||||||
if ( lv ) {
|
|
||||||
lv->cycle = cycle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void listview_set_scroll_type ( listview *lv, ScrollType type )
|
void listview_set_scroll_type ( listview *lv, ScrollType type )
|
||||||
{
|
{
|
||||||
if ( lv ) {
|
if ( lv ) {
|
||||||
|
@ -512,3 +585,37 @@ void listview_set_multi_select ( listview *lv, gboolean enable )
|
||||||
lv->multi_select = enable;
|
lv->multi_select = enable;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void listview_set_num_lines ( listview *lv, unsigned int num_lines )
|
||||||
|
{
|
||||||
|
if ( lv ) {
|
||||||
|
lv->menu_lines = num_lines;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int listview_get_num_lines ( listview *lv )
|
||||||
|
{
|
||||||
|
if ( lv ) {
|
||||||
|
return lv->menu_lines;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
void listview_set_max_lines ( listview *lv, unsigned int max_lines )
|
||||||
|
{
|
||||||
|
if ( lv ) {
|
||||||
|
lv->max_displayed_lines = max_lines;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean listview_get_fixed_num_lines ( listview *lv )
|
||||||
|
{
|
||||||
|
if ( lv ) {
|
||||||
|
return lv->fixed_num_lines;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
void listview_set_fixed_num_lines ( listview *lv )
|
||||||
|
{
|
||||||
|
if ( lv ) {
|
||||||
|
lv->fixed_num_lines = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -27,24 +27,37 @@
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include "widgets/scrollbar.h"
|
#include "widgets/scrollbar.h"
|
||||||
#include "x11-helper.h"
|
#include "x11-helper.h"
|
||||||
#include "settings.h"
|
|
||||||
|
#include "theme.h"
|
||||||
|
|
||||||
|
#define DEFAULT_SCROLLBAR_WIDTH 8
|
||||||
|
|
||||||
static void scrollbar_draw ( widget *, cairo_t * );
|
static void scrollbar_draw ( widget *, cairo_t * );
|
||||||
static void scrollbar_free ( widget * );
|
static void scrollbar_free ( widget * );
|
||||||
static gboolean scrollbar_motion_notify ( widget *wid, xcb_motion_notify_event_t *xme );
|
static gboolean scrollbar_motion_notify ( widget *wid, xcb_motion_notify_event_t *xme );
|
||||||
|
|
||||||
scrollbar *scrollbar_create ( short x, short y, short w, short h )
|
|
||||||
|
static int scrollbar_get_desired_height ( widget *wid )
|
||||||
|
{
|
||||||
|
// Want height we are.
|
||||||
|
return wid->h;
|
||||||
|
}
|
||||||
|
|
||||||
|
scrollbar *scrollbar_create ( const char *name )
|
||||||
{
|
{
|
||||||
scrollbar *sb = g_malloc0 ( sizeof ( scrollbar ) );
|
scrollbar *sb = g_malloc0 ( sizeof ( scrollbar ) );
|
||||||
|
widget_init ( WIDGET (sb), name );
|
||||||
sb->widget.x = x;
|
sb->widget.x = 0;
|
||||||
sb->widget.y = y;
|
sb->widget.y = 0;
|
||||||
sb->widget.w = MAX ( 1, w );
|
sb->width = rofi_theme_get_distance ( WIDGET (sb), "handle-width", DEFAULT_SCROLLBAR_WIDTH );
|
||||||
sb->widget.h = MAX ( 1, h );
|
int width = distance_get_pixel (sb->width, ORIENTATION_HORIZONTAL);
|
||||||
|
sb->widget.w = widget_padding_get_padding_width ( WIDGET (sb)) + width;
|
||||||
|
sb->widget.h = widget_padding_get_padding_height ( WIDGET ( sb ) );
|
||||||
|
|
||||||
sb->widget.draw = scrollbar_draw;
|
sb->widget.draw = scrollbar_draw;
|
||||||
sb->widget.free = scrollbar_free;
|
sb->widget.free = scrollbar_free;
|
||||||
sb->widget.motion_notify = scrollbar_motion_notify;
|
sb->widget.motion_notify = scrollbar_motion_notify;
|
||||||
|
sb->widget.get_desired_height = scrollbar_get_desired_height;
|
||||||
|
|
||||||
sb->length = 10;
|
sb->length = 10;
|
||||||
sb->pos = 0;
|
sb->pos = 0;
|
||||||
|
@ -97,20 +110,26 @@ void scrollbar_set_handle_length ( scrollbar *sb, unsigned int pos_length )
|
||||||
static void scrollbar_draw ( widget *wid, cairo_t *draw )
|
static void scrollbar_draw ( widget *wid, cairo_t *draw )
|
||||||
{
|
{
|
||||||
scrollbar *sb = (scrollbar *) wid;
|
scrollbar *sb = (scrollbar *) wid;
|
||||||
|
unsigned int wh = widget_padding_get_remaining_height ( wid );
|
||||||
// Calculate position and size.
|
// Calculate position and size.
|
||||||
unsigned int r = ( sb->length * wid->h ) / ( (double) ( sb->length + sb->pos_length ) );
|
unsigned int r = ( sb->length * wh ) / ( (double) ( sb->length + sb->pos_length ) );
|
||||||
unsigned int handle = wid->h - r;
|
unsigned int handle = wid->h - r;
|
||||||
double sec = ( ( r ) / (double) ( sb->length - 1 ) );
|
double sec = ( ( r ) / (double) ( sb->length - 1 ) );
|
||||||
unsigned int height = handle;
|
unsigned int height = handle;
|
||||||
unsigned int y = sb->pos * sec;
|
unsigned int y = sb->pos * sec;
|
||||||
// Set max pos.
|
// Set max pos.
|
||||||
y = MIN ( y, wid->h - handle );
|
y = MIN ( y, wh - handle );
|
||||||
// Never go out of bar.
|
// Never go out of bar.
|
||||||
height = MAX ( 2, height );
|
height = MAX ( 2, height );
|
||||||
// Cap length;
|
// Cap length;
|
||||||
color_separator ( draw );
|
rofi_theme_get_color ( WIDGET (sb ), "foreground", draw );
|
||||||
|
rofi_theme_get_color ( WIDGET (sb ), "handle-color", draw );
|
||||||
|
|
||||||
cairo_rectangle ( draw, sb->widget.x, sb->widget.y + y, sb->widget.w, height );
|
cairo_rectangle ( draw,
|
||||||
|
widget_padding_get_left ( wid ),
|
||||||
|
widget_padding_get_top ( wid ) + y,
|
||||||
|
widget_padding_get_remaining_width ( wid ),
|
||||||
|
height );
|
||||||
cairo_fill ( draw );
|
cairo_fill ( draw );
|
||||||
}
|
}
|
||||||
static gboolean scrollbar_motion_notify ( widget *wid, xcb_motion_notify_event_t *xme )
|
static gboolean scrollbar_motion_notify ( widget *wid, xcb_motion_notify_event_t *xme )
|
||||||
|
@ -140,3 +159,4 @@ unsigned int scrollbar_clicked ( const scrollbar *sb, int y )
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,129 +0,0 @@
|
||||||
/**
|
|
||||||
* MIT/X11 License
|
|
||||||
* Modified (c) 2016-2017 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 <xkbcommon/xkbcommon.h>
|
|
||||||
#include <glib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include "widgets/widget.h"
|
|
||||||
#include "widgets/widget-internal.h"
|
|
||||||
#include "widgets/separator.h"
|
|
||||||
#include "x11-helper.h"
|
|
||||||
#include "settings.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal structure for the separator.
|
|
||||||
*/
|
|
||||||
struct _separator
|
|
||||||
{
|
|
||||||
widget widget;
|
|
||||||
separator_type type;
|
|
||||||
separator_line_style line_style;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Configuration value for separator style indicating no line */
|
|
||||||
const char *const _separator_style_none = "none";
|
|
||||||
/** Configuration value for separator style indicating dashed line. */
|
|
||||||
const char *const _separator_style_dash = "dash";
|
|
||||||
static void separator_draw ( widget *, cairo_t * );
|
|
||||||
static void separator_free ( widget * );
|
|
||||||
|
|
||||||
separator *separator_create ( separator_type type, short sw )
|
|
||||||
{
|
|
||||||
separator *sb = g_malloc0 ( sizeof ( separator ) );
|
|
||||||
sb->type = type;
|
|
||||||
|
|
||||||
sb->widget.x = 0;
|
|
||||||
sb->widget.y = 0;
|
|
||||||
if ( sb->type == S_HORIZONTAL ) {
|
|
||||||
sb->widget.w = 1;
|
|
||||||
sb->widget.h = MAX ( 1, sw );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sb->widget.h = 1;
|
|
||||||
sb->widget.w = MAX ( 1, sw );
|
|
||||||
}
|
|
||||||
|
|
||||||
sb->widget.draw = separator_draw;
|
|
||||||
sb->widget.free = separator_free;
|
|
||||||
|
|
||||||
// Enabled by default
|
|
||||||
sb->widget.enabled = TRUE;
|
|
||||||
return sb;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void separator_free ( widget *wid )
|
|
||||||
{
|
|
||||||
separator *sb = (separator *) wid;
|
|
||||||
g_free ( sb );
|
|
||||||
}
|
|
||||||
|
|
||||||
void separator_set_line_style ( separator *sp, separator_line_style style )
|
|
||||||
{
|
|
||||||
if ( sp ) {
|
|
||||||
sp->line_style = style;
|
|
||||||
widget_need_redraw ( WIDGET ( sp ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void separator_set_line_style_from_string ( separator *sp, const char *style_str )
|
|
||||||
{
|
|
||||||
if ( !sp ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
separator_line_style style = S_LINE_SOLID;
|
|
||||||
if ( g_strcmp0 ( style_str, _separator_style_none ) == 0 ) {
|
|
||||||
style = S_LINE_NONE;
|
|
||||||
}
|
|
||||||
else if ( g_strcmp0 ( style_str, _separator_style_dash ) == 0 ) {
|
|
||||||
style = S_LINE_DASH;
|
|
||||||
}
|
|
||||||
separator_set_line_style ( sp, style );
|
|
||||||
}
|
|
||||||
|
|
||||||
static void separator_draw ( widget *wid, cairo_t *draw )
|
|
||||||
{
|
|
||||||
separator *sep = (separator *) wid;
|
|
||||||
if ( sep->line_style == S_LINE_NONE ) {
|
|
||||||
// Nothing to draw.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
color_separator ( draw );
|
|
||||||
if ( sep->line_style == S_LINE_DASH ) {
|
|
||||||
const double dashes[1] = { 4 };
|
|
||||||
cairo_set_dash ( draw, dashes, 1, 0.0 );
|
|
||||||
}
|
|
||||||
if ( sep->type == S_HORIZONTAL ) {
|
|
||||||
cairo_set_line_width ( draw, wid->h );
|
|
||||||
double half = wid->h / 2.0;
|
|
||||||
cairo_move_to ( draw, wid->x, wid->y + half );
|
|
||||||
cairo_line_to ( draw, wid->x + wid->w, wid->y + half );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
cairo_set_line_width ( draw, wid->w );
|
|
||||||
double half = wid->w / 2.0;
|
|
||||||
cairo_move_to ( draw, wid->x + half, wid->y );
|
|
||||||
cairo_line_to ( draw, wid->x + half, wid->y + wid->h );
|
|
||||||
}
|
|
||||||
cairo_stroke ( draw );
|
|
||||||
}
|
|
|
@ -29,19 +29,21 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include "settings.h"
|
|
||||||
#include "widgets/textbox.h"
|
#include "widgets/textbox.h"
|
||||||
#include "keyb.h"
|
#include "keyb.h"
|
||||||
#include "x11-helper.h"
|
#include "x11-helper.h"
|
||||||
#include "mode.h"
|
#include "mode.h"
|
||||||
#include "view.h"
|
#include "view.h"
|
||||||
|
|
||||||
|
#include "theme.h"
|
||||||
|
|
||||||
#define DOT_OFFSET 15
|
#define DOT_OFFSET 15
|
||||||
|
|
||||||
static void textbox_draw ( widget *, cairo_t * );
|
static void textbox_draw ( widget *, cairo_t * );
|
||||||
static void textbox_free ( widget * );
|
static void textbox_free ( widget * );
|
||||||
static int textbox_get_width ( widget * );
|
static int textbox_get_width ( widget * );
|
||||||
static int _textbox_get_height ( widget * );
|
static int _textbox_get_height ( widget * );
|
||||||
|
static void __textbox_update_pango_text ( textbox *tb );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param tb Handle to the textbox
|
* @param tb Handle to the textbox
|
||||||
|
@ -50,26 +52,6 @@ static int _textbox_get_height ( widget * );
|
||||||
*/
|
*/
|
||||||
static void textbox_cursor_end ( textbox *tb );
|
static void textbox_cursor_end ( textbox *tb );
|
||||||
|
|
||||||
/**
|
|
||||||
* Font + font color cache.
|
|
||||||
* Avoid re-loading font on every change on every textbox.
|
|
||||||
*/
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
Color fg;
|
|
||||||
Color bg;
|
|
||||||
Color bgalt;
|
|
||||||
Color hlfg;
|
|
||||||
Color hlbg;
|
|
||||||
} RowColor;
|
|
||||||
|
|
||||||
/** Number of states */
|
|
||||||
#define num_states 3
|
|
||||||
/**
|
|
||||||
* Different colors for the different states
|
|
||||||
*/
|
|
||||||
RowColor colors[num_states];
|
|
||||||
|
|
||||||
/** Default pango context */
|
/** Default pango context */
|
||||||
static PangoContext *p_context = NULL;
|
static PangoContext *p_context = NULL;
|
||||||
/** The pango font metrics */
|
/** The pango font metrics */
|
||||||
|
@ -95,24 +77,34 @@ static void textbox_resize ( widget *wid, short w, short h )
|
||||||
textbox *tb = (textbox *) wid;
|
textbox *tb = (textbox *) wid;
|
||||||
textbox_moveresize ( tb, tb->widget.x, tb->widget.y, w, h );
|
textbox_moveresize ( tb, tb->widget.x, tb->widget.y, w, h );
|
||||||
}
|
}
|
||||||
|
static int textbox_get_desired_height ( widget *wid )
|
||||||
|
{
|
||||||
|
textbox *tb = (textbox *)wid;
|
||||||
|
if ( (tb->flags & TB_AUTOHEIGHT) == 0 )
|
||||||
|
{
|
||||||
|
return tb->widget.h;
|
||||||
|
}
|
||||||
|
if ( tb->changed ) {
|
||||||
|
__textbox_update_pango_text ( tb );
|
||||||
|
}
|
||||||
|
int height = textbox_get_height (tb);
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
textbox* textbox_create ( TextboxFlags flags, short x, short y, short w, short h,
|
textbox* textbox_create ( const char *name, TextboxFlags flags, TextBoxFontType tbft, const char *text )
|
||||||
TextBoxFontType tbft, const char *text )
|
|
||||||
{
|
{
|
||||||
textbox *tb = g_slice_new0 ( textbox );
|
textbox *tb = g_slice_new0 ( textbox );
|
||||||
|
|
||||||
|
widget_init ( WIDGET (tb), name );
|
||||||
|
|
||||||
tb->widget.draw = textbox_draw;
|
tb->widget.draw = textbox_draw;
|
||||||
tb->widget.free = textbox_free;
|
tb->widget.free = textbox_free;
|
||||||
tb->widget.resize = textbox_resize;
|
tb->widget.resize = textbox_resize;
|
||||||
tb->widget.get_width = textbox_get_width;
|
tb->widget.get_width = textbox_get_width;
|
||||||
tb->widget.get_height = _textbox_get_height;
|
tb->widget.get_height = _textbox_get_height;
|
||||||
|
tb->widget.get_desired_height = textbox_get_desired_height;
|
||||||
tb->flags = flags;
|
tb->flags = flags;
|
||||||
|
|
||||||
tb->widget.x = x;
|
|
||||||
tb->widget.y = y;
|
|
||||||
tb->widget.w = MAX ( 1, w );
|
|
||||||
tb->widget.h = MAX ( 1, h );
|
|
||||||
|
|
||||||
tb->changed = FALSE;
|
tb->changed = FALSE;
|
||||||
|
|
||||||
tb->main_surface = cairo_image_surface_create ( CAIRO_FORMAT_ARGB32, tb->widget.w, tb->widget.h );
|
tb->main_surface = cairo_image_surface_create ( CAIRO_FORMAT_ARGB32, tb->widget.w, tb->widget.h );
|
||||||
|
@ -140,6 +132,18 @@ textbox* textbox_create ( TextboxFlags flags, short x, short y, short w, short h
|
||||||
return tb;
|
return tb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* State names used for theming.
|
||||||
|
*/
|
||||||
|
const char const *const theme_prop_names[][3] = {
|
||||||
|
/** Normal row */
|
||||||
|
{"normal.normal", "selected.normal", "alternate.normal"},
|
||||||
|
/** Urgent row */
|
||||||
|
{"normal.urgent", "selected.urgent", "alternate.urgent"},
|
||||||
|
/** Active row */
|
||||||
|
{"normal.active", "selected.active", "alternate.active"},
|
||||||
|
};
|
||||||
|
|
||||||
void textbox_font ( textbox *tb, TextBoxFontType tbft )
|
void textbox_font ( textbox *tb, TextBoxFontType tbft )
|
||||||
{
|
{
|
||||||
TextBoxFontType t = tbft & STATE_MASK;
|
TextBoxFontType t = tbft & STATE_MASK;
|
||||||
|
@ -150,23 +154,19 @@ void textbox_font ( textbox *tb, TextBoxFontType tbft )
|
||||||
if ( t == ( URGENT | ACTIVE ) ) {
|
if ( t == ( URGENT | ACTIVE ) ) {
|
||||||
t = ACTIVE;
|
t = ACTIVE;
|
||||||
}
|
}
|
||||||
RowColor *color = &( colors[t] );
|
|
||||||
switch ( ( tbft & FMOD_MASK ) )
|
switch ( ( tbft & FMOD_MASK ) )
|
||||||
{
|
{
|
||||||
case HIGHLIGHT:
|
case HIGHLIGHT:
|
||||||
tb->color_bg = color->hlbg;
|
widget_set_state ( WIDGET (tb), theme_prop_names[t][1]);
|
||||||
tb->color_fg = color->hlfg;
|
|
||||||
break;
|
break;
|
||||||
case ALT:
|
case ALT:
|
||||||
tb->color_bg = color->bgalt;
|
widget_set_state ( WIDGET (tb), theme_prop_names[t][2]);
|
||||||
tb->color_fg = color->fg;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
tb->color_bg = color->bg;
|
widget_set_state ( WIDGET (tb), theme_prop_names[t][0]);
|
||||||
tb->color_fg = color->fg;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if ( tb->tbft != tbft ) {
|
if ( tb->tbft != tbft || tb->widget.state == NULL ) {
|
||||||
tb->update = TRUE;
|
tb->update = TRUE;
|
||||||
widget_queue_redraw ( WIDGET ( tb ) );
|
widget_queue_redraw ( WIDGET ( tb ) );
|
||||||
}
|
}
|
||||||
|
@ -232,7 +232,9 @@ void textbox_text ( textbox *tb, const char *text )
|
||||||
__textbox_update_pango_text ( tb );
|
__textbox_update_pango_text ( tb );
|
||||||
if ( tb->flags & TB_AUTOWIDTH ) {
|
if ( tb->flags & TB_AUTOWIDTH ) {
|
||||||
textbox_moveresize ( tb, tb->widget.x, tb->widget.y, tb->widget.w, tb->widget.h );
|
textbox_moveresize ( tb, tb->widget.x, tb->widget.y, tb->widget.w, tb->widget.h );
|
||||||
widget_update ( WIDGET ( tb ) );
|
if ( WIDGET(tb)->parent ){
|
||||||
|
widget_update ( WIDGET ( tb )->parent );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tb->cursor = MAX ( 0, MIN ( ( int ) g_utf8_strlen ( tb->text, -1 ), tb->cursor ) );
|
tb->cursor = MAX ( 0, MIN ( ( int ) g_utf8_strlen ( tb->text, -1 ), tb->cursor ) );
|
||||||
|
@ -246,7 +248,7 @@ void textbox_moveresize ( textbox *tb, int x, int y, int w, int h )
|
||||||
if ( tb->flags & TB_AUTOWIDTH ) {
|
if ( tb->flags & TB_AUTOWIDTH ) {
|
||||||
pango_layout_set_width ( tb->layout, -1 );
|
pango_layout_set_width ( tb->layout, -1 );
|
||||||
unsigned int offset = ( tb->flags & TB_INDICATOR ) ? DOT_OFFSET : 0;
|
unsigned int offset = ( tb->flags & TB_INDICATOR ) ? DOT_OFFSET : 0;
|
||||||
w = textbox_get_font_width ( tb ) + 2 * config.line_padding + offset;
|
w = textbox_get_font_width ( tb ) + widget_padding_get_padding_width ( WIDGET (tb) ) + offset;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// set ellipsize
|
// set ellipsize
|
||||||
|
@ -261,8 +263,9 @@ void textbox_moveresize ( textbox *tb, int x, int y, int w, int h )
|
||||||
if ( tb->flags & TB_AUTOHEIGHT ) {
|
if ( tb->flags & TB_AUTOHEIGHT ) {
|
||||||
// Width determines height!
|
// Width determines height!
|
||||||
int tw = MAX ( 1, w );
|
int tw = MAX ( 1, w );
|
||||||
pango_layout_set_width ( tb->layout, PANGO_SCALE * ( tw - 2 * config.line_padding - offset ) );
|
pango_layout_set_width ( tb->layout, PANGO_SCALE * ( tw - widget_padding_get_padding_width ( WIDGET (tb) ) - offset ) );
|
||||||
h = textbox_get_height ( tb );
|
int hd = textbox_get_height ( tb );
|
||||||
|
h = MAX (hd, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( x != tb->widget.x || y != tb->widget.y || w != tb->widget.w || h != tb->widget.h ) {
|
if ( x != tb->widget.x || y != tb->widget.y || w != tb->widget.w || h != tb->widget.h ) {
|
||||||
|
@ -273,7 +276,7 @@ void textbox_moveresize ( textbox *tb, int x, int y, int w, int h )
|
||||||
}
|
}
|
||||||
|
|
||||||
// We always want to update this
|
// We always want to update this
|
||||||
pango_layout_set_width ( tb->layout, PANGO_SCALE * ( tb->widget.w - 2 * config.line_padding - offset ) );
|
pango_layout_set_width ( tb->layout, PANGO_SCALE * ( tb->widget.w - widget_padding_get_padding_width ( WIDGET (tb) ) - offset ) );
|
||||||
tb->update = TRUE;
|
tb->update = TRUE;
|
||||||
widget_queue_redraw ( WIDGET ( tb ) );
|
widget_queue_redraw ( WIDGET ( tb ) );
|
||||||
}
|
}
|
||||||
|
@ -286,7 +289,6 @@ static void textbox_free ( widget *wid )
|
||||||
g_source_remove ( tb->blink_timeout );
|
g_source_remove ( tb->blink_timeout );
|
||||||
tb->blink_timeout = 0;
|
tb->blink_timeout = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_free ( tb->text );
|
g_free ( tb->text );
|
||||||
|
|
||||||
if ( tb->layout != NULL ) {
|
if ( tb->layout != NULL ) {
|
||||||
|
@ -316,13 +318,15 @@ static void texbox_update ( textbox *tb )
|
||||||
}
|
}
|
||||||
tb->main_surface = cairo_image_surface_create ( CAIRO_FORMAT_ARGB32, tb->widget.w, tb->widget.h );
|
tb->main_surface = cairo_image_surface_create ( CAIRO_FORMAT_ARGB32, tb->widget.w, tb->widget.h );
|
||||||
tb->main_draw = cairo_create ( tb->main_surface );
|
tb->main_draw = cairo_create ( tb->main_surface );
|
||||||
cairo_set_operator ( tb->main_draw, CAIRO_OPERATOR_SOURCE );
|
cairo_set_operator ( tb->main_draw, CAIRO_OPERATOR_OVER );
|
||||||
|
|
||||||
pango_cairo_update_layout ( tb->main_draw, tb->layout );
|
pango_cairo_update_layout ( tb->main_draw, tb->layout );
|
||||||
int font_height = textbox_get_font_height ( tb );
|
int font_height = textbox_get_font_height ( tb );
|
||||||
|
|
||||||
int cursor_x = 0;
|
int cursor_x = 0;
|
||||||
int cursor_width = MAX ( 2, font_height / 10 );
|
int cursor_y = 0;
|
||||||
|
int cursor_width = 2;//MAX ( 2, font_height / 10 );
|
||||||
|
int cursor_height = font_height;
|
||||||
|
|
||||||
if ( tb->changed ) {
|
if ( tb->changed ) {
|
||||||
__textbox_update_pango_text ( tb );
|
__textbox_update_pango_text ( tb );
|
||||||
|
@ -338,50 +342,52 @@ static void texbox_update ( textbox *tb )
|
||||||
char *offset = g_utf8_offset_to_pointer ( text, cursor_offset );
|
char *offset = g_utf8_offset_to_pointer ( text, cursor_offset );
|
||||||
pango_layout_get_cursor_pos ( tb->layout, offset - text, &pos, NULL );
|
pango_layout_get_cursor_pos ( tb->layout, offset - text, &pos, NULL );
|
||||||
cursor_x = pos.x / PANGO_SCALE;
|
cursor_x = pos.x / PANGO_SCALE;
|
||||||
|
cursor_y = pos.y / PANGO_SCALE;
|
||||||
|
cursor_height = pos.height/PANGO_SCALE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip the side MARGIN on the X axis.
|
// Skip the side MARGIN on the X axis.
|
||||||
int x = config.line_padding + offset;
|
int x = widget_padding_get_left ( WIDGET (tb) ) + offset;
|
||||||
int y = 0;
|
int y = 0;
|
||||||
|
|
||||||
if ( tb->flags & TB_RIGHT ) {
|
if ( tb->flags & TB_RIGHT ) {
|
||||||
int line_width = 0;
|
int line_width = 0;
|
||||||
// Get actual width.
|
// Get actual width.
|
||||||
pango_layout_get_pixel_size ( tb->layout, &line_width, NULL );
|
pango_layout_get_pixel_size ( tb->layout, &line_width, NULL );
|
||||||
x = ( tb->widget.w - line_width - config.line_padding - offset );
|
x = ( tb->widget.w - line_width - widget_padding_get_right ( WIDGET (tb) ) - offset );
|
||||||
}
|
}
|
||||||
else if ( tb->flags & TB_CENTER ) {
|
else if ( tb->flags & TB_CENTER ) {
|
||||||
int tw = textbox_get_font_width ( tb );
|
int tw = textbox_get_font_width ( tb );
|
||||||
x = ( ( tb->widget.w - tw - 2 * config.line_padding - offset ) ) / 2;
|
x = ( ( tb->widget.w - tw - widget_padding_get_padding_width( WIDGET (tb) ) - offset ) ) / 2;
|
||||||
}
|
}
|
||||||
y = config.line_padding + ( pango_font_metrics_get_ascent ( p_metrics ) - pango_layout_get_baseline ( tb->layout ) ) / PANGO_SCALE;
|
y = widget_padding_get_top ( WIDGET (tb) ) + ( pango_font_metrics_get_ascent ( p_metrics ) - pango_layout_get_baseline ( tb->layout ) ) / PANGO_SCALE;
|
||||||
|
|
||||||
// Set ARGB
|
// Set background transparency
|
||||||
Color col = tb->color_bg;
|
//cairo_set_source_rgba ( tb->main_draw, 0,0,0,0.0);
|
||||||
cairo_set_source_rgba ( tb->main_draw, col.red, col.green, col.blue, col.alpha );
|
//cairo_paint ( tb->main_draw );
|
||||||
cairo_paint ( tb->main_draw );
|
|
||||||
|
|
||||||
col = tb->color_fg;
|
rofi_theme_get_color ( WIDGET ( tb ), "foreground", tb->main_draw);
|
||||||
cairo_set_source_rgba ( tb->main_draw, col.red, col.green, col.blue, col.alpha );
|
|
||||||
// draw the cursor
|
// draw the cursor
|
||||||
if ( tb->flags & TB_EDITABLE && tb->blink ) {
|
if ( tb->flags & TB_EDITABLE && tb->blink ) {
|
||||||
cairo_rectangle ( tb->main_draw, x + cursor_x, y, cursor_width, font_height );
|
cairo_rectangle ( tb->main_draw, x + cursor_x, y+cursor_y, cursor_width, cursor_height);
|
||||||
cairo_fill ( tb->main_draw );
|
cairo_fill ( tb->main_draw );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set ARGB
|
// Set ARGB
|
||||||
// We need to set over, otherwise subpixel hinting wont work.
|
// We need to set over, otherwise subpixel hinting wont work.
|
||||||
cairo_set_operator ( tb->main_draw, CAIRO_OPERATOR_OVER );
|
//cairo_set_operator ( tb->main_draw, CAIRO_OPERATOR_OVER );
|
||||||
cairo_move_to ( tb->main_draw, x, y );
|
cairo_move_to ( tb->main_draw, x, y );
|
||||||
pango_cairo_show_layout ( tb->main_draw, tb->layout );
|
pango_cairo_show_layout ( tb->main_draw, tb->layout );
|
||||||
|
|
||||||
if ( ( tb->flags & TB_INDICATOR ) == TB_INDICATOR && ( tb->tbft & ( SELECTED | HIGHLIGHT ) ) ) {
|
if ( ( tb->flags & TB_INDICATOR ) == TB_INDICATOR && ( tb->tbft & ( SELECTED ) ) ) {
|
||||||
|
/*
|
||||||
if ( ( tb->tbft & SELECTED ) == SELECTED ) {
|
if ( ( tb->tbft & SELECTED ) == SELECTED ) {
|
||||||
cairo_set_source_rgba ( tb->main_draw, col.red, col.green, col.blue, col.alpha );
|
cairo_set_source_rgba ( tb->main_draw, col.red, col.green, col.blue, col.alpha );
|
||||||
}
|
}
|
||||||
else if ( ( tb->tbft & HIGHLIGHT ) == HIGHLIGHT ) {
|
else if ( ( tb->tbft & HIGHLIGHT ) == HIGHLIGHT ) {
|
||||||
cairo_set_source_rgba ( tb->main_draw, col.red, col.green, col.blue, col.alpha * 0.2 );
|
cairo_set_source_rgba ( tb->main_draw, col.red, col.green, col.blue, col.alpha * 0.2 );
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
cairo_arc ( tb->main_draw, DOT_OFFSET / 2.0, tb->widget.h / 2.0, 2.0, 0, 2.0 * M_PI );
|
cairo_arc ( tb->main_draw, DOT_OFFSET / 2.0, tb->widget.h / 2.0, 2.0, 0, 2.0 * M_PI );
|
||||||
cairo_fill ( tb->main_draw );
|
cairo_fill ( tb->main_draw );
|
||||||
|
@ -396,9 +402,8 @@ static void textbox_draw ( widget *wid, cairo_t *draw )
|
||||||
texbox_update ( tb );
|
texbox_update ( tb );
|
||||||
|
|
||||||
/* Write buffer */
|
/* Write buffer */
|
||||||
|
cairo_set_source_surface ( draw, tb->main_surface, 0,0 );
|
||||||
cairo_set_source_surface ( draw, tb->main_surface, tb->widget.x, tb->widget.y );
|
cairo_rectangle ( draw, 0,0, tb->widget.w, tb->widget.h );
|
||||||
cairo_rectangle ( draw, tb->widget.x, tb->widget.y, tb->widget.w, tb->widget.h );
|
|
||||||
cairo_fill ( draw );
|
cairo_fill ( draw );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -709,47 +714,8 @@ gboolean textbox_append_char ( textbox *tb, const char *pad, const int pad_len )
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***
|
|
||||||
* Font setup.
|
|
||||||
*/
|
|
||||||
static void textbox_parse_string ( const char *str, RowColor *color )
|
|
||||||
{
|
|
||||||
if ( str == NULL ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
char *cstr = g_strdup ( str );
|
|
||||||
char *endp = NULL;
|
|
||||||
char *token;
|
|
||||||
int index = 0;
|
|
||||||
const char *const sep = ",";
|
|
||||||
for ( token = strtok_r ( cstr, sep, &endp ); token != NULL; token = strtok_r ( NULL, sep, &endp ) ) {
|
|
||||||
switch ( index )
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
color->bg = color_get ( g_strstrip ( token ) );
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
color->fg = color_get ( g_strstrip ( token ) );
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
color->bgalt = color_get ( g_strstrip ( token ) );
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
color->hlbg = color_get ( g_strstrip ( token ) );
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
color->hlfg = color_get ( g_strstrip ( token ) );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
g_free ( cstr );
|
|
||||||
}
|
|
||||||
void textbox_setup ( void )
|
void textbox_setup ( void )
|
||||||
{
|
{
|
||||||
textbox_parse_string ( config.color_normal, &( colors[NORMAL] ) );
|
|
||||||
textbox_parse_string ( config.color_urgent, &( colors[URGENT] ) );
|
|
||||||
textbox_parse_string ( config.color_active, &( colors[ACTIVE] ) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void textbox_set_pango_context ( PangoContext *p )
|
void textbox_set_pango_context ( PangoContext *p )
|
||||||
|
@ -774,12 +740,9 @@ void textbox_cleanup ( void )
|
||||||
int textbox_get_width ( widget *wid )
|
int textbox_get_width ( widget *wid )
|
||||||
{
|
{
|
||||||
textbox *tb = (textbox *) wid;
|
textbox *tb = (textbox *) wid;
|
||||||
if ( !wid->expand ) {
|
|
||||||
if ( tb->flags & TB_AUTOWIDTH ) {
|
if ( tb->flags & TB_AUTOWIDTH ) {
|
||||||
unsigned int offset = ( tb->flags & TB_INDICATOR ) ? DOT_OFFSET : 0;
|
unsigned int offset = ( tb->flags & TB_INDICATOR ) ? DOT_OFFSET : 0;
|
||||||
return textbox_get_font_width ( tb ) + 2 * config.line_padding + offset;
|
return textbox_get_font_width ( tb ) + widget_padding_get_padding_width ( wid ) + offset;
|
||||||
}
|
|
||||||
return tb->widget.w;
|
|
||||||
}
|
}
|
||||||
return tb->widget.w;
|
return tb->widget.w;
|
||||||
}
|
}
|
||||||
|
@ -787,17 +750,14 @@ int textbox_get_width ( widget *wid )
|
||||||
int _textbox_get_height ( widget *wid )
|
int _textbox_get_height ( widget *wid )
|
||||||
{
|
{
|
||||||
textbox *tb = (textbox *) wid;
|
textbox *tb = (textbox *) wid;
|
||||||
if ( !wid->expand ) {
|
|
||||||
if ( tb->flags & TB_AUTOHEIGHT ) {
|
if ( tb->flags & TB_AUTOHEIGHT ) {
|
||||||
return textbox_get_height ( tb );
|
return textbox_get_height ( tb );
|
||||||
}
|
}
|
||||||
return tb->widget.h;
|
return tb->widget.h;
|
||||||
}
|
|
||||||
return tb->widget.h;
|
|
||||||
}
|
}
|
||||||
int textbox_get_height ( const textbox *tb )
|
int textbox_get_height ( const textbox *tb )
|
||||||
{
|
{
|
||||||
return textbox_get_font_height ( tb ) + 2 * config.line_padding;
|
return textbox_get_font_height ( tb ) + widget_padding_get_padding_height ( WIDGET (tb) );
|
||||||
}
|
}
|
||||||
|
|
||||||
int textbox_get_font_height ( const textbox *tb )
|
int textbox_get_font_height ( const textbox *tb )
|
||||||
|
@ -814,14 +774,30 @@ int textbox_get_font_width ( const textbox *tb )
|
||||||
return width;
|
return width;
|
||||||
}
|
}
|
||||||
|
|
||||||
double textbox_get_estimated_char_width ( void )
|
/** Caching for the expected character height. */
|
||||||
|
static double char_height = -1;
|
||||||
|
double textbox_get_estimated_char_height ( void )
|
||||||
{
|
{
|
||||||
int width = pango_font_metrics_get_approximate_char_width ( p_metrics );
|
if ( char_height < 0 ){
|
||||||
return ( width ) / (double) PANGO_SCALE;
|
int height = pango_font_metrics_get_ascent ( p_metrics ) + pango_font_metrics_get_descent ( p_metrics );
|
||||||
|
char_height = ( height ) / (double) PANGO_SCALE;
|
||||||
|
}
|
||||||
|
return char_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
int textbox_get_estimated_char_height ( void )
|
/** Caching for the expected character width. */
|
||||||
|
static double char_width = -1;
|
||||||
|
double textbox_get_estimated_char_width ( void )
|
||||||
|
{
|
||||||
|
if ( char_width < 0 ){
|
||||||
|
int width = pango_font_metrics_get_approximate_char_width ( p_metrics );
|
||||||
|
char_width = ( width ) / (double) PANGO_SCALE;
|
||||||
|
}
|
||||||
|
return char_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
int textbox_get_estimated_height ( const textbox *tb, int eh )
|
||||||
{
|
{
|
||||||
int height = pango_font_metrics_get_ascent ( p_metrics ) + pango_font_metrics_get_descent ( p_metrics );
|
int height = pango_font_metrics_get_ascent ( p_metrics ) + pango_font_metrics_get_descent ( p_metrics );
|
||||||
return ( height ) / PANGO_SCALE + 2 * config.line_padding;
|
return ( eh*height ) / PANGO_SCALE + widget_padding_get_padding_height ( WIDGET ( tb ) );
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,31 @@
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include "widgets/widget.h"
|
#include "widgets/widget.h"
|
||||||
#include "widgets/widget-internal.h"
|
#include "widgets/widget-internal.h"
|
||||||
|
#include "theme.h"
|
||||||
|
|
||||||
|
|
||||||
|
void widget_init ( widget *widget , const char *name )
|
||||||
|
{
|
||||||
|
widget->name = g_strdup(name);
|
||||||
|
widget->padding = (Padding){ {0, PW_PX, SOLID}, {0, PW_PX, SOLID}, {0, PW_PX, SOLID}, {0, PW_PX, SOLID}};
|
||||||
|
widget->border = (Padding){ {0, PW_PX, SOLID}, {0, PW_PX, SOLID}, {0, PW_PX, SOLID}, {0, PW_PX, SOLID}};
|
||||||
|
widget->margin = (Padding){ {0, PW_PX, SOLID}, {0, PW_PX, SOLID}, {0, PW_PX, SOLID}, {0, PW_PX, SOLID}};
|
||||||
|
|
||||||
|
widget->padding = rofi_theme_get_padding ( widget, "padding", widget->padding);
|
||||||
|
widget->border = rofi_theme_get_padding ( widget, "border", widget->border);
|
||||||
|
widget->margin = rofi_theme_get_padding ( widget, "margin", widget->margin);
|
||||||
|
}
|
||||||
|
|
||||||
|
void widget_set_state ( widget *widget, const char *state )
|
||||||
|
{
|
||||||
|
if ( g_strcmp0(widget->state, state ) ){
|
||||||
|
widget->state = state;
|
||||||
|
// Update border.
|
||||||
|
widget->border = rofi_theme_get_padding ( widget, "border", widget->border);
|
||||||
|
|
||||||
|
widget_queue_redraw ( widget );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int widget_intersect ( const widget *widget, int x, int y )
|
int widget_intersect ( const widget *widget, int x, int y )
|
||||||
{
|
{
|
||||||
|
@ -20,12 +45,16 @@ void widget_resize ( widget *widget, short w, short h )
|
||||||
{
|
{
|
||||||
if ( widget != NULL ) {
|
if ( widget != NULL ) {
|
||||||
if ( widget->resize != NULL ) {
|
if ( widget->resize != NULL ) {
|
||||||
|
if ( widget->w != w || widget->h != h ) {
|
||||||
widget->resize ( widget, w, h );
|
widget->resize ( widget, w, h );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
widget->w = w;
|
widget->w = w;
|
||||||
widget->h = h;
|
widget->h = h;
|
||||||
}
|
}
|
||||||
|
// On a resize we always want to udpate.
|
||||||
|
widget_queue_redraw ( widget );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void widget_move ( widget *widget, short x, short y )
|
void widget_move ( widget *widget, short x, short y )
|
||||||
|
@ -49,6 +78,7 @@ void widget_enable ( widget *widget )
|
||||||
if ( widget && !widget->enabled ) {
|
if ( widget && !widget->enabled ) {
|
||||||
widget->enabled = TRUE;
|
widget->enabled = TRUE;
|
||||||
widget_update ( widget );
|
widget_update ( widget );
|
||||||
|
widget_update ( widget->parent );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void widget_disable ( widget *widget )
|
void widget_disable ( widget *widget )
|
||||||
|
@ -56,21 +86,92 @@ void widget_disable ( widget *widget )
|
||||||
if ( widget && widget->enabled ) {
|
if ( widget && widget->enabled ) {
|
||||||
widget->enabled = FALSE;
|
widget->enabled = FALSE;
|
||||||
widget_update ( widget );
|
widget_update ( widget );
|
||||||
|
widget_update ( widget->parent );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void widget_draw ( widget *widget, cairo_t *d )
|
void widget_draw ( widget *widget, cairo_t *d )
|
||||||
{
|
{
|
||||||
// Check if enabled and if draw is implemented.
|
// Check if enabled and if draw is implemented.
|
||||||
if ( widget && widget->enabled && widget->draw ) {
|
if ( widget && widget->enabled && widget->draw ) {
|
||||||
|
// Don't draw if there is no space.
|
||||||
|
if ( widget->h < 1 || widget->w < 1 ){
|
||||||
|
widget->need_redraw = FALSE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Store current state.
|
||||||
|
cairo_save ( d );
|
||||||
|
int margin_left = distance_get_pixel ( widget->margin.left, ORIENTATION_HORIZONTAL);
|
||||||
|
int margin_top = distance_get_pixel ( widget->margin.top, ORIENTATION_VERTICAL);
|
||||||
|
int margin_right = distance_get_pixel ( widget->margin.right, ORIENTATION_HORIZONTAL);
|
||||||
|
int margin_bottom = distance_get_pixel ( widget->margin.bottom, ORIENTATION_VERTICAL);
|
||||||
|
// Define a clipmask so we won't draw outside out widget.
|
||||||
|
cairo_rectangle ( d,
|
||||||
|
widget->x+margin_left,
|
||||||
|
widget->y+margin_top,
|
||||||
|
widget->w-margin_right-margin_left,
|
||||||
|
widget->h-margin_top-margin_bottom
|
||||||
|
);
|
||||||
|
cairo_clip ( d );
|
||||||
|
|
||||||
|
rofi_theme_get_color ( widget, "background", d );
|
||||||
|
cairo_paint( d ) ;
|
||||||
|
|
||||||
|
// Set new x/y possition.
|
||||||
|
cairo_translate ( d, widget->x, widget->y);
|
||||||
|
|
||||||
|
int left = distance_get_pixel ( widget->border.left, ORIENTATION_HORIZONTAL );
|
||||||
|
int right = distance_get_pixel ( widget->border.right, ORIENTATION_HORIZONTAL);
|
||||||
|
int top = distance_get_pixel ( widget->border.top, ORIENTATION_VERTICAL);
|
||||||
|
int bottom = distance_get_pixel ( widget->border.bottom, ORIENTATION_VERTICAL );
|
||||||
|
if ( left || top || right || bottom ) {
|
||||||
|
cairo_save ( d );
|
||||||
|
rofi_theme_get_color ( widget, "foreground", d );
|
||||||
|
if ( left > 0 ) {
|
||||||
|
cairo_set_line_width ( d, left );
|
||||||
|
distance_get_linestyle ( widget->border.left, d);
|
||||||
|
cairo_move_to ( d, margin_left + left/2.0, margin_top );
|
||||||
|
cairo_line_to ( d, margin_left + left/2.0, widget->h-margin_bottom);
|
||||||
|
cairo_stroke ( d );
|
||||||
|
}
|
||||||
|
if ( right > 0 ) {
|
||||||
|
cairo_set_line_width ( d, right );
|
||||||
|
distance_get_linestyle ( widget->border.right, d);
|
||||||
|
cairo_move_to ( d, widget->w - margin_right - right/2.0, 0 );
|
||||||
|
cairo_line_to ( d, widget->w - margin_right - right/2.0, widget->h-margin_bottom );
|
||||||
|
cairo_stroke ( d );
|
||||||
|
}
|
||||||
|
if ( top > 0 ) {
|
||||||
|
cairo_set_line_width ( d, top );
|
||||||
|
distance_get_linestyle ( widget->border.top, d);
|
||||||
|
cairo_move_to ( d, margin_left,margin_top+ top/2.0 );
|
||||||
|
cairo_line_to ( d, widget->w-margin_right, margin_top+top/2.0 );
|
||||||
|
cairo_stroke ( d );
|
||||||
|
}
|
||||||
|
if ( bottom > 0 ) {
|
||||||
|
cairo_set_line_width ( d, bottom );
|
||||||
|
distance_get_linestyle ( widget->border.bottom, d);
|
||||||
|
cairo_move_to ( d, margin_left, widget->h-bottom/2.0-margin_bottom);
|
||||||
|
cairo_line_to ( d, widget->w-margin_right, widget->h-bottom/2.0-margin_bottom);
|
||||||
|
cairo_stroke ( d );
|
||||||
|
}
|
||||||
|
cairo_restore (d);
|
||||||
|
}
|
||||||
widget->draw ( widget, d );
|
widget->draw ( widget, d );
|
||||||
widget->need_redraw = FALSE;
|
widget->need_redraw = FALSE;
|
||||||
|
|
||||||
|
cairo_restore ( d );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void widget_free ( widget *wid )
|
void widget_free ( widget *wid )
|
||||||
{
|
{
|
||||||
if ( wid && wid->free ) {
|
if ( wid ) {
|
||||||
|
if ( wid->name ) {
|
||||||
|
g_free ( wid->name );
|
||||||
|
}
|
||||||
|
if ( wid->free ) {
|
||||||
wid->free ( wid );
|
wid->free ( wid );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int widget_get_height ( widget *widget )
|
int widget_get_height ( widget *widget )
|
||||||
|
@ -115,8 +216,6 @@ void widget_update ( widget *widget )
|
||||||
if ( widget->update ) {
|
if ( widget->update ) {
|
||||||
widget->update ( widget );
|
widget->update ( widget );
|
||||||
}
|
}
|
||||||
// Recurse back.
|
|
||||||
widget_update ( widget->parent );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,3 +262,79 @@ gboolean widget_motion_notify ( widget *wid, xcb_motion_notify_event_t *xme )
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void widget_set_name ( widget *wid, const char *name )
|
||||||
|
{
|
||||||
|
if ( wid->name ) {
|
||||||
|
g_free(wid);
|
||||||
|
}
|
||||||
|
wid->name = g_strdup ( name );
|
||||||
|
}
|
||||||
|
|
||||||
|
int widget_padding_get_left ( const widget *wid )
|
||||||
|
{
|
||||||
|
int distance = distance_get_pixel ( wid->padding.left, ORIENTATION_HORIZONTAL );
|
||||||
|
distance += distance_get_pixel ( wid->border.left, ORIENTATION_HORIZONTAL );
|
||||||
|
distance += distance_get_pixel ( wid->margin.left, ORIENTATION_HORIZONTAL );
|
||||||
|
return distance;
|
||||||
|
}
|
||||||
|
int widget_padding_get_right ( const widget *wid )
|
||||||
|
{
|
||||||
|
int distance = distance_get_pixel ( wid->padding.right, ORIENTATION_HORIZONTAL );
|
||||||
|
distance += distance_get_pixel ( wid->border.right, ORIENTATION_HORIZONTAL );
|
||||||
|
distance += distance_get_pixel ( wid->margin.right, ORIENTATION_HORIZONTAL );
|
||||||
|
return distance;
|
||||||
|
}
|
||||||
|
int widget_padding_get_top ( const widget *wid )
|
||||||
|
{
|
||||||
|
int distance = distance_get_pixel ( wid->padding.top, ORIENTATION_VERTICAL );
|
||||||
|
distance += distance_get_pixel ( wid->border.top, ORIENTATION_VERTICAL );
|
||||||
|
distance += distance_get_pixel ( wid->margin.top, ORIENTATION_VERTICAL );
|
||||||
|
return distance;
|
||||||
|
}
|
||||||
|
int widget_padding_get_bottom ( const widget *wid )
|
||||||
|
{
|
||||||
|
int distance = distance_get_pixel ( wid->padding.bottom, ORIENTATION_VERTICAL );
|
||||||
|
distance += distance_get_pixel ( wid->border.bottom, ORIENTATION_VERTICAL );
|
||||||
|
distance += distance_get_pixel ( wid->margin.bottom, ORIENTATION_VERTICAL );
|
||||||
|
return distance;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int widget_get_desired_height ( widget *wid )
|
||||||
|
{
|
||||||
|
if ( wid && wid->get_desired_height )
|
||||||
|
{
|
||||||
|
return wid->get_desired_height ( wid );
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -194,6 +194,8 @@ static XrmOption xrmOptions[] = {
|
||||||
"Click outside the window to exit", CONFIG_DEFAULT },
|
"Click outside the window to exit", CONFIG_DEFAULT },
|
||||||
{ xrm_Boolean, "show-match", { .snum = &config.show_match }, NULL,
|
{ xrm_Boolean, "show-match", { .snum = &config.show_match }, NULL,
|
||||||
"Indicate how it match by underlining it.", CONFIG_DEFAULT },
|
"Indicate how it match by underlining it.", CONFIG_DEFAULT },
|
||||||
|
{ xrm_String, "theme", { .str = &config.theme }, NULL,
|
||||||
|
"New style theme file", CONFIG_DEFAULT },
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Dynamic array of extra options */
|
/** Dynamic array of extra options */
|
||||||
|
|
|
@ -22,6 +22,16 @@ unsigned int test =0;
|
||||||
abort ( ); \
|
abort ( ); \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
int textbox_get_estimated_char_height ( void );
|
||||||
|
int textbox_get_estimated_char_height ( void )
|
||||||
|
{
|
||||||
|
return 16;
|
||||||
|
}
|
||||||
|
void rofi_view_get_current_monitor ( int *width, int *height )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static gboolean test_widget_clicked ( G_GNUC_UNUSED widget *wid, G_GNUC_UNUSED xcb_button_press_event_t* xce, G_GNUC_UNUSED void *data )
|
static gboolean test_widget_clicked ( G_GNUC_UNUSED widget *wid, G_GNUC_UNUSED xcb_button_press_event_t* xce, G_GNUC_UNUSED void *data )
|
||||||
{
|
{
|
||||||
|
@ -31,11 +41,12 @@ static gboolean test_widget_clicked ( G_GNUC_UNUSED widget *wid, G_GNUC_UNUSED x
|
||||||
int main ( G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv )
|
int main ( G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv )
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
box *b = box_create ( BOX_HORIZONTAL, 0, 0, 100, 20 );
|
box *b = box_create ( "box", BOX_HORIZONTAL );
|
||||||
box_set_padding ( b, 5 );
|
//box_set_padding ( b, 5 );
|
||||||
|
widget_resize ( WIDGET (b), 100, 20);
|
||||||
|
|
||||||
widget *wid1 = g_malloc0(sizeof(widget));
|
widget *wid1 = g_malloc0(sizeof(widget));
|
||||||
box_add ( b , WIDGET( wid1 ), TRUE, FALSE );
|
box_add ( b , WIDGET( wid1 ), TRUE, 0 );
|
||||||
// Widget not enabled. no width allocated.
|
// Widget not enabled. no width allocated.
|
||||||
TASSERTE ( wid1->h, 0);
|
TASSERTE ( wid1->h, 0);
|
||||||
TASSERTE ( wid1->w, 0 );
|
TASSERTE ( wid1->w, 0 );
|
||||||
|
@ -46,57 +57,58 @@ int main ( G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv )
|
||||||
TASSERTE ( wid1->w, 100 );
|
TASSERTE ( wid1->w, 100 );
|
||||||
widget *wid2 = g_malloc0(sizeof(widget));
|
widget *wid2 = g_malloc0(sizeof(widget));
|
||||||
widget_enable ( WIDGET ( wid2 ) );
|
widget_enable ( WIDGET ( wid2 ) );
|
||||||
box_add ( b , WIDGET( wid2 ), TRUE, FALSE );
|
box_add ( b , WIDGET( wid2 ), TRUE, 1 );
|
||||||
TASSERTE ( wid1->h, 20);
|
TASSERTE ( wid1->h, 20);
|
||||||
TASSERTE ( wid1->w, 47);
|
TASSERTE ( wid1->w, 49);
|
||||||
TASSERTE ( wid2->h, 20);
|
TASSERTE ( wid2->h, 20);
|
||||||
TASSERTE ( wid2->w, 48);
|
TASSERTE ( wid2->w, 49);
|
||||||
|
|
||||||
widget *wid3 = g_malloc0(sizeof(widget));
|
widget *wid3 = g_malloc0(sizeof(widget));
|
||||||
widget_enable ( WIDGET ( wid3 ) );
|
widget_enable ( WIDGET ( wid3 ) );
|
||||||
box_add ( b , WIDGET( wid3 ), FALSE, FALSE );
|
box_add ( b , WIDGET( wid3 ), FALSE, 2 );
|
||||||
TASSERTE ( wid1->h, 20);
|
TASSERTE ( wid1->h, 20);
|
||||||
TASSERTE ( wid1->w, 45);
|
TASSERTE ( wid1->w, 48);
|
||||||
TASSERTE ( wid2->h, 20);
|
TASSERTE ( wid2->h, 20);
|
||||||
TASSERTE ( wid2->w, 45);
|
TASSERTE ( wid2->w, 48);
|
||||||
|
|
||||||
widget_resize ( WIDGET (wid3) , 20, 10 );
|
widget_resize ( WIDGET (wid3) , 20, 10 );
|
||||||
// TODO should this happen automagically?
|
// TODO should this happen automagically?
|
||||||
widget_update ( WIDGET ( b ) ) ;
|
widget_update ( WIDGET ( b ) ) ;
|
||||||
TASSERTE ( wid1->h, 20);
|
TASSERTE ( wid1->h, 20);
|
||||||
TASSERTE ( wid1->w, 35);
|
TASSERTE ( wid1->w, 38);
|
||||||
TASSERTE ( wid2->h, 20);
|
TASSERTE ( wid2->h, 20);
|
||||||
TASSERTE ( wid2->w, 35);
|
TASSERTE ( wid2->w, 38);
|
||||||
TASSERTE ( wid3->h, 20);
|
TASSERTE ( wid3->h, 20);
|
||||||
TASSERTE ( wid3->w, 20);
|
TASSERTE ( wid3->w, 20);
|
||||||
|
|
||||||
widget_resize ( WIDGET (b ), 200, 20 );
|
widget_resize ( WIDGET (b ), 200, 20 );
|
||||||
TASSERTE ( wid1->h, 20);
|
TASSERTE ( wid1->h, 20);
|
||||||
TASSERTE ( wid1->w, 85);
|
TASSERTE ( wid1->w, 88);
|
||||||
TASSERTE ( wid2->h, 20);
|
TASSERTE ( wid2->h, 20);
|
||||||
TASSERTE ( wid2->w, 85);
|
TASSERTE ( wid2->w, 88);
|
||||||
TASSERTE ( wid3->h, 20);
|
TASSERTE ( wid3->h, 20);
|
||||||
TASSERTE ( wid3->w, 20);
|
TASSERTE ( wid3->w, 20);
|
||||||
TASSERTE ( box_get_fixed_pixels ( b ) , 30 );
|
TASSERTE ( box_get_fixed_pixels ( b ) , 24 );
|
||||||
|
|
||||||
widget *wid4 = g_malloc0(sizeof(widget));
|
widget *wid4 = g_malloc0(sizeof(widget));
|
||||||
widget_enable ( WIDGET ( wid4 ) );
|
widget_enable ( WIDGET ( wid4 ) );
|
||||||
widget_resize ( WIDGET ( wid4 ), 20, 20 );
|
widget_resize ( WIDGET ( wid4 ), 20, 20 );
|
||||||
box_add ( b , WIDGET( wid4 ), FALSE, TRUE );
|
box_add ( b , WIDGET( wid4 ), FALSE, 5 );
|
||||||
TASSERTE ( wid4->x, 200-20);
|
TASSERTE ( wid4->x, 200-20);
|
||||||
widget *wid5 = g_malloc0(sizeof(widget));
|
widget *wid5 = g_malloc0(sizeof(widget));
|
||||||
widget_enable ( WIDGET ( wid5 ) );
|
widget_enable ( WIDGET ( wid5 ) );
|
||||||
widget_resize ( WIDGET ( wid5 ), 20, 20 );
|
widget_resize ( WIDGET ( wid5 ), 20, 20 );
|
||||||
box_add ( b , WIDGET( wid5 ), TRUE, TRUE );
|
box_add ( b , WIDGET( wid5 ), TRUE, 6 );
|
||||||
TASSERTE ( wid5->x, 128);
|
TASSERTE ( wid5->x, 149);
|
||||||
widget_free ( WIDGET ( b ) );
|
widget_free ( WIDGET ( b ) );
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
box *b = box_create ( BOX_VERTICAL, 0, 0, 20, 100 );
|
box *b = box_create ( "box", BOX_VERTICAL );
|
||||||
box_set_padding ( b, 5 );
|
widget_resize ( WIDGET (b), 20, 100);
|
||||||
|
//box_set_padding ( b, 5 );
|
||||||
|
|
||||||
widget *wid1 = g_malloc0(sizeof(widget));
|
widget *wid1 = g_malloc0(sizeof(widget));
|
||||||
box_add ( b , WIDGET( wid1 ), TRUE, FALSE );
|
box_add ( b , WIDGET( wid1 ), TRUE, 0 );
|
||||||
// Widget not enabled. no width allocated.
|
// Widget not enabled. no width allocated.
|
||||||
TASSERTE ( wid1->h, 0);
|
TASSERTE ( wid1->h, 0);
|
||||||
TASSERTE ( wid1->w, 0 );
|
TASSERTE ( wid1->w, 0 );
|
||||||
|
@ -107,60 +119,62 @@ int main ( G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv )
|
||||||
TASSERTE ( wid1->w, 20 );
|
TASSERTE ( wid1->w, 20 );
|
||||||
widget *wid2 = g_malloc0(sizeof(widget));
|
widget *wid2 = g_malloc0(sizeof(widget));
|
||||||
widget_enable ( WIDGET ( wid2 ) );
|
widget_enable ( WIDGET ( wid2 ) );
|
||||||
box_add ( b , WIDGET( wid2 ), TRUE, FALSE );
|
box_add ( b , WIDGET( wid2 ), TRUE, 1 );
|
||||||
TASSERTE ( wid1->w, 20);
|
TASSERTE ( wid1->w, 20);
|
||||||
TASSERTE ( wid1->h, 47);
|
TASSERTE ( wid1->h, 49);
|
||||||
TASSERTE ( wid2->w, 20);
|
TASSERTE ( wid2->w, 20);
|
||||||
TASSERTE ( wid2->h, 48);
|
TASSERTE ( wid2->h, 49);
|
||||||
|
|
||||||
widget *wid3 = g_malloc0(sizeof(widget));
|
widget *wid3 = g_malloc0(sizeof(widget));
|
||||||
widget_enable ( WIDGET ( wid3 ) );
|
widget_enable ( WIDGET ( wid3 ) );
|
||||||
box_add ( b , WIDGET( wid3 ), FALSE, FALSE );
|
box_add ( b , WIDGET( wid3 ), FALSE, 2 );
|
||||||
TASSERTE ( wid1->w, 20);
|
TASSERTE ( wid1->w, 20);
|
||||||
TASSERTE ( wid1->h, 45);
|
TASSERTE ( wid1->h, 48);
|
||||||
TASSERTE ( wid2->w, 20);
|
TASSERTE ( wid2->w, 20);
|
||||||
TASSERTE ( wid2->h, 45);
|
TASSERTE ( wid2->h, 48);
|
||||||
|
|
||||||
widget_resize ( WIDGET (wid3) , 10, 20 );
|
widget_resize ( WIDGET (wid3) , 10, 20 );
|
||||||
// TODO should this happen automagically?
|
// TODO should this happen automagically?
|
||||||
widget_update ( WIDGET ( b ) ) ;
|
widget_update ( WIDGET ( b ) ) ;
|
||||||
TASSERTE ( wid1->w, 20);
|
TASSERTE ( wid1->w, 20);
|
||||||
TASSERTE ( wid1->h, 35);
|
TASSERTE ( wid1->h, 48);
|
||||||
TASSERTE ( wid2->w, 20);
|
TASSERTE ( wid2->w, 20);
|
||||||
TASSERTE ( wid2->h, 35);
|
TASSERTE ( wid2->h, 48);
|
||||||
TASSERTE ( wid3->w, 20);
|
TASSERTE ( wid3->w, 20);
|
||||||
TASSERTE ( wid3->h, 20);
|
TASSERTE ( wid3->h, 0);
|
||||||
|
|
||||||
widget_resize ( WIDGET (b ), 20, 200 );
|
widget_resize ( WIDGET (b ), 20, 200 );
|
||||||
TASSERTE ( wid1->w, 20);
|
TASSERTE ( wid1->w, 20);
|
||||||
TASSERTE ( wid1->h, 85);
|
TASSERTE ( wid1->h, 98);
|
||||||
TASSERTE ( wid2->w, 20);
|
TASSERTE ( wid2->w, 20);
|
||||||
TASSERTE ( wid2->h, 85);
|
TASSERTE ( wid2->h, 98);
|
||||||
TASSERTE ( wid3->w, 20);
|
TASSERTE ( wid3->w, 20);
|
||||||
TASSERTE ( wid3->h, 20);
|
// has no height, gets no height.
|
||||||
TASSERTE ( box_get_fixed_pixels ( b ) , 30 );
|
TASSERTE ( wid3->h, 0);
|
||||||
|
TASSERTE ( box_get_fixed_pixels ( b ) , 4 );
|
||||||
widget *wid4 = g_malloc0(sizeof(widget));
|
widget *wid4 = g_malloc0(sizeof(widget));
|
||||||
widget_enable ( WIDGET ( wid4 ) );
|
widget_enable ( WIDGET ( wid4 ) );
|
||||||
widget_resize ( WIDGET ( wid4 ), 20, 20 );
|
widget_resize ( WIDGET ( wid4 ), 20, 20 );
|
||||||
box_add ( b , WIDGET( wid4 ), FALSE, TRUE );
|
box_add ( b , WIDGET( wid4 ), FALSE, 5 );
|
||||||
TASSERTE ( wid4->y, 200-20);
|
TASSERTE ( wid4->y, 200);
|
||||||
widget *wid5 = g_malloc0(sizeof(widget));
|
widget *wid5 = g_malloc0(sizeof(widget));
|
||||||
widget_enable ( WIDGET ( wid5 ) );
|
widget_enable ( WIDGET ( wid5 ) );
|
||||||
widget_resize ( WIDGET ( wid5 ), 20, 20 );
|
widget_resize ( WIDGET ( wid5 ), 20, 20 );
|
||||||
box_add ( b , WIDGET( wid5 ), TRUE, TRUE );
|
box_add ( b , WIDGET( wid5 ), TRUE, 6 );
|
||||||
TASSERTE ( wid5->y, 128);
|
TASSERTE ( wid5->y, 136);
|
||||||
widget_free ( WIDGET ( b ) );
|
widget_free ( WIDGET ( b ) );
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
box *b = box_create ( BOX_VERTICAL, 0, 0, 20, 100 );
|
box *b = box_create ( "box", BOX_VERTICAL );
|
||||||
box_set_padding ( b, 5 );
|
widget_resize ( WIDGET (b), 20, 100);
|
||||||
|
//box_set_padding ( b, 5 );
|
||||||
widget *wid1 = g_malloc0(sizeof(widget));
|
widget *wid1 = g_malloc0(sizeof(widget));
|
||||||
widget_enable(wid1);
|
widget_enable(wid1);
|
||||||
wid1->clicked = test_widget_clicked;
|
wid1->clicked = test_widget_clicked;
|
||||||
box_add ( b , WIDGET( wid1 ), TRUE, FALSE );
|
box_add ( b , WIDGET( wid1 ), TRUE, 0 );
|
||||||
widget *wid2 = g_malloc0(sizeof(widget));
|
widget *wid2 = g_malloc0(sizeof(widget));
|
||||||
widget_enable(wid2);
|
widget_enable(wid2);
|
||||||
box_add ( b , WIDGET( wid2 ), TRUE, FALSE );
|
box_add ( b , WIDGET( wid2 ), TRUE, 1 );
|
||||||
|
|
||||||
xcb_button_press_event_t xce;
|
xcb_button_press_event_t xce;
|
||||||
xce.event_x = 10;
|
xce.event_x = 10;
|
||||||
|
@ -169,7 +183,7 @@ int main ( G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv )
|
||||||
|
|
||||||
xce.event_y = 50;
|
xce.event_y = 50;
|
||||||
TASSERTE ( widget_clicked ( WIDGET(b), &xce ), 0);
|
TASSERTE ( widget_clicked ( WIDGET(b), &xce ), 0);
|
||||||
xce.event_y = 45;
|
xce.event_y = 48;
|
||||||
TASSERTE ( widget_clicked ( WIDGET(b), &xce ), 1);
|
TASSERTE ( widget_clicked ( WIDGET(b), &xce ), 1);
|
||||||
widget_disable ( wid2 );
|
widget_disable ( wid2 );
|
||||||
xce.event_y = 60;
|
xce.event_y = 60;
|
||||||
|
|
|
@ -23,14 +23,25 @@ unsigned int test =0;
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int textbox_get_estimated_char_height ( void );
|
||||||
|
int textbox_get_estimated_char_height ( void )
|
||||||
|
{
|
||||||
|
return 16;
|
||||||
|
}
|
||||||
void color_separator ( G_GNUC_UNUSED void *d )
|
void color_separator ( G_GNUC_UNUSED void *d )
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void rofi_view_get_current_monitor ( int *width, int *height )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
int main ( G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv )
|
int main ( G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv )
|
||||||
{
|
{
|
||||||
scrollbar * sb = scrollbar_create ( 0, 0, 10, 100);
|
scrollbar * sb = scrollbar_create ( "scrollbar" );
|
||||||
|
widget_resize ( WIDGET (sb), 10, 100);
|
||||||
|
|
||||||
scrollbar_set_handle ( NULL, 10213);
|
scrollbar_set_handle ( NULL, 10213);
|
||||||
scrollbar_set_max_value ( NULL, 10 );
|
scrollbar_set_max_value ( NULL, 10 );
|
||||||
|
|
|
@ -24,12 +24,10 @@ unsigned int normal_window_mode = 0;
|
||||||
void rofi_view_queue_redraw ()
|
void rofi_view_queue_redraw ()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
Color color_get ( G_GNUC_UNUSED const char *name )
|
void rofi_view_get_current_monitor ( int *width, int *height )
|
||||||
{
|
{
|
||||||
Color retv = { 1.0, 1.0, 1.0, 1.0 };
|
|
||||||
return retv;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
}
|
||||||
int rofi_view_error_dialog ( const char *msg, G_GNUC_UNUSED int markup )
|
int rofi_view_error_dialog ( const char *msg, G_GNUC_UNUSED int markup )
|
||||||
{
|
{
|
||||||
fputs ( msg, stderr );
|
fputs ( msg, stderr );
|
||||||
|
@ -53,8 +51,7 @@ int main ( G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv )
|
||||||
PangoContext *p = pango_cairo_create_context ( draw );
|
PangoContext *p = pango_cairo_create_context ( draw );
|
||||||
textbox_set_pango_context ( p );
|
textbox_set_pango_context ( p );
|
||||||
|
|
||||||
textbox *box = textbox_create ( TB_EDITABLE | TB_AUTOWIDTH | TB_AUTOHEIGHT, 0, 0, -1, -1,
|
textbox *box = textbox_create ( "textbox", TB_EDITABLE | TB_AUTOWIDTH | TB_AUTOHEIGHT, NORMAL, "test" );
|
||||||
NORMAL, "test" );
|
|
||||||
TASSERT ( box != NULL );
|
TASSERT ( box != NULL );
|
||||||
|
|
||||||
textbox_keybinding ( box, MOVE_END );
|
textbox_keybinding ( box, MOVE_END );
|
||||||
|
|
|
@ -12,7 +12,19 @@ unsigned int test =0;
|
||||||
assert ( a ); \
|
assert ( a ); \
|
||||||
printf ( "Test %3i passed (%s)\n", ++test, # a ); \
|
printf ( "Test %3i passed (%s)\n", ++test, # a ); \
|
||||||
}
|
}
|
||||||
|
void rofi_view_queue_redraw ( void )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
void rofi_view_get_current_monitor ( int *width, int *height )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
int rofi_view_error_dialog ( const char *msg, G_GNUC_UNUSED int markup )
|
||||||
|
{
|
||||||
|
fputs ( msg, stderr );
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
int main ( G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv )
|
int main ( G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv )
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,11 +4,11 @@
|
||||||
! Copyright: Dave Davenport
|
! Copyright: Dave Davenport
|
||||||
! ------------------------------------------------------------------------------
|
! ------------------------------------------------------------------------------
|
||||||
! "Color scheme for normal row" Set from: File
|
! "Color scheme for normal row" Set from: File
|
||||||
rofi.color-normal: argb:0000000, #dbdfbc, argb:00000000, #dbdfbc, #02143f
|
rofi.color-normal: argb:00000000, #dbdfbc, argb:00000000, #dbdfbc, #02143f
|
||||||
! "Color scheme for urgent row" Set from: File
|
! "Color scheme for urgent row" Set from: File
|
||||||
rofi.color-urgent: argb:0000000, #ff81ff, argb:00000000, #ff817f, #02143f
|
rofi.color-urgent: argb:00000000, #ff81ff, argb:00000000, #ff817f, #02143f
|
||||||
! "Color scheme for active row" Set from: File
|
! "Color scheme for active row" Set from: File
|
||||||
rofi.color-active: argb:0000000, #8ac4ff, argb:00000000, #8ac4ff, #02143f
|
rofi.color-active: argb:00000000, #8ac4ff, argb:00000000, #8ac4ff, #02143f
|
||||||
! "Color scheme window" Set from: File
|
! "Color scheme window" Set from: File
|
||||||
rofi.color-window: argb:dd000021, #dbdfbc, #dbdfbc
|
rofi.color-window: argb:dd000021, #dbdfbc, #dbdfbc
|
||||||
! "Separator style (none, dash, solid)" Set from: XResources
|
! "Separator style (none, dash, solid)" Set from: XResources
|
||||||
|
|
Loading…
Reference in a new issue