Commit d8cb8fea authored by stransky's avatar stransky
Browse files

Bug 1731752 [Linux] Keep D&D data cache until GdkDragContext change, r=emilio

parent 1749ba14
Loading
Loading
Loading
Loading
+14 −9
Original line number Diff line number Diff line
@@ -114,7 +114,8 @@ static void invisibleSourceDragDataGet(GtkWidget* aWidget,
nsDragService::nsDragService()
    : mScheduledTask(eDragTaskNone),
      mTaskSource(0),
      mScheduledTaskIsRunning(false)
      mScheduledTaskIsRunning(false),
      mCachedDragContext()
#ifdef MOZ_WAYLAND
      ,
      mPendingWaylandDataOffer(nullptr),
@@ -485,6 +486,7 @@ nsDragService::EndDragSession(bool aDoneDrag, uint32_t aKeyModifiers) {
#endif
  mTargetWindow = nullptr;
  mPendingWindow = nullptr;
  mCachedDragContext = 0;

  return nsBaseDragService::EndDragSession(aDoneDrag, aKeyModifiers);
}
@@ -1038,6 +1040,14 @@ void nsDragService::ReplyToDragMotion(RefPtr<DataOffer> aDragContext) {
}
#endif

void nsDragService::EnsureCachedDataValidForContext(
    GdkDragContext* aDragContext) {
  if (mCachedDragContext != (uintptr_t)aDragContext) {
    mCachedData.Clear();
    mCachedDragContext = (uintptr_t)aDragContext;
  }
}

void nsDragService::TargetDataReceived(GtkWidget* aWidget,
                                       GdkDragContext* aContext, gint aX,
                                       gint aY,
@@ -1046,6 +1056,8 @@ void nsDragService::TargetDataReceived(GtkWidget* aWidget,
  LOGDRAGSERVICE(("nsDragService::TargetDataReceived"));
  TargetResetData();

  EnsureCachedDataValidForContext(aContext);

  mTargetDragDataReceived = true;
  gint len = gtk_selection_data_get_length(aSelectionData);
  const guchar* data = gtk_selection_data_get_data(aSelectionData);
@@ -1146,6 +1158,7 @@ void nsDragService::GetTargetDragData(GdkAtom aFlavor,
    // as mTargetDragContext.
    // Especially with multiple items the same data is requested
    // very often.
    EnsureCachedDataValidForContext(mTargetDragContext);
    if (auto cached = mCachedData.Lookup(flavor)) {
      mTargetDragDataLen = cached->Length();
      LOGDRAGSERVICE(("Using cached data for %s, length is %d", flavor.get(),
@@ -2017,8 +2030,6 @@ gboolean nsDragService::RunScheduledTask() {
#endif
  mTargetTime = mPendingTime;

  mCachedData.Clear();

  // http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html#drag-and-drop-processing-model
  // (as at 27 December 2010) indicates that a "drop" event should only be
  // fired (at the current target element) if the current drag operation is
@@ -2079,10 +2090,6 @@ gboolean nsDragService::RunScheduledTask() {
      gtk_drag_finish(mTargetDragContext, success,
                      /* del = */ FALSE, mTargetTime);
    }

    // This drag is over, so clear out our reference to the previous
    // window.
    mTargetWindow = nullptr;
    // Make sure to end the drag session. If this drag started in a
    // different app, we won't get a drag_end signal to end it from.
    EndDragSession(true, GetCurrentModifiers());
@@ -2096,8 +2103,6 @@ gboolean nsDragService::RunScheduledTask() {
  mTargetWaylandDataOffer = nullptr;
#endif

  mCachedData.Clear();

  // If we got another drag signal while running the sheduled task, that
  // must have happened while running a nested event loop.  Leave the task
  // source on the event loop.
+8 −0
Original line number Diff line number Diff line
@@ -138,6 +138,11 @@ class nsDragService final : public nsBaseDragService, public nsIObserver {
  // We cache all data for the current drag context,
  // because waiting for the data in GetTargetDragData can be very slow.
  nsTHashMap<nsCStringHashKey, nsTArray<uint8_t>> mCachedData;
  // mCachedData are tied to mCachedDragContext. mCachedDragContext is not
  // ref counted and may be already deleted on Gtk side.
  // We used it for mCachedData invalidation only and can't be used for
  // any D&D operation.
  uintptr_t mCachedDragContext;

#ifdef MOZ_WAYLAND
  RefPtr<DataOffer> mPendingWaylandDataOffer;
@@ -186,6 +191,9 @@ class nsDragService final : public nsBaseDragService, public nsIObserver {
  void GetTargetDragData(GdkAtom aFlavor, nsTArray<nsCString>& aDropFlavors);
  // this will reset all of the target vars
  void TargetResetData(void);
  // Ensure our data cache belongs to aDragContext and clear the cache if
  // aDragContext is different than mCachedDragContext.
  void EnsureCachedDataValidForContext(GdkDragContext* aDragContext);

  // source side vars