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}/ewmh.c
|
||||||
${SOURCE_DIR}/keybinding.c
|
${SOURCE_DIR}/keybinding.c
|
||||||
${SOURCE_DIR}/keygrabber.c
|
${SOURCE_DIR}/keygrabber.c
|
||||||
|
${SOURCE_DIR}/mousegrabber.c
|
||||||
${SOURCE_DIR}/layout.c
|
${SOURCE_DIR}/layout.c
|
||||||
${SOURCE_DIR}/luaa.c
|
${SOURCE_DIR}/luaa.c
|
||||||
${SOURCE_DIR}/hooks.c
|
${SOURCE_DIR}/hooks.c
|
||||||
|
|
|
@ -327,6 +327,7 @@ main(int argc, char **argv)
|
||||||
/* clear the globalconf structure */
|
/* clear the globalconf structure */
|
||||||
p_clear(&globalconf, 1);
|
p_clear(&globalconf, 1);
|
||||||
globalconf.keygrabber = LUA_REFNIL;
|
globalconf.keygrabber = LUA_REFNIL;
|
||||||
|
globalconf.mousegrabber = LUA_REFNIL;
|
||||||
|
|
||||||
/* save argv */
|
/* save argv */
|
||||||
for(i = 0; i < argc; i++)
|
for(i = 0; i < argc; i++)
|
||||||
|
|
28
event.c
28
event.c
|
@ -35,6 +35,7 @@
|
||||||
#include "titlebar.h"
|
#include "titlebar.h"
|
||||||
#include "keybinding.h"
|
#include "keybinding.h"
|
||||||
#include "keygrabber.h"
|
#include "keygrabber.h"
|
||||||
|
#include "mousegrabber.h"
|
||||||
#include "luaa.h"
|
#include "luaa.h"
|
||||||
#include "systray.h"
|
#include "systray.h"
|
||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
|
@ -133,6 +134,29 @@ widget_getbycoords(position_t position, widget_node_array_t *widgets,
|
||||||
return NULL;
|
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.
|
/** The button press event handler.
|
||||||
* \param data The type of mouse event.
|
* \param data The type of mouse event.
|
||||||
* \param connection The connection to the X server.
|
* \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 */
|
* drop them */
|
||||||
ev->state &= 0x00ff;
|
ev->state &= 0x00ff;
|
||||||
|
|
||||||
|
event_handle_mousegrabber(ev->root_x, ev->root_y, ev->state);
|
||||||
|
|
||||||
if((wibox = wibox_getbywin(ev->event))
|
if((wibox = wibox_getbywin(ev->event))
|
||||||
|| (wibox = wibox_getbywin(ev->child)))
|
|| (wibox = wibox_getbywin(ev->child)))
|
||||||
{
|
{
|
||||||
|
@ -408,6 +434,8 @@ event_handle_motionnotify(void *data __attribute__ ((unused)),
|
||||||
wibox_t *wibox = wibox_getbywin(ev->event);
|
wibox_t *wibox = wibox_getbywin(ev->event);
|
||||||
widget_t *w;
|
widget_t *w;
|
||||||
|
|
||||||
|
event_handle_mousegrabber(ev->root_x, ev->root_y, ev->state);
|
||||||
|
|
||||||
if(wibox
|
if(wibox
|
||||||
&& (w = widget_getbycoords(wibox->position, &wibox->widgets,
|
&& (w = widget_getbycoords(wibox->position, &wibox->widgets,
|
||||||
wibox->sw.geometry.width,
|
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_hooks_lib[];
|
||||||
extern const struct luaL_reg awesome_keygrabber_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_methods[];
|
||||||
extern const struct luaL_reg awesome_button_meta[];
|
extern const struct luaL_reg awesome_button_meta[];
|
||||||
extern const struct luaL_reg awesome_image_methods[];
|
extern const struct luaL_reg awesome_image_methods[];
|
||||||
|
@ -769,6 +770,9 @@ luaA_init(void)
|
||||||
/* Export keygrabber lib */
|
/* Export keygrabber lib */
|
||||||
luaL_register(L, "keygrabber", awesome_keygrabber_lib);
|
luaL_register(L, "keygrabber", awesome_keygrabber_lib);
|
||||||
|
|
||||||
|
/* Export mousegrabber lib */
|
||||||
|
luaL_register(L, "mousegrabber", awesome_mousegrabber_lib);
|
||||||
|
|
||||||
/* Export otable lib */
|
/* Export otable lib */
|
||||||
luaA_openlib(L, "otable", otable_methods, otable_meta);
|
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;
|
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.
|
/** Get or set the mouse coords.
|
||||||
* \param L The Lua VM state.
|
* \param L The Lua VM state.
|
||||||
* \return The number of elements pushed on stack.
|
* \return The number of elements pushed on stack.
|
||||||
|
@ -1330,8 +1361,8 @@ luaA_mouse_newindex(lua_State *L)
|
||||||
static int
|
static int
|
||||||
luaA_mouse_coords(lua_State *L)
|
luaA_mouse_coords(lua_State *L)
|
||||||
{
|
{
|
||||||
uint16_t mask, maski;
|
uint16_t mask;
|
||||||
int screen, x, y, mouse_x, mouse_y, i = 1;
|
int screen, x, y, mouse_x, mouse_y;
|
||||||
|
|
||||||
if(lua_gettop(L) == 1)
|
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))
|
if(!mouse_query_pointer_root(&screen, &mouse_x, &mouse_y, &mask))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
lua_newtable(L);
|
return luaA_mouse_pushstatus(L, mouse_x, mouse_y, mask);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct luaL_reg awesome_mouse_methods[] =
|
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 **);
|
void button_delete(button_t **);
|
||||||
|
|
||||||
bool mouse_query_pointer(xcb_window_t, int *, int *, uint16_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)
|
DO_RCNT(button_t, button, button_delete)
|
||||||
ARRAY_FUNCS(button_t *, button, button_unref)
|
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
|
|
@ -361,6 +361,8 @@ struct awesome_t
|
||||||
struct ev_timer timer;
|
struct ev_timer timer;
|
||||||
/** The key grabber function */
|
/** The key grabber function */
|
||||||
luaA_ref keygrabber;
|
luaA_ref keygrabber;
|
||||||
|
/** The mouse pointer grabber function */
|
||||||
|
luaA_ref mousegrabber;
|
||||||
/** Focused screen */
|
/** Focused screen */
|
||||||
screen_t *screen_focus;
|
screen_t *screen_focus;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue