diff --git a/js/ui/workspace.js b/js/ui/workspace.js index 34c0b1f0c..868f91bc9 100644 --- a/js/ui/workspace.js +++ b/js/ui/workspace.js @@ -94,15 +94,25 @@ class WindowCloneLayout extends Clutter.LayoutManager { } }); -var WindowClone = class { - constructor(realWindow, workspace) { +var WindowClone = GObject.registerClass({ + Signals: { + 'drag-begin': {}, + 'drag-cancelled': {}, + 'drag-end': {}, + 'hide-chrome': {}, + 'selected': { param_types: [GObject.TYPE_UINT] }, + 'show-chrome': {}, + 'size-changed': {} + }, +}, class WindowClone extends St.Widget { + _init(realWindow, workspace) { this.realWindow = realWindow; this.metaWindow = realWindow.meta_window; this.metaWindow._delegate = this; this._workspace = workspace; this._windowClone = new Clutter.Clone({ source: realWindow }); - // We expect this.actor to be used for all interaction rather than + // We expect this to be used for all interaction rather than // this._windowClone; as the former is reactive and the latter // is not, this just works for most cases. However, for DND all // actors are picked, so DND operations would operate on the clone. @@ -113,14 +123,16 @@ var WindowClone = class { // the invisible border; this is inconvenient; rather than trying // to compensate all over the place we insert a ClutterActor into // the hierarchy that is sized to only the visible portion. - this.actor = new St.Widget({ reactive: true, - can_focus: true, - accessible_role: Atk.Role.PUSH_BUTTON, - layout_manager: new WindowCloneLayout() }); + super._init({ + reactive: true, + can_focus: true, + accessible_role: Atk.Role.PUSH_BUTTON, + layout_manager: new WindowCloneLayout() + }); - this.actor.add_child(this._windowClone); + this.add_child(this._windowClone); - this.actor._delegate = this; + this._delegate = this; this.slotId = 0; this._slot = [0, 0, 0, 0]; @@ -142,23 +154,23 @@ var WindowClone = class { this._updateAttachedDialogs(); this._computeBoundingBox(); - this.actor.x = this._boundingBox.x; - this.actor.y = this._boundingBox.y; + this.x = this._boundingBox.x; + this.y = this._boundingBox.y; let clickAction = new Clutter.ClickAction(); clickAction.connect('clicked', this._onClicked.bind(this)); clickAction.connect('long-press', this._onLongPress.bind(this)); - this.actor.add_action(clickAction); - this.actor.connect('destroy', this._onDestroy.bind(this)); - this.actor.connect('key-press-event', this._onKeyPress.bind(this)); + this.add_action(clickAction); + this.connect('destroy', this._onDestroy.bind(this)); + this.connect('key-press-event', this._onKeyPress.bind(this)); - this.actor.connect('enter-event', () => this.emit('show-chrome')); - this.actor.connect('key-focus-in', () => this.emit('show-chrome')); + this.connect('enter-event', () => this.emit('show-chrome')); + this.connect('key-focus-in', () => this.emit('show-chrome')); - this.actor.connect('leave-event', () => this.emit('hide-chrome')); - this.actor.connect('key-focus-out', () => this.emit('hide-chrome')); + this.connect('leave-event', () => this.emit('hide-chrome')); + this.connect('key-focus-out', () => this.emit('hide-chrome')); - this._draggable = DND.makeDraggable(this.actor, + this._draggable = DND.makeDraggable(this, { restoreOnSuccess: true, manualMode: true, dragActorMaxSize: WINDOW_DND_SIZE, @@ -185,7 +197,7 @@ var WindowClone = class { deleteAll() { // Delete all windows, starting from the bottom-most (most-modal) one - let windows = this.actor.get_children(); + let windows = this.get_children(); for (let i = windows.length - 1; i >= 1; i--) { let realWindow = windows[i].source; let metaWindow = realWindow.meta_window; @@ -215,7 +227,7 @@ var WindowClone = class { } hasAttachedDialogs() { - return this.actor.get_n_children() > 1; + return this.get_n_children() > 1; } _doAddAttachedDialog(metaWin, realWin) { @@ -229,7 +241,7 @@ var WindowClone = class { this._onMetaWindowSizeChanged(); }); - this.actor.add_child(clone); + this.add_child(clone); } _updateAttachedDialogs() { @@ -267,7 +279,7 @@ var WindowClone = class { _computeBoundingBox() { let rect = this.metaWindow.get_frame_rect(); - this.actor.get_children().forEach(child => { + this.get_children().forEach(child => { let realWindow; if (child == this._windowClone) realWindow = this.realWindow; @@ -280,7 +292,7 @@ var WindowClone = class { // Convert from a MetaRectangle to a native JS object this._boundingBox = { x: rect.x, y: rect.y, width: rect.width, height: rect.height }; - this.actor.layout_manager.boundingBox = rect; + this.layout_manager.boundingBox = rect; } // Find the actor just below us, respecting reparenting done by DND code @@ -306,17 +318,13 @@ var WindowClone = class { let actualAbove = this.getActualStackAbove(); if (actualAbove == null) - this.actor.lower_bottom(); + this.lower_bottom(); else - this.actor.raise(actualAbove); - } - - destroy() { - this.actor.destroy(); + this.raise(actualAbove); } _disconnectSignals() { - this.actor.get_children().forEach(child => { + this.get_children().forEach(child => { let realWindow; if (child == this._windowClone) realWindow = this.realWindow; @@ -338,14 +346,12 @@ var WindowClone = class { this._disconnectSignals(); this.metaWindow._delegate = null; - this.actor._delegate = null; + this._delegate = null; if (this.inDrag) { this.emit('drag-end'); this.inDrag = false; } - - this.disconnectAll(); } _activate() { @@ -393,8 +399,8 @@ var WindowClone = class { _onDragBegin(draggable, time) { this._dragSlot = this._slot; - [this.dragOrigX, this.dragOrigY] = this.actor.get_position(); - this.dragOrigScale = this.actor.scale_x; + [this.dragOrigX, this.dragOrigY] = this.get_position(); + this.dragOrigScale = this.scale_x; this.inDrag = true; this.emit('drag-begin'); } @@ -417,18 +423,17 @@ var WindowClone = class { // We may not have a parent if DnD completed successfully, in // which case our clone will shortly be destroyed and replaced // with a new one on the target workspace. - if (this.actor.get_parent() != null) { + if (this.get_parent() != null) { if (this._stackAbove == null) - this.actor.lower_bottom(); + this.lower_bottom(); else - this.actor.raise(this._stackAbove); + this.raise(this._stackAbove); } this.emit('drag-end'); } -}; -Signals.addSignalMethods(WindowClone.prototype); +}); /** @@ -452,7 +457,7 @@ var WindowOverlay = class { this.title = new St.Label({ style_class: 'window-caption', text: this._getCaption() }); this.title.clutter_text.ellipsize = Pango.EllipsizeMode.END; - windowClone.actor.label_actor = this.title; + windowClone.label_actor = this.title; this._maxTitleWidth = -1; @@ -467,7 +472,7 @@ var WindowOverlay = class { this.closeButton.connect('clicked', () => this._windowClone.deleteAll()); - windowClone.actor.connect('destroy', this._onDestroy.bind(this)); + windowClone.connect('destroy', this._onDestroy.bind(this)); windowClone.connect('show-chrome', this._onShowChrome.bind(this)); windowClone.connect('hide-chrome', this._onHideChrome.bind(this)); @@ -503,7 +508,7 @@ var WindowOverlay = class { show() { this._hidden = false; - if (this._windowClone.actor['has-pointer']) + if (this._windowClone['has-pointer']) this._animateVisible(); } @@ -675,7 +680,7 @@ var WindowOverlay = class { _idleHideOverlay() { this._idleHideOverlayId = 0; - if (!this._windowClone.actor['has-pointer'] && + if (!this._windowClone['has-pointer'] && !this.closeButton['has-pointer']) this._animateInvisible(); @@ -1296,8 +1301,8 @@ var Workspace = class { if (clone.inDrag) continue; - let cloneWidth = clone.actor.width * scale; - let cloneHeight = clone.actor.height * scale; + let cloneWidth = clone.width * scale; + let cloneHeight = clone.height * scale; clone.slot = [x, y, cloneWidth, cloneHeight]; let cloneCenter = x + cloneWidth / 2; @@ -1312,10 +1317,10 @@ var Workspace = class { if (!clone.positioned) { // This window appeared after the overview was already up // Grow the clone from the center of the slot - clone.actor.x = x + cloneWidth / 2; - clone.actor.y = y + cloneHeight / 2; - clone.actor.scale_x = 0; - clone.actor.scale_y = 0; + clone.x = x + cloneWidth / 2; + clone.y = y + cloneHeight / 2; + clone.scale_x = 0; + clone.scale_y = 0; clone.positioned = true; } @@ -1325,14 +1330,14 @@ var Workspace = class { * therefore we need to resize them now so they * can be scaled up later */ if (initialPositioning) { - clone.actor.opacity = 0; - clone.actor.scale_x = 0; - clone.actor.scale_y = 0; - clone.actor.x = x; - clone.actor.y = y; + clone.opacity = 0; + clone.scale_x = 0; + clone.scale_y = 0; + clone.x = x; + clone.y = y; } - Tweener.addTween(clone.actor, + Tweener.addTween(clone, { opacity: 255, time: Overview.ANIMATION_TIME, transition: 'easeInQuad' @@ -1342,10 +1347,10 @@ var Workspace = class { this._animateClone(clone, clone.overlay, x, y, scale); } else { // cancel any active tweens (otherwise they might override our changes) - Tweener.removeTweens(clone.actor); - clone.actor.set_position(x, y); - clone.actor.set_scale(scale, scale); - clone.actor.set_opacity(255); + Tweener.removeTweens(clone); + clone.set_position(x, y); + clone.set_scale(scale, scale); + clone.set_opacity(255); clone.overlay.relayout(false); this._showWindowOverlay(clone, clone.overlay); } @@ -1366,13 +1371,13 @@ var Workspace = class { clone.setStackAbove(this._dropRect); } else { let previousClone = clones[i - 1]; - clone.setStackAbove(previousClone.actor); + clone.setStackAbove(previousClone); } } } _animateClone(clone, overlay, x, y, scale) { - Tweener.addTween(clone.actor, + Tweener.addTween(clone, { x: x, y: y, scale_x: scale, @@ -1411,7 +1416,7 @@ var Workspace = class { let actorUnderPointer = global.stage.get_actor_at_pos(Clutter.PickMode.REACTIVE, x, y); for (let i = 0; i < this._windows.length; i++) { - if (this._windows[i].actor == actorUnderPointer) + if (this._windows[i] == actorUnderPointer) return GLib.SOURCE_CONTINUE; } @@ -1433,12 +1438,12 @@ var Workspace = class { // destroyed; we'd like to animate this, but it's too late at // this point.) if (win) { - let [stageX, stageY] = clone.actor.get_transformed_position(); - let [stageWidth, stageHeight] = clone.actor.get_transformed_size(); + let [stageX, stageY] = clone.get_transformed_position(); + let [stageWidth, stageHeight] = clone.get_transformed_size(); win._overviewHint = { x: stageX, y: stageY, - scale: stageWidth / clone.actor.width + scale: stageWidth / clone.width }; } clone.destroy(); @@ -1518,11 +1523,11 @@ var Workspace = class { let scale = win._overviewHint.scale; delete win._overviewHint; - clone.slot = [x, y, clone.actor.width * scale, clone.actor.height * scale]; + clone.slot = [x, y, clone.width * scale, clone.height * scale]; clone.positioned = true; - clone.actor.set_position(x, y); - clone.actor.set_scale(scale, scale); + clone.set_position(x, y); + clone.set_scale(scale, scale); clone.overlay.relayout(false); } @@ -1596,7 +1601,7 @@ var Workspace = class { let overlay = this._windowOverlays[i]; if (overlay) overlay.hide(); - this._windows[i].actor.opacity = 0; + this._windows[i].opacity = 0; } else { let fromTop = topIndex - i; let time; @@ -1605,7 +1610,7 @@ var Workspace = class { else time = windowBaseTime; - this._windows[i].actor.opacity = 255; + this._windows[i].opacity = 255; this._fadeWindow(i, time, 0); } } @@ -1619,7 +1624,7 @@ var Workspace = class { for (let i = 0; i < this._windows.length; i++) { let clone = this._windows[i]; - Tweener.removeTweens(clone.actor); + Tweener.removeTweens(clone); } if (this._repositionWindowsId > 0) { @@ -1654,7 +1659,7 @@ var Workspace = class { let overlay = this._windowOverlays[i]; if (overlay) overlay.hide(); - this._windows[i].actor.opacity = 0; + this._windows[i].opacity = 0; } else { let fromTop = topIndex - i; let time; @@ -1663,7 +1668,7 @@ var Workspace = class { else time = windowBaseTime * nTimeSlots; - this._windows[i].actor.opacity = 0; + this._windows[i].opacity = 0; this._fadeWindow(i, time, 255); } } @@ -1678,18 +1683,18 @@ var Workspace = class { if (clone.metaWindow.showing_on_its_workspace()) { let [origX, origY] = clone.getOriginalPosition(); - clone.actor.scale_x = 1; - clone.actor.scale_y = 1; - clone.actor.x = origX; - clone.actor.y = origY; - Tweener.addTween(clone.actor, + clone.scale_x = 1; + clone.scale_y = 1; + clone.x = origX; + clone.y = origY; + Tweener.addTween(clone, { time: time, opacity: opacity, transition: 'easeOutQuad' }); } else { // The window is hidden - clone.actor.opacity = 0; + clone.opacity = 0; } } @@ -1706,7 +1711,7 @@ var Workspace = class { for (let i = 0; i < this._windows.length; i++) { let clone = this._windows[i]; - Tweener.removeTweens(clone.actor); + Tweener.removeTweens(clone); } if (this._repositionWindowsId > 0) { @@ -1732,7 +1737,7 @@ var Workspace = class { if (clone.metaWindow.showing_on_its_workspace()) { let [origX, origY] = clone.getOriginalPosition(); - Tweener.addTween(clone.actor, + Tweener.addTween(clone, { x: origX, y: origY, scale_x: 1.0, @@ -1743,7 +1748,7 @@ var Workspace = class { }); } else { // The window is hidden, make it shrink and fade it out - Tweener.addTween(clone.actor, + Tweener.addTween(clone, { scale_x: 0, scale_y: 0, opacity: 0, @@ -1834,16 +1839,16 @@ var Workspace = class { clone.connect('size-changed', () => { this._recalculateWindowPositions(WindowPositionFlags.NONE); }); - clone.actor.connect('destroy', () => { + clone.connect('destroy', () => { this._removeWindowClone(clone.metaWindow); }); - this.actor.add_actor(clone.actor); + this.actor.add_actor(clone); overlay.connect('chrome-visible', () => { let focus = global.stage.key_focus; if (focus == null || this.actor.contains(focus)) - clone.actor.grab_key_focus(); + clone.grab_key_focus(); this._windowOverlays.forEach(o => { if (o != overlay) @@ -1854,7 +1859,7 @@ var Workspace = class { if (this._windows.length == 0) clone.setStackAbove(null); else - clone.setStackAbove(this._windows[this._windows.length - 1].actor); + clone.setStackAbove(this._windows[this._windows.length - 1]); this._windows.push(clone); this._windowOverlays.push(overlay);