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 <caolanm@redhat.com>
diff --git a/vcl/unx/gtk3/gtkinst.cxx b/vcl/unx/gtk3/gtkinst.cxx
index 4fa9dce..339958f 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;
@@ -3268,6 +3270,14 @@ private:
}
#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
void signal_drag_begin(GdkDragContext* context)
@@ -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;