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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aioxlib
3
- Version: 0.0.4
3
+ Version: 0.0.5
4
4
  Summary: Human friendly interface to XLib subsystems using asyncio python
5
5
  Author-email: Jose Tiago Macara Coutinho <coutinhotiago@gmail.com>
6
6
  License-Expression: GPL-3.0-or-later
@@ -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.4"
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
- EXTENSIONS = {"MIT-SHM": SharedMemory}
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:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aioxlib
3
- Version: 0.0.4
3
+ Version: 0.0.5
4
4
  Summary: Human friendly interface to XLib subsystems using asyncio python
5
5
  Author-email: Jose Tiago Macara Coutinho <coutinhotiago@gmail.com>
6
6
  License-Expression: GPL-3.0-or-later
@@ -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