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:
Uli Schlachter 2013-03-29 16:07:13 +01:00
parent fc49e28025
commit ee1fe4dd59
6 changed files with 41 additions and 53 deletions

35
event.c
View File

@ -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;

View File

@ -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
View File

@ -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;

View File

@ -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

View File

@ -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.

View File

@ -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