[gtk+/gtk-3-20] win32: rework how to enumerate the monitors
- From: Ignacio Casal Quinteiro <icq src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/gtk-3-20] win32: rework how to enumerate the monitors
- Date: Tue, 21 Feb 2017 10:37:32 +0000 (UTC)
commit bd725d3208408fdc30977a4642caa4702283e94d
Author: Ignacio Casal Quinteiro <icq gnome org>
Date: Mon Feb 20 10:27:11 2017 +0100
win32: rework how to enumerate the monitors
It is racy to enumerate first the monitors and then reenumerate
using the previous counter since at that point we might endup
getting a new monitor and crash on the assert.
https://bugzilla.gnome.org/show_bug.cgi?id=779002
gdk/win32/gdkscreen-win32.c | 86 ++++++++++++++++++------------------------
1 files changed, 37 insertions(+), 49 deletions(-)
---
diff --git a/gdk/win32/gdkscreen-win32.c b/gdk/win32/gdkscreen-win32.c
index 2a8d101..8861f72 100644
--- a/gdk/win32/gdkscreen-win32.c
+++ b/gdk/win32/gdkscreen-win32.c
@@ -38,7 +38,7 @@ struct _GdkWin32Screen
GdkScreen parent_instance;
gint num_monitors;
- GdkWin32Monitor *monitors;
+ GdkWin32Monitor **monitors;
GdkVisual *system_visual;
GdkVisual *rgba_visual;
@@ -57,6 +57,15 @@ struct _GdkWin32ScreenClass
G_DEFINE_TYPE (GdkWin32Screen, gdk_win32_screen, GDK_TYPE_SCREEN)
+static void
+free_monitor (gpointer user_data)
+{
+ GdkWin32Monitor *monitor = (GdkWin32Monitor *)user_data;
+
+ g_free (monitor->name);
+ g_free (monitor);
+}
+
static gint
get_color_precision (gulong mask)
{
@@ -263,9 +272,9 @@ init_root_window_size (GdkWin32Screen *screen)
GdkRectangle rect;
int i;
- rect = screen->monitors[0].rect;
+ rect = screen->monitors[0]->rect;
for (i = 1; i < screen->num_monitors; i++)
- gdk_rectangle_union (&rect, &screen->monitors[i].rect, &rect);
+ gdk_rectangle_union (&rect, &screen->monitors[i]->rect, &rect);
screen->root_window->width = rect.width;
screen->root_window->height = rect.height;
@@ -309,22 +318,9 @@ init_root_window (GdkWin32Screen *screen_win32)
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;
+ GPtrArray *monitors;
} EnumMonitorData;
static BOOL CALLBACK
@@ -352,10 +348,6 @@ enum_monitor (HMONITOR hmonitor,
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);
@@ -363,6 +355,7 @@ enum_monitor (HMONITOR hmonitor,
#define MONITORINFOF_PRIMARY 1
#endif
+ monitor = g_new0 (GdkWin32Monitor, 1);
monitor->name = g_strdup (monitor_info.szDevice);
hDC = CreateDCA ("DISPLAY", monitor_info.szDevice, NULL, NULL);
monitor->width_mm = GetDeviceCaps (hDC, HORZSIZE);
@@ -377,17 +370,13 @@ enum_monitor (HMONITOR hmonitor,
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++;
+ if (monitor_info.dwFlags & MONITORINFOF_PRIMARY)
+ /* Put primary monitor at index 0, just in case somebody needs
+ * to know which one is the primary.
+ */
+ g_ptr_array_insert (data->monitors, 0, monitor);
+ else
+ g_ptr_array_add (data->monitors, monitor);
return TRUE;
}
@@ -395,27 +384,27 @@ enum_monitor (HMONITOR hmonitor,
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;
+ data.screen = screen;
+ data.monitors = g_ptr_array_new ();
- screen->monitors = g_renew (GdkWin32Monitor, screen->monitors, screen->num_monitors);
+ for (i = 0; i < screen->num_monitors; i++)
+ free_monitor (screen->monitors[i]);
- data.screen = screen;
- data.index = 0;
EnumDisplayMonitors (NULL, NULL, enum_monitor, (LPARAM) &data);
+ screen->num_monitors = data.monitors->len;
+ screen->monitors = (GdkWin32Monitor **)g_ptr_array_free (data.monitors, FALSE);
+
_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;
+ GdkRectangle *rect = &screen->monitors[i]->rect;
_gdk_offset_x = MAX (_gdk_offset_x, -rect->x);
_gdk_offset_y = MAX (_gdk_offset_y, -rect->y);
}
@@ -426,10 +415,10 @@ init_monitors (GdkWin32Screen *screen)
for (i = 0; i < screen->num_monitors; i++)
{
GdkRectangle *rect;
- rect = &screen->monitors[i].rect;
+ rect = &screen->monitors[i]->rect;
rect->x += _gdk_offset_x;
rect->y += _gdk_offset_y;
- rect = &screen->monitors[i].work_rect;
+ 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,
@@ -546,7 +535,7 @@ gdk_win32_screen_get_monitor_width_mm (GdkScreen *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;
+ return win32_screen->monitors[num_monitor]->width_mm;
}
static gint
@@ -558,7 +547,7 @@ gdk_win32_screen_get_monitor_height_mm (GdkScreen *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;
+ return win32_screen->monitors[num_monitor]->height_mm;
}
static gchar *
@@ -570,7 +559,7 @@ gdk_win32_screen_get_monitor_plug_name (GdkScreen *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);
+ return g_strdup (win32_screen->monitors[num_monitor]->name);
}
static void
@@ -583,7 +572,7 @@ gdk_win32_screen_get_monitor_geometry (GdkScreen *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;
+ *dest = win32_screen->monitors[num_monitor]->rect;
}
static void
@@ -596,7 +585,7 @@ gdk_win32_screen_get_monitor_workarea (GdkScreen *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;
+ *dest = win32_screen->monitors[num_monitor]->work_rect;
}
static gint
@@ -754,8 +743,7 @@ gdk_win32_screen_finalize (GObject *object)
gint i;
for (i = 0; i < screen->num_monitors; i++)
- g_free (screen->monitors[i].name);
- g_free (screen->monitors);
+ free_monitor (screen->monitors[i]);
G_OBJECT_CLASS (gdk_win32_screen_parent_class)->finalize (object);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]