win32: Port to new monitor api
This commit is contained in:
parent
5c1d0915af
commit
026cb53875
50
configure.ac
50
configure.ac
@ -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__ */
|
||||
|
833
gdk/win32/gdkmonitor-win32.c
Normal file
833
gdk/win32/gdkmonitor-win32.c
Normal file
@ -0,0 +1,833 @@
|
||||
/*
|
||||
* 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]);
|
||||
}
|
||||
|
||||
g_free (edid);
|
||||
}
|
||||
|
||||
RegCloseKey (device_registry_key);
|
||||
}
|
||||
|
||||
SetupDiDestroyDeviceInfoList (device_infoset);
|
||||
|
||||
return monitor_array;
|
||||
}
|
||||
|
||||
static void
|
||||
populate_monitor_devices_from_display_config (GPtrArray *monitors)
|
||||
{
|
||||
HMODULE user32;
|
||||
LONG return_code;
|
||||
funcGetDisplayConfigBufferSizes getDisplayConfigBufferSizes;
|
||||
funcQueryDisplayConfig queryDisplayConfig;
|
||||
funcDisplayConfigGetDeviceInfo displayConfigGetDeviceInfo;
|
||||
UINT32 dispconf_mode_count;
|
||||
UINT32 dispconf_path_count;
|
||||
fixedDISPLAYCONFIG_PATH_INFO *dispconf_paths;
|
||||
DISPLAYCONFIG_MODE_INFO *dispconf_modes;
|
||||
gint path_index;
|
||||
|
||||
user32 = LoadLibraryA ("user32.dll");
|
||||
|
||||
if (user32 == NULL)
|
||||
return;
|
||||
|
||||
getDisplayConfigBufferSizes = (funcGetDisplayConfigBufferSizes) GetProcAddress (user32,
|
||||
"GetDisplayConfigBufferSizes");
|
||||
queryDisplayConfig = (funcQueryDisplayConfig) GetProcAddress (user32,
|
||||
"QueryDisplayConfig");
|
||||
displayConfigGetDeviceInfo = (funcDisplayConfigGetDeviceInfo) GetProcAddress (user32,
|
||||
"DisplayConfigGetDeviceInfo");
|
||||
if (getDisplayConfigBufferSizes == NULL ||
|
||||
queryDisplayConfig == NULL ||
|
||||
displayConfigGetDeviceInfo == NULL)
|
||||
{
|
||||
/* This does happen on Windows Vista, so don't warn about this */
|
||||
FreeLibrary (user32);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
return_code = getDisplayConfigBufferSizes (QDC_ONLY_ACTIVE_PATHS,
|
||||
&dispconf_path_count,
|
||||
&dispconf_mode_count);
|
||||
|
||||
if (return_code != ERROR_SUCCESS)
|
||||
{
|
||||
g_warning ("Can't get displayconfig buffer size: 0x%lx\n", return_code);
|
||||
FreeLibrary (user32);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
dispconf_paths = g_new (fixedDISPLAYCONFIG_PATH_INFO, dispconf_path_count);
|
||||
dispconf_modes = g_new (DISPLAYCONFIG_MODE_INFO, dispconf_mode_count);
|
||||
|
||||
return_code = queryDisplayConfig (QDC_ONLY_ACTIVE_PATHS,
|
||||
&dispconf_path_count,
|
||||
dispconf_paths,
|
||||
&dispconf_mode_count,
|
||||
dispconf_modes,
|
||||
NULL);
|
||||
|
||||
if (return_code != ERROR_SUCCESS)
|
||||
{
|
||||
g_free (dispconf_paths);
|
||||
g_free (dispconf_modes);
|
||||
FreeLibrary (user32);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
for (path_index = 0; path_index < dispconf_path_count; path_index++)
|
||||
{
|
||||
fixedDISPLAYCONFIG_TARGET_DEVICE_NAME tdn;
|
||||
gint i;
|
||||
GdkWin32Monitor *w32mon;
|
||||
GdkMonitor *mon;
|
||||
gchar *path, *path_lower;
|
||||
DISPLAYCONFIG_RATIONAL *refresh;
|
||||
|
||||
if ((dispconf_paths[path_index].flags & DISPLAYCONFIG_PATH_ACTIVE) == 0)
|
||||
continue;
|
||||
|
||||
tdn.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME;
|
||||
tdn.header.size = sizeof (tdn);
|
||||
tdn.header.adapterId = dispconf_paths[path_index].targetInfo.adapterId;
|
||||
tdn.header.id = dispconf_paths[path_index].targetInfo.id;
|
||||
|
||||
return_code = displayConfigGetDeviceInfo (&tdn.header);
|
||||
|
||||
if (return_code != ERROR_SUCCESS)
|
||||
continue;
|
||||
|
||||
path = g_utf16_to_utf8 (tdn.monitorDevicePath, -1, NULL, NULL, NULL);
|
||||
|
||||
if (path == NULL)
|
||||
continue;
|
||||
|
||||
path_lower = g_utf8_strdown (path, -1);
|
||||
|
||||
g_free (path);
|
||||
|
||||
for (i = 0, w32mon = NULL; i < monitors->len; i++)
|
||||
{
|
||||
GdkWin32Monitor *m = g_ptr_array_index (monitors, i);
|
||||
|
||||
if (g_strcmp0 (m->instance_path, path_lower) != 0)
|
||||
continue;
|
||||
|
||||
w32mon = m;
|
||||
break;
|
||||
}
|
||||
|
||||
g_free (path_lower);
|
||||
|
||||
if (w32mon == NULL)
|
||||
continue;
|
||||
|
||||
mon = GDK_MONITOR (w32mon);
|
||||
|
||||
if (!tdn.flags.friendlyNameForced)
|
||||
{
|
||||
/* monitorFriendlyDeviceName is usually nicer */
|
||||
gchar *name = g_utf16_to_utf8 (tdn.monitorFriendlyDeviceName, -1, NULL, NULL, NULL);
|
||||
gdk_monitor_set_model (mon, name);
|
||||
g_free (name);
|
||||
}
|
||||
|
||||
refresh = &dispconf_paths[path_index].targetInfo.refreshRate;
|
||||
gdk_monitor_set_refresh_rate (mon,
|
||||
refresh->Numerator * 1000 / refresh->Denominator);
|
||||
}
|
||||
|
||||
g_free (dispconf_paths);
|
||||
g_free (dispconf_modes);
|
||||
|
||||
FreeLibrary (user32);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
GPtrArray *monitors;
|
||||
gboolean have_monitor_devices;
|
||||
GdkWin32Display *display;
|
||||
} EnumMonitorData;
|
||||
|
||||
static BOOL CALLBACK
|
||||
enum_monitor (HMONITOR hmonitor,
|
||||
HDC hdc,
|
||||
LPRECT rect,
|
||||
LPARAM param)
|
||||
{
|
||||
EnumMonitorData *data = (EnumMonitorData *) param;
|
||||
MONITORINFOEXW monitor_info;
|
||||
DWORD i_adapter;
|
||||
|
||||
/* Grab monitor_info for this logical monitor */
|
||||
monitor_info.cbSize = sizeof (MONITORINFOEXW);
|
||||
GetMonitorInfoW (hmonitor, (MONITORINFO *) &monitor_info);
|
||||
|
||||
/* Sidestep to enumerate display adapters */
|
||||
for (i_adapter = 0; TRUE; i_adapter++)
|
||||
{
|
||||
DISPLAY_DEVICEW dd;
|
||||
DEVMODEW dm;
|
||||
DWORD i_monitor;
|
||||
DWORD frequency;
|
||||
|
||||
memset (&dd, 0, sizeof (dd));
|
||||
dd.cb = sizeof (dd);
|
||||
|
||||
/* Get i_adapter'th adapter */
|
||||
if (!EnumDisplayDevicesW (NULL, i_adapter, &dd, EDD_GET_DEVICE_INTERFACE_NAME))
|
||||
break;
|
||||
|
||||
if ((dd.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) == 0)
|
||||
continue;
|
||||
|
||||
/* Match this display adapter to one for which we've got monitor_info
|
||||
* (logical monitor == adapter)
|
||||
*/
|
||||
if (wcscmp (dd.DeviceName, monitor_info.szDevice) != 0)
|
||||
continue;
|
||||
|
||||
dm.dmSize = sizeof (dm);
|
||||
|
||||
/* Grab refresh rate for this adapter while we're at it */
|
||||
if (EnumDisplaySettingsW (dd.DeviceName, ENUM_CURRENT_SETTINGS, &dm))
|
||||
frequency = dm.dmDisplayFrequency;
|
||||
else
|
||||
frequency = 0;
|
||||
|
||||
/* Enumerate monitors connected to this display adapter */
|
||||
for (i_monitor = 0; TRUE; i_monitor++)
|
||||
{
|
||||
DISPLAY_DEVICEW dd_monitor;
|
||||
gchar *device_id_lower, *tmp;
|
||||
DWORD i;
|
||||
GdkWin32Monitor *w32mon;
|
||||
GdkMonitor *mon;
|
||||
GdkRectangle rect;
|
||||
|
||||
memset (&dd_monitor, 0, sizeof (dd_monitor));
|
||||
dd_monitor.cb = sizeof (dd_monitor);
|
||||
|
||||
if (data->have_monitor_devices)
|
||||
{
|
||||
/* Get i_monitor'th monitor */
|
||||
if (!EnumDisplayDevicesW (dd.DeviceName, i_monitor, &dd_monitor, EDD_GET_DEVICE_INTERFACE_NAME))
|
||||
break;
|
||||
|
||||
tmp = g_utf16_to_utf8 (dd_monitor.DeviceID, -1, NULL, NULL, NULL);
|
||||
|
||||
if (tmp == NULL)
|
||||
continue;
|
||||
|
||||
device_id_lower = g_utf8_strdown (tmp, -1);
|
||||
g_free (tmp);
|
||||
|
||||
/* Match this monitor to one of the monitor devices we found earlier */
|
||||
for (i = 0, w32mon = NULL; i < data->monitors->len; i++)
|
||||
{
|
||||
GdkWin32Monitor *m = g_ptr_array_index (data->monitors, i);
|
||||
|
||||
if (g_strcmp0 (device_id_lower, m->instance_path) != 0)
|
||||
continue;
|
||||
|
||||
w32mon = m;
|
||||
break;
|
||||
}
|
||||
|
||||
g_free (device_id_lower);
|
||||
|
||||
if (w32mon == NULL)
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Headless PC or a virtual machine, it has no monitor devices.
|
||||
* Make one up.
|
||||
*/
|
||||
w32mon = g_object_new (GDK_TYPE_WIN32_MONITOR, "display", data->display, NULL);
|
||||
g_ptr_array_add (data->monitors, w32mon);
|
||||
i = data->monitors->len - 1;
|
||||
w32mon->madeup = TRUE;
|
||||
}
|
||||
|
||||
mon = GDK_MONITOR (w32mon);
|
||||
|
||||
if (gdk_monitor_get_model (mon) == NULL)
|
||||
{
|
||||
|
||||
gchar *name = NULL;
|
||||
|
||||
/* Only use dd.DeviceName as a last resort, as it is just
|
||||
* \\.\DISPLAYX\MonitorY (for some values of X and Y).
|
||||
*/
|
||||
if (dd_monitor.DeviceName[0] != L'\0')
|
||||
name = g_utf16_to_utf8 (dd_monitor.DeviceName, -1, NULL, NULL, NULL);
|
||||
else if (dd.DeviceName[0] != L'\0')
|
||||
name = g_utf16_to_utf8 (dd.DeviceName, -1, NULL, NULL, NULL);
|
||||
|
||||
if (name != NULL)
|
||||
gdk_monitor_set_model (mon, name);
|
||||
|
||||
g_free (name);
|
||||
}
|
||||
|
||||
/* GetDeviceCaps seems to provide a wild guess, prefer more precise EDID info */
|
||||
if (gdk_monitor_get_width_mm (mon) == 0 &&
|
||||
gdk_monitor_get_height_mm (mon) == 0)
|
||||
{
|
||||
HDC hDC = CreateDCW (L"DISPLAY", monitor_info.szDevice, NULL, NULL);
|
||||
|
||||
gdk_monitor_set_physical_size (mon,
|
||||
GetDeviceCaps (hDC, HORZSIZE),
|
||||
GetDeviceCaps (hDC, VERTSIZE));
|
||||
DeleteDC (hDC);
|
||||
}
|
||||
|
||||
/* frequency is in Hz and is unsigned long,
|
||||
* prefer more precise refresh_rate found earlier,
|
||||
* which comes as a Numerator & Denominator pair and is more precise.
|
||||
*/
|
||||
if (gdk_monitor_get_refresh_rate (mon) == 0)
|
||||
gdk_monitor_set_refresh_rate (mon, frequency * 1000);
|
||||
|
||||
/* This is the reason this function exists. This data is not available
|
||||
* via other functions.
|
||||
*/
|
||||
rect.x = monitor_info.rcMonitor.left;
|
||||
rect.y = monitor_info.rcMonitor.top;
|
||||
rect.width = monitor_info.rcMonitor.right - monitor_info.rcMonitor.left;
|
||||
rect.height = monitor_info.rcMonitor.bottom - monitor_info.rcMonitor.top;
|
||||
gdk_monitor_set_position (mon, rect.x, rect.y);
|
||||
gdk_monitor_set_size (mon, rect.width, rect.height);
|
||||
|
||||
rect.x = monitor_info.rcWork.left;
|
||||
rect.y = monitor_info.rcWork.top;
|
||||
rect.width = monitor_info.rcWork.right - monitor_info.rcWork.left;
|
||||
rect.height = monitor_info.rcWork.bottom - monitor_info.rcWork.top;
|
||||
w32mon->work_rect = rect;
|
||||
|
||||
if (monitor_info.dwFlags & MONITORINFOF_PRIMARY && i != 0)
|
||||
{
|
||||
/* Put primary monitor at index 0, just in case somebody needs
|
||||
* to know which one is the primary.
|
||||
*/
|
||||
GdkWin32Monitor *temp = g_ptr_array_index (data->monitors, 0);
|
||||
g_ptr_array_index (data->monitors, 0) = w32mon;
|
||||
g_ptr_array_index (data->monitors, i) = temp;
|
||||
}
|
||||
|
||||
/* Work area is the most important component, actively used by GTK,
|
||||
* but our initial list of monitor devices did not have it.
|
||||
* Any monitor devices not matched in this functions will have
|
||||
* 0-filled work area and will therefore be useless, so let them
|
||||
* keep remove == TRUE and be removed further up the stack.
|
||||
*/
|
||||
w32mon->remove = FALSE;
|
||||
|
||||
/* One virtual monitor per display adapter */
|
||||
if (w32mon->madeup)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GPtrArray *
|
||||
_gdk_win32_display_get_monitor_list (GdkWin32Display *win32_display)
|
||||
{
|
||||
EnumMonitorData data;
|
||||
gint i;
|
||||
|
||||
data.display = win32_display;
|
||||
data.monitors = get_monitor_devices (win32_display);
|
||||
|
||||
if (data.monitors->len != 0)
|
||||
{
|
||||
populate_monitor_devices_from_display_config (data.monitors);
|
||||
data.have_monitor_devices = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
data.have_monitor_devices = FALSE;
|
||||
}
|
||||
|
||||
EnumDisplayMonitors (NULL, NULL, enum_monitor, (LPARAM) &data);
|
||||
|
||||
_gdk_offset_x = G_MININT;
|
||||
_gdk_offset_y = G_MININT;
|
||||
|
||||
for (i = 0; i < data.monitors->len; i++)
|
||||
{
|
||||
GdkWin32Monitor *m;
|
||||
GdkRectangle rect;
|
||||
|
||||
m = g_ptr_array_index (data.monitors, i);
|
||||
|
||||
if (m->remove)
|
||||
{
|
||||
g_ptr_array_remove_index (data.monitors, i);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Calculate offset */
|
||||
gdk_monitor_get_geometry (GDK_MONITOR (m), &rect);
|
||||
_gdk_offset_x = MAX (_gdk_offset_x, -rect.x);
|
||||
_gdk_offset_y = MAX (_gdk_offset_y, -rect.y);
|
||||
}
|
||||
|
||||
GDK_NOTE (MISC, g_print ("Multi-monitor offset: (%d,%d)\n",
|
||||
_gdk_offset_x, _gdk_offset_y));
|
||||
|
||||
/* Translate monitor coords into GDK coordinate space */
|
||||
for (i = 0; i < data.monitors->len; i++)
|
||||
{
|
||||
GdkWin32Monitor *m;
|
||||
GdkRectangle rect;
|
||||
|
||||
m = g_ptr_array_index (data.monitors, i);
|
||||
|
||||
gdk_monitor_get_geometry (GDK_MONITOR (m), &rect);
|
||||
rect.x += _gdk_offset_x;
|
||||
rect.y += _gdk_offset_y;
|
||||
gdk_monitor_set_position (GDK_MONITOR (m), rect.x, rect.y);
|
||||
|
||||
m->work_rect.x += _gdk_offset_x;
|
||||
m->work_rect.y += _gdk_offset_y;
|
||||
|
||||
GDK_NOTE (MISC, g_print ("Monitor %d: %dx%d@%+d%+d\n", i,
|
||||
rect.width, rect.height, rect.x, rect.y));
|
||||
}
|
||||
|
||||
return data.monitors;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_win32_monitor_finalize (GObject *object)
|
||||
{
|
||||
GdkWin32Monitor *win32_monitor = GDK_WIN32_MONITOR (object);
|
||||
|
||||
g_free (win32_monitor->instance_path);
|
||||
|
||||
G_OBJECT_CLASS (gdk_win32_monitor_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
int
|
||||
_gdk_win32_monitor_compare (GdkWin32Monitor *a,
|
||||
GdkWin32Monitor *b)
|
||||
{
|
||||
if (a->instance_path != NULL &&
|
||||
b->instance_path != NULL)
|
||||
return g_strcmp0 (a->instance_path, b->instance_path);
|
||||
|
||||
return a == b ? 0 : a < b ? -1 : 1;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_win32_monitor_get_workarea (GdkMonitor *monitor,
|
||||
GdkRectangle *dest)
|
||||
{
|
||||
GdkWin32Monitor *win32_monitor = GDK_WIN32_MONITOR (monitor);
|
||||
|
||||
*dest = win32_monitor->work_rect;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_win32_monitor_init (GdkWin32Monitor *monitor)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_win32_monitor_class_init (GdkWin32MonitorClass *class)
|
||||
{
|
||||
G_OBJECT_CLASS (class)->finalize = gdk_win32_monitor_finalize;
|
||||
|
||||
GDK_MONITOR_CLASS (class)->get_workarea = gdk_win32_monitor_get_workarea;
|
||||
}
|
57
gdk/win32/gdkmonitor-win32.h
Normal file
57
gdk/win32/gdkmonitor-win32.h
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef __GDK_WIN32_MONITOR_PRIVATE_H__
|
||||
#define __GDK_WIN32_MONITOR_PRIVATE_H__
|
||||
|
||||
#include <windows.h>
|
||||
#include <glib.h>
|
||||
#include <gio/gio.h>
|
||||
|
||||
#include "gdkmonitorprivate.h"
|
||||
|
||||
#include "gdkwin32monitor.h"
|
||||
|
||||
struct _GdkWin32Monitor
|
||||
{
|
||||
GdkMonitor parent;
|
||||
|
||||
/* work area */
|
||||
GdkRectangle work_rect;
|
||||
|
||||
/* Device instance path (used to match GdkWin32Monitor to monitor device) */
|
||||
gchar *instance_path;
|
||||
|
||||
/* TRUE if monitor is made up by us
|
||||
* (this happens when system has logical monitors, but no physical ones).
|
||||
*/
|
||||
guint madeup : 1;
|
||||
|
||||
/* TRUE if we should notify GDK about this monitor being added */
|
||||
guint add : 1;
|
||||
|
||||
/* TRUE if we should notify GDK about this monitor being removed */
|
||||
guint remove : 1;
|
||||
};
|
||||
|
||||
struct _GdkWin32MonitorClass {
|
||||
GdkMonitorClass parent_class;
|
||||
};
|
||||
|
||||
int _gdk_win32_monitor_compare (GdkWin32Monitor *a, GdkWin32Monitor *b);
|
||||
|
||||
#endif
|
@ -22,24 +22,15 @@
|
||||
#include "gdkwin32screen.h"
|
||||
#include "gdkdisplayprivate.h"
|
||||
#include "gdkvisualprivate.h"
|
||||
#include "gdkdisplay-win32.h"
|
||||
#include "gdkmonitor-win32.h"
|
||||
|
||||
#include <dwmapi.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gchar *name;
|
||||
gint width_mm, height_mm;
|
||||
GdkRectangle rect;
|
||||
GdkRectangle work_rect;
|
||||
} GdkWin32Monitor;
|
||||
|
||||
struct _GdkWin32Screen
|
||||
{
|
||||
GdkScreen parent_instance;
|
||||
|
||||
gint num_monitors;
|
||||
GdkWin32Monitor *monitors;
|
||||
|
||||
GdkVisual *system_visual;
|
||||
GdkVisual *rgba_visual;
|
||||
gint available_visual_depths[1];
|
||||
@ -257,26 +248,44 @@ init_visual (GdkScreen *screen,
|
||||
return visual;
|
||||
}
|
||||
|
||||
static void
|
||||
static gboolean
|
||||
init_root_window_size (GdkWin32Screen *screen)
|
||||
{
|
||||
GdkRectangle rect;
|
||||
GdkRectangle result;
|
||||
int i;
|
||||
GdkDisplay *display = _gdk_display;
|
||||
int monitor_count;
|
||||
GdkMonitor *monitor;
|
||||
gboolean changed;
|
||||
|
||||
rect = screen->monitors[0].rect;
|
||||
for (i = 1; i < screen->num_monitors; i++)
|
||||
gdk_rectangle_union (&rect, &screen->monitors[i].rect, &rect);
|
||||
monitor_count = gdk_display_get_n_monitors (display);
|
||||
monitor = gdk_display_get_monitor (display, 0);
|
||||
gdk_monitor_get_geometry (monitor, &result);
|
||||
|
||||
screen->root_window->width = rect.width;
|
||||
screen->root_window->height = rect.height;
|
||||
for (i = 1; i < monitor_count; i++)
|
||||
{
|
||||
GdkRectangle rect;
|
||||
|
||||
monitor = gdk_display_get_monitor (display, i);
|
||||
gdk_monitor_get_geometry (monitor, &rect);
|
||||
gdk_rectangle_union (&result, &rect, &result);
|
||||
}
|
||||
|
||||
changed = screen->root_window->width != result.width ||
|
||||
screen->root_window->height != result.height;
|
||||
screen->root_window->width = result.width;
|
||||
screen->root_window->height = result.height;
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
static void
|
||||
static gboolean
|
||||
init_root_window (GdkWin32Screen *screen_win32)
|
||||
{
|
||||
GdkScreen *screen;
|
||||
GdkWindow *window;
|
||||
GdkWindowImplWin32 *impl_win32;
|
||||
gboolean changed;
|
||||
|
||||
screen = GDK_SCREEN (screen_win32);
|
||||
|
||||
@ -295,7 +304,7 @@ init_root_window (GdkWin32Screen *screen_win32)
|
||||
|
||||
screen_win32->root_window = window;
|
||||
|
||||
init_root_window_size (screen_win32);
|
||||
changed = init_root_window_size (screen_win32);
|
||||
|
||||
window->x = 0;
|
||||
window->y = 0;
|
||||
@ -307,134 +316,8 @@ init_root_window (GdkWin32Screen *screen_win32)
|
||||
gdk_win32_handle_table_insert ((HANDLE *) &impl_win32->handle, window);
|
||||
|
||||
GDK_NOTE (MISC, g_print ("screen->root_window=%p\n", window));
|
||||
}
|
||||
|
||||
static BOOL CALLBACK
|
||||
count_monitor (HMONITOR hmonitor,
|
||||
HDC hdc,
|
||||
LPRECT rect,
|
||||
LPARAM data)
|
||||
{
|
||||
gint *n = (gint *) data;
|
||||
|
||||
(*n)++;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
GdkWin32Screen *screen;
|
||||
gint index;
|
||||
} EnumMonitorData;
|
||||
|
||||
static BOOL CALLBACK
|
||||
enum_monitor (HMONITOR hmonitor,
|
||||
HDC hdc,
|
||||
LPRECT rect,
|
||||
LPARAM param)
|
||||
{
|
||||
/* The struct MONITORINFOEX definition is for some reason different
|
||||
* in the winuser.h bundled with mingw64 from that in MSDN and the
|
||||
* official 32-bit mingw (the MONITORINFO part is in a separate "mi"
|
||||
* member). So to keep this easily compileable with either, repeat
|
||||
* the MSDN definition it here.
|
||||
*/
|
||||
typedef struct tagMONITORINFOEXA2 {
|
||||
DWORD cbSize;
|
||||
RECT rcMonitor;
|
||||
RECT rcWork;
|
||||
DWORD dwFlags;
|
||||
CHAR szDevice[CCHDEVICENAME];
|
||||
} MONITORINFOEXA2;
|
||||
|
||||
EnumMonitorData *data = (EnumMonitorData *) param;
|
||||
GdkWin32Monitor *monitor;
|
||||
MONITORINFOEXA2 monitor_info;
|
||||
HDC hDC;
|
||||
|
||||
g_assert (data->index < data->screen->num_monitors);
|
||||
|
||||
monitor = data->screen->monitors + data->index;
|
||||
|
||||
monitor_info.cbSize = sizeof (MONITORINFOEXA2);
|
||||
GetMonitorInfoA (hmonitor, (MONITORINFO *) &monitor_info);
|
||||
|
||||
#ifndef MONITORINFOF_PRIMARY
|
||||
#define MONITORINFOF_PRIMARY 1
|
||||
#endif
|
||||
|
||||
monitor->name = g_strdup (monitor_info.szDevice);
|
||||
hDC = CreateDCA ("DISPLAY", monitor_info.szDevice, NULL, NULL);
|
||||
monitor->width_mm = GetDeviceCaps (hDC, HORZSIZE);
|
||||
monitor->height_mm = GetDeviceCaps (hDC, VERTSIZE);
|
||||
DeleteDC (hDC);
|
||||
monitor->rect.x = monitor_info.rcMonitor.left;
|
||||
monitor->rect.y = monitor_info.rcMonitor.top;
|
||||
monitor->rect.width = monitor_info.rcMonitor.right - monitor_info.rcMonitor.left;
|
||||
monitor->rect.height = monitor_info.rcMonitor.bottom - monitor_info.rcMonitor.top;
|
||||
monitor->work_rect.x = monitor_info.rcWork.left;
|
||||
monitor->work_rect.y = monitor_info.rcWork.top;
|
||||
monitor->work_rect.width = monitor_info.rcWork.right - monitor_info.rcWork.left;
|
||||
monitor->work_rect.height = monitor_info.rcWork.bottom - monitor_info.rcWork.top;
|
||||
|
||||
if (monitor_info.dwFlags & MONITORINFOF_PRIMARY && data->index != 0)
|
||||
{
|
||||
/* Put primary monitor at index 0, just in case somebody needs
|
||||
* to know which one is the primary.
|
||||
*/
|
||||
GdkWin32Monitor temp = *monitor;
|
||||
*monitor = data->screen->monitors[0];
|
||||
data->screen->monitors[0] = temp;
|
||||
}
|
||||
|
||||
data->index++;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
init_monitors (GdkWin32Screen *screen)
|
||||
{
|
||||
gint count;
|
||||
EnumMonitorData data;
|
||||
gint i;
|
||||
|
||||
count = 0;
|
||||
EnumDisplayMonitors (NULL, NULL, count_monitor, (LPARAM) &count);
|
||||
screen->num_monitors = count;
|
||||
|
||||
screen->monitors = g_renew (GdkWin32Monitor, screen->monitors, screen->num_monitors);
|
||||
|
||||
data.screen = screen;
|
||||
data.index = 0;
|
||||
EnumDisplayMonitors (NULL, NULL, enum_monitor, (LPARAM) &data);
|
||||
|
||||
_gdk_offset_x = G_MININT;
|
||||
_gdk_offset_y = G_MININT;
|
||||
|
||||
/* Calculate offset */
|
||||
for (i = 0; i < screen->num_monitors; i++)
|
||||
{
|
||||
GdkRectangle *rect = &screen->monitors[i].rect;
|
||||
_gdk_offset_x = MAX (_gdk_offset_x, -rect->x);
|
||||
_gdk_offset_y = MAX (_gdk_offset_y, -rect->y);
|
||||
}
|
||||
GDK_NOTE (MISC, g_print ("Multi-monitor offset: (%d,%d)\n",
|
||||
_gdk_offset_x, _gdk_offset_y));
|
||||
|
||||
/* Translate monitor coords into GDK coordinate space */
|
||||
for (i = 0; i < screen->num_monitors; i++)
|
||||
{
|
||||
GdkRectangle *rect;
|
||||
rect = &screen->monitors[i].rect;
|
||||
rect->x += _gdk_offset_x;
|
||||
rect->y += _gdk_offset_y;
|
||||
rect = &screen->monitors[i].work_rect;
|
||||
rect->x += _gdk_offset_x;
|
||||
rect->y += _gdk_offset_y;
|
||||
GDK_NOTE (MISC, g_print ("Monitor %d: %dx%d@%+d%+d\n", i,
|
||||
rect->width, rect->height, rect->x, rect->y));
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -470,7 +353,7 @@ gdk_win32_screen_init (GdkWin32Screen *win32_screen)
|
||||
win32_screen->available_visual_depths[0] = win32_screen->rgba_visual->depth;
|
||||
win32_screen->available_visual_types[0] = win32_screen->rgba_visual->type;
|
||||
|
||||
init_monitors (win32_screen);
|
||||
_gdk_win32_display_init_monitors (GDK_WIN32_DISPLAY (_gdk_display));
|
||||
init_root_window (win32_screen);
|
||||
|
||||
/* On Windows 8 and later, DWM (composition) is always enabled */
|
||||
@ -480,9 +363,15 @@ gdk_win32_screen_init (GdkWin32Screen *win32_screen)
|
||||
void
|
||||
_gdk_win32_screen_on_displaychange_event (GdkWin32Screen *screen)
|
||||
{
|
||||
init_monitors (screen);
|
||||
init_root_window_size (screen);
|
||||
g_signal_emit_by_name (screen, "size-changed");
|
||||
gboolean monitors_changed;
|
||||
|
||||
monitors_changed = _gdk_win32_display_init_monitors (GDK_WIN32_DISPLAY (_gdk_display));
|
||||
|
||||
if (init_root_window_size (screen))
|
||||
g_signal_emit_by_name (screen, "size-changed");
|
||||
|
||||
if (monitors_changed)
|
||||
g_signal_emit_by_name (screen, "monitors-changed");
|
||||
}
|
||||
|
||||
static GdkDisplay *
|
||||
@ -521,84 +410,6 @@ gdk_win32_screen_get_root_window (GdkScreen *screen)
|
||||
return GDK_WIN32_SCREEN (screen)->root_window;
|
||||
}
|
||||
|
||||
static gint
|
||||
gdk_win32_screen_get_n_monitors (GdkScreen *screen)
|
||||
{
|
||||
g_return_val_if_fail (screen == gdk_display_get_default_screen (gdk_display_get_default ()), 0);
|
||||
|
||||
return GDK_WIN32_SCREEN (screen)->num_monitors;
|
||||
}
|
||||
|
||||
static gint
|
||||
gdk_win32_screen_get_primary_monitor (GdkScreen *screen)
|
||||
{
|
||||
g_return_val_if_fail (screen == gdk_display_get_default_screen (gdk_display_get_default ()), 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static gint
|
||||
gdk_win32_screen_get_monitor_width_mm (GdkScreen *screen,
|
||||
gint num_monitor)
|
||||
{
|
||||
GdkWin32Screen *win32_screen = GDK_WIN32_SCREEN (screen);
|
||||
|
||||
g_return_val_if_fail (screen == gdk_display_get_default_screen (gdk_display_get_default ()), 0);
|
||||
g_return_val_if_fail (num_monitor < win32_screen->num_monitors, 0);
|
||||
|
||||
return win32_screen->monitors[num_monitor].width_mm;
|
||||
}
|
||||
|
||||
static gint
|
||||
gdk_win32_screen_get_monitor_height_mm (GdkScreen *screen,
|
||||
gint num_monitor)
|
||||
{
|
||||
GdkWin32Screen *win32_screen = GDK_WIN32_SCREEN (screen);
|
||||
|
||||
g_return_val_if_fail (screen == gdk_display_get_default_screen (gdk_display_get_default ()), 0);
|
||||
g_return_val_if_fail (num_monitor < win32_screen->num_monitors, 0);
|
||||
|
||||
return win32_screen->monitors[num_monitor].height_mm;
|
||||
}
|
||||
|
||||
static gchar *
|
||||
gdk_win32_screen_get_monitor_plug_name (GdkScreen *screen,
|
||||
gint num_monitor)
|
||||
{
|
||||
GdkWin32Screen *win32_screen = GDK_WIN32_SCREEN (screen);
|
||||
|
||||
g_return_val_if_fail (screen == gdk_display_get_default_screen (gdk_display_get_default ()), NULL);
|
||||
g_return_val_if_fail (num_monitor < win32_screen->num_monitors, NULL);
|
||||
|
||||
return g_strdup (win32_screen->monitors[num_monitor].name);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_win32_screen_get_monitor_geometry (GdkScreen *screen,
|
||||
gint num_monitor,
|
||||
GdkRectangle *dest)
|
||||
{
|
||||
GdkWin32Screen *win32_screen = GDK_WIN32_SCREEN (screen);
|
||||
|
||||
g_return_if_fail (screen == gdk_display_get_default_screen (gdk_display_get_default ()));
|
||||
g_return_if_fail (num_monitor < win32_screen->num_monitors);
|
||||
|
||||
*dest = win32_screen->monitors[num_monitor].rect;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_win32_screen_get_monitor_workarea (GdkScreen *screen,
|
||||
gint num_monitor,
|
||||
GdkRectangle *dest)
|
||||
{
|
||||
GdkWin32Screen *win32_screen = GDK_WIN32_SCREEN (screen);
|
||||
|
||||
g_return_if_fail (screen == gdk_display_get_default_screen (gdk_display_get_default ()));
|
||||
g_return_if_fail (num_monitor < win32_screen->num_monitors);
|
||||
|
||||
*dest = win32_screen->monitors[num_monitor].work_rect;
|
||||
}
|
||||
|
||||
static gint
|
||||
gdk_win32_screen_get_number (GdkScreen *screen)
|
||||
{
|
||||
@ -750,13 +561,6 @@ gdk_win32_screen_list_visuals (GdkScreen *screen)
|
||||
static void
|
||||
gdk_win32_screen_finalize (GObject *object)
|
||||
{
|
||||
GdkWin32Screen *screen = GDK_WIN32_SCREEN (object);
|
||||
gint i;
|
||||
|
||||
for (i = 0; i < screen->num_monitors; i++)
|
||||
g_free (screen->monitors[i].name);
|
||||
g_free (screen->monitors);
|
||||
|
||||
G_OBJECT_CLASS (gdk_win32_screen_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
@ -775,13 +579,6 @@ gdk_win32_screen_class_init (GdkWin32ScreenClass *klass)
|
||||
screen_class->get_height_mm = gdk_win32_screen_get_height_mm;
|
||||
screen_class->get_number = gdk_win32_screen_get_number;
|
||||
screen_class->get_root_window = gdk_win32_screen_get_root_window;
|
||||
screen_class->get_n_monitors = gdk_win32_screen_get_n_monitors;
|
||||
screen_class->get_primary_monitor = gdk_win32_screen_get_primary_monitor;
|
||||
screen_class->get_monitor_width_mm = gdk_win32_screen_get_monitor_width_mm;
|
||||
screen_class->get_monitor_height_mm = gdk_win32_screen_get_monitor_height_mm;
|
||||
screen_class->get_monitor_plug_name = gdk_win32_screen_get_monitor_plug_name;
|
||||
screen_class->get_monitor_geometry = gdk_win32_screen_get_monitor_geometry;
|
||||
screen_class->get_monitor_workarea = gdk_win32_screen_get_monitor_workarea;
|
||||
screen_class->is_composited = gdk_win32_screen_is_composited;
|
||||
screen_class->make_display_name = gdk_win32_screen_make_display_name;
|
||||
screen_class->get_active_window = gdk_win32_screen_get_active_window;
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include <gdk/win32/gdkwin32screen.h>
|
||||
#include <gdk/win32/gdkwin32window.h>
|
||||
#include <gdk/win32/gdkwin32misc.h>
|
||||
#include <gdk/win32/gdkwin32monitor.h>
|
||||
#include <gdk/win32/gdkwin32glcontext.h>
|
||||
|
||||
#undef __GDKWIN32_H_INSIDE__
|
||||
|
50
gdk/win32/gdkwin32monitor.h
Normal file
50
gdk/win32/gdkwin32monitor.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* gdkwin32monitor.h
|
||||
*
|
||||
* Copyright 2016 Red Hat, Inc.
|
||||
*
|
||||
* Matthias Clasen <mclasen@redhat.com>
|
||||
* Руслан Ижбулатов <lrn1986@gmail.com>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef __GDK_WIN32_MONITOR_H__
|
||||
#define __GDK_WIN32_MONITOR_H__
|
||||
|
||||
#if !defined (__GDKWIN32_H_INSIDE__) && !defined (GDK_COMPILATION)
|
||||
#error "Only <gdk/gdkwin32.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gdk/gdkmonitor.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDK_TYPE_WIN32_MONITOR (gdk_win32_monitor_get_type ())
|
||||
#define GDK_WIN32_MONITOR(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_WIN32_MONITOR, GdkWin32Monitor))
|
||||
#define GDK_IS_WIN32_MONITOR(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_WIN32_MONITOR))
|
||||
|
||||
#ifdef GDK_COMPILATION
|
||||
typedef struct _GdkWin32Monitor GdkWin32Monitor;
|
||||
#else
|
||||
typedef GdkMonitor GdkWin32Monitor;
|
||||
#endif
|
||||
typedef struct _GdkWin32MonitorClass GdkWin32MonitorClass;
|
||||
|
||||
GDK_AVAILABLE_IN_3_22
|
||||
GType gdk_win32_monitor_get_type (void) G_GNUC_CONST;
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_WIN32_MONITOR_H__ */
|
Loading…
Reference in New Issue
Block a user