Skip to content

Commit

Permalink
#1526 get dpi from comtypes
Browse files Browse the repository at this point in the history
and refactor comtypes query into a utility context manager
  • Loading branch information
totaam committed Aug 20, 2022
1 parent 411f637 commit c4c8fa2
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 21 deletions.
7 changes: 6 additions & 1 deletion xpra/platform/gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@ def get_ydpi():
return -1


def get_monitors_info(display, xscale=1, yscale=1):
from xpra.gtk_common import gtk_util
return gtk_util.get_monitors_info(display, xscale, yscale)


def get_icon_size():
xdpi = get_xdpi()
ydpi = get_ydpi()
Expand Down Expand Up @@ -324,7 +329,7 @@ def fnames(l):
"get_session_type",
"get_vrefresh", "get_workarea", "get_workareas",
"get_number_of_desktops", "get_desktop_names",
"get_antialias_info", "get_icc_info", "get_display_icc_info", "get_xdpi", "get_ydpi",
"get_antialias_info", "get_icc_info", "get_display_icc_info", "get_xdpi", "get_ydpi", "get_monitors_info",
"get_icon_size",
"get_window_min_size", "get_window_max_size",
"get_mouse_config",
Expand Down
17 changes: 17 additions & 0 deletions xpra/platform/win32/comtypes_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ def __enter__(self):
logger.setLevel(logging.WARNING)
self.verbose = None
from comtypes import client #@UnresolvedImport
client.gen_dir = None
from comtypes import CoInitialize #@UnresolvedImport
CoInitialize()
gen = getattr(client, "_generate", None)
if gen:
self.verbose = getattr(gen, "__verbose__", None)
Expand All @@ -41,3 +44,17 @@ def __exit__(self, *_args):
gen.__verbose__ = self.verbose
for i, logger in enumerate(self.loggers):
logger.setLevel(self.saved_levels[i])


class CIMV2_Query(QuietenLogging):

def __init__(self, query):
self.query = query
super().__init__()

def __enter__(self):
super().__enter__()
from comtypes.client import CreateObject #@UnresolvedImport
o = CreateObject("WbemScripting.SWbemLocator")
s = o.ConnectServer(".", "root\\cimv2")
return s.ExecQuery(self.query)
43 changes: 42 additions & 1 deletion xpra/platform/win32/gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
GetIntSystemParametersInfo,
GetUserObjectInformationA, OpenInputDesktop, CloseDesktop,
GetMonitorInfo,
user32,
)
from xpra.common import KeyEvent
from xpra.util import AdHocStruct, csv, envint, envbool, typedict
Expand All @@ -53,6 +52,7 @@
REINIT_VISIBLE_WINDOWS = envbool("XPRA_WIN32_REINIT_VISIBLE_WINDOWS", True)
SCREENSAVER_LISTENER_POLL_DELAY = envint("XPRA_SCREENSAVER_LISTENER_POLL_DELAY", 10)
APP_ID = os.environ.get("XPRA_WIN32_APP_ID", "Xpra")
MONITOR_DPI = envbool("XPRA_WIN32_MONITOR_DPI", True)


PyCapsule_GetPointer = pythonapi.PyCapsule_GetPointer
Expand Down Expand Up @@ -902,6 +902,47 @@ def show_desktop(b):
log.warn("failed to call show_desktop(%s): %s", b, e)



def get_monitors_info(display, xscale=1, yscale=1):
from xpra.gtk_common import gtk_util
monitors_info = gtk_util.get_monitors_info(display, xscale, yscale)
if MONITOR_DPI:
#try to get more precise data by querying the DPI using comtypes:
from xpra.platform.win32.comtypes_util import CIMV2_Query
with CIMV2_Query("SELECT * FROM Win32_DesktopMonitor") as res:
index = 0
for monitor in res:
dminfo = dict((k, monitor.Properties_[k].Value) for k in (
"DeviceID", "MonitorManufacturer", "MonitorType",
"ScreenWidth", "ScreenHeight",
"PixelsPerXLogicalInch", "PixelsPerYLogicalInch",
))
log(f"Win32_DesktopMonitor {index}: {dminfo}")
manufacturer = dminfo["MonitorManufacturer"]
model = dminfo["MonitorType"]
#find this monitor entry in the gtk info:
mmatch = None
for monitor_info in monitors_info.values():
if monitor_info.get("manufacturer")==manufacturer and monitor_info.get("model")==model:
mmatch = monitor_info
break
if mmatch:
dpix = dminfo["PixelsPerXLogicalInch"]
dpiy = dminfo["PixelsPerYLogicalInch"]
#get the screen size from gtk because Win32_DesktopMonitor can be None!
width = dminfo["ScreenWidth"] or mmatch["geometry"][2]
height = dminfo["ScreenHeight"] or mmatch["geometry"][3]
if dpix>0 and dpiy>0 and width>0 and height>0:
mmatch.update({
"dpi-x" : dpix,
"dpi-y" : dpiy,
"width-mm" : round(width*25.4/dpix),
"height-mm" : round(height*25.4/dpiy),
})
index += 1
return monitors_info


WM_WTSSESSION_CHANGE = 0x02b1
WTS_CONSOLE_CONNECT = 0x1
WTS_CONSOLE_DISCONNECT = 0x2
Expand Down
31 changes: 12 additions & 19 deletions xpra/platform/win32/netdev_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,10 @@


def get_interface_info(_fd, iface):
from xpra.platform.win32.comtypes_util import QuietenLogging
with QuietenLogging():
try:
import comtypes.client
comtypes.client.gen_dir = None
from comtypes import CoInitialize #@UnresolvedImport
CoInitialize()
from comtypes.client import CreateObject #@UnresolvedImport
o = CreateObject("WbemScripting.SWbemLocator")
s = o.ConnectServer(".", "root\\cimv2")
query = "SELECT * FROM Win32_NetworkAdapter WHERE GUID='%s'" % iface
res = s.ExecQuery(query)
from xpra.platform.win32.comtypes_util import CIMV2_Query
query = "SELECT * FROM Win32_NetworkAdapter WHERE GUID='%s'" % iface
try:
with CIMV2_Query(query) as res:
log("ExecQuery(%s) returned %i rows", query, res.Count)
if res.Count==1:
for r in res:
Expand All @@ -44,13 +36,14 @@ def get_interface_info(_fd, iface):
props[ik] = v
log("get_interface_info(%s)=%s" % (iface, props))
return props
except Exception as e:
log("get_interface_info(%s)", iface, exc_info=True)
from xpra.util import first_time
if first_time("win32-network-query"):
log.info("cannot query network interface:")
log.info(" %s", e)
return {}
except Exception as e:
log("get_interface_info(%s)", iface, exc_info=True)
from xpra.util import first_time
if first_time("win32-network-query"):
log.info("cannot query network interface:")
log.info(" %s", e)
return {}


def get_tcp_info(sock): #pylint: disable=unused-argument
"""
Expand Down

0 comments on commit c4c8fa2

Please sign in to comment.