diff options
Diffstat (limited to 'libgnome-desktop/gnome-rr-output-info.c')
-rw-r--r-- | libgnome-desktop/gnome-rr-output-info.c | 275 |
1 files changed, 274 insertions, 1 deletions
diff --git a/libgnome-desktop/gnome-rr-output-info.c b/libgnome-desktop/gnome-rr-output-info.c index ff8ce780..d50dfa89 100644 --- a/libgnome-desktop/gnome-rr-output-info.c +++ b/libgnome-desktop/gnome-rr-output-info.c @@ -98,6 +98,72 @@ void gnome_rr_output_info_set_active (GnomeRROutputInfo *self, gboolean active) self->priv->on = active; } +static void gnome_rr_output_info_get_tiled_geometry (GnomeRROutputInfo *self, + int *x, + int *y, + int *width, + int *height) +{ + GnomeRROutputInfo **outputs; + gboolean active; + int i; + int ht, vt; + int total_w = 0, total_h = 0; + + outputs = gnome_rr_config_get_outputs (self->priv->config); + + /* + * iterate over all the outputs from 0,0 -> h,v + * find the output for each tile, + * if it is the 0 tile, store the x/y offsets. + * if the tile is active, add the tile to the total w/h + * for the output if the tile is in the 0 row or 0 column. + */ + for (ht = 0; ht < self->priv->tile.max_horiz_tiles; ht++) + { + for (vt = 0; vt < self->priv->tile.max_vert_tiles; vt++) + { + for (i = 0; outputs[i]; i++) + { + GnomeRRTile *this_tile = &outputs[i]->priv->tile; + + if (!outputs[i]->priv->is_tiled) + continue; + + if (this_tile->group_id != self->priv->tile.group_id) + continue; + + if (this_tile->loc_horiz != ht || + this_tile->loc_vert != vt) + continue; + + if (vt == 0 && ht == 0) + { + if (x) + *x = outputs[i]->priv->x; + if (y) + *y = outputs[i]->priv->y; + } + + active = gnome_rr_output_info_is_active (outputs[i]); + if (!active) + continue; + + if (this_tile->loc_horiz == 0) + total_h += outputs[i]->priv->height; + + if (this_tile->loc_vert == 0) + total_w += outputs[i]->priv->width; + } + } + } + + if (width) + *width = total_w; + if (height) + *height = total_h; +} + /** * gnome_rr_output_info_get_geometry: * @self: a #GnomeRROutputInfo @@ -105,11 +171,20 @@ void gnome_rr_output_info_set_active (GnomeRROutputInfo *self, gboolean active) * @y: (out) (allow-none): * @width: (out) (allow-none): * @height: (out) (allow-none): + * + * Get the geometry for the monitor connected to the specified output. + * If the monitor is a tiled monitor, it returns the geometry for the complete monitor. */ void gnome_rr_output_info_get_geometry (GnomeRROutputInfo *self, int *x, int *y, int *width, int *height) { g_return_if_fail (GNOME_IS_RR_OUTPUT_INFO (self)); + if (self->priv->is_tiled) + { + gnome_rr_output_info_get_tiled_geometry (self, x, y, width, height); + return; + } + if (x) *x = self->priv->x; if (y) @@ -120,10 +195,106 @@ void gnome_rr_output_info_get_geometry (GnomeRROutputInfo *self, int *x, int *y, *height = self->priv->height; } -void gnome_rr_output_info_set_geometry (GnomeRROutputInfo *self, int x, int y, int width, int height) +static void gnome_rr_output_info_set_tiled_geometry (GnomeRROutputInfo *self, int x, int y, int width, int height) +{ + GnomeRROutputInfo **outputs; + gboolean primary_tile_only = FALSE; + int ht, vt, i; + int x_off; + + primary_tile_only = TRUE; + + if (width == self->priv->total_tiled_width && + height == self->priv->total_tiled_height) + primary_tile_only = FALSE; + + outputs = gnome_rr_config_get_outputs (self->priv->config); + /* + * iterate over all the outputs from 0,0 -> h,v + * find the output for each tile, + * if only the primary tile is being set, disable + * the non-primary tiles, and set the output up + * for tile 0 only. + * if all tiles are being set, then store the + * dimensions for this tile, and increase the offsets. + * y_off is reset per column of tiles, + * addx is incremented for the first row of tiles + * to set the correct x offset. + */ + x_off = 0; + for (ht = 0; ht < self->priv->tile.max_horiz_tiles; ht++) + { + int y_off = 0; + int addx = 0; + for (vt = 0; vt < self->priv->tile.max_vert_tiles; vt++) + { + for (i = 0; outputs[i]; i++) + { + GnomeRRTile *this_tile = &outputs[i]->priv->tile; + + if (!outputs[i]->priv->is_tiled) + continue; + + if (this_tile->group_id != self->priv->tile.group_id) + continue; + + if (this_tile->loc_horiz != ht || + this_tile->loc_vert != vt) + continue; + + /* for primary tile only configs turn off non-primary + tiles - turn them on for tiled ones */ + if (ht != 0 || vt != 0) + outputs[i]->priv->on = !primary_tile_only; + + if (primary_tile_only) + { + if (ht == 0 && vt == 0) + { + outputs[i]->priv->x = x; + outputs[i]->priv->y = y; + outputs[i]->priv->width = width; + outputs[i]->priv->height = height; + } + } + else + { + outputs[i]->priv->x = x + x_off; + outputs[i]->priv->y = y + y_off; + outputs[i]->priv->width = this_tile->width; + outputs[i]->priv->height = this_tile->height; + + y_off += this_tile->height; + if (vt == 0) + addx = this_tile->width; + } + } + } + x_off += addx; + } +} + +/** + * gnome_rr_output_info_set_geometry: + * @self: a #GnomeRROutputInfo + * @x: x offset for monitor + * @y: y offset for monitor + * @width: monitor width + * @height: monitor height + * + * Set the geometry for the monitor connected to the specified output. + * If the monitor is a tiled monitor, it sets the geometry for the complete monitor. + */ + +void gnome_rr_output_info_set_geometry (GnomeRROutputInfo *self, int x, int y, int width, int height) { g_return_if_fail (GNOME_IS_RR_OUTPUT_INFO (self)); + if (self->priv->is_tiled) + { + gnome_rr_output_info_set_tiled_geometry (self, x, y, width, height); + return; + } self->priv->x = x; self->priv->y = y; self->priv->width = width; @@ -151,10 +322,90 @@ GnomeRRRotation gnome_rr_output_info_get_rotation (GnomeRROutputInfo *self) return self->priv->rotation; } +static void gnome_rr_output_info_set_tiled_rotation (GnomeRROutputInfo *self, GnomeRRRotation rotation) +{ + GnomeRROutputInfo **outputs; + int x_off; + int base_x = 0, base_y = 0; + int ht, vt; + int i; + + outputs = gnome_rr_config_get_outputs (self->priv->config); + x_off = 0; + /* + * iterate over all the outputs from 0,0 -> h,v + * find the output for each tile, + * for all tiles set the rotation, + * for the 0 tile use the base X/Y offsets + * for non-0 tile, rotate the offsets of each + * tile so things display correctly. + */ + for (ht = 0; ht < self->priv->tile.max_horiz_tiles; ht++) + { + int y_off = 0; + int addx = 0; + for (vt = 0; vt < self->priv->tile.max_vert_tiles; vt++) + { + for (i = 0; outputs[i] != NULL; i++) + { + GnomeRRTile *this_tile = &outputs[i]->priv->tile; + int new_x, new_y; + + if (!outputs[i]->priv->is_tiled) + continue; + + if (this_tile->group_id != self->priv->tile.group_id) + continue; + + if (this_tile->loc_horiz != ht || + this_tile->loc_vert != vt) + continue; + + /* set tile rotation */ + outputs[i]->priv->rotation = rotation; + + /* for non-zero tiles - change the offsets */ + if (ht == 0 && vt == 0) + { + base_x = outputs[i]->priv->x; + base_y = outputs[i]->priv->y; + } + else + { + if ((rotation & GNOME_RR_ROTATION_90) || (rotation & GNOME_RR_ROTATION_270)) + { + new_x = base_x + y_off; + new_y = base_y + x_off; + } + else + { + new_x = base_x + x_off; + new_y = base_y + y_off; + } + outputs[i]->priv->x = new_x; + outputs[i]->priv->y = new_y; + outputs[i]->priv->width = this_tile->width; + outputs[i]->priv->height = this_tile->height; + } + + y_off += this_tile->height; + if (vt == 0) + addx = this_tile->width; + } + } + x_off += addx; + } +} + void gnome_rr_output_info_set_rotation (GnomeRROutputInfo *self, GnomeRRRotation rotation) { g_return_if_fail (GNOME_IS_RR_OUTPUT_INFO (self)); + if (self->priv->is_tiled) + { + gnome_rr_output_info_set_tiled_rotation (self, rotation); + return; + } self->priv->rotation = rotation; } @@ -266,3 +517,25 @@ void gnome_rr_output_info_set_underscanning (GnomeRROutputInfo *self, self->priv->underscanning = underscanning; } + +/** + * gnome_rr_output_info_is_primary_tile + * @self: a #GnomeRROutputInfo + * + * Returns: %TRUE if the specified output is connected to + * the primary tile of a monitor or to an untiled monitor, + * %FALSE if the output is connected to a secondary tile. + */ +gboolean gnome_rr_output_info_is_primary_tile(GnomeRROutputInfo *self) +{ + g_return_val_if_fail (GNOME_IS_RR_OUTPUT_INFO (self), FALSE); + + if (!self->priv->is_tiled) + return TRUE; + + if (self->priv->tile.loc_horiz == 0 && + self->priv->tile.loc_vert == 0) + return TRUE; + + return FALSE; +} |