Commit 026cb538 authored by LRN's avatar LRN Committed by Matthias Clasen

win32: Port to new monitor api

parent 5c1d0915
......@@ -385,7 +385,7 @@ if test "$enable_win32_backend" = "yes"; then
backend_immodules="$backend_immodules,ime"
GDK_WINDOWING="$GDK_WINDOWING
#define GDK_WINDOWING_WIN32"
GDK_EXTRA_LIBS="$GDK_EXTRA_LIBS -lgdi32 -limm32 -lshell32 -lole32 -Wl,-luuid -lwinmm -ldwmapi"
GDK_EXTRA_LIBS="$GDK_EXTRA_LIBS -lgdi32 -limm32 -lshell32 -lole32 -Wl,-luuid -lwinmm -ldwmapi -lsetupapi -lcfgmgr32"
AM_CONDITIONAL(USE_WIN32, true)
PANGO_PACKAGES="pangowin32 pangocairo"
else
......@@ -756,6 +756,54 @@ case $host in
;;
esac
AS_CASE([$host_os],
[mingw*],
[
AC_CHECK_SIZEOF(
[DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY],
[],
[
#define _WIN32_WINNT 0x601
#include <windows.h>
]
)
AS_IF(
[test x$ac_cv_sizeof_DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY = x4],
[AC_MSG_RESULT([DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY is OK])],
[test x$ac_cv_sizeof_DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY = x0],
[AC_MSG_ERROR([DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY is unavailable])],
[AC_MSG_RESULT([DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY is not OK])]
)
AC_MSG_CHECKING([for SetupDiGetDevicePropertyW])
gtk_save_LIBS="$LIBS"
LIBS="-lsetupapi $LIBS"
AC_TRY_LINK(
[
#define _WIN32_WINNT 0x0600
#include <windows.h>
#include <devpropdef.h>
#include <setupapi.h>
],
[return SetupDiGetDevicePropertyW(NULL, NULL, NULL, NULL, NULL, 0, NULL, 0);],
[have_SetupDiGetDevicePropertyW=yes],
[have_SetupDiGetDevicePropertyW=no]
)
AS_IF(
[test x$have_SetupDiGetDevicePropertyW = xyes],
[
AC_DEFINE(
[HAVE_SETUP_DI_GET_DEVICE_PROPERTY_W],
[1],
[Define to 1 if SetupDiGetDevicePropertyW() is available]
)
]
)
AC_MSG_RESULT([$have_SetupDiGetDevicePropertyW])
LIBS="$gtk_save_LIBS"
],
[]
)
AC_SUBST(MATH_LIB)
#
# see bug 162979
......
......@@ -47,6 +47,8 @@ libgdk_win32_la_SOURCES = \
gdkglobals-win32.c \
gdkkeys-win32.c \
gdkmain-win32.c \
gdkmonitor-win32.c \
gdkmonitor-win32.h \
gdkprivate-win32.h \
gdkproperty-win32.c \
gdkscreen-win32.c \
......@@ -56,10 +58,11 @@ libgdk_win32_la_SOURCES = \
gdkwin32display.h \
gdkwin32displaymanager.h \
gdkwin32dnd.h \
gdkwin32glcontext.h \
gdkwin32glcontext.h \
gdkwin32.h \
gdkwin32id.c \
gdkwin32keys.h \
gdkwin32monitor.h \
gdkwin32screen.h \
gdkwin32window.h \
gdkwindow-win32.c \
......@@ -76,9 +79,10 @@ libgdkwin32include_HEADERS = \
gdkwin32display.h \
gdkwin32displaymanager.h\
gdkwin32dnd.h \
gdkwin32glcontext.h \
gdkwin32glcontext.h \
gdkwin32keys.h \
gdkwin32misc.h \
gdkwin32monitor.h \
gdkwin32screen.h \
gdkwin32window.h
......
......@@ -25,10 +25,178 @@
#include "gdkwin32display.h"
#include "gdkwin32screen.h"
#include "gdkwin32window.h"
#include "gdkmonitor-win32.h"
#include "gdkwin32.h"
static int debug_indent = 0;
static GdkMonitor *
_gdk_win32_display_find_matching_monitor (GdkWin32Display *win32_display,
GdkMonitor *needle)
{
int i;
for (i = 0; i < win32_display->monitors->len; i++)
{
GdkWin32Monitor *m;
m = GDK_WIN32_MONITOR (g_ptr_array_index (win32_display->monitors, i));
if (_gdk_win32_monitor_compare (m, GDK_WIN32_MONITOR (needle)) == 0)
return GDK_MONITOR (m);
}
return NULL;
}
gboolean
_gdk_win32_display_init_monitors (GdkWin32Display *win32_display)
{
GdkDisplay *display = GDK_DISPLAY (win32_display);
GPtrArray *new_monitors;
gint i;
gboolean changed = FALSE;
GdkWin32Monitor *primary_to_move = NULL;
for (i = 0; i < win32_display->monitors->len; i++)
GDK_WIN32_MONITOR (g_ptr_array_index (win32_display->monitors, i))->remove = TRUE;
new_monitors = _gdk_win32_display_get_monitor_list (win32_display);
for (i = 0; i < new_monitors->len; i++)
{
GdkWin32Monitor *w32_m;
GdkMonitor *m;
GdkWin32Monitor *w32_ex_monitor;
GdkMonitor *ex_monitor;
GdkRectangle geometry, ex_geometry;
GdkRectangle workarea, ex_workarea;
w32_m = GDK_WIN32_MONITOR (g_ptr_array_index (new_monitors, i));
m = GDK_MONITOR (w32_m);
ex_monitor = _gdk_win32_display_find_matching_monitor (win32_display, m);
w32_ex_monitor = GDK_WIN32_MONITOR (ex_monitor);
if (ex_monitor == NULL)
{
w32_m->add = TRUE;
changed = TRUE;
continue;
}
w32_ex_monitor->remove = FALSE;
if (i == 0)
primary_to_move = w32_ex_monitor;
gdk_monitor_get_geometry (m, &geometry);
gdk_monitor_get_geometry (ex_monitor, &ex_geometry);
gdk_monitor_get_workarea (m, &workarea);
gdk_monitor_get_workarea (ex_monitor, &ex_workarea);
if (memcmp (&workarea, &ex_workarea, sizeof (GdkRectangle)) != 0)
{
w32_ex_monitor->work_rect = workarea;
changed = TRUE;
}
if (memcmp (&geometry, &ex_geometry, sizeof (GdkRectangle)) != 0)
{
gdk_monitor_set_size (ex_monitor, geometry.width, geometry.height);
gdk_monitor_set_position (ex_monitor, geometry.x, geometry.y);
changed = TRUE;
}
if (gdk_monitor_get_width_mm (m) != gdk_monitor_get_width_mm (ex_monitor) ||
gdk_monitor_get_height_mm (m) != gdk_monitor_get_height_mm (ex_monitor))
{
gdk_monitor_set_physical_size (ex_monitor,
gdk_monitor_get_width_mm (m),
gdk_monitor_get_height_mm (m));
changed = TRUE;
}
if (g_strcmp0 (gdk_monitor_get_model (m), gdk_monitor_get_model (ex_monitor)) != 0)
{
gdk_monitor_set_model (ex_monitor,
gdk_monitor_get_model (m));
changed = TRUE;
}
if (g_strcmp0 (gdk_monitor_get_manufacturer (m), gdk_monitor_get_manufacturer (ex_monitor)) != 0)
{
gdk_monitor_set_manufacturer (ex_monitor,
gdk_monitor_get_manufacturer (m));
changed = TRUE;
}
if (gdk_monitor_get_refresh_rate (m) != gdk_monitor_get_refresh_rate (ex_monitor))
{
gdk_monitor_set_refresh_rate (ex_monitor, gdk_monitor_get_refresh_rate (m));
changed = TRUE;
}
if (gdk_monitor_get_scale_factor (m) != gdk_monitor_get_scale_factor (ex_monitor))
{
gdk_monitor_set_scale_factor (ex_monitor, gdk_monitor_get_scale_factor (m));
changed = TRUE;
}
if (gdk_monitor_get_subpixel_layout (m) != gdk_monitor_get_subpixel_layout (ex_monitor))
{
gdk_monitor_set_subpixel_layout (ex_monitor, gdk_monitor_get_subpixel_layout (m));
changed = TRUE;
}
}
for (i = win32_display->monitors->len - 1; i >= 0; i--)
{
GdkWin32Monitor *w32_ex_monitor;
GdkMonitor *ex_monitor;
w32_ex_monitor = GDK_WIN32_MONITOR (g_ptr_array_index (win32_display->monitors, i));
ex_monitor = GDK_MONITOR (w32_ex_monitor);
if (!w32_ex_monitor->remove)
continue;
changed = TRUE;
gdk_display_monitor_removed (display, ex_monitor);
g_ptr_array_remove_index (win32_display->monitors, i);
}
for (i = 0; i < new_monitors->len; i++)
{
GdkWin32Monitor *w32_m;
GdkMonitor *m;
w32_m = GDK_WIN32_MONITOR (g_ptr_array_index (new_monitors, i));
m = GDK_MONITOR (w32_m);
if (!w32_m->add)
continue;
gdk_display_monitor_added (display, m);
if (i == 0)
g_ptr_array_insert (win32_display->monitors, 0, g_object_ref (w32_m));
else
g_ptr_array_add (win32_display->monitors, g_object_ref (w32_m));
}
g_ptr_array_free (new_monitors, TRUE);
if (primary_to_move)
{
g_ptr_array_remove (win32_display->monitors, g_object_ref (primary_to_move));
g_ptr_array_insert (win32_display->monitors, 0, primary_to_move);
changed = TRUE;
}
return changed;
}
/**
* gdk_win32_display_set_cursor_theme:
* @display: (type GdkWin32Display): a #GdkDisplay
......@@ -636,12 +804,15 @@ gdk_win32_display_finalize (GObject *object)
_gdk_win32_display_finalize_cursors (display_win32);
_gdk_win32_dnd_exit ();
g_ptr_array_free (display_win32->monitors, TRUE);
G_OBJECT_CLASS (gdk_win32_display_parent_class)->finalize (object);
}
static void
gdk_win32_display_init (GdkWin32Display *display)
{
display->monitors = g_ptr_array_new_with_free_func (g_object_unref);
_gdk_win32_display_init_cursors (display);
}
......@@ -676,6 +847,39 @@ gdk_win32_display_pop_error_trap (GdkDisplay *display,
return 0;
}
static int
gdk_win32_display_get_n_monitors (GdkDisplay *display)
{
GdkWin32Display *win32_display = GDK_WIN32_DISPLAY (display);
return win32_display->monitors->len;
}
static GdkMonitor *
gdk_win32_display_get_monitor (GdkDisplay *display,
int monitor_num)
{
GdkWin32Display *win32_display = GDK_WIN32_DISPLAY (display);
if (0 <= monitor_num || monitor_num < win32_display->monitors->len)
return (GdkMonitor *) g_ptr_array_index (win32_display->monitors, monitor_num);
return NULL;
}
static GdkMonitor *
gdk_win32_display_get_primary_monitor (GdkDisplay *display)
{
GdkWin32Display *win32_display = GDK_WIN32_DISPLAY (display);
/* We arrange for the first monitor in the array to also be the primiary monitor */
if (win32_display->monitors->len > 0)
return (GdkMonitor *) g_ptr_array_index (win32_display->monitors, 0);
return NULL;
}
static void
gdk_win32_display_class_init (GdkWin32DisplayClass *klass)
{
......@@ -731,5 +935,9 @@ gdk_win32_display_class_init (GdkWin32DisplayClass *klass)
display_class->utf8_to_string_target = _gdk_win32_display_utf8_to_string_target;
display_class->make_gl_context_current = _gdk_win32_display_make_gl_context_current;
display_class->get_n_monitors = gdk_win32_display_get_n_monitors;
display_class->get_monitor = gdk_win32_display_get_monitor;
display_class->get_primary_monitor = gdk_win32_display_get_primary_monitor;
_gdk_win32_windowing_init ();
}
......@@ -42,6 +42,8 @@ struct _GdkWin32Display
HDC gl_hdc;
HWND gl_hwnd;
GPtrArray *monitors;
guint hasWglARBCreateContext : 1;
guint hasWglEXTSwapControl : 1;
guint hasWglOMLSyncControl : 1;
......@@ -52,4 +54,8 @@ struct _GdkWin32DisplayClass
GdkDisplayClass display_class;
};
gboolean _gdk_win32_display_init_monitors (GdkWin32Display *display);
GPtrArray *_gdk_win32_display_get_monitor_list (GdkWin32Display *display);
#endif /* __GDK_DISPLAY__WIN32_H__ */
/*
* Copyright © 2016 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#if defined (_WIN32_WINNT) && WIN32_WINNT < 0x0601
# undef _WIN32_WINNT
# define _WIN32_WINNT 0x0601
# ifdef WINVER
# undef WINVER
# endif
# define WINVER _WIN32_WINNT
#elif !defined (_WIN32_WINNT)
# define _WIN32_WINNT 0x0601
# ifdef WINVER
# undef WINVER
# endif
# define WINVER _WIN32_WINNT
#endif
#include "config.h"
#include "gdkmonitor-win32.h"
#include <glib.h>
#include <gio/gio.h>
#include <cfgmgr32.h>
#include <devpropdef.h>
#include <setupapi.h>
#include "gdkprivate-win32.h"
G_DEFINE_TYPE (GdkWin32Monitor, gdk_win32_monitor, GDK_TYPE_MONITOR)
/* MinGW-w64 carelessly put DISPLAYCONFIG_OUTPUT_TECHNOLOGY_OTHER = -1 into this
* enum, as documented by MSDN. However, with
* DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INTERNAL = 0x80000000 and
* DISPLAYCONFIG_OUTPUT_TECHNOLOGY_FORCE_UINT32 = 0xFFFFFFFF
* this had the effect of increasing enum size from 4 to 8 bytes,
* when compiled by GCC (MSVC doesn't have this problem), breaking ABI.
* At the moment of writing MinGW-w64 headers are still broken.
* When they are fixed, replace 9999 with actual version numbers.
* The fix below is not necessarily correct, but it works.
*/
#if SIZEOF_DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY == 4
# define fixedDISPLAYCONFIG_PATH_INFO DISPLAYCONFIG_PATH_INFO
# define fixedDISPLAYCONFIG_TARGET_DEVICE_NAME DISPLAYCONFIG_TARGET_DEVICE_NAME
#else
typedef enum {
fixedDISPLAYCONFIG_OUTPUT_TECHNOLOGY_OTHER = (int) -1,
fixedDISPLAYCONFIG_OUTPUT_TECHNOLOGY_HD15 = (int) 0,
fixedDISPLAYCONFIG_OUTPUT_TECHNOLOGY_SVIDEO = (int) 1,
fixedDISPLAYCONFIG_OUTPUT_TECHNOLOGY_COMPOSITE_VIDEO = (int) 2,
fixedDISPLAYCONFIG_OUTPUT_TECHNOLOGY_COMPONENT_VIDEO = (int) 3,
fixedDISPLAYCONFIG_OUTPUT_TECHNOLOGY_DVI = (int) 4,
fixedDISPLAYCONFIG_OUTPUT_TECHNOLOGY_HDMI = (int) 5,
fixedDISPLAYCONFIG_OUTPUT_TECHNOLOGY_LVDS = (int) 6,
fixedDISPLAYCONFIG_OUTPUT_TECHNOLOGY_D_JPN = (int) 8,
fixedDISPLAYCONFIG_OUTPUT_TECHNOLOGY_SDI = (int) 9,
fixedDISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EXTERNAL = (int) 10,
fixedDISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EMBEDDED = (int) 11,
fixedDISPLAYCONFIG_OUTPUT_TECHNOLOGY_UDI_EXTERNAL = (int) 12,
fixedDISPLAYCONFIG_OUTPUT_TECHNOLOGY_UDI_EMBEDDED = (int) 13,
fixedDISPLAYCONFIG_OUTPUT_TECHNOLOGY_SDTVDONGLE = (int) 14,
fixedDISPLAYCONFIG_OUTPUT_TECHNOLOGY_INTERNAL = (int) 0x80000000,
fixedDISPLAYCONFIG_OUTPUT_TECHNOLOGY_FORCE_UINT32 = (int) 0xFFFFFFFF
} fixedDISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY;
typedef struct fixedDISPLAYCONFIG_PATH_TARGET_INFO {
LUID adapterId;
UINT32 id;
UINT32 modeInfoIdx;
fixedDISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY outputTechnology;
DISPLAYCONFIG_ROTATION rotation;
DISPLAYCONFIG_SCALING scaling;
DISPLAYCONFIG_RATIONAL refreshRate;
DISPLAYCONFIG_SCANLINE_ORDERING scanLineOrdering;
WINBOOL targetAvailable;
UINT32 statusFlags;
} fixedDISPLAYCONFIG_PATH_TARGET_INFO;
typedef struct fixedDISPLAYCONFIG_PATH_INFO
{
DISPLAYCONFIG_PATH_SOURCE_INFO sourceInfo;
fixedDISPLAYCONFIG_PATH_TARGET_INFO targetInfo;
UINT32 flags;
} fixedDISPLAYCONFIG_PATH_INFO;
typedef struct fixedDISPLAYCONFIG_TARGET_DEVICE_NAME
{
DISPLAYCONFIG_DEVICE_INFO_HEADER header;
DISPLAYCONFIG_TARGET_DEVICE_NAME_FLAGS flags;
fixedDISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY outputTechnology;
UINT16 edidManufactureId;
UINT16 edidProductCodeId;
UINT32 connectorInstance;
WCHAR monitorFriendlyDeviceName[64];
WCHAR monitorDevicePath[128];
} fixedDISPLAYCONFIG_TARGET_DEVICE_NAME;
#endif
/* MinGW-w64 does not have these functions in its import libraries
* at the moment of writing.
* Also, Windows Vista doesn't have these functions at all
* (according to MSDN it does, but that is a lie), so we'd have
* to load them manually anyway (otherwise GTK apps won't even start
* on Vista).
*/
typedef LONG WINAPI
(* funcGetDisplayConfigBufferSizes) (UINT32 flags,
UINT32* numPathArrayElements,
UINT32* numModeInfoArrayElements);
typedef LONG WINAPI
(* funcQueryDisplayConfig) (UINT32 flags,
UINT32* numPathArrayElements,
fixedDISPLAYCONFIG_PATH_INFO* pathArray,
UINT32* numModeInfoArrayElements,
DISPLAYCONFIG_MODE_INFO* modeInfoArray,
DISPLAYCONFIG_TOPOLOGY_ID* currentTopologyId);
typedef LONG WINAPI
(* funcDisplayConfigGetDeviceInfo) (DISPLAYCONFIG_DEVICE_INFO_HEADER* requestPacket);
#ifndef MONITORINFOF_PRIMARY
#define MONITORINFOF_PRIMARY 1
#endif
/* MinGW-w64 does not have a prototype for function in its headers
* at the moment of writing.
*/
#if !defined (HAVE_SETUP_DI_GET_DEVICE_PROPERTY_W)
BOOL WINAPI SetupDiGetDevicePropertyW (HDEVINFO DeviceInfoSet,
PSP_DEVINFO_DATA DeviceInfoData,
const DEVPROPKEY *PropertyKey,
DEVPROPTYPE *PropertyType,
PBYTE PropertyBuffer,
DWORD PropertyBufferSize,
PDWORD RequiredSize,
DWORD Flags);
#endif
#define G_GUID_FORMAT "%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X"
#define g_format_guid(guid) (guid)->Data1, \
(guid)->Data2, \
(guid)->Data3, \
(guid)->Data4[0], \
(guid)->Data4[1], \
(guid)->Data4[2], \
(guid)->Data4[3], \
(guid)->Data4[4], \
(guid)->Data4[5], \
(guid)->Data4[6], \
(guid)->Data4[7]
static gboolean
get_device_property (HDEVINFO device_infoset,
SP_DEVINFO_DATA *device_info_data,
DEVPROPKEY *property_key,
gpointer *r_buffer,
gsize *r_buffer_size,
DEVPROPTYPE *r_property_type,
GError **error)
{
DEVPROPTYPE property_type;
gpointer property;
DWORD property_size;
property = NULL;
property_size = 0;
if (!SetupDiGetDevicePropertyW (device_infoset,
device_info_data,
property_key,
&property_type,
property,
property_size,
&property_size,
0))
{
DWORD error_code = GetLastError ();
if (error_code != ERROR_INSUFFICIENT_BUFFER)
{
gchar *emsg = g_win32_error_message (error_code);
g_warning ("Failed to get device node property {" G_GUID_FORMAT "},%lu size: %s",
g_format_guid (&property_key->fmtid),
property_key->pid,
emsg);
g_free (emsg);
return FALSE;
}
}
if (r_buffer)
{
property = g_malloc (property_size);
if (!SetupDiGetDevicePropertyW (device_infoset,
device_info_data,
property_key,
&property_type,
property,
property_size,
&property_size,
0))
{
DWORD error_code = GetLastError ();
gchar *emsg = g_win32_error_message (error_code);
g_warning ("Failed to get device node property {" G_GUID_FORMAT "},%lu: %s",
g_format_guid (&property_key->fmtid),
property_key->pid,
emsg);
g_free (emsg);
return FALSE;
}
*r_buffer = property;
}
if (r_buffer_size)
*r_buffer_size = property_size;
if (r_property_type)
*r_property_type = property_type;
return TRUE;
}
static GPtrArray *
get_monitor_devices (GdkWin32Display *win32_display)
{
GPtrArray *monitor_array;
HDEVINFO device_infoset;
SP_DEVINFO_DATA device_info_data;
DWORD device_index;
GUID device_interface_monitor = {0xe6f07b5f, 0xee97, 0x4a90, {0xb0, 0x76, 0x33, 0xf5, 0x7b, 0xf4, 0xea, 0xa7}};
DEVPROPKEY pkey_device_instance_id = {{0x78C34FC8, 0x104A, 0x4ACA, {0x9E, 0xA4, 0x52, 0x4D, 0x52, 0x99, 0x6E, 0x57}}, 256};
DEVPROPKEY pkey_manufacturer = {{0xA45C254E, 0xDF1C, 0x4EFD, {0x80, 0x20, 0x67, 0xD1, 0x46, 0xA8, 0x50, 0xE0}}, 13};
DEVPROPKEY pkey_display_name = {{0xB725F130, 0x47EF, 0x101A, {0xA5, 0xF1, 0x02, 0x60, 0x8C, 0x9E, 0xEB, 0xAC}}, 10};
monitor_array = g_ptr_array_new_with_free_func (g_object_unref);
device_infoset = SetupDiGetClassDevs (&device_interface_monitor, 0, 0, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
if (device_infoset == INVALID_HANDLE_VALUE)
return monitor_array;
for (device_index = 0; TRUE; device_index++)
{
gunichar2 *p;
gchar *instance_path;
gunichar2 *prop;
DWORD proptype;
HKEY device_registry_key;
GdkWin32Monitor *w32mon;
GdkMonitor *mon;
unsigned char *edid;
DWORD edid_size;
DWORD edid_type;
memset (&device_info_data, 0, sizeof (device_info_data));
device_info_data.cbSize = sizeof (device_info_data);
if (!SetupDiEnumDeviceInfo (device_infoset, device_index, &device_info_data))
{
DWORD error_code = GetLastError ();
if (error_code == ERROR_NO_MORE_ITEMS)
break;
g_warning ("SetupDiEnumDeviceInfo() failed: %lu\n", error_code);
break;
}
if (!get_device_property (device_infoset,
&device_info_data,
&pkey_device_instance_id,
(gpointer *) &prop,
NULL,
&proptype,
NULL))
continue;
if (proptype != DEVPROP_TYPE_STRING)
{
g_free (prop);
continue;
}
w32mon = g_object_new (GDK_TYPE_WIN32_MONITOR, "display", win32_display, NULL);
mon = GDK_MONITOR (w32mon);
g_ptr_array_add (monitor_array, w32mon);
/* Half-initialized monitors are candidates for removal */
w32mon->remove = TRUE;
/* device instance ID looks like: DISPLAY\FOO\X&XXXXXXX&X&UIDXXX */
for (p = prop; p[0]; p++)
if (p[0] == L'\\')
p[0] = L'#';
/* now device instance ID looks like: DISPLAY#FOO#X&XXXXXXX&X&UIDXXX */
/* instance path looks like: \\?\DISPLAY#FOO#X&XXXXXXX&X&UIDXXX#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7} */
instance_path = g_strdup_printf ("\\\\?\\%ls#{" G_GUID_FORMAT "}",
prop,
g_format_guid (&device_interface_monitor));
w32mon->instance_path = g_utf8_strdown (instance_path, -1);
g_free (instance_path);
g_free (prop);
if (get_device_property (device_infoset,
&device_info_data,
&pkey_manufacturer,
(gpointer *) &prop,
NULL, &proptype, NULL))
{
if (proptype == DEVPROP_TYPE_STRING)
{
gchar *manufacturer = g_utf16_to_utf8 (prop, -1, NULL, NULL, NULL);
gdk_monitor_set_manufacturer (mon, manufacturer);
g_free (manufacturer);
}
g_free (prop);
}
if (get_device_property (device_infoset,
&device_info_data,
&pkey_display_name,
(gpointer *) &prop,
NULL, &proptype, NULL))
{
if (proptype == DEVPROP_TYPE_STRING)
{
gchar *name = g_utf16_to_utf8 (prop, -1, NULL, NULL, NULL);
gdk_monitor_set_model (mon, name);
g_free (name);
}
g_free (prop);
}
device_registry_key = SetupDiOpenDevRegKey (device_infoset, &device_info_data, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ);
if (device_registry_key == NULL || device_registry_key == INVALID_HANDLE_VALUE)
continue;
edid = NULL;
edid_size = 0;
if (RegQueryValueExW (device_registry_key, L"EDID",
NULL, &edid_type,
edid, &edid_size) == ERROR_SUCCESS)
{
edid = g_malloc (edid_size);
if (RegQueryValueExW (device_registry_key, L"EDID",
NULL, &edid_type,
edid, &edid_size) == ERROR_SUCCESS)
{
gdk_monitor_set_physical_size (mon,
((edid[68] & 0x00F0) << 4) + edid[66],
((edid[68] & 0x000F) << 8) + edid[67]);
}