| OLD | NEW |
| (Empty) |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "components/mus/public/cpp/window_tree_client.h" | |
| 6 | |
| 7 #include <stddef.h> | |
| 8 | |
| 9 #include <string> | |
| 10 #include <utility> | |
| 11 #include <vector> | |
| 12 | |
| 13 #include "base/bind.h" | |
| 14 #include "base/memory/ptr_util.h" | |
| 15 #include "components/mus/common/util.h" | |
| 16 #include "components/mus/public/cpp/input_event_handler.h" | |
| 17 #include "components/mus/public/cpp/lib/in_flight_change.h" | |
| 18 #include "components/mus/public/cpp/lib/window_private.h" | |
| 19 #include "components/mus/public/cpp/window_manager_delegate.h" | |
| 20 #include "components/mus/public/cpp/window_observer.h" | |
| 21 #include "components/mus/public/cpp/window_tracker.h" | |
| 22 #include "components/mus/public/cpp/window_tree_client_delegate.h" | |
| 23 #include "components/mus/public/cpp/window_tree_client_observer.h" | |
| 24 #include "components/mus/public/interfaces/window_manager_window_tree_factory.mo
jom.h" | |
| 25 #include "services/shell/public/cpp/connector.h" | |
| 26 #include "ui/display/mojo/display_type_converters.h" | |
| 27 #include "ui/events/event.h" | |
| 28 #include "ui/gfx/geometry/insets.h" | |
| 29 #include "ui/gfx/geometry/size.h" | |
| 30 | |
| 31 namespace mus { | |
| 32 | |
| 33 void DeleteWindowTreeClient(WindowTreeClient* client) { delete client; } | |
| 34 | |
| 35 Id MakeTransportId(ClientSpecificId client_id, ClientSpecificId local_id) { | |
| 36 return (client_id << 16) | local_id; | |
| 37 } | |
| 38 | |
| 39 Id server_id(Window* window) { | |
| 40 return WindowPrivate(window).server_id(); | |
| 41 } | |
| 42 | |
| 43 // Helper called to construct a local window object from transport data. | |
| 44 Window* AddWindowToClient(WindowTreeClient* client, | |
| 45 Window* parent, | |
| 46 const mojom::WindowDataPtr& window_data) { | |
| 47 // We don't use the ctor that takes a WindowTreeClient here, since it will | |
| 48 // call back to the service and attempt to create a new window. | |
| 49 Window* window = WindowPrivate::LocalCreate(); | |
| 50 WindowPrivate private_window(window); | |
| 51 private_window.set_client(client); | |
| 52 private_window.set_server_id(window_data->window_id); | |
| 53 private_window.set_visible(window_data->visible); | |
| 54 private_window.set_properties( | |
| 55 window_data->properties | |
| 56 .To<std::map<std::string, std::vector<uint8_t>>>()); | |
| 57 client->AddWindow(window); | |
| 58 private_window.LocalSetBounds(gfx::Rect(), window_data->bounds); | |
| 59 if (parent) | |
| 60 WindowPrivate(parent).LocalAddChild(window); | |
| 61 return window; | |
| 62 } | |
| 63 | |
| 64 Window* BuildWindowTree(WindowTreeClient* client, | |
| 65 const mojo::Array<mojom::WindowDataPtr>& windows, | |
| 66 Window* initial_parent) { | |
| 67 std::vector<Window*> parents; | |
| 68 Window* root = NULL; | |
| 69 Window* last_window = NULL; | |
| 70 if (initial_parent) | |
| 71 parents.push_back(initial_parent); | |
| 72 for (size_t i = 0; i < windows.size(); ++i) { | |
| 73 if (last_window && windows[i]->parent_id == server_id(last_window)) { | |
| 74 parents.push_back(last_window); | |
| 75 } else if (!parents.empty()) { | |
| 76 while (server_id(parents.back()) != windows[i]->parent_id) | |
| 77 parents.pop_back(); | |
| 78 } | |
| 79 Window* window = AddWindowToClient( | |
| 80 client, !parents.empty() ? parents.back() : NULL, windows[i]); | |
| 81 if (!last_window) | |
| 82 root = window; | |
| 83 last_window = window; | |
| 84 } | |
| 85 return root; | |
| 86 } | |
| 87 | |
| 88 WindowTreeClient::WindowTreeClient( | |
| 89 WindowTreeClientDelegate* delegate, | |
| 90 WindowManagerDelegate* window_manager_delegate, | |
| 91 mojo::InterfaceRequest<mojom::WindowTreeClient> request) | |
| 92 : client_id_(0), | |
| 93 next_window_id_(1), | |
| 94 next_change_id_(1), | |
| 95 delegate_(delegate), | |
| 96 window_manager_delegate_(window_manager_delegate), | |
| 97 capture_window_(nullptr), | |
| 98 focused_window_(nullptr), | |
| 99 binding_(this), | |
| 100 tree_(nullptr), | |
| 101 delete_on_no_roots_(!window_manager_delegate), | |
| 102 in_destructor_(false), | |
| 103 weak_factory_(this) { | |
| 104 // Allow for a null request in tests. | |
| 105 if (request.is_pending()) | |
| 106 binding_.Bind(std::move(request)); | |
| 107 if (window_manager_delegate) | |
| 108 window_manager_delegate->SetWindowManagerClient(this); | |
| 109 } | |
| 110 | |
| 111 WindowTreeClient::~WindowTreeClient() { | |
| 112 in_destructor_ = true; | |
| 113 | |
| 114 FOR_EACH_OBSERVER(WindowTreeClientObserver, observers_, | |
| 115 OnWillDestroyClient(this)); | |
| 116 | |
| 117 std::vector<Window*> non_owned; | |
| 118 WindowTracker tracker; | |
| 119 while (!windows_.empty()) { | |
| 120 IdToWindowMap::iterator it = windows_.begin(); | |
| 121 if (OwnsWindow(it->second)) { | |
| 122 it->second->Destroy(); | |
| 123 } else { | |
| 124 tracker.Add(it->second); | |
| 125 windows_.erase(it); | |
| 126 } | |
| 127 } | |
| 128 | |
| 129 // Delete the non-owned windows last. In the typical case these are roots. The | |
| 130 // exception is the window manager and embed roots, which may know about | |
| 131 // other random windows that it doesn't own. | |
| 132 // NOTE: we manually delete as we're a friend. | |
| 133 while (!tracker.windows().empty()) | |
| 134 delete tracker.windows().front(); | |
| 135 | |
| 136 FOR_EACH_OBSERVER(WindowTreeClientObserver, observers_, | |
| 137 OnDidDestroyClient(this)); | |
| 138 | |
| 139 delegate_->OnDidDestroyClient(this); | |
| 140 } | |
| 141 | |
| 142 void WindowTreeClient::ConnectViaWindowTreeFactory( | |
| 143 shell::Connector* connector) { | |
| 144 // Clients created with no root shouldn't delete automatically. | |
| 145 delete_on_no_roots_ = false; | |
| 146 | |
| 147 // The client id doesn't really matter, we use 101 purely for debugging. | |
| 148 client_id_ = 101; | |
| 149 | |
| 150 mojom::WindowTreeFactoryPtr factory; | |
| 151 connector->ConnectToInterface("mojo:mus", &factory); | |
| 152 mojom::WindowTreePtr window_tree; | |
| 153 factory->CreateWindowTree(GetProxy(&window_tree), | |
| 154 binding_.CreateInterfacePtrAndBind()); | |
| 155 SetWindowTree(std::move(window_tree)); | |
| 156 } | |
| 157 | |
| 158 void WindowTreeClient::ConnectAsWindowManager(shell::Connector* connector) { | |
| 159 DCHECK(window_manager_delegate_); | |
| 160 | |
| 161 mojom::WindowManagerWindowTreeFactoryPtr factory; | |
| 162 connector->ConnectToInterface("mojo:mus", &factory); | |
| 163 mojom::WindowTreePtr window_tree; | |
| 164 factory->CreateWindowTree(GetProxy(&window_tree), | |
| 165 binding_.CreateInterfacePtrAndBind()); | |
| 166 SetWindowTree(std::move(window_tree)); | |
| 167 } | |
| 168 | |
| 169 void WindowTreeClient::WaitForEmbed() { | |
| 170 DCHECK(roots_.empty()); | |
| 171 // OnEmbed() is the first function called. | |
| 172 binding_.WaitForIncomingMethodCall(); | |
| 173 // TODO(sky): deal with pipe being closed before we get OnEmbed(). | |
| 174 } | |
| 175 | |
| 176 void WindowTreeClient::DestroyWindow(Window* window) { | |
| 177 DCHECK(tree_); | |
| 178 const uint32_t change_id = ScheduleInFlightChange(base::WrapUnique( | |
| 179 new CrashInFlightChange(window, ChangeType::DELETE_WINDOW))); | |
| 180 tree_->DeleteWindow(change_id, server_id(window)); | |
| 181 } | |
| 182 | |
| 183 void WindowTreeClient::AddChild(Window* parent, Id child_id) { | |
| 184 DCHECK(tree_); | |
| 185 const uint32_t change_id = ScheduleInFlightChange( | |
| 186 base::WrapUnique(new CrashInFlightChange(parent, ChangeType::ADD_CHILD))); | |
| 187 tree_->AddWindow(change_id, parent->server_id(), child_id); | |
| 188 } | |
| 189 | |
| 190 void WindowTreeClient::RemoveChild(Window* parent, Id child_id) { | |
| 191 DCHECK(tree_); | |
| 192 const uint32_t change_id = ScheduleInFlightChange(base::WrapUnique( | |
| 193 new CrashInFlightChange(parent, ChangeType::REMOVE_CHILD))); | |
| 194 tree_->RemoveWindowFromParent(change_id, child_id); | |
| 195 } | |
| 196 | |
| 197 void WindowTreeClient::AddTransientWindow(Window* window, | |
| 198 Id transient_window_id) { | |
| 199 DCHECK(tree_); | |
| 200 const uint32_t change_id = ScheduleInFlightChange(base::WrapUnique( | |
| 201 new CrashInFlightChange(window, ChangeType::ADD_TRANSIENT_WINDOW))); | |
| 202 tree_->AddTransientWindow(change_id, server_id(window), transient_window_id); | |
| 203 } | |
| 204 | |
| 205 void WindowTreeClient::RemoveTransientWindowFromParent(Window* window) { | |
| 206 DCHECK(tree_); | |
| 207 const uint32_t change_id = | |
| 208 ScheduleInFlightChange(base::WrapUnique(new CrashInFlightChange( | |
| 209 window, ChangeType::REMOVE_TRANSIENT_WINDOW_FROM_PARENT))); | |
| 210 tree_->RemoveTransientWindowFromParent(change_id, server_id(window)); | |
| 211 } | |
| 212 | |
| 213 void WindowTreeClient::SetModal(Window* window) { | |
| 214 DCHECK(tree_); | |
| 215 const uint32_t change_id = ScheduleInFlightChange( | |
| 216 base::WrapUnique(new InFlightSetModalChange(window))); | |
| 217 tree_->SetModal(change_id, server_id(window)); | |
| 218 } | |
| 219 | |
| 220 void WindowTreeClient::Reorder(Window* window, | |
| 221 Id relative_window_id, | |
| 222 mojom::OrderDirection direction) { | |
| 223 DCHECK(tree_); | |
| 224 const uint32_t change_id = ScheduleInFlightChange( | |
| 225 base::WrapUnique(new CrashInFlightChange(window, ChangeType::REORDER))); | |
| 226 tree_->ReorderWindow(change_id, server_id(window), relative_window_id, | |
| 227 direction); | |
| 228 } | |
| 229 | |
| 230 bool WindowTreeClient::OwnsWindow(Window* window) const { | |
| 231 // Windows created via CreateTopLevelWindow() are not owned by us, but have | |
| 232 // our client id. | |
| 233 return HiWord(server_id(window)) == client_id_ && | |
| 234 roots_.count(window) == 0; | |
| 235 } | |
| 236 | |
| 237 void WindowTreeClient::SetBounds(Window* window, | |
| 238 const gfx::Rect& old_bounds, | |
| 239 const gfx::Rect& bounds) { | |
| 240 DCHECK(tree_); | |
| 241 const uint32_t change_id = ScheduleInFlightChange( | |
| 242 base::WrapUnique(new InFlightBoundsChange(window, old_bounds))); | |
| 243 tree_->SetWindowBounds(change_id, server_id(window), bounds); | |
| 244 } | |
| 245 | |
| 246 void WindowTreeClient::SetCapture(Window* window) { | |
| 247 // In order for us to get here we had to have exposed a window, which implies | |
| 248 // we got a client. | |
| 249 DCHECK(tree_); | |
| 250 if (capture_window_ == window) | |
| 251 return; | |
| 252 const uint32_t change_id = ScheduleInFlightChange( | |
| 253 base::WrapUnique(new InFlightCaptureChange(this, capture_window_))); | |
| 254 tree_->SetCapture(change_id, server_id(window)); | |
| 255 LocalSetCapture(window); | |
| 256 } | |
| 257 | |
| 258 void WindowTreeClient::ReleaseCapture(Window* window) { | |
| 259 // In order for us to get here we had to have exposed a window, which implies | |
| 260 // we got a client. | |
| 261 DCHECK(tree_); | |
| 262 if (capture_window_ != window) | |
| 263 return; | |
| 264 const uint32_t change_id = ScheduleInFlightChange( | |
| 265 base::WrapUnique(new InFlightCaptureChange(this, window))); | |
| 266 tree_->ReleaseCapture(change_id, server_id(window)); | |
| 267 LocalSetCapture(nullptr); | |
| 268 } | |
| 269 | |
| 270 void WindowTreeClient::SetClientArea( | |
| 271 Id window_id, | |
| 272 const gfx::Insets& client_area, | |
| 273 const std::vector<gfx::Rect>& additional_client_areas) { | |
| 274 DCHECK(tree_); | |
| 275 tree_->SetClientArea(window_id, client_area, additional_client_areas); | |
| 276 } | |
| 277 | |
| 278 void WindowTreeClient::SetHitTestMask(Id window_id, const gfx::Rect& mask) { | |
| 279 DCHECK(tree_); | |
| 280 tree_->SetHitTestMask(window_id, mask); | |
| 281 } | |
| 282 | |
| 283 void WindowTreeClient::ClearHitTestMask(Id window_id) { | |
| 284 DCHECK(tree_); | |
| 285 tree_->SetHitTestMask(window_id, {}); | |
| 286 } | |
| 287 | |
| 288 void WindowTreeClient::SetFocus(Window* window) { | |
| 289 // In order for us to get here we had to have exposed a window, which implies | |
| 290 // we got a client. | |
| 291 DCHECK(tree_); | |
| 292 const uint32_t change_id = ScheduleInFlightChange( | |
| 293 base::WrapUnique(new InFlightFocusChange(this, focused_window_))); | |
| 294 tree_->SetFocus(change_id, window ? server_id(window) : 0); | |
| 295 LocalSetFocus(window); | |
| 296 } | |
| 297 | |
| 298 void WindowTreeClient::SetCanFocus(Id window_id, bool can_focus) { | |
| 299 DCHECK(tree_); | |
| 300 tree_->SetCanFocus(window_id, can_focus); | |
| 301 } | |
| 302 | |
| 303 void WindowTreeClient::SetPredefinedCursor(Id window_id, | |
| 304 mus::mojom::Cursor cursor_id) { | |
| 305 DCHECK(tree_); | |
| 306 | |
| 307 Window* window = GetWindowByServerId(window_id); | |
| 308 if (!window) | |
| 309 return; | |
| 310 | |
| 311 // We make an inflight change thing here. | |
| 312 const uint32_t change_id = ScheduleInFlightChange(base::WrapUnique( | |
| 313 new InFlightPredefinedCursorChange(window, window->predefined_cursor()))); | |
| 314 tree_->SetPredefinedCursor(change_id, window_id, cursor_id); | |
| 315 } | |
| 316 | |
| 317 void WindowTreeClient::SetVisible(Window* window, bool visible) { | |
| 318 DCHECK(tree_); | |
| 319 const uint32_t change_id = ScheduleInFlightChange( | |
| 320 base::WrapUnique(new InFlightVisibleChange(window, !visible))); | |
| 321 tree_->SetWindowVisibility(change_id, server_id(window), visible); | |
| 322 } | |
| 323 | |
| 324 void WindowTreeClient::SetOpacity(Window* window, float opacity) { | |
| 325 DCHECK(tree_); | |
| 326 const uint32_t change_id = ScheduleInFlightChange( | |
| 327 base::WrapUnique(new InFlightOpacityChange(window, window->opacity()))); | |
| 328 tree_->SetWindowOpacity(change_id, server_id(window), opacity); | |
| 329 } | |
| 330 | |
| 331 void WindowTreeClient::SetProperty(Window* window, | |
| 332 const std::string& name, | |
| 333 mojo::Array<uint8_t> data) { | |
| 334 DCHECK(tree_); | |
| 335 | |
| 336 mojo::Array<uint8_t> old_value(nullptr); | |
| 337 if (window->HasSharedProperty(name)) | |
| 338 old_value = mojo::Array<uint8_t>::From(window->properties_[name]); | |
| 339 | |
| 340 const uint32_t change_id = ScheduleInFlightChange( | |
| 341 base::WrapUnique(new InFlightPropertyChange(window, name, old_value))); | |
| 342 tree_->SetWindowProperty(change_id, server_id(window), mojo::String(name), | |
| 343 std::move(data)); | |
| 344 } | |
| 345 | |
| 346 void WindowTreeClient::SetWindowTextInputState( | |
| 347 Id window_id, | |
| 348 mojo::TextInputStatePtr state) { | |
| 349 DCHECK(tree_); | |
| 350 tree_->SetWindowTextInputState(window_id, std::move(state)); | |
| 351 } | |
| 352 | |
| 353 void WindowTreeClient::SetImeVisibility(Id window_id, | |
| 354 bool visible, | |
| 355 mojo::TextInputStatePtr state) { | |
| 356 DCHECK(tree_); | |
| 357 tree_->SetImeVisibility(window_id, visible, std::move(state)); | |
| 358 } | |
| 359 | |
| 360 void WindowTreeClient::Embed(Id window_id, | |
| 361 mojom::WindowTreeClientPtr client, | |
| 362 uint32_t flags, | |
| 363 const mojom::WindowTree::EmbedCallback& callback) { | |
| 364 DCHECK(tree_); | |
| 365 tree_->Embed(window_id, std::move(client), flags, callback); | |
| 366 } | |
| 367 | |
| 368 void WindowTreeClient::RequestClose(Window* window) { | |
| 369 if (window_manager_internal_client_) | |
| 370 window_manager_internal_client_->WmRequestClose(server_id(window)); | |
| 371 } | |
| 372 | |
| 373 void WindowTreeClient::AttachSurface( | |
| 374 Id window_id, | |
| 375 mojom::SurfaceType type, | |
| 376 mojo::InterfaceRequest<mojom::Surface> surface, | |
| 377 mojom::SurfaceClientPtr client) { | |
| 378 DCHECK(tree_); | |
| 379 tree_->AttachSurface(window_id, type, std::move(surface), std::move(client)); | |
| 380 } | |
| 381 | |
| 382 void WindowTreeClient::LocalSetCapture(Window* window) { | |
| 383 if (capture_window_ == window) | |
| 384 return; | |
| 385 Window* lost_capture = capture_window_; | |
| 386 capture_window_ = window; | |
| 387 if (lost_capture) { | |
| 388 FOR_EACH_OBSERVER(WindowObserver, *WindowPrivate(lost_capture).observers(), | |
| 389 OnWindowLostCapture(lost_capture)); | |
| 390 } | |
| 391 } | |
| 392 | |
| 393 void WindowTreeClient::LocalSetFocus(Window* focused) { | |
| 394 Window* blurred = focused_window_; | |
| 395 // Update |focused_window_| before calling any of the observers, so that the | |
| 396 // observers get the correct result from calling |Window::HasFocus()|, | |
| 397 // |WindowTreeClient::GetFocusedWindow()| etc. | |
| 398 focused_window_ = focused; | |
| 399 if (blurred) { | |
| 400 FOR_EACH_OBSERVER(WindowObserver, *WindowPrivate(blurred).observers(), | |
| 401 OnWindowFocusChanged(focused, blurred)); | |
| 402 } | |
| 403 if (focused) { | |
| 404 FOR_EACH_OBSERVER(WindowObserver, *WindowPrivate(focused).observers(), | |
| 405 OnWindowFocusChanged(focused, blurred)); | |
| 406 } | |
| 407 FOR_EACH_OBSERVER(WindowTreeClientObserver, observers_, | |
| 408 OnWindowTreeFocusChanged(focused, blurred)); | |
| 409 } | |
| 410 | |
| 411 void WindowTreeClient::AddWindow(Window* window) { | |
| 412 DCHECK(windows_.find(server_id(window)) == windows_.end()); | |
| 413 windows_[server_id(window)] = window; | |
| 414 } | |
| 415 | |
| 416 void WindowTreeClient::OnWindowDestroying(Window* window) { | |
| 417 if (window == capture_window_) { | |
| 418 // Normally the queue updates itself upon window destruction. However since | |
| 419 // |window| is being destroyed, it will not be possible to notify its | |
| 420 // observers of the lost capture. Update local state now. | |
| 421 LocalSetCapture(nullptr); | |
| 422 } | |
| 423 // For |focused_window_| window destruction clears the entire focus state. | |
| 424 } | |
| 425 | |
| 426 void WindowTreeClient::OnWindowDestroyed(Window* window) { | |
| 427 windows_.erase(server_id(window)); | |
| 428 | |
| 429 for (auto& entry : embedded_windows_) { | |
| 430 auto it = entry.second.find(window); | |
| 431 if (it != entry.second.end()) { | |
| 432 entry.second.erase(it); | |
| 433 break; | |
| 434 } | |
| 435 } | |
| 436 | |
| 437 // Remove any InFlightChanges associated with the window. | |
| 438 std::set<uint32_t> in_flight_change_ids_to_remove; | |
| 439 for (const auto& pair : in_flight_map_) { | |
| 440 if (pair.second->window() == window) | |
| 441 in_flight_change_ids_to_remove.insert(pair.first); | |
| 442 } | |
| 443 for (auto change_id : in_flight_change_ids_to_remove) | |
| 444 in_flight_map_.erase(change_id); | |
| 445 | |
| 446 if (roots_.erase(window) > 0 && roots_.empty() && delete_on_no_roots_ && | |
| 447 !in_destructor_) { | |
| 448 delete this; | |
| 449 } | |
| 450 } | |
| 451 | |
| 452 Window* WindowTreeClient::GetWindowByServerId(Id id) { | |
| 453 IdToWindowMap::const_iterator it = windows_.find(id); | |
| 454 return it != windows_.end() ? it->second : NULL; | |
| 455 } | |
| 456 | |
| 457 InFlightChange* WindowTreeClient::GetOldestInFlightChangeMatching( | |
| 458 const InFlightChange& change) { | |
| 459 for (const auto& pair : in_flight_map_) { | |
| 460 if (pair.second->window() == change.window() && | |
| 461 pair.second->change_type() == change.change_type() && | |
| 462 pair.second->Matches(change)) { | |
| 463 return pair.second.get(); | |
| 464 } | |
| 465 } | |
| 466 return nullptr; | |
| 467 } | |
| 468 | |
| 469 uint32_t WindowTreeClient::ScheduleInFlightChange( | |
| 470 std::unique_ptr<InFlightChange> change) { | |
| 471 DCHECK(!change->window() || | |
| 472 windows_.count(change->window()->server_id()) > 0); | |
| 473 const uint32_t change_id = next_change_id_++; | |
| 474 in_flight_map_[change_id] = std::move(change); | |
| 475 return change_id; | |
| 476 } | |
| 477 | |
| 478 bool WindowTreeClient::ApplyServerChangeToExistingInFlightChange( | |
| 479 const InFlightChange& change) { | |
| 480 InFlightChange* existing_change = GetOldestInFlightChangeMatching(change); | |
| 481 if (!existing_change) | |
| 482 return false; | |
| 483 | |
| 484 existing_change->SetRevertValueFrom(change); | |
| 485 return true; | |
| 486 } | |
| 487 | |
| 488 Window* WindowTreeClient::NewWindowImpl( | |
| 489 NewWindowType type, | |
| 490 const Window::SharedProperties* properties) { | |
| 491 DCHECK(tree_); | |
| 492 Window* window = | |
| 493 new Window(this, MakeTransportId(client_id_, next_window_id_++)); | |
| 494 if (properties) | |
| 495 window->properties_ = *properties; | |
| 496 AddWindow(window); | |
| 497 | |
| 498 const uint32_t change_id = ScheduleInFlightChange(base::WrapUnique( | |
| 499 new CrashInFlightChange(window, type == NewWindowType::CHILD | |
| 500 ? ChangeType::NEW_WINDOW | |
| 501 : ChangeType::NEW_TOP_LEVEL_WINDOW))); | |
| 502 mojo::Map<mojo::String, mojo::Array<uint8_t>> transport_properties; | |
| 503 if (properties) { | |
| 504 transport_properties = | |
| 505 mojo::Map<mojo::String, mojo::Array<uint8_t>>::From(*properties); | |
| 506 } | |
| 507 if (type == NewWindowType::CHILD) { | |
| 508 tree_->NewWindow(change_id, server_id(window), | |
| 509 std::move(transport_properties)); | |
| 510 } else { | |
| 511 roots_.insert(window); | |
| 512 tree_->NewTopLevelWindow(change_id, server_id(window), | |
| 513 std::move(transport_properties)); | |
| 514 } | |
| 515 return window; | |
| 516 } | |
| 517 | |
| 518 void WindowTreeClient::SetWindowTree(mojom::WindowTreePtr window_tree_ptr) { | |
| 519 tree_ptr_ = std::move(window_tree_ptr); | |
| 520 tree_ = tree_ptr_.get(); | |
| 521 | |
| 522 tree_ptr_->GetCursorLocationMemory( | |
| 523 base::Bind(&WindowTreeClient::OnReceivedCursorLocationMemory, | |
| 524 weak_factory_.GetWeakPtr())); | |
| 525 | |
| 526 tree_ptr_.set_connection_error_handler(base::Bind( | |
| 527 &WindowTreeClient::OnConnectionLost, weak_factory_.GetWeakPtr())); | |
| 528 | |
| 529 if (window_manager_delegate_) { | |
| 530 tree_ptr_->GetWindowManagerClient(GetProxy(&window_manager_internal_client_, | |
| 531 tree_ptr_.associated_group())); | |
| 532 } | |
| 533 } | |
| 534 | |
| 535 void WindowTreeClient::OnConnectionLost() { | |
| 536 delete this; | |
| 537 } | |
| 538 | |
| 539 void WindowTreeClient::OnEmbedImpl(mojom::WindowTree* window_tree, | |
| 540 ClientSpecificId client_id, | |
| 541 mojom::WindowDataPtr root_data, | |
| 542 int64_t display_id, | |
| 543 Id focused_window_id, | |
| 544 bool drawn) { | |
| 545 // WARNING: this is only called if WindowTreeClient was created as the | |
| 546 // result of an embedding. | |
| 547 tree_ = window_tree; | |
| 548 client_id_ = client_id; | |
| 549 | |
| 550 DCHECK(roots_.empty()); | |
| 551 Window* root = AddWindowToClient(this, nullptr, root_data); | |
| 552 WindowPrivate(root).LocalSetDisplay(display_id); | |
| 553 roots_.insert(root); | |
| 554 | |
| 555 focused_window_ = GetWindowByServerId(focused_window_id); | |
| 556 | |
| 557 WindowPrivate(root).LocalSetParentDrawn(drawn); | |
| 558 | |
| 559 delegate_->OnEmbed(root); | |
| 560 | |
| 561 if (focused_window_) { | |
| 562 FOR_EACH_OBSERVER(WindowTreeClientObserver, observers_, | |
| 563 OnWindowTreeFocusChanged(focused_window_, nullptr)); | |
| 564 } | |
| 565 } | |
| 566 | |
| 567 void WindowTreeClient::WmNewDisplayAddedImpl(const display::Display& display, | |
| 568 mojom::WindowDataPtr root_data, | |
| 569 bool parent_drawn) { | |
| 570 DCHECK(window_manager_delegate_); | |
| 571 | |
| 572 Window* root = AddWindowToClient(this, nullptr, root_data); | |
| 573 WindowPrivate(root).LocalSetDisplay(display.id()); | |
| 574 WindowPrivate(root).LocalSetParentDrawn(parent_drawn); | |
| 575 roots_.insert(root); | |
| 576 | |
| 577 window_manager_delegate_->OnWmNewDisplay(root, display); | |
| 578 } | |
| 579 | |
| 580 void WindowTreeClient::OnReceivedCursorLocationMemory( | |
| 581 mojo::ScopedSharedBufferHandle handle) { | |
| 582 cursor_location_mapping_ = handle->Map(sizeof(base::subtle::Atomic32)); | |
| 583 DCHECK(cursor_location_mapping_); | |
| 584 } | |
| 585 | |
| 586 //////////////////////////////////////////////////////////////////////////////// | |
| 587 // WindowTreeClient, WindowTreeClient implementation: | |
| 588 | |
| 589 void WindowTreeClient::SetDeleteOnNoRoots(bool value) { | |
| 590 delete_on_no_roots_ = value; | |
| 591 } | |
| 592 | |
| 593 const std::set<Window*>& WindowTreeClient::GetRoots() { | |
| 594 return roots_; | |
| 595 } | |
| 596 | |
| 597 Window* WindowTreeClient::GetFocusedWindow() { | |
| 598 return focused_window_; | |
| 599 } | |
| 600 | |
| 601 void WindowTreeClient::ClearFocus() { | |
| 602 if (!focused_window_) | |
| 603 return; | |
| 604 | |
| 605 SetFocus(nullptr); | |
| 606 } | |
| 607 | |
| 608 gfx::Point WindowTreeClient::GetCursorScreenPoint() { | |
| 609 // We raced initialization. Return (0, 0). | |
| 610 if (!cursor_location_memory()) | |
| 611 return gfx::Point(); | |
| 612 | |
| 613 base::subtle::Atomic32 location = | |
| 614 base::subtle::NoBarrier_Load(cursor_location_memory()); | |
| 615 return gfx::Point(static_cast<int16_t>(location >> 16), | |
| 616 static_cast<int16_t>(location & 0xFFFF)); | |
| 617 } | |
| 618 | |
| 619 void WindowTreeClient::SetEventObserver(mojom::EventMatcherPtr matcher) { | |
| 620 if (matcher.is_null()) { | |
| 621 has_event_observer_ = false; | |
| 622 tree_->SetEventObserver(nullptr, 0u); | |
| 623 } else { | |
| 624 has_event_observer_ = true; | |
| 625 event_observer_id_++; | |
| 626 tree_->SetEventObserver(std::move(matcher), event_observer_id_); | |
| 627 } | |
| 628 } | |
| 629 | |
| 630 Window* WindowTreeClient::NewWindow( | |
| 631 const Window::SharedProperties* properties) { | |
| 632 return NewWindowImpl(NewWindowType::CHILD, properties); | |
| 633 } | |
| 634 | |
| 635 Window* WindowTreeClient::NewTopLevelWindow( | |
| 636 const Window::SharedProperties* properties) { | |
| 637 Window* window = NewWindowImpl(NewWindowType::TOP_LEVEL, properties); | |
| 638 // Assume newly created top level windows are drawn by default, otherwise | |
| 639 // requests to focus will fail. We will get the real value in | |
| 640 // OnTopLevelCreated(). | |
| 641 window->LocalSetParentDrawn(true); | |
| 642 return window; | |
| 643 } | |
| 644 | |
| 645 #if !defined(NDEBUG) | |
| 646 std::string WindowTreeClient::GetDebugWindowHierarchy() const { | |
| 647 std::string result; | |
| 648 for (Window* root : roots_) | |
| 649 BuildDebugInfo(std::string(), root, &result); | |
| 650 return result; | |
| 651 } | |
| 652 | |
| 653 void WindowTreeClient::BuildDebugInfo(const std::string& depth, | |
| 654 Window* window, | |
| 655 std::string* result) const { | |
| 656 std::string name = window->GetName(); | |
| 657 *result += base::StringPrintf( | |
| 658 "%sid=%d visible=%s bounds=%d,%d %dx%d %s\n", depth.c_str(), | |
| 659 window->server_id(), window->visible() ? "true" : "false", | |
| 660 window->bounds().x(), window->bounds().y(), window->bounds().width(), | |
| 661 window->bounds().height(), !name.empty() ? name.c_str() : "(no name)"); | |
| 662 for (Window* child : window->children()) | |
| 663 BuildDebugInfo(depth + " ", child, result); | |
| 664 } | |
| 665 #endif // !defined(NDEBUG) | |
| 666 | |
| 667 //////////////////////////////////////////////////////////////////////////////// | |
| 668 // WindowTreeClient, WindowTreeClient implementation: | |
| 669 | |
| 670 void WindowTreeClient::AddObserver(WindowTreeClientObserver* observer) { | |
| 671 observers_.AddObserver(observer); | |
| 672 } | |
| 673 | |
| 674 void WindowTreeClient::RemoveObserver(WindowTreeClientObserver* observer) { | |
| 675 observers_.RemoveObserver(observer); | |
| 676 } | |
| 677 | |
| 678 void WindowTreeClient::OnEmbed(ClientSpecificId client_id, | |
| 679 mojom::WindowDataPtr root_data, | |
| 680 mojom::WindowTreePtr tree, | |
| 681 int64_t display_id, | |
| 682 Id focused_window_id, | |
| 683 bool drawn) { | |
| 684 DCHECK(!tree_ptr_); | |
| 685 tree_ptr_ = std::move(tree); | |
| 686 tree_ptr_.set_connection_error_handler( | |
| 687 base::Bind(&DeleteWindowTreeClient, this)); | |
| 688 | |
| 689 if (window_manager_delegate_) { | |
| 690 tree_ptr_->GetWindowManagerClient(GetProxy(&window_manager_internal_client_, | |
| 691 tree_ptr_.associated_group())); | |
| 692 } | |
| 693 | |
| 694 OnEmbedImpl(tree_ptr_.get(), client_id, std::move(root_data), display_id, | |
| 695 focused_window_id, drawn); | |
| 696 } | |
| 697 | |
| 698 void WindowTreeClient::OnEmbeddedAppDisconnected(Id window_id) { | |
| 699 Window* window = GetWindowByServerId(window_id); | |
| 700 if (window) { | |
| 701 FOR_EACH_OBSERVER(WindowObserver, *WindowPrivate(window).observers(), | |
| 702 OnWindowEmbeddedAppDisconnected(window)); | |
| 703 } | |
| 704 } | |
| 705 | |
| 706 void WindowTreeClient::OnUnembed(Id window_id) { | |
| 707 Window* window = GetWindowByServerId(window_id); | |
| 708 if (!window) | |
| 709 return; | |
| 710 | |
| 711 delegate_->OnUnembed(window); | |
| 712 WindowPrivate(window).LocalDestroy(); | |
| 713 } | |
| 714 | |
| 715 void WindowTreeClient::OnLostCapture(Id window_id) { | |
| 716 Window* window = GetWindowByServerId(window_id); | |
| 717 if (!window) | |
| 718 return; | |
| 719 | |
| 720 InFlightCaptureChange reset_change(this, nullptr); | |
| 721 if (ApplyServerChangeToExistingInFlightChange(reset_change)) | |
| 722 return; | |
| 723 | |
| 724 LocalSetCapture(nullptr); | |
| 725 } | |
| 726 | |
| 727 void WindowTreeClient::OnTopLevelCreated(uint32_t change_id, | |
| 728 mojom::WindowDataPtr data, | |
| 729 int64_t display_id, | |
| 730 bool drawn) { | |
| 731 // The server ack'd the top level window we created and supplied the state | |
| 732 // of the window at the time the server created it. For properties we do not | |
| 733 // have changes in flight for we can update them immediately. For properties | |
| 734 // with changes in flight we set the revert value from the server. | |
| 735 | |
| 736 if (!in_flight_map_.count(change_id)) { | |
| 737 // The window may have been destroyed locally before the server could finish | |
| 738 // creating the window, and before the server received the notification that | |
| 739 // the window has been destroyed. | |
| 740 return; | |
| 741 } | |
| 742 std::unique_ptr<InFlightChange> change(std::move(in_flight_map_[change_id])); | |
| 743 in_flight_map_.erase(change_id); | |
| 744 | |
| 745 Window* window = change->window(); | |
| 746 WindowPrivate window_private(window); | |
| 747 | |
| 748 // Drawn state and display-id always come from the server (they can't be | |
| 749 // modified locally). | |
| 750 window_private.LocalSetParentDrawn(drawn); | |
| 751 window_private.LocalSetDisplay(display_id); | |
| 752 | |
| 753 // The default visibilty is false, we only need update visibility if it | |
| 754 // differs from that. | |
| 755 if (data->visible) { | |
| 756 InFlightVisibleChange visible_change(window, data->visible); | |
| 757 InFlightChange* current_change = | |
| 758 GetOldestInFlightChangeMatching(visible_change); | |
| 759 if (current_change) | |
| 760 current_change->SetRevertValueFrom(visible_change); | |
| 761 else | |
| 762 window_private.LocalSetVisible(true); | |
| 763 } | |
| 764 | |
| 765 const gfx::Rect bounds(data->bounds); | |
| 766 { | |
| 767 InFlightBoundsChange bounds_change(window, bounds); | |
| 768 InFlightChange* current_change = | |
| 769 GetOldestInFlightChangeMatching(bounds_change); | |
| 770 if (current_change) | |
| 771 current_change->SetRevertValueFrom(bounds_change); | |
| 772 else if (window->bounds() != bounds) | |
| 773 window_private.LocalSetBounds(window->bounds(), bounds); | |
| 774 } | |
| 775 | |
| 776 // There is currently no API to bulk set properties, so we iterate over each | |
| 777 // property individually. | |
| 778 Window::SharedProperties properties = | |
| 779 data->properties.To<std::map<std::string, std::vector<uint8_t>>>(); | |
| 780 for (const auto& pair : properties) { | |
| 781 InFlightPropertyChange property_change( | |
| 782 window, pair.first, mojo::Array<uint8_t>::From(pair.second)); | |
| 783 InFlightChange* current_change = | |
| 784 GetOldestInFlightChangeMatching(property_change); | |
| 785 if (current_change) | |
| 786 current_change->SetRevertValueFrom(property_change); | |
| 787 else | |
| 788 window_private.LocalSetSharedProperty(pair.first, &(pair.second)); | |
| 789 } | |
| 790 | |
| 791 // Top level windows should not have a parent. | |
| 792 DCHECK_EQ(0u, data->parent_id); | |
| 793 } | |
| 794 | |
| 795 void WindowTreeClient::OnWindowBoundsChanged(Id window_id, | |
| 796 const gfx::Rect& old_bounds, | |
| 797 const gfx::Rect& new_bounds) { | |
| 798 Window* window = GetWindowByServerId(window_id); | |
| 799 if (!window) | |
| 800 return; | |
| 801 | |
| 802 InFlightBoundsChange new_change(window, new_bounds); | |
| 803 if (ApplyServerChangeToExistingInFlightChange(new_change)) | |
| 804 return; | |
| 805 | |
| 806 WindowPrivate(window).LocalSetBounds(old_bounds, new_bounds); | |
| 807 } | |
| 808 | |
| 809 void WindowTreeClient::OnClientAreaChanged( | |
| 810 uint32_t window_id, | |
| 811 const gfx::Insets& new_client_area, | |
| 812 mojo::Array<gfx::Rect> new_additional_client_areas) { | |
| 813 Window* window = GetWindowByServerId(window_id); | |
| 814 if (window) { | |
| 815 WindowPrivate(window).LocalSetClientArea( | |
| 816 new_client_area, | |
| 817 new_additional_client_areas.To<std::vector<gfx::Rect>>()); | |
| 818 } | |
| 819 } | |
| 820 | |
| 821 void WindowTreeClient::OnTransientWindowAdded( | |
| 822 uint32_t window_id, | |
| 823 uint32_t transient_window_id) { | |
| 824 Window* window = GetWindowByServerId(window_id); | |
| 825 Window* transient_window = GetWindowByServerId(transient_window_id); | |
| 826 // window or transient_window or both may be null if a local delete occurs | |
| 827 // with an in flight add from the server. | |
| 828 if (window && transient_window) | |
| 829 WindowPrivate(window).LocalAddTransientWindow(transient_window); | |
| 830 } | |
| 831 | |
| 832 void WindowTreeClient::OnTransientWindowRemoved( | |
| 833 uint32_t window_id, | |
| 834 uint32_t transient_window_id) { | |
| 835 Window* window = GetWindowByServerId(window_id); | |
| 836 Window* transient_window = GetWindowByServerId(transient_window_id); | |
| 837 // window or transient_window or both may be null if a local delete occurs | |
| 838 // with an in flight delete from the server. | |
| 839 if (window && transient_window) | |
| 840 WindowPrivate(window).LocalRemoveTransientWindow(transient_window); | |
| 841 } | |
| 842 | |
| 843 void WindowTreeClient::OnWindowHierarchyChanged( | |
| 844 Id window_id, | |
| 845 Id old_parent_id, | |
| 846 Id new_parent_id, | |
| 847 mojo::Array<mojom::WindowDataPtr> windows) { | |
| 848 Window* initial_parent = | |
| 849 windows.size() ? GetWindowByServerId(windows[0]->parent_id) : NULL; | |
| 850 | |
| 851 const bool was_window_known = GetWindowByServerId(window_id) != nullptr; | |
| 852 | |
| 853 BuildWindowTree(this, windows, initial_parent); | |
| 854 | |
| 855 // If the window was not known, then BuildWindowTree() will have created it | |
| 856 // and parented the window. | |
| 857 if (!was_window_known) | |
| 858 return; | |
| 859 | |
| 860 Window* new_parent = GetWindowByServerId(new_parent_id); | |
| 861 Window* old_parent = GetWindowByServerId(old_parent_id); | |
| 862 Window* window = GetWindowByServerId(window_id); | |
| 863 if (new_parent) | |
| 864 WindowPrivate(new_parent).LocalAddChild(window); | |
| 865 else | |
| 866 WindowPrivate(old_parent).LocalRemoveChild(window); | |
| 867 } | |
| 868 | |
| 869 void WindowTreeClient::OnWindowReordered(Id window_id, | |
| 870 Id relative_window_id, | |
| 871 mojom::OrderDirection direction) { | |
| 872 Window* window = GetWindowByServerId(window_id); | |
| 873 Window* relative_window = GetWindowByServerId(relative_window_id); | |
| 874 if (window && relative_window) | |
| 875 WindowPrivate(window).LocalReorder(relative_window, direction); | |
| 876 } | |
| 877 | |
| 878 void WindowTreeClient::OnWindowDeleted(Id window_id) { | |
| 879 Window* window = GetWindowByServerId(window_id); | |
| 880 if (window) | |
| 881 WindowPrivate(window).LocalDestroy(); | |
| 882 } | |
| 883 | |
| 884 Window* WindowTreeClient::GetCaptureWindow() { | |
| 885 return capture_window_; | |
| 886 } | |
| 887 | |
| 888 void WindowTreeClient::OnWindowVisibilityChanged(Id window_id, | |
| 889 bool visible) { | |
| 890 Window* window = GetWindowByServerId(window_id); | |
| 891 if (!window) | |
| 892 return; | |
| 893 | |
| 894 InFlightVisibleChange new_change(window, visible); | |
| 895 if (ApplyServerChangeToExistingInFlightChange(new_change)) | |
| 896 return; | |
| 897 | |
| 898 WindowPrivate(window).LocalSetVisible(visible); | |
| 899 } | |
| 900 | |
| 901 void WindowTreeClient::OnWindowOpacityChanged(Id window_id, | |
| 902 float old_opacity, | |
| 903 float new_opacity) { | |
| 904 Window* window = GetWindowByServerId(window_id); | |
| 905 if (!window) | |
| 906 return; | |
| 907 | |
| 908 InFlightOpacityChange new_change(window, new_opacity); | |
| 909 if (ApplyServerChangeToExistingInFlightChange(new_change)) | |
| 910 return; | |
| 911 | |
| 912 WindowPrivate(window).LocalSetOpacity(new_opacity); | |
| 913 } | |
| 914 | |
| 915 void WindowTreeClient::OnWindowParentDrawnStateChanged(Id window_id, | |
| 916 bool drawn) { | |
| 917 Window* window = GetWindowByServerId(window_id); | |
| 918 if (window) | |
| 919 WindowPrivate(window).LocalSetParentDrawn(drawn); | |
| 920 } | |
| 921 | |
| 922 void WindowTreeClient::OnWindowSharedPropertyChanged( | |
| 923 Id window_id, | |
| 924 const mojo::String& name, | |
| 925 mojo::Array<uint8_t> new_data) { | |
| 926 Window* window = GetWindowByServerId(window_id); | |
| 927 if (!window) | |
| 928 return; | |
| 929 | |
| 930 InFlightPropertyChange new_change(window, name, new_data); | |
| 931 if (ApplyServerChangeToExistingInFlightChange(new_change)) | |
| 932 return; | |
| 933 | |
| 934 WindowPrivate(window).LocalSetSharedProperty(name, std::move(new_data)); | |
| 935 } | |
| 936 | |
| 937 void WindowTreeClient::OnWindowInputEvent(uint32_t event_id, | |
| 938 Id window_id, | |
| 939 std::unique_ptr<ui::Event> event, | |
| 940 uint32_t event_observer_id) { | |
| 941 DCHECK(event); | |
| 942 Window* window = GetWindowByServerId(window_id); // May be null. | |
| 943 | |
| 944 // Non-zero event_observer_id means it matched an event observer on the | |
| 945 // server. | |
| 946 if (event_observer_id != 0 && has_event_observer_ && | |
| 947 event_observer_id == event_observer_id_) | |
| 948 delegate_->OnEventObserved(*event.get(), window); | |
| 949 | |
| 950 if (!window || !window->input_event_handler_) { | |
| 951 tree_->OnWindowInputEventAck(event_id, mojom::EventResult::UNHANDLED); | |
| 952 return; | |
| 953 } | |
| 954 | |
| 955 std::unique_ptr<base::Callback<void(mojom::EventResult)>> ack_callback( | |
| 956 new base::Callback<void(mojom::EventResult)>( | |
| 957 base::Bind(&mojom::WindowTree::OnWindowInputEventAck, | |
| 958 base::Unretained(tree_), event_id))); | |
| 959 | |
| 960 // TODO(moshayedi): crbug.com/617222. No need to convert to ui::MouseEvent or | |
| 961 // ui::TouchEvent once we have proper support for pointer events. | |
| 962 if (event->IsMousePointerEvent()) { | |
| 963 window->input_event_handler_->OnWindowInputEvent( | |
| 964 window, ui::MouseEvent(*event->AsPointerEvent()), &ack_callback); | |
| 965 } else if (event->IsTouchPointerEvent()) { | |
| 966 window->input_event_handler_->OnWindowInputEvent( | |
| 967 window, ui::TouchEvent(*event->AsPointerEvent()), &ack_callback); | |
| 968 } else { | |
| 969 window->input_event_handler_->OnWindowInputEvent(window, *event.get(), | |
| 970 &ack_callback); | |
| 971 } | |
| 972 | |
| 973 // The handler did not take ownership of the callback, so we send the ack, | |
| 974 // marking the event as not consumed. | |
| 975 if (ack_callback) | |
| 976 ack_callback->Run(mojom::EventResult::UNHANDLED); | |
| 977 } | |
| 978 | |
| 979 void WindowTreeClient::OnEventObserved(std::unique_ptr<ui::Event> event, | |
| 980 uint32_t event_observer_id) { | |
| 981 DCHECK(event); | |
| 982 if (has_event_observer_ && event_observer_id == event_observer_id_) | |
| 983 delegate_->OnEventObserved(*event.get(), nullptr /* target */); | |
| 984 } | |
| 985 | |
| 986 void WindowTreeClient::OnWindowFocused(Id focused_window_id) { | |
| 987 Window* focused_window = GetWindowByServerId(focused_window_id); | |
| 988 InFlightFocusChange new_change(this, focused_window); | |
| 989 if (ApplyServerChangeToExistingInFlightChange(new_change)) | |
| 990 return; | |
| 991 | |
| 992 LocalSetFocus(focused_window); | |
| 993 } | |
| 994 | |
| 995 void WindowTreeClient::OnWindowPredefinedCursorChanged( | |
| 996 Id window_id, | |
| 997 mojom::Cursor cursor) { | |
| 998 Window* window = GetWindowByServerId(window_id); | |
| 999 if (!window) | |
| 1000 return; | |
| 1001 | |
| 1002 InFlightPredefinedCursorChange new_change(window, cursor); | |
| 1003 if (ApplyServerChangeToExistingInFlightChange(new_change)) | |
| 1004 return; | |
| 1005 | |
| 1006 WindowPrivate(window).LocalSetPredefinedCursor(cursor); | |
| 1007 } | |
| 1008 | |
| 1009 void WindowTreeClient::OnChangeCompleted(uint32_t change_id, bool success) { | |
| 1010 std::unique_ptr<InFlightChange> change(std::move(in_flight_map_[change_id])); | |
| 1011 in_flight_map_.erase(change_id); | |
| 1012 if (!change) | |
| 1013 return; | |
| 1014 | |
| 1015 if (!success) | |
| 1016 change->ChangeFailed(); | |
| 1017 | |
| 1018 InFlightChange* next_change = GetOldestInFlightChangeMatching(*change); | |
| 1019 if (next_change) { | |
| 1020 if (!success) | |
| 1021 next_change->SetRevertValueFrom(*change); | |
| 1022 } else if (!success) { | |
| 1023 change->Revert(); | |
| 1024 } | |
| 1025 } | |
| 1026 | |
| 1027 void WindowTreeClient::GetWindowManager( | |
| 1028 mojo::AssociatedInterfaceRequest<WindowManager> internal) { | |
| 1029 window_manager_internal_.reset( | |
| 1030 new mojo::AssociatedBinding<mojom::WindowManager>(this, | |
| 1031 std::move(internal))); | |
| 1032 } | |
| 1033 | |
| 1034 void WindowTreeClient::RequestClose(uint32_t window_id) { | |
| 1035 Window* window = GetWindowByServerId(window_id); | |
| 1036 if (!window || !IsRoot(window)) | |
| 1037 return; | |
| 1038 | |
| 1039 FOR_EACH_OBSERVER(WindowObserver, *WindowPrivate(window).observers(), | |
| 1040 OnRequestClose(window)); | |
| 1041 } | |
| 1042 | |
| 1043 void WindowTreeClient::OnConnect(ClientSpecificId client_id) { | |
| 1044 client_id_ = client_id; | |
| 1045 } | |
| 1046 | |
| 1047 void WindowTreeClient::WmNewDisplayAdded(mojom::DisplayPtr display, | |
| 1048 mojom::WindowDataPtr root_data, | |
| 1049 bool parent_drawn) { | |
| 1050 WmNewDisplayAddedImpl(display.To<display::Display>(), std::move(root_data), | |
| 1051 parent_drawn); | |
| 1052 } | |
| 1053 | |
| 1054 void WindowTreeClient::WmSetBounds(uint32_t change_id, | |
| 1055 Id window_id, | |
| 1056 const gfx::Rect& transit_bounds) { | |
| 1057 Window* window = GetWindowByServerId(window_id); | |
| 1058 bool result = false; | |
| 1059 if (window) { | |
| 1060 DCHECK(window_manager_delegate_); | |
| 1061 gfx::Rect bounds = transit_bounds; | |
| 1062 result = window_manager_delegate_->OnWmSetBounds(window, &bounds); | |
| 1063 if (result) { | |
| 1064 // If the resulting bounds differ return false. Returning false ensures | |
| 1065 // the client applies the bounds we set below. | |
| 1066 result = bounds == transit_bounds; | |
| 1067 window->SetBounds(bounds); | |
| 1068 } | |
| 1069 } | |
| 1070 if (window_manager_internal_client_) | |
| 1071 window_manager_internal_client_->WmResponse(change_id, result); | |
| 1072 } | |
| 1073 | |
| 1074 void WindowTreeClient::WmSetProperty(uint32_t change_id, | |
| 1075 Id window_id, | |
| 1076 const mojo::String& name, | |
| 1077 mojo::Array<uint8_t> transit_data) { | |
| 1078 Window* window = GetWindowByServerId(window_id); | |
| 1079 bool result = false; | |
| 1080 if (window) { | |
| 1081 DCHECK(window_manager_delegate_); | |
| 1082 std::unique_ptr<std::vector<uint8_t>> data; | |
| 1083 if (!transit_data.is_null()) { | |
| 1084 data.reset( | |
| 1085 new std::vector<uint8_t>(transit_data.To<std::vector<uint8_t>>())); | |
| 1086 } | |
| 1087 result = window_manager_delegate_->OnWmSetProperty(window, name, &data); | |
| 1088 if (result) { | |
| 1089 // If the resulting bounds differ return false. Returning false ensures | |
| 1090 // the client applies the bounds we set below. | |
| 1091 window->SetSharedPropertyInternal(name, data.get()); | |
| 1092 } | |
| 1093 } | |
| 1094 if (window_manager_internal_client_) | |
| 1095 window_manager_internal_client_->WmResponse(change_id, result); | |
| 1096 } | |
| 1097 | |
| 1098 void WindowTreeClient::WmCreateTopLevelWindow( | |
| 1099 uint32_t change_id, | |
| 1100 ClientSpecificId requesting_client_id, | |
| 1101 mojo::Map<mojo::String, mojo::Array<uint8_t>> transport_properties) { | |
| 1102 std::map<std::string, std::vector<uint8_t>> properties = | |
| 1103 transport_properties.To<std::map<std::string, std::vector<uint8_t>>>(); | |
| 1104 Window* window = | |
| 1105 window_manager_delegate_->OnWmCreateTopLevelWindow(&properties); | |
| 1106 embedded_windows_[requesting_client_id].insert(window); | |
| 1107 if (window_manager_internal_client_) { | |
| 1108 window_manager_internal_client_->OnWmCreatedTopLevelWindow( | |
| 1109 change_id, server_id(window)); | |
| 1110 } | |
| 1111 } | |
| 1112 | |
| 1113 void WindowTreeClient::WmClientJankinessChanged(ClientSpecificId client_id, | |
| 1114 bool janky) { | |
| 1115 if (window_manager_delegate_) { | |
| 1116 auto it = embedded_windows_.find(client_id); | |
| 1117 CHECK(it != embedded_windows_.end()); | |
| 1118 window_manager_delegate_->OnWmClientJankinessChanged( | |
| 1119 embedded_windows_[client_id], janky); | |
| 1120 } | |
| 1121 } | |
| 1122 | |
| 1123 void WindowTreeClient::OnAccelerator(uint32_t id, | |
| 1124 std::unique_ptr<ui::Event> event) { | |
| 1125 DCHECK(event); | |
| 1126 window_manager_delegate_->OnAccelerator(id, *event.get()); | |
| 1127 } | |
| 1128 | |
| 1129 void WindowTreeClient::SetFrameDecorationValues( | |
| 1130 mojom::FrameDecorationValuesPtr values) { | |
| 1131 if (window_manager_internal_client_) { | |
| 1132 window_manager_internal_client_->WmSetFrameDecorationValues( | |
| 1133 std::move(values)); | |
| 1134 } | |
| 1135 } | |
| 1136 | |
| 1137 void WindowTreeClient::SetNonClientCursor(Window* window, | |
| 1138 mus::mojom::Cursor cursor_id) { | |
| 1139 window_manager_internal_client_->WmSetNonClientCursor(server_id(window), | |
| 1140 cursor_id); | |
| 1141 } | |
| 1142 | |
| 1143 void WindowTreeClient::AddAccelerator( | |
| 1144 uint32_t id, | |
| 1145 mojom::EventMatcherPtr event_matcher, | |
| 1146 const base::Callback<void(bool)>& callback) { | |
| 1147 if (window_manager_internal_client_) { | |
| 1148 window_manager_internal_client_->AddAccelerator( | |
| 1149 id, std::move(event_matcher), callback); | |
| 1150 } | |
| 1151 } | |
| 1152 | |
| 1153 void WindowTreeClient::RemoveAccelerator(uint32_t id) { | |
| 1154 if (window_manager_internal_client_) { | |
| 1155 window_manager_internal_client_->RemoveAccelerator(id); | |
| 1156 } | |
| 1157 } | |
| 1158 | |
| 1159 void WindowTreeClient::AddActivationParent(Window* window) { | |
| 1160 if (window_manager_internal_client_) | |
| 1161 window_manager_internal_client_->AddActivationParent(server_id(window)); | |
| 1162 } | |
| 1163 | |
| 1164 void WindowTreeClient::RemoveActivationParent(Window* window) { | |
| 1165 if (window_manager_internal_client_) | |
| 1166 window_manager_internal_client_->RemoveActivationParent(server_id(window)); | |
| 1167 } | |
| 1168 | |
| 1169 void WindowTreeClient::ActivateNextWindow() { | |
| 1170 if (window_manager_internal_client_) | |
| 1171 window_manager_internal_client_->ActivateNextWindow(); | |
| 1172 } | |
| 1173 | |
| 1174 void WindowTreeClient::SetUnderlaySurfaceOffsetAndExtendedHitArea( | |
| 1175 Window* window, | |
| 1176 const gfx::Vector2d& offset, | |
| 1177 const gfx::Insets& hit_area) { | |
| 1178 if (window_manager_internal_client_) { | |
| 1179 window_manager_internal_client_->SetUnderlaySurfaceOffsetAndExtendedHitArea( | |
| 1180 server_id(window), offset.x(), offset.y(), hit_area); | |
| 1181 } | |
| 1182 } | |
| 1183 | |
| 1184 } // namespace mus | |
| OLD | NEW |