539 lines
13 KiB
C
539 lines
13 KiB
C
/*
|
|
* Copyright (C) 2000 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 int area_w = 3;
|
|
static int area_h = 3;
|
|
|
|
#define AREA_FIX(ax, ay) \
|
|
if (ax < 0) \
|
|
ax = 0; \
|
|
else if (ax >= area_w) \
|
|
ax = area_w - 1; \
|
|
if (ay < 0) \
|
|
ay = 0; \
|
|
else if (ay >= area_h) \
|
|
ay = area_h - 1;
|
|
|
|
void
|
|
SetNewAreaSize(int ax, int ay)
|
|
{
|
|
|
|
int a, b, i, num;
|
|
EWin **lst;
|
|
|
|
if (ax <= 0)
|
|
return;
|
|
if (ay <= 0)
|
|
return;
|
|
|
|
GetAreaSize(&a, &b);
|
|
if ((a == ax) && (b == ay))
|
|
return;
|
|
SetAreaSize(ax, ay);
|
|
lst = (EWin **) ListItemType(&num, LIST_TYPE_EWIN);
|
|
if (lst)
|
|
{
|
|
for (i = 0; i < num; i++)
|
|
{
|
|
if ((!(lst[i]->sticky)) && (!(lst[i]->fixedpos)))
|
|
{
|
|
if (lst[i]->area_x >= ax)
|
|
MoveEwinToArea(lst[i], ax - 1, lst[i]->area_x);
|
|
if (lst[i]->area_y >= ay)
|
|
MoveEwinToArea(lst[i], lst[i]->area_x, ay - 1);
|
|
}
|
|
}
|
|
Efree(lst);
|
|
}
|
|
GetCurrentArea(&a, &b);
|
|
if (a >= ax)
|
|
{
|
|
SetCurrentArea(ax - 1, b);
|
|
GetCurrentArea(&a, &b);
|
|
}
|
|
if (b >= ay)
|
|
SetCurrentArea(a, ay - 1);
|
|
}
|
|
|
|
void
|
|
GetCurrentArea(int *ax, int *ay)
|
|
{
|
|
EDBUG(4, "GetCurrentArea");
|
|
*ax = desks.desk[desks.current].current_area_x;
|
|
*ay = desks.desk[desks.current].current_area_y;
|
|
EDBUG_RETURN_;
|
|
}
|
|
|
|
void
|
|
SetAreaSize(int aw, int ah)
|
|
{
|
|
EDBUG(4, "SetAreaSize");
|
|
if (aw < 1)
|
|
aw = 1;
|
|
if (ah < 1)
|
|
ah = 1;
|
|
area_w = aw;
|
|
area_h = ah;
|
|
GNOME_SetAreaCount();
|
|
PagerReArea();
|
|
EDBUG_RETURN_;
|
|
}
|
|
|
|
void
|
|
GetAreaSize(int *aw, int *ah)
|
|
{
|
|
EDBUG(4, "GetAreaSize");
|
|
*aw = area_w;
|
|
*ah = area_h;
|
|
EDBUG_RETURN_;
|
|
}
|
|
|
|
void
|
|
InitCurrentArea(int ax, int ay)
|
|
{
|
|
EDBUG(4, "InitCurrentArea");
|
|
AREA_FIX(ax, ay);
|
|
desks.desk[desks.current].current_area_x = ax;
|
|
desks.desk[desks.current].current_area_y = ay;
|
|
EDBUG_RETURN_;
|
|
}
|
|
|
|
void
|
|
SetCurrentLinearArea(int a)
|
|
{
|
|
if (a < 0)
|
|
a = 0;
|
|
else if (a >= (area_w * area_h))
|
|
a = (area_w * area_h) - 1;
|
|
SetCurrentArea(a - ((a / area_w) * area_w), (a / area_w));
|
|
}
|
|
|
|
int
|
|
GetCurrentLinearArea(void)
|
|
{
|
|
return ((desks.desk[desks.current].current_area_y * area_w) +
|
|
desks.desk[desks.current].current_area_x);
|
|
}
|
|
|
|
void
|
|
MoveCurrentLinearAreaBy(int a)
|
|
{
|
|
SetCurrentLinearArea(GetCurrentLinearArea() + a);
|
|
}
|
|
|
|
void
|
|
MoveEwinToLinearArea(EWin * ewin, int a)
|
|
{
|
|
if (a < 0)
|
|
a = 0;
|
|
else if (a >= (area_w * area_h))
|
|
a = (area_w * area_h) - 1;
|
|
MoveEwinToArea(ewin, a - ((a / area_w) * area_w), (a / area_w));
|
|
}
|
|
|
|
void
|
|
MoveEwinLinearAreaBy(EWin * ewin, int a)
|
|
{
|
|
a += (ewin->area_y * area_w) + (ewin->area_x);
|
|
if (a < 0)
|
|
a = 0;
|
|
else if (a >= (area_w * area_h))
|
|
a = (area_w * area_h) - 1;
|
|
MoveEwinToArea(ewin, a - ((a / area_w) * area_w), (a / area_w));
|
|
}
|
|
|
|
void
|
|
SlideWindowsBy(Window * win, int num, int dx, int dy, int speed)
|
|
{
|
|
int i, k, spd, x, y, min;
|
|
struct timeval timev1, timev2;
|
|
int dsec, dusec;
|
|
double tm;
|
|
struct _xy
|
|
{
|
|
int x, y;
|
|
}
|
|
*xy;
|
|
|
|
EDBUG(5, "SlideWindowsBy");
|
|
spd = 16;
|
|
min = 2;
|
|
if (num < 1)
|
|
EDBUG_RETURN_;
|
|
xy = Emalloc(sizeof(struct _xy) * num);
|
|
|
|
for (i = 0; i < num; i++)
|
|
GetWinXY(win[i], &(xy[i].x), &(xy[i].y));
|
|
for (k = 0; k <= 1024; k += spd)
|
|
{
|
|
gettimeofday(&timev1, NULL);
|
|
for (i = 0; i < num; i++)
|
|
{
|
|
x = ((xy[i].x * (1024 - k)) + ((xy[i].x + dx) * k)) >> 10;
|
|
y = ((xy[i].y * (1024 - k)) + ((xy[i].y + dy) * k)) >> 10;
|
|
EMoveWindow(disp, win[i], x, y);
|
|
}
|
|
XSync(disp, False);
|
|
gettimeofday(&timev2, NULL);
|
|
dsec = timev2.tv_sec - timev1.tv_sec;
|
|
dusec = timev2.tv_usec - timev1.tv_usec;
|
|
if (dusec < 0)
|
|
{
|
|
dsec--;
|
|
dusec += 1000000;
|
|
}
|
|
tm = (double)dsec + (((double)dusec) / 1000000);
|
|
spd = (int)((double)speed * tm);
|
|
if (spd < min)
|
|
spd = min;
|
|
}
|
|
for (i = 0; i < num; i++)
|
|
EMoveWindow(disp, win[i], xy[i].x + dx, xy[i].y + dy);
|
|
if (xy)
|
|
Efree(xy);
|
|
EDBUG_RETURN_;
|
|
}
|
|
|
|
void
|
|
SetCurrentArea(int ax, int ay)
|
|
{
|
|
EWin **lst;
|
|
int i, num, a1, a2, x, y, dx, dy;
|
|
ToolTip *tt;
|
|
|
|
EDBUG(4, "SetCurrentArea");
|
|
if ((mode.mode == MODE_RESIZE) ||
|
|
(mode.mode == MODE_RESIZE_H) || (mode.mode == MODE_RESIZE_V))
|
|
EDBUG_RETURN_;
|
|
|
|
AREA_FIX(ax, ay);
|
|
if ((ax == desks.desk[desks.current].current_area_x) &&
|
|
(ay == desks.desk[desks.current].current_area_y))
|
|
EDBUG_RETURN_;
|
|
tt = FindItem("DEFAULT", 0, LIST_FINDBY_NAME, LIST_TYPE_TOOLTIP);
|
|
HideToolTip(tt);
|
|
dx = ax - desks.desk[desks.current].current_area_x;
|
|
dy = ay - desks.desk[desks.current].current_area_y;
|
|
if (dx < 0)
|
|
{
|
|
AUDIO_PLAY("SOUND_MOVE_AREA_LEFT");
|
|
}
|
|
else if (dx > 0)
|
|
{
|
|
AUDIO_PLAY("SOUND_MOVE_AREA_RIGHT");
|
|
}
|
|
else if (dy < 0)
|
|
{
|
|
AUDIO_PLAY("SOUND_MOVE_AREA_UP");
|
|
}
|
|
else if (dy > 0)
|
|
{
|
|
AUDIO_PLAY("SOUND_MOVE_AREA_DOWN");
|
|
}
|
|
|
|
/* if we're in move mode.... and its non opaque undraw our boxes */
|
|
if ((mode.mode == MODE_MOVE) && (mode.ewin) && (mode.movemode > 0) &&
|
|
(!mode.moveresize_pending_ewin))
|
|
{
|
|
lst =
|
|
ListWinGroupMembersForEwin(mode.ewin, ACTION_MOVE, mode.nogroup,
|
|
&num);
|
|
for (i = 0; i < num; i++)
|
|
{
|
|
x = lst[i]->x;
|
|
y = lst[i]->y;
|
|
DrawEwinShape(lst[i], mode.movemode,
|
|
x, y, lst[i]->client.w, lst[i]->client.h, 3);
|
|
}
|
|
Efree(lst);
|
|
}
|
|
/* remove lots of event masks from windows.. we dont want to bother */
|
|
/* handling events as a result of our playing wiht windows */
|
|
FocusToEWin(NULL);
|
|
BeginNewDeskFocus();
|
|
/* move all the windows around */
|
|
lst = (EWin **) ListItemType(&num, LIST_TYPE_EWIN);
|
|
if (lst)
|
|
{
|
|
if (desks.slidein)
|
|
{
|
|
int wnum = 0;
|
|
Window *wl = NULL;
|
|
|
|
/* create the list of windwos to move */
|
|
for (i = 0; i < num; i++)
|
|
{
|
|
if ((lst[i]->desktop == desks.current) &&
|
|
(!lst[i]->sticky) && (!lst[i]->fixedpos) &&
|
|
(!lst[i]->iconified))
|
|
{
|
|
if ((lst[i]->floating) && (mode.movemode > 0))
|
|
{
|
|
wnum++;
|
|
wl = Erealloc(wl, sizeof(Window) * wnum);
|
|
wl[wnum - 1] = lst[i]->win;
|
|
}
|
|
else if (!lst[i]->floating)
|
|
{
|
|
wnum++;
|
|
wl = Erealloc(wl, sizeof(Window) * wnum);
|
|
wl[wnum - 1] = lst[i]->win;
|
|
}
|
|
}
|
|
}
|
|
/* slide them */
|
|
if (wl)
|
|
{
|
|
SlideWindowsBy(wl, wnum,
|
|
-(root.w *
|
|
(ax -
|
|
desks.desk[desks.current].current_area_x)),
|
|
-(root.h *
|
|
(ay -
|
|
desks.desk[desks.current].current_area_y)),
|
|
desks.slidespeed);
|
|
Efree(wl);
|
|
}
|
|
/* move the windows to their final positions */
|
|
for (i = 0; i < num; i++)
|
|
{
|
|
if ((lst[i]->desktop == desks.current) &&
|
|
(!lst[i]->sticky) && (!lst[i]->fixedpos) &&
|
|
(!lst[i]->iconified))
|
|
{
|
|
if (!lst[i]->floating)
|
|
{
|
|
char setflip = 0;
|
|
|
|
a1 = lst[i]->area_x;
|
|
a2 = lst[i]->area_y;
|
|
if (!mode.flipp)
|
|
{
|
|
setflip = 1;
|
|
mode.flipp = 1;
|
|
}
|
|
MoveEwin(lst[i],
|
|
lst[i]->x -
|
|
(root.w *
|
|
(ax -
|
|
desks.desk[desks.current].
|
|
current_area_x)),
|
|
lst[i]->y -
|
|
(root.h *
|
|
(ay -
|
|
desks.desk[desks.current].
|
|
current_area_y)));
|
|
if (setflip)
|
|
mode.flipp = 0;
|
|
lst[i]->area_x = a1;
|
|
lst[i]->area_y = a2;
|
|
GNOME_SetEwinArea(lst[i]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* move all widnwos across.... */
|
|
for (i = 0; i < num; i++)
|
|
{
|
|
if ((lst[i]->desktop == desks.current) &&
|
|
(!lst[i]->sticky) && (!lst[i]->fixedpos) &&
|
|
(!lst[i]->iconified))
|
|
{
|
|
/* if we're moving this window and its not opaque move */
|
|
/* warp it across withotu remebering the xy stuff */
|
|
/* well work out the xy stuff later when the move finishes */
|
|
if (lst[i]->floating)
|
|
{
|
|
if (mode.movemode > 0)
|
|
{
|
|
GetWinXY(lst[i]->win, &x, &y);
|
|
EMoveWindow(disp, lst[i]->win,
|
|
x -
|
|
(root.w *
|
|
(ax -
|
|
desks.desk[desks.current].
|
|
current_area_x)),
|
|
y -
|
|
(root.h *
|
|
(ay -
|
|
desks.desk[desks.current].
|
|
current_area_y)));
|
|
}
|
|
}
|
|
/* if we're not moving it... move it across */
|
|
else
|
|
{
|
|
char setflip = 0;
|
|
|
|
a1 = lst[i]->area_x;
|
|
a2 = lst[i]->area_y;
|
|
if (!mode.flipp)
|
|
{
|
|
setflip = 1;
|
|
mode.flipp = 1;
|
|
}
|
|
MoveEwin(lst[i],
|
|
lst[i]->x -
|
|
(root.w *
|
|
(ax -
|
|
desks.desk[desks.current].
|
|
current_area_x)),
|
|
lst[i]->y -
|
|
(root.h *
|
|
(ay -
|
|
desks.desk[desks.current].
|
|
current_area_y)));
|
|
if (setflip)
|
|
mode.flipp = 0;
|
|
lst[i]->area_x = a1;
|
|
lst[i]->area_y = a2;
|
|
GNOME_SetEwinArea(lst[i]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Efree(lst);
|
|
}
|
|
/* set the current area up in out data structs */
|
|
desks.desk[desks.current].current_area_x = ax;
|
|
desks.desk[desks.current].current_area_y = ay;
|
|
/* set gnome hints up for it */
|
|
GNOME_SetCurrentArea();
|
|
XSync(disp, False);
|
|
/* redraw any windows that were in "move mode" */
|
|
mode.moveresize_pending_ewin = NULL;
|
|
if ((mode.mode == MODE_MOVE) && (mode.ewin))
|
|
{
|
|
lst = (EWin **) ListItemType(&num, LIST_TYPE_EWIN);
|
|
if (lst)
|
|
{
|
|
for (i = 0; i < num; i++)
|
|
{
|
|
if (lst[i]->floating)
|
|
{
|
|
if (mode.movemode > 0)
|
|
{
|
|
if (mode.flipp)
|
|
{
|
|
x = lst[i]->x - (dx * root.w);
|
|
y = lst[i]->y - (dy * root.h);
|
|
}
|
|
else
|
|
{
|
|
x = lst[i]->x;
|
|
y = lst[i]->y;
|
|
}
|
|
if (mode.movemode == 5)
|
|
DrawEwinShape(lst[i], mode.movemode,
|
|
x, y,
|
|
lst[i]->client.w, lst[i]->client.h,
|
|
4);
|
|
else
|
|
DrawEwinShape(lst[i], mode.movemode, x, y,
|
|
lst[i]->client.w, lst[i]->client.h,
|
|
0);
|
|
if (mode.flipp)
|
|
{
|
|
mode.next_move_x_plus = dx * root.w;
|
|
mode.next_move_y_plus = dy * root.h;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (mode.flipp)
|
|
{
|
|
x = lst[i]->x - (dx * root.w);
|
|
y = lst[i]->y - (dy * root.h);
|
|
}
|
|
else
|
|
{
|
|
x = lst[i]->x;
|
|
y = lst[i]->y;
|
|
}
|
|
DrawEwinShape(lst[i], mode.movemode,
|
|
x, y,
|
|
lst[i]->client.w, lst[i]->client.h,
|
|
0);
|
|
if (mode.flipp)
|
|
{
|
|
lst[i]->x = x + (dx * root.w);
|
|
lst[i]->y = y + (dy * root.h);
|
|
lst[i]->reqx = lst[i]->x;
|
|
lst[i]->reqy = lst[i]->y;
|
|
}
|
|
}
|
|
}
|
|
RedrawPagersForDesktop(lst[i]->desktop, 3);
|
|
PagerEwinOutsideAreaUpdate(lst[i]);
|
|
}
|
|
Efree(lst);
|
|
}
|
|
}
|
|
/* re-focus on a new ewin on that new desktop area */
|
|
NewDeskFocus();
|
|
/* tell the FX api abotu the change */
|
|
FX_DeskChange();
|
|
/* update which "edge flip resistance" detector windows are visible */
|
|
ShowEdgeWindows();
|
|
/* update our pager */
|
|
UpdatePagerSel();
|
|
ForceUpdatePagersForDesktop(desks.current);
|
|
EDBUG_RETURN_;
|
|
}
|
|
|
|
void
|
|
MoveEwinToArea(EWin * ewin, int ax, int ay)
|
|
{
|
|
EDBUG(4, "MoveEwinToArea");
|
|
AREA_FIX(ax, ay);
|
|
MoveEwin(ewin, ewin->x + (root.w * (ax - ewin->area_x)),
|
|
ewin->y + (root.h * (ay - ewin->area_y)));
|
|
ewin->area_x = ax;
|
|
ewin->area_y = ay;
|
|
GNOME_SetEwinArea(ewin);
|
|
EDBUG_RETURN_;
|
|
}
|
|
|
|
void
|
|
SetEwinToCurrentArea(EWin * ewin)
|
|
{
|
|
EDBUG(4, "SetEwinToCurrentArea");
|
|
ewin->area_x = desks.desk[ewin->desktop].current_area_x;
|
|
ewin->area_y = desks.desk[ewin->desktop].current_area_y;
|
|
GNOME_SetEwinArea(ewin);
|
|
EDBUG_RETURN_;
|
|
}
|
|
|
|
void
|
|
MoveCurrentAreaBy(int ax, int ay)
|
|
{
|
|
EDBUG(4, "MoveCurrentAreaBy");
|
|
|
|
SetCurrentArea(desks.desk[desks.current].current_area_x + ax,
|
|
desks.desk[desks.current].current_area_y + ay);
|
|
EDBUG_RETURN_;
|
|
}
|