Advertisement
Guest User

Untitled

a guest
May 28th, 2017
530
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.58 KB | None | 0 0
  1. /*****************************************************************************
  2.  *
  3.  * Authors: Michel Eyckmans (MCE) & Stefan De Troch (SDT)
  4.  *
  5.  * Content: This file is part of version 2.x of xautolock. It implements
  6.  *          the stuff used when the program is not using a screen saver
  7.  *          extension and thus has to use the good old "do it yourself"
  8.  *          approach for detecting user activity.
  9.  *
  10.  *          The basic idea is that we initially traverse the window tree,
  11.  *          selecting SubstructureNotify on all windows and adding each
  12.  *          window to a temporary list. About +- 30 seconds later, we
  13.  *          scan this list, now asking for KeyPress events. The delay
  14.  *          is needed in order to interfere as little as possible with
  15.  *          the event propagation mechanism. Whenever a new window is
  16.  *          created by an application, a similar process takes place.
  17.  *
  18.  *          Please send bug reports etc. to mce@scarlet.be.
  19.  *
  20.  * --------------------------------------------------------------------------
  21.  *
  22.  * Copyright 1990, 1992-1999, 2001-2002, 2004, 2007 by  Stefan De Troch and
  23.  * Michel Eyckmans.
  24.  *
  25.  * Versions 2.0 and above of xautolock are available under version 2 of the
  26.  * GNU GPL. Earlier versions are available under other conditions. For more
  27.  * information, see the License file.
  28.  *
  29.  *****************************************************************************/
  30.  
  31. #include "diy.h"
  32. #include "state.h"
  33. #include "options.h"
  34. #include "miscutil.h"
  35.  
  36. static void selectEvents (Window window, Bool substructureOnly);
  37.  
  38. /*
  39.  *  Window queue management.
  40.  */
  41. typedef struct item
  42. {
  43.   Window       window;
  44.   time_t       creationtime;
  45.   struct item* next;
  46. } anItem, *item;
  47.  
  48. static struct
  49. {
  50.   Display*     display;
  51.   struct item* head;
  52.   struct item* tail;
  53. } queue;
  54.  
  55. static void
  56. addToQueue (Window window)
  57. {
  58.   item newItem = newObj (anItem);
  59.  
  60.   newItem->window = window;
  61.   newItem->creationtime = time (0);
  62.   newItem->next = 0;
  63.  
  64.   if (!queue.head) queue.head = newItem;
  65.   if ( queue.tail) queue.tail->next = newItem;
  66.  
  67.   queue.tail = newItem;
  68. }
  69.  
  70. static void
  71. processQueue (time_t age)
  72. {
  73.   if (queue.head)
  74.   {
  75.     time_t now = time (0);
  76.     item current = queue.head;
  77.  
  78.     while (current && current->creationtime + age < now)
  79.     {
  80.       selectEvents (current->window, False);
  81.       queue.head = current->next;
  82.       free (current);
  83.       current = queue.head;
  84.     }
  85.  
  86.     if (!queue.head) queue.tail = 0;
  87.   }
  88. }
  89.  
  90. /*
  91.  *  Function for selecting all interesting events on a given
  92.  *  (tree of) window(s).
  93.  */
  94. static void
  95. selectEvents (Window window, Bool substructureOnly)
  96. {
  97.   Window            root;              /* root window of the window */
  98.   Window            parent;            /* parent of the window      */
  99.   Window*           children;          /* children of the window    */
  100.   unsigned          nofChildren = 0;   /* number of children        */
  101.   unsigned          i;                 /* loop counter              */
  102.   XWindowAttributes attribs;           /* attributes of the window  */
  103.  
  104.  /*
  105.   *  Start by querying the server about the root and parent windows.
  106.   */
  107.   if (!XQueryTree (queue.display, window, &root, &parent,
  108.                    &children, &nofChildren))
  109.   {
  110.     return;
  111.   }
  112.  
  113.   if (nofChildren) (void) XFree ((char*) children);
  114.  
  115.  /*
  116.   *  Build the appropriate event mask. The basic idea is that we don't
  117.   *  want to interfere with the normal event propagation mechanism if
  118.   *  we don't have to.
  119.   *
  120.   *  On the root window, we need to ask for both substructureNotify
  121.   *  and KeyPress events. On all other windows, we always need
  122.   *  substructureNotify, but only need Keypress if some other client
  123.   *  also asked for them, or if they are not being propagated up the
  124.   *  window tree.
  125.   */
  126.   if (substructureOnly)
  127.   {
  128.     (void) XSelectInput (queue.display, window, SubstructureNotifyMask);
  129.   }
  130.   else
  131.   {
  132.     if (parent == None) /* the *real* rootwindow */
  133.     {
  134.       attribs.all_event_masks =
  135.       attribs.do_not_propagate_mask = KeyPressMask;
  136.     }
  137.     else if (!XGetWindowAttributes (queue.display, window, &attribs))
  138.     {
  139.       return;
  140.     }
  141.  
  142.     (void) XSelectInput (queue.display, window,
  143.                            SubstructureNotifyMask
  144.                          | (  (  attribs.all_event_masks
  145.                                | attribs.do_not_propagate_mask)
  146.                             & KeyPressMask));
  147.   }
  148.  
  149.  /*
  150.   *  Now ask for the list of children again, since it might have changed
  151.   *  in between the last time and us selecting SubstructureNotifyMask.
  152.   *
  153.   *  There is a (very small) chance that we might process a subtree twice:
  154.   *  child windows that have been created after our XSelectinput() has
  155.   *  been processed but before we get to the XQueryTree() bit will be
  156.   *  in this situation. This is harmless. It could be avoided by using
  157.   *  XGrabServer(), but that'd be an impolite thing to do, and since it
  158.   *  isn't required...
  159.   */
  160.   if (!XQueryTree (queue.display, window, &root, &parent,
  161.                    &children, &nofChildren))
  162.   {
  163.     return;
  164.   }
  165.  
  166.  /*
  167.   *  Now do the same thing for all children.
  168.   */
  169.   for (i = 0; i < nofChildren; ++i)
  170.   {
  171.     selectEvents (children[i], substructureOnly);
  172.   }
  173.  
  174.   if (nofChildren) (void) XFree ((char*) children);
  175. }
  176.  
  177. /*
  178.  *  Function for processing any events that have come in since
  179.  *  last time. It is crucial that this function does not block
  180.  *  in case nothing interesting happened.
  181.  */
  182. void
  183. processEvents (void)
  184. {
  185.   while (XPending (queue.display))
  186.   {
  187.     XEvent event;
  188.  
  189.     if (XCheckMaskEvent (queue.display, SubstructureNotifyMask, &event))
  190.     {
  191.       if (event.type == CreateNotify)
  192.       {
  193.         addToQueue (event.xcreatewindow.window);
  194.       }
  195.     }
  196.     else
  197.     {
  198.       (void) XNextEvent (queue.display, &event);
  199.     }
  200.  
  201.    /*
  202.     *  Reset the triggers if and only if the event is a
  203.     *  KeyPress event *and* was not generated by XSendEvent().
  204.     */
  205.     if (   event.type == KeyPress
  206.         && !event.xany.send_event)
  207.     {
  208.       resetTriggers ();
  209.     }
  210.   }
  211.  
  212.  /*
  213.   *  Check the window queue for entries that are older than
  214.   *  CREATION_DELAY seconds.
  215.   */
  216.   processQueue ((time_t) CREATION_DELAY);
  217. }
  218.  
  219. /*
  220.  *  Function for initialising the whole shebang.
  221.  */
  222. void
  223. initDiy (Display* d)
  224. {
  225.   int s;
  226.  
  227.   queue.display = d;
  228.   queue.tail = 0;
  229.   queue.head = 0;
  230.  
  231.   for (s = -1; ++s < ScreenCount (d); )
  232.   {
  233.     Window root = RootWindowOfScreen (ScreenOfDisplay (d, s));
  234.     addToQueue (root);
  235.     selectEvents (root, True);
  236.   }
  237. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement