Bug 1745590 [Wayland] Don't use external GtkWidget as focus source, r=emilio

We get wl_keyboard_enter event for all wl_surfaces which includes file dialogs owned by Gtk.
We can't use such wl_surface as focus source as it's not owned/managed by Firefox.

When we request focus on Wayland, check that we should have the focus (by gFocusWindow)
and also check if we really have it (by comparing wl_surface owned by gFocusWindow and
wl_surface obtained from wl_keyboard_enter).

Differential Revision: https://phabricator.services.mozilla.com/D133634
This commit is contained in:
stransky 2021-12-14 08:37:13 +00:00
Родитель 83c32ae54f
Коммит 431724df87
3 изменённых файлов: 37 добавлений и 13 удалений

Просмотреть файл

@ -2424,17 +2424,23 @@ void KeymapWrapper::WillDispatchKeyboardEventInternal(
#ifdef MOZ_WAYLAND
void KeymapWrapper::SetFocusIn(wl_surface* aFocusSurface,
uint32_t aFocusSerial) {
LOGW("KeymapWrapper::SetFocusIn() surface %p ID %d serial %d", aFocusSurface,
aFocusSurface ? wl_proxy_get_id((struct wl_proxy*)aFocusSurface) : 0,
aFocusSerial);
KeymapWrapper* keymapWrapper = KeymapWrapper::GetInstance();
keymapWrapper->mFocusSurface = aFocusSurface;
keymapWrapper->mFocusSerial = aFocusSerial;
}
// aFocusSurface can be null in case that focused surface is already destroyed.
void KeymapWrapper::SetFocusOut(wl_surface* aFocusSurface) {
KeymapWrapper* keymapWrapper = KeymapWrapper::GetInstance();
if (aFocusSurface == keymapWrapper->mFocusSurface) {
keymapWrapper->mFocusSurface = nullptr;
keymapWrapper->mFocusSerial = 0;
}
LOGW("KeymapWrapper::SetFocusOut surface %p ID %d", aFocusSurface,
aFocusSurface ? wl_proxy_get_id((struct wl_proxy*)aFocusSurface) : 0);
keymapWrapper->mFocusSurface = nullptr;
keymapWrapper->mFocusSerial = 0;
}
void KeymapWrapper::GetFocusInfo(wl_surface** aFocusSurface,
@ -2453,7 +2459,6 @@ wl_seat* KeymapWrapper::GetSeat() {
KeymapWrapper* keymapWrapper = KeymapWrapper::GetInstance();
return keymapWrapper->mSeat;
}
#endif
} // namespace widget

Просмотреть файл

@ -2845,6 +2845,9 @@ void nsWindow::FocusWaylandWindow(const char* aTokenID) {
return;
}
LOG(" requesting xdg-activation, surface ID %d",
wl_proxy_get_id((struct wl_proxy*)surface));
xdg_activation_v1* xdg_activation = WaylandDisplayGet()->GetXdgActivation();
xdg_activation_v1_activate(xdg_activation, aTokenID, surface);
}
@ -2862,12 +2865,17 @@ static const struct xdg_activation_token_v1_listener token_listener = {
};
void nsWindow::RequestFocusWaylandWindow(RefPtr<nsWindow> aWindow) {
LOG("nsWindow::RequestWindowFocusWayland(%p)", (void*)aWindow);
LOGW("nsWindow::RequestFocusWaylandWindow(%p) gFocusWindow %p",
(void*)aWindow, gFocusWindow);
if (!gFocusWindow) {
LOGW(" missing gFocusWindow, quit.");
}
RefPtr<nsWaylandDisplay> display = WaylandDisplayGet();
xdg_activation_v1* xdg_activation = display->GetXdgActivation();
if (!xdg_activation) {
LOG(" xdg-activation is missing, quit.");
LOGW(" xdg-activation is missing, quit.");
return;
}
@ -2875,13 +2883,25 @@ void nsWindow::RequestFocusWaylandWindow(RefPtr<nsWindow> aWindow) {
uint32_t focusSerial;
KeymapWrapper::GetFocusInfo(&focusSurface, &focusSerial);
if (!focusSurface) {
LOG(" We're missing focused window, quit.");
LOGW(" We're missing focused window, quit.");
return;
}
LOG(" requesting xdg-activation token, surface ID %d serial %d seat ID %d",
wl_proxy_get_id((struct wl_proxy*)focusSurface), focusSerial,
wl_proxy_get_id((struct wl_proxy*)KeymapWrapper::GetSeat()));
GdkWindow* gdkWindow = gtk_widget_get_window(gFocusWindow->mShell);
wl_surface* surface =
gdkWindow ? gdk_wayland_window_get_wl_surface(gdkWindow) : nullptr;
if (focusSurface != surface) {
LOGW(" focused surface %p and gFocusWindow surface %p don't match, quit.",
focusSurface, surface);
return;
}
LOGW(
" requesting xdg-activation token, surface %p ID %d serial %d seat ID "
"%d",
focusSurface,
focusSurface ? wl_proxy_get_id((struct wl_proxy*)focusSurface) : 0,
focusSerial, wl_proxy_get_id((struct wl_proxy*)KeymapWrapper::GetSeat()));
// Store activation token at activated window for further release.
g_clear_pointer(&aWindow->mXdgToken, xdg_activation_token_v1_destroy);

Просмотреть файл

@ -386,8 +386,7 @@ class nsWindow final : public nsBaseWidget {
#ifdef MOZ_WAYLAND
// Use xdg-activation protocol to transfer focus from gFocusWindow to aWindow.
// RequestFocusWaylandWindow needs to be called on focused window only.
void RequestFocusWaylandWindow(RefPtr<nsWindow> aWindow);
static void RequestFocusWaylandWindow(RefPtr<nsWindow> aWindow);
void FocusWaylandWindow(const char* aTokenID);
bool GetCSDDecorationOffset(int* aDx, int* aDy);