e16/src/focus.c

1026 lines
25 KiB
C

/*
* Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors
* Copyright (C) 2004-2007 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 "E.h"
#include "cursors.h"
#include "desktops.h" /* FIXME - Should not be here */
#include "dialog.h"
#include "emodule.h"
#include "ewins.h"
#include "focus.h"
#include "grabs.h"
#include "hints.h"
#include "timers.h"
#include "xwin.h"
#define EwinListFocusRaise(ewin) EobjListFocusRaise(EoObj(ewin))
#define EwinListFocusLower(ewin) EobjListFocusLower(EoObj(ewin))
static char focus_inhibit = 1;
static char focus_is_set = 0;
static char focus_pending_update_grabs = 0;
static int focus_pending_why = 0;
static EWin *focus_pending_ewin = NULL;
static EWin *focus_pending_new = NULL;
void
FocusEnable(int on)
{
if (on)
{
if (focus_inhibit > 0)
focus_inhibit--;
}
else
{
focus_inhibit++;
}
if (EDebug(EDBUG_TYPE_FOCUS))
Eprintf("FocusEnable inhibit=%d\n", focus_inhibit);
}
/*
* Return !0 if it is OK to focus ewin.
*/
static int
FocusEwinValid(EWin * ewin, int want_on_screen, int click, int want_visible)
{
if (!ewin)
return 0;
#if 0
Eprintf("FocusEwinValid %#lx %s: st=%d sh=%d inh=%d cl=%d(%d) vis=%d(%d)\n",
EwinGetClientXwin(ewin), EwinGetTitle(ewin),
ewin->state.state, EoIsShown(ewin), ewin->state.inhibit_focus,
click, ewin->props.focusclick, want_visible, ewin->state.visibility);
#endif
if (ewin->state.inhibit_focus)
return 0;
if (!EwinIsMapped(ewin) || !EoIsShown(ewin))
return 0;
if (ewin->props.focusclick && !click)
return 0;
if (want_visible && ewin->state.visibility == VisibilityFullyObscured)
return 0;
return !want_on_screen || EwinIsOnScreen(ewin);
}
/*
* Return the ewin to focus after entering area or losing focused window.
*/
static EWin *
FocusEwinSelect(void)
{
EWin *const *lst, *ewin;
int num, i;
switch (Conf.focus.mode)
{
default:
case MODE_FOCUS_POINTER:
ewin = GetEwinPointerInClient();
if (ewin && !FocusEwinValid(ewin, 1, 0, 0))
ewin = NULL;
break;
case MODE_FOCUS_SLOPPY:
ewin = GetEwinPointerInClient();
if (ewin && FocusEwinValid(ewin, 1, 0, 0))
break;
goto do_select;
case MODE_FOCUS_CLICK:
goto do_select;
do_select:
ewin = NULL;
lst = EwinListFocusGet(&num);
for (i = 0; i < num; i++)
{
if (!FocusEwinValid(lst[i], 1, 0, 0) ||
lst[i]->props.skip_focuslist)
continue;
ewin = lst[i];
break;
}
break;
}
return ewin;
}
static void
AutoraiseTimeout(int val, void *data __UNUSED__)
{
EWin *ewin;
if (Conf.focus.mode == MODE_FOCUS_CLICK)
return;
ewin = EwinFindByClient(val);
if (ewin)
EwinRaise(ewin);
}
static void
ReverseTimeout(int val, void *data __UNUSED__)
{
EWin *ewin;
ewin = EwinFindByClient(val);
if (ewin)
EwinListFocusRaise(ewin);
}
static void
FocusGetNextEwin(void)
{
EWin *const *lst;
EWin *ewin;
int i, num;
lst = EwinListFocusGet(&num);
if (num <= 1)
return;
ewin = NULL;
for (i = num - 1; i >= 0; i--)
{
if (!FocusEwinValid(lst[i], 1, 0, 0) || lst[i]->props.skip_focuslist)
continue;
ewin = lst[i];
break;
}
if (ewin)
FocusToEWin(ewin, FOCUS_NEXT);
}
static void
FocusGetPrevEwin(void)
{
EWin *const *lst;
EWin *ewin;
int i, num;
lst = EwinListFocusGet(&num);
if (num <= 1)
return;
ewin = NULL;
for (i = 1; i < num; i++)
{
if (!FocusEwinValid(lst[i], 1, 0, 0) || lst[i]->props.skip_focuslist)
continue;
ewin = lst[i];
break;
}
if (ewin)
FocusToEWin(ewin, FOCUS_PREV);
}
static void
FocusEwinSetGrabs(EWin * ewin)
{
int set = 0;
if (((Conf.focus.mode == MODE_FOCUS_CLICK || ewin->props.focusclick) &&
!ewin->state.active) ||
(Conf.focus.clickraises && !EwinListStackIsRaised(ewin)))
set = 1;
if (set)
{
if (!ewin->state.click_grab_isset)
{
GrabButtonSet(AnyButton, AnyModifier, EwinGetContainerWin(ewin),
ButtonPressMask, ECSR_PGRAB, 1);
if (EDebug(EDBUG_TYPE_GRABS))
Eprintf("FocusEwinSetGrabs: %#lx set %s\n",
EwinGetClientXwin(ewin), EwinGetTitle(ewin));
ewin->state.click_grab_isset = 1;
}
}
else
{
if (ewin->state.click_grab_isset)
{
GrabButtonRelease(AnyButton, AnyModifier,
EwinGetContainerWin(ewin));
if (EDebug(EDBUG_TYPE_GRABS))
Eprintf("FocusEwinSetGrabs: %#lx unset %s\n",
EwinGetClientXwin(ewin), EwinGetTitle(ewin));
ewin->state.click_grab_isset = 0;
}
}
}
static void
FocusEwinSetActive(EWin * ewin, int active)
{
if (ewin->state.active == active)
return;
ewin->state.active = active;
EwinBorderUpdateState(ewin);
EwinUpdateOpacity(ewin);
FocusGrabsUpdate();
if (active && ewin->state.attention)
{
ewin->state.attention = 0;
HintsSetWindowState(ewin);
}
}
static void
doFocusGrabsUpdate(void)
{
EWin *const *lst, *ewin;
int i, num;
lst = EwinListGetAll(&num);
for (i = 0; i < num; i++)
{
ewin = lst[i];
FocusEwinSetGrabs(ewin);
}
focus_pending_update_grabs = 0;
}
void
FocusGrabsUpdate(void)
{
focus_pending_update_grabs = 1;
}
static void
doFocusToEwin(EWin * ewin, int why)
{
int do_focus = 0;
int do_raise = 0, do_warp = 0;
if (focus_inhibit)
return;
if (EDebug(EDBUG_TYPE_FOCUS))
Eprintf("doFocusToEWin %#lx %s why=%d\n",
(ewin) ? EwinGetClientXwin(ewin) : 0,
(ewin) ? EwinGetTitle(ewin) : "None", why);
switch (why)
{
case FOCUS_NEXT:
case FOCUS_PREV:
if (Conf.focus.raise_on_next)
do_raise = 1;
if (Conf.focus.warp_on_next)
do_warp = 1;
/* Fall thru */
default:
case FOCUS_SET:
case FOCUS_ENTER:
case FOCUS_LEAVE: /* Unused */
case FOCUS_CLICK:
if (ewin && ewin == Mode.focuswin)
return;
if (ewin == NULL) /* Unfocus */
break;
if (!FocusEwinValid(ewin, 1, why == FOCUS_CLICK, 0))
return;
break;
case FOCUS_INIT:
case FOCUS_DESK_ENTER:
ewin = FocusEwinSelect();
break;
case FOCUS_DESK_LEAVE:
focus_is_set = 0;
case FOCUS_NONE:
ewin = NULL;
if (ewin == Mode.focuswin)
return;
break;
case FOCUS_EWIN_UNMAP:
if (Mode.focuswin)
return;
ewin = FocusEwinSelect();
if (ewin == Mode.focuswin)
ewin = NULL;
break;
case FOCUS_EWIN_NEW:
if (Conf.focus.all_new_windows_get_focus)
do_focus = 1;
else if (Mode.place.doing_manual)
do_focus = 1;
if (ewin->props.focus_when_mapped)
do_focus = 2;
if (EwinIsTransient(ewin))
{
if (Conf.focus.new_transients_get_focus)
{
do_focus = 2;
}
else if (Conf.focus.new_transients_get_focus_if_group_focused)
{
EWin *ewin2;
ewin2 = EwinFindByClient(EwinGetTransientFor(ewin));
if ((ewin2) && (Mode.focuswin == ewin2))
do_focus = 2;
}
if (do_focus == 2)
DeskGotoByEwin(ewin);
}
if (!do_focus)
return;
if (!FocusEwinValid(ewin, 1, 0, 0))
return;
break;
}
if (ewin == Mode.focuswin && focus_is_set)
return;
/* Check if ewin is a valid focus window target */
if (!ewin)
goto done;
/* NB! ewin != NULL */
if (why != FOCUS_CLICK && ewin->props.focusclick)
return;
if (Conf.autoraise.enable)
{
RemoveTimerEvent("AUTORAISE_TIMEOUT");
if (Conf.focus.mode != MODE_FOCUS_CLICK)
DoIn("AUTORAISE_TIMEOUT", 0.001 * Conf.autoraise.delay,
AutoraiseTimeout, EwinGetClientXwin(ewin), NULL);
}
if (do_raise)
EwinRaise(ewin);
if (Conf.focus.warp_always)
do_warp = 1;
if (do_warp && ewin != Mode.mouse_over_ewin)
{
EXWarpPointer(EoGetXwin(ewin), EoGetW(ewin) / 2, EoGetH(ewin) / 2);
Mode.mouse_over_ewin = ewin;
}
RemoveTimerEvent("REVERSE_FOCUS_TIMEOUT");
switch (why)
{
case FOCUS_PREV:
DoIn("REVERSE_FOCUS_TIMEOUT", 0.5, ReverseTimeout,
EwinGetClientXwin(ewin), NULL);
break;
case FOCUS_DESK_ENTER:
if (Conf.focus.mode == MODE_FOCUS_CLICK)
break;
default:
case FOCUS_INIT:
case FOCUS_NEXT:
EwinListFocusRaise(ewin);
break;
}
SoundPlay("SOUND_FOCUS_SET");
done:
/* Unset old focus window (if any) highlighting */
if (Mode.focuswin)
FocusEwinSetActive(Mode.focuswin, 0);
ICCCM_Cmap(ewin);
/* Quit if pointer is not on our screen */
if (!EQueryPointer(NULL, NULL, NULL, NULL, NULL))
{
Mode.focuswin = NULL;
return;
}
/* Set new focus window (if any) highlighting */
Mode.focuswin = ewin;
if (Mode.focuswin)
FocusEwinSetActive(Mode.focuswin, 1);
if (why == FOCUS_DESK_LEAVE)
return;
ICCCM_Focus(ewin);
focus_is_set = 1;
}
void
FocusToEWin(EWin * ewin, int why)
{
if (EDebug(EDBUG_TYPE_FOCUS))
Eprintf("FocusToEWin(%d) %#lx %s why=%d\n", focus_inhibit,
(ewin) ? EwinGetClientXwin(ewin) : 0,
(ewin) ? EwinGetTitle(ewin) : "None", why);
switch (why)
{
case FOCUS_EWIN_NEW:
if (!FocusEwinValid(ewin, 0, 0, 0))
break;
focus_pending_new = ewin;
focus_pending_why = why;
focus_pending_ewin = ewin;
break;
default:
if (ewin && !FocusEwinValid(ewin, 0, why == FOCUS_CLICK, 0))
break;
focus_pending_why = why;
focus_pending_ewin = ewin;
break;
case FOCUS_EWIN_UNMAP:
focus_pending_why = why;
focus_pending_ewin = NULL;
if (ewin == Mode.focuswin)
{
Mode.focuswin = NULL;
focus_is_set = 0;
if (!EoIsGone(ewin))
FocusEwinSetActive(ewin, 0);
}
if (ewin == focus_pending_new)
focus_pending_new = NULL;
break;
}
}
static void
FocusSet(void)
{
if (focus_pending_new && Conf.focus.all_new_windows_get_focus)
doFocusToEwin(focus_pending_new, FOCUS_EWIN_NEW);
else
doFocusToEwin(focus_pending_ewin, focus_pending_why);
focus_pending_why = 0;
focus_pending_ewin = focus_pending_new = NULL;
}
void
FocusNewDeskBegin(void)
{
/* Freeze keyboard */
XGrabKeyboard(disp, VRoot.xwin, False, GrabModeAsync, GrabModeSync,
CurrentTime);
focus_pending_new = NULL;
doFocusToEwin(NULL, FOCUS_DESK_LEAVE);
}
void
FocusNewDesk(void)
{
/* Set the mouse-over window */
Mode.mouse_over_ewin = GetEwinByCurrentPointer();
doFocusToEwin(NULL, FOCUS_DESK_ENTER);
/* Unfreeze keyboard */
XUngrabKeyboard(disp, CurrentTime);
}
static void
FocusInit(void)
{
/* Start focusing windows */
FocusEnable(1);
/* Set the mouse-over window */
Mode.mouse_over_ewin = GetEwinByCurrentPointer();
focus_pending_why = 0;
focus_pending_ewin = focus_pending_new = NULL;
FocusToEWin(NULL, FOCUS_INIT);
FocusSet();
/* Enable window placement features */
Mode.place.enable_features = 1;
}
static void
FocusExit(void)
{
}
/*
* Focus event handlers
*/
void
FocusHandleEnter(EWin * ewin, XEvent * ev)
{
Window win = ev->xcrossing.window;
Mode.mouse_over_ewin = ewin;
if (!ewin)
{
/* Entering root may mean entering this screen */
if (win == VRoot.xwin &&
(ev->xcrossing.mode == NotifyNormal &&
ev->xcrossing.detail != NotifyInferior))
{
FocusToEWin(NULL, FOCUS_DESK_ENTER);
return;
}
}
switch (Conf.focus.mode)
{
default:
case MODE_FOCUS_CLICK:
break;
case MODE_FOCUS_SLOPPY:
if (FocusEwinValid(ewin, 1, 0, 0))
FocusToEWin(ewin, FOCUS_ENTER);
break;
case MODE_FOCUS_POINTER:
if (!ewin || FocusEwinValid(ewin, 1, 0, 0))
FocusToEWin(ewin, FOCUS_ENTER);
break;
}
}
void
FocusHandleLeave(EWin * ewin __UNUSED__, XEvent * ev)
{
Window win = ev->xcrossing.window;
/* Leaving root may mean entering other screen */
if (win == VRoot.xwin &&
(ev->xcrossing.mode == NotifyNormal &&
ev->xcrossing.detail != NotifyInferior))
FocusToEWin(NULL, FOCUS_DESK_LEAVE);
}
void
FocusHandleChange(EWin * ewin __UNUSED__, XEvent * ev __UNUSED__)
{
#if 0 /* Debug */
if (ewin == Mode.focuswin && ev->type == FocusOut)
Eprintf("??? Lost focus: %s\n", EwinGetTitle(ewin));
#endif
}
void
FocusHandleClick(EWin * ewin, Win win)
{
if (Conf.focus.clickraises)
EwinRaise(ewin);
if (Conf.focus.mode == MODE_FOCUS_CLICK || ewin->props.focusclick)
FocusToEWin(ewin, FOCUS_CLICK);
/* Allow click to pass thorugh */
if (EDebug(EDBUG_TYPE_GRABS))
Eprintf("FocusHandleClick %#lx %#lx\n", WinGetXwin(win),
EwinGetContainerXwin(ewin));
if (win == EwinGetContainerWin(ewin))
{
ESync();
XAllowEvents(disp, ReplayPointer, CurrentTime);
ESync();
}
}
/*
* Configuration dialog
*/
static int tmp_focus;
static char tmp_clickalways;
static char tmp_new_focus;
static char tmp_popup_focus;
static char tmp_owner_popup_focus;
static char tmp_raise_focus;
static char tmp_warp_focus;
static char tmp_warp_always;
static char tmp_display_warp;
static char tmp_warp_after_focus;
static char tmp_raise_after_focus;
static char tmp_showsticky;
static char tmp_showshaded;
static char tmp_showiconified;
static char tmp_warpfocused;
static int tmp_warp_icon_mode;
static void
CB_ConfigureFocus(Dialog * d __UNUSED__, int val, void *data __UNUSED__)
{
if (val < 2)
{
Conf.focus.mode = tmp_focus;
Conf.focus.all_new_windows_get_focus = tmp_new_focus;
Conf.focus.new_transients_get_focus = tmp_popup_focus;
Conf.focus.new_transients_get_focus_if_group_focused =
tmp_owner_popup_focus;
Conf.focus.raise_on_next = tmp_raise_focus;
Conf.focus.warp_on_next = tmp_warp_focus;
Conf.focus.warp_always = tmp_warp_always;
Conf.warplist.enable = tmp_display_warp;
Conf.warplist.warp_on_select = tmp_warp_after_focus;
Conf.warplist.raise_on_select = tmp_raise_after_focus;
Conf.warplist.showsticky = tmp_showsticky;
Conf.warplist.showshaded = tmp_showshaded;
Conf.warplist.showiconified = tmp_showiconified;
Conf.warplist.warpfocused = tmp_warpfocused;
Conf.warplist.icon_mode = tmp_warp_icon_mode;
Conf.focus.clickraises = tmp_clickalways;
FocusGrabsUpdate();
}
autosave();
}
static void
_DlgFillFocus(Dialog * d __UNUSED__, DItem * table, void *data __UNUSED__)
{
DItem *di, *radio, *radio2;
tmp_focus = Conf.focus.mode;
tmp_new_focus = Conf.focus.all_new_windows_get_focus;
tmp_popup_focus = Conf.focus.new_transients_get_focus;
tmp_owner_popup_focus = Conf.focus.new_transients_get_focus_if_group_focused;
tmp_raise_focus = Conf.focus.raise_on_next;
tmp_warp_focus = Conf.focus.warp_on_next;
tmp_warp_always = Conf.focus.warp_always;
tmp_raise_after_focus = Conf.warplist.raise_on_select;
tmp_warp_after_focus = Conf.warplist.warp_on_select;
tmp_display_warp = Conf.warplist.enable;
tmp_showsticky = Conf.warplist.showsticky;
tmp_showshaded = Conf.warplist.showshaded;
tmp_showiconified = Conf.warplist.showiconified;
tmp_warpfocused = Conf.warplist.warpfocused;
tmp_warp_icon_mode = Conf.warplist.icon_mode;
tmp_clickalways = Conf.focus.clickraises;
DialogItemTableSetOptions(table, 2, 0, 0, 0);
radio = di = DialogAddItem(table, DITEM_RADIOBUTTON);
DialogItemSetColSpan(di, 2);
DialogItemSetText(di, _("Focus follows pointer"));
DialogItemRadioButtonSetFirst(di, radio);
DialogItemRadioButtonGroupSetVal(di, 0);
di = DialogAddItem(table, DITEM_RADIOBUTTON);
DialogItemSetColSpan(di, 2);
DialogItemSetText(di, _("Focus follows pointer sloppily"));
DialogItemRadioButtonSetFirst(di, radio);
DialogItemRadioButtonGroupSetVal(di, 1);
di = DialogAddItem(table, DITEM_RADIOBUTTON);
DialogItemSetColSpan(di, 2);
DialogItemSetText(di, _("Focus follows mouse clicks"));
DialogItemRadioButtonSetFirst(di, radio);
DialogItemRadioButtonGroupSetVal(di, 2);
DialogItemRadioButtonGroupSetValPtr(radio, &tmp_focus);
di = DialogAddItem(table, DITEM_SEPARATOR);
DialogItemSetColSpan(di, 2);
di = DialogAddItem(table, DITEM_CHECKBUTTON);
DialogItemSetColSpan(di, 2);
DialogItemSetText(di, _("Clicking in a window always raises it"));
DialogItemCheckButtonSetPtr(di, &tmp_clickalways);
di = DialogAddItem(table, DITEM_SEPARATOR);
DialogItemSetColSpan(di, 2);
di = DialogAddItem(table, DITEM_CHECKBUTTON);
DialogItemSetColSpan(di, 2);
DialogItemSetText(di, _("All new windows first get the focus"));
DialogItemCheckButtonSetPtr(di, &tmp_new_focus);
di = DialogAddItem(table, DITEM_CHECKBUTTON);
DialogItemSetColSpan(di, 2);
DialogItemSetText(di, _("Only new dialog windows get the focus"));
DialogItemCheckButtonSetPtr(di, &tmp_popup_focus);
di = DialogAddItem(table, DITEM_CHECKBUTTON);
DialogItemSetColSpan(di, 2);
DialogItemSetText(di,
_
("Only new dialogs whose owner is focused get the focus"));
DialogItemCheckButtonSetPtr(di, &tmp_owner_popup_focus);
di = DialogAddItem(table, DITEM_CHECKBUTTON);
DialogItemSetColSpan(di, 2);
DialogItemSetText(di, _("Raise windows while switching focus"));
DialogItemCheckButtonSetPtr(di, &tmp_raise_focus);
di = DialogAddItem(table, DITEM_CHECKBUTTON);
DialogItemSetColSpan(di, 2);
DialogItemSetText(di,
_("Send mouse pointer to window while switching focus"));
DialogItemCheckButtonSetPtr(di, &tmp_warp_focus);
di = DialogAddItem(table, DITEM_CHECKBUTTON);
DialogItemSetColSpan(di, 2);
DialogItemSetText(di,
_("Always send mouse pointer to window on focus switch"));
DialogItemCheckButtonSetPtr(di, &tmp_warp_always);
di = DialogAddItem(table, DITEM_SEPARATOR);
DialogItemSetColSpan(di, 2);
di = DialogAddItem(table, DITEM_CHECKBUTTON);
DialogItemSetColSpan(di, 2);
DialogItemSetText(di, _("Display and use focus list"));
DialogItemCheckButtonSetPtr(di, &tmp_display_warp);
di = DialogAddItem(table, DITEM_CHECKBUTTON);
DialogItemSetColSpan(di, 2);
DialogItemSetText(di, _("Include sticky windows in focus list"));
DialogItemCheckButtonSetPtr(di, &tmp_showsticky);
di = DialogAddItem(table, DITEM_CHECKBUTTON);
DialogItemSetColSpan(di, 2);
DialogItemSetText(di, _("Include shaded windows in focus list"));
DialogItemCheckButtonSetPtr(di, &tmp_showshaded);
di = DialogAddItem(table, DITEM_CHECKBUTTON);
DialogItemSetColSpan(di, 2);
DialogItemSetText(di, _("Include iconified windows in focus list"));
DialogItemCheckButtonSetPtr(di, &tmp_showiconified);
di = DialogAddItem(table, DITEM_CHECKBUTTON);
DialogItemSetColSpan(di, 2);
DialogItemSetText(di, _("Focus windows while switching"));
DialogItemCheckButtonSetPtr(di, &tmp_warpfocused);
di = DialogAddItem(table, DITEM_CHECKBUTTON);
DialogItemSetColSpan(di, 2);
DialogItemSetText(di, _("Raise windows after focus switch"));
DialogItemCheckButtonSetPtr(di, &tmp_raise_after_focus);
di = DialogAddItem(table, DITEM_CHECKBUTTON);
DialogItemSetColSpan(di, 2);
DialogItemSetText(di, _("Send mouse pointer to window after focus switch"));
DialogItemCheckButtonSetPtr(di, &tmp_warp_after_focus);
di = DialogAddItem(table, DITEM_SEPARATOR);
DialogItemSetColSpan(di, 2);
di = DialogAddItem(table, DITEM_TEXT);
DialogItemSetColSpan(di, 2);
DialogItemSetText(di,
_
("Focuslist image display policy (if one operation fails, try the next):"));
radio2 = di = DialogAddItem(table, DITEM_RADIOBUTTON);
DialogItemSetColSpan(di, 2);
DialogItemSetText(di, _("First E Icon, then App Icon"));
DialogItemRadioButtonSetFirst(di, radio2);
DialogItemRadioButtonGroupSetVal(di, 3);
di = DialogAddItem(table, DITEM_RADIOBUTTON);
DialogItemSetColSpan(di, 2);
DialogItemSetText(di, _("First App Icon, then E Icon"));
DialogItemRadioButtonSetFirst(di, radio2);
DialogItemRadioButtonGroupSetVal(di, 4);
di = DialogAddItem(table, DITEM_RADIOBUTTON);
DialogItemSetColSpan(di, 2);
DialogItemSetText(di, _("None"));
DialogItemRadioButtonSetFirst(di, radio2);
DialogItemRadioButtonGroupSetVal(di, 0);
DialogItemRadioButtonGroupSetValPtr(radio2, &tmp_warp_icon_mode);
}
const DialogDef DlgFocus = {
"CONFIGURE_FOCUS",
N_("Focus"),
N_("Focus Settings"),
"SOUND_SETTINGS_FOCUS",
"pix/focus.png",
N_("Enlightenment Focus\n" "Settings Dialog\n"),
_DlgFillFocus,
DLG_OAC, CB_ConfigureFocus,
};
/*
* Focus Module
*/
static void
FocusInitTimeout(int val __UNUSED__, void *data __UNUSED__)
{
FocusInit();
}
static void
_FocusIdler(void *data __UNUSED__)
{
if (!focus_inhibit && focus_pending_why)
FocusSet();
if (focus_pending_update_grabs)
doFocusGrabsUpdate();
}
static void
FocusSighan(int sig, void *prm __UNUSED__)
{
switch (sig)
{
case ESIGNAL_START:
/* Delay focusing a bit to allow things to settle down */
IdlerAdd(50, _FocusIdler, NULL);
DoIn("FOCUS_INIT_TIMEOUT", 0.5, FocusInitTimeout, 0, NULL);
break;
case ESIGNAL_EXIT:
FocusExit();
break;
}
}
static void
FocusIpc(const char *params, Client * c __UNUSED__)
{
const char *p;
char cmd[128], prm[4096];
int len;
cmd[0] = prm[0] = '\0';
p = params;
if (p)
{
len = 0;
sscanf(p, "%100s %4000s %n", cmd, prm, &len);
p += len;
}
if (!p || cmd[0] == '?')
{
EWin *ewin;
ewin = GetFocusEwin();
if (ewin)
IpcPrintf("Focused: %#lx\n", EwinGetClientXwin(ewin));
else
IpcPrintf("Focused: none\n");
}
else if (!strcmp(cmd, "cfg"))
{
DialogShowSimple(&DlgFocus, NULL);
}
else if (!strncmp(cmd, "mode", 2))
{
int mode = Conf.focus.mode;
if (!strcmp(prm, "click"))
{
mode = MODE_FOCUS_CLICK;
Mode.grabs.pointer_grab_active = 1;
}
else if (!strcmp(prm, "clicknograb"))
{
mode = MODE_FOCUS_CLICK;
Mode.grabs.pointer_grab_active = 0;
}
else if (!strcmp(prm, "pointer"))
{
mode = MODE_FOCUS_POINTER;
}
else if (!strcmp(prm, "sloppy"))
{
mode = MODE_FOCUS_SLOPPY;
}
else if (!strcmp(prm, "?"))
{
if (Conf.focus.mode == MODE_FOCUS_CLICK)
{
if (Mode.grabs.pointer_grab_active)
p = "click";
else
p = "clicknograb";
}
else if (Conf.focus.mode == MODE_FOCUS_SLOPPY)
p = "sloppy";
else if (Conf.focus.mode == MODE_FOCUS_POINTER)
p = "pointer";
else
p = "unknown";
IpcPrintf("Focus Mode: %s\n", p);
}
else
{
IpcPrintf("Error: unknown focus type\n");
}
if (Conf.focus.mode != mode)
{
Conf.focus.mode = mode;
FocusGrabsUpdate();
autosave();
}
}
else if (!strncmp(cmd, "next", 2))
{
if (Conf.warplist.enable)
WarpFocus(1);
else
FocusGetNextEwin();
}
else if (!strncmp(cmd, "prev", 2))
{
if (Conf.warplist.enable)
WarpFocus(-1);
else
FocusGetPrevEwin();
}
}
static const IpcItem FocusIpcArray[] = {
{
FocusIpc,
"focus", "sf",
"Focus functions",
" focus ? Show focus info\n"
" focus mode Set focus mode. Modes:\n"
" click: The traditional click-to-focus mode.\n"
" clicknograb: A similar focus mode, but without the grabbing of the click\n"
" (you cannot click anywhere in a window to focus it)\n"
" pointer: The focus will follow the mouse pointer\n"
" sloppy: The focus follows the mouse, but when over the desktop background\n"
" the last window does not lose the focus\n"}
,
};
#define N_IPC_FUNCS (sizeof(FocusIpcArray)/sizeof(IpcItem))
static const CfgItem FocusCfgItems[] = {
CFG_ITEM_INT(Conf.focus, mode, MODE_FOCUS_SLOPPY),
CFG_ITEM_BOOL(Conf.focus, clickraises, 1),
CFG_ITEM_BOOL(Conf.focus, transientsfollowleader, 1),
CFG_ITEM_BOOL(Conf.focus, switchfortransientmap, 1),
CFG_ITEM_BOOL(Conf.focus, all_new_windows_get_focus, 0),
CFG_ITEM_BOOL(Conf.focus, new_transients_get_focus, 0),
CFG_ITEM_BOOL(Conf.focus, new_transients_get_focus_if_group_focused, 1),
CFG_ITEM_BOOL(Conf.focus, raise_on_next, 1),
CFG_ITEM_BOOL(Conf.focus, warp_on_next, 0),
CFG_ITEM_BOOL(Conf.focus, warp_always, 0),
CFG_ITEM_BOOL(Conf, autoraise.enable, 0),
CFG_ITEM_INT(Conf, autoraise.delay, 500),
};
#define N_CFG_ITEMS (sizeof(FocusCfgItems)/sizeof(CfgItem))
/*
* Module descriptor
*/
const EModule ModFocus = {
"focus", NULL,
FocusSighan,
{N_IPC_FUNCS, FocusIpcArray},
{N_CFG_ITEMS, FocusCfgItems}
};