void () { // exec at glib-main-thread _stopTimer(); final Timer timer = new Timer(50, null); timer.addActionListener((e) -> { if (TRACE_EVENT_FILTER) _trace("EventFilter: start execution of timer callback"); // exec at EDT if (myTimer != timer) {// check that timer wasn't reset if (TRACE_EVENT_FILTER) _trace("EventFilter: skip timer-processing because timer was reset (i.e. myTimer == null)"); return; } ourLib.execOnMainLoop(glibLoopRunnable = () -> { // remove continuous series of sequential root events // because some implementations (of menu applet) regularly send packets of root events ('about-to-show' or/and 'open') int lastRootId = roots.size() - 1; int from = 0; while (from < queued.size()) { int size = queued.size(); // 1. find event from second root while (from < size && queued.get(from).rootId != 1) { ++from; } if (from == size) { break; } // 2. rewinds to first root int first = from - 1; if (first < 0 || queued.get(first).rootId != 0) { // no events from first root, rewind forward while (from < size && queued.get(from).rootId == 1) ++from; continue; } while (first >= 1 && queued.get(first - 1).rootId == 0 && from - first <= 1) { --first; } // 3. find last root int to = from + 1; while (to < size && queued.get(to).rootId != lastRootId) { ++to; } if (to == size) { break; } while (to < size && queued.get(to).rootId == lastRootId) { ++to; } // 4. remove fake segment if (TRACE_EVENT_FILTER) { _trace("EventFilter: remove segment [%d, %d) from queue of size=%d", first, to, queued.size()); } queued.subList(first, to).clear(); from = first + 1; } if (!queued.isEmpty()) { if (TRACE_ENABLED) { _trace("EventFilter: process queued events, size=%d", queued.size()); } _processQueue(); } else if (TRACE_ENABLED) { _trace("EventFilter: queue is empty"); } myTimer = null; closedMs = 0; // open filter if (TRACE_EVENT_FILTER) { _trace("EventFilter: filter is opened"); } }); }); myTimer = timer; myTimer.setRepeats(false); myTimer.start(); if (TRACE_EVENT_FILTER) { _trace("EventFilter: start timer"); } }