| // Copyright 2019 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/platform_window/x11/x11_window_manager.h" |
| |
| #include "base/stl_util.h" |
| #include "ui/platform_window/x11/x11_window.h" |
| |
| namespace ui { |
| |
| namespace { |
| |
| X11WindowManager* g_instance = nullptr; |
| |
| } // namespace |
| |
| X11WindowManager::X11WindowManager() { |
| DCHECK(!g_instance) << "There should only be a single X11WindowManager"; |
| g_instance = this; |
| } |
| |
| X11WindowManager::~X11WindowManager() = default; |
| |
| // static |
| X11WindowManager* X11WindowManager::GetInstance() { |
| if (!g_instance) { |
| auto manager = std::make_unique<X11WindowManager>(); |
| X11WindowManager* manager_ptr = manager.release(); |
| DCHECK_EQ(g_instance, manager_ptr); |
| } |
| return g_instance; |
| } |
| |
| void X11WindowManager::GrabEvents(X11Window* window) { |
| DCHECK_NE(located_events_grabber_, window); |
| |
| // Grabbing the mouse is asynchronous. However, we synchronously start |
| // forwarding all mouse events received by Chrome to the |
| // aura::WindowEventDispatcher which has capture. This makes capture |
| // synchronous for all intents and purposes if either: |
| // - |located_events_grabber_| is set to have capture. |
| // OR |
| // - The topmost window underneath the mouse is managed by Chrome. |
| auto* old_grabber = located_events_grabber_; |
| |
| // Update |located_events_grabber_| prior to calling OnXWindowLostCapture() to |
| // avoid releasing pointer grab. |
| located_events_grabber_ = window; |
| if (old_grabber) |
| old_grabber->OnXWindowLostCapture(); |
| |
| // the X11Window calls GrabPointer by itself. |
| } |
| |
| void X11WindowManager::UngrabEvents(X11Window* window) { |
| DCHECK_EQ(located_events_grabber_, window); |
| // Release mouse grab asynchronously. A window managed by Chrome is likely |
| // the topmost window underneath the mouse so the capture release being |
| // asynchronous is likely inconsequential. |
| auto* old_grabber = located_events_grabber_; |
| located_events_grabber_ = nullptr; |
| old_grabber->OnXWindowLostCapture(); |
| } |
| |
| void X11WindowManager::AddWindow(X11Window* window) { |
| DCHECK(window); |
| auto widget = window->GetWidget(); |
| DCHECK_NE(gfx::kNullAcceleratedWidget, widget); |
| DCHECK(!base::Contains(windows_, widget)); |
| windows_.emplace(widget, window); |
| } |
| |
| void X11WindowManager::RemoveWindow(X11Window* window) { |
| DCHECK(window); |
| auto widget = window->GetWidget(); |
| auto it = windows_.find(widget); |
| // The XWindow might not have been initialized due to some errors. |
| if (widget == gfx::kNullAcceleratedWidget) { |
| DCHECK(it == windows_.end()); |
| } else { |
| DCHECK(it != windows_.end()); |
| if (window_mouse_currently_on_ == it->second) |
| window_mouse_currently_on_ = nullptr; |
| windows_.erase(it); |
| } |
| } |
| |
| X11Window* X11WindowManager::GetWindow(gfx::AcceleratedWidget widget) const { |
| DCHECK_NE(gfx::kNullAcceleratedWidget, widget); |
| auto it = windows_.find(widget); |
| return it != windows_.end() ? it->second : nullptr; |
| } |
| |
| void X11WindowManager::MouseOnWindow(X11Window* window) { |
| if (window_mouse_currently_on_ == window) |
| return; |
| |
| window_mouse_currently_on_ = window; |
| window->OnMouseEnter(); |
| } |
| |
| std::vector<X11Window*> X11WindowManager::GetAllOpenWindows() const { |
| std::vector<X11Window*> all_windows; |
| for (const auto& item : windows_) |
| all_windows.push_back(item.second); |
| return all_windows; |
| } |
| |
| } // namespace ui |