Guest User

Untitled

a guest
May 27th, 2018
119
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 20.38 KB | None | 0 0
  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_emulated_32bit()
  433. {
  434. #ifdef __i386__
  435.     struct utsname sys_info;
  436.     int uname_res = uname(&sys_info);
  437.     // In case of error, most chances are - not emulated.
  438.     if (uname_res != 0) {
  439.       return FALSE;
  440.     }
  441.  
  442.     const char arch_64[] = "x86_64";
  443.     if (strncmp(sys_info.machine, arch_64, strlen(arch_64)) == 0) {
  444.       return TRUE;
  445.     }
  446.  
  447.     return FALSE;
  448. #else
  449.     return FALSE;
  450. #endif
  451. }
  452.  
  453. #define MAX_LIBRARY_PATH (1024)
  454.  
  455. // Returns the window ID from every type of event
  456. // that should be handled.
  457. Window extract_window_id(XEvent* ev) {
  458.   switch (ev->type) {
  459.     case FocusIn:
  460.       return ev->xfocus.window;
  461.       break;
  462.     case FocusOut:
  463.       return ev->xfocus.window;
  464.       break;
  465.     case Expose:
  466.       return ev->xexpose.window;
  467.       break;
  468.     case VisibilityNotify:
  469.       return ev->xvisibility.window;
  470.       break;
  471.     case CreateNotify:
  472.       return ev->xcreatewindow.window;
  473.       break;
  474.     case MapNotify:
  475.       return ev->xmap.window;
  476.       break;
  477.     case PropertyNotify:
  478.       return ev->xproperty.window;
  479.       break;
  480.     case DestroyNotify:
  481.       return ev->xdestroywindow.window;
  482.       break;
  483.     case ConfigureNotify:
  484.       return ev->xconfigure.window;
  485.       break;
  486.     case MotionNotify:
  487.       return ev->xmotion.window;
  488.       break;
  489.     case UnmapNotify:
  490.       return ev->xunmap.window;
  491.       break;
  492.     case EnterNotify:
  493.     case LeaveNotify:
  494.       return ev->xcrossing.window;
  495.       break;
  496.     case ReparentNotify:
  497.       return ev->xreparent.window;
  498.       break;
  499.     case ClientMessage:
  500.       return ev->xclient.window;
  501.       break;
  502.     case ButtonPress:
  503.     case ButtonRelease:
  504.       return ev->xbutton.window;
  505.       break;
  506.     case NoExpose:
  507.       break;
  508.     default:
  509.       LOG("Unknown event type %d\n", ev->type);
  510.   };
  511.   return 0;
  512. }
  513.  
  514. int is_library_for_architecture(const char* lib_name, uint16_t architecture_type)
  515. {
  516.     Elf32_Ehdr elf32_header;
  517.     int sz_elf32_header = sizeof(elf32_header);
  518.  
  519.     FILE* lib = fopen(lib_name, "r");
  520.     int sz_readed = fread(&elf32_header, 1, sz_elf32_header, lib);
  521.     fclose(lib);
  522.  
  523.     if (sz_readed != sz_elf32_header) {
  524.         return 1;
  525.     }
  526.  
  527.     if (memcmp(elf32_header.e_ident, ELFMAG, sizeof(ELFMAG) - 1) == 0
  528.             && elf32_header.e_type == ET_DYN
  529.             && elf32_header.e_machine == architecture_type)
  530.     {
  531.         return 0;
  532.     }
  533.  
  534.     return 1;
  535. }
  536.  
  537. int find_xlib(const char* possible_locations[],
  538.         int locations_length, uint16_t architecture_type, char location[])
  539. {
  540.     location[0] = 0x0;
  541.  
  542.     int i;
  543.     for (i = 0; i < locations_length; i++) {
  544.         const char* possible_location = possible_locations[i];
  545.  
  546.         if (access(possible_location, F_OK) == 0 &&
  547.             is_library_for_architecture(possible_location, architecture_type) == 0)
  548.         {
  549.             snprintf(location, MAX_LIBRARY_PATH, possible_location);
  550.             return 0;
  551.         }
  552.     }
  553.  
  554.     return 1;
  555. }
  556.  
  557. void* get_xlib_handle()
  558. {
  559.   void* ret_handle = NULL;
  560.   char library[MAX_LIBRARY_PATH + 1];
  561.  
  562.   int xlib_found = 1;
  563.   const char * possible_locations[] = {
  564.         "/usr/lib/libX11.so.6",                   //default_x11_location
  565.         "/usr/lib/x86_64-linux-gnu/libX11.so.6",  //debian_x11_location
  566.         "/usr/lib/i386-linux-gnu/libX11.so.6",    //ubuntu_32bit_x11_location
  567.         "/usr/lib64/libX11.so.6",                 //opensuse_x11_location
  568.         "/usr/lib32/libX11.so.6"
  569.   };
  570.   int locations_len = sizeof(possible_locations) / sizeof(char*);
  571.  
  572.   uint16_t architecture_type = (is_emulated_32bit() == FALSE ? EM_X86_64 : EM_386);
  573.   char * error_message = (is_emulated_32bit() == FALSE
  574.           ? "libX11_64bit could not be found on the following pathes: \n"
  575.           : "libX11_32bit could not be found on the following pathes: \n");
  576.  
  577.   xlib_found = find_xlib(possible_locations, locations_len, architecture_type, library);
  578.   if (xlib_found != 0) {
  579.       int i;
  580.       fprintf(stderr, error_message);
  581.       for (i = 0; i < locations_len; i++) {
  582.           fprintf(stderr, " %s\n", possible_locations[i]);
  583.       }
  584.   }
  585.  
  586.   if (xlib_found == 0) {
  587.       ret_handle = dlopen(library, RTLD_LAZY);
  588.       if (ret_handle == NULL) {
  589.         fprintf(stderr, "Failed to dlopen %s\n", library);
  590.         fprintf(stderr, "dlerror says: %s\n", dlerror());
  591.       }
  592.   }
  593.  
  594.   return ret_handle;
  595. }
  596.  
  597. void print_event_to_log(Display* dpy, XEvent* ev)
  598. {
  599. #ifdef DEBUG_PRINTOUTS
  600.   if ((ev->type != PropertyNotify) && (ev->type != ConfigureNotify)) {
  601.     print_event(g_out_stream, ev, dpy);
  602.   }
  603. #endif
  604. }
  605.  
  606. // This global variable is intentionally declared here - as I wish the rest
  607. // of the functions will act on it as a parameter.
  608. FocusKeepStatus g_focus_status;
  609.  
  610. void initFocusStatusAndXQueryTree() {
  611.   if (g_library_inited == FALSE) {
  612.     LOG("Library initialized.\n");
  613.     g_library_inited = TRUE;
  614.     init_cached_xquerytree();
  615.     init_focus_keep_struct(&g_focus_status);
  616.   }
  617. }
  618.  
  619. int XNextEvent(Display *display, XEvent *outEvent) {
  620.   // Code to pull the real function handle from X11 library.
  621.   void *handle = NULL;
  622.  
  623.   //This will turn the function proto into a function pointer declaration
  624.   int (*real_func)(Display *display, XEvent *outEvent) = NULL;
  625.   handle = get_xlib_handle();
  626.  
  627.   if (handle == NULL) {
  628.     return -1;
  629.   }
  630.  
  631.   // The real event from XNextEvent
  632.   XEvent realEvent;
  633.  
  634.   // Find the real function.
  635.   real_func = dlsym(handle, "XNextEvent");
  636.   // Invoke the real function.
  637.   int rf_ret = real_func(display, &realEvent);
  638.  
  639.   OPEN_LOGGING_FILE;
  640.  
  641.   initFocusStatusAndXQueryTree();
  642.  
  643.   // This display object will be used to inquire X server
  644.   // about inferior and parent windows.
  645.   Display* dpy = display;
  646.   //assert(dpy != NULL);
  647.  
  648.   print_event_to_log(dpy, &realEvent);
  649.  
  650.   // Is the event on a window other than the active one?
  651.   // If so, update gActiveWindow on two cases:
  652.   // 1. It's the first window known to the module.
  653.   // 2. It's the second window known to the module. The second
  654.   // window is the actual browser window (the first one is just a
  655.   // set-up one).
  656.   //
  657.   if ((get_active_window(&g_focus_status) == 0) && (is_focus_in(&realEvent))) {
  658.     set_active_window(&g_focus_status, &realEvent);
  659.   } else {
  660.     identify_switch_situation(&g_focus_status);
  661.   }
  662.  
  663.   if (is_reparent_notify(&realEvent)) {
  664.     identify_new_window_situation(&g_focus_status, &realEvent);
  665.   }
  666.  
  667.   if (is_destroy_notify(&realEvent)) {
  668.     identify_active_destroyed(&g_focus_status, &realEvent);
  669.   }
  670.  
  671.   if ((g_focus_status.during_switch == TRUE) ||
  672.       (get_active_window(&g_focus_status) == 0)) {
  673.       LOG("During switch: %d Active win: %#lx during close: %d\n",
  674.           g_focus_status.during_switch, get_active_window(&g_focus_status),
  675.           g_focus_status.during_close);
  676.     *outEvent = realEvent;
  677.   } else if (should_discard_focus_out_event(&g_focus_status, dpy, &realEvent)) {
  678.     // Fake an event!
  679.     fake_keymap_notify_event(outEvent, &realEvent);
  680.     LOG("Fake event for focus out.\n");
  681.   }  else if (should_discard_focus_in_event(&g_focus_status, dpy, &realEvent)) {
  682.     fake_keymap_notify_event(outEvent, &realEvent);
  683.     LOG("Fake event for focus in.\n");
  684.   } else {
  685.     *outEvent = realEvent;
  686.   }
  687.  
  688.   steal_focus_back_if_needed(&g_focus_status, dpy);
  689.  
  690.   dlclose(handle);
  691.   CLOSE_LOGGING_FILE;
  692.   return rf_ret;
  693. }
  694.  
  695. void notify_of_switch_to_window(long window_id) {
  696.   initFocusStatusAndXQueryTree();
  697.   g_focus_status.start_switch_window = TRUE;
  698.   OPEN_LOGGING_FILE;
  699.   LOG("Notify of switch-to-window with id %d\n", window_id);
  700.   CLOSE_LOGGING_FILE;
  701. }
  702.  
  703. void notify_of_close_window(long window_id) {
  704.   initFocusStatusAndXQueryTree();
  705.   g_focus_status.start_close_window = TRUE;
  706.   OPEN_LOGGING_FILE;
  707.   if (0 == window_id) {
  708.     LOG("Notify of close-all-windows.\n");
  709.   } else {
  710.     LOG("Notify of close-window with id %n", window_id);
  711.   }
  712.   CLOSE_LOGGING_FILE;
  713. }
Add Comment
Please, Sign In to add comment