]> git.decadent.org.uk Git - ion3.git/blobdiff - ioncore/focus.c
Update cfg_kludge_flash for Flash 10
[ion3.git] / ioncore / focus.c
index c25ec716ff1750906c2a9ad50927eccca32f0cb9..ee3fd86ab796625077e6101b5b8460bdf2d9cc1b 100644 (file)
@@ -1,12 +1,9 @@
 /*
  * ion/ioncore/focus.c
  *
- * Copyright (c) Tuomo Valkonen 1999-2007
+ * Copyright (c) Tuomo Valkonen 1999-2009
  *
- * 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>
@@ -104,7 +101,8 @@ WRegion *ioncore_goto_previous()
 
 /*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
@@ -166,10 +164,8 @@ void region_set_await_focus(WRegion *reg)
 }
 
 
-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;
@@ -180,6 +176,18 @@ static bool region_is_await(WRegion *reg)
 }
 
 
+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.
  */
@@ -293,9 +301,22 @@ void region_lost_focus(WRegion *reg)
  */
 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));
 }
 
 
@@ -306,8 +327,11 @@ bool region_may_control_focus(WRegion *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;
@@ -328,6 +352,9 @@ void region_finalise_focusing(WRegion* reg, Window win, bool warp)
     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, 
@@ -388,6 +415,7 @@ void region_do_warp(WRegion *reg)
 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);
 }
 
@@ -396,7 +424,7 @@ void region_maybewarp_now(WRegion *reg, bool warp)
 {
     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);
 }
 
 
@@ -450,34 +478,33 @@ WRegion *ioncore_current()
  */
 void region_pointer_focus_hack(WRegion *reg)
 {
-    WRegion *act=ioncore_await_focus();
-    const WRectangle *g=&REGION_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;
 }