[gnome-boxes] Various fixes for layout, animation and flickering



commit dea449c1cc93f509584a28676545d78011f31379
Author: Marc-Andrà Lureau <marcandre lureau gmail com>
Date:   Mon Oct 10 17:36:18 2011 +0200

    Various fixes for layout, animation and flickering

 src/app.vala             |   19 ++++++++---
 src/collection-view.vala |   68 ++++++++++++++++++++++----------------
 src/machine.vala         |   82 ++++++++++++++++++++++++++-------------------
 src/sidebar.vala         |    2 +-
 src/topbar.vala          |    2 +-
 src/util.vala            |    7 +++-
 6 files changed, 108 insertions(+), 72 deletions(-)
---
diff --git a/src/app.vala b/src/app.vala
index 78ef84f..2950f7f 100644
--- a/src/app.vala
+++ b/src/app.vala
@@ -7,6 +7,7 @@ using Clutter;
 using GVir;
 
 private enum Boxes.UIState {
+    NONE,
     COLLECTION,
     CREDS,
     DISPLAY,
@@ -25,7 +26,6 @@ private class Boxes.App: Boxes.UI {
     public Clutter.Stage stage;
     public Clutter.State state;
     public Clutter.Box box; // the whole app box
-    public Clutter.Box display_box; // the display box above
     public CollectionItem current_item; // current object/vm manipulated
     public GVir.Connection connection;
     public static const uint duration = 555;  // default to 1/2 for all transitions
@@ -103,9 +103,6 @@ private class Boxes.App: Boxes.UI {
         size_group.add_widget (topbar.corner);
         size_group.add_widget (sidebar.notebook);
 
-        display_box = new Clutter.Box (new Clutter.BinLayout (Clutter.BinAlignment.CENTER, Clutter.BinAlignment.CENTER));
-        stage.add_actor (display_box);
-
         window.show ();
 
         ui_state = UIState.COLLECTION;
@@ -135,6 +132,7 @@ private class Boxes.App: Boxes.UI {
         case UIState.COLLECTION:
             box.set_layout_manager (box_table);
             state.set_state ("collection");
+
             break;
         default:
             warning ("Unhandled UI state %s".printf (ui_state.to_string ()));
@@ -183,7 +181,18 @@ private class Boxes.App: Boxes.UI {
 
 private abstract class Boxes.UI: GLib.Object {
     public abstract Clutter.Actor actor { get; }
-    public UIState ui_state { get; set; }
+
+    private UIState _ui_state;
+    [CCode (notify = false)]
+    public UIState ui_state {
+        get { return _ui_state; }
+        set {
+            if (_ui_state != value) {
+                _ui_state = value;
+                notify_property("ui_state");
+            }
+        }
+    }
 
     public UI () {
         notify["ui-state"].connect ( (s, p) => {
diff --git a/src/collection-view.vala b/src/collection-view.vala
index 3ab88ac..5c8b0ed 100644
--- a/src/collection-view.vala
+++ b/src/collection-view.vala
@@ -18,34 +18,34 @@ private class Boxes.CollectionView: Boxes.UI {
     public override void ui_state_changed () {
         switch (ui_state) {
         case UIState.CREDS:
-            over_boxes.add_constraint_with_name ("top-box-size",
-                                                 new Clutter.BindConstraint (margin, BindCoordinate.SIZE, 0));
-            over_boxes.add_constraint_with_name ("top-box-position",
-                                                 new Clutter.BindConstraint (margin, BindCoordinate.POSITION, 0));
-            actor_add (over_boxes, app.stage);
-
             remove_item (app.current_item);
-            app.current_item.ui_state = UIState.CREDS;
-
             over_boxes.pack (app.current_item.actor,
                              "x-align", Clutter.BinAlignment.CENTER,
                              "y-align", Clutter.BinAlignment.CENTER);
+            app.current_item.ui_state = UIState.CREDS;
+            actor_add (over_boxes, app.stage);
 
+            /* item don't move anymore */
             boxes.set_layout_manager (new Clutter.FixedLayout ());
 
             break;
 
         case UIState.DISPLAY: {
             float x, y;
-            var actor = app.current_item.actor;
+            var display = app.current_item.actor;
+
+            /* move display/machine actor to stage, keep same position */
+            display.get_transformed_position (out x, out y);
+            actor_remove (display);
+            actor_add (display, app.stage);
+            display.set_position (x, y);
 
-            /* move box actor to stage */
-            actor.get_transformed_position (out x, out y);
-            if (actor.get_parent () == over_boxes)
-                over_boxes.remove_actor (actor);
-            if (actor.get_parent () != app.stage)
-                app.stage.add_actor (actor);
-            actor.set_position (x, y);
+            /* make sure the boxes stay where they are */
+            boxes.get_transformed_position (out x, out y);
+            boxes.set_position (x, y);
+            actor_pin (boxes);
+            margin.remove_constraint_by_name ("boxes-left");
+            margin.remove_constraint_by_name ("boxes-bottom");
 
             app.current_item.ui_state = UIState.DISPLAY;
 
@@ -53,15 +53,22 @@ private class Boxes.CollectionView: Boxes.UI {
         }
 
         case UIState.COLLECTION:
+            if (app.current_item != null) {
+                actor_remove (app.current_item.actor);
+                add_item (app.current_item);
+            }
+
+            /* follow main table layout again */
+            actor_unpin (boxes);
+            boxes.set_position (15f, 15f);
+            margin.add_constraint_with_name ("boxes-left",
+                                             new Clutter.SnapConstraint (app.stage, SnapEdge.RIGHT, SnapEdge.RIGHT, 0));
+            margin.add_constraint_with_name ("boxes-bottom",
+                                             new Clutter.SnapConstraint (app.stage, SnapEdge.BOTTOM, SnapEdge.RIGHT.BOTTOM, 0));
+            /* normal flow items */
             boxes.set_layout_manager (layout);
 
-            if (app.current_item == null)
-                break;
-
-            var actor = app.current_item.actor;
-            if (actor.get_parent () == over_boxes)
-                over_boxes.remove_actor (actor);
-            add_item (app.current_item);
+            actor_remove (over_boxes);
 
             break;
 
@@ -74,6 +81,7 @@ private class Boxes.CollectionView: Boxes.UI {
         if (item is Machine) {
             var machine = item as Machine;
 
+            message ("add");
             machine.machine_actor.ui_state = UIState.COLLECTION;
             actor_add (machine.actor, boxes);
         } else
@@ -93,24 +101,26 @@ private class Boxes.CollectionView: Boxes.UI {
     private void setup_view () {
         layout = new Clutter.FlowLayout (Clutter.FlowOrientation.HORIZONTAL);
         margin = new Clutter.Group ();
+        margin.set_clip_to_allocation (true);
+        /* this helps to keep the app table inside the window, otherwise, it allocated large */
+        margin.set_size (1f, 1f);
+
         boxes = new Clutter.Box (layout);
         layout.set_column_spacing (35);
         layout.set_row_spacing (25);
         margin.add (boxes);
         app.box.pack (margin, "column", 1, "row", 1, "x-expand", true, "y-expand", true);
 
-        boxes.set_position (15f, 15f);
         boxes.add_constraint_with_name ("boxes-width",
                                         new Clutter.BindConstraint (margin, BindCoordinate.WIDTH, -25f));
         boxes.add_constraint_with_name ("boxes-height",
                                         new Clutter.BindConstraint (margin, BindCoordinate.HEIGHT, -25f));
-        // FIXME! report bug to clutter about flow inside table
-        margin.add_constraint_with_name ("boxes-left",
-                                         new Clutter.SnapConstraint (app.stage, SnapEdge.RIGHT, SnapEdge.RIGHT, 0));
-        margin.add_constraint_with_name ("boxes-bottom",
-                                         new Clutter.SnapConstraint (app.stage, SnapEdge.BOTTOM, SnapEdge.RIGHT.BOTTOM, 0));
 
         over_boxes = new Clutter.Box (new Clutter.BinLayout (Clutter.BinAlignment.FILL, Clutter.BinAlignment.FILL));
+        over_boxes.add_constraint_with_name ("top-box-size",
+                                             new Clutter.BindConstraint (margin, BindCoordinate.SIZE, 0));
+        over_boxes.add_constraint_with_name ("top-box-position",
+                                             new Clutter.BindConstraint (margin, BindCoordinate.POSITION, 0));
 
         app.state.set_key (null, "creds", boxes, "opacity", AnimationMode.EASE_OUT_QUAD, (uint) 0, 0, 0);
         app.state.set_key (null, "display", boxes, "opacity", AnimationMode.EASE_OUT_QUAD, (uint) 0, 0, 0);
diff --git a/src/machine.vala b/src/machine.vala
index 112da4a..6d07188 100644
--- a/src/machine.vala
+++ b/src/machine.vala
@@ -19,7 +19,34 @@ private class Boxes.Machine: Boxes.CollectionItem {
         }
     }
 
-    private Display display;
+    private ulong show_id;
+    private ulong disconnected_id;
+
+    private Display? _display;
+    private Display? display {
+        get { return _display; }
+        set {
+            if (_display != null) {
+                _display.disconnect (show_id);
+                _display.disconnect (disconnected_id);
+            }
+
+            _display = value;
+
+            show_id = _display.show.connect ((id) => {
+                app.ui_state = Boxes.UIState.DISPLAY;
+                try {
+                    machine_actor.show_display (display.get_display (0));
+                } catch (Boxes.Error error) {
+                    warning (error.message);
+                }
+            });
+
+            disconnected_id = _display.disconnected.connect (() => {
+                app.ui_state = Boxes.UIState.COLLECTION;
+            });
+        }
+    }
 
     public Machine (Boxes.App app, GVir.Domain domain) {
         this.domain = domain;
@@ -34,19 +61,6 @@ private class Boxes.Machine: Boxes.CollectionItem {
 
             return true;
         });
-
-        app.state.completed.connect ( () => {
-            if (app.state.state == "display") {
-                if (app.current_item != this)
-                    return;
-
-                try {
-                    machine_actor.show_display (display.get_display (0));
-                } catch (Boxes.Error error) {
-                    warning (error.message);
-                }
-            }
-        });
     }
 
     public async bool take_screenshot () throws GLib.Error {
@@ -163,14 +177,6 @@ private class Boxes.Machine: Boxes.CollectionItem {
 
             return;
         }
-
-        display.show.connect ((id) => {
-            app.ui_state = Boxes.UIState.DISPLAY;
-        });
-
-        display.disconnected.connect (() => {
-            app.ui_state = Boxes.UIState.COLLECTION;
-        });
     }
 
     public override void ui_state_changed () {
@@ -183,7 +189,8 @@ private class Boxes.MachineActor: Boxes.UI {
     public Clutter.Box box;
 
     private GtkClutter.Texture screenshot;
-    private GtkClutter.Actor gtkactor;
+    public GtkClutter.Actor gtk_vbox;
+    public GtkClutter.Actor gtk_display;
     private Gtk.Label label;
     private Gtk.VBox vbox; // and the vbox under it
     private Gtk.Entry entry;
@@ -205,18 +212,18 @@ private class Boxes.MachineActor: Boxes.UI {
         screenshot.keep_aspect_ratio = true;
 
         vbox = new Gtk.VBox (false, 0);
-        gtkactor = new GtkClutter.Actor.with_contents (vbox);
+        gtk_vbox = new GtkClutter.Actor.with_contents (vbox);
         label = new Gtk.Label (machine.name);
         vbox.add (label);
         entry = new Gtk.Entry ();
         entry.set_visibility (false);
-        entry.set_placeholder_text (_("Password")); // TODO: i18n stupid vala...
+        entry.set_placeholder_text (_("Password"));
         vbox.add (entry);
 
         vbox.show_all ();
         entry.hide ();
 
-        actor_add (gtkactor, box);
+        actor_add (gtk_vbox, box);
     }
 
     public void scale_screenshot (float scale = 1.5f) {
@@ -233,23 +240,29 @@ private class Boxes.MachineActor: Boxes.UI {
             return;
         }
 
-        actor_remove (screenshot);
-
+        /* before display was in the vbox, but there are scaling issues, so now on stage */
         this.display = display;
-        vbox.add (display);
-
+        gtk_display = new GtkClutter.Actor.with_contents (display);
+        gtk_display.add_constraint_with_name ("display-fs", new Clutter.BindConstraint (machine.app.stage, BindCoordinate.SIZE, 0));
         display.show ();
-        display.grab_focus ();
+
+        // FIXME: there is flickering if we show it without delay
+        // where does this rendering delay come from?
+        Timeout.add (Boxes.App.duration, () => {
+            machine.app.stage.add (gtk_display);
+            gtk_display.grab_key_focus ();
+            display.grab_focus ();
+            return false;
+        });
     }
 
     public void hide_display () {
         if (display == null)
             return;
 
-        vbox.remove (display);
+        actor_remove (gtk_display);
         display = null;
-
-        box.pack_at (screenshot, 0);
+        gtk_display = null;
     }
 
     public override void ui_state_changed () {
@@ -275,7 +288,6 @@ private class Boxes.MachineActor: Boxes.UI {
             actor.animate (Clutter.AnimationMode.LINEAR, Boxes.App.duration,
                            "x", 0.0f,
                            "y", 0.0f);
-
             break;
         }
 
diff --git a/src/sidebar.vala b/src/sidebar.vala
index 176d368..d3db182 100644
--- a/src/sidebar.vala
+++ b/src/sidebar.vala
@@ -35,7 +35,7 @@ private class Boxes.Sidebar: Boxes.UI {
 
     public override void ui_state_changed () {
         if (ui_state == UIState.DISPLAY)
-            pin_actor (actor);
+            actor_pin (actor);
     }
 
     private void list_append (ListStore listmodel,
diff --git a/src/topbar.vala b/src/topbar.vala
index 3fa5ed6..12481d4 100644
--- a/src/topbar.vala
+++ b/src/topbar.vala
@@ -91,7 +91,7 @@ private class Boxes.Topbar: Boxes.UI {
             break;
 
         case UIState.DISPLAY:
-            pin_actor (gtk_actor);
+            actor_pin (gtk_actor);
             break;
 
         default:
diff --git a/src/util.vala b/src/util.vala
index 139cca7..39b6b19 100644
--- a/src/util.vala
+++ b/src/util.vala
@@ -102,7 +102,12 @@ namespace Boxes {
         container.remove (actor);
     }
 
-    private void pin_actor (Clutter.Actor actor) {
+    private void actor_pin (Clutter.Actor actor) {
         actor.set_geometry (actor.get_geometry ());
     }
+
+    private void actor_unpin (Clutter.Actor actor) {
+        actor.set_size (-1, -1);
+        actor.set_position (-1, -1);
+    }
 }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]