Spaces:
Runtime error
Runtime error
# Xlib.xobject.drawable -- drawable objects (window and pixmap) | |
# | |
# Copyright (C) 2000 Peter Liljenberg <petli@ctrl-c.liu.se> | |
# | |
# This library is free software; you can redistribute it and/or | |
# modify it under the terms of the GNU Lesser General Public License | |
# as published by the Free Software Foundation; either version 2.1 | |
# 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 Lesser General Public License for more details. | |
# | |
# You should have received a copy of the GNU Lesser 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 | |
from Xlib import X, Xatom | |
from Xlib.protocol import request, rq | |
# Other X resource objects | |
from . import resource | |
from . import colormap | |
from . import cursor | |
from . import fontable | |
# Inter-client communication conventions | |
from . import icccm | |
class Drawable(resource.Resource): | |
__drawable__ = resource.Resource.__resource__ | |
def get_geometry(self): | |
return request.GetGeometry(display = self.display, | |
drawable = self) | |
def create_pixmap(self, width, height, depth): | |
pid = self.display.allocate_resource_id() | |
request.CreatePixmap(display = self.display, | |
depth = depth, | |
pid = pid, | |
drawable = self.id, | |
width = width, | |
height = height) | |
cls = self.display.get_resource_class('pixmap', Pixmap) | |
return cls(self.display, pid, owner = 1) | |
def create_gc(self, **keys): | |
cid = self.display.allocate_resource_id() | |
request.CreateGC(display = self.display, | |
cid = cid, | |
drawable = self.id, | |
attrs = keys) | |
cls = self.display.get_resource_class('gc', fontable.GC) | |
return cls(self.display, cid, owner = 1) | |
def copy_area(self, gc, src_drawable, src_x, src_y, width, height, dst_x, dst_y, onerror = None): | |
request.CopyArea(display = self.display, | |
onerror = onerror, | |
src_drawable = src_drawable, | |
dst_drawable = self.id, | |
gc = gc, | |
src_x = src_x, | |
src_y = src_y, | |
dst_x = dst_x, | |
dst_y = dst_y, | |
width = width, | |
height = height) | |
def copy_plane(self, gc, src_drawable, src_x, src_y, width, height, | |
dst_x, dst_y, bit_plane, onerror = None): | |
request.CopyPlane(display = self.display, | |
onerror = onerror, | |
src_drawable = src_drawable, | |
dst_drawable = self.id, | |
gc = gc, | |
src_x = src_x, | |
src_y = src_y, | |
dst_x = dst_x, | |
dst_y = dst_y, | |
width = width, | |
height = height, | |
bit_plane = bit_plane) | |
def poly_point(self, gc, coord_mode, points, onerror = None): | |
request.PolyPoint(display = self.display, | |
onerror = onerror, | |
coord_mode = coord_mode, | |
drawable = self.id, | |
gc = gc, | |
points = points) | |
def point(self, gc, x, y, onerror = None): | |
request.PolyPoint(display = self.display, | |
onerror = onerror, | |
coord_mode = X.CoordModeOrigin, | |
drawable = self.id, | |
gc = gc, | |
points = [(x, y)]) | |
def poly_line(self, gc, coord_mode, points, onerror = None): | |
request.PolyLine(display = self.display, | |
onerror = onerror, | |
coord_mode = coord_mode, | |
drawable = self.id, | |
gc = gc, | |
points = points) | |
def line(self, gc, x1, y1, x2, y2, onerror = None): | |
request.PolySegment(display = self.display, | |
onerror = onerror, | |
drawable = self.id, | |
gc = gc, | |
segments = [(x1, y1, x2, y2)]) | |
def poly_segment(self, gc, segments, onerror = None): | |
request.PolySegment(display = self.display, | |
onerror = onerror, | |
drawable = self.id, | |
gc = gc, | |
segments = segments) | |
def poly_rectangle(self, gc, rectangles, onerror = None): | |
request.PolyRectangle(display = self.display, | |
onerror = onerror, | |
drawable = self.id, | |
gc = gc, | |
rectangles = rectangles) | |
def rectangle(self, gc, x, y, width, height, onerror = None): | |
request.PolyRectangle(display = self.display, | |
onerror = onerror, | |
drawable = self.id, | |
gc = gc, | |
rectangles = [(x, y, width, height)]) | |
def poly_arc(self, gc, arcs, onerror = None): | |
request.PolyArc(display = self.display, | |
onerror = onerror, | |
drawable = self.id, | |
gc = gc, | |
arcs = arcs) | |
def arc(self, gc, x, y, width, height, angle1, angle2, onerror = None): | |
request.PolyArc(display = self.display, | |
onerror = onerror, | |
drawable = self.id, | |
gc = gc, | |
arcs = [(x, y, width, height, angle1, angle2)]) | |
def fill_poly(self, gc, shape, coord_mode, points, onerror = None): | |
request.FillPoly(display = self.display, | |
onerror = onerror, | |
shape = shape, | |
coord_mode = coord_mode, | |
drawable = self.id, | |
gc = gc, | |
points = points) | |
def poly_fill_rectangle(self, gc, rectangles, onerror = None): | |
request.PolyFillRectangle(display = self.display, | |
onerror = onerror, | |
drawable = self.id, | |
gc = gc, | |
rectangles = rectangles) | |
def fill_rectangle(self, gc, x, y, width, height, onerror = None): | |
request.PolyFillRectangle(display = self.display, | |
onerror = onerror, | |
drawable = self.id, | |
gc = gc, | |
rectangles = [(x, y, width, height)]) | |
def poly_fill_arc(self, gc, arcs, onerror = None): | |
request.PolyFillArc(display = self.display, | |
onerror = onerror, | |
drawable = self.id, | |
gc = gc, | |
arcs = arcs) | |
def fill_arc(self, gc, x, y, width, height, angle1, angle2, onerror = None): | |
request.PolyFillArc(display = self.display, | |
onerror = onerror, | |
drawable = self.id, | |
gc = gc, | |
arcs = [(x, y, width, height, angle1, angle2)]) | |
def put_image(self, gc, x, y, width, height, format, | |
depth, left_pad, data, onerror = None): | |
request.PutImage(display = self.display, | |
onerror = onerror, | |
format = format, | |
drawable = self.id, | |
gc = gc, | |
width = width, | |
height = height, | |
dst_x = x, | |
dst_y = y, | |
left_pad = left_pad, | |
depth = depth, | |
data = data) | |
# Trivial little method for putting PIL images. Will break on anything | |
# but depth 1 or 24... | |
def put_pil_image(self, gc, x, y, image, onerror = None): | |
width, height = image.size | |
if image.mode == '1': | |
format = X.XYBitmap | |
depth = 1 | |
if self.display.info.bitmap_format_bit_order == 0: | |
rawmode = '1;R' | |
else: | |
rawmode = '1' | |
pad = self.display.info.bitmap_format_scanline_pad | |
stride = roundup(width, pad) >> 3 | |
elif image.mode == 'RGB': | |
format = X.ZPixmap | |
depth = 24 | |
if self.display.info.image_byte_order == 0: | |
rawmode = 'BGRX' | |
else: | |
rawmode = 'RGBX' | |
pad = self.display.info.bitmap_format_scanline_pad | |
unit = self.display.info.bitmap_format_scanline_unit | |
stride = roundup(width * unit, pad) >> 3 | |
else: | |
raise ValueError('Unknown data format') | |
maxlen = (self.display.info.max_request_length << 2) \ | |
- request.PutImage._request.static_size | |
split = maxlen // stride | |
x1 = 0 | |
x2 = width | |
y1 = 0 | |
while y1 < height: | |
h = min(height, split) | |
if h < height: | |
subimage = image.crop((x1, y1, x2, y1 + h)) | |
else: | |
subimage = image | |
w, h = subimage.size | |
data = subimage.tobytes("raw", rawmode, stride, 0) | |
self.put_image(gc, x, y, w, h, format, depth, 0, data) | |
y1 = y1 + h | |
y = y + h | |
def get_image(self, x, y, width, height, format, plane_mask): | |
return request.GetImage(display = self.display, | |
format = format, | |
drawable = self.id, | |
x = x, | |
y = y, | |
width = width, | |
height = height, | |
plane_mask = plane_mask) | |
def draw_text(self, gc, x, y, text, onerror = None): | |
request.PolyText8(display = self.display, | |
onerror = onerror, | |
drawable = self.id, | |
gc = gc, | |
x = x, | |
y = y, | |
items = [text]) | |
def poly_text(self, gc, x, y, items, onerror = None): | |
request.PolyText8(display = self.display, | |
onerror = onerror, | |
drawable = self.id, | |
gc = gc, | |
x = x, | |
y = y, | |
items = items) | |
def poly_text_16(self, gc, x, y, items, onerror = None): | |
request.PolyText16(display = self.display, | |
onerror = onerror, | |
drawable = self.id, | |
gc = gc, | |
x = x, | |
y = y, | |
items = items) | |
def image_text(self, gc, x, y, string, onerror = None): | |
request.ImageText8(display = self.display, | |
onerror = onerror, | |
drawable = self.id, | |
gc = gc, | |
x = x, | |
y = y, | |
string = string) | |
def image_text_16(self, gc, x, y, string, onerror = None): | |
request.ImageText16(display = self.display, | |
onerror = onerror, | |
drawable = self.id, | |
gc = gc, | |
x = x, | |
y = y, | |
string = string) | |
def query_best_size(self, item_class, width, height): | |
return request.QueryBestSize(display = self.display, | |
item_class = item_class, | |
drawable = self.id, | |
width = width, | |
height = height) | |
class Window(Drawable): | |
__window__ = resource.Resource.__resource__ | |
_STRING_ENCODING = 'ISO-8859-1' | |
_UTF8_STRING_ENCODING = 'UTF-8' | |
def create_window(self, x, y, width, height, border_width, depth, | |
window_class = X.CopyFromParent, | |
visual = X.CopyFromParent, | |
onerror = None, | |
**keys): | |
wid = self.display.allocate_resource_id() | |
request.CreateWindow(display = self.display, | |
onerror = onerror, | |
depth = depth, | |
wid = wid, | |
parent = self.id, | |
x = x, | |
y = y, | |
width = width, | |
height = height, | |
border_width = border_width, | |
window_class = window_class, | |
visual = visual, | |
attrs = keys) | |
cls = self.display.get_resource_class('window', Window) | |
return cls(self.display, wid, owner = 1) | |
def change_attributes(self, onerror = None, **keys): | |
request.ChangeWindowAttributes(display = self.display, | |
onerror = onerror, | |
window = self.id, | |
attrs = keys) | |
def get_attributes(self): | |
return request.GetWindowAttributes(display = self.display, | |
window = self.id) | |
def destroy(self, onerror = None): | |
request.DestroyWindow(display = self.display, | |
onerror = onerror, | |
window = self.id) | |
self.display.free_resource_id(self.id) | |
def destroy_sub_windows(self, onerror = None): | |
request.DestroySubWindows(display = self.display, | |
onerror = onerror, | |
window = self.id) | |
def change_save_set(self, mode, onerror = None): | |
request.ChangeSaveSet(display = self.display, | |
onerror = onerror, | |
mode = mode, | |
window = self.id) | |
def reparent(self, parent, x, y, onerror = None): | |
request.ReparentWindow(display = self.display, | |
onerror = onerror, | |
window = self.id, | |
parent = parent, | |
x = x, | |
y = y) | |
def map(self, onerror = None): | |
request.MapWindow(display = self.display, | |
onerror = onerror, | |
window = self.id) | |
def map_sub_windows(self, onerror = None): | |
request.MapSubwindows(display = self.display, | |
onerror = onerror, | |
window = self.id) | |
def unmap(self, onerror = None): | |
request.UnmapWindow(display = self.display, | |
onerror = onerror, | |
window = self.id) | |
def unmap_sub_windows(self, onerror = None): | |
request.UnmapSubwindows(display = self.display, | |
onerror = onerror, | |
window = self.id) | |
def configure(self, onerror = None, **keys): | |
request.ConfigureWindow(display = self.display, | |
onerror = onerror, | |
window = self.id, | |
attrs = keys) | |
def circulate(self, direction, onerror = None): | |
request.CirculateWindow(display = self.display, | |
onerror = onerror, | |
direction = direction, | |
window = self.id) | |
def raise_window(self, onerror = None): | |
"""alias for raising the window to the top - as in XRaiseWindow""" | |
self.configure(onerror, stack_mode = X.Above) | |
def query_tree(self): | |
return request.QueryTree(display = self.display, | |
window = self.id) | |
def change_property(self, property, property_type, format, data, | |
mode = X.PropModeReplace, onerror = None): | |
request.ChangeProperty(display = self.display, | |
onerror = onerror, | |
mode = mode, | |
window = self.id, | |
property = property, | |
type = property_type, | |
data = (format, data)) | |
def change_text_property(self, property, property_type, data, | |
mode = X.PropModeReplace, onerror = None): | |
if not isinstance(data, bytes): | |
if property_type == Xatom.STRING: | |
data = data.encode(self._STRING_ENCODING) | |
elif property_type == self.display.get_atom('UTF8_STRING'): | |
data = data.encode(self._UTF8_STRING_ENCODING) | |
self.change_property(property, property_type, 8, data, | |
mode=mode, onerror=onerror) | |
def delete_property(self, property, onerror = None): | |
request.DeleteProperty(display = self.display, | |
onerror = onerror, | |
window = self.id, | |
property = property) | |
def get_property(self, property, property_type, offset, length, delete = False): | |
r = request.GetProperty(display = self.display, | |
delete = delete, | |
window = self.id, | |
property = property, | |
type = property_type, | |
long_offset = offset, | |
long_length = length) | |
if r.property_type: | |
fmt, value = r.value | |
r.format = fmt | |
r.value = value | |
return r | |
else: | |
return None | |
def get_full_property(self, property, property_type, sizehint = 10): | |
prop = self.get_property(property, property_type, 0, sizehint) | |
if prop: | |
val = prop.value | |
if prop.bytes_after: | |
prop = self.get_property(property, property_type, sizehint, | |
prop.bytes_after // 4 + 1) | |
val = val + prop.value | |
prop.value = val | |
return prop | |
else: | |
return None | |
def get_full_text_property(self, property, property_type=X.AnyPropertyType, sizehint = 10): | |
prop = self.get_full_property(property, property_type, | |
sizehint=sizehint) | |
if prop is None or prop.format != 8: | |
return None | |
if prop.property_type == Xatom.STRING: | |
prop.value = prop.value.decode(self._STRING_ENCODING) | |
elif prop.property_type == self.display.get_atom('UTF8_STRING'): | |
prop.value = prop.value.decode(self._UTF8_STRING_ENCODING) | |
# FIXME: at least basic support for compound text would be nice. | |
# elif prop.property_type == self.display.get_atom('COMPOUND_TEXT'): | |
return prop.value | |
def list_properties(self): | |
r = request.ListProperties(display = self.display, | |
window = self.id) | |
return r.atoms | |
def set_selection_owner(self, selection, time, onerror = None): | |
request.SetSelectionOwner(display = self.display, | |
onerror = onerror, | |
window = self.id, | |
selection = selection, | |
time = time) | |
def convert_selection(self, selection, target, property, time, onerror = None): | |
request.ConvertSelection(display = self.display, | |
onerror = onerror, | |
requestor = self.id, | |
selection = selection, | |
target = target, | |
property = property, | |
time = time) | |
def send_event(self, event, event_mask = 0, propagate = False, onerror = None): | |
request.SendEvent(display = self.display, | |
onerror = onerror, | |
propagate = propagate, | |
destination = self.id, | |
event_mask = event_mask, | |
event = event) | |
def grab_pointer(self, owner_events, event_mask, | |
pointer_mode, keyboard_mode, | |
confine_to, cursor, time): | |
r = request.GrabPointer(display = self.display, | |
owner_events = owner_events, | |
grab_window = self.id, | |
event_mask = event_mask, | |
pointer_mode = pointer_mode, | |
keyboard_mode = keyboard_mode, | |
confine_to = confine_to, | |
cursor = cursor, | |
time = time) | |
return r.status | |
def grab_button(self, button, modifiers, owner_events, event_mask, | |
pointer_mode, keyboard_mode, | |
confine_to, cursor, onerror = None): | |
request.GrabButton(display = self.display, | |
onerror = onerror, | |
owner_events = owner_events, | |
grab_window = self.id, | |
event_mask = event_mask, | |
pointer_mode = pointer_mode, | |
keyboard_mode = keyboard_mode, | |
confine_to = confine_to, | |
cursor = cursor, | |
button = button, | |
modifiers = modifiers) | |
def ungrab_button(self, button, modifiers, onerror = None): | |
request.UngrabButton(display = self.display, | |
onerror = onerror, | |
button = button, | |
grab_window = self.id, | |
modifiers = modifiers) | |
def grab_keyboard(self, owner_events, pointer_mode, keyboard_mode, time): | |
r = request.GrabKeyboard(display = self.display, | |
owner_events = owner_events, | |
grab_window = self.id, | |
time = time, | |
pointer_mode = pointer_mode, | |
keyboard_mode = keyboard_mode) | |
return r.status | |
def grab_key(self, key, modifiers, owner_events, pointer_mode, keyboard_mode, onerror = None): | |
request.GrabKey(display = self.display, | |
onerror = onerror, | |
owner_events = owner_events, | |
grab_window = self.id, | |
modifiers = modifiers, | |
key = key, | |
pointer_mode = pointer_mode, | |
keyboard_mode = keyboard_mode) | |
def ungrab_key(self, key, modifiers, onerror = None): | |
request.UngrabKey(display = self.display, | |
onerror = onerror, | |
key = key, | |
grab_window = self.id, | |
modifiers = modifiers) | |
def query_pointer(self): | |
return request.QueryPointer(display = self.display, | |
window = self.id) | |
def get_motion_events(self, start, stop): | |
r = request.GetMotionEvents(display = self.display, | |
window = self.id, | |
start = start, | |
stop = stop) | |
return r.events | |
def translate_coords(self, src_window, src_x, src_y): | |
return request.TranslateCoords(display = self.display, | |
src_wid = src_window, | |
dst_wid = self.id, | |
src_x = src_x, | |
src_y = src_y) | |
def warp_pointer(self, x, y, src_window = 0, src_x = 0, src_y = 0, | |
src_width = 0, src_height = 0, onerror = None): | |
request.WarpPointer(display = self.display, | |
onerror = onerror, | |
src_window = src_window, | |
dst_window = self.id, | |
src_x = src_x, | |
src_y = src_y, | |
src_width = src_width, | |
src_height = src_height, | |
dst_x = x, | |
dst_y = y) | |
def set_input_focus(self, revert_to, time, onerror = None): | |
request.SetInputFocus(display = self.display, | |
onerror = onerror, | |
revert_to = revert_to, | |
focus = self.id, | |
time = time) | |
def clear_area(self, x = 0, y = 0, width = 0, height = 0, exposures = False, onerror = None): | |
request.ClearArea(display = self.display, | |
onerror = onerror, | |
exposures = exposures, | |
window = self.id, | |
x = x, | |
y = y, | |
width = width, | |
height = height) | |
def create_colormap(self, visual, alloc): | |
mid = self.display.allocate_resource_id() | |
request.CreateColormap(display = self.display, | |
alloc = alloc, | |
mid = mid, | |
window = self.id, | |
visual = visual) | |
cls = self.display.get_resource_class('colormap', colormap.Colormap) | |
return cls(self.display, mid, owner = 1) | |
def list_installed_colormaps(self): | |
r = request.ListInstalledColormaps(display = self.display, | |
window = self.id) | |
return r.cmaps | |
def rotate_properties(self, properties, delta, onerror = None): | |
request.RotateProperties(display = self.display, | |
onerror = onerror, | |
window = self.id, | |
delta = delta, | |
properties = properties) | |
def set_wm_name(self, name, onerror = None): | |
self.change_text_property(Xatom.WM_NAME, Xatom.STRING, name, | |
onerror = onerror) | |
def get_wm_name(self): | |
return self.get_full_text_property(Xatom.WM_NAME, Xatom.STRING) | |
def set_wm_icon_name(self, name, onerror = None): | |
self.change_text_property(Xatom.WM_ICON_NAME, Xatom.STRING, name, | |
onerror = onerror) | |
def get_wm_icon_name(self): | |
return self.get_full_text_property(Xatom.WM_ICON_NAME, Xatom.STRING) | |
def set_wm_class(self, inst, cls, onerror = None): | |
self.change_text_property(Xatom.WM_CLASS, Xatom.STRING, | |
'%s\0%s\0' % (inst, cls), | |
onerror = onerror) | |
def get_wm_class(self): | |
value = self.get_full_text_property(Xatom.WM_CLASS, Xatom.STRING) | |
if value is None: | |
return None | |
parts = value.split('\0') | |
if len(parts) < 2: | |
return None | |
else: | |
return parts[0], parts[1] | |
def set_wm_transient_for(self, window, onerror = None): | |
self.change_property(Xatom.WM_TRANSIENT_FOR, Xatom.WINDOW, | |
32, [window.id], | |
onerror = onerror) | |
def get_wm_transient_for(self): | |
d = self.get_property(Xatom.WM_TRANSIENT_FOR, Xatom.WINDOW, 0, 1) | |
if d is None or d.format != 32 or len(d.value) < 1: | |
return None | |
else: | |
cls = self.display.get_resource_class('window', Window) | |
return cls(self.display, d.value[0]) | |
def set_wm_protocols(self, protocols, onerror = None): | |
self.change_property(self.display.get_atom('WM_PROTOCOLS'), | |
Xatom.ATOM, 32, protocols, | |
onerror = onerror) | |
def get_wm_protocols(self): | |
d = self.get_full_property(self.display.get_atom('WM_PROTOCOLS'), Xatom.ATOM) | |
if d is None or d.format != 32: | |
return [] | |
else: | |
return d.value | |
def set_wm_colormap_windows(self, windows, onerror = None): | |
self.change_property(self.display.get_atom('WM_COLORMAP_WINDOWS'), | |
Xatom.WINDOW, 32, | |
map(lambda w: w.id, windows), | |
onerror = onerror) | |
def get_wm_colormap_windows(self): | |
d = self.get_full_property(self.display.get_atom('WM_COLORMAP_WINDOWS'), | |
Xatom.WINDOW) | |
if d is None or d.format != 32: | |
return [] | |
else: | |
cls = self.display.get_resource_class('window', Window) | |
return map(lambda i, d = self.display, c = cls: c(d, i), | |
d.value) | |
def set_wm_client_machine(self, name, onerror = None): | |
self.change_text_property(Xatom.WM_CLIENT_MACHINE, Xatom.STRING, name, | |
onerror = onerror) | |
def get_wm_client_machine(self): | |
return self.get_full_text_property(Xatom.WM_CLIENT_MACHINE, Xatom.STRING) | |
def set_wm_normal_hints(self, hints = {}, onerror = None, **keys): | |
self._set_struct_prop(Xatom.WM_NORMAL_HINTS, Xatom.WM_SIZE_HINTS, | |
icccm.WMNormalHints, hints, keys, onerror) | |
def get_wm_normal_hints(self): | |
return self._get_struct_prop(Xatom.WM_NORMAL_HINTS, Xatom.WM_SIZE_HINTS, | |
icccm.WMNormalHints) | |
def set_wm_hints(self, hints = {}, onerror = None, **keys): | |
self._set_struct_prop(Xatom.WM_HINTS, Xatom.WM_HINTS, | |
icccm.WMHints, hints, keys, onerror) | |
def get_wm_hints(self): | |
return self._get_struct_prop(Xatom.WM_HINTS, Xatom.WM_HINTS, | |
icccm.WMHints) | |
def set_wm_state(self, hints = {}, onerror = None, **keys): | |
atom = self.display.get_atom('WM_STATE') | |
self._set_struct_prop(atom, atom, icccm.WMState, hints, keys, onerror) | |
def get_wm_state(self): | |
atom = self.display.get_atom('WM_STATE') | |
return self._get_struct_prop(atom, atom, icccm.WMState) | |
def set_wm_icon_size(self, hints = {}, onerror = None, **keys): | |
self._set_struct_prop(Xatom.WM_ICON_SIZE, Xatom.WM_ICON_SIZE, | |
icccm.WMIconSize, hints, keys, onerror) | |
def get_wm_icon_size(self): | |
return self._get_struct_prop(Xatom.WM_ICON_SIZE, Xatom.WM_ICON_SIZE, | |
icccm.WMIconSize) | |
# Helper function for getting structured properties. | |
# pname and ptype are atoms, and pstruct is a Struct object. | |
# Returns a DictWrapper, or None | |
def _get_struct_prop(self, pname, ptype, pstruct): | |
r = self.get_property(pname, ptype, 0, pstruct.static_size // 4) | |
if r and r.format == 32: | |
value = rq.encode_array(r.value) | |
if len(value) == pstruct.static_size: | |
return pstruct.parse_binary(value, self.display)[0] | |
return None | |
# Helper function for setting structured properties. | |
# pname and ptype are atoms, and pstruct is a Struct object. | |
# hints is a mapping or a DictWrapper, keys is a mapping. keys | |
# will be modified. onerror is the error handler. | |
def _set_struct_prop(self, pname, ptype, pstruct, hints, keys, onerror): | |
if isinstance(hints, rq.DictWrapper): | |
keys.update(hints._data) | |
else: | |
keys.update(hints) | |
value = pstruct.to_binary(*(), **keys) | |
self.change_property(pname, ptype, 32, value, onerror = onerror) | |
class Pixmap(Drawable): | |
__pixmap__ = resource.Resource.__resource__ | |
def free(self, onerror = None): | |
request.FreePixmap(display = self.display, | |
onerror = onerror, | |
pixmap = self.id) | |
self.display.free_resource_id(self.id) | |
def create_cursor(self, mask, foreground, background, x, y): | |
fore_red, fore_green, fore_blue = foreground | |
back_red, back_green, back_blue = background | |
cid = self.display.allocate_resource_id() | |
request.CreateCursor(display = self.display, | |
cid = cid, | |
source = self.id, | |
mask = mask, | |
fore_red = fore_red, | |
fore_green = fore_green, | |
fore_blue = fore_blue, | |
back_red = back_red, | |
back_green = back_green, | |
back_blue = back_blue, | |
x = x, | |
y = y) | |
cls = self.display.get_resource_class('cursor', cursor.Cursor) | |
return cls(self.display, cid, owner = 1) | |
def roundup(value, unit): | |
return (value + (unit - 1)) & ~(unit - 1) | |