vcl/unx/gtk3/gtkinst.cxx |   98 +++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 91 insertions(+), 7 deletions(-)

New commits:
commit 231ad90b597410cab7f4f2e9a7b4547d97fb9972
Author:     Caolán McNamara <caol...@redhat.com>
AuthorDate: Thu Jan 19 15:37:31 2023 +0000
Commit:     Caolán McNamara <caol...@redhat.com>
CommitDate: Fri Jan 20 08:53:53 2023 +0000

    tdf#149412 gtk3: show all selected rows in dnd icon
    
    otherwise it looks like only one row is getting moved
    
    Change-Id: Ie0b63a9c3cea377c3753785d9c6f7958cbc7ac1b
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145818
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caol...@redhat.com>

diff --git a/vcl/unx/gtk3/gtkinst.cxx b/vcl/unx/gtk3/gtkinst.cxx
index 4fa9dce0a5b5..339958ff606d 100644
--- a/vcl/unx/gtk3/gtkinst.cxx
+++ b/vcl/unx/gtk3/gtkinst.cxx
@@ -2829,8 +2829,10 @@ private:
 #endif
     int m_nPressedButton;
 #if !GTK_CHECK_VERSION(4, 0, 0)
+protected:
     int m_nPressStartX;
     int m_nPressStartY;
+private:
 #endif
     ImplSVEvent* m_pDragCancelEvent;
     GtkCssProvider* m_pBgCssProvider;
@@ -3267,6 +3269,14 @@ private:
         return false;
     }
 
+#if GTK_CHECK_VERSION(4, 0, 0)
+    virtual void drag_set_icon(GtkDragSource*)
+#else
+    virtual void drag_set_icon(GdkDragContext*)
+#endif
+    {
+    }
+
 #if GTK_CHECK_VERSION(4, 0, 0)
     void signal_drag_begin(GtkDragSource* context)
 #else
@@ -3278,19 +3288,22 @@ private:
         {
 #if !GTK_CHECK_VERSION(4, 0, 0)
             launch_drag_cancel(context);
-#else
-            (void)context;
 #endif
             return;
         }
-#if !GTK_CHECK_VERSION(4, 0, 0)
         if (bUnsetDragIcon)
         {
+#if !GTK_CHECK_VERSION(4, 0, 0)
             cairo_surface_t *surface = 
cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 0, 0);
             gtk_drag_set_icon_surface(context, surface);
             cairo_surface_destroy(surface);
-        }
 #endif
+        }
+        else
+        {
+            drag_set_icon(context);
+        }
+
         if (!m_xDragSource)
             return;
         m_xDragSource->setActiveDragSource();
@@ -4902,11 +4915,11 @@ namespace
     {
         Size aSize(rDevice.GetOutputSizePixel());
         cairo_surface_t* orig_surface = get_underlying_cairo_surface(rDevice);
-        double m_fXScale, m_fYScale;
-        dl_cairo_surface_get_device_scale(orig_surface, &m_fXScale, 
&m_fYScale);
+        double fXScale, fYScale;
+        dl_cairo_surface_get_device_scale(orig_surface, &fXScale, &fYScale);
 
         cairo_surface_t* surface;
-        if (m_fXScale != 1.0 || m_fYScale != -1)
+        if (fXScale != 1.0 || fYScale != -1)
         {
             surface = cairo_surface_create_similar_image(orig_surface,
                                                          CAIRO_FORMAT_ARGB32,
@@ -16441,6 +16454,77 @@ public:
         return false;
     }
 
+#if GTK_CHECK_VERSION(4, 0, 0)
+    virtual void drag_set_icon(GtkDragSource*) override
+    {
+    }
+#else
+    virtual void drag_set_icon(GdkDragContext* context) override
+    {
+        GtkTreeSelection *selection = gtk_tree_view_get_selection(m_pTreeView);
+        if (gtk_tree_selection_get_mode(selection) == GTK_SELECTION_MULTIPLE)
+        {
+            int nWidth = 0;
+            int nHeight = 0;
+
+            GList* pList = 
gtk_tree_selection_get_selected_rows(gtk_tree_view_get_selection(m_pTreeView), 
nullptr);
+            std::vector<cairo_surface_t*> surfaces;
+            std::vector<int> heights;
+            for (GList* pItem = g_list_first(pList); pItem; pItem = 
g_list_next(pItem))
+            {
+                GtkTreePath* pPath = static_cast<GtkTreePath*>(pItem->data);
+
+                
surfaces.push_back(gtk_tree_view_create_row_drag_icon(m_pTreeView, pPath));
+
+                double x1, x2, y1, y2;
+                cairo_t* cr = cairo_create(surfaces.back());
+                cairo_clip_extents(cr, &x1, &y1, &x2, &y2);
+                cairo_destroy(cr);
+
+                heights.push_back(y2 - y1);
+
+                nWidth = std::max(nWidth, static_cast<int>(x2 - x1));
+                nHeight += heights.back();
+            }
+            g_list_free_full(pList, 
reinterpret_cast<GDestroyNotify>(gtk_tree_path_free));
+
+            // if its just one, then don't do anything and leave the default 
dnd icon as-is
+            if (surfaces.size() > 1)
+            {
+                cairo_surface_t* target = 
cairo_surface_create_similar(surfaces[0],
+                                                                       
cairo_surface_get_content(surfaces[0]),
+                                                                       nWidth,
+                                                                       
nHeight);
+
+                cairo_t* cr = cairo_create(target);
+
+                double y_pos = 0;
+                for (size_t i = 0; i < surfaces.size(); ++i)
+                {
+                    cairo_set_source_surface(cr, surfaces[i], 2, y_pos + 2);
+                    cairo_rectangle(cr, 0, y_pos, nWidth, heights[i]);
+                    cairo_fill(cr);
+                    y_pos += heights[i];
+                }
+
+                cairo_destroy(cr);
+
+                double fXScale, fYScale;
+                dl_cairo_surface_get_device_scale(target, &fXScale, &fYScale);
+                cairo_surface_set_device_offset(target,
+                                                - m_nPressStartX * fXScale,
+                                                0);
+
+                gtk_drag_set_icon_surface(context, target);
+                cairo_surface_destroy(target);
+            }
+
+            for (auto surface : surfaces)
+                cairo_surface_destroy(surface);
+        }
+    }
+#endif
+
     virtual void do_signal_drag_end() override
     {
         g_DragSource = nullptr;

Reply via email to