[pygtk] drag-related async on linux (examples)

Greg Hazel gah at thalassocracy.org
Fri Sep 23 18:56:12 WST 2005


gtk 2.6.10
debian (tested and does not occur on Windows)

I'm running in to what looks like a pygtk (maybe gtk?) bug having to do with
DnD operations:

If you begin a file drag from a source like Nautilus, then "scrub" the
cursor across a pygtk window expecting a drop, eventually an async will
occur. The more targets you can move in and out of, the faster you get the
error. A drop does not need to occur for the bug to be presented.

Attached is a little demo script that makes the situation obvious, but it
can also be viewed in the dnd demo from pygtk-demo. In the demo, "scrub" as
described. The async is then brought forth on drop by overflowing a stack on
a secondary thread (which does no gtk operations!). If the async does not
occur, you will get a message saying so.

Example output from the attached demo:

Drag a file from a source (like Nautilus) and move it on then off the
window.
Generate about 20 'drag_leave' messages, then drop the file on the window.
  File "dragtargets.py", line 21, in drag_leave()
..18 more..
  File "dragtargets.py", line 21, in drag_leave()
  File "dragtargets.py", line 40, in drag_data_received()
Xlib: unexpected async reply (sequence 0x9cc)!

Example output from pygtk-demo:

motion, source  unknown
leave
Xlib: sequence lost (0x1c2f3 > 0xc2f4) in reply type 0x0!
Xlib: sequence lost (0x1c36d > 0xc36e) in reply type 0x0!
motion, source  unknown
leave
-------------- next part --------------
#!/usr/local/env python

import os
import sys
import urllib
import threading
import pygtk
pygtk.require('2.0')
import gtk

import traceback

def print_tb():
    tb = traceback.extract_stack()
    file, linenum, func, line = tb[1]
    root, file = os.path.split(file)
    linenum = str(linenum)
    print "  File \"" + file + "\", line " + linenum + ", in " + func + "()"

def drag_leave(*args):
    print_tb()    

def rec_deinc(x):
    if x > 0:
        rec_deinc(x - 1)

def try_to_overflow(x):
    try:
        rec_deinc(x)
    except:
        import traceback
        traceback.print_exc(file = open("overflow.txt", "w"))
        print "stack overflow (this is expected, do more dragging)"
        return
    
    print "could not overflow the stack (increase 'overflow_size')"

def drag_data_received(widget, drag_context, x, y, selection,
                       target_type, time):
    print_tb()
    overflow_size = 80000
    #try_to_overflow(overflow_size)
    t = threading.Thread(target=try_to_overflow, args=(overflow_size,))
    t.start()
    

gtk.threads_init()

print "Drag a file from a source (like Nautilus) and move it on then off the window."
print "Generate about 20 'drag_leave' messages, then drop the file on the window."

w = gtk.Window()
w.set_size_request(200, 150)
w.drag_dest_set(gtk.DEST_DEFAULT_ALL,
                [('text/uri-list', 0, 1), ],
                gtk.gdk.ACTION_MOVE)

w.connect('drag_leave', drag_leave)
w.connect('drag_data_received', drag_data_received)
w.connect('destroy', lambda w: gtk.main_quit())
w.show_all()

gtk.threads_enter()
gtk.main()
gtk.threads_leave()



More information about the pygtk mailing list