Bug 1218552 - Fix GTK drag-and-drop coordinate scaling on HiDPI displays (r=karlt)

This commit is contained in:
Bill McCloskey 2015-10-26 13:33:13 -07:00
parent 946855ad65
commit 164b197f13
6 changed files with 40 additions and 24 deletions

View File

@ -237,8 +237,12 @@ OnSourceGrabEventAfter(GtkWidget *widget, GdkEvent *event, gpointer user_data)
// Update the cursor position. The last of these recorded gets used for
// the eDragEnd event.
nsDragService *dragService = static_cast<nsDragService*>(user_data);
dragService->SetDragEndPoint(nsIntPoint(event->motion.x_root,
event->motion.y_root));
gint scale = nsScreenGtk::GetGtkMonitorScaleFactor();
LayoutDeviceIntPoint p = {
floor(event->motion.x_root * scale + 0.5),
floor(event->motion.y_root * scale + 0.5)
};
dragService->SetDragEndPoint(p);
} else if (sMotionEvent && (event->type == GDK_KEY_PRESS ||
event->type == GDK_KEY_RELEASE)) {
// Update modifier state from key events.
@ -396,7 +400,7 @@ nsDragService::InvokeDragSessionImpl(nsISupportsArray* aArrayTransferables,
G_CALLBACK(OnSourceGrabEventAfter), this);
}
// We don't have a drag end point yet.
mEndDragPoint = nsIntPoint(-1, -1);
mEndDragPoint = LayoutDeviceIntPoint(-1, -1);
rv = NS_OK;
}
else {
@ -1413,8 +1417,9 @@ nsDragService::SourceEndDragSession(GdkDragContext *aContext,
gint x, y;
GdkDisplay* display = gdk_display_get_default();
if (display) {
gint scale = nsScreenGtk::GetGtkMonitorScaleFactor();
gdk_display_get_pointer(display, nullptr, &x, &y, nullptr);
SetDragEndPoint(nsIntPoint(x, y));
SetDragEndPoint(LayoutDeviceIntPoint(x * scale, y * scale));
}
}
@ -1462,7 +1467,7 @@ nsDragService::SourceEndDragSession(GdkDragContext *aContext,
}
// Schedule the appropriate drag end dom events.
Schedule(eDragTaskSourceEnd, nullptr, nullptr, nsIntPoint(), 0);
Schedule(eDragTaskSourceEnd, nullptr, nullptr, LayoutDeviceIntPoint(), 0);
}
static void
@ -1783,7 +1788,7 @@ invisibleSourceDragEnd(GtkWidget *aWidget,
gboolean
nsDragService::ScheduleMotionEvent(nsWindow *aWindow,
GdkDragContext *aDragContext,
nsIntPoint aWindowPoint, guint aTime)
LayoutDeviceIntPoint aWindowPoint, guint aTime)
{
if (mScheduledTask == eDragTaskMotion) {
// The drag source has sent another motion message before we've
@ -1806,7 +1811,7 @@ nsDragService::ScheduleLeaveEvent()
// We don't know at this stage whether a drop signal will immediately
// follow. If the drop signal gets sent it will happen before we return
// to the main loop and the scheduled leave task will be replaced.
if (!Schedule(eDragTaskLeave, nullptr, nullptr, nsIntPoint(), 0)) {
if (!Schedule(eDragTaskLeave, nullptr, nullptr, LayoutDeviceIntPoint(), 0)) {
NS_WARNING("Drag leave after drop");
}
}
@ -1814,7 +1819,7 @@ nsDragService::ScheduleLeaveEvent()
gboolean
nsDragService::ScheduleDropEvent(nsWindow *aWindow,
GdkDragContext *aDragContext,
nsIntPoint aWindowPoint, guint aTime)
LayoutDeviceIntPoint aWindowPoint, guint aTime)
{
if (!Schedule(eDragTaskDrop, aWindow,
aDragContext, aWindowPoint, aTime)) {
@ -1822,7 +1827,7 @@ nsDragService::ScheduleDropEvent(nsWindow *aWindow,
return FALSE;
}
SetDragEndPoint(aWindowPoint + aWindow->WidgetToScreenOffsetUntyped());
SetDragEndPoint(aWindowPoint + aWindow->WidgetToScreenOffset());
// We'll reply with gtk_drag_finish().
return TRUE;
@ -1831,7 +1836,7 @@ nsDragService::ScheduleDropEvent(nsWindow *aWindow,
gboolean
nsDragService::Schedule(DragTask aTask, nsWindow *aWindow,
GdkDragContext *aDragContext,
nsIntPoint aWindowPoint, guint aTime)
LayoutDeviceIntPoint aWindowPoint, guint aTime)
{
// If there is an existing leave or motion task scheduled, then that
// will be replaced. When the new task is run, it will dispatch

View File

@ -96,12 +96,12 @@ public:
gboolean ScheduleMotionEvent(nsWindow *aWindow,
GdkDragContext *aDragContext,
nsIntPoint aWindowPoint,
mozilla::LayoutDeviceIntPoint aWindowPoint,
guint aTime);
void ScheduleLeaveEvent();
gboolean ScheduleDropEvent(nsWindow *aWindow,
GdkDragContext *aDragContext,
nsIntPoint aWindowPoint,
mozilla::LayoutDeviceIntPoint aWindowPoint,
guint aTime);
nsWindow* GetMostRecentDestWindow()
@ -154,7 +154,7 @@ private:
// when the scheduled task is run. mPendingWindow and mPendingDragContext
// will be nullptr if the scheduled task is eDragTaskLeave.
RefPtr<nsWindow> mPendingWindow;
nsIntPoint mPendingWindowPoint;
mozilla::LayoutDeviceIntPoint mPendingWindowPoint;
nsCountedRef<GdkDragContext> mPendingDragContext;
guint mPendingTime;
@ -162,7 +162,7 @@ private:
// eDragTaskMotion or eDragTaskDrop task that was run or is still running.
// mTargetWindow is cleared once the drag has completed or left.
RefPtr<nsWindow> mTargetWindow;
nsIntPoint mTargetWindowPoint;
mozilla::LayoutDeviceIntPoint mTargetWindowPoint;
// mTargetWidget and mTargetDragContext are set only while dispatching
// motion or drop events. mTime records the corresponding timestamp.
nsCountedRef<GtkWidget> mTargetWidget;
@ -210,7 +210,7 @@ private:
gboolean Schedule(DragTask aTask, nsWindow *aWindow,
GdkDragContext *aDragContext,
nsIntPoint aWindowPoint, guint aTime);
mozilla::LayoutDeviceIntPoint aWindowPoint, guint aTime);
// Callback for g_idle_add_full() to run mScheduledTask.
static gboolean TaskDispatchCallback(gpointer data);

View File

@ -3331,7 +3331,7 @@ nsWindow::ThemeChanged()
}
void
nsWindow::DispatchDragEvent(EventMessage aMsg, const nsIntPoint& aRefPoint,
nsWindow::DispatchDragEvent(EventMessage aMsg, const LayoutDeviceIntPoint& aRefPoint,
guint aTime)
{
WidgetDragEvent event(true, aMsg, this);
@ -3340,7 +3340,7 @@ nsWindow::DispatchDragEvent(EventMessage aMsg, const nsIntPoint& aRefPoint,
InitDragEvent(event);
}
event.refPoint = LayoutDeviceIntPoint::FromUntyped(aRefPoint);
event.refPoint = aRefPoint;
event.time = aTime;
event.timeStamp = GetEventTimeStamp(aTime);
@ -5978,9 +5978,11 @@ drag_motion_event_cb(GtkWidget *aWidget,
LOGDRAG(("nsWindow drag-motion signal for %p\n", (void*)innerMostWindow));
LayoutDeviceIntPoint point = window->GdkPointToDevicePixels({ retx, rety });
return nsDragService::GetInstance()->
ScheduleMotionEvent(innerMostWindow, aDragContext,
nsIntPoint(retx, rety), aTime);
point, aTime);
}
static void
@ -6048,9 +6050,11 @@ drag_drop_event_cb(GtkWidget *aWidget,
LOGDRAG(("nsWindow drag-drop signal for %p\n", (void*)innerMostWindow));
LayoutDeviceIntPoint point = window->GdkPointToDevicePixels({ retx, rety });
return nsDragService::GetInstance()->
ScheduleDropEvent(innerMostWindow, aDragContext,
nsIntPoint(retx, rety), aTime);
point, aTime);
}
static void

View File

@ -269,7 +269,7 @@ public:
bool IsDestroyed() { return mIsDestroyed; }
void DispatchDragEvent(mozilla::EventMessage aMsg,
const nsIntPoint& aRefPoint,
const mozilla::LayoutDeviceIntPoint& aRefPoint,
guint aTime);
static void UpdateDragStatus (GdkDragContext *aDragContext,
nsIDragService *aDragService);

View File

@ -217,7 +217,7 @@ nsBaseDragService::InvokeDragSession(nsIDOMNode *aDOMNode,
// stash the document of the dom node
aDOMNode->GetOwnerDocument(getter_AddRefs(mSourceDocument));
mSourceNode = aDOMNode;
mEndDragPoint = nsIntPoint(0, 0);
mEndDragPoint = LayoutDeviceIntPoint(0, 0);
// When the mouse goes down, the selection code starts a mouse
// capture. However, this gets in the way of determining drag
@ -413,7 +413,7 @@ nsBaseDragService::EndDragSession(bool aDoneDrag)
mImageOffset = CSSIntPoint();
mScreenX = -1;
mScreenY = -1;
mEndDragPoint = nsIntPoint(0, 0);
mEndDragPoint = LayoutDeviceIntPoint(0, 0);
mInputSource = nsIDOMMouseEvent::MOZ_SOURCE_MOUSE;
return NS_OK;

View File

@ -54,7 +54,14 @@ public:
NS_DECL_NSIDRAGSERVICE
NS_DECL_NSIDRAGSESSION
void SetDragEndPoint(nsIntPoint aEndDragPoint) { mEndDragPoint = aEndDragPoint; }
void SetDragEndPoint(nsIntPoint aEndDragPoint)
{
mEndDragPoint = mozilla::LayoutDeviceIntPoint::FromUntyped(aEndDragPoint);
}
void SetDragEndPoint(mozilla::LayoutDeviceIntPoint aEndDragPoint)
{
mEndDragPoint = aEndDragPoint;
}
uint16_t GetInputSource() { return mInputSource; }
@ -171,7 +178,7 @@ protected:
int32_t mScreenY;
// the screen position where the drag ended
nsIntPoint mEndDragPoint;
mozilla::LayoutDeviceIntPoint mEndDragPoint;
uint32_t mSuppressLevel;