Fix fullscreen resolution for specific monitor selection

Problem: Previous fix removed /f but didn't provide proper resolution,
causing RDP to open in very low resolution window instead of fullscreen.

Solution: Calculate combined resolution of selected monitors
- 2 monitors (1,2): /size:3840x1080 /monitors:1,2
- 3 monitors (1,2,0): /size:5760x1080 /monitors:1,2,0

Changes:
- Add _get_monitors_combined_resolution() method
- Calculate total width from leftmost to rightmost selected monitor
- Use calculated resolution with /size: parameter
- Eliminate duplicate monitor selection calls
- Enhanced logging for resolution calculation

Expected result:
- '2 Monitors' opens fullscreen across 2 monitors at proper resolution
- '3 Monitors' opens fullscreen across 3 monitors at proper resolution
- Maintains /monitors: parameter for correct monitor targeting
This commit is contained in:
root
2025-09-18 11:05:10 +02:00
parent e727430a4f
commit 0ff0ef1cb1
2 changed files with 166 additions and 16 deletions

View File

@@ -245,7 +245,50 @@ class RDPClient:
return options
def _get_best_monitor_selection(self, count):
def _get_monitors_combined_resolution(self, monitor_list):
"""Get the combined resolution for selected monitors"""
try:
result = subprocess.run(['xfreerdp', '/monitor-list'],
capture_output=True, text=True, timeout=5)
if result.returncode == 0:
lines = result.stdout.strip().split('\n')
selected_monitors = [int(x.strip()) for x in monitor_list.split(',')]
min_x = float('inf')
max_x = 0
max_y = 0
for line in lines:
cleaned_line = line.strip().replace('*', '').strip()
if '[' in cleaned_line and ']' in cleaned_line:
parts = cleaned_line.split()
if len(parts) >= 3:
id_part = parts[0]
res_part = parts[1] # 1920x1080
pos_part = parts[2] # +3840+0
if '[' in id_part and ']' in id_part:
monitor_id = int(id_part.strip('[]'))
if monitor_id in selected_monitors:
# Parse resolution
width, height = map(int, res_part.split('x'))
# Parse position
pos_coords = pos_part.split('+')[1:] # ['3840', '0']
x_pos = int(pos_coords[0])
min_x = min(min_x, x_pos)
max_x = max(max_x, x_pos + width)
max_y = max(max_y, height)
if min_x != float('inf'):
total_width = max_x - min_x
total_height = max_y
return f"{total_width}x{total_height}"
except Exception as e:
self.logger.error(f"Error calculating combined resolution: {e}")
# Fallback to a reasonable default
return "3840x1080" # Assume dual 1920x1080 monitors
"""Get the best monitor selection based on layout"""
try:
result = subprocess.run(['xfreerdp', '/monitor-list'],
@@ -846,13 +889,25 @@ Multi-Monitor Support:
multimon = conn.get("multimon", "No")
use_specific_monitors = multimon in ["2 Monitors", "3 Monitors", "4 Monitors"]
# Resolution - avoid /f with specific monitor selection due to conflicts
# Get monitor list once if needed
monitor_list = None
if use_specific_monitors:
if multimon == "2 Monitors":
monitor_list = self._get_best_monitor_selection(2)
elif multimon == "3 Monitors":
monitor_list = self._get_best_monitor_selection(3)
elif multimon == "4 Monitors":
monitor_list = self._get_best_monitor_selection(4)
# Resolution - calculate proper size for specific monitor selection
resolution = conn.get("resolution", "1920x1080")
if resolution == "Full Screen" and not use_specific_monitors:
cmd.append("/f")
elif resolution == "Full Screen" and use_specific_monitors:
# Don't use /f with specific monitors - let /monitors: determine the layout
self.logger.info("Skipping /f (fullscreen) due to specific monitor selection")
# Calculate combined resolution for selected monitors
combined_res = self._get_monitors_combined_resolution(monitor_list)
cmd.append(f"/size:{combined_res}")
self.logger.info(f"Using calculated resolution {combined_res} for {multimon}: {monitor_list}")
else:
cmd.append(f"/size:{resolution}")
@@ -860,19 +915,10 @@ Multi-Monitor Support:
color_depth = conn.get("color_depth", 32)
cmd.append(f"/bpp:{color_depth}")
# Multiple monitors - use /monitors: without /multimon for specific selection
if multimon == "2 Monitors":
monitor_list = self._get_best_monitor_selection(2)
# Multiple monitors - use /monitors: for specific selection
if use_specific_monitors:
cmd.append(f"/monitors:{monitor_list}")
self.logger.info(f"Using specific monitors for 2 monitors: {monitor_list}")
elif multimon == "3 Monitors":
monitor_list = self._get_best_monitor_selection(3)
cmd.append(f"/monitors:{monitor_list}")
self.logger.info(f"Using specific monitors for 3 monitors: {monitor_list}")
elif multimon == "4 Monitors":
monitor_list = self._get_best_monitor_selection(4)
cmd.append(f"/monitors:{monitor_list}")
self.logger.info(f"Using specific monitors for 4 monitors: {monitor_list}")
self.logger.info(f"Using specific monitors for {multimon}: {monitor_list}")
elif multimon == "All Monitors":
cmd.append("/multimon")
self.logger.info("Using all available monitors")