Skip to content

Commit

Permalink
Bug 1622107 [Wayland] Reset Drag and Drop operation when compositor f…
Browse files Browse the repository at this point in the history
…ails to cancel it, r=jhorak

This is a workaround for https://gitlab.gnome.org/GNOME/mutter/-/issues/1658

Wayland compositor sometimes fails to send wl_data_source::cancelled() so we don't get info that the D&D is finished
and it's still marked as active internally which preverts Firefox to do any further D&D operation.

In the patch we detect such scenario and reset internal D&D state.

Differential Revision: https://phabricator.services.mozilla.com/D106266
  • Loading branch information
stransky committed Mar 1, 2021
1 parent b5b2bab commit c9635cd
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 2 deletions.
41 changes: 39 additions & 2 deletions widget/gtk/nsWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3699,6 +3699,10 @@ void nsWindow::OnButtonPressEvent(GdkEventButton* aEvent) {
if (!StaticPrefs::ui_context_menus_after_mouseup()) {
DispatchContextMenuEventFromMouseEvent(domButton, aEvent);
}

if (!mIsX11Display) {
WaylandDragWorkaround(aEvent);
}
}

void nsWindow::OnButtonReleaseEvent(GdkEventButton* aEvent) {
Expand Down Expand Up @@ -6453,15 +6457,48 @@ bool nsWindow::CheckForRollup(gdouble aMouseX, gdouble aMouseY, bool aIsWheel,
/* static */
bool nsWindow::DragInProgress(void) {
nsCOMPtr<nsIDragService> dragService = do_GetService(kCDragServiceCID);

if (!dragService) return false;
if (!dragService) {
return false;
}

nsCOMPtr<nsIDragSession> currentDragSession;
dragService->GetCurrentSession(getter_AddRefs(currentDragSession));

return currentDragSession != nullptr;
}

// This is an ugly workaround for
// https://bugzilla.mozilla.org/show_bug.cgi?id=1622107
// We try to detect when Wayland compositor / gtk fails to deliver
// info about finished D&D operations and cancel it on our own.
void nsWindow::WaylandDragWorkaround(GdkEventButton* aEvent) {
static int buttonPressCountWithDrag = 0;

// We track only left button state as Firefox performs D&D on left
// button only.
if (aEvent->button != 1 || aEvent->type != GDK_BUTTON_PRESS) {
return;
}

nsCOMPtr<nsIDragService> dragService = do_GetService(kCDragServiceCID);
if (!dragService) {
return;
}
nsCOMPtr<nsIDragSession> currentDragSession;
dragService->GetCurrentSession(getter_AddRefs(currentDragSession));

if (currentDragSession != nullptr) {
buttonPressCountWithDrag++;
if (buttonPressCountWithDrag > 1) {
NS_WARNING(
"Quit unfinished Wayland Drag and Drop operation. Buggy Wayland "
"compositor?");
buttonPressCountWithDrag = 0;
dragService->EndDragSession(false, 0);
}
}
}

static bool is_mouse_in_window(GdkWindow* aWindow, gdouble aMouseX,
gdouble aMouseY) {
gint x = 0;
Expand Down
1 change: 1 addition & 0 deletions widget/gtk/nsWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ class nsWindow final : public nsBaseWidget {
bool GetCSDDecorationOffset(int* aDx, int* aDy);
void SetEGLNativeWindowSize(const LayoutDeviceIntSize& aEGLWindowSize);
static nsWindow* GetFocusedWindow();
void WaylandDragWorkaround(GdkEventButton* aEvent);
#endif

RefPtr<mozilla::gfx::VsyncSource> GetVsyncSource() override;
Expand Down

0 comments on commit c9635cd

Please sign in to comment.