@@ -146,7 +146,7 @@ void CustomizableToolBar::startDrag(QWidget *widget, const QPoint &globalPos)
146146 // Snapshot BEFORE making transparent
147147 const QPixmap snap = widget->grab ();
148148
149- // Make drag widget invisible but keep it in layout — no reflow
149+ // Make drag widget invisible but keep it in layout, avoiding reflow
150150 auto *effect = new QGraphicsOpacityEffect (widget);
151151 effect->setOpacity (0.0 );
152152 widget->setGraphicsEffect (effect);
@@ -177,45 +177,62 @@ void CustomizableToolBar::updateDrag(const QPoint &globalPos)
177177 const QPoint toolbarTopLeft = mapToGlobal (QPoint (0 , 0 ));
178178 const int boundaryGX = getBoundaryGlobalX ();
179179
180- const int clampedX = qBound (toolbarTopLeft.x (), globalPos.x () - m_dragOffsetX, boundaryGX - fw - 1 );
180+ const int clampedX = qBound (toolbarTopLeft.x (), globalPos.x () - m_dragOffsetX, boundaryGX - fw + 20 );
181181 const int clampedY = toolbarTopLeft.y () + (height () - fh) / 2 ;
182182 m_floatLabel->move (clampedX, clampedY);
183183
184- // Find which neighbour the float centre is over
185- const int floatCentreX = mapFromGlobal (QPoint (clampedX + fw / 2 , 0 )).x ();
184+ const int dragFloatLeft = mapFromGlobal (QPoint (clampedX, 0 )).x ();
185+ const int dragFloatCentre = mapFromGlobal (QPoint (clampedX + fw / 2 , 0 )).x ();
186+ const bool movingLeft = (dragFloatCentre < m_lastFloatCentreX);
187+ m_lastFloatCentreX = dragFloatCentre;
188+
186189 const int bi = findBoundaryIndex ();
187190 const QList<QAction *> acts = actions ();
188191
189192 QAction *newInsertBefore = (bi >= 0 ) ? acts[bi] : nullptr ;
193+ bool foundFirst = false ;
190194 for (int i = 0 ; i < bi; ++i)
191195 {
192196 QAction *a = acts[i];
193197 if (a == m_dragAction)
194198 continue ;
195199 QWidget *w = widgetForAction (a);
196- if (!w)
200+ if (!w && !a-> isSeparator () )
197201 continue ;
198- if (floatCentreX < w->x () + w->width () / 2 )
202+
203+ int threshold = 0 ;
204+ if (a->isSeparator ())
205+ {
206+ threshold = w ? w->x () + w->width () : 0 ;
207+ }
208+ else
209+ {
210+ threshold = !foundFirst ? w->x () + w->width () : w->x () + w->width () / 2 ;
211+ foundFirst = true ;
212+ }
213+
214+ // Use float left edge for separators when moving left, centre otherwise
215+ const int compareX = (a->isSeparator () && movingLeft) ? dragFloatLeft : dragFloatCentre;
216+ if (compareX < threshold)
199217 {
200218 newInsertBefore = a;
201219 break ;
202220 }
203221 }
204222
205- // Only swap when target slot changes — one atomic reorder per crossing
223+ // Only swap when target slot changes, one atomic reorder per crossing
206224 if (newInsertBefore == m_gapTarget)
207225 return ;
208226
209227 m_gapTarget = newInsertBefore;
210228
211- // Briefly hide the drag widget during reorder to avoid flash
229+ // Briefly remove opacity effect during reorder, reapply to new widget
212230 if (m_dragWidget)
213231 m_dragWidget->setGraphicsEffect (nullptr );
214232
215233 removeAction (m_dragAction);
216234 insertAction (m_gapTarget, m_dragAction);
217235
218- // Restore opacity effect on new widget
219236 QWidget *newWidget = widgetForAction (m_dragAction);
220237 if (newWidget)
221238 {
@@ -240,11 +257,11 @@ void CustomizableToolBar::endDrag(const QPoint &globalPos)
240257 delete m_floatLabel;
241258 m_floatLabel = nullptr ;
242259
243- // Remove opacity effect — restore widget appearance
260+ // Remove opacity effect, restore widget appearance
244261 if (m_dragWidget)
245262 m_dragWidget->setGraphicsEffect (nullptr );
246263
247- // Reorder already committed live in updateDrag — just save state
264+ // Reorder already committed live in updateDrag, just save state
248265 emit actionOrderChanged ();
249266
250267 m_gapTarget = nullptr ;
0 commit comments