[Spice-commits] 6 commits - configure.ac gtk/channel-usbredir-priv.h gtk/channel-usbredir.c gtk/map-file gtk/spice-client-glib-usb-acl-helper.c gtk/spicy.c gtk/usb-acl-helper.c gtk/usb-device-manager-priv.h gtk/usb-device-manager.c gtk/usb-device-manager.h gtk/usb-device-widget.c
Hans de Goede
jwrdegoede at kemper.freedesktop.org
Thu Feb 23 00:14:22 PST 2012
configure.ac | 6 -
gtk/channel-usbredir-priv.h | 6 +
gtk/channel-usbredir.c | 80 ++++++++++++-
gtk/map-file | 1
gtk/spice-client-glib-usb-acl-helper.c | 5
gtk/spicy.c | 7 +
gtk/usb-acl-helper.c | 13 +-
gtk/usb-device-manager-priv.h | 3
gtk/usb-device-manager.c | 116 ++++++++++++++++++-
gtk/usb-device-manager.h | 9 +
gtk/usb-device-widget.c | 196 +++++++++++++++++++++++++++------
11 files changed, 390 insertions(+), 52 deletions(-)
New commits:
commit 2e4a9c91849f93d9a09e3bffedadc30e667455f9
Author: Hans de Goede <hdegoede at redhat.com>
Date: Sun Feb 19 00:29:39 2012 +0100
usbredir: Add awareness of host/guest side filtering
Signed-off-by: Hans de Goede <hdegoede at redhat.com>
diff --git a/configure.ac b/configure.ac
index bf9b4ed..6e8c8e3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -346,7 +346,7 @@ if test "x$enable_usbredir" = "xno"; then
have_usbredir="no"
else
PKG_CHECK_MODULES([USBREDIR],
- [gudev-1.0 libusb-1.0 >= 1.0.9 libusbredirhost >= 0.3.4 libusbredirparser >= 0.3.4],
+ [gudev-1.0 libusb-1.0 >= 1.0.9 libusbredirhost >= 0.4 libusbredirparser >= 0.4],
[have_usbredir=yes],
[have_usbredir=no])
if test "x$have_usbredir" = "xno" && test "x$enable_usbredir" = "xyes"; then
diff --git a/gtk/channel-usbredir-priv.h b/gtk/channel-usbredir-priv.h
index 10dd479..5d28c79 100644
--- a/gtk/channel-usbredir-priv.h
+++ b/gtk/channel-usbredir-priv.h
@@ -22,6 +22,7 @@
#define __SPICE_CLIENT_USBREDIR_CHANNEL_PRIV_H__
#include <libusb.h>
+#include <usbredirfilter.h>
#include "spice-client.h"
G_BEGIN_DECLS
@@ -49,6 +50,11 @@ void spice_usbredir_channel_disconnect_device(SpiceUsbredirChannel *channel);
libusb_device *spice_usbredir_channel_get_device(SpiceUsbredirChannel *channel);
+void spice_usbredir_channel_get_guest_filter(
+ SpiceUsbredirChannel *channel,
+ const struct usbredirfilter_rule **rules_ret,
+ int *rules_count_ret);
+
G_END_DECLS
#endif /* __SPICE_CLIENT_USBREDIR_CHANNEL_PRIV_H__ */
diff --git a/gtk/channel-usbredir.c b/gtk/channel-usbredir.c
index fa7dce0..eb81fe5 100644
--- a/gtk/channel-usbredir.c
+++ b/gtk/channel-usbredir.c
@@ -408,6 +408,22 @@ libusb_device *spice_usbredir_channel_get_device(SpiceUsbredirChannel *channel)
return channel->priv->device;
}
+G_GNUC_INTERNAL
+void spice_usbredir_channel_get_guest_filter(
+ SpiceUsbredirChannel *channel,
+ const struct usbredirfilter_rule **rules_ret,
+ int *rules_count_ret)
+{
+ SpiceUsbredirChannelPrivate *priv = channel->priv;
+
+ g_return_if_fail(priv->host != NULL);
+
+ usbredirhost_get_guest_filter(priv->host, rules_ret, rules_count_ret);
+}
+
+/* ------------------------------------------------------------------ */
+/* callbacks (any context) */
+
/* Note that this function must be re-entrant safe, as it can get called
from both the main thread as well as from the usb event handling thread */
static void usbredir_write_flush_callback(void *user_data)
@@ -422,9 +438,6 @@ static void usbredir_write_flush_callback(void *user_data)
usbredirhost_write_guest_data(priv->host);
}
-/* ------------------------------------------------------------------ */
-/* callbacks (any context) */
-
static void usbredir_log(void *user_data, int level, const char *msg)
{
SpiceUsbredirChannel *channel = user_data;
diff --git a/gtk/usb-device-manager.c b/gtk/usb-device-manager.c
index 959e0ab..37cc88b 100644
--- a/gtk/usb-device-manager.c
+++ b/gtk/usb-device-manager.c
@@ -921,8 +921,9 @@ spice_usb_device_manager_can_redirect_device(SpiceUsbDeviceManager *self,
GError **err)
{
#ifdef USE_USBREDIR
+ const struct usbredirfilter_rule *guest_filter_rules = NULL;
SpiceUsbDeviceManagerPrivate *priv = self->priv;
- int i;
+ int i, guest_filter_rules_count;
gboolean enabled;
g_return_val_if_fail(SPICE_IS_USB_DEVICE_MANAGER(self), FALSE);
@@ -946,6 +947,21 @@ spice_usb_device_manager_can_redirect_device(SpiceUsbDeviceManager *self,
if (spice_usb_device_manager_is_device_connected(self, device))
return TRUE;
+ /* We assume all channels have the same filter, so we just take the
+ filter from the first channel */
+ spice_usbredir_channel_get_guest_filter(
+ g_ptr_array_index(priv->channels, 0),
+ &guest_filter_rules, &guest_filter_rules_count);
+
+ if (guest_filter_rules &&
+ usbredirhost_check_device_filter(
+ guest_filter_rules, guest_filter_rules_count,
+ (libusb_device *)device, 0) != 0) {
+ g_set_error_literal(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
+ _("Some USB devices are blocked by host policy"));
+ return FALSE;
+ }
+
/* Check if there are free channels */
for (i = 0; i < priv->channels->len; i++) {
SpiceUsbredirChannel *channel = g_ptr_array_index(priv->channels, i);
commit e84b55a675bd5c25173194e4ee2518d9412d42f0
Author: Hans de Goede <hdegoede at redhat.com>
Date: Tue Feb 21 11:50:03 2012 +0100
usbredir: Add a spice_usb_device_manager_can_redirect_device function
Add a spice_usb_device_manager_can_redirect_device function and use this
in SpiceUsbDeviceWidget to check if redirection is available.
Signed-off-by: Hans de Goede <hdegoede at redhat.com>
diff --git a/gtk/map-file b/gtk/map-file
index 320dae3..81cd682 100644
--- a/gtk/map-file
+++ b/gtk/map-file
@@ -85,6 +85,7 @@ spice_smartcard_reader_get_type;
spice_smartcard_reader_is_software;
spice_usb_device_get_description;
spice_usb_device_get_type;
+spice_usb_device_manager_can_redirect_device;
spice_usb_device_manager_connect_device_async;
spice_usb_device_manager_connect_device_finish;
spice_usb_device_manager_disconnect_device;
diff --git a/gtk/usb-device-manager.c b/gtk/usb-device-manager.c
index dea0ab5..959e0ab 100644
--- a/gtk/usb-device-manager.c
+++ b/gtk/usb-device-manager.c
@@ -212,7 +212,7 @@ static gboolean spice_usb_device_manager_initable_init(GInitable *initable,
return TRUE;
#else
g_set_error_literal(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
- "USB redirection support not compiled in");
+ _("USB redirection support not compiled in"));
return FALSE;
#endif
}
@@ -578,10 +578,17 @@ static void spice_usb_device_manager_add_dev(SpiceUsbDeviceManager *self,
g_ptr_array_add(priv->devices, device);
if (priv->auto_connect) {
- if (usbredirhost_check_device_filter(
- priv->auto_conn_filter_rules,
- priv->auto_conn_filter_rules_count,
- device, 0) == 0)
+ gboolean can_redirect, auto_ok;
+
+ can_redirect = spice_usb_device_manager_can_redirect_device(
+ self, (SpiceUsbDevice *)device, NULL);
+
+ auto_ok = usbredirhost_check_device_filter(
+ priv->auto_conn_filter_rules,
+ priv->auto_conn_filter_rules_count,
+ device, 0) == 0;
+
+ if (can_redirect && auto_ok)
spice_usb_device_manager_connect_device_async(self,
(SpiceUsbDevice *)device, NULL,
spice_usb_device_manager_auto_connect_cb,
@@ -861,7 +868,7 @@ void spice_usb_device_manager_connect_device_async(SpiceUsbDeviceManager *self,
g_simple_async_result_set_error(result,
SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
- "No free USB channel");
+ _("No free USB channel"));
#ifdef USE_USBREDIR
done:
#endif
@@ -908,6 +915,58 @@ void spice_usb_device_manager_disconnect_device(SpiceUsbDeviceManager *self,
#endif
}
+gboolean
+spice_usb_device_manager_can_redirect_device(SpiceUsbDeviceManager *self,
+ SpiceUsbDevice *device,
+ GError **err)
+{
+#ifdef USE_USBREDIR
+ SpiceUsbDeviceManagerPrivate *priv = self->priv;
+ int i;
+ gboolean enabled;
+
+ g_return_val_if_fail(SPICE_IS_USB_DEVICE_MANAGER(self), FALSE);
+ g_return_val_if_fail(device != NULL, FALSE);
+ g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
+
+ g_object_get(G_OBJECT(priv->session), "enable-usbredir", &enabled, NULL);
+ if (!enabled) {
+ g_set_error_literal(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
+ _("USB redirection is disabled"));
+ return FALSE;
+ }
+
+ if (!priv->channels->len) {
+ g_set_error_literal(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
+ _("The connected VM is not configured for USB redirection"));
+ return FALSE;
+ }
+
+ /* Skip the other checks for already connected devices */
+ if (spice_usb_device_manager_is_device_connected(self, device))
+ return TRUE;
+
+ /* Check if there are free channels */
+ for (i = 0; i < priv->channels->len; i++) {
+ SpiceUsbredirChannel *channel = g_ptr_array_index(priv->channels, i);
+
+ if (!spice_usbredir_channel_get_device(channel))
+ break;
+ }
+ if (i == priv->channels->len) {
+ g_set_error_literal(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
+ _("There are no free USB channels"));
+ return FALSE;
+ }
+
+ return TRUE;
+#else
+ g_set_error_literal(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
+ _("USB redirection support not compiled in"));
+ return FALSE;
+#endif
+}
+
/**
* spice_usb_device_get_description:
* @device: #SpiceUsbDevice to get the description of
diff --git a/gtk/usb-device-manager.h b/gtk/usb-device-manager.h
index eabfd00..de0e2ba 100644
--- a/gtk/usb-device-manager.h
+++ b/gtk/usb-device-manager.h
@@ -110,6 +110,11 @@ gboolean spice_usb_device_manager_connect_device_finish(
void spice_usb_device_manager_disconnect_device(SpiceUsbDeviceManager *manager,
SpiceUsbDevice *device);
+gboolean
+spice_usb_device_manager_can_redirect_device(SpiceUsbDeviceManager *self,
+ SpiceUsbDevice *device,
+ GError **err);
+
G_END_DECLS
#endif /* __SPICE_USB_DEVICE_MANAGER_H__ */
diff --git a/gtk/usb-device-widget.c b/gtk/usb-device-widget.c
index 1bfffc0..faaeace 100644
--- a/gtk/usb-device-widget.c
+++ b/gtk/usb-device-widget.c
@@ -71,6 +71,7 @@ struct _SpiceUsbDeviceWidgetPrivate {
gchar *device_format_string;
SpiceUsbDeviceManager *manager;
GtkWidget *info_bar;
+ gchar *err_msg;
};
static guint signals[LAST_SIGNAL] = { 0, };
@@ -167,11 +168,9 @@ static GObject *spice_usb_device_widget_constructor(
GObject *obj;
SpiceUsbDeviceWidget *self;
SpiceUsbDeviceWidgetPrivate *priv;
- const gchar *err_msg = NULL;
GPtrArray *devices = NULL;
GError *err = NULL;
GtkWidget *label;
- gboolean enabled;
gchar *str;
int i;
@@ -187,28 +186,6 @@ static GObject *spice_usb_device_widget_constructor(
if (!priv->session)
g_error("SpiceUsbDeviceWidget constructed without a session");
- g_object_get(G_OBJECT(priv->session), "enable-usbredir", &enabled, NULL);
- if (!enabled)
- err_msg = _("USB redirection is disabled");
-
- if (!err_msg && !spice_session_has_channel_type(priv->session,
- SPICE_CHANNEL_USBREDIR))
- err_msg = _("The connected VM is not configured for USB redirection");
-
- if (!err_msg) {
- priv->manager = spice_usb_device_manager_get(priv->session, &err);
- if (!err) {
- g_signal_connect(priv->manager, "device-added",
- G_CALLBACK(device_added_cb), self);
- g_signal_connect(priv->manager, "device-removed",
- G_CALLBACK(device_removed_cb), self);
- g_signal_connect(priv->manager, "device-error",
- G_CALLBACK(device_error_cb), self);
- devices = spice_usb_device_manager_get_devices(priv->manager);
- } else
- err_msg = err->message;
- }
-
label = gtk_label_new(NULL);
str = g_strdup_printf("<b>%s</b>", _("Select USB devices to redirect"));
gtk_label_set_markup(GTK_LABEL (label), str);
@@ -216,14 +193,24 @@ static GObject *spice_usb_device_widget_constructor(
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
gtk_box_pack_start(GTK_BOX(self), label, FALSE, FALSE, 0);
- if (err_msg) {
- spice_usb_device_widget_show_info_bar(self, err_msg,
+ priv->manager = spice_usb_device_manager_get(priv->session, &err);
+ if (err) {
+ spice_usb_device_widget_show_info_bar(self, err->message,
GTK_MESSAGE_WARNING,
GTK_STOCK_DIALOG_WARNING);
g_clear_error(&err);
return obj;
}
+ g_signal_connect(priv->manager, "device-added",
+ G_CALLBACK(device_added_cb), self);
+ g_signal_connect(priv->manager, "device-removed",
+ G_CALLBACK(device_removed_cb), self);
+ g_signal_connect(priv->manager, "device-error",
+ G_CALLBACK(device_error_cb), self);
+
+ devices = spice_usb_device_manager_get_devices(priv->manager);
+
for (i = 0; i < devices->len; i++)
device_added_cb(NULL, g_ptr_array_index(devices, i), self);
@@ -351,6 +338,60 @@ static SpiceUsbDevice *get_usb_device(GtkWidget *widget)
return g_object_get_data(G_OBJECT(widget), "usb-device");
}
+static void check_can_redirect(GtkWidget *widget, gpointer user_data)
+{
+ SpiceUsbDeviceWidget *self = SPICE_USB_DEVICE_WIDGET(user_data);
+ SpiceUsbDeviceWidgetPrivate *priv = self->priv;
+ SpiceUsbDevice *device;
+ gboolean can_redirect;
+ GError *err = NULL;
+
+ device = get_usb_device(widget);
+ if (!device)
+ return; /* Non device widget, ie the info_bar */
+
+ can_redirect = spice_usb_device_manager_can_redirect_device(priv->manager,
+ device, &err);
+ gtk_widget_set_sensitive(widget, can_redirect);
+
+ /* If we can not redirect this device, append the error message to
+ err_msg, but only if it is *not* already there! */
+ if (!can_redirect) {
+ if (priv->err_msg) {
+ if (!strstr(priv->err_msg, err->message)) {
+ gchar *old_err_msg = priv->err_msg;
+
+ priv->err_msg = g_strdup_printf("%s\n%s", priv->err_msg,
+ err->message);
+ g_free(old_err_msg);
+ }
+ } else {
+ priv->err_msg = g_strdup(err->message);
+ }
+ }
+
+ g_clear_error(&err);
+}
+
+static gboolean spice_usb_device_widget_update_status(gpointer user_data)
+{
+ SpiceUsbDeviceWidget *self = SPICE_USB_DEVICE_WIDGET(user_data);
+ SpiceUsbDeviceWidgetPrivate *priv = self->priv;
+
+ gtk_container_foreach(GTK_CONTAINER(self), check_can_redirect, self);
+
+ if (priv->err_msg) {
+ spice_usb_device_widget_show_info_bar(self, priv->err_msg,
+ GTK_MESSAGE_INFO,
+ GTK_STOCK_DIALOG_WARNING);
+ g_free(priv->err_msg);
+ priv->err_msg = NULL;
+ } else {
+ spice_usb_device_widget_hide_info_bar(self);
+ }
+ return FALSE;
+}
+
typedef struct _connect_cb_data {
GtkWidget *check;
SpiceUsbDeviceWidget *self;
@@ -379,6 +420,7 @@ static void connect_cb(GObject *gobject, GAsyncResult *res, gpointer user_data)
g_error_free(err);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->check), FALSE);
+ spice_usb_device_widget_update_status(self);
}
g_object_unref(data->check);
@@ -407,6 +449,7 @@ static void checkbox_clicked_cb(GtkWidget *check, gpointer user_data)
spice_usb_device_manager_disconnect_device(priv->manager,
device);
}
+ spice_usb_device_widget_update_status(self);
}
static void checkbox_usb_device_destroy_notify(gpointer data)
@@ -459,6 +502,8 @@ static void device_removed_cb(SpiceUsbDeviceManager *manager,
gtk_container_foreach(GTK_CONTAINER(self),
destroy_widget_by_usb_device, device);
+
+ spice_usb_device_widget_update_status(self);
}
static void set_inactive_by_usb_device(GtkWidget *widget, gpointer user_data)
@@ -474,4 +519,6 @@ static void device_error_cb(SpiceUsbDeviceManager *manager,
gtk_container_foreach(GTK_CONTAINER(self),
set_inactive_by_usb_device, device);
+
+ spice_usb_device_widget_update_status(self);
}
commit fdb494f7ece881485e473736b89ca48721e90e72
Author: Hans de Goede <hdegoede at redhat.com>
Date: Mon Feb 20 20:31:39 2012 +0100
usb-device-widget: Use an info_bar for error messages
And in general gnome-hig-ify usb-device-widget:
* Use spacing instead of padding so that there is no padding at the
outside/border of the widget, allowing the user to control the border size.
* Use multiple of 6 as spacing / indentation values
* Show the label left justified and bold, show the checkboxes (and the info
bar) 12 pixels indented from the label
Signed-off-by: Hans de Goede <hdegoede at redhat.com>
diff --git a/gtk/spicy.c b/gtk/spicy.c
index 40b724e..0486610 100644
--- a/gtk/spicy.c
+++ b/gtk/spicy.c
@@ -437,13 +437,16 @@ static void menu_cb_select_usb_devices(GtkAction *action, void *data)
GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
NULL);
gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT);
+ gtk_container_set_border_width(GTK_CONTAINER(dialog), 12);
+ gtk_box_set_spacing(GTK_BOX(gtk_bin_get_child(GTK_BIN(dialog))), 12);
+
area = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
usb_device_widget = spice_usb_device_widget_new(win->conn->session,
"%s %s");
g_signal_connect(usb_device_widget, "connect-failed",
G_CALLBACK(usb_connect_failed), NULL);
- gtk_box_pack_start(GTK_BOX(area), usb_device_widget, TRUE, TRUE, 5);
+ gtk_box_pack_start(GTK_BOX(area), usb_device_widget, TRUE, TRUE, 0);
/* This shrinks the dialog when USB devices are unplugged */
g_signal_connect(usb_device_widget, "remove",
diff --git a/gtk/usb-device-widget.c b/gtk/usb-device-widget.c
index 4b504ca..1bfffc0 100644
--- a/gtk/usb-device-widget.c
+++ b/gtk/usb-device-widget.c
@@ -70,6 +70,7 @@ struct _SpiceUsbDeviceWidgetPrivate {
SpiceSession *session;
gchar *device_format_string;
SpiceUsbDeviceManager *manager;
+ GtkWidget *info_bar;
};
static guint signals[LAST_SIGNAL] = { 0, };
@@ -118,6 +119,48 @@ static void spice_usb_device_widget_set_property(GObject *gobject,
}
}
+static void spice_usb_device_widget_hide_info_bar(SpiceUsbDeviceWidget *self)
+{
+ SpiceUsbDeviceWidgetPrivate *priv = self->priv;
+
+ if (priv->info_bar) {
+ gtk_widget_destroy(priv->info_bar);
+ priv->info_bar = NULL;
+ }
+}
+
+static void
+spice_usb_device_widget_show_info_bar(SpiceUsbDeviceWidget *self,
+ const gchar *message,
+ GtkMessageType message_type,
+ const gchar *stock_icon_id)
+{
+ SpiceUsbDeviceWidgetPrivate *priv = self->priv;
+ GtkWidget *info_bar, *content_area, *hbox, *widget;
+
+ spice_usb_device_widget_hide_info_bar(self);
+
+ info_bar = gtk_info_bar_new();
+ gtk_info_bar_set_message_type(GTK_INFO_BAR(info_bar), message_type);
+
+ content_area = gtk_info_bar_get_content_area(GTK_INFO_BAR(info_bar));
+ hbox = gtk_hbox_new(FALSE, 12);
+ gtk_container_add(GTK_CONTAINER(content_area), hbox);
+
+ widget = gtk_image_new_from_stock(stock_icon_id,
+ GTK_ICON_SIZE_SMALL_TOOLBAR);
+ gtk_box_pack_start(GTK_BOX(hbox), widget, FALSE, FALSE, 0);
+
+ widget = gtk_label_new(message);
+ gtk_box_pack_start(GTK_BOX(hbox), widget, TRUE, TRUE, 0);
+
+ priv->info_bar = gtk_alignment_new(0.0, 0.0, 1.0, 0.0);
+ gtk_alignment_set_padding(GTK_ALIGNMENT(priv->info_bar), 0, 0, 12, 0);
+ gtk_container_add(GTK_CONTAINER(priv->info_bar), info_bar);
+ gtk_box_pack_start(GTK_BOX(self), priv->info_bar, FALSE, FALSE, 0);
+ gtk_widget_show_all(priv->info_bar);
+}
+
static GObject *spice_usb_device_widget_constructor(
GType gtype, guint n_properties, GObjectConstructParam *properties)
{
@@ -129,6 +172,7 @@ static GObject *spice_usb_device_widget_constructor(
GError *err = NULL;
GtkWidget *label;
gboolean enabled;
+ gchar *str;
int i;
{
@@ -165,16 +209,21 @@ static GObject *spice_usb_device_widget_constructor(
err_msg = err->message;
}
+ label = gtk_label_new(NULL);
+ str = g_strdup_printf("<b>%s</b>", _("Select USB devices to redirect"));
+ gtk_label_set_markup(GTK_LABEL (label), str);
+ g_free(str);
+ gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
+ gtk_box_pack_start(GTK_BOX(self), label, FALSE, FALSE, 0);
+
if (err_msg) {
- label = gtk_label_new(err_msg);
- gtk_box_pack_start(GTK_BOX(self), label, TRUE, TRUE, 5);
+ spice_usb_device_widget_show_info_bar(self, err_msg,
+ GTK_MESSAGE_WARNING,
+ GTK_STOCK_DIALOG_WARNING);
g_clear_error(&err);
return obj;
}
- label = gtk_label_new(_("Select USB devices to redirect"));
- gtk_box_pack_start(GTK_BOX(self), label, TRUE, TRUE, 5);
-
for (i = 0; i < devices->len; i++)
device_added_cb(NULL, g_ptr_array_index(devices, i), self);
@@ -286,11 +335,22 @@ GtkWidget *spice_usb_device_widget_new(SpiceSession *session,
return g_object_new(SPICE_TYPE_USB_DEVICE_WIDGET,
"session", session,
"device-format-string", device_format_string,
+ "spacing", 6,
NULL);
}
/* ------------------------------------------------------------------ */
/* callbacks */
+
+static SpiceUsbDevice *get_usb_device(GtkWidget *widget)
+{
+ if (!GTK_IS_ALIGNMENT(widget))
+ return NULL;
+
+ widget = gtk_bin_get_child(GTK_BIN(widget));
+ return g_object_get_data(G_OBJECT(widget), "usb-device");
+}
+
typedef struct _connect_cb_data {
GtkWidget *check;
SpiceUsbDeviceWidget *self;
@@ -359,13 +419,13 @@ static void device_added_cb(SpiceUsbDeviceManager *manager,
{
SpiceUsbDeviceWidget *self = SPICE_USB_DEVICE_WIDGET(user_data);
SpiceUsbDeviceWidgetPrivate *priv = self->priv;
- GtkWidget *check;
+ GtkWidget *align, *check;
gchar *desc;
desc = spice_usb_device_get_description(device,
priv->device_format_string);
-
check = gtk_check_button_new_with_label(desc);
+ g_free(desc);
if (spice_usb_device_manager_is_device_connected(priv->manager,
device))
@@ -378,15 +438,17 @@ static void device_added_cb(SpiceUsbDeviceManager *manager,
g_signal_connect(G_OBJECT(check), "clicked",
G_CALLBACK(checkbox_clicked_cb), self);
- gtk_box_pack_start(GTK_BOX(self), check, TRUE, TRUE, 5);
- gtk_widget_show(check);
-
- g_free(desc);
+ align = gtk_alignment_new(0, 0, 0, 0);
+ gtk_alignment_set_padding(GTK_ALIGNMENT(align), 0, 0, 12, 0);
+ gtk_container_add(GTK_CONTAINER(align), check);
+ gtk_box_pack_end(GTK_BOX(self), align, FALSE, FALSE, 0);
+ spice_usb_device_widget_update_status(self);
+ gtk_widget_show_all(align);
}
static void destroy_widget_by_usb_device(GtkWidget *widget, gpointer user_data)
{
- if (g_object_get_data(G_OBJECT(widget), "usb-device") == user_data)
+ if (get_usb_device(widget) == user_data)
gtk_widget_destroy(widget);
}
@@ -401,7 +463,7 @@ static void device_removed_cb(SpiceUsbDeviceManager *manager,
static void set_inactive_by_usb_device(GtkWidget *widget, gpointer user_data)
{
- if (g_object_get_data(G_OBJECT(widget), "usb-device") == user_data)
+ if (get_usb_device(widget) == user_data)
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), FALSE);
}
commit 708d77a9ad51c659de0b5ef5a8225e8310f13499
Author: Hans de Goede <hdegoede at redhat.com>
Date: Mon Feb 20 16:45:32 2012 +0100
configure: Fix "USB redirection support" summary on --disable-usbredir
When running "./configure --disable-usbredir" the
"USB redirection support" line in the summary at the end of ./configure
would be empty after "support" instead of ending with yes or no.
Signed-off-by: Hans de Goede <hdegoede at redhat.com>
diff --git a/configure.ac b/configure.ac
index 7332b6d..bf9b4ed 100644
--- a/configure.ac
+++ b/configure.ac
@@ -343,7 +343,7 @@ AC_ARG_ENABLE([usbredir],
[enable_usbredir="auto"])
if test "x$enable_usbredir" = "xno"; then
- AM_CONDITIONAL(WITH_USBREDIR, false)
+ have_usbredir="no"
else
PKG_CHECK_MODULES([USBREDIR],
[gudev-1.0 libusb-1.0 >= 1.0.9 libusbredirhost >= 0.3.4 libusbredirparser >= 0.3.4],
@@ -355,8 +355,8 @@ else
if test "x$have_usbredir" = "xyes"; then
AC_DEFINE(USE_USBREDIR, [1], [Define if supporting usbredir proxying])
fi
- AM_CONDITIONAL([WITH_USBREDIR], [test "x$have_usbredir" = "xyes"])
fi
+AM_CONDITIONAL([WITH_USBREDIR], [test "x$have_usbredir" = "xyes"])
AC_ARG_ENABLE([polkit],
AS_HELP_STRING([--enable-polkit=@<:@auto/yes/no@:>@],
commit c64150541db0b8301f066901671bba1b7040599f
Author: Hans de Goede <hdegoede at redhat.com>
Date: Sun Feb 19 09:27:54 2012 +0100
usbredir: Treat the user cancelling the policykit dialog as a cancel
Rather then treating it as any other error. This avoids showing an error
dialog after the user pressed cancel in the policykit dialog.
Signed-off-by: Hans de Goede <hdegoede at redhat.com>
diff --git a/gtk/spice-client-glib-usb-acl-helper.c b/gtk/spice-client-glib-usb-acl-helper.c
index bd01979..aaa1180 100644
--- a/gtk/spice-client-glib-usb-acl-helper.c
+++ b/gtk/spice-client-glib-usb-acl-helper.c
@@ -177,6 +177,11 @@ static void check_authorization_cb(PolkitAuthority *authority,
return;
}
+ if (polkit_authorization_result_get_dismissed(result)) {
+ ERROR("CANCELED\n");
+ return;
+ }
+
if (!polkit_authorization_result_get_is_authorized(result)) {
ERROR("Not authorized\n");
return;
diff --git a/gtk/usb-acl-helper.c b/gtk/usb-acl-helper.c
index b79e122..6a459c5 100644
--- a/gtk/usb-acl-helper.c
+++ b/gtk/usb-acl-helper.c
@@ -87,6 +87,13 @@ static void spice_usb_acl_helper_class_init(SpiceUsbAclHelperClass *klass)
/* ------------------------------------------------------------------ */
/* callbacks */
+static void async_result_set_cancelled(GSimpleAsyncResult *result)
+{
+ g_simple_async_result_set_error(result,
+ G_IO_ERROR, G_IO_ERROR_CANCELLED,
+ "Setting USB device node ACL cancelled");
+}
+
static gboolean cb_out_watch(GIOChannel *channel,
GIOCondition cond,
gpointer *user_data)
@@ -111,6 +118,8 @@ static gboolean cb_out_watch(GIOChannel *channel,
string[strlen(string) - 1] = 0;
if (!strcmp(string, "SUCCESS")) {
success = TRUE;
+ } else if (!strcmp(string, "CANCELED")) {
+ async_result_set_cancelled(priv->result);
} else {
g_simple_async_result_set_error(priv->result,
SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
@@ -278,9 +287,7 @@ void spice_usb_acl_helper_close_acl(SpiceUsbAclHelper *self)
/* If the acl open has not completed yet report it as cancelled */
if (priv->result) {
- g_simple_async_result_set_error(priv->result,
- G_IO_ERROR, G_IO_ERROR_CANCELLED,
- "Setting USB device node ACL cancelled");
+ async_result_set_cancelled(priv->result);
g_simple_async_result_complete_in_idle(priv->result);
}
commit bde67bf22361da794e75effa2255d7f3a3c713e2
Author: Hans de Goede <hdegoede at redhat.com>
Date: Sat Feb 18 16:59:03 2012 +0100
usbredir: Add device rejected errors
Signed-off-by: Hans de Goede <hdegoede at redhat.com>
diff --git a/gtk/channel-usbredir.c b/gtk/channel-usbredir.c
index e22aa6c..fa7dce0 100644
--- a/gtk/channel-usbredir.c
+++ b/gtk/channel-usbredir.c
@@ -513,6 +513,42 @@ static void usbredir_free_lock(void *user_data) {
}
/* --------------------------------------------------------------------- */
+
+/* Events to be handled in main context */
+enum {
+ DEVICE_ERROR,
+};
+
+struct DEVICE_ERROR {
+ libusb_device *device;
+ GError *error;
+};
+
+/* main context */
+static void do_emit_main_context(GObject *object, int event, gpointer params)
+{
+ SpiceUsbredirChannel *channel = SPICE_USBREDIR_CHANNEL(object);
+ SpiceUsbredirChannelPrivate *priv = channel->priv;
+
+ switch (event) {
+ case DEVICE_ERROR: {
+ struct DEVICE_ERROR *p = params;
+ /* Check that the device has not changed before we manage to run */
+ if (p->device == priv->device) {
+ spice_usbredir_channel_disconnect_device(channel);
+ spice_usb_device_manager_device_error(
+ spice_usb_device_manager_get(
+ spice_channel_get_session(SPICE_CHANNEL(channel)), NULL),
+ (SpiceUsbDevice *)p->device, p->error);
+ }
+ break;
+ }
+ default:
+ g_warn_if_reached();
+ }
+}
+
+/* --------------------------------------------------------------------- */
/* coroutine context */
static void spice_usbredir_handle_msg(SpiceChannel *c, SpiceMsgIn *msg)
{
@@ -544,7 +580,7 @@ static void usbredir_handle_msg(SpiceChannel *c, SpiceMsgIn *in)
{
SpiceUsbredirChannel *channel = SPICE_USBREDIR_CHANNEL(c);
SpiceUsbredirChannelPrivate *priv = channel->priv;
- int size;
+ int r, size;
uint8_t *buf;
g_return_if_fail(priv->host != NULL);
@@ -556,7 +592,28 @@ static void usbredir_handle_msg(SpiceChannel *c, SpiceMsgIn *in)
priv->read_buf = buf;
priv->read_buf_size = size;
- usbredirhost_read_guest_data(priv->host);
+ r = usbredirhost_read_guest_data(priv->host);
+ if (r == usbredirhost_read_device_rejected) {
+ libusb_device *device = priv->device;
+ gchar *desc;
+ GError *err;
+
+ g_return_if_fail(device != NULL);
+
+ desc = spice_usb_device_get_description((SpiceUsbDevice *)device,
+ NULL);
+ err = g_error_new(SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
+ "%s rejected by host", desc);
+ g_free(desc);
+
+ SPICE_DEBUG("%s", err->message);
+
+ g_boxed_copy(spice_usb_device_get_type(), device);
+ emit_main_context(channel, DEVICE_ERROR, device, err);
+ g_boxed_free(spice_usb_device_get_type(), device);
+
+ g_error_free(err);
+ }
}
#endif /* USE_USBREDIR */
diff --git a/gtk/spicy.c b/gtk/spicy.c
index 2757bd7..40b724e 100644
--- a/gtk/spicy.c
+++ b/gtk/spicy.c
@@ -1573,6 +1573,8 @@ static spice_connection *connection_new(void)
if (manager) {
g_signal_connect(manager, "auto-connect-failed",
G_CALLBACK(usb_connect_failed), NULL);
+ g_signal_connect(manager, "device-error",
+ G_CALLBACK(usb_connect_failed), NULL);
}
connections++;
diff --git a/gtk/usb-device-manager-priv.h b/gtk/usb-device-manager-priv.h
index b0b2f74..912e3bf 100644
--- a/gtk/usb-device-manager-priv.h
+++ b/gtk/usb-device-manager-priv.h
@@ -31,6 +31,9 @@ gboolean spice_usb_device_manager_start_event_listening(
void spice_usb_device_manager_stop_event_listening(
SpiceUsbDeviceManager *manager);
+void spice_usb_device_manager_device_error(
+ SpiceUsbDeviceManager *manager, SpiceUsbDevice *device, GError *err);
+
G_END_DECLS
#endif /* __SPICE_USB_DEVICE_MANAGER_PRIV_H__ */
diff --git a/gtk/usb-device-manager.c b/gtk/usb-device-manager.c
index b6dfa20..dea0ab5 100644
--- a/gtk/usb-device-manager.c
+++ b/gtk/usb-device-manager.c
@@ -85,6 +85,7 @@ enum
DEVICE_ADDED,
DEVICE_REMOVED,
AUTO_CONNECT_FAILED,
+ DEVICE_ERROR,
LAST_SIGNAL,
};
@@ -433,6 +434,28 @@ static void spice_usb_device_manager_class_init(SpiceUsbDeviceManagerClass *klas
SPICE_TYPE_USB_DEVICE,
G_TYPE_ERROR);
+ /**
+ * SpiceUsbDeviceManager::device-error:
+ * @manager: #SpiceUsbDeviceManager that emitted the signal
+ * @device: #SpiceUsbDevice boxed object corresponding to the device which has an error
+ * @error: #GError describing the error
+ *
+ * The #SpiceUsbDeviceManager::device-error signal is emitted whenever an
+ * error happens which causes a device to no longer be available to the
+ * guest.
+ **/
+ signals[DEVICE_ERROR] =
+ g_signal_new("device-error",
+ G_OBJECT_CLASS_TYPE(gobject_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET(SpiceUsbDeviceManagerClass, device_error),
+ NULL, NULL,
+ g_cclosure_user_marshal_VOID__BOXED_BOXED,
+ G_TYPE_NONE,
+ 2,
+ SPICE_TYPE_USB_DEVICE,
+ G_TYPE_ERROR);
+
g_type_class_add_private(klass, sizeof(SpiceUsbDeviceManagerPrivate));
}
@@ -682,6 +705,12 @@ void spice_usb_device_manager_stop_event_listening(
if (priv->event_listeners == 0)
priv->event_thread_run = FALSE;
}
+
+void spice_usb_device_manager_device_error(
+ SpiceUsbDeviceManager *self, SpiceUsbDevice *device, GError *err)
+{
+ g_signal_emit(self, signals[DEVICE_ERROR], 0, device, err);
+}
#endif
static SpiceUsbredirChannel *spice_usb_device_manager_get_channel_for_dev(
diff --git a/gtk/usb-device-manager.h b/gtk/usb-device-manager.h
index ec1a896..eabfd00 100644
--- a/gtk/usb-device-manager.h
+++ b/gtk/usb-device-manager.h
@@ -76,12 +76,14 @@ struct _SpiceUsbDeviceManagerClass
SpiceUsbDevice *device);
void (*auto_connect_failed) (SpiceUsbDeviceManager *manager,
SpiceUsbDevice *device, GError *error);
+ void (*device_error) (SpiceUsbDeviceManager *manager,
+ SpiceUsbDevice *device, GError *error);
/*< private >*/
/*
* If adding fields to this struct, remove corresponding
* amount of padding to avoid changing overall struct size
*/
- gchar _spice_reserved[SPICE_RESERVED_PADDING];
+ gchar _spice_reserved[SPICE_RESERVED_PADDING - sizeof(void*)];
};
GType spice_usb_device_get_type(void);
diff --git a/gtk/usb-device-widget.c b/gtk/usb-device-widget.c
index 028723f..4b504ca 100644
--- a/gtk/usb-device-widget.c
+++ b/gtk/usb-device-widget.c
@@ -45,6 +45,8 @@ static void device_added_cb(SpiceUsbDeviceManager *manager,
SpiceUsbDevice *device, gpointer user_data);
static void device_removed_cb(SpiceUsbDeviceManager *manager,
SpiceUsbDevice *device, gpointer user_data);
+static void device_error_cb(SpiceUsbDeviceManager *manager,
+ SpiceUsbDevice *device, GError *err, gpointer user_data);
/* ------------------------------------------------------------------ */
/* gobject glue */
@@ -156,6 +158,8 @@ static GObject *spice_usb_device_widget_constructor(
G_CALLBACK(device_added_cb), self);
g_signal_connect(priv->manager, "device-removed",
G_CALLBACK(device_removed_cb), self);
+ g_signal_connect(priv->manager, "device-error",
+ G_CALLBACK(device_error_cb), self);
devices = spice_usb_device_manager_get_devices(priv->manager);
} else
err_msg = err->message;
@@ -189,6 +193,8 @@ static void spice_usb_device_widget_finalize(GObject *object)
device_added_cb, self);
g_signal_handlers_disconnect_by_func(priv->manager,
device_removed_cb, self);
+ g_signal_handlers_disconnect_by_func(priv->manager,
+ device_error_cb, self);
}
g_object_unref(priv->session);
g_free(priv->device_format_string);
@@ -392,3 +398,18 @@ static void device_removed_cb(SpiceUsbDeviceManager *manager,
gtk_container_foreach(GTK_CONTAINER(self),
destroy_widget_by_usb_device, device);
}
+
+static void set_inactive_by_usb_device(GtkWidget *widget, gpointer user_data)
+{
+ if (g_object_get_data(G_OBJECT(widget), "usb-device") == user_data)
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), FALSE);
+}
+
+static void device_error_cb(SpiceUsbDeviceManager *manager,
+ SpiceUsbDevice *device, GError *err, gpointer user_data)
+{
+ SpiceUsbDeviceWidget *self = SPICE_USB_DEVICE_WIDGET(user_data);
+
+ gtk_container_foreach(GTK_CONTAINER(self),
+ set_inactive_by_usb_device, device);
+}
More information about the Spice-commits
mailing list