Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- The setup:
- An indicator in the panel (Shell.GenericContainer), containing
- - workspaces (St.Bin containing a St.Group/St.Widget (depending on GNOME 3.2 or 3.4))
- containing:
- - windows (St.Bin)
- The window St.Bins adjust their size/position with their actual windows, and although this works, I **do not see the St.Bins move accordingly unless I call queue_relayout() on the Shell.GenericContainer**. Calling .queue_relayout() on anything else has no effect, and ommitting any .queue_relayout() call also has no effect (i.e. St.Bin doesn't move).
- To demonstrate this I've called .queue_relayout() on the size-changed signal and not called it in the position-changed signal, so when you move windows around you will not see the St.Bins move, but when you change their size the St.Bins will be updated. (in the WindowClone class)
- How can I fix this? I shouldn't have to store a pointer to the SHell.GenericContainer *within* the lowest-level St.Bin simply to call .queue_relayout?
- */
- ///// CODE ////
- const Lang = imports.lang;
- const Mainloop = imports.mainloop;
- const Shell = imports.gi.Shell;
- const St = imports.gi.St;
- const Main = imports.ui.main;
- const PanelMenu = imports.ui.panelMenu;
- /* Compatibility for dev version (remove later) */
- const StGroup = St.Group || St.Widget;
- /* Extension variables */
- let indicator;
- // the indicator in the top panel
- function WorkspaceApplet() {
- this._init.apply(this, arguments);
- }
- WorkspaceApplet.prototype = {
- __proto__: PanelMenu.Button.prototype,
- _init: function () {
- PanelMenu.Button.prototype._init.call(this,
- St.Align.START, // menu alignment
- 'workspace-inicator' // text
- );
- this._container = new Shell.GenericContainer({
- reactive: true
- });
- this._container.connect('get-preferred-width',
- Lang.bind(this, this._getPreferredWidth));
- this._container.connect('get-preferred-height',
- Lang.bind(this, this._getPreferredHeight));
- this._container.connect('allocate', Lang.bind(this, this._allocate));
- this.actor.add_actor(this._container);
- // add a "workspace" actor.
- let workspace = new WorkspaceThumbnail(0);
- this._container.add_actor(workspace.actor);
- },
- //// allocation ////
- _getPreferredHeight: function (actor, forWidth, alloc) {
- alloc.min_size = alloc.natural_size = Main.panel.actor.height;
- },
- _getPreferredWidth: function (actor, forHeight, alloc) {
- alloc.min_size = alloc.natural_size = Main.panel.actor.height * global.stage.width / global.stage.height;
- },
- _allocate: function (actor, box, flags) {
- let children = this._container.get_children();
- // just allocate the whole space
- children[0].allocate(box, flags);
- }
- };
- // represents a workspace, contains up-to-date snapshot of window.
- function WorkspaceThumbnail() {
- this._init.apply(this, arguments);
- }
- WorkspaceThumbnail.prototype = {
- _init: function (index) {
- this._index = index;
- this.workspace = global.screen.get_workspace_by_index(index);
- this.actor = new St.Bin({
- track_hover: true,
- reactive: true
- });
- this.actor.style = 'border: 1px solid white; background: #888888'; // so we can see
- this.actor._delegate = this;
- // need to hold many windows
- this._workspace = new StGroup({
- clip_to_allocation: true
- });
- this.actor.child = this._workspace;
- this.workspace.connect('window-added', Lang.bind(this, this._onWindowAdded));
- },
- _onWindowAdded: function (ws, win) {
- let winActor = win.get_compositor_private();
- if (!winActor) {
- Mainloop.idle_add(Lang.bind(this, function () {
- this._onWindowAdded(ws, win);
- }));
- } else {
- // window has an actor, make a clone for it.
- log('making clone of window ' + win.get_title());
- let clone = new WindowClone(winActor);
- this._workspace.add_actor(clone.actor);
- }
- },
- };
- // one per window
- function WindowClone() {
- this._init.apply(this, arguments);
- }
- WindowClone.prototype = {
- _init: function (winActor) {
- this.actor = new St.Bin({
- x_fill: false,
- y_fill: false,
- x_align: St.Align.MIDDLE,
- y_align: St.Align.MIDDLE
- });
- this.actor._delegate = this;
- this.actor.style = 'border: 1px solid white; background: #cecece'; // so we can see
- this.winActor = winActor;
- this.metaWindow = winActor.meta_window;
- // we could use .set_scale but that makes it not as easy to
- // style the St.Bin (e.g. if border width is 1 and we use a scale
- // factor on the actor, we won't see the border at all)
- // hard code scale for now; in reality it is based off the WorkspaceThumbnail's
- // width/height.
- this._scale = Main.panel.actor.height / global.stage.height;
- if (!this.actor.realized) {
- let onetime = this.actor.connect('notify::realized',
- Lang.bind(this, function () {
- if (this.actor.realized) {
- this.actor.disconnect(onetime);
- this.init();
- }
- }));
- } else {
- this.init();
- }
- },
- init: function () {
- this.winActor.connect('position-changed', Lang.bind(this, this._onPositionChanged));
- this.winActor.connect('size-changed', Lang.bind(this, this._onSizeChanged));
- this._grandaddy = indicator.actor;
- this._onPositionChanged();
- this._onSizeChanged();
- },
- _onPositionChanged: function () {
- // update our position
- let rect = this.metaWindow.get_outer_rect(),
- newx = Math.round(rect.x * this._scale),
- newy = Math.round(rect.y * this._scale);
- if (this.actor.x === newx && this.actor.y === newy) {
- return;
- }
- // log('new position %d, %d'.format(newx, newy));
- this.actor.x = newx;
- this.actor.y = newy;
- // NOTE !! If I don't include the following line, the thumbnail
- // will not update !! why is this?
- // this.actor.queue_relayout, this.parent.queue_relayout all do
- // *not* cause the thumbnail to update.
- /* // uncomment the following to make it work
- if (this._grandaddy) {
- this._grandaddy.queue_relayout();
- }
- */
- },
- _onSizeChanged: function () {
- let rect = this.metaWindow.get_outer_rect(),
- newwid = Math.round(rect.width * this._scale),
- newh = Math.round(rect.height * this._scale);
- if (this.actor.width === newwid && this.actor.height === newh) {
- return;
- }
- // log('new size %dx%d'.format(newwid, newh));
- this.actor.width = newwid;
- this.actor.height = newh;
- // NOTE !! If I don't include the following line, the thumbnail
- // will not update !! why is this?
- // this.actor.queue_relayout, this.parent.queue_relayout all do
- // *not* cause the thumbnail to update.
- if (this._grandaddy) {
- this._grandaddy.queue_relayout();
- }
- }
- };
- /** Extension code **/
- function init(metadata) {
- }
- function enable() {
- indicator = new WorkspaceApplet();
- Main.panel.addToStatusArea('graphical-workspace-indicator', indicator);
- }
- function disable() {
- indicator = null;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement