xrandr: use "hotplug_mode_update" property

Use the "hotplug_mode_update" connector property indicating that the
screen settings should be updated: get a new preferred mode on hotplug
events to handle dynamic guest resizing (where you resize the host
window and the guest resizes with it).

https://bugzilla.gnome.org/show_bug.cgi?id=711216
This commit is contained in:
Marc-André Lureau 2013-10-31 14:37:44 +01:00
parent 21c46852cd
commit ca5d115715
4 changed files with 82 additions and 20 deletions

View File

@ -817,6 +817,22 @@ meta_monitor_config_match_current (MetaMonitorConfig *self,
return ok; return ok;
} }
gboolean
meta_monitor_manager_has_hotplug_mode_update (MetaMonitorManager *manager)
{
MetaOutput *outputs;
unsigned n_outputs;
unsigned int i;
outputs = meta_monitor_manager_get_outputs (manager, &n_outputs);
for (i = 0; i < n_outputs; i++)
if (outputs[i].hotplug_mode_update)
return TRUE;
return FALSE;
}
static MetaConfiguration * static MetaConfiguration *
meta_monitor_config_get_stored (MetaMonitorConfig *self, meta_monitor_config_get_stored (MetaMonitorConfig *self,
MetaOutput *outputs, MetaOutput *outputs,

View File

@ -116,6 +116,9 @@ struct _MetaOutput
*/ */
gboolean is_primary; gboolean is_primary;
gboolean is_presentation; gboolean is_presentation;
/* get a new preferred mode on hotplug events, to handle dynamic guest resizing */
gboolean hotplug_mode_update;
}; };
struct _MetaCRTC struct _MetaCRTC
@ -383,6 +386,7 @@ void meta_output_info_free (MetaOutputInfo *info);
void meta_monitor_manager_free_output_array (MetaOutput *old_outputs, void meta_monitor_manager_free_output_array (MetaOutput *old_outputs,
int n_old_outputs); int n_old_outputs);
gboolean meta_monitor_manager_has_hotplug_mode_update (MetaMonitorManager *manager);
/* Returns true if transform causes width and height to be inverted /* Returns true if transform causes width and height to be inverted
This is true for the odd transforms in the enum */ This is true for the odd transforms in the enum */

View File

@ -311,6 +311,29 @@ read_output_edid (MetaMonitorManagerXrandr *manager_xrandr,
return NULL; return NULL;
} }
static gboolean
output_get_hotplug_mode_update (MetaMonitorManagerXrandr *manager_xrandr,
XID output_id)
{
MetaDisplay *display = meta_get_display ();
XRRPropertyInfo *info;
gboolean result = FALSE;
meta_error_trap_push (display);
info = XRRQueryOutputProperty (manager_xrandr->xdisplay, output_id,
display->atom_hotplug_mode_update);
meta_error_trap_pop (display);
if (info)
{
result = TRUE;
XFree (info);
}
return result;
}
static void static void
meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager) meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
{ {
@ -484,6 +507,8 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
meta_output->width_mm = output->mm_width; meta_output->width_mm = output->mm_width;
meta_output->height_mm = output->mm_height; meta_output->height_mm = output->mm_height;
meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN; meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
meta_output->hotplug_mode_update =
output_get_hotplug_mode_update (manager_xrandr, meta_output->output_id);
meta_output->n_modes = output->nmode; meta_output->n_modes = output->nmode;
meta_output->modes = g_new0 (MetaMonitorMode *, meta_output->n_modes); meta_output->modes = g_new0 (MetaMonitorMode *, meta_output->n_modes);
@ -971,6 +996,16 @@ meta_monitor_manager_xrandr_set_crtc_gamma (MetaMonitorManager *manager,
XRRFreeGamma (gamma); XRRFreeGamma (gamma);
} }
static void
meta_monitor_manager_xrandr_rebuild_derived (MetaMonitorManager *manager)
{
/* This will be a no-op if the change was from our side, as
we already called it in the DBus method handler */
meta_monitor_config_update_current (manager->config, manager);
meta_monitor_manager_rebuild_derived (manager);
}
static gboolean static gboolean
meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManager *manager, meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManager *manager,
XEvent *event) XEvent *event)
@ -980,6 +1015,7 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManager *manager,
MetaCRTC *old_crtcs; MetaCRTC *old_crtcs;
MetaMonitorMode *old_modes; MetaMonitorMode *old_modes;
int n_old_outputs; int n_old_outputs;
gboolean new_config;
if ((event->type - manager_xrandr->rr_event_base) != RRScreenChangeNotify) if ((event->type - manager_xrandr->rr_event_base) != RRScreenChangeNotify)
return FALSE; return FALSE;
@ -995,6 +1031,22 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManager *manager,
manager->serial++; manager->serial++;
meta_monitor_manager_xrandr_read_current (manager); meta_monitor_manager_xrandr_read_current (manager);
new_config = manager_xrandr->resources->timestamp >=
manager_xrandr->resources->configTimestamp;
if (meta_monitor_manager_has_hotplug_mode_update (manager))
{
/* Check if the current intended configuration is a result of an
XRandR call. Otherwise, hotplug_mode_update tells us to get
a new preferred mode on hotplug events to handle dynamic
guest resizing. */
if (new_config)
meta_monitor_manager_xrandr_rebuild_derived (manager);
else
meta_monitor_config_make_default (manager->config, manager);
}
else
{
/* Check if the current intended configuration has the same outputs /* Check if the current intended configuration has the same outputs
as the new real one, or if the event is a result of an XRandR call. as the new real one, or if the event is a result of an XRandR call.
If so, we can go straight to rebuild the logical config and tell If so, we can go straight to rebuild the logical config and tell
@ -1003,23 +1055,12 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManager *manager,
MetaMonitorConfig. MetaMonitorConfig.
Note that we need to check both the timestamps and the list of Note that we need to check both the timestamps and the list of
outputs, because the X server might emit spurious events with outputs, because the X server might emit spurious events with new
new configTimestamps (bug 702804), and the driver may have configTimestamps (bug 702804), and the driver may have changed
changed the EDID for some other reason (old broken qxl and vbox the EDID for some other reason (old qxl and vbox drivers). */
drivers...). if (new_config || meta_monitor_config_match_current (manager->config, manager))
*/ meta_monitor_manager_xrandr_rebuild_derived (manager);
if (manager_xrandr->resources->timestamp >= manager_xrandr->resources->configTimestamp || else if (!meta_monitor_config_apply_stored (manager->config, manager))
meta_monitor_config_match_current (manager->config, manager))
{
/* This will be a no-op if the change was from our side, as
we already called it in the DBus method handler */
meta_monitor_config_update_current (manager->config, manager);
meta_monitor_manager_rebuild_derived (manager);
}
else
{
if (!meta_monitor_config_apply_stored (manager->config, manager))
meta_monitor_config_make_default (manager->config, manager); meta_monitor_config_make_default (manager->config, manager);
} }

View File

@ -81,6 +81,7 @@ item(TIMESTAMP)
item(VERSION) item(VERSION)
item(ATOM_PAIR) item(ATOM_PAIR)
item(BACKLIGHT) item(BACKLIGHT)
item(hotplug_mode_update)
/* Oddities: These are used, and we need atoms for them, /* Oddities: These are used, and we need atoms for them,
* but when we need all _NET_WM hints (i.e. when we're making * but when we need all _NET_WM hints (i.e. when we're making