зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1795849 [Linux] Chancel D&D operation on Wayland and XWayland when D&D source window is closing r=emilio
Differential Revision: https://phabricator.services.mozilla.com/D159588
This commit is contained in:
Родитель
4cc3078461
Коммит
599b985afe
|
@ -462,8 +462,7 @@ void GfxInfo::GetData() {
|
|||
// layer. For all intents and purposes, we should otherwise believe we are
|
||||
// using X11.
|
||||
mIsWayland = GdkIsWaylandDisplay();
|
||||
const char* waylandDisplay = getenv("WAYLAND_DISPLAY");
|
||||
mIsXWayland = !mIsWayland && waylandDisplay;
|
||||
mIsXWayland = IsXWaylandProtocol();
|
||||
|
||||
// Make a best effort guess at the desktop environment in use. Sadly there
|
||||
// does not appear to be a standard way to do this, so we check a few
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
#include "mozilla/UniquePtr.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsWindow.h"
|
||||
#include "nsIGfxInfo.h"
|
||||
#include "mozilla/Components.h"
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <dlfcn.h>
|
||||
|
@ -71,6 +73,13 @@ bool GdkIsX11Display(GdkDisplay* display) {
|
|||
G_TYPE_CHECK_INSTANCE_TYPE(display, sGdkX11DisplayGetType());
|
||||
}
|
||||
|
||||
bool IsXWaylandProtocol() {
|
||||
static bool isXwayland = [] {
|
||||
return !GdkIsWaylandDisplay() && !!getenv("WAYLAND_DISPLAY");
|
||||
}();
|
||||
return isXwayland;
|
||||
}
|
||||
|
||||
bool GdkIsWaylandDisplay() {
|
||||
static bool isWaylandDisplay = gdk_display_get_default() &&
|
||||
GdkIsWaylandDisplay(gdk_display_get_default());
|
||||
|
|
|
@ -31,6 +31,8 @@ bool GdkIsX11Display(GdkDisplay* display);
|
|||
bool GdkIsWaylandDisplay();
|
||||
bool GdkIsX11Display();
|
||||
|
||||
bool IsXWaylandProtocol();
|
||||
|
||||
GdkDevice* GdkGetPointer();
|
||||
|
||||
// Sets / returns the last mouse press event we processed.
|
||||
|
|
|
@ -168,13 +168,13 @@ nsDragService::nsDragService()
|
|||
}
|
||||
|
||||
// set up our logging module
|
||||
LOGDRAGSERVICE("nsDragService::nsDragService");
|
||||
mCanDrop = false;
|
||||
mTargetDragDataReceived = false;
|
||||
mTargetDragData = 0;
|
||||
mTargetDragDataLen = 0;
|
||||
mTempFileTimerID = 0;
|
||||
mEventLoopDepth = 0;
|
||||
LOGDRAGSERVICE("nsDragService::nsDragService");
|
||||
}
|
||||
|
||||
nsDragService::~nsDragService() {
|
||||
|
@ -388,8 +388,19 @@ nsresult nsDragService::InvokeDragSessionImpl(
|
|||
mHiddenWidget, sourceList, action, 1,
|
||||
existingEvent ? existingEvent : &fakeEvent, -1, -1);
|
||||
|
||||
LOGDRAGSERVICE("nsDragService::InvokeDragSessionImpl GdkDragContext %p",
|
||||
context);
|
||||
if (widget::GdkIsWaylandDisplay() || widget::IsXWaylandProtocol()) {
|
||||
GdkDevice* device = gdk_drag_context_get_device(context);
|
||||
GdkWindow* gdkWindow =
|
||||
gdk_device_get_window_at_position(device, nullptr, nullptr);
|
||||
mSourceWindow = nsWindow::GetWindow(gdkWindow);
|
||||
if (mSourceWindow) {
|
||||
mSourceWindow->SetDragSource(context);
|
||||
}
|
||||
}
|
||||
|
||||
LOGDRAGSERVICE(
|
||||
"nsDragService::InvokeDragSessionImpl GdkDragContext [%p] nsWindow [%p]",
|
||||
context, mSourceWindow.get());
|
||||
|
||||
nsresult rv;
|
||||
if (context) {
|
||||
|
@ -531,6 +542,10 @@ nsDragService::EndDragSession(bool aDoneDrag, uint32_t aKeyModifiers) {
|
|||
}
|
||||
|
||||
// We're done with the drag context.
|
||||
if (mSourceWindow) {
|
||||
mSourceWindow->SetDragSource(nullptr);
|
||||
mSourceWindow = nullptr;
|
||||
}
|
||||
mTargetDragContextForRemote = nullptr;
|
||||
mTargetWindow = nullptr;
|
||||
mPendingWindow = nullptr;
|
||||
|
|
|
@ -132,6 +132,9 @@ class nsDragService final : public nsBaseDragService, public nsIObserver {
|
|||
guint mTaskSource;
|
||||
bool mScheduledTaskIsRunning;
|
||||
|
||||
// Where the drag begins. We need to keep it open on Wayland.
|
||||
RefPtr<nsWindow> mSourceWindow;
|
||||
|
||||
// target/destination side vars
|
||||
// These variables keep track of the state of the current drag.
|
||||
|
||||
|
|
|
@ -1416,8 +1416,10 @@ void nsWindow::WaylandPopupHierarchyHideByLayout(
|
|||
// Hide all popups which are not in layout popup chain
|
||||
nsWindow* popup = mWaylandPopupNext;
|
||||
while (popup) {
|
||||
// Tooltips are not tracked in layout chain
|
||||
if (!popup->mPopupClosed && popup->mPopupType != ePopupTypeTooltip) {
|
||||
MOZ_ASSERT(popup->mPopupType != ePopupTypeTooltip,
|
||||
"Tooltips should be closed!");
|
||||
// Don't check closed popups and drag source popups
|
||||
if (!popup->mPopupClosed && !popup->mSourceDragContext) {
|
||||
if (!popup->IsPopupInLayoutPopupChain(aLayoutWidgetHierarchy,
|
||||
/* aMustMatchParent */ false)) {
|
||||
LOG(" hidding popup [%p]", popup);
|
||||
|
@ -4084,6 +4086,15 @@ void nsWindow::OnUnmap() {
|
|||
// untill OnUnrealize is called.
|
||||
mIsMapped = false;
|
||||
|
||||
if (mSourceDragContext) {
|
||||
static auto sGtkDragCancel =
|
||||
(void (*)(GdkDragContext*))dlsym(RTLD_DEFAULT, "gtk_drag_cancel");
|
||||
if (sGtkDragCancel) {
|
||||
sGtkDragCancel(mSourceDragContext);
|
||||
mSourceDragContext = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MOZ_WAYLAND
|
||||
// wl_surface owned by mContainer is going to be deleted.
|
||||
// Make sure we don't paint to it on Wayland.
|
||||
|
@ -5249,6 +5260,7 @@ void nsWindow::OnScaleChanged() {
|
|||
void nsWindow::DispatchDragEvent(EventMessage aMsg,
|
||||
const LayoutDeviceIntPoint& aRefPoint,
|
||||
guint aTime) {
|
||||
LOGDRAG("nsWindow::DispatchDragEvent");
|
||||
WidgetDragEvent event(true, aMsg, this);
|
||||
|
||||
InitDragEvent(event);
|
||||
|
@ -5265,7 +5277,7 @@ void nsWindow::OnDragDataReceivedEvent(GtkWidget* aWidget,
|
|||
GtkSelectionData* aSelectionData,
|
||||
guint aInfo, guint aTime,
|
||||
gpointer aData) {
|
||||
LOGDRAG("nsWindow::OnDragDataReceived(%p)\n", (void*)this);
|
||||
LOGDRAG("nsWindow::OnDragDataReceived");
|
||||
|
||||
RefPtr<nsDragService> dragService = nsDragService::GetInstance();
|
||||
nsDragService::AutoEventLoop loop(dragService);
|
||||
|
@ -7437,6 +7449,7 @@ void nsWindow::HideWindowChrome(bool aShouldHide) {
|
|||
|
||||
bool nsWindow::CheckForRollup(gdouble aMouseX, gdouble aMouseY, bool aIsWheel,
|
||||
bool aAlwaysRollup) {
|
||||
LOG("nsWindow::CheckForRollup() aAlwaysRollup %d", aAlwaysRollup);
|
||||
nsIRollupListener* rollupListener = GetActiveRollupListener();
|
||||
nsCOMPtr<nsIWidget> rollupWidget;
|
||||
if (rollupListener) {
|
||||
|
@ -7550,13 +7563,11 @@ MOZ_CAN_RUN_SCRIPT static void WaylandDragWorkaround(GdkEventButton* aEvent) {
|
|||
|
||||
static nsWindow* get_window_for_gtk_widget(GtkWidget* widget) {
|
||||
gpointer user_data = g_object_get_data(G_OBJECT(widget), "nsWindow");
|
||||
|
||||
return static_cast<nsWindow*>(user_data);
|
||||
}
|
||||
|
||||
static nsWindow* get_window_for_gdk_window(GdkWindow* window) {
|
||||
gpointer user_data = g_object_get_data(G_OBJECT(window), "nsWindow");
|
||||
|
||||
return static_cast<nsWindow*>(user_data);
|
||||
}
|
||||
|
||||
|
@ -9749,6 +9760,10 @@ LayoutDeviceIntSize nsWindow::GetMozContainerSize() {
|
|||
return size;
|
||||
}
|
||||
|
||||
nsWindow* nsWindow::GetWindow(GdkWindow* window) {
|
||||
return get_window_for_gdk_window(window);
|
||||
}
|
||||
|
||||
void nsWindow::ClearRenderingQueue() {
|
||||
LOG("nsWindow::ClearRenderingQueue()");
|
||||
|
||||
|
@ -9813,3 +9828,7 @@ void nsWindow::NotifyOcclusionState(mozilla::widget::OcclusionState aState) {
|
|||
mWidgetListener->OcclusionStateChanged(mIsFullyOccluded);
|
||||
}
|
||||
}
|
||||
|
||||
void nsWindow::SetDragSource(GdkDragContext* aSourceDragContext) {
|
||||
mSourceDragContext = aSourceDragContext;
|
||||
}
|
||||
|
|
|
@ -295,6 +295,7 @@ class nsWindow final : public nsBaseWidget {
|
|||
const LayoutDeviceIntPoint& aRefPoint, guint aTime);
|
||||
static void UpdateDragStatus(GdkDragContext* aDragContext,
|
||||
nsIDragService* aDragService);
|
||||
void SetDragSource(GdkDragContext* aSourceDragContext);
|
||||
|
||||
WidgetEventTime GetWidgetEventTime(guint32 aEventTime);
|
||||
mozilla::TimeStamp GetEventTimeStamp(guint32 aEventTime);
|
||||
|
@ -461,6 +462,8 @@ class nsWindow final : public nsBaseWidget {
|
|||
|
||||
void NotifyOcclusionState(mozilla::widget::OcclusionState aState) override;
|
||||
|
||||
static nsWindow* GetWindow(GdkWindow* window);
|
||||
|
||||
protected:
|
||||
virtual ~nsWindow();
|
||||
|
||||
|
@ -980,6 +983,7 @@ class nsWindow final : public nsBaseWidget {
|
|||
xdg_activation_token_v1* mXdgToken = nullptr;
|
||||
#endif
|
||||
mozilla::widget::WindowSurfaceProvider mSurfaceProvider;
|
||||
GdkDragContext* mSourceDragContext = nullptr;
|
||||
};
|
||||
|
||||
#endif /* __nsWindow_h__ */
|
||||
|
|
Загрузка…
Ссылка в новой задаче