]> git.decadent.org.uk Git - ion3.git/blobdiff - ioncore/eventh.c
Imported Upstream version 20090110
[ion3.git] / ioncore / eventh.c
index 91ab5501dfd2405575798afe79890d31097f8518..861007f4b06eb3da7564797025408f39a993be1b 100644 (file)
@@ -1,12 +1,9 @@
 /*
  * ion/ioncore/eventh.c
  *
- * Copyright (c) Tuomo Valkonen 1999-2006
+ * 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 <stdlib.h>
@@ -63,7 +60,7 @@ bool ioncore_handle_event(XEvent *ev)
         ioncore_handle_property(&(ev->xproperty));
         break;
     CASE_EVENT(FocusIn)
-        ioncore_handle_focus_in(&(ev->xfocus), FALSE);
+        ioncore_handle_focus_in(&(ev->xfocus));
         break;
     CASE_EVENT(FocusOut)
         ioncore_handle_focus_out(&(ev->xfocus));
@@ -305,26 +302,19 @@ void ioncore_handle_expose(const XExposeEvent *ev)
 /*{{{ Enter window, focus */
 
 
-/*extern Time ioncore_focus_time;*/
-
-
-static void do_handle_enter_window(XEvent *ev)
+void ioncore_handle_enter_window(XEvent *ev)
 {
     XEnterWindowEvent *eev=&(ev->xcrossing);
     WRegion *reg=NULL;
     
-    if(ioncore_g.input_mode!=IONCORE_INPUTMODE_NORMAL)
+    if(ioncore_g.input_mode!=IONCORE_INPUTMODE_NORMAL ||
+       ioncore_g.no_mousefocus){
         return;
-    
-    /*if(ioncore_g.focus_next!=NULL && ioncore_focus_time==CurrentTime)
-        return;*/
+    }
         
-    /*if(ioncore_await_warp())
-        return;
-    
     if(eev->mode!=NotifyNormal && !ioncore_g.warp_enabled)
-        return;*/
-        
+        return;
+                
     reg=XWINDOW_REGION_OF_T(eev->window, WRegion);
     
     if(reg==NULL)
@@ -335,9 +325,15 @@ static void do_handle_enter_window(XEvent *ev)
         
     if(region_skip_focus(reg))
         return;
-        
+    
+    if(ioncore_g.focus_next!=NULL &&
+       ioncore_g.focus_next_source<IONCORE_FOCUSNEXT_ENTERWINDOW){
+        return;
+    }
+    
     /* If a child of 'reg' is to be focused, do not process this
-     * event.
+     * event. (ioncore_g.focus_next should only be set here by
+     * another call to use from ioncore_handle_enter_window below.)
      */
     if(ioncore_g.focus_next!=NULL){
         WRegion *r2=ioncore_g.focus_next;
@@ -348,20 +344,11 @@ static void do_handle_enter_window(XEvent *ev)
         }
     }
     
-    region_goto_flags(reg, (REGION_GOTO_FOCUS|
-                            REGION_GOTO_NOWARP|
-                            REGION_GOTO_ENTERWINDOW));
-}
-
-
-void ioncore_handle_enter_window(XEvent *ev)
-{
-    do{
-        /* *sigh*, it doesn't seem reasonably simply possible to
-         * process events in-order.
-         */
-        do_handle_enter_window(ev);
-    }while(XCheckMaskEvent(ioncore_g.dpy, EnterWindowMask, ev));
+    if(region_goto_flags(reg, (REGION_GOTO_FOCUS|
+                               REGION_GOTO_NOWARP|
+                               REGION_GOTO_ENTERWINDOW))){
+        ioncore_g.focus_next_source=IONCORE_FOCUSNEXT_ENTERWINDOW;
+    }
 }
 
 
@@ -378,8 +365,7 @@ static bool pointer_in_root(Window root1)
 }
 
 
-
-void ioncore_handle_focus_in(const XFocusChangeEvent *ev, bool skip)
+void ioncore_handle_focus_in(const XFocusChangeEvent *ev)
 {
     WRegion *reg;
     WWindow *wwin;
@@ -397,20 +383,6 @@ void ioncore_handle_focus_in(const XFocusChangeEvent *ev, bool skip)
     if(ev->detail==NotifyPointer)
         return;
     
-    /* Root windows appear either as WRootWins or WScreens */
-    if(ev->window==region_root_of(reg)){
-        D(fprintf(stderr, "scr-in %d %d %d\n", ROOTWIN_OF(reg)->xscr,
-                  ev->mode, ev->detail));
-        if((ev->detail==NotifyPointerRoot || ev->detail==NotifyDetailNone) &&
-           pointer_in_root(ev->window) && ioncore_g.focus_next==NULL){
-            /* Restore focus */
-            if(!skip)
-                region_set_focus(reg);
-            return;
-        }
-        /*return;*/
-    }
-
     /* Input contexts */
     if(OBJ_IS(reg, WWindow)){
         wwin=(WWindow*)reg;
@@ -422,6 +394,25 @@ void ioncore_handle_focus_in(const XFocusChangeEvent *ev, bool skip)
         netwm_set_active(reg);
     
     region_got_focus(reg);
+    
+    if(ioncore_g.focus_next!=NULL && 
+       ioncore_g.focus_next_source<IONCORE_FOCUSNEXT_FALLBACK){
+        return;
+    }
+    
+    if((ev->detail==NotifyPointerRoot || ev->detail==NotifyDetailNone) 
+       && ev->window==region_root_of(reg) /* OBJ_IS(reg, WRootWin) */){
+        /* Restore focus if it was returned to a root window and we don't
+         * know of a pending focus change.
+         */
+        if(pointer_in_root(ev->window)){
+            region_set_focus(reg);
+            ioncore_g.focus_next_source=IONCORE_FOCUSNEXT_FALLBACK;
+        }
+    }else{
+        /* Something got the focus, don't use fallback. */
+        ioncore_g.focus_next=NULL;
+    }
 }
 
 
@@ -509,7 +500,7 @@ void ioncore_handle_buttonpress(XEvent *ev)
             ioncore_handle_grabs(ev);
             break;
         CASE_EVENT(FocusIn)
-            ioncore_handle_focus_in(&(ev->xfocus), FALSE);
+            ioncore_handle_focus_in(&(ev->xfocus));
             break;
         CASE_EVENT(FocusOut)
             ioncore_handle_focus_out(&(ev->xfocus));