[gnome-shell/T27795: 86/138] Adapt the grid's size when ViewsDisplayContainer changes its allocation



commit eb7b07c41464578185b57b3bcef5ed3c12574cb2
Author: Mario Sanchez Prada <mario endlessm com>
Date:   Wed Jun 14 12:18:43 2017 +0100

    Adapt the grid's size when ViewsDisplayContainer changes its allocation
    
    In upstream's code, the AppDisplay's actor is the topmost container in
    the APPS page, controlled by ViewsSelector, so it made sense to connect
    to changes in the allocation of it to adapt its internal parameters used
    to compute the number of rows and dimensions of the internal actors, as
    such allocation would basically be the maximum available space in the
    screen to show the applications grid.
    
    However, in EOS we pack the AppDisplay's actor inside another container
    that will also hold the search entry widget and the search results page,
    meaning that the allocation of all those things (including the AppDisplay's
    actor that contains the grid) is now performed via a custom layout manager
    and so connecting to the allocation-changed signal at that level won't be
    right, since it will be triggered anytime we manually allocate AppDisplay,
    causing a chicken-egg situation since we need to allocate it to know the
    preferred height of it, and we need the preferred height of it to assign
    the right allocation considering the search box and the results page.
    
    The solution to this is to move the emission of the allocation-changed
    signal from the AppDisplay's top (container) actor to the new container
    that now owns AppDisplay, and which will now be added as the topmost
    actor in the APPs page of ViewsSelector. By doing this, we only get
    the allocation-changed signal emmitted when the allocation of the actual
    page changes (e.g. resolution change) and not each time we manually
    allocate the AppDisplay from the custom layout manager.
    
    https://phabricator.endlessm.com/T17230
    https://phabricator.endlessm.com/T17840

 js/ui/appDisplay.js   | 35 +++++++----------------------------
 js/ui/viewSelector.js | 37 ++++++++++++++++++++++++++++++++++---
 2 files changed, 41 insertions(+), 31 deletions(-)
---
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
index 7b9c6a512d..5715e256e1 100644
--- a/js/ui/appDisplay.js
+++ b/js/ui/appDisplay.js
@@ -877,29 +877,16 @@ class ControlsBoxLayout extends Clutter.BoxLayout {
     }
 });
 
-var ViewStackLayout = GObject.registerClass({
-    Signals: { 'allocated-size-changed': { param_types: [GObject.TYPE_INT,
-                                                         GObject.TYPE_INT] } },
-}, class ViewStackLayout extends Clutter.BinLayout {
-    vfunc_allocate(actor, box, flags) {
-        let availWidth = box.x2 - box.x1;
-        let availHeight = box.y2 - box.y1;
-        // Prepare children of all views for the upcoming allocation, calculate all
-        // the needed values to adapt available size
-        this.emit('allocated-size-changed', availWidth, availHeight);
-        super.vfunc_allocate(actor, box, flags);
-    }
-});
-
 var AppDisplay = class AppDisplay {
     constructor() {
         this._privacySettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.privacy' });
         this._allView = new AllView();
 
-        let viewStackLayout = new ViewStackLayout();
-        this.actor = new St.Widget({ x_expand: true, y_expand: true,
-                                     layout_manager: viewStackLayout });
-        viewStackLayout.connect('allocated-size-changed', this._onAllocatedSizeChanged.bind(this));
+        this.actor = new St.Widget({
+            x_expand: true,
+            y_expand: true,
+            layout_manager: new Clutter.BinLayout(),
+        });
 
         this.actor.add_actor(this._allView.actor);
         this._showView();
@@ -918,16 +905,8 @@ var AppDisplay = class AppDisplay {
         this._allView.view.selectApp(id);
     }
 
-    _onAllocatedSizeChanged(actor, width, height) {
-        let box = new Clutter.ActorBox();
-        box.x1 = box.y1 = 0;
-        box.x2 = width;
-        box.y2 = height;
-        box = this.actor.get_theme_node().get_content_box(box);
-        let availWidth = box.x2 - box.x1;
-        let availHeight = box.y2 - box.y1;
-
-        this._allView.adaptToSize(availWidth, availHeight);
+    adaptToSize(width, height) {
+        return this._allView.adaptToSize(width, height);
     }
 };
 
diff --git a/js/ui/viewSelector.js b/js/ui/viewSelector.js
index 64b12514ef..e99fc8ecf3 100644
--- a/js/ui/viewSelector.js
+++ b/js/ui/viewSelector.js
@@ -129,8 +129,13 @@ var ShowOverviewAction = GObject.registerClass({
     }
 });
 
-var ViewsDisplayLayout = GObject.registerClass(
-class ViewsDisplayLayout extends Clutter.BinLayout {
+var ViewsDisplayLayout = GObject.registerClass({
+    Signals: {
+        'grid-available-size-changed': {
+            param_types: [GObject.TYPE_INT, GObject.TYPE_INT]
+        },
+    },
+}, class ViewsDisplayLayout extends Clutter.BinLayout {
     _init(appDisplayActor) {
         super._init();
 
@@ -141,6 +146,17 @@ class ViewsDisplayLayout extends Clutter.BinLayout {
     _onStyleChanged() {
         this.layout_changed();
     }
+
+    vfunc_allocate(actor, box, flags) {
+        let availWidth = box.x2 - box.x1;
+        let availHeight = box.y2 - box.y1;
+
+        // We want to emit the signal BEFORE any allocation has happened since the
+        // icon grid will need to precompute certain values before being able to
+        // report a sensible preferred height for the specified width.
+        this.emit('grid-available-size-changed', availWidth, availHeight);
+        super.vfunc_allocate(actor, box, flags);
+    }
 });
 
 var ViewsDisplayContainer = GObject.registerClass(
@@ -149,15 +165,30 @@ class ViewsDisplayContainer extends St.Widget {
         this._appDisplay = appDisplay;
         this._activePage = ViewsDisplayPage.APP_GRID;
 
+        let layoutManager = new ViewsDisplayLayout(this._appDisplay.actor);
         super._init({
-            layout_manager: new ViewsDisplayLayout(this._appDisplay.actor),
+            layout_manager: layoutManager,
             x_expand: true,
             y_expand: true,
         });
 
+        layoutManager.connect('grid-available-size-changed', this._onGridAvailableSizeChanged.bind(this));
+
         this.add_actor(this._appDisplay.actor);
     }
 
+    _onGridAvailableSizeChanged(actor, width, height) {
+        let box = new Clutter.ActorBox();
+        box.x1 = box.y1 = 0;
+        box.x2 = width;
+        box.y2 = height;
+        box = this._appDisplay.actor.get_theme_node().get_content_box(box);
+        let availWidth = box.x2 - box.x1;
+        let availHeight = box.y2 - box.y1;
+
+        this._appDisplay.adaptToSize(availWidth, availHeight);
+    }
+
     showPage(page) {
         if (this._activePage === page)
             return;


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