diff --git a/common/swindow.c b/common/swindow.c index 7ed5984f..7325d7ff 100644 --- a/common/swindow.c +++ b/common/swindow.c @@ -61,7 +61,7 @@ simplewindow_new(xcb_connection_t *conn, int phys_screen, int x, int y, | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW | XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE - | XCB_EVENT_MASK_EXPOSURE; + | XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_EXPOSURE; sw->window = xcb_generate_id(conn); xcb_create_window(conn, s->root_depth, sw->window, s->root, x, y, w, h, diff --git a/common/tokenize.gperf b/common/tokenize.gperf index d1e956c3..229a55d3 100644 --- a/common/tokenize.gperf +++ b/common/tokenize.gperf @@ -35,6 +35,8 @@ layout left line machine +mouse_enter +mouse_leave mwfact ncol nmaster diff --git a/event.c b/event.c index e6808d6a..9fa285ff 100644 --- a/event.c +++ b/event.c @@ -37,6 +37,7 @@ #include "keygrabber.h" #include "lua.h" #include "systray.h" +#include "statusbar.h" #include "layouts/floating.h" #include "common/atoms.h" @@ -329,6 +330,107 @@ event_handle_destroynotify(void *data __attribute__ ((unused)), return 0; } +/** Handle a motion notify over widgets. + * \param object The object. + * \param type The object type. + * \param mouse_over The pointer to the registered mouse over widget. + * \param w The new widget the mouse is over. + */ +static void +event_handle_widget_motionnotify(void *object, + awesome_type_t type, + widget_node_t **mouse_over, + widget_node_t *w) +{ + if(w != *mouse_over) + { + if(*mouse_over) + { + /* call mouse leave function on old widget */ + luaA_pushpointer(globalconf.L, object, type); + luaA_dofunction(globalconf.L, (*mouse_over)->widget->mouse_leave, 1, 0); + } + if(w) + { + /* call mouse enter function on new widget and register it */ + *mouse_over = w; + luaA_pushpointer(globalconf.L, object, type); + luaA_dofunction(globalconf.L, w->widget->mouse_enter, 1, 0); + } + } +} + +/** The motion notify event handler. + * \param data currently unused. + * \param connection The connection to the X server. + * \param ev The event. + */ +static int +event_handle_motionnotify(void *data __attribute__ ((unused)), + xcb_connection_t *connection, + xcb_motion_notify_event_t *ev) +{ + statusbar_t *statusbar = statusbar_getbywin(ev->event); + client_t *c; + widget_node_t *w; + + if(statusbar) + { + w = widget_getbycoords(statusbar->position, statusbar->widgets, + statusbar->width, statusbar->height, + ev->event_x, ev->event_y); + event_handle_widget_motionnotify(statusbar, + AWESOME_TYPE_STATUSBAR, + &statusbar->mouse_over, w); + } + else if((c = client_getbytitlebarwin(ev->event))) + { + w = widget_getbycoords(c->titlebar->position, c->titlebar->widgets, + c->titlebar->width, c->titlebar->height, + ev->event_x, ev->event_y); + event_handle_widget_motionnotify(c->titlebar, + AWESOME_TYPE_TITLEBAR, + &c->titlebar->mouse_over, w); + } + + return 0; +} + +/** The leave notify event handler. + * \param data currently unused. + * \param connection The connection to the X server. + * \param ev The event. + */ +static int +event_handle_leavenotify(void *data __attribute__ ((unused)), + xcb_connection_t *connection, + xcb_leave_notify_event_t *ev) +{ + statusbar_t *statusbar = statusbar_getbywin(ev->event); + client_t *c; + + if(statusbar) + { + if(statusbar->mouse_over) + { + /* call mouse leave function on widget the mouse was over */ + luaA_statusbar_userdata_new(globalconf.L, statusbar); + luaA_dofunction(globalconf.L, statusbar->mouse_over->widget->mouse_leave, 1, 0); + } + } + else if((c = client_getbytitlebarwin(ev->event))) + { + if(c->titlebar->mouse_over) + { + /* call mouse leave function on widget the mouse was over */ + luaA_titlebar_userdata_new(globalconf.L, c->titlebar); + luaA_dofunction(globalconf.L, c->titlebar->mouse_over->widget->mouse_leave, 1, 0); + } + } + + return 0; +} + /** The enter notify event handler. * \param data currently unused. * \param connection The connection to the X server. @@ -705,6 +807,8 @@ void a_xcb_set_event_handlers(void) xcb_event_set_configure_notify_handler(&globalconf.evenths, event_handle_configurenotify, NULL); xcb_event_set_destroy_notify_handler(&globalconf.evenths, event_handle_destroynotify, NULL); xcb_event_set_enter_notify_handler(&globalconf.evenths, event_handle_enternotify, NULL); + xcb_event_set_leave_notify_handler(&globalconf.evenths, event_handle_leavenotify, NULL); + xcb_event_set_motion_notify_handler(&globalconf.evenths, event_handle_motionnotify, NULL); xcb_event_set_expose_handler(&globalconf.evenths, event_handle_expose, NULL); xcb_event_set_key_press_handler(&globalconf.evenths, event_handle_keypress, NULL); xcb_event_set_map_request_handler(&globalconf.evenths, event_handle_maprequest, NULL); diff --git a/statusbar.c b/statusbar.c index 407722ac..5a6e0a7a 100644 --- a/statusbar.c +++ b/statusbar.c @@ -606,6 +606,7 @@ luaA_statusbar_widgets(lua_State *L) { luaA_widget_set(L, 2, *statusbar, &(*statusbar)->widgets); (*statusbar)->need_update = true; + (*statusbar)->mouse_over = NULL; return 1; } return luaA_widget_get(L, (*statusbar)->widgets); diff --git a/structs.h b/structs.h index ba5b5345..657c56af 100644 --- a/structs.h +++ b/structs.h @@ -108,6 +108,8 @@ struct widget_t int (*newindex)(lua_State *, awesome_token_t); /** Button event handler */ void (*button)(widget_node_t *, xcb_button_press_event_t *, int, void *, awesome_type_t); + /** Mouse over event handler */ + luaA_ref mouse_enter, mouse_leave; /** Alignement */ alignment_t align; /** Misc private data */ @@ -168,6 +170,8 @@ struct titlebar_t alignment_t align; /** Widgets */ widget_node_t *widgets; + /** Widget the mouse is over */ + widget_node_t *mouse_over; /** Width and height */ int width, height; /** Titlebar window */ @@ -233,6 +237,8 @@ struct statusbar_t { xcolor_t fg, bg; } colors; + /** Widget the mouse is over */ + widget_node_t *mouse_over; /** Next and previous statusbars */ statusbar_t *prev, *next; }; diff --git a/widget.c b/widget.c index 4d71d35d..83a9d9db 100644 --- a/widget.c +++ b/widget.c @@ -292,6 +292,8 @@ luaA_widget_new(lua_State *L) /* Set visible by default. */ w->isvisible = true; + w->mouse_enter = w->mouse_leave = LUA_REFNIL; + w->name = a_strdup(buf); return luaA_widget_userdata_new(L, w); @@ -337,6 +339,8 @@ luaA_widget_tostring(lua_State *L) * \luastack * \lfield visible The widget visibility. * \lfield name The widget name. + * \lfield mouse_enter A function to execute when the mouse enter the widget. + * \lfield mouse_leave A function to execute when the mouse leave the widget. */ static int luaA_widget_index(lua_State *L) @@ -357,6 +361,12 @@ luaA_widget_index(lua_State *L) case A_TK_NAME: lua_pushstring(L, (*widget)->name); return 1; + case A_TK_MOUSE_ENTER: + lua_rawgeti(L, LUA_REGISTRYINDEX, (*widget)->mouse_enter); + return 1; + case A_TK_MOUSE_LEAVE: + lua_rawgeti(L, LUA_REGISTRYINDEX, (*widget)->mouse_leave); + return 1; default: break; } @@ -381,6 +391,12 @@ luaA_widget_newindex(lua_State *L) case A_TK_VISIBLE: (*widget)->isvisible = luaA_checkboolean(L, 3); break; + case A_TK_MOUSE_ENTER: + luaA_registerfct(L, 3, &(*widget)->mouse_enter); + break; + case A_TK_MOUSE_LEAVE: + luaA_registerfct(L, 3, &(*widget)->mouse_leave); + break; default: return (*widget)->newindex ? (*widget)->newindex(L, token) : 0; }