e16/src/warp.c

450 lines
11 KiB
C
Raw Normal View History

/*
* Copyright (C) 2000-2005 Carsten Haitzler, Geoff Harrison and various contributors
* Copyright (C) 2004-2005 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.
*/
/*
* Author: Merlin Hughes
* - merlin@merlin.org
*
* This code is free software.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
#include "E.h"
#include "emodule.h"
#include "ewins.h"
#include "icons.h"
#include "tooltips.h"
#include "xwin.h"
2004-12-28 15:46:49 -08:00
#include <X11/keysym.h>
typedef struct
{
EWin *ewin;
Window win;
char *txt;
} WarplistItem;
2004-12-28 15:46:49 -08:00
static void WarpFocusHandleEvent(XEvent * ev, void *prm);
static EObj *warpFocusWindow = NULL;
static int warpFocusIndex = 0;
static unsigned int warpFocusKey = 0;
static int warplist_num = 0;
static WarplistItem *warplist;
2005-09-10 18:50:10 -07:00
static char warpFirst = 0;
#define ICON_PAD 2
static void
WarpFocusShow(EWin * ewin)
{
TextClass *tc;
ImageClass *ic;
int i, x, y, w, h, ww, hh;
static int mw, mh, tw, th;
char s[1024];
const char *fmt;
WarplistItem *wl;
if (!warplist)
return;
2004-12-28 15:46:49 -08:00
tc = TextclassFind("WARPFOCUS", 0);
if (!tc)
2004-12-28 15:46:49 -08:00
tc = TextclassFind("COORDS", 1);
ic = ImageclassFind("WARPFOCUS", 0);
if (!ic)
2004-12-28 15:46:49 -08:00
ic = ImageclassFind("COORDS", 1);
if ((!ic) || (!tc))
return;
if (!warpFocusWindow)
2004-12-28 15:46:49 -08:00
{
EObj *eo;
eo = EobjWindowCreate(EOBJ_TYPE_MISC, 0, 0, 1, 1, 1, "Warp");
if (!eo)
return;
warpFocusWindow = eo;
EventCallbackRegister(eo->win, 0, WarpFocusHandleEvent, NULL);
ESelectInput(eo->win, ButtonReleaseMask);
TooltipsEnable(0);
2004-12-28 15:46:49 -08:00
}
if (!warpFocusWindow->shown)
{
w = 0;
h = 0;
for (i = 0; i < warplist_num; i++)
{
wl = warplist + i;
wl->win = ECreateWindow(warpFocusWindow->win, 0, 0, 1, 1, 0);
EMapWindow(wl->win);
if (wl->ewin->state.iconified)
fmt = "[%s]";
else if (wl->ewin->state.shaded)
fmt = "=%s=";
else
fmt = "%s";
Esnprintf(s, sizeof(s), fmt, EwinGetName(wl->ewin));
wl->txt = strdup(s);
TextSize(tc, 0, 0, 0, wl->txt, &ww, &hh, 17);
if (ww > w)
w = ww;
if (hh > h)
h = hh;
}
tw = w; /* Text size */
th = h;
w += (ic->padding.left + ic->padding.right);
h += (ic->padding.top + ic->padding.bottom);
if (Conf.warplist.icon_mode != 0)
w += h;
mw = w; /* Focus list item size */
mh = h;
GetPointerScreenAvailableArea(&x, &y, &ww, &hh);
x += (ww - w) / 2;
y += (hh - h * warplist_num) / 2;
EobjMoveResize(warpFocusWindow, x, y, w, h * warplist_num);
for (i = 0; i < warplist_num; i++)
{
EMoveResizeWindow(warplist[i].win, 0, (h * i), mw, mh);
}
EobjMap(warpFocusWindow, 0);
/*
* Grab the keyboard. The grab is automatically released when
* WarpFocusHide unmaps warpFocusWindow.
*/
GrabKeyboardSet(warpFocusWindow->win);
GrabPointerSet(warpFocusWindow->win, None, 0);
2005-09-10 18:50:10 -07:00
warpFirst = 1;
}
for (i = 0; i < warplist_num; i++)
{
wl = warplist + i;
if (!EwinFindByPtr(wl->ewin))
wl->ewin = NULL;
if (wl->ewin)
{
int state;
state = (ewin == wl->ewin) ? STATE_CLICKED : STATE_NORMAL;
ImageclassApply(ic, wl->win, mw, mh, 0, 0, state, 0, ST_WARPLIST);
/* New icon stuff */
if (Conf.warplist.icon_mode != 0)
{
int icon_size = mh - 2 * ICON_PAD;
Imlib_Image *im;
TextDraw(tc, wl->win, 0, 0, state, wl->txt,
ic->padding.left + mh, ic->padding.top,
tw, th, 0, 0);
im = EwinIconImageGet(wl->ewin, icon_size,
Conf.warplist.icon_mode);
if (!im)
continue;
imlib_context_set_image(im);
imlib_context_set_drawable(wl->win);
imlib_context_set_blend(1);
imlib_render_image_on_drawable_at_size(ic->padding.left +
ICON_PAD, ICON_PAD,
icon_size, icon_size);
imlib_free_image();
imlib_context_set_blend(0);
}
else
{
TextclassApply(ic, wl->win, mw, mh, 0, 0, state, 0,
tc, wl->txt);
}
}
}
/* FIXME - Check shape */
EShapePropagate(warpFocusWindow->win);
EobjChangeShape(warpFocusWindow);
EFlush();
}
static void
WarpFocusHide(void)
{
int i;
if (warpFocusWindow && warpFocusWindow->shown)
{
EobjUnmap(warpFocusWindow);
for (i = 0; i < warplist_num; i++)
{
EDestroyWindow(warplist[i].win);
Efree(warplist[i].txt);
}
#if 0 /* We might as well keep it around */
EventCallbackUnregister(warpFocusWindow->win, 0, WarpFocusHandleEvent,
NULL);
EobjWindowDestroy(warpFocusWindow);
warpFocusWindow = None;
#endif
TooltipsEnable(1);
}
if (warplist)
Efree(warplist);
warplist = NULL;
warplist_num = 0;
}
2004-12-28 15:46:49 -08:00
void
WarpFocus(int delta)
{
EWin *const *lst;
EWin *ewin;
int i, num;
WarplistItem *wl;
2004-12-28 15:46:49 -08:00
/* Remember invoking keycode (ugly hack) */
if (!warpFocusWindow || !warpFocusWindow->shown)
warpFocusKey = Mode.events.last_keycode;
2004-12-28 15:46:49 -08:00
if (!warplist)
2004-12-28 15:46:49 -08:00
{
lst = EwinListFocusGet(&num);
for (i = 0; i < num; i++)
2004-12-28 15:46:49 -08:00
{
ewin = lst[i];
2004-12-28 15:46:49 -08:00
if ( /* Either visible or iconified */
((EwinIsOnScreen(ewin)) || (ewin->state.iconified)) &&
2004-12-28 15:46:49 -08:00
/* Exclude windows that explicitely say so */
(!ewin->props.skip_focuslist) &&
2005-09-10 18:50:10 -07:00
(!ewin->props.skip_ext_task) &&
2004-12-28 15:46:49 -08:00
/* Keep shaded windows if conf say so */
((!ewin->state.shaded) || (Conf.warplist.showshaded)) &&
2004-12-28 15:46:49 -08:00
/* Keep sticky windows if conf say so */
((!EoIsSticky(ewin)) || (Conf.warplist.showsticky)) &&
/* Keep iconified windows if conf say so */
((!ewin->state.iconified) || (Conf.warplist.showiconified)))
{
warplist_num++;
warplist = Erealloc(warplist,
warplist_num * sizeof(WarplistItem));
wl = warplist + warplist_num - 1;
wl->ewin = ewin;
}
2004-12-28 15:46:49 -08:00
}
/* Hmmm. Hack... */
if (warplist_num >= 2 && warplist[1].ewin == GetFocusEwin())
2004-12-28 15:46:49 -08:00
{
warplist[1].ewin = warplist[0].ewin;
warplist[0].ewin = GetFocusEwin();
2004-12-28 15:46:49 -08:00
}
warpFocusIndex = 0;
2004-12-28 15:46:49 -08:00
}
if (!warplist)
return;
warpFocusIndex = (warpFocusIndex + warplist_num + delta) % warplist_num;
ewin = warplist[warpFocusIndex].ewin;
if (!EwinFindByPtr(ewin))
ewin = NULL;
if (!ewin)
return;
2005-07-09 15:55:56 -07:00
WarpFocusShow(ewin);
if (Conf.focus.raise_on_next)
RaiseEwin(ewin);
if (Conf.focus.warp_on_next)
if (ewin != Mode.mouse_over_ewin && !ewin->state.iconified)
2005-07-09 15:55:56 -07:00
{
EWarpPointer(EoGetWin(ewin), EoGetW(ewin) / 2, EoGetH(ewin) / 2);
2005-07-09 15:55:56 -07:00
Mode.mouse_over_ewin = ewin;
}
if (Conf.warplist.warpfocused)
FocusToEWin(ewin, FOCUS_SET);
2004-12-28 15:46:49 -08:00
}
static void
WarpFocusClick(int ix)
2004-12-28 15:46:49 -08:00
{
EWin *ewin;
if (!warplist)
return;
2004-12-28 15:46:49 -08:00
ewin = warplist[ix].ewin;
if (!EwinFindByPtr(ewin))
return;
2004-12-28 15:46:49 -08:00
RaiseEwin(ewin);
if (ewin->state.iconified)
EwinDeIconify(ewin);
FocusToEWin(ewin, FOCUS_SET);
}
static void
WarpFocusFinish(void)
{
EWin *ewin;
ewin = warplist[warpFocusIndex].ewin;
2004-12-28 15:46:49 -08:00
WarpFocusHide();
if (!EwinFindByPtr(ewin))
return;
2004-12-28 15:46:49 -08:00
if (ewin->state.iconified)
EwinDeIconify(ewin);
if (ewin->state.shaded)
EwinUnShade(ewin);
if (Conf.warplist.raise_on_select)
RaiseEwin(ewin);
if (Conf.warplist.warp_on_select)
if (ewin != Mode.mouse_over_ewin)
2005-07-09 15:55:56 -07:00
{
EWarpPointer(EoGetWin(ewin), EoGetW(ewin) / 2, EoGetH(ewin) / 2);
2005-07-09 15:55:56 -07:00
Mode.mouse_over_ewin = ewin;
}
FocusToEWin(ewin, FOCUS_SET);
2004-12-28 15:46:49 -08:00
}
static void
WarpFocusHandleEvent(XEvent * ev, void *prm __UNUSED__)
{
KeySym key;
2004-12-28 15:46:49 -08:00
switch (ev->type)
{
#if 0 /* Not necessary when sampling keycode in events.c */
case KeyPress:
if (warpFocusWindow->shown && ev->xany.window == VRoot.win)
2004-12-28 15:46:49 -08:00
warpFocusKey = ev->xkey.keycode;
break;
#endif
case KeyRelease:
2005-09-10 18:50:10 -07:00
if (!warpFocusWindow->shown)
break;
2005-09-10 18:50:10 -07:00
if (warpFirst)
{
warpFirst = 0;
break;
}
if (ev->xkey.keycode == warpFocusKey)
key = XK_Tab;
else
key = XLookupKeysym(&ev->xkey, 0);
switch (key)
{
default:
WarpFocusFinish();
break;
2005-09-10 18:50:10 -07:00
case XK_Tab:
case XK_Down:
WarpFocus(1);
break;
case XK_Up:
WarpFocus(-1);
break;
}
2004-12-28 15:46:49 -08:00
break;
case ButtonRelease:
WarpFocusClick((ev->xbutton.y * warplist_num) / warpFocusWindow->h);
break;
2004-12-28 15:46:49 -08:00
}
}
static void
WarplistInit(void)
{
#if 0 /* Not necessary when sampling keycode in events.c */
/* Ugly hack to get the invoking key press */
EventCallbackRegister(VRoot.win, 0, WarpFocusHandleEvent, NULL);
#endif
}
/*
* Warplist module
*/
static void
WarplistCfgValidate(void)
{
if (Conf.warplist.icon_mode < 0 || Conf.warplist.icon_mode > 3)
Conf.warplist.icon_mode = 3;
}
2004-12-28 15:46:49 -08:00
static void
WarplistSighan(int sig, void *prm __UNUSED__)
{
switch (sig)
{
case ESIGNAL_INIT:
WarplistInit();
WarplistCfgValidate();
2004-12-28 15:46:49 -08:00
break;
}
}
static const CfgItem WarplistCfgItems[] = {
CFG_ITEM_INT(Conf.warplist, icon_mode, 3),
2004-12-28 15:46:49 -08:00
CFG_ITEM_BOOL(Conf.warplist, enable, 1),
CFG_ITEM_BOOL(Conf.warplist, showsticky, 1),
CFG_ITEM_BOOL(Conf.warplist, showshaded, 1),
CFG_ITEM_BOOL(Conf.warplist, showiconified, 0),
CFG_ITEM_BOOL(Conf.warplist, warpfocused, 1),
CFG_ITEM_BOOL(Conf.warplist, raise_on_select, 1),
CFG_ITEM_BOOL(Conf.warplist, warp_on_select, 0),
};
#define N_CFG_ITEMS (sizeof(WarplistCfgItems)/sizeof(CfgItem))
EModule ModWarplist = {
"warplist", "warp",
WarplistSighan,
{0, NULL},
{N_CFG_ITEMS, WarplistCfgItems}
};