Skip to content

Commit

Permalink
Change mouse cursor on widget hover
Browse files Browse the repository at this point in the history
Currently only listview element and editbox are supported.
  • Loading branch information
TonCherAmi committed May 16, 2021
1 parent 04c006a commit 40cd101
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 9 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ addons:
- libxcb-xinerama0-dev
- libxcb-xkb-dev
- libxcb-xrm-dev
- libxcb-cursor-dev
- libxkbcommon-dev
- libxkbcommon-dev
- libxkbcommon-x11-dev
Expand Down
1 change: 1 addition & 0 deletions INSTALL.md
Original file line number Diff line number Diff line change
Expand Up @@ -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-xrm [new module might not be available in your distribution. The source can be found
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
`<package>-devel`.
Expand Down
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -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])
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])
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([cairo], [cairo cairo-xcb])
PKG_CHECK_MODULES([libsn], [libstartup-notification-1.0 ])
Expand Down
23 changes: 23 additions & 0 deletions include/xcb.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,28 @@ cairo_surface_t *x11_helper_get_screenshot_surface ( void );
*/
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
} CursorType;

/**
* @param window
* @param type
*
* Change mouse cursor
*/
void x11_set_cursor( xcb_window_t window, CursorType type );

/**
* List of window managers that need different behaviour to functioning.
*/
Expand Down Expand Up @@ -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.
*/
void cairo_image_surface_blur(cairo_surface_t* surface, double radius, double deviation);

#endif
1 change: 1 addition & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ deps += [
dependency('xcb-icccm'),
dependency('xcb-xrm'),
dependency('xcb-randr'),
dependency('xcb-cursor'),
dependency('xcb-xinerama'),
dependency('cairo-xcb'),
dependency('libstartup-notification-1.0'),
Expand Down
24 changes: 16 additions & 8 deletions source/view.c
Original file line number Diff line number Diff line change
Expand Up @@ -722,7 +722,7 @@ static void rofi_view_setup_fake_transparency ( widget *win, const char* const f
}
else {
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 );
cairo_t *dr = cairo_create ( CacheState.fake_bg );
if ( CacheState.fake_bgrel ) {
Expand All @@ -748,10 +748,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 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_STRUCTURE_NOTIFY | XCB_EVENT_MASK_FOCUS_CHANGE | XCB_EVENT_MASK_BUTTON_1_MOTION;
if ( config.hover_select == TRUE ) {
xcb_event_masks |= XCB_EVENT_MASK_POINTER_MOTION;
}
XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_FOCUS_CHANGE | XCB_EVENT_MASK_BUTTON_1_MOTION | XCB_EVENT_MASK_POINTER_MOTION;

uint32_t selval[] = {
XCB_BACK_PIXMAP_NONE, 0,
XCB_GRAVITY_STATIC,
Expand Down Expand Up @@ -1504,15 +1502,25 @@ void rofi_view_handle_mouse_motion ( RofiViewState *state, gint x, gint y, gbool
{
state->mouse.x = x;
state->mouse.y = y;
if ( find_mouse_target ) {
widget *target = widget_find_mouse_target ( WIDGET ( state->main_window ), SCOPE_MOUSE_LISTVIEW_ELEMENT, x, y );
if ( target != NULL ) {

widget *target = NULL;

if ( ( target = widget_find_mouse_target ( WIDGET ( state->main_window ), SCOPE_MOUSE_EDITBOX, x, y ) ) != NULL ) {
x11_set_cursor( CacheState.main_window, CURSOR_TEXT );
} else if ( ( target = widget_find_mouse_target ( WIDGET ( state->main_window ), SCOPE_MOUSE_LISTVIEW_ELEMENT, x, y ) ) != NULL ) {
x11_set_cursor( CacheState.main_window, CURSOR_POINTER );

if ( find_mouse_target ) {
state->mouse.motion_target = target;
}
} else {
x11_set_cursor( CacheState.main_window, CURSOR_DEFAULT );
}

if ( state->mouse.motion_target != NULL ) {
widget_xy_to_relative ( state->mouse.motion_target, &x, &y );
widget_motion_notify ( state->mouse.motion_target, x, y );

if ( find_mouse_target ) {
state->mouse.motion_target = NULL;
}
Expand Down
57 changes: 57 additions & 0 deletions source/xcb.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#include <xcb/xinerama.h>
#include <xcb/xcb_ewmh.h>
#include <xcb/xproto.h>
#include <xcb/xcb_cursor.h>
#include <xcb/xkb.h>
#include <xkbcommon/xkbcommon.h>
#include <xkbcommon/xkbcommon-x11.h>
Expand All @@ -70,6 +71,7 @@

/** 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 ) ) ) )

WindowManagerQuirk current_window_manager = WM_EWHM;

/**
Expand Down Expand Up @@ -98,6 +100,12 @@ static xcb_visualtype_t *root_visual = NULL;
xcb_atom_t netatoms[NUM_NETATOMS];
const char *netatom_names[] = { EWMH_ATOMS ( ATOM_CHAR ) };

xcb_cursor_t cursors[NUM_CURSORS] = { XCB_CURSOR_NONE, XCB_CURSOR_NONE, XCB_CURSOR_NONE };

const char *default_cursor_names[] = { "left_ptr", "arrow", "dnd-none", "op_left_arrow" };
const char *pointer_cursor_names[] = { "pointing_hand", "pointer", "hand", "hand1", "hand2", "e29285e634086352946a0e7090d73106", "9d800788f1b08800ae810202380a0822" };
const char *text_cursor_names[] = { "text", "060c183030e17efd0408102040c08602" };

static xcb_visualtype_t * lookup_visual ( xcb_screen_t *s, xcb_visualid_t visual )
{
xcb_depth_iterator_t d;
Expand Down Expand Up @@ -1504,6 +1512,40 @@ 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 < sizeof ( default_cursor_names ) / sizeof ( default_cursor_names[0] ); ++i ) {
cursors[CURSOR_DEFAULT] = xcb_cursor_load_cursor ( ctx, default_cursor_names[i] );

if (cursors[CURSOR_DEFAULT] != XCB_CURSOR_NONE) {
break;
}
}

for ( int i = 0; i < sizeof ( pointer_cursor_names ) / sizeof ( pointer_cursor_names[0] ); ++i ) {
cursors[CURSOR_POINTER] = xcb_cursor_load_cursor ( ctx, pointer_cursor_names[i] );

if (cursors[CURSOR_POINTER] != XCB_CURSOR_NONE) {
break;
}
}

for ( int i = 0; i < sizeof ( text_cursor_names ) / sizeof ( text_cursor_names[0] ); ++i ) {
cursors[CURSOR_TEXT] = xcb_cursor_load_cursor ( ctx, text_cursor_names[i] );

if (cursors[CURSOR_TEXT] != XCB_CURSOR_NONE) {
break;
}
}

xcb_cursor_context_free ( ctx );
}

/** Retry count of grabbing keyboard. */
unsigned int lazy_grab_retry_count_kb = 0;
/** Retry count of grabbing pointer. */
Expand Down Expand Up @@ -1540,6 +1582,8 @@ gboolean display_late_setup ( void )
{
x11_create_visual_and_colormap ();

x11_lookup_cursors ();

/**
* Create window (without showing)
*/
Expand Down Expand Up @@ -1633,3 +1677,16 @@ void x11_disable_decoration ( xcb_window_t window )
xcb_atom_t ha = netatoms[_MOTIF_WM_HINTS];
xcb_change_property ( xcb->connection, XCB_PROP_MODE_REPLACE, window, ha, ha, 32, 5, &hints );
}

void x11_set_cursor ( xcb_window_t window, CursorType 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]) );
}

0 comments on commit 40cd101

Please sign in to comment.