Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
gtk
Project overview
Project overview
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
1,146
Issues
1,146
List
Boards
Labels
Milestones
Merge Requests
99
Merge Requests
99
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Container Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
GNOME
gtk
Commits
026cb538
Commit
026cb538
authored
Apr 20, 2016
by
LRN
Committed by
Matthias Clasen
Apr 27, 2016
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
win32: Port to new monitor api
parent
5c1d0915
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
1250 additions
and
246 deletions
+1250
-246
configure.ac
configure.ac
+49
-1
gdk/win32/Makefile.am
gdk/win32/Makefile.am
+6
-2
gdk/win32/gdkdisplay-win32.c
gdk/win32/gdkdisplay-win32.c
+208
-0
gdk/win32/gdkdisplay-win32.h
gdk/win32/gdkdisplay-win32.h
+6
-0
gdk/win32/gdkmonitor-win32.c
gdk/win32/gdkmonitor-win32.c
+833
-0
gdk/win32/gdkmonitor-win32.h
gdk/win32/gdkmonitor-win32.h
+57
-0
gdk/win32/gdkscreen-win32.c
gdk/win32/gdkscreen-win32.c
+40
-243
gdk/win32/gdkwin32.h
gdk/win32/gdkwin32.h
+1
-0
gdk/win32/gdkwin32monitor.h
gdk/win32/gdkwin32monitor.h
+50
-0
No files found.
configure.ac
View file @
026cb538
...
...
@@ -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
...
...
gdk/win32/Makefile.am
View file @
026cb538
...
...
@@ -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
...
...
gdk/win32/gdkdisplay-win32.c
View file @
026cb538
...
...
@@ -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
();
}
gdk/win32/gdkdisplay-win32.h
View file @
026cb538
...
...
@@ -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__ */
gdk/win32/gdkmonitor-win32.c
0 → 100644
View file @
026cb538
/*
* 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
]);
}