mouse: move resize code to awful.mouse

Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
Julien Danjou 2008-11-17 17:12:54 +01:00
parent 33c7083617
commit 53a830aea1
8 changed files with 227 additions and 599 deletions

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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