Revert "Support more than 5 mouse buttons" (FS#1082)
This reverts commit bd8158495e
.
The idea was to track the current list of pressed and depressed mouse buttons,
because we get button events for more than 5 buttons, but can only query the
state of the first 5 buttons.
However, there are cases where we see button presses, but won't see the
corresponding release event. This is quite bad.
Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
parent
fc49e28025
commit
ee1fe4dd59
35
event.c
35
event.c
|
@ -113,7 +113,7 @@ event_handle_mousegrabber(int x, int y, uint16_t mask)
|
||||||
if(globalconf.mousegrabber != LUA_REFNIL)
|
if(globalconf.mousegrabber != LUA_REFNIL)
|
||||||
{
|
{
|
||||||
lua_rawgeti(globalconf.L, LUA_REGISTRYINDEX, globalconf.mousegrabber);
|
lua_rawgeti(globalconf.L, LUA_REGISTRYINDEX, globalconf.mousegrabber);
|
||||||
luaA_mouse_pushstatus(globalconf.L, x, y);
|
mousegrabber_handleevent(globalconf.L, x, y, mask);
|
||||||
if(lua_pcall(globalconf.L, 1, 1, 0))
|
if(lua_pcall(globalconf.L, 1, 1, 0))
|
||||||
{
|
{
|
||||||
warn("error running function: %s", lua_tostring(globalconf.L, -1));
|
warn("error running function: %s", lua_tostring(globalconf.L, -1));
|
||||||
|
@ -156,37 +156,6 @@ event_emit_button(xcb_button_press_event_t *ev)
|
||||||
luaA_object_emit_signal(globalconf.L, -5, name, 4);
|
luaA_object_emit_signal(globalconf.L, -5, name, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Update the global button state
|
|
||||||
* \param response_type XCB_BUTTON_PRESS or XCB_BUTTON_RELEASE
|
|
||||||
* \param button Button being changed
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
event_update_button_state(uint8_t response_type, uint8_t button)
|
|
||||||
{
|
|
||||||
/* There is no button 0! */
|
|
||||||
const unsigned int max_button = sizeof(globalconf.buttons_pressed) * 8;
|
|
||||||
uint32_t mask = 1 << (button - 1);
|
|
||||||
|
|
||||||
if (button > max_button) {
|
|
||||||
warn("Button %d pressed, but we only support %d buttons", button, max_button);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(response_type & XCB_EVENT_RESPONSE_TYPE_MASK)
|
|
||||||
{
|
|
||||||
case XCB_BUTTON_PRESS:
|
|
||||||
/* Set the (button-1)-st bit */
|
|
||||||
globalconf.buttons_pressed |= mask;
|
|
||||||
break;
|
|
||||||
case XCB_BUTTON_RELEASE:
|
|
||||||
/* Clear the (button-1)-st bit */
|
|
||||||
globalconf.buttons_pressed &= ~mask;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
fatal("Invalid event type");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The button press event handler.
|
/** The button press event handler.
|
||||||
* \param ev The event.
|
* \param ev The event.
|
||||||
*/
|
*/
|
||||||
|
@ -198,8 +167,6 @@ event_handle_button(xcb_button_press_event_t *ev)
|
||||||
|
|
||||||
globalconf.timestamp = ev->time;
|
globalconf.timestamp = ev->time;
|
||||||
|
|
||||||
event_update_button_state(ev->response_type, ev->detail);
|
|
||||||
|
|
||||||
if(event_handle_mousegrabber(ev->root_x, ev->root_y, 1 << (ev->detail - 1 + 8)))
|
if(event_handle_mousegrabber(ev->root_x, ev->root_y, 1 << (ev->detail - 1 + 8)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -80,8 +80,6 @@ typedef struct
|
||||||
button_array_t buttons;
|
button_array_t buttons;
|
||||||
/** Modifiers masks */
|
/** Modifiers masks */
|
||||||
uint16_t numlockmask, shiftlockmask, capslockmask, modeswitchmask;
|
uint16_t numlockmask, shiftlockmask, capslockmask, modeswitchmask;
|
||||||
/** Bitmask for currently pressed buttons */
|
|
||||||
uint32_t buttons_pressed;
|
|
||||||
/** Check for XTest extension */
|
/** Check for XTest extension */
|
||||||
bool have_xtest;
|
bool have_xtest;
|
||||||
/** Clients list */
|
/** Clients list */
|
||||||
|
|
41
mouse.c
41
mouse.c
|
@ -32,10 +32,11 @@
|
||||||
* \param x will be set to the Pointer-x-coordinate relative to window
|
* \param x will be set to the Pointer-x-coordinate relative to window
|
||||||
* \param y will be set to the Pointer-y-coordinate relative to window
|
* \param y will be set to the Pointer-y-coordinate relative to window
|
||||||
* \param child Will be set to the window under the pointer.
|
* \param child Will be set to the window under the pointer.
|
||||||
|
* \param mask will be set to the current buttons state
|
||||||
* \return true on success, false if an error occurred
|
* \return true on success, false if an error occurred
|
||||||
**/
|
**/
|
||||||
static bool
|
bool
|
||||||
mouse_query_pointer(xcb_window_t window, int16_t *x, int16_t *y, xcb_window_t *child)
|
mouse_query_pointer(xcb_window_t window, int16_t *x, int16_t *y, xcb_window_t *child, uint16_t *mask)
|
||||||
{
|
{
|
||||||
xcb_query_pointer_cookie_t query_ptr_c;
|
xcb_query_pointer_cookie_t query_ptr_c;
|
||||||
xcb_query_pointer_reply_t *query_ptr_r;
|
xcb_query_pointer_reply_t *query_ptr_r;
|
||||||
|
@ -49,6 +50,8 @@ mouse_query_pointer(xcb_window_t window, int16_t *x, int16_t *y, xcb_window_t *c
|
||||||
*x = query_ptr_r->win_x;
|
*x = query_ptr_r->win_x;
|
||||||
*y = query_ptr_r->win_y;
|
*y = query_ptr_r->win_y;
|
||||||
|
|
||||||
|
if(mask)
|
||||||
|
*mask = query_ptr_r->mask;
|
||||||
if(child)
|
if(child)
|
||||||
*child = query_ptr_r->child;
|
*child = query_ptr_r->child;
|
||||||
|
|
||||||
|
@ -64,10 +67,12 @@ mouse_query_pointer(xcb_window_t window, int16_t *x, int16_t *y, xcb_window_t *c
|
||||||
* \param mask This will be set to the current buttons state.
|
* \param mask This will be set to the current buttons state.
|
||||||
* \return True on success, false if an error occurred.
|
* \return True on success, false if an error occurred.
|
||||||
*/
|
*/
|
||||||
static inline bool
|
static bool
|
||||||
mouse_query_pointer_root(int16_t *x, int16_t *y, xcb_window_t *child)
|
mouse_query_pointer_root(int16_t *x, int16_t *y, xcb_window_t *child, uint16_t *mask)
|
||||||
{
|
{
|
||||||
return mouse_query_pointer(globalconf.screen->root, x, y, child);
|
xcb_window_t root = globalconf.screen->root;
|
||||||
|
|
||||||
|
return mouse_query_pointer(root, x, y, child, mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set the pointer position.
|
/** Set the pointer position.
|
||||||
|
@ -100,7 +105,7 @@ luaA_mouse_index(lua_State *L)
|
||||||
if (A_STRNEQ(attr, "screen"))
|
if (A_STRNEQ(attr, "screen"))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!mouse_query_pointer_root(&mouse_x, &mouse_y, NULL))
|
if (!mouse_query_pointer_root(&mouse_x, &mouse_y, NULL, NULL))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
screen = screen_getbycoord(mouse_x, mouse_y);
|
screen = screen_getbycoord(mouse_x, mouse_y);
|
||||||
|
@ -139,7 +144,7 @@ luaA_mouse_newindex(lua_State *L)
|
||||||
* \param mask The button mask.
|
* \param mask The button mask.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
luaA_mouse_pushstatus(lua_State *L, int x, int y)
|
luaA_mouse_pushstatus(lua_State *L, int x, int y, uint16_t mask)
|
||||||
{
|
{
|
||||||
lua_createtable(L, 0, 2);
|
lua_createtable(L, 0, 2);
|
||||||
lua_pushnumber(L, x);
|
lua_pushnumber(L, x);
|
||||||
|
@ -149,12 +154,15 @@ luaA_mouse_pushstatus(lua_State *L, int x, int y)
|
||||||
|
|
||||||
lua_createtable(L, 5, 0);
|
lua_createtable(L, 5, 0);
|
||||||
|
|
||||||
const unsigned int max_button = sizeof(globalconf.buttons_pressed) * 8;
|
int i = 1;
|
||||||
unsigned int mask = 1;
|
|
||||||
for (unsigned int i = 1; i <= max_button; i++, mask <<= 1)
|
for(uint16_t maski = XCB_BUTTON_MASK_1; maski <= XCB_BUTTON_MASK_5; maski <<= 1)
|
||||||
{
|
{
|
||||||
lua_pushboolean(L, globalconf.buttons_pressed & mask);
|
if(mask & maski)
|
||||||
lua_rawseti(L, -2, i);
|
lua_pushboolean(L, true);
|
||||||
|
else
|
||||||
|
lua_pushboolean(L, false);
|
||||||
|
lua_rawseti(L, -2, i++);
|
||||||
}
|
}
|
||||||
lua_setfield(L, -2, "buttons");
|
lua_setfield(L, -2, "buttons");
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -167,6 +175,7 @@ luaA_mouse_pushstatus(lua_State *L, int x, int y)
|
||||||
static int
|
static int
|
||||||
luaA_mouse_coords(lua_State *L)
|
luaA_mouse_coords(lua_State *L)
|
||||||
{
|
{
|
||||||
|
uint16_t mask;
|
||||||
int x, y;
|
int x, y;
|
||||||
int16_t mouse_x, mouse_y;
|
int16_t mouse_x, mouse_y;
|
||||||
|
|
||||||
|
@ -175,7 +184,7 @@ luaA_mouse_coords(lua_State *L)
|
||||||
luaA_checktable(L, 1);
|
luaA_checktable(L, 1);
|
||||||
bool ignore_enter_notify = (lua_gettop(L) == 2 && luaA_checkboolean(L, 2));
|
bool ignore_enter_notify = (lua_gettop(L) == 2 && luaA_checkboolean(L, 2));
|
||||||
|
|
||||||
if(!mouse_query_pointer_root(&mouse_x, &mouse_y, NULL))
|
if(!mouse_query_pointer_root(&mouse_x, &mouse_y, NULL, &mask))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
x = luaA_getopt_number(L, 1, "x", mouse_x);
|
x = luaA_getopt_number(L, 1, "x", mouse_x);
|
||||||
|
@ -192,10 +201,10 @@ luaA_mouse_coords(lua_State *L)
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!mouse_query_pointer_root(&mouse_x, &mouse_y, NULL))
|
if(!mouse_query_pointer_root(&mouse_x, &mouse_y, NULL, &mask))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return luaA_mouse_pushstatus(L, mouse_x, mouse_y);
|
return luaA_mouse_pushstatus(L, mouse_x, mouse_y, mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get the client which is under the pointer.
|
/** Get the client which is under the pointer.
|
||||||
|
@ -210,7 +219,7 @@ luaA_mouse_object_under_pointer(lua_State *L)
|
||||||
int16_t mouse_x, mouse_y;
|
int16_t mouse_x, mouse_y;
|
||||||
xcb_window_t child;
|
xcb_window_t child;
|
||||||
|
|
||||||
if(!mouse_query_pointer_root(&mouse_x, &mouse_y, &child))
|
if(!mouse_query_pointer_root(&mouse_x, &mouse_y, &child, NULL))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
drawin_t *drawin;
|
drawin_t *drawin;
|
||||||
|
|
3
mouse.h
3
mouse.h
|
@ -26,7 +26,8 @@
|
||||||
#include <xcb/xcb.h>
|
#include <xcb/xcb.h>
|
||||||
#include <lua.h>
|
#include <lua.h>
|
||||||
|
|
||||||
int luaA_mouse_pushstatus(lua_State *, int, int);
|
bool mouse_query_pointer(xcb_window_t, int16_t *, int16_t *, xcb_window_t *, uint16_t *);
|
||||||
|
int luaA_mouse_pushstatus(lua_State *, int, int, uint16_t);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||||
|
|
|
@ -59,6 +59,18 @@ mousegrabber_grab(xcb_cursor_t cursor)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Handle mouse motion events.
|
||||||
|
* \param L Lua stack to push the pointer motion.
|
||||||
|
* \param x The received mouse event x component.
|
||||||
|
* \param y The received mouse event y component.
|
||||||
|
* \param mask The received mouse event bit mask.
|
||||||
|
*/
|
||||||
|
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
|
/** Grab the mouse pointer and list motions, calling callback function at each
|
||||||
* motion. The callback function must return a boolean value: true to
|
* motion. The callback function must return a boolean value: true to
|
||||||
* continue grabbing, false to stop.
|
* continue grabbing, false to stop.
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <xcb/xcb.h>
|
#include <xcb/xcb.h>
|
||||||
|
|
||||||
int luaA_mousegrabber_stop(lua_State *);
|
int luaA_mousegrabber_stop(lua_State *);
|
||||||
|
void mousegrabber_handleevent(lua_State *, int, int, uint16_t);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||||
|
|
Loading…
Reference in New Issue