@@ -616,6 +616,7 @@ def draw(
616616 drop_insert_index : int = - 1 ,
617617 hovered_id : str = "" ,
618618 drop_target_id : str = "" ,
619+ cursor_main : float = - 1.0 ,
619620 ) -> None :
620621 """Main draw entry point -- called on every 'draw' signal.
621622
@@ -651,6 +652,7 @@ def draw(
651652 drop_insert_index = drop_insert_index ,
652653 hovered_id = hovered_id ,
653654 drop_target_id = drop_target_id ,
655+ cursor_main = cursor_main ,
654656 )
655657 cr .set_operator (cairo .OPERATOR_SOURCE )
656658 cr .set_source_surface (offscreen , 0 , 0 )
@@ -667,6 +669,7 @@ def _draw_content(
667669 drop_insert_index : int ,
668670 hovered_id : str ,
669671 drop_target_id : str = "" ,
672+ cursor_main : float = - 1.0 ,
670673 ) -> None :
671674 """Render all dock content to a Cairo context."""
672675 pos = config .pos
@@ -899,24 +902,36 @@ def _draw_content(
899902 )
900903
901904 # --- Draw indicators ---
905+ # While dragging, the dragged item's icon is rendered by GTK as a drag
906+ # image that follows the cursor, while its layout slot keeps advancing
907+ # as the model reorders. Drawing the dot at the slot drifts visibly
908+ # ahead of the cursor until the next reorder snap. Pin the dragged
909+ # item's indicator to the cursor instead so it tracks the drag ghost.
902910 for i , (item , li ) in enumerate (zip (items , layout , strict = True )):
903- if item .is_running :
904- slide = self .slide_offsets .get (item .desktop_id , 0.0 )
905- drop_shift = (
906- gap if drop_insert_index >= 0 and i >= drop_insert_index else 0
907- )
908- self ._draw_indicator (
909- cr = cr ,
910- item = item ,
911- li = li ,
912- show_window_count_numbers = config .show_window_count_numbers ,
913- base_size = icon_size ,
914- main_pos = icon_offset + slide + drop_shift ,
915- cross_size = cross_size ,
916- hide_cross = hide_cross ,
917- theme = theme ,
918- pos = pos ,
919- )
911+ if not item .is_running :
912+ continue
913+ slide = self .slide_offsets .get (item .desktop_id , 0.0 )
914+ drop_shift = gap if drop_insert_index >= 0 and i >= drop_insert_index else 0
915+ if i == drag_index and cursor_main >= 0 :
916+ # Center the indicator under the cursor by passing a main_pos
917+ # such that _draw_indicator's "li.x + main_pos + scaled/2"
918+ # resolves to cursor_main.
919+ scaled_size = icon_size * li .scale
920+ main_pos_indicator = cursor_main - li .x - scaled_size / 2
921+ else :
922+ main_pos_indicator = icon_offset + slide + drop_shift
923+ self ._draw_indicator (
924+ cr = cr ,
925+ item = item ,
926+ li = li ,
927+ show_window_count_numbers = config .show_window_count_numbers ,
928+ base_size = icon_size ,
929+ main_pos = main_pos_indicator ,
930+ cross_size = cross_size ,
931+ hide_cross = hide_cross ,
932+ theme = theme ,
933+ pos = pos ,
934+ )
920935
921936 # --- Draw per-app overlays ---
922937 for i , (item , li ) in enumerate (zip (items , layout , strict = True )):
0 commit comments