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", " ")
-- 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", " ")
-- 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 *);