[Spice-devel] [PATCH spice-gtk 18/25] spicy: learn to deal with monitors
Alon Levy
alevy at redhat.com
Sun Jul 15 23:11:46 PDT 2012
On Fri, Jul 13, 2012 at 12:29:15AM +0200, Marc-André Lureau wrote:
> ---
> gtk/spicy.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++---------
> 1 file changed, 84 insertions(+), 14 deletions(-)
>
> diff --git a/gtk/spicy.c b/gtk/spicy.c
> index 5ffe3b7..ac2088e 100644
> --- a/gtk/spicy.c
> +++ b/gtk/spicy.c
> @@ -62,7 +62,8 @@ typedef struct _SpiceWindowClass SpiceWindowClass;
> struct _SpiceWindow {
> GObject object;
> spice_connection *conn;
> - int id;
> + gint id;
> + gint monitor_id;
> GtkWidget *toplevel, *spice;
> GtkWidget *menubar, *toolbar;
> GtkWidget *ritem, *rmenu;
> @@ -87,10 +88,15 @@ struct _SpiceWindowClass
>
> G_DEFINE_TYPE (SpiceWindow, spice_window, G_TYPE_OBJECT);
>
> +#define CHANNELID_MAX 4
> +#define MONITORID_MAX 4
> +
> +// FIXME: turn this into an object, get rid of fixed wins array, use
> +// signals to replace the various callback that iterate over wins array
> struct spice_connection {
> SpiceSession *session;
> SpiceGtkSession *gtk_session;
> - SpiceWindow *wins[4];
> + SpiceWindow *wins[CHANNELID_MAX * MONITORID_MAX];
> SpiceAudio *audio;
> const char *mouse_state;
> const char *agent_state;
> @@ -1141,7 +1147,7 @@ spice_window_init (SpiceWindow *self)
> {
> }
>
> -static SpiceWindow *create_spice_window(spice_connection *conn, int id, SpiceChannel *channel)
> +static SpiceWindow *create_spice_window(spice_connection *conn, SpiceChannel *channel, int id, gint monitor_id)
> {
> char title[32];
> SpiceWindow *win;
> @@ -1154,12 +1160,13 @@ static SpiceWindow *create_spice_window(spice_connection *conn, int id, SpiceCha
>
> win = g_object_new(SPICE_TYPE_WINDOW, NULL);
> win->id = id;
> + win->monitor_id = monitor_id;
> win->conn = conn;
> win->display_channel = channel;
>
> /* toplevel */
> win->toplevel = gtk_window_new(GTK_WINDOW_TOPLEVEL);
> - snprintf(title, sizeof(title), _("spice display %d"), id);
> + snprintf(title, sizeof(title), _("spice display %d:%d"), id, monitor_id);
> gtk_window_set_title(GTK_WINDOW(win->toplevel), title);
> g_signal_connect(G_OBJECT(win->toplevel), "window-state-event",
> G_CALLBACK(window_state_cb), win);
> @@ -1204,7 +1211,7 @@ static SpiceWindow *create_spice_window(spice_connection *conn, int id, SpiceCha
> #endif
>
> /* spice display */
> - win->spice = GTK_WIDGET(spice_display_new(conn->session, id));
> + win->spice = GTK_WIDGET(spice_display_new_with_monitor(conn->session, id, monitor_id));
> g_signal_connect(win->spice, "configure-event", G_CALLBACK(configure_event_cb), win);
> seq = spice_grab_sequence_new_from_string("Shift_L+F12");
> spice_display_set_grab_keys(SPICE_DISPLAY(win->spice), seq);
> @@ -1324,7 +1331,10 @@ static SpiceWindow *create_spice_window(spice_connection *conn, int id, SpiceCha
>
> static void destroy_spice_window(SpiceWindow *win)
> {
> - SPICE_DEBUG("destroy window (#%d)", win->id);
> + if (win == NULL)
> + return;
> +
> + SPICE_DEBUG("destroy window (#%d:%d)", win->id, win->monitor_id);
> g_object_unref(win->ag);
> g_object_unref(win->ui);
> gtk_widget_destroy(win->toplevel);
> @@ -1490,6 +1500,70 @@ static void update_auto_usbredir_sensitive(spice_connection *conn)
> #endif
> }
>
> +static SpiceWindow* get_window(spice_connection *conn, int channel_id, int monitor_id)
> +{
> + g_return_val_if_fail(channel_id < CHANNELID_MAX, NULL);
> + g_return_val_if_fail(monitor_id < MONITORID_MAX, NULL);
> +
> + return conn->wins[channel_id * CHANNELID_MAX + monitor_id];
> +}
> +
> +static void add_window(spice_connection *conn, SpiceWindow *win)
> +{
> + g_return_if_fail(win != NULL);
> + g_return_if_fail(win->id < CHANNELID_MAX);
> + g_return_if_fail(win->monitor_id < MONITORID_MAX);
> + g_return_if_fail(conn->wins[win->id * CHANNELID_MAX + win->monitor_id] == NULL);
> +
> + SPICE_DEBUG("add display monitor %d:%d", win->id, win->monitor_id);
> + conn->wins[win->id * CHANNELID_MAX + win->monitor_id] = win;
> +}
> +
> +static void del_window(spice_connection *conn, SpiceWindow *win)
> +{
> + if (win == NULL)
> + return;
> +
> + g_return_if_fail(win->id < CHANNELID_MAX);
> + g_return_if_fail(win->monitor_id < MONITORID_MAX);
> +
> + g_debug("del display monitor %d:%d", win->id, win->monitor_id);
> + conn->wins[win->id * CHANNELID_MAX + win->monitor_id] = NULL;
> + destroy_spice_window(win);
> +}
> +
> +static void display_monitors(SpiceChannel *display, GParamSpec *pspec,
> + spice_connection *conn)
> +{
> + GArray *monitors = NULL;
> + int id;
> + guint i;
> +
> + g_object_get(display,
> + "channel-id", &id,
> + "monitors", &monitors,
> + NULL);
> + g_return_if_fail(monitors != NULL);
> +
> + for (i = 0; i < monitors->len; i++) {
> + SpiceWindow *w;
> +
> + if (!get_window(conn, id, i)) {
> + w = create_spice_window(conn, display, id, i);
> + add_window(conn, w);
> + spice_g_signal_connect_object(display, "display-mark",
> + G_CALLBACK(display_mark), w, 0);
> + gtk_widget_show(w->toplevel);
> + update_auto_usbredir_sensitive(conn);
This is a little ugly - but not related to this patch. I mean, you
shouldn't have to specify update_auto_usbredir_sensitive here, it should
be in the widget. But this is spicy anyway.
> + }
> + }
> +
> + for (; i < MONITORID_MAX; i++)
> + del_window(conn, get_window(conn, id, i));
> +
> + g_clear_pointer(&monitors, g_array_unref);
> +}
> +
> static void channel_new(SpiceSession *s, SpiceChannel *channel, gpointer data)
> {
> spice_connection *conn = data;
> @@ -1517,10 +1591,9 @@ 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, channel);
> - g_signal_connect(channel, "display-mark",
> - G_CALLBACK(display_mark), conn->wins[id]);
> - update_auto_usbredir_sensitive(conn);
> + g_signal_connect(channel, "notify::monitors",
> + G_CALLBACK(display_monitors), conn);
> + spice_channel_connect(channel);
> }
>
> if (SPICE_IS_INPUTS_CHANNEL(channel)) {
> @@ -1552,11 +1625,8 @@ static void channel_destroy(SpiceSession *s, SpiceChannel *channel, gpointer dat
> if (SPICE_IS_DISPLAY_CHANNEL(channel)) {
> if (id >= SPICE_N_ELEMENTS(conn->wins))
> return;
> - if (conn->wins[id] == NULL)
> - return;
> SPICE_DEBUG("zap display channel (#%d)", id);
> - destroy_spice_window(conn->wins[id]);
> - conn->wins[id] = NULL;
> + /* FIXME destroy widget only */
> }
>
> if (SPICE_IS_PLAYBACK_CHANNEL(channel)) {
> --
> 1.7.10.4
>
> _______________________________________________
> Spice-devel mailing list
> Spice-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/spice-devel
More information about the Spice-devel
mailing list