e16/src/moveresize.c

738 lines
18 KiB
C
Raw Normal View History

/*
2004-01-19 14:30:35 -08:00
* Copyright (C) 2000-2004 Carsten Haitzler, Geoff Harrison and various contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies of the Software, its documentation and marketing & publicity
* materials, and acknowledgment shall be given in the documentation, materials
* and software packages that this Software was used.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "E.h"
static EWin *mode_moveresize_ewin = NULL;
static int start_move_desk = 0;
static int start_move_x = 0;
static int start_move_y = 0;
static int real_move_mode = 0;
int
ActionMoveStart(EWin * ewin, const void *params, char constrained, int nogroup)
{
EWin **gwins;
int i, num;
EDBUG(6, "DoMove");
if (!ewin || ewin->fixedpos)
EDBUG_RETURN(0);
mode_moveresize_ewin = ewin;
real_move_mode = Conf.movemode;
#if 0 /* Why do this? Let's see what happens if we don't :) */
if (((ewin->groups) || (ewin->has_transients)) && (Conf.movemode > 0))
Conf.movemode = 0;
#endif
if (Conf.movemode > 0)
{
FX_Pause();
GrabX();
}
UnGrabTheButtons();
GrabConfineThePointer(VRoot.win);
SoundPlay("SOUND_MOVE_START");
Mode.mode = MODE_MOVE_PENDING;
Mode.constrained = constrained;
Mode.start_x = Mode.x;
Mode.start_y = Mode.y;
Mode.win_x = ewin->x;
Mode.win_y = ewin->y;
Mode.win_w = ewin->client.w;
Mode.win_h = ewin->client.h;
Mode.firstlast = 0;
start_move_desk = ewin->desktop;
gwins = ListWinGroupMembersForEwin(ewin, ACTION_MOVE, nogroup
|| Mode.swapmovemode, &num);
for (i = 0; i < num; i++)
{
FloatEwinAt(gwins[i], gwins[i]->x, gwins[i]->y);
#if 0 /* Will never get here */
if (Mode.mode == MODE_MOVE)
DrawEwinShape(gwins[i], Conf.movemode, gwins[i]->x, gwins[i]->y,
gwins[i]->client.w, gwins[i]->client.h,
Mode.firstlast);
#endif
}
Efree(gwins);
Mode.firstlast = 1;
Mode.swapcoord_x = start_move_x = ewin->x;
Mode.swapcoord_y = start_move_y = ewin->y;
EDBUG_RETURN(0);
params = NULL;
}
int
ActionMoveEnd(EWin * ewin)
{
EWin **gwins;
int d, wasresize = 0, num, i;
EDBUG(6, "doMoveEnd");
UnGrabTheButtons();
if (ewin && ewin != mode_moveresize_ewin)
return 0;
SoundPlay("SOUND_MOVE_STOP");
ewin = mode_moveresize_ewin;
if (!ewin)
{
if (Conf.movemode > 0)
UngrabX();
if (Mode.mode == MODE_MOVE)
ForceUpdatePagersForDesktop(desks.current);
Conf.movemode = real_move_mode;
EDBUG_RETURN(0);
}
Mode.firstlast = 2;
d = DesktopAt(Mode.x, Mode.y);
gwins = ListWinGroupMembersForEwin(ewin, ACTION_MOVE, Mode.nogroup
|| Mode.swapmovemode, &num);
#if 1 /* Is this OK? */
if (Conf.movemode == 0)
for (i = 0; i < num; i++)
DetermineEwinFloat(gwins[i], 0, 0);
#endif
if (Mode.mode == MODE_MOVE)
{
wasresize = 1;
for (i = 0; i < num; i++)
DrawEwinShape(gwins[i], Conf.movemode, gwins[i]->x, gwins[i]->y,
gwins[i]->client.w, gwins[i]->client.h,
Mode.firstlast);
for (i = 0; i < num; i++)
MoveEwin(gwins[i], gwins[i]->x, gwins[i]->y);
}
Mode.mode = MODE_NONE;
for (i = 0; i < num; i++)
{
if ((gwins[i]->floating) || (Conf.movemode > 0))
{
if (gwins[i]->floating)
MoveEwinToDesktopAt(gwins[i], d,
gwins[i]->x - (desks.desk[d].x -
desks.
desk[gwins[i]->desktop].x),
gwins[i]->y - (desks.desk[d].y -
desks.
desk[gwins[i]->desktop].y));
else
MoveEwinToDesktopAt(gwins[i], d, gwins[i]->x, gwins[i]->y);
gwins[i]->floating = 0;
}
if ((Conf.movemode > 0) && (gwins[i]->has_transients))
{
EWin **lst;
int j, num2;
int dx, dy;
dx = ewin->x - start_move_x;
dy = ewin->y - start_move_y;
lst = ListTransientsFor(gwins[i]->client.win, &num2);
if (lst)
{
for (j = 0; j < num2; j++)
MoveEwin(lst[j], lst[j]->x + dx, lst[j]->y + dy);
Efree(lst);
}
}
RaiseEwin(gwins[i]);
ICCCM_Configure(gwins[i]);
}
StackDesktop(ewin->desktop); /* Restack to "un-float" */
Mode.firstlast = 0;
HideCoords();
XSync(disp, False);
if (Conf.movemode > 0)
{
FX_Pause();
UngrabX();
}
RememberImportantInfoForEwins(ewin);
if (wasresize)
ForceUpdatePagersForDesktop(desks.current);
Efree(gwins);
Conf.movemode = real_move_mode;
Mode.nogroup = 0;
Mode.swapmovemode = 0;
if (Mode.have_place_grab)
{
Mode.have_place_grab = 0;
XUngrabPointer(disp, CurrentTime);
}
EwinUpdateAfterMoveResize(ewin, 0);
EDBUG_RETURN(0);
}
int
ActionMoveSuspend(void)
{
EWin *ewin;
int x, y;
ewin = mode_moveresize_ewin;
if (!ewin)
return 0;
if ((Mode.mode == MODE_MOVE) && (Conf.movemode > 0))
{
x = ewin->x;
y = ewin->y;
ewin->x = -99999;
ewin->y = -99999;
ewin->reqx = -99999;
ewin->reqy = -99999;
DrawEwinShape(ewin, Conf.movemode, x, y,
ewin->client.w, ewin->client.h, /*3? */ 2);
}
else
{
FloatEwinAt(ewin,
ewin->x + desks.desk[ewin->desktop].x,
ewin->y + desks.desk[ewin->desktop].y);
}
return 0;
}
int
ActionMoveResume(void)
{
EWin *ewin;
int x, y;
ewin = mode_moveresize_ewin;
if (!ewin)
return 0;
if (Mode.mode == MODE_MOVE_PENDING)
Mode.mode = MODE_MOVE;
x = ewin->x;
y = ewin->y;
ewin->x = -99999;
ewin->y = -99999;
ewin->reqx = -99999;
ewin->reqy = -99999;
DrawEwinShape(ewin, Conf.movemode, x, y,
ewin->client.w, ewin->client.h, (Conf.movemode == 5) ? 4 : 0);
return 0;
}
int
ActionResizeStart(EWin * ewin, const void *params, int hv)
{
int x, y, w, h;
EDBUG(6, "DoResize");
if (!ewin || ewin->shaded)
EDBUG_RETURN(0);
mode_moveresize_ewin = ewin;
if (Conf.resizemode > 0)
{
FX_Pause();
GrabX();
}
Mode.queue_up = 0;
SoundPlay("SOUND_RESIZE_START");
UnGrabTheButtons();
GrabConfineThePointer(VRoot.win);
switch (hv)
{
case MODE_RESIZE:
Mode.mode = hv;
x = Mode.x - ewin->x;
y = Mode.y - ewin->y;
w = ewin->w >> 1;
h = ewin->h >> 1;
if ((x < w) && (y < h))
Mode.resize_detail = 0;
if ((x >= w) && (y < h))
Mode.resize_detail = 1;
if ((x < w) && (y >= h))
Mode.resize_detail = 2;
if ((x >= w) && (y >= h))
Mode.resize_detail = 3;
break;
case MODE_RESIZE_H:
Mode.mode = hv;
x = Mode.x - ewin->x;
w = ewin->w >> 1;
if (x < w)
Mode.resize_detail = 0;
else
Mode.resize_detail = 1;
break;
case MODE_RESIZE_V:
Mode.mode = hv;
y = Mode.y - ewin->y;
h = ewin->h >> 1;
if (y < h)
Mode.resize_detail = 0;
else
Mode.resize_detail = 1;
break;
}
Mode.start_x = Mode.x;
Mode.start_y = Mode.y;
Mode.win_x = ewin->x;
Mode.win_y = ewin->y;
Mode.win_w = ewin->client.w;
Mode.win_h = ewin->client.h;
Mode.firstlast = 0;
DrawEwinShape(ewin, Conf.resizemode, ewin->x, ewin->y, ewin->client.w,
ewin->client.h, Mode.firstlast);
Mode.firstlast = 1;
EDBUG_RETURN(0);
params = NULL;
}
int
ActionResizeEnd(EWin * ewin)
{
int i;
EDBUG(0, "doResizeEnd");
UnGrabTheButtons();
if (ewin && ewin != mode_moveresize_ewin)
return 0;
SoundPlay("SOUND_RESIZE_STOP");
ewin = mode_moveresize_ewin;
if (!ewin)
{
if (Conf.resizemode > 0)
UngrabX();
ForceUpdatePagersForDesktop(desks.current);
EDBUG_RETURN(0);
}
Mode.queue_up = DRAW_QUEUE_ENABLE;
Mode.mode = MODE_NONE;
Mode.firstlast = 2;
DrawEwinShape(ewin, Conf.resizemode, ewin->x, ewin->y, ewin->client.w,
ewin->client.h, Mode.firstlast);
for (i = 0; i < ewin->border->num_winparts; i++)
ewin->bits[i].no_expose = 1;
ICCCM_Configure(ewin);
HideCoords();
XSync(disp, False);
if (Conf.resizemode > 0)
{
FX_Pause();
UngrabX();
}
Mode.firstlast = 0;
ForceUpdatePagersForDesktop(desks.current);
RememberImportantInfoForEwin(ewin);
EwinUpdateAfterMoveResize(ewin, 1);
EDBUG_RETURN(0);
}
void
ActionMoveHandleMotion(void)
{
int dx, dy;
EWin *ewin;
EWin **gwins;
int i, j, num;
int ndx, ndy;
int prx, pry;
int screen_snap_dist;
ewin = mode_moveresize_ewin;
if (!ewin)
return;
gwins = ListWinGroupMembersForEwin(ewin, ACTION_MOVE,
Mode.nogroup || Mode.swapmovemode, &num);
if (Mode.mode == MODE_MOVE_PENDING)
{
for (i = 0; i < num; i++)
DrawEwinShape(gwins[i], Conf.movemode, gwins[i]->x,
gwins[i]->y, gwins[i]->client.w,
gwins[i]->client.h, 0);
Mode.mode = MODE_MOVE;
}
dx = Mode.x - Mode.px;
dy = Mode.y - Mode.py;
if (Mode.next_move_x_plus != 0)
{
dx += Mode.next_move_x_plus;
Mode.next_move_x_plus = 0;
}
if (Mode.next_move_y_plus != 0)
{
dy += Mode.next_move_y_plus;
Mode.next_move_y_plus = 0;
}
{
char jumpx, jumpy;
int min_dx, max_dx, min_dy, max_dy;
jumpx = 0;
jumpy = 0;
min_dx = dx;
min_dy = dy;
max_dx = dx;
max_dy = dy;
for (i = 0; i < num; i++)
{
ndx = dx;
ndy = dy;
/* make our ewin resist other ewins around the place */
SnapEwin(gwins[i], dx, dy, &ndx, &ndy);
if ((dx < 0) && (ndx <= 0))
{
if (ndx > min_dx)
min_dx = ndx;
if (ndx < max_dx)
max_dx = ndx;
}
else if (ndx >= 0)
{
if (ndx < min_dx)
min_dx = ndx;
if (ndx > max_dx)
max_dx = ndx;
}
if ((dy < 0) && (ndy <= 0))
{
if (ndy > min_dy)
min_dy = ndy;
if (ndy < max_dy)
max_dy = ndy;
}
else if (ndy >= 0)
{
if (ndy < min_dy)
min_dy = ndy;
if (ndy > max_dy)
max_dy = ndy;
}
}
if (min_dx == dx)
ndx = max_dx;
else
ndx = min_dx;
if (min_dy == dy)
ndy = max_dy;
else
ndy = min_dy;
screen_snap_dist =
Mode.constrained ? (VRoot.w + VRoot.h) : Conf.snap.screen_snap_dist;
for (i = 0; i < num; i++)
{
/* jump out of snap horizontally */
if ((ndx != dx)
&& (((gwins[i]->x == 0)
&&
(!(IN_RANGE
(gwins[i]->reqx, gwins[i]->x,
screen_snap_dist))))
|| ((gwins[i]->x == (VRoot.w - gwins[i]->w))
&&
(!(IN_RANGE
(gwins[i]->reqx, gwins[i]->x,
screen_snap_dist))))
|| ((gwins[i]->x != 0)
&& (gwins[i]->x != (VRoot.w - gwins[i]->w)
&&
(!(IN_RANGE
(gwins[i]->reqx, gwins[i]->x,
Conf.snap.edge_snap_dist)))))))
{
jumpx = 1;
ndx = gwins[i]->reqx - gwins[i]->x + dx;
}
/* jump out of snap vertically */
if ((ndy != dy)
&& (((gwins[i]->y == 0)
&&
(!(IN_RANGE
(gwins[i]->reqy, gwins[i]->y,
screen_snap_dist))))
|| ((gwins[i]->y == (VRoot.h - gwins[i]->h))
&&
(!(IN_RANGE
(gwins[i]->reqy, gwins[i]->y,
screen_snap_dist))))
|| ((gwins[i]->y != 0)
&& (gwins[i]->y != (VRoot.h - gwins[i]->h)
&&
(!(IN_RANGE
(gwins[i]->reqy, gwins[i]->y,
Conf.snap.edge_snap_dist)))))))
{
jumpy = 1;
ndy = gwins[i]->reqy - gwins[i]->y + dy;
}
}
for (i = 0; i < num; i++)
{
/* if its opaque move mode check to see if we have to float */
/* the window aboe all desktops (reparent to root) */
if (Conf.movemode == 0)
DetermineEwinFloat(gwins[i], ndx, ndy);
/* draw the new position of the window */
prx = gwins[i]->reqx;
pry = gwins[i]->reqy;
DrawEwinShape(gwins[i], Conf.movemode, gwins[i]->x + ndx,
gwins[i]->y + ndy, gwins[i]->client.w,
gwins[i]->client.h, Mode.firstlast);
/* if we didnt jump the winow after a resist at the edge */
/* reset the requested x to be the prev. requested + delta */
if (!(jumpx))
gwins[i]->reqx = prx + dx;
if (!(jumpy))
gwins[i]->reqy = pry + dy;
/* swapping of group member locations: */
if (Mode.swapmovemode && Conf.group_swapmove)
{
EWin **all_gwins;
int all_gwins_num;
all_gwins =
ListWinGroupMembersForEwin(ewin, ACTION_NONE, 0,
&all_gwins_num);
for (j = 0; j < all_gwins_num; j++)
{
if (gwins[i] == all_gwins[j])
continue;
/* check for sufficient overlap and avoid flickering */
if (((gwins
[i]->x >= all_gwins[j]->x
&& gwins[i]->x <=
all_gwins[j]->x + all_gwins[j]->w / 2
&& Mode.x <= Mode.px)
|| (gwins[i]->x <= all_gwins[j]->x
&& gwins[i]->x + gwins[i]->w / 2 >=
all_gwins[j]->x && Mode.x >= Mode.px))
&&
((gwins
[i]->y >= all_gwins[j]->y
&& gwins[i]->y <=
all_gwins[j]->y + all_gwins[j]->h / 2
&& Mode.y <= Mode.py)
|| (gwins[i]->y <= all_gwins[j]->y
&& gwins[i]->y + gwins[i]->h / 2 >=
all_gwins[j]->y && Mode.y >= Mode.py)))
{
int tmp_swapcoord_x;
int tmp_swapcoord_y;
tmp_swapcoord_x = Mode.swapcoord_x;
tmp_swapcoord_y = Mode.swapcoord_y;
Mode.swapcoord_x = all_gwins[j]->x;
Mode.swapcoord_y = all_gwins[j]->y;
MoveEwin(all_gwins[j], tmp_swapcoord_x,
tmp_swapcoord_y);
break;
}
}
Efree(all_gwins);
}
}
}
Efree(gwins);
}
void
ActionResizeHandleMotion(void)
{
int pw, ph;
int x, y, w, h;
EWin *ewin;
ewin = mode_moveresize_ewin;
if (!ewin)
return;
switch (Mode.mode)
{
case MODE_RESIZE:
switch (Mode.resize_detail)
{
case 0:
pw = ewin->client.w;
ph = ewin->client.h;
w = Mode.win_w - (Mode.x - Mode.start_x);
h = Mode.win_h - (Mode.y - Mode.start_y);
x = Mode.win_x + (Mode.x - Mode.start_x);
y = Mode.win_y + (Mode.y - Mode.start_y);
ewin->client.w = w;
ewin->client.h = h;
ICCCM_MatchSize(ewin);
w = ewin->client.w;
h = ewin->client.h;
if (pw == ewin->client.w)
x = ewin->x;
else
x = Mode.win_x + Mode.win_w - w;
if (ph == ewin->client.h)
y = ewin->y;
else
y = Mode.win_y + Mode.win_h - h;
ewin->client.w = pw;
ewin->client.h = ph;
DrawEwinShape(ewin, Conf.resizemode, x, y, w, h, Mode.firstlast);
break;
case 1:
ph = ewin->client.h;
w = Mode.win_w + (Mode.x - Mode.start_x);
h = Mode.win_h - (Mode.y - Mode.start_y);
x = ewin->x;
y = Mode.win_y + (Mode.y - Mode.start_y);
ewin->client.h = h;
ICCCM_MatchSize(ewin);
h = ewin->client.h;
if (ph == ewin->client.h)
y = ewin->y;
else
y = Mode.win_y + Mode.win_h - h;
ewin->client.h = ph;
DrawEwinShape(ewin, Conf.resizemode, x, y, w, h, Mode.firstlast);
break;
case 2:
pw = ewin->client.w;
w = Mode.win_w - (Mode.x - Mode.start_x);
h = Mode.win_h + (Mode.y - Mode.start_y);
x = Mode.win_x + (Mode.x - Mode.start_x);
y = ewin->y;
ewin->client.w = w;
ICCCM_MatchSize(ewin);
w = ewin->client.w;
if (pw == ewin->client.w)
x = ewin->x;
else
x = Mode.win_x + Mode.win_w - w;
ewin->client.w = pw;
DrawEwinShape(ewin, Conf.resizemode, x, y, w, h, Mode.firstlast);
break;
case 3:
w = Mode.win_w + (Mode.x - Mode.start_x);
h = Mode.win_h + (Mode.y - Mode.start_y);
x = ewin->x;
y = ewin->y;
DrawEwinShape(ewin, Conf.resizemode, x, y, w, h, Mode.firstlast);
break;
default:
break;
}
break;
case MODE_RESIZE_H:
switch (Mode.resize_detail)
{
case 0:
pw = ewin->client.w;
w = Mode.win_w - (Mode.x - Mode.start_x);
h = ewin->client.h;
x = Mode.win_x + (Mode.x - Mode.start_x);
y = ewin->y;
ewin->client.w = w;
ICCCM_MatchSize(ewin);
w = ewin->client.w;
if (pw == ewin->client.w)
x = ewin->x;
else
x = Mode.win_x + Mode.win_w - w;
ewin->client.w = pw;
DrawEwinShape(ewin, Conf.resizemode, x, y, w, h, Mode.firstlast);
break;
case 1:
w = Mode.win_w + (Mode.x - Mode.start_x);
h = ewin->client.h;
x = ewin->x;
y = ewin->y;
DrawEwinShape(ewin, Conf.resizemode, x, y, w, h, Mode.firstlast);
break;
default:
break;
}
break;
case MODE_RESIZE_V:
switch (Mode.resize_detail)
{
case 0:
ph = ewin->client.h;
w = ewin->client.w;
h = Mode.win_h - (Mode.y - Mode.start_y);
x = ewin->x;
y = Mode.win_y + (Mode.y - Mode.start_y);
ewin->client.h = h;
ICCCM_MatchSize(ewin);
h = ewin->client.h;
if (ph == ewin->client.h)
y = ewin->y;
else
y = Mode.win_y + Mode.win_h - h;
ewin->client.h = ph;
DrawEwinShape(ewin, Conf.resizemode, x, y, w, h, Mode.firstlast);
break;
case 1:
w = ewin->client.w;
h = Mode.win_h + (Mode.y - Mode.start_y);
x = ewin->x;
y = ewin->y;
DrawEwinShape(ewin, Conf.resizemode, x, y, w, h, Mode.firstlast);
break;
default:
break;
}
break;
default:
break;
}
}