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({
|
c:buttons({
|
||||||
button({ }, 1, function (c) client.focus = c; c:raise() end),
|
button({ }, 1, function (c) client.focus = c; c:raise() end),
|
||||||
button({ modkey }, 1, awful.mouse.client.move),
|
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
|
-- New client may not receive focus
|
||||||
-- if they're not focusable, so set border anyway.
|
-- 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;
|
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[] =
|
const struct luaL_reg awesome_client_methods[] =
|
||||||
{
|
{
|
||||||
{ "get", luaA_client_get },
|
{ "get", luaA_client_get },
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
-- Grab environment we need
|
-- Grab environment we need
|
||||||
local layout = require("awful.layout")
|
local layout = require("awful.layout")
|
||||||
|
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 math = math
|
local math = math
|
||||||
|
@ -135,4 +136,212 @@ function client.move(c, snap)
|
||||||
end, "fleur")
|
end, "fleur")
|
||||||
end
|
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
|
-- 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 hooks = require("awful.hooks")
|
||||||
local util = require("awful.util")
|
local util = require("awful.util")
|
||||||
local widget = require("awful.widget")
|
local widget = require("awful.widget")
|
||||||
|
local mouse = require("awful.mouse")
|
||||||
|
|
||||||
--- Titlebar module for awful
|
--- Titlebar module for awful
|
||||||
module("awful.titlebar")
|
module("awful.titlebar")
|
||||||
|
@ -54,9 +55,9 @@ function add(c, args)
|
||||||
-- Redirect relevant events to the client the titlebar belongs to
|
-- Redirect relevant events to the client the titlebar belongs to
|
||||||
local bts =
|
local bts =
|
||||||
{
|
{
|
||||||
capi.button({ }, 1, function (t) capi.client.focus = t.client t.client:raise() t.client:mouse_move() 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) t.client:mouse_move() end),
|
capi.button({ args.modkey }, 1, function (t) mouse.client.move(t.client) end),
|
||||||
capi.button({ args.modkey }, 3, function (t) t.client:mouse_resize() end)
|
capi.button({ args.modkey }, 3, function (t) mouse.client.resize(t.client) end)
|
||||||
}
|
}
|
||||||
title:buttons(bts)
|
title:buttons(bts)
|
||||||
function title.mouse_enter(s) hooks.user.call('mouse_enter', c) end
|
function title.mouse_enter(s) hooks.user.call('mouse_enter', c) end
|
||||||
|
@ -85,8 +86,8 @@ function add(c, args)
|
||||||
local bts =
|
local bts =
|
||||||
{
|
{
|
||||||
capi.button({ }, 1, nil, function (t) t.client:kill() end),
|
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 }, 1, function (t) mouse.client.move(t.client) end),
|
||||||
capi.button({ args.modkey }, 3, function (t) t.client:mouse_resize() end)
|
capi.button({ args.modkey }, 3, function (t) mouse.client.resize(t.client) end)
|
||||||
}
|
}
|
||||||
if close then
|
if close then
|
||||||
local rbts = close:buttons()
|
local rbts = close:buttons()
|
||||||
|
|
586
mouse.c
586
mouse.c
|
@ -30,44 +30,12 @@
|
||||||
#include "layouts/magnifier.h"
|
#include "layouts/magnifier.h"
|
||||||
#include "common/xcursor.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;
|
extern awesome_t globalconf;
|
||||||
|
|
||||||
DO_LUA_NEW(static, button_t, button, "button", button_ref)
|
DO_LUA_NEW(static, button_t, button, "button", button_ref)
|
||||||
DO_LUA_GC(button_t, button, "button", button_unref)
|
DO_LUA_GC(button_t, button, "button", button_unref)
|
||||||
DO_LUA_EQ(button_t, button, "button")
|
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.
|
/** Delete a button.
|
||||||
* \param button The button to destroy.
|
* \param button The button to destroy.
|
||||||
*/
|
*/
|
||||||
|
@ -79,75 +47,6 @@ button_delete(button_t **button)
|
||||||
p_delete(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.
|
/** Get the pointer position.
|
||||||
* \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
|
||||||
|
@ -202,38 +101,6 @@ mouse_query_pointer_root(int *s, int *x, int *y, uint16_t *mask)
|
||||||
return false;
|
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.
|
/** Set the pointer position.
|
||||||
* \param window The destination window.
|
* \param window The destination window.
|
||||||
* \param x X-coordinate inside 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 );
|
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.
|
/** Create a new mouse button bindings.
|
||||||
* \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.
|
||||||
|
|
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)
|
DO_RCNT(button_t, button, button_delete)
|
||||||
ARRAY_FUNCS(button_t *, button, button_unref)
|
ARRAY_FUNCS(button_t *, button, button_unref)
|
||||||
|
|
||||||
int luaA_client_mouse_resize(lua_State *);
|
|
||||||
|
|
||||||
int luaA_button_array_get(lua_State *, button_array_t *);
|
int luaA_button_array_get(lua_State *, button_array_t *);
|
||||||
void luaA_button_array_set(lua_State *, int idx, 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
|
else
|
||||||
c->minax = c->maxax = c->minay = c->maxay = 0;
|
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
|
static int
|
||||||
|
|
|
@ -154,7 +154,6 @@ struct client_t
|
||||||
/* Size hints */
|
/* Size hints */
|
||||||
int basew, baseh, incw, inch, maxw, maxh, minw, minh;
|
int basew, baseh, incw, inch, maxw, maxh, minw, minh;
|
||||||
int minax, maxax, minay, maxay;
|
int minax, maxax, minay, maxay;
|
||||||
bool hassizehints;
|
|
||||||
/** Strut */
|
/** Strut */
|
||||||
strut_t strut;
|
strut_t strut;
|
||||||
/** Respect resize hints */
|
/** Respect resize hints */
|
||||||
|
|
Loading…
Reference in New Issue