Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

XDND drag: Pointer grab broken when source gets unmapped #6

Open
sstuhr opened this issue Aug 30, 2015 · 1 comment
Open

XDND drag: Pointer grab broken when source gets unmapped #6

sstuhr opened this issue Aug 30, 2015 · 1 comment

Comments

@sstuhr
Copy link

sstuhr commented Aug 30, 2015

In X11, when dragging from a TkDND source, if the source widget is unmapped during the drag operation, then the pointer grab, and thus the whole drag operation, is broken (though one can still drop within the application itself).

In desktop environments like Xfce, that supports multiple desktops, one can switch between desktops during a drag operation by having a pager in a panel and hovering over a different desktop in said pager. When the desktop is switched, the source (and its toplevel) is unmapped, and the drag operation is broken.

The solution could be to do the pointer grab (and just the pointer grab) on an offscreen toplevel window with wm overrideredirect 1 and wm geometry 1x1+-256+-256.

It would probably also make sense to make said toplevel a child of the source widget, and stop the drag operation on said toplevel's <Destroy>. This would fix a different issue, one encountered when one closes the toplevel containing the source widget during a drag operation, by using a window manager dependent keyboard shortcut (like Alt+F4) - the drag tries to keep going, but the source widget has been destroyed.

The following code implements switching of ttk::notebook tabs during a drag operation (by hovering over a tab), and encounters this issue.

package require tkdnd
catch {console show}

pack [ttk::notebook .notebook] \
  -expand 1 -fill both -padx 12 -pady 12

tkdnd::drop_target register .notebook *

proc handle_notebook_position {widget mouse_x mouse_y} {
  set x [expr {$mouse_x - [winfo rootx $widget]}]
  set y [expr {$mouse_y - [winfo rooty $widget]}]
  set tabid [$widget identify tab $x $y]

  if {$tabid != "" && $tabid != [$widget index current]} {
    $widget select $tabid
  }
  return refuse_drop
}

bind .notebook <<DropPosition>> {handle_notebook_position %W %X %Y}

.notebook add [ttk::button .drag_source -text "Drag Source"] \
  -sticky new -padding 12 -text "Source"

tkdnd::drag_source register .drag_source DND_Text

bind .drag_source <<DragInitCmd>> \
  {list copy DND_Text {Text to be dragged}}

.notebook add [ttk::button .drop_target -text "Drop Target"] \
  -sticky new -padding 12 -text "Target"

tkdnd::drop_target register .drop_target DND_Text

bind .drop_target <<DropEnter>> {%W state  active}
bind .drop_target <<DropLeave>> {%W state !active}
bind .drop_target <<Drop>> {
  puts "Data of type %T dropped: \"%D\""
  %W state !active
  return %A
}
@petasis
Copy link
Owner

petasis commented Aug 30, 2015

Hm, I have never thought about this at all. And I am not sure the XDND protocol specifies what is happening in such a case.

We need to further study what other implementations do to handle this. Thanks for pointing it out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants