Skip to content

Commit

Permalink
Bug 1804877 [Wayland] Rename nsWindow::RequestFocusWaylandWindow to n…
Browse files Browse the repository at this point in the history
…sWindow::TransferFocusToWaylandWindow() and use FocusWaylandWindow() there r=emilio

Depends on D165150

Differential Revision: https://phabricator.services.mozilla.com/D165151
  • Loading branch information
stransky committed Jan 3, 2023
1 parent 82686d5 commit 7410a96
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 79 deletions.
109 changes: 32 additions & 77 deletions widget/gtk/nsWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -608,7 +608,6 @@ void nsWindow::Destroy() {
mWaylandVsyncSource = nullptr;
}
mWaylandVsyncDispatcher = nullptr;
MozClearPointer(mXdgToken, xdg_activation_token_v1_destroy);
#endif

/** Need to clean our LayerManager up while still alive */
Expand Down Expand Up @@ -3038,7 +3037,8 @@ void nsWindow::SetUserTimeAndStartupTokenForActivatedWindow() {
gtk_window_set_startup_id(GTK_WINDOW(mShell),
mWindowActivationTokenFromEnv.get());
// In the case of X11, the above call is all we need. For wayland we need
// to keep the token around until we take it in RequestFocusWaylandWindow.
// to keep the token around until we take it in
// TransferFocusToWaylandWindow.
mWindowActivationTokenFromEnv.Truncate();
}
} else if (uint32_t timestamp = toolkit->GetFocusTimestamp()) {
Expand Down Expand Up @@ -3083,8 +3083,6 @@ guint32 nsWindow::GetLastUserInputTime() {
#ifdef MOZ_WAYLAND
void nsWindow::FocusWaylandWindow(const char* aTokenID) {
MOZ_DIAGNOSTIC_ASSERT(aTokenID);
auto releaseToken = MakeScopeExit(
[&] { MozClearPointer(mXdgToken, xdg_activation_token_v1_destroy); });

LOG("nsWindow::FocusWaylandWindow(%s)", aTokenID);
if (IsDestroyed()) {
Expand All @@ -3107,80 +3105,26 @@ void nsWindow::FocusWaylandWindow(const char* aTokenID) {
xdg_activation_v1_activate(xdg_activation, aTokenID, surface);
}

// We've got activation token from Wayland compositor so it's time to use it.
static void token_done(gpointer data, struct xdg_activation_token_v1* provider,
const char* token) {
// Compensate aWindow->AddRef() from nsWindow::RequestFocusWaylandWindow().
RefPtr<nsWindow> window = dont_AddRef(static_cast<nsWindow*>(data));
window->FocusWaylandWindow(token);
}

static const struct xdg_activation_token_v1_listener token_listener = {
token_done,
};

void nsWindow::RequestFocusWaylandWindow(RefPtr<nsWindow> aWindow) {
LOGW("nsWindow::RequestFocusWaylandWindow(%p) gFocusWindow %p", aWindow.get(),
// Transfer focus from gFocusWindow to aWindow and use xdg_activation
// protocol for it.
void nsWindow::TransferFocusToWaylandWindow(nsWindow* aWindow) {
LOGW("nsWindow::TransferFocusToWaylandWindow(%p) gFocusWindow %p", aWindow,
gFocusWindow);

auto existingToken = std::move(aWindow->mWindowActivationTokenFromEnv);
if (!existingToken.IsEmpty()) {
LOGW(" has existing activation token.");
aWindow->FocusWaylandWindow(existingToken.get());
return;
}

if (!gFocusWindow || gFocusWindow->IsDestroyed()) {
LOGW(" missing gFocusWindow, quit.");
return;
}

RefPtr<nsWaylandDisplay> display = WaylandDisplayGet();
xdg_activation_v1* xdg_activation = display->GetXdgActivation();
if (!xdg_activation) {
LOGW(" xdg-activation is missing, quit.");
return;
}

wl_surface* focusSurface;
uint32_t focusSerial;
KeymapWrapper::GetFocusInfo(&focusSurface, &focusSerial);
if (!focusSurface) {
LOGW(" We're missing KeymapWrapper focused window, quit.");
return;
}

GdkWindow* gdkWindow = gtk_widget_get_window(gFocusWindow->mShell);
if (!gdkWindow) {
LOGW(" gFocusWindow is not mapped, quit.");
return;
}
wl_surface* surface = gdk_wayland_window_get_wl_surface(gdkWindow);
if (focusSurface != surface) {
LOGW(" focused surface %p and gFocusWindow surface %p don't match, quit.",
focusSurface, surface);
auto promise = mozilla::widget::RequestWaylandFocusPromise();
if (NS_WARN_IF(!promise)) {
LOGW(" quit, failed to create TransferFocusToWaylandWindow [%p]", aWindow);
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.
MozClearPointer(aWindow->mXdgToken, xdg_activation_token_v1_destroy);
aWindow->mXdgToken = xdg_activation_v1_get_activation_token(xdg_activation);

// Addref aWindow to avoid potential release untill we get token_done
// callback.
xdg_activation_token_v1_add_listener(aWindow->mXdgToken, &token_listener,
do_AddRef(aWindow).take());
xdg_activation_token_v1_set_serial(aWindow->mXdgToken, focusSerial,
KeymapWrapper::GetSeat());
xdg_activation_token_v1_set_surface(aWindow->mXdgToken, focusSurface);
xdg_activation_token_v1_commit(aWindow->mXdgToken);
promise->Then(
GetMainThreadSerialEventTarget(), __func__,
/* resolve */
[window = RefPtr{aWindow}](nsCString token) {
window->FocusWaylandWindow(token.get());
},
/* reject */
[window = RefPtr{aWindow}](bool state) {
LOGW("TransferFocusToWaylandWindow [%p] failed", window.get());
});
}
#endif

Expand All @@ -3207,6 +3151,7 @@ void nsWindow::SetFocus(Raise aRaise, mozilla::dom::CallerType aCallerType) {
aRaise == Raise::Yes && toplevelWidget &&
!gtk_widget_has_focus(toplevelWidget)) {
if (gtk_widget_get_visible(mShell)) {
LOG(" toplevel is not focused");
gdk_window_show_unraised(gtk_widget_get_window(mShell));
// Unset the urgency hint if possible.
SetUrgencyHint(mShell, false);
Expand All @@ -3227,7 +3172,8 @@ void nsWindow::SetFocus(Raise aRaise, mozilla::dom::CallerType aCallerType) {
if (StaticPrefs::mozilla_widget_raise_on_setfocus_AtStartup() &&
toplevelWindow->mIsShown && toplevelWindow->mShell &&
!gtk_window_is_active(GTK_WINDOW(toplevelWindow->mShell))) {
LOG(" requesting toplevel activation [%p]\n", toplevelWindow.get());
LOG(" toplevel is visible but not active, requesting activation [%p]",
toplevelWindow.get());

// Take the time here explicitly for the call below.
const uint32_t timestamp = [&] {
Expand All @@ -3246,7 +3192,16 @@ void nsWindow::SetFocus(Raise aRaise, mozilla::dom::CallerType aCallerType) {

#ifdef MOZ_WAYLAND
if (GdkIsWaylandDisplay()) {
RequestFocusWaylandWindow(toplevelWindow);
auto existingToken =
std::move(toplevelWindow->mWindowActivationTokenFromEnv);
if (!existingToken.IsEmpty()) {
LOG(" has existing activation token.");
toplevelWindow->FocusWaylandWindow(existingToken.get());
} else {
LOG(" missing activation token, try to transfer from focused "
"window");
TransferFocusToWaylandWindow(toplevelWindow);
}
}
#endif
}
Expand Down
3 changes: 1 addition & 2 deletions widget/gtk/nsWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@ class nsWindow final : public nsBaseWidget {

#ifdef MOZ_WAYLAND
// Use xdg-activation protocol to transfer focus from gFocusWindow to aWindow.
static void RequestFocusWaylandWindow(RefPtr<nsWindow> aWindow);
static void TransferFocusToWaylandWindow(nsWindow* aWindow);
void FocusWaylandWindow(const char* aTokenID);

bool GetCSDDecorationOffset(int* aDx, int* aDy);
Expand Down Expand Up @@ -979,7 +979,6 @@ class nsWindow final : public nsBaseWidget {
LayoutDeviceIntPoint mNativePointerLockCenter;
zwp_locked_pointer_v1* mLockedPointer = nullptr;
zwp_relative_pointer_v1* mRelativePointer = nullptr;
xdg_activation_token_v1* mXdgToken = nullptr;
#endif
// An activation token from our environment (see handling of the
// XDG_ACTIVATION_TOKEN/DESKTOP_STARTUP_ID) env vars.
Expand Down

0 comments on commit 7410a96

Please sign in to comment.