mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice-gtk
synced 2026-01-24 17:01:52 +00:00
gtk: import display configuration from gnome-desktop
This commit is contained in:
parent
07a3d7b2cd
commit
a2ad8d1bed
20
configure.ac
20
configure.ac
@ -166,7 +166,7 @@ if test "x$with_sasl" != "xno"; then
|
||||
SASL_LIBS="$SASL_LIBS -lsasl"
|
||||
else
|
||||
AC_MSG_ERROR([You must install the Cyrus SASL development package in order to compile GTK-VNC])
|
||||
fi
|
||||
fi
|
||||
CFLAGS="$old_cflags"
|
||||
LIBS="$old_libs"
|
||||
if test "x$with_sasl2" = "xyes" -o "x$with_sasl" = "xyes" ; then
|
||||
@ -211,6 +211,24 @@ PKG_CHECK_MODULES(GTK, gtk+-$GTK_API_VERSION >= $GTK_REQUIRED)
|
||||
AC_SUBST(GTK_CFLAGS)
|
||||
AC_SUBST(GTK_LIBS)
|
||||
|
||||
PKG_CHECK_MODULES(XRANDR, x11 xrandr)
|
||||
AC_SUBST(XRANDR_CFLAGS)
|
||||
AC_SUBST(XRANDR_LIBS)
|
||||
AC_DEFINE(HAVE_RANDR, 1, [Define if the xrandr library is present])
|
||||
AC_ARG_WITH(pnp-ids-path,
|
||||
[AC_HELP_STRING([--with-pnp-ids-path],
|
||||
[Specify the path to pnp.ids @<:@default=(internal)@:>@])],,
|
||||
[with_pnp_ids_path="\${pnpdatadir}/pnp.ids"])
|
||||
|
||||
AM_CONDITIONAL(USE_INTERNAL_PNP_IDS, test "x$with_pnp_ids_path" = "x\${pnpdatadir}/pnp.ids")
|
||||
PNP_IDS=$with_pnp_ids_path
|
||||
AC_SUBST(PNP_IDS)
|
||||
if test "x$with_pnp_ids_path" = "x\${pnpdatadir}/pnp.ids"; then
|
||||
EXTERNAL_PNP_IDS="no (internal)"
|
||||
else
|
||||
EXTERNAL_PNP_IDS="$with_pnp_ids_path"
|
||||
fi
|
||||
|
||||
PKG_CHECK_MODULES(GLIB2, glib-2.0 >= 2.22)
|
||||
AC_SUBST(GLIB2_CFLAGS)
|
||||
AC_SUBST(GLIB2_LIBS)
|
||||
|
||||
@ -43,6 +43,7 @@ SPICE_COMMON_CPPFLAGS = \
|
||||
-DG_LOG_DOMAIN=\"GSpice\" \
|
||||
-DSW_CANVAS_CACHE \
|
||||
-DSPICE_GTK_LOCALEDIR=\"${SPICE_GTK_LOCALEDIR}\" \
|
||||
-DPNP_IDS=\""$(PNP_IDS)"\"\
|
||||
\
|
||||
-I$(COMMON_DIR) \
|
||||
-I$(CLIENT_DIR) \
|
||||
@ -253,15 +254,31 @@ libspice_client_glibinclude_HEADERS = \
|
||||
$(NULL)
|
||||
|
||||
|
||||
spicy_SOURCES = \
|
||||
spicy.c \
|
||||
spice-cmdline.h \
|
||||
spice-cmdline.c \
|
||||
spicy_SOURCES = \
|
||||
spicy.c \
|
||||
display/edid.h \
|
||||
display/edid-parse.c \
|
||||
display/display-name.c \
|
||||
display/gnome-rr-config.c \
|
||||
display/gnome-rr-config.h \
|
||||
display/gnome-rr-output-info.c \
|
||||
display/gnome-rr-output-info.h \
|
||||
display/gnome-rr-private.h \
|
||||
display/gnome-rr.c \
|
||||
display/gnome-rr.h \
|
||||
spice-cmdline.h \
|
||||
spice-cmdline.c \
|
||||
$(NULL)
|
||||
|
||||
spicy_LDADD = \
|
||||
libspice-client-gtk-$(SPICE_GTK_API_VERSION).la \
|
||||
libspice-client-glib-2.0.la \
|
||||
$(XRANDR_LIBS) \
|
||||
$(NULL)
|
||||
|
||||
spicy_CPPFLAGS = \
|
||||
$(AM_CPPFLAGS) \
|
||||
$(XRANDR_CFLAGS) \
|
||||
$(NULL)
|
||||
|
||||
|
||||
|
||||
299
gtk/display/display-name.c
Normal file
299
gtk/display/display-name.c
Normal file
@ -0,0 +1,299 @@
|
||||
/*
|
||||
* Copyright 2007 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||
* the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/* Author: Soren Sandmann <sandmann@redhat.com> */
|
||||
|
||||
#include <config.h>
|
||||
#include <glib/gi18n-lib.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <glib.h>
|
||||
#include "edid.h"
|
||||
|
||||
typedef struct Vendor Vendor;
|
||||
struct Vendor
|
||||
{
|
||||
const char vendor_id[4];
|
||||
const char vendor_name[28];
|
||||
};
|
||||
|
||||
/* This list of vendor codes derived from lshw
|
||||
*
|
||||
* http://ezix.org/project/wiki/HardwareLiSter
|
||||
*
|
||||
* Note: we now prefer to use data coming from hwdata (and shipped with
|
||||
* gnome-desktop). See
|
||||
* http://git.fedorahosted.org/git/?p=hwdata.git;a=blob_plain;f=pnp.ids;hb=HEAD
|
||||
* All contributions to the list of vendors should go there.
|
||||
*/
|
||||
static const struct Vendor vendors[] =
|
||||
{
|
||||
{ "AIC", "AG Neovo" },
|
||||
{ "ACR", "Acer" },
|
||||
{ "DEL", "DELL" },
|
||||
{ "SAM", "SAMSUNG" },
|
||||
{ "SNY", "SONY" },
|
||||
{ "SEC", "Epson" },
|
||||
{ "WAC", "Wacom" },
|
||||
{ "NEC", "NEC" },
|
||||
{ "CMO", "CMO" }, /* Chi Mei */
|
||||
{ "BNQ", "BenQ" },
|
||||
|
||||
{ "ABP", "Advansys" },
|
||||
{ "ACC", "Accton" },
|
||||
{ "ACE", "Accton" },
|
||||
{ "ADP", "Adaptec" },
|
||||
{ "ADV", "AMD" },
|
||||
{ "AIR", "AIR" },
|
||||
{ "AMI", "AMI" },
|
||||
{ "ASU", "ASUS" },
|
||||
{ "ATI", "ATI" },
|
||||
{ "ATK", "Allied Telesyn" },
|
||||
{ "AZT", "Aztech" },
|
||||
{ "BAN", "Banya" },
|
||||
{ "BRI", "Boca Research" },
|
||||
{ "BUS", "Buslogic" },
|
||||
{ "CCI", "Cache Computers Inc." },
|
||||
{ "CHA", "Chase" },
|
||||
{ "CMD", "CMD Technology, Inc." },
|
||||
{ "COG", "Cogent" },
|
||||
{ "CPQ", "Compaq" },
|
||||
{ "CRS", "Crescendo" },
|
||||
{ "CSC", "Crystal" },
|
||||
{ "CSI", "CSI" },
|
||||
{ "CTL", "Creative Labs" },
|
||||
{ "DBI", "Digi" },
|
||||
{ "DEC", "Digital Equipment" },
|
||||
{ "DBK", "Databook" },
|
||||
{ "EGL", "Eagle Technology" },
|
||||
{ "ELS", "ELSA" },
|
||||
{ "ESS", "ESS" },
|
||||
{ "FAR", "Farallon" },
|
||||
{ "FDC", "Future Domain" },
|
||||
{ "HWP", "Hewlett-Packard" },
|
||||
{ "IBM", "IBM" },
|
||||
{ "INT", "Intel" },
|
||||
{ "ISA", "Iomega" },
|
||||
{ "LEN", "Lenovo" },
|
||||
{ "MDG", "Madge" },
|
||||
{ "MDY", "Microdyne" },
|
||||
{ "MET", "Metheus" },
|
||||
{ "MIC", "Micronics" },
|
||||
{ "MLX", "Mylex" },
|
||||
{ "NVL", "Novell" },
|
||||
{ "OLC", "Olicom" },
|
||||
{ "PRO", "Proteon" },
|
||||
{ "RII", "Racal" },
|
||||
{ "RTL", "Realtek" },
|
||||
{ "SCM", "SCM" },
|
||||
{ "SKD", "SysKonnect" },
|
||||
{ "SGI", "SGI" },
|
||||
{ "SMC", "SMC" },
|
||||
{ "SNI", "Siemens Nixdorf" },
|
||||
{ "STL", "Stallion Technologies" },
|
||||
{ "SUN", "Sun" },
|
||||
{ "SUP", "SupraExpress" },
|
||||
{ "SVE", "SVEC" },
|
||||
{ "TCC", "Thomas-Conrad" },
|
||||
{ "TCI", "Tulip" },
|
||||
{ "TCM", "3Com" },
|
||||
{ "TCO", "Thomas-Conrad" },
|
||||
{ "TEC", "Tecmar" },
|
||||
{ "TRU", "Truevision" },
|
||||
{ "TOS", "Toshiba" },
|
||||
{ "TYN", "Tyan" },
|
||||
{ "UBI", "Ungermann-Bass" },
|
||||
{ "USC", "UltraStor" },
|
||||
{ "VDM", "Vadem" },
|
||||
{ "VMI", "Vermont" },
|
||||
{ "WDC", "Western Digital" },
|
||||
{ "ZDS", "Zeos" },
|
||||
|
||||
/* From http://faydoc.tripod.com/structures/01/0136.htm */
|
||||
{ "ACT", "Targa" },
|
||||
{ "ADI", "ADI" },
|
||||
{ "AOC", "AOC Intl" },
|
||||
{ "API", "Acer America" },
|
||||
{ "APP", "Apple Computer" },
|
||||
{ "ART", "ArtMedia" },
|
||||
{ "AST", "AST Research" },
|
||||
{ "CPL", "Compal" },
|
||||
{ "CTX", "Chuntex Electronic Co." },
|
||||
{ "DPC", "Delta Electronics" },
|
||||
{ "DWE", "Daewoo" },
|
||||
{ "ECS", "ELITEGROUP" },
|
||||
{ "EIZ", "EIZO" },
|
||||
{ "FCM", "Funai" },
|
||||
{ "GSM", "LG Electronics" },
|
||||
{ "GWY", "Gateway 2000" },
|
||||
{ "HEI", "Hyundai" },
|
||||
{ "HIT", "Hitachi" },
|
||||
{ "HSL", "Hansol" },
|
||||
{ "HTC", "Hitachi" },
|
||||
{ "ICL", "Fujitsu ICL" },
|
||||
{ "IVM", "Idek Iiyama" },
|
||||
{ "KFC", "KFC Computek" },
|
||||
{ "LKM", "ADLAS" },
|
||||
{ "LNK", "LINK Tech" },
|
||||
{ "LTN", "Lite-On" },
|
||||
{ "MAG", "MAG InnoVision" },
|
||||
{ "MAX", "Maxdata" },
|
||||
{ "MEI", "Panasonic" },
|
||||
{ "MEL", "Mitsubishi" },
|
||||
{ "MIR", "miro" },
|
||||
{ "MTC", "MITAC" },
|
||||
{ "NAN", "NANAO" },
|
||||
{ "NEC", "NEC Tech" },
|
||||
{ "NOK", "Nokia" },
|
||||
{ "OQI", "OPTIQUEST" },
|
||||
{ "PBN", "Packard Bell" },
|
||||
{ "PGS", "Princeton" },
|
||||
{ "PHL", "Philips" },
|
||||
{ "REL", "Relisys" },
|
||||
{ "SDI", "Samtron" },
|
||||
{ "SMI", "Smile" },
|
||||
{ "SPT", "Sceptre" },
|
||||
{ "SRC", "Shamrock Technology" },
|
||||
{ "STP", "Sceptre" },
|
||||
{ "TAT", "Tatung" },
|
||||
{ "TRL", "Royal Information Company" },
|
||||
{ "TSB", "Toshiba, Inc." },
|
||||
{ "UNM", "Unisys" },
|
||||
{ "VSC", "ViewSonic" },
|
||||
{ "WTC", "Wen Tech" },
|
||||
{ "ZCM", "Zenith Data Systems" },
|
||||
|
||||
{ "???", "Unknown" },
|
||||
};
|
||||
|
||||
static GHashTable *pnp_ids = NULL;
|
||||
|
||||
static void
|
||||
read_pnp_ids (void)
|
||||
{
|
||||
gchar *contents;
|
||||
gchar **lines;
|
||||
gchar *line;
|
||||
gchar *code, *name;
|
||||
gint i;
|
||||
|
||||
if (pnp_ids)
|
||||
return;
|
||||
|
||||
pnp_ids = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
||||
|
||||
if (g_file_get_contents (PNP_IDS, &contents, NULL, NULL))
|
||||
{
|
||||
lines = g_strsplit (contents, "\n", -1);
|
||||
for (i = 0; lines[i]; i++)
|
||||
{
|
||||
line = lines[i];
|
||||
if (line[0] && line[1] && line[2] && line[3] == '\t' && line[4])
|
||||
{
|
||||
code = line;
|
||||
line[3] = '\0';
|
||||
name = line + 4;
|
||||
g_hash_table_insert (pnp_ids, code, name);
|
||||
}
|
||||
}
|
||||
g_free (lines);
|
||||
g_free (contents);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const char *
|
||||
find_vendor (const char *code)
|
||||
{
|
||||
const char *vendor_name;
|
||||
int i;
|
||||
|
||||
read_pnp_ids ();
|
||||
|
||||
vendor_name = g_hash_table_lookup (pnp_ids, code);
|
||||
|
||||
if (vendor_name)
|
||||
return vendor_name;
|
||||
|
||||
for (i = 0; i < sizeof (vendors) / sizeof (vendors[0]); ++i)
|
||||
{
|
||||
const Vendor *v = &(vendors[i]);
|
||||
|
||||
if (strcmp (v->vendor_id, code) == 0)
|
||||
return v->vendor_name;
|
||||
}
|
||||
|
||||
return code;
|
||||
};
|
||||
|
||||
char *
|
||||
make_display_name (const MonitorInfo *info)
|
||||
{
|
||||
const char *vendor;
|
||||
int width_mm, height_mm, inches;
|
||||
|
||||
if (info)
|
||||
{
|
||||
vendor = find_vendor (info->manufacturer_code);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Translators: "Unknown" here is used to identify a monitor for which
|
||||
* we don't know the vendor. When a vendor is known, the name of the
|
||||
* vendor is used. */
|
||||
vendor = C_("Monitor vendor", "Unknown");
|
||||
}
|
||||
|
||||
if (info && info->width_mm != -1 && info->height_mm)
|
||||
{
|
||||
width_mm = info->width_mm;
|
||||
height_mm = info->height_mm;
|
||||
}
|
||||
else if (info && info->n_detailed_timings)
|
||||
{
|
||||
width_mm = info->detailed_timings[0].width_mm;
|
||||
height_mm = info->detailed_timings[0].height_mm;
|
||||
}
|
||||
else
|
||||
{
|
||||
width_mm = -1;
|
||||
height_mm = -1;
|
||||
}
|
||||
|
||||
if (width_mm != -1 && height_mm != -1)
|
||||
{
|
||||
double d = sqrt (width_mm * width_mm + height_mm * height_mm);
|
||||
|
||||
inches = (int)(d / 25.4 + 0.5);
|
||||
}
|
||||
else
|
||||
{
|
||||
inches = -1;
|
||||
}
|
||||
|
||||
if (inches > 0)
|
||||
return g_strdup_printf ("%s %d\"", vendor, inches);
|
||||
else
|
||||
return g_strdup (vendor);
|
||||
}
|
||||
540
gtk/display/edid-parse.c
Normal file
540
gtk/display/edid-parse.c
Normal file
@ -0,0 +1,540 @@
|
||||
/*
|
||||
* Copyright 2007 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||
* the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/* Author: Soren Sandmann <sandmann@redhat.com> */
|
||||
|
||||
#include "edid.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <glib.h>
|
||||
|
||||
static int
|
||||
get_bit (int in, int bit)
|
||||
{
|
||||
return (in & (1 << bit)) >> bit;
|
||||
}
|
||||
|
||||
static int
|
||||
get_bits (int in, int begin, int end)
|
||||
{
|
||||
int mask = (1 << (end - begin + 1)) - 1;
|
||||
|
||||
return (in >> begin) & mask;
|
||||
}
|
||||
|
||||
static int
|
||||
decode_header (const uchar *edid)
|
||||
{
|
||||
if (memcmp (edid, "\x00\xff\xff\xff\xff\xff\xff\x00", 8) == 0)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static int
|
||||
decode_vendor_and_product_identification (const uchar *edid, MonitorInfo *info)
|
||||
{
|
||||
int is_model_year;
|
||||
|
||||
/* Manufacturer Code */
|
||||
info->manufacturer_code[0] = get_bits (edid[0x08], 2, 6);
|
||||
info->manufacturer_code[1] = get_bits (edid[0x08], 0, 1) << 3;
|
||||
info->manufacturer_code[1] |= get_bits (edid[0x09], 5, 7);
|
||||
info->manufacturer_code[2] = get_bits (edid[0x09], 0, 4);
|
||||
info->manufacturer_code[3] = '\0';
|
||||
|
||||
info->manufacturer_code[0] += 'A' - 1;
|
||||
info->manufacturer_code[1] += 'A' - 1;
|
||||
info->manufacturer_code[2] += 'A' - 1;
|
||||
|
||||
/* Product Code */
|
||||
info->product_code = edid[0x0b] << 8 | edid[0x0a];
|
||||
|
||||
/* Serial Number */
|
||||
info->serial_number =
|
||||
edid[0x0c] | edid[0x0d] << 8 | edid[0x0e] << 16 | edid[0x0f] << 24;
|
||||
|
||||
/* Week and Year */
|
||||
is_model_year = FALSE;
|
||||
switch (edid[0x10])
|
||||
{
|
||||
case 0x00:
|
||||
info->production_week = -1;
|
||||
break;
|
||||
|
||||
case 0xff:
|
||||
info->production_week = -1;
|
||||
is_model_year = TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
info->production_week = edid[0x10];
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_model_year)
|
||||
{
|
||||
info->production_year = -1;
|
||||
info->model_year = 1990 + edid[0x11];
|
||||
}
|
||||
else
|
||||
{
|
||||
info->production_year = 1990 + edid[0x11];
|
||||
info->model_year = -1;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int
|
||||
decode_edid_version (const uchar *edid, MonitorInfo *info)
|
||||
{
|
||||
info->major_version = edid[0x12];
|
||||
info->minor_version = edid[0x13];
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int
|
||||
decode_display_parameters (const uchar *edid, MonitorInfo *info)
|
||||
{
|
||||
/* Digital vs Analog */
|
||||
info->is_digital = get_bit (edid[0x14], 7);
|
||||
|
||||
if (info->is_digital)
|
||||
{
|
||||
int bits;
|
||||
|
||||
static const int bit_depth[8] =
|
||||
{
|
||||
-1, 6, 8, 10, 12, 14, 16, -1
|
||||
};
|
||||
|
||||
static const Interface interfaces[6] =
|
||||
{
|
||||
UNDEFINED, DVI, HDMI_A, HDMI_B, MDDI, DISPLAY_PORT
|
||||
};
|
||||
|
||||
bits = get_bits (edid[0x14], 4, 6);
|
||||
info->connector.digital.bits_per_primary = bit_depth[bits];
|
||||
|
||||
bits = get_bits (edid[0x14], 0, 3);
|
||||
|
||||
if (bits <= 5)
|
||||
info->connector.digital.interface = interfaces[bits];
|
||||
else
|
||||
info->connector.digital.interface = UNDEFINED;
|
||||
}
|
||||
else
|
||||
{
|
||||
int bits = get_bits (edid[0x14], 5, 6);
|
||||
|
||||
static const double levels[][3] =
|
||||
{
|
||||
{ 0.7, 0.3, 1.0 },
|
||||
{ 0.714, 0.286, 1.0 },
|
||||
{ 1.0, 0.4, 1.4 },
|
||||
{ 0.7, 0.0, 0.7 },
|
||||
};
|
||||
|
||||
info->connector.analog.video_signal_level = levels[bits][0];
|
||||
info->connector.analog.sync_signal_level = levels[bits][1];
|
||||
info->connector.analog.total_signal_level = levels[bits][2];
|
||||
|
||||
info->connector.analog.blank_to_black = get_bit (edid[0x14], 4);
|
||||
|
||||
info->connector.analog.separate_hv_sync = get_bit (edid[0x14], 3);
|
||||
info->connector.analog.composite_sync_on_h = get_bit (edid[0x14], 2);
|
||||
info->connector.analog.composite_sync_on_green = get_bit (edid[0x14], 1);
|
||||
|
||||
info->connector.analog.serration_on_vsync = get_bit (edid[0x14], 0);
|
||||
}
|
||||
|
||||
/* Screen Size / Aspect Ratio */
|
||||
if (edid[0x15] == 0 && edid[0x16] == 0)
|
||||
{
|
||||
info->width_mm = -1;
|
||||
info->height_mm = -1;
|
||||
info->aspect_ratio = -1.0;
|
||||
}
|
||||
else if (edid[0x16] == 0)
|
||||
{
|
||||
info->width_mm = -1;
|
||||
info->height_mm = -1;
|
||||
info->aspect_ratio = 100.0 / (edid[0x15] + 99);
|
||||
}
|
||||
else if (edid[0x15] == 0)
|
||||
{
|
||||
info->width_mm = -1;
|
||||
info->height_mm = -1;
|
||||
info->aspect_ratio = 100.0 / (edid[0x16] + 99);
|
||||
info->aspect_ratio = 1/info->aspect_ratio; /* portrait */
|
||||
}
|
||||
else
|
||||
{
|
||||
info->width_mm = 10 * edid[0x15];
|
||||
info->height_mm = 10 * edid[0x16];
|
||||
}
|
||||
|
||||
/* Gamma */
|
||||
if (edid[0x17] == 0xFF)
|
||||
info->gamma = -1.0;
|
||||
else
|
||||
info->gamma = (edid[0x17] + 100.0) / 100.0;
|
||||
|
||||
/* Features */
|
||||
info->standby = get_bit (edid[0x18], 7);
|
||||
info->suspend = get_bit (edid[0x18], 6);
|
||||
info->active_off = get_bit (edid[0x18], 5);
|
||||
|
||||
if (info->is_digital)
|
||||
{
|
||||
info->connector.digital.rgb444 = TRUE;
|
||||
if (get_bit (edid[0x18], 3))
|
||||
info->connector.digital.ycrcb444 = 1;
|
||||
if (get_bit (edid[0x18], 4))
|
||||
info->connector.digital.ycrcb422 = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
int bits = get_bits (edid[0x18], 3, 4);
|
||||
ColorType color_type[4] =
|
||||
{
|
||||
MONOCHROME, RGB, OTHER_COLOR, UNDEFINED_COLOR
|
||||
};
|
||||
|
||||
info->connector.analog.color_type = color_type[bits];
|
||||
}
|
||||
|
||||
info->srgb_is_standard = get_bit (edid[0x18], 2);
|
||||
|
||||
/* In 1.3 this is called "has preferred timing" */
|
||||
info->preferred_timing_includes_native = get_bit (edid[0x18], 1);
|
||||
|
||||
/* FIXME: In 1.3 this indicates whether the monitor accepts GTF */
|
||||
info->continuous_frequency = get_bit (edid[0x18], 0);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static double
|
||||
decode_fraction (int high, int low)
|
||||
{
|
||||
double result = 0.0;
|
||||
int i;
|
||||
|
||||
high = (high << 2) | low;
|
||||
|
||||
for (i = 0; i < 10; ++i)
|
||||
result += get_bit (high, i) * pow (2, i - 10);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int
|
||||
decode_color_characteristics (const uchar *edid, MonitorInfo *info)
|
||||
{
|
||||
info->red_x = decode_fraction (edid[0x1b], get_bits (edid[0x19], 6, 7));
|
||||
info->red_y = decode_fraction (edid[0x1c], get_bits (edid[0x19], 5, 4));
|
||||
info->green_x = decode_fraction (edid[0x1d], get_bits (edid[0x19], 2, 3));
|
||||
info->green_y = decode_fraction (edid[0x1e], get_bits (edid[0x19], 0, 1));
|
||||
info->blue_x = decode_fraction (edid[0x1f], get_bits (edid[0x1a], 6, 7));
|
||||
info->blue_y = decode_fraction (edid[0x20], get_bits (edid[0x1a], 4, 5));
|
||||
info->white_x = decode_fraction (edid[0x21], get_bits (edid[0x1a], 2, 3));
|
||||
info->white_y = decode_fraction (edid[0x22], get_bits (edid[0x1a], 0, 1));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int
|
||||
decode_established_timings (const uchar *edid, MonitorInfo *info)
|
||||
{
|
||||
static const Timing established[][8] =
|
||||
{
|
||||
{
|
||||
{ 800, 600, 60 },
|
||||
{ 800, 600, 56 },
|
||||
{ 640, 480, 75 },
|
||||
{ 640, 480, 72 },
|
||||
{ 640, 480, 67 },
|
||||
{ 640, 480, 60 },
|
||||
{ 720, 400, 88 },
|
||||
{ 720, 400, 70 }
|
||||
},
|
||||
{
|
||||
{ 1280, 1024, 75 },
|
||||
{ 1024, 768, 75 },
|
||||
{ 1024, 768, 70 },
|
||||
{ 1024, 768, 60 },
|
||||
{ 1024, 768, 87 },
|
||||
{ 832, 624, 75 },
|
||||
{ 800, 600, 75 },
|
||||
{ 800, 600, 72 }
|
||||
},
|
||||
{
|
||||
{ 0, 0, 0 },
|
||||
{ 0, 0, 0 },
|
||||
{ 0, 0, 0 },
|
||||
{ 0, 0, 0 },
|
||||
{ 0, 0, 0 },
|
||||
{ 0, 0, 0 },
|
||||
{ 0, 0, 0 },
|
||||
{ 1152, 870, 75 }
|
||||
},
|
||||
};
|
||||
|
||||
int i, j, idx;
|
||||
|
||||
idx = 0;
|
||||
for (i = 0; i < 3; ++i)
|
||||
{
|
||||
for (j = 0; j < 8; ++j)
|
||||
{
|
||||
int byte = edid[0x23 + i];
|
||||
|
||||
if (get_bit (byte, j) && established[i][j].frequency != 0)
|
||||
info->established[idx++] = established[i][j];
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int
|
||||
decode_standard_timings (const uchar *edid, MonitorInfo *info)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
int first = edid[0x26 + 2 * i];
|
||||
int second = edid[0x27 + 2 * i];
|
||||
|
||||
if (first != 0x01 && second != 0x01)
|
||||
{
|
||||
int w = 8 * (first + 31);
|
||||
int h = 0;
|
||||
|
||||
switch (get_bits (second, 6, 7))
|
||||
{
|
||||
case 0x00: h = (w / 16) * 10; break;
|
||||
case 0x01: h = (w / 4) * 3; break;
|
||||
case 0x02: h = (w / 5) * 4; break;
|
||||
case 0x03: h = (w / 16) * 9; break;
|
||||
}
|
||||
|
||||
info->standard[i].width = w;
|
||||
info->standard[i].height = h;
|
||||
info->standard[i].frequency = get_bits (second, 0, 5) + 60;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
decode_lf_string (const uchar *s, int n_chars, char *result)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < n_chars; ++i)
|
||||
{
|
||||
if (s[i] == 0x0a)
|
||||
{
|
||||
*result++ = '\0';
|
||||
break;
|
||||
}
|
||||
else if (s[i] == 0x00)
|
||||
{
|
||||
/* Convert embedded 0's to spaces */
|
||||
*result++ = ' ';
|
||||
}
|
||||
else
|
||||
{
|
||||
*result++ = s[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
decode_display_descriptor (const uchar *desc,
|
||||
MonitorInfo *info)
|
||||
{
|
||||
switch (desc[0x03])
|
||||
{
|
||||
case 0xFC:
|
||||
decode_lf_string (desc + 5, 13, info->dsc_product_name);
|
||||
break;
|
||||
case 0xFF:
|
||||
decode_lf_string (desc + 5, 13, info->dsc_serial_number);
|
||||
break;
|
||||
case 0xFE:
|
||||
decode_lf_string (desc + 5, 13, info->dsc_string);
|
||||
break;
|
||||
case 0xFD:
|
||||
/* Range Limits */
|
||||
break;
|
||||
case 0xFB:
|
||||
/* Color Point */
|
||||
break;
|
||||
case 0xFA:
|
||||
/* Timing Identifications */
|
||||
break;
|
||||
case 0xF9:
|
||||
/* Color Management */
|
||||
break;
|
||||
case 0xF8:
|
||||
/* Timing Codes */
|
||||
break;
|
||||
case 0xF7:
|
||||
/* Established Timings */
|
||||
break;
|
||||
case 0x10:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
decode_detailed_timing (const uchar *timing,
|
||||
DetailedTiming *detailed)
|
||||
{
|
||||
int bits;
|
||||
StereoType stereo[] =
|
||||
{
|
||||
NO_STEREO, NO_STEREO, FIELD_RIGHT, FIELD_LEFT,
|
||||
TWO_WAY_RIGHT_ON_EVEN, TWO_WAY_LEFT_ON_EVEN,
|
||||
FOUR_WAY_INTERLEAVED, SIDE_BY_SIDE
|
||||
};
|
||||
|
||||
detailed->pixel_clock = (timing[0x00] | timing[0x01] << 8) * 10000;
|
||||
detailed->h_addr = timing[0x02] | ((timing[0x04] & 0xf0) << 4);
|
||||
detailed->h_blank = timing[0x03] | ((timing[0x04] & 0x0f) << 8);
|
||||
detailed->v_addr = timing[0x05] | ((timing[0x07] & 0xf0) << 4);
|
||||
detailed->v_blank = timing[0x06] | ((timing[0x07] & 0x0f) << 8);
|
||||
detailed->h_front_porch = timing[0x08] | get_bits (timing[0x0b], 6, 7) << 8;
|
||||
detailed->h_sync = timing[0x09] | get_bits (timing[0x0b], 4, 5) << 8;
|
||||
detailed->v_front_porch =
|
||||
get_bits (timing[0x0a], 4, 7) | get_bits (timing[0x0b], 2, 3) << 4;
|
||||
detailed->v_sync =
|
||||
get_bits (timing[0x0a], 0, 3) | get_bits (timing[0x0b], 0, 1) << 4;
|
||||
detailed->width_mm = timing[0x0c] | get_bits (timing[0x0e], 4, 7) << 8;
|
||||
detailed->height_mm = timing[0x0d] | get_bits (timing[0x0e], 0, 3) << 8;
|
||||
detailed->right_border = timing[0x0f];
|
||||
detailed->top_border = timing[0x10];
|
||||
|
||||
detailed->interlaced = get_bit (timing[0x11], 7);
|
||||
|
||||
/* Stereo */
|
||||
bits = get_bits (timing[0x11], 5, 6) << 1 | get_bit (timing[0x11], 0);
|
||||
detailed->stereo = stereo[bits];
|
||||
|
||||
/* Sync */
|
||||
bits = timing[0x11];
|
||||
|
||||
detailed->digital_sync = get_bit (bits, 4);
|
||||
if (detailed->digital_sync)
|
||||
{
|
||||
detailed->connector.digital.composite = !get_bit (bits, 3);
|
||||
|
||||
if (detailed->connector.digital.composite)
|
||||
{
|
||||
detailed->connector.digital.serrations = get_bit (bits, 2);
|
||||
detailed->connector.digital.negative_vsync = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
detailed->connector.digital.serrations = FALSE;
|
||||
detailed->connector.digital.negative_vsync = !get_bit (bits, 2);
|
||||
}
|
||||
|
||||
detailed->connector.digital.negative_hsync = !get_bit (bits, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
detailed->connector.analog.bipolar = get_bit (bits, 3);
|
||||
detailed->connector.analog.serrations = get_bit (bits, 2);
|
||||
detailed->connector.analog.sync_on_green = !get_bit (bits, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
decode_descriptors (const uchar *edid, MonitorInfo *info)
|
||||
{
|
||||
int i;
|
||||
int timing_idx;
|
||||
|
||||
timing_idx = 0;
|
||||
|
||||
for (i = 0; i < 4; ++i)
|
||||
{
|
||||
int index = 0x36 + i * 18;
|
||||
|
||||
if (edid[index + 0] == 0x00 && edid[index + 1] == 0x00)
|
||||
{
|
||||
decode_display_descriptor (edid + index, info);
|
||||
}
|
||||
else
|
||||
{
|
||||
decode_detailed_timing (
|
||||
edid + index, &(info->detailed_timings[timing_idx++]));
|
||||
}
|
||||
}
|
||||
|
||||
info->n_detailed_timings = timing_idx;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
decode_check_sum (const uchar *edid,
|
||||
MonitorInfo *info)
|
||||
{
|
||||
int i;
|
||||
uchar check = 0;
|
||||
|
||||
for (i = 0; i < 128; ++i)
|
||||
check += edid[i];
|
||||
|
||||
info->checksum = check;
|
||||
}
|
||||
|
||||
MonitorInfo *
|
||||
decode_edid (const uchar *edid)
|
||||
{
|
||||
MonitorInfo *info = g_new0 (MonitorInfo, 1);
|
||||
|
||||
decode_check_sum (edid, info);
|
||||
|
||||
if (decode_header (edid)
|
||||
&& decode_vendor_and_product_identification (edid, info)
|
||||
&& decode_edid_version (edid, info)
|
||||
&& decode_display_parameters (edid, info)
|
||||
&& decode_color_characteristics (edid, info)
|
||||
&& decode_established_timings (edid, info)
|
||||
&& decode_standard_timings (edid, info)
|
||||
&& decode_descriptors (edid, info))
|
||||
{
|
||||
return info;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_free (info);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
194
gtk/display/edid.h
Normal file
194
gtk/display/edid.h
Normal file
@ -0,0 +1,194 @@
|
||||
/* edid.h
|
||||
*
|
||||
* Copyright 2007, 2008, Red Hat, Inc.
|
||||
*
|
||||
* This file is part of the Gnome Library.
|
||||
*
|
||||
* The Gnome Library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* The Gnome Library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with the Gnome Library; see the file COPYING.LIB. If not,
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* Author: Soren Sandmann <sandmann@redhat.com>
|
||||
*/
|
||||
|
||||
#ifndef EDID_H
|
||||
#define EDID_H
|
||||
|
||||
typedef unsigned char uchar;
|
||||
typedef struct MonitorInfo MonitorInfo;
|
||||
typedef struct Timing Timing;
|
||||
typedef struct DetailedTiming DetailedTiming;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
UNDEFINED,
|
||||
DVI,
|
||||
HDMI_A,
|
||||
HDMI_B,
|
||||
MDDI,
|
||||
DISPLAY_PORT
|
||||
} Interface;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
UNDEFINED_COLOR,
|
||||
MONOCHROME,
|
||||
RGB,
|
||||
OTHER_COLOR
|
||||
} ColorType;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
NO_STEREO,
|
||||
FIELD_RIGHT,
|
||||
FIELD_LEFT,
|
||||
TWO_WAY_RIGHT_ON_EVEN,
|
||||
TWO_WAY_LEFT_ON_EVEN,
|
||||
FOUR_WAY_INTERLEAVED,
|
||||
SIDE_BY_SIDE
|
||||
} StereoType;
|
||||
|
||||
struct Timing
|
||||
{
|
||||
int width;
|
||||
int height;
|
||||
int frequency;
|
||||
};
|
||||
|
||||
struct DetailedTiming
|
||||
{
|
||||
int pixel_clock;
|
||||
int h_addr;
|
||||
int h_blank;
|
||||
int h_sync;
|
||||
int h_front_porch;
|
||||
int v_addr;
|
||||
int v_blank;
|
||||
int v_sync;
|
||||
int v_front_porch;
|
||||
int width_mm;
|
||||
int height_mm;
|
||||
int right_border;
|
||||
int top_border;
|
||||
int interlaced;
|
||||
StereoType stereo;
|
||||
|
||||
int digital_sync;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
int bipolar;
|
||||
int serrations;
|
||||
int sync_on_green;
|
||||
} analog;
|
||||
|
||||
struct
|
||||
{
|
||||
int composite;
|
||||
int serrations;
|
||||
int negative_vsync;
|
||||
int negative_hsync;
|
||||
} digital;
|
||||
} connector;
|
||||
};
|
||||
|
||||
struct MonitorInfo
|
||||
{
|
||||
int checksum;
|
||||
char manufacturer_code[4];
|
||||
int product_code;
|
||||
unsigned int serial_number;
|
||||
|
||||
int production_week; /* -1 if not specified */
|
||||
int production_year; /* -1 if not specified */
|
||||
int model_year; /* -1 if not specified */
|
||||
|
||||
int major_version;
|
||||
int minor_version;
|
||||
|
||||
int is_digital;
|
||||
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
int bits_per_primary;
|
||||
Interface interface;
|
||||
int rgb444;
|
||||
int ycrcb444;
|
||||
int ycrcb422;
|
||||
} digital;
|
||||
|
||||
struct
|
||||
{
|
||||
double video_signal_level;
|
||||
double sync_signal_level;
|
||||
double total_signal_level;
|
||||
|
||||
int blank_to_black;
|
||||
|
||||
int separate_hv_sync;
|
||||
int composite_sync_on_h;
|
||||
int composite_sync_on_green;
|
||||
int serration_on_vsync;
|
||||
ColorType color_type;
|
||||
} analog;
|
||||
} connector;
|
||||
|
||||
int width_mm; /* -1 if not specified */
|
||||
int height_mm; /* -1 if not specified */
|
||||
double aspect_ratio; /* -1.0 if not specififed */
|
||||
|
||||
double gamma; /* -1.0 if not specified */
|
||||
|
||||
int standby;
|
||||
int suspend;
|
||||
int active_off;
|
||||
|
||||
int srgb_is_standard;
|
||||
int preferred_timing_includes_native;
|
||||
int continuous_frequency;
|
||||
|
||||
double red_x;
|
||||
double red_y;
|
||||
double green_x;
|
||||
double green_y;
|
||||
double blue_x;
|
||||
double blue_y;
|
||||
double white_x;
|
||||
double white_y;
|
||||
|
||||
Timing established[24]; /* Terminated by 0x0x0 */
|
||||
Timing standard[8];
|
||||
|
||||
int n_detailed_timings;
|
||||
DetailedTiming detailed_timings[4]; /* If monitor has a preferred
|
||||
* mode, it is the first one
|
||||
* (whether it has, is
|
||||
* determined by the
|
||||
* preferred_timing_includes
|
||||
* bit.
|
||||
*/
|
||||
|
||||
/* Optional product description */
|
||||
char dsc_serial_number[14];
|
||||
char dsc_product_name[14];
|
||||
char dsc_string[14]; /* Unspecified ASCII data */
|
||||
};
|
||||
|
||||
MonitorInfo *decode_edid (const uchar *data);
|
||||
char *make_display_name (const MonitorInfo *info);
|
||||
|
||||
#endif
|
||||
1982
gtk/display/gnome-rr-config.c
Normal file
1982
gtk/display/gnome-rr-config.c
Normal file
File diff suppressed because it is too large
Load Diff
150
gtk/display/gnome-rr-config.h
Normal file
150
gtk/display/gnome-rr-config.h
Normal file
@ -0,0 +1,150 @@
|
||||
/* gnome-rr-config.h
|
||||
* -*- c-basic-offset: 4 -*-
|
||||
*
|
||||
* Copyright 2007, 2008, Red Hat, Inc.
|
||||
* Copyright 2010 Giovanni Campagna
|
||||
*
|
||||
* This file is part of the Gnome Library.
|
||||
*
|
||||
* The Gnome Library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* The Gnome Library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with the Gnome Library; see the file COPYING.LIB. If not,
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* Author: Soren Sandmann <sandmann@redhat.com>
|
||||
*/
|
||||
#ifndef GNOME_RR_CONFIG_H
|
||||
#define GNOME_RR_CONFIG_H
|
||||
|
||||
#ifndef GNOME_DESKTOP_USE_UNSTABLE_API
|
||||
#error gnome-rr-config.h is unstable API. You must define GNOME_DESKTOP_USE_UNSTABLE_API before including gnome-rr-config.h
|
||||
#endif
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
#include "gnome-rr.h"
|
||||
|
||||
typedef struct GnomeRROutputInfoPrivate GnomeRROutputInfoPrivate;
|
||||
typedef struct GnomeRRConfigPrivate GnomeRRConfigPrivate;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GObject parent;
|
||||
|
||||
/*< private >*/
|
||||
GnomeRROutputInfoPrivate *priv;
|
||||
} GnomeRROutputInfo;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
} GnomeRROutputInfoClass;
|
||||
|
||||
#define GNOME_TYPE_RR_OUTPUT_INFO (gnome_rr_output_info_get_type())
|
||||
#define GNOME_RR_OUTPUT_INFO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GNOME_TYPE_RR_OUTPUT_INFO, GnomeRROutputInfo))
|
||||
#define GNOME_IS_RR_OUTPUT_INFO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GNOME_TYPE_RR_OUTPUT_INFO))
|
||||
#define GNOME_RR_OUTPUT_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GNOME_TYPE_RR_OUTPUT_INFO, GnomeRROutputInfoClass))
|
||||
#define GNOME_IS_RR_OUTPUT_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GNOME_TYPE_RR_OUTPUT_INFO))
|
||||
#define GNOME_RR_OUTPUT_INFO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GNOME_TYPE_RR_OUTPUT_INFO, GnomeRROutputInfoClass))
|
||||
|
||||
GType gnome_rr_output_info_get_type (void);
|
||||
|
||||
char *gnome_rr_output_info_get_name (GnomeRROutputInfo *self);
|
||||
|
||||
gboolean gnome_rr_output_info_is_active (GnomeRROutputInfo *self);
|
||||
void gnome_rr_output_info_set_active (GnomeRROutputInfo *self, gboolean active);
|
||||
|
||||
void gnome_rr_output_info_get_geometry (GnomeRROutputInfo *self, int *x, int *y, int *width, int *height);
|
||||
void gnome_rr_output_info_set_geometry (GnomeRROutputInfo *self, int x, int y, int width, int height);
|
||||
|
||||
int gnome_rr_output_info_get_refresh_rate (GnomeRROutputInfo *self);
|
||||
void gnome_rr_output_info_set_refresh_rate (GnomeRROutputInfo *self, int rate);
|
||||
|
||||
GnomeRRRotation gnome_rr_output_info_get_rotation (GnomeRROutputInfo *self);
|
||||
void gnome_rr_output_info_set_rotation (GnomeRROutputInfo *self, GnomeRRRotation rotation);
|
||||
|
||||
gboolean gnome_rr_output_info_is_connected (GnomeRROutputInfo *self);
|
||||
void gnome_rr_output_info_get_vendor (GnomeRROutputInfo *self, gchar* vendor);
|
||||
guint gnome_rr_output_info_get_product (GnomeRROutputInfo *self);
|
||||
guint gnome_rr_output_info_get_serial (GnomeRROutputInfo *self);
|
||||
double gnome_rr_output_info_get_aspect_ratio (GnomeRROutputInfo *self);
|
||||
char *gnome_rr_output_info_get_display_name (GnomeRROutputInfo *self);
|
||||
|
||||
gboolean gnome_rr_output_info_get_primary (GnomeRROutputInfo *self);
|
||||
void gnome_rr_output_info_set_primary (GnomeRROutputInfo *self, gboolean primary);
|
||||
|
||||
int gnome_rr_output_info_get_preferred_width (GnomeRROutputInfo *self);
|
||||
int gnome_rr_output_info_get_preferred_height (GnomeRROutputInfo *self);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GObject parent;
|
||||
|
||||
/*< private >*/
|
||||
GnomeRRConfigPrivate *priv;
|
||||
} GnomeRRConfig;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
} GnomeRRConfigClass;
|
||||
|
||||
#define GNOME_TYPE_RR_CONFIG (gnome_rr_config_get_type())
|
||||
#define GNOME_RR_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GNOME_TYPE_RR_CONFIG, GnomeRRConfig))
|
||||
#define GNOME_IS_RR_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GNOME_TYPE_RR_CONFIG))
|
||||
#define GNOME_RR_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GNOME_TYPE_RR_CONFIG, GnomeRRConfigClass))
|
||||
#define GNOME_IS_RR_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GNOME_TYPE_RR_CONFIG))
|
||||
#define GNOME_RR_CONFIG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GNOME_TYPE_RR_CONFIG, GnomeRRConfigClass))
|
||||
|
||||
GType gnome_rr_config_get_type (void);
|
||||
|
||||
GnomeRRConfig *gnome_rr_config_new_current (GnomeRRScreen *screen,
|
||||
GError **error);
|
||||
GnomeRRConfig *gnome_rr_config_new_stored (GnomeRRScreen *screen,
|
||||
GError **error);
|
||||
gboolean gnome_rr_config_load_current (GnomeRRConfig *self,
|
||||
GError **error);
|
||||
gboolean gnome_rr_config_load_filename (GnomeRRConfig *self,
|
||||
const gchar *filename,
|
||||
GError **error);
|
||||
gboolean gnome_rr_config_match (GnomeRRConfig *config1,
|
||||
GnomeRRConfig *config2);
|
||||
gboolean gnome_rr_config_equal (GnomeRRConfig *config1,
|
||||
GnomeRRConfig *config2);
|
||||
gboolean gnome_rr_config_save (GnomeRRConfig *configuration,
|
||||
GError **error);
|
||||
void gnome_rr_config_sanitize (GnomeRRConfig *configuration);
|
||||
gboolean gnome_rr_config_ensure_primary (GnomeRRConfig *configuration);
|
||||
|
||||
gboolean gnome_rr_config_apply_with_time (GnomeRRConfig *configuration,
|
||||
GnomeRRScreen *screen,
|
||||
guint32 timestamp,
|
||||
GError **error);
|
||||
|
||||
gboolean gnome_rr_config_apply_from_filename_with_time (GnomeRRScreen *screen,
|
||||
const char *filename,
|
||||
guint32 timestamp,
|
||||
GError **error);
|
||||
|
||||
gboolean gnome_rr_config_applicable (GnomeRRConfig *configuration,
|
||||
GnomeRRScreen *screen,
|
||||
GError **error);
|
||||
|
||||
gboolean gnome_rr_config_get_clone (GnomeRRConfig *configuration);
|
||||
void gnome_rr_config_set_clone (GnomeRRConfig *configuration, gboolean clone);
|
||||
GnomeRROutputInfo **gnome_rr_config_get_outputs (GnomeRRConfig *configuration);
|
||||
|
||||
char *gnome_rr_config_get_backup_filename (void);
|
||||
char *gnome_rr_config_get_intended_filename (void);
|
||||
|
||||
#endif
|
||||
246
gtk/display/gnome-rr-output-info.c
Normal file
246
gtk/display/gnome-rr-output-info.c
Normal file
@ -0,0 +1,246 @@
|
||||
/* gnome-rr-output-info.c
|
||||
* -*- c-basic-offset: 4 -*-
|
||||
*
|
||||
* Copyright 2010 Giovanni Campagna
|
||||
*
|
||||
* This file is part of the Gnome Desktop Library.
|
||||
*
|
||||
* The Gnome Desktop Library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* The Gnome Library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with the Gnome Desktop Library; see the file COPYING.LIB. If not,
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#define GNOME_DESKTOP_USE_UNSTABLE_API
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "gnome-rr-config.h"
|
||||
|
||||
#include "edid.h"
|
||||
#include "gnome-rr-private.h"
|
||||
|
||||
G_DEFINE_TYPE (GnomeRROutputInfo, gnome_rr_output_info, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
gnome_rr_output_info_init (GnomeRROutputInfo *self)
|
||||
{
|
||||
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GNOME_TYPE_RR_OUTPUT_INFO, GnomeRROutputInfoPrivate);
|
||||
|
||||
self->priv->name = NULL;
|
||||
self->priv->on = FALSE;
|
||||
self->priv->display_name = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gnome_rr_output_info_finalize (GObject *gobject)
|
||||
{
|
||||
GnomeRROutputInfo *self = GNOME_RR_OUTPUT_INFO (gobject);
|
||||
|
||||
g_free (self->priv->name);
|
||||
g_free (self->priv->display_name);
|
||||
|
||||
G_OBJECT_CLASS (gnome_rr_output_info_parent_class)->finalize (gobject);
|
||||
}
|
||||
|
||||
static void
|
||||
gnome_rr_output_info_class_init (GnomeRROutputInfoClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
g_type_class_add_private (klass, sizeof (GnomeRROutputInfoPrivate));
|
||||
|
||||
gobject_class->finalize = gnome_rr_output_info_finalize;
|
||||
}
|
||||
|
||||
/**
|
||||
* gnome_rr_output_info_get_name:
|
||||
*
|
||||
* Returns: (transfer none): the output name
|
||||
*/
|
||||
char *gnome_rr_output_info_get_name (GnomeRROutputInfo *self)
|
||||
{
|
||||
g_return_val_if_fail (GNOME_IS_RR_OUTPUT_INFO (self), NULL);
|
||||
|
||||
return self->priv->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* gnome_rr_output_info_is_active:
|
||||
*
|
||||
* Returns: whether there is a CRTC assigned to this output (i.e. a signal is being sent to it)
|
||||
*/
|
||||
gboolean gnome_rr_output_info_is_active (GnomeRROutputInfo *self)
|
||||
{
|
||||
g_return_val_if_fail (GNOME_IS_RR_OUTPUT_INFO (self), FALSE);
|
||||
|
||||
return self->priv->on;
|
||||
}
|
||||
|
||||
void gnome_rr_output_info_set_active (GnomeRROutputInfo *self, gboolean active)
|
||||
{
|
||||
g_return_if_fail (GNOME_IS_RR_OUTPUT_INFO (self));
|
||||
|
||||
self->priv->on = active;
|
||||
}
|
||||
|
||||
/**
|
||||
* gnome_rr_output_info_get_geometry:
|
||||
*
|
||||
* @self: a #GnomeRROutputInfo
|
||||
* @x: (out) (allow-none):
|
||||
* @y: (out) (allow-none):
|
||||
* @width: (out) (allow-none):
|
||||
* @height: (out) (allow-none):
|
||||
*/
|
||||
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 (x)
|
||||
*x = self->priv->x;
|
||||
if (y)
|
||||
*y = self->priv->y;
|
||||
if (width)
|
||||
*width = self->priv->width;
|
||||
if (height)
|
||||
*height = self->priv->height;
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
self->priv->x = x;
|
||||
self->priv->y = y;
|
||||
self->priv->width = width;
|
||||
self->priv->height = height;
|
||||
}
|
||||
|
||||
int gnome_rr_output_info_get_refresh_rate (GnomeRROutputInfo *self)
|
||||
{
|
||||
g_return_val_if_fail (GNOME_IS_RR_OUTPUT_INFO (self), 0);
|
||||
|
||||
return self->priv->rate;
|
||||
}
|
||||
|
||||
void gnome_rr_output_info_set_refresh_rate (GnomeRROutputInfo *self, int rate)
|
||||
{
|
||||
g_return_if_fail (GNOME_IS_RR_OUTPUT_INFO (self));
|
||||
|
||||
self->priv->rate = rate;
|
||||
}
|
||||
|
||||
GnomeRRRotation gnome_rr_output_info_get_rotation (GnomeRROutputInfo *self)
|
||||
{
|
||||
g_return_val_if_fail (GNOME_IS_RR_OUTPUT_INFO (self), GNOME_RR_ROTATION_0);
|
||||
|
||||
return self->priv->rotation;
|
||||
}
|
||||
|
||||
void gnome_rr_output_info_set_rotation (GnomeRROutputInfo *self, GnomeRRRotation rotation)
|
||||
{
|
||||
g_return_if_fail (GNOME_IS_RR_OUTPUT_INFO (self));
|
||||
|
||||
self->priv->rotation = rotation;
|
||||
}
|
||||
|
||||
/**
|
||||
* gnome_rr_output_info_is_connected:
|
||||
*
|
||||
* Returns: whether the output is physically connected to a monitor
|
||||
*/
|
||||
gboolean gnome_rr_output_info_is_connected (GnomeRROutputInfo *self)
|
||||
{
|
||||
g_return_val_if_fail (GNOME_IS_RR_OUTPUT_INFO (self), FALSE);
|
||||
|
||||
return self->priv->connected;
|
||||
}
|
||||
|
||||
/**
|
||||
* gnome_rr_output_info_get_vendor:
|
||||
*
|
||||
* @self: a #GnomeRROutputInfo
|
||||
* @vendor: (out caller-allocates) (array fixed-size=4):
|
||||
*/
|
||||
void gnome_rr_output_info_get_vendor (GnomeRROutputInfo *self, gchar* vendor)
|
||||
{
|
||||
g_return_if_fail (GNOME_IS_RR_OUTPUT_INFO (self));
|
||||
g_return_if_fail (vendor != NULL);
|
||||
|
||||
vendor[0] = self->priv->vendor[0];
|
||||
vendor[1] = self->priv->vendor[1];
|
||||
vendor[2] = self->priv->vendor[2];
|
||||
vendor[3] = self->priv->vendor[3];
|
||||
}
|
||||
|
||||
guint gnome_rr_output_info_get_product (GnomeRROutputInfo *self)
|
||||
{
|
||||
g_return_val_if_fail (GNOME_IS_RR_OUTPUT_INFO (self), 0);
|
||||
|
||||
return self->priv->product;
|
||||
}
|
||||
|
||||
guint gnome_rr_output_info_get_serial (GnomeRROutputInfo *self)
|
||||
{
|
||||
g_return_val_if_fail (GNOME_IS_RR_OUTPUT_INFO (self), 0);
|
||||
|
||||
return self->priv->serial;
|
||||
}
|
||||
|
||||
double gnome_rr_output_info_get_aspect_ratio (GnomeRROutputInfo *self)
|
||||
{
|
||||
g_return_val_if_fail (GNOME_IS_RR_OUTPUT_INFO (self), 0);
|
||||
|
||||
return self->priv->aspect;
|
||||
}
|
||||
|
||||
/**
|
||||
* gnome_rr_output_info_get_display_name:
|
||||
*
|
||||
* Returns: (transfer none): the display name of this output
|
||||
*/
|
||||
char *gnome_rr_output_info_get_display_name (GnomeRROutputInfo *self)
|
||||
{
|
||||
g_return_val_if_fail (GNOME_IS_RR_OUTPUT_INFO (self), NULL);
|
||||
|
||||
return self->priv->display_name;
|
||||
}
|
||||
|
||||
gboolean gnome_rr_output_info_get_primary (GnomeRROutputInfo *self)
|
||||
{
|
||||
g_return_val_if_fail (GNOME_IS_RR_OUTPUT_INFO (self), FALSE);
|
||||
|
||||
return self->priv->primary;
|
||||
}
|
||||
|
||||
void gnome_rr_output_info_set_primary (GnomeRROutputInfo *self, gboolean primary)
|
||||
{
|
||||
g_return_if_fail (GNOME_IS_RR_OUTPUT_INFO (self));
|
||||
|
||||
self->priv->primary = primary;
|
||||
}
|
||||
|
||||
int gnome_rr_output_info_get_preferred_width (GnomeRROutputInfo *self)
|
||||
{
|
||||
g_return_val_if_fail (GNOME_IS_RR_OUTPUT_INFO (self), 0);
|
||||
|
||||
return self->priv->pref_width;
|
||||
}
|
||||
|
||||
int gnome_rr_output_info_get_preferred_height (GnomeRROutputInfo *self)
|
||||
{
|
||||
g_return_val_if_fail (GNOME_IS_RR_OUTPUT_INFO (self), 0);
|
||||
|
||||
return self->priv->pref_height;
|
||||
}
|
||||
80
gtk/display/gnome-rr-private.h
Normal file
80
gtk/display/gnome-rr-private.h
Normal file
@ -0,0 +1,80 @@
|
||||
#ifndef GNOME_RR_PRIVATE_H
|
||||
#define GNOME_RR_PRIVATE_H
|
||||
|
||||
#ifdef HAVE_RANDR
|
||||
#include <X11/extensions/Xrandr.h>
|
||||
#endif
|
||||
|
||||
typedef struct ScreenInfo ScreenInfo;
|
||||
|
||||
struct ScreenInfo
|
||||
{
|
||||
int min_width;
|
||||
int max_width;
|
||||
int min_height;
|
||||
int max_height;
|
||||
|
||||
#ifdef HAVE_RANDR
|
||||
XRRScreenResources *resources;
|
||||
#endif
|
||||
|
||||
GnomeRROutput ** outputs;
|
||||
GnomeRRCrtc ** crtcs;
|
||||
GnomeRRMode ** modes;
|
||||
|
||||
GnomeRRScreen * screen;
|
||||
|
||||
GnomeRRMode ** clone_modes;
|
||||
|
||||
#ifdef HAVE_RANDR
|
||||
RROutput primary;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct GnomeRRScreenPrivate
|
||||
{
|
||||
GdkScreen * gdk_screen;
|
||||
GdkWindow * gdk_root;
|
||||
Display * xdisplay;
|
||||
Screen * xscreen;
|
||||
Window xroot;
|
||||
ScreenInfo * info;
|
||||
|
||||
int randr_event_base;
|
||||
int rr_major_version;
|
||||
int rr_minor_version;
|
||||
|
||||
Atom connector_type_atom;
|
||||
};
|
||||
|
||||
struct GnomeRROutputInfoPrivate
|
||||
{
|
||||
char * name;
|
||||
|
||||
gboolean on;
|
||||
int width;
|
||||
int height;
|
||||
int rate;
|
||||
int x;
|
||||
int y;
|
||||
GnomeRRRotation rotation;
|
||||
|
||||
gboolean connected;
|
||||
gchar vendor[4];
|
||||
guint product;
|
||||
guint serial;
|
||||
double aspect;
|
||||
int pref_width;
|
||||
int pref_height;
|
||||
char * display_name;
|
||||
gboolean primary;
|
||||
};
|
||||
|
||||
struct GnomeRRConfigPrivate
|
||||
{
|
||||
gboolean clone;
|
||||
GnomeRRScreen *screen;
|
||||
GnomeRROutputInfo **outputs;
|
||||
};
|
||||
|
||||
#endif
|
||||
2121
gtk/display/gnome-rr.c
Normal file
2121
gtk/display/gnome-rr.c
Normal file
File diff suppressed because it is too large
Load Diff
202
gtk/display/gnome-rr.h
Normal file
202
gtk/display/gnome-rr.h
Normal file
@ -0,0 +1,202 @@
|
||||
/* gnome-rr.h
|
||||
*
|
||||
* Copyright 2007, 2008, Red Hat, Inc.
|
||||
*
|
||||
* This file is part of the Gnome Library.
|
||||
*
|
||||
* The Gnome Library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* The Gnome Library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with the Gnome Library; see the file COPYING.LIB. If not,
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* Author: Soren Sandmann <sandmann@redhat.com>
|
||||
*/
|
||||
#ifndef GNOME_RR_H
|
||||
#define GNOME_RR_H
|
||||
|
||||
#ifndef GNOME_DESKTOP_USE_UNSTABLE_API
|
||||
#error GnomeRR is unstable API. You must define GNOME_DESKTOP_USE_UNSTABLE_API before including gnomerr.h
|
||||
#endif
|
||||
|
||||
#include <glib.h>
|
||||
#include <gdk/gdk.h>
|
||||
|
||||
typedef struct GnomeRRScreenPrivate GnomeRRScreenPrivate;
|
||||
typedef struct GnomeRROutput GnomeRROutput;
|
||||
typedef struct GnomeRRCrtc GnomeRRCrtc;
|
||||
typedef struct GnomeRRMode GnomeRRMode;
|
||||
|
||||
typedef struct {
|
||||
GObject parent;
|
||||
|
||||
GnomeRRScreenPrivate* priv;
|
||||
} GnomeRRScreen;
|
||||
|
||||
typedef struct {
|
||||
GObjectClass parent_class;
|
||||
|
||||
void (* changed) (void);
|
||||
} GnomeRRScreenClass;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GNOME_RR_ROTATION_0 = (1 << 0),
|
||||
GNOME_RR_ROTATION_90 = (1 << 1),
|
||||
GNOME_RR_ROTATION_180 = (1 << 2),
|
||||
GNOME_RR_ROTATION_270 = (1 << 3),
|
||||
GNOME_RR_REFLECT_X = (1 << 4),
|
||||
GNOME_RR_REFLECT_Y = (1 << 5)
|
||||
} GnomeRRRotation;
|
||||
|
||||
/* Error codes */
|
||||
|
||||
#define GNOME_RR_ERROR (gnome_rr_error_quark ())
|
||||
|
||||
GQuark gnome_rr_error_quark (void);
|
||||
|
||||
typedef enum {
|
||||
GNOME_RR_ERROR_UNKNOWN, /* generic "fail" */
|
||||
GNOME_RR_ERROR_NO_RANDR_EXTENSION, /* RANDR extension is not present */
|
||||
GNOME_RR_ERROR_RANDR_ERROR, /* generic/undescribed error from the underlying XRR API */
|
||||
GNOME_RR_ERROR_BOUNDS_ERROR, /* requested bounds of a CRTC are outside the maximum size */
|
||||
GNOME_RR_ERROR_CRTC_ASSIGNMENT, /* could not assign CRTCs to outputs */
|
||||
GNOME_RR_ERROR_NO_MATCHING_CONFIG, /* none of the saved configurations matched the current configuration */
|
||||
} GnomeRRError;
|
||||
|
||||
#define GNOME_RR_CONNECTOR_TYPE_PANEL "Panel" /* This is a laptop's built-in LCD */
|
||||
|
||||
#define GNOME_TYPE_RR_SCREEN (gnome_rr_screen_get_type())
|
||||
#define GNOME_RR_SCREEN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GNOME_TYPE_RR_SCREEN, GnomeRRScreen))
|
||||
#define GNOME_IS_RR_SCREEN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GNOME_TYPE_RR_SCREEN))
|
||||
#define GNOME_RR_SCREEN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GNOME_TYPE_RR_SCREEN, GnomeRRScreenClass))
|
||||
#define GNOME_IS_RR_SCREEN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GNOME_TYPE_RR_SCREEN))
|
||||
#define GNOME_RR_SCREEN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GNOME_TYPE_RR_SCREEN, GnomeRRScreenClass))
|
||||
|
||||
#define GNOME_TYPE_RR_OUTPUT (gnome_rr_output_get_type())
|
||||
#define GNOME_TYPE_RR_CRTC (gnome_rr_crtc_get_type())
|
||||
#define GNOME_TYPE_RR_MODE (gnome_rr_mode_get_type())
|
||||
|
||||
GType gnome_rr_screen_get_type (void);
|
||||
GType gnome_rr_output_get_type (void);
|
||||
GType gnome_rr_crtc_get_type (void);
|
||||
GType gnome_rr_mode_get_type (void);
|
||||
|
||||
/* GnomeRRScreen */
|
||||
GnomeRRScreen * gnome_rr_screen_new (GdkScreen *screen,
|
||||
GError **error);
|
||||
GnomeRROutput **gnome_rr_screen_list_outputs (GnomeRRScreen *screen);
|
||||
GnomeRRCrtc ** gnome_rr_screen_list_crtcs (GnomeRRScreen *screen);
|
||||
GnomeRRMode ** gnome_rr_screen_list_modes (GnomeRRScreen *screen);
|
||||
GnomeRRMode ** gnome_rr_screen_list_clone_modes (GnomeRRScreen *screen);
|
||||
void gnome_rr_screen_set_size (GnomeRRScreen *screen,
|
||||
int width,
|
||||
int height,
|
||||
int mm_width,
|
||||
int mm_height);
|
||||
GnomeRRCrtc * gnome_rr_screen_get_crtc_by_id (GnomeRRScreen *screen,
|
||||
guint32 id);
|
||||
gboolean gnome_rr_screen_refresh (GnomeRRScreen *screen,
|
||||
GError **error);
|
||||
GnomeRROutput * gnome_rr_screen_get_output_by_id (GnomeRRScreen *screen,
|
||||
guint32 id);
|
||||
GnomeRROutput * gnome_rr_screen_get_output_by_name (GnomeRRScreen *screen,
|
||||
const char *name);
|
||||
void gnome_rr_screen_get_ranges (GnomeRRScreen *screen,
|
||||
int *min_width,
|
||||
int *max_width,
|
||||
int *min_height,
|
||||
int *max_height);
|
||||
void gnome_rr_screen_get_timestamps (GnomeRRScreen *screen,
|
||||
guint32 *change_timestamp_ret,
|
||||
guint32 *config_timestamp_ret);
|
||||
|
||||
void gnome_rr_screen_set_primary_output (GnomeRRScreen *screen,
|
||||
GnomeRROutput *output);
|
||||
|
||||
GnomeRRMode **gnome_rr_screen_create_clone_modes (GnomeRRScreen *screen);
|
||||
|
||||
/* GnomeRROutput */
|
||||
guint32 gnome_rr_output_get_id (GnomeRROutput *output);
|
||||
const char * gnome_rr_output_get_name (GnomeRROutput *output);
|
||||
gboolean gnome_rr_output_is_connected (GnomeRROutput *output);
|
||||
int gnome_rr_output_get_size_inches (GnomeRROutput *output);
|
||||
int gnome_rr_output_get_width_mm (GnomeRROutput *outout);
|
||||
int gnome_rr_output_get_height_mm (GnomeRROutput *output);
|
||||
const guint8 * gnome_rr_output_get_edid_data (GnomeRROutput *output);
|
||||
GnomeRRCrtc ** gnome_rr_output_get_possible_crtcs (GnomeRROutput *output);
|
||||
GnomeRRMode * gnome_rr_output_get_current_mode (GnomeRROutput *output);
|
||||
GnomeRRCrtc * gnome_rr_output_get_crtc (GnomeRROutput *output);
|
||||
const char * gnome_rr_output_get_connector_type (GnomeRROutput *output);
|
||||
gboolean gnome_rr_output_is_laptop (GnomeRROutput *output);
|
||||
void gnome_rr_output_get_position (GnomeRROutput *output,
|
||||
int *x,
|
||||
int *y);
|
||||
gboolean gnome_rr_output_can_clone (GnomeRROutput *output,
|
||||
GnomeRROutput *clone);
|
||||
GnomeRRMode ** gnome_rr_output_list_modes (GnomeRROutput *output);
|
||||
GnomeRRMode * gnome_rr_output_get_preferred_mode (GnomeRROutput *output);
|
||||
gboolean gnome_rr_output_supports_mode (GnomeRROutput *output,
|
||||
GnomeRRMode *mode);
|
||||
gboolean gnome_rr_output_get_is_primary (GnomeRROutput *output);
|
||||
|
||||
/* GnomeRRMode */
|
||||
guint32 gnome_rr_mode_get_id (GnomeRRMode *mode);
|
||||
guint gnome_rr_mode_get_width (GnomeRRMode *mode);
|
||||
guint gnome_rr_mode_get_height (GnomeRRMode *mode);
|
||||
int gnome_rr_mode_get_freq (GnomeRRMode *mode);
|
||||
|
||||
/* GnomeRRCrtc */
|
||||
guint32 gnome_rr_crtc_get_id (GnomeRRCrtc *crtc);
|
||||
|
||||
#ifndef GNOME_DISABLE_DEPRECATED
|
||||
gboolean gnome_rr_crtc_set_config (GnomeRRCrtc *crtc,
|
||||
int x,
|
||||
int y,
|
||||
GnomeRRMode *mode,
|
||||
GnomeRRRotation rotation,
|
||||
GnomeRROutput **outputs,
|
||||
int n_outputs,
|
||||
GError **error);
|
||||
#endif
|
||||
|
||||
gboolean gnome_rr_crtc_set_config_with_time (GnomeRRCrtc *crtc,
|
||||
guint32 timestamp,
|
||||
int x,
|
||||
int y,
|
||||
GnomeRRMode *mode,
|
||||
GnomeRRRotation rotation,
|
||||
GnomeRROutput **outputs,
|
||||
int n_outputs,
|
||||
GError **error);
|
||||
gboolean gnome_rr_crtc_can_drive_output (GnomeRRCrtc *crtc,
|
||||
GnomeRROutput *output);
|
||||
GnomeRRMode * gnome_rr_crtc_get_current_mode (GnomeRRCrtc *crtc);
|
||||
void gnome_rr_crtc_get_position (GnomeRRCrtc *crtc,
|
||||
int *x,
|
||||
int *y);
|
||||
GnomeRRRotation gnome_rr_crtc_get_current_rotation (GnomeRRCrtc *crtc);
|
||||
GnomeRRRotation gnome_rr_crtc_get_rotations (GnomeRRCrtc *crtc);
|
||||
gboolean gnome_rr_crtc_supports_rotation (GnomeRRCrtc *crtc,
|
||||
GnomeRRRotation rotation);
|
||||
|
||||
gboolean gnome_rr_crtc_get_gamma (GnomeRRCrtc *crtc,
|
||||
int *size,
|
||||
unsigned short **red,
|
||||
unsigned short **green,
|
||||
unsigned short **blue);
|
||||
void gnome_rr_crtc_set_gamma (GnomeRRCrtc *crtc,
|
||||
int size,
|
||||
unsigned short *red,
|
||||
unsigned short *green,
|
||||
unsigned short *blue);
|
||||
#endif /* GNOME_RR_H */
|
||||
77
gtk/spicy.c
77
gtk/spicy.c
@ -22,11 +22,18 @@
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#define GNOME_DESKTOP_USE_UNSTABLE_API 2
|
||||
#include "display/gnome-rr.h"
|
||||
#include "display/gnome-rr-config.h"
|
||||
|
||||
#include "spice-widget.h"
|
||||
#include "spice-audio.h"
|
||||
#include "spice-common.h"
|
||||
#include "spice-cmdline.h"
|
||||
|
||||
#include "spice-cmdline.h"
|
||||
|
||||
/* config */
|
||||
static gboolean fullscreen = false;
|
||||
static gboolean version = false;
|
||||
@ -52,6 +59,7 @@ struct spice_window {
|
||||
GtkUIManager *ui;
|
||||
bool fullscreen;
|
||||
bool mouse_grabbed;
|
||||
SpiceChannel *channel;
|
||||
};
|
||||
|
||||
struct spice_connection {
|
||||
@ -67,6 +75,8 @@ struct spice_connection {
|
||||
static GMainLoop *mainloop;
|
||||
static int connections;
|
||||
static GKeyFile *keyfile;
|
||||
static GnomeRRScreen *rrscreen;
|
||||
static GnomeRRConfig *rrsaved;
|
||||
|
||||
static spice_connection *connection_new(void);
|
||||
static void connection_connect(spice_connection *conn);
|
||||
@ -369,7 +379,6 @@ static gboolean window_state_cb(GtkWidget *widget, GdkEventWindowState *event,
|
||||
gpointer data)
|
||||
{
|
||||
struct spice_window *win = data;
|
||||
|
||||
if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
|
||||
win->fullscreen = event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN;
|
||||
if (win->fullscreen) {
|
||||
@ -618,7 +627,38 @@ static void recent_item_activated_cb(GtkRecentChooser *chooser, gpointer data)
|
||||
connection_connect(conn);
|
||||
}
|
||||
|
||||
static spice_window *create_spice_window(spice_connection *conn, int id)
|
||||
static void resolution_change(struct spice_window *win)
|
||||
{
|
||||
}
|
||||
|
||||
static void resolution_restore(struct spice_window *win)
|
||||
{
|
||||
}
|
||||
|
||||
static gboolean configure_event_cb(GtkWidget *widget,
|
||||
GdkEventConfigure *event,
|
||||
gpointer data)
|
||||
{
|
||||
gboolean resize_guest;
|
||||
struct spice_window *win = data;
|
||||
guint w, h;
|
||||
|
||||
g_object_get(win->spice, "resize-guest", &resize_guest, NULL);
|
||||
if (resize_guest)
|
||||
return FALSE;
|
||||
|
||||
g_object_get(win->channel, "width", &w, "height", &h, NULL);
|
||||
g_message("test: %d %d win %d %d %d", w, h, event->width, event->height, win->fullscreen);
|
||||
if (win->fullscreen) {
|
||||
resolution_change(win);
|
||||
} else {
|
||||
resolution_restore(win);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static spice_window *create_spice_window(spice_connection *conn, int id, SpiceChannel *channel)
|
||||
{
|
||||
char title[32];
|
||||
struct spice_window *win;
|
||||
@ -636,6 +676,7 @@ static spice_window *create_spice_window(spice_connection *conn, int id)
|
||||
memset(win,0,sizeof(*win));
|
||||
win->id = id;
|
||||
win->conn = conn;
|
||||
win->channel = channel;
|
||||
g_message("create window (#%d)", win->id);
|
||||
|
||||
/* toplevel */
|
||||
@ -682,6 +723,7 @@ static spice_window *create_spice_window(spice_connection *conn, int id)
|
||||
|
||||
/* spice display */
|
||||
win->spice = GTK_WIDGET(spice_display_new(conn->session, id));
|
||||
g_signal_connect(win->spice, "configure-event", G_CALLBACK(configure_event_cb), win);
|
||||
seq = spice_grab_sequence_new_from_string("Shift+F12");
|
||||
spice_display_set_grab_keys(SPICE_DISPLAY(win->spice), seq);
|
||||
spice_grab_sequence_free(seq);
|
||||
@ -905,7 +947,7 @@ static void channel_new(SpiceSession *s, SpiceChannel *channel, gpointer data)
|
||||
if (conn->wins[id] != NULL)
|
||||
return;
|
||||
SPICE_DEBUG("new display channel (#%d)", id);
|
||||
conn->wins[id] = create_spice_window(conn, id);
|
||||
conn->wins[id] = create_spice_window(conn, id, channel);
|
||||
}
|
||||
|
||||
if (SPICE_IS_INPUTS_CHANNEL(channel)) {
|
||||
@ -1013,6 +1055,28 @@ static void connection_destroy(spice_connection *conn)
|
||||
g_main_loop_quit(mainloop);
|
||||
}
|
||||
|
||||
static void
|
||||
on_screen_changed(GnomeRRScreen *scr, gpointer data)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
rrsaved = gnome_rr_config_new_current(rrscreen, &error);
|
||||
if (!rrsaved) {
|
||||
g_warning("Can't get current display config: %s", error->message);
|
||||
goto end;
|
||||
}
|
||||
g_clear_error(&error);
|
||||
|
||||
if (!gnome_rr_config_apply_with_time(rrsaved, rrscreen,
|
||||
gtk_get_current_event_time (), &error)) {
|
||||
g_warning("Can't restore display config: %s", error->message);
|
||||
}
|
||||
g_clear_error(&error);
|
||||
|
||||
end:
|
||||
g_clear_error(&error);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
static GOptionEntry cmd_entries[] = {
|
||||
@ -1058,8 +1122,7 @@ int main(int argc, char *argv[])
|
||||
if (!g_key_file_load_from_file(keyfile, conf_file,
|
||||
G_KEY_FILE_KEEP_COMMENTS|G_KEY_FILE_KEEP_TRANSLATIONS, &error)) {
|
||||
SPICE_DEBUG("Couldn't load configuration: %s", error->message);
|
||||
g_error_free(error);
|
||||
error = NULL;
|
||||
g_clear_error(&error);
|
||||
}
|
||||
|
||||
/* parse opts */
|
||||
@ -1082,6 +1145,10 @@ int main(int argc, char *argv[])
|
||||
|
||||
g_type_init();
|
||||
mainloop = g_main_loop_new(NULL, false);
|
||||
rrscreen = gnome_rr_screen_new(gdk_screen_get_default (), &error);
|
||||
g_warn_if_fail(rrscreen != NULL);
|
||||
g_signal_connect(rrscreen, "changed", G_CALLBACK(on_screen_changed), NULL);
|
||||
on_screen_changed(rrscreen, NULL);
|
||||
|
||||
conn = connection_new();
|
||||
spice_cmdline_session_setup(conn->session);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user