199 lines
6.3 KiB
Python
199 lines
6.3 KiB
Python
|
# Xlib.ext.screensaver -- X ScreenSaver extension module
|
||
|
#
|
||
|
# Copyright (C) 2022 Vladimir Panteleev <git@cy.md>
|
||
|
#
|
||
|
# 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.,
|
||
|
# 51 Franklin Street,
|
||
|
# Fifth Floor,
|
||
|
# Boston, MA 02110-1301 USA
|
||
|
|
||
|
"""This extension allows registering the client as an X screensaver,
|
||
|
or query information about the current screensaver.
|
||
|
|
||
|
For detailed description see any of the following documents.
|
||
|
Protocol specification:
|
||
|
https://www.x.org/releases/X11R7.7/doc/scrnsaverproto/saver.html
|
||
|
XCB Protocol specification:
|
||
|
https://cgit.freedesktop.org/xcb/proto/tree/src/screensaver.xml
|
||
|
|
||
|
"""
|
||
|
|
||
|
from Xlib import X
|
||
|
from Xlib.protocol import rq, structs
|
||
|
|
||
|
extname = 'MIT-SCREEN-SAVER'
|
||
|
|
||
|
# Event members
|
||
|
NotifyMask = 1
|
||
|
CycleMask = 2
|
||
|
|
||
|
# Notify state
|
||
|
StateOff = 0
|
||
|
StateOn = 1
|
||
|
StateCycle = 2
|
||
|
|
||
|
# Notify kind
|
||
|
KindBlanked = 0
|
||
|
KindInternal = 1
|
||
|
KindExternal = 2
|
||
|
|
||
|
class QueryVersion(rq.ReplyRequest):
|
||
|
_request = rq.Struct(
|
||
|
rq.Card8('opcode'),
|
||
|
rq.Opcode(0),
|
||
|
rq.RequestLength(),
|
||
|
rq.Card8('major_version'),
|
||
|
rq.Card8('minor_version'),
|
||
|
rq.Pad(2),
|
||
|
)
|
||
|
|
||
|
_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),
|
||
|
major_version=1,
|
||
|
minor_version=0)
|
||
|
|
||
|
|
||
|
class QueryInfo(rq.ReplyRequest):
|
||
|
_request = rq.Struct(
|
||
|
rq.Card8('opcode'),
|
||
|
rq.Opcode(1),
|
||
|
rq.RequestLength(),
|
||
|
rq.Drawable('drawable'),
|
||
|
)
|
||
|
|
||
|
_reply = rq.Struct(
|
||
|
rq.ReplyCode(),
|
||
|
rq.Card8('state'),
|
||
|
rq.Card16('sequence_number'),
|
||
|
rq.ReplyLength(),
|
||
|
rq.Window('saver_window'),
|
||
|
rq.Card32('til_or_since'),
|
||
|
rq.Card32('idle'),
|
||
|
rq.Card32('event_mask'), # rq.Set('event_mask', 4, (NotifyMask, CycleMask)),
|
||
|
rq.Card8('kind'),
|
||
|
rq.Pad(7),
|
||
|
)
|
||
|
|
||
|
def query_info(self):
|
||
|
return QueryInfo(display=self.display,
|
||
|
opcode=self.display.get_extension_major(extname),
|
||
|
drawable=self,
|
||
|
)
|
||
|
|
||
|
|
||
|
class SelectInput(rq.Request):
|
||
|
_request = rq.Struct(
|
||
|
rq.Card8('opcode'),
|
||
|
rq.Opcode(2),
|
||
|
rq.RequestLength(),
|
||
|
rq.Drawable('drawable'),
|
||
|
rq.Card32('event_mask'), # rq.Set('event_mask', 4, (NotifyMask, CycleMask)),
|
||
|
)
|
||
|
|
||
|
def select_input(self, mask):
|
||
|
return SelectInput(display=self.display,
|
||
|
opcode=self.display.get_extension_major(extname),
|
||
|
drawable=self,
|
||
|
event_mask=mask,
|
||
|
)
|
||
|
|
||
|
|
||
|
class SetAttributes(rq.Request):
|
||
|
_request = rq.Struct(
|
||
|
rq.Card8('opcode'),
|
||
|
rq.Opcode(3),
|
||
|
rq.RequestLength(),
|
||
|
rq.Drawable('drawable'),
|
||
|
rq.Int16('x'),
|
||
|
rq.Int16('y'),
|
||
|
rq.Card16('width'),
|
||
|
rq.Card16('height'),
|
||
|
rq.Card16('border_width'),
|
||
|
rq.Set('window_class', 1, (X.CopyFromParent, X.InputOutput, X.InputOnly)),
|
||
|
rq.Card8('depth'),
|
||
|
rq.Card32('visual'),
|
||
|
structs.WindowValues('attrs'),
|
||
|
)
|
||
|
|
||
|
def set_attributes(self, x, y, width, height, border_width,
|
||
|
window_class = X.CopyFromParent,
|
||
|
depth = X.CopyFromParent,
|
||
|
visual = X.CopyFromParent,
|
||
|
onerror = None,
|
||
|
**keys):
|
||
|
return SetAttributes(display=self.display,
|
||
|
onerror = onerror,
|
||
|
opcode=self.display.get_extension_major(extname),
|
||
|
drawable=self,
|
||
|
x = x,
|
||
|
y = y,
|
||
|
width = width,
|
||
|
height = height,
|
||
|
border_width = border_width,
|
||
|
window_class = window_class,
|
||
|
depth = depth,
|
||
|
visual = visual,
|
||
|
attrs = keys)
|
||
|
|
||
|
|
||
|
class UnsetAttributes(rq.Request):
|
||
|
_request = rq.Struct(
|
||
|
rq.Card8('opcode'),
|
||
|
rq.Opcode(4),
|
||
|
rq.RequestLength(),
|
||
|
rq.Drawable('drawable'),
|
||
|
)
|
||
|
|
||
|
def unset_attributes(self, onerror = None):
|
||
|
return UnsetAttributes(display=self.display,
|
||
|
onerror = onerror,
|
||
|
opcode=self.display.get_extension_major(extname),
|
||
|
drawable=self)
|
||
|
|
||
|
|
||
|
class Notify(rq.Event):
|
||
|
_code = None
|
||
|
_fields = rq.Struct(
|
||
|
rq.Card8('type'),
|
||
|
rq.Set('state', 1, (StateOff, StateOn, StateCycle)),
|
||
|
rq.Card16('sequence_number'),
|
||
|
rq.Card32('timestamp'),
|
||
|
rq.Window('root'),
|
||
|
rq.Window('window'),
|
||
|
rq.Set('kind', 1, (KindBlanked, KindInternal, KindExternal)),
|
||
|
rq.Bool('forced'),
|
||
|
rq.Pad(14),
|
||
|
)
|
||
|
|
||
|
def init(disp, info):
|
||
|
disp.extension_add_method('display', 'screensaver_query_version', query_version)
|
||
|
disp.extension_add_method('drawable', 'screensaver_query_info', query_info)
|
||
|
disp.extension_add_method('drawable', 'screensaver_select_input', select_input)
|
||
|
disp.extension_add_method('drawable', 'screensaver_set_attributes', set_attributes)
|
||
|
disp.extension_add_method('drawable', 'screensaver_unset_attributes', unset_attributes)
|
||
|
|
||
|
disp.extension_add_event(info.first_event + 0, Notify)
|