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

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

Issue 2313033002: Refactor X11ForeignWindowManager (Reland) (Closed)
Patch Set: Rebase 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..4fc0c559772acd478825f3890bb65ffefa05f3c1
--- /dev/null
+++ b/ui/base/x/x11_window_event_manager.cc
@@ -0,0 +1,111 @@
+// 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 {
+
+XScopedEventSelector::XScopedEventSelector(XID xid, uint32_t event_mask)
+ : xid_(xid), event_mask_(event_mask) {
+ XWindowEventManager::GetInstance()->SelectEvents(xid_, event_mask_);
+}
+
+XScopedEventSelector::~XScopedEventSelector() {
+ XWindowEventManager::GetInstance()->DeselectEvents(xid_, event_mask_);
+}
+
+// static
+XWindowEventManager* XWindowEventManager::GetInstance() {
+ return base::Singleton<XWindowEventManager>::get();
+}
+
+class XWindowEventManager::MultiMask {
+ public:
+ MultiMask() {
+ for (int i = 0; i < kMaskSize; i++)
+ mask_bits_[i] = 0;
+ }
+
+ ~MultiMask() {}
+
+ void AddMask(uint32_t mask) {
+ for (int i = 0; i < kMaskSize; i++) {
+ if (mask & (1 << i))
+ mask_bits_[i]++;
+ }
+ }
+
+ void RemoveMask(uint32_t mask) {
+ for (int i = 0; i < kMaskSize; i++) {
+ if (mask & (1 << i)) {
+ DCHECK(mask_bits_[i]);
+ mask_bits_[i]--;
+ }
+ }
+ }
+
+ uint32_t ToMask() const {
+ uint32_t mask = NoEventMask;
+ for (int i = 0; i < kMaskSize; i++) {
+ if (mask_bits_[i])
+ mask |= (1 << i);
+ }
+ return mask;
+ }
+
+ private:
+ static constexpr auto kMaskSize = 25;
+
+ int mask_bits_[kMaskSize];
+
+ DISALLOW_COPY_AND_ASSIGN(MultiMask);
+};
+
+XWindowEventManager::XWindowEventManager() {}
+XWindowEventManager::~XWindowEventManager() {}
+
+void XWindowEventManager::SelectEvents(XID xid, uint32_t event_mask) {
+ std::unique_ptr<MultiMask>& mask = mask_map_[xid];
+ if (!mask)
+ mask.reset(new MultiMask());
+ uint32_t old_mask = mask_map_[xid]->ToMask();
+ mask->AddMask(event_mask);
+ AfterMaskChanged(xid, old_mask);
+}
+
+void XWindowEventManager::DeselectEvents(XID xid, uint32_t event_mask) {
+ DCHECK(mask_map_.find(xid) != mask_map_.end());
+ std::unique_ptr<MultiMask>& mask = mask_map_[xid];
+ uint32_t old_mask = mask->ToMask();
+ mask->RemoveMask(event_mask);
+ AfterMaskChanged(xid, old_mask);
+}
+
+void XWindowEventManager::AfterMaskChanged(XID xid, uint32_t old_mask) {
+ 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);
+}
+
+} // namespace ui
« no previous file with comments | « ui/base/x/x11_window_event_manager.h ('k') | ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698