mousegrabber: import
Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
parent
ffca477d5d
commit
0e972d4845
|
@ -46,6 +46,7 @@ set(AWE_SRCS
|
|||
${SOURCE_DIR}/ewmh.c
|
||||
${SOURCE_DIR}/keybinding.c
|
||||
${SOURCE_DIR}/keygrabber.c
|
||||
${SOURCE_DIR}/mousegrabber.c
|
||||
${SOURCE_DIR}/layout.c
|
||||
${SOURCE_DIR}/luaa.c
|
||||
${SOURCE_DIR}/hooks.c
|
||||
|
|
|
@ -327,6 +327,7 @@ main(int argc, char **argv)
|
|||
/* clear the globalconf structure */
|
||||
p_clear(&globalconf, 1);
|
||||
globalconf.keygrabber = LUA_REFNIL;
|
||||
globalconf.mousegrabber = LUA_REFNIL;
|
||||
|
||||
/* save argv */
|
||||
for(i = 0; i < argc; i++)
|
||||
|
|
28
event.c
28
event.c
|
@ -35,6 +35,7 @@
|
|||
#include "titlebar.h"
|
||||
#include "keybinding.h"
|
||||
#include "keygrabber.h"
|
||||
#include "mousegrabber.h"
|
||||
#include "luaa.h"
|
||||
#include "systray.h"
|
||||
#include "screen.h"
|
||||
|
@ -133,6 +134,29 @@ widget_getbycoords(position_t position, widget_node_array_t *widgets,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/** Handle an event with mouse grabber if needed
|
||||
* \param x The x coordinate.
|
||||
* \param y The y coordinate.
|
||||
* \param mask The mask buttons.
|
||||
*/
|
||||
static void
|
||||
event_handle_mousegrabber(int x, int y, uint16_t mask)
|
||||
{
|
||||
if(globalconf.mousegrabber != LUA_REFNIL)
|
||||
{
|
||||
lua_rawgeti(globalconf.L, LUA_REGISTRYINDEX, globalconf.mousegrabber);
|
||||
mousegrabber_handleevent(globalconf.L, x, y, mask);
|
||||
if(lua_pcall(globalconf.L, 1, 1, 0))
|
||||
{
|
||||
warn("error running function: %s", lua_tostring(globalconf.L, -1));
|
||||
luaA_mousegrabber_stop(globalconf.L);
|
||||
}
|
||||
else if(!lua_isboolean(globalconf.L, -1) || !lua_toboolean(globalconf.L, -1))
|
||||
luaA_mousegrabber_stop(globalconf.L);
|
||||
lua_pop(globalconf.L, 1); /* pop returned value */
|
||||
}
|
||||
}
|
||||
|
||||
/** The button press event handler.
|
||||
* \param data The type of mouse event.
|
||||
* \param connection The connection to the X server.
|
||||
|
@ -153,6 +177,8 @@ event_handle_button(void *data, xcb_connection_t *connection, xcb_button_press_e
|
|||
* drop them */
|
||||
ev->state &= 0x00ff;
|
||||
|
||||
event_handle_mousegrabber(ev->root_x, ev->root_y, ev->state);
|
||||
|
||||
if((wibox = wibox_getbywin(ev->event))
|
||||
|| (wibox = wibox_getbywin(ev->child)))
|
||||
{
|
||||
|
@ -408,6 +434,8 @@ event_handle_motionnotify(void *data __attribute__ ((unused)),
|
|||
wibox_t *wibox = wibox_getbywin(ev->event);
|
||||
widget_t *w;
|
||||
|
||||
event_handle_mousegrabber(ev->root_x, ev->root_y, ev->state);
|
||||
|
||||
if(wibox
|
||||
&& (w = widget_getbycoords(wibox->position, &wibox->widgets,
|
||||
wibox->sw.geometry.width,
|
||||
|
|
4
luaa.c
4
luaa.c
|
@ -56,6 +56,7 @@ extern awesome_t globalconf;
|
|||
|
||||
extern const struct luaL_reg awesome_hooks_lib[];
|
||||
extern const struct luaL_reg awesome_keygrabber_lib[];
|
||||
extern const struct luaL_reg awesome_mousegrabber_lib[];
|
||||
extern const struct luaL_reg awesome_button_methods[];
|
||||
extern const struct luaL_reg awesome_button_meta[];
|
||||
extern const struct luaL_reg awesome_image_methods[];
|
||||
|
@ -769,6 +770,9 @@ luaA_init(void)
|
|||
/* Export keygrabber lib */
|
||||
luaL_register(L, "keygrabber", awesome_keygrabber_lib);
|
||||
|
||||
/* Export mousegrabber lib */
|
||||
luaL_register(L, "mousegrabber", awesome_mousegrabber_lib);
|
||||
|
||||
/* Export otable lib */
|
||||
luaA_openlib(L, "otable", otable_methods, otable_meta);
|
||||
|
||||
|
|
51
mouse.c
51
mouse.c
|
@ -1320,6 +1320,37 @@ luaA_mouse_newindex(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/** Push a table with mouse status.
|
||||
* \param L The Lua VM state.
|
||||
* \param x The x coordinate.
|
||||
* \param y The y coordinate.
|
||||
* \param mask The button mask.
|
||||
*/
|
||||
int
|
||||
luaA_mouse_pushstatus(lua_State *L, int x, int y, uint16_t mask)
|
||||
{
|
||||
lua_newtable(L);
|
||||
lua_pushnumber(L, x);
|
||||
lua_setfield(L, -2, "x");
|
||||
lua_pushnumber(L, y);
|
||||
lua_setfield(L, -2, "y");
|
||||
|
||||
lua_newtable(L);
|
||||
|
||||
int i = 1;
|
||||
|
||||
for(uint16_t maski = XCB_BUTTON_MASK_1; maski <= XCB_BUTTON_MASK_5; maski <<= 1)
|
||||
{
|
||||
if(mask & maski)
|
||||
lua_pushboolean(L, true);
|
||||
else
|
||||
lua_pushboolean(L, false);
|
||||
lua_rawseti(L, -2, i++);
|
||||
}
|
||||
lua_setfield(L, -2, "buttons");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Get or set the mouse coords.
|
||||
* \param L The Lua VM state.
|
||||
* \return The number of elements pushed on stack.
|
||||
|
@ -1330,8 +1361,8 @@ luaA_mouse_newindex(lua_State *L)
|
|||
static int
|
||||
luaA_mouse_coords(lua_State *L)
|
||||
{
|
||||
uint16_t mask, maski;
|
||||
int screen, x, y, mouse_x, mouse_y, i = 1;
|
||||
uint16_t mask;
|
||||
int screen, x, y, mouse_x, mouse_y;
|
||||
|
||||
if(lua_gettop(L) == 1)
|
||||
{
|
||||
|
@ -1353,21 +1384,7 @@ luaA_mouse_coords(lua_State *L)
|
|||
if(!mouse_query_pointer_root(&screen, &mouse_x, &mouse_y, &mask))
|
||||
return 0;
|
||||
|
||||
lua_newtable(L);
|
||||
lua_pushnumber(L, mouse_x);
|
||||
lua_setfield(L, -2, "x");
|
||||
lua_pushnumber(L, mouse_y);
|
||||
lua_setfield(L, -2, "y");
|
||||
lua_newtable(L);
|
||||
for(maski = XCB_BUTTON_MASK_1; i <= XCB_BUTTON_MASK_5; maski <<= 1, i++)
|
||||
if(mask & maski)
|
||||
{
|
||||
lua_pushboolean(L, true);
|
||||
lua_rawseti(L, -2, i);
|
||||
}
|
||||
lua_setfield(L, -2, "buttons");
|
||||
|
||||
return 1;
|
||||
return luaA_mouse_pushstatus(L, mouse_x, mouse_y, mask);
|
||||
}
|
||||
|
||||
const struct luaL_reg awesome_mouse_methods[] =
|
||||
|
|
1
mouse.h
1
mouse.h
|
@ -42,6 +42,7 @@ struct button_t
|
|||
void button_delete(button_t **);
|
||||
|
||||
bool mouse_query_pointer(xcb_window_t, int *, int *, uint16_t *);
|
||||
int luaA_mouse_pushstatus(lua_State *, int, int, uint16_t);
|
||||
|
||||
DO_RCNT(button_t, button, button_delete)
|
||||
ARRAY_FUNCS(button_t *, button, button_unref)
|
||||
|
|
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* mousegrabber.c - mouse pointer grabbing
|
||||
*
|
||||
* Copyright © 2008 Julien Danjou <julien@danjou.info>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include "mouse.h"
|
||||
#include "mousegrabber.h"
|
||||
#include "common/xcursor.h"
|
||||
|
||||
extern awesome_t globalconf;
|
||||
|
||||
/** Grab the mouse.
|
||||
* \param cursor The cursor to use while grabbing.
|
||||
* \return True if mouse was grabbed.
|
||||
*/
|
||||
static bool
|
||||
mousegrabber_grab(xcb_cursor_t cursor)
|
||||
{
|
||||
xcb_window_t root;
|
||||
|
||||
for(int screen = 0;
|
||||
screen < xcb_setup_roots_length(xcb_get_setup(globalconf.connection));
|
||||
screen++)
|
||||
{
|
||||
int x, y;
|
||||
uint16_t mask;
|
||||
|
||||
root = xutil_screen_get(globalconf.connection, screen)->root;
|
||||
if(mouse_query_pointer(root, &x, &y, &mask))
|
||||
break;
|
||||
}
|
||||
|
||||
for(int i = 1000; i; i--)
|
||||
{
|
||||
xcb_grab_pointer_reply_t *grab_ptr_r;
|
||||
xcb_grab_pointer_cookie_t grab_ptr_c =
|
||||
xcb_grab_pointer_unchecked(globalconf.connection, false, root,
|
||||
XCB_EVENT_MASK_BUTTON_PRESS
|
||||
| XCB_EVENT_MASK_BUTTON_RELEASE
|
||||
| XCB_EVENT_MASK_POINTER_MOTION,
|
||||
XCB_GRAB_MODE_ASYNC,
|
||||
XCB_GRAB_MODE_ASYNC,
|
||||
root, cursor, XCB_CURRENT_TIME);
|
||||
|
||||
if((grab_ptr_r = xcb_grab_pointer_reply(globalconf.connection, grab_ptr_c, NULL)))
|
||||
{
|
||||
p_delete(&grab_ptr_r);
|
||||
return true;
|
||||
}
|
||||
usleep(1000);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Handle mouse motion events.
|
||||
* \param L Lua stack to push the pointer motion.
|
||||
* \param ev Received mouse motion event.
|
||||
*/
|
||||
void
|
||||
mousegrabber_handleevent(lua_State *L, int x, int y, uint16_t mask)
|
||||
{
|
||||
luaA_mouse_pushstatus(L, x, y, mask);
|
||||
}
|
||||
|
||||
/** Grab the mouse pointer and list motions, calling callback function at each
|
||||
* motion. The callback function must return a boolean value: true to
|
||||
* continue grabbing, false to stop.
|
||||
* The function is called with one argument:
|
||||
* a table containing modifiers pointer coordinates.
|
||||
*
|
||||
* \param L The Lua VM state.
|
||||
* \return The number of elements pushed on stack.
|
||||
*
|
||||
* \luastack
|
||||
*
|
||||
* \lparam A callback function as described above.
|
||||
*/
|
||||
static int
|
||||
luaA_mousegrabber_run(lua_State *L)
|
||||
{
|
||||
if(globalconf.mousegrabber != LUA_REFNIL)
|
||||
luaL_error(L, "mousegrabber already running");
|
||||
|
||||
uint16_t cfont = xcursor_font_fromstr(luaL_checkstring(L, 2));
|
||||
|
||||
if(cfont)
|
||||
{
|
||||
xcb_cursor_t cursor = xcursor_new(globalconf.connection, cfont);
|
||||
|
||||
luaA_registerfct(L, 1, &globalconf.mousegrabber);
|
||||
|
||||
if(!mousegrabber_grab(cursor))
|
||||
{
|
||||
luaA_unregister(L, &globalconf.mousegrabber);
|
||||
luaL_error(L, "unable to grab mouse pointer");
|
||||
}
|
||||
}
|
||||
else
|
||||
luaA_warn(L, "invalid cursor");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Stop grabbing the mouse pointer.
|
||||
* \param L The Lua VM state.
|
||||
* \return The number of elements pushed on stack.
|
||||
*/
|
||||
int
|
||||
luaA_mousegrabber_stop(lua_State *L)
|
||||
{
|
||||
xcb_ungrab_pointer(globalconf.connection, XCB_CURRENT_TIME);
|
||||
luaA_unregister(L, &globalconf.mousegrabber);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct luaL_reg awesome_mousegrabber_lib[] =
|
||||
{
|
||||
{ "run", luaA_mousegrabber_run },
|
||||
{ "stop", luaA_mousegrabber_stop },
|
||||
{ NULL, NULL }
|
||||
};
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* mousegrabber.h - mouse pointer grabbing header
|
||||
*
|
||||
* Copyright © 2008 Julien Danjou <julien@danjou.info>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AWESOME_MOUSEGRABBER_H
|
||||
#define AWESOME_MOUSEGRABBER_H
|
||||
|
||||
#include <lua.h>
|
||||
#include <xcb/xcb.h>
|
||||
|
||||
int luaA_mousegrabber_stop(lua_State *);
|
||||
void mousegrabber_handleevent(lua_State *, int, int, uint16_t);
|
||||
|
||||
#endif
|
||||
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80
|
Loading…
Reference in New Issue