
More info / discuss on my Plurk, blog or by email.
#!/usr/bin/env python
# gravity mouse proof of concept
# from example scribblesimple.py
# GTK - The GIMP Toolkit
# Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
# Copyright (C) 2001-2004 John Finlay
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
import pygtk
pygtk.require('2.0')
import gtk
import Xlib.display
# Backing pixmap for drawing area
pixmap = None
mine = False
d = Xlib.display.Display();
r = d.screen().root
label = gtk.Label("a label")
vslider = gtk.VScale(gtk.Adjustment(0, -9, 9, 1))
vslider.set_digits(0)
vslider.set_draw_value(True)
hslider = gtk.HScale(gtk.Adjustment(0, -9, 9, 1))
hslider.set_digits(0)
hslider.set_draw_value(True)
width = 0
height = 0
# Create a new backing pixmap of the appropriate size
def configure_event(widget, event):
global pixmap
x, y, width, height = widget.get_allocation()
pixmap = gtk.gdk.Pixmap(widget.window, width, height)
pixmap.draw_rectangle(widget.get_style().white_gc,
True, 0, 0, width, height)
draw_mass(widget, 60, 60)
draw_mass(widget, 400, 160)
return True
# Redraw the screen from the backing pixmap
def expose_event(widget, event):
global width, height
x , y, width, height = event.area
widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL],
pixmap, x, y, x, y, width, height)
return False
# Draw a mass (hot area) on the screen
def draw_mass(widget, x, y):
rect = (int(x-10), int(y-10), 20, 20)
pixmap.draw_rectangle(widget.get_style().black_gc, True,
rect[0], rect[1], rect[2], rect[3])
widget.queue_draw_area(rect[0], rect[1], rect[2], rect[3])
# Draw a rectangle on the screen
def draw_brush(widget, x, y):
rect = (int(x-5), int(y-5), 10, 10)
pixmap.draw_rectangle(widget.get_style().black_gc, True,
rect[0], rect[1], rect[2], rect[3])
widget.queue_draw_area(rect[0], rect[1], rect[2], rect[3])
def button_press_event(widget, event):
if event.button == 1 and pixmap != None:
draw_brush(widget, event.x, event.y)
return True
def adjust_motion(x, y):
global d, r, mine, label, vslider, hslider, width, height
label.set_label('(' + str(x) + ', ' + str(y) + ')')
if not mine:
hslider.set_value((x-int(width/2))/int(width/16))
d.warp_pointer(hslider.get_value(), vslider.get_value())
d.sync()
mine = True
else:
mine = False
def key_release_event(widget, event):
if 65307 == event.keyval:
gtk.main_quit()
return False
def motion_notify_event(widget, event):
if event.is_hint:
x, y, state = event.window.get_pointer()
else:
x = event.x
y = event.y
state = event.state
adjust_motion(x, y)
if state & gtk.gdk.BUTTON1_MASK and pixmap != None:
draw_brush(widget, x, y)
return True
def main():
global label, vslider, hslider
window = gtk.Window(gtk.WINDOW_TOPLEVEL)
window.set_name ("Test Input")
vbox = gtk.VBox(False, 0)
window.add(vbox)
vbox.show()
window.connect("destroy", lambda w: gtk.main_quit())
# Create the drawing area
drawing_area = gtk.DrawingArea()
drawing_area.set_size_request(200, 200)
hbox = gtk.HBox(False, 0)
hbox.show()
vslider.show()
hslider.show()
hbox.pack_start(vslider, False, False, 0)
hbox.pack_start(drawing_area, True, True, 0)
vbox.pack_start(hbox, True, True, 0)
drawing_area.show()
# Signals used to handle backing pixmap
drawing_area.connect("expose_event", expose_event)
drawing_area.connect("configure_event", configure_event)
# Event signals
drawing_area.connect("motion_notify_event", motion_notify_event)
drawing_area.connect("button_press_event", button_press_event)
window.connect("key_release_event", key_release_event)
drawing_area.set_events(gtk.gdk.EXPOSURE_MASK
| gtk.gdk.LEAVE_NOTIFY_MASK
| gtk.gdk.BUTTON_PRESS_MASK
| gtk.gdk.KEY_RELEASE_MASK
| gtk.gdk.POINTER_MOTION_MASK
| gtk.gdk.POINTER_MOTION_HINT_MASK)
vbox.pack_start(hslider, False, False, 0)
label.show()
vbox.pack_start(label, False, False, 0)
# .. And a quit button
button = gtk.Button("Quit")
vbox.pack_start(button, False, False, 0)
button.connect_object("clicked", lambda w: w.destroy(), window)
button.show()
window.show()
gtk.main()
return 0
if __name__ == "__main__":
main()