text: #include "e.h"
  
  /* local subsystem functions */
  static Eina_Bool _e_grabinput_focus_check(void *data);
  static void _e_grabinput_focus_do(Ecore_X_Window win, E_Focus_Method method);
  static void _e_grabinput_focus(Ecore_X_Window win, E_Focus_Method method);
  
  /* local subsystem globals */
  static Ecore_X_Window grab_mouse_win = 0;
  static Ecore_X_Window grab_key_win = 0;
  static Ecore_X_Window focus_win = 0;
  static E_Focus_Method focus_method = E_FOCUS_METHOD_NO_INPUT;
  static double last_focus_time = 0.0;
  
  static Ecore_X_Window focus_fix_win = 0;
  static Ecore_Timer *focus_fix_timer = NULL;
  static E_Focus_Method focus_fix_method = E_FOCUS_METHOD_NO_INPUT;
  
  /* externally accessible functions */
  EINTERN int
  e_grabinput_init(void)
  {
     return 1;
  }
  
  EINTERN int
  e_grabinput_shutdown(void)
  {
     if (focus_fix_timer)
       {
          ecore_timer_del(focus_fix_timer);
          focus_fix_timer = NULL;
       }
     return 1;
  }
  
  EAPI int
  e_grabinput_get(Ecore_X_Window mouse_win, int confine_mouse, Ecore_X_Window key_win)
  {
     if (grab_mouse_win)
       {
          ecore_x_pointer_ungrab();
          grab_mouse_win = 0;
       }
     if (grab_key_win)
       {
          ecore_x_keyboard_ungrab();
          grab_key_win = 0;
          focus_win = 0;
       }
     if (mouse_win)
       {
          int ret = 0;
  
          if (confine_mouse)
            ret = ecore_x_pointer_confine_grab(mouse_win);
          else
            ret = ecore_x_pointer_grab(mouse_win);
          if (!ret) return 0;
          grab_mouse_win = mouse_win;
       }
     if (key_win)
       {
          int ret = 0;
  
          ret = ecore_x_keyboard_grab(key_win);
          if (!ret)
            {
               if (grab_mouse_win)
                 {
                    ecore_x_pointer_ungrab();
                    grab_mouse_win = 0;
                 }
               return 0;
            }
          grab_key_win = key_win;
       }
     return 1;
  }
  
  EAPI void
  e_grabinput_release(Ecore_X_Window mouse_win, Ecore_X_Window key_win)
  {
     if (mouse_win == grab_mouse_win)
       {
          ecore_x_pointer_ungrab();
          grab_mouse_win = 0;
       }
     if (key_win == grab_key_win)
       {
          ecore_x_keyboard_ungrab();
          grab_key_win = 0;
          if (focus_win != 0)
            {
               /* fprintf(stderr, "release focus to %x\n", focus_win); */
               _e_grabinput_focus(focus_win, focus_method);
               focus_win = 0;
               focus_method = E_FOCUS_METHOD_NO_INPUT;
            }
       }
  }
  
  EAPI void
  e_grabinput_focus(Ecore_X_Window win, E_Focus_Method method)
  {
     if (grab_key_win != 0)
       {
          /* fprintf(stderr, "while grabbed focus changed to %x\n", win); */
          focus_win = win;
          focus_method = method;
       }
     else
       {
          /* fprintf(stderr, "focus to %x\n", win); */
          _e_grabinput_focus(win, method);
       }
  }
  
  EAPI double
  e_grabinput_last_focus_time_get(void)
  {
     return last_focus_time;
  }
  
  EAPI Ecore_X_Window
  e_grabinput_last_focus_win_get(void)
  {
     return focus_fix_win;
  }
  
  EAPI Ecore_X_Window
  e_grabinput_key_win_get(void)
  {
     return grab_key_win;
  }
  
  EAPI Ecore_X_Window
  e_grabinput_mouse_win_get(void)
  {
     return grab_mouse_win;
  }
  
  static Eina_Bool
  _e_grabinput_focus_check(void *data __UNUSED__)
  {
     if (ecore_x_window_focus_get() != focus_fix_win)
       {
          /* fprintf(stderr, "foc do 2\n"); */
          _e_grabinput_focus_do(focus_fix_win, focus_fix_method);
       }
     focus_fix_timer = NULL;
     return EINA_FALSE;
  }
  
  static void
  _e_grabinput_focus_do(Ecore_X_Window win, E_Focus_Method method)
  {
     /* fprintf(stderr, "focus to %x method %i\n", win, method); */
     switch (method)
       {
        case E_FOCUS_METHOD_NO_INPUT:
          break;
        case E_FOCUS_METHOD_LOCALLY_ACTIVE:
          ecore_x_window_focus(win);
          ecore_x_icccm_take_focus_send(win, ecore_x_current_time_get());
          break;
        case E_FOCUS_METHOD_GLOBALLY_ACTIVE:
          ecore_x_icccm_take_focus_send(win, ecore_x_current_time_get());
          break;
        case E_FOCUS_METHOD_PASSIVE:
          ecore_x_window_focus(win);
          break;
        default:
          break;
       }
  }
  
  static void
  _e_grabinput_focus(Ecore_X_Window win, E_Focus_Method method)
  {
     focus_fix_win = win;
     focus_fix_method = method;
     /* fprintf(stderr, "foc do 1\n"); */
     _e_grabinput_focus_do(win, method);
     last_focus_time = ecore_loop_time_get();
     if (focus_fix_timer) ecore_timer_del(focus_fix_timer);
     focus_fix_timer = ecore_timer_add(0.2, _e_grabinput_focus_check, NULL);
  }
  