-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathqemu-resize.py
executable file
·109 lines (79 loc) · 2.3 KB
/
qemu-resize.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#!/usr/bin/env python3
"""
My QEMU SDL window resizes itself to the correct size for its guest display, then forgets about that size for some reason when it loses focus. This script restores the window so its content size is as specified.
See sway-ipc(7) for protocol and message ids/formats.
"""
import json
import os
import socket
import struct
import sys
MAGIC = b"i3-ipc"
HEADER = struct.Struct("=6xII")
RUN_COMMAND = 0
GET_TREE = 4
TARGET_APP_ID = "qemu-system-x86_64"
TARGET_WIDTH = 1440
TARGET_HEIGHT = 900
def format_message(type_id, payload):
buf = bytearray(HEADER.size + len(payload))
HEADER.pack_into(buf, 0, len(payload), type_id)
buf[:len(MAGIC)] = MAGIC
buf[HEADER.size:] = payload
return buf
def recv_sized(sock, byte_length):
buf = bytearray(byte_length)
view = memoryview(buf)
while view:
r = sock.recv_into(view)
view = view[r:]
if r == 0:
raise EOFError
return buf
def read_message(sock):
header_buf = recv_sized(sock, HEADER.size)
if not header_buf.startswith(MAGIC):
raise Exception("expected i3-ipc magic string")
payload_len, type_id = HEADER.unpack(header_buf)
payload_buf = recv_sized(sock, payload_len)
return (type_id, payload_buf)
def walk(root):
stack = [root]
while stack:
node = stack.pop()
yield node
stack.extend(node["nodes"])
stack.extend(node["floating_nodes"])
def main():
with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as sock:
sock.connect(os.environb[b"SWAYSOCK"])
sock.sendall(format_message(GET_TREE, b""))
_, tree_json = read_message(sock)
tree = json.loads(tree_json)
target_node = next((node for node in walk(tree) if node.get("app_id") == TARGET_APP_ID), None)
if target_node is None:
print(f"No node with target app_id {TARGET_APP_ID!r} found.", file=sys.stderr)
raise SystemExit(1)
dw = (
target_node["rect"]["width"]
- target_node["window_rect"]["width"]
)
dh = (
target_node["rect"]["height"]
+ target_node["deco_rect"]["height"]
- target_node["window_rect"]["height"]
)
sock.sendall(
format_message(
RUN_COMMAND,
b"[app_id=%s] resize set width %d px height %d px" % (
TARGET_APP_ID.encode(),
TARGET_WIDTH + dw,
TARGET_HEIGHT + dh,
),
)
)
_, response_json = read_message(sock)
print(json.loads(response_json))
if __name__ == "__main__":
main()