1 /*
2 * Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors
3 * Copyright (C) 2004-2015 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 "config.h"
25
26 #include <X11/Xlib.h>
27
28 #include "E.h"
29 #include "desktops.h"
30 #include "eobj.h"
31 #include "ewins.h"
32 #include "menus.h" /* FIXME - Should not be here */
33 #include "timers.h"
34 #include "xwin.h"
35
36 static EObj *w1 = NULL, *w2 = NULL, *w3 = NULL, *w4 = NULL;
37 static Timer *edge_timer = NULL;
38
39 static int
EdgeTimeout(void * data)40 EdgeTimeout(void *data)
41 {
42 int val;
43 int ax, ay, aw, ah, dx, dy, dax, day;
44 EWin *ewin;
45
46 if (MenusActive())
47 goto done;
48 if (Conf.desks.edge_flip_mode == EDGE_FLIP_OFF)
49 goto done;
50
51 /* Quit if pointer has left screen */
52 if (!EQueryPointer(NULL, NULL, NULL, NULL, NULL))
53 goto done;
54
55 /* Quit if in fullscreen window */
56 ewin = GetEwinPointerInClient();
57 if (ewin && ewin->state.fullscreen)
58 goto done;
59
60 DeskCurrentGetArea(&ax, &ay);
61 DesksGetAreaSize(&aw, &ah);
62 val = PTR2INT(data);
63 dx = 0;
64 dy = 0;
65 dax = 0;
66 day = 0;
67 switch (val)
68 {
69 case 0:
70 if (ax == 0 && !Conf.desks.areas_wraparound)
71 goto done;
72 dx = WinGetW(VROOT) - 2;
73 dax = -1;
74 break;
75 case 1:
76 if (ax == (aw - 1) && !Conf.desks.areas_wraparound)
77 goto done;
78 dx = -(WinGetW(VROOT) - 2);
79 dax = 1;
80 break;
81 case 2:
82 if (ay == 0 && !Conf.desks.areas_wraparound)
83 goto done;
84 dy = WinGetH(VROOT) - 2;
85 day = -1;
86 break;
87 case 3:
88 if (ay == (ah - 1) && !Conf.desks.areas_wraparound)
89 goto done;
90 dy = -(WinGetH(VROOT) - 2);
91 day = 1;
92 break;
93 default:
94 break;
95 }
96 if (aw == 1)
97 dx = 0;
98 if (ah == 1)
99 dy = 0;
100 Mode.events.px = Mode.events.mx;
101 Mode.events.py = Mode.events.my;
102 Mode.events.mx = Mode.events.cx += dx;
103 Mode.events.my = Mode.events.cy += dy;
104 EWarpPointer(VROOT, Mode.events.mx, Mode.events.my);
105 DeskCurrentMoveAreaBy(dax, day);
106 Mode.events.px = Mode.events.mx;
107 Mode.events.py = Mode.events.my;
108
109 done:
110 edge_timer = NULL;
111 return 0;
112 }
113
114 static void
EdgeEvent(int dir)115 EdgeEvent(int dir)
116 {
117 static int lastdir = -1;
118
119 #if 0
120 Eprintf("%s: %d -> %d\n", __func__, lastdir, dir);
121 #endif
122 if (lastdir == dir || Conf.desks.edge_flip_mode == EDGE_FLIP_OFF)
123 return;
124
125 if (Conf.desks.edge_flip_mode == EDGE_FLIP_MOVE && Mode.mode != MODE_MOVE)
126 return;
127
128 TIMER_DEL(edge_timer);
129 if (dir >= 0)
130 {
131 if (Conf.desks.edge_flip_resistance <= 0)
132 Conf.desks.edge_flip_resistance = 1;
133 TIMER_ADD(edge_timer, 10 * Conf.desks.edge_flip_resistance,
134 EdgeTimeout, INT2PTR(dir));
135 }
136 lastdir = dir;
137 }
138
139 static void
EdgeHandleEvents(Win win __UNUSED__,XEvent * ev,void * prm)140 EdgeHandleEvents(Win win __UNUSED__, XEvent * ev, void *prm)
141 {
142 int dir;
143
144 dir = PTR2INT(prm);
145
146 switch (ev->type)
147 {
148 default:
149 break;
150
151 case EnterNotify:
152 EdgeEvent(dir);
153 break;
154
155 case LeaveNotify:
156 EdgeEvent(-1);
157 break;
158 }
159 }
160
161 void
EdgeCheckMotion(int x,int y)162 EdgeCheckMotion(int x, int y)
163 {
164 int dir;
165
166 if (x == 0)
167 dir = 0;
168 else if (x == WinGetW(VROOT) - 1)
169 dir = 1;
170 else if (y == 0)
171 dir = 2;
172 else if (y == WinGetH(VROOT) - 1)
173 dir = 3;
174 else
175 dir = -1;
176 EdgeEvent(dir);
177 }
178
179 static void
EdgeWindowShow(int which,int on)180 EdgeWindowShow(int which, int on)
181 {
182 EObj *eo;
183 int x, y, w, h;
184
185 x = y = 0;
186 w = h = 1;
187
188 switch (which)
189 {
190 default:
191 case 1: /* Left */
192 eo = w1;
193 h = WinGetH(VROOT);
194 break;
195 case 2: /* Right */
196 eo = w2;
197 x = WinGetW(VROOT) - 1;
198 h = WinGetH(VROOT);
199 break;
200 case 3: /* Top */
201 eo = w3;
202 w = WinGetW(VROOT);
203 break;
204 case 4: /* Bottom */
205 eo = w4;
206 y = WinGetH(VROOT) - 1;
207 w = WinGetW(VROOT);
208 break;
209 }
210
211 if (on)
212 {
213 EobjMoveResize(eo, x, y, w, h);
214 EobjMap(eo, 0);
215 }
216 else
217 {
218 EobjUnmap(eo);
219 }
220 }
221
222 void
EdgeWindowsShow(void)223 EdgeWindowsShow(void)
224 {
225 int ax, ay, cx, cy;
226
227 if (Conf.desks.edge_flip_mode == EDGE_FLIP_OFF)
228 {
229 EdgeWindowsHide();
230 return;
231 }
232
233 if (!w1)
234 {
235 w1 = EobjWindowCreate(EOBJ_TYPE_EVENT,
236 0, 0, 1, WinGetH(VROOT), 0, "Edge-L");
237 w2 = EobjWindowCreate(EOBJ_TYPE_EVENT,
238 WinGetW(VROOT) - 1, 0, 1, WinGetH(VROOT),
239 0, "Edge-R");
240 w3 = EobjWindowCreate(EOBJ_TYPE_EVENT,
241 0, 0, WinGetW(VROOT), 1, 0, "Edge-T");
242 w4 = EobjWindowCreate(EOBJ_TYPE_EVENT,
243 0, WinGetH(VROOT) - 1, WinGetW(VROOT), 1,
244 0, "Edge-B");
245 ESelectInput(EobjGetWin(w1), EnterWindowMask | LeaveWindowMask);
246 ESelectInput(EobjGetWin(w2), EnterWindowMask | LeaveWindowMask);
247 ESelectInput(EobjGetWin(w3), EnterWindowMask | LeaveWindowMask);
248 ESelectInput(EobjGetWin(w4), EnterWindowMask | LeaveWindowMask);
249 EventCallbackRegister(EobjGetWin(w1), EdgeHandleEvents, (void *)0);
250 EventCallbackRegister(EobjGetWin(w2), EdgeHandleEvents, (void *)1);
251 EventCallbackRegister(EobjGetWin(w3), EdgeHandleEvents, (void *)2);
252 EventCallbackRegister(EobjGetWin(w4), EdgeHandleEvents, (void *)3);
253 }
254 DeskCurrentGetArea(&cx, &cy);
255 DesksGetAreaSize(&ax, &ay);
256
257 EdgeWindowShow(1, cx != 0 || Conf.desks.areas_wraparound);
258 EdgeWindowShow(2, cx != (ax - 1) || Conf.desks.areas_wraparound);
259 EdgeWindowShow(3, cy != 0 || Conf.desks.areas_wraparound);
260 EdgeWindowShow(4, cy != (ay - 1) || Conf.desks.areas_wraparound);
261 }
262
263 void
EdgeWindowsHide(void)264 EdgeWindowsHide(void)
265 {
266 if (!w1)
267 return;
268
269 EobjUnmap(w1);
270 EobjUnmap(w2);
271 EobjUnmap(w3);
272 EobjUnmap(w4);
273 }
274