"Fossies" - the Fresh Open Source Software Archive

Member "selenium-selenium-4.8.1/cpp/linux-specific/x_ignore_nofocus.c" (17 Feb 2023, 21405 Bytes) of package /linux/www/selenium-selenium-4.8.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "x_ignore_nofocus.c" see the Fossies "Dox" file reference documentation.

    1 #include <stdio.h>
    2 #include <X11/Xlib.h>
    3 #include <X11/X.h>
    4 #include <dlfcn.h>
    5 #include <sys/utsname.h>
    6 #include <string.h>
    7 #include "print_events.h"
    8 #include <time.h>
    9 #include <sys/time.h>
   10 #include <stdlib.h>
   11 #include <assert.h>
   12 #include <unistd.h>
   13 #include <elf.h>
   14 
   15 #ifndef TRUE
   16 #define TRUE 1
   17 #endif
   18 
   19 #ifndef FALSE
   20 #define FALSE 0
   21 #endif
   22 
   23 // Define this to prevent events from being faked.
   24 //#undef NO_FAKING
   25 
   26 //#define DEBUG_PRINTOUTS
   27 
   28 #ifdef DEBUG_PRINTOUTS
   29 FILE* g_out_stream = 0;
   30 #define LOG(...) if (g_out_stream != NULL) { fprintf(g_out_stream, __VA_ARGS__); fflush(g_out_stream); }
   31 #define OPEN_LOGGING_FILE { g_out_stream = fopen("/tmp/x_ignore_focus_log.txt", "a+"); }
   32 #define CLOSE_LOGGING_FILE { fclose(g_out_stream); g_out_stream = NULL; }
   33 #else
   34 // This is to prevent compiler warning for unused variables.
   35 void do_nothing(const char* fmt, ...) {}
   36 #define LOG(...) do_nothing(__VA_ARGS__)
   37 #define OPEN_LOGGING_FILE ;
   38 #define CLOSE_LOGGING_FILE ;
   39 #endif
   40 
   41 int g_library_inited = FALSE;
   42 
   43 struct _FocusKeepStatus {
   44   Window active_window;
   45   Window new_window;
   46   int start_switch_window;
   47   int start_close_window;
   48   int during_switch;
   49   int during_close;
   50   int should_steal_focus;
   51   int encountered_focus_in_event;
   52   int active_window_from_close;
   53 };
   54 
   55 typedef struct _FocusKeepStatus FocusKeepStatus;
   56 
   57 void init_focus_keep_struct(FocusKeepStatus* stat)
   58 {
   59   stat->active_window = 0;
   60   stat->new_window = 0;
   61   stat->start_switch_window = FALSE;
   62   stat->start_close_window = FALSE;
   63   stat->during_switch = FALSE;
   64   stat->during_close = FALSE;
   65   stat->should_steal_focus = FALSE;
   66   // This boolean is for remembering if we already had a FocusIn event and
   67   // never re-send that event as well, not to break clients which expect to get
   68   // FocusOut before FocusIn
   69   stat->encountered_focus_in_event = FALSE;
   70   // This remembers if the active was learnt due to a close
   71   stat->active_window_from_close = FALSE;
   72 };
   73 
   74 Window get_active_window(FocusKeepStatus* stat)
   75 {
   76   return stat->active_window;
   77 }
   78 
   79 int is_focus_out(XEvent* ev)
   80 {
   81   return (ev->type == FocusOut);
   82 }
   83 
   84 int is_focus_in(XEvent* ev)
   85 {
   86   return (ev->type == FocusIn);
   87 }
   88 
   89 int is_reparent_notify(XEvent* ev)
   90 {
   91   return (ev->type == ReparentNotify);
   92 }
   93 
   94 int is_destroy_notify(XEvent* ev)
   95 {
   96   return (ev->type == DestroyNotify);
   97 }
   98 
   99 Window extract_window_id(XEvent* ev);
  100 
  101 struct {
  102   Window window_id;
  103   Window* related_windows;
  104 } g_cached_xquerytree;
  105 
  106 void init_cached_xquerytree()
  107 {
  108   g_cached_xquerytree.window_id = 0;
  109   g_cached_xquerytree.related_windows = 0;
  110 }
  111 
  112 // Performing XQueryTree after UnmapNotify for some of the
  113 // windows will cause a crash. Cache to prevent it.
  114 int cache_xquery_result(Display* dpy, Window for_win) {
  115   Window root_win = 0;
  116   Window parent_win = 0;
  117   Window* childs_list = NULL;
  118   unsigned int num_childs = 0;
  119   int k = 0;
  120 
  121   if ((g_cached_xquerytree.window_id == for_win) &&
  122       (g_cached_xquerytree.related_windows != NULL)) {
  123     return TRUE;
  124   }
  125 
  126   LOG("Invoking XQueryTree for window %#lx\n", for_win);
  127   int queryRes = XQueryTree(dpy, for_win, &root_win,
  128                             &parent_win, &childs_list, &num_childs);
  129   if (queryRes == 0) {
  130     LOG("XQueryTree failed, rc=%d\n", queryRes);
  131     return FALSE;
  132   }
  133 
  134   if (g_cached_xquerytree.related_windows != NULL) {
  135     free(g_cached_xquerytree.related_windows);
  136     g_cached_xquerytree.related_windows = NULL;
  137   }
  138 
  139   int numRelatedWindows = (1 /* parent_win */ +
  140                            1 /* actual win */ + num_childs + 1 /* NULL */);
  141 
  142 
  143   g_cached_xquerytree.related_windows = malloc(sizeof(Window) * numRelatedWindows);
  144   LOG("Allocated at address %p , numRelWindows: %d\n",
  145       g_cached_xquerytree.related_windows, numRelatedWindows);
  146   int relatedWinsIndex = 0;
  147   g_cached_xquerytree.related_windows[relatedWinsIndex++] = parent_win;
  148   g_cached_xquerytree.related_windows[relatedWinsIndex++] = for_win;
  149 
  150   if ((num_childs > 0) && (childs_list != NULL)) {
  151     for (k = 0; k < num_childs; k++) {
  152       g_cached_xquerytree.related_windows[relatedWinsIndex++] = childs_list[k];
  153     }
  154     XFree(childs_list);
  155     childs_list = NULL;
  156   }
  157   g_cached_xquerytree.related_windows[relatedWinsIndex] = 0;
  158 
  159   g_cached_xquerytree.window_id = for_win;
  160 
  161   return TRUE;
  162 }
  163 
  164 int lookup_in_xquery_cache(Window ev_win)
  165 {
  166   int ret_val = FALSE;
  167   int k = 0;
  168   if (g_cached_xquerytree.related_windows == NULL) {
  169     LOG("related_windows is NULL, cache is inconsistent.\n");
  170     return FALSE;
  171   }
  172   while ((g_cached_xquerytree.related_windows[k] != 0) && (!ret_val)) {
  173     if (g_cached_xquerytree.related_windows[k] == ev_win) {
  174       ret_val = TRUE;
  175     }
  176     k++;
  177   }
  178 
  179   return ret_val;
  180 }
  181 
  182 int window_ids_difference(Window win_one, Window win_two)
  183 {
  184   return (abs(win_one - win_two));
  185 }
  186 
  187 int event_on_active_or_adj_window(Display* dpy, XEvent* ev, Window active_win)
  188 {
  189   Window ev_win;
  190   int ret_val = FALSE;
  191 
  192   ev_win = extract_window_id(ev);
  193 
  194   // This is probably also essential as on focus in events on new windows
  195   // XQueryTree should not be called yet.
  196   if (active_win == ev_win) {
  197     return TRUE;
  198   }
  199 
  200   // "Obviously" related windows - ID of active window
  201   // and event_window differ by 1. By performing this check first,
  202   // we avoid calling XQueryTree which causes a segfault
  203   // if the window queried is being closed.
  204   if (abs(active_win - ev_win) <= 1) {
  205     ret_val = TRUE;
  206   } else {
  207     if (cache_xquery_result(dpy, active_win)) {
  208       ret_val = lookup_in_xquery_cache(ev_win);
  209     }
  210   }
  211 
  212   return ret_val;
  213 }
  214 
  215 #define MAX_BUFFER_SIZE (256)
  216 
  217 void identify_switch_situation(FocusKeepStatus* stat)
  218 {
  219   if (stat->start_switch_window || stat->start_close_window) {
  220     // In the middle of a window switch.
  221     Window old_active = get_active_window(stat);
  222     stat->active_window = 0;
  223     stat->during_switch = TRUE;
  224 
  225     if (stat->start_close_window) {
  226       stat->during_close = TRUE;
  227     }
  228 
  229     LOG("Window switching detected, active was: %#lx close: %d\n",
  230         old_active, stat->during_close);
  231 
  232     // Reset the the flags.
  233     stat->start_switch_window = FALSE;
  234     stat->start_close_window = FALSE;
  235   }
  236 }
  237 
  238 void set_active_window(FocusKeepStatus* stat, XEvent* ev)
  239 {
  240   stat->active_window = extract_window_id(ev);
  241   if (stat->during_close) {
  242     stat->active_window_from_close = TRUE;
  243   } else {
  244     stat->active_window_from_close = FALSE;
  245   }
  246   stat->encountered_focus_in_event = FALSE;
  247   stat->during_switch = FALSE;
  248   stat->start_switch_window = FALSE;
  249   stat->start_close_window = FALSE;
  250   LOG("Setting Active Window due to FocusIn: %#lx (from close: %d)\n",
  251       get_active_window(stat), stat->active_window_from_close);
  252 }
  253 
  254 void identify_new_window_situation(FocusKeepStatus* stat, XEvent* ev)
  255 {
  256   Window new_win = extract_window_id(ev);
  257   assert(is_reparent_notify(ev));
  258 
  259   if (get_active_window(stat) != 0) {
  260     stat->new_window = new_win;
  261     LOG("New window being created: %#lx\n", stat->new_window);
  262   } else {
  263     LOG("Reparent notify for window: %#lx, but no active.\n", new_win);
  264   }
  265 }
  266 
  267 void identify_active_destroyed(FocusKeepStatus* stat, XEvent* ev)
  268 {
  269   assert(is_destroy_notify(ev));
  270 
  271   if (extract_window_id(ev) == get_active_window(stat)) {
  272     LOG("Active window: %#lx is destroyed!\n", get_active_window(stat));
  273     stat->active_window = 0;
  274   }
  275 }
  276 
  277 void steal_focus_back_if_needed(FocusKeepStatus* stat, Display* dpy)
  278 {
  279   if ((stat->should_steal_focus) && (get_active_window(stat) != 0)) {
  280     stat->should_steal_focus = FALSE;
  281 
  282     if ((!stat->during_close) || (stat->active_window_from_close)) {
  283       LOG("Stealing focus back to %#lx\n", get_active_window(stat));
  284       stat->new_window = 0;
  285 
  286       XSetInputFocus(dpy, get_active_window(stat), RevertToParent, CurrentTime);
  287       // Allow a focus in event to flow again to the window considered
  288       // active.
  289       stat->encountered_focus_in_event = FALSE;
  290     } else {
  291       LOG("Not stealing focus back. During close: %d Active from close: %d.\n",
  292           stat->during_close, stat->active_window_from_close);
  293       // Set during_close to false here - This is the point where the state
  294       // transition is done - specifically, we consider the entire close
  295       // process to be completed.
  296       stat->during_close = FALSE;
  297     }
  298   }
  299 }
  300 
  301 int should_discard_focus_out_event(FocusKeepStatus* stat, Display* dpy,
  302                                    XEvent *ev)
  303 {
  304   int ret_val = FALSE;
  305   if (is_focus_out(ev) == FALSE) {
  306     return FALSE;
  307   }
  308 
  309   const int detail = ev->xfocus.detail;
  310 
  311   if (stat->new_window != 0) {
  312     /*
  313     if (!(event_on_active_or_adj_window(dpy, ev, stat->new_window)
  314         || event_on_active_or_adj_window(dpy, ev, get_active_window(stat)))) {
  315       LOG( "ERROR - Event on window %#lx, which is neither new nor active.\n",
  316            extract_window_id(ev));
  317     } else */ {
  318       LOG("Event on new/active (%#lx) during new window creation, allowing.",
  319           extract_window_id(ev));
  320       LOG(" New: %#lx Active: %#lx\n", stat->new_window, stat->active_window);
  321     }
  322     return FALSE;
  323   }
  324 
  325   if (event_on_active_or_adj_window(dpy, ev, get_active_window(stat))) {
  326     // If moving ownership between sub-windows of the same Firefox window.
  327     if ((detail == NotifyAncestor) || (detail == NotifyInferior)) {
  328       // Allow this one.
  329       LOG("Focus will move to ancestor / inferior (%d). Allowing.\n", detail);
  330       stat->encountered_focus_in_event = FALSE;
  331     } else {
  332       // Disallow transfer of focus to outside windows.
  333       if (!stat->active_window_from_close) {
  334         ret_val = TRUE;
  335       } else {
  336         LOG("FocusOut event, but active window from close. Not discarding.\n");
  337       }
  338     }
  339   } else {
  340     LOG("Got Focus out event on window %#lx but active window is %#lx\n",
  341         extract_window_id(ev), get_active_window(stat));
  342   }
  343 
  344   return ret_val;
  345 }
  346 
  347 int should_discard_focus_in_event(FocusKeepStatus* stat, Display* dpy,
  348                                   XEvent *ev)
  349 {
  350   int ret_val = FALSE;
  351   if (is_focus_in(ev) == FALSE) {
  352     return FALSE;
  353   }
  354 
  355   // Event not on active window - It's either on a new window currently being
  356   // created or on a different firefox one. On the first case, it will
  357   // be allowed through, but blocked on the second case.
  358   if (!event_on_active_or_adj_window(dpy, ev, get_active_window(stat))) {
  359     LOG("Got Focus in event on window %#lx but active window is %#lx\n",
  360         extract_window_id(ev), get_active_window(stat));
  361 
  362     if (stat->new_window != 0) {
  363       // If we are in the process of a new window creation, do not ignore
  364       // this focus in event - allow it both for the new window
  365       // and for a child window of it. However, if this is a focus in
  366       // event for a child window (not the new window itself), then
  367       // steal focus back from it afterwards.
  368       ret_val = FALSE;
  369       Window curr_win = extract_window_id(ev);
  370       if (curr_win == stat->new_window) {
  371         LOG("FocusIn event on new window - allowing.\n");
  372       } else {
  373         //if (event_on_active_or_adj_window(dpy, ev, stat->new_window) == FALSE) {
  374         if (window_ids_difference(curr_win, stat->new_window) > 4) {
  375           LOG("ERROR - Event on window %#lx\n", extract_window_id(ev));
  376         } else {
  377           LOG("FocusIn event on child of new window - steal focus!\n");
  378         }
  379         stat->should_steal_focus = TRUE;
  380       }
  381     } else {
  382       // Second case: No new window creation process disallow focus in
  383       ret_val = TRUE;
  384     }
  385   } else {
  386     // Event actually on the active window or an inferior window
  387     // of it.
  388     if (stat->encountered_focus_in_event == FALSE) {
  389       // If a focus in event for this window was not yet encountered,
  390       // allow this focus in event and ignore in the future.
  391       stat->encountered_focus_in_event = TRUE;
  392       ret_val = FALSE;
  393     } else {
  394       ret_val = TRUE;
  395     }
  396   }
  397 
  398   return ret_val;
  399 }
  400 
  401 #ifndef NO_FAKING
  402 // Real functions
  403 void fake_keymap_notify_event(XEvent* outEvent, XEvent* sourceEvent)
  404 {
  405   XEvent ev;
  406   ev.type = KeymapNotify;
  407   ev.xkeymap.serial = sourceEvent->xfocus.serial;
  408   ev.xkeymap.send_event = sourceEvent->xfocus.send_event;
  409   ev.xkeymap.display = sourceEvent->xfocus.display;
  410   ev.xkeymap.window = sourceEvent->xfocus.window;
  411   //bzero(ev.xkeymap.key_vector, 32);
  412   *outEvent = ev;
  413 }
  414 
  415 #else
  416 // Dummy functions - faking will not happen.
  417 void fake_keymap_notify_event(XEvent* outEvent, XEvent* sourceEvent)
  418 {
  419   LOG("*** Not faking keymap notify event.\n");
  420   *outEvent = *sourceEvent;
  421 }
  422 
  423 static int XSetInputFocus(Display *display, Window focus, int revert_to,
  424                           Time time)
  425 {
  426   LOG("*** Not stealing focus.\n");
  427   return 1;
  428 }
  429 
  430 #endif
  431 
  432 int is_32bit_system()
  433 {
  434     struct utsname sys_info;
  435     int uname_res = uname(&sys_info);
  436     // In case of error, arbitrarily decide it is.
  437     if (uname_res != 0) {
  438       return TRUE;
  439     }
  440 
  441     const char arch_64[] = "x86_64";
  442     if (strncmp(sys_info.machine, arch_64, strlen(arch_64)) == 0) {
  443       return FALSE;
  444     }
  445 
  446     return TRUE;
  447 }
  448 
  449 int is_emulated_32bit()
  450 {
  451 #ifdef __i386__
  452     return !is_32bit_system();
  453 #else
  454     return FALSE;
  455 #endif
  456 }
  457 
  458 #define MAX_LIBRARY_PATH (1024)
  459 
  460 // Returns the window ID from every type of event
  461 // that should be handled.
  462 Window extract_window_id(XEvent* ev) {
  463   switch (ev->type) {
  464     case FocusIn:
  465       return ev->xfocus.window;
  466       break;
  467     case FocusOut:
  468       return ev->xfocus.window;
  469       break;
  470     case Expose:
  471       return ev->xexpose.window;
  472       break;
  473     case VisibilityNotify:
  474       return ev->xvisibility.window;
  475       break;
  476     case CreateNotify:
  477       return ev->xcreatewindow.window;
  478       break;
  479     case MapNotify:
  480       return ev->xmap.window;
  481       break;
  482     case PropertyNotify:
  483       return ev->xproperty.window;
  484       break;
  485     case DestroyNotify:
  486       return ev->xdestroywindow.window;
  487       break;
  488     case ConfigureNotify:
  489       return ev->xconfigure.window;
  490       break;
  491     case MotionNotify:
  492       return ev->xmotion.window;
  493       break;
  494     case UnmapNotify:
  495       return ev->xunmap.window;
  496       break;
  497     case EnterNotify:
  498     case LeaveNotify:
  499       return ev->xcrossing.window;
  500       break;
  501     case ReparentNotify:
  502       return ev->xreparent.window;
  503       break;
  504     case ClientMessage:
  505       return ev->xclient.window;
  506       break;
  507     case ButtonPress:
  508     case ButtonRelease:
  509       return ev->xbutton.window;
  510       break;
  511     case NoExpose:
  512       break;
  513     default:
  514       LOG("Unknown event type %d\n", ev->type);
  515   };
  516   return 0;
  517 }
  518 
  519 int is_library_for_architecture(const char* lib_path, uint16_t arch)
  520 {
  521   Elf32_Ehdr elf32_header;
  522   int elf32_header_size = sizeof(elf32_header);
  523 
  524   FILE* lib = fopen(lib_path, "r");
  525   int bytes_read = fread(&elf32_header, 1, elf32_header_size, lib);
  526   fclose(lib);
  527   lib = NULL;
  528 
  529   if (bytes_read != elf32_header_size) {
  530     return FALSE;
  531   }
  532 
  533   if ((memcmp(elf32_header.e_ident, ELFMAG, sizeof(ELFMAG) - 1) == 0)
  534       && (elf32_header.e_type == ET_DYN) && (elf32_header.e_machine == arch))
  535   {
  536     return TRUE;
  537   }
  538 
  539   return FALSE;
  540 }
  541 
  542 int is_usable_library(const char *candidate_library, uint16_t desired_architecture)
  543 {
  544   if (access(candidate_library, F_OK) == 0 &&
  545       is_library_for_architecture(candidate_library, desired_architecture) == TRUE) {
  546     void *ret_handle = dlopen(candidate_library, RTLD_LAZY);
  547     if (ret_handle == NULL) {
  548       return FALSE;
  549     }
  550     dlclose(ret_handle);
  551 
  552     return TRUE;
  553   }
  554   return FALSE;
  555 }
  556 
  557 int find_xlib_by_arch(const char* possible_locations[],
  558     int locations_length, uint16_t desired_architecture)
  559 {
  560   int i;
  561   for (i = 0; i < locations_length; i++) {
  562     const char* possible_location = possible_locations[i];
  563 
  564     if (is_usable_library(possible_location, desired_architecture))
  565     {
  566       return i;
  567     }
  568   }
  569 
  570   return -1;
  571 }
  572 
  573 
  574 int find_xlib_by_env(char *library, uint16_t desired_architecture)
  575 {
  576   char *ld_env = getenv("LD_LIBRARY_PATH");
  577   if (ld_env == 0) {
  578     return FALSE;
  579   }
  580 
  581   char *ld_to_parse = strdup(ld_env);
  582 
  583   int found_library = FALSE;
  584   char *t = strtok(ld_to_parse, ":");
  585   char potential_library[MAX_LIBRARY_PATH + 1];
  586 
  587   while ((t != NULL) && (!found_library)) {
  588     snprintf(potential_library, MAX_LIBRARY_PATH, "%s/libX11.so.6", t);
  589     if (is_usable_library(potential_library, desired_architecture)) {
  590       strcpy(library, potential_library);
  591       found_library = TRUE;
  592     }
  593     t = strtok(NULL, ":");
  594   }
  595 
  596   free(ld_to_parse);
  597   return found_library;
  598 }
  599 
  600 void* get_xlib_handle()
  601 {
  602   void* ret_handle = NULL;
  603   char library[MAX_LIBRARY_PATH + 1];
  604 
  605   const char * possible_locations[] = {
  606         "/usr/lib/libX11.so.6",                   //default_x11_location
  607         "/usr/lib/x86_64-linux-gnu/libX11.so.6",  //debian_x11_location
  608         "/usr/lib/i386-linux-gnu/libX11.so.6",    //ubuntu_32bit_x11_location
  609         "/usr/lib64/libX11.so.6",                 //opensuse_x11_location
  610         "/usr/lib32/libX11.so.6"
  611   };
  612   int locations_len = sizeof(possible_locations) / sizeof(char*);
  613 
  614   uint16_t required_lib_arch;
  615   if (is_32bit_system() || is_emulated_32bit()) {
  616     required_lib_arch = EM_386;
  617   } else {
  618     required_lib_arch = EM_X86_64;
  619   }
  620   int suitable_xlib_index = find_xlib_by_arch(possible_locations, locations_len, required_lib_arch);
  621   int found_library = FALSE;
  622   if (suitable_xlib_index >= 0) {
  623     snprintf(library, MAX_LIBRARY_PATH, "%s", possible_locations[suitable_xlib_index]);
  624     found_library = TRUE;
  625   } else {
  626     found_library = find_xlib_by_env(library, required_lib_arch);
  627   }
  628   if (found_library == FALSE) {
  629     const char* desired_arch = (required_lib_arch == EM_386 ? "32-bit" : "64-bit");
  630     fprintf(stderr, "None of the following is a %s version of Xlib:", desired_arch);
  631     int i;
  632     for (i = 0; i < locations_len; i++) {
  633       fprintf(stderr, " %s\n", possible_locations[i]);
  634     }
  635     return NULL;
  636   }
  637 
  638   ret_handle = dlopen(library, RTLD_LAZY);
  639   if (ret_handle == NULL) {
  640     fprintf(stderr, "Failed to dlopen %s\n", library);
  641     fprintf(stderr, "dlerror says: %s\n", dlerror());
  642   }
  643 
  644   return ret_handle;
  645 }
  646 
  647 void print_event_to_log(Display* dpy, XEvent* ev)
  648 {
  649 #ifdef DEBUG_PRINTOUTS
  650   if ((ev->type != PropertyNotify) && (ev->type != ConfigureNotify)) {
  651     print_event(g_out_stream, ev, dpy);
  652   }
  653 #endif
  654 }
  655 
  656 // This global variable is intentionally declared here - as I wish the rest
  657 // of the functions will act on it as a parameter.
  658 FocusKeepStatus g_focus_status;
  659 
  660 void initFocusStatusAndXQueryTree() {
  661   if (g_library_inited == FALSE) {
  662     LOG("Library initialized.\n");
  663     g_library_inited = TRUE;
  664     init_cached_xquerytree();
  665     init_focus_keep_struct(&g_focus_status);
  666   }
  667 }
  668 
  669 int XNextEvent(Display *display, XEvent *outEvent) {
  670   // Code to pull the real function handle from X11 library.
  671   void *handle = NULL;
  672 
  673   //This will turn the function proto into a function pointer declaration
  674   int (*real_func)(Display *display, XEvent *outEvent) = NULL;
  675   handle = get_xlib_handle();
  676 
  677   if (handle == NULL) {
  678     return -1;
  679   }
  680 
  681   // The real event from XNextEvent
  682   XEvent realEvent;
  683 
  684   // Find the real function.
  685   real_func = dlsym(handle, "XNextEvent");
  686   // Invoke the real function.
  687   int rf_ret = real_func(display, &realEvent);
  688 
  689   OPEN_LOGGING_FILE;
  690 
  691   initFocusStatusAndXQueryTree();
  692 
  693   // This display object will be used to inquire X server
  694   // about inferior and parent windows.
  695   Display* dpy = display;
  696   //assert(dpy != NULL);
  697 
  698   print_event_to_log(dpy, &realEvent);
  699 
  700   // Is the event on a window other than the active one?
  701   // If so, update gActiveWindow on two cases:
  702   // 1. It's the first window known to the module.
  703   // 2. It's the second window known to the module. The second
  704   // window is the actual browser window (the first one is just a
  705   // set-up one).
  706   //
  707   if ((get_active_window(&g_focus_status) == 0) && (is_focus_in(&realEvent))) {
  708     set_active_window(&g_focus_status, &realEvent);
  709   } else {
  710     identify_switch_situation(&g_focus_status);
  711   }
  712 
  713   if (is_reparent_notify(&realEvent)) {
  714     identify_new_window_situation(&g_focus_status, &realEvent);
  715   }
  716 
  717   if (is_destroy_notify(&realEvent)) {
  718     identify_active_destroyed(&g_focus_status, &realEvent);
  719   }
  720 
  721   if ((g_focus_status.during_switch == TRUE) ||
  722       (get_active_window(&g_focus_status) == 0)) {
  723       LOG("During switch: %d Active win: %#lx during close: %d\n",
  724           g_focus_status.during_switch, get_active_window(&g_focus_status),
  725           g_focus_status.during_close);
  726     *outEvent = realEvent;
  727   } else if (should_discard_focus_out_event(&g_focus_status, dpy, &realEvent)) {
  728     // Fake an event!
  729     fake_keymap_notify_event(outEvent, &realEvent);
  730     LOG("Fake event for focus out.\n");
  731   }  else if (should_discard_focus_in_event(&g_focus_status, dpy, &realEvent)) {
  732     fake_keymap_notify_event(outEvent, &realEvent);
  733     LOG("Fake event for focus in.\n");
  734   } else {
  735     *outEvent = realEvent;
  736   }
  737 
  738   steal_focus_back_if_needed(&g_focus_status, dpy);
  739 
  740   dlclose(handle);
  741   CLOSE_LOGGING_FILE;
  742   return rf_ret;
  743 }
  744 
  745 void notify_of_switch_to_window(long window_id) {
  746   initFocusStatusAndXQueryTree();
  747   g_focus_status.start_switch_window = TRUE;
  748   OPEN_LOGGING_FILE;
  749   LOG("Notify of switch-to-window with id %d\n", window_id);
  750   CLOSE_LOGGING_FILE;
  751 }
  752 
  753 void notify_of_close_window(long window_id) {
  754   initFocusStatusAndXQueryTree();
  755   g_focus_status.start_close_window = TRUE;
  756   OPEN_LOGGING_FILE;
  757   if (0 == window_id) {
  758     LOG("Notify of close-all-windows.\n");
  759   } else {
  760     LOG("Notify of close-window with id %n", window_id);
  761   }
  762   CLOSE_LOGGING_FILE;
  763 }