From e29796bba5031a999065b2480ddb69a324e3ce11 Mon Sep 17 00:00:00 2001 From: jpattWPC Date: Mon, 14 Mar 2022 21:24:36 -0500 Subject: [PATCH] DPI Scaling Issue Fix Fixed DPI scaling issue that was causing the window to have text cut off. A known limitation is the scaling is based off the first monitor, and does not dynamically rescale (that I'm aware of). --- build_vdiclient.bat | 2 +- dist/vdiclient.json | 2 +- requirements.bat | 3 ++- vdiclient.py | 46 ++++++++++++++++++++++++++++++++++----------- 4 files changed, 39 insertions(+), 14 deletions(-) diff --git a/build_vdiclient.bat b/build_vdiclient.bat index 253d6d4..4344ef2 100644 --- a/build_vdiclient.bat +++ b/build_vdiclient.bat @@ -1,5 +1,5 @@ @echo off -pyinstaller --noconsole --noconfirm --hidden-import proxmoxer.backends --hidden-import proxmoxer.backends.https --hidden-import proxmoxer.backends.https.AuthenticationError --hidden-import proxmoxer.core --hidden-import proxmoxer.core.ResourceException --hidden-import subprocess.TimeoutExpired --hidden-import subprocess.CalledProcessError --hidden-import requests.exceptions --hidden-import requests.exceptions.ConnectTimeout --hidden-import requests.exceptions.ConnectionError -i vdiicon.ico vdiclient.py +pyinstaller --noconsole --noconfirm --hidden-import proxmoxer.backends --hidden-import proxmoxer.backends.https --hidden-import proxmoxer.backends.https.AuthenticationError --hidden-import proxmoxer.core --hidden-import proxmoxer.core.ResourceException --hidden-import subprocess.TimeoutExpired --hidden-import subprocess.CalledProcessError --hidden-import requests.exceptions --hidden-import requests.exceptions.ReadTimeout --hidden-import requests.exceptions.ConnectTimeout --hidden-import requests.exceptions.ConnectionError -i vdiicon.ico vdiclient.py copy vdiclient.png dist\vdiclient copy vdiicon.ico dist\vdiclient del dist\vdiclient\opengl32sw.dll diff --git a/dist/vdiclient.json b/dist/vdiclient.json index 3b2bf28..457a1fc 100644 --- a/dist/vdiclient.json +++ b/dist/vdiclient.json @@ -1,6 +1,6 @@ { "upgrade_guid" : "46cbad92-353e-4b28-9bee-83950991dad8", - "version" : "1.0.1", + "version" : "1.0.2", "product_name" : "VDI Client", "manufacturer" : "Josh Patten", "name" : "VDI Client", diff --git a/requirements.bat b/requirements.bat index cd23ad0..9a17ff0 100644 --- a/requirements.bat +++ b/requirements.bat @@ -2,4 +2,5 @@ pip install pyinstaller pip install proxmoxer pip install PySimpleGUIQt -pip install requests \ No newline at end of file +pip install requests +pip install pywin32 \ No newline at end of file diff --git a/vdiclient.py b/vdiclient.py index bdf8825..85fb01c 100644 --- a/vdiclient.py +++ b/vdiclient.py @@ -11,11 +11,13 @@ from time import sleep from io import StringIO + class G: hostpool = [] spiceproxy_conv = {} proxmox = None vvcmd = None + scaling = 1 ######### title = 'VDI Login' backend = 'pve' @@ -32,6 +34,24 @@ class G: sg.theme(G.theme) +def get_dpi(): + import ctypes + import win32api # pip install pywin32 + shcore = ctypes.windll.shcore + monitors = win32api.EnumDisplayMonitors() + hresult = shcore.SetProcessDpiAwareness(2) + assert hresult == 0 + dpiX = ctypes.c_uint() + dpiY = ctypes.c_uint() + for i, monitor in enumerate(monitors): + shcore.GetDpiForMonitor( + monitor[0].handle, + 0, + ctypes.byref(dpiX), + ctypes.byref(dpiY) + ) + return dpiX.value/96 + def loadconfig(config_location = None): if config_location: config = ConfigParser(delimiters='=') @@ -132,14 +152,14 @@ def win_popup_button(message, button): def setmainlayout(): layout = [] if G.imagefile: - layout.append([sg.Image(G.imagefile), sg.Text(G.title, size =(18, 1), justification='c', font=["Helvetica", 18])]) + layout.append([sg.Image(G.imagefile), sg.Text(G.title, size =(18*G.scaling, 1*G.scaling), justification='c', font=["Helvetica", 18])]) else: - layout.append([sg.Text(G.title, size =(30, 1), justification='c', font=["Helvetica", 18])]) - layout.append([sg.Text("Username", size =(12, 1), font=["Helvetica", 12]), sg.InputText(default_text=G.user,key='-username-', font=["Helvetica", 12])]) - layout.append([sg.Text("Password", size =(12, 1),font=["Helvetica", 12]), sg.InputText(key='-password-', password_char='*', font=["Helvetica", 12])]) + layout.append([sg.Text(G.title, size =(30*G.scaling, 1*G.scaling), justification='c', font=["Helvetica", 18])]) + layout.append([sg.Text("Username", size =(12*G.scaling, 1*G.scaling), font=["Helvetica", 12]), sg.InputText(default_text=G.user,key='-username-', font=["Helvetica", 12])]) + layout.append([sg.Text("Password", size =(12*G.scaling, 1*G.scaling),font=["Helvetica", 12]), sg.InputText(key='-password-', password_char='*', font=["Helvetica", 12])]) if G.totp: - layout.append([sg.Text("OTP Key", size =(12, 1), font=["Helvetica", 12]), sg.InputText(key='-totp-', font=["Helvetica", 12])]) + layout.append([sg.Text("OTP Key", size =(12*G.scaling, 1), font=["Helvetica", 12]), sg.InputText(key='-totp-', font=["Helvetica", 12])]) if G.kiosk: layout.append([sg.Button("Log In", font=["Helvetica", 14])]) else: @@ -155,10 +175,10 @@ def getvms(): def setvmlayout(vms): layout = [] if G.imagefile: - layout.append([sg.Image(G.imagefile), sg.Text(G.title, size =(18, 1), justification='c', font=["Helvetica", 18])]) + layout.append([sg.Image(G.imagefile), sg.Text(G.title, size =(18*G.scaling, 1*G.scaling), justification='c', font=["Helvetica", 18])]) else: - layout.append([sg.Text(G.title, size =(30, 1), justification='c', font=["Helvetica", 18])]) - layout.append([sg.Text('Please select a desktop instance to connect to', size =(40, 1), justification='c', font=["Helvetica", 10])]) + layout.append([sg.Text(G.title, size =(30*G.scaling, 1*G.scaling), justification='c', font=["Helvetica", 18])]) + layout.append([sg.Text('Please select a desktop instance to connect to', size =(40*G.scaling, 1*G.scaling), justification='c', font=["Helvetica", 10])]) layoutcolumn = [] for vm in vms: if not vm["status"] == "unknown": @@ -166,7 +186,7 @@ def setvmlayout(vms): layoutcolumn.append([sg.Text(vm['name'], font=["Helvetica", 14]), sg.Button('Connect', font=["Helvetica", 14], key=connkeyname)]) layoutcolumn.append([sg.HorizontalSeparator()]) if len(vms) > 5: # We need a scrollbar - layout.append([sg.Column(layoutcolumn, scrollable = True, size = [450, None] )]) + layout.append([sg.Column(layoutcolumn, scrollable = True, size = [450*G.scaling, None] )]) else: for row in layoutcolumn: layout.append(row) @@ -175,7 +195,7 @@ def setvmlayout(vms): def iniwin(inistring): inilayout = [ - [sg.Multiline(default_text=inistring, size=(800, 600))] + [sg.Multiline(default_text=inistring, size=(800*G.scaling, 600*G.scaling))] ] iniwindow = sg.Window('INI debug', inilayout) while True: @@ -310,7 +330,7 @@ def pveauth(username, passwd, totp): err = e connected = True return connected, authenticated, err - except (requests.exceptions.ConnectTimeout, requests.exceptions.ConnectionError) as e: + except (requests.exceptions.ReadTimeout, requests.exceptions.ConnectTimeout, requests.exceptions.ConnectionError) as e: err = e connected = False return connected, authenticated, err @@ -374,6 +394,10 @@ def showvms(): return True def main(): + if os.name == 'nt': + G.scaling = get_dpi() + else: + G.scaling = 1.0 #TODO FIXME: Figure out scaling on Linux config_location = None if len(sys.argv) > 1: if sys.argv[1] == '--list_themes':