mouse: add object_under_pointer

Signed-off-by: Gregor Best <farhaven@googlemail.com>
Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
Gregor Best 2008-12-03 23:03:44 +01:00 committed by Julien Danjou
parent 53d7062917
commit 0235d995c2
7 changed files with 115 additions and 77 deletions

44
event.c
View File

@ -89,50 +89,6 @@ event_handle_mouse_button(client_t *c,
} }
} }
/** Get a widget node from a wibox by coords.
* \param Container position.
* \param widgets The widget list.
* \param width The container width.
* \param height The container height.
* \param x X coordinate of the widget.
* \param y Y coordinate of the widget.
* \return A widget.
*/
static widget_t *
widget_getbycoords(position_t position, widget_node_array_t *widgets,
int width, int height, int16_t *x, int16_t *y)
{
int tmp;
/* Need to transform coordinates like it was top/bottom */
switch(position)
{
case Right:
tmp = *y;
*y = width - *x;
*x = tmp;
break;
case Left:
tmp = *y;
*y = *x;
*x = height - tmp;
break;
default:
break;
}
for(int i = 0; i < widgets->len; i++)
{
widget_node_t *w = &widgets->tab[i];
if(w->widget->isvisible &&
*x >= w->geometry.x && *x < w->geometry.x + w->geometry.width
&& *y >= w->geometry.y && *y < w->geometry.y + w->geometry.height)
return w->widget;
}
return NULL;
}
/** Handle an event with mouse grabber if needed /** Handle an event with mouse grabber if needed
* \param x The x coordinate. * \param x The x coordinate.
* \param y The y coordinate. * \param y The y coordinate.

View File

@ -9,6 +9,7 @@ local layout = require("awful.layout")
local tag = require("awful.tag") local tag = require("awful.tag")
local hooks = require("awful.hooks") local hooks = require("awful.hooks")
local aclient = require("awful.client") local aclient = require("awful.client")
local type = type
local math = math local math = math
local ipairs = ipairs local ipairs = ipairs
local capi = local capi =
@ -24,6 +25,27 @@ module("awful.mouse")
client = {} client = {}
function client_under_pointer()
local obj = capi.mouse.object_under_pointer()
if type(obj) == "client" then
return obj
end
end
function wibox_under_pointer()
local obj = capi.mouse.object_under_pointer()
if type(obj) == "wibox" then
return obj
end
end
function widget_under_pointer()
local obj, obj2 = capi.mouse.object_under_pointer()
if type(obj2) == "widget" then
return obj2
end
end
local function snap_outside(g, sg, snap) local function snap_outside(g, sg, snap)
if g.x < snap + sg.x + sg.width and g.x > sg.x + sg.width then if g.x < snap + sg.x + sg.width and g.x > sg.x + sg.width then
g.x = sg.x + sg.width g.x = sg.x + sg.width
@ -119,7 +141,7 @@ function client.move(c, snap)
elseif lay ~= layout.suit.magnifier then elseif lay ~= layout.suit.magnifier then
c.screen = capi.mouse.screen c.screen = capi.mouse.screen
if layout.get(c.screen) ~= layout.suit.floating then if layout.get(c.screen) ~= layout.suit.floating then
local c_u_m = capi.mouse.client_under_pointer() local c_u_m = client_under_pointer()
if c_u_m and not aclient.floating.get(c_u_m) then if c_u_m and not aclient.floating.get(c_u_m) then
if c_u_m ~= c then if c_u_m ~= c then
c:swap(c_u_m) c:swap(c_u_m)

73
mouse.c
View File

@ -24,6 +24,7 @@
#include "common/tokenize.h" #include "common/tokenize.h"
#include "screen.h" #include "screen.h"
#include "tag.h" #include "tag.h"
#include "wibox.h"
#include "common/xcursor.h" #include "common/xcursor.h"
extern awesome_t globalconf; extern awesome_t globalconf;
@ -47,11 +48,12 @@ button_delete(button_t **button)
* \param window The window to get position on. * \param window The window to get position on.
* \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 mask will be set to the current buttons state * \param mask will be set to the current buttons state
* \return true on success, false if an error occured * \return true on success, false if an error occured
**/ **/
bool bool
mouse_query_pointer(xcb_window_t window, int *x, int *y, uint16_t *mask) 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;
@ -66,6 +68,8 @@ mouse_query_pointer(xcb_window_t window, int *x, int *y, uint16_t *mask)
*y = query_ptr_r->win_y; *y = query_ptr_r->win_y;
if (mask) if (mask)
*mask = query_ptr_r->mask; *mask = query_ptr_r->mask;
if(child)
*child = query_ptr_r->child;
p_delete(&query_ptr_r); p_delete(&query_ptr_r);
@ -76,11 +80,12 @@ mouse_query_pointer(xcb_window_t window, int *x, int *y, uint16_t *mask)
* \param screen This will be set to the screen number the mouse is on. * \param screen This will be set to the screen number the mouse is on.
* \param x This will be set to the Pointer-x-coordinate relative to window. * \param x This will be set to the Pointer-x-coordinate relative to window.
* \param y This will be set to the Pointer-y-coordinate relative to window. * \param y This will be set to the Pointer-y-coordinate relative to window.
* \param child This will be set to the window under the pointer.
* \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 occured. * \return True on success, false if an error occured.
*/ */
static bool static bool
mouse_query_pointer_root(int *s, int *x, int *y, uint16_t *mask) mouse_query_pointer_root(int *s, int16_t *x, int16_t *y, xcb_window_t *child, uint16_t *mask)
{ {
for(int screen = 0; for(int screen = 0;
screen < xcb_setup_roots_length(xcb_get_setup(globalconf.connection)); screen < xcb_setup_roots_length(xcb_get_setup(globalconf.connection));
@ -88,7 +93,7 @@ mouse_query_pointer_root(int *s, int *x, int *y, uint16_t *mask)
{ {
xcb_window_t root = xutil_screen_get(globalconf.connection, screen)->root; xcb_window_t root = xutil_screen_get(globalconf.connection, screen)->root;
if(mouse_query_pointer(root, x, y, mask)) if(mouse_query_pointer(root, x, y, child, mask))
{ {
*s = screen; *s = screen;
return true; return true;
@ -324,13 +329,13 @@ luaA_mouse_index(lua_State *L)
{ {
size_t len; size_t len;
const char *attr = luaL_checklstring(L, 2, &len); const char *attr = luaL_checklstring(L, 2, &len);
int mouse_x, mouse_y, i; int16_t mouse_x, mouse_y;
int screen; int screen, i;
switch(a_tokenize(attr, len)) switch(a_tokenize(attr, len))
{ {
case A_TK_SCREEN: case A_TK_SCREEN:
if(!mouse_query_pointer_root(&screen, &mouse_x, &mouse_y, NULL)) if(!mouse_query_pointer_root(&screen, &mouse_x, &mouse_y, NULL, NULL))
return 0; return 0;
i = screen_getbycoord(screen, mouse_x, mouse_y); i = screen_getbycoord(screen, mouse_x, mouse_y);
@ -421,7 +426,8 @@ static int
luaA_mouse_coords(lua_State *L) luaA_mouse_coords(lua_State *L)
{ {
uint16_t mask; uint16_t mask;
int screen, x, y, mouse_x, mouse_y; int screen, x, y;
int16_t mouse_x, mouse_y;
if(lua_gettop(L) == 1) if(lua_gettop(L) == 1)
{ {
@ -429,7 +435,7 @@ luaA_mouse_coords(lua_State *L)
luaA_checktable(L, 1); luaA_checktable(L, 1);
if(!mouse_query_pointer_root(&screen, &mouse_x, &mouse_y, &mask)) if(!mouse_query_pointer_root(&screen, &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);
@ -440,7 +446,7 @@ luaA_mouse_coords(lua_State *L)
lua_pop(L, 1); lua_pop(L, 1);
} }
if(!mouse_query_pointer_root(&screen, &mouse_x, &mouse_y, &mask)) if(!mouse_query_pointer_root(&screen, &mouse_x, &mouse_y, NULL, &mask))
return 0; return 0;
return luaA_mouse_pushstatus(L, mouse_x, mouse_y, mask); return luaA_mouse_pushstatus(L, mouse_x, mouse_y, mask);
@ -453,30 +459,39 @@ luaA_mouse_coords(lua_State *L)
* \lreturn A client or nil. * \lreturn A client or nil.
*/ */
static int static int
luaA_mouse_client_under_pointer(lua_State *L) luaA_mouse_object_under_pointer(lua_State *L)
{ {
for(int screen = 0; int screen;
screen < xcb_setup_roots_length(xcb_get_setup(globalconf.connection)); int16_t mouse_x, mouse_y;
screen++) xcb_window_t child;
{
xcb_window_t root = xutil_screen_get(globalconf.connection, screen)->root;
xcb_query_pointer_reply_t *query_ptr_r;
xcb_query_pointer_cookie_t query_ptr_c = xcb_query_pointer_unchecked(globalconf.connection, root);
query_ptr_r = xcb_query_pointer_reply(globalconf.connection, query_ptr_c, NULL);
if(query_ptr_r) if(!mouse_query_pointer_root(&screen, &mouse_x, &mouse_y, &child, NULL))
return 0;
wibox_t *wibox;
client_t *client;
if((wibox = wibox_getbywin(child)))
{
luaA_wibox_userdata_new(L, wibox);
int16_t x = mouse_x - wibox->sw.geometry.x;
int16_t y = mouse_y - wibox->sw.geometry.y;
widget_t *widget = widget_getbycoords(wibox->position, &wibox->widgets,
wibox->sw.geometry.width,
wibox->sw.geometry.height,
&x, &y);
if(widget)
{ {
client_t *c = client_getbywin(query_ptr_r->child); luaA_widget_userdata_new(L, widget);
p_delete(&query_ptr_r); return 2;
if(c)
return luaA_client_userdata_new(L, c);
else
{
lua_pushnil(L);
return 1;
}
} }
return 1;
} }
else if((client = client_getbywin(child)))
return luaA_client_userdata_new(L, client);
return 0; return 0;
} }
@ -485,7 +500,7 @@ const struct luaL_reg awesome_mouse_methods[] =
{ "__index", luaA_mouse_index }, { "__index", luaA_mouse_index },
{ "__newindex", luaA_mouse_newindex }, { "__newindex", luaA_mouse_newindex },
{ "coords", luaA_mouse_coords }, { "coords", luaA_mouse_coords },
{ "client_under_pointer", luaA_mouse_client_under_pointer }, { "object_under_pointer", luaA_mouse_object_under_pointer },
{ NULL, NULL } { NULL, NULL }
}; };
const struct luaL_reg awesome_mouse_meta[] = const struct luaL_reg awesome_mouse_meta[] =

View File

@ -41,7 +41,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, int16_t *, int16_t *, xcb_window_t *, uint16_t *);
int luaA_mouse_pushstatus(lua_State *, 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)

View File

@ -40,11 +40,11 @@ mousegrabber_grab(xcb_cursor_t cursor)
screen < xcb_setup_roots_length(xcb_get_setup(globalconf.connection)); screen < xcb_setup_roots_length(xcb_get_setup(globalconf.connection));
screen++) screen++)
{ {
int x, y; int16_t x, y;
uint16_t mask; uint16_t mask;
root = xutil_screen_get(globalconf.connection, screen)->root; root = xutil_screen_get(globalconf.connection, screen)->root;
if(mouse_query_pointer(root, &x, &y, &mask)) if(mouse_query_pointer(root, &x, &y, NULL, &mask))
break; break;
} }

View File

@ -69,6 +69,50 @@ widget_calculate_offset(int barwidth, int widgetwidth, int offset, int alignment
return barwidth - offset - widgetwidth; return barwidth - offset - widgetwidth;
} }
/** Get a widget node from a wibox by coords.
* \param Container position.
* \param widgets The widget list.
* \param width The container width.
* \param height The container height.
* \param x X coordinate of the widget.
* \param y Y coordinate of the widget.
* \return A widget.
*/
widget_t *
widget_getbycoords(position_t position, widget_node_array_t *widgets,
int width, int height, int16_t *x, int16_t *y)
{
int tmp;
/* Need to transform coordinates like it was top/bottom */
switch(position)
{
case Right:
tmp = *y;
*y = width - *x;
*x = tmp;
break;
case Left:
tmp = *y;
*y = *x;
*x = height - tmp;
break;
default:
break;
}
for(int i = 0; i < widgets->len; i++)
{
widget_node_t *w = &widgets->tab[i];
if(w->widget->isvisible &&
*x >= w->geometry.x && *x < w->geometry.x + w->geometry.width
&& *y >= w->geometry.y && *y < w->geometry.y + w->geometry.height)
return w->widget;
}
return NULL;
}
/** Convert a Lua table to a list of widget nodet. /** Convert a Lua table to a list of widget nodet.
* \param L The Lua VM state. * \param L The Lua VM state.
* \param widgets The linked list of widget node. * \param widgets The linked list of widget node.

View File

@ -37,6 +37,7 @@ void widget_delete(widget_t **);
DO_RCNT(widget_t, widget, widget_delete) DO_RCNT(widget_t, widget, widget_delete)
int widget_calculate_offset(int, int, int, int); int widget_calculate_offset(int, int, int, int);
widget_t *widget_getbycoords(position_t, widget_node_array_t *, int, int, int16_t *, int16_t *);
void widget_render(widget_node_array_t *, draw_context_t *, xcb_gcontext_t, xcb_drawable_t, int, orientation_t, int, int, wibox_t *); void widget_render(widget_node_array_t *, draw_context_t *, xcb_gcontext_t, xcb_drawable_t, int, orientation_t, int, int, wibox_t *);
int luaA_widget_userdata_new(lua_State *, widget_t *); int luaA_widget_userdata_new(lua_State *, widget_t *);