| // Copyright 2016 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/gfx/win/rendering_window_manager.h" |
| |
| #include "base/bind.h" |
| #include "base/logging.h" |
| #include "base/no_destructor.h" |
| #include "base/single_thread_task_runner.h" |
| #include "base/threading/thread_task_runner_handle.h" |
| |
| namespace gfx { |
| |
| // static |
| RenderingWindowManager* RenderingWindowManager::GetInstance() { |
| static base::NoDestructor<RenderingWindowManager> instance; |
| return instance.get(); |
| } |
| |
| void RenderingWindowManager::RegisterParent(HWND parent) { |
| DCHECK(task_runner_->BelongsToCurrentThread()); |
| registered_hwnds_.emplace(parent, nullptr); |
| } |
| |
| void RenderingWindowManager::RegisterChild(HWND parent, |
| HWND child, |
| DWORD expected_child_process_id) { |
| if (!child) |
| return; |
| |
| // This can be called from any thread, if we're not on the correct thread then |
| // PostTask back to the UI thread before doing anything. |
| if (!task_runner_->BelongsToCurrentThread()) { |
| task_runner_->PostTask( |
| FROM_HERE, base::BindOnce(&RenderingWindowManager::RegisterChild, |
| base::Unretained(this), parent, child, |
| expected_child_process_id)); |
| return; |
| } |
| |
| // Check that |parent| was registered as a HWND that could have a child HWND. |
| auto it = registered_hwnds_.find(parent); |
| if (it == registered_hwnds_.end()) |
| return; |
| |
| // Check that |child| belongs to the GPU process. |
| DWORD child_process_id = 0; |
| DWORD child_thread_id = GetWindowThreadProcessId(child, &child_process_id); |
| if (!child_thread_id || child_process_id != expected_child_process_id) { |
| DLOG(ERROR) << "Child HWND not owned by GPU process."; |
| return; |
| } |
| |
| it->second = child; |
| |
| ::SetParent(child, parent); |
| // Move D3D window behind Chrome's window to avoid losing some messages. |
| ::SetWindowPos(child, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); |
| } |
| |
| void RenderingWindowManager::UnregisterParent(HWND parent) { |
| DCHECK(task_runner_->BelongsToCurrentThread()); |
| registered_hwnds_.erase(parent); |
| } |
| |
| bool RenderingWindowManager::HasValidChildWindow(HWND parent) { |
| DCHECK(task_runner_->BelongsToCurrentThread()); |
| auto it = registered_hwnds_.find(parent); |
| if (it == registered_hwnds_.end()) |
| return false; |
| return !!it->second && ::IsWindow(it->second); |
| } |
| |
| RenderingWindowManager::RenderingWindowManager() |
| : task_runner_(base::ThreadTaskRunnerHandle::Get()) {} |
| |
| RenderingWindowManager::~RenderingWindowManager() = default; |
| |
| } // namespace gfx |