# Xlib.ext.shape -- SHAPE extension module
#
# Copyright (C) 2002 Jeffrey Boser <verin@lvcm.com>
#
# 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
# Constants to use
#
# Regions of a window
ShapeBounding = 0 # the 'edge' of a shaped window
ShapeClip = 1 # the clipping region
# Shape Operations
ShapeSet = 0 # Set the region unmodified (dest=src)
ShapeUnion = 1 # Add the new region to the old (dest=src|dest)
ShapeIntersect = 2 # Use the intersection (dest=src&dest)
ShapeSubtract = 3 # remove region (dest = dest - intersect)
ShapeInvert = 4 # opposite of subtract (dest = src - intersect)
# Events
ShapeNotifyMask = (1<<0) #a keypress mask?
ShapeNotify = 0 #still unsure of these values
# How to Use
# The basic functions that change the shapes of things are:
# shape_rectangles (uses a set of rectangles as the source)
# operation, region, ordering, rects
# shape_mask (uses a bitmap as the source)
# operation, region, x_offset, y_offset, bitmap
# shape_combine (uses a window as the source)
# operation, src_region, dest_region, x_offset, y_offset, src_window
# shape_offset (moves the region)
# region, x_offset, y_offset
# The functions to find stuff out (these three return mappings of field/values):
# shape_query_version (shape extension version)
# major_version, minor_version
# shape_query_extents (rectangle boundaries of a window's regions)
# clip_shaped, clip_x, clip_y, clip_width, clip_height,
# bounding_shaped, bounding_x, bounding_y, bounding_width, bounding_height
# shape_input_selected (if the window products shapenotify events)
# enabled
# shape_get_rectangles (the rectangles set by shape_rectangles)
# ordering, rects
# And to turn on shape notify events:
# shape_select_input
# enable
from Xlib import X
from Xlib.protocol import rq,structs
extname = 'SHAPE'
class QueryVersion(rq.ReplyRequest):
_request = rq.Struct(
rq.Card8('opcode'),
rq.Opcode(0),
rq.RequestLength(),
)
_reply = rq.Struct(
rq.ReplyCode(),
rq.Pad(1),
rq.Card16('sequence_number'),
rq.ReplyLength(),
rq.Card16('major_version'),
rq.Card16('minor_version'),
rq.Pad(20),
)
def query_version(self):
return QueryVersion(
display = self.display,
opcode = self.display.get_extension_major(extname),
)
class Rectangles(rq.Request):
_request = rq.Struct(
rq.Card8('opcode'),
rq.Opcode(1),
rq.RequestLength(),
rq.Card8('operation'),
rq.Set('region', 1, (ShapeBounding, ShapeClip)),
rq.Card8('ordering'),
rq.Pad(1),
rq.Window('window'),
rq.Int16('x'),
rq.Int16('y'),
rq.List('rectangles', structs.Rectangle),
)
def rectangles(self, region, operation, ordering, x, y, rectangles):
Rectangles(
display = self.display,
opcode = self.display.get_extension_major(extname),
operation = operation,
region = region,
ordering = ordering,
window = self.id,
x = x,
y = y,
rectangles = rectangles,
)
class Mask(rq.Request):
_request = rq.Struct(
rq.Card8('opcode'),
rq.Opcode(2),
rq.RequestLength(),
rq.Card8('operation'),
rq.Set('region', 1, (ShapeBounding, ShapeClip)),
rq.Pad(2),
rq.Window('window'),
rq.Int16('x'),
rq.Int16('y'),
rq.Pixmap('source', (X.NONE, )),
)
def mask(self, operation, region, x, y, source):
Mask(display = self.display,
opcode = self.display.get_extension_major(extname),
window = self.id,
operation = operation,
region = region,
x = x,
y = y,
source = source,
)
class Combine(rq.Request):
_request = rq.Struct(
rq.Card8('opcode'),
rq.Opcode(3),
rq.RequestLength(),
rq.Card8('operation'),
rq.Set('dest_region', 1, (ShapeBounding, ShapeClip)),
rq.Set('source_region', 1, (ShapeBounding, ShapeClip)),
rq.Pad(1),
rq.Window('dest'),
rq.Int16('x'),
rq.Int16('y'),
rq.Window('source'),
)
def combine(self, operation, region, source, source_region, x, y):
Combine(
display = self.display,
opcode = self.display.get_extension_major(extname),
operation = operation,
dest_region = region,
source_region = source_region,
dest = self.id,
x = x,
y = y,
source = source,
)
class Offset(rq.Request):
_request = rq.Struct(
rq.Card8('opcode'),
rq.Opcode(4),
rq.RequestLength(),
rq.Set('region', 1, (ShapeBounding, ShapeClip)),
rq.Pad(3),
rq.Window('window'),
rq.Int16('x'),
rq.Int16('y'),
)
def offset(self, region, x, y):
Offset(
display = self.display,
opcode = self.display.get_extension_major(extname),
region = region,
window = self.id,
x = x,
y = y,
)
class QueryExtents(rq.ReplyRequest):
_request = rq.Struct(
rq.Card8('opcode'),
rq.Opcode(5),
rq.RequestLength(),
rq.Window('window'),
)
_reply = rq.Struct(
rq.ReplyCode(),
rq.Pad(1),
rq.Card16('sequence_number'),
rq.ReplyLength(),
rq.Bool('bounding_shaped'),
rq.Bool('clip_shaped'),
rq.Pad(2),
rq.Int16('bounding_x'),
rq.Int16('bounding_y'),
rq.Card16('bounding_width'),
rq.Card16('bounding_height'),
rq.Int16('clip_x'),
rq.Int16('clip_y'),
rq.Card16('clip_width'),
rq.Card16('clip_height'),
rq.Pad(4),
)
def query_extents(self):
return QueryExtents(
display = self.display,
opcode = self.display.get_extension_major(extname),
window = self.id,
)
class SelectInput(rq.Request):
_request = rq.Struct(
rq.Card8('opcode'),
rq.Opcode(6),
rq.RequestLength(),
rq.Window('window'),
rq.Bool('enable'),
rq.Pad(3),
)
def select_input(self, enable = 1):
SelectInput(
display = self.display,
opcode = self.display.get_extension_major(extname),
window = self.id,
enable = enable,
)
class InputSelected(rq.ReplyRequest):
_request = rq.Struct(
rq.Card8('opcode'),
rq.Opcode(7),
rq.RequestLength(),
rq.Window('window'),
)
_reply = rq.Struct(
rq.ReplyCode(),
rq.Bool('enabled'),
rq.Card16('sequence_number'),
rq.ReplyLength(),
rq.Pad(24),
)
def input_selected(self):
reply = InputSelected(
display = self.display,
opcode = self.display.get_extension_major(extname),
window = self.id,
)
return reply.enabled
class GetRectangles(rq.ReplyRequest):
_request = rq.Struct(
rq.Card8('opcode'),
rq.Opcode(8),
rq.RequestLength(),
rq.Window('window'),
rq.Set('region', 1, (ShapeBounding, ShapeClip)),
rq.Pad(3),
)
_reply = rq.Struct(
rq.ReplyCode(),
rq.Card8('ordering'),
rq.Card16('sequence_number'),
rq.ReplyLength(),
rq.LengthOf('rectangles', 4),
rq.Pad(20),
rq.List('rectangles', structs.Rectangle),
)
def get_rectangles(self, region):
return GetRectangles(
display = self.display,
opcode = self.display.get_extension_major(extname),
window = self.id,
region = region,
)
class ShapeNotify(rq.Event):
_code = None
_fields = rq.Struct( rq.Card8('type'),
rq.Set('region', 1, (ShapeBounding, ShapeClip)),
rq.Card16('sequence_number'),
rq.Window('window'),
rq.Int16('x'),
rq.Int16('y'),
rq.Card16('width'),
rq.Card16('height'),
rq.Card32('time'),
rq.Bool('shaped'),
rq.Pad(11),
)
def init(disp, info):
disp.extension_add_method('display', 'shape_query_version', query_version )
disp.extension_add_method('window', 'shape_rectangles', rectangles )
disp.extension_add_method('window', 'shape_mask', mask )
disp.extension_add_method('window', 'shape_combine', combine )
disp.extension_add_method('window', 'shape_offset', offset )
disp.extension_add_method('window', 'shape_query_extents', query_extents )
disp.extension_add_method('window', 'shape_select_input', select_input )
disp.extension_add_method('window', 'shape_input_selected', input_selected )
disp.extension_add_method('window', 'shape_get_rectangles', get_rectangles )
disp.extension_add_event(info.first_event, ShapeNotify)
|