[gnome-shell/wip/gbsneto/actor-tree: 3/3] lookingGlass: Add actor tree inspector
- From: Georges Basile Stavracas Neto <gbsneto src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell/wip/gbsneto/actor-tree: 3/3] lookingGlass: Add actor tree inspector
- Date: Tue, 2 Jun 2020 03:47:26 +0000 (UTC)
commit e0dc18e5f5996a141fca3dff80609d9724081f26
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date: Sun May 31 17:31:48 2020 -0300
lookingGlass: Add actor tree inspector
Being able to visualize the actor tree is a handy feature
to have, specially when debugging the hierarchy.
Add a new "Actors" tab to the Looking Glass with the actor
tree inspector. The tree is cleared on unmap to not get
heavy on the number of actors.
https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1292
.../gnome-shell-sass/widgets/_looking-glass.scss | 7 +
js/ui/lookingGlass.js | 189 +++++++++++++++++++++
2 files changed, 196 insertions(+)
---
diff --git a/data/theme/gnome-shell-sass/widgets/_looking-glass.scss
b/data/theme/gnome-shell-sass/widgets/_looking-glass.scss
index 9c38e63602..006c2ef920 100644
--- a/data/theme/gnome-shell-sass/widgets/_looking-glass.scss
+++ b/data/theme/gnome-shell-sass/widgets/_looking-glass.scss
@@ -1,5 +1,7 @@
/* Looking Glass */
+$text_fg_color: #ccc;
+
// Dialog
#LookingGlassDialog {
background-color: $osd_bg_color;
@@ -52,6 +54,11 @@
&:hover { color: lighten($link_color, 10%); }
&:active { color: darken($link_color, 10%); }
}
+ .actor-link {
+ color: $text_fg_color;
+ &:hover { color: lighten($text_fg_color, 20%); }
+ &:active { color: darken($text_fg_color, 20%); }
+ }
}
.lg-completions-text {
diff --git a/js/ui/lookingGlass.js b/js/ui/lookingGlass.js
index a5d762987c..89f293a83d 100644
--- a/js/ui/lookingGlass.js
+++ b/js/ui/lookingGlass.js
@@ -802,6 +802,192 @@ var Extensions = GObject.registerClass({
}
});
+
+var ActorLink = GObject.registerClass({
+ Signals: {
+ 'inspect-actor': {},
+ },
+}, class ActorLink extends St.Button {
+ _init(actor) {
+ this._arrow = new St.Icon({
+ icon_name: 'pan-end-symbolic',
+ icon_size: 8,
+ x_align: Clutter.ActorAlign.CENTER,
+ y_align: Clutter.ActorAlign.CENTER,
+ pivot_point: new Graphene.Point({ x: 0.5, y: 0.5 }),
+ });
+
+ const label = new St.Label({
+ text: actor.toString(),
+ x_align: Clutter.ActorAlign.START,
+ });
+
+ const inspectButton = new St.Button({
+ child: new St.Icon({
+ icon_name: 'insert-object-symbolic',
+ icon_size: 12,
+ y_align: Clutter.ActorAlign.CENTER,
+ }),
+ reactive: true,
+ x_expand: true,
+ x_align: Clutter.ActorAlign.START,
+ y_align: Clutter.ActorAlign.CENTER,
+ });
+ inspectButton.connect('clicked', () => this.emit('inspect-actor'));
+
+ const box = new St.BoxLayout();
+ box.add_child(this._arrow);
+ box.add_child(label);
+ box.add_child(inspectButton);
+
+ super._init({
+ reactive: true,
+ track_hover: true,
+ toggle_mode: true,
+ style_class: 'actor-link',
+ child: box,
+ x_align: Clutter.ActorAlign.START,
+ });
+ this.get_child().single_line_mode = true;
+
+ this._actor = actor;
+ }
+
+ vfunc_clicked() {
+ this._arrow.ease({
+ rotation_angle_z: this.checked ? 90 : 0,
+ duration: 250,
+ });
+ }
+});
+
+var ActorTreeViewer = GObject.registerClass(
+class ActorTreeViewer extends St.BoxLayout {
+ _init(lookingGlass) {
+ super._init();
+
+ this._lookingGlass = lookingGlass;
+ this._actorData = new Map();
+ }
+
+ _showActorChildren(actor) {
+ const data = this._actorData.get(actor);
+ if (!data || data.visible)
+ return;
+
+ data.visible = true;
+ data.actorAddedId = actor.connect('actor-added', (container, child) => {
+ this._addActor(data.childrenContainer, child);
+ });
+ data.actorRemovedId = actor.connect('actor-removed', (container, child) => {
+ this._removeActor(child);
+ });
+
+ for (let child of actor)
+ this._addActor(data.children, child);
+ }
+
+ _hideActorChildren(actor) {
+ const data = this._actorData.get(actor);
+ if (!data || !data.visible)
+ return;
+
+ for (let child of actor)
+ this._removeActor(child);
+
+ data.visible = false;
+ if (data.actorAddedId > 0) {
+ actor.disconnect(data.actorAddedId);
+ data.actorAddedId = 0;
+ }
+ if (data.actorRemovedId > 0) {
+ actor.disconnect(data.actorRemovedId);
+ data.actorRemovedId = 0;
+ }
+ data.children.remove_all_children();
+ }
+
+ _addActor(container, actor) {
+ if (this._actorData.has(actor))
+ return;
+
+ if (actor === this._lookingGlass)
+ return;
+
+ const button = new ActorLink(actor);
+ button.connect('notify::checked', () => {
+ this._lookingGlass.setBorderPaintTarget(actor);
+ if (button.checked)
+ this._showActorChildren(actor);
+ else
+ this._hideActorChildren(actor);
+ });
+ button.connect('inspect-actor', () => {
+ this._lookingGlass.inspectObject(actor, button);
+ });
+
+ const mainContainer = new St.BoxLayout({ vertical: true });
+ const childrenContainer = new St.BoxLayout({
+ vertical: true,
+ style: 'padding: 0 0 0 18px',
+ });
+
+ mainContainer.add_child(button);
+ mainContainer.add_child(childrenContainer);
+
+ this._actorData.set(actor, {
+ button,
+ container: mainContainer,
+ children: childrenContainer,
+ visible: false,
+ actorAddedId: 0,
+ actorRemovedId: 0,
+ actorDestroyedId: actor.connect('destroy', () => this._removeActor(actor)),
+ });
+
+ let belowChild = null;
+ const nextSibling = actor.get_next_sibling();
+ if (nextSibling && this._actorData.has(nextSibling))
+ belowChild = this._actorData.get(nextSibling).container;
+
+ container.insert_child_above(mainContainer, belowChild);
+ }
+
+ _removeActor(actor) {
+ const data = this._actorData.get(actor);
+ if (!data)
+ return;
+
+ for (let child of actor)
+ this._removeActor(child);
+
+ if (data.actorAddedId > 0) {
+ actor.disconnect(data.actorAddedId);
+ data.actorAddedId = 0;
+ }
+ if (data.actorRemovedId > 0) {
+ actor.disconnect(data.actorRemovedId);
+ data.actorRemovedId = 0;
+ }
+ if (data.actorDestroyedId > 0) {
+ actor.disconnect(data.actorDestroyedId);
+ data.actorDestroyedId = 0;
+ }
+ data.container.destroy();
+ this._actorData.delete(actor);
+ }
+
+ vfunc_map() {
+ super.vfunc_map();
+ this._addActor(this, global.stage);
+ }
+
+ vfunc_unmap() {
+ super.vfunc_unmap();
+ this._removeActor(global.stage);
+ }
+});
+
var LookingGlass = GObject.registerClass(
class LookingGlass extends St.BoxLayout {
_init() {
@@ -917,6 +1103,9 @@ class LookingGlass extends St.BoxLayout {
this._extensions = new Extensions(this);
notebook.appendPage('Extensions', this._extensions);
+ this._actorTreeViewer = new ActorTreeViewer(this);
+ notebook.appendPage('Actors', this._actorTreeViewer);
+
this._entry.clutter_text.connect('activate', (o, _e) => {
// Hide any completions we are currently showing
this._hideCompletions();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]