 Chromium Code Reviews
 Chromium Code Reviews Issue 1712103002:
  ozone/platform/wayland: Implement pointer handling  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@master
    
  
    Issue 1712103002:
  ozone/platform/wayland: Implement pointer handling  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@master| OLD | NEW | 
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include "ui/ozone/platform/wayland/wayland_display.h" | 5 #include "ui/ozone/platform/wayland/wayland_display.h" | 
| 6 | 6 | 
| 7 #include <xdg-shell-unstable-v5-client-protocol.h> | 7 #include <xdg-shell-unstable-v5-client-protocol.h> | 
| 8 | 8 | 
| 9 #include "base/bind.h" | |
| 9 #include "base/logging.h" | 10 #include "base/logging.h" | 
| 10 #include "base/message_loop/message_loop.h" | 11 #include "base/message_loop/message_loop.h" | 
| 11 #include "ui/ozone/platform/wayland/wayland_object.h" | 12 #include "ui/ozone/platform/wayland/wayland_object.h" | 
| 12 #include "ui/ozone/platform/wayland/wayland_window.h" | 13 #include "ui/ozone/platform/wayland/wayland_window.h" | 
| 13 | 14 | 
| 14 static_assert(XDG_SHELL_VERSION_CURRENT == 5, "Unsupported xdg-shell version"); | 15 static_assert(XDG_SHELL_VERSION_CURRENT == 5, "Unsupported xdg-shell version"); | 
| 15 | 16 | 
| 16 namespace ui { | 17 namespace ui { | 
| 17 namespace { | 18 namespace { | 
| 18 const uint32_t kMaxCompositorVersion = 4; | 19 const uint32_t kMaxCompositorVersion = 4; | 
| 20 const uint32_t kMaxSeatVersion = 4; | |
| 19 const uint32_t kMaxShmVersion = 1; | 21 const uint32_t kMaxShmVersion = 1; | 
| 20 const uint32_t kMaxXdgShellVersion = 1; | 22 const uint32_t kMaxXdgShellVersion = 1; | 
| 21 } // namespace | 23 } // namespace | 
| 22 | 24 | 
| 23 WaylandDisplay::WaylandDisplay() {} | 25 WaylandDisplay::WaylandDisplay() {} | 
| 24 | 26 | 
| 25 WaylandDisplay::~WaylandDisplay() {} | 27 WaylandDisplay::~WaylandDisplay() {} | 
| 26 | 28 | 
| 27 bool WaylandDisplay::Initialize() { | 29 bool WaylandDisplay::Initialize() { | 
| 28 static const wl_registry_listener registry_listener = { | 30 static const wl_registry_listener registry_listener = { | 
| (...skipping 16 matching lines...) Expand all Loading... | |
| 45 wl_display_roundtrip(display_.get()); | 47 wl_display_roundtrip(display_.get()); | 
| 46 | 48 | 
| 47 if (!compositor_) { | 49 if (!compositor_) { | 
| 48 LOG(ERROR) << "No wl_compositor object"; | 50 LOG(ERROR) << "No wl_compositor object"; | 
| 49 return false; | 51 return false; | 
| 50 } | 52 } | 
| 51 if (!shm_) { | 53 if (!shm_) { | 
| 52 LOG(ERROR) << "No wl_shm object"; | 54 LOG(ERROR) << "No wl_shm object"; | 
| 53 return false; | 55 return false; | 
| 54 } | 56 } | 
| 57 if (!seat_) { | |
| 58 LOG(ERROR) << "No wl_seat object"; | |
| 59 return false; | |
| 60 } | |
| 55 if (!shell_) { | 61 if (!shell_) { | 
| 56 LOG(ERROR) << "No xdg_shell object"; | 62 LOG(ERROR) << "No xdg_shell object"; | 
| 57 return false; | 63 return false; | 
| 58 } | 64 } | 
| 59 | 65 | 
| 60 return true; | 66 return true; | 
| 61 } | 67 } | 
| 62 | 68 | 
| 63 void WaylandDisplay::Flush() { | 69 void WaylandDisplay::Flush() { | 
| 64 DCHECK(display_); | 70 DCHECK(display_); | 
| 65 wl_display_flush(display_.get()); | 71 wl_display_flush(display_.get()); | 
| 66 } | 72 } | 
| 67 | 73 | 
| 68 WaylandWindow* WaylandDisplay::GetWindow(gfx::AcceleratedWidget widget) { | 74 WaylandWindow* WaylandDisplay::GetWindow(gfx::AcceleratedWidget widget) { | 
| 69 auto it = window_map_.find(widget); | 75 auto it = window_map_.find(widget); | 
| 70 return it == window_map_.end() ? nullptr : it->second; | 76 return it == window_map_.end() ? nullptr : it->second; | 
| 71 } | 77 } | 
| 72 | 78 | 
| 73 void WaylandDisplay::AddWindow(WaylandWindow* window) { | 79 void WaylandDisplay::AddWindow(WaylandWindow* window) { | 
| 74 window_map_[window->GetWidget()] = window; | 80 window_map_[window->GetWidget()] = window; | 
| 75 } | 81 } | 
| 76 | 82 | 
| 77 void WaylandDisplay::RemoveWindow(WaylandWindow* window) { | 83 void WaylandDisplay::RemoveWindow(WaylandWindow* window) { | 
| 78 window_map_.erase(window->GetWidget()); | 84 window_map_.erase(window->GetWidget()); | 
| 79 } | 85 } | 
| 80 | 86 | 
| 81 void WaylandDisplay::OnDispatcherListChanged() { | 87 void WaylandDisplay::OnDispatcherListChanged() { | 
| 82 if (watching_) | 88 if (watching_ || !base::MessageLoopForUI::IsCurrent()) | 
| 83 return; | 89 return; | 
| 84 | 90 | 
| 85 DCHECK(display_); | 91 DCHECK(display_); | 
| 86 DCHECK(base::MessageLoopForUI::IsCurrent()); | |
| 
spang
2016/02/26 01:41:11
I hope this cannot get called off the UI thread..
 
Michael Forney
2016/02/26 01:47:34
I changed it to a conditional because this gets ca
 
spang
2016/02/26 03:51:45
Sure, create a UI message loop from the test befor
 
Michael Forney
2016/02/27 00:01:37
Cool. Looks like just creating a MessageLoopForUI
 | |
| 87 base::MessageLoopForUI::current()->WatchFileDescriptor( | 92 base::MessageLoopForUI::current()->WatchFileDescriptor( | 
| 88 wl_display_get_fd(display_.get()), true, | 93 wl_display_get_fd(display_.get()), true, | 
| 89 base::MessagePumpLibevent::WATCH_READ, &controller_, this); | 94 base::MessagePumpLibevent::WATCH_READ, &controller_, this); | 
| 90 watching_ = true; | 95 watching_ = true; | 
| 91 } | 96 } | 
| 92 | 97 | 
| 98 void WaylandDisplay::DispatchUiEvent(Event* event) { | |
| 99 PlatformEventSource::DispatchEvent(event); | |
| 100 } | |
| 101 | |
| 93 void WaylandDisplay::OnFileCanReadWithoutBlocking(int fd) { | 102 void WaylandDisplay::OnFileCanReadWithoutBlocking(int fd) { | 
| 94 wl_display_dispatch(display_.get()); | 103 wl_display_dispatch(display_.get()); | 
| 95 for (const auto& window : window_map_) | 104 for (const auto& window : window_map_) | 
| 96 window.second->ApplyPendingBounds(); | 105 window.second->ApplyPendingBounds(); | 
| 97 } | 106 } | 
| 98 | 107 | 
| 99 void WaylandDisplay::OnFileCanWriteWithoutBlocking(int fd) {} | 108 void WaylandDisplay::OnFileCanWriteWithoutBlocking(int fd) {} | 
| 100 | 109 | 
| 101 // static | 110 // static | 
| 102 void WaylandDisplay::Global(void* data, | 111 void WaylandDisplay::Global(void* data, | 
| 103 wl_registry* registry, | 112 wl_registry* registry, | 
| 104 uint32_t name, | 113 uint32_t name, | 
| 105 const char* interface, | 114 const char* interface, | 
| 106 uint32_t version) { | 115 uint32_t version) { | 
| 116 static const wl_seat_listener seat_listener = { | |
| 117 &WaylandDisplay::Capabilities, &WaylandDisplay::Name, | |
| 118 }; | |
| 107 static const xdg_shell_listener shell_listener = { | 119 static const xdg_shell_listener shell_listener = { | 
| 108 &WaylandDisplay::Ping, | 120 &WaylandDisplay::Ping, | 
| 109 }; | 121 }; | 
| 110 | 122 | 
| 111 WaylandDisplay* display = static_cast<WaylandDisplay*>(data); | 123 WaylandDisplay* display = static_cast<WaylandDisplay*>(data); | 
| 112 if (!display->compositor_ && strcmp(interface, "wl_compositor") == 0) { | 124 if (!display->compositor_ && strcmp(interface, "wl_compositor") == 0) { | 
| 113 display->compositor_ = wl::Bind<wl_compositor>( | 125 display->compositor_ = wl::Bind<wl_compositor>( | 
| 114 registry, name, std::min(version, kMaxCompositorVersion)); | 126 registry, name, std::min(version, kMaxCompositorVersion)); | 
| 115 if (!display->compositor_) | 127 if (!display->compositor_) | 
| 116 LOG(ERROR) << "Failed to bind to wl_compositor global"; | 128 LOG(ERROR) << "Failed to bind to wl_compositor global"; | 
| 117 } else if (!display->shm_ && strcmp(interface, "wl_shm") == 0) { | 129 } else if (!display->shm_ && strcmp(interface, "wl_shm") == 0) { | 
| 118 display->shm_ = | 130 display->shm_ = | 
| 119 wl::Bind<wl_shm>(registry, name, std::min(version, kMaxShmVersion)); | 131 wl::Bind<wl_shm>(registry, name, std::min(version, kMaxShmVersion)); | 
| 120 if (!display->shm_) | 132 if (!display->shm_) | 
| 121 LOG(ERROR) << "Failed to bind to wl_shm global"; | 133 LOG(ERROR) << "Failed to bind to wl_shm global"; | 
| 134 } else if (!display->seat_ && strcmp(interface, "wl_seat") == 0) { | |
| 135 display->seat_ = | |
| 136 wl::Bind<wl_seat>(registry, name, std::min(version, kMaxSeatVersion)); | |
| 137 if (!display->seat_) { | |
| 138 LOG(ERROR) << "Failed to bind to wl_seat global"; | |
| 139 return; | |
| 140 } | |
| 141 wl_seat_add_listener(display->seat_.get(), &seat_listener, display); | |
| 122 } else if (!display->shell_ && strcmp(interface, "xdg_shell") == 0) { | 142 } else if (!display->shell_ && strcmp(interface, "xdg_shell") == 0) { | 
| 123 display->shell_ = wl::Bind<xdg_shell>( | 143 display->shell_ = wl::Bind<xdg_shell>( | 
| 124 registry, name, std::min(version, kMaxXdgShellVersion)); | 144 registry, name, std::min(version, kMaxXdgShellVersion)); | 
| 125 if (!display->shell_) { | 145 if (!display->shell_) { | 
| 126 LOG(ERROR) << "Failed to bind to xdg_shell global"; | 146 LOG(ERROR) << "Failed to bind to xdg_shell global"; | 
| 127 return; | 147 return; | 
| 128 } | 148 } | 
| 129 xdg_shell_add_listener(display->shell_.get(), &shell_listener, display); | 149 xdg_shell_add_listener(display->shell_.get(), &shell_listener, display); | 
| 130 xdg_shell_use_unstable_version(display->shell_.get(), | 150 xdg_shell_use_unstable_version(display->shell_.get(), | 
| 131 XDG_SHELL_VERSION_CURRENT); | 151 XDG_SHELL_VERSION_CURRENT); | 
| 132 } | 152 } | 
| 133 } | 153 } | 
| 134 | 154 | 
| 135 // static | 155 // static | 
| 136 void WaylandDisplay::GlobalRemove(void* data, | 156 void WaylandDisplay::GlobalRemove(void* data, | 
| 137 wl_registry* registry, | 157 wl_registry* registry, | 
| 138 uint32_t name) { | 158 uint32_t name) { | 
| 139 NOTIMPLEMENTED(); | 159 NOTIMPLEMENTED(); | 
| 140 } | 160 } | 
| 141 | 161 | 
| 142 // static | 162 // static | 
| 163 void WaylandDisplay::Capabilities(void* data, | |
| 164 wl_seat* seat, | |
| 165 uint32_t capabilities) { | |
| 166 WaylandDisplay* display = static_cast<WaylandDisplay*>(data); | |
| 167 if (capabilities & WL_SEAT_CAPABILITY_POINTER) { | |
| 168 if (!display->pointer_) { | |
| 169 wl_pointer* pointer = wl_seat_get_pointer(display->seat_.get()); | |
| 170 if (!pointer) { | |
| 171 LOG(ERROR) << "Failed to get wl_pointer from seat"; | |
| 172 return; | |
| 173 } | |
| 174 display->pointer_ = make_scoped_ptr(new WaylandPointer( | |
| 175 pointer, base::Bind(&WaylandDisplay::DispatchUiEvent, | |
| 176 base::Unretained(display)))); | |
| 177 } | |
| 178 } else if (display->pointer_) { | |
| 179 display->pointer_.reset(); | |
| 
spang
2016/02/26 01:41:11
How could the capability get revoked?
 
Michael Forney
2016/02/26 01:47:34
The user unplugs their mouse, and seat no longer h
 | |
| 180 } | |
| 181 } | |
| 182 | |
| 183 // static | |
| 184 void WaylandDisplay::Name(void* data, wl_seat* seat, const char* name) {} | |
| 185 | |
| 186 // static | |
| 143 void WaylandDisplay::Ping(void* data, xdg_shell* shell, uint32_t serial) { | 187 void WaylandDisplay::Ping(void* data, xdg_shell* shell, uint32_t serial) { | 
| 144 xdg_shell_pong(shell, serial); | 188 xdg_shell_pong(shell, serial); | 
| 145 } | 189 } | 
| 146 | 190 | 
| 147 } // namespace ui | 191 } // namespace ui | 
| OLD | NEW |