/usr/share/doc/python3-xlib/examples/draw-proto.py is in python3-xlib 0.14+20091101-1ubuntu2.
This file is owned by root:root, with mode 0o755.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 | #!/usr/bin/python3
#
# examples/draw.py -- protocol test application.
#
# Copyright (C) 2000 Peter Liljenberg <petli@ctrl-c.liu.se>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
import sys
import os
# Change path so we find Xlib
sys.path.insert(1, os.path.join(sys.path[0], '..'))
from Xlib import X
from Xlib.protocol import display
from Xlib.protocol.request import *
# Application window (only one)
class Window:
def __init__(self, display):
self.d = display
self.objects = []
# Find which screen to open the window on
self.screen = self.d.info.roots[self.d.default_screen]
# Allocate ids to the window and gc
self.window = self.d.allocate_resource_id()
self.gc = self.d.allocate_resource_id()
# Create a window
CreateWindow(self.d, None,
self.screen.root_depth,
self.window,
self.screen.root,
50, 50, 300, 200, 2,
X.InputOutput,
X.CopyFromParent,
# special attribute values
background_pixel = self.screen.white_pixel,
event_mask = (X.ExposureMask |
X.StructureNotifyMask |
X.ButtonPressMask |
X.ButtonReleaseMask |
X.Button1MotionMask),
colormap = X.CopyFromParent)
# Create a gc for drawing
CreateGC(self.d, None,
self.gc,
self.window,
# special attribute values
foreground = self.screen.black_pixel,
background = self.screen.white_pixel)
# Map the window, making it visible
MapWindow(self.d, None, self.window)
# Main loop, handling events
def loop(self):
current = None
while 1:
e = self.d.next_event()
# Window has been destroyed, quit
if e.type == X.DestroyNotify:
sys.exit(0)
# Some part of the window has been exposed,
# redraw all the objects.
if e.type == X.Expose:
for o in self.objects:
o.expose(e)
# Left button pressed, start to draw
if e.type == X.ButtonPress and e.detail == 1:
current = Movement(self, e)
self.objects.append(current)
# Left button released, finish drawing
if e.type == X.ButtonRelease and e.detail == 1 and current:
current.finish(e)
current = None
# Mouse movement with button pressed, draw
if e.type == X.MotionNotify and current:
current.motion(e)
# A drawed objects, consisting of either a single
# rhomboid, or two rhomboids connected by a winding line
class Movement:
def __init__(self, win, ev):
self.win = win
self.left = ev.event_x - 5
self.right = ev.event_x + 5
self.top = ev.event_y - 5
self.bottom = ev.event_y + 5
self.time = ev.time
self.lines = [(ev.event_x, ev.event_y)]
self.first = Rhomboid(self.win, ev)
self.last = None
def motion(self, ev):
# Find all the mouse coordinates since the
# last event received
r = GetMotionEvents(self.win.d,
window = self.win.window,
start = self.time,
stop = ev.time)
# Record the previous last coordinate, and append
# the new coordinates
firstline = len(self.lines) - 1
if r.events:
# Discard the first coordinate if that is identical to
# the last recorded coordinate
pos = r.events[0]
if (pos.x, pos.y) == self.lines[-1]:
events = r.events[1:]
else:
events = r.events
# Append all coordinates
for pos in events:
x = pos.x
y = pos.y
if x < self.left:
self.left = x
if x > self.right:
self.right = x
if y < self.top:
self.top = y
if y > self.bottom:
self.bottom = y
self.lines.append((x, y))
# Append the event coordinate, if that is different from the
# last movement coordinate
if (ev.event_x, ev.event_y) != self.lines[-1]:
self.lines.append((ev.event_x, ev.event_y))
# Draw a line between the new coordinates
PolyLine(self.win.d, None,
X.CoordModeOrigin,
self.win.window,
self.win.gc,
self.lines[firstline:])
self.time = ev.time
def finish(self, ev):
self.motion(ev)
if len(self.lines) > 1:
self.last = Rhomboid(self.win, ev)
self.left = min(ev.event_x - 5, self.left)
self.right = max(ev.event_x + 5, self.right)
self.top = min(ev.event_y - 5, self.top)
self.bottom = max(ev.event_y + 5, self.bottom)
def expose(self, ev):
# We should check if this object is in the exposed
# area, but I can't be bothered right now, so just
# redraw on the last Expose in every batch
if ev.count == 0:
self.first.draw()
if self.last:
# Redraw all the lines
PolyLine(self.win.d, None,
X.CoordModeOrigin,
self.win.window,
self.win.gc,
self.lines)
self.last.draw()
# A rhomboid, drawed around the Movement endpoints
class Rhomboid:
def __init__(self, win, ev):
self.win = win
self.x = ev.event_x
self.y = ev.event_y
self.draw()
def draw(self):
# Draw the segments of the rhomboid
PolyLine(self.win.d, None,
X.CoordModePrevious,
self.win.window,
self.win.gc,
[(self.x, self.y - 5),
(5, 5),
(-5, 5),
(-5, -5),
(5, -5)])
if __name__ == '__main__':
Window(display.Display()).loop()
|