2 * Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors
3 * Copyright (C) 2004-2009 Kim Woelders
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:
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.
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.
25 * Author: Merlin Hughes
28 * This code is free software.
30 * This program is distributed in the hope that it will be useful,
31 * but WITHOUT ANY WARRANTY; without even the implied warranty of
32 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
46 #include <X11/keysym.h>
61 static void WarpFocusHandleEvent(Win win, XEvent * ev, void *prm);
63 static WarpFocusWin *warpFocusWindow = NULL;
65 static int warpFocusIndex = 0;
66 static unsigned int warpFocusKey = 0;
67 static unsigned int warpFocusState = 0;
68 static int warplist_num = 0;
69 static WarplistItem *warplist;
74 WarpFocusWinCreate(void)
78 fw = ECALLOC(WarpFocusWin, 1);
82 EoInit(fw, EOBJ_TYPE_MISC, None, 0, 0, 1, 1, 1, "Warp");
88 EventCallbackRegister(EoGetWin(fw), 0, WarpFocusHandleEvent, NULL);
89 ESelectInput(EoGetWin(fw), ButtonReleaseMask);
91 fw->tc = TextclassFind("WARPFOCUS", 0);
93 fw->tc = TextclassFind("COORDS", 1);
95 fw->ic = ImageclassFind("WARPFOCUS", 0);
97 fw->ic = ImageclassFind("COORDS", 1);
104 WarpFocusWinDestroy(WarpFocusWin * fw)
106 EventCallbackUnregister(EoGetWin(fw), 0, WarpFocusHandleEvent, NULL);
113 WarpFocusWinShow(WarpFocusWin * fw)
118 int i, x, y, w, h, ww, hh;
119 char s[1024], ss[32];
124 pad = ImageclassGetPadding(fw->ic);
126 for (i = 0; i < warplist_num; i++)
129 wi->win = ECreateWindow(EoGetWin(fw), 0, 0, 1, 1, 0);
133 if (ewin->state.iconified)
135 else if (ewin->state.shaded)
140 if (Conf.warplist.showalldesks)
142 if (EoIsSticky(ewin) || ewin->state.iconified)
145 Esnprintf(ss, sizeof(ss), "[%d] ", EoGetDeskNum(ewin));
147 Esnprintf(s, sizeof(s), fmt, ss, EwinGetTitle(ewin));
149 TextSize(fw->tc, 0, 0, 0, wi->txt, &ww, &hh, 17);
156 fw->tw = w; /* Text size */
158 w += pad->left + pad->right;
159 h += pad->top + pad->bottom;
160 if (Conf.warplist.icon_mode != 0)
162 fw->mw = w; /* Focus list item size */
166 EShapeSetMask(EoGetWin(fw), 0, 0, None);
168 ScreenGetAvailableAreaByPointer(&x, &y, &ww, &hh);
170 y += (hh - h * warplist_num) / 2;
171 EoMoveResize(fw, x, y, w, h * warplist_num);
173 for (i = 0; i < warplist_num; i++)
174 EMoveResizeWindow(warplist[i].win, 0, (h * i), fw->mw, fw->mh);
179 * Grab the keyboard. The grab is automatically released when
180 * WarpFocusHide unmaps warpFocusWindow.
182 GrabKeyboardSet(EoGetWin(fw));
183 GrabPointerSet(EoGetWin(fw), None, 0);
189 WarpFocusWinHide(WarpFocusWin * fw)
194 for (i = 0; i < warplist_num; i++)
196 EDestroyWindow(warplist[i].win);
197 Efree(warplist[i].txt);
199 #if 0 /* We might as well keep it around */
200 WarpFocusWinDestroy(fw);
201 warpFocusWindow = NULL;
208 WarpFocusWinPaint(WarpFocusWin * fw)
214 pad = ImageclassGetPadding(fw->ic);
216 for (i = 0; i < warplist_num; i++)
220 if (!EwinFindByPtr(wi->ewin))
225 state = (i == warpFocusIndex) ? STATE_CLICKED : STATE_NORMAL;
227 ImageclassApply(fw->ic, wi->win, 0, 0, state, ST_WARPLIST);
230 if (Conf.warplist.icon_mode != 0)
232 int icon_size = fw->mh - 2 * ICON_PAD;
235 im = EwinIconImageGet(wi->ewin, icon_size,
236 Conf.warplist.icon_mode);
239 EImageRenderOnDrawable(im, wi->win, None,
240 EIMAGE_BLEND | EIMAGE_ANTI_ALIAS,
241 pad->left + ICON_PAD, ICON_PAD,
242 icon_size, icon_size);
248 TextDraw(fw->tc, wi->win, None, 0, 0, state, wi->txt,
249 pad->left + iw, pad->top, fw->tw, fw->th, 0, 0);
252 /* FIXME - Check shape */
253 EoShapeUpdate(fw, 1);
259 WarpFocusWin *fw = warpFocusWindow;
266 warpFocusWindow = fw = WarpFocusWinCreate();
272 WarpFocusWinShow(fw);
274 WarpFocusWinPaint(fw);
280 WarpFocusWin *fw = warpFocusWindow;
282 if (fw && EoIsShown(fw))
283 WarpFocusWinHide(fw);
293 WarpFocusWin *fw = warpFocusWindow;
299 /* Remember invoking keycode (ugly hack) */
300 if (!fw || !EoIsShown(fw))
302 warpFocusKey = Mode.events.last_keycode;
303 warpFocusState = Mode.events.last_keystate;
308 lst = EwinListFocusGet(&num);
309 for (i = 0; i < num; i++)
312 if ( /* Either visible or iconified */
313 ((EwinIsOnScreen(ewin)) || (ewin->state.iconified) ||
314 (Conf.warplist.showalldesks)) &&
315 /* Exclude windows that explicitely say so */
316 (!ewin->props.skip_focuslist) &&
317 (!ewin->props.skip_ext_task) &&
318 /* Keep shaded windows if conf say so */
319 ((!ewin->state.shaded) || (Conf.warplist.showshaded)) &&
320 /* Keep sticky windows if conf say so */
321 ((!EoIsSticky(ewin)) || (Conf.warplist.showsticky)) &&
322 /* Keep iconified windows if conf say so */
323 ((!ewin->state.iconified) || (Conf.warplist.showiconified)))
326 warplist = EREALLOC(WarplistItem, warplist, warplist_num);
327 wl = warplist + warplist_num - 1;
333 if (warplist_num >= 2 && warplist[1].ewin == GetFocusEwin())
335 warplist[1].ewin = warplist[0].ewin;
336 warplist[0].ewin = GetFocusEwin();
345 warpFocusIndex = (warpFocusIndex + warplist_num + delta) % warplist_num;
346 ewin = warplist[warpFocusIndex].ewin;
347 if (!EwinFindByPtr(ewin))
354 if (!EwinIsOnScreen(ewin))
357 if (Conf.focus.raise_on_next)
359 if (Conf.focus.warp_on_next)
361 if (Conf.warplist.warpfocused)
362 FocusToEWin(ewin, FOCUS_SET);
366 WarpFocusClick(int ix)
372 if (ix < 0 || ix >= warplist_num)
374 if (ix == warpFocusIndex)
380 ewin = warplist[ix].ewin;
381 if (!EwinFindByPtr(ewin))
384 if (Conf.focus.raise_on_next)
387 FocusToEWin(ewin, FOCUS_SET);
391 WarpFocusFinish(void)
395 ewin = warplist[warpFocusIndex].ewin;
399 if (!EwinFindByPtr(ewin))
402 EwinOpActivate(ewin, OPSRC_USER, Conf.warplist.raise_on_select);
403 if (Conf.warplist.warp_on_select)
408 WarpFocusHandleEvent(Win win __UNUSED__, XEvent * ev, void *prm __UNUSED__)
410 WarpFocusWin *fw = warpFocusWindow;
420 if (ev->xkey.keycode == warpFocusKey)
422 if (((ev->xkey.state ^ warpFocusState) &
423 Mode.masks.mod_key_mask) == 0)
429 key = XLookupKeysym(&ev->xkey, 0);
447 EQueryPointer(NULL, NULL, NULL, NULL, &mask);
448 if ((mask & Mode.masks.mod_key_mask) == 0)
453 if (ev->xkey.keycode == warpFocusKey)
456 key = XLookupKeysym(&ev->xkey, 0);
471 WarpFocusClick((ev->xbutton.y * warplist_num) / EoGetH(fw));
481 WarplistCfgValidate(void)
483 if (Conf.warplist.icon_mode < 0 || Conf.warplist.icon_mode > 3)
484 Conf.warplist.icon_mode = 3;
488 WarplistSighan(int sig, void *prm __UNUSED__)
493 WarplistCfgValidate();
498 static const CfgItem WarplistCfgItems[] = {
499 CFG_ITEM_BOOL(Conf.warplist, enable, 1),
500 CFG_ITEM_BOOL(Conf.warplist, showsticky, 1),
501 CFG_ITEM_BOOL(Conf.warplist, showshaded, 1),
502 CFG_ITEM_BOOL(Conf.warplist, showiconified, 1),
503 CFG_ITEM_BOOL(Conf.warplist, showalldesks, 0),
504 CFG_ITEM_BOOL(Conf.warplist, warpfocused, 1),
505 CFG_ITEM_BOOL(Conf.warplist, raise_on_select, 1),
506 CFG_ITEM_BOOL(Conf.warplist, warp_on_select, 0),
507 CFG_ITEM_INT(Conf.warplist, icon_mode, 3),
509 #define N_CFG_ITEMS (sizeof(WarplistCfgItems)/sizeof(CfgItem))
511 extern const EModule ModWarplist;
512 const EModule ModWarplist = {
516 {N_CFG_ITEMS, WarplistCfgItems}