/*
* ion/ioncore/focus.c
*
- * Copyright (c) Tuomo Valkonen 1999-2007.
+ * Copyright (c) Tuomo Valkonen 1999-2008.
*
- * Ion is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
+ * See the included file LICENSE for details.
*/
#include <libmainloop/hooks.h>
/*EXTL_DOC
* Iterate over focus history until \var{iterfn} returns \code{false}.
- * The function itself returns \code{true} if it reaches the end of list
+ * The function is called in protected mode.
+ * This routine returns \code{true} if it reaches the end of list
* without this happening.
*/
EXTL_EXPORT
}
-static bool region_is_await(WRegion *reg)
+static bool region_is_parent(WRegion *reg, WRegion *aw)
{
- WRegion *aw=(WRegion*)await_watch.obj;
-
while(aw!=NULL){
if(aw==reg)
return TRUE;
}
+static bool region_is_await(WRegion *reg)
+{
+ return region_is_parent(reg, (WRegion*)await_watch.obj);
+}
+
+
+static bool region_is_focusnext(WRegion *reg)
+{
+ return region_is_parent(reg, ioncore_g.focus_next);
+}
+
+
/* Only keep await status if focus event is to an ancestor of the await
* region.
*/
*/
EXTL_SAFE
EXTL_EXPORT_MEMBER
-bool region_is_active(WRegion *reg)
+bool region_is_active(WRegion *reg, bool pseudoact_ok)
{
- return REGION_IS_ACTIVE(reg);
+ return (REGION_IS_ACTIVE(reg) ||
+ (pseudoact_ok && REGION_IS_PSEUDOACTIVE(reg)));
+}
+
+
+bool region_manager_is_focusnext(WRegion *reg)
+{
+ if(reg==NULL || ioncore_g.focus_next==NULL)
+ return FALSE;
+
+ if(reg==ioncore_g.focus_next)
+ return TRUE;
+
+ return region_manager_is_focusnext(REGION_MANAGER(reg));
}
if(REGION_IS_ACTIVE(reg) || REGION_IS_PSEUDOACTIVE(reg))
return TRUE;
-
- if(region_is_await(reg))
+
+ if(region_is_await(reg) || region_is_focusnext(reg))
+ return TRUE;
+
+ if(region_manager_is_focusnext(reg))
return TRUE;
return FALSE;
if(warp)
region_do_warp(reg);
+ if(REGION_IS_ACTIVE(reg) && ioncore_await_focus()==NULL)
+ return;
+
region_set_await_focus(reg);
/*xwindow_do_set_focus(win);*/
XSetInputFocus(ioncore_g.dpy, win, RevertToParent,
void region_maybewarp(WRegion *reg, bool warp)
{
ioncore_g.focus_next=reg;
+ ioncore_g.focus_next_source=IONCORE_FOCUSNEXT_OTHER;
ioncore_g.warp_next=(warp && ioncore_g.warp_enabled);
}
{
ioncore_g.focus_next=NULL;
/* TODO: what if focus isn't set? Should focus_next be reset then? */
- region_do_set_focus(reg, warp);
+ region_do_set_focus(reg, warp && ioncore_g.warp_enabled);
}
*/
void region_pointer_focus_hack(WRegion *reg)
{
- WRegion *act=ioncore_await_focus();
- const WRectangle *g=®ION_GEOM(reg);
- int x, y;
+ WRegion *act;
if(ioncore_g.opmode!=IONCORE_OPMODE_NORMAL)
return;
-
- if(!REGION_IS_ACTIVE(reg) && act==NULL)
- act=ioncore_g.focus_current;
- if(act==NULL || OBJ_IS_BEING_DESTROYED(act))
+ if(ioncore_g.focus_next!=NULL &&
+ ioncore_g.focus_next_source<=IONCORE_FOCUSNEXT_POINTERHACK){
return;
-
- /* Ok, anything under us should not get focus as we're unmapped:
- * Either we don't have the focus, or focus change somewhere else
- * is pending.
- *
- * It might be possible to do the pointer check more efficiently
- * by trying to maintain our internal pointer containment state
- * by tracking Enter/Leave events...
- */
+ }
- xwindow_pointer_pos(region_xwindow(reg), &x, &y);
+ act=ioncore_await_focus();
+
+ if((REGION_IS_ACTIVE(reg) && act==NULL) || !region_is_fully_mapped(reg))
+ return;
- if(x>=0 && y>=0 && x<g->w && y<g->h){
- D(fprintf(stderr, "Pointer here and shouldn't alter focus!\n"));
- region_set_focus(act);
+ if(act==NULL)
+ act=ioncore_g.focus_current;
+
+ if(act==NULL ||
+ OBJ_IS_BEING_DESTROYED(act) ||
+ !region_is_fully_mapped(act) ||
+ region_skip_focus(act)){
+ return;
}
+
+ region_set_focus(act);
+ ioncore_g.focus_next_source=IONCORE_FOCUSNEXT_POINTERHACK;
}