#!/usr/bin/env python3 """Rotate display using GNOME Mutter DisplayConfig API (Wayland)""" import sys from gi.repository import Gio, GLib def rotate_display(): bus = Gio.bus_get_sync(Gio.BusType.SESSION, None) proxy = Gio.DBusProxy.new_sync( bus, Gio.DBusProxyFlags.NONE, None, 'org.gnome.Mutter.DisplayConfig', '/org/gnome/Mutter/DisplayConfig', 'org.gnome.Mutter.DisplayConfig', None ) # Get current state result = proxy.GetCurrentState() serial = result[0] monitors = result[1] logical_monitors = result[2] properties = result[3] print(f"Found {len(logical_monitors)} logical monitor(s)") # Find HDMI-1 and rotate it new_logical_monitors = [] found_hdmi = False for lm in logical_monitors: x, y, scale, transform, primary, monitors_list, props = lm print(f"Logical monitor: x={x}, y={y}, scale={scale}, transform={transform}, primary={primary}") # Check if this logical monitor contains HDMI-1 hdmi_in_this_lm = False for monitor_info in monitors_list: # monitor_info is a tuple: (connector, vendor, product, serial, ...) connector = monitor_info[0] if isinstance(monitor_info, tuple) else monitor_info print(f" Monitor: {connector}") if connector == "HDMI-1": hdmi_in_this_lm = True found_hdmi = True break if hdmi_in_this_lm: # Rotate left (90° CCW) = transform 1 # 0=normal, 1=90° left, 2=180°, 3=270° right new_transform = 1 # 90° left (portrait) # Ensure monitors_list is a list of tuples (not just a list) monitors_tuple_list = tuple(monitors_list) if isinstance(monitors_list, list) else monitors_list new_lm = (x, y, scale, new_transform, primary, monitors_tuple_list, props) new_logical_monitors.append(new_lm) print(f"✓ Rotating HDMI-1 to portrait (90° left, transform={new_transform})") else: # Keep other monitors unchanged new_logical_monitors.append(lm) if not found_hdmi: print("Error: HDMI-1 not found in any logical monitor") return False if not new_logical_monitors: print("Error: No logical monitors to configure") return False # Apply the new configuration # Method: 1 = logical, 2 = physical # The actual structure is: (i, i, d, u, b, a(ssss), a{sv}) # i=int32 (x), i=int32 (y), d=double (scale), u=uint32 (transform), # b=boolean (primary), a(ssss)=array of 4-strings (monitor info), a{sv}=props try: # Use the exact structure we see from GetCurrentState result = proxy.ApplyMonitorsConfig('(uua(iiiduba(ssss)a{sv})a{sv})', serial, 1, new_logical_monitors, properties) print("✓ Display rotation applied successfully!") print("✓ Check your screen - HDMI-1 should now be in portrait mode (90° left)!") return True except Exception as e: print(f"Error: {e}") import traceback traceback.print_exc() return False if __name__ == '__main__': rotate_display()