Find the answer to your Linux question:
Results 1 to 2 of 2
Hi, I'm needing to write a very simple application and I'd like to do it in pygtk as a simple script, but I don't know how to get the Gnu/Gimp ...
  1. #1
    Just Joined!
    Join Date
    May 2009
    Location
    Oregon
    Posts
    51

    Python GTK digitization question.

    Hi,
    I'm needing to write a very simple application and I'd like to do it in pygtk as a simple script, but I don't know how to get the Gnu/Gimp toolkit to do something that happens in Gimp.
    When doing a screen capture, Gimp enables a mode that allows the program to capture a Click or drag that is outside the graphical window to locate where the screen capture is going to happen.

    I'd like to do the same thing, but I don't need screen capture capability -- just the ability to collect all clicks x,y positions (in pixels, or whatever units are convenient) from the mouse wherever they are, especially outside the graphics window I have for the python app -- and this needs to continue until I click on a release button to cancel the mode.

    How can this be done from python? / where is documentation on this particular part of pyGtk ?

  2. #2
    Just Joined!
    Join Date
    May 2009
    Location
    Oregon
    Posts
    51

    Solved, but not well.

    Well, I suppose the system update buried my question.
    It took me two days to figure out -- yuck.

    I took apart the source code for Gimp, only to find out they didn't use the GTK toolkit to do the screen capture. Highly disappointing....

    I finally did find a poorly documented function called gtk.gdk.pointer_grab() that had made it possible to do.
    It has one huge drawback, though, and that is a lack of any fine control over what does and does not get signals. Apparently one widget siezes control, and none of the other buttons, etc. get signals -- and nor does the rest of X11 except the root server. So, it tricky to work with. And although in theory, one ought to be able implement the signals by directly calling the objects and it "should" propagate to the parent (or siblings?) I couldn't get that to work.

    Nor could I figure out a way to detect when the mouse entered the application area again to turn Off the capture using any simple signal or event; and even though mouse events can be routed to a callback function; there is an ugly in X11 with the mouse hints that causes all mouse data to stop flowing when the cursor leaves the window -- which generally leads to deadlock.

    So, my solution, finally -- was to write it in two parts; I use a timer callback every half second to the mouse callback, and I force a read of the mouse position. That allows me to detect when the pointer leaves the application window -- and starts surfing the desktop;

    If anyone knows a better way to do this -- I'd love to know, just to satisfy my curiosity. BTW, I'm not using global variables, but am passing a list of object references -- because it is easier than trying to figure which callback (switched, object, connect) works for which widget -- they seem to be quite inconsistent. In any event (chuckle) at least I didn't leave another TOTALLY unanswered question for people to find with Google....



    Code:
    import gtk
    import gtk.gdk  # the X11 interface is handled in gdk
    import gobject  # needed for timer
    
    ....
    blah blah
    ....
    
    
    def hold( widgetsHold ):
            """
            Callback from a toggle button to "hold" the pointers (screen grab).
            widgetsHold[0] is the list of all objects in the application
            widgetsHold[1] is the toggle buttion itself.
            To do a grab requires a gdk (not GTK window) element.
            The last three elements of the widget list is used to remember
            the state of the "hold" button and mouse pointer
            """
    
    	active=widgetsHold[1].get_active()
    	widgetsHold[0][-1]= ( active and True )
    	widgetsHold[0][0].get_pointer()
    	if widgetsHold[0][-2]: gdk.gtk.pointer_ungrab() 
    	widgetsHold[0][-2]=False
    	return True
    
    def holdOn( widgets, event ):
           """
           Track the mouse to determine when it leaves and enters the
           application window.  None of the Enter, Focus, or other signals
           appear able to handle this when a grab is in effect.
           A timer calls this function periodically as well as the mouse
           but it only processes when the "hold" button is active wigets[-1]
           """
    
    	if not widgets[-1]: return True
     
    	if event and event.is_hint: x=event.x; y=event.y
    	else: x,y,state = widgets[0].window.get_pointer()
    
    	xx,yy=widgets[0].get_size()
    	now=True
    	if (x>0 and y>0 and x<xx and y<yy): now=False
    
    	if widgets[-2] == now: return True # already using correct setting
    
            # Toggle it whatever it is...
    	if now:
    		gtk.gdk.pointer_grab(widgets[0].get_window(),
    				owner_events=False,
    				event_mask=gtk.gdk.BUTTON_PRESS_MASK |
    					   gtk.gdk.POINTER_MOTION_MASK |
    					   gtk.gdk.POINTER_MOTION_HINT_MASK |
    					   0,
    				confine_to=None,
    				cursor=gtk.gdk.Cursor( gtk.gdk.DOTBOX )
    		)
    	else:
    		gtk.gdk.pointer_ungrab();
    		widgets[-2]=False
    	widgets[-2]=now
    	return True
    
    ...
    Blah Blah
    ....
    
    main()
    #...blah...
    #oh ... one mistake I made for time wasting, is I used a list rather than a named dictionary .... which was fast, but caused headaches remembering which number was which .... next time, I'd use a dictionary...
    
      widgets=[ window,[], False,
    		    [0,False,False,False, False, False ],
    		    [ [.5430e-9,[0,0]],[.5446e-9,[0,0]],[200,[0,0]],[1000,[0,0]],[False,[0,0]],[False,[0,0]],
    		       [0,(0,0)], 0, 0 ] ]  
    ...
      # The button to start the grab fishing trip with...
    
        widget=gtk.ToggleButton("Hold")
        grab=widget
        widget.connect_object( "toggled", hold, [widgets, grab] )
    
        # connect_object is needed to pass the widgets list; but
        # with toggle buttons it doesn't pass the "event" parameter
        # probably needs some other kind of callback -- but who knows
        # this definitely works, though.
    
        hbox.pack_start( widget, False, False, 0 )
        widget.show()
        widgets[3][4]=widget
    
    ...
    widgets.extend( [ False,(False,False), False, False ] );# Track & warp
    window.connect_object("motion_notify_event", holdOn, widgets )
    ...
    
    # blah...
    # and finally, the timer...
    
     gobject.timeout_add( 500, holdOn, widgets, False );
    
        window.show()
        gtk.main()

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
...