aioxlib 0.0.4__tar.gz → 0.0.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {aioxlib-0.0.4 → aioxlib-0.0.5}/PKG-INFO +1 -1
- {aioxlib-0.0.4 → aioxlib-0.0.5}/aioxlib/__init__.py +208 -2
- {aioxlib-0.0.4 → aioxlib-0.0.5}/aioxlib.egg-info/PKG-INFO +1 -1
- {aioxlib-0.0.4 → aioxlib-0.0.5}/tests/test_aioxlib.py +291 -0
- {aioxlib-0.0.4 → aioxlib-0.0.5}/README.md +0 -0
- {aioxlib-0.0.4 → aioxlib-0.0.5}/aioxlib.egg-info/SOURCES.txt +0 -0
- {aioxlib-0.0.4 → aioxlib-0.0.5}/aioxlib.egg-info/dependency_links.txt +0 -0
- {aioxlib-0.0.4 → aioxlib-0.0.5}/aioxlib.egg-info/top_level.txt +0 -0
- {aioxlib-0.0.4 → aioxlib-0.0.5}/pyproject.toml +0 -0
- {aioxlib-0.0.4 → aioxlib-0.0.5}/setup.cfg +0 -0
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# Copyright (c) 2026 Tiago Coutinho
|
|
5
5
|
# Distributed under the GPLv3 license. See LICENSE for more info.
|
|
6
6
|
|
|
7
|
-
__version__ = "0.0.
|
|
7
|
+
__version__ = "0.0.5"
|
|
8
8
|
|
|
9
9
|
import asyncio
|
|
10
10
|
import enum
|
|
@@ -1818,7 +1818,213 @@ class SharedMemory(Extension):
|
|
|
1818
1818
|
self.display.write(payload)
|
|
1819
1819
|
|
|
1820
1820
|
|
|
1821
|
-
|
|
1821
|
+
class DoubleBufferOperation(enum.IntEnum):
|
|
1822
|
+
GetVersion = 0
|
|
1823
|
+
AllocateBackBufferName = 1
|
|
1824
|
+
DeallocateBackBufferName = 2
|
|
1825
|
+
SwapBuffers = 3
|
|
1826
|
+
BeginIdiom = 4
|
|
1827
|
+
EndIdiom = 5
|
|
1828
|
+
GetVisualInfo = 6
|
|
1829
|
+
GetBackBufferAttributes = 7
|
|
1830
|
+
|
|
1831
|
+
|
|
1832
|
+
class SwapAction(enum.IntEnum):
|
|
1833
|
+
"""What to do with the new back buffer after a swap."""
|
|
1834
|
+
|
|
1835
|
+
Undefined = 0
|
|
1836
|
+
Background = 1
|
|
1837
|
+
Untouched = 2
|
|
1838
|
+
Copied = 3
|
|
1839
|
+
|
|
1840
|
+
|
|
1841
|
+
def pack_dbe_get_version(opcode, client_major=1, client_minor=0):
|
|
1842
|
+
return struct.pack(
|
|
1843
|
+
"BBHBBH",
|
|
1844
|
+
opcode,
|
|
1845
|
+
DoubleBufferOperation.GetVersion,
|
|
1846
|
+
2,
|
|
1847
|
+
client_major,
|
|
1848
|
+
client_minor,
|
|
1849
|
+
0,
|
|
1850
|
+
)
|
|
1851
|
+
|
|
1852
|
+
|
|
1853
|
+
def unpack_dbe_get_version(data, offset=0):
|
|
1854
|
+
result, offset = unpack_reply_head(data, offset)
|
|
1855
|
+
major, minor = struct.unpack_from("=BB", data, offset)
|
|
1856
|
+
offset += 2 + 22
|
|
1857
|
+
result["major_version"] = major
|
|
1858
|
+
result["minor_version"] = minor
|
|
1859
|
+
return result, offset
|
|
1860
|
+
|
|
1861
|
+
|
|
1862
|
+
def pack_dbe_allocate_back_buffer(opcode, window, buffer, swap_action=SwapAction.Undefined):
|
|
1863
|
+
return struct.pack(
|
|
1864
|
+
"BBHIIB3x",
|
|
1865
|
+
opcode,
|
|
1866
|
+
DoubleBufferOperation.AllocateBackBufferName,
|
|
1867
|
+
4,
|
|
1868
|
+
int(window),
|
|
1869
|
+
int(buffer),
|
|
1870
|
+
int(swap_action),
|
|
1871
|
+
)
|
|
1872
|
+
|
|
1873
|
+
|
|
1874
|
+
def pack_dbe_deallocate_back_buffer(opcode, buffer):
|
|
1875
|
+
return struct.pack(
|
|
1876
|
+
"BBHI",
|
|
1877
|
+
opcode,
|
|
1878
|
+
DoubleBufferOperation.DeallocateBackBufferName,
|
|
1879
|
+
2,
|
|
1880
|
+
int(buffer),
|
|
1881
|
+
)
|
|
1882
|
+
|
|
1883
|
+
|
|
1884
|
+
def pack_dbe_swap_buffers(opcode, actions):
|
|
1885
|
+
"""actions: sequence of (window, swap_action) pairs."""
|
|
1886
|
+
n = len(actions)
|
|
1887
|
+
length = 2 + 2 * n
|
|
1888
|
+
parts = [struct.pack("=BBHI", opcode, DoubleBufferOperation.SwapBuffers, length, n)]
|
|
1889
|
+
for window, action in actions:
|
|
1890
|
+
parts.append(struct.pack("=IB3x", int(window), int(action)))
|
|
1891
|
+
return b"".join(parts)
|
|
1892
|
+
|
|
1893
|
+
|
|
1894
|
+
def pack_dbe_begin_idiom(opcode):
|
|
1895
|
+
return struct.pack("=BBH", opcode, DoubleBufferOperation.BeginIdiom, 1)
|
|
1896
|
+
|
|
1897
|
+
|
|
1898
|
+
def pack_dbe_end_idiom(opcode):
|
|
1899
|
+
return struct.pack("=BBH", opcode, DoubleBufferOperation.EndIdiom, 1)
|
|
1900
|
+
|
|
1901
|
+
|
|
1902
|
+
def pack_dbe_get_visual_info(opcode, drawables):
|
|
1903
|
+
"""drawables: sequence of drawable ids (empty = all screens)."""
|
|
1904
|
+
n = len(drawables)
|
|
1905
|
+
length = 2 + n
|
|
1906
|
+
header = struct.pack("=BBHI", opcode, DoubleBufferOperation.GetVisualInfo, length, n)
|
|
1907
|
+
body = b"".join(struct.pack("=I", int(d)) for d in drawables)
|
|
1908
|
+
return header + body
|
|
1909
|
+
|
|
1910
|
+
|
|
1911
|
+
def unpack_dbe_get_visual_info(data, offset=0):
|
|
1912
|
+
result, offset = unpack_reply_head(data, offset)
|
|
1913
|
+
(n_screens,) = struct.unpack_from("=I", data, offset)
|
|
1914
|
+
offset += 4 + 20
|
|
1915
|
+
screens = []
|
|
1916
|
+
for _ in range(n_screens):
|
|
1917
|
+
(n_infos,) = struct.unpack_from("=I", data, offset)
|
|
1918
|
+
offset += 4
|
|
1919
|
+
infos = []
|
|
1920
|
+
for _ in range(n_infos):
|
|
1921
|
+
visual, depth, perflevel = struct.unpack_from("=IBB2x", data, offset)
|
|
1922
|
+
offset += 8
|
|
1923
|
+
infos.append({"visual": visual, "depth": depth, "perflevel": perflevel})
|
|
1924
|
+
screens.append(infos)
|
|
1925
|
+
result["screens"] = screens
|
|
1926
|
+
return result, offset
|
|
1927
|
+
|
|
1928
|
+
|
|
1929
|
+
def pack_dbe_get_back_buffer_attributes(opcode, buffer):
|
|
1930
|
+
return struct.pack(
|
|
1931
|
+
"BBHI",
|
|
1932
|
+
opcode,
|
|
1933
|
+
DoubleBufferOperation.GetBackBufferAttributes,
|
|
1934
|
+
2,
|
|
1935
|
+
int(buffer),
|
|
1936
|
+
)
|
|
1937
|
+
|
|
1938
|
+
|
|
1939
|
+
def unpack_dbe_get_back_buffer_attributes(data, offset=0):
|
|
1940
|
+
result, offset = unpack_reply_head(data, offset)
|
|
1941
|
+
(window,) = struct.unpack_from("=I", data, offset)
|
|
1942
|
+
offset += 4 + 20
|
|
1943
|
+
result["window"] = window
|
|
1944
|
+
return result, offset
|
|
1945
|
+
|
|
1946
|
+
|
|
1947
|
+
class BackBuffer(Drawable):
|
|
1948
|
+
def __init__(self, bid, window, extension):
|
|
1949
|
+
super().__init__(extension.display, bid)
|
|
1950
|
+
self.window = window
|
|
1951
|
+
self.extension = extension
|
|
1952
|
+
|
|
1953
|
+
async def swap(self, swap_action=SwapAction.Undefined):
|
|
1954
|
+
return await self.extension.swap(self.window, swap_action)
|
|
1955
|
+
|
|
1956
|
+
async def __aenter__(self):
|
|
1957
|
+
return self
|
|
1958
|
+
|
|
1959
|
+
async def __aexit__(self, *_):
|
|
1960
|
+
await self.extension.deallocate_back_buffer(self.id)
|
|
1961
|
+
|
|
1962
|
+
|
|
1963
|
+
class DoubleBuffer(Extension):
|
|
1964
|
+
"""X Double Buffer Extension (DOUBLE-BUFFER / DBE).
|
|
1965
|
+
|
|
1966
|
+
Provides front/back buffers for flicker-free animation. Query with::
|
|
1967
|
+
|
|
1968
|
+
dbe = await display.query_extension("DOUBLE-BUFFER")
|
|
1969
|
+
"""
|
|
1970
|
+
|
|
1971
|
+
BaseBadBuffer = 0
|
|
1972
|
+
|
|
1973
|
+
def __init__(self, display, info):
|
|
1974
|
+
super().__init__(display, info)
|
|
1975
|
+
self.BadBuffer = info["base_error"] + self.BaseBadBuffer
|
|
1976
|
+
self.errors = {self.BadBuffer: "BadBuffer"}
|
|
1977
|
+
self.commands = {self.code: "Dbe"}
|
|
1978
|
+
|
|
1979
|
+
async def version(self, client_major=1, client_minor=0):
|
|
1980
|
+
payload = pack_dbe_get_version(self.code, client_major, client_minor)
|
|
1981
|
+
return await self.display.write_read(payload, unpack_dbe_get_version)
|
|
1982
|
+
|
|
1983
|
+
async def allocate_back_buffer(self, window, swap_action=SwapAction.Undefined, buffer=None):
|
|
1984
|
+
"""Allocate a back-buffer XID for *window*.
|
|
1985
|
+
|
|
1986
|
+
Returns the back-buffer resource id (drawable usable with core
|
|
1987
|
+
drawing requests).
|
|
1988
|
+
"""
|
|
1989
|
+
if buffer is None:
|
|
1990
|
+
buffer = self.display.resources.allocate()
|
|
1991
|
+
payload = pack_dbe_allocate_back_buffer(self.code, window, buffer, swap_action)
|
|
1992
|
+
self.display.write(payload)
|
|
1993
|
+
return BackBuffer(buffer, window, self)
|
|
1994
|
+
|
|
1995
|
+
async def deallocate_back_buffer(self, buffer):
|
|
1996
|
+
payload = pack_dbe_deallocate_back_buffer(self.code, buffer)
|
|
1997
|
+
self.display.write(payload)
|
|
1998
|
+
|
|
1999
|
+
async def swap_buffers(self, actions):
|
|
2000
|
+
"""Swap front/back buffers.
|
|
2001
|
+
|
|
2002
|
+
*actions* is a sequence of ``(window, swap_action)`` pairs.
|
|
2003
|
+
"""
|
|
2004
|
+
payload = pack_dbe_swap_buffers(self.code, actions)
|
|
2005
|
+
self.display.write(payload)
|
|
2006
|
+
|
|
2007
|
+
async def swap(self, window, swap_action=SwapAction.Undefined):
|
|
2008
|
+
"""Convenience: swap a single window."""
|
|
2009
|
+
await self.swap_buffers([(window, swap_action)])
|
|
2010
|
+
|
|
2011
|
+
async def begin_idiom(self):
|
|
2012
|
+
self.display.write(pack_dbe_begin_idiom(self.code))
|
|
2013
|
+
|
|
2014
|
+
async def end_idiom(self):
|
|
2015
|
+
self.display.write(pack_dbe_end_idiom(self.code))
|
|
2016
|
+
|
|
2017
|
+
async def get_visual_info(self, drawables=()):
|
|
2018
|
+
"""Return per-screen lists of visuals that support double buffering."""
|
|
2019
|
+
payload = pack_dbe_get_visual_info(self.code, drawables)
|
|
2020
|
+
return await self.display.write_read(payload, unpack_dbe_get_visual_info)
|
|
2021
|
+
|
|
2022
|
+
async def get_back_buffer_attributes(self, buffer):
|
|
2023
|
+
payload = pack_dbe_get_back_buffer_attributes(self.code, buffer)
|
|
2024
|
+
return await self.display.write_read(payload, unpack_dbe_get_back_buffer_attributes)
|
|
2025
|
+
|
|
2026
|
+
|
|
2027
|
+
EXTENSIONS = {"MIT-SHM": SharedMemory, "DOUBLE-BUFFER": DoubleBuffer}
|
|
1822
2028
|
|
|
1823
2029
|
|
|
1824
2030
|
class Pipeline:
|
|
@@ -34,6 +34,8 @@ from aioxlib import (
|
|
|
34
34
|
CoordinateMode,
|
|
35
35
|
CreateWindowAttributes,
|
|
36
36
|
Display,
|
|
37
|
+
DoubleBuffer,
|
|
38
|
+
DoubleBufferOperation,
|
|
37
39
|
Drawable,
|
|
38
40
|
ErrorCode,
|
|
39
41
|
Event,
|
|
@@ -48,6 +50,7 @@ from aioxlib import (
|
|
|
48
50
|
SharedMemory,
|
|
49
51
|
SharedMemoryOperation,
|
|
50
52
|
Status,
|
|
53
|
+
SwapAction,
|
|
51
54
|
VisualClass,
|
|
52
55
|
Window,
|
|
53
56
|
Xauthority,
|
|
@@ -60,6 +63,14 @@ from aioxlib import (
|
|
|
60
63
|
pack_close_font,
|
|
61
64
|
pack_create_gc,
|
|
62
65
|
pack_create_window,
|
|
66
|
+
pack_dbe_allocate_back_buffer,
|
|
67
|
+
pack_dbe_begin_idiom,
|
|
68
|
+
pack_dbe_deallocate_back_buffer,
|
|
69
|
+
pack_dbe_end_idiom,
|
|
70
|
+
pack_dbe_get_back_buffer_attributes,
|
|
71
|
+
pack_dbe_get_version,
|
|
72
|
+
pack_dbe_get_visual_info,
|
|
73
|
+
pack_dbe_swap_buffers,
|
|
63
74
|
pack_destroy_window,
|
|
64
75
|
pack_free_gc,
|
|
65
76
|
pack_get_font_path,
|
|
@@ -88,6 +99,9 @@ from aioxlib import (
|
|
|
88
99
|
read_setup,
|
|
89
100
|
round_bytes,
|
|
90
101
|
unpack_client_message,
|
|
102
|
+
unpack_dbe_get_back_buffer_attributes,
|
|
103
|
+
unpack_dbe_get_version,
|
|
104
|
+
unpack_dbe_get_visual_info,
|
|
91
105
|
unpack_depth,
|
|
92
106
|
unpack_error,
|
|
93
107
|
unpack_event,
|
|
@@ -2811,6 +2825,283 @@ class TestSharedMemory:
|
|
|
2811
2825
|
assert EXTENSIONS["MIT-SHM"] is SharedMemory
|
|
2812
2826
|
|
|
2813
2827
|
|
|
2828
|
+
# ===========================================================================
|
|
2829
|
+
# DOUBLE-BUFFER (DBE) extension
|
|
2830
|
+
# ===========================================================================
|
|
2831
|
+
|
|
2832
|
+
|
|
2833
|
+
class TestDbePack:
|
|
2834
|
+
def test_get_version(self):
|
|
2835
|
+
data = pack_dbe_get_version(140, client_major=1, client_minor=0)
|
|
2836
|
+
assert data[0] == 140
|
|
2837
|
+
assert data[1] == DoubleBufferOperation.GetVersion
|
|
2838
|
+
assert len(data) == 8
|
|
2839
|
+
|
|
2840
|
+
def test_allocate_back_buffer(self):
|
|
2841
|
+
data = pack_dbe_allocate_back_buffer(140, window=0x100, buffer=0x200, swap_action=SwapAction.Copied)
|
|
2842
|
+
assert data[0] == 140
|
|
2843
|
+
assert data[1] == DoubleBufferOperation.AllocateBackBufferName
|
|
2844
|
+
wnd, buf = struct.unpack_from("=II", data, 4)
|
|
2845
|
+
assert wnd == 0x100
|
|
2846
|
+
assert buf == 0x200
|
|
2847
|
+
assert data[12] == SwapAction.Copied
|
|
2848
|
+
assert len(data) == 16
|
|
2849
|
+
|
|
2850
|
+
def test_deallocate_back_buffer(self):
|
|
2851
|
+
data = pack_dbe_deallocate_back_buffer(140, 0x200)
|
|
2852
|
+
assert data[0] == 140
|
|
2853
|
+
assert data[1] == DoubleBufferOperation.DeallocateBackBufferName
|
|
2854
|
+
assert struct.unpack_from("=I", data, 4)[0] == 0x200
|
|
2855
|
+
|
|
2856
|
+
def test_swap_buffers(self):
|
|
2857
|
+
actions = [
|
|
2858
|
+
(0x10, SwapAction.Background),
|
|
2859
|
+
(0x20, SwapAction.Untouched),
|
|
2860
|
+
]
|
|
2861
|
+
data = pack_dbe_swap_buffers(140, actions)
|
|
2862
|
+
assert data[0] == 140
|
|
2863
|
+
assert data[1] == DoubleBufferOperation.SwapBuffers
|
|
2864
|
+
n = struct.unpack_from("=I", data, 4)[0]
|
|
2865
|
+
assert n == 2
|
|
2866
|
+
assert len(data) == 8 + 2 * 8
|
|
2867
|
+
|
|
2868
|
+
def test_begin_end_idiom(self):
|
|
2869
|
+
b = pack_dbe_begin_idiom(140)
|
|
2870
|
+
e = pack_dbe_end_idiom(140)
|
|
2871
|
+
assert b[1] == DoubleBufferOperation.BeginIdiom
|
|
2872
|
+
assert e[1] == DoubleBufferOperation.EndIdiom
|
|
2873
|
+
assert len(b) == 4 and len(e) == 4
|
|
2874
|
+
|
|
2875
|
+
def test_get_visual_info_empty(self):
|
|
2876
|
+
data = pack_dbe_get_visual_info(140, [])
|
|
2877
|
+
assert data[1] == DoubleBufferOperation.GetVisualInfo
|
|
2878
|
+
assert struct.unpack_from("=I", data, 4)[0] == 0
|
|
2879
|
+
|
|
2880
|
+
def test_get_visual_info_with_drawables(self):
|
|
2881
|
+
data = pack_dbe_get_visual_info(140, [0x100, 0x200])
|
|
2882
|
+
assert struct.unpack_from("=I", data, 4)[0] == 2
|
|
2883
|
+
assert struct.unpack_from("=II", data, 8) == (0x100, 0x200)
|
|
2884
|
+
|
|
2885
|
+
def test_get_back_buffer_attributes(self):
|
|
2886
|
+
data = pack_dbe_get_back_buffer_attributes(140, 0x30)
|
|
2887
|
+
assert data[1] == DoubleBufferOperation.GetBackBufferAttributes
|
|
2888
|
+
assert struct.unpack_from("=I", data, 4)[0] == 0x30
|
|
2889
|
+
|
|
2890
|
+
|
|
2891
|
+
class TestDbeUnpack:
|
|
2892
|
+
def test_get_version(self):
|
|
2893
|
+
head = struct.pack("=BBHI", 1, 0, 1, 0)
|
|
2894
|
+
body = struct.pack("=BB22x", 1, 0)
|
|
2895
|
+
result, offset = unpack_dbe_get_version(head + body)
|
|
2896
|
+
assert result["major_version"] == 1
|
|
2897
|
+
assert result["minor_version"] == 0
|
|
2898
|
+
assert offset == 32
|
|
2899
|
+
|
|
2900
|
+
def test_get_visual_info(self):
|
|
2901
|
+
# 1 screen, 2 visuals
|
|
2902
|
+
head = struct.pack("=BBHI", 1, 0, 1, 0)
|
|
2903
|
+
# n_screens + 20 pad, then per screen: n_infos + infos
|
|
2904
|
+
body = struct.pack("=I20x", 1)
|
|
2905
|
+
body += struct.pack("=I", 2)
|
|
2906
|
+
body += struct.pack("=IBB2x", 0x21, 24, 0)
|
|
2907
|
+
body += struct.pack("=IBB2x", 0x22, 16, 1)
|
|
2908
|
+
result, _ = unpack_dbe_get_visual_info(head + body)
|
|
2909
|
+
assert len(result["screens"]) == 1
|
|
2910
|
+
infos = result["screens"][0]
|
|
2911
|
+
assert len(infos) == 2
|
|
2912
|
+
assert infos[0] == {"visual": 0x21, "depth": 24, "perflevel": 0}
|
|
2913
|
+
assert infos[1]["visual"] == 0x22
|
|
2914
|
+
|
|
2915
|
+
def test_get_back_buffer_attributes(self):
|
|
2916
|
+
head = struct.pack("=BBHI", 1, 0, 1, 0)
|
|
2917
|
+
body = struct.pack("=I20x", 0x100)
|
|
2918
|
+
result, offset = unpack_dbe_get_back_buffer_attributes(head + body)
|
|
2919
|
+
assert result["window"] == 0x100
|
|
2920
|
+
assert offset == 32
|
|
2921
|
+
|
|
2922
|
+
|
|
2923
|
+
class TestDoubleBuffer:
|
|
2924
|
+
@pytest.fixture
|
|
2925
|
+
def display(self):
|
|
2926
|
+
conn = MagicMock()
|
|
2927
|
+
conn.write = MagicMock()
|
|
2928
|
+
d = Display(conn, {"protocol": "unix", "port": 0, "screen": 0})
|
|
2929
|
+
d.resources = ResourceManager(0x200000, 0x1FFFFF)
|
|
2930
|
+
d.info = {"max_request_length": 65535}
|
|
2931
|
+
return d
|
|
2932
|
+
|
|
2933
|
+
@pytest.fixture
|
|
2934
|
+
def dbe(self, display):
|
|
2935
|
+
info = {
|
|
2936
|
+
"present": 1,
|
|
2937
|
+
"opcode": 141,
|
|
2938
|
+
"base_event": 0,
|
|
2939
|
+
"base_error": 130,
|
|
2940
|
+
}
|
|
2941
|
+
return DoubleBuffer(display, info)
|
|
2942
|
+
|
|
2943
|
+
def test_init(self, dbe):
|
|
2944
|
+
assert dbe.code == 141
|
|
2945
|
+
assert dbe.BadBuffer == 130
|
|
2946
|
+
assert dbe.errors[130] == "BadBuffer"
|
|
2947
|
+
assert dbe.commands[141] == "Dbe"
|
|
2948
|
+
|
|
2949
|
+
def test_registered_in_extensions(self):
|
|
2950
|
+
assert EXTENSIONS["DOUBLE-BUFFER"] is DoubleBuffer
|
|
2951
|
+
assert "MIT-SHM" in EXTENSIONS
|
|
2952
|
+
|
|
2953
|
+
@pytest.mark.asyncio
|
|
2954
|
+
async def test_version(self, dbe, display):
|
|
2955
|
+
expected = {"major_version": 1, "minor_version": 0}
|
|
2956
|
+
|
|
2957
|
+
async def write_read(payload, cb):
|
|
2958
|
+
assert payload[0] == 141
|
|
2959
|
+
assert payload[1] == DoubleBufferOperation.GetVersion
|
|
2960
|
+
return expected
|
|
2961
|
+
|
|
2962
|
+
display.write_read = write_read
|
|
2963
|
+
result = await dbe.version()
|
|
2964
|
+
assert result is expected
|
|
2965
|
+
|
|
2966
|
+
@pytest.mark.asyncio
|
|
2967
|
+
async def test_allocate_back_buffer(self, dbe, display):
|
|
2968
|
+
buf = await dbe.allocate_back_buffer(0x100, SwapAction.Copied)
|
|
2969
|
+
assert buf.id == 0x200000
|
|
2970
|
+
payload = display.connection.write.call_args[0][0]
|
|
2971
|
+
assert payload[0] == 141
|
|
2972
|
+
assert payload[1] == DoubleBufferOperation.AllocateBackBufferName
|
|
2973
|
+
assert payload[12] == SwapAction.Copied
|
|
2974
|
+
|
|
2975
|
+
@pytest.mark.asyncio
|
|
2976
|
+
async def test_allocate_explicit_buffer_id(self, dbe, display):
|
|
2977
|
+
buf = await dbe.allocate_back_buffer(0x100, buffer=0x99)
|
|
2978
|
+
assert buf.id == 0x99
|
|
2979
|
+
|
|
2980
|
+
@pytest.mark.asyncio
|
|
2981
|
+
async def test_deallocate_back_buffer(self, dbe, display):
|
|
2982
|
+
await dbe.deallocate_back_buffer(0x30)
|
|
2983
|
+
payload = display.connection.write.call_args[0][0]
|
|
2984
|
+
assert payload[1] == DoubleBufferOperation.DeallocateBackBufferName
|
|
2985
|
+
|
|
2986
|
+
@pytest.mark.asyncio
|
|
2987
|
+
async def test_swap_buffers(self, dbe, display):
|
|
2988
|
+
await dbe.swap_buffers([(0x10, SwapAction.Background)])
|
|
2989
|
+
payload = display.connection.write.call_args[0][0]
|
|
2990
|
+
assert payload[1] == DoubleBufferOperation.SwapBuffers
|
|
2991
|
+
|
|
2992
|
+
@pytest.mark.asyncio
|
|
2993
|
+
async def test_swap_convenience(self, dbe, display):
|
|
2994
|
+
await dbe.swap(0x10, SwapAction.Untouched)
|
|
2995
|
+
payload = display.connection.write.call_args[0][0]
|
|
2996
|
+
assert payload[1] == DoubleBufferOperation.SwapBuffers
|
|
2997
|
+
n = struct.unpack_from("=I", payload, 4)[0]
|
|
2998
|
+
assert n == 1
|
|
2999
|
+
|
|
3000
|
+
@pytest.mark.asyncio
|
|
3001
|
+
async def test_begin_end_idiom(self, dbe, display):
|
|
3002
|
+
await dbe.begin_idiom()
|
|
3003
|
+
await dbe.end_idiom()
|
|
3004
|
+
calls = display.connection.write.call_args_list
|
|
3005
|
+
assert calls[0][0][0][1] == DoubleBufferOperation.BeginIdiom
|
|
3006
|
+
assert calls[1][0][0][1] == DoubleBufferOperation.EndIdiom
|
|
3007
|
+
|
|
3008
|
+
@pytest.mark.asyncio
|
|
3009
|
+
async def test_get_visual_info(self, dbe, display):
|
|
3010
|
+
expected = {"screens": [[{"visual": 1, "depth": 24, "perflevel": 0}]]}
|
|
3011
|
+
|
|
3012
|
+
async def write_read(payload, cb):
|
|
3013
|
+
assert payload[1] == DoubleBufferOperation.GetVisualInfo
|
|
3014
|
+
return expected
|
|
3015
|
+
|
|
3016
|
+
display.write_read = write_read
|
|
3017
|
+
result = await dbe.get_visual_info()
|
|
3018
|
+
assert result is expected
|
|
3019
|
+
|
|
3020
|
+
@pytest.mark.asyncio
|
|
3021
|
+
async def test_get_back_buffer_attributes(self, dbe, display):
|
|
3022
|
+
expected = {"window": 0x100}
|
|
3023
|
+
|
|
3024
|
+
async def write_read(payload, cb):
|
|
3025
|
+
assert payload[1] == DoubleBufferOperation.GetBackBufferAttributes
|
|
3026
|
+
return expected
|
|
3027
|
+
|
|
3028
|
+
display.write_read = write_read
|
|
3029
|
+
result = await dbe.get_back_buffer_attributes(0x30)
|
|
3030
|
+
assert result["window"] == 0x100
|
|
3031
|
+
|
|
3032
|
+
@pytest.mark.asyncio
|
|
3033
|
+
async def test_query_extension_wires_dbe(self, display):
|
|
3034
|
+
display._extensions_cache = {"DOUBLE-BUFFER": None}
|
|
3035
|
+
|
|
3036
|
+
async def write_read(payload, callback):
|
|
3037
|
+
head = struct.pack("=BBHI", 1, 0, 1, 0)
|
|
3038
|
+
body = struct.pack("=BBBB20x", 1, 141, 0, 130)
|
|
3039
|
+
reply, _ = callback(head + body, 0)
|
|
3040
|
+
return reply
|
|
3041
|
+
|
|
3042
|
+
display.write_read = write_read
|
|
3043
|
+
# Display.query_extension needs list_extensions path — use the
|
|
3044
|
+
# already-primed cache of known extension names.
|
|
3045
|
+
ext = await display.query_extension("DOUBLE-BUFFER")
|
|
3046
|
+
assert isinstance(ext, DoubleBuffer)
|
|
3047
|
+
assert ext.code == 141
|
|
3048
|
+
assert 141 in display.commands
|
|
3049
|
+
|
|
3050
|
+
|
|
3051
|
+
class TestBackBuffer:
|
|
3052
|
+
@pytest.fixture
|
|
3053
|
+
def display(self):
|
|
3054
|
+
conn = MagicMock()
|
|
3055
|
+
conn.write = MagicMock()
|
|
3056
|
+
d = Display(conn, {"protocol": "unix", "port": 0, "screen": 0})
|
|
3057
|
+
d.resources = ResourceManager(0x200000, 0x1FFFFF)
|
|
3058
|
+
d.info = {"max_request_length": 65535}
|
|
3059
|
+
return d
|
|
3060
|
+
|
|
3061
|
+
@pytest.fixture
|
|
3062
|
+
def dbe(self, display):
|
|
3063
|
+
info = {
|
|
3064
|
+
"present": 1,
|
|
3065
|
+
"opcode": 141,
|
|
3066
|
+
"base_event": 0,
|
|
3067
|
+
"base_error": 130,
|
|
3068
|
+
}
|
|
3069
|
+
return DoubleBuffer(display, info)
|
|
3070
|
+
|
|
3071
|
+
@pytest.mark.asyncio
|
|
3072
|
+
async def test_back_buffer_context(self, dbe, display):
|
|
3073
|
+
async with await dbe.allocate_back_buffer(0x100, SwapAction.Copied) as buf:
|
|
3074
|
+
assert buf.id == 0x200000
|
|
3075
|
+
payload = display.connection.write.call_args[0][0]
|
|
3076
|
+
assert payload[0] == 141
|
|
3077
|
+
assert payload[1] == DoubleBufferOperation.AllocateBackBufferName
|
|
3078
|
+
assert payload[12] == SwapAction.Copied
|
|
3079
|
+
|
|
3080
|
+
payload = display.connection.write.call_args[0][0]
|
|
3081
|
+
assert payload[1] == DoubleBufferOperation.DeallocateBackBufferName
|
|
3082
|
+
|
|
3083
|
+
@pytest.mark.asyncio
|
|
3084
|
+
async def test_swap_buffers(self, dbe, display):
|
|
3085
|
+
async with await dbe.allocate_back_buffer(0x100, SwapAction.Copied) as buf:
|
|
3086
|
+
payload = display.connection.write.call_args[0][0]
|
|
3087
|
+
assert payload[0] == 141
|
|
3088
|
+
assert payload[1] == DoubleBufferOperation.AllocateBackBufferName
|
|
3089
|
+
assert payload[12] == SwapAction.Copied
|
|
3090
|
+
await buf.swap(SwapAction.Background)
|
|
3091
|
+
payload = display.connection.write.call_args[0][0]
|
|
3092
|
+
assert payload[1] == DoubleBufferOperation.SwapBuffers
|
|
3093
|
+
payload = display.connection.write.call_args[0][0]
|
|
3094
|
+
assert payload[1] == DoubleBufferOperation.DeallocateBackBufferName
|
|
3095
|
+
|
|
3096
|
+
|
|
3097
|
+
class TestSwapActionEnum:
|
|
3098
|
+
def test_values(self):
|
|
3099
|
+
assert SwapAction.Undefined == 0
|
|
3100
|
+
assert SwapAction.Background == 1
|
|
3101
|
+
assert SwapAction.Untouched == 2
|
|
3102
|
+
assert SwapAction.Copied == 3
|
|
3103
|
+
|
|
3104
|
+
|
|
2814
3105
|
# ---------------------------------------------------------------------------
|
|
2815
3106
|
# Display — deeper coverage
|
|
2816
3107
|
# ---------------------------------------------------------------------------
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|