chiark / gitweb /
Imported Upstream version 1.0.0
[e16] / src / edge.c
1 /*
2  * Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors
3  * Copyright (C) 2004-2008 Kim Woelders
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy
6  * of this software and associated documentation files (the "Software"), to
7  * deal in the Software without restriction, including without limitation the
8  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9  * sell copies of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies of the Software, its documentation and marketing & publicity
14  * materials, and acknowledgment shall be given in the documentation, materials
15  * and software packages that this Software was used.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20  * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24 #include "E.h"
25 #include "desktops.h"
26 #include "eobj.h"
27 #include "ewins.h"
28 #include "menus.h"              /* FIXME - Should not be here */
29 #include "timers.h"
30 #include "xwin.h"
31
32 static EObj        *w1 = NULL, *w2 = NULL, *w3 = NULL, *w4 = NULL;
33 static Timer       *edge_timer = NULL;
34
35 static int
36 EdgeTimeout(void *data)
37 {
38    int                 val;
39    int                 ax, ay, aw, ah, dx, dy, dax, day;
40    EWin               *ewin;
41
42    if (MenusActive())
43       goto done;
44    if (Conf.desks.edge_flip_mode == EDGE_FLIP_OFF)
45       goto done;
46
47    /* Quit if pointer has left screen */
48    if (!EQueryPointer(NULL, NULL, NULL, NULL, NULL))
49       goto done;
50
51    /* Quit if in fullscreen window */
52    ewin = GetEwinPointerInClient();
53    if (ewin && ewin->state.fullscreen)
54       goto done;
55
56    DeskCurrentGetArea(&ax, &ay);
57    DesksGetAreaSize(&aw, &ah);
58    val = PTR2INT(data);
59    dx = 0;
60    dy = 0;
61    dax = 0;
62    day = 0;
63    switch (val)
64      {
65      case 0:
66         if (ax == 0 && !Conf.desks.areas_wraparound)
67            goto done;
68         dx = WinGetW(VROOT) - 2;
69         dax = -1;
70         break;
71      case 1:
72         if (ax == (aw - 1) && !Conf.desks.areas_wraparound)
73            goto done;
74         dx = -(WinGetW(VROOT) - 2);
75         dax = 1;
76         break;
77      case 2:
78         if (ay == 0 && !Conf.desks.areas_wraparound)
79            goto done;
80         dy = WinGetH(VROOT) - 2;
81         day = -1;
82         break;
83      case 3:
84         if (ay == (ah - 1) && !Conf.desks.areas_wraparound)
85            goto done;
86         dy = -(WinGetH(VROOT) - 2);
87         day = 1;
88         break;
89      default:
90         break;
91      }
92    if (aw == 1)
93       dx = 0;
94    if (ah == 1)
95       dy = 0;
96    Mode.events.px = Mode.events.mx;
97    Mode.events.py = Mode.events.my;
98    Mode.events.mx = Mode.events.cx += dx;
99    Mode.events.my = Mode.events.cy += dy;
100    EXWarpPointer(WinGetXwin(VROOT), Mode.events.mx, Mode.events.my);
101    DeskCurrentMoveAreaBy(dax, day);
102    Mode.events.px = Mode.events.mx;
103    Mode.events.py = Mode.events.my;
104
105  done:
106    edge_timer = NULL;
107    return 0;
108 }
109
110 static void
111 EdgeEvent(int dir)
112 {
113    static int          lastdir = -1;
114
115 #if 0
116    Eprintf("EdgeEvent %d -> %d\n", lastdir, dir);
117 #endif
118    if (lastdir == dir || Conf.desks.edge_flip_mode == EDGE_FLIP_OFF)
119       return;
120
121    if (Conf.desks.edge_flip_mode == EDGE_FLIP_MOVE && Mode.mode != MODE_MOVE)
122       return;
123
124    TIMER_DEL(edge_timer);
125    if (dir >= 0)
126      {
127         if (Conf.desks.edge_flip_resistance <= 0)
128            Conf.desks.edge_flip_resistance = 1;
129         TIMER_ADD(edge_timer, ((double)Conf.desks.edge_flip_resistance) / 100.0,
130                   EdgeTimeout, INT2PTR(dir));
131      }
132    lastdir = dir;
133 }
134
135 static void
136 EdgeHandleEvents(Win win __UNUSED__, XEvent * ev, void *prm)
137 {
138    int                 dir;
139
140    dir = (long)prm;
141
142    switch (ev->type)
143      {
144      default:
145         break;
146
147      case EnterNotify:
148         EdgeEvent(dir);
149         break;
150
151      case LeaveNotify:
152         EdgeEvent(-1);
153         break;
154      }
155 }
156
157 void
158 EdgeCheckMotion(int x, int y)
159 {
160    int                 dir;
161
162    if (x == 0)
163       dir = 0;
164    else if (x == WinGetW(VROOT) - 1)
165       dir = 1;
166    else if (y == 0)
167       dir = 2;
168    else if (y == WinGetH(VROOT) - 1)
169       dir = 3;
170    else
171       dir = -1;
172    EdgeEvent(dir);
173 }
174
175 static void
176 EdgeWindowShow(int which, int on)
177 {
178    EObj               *eo;
179    int                 x, y, w, h;
180
181    x = y = 0;
182    w = h = 1;
183
184    switch (which)
185      {
186      default:
187      case 1:                    /* Left */
188         eo = w1;
189         h = WinGetH(VROOT);
190         break;
191      case 2:                    /* Right */
192         eo = w2;
193         x = WinGetW(VROOT) - 1;
194         h = WinGetH(VROOT);
195         break;
196      case 3:                    /* Top */
197         eo = w3;
198         w = WinGetW(VROOT);
199         break;
200      case 4:                    /* Bottom */
201         eo = w4;
202         y = WinGetH(VROOT) - 1;
203         w = WinGetW(VROOT);
204         break;
205      }
206
207    if (on)
208      {
209         EobjMoveResize(eo, x, y, w, h);
210         EobjMap(eo, 0);
211      }
212    else
213      {
214         EobjUnmap(eo);
215      }
216 }
217
218 void
219 EdgeWindowsShow(void)
220 {
221    int                 ax, ay, cx, cy;
222
223    if (Conf.desks.edge_flip_mode == EDGE_FLIP_OFF)
224      {
225         EdgeWindowsHide();
226         return;
227      }
228
229    if (!w1)
230      {
231         w1 = EobjWindowCreate(EOBJ_TYPE_EVENT,
232                               0, 0, 1, WinGetH(VROOT), 0, "Edge-L");
233         w2 = EobjWindowCreate(EOBJ_TYPE_EVENT,
234                               WinGetW(VROOT) - 1, 0, 1, WinGetH(VROOT),
235                               0, "Edge-R");
236         w3 = EobjWindowCreate(EOBJ_TYPE_EVENT,
237                               0, 0, WinGetW(VROOT), 1, 0, "Edge-T");
238         w4 = EobjWindowCreate(EOBJ_TYPE_EVENT,
239                               0, WinGetH(VROOT) - 1, WinGetW(VROOT), 1,
240                               0, "Edge-B");
241         ESelectInput(EobjGetWin(w1), EnterWindowMask | LeaveWindowMask);
242         ESelectInput(EobjGetWin(w2), EnterWindowMask | LeaveWindowMask);
243         ESelectInput(EobjGetWin(w3), EnterWindowMask | LeaveWindowMask);
244         ESelectInput(EobjGetWin(w4), EnterWindowMask | LeaveWindowMask);
245         EventCallbackRegister(EobjGetWin(w1), 0, EdgeHandleEvents, (void *)0);
246         EventCallbackRegister(EobjGetWin(w2), 0, EdgeHandleEvents, (void *)1);
247         EventCallbackRegister(EobjGetWin(w3), 0, EdgeHandleEvents, (void *)2);
248         EventCallbackRegister(EobjGetWin(w4), 0, EdgeHandleEvents, (void *)3);
249      }
250    DeskCurrentGetArea(&cx, &cy);
251    DesksGetAreaSize(&ax, &ay);
252
253    EdgeWindowShow(1, cx != 0 || Conf.desks.areas_wraparound);
254    EdgeWindowShow(2, cx != (ax - 1) || Conf.desks.areas_wraparound);
255    EdgeWindowShow(3, cy != 0 || Conf.desks.areas_wraparound);
256    EdgeWindowShow(4, cy != (ay - 1) || Conf.desks.areas_wraparound);
257 }
258
259 void
260 EdgeWindowsHide(void)
261 {
262    if (!w1)
263       return;
264
265    EobjUnmap(w1);
266    EobjUnmap(w2);
267    EobjUnmap(w3);
268    EobjUnmap(w4);
269 }