GDK W32: Ensure that we use made-up monitors when there are none

Previously GDK only made up monitors when it initially found none. Now it
also makes up monitors when it initially finds some, but later fails to get
their informatin in a normal way and finally prunes them out, being left with
zero monitors.

Having zero-length monitor array is unexpected and causes a number
of critical warnings and some critical functionality (such as displaying
drop-down menus) fails in such cases.

Ideally, there might be such a way to interrogate W32 API that produces the
information about non-real (but active) monitors out of it so that it isn't
necessary for us to make stuff up. However, this code is already complicated,
and i am not prepared to dig W32 API to find a way to do this.

This fixes the issues people had when they accessed a Windows desktop via RDP.

https://bugzilla.gnome.org/show_bug.cgi?id=777527
This commit is contained in:
Руслан Ижбулатов 2017-01-20 10:23:00 +00:00
parent f7ae36739a
commit 58ba4d6a3e

View File

@ -722,6 +722,25 @@ enum_monitor (HMONITOR hmonitor,
return TRUE;
}
static void
prune_monitors (EnumMonitorData *data)
{
gint i;
for (i = 0; i < data->monitors->len; i++)
{
GdkWin32Monitor *m;
m = g_ptr_array_index (data->monitors, i);
if (m->remove)
{
g_ptr_array_remove_index (data->monitors, i);
continue;
}
}
}
GPtrArray *
_gdk_win32_display_get_monitor_list (GdkWin32Display *win32_display)
{
@ -743,6 +762,18 @@ _gdk_win32_display_get_monitor_list (GdkWin32Display *win32_display)
EnumDisplayMonitors (NULL, NULL, enum_monitor, (LPARAM) &data);
prune_monitors (&data);
if (data.monitors->len == 0 && data.have_monitor_devices)
{
/* We thought we had monitors, but enumeration eventually failed, and
* we have none. Try again, this time making stuff up as we go.
*/
data.have_monitor_devices = FALSE;
EnumDisplayMonitors (NULL, NULL, enum_monitor, (LPARAM) &data);
prune_monitors (&data);
}
_gdk_offset_x = G_MININT;
_gdk_offset_y = G_MININT;
@ -753,12 +784,6 @@ _gdk_win32_display_get_monitor_list (GdkWin32Display *win32_display)
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);