blob: cdfd31dd6a4fb4c6a990f38350751c1f4f55d7d8 [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/views/test/x11_property_change_waiter.h"
#include <X11/Xlib.h>
#include "base/run_loop.h"
#include "ui/events/platform/platform_event_source.h"
#include "ui/events/platform/scoped_event_dispatcher.h"
#include "ui/gfx/x/x11_atom_cache.h"
namespace views {
X11PropertyChangeWaiter::X11PropertyChangeWaiter(XID window,
const char* property)
: x_window_(window),
property_(property),
wait_(true),
old_event_mask_(0) {
Display* display = gfx::GetXDisplay();
// Ensure that we are listening to PropertyNotify events for |window|. This
// is not the case for windows which were not created by
// DesktopWindowTreeHostX11.
XWindowAttributes attributes;
XGetWindowAttributes(display, x_window_, &attributes);
old_event_mask_ = attributes.your_event_mask;
XSelectInput(display, x_window_, old_event_mask_ | PropertyChangeMask);
const char* kAtomsToCache[] = { property, NULL };
atom_cache_.reset(new ui::X11AtomCache(display, kAtomsToCache));
// Override the dispatcher so that we get events before
// DesktopWindowTreeHostX11 does. We must do this because
// DesktopWindowTreeHostX11 stops propagation.
dispatcher_ = ui::PlatformEventSource::GetInstance()->
OverrideDispatcher(this).Pass();
}
X11PropertyChangeWaiter::~X11PropertyChangeWaiter() {
XSelectInput(gfx::GetXDisplay(), x_window_, old_event_mask_);
}
void X11PropertyChangeWaiter::Wait() {
if (!wait_)
return;
base::RunLoop run_loop;
quit_closure_ = run_loop.QuitClosure();
run_loop.Run();
dispatcher_.reset();
}
bool X11PropertyChangeWaiter::ShouldKeepOnWaiting(
const ui::PlatformEvent& event) {
// Stop waiting once we get a property change.
return true;
}
bool X11PropertyChangeWaiter::CanDispatchEvent(const ui::PlatformEvent& event) {
NOTREACHED();
return true;
}
uint32_t X11PropertyChangeWaiter::DispatchEvent(
const ui::PlatformEvent& event) {
if (!wait_ ||
event->type != PropertyNotify ||
event->xproperty.window != x_window_ ||
event->xproperty.atom != atom_cache_->GetAtom(property_) ||
ShouldKeepOnWaiting(event)) {
return ui::POST_DISPATCH_PERFORM_DEFAULT;
}
wait_ = false;
if (!quit_closure_.is_null())
quit_closure_.Run();
return ui::POST_DISPATCH_PERFORM_DEFAULT;
}
} // namespace views