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; }
static gboolean init_randr13 (GdkScreen *screen, gboolean *changed) { #ifdef HAVE_RANDR GdkDisplay *display = gdk_screen_get_display (screen); GdkX11Display *x11_display = GDK_X11_DISPLAY (display); GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen); XRRScreenResources *resources; RROutput primary_output = None; RROutput first_output = None; int i; gboolean randr12_compat = FALSE; int old_primary; if (!x11_display->have_randr13) return FALSE; resources = XRRGetScreenResourcesCurrent (x11_screen->xdisplay, x11_screen->xroot_window); if (!resources) return FALSE; for (i = 0; i < x11_display->monitors->len; i++) { GdkX11Monitor *monitor = x11_display->monitors->pdata[i]; monitor->add = FALSE; monitor->remove = TRUE; } for (i = 0; i < resources->noutput; ++i) { RROutput output = resources->outputs[i]; XRROutputInfo *output_info = XRRGetOutputInfo (x11_screen->xdisplay, resources, output); /* Non RandR1.2+ X driver have output name "default" */ randr12_compat |= !g_strcmp0 (output_info->name, "default"); if (output_info->connection == RR_Disconnected) { XRRFreeOutputInfo (output_info); continue; } if (output_info->crtc) { GdkX11Monitor *monitor; XRRCrtcInfo *crtc = XRRGetCrtcInfo (x11_screen->xdisplay, resources, output_info->crtc); char *name; GdkRectangle geometry; GdkRectangle newgeo; int j; int refresh_rate = 0; for (j = 0; j < resources->nmode; j++) { XRRModeInfo *xmode = &resources->modes[j]; if (xmode->id == crtc->mode) { refresh_rate = (1000 * xmode->dotClock) / (xmode->hTotal *xmode->vTotal); break; } } monitor = find_monitor_by_output (x11_display, output); if (monitor) monitor->remove = FALSE; else { monitor = g_object_new (gdk_x11_monitor_get_type (), "display", display, NULL); monitor->output = output; monitor->add = TRUE; g_ptr_array_add (x11_display->monitors, monitor); } gdk_monitor_get_geometry (GDK_MONITOR (monitor), &geometry); name = g_strndup (output_info->name, output_info->nameLen); newgeo.x = crtc->x / x11_screen->window_scale; newgeo.y = crtc->y / x11_screen->window_scale; newgeo.width = crtc->width / x11_screen->window_scale; newgeo.height = crtc->height / x11_screen->window_scale; if (newgeo.x != geometry.x || newgeo.y != geometry.y || newgeo.width != geometry.width || newgeo.height != geometry.height || output_info->mm_width != gdk_monitor_get_width_mm (GDK_MONITOR (monitor)) || output_info->mm_height != gdk_monitor_get_height_mm (GDK_MONITOR (monitor)) || g_strcmp0 (name, gdk_monitor_get_model (GDK_MONITOR (monitor))) != 0) *changed = TRUE; gdk_monitor_set_position (GDK_MONITOR (monitor), newgeo.x, newgeo.y); gdk_monitor_set_size (GDK_MONITOR (monitor), newgeo.width, newgeo.height); g_object_notify (G_OBJECT (monitor), "workarea"); gdk_monitor_set_physical_size (GDK_MONITOR (monitor), output_info->mm_width, output_info->mm_height); gdk_monitor_set_subpixel_layout (GDK_MONITOR (monitor), translate_subpixel_order (output_info->subpixel_order)); gdk_monitor_set_refresh_rate (GDK_MONITOR (monitor), refresh_rate); gdk_monitor_set_scale_factor (GDK_MONITOR (monitor), x11_screen->window_scale); gdk_monitor_set_model (GDK_MONITOR (monitor), name); g_free (name); XRRFreeCrtcInfo (crtc); } XRRFreeOutputInfo (output_info); } if (resources->noutput > 0) first_output = resources->outputs[0]; XRRFreeScreenResources (resources); if (randr12_compat) { for (i = 0; i < x11_display->monitors->len; i++) { GdkX11Monitor *monitor = x11_display->monitors->pdata[i]; if (monitor->remove) gdk_display_monitor_removed (display, GDK_MONITOR (monitor)); } g_ptr_array_remove_range (x11_display->monitors, 0, x11_display->monitors->len); return FALSE; } for (i = x11_display->monitors->len - 1; i >= 0; i--) { GdkX11Monitor *monitor = x11_display->monitors->pdata[i]; if (monitor->add) { gdk_display_monitor_added (display, GDK_MONITOR (monitor)); *changed = TRUE; } else if (monitor->remove) { g_object_ref (monitor); g_ptr_array_remove (x11_display->monitors, monitor); gdk_display_monitor_removed (display, GDK_MONITOR (monitor)); g_object_unref (monitor); *changed = TRUE; } } old_primary = x11_display->primary_monitor; x11_display->primary_monitor = 0; primary_output = XRRGetOutputPrimary (x11_screen->xdisplay, x11_screen->xroot_window); for (i = 0; i < x11_display->monitors->len; ++i) { GdkX11Monitor *monitor = x11_display->monitors->pdata[i]; if (monitor->output == primary_output) { x11_display->primary_monitor = i; break; } /* No RandR1.3+ available or no primary set, fall back to prefer LVDS as primary if present */ if (primary_output == None && g_ascii_strncasecmp (gdk_monitor_get_model (GDK_MONITOR (monitor)), "LVDS", 4) == 0) { x11_display->primary_monitor = i; break; } /* No primary specified and no LVDS found */ if (monitor->output == first_output) x11_display->primary_monitor = i; } if (x11_display->primary_monitor != old_primary) *changed = TRUE; return x11_display->monitors->len > 0; #endif return FALSE; }
static void init_no_multihead (GdkScreen *screen, gboolean *changed) { GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen); GdkX11Display *x11_display = GDK_X11_DISPLAY (x11_screen->display); GdkX11Monitor *monitor; GdkRectangle geometry; int i; for (i = 0; i < x11_display->monitors->len; i++) { GdkX11Monitor *monitor = x11_display->monitors->pdata[i]; monitor->add = FALSE; monitor->remove = TRUE; } monitor = find_monitor_by_output (x11_display, 0); if (monitor) monitor->remove = FALSE; else { monitor = g_object_new (gdk_x11_monitor_get_type (), "display", x11_display, NULL); monitor->output = 0; monitor->add = TRUE; g_ptr_array_add (x11_display->monitors, monitor); } gdk_monitor_get_geometry (GDK_MONITOR (monitor), &geometry); if (0 != geometry.x || 0 != geometry.y || gdk_screen_get_width (screen) != geometry.width || gdk_screen_get_height (screen) != geometry.height || gdk_screen_get_width_mm (screen) != gdk_monitor_get_width_mm (GDK_MONITOR (monitor)) || gdk_screen_get_height_mm (screen) != gdk_monitor_get_height_mm (GDK_MONITOR (monitor))) *changed = TRUE; gdk_monitor_set_position (GDK_MONITOR (monitor), 0, 0); gdk_monitor_set_size (GDK_MONITOR (monitor), gdk_screen_get_width (screen), gdk_screen_get_height (screen)); g_object_notify (G_OBJECT (monitor), "workarea"); gdk_monitor_set_physical_size (GDK_MONITOR (monitor), gdk_screen_get_height_mm (screen), gdk_screen_get_height_mm (screen)); gdk_monitor_set_scale_factor (GDK_MONITOR (monitor), x11_screen->window_scale); if (x11_display->primary_monitor != 0) *changed = TRUE; x11_display->primary_monitor = 0; for (i = x11_display->monitors->len - 1; i >= 0; i--) { GdkX11Monitor *monitor = x11_display->monitors->pdata[i]; if (monitor->add) { gdk_display_monitor_added (GDK_DISPLAY (x11_display), GDK_MONITOR (monitor)); *changed = TRUE; } else if (monitor->remove) { g_object_ref (monitor); g_ptr_array_remove (x11_display->monitors, monitor); gdk_display_monitor_removed (GDK_DISPLAY (x11_display), GDK_MONITOR (monitor)); g_object_unref (monitor); *changed = TRUE; } } }
static gboolean init_randr15 (GdkX11Screen *x11_screen, gboolean *changed) { #ifdef HAVE_RANDR15 GdkDisplay *display = GDK_SCREEN_DISPLAY (x11_screen); GdkX11Display *x11_display = GDK_X11_DISPLAY (display); XRRScreenResources *resources; RROutput primary_output = None; RROutput first_output = None; int i; XRRMonitorInfo *rr_monitors; int num_rr_monitors; int old_primary; if (!x11_display->have_randr15) return FALSE; resources = XRRGetScreenResourcesCurrent (x11_screen->xdisplay, x11_screen->xroot_window); if (!resources) return FALSE; rr_monitors = XRRGetMonitors (x11_screen->xdisplay, x11_screen->xroot_window, True, &num_rr_monitors); if (!rr_monitors) return FALSE; for (i = 0; i < x11_display->monitors->len; i++) { GdkX11Monitor *monitor = x11_display->monitors->pdata[i]; monitor->add = FALSE; monitor->remove = TRUE; } for (i = 0; i < num_rr_monitors; i++) { RROutput output = rr_monitors[i].outputs[0]; XRROutputInfo *output_info; GdkX11Monitor *monitor; GdkRectangle geometry; GdkRectangle newgeo; char *name; int refresh_rate = 0; gdk_x11_display_error_trap_push (display); output_info = XRRGetOutputInfo (x11_screen->xdisplay, resources, output); if (gdk_x11_display_error_trap_pop (display)) continue; if (output_info == NULL) continue; if (output_info->connection == RR_Disconnected) { XRRFreeOutputInfo (output_info); continue; } if (first_output == None) first_output = output; if (output_info->crtc) { XRRCrtcInfo *crtc = XRRGetCrtcInfo (x11_screen->xdisplay, resources, output_info->crtc); int j; for (j = 0; j < resources->nmode; j++) { XRRModeInfo *xmode = &resources->modes[j]; if (xmode->id == crtc->mode) { if (xmode->hTotal != 0 && xmode->vTotal != 0) refresh_rate = (1000 * xmode->dotClock) / (xmode->hTotal * xmode->vTotal); break; } } XRRFreeCrtcInfo (crtc); } monitor = find_monitor_by_output (x11_display, output); if (monitor) monitor->remove = FALSE; else { monitor = g_object_new (GDK_TYPE_X11_MONITOR, "display", display, NULL); monitor->output = output; monitor->add = TRUE; g_ptr_array_add (x11_display->monitors, monitor); } gdk_monitor_get_geometry (GDK_MONITOR (monitor), &geometry); name = g_strndup (output_info->name, output_info->nameLen); newgeo.x = rr_monitors[i].x / x11_screen->surface_scale; newgeo.y = rr_monitors[i].y / x11_screen->surface_scale; newgeo.width = rr_monitors[i].width / x11_screen->surface_scale; newgeo.height = rr_monitors[i].height / x11_screen->surface_scale; if (newgeo.x != geometry.x || newgeo.y != geometry.y || newgeo.width != geometry.width || newgeo.height != geometry.height || rr_monitors[i].mwidth != gdk_monitor_get_width_mm (GDK_MONITOR (monitor)) || rr_monitors[i].mheight != gdk_monitor_get_height_mm (GDK_MONITOR (monitor)) || g_strcmp0 (name, gdk_monitor_get_model (GDK_MONITOR (monitor)))) *changed = TRUE; gdk_monitor_set_position (GDK_MONITOR (monitor), newgeo.x, newgeo.y); gdk_monitor_set_size (GDK_MONITOR (monitor), newgeo.width, newgeo.height); g_object_notify (G_OBJECT (monitor), "workarea"); gdk_monitor_set_physical_size (GDK_MONITOR (monitor), rr_monitors[i].mwidth, rr_monitors[i].mheight); gdk_monitor_set_subpixel_layout (GDK_MONITOR (monitor), translate_subpixel_order (output_info->subpixel_order)); gdk_monitor_set_refresh_rate (GDK_MONITOR (monitor), refresh_rate); gdk_monitor_set_scale_factor (GDK_MONITOR (monitor), x11_screen->surface_scale); gdk_monitor_set_model (GDK_MONITOR (monitor), name); g_free (name); if (rr_monitors[i].primary) primary_output = monitor->output; XRRFreeOutputInfo (output_info); } XRRFreeMonitors (rr_monitors); XRRFreeScreenResources (resources); for (i = x11_display->monitors->len - 1; i >= 0; i--) { GdkX11Monitor *monitor = x11_display->monitors->pdata[i]; if (monitor->add) { gdk_display_monitor_added (display, GDK_MONITOR (monitor)); *changed = TRUE; } else if (monitor->remove) { g_object_ref (monitor); g_ptr_array_remove (x11_display->monitors, monitor); gdk_display_monitor_removed (display, GDK_MONITOR (monitor)); g_object_unref (monitor); *changed = TRUE; } } old_primary = x11_display->primary_monitor; x11_display->primary_monitor = 0; for (i = 0; i < x11_display->monitors->len; ++i) { GdkX11Monitor *monitor = x11_display->monitors->pdata[i]; if (monitor->output == primary_output) { x11_display->primary_monitor = i; break; } /* No RandR1.3+ available or no primary set, fall back to prefer LVDS as primary if present */ if (primary_output == None && g_ascii_strncasecmp (gdk_monitor_get_model (GDK_MONITOR (monitor)), "LVDS", 4) == 0) { x11_display->primary_monitor = i; break; } /* No primary specified and no LVDS found */ if (monitor->output == first_output) x11_display->primary_monitor = i; } if (x11_display->primary_monitor != old_primary) *changed = TRUE; return x11_display->monitors->len > 0; #endif return FALSE; }