diff --git a/awesomerc.lua.in b/awesomerc.lua.in index 6d7135292..55e188ef5 100644 --- a/awesomerc.lua.in +++ b/awesomerc.lua.in @@ -72,19 +72,19 @@ end -- {{{ Statusbar -- Create a taglist widget mytaglist = widget.new({ type = "taglist", name = "mytaglist" }) -mytaglist:mouse({}, 1, function (object, tag) awful.tag.viewonly(tag) end) -mytaglist:mouse({ modkey }, 1, function (object, tag) awful.client.movetotag(tag) end) -mytaglist:mouse({}, 3, function (object, tag) tag:view(not tag:isselected()) end) -mytaglist:mouse({ modkey }, 3, function (object, tag) awful.client.toggletag(tag) end) -mytaglist:mouse({ }, 4, awful.tag.viewnext) -mytaglist:mouse({ }, 5, awful.tag.viewprev) +mytaglist:mouse_add(mouse.new({}, 1, function (object, tag) awful.tag.viewonly(tag) end)) +mytaglist:mouse_add(mouse.new({ modkey }, 1, function (object, tag) awful.client.movetotag(tag) end)) +mytaglist:mouse_add(mouse.new({}, 3, function (object, tag) tag:view(not tag:isselected()) end)) +mytaglist:mouse_add(mouse.new({ modkey }, 3, function (object, tag) awful.client.toggletag(tag) end)) +mytaglist:mouse_add(mouse.new({ }, 4, awful.tag.viewnext)) +mytaglist:mouse_add(mouse.new({ }, 5, awful.tag.viewprev)) mytaglist:set("text_focus", " </span> ") -- Create a tasklist widget mytasklist = widget.new({ type = "tasklist", name = "mytasklist" }) -mytasklist:mouse({ }, 1, function (object, c) c:focus_set(); c:raise() end) -mytasklist:mouse({ }, 4, function () awful.client.focus(1) end) -mytasklist:mouse({ }, 5, function () awful.client.focus(-1) end) +mytasklist:mouse_add(mouse.new({ }, 1, function (object, c) c:focus_set(); c:raise() end)) +mytasklist:mouse_add(mouse.new({ }, 4, function () awful.client.focus(1) end)) +mytasklist:mouse_add(mouse.new({ }, 5, function () awful.client.focus(-1) end)) mytasklist:set("text_focus", "<bg color='"..bg_focus.."'/> <span color='"..fg_focus.."'><title/></span> ") -- Create a textbox widget @@ -102,10 +102,10 @@ myiconbox:set("image", "@iconsdir@/awesome16.png") mylayoutbox = {} for s = 1, screen.count() do mylayoutbox[s] = widget.new({ type = "iconbox", name = "myiconbox", align = "right" }) - mylayoutbox[s]:mouse({ }, 1, function () awful.layout.inc(layouts, 1) end) - mylayoutbox[s]:mouse({ }, 3, function () awful.layout.inc(layouts, -1) end) - mylayoutbox[s]:mouse({ }, 4, function () awful.layout.inc(layouts, 1) end) - mylayoutbox[s]:mouse({ }, 5, function () awful.layout.inc(layouts, -1) end) + mylayoutbox[s]:mouse_add(mouse.new({ }, 1, function () awful.layout.inc(layouts, 1) end)) + mylayoutbox[s]:mouse_add(mouse.new({ }, 3, function () awful.layout.inc(layouts, -1) end)) + mylayoutbox[s]:mouse_add(mouse.new({ }, 4, function () awful.layout.inc(layouts, 1) end)) + mylayoutbox[s]:mouse_add(mouse.new({ }, 5, function () awful.layout.inc(layouts, -1) end)) mylayoutbox[s]:set("image", "@iconsdir@/layouts/tilew.png") end @@ -125,12 +125,9 @@ end -- }}} -- {{{ Mouse bindings -awesome.mouse({ }, 3, function () awful.spawn(terminal) end) -awesome.mouse({ }, 4, awful.tag.viewnext) -awesome.mouse({ }, 5, awful.tag.viewprev) -client.mouse({ }, 1, function (c) c:focus_set(); c:raise() end) -client.mouse({ modkey }, 1, function (c) c:mouse_move() end) -client.mouse({ modkey }, 3, function (c) c:mouse_resize() end) +awesome.mouse_add(mouse.new({ }, 3, function () awful.spawn(terminal) end)) +awesome.mouse_add(mouse.new({ }, 4, awful.tag.viewnext)) +awesome.mouse_add(mouse.new({ }, 5, awful.tag.viewprev)) -- }}} -- {{{ Key bindings @@ -301,6 +298,10 @@ end -- Hook function to execute when a new client appears. function hook_manage(c) + -- Add mouse bindings + c:mouse_add(mouse.new({ }, 1, function (c) c:focus_set(); c:raise() end)) + c:mouse_add(mouse.new({ modkey }, 1, function (c) c:mouse_move() end)) + c:mouse_add(mouse.new({ modkey }, 3, function (c) c:mouse_resize() end)) -- New client may not receive focus -- if they're not focusable, so set border anyway. c:border_set({ width = border_width, color = border_normal }) diff --git a/client.c b/client.c index d61ce177a..743e78479 100644 --- a/client.c +++ b/client.c @@ -256,7 +256,7 @@ client_focus(client_t *c, int screen) c->win, XCB_CURRENT_TIME); /* since we're dropping EnterWindow events and sometimes the window * will appear under the mouse, grabbuttons */ - window_grabbuttons(c->win, c->phys_screen); + window_grabbuttons(c->win, c->phys_screen, c->buttons); phys_screen = c->phys_screen; /* Some layouts use focused client differently, so call them back. */ @@ -855,37 +855,32 @@ luaA_client_get(lua_State *L) /** Add mouse bindings over clients's window. * \param L The Lua VM state. * \luastack - * \lparam A table with modifier keys. - * \lparam A mouse button number - * \lparam A function to execute. + * \lvalue A client. + * \lparam A button binding. */ static int -luaA_client_mouse(lua_State *L) +luaA_client_mouse_add(lua_State *L) { - size_t i, len; - int b; - button_t *button; - - /* arg 1 is modkey table */ - luaA_checktable(L, 1); - /* arg 2 is mouse button */ - b = luaL_checknumber(L, 2); - /* arg 3 is cmd to run */ - luaA_checkfunction(L, 3); - - button = p_new(button_t, 1); - button->button = xutil_button_fromint(b); - button->fct = luaL_ref(L, LUA_REGISTRYINDEX); - - len = lua_objlen(L, 1); - for(i = 1; i <= len; i++) - { - lua_rawgeti(L, 1, i); - button->mod |= xutil_keymask_fromstr(luaL_checkstring(L, -1)); - } - - button_list_push(&globalconf.buttons.client, button); + client_t **c = luaA_checkudata(L, 1, "client"); + button_t **b = luaA_checkudata(L, 2, "mouse"); + button_list_push(&(*c)->buttons, *b); + button_ref(b); + return 0; +} +/** Remove mouse bindings over clients's window. + * \param L The Lua VM state. + * \luastack + * \lvalue A client. + * \lparam A button binding. + */ +static int +luaA_client_mouse_remove(lua_State *L) +{ + client_t **c = luaA_checkudata(L, 1, "client"); + button_t **b = luaA_checkudata(L, 1, "mouse"); + button_list_detach(&(*c)->buttons, *b); + button_unref(b); return 0; } @@ -1440,7 +1435,6 @@ const struct luaL_reg awesome_client_methods[] = { "get", luaA_client_get }, { "focus_get", luaA_client_focus_get }, { "visible_get", luaA_client_visible_get }, - { "mouse", luaA_client_mouse }, { NULL, NULL } }; const struct luaL_reg awesome_client_meta[] = @@ -1472,6 +1466,8 @@ const struct luaL_reg awesome_client_meta[] = { "hide", luaA_client_hide }, { "unhide", luaA_client_unhide }, { "ishidden", luaA_client_ishidden }, + { "mouse_add", luaA_client_mouse_add }, + { "mouse_remove", luaA_client_mouse_remove }, { "__eq", luaA_client_eq }, { "__tostring", luaA_client_tostring }, { NULL, NULL } diff --git a/event.c b/event.c index 7c9ebe568..f98c68994 100644 --- a/event.c +++ b/event.c @@ -156,7 +156,7 @@ event_handle_buttonpress(void *data __attribute__ ((unused)), if((c = client_getbywin(ev->event))) { - event_handle_mouse_button_press(c, ev->detail, ev->state, globalconf.buttons.client); + event_handle_mouse_button_press(c, ev->detail, ev->state, c->buttons); xcb_allow_events(globalconf.connection, XCB_ALLOW_REPLAY_POINTER, XCB_CURRENT_TIME); } else @@ -321,7 +321,7 @@ event_handle_enternotify(void *data __attribute__ ((unused)), if((c = client_getbytitlebarwin(ev->event)) || (c = client_getbywin(ev->event))) { - window_grabbuttons(c->win, c->phys_screen); + window_grabbuttons(c->win, c->phys_screen, c->buttons); /* the idea behind saving pointer_x and pointer_y is Bob Marley powered * this will allow us top drop some EnterNotify events and thus not giving * focus to windows appering under the cursor without a cursor move */ diff --git a/lua.c b/lua.c index 451941d05..c040d2a27 100644 --- a/lua.c +++ b/lua.c @@ -44,8 +44,9 @@ extern awesome_t globalconf; extern bool running; extern const name_func_link_t FloatingPlacementList[]; -extern const struct luaL_reg awesome_mouse_lib[]; extern const struct luaL_reg awesome_keygrabber_lib[]; +extern const struct luaL_reg awesome_mouse_methods[]; +extern const struct luaL_reg awesome_mouse_meta[]; extern const struct luaL_reg awesome_client_methods[]; extern const struct luaL_reg awesome_client_meta[]; extern const struct luaL_reg awesome_titlebar_methods[]; @@ -59,43 +60,22 @@ extern const struct luaL_reg awesome_statusbar_meta[]; extern const struct luaL_reg awesome_keybinding_methods[]; extern const struct luaL_reg awesome_keybinding_meta[]; -/** Define a global mouse binding. This binding will be available when you'll +/** Add a global mouse binding. This binding will be available when you'll * click on root window. * \param L The Lua VM state. * * \luastack - * \lparam A table with modifiers keys. - * \lparam A mouse button number. - * \lparam A function to execute. + * \lparam A mouse button binding. */ static int -luaA_mouse(lua_State *L) +luaA_mouse_add(lua_State *L) { - size_t i, len; - int b; - button_t *button; + button_t **button = luaA_checkudata(L, 1, "mouse"); - /* arg 1 is modkey table */ - luaA_checktable(L, 1); - /* arg 2 is mouse button */ - b = luaL_checknumber(L, 2); - /* arg 3 is cmd to run */ - luaA_checkfunction(L, 3); + button_list_push(&globalconf.buttons.root, *button); + button_ref(button); - button = p_new(button_t, 1); - button->button = xutil_button_fromint(b); - button->fct = luaL_ref(L, LUA_REGISTRYINDEX); - - len = lua_objlen(L, 1); - for(i = 1; i <= len; i++) - { - lua_rawgeti(L, 1, i); - button->mod |= xutil_keymask_fromstr(luaL_checkstring(L, -1)); - } - - button_list_push(&globalconf.buttons.root, button); - - window_root_grabbutton(button); + window_root_grabbutton(*button); return 0; } @@ -486,7 +466,7 @@ luaA_init(void) { "restart", luaA_restart }, { "floating_placement_set", luaA_floating_placement_set }, { "padding_set", luaA_padding_set }, - { "mouse", luaA_mouse }, + { "mouse_add", luaA_mouse_add }, { "resizehints_set", luaA_resizehints_set }, { "font_set", luaA_font_set }, { "colors_set", luaA_colors_set }, @@ -526,12 +506,12 @@ luaA_init(void) /* Export hooks lib */ luaL_register(L, "hooks", awesome_hooks_lib); - /* Export mouses lib */ - luaL_register(L, "mouse", awesome_mouse_lib); - /* Export keygrabber lib */ luaL_register(L, "keygrabber", awesome_keygrabber_lib); + /* Export mouse */ + luaA_openlib(L, "mouse", awesome_mouse_methods, awesome_mouse_meta); + /* Export tag */ luaA_openlib(L, "tag", awesome_tag_methods, awesome_tag_meta); diff --git a/mouse.c b/mouse.c index e734efd41..0a1ef77a1 100644 --- a/mouse.c +++ b/mouse.c @@ -828,11 +828,62 @@ luaA_mouse_screen_get(lua_State *L) return 1; } -const struct luaL_reg awesome_mouse_lib[] = +/** Create a new mouse userdata. + * \param t The mouse. + */ +static int +luaA_mouse_userdata_new(button_t *bt) { + button_t **b = lua_newuserdata(globalconf.L, sizeof(button_t *)); + *b = bt; + button_ref(b); + return luaA_settype(globalconf.L, "mouse"); +} + +/** Create a new mouse button bindings. + * \param L The Lua VM state. + * \luastack + * \lparam A table with modifiers keys. + * \lparam A mouse button number. + * \lparam A function to execute on click events. + * \lreturn A mouse button binding. + */ +static int +luaA_mouse_new(lua_State *L) +{ + int i, len; + button_t *button; + + luaA_checktable(L, 1); + /* arg 3 is mouse button */ + i = luaL_checknumber(L, 2); + /* arg 4 is cmd to run */ + luaA_checkfunction(L, 3); + + button = p_new(button_t, 1); + button->button = xutil_button_fromint(i); + button->fct = luaL_ref(L, LUA_REGISTRYINDEX); + + len = lua_objlen(L, 1); + for(i = 1; i <= len; i++) + { + lua_rawgeti(L, 1, i); + button->mod |= xutil_keymask_fromstr(luaL_checkstring(L, -1)); + } + + return luaA_mouse_userdata_new(button); +} + +const struct luaL_reg awesome_mouse_methods[] = +{ + { "new", luaA_mouse_new }, { "screen_get", luaA_mouse_screen_get }, { "coords_set", luaA_mouse_coords_set }, { NULL, NULL } }; +const struct luaL_reg awesome_mouse_meta[] = +{ + { NULL, NULL } +}; // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/structs.h b/structs.h index f3b9f25b8..943542f30 100644 --- a/structs.h +++ b/structs.h @@ -80,6 +80,8 @@ typedef enum /** Mouse buttons bindings */ struct button_t { + /** Ref count */ + int refcount; /** Key modifiers */ unsigned long mod; /** Mouse button number */ @@ -91,6 +93,7 @@ struct button_t }; DO_SLIST(button_t, button, p_delete) +DO_RCNT(button_t, button, p_delete) /** Widget */ struct widget_t @@ -291,6 +294,8 @@ struct client_t char *icon_path; /** Titlebar */ titlebar_t *titlebar; + /** Button bindings */ + button_t *buttons; /** Next and previous clients */ client_t *prev, *next; }; @@ -381,7 +386,6 @@ struct awesome_t struct { button_t *root; - button_t *client; } buttons; /** Numlock mask */ unsigned int numlockmask; diff --git a/widget.c b/widget.c index 1ecb290c2..873b84dcd 100644 --- a/widget.c +++ b/widget.c @@ -350,39 +350,37 @@ luaA_widget_new(lua_State *L) * * \luastack * \lvalue A widget. - * \lparam A table containing modifiers keys. - * \lparam A button number. - * \lparam A function to execute. Some widgets may pass arguments to this + * \lvalue A mouse button bindings object. * function. */ static int -luaA_widget_mouse(lua_State *L) +luaA_widget_mouse_add(lua_State *L) { - size_t i, len; - /* arg 1 is object */ widget_t **widget = luaA_checkudata(L, 1, "widget"); - int b; - button_t *button; + button_t **b = luaA_checkudata(L, 2, "mouse"); - /* arg 2 is modkey table */ - luaA_checktable(L, 2); - /* arg 3 is mouse button */ - b = luaL_checknumber(L, 3); - /* arg 4 is cmd to run */ - luaA_checkfunction(L, 4); + button_list_push(&(*widget)->buttons, *b); + button_ref(b); - button = p_new(button_t, 1); - button->button = xutil_button_fromint(b); - button->fct = luaL_ref(L, LUA_REGISTRYINDEX); + return 0; +} - len = lua_objlen(L, 2); - for(i = 1; i <= len; i++) - { - lua_rawgeti(L, 2, i); - button->mod |= xutil_keymask_fromstr(luaL_checkstring(L, -1)); - } +/** Remove a mouse button bindings from a widget. + * \param L The Lua VM state. + * + * \luastack + * \lvalue A widget. + * \lvalue A mouse button bindings object. + * function. + */ +static int +luaA_widget_mouse_remove(lua_State *L) +{ + widget_t **widget = luaA_checkudata(L, 1, "widget"); + button_t **b = luaA_checkudata(L, 2, "mouse"); - button_list_push(&(*widget)->buttons, button); + button_list_detach(&(*widget)->buttons, *b); + button_unref(b); return 0; } @@ -565,7 +563,8 @@ const struct luaL_reg awesome_widget_methods[] = }; const struct luaL_reg awesome_widget_meta[] = { - { "mouse", luaA_widget_mouse }, + { "mouse_add", luaA_widget_mouse_add }, + { "mouse_remove", luaA_widget_mouse_remove }, { "set", luaA_widget_set }, { "name_set", luaA_widget_name_set }, { "name_get", luaA_widget_name_get }, diff --git a/window.c b/window.c index 43452e242..f04b7916b 100644 --- a/window.c +++ b/window.c @@ -110,11 +110,11 @@ window_configure(xcb_window_t win, area_t geometry, int border) * \param phys_screen Physical screen number. */ void -window_grabbuttons(xcb_window_t win, int phys_screen) +window_grabbuttons(xcb_window_t win, int phys_screen, button_t *buttons) { button_t *b; - for(b = globalconf.buttons.client; b; b = b->next) + for(b = buttons; b; b = b->next) { xcb_grab_button(globalconf.connection, false, win, BUTTONMASK, XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC, XCB_NONE, XCB_NONE, diff --git a/window.h b/window.h index e2586e8b9..3d83b969a 100644 --- a/window.h +++ b/window.h @@ -22,12 +22,12 @@ #ifndef AWESOME_WINDOW_H #define AWESOME_WINDOW_H -#include "common/draw.h" +#include "structs.h" void window_setstate(xcb_window_t, long); long window_getstate(xcb_window_t); void window_configure(xcb_window_t, area_t, int); -void window_grabbuttons(xcb_window_t, int); +void window_grabbuttons(xcb_window_t, int, button_t *); void window_root_grabbutton(button_t *); void window_root_grabbuttons(void); void window_root_grabkey(keybinding_t *);