[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