Bug 1793629 - Implement attention indicator for the unified extensions button, r...
[gecko.git] / widget / windows / WinCompositorWindowThread.cpp
blobf712522bc770d1f23e7e91ebbe64321090e960b6
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "base/platform_thread.h"
8 #include "WinCompositorWindowThread.h"
9 #include "mozilla/gfx/Logging.h"
10 #include "mozilla/layers/SynchronousTask.h"
11 #include "mozilla/StaticPtr.h"
12 #include "transport/runnable_utils.h"
13 #include "mozilla/StaticPrefs_apz.h"
15 #if WINVER < 0x0602
16 # define WS_EX_NOREDIRECTIONBITMAP 0x00200000L
17 #endif
19 namespace mozilla {
20 namespace widget {
22 static StaticRefPtr<WinCompositorWindowThread> sWinCompositorWindowThread;
24 WinCompositorWindowThread::WinCompositorWindowThread(base::Thread* aThread)
25 : mThread(aThread) {}
27 WinCompositorWindowThread::~WinCompositorWindowThread() { delete mThread; }
29 /* static */
30 WinCompositorWindowThread* WinCompositorWindowThread::Get() {
31 return sWinCompositorWindowThread;
34 /* static */
35 void WinCompositorWindowThread::Start() {
36 MOZ_ASSERT(NS_IsMainThread());
37 MOZ_ASSERT(!sWinCompositorWindowThread);
39 base::Thread* thread = new base::Thread("WinCompositor");
41 base::Thread::Options options;
42 // HWND requests ui thread.
43 options.message_loop_type = MessageLoop::TYPE_UI;
45 if (!thread->StartWithOptions(options)) {
46 delete thread;
47 return;
50 sWinCompositorWindowThread = new WinCompositorWindowThread(thread);
53 /* static */
54 void WinCompositorWindowThread::ShutDown() {
55 MOZ_ASSERT(NS_IsMainThread());
56 MOZ_ASSERT(sWinCompositorWindowThread);
58 layers::SynchronousTask task("WinCompositorWindowThread");
59 RefPtr<Runnable> runnable = WrapRunnable(
60 RefPtr<WinCompositorWindowThread>(sWinCompositorWindowThread.get()),
61 &WinCompositorWindowThread::ShutDownTask, &task);
62 sWinCompositorWindowThread->Loop()->PostTask(runnable.forget());
63 task.Wait();
65 sWinCompositorWindowThread = nullptr;
68 void WinCompositorWindowThread::ShutDownTask(layers::SynchronousTask* aTask) {
69 layers::AutoCompleteTask complete(aTask);
70 MOZ_ASSERT(IsInCompositorWindowThread());
73 /* static */
74 MessageLoop* WinCompositorWindowThread::Loop() {
75 return sWinCompositorWindowThread
76 ? sWinCompositorWindowThread->mThread->message_loop()
77 : nullptr;
80 /* static */
81 bool WinCompositorWindowThread::IsInCompositorWindowThread() {
82 return sWinCompositorWindowThread &&
83 sWinCompositorWindowThread->mThread->thread_id() ==
84 PlatformThread::CurrentId();
87 const wchar_t kClassNameCompositorInitalParent[] =
88 L"MozillaCompositorInitialParentClass";
89 const wchar_t kClassNameCompositor[] = L"MozillaCompositorWindowClass";
91 ATOM g_compositor_inital_parent_window_class;
92 ATOM g_compositor_window_class;
94 // This runs on the window owner thread.
95 void InitializeInitialParentWindowClass() {
96 if (g_compositor_inital_parent_window_class) {
97 return;
100 WNDCLASSW wc;
101 wc.style = 0;
102 wc.lpfnWndProc = ::DefWindowProcW;
103 wc.cbClsExtra = 0;
104 wc.cbWndExtra = 0;
105 wc.hInstance = GetModuleHandle(nullptr);
106 wc.hIcon = nullptr;
107 wc.hCursor = nullptr;
108 wc.hbrBackground = nullptr;
109 wc.lpszMenuName = nullptr;
110 wc.lpszClassName = kClassNameCompositorInitalParent;
111 g_compositor_inital_parent_window_class = ::RegisterClassW(&wc);
114 // This runs on the window owner thread.
115 void InitializeWindowClass() {
116 if (g_compositor_window_class) {
117 return;
120 WNDCLASSW wc;
121 wc.style = CS_OWNDC;
122 wc.lpfnWndProc = ::DefWindowProcW;
123 wc.cbClsExtra = 0;
124 wc.cbWndExtra = 0;
125 wc.hInstance = GetModuleHandle(nullptr);
126 wc.hIcon = nullptr;
127 wc.hCursor = nullptr;
128 wc.hbrBackground = nullptr;
129 wc.lpszMenuName = nullptr;
130 wc.lpszClassName = kClassNameCompositor;
131 g_compositor_window_class = ::RegisterClassW(&wc);
134 /* static */
135 WinCompositorWnds WinCompositorWindowThread::CreateCompositorWindow() {
136 MOZ_ASSERT(Loop());
138 if (!Loop()) {
139 return WinCompositorWnds(nullptr, nullptr);
142 layers::SynchronousTask task("Create compositor window");
144 HWND initialParentWnd = nullptr;
145 HWND compositorWnd = nullptr;
147 RefPtr<Runnable> runnable = NS_NewRunnableFunction(
148 "WinCompositorWindowThread::CreateCompositorWindow::Runnable", [&]() {
149 layers::AutoCompleteTask complete(&task);
151 InitializeInitialParentWindowClass();
152 InitializeWindowClass();
154 // Create initial parent window.
155 // We could not directly create a compositor window with a main window
156 // as parent window, so instead create it with a temporary placeholder
157 // parent. Its parent is set as main window in UI process.
158 initialParentWnd =
159 ::CreateWindowEx(WS_EX_TOOLWINDOW, kClassNameCompositorInitalParent,
160 nullptr, WS_POPUP | WS_DISABLED, 0, 0, 1, 1,
161 nullptr, 0, GetModuleHandle(nullptr), 0);
162 if (!initialParentWnd) {
163 gfxCriticalNoteOnce << "Inital parent window failed "
164 << ::GetLastError();
165 return;
168 DWORD extendedStyle = WS_EX_NOPARENTNOTIFY | WS_EX_NOREDIRECTIONBITMAP;
170 if (!StaticPrefs::apz_windows_force_disable_direct_manipulation()) {
171 extendedStyle |= WS_EX_LAYERED | WS_EX_TRANSPARENT;
174 compositorWnd = ::CreateWindowEx(
175 extendedStyle, kClassNameCompositor, nullptr,
176 WS_CHILDWINDOW | WS_DISABLED | WS_VISIBLE, 0, 0, 1, 1,
177 initialParentWnd, 0, GetModuleHandle(nullptr), 0);
178 if (!compositorWnd) {
179 gfxCriticalNoteOnce << "Compositor window failed "
180 << ::GetLastError();
184 Loop()->PostTask(runnable.forget());
186 task.Wait();
188 return WinCompositorWnds(compositorWnd, initialParentWnd);
191 /* static */
192 void WinCompositorWindowThread::DestroyCompositorWindow(
193 WinCompositorWnds aWnds) {
194 MOZ_ASSERT(aWnds.mCompositorWnd);
195 MOZ_ASSERT(aWnds.mInitialParentWnd);
196 MOZ_ASSERT(Loop());
198 if (!Loop()) {
199 return;
202 RefPtr<Runnable> runnable = NS_NewRunnableFunction(
203 "WinCompositorWidget::CreateNativeWindow::Runnable", [aWnds]() {
204 ::DestroyWindow(aWnds.mCompositorWnd);
205 ::DestroyWindow(aWnds.mInitialParentWnd);
208 Loop()->PostTask(runnable.forget());
211 } // namespace widget
212 } // namespace mozilla