• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "ui/views/test/x11_property_change_waiter.h"
6 
7 #include <X11/Xlib.h>
8 
9 #include "base/run_loop.h"
10 #include "ui/events/platform/platform_event_source.h"
11 #include "ui/events/platform/scoped_event_dispatcher.h"
12 #include "ui/gfx/x/x11_atom_cache.h"
13 
14 namespace views {
15 
X11PropertyChangeWaiter(XID window,const char * property)16 X11PropertyChangeWaiter::X11PropertyChangeWaiter(XID window,
17                                                  const char* property)
18     : x_window_(window),
19       property_(property),
20       wait_(true),
21       old_event_mask_(0) {
22   Display* display = gfx::GetXDisplay();
23 
24   // Ensure that we are listening to PropertyNotify events for |window|. This
25   // is not the case for windows which were not created by
26   // DesktopWindowTreeHostX11.
27   XWindowAttributes attributes;
28   XGetWindowAttributes(display, x_window_, &attributes);
29   old_event_mask_ = attributes.your_event_mask;
30   XSelectInput(display, x_window_, old_event_mask_ | PropertyChangeMask);
31 
32   const char* kAtomsToCache[] = { property, NULL };
33   atom_cache_.reset(new ui::X11AtomCache(display, kAtomsToCache));
34 
35   // Override the dispatcher so that we get events before
36   // DesktopWindowTreeHostX11 does. We must do this because
37   // DesktopWindowTreeHostX11 stops propagation.
38   dispatcher_ = ui::PlatformEventSource::GetInstance()->
39       OverrideDispatcher(this).Pass();
40 }
41 
~X11PropertyChangeWaiter()42 X11PropertyChangeWaiter::~X11PropertyChangeWaiter() {
43   XSelectInput(gfx::GetXDisplay(), x_window_, old_event_mask_);
44 }
45 
Wait()46 void X11PropertyChangeWaiter::Wait() {
47   if (!wait_)
48     return;
49 
50   base::RunLoop run_loop;
51   quit_closure_ = run_loop.QuitClosure();
52   run_loop.Run();
53 
54   dispatcher_.reset();
55 }
56 
ShouldKeepOnWaiting(const ui::PlatformEvent & event)57 bool X11PropertyChangeWaiter::ShouldKeepOnWaiting(
58     const ui::PlatformEvent& event) {
59   // Stop waiting once we get a property change.
60   return true;
61 }
62 
CanDispatchEvent(const ui::PlatformEvent & event)63 bool X11PropertyChangeWaiter::CanDispatchEvent(const ui::PlatformEvent& event) {
64   NOTREACHED();
65   return true;
66 }
67 
DispatchEvent(const ui::PlatformEvent & event)68 uint32_t X11PropertyChangeWaiter::DispatchEvent(
69     const ui::PlatformEvent& event) {
70   if (!wait_ ||
71       event->type != PropertyNotify ||
72       event->xproperty.window != x_window_ ||
73       event->xproperty.atom != atom_cache_->GetAtom(property_) ||
74       ShouldKeepOnWaiting(event)) {
75     return ui::POST_DISPATCH_PERFORM_DEFAULT;
76   }
77 
78   wait_ = false;
79   if (!quit_closure_.is_null())
80     quit_closure_.Run();
81   return ui::POST_DISPATCH_PERFORM_DEFAULT;
82 }
83 
84 }  // namespace views
85