Bug Summary

File:root/firefox-clang/widget/gtk/nsWindowWaylandGtk.cpp
Warning:line 1303, column 14
Value stored to 'tmp' during its initialization is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O2 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name nsWindowWaylandGtk.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/widget/gtk -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/widget/gtk -resource-dir /usr/lib/llvm-23/lib/clang/23 -include /root/firefox-clang/config/gcc_hidden.h -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -D _GLIBCXX_ASSERTIONS=1 -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D CAIRO_GFX -D MOZ_APP_NAME="firefox" -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /root/firefox-clang/widget/gtk -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/widget/gtk -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /root/firefox-clang/ipc/chromium/src -I /root/firefox-clang/third_party/abseil-cpp -I /root/firefox-clang/layout/base -I /root/firefox-clang/layout/forms -I /root/firefox-clang/layout/generic -I /root/firefox-clang/layout/xul -I /root/firefox-clang/other-licenses/atk-1.0 -I /root/firefox-clang/third_party/cups/include -I /root/firefox-clang/widget -I /root/firefox-clang/widget/headless -I /root/firefox-clang/widget/x11 -I /root/firefox-clang/third_party/gbm/gbm -I /root/firefox-clang/third_party/drm/drm -I /root/firefox-clang/third_party/drm/drm/include -I /root/firefox-clang/third_party/drm/drm/include/libdrm -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -I /usr/include/gtk-3.0/unix-print -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cloudproviders -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/include/fribidi -I /usr/include/harfbuzz -I /usr/include/atk-1.0 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/glycin-2 -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/gio-unix-2.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cloudproviders -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/glycin-2 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/atk-1.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/include/fribidi -I /usr/include/pixman-1 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/gio-unix-2.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/x86_64-linux-gnu/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16/backward -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-error=pessimizing-move -Wno-error=large-by-value-copy=128 -Wno-error=implicit-int-float-conversion -Wno-error=thread-safety-analysis -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -Wno-character-conversion -std=gnu++20 -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fno-implicit-modules -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-11-12-001017-1011516-1 -x c++ /root/firefox-clang/widget/gtk/nsWindowWaylandGtk.cpp
1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5#include "nsWindowWaylandGtk.h"
6
7#include <dlfcn.h>
8
9#include "WaylandVsyncSource.h"
10#include "WidgetUtilsGtk.h"
11#include "mozilla/StaticPrefs_widget.h"
12#include "mozilla/VsyncDispatcher.h"
13#include "mozilla/gfx/Logging.h"
14#include "mozilla/webrender/WebRenderTypes.h"
15#include "nsAppShell.h"
16#include "nsGtkKeyUtils.h"
17#include "nsGtkUtils.h"
18#include "nsMenuPopupFrame.h"
19#include "nsWaylandDisplay.h"
20#include "nsWindow.h"
21
22using namespace mozilla;
23using namespace mozilla::gfx;
24using namespace mozilla::layers;
25using namespace mozilla::widget;
26
27// All nsWindowWaylandPopup instances are actually nsWindowWaylandPopupGtk, so
28// PopupAsGtk() only returns null when aPopup itself is null (e.g. end of
29// chain).
30static nsWindowWaylandPopupGtk* PopupAsGtk(nsWindowWaylandPopup* aPopup) {
31 return aPopup ? aPopup->AsGtk() : nullptr;
32}
33
34/*
35 Window restore session uses GetWorkspaceID()/MoveToWorkspace() differently
36 on Wayland.
37
38 MoveToWorkspace() is normally called when a window is visible/rendered and
39 widget code moves the window to a particular workspace. That approach doesn't
40 work on Wayland where an application can't position itself.
41
42 On Wayland we need to place the window before it's shown, so we use this
43 path instead:
44
45 1) In ConfigureToplevelWindowNative() we register an "xdg-toplevel-realized"
46 GTK signal handler to get notified when the xdg_toplevel window is created.
47 2) Block NativeShow() while mWaitingToSessionRestore is set. We can't show
48 the toplevel window until we have a window restore ID provided by a
49 MoveToWorkspace() call.
50 3) In MoveToWorkspace(), save the session ID and show the window. That fires
51 the "xdg-toplevel-realized" signal which gives us the xdg_toplevel and we
52 restore window state according to the session ID.
53
54 Likewise we use GetWorkspaceID() to create/save the xdg_toplevel session
55 for later restore.
56
57 A window which does not wait for session restore cannot be restored, so it
58 ignores MoveToWorkspace() and is added to the session under a new ID instead.
59 This happens when a previous session is restored from the menu or a closed
60 window is reopened.
61*/
62
63static struct xdg_toplevel* GetXdgToplevelFromGdkWindow(GdkWindow* aWindow) {
64 static auto sGdkWaylandWindowGetXdgToplevel =
65 (struct xdg_toplevel * (*)(GdkWindow*))
66 dlsym(RTLD_DEFAULT((void *) 0), "gdk_wayland_window_get_xdg_toplevel");
67 if (!sGdkWaylandWindowGetXdgToplevel) {
68 return nullptr;
69 }
70 return sGdkWaylandWindowGetXdgToplevel(aWindow);
71}
72
73// aRestoreWindow = true means we're loading mSessionRestoreToken
74// from already saved toplevel window state.
75// aRestoreWindow = false means we're creating a new restore session.
76bool nsWindowWaylandToplevelGtk::CreateRestoreSession(bool aRestoreWindow) {
77 MOZ_DIAGNOSTIC_ASSERT(!mSessionRestoreToken)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mSessionRestoreToken)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mSessionRestoreToken))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("!mSessionRestoreToken"
, "/root/firefox-clang/widget/gtk/nsWindowWaylandGtk.cpp", 77
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mSessionRestoreToken"
")"); do { MOZ_CrashSequence(__null, 77); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
78 GdkWindow* window = GetToplevelGdkWindow();
79 if (!window) {
80 LOG("nsWindowWaylandToplevelGtk::CreateRestoreSession(): failed to get "do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandToplevelGtk::CreateRestoreSession(): failed to get "
"GdkWindow, quit.", this->GetDebugTag().get()); } } while
(0)
81 "GdkWindow, quit.")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandToplevelGtk::CreateRestoreSession(): failed to get "
"GdkWindow, quit.", this->GetDebugTag().get()); } } while
(0)
;
82 return false;
83 }
84 struct xdg_toplevel* toplevel = GetXdgToplevelFromGdkWindow(window);
85 if (!toplevel) {
86 LOG("nsWindowWaylandToplevelGtk::CreateRestoreSession(): failed to get "do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandToplevelGtk::CreateRestoreSession(): failed to get "
"xdg-toplevel, quit.", this->GetDebugTag().get()); } } while
(0)
87 "xdg-toplevel, quit.")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandToplevelGtk::CreateRestoreSession(): failed to get "
"xdg-toplevel, quit.", this->GetDebugTag().get()); } } while
(0)
;
88 return false;
89 }
90 return CreateRestoreSessionImpl(aRestoreWindow, toplevel);
91}
92
93#ifdef MOZ_LOGGING1
94static void SessionRestoredHandler(void* aData,
95 xdg_toplevel_session_v1* aToplevelSession) {
96 LOGW("nsWindowWayland restored [%p]", aData)do { const ::mozilla::LogModule* moz_real_module = gWidgetLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "nsWindowWayland restored [%p]"
, aData); } } while (0)
;
97}
98
99static const xdg_toplevel_session_v1_listener sSessionListener = {
100 SessionRestoredHandler,
101};
102#endif
103
104void nsWindowWaylandToplevelGtk::RestoreXdgToplevel() {
105 LOG("nsWindowWaylandToplevelGtk::RestoreXdgToplevel() ID %s GdkWindow [%p]",do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandToplevelGtk::RestoreXdgToplevel() ID %s GdkWindow [%p]"
, this->GetDebugTag().get(), mWorkspaceID.get(), GetToplevelGdkWindow
()); } } while (0)
106 mWorkspaceID.get(), GetToplevelGdkWindow())do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandToplevelGtk::RestoreXdgToplevel() ID %s GdkWindow [%p]"
, this->GetDebugTag().get(), mWorkspaceID.get(), GetToplevelGdkWindow
()); } } while (0)
;
107 if (CreateRestoreSession(/* aRestoreWindow */ true)) {
108#ifdef MOZ_LOGGING1
109 if (LOG_ENABLED()((__builtin_expect(!!(mozilla::detail::log_test(gWidgetPopupLog
, mozilla::LogLevel::Debug)), 0)) || (__builtin_expect(!!(mozilla
::detail::log_test(gWidgetLog, mozilla::LogLevel::Debug)), 0)
))
) {
110 xdg_toplevel_session_v1_add_listener(mSessionRestoreToken,
111 &sSessionListener, this);
112 }
113#endif
114 }
115}
116
117void nsWindowWaylandToplevelGtk::FocusWaylandWindow(const char* aTokenID) {
118 MOZ_DIAGNOSTIC_ASSERT(aTokenID)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aTokenID)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aTokenID))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aTokenID", "/root/firefox-clang/widget/gtk/nsWindowWaylandGtk.cpp"
, 118); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aTokenID"
")"); do { MOZ_CrashSequence(__null, 118); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
119
120 LOG("nsWindowWaylandToplevelGtk::FocusWaylandWindow(%s)", aTokenID)do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandToplevelGtk::FocusWaylandWindow(%s)"
, this->GetDebugTag().get(), aTokenID); } } while (0)
;
121 if (IsDestroyed()) {
122 LOG(" already destroyed, quit.")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " already destroyed, quit.", this->
GetDebugTag().get()); } } while (0)
;
123 return;
124 }
125 wl_surface* surface =
126 mGdkWindow ? gdk_wayland_window_get_wl_surface(mGdkWindow) : nullptr;
127 if (!surface) {
128 LOG(" mGdkWindow is not visible, quit.")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " mGdkWindow is not visible, quit."
, this->GetDebugTag().get()); } } while (0)
;
129 return;
130 }
131
132 FocusWaylandWindowImpl(aTokenID, surface);
133}
134
135void nsWindowWaylandToplevelGtk::MaybeCreatePipResources() {
136 LOG("MaybeCreatePipResources()")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "MaybeCreatePipResources()", this->
GetDebugTag().get()); } } while (0)
;
137 if (!IsPipWindow()) {
138 return;
139 }
140
141 static xx_pip_v1_listener pip_listener = {
142 .closed =
143 [](void* data, xx_pip_v1*) {
144 LOGW("xx_pip_v1_listener::closed()")do { const ::mozilla::LogModule* moz_real_module = gWidgetLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "xx_pip_v1_listener::closed()"
); } } while (0)
;
145 RefPtr self = static_cast<nsWindowWaylandToplevelGtk*>(data);
146 gtk_window_close(GTK_WINDOW(self->mShell)((((GtkWindow*) (void *) ((self->mShell))))));
147 },
148 .configure_bounds =
149 [](void* data, xx_pip_v1*, int32_t w, int32_t h) {
150 LOGW("xx_pip_v1_listener::configure_bounds(%d, %d)", w, h)do { const ::mozilla::LogModule* moz_real_module = gWidgetLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "xx_pip_v1_listener::configure_bounds(%d, %d)"
, w, h); } } while (0)
;
151 },
152 .configure_size =
153 [](void* data, xx_pip_v1*, int32_t w, int32_t h) {
154 LOGW("xx_pip_v1_listener::configure_size(%d, %d)", w, h)do { const ::mozilla::LogModule* moz_real_module = gWidgetLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "xx_pip_v1_listener::configure_size(%d, %d)"
, w, h); } } while (0)
;
155 auto* self = static_cast<nsWindowWaylandToplevelGtk*>(data);
156 if (w == 0 && h == 0) {
157 gtk_window_get_size(GTK_WINDOW(self->mShell)((((GtkWindow*) (void *) ((self->mShell))))), &w, &h);
158 }
159 self->mPipResources.mConfigureSize = {w, h};
160 },
161 };
162
163 static xdg_surface_listener surface_listener = {
164 .configure =
165 [](void* data, struct xdg_surface* surface, uint32_t serial) {
166 LOGW("xdg_surface_listener::configure(%u)", serial)do { const ::mozilla::LogModule* moz_real_module = gWidgetLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "xdg_surface_listener::configure(%u)"
, serial); } } while (0)
;
167 RefPtr self = static_cast<nsWindowWaylandToplevelGtk*>(data);
168 xdg_surface_ack_configure(surface, serial);
169 auto size = self->mPipResources.mConfigureSize;
170 gtk_window_resize(GTK_WINDOW(self->mShell)((((GtkWindow*) (void *) ((self->mShell))))), size.width,
171 size.height);
172 },
173 };
174
175 auto* surf = gdk_wayland_window_get_wl_surface(GetToplevelGdkWindow());
176 MOZ_DIAGNOSTIC_ASSERT(surf, "Should have a wayland surface by now")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(surf)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(surf))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("surf" " (" "Should have a wayland surface by now"
")", "/root/firefox-clang/widget/gtk/nsWindowWaylandGtk.cpp"
, 176); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "surf"
") (" "Should have a wayland surface by now" ")"); do { MOZ_CrashSequence
(__null, 176); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
177 mPipResources.mXdgSurface =
178 xdg_wm_base_get_xdg_surface(WaylandDisplayGet()->GetXdgWm(), surf);
179 xdg_surface_add_listener(mPipResources.mXdgSurface, &surface_listener, this);
180 mPipResources.mPipSurface = xx_pip_shell_v1_get_pip(
181 WaylandDisplayGet()->GetPipShell(), mPipResources.mXdgSurface);
182 xx_pip_v1_add_listener(mPipResources.mPipSurface, &pip_listener, this);
183
184 const char* appId = !mGtkWindowAppClass.IsEmpty() ? mGtkWindowAppClass.get()
185 : gdk_get_program_class();
186 xx_pip_v1_set_app_id(mPipResources.mPipSurface, appId);
187
188 wl_surface_commit(surf);
189}
190
191void nsWindowWaylandToplevelGtk::ClearPipResources() {
192 MozClearPointer(mPipResources.mPipSurface, xx_pip_v1_destroy);
193 MozClearPointer(mPipResources.mXdgSurface, xdg_surface_destroy);
194}
195
196bool nsWindowWaylandToplevelGtk::PIPMove() {
197 if (!mPipResources.mPipSurface) {
198 return false;
199 }
200 xx_pip_v1_move(mPipResources.mPipSurface,
201 gdk_wayland_device_get_wl_seat(GdkGetPointer()),
202 nsWaylandDisplay::GetLastEventSerial());
203 return true;
204}
205
206bool nsWindowWaylandToplevelGtk::PIPResize(GdkWindowEdge aEdge) {
207 if (!mPipResources.mPipSurface) {
208 return false;
209 }
210 auto pipEdges = [&] {
211 switch (aEdge) {
212 case GDK_WINDOW_EDGE_NORTH:
213 return XX_PIP_V1_RESIZE_EDGE_TOP;
214 case GDK_WINDOW_EDGE_NORTH_WEST:
215 return XX_PIP_V1_RESIZE_EDGE_TOP_LEFT;
216 case GDK_WINDOW_EDGE_NORTH_EAST:
217 return XX_PIP_V1_RESIZE_EDGE_TOP_RIGHT;
218 case GDK_WINDOW_EDGE_SOUTH:
219 return XX_PIP_V1_RESIZE_EDGE_BOTTOM;
220 case GDK_WINDOW_EDGE_SOUTH_WEST:
221 return XX_PIP_V1_RESIZE_EDGE_BOTTOM_LEFT;
222 case GDK_WINDOW_EDGE_SOUTH_EAST:
223 return XX_PIP_V1_RESIZE_EDGE_BOTTOM_RIGHT;
224 case GDK_WINDOW_EDGE_WEST:
225 return XX_PIP_V1_RESIZE_EDGE_LEFT;
226 case GDK_WINDOW_EDGE_EAST:
227 return XX_PIP_V1_RESIZE_EDGE_RIGHT;
228 }
229 return XX_PIP_V1_RESIZE_EDGE_TOP_LEFT;
230 }();
231 xx_pip_v1_resize(mPipResources.mPipSurface,
232 gdk_wayland_device_get_wl_seat(GdkGetPointer()),
233 nsWaylandDisplay::GetLastEventSerial(), pipEdges);
234 return true;
235}
236
237void nsWindowWaylandToplevelGtk::CreateNative() {
238 LOG("nsWindowWaylandToplevelGtk::CreateNative()")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandToplevelGtk::CreateNative()"
, this->GetDebugTag().get()); } } while (0)
;
239
240 // Ensure that KeymapWrapper is created on Wayland as we need it for
241 // keyboard focus tracking.
242 KeymapWrapper::EnsureInstance();
243
244 mSurfaceProvider.Initialize(this);
245
246 // Initialize the window specific VsyncSource early in order to avoid races
247 // with BrowserParent::UpdateVsyncParentVsyncDispatcher().
248 // Only use for toplevel windows for now, see bug 1619246.
249
250 if (StaticPrefs::widget_wayland_vsync_enabled_AtStartup() &&
251 IsTopLevelWidget()) {
252 LOG_VSYNC(" create WaylandVsyncSource")do { const ::mozilla::LogModule* moz_real_module = gWidgetVsync
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "%s: " " create WaylandVsyncSource"
, GetDebugTag().get()); } } while (0)
;
253 mWaylandVsyncSource = new WaylandVsyncSource(this);
254 mWaylandVsyncSource->Init();
255 mWaylandVsyncDispatcher = new VsyncDispatcher(mWaylandVsyncSource);
256 mWaylandVsyncSource->EnableVSyncSource();
257 }
258
259 if (IsPipWindow()) {
260 // This avoids GTK from managing our top level surface role.
261 // We'll handle it manually in OnMap().
262 gdk_wayland_window_set_use_custom_surface(GetToplevelGdkWindow());
263 }
264
265 mWaitingToSessionRestore =
266 IsTopLevelWidget() &&
267 nsAppShell::UpdateAndGetSessionState() == eSessionRestoring;
268
269 LOGVERBOSE(" mWaitingToSessionRestore %d", mWaitingToSessionRestore)do { const ::mozilla::LogModule* moz_real_module = IsPopup() ?
gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Verbose
)), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "%s: " " mWaitingToSessionRestore %d", GetDebugTag
().get(), mWaitingToSessionRestore); } } while (0)
;
270}
271
272void nsWindowWaylandToplevelGtk::ConfigureToplevelWindowNative() {
273 LOG("nsWindowWaylandToplevelGtk::ConfigureToplevelWindow() register callback "do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandToplevelGtk::ConfigureToplevelWindow() register callback "
"for toplevel GdkWindow [%p]", this->GetDebugTag().get(),
GetToplevelGdkWindow()); } } while (0)
274 "for toplevel GdkWindow [%p]",do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandToplevelGtk::ConfigureToplevelWindow() register callback "
"for toplevel GdkWindow [%p]", this->GetDebugTag().get(),
GetToplevelGdkWindow()); } } while (0)
275 GetToplevelGdkWindow())do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandToplevelGtk::ConfigureToplevelWindow() register callback "
"for toplevel GdkWindow [%p]", this->GetDebugTag().get(),
GetToplevelGdkWindow()); } } while (0)
;
276 if (!mWaitingToSessionRestore) {
277 return;
278 }
279 auto* window = GetToplevelGdkWindow();
280 if (!window) {
281 LOG(" quit, missing toplevel GdkWindow!")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " quit, missing toplevel GdkWindow!"
, this->GetDebugTag().get()); } } while (0)
;
282 return;
283 }
284 MOZ_ASSERT(g_signal_lookup("xdg-toplevel-realized", G_OBJECT_TYPE(window)),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(g_signal_lookup("xdg-toplevel-realized", (((((GTypeClass
*) (((GTypeInstance*) (window))->g_class))->g_type)))))
>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(g_signal_lookup("xdg-toplevel-realized", (((((GTypeClass
*) (((GTypeInstance*) (window))->g_class))->g_type)))))
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("g_signal_lookup(\"xdg-toplevel-realized\", (((((GTypeClass*) (((GTypeInstance*) (window))->g_class))->g_type))))"
" (" "Session restore support shouldbe disabled!" ")", "/root/firefox-clang/widget/gtk/nsWindowWaylandGtk.cpp"
, 285); AnnotateMozCrashReason("MOZ_ASSERT" "(" "g_signal_lookup(\"xdg-toplevel-realized\", (((((GTypeClass*) (((GTypeInstance*) (window))->g_class))->g_type))))"
") (" "Session restore support shouldbe disabled!" ")"); do {
MOZ_CrashSequence(__null, 285); __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
285 "Session restore support shouldbe disabled!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(g_signal_lookup("xdg-toplevel-realized", (((((GTypeClass
*) (((GTypeInstance*) (window))->g_class))->g_type)))))
>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(g_signal_lookup("xdg-toplevel-realized", (((((GTypeClass
*) (((GTypeInstance*) (window))->g_class))->g_type)))))
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("g_signal_lookup(\"xdg-toplevel-realized\", (((((GTypeClass*) (((GTypeInstance*) (window))->g_class))->g_type))))"
" (" "Session restore support shouldbe disabled!" ")", "/root/firefox-clang/widget/gtk/nsWindowWaylandGtk.cpp"
, 285); AnnotateMozCrashReason("MOZ_ASSERT" "(" "g_signal_lookup(\"xdg-toplevel-realized\", (((((GTypeClass*) (((GTypeInstance*) (window))->g_class))->g_type))))"
") (" "Session restore support shouldbe disabled!" ")"); do {
MOZ_CrashSequence(__null, 285); __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
286 if (g_signal_handler_is_connected(window, mXdgToplevelRealizedID)) {
287 return;
288 }
289 mXdgToplevelRealizedID = g_signal_connect(g_signal_connect_data ((window), ("xdg-toplevel-realized"), (
((GCallback) (+[](GtkWidget* widget) -> gboolean { do { const
::mozilla::LogModule* moz_real_module = gWidgetLog; if ((__builtin_expect
(!!(mozilla::detail::log_test(moz_real_module, mozilla::LogLevel
::Debug)), 0))) { mozilla::detail::log_print(moz_real_module,
mozilla::LogLevel::Debug, "nsWindowWaylandToplevelGtk::ConfigureToplevelWindow() callback"
); } } while (0); RefPtr<nsWindowWaylandToplevelGtk> window
= static_cast<nsWindowWaylandToplevelGtk*>( nsWindow::
FromGtkWidget(widget)); if (!window) { return (0); } g_signal_handler_disconnect
(window->GetToplevelGdkWindow(), window->mXdgToplevelRealizedID
); window->mXdgToplevelRealizedID = 0; window->RestoreXdgToplevel
(); return (0); }))), (nullptr), __null, (GConnectFlags) 0)
290 window, "xdg-toplevel-realized",g_signal_connect_data ((window), ("xdg-toplevel-realized"), (
((GCallback) (+[](GtkWidget* widget) -> gboolean { do { const
::mozilla::LogModule* moz_real_module = gWidgetLog; if ((__builtin_expect
(!!(mozilla::detail::log_test(moz_real_module, mozilla::LogLevel
::Debug)), 0))) { mozilla::detail::log_print(moz_real_module,
mozilla::LogLevel::Debug, "nsWindowWaylandToplevelGtk::ConfigureToplevelWindow() callback"
); } } while (0); RefPtr<nsWindowWaylandToplevelGtk> window
= static_cast<nsWindowWaylandToplevelGtk*>( nsWindow::
FromGtkWidget(widget)); if (!window) { return (0); } g_signal_handler_disconnect
(window->GetToplevelGdkWindow(), window->mXdgToplevelRealizedID
); window->mXdgToplevelRealizedID = 0; window->RestoreXdgToplevel
(); return (0); }))), (nullptr), __null, (GConnectFlags) 0)
291 G_CALLBACK(+[](GtkWidget* widget) -> gboolean {g_signal_connect_data ((window), ("xdg-toplevel-realized"), (
((GCallback) (+[](GtkWidget* widget) -> gboolean { do { const
::mozilla::LogModule* moz_real_module = gWidgetLog; if ((__builtin_expect
(!!(mozilla::detail::log_test(moz_real_module, mozilla::LogLevel
::Debug)), 0))) { mozilla::detail::log_print(moz_real_module,
mozilla::LogLevel::Debug, "nsWindowWaylandToplevelGtk::ConfigureToplevelWindow() callback"
); } } while (0); RefPtr<nsWindowWaylandToplevelGtk> window
= static_cast<nsWindowWaylandToplevelGtk*>( nsWindow::
FromGtkWidget(widget)); if (!window) { return (0); } g_signal_handler_disconnect
(window->GetToplevelGdkWindow(), window->mXdgToplevelRealizedID
); window->mXdgToplevelRealizedID = 0; window->RestoreXdgToplevel
(); return (0); }))), (nullptr), __null, (GConnectFlags) 0)
292 LOGW("nsWindowWaylandToplevelGtk::ConfigureToplevelWindow() callback");g_signal_connect_data ((window), ("xdg-toplevel-realized"), (
((GCallback) (+[](GtkWidget* widget) -> gboolean { do { const
::mozilla::LogModule* moz_real_module = gWidgetLog; if ((__builtin_expect
(!!(mozilla::detail::log_test(moz_real_module, mozilla::LogLevel
::Debug)), 0))) { mozilla::detail::log_print(moz_real_module,
mozilla::LogLevel::Debug, "nsWindowWaylandToplevelGtk::ConfigureToplevelWindow() callback"
); } } while (0); RefPtr<nsWindowWaylandToplevelGtk> window
= static_cast<nsWindowWaylandToplevelGtk*>( nsWindow::
FromGtkWidget(widget)); if (!window) { return (0); } g_signal_handler_disconnect
(window->GetToplevelGdkWindow(), window->mXdgToplevelRealizedID
); window->mXdgToplevelRealizedID = 0; window->RestoreXdgToplevel
(); return (0); }))), (nullptr), __null, (GConnectFlags) 0)
293 RefPtr<nsWindowWaylandToplevelGtk> window =g_signal_connect_data ((window), ("xdg-toplevel-realized"), (
((GCallback) (+[](GtkWidget* widget) -> gboolean { do { const
::mozilla::LogModule* moz_real_module = gWidgetLog; if ((__builtin_expect
(!!(mozilla::detail::log_test(moz_real_module, mozilla::LogLevel
::Debug)), 0))) { mozilla::detail::log_print(moz_real_module,
mozilla::LogLevel::Debug, "nsWindowWaylandToplevelGtk::ConfigureToplevelWindow() callback"
); } } while (0); RefPtr<nsWindowWaylandToplevelGtk> window
= static_cast<nsWindowWaylandToplevelGtk*>( nsWindow::
FromGtkWidget(widget)); if (!window) { return (0); } g_signal_handler_disconnect
(window->GetToplevelGdkWindow(), window->mXdgToplevelRealizedID
); window->mXdgToplevelRealizedID = 0; window->RestoreXdgToplevel
(); return (0); }))), (nullptr), __null, (GConnectFlags) 0)
294 static_cast<nsWindowWaylandToplevelGtk*>(g_signal_connect_data ((window), ("xdg-toplevel-realized"), (
((GCallback) (+[](GtkWidget* widget) -> gboolean { do { const
::mozilla::LogModule* moz_real_module = gWidgetLog; if ((__builtin_expect
(!!(mozilla::detail::log_test(moz_real_module, mozilla::LogLevel
::Debug)), 0))) { mozilla::detail::log_print(moz_real_module,
mozilla::LogLevel::Debug, "nsWindowWaylandToplevelGtk::ConfigureToplevelWindow() callback"
); } } while (0); RefPtr<nsWindowWaylandToplevelGtk> window
= static_cast<nsWindowWaylandToplevelGtk*>( nsWindow::
FromGtkWidget(widget)); if (!window) { return (0); } g_signal_handler_disconnect
(window->GetToplevelGdkWindow(), window->mXdgToplevelRealizedID
); window->mXdgToplevelRealizedID = 0; window->RestoreXdgToplevel
(); return (0); }))), (nullptr), __null, (GConnectFlags) 0)
295 nsWindow::FromGtkWidget(widget));g_signal_connect_data ((window), ("xdg-toplevel-realized"), (
((GCallback) (+[](GtkWidget* widget) -> gboolean { do { const
::mozilla::LogModule* moz_real_module = gWidgetLog; if ((__builtin_expect
(!!(mozilla::detail::log_test(moz_real_module, mozilla::LogLevel
::Debug)), 0))) { mozilla::detail::log_print(moz_real_module,
mozilla::LogLevel::Debug, "nsWindowWaylandToplevelGtk::ConfigureToplevelWindow() callback"
); } } while (0); RefPtr<nsWindowWaylandToplevelGtk> window
= static_cast<nsWindowWaylandToplevelGtk*>( nsWindow::
FromGtkWidget(widget)); if (!window) { return (0); } g_signal_handler_disconnect
(window->GetToplevelGdkWindow(), window->mXdgToplevelRealizedID
); window->mXdgToplevelRealizedID = 0; window->RestoreXdgToplevel
(); return (0); }))), (nullptr), __null, (GConnectFlags) 0)
296 if (!window) {g_signal_connect_data ((window), ("xdg-toplevel-realized"), (
((GCallback) (+[](GtkWidget* widget) -> gboolean { do { const
::mozilla::LogModule* moz_real_module = gWidgetLog; if ((__builtin_expect
(!!(mozilla::detail::log_test(moz_real_module, mozilla::LogLevel
::Debug)), 0))) { mozilla::detail::log_print(moz_real_module,
mozilla::LogLevel::Debug, "nsWindowWaylandToplevelGtk::ConfigureToplevelWindow() callback"
); } } while (0); RefPtr<nsWindowWaylandToplevelGtk> window
= static_cast<nsWindowWaylandToplevelGtk*>( nsWindow::
FromGtkWidget(widget)); if (!window) { return (0); } g_signal_handler_disconnect
(window->GetToplevelGdkWindow(), window->mXdgToplevelRealizedID
); window->mXdgToplevelRealizedID = 0; window->RestoreXdgToplevel
(); return (0); }))), (nullptr), __null, (GConnectFlags) 0)
297 return FALSE;g_signal_connect_data ((window), ("xdg-toplevel-realized"), (
((GCallback) (+[](GtkWidget* widget) -> gboolean { do { const
::mozilla::LogModule* moz_real_module = gWidgetLog; if ((__builtin_expect
(!!(mozilla::detail::log_test(moz_real_module, mozilla::LogLevel
::Debug)), 0))) { mozilla::detail::log_print(moz_real_module,
mozilla::LogLevel::Debug, "nsWindowWaylandToplevelGtk::ConfigureToplevelWindow() callback"
); } } while (0); RefPtr<nsWindowWaylandToplevelGtk> window
= static_cast<nsWindowWaylandToplevelGtk*>( nsWindow::
FromGtkWidget(widget)); if (!window) { return (0); } g_signal_handler_disconnect
(window->GetToplevelGdkWindow(), window->mXdgToplevelRealizedID
); window->mXdgToplevelRealizedID = 0; window->RestoreXdgToplevel
(); return (0); }))), (nullptr), __null, (GConnectFlags) 0)
298 }g_signal_connect_data ((window), ("xdg-toplevel-realized"), (
((GCallback) (+[](GtkWidget* widget) -> gboolean { do { const
::mozilla::LogModule* moz_real_module = gWidgetLog; if ((__builtin_expect
(!!(mozilla::detail::log_test(moz_real_module, mozilla::LogLevel
::Debug)), 0))) { mozilla::detail::log_print(moz_real_module,
mozilla::LogLevel::Debug, "nsWindowWaylandToplevelGtk::ConfigureToplevelWindow() callback"
); } } while (0); RefPtr<nsWindowWaylandToplevelGtk> window
= static_cast<nsWindowWaylandToplevelGtk*>( nsWindow::
FromGtkWidget(widget)); if (!window) { return (0); } g_signal_handler_disconnect
(window->GetToplevelGdkWindow(), window->mXdgToplevelRealizedID
); window->mXdgToplevelRealizedID = 0; window->RestoreXdgToplevel
(); return (0); }))), (nullptr), __null, (GConnectFlags) 0)
299
300 g_signal_handler_disconnect(window->GetToplevelGdkWindow(),g_signal_connect_data ((window), ("xdg-toplevel-realized"), (
((GCallback) (+[](GtkWidget* widget) -> gboolean { do { const
::mozilla::LogModule* moz_real_module = gWidgetLog; if ((__builtin_expect
(!!(mozilla::detail::log_test(moz_real_module, mozilla::LogLevel
::Debug)), 0))) { mozilla::detail::log_print(moz_real_module,
mozilla::LogLevel::Debug, "nsWindowWaylandToplevelGtk::ConfigureToplevelWindow() callback"
); } } while (0); RefPtr<nsWindowWaylandToplevelGtk> window
= static_cast<nsWindowWaylandToplevelGtk*>( nsWindow::
FromGtkWidget(widget)); if (!window) { return (0); } g_signal_handler_disconnect
(window->GetToplevelGdkWindow(), window->mXdgToplevelRealizedID
); window->mXdgToplevelRealizedID = 0; window->RestoreXdgToplevel
(); return (0); }))), (nullptr), __null, (GConnectFlags) 0)
301 window->mXdgToplevelRealizedID);g_signal_connect_data ((window), ("xdg-toplevel-realized"), (
((GCallback) (+[](GtkWidget* widget) -> gboolean { do { const
::mozilla::LogModule* moz_real_module = gWidgetLog; if ((__builtin_expect
(!!(mozilla::detail::log_test(moz_real_module, mozilla::LogLevel
::Debug)), 0))) { mozilla::detail::log_print(moz_real_module,
mozilla::LogLevel::Debug, "nsWindowWaylandToplevelGtk::ConfigureToplevelWindow() callback"
); } } while (0); RefPtr<nsWindowWaylandToplevelGtk> window
= static_cast<nsWindowWaylandToplevelGtk*>( nsWindow::
FromGtkWidget(widget)); if (!window) { return (0); } g_signal_handler_disconnect
(window->GetToplevelGdkWindow(), window->mXdgToplevelRealizedID
); window->mXdgToplevelRealizedID = 0; window->RestoreXdgToplevel
(); return (0); }))), (nullptr), __null, (GConnectFlags) 0)
302 window->mXdgToplevelRealizedID = 0;g_signal_connect_data ((window), ("xdg-toplevel-realized"), (
((GCallback) (+[](GtkWidget* widget) -> gboolean { do { const
::mozilla::LogModule* moz_real_module = gWidgetLog; if ((__builtin_expect
(!!(mozilla::detail::log_test(moz_real_module, mozilla::LogLevel
::Debug)), 0))) { mozilla::detail::log_print(moz_real_module,
mozilla::LogLevel::Debug, "nsWindowWaylandToplevelGtk::ConfigureToplevelWindow() callback"
); } } while (0); RefPtr<nsWindowWaylandToplevelGtk> window
= static_cast<nsWindowWaylandToplevelGtk*>( nsWindow::
FromGtkWidget(widget)); if (!window) { return (0); } g_signal_handler_disconnect
(window->GetToplevelGdkWindow(), window->mXdgToplevelRealizedID
); window->mXdgToplevelRealizedID = 0; window->RestoreXdgToplevel
(); return (0); }))), (nullptr), __null, (GConnectFlags) 0)
303
304 window->RestoreXdgToplevel();g_signal_connect_data ((window), ("xdg-toplevel-realized"), (
((GCallback) (+[](GtkWidget* widget) -> gboolean { do { const
::mozilla::LogModule* moz_real_module = gWidgetLog; if ((__builtin_expect
(!!(mozilla::detail::log_test(moz_real_module, mozilla::LogLevel
::Debug)), 0))) { mozilla::detail::log_print(moz_real_module,
mozilla::LogLevel::Debug, "nsWindowWaylandToplevelGtk::ConfigureToplevelWindow() callback"
); } } while (0); RefPtr<nsWindowWaylandToplevelGtk> window
= static_cast<nsWindowWaylandToplevelGtk*>( nsWindow::
FromGtkWidget(widget)); if (!window) { return (0); } g_signal_handler_disconnect
(window->GetToplevelGdkWindow(), window->mXdgToplevelRealizedID
); window->mXdgToplevelRealizedID = 0; window->RestoreXdgToplevel
(); return (0); }))), (nullptr), __null, (GConnectFlags) 0)
305 return FALSE;g_signal_connect_data ((window), ("xdg-toplevel-realized"), (
((GCallback) (+[](GtkWidget* widget) -> gboolean { do { const
::mozilla::LogModule* moz_real_module = gWidgetLog; if ((__builtin_expect
(!!(mozilla::detail::log_test(moz_real_module, mozilla::LogLevel
::Debug)), 0))) { mozilla::detail::log_print(moz_real_module,
mozilla::LogLevel::Debug, "nsWindowWaylandToplevelGtk::ConfigureToplevelWindow() callback"
); } } while (0); RefPtr<nsWindowWaylandToplevelGtk> window
= static_cast<nsWindowWaylandToplevelGtk*>( nsWindow::
FromGtkWidget(widget)); if (!window) { return (0); } g_signal_handler_disconnect
(window->GetToplevelGdkWindow(), window->mXdgToplevelRealizedID
); window->mXdgToplevelRealizedID = 0; window->RestoreXdgToplevel
(); return (0); }))), (nullptr), __null, (GConnectFlags) 0)
306 }),g_signal_connect_data ((window), ("xdg-toplevel-realized"), (
((GCallback) (+[](GtkWidget* widget) -> gboolean { do { const
::mozilla::LogModule* moz_real_module = gWidgetLog; if ((__builtin_expect
(!!(mozilla::detail::log_test(moz_real_module, mozilla::LogLevel
::Debug)), 0))) { mozilla::detail::log_print(moz_real_module,
mozilla::LogLevel::Debug, "nsWindowWaylandToplevelGtk::ConfigureToplevelWindow() callback"
); } } while (0); RefPtr<nsWindowWaylandToplevelGtk> window
= static_cast<nsWindowWaylandToplevelGtk*>( nsWindow::
FromGtkWidget(widget)); if (!window) { return (0); } g_signal_handler_disconnect
(window->GetToplevelGdkWindow(), window->mXdgToplevelRealizedID
); window->mXdgToplevelRealizedID = 0; window->RestoreXdgToplevel
(); return (0); }))), (nullptr), __null, (GConnectFlags) 0)
307 nullptr)g_signal_connect_data ((window), ("xdg-toplevel-realized"), (
((GCallback) (+[](GtkWidget* widget) -> gboolean { do { const
::mozilla::LogModule* moz_real_module = gWidgetLog; if ((__builtin_expect
(!!(mozilla::detail::log_test(moz_real_module, mozilla::LogLevel
::Debug)), 0))) { mozilla::detail::log_print(moz_real_module,
mozilla::LogLevel::Debug, "nsWindowWaylandToplevelGtk::ConfigureToplevelWindow() callback"
); } } while (0); RefPtr<nsWindowWaylandToplevelGtk> window
= static_cast<nsWindowWaylandToplevelGtk*>( nsWindow::
FromGtkWidget(widget)); if (!window) { return (0); } g_signal_handler_disconnect
(window->GetToplevelGdkWindow(), window->mXdgToplevelRealizedID
); window->mXdgToplevelRealizedID = 0; window->RestoreXdgToplevel
(); return (0); }))), (nullptr), __null, (GConnectFlags) 0)
;
308}
309
310void nsWindowWaylandToplevelGtk::DestroyNative() {
311 LOG("nsWindowWaylandToplevelGtk::DestroyNative()")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandToplevelGtk::DestroyNative()"
, this->GetDebugTag().get()); } } while (0)
;
312 if (mXdgToplevelRealizedID) {
313 g_signal_handler_disconnect(GetToplevelGdkWindow(), mXdgToplevelRealizedID);
314 mXdgToplevelRealizedID = 0;
315 }
316 MozClearPointer(mSessionRestoreToken, xdg_toplevel_session_v1_destroy);
317 ClearPipResources();
318
319 // Shut down our local vsync source
320 // Also drops reference to nsWindow::mSurface.
321 if (mWaylandVsyncSource) {
322 mWaylandVsyncSource->Shutdown();
323 mWaylandVsyncSource = nullptr;
324 }
325 mWaylandVsyncDispatcher = nullptr;
326 UnlockNativePointer();
327}
328
329void nsWindowWaylandToplevelGtk::NativeShow(bool aAction) {
330 if (aAction) {
331 mNeedsShow = true;
332 if (mWaitingToSessionRestore) {
333 LOG("nsWindowWaylandToplevelGtk::NativeShow() waiting to session "do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandToplevelGtk::NativeShow() waiting to session "
"restore, " "quit.", this->GetDebugTag().get()); } } while
(0)
334 "restore, "do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandToplevelGtk::NativeShow() waiting to session "
"restore, " "quit.", this->GetDebugTag().get()); } } while
(0)
335 "quit.")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandToplevelGtk::NativeShow() waiting to session "
"restore, " "quit.", this->GetDebugTag().get()); } } while
(0)
;
336 if (nsAppShell::UpdateAndGetSessionState() == eSessionRestoring) {
337 return;
338 }
339 mWaitingToSessionRestore = false;
340 NS_WARNING("Wayland session restore failed!")NS_DebugBreak(NS_DEBUG_WARNING, "Wayland session restore failed!"
, nullptr, "/root/firefox-clang/widget/gtk/nsWindowWaylandGtk.cpp"
, 340)
;
341 }
342
343 LOG("nsWindowWaylandToplevelGtk::NativeShow show\n")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandToplevelGtk::NativeShow show\n"
, this->GetDebugTag().get()); } } while (0)
;
344
345 gtk_widget_show(mShell);
346 SetUserTimeAndStartupTokenForActivatedWindow();
347
348 auto token = std::move(mWindowActivationTokenFromEnv);
349 if (!token.IsEmpty()) {
350 FocusWaylandWindow(token.get());
351 } else {
352 TransferFocusTo();
353 }
354 mNeedsShow = false;
355 } else {
356 LOG("nsWindowWaylandToplevelGtk::NativeShow hide\n")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandToplevelGtk::NativeShow hide\n"
, this->GetDebugTag().get()); } } while (0)
;
357 // Close any popups left open on top of us before we disappear.
358 HideAndRemoveAppPopups();
359 gtk_widget_hide(mShell);
360 }
361}
362
363// Apply workaround for Mutter compositor bug (mzbz#1777269).
364//
365// When we open a popup window (tooltip for instance) attached to
366// GDK_WINDOW_TYPE_HINT_UTILITY parent popup, Mutter compositor sends bogus
367// leave/enter events to the GDK_WINDOW_TYPE_HINT_UTILITY popup.
368// That leads to immediate tooltip close. As a workaround ignore these
369// bogus events.
370//
371// We need to check two affected window types:
372//
373// - toplevel window with at least two child popups where the first one is
374// GDK_WINDOW_TYPE_HINT_UTILITY.
375// - GDK_WINDOW_TYPE_HINT_UTILITY popup with a child popup
376//
377// We need to mask two bogus leave/enter sequences:
378// 1) Leave (popup) -> Enter (toplevel)
379// 2) Leave (toplevel) -> Enter (popup)
380//
381// TODO: persistent (non-tracked) popups with tooltip/child popups?
382//
383bool nsWindowWaylandToplevelGtk::ApplyEnterLeaveMutterWorkaround() {
384 // Leave (toplevel) case
385 auto* firstPopup = GetFirstPopup();
386 if (mWindowType == WindowType::TopLevel && firstPopup &&
387 !firstPopup->IsLastPopup() &&
388 gtk_window_get_type_hint(GTK_WINDOW(firstPopup->GetGtkWidget())((((GtkWindow*) (void *) ((firstPopup->GetGtkWidget())))))) ==
389 GDK_WINDOW_TYPE_HINT_UTILITY) {
390 LOG("nsWindowWaylandToplevelGtk::ApplyEnterLeaveMutterWorkaround(): leave "do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandToplevelGtk::ApplyEnterLeaveMutterWorkaround(): leave "
"toplevel", this->GetDebugTag().get()); } } while (0)
391 "toplevel")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandToplevelGtk::ApplyEnterLeaveMutterWorkaround(): leave "
"toplevel", this->GetDebugTag().get()); } } while (0)
;
392 return true;
393 }
394 return false;
395}
396
397void nsWindowWaylandToplevelGtk::OnMapNative() { MaybeCreatePipResources(); }
398
399void nsWindowWaylandToplevelGtk::HideAndRemoveAppPopups() {
400 // Hide back-to-front so child popups close before their parents.
401 auto* popup = FindLastWindow(this)->AsWaylandPopup();
402 while (popup) {
403 auto* prev = popup->GetPrevPopup();
404 popup->HidePopupWindow(/* aTemporaryHide */ false,
405 /* aRemoveFromPopupList */ true);
406 popup = prev;
407 }
408}
409
410// ----------------------------------------------------------------------
411// nsWindowWaylandPopupGtk
412// ----------------------------------------------------------------------
413
414nsWindowWaylandPopupGtk::nsWindowWaylandPopupGtk()
415 : mWaylandApplyPopupPositionBeforeShow(true) {}
416
417void nsWindowWaylandPopupGtk::CreateNative() {
418 LOG("nsWindowWaylandPopupGtk::CreateNative()")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandPopupGtk::CreateNative()"
, this->GetDebugTag().get()); } } while (0)
;
419
420 // Ensure that KeymapWrapper is created on Wayland as we need it for
421 // keyboard focus tracking.
422 KeymapWrapper::EnsureInstance();
423
424 mSurfaceProvider.Initialize(this);
425}
426
427void nsWindowWaylandPopupGtk::DestroyNative() {
428 LOG("nsWindowWaylandPopupGtk::DestroyNative()")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandPopupGtk::DestroyNative()"
, this->GetDebugTag().get()); } } while (0)
;
429 UnlockNativePointer();
430}
431
432bool nsWindowWaylandPopupGtk::WaylandPopupAnchorAdjustForParentPopup(
433 GdkRectangle* aPopupAnchor, GdkPoint* aOffset) {
434 LOG("nsWindowWaylandPopupGtk::WaylandPopupAnchorAdjustForParentPopup")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandPopupGtk::WaylandPopupAnchorAdjustForParentPopup"
, this->GetDebugTag().get()); } } while (0)
;
435
436 GtkWindow* parentGtkWindow = gtk_window_get_transient_for(GTK_WINDOW(mShell)((((GtkWindow*) (void *) ((mShell))))));
437 if (!parentGtkWindow || !GTK_IS_WIDGET(parentGtkWindow)(((__extension__ ({ GTypeInstance *_inst = (GTypeInstance*) (
(parentGtkWindow)); GType _t = ((gtk_widget_get_type ())); gboolean
_r; if (!_inst) _r = (0); else if (_inst->g_class &&
_inst->g_class->g_type == _t) _r = (!(0)); else _r = g_type_check_instance_is_a
(_inst, _t); _r; }))))
) {
438 NS_WARNING("Popup has no parent!")NS_DebugBreak(NS_DEBUG_WARNING, "Popup has no parent!", nullptr
, "/root/firefox-clang/widget/gtk/nsWindowWaylandGtk.cpp", 438
)
;
439 return false;
440 }
441 GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(parentGtkWindow)((((GtkWidget*) (void *) ((parentGtkWindow))))));
442 if (!window) {
443 NS_WARNING("Popup parrent is not mapped!")NS_DebugBreak(NS_DEBUG_WARNING, "Popup parrent is not mapped!"
, nullptr, "/root/firefox-clang/widget/gtk/nsWindowWaylandGtk.cpp"
, 443)
;
444 return false;
445 }
446
447 GdkRectangle parentWindowRect = {0, 0, gdk_window_get_width(window),
448 gdk_window_get_height(window)};
449 LOG(" parent window size %d x %d", parentWindowRect.width,do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " parent window size %d x %d", this
->GetDebugTag().get(), parentWindowRect.width, parentWindowRect
.height); } } while (0)
450 parentWindowRect.height)do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " parent window size %d x %d", this
->GetDebugTag().get(), parentWindowRect.width, parentWindowRect
.height); } } while (0)
;
451
452 // We can't have rectangle anchor with zero width/height.
453 if (!aPopupAnchor->width) {
454 aPopupAnchor->width = 1;
455 }
456 if (!aPopupAnchor->height) {
457 aPopupAnchor->height = 1;
458 }
459
460 GdkRectangle finalRect;
461 if (!gdk_rectangle_intersect(aPopupAnchor, &parentWindowRect, &finalRect)) {
462 return false;
463 }
464 *aPopupAnchor = finalRect;
465 LOG(" anchor is correct %d,%d -> %d x %d", finalRect.x, finalRect.y,do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " anchor is correct %d,%d -> %d x %d"
, this->GetDebugTag().get(), finalRect.x, finalRect.y, finalRect
.width, finalRect.height); } } while (0)
466 finalRect.width, finalRect.height)do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " anchor is correct %d,%d -> %d x %d"
, this->GetDebugTag().get(), finalRect.x, finalRect.y, finalRect
.width, finalRect.height); } } while (0)
;
467
468 *aOffset = mPopupMoveToRectParams.mOffset;
469 LOG(" anchor offset %d, %d", aOffset->x, aOffset->y)do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " anchor offset %d, %d", this->
GetDebugTag().get(), aOffset->x, aOffset->y); } } while
(0)
;
470 return true;
471}
472
473bool nsWindowWaylandPopupGtk::WaylandPopupCheckAndGetAnchor(
474 GdkRectangle* aPopupAnchor, GdkPoint* aOffset) {
475 LOG("nsWindowWaylandPopupGtk::WaylandPopupCheckAndGetAnchor")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandPopupGtk::WaylandPopupCheckAndGetAnchor"
, this->GetDebugTag().get()); } } while (0)
;
476
477 GdkWindow* gdkWindow = GetToplevelGdkWindow();
478 nsMenuPopupFrame* popupFrame = GetPopupFrame();
479 if (!gdkWindow || !popupFrame) {
480 LOG(" can't use move-to-rect due missing gdkWindow or popupFrame")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " can't use move-to-rect due missing gdkWindow or popupFrame"
, this->GetDebugTag().get()); } } while (0)
;
481 return false;
482 }
483
484 if (popupFrame->IsConstrainedByLayout()) {
485 LOG(" can't use move-to-rect, flipped / constrained by layout")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " can't use move-to-rect, flipped / constrained by layout"
, this->GetDebugTag().get()); } } while (0)
;
486 return false;
487 }
488
489 if (!mPopupMoveToRectParams.mAnchorSet) {
490 mPopupMoveToRectParams = WaylandPopupGetPositionFromLayout();
491 }
492
493 // Update popup layout coordinates from layout by recent popup hierarchy
494 // (calculate correct position according to parent window)
495 // and convert to Gtk coordinates.
496 DesktopIntRect anchorRect =
497 ToDesktopPixels(mPopupMoveToRectParams.mAnchorRect);
498 if (!WaylandPopupIsFirst()) {
499 DesktopIntPoint parent = WaylandGetParentPosition();
500 LOG(" subtract parent position from anchor [%d, %d]\n", parent.x.value,do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " subtract parent position from anchor [%d, %d]\n"
, this->GetDebugTag().get(), parent.x.value, parent.y.value
); } } while (0)
501 parent.y.value)do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " subtract parent position from anchor [%d, %d]\n"
, this->GetDebugTag().get(), parent.x.value, parent.y.value
); } } while (0)
;
502 anchorRect.MoveBy(-parent);
503 }
504
505 *aPopupAnchor = GdkRectangle{anchorRect.x, anchorRect.y, anchorRect.width,
506 anchorRect.height};
507 LOG(" anchored to rectangle [%d, %d] -> [%d x %d]", aPopupAnchor->x,do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " anchored to rectangle [%d, %d] -> [%d x %d]"
, this->GetDebugTag().get(), aPopupAnchor->x, aPopupAnchor
->y, aPopupAnchor->width, aPopupAnchor->height); } }
while (0)
508 aPopupAnchor->y, aPopupAnchor->width, aPopupAnchor->height)do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " anchored to rectangle [%d, %d] -> [%d x %d]"
, this->GetDebugTag().get(), aPopupAnchor->x, aPopupAnchor
->y, aPopupAnchor->width, aPopupAnchor->height); } }
while (0)
;
509
510 if (!WaylandPopupAnchorAdjustForParentPopup(aPopupAnchor, aOffset)) {
511 LOG(" can't use move-to-rect, anchor is not placed inside of parent "do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " can't use move-to-rect, anchor is not placed inside of parent "
"window", this->GetDebugTag().get()); } } while (0)
512 "window")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " can't use move-to-rect, anchor is not placed inside of parent "
"window", this->GetDebugTag().get()); } } while (0)
;
513 return false;
514 }
515
516 return true;
517}
518
519void nsWindowWaylandPopupGtk::WaylandPopupPrepareForMove() {
520 LOG("nsWindowWaylandPopupGtk::WaylandPopupPrepareForMove()")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandPopupGtk::WaylandPopupPrepareForMove()"
, this->GetDebugTag().get()); } } while (0)
;
521
522 if (mPopupType == PopupType::Tooltip) {
523 // Don't fiddle with tooltips type, just hide it before move-to-rect
524 if (mPopupUseMoveToRect && gtk_widget_is_visible(mShell)) {
525 HidePopupWindow(/* aTemporaryHide */ true,
526 /* aRemoveFromPopupList */ false);
527 }
528 LOG(" it's tooltip, quit")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " it's tooltip, quit", this->GetDebugTag
().get()); } } while (0)
;
529 return;
530 }
531
532 // See https://bugzilla.mozilla.org/show_bug.cgi?id=1785185#c8
533 // gtk_window_move() needs GDK_WINDOW_TYPE_HINT_UTILITY popup type.
534 // move-to-rect requires GDK_WINDOW_TYPE_HINT_POPUP_MENU popups type.
535 // We need to set it before map event when popup is hidden.
536 const GdkWindowTypeHint currentType =
537 gtk_window_get_type_hint(GTK_WINDOW(mShell)((((GtkWindow*) (void *) ((mShell))))));
538 const GdkWindowTypeHint requiredType = mPopupUseMoveToRect
539 ? GDK_WINDOW_TYPE_HINT_POPUP_MENU
540 : GDK_WINDOW_TYPE_HINT_UTILITY;
541
542 if (!mPopupUseMoveToRect && currentType == requiredType) {
543 LOG(" type matches and we're not forced to hide it, quit.")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " type matches and we're not forced to hide it, quit."
, this->GetDebugTag().get()); } } while (0)
;
544 return;
545 }
546
547 if (gtk_widget_is_visible(mShell)) {
548 HidePopupWindow(/* aTemporaryHide */ true,
549 /* aRemoveFromPopupList */ false);
550 }
551
552 if (currentType != requiredType) {
553 LOG(" set type %s",do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " set type %s", this->GetDebugTag
().get(), requiredType == GDK_WINDOW_TYPE_HINT_POPUP_MENU ? "MENU"
: "UTILITY"); } } while (0)
554 requiredType == GDK_WINDOW_TYPE_HINT_POPUP_MENU ? "MENU" : "UTILITY")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " set type %s", this->GetDebugTag
().get(), requiredType == GDK_WINDOW_TYPE_HINT_POPUP_MENU ? "MENU"
: "UTILITY"); } } while (0)
;
555 gtk_window_set_type_hint(GTK_WINDOW(mShell)((((GtkWindow*) (void *) ((mShell))))), requiredType);
556 }
557}
558
559// Plain popup move on Wayland - simply place popup on given location.
560// We can't just call gtk_window_move() as it's not effective on visible
561// popups.
562void nsWindowWaylandPopupGtk::WaylandPopupMovePlain(int aX, int aY) {
563 LOG("nsWindowWaylandPopupGtk::WaylandPopupMovePlain(%d, %d)", aX, aY)do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandPopupGtk::WaylandPopupMovePlain(%d, %d)"
, this->GetDebugTag().get(), aX, aY); } } while (0)
;
564
565 // We can directly move only popups based on wl_subsurface type.
566 MOZ_DIAGNOSTIC_ASSERT(gtk_window_get_type_hint(GTK_WINDOW(mShell)) ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype(gtk_window_get_type_hint(((((GtkWindow*) (void *) ((
mShell)))))) == GDK_WINDOW_TYPE_HINT_UTILITY || gtk_window_get_type_hint
(((((GtkWindow*) (void *) ((mShell)))))) == GDK_WINDOW_TYPE_HINT_TOOLTIP
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(gtk_window_get_type_hint(((((GtkWindow*) (void *) ((
mShell)))))) == GDK_WINDOW_TYPE_HINT_UTILITY || gtk_window_get_type_hint
(((((GtkWindow*) (void *) ((mShell)))))) == GDK_WINDOW_TYPE_HINT_TOOLTIP
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"gtk_window_get_type_hint(((((GtkWindow*) (void *) ((mShell)))))) == GDK_WINDOW_TYPE_HINT_UTILITY || gtk_window_get_type_hint(((((GtkWindow*) (void *) ((mShell)))))) == GDK_WINDOW_TYPE_HINT_TOOLTIP"
, "/root/firefox-clang/widget/gtk/nsWindowWaylandGtk.cpp", 569
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "gtk_window_get_type_hint(((((GtkWindow*) (void *) ((mShell)))))) == GDK_WINDOW_TYPE_HINT_UTILITY || gtk_window_get_type_hint(((((GtkWindow*) (void *) ((mShell)))))) == GDK_WINDOW_TYPE_HINT_TOOLTIP"
")"); do { MOZ_CrashSequence(__null, 569); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
567 GDK_WINDOW_TYPE_HINT_UTILITY ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(gtk_window_get_type_hint(((((GtkWindow*) (void *) ((
mShell)))))) == GDK_WINDOW_TYPE_HINT_UTILITY || gtk_window_get_type_hint
(((((GtkWindow*) (void *) ((mShell)))))) == GDK_WINDOW_TYPE_HINT_TOOLTIP
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(gtk_window_get_type_hint(((((GtkWindow*) (void *) ((
mShell)))))) == GDK_WINDOW_TYPE_HINT_UTILITY || gtk_window_get_type_hint
(((((GtkWindow*) (void *) ((mShell)))))) == GDK_WINDOW_TYPE_HINT_TOOLTIP
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"gtk_window_get_type_hint(((((GtkWindow*) (void *) ((mShell)))))) == GDK_WINDOW_TYPE_HINT_UTILITY || gtk_window_get_type_hint(((((GtkWindow*) (void *) ((mShell)))))) == GDK_WINDOW_TYPE_HINT_TOOLTIP"
, "/root/firefox-clang/widget/gtk/nsWindowWaylandGtk.cpp", 569
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "gtk_window_get_type_hint(((((GtkWindow*) (void *) ((mShell)))))) == GDK_WINDOW_TYPE_HINT_UTILITY || gtk_window_get_type_hint(((((GtkWindow*) (void *) ((mShell)))))) == GDK_WINDOW_TYPE_HINT_TOOLTIP"
")"); do { MOZ_CrashSequence(__null, 569); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
568 gtk_window_get_type_hint(GTK_WINDOW(mShell)) ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype(gtk_window_get_type_hint(((((GtkWindow*) (void *) ((
mShell)))))) == GDK_WINDOW_TYPE_HINT_UTILITY || gtk_window_get_type_hint
(((((GtkWindow*) (void *) ((mShell)))))) == GDK_WINDOW_TYPE_HINT_TOOLTIP
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(gtk_window_get_type_hint(((((GtkWindow*) (void *) ((
mShell)))))) == GDK_WINDOW_TYPE_HINT_UTILITY || gtk_window_get_type_hint
(((((GtkWindow*) (void *) ((mShell)))))) == GDK_WINDOW_TYPE_HINT_TOOLTIP
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"gtk_window_get_type_hint(((((GtkWindow*) (void *) ((mShell)))))) == GDK_WINDOW_TYPE_HINT_UTILITY || gtk_window_get_type_hint(((((GtkWindow*) (void *) ((mShell)))))) == GDK_WINDOW_TYPE_HINT_TOOLTIP"
, "/root/firefox-clang/widget/gtk/nsWindowWaylandGtk.cpp", 569
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "gtk_window_get_type_hint(((((GtkWindow*) (void *) ((mShell)))))) == GDK_WINDOW_TYPE_HINT_UTILITY || gtk_window_get_type_hint(((((GtkWindow*) (void *) ((mShell)))))) == GDK_WINDOW_TYPE_HINT_TOOLTIP"
")"); do { MOZ_CrashSequence(__null, 569); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
569 GDK_WINDOW_TYPE_HINT_TOOLTIP)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(gtk_window_get_type_hint(((((GtkWindow*) (void *) ((
mShell)))))) == GDK_WINDOW_TYPE_HINT_UTILITY || gtk_window_get_type_hint
(((((GtkWindow*) (void *) ((mShell)))))) == GDK_WINDOW_TYPE_HINT_TOOLTIP
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(gtk_window_get_type_hint(((((GtkWindow*) (void *) ((
mShell)))))) == GDK_WINDOW_TYPE_HINT_UTILITY || gtk_window_get_type_hint
(((((GtkWindow*) (void *) ((mShell)))))) == GDK_WINDOW_TYPE_HINT_TOOLTIP
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"gtk_window_get_type_hint(((((GtkWindow*) (void *) ((mShell)))))) == GDK_WINDOW_TYPE_HINT_UTILITY || gtk_window_get_type_hint(((((GtkWindow*) (void *) ((mShell)))))) == GDK_WINDOW_TYPE_HINT_TOOLTIP"
, "/root/firefox-clang/widget/gtk/nsWindowWaylandGtk.cpp", 569
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "gtk_window_get_type_hint(((((GtkWindow*) (void *) ((mShell)))))) == GDK_WINDOW_TYPE_HINT_UTILITY || gtk_window_get_type_hint(((((GtkWindow*) (void *) ((mShell)))))) == GDK_WINDOW_TYPE_HINT_TOOLTIP"
")"); do { MOZ_CrashSequence(__null, 569); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
570
571 gtk_window_move(GTK_WINDOW(mShell)((((GtkWindow*) (void *) ((mShell))))), aX, aY);
572
573 // gtk_window_move() can trick us. When widget is hidden gtk_window_move()
574 // does not move the widget but sets new widget coordinates when widget
575 // is mapped again.
576 //
577 // If popup used move-to-rect before
578 // (GdkWindow has POSITION_METHOD_MOVE_TO_RECT set), popup will use
579 // move-to-rect again when it's mapped and we'll get bogus move-to-rect
580 // callback.
581 //
582 // gdk_window_move() sets position_method to POSITION_METHOD_MOVE_RESIZE
583 // so we'll use plain move when popup is shown.
584 if (!gtk_widget_get_mapped(mShell)) {
585 if (GdkWindow* window = GetToplevelGdkWindow()) {
586 gdk_window_move(window, aX, aY);
587 }
588 }
589}
590
591static void NativeMoveResizeCallback(GdkWindow* window,
592 const GdkRectangle* flipped_rect,
593 const GdkRectangle* final_rect,
594 gboolean flipped_x, gboolean flipped_y,
595 void* aWindow) {
596 LOG_POPUP("[%p] NativeMoveResizeCallback flipped_x %d flipped_y %d\n",do { const ::mozilla::LogModule* moz_real_module = gWidgetPopupLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "[%p] NativeMoveResizeCallback flipped_x %d flipped_y %d\n"
, aWindow, flipped_x, flipped_y); } } while (0)
597 aWindow, flipped_x, flipped_y)do { const ::mozilla::LogModule* moz_real_module = gWidgetPopupLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "[%p] NativeMoveResizeCallback flipped_x %d flipped_y %d\n"
, aWindow, flipped_x, flipped_y); } } while (0)
;
598 LOG_POPUP("[%p] new position [%d, %d] -> [%d x %d]", aWindow,do { const ::mozilla::LogModule* moz_real_module = gWidgetPopupLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "[%p] new position [%d, %d] -> [%d x %d]"
, aWindow, final_rect->x, final_rect->y, final_rect->
width, final_rect->height); } } while (0)
599 final_rect->x, final_rect->y, final_rect->width,do { const ::mozilla::LogModule* moz_real_module = gWidgetPopupLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "[%p] new position [%d, %d] -> [%d x %d]"
, aWindow, final_rect->x, final_rect->y, final_rect->
width, final_rect->height); } } while (0)
600 final_rect->height)do { const ::mozilla::LogModule* moz_real_module = gWidgetPopupLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "[%p] new position [%d, %d] -> [%d x %d]"
, aWindow, final_rect->x, final_rect->y, final_rect->
width, final_rect->height); } } while (0)
;
601 MOZ_DIAGNOSTIC_ASSERT(nsWindow::FromGdkWindow(window), "Missing nsWindow!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(nsWindow::FromGdkWindow(window))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(nsWindow::FromGdkWindow(window
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("nsWindow::FromGdkWindow(window)" " (" "Missing nsWindow!" ")"
, "/root/firefox-clang/widget/gtk/nsWindowWaylandGtk.cpp", 601
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "nsWindow::FromGdkWindow(window)"
") (" "Missing nsWindow!" ")"); do { MOZ_CrashSequence(__null
, 601); __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
602 MOZ_DIAGNOSTIC_ASSERT(nsWindow::FromGdkWindow(window)->AsWaylandPopup(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(nsWindow::FromGdkWindow(window)->AsWaylandPopup()
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(nsWindow::FromGdkWindow(window)->AsWaylandPopup()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"nsWindow::FromGdkWindow(window)->AsWaylandPopup()" " (" "Not a Wayland popup!"
")", "/root/firefox-clang/widget/gtk/nsWindowWaylandGtk.cpp"
, 603); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "nsWindow::FromGdkWindow(window)->AsWaylandPopup()"
") (" "Not a Wayland popup!" ")"); do { MOZ_CrashSequence(__null
, 603); __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
603 "Not a Wayland popup!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(nsWindow::FromGdkWindow(window)->AsWaylandPopup()
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(nsWindow::FromGdkWindow(window)->AsWaylandPopup()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"nsWindow::FromGdkWindow(window)->AsWaylandPopup()" " (" "Not a Wayland popup!"
")", "/root/firefox-clang/widget/gtk/nsWindowWaylandGtk.cpp"
, 603); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "nsWindow::FromGdkWindow(window)->AsWaylandPopup()"
") (" "Not a Wayland popup!" ")"); do { MOZ_CrashSequence(__null
, 603); __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
604 static_cast<nsWindowWaylandPopupGtk*>(
605 nsWindow::FromGdkWindow(window)->AsWaylandPopup())
606 ->NativeMoveResizeWaylandPopupCallback(final_rect, flipped_x, flipped_y);
607}
608
609void nsWindowWaylandPopupGtk::WaylandPopupMoveImpl() {
610 // Available as of GTK 3.24+
611 static auto sGdkWindowMoveToRect = (void (*)(
612 GdkWindow*, const GdkRectangle*, GdkGravity, GdkGravity, GdkAnchorHints,
613 gint, gint))dlsym(RTLD_DEFAULT((void *) 0), "gdk_window_move_to_rect");
614
615 if (mPopupUseMoveToRect && !sGdkWindowMoveToRect) {
616 LOG("can't use move-to-rect due missing gdk_window_move_to_rect()")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "can't use move-to-rect due missing gdk_window_move_to_rect()"
, this->GetDebugTag().get()); } } while (0)
;
617 mPopupUseMoveToRect = false;
618 }
619
620 GdkRectangle gtkAnchorRect;
621 GdkPoint offset;
622 if (mPopupUseMoveToRect) {
623 mPopupUseMoveToRect =
624 WaylandPopupCheckAndGetAnchor(&gtkAnchorRect, &offset);
625 }
626
627 LOG("nsWindowWaylandPopupGtk::WaylandPopupMove")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandPopupGtk::WaylandPopupMove"
, this->GetDebugTag().get()); } } while (0)
;
628 LOG(" popup use move to rect %d", mPopupUseMoveToRect)do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " popup use move to rect %d", this
->GetDebugTag().get(), mPopupUseMoveToRect); } } while (0)
;
629
630 WaylandPopupPrepareForMove();
631
632 if (!mPopupUseMoveToRect) {
633 auto pos = mLastMoveRequest - WaylandGetParentPosition();
634 WaylandPopupMovePlain(pos.x, pos.y);
635 // Layout already should be aware of our bounds, since we didn't change it
636 // from the widget side for flipping or so.
637 return;
638 }
639
640 // Correct popup position now. It will be updated by gdk_window_move_to_rect()
641 // anyway but we need to set it now to avoid a race condition here.
642 WaylandPopupRemoveNegativePosition();
643
644 GdkWindow* gdkWindow = GetToplevelGdkWindow();
645 if (!g_signal_handler_find(gdkWindow, G_SIGNAL_MATCH_FUNC, 0, 0, nullptr,
646 FuncToGpointer(NativeMoveResizeCallback), this)) {
647 g_signal_connect(gdkWindow, "moved-to-rect",g_signal_connect_data ((gdkWindow), ("moved-to-rect"), (((GCallback
) (NativeMoveResizeCallback))), (this), __null, (GConnectFlags
) 0)
648 G_CALLBACK(NativeMoveResizeCallback), this)g_signal_connect_data ((gdkWindow), ("moved-to-rect"), (((GCallback
) (NativeMoveResizeCallback))), (this), __null, (GConnectFlags
) 0)
;
649 }
650 mWaitingForMoveToRectCallback = true;
651
652#ifdef MOZ_LOGGING1
653 if (LOG_ENABLED()((__builtin_expect(!!(mozilla::detail::log_test(gWidgetPopupLog
, mozilla::LogLevel::Debug)), 0)) || (__builtin_expect(!!(mozilla
::detail::log_test(gWidgetLog, mozilla::LogLevel::Debug)), 0)
))
) {
654 LOG(" Call move-to-rect")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " Call move-to-rect", this->GetDebugTag
().get()); } } while (0)
;
655 LOG(" Anchor rect [%d, %d] -> [%d x %d]", gtkAnchorRect.x, gtkAnchorRect.y,do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " Anchor rect [%d, %d] -> [%d x %d]"
, this->GetDebugTag().get(), gtkAnchorRect.x, gtkAnchorRect
.y, gtkAnchorRect.width, gtkAnchorRect.height); } } while (0)
656 gtkAnchorRect.width, gtkAnchorRect.height)do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " Anchor rect [%d, %d] -> [%d x %d]"
, this->GetDebugTag().get(), gtkAnchorRect.x, gtkAnchorRect
.y, gtkAnchorRect.width, gtkAnchorRect.height); } } while (0)
;
657 LOG(" Offset [%d, %d]", offset.x, offset.y)do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " Offset [%d, %d]", this->GetDebugTag
().get(), offset.x, offset.y); } } while (0)
;
658 LOG(" AnchorType")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " AnchorType", this->GetDebugTag
().get()); } } while (0)
;
659 LogPopupGravity(mPopupMoveToRectParams.mAnchorRectType);
660 LOG(" PopupAnchorType")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " PopupAnchorType", this->GetDebugTag
().get()); } } while (0)
;
661 LogPopupGravity(mPopupMoveToRectParams.mPopupAnchorType);
662 LogPopupAnchorHints(mPopupMoveToRectParams.mHints);
663 }
664#endif
665
666 sGdkWindowMoveToRect(gdkWindow, &gtkAnchorRect,
667 mPopupMoveToRectParams.mAnchorRectType,
668 mPopupMoveToRectParams.mPopupAnchorType,
669 mPopupMoveToRectParams.mHints, offset.x, offset.y);
670}
671
672// Wayland keeps strong popup window hierarchy. We need to track active
673// (visible) popup windows and make sure we hide popup on the same level
674// before we open another one on that level. It means that every open
675// popup needs to have an unique parent.
676void nsWindowWaylandPopupGtk::UpdateWaylandPopupHierarchy() {
677 LOG("nsWindowWaylandPopupGtk::UpdateWaylandPopupHierarchy\n")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandPopupGtk::UpdateWaylandPopupHierarchy\n"
, this->GetDebugTag().get()); } } while (0)
;
678
679 // This popup hasn't been added to popup hierarchy yet so no need to
680 // do any configurations.
681 if (!IsInPopupHierarchy()) {
682 LOG(" popup isn't in hierarchy\n")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " popup isn't in hierarchy\n", this
->GetDebugTag().get()); } } while (0)
;
683 return;
684 }
685
686 nsWindowWaylandPopupGtk* firstPopup =
687 PopupAsGtk(mWaylandToplevel->GetFirstPopup());
688 MOZ_DIAGNOSTIC_ASSERT(firstPopup, "In hierarchy without a first popup?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(firstPopup)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(firstPopup))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("firstPopup" " (" "In hierarchy without a first popup?"
")", "/root/firefox-clang/widget/gtk/nsWindowWaylandGtk.cpp"
, 688); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "firstPopup"
") (" "In hierarchy without a first popup?" ")"); do { MOZ_CrashSequence
(__null, 688); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
689 if (!firstPopup) {
690 return;
691 }
692
693#ifdef MOZ_LOGGING1
694 LogPopupHierarchy(firstPopup);
695 auto printPopupHierarchy =
696 MakeScopeExit([&] { LogPopupHierarchy(firstPopup); });
697#endif
698
699 // Hide all tooltips without the last one. Tooltip can't be popup parent.
700 firstPopup->WaylandPopupHideTooltips();
701
702 // See Bug 1709254 / https://gitlab.gnome.org/GNOME/gtk/-/issues/5092
703 // It's possible that Wayland compositor refuses to show
704 // a popup although Gtk claims it's visible.
705 // We don't know if the popup is shown or not.
706 // To avoid application crash refuse to create any child of such invisible
707 // popup and close any child of it now.
708 firstPopup->WaylandPopupCloseOrphanedPopups();
709
710 // Check if we have any remote content / overflow window in hierarchy.
711 // We can't attach such widget on top of other popup.
712 firstPopup->CloseAllPopupsBeforeRemotePopup();
713
714 // Check if your popup hierarchy matches layout hierarchy.
715 // For instance we should not connect hamburger menu on top
716 // of context menu.
717 // Close all popups from different layout chains if possible.
718 AutoTArray<nsIWidget*, 5> layoutPopupWidgetChain;
719 GetLayoutPopupWidgetChain(&layoutPopupWidgetChain);
720
721 firstPopup->WaylandPopupHierarchyHideByLayout(&layoutPopupWidgetChain);
722 firstPopup->WaylandPopupHierarchyValidateByLayout(&layoutPopupWidgetChain);
723
724 // Now we have Popup hierarchy complete.
725 // Find first unchanged (and still open) popup to start with hierarchy
726 // changes.
727 nsWindowWaylandPopupGtk* changedPopup = firstPopup;
728 while (changedPopup) {
729 // Stop when parent of this popup was changed and we need to recalc
730 // popup position.
731 if (changedPopup->mPopupChanged) {
732 break;
733 }
734 // Stop when this popup is closed.
735 if (changedPopup->mPopupClosed) {
736 break;
737 }
738 changedPopup = PopupAsGtk(changedPopup->GetNextPopup());
739 }
740
741 // We don't need to recompute popup positions, quit now.
742 if (!changedPopup) {
743 LOG(" changed Popup is null, quit.\n")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " changed Popup is null, quit.\n",
this->GetDebugTag().get()); } } while (0)
;
744 return;
745 }
746
747 LOG(" first changed popup [%p]\n", (void*)changedPopup)do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " first changed popup [%p]\n", this
->GetDebugTag().get(), (void*)changedPopup); } } while (0)
;
748
749 // Hide parent popups if necessary (there are layout discontinuity)
750 // reposition the popup and show them again.
751 changedPopup->WaylandPopupHierarchyHideTemporary();
752
753 // May be the toplevel window when changedPopup is the first popup.
754 nsWindowWayland* parentOfChangedPopup = nullptr;
755 if (changedPopup->mPopupClosed) {
756 parentOfChangedPopup = changedPopup->GetPrevWindow();
757 }
758 changedPopup->RemoveClosedPopups();
759
760 // There's nothing left, just quit
761 firstPopup = PopupAsGtk(mWaylandToplevel->GetFirstPopup());
762 if (!firstPopup) {
763 return;
764 }
765
766 // It's possible that changedPopup was removed from widget hierarchy,
767 // in such case use child popup of the removed one if there's any.
768 if (!changedPopup->IsInPopupHierarchy()) {
769 if (!parentOfChangedPopup || !parentOfChangedPopup->GetNextWindow()) {
770 LOG(" last popup was removed, quit.\n")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " last popup was removed, quit.\n"
, this->GetDebugTag().get()); } } while (0)
;
771 return;
772 }
773 changedPopup = static_cast<nsWindowWaylandPopupGtk*>(
774 parentOfChangedPopup->GetNextWindow()->AsWaylandPopup());
775 }
776
777 GetLayoutPopupWidgetChain(&layoutPopupWidgetChain);
778 firstPopup->WaylandPopupHierarchyValidateByLayout(&layoutPopupWidgetChain);
779
780 changedPopup->WaylandPopupHierarchyCalculatePositions();
781
782 nsWindowWaylandPopupGtk* popup = changedPopup;
783 while (popup) {
784 const bool useMoveToRect = [&] {
785 if (!StaticPrefs::widget_wayland_use_move_to_rect_AtStartup()) {
786 return false; // Not available.
787 }
788 if (!popup->mPopupMatchesLayout) {
789 // We can use move_to_rect only when popups in popup hierarchy matches
790 // layout hierarchy as move_to_rect request that parent/child
791 // popups are adjacent.
792 return false;
793 }
794 nsWindowWaylandPopupGtk* parentPopup = PopupAsGtk(popup->GetPrevPopup());
795 if (parentPopup && !parentPopup->WaylandPopupIsFirst() &&
796 !parentPopup->mPopupUseMoveToRect) {
797 // We can't use move-to-rect if there are more parents of
798 // wl_subsurface popups types.
799 //
800 // It's because wl_subsurface is ignored by xdg_popup
801 // (created by move-to-rect) so our popup scenario:
802 //
803 // toplevel -> xdg_popup(1) -> wl_subsurface(2) -> xdg_popup(3)
804 //
805 // looks for Wayland compositor as:
806 //
807 // toplevel -> xdg_popup(1) -> xdg_popup(3)
808 //
809 // If xdg_popup(1) and xdg_popup(3) are not connected
810 // move-to-rect applied to xdg_popup(3) fails and we get missing popup.
811 return false;
812 }
813 return true;
814 }();
815
816 popup->mPopupUseMoveToRect = useMoveToRect;
817
818 LOG(" popup [%p] matches layout [%d] anchored [%d] first popup [%d] use "do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " popup [%p] matches layout [%d] anchored [%d] first popup [%d] use "
"move-to-rect %d\n", this->GetDebugTag().get(), popup, popup
->mPopupMatchesLayout, popup->mPopupAnchored, popup->
WaylandPopupIsFirst(), popup->mPopupUseMoveToRect); } } while
(0)
819 "move-to-rect %d\n",do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " popup [%p] matches layout [%d] anchored [%d] first popup [%d] use "
"move-to-rect %d\n", this->GetDebugTag().get(), popup, popup
->mPopupMatchesLayout, popup->mPopupAnchored, popup->
WaylandPopupIsFirst(), popup->mPopupUseMoveToRect); } } while
(0)
820 popup, popup->mPopupMatchesLayout, popup->mPopupAnchored,do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " popup [%p] matches layout [%d] anchored [%d] first popup [%d] use "
"move-to-rect %d\n", this->GetDebugTag().get(), popup, popup
->mPopupMatchesLayout, popup->mPopupAnchored, popup->
WaylandPopupIsFirst(), popup->mPopupUseMoveToRect); } } while
(0)
821 popup->WaylandPopupIsFirst(), popup->mPopupUseMoveToRect)do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " popup [%p] matches layout [%d] anchored [%d] first popup [%d] use "
"move-to-rect %d\n", this->GetDebugTag().get(), popup, popup
->mPopupMatchesLayout, popup->mPopupAnchored, popup->
WaylandPopupIsFirst(), popup->mPopupUseMoveToRect); } } while
(0)
;
822
823 if (popup->mPopupUseMoveToRect && !popup->mPopupMatchesLayout) {
824 gfxCriticalNotemozilla::gfx::CriticalLog(mozilla::gfx::CriticalLog::DefaultOptions
(false))
<< "Wayland: Positioned popup with missing anchor!";
825 }
826
827 popup->WaylandPopupMoveImpl();
828 popup->mPopupChanged = false;
829 popup = PopupAsGtk(popup->GetNextPopup());
830 }
831
832 changedPopup->WaylandPopupHierarchyShowTemporaryHidden();
833}
834
835// Gtk refuses to map popup window with x < 0 && y < 0 relative coordinates
836// see https://gitlab.gnome.org/GNOME/gtk/-/issues/4071
837// as a workaround just fool around and place the popup temporary to 0,0.
838bool nsWindowWaylandPopupGtk::WaylandPopupRemoveNegativePosition(int* aX,
839 int* aY) {
840 // https://gitlab.gnome.org/GNOME/gtk/-/issues/4071 applies to temporary
841 // windows only
842 GdkWindow* window = GetToplevelGdkWindow();
843 if (!window || gdk_window_get_window_type(window) != GDK_WINDOW_TEMP) {
844 return false;
845 }
846
847 LOG("nsWindowWaylandPopupGtk::WaylandPopupRemoveNegativePosition()")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandPopupGtk::WaylandPopupRemoveNegativePosition()"
, this->GetDebugTag().get()); } } while (0)
;
848
849 int x, y;
850 gtk_window_get_position(GTK_WINDOW(mShell)((((GtkWindow*) (void *) ((mShell))))), &x, &y);
851 bool moveBack = (x < 0 && y < 0);
852 if (moveBack) {
853 gtk_window_move(GTK_WINDOW(mShell)((((GtkWindow*) (void *) ((mShell))))), 0, 0);
854 if (aX) {
855 *aX = x;
856 }
857 if (aY) {
858 *aY = y;
859 }
860 }
861
862 gdk_window_get_geometry(window, &x, &y, nullptr, nullptr);
863 if (x < 0 && y < 0) {
864 gdk_window_move(window, 0, 0);
865 }
866
867 return moveBack;
868}
869
870void nsWindowWaylandPopupGtk::ShowWaylandPopupWindow() {
871 LOG("nsWindowWaylandPopupGtk::ShowWaylandPopupWindow. Expected to see "do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandPopupGtk::ShowWaylandPopupWindow. Expected to see "
"visible.", this->GetDebugTag().get()); } } while (0)
872 "visible.")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandPopupGtk::ShowWaylandPopupWindow. Expected to see "
"visible.", this->GetDebugTag().get()); } } while (0)
;
873 MOZ_ASSERT(IsWaylandPopup())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsWaylandPopup())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsWaylandPopup()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("IsWaylandPopup()"
, "/root/firefox-clang/widget/gtk/nsWindowWaylandGtk.cpp", 873
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsWaylandPopup()"
")"); do { MOZ_CrashSequence(__null, 873); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
874
875 if (!mPopupTrackInHierarchy) {
876 LOG(" popup is not tracked in popup hierarchy, show it now")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " popup is not tracked in popup hierarchy, show it now"
, this->GetDebugTag().get()); } } while (0)
;
877 gtk_widget_show(mShell);
878 return;
879 }
880
881 // Popup position was checked before gdk_window_move_to_rect() callback
882 // so just show it.
883 if (mPopupUseMoveToRect && mWaitingForMoveToRectCallback) {
884 LOG(" active move-to-rect callback, show it as is")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " active move-to-rect callback, show it as is"
, this->GetDebugTag().get()); } } while (0)
;
885 gtk_widget_show(mShell);
886 return;
887 }
888
889 if (gtk_widget_is_visible(mShell)) {
890 LOG(" is already visible, quit")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " is already visible, quit", this->
GetDebugTag().get()); } } while (0)
;
891 return;
892 }
893
894 int x, y;
895 bool moved = WaylandPopupRemoveNegativePosition(&x, &y);
896 gtk_widget_show(mShell);
897 if (moved) {
898 LOG(" move back to (%d, %d) and show", x, y)do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " move back to (%d, %d) and show",
this->GetDebugTag().get(), x, y); } } while (0)
;
899 gtk_window_move(GTK_WINDOW(mShell)((((GtkWindow*) (void *) ((mShell))))), x, y);
900 }
901}
902
903// Hide and potentially removes popup from popup hierarchy.
904void nsWindowWaylandPopupGtk::HidePopupWindow(bool aTemporaryHide,
905 bool aRemoveFromPopupList) {
906 LOG("nsWindowWaylandPopupGtk::HidePopupWindow: remove from list %d\n",do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandPopupGtk::HidePopupWindow: remove from list %d\n"
, this->GetDebugTag().get(), aRemoveFromPopupList); } } while
(0)
907 aRemoveFromPopupList)do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandPopupGtk::HidePopupWindow: remove from list %d\n"
, this->GetDebugTag().get(), aRemoveFromPopupList); } } while
(0)
;
908 if (aRemoveFromPopupList) {
909 RemovePopupFromHierarchyList();
910 }
911
912 if (!mPopupClosed) {
913 mPopupClosed = !aTemporaryHide;
914 }
915
916 bool visible = gtk_widget_is_visible(mShell);
917 LOG(" gtk_widget_is_visible() = %d\n", visible)do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " gtk_widget_is_visible() = %d\n",
this->GetDebugTag().get(), visible); } } while (0)
;
918
919 // Restore only popups which are really visible
920 mPopupTemporaryHidden = aTemporaryHide && visible;
921
922 // Hide only visible popups or popups closed pernamently.
923 if (visible) {
924 gtk_widget_hide(mShell);
925
926 // If there's pending Move-To-Rect callback and we hide the popup
927 // the callback won't be called any more.
928 mWaitingForMoveToRectCallback = false;
929 }
930
931 if (mPopupClosed) {
932 LOG(" Clearing mMoveToRectPopupSize\n")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " Clearing mMoveToRectPopupSize\n"
, this->GetDebugTag().get()); } } while (0)
;
933 mMoveToRectPopupSize = {};
934 }
935}
936
937void nsWindowWaylandPopupGtk::NativeShow(bool aAction) {
938 if (aAction) {
939 // unset our flag now that our window has been shown
940 mNeedsShow = true;
941 auto removeShow = MakeScopeExit([&] { mNeedsShow = false; });
942
943 LOG("nsWindowWaylandPopupGtk::NativeShow show\n")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandPopupGtk::NativeShow show\n"
, this->GetDebugTag().get()); } } while (0)
;
944
945 mPopupClosed = false;
946 const bool trackedInHierarchy = WaylandPopupConfigure();
947 if (trackedInHierarchy) {
948 AddWindowToPopupHierarchy();
949 }
950 if (mWaylandApplyPopupPositionBeforeShow) {
951 // NOTE(emilio): This will end up calling UpdateWaylandPopupHierarchy if
952 // needed.
953 NativeMoveResize(/* move */ true, /* resize */ false);
954 } else if (trackedInHierarchy) {
955 UpdateWaylandPopupHierarchy();
956 }
957 if (mPopupClosed) {
958 return;
959 }
960 ShowWaylandPopupWindow();
961 } else {
962 LOG("nsWindowWaylandPopupGtk::NativeShow hide\n")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandPopupGtk::NativeShow hide\n"
, this->GetDebugTag().get()); } } while (0)
;
963 // We can't close tracked popups directly as they may have visible
964 // child popups. Just mark is as closed and let
965 // UpdateWaylandPopupHierarchy() do the job.
966 if (IsInPopupHierarchy()) {
967 WaylandPopupMarkAsClosed();
968 UpdateWaylandPopupHierarchy();
969 } else {
970 // Close untracked popups directly.
971 HidePopupWindow(/* aTemporaryHide */ false,
972 /* aRemoveFromPopupList */ true);
973 }
974 }
975}
976
977// Configure Wayland popup. If true is returned we need to track popup
978// in popup hierarchy. Otherwise we just show it as is.
979bool nsWindowWaylandPopupGtk::WaylandPopupConfigure() {
980 if (mIsDragPopup) {
981 return false;
982 }
983
984 // Don't track popups without frame
985 nsMenuPopupFrame* popupFrame = GetPopupFrame();
986 if (!popupFrame) {
987 return false;
988 }
989
990 // Popup state can be changed, see Bug 1728952.
991 bool permanentStateMatches =
992 mPopupTrackInHierarchy == !WaylandPopupIsPermanent();
993
994 // Popup permanent state (noautohide attribute) can change during popup life.
995 if (mPopupTrackInHierarchyConfigured && permanentStateMatches) {
996 return mPopupTrackInHierarchy;
997 }
998
999 // Configure persistent popup params only once.
1000 // WaylandPopupIsAnchored() can give it wrong value after
1001 // nsMenuPopupFrame::MoveTo() call which we use in move-to-rect callback
1002 // to position popup after wayland position change.
1003 if (!mPopupTrackInHierarchyConfigured) {
1004 mPopupAnchored = WaylandPopupIsAnchored();
1005 mPopupContextMenu = WaylandPopupIsContextMenu();
1006 }
1007
1008 LOG("nsWindowWaylandPopupGtk::WaylandPopupConfigure tracked %d anchored %d "do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandPopupGtk::WaylandPopupConfigure tracked %d anchored %d "
"hint %d permanent %d\n", this->GetDebugTag().get(), mPopupTrackInHierarchy
, mPopupAnchored, int(mPopupType), WaylandPopupIsPermanent())
; } } while (0)
1009 "hint %d permanent %d\n",do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandPopupGtk::WaylandPopupConfigure tracked %d anchored %d "
"hint %d permanent %d\n", this->GetDebugTag().get(), mPopupTrackInHierarchy
, mPopupAnchored, int(mPopupType), WaylandPopupIsPermanent())
; } } while (0)
1010 mPopupTrackInHierarchy, mPopupAnchored, int(mPopupType),do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandPopupGtk::WaylandPopupConfigure tracked %d anchored %d "
"hint %d permanent %d\n", this->GetDebugTag().get(), mPopupTrackInHierarchy
, mPopupAnchored, int(mPopupType), WaylandPopupIsPermanent())
; } } while (0)
1011 WaylandPopupIsPermanent())do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandPopupGtk::WaylandPopupConfigure tracked %d anchored %d "
"hint %d permanent %d\n", this->GetDebugTag().get(), mPopupTrackInHierarchy
, mPopupAnchored, int(mPopupType), WaylandPopupIsPermanent())
; } } while (0)
;
1012
1013 // Permanent state changed and popup is mapped.
1014 // We need to switch popup type but that's done when popup is mapped
1015 // by Gtk so we need to unmap the popup here.
1016 // It will be mapped again by gtk_widget_show().
1017 if (!permanentStateMatches && mIsMapped) {
1018 LOG(" permanent state change from %d to %d, unmapping",do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " permanent state change from %d to %d, unmapping"
, this->GetDebugTag().get(), mPopupTrackInHierarchy, !WaylandPopupIsPermanent
()); } } while (0)
1019 mPopupTrackInHierarchy, !WaylandPopupIsPermanent())do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " permanent state change from %d to %d, unmapping"
, this->GetDebugTag().get(), mPopupTrackInHierarchy, !WaylandPopupIsPermanent
()); } } while (0)
;
1020 gtk_widget_unmap(mShell);
1021 }
1022
1023 mPopupTrackInHierarchy = !WaylandPopupIsPermanent();
1024 LOG(" tracked in hierarchy %d\n", mPopupTrackInHierarchy)do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " tracked in hierarchy %d\n", this
->GetDebugTag().get(), mPopupTrackInHierarchy); } } while (
0)
;
1025
1026 // See gdkwindow-wayland.c and
1027 // should_map_as_popup()/should_map_as_subsurface()
1028 GdkWindowTypeHint gtkTypeHint;
1029 switch (mPopupType) {
1030 case PopupType::Menu:
1031 // GDK_WINDOW_TYPE_HINT_POPUP_MENU is mapped as xdg_popup by default.
1032 // We use this type for all menu popups.
1033 gtkTypeHint = GDK_WINDOW_TYPE_HINT_POPUP_MENU;
1034 LOG(" popup type Menu")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " popup type Menu", this->GetDebugTag
().get()); } } while (0)
;
1035 break;
1036 case PopupType::Tooltip:
1037 gtkTypeHint = GDK_WINDOW_TYPE_HINT_TOOLTIP;
1038 LOG(" popup type Tooltip")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " popup type Tooltip", this->GetDebugTag
().get()); } } while (0)
;
1039 break;
1040 default:
1041 gtkTypeHint = GDK_WINDOW_TYPE_HINT_UTILITY;
1042 LOG(" popup type Utility")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " popup type Utility", this->GetDebugTag
().get()); } } while (0)
;
1043 break;
1044 }
1045
1046 if (!mPopupTrackInHierarchy) {
1047 // GDK_WINDOW_TYPE_HINT_UTILITY is mapped as wl_subsurface
1048 // by default.
1049 LOG(" not tracked in popup hierarchy, switch to Utility")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " not tracked in popup hierarchy, switch to Utility"
, this->GetDebugTag().get()); } } while (0)
;
1050 gtkTypeHint = GDK_WINDOW_TYPE_HINT_UTILITY;
1051 }
1052 gtk_window_set_type_hint(GTK_WINDOW(mShell)((((GtkWindow*) (void *) ((mShell))))), gtkTypeHint);
1053
1054 mPopupTrackInHierarchyConfigured = true;
1055 return mPopupTrackInHierarchy;
1056}
1057
1058// Hide popups which are not in popup chain.
1059void nsWindowWaylandPopupGtk::WaylandPopupHierarchyHideByLayout(
1060 nsTArray<nsIWidget*>* aLayoutWidgetHierarchy) {
1061 LOG("nsWindowWaylandPopupGtk::WaylandPopupHierarchyHideByLayout")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandPopupGtk::WaylandPopupHierarchyHideByLayout"
, this->GetDebugTag().get()); } } while (0)
;
1062 MOZ_ASSERT(WaylandPopupIsFirst(), "Should be called on the first popup!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(WaylandPopupIsFirst())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(WaylandPopupIsFirst()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("WaylandPopupIsFirst()"
" (" "Should be called on the first popup!" ")", "/root/firefox-clang/widget/gtk/nsWindowWaylandGtk.cpp"
, 1062); AnnotateMozCrashReason("MOZ_ASSERT" "(" "WaylandPopupIsFirst()"
") (" "Should be called on the first popup!" ")"); do { MOZ_CrashSequence
(__null, 1062); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1063
1064 // Hide all popups which are not in layout popup chain
1065 nsWindowWaylandPopupGtk* popup = this;
1066 while (popup) {
1067 // Don't check closed popups and drag source popups and tooltips.
1068 if (!popup->mPopupClosed && popup->mPopupType != PopupType::Tooltip &&
1069 !popup->mSourceDragContext) {
1070 if (!popup->IsPopupInLayoutPopupChain(aLayoutWidgetHierarchy,
1071 /* aMustMatchParent */ false)) {
1072 LOG(" hidding popup [%p]", popup)do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " hidding popup [%p]", this->GetDebugTag
().get(), popup); } } while (0)
;
1073 popup->WaylandPopupMarkAsClosed();
1074 }
1075 }
1076 popup = PopupAsGtk(popup->GetNextPopup());
1077 }
1078}
1079
1080void nsWindowWaylandPopupGtk::WaylandPopupHierarchyHideTemporary() {
1081 LOG("nsWindowWaylandPopupGtk::WaylandPopupHierarchyHideTemporary()")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandPopupGtk::WaylandPopupHierarchyHideTemporary()"
, this->GetDebugTag().get()); } } while (0)
;
1082 nsWindowWaylandPopup* popup = FindLastWindow(this)->AsWaylandPopup();
1083 while (popup && popup != this) {
1084 LOG(" temporary hidding popup [%p]", popup)do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " temporary hidding popup [%p]", this
->GetDebugTag().get(), popup); } } while (0)
;
1085 nsWindowWaylandPopup* prev = popup->GetPrevPopup();
1086 popup->HidePopupWindow(/* aTemporaryHide */ true,
1087 /* aRemoveFromPopupList */ false);
1088 popup = prev;
1089 }
1090}
1091
1092void nsWindowWaylandPopupGtk::WaylandPopupHierarchyShowTemporaryHidden() {
1093 LOG("nsWindowWaylandPopupGtk::WaylandPopupHierarchyShowTemporaryHidden()")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandPopupGtk::WaylandPopupHierarchyShowTemporaryHidden()"
, this->GetDebugTag().get()); } } while (0)
;
1094 nsWindowWaylandPopupGtk* popup = this;
1095 while (popup) {
1096 if (popup->mPopupTemporaryHidden) {
1097 popup->mPopupTemporaryHidden = false;
1098 LOG(" showing temporary hidden popup [%p]", popup)do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " showing temporary hidden popup [%p]"
, this->GetDebugTag().get(), popup); } } while (0)
;
1099 popup->ShowWaylandPopupWindow();
1100 }
1101 popup = PopupAsGtk(popup->GetNextPopup());
1102 }
1103}
1104
1105void nsWindowWaylandPopupGtk::WaylandPopupHierarchyCalculatePositions() {
1106 LOG("nsWindowWaylandPopupGtk::WaylandPopupHierarchyCalculatePositions()")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandPopupGtk::WaylandPopupHierarchyCalculatePositions()"
, this->GetDebugTag().get()); } } while (0)
;
1107
1108 // Set widget hierarchy in Gtk
1109 nsWindowWaylandPopupGtk* popup =
1110 PopupAsGtk(mWaylandToplevel->GetFirstPopup());
1111 while (popup) {
1112 LOG(" popup [%p] set parent window [%p]", (void*)popup,do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " popup [%p] set parent window [%p]"
, this->GetDebugTag().get(), (void*)popup, (void*)popup->
mWaylandWindowPrev.get()); } } while (0)
1113 (void*)popup->mWaylandWindowPrev.get())do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " popup [%p] set parent window [%p]"
, this->GetDebugTag().get(), (void*)popup, (void*)popup->
mWaylandWindowPrev.get()); } } while (0)
;
1114 GtkWindowSetTransientFor(
1115 GTK_WINDOW(popup->mShell)((((GtkWindow*) (void *) ((popup->mShell))))),
1116 GTK_WINDOW(popup->mWaylandWindowPrev->GetGtkWidget())((((GtkWindow*) (void *) ((popup->mWaylandWindowPrev->GetGtkWidget
())))))
);
1117 popup = PopupAsGtk(popup->GetNextPopup());
1118 }
1119}
1120
1121DesktopIntPoint nsWindowWaylandPopupGtk::WaylandGetParentPosition() const {
1122 MOZ_ASSERT(IsPopup())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsPopup())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsPopup()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("IsPopup()", "/root/firefox-clang/widget/gtk/nsWindowWaylandGtk.cpp"
, 1122); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsPopup()" ")"
); do { MOZ_CrashSequence(__null, 1122); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1123 auto* window = GetEffectiveParent();
1124 if (NS_WARN_IF(!window)NS_warn_if_impl(!window, "!window", "/root/firefox-clang/widget/gtk/nsWindowWaylandGtk.cpp"
, 1124)
|| !window->IsPopup()) {
1125 return {0, 0};
1126 }
1127 // If our parent is a popup, offset to our toplevel bounds (note that in
1128 // Wayland there's no global coordinate space, so our "screen" offset is
1129 // really relative to the origin of our toplevel).
1130 DesktopIntPoint offset = window->WidgetToScreenOffsetUnscaled();
1131 LOG("nsWindowWaylandPopupGtk::WaylandGetParentPosition() [%d, %d]\n",do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandPopupGtk::WaylandGetParentPosition() [%d, %d]\n"
, this->GetDebugTag().get(), offset.x.value, offset.y.value
); } } while (0)
1132 offset.x.value, offset.y.value)do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandPopupGtk::WaylandGetParentPosition() [%d, %d]\n"
, this->GetDebugTag().get(), offset.x.value, offset.y.value
); } } while (0)
;
1133 return offset;
1134}
1135
1136void nsWindowWaylandPopupGtk::NativeMoveResizeWaylandPopupCallback(
1137 const GdkRectangle* aFinalSize, bool aFlippedX, bool aFlippedY) {
1138 // We're getting move-to-rect callback without move-to-rect call.
1139 // That indicates a compositor bug. It happens when a window is hidden and
1140 // shown again before move-to-rect callback is fired.
1141 // It may lead to incorrect popup placement as we may call
1142 // gtk_window_move() between hide & show.
1143 // See Bug 1777919, 1789581.
1144#if MOZ_LOGGING1
1145 if (!mWaitingForMoveToRectCallback) {
1146 LOG(" Bogus move-to-rect callback! Expect wrong popup coordinates.")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " Bogus move-to-rect callback! Expect wrong popup coordinates."
, this->GetDebugTag().get()); } } while (0)
;
1147 }
1148#endif
1149
1150 mWaitingForMoveToRectCallback = false;
1151
1152 bool movedByLayout = mMovedAfterMoveToRect;
1153 bool resizedByLayout = mResizedAfterMoveToRect;
1154
1155 // Popup was moved between move-to-rect call and move-to-rect callback
1156 // and the coordinates from move-to-rect callback are outdated.
1157 if (movedByLayout || resizedByLayout) {
1158 LOG(" Another move/resize called during waiting for callback\n")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " Another move/resize called during waiting for callback\n"
, this->GetDebugTag().get()); } } while (0)
;
1159 mMovedAfterMoveToRect = false;
1160 mResizedAfterMoveToRect = false;
1161 // Fire another round of move/resize to reflect latest request from layout.
1162 NativeMoveResize(movedByLayout, resizedByLayout);
1163 return;
1164 }
1165
1166 const GdkRectangle finalGdkRect = [&] {
1167 GdkRectangle finalRect = *aFinalSize;
1168 DesktopIntPoint parent = WaylandGetParentPosition();
1169 finalRect.x += parent.x;
1170 finalRect.y += parent.y;
1171 return finalRect;
1172 }();
1173
1174 // With fractional scaling, our devPx->Gdk->devPx conversion might not
1175 // perfectly round-trip. Compare gdk rects to check whether size or positions
1176 // have changed from what we'd request otherwise, in order to avoid
1177 // flickering.
1178 const auto currentRect = mClientArea;
1179 auto scale = GdkCeiledScaleFactor();
1180 auto IsSubstantiallyDifferent = [=](gint a, gint b) {
1181 return std::abs(a - b) > scale;
1182 };
1183
1184 const bool needsPositionUpdate =
1185 IsSubstantiallyDifferent(finalGdkRect.x, currentRect.x) ||
1186 IsSubstantiallyDifferent(finalGdkRect.y, currentRect.y);
1187 const bool needsSizeUpdate =
1188 IsSubstantiallyDifferent(finalGdkRect.width, currentRect.width) ||
1189 IsSubstantiallyDifferent(finalGdkRect.height, currentRect.height);
1190 const DesktopIntRect newClientArea = DesktopIntRect(
1191 finalGdkRect.x, finalGdkRect.y, finalGdkRect.width, finalGdkRect.height);
1192
1193 LOG(" orig gdk [%d, %d] -> [%d x %d]", currentRect.x, currentRect.y,do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " orig gdk [%d, %d] -> [%d x %d]"
, this->GetDebugTag().get(), currentRect.x, currentRect.y,
currentRect.width, currentRect.height); } } while (0)
1194 currentRect.width, currentRect.height)do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " orig gdk [%d, %d] -> [%d x %d]"
, this->GetDebugTag().get(), currentRect.x, currentRect.y,
currentRect.width, currentRect.height); } } while (0)
;
1195 LOG(" new gdk [%d, %d] -> [%d x %d]\n", finalGdkRect.x, finalGdkRect.y,do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " new gdk [%d, %d] -> [%d x %d]\n"
, this->GetDebugTag().get(), finalGdkRect.x, finalGdkRect.
y, finalGdkRect.width, finalGdkRect.height); } } while (0)
1196 finalGdkRect.width, finalGdkRect.height)do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " new gdk [%d, %d] -> [%d x %d]\n"
, this->GetDebugTag().get(), finalGdkRect.x, finalGdkRect.
y, finalGdkRect.width, finalGdkRect.height); } } while (0)
;
1197 LOG(" new mClientArea [%d, %d] -> [%d x %d]", newClientArea.x,do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " new mClientArea [%d, %d] -> [%d x %d]"
, this->GetDebugTag().get(), newClientArea.x, newClientArea
.y, newClientArea.width, newClientArea.height); } } while (0)
1198 newClientArea.y, newClientArea.width, newClientArea.height)do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " new mClientArea [%d, %d] -> [%d x %d]"
, this->GetDebugTag().get(), newClientArea.x, newClientArea
.y, newClientArea.width, newClientArea.height); } } while (0)
;
1199
1200 if (!needsSizeUpdate && !needsPositionUpdate) {
1201 LOG(" Size/position is the same, quit.")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " Size/position is the same, quit."
, this->GetDebugTag().get()); } } while (0)
;
1202 return;
1203 }
1204 if (needsSizeUpdate) {
1205 // Wayland compositor changed popup size request from layout.
1206 // Set the constraints to use them in nsMenuPopupFrame::SetPopupPosition().
1207 // Beware that gtk_window_resize() requests sizes asynchronously and so
1208 // newClientArea might not have the size from the most recent
1209 // gtk_window_resize().
1210 if (newClientArea.width < mLastSizeRequest.width) {
1211 mMoveToRectPopupSize.width = newClientArea.width;
1212 }
1213 if (newClientArea.height < mLastSizeRequest.height) {
1214 mMoveToRectPopupSize.height = newClientArea.height;
1215 }
1216 LOG(" mMoveToRectPopupSize set to [%d, %d]", mMoveToRectPopupSize.width,do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " mMoveToRectPopupSize set to [%d, %d]"
, this->GetDebugTag().get(), mMoveToRectPopupSize.width, mMoveToRectPopupSize
.height); } } while (0)
1217 mMoveToRectPopupSize.height)do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " mMoveToRectPopupSize set to [%d, %d]"
, this->GetDebugTag().get(), mMoveToRectPopupSize.width, mMoveToRectPopupSize
.height); } } while (0)
;
1218 }
1219
1220 mClientArea = newClientArea;
1221 mLastSizeRequest = newClientArea.Size();
1222 mLastMoveRequest = newClientArea.TopLeft();
1223
1224 // Check mClientArea size
1225 auto scaledSize = ToLayoutDevicePixels(mClientArea);
1226 if (mCompositorSession &&
1227 !wr::WindowSizeSanityCheck(scaledSize.width, scaledSize.height)) {
1228 gfxCriticalNoteOncestatic mozilla::gfx::CriticalLog sOnceAtLine1228 = mozilla::gfx
::CriticalLog(mozilla::gfx::CriticalLog::DefaultOptions(false
))
<< "Invalid mClientArea in PopupCallback " << scaledSize
1229 << " size state " << mSizeMode;
1230 }
1231 WaylandPopupPropagateChangesToLayout(needsPositionUpdate, needsSizeUpdate);
1232}
1233
1234// Position the popup directly by gtk_window_move() and try to keep it
1235// on screen by just moving it in scope of it's parent window.
1236//
1237// It's used when we position noautihode popup and we don't use xdg_positioner.
1238// See Bug 1718867
1239void nsWindowWaylandPopupGtk::WaylandPopupSetDirectPosition() {
1240 const DesktopIntRect newRect(mLastMoveRequest, mLastSizeRequest);
1241
1242 LOG("nsWindowWaylandPopupGtk::WaylandPopupSetDirectPosition %s",do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandPopupGtk::WaylandPopupSetDirectPosition %s"
, this->GetDebugTag().get(), ToString(newRect).c_str()); }
} while (0)
1243 ToString(newRect).c_str())do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandPopupGtk::WaylandPopupSetDirectPosition %s"
, this->GetDebugTag().get(), ToString(newRect).c_str()); }
} while (0)
;
1244
1245 mClientArea = newRect;
1246
1247 if (mIsDragPopup) {
1248 gtk_window_move(GTK_WINDOW(mShell)((((GtkWindow*) (void *) ((mShell))))), newRect.x, newRect.y);
1249 gtk_window_resize(GTK_WINDOW(mShell)((((GtkWindow*) (void *) ((mShell))))), newRect.width, newRect.height);
1250 // DND window is placed inside container so we need to make hard size
1251 // request to ensure parent container is resized too.
1252 gtk_widget_set_size_request(GTK_WIDGET(mShell)((((GtkWidget*) (void *) ((mShell))))), newRect.width,
1253 newRect.height);
1254 return;
1255 }
1256
1257 GtkWindow* parentGtkWindow = gtk_window_get_transient_for(GTK_WINDOW(mShell)((((GtkWindow*) (void *) ((mShell))))));
1258 auto* window = nsWindow::FromGtkWidget(GTK_WIDGET(parentGtkWindow)((((GtkWidget*) (void *) ((parentGtkWindow))))));
1259 if (!window) {
1260 return;
1261 }
1262 GdkWindow* gdkWindow = window->GetGdkWindow();
1263 if (!gdkWindow) {
1264 return;
1265 }
1266
1267 int parentWidth = gdk_window_get_width(gdkWindow);
1268 int popupWidth = newRect.width;
1269
1270 int x;
1271 gdk_window_get_position(gdkWindow, &x, nullptr);
1272
1273 auto pos = newRect.TopLeft();
1274 // If popup is bigger than main window just center it.
1275 if (popupWidth > parentWidth) {
1276 pos.x = -(parentWidth - popupWidth) / 2 + x;
1277 } else {
1278 if (pos.x < x) {
1279 // Stick with left window edge if it's placed too left
1280 pos.x = x;
1281 } else if (pos.x + popupWidth > parentWidth + x) {
1282 // Stick with right window edge otherwise
1283 pos.x = parentWidth + x - popupWidth;
1284 }
1285 }
1286
1287 LOG(" set position [%d, %d]\n", pos.x.value, pos.y.value)do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " set position [%d, %d]\n", this->
GetDebugTag().get(), pos.x.value, pos.y.value); } } while (0)
;
1288 gtk_window_move(GTK_WINDOW(mShell)((((GtkWindow*) (void *) ((mShell))))), pos.x, pos.y);
1289
1290 LOG(" set size [%d, %d]\n", newRect.width, newRect.height)do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " set size [%d, %d]\n", this->GetDebugTag
().get(), newRect.width, newRect.height); } } while (0)
;
1291 gtk_window_resize(GTK_WINDOW(mShell)((((GtkWindow*) (void *) ((mShell))))), newRect.width, newRect.height);
1292
1293 if (pos.x != newRect.x) {
1294 mClientArea.MoveTo(pos);
1295 WaylandPopupPropagateChangesToLayout(/* move */ true, /* resize */ false);
1296 }
1297}
1298
1299bool nsWindowWaylandPopupGtk::WaylandPopupFitsToplevelWindow() {
1300 LOG("nsWindowWaylandPopupGtk::WaylandPopupFitsToplevelWindow()")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandPopupGtk::WaylandPopupFitsToplevelWindow()"
, this->GetDebugTag().get()); } } while (0)
;
1301
1302 GtkWindow* parent = gtk_window_get_transient_for(GTK_WINDOW(mShell)((((GtkWindow*) (void *) ((mShell))))));
1303 GtkWindow* tmp = parent;
Value stored to 'tmp' during its initialization is never read
1304 while ((tmp = gtk_window_get_transient_for(GTK_WINDOW(parent)((((GtkWindow*) (void *) ((parent)))))))) {
1305 parent = tmp;
1306 }
1307 GdkWindow* toplevelGdkWindow = gtk_widget_get_window(GTK_WIDGET(parent)((((GtkWidget*) (void *) ((parent))))));
1308 if (NS_WARN_IF(!toplevelGdkWindow)NS_warn_if_impl(!toplevelGdkWindow, "!toplevelGdkWindow", "/root/firefox-clang/widget/gtk/nsWindowWaylandGtk.cpp"
, 1308)
) {
1309 return false;
1310 }
1311
1312 int parentWidth = gdk_window_get_width(toplevelGdkWindow);
1313 int parentHeight = gdk_window_get_height(toplevelGdkWindow);
1314 DesktopIntRect parentWidgetRect(0, 0, parentWidth, parentHeight);
1315
1316 nsWindowWayland* parentWindow = nullptr;
1317 if (auto* window = nsWindow::FromGtkWidget(GTK_WIDGET(parent)((((GtkWidget*) (void *) ((parent))))))) {
1318 parentWindow = window->AsWayland();
1319 }
1320 if (!parentWindow) {
1321 return false;
1322 }
1323
1324 DesktopIntRect parentClientArea = parentWindow->GetClientArea();
1325 LOG(" parent size %d x %d", parentClientArea.width, parentClientArea.height)do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " parent size %d x %d", this->GetDebugTag
().get(), parentClientArea.width, parentClientArea.height); }
} while (0)
;
1326
1327 DesktopIntRect popupRect(mLastMoveRequest, mLastSizeRequest);
1328 LOG(" popup topleft %d, %d size %d x %d", popupRect.x, popupRect.y,do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " popup topleft %d, %d size %d x %d"
, this->GetDebugTag().get(), popupRect.x, popupRect.y, popupRect
.width, popupRect.height); } } while (0)
1329 popupRect.width, popupRect.height)do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " popup topleft %d, %d size %d x %d"
, this->GetDebugTag().get(), popupRect.x, popupRect.y, popupRect
.width, popupRect.height); } } while (0)
;
1330
1331 bool fits = parentClientArea.Contains(popupRect);
1332 LOG(" fits %d", fits)do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " fits %d", this->GetDebugTag()
.get(), fits); } } while (0)
;
1333 return fits;
1334}
1335
1336void nsWindowWaylandPopupGtk::NativeMoveResizeWaylandPopup(bool aMove,
1337 bool aResize) {
1338 GdkRectangle rect{mLastMoveRequest.x, mLastMoveRequest.y,
1339 mLastSizeRequest.width, mLastSizeRequest.height};
1340
1341 LOG("nsWindowWaylandPopupGtk::NativeMoveResizeWaylandPopup [%d,%d] -> [%d x "do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandPopupGtk::NativeMoveResizeWaylandPopup [%d,%d] -> [%d x "
"%d] " "move %d resize %d\n", this->GetDebugTag().get(), rect
.x, rect.y, rect.width, rect.height, aMove, aResize); } } while
(0)
1342 "%d] "do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandPopupGtk::NativeMoveResizeWaylandPopup [%d,%d] -> [%d x "
"%d] " "move %d resize %d\n", this->GetDebugTag().get(), rect
.x, rect.y, rect.width, rect.height, aMove, aResize); } } while
(0)
1343 "move %d resize %d\n",do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandPopupGtk::NativeMoveResizeWaylandPopup [%d,%d] -> [%d x "
"%d] " "move %d resize %d\n", this->GetDebugTag().get(), rect
.x, rect.y, rect.width, rect.height, aMove, aResize); } } while
(0)
1344 rect.x, rect.y, rect.width, rect.height, aMove, aResize)do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandPopupGtk::NativeMoveResizeWaylandPopup [%d,%d] -> [%d x "
"%d] " "move %d resize %d\n", this->GetDebugTag().get(), rect
.x, rect.y, rect.width, rect.height, aMove, aResize); } } while
(0)
;
1345
1346 // Compositor may be confused by windows with width/height = 0
1347 // and positioning such windows leads to Bug 1555866.
1348 if (!AreBoundsSane()) {
1349 LOG(" Bounds are not sane (width: %d height: %d)\n",do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " Bounds are not sane (width: %d height: %d)\n"
, this->GetDebugTag().get(), mLastSizeRequest.width, mLastSizeRequest
.height); } } while (0)
1350 mLastSizeRequest.width, mLastSizeRequest.height)do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " Bounds are not sane (width: %d height: %d)\n"
, this->GetDebugTag().get(), mLastSizeRequest.width, mLastSizeRequest
.height); } } while (0)
;
1351 return;
1352 }
1353
1354 // It's safe to expect the popup position is handled onwards.
1355 if (aMove) {
1356 mWaylandApplyPopupPositionBeforeShow = false;
1357 }
1358
1359 MOZ_ASSERT(mClientMargin.IsAllZero())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mClientMargin.IsAllZero())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mClientMargin.IsAllZero())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("mClientMargin.IsAllZero()"
, "/root/firefox-clang/widget/gtk/nsWindowWaylandGtk.cpp", 1359
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mClientMargin.IsAllZero()"
")"); do { MOZ_CrashSequence(__null, 1359); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1360
1361 if (mWaitingForMoveToRectCallback) {
1362 LOG(" waiting for move to rect, scheduling")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " waiting for move to rect, scheduling"
, this->GetDebugTag().get()); } } while (0)
;
1363 // mClientArea position must not be overwritten before it is applied.
1364 // OnShellConfigureEvent() will not set mClientArea to an old position for
1365 // GTK_WINDOW_POPUP.
1366 MOZ_ASSERT(gtk_window_get_window_type(GTK_WINDOW(mShell)) ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype(gtk_window_get_window_type(((((GtkWindow*) (void *) (
(mShell)))))) == GTK_WINDOW_POPUP)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(gtk_window_get_window_type((
(((GtkWindow*) (void *) ((mShell)))))) == GTK_WINDOW_POPUP)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("gtk_window_get_window_type(((((GtkWindow*) (void *) ((mShell)))))) == GTK_WINDOW_POPUP"
, "/root/firefox-clang/widget/gtk/nsWindowWaylandGtk.cpp", 1367
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "gtk_window_get_window_type(((((GtkWindow*) (void *) ((mShell)))))) == GTK_WINDOW_POPUP"
")"); do { MOZ_CrashSequence(__null, 1367); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1367 GTK_WINDOW_POPUP)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(gtk_window_get_window_type(((((GtkWindow*) (void *) (
(mShell)))))) == GTK_WINDOW_POPUP)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(gtk_window_get_window_type((
(((GtkWindow*) (void *) ((mShell)))))) == GTK_WINDOW_POPUP)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("gtk_window_get_window_type(((((GtkWindow*) (void *) ((mShell)))))) == GTK_WINDOW_POPUP"
, "/root/firefox-clang/widget/gtk/nsWindowWaylandGtk.cpp", 1367
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "gtk_window_get_window_type(((((GtkWindow*) (void *) ((mShell)))))) == GTK_WINDOW_POPUP"
")"); do { MOZ_CrashSequence(__null, 1367); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1368 mMovedAfterMoveToRect = aMove;
1369 mResizedAfterMoveToRect = aResize;
1370 return;
1371 }
1372
1373 mMovedAfterMoveToRect = false;
1374 mResizedAfterMoveToRect = false;
1375
1376 bool trackedInHierarchy = WaylandPopupConfigure();
1377 // Read popup position from layout if it was moved.
1378 // This position is used by move-to-rect method as we need anchor and other
1379 // info to place popup correctly.
1380 // We need WaylandPopupConfigure() to be called before to have all needed
1381 // popup info in place (mainly the anchored flag).
1382 if (aMove) {
1383 mPopupMoveToRectParams = WaylandPopupGetPositionFromLayout();
1384 }
1385 if (!trackedInHierarchy) {
1386 WaylandPopupSetDirectPosition();
1387 return;
1388 }
1389
1390 if (aResize) {
1391 LOG(" set size [%d, %d]\n", rect.width, rect.height)do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " set size [%d, %d]\n", this->GetDebugTag
().get(), rect.width, rect.height); } } while (0)
;
1392 gtk_window_resize(GTK_WINDOW(mShell)((((GtkWindow*) (void *) ((mShell))))), rect.width, rect.height);
1393 }
1394
1395 if (!aMove && WaylandPopupFitsToplevelWindow()) {
1396 // Popup position has not been changed and its position/size fits
1397 // parent window so no need to reposition the window.
1398 LOG(" fits parent window size, just resize\n")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " " fits parent window size, just resize\n"
, this->GetDebugTag().get()); } } while (0)
;
1399 return;
1400 }
1401
1402 // Mark popup as changed as we're updating position/size.
1403 mPopupChanged = true;
1404
1405 mClientArea = DesktopIntRect(mLastMoveRequest, mLastSizeRequest);
1406
1407 UpdateWaylandPopupHierarchy();
1408}
1409
1410bool nsWindowWaylandPopupGtk::ApplyEnterLeaveMutterWorkaround() {
1411 // Leave (popup) case; see
1412 // nsWindowWaylandToplevelGtk::ApplyEnterLeaveMutterWorkaround() for the
1413 // toplevel case and more context on this workaround.
1414 if (mWaylandWindowNext && gtk_window_get_type_hint(GTK_WINDOW(mShell)((((GtkWindow*) (void *) ((mShell)))))) ==
1415 GDK_WINDOW_TYPE_HINT_UTILITY) {
1416 LOG("nsWindowWaylandPopupGtk::ApplyEnterLeaveMutterWorkaround(): leave "do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandPopupGtk::ApplyEnterLeaveMutterWorkaround(): leave "
"popup", this->GetDebugTag().get()); } } while (0)
1417 "popup")do { const ::mozilla::LogModule* moz_real_module = this->IsPopup
() ? gWidgetPopupLog : gWidgetLog; if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, mozilla::LogLevel::Debug)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Debug, "%s: " "nsWindowWaylandPopupGtk::ApplyEnterLeaveMutterWorkaround(): leave "
"popup", this->GetDebugTag().get()); } } while (0)
;
1418 return true;
1419 }
1420 return false;
1421}