Compare commits

...

4 Commits

Author SHA1 Message Date
David Reveman
c23c92b069 Handle scaling with RANDR transformations for Clone mode 2010-01-28 12:30:30 -06:00
David Reveman
acb0b4725f Add an (invisible for now) combo box to select scaling for a display 2010-01-28 12:08:11 -06:00
Federico Mena Quintero
6677c366a8 Set the GConf key for tablet rotation when the user clicks the checkbox
The actual call to xsetwacom(1) will be handled in gnome-settings-daemon.

Signed-off-by: Federico Mena Quintero <federico@novell.com>
2009-12-02 17:01:12 -06:00
Federico Mena Quintero
97b42a7ccf Add a checkbox to rotate a pressure-sensitive tablet as well as the monitor
For tablets, we will call xsetwacom(1) to rotate the stylus when the monitor is
rotated.  This is the corresponding option in the display capplet; it also depends
on a patch to gnome-settings-daemon to actually handle the changes.

For built-in tablets like a Tablet PC, you *want* the tablet to rotate
when you rotate the monitor.  However, this is not the case for external
tablets plugged to a desktop PC.

Signed-off-by: Federico Mena Quintero <federico@novell.com>
2009-12-02 17:00:28 -06:00
2 changed files with 304 additions and 8 deletions

View File

@@ -142,6 +142,23 @@
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label_scale">
<property name="visible">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">S_cale:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">scale_combo</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">GTK_SHRINK | GTK_FILL</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label3">
<property name="visible">True</property>
@@ -189,6 +206,18 @@
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="GtkComboBox" id="scale_combo">
<property name="visible">False</property>
</object>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<object class="GtkComboBox" id="refresh_combo">
<property name="visible">True</property>
@@ -318,6 +347,73 @@
<property name="position">6</property>
</packing>
</child>
<child>
<object class="GtkVBox" id="rotate-tablet-box">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">12</property>
<child>
<object class="GtkLabel" id="label9">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;Pressure-sensitive tablet&lt;/b&gt;</property>
<property name="use_underline">False</property>
<property name="use_markup">True</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</object>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<object class="GtkAlignment" id="alignment3">
<property name="visible">True</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xscale">1</property>
<property name="yscale">1</property>
<property name="top_padding">0</property>
<property name="bottom_padding">0</property>
<property name="left_padding">12</property>
<property name="right_padding">0</property>
<child>
<object class="GtkCheckButton" id="rotate-tablet">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">Ro_tate tablet as well as the monitor</property>
<property name="use_underline">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<property name="active">False</property>
<property name="inconsistent">False</property>
<property name="draw_indicator">True</property>
</object>
</child>
</object>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
</object>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
</object>
<packing>
<property name="position">1</property>

View File

@@ -23,6 +23,7 @@
#include <gtk/gtk.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include "scrollarea.h"
#define GNOME_DESKTOP_USE_UNSTABLE_API
#include <libgnomeui/gnome-rr.h>
@@ -51,12 +52,15 @@ struct App
GtkWidget *monitor_on_radio;
GtkWidget *monitor_off_radio;
GtkListStore *resolution_store;
GtkWidget *resolution_combo;
GtkWidget *resolution_combo;
GtkWidget *scale_combo;
GtkWidget *refresh_combo;
GtkWidget *rotation_combo;
GtkWidget *panel_checkbox;
GtkWidget *clone_checkbox;
GtkWidget *show_icon_checkbox;
GtkWidget *rotate_tablet_box;
GtkWidget *rotate_tablet_checkbox;
/* We store the event timestamp when the Apply button is clicked */
GtkWidget *apply_button;
@@ -85,6 +89,8 @@ static void monitor_on_off_toggled_cb (GtkToggleButton *toggle, gpointer data);
static void get_geometry (GnomeOutputInfo *output, int *w, int *h);
static void apply_configuration_returned_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, void *data);
#define ROTATE_TABLET_KEY "/apps/gnome_settings_daemon/xrandr/rotate_tablet_with_monitor"
static void
error_message (App *app, const char *primary_text, const char *secondary_text)
{
@@ -579,6 +585,85 @@ rebuild_resolution_combo (App *app)
}
}
static void
rebuild_scale_combo (App *app)
{
typedef struct
{
int width;
int height;
const char * name;
} ScaleInfo;
static const ScaleInfo scales[] = {
{ 0, 0, N_("None") },
/* { 800, 600, N_("800 x 600") }, */
{ 1024, 768, N_("1024 x 768") },
{ 1024, 900, N_("1024 x 900") },
/* { 1280, 1024, N_("1280 x 1024") } */
};
const char *selection;
GnomeRRTransform current;
int i;
double best = 0.1;
clear_combo (app->scale_combo);
if (!app->current_output || !app->current_output->on)
{
gtk_widget_set_sensitive (app->scale_combo, FALSE);
return;
}
g_assert (app->current_output != NULL);
gtk_widget_set_sensitive (app->scale_combo, TRUE);
current = app->current_output->transform;
selection = NULL;
for (i = 0; i < G_N_ELEMENTS (scales); ++i)
{
const ScaleInfo *info = &(scales[i]);
GnomeRRTransform transform = {
{
{ 1.0, 0.0, 0.0 },
{ 0.0, 1.0, 0.0 },
{ 0.0, 0.0, 1.0 }
}
};
double diff = 0.0;
int j, k;
if (info->width && info->height)
{
transform.transform[0][0] = (double) info->width /
app->current_output->width;
transform.transform[1][1] = (double) info->height /
app->current_output->height;
}
app->current_output->transform = transform;
add_key (app->scale_combo, info->name,
info->width, info->height, 0, -1);
for (j = 0; j < 3; j++)
for (k = 0; k < 3; k++)
diff += fabs (transform.transform[j][k] - current.transform[j][k]);
if (diff < best)
{
selection = info->name;
best = diff;
}
}
app->current_output->transform = current;
if (!(selection && combo_select (app->scale_combo, selection)))
combo_select (app->scale_combo, N_("None"));
}
static void
rebuild_gui (App *app)
{
@@ -600,6 +685,7 @@ rebuild_gui (App *app)
rebuild_current_monitor_label (app);
rebuild_on_off_radios (app);
rebuild_resolution_combo (app);
rebuild_scale_combo (app);
rebuild_rate_combo (app);
rebuild_rotation_combo (app);
@@ -782,6 +868,32 @@ realign_outputs_after_resolution_change (App *app, GnomeOutputInfo *output_that_
}
}
static void
update_scale (App *app)
{
int width;
int height;
if (!app->current_output)
return;
if (get_mode (app->scale_combo, &width, &height, NULL, NULL))
{
if (width && height)
{
app->current_output->transform.transform[0][0] = (double)
width / app->current_output->width;
app->current_output->transform.transform[1][1] = (double)
height / app->current_output->height;
}
else
{
app->current_output->transform.transform[0][0] = 1.0;
app->current_output->transform.transform[1][1] = 1.0;
}
}
}
static void
on_resolution_changed (GtkComboBox *box, gpointer data)
{
@@ -811,6 +923,17 @@ on_resolution_changed (GtkComboBox *box, gpointer data)
rebuild_rate_combo (app);
rebuild_rotation_combo (app);
rebuild_scale_combo (app);
update_scale (app);
foo_scroll_area_invalidate (FOO_SCROLL_AREA (app->area));
}
static void
on_scale_changed (GtkComboBox *box, gpointer data)
{
App *app = data;
update_scale (app);
foo_scroll_area_invalidate (FOO_SCROLL_AREA (app->area));
}
@@ -1696,7 +1819,7 @@ make_text_combo (GtkWidget *widget, int sort_column)
}
static void
compute_virtual_size_for_configuration (GnomeRRConfig *config, int *ret_width, int *ret_height)
compute_virtual_size_for_configuration (App *app, GnomeRRConfig *config, int *ret_width, int *ret_height)
{
int i;
int width, height;
@@ -1705,14 +1828,44 @@ compute_virtual_size_for_configuration (GnomeRRConfig *config, int *ret_width, i
for (i = 0; config->outputs[i] != NULL; i++)
{
GnomeOutputInfo *output;
GnomeOutputInfo *info;
GnomeRROutput *output;
output = config->outputs[i];
info = config->outputs[i];
output = gnome_rr_screen_get_output_by_name (app->screen, info->name);
if (output->on)
if (info->on && output)
{
width = MAX (width, output->x + output->width);
height = MAX (height, output->y + output->height);
GnomeRRMode **modes = gnome_rr_output_list_modes (output);
int j;
for (j = 0; modes[j] != NULL; ++j)
{
GnomeRRMode *mode = modes[i];
int width, height;
width = gnome_rr_mode_get_width (mode);
height = gnome_rr_mode_get_height (mode);
if (width == info->width && height == info->height)
{
int x, y, w, h;
int x1, y1, x2, y2;
gnome_rr_mode_get_geometry (mode,
info->rotation,
&info->transform,
&x1, &y1, &x2, &y2);
x = info->x + x1;
y = info->y + y1;
w = x2 - x1;
h = y2 - y1;
width = MAX (width, x + w);
height = MAX (height, y + h);
}
}
}
}
@@ -1727,7 +1880,7 @@ check_required_virtual_size (App *app)
int min_width, max_width;
int min_height, max_height;
compute_virtual_size_for_configuration (app->current_configuration, &req_width, &req_height);
compute_virtual_size_for_configuration (app, app->current_configuration, &req_width, &req_height);
gnome_rr_screen_get_ranges (app->screen, &min_width, &max_width, &min_height, &max_height);
@@ -2116,6 +2269,42 @@ apply_button_clicked_cb (GtkButton *button, gpointer data)
app->apply_button_clicked_timestamp = gtk_get_current_event_time ();
}
static void
rotate_tablet_toggled_cb (GtkToggleButton *button, gpointer data)
{
App *app = data;
gconf_client_set_bool (app->client, ROTATE_TABLET_KEY, gtk_toggle_button_get_active (app->rotate_tablet_checkbox), NULL);
}
static gboolean
tablet_is_present (void)
{
char *path;
/* This heuristic *SUCKS*, but it will have to do for now */
path = g_find_program_in_path ("xsetwacom");
if (path) {
g_free (path);
return TRUE;
} else
return FALSE;
}
/* Make sure to call this function *before* connecting to app->rotate_tablet_checkbox's "toggled" signal */
static void
set_rotate_tablet_widgets (App *app)
{
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (app->rotate_tablet_checkbox),
gconf_client_get_bool (app->client, ROTATE_TABLET_KEY, NULL));
if (tablet_is_present ())
gtk_widget_show_all (app->rotate_tablet_box);
else
gtk_widget_hide (app->rotate_tablet_box);
}
static GtkWidget*
_gtk_builder_get_widget (GtkBuilder *builder, const gchar *name)
{
@@ -2183,6 +2372,11 @@ run_application (App *app)
g_signal_connect (app->resolution_combo, "changed",
G_CALLBACK (on_resolution_changed), app);
app->scale_combo = _gtk_builder_get_widget (builder,
"scale_combo");
g_signal_connect (app->scale_combo, "changed",
G_CALLBACK (on_scale_changed), app);
app->refresh_combo = _gtk_builder_get_widget (builder, "refresh_combo");
g_signal_connect (app->refresh_combo, "changed",
G_CALLBACK (on_rate_changed), app);
@@ -2208,7 +2402,13 @@ run_application (App *app)
app->panel_checkbox = _gtk_builder_get_widget (builder, "panel_checkbox");
app->rotate_tablet_box = _gtk_builder_get_widget (builder, "rotate-tablet-box");
app->rotate_tablet_checkbox = _gtk_builder_get_widget (builder, "rotate-tablet");
set_rotate_tablet_widgets (app);
g_signal_connect (app->rotate_tablet_checkbox, "toggled", G_CALLBACK (rotate_tablet_toggled_cb), app);
make_text_combo (app->resolution_combo, 4);
make_text_combo (app->scale_combo, 4);
make_text_combo (app->refresh_combo, 3);
make_text_combo (app->rotation_combo, -1);