mirror of
https://github.com/lbonn/rofi
synced 2024-11-10 06:14:14 +00:00
Add cursor property (#1313)
* Change mouse cursor on widget hover Currently only listview element and editbox are supported. * Add cursor property
This commit is contained in:
parent
04c006a4a2
commit
dc28a97437
19 changed files with 284 additions and 9 deletions
|
@ -35,6 +35,7 @@ addons:
|
||||||
- libxcb-xinerama0-dev
|
- libxcb-xinerama0-dev
|
||||||
- libxcb-xkb-dev
|
- libxcb-xkb-dev
|
||||||
- libxcb-xrm-dev
|
- libxcb-xrm-dev
|
||||||
|
- libxcb-cursor-dev
|
||||||
- libxkbcommon-dev
|
- libxkbcommon-dev
|
||||||
- libxkbcommon-dev
|
- libxkbcommon-dev
|
||||||
- libxkbcommon-x11-dev
|
- libxkbcommon-x11-dev
|
||||||
|
|
|
@ -40,6 +40,7 @@ You can also use [Meson](https://mesonbuild.com/) as an alternative.
|
||||||
* xcb-util-wm (sometimes split as libxcb-ewmh and libxcb-icccm)
|
* xcb-util-wm (sometimes split as libxcb-ewmh and libxcb-icccm)
|
||||||
* xcb-util-xrm [new module might not be available in your distribution. The source can be found
|
* xcb-util-xrm [new module might not be available in your distribution. The source can be found
|
||||||
here](https://github.com/Airblader/xcb-util-xrm/)
|
here](https://github.com/Airblader/xcb-util-xrm/)
|
||||||
|
* xcb-util-cursor
|
||||||
|
|
||||||
On debian based systems, the developer packages are in the form of: `<package>-dev` on rpm based
|
On debian based systems, the developer packages are in the form of: `<package>-dev` on rpm based
|
||||||
`<package>-devel`.
|
`<package>-devel`.
|
||||||
|
|
|
@ -144,7 +144,7 @@ NK_INIT([bindings xdg-theme])
|
||||||
PKG_CHECK_MODULES([glib], [glib-2.0 >= ${glib_min_version} gio-unix-2.0 gmodule-2.0])
|
PKG_CHECK_MODULES([glib], [glib-2.0 >= ${glib_min_version} gio-unix-2.0 gmodule-2.0])
|
||||||
AC_DEFINE_UNQUOTED([GLIB_VERSION_MIN_REQUIRED], [(G_ENCODE_VERSION(${glib_min_major},${glib_min_minor}))], [The lower GLib version supported])
|
AC_DEFINE_UNQUOTED([GLIB_VERSION_MIN_REQUIRED], [(G_ENCODE_VERSION(${glib_min_major},${glib_min_minor}))], [The lower GLib version supported])
|
||||||
AC_DEFINE_UNQUOTED([GLIB_VERSION_MAX_ALLOWED], [(G_ENCODE_VERSION(${glib_min_major},${glib_min_minor}))], [The highest GLib version supported])
|
AC_DEFINE_UNQUOTED([GLIB_VERSION_MAX_ALLOWED], [(G_ENCODE_VERSION(${glib_min_major},${glib_min_minor}))], [The highest GLib version supported])
|
||||||
GW_CHECK_XCB([xcb-aux xcb-xkb xkbcommon xkbcommon-x11 xcb-ewmh xcb-icccm xcb-xrm xcb-randr xcb-xinerama])
|
GW_CHECK_XCB([xcb-aux xcb-xkb xkbcommon xkbcommon-x11 xcb-ewmh xcb-icccm xcb-xrm xcb-cursor xcb-randr xcb-xinerama])
|
||||||
PKG_CHECK_MODULES([pango], [pango pangocairo])
|
PKG_CHECK_MODULES([pango], [pango pangocairo])
|
||||||
PKG_CHECK_MODULES([cairo], [cairo cairo-xcb])
|
PKG_CHECK_MODULES([cairo], [cairo cairo-xcb])
|
||||||
PKG_CHECK_MODULES([libsn], [libstartup-notification-1.0 ])
|
PKG_CHECK_MODULES([libsn], [libstartup-notification-1.0 ])
|
||||||
|
|
|
@ -35,6 +35,7 @@ element {
|
||||||
padding: 1px ;
|
padding: 1px ;
|
||||||
spacing: 5px ;
|
spacing: 5px ;
|
||||||
border: 0;
|
border: 0;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
element normal.normal {
|
element normal.normal {
|
||||||
background-color: var(normal-background);
|
background-color: var(normal-background);
|
||||||
|
@ -76,11 +77,13 @@ element-text {
|
||||||
background-color: rgba ( 0, 0, 0, 0 % );
|
background-color: rgba ( 0, 0, 0, 0 % );
|
||||||
text-color: inherit;
|
text-color: inherit;
|
||||||
highlight: inherit;
|
highlight: inherit;
|
||||||
|
cursor: inherit;
|
||||||
}
|
}
|
||||||
element-icon {
|
element-icon {
|
||||||
background-color: rgba ( 0, 0, 0, 0 % );
|
background-color: rgba ( 0, 0, 0, 0 % );
|
||||||
size: 1.0000em ;
|
size: 1.0000em ;
|
||||||
text-color: inherit;
|
text-color: inherit;
|
||||||
|
cursor: inherit;
|
||||||
}
|
}
|
||||||
window {
|
window {
|
||||||
padding: 5;
|
padding: 5;
|
||||||
|
@ -121,6 +124,7 @@ sidebar {
|
||||||
button {
|
button {
|
||||||
spacing: 0;
|
spacing: 0;
|
||||||
text-color: var(normal-foreground);
|
text-color: var(normal-foreground);
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
button selected {
|
button selected {
|
||||||
background-color: var(selected-normal-background);
|
background-color: var(selected-normal-background);
|
||||||
|
@ -151,6 +155,7 @@ entry {
|
||||||
text-color: var(normal-foreground);
|
text-color: var(normal-foreground);
|
||||||
placeholder-color: grey;
|
placeholder-color: grey;
|
||||||
placeholder: "Type to filter";
|
placeholder: "Type to filter";
|
||||||
|
cursor: text;
|
||||||
}
|
}
|
||||||
prompt {
|
prompt {
|
||||||
spacing: 0;
|
spacing: 0;
|
||||||
|
|
|
@ -275,6 +275,8 @@ a reference
|
||||||
.IP \(bu 2
|
.IP \(bu 2
|
||||||
an orientation
|
an orientation
|
||||||
.IP \(bu 2
|
.IP \(bu 2
|
||||||
|
a cursor
|
||||||
|
.IP \(bu 2
|
||||||
a list of keywords
|
a list of keywords
|
||||||
.IP \(bu 2
|
.IP \(bu 2
|
||||||
an environment variable
|
an environment variable
|
||||||
|
@ -754,6 +756,16 @@ Format: \fB\fC(horizontal|vertical)\fR
|
||||||
.PP
|
.PP
|
||||||
Specify the orientation of the widget.
|
Specify the orientation of the widget.
|
||||||
|
|
||||||
|
.SH Cursor
|
||||||
|
.RS
|
||||||
|
.IP \(bu 2
|
||||||
|
Format: \fB\fC(default|pointer|text)\fR
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.PP
|
||||||
|
Specify the type of mouse cursor that is set when the mouse pointer is over the widget.
|
||||||
|
|
||||||
.SH List of keywords
|
.SH List of keywords
|
||||||
.RS
|
.RS
|
||||||
.IP \(bu 2
|
.IP \(bu 2
|
||||||
|
@ -1012,6 +1024,9 @@ Background color
|
||||||
.IP \(bu 2
|
.IP \(bu 2
|
||||||
\fBborder\-color\fP: color
|
\fBborder\-color\fP: color
|
||||||
Color of the border
|
Color of the border
|
||||||
|
.IP \(bu 2
|
||||||
|
\fBcursor\fP: cursor
|
||||||
|
Type of mouse cursor that is set when the mouse pointer is hovered over the widget.
|
||||||
|
|
||||||
.RE
|
.RE
|
||||||
|
|
||||||
|
|
|
@ -189,6 +189,7 @@ The current theme format supports different types:
|
||||||
* a position
|
* a position
|
||||||
* a reference
|
* a reference
|
||||||
* an orientation
|
* an orientation
|
||||||
|
* a cursor
|
||||||
* a list of keywords
|
* a list of keywords
|
||||||
* an environment variable
|
* an environment variable
|
||||||
* Inherit
|
* Inherit
|
||||||
|
@ -462,6 +463,12 @@ window {
|
||||||
|
|
||||||
Specify the orientation of the widget.
|
Specify the orientation of the widget.
|
||||||
|
|
||||||
|
## Cursor
|
||||||
|
|
||||||
|
* Format: `(default|pointer|text)`
|
||||||
|
|
||||||
|
Specify the type of mouse cursor that is set when the mouse pointer is over the widget.
|
||||||
|
|
||||||
## List of keywords
|
## List of keywords
|
||||||
|
|
||||||
* Format: `[ keyword, keyword ]`
|
* Format: `[ keyword, keyword ]`
|
||||||
|
@ -620,6 +627,8 @@ The following properties are currently supported:
|
||||||
Background color
|
Background color
|
||||||
* **border-color**: color
|
* **border-color**: color
|
||||||
Color of the border
|
Color of the border
|
||||||
|
* **cursor**: cursor
|
||||||
|
Type of mouse cursor that is set when the mouse pointer is hovered over the widget.
|
||||||
|
|
||||||
### window:
|
### window:
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,8 @@ typedef enum
|
||||||
P_LIST,
|
P_LIST,
|
||||||
/** Orientation */
|
/** Orientation */
|
||||||
P_ORIENTATION,
|
P_ORIENTATION,
|
||||||
|
/** Cursor */
|
||||||
|
P_CURSOR,
|
||||||
/** Inherit */
|
/** Inherit */
|
||||||
P_INHERIT,
|
P_INHERIT,
|
||||||
/** Number of types. */
|
/** Number of types. */
|
||||||
|
@ -140,6 +142,16 @@ typedef enum
|
||||||
ROFI_ORIENTATION_HORIZONTAL
|
ROFI_ORIENTATION_HORIZONTAL
|
||||||
} RofiOrientation;
|
} RofiOrientation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cursor type.
|
||||||
|
*/
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
ROFI_CURSOR_DEFAULT,
|
||||||
|
ROFI_CURSOR_POINTER,
|
||||||
|
ROFI_CURSOR_TEXT
|
||||||
|
} RofiCursorType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represent the color in theme.
|
* Represent the color in theme.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -217,6 +217,17 @@ int rofi_theme_get_boolean ( const widget *widget, const char *property, int
|
||||||
* @returns The orientation of this property for this widget or %def not found.
|
* @returns The orientation of this property for this widget or %def not found.
|
||||||
*/
|
*/
|
||||||
RofiOrientation rofi_theme_get_orientation ( const widget *widget, const char *property, RofiOrientation def );
|
RofiOrientation rofi_theme_get_orientation ( const widget *widget, const char *property, RofiOrientation def );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param widget The widget to query
|
||||||
|
* @param property The property to query.
|
||||||
|
* @param def The default value.
|
||||||
|
*
|
||||||
|
* Obtain the cursor indicated by %property of the widget.
|
||||||
|
*
|
||||||
|
* @returns The cursor for this widget or %def if not found.
|
||||||
|
*/
|
||||||
|
RofiCursorType rofi_theme_get_cursor_type ( const widget *widget, const char *property, RofiCursorType def );
|
||||||
/**
|
/**
|
||||||
* @param widget The widget to query
|
* @param widget The widget to query
|
||||||
* @param property The property to query.
|
* @param property The property to query.
|
||||||
|
|
|
@ -54,6 +54,9 @@ struct _widget
|
||||||
RofiPadding border;
|
RofiPadding border;
|
||||||
RofiPadding border_radius;
|
RofiPadding border_radius;
|
||||||
|
|
||||||
|
/** Cursor that is set when the widget is hovered */
|
||||||
|
RofiCursorType cursor_type;
|
||||||
|
|
||||||
/** enabled or not */
|
/** enabled or not */
|
||||||
gboolean enabled;
|
gboolean enabled;
|
||||||
/** Expand the widget when packed */
|
/** Expand the widget when packed */
|
||||||
|
|
|
@ -175,6 +175,28 @@ cairo_surface_t *x11_helper_get_screenshot_surface ( void );
|
||||||
*/
|
*/
|
||||||
void x11_disable_decoration ( xcb_window_t window );
|
void x11_disable_decoration ( xcb_window_t window );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of cursor types.
|
||||||
|
*/
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
/** Default arrow cursor */
|
||||||
|
CURSOR_DEFAULT = 0,
|
||||||
|
/** Cursor denoting a clickable area */
|
||||||
|
CURSOR_POINTER,
|
||||||
|
/** Cursor denoting an input field / selectable text */
|
||||||
|
CURSOR_TEXT,
|
||||||
|
NUM_CURSORS
|
||||||
|
} X11CursorType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param window
|
||||||
|
* @param type
|
||||||
|
*
|
||||||
|
* Change mouse cursor
|
||||||
|
*/
|
||||||
|
void x11_set_cursor ( xcb_window_t window, X11CursorType type );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of window managers that need different behaviour to functioning.
|
* List of window managers that need different behaviour to functioning.
|
||||||
*/
|
*/
|
||||||
|
@ -212,4 +234,5 @@ cairo_surface_t *x11_helper_get_screenshot_surface_window ( xcb_window_t window,
|
||||||
* Blur the content of the surface with radius and deviation.
|
* Blur the content of the surface with radius and deviation.
|
||||||
*/
|
*/
|
||||||
void cairo_image_surface_blur(cairo_surface_t* surface, double radius, double deviation);
|
void cairo_image_surface_blur(cairo_surface_t* surface, double radius, double deviation);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -227,6 +227,12 @@ LS_SOLID (?i:solid)
|
||||||
ORIENTATION_HORI (?i:horizontal)
|
ORIENTATION_HORI (?i:horizontal)
|
||||||
ORIENTATION_VERT (?i:vertical)
|
ORIENTATION_VERT (?i:vertical)
|
||||||
|
|
||||||
|
/* Cursor */
|
||||||
|
|
||||||
|
CURSOR_DEF (?i:default)
|
||||||
|
CURSOR_PTR (?i:pointer)
|
||||||
|
CURSOR_TXT (?i:text)
|
||||||
|
|
||||||
/* Color schema */
|
/* Color schema */
|
||||||
RGBA (?i:rgb[a]?)
|
RGBA (?i:rgb[a]?)
|
||||||
HWB (?i:hwb)
|
HWB (?i:hwb)
|
||||||
|
@ -598,6 +604,10 @@ if ( queue == NULL ){
|
||||||
<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{ORIENTATION_HORI} { return ORIENTATION_HORI; }
|
<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{ORIENTATION_HORI} { return ORIENTATION_HORI; }
|
||||||
<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{ORIENTATION_VERT} { return ORIENTATION_VERT; }
|
<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{ORIENTATION_VERT} { return ORIENTATION_VERT; }
|
||||||
|
|
||||||
|
<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{CURSOR_DEF} { return CURSOR_DEF; }
|
||||||
|
<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{CURSOR_PTR} { return CURSOR_PTR; }
|
||||||
|
<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{CURSOR_TXT} { return CURSOR_TXT; }
|
||||||
|
|
||||||
<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{COLOR_TRANSPARENT} {
|
<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{COLOR_TRANSPARENT} {
|
||||||
return T_COLOR_TRANSPARENT;
|
return T_COLOR_TRANSPARENT;
|
||||||
}
|
}
|
||||||
|
|
|
@ -200,6 +200,10 @@ static ThemeColor hwb_to_rgb ( double h, double w, double b)
|
||||||
%token ORIENTATION_HORI "Horizontal"
|
%token ORIENTATION_HORI "Horizontal"
|
||||||
%token ORIENTATION_VERT "Vertical"
|
%token ORIENTATION_VERT "Vertical"
|
||||||
|
|
||||||
|
%token CURSOR_DEF "Default"
|
||||||
|
%token CURSOR_PTR "Pointer"
|
||||||
|
%token CURSOR_TXT "Text"
|
||||||
|
|
||||||
%token T_COL_RGBA "rgb[a] colorscheme"
|
%token T_COL_RGBA "rgb[a] colorscheme"
|
||||||
%token T_COL_HSL "hsl colorscheme"
|
%token T_COL_HSL "hsl colorscheme"
|
||||||
%token T_COL_HWB "hwb colorscheme"
|
%token T_COL_HWB "hwb colorscheme"
|
||||||
|
@ -276,6 +280,7 @@ static ThemeColor hwb_to_rgb ( double h, double w, double b)
|
||||||
%type <list> t_property_element_list
|
%type <list> t_property_element_list
|
||||||
%type <list> t_property_element_list_optional
|
%type <list> t_property_element_list_optional
|
||||||
%type <ival> t_property_orientation
|
%type <ival> t_property_orientation
|
||||||
|
%type <ival> t_property_cursor
|
||||||
%type <ival> t_name_prefix_optional
|
%type <ival> t_name_prefix_optional
|
||||||
%start t_main
|
%start t_main
|
||||||
|
|
||||||
|
@ -512,6 +517,10 @@ t_property_element
|
||||||
$$ = rofi_theme_property_create ( P_ORIENTATION );
|
$$ = rofi_theme_property_create ( P_ORIENTATION );
|
||||||
$$->value.i = $1;
|
$$->value.i = $1;
|
||||||
}
|
}
|
||||||
|
| t_property_cursor {
|
||||||
|
$$ = rofi_theme_property_create ( P_CURSOR );
|
||||||
|
$$->value.i = $1;
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
/** List of elements */
|
/** List of elements */
|
||||||
|
@ -846,6 +855,12 @@ t_property_orientation
|
||||||
| ORIENTATION_VERT { $$ = ROFI_ORIENTATION_VERTICAL; }
|
| ORIENTATION_VERT { $$ = ROFI_ORIENTATION_VERTICAL; }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
t_property_cursor
|
||||||
|
: CURSOR_DEF { $$ = ROFI_CURSOR_DEFAULT; }
|
||||||
|
| CURSOR_PTR { $$ = ROFI_CURSOR_POINTER; }
|
||||||
|
| CURSOR_TXT { $$ = ROFI_CURSOR_TEXT; }
|
||||||
|
;
|
||||||
|
|
||||||
/** Property name */
|
/** Property name */
|
||||||
t_property_name
|
t_property_name
|
||||||
: T_PROP_NAME { $$ = $1; }
|
: T_PROP_NAME { $$ = $1; }
|
||||||
|
|
|
@ -66,6 +66,7 @@ deps += [
|
||||||
dependency('xcb-icccm'),
|
dependency('xcb-icccm'),
|
||||||
dependency('xcb-xrm'),
|
dependency('xcb-xrm'),
|
||||||
dependency('xcb-randr'),
|
dependency('xcb-randr'),
|
||||||
|
dependency('xcb-cursor'),
|
||||||
dependency('xcb-xinerama'),
|
dependency('xcb-xinerama'),
|
||||||
dependency('cairo-xcb'),
|
dependency('cairo-xcb'),
|
||||||
dependency('libstartup-notification-1.0'),
|
dependency('libstartup-notification-1.0'),
|
||||||
|
|
|
@ -28,6 +28,8 @@ const char * const PropertyTypeName[P_NUM_TYPES] = {
|
||||||
"List",
|
"List",
|
||||||
/** Orientation */
|
/** Orientation */
|
||||||
"Orientation",
|
"Orientation",
|
||||||
|
/** Cursor */
|
||||||
|
"Cursor",
|
||||||
/** Inherit */
|
/** Inherit */
|
||||||
"Inherit",
|
"Inherit",
|
||||||
};
|
};
|
||||||
|
|
|
@ -359,6 +359,13 @@ const char * const WindowLocationStr[9] = {
|
||||||
"west"
|
"west"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Textual representation of RofiCursorType */
|
||||||
|
const char *const RofiCursorTypeStr[3] = {
|
||||||
|
"default",
|
||||||
|
"pointer",
|
||||||
|
"text",
|
||||||
|
};
|
||||||
|
|
||||||
static void int_rofi_theme_print_property ( Property *p )
|
static void int_rofi_theme_print_property ( Property *p )
|
||||||
{
|
{
|
||||||
switch ( p->type )
|
switch ( p->type )
|
||||||
|
@ -376,6 +383,9 @@ static void int_rofi_theme_print_property ( Property *p )
|
||||||
case P_ORIENTATION:
|
case P_ORIENTATION:
|
||||||
printf ( "%s", ( p->value.i == ROFI_ORIENTATION_HORIZONTAL ) ? "horizontal" : "vertical" );
|
printf ( "%s", ( p->value.i == ROFI_ORIENTATION_HORIZONTAL ) ? "horizontal" : "vertical" );
|
||||||
break;
|
break;
|
||||||
|
case P_CURSOR:
|
||||||
|
printf ( "%s", RofiCursorTypeStr[p->value.i] );
|
||||||
|
break;
|
||||||
case P_HIGHLIGHT:
|
case P_HIGHLIGHT:
|
||||||
if ( p->value.highlight.style & ROFI_HL_BOLD ) {
|
if ( p->value.highlight.style & ROFI_HL_BOLD ) {
|
||||||
printf ( "bold " );
|
printf ( "bold " );
|
||||||
|
@ -814,6 +824,22 @@ RofiOrientation rofi_theme_get_orientation ( const widget *widget, const char *p
|
||||||
g_debug ( "Theme entry: #%s %s property %s unset.", widget->name, widget->state ? widget->state : "", property );
|
g_debug ( "Theme entry: #%s %s property %s unset.", widget->name, widget->state ? widget->state : "", property );
|
||||||
return def;
|
return def;
|
||||||
}
|
}
|
||||||
|
RofiCursorType rofi_theme_get_cursor_type ( const widget *widget, const char *property, RofiCursorType def )
|
||||||
|
{
|
||||||
|
ThemeWidget *wid = rofi_theme_find_widget ( widget->name, widget->state, FALSE );
|
||||||
|
Property *p = rofi_theme_find_property ( wid, P_CURSOR, property, FALSE );
|
||||||
|
if ( p ) {
|
||||||
|
if ( p->type == P_INHERIT ) {
|
||||||
|
if ( widget->parent ) {
|
||||||
|
return rofi_theme_get_cursor_type ( widget->parent, property, def );
|
||||||
|
}
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
return p->value.i;
|
||||||
|
}
|
||||||
|
g_debug ( "Theme entry: #%s %s property %s unset.", widget->name, widget->state ? widget->state : "", property );
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
|
||||||
const char *rofi_theme_get_string ( const widget *widget, const char *property, const char *def )
|
const char *rofi_theme_get_string ( const widget *widget, const char *property, const char *def )
|
||||||
{
|
{
|
||||||
|
|
|
@ -118,6 +118,8 @@ struct
|
||||||
guint repaint_source;
|
guint repaint_source;
|
||||||
/** Window fullscreen */
|
/** Window fullscreen */
|
||||||
gboolean fullscreen;
|
gboolean fullscreen;
|
||||||
|
/** Cursor type */
|
||||||
|
X11CursorType cursor_type;
|
||||||
} CacheState = {
|
} CacheState = {
|
||||||
.main_window = XCB_WINDOW_NONE,
|
.main_window = XCB_WINDOW_NONE,
|
||||||
.fake_bg = NULL,
|
.fake_bg = NULL,
|
||||||
|
@ -722,7 +724,7 @@ static void rofi_view_setup_fake_transparency ( widget *win, const char* const f
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
CacheState.fake_bg = cairo_image_surface_create ( CAIRO_FORMAT_ARGB32, CacheState.mon.w, CacheState.mon.h );
|
CacheState.fake_bg = cairo_image_surface_create ( CAIRO_FORMAT_ARGB32, CacheState.mon.w, CacheState.mon.h );
|
||||||
|
|
||||||
int blur = rofi_theme_get_integer ( WIDGET ( win ), "blur", 0 );
|
int blur = rofi_theme_get_integer ( WIDGET ( win ), "blur", 0 );
|
||||||
cairo_t *dr = cairo_create ( CacheState.fake_bg );
|
cairo_t *dr = cairo_create ( CacheState.fake_bg );
|
||||||
if ( CacheState.fake_bgrel ) {
|
if ( CacheState.fake_bgrel ) {
|
||||||
|
@ -748,10 +750,8 @@ void __create_window ( MenuFlags menu_flags )
|
||||||
uint32_t selmask = XCB_CW_BACK_PIXMAP | XCB_CW_BORDER_PIXEL | XCB_CW_BIT_GRAVITY | XCB_CW_BACKING_STORE | XCB_CW_EVENT_MASK | XCB_CW_COLORMAP;
|
uint32_t selmask = XCB_CW_BACK_PIXMAP | XCB_CW_BORDER_PIXEL | XCB_CW_BIT_GRAVITY | XCB_CW_BACKING_STORE | XCB_CW_EVENT_MASK | XCB_CW_COLORMAP;
|
||||||
uint32_t xcb_event_masks = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE |
|
uint32_t xcb_event_masks = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE |
|
||||||
XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_KEYMAP_STATE |
|
XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_KEYMAP_STATE |
|
||||||
XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_FOCUS_CHANGE | XCB_EVENT_MASK_BUTTON_1_MOTION;
|
XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_FOCUS_CHANGE | XCB_EVENT_MASK_BUTTON_1_MOTION | XCB_EVENT_MASK_POINTER_MOTION;
|
||||||
if ( config.hover_select == TRUE ) {
|
|
||||||
xcb_event_masks |= XCB_EVENT_MASK_POINTER_MOTION;
|
|
||||||
}
|
|
||||||
uint32_t selval[] = {
|
uint32_t selval[] = {
|
||||||
XCB_BACK_PIXMAP_NONE, 0,
|
XCB_BACK_PIXMAP_NONE, 0,
|
||||||
XCB_GRAVITY_STATIC,
|
XCB_GRAVITY_STATIC,
|
||||||
|
@ -1500,19 +1500,65 @@ void rofi_view_handle_text ( RofiViewState *state, char *text )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static X11CursorType rofi_cursor_type_to_x11_cursor_type ( RofiCursorType type )
|
||||||
|
{
|
||||||
|
switch ( type )
|
||||||
|
{
|
||||||
|
case ROFI_CURSOR_DEFAULT:
|
||||||
|
return CURSOR_DEFAULT;
|
||||||
|
|
||||||
|
case ROFI_CURSOR_POINTER:
|
||||||
|
return CURSOR_POINTER;
|
||||||
|
|
||||||
|
case ROFI_CURSOR_TEXT:
|
||||||
|
return CURSOR_TEXT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CURSOR_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static RofiCursorType rofi_view_resolve_cursor ( RofiViewState *state, gint x, gint y ) {
|
||||||
|
widget *target = widget_find_mouse_target ( WIDGET ( state->main_window ), WIDGET_TYPE_UNKNOWN, x, y );
|
||||||
|
|
||||||
|
return target != NULL
|
||||||
|
? target->cursor_type
|
||||||
|
: ROFI_CURSOR_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rofi_view_set_cursor ( RofiCursorType type )
|
||||||
|
{
|
||||||
|
X11CursorType x11_type = rofi_cursor_type_to_x11_cursor_type ( type );
|
||||||
|
|
||||||
|
if ( x11_type == CacheState.cursor_type ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CacheState.cursor_type = x11_type;
|
||||||
|
|
||||||
|
x11_set_cursor ( CacheState.main_window, x11_type );
|
||||||
|
}
|
||||||
|
|
||||||
void rofi_view_handle_mouse_motion ( RofiViewState *state, gint x, gint y, gboolean find_mouse_target )
|
void rofi_view_handle_mouse_motion ( RofiViewState *state, gint x, gint y, gboolean find_mouse_target )
|
||||||
{
|
{
|
||||||
state->mouse.x = x;
|
state->mouse.x = x;
|
||||||
state->mouse.y = y;
|
state->mouse.y = y;
|
||||||
|
|
||||||
|
RofiCursorType cursor_type = rofi_view_resolve_cursor ( state, x, y );
|
||||||
|
|
||||||
|
rofi_view_set_cursor ( cursor_type );
|
||||||
|
|
||||||
if ( find_mouse_target ) {
|
if ( find_mouse_target ) {
|
||||||
widget *target = widget_find_mouse_target ( WIDGET ( state->main_window ), SCOPE_MOUSE_LISTVIEW_ELEMENT, x, y );
|
widget *target = widget_find_mouse_target ( WIDGET ( state->main_window ), SCOPE_MOUSE_LISTVIEW_ELEMENT, x, y );
|
||||||
|
|
||||||
if ( target != NULL ) {
|
if ( target != NULL ) {
|
||||||
state->mouse.motion_target = target;
|
state->mouse.motion_target = target;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( state->mouse.motion_target != NULL ) {
|
if ( state->mouse.motion_target != NULL ) {
|
||||||
widget_xy_to_relative ( state->mouse.motion_target, &x, &y );
|
widget_xy_to_relative ( state->mouse.motion_target, &x, &y );
|
||||||
widget_motion_notify ( state->mouse.motion_target, x, y );
|
widget_motion_notify ( state->mouse.motion_target, x, y );
|
||||||
|
|
||||||
if ( find_mouse_target ) {
|
if ( find_mouse_target ) {
|
||||||
state->mouse.motion_target = NULL;
|
state->mouse.motion_target = NULL;
|
||||||
}
|
}
|
||||||
|
@ -1851,6 +1897,20 @@ static void rofi_view_add_widget ( RofiViewState *state, widget *parent_widget,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void rofi_view_ping_mouse ( RofiViewState *state )
|
||||||
|
{
|
||||||
|
xcb_query_pointer_cookie_t pointer_cookie = xcb_query_pointer ( xcb->connection, CacheState.main_window );
|
||||||
|
xcb_query_pointer_reply_t *pointer_reply = xcb_query_pointer_reply ( xcb->connection, pointer_cookie, NULL );
|
||||||
|
|
||||||
|
if ( pointer_reply == NULL ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rofi_view_handle_mouse_motion ( state, pointer_reply->win_x, pointer_reply->win_y, config.hover_select );
|
||||||
|
|
||||||
|
free ( pointer_reply );
|
||||||
|
}
|
||||||
|
|
||||||
RofiViewState *rofi_view_create ( Mode *sw,
|
RofiViewState *rofi_view_create ( Mode *sw,
|
||||||
const char *input,
|
const char *input,
|
||||||
MenuFlags menu_flags,
|
MenuFlags menu_flags,
|
||||||
|
@ -1921,6 +1981,7 @@ RofiViewState *rofi_view_create ( Mode *sw,
|
||||||
rofi_view_update ( state, TRUE );
|
rofi_view_update ( state, TRUE );
|
||||||
xcb_map_window ( xcb->connection, CacheState.main_window );
|
xcb_map_window ( xcb->connection, CacheState.main_window );
|
||||||
widget_queue_redraw ( WIDGET ( state->main_window ) );
|
widget_queue_redraw ( WIDGET ( state->main_window ) );
|
||||||
|
rofi_view_ping_mouse ( state );
|
||||||
xcb_flush ( xcb->connection );
|
xcb_flush ( xcb->connection );
|
||||||
|
|
||||||
/* When Override Redirect, the WM will not let us know we can take focus, so just steal it */
|
/* When Override Redirect, the WM will not let us know we can take focus, so just steal it */
|
||||||
|
|
|
@ -87,7 +87,9 @@ void widget_init ( widget *wid, widget *parent, WidgetType type, const char *nam
|
||||||
wid->border_radius = rofi_theme_get_padding ( wid, "border-radius", wid->def_border_radius );
|
wid->border_radius = rofi_theme_get_padding ( wid, "border-radius", wid->def_border_radius );
|
||||||
wid->margin = rofi_theme_get_padding ( wid, "margin", wid->def_margin );
|
wid->margin = rofi_theme_get_padding ( wid, "margin", wid->def_margin );
|
||||||
|
|
||||||
// bled by default
|
wid->cursor_type = rofi_theme_get_cursor_type ( wid, "cursor", ROFI_CURSOR_DEFAULT );
|
||||||
|
|
||||||
|
// enabled by default
|
||||||
wid->enabled = rofi_theme_get_boolean ( wid, "enabled", TRUE );
|
wid->enabled = rofi_theme_get_boolean ( wid, "enabled", TRUE );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -443,9 +445,11 @@ widget *widget_find_mouse_target ( widget *wid, WidgetType type, gint x, gint y
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( wid->type == type ) {
|
|
||||||
|
if ( wid->type == type || type == WIDGET_TYPE_UNKNOWN ) {
|
||||||
return wid;
|
return wid;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
49
source/xcb.c
49
source/xcb.c
|
@ -45,6 +45,7 @@
|
||||||
#include <xcb/xinerama.h>
|
#include <xcb/xinerama.h>
|
||||||
#include <xcb/xcb_ewmh.h>
|
#include <xcb/xcb_ewmh.h>
|
||||||
#include <xcb/xproto.h>
|
#include <xcb/xproto.h>
|
||||||
|
#include <xcb/xcb_cursor.h>
|
||||||
#include <xcb/xkb.h>
|
#include <xcb/xkb.h>
|
||||||
#include <xkbcommon/xkbcommon.h>
|
#include <xkbcommon/xkbcommon.h>
|
||||||
#include <xkbcommon/xkbcommon-x11.h>
|
#include <xkbcommon/xkbcommon-x11.h>
|
||||||
|
@ -70,6 +71,7 @@
|
||||||
|
|
||||||
/** Checks if the if x and y is inside rectangle. */
|
/** Checks if the if x and y is inside rectangle. */
|
||||||
#define INTERSECT( x, y, x1, y1, w1, h1 ) ( ( ( ( x ) >= ( x1 ) ) && ( ( x ) < ( x1 + w1 ) ) ) && ( ( ( y ) >= ( y1 ) ) && ( ( y ) < ( y1 + h1 ) ) ) )
|
#define INTERSECT( x, y, x1, y1, w1, h1 ) ( ( ( ( x ) >= ( x1 ) ) && ( ( x ) < ( x1 + w1 ) ) ) && ( ( ( y ) >= ( y1 ) ) && ( ( y ) < ( y1 + h1 ) ) ) )
|
||||||
|
|
||||||
WindowManagerQuirk current_window_manager = WM_EWHM;
|
WindowManagerQuirk current_window_manager = WM_EWHM;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -98,6 +100,18 @@ static xcb_visualtype_t *root_visual = NULL;
|
||||||
xcb_atom_t netatoms[NUM_NETATOMS];
|
xcb_atom_t netatoms[NUM_NETATOMS];
|
||||||
const char *netatom_names[] = { EWMH_ATOMS ( ATOM_CHAR ) };
|
const char *netatom_names[] = { EWMH_ATOMS ( ATOM_CHAR ) };
|
||||||
|
|
||||||
|
xcb_cursor_t cursors[NUM_CURSORS] = { XCB_CURSOR_NONE, XCB_CURSOR_NONE, XCB_CURSOR_NONE };
|
||||||
|
|
||||||
|
const struct
|
||||||
|
{
|
||||||
|
const char *css_name;
|
||||||
|
const char *traditional_name;
|
||||||
|
} cursor_names[] = {
|
||||||
|
{ "default", "left_ptr" },
|
||||||
|
{ "pointer", "hand" },
|
||||||
|
{ "text", "xterm" }
|
||||||
|
};
|
||||||
|
|
||||||
static xcb_visualtype_t * lookup_visual ( xcb_screen_t *s, xcb_visualid_t visual )
|
static xcb_visualtype_t * lookup_visual ( xcb_screen_t *s, xcb_visualid_t visual )
|
||||||
{
|
{
|
||||||
xcb_depth_iterator_t d;
|
xcb_depth_iterator_t d;
|
||||||
|
@ -1057,7 +1071,7 @@ static void main_loop_x11_event_handler_view ( xcb_generic_event_t *event )
|
||||||
if ( button_mask && config.click_to_exit == TRUE ) {
|
if ( button_mask && config.click_to_exit == TRUE ) {
|
||||||
xcb->mouse_seen = TRUE;
|
xcb->mouse_seen = TRUE;
|
||||||
}
|
}
|
||||||
rofi_view_handle_mouse_motion ( state, xme->event_x, xme->event_y, !button_mask );
|
rofi_view_handle_mouse_motion ( state, xme->event_x, xme->event_y, !button_mask && config.hover_select );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case XCB_BUTTON_PRESS:
|
case XCB_BUTTON_PRESS:
|
||||||
|
@ -1504,6 +1518,24 @@ static void x11_create_visual_and_colormap ( void )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void x11_lookup_cursors ( void ) {
|
||||||
|
xcb_cursor_context_t *ctx;
|
||||||
|
|
||||||
|
if ( xcb_cursor_context_new( xcb->connection, xcb->screen, &ctx ) < 0 ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( int i = 0; i < NUM_CURSORS; ++i ) {
|
||||||
|
cursors[i] = xcb_cursor_load_cursor ( ctx, cursor_names[i].css_name );
|
||||||
|
|
||||||
|
if ( cursors[i] == XCB_CURSOR_NONE ) {
|
||||||
|
cursors[i] = xcb_cursor_load_cursor ( ctx, cursor_names[i].traditional_name );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_cursor_context_free ( ctx );
|
||||||
|
}
|
||||||
|
|
||||||
/** Retry count of grabbing keyboard. */
|
/** 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. */
|
/** Retry count of grabbing pointer. */
|
||||||
|
@ -1540,6 +1572,8 @@ gboolean display_late_setup ( void )
|
||||||
{
|
{
|
||||||
x11_create_visual_and_colormap ();
|
x11_create_visual_and_colormap ();
|
||||||
|
|
||||||
|
x11_lookup_cursors ();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create window (without showing)
|
* Create window (without showing)
|
||||||
*/
|
*/
|
||||||
|
@ -1633,3 +1667,16 @@ void x11_disable_decoration ( xcb_window_t window )
|
||||||
xcb_atom_t ha = netatoms[_MOTIF_WM_HINTS];
|
xcb_atom_t ha = netatoms[_MOTIF_WM_HINTS];
|
||||||
xcb_change_property ( xcb->connection, XCB_PROP_MODE_REPLACE, window, ha, ha, 32, 5, &hints );
|
xcb_change_property ( xcb->connection, XCB_PROP_MODE_REPLACE, window, ha, ha, 32, 5, &hints );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void x11_set_cursor ( xcb_window_t window, X11CursorType type )
|
||||||
|
{
|
||||||
|
if ( type < 0 || type >= NUM_CURSORS ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( cursors[type] == XCB_CURSOR_NONE ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_change_window_attributes ( xcb->connection, window, XCB_CW_CURSOR, &( cursors[type] ) );
|
||||||
|
}
|
||||||
|
|
|
@ -1106,6 +1106,28 @@ START_TEST ( test_properties_orientation_case )
|
||||||
|
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
START_TEST ( test_properties_cursor )
|
||||||
|
{
|
||||||
|
widget wid;
|
||||||
|
wid.name = "blaat";
|
||||||
|
wid.state = NULL;
|
||||||
|
rofi_theme_parse_string ( "* { def: default; ptr: pointer; txt: text; }");
|
||||||
|
ck_assert_int_eq ( rofi_theme_get_cursor_type( &wid, "def", ROFI_CURSOR_TEXT), ROFI_CURSOR_DEFAULT);
|
||||||
|
ck_assert_int_eq ( rofi_theme_get_cursor_type( &wid, "ptr", ROFI_CURSOR_DEFAULT), ROFI_CURSOR_POINTER);
|
||||||
|
ck_assert_int_eq ( rofi_theme_get_cursor_type( &wid, "txt", ROFI_CURSOR_DEFAULT), ROFI_CURSOR_TEXT);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
START_TEST ( test_properties_cursor_case )
|
||||||
|
{
|
||||||
|
widget wid;
|
||||||
|
wid.name = "blaat";
|
||||||
|
wid.state = NULL;
|
||||||
|
rofi_theme_parse_string ( "* { def: dEfault; ptr: POINter; txt: tExt; }");
|
||||||
|
ck_assert_int_eq ( rofi_theme_get_cursor_type( &wid, "def", ROFI_CURSOR_TEXT), ROFI_CURSOR_DEFAULT);
|
||||||
|
ck_assert_int_eq ( rofi_theme_get_cursor_type( &wid, "ptr", ROFI_CURSOR_DEFAULT), ROFI_CURSOR_POINTER);
|
||||||
|
ck_assert_int_eq ( rofi_theme_get_cursor_type( &wid, "txt", ROFI_CURSOR_DEFAULT), ROFI_CURSOR_TEXT);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
START_TEST ( test_properties_list )
|
START_TEST ( test_properties_list )
|
||||||
{
|
{
|
||||||
widget wid;
|
widget wid;
|
||||||
|
@ -1375,6 +1397,13 @@ static Suite * theme_parser_suite (void)
|
||||||
tcase_add_test ( tc_prop_orientation, test_properties_orientation_case );
|
tcase_add_test ( tc_prop_orientation, test_properties_orientation_case );
|
||||||
suite_add_tcase(s, tc_prop_orientation );
|
suite_add_tcase(s, tc_prop_orientation );
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
TCase *tc_prop_cursor = tcase_create("Propertiescursor");
|
||||||
|
tcase_add_checked_fixture(tc_prop_cursor, theme_parser_setup, theme_parser_teardown);
|
||||||
|
tcase_add_test ( tc_prop_cursor, test_properties_cursor);
|
||||||
|
tcase_add_test ( tc_prop_cursor, test_properties_cursor_case );
|
||||||
|
suite_add_tcase(s, tc_prop_cursor );
|
||||||
|
}
|
||||||
{
|
{
|
||||||
TCase *tc_prop_list = tcase_create("Propertieslist");
|
TCase *tc_prop_list = tcase_create("Propertieslist");
|
||||||
tcase_add_checked_fixture(tc_prop_list, theme_parser_setup, theme_parser_teardown);
|
tcase_add_checked_fixture(tc_prop_list, theme_parser_setup, theme_parser_teardown);
|
||||||
|
|
Loading…
Reference in a new issue