Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 110 additions & 14 deletions Xlib/ext/randr.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@

"""RandR - provide access to the RandR extension information.

This implementation is based off version 1.3 of the XRandR protocol, and may
This implementation is based off version 1.5 of the XRandR protocol, and may
not be compatible with other versions.

Version 1.2 of the protocol is documented at:
Version 1.5 of the protocol is documented at:
http://cgit.freedesktop.org/xorg/proto/randrproto/tree/randrproto.txt

Version 1.3.1 here:
Expand All @@ -34,6 +34,7 @@
"""


from tkinter import W
from Xlib import X
from Xlib.protocol import rq, structs

Expand Down Expand Up @@ -122,6 +123,12 @@
BadRRCrtc = 1
BadRRMode = 2

# Error classes #
class BadRROutputError(Exception): pass

class BadRRCrtcError(Exception): pass

class BadRRModeError(Exception): pass

# Data Structures #

Expand Down Expand Up @@ -168,6 +175,19 @@
rq.Card32('matrix33'),
)

MonitorInfo = rq.Struct(
rq.Card32('name'),
rq.Bool('primary'),
rq.Bool('automatic'),
rq.LengthOf('crtcs', 2),
rq.Int16('x'),
rq.Int16('y'),
rq.Card16('width_in_pixels'),
rq.Card16('height_in_pixels'),
rq.Card32('width_in_millimeters'),
rq.Card32('height_in_millimeters'),
rq.List('crtcs', rq.Card32Obj)
)

# Requests #

Expand Down Expand Up @@ -197,7 +217,7 @@ def query_version(self):
display=self.display,
opcode=self.display.get_extension_major(extname),
major_version=1,
minor_version=3,
minor_version=5,
)


Expand Down Expand Up @@ -1078,6 +1098,76 @@ def get_output_primary(self):
)


# Version 1.5 methods

class GetMonitors(rq.ReplyRequest):
_request = rq.Struct(
rq.Card8('opcode'),
rq.Opcode(42),
rq.RequestLength(),
rq.Window('window'),
rq.Bool('is_active'),
rq.Pad(3)
)

_reply = rq.Struct(
rq.ReplyCode(),
rq.Pad(1),
rq.Card16('sequence_number'),
rq.ReplyLength(),
rq.Card32('timestamp'),
rq.LengthOf('monitors', 4),
rq.Card32('outputs'),
rq.Pad(12),
rq.List('monitors', MonitorInfo)
)


def get_monitors(self, is_active=True):
return GetMonitors(
display=self.display,
opcode=self.display.get_extension_major(extname),
window=self,
is_active=is_active
)

class SetMonitor(rq.Request):
_request = rq.Struct(
rq.Card8('opcode'),
rq.Opcode(43),
rq.RequestLength(),
rq.Window('window'),
rq.Object('monitor_info', MonitorInfo)
)


def set_monitor(self, monitor_info):
return SetMonitor(
display=self.display,
opcode=self.display.get_extension_major(extname),
window=self,
monitor_info=monitor_info
)


class DeleteMonitor(rq.Request):
_request = rq.Struct(
rq.Card8('opcode'),
rq.Opcode(44),
rq.RequestLength(),
rq.Window('window'),
rq.Card32('name')
)


def delete_monitor(self, name):
return DeleteMonitor(
display=self.display,
opcode=self.display.get_extension_major(extname),
window=self,
name=name
)

# Events #

class ScreenChangeNotify(rq.Event):
Expand Down Expand Up @@ -1149,8 +1239,6 @@ class OutputPropertyNotify(rq.Event):
rq.Card8('state'),
rq.Pad(11),
)


# Initialization #

def init(disp, info):
Expand Down Expand Up @@ -1186,12 +1274,20 @@ def init(disp, info):
disp.extension_add_method('display', 'xrandr_get_panning', get_panning)
disp.extension_add_method('display', 'xrandr_set_panning', set_panning)

disp.extension_add_event(info.first_event + RRScreenChangeNotify, ScreenChangeNotify)
# add RRNotify events (1 event code with 3 subcodes)
disp.extension_add_subevent(info.first_event + RRNotify, RRNotify_CrtcChange, CrtcChangeNotify)
disp.extension_add_subevent(info.first_event + RRNotify, RRNotify_OutputChange, OutputChangeNotify)
disp.extension_add_subevent(info.first_event + RRNotify, RRNotify_OutputProperty, OutputPropertyNotify)

#disp.extension_add_error(BadRROutput, BadRROutputError)
#disp.extension_add_error(BadRRCrtc, BadRRCrtcError)
#disp.extension_add_error(BadRRMode, BadRRModeError)
# If the server is running RANDR 1.5+, enable 1.5 compatible methods and events
version = query_version(disp)
if version.major_version == 1 and version.minor_version >= 5:
# version 1.5 compatible
disp.extension_add_method('window', 'xrandr_get_monitors', get_monitors)
disp.extension_add_method('window', 'xrandr_set_monitor', set_monitor)
disp.extension_add_method('window', 'xrandr_delete_monitor', delete_monitor)

disp.extension_add_event(info.first_event + RRScreenChangeNotify, ScreenChangeNotify)
# add RRNotify events (1 event code with 3 subcodes)
disp.extension_add_subevent(info.first_event + RRNotify, RRNotify_CrtcChange, CrtcChangeNotify)
disp.extension_add_subevent(info.first_event + RRNotify, RRNotify_OutputChange, OutputChangeNotify)
disp.extension_add_subevent(info.first_event + RRNotify, RRNotify_OutputProperty, OutputPropertyNotify)

disp.extension_add_error(BadRROutput, BadRROutputError)
disp.extension_add_error(BadRRCrtc, BadRRCrtcError)
disp.extension_add_error(BadRRMode, BadRRModeError)