Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1022)

Unified Diff: ui/base/x/x11_window_event_manager.cc

Issue 2313033002: Refactor X11ForeignWindowManager (Reland) (Closed)
Patch Set: Rename to XWindowEventmanager Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: ui/base/x/x11_window_event_manager.cc
diff --git a/ui/base/x/x11_window_event_manager.cc b/ui/base/x/x11_window_event_manager.cc
new file mode 100644
index 0000000000000000000000000000000000000000..c91fc29f834aef093f385a0b83d6db375145f5a1
--- /dev/null
+++ b/ui/base/x/x11_window_event_manager.cc
@@ -0,0 +1,104 @@
+// 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/base/x/x11_window_event_manager.h"
+
+#include <stddef.h>
+#include <X11/Xlib.h>
+#include <X11/Xlib-xcb.h>
+#include <xcb/xcb.h>
+
+#include "base/compiler_specific.h"
+#include "base/memory/singleton.h"
+
+namespace ui {
+
+// static
+XWindowEventManager* XWindowEventManager::GetInstance() {
+ return base::Singleton<XWindowEventManager>::get();
+}
+
+void XWindowEventManager::SelectEvents(XID xid, uint32_t event_mask) {
+ BeforeMaskChanged(xid);
+ MultiMask& mask = mask_map_[xid];
+ mask.AddMask(event_mask);
+ AfterMaskChanged(xid);
+}
+
+void XWindowEventManager::DeselectEvents(XID xid, uint32_t event_mask) {
+ DCHECK(mask_map_.find(xid) != mask_map_.end());
+ BeforeMaskChanged(xid);
+ MultiMask& mask = mask_map_[xid];
+ mask.RemoveMask(event_mask);
+ AfterMaskChanged(xid);
+}
+
+XWindowEventManager::XWindowEventManager() {}
+XWindowEventManager::~XWindowEventManager() {}
+
+void XWindowEventManager::BeforeMaskChanged(XID xid) {
+ old_mask_ = mask_map_[xid].ToMask();
Daniel Erat 2016/09/07 00:37:33 caching this in a single member feels a bit scary.
Tom (Use chromium acct) 2016/09/07 18:02:22 Done.
+}
+
+void XWindowEventManager::AfterMaskChanged(XID xid) {
+ uint32_t new_mask = mask_map_[xid].ToMask();
+ if (new_mask == old_mask_)
+ return;
+
+ XDisplay* display = gfx::GetXDisplay();
+ xcb_connection_t* connection = XGetXCBConnection(display);
+ auto cookie = xcb_change_window_attributes(connection, xid, XCB_CW_EVENT_MASK,
+ &new_mask);
+ // Window |xid| may already be destroyed at this point, so the
+ // change_attributes request may give a BadWindow error. In this case, just
+ // ignore the error.
+ xcb_discard_reply(connection, cookie.sequence);
+
+ if (new_mask == NoEventMask)
+ mask_map_.erase(xid);
+}
+
+XWindowEventManager::ScopedEventSelector::ScopedEventSelector(
+ XID xid,
+ uint32_t event_mask)
+ : xid_(xid), event_mask_(event_mask) {
+ XWindowEventManager::GetInstance()->SelectEvents(xid_, event_mask_);
+}
+
+XWindowEventManager::ScopedEventSelector::~ScopedEventSelector() {
+ XWindowEventManager::GetInstance()->DeselectEvents(xid_, event_mask_);
+}
+
+XWindowEventManager::MultiMask::MultiMask() {
+ for (int i = 0; i < kMaskSize; i++)
+ mask_bits[i] = 0;
+}
+
+XWindowEventManager::MultiMask::~MultiMask() {}
+
+void XWindowEventManager::MultiMask::AddMask(uint32_t mask) {
+ for (int i = 0; i < kMaskSize; i++) {
+ if (mask & (1 << i))
+ mask_bits[i]++;
+ }
+}
+
+void XWindowEventManager::MultiMask::RemoveMask(uint32_t mask) {
+ for (int i = 0; i < kMaskSize; i++) {
+ if (mask & (1 << i))
+ DCHECK(mask_bits[i]);
+ mask_bits[i]--;
+ }
+}
+
+uint32_t XWindowEventManager::MultiMask::ToMask() const {
+ uint32_t mask = NoEventMask;
+ for (int i = 0; i < kMaskSize; i++) {
+ if (mask_bits[i])
+ mask |= (1 << i);
+ }
+ return mask;
+}
+
+} // namespace ui

Powered by Google App Engine
This is Rietveld 408576698