e16/src/edge.c

280 lines
6.6 KiB
C

/*
* Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors
* Copyright (C) 2004-2021 Kim Woelders
*
* 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 "config.h"
#include <X11/Xlib.h>
#include "E.h"
#include "desktops.h"
#include "eobj.h"
#include "ewins.h"
#include "menus.h" /* FIXME - Should not be here */
#include "timers.h"
#include "xwin.h"
#define EW_L 0 /* Left */
#define EW_R 1 /* Right */
#define EW_T 2 /* Top */
#define EW_B 3 /* Bottom */
static EObj *w1 = NULL, *w2 = NULL, *w3 = NULL, *w4 = NULL;
static Timer *edge_timer = NULL;
static int
EdgeTimeout(void *data)
{
int val;
int ax, ay, aw, ah, dx, dy, dax, day;
EWin *ewin;
if (MenusActive())
goto done;
if (Conf.desks.edge_flip_mode == EDGE_FLIP_OFF)
goto done;
/* Quit if pointer has left screen */
if (!EQueryPointer(NULL, NULL, NULL, NULL, NULL))
goto done;
/* Quit if in fullscreen window */
ewin = GetEwinPointerInClient();
if (ewin && ewin->state.fullscreen)
goto done;
DeskCurrentGetArea(&ax, &ay);
DesksGetAreaSize(&aw, &ah);
val = PTR2INT(data);
dx = 0;
dy = 0;
dax = 0;
day = 0;
switch (val)
{
case EW_L:
if (ax == 0 && !Conf.desks.areas_wraparound)
goto done;
dx = WinGetW(VROOT) - 2;
dax = -1;
break;
case EW_R:
if (ax == (aw - 1) && !Conf.desks.areas_wraparound)
goto done;
dx = -(WinGetW(VROOT) - 2);
dax = 1;
break;
case EW_T:
if (ay == 0 && !Conf.desks.areas_wraparound)
goto done;
dy = WinGetH(VROOT) - 2;
day = -1;
break;
case EW_B:
if (ay == (ah - 1) && !Conf.desks.areas_wraparound)
goto done;
dy = -(WinGetH(VROOT) - 2);
day = 1;
break;
default:
break;
}
if (aw == 1)
dx = 0;
if (ah == 1)
dy = 0;
Mode.events.px = Mode.events.mx;
Mode.events.py = Mode.events.my;
Mode.events.mx = Mode.events.cx += dx;
Mode.events.my = Mode.events.cy += dy;
EWarpPointer(VROOT, Mode.events.mx, Mode.events.my);
DeskCurrentMoveAreaBy(dax, day);
Mode.events.px = Mode.events.mx;
Mode.events.py = Mode.events.my;
done:
edge_timer = NULL;
return 0;
}
static void
EdgeEvent(int dir)
{
static int lastdir = -1;
#if 0
Eprintf("%s: %d -> %d\n", __func__, lastdir, dir);
#endif
if (lastdir == dir || Conf.desks.edge_flip_mode == EDGE_FLIP_OFF)
return;
if (Conf.desks.edge_flip_mode == EDGE_FLIP_MOVE && Mode.mode != MODE_MOVE)
return;
TIMER_DEL(edge_timer);
if (dir >= 0)
{
if (Conf.desks.edge_flip_resistance <= 0)
Conf.desks.edge_flip_resistance = 1;
TIMER_ADD(edge_timer, 10 * Conf.desks.edge_flip_resistance,
EdgeTimeout, INT2PTR(dir));
}
lastdir = dir;
}
static void
EdgeHandleEvents(Win win __UNUSED__, XEvent * ev, void *prm)
{
int dir;
dir = PTR2INT(prm);
switch (ev->type)
{
default:
break;
case EnterNotify:
EdgeEvent(dir);
break;
case LeaveNotify:
EdgeEvent(-1);
break;
}
}
void
EdgeCheckMotion(int x, int y)
{
int dir;
if (x == 0)
dir = 0;
else if (x == WinGetW(VROOT) - 1)
dir = 1;
else if (y == 0)
dir = 2;
else if (y == WinGetH(VROOT) - 1)
dir = 3;
else
dir = -1;
EdgeEvent(dir);
}
static void
EdgeWindowShow(int which, int on)
{
EObj *eo;
int x, y, w, h;
x = y = 0;
w = h = 1;
switch (which)
{
default:
case EW_L: /* Left */
eo = w1;
h = WinGetH(VROOT);
break;
case EW_R: /* Right */
eo = w2;
x = WinGetW(VROOT) - 1;
h = WinGetH(VROOT);
break;
case EW_T: /* Top */
eo = w3;
w = WinGetW(VROOT);
break;
case EW_B: /* Bottom */
eo = w4;
y = WinGetH(VROOT) - 1;
w = WinGetW(VROOT);
break;
}
if (on)
{
EobjMoveResize(eo, x, y, w, h);
EobjMap(eo, 0);
}
else
{
EobjUnmap(eo);
}
}
void
EdgeWindowsShow(void)
{
int ax, ay, cx, cy;
if (Conf.desks.edge_flip_mode == EDGE_FLIP_OFF)
{
EdgeWindowsHide();
return;
}
if (!w1)
{
w1 = EobjWindowCreate(EOBJ_TYPE_EVENT,
0, 0, 1, WinGetH(VROOT), 0, "Edge-L");
w2 = EobjWindowCreate(EOBJ_TYPE_EVENT,
WinGetW(VROOT) - 1, 0, 1, WinGetH(VROOT),
0, "Edge-R");
w3 = EobjWindowCreate(EOBJ_TYPE_EVENT,
0, 0, WinGetW(VROOT), 1, 0, "Edge-T");
w4 = EobjWindowCreate(EOBJ_TYPE_EVENT,
0, WinGetH(VROOT) - 1, WinGetW(VROOT), 1,
0, "Edge-B");
ESelectInput(EobjGetWin(w1), EnterWindowMask | LeaveWindowMask);
ESelectInput(EobjGetWin(w2), EnterWindowMask | LeaveWindowMask);
ESelectInput(EobjGetWin(w3), EnterWindowMask | LeaveWindowMask);
ESelectInput(EobjGetWin(w4), EnterWindowMask | LeaveWindowMask);
EventCallbackRegister(EobjGetWin(w1), EdgeHandleEvents, (void *)EW_L);
EventCallbackRegister(EobjGetWin(w2), EdgeHandleEvents, (void *)EW_R);
EventCallbackRegister(EobjGetWin(w3), EdgeHandleEvents, (void *)EW_T);
EventCallbackRegister(EobjGetWin(w4), EdgeHandleEvents, (void *)EW_B);
}
DeskCurrentGetArea(&cx, &cy);
DesksGetAreaSize(&ax, &ay);
EdgeWindowShow(EW_L, cx != 0 || Conf.desks.areas_wraparound);
EdgeWindowShow(EW_R, cx != (ax - 1) || Conf.desks.areas_wraparound);
EdgeWindowShow(EW_T, cy != 0 || Conf.desks.areas_wraparound);
EdgeWindowShow(EW_B, cy != (ay - 1) || Conf.desks.areas_wraparound);
}
void
EdgeWindowsHide(void)
{
if (!w1)
return;
EobjUnmap(w1);
EobjUnmap(w2);
EobjUnmap(w3);
EobjUnmap(w4);
}