mouse: move resize code to awful.mouse
Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
parent
33c7083617
commit
53a830aea1
|
@ -336,7 +336,7 @@ awful.hooks.manage.register(function (c)
|
|||
c:buttons({
|
||||
button({ }, 1, function (c) client.focus = c; c:raise() end),
|
||||
button({ modkey }, 1, awful.mouse.client.move),
|
||||
button({ modkey }, 3, function (c) c:mouse_resize() end)
|
||||
button({ modkey }, 3, awful.mouse.client.resize)
|
||||
})
|
||||
-- New client may not receive focus
|
||||
-- if they're not focusable, so set border anyway.
|
||||
|
|
11
client.c
11
client.c
|
@ -1601,6 +1601,17 @@ luaA_client_mouse_move(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/** Resize a client with mouse (DEPRECATED).
|
||||
* \param L The Lua VM state.
|
||||
* \return The number of pushed elements.
|
||||
*/
|
||||
static int
|
||||
luaA_client_mouse_resize(lua_State *L)
|
||||
{
|
||||
luaA_deprecate(L, "awful.mouse.client.resize()");
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct luaL_reg awesome_client_methods[] =
|
||||
{
|
||||
{ "get", luaA_client_get },
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
-- Grab environment we need
|
||||
local layout = require("awful.layout")
|
||||
local tag = require("awful.tag")
|
||||
local hooks = require("awful.hooks")
|
||||
local aclient = require("awful.client")
|
||||
local math = math
|
||||
|
@ -135,4 +136,212 @@ function client.move(c, snap)
|
|||
end, "fleur")
|
||||
end
|
||||
|
||||
--- Get a client corner coordinates.
|
||||
-- @param c The client to get corner from, focused one by default.
|
||||
-- @param corner The corner to use: auto, top_left, top_right, bottom_left,
|
||||
-- bottom_right. Default is auto, and auto find the nearest corner.
|
||||
-- @return Actual used corner and x and y coordinates.
|
||||
function client.corner(c, corner)
|
||||
local c = c or capi.client.focus
|
||||
if not c then return end
|
||||
|
||||
local g = c:geometry()
|
||||
|
||||
if not corner or corner == "auto" then
|
||||
local m_c = capi.mouse.coords()
|
||||
if math.abs(g.y - m_c.y) < math.abs(g.y + g.height - m_c.y) then
|
||||
if math.abs(g.x - m_c.x) < math.abs(g.x + g.width - m_c.x) then
|
||||
corner = "top_left"
|
||||
else
|
||||
corner = "top_right"
|
||||
end
|
||||
else
|
||||
if math.abs(g.x - m_c.x) < math.abs(g.x + g.width - m_c.x) then
|
||||
corner = "bottom_left"
|
||||
else
|
||||
corner = "bottom_right"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local x, y
|
||||
if corner == "top_right" then
|
||||
x = g.x + g.width
|
||||
y = g.y
|
||||
elseif corner == "top_left" then
|
||||
x = g.x
|
||||
y = g.y
|
||||
elseif corner == "bottom_left" then
|
||||
x = g.x
|
||||
y = g.y + g.height
|
||||
else
|
||||
x = g.x + g.width
|
||||
y = g.y + g.height
|
||||
end
|
||||
|
||||
return corner, x, y
|
||||
end
|
||||
|
||||
local function client_resize_magnifier(c, corner)
|
||||
local corner, x, y = client.corner(c, corner)
|
||||
capi.mouse.coords({ x = x, y = y })
|
||||
|
||||
local wa = capi.screen[c.screen].workarea
|
||||
local center_x = wa.x + wa.width / 2
|
||||
local center_y = wa.y + wa.height / 2
|
||||
local maxdist_pow = (wa.width^2 + wa.height^2) / 4
|
||||
|
||||
capi.mousegrabber.run(function (mouse)
|
||||
for k, v in ipairs(mouse.buttons) do
|
||||
if v then
|
||||
local dx = center_x - mouse.x
|
||||
local dy = center_y - mouse.y
|
||||
local dist = dx^2 + dy^2
|
||||
|
||||
-- New master width factor
|
||||
local mwfact = dist / maxdist_pow
|
||||
tag.setmwfact(math.min(math.max(0.01, mwfact), 0.99), c.screen)
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end, corner .. "_corner")
|
||||
end
|
||||
|
||||
local function client_resize_tiled(c, lay)
|
||||
local wa = capi.screen[c.screen].workarea
|
||||
local mwfact = tag.selected(c.screen).mwfact
|
||||
local cursor
|
||||
if lay == "tile" then
|
||||
capi.mouse.coords({ x = wa.x + wa.width * mwfact })
|
||||
cursor = "sb_h_double_arrow"
|
||||
elseif lay == "tileleft" then
|
||||
capi.mouse.coords({ x = wa.x + wa.width * (1 - mwfact) })
|
||||
cursor = "sb_h_double_arrow"
|
||||
elseif lay == "tilebottom" then
|
||||
capi.mouse.coords({ y = wa.y + wa.height * mwfact })
|
||||
cursor = "sb_v_double_arrow"
|
||||
else
|
||||
capi.mouse.coords({ y = wa.y + wa.height * (1 - mwfact) })
|
||||
cursor = "sb_v_double_arrow"
|
||||
end
|
||||
|
||||
capi.mousegrabber.run(function (mouse)
|
||||
for k, v in ipairs(mouse.buttons) do
|
||||
if v then
|
||||
local fact_x = (mouse.x - wa.x) / wa.width
|
||||
local fact_y = (mouse.y - wa.y) / wa.height
|
||||
local mwfact
|
||||
|
||||
if lay == "tile" then
|
||||
mwfact = fact_x
|
||||
elseif lay == "tileleft" then
|
||||
mwfact = 1 - fact_x
|
||||
elseif lay == "tilebottom" then
|
||||
mwfact = fact_y
|
||||
else
|
||||
mwfact = 1 - fact_y
|
||||
end
|
||||
|
||||
tag.setmwfact(math.min(math.max(mwfact, 0.01), 0.99), c.screen)
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end, cursor)
|
||||
end
|
||||
|
||||
local function client_resize_floating(c, corner)
|
||||
local corner, x, y = client.corner(c, corner)
|
||||
local fixed_x, fixed_y
|
||||
local g = c:geometry()
|
||||
|
||||
-- Warp mouse pointer
|
||||
capi.mouse.coords({ x = x, y = y })
|
||||
|
||||
local fixed_x, fixed_y
|
||||
|
||||
capi.mousegrabber.run(function (mouse)
|
||||
for k, v in ipairs(mouse.buttons) do
|
||||
if v then
|
||||
-- Ignore screen changes
|
||||
if not c.floating
|
||||
and capi.mouse.screen ~= c.screen then
|
||||
return true
|
||||
end
|
||||
|
||||
local ng
|
||||
if corner == "bottom_right" then
|
||||
ng = { width = mouse.x - g.x,
|
||||
height = mouse.y - g.y }
|
||||
elseif corner == "bottom_left" then
|
||||
ng = { x = mouse.x,
|
||||
width = (g.x + g.width) - mouse.x,
|
||||
height = mouse.y - g.y }
|
||||
elseif corner == "top_left" then
|
||||
ng = { x = mouse.x,
|
||||
width = (g.x + g.width) - mouse.x,
|
||||
y = mouse.y,
|
||||
height = (g.y + g.height) - mouse.y }
|
||||
else
|
||||
ng = { width = mouse.x - g.x,
|
||||
y = mouse.y,
|
||||
height = (g.y + g.height) - mouse.y }
|
||||
end
|
||||
if ng.width <= 0 then ng.width = nil end
|
||||
if ng.height <= 0 then ng.height = nil end
|
||||
c:geometry({ width = ng.width, height = ng.height })
|
||||
-- Get real geometry that has been applied
|
||||
-- in case we honor size hints
|
||||
-- XXX: This should be rewritten when size
|
||||
-- hints are available from Lua.
|
||||
local rg = c:geometry()
|
||||
|
||||
if corner == "bottom_right" then
|
||||
ng = {}
|
||||
elseif corner == "bottom_left" then
|
||||
ng = { x = (g.x + g.width) - rg.width }
|
||||
elseif corner == "top_left" then
|
||||
ng = { x = (g.x + g.width) - rg.width,
|
||||
y = (g.y + g.height) - rg.height }
|
||||
else
|
||||
ng = { y = (g.y + g.height) - rg.height }
|
||||
end
|
||||
c:geometry({ x = ng.x, y = ng.y })
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end, corner .. "_corner")
|
||||
end
|
||||
|
||||
--- Resize a client.
|
||||
-- @param c The client to resize, or the focused one by default.
|
||||
-- @param corner The corner to grab on resize. Auto detected by default.
|
||||
function client.resize(c, corner)
|
||||
local c = c or capi.client.focus
|
||||
|
||||
if not c then return end
|
||||
|
||||
if c.fullscreen
|
||||
or c.type == "desktop"
|
||||
or c.type == "splash"
|
||||
or c.type == "dock" then
|
||||
return
|
||||
end
|
||||
|
||||
local lay = layout.get(c.screen)
|
||||
|
||||
if lay == "floating" or c.floating then
|
||||
return client_resize_floating(c, corner)
|
||||
elseif lay == "tile"
|
||||
or lay == "tileleft"
|
||||
or lay == "tilebottom"
|
||||
or lay == "tiletop" then
|
||||
return client_resize_tiled(c, lay)
|
||||
elseif lay == "magnifier" then
|
||||
return client_resize_magnifier(c, corner)
|
||||
end
|
||||
end
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80
|
||||
|
|
|
@ -19,6 +19,7 @@ local beautiful = require("beautiful")
|
|||
local hooks = require("awful.hooks")
|
||||
local util = require("awful.util")
|
||||
local widget = require("awful.widget")
|
||||
local mouse = require("awful.mouse")
|
||||
|
||||
--- Titlebar module for awful
|
||||
module("awful.titlebar")
|
||||
|
@ -54,9 +55,9 @@ function add(c, args)
|
|||
-- Redirect relevant events to the client the titlebar belongs to
|
||||
local bts =
|
||||
{
|
||||
capi.button({ }, 1, function (t) capi.client.focus = t.client t.client:raise() t.client:mouse_move() end),
|
||||
capi.button({ args.modkey }, 1, function (t) t.client:mouse_move() end),
|
||||
capi.button({ args.modkey }, 3, function (t) t.client:mouse_resize() end)
|
||||
capi.button({ }, 1, function (t) capi.client.focus = t.client t.client:raise() mouse.client.move(t.client) end),
|
||||
capi.button({ args.modkey }, 1, function (t) mouse.client.move(t.client) end),
|
||||
capi.button({ args.modkey }, 3, function (t) mouse.client.resize(t.client) end)
|
||||
}
|
||||
title:buttons(bts)
|
||||
function title.mouse_enter(s) hooks.user.call('mouse_enter', c) end
|
||||
|
@ -85,8 +86,8 @@ function add(c, args)
|
|||
local bts =
|
||||
{
|
||||
capi.button({ }, 1, nil, function (t) t.client:kill() end),
|
||||
capi.button({ args.modkey }, 1, function (t) t.client:mouse_move() end),
|
||||
capi.button({ args.modkey }, 3, function (t) t.client:mouse_resize() end)
|
||||
capi.button({ args.modkey }, 1, function (t) mouse.client.move(t.client) end),
|
||||
capi.button({ args.modkey }, 3, function (t) mouse.client.resize(t.client) end)
|
||||
}
|
||||
if close then
|
||||
local rbts = close:buttons()
|
||||
|
|
586
mouse.c
586
mouse.c
|
@ -30,44 +30,12 @@
|
|||
#include "layouts/magnifier.h"
|
||||
#include "common/xcursor.h"
|
||||
|
||||
#define MOUSEMASK (XCB_EVENT_MASK_BUTTON_PRESS \
|
||||
| XCB_EVENT_MASK_BUTTON_RELEASE \
|
||||
| XCB_EVENT_MASK_POINTER_MOTION)
|
||||
|
||||
extern awesome_t globalconf;
|
||||
|
||||
DO_LUA_NEW(static, button_t, button, "button", button_ref)
|
||||
DO_LUA_GC(button_t, button, "button", button_unref)
|
||||
DO_LUA_EQ(button_t, button, "button")
|
||||
|
||||
/** Define corners. */
|
||||
typedef enum
|
||||
{
|
||||
AutoCorner,
|
||||
TopRightCorner,
|
||||
TopLeftCorner,
|
||||
BottomLeftCorner,
|
||||
BottomRightCorner
|
||||
} corner_t;
|
||||
|
||||
/** Convert a corner name into a corner type.
|
||||
* \param str A string.
|
||||
* \param len String length.
|
||||
* \return A corner type.
|
||||
*/
|
||||
static corner_t
|
||||
a_strtocorner(const char *str, size_t len)
|
||||
{
|
||||
switch (a_tokenize(str, len))
|
||||
{
|
||||
case A_TK_BOTTOMRIGHT: return BottomRightCorner;
|
||||
case A_TK_BOTTOMLEFT: return BottomLeftCorner;
|
||||
case A_TK_TOPLEFT: return TopLeftCorner;
|
||||
case A_TK_TOPRIGHT: return TopRightCorner;
|
||||
default: return AutoCorner;
|
||||
}
|
||||
}
|
||||
|
||||
/** Delete a button.
|
||||
* \param button The button to destroy.
|
||||
*/
|
||||
|
@ -79,75 +47,6 @@ button_delete(button_t **button)
|
|||
p_delete(button);
|
||||
}
|
||||
|
||||
/** Set coordinates to a corner of an area.
|
||||
*
|
||||
* \param a The area.
|
||||
* \param[in,out] x The x coordinate.
|
||||
* \param[in,out] y The y coordinate.
|
||||
* \param corner The corner to snap to.
|
||||
* \return The corner the coordinates have been set to. If corner != AutoCorner
|
||||
* this is always equal to \em corner.
|
||||
*
|
||||
* \todo rename/move this is still awkward and might be useful somewhere else.
|
||||
*/
|
||||
static corner_t
|
||||
mouse_snap_to_corner(area_t a, int *x, int *y, corner_t corner)
|
||||
{
|
||||
int top, bottom, left, right;
|
||||
|
||||
top = AREA_TOP(a);
|
||||
bottom = AREA_BOTTOM(a);
|
||||
left = AREA_LEFT(a);
|
||||
right = AREA_RIGHT(a);
|
||||
|
||||
/* figure out the nearser corner */
|
||||
if(corner == AutoCorner)
|
||||
{
|
||||
if(abs(top - *y) < abs(bottom - *y))
|
||||
{
|
||||
if(abs(left - *x) < abs(right - *x))
|
||||
corner = TopLeftCorner;
|
||||
else
|
||||
corner = TopRightCorner;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(abs(left - *x) < abs(right - *x))
|
||||
corner = BottomLeftCorner;
|
||||
else
|
||||
corner = BottomRightCorner;
|
||||
}
|
||||
}
|
||||
|
||||
switch(corner)
|
||||
{
|
||||
case TopRightCorner:
|
||||
*x = right;
|
||||
*y = top;
|
||||
break;
|
||||
|
||||
case TopLeftCorner:
|
||||
*x = left;
|
||||
*y = top;
|
||||
break;
|
||||
|
||||
case BottomLeftCorner:
|
||||
*x = left;
|
||||
*y = bottom;
|
||||
break;
|
||||
|
||||
case BottomRightCorner:
|
||||
*x = right;
|
||||
*y = bottom;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return corner;
|
||||
}
|
||||
|
||||
/** Get the pointer position.
|
||||
* \param window The window to get position on.
|
||||
* \param x will be set to the Pointer-x-coordinate relative to window
|
||||
|
@ -202,38 +101,6 @@ mouse_query_pointer_root(int *s, int *x, int *y, uint16_t *mask)
|
|||
return false;
|
||||
}
|
||||
|
||||
/** Grab the Pointer.
|
||||
* \param window The window grabbed.
|
||||
* \param cursor The cursor to display.
|
||||
* \return True on success, false if an error occured.
|
||||
*/
|
||||
static bool
|
||||
mouse_grab_pointer(xcb_window_t window, xcb_cursor_t cursor)
|
||||
{
|
||||
xcb_grab_pointer_cookie_t grab_ptr_c;
|
||||
xcb_grab_pointer_reply_t *grab_ptr_r;
|
||||
|
||||
grab_ptr_c = xcb_grab_pointer_unchecked(globalconf.connection, false, window,
|
||||
MOUSEMASK, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC,
|
||||
window, cursor, XCB_CURRENT_TIME);
|
||||
grab_ptr_r = xcb_grab_pointer_reply(globalconf.connection, grab_ptr_c, NULL);
|
||||
|
||||
if(!grab_ptr_r)
|
||||
return false;
|
||||
|
||||
p_delete(&grab_ptr_r);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Ungrab the Pointer
|
||||
*/
|
||||
static inline void
|
||||
mouse_ungrab_pointer(void)
|
||||
{
|
||||
xcb_ungrab_pointer(globalconf.connection, XCB_CURRENT_TIME);
|
||||
}
|
||||
|
||||
/** Set the pointer position.
|
||||
* \param window The destination window.
|
||||
* \param x X-coordinate inside window.
|
||||
|
@ -246,459 +113,6 @@ mouse_warp_pointer(xcb_window_t window, int x, int y)
|
|||
0, 0, 0, 0, x, y );
|
||||
}
|
||||
|
||||
/** Utility function to help with mouse-dragging
|
||||
*
|
||||
* \param x set to x-coordinate of the last event on return
|
||||
* \param y set to y-coordinate of the last event on return
|
||||
* \return true if an motion event was received
|
||||
* false if an button release event was received
|
||||
*/
|
||||
static bool
|
||||
mouse_track_mouse_drag(int *x, int *y)
|
||||
{
|
||||
xcb_generic_event_t *ev;
|
||||
xcb_motion_notify_event_t *ev_motion;
|
||||
xcb_button_release_event_t *ev_button;
|
||||
|
||||
while(true)
|
||||
while((ev = xcb_wait_for_event(globalconf.connection)))
|
||||
switch((ev->response_type & 0x7F))
|
||||
{
|
||||
|
||||
case XCB_MOTION_NOTIFY:
|
||||
ev_motion = (xcb_motion_notify_event_t*) ev;
|
||||
*x = ev_motion->event_x;
|
||||
*y = ev_motion->event_y;
|
||||
p_delete(&ev);
|
||||
return true;
|
||||
|
||||
case XCB_BUTTON_RELEASE:
|
||||
ev_button = (xcb_button_release_event_t*) ev;
|
||||
*x = ev_button->event_x;
|
||||
*y = ev_button->event_y;
|
||||
p_delete(&ev);
|
||||
return false;
|
||||
|
||||
default:
|
||||
xcb_event_handle(&globalconf.evenths, ev);
|
||||
p_delete(&ev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** Resize a floating client with the mouse.
|
||||
* \param c The client to resize.
|
||||
* \param corner The corner to resize with.
|
||||
*/
|
||||
static void
|
||||
mouse_client_resize_floating(client_t *c, corner_t corner)
|
||||
{
|
||||
xcb_screen_t *screen;
|
||||
/* one corner of the client has a fixed position */
|
||||
int fixed_x, fixed_y;
|
||||
/* the other is moved with the mouse */
|
||||
int mouse_x = 0, mouse_y = 0;
|
||||
xcb_cursor_t cursor;
|
||||
int top, bottom, left, right;
|
||||
|
||||
/* do not resize fixed client */
|
||||
if(client_isfixed(c))
|
||||
return;
|
||||
|
||||
screen = xutil_screen_get(globalconf.connection, c->phys_screen);
|
||||
|
||||
/* get current mouse position */
|
||||
mouse_query_pointer(screen->root, &mouse_x, &mouse_y, NULL);
|
||||
|
||||
top = c->geometry.y;
|
||||
bottom = top + c->geometry.height;
|
||||
left = c->geometry.x;
|
||||
right = left + c->geometry.width;
|
||||
|
||||
/* figure out which corner to move */
|
||||
corner = mouse_snap_to_corner(c->geometry, &mouse_x, &mouse_y, corner);
|
||||
|
||||
/* the opposite corner is fixed */
|
||||
fixed_x = (mouse_x == left) ? right : left;
|
||||
fixed_y = (mouse_y == top) ? bottom : top;
|
||||
|
||||
/* select cursor */
|
||||
switch(corner)
|
||||
{
|
||||
default:
|
||||
cursor = xcursor_new(globalconf.connection, XC_top_left_corner);
|
||||
break;
|
||||
case TopRightCorner:
|
||||
cursor = xcursor_new(globalconf.connection, XC_top_right_corner);
|
||||
break;
|
||||
case BottomLeftCorner:
|
||||
cursor = xcursor_new(globalconf.connection, XC_bottom_left_corner);
|
||||
break;
|
||||
case BottomRightCorner:
|
||||
cursor = xcursor_new(globalconf.connection, XC_bottom_right_corner);
|
||||
break;
|
||||
}
|
||||
|
||||
/* grab the pointer */
|
||||
if(!mouse_grab_pointer(screen->root, cursor))
|
||||
return;
|
||||
|
||||
/* set pointer to the moveable corner */
|
||||
mouse_warp_pointer(screen->root, mouse_x, mouse_y);
|
||||
|
||||
/* for each motion event */
|
||||
while(mouse_track_mouse_drag(&mouse_x, &mouse_y))
|
||||
{
|
||||
/* new client geometry */
|
||||
area_t geo = { .x = MIN(fixed_x, mouse_x),
|
||||
.y = MIN(fixed_y, mouse_y),
|
||||
.width = (MAX(fixed_x, mouse_x) - MIN(fixed_x, mouse_x)),
|
||||
.height = (MAX(fixed_y, mouse_y) - MIN(fixed_y, mouse_y)) };
|
||||
/* new moveable corner */
|
||||
corner_t new_corner;
|
||||
|
||||
if(mouse_x == AREA_LEFT(geo))
|
||||
new_corner = (mouse_y == AREA_TOP(geo)) ? TopLeftCorner : BottomLeftCorner;
|
||||
else
|
||||
new_corner = (mouse_y == AREA_TOP(geo)) ? TopRightCorner : BottomRightCorner;
|
||||
|
||||
/* update cursor */
|
||||
if(corner != new_corner)
|
||||
{
|
||||
corner = new_corner;
|
||||
|
||||
switch(corner)
|
||||
{
|
||||
default: cursor = xcursor_new(globalconf.connection, XC_top_left_corner); break;
|
||||
case TopRightCorner: cursor = xcursor_new(globalconf.connection, XC_top_right_corner); break;
|
||||
case BottomLeftCorner: cursor = xcursor_new(globalconf.connection, XC_bottom_left_corner); break;
|
||||
case BottomRightCorner: cursor = xcursor_new(globalconf.connection, XC_bottom_right_corner); break;
|
||||
}
|
||||
|
||||
xcb_change_active_pointer_grab(globalconf.connection, cursor,
|
||||
XCB_CURRENT_TIME, MOUSEMASK);
|
||||
}
|
||||
|
||||
if(c->hassizehints && c->honorsizehints)
|
||||
{
|
||||
int dx, dy;
|
||||
|
||||
/* apply size hints */
|
||||
geo = client_geometry_hints(c, geo);
|
||||
|
||||
/* get the nonmoveable corner back onto fixed_x,fixed_y */
|
||||
switch(corner)
|
||||
{
|
||||
default /* TopLeftCorner */:
|
||||
dx = fixed_x - AREA_RIGHT(geo);
|
||||
dy = fixed_y - AREA_BOTTOM(geo);
|
||||
break;
|
||||
case TopRightCorner:
|
||||
dx = fixed_x - AREA_LEFT(geo);
|
||||
dy = fixed_y - AREA_BOTTOM(geo);
|
||||
break;
|
||||
case BottomRightCorner:
|
||||
dx = fixed_x - AREA_LEFT(geo);
|
||||
dy = fixed_y - AREA_TOP(geo);
|
||||
break;
|
||||
case BottomLeftCorner:
|
||||
dx = fixed_x - AREA_RIGHT(geo);
|
||||
dy = fixed_y - AREA_TOP(geo);
|
||||
break;
|
||||
}
|
||||
|
||||
geo.x += dx;
|
||||
geo.y += dy;
|
||||
}
|
||||
|
||||
/* resize the client */
|
||||
client_resize(c, geo, false);
|
||||
|
||||
/* refresh live */
|
||||
wibox_refresh();
|
||||
xcb_flush(globalconf.connection);
|
||||
}
|
||||
|
||||
/* relase pointer */
|
||||
mouse_ungrab_pointer();
|
||||
|
||||
}
|
||||
|
||||
/** Resize the master column/row of a tiled layout
|
||||
* \param c A client on the tag/layout to resize.
|
||||
*/
|
||||
static void
|
||||
mouse_client_resize_tiled(client_t *c)
|
||||
{
|
||||
xcb_screen_t *screen;
|
||||
/* screen area modulo wibox */
|
||||
area_t area;
|
||||
/* current tag */
|
||||
tag_t *tag;
|
||||
/* current layout */
|
||||
layout_t *layout;
|
||||
|
||||
int mouse_x = 0, mouse_y = 0;
|
||||
xcb_cursor_t cursor;
|
||||
|
||||
screen = xutil_screen_get(globalconf.connection, c->phys_screen);
|
||||
tag = tags_get_current(c->screen)[0];
|
||||
layout = tag->layout;
|
||||
|
||||
area = screen_area_get(tag->screen,
|
||||
&globalconf.screens[tag->screen].wiboxes,
|
||||
&globalconf.screens[tag->screen].padding,
|
||||
true);
|
||||
|
||||
mouse_query_pointer(screen->root, &mouse_x, &mouse_y, NULL);
|
||||
|
||||
/* select initial pointer position */
|
||||
if(layout == layout_tile)
|
||||
{
|
||||
mouse_x = area.x + area.width * tag->mwfact;
|
||||
cursor = xcursor_new(globalconf.connection, XC_bottom_right_corner);
|
||||
}
|
||||
else if(layout == layout_tileleft)
|
||||
{
|
||||
mouse_x = area.x + area.width * (1. - tag->mwfact);
|
||||
cursor = xcursor_new(globalconf.connection, XC_sb_h_double_arrow);
|
||||
}
|
||||
else if(layout == layout_tilebottom)
|
||||
{
|
||||
mouse_y = area.y + area.height * tag->mwfact;
|
||||
cursor = xcursor_new(globalconf.connection, XC_sb_v_double_arrow);
|
||||
}
|
||||
else if(layout == layout_tiletop)
|
||||
{
|
||||
mouse_y = area.y + area.height * (1. - tag->mwfact);
|
||||
cursor = xcursor_new(globalconf.connection, XC_sb_v_double_arrow);
|
||||
}
|
||||
else
|
||||
return;
|
||||
|
||||
/* grab the pointer */
|
||||
if(!mouse_grab_pointer(screen->root, cursor))
|
||||
return;
|
||||
|
||||
/* set pointer to the moveable border */
|
||||
mouse_warp_pointer(screen->root, mouse_x, mouse_y);
|
||||
|
||||
xcb_flush(globalconf.connection);
|
||||
|
||||
/* for each motion event */
|
||||
while(mouse_track_mouse_drag(&mouse_x, &mouse_y))
|
||||
{
|
||||
double mwfact = 0, fact_x, fact_y;
|
||||
|
||||
/* calculate new master / rest ratio */
|
||||
fact_x = (double) (mouse_x - area.x) / area.width;
|
||||
fact_y = (double) (mouse_y - area.y) / area.height;
|
||||
|
||||
if(layout == layout_tile)
|
||||
mwfact = fact_x;
|
||||
else if(layout == layout_tileleft)
|
||||
mwfact = 1. - fact_x;
|
||||
else if(layout == layout_tilebottom)
|
||||
mwfact = fact_y;
|
||||
else if(layout == layout_tiletop)
|
||||
mwfact = 1. - fact_y;
|
||||
|
||||
/* keep mwfact within reasonable bounds */
|
||||
mwfact = MIN(MAX( 0.01, mwfact), 0.99);
|
||||
|
||||
/* refresh layout */
|
||||
if(fabs(tag->mwfact - mwfact) >= 0.01)
|
||||
{
|
||||
tag->mwfact = mwfact;
|
||||
globalconf.screens[tag->screen].need_arrange = true;
|
||||
layout_refresh();
|
||||
wibox_refresh();
|
||||
xcb_flush(globalconf.connection);
|
||||
}
|
||||
}
|
||||
|
||||
/* relase pointer */
|
||||
mouse_ungrab_pointer();
|
||||
}
|
||||
|
||||
/** Resize the master client in mangifier layout
|
||||
* \param c The client to resize.
|
||||
*/
|
||||
static void
|
||||
mouse_client_resize_magnified(client_t *c)
|
||||
{
|
||||
/* screen area modulo wibox */
|
||||
area_t area;
|
||||
/* center of area */
|
||||
int center_x, center_y;
|
||||
/* max. distance from the center */
|
||||
double maxdist;
|
||||
/* mouse position */
|
||||
int mouse_x = 0, mouse_y = 0;
|
||||
/* cursor while grabbing */
|
||||
xcb_cursor_t cursor;
|
||||
corner_t corner = AutoCorner;
|
||||
/* current tag */
|
||||
tag_t *tag;
|
||||
xcb_window_t root;
|
||||
|
||||
tag = tags_get_current(c->screen)[0];
|
||||
|
||||
root = xutil_screen_get(globalconf.connection, c->phys_screen)->root;
|
||||
|
||||
area = screen_area_get(tag->screen,
|
||||
&globalconf.screens[tag->screen].wiboxes,
|
||||
&globalconf.screens[tag->screen].padding,
|
||||
true);
|
||||
|
||||
center_x = area.x + (round(area.width / 2.));
|
||||
center_y = area.y + (round(area.height / 2.));
|
||||
|
||||
maxdist = round(sqrt((area.width*area.width) + (area.height*area.height)) / 2.);
|
||||
|
||||
root = xutil_screen_get(globalconf.connection, c->phys_screen)->root;
|
||||
|
||||
if(!mouse_query_pointer(root, &mouse_x, &mouse_y, NULL))
|
||||
return;
|
||||
|
||||
/* select corner */
|
||||
corner = mouse_snap_to_corner(c->geometry, &mouse_x, &mouse_y, corner);
|
||||
|
||||
/* select cursor */
|
||||
switch(corner)
|
||||
{
|
||||
default:
|
||||
cursor = xcursor_new(globalconf.connection, XC_top_left_corner);
|
||||
break;
|
||||
case TopRightCorner:
|
||||
cursor = xcursor_new(globalconf.connection, XC_top_right_corner);
|
||||
break;
|
||||
case BottomLeftCorner:
|
||||
cursor = xcursor_new(globalconf.connection, XC_bottom_left_corner);
|
||||
break;
|
||||
case BottomRightCorner:
|
||||
cursor = xcursor_new(globalconf.connection, XC_bottom_right_corner);
|
||||
break;
|
||||
}
|
||||
|
||||
/* grab pointer */
|
||||
if(!mouse_grab_pointer(root, cursor))
|
||||
return;
|
||||
|
||||
/* move pointer to corner */
|
||||
mouse_warp_pointer(root, mouse_x, mouse_y);
|
||||
|
||||
/* for each motion event */
|
||||
while(mouse_track_mouse_drag(&mouse_x, &mouse_y))
|
||||
{
|
||||
/* \todo keep pointer on screen diagonals */
|
||||
double mwfact, dist, dx, dy;
|
||||
|
||||
/* calc distance from the center */
|
||||
dx = center_x - mouse_x;
|
||||
dy = center_y - mouse_y;
|
||||
dist = sqrt((dx * dx) + (dy * dy));
|
||||
|
||||
/* new master/rest ratio */
|
||||
mwfact = (dist * dist) / (maxdist * maxdist);
|
||||
|
||||
/* keep mwfact within reasonable bounds */
|
||||
mwfact = MIN(MAX( 0.01, mwfact), 0.99);
|
||||
|
||||
/* refresh the layout */
|
||||
if(fabs(tag->mwfact - mwfact) >= 0.01)
|
||||
{
|
||||
tag->mwfact = mwfact;
|
||||
globalconf.screens[tag->screen].need_arrange = true;
|
||||
layout_refresh();
|
||||
wibox_refresh();
|
||||
xcb_flush(globalconf.connection);
|
||||
}
|
||||
}
|
||||
|
||||
/* ungrab pointer */
|
||||
mouse_ungrab_pointer();
|
||||
}
|
||||
|
||||
/** Resize a client with the mouse.
|
||||
* \param c The client to resize.
|
||||
* \param corner The corner to use.
|
||||
*/
|
||||
static void
|
||||
mouse_client_resize(client_t *c, corner_t corner)
|
||||
{
|
||||
int n, screen;
|
||||
tag_t **curtags;
|
||||
layout_t *layout;
|
||||
xcb_screen_t *s;
|
||||
|
||||
if(c->isfullscreen
|
||||
|| c->type == WINDOW_TYPE_DESKTOP
|
||||
|| c->type == WINDOW_TYPE_SPLASH
|
||||
|| c->type == WINDOW_TYPE_DOCK)
|
||||
return;
|
||||
|
||||
curtags = tags_get_current(c->screen);
|
||||
layout = curtags[0]->layout;
|
||||
s = xutil_screen_get(globalconf.connection, c->phys_screen);
|
||||
|
||||
/* only handle floating, tiled and magnifier layouts */
|
||||
if(layout == layout_floating || client_isfloating(c))
|
||||
mouse_client_resize_floating(c, corner);
|
||||
else if(layout == layout_tile || layout == layout_tileleft
|
||||
|| layout == layout_tilebottom || layout == layout_tiletop)
|
||||
{
|
||||
screen = c->screen;
|
||||
for(n = 0, c = globalconf.clients; c; c = c->next)
|
||||
if(IS_TILED(c, screen))
|
||||
n++;
|
||||
|
||||
/* only masters on this screen? */
|
||||
if(n <= curtags[0]->nmaster)
|
||||
goto bailout;
|
||||
|
||||
/* no tiled clients on this screen? */
|
||||
for(c = globalconf.clients; c && !IS_TILED(c, screen); c = c->next);
|
||||
if(!c)
|
||||
goto bailout;
|
||||
|
||||
mouse_client_resize_tiled(c);
|
||||
}
|
||||
else if(layout == layout_magnifier)
|
||||
mouse_client_resize_magnified(c);
|
||||
|
||||
bailout:
|
||||
p_delete(&curtags);
|
||||
}
|
||||
|
||||
/** Resize a client with mouse.
|
||||
* \param L The Lua VM state.
|
||||
*
|
||||
* \luastack
|
||||
* \lvalue A client.
|
||||
* \lparam An optional table with keys: `corner', such as bottomleft,
|
||||
* topright, etc, to specify which corner to grab (default to auto).
|
||||
*/
|
||||
int
|
||||
luaA_client_mouse_resize(lua_State *L)
|
||||
{
|
||||
client_t **c = luaA_checkudata(L, 1, "client");
|
||||
corner_t corner = AutoCorner;
|
||||
size_t len;
|
||||
const char *buf;
|
||||
|
||||
if(lua_gettop(L) == 2 && !lua_isnil(L, 2))
|
||||
{
|
||||
luaA_checktable(L, 2);
|
||||
buf = luaA_getopt_lstring(L, 2, "corner", "auto", &len);
|
||||
corner = a_strtocorner(buf, len);
|
||||
}
|
||||
|
||||
mouse_client_resize(*c, corner);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Create a new mouse button bindings.
|
||||
* \param L The Lua VM state.
|
||||
* \return The number of elements pushed on stack.
|
||||
|
|
2
mouse.h
2
mouse.h
|
@ -47,8 +47,6 @@ int luaA_mouse_pushstatus(lua_State *, int, int, uint16_t);
|
|||
DO_RCNT(button_t, button, button_delete)
|
||||
ARRAY_FUNCS(button_t *, button, button_unref)
|
||||
|
||||
int luaA_client_mouse_resize(lua_State *);
|
||||
|
||||
int luaA_button_array_get(lua_State *, button_array_t *);
|
||||
void luaA_button_array_set(lua_State *, int idx, button_array_t *);
|
||||
|
||||
|
|
|
@ -140,10 +140,6 @@ property_update_wm_normal_hints(client_t *c, xcb_get_property_reply_t *reply)
|
|||
}
|
||||
else
|
||||
c->minax = c->maxax = c->minay = c->maxay = 0;
|
||||
|
||||
c->hassizehints = !(!c->basew && !c->baseh && !c->incw && !c->inch
|
||||
&& !c->maxw && !c->maxh && !c->minw && !c->minh
|
||||
&& !c->minax && !c->maxax && !c->minax && !c->minay);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
Loading…
Reference in New Issue