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 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 42 X11PropertyChangeWaiter::~X11PropertyChangeWaiter() { 43 XSelectInput(gfx::GetXDisplay(), x_window_, old_event_mask_); 44 } 45 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 57 bool X11PropertyChangeWaiter::ShouldKeepOnWaiting( 58 const ui::PlatformEvent& event) { 59 // Stop waiting once we get a property change. 60 return true; 61 } 62 63 bool X11PropertyChangeWaiter::CanDispatchEvent(const ui::PlatformEvent& event) { 64 NOTREACHED(); 65 return true; 66 } 67 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