Compare commits
	
		
			23 Commits
		
	
	
		
			gbsneto/co
			...
			gbsneto/ne
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					6fd0aafada | ||
| 
						 | 
					e5091ff17c | ||
| 
						 | 
					22534c4c64 | ||
| 
						 | 
					cd1c45731d | ||
| 
						 | 
					5380b06eb5 | ||
| 
						 | 
					be714f7401 | ||
| 
						 | 
					e71c249ea5 | ||
| 
						 | 
					5b6deff977 | ||
| 
						 | 
					6cd0c3f965 | ||
| 
						 | 
					d529e222d7 | ||
| 
						 | 
					2e23a0e6b8 | ||
| 
						 | 
					64aaa46333 | ||
| 
						 | 
					d1f61e884d | ||
| 
						 | 
					fe3d55eb80 | ||
| 
						 | 
					7a90b2d908 | ||
| 
						 | 
					137df4bc26 | ||
| 
						 | 
					23abe4eb22 | ||
| 
						 | 
					b7feb71490 | ||
| 
						 | 
					9aa9431a32 | ||
| 
						 | 
					c9e2afcf65 | ||
| 
						 | 
					be5ab24e97 | ||
| 
						 | 
					caf0c8dd7d | ||
| 
						 | 
					10a194e6ed | 
							
								
								
									
										19
									
								
								HACKING.md
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								HACKING.md
									
									
									
									
									
								
							@@ -186,27 +186,15 @@ and "double quotes" for strings that the user may see. This allows us to
 | 
			
		||||
quickly find untranslated or mistranslated strings by grepping through the
 | 
			
		||||
sources for double quotes without a gettext call around them.
 | 
			
		||||
 | 
			
		||||
## `actor` (deprecated) and `_delegate`
 | 
			
		||||
## `actor` and `_delegate`
 | 
			
		||||
 | 
			
		||||
gjs allows us to set so-called "expando properties" on introspected objects,
 | 
			
		||||
allowing us to treat them like any other. Because the Shell was built before
 | 
			
		||||
you could inherit from GTypes natively in JS, in some cases we have a wrapper
 | 
			
		||||
class that has a property called `actor` (now deprecated). We call this
 | 
			
		||||
wrapper class the "delegate".
 | 
			
		||||
you could inherit from GTypes natively in JS, we usually have a wrapper class
 | 
			
		||||
that has a property called `actor`. We call this wrapper class the "delegate".
 | 
			
		||||
 | 
			
		||||
We sometimes use expando properties to set a property called `_delegate` on
 | 
			
		||||
the actor itself:
 | 
			
		||||
```javascript
 | 
			
		||||
    var MyActor = GObject.registerClass(
 | 
			
		||||
    class MyActor extends Clutter.Actor {
 | 
			
		||||
        _init(params) {
 | 
			
		||||
            super._init(params);
 | 
			
		||||
            this._delegate = this;
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Or using the deprecated `actor`:
 | 
			
		||||
```javascript
 | 
			
		||||
    var MyClass = class {
 | 
			
		||||
        constructor() {
 | 
			
		||||
@@ -227,7 +215,6 @@ delegate object from an associated actor. For instance, the drag and drop
 | 
			
		||||
system calls the `handleDragOver` function on the delegate of a "drop target"
 | 
			
		||||
when the user drags an item over it. If you do not set the `_delegate`
 | 
			
		||||
property, your actor will not be able to be dropped onto.
 | 
			
		||||
In case the class is an actor itself, the `_delegate` can be just set to `this`.
 | 
			
		||||
 | 
			
		||||
## Functional style
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										7
									
								
								NEWS
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								NEWS
									
									
									
									
									
								
							@@ -1,10 +1,3 @@
 | 
			
		||||
3.35.1
 | 
			
		||||
======
 | 
			
		||||
* Misc. bug fixes and cleanups [Marco; Matthias; !758, #701212]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
  Marco Trevisan (Treviño)
 | 
			
		||||
 | 
			
		||||
3.34.1
 | 
			
		||||
======
 | 
			
		||||
* Fix "Frequent" view icons disappearing on hover [Jonas D.; #1502]
 | 
			
		||||
 
 | 
			
		||||
@@ -1929,6 +1929,7 @@ StScrollBar {
 | 
			
		||||
 | 
			
		||||
  StEntry {
 | 
			
		||||
    @extend %search_entry;
 | 
			
		||||
    width: -1px;
 | 
			
		||||
    border-radius: $button_radius;
 | 
			
		||||
    @if $variant=='dark' {
 | 
			
		||||
      $_gdm_entry_bg: transparentize(lighten(desaturate(#241f31, 20%), 2%), 0.5);
 | 
			
		||||
@@ -1986,6 +1987,15 @@ StScrollBar {
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .cancel-button {
 | 
			
		||||
    padding: 0;
 | 
			
		||||
    border-radius: 16px;
 | 
			
		||||
    width: 32px;
 | 
			
		||||
    height: 32px;
 | 
			
		||||
 | 
			
		||||
	  StIcon { icon-size: 16px; }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
  .login-dialog-logo-bin { padding: 24px 0px; }
 | 
			
		||||
@@ -2069,42 +2079,28 @@ StScrollBar {
 | 
			
		||||
 | 
			
		||||
$_screenshield_shadow: 0px 0px 6px rgba(0, 0, 0, 0.726);
 | 
			
		||||
 | 
			
		||||
.screen-shield-arrows {
 | 
			
		||||
    padding-bottom: 3em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.screen-shield-arrows Gjs_Arrow {
 | 
			
		||||
    color: white;
 | 
			
		||||
    width: 80px;
 | 
			
		||||
    height: 48px;
 | 
			
		||||
    -arrow-thickness: 12px;
 | 
			
		||||
    -arrow-shadow: $_screenshield_shadow;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.screen-shield-clock {
 | 
			
		||||
  color: white;
 | 
			
		||||
  text-shadow: $_screenshield_shadow;
 | 
			
		||||
  font-weight: bold;
 | 
			
		||||
  text-align: center;
 | 
			
		||||
  padding-bottom: 1.5em;
 | 
			
		||||
  padding-bottom: 2.5em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.screen-shield-clock-time {
 | 
			
		||||
  font-size: 72pt;
 | 
			
		||||
  text-shadow: $_screenshield_shadow;
 | 
			
		||||
  font-size: 64pt;
 | 
			
		||||
  font-weight: 200;
 | 
			
		||||
  padding-bottom: 24px;
 | 
			
		||||
  font-feature-settings: "tnum";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.screen-shield-clock-date { 
 | 
			
		||||
  font-size: 28pt;
 | 
			
		||||
  font-weight: normal;
 | 
			
		||||
  font-size: 16pt;
 | 
			
		||||
  font-weight: bold;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.screen-shield-notifications-container {
 | 
			
		||||
  spacing: 6px;
 | 
			
		||||
  width: 30em;
 | 
			
		||||
  background-color: transparent;
 | 
			
		||||
  max-height: 500px;
 | 
			
		||||
  padding: 24px 0;
 | 
			
		||||
  .summary-notification-stack-scrollview {
 | 
			
		||||
    padding-top: 0;
 | 
			
		||||
    padding-bottom: 0;
 | 
			
		||||
@@ -2112,7 +2108,7 @@ $_screenshield_shadow: 0px 0px 6px rgba(0, 0, 0, 0.726);
 | 
			
		||||
 | 
			
		||||
  .notification,
 | 
			
		||||
  .screen-shield-notification-source {
 | 
			
		||||
    padding: 12px 6px;
 | 
			
		||||
    padding: 12px;
 | 
			
		||||
    border: 1px solid $osd_outer_borders_color;
 | 
			
		||||
    background-color: transparentize($osd_bg_color,0.5);
 | 
			
		||||
    color: $osd_fg_color;
 | 
			
		||||
 
 | 
			
		||||
@@ -31,34 +31,34 @@ its dependencies to build from tarballs.</description>
 | 
			
		||||
  <programming-language>JavaScript</programming-language>
 | 
			
		||||
  <programming-language>C</programming-language>
 | 
			
		||||
 | 
			
		||||
  <author>
 | 
			
		||||
  <maintainer>
 | 
			
		||||
    <foaf:Person>
 | 
			
		||||
      <foaf:name>William Jon McCann</foaf:name>
 | 
			
		||||
      <foaf:mbox rdf:resource="mailto:jmccann@redhat.com" />
 | 
			
		||||
      <gnome:userid>mccann</gnome:userid>
 | 
			
		||||
    </foaf:Person>
 | 
			
		||||
  </author>
 | 
			
		||||
  <author>
 | 
			
		||||
  </maintainer>
 | 
			
		||||
  <maintainer>
 | 
			
		||||
    <foaf:Person>
 | 
			
		||||
      <foaf:name>Owen Taylor</foaf:name>
 | 
			
		||||
      <foaf:mbox rdf:resource="mailto:otaylor@redhat.com" />
 | 
			
		||||
      <gnome:userid>otaylor</gnome:userid>
 | 
			
		||||
    </foaf:Person>
 | 
			
		||||
  </author>
 | 
			
		||||
  <author>
 | 
			
		||||
  </maintainer>
 | 
			
		||||
  <maintainer>
 | 
			
		||||
    <foaf:Person>
 | 
			
		||||
      <foaf:name>Colin Walters</foaf:name>
 | 
			
		||||
      <foaf:mbox rdf:resource="mailto:walters@verbum.org" />
 | 
			
		||||
      <gnome:userid>walters</gnome:userid>
 | 
			
		||||
    </foaf:Person>
 | 
			
		||||
  </author>
 | 
			
		||||
  <author>
 | 
			
		||||
  </maintainer>
 | 
			
		||||
  <maintainer>
 | 
			
		||||
    <foaf:Person>
 | 
			
		||||
      <foaf:name>Marina Zhurakhinskaya</foaf:name>
 | 
			
		||||
      <foaf:mbox rdf:resource="mailto:marinaz@redhat.com" />
 | 
			
		||||
      <gnome:userid>marinaz</gnome:userid>
 | 
			
		||||
    </foaf:Person>
 | 
			
		||||
  </author>
 | 
			
		||||
  </maintainer>
 | 
			
		||||
  <maintainer>
 | 
			
		||||
    <foaf:Person>
 | 
			
		||||
      <foaf:name>Florian Müllner</foaf:name>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/* exported AuthPrompt */
 | 
			
		||||
 | 
			
		||||
const { Clutter, GObject, Pango, Shell, St } = imports.gi;
 | 
			
		||||
const { Clutter, Pango, Shell, St } = imports.gi;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
 | 
			
		||||
const Animation = imports.ui.animation;
 | 
			
		||||
const Batch = imports.gdm.batch;
 | 
			
		||||
@@ -16,6 +16,10 @@ var DEFAULT_BUTTON_WELL_ANIMATION_TIME = 300;
 | 
			
		||||
 | 
			
		||||
var MESSAGE_FADE_OUT_ANIMATION_TIME = 500;
 | 
			
		||||
 | 
			
		||||
const WIGGLE_OFFSET = 6;
 | 
			
		||||
const WIGGLE_DURATION = 65;
 | 
			
		||||
const N_WIGGLES = 3;
 | 
			
		||||
 | 
			
		||||
var AuthPromptMode = {
 | 
			
		||||
    UNLOCK_ONLY: 0,
 | 
			
		||||
    UNLOCK_OR_LOG_IN: 1
 | 
			
		||||
@@ -33,21 +37,8 @@ var BeginRequestType = {
 | 
			
		||||
    DONT_PROVIDE_USERNAME: 1
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var AuthPrompt = GObject.registerClass({
 | 
			
		||||
    Signals: {
 | 
			
		||||
        'cancelled': {},
 | 
			
		||||
        'failed': {},
 | 
			
		||||
        'next': {},
 | 
			
		||||
        'prompted': {},
 | 
			
		||||
        'reset': { param_types: [GObject.TYPE_UINT] },
 | 
			
		||||
    }
 | 
			
		||||
}, class AuthPrompt extends St.BoxLayout {
 | 
			
		||||
    _init(gdmClient, mode) {
 | 
			
		||||
        super._init({
 | 
			
		||||
            style_class: 'login-dialog-prompt-layout',
 | 
			
		||||
            vertical: true
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
var AuthPrompt = class {
 | 
			
		||||
    constructor(gdmClient, mode) {
 | 
			
		||||
        this.verificationStatus = AuthPromptStatus.NOT_VERIFYING;
 | 
			
		||||
 | 
			
		||||
        this._gdmClient = gdmClient;
 | 
			
		||||
@@ -80,59 +71,37 @@ var AuthPrompt = GObject.registerClass({
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
 | 
			
		||||
        this._userWell = new St.Bin({ x_fill: true, x_align: St.Align.START });
 | 
			
		||||
        this.add(this._userWell, {
 | 
			
		||||
            x_align: St.Align.START,
 | 
			
		||||
            x_fill: true,
 | 
			
		||||
            y_fill: true,
 | 
			
		||||
            expand: true
 | 
			
		||||
        this.actor = new St.BoxLayout({ style_class: 'login-dialog-prompt-layout',
 | 
			
		||||
                                        vertical: true });
 | 
			
		||||
        this.actor.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
        this.actor.connect('key-press-event', (actor, event) => {
 | 
			
		||||
            if (event.get_key_symbol() == Clutter.KEY_Escape)
 | 
			
		||||
                this.cancel();
 | 
			
		||||
            return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this._userWell = new St.Bin({ x_fill: true,
 | 
			
		||||
                                      x_align: St.Align.START });
 | 
			
		||||
        this.actor.add(this._userWell,
 | 
			
		||||
                       { x_align: St.Align.START,
 | 
			
		||||
                         x_fill: true,
 | 
			
		||||
                         y_fill: true,
 | 
			
		||||
                         expand: true });
 | 
			
		||||
        this._label = new St.Label({ style_class: 'login-dialog-prompt-label' });
 | 
			
		||||
 | 
			
		||||
        this.add(this._label, {
 | 
			
		||||
            expand: true,
 | 
			
		||||
            x_fill: false,
 | 
			
		||||
            y_fill: true,
 | 
			
		||||
            x_align: St.Align.START
 | 
			
		||||
        });
 | 
			
		||||
        this._entry = new St.Entry({ style_class: 'login-dialog-prompt-entry',
 | 
			
		||||
                                     can_focus: true });
 | 
			
		||||
        ShellEntry.addContextMenu(this._entry, { isPassword: true, actionMode: Shell.ActionMode.NONE });
 | 
			
		||||
        this.actor.add(this._label,
 | 
			
		||||
                       { expand: true,
 | 
			
		||||
                         x_fill: false,
 | 
			
		||||
                         y_fill: true,
 | 
			
		||||
                         x_align: St.Align.START });
 | 
			
		||||
 | 
			
		||||
        this.add(this._entry, {
 | 
			
		||||
            expand: true,
 | 
			
		||||
            x_fill: true,
 | 
			
		||||
            y_fill: false,
 | 
			
		||||
            x_align: St.Align.START
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this._entry.grab_key_focus();
 | 
			
		||||
        this._initEntryRow();
 | 
			
		||||
 | 
			
		||||
        this._message = new St.Label({ opacity: 0,
 | 
			
		||||
                                       styleClass: 'login-dialog-message' });
 | 
			
		||||
        this._message.clutter_text.line_wrap = true;
 | 
			
		||||
        this._message.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
 | 
			
		||||
        this.add(this._message, { x_fill: false, x_align: St.Align.START, y_align: St.Align.START });
 | 
			
		||||
 | 
			
		||||
        this._buttonBox = new St.BoxLayout({ style_class: 'login-dialog-button-box',
 | 
			
		||||
                                             vertical: false });
 | 
			
		||||
        this.add(this._buttonBox, {
 | 
			
		||||
            expand: true,
 | 
			
		||||
            x_align: St.Align.MIDDLE,
 | 
			
		||||
            y_align: St.Align.END
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this._defaultButtonWell = new St.Widget({ layout_manager: new Clutter.BinLayout() });
 | 
			
		||||
        this._defaultButtonWellActor = null;
 | 
			
		||||
 | 
			
		||||
        this._initButtons();
 | 
			
		||||
 | 
			
		||||
        this._spinner = new Animation.Spinner(DEFAULT_BUTTON_WELL_ICON_SIZE);
 | 
			
		||||
        this._spinner.opacity = 0;
 | 
			
		||||
        this._spinner.show();
 | 
			
		||||
        this._defaultButtonWell.add_child(this._spinner);
 | 
			
		||||
        this.actor.add(this._message, { x_fill: false, x_align: St.Align.START, y_align: St.Align.START });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onDestroy() {
 | 
			
		||||
@@ -140,58 +109,47 @@ var AuthPrompt = GObject.registerClass({
 | 
			
		||||
        this._userVerifier = null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_key_press_event(keyPressEvent) {
 | 
			
		||||
        if (keyPressEvent.keyval == Clutter.KEY_Escape)
 | 
			
		||||
            this.cancel();
 | 
			
		||||
        return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
    }
 | 
			
		||||
    _initEntryRow() {
 | 
			
		||||
        let mainBox = new St.BoxLayout({
 | 
			
		||||
            style_class: 'login-dialog-button-box',
 | 
			
		||||
            vertical: false,
 | 
			
		||||
        });
 | 
			
		||||
        this.actor.add_child(mainBox);
 | 
			
		||||
 | 
			
		||||
    _initButtons() {
 | 
			
		||||
        this.cancelButton = new St.Button({ style_class: 'modal-dialog-button button',
 | 
			
		||||
                                            button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
 | 
			
		||||
                                            reactive: true,
 | 
			
		||||
                                            can_focus: true,
 | 
			
		||||
                                            label: _("Cancel") });
 | 
			
		||||
        this.cancelButton = new St.Button({
 | 
			
		||||
            style_class: 'modal-dialog-button button cancel-button',
 | 
			
		||||
            button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
 | 
			
		||||
            reactive: true,
 | 
			
		||||
            can_focus: true,
 | 
			
		||||
            child: new St.Icon({ icon_name: 'go-previous-symbolic' }),
 | 
			
		||||
        });
 | 
			
		||||
        this.cancelButton.connect('clicked', () => this.cancel());
 | 
			
		||||
        this._buttonBox.add(this.cancelButton,
 | 
			
		||||
                            { expand: false,
 | 
			
		||||
                              x_fill: false,
 | 
			
		||||
                              y_fill: false,
 | 
			
		||||
                              x_align: St.Align.START,
 | 
			
		||||
                              y_align: St.Align.END });
 | 
			
		||||
        mainBox.add_child(this.cancelButton);
 | 
			
		||||
 | 
			
		||||
        this._buttonBox.add(this._defaultButtonWell,
 | 
			
		||||
                            { expand: true,
 | 
			
		||||
                              x_fill: false,
 | 
			
		||||
                              y_fill: false,
 | 
			
		||||
                              x_align: St.Align.END,
 | 
			
		||||
                              y_align: St.Align.MIDDLE });
 | 
			
		||||
        this.nextButton = new St.Button({ style_class: 'modal-dialog-button button',
 | 
			
		||||
                                          button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
 | 
			
		||||
                                          reactive: true,
 | 
			
		||||
                                          can_focus: true,
 | 
			
		||||
                                          label: _("Next") });
 | 
			
		||||
        this.nextButton.connect('clicked', () => this.emit('next'));
 | 
			
		||||
        this.nextButton.add_style_pseudo_class('default');
 | 
			
		||||
        this._buttonBox.add(this.nextButton,
 | 
			
		||||
                            { expand: false,
 | 
			
		||||
                              x_fill: false,
 | 
			
		||||
                              y_fill: false,
 | 
			
		||||
                              x_align: St.Align.END,
 | 
			
		||||
                              y_align: St.Align.END });
 | 
			
		||||
        this._entry = new St.Entry({
 | 
			
		||||
            style_class: 'login-dialog-prompt-entry',
 | 
			
		||||
            can_focus: true,
 | 
			
		||||
            x_expand: true,
 | 
			
		||||
        });
 | 
			
		||||
        ShellEntry.addContextMenu(this._entry, { isPassword: true, actionMode: Shell.ActionMode.NONE });
 | 
			
		||||
 | 
			
		||||
        this._updateNextButtonSensitivity(this._entry.text.length > 0);
 | 
			
		||||
        mainBox.add_child(this._entry);
 | 
			
		||||
 | 
			
		||||
        this._entry.grab_key_focus();
 | 
			
		||||
        this._entry.clutter_text.connect('activate', () => this.emit('next'));
 | 
			
		||||
        this._entry.clutter_text.connect('text-changed', () => {
 | 
			
		||||
            if (!this._userVerifier.hasPendingMessages)
 | 
			
		||||
                this._fadeOutMessage();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
            this._updateNextButtonSensitivity(this._entry.text.length > 0 || this.verificationStatus == AuthPromptStatus.VERIFYING);
 | 
			
		||||
        });
 | 
			
		||||
        this._entry.clutter_text.connect('activate', () => {
 | 
			
		||||
            if (this.nextButton.reactive)
 | 
			
		||||
                this.emit('next');
 | 
			
		||||
        });
 | 
			
		||||
        this._defaultButtonWell = new St.Widget({ layout_manager: new Clutter.BinLayout() });
 | 
			
		||||
        this._defaultButtonWellActor = null;
 | 
			
		||||
        mainBox.add_child(this._defaultButtonWell);
 | 
			
		||||
 | 
			
		||||
        this._spinner = new Animation.Spinner(DEFAULT_BUTTON_WELL_ICON_SIZE);
 | 
			
		||||
        this._spinner.actor.opacity = 0;
 | 
			
		||||
        this._spinner.actor.show();
 | 
			
		||||
        this._defaultButtonWell.add_child(this._spinner.actor);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onAskQuestion(verifier, serviceName, question, passwordChar) {
 | 
			
		||||
@@ -206,16 +164,6 @@ var AuthPrompt = GObject.registerClass({
 | 
			
		||||
        }
 | 
			
		||||
        this.setPasswordChar(passwordChar);
 | 
			
		||||
        this.setQuestion(question);
 | 
			
		||||
 | 
			
		||||
        if (passwordChar) {
 | 
			
		||||
            if (this._userVerifier.reauthenticating)
 | 
			
		||||
                this.nextButton.label = _("Unlock");
 | 
			
		||||
            else
 | 
			
		||||
                this.nextButton.label = C_("button", "Sign In");
 | 
			
		||||
        } else {
 | 
			
		||||
            this.nextButton.label = _("Next");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.updateSensitivity(true);
 | 
			
		||||
        this.emit('prompted');
 | 
			
		||||
    }
 | 
			
		||||
@@ -256,6 +204,35 @@ var AuthPrompt = GObject.registerClass({
 | 
			
		||||
        this.updateSensitivity(canRetry);
 | 
			
		||||
        this.setActorInDefaultButtonWell(null);
 | 
			
		||||
        this.verificationStatus = AuthPromptStatus.VERIFICATION_FAILED;
 | 
			
		||||
 | 
			
		||||
        this._wiggle();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _wiggle() {
 | 
			
		||||
        // Accelerate before wiggling
 | 
			
		||||
        this._entry.ease({
 | 
			
		||||
            translation_x: -WIGGLE_OFFSET,
 | 
			
		||||
            duration: WIGGLE_DURATION,
 | 
			
		||||
            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
 | 
			
		||||
            onComplete: () => {
 | 
			
		||||
                // Wiggle
 | 
			
		||||
                this._entry.ease({
 | 
			
		||||
                    translation_x: WIGGLE_OFFSET,
 | 
			
		||||
                    duration: WIGGLE_DURATION,
 | 
			
		||||
                    mode: Clutter.AnimationMode.LINEAR,
 | 
			
		||||
                    repeat_count: N_WIGGLES,
 | 
			
		||||
                    auto_reverse: true,
 | 
			
		||||
                    onComplete: () => {
 | 
			
		||||
                        // Decelerate and return to the original position
 | 
			
		||||
                        this._entry.ease({
 | 
			
		||||
                            translation_x: 0,
 | 
			
		||||
                            duration: WIGGLE_DURATION,
 | 
			
		||||
                            mode: Clutter.AnimationMode.EASE_IN_QUAD,
 | 
			
		||||
                        });
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onVerificationComplete() {
 | 
			
		||||
@@ -284,13 +261,13 @@ var AuthPrompt = GObject.registerClass({
 | 
			
		||||
            oldActor.remove_all_transitions();
 | 
			
		||||
 | 
			
		||||
        let wasSpinner;
 | 
			
		||||
        if (oldActor == this._spinner)
 | 
			
		||||
        if (oldActor == this._spinner.actor)
 | 
			
		||||
            wasSpinner = true;
 | 
			
		||||
        else
 | 
			
		||||
            wasSpinner = false;
 | 
			
		||||
 | 
			
		||||
        let isSpinner;
 | 
			
		||||
        if (actor == this._spinner)
 | 
			
		||||
        if (actor == this._spinner.actor)
 | 
			
		||||
            isSpinner = true;
 | 
			
		||||
        else
 | 
			
		||||
            isSpinner = false;
 | 
			
		||||
@@ -338,7 +315,7 @@ var AuthPrompt = GObject.registerClass({
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    startSpinning() {
 | 
			
		||||
        this.setActorInDefaultButtonWell(this._spinner, true);
 | 
			
		||||
        this.setActorInDefaultButtonWell(this._spinner.actor, true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    stopSpinning() {
 | 
			
		||||
@@ -408,20 +385,14 @@ var AuthPrompt = GObject.registerClass({
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _updateNextButtonSensitivity(sensitive) {
 | 
			
		||||
        this.nextButton.reactive = sensitive;
 | 
			
		||||
        this.nextButton.can_focus = sensitive;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    updateSensitivity(sensitive) {
 | 
			
		||||
        this._updateNextButtonSensitivity(sensitive && (this._entry.text.length > 0 || this.verificationStatus == AuthPromptStatus.VERIFYING));
 | 
			
		||||
        this._entry.reactive = sensitive;
 | 
			
		||||
        this._entry.clutter_text.editable = sensitive;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_hide() {
 | 
			
		||||
    hide() {
 | 
			
		||||
        this.setActorInDefaultButtonWell(null, true);
 | 
			
		||||
        super.vfunc_hide();
 | 
			
		||||
        this.actor.hide();
 | 
			
		||||
        this._message.opacity = 0;
 | 
			
		||||
 | 
			
		||||
        this.setUser(null);
 | 
			
		||||
@@ -437,7 +408,7 @@ var AuthPrompt = GObject.registerClass({
 | 
			
		||||
 | 
			
		||||
        if (user) {
 | 
			
		||||
            let userWidget = new UserWidget.UserWidget(user);
 | 
			
		||||
            this._userWell.set_child(userWidget);
 | 
			
		||||
            this._userWell.set_child(userWidget.actor);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -445,7 +416,6 @@ var AuthPrompt = GObject.registerClass({
 | 
			
		||||
        let oldStatus = this.verificationStatus;
 | 
			
		||||
        this.verificationStatus = AuthPromptStatus.NOT_VERIFYING;
 | 
			
		||||
        this.cancelButton.reactive = true;
 | 
			
		||||
        this.nextButton.label = _("Next");
 | 
			
		||||
        this._preemptiveAnswer = null;
 | 
			
		||||
 | 
			
		||||
        if (this._userVerifier)
 | 
			
		||||
@@ -522,4 +492,5 @@ var AuthPrompt = GObject.registerClass({
 | 
			
		||||
        this.reset();
 | 
			
		||||
        this.emit('cancelled');
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(AuthPrompt.prototype);
 | 
			
		||||
 
 | 
			
		||||
@@ -19,6 +19,7 @@
 | 
			
		||||
 | 
			
		||||
const { AccountsService, Atk, Clutter, Gdm, Gio,
 | 
			
		||||
        GLib, GObject, Meta, Pango, Shell, St } = imports.gi;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
 | 
			
		||||
const AuthPrompt = imports.gdm.authPrompt;
 | 
			
		||||
const Batch = imports.gdm.batch;
 | 
			
		||||
@@ -38,80 +39,72 @@ const _TIMED_LOGIN_IDLE_THRESHOLD = 5.0;
 | 
			
		||||
const _LOGO_ICON_HEIGHT = 48;
 | 
			
		||||
const _MAX_BOTTOM_MENU_ITEMS = 5;
 | 
			
		||||
 | 
			
		||||
var UserListItem = GObject.registerClass({
 | 
			
		||||
    GTypeName: 'LoginDialog_UserListItem',
 | 
			
		||||
    Signals: { 'activate': {} }
 | 
			
		||||
}, class UserListItem extends St.Button {
 | 
			
		||||
    _init(user) {
 | 
			
		||||
        let layout = new St.BoxLayout({ vertical: true });
 | 
			
		||||
        super._init({
 | 
			
		||||
            style_class: 'login-dialog-user-list-item',
 | 
			
		||||
            button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
 | 
			
		||||
            can_focus: true,
 | 
			
		||||
            child: layout,
 | 
			
		||||
            reactive: true,
 | 
			
		||||
            x_align: St.Align.START,
 | 
			
		||||
            x_fill: true
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
var UserListItem = class {
 | 
			
		||||
    constructor(user) {
 | 
			
		||||
        this.user = user;
 | 
			
		||||
        this._userChangedId = this.user.connect('changed',
 | 
			
		||||
                                                this._onUserChanged.bind(this));
 | 
			
		||||
 | 
			
		||||
        this.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
        this.connect('notify::hover', () => {
 | 
			
		||||
            this._setSelected(this.hover);
 | 
			
		||||
        let layout = new St.BoxLayout({ vertical: true });
 | 
			
		||||
        this.actor = new St.Button({ style_class: 'login-dialog-user-list-item',
 | 
			
		||||
                                     button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
 | 
			
		||||
                                     can_focus: true,
 | 
			
		||||
                                     child: layout,
 | 
			
		||||
                                     reactive: true,
 | 
			
		||||
                                     x_align: St.Align.START,
 | 
			
		||||
                                     x_fill: true });
 | 
			
		||||
        this.actor.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
 | 
			
		||||
        this.actor.connect('key-focus-in', () => {
 | 
			
		||||
            this._setSelected(true);
 | 
			
		||||
        });
 | 
			
		||||
        this.actor.connect('key-focus-out', () => {
 | 
			
		||||
            this._setSelected(false);
 | 
			
		||||
        });
 | 
			
		||||
        this.actor.connect('notify::hover', () => {
 | 
			
		||||
            this._setSelected(this.actor.hover);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this._userWidget = new UserWidget.UserWidget(this.user);
 | 
			
		||||
        layout.add(this._userWidget);
 | 
			
		||||
        layout.add(this._userWidget.actor);
 | 
			
		||||
 | 
			
		||||
        this._userWidget.bind_property('label-actor', this, 'label-actor',
 | 
			
		||||
                                       GObject.BindingFlags.SYNC_CREATE);
 | 
			
		||||
        this._userWidget.actor.bind_property('label-actor', this.actor, 'label-actor',
 | 
			
		||||
                                             GObject.BindingFlags.SYNC_CREATE);
 | 
			
		||||
 | 
			
		||||
        this._timedLoginIndicator = new St.Bin({ style_class: 'login-dialog-timed-login-indicator',
 | 
			
		||||
                                                 scale_x: 0,
 | 
			
		||||
                                                 visible: false });
 | 
			
		||||
        layout.add(this._timedLoginIndicator);
 | 
			
		||||
 | 
			
		||||
        this.actor.connect('clicked', this._onClicked.bind(this));
 | 
			
		||||
        this._onUserChanged();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_key_focus_in() {
 | 
			
		||||
        super.vfunc_key_focus_in();
 | 
			
		||||
        this._setSelected(true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_key_focus_out() {
 | 
			
		||||
        super.vfunc_key_focus_out();
 | 
			
		||||
        this._setSelected(false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onUserChanged() {
 | 
			
		||||
        this._updateLoggedIn();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _updateLoggedIn() {
 | 
			
		||||
        if (this.user.is_logged_in())
 | 
			
		||||
            this.add_style_pseudo_class('logged-in');
 | 
			
		||||
            this.actor.add_style_pseudo_class('logged-in');
 | 
			
		||||
        else
 | 
			
		||||
            this.remove_style_pseudo_class('logged-in');
 | 
			
		||||
            this.actor.remove_style_pseudo_class('logged-in');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onDestroy() {
 | 
			
		||||
        this.user.disconnect(this._userChangedId);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_clicked() {
 | 
			
		||||
    _onClicked() {
 | 
			
		||||
        this.emit('activate');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _setSelected(selected) {
 | 
			
		||||
        if (selected) {
 | 
			
		||||
            this.add_style_pseudo_class('selected');
 | 
			
		||||
            this.grab_key_focus();
 | 
			
		||||
            this.actor.add_style_pseudo_class('selected');
 | 
			
		||||
            this.actor.grab_key_focus();
 | 
			
		||||
        } else {
 | 
			
		||||
            this.remove_style_pseudo_class('selected');
 | 
			
		||||
            this.actor.remove_style_pseudo_class('selected');
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -152,30 +145,23 @@ var UserListItem = GObject.registerClass({
 | 
			
		||||
        this._timedLoginIndicator.visible = false;
 | 
			
		||||
        this._timedLoginIndicator.scale_x = 0.;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(UserListItem.prototype);
 | 
			
		||||
 | 
			
		||||
var UserList = GObject.registerClass({
 | 
			
		||||
    GTypeName: 'LoginDialog_UserList',
 | 
			
		||||
    Signals: {
 | 
			
		||||
        'activate': { param_types: [UserListItem.$gtype] },
 | 
			
		||||
        'item-added': { param_types: [UserListItem.$gtype] },
 | 
			
		||||
    }
 | 
			
		||||
}, class UserList extends St.ScrollView {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init({ style_class: 'login-dialog-user-list-view' });
 | 
			
		||||
        this.set_policy(St.PolicyType.NEVER,
 | 
			
		||||
                        St.PolicyType.AUTOMATIC);
 | 
			
		||||
var UserList = class {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        this.actor = new St.ScrollView({ style_class: 'login-dialog-user-list-view' });
 | 
			
		||||
        this.actor.set_policy(St.PolicyType.NEVER,
 | 
			
		||||
                              St.PolicyType.AUTOMATIC);
 | 
			
		||||
 | 
			
		||||
        this._box = new St.BoxLayout({ vertical: true,
 | 
			
		||||
                                       style_class: 'login-dialog-user-list',
 | 
			
		||||
                                       pseudo_class: 'expanded' });
 | 
			
		||||
 | 
			
		||||
        this.add_actor(this._box);
 | 
			
		||||
        this.actor.add_actor(this._box);
 | 
			
		||||
        this._items = {};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_key_focus_in() {
 | 
			
		||||
        this._moveFocusToItems();
 | 
			
		||||
        this.actor.connect('key-focus-in', this._moveFocusToItems.bind(this));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _moveFocusToItems() {
 | 
			
		||||
@@ -184,10 +170,10 @@ var UserList = GObject.registerClass({
 | 
			
		||||
        if (!hasItems)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (global.stage.get_key_focus() != this)
 | 
			
		||||
        if (global.stage.get_key_focus() != this.actor)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let focusSet = this.navigate_focus(null, St.DirectionType.TAB_FORWARD, false);
 | 
			
		||||
        let focusSet = this.actor.navigate_focus(null, St.DirectionType.TAB_FORWARD, false);
 | 
			
		||||
        if (!focusSet) {
 | 
			
		||||
            Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
 | 
			
		||||
                this._moveFocusToItems();
 | 
			
		||||
@@ -208,14 +194,14 @@ var UserList = GObject.registerClass({
 | 
			
		||||
 | 
			
		||||
        for (let userName in this._items) {
 | 
			
		||||
            let item = this._items[userName];
 | 
			
		||||
            item.sync_hover();
 | 
			
		||||
            item.actor.sync_hover();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    scrollToItem(item) {
 | 
			
		||||
        let box = item.get_allocation_box();
 | 
			
		||||
        let box = item.actor.get_allocation_box();
 | 
			
		||||
 | 
			
		||||
        let adjustment = this.get_vscroll_bar().get_adjustment();
 | 
			
		||||
        let adjustment = this.actor.get_vscroll_bar().get_adjustment();
 | 
			
		||||
 | 
			
		||||
        let value = (box.y1 + adjustment.step_increment / 2.0) - (adjustment.page_size / 2.0);
 | 
			
		||||
        adjustment.ease(value, {
 | 
			
		||||
@@ -225,9 +211,9 @@ var UserList = GObject.registerClass({
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    jumpToItem(item) {
 | 
			
		||||
        let box = item.get_allocation_box();
 | 
			
		||||
        let box = item.actor.get_allocation_box();
 | 
			
		||||
 | 
			
		||||
        let adjustment = this.get_vscroll_bar().get_adjustment();
 | 
			
		||||
        let adjustment = this.actor.get_vscroll_bar().get_adjustment();
 | 
			
		||||
 | 
			
		||||
        let value = (box.y1 + adjustment.step_increment / 2.0) - (adjustment.page_size / 2.0);
 | 
			
		||||
 | 
			
		||||
@@ -265,14 +251,14 @@ var UserList = GObject.registerClass({
 | 
			
		||||
        this.removeUser(user);
 | 
			
		||||
 | 
			
		||||
        let item = new UserListItem(user);
 | 
			
		||||
        this._box.add(item, { x_fill: true });
 | 
			
		||||
        this._box.add(item.actor, { x_fill: true });
 | 
			
		||||
 | 
			
		||||
        this._items[userName] = item;
 | 
			
		||||
 | 
			
		||||
        item.connect('activate', this._onItemActivated.bind(this));
 | 
			
		||||
 | 
			
		||||
        // Try to keep the focused item front-and-center
 | 
			
		||||
        item.connect('key-focus-in', () => this.scrollToItem(item));
 | 
			
		||||
        item.actor.connect('key-focus-in', () => this.scrollToItem(item));
 | 
			
		||||
 | 
			
		||||
        this._moveFocusToItems();
 | 
			
		||||
 | 
			
		||||
@@ -293,38 +279,33 @@ var UserList = GObject.registerClass({
 | 
			
		||||
        if (!item)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        item.destroy();
 | 
			
		||||
        item.actor.destroy();
 | 
			
		||||
        delete this._items[userName];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    numItems() {
 | 
			
		||||
        return Object.keys(this._items).length;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(UserList.prototype);
 | 
			
		||||
 | 
			
		||||
var SessionMenuButton = GObject.registerClass({
 | 
			
		||||
    GTypeName: 'LoginDialog_SessionMenuButton',
 | 
			
		||||
    Signals: { 'session-activated': { param_types: [GObject.TYPE_STRING] } }
 | 
			
		||||
}, class SessionMenuButton extends St.Bin {
 | 
			
		||||
    _init() {
 | 
			
		||||
var SessionMenuButton = class {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        let gearIcon = new St.Icon({ icon_name: 'emblem-system-symbolic' });
 | 
			
		||||
        let button = new St.Button({
 | 
			
		||||
            style_class: 'login-dialog-session-list-button',
 | 
			
		||||
            reactive: true,
 | 
			
		||||
            track_hover: true,
 | 
			
		||||
            can_focus: true,
 | 
			
		||||
            accessible_name: _("Choose Session"),
 | 
			
		||||
            accessible_role: Atk.Role.MENU,
 | 
			
		||||
            child: gearIcon
 | 
			
		||||
        });
 | 
			
		||||
        this._button = new St.Button({ style_class: 'login-dialog-session-list-button',
 | 
			
		||||
                                       reactive: true,
 | 
			
		||||
                                       track_hover: true,
 | 
			
		||||
                                       can_focus: true,
 | 
			
		||||
                                       accessible_name: _("Choose Session"),
 | 
			
		||||
                                       accessible_role: Atk.Role.MENU,
 | 
			
		||||
                                       child: gearIcon });
 | 
			
		||||
 | 
			
		||||
        super._init({ child: button });
 | 
			
		||||
        this._button = button;
 | 
			
		||||
        this.actor = new St.Bin({ child: this._button });
 | 
			
		||||
 | 
			
		||||
        let side = St.Side.TOP;
 | 
			
		||||
        let align = 0;
 | 
			
		||||
        if (Gdm.get_session_ids().length > _MAX_BOTTOM_MENU_ITEMS) {
 | 
			
		||||
            if (this.text_direction == Clutter.TextDirection.RTL)
 | 
			
		||||
            if (this.actor.text_direction == Clutter.TextDirection.RTL)
 | 
			
		||||
                side = St.Side.RIGHT;
 | 
			
		||||
            else
 | 
			
		||||
                side = St.Side.LEFT;
 | 
			
		||||
@@ -403,13 +384,15 @@ var SessionMenuButton = GObject.registerClass({
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(SessionMenuButton.prototype);
 | 
			
		||||
 | 
			
		||||
var LoginDialog = GObject.registerClass({
 | 
			
		||||
    Signals: { 'failed': {} },
 | 
			
		||||
}, class LoginDialog extends St.Widget {
 | 
			
		||||
    _init(parentActor) {
 | 
			
		||||
        super._init({ style_class: 'login-dialog', visible: false });
 | 
			
		||||
        super._init({ style_class: 'login-dialog',
 | 
			
		||||
                      visible: false });
 | 
			
		||||
 | 
			
		||||
        this.get_accessible().set_role(Atk.Role.WINDOW);
 | 
			
		||||
 | 
			
		||||
@@ -443,7 +426,7 @@ var LoginDialog = GObject.registerClass({
 | 
			
		||||
        this.add_child(this._userSelectionBox);
 | 
			
		||||
 | 
			
		||||
        this._userList = new UserList();
 | 
			
		||||
        this._userSelectionBox.add(this._userList,
 | 
			
		||||
        this._userSelectionBox.add(this._userList.actor,
 | 
			
		||||
                                   { expand: true,
 | 
			
		||||
                                     x_fill: true,
 | 
			
		||||
                                     y_fill: true });
 | 
			
		||||
@@ -452,7 +435,7 @@ var LoginDialog = GObject.registerClass({
 | 
			
		||||
        this._authPrompt.connect('prompted', this._onPrompted.bind(this));
 | 
			
		||||
        this._authPrompt.connect('reset', this._onReset.bind(this));
 | 
			
		||||
        this._authPrompt.hide();
 | 
			
		||||
        this.add_child(this._authPrompt);
 | 
			
		||||
        this.add_child(this._authPrompt.actor);
 | 
			
		||||
 | 
			
		||||
        // translators: this message is shown below the user list on the
 | 
			
		||||
        // login screen. It can be activated to reveal an entry for
 | 
			
		||||
@@ -511,9 +494,9 @@ var LoginDialog = GObject.registerClass({
 | 
			
		||||
            (list, sessionId) => {
 | 
			
		||||
                this._greeter.call_select_session_sync (sessionId, null);
 | 
			
		||||
            });
 | 
			
		||||
        this._sessionMenuButton.opacity = 0;
 | 
			
		||||
        this._sessionMenuButton.show();
 | 
			
		||||
        this._authPrompt.addActorToDefaultButtonWell(this._sessionMenuButton);
 | 
			
		||||
        this._sessionMenuButton.actor.opacity = 0;
 | 
			
		||||
        this._sessionMenuButton.actor.show();
 | 
			
		||||
        this._authPrompt.addActorToDefaultButtonWell(this._sessionMenuButton.actor);
 | 
			
		||||
 | 
			
		||||
        this._disableUserList = undefined;
 | 
			
		||||
        this._userListLoaded = false;
 | 
			
		||||
@@ -596,8 +579,8 @@ var LoginDialog = GObject.registerClass({
 | 
			
		||||
 | 
			
		||||
        let authPromptAllocation = null;
 | 
			
		||||
        let authPromptWidth = 0;
 | 
			
		||||
        if (this._authPrompt.visible) {
 | 
			
		||||
            authPromptAllocation = this._getCenterActorAllocation(dialogBox, this._authPrompt);
 | 
			
		||||
        if (this._authPrompt.actor.visible) {
 | 
			
		||||
            authPromptAllocation = this._getCenterActorAllocation(dialogBox, this._authPrompt.actor);
 | 
			
		||||
            authPromptWidth = authPromptAllocation.x2 - authPromptAllocation.x1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -707,7 +690,7 @@ var LoginDialog = GObject.registerClass({
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (authPromptAllocation)
 | 
			
		||||
            this._authPrompt.allocate(authPromptAllocation, flags);
 | 
			
		||||
            this._authPrompt.actor.allocate(authPromptAllocation, flags);
 | 
			
		||||
 | 
			
		||||
        if (userSelectionAllocation)
 | 
			
		||||
            this._userSelectionBox.allocate(userSelectionAllocation, flags);
 | 
			
		||||
@@ -811,7 +794,7 @@ var LoginDialog = GObject.registerClass({
 | 
			
		||||
    _onPrompted() {
 | 
			
		||||
        if (this._shouldShowSessionMenuButton()) {
 | 
			
		||||
            this._sessionMenuButton.updateSensitivity(true);
 | 
			
		||||
            this._authPrompt.setActorInDefaultButtonWell(this._sessionMenuButton);
 | 
			
		||||
            this._authPrompt.setActorInDefaultButtonWell(this._sessionMenuButton.actor);
 | 
			
		||||
        } else {
 | 
			
		||||
            this._sessionMenuButton.updateSensitivity(false);
 | 
			
		||||
        }
 | 
			
		||||
@@ -871,11 +854,11 @@ var LoginDialog = GObject.registerClass({
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _showPrompt() {
 | 
			
		||||
        if (this._authPrompt.visible)
 | 
			
		||||
        if (this._authPrompt.actor.visible)
 | 
			
		||||
            return;
 | 
			
		||||
        this._authPrompt.opacity = 0;
 | 
			
		||||
        this._authPrompt.show();
 | 
			
		||||
        this._authPrompt.ease({
 | 
			
		||||
        this._authPrompt.actor.opacity = 0;
 | 
			
		||||
        this._authPrompt.actor.show();
 | 
			
		||||
        this._authPrompt.actor.ease({
 | 
			
		||||
            opacity: 255,
 | 
			
		||||
            duration: _FADE_ANIMATION_TIME,
 | 
			
		||||
            mode: Clutter.AnimationMode.EASE_OUT_QUAD
 | 
			
		||||
@@ -1062,12 +1045,12 @@ var LoginDialog = GObject.registerClass({
 | 
			
		||||
                     () => {
 | 
			
		||||
                         // If idle timeout is done, make sure the timed login indicator is shown
 | 
			
		||||
                         if (delay > _TIMED_LOGIN_IDLE_THRESHOLD &&
 | 
			
		||||
                             this._authPrompt.visible)
 | 
			
		||||
                             this._authPrompt.actor.visible)
 | 
			
		||||
                             this._authPrompt.cancel();
 | 
			
		||||
 | 
			
		||||
                         if (delay > _TIMED_LOGIN_IDLE_THRESHOLD || firstRun) {
 | 
			
		||||
                             this._userList.scrollToItem(loginItem);
 | 
			
		||||
                             loginItem.grab_key_focus();
 | 
			
		||||
                             loginItem.actor.grab_key_focus();
 | 
			
		||||
                         }
 | 
			
		||||
                     },
 | 
			
		||||
 | 
			
		||||
@@ -1128,7 +1111,7 @@ var LoginDialog = GObject.registerClass({
 | 
			
		||||
        this._sessionMenuButton.close();
 | 
			
		||||
        this._setUserListExpanded(true);
 | 
			
		||||
        this._notListedButton.show();
 | 
			
		||||
        this._userList.grab_key_focus();
 | 
			
		||||
        this._userList.actor.grab_key_focus();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _beginVerificationForItem(item) {
 | 
			
		||||
@@ -1236,7 +1219,7 @@ var LoginDialog = GObject.registerClass({
 | 
			
		||||
                                        _("Login Window"),
 | 
			
		||||
                                        'dialog-password-symbolic',
 | 
			
		||||
                                        { sortGroup: CtrlAltTab.SortGroup.MIDDLE });
 | 
			
		||||
        this._userList.grab_key_focus();
 | 
			
		||||
        this._userList.actor.grab_key_focus();
 | 
			
		||||
        this.show();
 | 
			
		||||
        this.opacity = 0;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -127,11 +127,11 @@ function *run() {
 | 
			
		||||
    for (let i = 0; i < 2; i++) {
 | 
			
		||||
        Scripting.scriptEvent('applicationsShowStart');
 | 
			
		||||
        // eslint-disable-next-line require-atomic-updates
 | 
			
		||||
        Main.overview.dash.showAppsButton.checked = true;
 | 
			
		||||
        Main.overview._dash.showAppsButton.checked = true;
 | 
			
		||||
        yield Scripting.waitLeisure();
 | 
			
		||||
        Scripting.scriptEvent('applicationsShowDone');
 | 
			
		||||
        // eslint-disable-next-line require-atomic-updates
 | 
			
		||||
        Main.overview.dash.showAppsButton.checked = false;
 | 
			
		||||
        Main.overview._dash.showAppsButton.checked = false;
 | 
			
		||||
        yield Scripting.waitLeisure();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -127,7 +127,7 @@ function *run() {
 | 
			
		||||
 | 
			
		||||
    Scripting.scriptEvent('applicationsShowStart');
 | 
			
		||||
    // eslint-disable-next-line require-atomic-updates
 | 
			
		||||
    Main.overview.dash.showAppsButton.checked = true;
 | 
			
		||||
    Main.overview._dash.showAppsButton.checked = true;
 | 
			
		||||
 | 
			
		||||
    yield Scripting.waitLeisure();
 | 
			
		||||
    Scripting.scriptEvent('applicationsShowDone');
 | 
			
		||||
 
 | 
			
		||||
@@ -56,8 +56,8 @@ class AccessDialog extends ModalDialog.ModalDialog {
 | 
			
		||||
 | 
			
		||||
            let check = new CheckBox.CheckBox();
 | 
			
		||||
            check.getLabelActor().text = name;
 | 
			
		||||
            check.checked = selected == "true";
 | 
			
		||||
            content.insertBeforeBody(check);
 | 
			
		||||
            check.actor.checked = selected == "true";
 | 
			
		||||
            content.insertBeforeBody(check.actor);
 | 
			
		||||
 | 
			
		||||
            this._choices.set(id, check);
 | 
			
		||||
        }
 | 
			
		||||
@@ -99,7 +99,7 @@ class AccessDialog extends ModalDialog.ModalDialog {
 | 
			
		||||
        let results = {};
 | 
			
		||||
        if (response == DialogResponse.OK) {
 | 
			
		||||
            for (let [id, check] of this._choices) {
 | 
			
		||||
                let checked = check.checked ? 'true' : 'false';
 | 
			
		||||
                let checked = check.actor.checked ? 'true' : 'false';
 | 
			
		||||
                results[id] = new GLib.Variant('s', checked);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -28,20 +28,14 @@ var AppIconMode = {
 | 
			
		||||
function _createWindowClone(window, size) {
 | 
			
		||||
    let [width, height] = window.get_size();
 | 
			
		||||
    let scale = Math.min(1.0, size / width, size / height);
 | 
			
		||||
 | 
			
		||||
    let cloneWidth = size;
 | 
			
		||||
    let cloneHeight = size;
 | 
			
		||||
 | 
			
		||||
    if (width > height)
 | 
			
		||||
        cloneHeight = size * (height / width);
 | 
			
		||||
    else
 | 
			
		||||
        cloneWidth = size * (width / height);
 | 
			
		||||
 | 
			
		||||
    return new Clutter.Actor({
 | 
			
		||||
        content: window.content,
 | 
			
		||||
        width: cloneWidth,
 | 
			
		||||
        height: cloneHeight,
 | 
			
		||||
    });
 | 
			
		||||
    return new Clutter.Clone({ source: window,
 | 
			
		||||
                               width: width * scale,
 | 
			
		||||
                               height: height * scale,
 | 
			
		||||
                               x_align: Clutter.ActorAlign.CENTER,
 | 
			
		||||
                               y_align: Clutter.ActorAlign.CENTER,
 | 
			
		||||
                               // usual hack for the usual bug in ClutterBinLayout...
 | 
			
		||||
                               x_expand: true,
 | 
			
		||||
                               y_expand: true });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getWindows(workspace) {
 | 
			
		||||
@@ -411,26 +405,27 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
var CyclerHighlight = GObject.registerClass(
 | 
			
		||||
class CyclerHighlight extends St.Widget {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init({ layout_manager: new Clutter.BinLayout() });
 | 
			
		||||
class CyclerHighlight {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        this._window = null;
 | 
			
		||||
 | 
			
		||||
        this._clone = new Clutter.Actor();
 | 
			
		||||
        this.add_actor(this._clone);
 | 
			
		||||
        this.actor = new St.Widget({ layout_manager: new Clutter.BinLayout() });
 | 
			
		||||
 | 
			
		||||
        this._clone = new Clutter.Clone();
 | 
			
		||||
        this.actor.add_actor(this._clone);
 | 
			
		||||
 | 
			
		||||
        this._highlight = new St.Widget({ style_class: 'cycler-highlight' });
 | 
			
		||||
        this.add_actor(this._highlight);
 | 
			
		||||
        this.actor.add_actor(this._highlight);
 | 
			
		||||
 | 
			
		||||
        let coordinate = Clutter.BindCoordinate.ALL;
 | 
			
		||||
        let constraint = new Clutter.BindConstraint({ coordinate: coordinate });
 | 
			
		||||
        this._clone.bind_property('source', constraint, 'source', 0);
 | 
			
		||||
 | 
			
		||||
        this.add_constraint(constraint);
 | 
			
		||||
        this.actor.add_constraint(constraint);
 | 
			
		||||
 | 
			
		||||
        this.connect('notify::allocation', this._onAllocationChanged.bind(this));
 | 
			
		||||
        this.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
        this.actor.connect('notify::allocation',
 | 
			
		||||
                           this._onAllocationChanged.bind(this));
 | 
			
		||||
        this.actor.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    set window(w) {
 | 
			
		||||
@@ -439,8 +434,8 @@ class CyclerHighlight extends St.Widget {
 | 
			
		||||
 | 
			
		||||
        this._window = w;
 | 
			
		||||
 | 
			
		||||
        if (this._clone.content)
 | 
			
		||||
            this._clone.content.window_actor.sync_visibility();
 | 
			
		||||
        if (this._clone.source)
 | 
			
		||||
            this._clone.source.sync_visibility();
 | 
			
		||||
 | 
			
		||||
        let windowActor = this._window
 | 
			
		||||
            ? this._window.get_compositor_private() : null;
 | 
			
		||||
@@ -448,7 +443,7 @@ class CyclerHighlight extends St.Widget {
 | 
			
		||||
        if (windowActor)
 | 
			
		||||
            windowActor.hide();
 | 
			
		||||
 | 
			
		||||
        this._clone.content = windowActor.content;
 | 
			
		||||
        this._clone.source = windowActor;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onAllocationChanged() {
 | 
			
		||||
@@ -456,7 +451,7 @@ class CyclerHighlight extends St.Widget {
 | 
			
		||||
            this._highlight.set_size(0, 0);
 | 
			
		||||
            this._highlight.hide();
 | 
			
		||||
        } else {
 | 
			
		||||
            let [x, y] = this.allocation.get_origin();
 | 
			
		||||
            let [x, y] = this.actor.allocation.get_origin();
 | 
			
		||||
            let rect = this._window.get_frame_rect();
 | 
			
		||||
            this._highlight.set_size(rect.width, rect.height);
 | 
			
		||||
            this._highlight.set_position(rect.x - x, rect.y - y);
 | 
			
		||||
@@ -467,7 +462,7 @@ class CyclerHighlight extends St.Widget {
 | 
			
		||||
    _onDestroy() {
 | 
			
		||||
        this.window = null;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// We don't show an actual popup, so just provide what SwitcherPopup
 | 
			
		||||
// expects instead of inheriting from SwitcherList
 | 
			
		||||
@@ -494,7 +489,7 @@ var CyclerPopup = GObject.registerClass({
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._highlight = new CyclerHighlight();
 | 
			
		||||
        global.window_group.add_actor(this._highlight);
 | 
			
		||||
        global.window_group.add_actor(this._highlight.actor);
 | 
			
		||||
 | 
			
		||||
        this._switcherList = new CyclerList();
 | 
			
		||||
        this._switcherList.connect('item-highlighted', (list, index) => {
 | 
			
		||||
@@ -504,7 +499,7 @@ var CyclerPopup = GObject.registerClass({
 | 
			
		||||
 | 
			
		||||
    _highlightItem(index, _justOutline) {
 | 
			
		||||
        this._highlight.window = this._items[index];
 | 
			
		||||
        global.window_group.set_child_above_sibling(this._highlight, null);
 | 
			
		||||
        global.window_group.set_child_above_sibling(this._highlight.actor, null);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _finish() {
 | 
			
		||||
@@ -534,7 +529,7 @@ var CyclerPopup = GObject.registerClass({
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onDestroy() {
 | 
			
		||||
        this._highlight.destroy();
 | 
			
		||||
        this._highlight.actor.destroy();
 | 
			
		||||
 | 
			
		||||
        super._onDestroy();
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,18 +1,19 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/* exported Animation, AnimatedIcon, Spinner */
 | 
			
		||||
 | 
			
		||||
const { Clutter, GLib, GObject, Gio, St } = imports.gi;
 | 
			
		||||
const { Clutter, GLib, Gio, St } = imports.gi;
 | 
			
		||||
 | 
			
		||||
var ANIMATED_ICON_UPDATE_TIMEOUT = 16;
 | 
			
		||||
var SPINNER_ANIMATION_TIME = 300;
 | 
			
		||||
var SPINNER_ANIMATION_DELAY = 1000;
 | 
			
		||||
 | 
			
		||||
var Animation = GObject.registerClass(
 | 
			
		||||
class Animation extends St.Bin {
 | 
			
		||||
    _init(file, width, height, speed) {
 | 
			
		||||
        super._init({ width: width, height: height });
 | 
			
		||||
        this.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
        this.connect('resource-scale-changed',
 | 
			
		||||
var Animation = class {
 | 
			
		||||
    constructor(file, width, height, speed) {
 | 
			
		||||
        this.actor = new St.Bin();
 | 
			
		||||
        this.actor.set_size(width, height);
 | 
			
		||||
        this.actor.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
        this.actor.connect('notify::size', this._syncAnimationSize.bind(this));
 | 
			
		||||
        this.actor.connect('resource-scale-changed',
 | 
			
		||||
            this._loadFile.bind(this, file, width, height));
 | 
			
		||||
 | 
			
		||||
        let themeContext = St.ThemeContext.get_for_stage(global.stage);
 | 
			
		||||
@@ -51,14 +52,14 @@ class Animation extends St.Bin {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _loadFile(file, width, height) {
 | 
			
		||||
        let [validResourceScale, resourceScale] = this.get_resource_scale();
 | 
			
		||||
        let [validResourceScale, resourceScale] = this.actor.get_resource_scale();
 | 
			
		||||
        let wasPlaying = this._isPlaying;
 | 
			
		||||
 | 
			
		||||
        if (this._isPlaying)
 | 
			
		||||
            this.stop();
 | 
			
		||||
 | 
			
		||||
        this._isLoaded = false;
 | 
			
		||||
        this.destroy_all_children();
 | 
			
		||||
        this.actor.destroy_all_children();
 | 
			
		||||
 | 
			
		||||
        if (!validResourceScale) {
 | 
			
		||||
            if (wasPlaying)
 | 
			
		||||
@@ -71,7 +72,7 @@ class Animation extends St.Bin {
 | 
			
		||||
        this._animations = textureCache.load_sliced_image(file, width, height,
 | 
			
		||||
                                                          scaleFactor, resourceScale,
 | 
			
		||||
                                                          this._animationsLoaded.bind(this));
 | 
			
		||||
        this.set_child(this._animations);
 | 
			
		||||
        this.actor.set_child(this._animations);
 | 
			
		||||
 | 
			
		||||
        if (wasPlaying)
 | 
			
		||||
            this.play();
 | 
			
		||||
@@ -98,7 +99,7 @@ class Animation extends St.Bin {
 | 
			
		||||
        if (!this._isLoaded)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let [width, height] = this.get_size();
 | 
			
		||||
        let [width, height] = this.actor.get_size();
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < this._animations.get_n_children(); ++i)
 | 
			
		||||
            this._animations.get_child_at_index(i).set_size(width, height);
 | 
			
		||||
@@ -121,22 +122,20 @@ class Animation extends St.Bin {
 | 
			
		||||
            themeContext.disconnect(this._scaleChangedId);
 | 
			
		||||
        this._scaleChangedId = 0;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var AnimatedIcon = GObject.registerClass(
 | 
			
		||||
class AnimatedIcon extends Animation {
 | 
			
		||||
    _init(file, size) {
 | 
			
		||||
        super._init(file, size, size, ANIMATED_ICON_UPDATE_TIMEOUT);
 | 
			
		||||
var AnimatedIcon = class extends Animation {
 | 
			
		||||
    constructor(file, size) {
 | 
			
		||||
        super(file, size, size, ANIMATED_ICON_UPDATE_TIMEOUT);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var Spinner = GObject.registerClass(
 | 
			
		||||
class Spinner extends AnimatedIcon {
 | 
			
		||||
    _init(size, animate = false) {
 | 
			
		||||
var Spinner = class extends AnimatedIcon {
 | 
			
		||||
    constructor(size, animate = false) {
 | 
			
		||||
        let file = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/process-working.svg');
 | 
			
		||||
        super._init(file, size);
 | 
			
		||||
        super(file, size);
 | 
			
		||||
 | 
			
		||||
        this.opacity = 0;
 | 
			
		||||
        this.actor.opacity = 0;
 | 
			
		||||
        this._animate = animate;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -146,35 +145,35 @@ class Spinner extends AnimatedIcon {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    play() {
 | 
			
		||||
        this.remove_all_transitions();
 | 
			
		||||
        this.actor.remove_all_transitions();
 | 
			
		||||
 | 
			
		||||
        if (this._animate) {
 | 
			
		||||
            super.play();
 | 
			
		||||
            this.ease({
 | 
			
		||||
            this.actor.ease({
 | 
			
		||||
                opacity: 255,
 | 
			
		||||
                delay: SPINNER_ANIMATION_DELAY,
 | 
			
		||||
                duration: SPINNER_ANIMATION_TIME,
 | 
			
		||||
                mode: Clutter.AnimationMode.LINEAR
 | 
			
		||||
            });
 | 
			
		||||
        } else {
 | 
			
		||||
            this.opacity = 255;
 | 
			
		||||
            this.actor.opacity = 255;
 | 
			
		||||
            super.play();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    stop() {
 | 
			
		||||
        this.remove_all_transitions();
 | 
			
		||||
        this.actor.remove_all_transitions();
 | 
			
		||||
 | 
			
		||||
        if (this._animate) {
 | 
			
		||||
            this.ease({
 | 
			
		||||
            this.actor.ease({
 | 
			
		||||
                opacity: 0,
 | 
			
		||||
                duration: SPINNER_ANIMATION_TIME,
 | 
			
		||||
                mode: Clutter.AnimationMode.LINEAR,
 | 
			
		||||
                time: SPINNER_ANIMATION_TIME,
 | 
			
		||||
                transition: 'linear',
 | 
			
		||||
                onComplete: () => super.stop()
 | 
			
		||||
            });
 | 
			
		||||
        } else {
 | 
			
		||||
            this.opacity = 0;
 | 
			
		||||
            this.actor.opacity = 0;
 | 
			
		||||
            super.stop();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,5 +1,4 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/* exported SystemBackground */
 | 
			
		||||
 | 
			
		||||
// READ THIS FIRST
 | 
			
		||||
// Background handling is a maze of objects, both objects in this file, and
 | 
			
		||||
@@ -94,7 +93,7 @@
 | 
			
		||||
//     MetaBackgroundImage         MetaBackgroundImage
 | 
			
		||||
//     MetaBackgroundImage         MetaBackgroundImage
 | 
			
		||||
 | 
			
		||||
const { Clutter, GDesktopEnums, Gio, GLib, GObject, GnomeDesktop, Meta } = imports.gi;
 | 
			
		||||
const { Clutter, GDesktopEnums, Gio, GLib, GnomeDesktop, Meta } = imports.gi;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
 | 
			
		||||
const LoginManager = imports.misc.loginManager;
 | 
			
		||||
@@ -221,17 +220,16 @@ function getBackgroundCache() {
 | 
			
		||||
    return _backgroundCache;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var Background = GObject.registerClass({
 | 
			
		||||
    Signals: { 'loaded': {}, 'bg-changed': {} }
 | 
			
		||||
}, class Background extends Meta.Background {
 | 
			
		||||
    _init(params) {
 | 
			
		||||
var Background = class Background {
 | 
			
		||||
    constructor(params) {
 | 
			
		||||
        params = Params.parse(params, { monitorIndex: 0,
 | 
			
		||||
                                        layoutManager: Main.layoutManager,
 | 
			
		||||
                                        settings: null,
 | 
			
		||||
                                        file: null,
 | 
			
		||||
                                        style: null });
 | 
			
		||||
 | 
			
		||||
        super._init({ meta_display: global.display });
 | 
			
		||||
        this.background = new Meta.Background({ meta_display: global.display });
 | 
			
		||||
        this.background._delegate = this;
 | 
			
		||||
 | 
			
		||||
        this._settings = params.settings;
 | 
			
		||||
        this._file = params.file;
 | 
			
		||||
@@ -264,6 +262,8 @@ var Background = GObject.registerClass({
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    destroy() {
 | 
			
		||||
        this.background = null;
 | 
			
		||||
 | 
			
		||||
        this._cancellable.cancel();
 | 
			
		||||
        this._removeAnimationTimeout();
 | 
			
		||||
 | 
			
		||||
@@ -300,11 +300,9 @@ var Background = GObject.registerClass({
 | 
			
		||||
 | 
			
		||||
        this._changedIdleId = GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {
 | 
			
		||||
            this._changedIdleId = 0;
 | 
			
		||||
            this.emit('bg-changed');
 | 
			
		||||
            this.emit('changed');
 | 
			
		||||
            return GLib.SOURCE_REMOVE;
 | 
			
		||||
        });
 | 
			
		||||
        GLib.Source.set_name_by_id(this._changedIdleId,
 | 
			
		||||
            '[gnome-shell] Background._emitChangedSignal');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    updateResolution() {
 | 
			
		||||
@@ -330,7 +328,7 @@ var Background = GObject.registerClass({
 | 
			
		||||
            this.emit('loaded');
 | 
			
		||||
            return GLib.SOURCE_REMOVE;
 | 
			
		||||
        });
 | 
			
		||||
        GLib.Source.set_name_by_id(id, '[gnome-shell] Background._setLoaded Idle');
 | 
			
		||||
        GLib.Source.set_name_by_id(id, '[gnome-shell] this.emit');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _loadPattern() {
 | 
			
		||||
@@ -344,9 +342,9 @@ var Background = GObject.registerClass({
 | 
			
		||||
        let shadingType = this._settings.get_enum(COLOR_SHADING_TYPE_KEY);
 | 
			
		||||
 | 
			
		||||
        if (shadingType == GDesktopEnums.BackgroundShading.SOLID)
 | 
			
		||||
            this.set_color(color);
 | 
			
		||||
            this.background.set_color(color);
 | 
			
		||||
        else
 | 
			
		||||
            this.set_gradient(shadingType, color, secondColor);
 | 
			
		||||
            this.background.set_gradient(shadingType, color, secondColor);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _watchFile(file) {
 | 
			
		||||
@@ -382,13 +380,13 @@ var Background = GObject.registerClass({
 | 
			
		||||
        let finish = () => {
 | 
			
		||||
            this._setLoaded();
 | 
			
		||||
            if (files.length > 1) {
 | 
			
		||||
                this.set_blend(files[0], files[1],
 | 
			
		||||
                               this._animation.transitionProgress,
 | 
			
		||||
                               this._style);
 | 
			
		||||
                this.background.set_blend(files[0], files[1],
 | 
			
		||||
                                          this._animation.transitionProgress,
 | 
			
		||||
                                          this._style);
 | 
			
		||||
            } else if (files.length > 0) {
 | 
			
		||||
                this.set_file(files[0], this._style);
 | 
			
		||||
                this.background.set_file(files[0], this._style);
 | 
			
		||||
            } else {
 | 
			
		||||
                this.set_file(null, this._style);
 | 
			
		||||
                this.background.set_file(null, this._style);
 | 
			
		||||
            }
 | 
			
		||||
            this._queueUpdateAnimation();
 | 
			
		||||
        };
 | 
			
		||||
@@ -461,7 +459,7 @@ var Background = GObject.registerClass({
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _loadImage(file) {
 | 
			
		||||
        this.set_file(file, this._style);
 | 
			
		||||
        this.background.set_file(file, this._style);
 | 
			
		||||
        this._watchFile(file);
 | 
			
		||||
 | 
			
		||||
        let cache = Meta.BackgroundImageCache.get_default();
 | 
			
		||||
@@ -495,14 +493,13 @@ var Background = GObject.registerClass({
 | 
			
		||||
 | 
			
		||||
        this._loadFile(this._file);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(Background.prototype);
 | 
			
		||||
 | 
			
		||||
let _systemBackground;
 | 
			
		||||
 | 
			
		||||
var SystemBackground = GObject.registerClass({
 | 
			
		||||
    Signals: { 'loaded': {} }
 | 
			
		||||
}, class SystemBackground extends Meta.BackgroundActor {
 | 
			
		||||
    _init() {
 | 
			
		||||
var SystemBackground = class SystemBackground {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        let file = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/noise-texture.png');
 | 
			
		||||
 | 
			
		||||
        if (_systemBackground == null) {
 | 
			
		||||
@@ -511,11 +508,9 @@ var SystemBackground = GObject.registerClass({
 | 
			
		||||
            _systemBackground.set_file(file, GDesktopEnums.BackgroundStyle.WALLPAPER);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        super._init({
 | 
			
		||||
            meta_display: global.display,
 | 
			
		||||
            monitor: 0,
 | 
			
		||||
            background: _systemBackground
 | 
			
		||||
        });
 | 
			
		||||
        this.actor = new Meta.BackgroundActor({ meta_display: global.display,
 | 
			
		||||
                                                monitor: 0,
 | 
			
		||||
                                                background: _systemBackground });
 | 
			
		||||
 | 
			
		||||
        let cache = Meta.BackgroundImageCache.get_default();
 | 
			
		||||
        let image = cache.load(file);
 | 
			
		||||
@@ -534,7 +529,8 @@ var SystemBackground = GObject.registerClass({
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(SystemBackground.prototype);
 | 
			
		||||
 | 
			
		||||
var BackgroundSource = class BackgroundSource {
 | 
			
		||||
    constructor(layoutManager, settingsSchema) {
 | 
			
		||||
@@ -570,7 +566,7 @@ var BackgroundSource = class BackgroundSource {
 | 
			
		||||
 | 
			
		||||
        // We don't watch changes to settings here,
 | 
			
		||||
        // instead we rely on Background to watch those
 | 
			
		||||
        // and emit 'bg-changed' at the right time
 | 
			
		||||
        // and emit 'changed' at the right time
 | 
			
		||||
 | 
			
		||||
        if (this._overrideImage != null) {
 | 
			
		||||
            file = Gio.File.new_for_path(this._overrideImage);
 | 
			
		||||
@@ -599,7 +595,7 @@ var BackgroundSource = class BackgroundSource {
 | 
			
		||||
                style: style
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            background._changedId = background.connect('bg-changed', () => {
 | 
			
		||||
            background._changedId = background.connect('changed', () => {
 | 
			
		||||
                background.disconnect(background._changedId);
 | 
			
		||||
                background.destroy();
 | 
			
		||||
                delete this._backgrounds[monitorIndex];
 | 
			
		||||
@@ -736,7 +732,7 @@ var BackgroundManager = class BackgroundManager {
 | 
			
		||||
 | 
			
		||||
        this._newBackgroundActor = newBackgroundActor;
 | 
			
		||||
 | 
			
		||||
        let background = newBackgroundActor.background;
 | 
			
		||||
        let background = newBackgroundActor.background._delegate;
 | 
			
		||||
 | 
			
		||||
        if (background.isLoaded) {
 | 
			
		||||
            this._swapBackgroundActor();
 | 
			
		||||
@@ -756,7 +752,7 @@ var BackgroundManager = class BackgroundManager {
 | 
			
		||||
        let backgroundActor = new Meta.BackgroundActor({
 | 
			
		||||
            meta_display: global.display,
 | 
			
		||||
            monitor: this._monitorIndex,
 | 
			
		||||
            background,
 | 
			
		||||
            background: background.background,
 | 
			
		||||
            vignette: this._vignette,
 | 
			
		||||
            vignette_sharpness: 0.5,
 | 
			
		||||
            brightness: 0.5,
 | 
			
		||||
@@ -770,7 +766,7 @@ var BackgroundManager = class BackgroundManager {
 | 
			
		||||
            backgroundActor.lower_bottom();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let changeSignalId = background.connect('bg-changed', () => {
 | 
			
		||||
        let changeSignalId = background.connect('changed', () => {
 | 
			
		||||
            background.disconnect(changeSignalId);
 | 
			
		||||
            changeSignalId = null;
 | 
			
		||||
            this._updateBackgroundActor();
 | 
			
		||||
 
 | 
			
		||||
@@ -46,18 +46,12 @@ var BoxPointer = GObject.registerClass({
 | 
			
		||||
        this.add_actor(this._border);
 | 
			
		||||
        this.bin.raise(this._border);
 | 
			
		||||
        this._sourceAlignment = 0.5;
 | 
			
		||||
        this._muteInput = true;
 | 
			
		||||
        this._capturedEventId = 0;
 | 
			
		||||
        this._muteInput();
 | 
			
		||||
 | 
			
		||||
        this.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_captured_event() {
 | 
			
		||||
        if (this._muteInput)
 | 
			
		||||
            return Clutter.EVENT_STOP;
 | 
			
		||||
 | 
			
		||||
        return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onDestroy() {
 | 
			
		||||
        if (this._sourceActorDestroyId) {
 | 
			
		||||
            this._sourceActor.disconnect(this._sourceActorDestroyId);
 | 
			
		||||
@@ -69,6 +63,19 @@ var BoxPointer = GObject.registerClass({
 | 
			
		||||
        return this._arrowSide;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _muteInput() {
 | 
			
		||||
        if (this._capturedEventId == 0)
 | 
			
		||||
            this._capturedEventId = this.connect('captured-event',
 | 
			
		||||
                                                 () => Clutter.EVENT_STOP);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _unmuteInput() {
 | 
			
		||||
        if (this._capturedEventId != 0) {
 | 
			
		||||
            this.disconnect(this._capturedEventId);
 | 
			
		||||
            this._capturedEventId = 0;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    open(animate, onComplete) {
 | 
			
		||||
        let themeNode = this.get_theme_node();
 | 
			
		||||
        let rise = themeNode.get_length('-arrow-rise');
 | 
			
		||||
@@ -105,7 +112,7 @@ var BoxPointer = GObject.registerClass({
 | 
			
		||||
            duration: animationTime,
 | 
			
		||||
            mode: Clutter.AnimationMode.LINEAR,
 | 
			
		||||
            onComplete: () => {
 | 
			
		||||
                this._muteInput = false;
 | 
			
		||||
                this._unmuteInput();
 | 
			
		||||
                if (onComplete)
 | 
			
		||||
                    onComplete();
 | 
			
		||||
            }
 | 
			
		||||
@@ -140,7 +147,7 @@ var BoxPointer = GObject.registerClass({
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._muteInput = true;
 | 
			
		||||
        this._muteInput();
 | 
			
		||||
 | 
			
		||||
        this.remove_all_transitions();
 | 
			
		||||
        this.ease({
 | 
			
		||||
 
 | 
			
		||||
@@ -313,10 +313,8 @@ var DBusEventSource = class DBusEventSource {
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(DBusEventSource.prototype);
 | 
			
		||||
 | 
			
		||||
var Calendar = GObject.registerClass({
 | 
			
		||||
    Signals: { 'selected-date-changed': { param_types: [GLib.DateTime.$gtype] } }
 | 
			
		||||
}, class Calendar extends St.Widget {
 | 
			
		||||
    _init() {
 | 
			
		||||
var Calendar = class Calendar {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        this._weekStart = Shell.util_get_week_start();
 | 
			
		||||
        this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.calendar' });
 | 
			
		||||
 | 
			
		||||
@@ -346,11 +344,12 @@ var Calendar = GObject.registerClass({
 | 
			
		||||
 | 
			
		||||
        this._shouldDateGrabFocus = false;
 | 
			
		||||
 | 
			
		||||
        super._init({
 | 
			
		||||
            style_class: 'calendar',
 | 
			
		||||
            layout_manager: new Clutter.TableLayout(),
 | 
			
		||||
            reactive: true
 | 
			
		||||
        });
 | 
			
		||||
        this.actor = new St.Widget({ style_class: 'calendar',
 | 
			
		||||
                                     layout_manager: new Clutter.TableLayout(),
 | 
			
		||||
                                     reactive: true });
 | 
			
		||||
 | 
			
		||||
        this.actor.connect('scroll-event',
 | 
			
		||||
                           this._onScroll.bind(this));
 | 
			
		||||
 | 
			
		||||
        this._buildHeader ();
 | 
			
		||||
    }
 | 
			
		||||
@@ -374,10 +373,7 @@ var Calendar = GObject.registerClass({
 | 
			
		||||
 | 
			
		||||
        this._selectedDate = date;
 | 
			
		||||
        this._update();
 | 
			
		||||
 | 
			
		||||
        let datetime = GLib.DateTime.new_from_unix_local(
 | 
			
		||||
            this._selectedDate.getTime() / 1000);
 | 
			
		||||
        this.emit('selected-date-changed', datetime);
 | 
			
		||||
        this.emit('selected-date-changed', new Date(this._selectedDate));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    updateTimeZone() {
 | 
			
		||||
@@ -388,9 +384,9 @@ var Calendar = GObject.registerClass({
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _buildHeader() {
 | 
			
		||||
        let layout = this.layout_manager;
 | 
			
		||||
        let layout = this.actor.layout_manager;
 | 
			
		||||
        let offsetCols = this._useWeekdate ? 1 : 0;
 | 
			
		||||
        this.destroy_all_children();
 | 
			
		||||
        this.actor.destroy_all_children();
 | 
			
		||||
 | 
			
		||||
        // Top line of the calendar '<| September 2009 |>'
 | 
			
		||||
        this._topBox = new St.BoxLayout();
 | 
			
		||||
@@ -432,7 +428,7 @@ var Calendar = GObject.registerClass({
 | 
			
		||||
                                       can_focus: true });
 | 
			
		||||
            label.accessible_name = iter.toLocaleFormat('%A');
 | 
			
		||||
            let col;
 | 
			
		||||
            if (this.get_text_direction() == Clutter.TextDirection.RTL)
 | 
			
		||||
            if (this.actor.get_text_direction() == Clutter.TextDirection.RTL)
 | 
			
		||||
                col = 6 - (7 + iter.getDay() - this._weekStart) % 7;
 | 
			
		||||
            else
 | 
			
		||||
                col = offsetCols + (7 + iter.getDay() - this._weekStart) % 7;
 | 
			
		||||
@@ -441,11 +437,11 @@ var Calendar = GObject.registerClass({
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // All the children after this are days, and get removed when we update the calendar
 | 
			
		||||
        this._firstDayIndex = this.get_n_children();
 | 
			
		||||
        this._firstDayIndex = this.actor.get_n_children();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_scroll_event(scrollEvent) {
 | 
			
		||||
        switch (scrollEvent.direction) {
 | 
			
		||||
    _onScroll(actor, event) {
 | 
			
		||||
        switch (event.get_scroll_direction()) {
 | 
			
		||||
        case Clutter.ScrollDirection.UP:
 | 
			
		||||
        case Clutter.ScrollDirection.LEFT:
 | 
			
		||||
            this._onPrevMonthButtonClicked();
 | 
			
		||||
@@ -515,7 +511,7 @@ var Calendar = GObject.registerClass({
 | 
			
		||||
        let now = new Date();
 | 
			
		||||
 | 
			
		||||
        // Remove everything but the topBox and the weekday labels
 | 
			
		||||
        let children = this.get_children();
 | 
			
		||||
        let children = this.actor.get_children();
 | 
			
		||||
        for (let i = this._firstDayIndex; i < children.length; i++)
 | 
			
		||||
            children[i].destroy();
 | 
			
		||||
 | 
			
		||||
@@ -552,7 +548,7 @@ var Calendar = GObject.registerClass({
 | 
			
		||||
 | 
			
		||||
        beginDate.setTime(beginDate.getTime() - (weekPadding + daysToWeekStart) * MSECS_IN_DAY);
 | 
			
		||||
 | 
			
		||||
        let layout = this.layout_manager;
 | 
			
		||||
        let layout = this.actor.layout_manager;
 | 
			
		||||
        let iter = new Date(beginDate);
 | 
			
		||||
        let row = 2;
 | 
			
		||||
        // nRows here means 6 weeks + one header + one navbar
 | 
			
		||||
@@ -652,12 +648,12 @@ var Calendar = GObject.registerClass({
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(Calendar.prototype);
 | 
			
		||||
 | 
			
		||||
var EventMessage = GObject.registerClass(
 | 
			
		||||
class EventMessage extends MessageList.Message {
 | 
			
		||||
    _init(event, date) {
 | 
			
		||||
        super._init('', event.summary);
 | 
			
		||||
var EventMessage = class EventMessage extends MessageList.Message {
 | 
			
		||||
    constructor(event, date) {
 | 
			
		||||
        super('', event.summary);
 | 
			
		||||
 | 
			
		||||
        this._event = event;
 | 
			
		||||
        this._date = date;
 | 
			
		||||
@@ -666,12 +662,11 @@ class EventMessage extends MessageList.Message {
 | 
			
		||||
 | 
			
		||||
        this._icon = new St.Icon({ icon_name: 'x-office-calendar-symbolic' });
 | 
			
		||||
        this.setIcon(this._icon);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_style_changed() {
 | 
			
		||||
        let iconVisible = this.get_parent().has_style_pseudo_class('first-child');
 | 
			
		||||
        this._icon.opacity = (iconVisible ? 255 : 0);
 | 
			
		||||
        super.vfunc_style_changed();
 | 
			
		||||
        this.actor.connect('style-changed', () => {
 | 
			
		||||
            let iconVisible = this.actor.get_parent().has_style_pseudo_class('first-child');
 | 
			
		||||
            this._icon.opacity = (iconVisible ? 255 : 0);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _formatEventTime() {
 | 
			
		||||
@@ -707,12 +702,12 @@ class EventMessage extends MessageList.Message {
 | 
			
		||||
        }
 | 
			
		||||
        return title;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var NotificationMessage = GObject.registerClass(
 | 
			
		||||
var NotificationMessage =
 | 
			
		||||
class NotificationMessage extends MessageList.Message {
 | 
			
		||||
    _init(notification) {
 | 
			
		||||
        super._init(notification.title, notification.bannerBodyText);
 | 
			
		||||
    constructor(notification) {
 | 
			
		||||
        super(notification.title, notification.bannerBodyText);
 | 
			
		||||
        this.setUseBodyMarkup(notification.bannerBodyMarkup);
 | 
			
		||||
 | 
			
		||||
        this.notification = notification;
 | 
			
		||||
@@ -749,7 +744,7 @@ class NotificationMessage extends MessageList.Message {
 | 
			
		||||
        this.setUseBodyMarkup(n.bannerBodyMarkup);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_clicked() {
 | 
			
		||||
    _onClicked() {
 | 
			
		||||
        this.notification.activate();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -771,12 +766,11 @@ class NotificationMessage extends MessageList.Message {
 | 
			
		||||
    canClose() {
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var EventsSection = GObject.registerClass(
 | 
			
		||||
class EventsSection extends MessageList.MessageListSection {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init();
 | 
			
		||||
var EventsSection = class EventsSection extends MessageList.MessageListSection {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        super();
 | 
			
		||||
 | 
			
		||||
        this._desktopSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.interface' });
 | 
			
		||||
        this._desktopSettings.connect('changed', this._reloadEvents.bind(this));
 | 
			
		||||
@@ -788,7 +782,7 @@ class EventsSection extends MessageList.MessageListSection {
 | 
			
		||||
                                      label: '',
 | 
			
		||||
                                      x_align: St.Align.START,
 | 
			
		||||
                                      can_focus: true });
 | 
			
		||||
        this.insert_child_below(this._title, null);
 | 
			
		||||
        this.actor.insert_child_below(this._title, null);
 | 
			
		||||
 | 
			
		||||
        this._title.connect('clicked', this._onTitleClicked.bind(this));
 | 
			
		||||
        this._title.connect('key-focus-in', this._onKeyFocusIn.bind(this));
 | 
			
		||||
@@ -907,29 +901,12 @@ class EventsSection extends MessageList.MessageListSection {
 | 
			
		||||
 | 
			
		||||
        super._sync();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var TimeLabel = GObject.registerClass(
 | 
			
		||||
class NotificationTimeLabel extends St.Label {
 | 
			
		||||
    _init(datetime) {
 | 
			
		||||
        super._init({
 | 
			
		||||
            style_class: 'event-time',
 | 
			
		||||
            x_align: Clutter.ActorAlign.START,
 | 
			
		||||
            y_align: Clutter.ActorAlign.END
 | 
			
		||||
        });
 | 
			
		||||
        this._datetime = datetime;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_map() {
 | 
			
		||||
        this.text = Util.formatTimeSpan(this._datetime);
 | 
			
		||||
        super.vfunc_map();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
var NotificationSection = GObject.registerClass(
 | 
			
		||||
var NotificationSection =
 | 
			
		||||
class NotificationSection extends MessageList.MessageListSection {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init();
 | 
			
		||||
    constructor() {
 | 
			
		||||
        super();
 | 
			
		||||
 | 
			
		||||
        this._sources = new Map();
 | 
			
		||||
        this._nUrgent = 0;
 | 
			
		||||
@@ -938,6 +915,8 @@ class NotificationSection extends MessageList.MessageListSection {
 | 
			
		||||
        Main.messageTray.getSources().forEach(source => {
 | 
			
		||||
            this._sourceAdded(Main.messageTray, source);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this.actor.connect('notify::mapped', this._onMapped.bind(this));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get allowed() {
 | 
			
		||||
@@ -945,6 +924,17 @@ class NotificationSection extends MessageList.MessageListSection {
 | 
			
		||||
               !Main.sessionMode.isGreeter;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _createTimeLabel(datetime) {
 | 
			
		||||
        let label = new St.Label({ style_class: 'event-time',
 | 
			
		||||
                                   x_align: Clutter.ActorAlign.START,
 | 
			
		||||
                                   y_align: Clutter.ActorAlign.END });
 | 
			
		||||
        label.connect('notify::mapped', () => {
 | 
			
		||||
            if (label.mapped)
 | 
			
		||||
                label.text = Util.formatTimeSpan(datetime);
 | 
			
		||||
        });
 | 
			
		||||
        return label;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _sourceAdded(tray, source) {
 | 
			
		||||
        let obj = {
 | 
			
		||||
            destroyId: 0,
 | 
			
		||||
@@ -962,13 +952,13 @@ class NotificationSection extends MessageList.MessageListSection {
 | 
			
		||||
 | 
			
		||||
    _onNotificationAdded(source, notification) {
 | 
			
		||||
        let message = new NotificationMessage(notification);
 | 
			
		||||
        message.setSecondaryActor(new TimeLabel(notification.datetime));
 | 
			
		||||
        message.setSecondaryActor(this._createTimeLabel(notification.datetime));
 | 
			
		||||
 | 
			
		||||
        let isUrgent = notification.urgency == MessageTray.Urgency.CRITICAL;
 | 
			
		||||
 | 
			
		||||
        let updatedId = notification.connect('updated', () => {
 | 
			
		||||
            message.setSecondaryActor(new TimeLabel(notification.datetime));
 | 
			
		||||
            this.moveMessage(message, isUrgent ? 0 : this._nUrgent, this.mapped);
 | 
			
		||||
            message.setSecondaryActor(this._createTimeLabel(notification.datetime));
 | 
			
		||||
            this.moveMessage(message, isUrgent ? 0 : this._nUrgent, this.actor.mapped);
 | 
			
		||||
        });
 | 
			
		||||
        let destroyId = notification.connect('destroy', () => {
 | 
			
		||||
            notification.disconnect(destroyId);
 | 
			
		||||
@@ -988,7 +978,7 @@ class NotificationSection extends MessageList.MessageListSection {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let index = isUrgent ? 0 : this._nUrgent;
 | 
			
		||||
        this.addMessageAtIndex(message, index, this.mapped);
 | 
			
		||||
        this.addMessageAtIndex(message, index, this.actor.mapped);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onSourceDestroy(source, obj) {
 | 
			
		||||
@@ -998,23 +988,25 @@ class NotificationSection extends MessageList.MessageListSection {
 | 
			
		||||
        this._sources.delete(source);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_map() {
 | 
			
		||||
        this._messages.forEach(message => {
 | 
			
		||||
    _onMapped() {
 | 
			
		||||
        if (!this.actor.mapped)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        for (let message of this._messages.keys())
 | 
			
		||||
            if (message.notification.urgency != MessageTray.Urgency.CRITICAL)
 | 
			
		||||
                message.notification.acknowledged = true;
 | 
			
		||||
        });
 | 
			
		||||
        super.vfunc_map();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _shouldShow() {
 | 
			
		||||
        return !this.empty && isToday(this._date);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var Placeholder = class Placeholder {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        this.actor = new St.BoxLayout({ style_class: 'message-list-placeholder',
 | 
			
		||||
                                        vertical: true });
 | 
			
		||||
 | 
			
		||||
var Placeholder = GObject.registerClass(
 | 
			
		||||
class Placeholder extends St.BoxLayout {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init({ style_class: 'message-list-placeholder', vertical: true });
 | 
			
		||||
        this._date = new Date();
 | 
			
		||||
 | 
			
		||||
        let todayFile = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/no-notifications.svg');
 | 
			
		||||
@@ -1023,10 +1015,10 @@ class Placeholder extends St.BoxLayout {
 | 
			
		||||
        this._otherIcon = new Gio.FileIcon({ file: otherFile });
 | 
			
		||||
 | 
			
		||||
        this._icon = new St.Icon();
 | 
			
		||||
        this.add_actor(this._icon);
 | 
			
		||||
        this.actor.add_actor(this._icon);
 | 
			
		||||
 | 
			
		||||
        this._label = new St.Label();
 | 
			
		||||
        this.add_actor(this._label);
 | 
			
		||||
        this.actor.add_actor(this._label);
 | 
			
		||||
 | 
			
		||||
        this._sync();
 | 
			
		||||
    }
 | 
			
		||||
@@ -1053,24 +1045,20 @@ class Placeholder extends St.BoxLayout {
 | 
			
		||||
            this._label.text = _("No Events");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var CalendarMessageList = GObject.registerClass(
 | 
			
		||||
class CalendarMessageList extends St.Widget {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init({
 | 
			
		||||
            style_class: 'message-list',
 | 
			
		||||
            layout_manager: new Clutter.BinLayout(),
 | 
			
		||||
            x_expand: true,
 | 
			
		||||
            y_expand: true
 | 
			
		||||
        });
 | 
			
		||||
var CalendarMessageList = class CalendarMessageList {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        this.actor = new St.Widget({ style_class: 'message-list',
 | 
			
		||||
                                     layout_manager: new Clutter.BinLayout(),
 | 
			
		||||
                                     x_expand: true, y_expand: true });
 | 
			
		||||
 | 
			
		||||
        this._placeholder = new Placeholder();
 | 
			
		||||
        this.add_actor(this._placeholder);
 | 
			
		||||
        this.actor.add_actor(this._placeholder.actor);
 | 
			
		||||
 | 
			
		||||
        let box = new St.BoxLayout({ vertical: true,
 | 
			
		||||
                                     x_expand: true, y_expand: true });
 | 
			
		||||
        this.add_actor(box);
 | 
			
		||||
        this.actor.add_actor(box);
 | 
			
		||||
 | 
			
		||||
        this._scrollView = new St.ScrollView({ style_class: 'vfade',
 | 
			
		||||
                                               overlay_scrollbars: true,
 | 
			
		||||
@@ -1084,11 +1072,12 @@ class CalendarMessageList extends St.Widget {
 | 
			
		||||
                                            can_focus: true });
 | 
			
		||||
        this._clearButton.set_x_align(Clutter.ActorAlign.END);
 | 
			
		||||
        this._clearButton.connect('clicked', () => {
 | 
			
		||||
            this._sectionList.get_children().forEach(s => s.clear());
 | 
			
		||||
            let sections = [...this._sections.keys()];
 | 
			
		||||
            sections.forEach(s => s.clear());
 | 
			
		||||
        });
 | 
			
		||||
        box.add_actor(this._clearButton);
 | 
			
		||||
 | 
			
		||||
        this._placeholder.bind_property('visible',
 | 
			
		||||
        this._placeholder.actor.bind_property('visible',
 | 
			
		||||
            this._clearButton, 'visible',
 | 
			
		||||
            GObject.BindingFlags.INVERT_BOOLEAN);
 | 
			
		||||
 | 
			
		||||
@@ -1096,9 +1085,8 @@ class CalendarMessageList extends St.Widget {
 | 
			
		||||
                                               vertical: true,
 | 
			
		||||
                                               y_expand: true,
 | 
			
		||||
                                               y_align: Clutter.ActorAlign.START });
 | 
			
		||||
        this._sectionList.connect('actor-added', this._sync.bind(this));
 | 
			
		||||
        this._sectionList.connect('actor-removed', this._sync.bind(this));
 | 
			
		||||
        this._scrollView.add_actor(this._sectionList);
 | 
			
		||||
        this._sections = new Map();
 | 
			
		||||
 | 
			
		||||
        this._mediaSection = new Mpris.MediaSection();
 | 
			
		||||
        this._addSection(this._mediaSection);
 | 
			
		||||
@@ -1113,35 +1101,58 @@ class CalendarMessageList extends St.Widget {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _addSection(section) {
 | 
			
		||||
        let connectionsIds = [];
 | 
			
		||||
        let obj = {
 | 
			
		||||
            destroyId: 0,
 | 
			
		||||
            visibleId: 0,
 | 
			
		||||
            emptyChangedId: 0,
 | 
			
		||||
            canClearChangedId: 0,
 | 
			
		||||
            keyFocusId: 0
 | 
			
		||||
        };
 | 
			
		||||
        obj.destroyId = section.actor.connect('destroy', () => {
 | 
			
		||||
            this._removeSection(section);
 | 
			
		||||
        });
 | 
			
		||||
        obj.visibleId = section.actor.connect('notify::visible',
 | 
			
		||||
                                              this._sync.bind(this));
 | 
			
		||||
        obj.emptyChangedId = section.connect('empty-changed',
 | 
			
		||||
                                             this._sync.bind(this));
 | 
			
		||||
        obj.canClearChangedId = section.connect('can-clear-changed',
 | 
			
		||||
                                                this._sync.bind(this));
 | 
			
		||||
        obj.keyFocusId = section.connect('key-focus-in',
 | 
			
		||||
                                         this._onKeyFocusIn.bind(this));
 | 
			
		||||
 | 
			
		||||
        for (let prop of ['visible', 'empty', 'can-clear']) {
 | 
			
		||||
            connectionsIds.push(
 | 
			
		||||
                section.connect(`notify::${prop}`, this._sync.bind(this)));
 | 
			
		||||
        }
 | 
			
		||||
        connectionsIds.push(section.connect('message-focused', (_s, messageActor) => {
 | 
			
		||||
            Util.ensureActorVisibleInScrollView(this._scrollView, messageActor);
 | 
			
		||||
        }));
 | 
			
		||||
        this._sections.set(section, obj);
 | 
			
		||||
        this._sectionList.add_actor(section.actor);
 | 
			
		||||
        this._sync();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
        connectionsIds.push(section.connect('destroy', (section) => {
 | 
			
		||||
            connectionsIds.forEach(id => section.disconnect(id));
 | 
			
		||||
            this._sectionList.remove_actor(section);
 | 
			
		||||
        }));
 | 
			
		||||
    _removeSection(section) {
 | 
			
		||||
        let obj = this._sections.get(section);
 | 
			
		||||
        section.actor.disconnect(obj.destroyId);
 | 
			
		||||
        section.actor.disconnect(obj.visibleId);
 | 
			
		||||
        section.disconnect(obj.emptyChangedId);
 | 
			
		||||
        section.disconnect(obj.canClearChangedId);
 | 
			
		||||
        section.disconnect(obj.keyFocusId);
 | 
			
		||||
 | 
			
		||||
        this._sectionList.add_actor(section);
 | 
			
		||||
        this._sections.delete(section);
 | 
			
		||||
        this._sectionList.remove_actor(section.actor);
 | 
			
		||||
        this._sync();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onKeyFocusIn(section, actor) {
 | 
			
		||||
        Util.ensureActorVisibleInScrollView(this._scrollView, actor);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _sync() {
 | 
			
		||||
        let sections = this._sectionList.get_children();
 | 
			
		||||
        let sections = [...this._sections.keys()];
 | 
			
		||||
        let visible = sections.some(s => s.allowed);
 | 
			
		||||
        this.visible = visible;
 | 
			
		||||
        this.actor.visible = visible;
 | 
			
		||||
        if (!visible)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let empty = sections.every(s => s.empty || !s.visible);
 | 
			
		||||
        this._placeholder.visible = empty;
 | 
			
		||||
        let empty = sections.every(s => s.empty || !s.actor.visible);
 | 
			
		||||
        this._placeholder.actor.visible = empty;
 | 
			
		||||
 | 
			
		||||
        let canClear = sections.some(s => s.canClear && s.visible);
 | 
			
		||||
        let canClear = sections.some(s => s.canClear && s.actor.visible);
 | 
			
		||||
        this._clearButton.reactive = canClear;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -1150,7 +1161,8 @@ class CalendarMessageList extends St.Widget {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    setDate(date) {
 | 
			
		||||
        this._sectionList.get_children().forEach(s => s.setDate(date));
 | 
			
		||||
        for (let section of this._sections.keys())
 | 
			
		||||
            section.setDate(date);
 | 
			
		||||
        this._placeholder.setDate(date);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -1,19 +1,16 @@
 | 
			
		||||
/* exported CheckBox */
 | 
			
		||||
const { Clutter, GObject, Pango, St } = imports.gi;
 | 
			
		||||
const { Clutter, Pango, St } = imports.gi;
 | 
			
		||||
 | 
			
		||||
var CheckBox = GObject.registerClass(
 | 
			
		||||
class CheckBox extends St.Button {
 | 
			
		||||
    _init(label) {
 | 
			
		||||
var CheckBox = class CheckBox {
 | 
			
		||||
    constructor(label) {
 | 
			
		||||
        let container = new St.BoxLayout();
 | 
			
		||||
        super._init({
 | 
			
		||||
            style_class: 'check-box',
 | 
			
		||||
            child: container,
 | 
			
		||||
            button_mask: St.ButtonMask.ONE,
 | 
			
		||||
            toggle_mode: true,
 | 
			
		||||
            can_focus: true,
 | 
			
		||||
            x_fill: true,
 | 
			
		||||
            y_fill: true
 | 
			
		||||
        });
 | 
			
		||||
        this.actor = new St.Button({ style_class: 'check-box',
 | 
			
		||||
                                     child: container,
 | 
			
		||||
                                     button_mask: St.ButtonMask.ONE,
 | 
			
		||||
                                     toggle_mode: true,
 | 
			
		||||
                                     can_focus: true,
 | 
			
		||||
                                     x_fill: true,
 | 
			
		||||
                                     y_fill: true });
 | 
			
		||||
 | 
			
		||||
        this._box = new St.Bin();
 | 
			
		||||
        this._box.set_y_align(Clutter.ActorAlign.START);
 | 
			
		||||
@@ -35,4 +32,4 @@ class CheckBox extends St.Button {
 | 
			
		||||
    getLabelActor() {
 | 
			
		||||
        return this._label;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/* exported Component */
 | 
			
		||||
 | 
			
		||||
const { Gio, GObject, St } = imports.gi;
 | 
			
		||||
const { Gio, St } = imports.gi;
 | 
			
		||||
 | 
			
		||||
const GnomeSession = imports.misc.gnomeSession;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
@@ -272,10 +272,9 @@ var AutorunDispatcher = class {
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var AutorunSource = GObject.registerClass(
 | 
			
		||||
class AutorunSource extends MessageTray.Source {
 | 
			
		||||
    _init(manager, mount, apps) {
 | 
			
		||||
        super._init(mount.get_name());
 | 
			
		||||
var AutorunSource = class extends MessageTray.Source {
 | 
			
		||||
    constructor(manager, mount, apps) {
 | 
			
		||||
        super(mount.get_name());
 | 
			
		||||
 | 
			
		||||
        this._manager = manager;
 | 
			
		||||
        this.mount = mount;
 | 
			
		||||
@@ -285,7 +284,7 @@ class AutorunSource extends MessageTray.Source {
 | 
			
		||||
 | 
			
		||||
        // add ourselves as a source, and popup the notification
 | 
			
		||||
        Main.messageTray.add(this);
 | 
			
		||||
        this.showNotification(this._notification);
 | 
			
		||||
        this.notify(this._notification);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    getIcon() {
 | 
			
		||||
@@ -295,12 +294,11 @@ class AutorunSource extends MessageTray.Source {
 | 
			
		||||
    _createPolicy() {
 | 
			
		||||
        return new MessageTray.NotificationApplicationPolicy('org.gnome.Nautilus');
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var AutorunNotification = GObject.registerClass(
 | 
			
		||||
class AutorunNotification extends MessageTray.Notification {
 | 
			
		||||
    _init(manager, source) {
 | 
			
		||||
        super._init(source, source.title);
 | 
			
		||||
var AutorunNotification = class extends MessageTray.Notification {
 | 
			
		||||
    constructor(manager, source) {
 | 
			
		||||
        super(source, source.title);
 | 
			
		||||
 | 
			
		||||
        this._manager = manager;
 | 
			
		||||
        this._mount = source.mount;
 | 
			
		||||
@@ -352,6 +350,6 @@ class AutorunNotification extends MessageTray.Notification {
 | 
			
		||||
        let app = Gio.app_info_get_default_for_type('inode/directory', false);
 | 
			
		||||
        startAppForMount(app, this._mount);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var Component = AutorunManager;
 | 
			
		||||
 
 | 
			
		||||
@@ -77,13 +77,13 @@ class KeyringDialog extends ModalDialog.ModalDialog {
 | 
			
		||||
            this._workSpinner = new Animation.Spinner(WORK_SPINNER_ICON_SIZE, true);
 | 
			
		||||
 | 
			
		||||
            if (rtl) {
 | 
			
		||||
                layout.attach(this._workSpinner, 0, row, 1, 1);
 | 
			
		||||
                layout.attach(this._workSpinner.actor, 0, row, 1, 1);
 | 
			
		||||
                layout.attach(this._passwordEntry, 1, row, 1, 1);
 | 
			
		||||
                layout.attach(label, 2, row, 1, 1);
 | 
			
		||||
            } else {
 | 
			
		||||
                layout.attach(label, 0, row, 1, 1);
 | 
			
		||||
                layout.attach(this._passwordEntry, 1, row, 1, 1);
 | 
			
		||||
                layout.attach(this._workSpinner, 2, row, 1, 1);
 | 
			
		||||
                layout.attach(this._workSpinner.actor, 2, row, 1, 1);
 | 
			
		||||
            }
 | 
			
		||||
            row++;
 | 
			
		||||
        } else {
 | 
			
		||||
@@ -121,8 +121,8 @@ class KeyringDialog extends ModalDialog.ModalDialog {
 | 
			
		||||
        if (this.prompt.choice_visible) {
 | 
			
		||||
            let choice = new CheckBox.CheckBox();
 | 
			
		||||
            this.prompt.bind_property('choice-label', choice.getLabelActor(), 'text', GObject.BindingFlags.SYNC_CREATE);
 | 
			
		||||
            this.prompt.bind_property('choice-chosen', choice, 'checked', GObject.BindingFlags.SYNC_CREATE | GObject.BindingFlags.BIDIRECTIONAL);
 | 
			
		||||
            layout.attach(choice, rtl ? 0 : 1, row, 1, 1);
 | 
			
		||||
            this.prompt.bind_property('choice-chosen', choice.actor, 'checked', GObject.BindingFlags.SYNC_CREATE | GObject.BindingFlags.BIDIRECTIONAL);
 | 
			
		||||
            layout.attach(choice.actor, rtl ? 0 : 1, row, 1, 1);
 | 
			
		||||
            row++;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -734,7 +734,7 @@ var NetworkAgent = class {
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        Main.messageTray.add(source);
 | 
			
		||||
        source.showNotification(notification);
 | 
			
		||||
        source.notify(notification);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _newRequest(agent, requestId, connection, settingName, hints, flags) {
 | 
			
		||||
 
 | 
			
		||||
@@ -76,8 +76,8 @@ var AuthenticationDialog = GObject.registerClass({
 | 
			
		||||
            this._userAvatar = new UserWidget.Avatar(this._user,
 | 
			
		||||
                                                     { iconSize: DIALOG_ICON_SIZE,
 | 
			
		||||
                                                       styleClass: 'polkit-dialog-user-icon' });
 | 
			
		||||
            this._userAvatar.hide();
 | 
			
		||||
            userBox.add(this._userAvatar,
 | 
			
		||||
            this._userAvatar.actor.hide();
 | 
			
		||||
            userBox.add(this._userAvatar.actor,
 | 
			
		||||
                        { x_fill: true,
 | 
			
		||||
                          y_fill: false,
 | 
			
		||||
                          x_align: St.Align.END,
 | 
			
		||||
@@ -106,7 +106,7 @@ var AuthenticationDialog = GObject.registerClass({
 | 
			
		||||
                              { expand: true });
 | 
			
		||||
 | 
			
		||||
        this._workSpinner = new Animation.Spinner(WORK_SPINNER_ICON_SIZE, true);
 | 
			
		||||
        this._passwordBox.add(this._workSpinner);
 | 
			
		||||
        this._passwordBox.add(this._workSpinner.actor);
 | 
			
		||||
 | 
			
		||||
        this.setInitialKeyFocus(this._passwordEntry);
 | 
			
		||||
        this._passwordBox.hide();
 | 
			
		||||
@@ -305,7 +305,7 @@ var AuthenticationDialog = GObject.registerClass({
 | 
			
		||||
    _onUserChanged() {
 | 
			
		||||
        if (this._user.is_loaded && this._userAvatar) {
 | 
			
		||||
            this._userAvatar.update();
 | 
			
		||||
            this._userAvatar.show();
 | 
			
		||||
            this._userAvatar.actor.show();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -215,7 +215,7 @@ class TelepathyClient extends Tp.BaseClient {
 | 
			
		||||
                // We are already handling the channel, display the source
 | 
			
		||||
                let source = this._chatSources[channel.get_object_path()];
 | 
			
		||||
                if (source)
 | 
			
		||||
                    source.showNotification();
 | 
			
		||||
                    source.notify();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@@ -266,10 +266,9 @@ class TelepathyClient extends Tp.BaseClient {
 | 
			
		||||
    }
 | 
			
		||||
}) : null;
 | 
			
		||||
 | 
			
		||||
var ChatSource = HAVE_TP ? GObject.registerClass(
 | 
			
		||||
class ChatSource extends MessageTray.Source {
 | 
			
		||||
    _init(account, conn, channel, contact, client) {
 | 
			
		||||
        super._init(contact.get_alias());
 | 
			
		||||
var ChatSource = class extends MessageTray.Source {
 | 
			
		||||
    constructor(account, conn, channel, contact, client) {
 | 
			
		||||
        super(contact.get_alias());
 | 
			
		||||
 | 
			
		||||
        this._account = account;
 | 
			
		||||
        this._contact = contact;
 | 
			
		||||
@@ -327,7 +326,7 @@ class ChatSource extends MessageTray.Source {
 | 
			
		||||
 | 
			
		||||
        // We ack messages when the user expands the new notification
 | 
			
		||||
        let id = this._banner.connect('expanded', this._ackMessages.bind(this));
 | 
			
		||||
        this._banner.connect('destroy', () => {
 | 
			
		||||
        this._banner.actor.connect('destroy', () => {
 | 
			
		||||
            this._banner.disconnect(id);
 | 
			
		||||
            this._banner = null;
 | 
			
		||||
        });
 | 
			
		||||
@@ -477,7 +476,7 @@ class ChatSource extends MessageTray.Source {
 | 
			
		||||
            this._notification.appendMessage(pendingMessages[i], true);
 | 
			
		||||
 | 
			
		||||
        if (pendingMessages.length > 0)
 | 
			
		||||
            this.showNotification();
 | 
			
		||||
            this.notify();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    destroy(reason) {
 | 
			
		||||
@@ -554,7 +553,7 @@ class ChatSource extends MessageTray.Source {
 | 
			
		||||
 | 
			
		||||
    _notifyTimeout() {
 | 
			
		||||
        if (this._pendingMessages.length != 0)
 | 
			
		||||
            this.showNotification();
 | 
			
		||||
            this.notify();
 | 
			
		||||
 | 
			
		||||
        this._notifyTimeoutId = 0;
 | 
			
		||||
 | 
			
		||||
@@ -569,8 +568,8 @@ class ChatSource extends MessageTray.Source {
 | 
			
		||||
        this._notification.appendMessage(message);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    showNotification() {
 | 
			
		||||
        super.showNotification(this._notification);
 | 
			
		||||
    notify() {
 | 
			
		||||
        super.notify(this._notification);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    respond(text) {
 | 
			
		||||
@@ -626,18 +625,12 @@ class ChatSource extends MessageTray.Source {
 | 
			
		||||
        // 'pending-message-removed' for each one.
 | 
			
		||||
        this._channel.ack_all_pending_messages_async(null);
 | 
			
		||||
    }
 | 
			
		||||
}) : null;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var ChatNotification = HAVE_TP ? GObject.registerClass({
 | 
			
		||||
    Signals: {
 | 
			
		||||
        'message-removed': { param_types: [Tp.Message.$gtype] },
 | 
			
		||||
        'message-added': { param_types: [Tp.Message.$gtype] },
 | 
			
		||||
        'timestamp-changed': { param_types: [Tp.Message.$gtype] },
 | 
			
		||||
    }
 | 
			
		||||
}, class ChatNotification extends MessageTray.Notification {
 | 
			
		||||
    _init(source) {
 | 
			
		||||
        super._init(source, source.title, null,
 | 
			
		||||
            { secondaryGIcon: source.getSecondaryIcon() });
 | 
			
		||||
var ChatNotification = class extends MessageTray.Notification {
 | 
			
		||||
    constructor(source) {
 | 
			
		||||
        super(source, source.title, null,
 | 
			
		||||
              { secondaryGIcon: source.getSecondaryIcon() });
 | 
			
		||||
        this.setUrgency(MessageTray.Urgency.HIGH);
 | 
			
		||||
        this.setResident(true);
 | 
			
		||||
 | 
			
		||||
@@ -789,7 +782,7 @@ var ChatNotification = HAVE_TP ? GObject.registerClass({
 | 
			
		||||
 | 
			
		||||
        this._filterMessages();
 | 
			
		||||
    }
 | 
			
		||||
}) : null;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var ChatLineBox = GObject.registerClass(
 | 
			
		||||
class ChatLineBox extends St.BoxLayout {
 | 
			
		||||
@@ -799,10 +792,9 @@ class ChatLineBox extends St.BoxLayout {
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
var ChatNotificationBanner = GObject.registerClass(
 | 
			
		||||
class ChatNotificationBanner extends MessageTray.NotificationBanner {
 | 
			
		||||
    _init(notification) {
 | 
			
		||||
        super._init(notification);
 | 
			
		||||
var ChatNotificationBanner = class extends MessageTray.NotificationBanner {
 | 
			
		||||
    constructor(notification) {
 | 
			
		||||
        super(notification);
 | 
			
		||||
 | 
			
		||||
        this._responseEntry = new St.Entry({ style_class: 'chat-response',
 | 
			
		||||
                                             x_expand: true,
 | 
			
		||||
@@ -887,7 +879,8 @@ class ChatNotificationBanner extends MessageTray.NotificationBanner {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _addMessage(message) {
 | 
			
		||||
        let body = new MessageList.URLHighlighter(message.body, true, true);
 | 
			
		||||
        let highlighter = new MessageList.URLHighlighter(message.body, true, true);
 | 
			
		||||
        let body = highlighter.actor;
 | 
			
		||||
 | 
			
		||||
        let styles = message.styles;
 | 
			
		||||
        for (let i = 0; i < styles.length; i++)
 | 
			
		||||
@@ -975,6 +968,6 @@ class ChatNotificationBanner extends MessageTray.NotificationBanner {
 | 
			
		||||
            this.notification.source.setChatState(Tp.ChannelChatState.ACTIVE);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var Component = TelepathyComponent;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,8 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/* exported Dash */
 | 
			
		||||
 | 
			
		||||
const { Clutter, GLib, GObject,
 | 
			
		||||
        Graphene, Meta, Shell, St } = imports.gi;
 | 
			
		||||
const { Clutter, GLib, GObject, Meta, Shell, St } = imports.gi;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
 | 
			
		||||
const AppDisplay = imports.ui.appDisplay;
 | 
			
		||||
const AppFavorites = imports.ui.appFavorites;
 | 
			
		||||
@@ -23,10 +23,9 @@ function getAppFromSource(source) {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var DashIcon = GObject.registerClass(
 | 
			
		||||
class DashIcon extends AppDisplay.AppIcon {
 | 
			
		||||
    _init(app) {
 | 
			
		||||
        super._init(app, {
 | 
			
		||||
var DashIcon = class DashIcon extends AppDisplay.AppIcon {
 | 
			
		||||
    constructor(app) {
 | 
			
		||||
        super(app, {
 | 
			
		||||
            setSizeManually: true,
 | 
			
		||||
            showLabel: false
 | 
			
		||||
        });
 | 
			
		||||
@@ -46,7 +45,7 @@ class DashIcon extends AppDisplay.AppIcon {
 | 
			
		||||
    acceptDrop() {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// A container like StBin, but taking the child's scale into account
 | 
			
		||||
// when requesting a size
 | 
			
		||||
@@ -54,7 +53,7 @@ var DashItemContainer = GObject.registerClass(
 | 
			
		||||
class DashItemContainer extends St.Widget {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init({ style_class: 'dash-item-container',
 | 
			
		||||
                      pivot_point: new Graphene.Point({ x: .5, y: .5 }),
 | 
			
		||||
                      pivot_point: new Clutter.Point({ x: .5, y: .5 }),
 | 
			
		||||
                      scale_x: 0,
 | 
			
		||||
                      scale_y: 0,
 | 
			
		||||
                      opacity: 0,
 | 
			
		||||
@@ -331,10 +330,8 @@ class DashActor extends St.Widget {
 | 
			
		||||
 | 
			
		||||
const baseIconSizes = [16, 22, 24, 32, 48, 64];
 | 
			
		||||
 | 
			
		||||
var Dash = GObject.registerClass({
 | 
			
		||||
    Signals: { 'icon-size-changed': {} }
 | 
			
		||||
}, class Dash extends St.Bin {
 | 
			
		||||
    _init() {
 | 
			
		||||
var Dash = class Dash {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        this._maxHeight = -1;
 | 
			
		||||
        this.iconSize = 64;
 | 
			
		||||
        this._shownInitially = false;
 | 
			
		||||
@@ -362,11 +359,11 @@ var Dash = GObject.registerClass({
 | 
			
		||||
 | 
			
		||||
        this._container.add_actor(this._showAppsIcon);
 | 
			
		||||
 | 
			
		||||
        super._init({ child: this._container });
 | 
			
		||||
        this.connect('notify::height', () => {
 | 
			
		||||
            if (this._maxHeight != this.height)
 | 
			
		||||
        this.actor = new St.Bin({ child: this._container });
 | 
			
		||||
        this.actor.connect('notify::height', () => {
 | 
			
		||||
            if (this._maxHeight != this.actor.height)
 | 
			
		||||
                this._queueRedisplay();
 | 
			
		||||
            this._maxHeight = this.height;
 | 
			
		||||
            this._maxHeight = this.actor.height;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this._workId = Main.initializeDeferredWork(this._box, this._redisplay.bind(this));
 | 
			
		||||
@@ -389,7 +386,7 @@ var Dash = GObject.registerClass({
 | 
			
		||||
 | 
			
		||||
        // Translators: this is the name of the dock/favorites area on
 | 
			
		||||
        // the left of the overview
 | 
			
		||||
        Main.ctrlAltTabManager.addGroup(this, _("Dash"), 'user-bookmarks-symbolic');
 | 
			
		||||
        Main.ctrlAltTabManager.addGroup(this.actor, _("Dash"), 'user-bookmarks-symbolic');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onDragBegin() {
 | 
			
		||||
@@ -484,11 +481,11 @@ var Dash = GObject.registerClass({
 | 
			
		||||
                        });
 | 
			
		||||
 | 
			
		||||
        let item = new DashItemContainer();
 | 
			
		||||
        item.setChild(appIcon);
 | 
			
		||||
        item.setChild(appIcon.actor);
 | 
			
		||||
 | 
			
		||||
        // Override default AppIcon label_actor, now the
 | 
			
		||||
        // accessible_name is set at DashItemContainer.setLabelText
 | 
			
		||||
        appIcon.label_actor = null;
 | 
			
		||||
        appIcon.actor.label_actor = null;
 | 
			
		||||
        item.setLabelText(app.get_name());
 | 
			
		||||
 | 
			
		||||
        appIcon.icon.setIconSize(this.iconSize);
 | 
			
		||||
@@ -626,7 +623,7 @@ var Dash = GObject.registerClass({
 | 
			
		||||
            icon.icon.ease({
 | 
			
		||||
                width: targetWidth,
 | 
			
		||||
                height: targetHeight,
 | 
			
		||||
                duration: DASH_ANIMATION_TIME,
 | 
			
		||||
                time: DASH_ANIMATION_TIME,
 | 
			
		||||
                mode: Clutter.AnimationMode.EASE_OUT_QUAD
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
@@ -905,4 +902,5 @@ var Dash = GObject.registerClass({
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(Dash.prototype);
 | 
			
		||||
 
 | 
			
		||||
@@ -25,26 +25,24 @@ function _isToday(date) {
 | 
			
		||||
           now.getDate() == date.getDate();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function _gDateTimeToDate(datetime) {
 | 
			
		||||
    return new Date(datetime.to_unix() * 1000 + datetime.get_microsecond() / 1000);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var TodayButton = GObject.registerClass(
 | 
			
		||||
class TodayButton extends St.Button {
 | 
			
		||||
    _init(calendar) {
 | 
			
		||||
var TodayButton = class TodayButton {
 | 
			
		||||
    constructor(calendar) {
 | 
			
		||||
        // Having the ability to go to the current date if the user is already
 | 
			
		||||
        // on the current date can be confusing. So don't make the button reactive
 | 
			
		||||
        // until the selected date changes.
 | 
			
		||||
        super._init({
 | 
			
		||||
        this.actor = new St.Button({
 | 
			
		||||
            style_class: 'datemenu-today-button',
 | 
			
		||||
            x_align: St.Align.START,
 | 
			
		||||
            x_expand: true,
 | 
			
		||||
            can_focus: true,
 | 
			
		||||
            reactive: false
 | 
			
		||||
            reactive: false,
 | 
			
		||||
        });
 | 
			
		||||
        this.actor.connect('clicked', () => {
 | 
			
		||||
            this._calendar.setDate(new Date(), false);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        let hbox = new St.BoxLayout({ vertical: true });
 | 
			
		||||
        this.add_actor(hbox);
 | 
			
		||||
        this.actor.add_actor(hbox);
 | 
			
		||||
 | 
			
		||||
        this._dayLabel = new St.Label({ style_class: 'day-label',
 | 
			
		||||
                                        x_align: Clutter.ActorAlign.START });
 | 
			
		||||
@@ -54,17 +52,13 @@ class TodayButton extends St.Button {
 | 
			
		||||
        hbox.add_actor(this._dateLabel);
 | 
			
		||||
 | 
			
		||||
        this._calendar = calendar;
 | 
			
		||||
        this._calendar.connect('selected-date-changed', (_calendar, datetime) => {
 | 
			
		||||
        this._calendar.connect('selected-date-changed', (calendar, date) => {
 | 
			
		||||
            // Make the button reactive only if the selected date is not the
 | 
			
		||||
            // current date.
 | 
			
		||||
            this.reactive = !_isToday(_gDateTimeToDate(datetime));
 | 
			
		||||
            this.actor.reactive = !_isToday(date);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_clicked() {
 | 
			
		||||
        this._calendar.setDate(new Date(), false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    setDate(date) {
 | 
			
		||||
        this._dayLabel.set_text(date.toLocaleFormat('%A'));
 | 
			
		||||
 | 
			
		||||
@@ -81,29 +75,34 @@ class TodayButton extends St.Button {
 | 
			
		||||
         * date, e.g. "Tuesday February 17 2015".
 | 
			
		||||
         */
 | 
			
		||||
        dateFormat = Shell.util_translate_time_string (N_("%A %B %e %Y"));
 | 
			
		||||
        this.accessible_name = date.toLocaleFormat(dateFormat);
 | 
			
		||||
        this.actor.accessible_name = date.toLocaleFormat(dateFormat);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var WorldClocksSection = GObject.registerClass(
 | 
			
		||||
class WorldClocksSection extends St.Button {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init({
 | 
			
		||||
            style_class: 'world-clocks-button',
 | 
			
		||||
            x_fill: true,
 | 
			
		||||
            can_focus: true
 | 
			
		||||
        });
 | 
			
		||||
var WorldClocksSection = class WorldClocksSection {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        this._clock = new GnomeDesktop.WallClock();
 | 
			
		||||
        this._clockNotifyId = 0;
 | 
			
		||||
 | 
			
		||||
        this._locations = [];
 | 
			
		||||
 | 
			
		||||
        this.actor = new St.Button({ style_class: 'world-clocks-button',
 | 
			
		||||
                                     x_fill: true,
 | 
			
		||||
                                     can_focus: true });
 | 
			
		||||
        this.actor.connect('clicked', () => {
 | 
			
		||||
            if (this._clocksApp)
 | 
			
		||||
                this._clocksApp.activate();
 | 
			
		||||
 | 
			
		||||
            Main.overview.hide();
 | 
			
		||||
            Main.panel.closeCalendar();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        let layout = new Clutter.GridLayout({ orientation: Clutter.Orientation.VERTICAL });
 | 
			
		||||
        this._grid = new St.Widget({ style_class: 'world-clocks-grid',
 | 
			
		||||
                                     layout_manager: layout });
 | 
			
		||||
        layout.hookup_style(this._grid);
 | 
			
		||||
 | 
			
		||||
        this.child = this._grid;
 | 
			
		||||
        this.actor.child = this._grid;
 | 
			
		||||
 | 
			
		||||
        this._clocksApp = null;
 | 
			
		||||
        this._clocksProxy = new ClocksProxy(
 | 
			
		||||
@@ -126,17 +125,9 @@ class WorldClocksSection extends St.Button {
 | 
			
		||||
        this._sync();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_clicked() {
 | 
			
		||||
        if (this._clocksApp)
 | 
			
		||||
            this._clocksApp.activate();
 | 
			
		||||
 | 
			
		||||
        Main.overview.hide();
 | 
			
		||||
        Main.panel.closeCalendar();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _sync() {
 | 
			
		||||
        this._clocksApp = this._appSystem.lookup_app('org.gnome.clocks.desktop');
 | 
			
		||||
        this.visible = this._clocksApp != null;
 | 
			
		||||
        this.actor.visible = this._clocksApp != null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _clocksChanged() {
 | 
			
		||||
@@ -164,7 +155,7 @@ class WorldClocksSection extends St.Button {
 | 
			
		||||
                                    x_align: Clutter.ActorAlign.START,
 | 
			
		||||
                                    text: title });
 | 
			
		||||
        layout.attach(header, 0, 0, 2, 1);
 | 
			
		||||
        this.label_actor = header;
 | 
			
		||||
        this.actor.label_actor = header;
 | 
			
		||||
 | 
			
		||||
        let localOffset = GLib.DateTime.new_now_local().get_utc_offset();
 | 
			
		||||
 | 
			
		||||
@@ -245,23 +236,30 @@ class WorldClocksSection extends St.Button {
 | 
			
		||||
        this._settings.set_value('locations',
 | 
			
		||||
            new GLib.Variant('av', this._clocksProxy.Locations));
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
var WeatherSection = GObject.registerClass(
 | 
			
		||||
class WeatherSection extends St.Button {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init({
 | 
			
		||||
            style_class: 'weather-button',
 | 
			
		||||
            x_fill: true,
 | 
			
		||||
            can_focus: true
 | 
			
		||||
        });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var WeatherSection = class WeatherSection {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        this._weatherClient = new Weather.WeatherClient();
 | 
			
		||||
 | 
			
		||||
        this.actor = new St.Button({ style_class: 'weather-button',
 | 
			
		||||
                                     x_fill: true,
 | 
			
		||||
                                     can_focus: true });
 | 
			
		||||
        this.actor.connect('clicked', () => {
 | 
			
		||||
            this._weatherClient.activateApp();
 | 
			
		||||
 | 
			
		||||
            Main.overview.hide();
 | 
			
		||||
            Main.panel.closeCalendar();
 | 
			
		||||
        });
 | 
			
		||||
        this.actor.connect('notify::mapped', () => {
 | 
			
		||||
            if (this.actor.mapped)
 | 
			
		||||
                this._weatherClient.update();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        let box = new St.BoxLayout({ style_class: 'weather-box',
 | 
			
		||||
                                     vertical: true });
 | 
			
		||||
 | 
			
		||||
        this.child = box;
 | 
			
		||||
        this.actor.child = box;
 | 
			
		||||
 | 
			
		||||
        let titleBox = new St.BoxLayout();
 | 
			
		||||
        titleBox.add_child(new St.Label({ style_class: 'weather-header',
 | 
			
		||||
@@ -284,18 +282,6 @@ class WeatherSection extends St.Button {
 | 
			
		||||
        this._sync();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_map() {
 | 
			
		||||
        this._weatherClient.update();
 | 
			
		||||
        super.vfunc_map();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_clicked() {
 | 
			
		||||
        this._weatherClient.activateApp();
 | 
			
		||||
 | 
			
		||||
        Main.overview.hide();
 | 
			
		||||
        Main.panel.closeCalendar();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _getInfos() {
 | 
			
		||||
        let info = this._weatherClient.info;
 | 
			
		||||
        let forecasts = info.get_forecast_list();
 | 
			
		||||
@@ -386,27 +372,23 @@ class WeatherSection extends St.Button {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _sync() {
 | 
			
		||||
        this.visible = this._weatherClient.available;
 | 
			
		||||
        this.actor.visible = this._weatherClient.available;
 | 
			
		||||
 | 
			
		||||
        if (!this.visible)
 | 
			
		||||
        if (!this.actor.visible)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._titleLocation.visible = this._weatherClient.hasLocation;
 | 
			
		||||
 | 
			
		||||
        this._updateForecasts();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var MessagesIndicator = GObject.registerClass(
 | 
			
		||||
class MessagesIndicator extends St.Icon {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init({
 | 
			
		||||
            icon_name: 'message-indicator-symbolic',
 | 
			
		||||
            icon_size: 16,
 | 
			
		||||
            visible: false,
 | 
			
		||||
            y_expand: true,
 | 
			
		||||
            y_align: Clutter.ActorAlign.CENTER
 | 
			
		||||
        });
 | 
			
		||||
var MessagesIndicator = class MessagesIndicator {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        this.actor = new St.Icon({ icon_name: 'message-indicator-symbolic',
 | 
			
		||||
                                   icon_size: 16,
 | 
			
		||||
                                   visible: false, y_expand: true,
 | 
			
		||||
                                   y_align: Clutter.ActorAlign.CENTER });
 | 
			
		||||
 | 
			
		||||
        this._sources = [];
 | 
			
		||||
 | 
			
		||||
@@ -419,7 +401,7 @@ class MessagesIndicator extends St.Icon {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onSourceAdded(tray, source) {
 | 
			
		||||
        source.connect('notify::count', this._updateCount.bind(this));
 | 
			
		||||
        source.connect('count-updated', this._updateCount.bind(this));
 | 
			
		||||
        this._sources.push(source);
 | 
			
		||||
        this._updateCount();
 | 
			
		||||
    }
 | 
			
		||||
@@ -434,9 +416,9 @@ class MessagesIndicator extends St.Icon {
 | 
			
		||||
        this._sources.forEach(source => (count += source.unseenCount));
 | 
			
		||||
        count -= Main.messageTray.queueCount;
 | 
			
		||||
 | 
			
		||||
        this.visible = (count > 0);
 | 
			
		||||
        this.actor.visible = (count > 0);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var IndicatorPad = GObject.registerClass(
 | 
			
		||||
class IndicatorPad extends St.Widget {
 | 
			
		||||
@@ -529,9 +511,9 @@ class DateMenuButton extends PanelMenu.Button {
 | 
			
		||||
        this._indicator = new MessagesIndicator();
 | 
			
		||||
 | 
			
		||||
        let box = new St.BoxLayout();
 | 
			
		||||
        box.add_actor(new IndicatorPad(this._indicator));
 | 
			
		||||
        box.add_actor(new IndicatorPad(this._indicator.actor));
 | 
			
		||||
        box.add_actor(this._clockDisplay);
 | 
			
		||||
        box.add_actor(this._indicator);
 | 
			
		||||
        box.add_actor(this._indicator.actor);
 | 
			
		||||
 | 
			
		||||
        this.label_actor = this._clockDisplay;
 | 
			
		||||
        this.add_actor(box);
 | 
			
		||||
@@ -547,11 +529,11 @@ class DateMenuButton extends PanelMenu.Button {
 | 
			
		||||
        bin.add_actor(hbox);
 | 
			
		||||
 | 
			
		||||
        this._calendar = new Calendar.Calendar();
 | 
			
		||||
        this._calendar.connect('selected-date-changed', (_calendar, datetime) => {
 | 
			
		||||
            let date = _gDateTimeToDate(datetime);
 | 
			
		||||
            layout.frozen = !_isToday(date);
 | 
			
		||||
            this._messageList.setDate(date);
 | 
			
		||||
        });
 | 
			
		||||
        this._calendar.connect('selected-date-changed',
 | 
			
		||||
                               (calendar, date) => {
 | 
			
		||||
                                   layout.frozen = !_isToday(date);
 | 
			
		||||
                                   this._messageList.setDate(date);
 | 
			
		||||
                               });
 | 
			
		||||
 | 
			
		||||
        this.menu.connect('open-state-changed', (menu, isOpen) => {
 | 
			
		||||
            // Whenever the menu is opened, select today
 | 
			
		||||
@@ -565,19 +547,19 @@ class DateMenuButton extends PanelMenu.Button {
 | 
			
		||||
 | 
			
		||||
        // Fill up the first column
 | 
			
		||||
        this._messageList = new Calendar.CalendarMessageList();
 | 
			
		||||
        hbox.add(this._messageList, { expand: true, y_fill: false, y_align: St.Align.START });
 | 
			
		||||
        hbox.add(this._messageList.actor, { expand: true, y_fill: false, y_align: St.Align.START });
 | 
			
		||||
 | 
			
		||||
        // Fill up the second column
 | 
			
		||||
        let boxLayout = new CalendarColumnLayout(this._calendar);
 | 
			
		||||
        let boxLayout = new CalendarColumnLayout(this._calendar.actor);
 | 
			
		||||
        vbox = new St.Widget({ style_class: 'datemenu-calendar-column',
 | 
			
		||||
                               layout_manager: boxLayout });
 | 
			
		||||
        boxLayout.hookup_style(vbox);
 | 
			
		||||
        hbox.add(vbox);
 | 
			
		||||
 | 
			
		||||
        this._date = new TodayButton(this._calendar);
 | 
			
		||||
        vbox.add_actor(this._date);
 | 
			
		||||
        vbox.add_actor(this._date.actor);
 | 
			
		||||
 | 
			
		||||
        vbox.add_actor(this._calendar);
 | 
			
		||||
        vbox.add_actor(this._calendar.actor);
 | 
			
		||||
 | 
			
		||||
        this._displaysSection = new St.ScrollView({ style_class: 'datemenu-displays-section vfade',
 | 
			
		||||
                                                    x_expand: true, x_fill: true,
 | 
			
		||||
@@ -590,10 +572,10 @@ class DateMenuButton extends PanelMenu.Button {
 | 
			
		||||
        this._displaysSection.add_actor(displaysBox);
 | 
			
		||||
 | 
			
		||||
        this._clocksItem = new WorldClocksSection();
 | 
			
		||||
        displaysBox.add(this._clocksItem, { x_fill: true });
 | 
			
		||||
        displaysBox.add(this._clocksItem.actor, { x_fill: true });
 | 
			
		||||
 | 
			
		||||
        this._weatherItem = new WeatherSection();
 | 
			
		||||
        displaysBox.add(this._weatherItem, { x_fill: true });
 | 
			
		||||
        displaysBox.add(this._weatherItem.actor, { x_fill: true });
 | 
			
		||||
 | 
			
		||||
        // Done with hbox for calendar and event list
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -207,10 +207,10 @@ function _setCheckBoxLabel(checkBox, text) {
 | 
			
		||||
 | 
			
		||||
    if (text) {
 | 
			
		||||
        label.set_text(text);
 | 
			
		||||
        checkBox.show();
 | 
			
		||||
        checkBox.actor.show();
 | 
			
		||||
    } else {
 | 
			
		||||
        label.set_text('');
 | 
			
		||||
        checkBox.hide();
 | 
			
		||||
        checkBox.actor.hide();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -297,8 +297,8 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
 | 
			
		||||
                            y_align: St.Align.START });
 | 
			
		||||
 | 
			
		||||
        this._checkBox = new CheckBox.CheckBox();
 | 
			
		||||
        this._checkBox.connect('clicked', this._sync.bind(this));
 | 
			
		||||
        messageLayout.add(this._checkBox);
 | 
			
		||||
        this._checkBox.actor.connect('clicked', this._sync.bind(this));
 | 
			
		||||
        messageLayout.add(this._checkBox.actor);
 | 
			
		||||
 | 
			
		||||
        this._batteryWarning = new St.Label({ style_class: 'end-session-dialog-warning',
 | 
			
		||||
                                              text: _("Running on battery power: please plug in before installing updates.") });
 | 
			
		||||
@@ -376,12 +376,12 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
 | 
			
		||||
        let subject = dialogContent.subject;
 | 
			
		||||
 | 
			
		||||
        // Use different title when we are installing updates
 | 
			
		||||
        if (dialogContent.subjectWithUpdates && this._checkBox.checked)
 | 
			
		||||
        if (dialogContent.subjectWithUpdates && this._checkBox.actor.checked)
 | 
			
		||||
            subject = dialogContent.subjectWithUpdates;
 | 
			
		||||
 | 
			
		||||
        if (dialogContent.showBatteryWarning) {
 | 
			
		||||
            // Warn when running on battery power
 | 
			
		||||
            if (this._powerProxy.OnBattery && this._checkBox.checked)
 | 
			
		||||
            if (this._powerProxy.OnBattery && this._checkBox.actor.checked)
 | 
			
		||||
                this._batteryWarning.opacity = 255;
 | 
			
		||||
            else
 | 
			
		||||
                this._batteryWarning.opacity = 0;
 | 
			
		||||
@@ -429,7 +429,7 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
 | 
			
		||||
            let avatarWidget = new UserWidget.Avatar(this._user,
 | 
			
		||||
                                                     { iconSize: _DIALOG_ICON_SIZE,
 | 
			
		||||
                                                       styleClass: dialogContent.iconStyleClass });
 | 
			
		||||
            this._iconBin.child = avatarWidget;
 | 
			
		||||
            this._iconBin.child = avatarWidget.actor;
 | 
			
		||||
            avatarWidget.update();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -485,13 +485,13 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        // Offline update not available; just emit the signal
 | 
			
		||||
        if (!this._checkBox.visible) {
 | 
			
		||||
        if (!this._checkBox.actor.visible) {
 | 
			
		||||
            callback();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Trigger the offline update as requested
 | 
			
		||||
        if (this._checkBox.checked) {
 | 
			
		||||
        if (this._checkBox.actor.checked) {
 | 
			
		||||
            switch (signal) {
 | 
			
		||||
            case "ConfirmedReboot":
 | 
			
		||||
                this._triggerOfflineUpdateReboot(callback);
 | 
			
		||||
@@ -656,7 +656,7 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
 | 
			
		||||
 | 
			
		||||
        let actor = new St.BoxLayout({ style_class: 'end-session-dialog-session-list-item',
 | 
			
		||||
                                       can_focus: true });
 | 
			
		||||
        actor.add(avatar);
 | 
			
		||||
        actor.add(avatar.actor);
 | 
			
		||||
 | 
			
		||||
        let nameLabel = new St.Label({ text: userLabelText,
 | 
			
		||||
                                       style_class: 'end-session-dialog-session-list-item-name',
 | 
			
		||||
@@ -754,14 +754,14 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
 | 
			
		||||
        let updatesAllowed = this._updatesPermission && this._updatesPermission.allowed;
 | 
			
		||||
 | 
			
		||||
        _setCheckBoxLabel(this._checkBox, dialogContent.checkBoxText || '');
 | 
			
		||||
        this._checkBox.visible = (dialogContent.checkBoxText && updatePrepared && updatesAllowed);
 | 
			
		||||
        this._checkBox.checked = (updatePrepared && updateTriggered);
 | 
			
		||||
        this._checkBox.actor.visible = (dialogContent.checkBoxText && updatePrepared && updatesAllowed);
 | 
			
		||||
        this._checkBox.actor.checked = (updatePrepared && updateTriggered);
 | 
			
		||||
 | 
			
		||||
        // We show the warning either together with the checkbox, or when
 | 
			
		||||
        // updates have already been triggered, but the user doesn't have
 | 
			
		||||
        // enough permissions to cancel them.
 | 
			
		||||
        this._batteryWarning.visible = (dialogContent.showBatteryWarning &&
 | 
			
		||||
                                        (this._checkBox.visible || updatePrepared && updateTriggered && !updatesAllowed));
 | 
			
		||||
                                        (this._checkBox.actor.visible || updatePrepared && updateTriggered && !updatesAllowed));
 | 
			
		||||
 | 
			
		||||
        this._updateButtons();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -105,10 +105,22 @@ function _easeActor(actor, params) {
 | 
			
		||||
        actor.set_easing_delay(params.delay);
 | 
			
		||||
    delete params.delay;
 | 
			
		||||
 | 
			
		||||
    let repeat_count = 0;
 | 
			
		||||
    if (params.repeat_count != undefined)
 | 
			
		||||
        repeat_count = params.repeat_count;
 | 
			
		||||
    delete params.repeat_count;
 | 
			
		||||
 | 
			
		||||
    let auto_reverse = false;
 | 
			
		||||
    if (params.auto_reverse != undefined)
 | 
			
		||||
        auto_reverse = params.auto_reverse;
 | 
			
		||||
    delete params.auto_reverse;
 | 
			
		||||
 | 
			
		||||
    if (params.mode != undefined)
 | 
			
		||||
        actor.set_easing_mode(params.mode);
 | 
			
		||||
    delete params.mode;
 | 
			
		||||
 | 
			
		||||
    Meta.disable_unredirect_for_display(global.display);
 | 
			
		||||
 | 
			
		||||
    let cleanup = () => Meta.enable_unredirect_for_display(global.display);
 | 
			
		||||
    let callback = _makeEaseCallback(params, cleanup);
 | 
			
		||||
 | 
			
		||||
@@ -122,15 +134,14 @@ function _easeActor(actor, params) {
 | 
			
		||||
    let transition = animatedProps.map(p => actor.get_transition(p))
 | 
			
		||||
        .find(t => t !== null);
 | 
			
		||||
 | 
			
		||||
    if (transition && transition.delay)
 | 
			
		||||
        transition.connect('started', () => Meta.disable_unredirect_for_display(global.display));
 | 
			
		||||
    else
 | 
			
		||||
        Meta.disable_unredirect_for_display(global.display);
 | 
			
		||||
    if (transition) {
 | 
			
		||||
        transition.repeat_count = repeat_count;
 | 
			
		||||
        transition.auto_reverse = auto_reverse;
 | 
			
		||||
 | 
			
		||||
    if (transition)
 | 
			
		||||
        transition.connect('stopped', (t, finished) => callback(finished));
 | 
			
		||||
    else
 | 
			
		||||
    } else {
 | 
			
		||||
        callback(true);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function _easeActorProperty(actor, propName, target, params) {
 | 
			
		||||
@@ -143,11 +154,23 @@ function _easeActorProperty(actor, propName, target, params) {
 | 
			
		||||
        params.duration = adjustAnimationTime(params.duration);
 | 
			
		||||
    let duration = Math.floor(params.duration || 0);
 | 
			
		||||
 | 
			
		||||
    let repeat_count = 0;
 | 
			
		||||
    if (params.repeat_count != undefined)
 | 
			
		||||
        repeat_count = params.repeat_count;
 | 
			
		||||
    delete params.repeat_count;
 | 
			
		||||
 | 
			
		||||
    let auto_reverse = false;
 | 
			
		||||
    if (params.auto_reverse != undefined)
 | 
			
		||||
        auto_reverse = params.auto_reverse;
 | 
			
		||||
    delete params.auto_reverse;
 | 
			
		||||
 | 
			
		||||
    // Copy Clutter's behavior for implicit animations, see
 | 
			
		||||
    // should_skip_implicit_transition()
 | 
			
		||||
    if (actor instanceof Clutter.Actor && !actor.mapped)
 | 
			
		||||
        duration = 0;
 | 
			
		||||
 | 
			
		||||
    Meta.disable_unredirect_for_display(global.display);
 | 
			
		||||
 | 
			
		||||
    let cleanup = () => Meta.enable_unredirect_for_display(global.display);
 | 
			
		||||
    let callback = _makeEaseCallback(params, cleanup);
 | 
			
		||||
 | 
			
		||||
@@ -158,7 +181,6 @@ function _easeActorProperty(actor, propName, target, params) {
 | 
			
		||||
        let [obj, prop] = _getPropertyTarget(actor, propName);
 | 
			
		||||
        obj[prop] = target;
 | 
			
		||||
 | 
			
		||||
        Meta.disable_unredirect_for_display(global.display);
 | 
			
		||||
        callback(true);
 | 
			
		||||
 | 
			
		||||
        return;
 | 
			
		||||
@@ -168,17 +190,14 @@ function _easeActorProperty(actor, propName, target, params) {
 | 
			
		||||
    let transition = new Clutter.PropertyTransition(Object.assign({
 | 
			
		||||
        property_name: propName,
 | 
			
		||||
        interval: new Clutter.Interval({ value_type: pspec.value_type }),
 | 
			
		||||
        remove_on_complete: true
 | 
			
		||||
        remove_on_complete: true,
 | 
			
		||||
        repeat_count: repeat_count,
 | 
			
		||||
        auto_reverse: auto_reverse,
 | 
			
		||||
    }, params));
 | 
			
		||||
    actor.add_transition(propName, transition);
 | 
			
		||||
 | 
			
		||||
    transition.set_to(target);
 | 
			
		||||
 | 
			
		||||
    if (transition.delay)
 | 
			
		||||
        transition.connect('started', () => Meta.disable_unredirect_for_display(global.display));
 | 
			
		||||
    else
 | 
			
		||||
        Meta.disable_unredirect_for_display(global.display);
 | 
			
		||||
 | 
			
		||||
    transition.connect('stopped', (t, finished) => callback(finished));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,8 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/* exported CandidatePopup */
 | 
			
		||||
 | 
			
		||||
const { Clutter, GObject, IBus, St } = imports.gi;
 | 
			
		||||
const { Clutter, IBus, St } = imports.gi;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
 | 
			
		||||
const BoxPointer = imports.ui.boxpointer;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
@@ -11,23 +12,11 @@ var MAX_CANDIDATES_PER_PAGE = 16;
 | 
			
		||||
var DEFAULT_INDEX_LABELS = ['1', '2', '3', '4', '5', '6', '7', '8',
 | 
			
		||||
                            '9', '0', 'a', 'b', 'c', 'd', 'e', 'f'];
 | 
			
		||||
 | 
			
		||||
var CandidateArea = GObject.registerClass({
 | 
			
		||||
    Signals: {
 | 
			
		||||
        'candidate-clicked': { param_types: [GObject.TYPE_UINT,
 | 
			
		||||
                                             GObject.TYPE_UINT,
 | 
			
		||||
                                             Clutter.ModifierType.$gtype] },
 | 
			
		||||
        'cursor-down': {},
 | 
			
		||||
        'cursor-up': {},
 | 
			
		||||
        'next-page': {},
 | 
			
		||||
        'previous-page': {},
 | 
			
		||||
    }
 | 
			
		||||
}, class CandidateArea extends St.BoxLayout {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init({
 | 
			
		||||
            vertical: true,
 | 
			
		||||
            reactive: true,
 | 
			
		||||
            visible: false
 | 
			
		||||
        });
 | 
			
		||||
var CandidateArea = class CandidateArea {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        this.actor = new St.BoxLayout({ vertical: true,
 | 
			
		||||
                                        reactive: true,
 | 
			
		||||
                                        visible: false });
 | 
			
		||||
        this._candidateBoxes = [];
 | 
			
		||||
        for (let i = 0; i < MAX_CANDIDATES_PER_PAGE; ++i) {
 | 
			
		||||
            let box = new St.BoxLayout({ style_class: 'candidate-box',
 | 
			
		||||
@@ -38,7 +27,7 @@ var CandidateArea = GObject.registerClass({
 | 
			
		||||
            box.add(box._indexLabel, { y_fill: false });
 | 
			
		||||
            box.add(box._candidateLabel, { y_fill: false });
 | 
			
		||||
            this._candidateBoxes.push(box);
 | 
			
		||||
            this.add(box);
 | 
			
		||||
            this.actor.add(box);
 | 
			
		||||
 | 
			
		||||
            let j = i;
 | 
			
		||||
            box.connect('button-release-event', (actor, event) => {
 | 
			
		||||
@@ -47,6 +36,19 @@ var CandidateArea = GObject.registerClass({
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.actor.connect('scroll-event', (actor, event) => {
 | 
			
		||||
            let direction = event.get_scroll_direction();
 | 
			
		||||
            switch (direction) {
 | 
			
		||||
            case Clutter.ScrollDirection.UP:
 | 
			
		||||
                this.emit('cursor-up');
 | 
			
		||||
                break;
 | 
			
		||||
            case Clutter.ScrollDirection.DOWN:
 | 
			
		||||
                this.emit('cursor-down');
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this._buttonBox = new St.BoxLayout({ style_class: 'candidate-page-button-box' });
 | 
			
		||||
 | 
			
		||||
        this._previousButton = new St.Button({ style_class: 'candidate-page-button candidate-page-button-previous button' });
 | 
			
		||||
@@ -57,7 +59,7 @@ var CandidateArea = GObject.registerClass({
 | 
			
		||||
        this._nextButton.child = new St.Icon({ style_class: 'candidate-page-button-icon' });
 | 
			
		||||
        this._buttonBox.add(this._nextButton, { expand: true });
 | 
			
		||||
 | 
			
		||||
        this.add(this._buttonBox);
 | 
			
		||||
        this.actor.add(this._buttonBox);
 | 
			
		||||
 | 
			
		||||
        this._previousButton.connect('clicked', () => {
 | 
			
		||||
            this.emit('previous-page');
 | 
			
		||||
@@ -70,18 +72,6 @@ var CandidateArea = GObject.registerClass({
 | 
			
		||||
        this._cursorPosition = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_scroll_event(scrollEvent) {
 | 
			
		||||
        switch (scrollEvent.direction) {
 | 
			
		||||
        case Clutter.ScrollDirection.UP:
 | 
			
		||||
            this.emit('cursor-up');
 | 
			
		||||
            break;
 | 
			
		||||
        case Clutter.ScrollDirection.DOWN:
 | 
			
		||||
            this.emit('cursor-down');
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    setOrientation(orientation) {
 | 
			
		||||
        if (this._orientation == orientation)
 | 
			
		||||
            return;
 | 
			
		||||
@@ -89,15 +79,15 @@ var CandidateArea = GObject.registerClass({
 | 
			
		||||
        this._orientation = orientation;
 | 
			
		||||
 | 
			
		||||
        if (this._orientation == IBus.Orientation.HORIZONTAL) {
 | 
			
		||||
            this.vertical = false;
 | 
			
		||||
            this.remove_style_class_name('vertical');
 | 
			
		||||
            this.add_style_class_name('horizontal');
 | 
			
		||||
            this.actor.vertical = false;
 | 
			
		||||
            this.actor.remove_style_class_name('vertical');
 | 
			
		||||
            this.actor.add_style_class_name('horizontal');
 | 
			
		||||
            this._previousButton.child.icon_name = 'go-previous-symbolic';
 | 
			
		||||
            this._nextButton.child.icon_name = 'go-next-symbolic';
 | 
			
		||||
        } else {                // VERTICAL || SYSTEM
 | 
			
		||||
            this.vertical = true;
 | 
			
		||||
            this.add_style_class_name('vertical');
 | 
			
		||||
            this.remove_style_class_name('horizontal');
 | 
			
		||||
            this.actor.vertical = true;
 | 
			
		||||
            this.actor.add_style_class_name('vertical');
 | 
			
		||||
            this.actor.remove_style_class_name('horizontal');
 | 
			
		||||
            this._previousButton.child.icon_name = 'go-up-symbolic';
 | 
			
		||||
            this._nextButton.child.icon_name = 'go-down-symbolic';
 | 
			
		||||
        }
 | 
			
		||||
@@ -131,23 +121,22 @@ var CandidateArea = GObject.registerClass({
 | 
			
		||||
        this._previousButton.reactive = wrapsAround || page > 0;
 | 
			
		||||
        this._nextButton.reactive = wrapsAround || page < nPages - 1;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
var CandidatePopup = GObject.registerClass(
 | 
			
		||||
class IbusCandidatePopup extends BoxPointer.BoxPointer {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init(St.Side.TOP);
 | 
			
		||||
        this.visible = false;
 | 
			
		||||
        this.style_class = 'candidate-popup-boxpointer';
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(CandidateArea.prototype);
 | 
			
		||||
 | 
			
		||||
var CandidatePopup = class CandidatePopup {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        this._dummyCursor = new St.Widget({ opacity: 0 });
 | 
			
		||||
        Main.layoutManager.uiGroup.add_actor(this._dummyCursor);
 | 
			
		||||
 | 
			
		||||
        Main.layoutManager.addChrome(this);
 | 
			
		||||
        this._boxPointer = new BoxPointer.BoxPointer(St.Side.TOP);
 | 
			
		||||
        this._boxPointer.visible = false;
 | 
			
		||||
        this._boxPointer.style_class = 'candidate-popup-boxpointer';
 | 
			
		||||
        Main.layoutManager.addChrome(this._boxPointer);
 | 
			
		||||
 | 
			
		||||
        let box = new St.BoxLayout({ style_class: 'candidate-popup-content',
 | 
			
		||||
                                     vertical: true });
 | 
			
		||||
        this.bin.set_child(box);
 | 
			
		||||
        this._boxPointer.bin.set_child(box);
 | 
			
		||||
 | 
			
		||||
        this._preeditText = new St.Label({ style_class: 'candidate-popup-text',
 | 
			
		||||
                                           visible: false });
 | 
			
		||||
@@ -158,7 +147,7 @@ class IbusCandidatePopup extends BoxPointer.BoxPointer {
 | 
			
		||||
        box.add(this._auxText);
 | 
			
		||||
 | 
			
		||||
        this._candidateArea = new CandidateArea();
 | 
			
		||||
        box.add(this._candidateArea);
 | 
			
		||||
        box.add(this._candidateArea.actor);
 | 
			
		||||
 | 
			
		||||
        this._candidateArea.connect('previous-page', () => {
 | 
			
		||||
            this._panelService.page_up();
 | 
			
		||||
@@ -236,7 +225,7 @@ class IbusCandidatePopup extends BoxPointer.BoxPointer {
 | 
			
		||||
            this._updateVisibility();
 | 
			
		||||
        });
 | 
			
		||||
        panelService.connect('update-lookup-table', (_ps, lookupTable, visible) => {
 | 
			
		||||
            this._candidateArea.visible = visible;
 | 
			
		||||
            this._candidateArea.actor.visible = visible;
 | 
			
		||||
            this._updateVisibility();
 | 
			
		||||
 | 
			
		||||
            let nCandidates = lookupTable.get_number_of_candidates();
 | 
			
		||||
@@ -272,15 +261,15 @@ class IbusCandidatePopup extends BoxPointer.BoxPointer {
 | 
			
		||||
            this._candidateArea.updateButtons(lookupTable.is_round(), page, nPages);
 | 
			
		||||
        });
 | 
			
		||||
        panelService.connect('show-lookup-table', () => {
 | 
			
		||||
            this._candidateArea.show();
 | 
			
		||||
            this._candidateArea.actor.show();
 | 
			
		||||
            this._updateVisibility();
 | 
			
		||||
        });
 | 
			
		||||
        panelService.connect('hide-lookup-table', () => {
 | 
			
		||||
            this._candidateArea.hide();
 | 
			
		||||
            this._candidateArea.actor.hide();
 | 
			
		||||
            this._updateVisibility();
 | 
			
		||||
        });
 | 
			
		||||
        panelService.connect('focus-out', () => {
 | 
			
		||||
            this.close(BoxPointer.PopupAnimation.NONE);
 | 
			
		||||
            this._boxPointer.close(BoxPointer.PopupAnimation.NONE);
 | 
			
		||||
            Main.keyboard.resetSuggestions();
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
@@ -289,22 +278,22 @@ class IbusCandidatePopup extends BoxPointer.BoxPointer {
 | 
			
		||||
        this._dummyCursor.set_position(Math.round(x), Math.round(y));
 | 
			
		||||
        this._dummyCursor.set_size(Math.round(w), Math.round(h));
 | 
			
		||||
 | 
			
		||||
        if (this.visible)
 | 
			
		||||
            this.setPosition(this._dummyCursor, 0);
 | 
			
		||||
        if (this._boxPointer.visible)
 | 
			
		||||
            this._boxPointer.setPosition(this._dummyCursor, 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _updateVisibility() {
 | 
			
		||||
        let isVisible = (!Main.keyboard.visible &&
 | 
			
		||||
                         (this._preeditText.visible ||
 | 
			
		||||
                          this._auxText.visible ||
 | 
			
		||||
                          this._candidateArea.visible));
 | 
			
		||||
                          this._candidateArea.actor.visible));
 | 
			
		||||
 | 
			
		||||
        if (isVisible) {
 | 
			
		||||
            this.setPosition(this._dummyCursor, 0);
 | 
			
		||||
            this.open(BoxPointer.PopupAnimation.NONE);
 | 
			
		||||
            this.raise_top();
 | 
			
		||||
            this._boxPointer.setPosition(this._dummyCursor, 0);
 | 
			
		||||
            this._boxPointer.open(BoxPointer.PopupAnimation.NONE);
 | 
			
		||||
            this._boxPointer.raise_top();
 | 
			
		||||
        } else {
 | 
			
		||||
            this.close(BoxPointer.PopupAnimation.NONE);
 | 
			
		||||
            this._boxPointer.close(BoxPointer.PopupAnimation.NONE);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -314,4 +303,4 @@ class IbusCandidatePopup extends BoxPointer.BoxPointer {
 | 
			
		||||
            if (attr.get_attr_type() == IBus.AttrType.BACKGROUND)
 | 
			
		||||
                clutterText.set_selection(attr.get_start_index(), attr.get_end_index());
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/* exported BaseIcon, IconGrid, PaginatedIconGrid */
 | 
			
		||||
 | 
			
		||||
const { Clutter, GLib, GObject, Graphene, Meta, St } = imports.gi;
 | 
			
		||||
const { Clutter, GLib, GObject, Meta, St } = imports.gi;
 | 
			
		||||
 | 
			
		||||
const Params = imports.misc.params;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
@@ -231,18 +231,18 @@ var IconGrid = GObject.registerClass({
 | 
			
		||||
        this._fixedHItemSize = this._fixedVItemSize = undefined;
 | 
			
		||||
        this.connect('style-changed', this._onStyleChanged.bind(this));
 | 
			
		||||
 | 
			
		||||
        // Cancel animations when hiding the overview, to avoid icons
 | 
			
		||||
        // swarming into the void ...
 | 
			
		||||
        this.connect('notify::mapped', () => {
 | 
			
		||||
            if (!this.mapped)
 | 
			
		||||
                this._resetAnimationActors();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this.connect('actor-added', this._childAdded.bind(this));
 | 
			
		||||
        this.connect('actor-removed', this._childRemoved.bind(this));
 | 
			
		||||
        this.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_unmap() {
 | 
			
		||||
        // Cancel animations when hiding the overview, to avoid icons
 | 
			
		||||
        // swarming into the void ...
 | 
			
		||||
        this._resetAnimationActors();
 | 
			
		||||
        super.vfunc_unmap();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onDestroy() {
 | 
			
		||||
        if (this._updateIconSizesLaterId) {
 | 
			
		||||
            Meta.later_remove (this._updateIconSizesLaterId);
 | 
			
		||||
@@ -402,7 +402,7 @@ var IconGrid = GObject.registerClass({
 | 
			
		||||
        let allocationBox = this.get_allocation_box();
 | 
			
		||||
        let paintBox = themeNode.get_paint_box(allocationBox);
 | 
			
		||||
 | 
			
		||||
        let origin = new Graphene.Point3D();
 | 
			
		||||
        let origin = new Clutter.Vertex();
 | 
			
		||||
        origin.x = paintBox.x1 - allocationBox.x1;
 | 
			
		||||
        origin.y = paintBox.y1 - allocationBox.y1;
 | 
			
		||||
        origin.z = 0.0;
 | 
			
		||||
@@ -717,13 +717,13 @@ var IconGrid = GObject.registerClass({
 | 
			
		||||
 | 
			
		||||
        this._items.push(item);
 | 
			
		||||
        if (index !== undefined)
 | 
			
		||||
            this.insert_child_at_index(item, index);
 | 
			
		||||
            this.insert_child_at_index(item.actor, index);
 | 
			
		||||
        else
 | 
			
		||||
            this.add_actor(item);
 | 
			
		||||
            this.add_actor(item.actor);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    removeItem(item) {
 | 
			
		||||
        this.remove_child(item);
 | 
			
		||||
        this.remove_child(item.actor);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    getItemAtIndex(index) {
 | 
			
		||||
@@ -963,7 +963,7 @@ var PaginatedIconGrid = GObject.registerClass({
 | 
			
		||||
    */
 | 
			
		||||
    openExtraSpace(sourceItem, side, nRows) {
 | 
			
		||||
        let children = this._getVisibleChildren();
 | 
			
		||||
        let index = children.indexOf(sourceItem);
 | 
			
		||||
        let index = children.indexOf(sourceItem.actor);
 | 
			
		||||
        if (index == -1)
 | 
			
		||||
            throw new Error('Item not found.');
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/* exported KeyboardManager */
 | 
			
		||||
/* exported Keyboard */
 | 
			
		||||
 | 
			
		||||
const { Clutter, Gio, GLib, GObject, Meta, St } = imports.gi;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
@@ -89,11 +89,8 @@ class KeyContainer extends St.Widget {
 | 
			
		||||
        let gridLayout = new Clutter.GridLayout({ orientation: Clutter.Orientation.HORIZONTAL,
 | 
			
		||||
                                                  column_homogeneous: true,
 | 
			
		||||
                                                  row_homogeneous: true });
 | 
			
		||||
        super._init({
 | 
			
		||||
            layout_manager: gridLayout,
 | 
			
		||||
            x_expand: true,
 | 
			
		||||
            y_expand: true
 | 
			
		||||
        });
 | 
			
		||||
        super._init({ layout_manager: gridLayout,
 | 
			
		||||
                      x_expand: true, y_expand: true });
 | 
			
		||||
        this._gridLayout = gridLayout;
 | 
			
		||||
        this._currentRow = 0;
 | 
			
		||||
        this._currentCol = 0;
 | 
			
		||||
@@ -164,23 +161,24 @@ class KeyContainer extends St.Widget {
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
var Suggestions = GObject.registerClass(
 | 
			
		||||
class Suggestions extends St.BoxLayout {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init({ style_class: 'word-suggestions', vertical: false });
 | 
			
		||||
        this.show();
 | 
			
		||||
var Suggestions = class {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        this.actor = new St.BoxLayout({ style_class: 'word-suggestions',
 | 
			
		||||
                                        vertical: false });
 | 
			
		||||
        this.actor.show();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    add(word, callback) {
 | 
			
		||||
        let button = new St.Button({ label: word });
 | 
			
		||||
        button.connect('clicked', callback);
 | 
			
		||||
        this.add(button);
 | 
			
		||||
        this.actor.add(button);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    clear() {
 | 
			
		||||
        this.remove_all_children();
 | 
			
		||||
        this.actor.remove_all_children();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(Suggestions.prototype);
 | 
			
		||||
 | 
			
		||||
var LanguageSelectionPopup = class extends PopupMenu.PopupMenu {
 | 
			
		||||
    constructor(actor) {
 | 
			
		||||
@@ -245,25 +243,17 @@ var LanguageSelectionPopup = class extends PopupMenu.PopupMenu {
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var Key = GObject.registerClass({
 | 
			
		||||
    Signals: {
 | 
			
		||||
        'activated': {},
 | 
			
		||||
        'long-press': {},
 | 
			
		||||
        'pressed': { param_types: [GObject.TYPE_UINT, GObject.TYPE_STRING] },
 | 
			
		||||
        'released': { param_types: [GObject.TYPE_UINT, GObject.TYPE_STRING] },
 | 
			
		||||
    }
 | 
			
		||||
}, class Key extends St.BoxLayout {
 | 
			
		||||
    _init(key, extendedKeys) {
 | 
			
		||||
        super._init({ style_class: 'key-container' });
 | 
			
		||||
 | 
			
		||||
var Key = class Key {
 | 
			
		||||
    constructor(key, extendedKeys) {
 | 
			
		||||
        this.key = key || "";
 | 
			
		||||
        this.keyButton = this._makeKey(this.key);
 | 
			
		||||
 | 
			
		||||
        /* Add the key in a container, so keys can be padded without losing
 | 
			
		||||
         * logical proportions between those.
 | 
			
		||||
         */
 | 
			
		||||
        this.add(this.keyButton, { expand: true, x_fill: true });
 | 
			
		||||
        this.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
        this.actor = new St.BoxLayout ({ style_class: 'key-container' });
 | 
			
		||||
        this.actor.add(this.keyButton, { expand: true, x_fill: true });
 | 
			
		||||
        this.actor.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
 | 
			
		||||
        this._extended_keys = extendedKeys;
 | 
			
		||||
        this._extended_keyboard = null;
 | 
			
		||||
@@ -471,7 +461,8 @@ var Key = GObject.registerClass({
 | 
			
		||||
        else
 | 
			
		||||
            this.keyButton.remove_style_pseudo_class('latched');
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(Key.prototype);
 | 
			
		||||
 | 
			
		||||
var KeyboardModel = class {
 | 
			
		||||
    constructor(groupName) {
 | 
			
		||||
@@ -599,6 +590,7 @@ var EmojiPager = GObject.registerClass({
 | 
			
		||||
            reactive: true,
 | 
			
		||||
            clip_to_allocation: true
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this._sections = sections;
 | 
			
		||||
        this._nCols = nCols;
 | 
			
		||||
        this._nRows = nRows;
 | 
			
		||||
@@ -809,7 +801,7 @@ var EmojiPager = GObject.registerClass({
 | 
			
		||||
                this.emit('emoji', str);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            gridLayout.attach(key, col, row, 1, 1);
 | 
			
		||||
            gridLayout.attach(key.actor, col, row, 1, 1);
 | 
			
		||||
 | 
			
		||||
            col++;
 | 
			
		||||
            if (col >= this._nCols) {
 | 
			
		||||
@@ -851,7 +843,7 @@ var EmojiPager = GObject.registerClass({
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let page = this._pages[nPage];
 | 
			
		||||
        this.emit('page-changed', page.section.label, page.page, page.nPages);
 | 
			
		||||
        this.emit('page-changed', page.section, page.page, page.nPages);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    setCurrentSection(section, nPage) {
 | 
			
		||||
@@ -866,21 +858,8 @@ var EmojiPager = GObject.registerClass({
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
var EmojiSelection = GObject.registerClass({
 | 
			
		||||
    Signals: {
 | 
			
		||||
        'emoji-selected': { param_types: [GObject.TYPE_STRING] },
 | 
			
		||||
        'close-request': {},
 | 
			
		||||
        'toggle': {},
 | 
			
		||||
    }
 | 
			
		||||
}, class EmojiSelection extends St.BoxLayout {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init({
 | 
			
		||||
            style_class: 'emoji-panel',
 | 
			
		||||
            x_expand: true,
 | 
			
		||||
            y_expand: true,
 | 
			
		||||
            vertical: true
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
var EmojiSelection = class EmojiSelection {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        this._sections = [
 | 
			
		||||
            { first: 'grinning face', label: '🙂️' },
 | 
			
		||||
            { first: 'selfie', label: '👍️' },
 | 
			
		||||
@@ -895,44 +874,38 @@ var EmojiSelection = GObject.registerClass({
 | 
			
		||||
 | 
			
		||||
        this._populateSections();
 | 
			
		||||
 | 
			
		||||
        this.actor = new St.BoxLayout({ style_class: 'emoji-panel',
 | 
			
		||||
                                        x_expand: true,
 | 
			
		||||
                                        y_expand: true,
 | 
			
		||||
                                        vertical: true });
 | 
			
		||||
        this.actor.connect('notify::mapped', () => this._emojiPager.setCurrentPage(0));
 | 
			
		||||
 | 
			
		||||
        this._emojiPager = new EmojiPager(this._sections, 11, 3);
 | 
			
		||||
        this._emojiPager.connect('page-changed', (pager, sectionLabel, page, nPages) => {
 | 
			
		||||
            this._onPageChanged(sectionLabel, page, nPages);
 | 
			
		||||
        this._emojiPager.connect('page-changed', (pager, section, page, nPages) => {
 | 
			
		||||
            this._onPageChanged(section, page, nPages);
 | 
			
		||||
        });
 | 
			
		||||
        this._emojiPager.connect('emoji', (pager, str) => {
 | 
			
		||||
            this.emit('emoji-selected', str);
 | 
			
		||||
        });
 | 
			
		||||
        this.add(this._emojiPager, { expand: true });
 | 
			
		||||
        this.actor.add(this._emojiPager.actor, { expand: true });
 | 
			
		||||
 | 
			
		||||
        this._pageIndicator = new PageIndicators.PageIndicators(
 | 
			
		||||
            Clutter.Orientation.HORIZONTAL
 | 
			
		||||
        );
 | 
			
		||||
        this.add(this._pageIndicator, { expand: true, x_fill: false, y_fill: false });
 | 
			
		||||
        this._pageIndicator = new PageIndicators.PageIndicators(false);
 | 
			
		||||
        this.actor.add(this._pageIndicator, { expand: true, x_fill: false, y_fill: false });
 | 
			
		||||
        this._pageIndicator.setReactive(false);
 | 
			
		||||
 | 
			
		||||
        let bottomRow = this._createBottomRow();
 | 
			
		||||
        this.add(bottomRow, { expand: true, x_fill: false, y_fill: false });
 | 
			
		||||
        this.actor.add(bottomRow, { expand: true, x_fill: false, y_fill: false });
 | 
			
		||||
 | 
			
		||||
        this._emojiPager.setCurrentPage(0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_map() {
 | 
			
		||||
        this._emojiPager.setCurrentPage(0);
 | 
			
		||||
        super.vfunc_map();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_unmap() {
 | 
			
		||||
        super.vfunc_unmap();
 | 
			
		||||
        this._emojiPager.setCurrentPage(0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onPageChanged(sectionLabel, page, nPages) {
 | 
			
		||||
    _onPageChanged(section, page, nPages) {
 | 
			
		||||
        this._pageIndicator.setNPages(nPages);
 | 
			
		||||
        this._pageIndicator.setCurrentPage(page);
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < this._sections.length; i++) {
 | 
			
		||||
            let sect = this._sections[i];
 | 
			
		||||
            sect.button.setLatched(sectionLabel == sect.label);
 | 
			
		||||
            sect.button.setLatched(section == sect);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -988,14 +961,14 @@ var EmojiSelection = GObject.registerClass({
 | 
			
		||||
        key = new Key('ABC', []);
 | 
			
		||||
        key.keyButton.add_style_class_name('default-key');
 | 
			
		||||
        key.connect('released', () => this.emit('toggle'));
 | 
			
		||||
        row.appendKey(key, 1.5);
 | 
			
		||||
        row.appendKey(key.actor, 1.5);
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < this._sections.length; i++) {
 | 
			
		||||
            let section = this._sections[i];
 | 
			
		||||
 | 
			
		||||
            key = new Key(section.label, []);
 | 
			
		||||
            key.connect('released', () => this._emojiPager.setCurrentSection(section, 0));
 | 
			
		||||
            row.appendKey(key);
 | 
			
		||||
            row.appendKey(key.actor);
 | 
			
		||||
 | 
			
		||||
            section.button = key;
 | 
			
		||||
        }
 | 
			
		||||
@@ -1004,9 +977,9 @@ var EmojiSelection = GObject.registerClass({
 | 
			
		||||
        key.keyButton.add_style_class_name('default-key');
 | 
			
		||||
        key.keyButton.add_style_class_name('hide-key');
 | 
			
		||||
        key.connect('released', () => {
 | 
			
		||||
            this.emit('close-request');
 | 
			
		||||
            this.emit('hide');
 | 
			
		||||
        });
 | 
			
		||||
        row.appendKey(key);
 | 
			
		||||
        row.appendKey(key.actor);
 | 
			
		||||
        row.layoutButtons();
 | 
			
		||||
 | 
			
		||||
        let actor = new AspectContainer({ layout_manager: new Clutter.BinLayout(),
 | 
			
		||||
@@ -1020,14 +993,11 @@ var EmojiSelection = GObject.registerClass({
 | 
			
		||||
 | 
			
		||||
        return actor;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(EmojiSelection.prototype);
 | 
			
		||||
 | 
			
		||||
var Keypad = GObject.registerClass({
 | 
			
		||||
    Signals: {
 | 
			
		||||
        'keyval': { param_types: [GObject.TYPE_UINT] },
 | 
			
		||||
    }
 | 
			
		||||
}, class Keypad extends AspectContainer {
 | 
			
		||||
    _init() {
 | 
			
		||||
var Keypad = class Keypad {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        let keys = [
 | 
			
		||||
            { label: '1', keyval: Clutter.KEY_1, left: 0, top: 0 },
 | 
			
		||||
            { label: '2', keyval: Clutter.KEY_2, left: 1, top: 0 },
 | 
			
		||||
@@ -1043,17 +1013,14 @@ var Keypad = GObject.registerClass({
 | 
			
		||||
            { keyval: Clutter.KEY_Return, extraClassName: 'enter-key', left: 3, top: 1, height: 2 },
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
        super._init({
 | 
			
		||||
            layout_manager: new Clutter.BinLayout(),
 | 
			
		||||
            x_expand: true,
 | 
			
		||||
            y_expand: true
 | 
			
		||||
        });
 | 
			
		||||
        this.actor = new AspectContainer({ layout_manager: new Clutter.BinLayout(),
 | 
			
		||||
                                           x_expand: true, y_expand: true });
 | 
			
		||||
 | 
			
		||||
        let gridLayout = new Clutter.GridLayout({ orientation: Clutter.Orientation.HORIZONTAL,
 | 
			
		||||
                                                  column_homogeneous: true,
 | 
			
		||||
                                                  row_homogeneous: true });
 | 
			
		||||
        this._box = new St.Widget({ layout_manager: gridLayout, x_expand: true, y_expand: true });
 | 
			
		||||
        this.add_child(this._box);
 | 
			
		||||
        this.actor.add_child(this._box);
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < keys.length; i++) {
 | 
			
		||||
            let cur = keys[i];
 | 
			
		||||
@@ -1065,32 +1032,86 @@ var Keypad = GObject.registerClass({
 | 
			
		||||
            let w, h;
 | 
			
		||||
            w = cur.width || 1;
 | 
			
		||||
            h = cur.height || 1;
 | 
			
		||||
            gridLayout.attach(key, cur.left, cur.top, w, h);
 | 
			
		||||
            gridLayout.attach(key.actor, cur.left, cur.top, w, h);
 | 
			
		||||
 | 
			
		||||
            key.connect('released', () => {
 | 
			
		||||
                this.emit('keyval', cur.keyval);
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(Keypad.prototype);
 | 
			
		||||
 | 
			
		||||
var KeyboardManager = class KeyBoardManager {
 | 
			
		||||
var Keyboard = class Keyboard {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        this._keyboard = null;
 | 
			
		||||
        this.actor = null;
 | 
			
		||||
        this._focusInExtendedKeys = false;
 | 
			
		||||
        this._emojiActive = false;
 | 
			
		||||
 | 
			
		||||
        this._languagePopup = null;
 | 
			
		||||
        this._currentFocusWindow = null;
 | 
			
		||||
        this._animFocusedWindow = null;
 | 
			
		||||
        this._delayedAnimFocusWindow = null;
 | 
			
		||||
 | 
			
		||||
        this._enableKeyboard = false; // a11y settings value
 | 
			
		||||
        this._enabled = false; // enabled state (by setting or device type)
 | 
			
		||||
        this._latched = false; // current level is latched
 | 
			
		||||
 | 
			
		||||
        this._a11yApplicationsSettings = new Gio.Settings({ schema_id: A11Y_APPLICATIONS_SCHEMA });
 | 
			
		||||
        this._a11yApplicationsSettings.connect('changed', this._syncEnabled.bind(this));
 | 
			
		||||
 | 
			
		||||
        this._lastDeviceId = null;
 | 
			
		||||
        Meta.get_backend().connect('last-device-changed', (backend, deviceId) => {
 | 
			
		||||
            let manager = Clutter.DeviceManager.get_default();
 | 
			
		||||
            let device = manager.get_device(deviceId);
 | 
			
		||||
        this._suggestions = null;
 | 
			
		||||
        this._emojiKeyVisible = Meta.is_wayland_compositor();
 | 
			
		||||
 | 
			
		||||
            if (device.get_device_name().indexOf('XTEST') < 0) {
 | 
			
		||||
                this._lastDeviceId = deviceId;
 | 
			
		||||
                this._syncEnabled();
 | 
			
		||||
            }
 | 
			
		||||
        this._focusTracker = new FocusTracker();
 | 
			
		||||
        this._focusTracker.connect('position-changed', this._onFocusPositionChanged.bind(this));
 | 
			
		||||
        this._focusTracker.connect('reset', () => {
 | 
			
		||||
            this._delayedAnimFocusWindow = null;
 | 
			
		||||
            this._animFocusedWindow = null;
 | 
			
		||||
            this._oskFocusWindow = null;
 | 
			
		||||
        });
 | 
			
		||||
        this._focusTracker.connect('focus-changed', (tracker, focused) => {
 | 
			
		||||
            // Valid only for X11
 | 
			
		||||
            if (Meta.is_wayland_compositor())
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            if (focused)
 | 
			
		||||
                this.show(Main.layoutManager.focusIndex);
 | 
			
		||||
            else
 | 
			
		||||
                this.hide();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        Meta.get_backend().connect('last-device-changed',
 | 
			
		||||
            (backend, deviceId) => {
 | 
			
		||||
                let manager = Clutter.DeviceManager.get_default();
 | 
			
		||||
                let device = manager.get_device(deviceId);
 | 
			
		||||
 | 
			
		||||
                if (!device.get_device_name().includes('XTEST')) {
 | 
			
		||||
                    this._lastDeviceId = deviceId;
 | 
			
		||||
                    this._syncEnabled();
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
        this._syncEnabled();
 | 
			
		||||
 | 
			
		||||
        this._showIdleId = 0;
 | 
			
		||||
 | 
			
		||||
        this._keyboardVisible = false;
 | 
			
		||||
        Main.layoutManager.connect('keyboard-visible-changed', (o, visible) => {
 | 
			
		||||
            this._keyboardVisible = visible;
 | 
			
		||||
        });
 | 
			
		||||
        this._keyboardRequested = false;
 | 
			
		||||
        this._keyboardRestingId = 0;
 | 
			
		||||
 | 
			
		||||
        Main.layoutManager.connect('monitors-changed', this._relayout.bind(this));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get visible() {
 | 
			
		||||
        return this._keyboardVisible;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onFocusPositionChanged(focusTracker) {
 | 
			
		||||
        let rect = focusTracker.getCurrentRect();
 | 
			
		||||
        this.setCursorLocation(focusTracker.currentWindow, rect.x, rect.y, rect.width, rect.height);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _lastDeviceIsTouchscreen() {
 | 
			
		||||
@@ -1107,143 +1128,38 @@ var KeyboardManager = class KeyBoardManager {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _syncEnabled() {
 | 
			
		||||
        let enableKeyboard = this._a11yApplicationsSettings.get_boolean(SHOW_KEYBOARD);
 | 
			
		||||
        let enabled = enableKeyboard || this._lastDeviceIsTouchscreen();
 | 
			
		||||
        if (!enabled && !this._keyboard)
 | 
			
		||||
        let wasEnabled = this._enabled;
 | 
			
		||||
        this._enableKeyboard = this._a11yApplicationsSettings.get_boolean(SHOW_KEYBOARD);
 | 
			
		||||
        this._enabled = this._enableKeyboard || this._lastDeviceIsTouchscreen();
 | 
			
		||||
        if (!this._enabled && !this._keyboardController)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (enabled && !this._keyboard) {
 | 
			
		||||
            this._keyboard = new Keyboard();
 | 
			
		||||
        } else if (!enabled && this._keyboard) {
 | 
			
		||||
            this._keyboard.setCursorLocation(null);
 | 
			
		||||
        if (this._enabled && !this._keyboardController)
 | 
			
		||||
            this._setupKeyboard();
 | 
			
		||||
        else if (!this._enabled)
 | 
			
		||||
            this.setCursorLocation(null);
 | 
			
		||||
 | 
			
		||||
        if (!this._enabled && wasEnabled)
 | 
			
		||||
            Main.layoutManager.hideKeyboard(true);
 | 
			
		||||
            this._keyboard.destroy();
 | 
			
		||||
            this._keyboard = null;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get keyboardActor() {
 | 
			
		||||
        return this._keyboard;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get visible() {
 | 
			
		||||
        return this._keyboard && this._keyboard.visible;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    open(monitor) {
 | 
			
		||||
        if (this._keyboard)
 | 
			
		||||
            this._keyboard.open(monitor);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    close() {
 | 
			
		||||
        if (this._keyboard)
 | 
			
		||||
            this._keyboard.close();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    addSuggestion(text, callback) {
 | 
			
		||||
        if (this._keyboard)
 | 
			
		||||
            this._keyboard.addSuggestion(text, callback);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    resetSuggestions() {
 | 
			
		||||
        if (this._keyboard)
 | 
			
		||||
            this._keyboard.resetSuggestions();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    shouldTakeEvent(event) {
 | 
			
		||||
        if (!this._keyboard)
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        let actor = event.get_source();
 | 
			
		||||
        return Main.layoutManager.keyboardBox.contains(actor) ||
 | 
			
		||||
               !!actor._extended_keys || !!actor.extended_key;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var Keyboard = GObject.registerClass(
 | 
			
		||||
class Keyboard extends St.BoxLayout {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init({ name: 'keyboard', vertical: true });
 | 
			
		||||
        this._focusInExtendedKeys = false;
 | 
			
		||||
        this._emojiActive = false;
 | 
			
		||||
 | 
			
		||||
        this._languagePopup = null;
 | 
			
		||||
        this._currentFocusWindow = null;
 | 
			
		||||
        this._animFocusedWindow = null;
 | 
			
		||||
        this._delayedAnimFocusWindow = null;
 | 
			
		||||
 | 
			
		||||
        this._latched = false; // current level is latched
 | 
			
		||||
 | 
			
		||||
        this._suggestions = null;
 | 
			
		||||
        this._emojiKeyVisible = Meta.is_wayland_compositor();
 | 
			
		||||
 | 
			
		||||
        this._focusTracker = new FocusTracker();
 | 
			
		||||
        this._connectSignal(this._focusTracker, 'position-changed',
 | 
			
		||||
            this._onFocusPositionChanged.bind(this));
 | 
			
		||||
        this._connectSignal(this._focusTracker, 'reset', () => {
 | 
			
		||||
            this._delayedAnimFocusWindow = null;
 | 
			
		||||
            this._animFocusedWindow = null;
 | 
			
		||||
            this._oskFocusWindow = null;
 | 
			
		||||
        });
 | 
			
		||||
        // Valid only for X11
 | 
			
		||||
        if (!Meta.is_wayland_compositor()) {
 | 
			
		||||
            this._connectSignal(this._focusTracker, 'focus-changed', (_tracker, focused) => {
 | 
			
		||||
                if (focused)
 | 
			
		||||
                    this.open(Main.layoutManager.focusIndex);
 | 
			
		||||
                else
 | 
			
		||||
                    this.close();
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._showIdleId = 0;
 | 
			
		||||
 | 
			
		||||
        this._keyboardVisible = false;
 | 
			
		||||
        this._connectSignal(Main.layoutManager, 'keyboard-visible-changed', (_lm, visible) => {
 | 
			
		||||
            this._keyboardVisible = visible;
 | 
			
		||||
        });
 | 
			
		||||
        this._keyboardRequested = false;
 | 
			
		||||
        this._keyboardRestingId = 0;
 | 
			
		||||
 | 
			
		||||
        this._connectSignal(Main.layoutManager, 'monitors-changed', this._relayout.bind(this));
 | 
			
		||||
 | 
			
		||||
        this._setupKeyboard();
 | 
			
		||||
 | 
			
		||||
        this.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _connectSignal(obj, signal, callback) {
 | 
			
		||||
        if (!this._connectionsIDs)
 | 
			
		||||
            this._connectionsIDs = [];
 | 
			
		||||
 | 
			
		||||
        let id = obj.connect(signal, callback);
 | 
			
		||||
        this._connectionsIDs.push([obj, id]);
 | 
			
		||||
        return id;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get visible() {
 | 
			
		||||
        return this._keyboardVisible && super.visible;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onFocusPositionChanged(focusTracker) {
 | 
			
		||||
        let rect = focusTracker.getCurrentRect();
 | 
			
		||||
        this.setCursorLocation(focusTracker.currentWindow, rect.x, rect.y, rect.width, rect.height);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onDestroy() {
 | 
			
		||||
        for (let [obj, id] of this._connectionsIDs)
 | 
			
		||||
            obj.disconnect(id);
 | 
			
		||||
        delete this._connectionsIDs;
 | 
			
		||||
 | 
			
		||||
    _destroyKeyboard() {
 | 
			
		||||
        if (this._keyboardNotifyId)
 | 
			
		||||
            this._keyboardController.disconnect(this._keyboardNotifyId);
 | 
			
		||||
        if (this._keyboardGroupsChangedId)
 | 
			
		||||
            this._keyboardController.disconnect(this._keyboardGroupsChangedId);
 | 
			
		||||
        if (this._keyboardStateId)
 | 
			
		||||
            this._keyboardController.disconnect(this._keyboardStateId);
 | 
			
		||||
        if (this._emojiKeyVisibleId)
 | 
			
		||||
            this._keyboardController.disconnect(this._emojiKeyVisibleId);
 | 
			
		||||
        if (this._keypadVisibleId)
 | 
			
		||||
            this._keyboardController.disconnect(this._keypadVisibleId);
 | 
			
		||||
        if (this._focusNotifyId)
 | 
			
		||||
            global.stage.disconnect(this._focusNotifyId);
 | 
			
		||||
        this._clearShowIdle();
 | 
			
		||||
 | 
			
		||||
        this._keyboardController = null;
 | 
			
		||||
        this._suggestions = null;
 | 
			
		||||
        this._aspectContainer = null;
 | 
			
		||||
        this._emojiSelection = null;
 | 
			
		||||
        this._keypad = null;
 | 
			
		||||
 | 
			
		||||
        Main.layoutManager.untrackChrome(this);
 | 
			
		||||
        Main.layoutManager.keyboardBox.remove_actor(this);
 | 
			
		||||
        this._keyboard = null;
 | 
			
		||||
        this.actor.destroy();
 | 
			
		||||
        this.actor = null;
 | 
			
		||||
 | 
			
		||||
        if (this._languagePopup) {
 | 
			
		||||
            this._languagePopup.destroy();
 | 
			
		||||
@@ -1252,8 +1168,9 @@ class Keyboard extends St.BoxLayout {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _setupKeyboard() {
 | 
			
		||||
        Main.layoutManager.keyboardBox.add_actor(this);
 | 
			
		||||
        Main.layoutManager.trackChrome(this);
 | 
			
		||||
        this.actor = new St.BoxLayout({ name: 'keyboard', vertical: true, reactive: true });
 | 
			
		||||
        Main.layoutManager.keyboardBox.add_actor(this.actor);
 | 
			
		||||
        Main.layoutManager.trackChrome(this.actor);
 | 
			
		||||
 | 
			
		||||
        this._keyboardController = new KeyboardController();
 | 
			
		||||
 | 
			
		||||
@@ -1261,28 +1178,30 @@ class Keyboard extends St.BoxLayout {
 | 
			
		||||
        this._currentPage = null;
 | 
			
		||||
 | 
			
		||||
        this._suggestions = new Suggestions();
 | 
			
		||||
        this.add(this._suggestions, { x_align: St.Align.MIDDLE, x_fill: false });
 | 
			
		||||
        this.actor.add(this._suggestions.actor,
 | 
			
		||||
                       { x_align: St.Align.MIDDLE,
 | 
			
		||||
                         x_fill: false });
 | 
			
		||||
 | 
			
		||||
        this._aspectContainer = new AspectContainer({ layout_manager: new Clutter.BinLayout() });
 | 
			
		||||
        this.add(this._aspectContainer, { expand: true });
 | 
			
		||||
        this.actor.add(this._aspectContainer, { expand: true });
 | 
			
		||||
 | 
			
		||||
        this._emojiSelection = new EmojiSelection();
 | 
			
		||||
        this._emojiSelection.connect('toggle', this._toggleEmoji.bind(this));
 | 
			
		||||
        this._emojiSelection.connect('close-request', () => this.close());
 | 
			
		||||
        this._emojiSelection.connect('hide', () => this.hide());
 | 
			
		||||
        this._emojiSelection.connect('emoji-selected', (selection, emoji) => {
 | 
			
		||||
            this._keyboardController.commitString(emoji);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this._aspectContainer.add_child(this._emojiSelection);
 | 
			
		||||
        this._emojiSelection.hide();
 | 
			
		||||
        this._aspectContainer.add_child(this._emojiSelection.actor);
 | 
			
		||||
        this._emojiSelection.actor.hide();
 | 
			
		||||
 | 
			
		||||
        this._keypad = new Keypad();
 | 
			
		||||
        this._connectSignal(this._keypad, 'keyval', (_keypad, keyval) => {
 | 
			
		||||
        this._keypad.connect('keyval', (keypad, keyval) => {
 | 
			
		||||
            this._keyboardController.keyvalPress(keyval);
 | 
			
		||||
            this._keyboardController.keyvalRelease(keyval);
 | 
			
		||||
        });
 | 
			
		||||
        this._aspectContainer.add_child(this._keypad);
 | 
			
		||||
        this._keypad.hide();
 | 
			
		||||
        this._aspectContainer.add_child(this._keypad.actor);
 | 
			
		||||
        this._keypad.actor.hide();
 | 
			
		||||
        this._keypadVisible = false;
 | 
			
		||||
 | 
			
		||||
        this._ensureKeysForGroup(this._keyboardController.getCurrentGroup());
 | 
			
		||||
@@ -1291,22 +1210,16 @@ class Keyboard extends St.BoxLayout {
 | 
			
		||||
        // Keyboard models are defined in LTR, we must override
 | 
			
		||||
        // the locale setting in order to avoid flipping the
 | 
			
		||||
        // keyboard on RTL locales.
 | 
			
		||||
        this.text_direction = Clutter.TextDirection.LTR;
 | 
			
		||||
        this.actor.text_direction = Clutter.TextDirection.LTR;
 | 
			
		||||
 | 
			
		||||
        this._connectSignal(this._keyboardController, 'active-group',
 | 
			
		||||
            this._onGroupChanged.bind(this));
 | 
			
		||||
        this._connectSignal(this._keyboardController, 'groups-changed',
 | 
			
		||||
            this._onKeyboardGroupsChanged.bind(this));
 | 
			
		||||
        this._connectSignal(this._keyboardController, 'panel-state',
 | 
			
		||||
            this._onKeyboardStateChanged.bind(this));
 | 
			
		||||
        this._connectSignal(this._keyboardController, 'keypad-visible',
 | 
			
		||||
            this._onKeypadVisible.bind(this));
 | 
			
		||||
        this._connectSignal(global.stage, 'notify::key-focus',
 | 
			
		||||
            this._onKeyFocusChanged.bind(this));
 | 
			
		||||
        this._keyboardNotifyId = this._keyboardController.connect('active-group', this._onGroupChanged.bind(this));
 | 
			
		||||
        this._keyboardGroupsChangedId = this._keyboardController.connect('groups-changed', this._onKeyboardGroupsChanged.bind(this));
 | 
			
		||||
        this._keyboardStateId = this._keyboardController.connect('panel-state', this._onKeyboardStateChanged.bind(this));
 | 
			
		||||
        this._keypadVisibleId = this._keyboardController.connect('keypad-visible', this._onKeypadVisible.bind(this));
 | 
			
		||||
        this._focusNotifyId = global.stage.connect('notify::key-focus', this._onKeyFocusChanged.bind(this));
 | 
			
		||||
 | 
			
		||||
        if (Meta.is_wayland_compositor())
 | 
			
		||||
            this._connectSignal(this._keyboardController, 'emoji-visible',
 | 
			
		||||
                this._onEmojiKeyVisible.bind(this));
 | 
			
		||||
            this._emojiKeyVisibleId = this._keyboardController.connect('emoji-visible', this._onEmojiKeyVisible.bind(this));
 | 
			
		||||
 | 
			
		||||
        this._relayout();
 | 
			
		||||
    }
 | 
			
		||||
@@ -1322,17 +1235,17 @@ class Keyboard extends St.BoxLayout {
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (!(focus instanceof Clutter.Text)) {
 | 
			
		||||
            this.close();
 | 
			
		||||
            this.hide();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!this._showIdleId) {
 | 
			
		||||
            this._showIdleId = GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => {
 | 
			
		||||
                this.open(Main.layoutManager.focusIndex);
 | 
			
		||||
                this.show(Main.layoutManager.focusIndex);
 | 
			
		||||
                this._showIdleId = 0;
 | 
			
		||||
                return GLib.SOURCE_REMOVE;
 | 
			
		||||
            });
 | 
			
		||||
            GLib.Source.set_name_by_id(this._showIdleId, '[gnome-shell] this.open');
 | 
			
		||||
            GLib.Source.set_name_by_id(this._showIdleId, '[gnome-shell] this.show');
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -1396,7 +1309,7 @@ class Keyboard extends St.BoxLayout {
 | 
			
		||||
                    this._setActiveLayer(0);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            layout.appendKey(button, button.keyButton.keyWidth);
 | 
			
		||||
            layout.appendKey(button.actor, button.keyButton.keyWidth);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -1444,7 +1357,7 @@ class Keyboard extends St.BoxLayout {
 | 
			
		||||
                if (keyval != null)
 | 
			
		||||
                    this._keyboardController.keyvalRelease(keyval);
 | 
			
		||||
                else if (action == 'hide')
 | 
			
		||||
                    this.close();
 | 
			
		||||
                    this.hide();
 | 
			
		||||
                else if (action == 'languageMenu')
 | 
			
		||||
                    this._popupLanguageMenu(actor);
 | 
			
		||||
                else if (action == 'emoji')
 | 
			
		||||
@@ -1467,7 +1380,7 @@ class Keyboard extends St.BoxLayout {
 | 
			
		||||
                    /* Only hide the key actor, so the container still takes space */
 | 
			
		||||
                    extraButton.keyButton.hide();
 | 
			
		||||
                } else {
 | 
			
		||||
                    extraButton.hide();
 | 
			
		||||
                    extraButton.actor.hide();
 | 
			
		||||
                }
 | 
			
		||||
                extraButton.setWidth(1.5);
 | 
			
		||||
            } else if (key.right && numKeys > 8) {
 | 
			
		||||
@@ -1478,7 +1391,7 @@ class Keyboard extends St.BoxLayout {
 | 
			
		||||
                extraButton.setWidth(1.5);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            layout.appendKey(extraButton, extraButton.keyButton.keyWidth);
 | 
			
		||||
            layout.appendKey(extraButton.actor, extraButton.keyButton.keyWidth);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -1489,7 +1402,7 @@ class Keyboard extends St.BoxLayout {
 | 
			
		||||
 | 
			
		||||
    _setEmojiActive(active) {
 | 
			
		||||
        this._emojiActive = active;
 | 
			
		||||
        this._emojiSelection.visible = this._emojiActive;
 | 
			
		||||
        this._emojiSelection.actor.visible = this._emojiActive;
 | 
			
		||||
        this._updateCurrentPageVisible();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -1557,12 +1470,12 @@ class Keyboard extends St.BoxLayout {
 | 
			
		||||
    _relayout() {
 | 
			
		||||
        let monitor = Main.layoutManager.keyboardMonitor;
 | 
			
		||||
 | 
			
		||||
        if (!monitor)
 | 
			
		||||
        if (this.actor == null || monitor == null)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let maxHeight = monitor.height / 3;
 | 
			
		||||
        this.width = monitor.width;
 | 
			
		||||
        this.height = maxHeight;
 | 
			
		||||
        this.actor.width = monitor.width;
 | 
			
		||||
        this.actor.height = maxHeight;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onGroupChanged() {
 | 
			
		||||
@@ -1571,7 +1484,7 @@ class Keyboard extends St.BoxLayout {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onKeyboardGroupsChanged() {
 | 
			
		||||
        let nonGroupActors = [this._emojiSelection, this._keypad];
 | 
			
		||||
        let nonGroupActors = [this._emojiSelection.actor, this._keypad.actor];
 | 
			
		||||
        this._aspectContainer.get_children().filter(c => !nonGroupActors.includes(c)).forEach(c => {
 | 
			
		||||
            c.destroy();
 | 
			
		||||
        });
 | 
			
		||||
@@ -1585,7 +1498,7 @@ class Keyboard extends St.BoxLayout {
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._keypadVisible = visible;
 | 
			
		||||
        this._keypad.visible = this._keypadVisible;
 | 
			
		||||
        this._keypad.actor.visible = this._keypadVisible;
 | 
			
		||||
        this._updateCurrentPageVisible();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -1610,9 +1523,9 @@ class Keyboard extends St.BoxLayout {
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (enabled)
 | 
			
		||||
            this.open(Main.layoutManager.focusIndex);
 | 
			
		||||
            this.show(Main.layoutManager.focusIndex);
 | 
			
		||||
        else
 | 
			
		||||
            this.close();
 | 
			
		||||
            this.hide();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _setActiveLayer(activeLevel) {
 | 
			
		||||
@@ -1639,6 +1552,12 @@ class Keyboard extends St.BoxLayout {
 | 
			
		||||
        this._updateCurrentPageVisible();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    shouldTakeEvent(event) {
 | 
			
		||||
        let actor = event.get_source();
 | 
			
		||||
        return Main.layoutManager.keyboardBox.contains(actor) ||
 | 
			
		||||
               !!actor._extended_keys || !!actor.extended_key;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _clearKeyboardRestTimer() {
 | 
			
		||||
        if (!this._keyboardRestingId)
 | 
			
		||||
            return;
 | 
			
		||||
@@ -1646,7 +1565,10 @@ class Keyboard extends St.BoxLayout {
 | 
			
		||||
        this._keyboardRestingId = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    open(monitor) {
 | 
			
		||||
    show(monitor) {
 | 
			
		||||
        if (!this._enabled)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._clearShowIdle();
 | 
			
		||||
        this._keyboardRequested = true;
 | 
			
		||||
 | 
			
		||||
@@ -1663,13 +1585,13 @@ class Keyboard extends St.BoxLayout {
 | 
			
		||||
                                                   KEYBOARD_REST_TIME,
 | 
			
		||||
                                                   () => {
 | 
			
		||||
                                                       this._clearKeyboardRestTimer();
 | 
			
		||||
                                                       this._open(monitor);
 | 
			
		||||
                                                       this._show(monitor);
 | 
			
		||||
                                                       return GLib.SOURCE_REMOVE;
 | 
			
		||||
                                                   });
 | 
			
		||||
        GLib.Source.set_name_by_id(this._keyboardRestingId, '[gnome-shell] this._clearKeyboardRestTimer');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _open(monitor) {
 | 
			
		||||
    _show(monitor) {
 | 
			
		||||
        if (!this._keyboardRequested)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
@@ -1685,7 +1607,10 @@ class Keyboard extends St.BoxLayout {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    close() {
 | 
			
		||||
    hide() {
 | 
			
		||||
        if (!this._enabled)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._clearShowIdle();
 | 
			
		||||
        this._keyboardRequested = false;
 | 
			
		||||
 | 
			
		||||
@@ -1697,13 +1622,13 @@ class Keyboard extends St.BoxLayout {
 | 
			
		||||
                                                   KEYBOARD_REST_TIME,
 | 
			
		||||
                                                   () => {
 | 
			
		||||
                                                       this._clearKeyboardRestTimer();
 | 
			
		||||
                                                       this._close();
 | 
			
		||||
                                                       this._hide();
 | 
			
		||||
                                                       return GLib.SOURCE_REMOVE;
 | 
			
		||||
                                                   });
 | 
			
		||||
        GLib.Source.set_name_by_id(this._keyboardRestingId, '[gnome-shell] this._clearKeyboardRestTimer');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _close() {
 | 
			
		||||
    _hide() {
 | 
			
		||||
        if (this._keyboardRequested)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
@@ -1720,7 +1645,7 @@ class Keyboard extends St.BoxLayout {
 | 
			
		||||
        if (!this._suggestions)
 | 
			
		||||
            return;
 | 
			
		||||
        this._suggestions.add(text, callback);
 | 
			
		||||
        this._suggestions.show();
 | 
			
		||||
        this._suggestions.actor.show();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _clearShowIdle() {
 | 
			
		||||
@@ -1797,7 +1722,7 @@ class Keyboard extends St.BoxLayout {
 | 
			
		||||
 | 
			
		||||
        this._oskFocusWindow = window;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var KeyboardController = class {
 | 
			
		||||
    constructor() {
 | 
			
		||||
 
 | 
			
		||||
@@ -606,17 +606,17 @@ var LayoutManager = GObject.registerClass({
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        this._systemBackground = new Background.SystemBackground();
 | 
			
		||||
        this._systemBackground.hide();
 | 
			
		||||
        this._systemBackground.actor.hide();
 | 
			
		||||
 | 
			
		||||
        global.stage.insert_child_below(this._systemBackground, null);
 | 
			
		||||
        global.stage.insert_child_below(this._systemBackground.actor, null);
 | 
			
		||||
 | 
			
		||||
        let constraint = new Clutter.BindConstraint({ source: global.stage,
 | 
			
		||||
                                                      coordinate: Clutter.BindCoordinate.ALL });
 | 
			
		||||
        this._systemBackground.add_constraint(constraint);
 | 
			
		||||
        this._systemBackground.actor.add_constraint(constraint);
 | 
			
		||||
 | 
			
		||||
        let signalId = this._systemBackground.connect('loaded', () => {
 | 
			
		||||
            this._systemBackground.disconnect(signalId);
 | 
			
		||||
            this._systemBackground.show();
 | 
			
		||||
            this._systemBackground.actor.show();
 | 
			
		||||
            global.stage.show();
 | 
			
		||||
 | 
			
		||||
            this._prepareStartupAnimation();
 | 
			
		||||
@@ -722,7 +722,7 @@ var LayoutManager = GObject.registerClass({
 | 
			
		||||
        this._coverPane.destroy();
 | 
			
		||||
        this._coverPane = null;
 | 
			
		||||
 | 
			
		||||
        this._systemBackground.destroy();
 | 
			
		||||
        this._systemBackground.actor.destroy();
 | 
			
		||||
        this._systemBackground = null;
 | 
			
		||||
 | 
			
		||||
        this._startingUp = false;
 | 
			
		||||
@@ -1112,11 +1112,8 @@ var LayoutManager = GObject.registerClass({
 | 
			
		||||
//
 | 
			
		||||
// This class manages a "hot corner" that can toggle switching to
 | 
			
		||||
// overview.
 | 
			
		||||
var HotCorner = GObject.registerClass(
 | 
			
		||||
class HotCorner extends Clutter.Actor {
 | 
			
		||||
    _init(layoutManager, monitor, x, y) {
 | 
			
		||||
        super._init();
 | 
			
		||||
 | 
			
		||||
var HotCorner = class HotCorner {
 | 
			
		||||
    constructor(layoutManager, monitor, x, y) {
 | 
			
		||||
        // We use this flag to mark the case where the user has entered the
 | 
			
		||||
        // hot corner and has not left both the hot corner and a surrounding
 | 
			
		||||
        // guard area (the "environs"). This avoids triggering the hot corner
 | 
			
		||||
@@ -1145,8 +1142,6 @@ class HotCorner extends Clutter.Actor {
 | 
			
		||||
 | 
			
		||||
        this._ripples = new Ripples.Ripples(px, py, 'ripple-box');
 | 
			
		||||
        this._ripples.addTo(layoutManager.uiGroup);
 | 
			
		||||
 | 
			
		||||
        this.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    setBarrierSize(size) {
 | 
			
		||||
@@ -1186,14 +1181,11 @@ class HotCorner extends Clutter.Actor {
 | 
			
		||||
 | 
			
		||||
    _setupFallbackCornerIfNeeded(layoutManager) {
 | 
			
		||||
        if (!global.display.supports_extended_barriers()) {
 | 
			
		||||
            this.set({
 | 
			
		||||
                name: 'hot-corner-environs',
 | 
			
		||||
                x: this._x,
 | 
			
		||||
                y: this._y,
 | 
			
		||||
                width: 3,
 | 
			
		||||
                height: 3,
 | 
			
		||||
                reactive: true
 | 
			
		||||
            });
 | 
			
		||||
            this.actor = new Clutter.Actor({ name: 'hot-corner-environs',
 | 
			
		||||
                                             x: this._x, y: this._y,
 | 
			
		||||
                                             width: 3,
 | 
			
		||||
                                             height: 3,
 | 
			
		||||
                                             reactive: true });
 | 
			
		||||
 | 
			
		||||
            this._corner = new Clutter.Actor({ name: 'hot-corner',
 | 
			
		||||
                                               width: 1,
 | 
			
		||||
@@ -1202,16 +1194,19 @@ class HotCorner extends Clutter.Actor {
 | 
			
		||||
                                               reactive: true });
 | 
			
		||||
            this._corner._delegate = this;
 | 
			
		||||
 | 
			
		||||
            this.add_child(this._corner);
 | 
			
		||||
            layoutManager.addChrome(this);
 | 
			
		||||
            this.actor.add_child(this._corner);
 | 
			
		||||
            layoutManager.addChrome(this.actor);
 | 
			
		||||
 | 
			
		||||
            if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL) {
 | 
			
		||||
                this._corner.set_position(this.width - this._corner.width, 0);
 | 
			
		||||
                this.set_anchor_point_from_gravity(Clutter.Gravity.NORTH_EAST);
 | 
			
		||||
                this._corner.set_position(this.actor.width - this._corner.width, 0);
 | 
			
		||||
                this.actor.set_anchor_point_from_gravity(Clutter.Gravity.NORTH_EAST);
 | 
			
		||||
            } else {
 | 
			
		||||
                this._corner.set_position(0, 0);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            this.actor.connect('leave-event',
 | 
			
		||||
                               this._onEnvironsLeft.bind(this));
 | 
			
		||||
 | 
			
		||||
            this._corner.connect('enter-event',
 | 
			
		||||
                                 this._onCornerEntered.bind(this));
 | 
			
		||||
            this._corner.connect('leave-event',
 | 
			
		||||
@@ -1219,11 +1214,14 @@ class HotCorner extends Clutter.Actor {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onDestroy() {
 | 
			
		||||
    destroy() {
 | 
			
		||||
        this.setBarrierSize(0);
 | 
			
		||||
        this._pressureBarrier.destroy();
 | 
			
		||||
        this._pressureBarrier = null;
 | 
			
		||||
 | 
			
		||||
        if (this.actor)
 | 
			
		||||
            this.actor.destroy();
 | 
			
		||||
 | 
			
		||||
        this._ripples.destroy();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -1255,18 +1253,18 @@ class HotCorner extends Clutter.Actor {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onCornerLeft(actor, event) {
 | 
			
		||||
        if (event.get_related() != this)
 | 
			
		||||
        if (event.get_related() != this.actor)
 | 
			
		||||
            this._entered = false;
 | 
			
		||||
        // Consume event, otherwise this will confuse onEnvironsLeft
 | 
			
		||||
        return Clutter.EVENT_STOP;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_leave_event(crossingEvent) {
 | 
			
		||||
        if (crossingEvent.related != this._corner)
 | 
			
		||||
    _onEnvironsLeft(actor, event) {
 | 
			
		||||
        if (event.get_related() != this._corner)
 | 
			
		||||
            this._entered = false;
 | 
			
		||||
        return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var PressureBarrier = class PressureBarrier {
 | 
			
		||||
    constructor(threshold, timeout, actionMode) {
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,7 @@
 | 
			
		||||
/* exported Lightbox */
 | 
			
		||||
 | 
			
		||||
const { Clutter, GObject, Shell, St } = imports.gi;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
 | 
			
		||||
const Params = imports.misc.params;
 | 
			
		||||
 | 
			
		||||
@@ -88,8 +89,8 @@ var RadialShaderEffect = GObject.registerClass({
 | 
			
		||||
 *           - inhibitEvents: whether to inhibit events for @container
 | 
			
		||||
 *           - width: shade actor width
 | 
			
		||||
 *           - height: shade actor height
 | 
			
		||||
 *           - fadeFactor: fading opacity factor
 | 
			
		||||
 *           - radialEffect: whether to enable the GLSL radial effect
 | 
			
		||||
 *           - fadeInTime: milliseconds used to fade in
 | 
			
		||||
 *           - fadeOutTime: milliseconds used to fade out
 | 
			
		||||
 *
 | 
			
		||||
 * Lightbox creates a dark translucent "shade" actor to hide the
 | 
			
		||||
 * contents of @container, and allows you to specify particular actors
 | 
			
		||||
@@ -105,13 +106,8 @@ var RadialShaderEffect = GObject.registerClass({
 | 
			
		||||
 * @container and will track any changes in its size. You can override
 | 
			
		||||
 * this by passing an explicit width and height in @params.
 | 
			
		||||
 */
 | 
			
		||||
var Lightbox = GObject.registerClass({
 | 
			
		||||
    Properties: {
 | 
			
		||||
        'active': GObject.ParamSpec.boolean(
 | 
			
		||||
            'active', 'active', 'active', GObject.ParamFlags.READABLE, false),
 | 
			
		||||
    }
 | 
			
		||||
}, class Lightbox extends St.Bin {
 | 
			
		||||
    _init(container, params) {
 | 
			
		||||
var Lightbox = class Lightbox {
 | 
			
		||||
    constructor(container, params) {
 | 
			
		||||
        params = Params.parse(params, {
 | 
			
		||||
            inhibitEvents: false,
 | 
			
		||||
            width: null,
 | 
			
		||||
@@ -120,34 +116,32 @@ var Lightbox = GObject.registerClass({
 | 
			
		||||
            radialEffect: false,
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        super._init({
 | 
			
		||||
            reactive: params.inhibitEvents,
 | 
			
		||||
            width: params.width,
 | 
			
		||||
            height: params.height,
 | 
			
		||||
            visible: false
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this._active = false;
 | 
			
		||||
        this._container = container;
 | 
			
		||||
        this._children = container.get_children();
 | 
			
		||||
        this._fadeFactor = params.fadeFactor;
 | 
			
		||||
        this._radialEffect = Clutter.feature_available(Clutter.FeatureFlags.SHADERS_GLSL) && params.radialEffect;
 | 
			
		||||
 | 
			
		||||
        this.actor = new St.Bin({ reactive: params.inhibitEvents });
 | 
			
		||||
 | 
			
		||||
        if (this._radialEffect)
 | 
			
		||||
            this.add_effect(new RadialShaderEffect({ name: 'radial' }));
 | 
			
		||||
            this.actor.add_effect(new RadialShaderEffect({ name: 'radial' }));
 | 
			
		||||
        else
 | 
			
		||||
            this.set({ opacity: 0, style_class: 'lightbox' });
 | 
			
		||||
            this.actor.set({ opacity: 0, style_class: 'lightbox' });
 | 
			
		||||
 | 
			
		||||
        container.add_actor(this);
 | 
			
		||||
        this.raise_top();
 | 
			
		||||
        container.add_actor(this.actor);
 | 
			
		||||
        this.actor.raise_top();
 | 
			
		||||
        this.actor.hide();
 | 
			
		||||
        this.shown = false;
 | 
			
		||||
 | 
			
		||||
        this.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
        this.actor.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
 | 
			
		||||
        if (!params.width || !params.height) {
 | 
			
		||||
            this.add_constraint(new Clutter.BindConstraint({
 | 
			
		||||
                source: container,
 | 
			
		||||
                coordinate: Clutter.BindCoordinate.ALL
 | 
			
		||||
            }));
 | 
			
		||||
        if (params.width && params.height) {
 | 
			
		||||
            this.actor.width = params.width;
 | 
			
		||||
            this.actor.height = params.height;
 | 
			
		||||
        } else {
 | 
			
		||||
            let constraint = new Clutter.BindConstraint({ source: container,
 | 
			
		||||
                                                          coordinate: Clutter.BindCoordinate.ALL });
 | 
			
		||||
            this.actor.add_constraint(constraint);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._actorAddedSignalId = container.connect('actor-added', this._actorAdded.bind(this));
 | 
			
		||||
@@ -156,20 +150,16 @@ var Lightbox = GObject.registerClass({
 | 
			
		||||
        this._highlighted = null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get active() {
 | 
			
		||||
        return this._active;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _actorAdded(container, newChild) {
 | 
			
		||||
        let children = this._container.get_children();
 | 
			
		||||
        let myIndex = children.indexOf(this);
 | 
			
		||||
        let myIndex = children.indexOf(this.actor);
 | 
			
		||||
        let newChildIndex = children.indexOf(newChild);
 | 
			
		||||
 | 
			
		||||
        if (newChildIndex > myIndex) {
 | 
			
		||||
            // The child was added above the shade (presumably it was
 | 
			
		||||
            // made the new top-most child). Move it below the shade,
 | 
			
		||||
            // and add it to this._children as the new topmost actor.
 | 
			
		||||
            this._container.set_child_above_sibling(this, newChild);
 | 
			
		||||
            newChild.lower(this.actor);
 | 
			
		||||
            this._children.push(newChild);
 | 
			
		||||
        } else if (newChildIndex == 0) {
 | 
			
		||||
            // Bottom of stack
 | 
			
		||||
@@ -182,8 +172,8 @@ var Lightbox = GObject.registerClass({
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    lightOn(fadeInTime) {
 | 
			
		||||
        this.remove_all_transitions();
 | 
			
		||||
    show(fadeInTime) {
 | 
			
		||||
        this.actor.remove_all_transitions();
 | 
			
		||||
 | 
			
		||||
        let easeProps = {
 | 
			
		||||
            duration: fadeInTime || 0,
 | 
			
		||||
@@ -191,46 +181,44 @@ var Lightbox = GObject.registerClass({
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        let onComplete = () => {
 | 
			
		||||
            this._active = true;
 | 
			
		||||
            this.notify('active');
 | 
			
		||||
            this.shown = true;
 | 
			
		||||
            this.emit('shown');
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        this.show();
 | 
			
		||||
        this.actor.show();
 | 
			
		||||
 | 
			
		||||
        if (this._radialEffect) {
 | 
			
		||||
            this.ease_property(
 | 
			
		||||
            this.actor.ease_property(
 | 
			
		||||
                '@effects.radial.brightness', VIGNETTE_BRIGHTNESS, easeProps);
 | 
			
		||||
            this.ease_property(
 | 
			
		||||
            this.actor.ease_property(
 | 
			
		||||
                '@effects.radial.sharpness', VIGNETTE_SHARPNESS,
 | 
			
		||||
                Object.assign({ onComplete }, easeProps));
 | 
			
		||||
        } else {
 | 
			
		||||
            this.ease(Object.assign(easeProps, {
 | 
			
		||||
            this.actor.ease(Object.assign(easeProps, {
 | 
			
		||||
                opacity: 255 * this._fadeFactor,
 | 
			
		||||
                onComplete
 | 
			
		||||
            }));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    lightOff(fadeOutTime) {
 | 
			
		||||
        this.remove_all_transitions();
 | 
			
		||||
 | 
			
		||||
        this._active = false;
 | 
			
		||||
        this.notify('active');
 | 
			
		||||
    hide(fadeOutTime) {
 | 
			
		||||
        this.shown = false;
 | 
			
		||||
        this.actor.remove_all_transitions();
 | 
			
		||||
 | 
			
		||||
        let easeProps = {
 | 
			
		||||
            duration: fadeOutTime || 0,
 | 
			
		||||
            mode: Clutter.AnimationMode.EASE_OUT_QUAD
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        let onComplete = () => this.hide();
 | 
			
		||||
        let onComplete = () => this.actor.hide();
 | 
			
		||||
 | 
			
		||||
        if (this._radialEffect) {
 | 
			
		||||
            this.ease_property(
 | 
			
		||||
            this.actor.ease_property(
 | 
			
		||||
                '@effects.radial.brightness', 1.0, easeProps);
 | 
			
		||||
            this.ease_property(
 | 
			
		||||
            this.actor.ease_property(
 | 
			
		||||
                '@effects.radial.sharpness', 0.0, Object.assign({ onComplete }, easeProps));
 | 
			
		||||
        } else {
 | 
			
		||||
            this.ease(Object.assign(easeProps, { opacity: 0, onComplete }));
 | 
			
		||||
            this.actor.ease(Object.assign(easeProps, { opacity: 0, onComplete }));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -261,7 +249,7 @@ var Lightbox = GObject.registerClass({
 | 
			
		||||
        // case we may need to indicate some *other* actor as the new
 | 
			
		||||
        // sibling of the to-be-lowered one.
 | 
			
		||||
 | 
			
		||||
        let below = this;
 | 
			
		||||
        let below = this.actor;
 | 
			
		||||
        for (let i = this._children.length - 1; i >= 0; i--) {
 | 
			
		||||
            if (this._children[i] == window)
 | 
			
		||||
                this._children[i].raise_top();
 | 
			
		||||
@@ -274,6 +262,15 @@ var Lightbox = GObject.registerClass({
 | 
			
		||||
        this._highlighted = window;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * destroy:
 | 
			
		||||
     *
 | 
			
		||||
     * Destroys the lightbox.
 | 
			
		||||
     */
 | 
			
		||||
    destroy() {
 | 
			
		||||
        this.actor.destroy();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * _onDestroy:
 | 
			
		||||
     *
 | 
			
		||||
@@ -281,15 +278,10 @@ var Lightbox = GObject.registerClass({
 | 
			
		||||
     * by destroying its container or by explicitly calling this.destroy().
 | 
			
		||||
     */
 | 
			
		||||
    _onDestroy() {
 | 
			
		||||
        if (this._actorAddedSignalId) {
 | 
			
		||||
            this._container.disconnect(this._actorAddedSignalId);
 | 
			
		||||
            this._actorAddedSignalId = 0;
 | 
			
		||||
        }
 | 
			
		||||
        if (this._actorRemovedSignalId) {
 | 
			
		||||
            this._container.disconnect(this._actorRemovedSignalId);
 | 
			
		||||
            this._actorRemovedSignalId = 0;
 | 
			
		||||
        }
 | 
			
		||||
        this._container.disconnect(this._actorAddedSignalId);
 | 
			
		||||
        this._container.disconnect(this._actorRemovedSignalId);
 | 
			
		||||
 | 
			
		||||
        this.highlight(null);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(Lightbox.prototype);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,8 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/* exported LookingGlass */
 | 
			
		||||
 | 
			
		||||
const { Clutter, Cogl, Gio, GLib, GObject,
 | 
			
		||||
        Graphene, Meta, Pango, Shell, St } = imports.gi;
 | 
			
		||||
const { Clutter, Cogl, Gio, GLib,
 | 
			
		||||
        GObject, Meta, Pango, Shell, St } = imports.gi;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
const System = imports.system;
 | 
			
		||||
 | 
			
		||||
@@ -110,11 +110,9 @@ var AutoComplete = class AutoComplete {
 | 
			
		||||
Signals.addSignalMethods(AutoComplete.prototype);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
var Notebook = GObject.registerClass({
 | 
			
		||||
    Signals: { 'selection': { param_types: [Clutter.Actor.$gtype] } },
 | 
			
		||||
}, class Notebook extends St.BoxLayout {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init({ vertical: true });
 | 
			
		||||
var Notebook = class Notebook {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        this.actor = new St.BoxLayout({ vertical: true });
 | 
			
		||||
 | 
			
		||||
        this.tabControls = new St.BoxLayout({ style_class: 'labels' });
 | 
			
		||||
 | 
			
		||||
@@ -145,7 +143,7 @@ var Notebook = GObject.registerClass({
 | 
			
		||||
                        _scrollToBottom: false };
 | 
			
		||||
        this._tabs.push(tabData);
 | 
			
		||||
        scrollview.hide();
 | 
			
		||||
        this.add(scrollview, { expand: true });
 | 
			
		||||
        this.actor.add(scrollview, { expand: true });
 | 
			
		||||
 | 
			
		||||
        let vAdjust = scrollview.vscroll.adjustment;
 | 
			
		||||
        vAdjust.connect('changed', () => this._onAdjustScopeChanged(tabData));
 | 
			
		||||
@@ -176,7 +174,7 @@ var Notebook = GObject.registerClass({
 | 
			
		||||
        // Focus the new tab before unmapping the old one
 | 
			
		||||
        let tabData = this._tabs[index];
 | 
			
		||||
        if (!tabData.scrollView.navigate_focus(null, St.DirectionType.TAB_FORWARD, false))
 | 
			
		||||
            this.grab_key_focus();
 | 
			
		||||
            this.actor.grab_key_focus();
 | 
			
		||||
 | 
			
		||||
        this._unselect();
 | 
			
		||||
 | 
			
		||||
@@ -236,7 +234,8 @@ var Notebook = GObject.registerClass({
 | 
			
		||||
 | 
			
		||||
        this.selectIndex(prevIndex);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(Notebook.prototype);
 | 
			
		||||
 | 
			
		||||
function objectToString(o) {
 | 
			
		||||
    if (typeof o == typeof objectToString) {
 | 
			
		||||
@@ -247,64 +246,57 @@ function objectToString(o) {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var ObjLink = GObject.registerClass(
 | 
			
		||||
class ObjLink extends St.Button {
 | 
			
		||||
    _init(lookingGlass, o, title) {
 | 
			
		||||
var ObjLink = class ObjLink {
 | 
			
		||||
    constructor(lookingGlass, o, title) {
 | 
			
		||||
        let text;
 | 
			
		||||
        if (title)
 | 
			
		||||
            text = title;
 | 
			
		||||
        else
 | 
			
		||||
            text = objectToString(o);
 | 
			
		||||
        text = GLib.markup_escape_text(text, -1);
 | 
			
		||||
 | 
			
		||||
        super._init({
 | 
			
		||||
            reactive: true,
 | 
			
		||||
            track_hover: true,
 | 
			
		||||
            style_class: 'shell-link',
 | 
			
		||||
            label: text
 | 
			
		||||
        });
 | 
			
		||||
        this.get_child().single_line_mode = true;
 | 
			
		||||
 | 
			
		||||
        this._obj = o;
 | 
			
		||||
 | 
			
		||||
        this.actor = new St.Button({ reactive: true,
 | 
			
		||||
                                     track_hover: true,
 | 
			
		||||
                                     style_class: 'shell-link',
 | 
			
		||||
                                     label: text });
 | 
			
		||||
        this.actor.get_child().single_line_mode = true;
 | 
			
		||||
        this.actor.connect('clicked', this._onClicked.bind(this));
 | 
			
		||||
 | 
			
		||||
        this._lookingGlass = lookingGlass;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_clicked() {
 | 
			
		||||
        this._lookingGlass.inspectObject(this._obj, this);
 | 
			
		||||
    _onClicked() {
 | 
			
		||||
        this._lookingGlass.inspectObject(this._obj, this.actor);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
var Result = GObject.registerClass({
 | 
			
		||||
    GTypeName: 'LookingClass_Result'
 | 
			
		||||
}, class Result extends St.BoxLayout {
 | 
			
		||||
    _init(lookingGlass, command, o, index) {
 | 
			
		||||
        super._init({ vertical: true });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var Result = class Result {
 | 
			
		||||
    constructor(lookingGlass, command, o, index) {
 | 
			
		||||
        this.index = index;
 | 
			
		||||
        this.o = o;
 | 
			
		||||
 | 
			
		||||
        this.actor = new St.BoxLayout({ vertical: true });
 | 
			
		||||
        this._lookingGlass = lookingGlass;
 | 
			
		||||
 | 
			
		||||
        let cmdTxt = new St.Label({ text: command });
 | 
			
		||||
        cmdTxt.clutter_text.ellipsize = Pango.EllipsizeMode.END;
 | 
			
		||||
        this.add(cmdTxt);
 | 
			
		||||
        this.actor.add(cmdTxt);
 | 
			
		||||
        let box = new St.BoxLayout({});
 | 
			
		||||
        this.add(box);
 | 
			
		||||
        this.actor.add(box);
 | 
			
		||||
        let resultTxt = new St.Label({ text: `r(${index}) = ` });
 | 
			
		||||
        resultTxt.clutter_text.ellipsize = Pango.EllipsizeMode.END;
 | 
			
		||||
        box.add(resultTxt);
 | 
			
		||||
        let objLink = new ObjLink(this._lookingGlass, o);
 | 
			
		||||
        box.add(objLink);
 | 
			
		||||
        box.add(objLink.actor);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var WindowList = GObject.registerClass({
 | 
			
		||||
    GTypeName: 'LookingClass_WindowList'
 | 
			
		||||
}, class WindowList extends St.BoxLayout {
 | 
			
		||||
    _init(lookingGlass) {
 | 
			
		||||
        super._init({ name: 'Windows', vertical: true, style: 'spacing: 8px' });
 | 
			
		||||
var WindowList = class WindowList {
 | 
			
		||||
    constructor(lookingGlass) {
 | 
			
		||||
        this.actor = new St.BoxLayout({ name: 'Windows', vertical: true, style: 'spacing: 8px' });
 | 
			
		||||
        let tracker = Shell.WindowTracker.get_default();
 | 
			
		||||
        this._updateId = Main.initializeDeferredWork(this, this._updateWindowList.bind(this));
 | 
			
		||||
        this._updateId = Main.initializeDeferredWork(this.actor, this._updateWindowList.bind(this));
 | 
			
		||||
        global.display.connect('window-created', this._updateWindowList.bind(this));
 | 
			
		||||
        tracker.connect('tracked-windows-changed', this._updateWindowList.bind(this));
 | 
			
		||||
 | 
			
		||||
@@ -315,7 +307,7 @@ var WindowList = GObject.registerClass({
 | 
			
		||||
        if (!this._lookingGlass.isOpen)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this.destroy_all_children();
 | 
			
		||||
        this.actor.destroy_all_children();
 | 
			
		||||
        let windows = global.get_window_actors();
 | 
			
		||||
        let tracker = Shell.WindowTracker.get_default();
 | 
			
		||||
        for (let i = 0; i < windows.length; i++) {
 | 
			
		||||
@@ -326,9 +318,9 @@ var WindowList = GObject.registerClass({
 | 
			
		||||
                metaWindow._lookingGlassManaged = true;
 | 
			
		||||
            }
 | 
			
		||||
            let box = new St.BoxLayout({ vertical: true });
 | 
			
		||||
            this.add(box);
 | 
			
		||||
            this.actor.add(box);
 | 
			
		||||
            let windowLink = new ObjLink(this._lookingGlass, metaWindow, metaWindow.title);
 | 
			
		||||
            box.add(windowLink, { x_align: St.Align.START, x_fill: false });
 | 
			
		||||
            box.add(windowLink.actor, { x_align: St.Align.START, x_fill: false });
 | 
			
		||||
            let propsBox = new St.BoxLayout({ vertical: true, style: 'padding-left: 6px;' });
 | 
			
		||||
            box.add(propsBox);
 | 
			
		||||
            propsBox.add(new St.Label({ text: `wmclass: ${metaWindow.get_wm_class()}` }));
 | 
			
		||||
@@ -339,7 +331,7 @@ var WindowList = GObject.registerClass({
 | 
			
		||||
                propsBox.add(propBox);
 | 
			
		||||
                propBox.add(new St.Label({ text: 'app: ' }), { y_fill: false });
 | 
			
		||||
                let appLink = new ObjLink(this._lookingGlass, app, app.get_id());
 | 
			
		||||
                propBox.add(appLink, { y_fill: false });
 | 
			
		||||
                propBox.add(appLink.actor, { y_fill: false });
 | 
			
		||||
                propBox.add(icon, { y_fill: false });
 | 
			
		||||
            } else {
 | 
			
		||||
                propsBox.add(new St.Label({ text: '<untracked>' }));
 | 
			
		||||
@@ -350,27 +342,23 @@ var WindowList = GObject.registerClass({
 | 
			
		||||
    update() {
 | 
			
		||||
        this._updateWindowList();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
var ObjInspector = GObject.registerClass(
 | 
			
		||||
class ObjInspector extends St.ScrollView {
 | 
			
		||||
    _init(lookingGlass) {
 | 
			
		||||
        super._init({
 | 
			
		||||
            pivot_point: new Graphene.Point({ x: 0.5, y: 0.5 }),
 | 
			
		||||
            x_fill: true,
 | 
			
		||||
            y_fill: true
 | 
			
		||||
        });
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(WindowList.prototype);
 | 
			
		||||
 | 
			
		||||
var ObjInspector = class ObjInspector {
 | 
			
		||||
    constructor(lookingGlass) {
 | 
			
		||||
        this._obj = null;
 | 
			
		||||
        this._previousObj = null;
 | 
			
		||||
 | 
			
		||||
        this._parentList = [];
 | 
			
		||||
 | 
			
		||||
        this.get_hscroll_bar().hide();
 | 
			
		||||
        this.actor = new St.ScrollView({ pivot_point: new Clutter.Point({ x: 0.5, y: 0.5 }),
 | 
			
		||||
                                         x_fill: true, y_fill: true });
 | 
			
		||||
        this.actor.get_hscroll_bar().hide();
 | 
			
		||||
        this._container = new St.BoxLayout({ name: 'LookingGlassPropertyInspector',
 | 
			
		||||
                                             style_class: 'lg-dialog',
 | 
			
		||||
                                             vertical: true });
 | 
			
		||||
        this.add_actor(this._container);
 | 
			
		||||
        this.actor.add_actor(this._container);
 | 
			
		||||
 | 
			
		||||
        this._lookingGlass = lookingGlass;
 | 
			
		||||
    }
 | 
			
		||||
@@ -416,7 +404,7 @@ class ObjInspector extends St.ScrollView {
 | 
			
		||||
                let link;
 | 
			
		||||
                try {
 | 
			
		||||
                    let prop = obj[propName];
 | 
			
		||||
                    link = new ObjLink(this._lookingGlass, prop);
 | 
			
		||||
                    link = new ObjLink(this._lookingGlass, prop).actor;
 | 
			
		||||
                } catch (e) {
 | 
			
		||||
                    link = new St.Label({ text: '<error>' });
 | 
			
		||||
                }
 | 
			
		||||
@@ -433,17 +421,17 @@ class ObjInspector extends St.ScrollView {
 | 
			
		||||
            return;
 | 
			
		||||
        this._previousObj = null;
 | 
			
		||||
        this._open = true;
 | 
			
		||||
        this.show();
 | 
			
		||||
        this.actor.show();
 | 
			
		||||
        if (sourceActor) {
 | 
			
		||||
            this.set_scale(0, 0);
 | 
			
		||||
            this.ease({
 | 
			
		||||
            this.actor.set_scale(0, 0);
 | 
			
		||||
            this.actor.ease({
 | 
			
		||||
                scale_x: 1,
 | 
			
		||||
                scale_y: 1,
 | 
			
		||||
                mode: Clutter.AnimationMode.EASE_OUT_QUAD,
 | 
			
		||||
                duration: 200
 | 
			
		||||
                time: 200
 | 
			
		||||
            });
 | 
			
		||||
        } else {
 | 
			
		||||
            this.set_scale(1, 1);
 | 
			
		||||
            this.actor.set_scale(1, 1);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -451,7 +439,7 @@ class ObjInspector extends St.ScrollView {
 | 
			
		||||
        if (!this._open)
 | 
			
		||||
            return;
 | 
			
		||||
        this._open = false;
 | 
			
		||||
        this.hide();
 | 
			
		||||
        this.actor.hide();
 | 
			
		||||
        this._previousObj = null;
 | 
			
		||||
        this._obj = null;
 | 
			
		||||
    }
 | 
			
		||||
@@ -465,7 +453,7 @@ class ObjInspector extends St.ScrollView {
 | 
			
		||||
    _onBack() {
 | 
			
		||||
        this.selectObject(this._previousObj, true);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var RedBorderEffect = GObject.registerClass(
 | 
			
		||||
class RedBorderEffect extends Clutter.Effect {
 | 
			
		||||
@@ -496,7 +484,8 @@ var Inspector = GObject.registerClass({
 | 
			
		||||
               'target': { param_types: [Clutter.Actor.$gtype, GObject.TYPE_DOUBLE, GObject.TYPE_DOUBLE] } },
 | 
			
		||||
}, class Inspector extends Clutter.Actor {
 | 
			
		||||
    _init(lookingGlass) {
 | 
			
		||||
        super._init({ width: 0, height: 0 });
 | 
			
		||||
        super._init({ width: 0,
 | 
			
		||||
                      height: 0 });
 | 
			
		||||
 | 
			
		||||
        Main.uiGroup.add_actor(this);
 | 
			
		||||
 | 
			
		||||
@@ -631,20 +620,18 @@ var Inspector = GObject.registerClass({
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
var Extensions = GObject.registerClass({
 | 
			
		||||
    GTypeName: 'LookingClass_Extensions'
 | 
			
		||||
}, class Extensions extends St.BoxLayout {
 | 
			
		||||
    _init(lookingGlass) {
 | 
			
		||||
        super._init({ vertical: true, name: 'lookingGlassExtensions' });
 | 
			
		||||
 | 
			
		||||
var Extensions = class Extensions {
 | 
			
		||||
    constructor(lookingGlass) {
 | 
			
		||||
        this._lookingGlass = lookingGlass;
 | 
			
		||||
        this.actor = new St.BoxLayout({ vertical: true,
 | 
			
		||||
                                        name: 'lookingGlassExtensions' });
 | 
			
		||||
        this._noExtensions = new St.Label({ style_class: 'lg-extensions-none',
 | 
			
		||||
                                            text: _("No extensions installed") });
 | 
			
		||||
        this._numExtensions = 0;
 | 
			
		||||
        this._extensionsList = new St.BoxLayout({ vertical: true,
 | 
			
		||||
                                                  style_class: 'lg-extensions-list' });
 | 
			
		||||
        this._extensionsList.add(this._noExtensions);
 | 
			
		||||
        this.add(this._extensionsList);
 | 
			
		||||
        this.actor.add(this._extensionsList);
 | 
			
		||||
 | 
			
		||||
        Main.extensionManager.getUuids().forEach(uuid => {
 | 
			
		||||
            this._loadExtension(null, uuid);
 | 
			
		||||
@@ -772,19 +759,10 @@ var Extensions = GObject.registerClass({
 | 
			
		||||
 | 
			
		||||
        return box;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
var LookingGlass = GObject.registerClass(
 | 
			
		||||
class LookingGlass extends St.BoxLayout {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init({
 | 
			
		||||
            name: 'LookingGlassDialog',
 | 
			
		||||
            style_class: 'lg-dialog',
 | 
			
		||||
            vertical: true,
 | 
			
		||||
            visible: false,
 | 
			
		||||
            reactive: true
 | 
			
		||||
        });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var LookingGlass = class LookingGlass {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        this._borderPaintTarget = null;
 | 
			
		||||
        this._redBorderEffect = new RedBorderEffect();
 | 
			
		||||
 | 
			
		||||
@@ -792,18 +770,26 @@ class LookingGlass extends St.BoxLayout {
 | 
			
		||||
 | 
			
		||||
        this._it = null;
 | 
			
		||||
        this._offset = 0;
 | 
			
		||||
        this._results = [];
 | 
			
		||||
 | 
			
		||||
        // Sort of magic, but...eh.
 | 
			
		||||
        this._maxItems = 150;
 | 
			
		||||
 | 
			
		||||
        this.actor = new St.BoxLayout({ name: 'LookingGlassDialog',
 | 
			
		||||
                                        style_class: 'lg-dialog',
 | 
			
		||||
                                        vertical: true,
 | 
			
		||||
                                        visible: false,
 | 
			
		||||
                                        reactive: true });
 | 
			
		||||
        this.actor.connect('key-press-event', this._globalKeyPressEvent.bind(this));
 | 
			
		||||
 | 
			
		||||
        this._interfaceSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.interface' });
 | 
			
		||||
        this._interfaceSettings.connect('changed::monospace-font-name',
 | 
			
		||||
                                        this._updateFont.bind(this));
 | 
			
		||||
        this._updateFont();
 | 
			
		||||
 | 
			
		||||
        // We want it to appear to slide out from underneath the panel
 | 
			
		||||
        Main.uiGroup.add_actor(this);
 | 
			
		||||
        Main.uiGroup.set_child_below_sibling(this,
 | 
			
		||||
        Main.uiGroup.add_actor(this.actor);
 | 
			
		||||
        Main.uiGroup.set_child_below_sibling(this.actor,
 | 
			
		||||
                                             Main.layoutManager.panelBox);
 | 
			
		||||
        Main.layoutManager.panelBox.connect('allocation-changed',
 | 
			
		||||
                                            this._queueResize.bind(this));
 | 
			
		||||
@@ -811,11 +797,11 @@ class LookingGlass extends St.BoxLayout {
 | 
			
		||||
                                               this._queueResize.bind(this));
 | 
			
		||||
 | 
			
		||||
        this._objInspector = new ObjInspector(this);
 | 
			
		||||
        Main.uiGroup.add_actor(this._objInspector);
 | 
			
		||||
        this._objInspector.hide();
 | 
			
		||||
        Main.uiGroup.add_actor(this._objInspector.actor);
 | 
			
		||||
        this._objInspector.actor.hide();
 | 
			
		||||
 | 
			
		||||
        let toolbar = new St.BoxLayout({ name: 'Toolbar' });
 | 
			
		||||
        this.add_actor(toolbar);
 | 
			
		||||
        this.actor.add_actor(toolbar);
 | 
			
		||||
        let inspectIcon = new St.Icon({ icon_name: 'gtk-color-picker',
 | 
			
		||||
                                        icon_size: 24 });
 | 
			
		||||
        toolbar.add_actor(inspectIcon);
 | 
			
		||||
@@ -826,10 +812,10 @@ class LookingGlass extends St.BoxLayout {
 | 
			
		||||
                this._pushResult(`inspect(${Math.round(stageX)}, ${Math.round(stageY)})`, target);
 | 
			
		||||
            });
 | 
			
		||||
            inspector.connect('closed', () => {
 | 
			
		||||
                this.show();
 | 
			
		||||
                this.actor.show();
 | 
			
		||||
                global.stage.set_key_focus(this._entry);
 | 
			
		||||
            });
 | 
			
		||||
            this.hide();
 | 
			
		||||
            this.actor.hide();
 | 
			
		||||
            return Clutter.EVENT_STOP;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
@@ -851,7 +837,7 @@ class LookingGlass extends St.BoxLayout {
 | 
			
		||||
 | 
			
		||||
        let notebook = new Notebook();
 | 
			
		||||
        this._notebook = notebook;
 | 
			
		||||
        this.add(notebook, { expand: true });
 | 
			
		||||
        this.actor.add(notebook.actor, { expand: true });
 | 
			
		||||
 | 
			
		||||
        let emptyBox = new St.Bin();
 | 
			
		||||
        toolbar.add(emptyBox, { expand: true });
 | 
			
		||||
@@ -874,10 +860,10 @@ class LookingGlass extends St.BoxLayout {
 | 
			
		||||
        this._entryArea.add(this._entry, { expand: true });
 | 
			
		||||
 | 
			
		||||
        this._windowList = new WindowList(this);
 | 
			
		||||
        notebook.appendPage('Windows', this._windowList);
 | 
			
		||||
        notebook.appendPage('Windows', this._windowList.actor);
 | 
			
		||||
 | 
			
		||||
        this._extensions = new Extensions(this);
 | 
			
		||||
        notebook.appendPage('Extensions', this._extensions);
 | 
			
		||||
        notebook.appendPage('Extensions', this._extensions.actor);
 | 
			
		||||
 | 
			
		||||
        this._entry.clutter_text.connect('activate', (o, _e) => {
 | 
			
		||||
            // Hide any completions we are currently showing
 | 
			
		||||
@@ -919,7 +905,7 @@ class LookingGlass extends St.BoxLayout {
 | 
			
		||||
        // monospace font to be bold/oblique/etc. Could easily be added here.
 | 
			
		||||
        let size = fontDesc.get_size() / 1024.;
 | 
			
		||||
        let unit = fontDesc.get_size_is_absolute() ? 'px' : 'pt';
 | 
			
		||||
        this.style = `
 | 
			
		||||
        this.actor.style = `
 | 
			
		||||
            font-size: ${size}${unit};
 | 
			
		||||
            font-family: "${fontDesc.get_family()}";`;
 | 
			
		||||
    }
 | 
			
		||||
@@ -933,14 +919,17 @@ class LookingGlass extends St.BoxLayout {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _pushResult(command, obj) {
 | 
			
		||||
        let index = this._resultsArea.get_n_children() + this._offset;
 | 
			
		||||
        let index = this._results.length + this._offset;
 | 
			
		||||
        let result = new Result(this, CHEVRON + command, obj, index);
 | 
			
		||||
        this._resultsArea.add(result);
 | 
			
		||||
        this._results.push(result);
 | 
			
		||||
        this._resultsArea.add(result.actor);
 | 
			
		||||
        if (obj instanceof Clutter.Actor)
 | 
			
		||||
            this.setBorderPaintTarget(obj);
 | 
			
		||||
 | 
			
		||||
        if (this._resultsArea.get_n_children() > this._maxItems) {
 | 
			
		||||
            this._resultsArea.get_first_child().destroy();
 | 
			
		||||
        let children = this._resultsArea.get_children();
 | 
			
		||||
        if (children.length > this._maxItems) {
 | 
			
		||||
            this._results.shift();
 | 
			
		||||
            children[0].destroy();
 | 
			
		||||
            this._offset++;
 | 
			
		||||
        }
 | 
			
		||||
        this._it = obj;
 | 
			
		||||
@@ -1027,7 +1016,7 @@ class LookingGlass extends St.BoxLayout {
 | 
			
		||||
 | 
			
		||||
    getResult(idx) {
 | 
			
		||||
        try {
 | 
			
		||||
            return this._resultsArea.get_child_at_index(idx - this._offset).o;
 | 
			
		||||
            return this._results[idx - this._offset].o;
 | 
			
		||||
        } catch (e) {
 | 
			
		||||
            throw new Error(`Unknown result at index ${idx}`);
 | 
			
		||||
        }
 | 
			
		||||
@@ -1052,15 +1041,15 @@ class LookingGlass extends St.BoxLayout {
 | 
			
		||||
        let myWidth = primary.width * 0.7;
 | 
			
		||||
        let availableHeight = primary.height - Main.layoutManager.keyboardBox.height;
 | 
			
		||||
        let myHeight = Math.min(primary.height * 0.7, availableHeight * 0.9);
 | 
			
		||||
        this.x = primary.x + (primary.width - myWidth) / 2;
 | 
			
		||||
        this.actor.x = primary.x + (primary.width - myWidth) / 2;
 | 
			
		||||
        this._hiddenY = primary.y + Main.layoutManager.panelBox.height - myHeight;
 | 
			
		||||
        this._targetY = this._hiddenY + myHeight;
 | 
			
		||||
        this.y = this._hiddenY;
 | 
			
		||||
        this.width = myWidth;
 | 
			
		||||
        this.height = myHeight;
 | 
			
		||||
        this._objInspector.set_size(Math.floor(myWidth * 0.8), Math.floor(myHeight * 0.8));
 | 
			
		||||
        this._objInspector.set_position(this.x + Math.floor(myWidth * 0.1),
 | 
			
		||||
                                        this._targetY + Math.floor(myHeight * 0.1));
 | 
			
		||||
        this.actor.y = this._hiddenY;
 | 
			
		||||
        this.actor.width = myWidth;
 | 
			
		||||
        this.actor.height = myHeight;
 | 
			
		||||
        this._objInspector.actor.set_size(Math.floor(myWidth * 0.8), Math.floor(myHeight * 0.8));
 | 
			
		||||
        this._objInspector.actor.set_position(this.actor.x + Math.floor(myWidth * 0.1),
 | 
			
		||||
                                              this._targetY + Math.floor(myHeight * 0.1));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    insertObject(obj) {
 | 
			
		||||
@@ -1073,10 +1062,11 @@ class LookingGlass extends St.BoxLayout {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Handle key events which are relevant for all tabs of the LookingGlass
 | 
			
		||||
    vfunc_key_press_event(keyPressEvent) {
 | 
			
		||||
        let symbol = keyPressEvent.keyval;
 | 
			
		||||
    _globalKeyPressEvent(actor, event) {
 | 
			
		||||
        let symbol = event.get_key_symbol();
 | 
			
		||||
        let modifierState = event.get_state();
 | 
			
		||||
        if (symbol == Clutter.Escape) {
 | 
			
		||||
            if (this._objInspector.visible) {
 | 
			
		||||
            if (this._objInspector.actor.visible) {
 | 
			
		||||
                this._objInspector.close();
 | 
			
		||||
            } else {
 | 
			
		||||
                this.close();
 | 
			
		||||
@@ -1084,7 +1074,7 @@ class LookingGlass extends St.BoxLayout {
 | 
			
		||||
            return Clutter.EVENT_STOP;
 | 
			
		||||
        }
 | 
			
		||||
        // Ctrl+PgUp and Ctrl+PgDown switches tabs in the notebook view
 | 
			
		||||
        if (keyPressEvent.modifier_state & Clutter.ModifierType.CONTROL_MASK) {
 | 
			
		||||
        if (modifierState & Clutter.ModifierType.CONTROL_MASK) {
 | 
			
		||||
            if (symbol == Clutter.KEY_Page_Up) {
 | 
			
		||||
                this._notebook.prevTab();
 | 
			
		||||
            } else if (symbol == Clutter.KEY_Page_Down) {
 | 
			
		||||
@@ -1102,16 +1092,16 @@ class LookingGlass extends St.BoxLayout {
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._notebook.selectIndex(0);
 | 
			
		||||
        this.show();
 | 
			
		||||
        this.actor.show();
 | 
			
		||||
        this._open = true;
 | 
			
		||||
        this._history.lastItem();
 | 
			
		||||
 | 
			
		||||
        this.remove_all_transitions();
 | 
			
		||||
        this.actor.remove_all_transitions();
 | 
			
		||||
 | 
			
		||||
        // We inverse compensate for the slow-down so you can change the factor
 | 
			
		||||
        // through LookingGlass without long waits.
 | 
			
		||||
        let duration = LG_ANIMATION_TIME / St.Settings.get().slow_down_factor;
 | 
			
		||||
        this.ease({
 | 
			
		||||
        this.actor.ease({
 | 
			
		||||
            y: this._targetY,
 | 
			
		||||
            duration,
 | 
			
		||||
            mode: Clutter.AnimationMode.EASE_OUT_QUAD
 | 
			
		||||
@@ -1124,10 +1114,10 @@ class LookingGlass extends St.BoxLayout {
 | 
			
		||||
        if (!this._open)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._objInspector.hide();
 | 
			
		||||
        this._objInspector.actor.hide();
 | 
			
		||||
 | 
			
		||||
        this._open = false;
 | 
			
		||||
        this.remove_all_transitions();
 | 
			
		||||
        this.actor.remove_all_transitions();
 | 
			
		||||
 | 
			
		||||
        this.setBorderPaintTarget(null);
 | 
			
		||||
 | 
			
		||||
@@ -1136,15 +1126,16 @@ class LookingGlass extends St.BoxLayout {
 | 
			
		||||
        let settings = St.Settings.get();
 | 
			
		||||
        let duration = Math.min(LG_ANIMATION_TIME / settings.slow_down_factor,
 | 
			
		||||
                                LG_ANIMATION_TIME);
 | 
			
		||||
        this.ease({
 | 
			
		||||
        this.actor.ease({
 | 
			
		||||
            y: this._hiddenY,
 | 
			
		||||
            duration,
 | 
			
		||||
            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
 | 
			
		||||
            onComplete: () => this.hide()
 | 
			
		||||
            onComplete: () => this.actor.hide()
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get isOpen() {
 | 
			
		||||
        return this._open;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(LookingGlass.prototype);
 | 
			
		||||
 
 | 
			
		||||
@@ -1290,7 +1290,7 @@ var ZoomRegion = class ZoomRegion {
 | 
			
		||||
 | 
			
		||||
        // Add a background for when the magnified uiGroup is scrolled
 | 
			
		||||
        // out of view (don't want to see desktop showing through).
 | 
			
		||||
        this._background = new Background.SystemBackground();
 | 
			
		||||
        this._background = (new Background.SystemBackground()).actor;
 | 
			
		||||
        mainGroup.add_actor(this._background);
 | 
			
		||||
 | 
			
		||||
        // Clone the group that contains all of UI on the screen.  This is the
 | 
			
		||||
@@ -1587,9 +1587,8 @@ var ZoomRegion = class ZoomRegion {
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var Crosshairs = GObject.registerClass(
 | 
			
		||||
class Crosshairs extends Clutter.Actor {
 | 
			
		||||
    _init() {
 | 
			
		||||
var Crosshairs = class Crosshairs {
 | 
			
		||||
    constructor() {
 | 
			
		||||
 | 
			
		||||
        // Set the group containing the crosshairs to three times the desktop
 | 
			
		||||
        // size in case the crosshairs need to appear to be infinite in
 | 
			
		||||
@@ -1597,7 +1596,7 @@ class Crosshairs extends Clutter.Actor {
 | 
			
		||||
        let groupWidth = global.screen_width * 3;
 | 
			
		||||
        let groupHeight = global.screen_height * 3;
 | 
			
		||||
 | 
			
		||||
        super._init({
 | 
			
		||||
        this._actor = new Clutter.Actor({
 | 
			
		||||
            clip_to_allocation: false,
 | 
			
		||||
            width: groupWidth,
 | 
			
		||||
            height: groupHeight
 | 
			
		||||
@@ -1606,10 +1605,10 @@ class Crosshairs extends Clutter.Actor {
 | 
			
		||||
        this._horizRightHair = new Clutter.Actor();
 | 
			
		||||
        this._vertTopHair = new Clutter.Actor();
 | 
			
		||||
        this._vertBottomHair = new Clutter.Actor();
 | 
			
		||||
        this.add_actor(this._horizLeftHair);
 | 
			
		||||
        this.add_actor(this._horizRightHair);
 | 
			
		||||
        this.add_actor(this._vertTopHair);
 | 
			
		||||
        this.add_actor(this._vertBottomHair);
 | 
			
		||||
        this._actor.add_actor(this._horizLeftHair);
 | 
			
		||||
        this._actor.add_actor(this._horizRightHair);
 | 
			
		||||
        this._actor.add_actor(this._vertTopHair);
 | 
			
		||||
        this._actor.add_actor(this._vertBottomHair);
 | 
			
		||||
        this._clipSize = [0, 0];
 | 
			
		||||
        this._clones = [];
 | 
			
		||||
        this.reCenter();
 | 
			
		||||
@@ -1619,7 +1618,7 @@ class Crosshairs extends Clutter.Actor {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _monitorsChanged() {
 | 
			
		||||
        this.set_size(global.screen_width * 3, global.screen_height * 3);
 | 
			
		||||
        this._actor.set_size(global.screen_width * 3, global.screen_height * 3);
 | 
			
		||||
        this.reCenter();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -1640,15 +1639,12 @@ class Crosshairs extends Clutter.Actor {
 | 
			
		||||
        if (zoomRegion && magnifiedMouse) {
 | 
			
		||||
            let container = magnifiedMouse.get_parent();
 | 
			
		||||
            if (container) {
 | 
			
		||||
                crosshairsActor = this;
 | 
			
		||||
                if (this.get_parent() != null) {
 | 
			
		||||
                    crosshairsActor = new Clutter.Clone({ source: this });
 | 
			
		||||
                crosshairsActor = this._actor;
 | 
			
		||||
                if (this._actor.get_parent() != null) {
 | 
			
		||||
                    crosshairsActor = new Clutter.Clone({ source: this._actor });
 | 
			
		||||
                    this._clones.push(crosshairsActor);
 | 
			
		||||
 | 
			
		||||
                    // Clones don't share visibility.
 | 
			
		||||
                    this.bind_property('visible', crosshairsActor, 'visible',
 | 
			
		||||
                                       GObject.BindingFlags.SYNC_CREATE);
 | 
			
		||||
                }
 | 
			
		||||
                crosshairsActor.visible = this._actor.visible;
 | 
			
		||||
 | 
			
		||||
                container.add_actor(crosshairsActor);
 | 
			
		||||
                container.raise_child(magnifiedMouse, crosshairsActor);
 | 
			
		||||
@@ -1667,7 +1663,7 @@ class Crosshairs extends Clutter.Actor {
 | 
			
		||||
     * child actor if it was just a clone of the crosshairs actor.
 | 
			
		||||
     */
 | 
			
		||||
    removeFromParent(childActor) {
 | 
			
		||||
        if (childActor == this)
 | 
			
		||||
        if (childActor == this._actor)
 | 
			
		||||
            childActor.get_parent().remove_actor(childActor);
 | 
			
		||||
        else
 | 
			
		||||
            childActor.destroy();
 | 
			
		||||
@@ -1777,6 +1773,28 @@ class Crosshairs extends Clutter.Actor {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * show:
 | 
			
		||||
     * Show the crosshairs.
 | 
			
		||||
     */
 | 
			
		||||
    show() {
 | 
			
		||||
        this._actor.show();
 | 
			
		||||
        // Clones don't share visibility.
 | 
			
		||||
        for (let i = 0; i < this._clones.length; i++)
 | 
			
		||||
            this._clones[i].show();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * hide:
 | 
			
		||||
     * Hide the crosshairs.
 | 
			
		||||
     */
 | 
			
		||||
    hide() {
 | 
			
		||||
        this._actor.hide();
 | 
			
		||||
        // Clones don't share visibility.
 | 
			
		||||
        for (let i = 0; i < this._clones.length; i++)
 | 
			
		||||
            this._clones[i].hide();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * reCenter:
 | 
			
		||||
     * Reposition the horizontal and vertical hairs such that they cross at
 | 
			
		||||
@@ -1785,7 +1803,7 @@ class Crosshairs extends Clutter.Actor {
 | 
			
		||||
     * @clipSize:  Optional.  If present, an array of the form [width, height].
 | 
			
		||||
     */
 | 
			
		||||
    reCenter(clipSize) {
 | 
			
		||||
        let [groupWidth, groupHeight] = this.get_size();
 | 
			
		||||
        let [groupWidth, groupHeight] = this._actor.get_size();
 | 
			
		||||
        let leftLength = this._horizLeftHair.get_width();
 | 
			
		||||
        let topLength = this._vertTopHair.get_height();
 | 
			
		||||
        let thickness = this._horizLeftHair.get_height();
 | 
			
		||||
@@ -1807,7 +1825,7 @@ class Crosshairs extends Clutter.Actor {
 | 
			
		||||
        this._vertTopHair.set_position((groupWidth - thickness) / 2, top);
 | 
			
		||||
        this._vertBottomHair.set_position((groupWidth - thickness) / 2, bottom);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var MagShaderEffects = class MagShaderEffects {
 | 
			
		||||
    constructor(uiGroupClone) {
 | 
			
		||||
 
 | 
			
		||||
@@ -189,7 +189,7 @@ function _initializeUI() {
 | 
			
		||||
 | 
			
		||||
    messageTray = new MessageTray.MessageTray();
 | 
			
		||||
    panel = new Panel.Panel();
 | 
			
		||||
    keyboard = new Keyboard.KeyboardManager();
 | 
			
		||||
    keyboard = new Keyboard.Keyboard();
 | 
			
		||||
    notificationDaemon = new NotificationDaemon.NotificationDaemon();
 | 
			
		||||
    windowAttentionHandler = new WindowAttentionHandler.WindowAttentionHandler();
 | 
			
		||||
    componentManager = new Components.ComponentManager();
 | 
			
		||||
@@ -262,19 +262,6 @@ function _initializeUI() {
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let credentials = new Gio.Credentials();
 | 
			
		||||
        if (credentials.get_unix_user() === 0) {
 | 
			
		||||
            notify(_('Logged in as a privileged user'),
 | 
			
		||||
                   _('Running a session as a privileged user should be avoided for security reasons. If possible, you should log in as a normal user.'));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (sessionMode.currentMode !== 'gdm' &&
 | 
			
		||||
            sessionMode.currentMode !== 'initial-setup' &&
 | 
			
		||||
            screenShield === null) {
 | 
			
		||||
            notify(_('Screen Lock disabled'),
 | 
			
		||||
                   _('Screen Locking requires the GNOME display manager.'));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        LoginManager.registerSessionWithGDM();
 | 
			
		||||
 | 
			
		||||
        let perfModuleName = GLib.getenv("SHELL_PERF_MODULE");
 | 
			
		||||
@@ -403,7 +390,7 @@ function notify(msg, details) {
 | 
			
		||||
    messageTray.add(source);
 | 
			
		||||
    let notification = new MessageTray.Notification(source, msg, details);
 | 
			
		||||
    notification.setTransient(true);
 | 
			
		||||
    source.showNotification(notification);
 | 
			
		||||
    source.notify(notification);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,7 @@
 | 
			
		||||
/* exported MessageListSection */
 | 
			
		||||
const { Atk, Clutter, Gio, GLib,
 | 
			
		||||
        GObject, Graphene, Meta, Pango, St } = imports.gi;
 | 
			
		||||
const { Atk, Clutter, Gio, GLib, GObject, Meta, Pango, St } = imports.gi;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const MessageTray = imports.ui.messageTray;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
 | 
			
		||||
const Calendar = imports.ui.calendar;
 | 
			
		||||
const Util = imports.misc.util;
 | 
			
		||||
@@ -32,18 +31,13 @@ function _fixMarkup(text, allowMarkup) {
 | 
			
		||||
    return GLib.markup_escape_text(text, -1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var URLHighlighter = GObject.registerClass(
 | 
			
		||||
class URLHighlighter extends St.Label {
 | 
			
		||||
    _init(text = '', lineWrap, allowMarkup) {
 | 
			
		||||
        super._init({
 | 
			
		||||
            reactive: true,
 | 
			
		||||
            style_class: 'url-highlighter',
 | 
			
		||||
            x_expand: true,
 | 
			
		||||
            x_align: Clutter.ActorAlign.START
 | 
			
		||||
        });
 | 
			
		||||
var URLHighlighter = class URLHighlighter {
 | 
			
		||||
    constructor(text = '', lineWrap, allowMarkup) {
 | 
			
		||||
        this.actor = new St.Label({ reactive: true, style_class: 'url-highlighter',
 | 
			
		||||
                                    x_expand: true, x_align: Clutter.ActorAlign.START });
 | 
			
		||||
        this._linkColor = '#ccccff';
 | 
			
		||||
        this.connect('style-changed', () => {
 | 
			
		||||
            let [hasColor, color] = this.get_theme_node().lookup_color('link-color', false);
 | 
			
		||||
        this.actor.connect('style-changed', () => {
 | 
			
		||||
            let [hasColor, color] = this.actor.get_theme_node().lookup_color('link-color', false);
 | 
			
		||||
            if (hasColor) {
 | 
			
		||||
                let linkColor = color.to_string().substr(0, 7);
 | 
			
		||||
                if (linkColor != this._linkColor) {
 | 
			
		||||
@@ -52,75 +46,70 @@ class URLHighlighter extends St.Label {
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
        this.clutter_text.line_wrap = lineWrap;
 | 
			
		||||
        this.clutter_text.line_wrap_mode = Pango.WrapMode.WORD_CHAR;
 | 
			
		||||
        this.actor.clutter_text.line_wrap = lineWrap;
 | 
			
		||||
        this.actor.clutter_text.line_wrap_mode = Pango.WrapMode.WORD_CHAR;
 | 
			
		||||
 | 
			
		||||
        this.setMarkup(text, allowMarkup);
 | 
			
		||||
    }
 | 
			
		||||
        this.actor.connect('button-press-event', (actor, event) => {
 | 
			
		||||
            // Don't try to URL highlight when invisible.
 | 
			
		||||
            // The MessageTray doesn't actually hide us, so
 | 
			
		||||
            // we need to check for paint opacities as well.
 | 
			
		||||
            if (!actor.visible || actor.get_paint_opacity() == 0)
 | 
			
		||||
                return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
 | 
			
		||||
    vfunc_button_press_event(buttonEvent) {
 | 
			
		||||
        // Don't try to URL highlight when invisible.
 | 
			
		||||
        // The MessageTray doesn't actually hide us, so
 | 
			
		||||
        // we need to check for paint opacities as well.
 | 
			
		||||
        if (!this.visible || this.get_paint_opacity() == 0)
 | 
			
		||||
            // Keep Notification.actor from seeing this and taking
 | 
			
		||||
            // a pointer grab, which would block our button-release-event
 | 
			
		||||
            // handler, if an URL is clicked
 | 
			
		||||
            return this._findUrlAtPos(event) != -1;
 | 
			
		||||
        });
 | 
			
		||||
        this.actor.connect('button-release-event', (actor, event) => {
 | 
			
		||||
            if (!actor.visible || actor.get_paint_opacity() == 0)
 | 
			
		||||
                return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
 | 
			
		||||
            let urlId = this._findUrlAtPos(event);
 | 
			
		||||
            if (urlId != -1) {
 | 
			
		||||
                let url = this._urls[urlId].url;
 | 
			
		||||
                if (!url.includes(':'))
 | 
			
		||||
                    url = 'http://' + url;
 | 
			
		||||
 | 
			
		||||
                Gio.app_info_launch_default_for_uri(url, global.create_app_launch_context(0, -1));
 | 
			
		||||
                return Clutter.EVENT_STOP;
 | 
			
		||||
            }
 | 
			
		||||
            return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
        });
 | 
			
		||||
        this.actor.connect('motion-event', (actor, event) => {
 | 
			
		||||
            if (!actor.visible || actor.get_paint_opacity() == 0)
 | 
			
		||||
                return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
 | 
			
		||||
        // Keep Notification from seeing this and taking
 | 
			
		||||
        // a pointer grab, which would block our button-release-event
 | 
			
		||||
        // handler, if an URL is clicked
 | 
			
		||||
        return this._findUrlAtPos(buttonEvent) != -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_button_release_event(buttonEvent) {
 | 
			
		||||
        if (!this.visible || this.get_paint_opacity() == 0)
 | 
			
		||||
            let urlId = this._findUrlAtPos(event);
 | 
			
		||||
            if (urlId != -1 && !this._cursorChanged) {
 | 
			
		||||
                global.display.set_cursor(Meta.Cursor.POINTING_HAND);
 | 
			
		||||
                this._cursorChanged = true;
 | 
			
		||||
            } else if (urlId == -1) {
 | 
			
		||||
                global.display.set_cursor(Meta.Cursor.DEFAULT);
 | 
			
		||||
                this._cursorChanged = false;
 | 
			
		||||
            }
 | 
			
		||||
            return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
        });
 | 
			
		||||
        this.actor.connect('leave-event', () => {
 | 
			
		||||
            if (!this.actor.visible || this.actor.get_paint_opacity() == 0)
 | 
			
		||||
                return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
 | 
			
		||||
        let urlId = this._findUrlAtPos(buttonEvent);
 | 
			
		||||
        if (urlId != -1) {
 | 
			
		||||
            let url = this._urls[urlId].url;
 | 
			
		||||
            if (!url.includes(':'))
 | 
			
		||||
                url = 'http://' + url;
 | 
			
		||||
 | 
			
		||||
            Gio.app_info_launch_default_for_uri(
 | 
			
		||||
                url, global.create_app_launch_context(0, -1));
 | 
			
		||||
            return Clutter.EVENT_STOP;
 | 
			
		||||
        }
 | 
			
		||||
        return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_motion_event(motionEvent) {
 | 
			
		||||
        if (!this.visible || this.get_paint_opacity() == 0)
 | 
			
		||||
            if (this._cursorChanged) {
 | 
			
		||||
                this._cursorChanged = false;
 | 
			
		||||
                global.display.set_cursor(Meta.Cursor.DEFAULT);
 | 
			
		||||
            }
 | 
			
		||||
            return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
 | 
			
		||||
        let urlId = this._findUrlAtPos(motionEvent);
 | 
			
		||||
        if (urlId != -1 && !this._cursorChanged) {
 | 
			
		||||
            global.display.set_cursor(Meta.Cursor.POINTING_HAND);
 | 
			
		||||
            this._cursorChanged = true;
 | 
			
		||||
        } else if (urlId == -1) {
 | 
			
		||||
            global.display.set_cursor(Meta.Cursor.DEFAULT);
 | 
			
		||||
            this._cursorChanged = false;
 | 
			
		||||
        }
 | 
			
		||||
        return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_leave_event(crossingEvent) {
 | 
			
		||||
        if (!this.visible || this.get_paint_opacity() == 0)
 | 
			
		||||
            return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
 | 
			
		||||
        if (this._cursorChanged) {
 | 
			
		||||
            this._cursorChanged = false;
 | 
			
		||||
            global.display.set_cursor(Meta.Cursor.DEFAULT);
 | 
			
		||||
        }
 | 
			
		||||
        return super.vfunc_leave_event(crossingEvent);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    setMarkup(text, allowMarkup) {
 | 
			
		||||
        text = text ? _fixMarkup(text, allowMarkup) : '';
 | 
			
		||||
        this._text = text;
 | 
			
		||||
 | 
			
		||||
        this.clutter_text.set_markup(text);
 | 
			
		||||
        this.actor.clutter_text.set_markup(text);
 | 
			
		||||
        /* clutter_text.text contain text without markup */
 | 
			
		||||
        this._urls = Util.findUrls(this.clutter_text.text);
 | 
			
		||||
        this._urls = Util.findUrls(this.actor.clutter_text.text);
 | 
			
		||||
        this._highlightUrls();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -136,15 +125,16 @@ class URLHighlighter extends St.Label {
 | 
			
		||||
            pos = url.pos + url.url.length;
 | 
			
		||||
        }
 | 
			
		||||
        markup += this._text.substr(pos);
 | 
			
		||||
        this.clutter_text.set_markup(markup);
 | 
			
		||||
        this.actor.clutter_text.set_markup(markup);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _findUrlAtPos(event) {
 | 
			
		||||
        let { x, y } = event;
 | 
			
		||||
        [, x, y] = this.transform_stage_point(x, y);
 | 
			
		||||
        let success_;
 | 
			
		||||
        let [x, y] = event.get_coords();
 | 
			
		||||
        [success_, x, y] = this.actor.transform_stage_point(x, y);
 | 
			
		||||
        let findPos = -1;
 | 
			
		||||
        for (let i = 0; i < this.clutter_text.text.length; i++) {
 | 
			
		||||
            let [, px, py, lineHeight] = this.clutter_text.position_to_coords(i);
 | 
			
		||||
        for (let i = 0; i < this.actor.clutter_text.text.length; i++) {
 | 
			
		||||
            let [success_, px, py, lineHeight] = this.actor.clutter_text.position_to_coords(i);
 | 
			
		||||
            if (py > y || py + lineHeight < y || x < px)
 | 
			
		||||
                continue;
 | 
			
		||||
            findPos = i;
 | 
			
		||||
@@ -157,7 +147,7 @@ class URLHighlighter extends St.Label {
 | 
			
		||||
        }
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var ScaleLayout = GObject.registerClass(
 | 
			
		||||
class ScaleLayout extends Clutter.BinLayout {
 | 
			
		||||
@@ -293,29 +283,21 @@ var LabelExpanderLayout = GObject.registerClass({
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
var Message = GObject.registerClass({
 | 
			
		||||
    GTypeName: 'MessageList_Message',
 | 
			
		||||
    Signals: {
 | 
			
		||||
        'close': {},
 | 
			
		||||
        'expanded': {},
 | 
			
		||||
        'unexpanded': {},
 | 
			
		||||
    }
 | 
			
		||||
}, class Message extends St.Button {
 | 
			
		||||
    _init(title, body) {
 | 
			
		||||
        super._init({
 | 
			
		||||
            style_class: 'message',
 | 
			
		||||
            accessible_role: Atk.Role.NOTIFICATION,
 | 
			
		||||
            can_focus: true,
 | 
			
		||||
            x_expand: true,
 | 
			
		||||
            x_fill: true
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
var Message = class Message {
 | 
			
		||||
    constructor(title, body) {
 | 
			
		||||
        this.expanded = false;
 | 
			
		||||
 | 
			
		||||
        this._useBodyMarkup = false;
 | 
			
		||||
 | 
			
		||||
        this.actor = new St.Button({ style_class: 'message',
 | 
			
		||||
                                     accessible_role: Atk.Role.NOTIFICATION,
 | 
			
		||||
                                     can_focus: true,
 | 
			
		||||
                                     x_expand: true, x_fill: true });
 | 
			
		||||
        this.actor.connect('key-press-event',
 | 
			
		||||
                           this._onKeyPressed.bind(this));
 | 
			
		||||
 | 
			
		||||
        let vbox = new St.BoxLayout({ vertical: true });
 | 
			
		||||
        this.set_child(vbox);
 | 
			
		||||
        this.actor.set_child(vbox);
 | 
			
		||||
 | 
			
		||||
        let hbox = new St.BoxLayout();
 | 
			
		||||
        vbox.add_actor(hbox);
 | 
			
		||||
@@ -359,14 +341,15 @@ var Message = GObject.registerClass({
 | 
			
		||||
        contentBox.add_actor(this._bodyStack);
 | 
			
		||||
 | 
			
		||||
        this.bodyLabel = new URLHighlighter('', false, this._useBodyMarkup);
 | 
			
		||||
        this.bodyLabel.add_style_class_name('message-body');
 | 
			
		||||
        this._bodyStack.add_actor(this.bodyLabel);
 | 
			
		||||
        this.bodyLabel.actor.add_style_class_name('message-body');
 | 
			
		||||
        this._bodyStack.add_actor(this.bodyLabel.actor);
 | 
			
		||||
        this.setBody(body);
 | 
			
		||||
 | 
			
		||||
        this._closeButton.connect('clicked', this.close.bind(this));
 | 
			
		||||
        let actorHoverId = this.connect('notify::hover', this._sync.bind(this));
 | 
			
		||||
        this._closeButton.connect('destroy', this.disconnect.bind(this, actorHoverId));
 | 
			
		||||
        this.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
        let actorHoverId = this.actor.connect('notify::hover', this._sync.bind(this));
 | 
			
		||||
        this._closeButton.connect('destroy', this.actor.disconnect.bind(this.actor, actorHoverId));
 | 
			
		||||
        this.actor.connect('clicked', this._onClicked.bind(this));
 | 
			
		||||
        this.actor.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
        this._sync();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -452,7 +435,7 @@ var Message = GObject.registerClass({
 | 
			
		||||
        if (this._bodyStack.get_n_children() < 2) {
 | 
			
		||||
            this._expandedLabel = new URLHighlighter(this._bodyText,
 | 
			
		||||
                                                     true, this._useBodyMarkup);
 | 
			
		||||
            this.setExpandedBody(this._expandedLabel);
 | 
			
		||||
            this.setExpandedBody(this._expandedLabel.actor);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (animate) {
 | 
			
		||||
@@ -505,16 +488,19 @@ var Message = GObject.registerClass({
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _sync() {
 | 
			
		||||
        let visible = this.hover && this.canClose();
 | 
			
		||||
        let visible = this.actor.hover && this.canClose();
 | 
			
		||||
        this._closeButton.opacity = visible ? 255 : 0;
 | 
			
		||||
        this._closeButton.reactive = visible;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onClicked() {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onDestroy() {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_key_press_event(keyEvent) {
 | 
			
		||||
        let keysym = keyEvent.keyval;
 | 
			
		||||
    _onKeyPressed(a, event) {
 | 
			
		||||
        let keysym = event.get_key_symbol();
 | 
			
		||||
 | 
			
		||||
        if (keysym == Clutter.KEY_Delete ||
 | 
			
		||||
            keysym == Clutter.KEY_KP_Delete) {
 | 
			
		||||
@@ -523,66 +509,37 @@ var Message = GObject.registerClass({
 | 
			
		||||
        }
 | 
			
		||||
        return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(Message.prototype);
 | 
			
		||||
 | 
			
		||||
var MessageListSection = GObject.registerClass({
 | 
			
		||||
    Properties: {
 | 
			
		||||
        'can-clear': GObject.ParamSpec.boolean(
 | 
			
		||||
            'can-clear', 'can-clear', 'can-clear',
 | 
			
		||||
            GObject.ParamFlags.READABLE,
 | 
			
		||||
            false),
 | 
			
		||||
        'empty': GObject.ParamSpec.boolean(
 | 
			
		||||
            'empty', 'empty', 'empty',
 | 
			
		||||
            GObject.ParamFlags.READABLE,
 | 
			
		||||
            true),
 | 
			
		||||
    },
 | 
			
		||||
    Signals: {
 | 
			
		||||
        'can-clear-changed': {},
 | 
			
		||||
        'empty-changed': {},
 | 
			
		||||
        'message-focused': { param_types: [Message.$gtype] },
 | 
			
		||||
    }
 | 
			
		||||
}, class MessageListSection extends St.BoxLayout {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init({
 | 
			
		||||
            style_class: 'message-list-section',
 | 
			
		||||
            clip_to_allocation: true,
 | 
			
		||||
            vertical: true,
 | 
			
		||||
            x_expand: true
 | 
			
		||||
        });
 | 
			
		||||
var MessageListSection = class MessageListSection {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        this.actor = new St.BoxLayout({ style_class: 'message-list-section',
 | 
			
		||||
                                        clip_to_allocation: true,
 | 
			
		||||
                                        x_expand: true, vertical: true });
 | 
			
		||||
 | 
			
		||||
        this._list = new St.BoxLayout({ style_class: 'message-list-section-list',
 | 
			
		||||
                                        vertical: true });
 | 
			
		||||
        this.add_actor(this._list);
 | 
			
		||||
        this.actor.add_actor(this._list);
 | 
			
		||||
 | 
			
		||||
        this._list.connect('actor-added', this._sync.bind(this));
 | 
			
		||||
        this._list.connect('actor-removed', this._sync.bind(this));
 | 
			
		||||
 | 
			
		||||
        let id = Main.sessionMode.connect('updated',
 | 
			
		||||
                                          this._sync.bind(this));
 | 
			
		||||
        this.connect('destroy', () => {
 | 
			
		||||
        this.actor.connect('destroy', () => {
 | 
			
		||||
            Main.sessionMode.disconnect(id);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this._messages = new Map();
 | 
			
		||||
        this._date = new Date();
 | 
			
		||||
        this._empty = true;
 | 
			
		||||
        this._canClear = false;
 | 
			
		||||
        this.empty = true;
 | 
			
		||||
        this.canClear = false;
 | 
			
		||||
        this._sync();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get empty() {
 | 
			
		||||
        return this._empty;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get canClear() {
 | 
			
		||||
        return this._canClear;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get _messages() {
 | 
			
		||||
        return this._list.get_children().map(i => i.child);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onKeyFocusIn(messageActor) {
 | 
			
		||||
        this.emit('message-focused', messageActor);
 | 
			
		||||
    _onKeyFocusIn(actor) {
 | 
			
		||||
        this.emit('key-focus-in', actor);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get allowed() {
 | 
			
		||||
@@ -601,62 +558,58 @@ var MessageListSection = GObject.registerClass({
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    addMessageAtIndex(message, index, animate) {
 | 
			
		||||
        if (this._messages.includes(message))
 | 
			
		||||
            throw new Error('Message was already added previously');
 | 
			
		||||
 | 
			
		||||
        let listItem = new St.Bin({
 | 
			
		||||
            child: message,
 | 
			
		||||
            x_fill: true,
 | 
			
		||||
            y_fill: true,
 | 
			
		||||
            layout_manager: new ScaleLayout(),
 | 
			
		||||
            pivot_point: new Graphene.Point({ x: .5, y: .5 }),
 | 
			
		||||
        let obj = {
 | 
			
		||||
            container: null,
 | 
			
		||||
            destroyId: 0,
 | 
			
		||||
            keyFocusId: 0,
 | 
			
		||||
            closeId: 0
 | 
			
		||||
        };
 | 
			
		||||
        let pivot = new Clutter.Point({ x: .5, y: .5 });
 | 
			
		||||
        let scale = animate ? 0 : 1;
 | 
			
		||||
        obj.container = new St.Widget({ layout_manager: new ScaleLayout(),
 | 
			
		||||
                                        pivot_point: pivot,
 | 
			
		||||
                                        scale_x: scale, scale_y: scale });
 | 
			
		||||
        obj.keyFocusId = message.actor.connect('key-focus-in',
 | 
			
		||||
            this._onKeyFocusIn.bind(this));
 | 
			
		||||
        obj.destroyId = message.actor.connect('destroy', () => {
 | 
			
		||||
            this.removeMessage(message, false);
 | 
			
		||||
        });
 | 
			
		||||
        listItem._connectionsIds = [];
 | 
			
		||||
 | 
			
		||||
        listItem._connectionsIds.push(message.connect('key-focus-in',
 | 
			
		||||
            this._onKeyFocusIn.bind(this)));
 | 
			
		||||
        listItem._connectionsIds.push(message.connect('close', () => {
 | 
			
		||||
        obj.closeId = message.connect('close', () => {
 | 
			
		||||
            this.removeMessage(message, true);
 | 
			
		||||
        }));
 | 
			
		||||
        listItem._connectionsIds.push(message.connect('destroy', () => {
 | 
			
		||||
            listItem._connectionsIds.forEach(id => message.disconnect(id));
 | 
			
		||||
            listItem.destroy();
 | 
			
		||||
        }));
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this._list.insert_child_at_index(listItem, index);
 | 
			
		||||
        this._messages.set(message, obj);
 | 
			
		||||
        obj.container.add_actor(message.actor);
 | 
			
		||||
 | 
			
		||||
        if (animate) {
 | 
			
		||||
            listItem.set({ scale_x: 0, scale_y: 0 });
 | 
			
		||||
            listItem.ease({
 | 
			
		||||
        this._list.insert_child_at_index(obj.container, index);
 | 
			
		||||
 | 
			
		||||
        if (animate)
 | 
			
		||||
            obj.container.ease({
 | 
			
		||||
                scale_x: 1,
 | 
			
		||||
                scale_y: 1,
 | 
			
		||||
                duration: MESSAGE_ANIMATION_TIME,
 | 
			
		||||
                mode: Clutter.AnimationMode.EASE_OUT_QUAD
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    moveMessage(message, index, animate) {
 | 
			
		||||
        if (!this._messages.includes(message))
 | 
			
		||||
            throw new Error(`Impossible to move the untracked message ${message}`);
 | 
			
		||||
 | 
			
		||||
        let listItem = message.get_parent();
 | 
			
		||||
        let obj = this._messages.get(message);
 | 
			
		||||
 | 
			
		||||
        if (!animate) {
 | 
			
		||||
            this._list.set_child_at_index(listItem, index);
 | 
			
		||||
            this._list.set_child_at_index(obj.container, index);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let onComplete = () => {
 | 
			
		||||
            this._list.set_child_at_index(listItem, index);
 | 
			
		||||
            listItem.ease({
 | 
			
		||||
            this._list.set_child_at_index(obj.container, index);
 | 
			
		||||
            obj.container.ease({
 | 
			
		||||
                scale_x: 1,
 | 
			
		||||
                scale_y: 1,
 | 
			
		||||
                duration: MESSAGE_ANIMATION_TIME,
 | 
			
		||||
                mode: Clutter.AnimationMode.EASE_OUT_QUAD
 | 
			
		||||
            });
 | 
			
		||||
        };
 | 
			
		||||
        listItem.ease({
 | 
			
		||||
        obj.container.ease({
 | 
			
		||||
            scale_x: 0,
 | 
			
		||||
            scale_y: 0,
 | 
			
		||||
            duration: MESSAGE_ANIMATION_TIME,
 | 
			
		||||
@@ -666,31 +619,33 @@ var MessageListSection = GObject.registerClass({
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    removeMessage(message, animate) {
 | 
			
		||||
        if (!this._messages.includes(message))
 | 
			
		||||
            throw new Error(`Impossible to remove the untracked message ${message}`);
 | 
			
		||||
        let obj = this._messages.get(message);
 | 
			
		||||
 | 
			
		||||
        let listItem = message.get_parent();
 | 
			
		||||
        listItem._connectionsIds.forEach(id => message.disconnect(id));
 | 
			
		||||
        message.actor.disconnect(obj.destroyId);
 | 
			
		||||
        message.actor.disconnect(obj.keyFocusId);
 | 
			
		||||
        message.disconnect(obj.closeId);
 | 
			
		||||
 | 
			
		||||
        this._messages.delete(message);
 | 
			
		||||
 | 
			
		||||
        if (animate) {
 | 
			
		||||
            listItem.ease({
 | 
			
		||||
            obj.container.ease({
 | 
			
		||||
                scale_x: 0,
 | 
			
		||||
                scale_y: 0,
 | 
			
		||||
                duration: MESSAGE_ANIMATION_TIME,
 | 
			
		||||
                mode: Clutter.AnimationMode.EASE_OUT_QUAD,
 | 
			
		||||
                onComplete: () => {
 | 
			
		||||
                    listItem.destroy();
 | 
			
		||||
                    obj.container.destroy();
 | 
			
		||||
                    global.sync_pointer();
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
        } else {
 | 
			
		||||
            listItem.destroy();
 | 
			
		||||
            obj.container.destroy();
 | 
			
		||||
            global.sync_pointer();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    clear() {
 | 
			
		||||
        let messages = this._messages.filter(msg => msg.canClose());
 | 
			
		||||
        let messages = [...this._messages.keys()].filter(msg => msg.canClose());
 | 
			
		||||
 | 
			
		||||
        // If there are few messages, letting them all zoom out looks OK
 | 
			
		||||
        if (messages.length < 2) {
 | 
			
		||||
@@ -703,8 +658,9 @@ var MessageListSection = GObject.registerClass({
 | 
			
		||||
            let delay = MESSAGE_ANIMATION_TIME / Math.max(messages.length, 5);
 | 
			
		||||
            for (let i = 0; i < messages.length; i++) {
 | 
			
		||||
                let message = messages[i];
 | 
			
		||||
                message.get_parent().ease({
 | 
			
		||||
                    translation_x: this._list.width,
 | 
			
		||||
                let obj = this._messages.get(message);
 | 
			
		||||
                obj.container.ease({
 | 
			
		||||
                    anchor_x: this._list.width,
 | 
			
		||||
                    opacity: 0,
 | 
			
		||||
                    duration: MESSAGE_ANIMATION_TIME,
 | 
			
		||||
                    delay: i * delay,
 | 
			
		||||
@@ -715,25 +671,33 @@ var MessageListSection = GObject.registerClass({
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _canClear() {
 | 
			
		||||
        for (let message of this._messages.keys())
 | 
			
		||||
            if (message.canClose())
 | 
			
		||||
                return true;
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _shouldShow() {
 | 
			
		||||
        return !this.empty;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _sync() {
 | 
			
		||||
        let messages = this._messages;
 | 
			
		||||
        let empty = messages.length == 0;
 | 
			
		||||
        let empty = this._list.get_n_children() == 0;
 | 
			
		||||
        let changed = this.empty !== empty;
 | 
			
		||||
        this.empty = empty;
 | 
			
		||||
 | 
			
		||||
        if (this._empty != empty) {
 | 
			
		||||
            this._empty = empty;
 | 
			
		||||
            this.notify('empty');
 | 
			
		||||
        }
 | 
			
		||||
        if (changed)
 | 
			
		||||
            this.emit('empty-changed');
 | 
			
		||||
 | 
			
		||||
        let canClear = messages.some(m => m.canClose());
 | 
			
		||||
        if (this._canClear != canClear) {
 | 
			
		||||
            this._canClear = canClear;
 | 
			
		||||
            this.notify('can-clear');
 | 
			
		||||
        }
 | 
			
		||||
        let canClear = this._canClear();
 | 
			
		||||
        changed = this.canClear !== canClear;
 | 
			
		||||
        this.canClear = canClear;
 | 
			
		||||
 | 
			
		||||
        this.visible = this.allowed && this._shouldShow();
 | 
			
		||||
        if (changed)
 | 
			
		||||
            this.emit('can-clear-changed');
 | 
			
		||||
 | 
			
		||||
        this.actor.visible = this.allowed && this._shouldShow();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(MessageListSection.prototype);
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,7 @@
 | 
			
		||||
   SystemNotificationSource, MessageTray */
 | 
			
		||||
 | 
			
		||||
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
 | 
			
		||||
const Calendar = imports.ui.calendar;
 | 
			
		||||
const GnomeSession = imports.misc.gnomeSession;
 | 
			
		||||
@@ -133,84 +134,72 @@ var FocusGrabber = class FocusGrabber {
 | 
			
		||||
// source, such as whether to play sound or honour the critical bit.
 | 
			
		||||
//
 | 
			
		||||
// A notification without a policy object will inherit the default one.
 | 
			
		||||
var NotificationPolicy = GObject.registerClass({
 | 
			
		||||
    GTypeName: 'MessageTray_NotificationPolicy',
 | 
			
		||||
    Properties: {
 | 
			
		||||
        'enable': GObject.ParamSpec.boolean(
 | 
			
		||||
            'enable', 'enable', 'enable',
 | 
			
		||||
            GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
 | 
			
		||||
            true),
 | 
			
		||||
        'enable-sound': GObject.ParamSpec.boolean(
 | 
			
		||||
            'enable-sound', 'enable-sound', 'enable-sound',
 | 
			
		||||
            GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
 | 
			
		||||
            true),
 | 
			
		||||
        'show-banners': GObject.ParamSpec.boolean(
 | 
			
		||||
            'show-banners', 'show-banners', 'show-banners',
 | 
			
		||||
            GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
 | 
			
		||||
            true),
 | 
			
		||||
        'force-expanded': GObject.ParamSpec.boolean(
 | 
			
		||||
            'force-expanded', 'force-expanded', 'force-expanded',
 | 
			
		||||
            GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
 | 
			
		||||
            false),
 | 
			
		||||
        'show-in-lock-screen': GObject.ParamSpec.boolean(
 | 
			
		||||
            'show-in-lock-screen', 'show-in-lock-screen', 'show-in-lock-screen',
 | 
			
		||||
            GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
 | 
			
		||||
            false),
 | 
			
		||||
        'details-in-lock-screen': GObject.ParamSpec.boolean(
 | 
			
		||||
            'details-in-lock-screen', 'details-in-lock-screen', 'details-in-lock-screen',
 | 
			
		||||
            GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
 | 
			
		||||
            false),
 | 
			
		||||
var NotificationPolicy = class NotificationPolicy {
 | 
			
		||||
    constructor(params) {
 | 
			
		||||
        params = Params.parse(params, {
 | 
			
		||||
            enable: true,
 | 
			
		||||
            enableSound: true,
 | 
			
		||||
            showBanners: true,
 | 
			
		||||
            forceExpanded: false,
 | 
			
		||||
            showInLockScreen: true,
 | 
			
		||||
            detailsInLockScreen: false,
 | 
			
		||||
        });
 | 
			
		||||
        Object.getOwnPropertyNames(params).forEach(key => {
 | 
			
		||||
            let desc = Object.getOwnPropertyDescriptor(params, key);
 | 
			
		||||
            Object.defineProperty(this, `_${key}`, desc);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
}, class NotificationPolicy extends GObject.Object {
 | 
			
		||||
 | 
			
		||||
    // Do nothing for the default policy. These methods are only useful for the
 | 
			
		||||
    // GSettings policy.
 | 
			
		||||
    store() { }
 | 
			
		||||
 | 
			
		||||
    destroy() {
 | 
			
		||||
        this.run_dispose();
 | 
			
		||||
    destroy() { }
 | 
			
		||||
 | 
			
		||||
    get enable() {
 | 
			
		||||
        return this._enable;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get enableSound() {
 | 
			
		||||
        return this.enable_sound;
 | 
			
		||||
        return this._enableSound;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get showBanners() {
 | 
			
		||||
        return this.show_banners;
 | 
			
		||||
        return this._showBanners;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get forceExpanded() {
 | 
			
		||||
        return this.force_expanded;
 | 
			
		||||
        return this._forceExpanded;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get showInLockScreen() {
 | 
			
		||||
        return this.show_in_lock_screen;
 | 
			
		||||
        return this._showInLockScreen;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get detailsInLockScreen() {
 | 
			
		||||
        return this.details_in_lock_screen;
 | 
			
		||||
        return this._detailsInLockScreen;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(NotificationPolicy.prototype);
 | 
			
		||||
 | 
			
		||||
var NotificationGenericPolicy = GObject.registerClass({
 | 
			
		||||
    GTypeName: 'MessageTray_NotificationGenericPolicy'
 | 
			
		||||
}, class NotificationGenericPolicy extends NotificationPolicy {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init();
 | 
			
		||||
var NotificationGenericPolicy =
 | 
			
		||||
class NotificationGenericPolicy extends NotificationPolicy {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        super();
 | 
			
		||||
        this.id = 'generic';
 | 
			
		||||
 | 
			
		||||
        this._masterSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.notifications' });
 | 
			
		||||
        this._masterSettings.connect('changed', this._changed.bind(this));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    store() { }
 | 
			
		||||
 | 
			
		||||
    destroy() {
 | 
			
		||||
        this._masterSettings.run_dispose();
 | 
			
		||||
 | 
			
		||||
        super.destroy();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _changed(settings, key) {
 | 
			
		||||
        if (this.constructor.find_property(key))
 | 
			
		||||
            this.notify(key);
 | 
			
		||||
        this.emit('policy-changed', key);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get showBanners() {
 | 
			
		||||
@@ -220,13 +209,12 @@ var NotificationGenericPolicy = GObject.registerClass({
 | 
			
		||||
    get showInLockScreen() {
 | 
			
		||||
        return this._masterSettings.get_boolean('show-in-lock-screen');
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var NotificationApplicationPolicy = GObject.registerClass({
 | 
			
		||||
    GTypeName: 'MessageTray_NotificationApplicationPolicy'
 | 
			
		||||
}, class NotificationApplicationPolicy extends NotificationPolicy {
 | 
			
		||||
    _init(id) {
 | 
			
		||||
        super._init();
 | 
			
		||||
var NotificationApplicationPolicy =
 | 
			
		||||
class NotificationApplicationPolicy extends NotificationPolicy {
 | 
			
		||||
    constructor(id) {
 | 
			
		||||
        super();
 | 
			
		||||
 | 
			
		||||
        this.id = id;
 | 
			
		||||
        this._canonicalId = this._canonicalizeId(id);
 | 
			
		||||
@@ -252,13 +240,12 @@ var NotificationApplicationPolicy = GObject.registerClass({
 | 
			
		||||
    destroy() {
 | 
			
		||||
        this._masterSettings.run_dispose();
 | 
			
		||||
        this._settings.run_dispose();
 | 
			
		||||
 | 
			
		||||
        super.destroy();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _changed(settings, key) {
 | 
			
		||||
        if (this.constructor.find_property(key))
 | 
			
		||||
            this.notify(key);
 | 
			
		||||
        this.emit('policy-changed', key);
 | 
			
		||||
        if (key == 'enable')
 | 
			
		||||
            this.emit('enable-changed');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _canonicalizeId(id) {
 | 
			
		||||
@@ -292,7 +279,7 @@ var NotificationApplicationPolicy = GObject.registerClass({
 | 
			
		||||
    get detailsInLockScreen() {
 | 
			
		||||
        return this._settings.get_boolean('details-in-lock-screen');
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Notification:
 | 
			
		||||
// @source: the notification's Source
 | 
			
		||||
@@ -349,26 +336,12 @@ var NotificationApplicationPolicy = GObject.registerClass({
 | 
			
		||||
// @source allows playing sounds).
 | 
			
		||||
//
 | 
			
		||||
// [1] https://developer.gnome.org/notification-spec/#markup
 | 
			
		||||
var Notification = GObject.registerClass({
 | 
			
		||||
    GTypeName: 'MessageTray_Notification',
 | 
			
		||||
    Properties: {
 | 
			
		||||
        'acknowledged': GObject.ParamSpec.boolean(
 | 
			
		||||
            'acknowledged', 'acknowledged', 'acknowledged',
 | 
			
		||||
            GObject.ParamFlags.READWRITE,
 | 
			
		||||
            false),
 | 
			
		||||
    },
 | 
			
		||||
    Signals: {
 | 
			
		||||
        'activated': {},
 | 
			
		||||
        'destroy': { param_types: [GObject.TYPE_UINT] },
 | 
			
		||||
        'updated': { param_types: [GObject.TYPE_BOOLEAN] },
 | 
			
		||||
    }
 | 
			
		||||
}, class Notification extends GObject.Object {
 | 
			
		||||
    _init(source, title, banner, params) {
 | 
			
		||||
        super._init();
 | 
			
		||||
 | 
			
		||||
var Notification = class Notification {
 | 
			
		||||
    constructor(source, title, banner, params) {
 | 
			
		||||
        this.source = source;
 | 
			
		||||
        this.title = title;
 | 
			
		||||
        this.urgency = Urgency.NORMAL;
 | 
			
		||||
        this.resident = false;
 | 
			
		||||
        // 'transient' is a reserved keyword in JS, so we have to use an alternate variable name
 | 
			
		||||
        this.isTransient = false;
 | 
			
		||||
        this.privacyScope = PrivacyScope.USER;
 | 
			
		||||
@@ -380,7 +353,6 @@ var Notification = GObject.registerClass({
 | 
			
		||||
        this._soundFile = null;
 | 
			
		||||
        this._soundPlayed = false;
 | 
			
		||||
        this.actions = [];
 | 
			
		||||
        this.setResident(false);
 | 
			
		||||
 | 
			
		||||
        // If called with only one argument we assume the caller
 | 
			
		||||
        // will call .update() later on. This is the case of
 | 
			
		||||
@@ -450,7 +422,7 @@ var Notification = GObject.registerClass({
 | 
			
		||||
        if (this._acknowledged == v)
 | 
			
		||||
            return;
 | 
			
		||||
        this._acknowledged = v;
 | 
			
		||||
        this.notify('acknowledged');
 | 
			
		||||
        this.emit('acknowledged-changed');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    setUrgency(urgency) {
 | 
			
		||||
@@ -459,15 +431,6 @@ var Notification = GObject.registerClass({
 | 
			
		||||
 | 
			
		||||
    setResident(resident) {
 | 
			
		||||
        this.resident = resident;
 | 
			
		||||
 | 
			
		||||
        if (this.resident) {
 | 
			
		||||
            if (this._activatedId) {
 | 
			
		||||
                this.disconnect(this._activatedId);
 | 
			
		||||
                this._activatedId = 0;
 | 
			
		||||
            }
 | 
			
		||||
        } else if (!this._activatedId) {
 | 
			
		||||
            this._activatedId = this.connect_after('activated', () => this.destroy());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    setTransient(isTransient) {
 | 
			
		||||
@@ -509,30 +472,23 @@ var Notification = GObject.registerClass({
 | 
			
		||||
 | 
			
		||||
    activate() {
 | 
			
		||||
        this.emit('activated');
 | 
			
		||||
        if (!this.resident)
 | 
			
		||||
            this.destroy();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    destroy(reason = NotificationDestroyedReason.DISMISSED) {
 | 
			
		||||
        if (this._activatedId) {
 | 
			
		||||
            this.disconnect(this._activatedId);
 | 
			
		||||
            delete this._activatedId;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.emit('destroy', reason);
 | 
			
		||||
        this.run_dispose();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(Notification.prototype);
 | 
			
		||||
 | 
			
		||||
var NotificationBanner = GObject.registerClass({
 | 
			
		||||
    Signals: {
 | 
			
		||||
        'done-displaying': {},
 | 
			
		||||
        'unfocused': {},
 | 
			
		||||
    }
 | 
			
		||||
}, class NotificationBanner extends Calendar.NotificationMessage {
 | 
			
		||||
    _init(notification) {
 | 
			
		||||
        super._init(notification);
 | 
			
		||||
var NotificationBanner =
 | 
			
		||||
class NotificationBanner extends Calendar.NotificationMessage {
 | 
			
		||||
    constructor(notification) {
 | 
			
		||||
        super(notification);
 | 
			
		||||
 | 
			
		||||
        this.can_focus = false;
 | 
			
		||||
        this.add_style_class_name('notification-banner');
 | 
			
		||||
        this.actor.can_focus = false;
 | 
			
		||||
        this.actor.add_style_class_name('notification-banner');
 | 
			
		||||
 | 
			
		||||
        this._buttonBox = null;
 | 
			
		||||
 | 
			
		||||
@@ -619,7 +575,7 @@ var NotificationBanner = GObject.registerClass({
 | 
			
		||||
 | 
			
		||||
        return this.addButton(button, callback);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var SourceActor = GObject.registerClass(
 | 
			
		||||
class SourceActor extends St.Widget {
 | 
			
		||||
@@ -684,7 +640,7 @@ class SourceActorWithLabel extends SourceActor {
 | 
			
		||||
 | 
			
		||||
        this.add_actor(this._counterBin);
 | 
			
		||||
 | 
			
		||||
        this._countUpdatedId = this._source.connect('notify::count', this._updateCount.bind(this));
 | 
			
		||||
        this._countUpdatedId = this._source.connect('count-updated', this._updateCount.bind(this));
 | 
			
		||||
        this._updateCount();
 | 
			
		||||
 | 
			
		||||
        this.connect('destroy', () => {
 | 
			
		||||
@@ -732,34 +688,11 @@ class SourceActorWithLabel extends SourceActor {
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
var Source = GObject.registerClass({
 | 
			
		||||
    GTypeName: 'MessageTray_Source',
 | 
			
		||||
    Properties: {
 | 
			
		||||
        'count': GObject.ParamSpec.int(
 | 
			
		||||
            'count', 'count', 'count',
 | 
			
		||||
            GObject.ParamFlags.READABLE,
 | 
			
		||||
            0, GLib.MAXINT32, 0),
 | 
			
		||||
        'policy': GObject.ParamSpec.object(
 | 
			
		||||
            'policy', 'policy', 'policy',
 | 
			
		||||
            GObject.ParamFlags.READWRITE,
 | 
			
		||||
            NotificationPolicy.$gtype),
 | 
			
		||||
        'title': GObject.ParamSpec.string(
 | 
			
		||||
            'title', 'title', 'title',
 | 
			
		||||
            GObject.ParamFlags.READWRITE,
 | 
			
		||||
            null),
 | 
			
		||||
    },
 | 
			
		||||
    Signals: {
 | 
			
		||||
        'destroy': { param_types: [GObject.TYPE_UINT] },
 | 
			
		||||
        'icon-updated': {},
 | 
			
		||||
        'notification-added': { param_types: [Notification.$gtype] },
 | 
			
		||||
        'notification-show': { param_types: [Notification.$gtype] },
 | 
			
		||||
    }
 | 
			
		||||
}, class Source extends GObject.Object {
 | 
			
		||||
    _init(title, iconName) {
 | 
			
		||||
        super._init({ title: title });
 | 
			
		||||
 | 
			
		||||
var Source = class Source {
 | 
			
		||||
    constructor(title, iconName) {
 | 
			
		||||
        this.SOURCE_ICON_SIZE = 48;
 | 
			
		||||
 | 
			
		||||
        this.title = title;
 | 
			
		||||
        this.iconName = iconName;
 | 
			
		||||
 | 
			
		||||
        this.isChat = false;
 | 
			
		||||
@@ -794,7 +727,7 @@ var Source = GObject.registerClass({
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    countUpdated() {
 | 
			
		||||
        super.notify('count');
 | 
			
		||||
        this.emit('count-updated');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _createPolicy() {
 | 
			
		||||
@@ -808,11 +741,8 @@ var Source = GObject.registerClass({
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    setTitle(newTitle) {
 | 
			
		||||
        if (this.title == newTitle)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this.title = newTitle;
 | 
			
		||||
        this.notify('title');
 | 
			
		||||
        this.emit('title-changed');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    createBanner(notification) {
 | 
			
		||||
@@ -837,10 +767,10 @@ var Source = GObject.registerClass({
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this.notifications.splice(index, 1);
 | 
			
		||||
        this.countUpdated();
 | 
			
		||||
 | 
			
		||||
        if (this.notifications.length == 0)
 | 
			
		||||
            this.destroy();
 | 
			
		||||
 | 
			
		||||
        this.countUpdated();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pushNotification(notification) {
 | 
			
		||||
@@ -851,39 +781,24 @@ var Source = GObject.registerClass({
 | 
			
		||||
            this.notifications.shift().destroy(NotificationDestroyedReason.EXPIRED);
 | 
			
		||||
 | 
			
		||||
        notification.connect('destroy', this._onNotificationDestroy.bind(this));
 | 
			
		||||
        notification.connect('notify::acknowledged', this.countUpdated.bind(this));
 | 
			
		||||
        notification.connect('acknowledged-changed', this.countUpdated.bind(this));
 | 
			
		||||
        this.notifications.push(notification);
 | 
			
		||||
        this.emit('notification-added', notification);
 | 
			
		||||
 | 
			
		||||
        this.countUpdated();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    showNotification(notification) {
 | 
			
		||||
    notify(notification) {
 | 
			
		||||
        notification.acknowledged = false;
 | 
			
		||||
        this.pushNotification(notification);
 | 
			
		||||
 | 
			
		||||
        if (this.policy.showBanners || notification.urgency == Urgency.CRITICAL) {
 | 
			
		||||
            this.emit('notification-show', notification);
 | 
			
		||||
            this.emit('notify', notification);
 | 
			
		||||
        } else {
 | 
			
		||||
            notification.playSound();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    notify(propName) {
 | 
			
		||||
        if (propName instanceof Notification) {
 | 
			
		||||
            try {
 | 
			
		||||
                throw new Error('Source.notify() has been moved to Source.showNotification()' +
 | 
			
		||||
                                'this code will break in the future');
 | 
			
		||||
            } catch (e) {
 | 
			
		||||
                logError(e);
 | 
			
		||||
                this.showNotification(propName);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        super.notify(propName);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    destroy(reason) {
 | 
			
		||||
        this.policy.destroy();
 | 
			
		||||
 | 
			
		||||
@@ -894,8 +809,6 @@ var Source = GObject.registerClass({
 | 
			
		||||
            notifications[i].destroy(reason);
 | 
			
		||||
 | 
			
		||||
        this.emit('destroy', reason);
 | 
			
		||||
 | 
			
		||||
        this.run_dispose();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    iconUpdated() {
 | 
			
		||||
@@ -910,23 +823,14 @@ var Source = GObject.registerClass({
 | 
			
		||||
        for (let i = this.notifications.length - 1; i >= 0; i--)
 | 
			
		||||
            if (!this.notifications[i].resident)
 | 
			
		||||
                this.notifications[i].destroy();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
var MessageTray = GObject.registerClass({
 | 
			
		||||
    Signals: {
 | 
			
		||||
        'queue-changed': {},
 | 
			
		||||
        'source-added': { param_types: [Source.$gtype] },
 | 
			
		||||
        'source-removed': { param_types: [Source.$gtype] },
 | 
			
		||||
        this.countUpdated();
 | 
			
		||||
    }
 | 
			
		||||
}, class MessageTray extends St.Widget {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init({
 | 
			
		||||
            visible: false,
 | 
			
		||||
            clip_to_allocation: true,
 | 
			
		||||
            layout_manager: new Clutter.BinLayout()
 | 
			
		||||
        });
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(Source.prototype);
 | 
			
		||||
 | 
			
		||||
var MessageTray = class MessageTray {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        this._presence = new GnomeSession.Presence((proxy, _error) => {
 | 
			
		||||
            this._onStatusChanged(proxy.status);
 | 
			
		||||
        });
 | 
			
		||||
@@ -943,15 +847,18 @@ var MessageTray = GObject.registerClass({
 | 
			
		||||
            // so fix up Clutter's view of the pointer position in
 | 
			
		||||
            // that case.
 | 
			
		||||
            let related = ev.get_related();
 | 
			
		||||
            if (!related || this.contains(related))
 | 
			
		||||
            if (!related || this.actor.contains(related))
 | 
			
		||||
                global.sync_pointer();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this.actor = new St.Widget({ visible: false,
 | 
			
		||||
                                     clip_to_allocation: true,
 | 
			
		||||
                                     layout_manager: new Clutter.BinLayout() });
 | 
			
		||||
        let constraint = new Layout.MonitorConstraint({ primary: true });
 | 
			
		||||
        Main.layoutManager.panelBox.bind_property('visible',
 | 
			
		||||
                                                  constraint, 'work-area',
 | 
			
		||||
                                                  GObject.BindingFlags.SYNC_CREATE);
 | 
			
		||||
        this.add_constraint(constraint);
 | 
			
		||||
        this.actor.add_constraint(constraint);
 | 
			
		||||
 | 
			
		||||
        this._bannerBin = new St.Widget({ name: 'notification-container',
 | 
			
		||||
                                          reactive: true,
 | 
			
		||||
@@ -965,7 +872,7 @@ var MessageTray = GObject.registerClass({
 | 
			
		||||
                                this._onNotificationKeyRelease.bind(this));
 | 
			
		||||
        this._bannerBin.connect('notify::hover',
 | 
			
		||||
                                this._onNotificationHoverChanged.bind(this));
 | 
			
		||||
        this.add_actor(this._bannerBin);
 | 
			
		||||
        this.actor.add_actor(this._bannerBin);
 | 
			
		||||
 | 
			
		||||
        this._notificationFocusGrabber = new FocusGrabber(this._bannerBin);
 | 
			
		||||
        this._notificationQueue = [];
 | 
			
		||||
@@ -994,7 +901,7 @@ var MessageTray = GObject.registerClass({
 | 
			
		||||
        this._notificationTimeoutId = 0;
 | 
			
		||||
        this._notificationRemoved = false;
 | 
			
		||||
 | 
			
		||||
        Main.layoutManager.addChrome(this, { affectsInputRegion: false });
 | 
			
		||||
        Main.layoutManager.addChrome(this.actor, { affectsInputRegion: false });
 | 
			
		||||
        Main.layoutManager.trackChrome(this._bannerBin, { affectsInputRegion: true });
 | 
			
		||||
 | 
			
		||||
        global.display.connect('in-fullscreen-changed', this._updateState.bind(this));
 | 
			
		||||
@@ -1037,11 +944,11 @@ var MessageTray = GObject.registerClass({
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onDragBegin() {
 | 
			
		||||
        Shell.util_set_hidden_from_pick(this, true);
 | 
			
		||||
        Shell.util_set_hidden_from_pick(this.actor, true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onDragEnd() {
 | 
			
		||||
        Shell.util_set_hidden_from_pick(this, false);
 | 
			
		||||
        Shell.util_set_hidden_from_pick(this.actor, false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get bannerAlignment() {
 | 
			
		||||
@@ -1090,22 +997,22 @@ var MessageTray = GObject.registerClass({
 | 
			
		||||
        // Register that we got a notification for this source
 | 
			
		||||
        source.policy.store();
 | 
			
		||||
 | 
			
		||||
        source.policy.connect('notify::enable', () => {
 | 
			
		||||
        source.policy.connect('enable-changed', () => {
 | 
			
		||||
            this._onSourceEnableChanged(source.policy, source);
 | 
			
		||||
        });
 | 
			
		||||
        source.policy.connect('notify', this._updateState.bind(this));
 | 
			
		||||
        source.policy.connect('policy-changed', this._updateState.bind(this));
 | 
			
		||||
        this._onSourceEnableChanged(source.policy, source);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _addSource(source) {
 | 
			
		||||
        let obj = {
 | 
			
		||||
            showId: 0,
 | 
			
		||||
            notifyId: 0,
 | 
			
		||||
            destroyId: 0,
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        this._sources.set(source, obj);
 | 
			
		||||
 | 
			
		||||
        obj.showId = source.connect('notification-show', this._onNotificationShow.bind(this));
 | 
			
		||||
        obj.notifyId = source.connect('notify', this._onNotify.bind(this));
 | 
			
		||||
        obj.destroyId = source.connect('destroy', this._onSourceDestroy.bind(this));
 | 
			
		||||
 | 
			
		||||
        this.emit('source-added', source);
 | 
			
		||||
@@ -1115,7 +1022,7 @@ var MessageTray = GObject.registerClass({
 | 
			
		||||
        let obj = this._sources.get(source);
 | 
			
		||||
        this._sources.delete(source);
 | 
			
		||||
 | 
			
		||||
        source.disconnect(obj.showId);
 | 
			
		||||
        source.disconnect(obj.notifyId);
 | 
			
		||||
        source.disconnect(obj.destroyId);
 | 
			
		||||
 | 
			
		||||
        this.emit('source-removed', source);
 | 
			
		||||
@@ -1156,7 +1063,7 @@ var MessageTray = GObject.registerClass({
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onNotificationShow(_source, notification) {
 | 
			
		||||
    _onNotify(source, notification) {
 | 
			
		||||
        if (this._notification == notification) {
 | 
			
		||||
            // If a notification that is being shown is updated, we update
 | 
			
		||||
            // how it is shown and extend the time until it auto-hides.
 | 
			
		||||
@@ -1288,7 +1195,7 @@ var MessageTray = GObject.registerClass({
 | 
			
		||||
    // at the present time.
 | 
			
		||||
    _updateState() {
 | 
			
		||||
        let hasMonitor = Main.layoutManager.primaryMonitor != null;
 | 
			
		||||
        this.visible = !this._bannerBlocked && hasMonitor && this._banner != null;
 | 
			
		||||
        this.actor.visible = !this._bannerBlocked && hasMonitor && this._banner != null;
 | 
			
		||||
        if (this._bannerBlocked || !hasMonitor)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
@@ -1368,11 +1275,11 @@ var MessageTray = GObject.registerClass({
 | 
			
		||||
            this._updateState();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this._bannerBin.add_actor(this._banner);
 | 
			
		||||
        this._bannerBin.add_actor(this._banner.actor);
 | 
			
		||||
 | 
			
		||||
        this._bannerBin.opacity = 0;
 | 
			
		||||
        this._bannerBin.y = -this._banner.height;
 | 
			
		||||
        this.show();
 | 
			
		||||
        this._bannerBin.y = -this._banner.actor.height;
 | 
			
		||||
        this.actor.show();
 | 
			
		||||
 | 
			
		||||
        Meta.disable_unredirect_for_display(global.display);
 | 
			
		||||
        this._updateShowingNotification();
 | 
			
		||||
@@ -1519,16 +1426,16 @@ var MessageTray = GObject.registerClass({
 | 
			
		||||
    _hideNotificationCompleted() {
 | 
			
		||||
        let notification = this._notification;
 | 
			
		||||
        this._notification = null;
 | 
			
		||||
        if (!this._notificationRemoved && notification.isTransient)
 | 
			
		||||
        if (notification.isTransient)
 | 
			
		||||
            notification.destroy(NotificationDestroyedReason.EXPIRED);
 | 
			
		||||
 | 
			
		||||
        this._pointerInNotification = false;
 | 
			
		||||
        this._notificationRemoved = false;
 | 
			
		||||
        Meta.enable_unredirect_for_display(global.display);
 | 
			
		||||
 | 
			
		||||
        this._banner.destroy();
 | 
			
		||||
        this._banner.actor.destroy();
 | 
			
		||||
        this._banner = null;
 | 
			
		||||
        this.hide();
 | 
			
		||||
        this.actor.hide();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _expandActiveNotification() {
 | 
			
		||||
@@ -1550,15 +1457,15 @@ var MessageTray = GObject.registerClass({
 | 
			
		||||
    _ensureBannerFocused() {
 | 
			
		||||
        this._notificationFocusGrabber.grabFocus();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(MessageTray.prototype);
 | 
			
		||||
 | 
			
		||||
var SystemNotificationSource = GObject.registerClass(
 | 
			
		||||
class SystemNotificationSource extends Source {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init(_("System Information"), 'dialog-information-symbolic');
 | 
			
		||||
var SystemNotificationSource = class SystemNotificationSource extends Source {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        super(_("System Information"), 'dialog-information-symbolic');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    open() {
 | 
			
		||||
        this.destroy();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -121,7 +121,7 @@ var ModalDialog = GObject.registerClass({
 | 
			
		||||
 | 
			
		||||
        this.dialogLayout.opacity = 255;
 | 
			
		||||
        if (this._lightbox)
 | 
			
		||||
            this._lightbox.lightOn();
 | 
			
		||||
            this._lightbox.show();
 | 
			
		||||
        this.opacity = 0;
 | 
			
		||||
        this.show();
 | 
			
		||||
        this.ease({
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
/* exported MediaSection */
 | 
			
		||||
const { Gio, GObject, Shell, St } = imports.gi;
 | 
			
		||||
const { Gio, Shell, St } = imports.gi;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
 | 
			
		||||
const Calendar = imports.ui.calendar;
 | 
			
		||||
@@ -19,10 +19,9 @@ const MprisPlayerProxy = Gio.DBusProxy.makeProxyWrapper(MprisPlayerIface);
 | 
			
		||||
 | 
			
		||||
const MPRIS_PLAYER_PREFIX = 'org.mpris.MediaPlayer2.';
 | 
			
		||||
 | 
			
		||||
var MediaMessage = GObject.registerClass(
 | 
			
		||||
class MediaMessage extends MessageList.Message {
 | 
			
		||||
    _init(player) {
 | 
			
		||||
        super._init('', '');
 | 
			
		||||
var MediaMessage = class MediaMessage extends MessageList.Message {
 | 
			
		||||
    constructor(player) {
 | 
			
		||||
        super('', '');
 | 
			
		||||
 | 
			
		||||
        this._player = player;
 | 
			
		||||
 | 
			
		||||
@@ -49,7 +48,7 @@ class MediaMessage extends MessageList.Message {
 | 
			
		||||
        this._update();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_clicked() {
 | 
			
		||||
    _onClicked() {
 | 
			
		||||
        this._player.raise();
 | 
			
		||||
        Main.panel.closeCalendar();
 | 
			
		||||
    }
 | 
			
		||||
@@ -80,7 +79,7 @@ class MediaMessage extends MessageList.Message {
 | 
			
		||||
        this._updateNavButton(this._prevButton, this._player.canGoPrevious);
 | 
			
		||||
        this._updateNavButton(this._nextButton, this._player.canGoNext);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var MprisPlayer = class MprisPlayer {
 | 
			
		||||
    constructor(busName) {
 | 
			
		||||
@@ -195,10 +194,9 @@ var MprisPlayer = class MprisPlayer {
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(MprisPlayer.prototype);
 | 
			
		||||
 | 
			
		||||
var MediaSection = GObject.registerClass(
 | 
			
		||||
class MediaSection extends MessageList.MessageListSection {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init();
 | 
			
		||||
var MediaSection = class MediaSection extends MessageList.MessageListSection {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        super();
 | 
			
		||||
 | 
			
		||||
        this._players = new Map();
 | 
			
		||||
 | 
			
		||||
@@ -249,4 +247,4 @@ class MediaSection extends MessageList.MessageListSection {
 | 
			
		||||
        if (newOwner && !oldOwner)
 | 
			
		||||
            this._addPlayer(name);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/* exported NotificationDaemon */
 | 
			
		||||
 | 
			
		||||
const { GdkPixbuf, Gio, GLib, GObject, Shell, St } = imports.gi;
 | 
			
		||||
const { GdkPixbuf, Gio, GLib, Shell, St } = imports.gi;
 | 
			
		||||
 | 
			
		||||
const Config = imports.misc.config;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
@@ -412,10 +412,10 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var FdoNotificationDaemonSource = GObject.registerClass(
 | 
			
		||||
var FdoNotificationDaemonSource =
 | 
			
		||||
class FdoNotificationDaemonSource extends MessageTray.Source {
 | 
			
		||||
    _init(title, pid, sender, appId) {
 | 
			
		||||
        super._init(title);
 | 
			
		||||
    constructor(title, pid, sender, appId) {
 | 
			
		||||
        super(title);
 | 
			
		||||
 | 
			
		||||
        this.pid = pid;
 | 
			
		||||
        this.app = this._getApp(appId);
 | 
			
		||||
@@ -464,7 +464,7 @@ class FdoNotificationDaemonSource extends MessageTray.Source {
 | 
			
		||||
        if (notification.resident && this.app && tracker.focus_app == this.app)
 | 
			
		||||
            this.pushNotification(notification);
 | 
			
		||||
        else
 | 
			
		||||
            this.showNotification(notification);
 | 
			
		||||
            this.notify(notification);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _getApp(appId) {
 | 
			
		||||
@@ -526,7 +526,7 @@ class FdoNotificationDaemonSource extends MessageTray.Source {
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const PRIORITY_URGENCY_MAP = {
 | 
			
		||||
    low: MessageTray.Urgency.LOW,
 | 
			
		||||
@@ -535,10 +535,10 @@ const PRIORITY_URGENCY_MAP = {
 | 
			
		||||
    urgent: MessageTray.Urgency.CRITICAL
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var GtkNotificationDaemonNotification = GObject.registerClass(
 | 
			
		||||
var GtkNotificationDaemonNotification =
 | 
			
		||||
class GtkNotificationDaemonNotification extends MessageTray.Notification {
 | 
			
		||||
    _init(source, notification) {
 | 
			
		||||
        super._init(source);
 | 
			
		||||
    constructor(source, notification) {
 | 
			
		||||
        super(source);
 | 
			
		||||
        this._serialized = GLib.Variant.new('a{sv}', notification);
 | 
			
		||||
 | 
			
		||||
        let { title,
 | 
			
		||||
@@ -602,7 +602,7 @@ class GtkNotificationDaemonNotification extends MessageTray.Notification {
 | 
			
		||||
    serialize() {
 | 
			
		||||
        return this._serialized;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const FdoApplicationIface = loadInterfaceXML('org.freedesktop.Application');
 | 
			
		||||
const FdoApplicationProxy = Gio.DBusProxy.makeProxyWrapper(FdoApplicationIface);
 | 
			
		||||
@@ -618,9 +618,9 @@ function getPlatformData() {
 | 
			
		||||
 | 
			
		||||
function InvalidAppError() {}
 | 
			
		||||
 | 
			
		||||
var GtkNotificationDaemonAppSource = GObject.registerClass(
 | 
			
		||||
var GtkNotificationDaemonAppSource =
 | 
			
		||||
class GtkNotificationDaemonAppSource extends MessageTray.Source {
 | 
			
		||||
    _init(appId) {
 | 
			
		||||
    constructor(appId) {
 | 
			
		||||
        let objectPath = objectPathFromAppId(appId);
 | 
			
		||||
        if (!GLib.Variant.is_object_path(objectPath))
 | 
			
		||||
            throw new InvalidAppError();
 | 
			
		||||
@@ -629,7 +629,7 @@ class GtkNotificationDaemonAppSource extends MessageTray.Source {
 | 
			
		||||
        if (!app)
 | 
			
		||||
            throw new InvalidAppError();
 | 
			
		||||
 | 
			
		||||
        super._init(app.get_name());
 | 
			
		||||
        super(app.get_name());
 | 
			
		||||
 | 
			
		||||
        this._appId = appId;
 | 
			
		||||
        this._app = app;
 | 
			
		||||
@@ -690,7 +690,7 @@ class GtkNotificationDaemonAppSource extends MessageTray.Source {
 | 
			
		||||
        this._notifications[notificationId] = notification;
 | 
			
		||||
 | 
			
		||||
        if (showBanner)
 | 
			
		||||
            this.showNotification(notification);
 | 
			
		||||
            this.notify(notification);
 | 
			
		||||
        else
 | 
			
		||||
            this.pushNotification(notification);
 | 
			
		||||
 | 
			
		||||
@@ -716,7 +716,7 @@ class GtkNotificationDaemonAppSource extends MessageTray.Source {
 | 
			
		||||
        }
 | 
			
		||||
        return [this._appId, notifications];
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const GtkNotificationsIface = loadInterfaceXML('org.gtk.Notifications');
 | 
			
		||||
 | 
			
		||||
@@ -742,7 +742,7 @@ var GtkNotificationDaemon = class GtkNotificationDaemon {
 | 
			
		||||
            delete this._sources[appId];
 | 
			
		||||
            this._saveNotifications();
 | 
			
		||||
        });
 | 
			
		||||
        source.connect('notify::count', this._saveNotifications.bind(this));
 | 
			
		||||
        source.connect('count-updated', this._saveNotifications.bind(this));
 | 
			
		||||
        Main.messageTray.add(source);
 | 
			
		||||
        this._sources[appId] = source;
 | 
			
		||||
        return source;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,33 +1,30 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/* exported OsdMonitorLabeler */
 | 
			
		||||
 | 
			
		||||
const { Clutter, Gio, GObject, Meta, St } = imports.gi;
 | 
			
		||||
const { Clutter, Gio, Meta, St } = imports.gi;
 | 
			
		||||
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
 | 
			
		||||
var OsdMonitorLabel = GObject.registerClass(
 | 
			
		||||
class OsdMonitorLabel extends St.Widget {
 | 
			
		||||
    _init(monitor, label) {
 | 
			
		||||
        super._init({ x_expand: true, y_expand: true });
 | 
			
		||||
var OsdMonitorLabel = class {
 | 
			
		||||
    constructor(monitor, label) {
 | 
			
		||||
        this._actor = new St.Widget({ x_expand: true,
 | 
			
		||||
                                      y_expand: true });
 | 
			
		||||
 | 
			
		||||
        this._monitor = monitor;
 | 
			
		||||
 | 
			
		||||
        this._box = new St.BoxLayout({ style_class: 'osd-window',
 | 
			
		||||
                                       vertical: true });
 | 
			
		||||
        this.add_actor(this._box);
 | 
			
		||||
        this._actor.add_actor(this._box);
 | 
			
		||||
 | 
			
		||||
        this._label = new St.Label({ style_class: 'osd-monitor-label',
 | 
			
		||||
                                     text: label });
 | 
			
		||||
        this._box.add(this._label);
 | 
			
		||||
 | 
			
		||||
        Main.uiGroup.add_child(this);
 | 
			
		||||
        Main.uiGroup.set_child_above_sibling(this, null);
 | 
			
		||||
        Main.uiGroup.add_child(this._actor);
 | 
			
		||||
        Main.uiGroup.set_child_above_sibling(this._actor, null);
 | 
			
		||||
        this._position();
 | 
			
		||||
 | 
			
		||||
        Meta.disable_unredirect_for_display(global.display);
 | 
			
		||||
        this.connect('destroy', () => {
 | 
			
		||||
            Meta.enable_unredirect_for_display(global.display);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _position() {
 | 
			
		||||
@@ -40,7 +37,12 @@ class OsdMonitorLabel extends St.Widget {
 | 
			
		||||
 | 
			
		||||
        this._box.y = workArea.y;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
    destroy() {
 | 
			
		||||
        this._actor.destroy();
 | 
			
		||||
        Meta.enable_unredirect_for_display(global.display);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var OsdMonitorLabeler = class {
 | 
			
		||||
    constructor() {
 | 
			
		||||
 
 | 
			
		||||
@@ -41,25 +41,22 @@ class OsdWindowConstraint extends Clutter.Constraint {
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
var OsdWindow = GObject.registerClass(
 | 
			
		||||
class OsdWindow extends St.Widget {
 | 
			
		||||
    _init(monitorIndex) {
 | 
			
		||||
        super._init({
 | 
			
		||||
            x_expand: true,
 | 
			
		||||
            y_expand: true,
 | 
			
		||||
            x_align: Clutter.ActorAlign.CENTER,
 | 
			
		||||
            y_align: Clutter.ActorAlign.CENTER
 | 
			
		||||
        });
 | 
			
		||||
var OsdWindow = class {
 | 
			
		||||
    constructor(monitorIndex) {
 | 
			
		||||
        this.actor = new St.Widget({ x_expand: true,
 | 
			
		||||
                                     y_expand: true,
 | 
			
		||||
                                     x_align: Clutter.ActorAlign.CENTER,
 | 
			
		||||
                                     y_align: Clutter.ActorAlign.CENTER });
 | 
			
		||||
 | 
			
		||||
        this._monitorIndex = monitorIndex;
 | 
			
		||||
        let constraint = new Layout.MonitorConstraint({ index: monitorIndex });
 | 
			
		||||
        this.add_constraint(constraint);
 | 
			
		||||
        this.actor.add_constraint(constraint);
 | 
			
		||||
 | 
			
		||||
        this._boxConstraint = new OsdWindowConstraint();
 | 
			
		||||
        this._box = new St.BoxLayout({ style_class: 'osd-window',
 | 
			
		||||
                                       vertical: true });
 | 
			
		||||
        this._box.add_constraint(this._boxConstraint);
 | 
			
		||||
        this.add_actor(this._box);
 | 
			
		||||
        this.actor.add_actor(this._box);
 | 
			
		||||
 | 
			
		||||
        this._icon = new St.Icon();
 | 
			
		||||
        this._box.add(this._icon, { expand: true });
 | 
			
		||||
@@ -76,7 +73,7 @@ class OsdWindow extends St.Widget {
 | 
			
		||||
        this._hideTimeoutId = 0;
 | 
			
		||||
        this._reset();
 | 
			
		||||
 | 
			
		||||
        this.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
        this.actor.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
 | 
			
		||||
        this._monitorsChangedId =
 | 
			
		||||
            Main.layoutManager.connect('monitors-changed',
 | 
			
		||||
@@ -86,7 +83,7 @@ class OsdWindow extends St.Widget {
 | 
			
		||||
            themeContext.connect('notify::scale-factor',
 | 
			
		||||
                                 this._relayout.bind(this));
 | 
			
		||||
        this._relayout();
 | 
			
		||||
        Main.uiGroup.add_child(this);
 | 
			
		||||
        Main.uiGroup.add_child(this.actor);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onDestroy() {
 | 
			
		||||
@@ -113,7 +110,7 @@ class OsdWindow extends St.Widget {
 | 
			
		||||
    setLevel(value) {
 | 
			
		||||
        this._level.visible = (value != undefined);
 | 
			
		||||
        if (value != undefined) {
 | 
			
		||||
            if (this.visible)
 | 
			
		||||
            if (this.actor.visible)
 | 
			
		||||
                this._level.ease_property('value', value, {
 | 
			
		||||
                    mode: Clutter.AnimationMode.EASE_OUT_QUAD,
 | 
			
		||||
                    duration: LEVEL_ANIMATION_TIME
 | 
			
		||||
@@ -131,13 +128,13 @@ class OsdWindow extends St.Widget {
 | 
			
		||||
        if (!this._icon.gicon)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (!this.visible) {
 | 
			
		||||
        if (!this.actor.visible) {
 | 
			
		||||
            Meta.disable_unredirect_for_display(global.display);
 | 
			
		||||
            super.show();
 | 
			
		||||
            this.opacity = 0;
 | 
			
		||||
            this.get_parent().set_child_above_sibling(this, null);
 | 
			
		||||
            this.actor.show();
 | 
			
		||||
            this.actor.opacity = 0;
 | 
			
		||||
            this.actor.get_parent().set_child_above_sibling(this.actor, null);
 | 
			
		||||
 | 
			
		||||
            this.ease({
 | 
			
		||||
            this.actor.ease({
 | 
			
		||||
                opacity: 255,
 | 
			
		||||
                duration: FADE_TIME,
 | 
			
		||||
                mode: Clutter.AnimationMode.EASE_OUT_QUAD
 | 
			
		||||
@@ -161,7 +158,7 @@ class OsdWindow extends St.Widget {
 | 
			
		||||
 | 
			
		||||
    _hide() {
 | 
			
		||||
        this._hideTimeoutId = 0;
 | 
			
		||||
        this.ease({
 | 
			
		||||
        this.actor.ease({
 | 
			
		||||
            opacity: 0,
 | 
			
		||||
            duration: FADE_TIME,
 | 
			
		||||
            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
 | 
			
		||||
@@ -174,7 +171,7 @@ class OsdWindow extends St.Widget {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _reset() {
 | 
			
		||||
        super.hide();
 | 
			
		||||
        this.actor.hide();
 | 
			
		||||
        this.setLabel(null);
 | 
			
		||||
        this.setMaxLevel(null);
 | 
			
		||||
        this.setLevel(null);
 | 
			
		||||
@@ -196,7 +193,7 @@ class OsdWindow extends St.Widget {
 | 
			
		||||
        this._box.translation_y = Math.round(monitor.height / 4);
 | 
			
		||||
        this._boxConstraint.minSize = popupSize;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var OsdWindowManager = class {
 | 
			
		||||
    constructor() {
 | 
			
		||||
@@ -213,7 +210,7 @@ var OsdWindowManager = class {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (let i = Main.layoutManager.monitors.length; i < this._osdWindows.length; i++) {
 | 
			
		||||
            this._osdWindows[i].destroy();
 | 
			
		||||
            this._osdWindows[i].actor.destroy();
 | 
			
		||||
            this._osdWindows[i] = null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/* exported Overview */
 | 
			
		||||
 | 
			
		||||
const { Clutter, GLib, GObject, Meta, Shell, St } = imports.gi;
 | 
			
		||||
const { Clutter, GLib, Meta, Shell, St } = imports.gi;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
 | 
			
		||||
const Background = imports.ui.background;
 | 
			
		||||
@@ -72,108 +72,36 @@ var ShellInfo = class {
 | 
			
		||||
        if (undoCallback)
 | 
			
		||||
            notification.addAction(_("Undo"), this._onUndoClicked.bind(this));
 | 
			
		||||
 | 
			
		||||
        this._source.showNotification(notification);
 | 
			
		||||
        this._source.notify(notification);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var OverviewActor = GObject.registerClass(
 | 
			
		||||
class OverviewActor extends St.BoxLayout {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init({
 | 
			
		||||
            name: 'overview',
 | 
			
		||||
            /* Translators: This is the main view to select
 | 
			
		||||
                activities. See also note for "Activities" string. */
 | 
			
		||||
            accessible_name: _("Overview"),
 | 
			
		||||
            vertical: true
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this.add_constraint(new LayoutManager.MonitorConstraint({ primary: true }));
 | 
			
		||||
 | 
			
		||||
        // Add a clone of the panel to the overview so spacing and such is
 | 
			
		||||
        // automatic
 | 
			
		||||
        let panelGhost = new St.Bin({
 | 
			
		||||
            child: new Clutter.Clone({ source: Main.panel }),
 | 
			
		||||
            reactive: false,
 | 
			
		||||
            opacity: 0
 | 
			
		||||
        });
 | 
			
		||||
        this.add_actor(panelGhost);
 | 
			
		||||
 | 
			
		||||
        this._searchEntry = new St.Entry({
 | 
			
		||||
            style_class: 'search-entry',
 | 
			
		||||
            /* Translators: this is the text displayed
 | 
			
		||||
               in the search entry when no search is
 | 
			
		||||
               active; it should not exceed ~30
 | 
			
		||||
               characters. */
 | 
			
		||||
            hint_text: _("Type to search…"),
 | 
			
		||||
            track_hover: true,
 | 
			
		||||
            can_focus: true
 | 
			
		||||
        });
 | 
			
		||||
        let searchEntryBin = new St.Bin({
 | 
			
		||||
            child: this._searchEntry,
 | 
			
		||||
            x_align: St.Align.MIDDLE
 | 
			
		||||
        });
 | 
			
		||||
        this.add_actor(searchEntryBin);
 | 
			
		||||
 | 
			
		||||
        this._controls = new OverviewControls.ControlsManager(this._searchEntry);
 | 
			
		||||
 | 
			
		||||
        // Add our same-line elements after the search entry
 | 
			
		||||
        this.add(this._controls, { y_fill: true, expand: true });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get dash() {
 | 
			
		||||
        return this._controls.dash;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get searchEntry() {
 | 
			
		||||
        return this._searchEntry;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get viewSelector() {
 | 
			
		||||
        return this._controls.viewSelector;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
var Overview = class {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        this._overviewCreated = false;
 | 
			
		||||
        this._initCalled = false;
 | 
			
		||||
 | 
			
		||||
        Main.sessionMode.connect('updated', this._sessionUpdated.bind(this));
 | 
			
		||||
        this._sessionUpdated();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get dash() {
 | 
			
		||||
        return this._overview.dash;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get dashIconSize() {
 | 
			
		||||
        logError(new Error('Usage of Overview.\'dashIconSize\' is deprecated, ' +
 | 
			
		||||
            'use \'dash.iconSize\' property instead'));
 | 
			
		||||
        return this.dash.iconSize;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get viewSelector() {
 | 
			
		||||
        return this._overview.viewSelector;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get animationInProgress() {
 | 
			
		||||
        return this._animationInProgress;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get visible() {
 | 
			
		||||
        return this._visible;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get visibleTarget() {
 | 
			
		||||
        return this._visibleTarget;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _createOverview() {
 | 
			
		||||
        if (this._overview)
 | 
			
		||||
        if (this._overviewCreated)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (this.isDummy)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._overviewCreated = true;
 | 
			
		||||
 | 
			
		||||
        this._overview = new St.BoxLayout({ name: 'overview',
 | 
			
		||||
                                            /* Translators: This is the main view to select
 | 
			
		||||
                                               activities. See also note for "Activities" string. */
 | 
			
		||||
                                            accessible_name: _("Overview"),
 | 
			
		||||
                                            vertical: true });
 | 
			
		||||
        this._overview.add_constraint(new LayoutManager.MonitorConstraint({ primary: true }));
 | 
			
		||||
        this._overview._delegate = this;
 | 
			
		||||
 | 
			
		||||
        // The main Background actors are inside global.window_group which are
 | 
			
		||||
        // hidden when displaying the overview, so we create a new
 | 
			
		||||
        // one. Instances of this class share a single CoglTexture behind the
 | 
			
		||||
@@ -188,11 +116,11 @@ var Overview = class {
 | 
			
		||||
 | 
			
		||||
        this._activationTime = 0;
 | 
			
		||||
 | 
			
		||||
        this._visible = false;          // animating to overview, in overview, animating out
 | 
			
		||||
        this.visible = false;           // animating to overview, in overview, animating out
 | 
			
		||||
        this._shown = false;            // show() and not hide()
 | 
			
		||||
        this._modal = false;            // have a modal grab
 | 
			
		||||
        this._animationInProgress = false;
 | 
			
		||||
        this._visibleTarget = false;
 | 
			
		||||
        this.animationInProgress = false;
 | 
			
		||||
        this.visibleTarget = false;
 | 
			
		||||
 | 
			
		||||
        // During transitions, we raise this to the top to avoid having the overview
 | 
			
		||||
        // area be reactive; it causes too many issues such as double clicks on
 | 
			
		||||
@@ -201,6 +129,9 @@ var Overview = class {
 | 
			
		||||
                                              reactive: true });
 | 
			
		||||
        Main.layoutManager.overviewGroup.add_child(this._coverPane);
 | 
			
		||||
        this._coverPane.connect('event', () => Clutter.EVENT_STOP);
 | 
			
		||||
 | 
			
		||||
        Main.layoutManager.overviewGroup.add_child(this._overview);
 | 
			
		||||
 | 
			
		||||
        this._coverPane.hide();
 | 
			
		||||
 | 
			
		||||
        // XDND
 | 
			
		||||
@@ -282,12 +213,41 @@ var Overview = class {
 | 
			
		||||
        if (this.isDummy)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._overview = new OverviewActor();
 | 
			
		||||
        this._overview._delegate = this;
 | 
			
		||||
        Main.layoutManager.overviewGroup.add_child(this._overview);
 | 
			
		||||
 | 
			
		||||
        this._shellInfo = new ShellInfo();
 | 
			
		||||
 | 
			
		||||
        // Add a clone of the panel to the overview so spacing and such is
 | 
			
		||||
        // automatic
 | 
			
		||||
        this._panelGhost = new St.Bin({ child: new Clutter.Clone({ source: Main.panel }),
 | 
			
		||||
                                        reactive: false,
 | 
			
		||||
                                        opacity: 0 });
 | 
			
		||||
        this._overview.add_actor(this._panelGhost);
 | 
			
		||||
 | 
			
		||||
        this._searchEntry = new St.Entry({ style_class: 'search-entry',
 | 
			
		||||
                                           /* Translators: this is the text displayed
 | 
			
		||||
                                              in the search entry when no search is
 | 
			
		||||
                                              active; it should not exceed ~30
 | 
			
		||||
                                              characters. */
 | 
			
		||||
                                           hint_text: _("Type to search…"),
 | 
			
		||||
                                           track_hover: true,
 | 
			
		||||
                                           can_focus: true });
 | 
			
		||||
        this._searchEntryBin = new St.Bin({ child: this._searchEntry,
 | 
			
		||||
                                            x_align: St.Align.MIDDLE });
 | 
			
		||||
        this._overview.add_actor(this._searchEntryBin);
 | 
			
		||||
 | 
			
		||||
        // Create controls
 | 
			
		||||
        this._controls = new OverviewControls.ControlsManager(this._searchEntry);
 | 
			
		||||
        this._dash = this._controls.dash;
 | 
			
		||||
        this.viewSelector = this._controls.viewSelector;
 | 
			
		||||
 | 
			
		||||
        // Add our same-line elements after the search entry
 | 
			
		||||
        this._overview.add(this._controls.actor, { y_fill: true, expand: true });
 | 
			
		||||
 | 
			
		||||
        // TODO - recalculate everything when desktop size changes
 | 
			
		||||
        this.dashIconSize = this._dash.iconSize;
 | 
			
		||||
        this._dash.connect('icon-size-changed', () => {
 | 
			
		||||
            this.dashIconSize = this._dash.iconSize;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        Main.layoutManager.connect('monitors-changed', this._relayout.bind(this));
 | 
			
		||||
        this._relayout();
 | 
			
		||||
    }
 | 
			
		||||
@@ -400,12 +360,8 @@ var Overview = class {
 | 
			
		||||
            return null;
 | 
			
		||||
 | 
			
		||||
        let window = windows[0];
 | 
			
		||||
        let clone = new Clutter.Actor({
 | 
			
		||||
            source: window.content,
 | 
			
		||||
            request_mode: Clutter.RequestMode.CONTENT_SIZE,
 | 
			
		||||
            x: window.x,
 | 
			
		||||
            y: window.y,
 | 
			
		||||
        });
 | 
			
		||||
        let clone = new Clutter.Clone({ source: window,
 | 
			
		||||
                                        x: window.x, y: window.y });
 | 
			
		||||
        clone.source.connect('destroy', () => {
 | 
			
		||||
            clone.destroy();
 | 
			
		||||
        });
 | 
			
		||||
@@ -470,7 +426,7 @@ var Overview = class {
 | 
			
		||||
 | 
			
		||||
    focusSearch() {
 | 
			
		||||
        this.show();
 | 
			
		||||
        this._overview.searchEntry.grab_key_focus();
 | 
			
		||||
        this._searchEntry.grab_key_focus();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fadeInDesktop() {
 | 
			
		||||
@@ -508,11 +464,11 @@ var Overview = class {
 | 
			
		||||
    // the overview if the user both triggered the hot corner and
 | 
			
		||||
    // clicked the Activities button.
 | 
			
		||||
    shouldToggleByCornerOrButton() {
 | 
			
		||||
        if (this._animationInProgress)
 | 
			
		||||
        if (this.animationInProgress)
 | 
			
		||||
            return false;
 | 
			
		||||
        if (this._inItemDrag || this._inWindowDrag)
 | 
			
		||||
            return false;
 | 
			
		||||
        if (!this._activationTime ||
 | 
			
		||||
        if (this._activationTime == 0 ||
 | 
			
		||||
            GLib.get_monotonic_time() / GLib.USEC_PER_SEC - this._activationTime > OVERVIEW_ACTIVATION_TIMEOUT)
 | 
			
		||||
            return true;
 | 
			
		||||
        return false;
 | 
			
		||||
@@ -522,7 +478,7 @@ var Overview = class {
 | 
			
		||||
        // We delay grab changes during animation so that when removing the
 | 
			
		||||
        // overview we don't have a problem with the release of a press/release
 | 
			
		||||
        // going to an application.
 | 
			
		||||
        if (this._animationInProgress)
 | 
			
		||||
        if (this.animationInProgress)
 | 
			
		||||
            return true;
 | 
			
		||||
 | 
			
		||||
        if (this._shown) {
 | 
			
		||||
@@ -564,12 +520,12 @@ var Overview = class {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    _animateVisible() {
 | 
			
		||||
        if (this._visible || this._animationInProgress)
 | 
			
		||||
        if (this.visible || this.animationInProgress)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._visible = true;
 | 
			
		||||
        this._animationInProgress = true;
 | 
			
		||||
        this._visibleTarget = true;
 | 
			
		||||
        this.visible = true;
 | 
			
		||||
        this.animationInProgress = true;
 | 
			
		||||
        this.visibleTarget = true;
 | 
			
		||||
        this._activationTime = GLib.get_monotonic_time() / GLib.USEC_PER_SEC;
 | 
			
		||||
 | 
			
		||||
        Meta.disable_unredirect_for_display(global.display);
 | 
			
		||||
@@ -590,7 +546,7 @@ var Overview = class {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _showDone() {
 | 
			
		||||
        this._animationInProgress = false;
 | 
			
		||||
        this.animationInProgress = false;
 | 
			
		||||
        this._desktopFade.hide();
 | 
			
		||||
        this._coverPane.hide();
 | 
			
		||||
 | 
			
		||||
@@ -630,11 +586,11 @@ var Overview = class {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _animateNotVisible() {
 | 
			
		||||
        if (!this._visible || this._animationInProgress)
 | 
			
		||||
        if (!this.visible || this.animationInProgress)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._animationInProgress = true;
 | 
			
		||||
        this._visibleTarget = false;
 | 
			
		||||
        this.animationInProgress = true;
 | 
			
		||||
        this.visibleTarget = false;
 | 
			
		||||
 | 
			
		||||
        this.viewSelector.animateFromOverview();
 | 
			
		||||
 | 
			
		||||
@@ -660,8 +616,8 @@ var Overview = class {
 | 
			
		||||
        this._desktopFade.hide();
 | 
			
		||||
        this._coverPane.hide();
 | 
			
		||||
 | 
			
		||||
        this._visible = false;
 | 
			
		||||
        this._animationInProgress = false;
 | 
			
		||||
        this.visible = false;
 | 
			
		||||
        this.animationInProgress = false;
 | 
			
		||||
 | 
			
		||||
        this.emit('hidden');
 | 
			
		||||
        // Handle any calls to show* while we were hiding
 | 
			
		||||
@@ -677,17 +633,14 @@ var Overview = class {
 | 
			
		||||
        if (this.isDummy)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (this._visible)
 | 
			
		||||
        if (this.visible)
 | 
			
		||||
            this.hide();
 | 
			
		||||
        else
 | 
			
		||||
            this.show();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    getShowAppsButton() {
 | 
			
		||||
        logError(new Error('Usage of Overview.\'getShowAppsButton\' is deprecated, ' +
 | 
			
		||||
            'use \'dash.showAppsButton\' property instead'));
 | 
			
		||||
 | 
			
		||||
        return this.dash.showAppsButton;
 | 
			
		||||
        return this._dash.showAppsButton;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(Overview.prototype);
 | 
			
		||||
 
 | 
			
		||||
@@ -118,22 +118,19 @@ var SlideLayout = GObject.registerClass({
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
var SlidingControl = GObject.registerClass(
 | 
			
		||||
class SlidingControl extends St.Widget {
 | 
			
		||||
    _init(params) {
 | 
			
		||||
var SlidingControl = class {
 | 
			
		||||
    constructor(params) {
 | 
			
		||||
        params = Params.parse(params, { slideDirection: SlideDirection.LEFT });
 | 
			
		||||
 | 
			
		||||
        this.layout = new SlideLayout();
 | 
			
		||||
        this.layout.slideDirection = params.slideDirection;
 | 
			
		||||
        super._init({
 | 
			
		||||
            layout_manager: this.layout,
 | 
			
		||||
            style_class: 'overview-controls',
 | 
			
		||||
            clip_to_allocation: true
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this._visible = true;
 | 
			
		||||
        this._inDrag = false;
 | 
			
		||||
 | 
			
		||||
        this.layout = new SlideLayout();
 | 
			
		||||
        this.layout.slideDirection = params.slideDirection;
 | 
			
		||||
        this.actor = new St.Widget({ layout_manager: this.layout,
 | 
			
		||||
                                     style_class: 'overview-controls',
 | 
			
		||||
                                     clip_to_allocation: true });
 | 
			
		||||
 | 
			
		||||
        Main.overview.connect('hiding', this._onOverviewHiding.bind(this));
 | 
			
		||||
 | 
			
		||||
        Main.overview.connect('item-drag-begin', this._onDragBegin.bind(this));
 | 
			
		||||
@@ -150,20 +147,20 @@ class SlidingControl extends St.Widget {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _updateSlide() {
 | 
			
		||||
        this.ease_property('@layout.slide-x', this._getSlide(), {
 | 
			
		||||
        this.actor.ease_property('@layout.slide-x', this._getSlide(), {
 | 
			
		||||
            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
 | 
			
		||||
            duration: SIDE_CONTROLS_ANIMATION_TIME,
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    getVisibleWidth() {
 | 
			
		||||
        let child = this.get_first_child();
 | 
			
		||||
        let child = this.actor.get_first_child();
 | 
			
		||||
        let [, , natWidth] = child.get_preferred_size();
 | 
			
		||||
        return natWidth;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _getTranslation() {
 | 
			
		||||
        let child = this.get_first_child();
 | 
			
		||||
        let child = this.actor.get_first_child();
 | 
			
		||||
        let direction = getRtlSlideDirection(this.layout.slideDirection, child);
 | 
			
		||||
        let visibleWidth = this.getVisibleWidth();
 | 
			
		||||
 | 
			
		||||
@@ -189,7 +186,7 @@ class SlidingControl extends St.Widget {
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this.layout.translation_x = translationStart;
 | 
			
		||||
        this.ease_property('@layout.translation-x', translationEnd, {
 | 
			
		||||
        this.actor.ease_property('@layout.translation-x', translationEnd, {
 | 
			
		||||
            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
 | 
			
		||||
            duration: SIDE_CONTROLS_ANIMATION_TIME,
 | 
			
		||||
        });
 | 
			
		||||
@@ -221,7 +218,7 @@ class SlidingControl extends St.Widget {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fadeIn() {
 | 
			
		||||
        this.ease({
 | 
			
		||||
        this.actor.ease({
 | 
			
		||||
            opacity: 255,
 | 
			
		||||
            duration: SIDE_CONTROLS_ANIMATION_TIME / 2,
 | 
			
		||||
            mode: Clutter.AnimationMode.EASE_IN_QUAD
 | 
			
		||||
@@ -229,7 +226,7 @@ class SlidingControl extends St.Widget {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fadeHalf() {
 | 
			
		||||
        this.ease({
 | 
			
		||||
        this.actor.ease({
 | 
			
		||||
            opacity: 128,
 | 
			
		||||
            duration: SIDE_CONTROLS_ANIMATION_TIME / 2,
 | 
			
		||||
            mode: Clutter.AnimationMode.EASE_OUT_QUAD
 | 
			
		||||
@@ -252,38 +249,37 @@ class SlidingControl extends St.Widget {
 | 
			
		||||
        // selector; this means we can now safely set the full slide for
 | 
			
		||||
        // the next page, since slideIn or slideOut might have been called,
 | 
			
		||||
        // changing the visiblity
 | 
			
		||||
        this.remove_transition('@layout.slide-x');
 | 
			
		||||
        this.actor.remove_transition('@layout.slide-x');
 | 
			
		||||
        this.layout.slide_x = this._getSlide();
 | 
			
		||||
        this._updateTranslation();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var ThumbnailsSlider = GObject.registerClass(
 | 
			
		||||
class ThumbnailsSlider extends SlidingControl {
 | 
			
		||||
    _init(thumbnailsBox) {
 | 
			
		||||
        super._init({ slideDirection: SlideDirection.RIGHT });
 | 
			
		||||
var ThumbnailsSlider = class extends SlidingControl {
 | 
			
		||||
    constructor(thumbnailsBox) {
 | 
			
		||||
        super({ slideDirection: SlideDirection.RIGHT });
 | 
			
		||||
 | 
			
		||||
        this._thumbnailsBox = thumbnailsBox;
 | 
			
		||||
 | 
			
		||||
        this.request_mode = Clutter.RequestMode.WIDTH_FOR_HEIGHT;
 | 
			
		||||
        this.reactive = true;
 | 
			
		||||
        this.track_hover = true;
 | 
			
		||||
        this.add_actor(this._thumbnailsBox);
 | 
			
		||||
        this.actor.request_mode = Clutter.RequestMode.WIDTH_FOR_HEIGHT;
 | 
			
		||||
        this.actor.reactive = true;
 | 
			
		||||
        this.actor.track_hover = true;
 | 
			
		||||
        this.actor.add_actor(this._thumbnailsBox);
 | 
			
		||||
 | 
			
		||||
        Main.layoutManager.connect('monitors-changed', this._updateSlide.bind(this));
 | 
			
		||||
        global.workspace_manager.connect('active-workspace-changed',
 | 
			
		||||
                                         this._updateSlide.bind(this));
 | 
			
		||||
        global.workspace_manager.connect('notify::n-workspaces',
 | 
			
		||||
                                         this._updateSlide.bind(this));
 | 
			
		||||
        this.connect('notify::hover', this._updateSlide.bind(this));
 | 
			
		||||
        this._thumbnailsBox.bind_property('visible', this, 'visible', GObject.BindingFlags.SYNC_CREATE);
 | 
			
		||||
        this.actor.connect('notify::hover', this._updateSlide.bind(this));
 | 
			
		||||
        this._thumbnailsBox.bind_property('visible', this.actor, 'visible', GObject.BindingFlags.SYNC_CREATE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _getAlwaysZoomOut() {
 | 
			
		||||
        // Always show the pager on hover, during a drag, or if workspaces are
 | 
			
		||||
        // actually used, e.g. there are windows on any non-active workspace
 | 
			
		||||
        let workspaceManager = global.workspace_manager;
 | 
			
		||||
        let alwaysZoomOut = this.hover ||
 | 
			
		||||
        let alwaysZoomOut = this.actor.hover ||
 | 
			
		||||
                            this._inDrag ||
 | 
			
		||||
                            !Meta.prefs_get_dynamic_workspaces() ||
 | 
			
		||||
                            workspaceManager.n_workspaces > 2 ||
 | 
			
		||||
@@ -308,12 +304,12 @@ class ThumbnailsSlider extends SlidingControl {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    getNonExpandedWidth() {
 | 
			
		||||
        let child = this.get_first_child();
 | 
			
		||||
        let child = this.actor.get_first_child();
 | 
			
		||||
        return child.get_theme_node().get_length('visible-width');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onDragEnd() {
 | 
			
		||||
        this.sync_hover();
 | 
			
		||||
        this.actor.sync_hover();
 | 
			
		||||
        super._onDragEnd();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -325,7 +321,7 @@ class ThumbnailsSlider extends SlidingControl {
 | 
			
		||||
        if (alwaysZoomOut)
 | 
			
		||||
            return 1;
 | 
			
		||||
 | 
			
		||||
        let child = this.get_first_child();
 | 
			
		||||
        let child = this.actor.get_first_child();
 | 
			
		||||
        let preferredHeight = child.get_preferred_height(-1)[1];
 | 
			
		||||
        let expandedWidth = child.get_preferred_width(preferredHeight)[1];
 | 
			
		||||
 | 
			
		||||
@@ -339,25 +335,24 @@ class ThumbnailsSlider extends SlidingControl {
 | 
			
		||||
        else
 | 
			
		||||
            return this.getNonExpandedWidth();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var DashSlider = GObject.registerClass(
 | 
			
		||||
class DashSlider extends SlidingControl {
 | 
			
		||||
    _init(dash) {
 | 
			
		||||
        super._init({ slideDirection: SlideDirection.LEFT });
 | 
			
		||||
var DashSlider = class extends SlidingControl {
 | 
			
		||||
    constructor(dash) {
 | 
			
		||||
        super({ slideDirection: SlideDirection.LEFT });
 | 
			
		||||
 | 
			
		||||
        this._dash = dash;
 | 
			
		||||
 | 
			
		||||
        // SlideLayout reads the actor's expand flags to decide
 | 
			
		||||
        // whether to allocate the natural size to its child, or the whole
 | 
			
		||||
        // available allocation
 | 
			
		||||
        this._dash.x_expand = true;
 | 
			
		||||
        this._dash.actor.x_expand = true;
 | 
			
		||||
 | 
			
		||||
        this.x_expand = true;
 | 
			
		||||
        this.x_align = Clutter.ActorAlign.START;
 | 
			
		||||
        this.y_expand = true;
 | 
			
		||||
        this.actor.x_expand = true;
 | 
			
		||||
        this.actor.x_align = Clutter.ActorAlign.START;
 | 
			
		||||
        this.actor.y_expand = true;
 | 
			
		||||
 | 
			
		||||
        this.add_actor(this._dash);
 | 
			
		||||
        this.actor.add_actor(this._dash.actor);
 | 
			
		||||
 | 
			
		||||
        this._dash.connect('icon-size-changed', this._updateSlide.bind(this));
 | 
			
		||||
    }
 | 
			
		||||
@@ -376,7 +371,7 @@ class DashSlider extends SlidingControl {
 | 
			
		||||
    _onWindowDragEnd() {
 | 
			
		||||
        this.fadeIn();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var DashSpacer = GObject.registerClass(
 | 
			
		||||
class DashSpacer extends St.Widget {
 | 
			
		||||
@@ -421,21 +416,12 @@ var ControlsLayout = GObject.registerClass({
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
var ControlsManager = GObject.registerClass(
 | 
			
		||||
class ControlsManager extends St.Widget {
 | 
			
		||||
    _init(searchEntry) {
 | 
			
		||||
        let layout = new ControlsLayout();
 | 
			
		||||
        super._init({
 | 
			
		||||
            layout_manager: layout,
 | 
			
		||||
            x_expand: true,
 | 
			
		||||
            y_expand: true,
 | 
			
		||||
            clip_to_allocation: true
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
var ControlsManager = class {
 | 
			
		||||
    constructor(searchEntry) {
 | 
			
		||||
        this.dash = new Dash.Dash();
 | 
			
		||||
        this._dashSlider = new DashSlider(this.dash);
 | 
			
		||||
        this._dashSpacer = new DashSpacer();
 | 
			
		||||
        this._dashSpacer.setDashActor(this._dashSlider);
 | 
			
		||||
        this._dashSpacer.setDashActor(this._dashSlider.actor);
 | 
			
		||||
 | 
			
		||||
        this._thumbnailsBox = new WorkspaceThumbnail.ThumbnailsBox();
 | 
			
		||||
        this._thumbnailsSlider = new ThumbnailsSlider(this._thumbnailsBox);
 | 
			
		||||
@@ -445,15 +431,20 @@ class ControlsManager extends St.Widget {
 | 
			
		||||
        this.viewSelector.connect('page-changed', this._setVisibility.bind(this));
 | 
			
		||||
        this.viewSelector.connect('page-empty', this._onPageEmpty.bind(this));
 | 
			
		||||
 | 
			
		||||
        let layout = new ControlsLayout();
 | 
			
		||||
        this.actor = new St.Widget({ layout_manager: layout,
 | 
			
		||||
                                     x_expand: true, y_expand: true,
 | 
			
		||||
                                     clip_to_allocation: true });
 | 
			
		||||
        this._group = new St.BoxLayout({ name: 'overview-group',
 | 
			
		||||
                                         x_expand: true, y_expand: true });
 | 
			
		||||
        this.add_actor(this._group);
 | 
			
		||||
        this.actor.add_actor(this._group);
 | 
			
		||||
 | 
			
		||||
        this.add_actor(this._dashSlider);
 | 
			
		||||
        this.actor.add_actor(this._dashSlider.actor);
 | 
			
		||||
 | 
			
		||||
        this._group.add_actor(this._dashSpacer);
 | 
			
		||||
        this._group.add(this.viewSelector, { x_fill: true, expand: true });
 | 
			
		||||
        this._group.add_actor(this._thumbnailsSlider);
 | 
			
		||||
        this._group.add(this.viewSelector.actor, { x_fill: true,
 | 
			
		||||
                                                   expand: true });
 | 
			
		||||
        this._group.add_actor(this._thumbnailsSlider.actor);
 | 
			
		||||
 | 
			
		||||
        layout.connect('allocation-changed', this._updateWorkspacesGeometry.bind(this));
 | 
			
		||||
 | 
			
		||||
@@ -461,18 +452,18 @@ class ControlsManager extends St.Widget {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _updateWorkspacesGeometry() {
 | 
			
		||||
        let [x, y] = this.get_transformed_position();
 | 
			
		||||
        let [width, height] = this.get_transformed_size();
 | 
			
		||||
        let [x, y] = this.actor.get_transformed_position();
 | 
			
		||||
        let [width, height] = this.actor.get_transformed_size();
 | 
			
		||||
        let geometry = { x: x, y: y, width: width, height: height };
 | 
			
		||||
 | 
			
		||||
        let spacing = this.get_theme_node().get_length('spacing');
 | 
			
		||||
        let spacing = this.actor.get_theme_node().get_length('spacing');
 | 
			
		||||
        let dashWidth = this._dashSlider.getVisibleWidth() + spacing;
 | 
			
		||||
        let thumbnailsWidth = this._thumbnailsSlider.getNonExpandedWidth() + spacing;
 | 
			
		||||
 | 
			
		||||
        geometry.width -= dashWidth;
 | 
			
		||||
        geometry.width -= thumbnailsWidth;
 | 
			
		||||
 | 
			
		||||
        if (this.get_text_direction() == Clutter.TextDirection.LTR)
 | 
			
		||||
        if (this.actor.get_text_direction() == Clutter.TextDirection.LTR)
 | 
			
		||||
            geometry.x += dashWidth;
 | 
			
		||||
        else
 | 
			
		||||
            geometry.x += thumbnailsWidth;
 | 
			
		||||
@@ -519,4 +510,4 @@ class ControlsManager extends St.Widget {
 | 
			
		||||
 | 
			
		||||
        this._updateSpacerVisibility();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										178
									
								
								js/ui/padOsd.js
									
									
									
									
									
								
							
							
						
						
									
										178
									
								
								js/ui/padOsd.js
									
									
									
									
									
								
							@@ -1,5 +1,5 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/* exported PadOsd, PadOsdService */
 | 
			
		||||
/* exported PadOsdService */
 | 
			
		||||
 | 
			
		||||
const { Atk, Clutter, GDesktopEnums, Gio,
 | 
			
		||||
        GLib, GObject, Gtk, Meta, Rsvg, St } = imports.gi;
 | 
			
		||||
@@ -22,45 +22,40 @@ const CCW = 1;
 | 
			
		||||
const UP = 0;
 | 
			
		||||
const DOWN = 1;
 | 
			
		||||
 | 
			
		||||
var PadChooser = GObject.registerClass({
 | 
			
		||||
    Signals: { 'pad-selected': { param_types: [Clutter.InputDevice.$gtype] } }
 | 
			
		||||
}, class PadChooser extends St.Button {
 | 
			
		||||
    _init(device, groupDevices) {
 | 
			
		||||
        super._init({
 | 
			
		||||
            style_class: 'pad-chooser-button',
 | 
			
		||||
            toggle_mode: true,
 | 
			
		||||
            x_fill: false,
 | 
			
		||||
            y_fill: false,
 | 
			
		||||
            x_align: St.Align.MIDDLE,
 | 
			
		||||
            y_align: St.Align.MIDDLE
 | 
			
		||||
        });
 | 
			
		||||
var PadChooser = class {
 | 
			
		||||
    constructor(device, groupDevices) {
 | 
			
		||||
        this.actor = new St.Button({ style_class: 'pad-chooser-button',
 | 
			
		||||
                                     toggle_mode: true,
 | 
			
		||||
                                     x_fill: false,
 | 
			
		||||
                                     y_fill: false,
 | 
			
		||||
                                     x_align: St.Align.MIDDLE,
 | 
			
		||||
                                     y_align: St.Align.MIDDLE });
 | 
			
		||||
        this.currentDevice = device;
 | 
			
		||||
        this._padChooserMenu = null;
 | 
			
		||||
 | 
			
		||||
        let arrow = new St.Icon({ style_class: 'popup-menu-arrow',
 | 
			
		||||
                                  icon_name: 'pan-down-symbolic',
 | 
			
		||||
                                  accessible_role: Atk.Role.ARROW });
 | 
			
		||||
        this.set_child(arrow);
 | 
			
		||||
        this.actor.set_child(arrow);
 | 
			
		||||
        this._ensureMenu(groupDevices);
 | 
			
		||||
 | 
			
		||||
        this.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_clicked() {
 | 
			
		||||
        if (this.get_checked()) {
 | 
			
		||||
            if (this._padChooserMenu != null)
 | 
			
		||||
                this._padChooserMenu.open(true);
 | 
			
		||||
            else
 | 
			
		||||
                this.set_checked(false);
 | 
			
		||||
        } else {
 | 
			
		||||
            this._padChooserMenu.close(true);
 | 
			
		||||
        }
 | 
			
		||||
        this.actor.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
        this.actor.connect('clicked', actor => {
 | 
			
		||||
            if (actor.get_checked()) {
 | 
			
		||||
                if (this._padChooserMenu != null)
 | 
			
		||||
                    this._padChooserMenu.open(true);
 | 
			
		||||
                else
 | 
			
		||||
                    this.set_checked(false);
 | 
			
		||||
            } else {
 | 
			
		||||
                this._padChooserMenu.close(true);
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _ensureMenu(devices) {
 | 
			
		||||
        this._padChooserMenu =  new PopupMenu.PopupMenu(this, 0.5, St.Side.TOP);
 | 
			
		||||
        this._padChooserMenu =  new PopupMenu.PopupMenu(this.actor, 0.5, St.Side.TOP);
 | 
			
		||||
        this._padChooserMenu.connect('menu-closed', () => {
 | 
			
		||||
            this.set_checked(false);
 | 
			
		||||
            this.actor.set_checked(false);
 | 
			
		||||
        });
 | 
			
		||||
        this._padChooserMenu.actor.hide();
 | 
			
		||||
        Main.uiGroup.add_actor(this._padChooserMenu.actor);
 | 
			
		||||
@@ -83,20 +78,24 @@ var PadChooser = GObject.registerClass({
 | 
			
		||||
    update(devices) {
 | 
			
		||||
        if (this._padChooserMenu)
 | 
			
		||||
            this._padChooserMenu.actor.destroy();
 | 
			
		||||
        this.set_checked(false);
 | 
			
		||||
        this.actor.set_checked(false);
 | 
			
		||||
        this._ensureMenu(devices);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
var KeybindingEntry = GObject.registerClass({
 | 
			
		||||
    GTypeName: 'PadOsd_KeybindingEntry',
 | 
			
		||||
    Signals: { 'keybinding-edited': {} }
 | 
			
		||||
}, class KeybindingEntry extends St.Entry {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init({ hint_text: _("New shortcut…"), style: 'width: 10em' });
 | 
			
		||||
    destroy() {
 | 
			
		||||
        this.actor.destroy();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(PadChooser.prototype);
 | 
			
		||||
 | 
			
		||||
var KeybindingEntry = class {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        this.actor = new St.Entry({ hint_text: _("New shortcut…"),
 | 
			
		||||
                                    style: 'width: 10em' });
 | 
			
		||||
        this.actor.connect('captured-event', this._onCapturedEvent.bind(this));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_captured_event(event) {
 | 
			
		||||
    _onCapturedEvent(actor, event) {
 | 
			
		||||
        if (event.type() != Clutter.EventType.KEY_PRESS)
 | 
			
		||||
            return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
 | 
			
		||||
@@ -104,24 +103,23 @@ var KeybindingEntry = GObject.registerClass({
 | 
			
		||||
                                                    event.get_key_symbol(),
 | 
			
		||||
                                                    event.get_key_code(),
 | 
			
		||||
                                                    event.get_state());
 | 
			
		||||
        this.set_text(str);
 | 
			
		||||
        this.actor.set_text(str);
 | 
			
		||||
        this.emit('keybinding-edited', str);
 | 
			
		||||
        return Clutter.EVENT_STOP;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(KeybindingEntry.prototype);
 | 
			
		||||
 | 
			
		||||
var ActionComboBox = GObject.registerClass({
 | 
			
		||||
    GTypeName: 'PadOsd_ActionComboBox',
 | 
			
		||||
    Signals: { 'action-selected': { param_types: [GObject.TYPE_INT] } }
 | 
			
		||||
}, class ActionComboBox extends St.Button {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init({ style_class: 'button' });
 | 
			
		||||
        this.set_toggle_mode(true);
 | 
			
		||||
var ActionComboBox = class {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        this.actor = new St.Button({ style_class: 'button' });
 | 
			
		||||
        this.actor.connect('clicked', this._onButtonClicked.bind(this));
 | 
			
		||||
        this.actor.set_toggle_mode(true);
 | 
			
		||||
 | 
			
		||||
        let boxLayout = new Clutter.BoxLayout({ orientation: Clutter.Orientation.HORIZONTAL,
 | 
			
		||||
                                                spacing: 6 });
 | 
			
		||||
        let box = new St.Widget({ layout_manager: boxLayout });
 | 
			
		||||
        this.set_child(box);
 | 
			
		||||
        this.actor.set_child(box);
 | 
			
		||||
 | 
			
		||||
        this._label = new St.Label({ style_class: 'combo-box-label' });
 | 
			
		||||
        box.add_child(this._label);
 | 
			
		||||
@@ -133,9 +131,9 @@ var ActionComboBox = GObject.registerClass({
 | 
			
		||||
                                  y_align: Clutter.ActorAlign.CENTER });
 | 
			
		||||
        box.add_child(arrow);
 | 
			
		||||
 | 
			
		||||
        this._editMenu = new PopupMenu.PopupMenu(this, 0, St.Side.TOP);
 | 
			
		||||
        this._editMenu = new PopupMenu.PopupMenu(this.actor, 0, St.Side.TOP);
 | 
			
		||||
        this._editMenu.connect('menu-closed', () => {
 | 
			
		||||
            this.set_checked(false);
 | 
			
		||||
            this.actor.set_checked(false);
 | 
			
		||||
        });
 | 
			
		||||
        this._editMenu.actor.hide();
 | 
			
		||||
        Main.uiGroup.add_actor(this._editMenu.actor);
 | 
			
		||||
@@ -181,8 +179,8 @@ var ActionComboBox = GObject.registerClass({
 | 
			
		||||
        this._editMenu.close(true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_clicked() {
 | 
			
		||||
        if (this.get_checked())
 | 
			
		||||
    _onButtonClicked() {
 | 
			
		||||
        if (this.actor.get_checked())
 | 
			
		||||
            this.popup();
 | 
			
		||||
        else
 | 
			
		||||
            this.popdown();
 | 
			
		||||
@@ -191,40 +189,38 @@ var ActionComboBox = GObject.registerClass({
 | 
			
		||||
    setButtonActionsActive(active) {
 | 
			
		||||
        this._buttonItems.forEach(item => item.setSensitive(active));
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(ActionComboBox.prototype);
 | 
			
		||||
 | 
			
		||||
var ActionEditor = GObject.registerClass({
 | 
			
		||||
    GTypeName: 'PadOsd_ActionEditor',
 | 
			
		||||
    Signals: { 'done': {} }
 | 
			
		||||
}, class ActionEditor extends St.Widget {
 | 
			
		||||
    _init() {
 | 
			
		||||
var ActionEditor = class {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        let boxLayout = new Clutter.BoxLayout({ orientation: Clutter.Orientation.HORIZONTAL,
 | 
			
		||||
                                                spacing: 12 });
 | 
			
		||||
 | 
			
		||||
        super._init({ layout_manager: boxLayout });
 | 
			
		||||
        this.actor = new St.Widget({ layout_manager: boxLayout });
 | 
			
		||||
 | 
			
		||||
        this._actionComboBox = new ActionComboBox();
 | 
			
		||||
        this._actionComboBox.connect('action-selected', this._onActionSelected.bind(this));
 | 
			
		||||
        this.add_actor(this._actionComboBox);
 | 
			
		||||
        this.actor.add_actor(this._actionComboBox.actor);
 | 
			
		||||
 | 
			
		||||
        this._keybindingEdit = new KeybindingEntry();
 | 
			
		||||
        this._keybindingEdit.connect('keybinding-edited', this._onKeybindingEdited.bind(this));
 | 
			
		||||
        this.add_actor(this._keybindingEdit);
 | 
			
		||||
        this.actor.add_actor(this._keybindingEdit.actor);
 | 
			
		||||
 | 
			
		||||
        this._doneButton = new St.Button({ label: _("Done"),
 | 
			
		||||
                                           style_class: 'button',
 | 
			
		||||
                                           x_expand: false });
 | 
			
		||||
        this._doneButton.connect('clicked', this._onEditingDone.bind(this));
 | 
			
		||||
        this.add_actor(this._doneButton);
 | 
			
		||||
        this.actor.add_actor(this._doneButton);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _updateKeybindingEntryState() {
 | 
			
		||||
        if (this._currentAction == GDesktopEnums.PadButtonAction.KEYBINDING) {
 | 
			
		||||
            this._keybindingEdit.set_text(this._currentKeybinding);
 | 
			
		||||
            this._keybindingEdit.show();
 | 
			
		||||
            this._keybindingEdit.grab_key_focus();
 | 
			
		||||
            this._keybindingEdit.actor.set_text(this._currentKeybinding);
 | 
			
		||||
            this._keybindingEdit.actor.show();
 | 
			
		||||
            this._keybindingEdit.actor.grab_key_focus();
 | 
			
		||||
        } else {
 | 
			
		||||
            this._keybindingEdit.hide();
 | 
			
		||||
            this._keybindingEdit.actor.hide();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -242,7 +238,7 @@ var ActionEditor = GObject.registerClass({
 | 
			
		||||
 | 
			
		||||
    close() {
 | 
			
		||||
        this._actionComboBox.popdown();
 | 
			
		||||
        this.hide();
 | 
			
		||||
        this.actor.hide();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onKeybindingEdited(entry, keybinding) {
 | 
			
		||||
@@ -276,7 +272,8 @@ var ActionEditor = GObject.registerClass({
 | 
			
		||||
        this.close();
 | 
			
		||||
        this.emit('done');
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(ActionEditor.prototype);
 | 
			
		||||
 | 
			
		||||
var PadDiagram = GObject.registerClass({
 | 
			
		||||
    Properties: {
 | 
			
		||||
@@ -618,18 +615,8 @@ var PadDiagram = GObject.registerClass({
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
var PadOsd = GObject.registerClass({
 | 
			
		||||
    Signals: { 'pad-selected': { param_types: [Clutter.InputDevice.$gtype] } }
 | 
			
		||||
}, class PadOsd extends St.BoxLayout {
 | 
			
		||||
    _init(padDevice, settings, imagePath, editionMode, monitorIndex) {
 | 
			
		||||
        super._init({
 | 
			
		||||
            style_class: 'pad-osd-window',
 | 
			
		||||
            vertical: true,
 | 
			
		||||
            x_expand: true,
 | 
			
		||||
            y_expand: true,
 | 
			
		||||
            reactive: true
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
var PadOsd = class {
 | 
			
		||||
    constructor(padDevice, settings, imagePath, editionMode, monitorIndex) {
 | 
			
		||||
        this.padDevice = padDevice;
 | 
			
		||||
        this._groupPads = [padDevice];
 | 
			
		||||
        this._settings = settings;
 | 
			
		||||
@@ -666,18 +653,23 @@ var PadOsd = GObject.registerClass({
 | 
			
		||||
                this._groupPads.push(device);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
        Main.uiGroup.add_actor(this);
 | 
			
		||||
        this.actor = new St.BoxLayout({ style_class: 'pad-osd-window',
 | 
			
		||||
                                        x_expand: true,
 | 
			
		||||
                                        y_expand: true,
 | 
			
		||||
                                        vertical: true,
 | 
			
		||||
                                        reactive: true });
 | 
			
		||||
        this.actor.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
        Main.uiGroup.add_actor(this.actor);
 | 
			
		||||
 | 
			
		||||
        this._monitorIndex = monitorIndex;
 | 
			
		||||
        let constraint = new Layout.MonitorConstraint({ index: monitorIndex });
 | 
			
		||||
        this.add_constraint(constraint);
 | 
			
		||||
        this.actor.add_constraint(constraint);
 | 
			
		||||
 | 
			
		||||
        this._titleBox = new St.BoxLayout({ style_class: 'pad-osd-title-box',
 | 
			
		||||
                                            vertical: false,
 | 
			
		||||
                                            x_expand: false,
 | 
			
		||||
                                            x_align: Clutter.ActorAlign.CENTER });
 | 
			
		||||
        this.add_actor(this._titleBox);
 | 
			
		||||
        this.actor.add_actor(this._titleBox);
 | 
			
		||||
 | 
			
		||||
        let labelBox = new St.BoxLayout({ style_class: 'pad-osd-title-menu-box',
 | 
			
		||||
                                          vertical: true });
 | 
			
		||||
@@ -698,10 +690,10 @@ var PadOsd = GObject.registerClass({
 | 
			
		||||
 | 
			
		||||
        this._padDiagram = new PadDiagram({ image: this._imagePath,
 | 
			
		||||
                                            left_handed: settings.get_boolean('left-handed'),
 | 
			
		||||
                                            editor_actor: this._actionEditor,
 | 
			
		||||
                                            editor_actor: this._actionEditor.actor,
 | 
			
		||||
                                            x_expand: true,
 | 
			
		||||
                                            y_expand: true });
 | 
			
		||||
        this.add_actor(this._padDiagram);
 | 
			
		||||
        this.actor.add_actor(this._padDiagram);
 | 
			
		||||
 | 
			
		||||
        // FIXME: Fix num buttons.
 | 
			
		||||
        let i = 0;
 | 
			
		||||
@@ -732,7 +724,7 @@ var PadOsd = GObject.registerClass({
 | 
			
		||||
                                        x_expand: true,
 | 
			
		||||
                                        x_align: Clutter.ActorAlign.CENTER,
 | 
			
		||||
                                        y_align: Clutter.ActorAlign.CENTER });
 | 
			
		||||
        this.add_actor(buttonBox);
 | 
			
		||||
        this.actor.add_actor(buttonBox);
 | 
			
		||||
        this._editButton = new St.Button({ label: _("Edit…"),
 | 
			
		||||
                                           style_class: 'button',
 | 
			
		||||
                                           x_align: Clutter.ActorAlign.CENTER,
 | 
			
		||||
@@ -743,7 +735,7 @@ var PadOsd = GObject.registerClass({
 | 
			
		||||
        buttonBox.add_actor(this._editButton);
 | 
			
		||||
 | 
			
		||||
        this._syncEditionMode();
 | 
			
		||||
        Main.pushModal(this);
 | 
			
		||||
        Main.pushModal(this.actor);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _updatePadChooser() {
 | 
			
		||||
@@ -753,7 +745,7 @@ var PadOsd = GObject.registerClass({
 | 
			
		||||
                this._padChooser.connect('pad-selected', (chooser, pad) => {
 | 
			
		||||
                    this._requestForOtherPad(pad);
 | 
			
		||||
                });
 | 
			
		||||
                this._titleBox.add_child(this._padChooser);
 | 
			
		||||
                this._titleBox.add_child(this._padChooser.actor);
 | 
			
		||||
            } else {
 | 
			
		||||
                this._padChooser.update(this._groupPads);
 | 
			
		||||
            }
 | 
			
		||||
@@ -926,8 +918,12 @@ var PadOsd = GObject.registerClass({
 | 
			
		||||
        this._syncEditionMode();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    destroy() {
 | 
			
		||||
        this.actor.destroy();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onDestroy() {
 | 
			
		||||
        Main.popModal(this);
 | 
			
		||||
        Main.popModal(this.actor);
 | 
			
		||||
        this._actionEditor.close();
 | 
			
		||||
 | 
			
		||||
        let deviceManager = Clutter.DeviceManager.get_default();
 | 
			
		||||
@@ -945,9 +941,11 @@ var PadOsd = GObject.registerClass({
 | 
			
		||||
            this._capturedEventId = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.actor = null;
 | 
			
		||||
        this.emit('closed');
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(PadOsd.prototype);
 | 
			
		||||
 | 
			
		||||
const PadOsdIface = loadInterfaceXML('org.gnome.Shell.Wacom.PadOsd');
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -20,17 +20,14 @@ var ANIMATION_DELAY = 100;
 | 
			
		||||
var PageIndicators = GObject.registerClass({
 | 
			
		||||
    Signals: { 'page-activated': { param_types: [GObject.TYPE_INT] } }
 | 
			
		||||
}, class PageIndicators extends St.BoxLayout {
 | 
			
		||||
    _init(orientation = Clutter.Orientation.VERTICAL) {
 | 
			
		||||
        let vertical = orientation == Clutter.Orientation.VERTICAL;
 | 
			
		||||
        super._init({
 | 
			
		||||
            style_class: 'page-indicators',
 | 
			
		||||
            vertical,
 | 
			
		||||
            x_expand: true, y_expand: true,
 | 
			
		||||
            x_align: vertical ? Clutter.ActorAlign.END : Clutter.ActorAlign.CENTER,
 | 
			
		||||
            y_align: vertical ? Clutter.ActorAlign.CENTER : Clutter.ActorAlign.END,
 | 
			
		||||
            reactive: true,
 | 
			
		||||
            clip_to_allocation: true
 | 
			
		||||
        });
 | 
			
		||||
    _init(vertical = true) {
 | 
			
		||||
        super._init({ style_class: 'page-indicators',
 | 
			
		||||
                      vertical,
 | 
			
		||||
                      x_expand: true, y_expand: true,
 | 
			
		||||
                      x_align: vertical ? Clutter.ActorAlign.END : Clutter.ActorAlign.CENTER,
 | 
			
		||||
                      y_align: vertical ? Clutter.ActorAlign.CENTER : Clutter.ActorAlign.END,
 | 
			
		||||
                      reactive: true,
 | 
			
		||||
                      clip_to_allocation: true });
 | 
			
		||||
        this._nPages = 0;
 | 
			
		||||
        this._currentPage = undefined;
 | 
			
		||||
        this._reactive = true;
 | 
			
		||||
@@ -96,26 +93,18 @@ var PageIndicators = GObject.registerClass({
 | 
			
		||||
var AnimatedPageIndicators = GObject.registerClass(
 | 
			
		||||
class AnimatedPageIndicators extends PageIndicators {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init();
 | 
			
		||||
        this.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
    }
 | 
			
		||||
        super._init(true);
 | 
			
		||||
 | 
			
		||||
    _onDestroy() {
 | 
			
		||||
        if (this.animateLater) {
 | 
			
		||||
            Meta.later_remove(this.animateLater);
 | 
			
		||||
            this.animateLater = 0;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
        this.connect('notify::mapped', () => {
 | 
			
		||||
            if (!this.mapped)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
    vfunc_map() {
 | 
			
		||||
        super.vfunc_map();
 | 
			
		||||
 | 
			
		||||
        // Implicit animations are skipped for unmapped actors, and our
 | 
			
		||||
        // children aren't mapped yet, so defer to a later handler
 | 
			
		||||
        this.animateLater = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
 | 
			
		||||
            this.animateLater = 0;
 | 
			
		||||
            this.animateIndicators(AnimationDirection.IN);
 | 
			
		||||
            return GLib.SOURCE_REMOVE;
 | 
			
		||||
            // Implicit animations are skipped for unmapped actors, and our
 | 
			
		||||
            // children aren't mapped yet, so defer to a later handler
 | 
			
		||||
            Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
 | 
			
		||||
                this.animateIndicators(AnimationDirection.IN);
 | 
			
		||||
                return GLib.SOURCE_REMOVE;
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										159
									
								
								js/ui/panel.js
									
									
									
									
									
								
							
							
						
						
									
										159
									
								
								js/ui/panel.js
									
									
									
									
									
								
							@@ -235,7 +235,7 @@ var AppMenuButton = GObject.registerClass({
 | 
			
		||||
        this._overviewShowingId = Main.overview.connect('showing', this._sync.bind(this));
 | 
			
		||||
 | 
			
		||||
        this._spinner = new Animation.Spinner(PANEL_ICON_SIZE, true);
 | 
			
		||||
        this._container.add_actor(this._spinner);
 | 
			
		||||
        this._container.add_actor(this._spinner.actor);
 | 
			
		||||
 | 
			
		||||
        let menu = new AppMenu(this);
 | 
			
		||||
        this.setMenu(menu);
 | 
			
		||||
@@ -430,6 +430,9 @@ class ActivitiesButton extends PanelMenu.Button {
 | 
			
		||||
 | 
			
		||||
        this.label_actor = this._label;
 | 
			
		||||
 | 
			
		||||
        this.connect('captured-event', this._onCapturedEvent.bind(this));
 | 
			
		||||
        this.connect_after('key-release-event', this._onKeyRelease.bind(this));
 | 
			
		||||
 | 
			
		||||
        Main.overview.connect('showing', () => {
 | 
			
		||||
            this.add_style_pseudo_class('overview');
 | 
			
		||||
            this.add_accessible_state (Atk.StateType.CHECKED);
 | 
			
		||||
@@ -456,7 +459,7 @@ class ActivitiesButton extends PanelMenu.Button {
 | 
			
		||||
        return DND.DragMotionResult.CONTINUE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_captured_event(event) {
 | 
			
		||||
    _onCapturedEvent(actor, event) {
 | 
			
		||||
        if (event.type() == Clutter.EventType.BUTTON_PRESS ||
 | 
			
		||||
            event.type() == Clutter.EventType.TOUCH_BEGIN) {
 | 
			
		||||
            if (!Main.overview.shouldToggleByCornerOrButton())
 | 
			
		||||
@@ -465,7 +468,9 @@ class ActivitiesButton extends PanelMenu.Button {
 | 
			
		||||
        return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_event(event) {
 | 
			
		||||
    _onEvent(actor, event) {
 | 
			
		||||
        super._onEvent(actor, event);
 | 
			
		||||
 | 
			
		||||
        if (event.type() == Clutter.EventType.TOUCH_END ||
 | 
			
		||||
            event.type() == Clutter.EventType.BUTTON_RELEASE)
 | 
			
		||||
            if (Main.overview.shouldToggleByCornerOrButton())
 | 
			
		||||
@@ -474,16 +479,13 @@ class ActivitiesButton extends PanelMenu.Button {
 | 
			
		||||
        return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_key_release_event(keyEvent) {
 | 
			
		||||
        let ret = super.vfunc_key_release_event(keyEvent);
 | 
			
		||||
        if (ret == Clutter.EVENT_PROPAGATE) {
 | 
			
		||||
            let symbol = keyEvent.keyval;
 | 
			
		||||
            if (symbol == Clutter.KEY_Return || symbol == Clutter.KEY_space) {
 | 
			
		||||
                if (Main.overview.shouldToggleByCornerOrButton())
 | 
			
		||||
                    Main.overview.toggle();
 | 
			
		||||
            }
 | 
			
		||||
    _onKeyRelease(actor, event) {
 | 
			
		||||
        let symbol = event.get_key_symbol();
 | 
			
		||||
        if (symbol == Clutter.KEY_Return || symbol == Clutter.KEY_space) {
 | 
			
		||||
            if (Main.overview.shouldToggleByCornerOrButton())
 | 
			
		||||
                Main.overview.toggle();
 | 
			
		||||
        }
 | 
			
		||||
        return ret;
 | 
			
		||||
        return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _xdndToggleOverview() {
 | 
			
		||||
@@ -499,12 +501,13 @@ class ActivitiesButton extends PanelMenu.Button {
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
var PanelCorner = GObject.registerClass(
 | 
			
		||||
class PanelCorner extends St.DrawingArea {
 | 
			
		||||
    _init(side) {
 | 
			
		||||
var PanelCorner = class {
 | 
			
		||||
    constructor(side) {
 | 
			
		||||
        this._side = side;
 | 
			
		||||
 | 
			
		||||
        super._init({ style_class: 'panel-corner' });
 | 
			
		||||
        this.actor = new St.DrawingArea({ style_class: 'panel-corner' });
 | 
			
		||||
        this.actor.connect('style-changed', this._styleChanged.bind(this));
 | 
			
		||||
        this.actor.connect('repaint', this._repaint.bind(this));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _findRightmostButton(container) {
 | 
			
		||||
@@ -594,7 +597,7 @@ class PanelCorner extends St.DrawingArea {
 | 
			
		||||
            this._buttonStyleChangedSignalId = button.connect('style-changed',
 | 
			
		||||
                () => {
 | 
			
		||||
                    let pseudoClass = button.get_style_pseudo_class();
 | 
			
		||||
                    this.set_style_pseudo_class(pseudoClass);
 | 
			
		||||
                    this.actor.set_style_pseudo_class(pseudoClass);
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            // The corner doesn't support theme transitions, so override
 | 
			
		||||
@@ -603,8 +606,8 @@ class PanelCorner extends St.DrawingArea {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_repaint() {
 | 
			
		||||
        let node = this.get_theme_node();
 | 
			
		||||
    _repaint() {
 | 
			
		||||
        let node = this.actor.get_theme_node();
 | 
			
		||||
 | 
			
		||||
        let cornerRadius = node.get_length("-panel-corner-radius");
 | 
			
		||||
        let borderWidth = node.get_length('-panel-corner-border-width');
 | 
			
		||||
@@ -615,7 +618,7 @@ class PanelCorner extends St.DrawingArea {
 | 
			
		||||
        let overlap = borderColor.alpha != 0;
 | 
			
		||||
        let offsetY = overlap ? 0 : borderWidth;
 | 
			
		||||
 | 
			
		||||
        let cr = this.get_context();
 | 
			
		||||
        let cr = this.actor.get_context();
 | 
			
		||||
        cr.setOperator(Cairo.Operator.SOURCE);
 | 
			
		||||
 | 
			
		||||
        cr.moveTo(0, offsetY);
 | 
			
		||||
@@ -651,17 +654,16 @@ class PanelCorner extends St.DrawingArea {
 | 
			
		||||
        cr.$dispose();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_style_changed() {
 | 
			
		||||
        super.vfunc_style_changed();
 | 
			
		||||
        let node = this.get_theme_node();
 | 
			
		||||
    _styleChanged() {
 | 
			
		||||
        let node = this.actor.get_theme_node();
 | 
			
		||||
 | 
			
		||||
        let cornerRadius = node.get_length("-panel-corner-radius");
 | 
			
		||||
        let borderWidth = node.get_length('-panel-corner-border-width');
 | 
			
		||||
 | 
			
		||||
        this.set_size(cornerRadius, borderWidth + cornerRadius);
 | 
			
		||||
        this.set_anchor_point(0, borderWidth);
 | 
			
		||||
        this.actor.set_size(cornerRadius, borderWidth + cornerRadius);
 | 
			
		||||
        this.actor.set_anchor_point(0, borderWidth);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var AggregateLayout = GObject.registerClass(
 | 
			
		||||
class AggregateLayout extends Clutter.BoxLayout {
 | 
			
		||||
@@ -726,20 +728,20 @@ class AggregateMenu extends PanelMenu.Button {
 | 
			
		||||
        this._nightLight = new imports.ui.status.nightLight.Indicator();
 | 
			
		||||
        this._thunderbolt = new imports.ui.status.thunderbolt.Indicator();
 | 
			
		||||
 | 
			
		||||
        this._indicators.add_child(this._thunderbolt);
 | 
			
		||||
        this._indicators.add_child(this._screencast);
 | 
			
		||||
        this._indicators.add_child(this._location);
 | 
			
		||||
        this._indicators.add_child(this._nightLight);
 | 
			
		||||
        this._indicators.add_child(this._thunderbolt.indicators);
 | 
			
		||||
        this._indicators.add_child(this._screencast.indicators);
 | 
			
		||||
        this._indicators.add_child(this._location.indicators);
 | 
			
		||||
        this._indicators.add_child(this._nightLight.indicators);
 | 
			
		||||
        if (this._network) {
 | 
			
		||||
            this._indicators.add_child(this._network);
 | 
			
		||||
            this._indicators.add_child(this._network.indicators);
 | 
			
		||||
        }
 | 
			
		||||
        if (this._bluetooth) {
 | 
			
		||||
            this._indicators.add_child(this._bluetooth);
 | 
			
		||||
            this._indicators.add_child(this._bluetooth.indicators);
 | 
			
		||||
        }
 | 
			
		||||
        this._indicators.add_child(this._remoteAccess);
 | 
			
		||||
        this._indicators.add_child(this._rfkill);
 | 
			
		||||
        this._indicators.add_child(this._volume);
 | 
			
		||||
        this._indicators.add_child(this._power);
 | 
			
		||||
        this._indicators.add_child(this._remoteAccess.indicators);
 | 
			
		||||
        this._indicators.add_child(this._rfkill.indicators);
 | 
			
		||||
        this._indicators.add_child(this._volume.indicators);
 | 
			
		||||
        this._indicators.add_child(this._power.indicators);
 | 
			
		||||
        this._indicators.add_child(PopupMenu.arrowIcon(St.Side.BOTTOM));
 | 
			
		||||
 | 
			
		||||
        this.menu.addMenuItem(this._volume.menu);
 | 
			
		||||
@@ -797,10 +799,14 @@ class Panel extends St.Widget {
 | 
			
		||||
        this.add_child(this._rightBox);
 | 
			
		||||
 | 
			
		||||
        this._leftCorner = new PanelCorner(St.Side.LEFT);
 | 
			
		||||
        this.add_child(this._leftCorner);
 | 
			
		||||
        this.add_child(this._leftCorner.actor);
 | 
			
		||||
 | 
			
		||||
        this._rightCorner = new PanelCorner(St.Side.RIGHT);
 | 
			
		||||
        this.add_child(this._rightCorner);
 | 
			
		||||
        this.add_child(this._rightCorner.actor);
 | 
			
		||||
 | 
			
		||||
        this.connect('button-press-event', this._onButtonPress.bind(this));
 | 
			
		||||
        this.connect('touch-event', this._onButtonPress.bind(this));
 | 
			
		||||
        this.connect('key-press-event', this._onKeyPress.bind(this));
 | 
			
		||||
 | 
			
		||||
        Main.overview.connect('showing', () => {
 | 
			
		||||
            this.add_style_pseudo_class('overview');
 | 
			
		||||
@@ -889,65 +895,62 @@ class Panel extends St.Widget {
 | 
			
		||||
 | 
			
		||||
        let cornerWidth, cornerHeight;
 | 
			
		||||
 | 
			
		||||
        [, cornerWidth] = this._leftCorner.get_preferred_width(-1);
 | 
			
		||||
        [, cornerHeight] = this._leftCorner.get_preferred_height(-1);
 | 
			
		||||
        [, cornerWidth] = this._leftCorner.actor.get_preferred_width(-1);
 | 
			
		||||
        [, cornerHeight] = this._leftCorner.actor.get_preferred_height(-1);
 | 
			
		||||
        childBox.x1 = 0;
 | 
			
		||||
        childBox.x2 = cornerWidth;
 | 
			
		||||
        childBox.y1 = allocHeight;
 | 
			
		||||
        childBox.y2 = allocHeight + cornerHeight;
 | 
			
		||||
        this._leftCorner.allocate(childBox, flags);
 | 
			
		||||
        this._leftCorner.actor.allocate(childBox, flags);
 | 
			
		||||
 | 
			
		||||
        [, cornerWidth] = this._rightCorner.get_preferred_width(-1);
 | 
			
		||||
        [, cornerHeight] = this._rightCorner.get_preferred_height(-1);
 | 
			
		||||
        [, cornerWidth] = this._rightCorner.actor.get_preferred_width(-1);
 | 
			
		||||
        [, cornerHeight] = this._rightCorner.actor.get_preferred_height(-1);
 | 
			
		||||
        childBox.x1 = allocWidth - cornerWidth;
 | 
			
		||||
        childBox.x2 = allocWidth;
 | 
			
		||||
        childBox.y1 = allocHeight;
 | 
			
		||||
        childBox.y2 = allocHeight + cornerHeight;
 | 
			
		||||
        this._rightCorner.allocate(childBox, flags);
 | 
			
		||||
        this._rightCorner.actor.allocate(childBox, flags);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _tryDragWindow(event) {
 | 
			
		||||
    _onButtonPress(actor, event) {
 | 
			
		||||
        if (Main.modalCount > 0)
 | 
			
		||||
            return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
 | 
			
		||||
        if (event.source != this)
 | 
			
		||||
        if (event.get_source() != actor)
 | 
			
		||||
            return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
 | 
			
		||||
        let { x, y } = event;
 | 
			
		||||
        let dragWindow = this._getDraggableWindowForPosition(x);
 | 
			
		||||
        let type = event.type();
 | 
			
		||||
        let isPress = type == Clutter.EventType.BUTTON_PRESS;
 | 
			
		||||
        if (!isPress && type != Clutter.EventType.TOUCH_BEGIN)
 | 
			
		||||
            return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
 | 
			
		||||
        let button = isPress ? event.get_button() : -1;
 | 
			
		||||
        if (isPress && button != 1)
 | 
			
		||||
            return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
 | 
			
		||||
        let [stageX, stageY] = event.get_coords();
 | 
			
		||||
 | 
			
		||||
        let dragWindow = this._getDraggableWindowForPosition(stageX);
 | 
			
		||||
 | 
			
		||||
        if (!dragWindow)
 | 
			
		||||
            return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
 | 
			
		||||
        return global.display.begin_grab_op(
 | 
			
		||||
            dragWindow,
 | 
			
		||||
            Meta.GrabOp.MOVING,
 | 
			
		||||
            false, /* pointer grab */
 | 
			
		||||
            true, /* frame action */
 | 
			
		||||
            event.button || -1,
 | 
			
		||||
            event.modifier_state,
 | 
			
		||||
            event.time,
 | 
			
		||||
            x, y) ? Clutter.EVENT_STOP : Clutter.EVENT_PROPAGATE;
 | 
			
		||||
        global.display.begin_grab_op(dragWindow,
 | 
			
		||||
                                     Meta.GrabOp.MOVING,
 | 
			
		||||
                                     false, /* pointer grab */
 | 
			
		||||
                                     true, /* frame action */
 | 
			
		||||
                                     button,
 | 
			
		||||
                                     event.get_state(),
 | 
			
		||||
                                     event.get_time(),
 | 
			
		||||
                                     stageX, stageY);
 | 
			
		||||
 | 
			
		||||
        return Clutter.EVENT_STOP;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_button_press_event(buttonEvent) {
 | 
			
		||||
        if (buttonEvent.button != 1)
 | 
			
		||||
            return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
 | 
			
		||||
        return this._tryDragWindow(buttonEvent);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_touch_event(touchEvent) {
 | 
			
		||||
        if (touchEvent.type != Clutter.EventType.TOUCH_BEGIN)
 | 
			
		||||
            return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
 | 
			
		||||
        return this._tryDragWindow(touchEvent);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_key_press_event(keyEvent) {
 | 
			
		||||
        let symbol = keyEvent.keyval;
 | 
			
		||||
    _onKeyPress(actor, event) {
 | 
			
		||||
        let symbol = event.get_key_symbol();
 | 
			
		||||
        if (symbol == Clutter.KEY_Escape) {
 | 
			
		||||
            global.display.focus_default_window(keyEvent.time);
 | 
			
		||||
            global.display.focus_default_window(event.get_time());
 | 
			
		||||
            return Clutter.EVENT_STOP;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -1111,14 +1114,14 @@ class Panel extends St.Widget {
 | 
			
		||||
 | 
			
		||||
    _addStyleClassName(className) {
 | 
			
		||||
        this.add_style_class_name(className);
 | 
			
		||||
        this._rightCorner.add_style_class_name(className);
 | 
			
		||||
        this._leftCorner.add_style_class_name(className);
 | 
			
		||||
        this._rightCorner.actor.add_style_class_name(className);
 | 
			
		||||
        this._leftCorner.actor.add_style_class_name(className);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _removeStyleClassName(className) {
 | 
			
		||||
        this.remove_style_class_name(className);
 | 
			
		||||
        this._rightCorner.remove_style_class_name(className);
 | 
			
		||||
        this._leftCorner.remove_style_class_name(className);
 | 
			
		||||
        this._rightCorner.actor.remove_style_class_name(className);
 | 
			
		||||
        this._leftCorner.actor.remove_style_class_name(className);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onMenuSet(indicator) {
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,7 @@
 | 
			
		||||
/* exported Button, SystemIndicator */
 | 
			
		||||
 | 
			
		||||
const { Atk, Clutter, GObject, St } = imports.gi;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const Params = imports.misc.params;
 | 
			
		||||
@@ -100,6 +101,9 @@ var Button = GObject.registerClass({
 | 
			
		||||
                      accessible_name: nameText ? nameText : "",
 | 
			
		||||
                      accessible_role: Atk.Role.MENU });
 | 
			
		||||
 | 
			
		||||
        this.connect('event', this._onEvent.bind(this));
 | 
			
		||||
        this.connect('notify::visible', this._onVisibilityChanged.bind(this));
 | 
			
		||||
 | 
			
		||||
        if (dontCreateMenu)
 | 
			
		||||
            this.menu = new PopupMenu.PopupDummyMenu(this);
 | 
			
		||||
        else
 | 
			
		||||
@@ -128,7 +132,7 @@ var Button = GObject.registerClass({
 | 
			
		||||
        this.emit('menu-set');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_event(event) {
 | 
			
		||||
    _onEvent(actor, event) {
 | 
			
		||||
        if (this.menu &&
 | 
			
		||||
            (event.type() == Clutter.EventType.TOUCH_BEGIN ||
 | 
			
		||||
             event.type() == Clutter.EventType.BUTTON_PRESS))
 | 
			
		||||
@@ -137,10 +141,11 @@ var Button = GObject.registerClass({
 | 
			
		||||
        return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_hide() {
 | 
			
		||||
        super.vfunc_hide();
 | 
			
		||||
    _onVisibilityChanged() {
 | 
			
		||||
        if (!this.menu)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (this.menu)
 | 
			
		||||
        if (!this.visible)
 | 
			
		||||
            this.menu.close();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -195,34 +200,24 @@ var Button = GObject.registerClass({
 | 
			
		||||
 * of an icon and a menu section, which will be composed into the
 | 
			
		||||
 * aggregate menu.
 | 
			
		||||
 */
 | 
			
		||||
var SystemIndicator = GObject.registerClass({
 | 
			
		||||
    GTypeName: 'PanelMenu_SystemIndicator',
 | 
			
		||||
}, class SystemIndicator extends St.BoxLayout {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init({
 | 
			
		||||
            style_class: 'panel-status-indicators-box',
 | 
			
		||||
            reactive: true,
 | 
			
		||||
            visible: false
 | 
			
		||||
        });
 | 
			
		||||
var SystemIndicator = class {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        this.indicators = new St.BoxLayout({ style_class: 'panel-status-indicators-box',
 | 
			
		||||
                                             reactive: true });
 | 
			
		||||
        this.indicators.hide();
 | 
			
		||||
        this.menu = new PopupMenu.PopupMenuSection();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get indicators() {
 | 
			
		||||
        let klass = this.constructor.name;
 | 
			
		||||
        let { stack } = new Error();
 | 
			
		||||
        log(`Usage of indicator.indicators is deprecated for ${klass}\n${stack}`);
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _syncIndicatorsVisible() {
 | 
			
		||||
        this.visible = this.get_children().some(a => a.visible);
 | 
			
		||||
        this.indicators.visible = this.indicators.get_children().some(a => a.visible);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _addIndicator() {
 | 
			
		||||
        let icon = new St.Icon({ style_class: 'system-status-icon' });
 | 
			
		||||
        this.add_actor(icon);
 | 
			
		||||
        this.indicators.add_actor(icon);
 | 
			
		||||
        icon.connect('notify::visible', this._syncIndicatorsVisible.bind(this));
 | 
			
		||||
        this._syncIndicatorsVisible();
 | 
			
		||||
        return icon;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(SystemIndicator.prototype);
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
            PopupImageMenuItem, PopupMenu, PopupDummyMenu, PopupSubMenu,
 | 
			
		||||
            PopupMenuSection, PopupSubMenuMenuItem, PopupMenuManager */
 | 
			
		||||
 | 
			
		||||
const { Atk, Clutter, Gio, GObject, Graphene, Shell, St } = imports.gi;
 | 
			
		||||
const { Atk, Clutter, Gio, GObject, Shell, St } = imports.gi;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
 | 
			
		||||
const BoxPointer = imports.ui.boxpointer;
 | 
			
		||||
@@ -97,6 +97,12 @@ var PopupBaseMenuItem = GObject.registerClass({
 | 
			
		||||
        if (params.style_class)
 | 
			
		||||
            this.add_style_class_name(params.style_class);
 | 
			
		||||
 | 
			
		||||
        if (this._activatable) {
 | 
			
		||||
            this.connect('button-press-event', this._onButtonPressEvent.bind(this));
 | 
			
		||||
            this.connect('button-release-event', this._onButtonReleaseEvent.bind(this));
 | 
			
		||||
            this.connect('touch-event', this._onTouchEvent.bind(this));
 | 
			
		||||
            this.connect('key-press-event', this._onKeyPressEvent.bind(this));
 | 
			
		||||
        }
 | 
			
		||||
        if (params.reactive && params.hover)
 | 
			
		||||
            this.bind_property('hover', this, 'active', GObject.BindingFlags.SYNC_CREATE);
 | 
			
		||||
    }
 | 
			
		||||
@@ -118,44 +124,32 @@ var PopupBaseMenuItem = GObject.registerClass({
 | 
			
		||||
        this._parent = parent;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_button_press_event(buttonEvent) {
 | 
			
		||||
        if (!this._activatable)
 | 
			
		||||
            return super.vfunc_button_press_event(buttonEvent);
 | 
			
		||||
 | 
			
		||||
    _onButtonPressEvent() {
 | 
			
		||||
        // This is the CSS active state
 | 
			
		||||
        this.add_style_pseudo_class('active');
 | 
			
		||||
        return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_button_release_event(buttonEvent) {
 | 
			
		||||
        if (!this._activatable)
 | 
			
		||||
            return super.vfunc_button_release_event(buttonEvent);
 | 
			
		||||
 | 
			
		||||
    _onButtonReleaseEvent(actor, event) {
 | 
			
		||||
        this.remove_style_pseudo_class('active');
 | 
			
		||||
        this.activate(Clutter.get_current_event());
 | 
			
		||||
        this.activate(event);
 | 
			
		||||
        return Clutter.EVENT_STOP;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_touch_event(touchEvent) {
 | 
			
		||||
        if (!this._activatable)
 | 
			
		||||
            return super.vfunc_touch_event(touchEvent);
 | 
			
		||||
 | 
			
		||||
        if (touchEvent.type == Clutter.EventType.TOUCH_END) {
 | 
			
		||||
    _onTouchEvent(actor, event) {
 | 
			
		||||
        if (event.type() == Clutter.EventType.TOUCH_END) {
 | 
			
		||||
            this.remove_style_pseudo_class('active');
 | 
			
		||||
            this.activate(Clutter.get_current_event());
 | 
			
		||||
            this.activate(event);
 | 
			
		||||
            return Clutter.EVENT_STOP;
 | 
			
		||||
        } else if (touchEvent.type == Clutter.EventType.TOUCH_BEGIN) {
 | 
			
		||||
        } else if (event.type() == Clutter.EventType.TOUCH_BEGIN) {
 | 
			
		||||
            // This is the CSS active state
 | 
			
		||||
            this.add_style_pseudo_class('active');
 | 
			
		||||
        }
 | 
			
		||||
        return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_key_press_event(keyEvent) {
 | 
			
		||||
        if (!this._activatable)
 | 
			
		||||
            return super.vfunc_key_press_event(keyEvent);
 | 
			
		||||
 | 
			
		||||
        let state = keyEvent.modifier_state;
 | 
			
		||||
    _onKeyPressEvent(actor, event) {
 | 
			
		||||
        let state = event.get_state();
 | 
			
		||||
 | 
			
		||||
        // if user has a modifier down (except capslock and numlock)
 | 
			
		||||
        // then don't handle the key press here
 | 
			
		||||
@@ -166,9 +160,9 @@ var PopupBaseMenuItem = GObject.registerClass({
 | 
			
		||||
        if (state)
 | 
			
		||||
            return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
 | 
			
		||||
        let symbol = keyEvent.keyval;
 | 
			
		||||
        let symbol = event.get_key_symbol();
 | 
			
		||||
        if (symbol == Clutter.KEY_space || symbol == Clutter.KEY_Return) {
 | 
			
		||||
            this.activate(Clutter.get_current_event());
 | 
			
		||||
            this.activate(event);
 | 
			
		||||
            return Clutter.EVENT_STOP;
 | 
			
		||||
        }
 | 
			
		||||
        return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
@@ -1136,7 +1130,7 @@ class PopupSubMenuMenuItem extends PopupBaseMenuItem {
 | 
			
		||||
        this.add(expander, { expand: true });
 | 
			
		||||
 | 
			
		||||
        this._triangle = arrowIcon(St.Side.RIGHT);
 | 
			
		||||
        this._triangle.pivot_point = new Graphene.Point({ x: 0.5, y: 0.6 });
 | 
			
		||||
        this._triangle.pivot_point = new Clutter.Point({ x: 0.5, y: 0.6 });
 | 
			
		||||
 | 
			
		||||
        this._triangleBin = new St.Widget({ y_expand: true,
 | 
			
		||||
                                            y_align: Clutter.ActorAlign.CENTER });
 | 
			
		||||
@@ -1191,8 +1185,8 @@ class PopupSubMenuMenuItem extends PopupBaseMenuItem {
 | 
			
		||||
        return this.menu.isOpen;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_key_press_event(keyPressEvent) {
 | 
			
		||||
        let symbol = keyPressEvent.keyval;
 | 
			
		||||
    _onKeyPressEvent(actor, event) {
 | 
			
		||||
        let symbol = event.get_key_symbol();
 | 
			
		||||
 | 
			
		||||
        if (symbol == Clutter.KEY_Right) {
 | 
			
		||||
            this._setOpenState(true);
 | 
			
		||||
@@ -1203,14 +1197,14 @@ class PopupSubMenuMenuItem extends PopupBaseMenuItem {
 | 
			
		||||
            return Clutter.EVENT_STOP;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return super.vfunc_key_press_event(keyPressEvent);
 | 
			
		||||
        return super._onKeyPressEvent(actor, event);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    activate(_event) {
 | 
			
		||||
        this._setOpenState(true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_button_release_event() {
 | 
			
		||||
    _onButtonReleaseEvent() {
 | 
			
		||||
        // Since we override the parent, we need to manage what the parent does
 | 
			
		||||
        // with the active style class
 | 
			
		||||
        this.remove_style_pseudo_class('active');
 | 
			
		||||
@@ -1218,8 +1212,8 @@ class PopupSubMenuMenuItem extends PopupBaseMenuItem {
 | 
			
		||||
        return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_touch_event(touchEvent) {
 | 
			
		||||
        if (touchEvent.type == Clutter.EventType.TOUCH_END) {
 | 
			
		||||
    _onTouchEvent(actor, event) {
 | 
			
		||||
        if (event.type() == Clutter.EventType.TOUCH_END) {
 | 
			
		||||
            // Since we override the parent, we need to manage what the parent does
 | 
			
		||||
            // with the active style class
 | 
			
		||||
            this.remove_style_pseudo_class('active');
 | 
			
		||||
 
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,7 +1,8 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/* exported ScreenshotService */
 | 
			
		||||
 | 
			
		||||
const { Clutter, Graphene, Gio, GObject, GLib, Meta, Shell, St } = imports.gi;
 | 
			
		||||
const { Clutter, Gio, GLib, Meta, Shell, St } = imports.gi;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
 | 
			
		||||
const GrabHelper = imports.ui.grabHelper;
 | 
			
		||||
const Lightbox = imports.ui.lightbox;
 | 
			
		||||
@@ -197,7 +198,7 @@ var ScreenshotService = class {
 | 
			
		||||
                let screenshot = this._createScreenshot(invocation, false);
 | 
			
		||||
                if (!screenshot)
 | 
			
		||||
                    return;
 | 
			
		||||
                screenshot.pick_color(coords.x, coords.y, (_o, res) => {
 | 
			
		||||
                screenshot.pick_color(...coords, (o, res) => {
 | 
			
		||||
                    let [success_, color] = screenshot.pick_color_finish(res);
 | 
			
		||||
                    let { red, green, blue } = color;
 | 
			
		||||
                    let retval = GLib.Variant.new('(a{sv})', [{
 | 
			
		||||
@@ -218,62 +219,62 @@ var ScreenshotService = class {
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var SelectArea = GObject.registerClass({
 | 
			
		||||
    GTypeName: 'Screenshot_SelectArea',
 | 
			
		||||
    Signals: { 'finished': { param_types: [Meta.Rectangle.$gtype] } }
 | 
			
		||||
}, class SelectArea extends St.Widget {
 | 
			
		||||
    _init() {
 | 
			
		||||
var SelectArea = class {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        this._startX = -1;
 | 
			
		||||
        this._startY = -1;
 | 
			
		||||
        this._lastX = 0;
 | 
			
		||||
        this._lastY = 0;
 | 
			
		||||
        this._result = null;
 | 
			
		||||
 | 
			
		||||
        super._init({
 | 
			
		||||
            visible: false,
 | 
			
		||||
            reactive: true,
 | 
			
		||||
            x: 0,
 | 
			
		||||
            y: 0
 | 
			
		||||
        });
 | 
			
		||||
        Main.uiGroup.add_actor(this);
 | 
			
		||||
        this._group = new St.Widget({ visible: false,
 | 
			
		||||
                                      reactive: true,
 | 
			
		||||
                                      x: 0,
 | 
			
		||||
                                      y: 0 });
 | 
			
		||||
        Main.uiGroup.add_actor(this._group);
 | 
			
		||||
 | 
			
		||||
        this._grabHelper = new GrabHelper.GrabHelper(this);
 | 
			
		||||
        this._grabHelper = new GrabHelper.GrabHelper(this._group);
 | 
			
		||||
 | 
			
		||||
        this._group.connect('button-press-event',
 | 
			
		||||
                            this._onButtonPress.bind(this));
 | 
			
		||||
        this._group.connect('button-release-event',
 | 
			
		||||
                            this._onButtonRelease.bind(this));
 | 
			
		||||
        this._group.connect('motion-event',
 | 
			
		||||
                            this._onMotionEvent.bind(this));
 | 
			
		||||
 | 
			
		||||
        let constraint = new Clutter.BindConstraint({ source: global.stage,
 | 
			
		||||
                                                      coordinate: Clutter.BindCoordinate.ALL });
 | 
			
		||||
        this.add_constraint(constraint);
 | 
			
		||||
        this._group.add_constraint(constraint);
 | 
			
		||||
 | 
			
		||||
        this._rubberband = new St.Widget({
 | 
			
		||||
            style_class: 'select-area-rubberband',
 | 
			
		||||
            visible: false
 | 
			
		||||
        });
 | 
			
		||||
        this.add_actor(this._rubberband);
 | 
			
		||||
        this._group.add_actor(this._rubberband);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_show() {
 | 
			
		||||
        if (!this._grabHelper.grab({ actor: this,
 | 
			
		||||
    show() {
 | 
			
		||||
        if (!this._grabHelper.grab({ actor: this._group,
 | 
			
		||||
                                     onUngrab: this._onUngrab.bind(this) }))
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        global.display.set_cursor(Meta.Cursor.CROSSHAIR);
 | 
			
		||||
        Main.uiGroup.set_child_above_sibling(this, null);
 | 
			
		||||
        super.vfunc_show();
 | 
			
		||||
        Main.uiGroup.set_child_above_sibling(this._group, null);
 | 
			
		||||
        this._group.visible = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _getGeometry() {
 | 
			
		||||
        return new Meta.Rectangle({
 | 
			
		||||
            x: Math.min(this._startX, this._lastX),
 | 
			
		||||
            y: Math.min(this._startY, this._lastY),
 | 
			
		||||
            width: Math.abs(this._startX - this._lastX) + 1,
 | 
			
		||||
            height: Math.abs(this._startY - this._lastY) + 1
 | 
			
		||||
        });
 | 
			
		||||
        return { x: Math.min(this._startX, this._lastX),
 | 
			
		||||
                 y: Math.min(this._startY, this._lastY),
 | 
			
		||||
                 width: Math.abs(this._startX - this._lastX) + 1,
 | 
			
		||||
                 height: Math.abs(this._startY - this._lastY) + 1 };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_motion_event(motionEvent) {
 | 
			
		||||
    _onMotionEvent(actor, event) {
 | 
			
		||||
        if (this._startX == -1 || this._startY == -1 || this._result)
 | 
			
		||||
            return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
 | 
			
		||||
        [this._lastX, this._lastY] = [motionEvent.x, motionEvent.y];
 | 
			
		||||
        [this._lastX, this._lastY] = event.get_coords();
 | 
			
		||||
        this._lastX = Math.floor(this._lastX);
 | 
			
		||||
        this._lastY = Math.floor(this._lastY);
 | 
			
		||||
        let geometry = this._getGeometry();
 | 
			
		||||
@@ -285,8 +286,8 @@ var SelectArea = GObject.registerClass({
 | 
			
		||||
        return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_button_press_event(buttonEvent) {
 | 
			
		||||
        [this._startX, this._startY] = [buttonEvent.x, buttonEvent.y];
 | 
			
		||||
    _onButtonPress(actor, event) {
 | 
			
		||||
        [this._startX, this._startY] = event.get_coords();
 | 
			
		||||
        this._startX = Math.floor(this._startX);
 | 
			
		||||
        this._startY = Math.floor(this._startY);
 | 
			
		||||
        this._rubberband.set_position(this._startX, this._startY);
 | 
			
		||||
@@ -294,9 +295,9 @@ var SelectArea = GObject.registerClass({
 | 
			
		||||
        return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_button_release_event() {
 | 
			
		||||
    _onButtonRelease() {
 | 
			
		||||
        this._result = this._getGeometry();
 | 
			
		||||
        this.ease({
 | 
			
		||||
        this._group.ease({
 | 
			
		||||
            opacity: 0,
 | 
			
		||||
            duration: 200,
 | 
			
		||||
            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
 | 
			
		||||
@@ -310,43 +311,43 @@ var SelectArea = GObject.registerClass({
 | 
			
		||||
        this.emit('finished', this._result);
 | 
			
		||||
 | 
			
		||||
        GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {
 | 
			
		||||
            this.destroy();
 | 
			
		||||
            this._group.destroy();
 | 
			
		||||
            return GLib.SOURCE_REMOVE;
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
var PickPixel = GObject.registerClass({
 | 
			
		||||
    GTypeName: 'Screenshot_PickPixel',
 | 
			
		||||
    Signals: { 'finished': { param_types: [Graphene.Point.$gtype] } }
 | 
			
		||||
}, class PickPixel extends St.Widget {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init({ visible: false, reactive: true });
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(SelectArea.prototype);
 | 
			
		||||
 | 
			
		||||
var PickPixel = class {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        this._result = null;
 | 
			
		||||
 | 
			
		||||
        Main.uiGroup.add_actor(this);
 | 
			
		||||
        this._group = new St.Widget({ visible: false,
 | 
			
		||||
                                      reactive: true });
 | 
			
		||||
        Main.uiGroup.add_actor(this._group);
 | 
			
		||||
 | 
			
		||||
        this._grabHelper = new GrabHelper.GrabHelper(this);
 | 
			
		||||
        this._grabHelper = new GrabHelper.GrabHelper(this._group);
 | 
			
		||||
 | 
			
		||||
        this._group.connect('button-release-event',
 | 
			
		||||
                            this._onButtonRelease.bind(this));
 | 
			
		||||
 | 
			
		||||
        let constraint = new Clutter.BindConstraint({ source: global.stage,
 | 
			
		||||
                                                      coordinate: Clutter.BindCoordinate.ALL });
 | 
			
		||||
        this.add_constraint(constraint);
 | 
			
		||||
        this._group.add_constraint(constraint);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_show() {
 | 
			
		||||
        if (!this._grabHelper.grab({ actor: this,
 | 
			
		||||
    show() {
 | 
			
		||||
        if (!this._grabHelper.grab({ actor: this._group,
 | 
			
		||||
                                     onUngrab: this._onUngrab.bind(this) }))
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        global.display.set_cursor(Meta.Cursor.CROSSHAIR);
 | 
			
		||||
        Main.uiGroup.set_child_above_sibling(this, null);
 | 
			
		||||
        super.vfunc_show();
 | 
			
		||||
        Main.uiGroup.set_child_above_sibling(this._group, null);
 | 
			
		||||
        this._group.visible = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_button_release_event(buttonEvent) {
 | 
			
		||||
        let { x, y } = buttonEvent;
 | 
			
		||||
        this._result = new Graphene.Point({ x, y });
 | 
			
		||||
    _onButtonRelease(actor, event) {
 | 
			
		||||
        this._result = event.get_coords();
 | 
			
		||||
        this._grabHelper.ungrab();
 | 
			
		||||
        return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
    }
 | 
			
		||||
@@ -356,29 +357,29 @@ var PickPixel = GObject.registerClass({
 | 
			
		||||
        this.emit('finished', this._result);
 | 
			
		||||
 | 
			
		||||
        GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {
 | 
			
		||||
            this.destroy();
 | 
			
		||||
            this._group.destroy();
 | 
			
		||||
            return GLib.SOURCE_REMOVE;
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(PickPixel.prototype);
 | 
			
		||||
 | 
			
		||||
var FLASHSPOT_ANIMATION_OUT_TIME = 500; // milliseconds
 | 
			
		||||
 | 
			
		||||
var Flashspot = GObject.registerClass(
 | 
			
		||||
class Flashspot extends Lightbox.Lightbox {
 | 
			
		||||
    _init(area) {
 | 
			
		||||
        super._init(Main.uiGroup, {
 | 
			
		||||
            inhibitEvents: true,
 | 
			
		||||
            width: area.width,
 | 
			
		||||
            height: area.height
 | 
			
		||||
        });
 | 
			
		||||
        this.style_class = 'flashspot';
 | 
			
		||||
        this.set_position(area.x, area.y);
 | 
			
		||||
var Flashspot = class extends Lightbox.Lightbox {
 | 
			
		||||
    constructor(area) {
 | 
			
		||||
        super(Main.uiGroup, { inhibitEvents: true,
 | 
			
		||||
                              width: area.width,
 | 
			
		||||
                              height: area.height });
 | 
			
		||||
 | 
			
		||||
        this.actor.style_class = 'flashspot';
 | 
			
		||||
        this.actor.set_position(area.x, area.y);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fire(doneCallback) {
 | 
			
		||||
        this.set({ visible: true, opacity: 255 });
 | 
			
		||||
        this.ease({
 | 
			
		||||
        this.actor.show();
 | 
			
		||||
        this.actor.opacity = 255;
 | 
			
		||||
        this.actor.ease({
 | 
			
		||||
            opacity: 0,
 | 
			
		||||
            duration: FLASHSPOT_ANIMATION_OUT_TIME,
 | 
			
		||||
            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
 | 
			
		||||
@@ -389,4 +390,4 @@ class Flashspot extends Lightbox.Lightbox {
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										233
									
								
								js/ui/search.js
									
									
									
									
									
								
							
							
						
						
									
										233
									
								
								js/ui/search.js
									
									
									
									
									
								
							@@ -1,7 +1,7 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/* exported SearchResultsView, SearchResultInterface */
 | 
			
		||||
 | 
			
		||||
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
 | 
			
		||||
const AppDisplay = imports.ui.appDisplay;
 | 
			
		||||
const IconGrid = imports.ui.iconGrid;
 | 
			
		||||
@@ -32,56 +32,39 @@ class MaxWidthBox extends St.BoxLayout {
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
var SearchResultInterface = GObject.registerClass({
 | 
			
		||||
    Requires: [Clutter.Actor],
 | 
			
		||||
}, class SearchResultInterface extends GObject.Interface {
 | 
			
		||||
    activate() {
 | 
			
		||||
        throw new GObject.NotImplementedError('activate in %s'.format(this.constructor.name));
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
var SearchResult = GObject.registerClass({
 | 
			
		||||
    Implements: [SearchResultInterface]
 | 
			
		||||
}, class SearchResult extends St.Button {
 | 
			
		||||
    _init(provider, metaInfo, resultsView) {
 | 
			
		||||
var SearchResult = class {
 | 
			
		||||
    constructor(provider, metaInfo, resultsView) {
 | 
			
		||||
        this.provider = provider;
 | 
			
		||||
        this.metaInfo = metaInfo;
 | 
			
		||||
        this._resultsView = resultsView;
 | 
			
		||||
 | 
			
		||||
        super._init({
 | 
			
		||||
            reactive: true,
 | 
			
		||||
            can_focus: true,
 | 
			
		||||
            track_hover: true,
 | 
			
		||||
            x_align: St.Align.START,
 | 
			
		||||
            y_fill: true
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
        this.actor = new St.Button({ reactive: true,
 | 
			
		||||
                                     can_focus: true,
 | 
			
		||||
                                     track_hover: true,
 | 
			
		||||
                                     x_align: St.Align.START,
 | 
			
		||||
                                     y_fill: true });
 | 
			
		||||
 | 
			
		||||
    vfunc_clicked() {
 | 
			
		||||
        this.activate();
 | 
			
		||||
        this.actor._delegate = this;
 | 
			
		||||
        this.actor.connect('clicked', this.activate.bind(this));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    activate() {
 | 
			
		||||
        this.provider.activateResult(this.metaInfo.id, this._resultsView.terms);
 | 
			
		||||
 | 
			
		||||
        if (this.metaInfo.clipboardText)
 | 
			
		||||
            St.Clipboard.get_default().set_text(
 | 
			
		||||
                St.ClipboardType.CLIPBOARD, this.metaInfo.clipboardText);
 | 
			
		||||
        Main.overview.toggle();
 | 
			
		||||
        this.emit('activate', this.metaInfo.id);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(SearchResult.prototype);
 | 
			
		||||
 | 
			
		||||
var ListSearchResult = GObject.registerClass(
 | 
			
		||||
class ListSearchResult extends SearchResult {
 | 
			
		||||
    _init(provider, metaInfo, resultsView) {
 | 
			
		||||
        super._init(provider, metaInfo, resultsView);
 | 
			
		||||
var ListSearchResult = class extends SearchResult {
 | 
			
		||||
 | 
			
		||||
        this.style_class = 'list-search-result';
 | 
			
		||||
        this.x_fill = true;
 | 
			
		||||
    constructor(provider, metaInfo, resultsView) {
 | 
			
		||||
        super(provider, metaInfo, resultsView);
 | 
			
		||||
 | 
			
		||||
        this.actor.style_class = 'list-search-result';
 | 
			
		||||
        this.actor.x_fill = true;
 | 
			
		||||
 | 
			
		||||
        let content = new St.BoxLayout({ style_class: 'list-search-result-content',
 | 
			
		||||
                                         vertical: false });
 | 
			
		||||
        this.set_child(content);
 | 
			
		||||
        this.actor.set_child(content);
 | 
			
		||||
 | 
			
		||||
        this._termsChangedId = 0;
 | 
			
		||||
 | 
			
		||||
@@ -104,7 +87,7 @@ class ListSearchResult extends SearchResult {
 | 
			
		||||
                              x_align: St.Align.START,
 | 
			
		||||
                              y_align: St.Align.MIDDLE });
 | 
			
		||||
 | 
			
		||||
        this.label_actor = title;
 | 
			
		||||
        this.actor.label_actor = title;
 | 
			
		||||
 | 
			
		||||
        if (this.metaInfo['description']) {
 | 
			
		||||
            this._descriptionLabel = new St.Label({ style_class: 'list-search-result-description' });
 | 
			
		||||
@@ -120,7 +103,7 @@ class ListSearchResult extends SearchResult {
 | 
			
		||||
            this._highlightTerms();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
        this.actor.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get ICON_SIZE() {
 | 
			
		||||
@@ -137,53 +120,50 @@ class ListSearchResult extends SearchResult {
 | 
			
		||||
            this._resultsView.disconnect(this._termsChangedId);
 | 
			
		||||
        this._termsChangedId = 0;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var GridSearchResult = GObject.registerClass(
 | 
			
		||||
class GridSearchResult extends SearchResult {
 | 
			
		||||
    _init(provider, metaInfo, resultsView) {
 | 
			
		||||
        super._init(provider, metaInfo, resultsView);
 | 
			
		||||
var GridSearchResult = class extends SearchResult {
 | 
			
		||||
    constructor(provider, metaInfo, resultsView) {
 | 
			
		||||
        super(provider, metaInfo, resultsView);
 | 
			
		||||
 | 
			
		||||
        this.style_class = 'grid-search-result';
 | 
			
		||||
        this.actor.style_class = 'grid-search-result';
 | 
			
		||||
 | 
			
		||||
        this.icon = new IconGrid.BaseIcon(this.metaInfo['name'],
 | 
			
		||||
                                          { createIcon: this.metaInfo['createIcon'] });
 | 
			
		||||
        let content = new St.Bin({ child: this.icon });
 | 
			
		||||
        this.set_child(content);
 | 
			
		||||
        this.label_actor = this.icon.label;
 | 
			
		||||
        this.actor.set_child(content);
 | 
			
		||||
        this.actor.label_actor = this.icon.label;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
var SearchResultsBase = GObject.registerClass({
 | 
			
		||||
    GTypeFlags: GObject.TypeFlags.ABSTRACT,
 | 
			
		||||
    Properties: {
 | 
			
		||||
        'focus-child': GObject.ParamSpec.object(
 | 
			
		||||
            'focus-child', 'focus-child', 'focus-child',
 | 
			
		||||
            GObject.ParamFlags.READABLE,
 | 
			
		||||
            Clutter.Actor.$gtype),
 | 
			
		||||
    }
 | 
			
		||||
}, class SearchResultsBase extends St.BoxLayout {
 | 
			
		||||
    _init(provider, resultsView) {
 | 
			
		||||
        super._init({ style_class: 'search-section', vertical: true });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var SearchResultsBase = class {
 | 
			
		||||
    constructor(provider, resultsView) {
 | 
			
		||||
        this.provider = provider;
 | 
			
		||||
        this._resultsView = resultsView;
 | 
			
		||||
 | 
			
		||||
        this._terms = [];
 | 
			
		||||
        this._focusChild = null;
 | 
			
		||||
 | 
			
		||||
        this.actor = new St.BoxLayout({ style_class: 'search-section',
 | 
			
		||||
                                        vertical: true });
 | 
			
		||||
 | 
			
		||||
        this._resultDisplayBin = new St.Bin({ x_fill: true,
 | 
			
		||||
                                              y_fill: true });
 | 
			
		||||
        this.add(this._resultDisplayBin, { expand: true });
 | 
			
		||||
        this.actor.add(this._resultDisplayBin, { expand: true });
 | 
			
		||||
 | 
			
		||||
        let separator = new St.Widget({ style_class: 'search-section-separator' });
 | 
			
		||||
        this.add(separator);
 | 
			
		||||
        this.actor.add(separator);
 | 
			
		||||
 | 
			
		||||
        this._resultDisplays = {};
 | 
			
		||||
 | 
			
		||||
        this._clipboard = St.Clipboard.get_default();
 | 
			
		||||
 | 
			
		||||
        this._cancellable = new Gio.Cancellable();
 | 
			
		||||
 | 
			
		||||
        this.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
        this.actor.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    destroy() {
 | 
			
		||||
        this.actor.destroy();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onDestroy() {
 | 
			
		||||
@@ -200,21 +180,21 @@ var SearchResultsBase = GObject.registerClass({
 | 
			
		||||
    clear() {
 | 
			
		||||
        this._cancellable.cancel();
 | 
			
		||||
        for (let resultId in this._resultDisplays)
 | 
			
		||||
            this._resultDisplays[resultId].destroy();
 | 
			
		||||
            this._resultDisplays[resultId].actor.destroy();
 | 
			
		||||
        this._resultDisplays = {};
 | 
			
		||||
        this._clearResultDisplay();
 | 
			
		||||
        this.hide();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get focusChild() {
 | 
			
		||||
        return this._focusChild;
 | 
			
		||||
        this.actor.hide();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _keyFocusIn(actor) {
 | 
			
		||||
        if (this._focusChild == actor)
 | 
			
		||||
            return;
 | 
			
		||||
        this._focusChild = actor;
 | 
			
		||||
        this.notify('focus-child');
 | 
			
		||||
        this.emit('key-focus-in', actor);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _activateResult(result, id) {
 | 
			
		||||
        this.provider.activateResult(id, this._terms);
 | 
			
		||||
        if (result.metaInfo.clipboardText)
 | 
			
		||||
            this._clipboard.set_text(St.ClipboardType.CLIPBOARD, result.metaInfo.clipboardText);
 | 
			
		||||
        Main.overview.toggle();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _setMoreCount(_count) {
 | 
			
		||||
@@ -253,9 +233,8 @@ var SearchResultsBase = GObject.registerClass({
 | 
			
		||||
                metasNeeded.forEach((resultId, i) => {
 | 
			
		||||
                    let meta = metas[i];
 | 
			
		||||
                    let display = this._createResultDisplay(meta);
 | 
			
		||||
                    if (!(display instanceof SearchResultInterface))
 | 
			
		||||
                        throw new Error(`${display} is not a valid search result`);
 | 
			
		||||
                    display.connect('key-focus-in', this._keyFocusIn.bind(this));
 | 
			
		||||
                    display.connect('activate', this._activateResult.bind(this));
 | 
			
		||||
                    display.actor.connect('key-focus-in', this._keyFocusIn.bind(this));
 | 
			
		||||
                    this._resultDisplays[resultId] = display;
 | 
			
		||||
                });
 | 
			
		||||
                callback(true);
 | 
			
		||||
@@ -267,7 +246,7 @@ var SearchResultsBase = GObject.registerClass({
 | 
			
		||||
        this._terms = terms;
 | 
			
		||||
        if (providerResults.length == 0) {
 | 
			
		||||
            this._clearResultDisplay();
 | 
			
		||||
            this.hide();
 | 
			
		||||
            this.actor.hide();
 | 
			
		||||
            callback();
 | 
			
		||||
        } else {
 | 
			
		||||
            let maxResults = this._getMaxDisplayedResults();
 | 
			
		||||
@@ -286,23 +265,22 @@ var SearchResultsBase = GObject.registerClass({
 | 
			
		||||
                // To avoid CSS transitions causing flickering when
 | 
			
		||||
                // the first search result stays the same, we hide the
 | 
			
		||||
                // content while filling in the results.
 | 
			
		||||
                this.hide();
 | 
			
		||||
                this.actor.hide();
 | 
			
		||||
                this._clearResultDisplay();
 | 
			
		||||
                results.forEach(resultId => {
 | 
			
		||||
                    this._addItem(this._resultDisplays[resultId]);
 | 
			
		||||
                });
 | 
			
		||||
                this._setMoreCount(this.provider.canLaunchSearch ? moreCount : 0);
 | 
			
		||||
                this.show();
 | 
			
		||||
                this.actor.show();
 | 
			
		||||
                callback();
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var ListSearchResults = GObject.registerClass(
 | 
			
		||||
class ListSearchResults extends SearchResultsBase {
 | 
			
		||||
    _init(provider, resultsView) {
 | 
			
		||||
        super._init(provider, resultsView);
 | 
			
		||||
var ListSearchResults = class extends SearchResultsBase {
 | 
			
		||||
    constructor(provider, resultsView) {
 | 
			
		||||
        super(provider, resultsView);
 | 
			
		||||
 | 
			
		||||
        this._container = new St.BoxLayout({ style_class: 'search-section-content' });
 | 
			
		||||
        this.providerInfo = new ProviderInfo(provider);
 | 
			
		||||
@@ -343,21 +321,21 @@ class ListSearchResults extends SearchResultsBase {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _addItem(display) {
 | 
			
		||||
        this._content.add_actor(display);
 | 
			
		||||
        this._content.add_actor(display.actor);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    getFirstResult() {
 | 
			
		||||
        if (this._content.get_n_children() > 0)
 | 
			
		||||
            return this._content.get_child_at_index(0);
 | 
			
		||||
            return this._content.get_child_at_index(0)._delegate;
 | 
			
		||||
        else
 | 
			
		||||
            return null;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(ListSearchResults.prototype);
 | 
			
		||||
 | 
			
		||||
var GridSearchResults = GObject.registerClass(
 | 
			
		||||
class GridSearchResults extends SearchResultsBase {
 | 
			
		||||
    _init(provider, resultsView) {
 | 
			
		||||
        super._init(provider, resultsView);
 | 
			
		||||
var GridSearchResults = class extends SearchResultsBase {
 | 
			
		||||
    constructor(provider, resultsView) {
 | 
			
		||||
        super(provider, resultsView);
 | 
			
		||||
 | 
			
		||||
        this._grid = new IconGrid.IconGrid({ rowLimit: MAX_GRID_SEARCH_RESULTS_ROWS,
 | 
			
		||||
                                             xAlign: St.Align.START });
 | 
			
		||||
@@ -379,7 +357,7 @@ class GridSearchResults extends SearchResultsBase {
 | 
			
		||||
 | 
			
		||||
    updateSearch(...args) {
 | 
			
		||||
        if (this._notifyAllocationId)
 | 
			
		||||
            this.disconnect(this._notifyAllocationId);
 | 
			
		||||
            this.actor.disconnect(this._notifyAllocationId);
 | 
			
		||||
        if (this._updateSearchLater) {
 | 
			
		||||
            Meta.later_remove(this._updateSearchLater);
 | 
			
		||||
            delete this._updateSearchLater;
 | 
			
		||||
@@ -387,7 +365,7 @@ class GridSearchResults extends SearchResultsBase {
 | 
			
		||||
 | 
			
		||||
        // Make sure the maximum number of results calculated by
 | 
			
		||||
        // _getMaxDisplayedResults() is updated after width changes.
 | 
			
		||||
        this._notifyAllocationId = this.connect('notify::allocation', () => {
 | 
			
		||||
        this._notifyAllocationId = this.actor.connect('notify::allocation', () => {
 | 
			
		||||
            if (this._updateSearchLater)
 | 
			
		||||
                return;
 | 
			
		||||
            this._updateSearchLater = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
 | 
			
		||||
@@ -401,7 +379,7 @@ class GridSearchResults extends SearchResultsBase {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _getMaxDisplayedResults() {
 | 
			
		||||
        let width = this.allocation.get_width();
 | 
			
		||||
        let width = this.actor.allocation.x2 - this.actor.allocation.x1;
 | 
			
		||||
        if (width == 0)
 | 
			
		||||
            return -1;
 | 
			
		||||
 | 
			
		||||
@@ -424,17 +402,17 @@ class GridSearchResults extends SearchResultsBase {
 | 
			
		||||
 | 
			
		||||
    getFirstResult() {
 | 
			
		||||
        if (this._grid.visibleItemsCount() > 0)
 | 
			
		||||
            return this._grid.getItemAtIndex(0);
 | 
			
		||||
            return this._grid.getItemAtIndex(0)._delegate;
 | 
			
		||||
        else
 | 
			
		||||
            return null;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(GridSearchResults.prototype);
 | 
			
		||||
 | 
			
		||||
var SearchResultsView = GObject.registerClass({
 | 
			
		||||
    Signals: { 'terms-changed': {} }
 | 
			
		||||
}, class SearchResultsView extends St.BoxLayout {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init({ name: 'searchResults', vertical: true });
 | 
			
		||||
var SearchResults = class {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        this.actor = new St.BoxLayout({ name: 'searchResults',
 | 
			
		||||
                                        vertical: true });
 | 
			
		||||
 | 
			
		||||
        this._content = new MaxWidthBox({ name: 'searchResultsContent',
 | 
			
		||||
                                          vertical: true });
 | 
			
		||||
@@ -450,18 +428,16 @@ var SearchResultsView = GObject.registerClass({
 | 
			
		||||
        action.connect('pan', this._onPan.bind(this));
 | 
			
		||||
        this._scrollView.add_action(action);
 | 
			
		||||
 | 
			
		||||
        this.add(this._scrollView, {
 | 
			
		||||
            x_fill: true,
 | 
			
		||||
            y_fill: true,
 | 
			
		||||
            expand: true,
 | 
			
		||||
            x_align: St.Align.START,
 | 
			
		||||
            y_align: St.Align.STAR
 | 
			
		||||
        });
 | 
			
		||||
        this.actor.add(this._scrollView, { x_fill: true,
 | 
			
		||||
                                           y_fill: true,
 | 
			
		||||
                                           expand: true,
 | 
			
		||||
                                           x_align: St.Align.START,
 | 
			
		||||
                                           y_align: St.Align.START });
 | 
			
		||||
 | 
			
		||||
        this._statusText = new St.Label({ style_class: 'search-statustext' });
 | 
			
		||||
        this._statusBin = new St.Bin({ x_align: St.Align.MIDDLE,
 | 
			
		||||
                                       y_align: St.Align.MIDDLE });
 | 
			
		||||
        this.add(this._statusBin, { expand: true });
 | 
			
		||||
        this.actor.add(this._statusBin, { expand: true });
 | 
			
		||||
        this._statusBin.add_actor(this._statusText);
 | 
			
		||||
 | 
			
		||||
        this._highlightDefault = false;
 | 
			
		||||
@@ -491,10 +467,6 @@ var SearchResultsView = GObject.registerClass({
 | 
			
		||||
        this._reloadRemoteProviders();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get terms() {
 | 
			
		||||
        return this._terms;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _reloadRemoteProviders() {
 | 
			
		||||
        let remoteProviders = this._providers.filter(p => p.isRemoteProvider);
 | 
			
		||||
        remoteProviders.forEach(provider => {
 | 
			
		||||
@@ -619,12 +591,12 @@ var SearchResultsView = GObject.registerClass({
 | 
			
		||||
    _onPan(action) {
 | 
			
		||||
        let [dist_, dx_, dy] = action.get_motion_delta(0);
 | 
			
		||||
        let adjustment = this._scrollView.vscroll.adjustment;
 | 
			
		||||
        adjustment.value -= (dy / this.height) * adjustment.page_size;
 | 
			
		||||
        adjustment.value -= (dy / this.actor.height) * adjustment.page_size;
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _focusChildChanged(provider) {
 | 
			
		||||
        Util.ensureActorVisibleInScrollView(this._scrollView, provider.focusChild);
 | 
			
		||||
    _keyFocusIn(provider, actor) {
 | 
			
		||||
        Util.ensureActorVisibleInScrollView(this._scrollView, actor);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _ensureProviderDisplay(provider) {
 | 
			
		||||
@@ -637,9 +609,9 @@ var SearchResultsView = GObject.registerClass({
 | 
			
		||||
        else
 | 
			
		||||
            providerDisplay = new GridSearchResults(provider, this);
 | 
			
		||||
 | 
			
		||||
        providerDisplay.connect('notify::focus-child', this._focusChildChanged.bind(this));
 | 
			
		||||
        providerDisplay.hide();
 | 
			
		||||
        this._content.add(providerDisplay);
 | 
			
		||||
        providerDisplay.connect('key-focus-in', this._keyFocusIn.bind(this));
 | 
			
		||||
        providerDisplay.actor.hide();
 | 
			
		||||
        this._content.add(providerDisplay.actor);
 | 
			
		||||
        provider.display = providerDisplay;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -657,7 +629,7 @@ var SearchResultsView = GObject.registerClass({
 | 
			
		||||
            let provider = providers[i];
 | 
			
		||||
            let display = provider.display;
 | 
			
		||||
 | 
			
		||||
            if (!display.visible)
 | 
			
		||||
            if (!display.actor.visible)
 | 
			
		||||
                continue;
 | 
			
		||||
 | 
			
		||||
            let firstResult = display.getFirstResult();
 | 
			
		||||
@@ -732,22 +704,22 @@ var SearchResultsView = GObject.registerClass({
 | 
			
		||||
            this._doSearch();
 | 
			
		||||
 | 
			
		||||
        if (this._defaultResult)
 | 
			
		||||
            this._defaultResult.popup_menu();
 | 
			
		||||
            this._defaultResult.actor.popup_menu();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    navigateFocus(direction) {
 | 
			
		||||
        let rtl = this.get_text_direction() == Clutter.TextDirection.RTL;
 | 
			
		||||
        let rtl = this.actor.get_text_direction() == Clutter.TextDirection.RTL;
 | 
			
		||||
        if (direction == St.DirectionType.TAB_BACKWARD ||
 | 
			
		||||
            direction == (rtl
 | 
			
		||||
                ? St.DirectionType.RIGHT
 | 
			
		||||
                : St.DirectionType.LEFT) ||
 | 
			
		||||
            direction == St.DirectionType.UP) {
 | 
			
		||||
            this.navigate_focus(null, direction, false);
 | 
			
		||||
            this.actor.navigate_focus(null, direction, false);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let from = this._defaultResult ? this._defaultResult : null;
 | 
			
		||||
        this.navigate_focus(from, direction, false);
 | 
			
		||||
        let from = this._defaultResult ? this._defaultResult.actor : null;
 | 
			
		||||
        this.actor.navigate_focus(from, direction, false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _setSelected(result, selected) {
 | 
			
		||||
@@ -755,10 +727,10 @@ var SearchResultsView = GObject.registerClass({
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (selected) {
 | 
			
		||||
            result.add_style_pseudo_class('selected');
 | 
			
		||||
            Util.ensureActorVisibleInScrollView(this._scrollView, result);
 | 
			
		||||
            result.actor.add_style_pseudo_class('selected');
 | 
			
		||||
            Util.ensureActorVisibleInScrollView(this._scrollView, result.actor);
 | 
			
		||||
        } else {
 | 
			
		||||
            result.remove_style_pseudo_class('selected');
 | 
			
		||||
            result.actor.remove_style_pseudo_class('selected');
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -771,7 +743,8 @@ var SearchResultsView = GObject.registerClass({
 | 
			
		||||
 | 
			
		||||
        return description.replace(this._highlightRegex, '<b>$1</b>');
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(SearchResults.prototype);
 | 
			
		||||
 | 
			
		||||
var ProviderInfo = GObject.registerClass(
 | 
			
		||||
class ProviderInfo extends St.Button {
 | 
			
		||||
 
 | 
			
		||||
@@ -53,19 +53,6 @@ const _modes = {
 | 
			
		||||
        panelStyle: 'login-screen'
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    'lock-screen': {
 | 
			
		||||
        isLocked: true,
 | 
			
		||||
        isGreeter: undefined,
 | 
			
		||||
        unlockDialog: undefined,
 | 
			
		||||
        components: ['polkitAgent', 'telepathyClient'],
 | 
			
		||||
        panel: {
 | 
			
		||||
            left: [],
 | 
			
		||||
            center: [],
 | 
			
		||||
            right: ['aggregateMenu']
 | 
			
		||||
        },
 | 
			
		||||
        panelStyle: 'lock-screen'
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    'unlock-dialog': {
 | 
			
		||||
        isLocked: true,
 | 
			
		||||
        unlockDialog: undefined,
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,7 @@
 | 
			
		||||
/* exported ShellMountOperation, GnomeShellMountOpHandler */
 | 
			
		||||
 | 
			
		||||
const { Clutter, Gio, GLib, GObject, Pango, Shell, St } = imports.gi;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
 | 
			
		||||
const Animation = imports.ui.animation;
 | 
			
		||||
const CheckBox = imports.ui.checkBox;
 | 
			
		||||
@@ -43,23 +44,19 @@ function _setLabelsForMessage(content, message) {
 | 
			
		||||
 | 
			
		||||
/* -------------------------------------------------------- */
 | 
			
		||||
 | 
			
		||||
var ListItem = GObject.registerClass({
 | 
			
		||||
    GTypeName: 'ShellMountOperation_ListItem',
 | 
			
		||||
    Signals: { 'activate': {} }
 | 
			
		||||
}, class ListItem extends St.Button {
 | 
			
		||||
    _init(app) {
 | 
			
		||||
        let layout = new St.BoxLayout({ vertical: false });
 | 
			
		||||
        super._init({
 | 
			
		||||
            style_class: 'mount-dialog-app-list-item',
 | 
			
		||||
            can_focus: true,
 | 
			
		||||
            child: layout,
 | 
			
		||||
            reactive: true,
 | 
			
		||||
            x_align: St.Align.START,
 | 
			
		||||
            x_fill: true
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
var ListItem = class {
 | 
			
		||||
    constructor(app) {
 | 
			
		||||
        this._app = app;
 | 
			
		||||
 | 
			
		||||
        let layout = new St.BoxLayout({ vertical: false });
 | 
			
		||||
 | 
			
		||||
        this.actor = new St.Button({ style_class: 'mount-dialog-app-list-item',
 | 
			
		||||
                                     can_focus: true,
 | 
			
		||||
                                     child: layout,
 | 
			
		||||
                                     reactive: true,
 | 
			
		||||
                                     x_align: St.Align.START,
 | 
			
		||||
                                     x_fill: true });
 | 
			
		||||
 | 
			
		||||
        this._icon = this._app.create_icon_texture(LIST_ITEM_ICON_SIZE);
 | 
			
		||||
 | 
			
		||||
        let iconBin = new St.Bin({ style_class: 'mount-dialog-app-list-item-icon',
 | 
			
		||||
@@ -71,13 +68,16 @@ var ListItem = GObject.registerClass({
 | 
			
		||||
        let labelBin = new St.Bin({ y_align: St.Align.MIDDLE,
 | 
			
		||||
                                    child: this._nameLabel });
 | 
			
		||||
        layout.add(labelBin);
 | 
			
		||||
 | 
			
		||||
        this.actor.connect('clicked', this._onClicked.bind(this));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_clicked() {
 | 
			
		||||
    _onClicked() {
 | 
			
		||||
        this.emit('activate');
 | 
			
		||||
        this._app.activate();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(ListItem.prototype);
 | 
			
		||||
 | 
			
		||||
var ShellMountOperation = class {
 | 
			
		||||
    constructor(source, params) {
 | 
			
		||||
@@ -219,10 +219,9 @@ var ShellMountOperation = class {
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var ShellUnmountNotifier = GObject.registerClass(
 | 
			
		||||
class ShellUnmountNotifier extends MessageTray.Source {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init('', 'media-removable');
 | 
			
		||||
var ShellUnmountNotifier = class extends MessageTray.Source {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        super('', 'media-removable');
 | 
			
		||||
 | 
			
		||||
        this._notification = null;
 | 
			
		||||
        Main.messageTray.add(this);
 | 
			
		||||
@@ -239,7 +238,7 @@ class ShellUnmountNotifier extends MessageTray.Source {
 | 
			
		||||
            this._notification.update(header, text);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.showNotification(this._notification);
 | 
			
		||||
        this.notify(this._notification);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    done(message) {
 | 
			
		||||
@@ -252,10 +251,10 @@ class ShellUnmountNotifier extends MessageTray.Source {
 | 
			
		||||
            let notification = new MessageTray.Notification(this, message, null);
 | 
			
		||||
            notification.setTransient(true);
 | 
			
		||||
 | 
			
		||||
            this.showNotification(notification);
 | 
			
		||||
            this.notify(notification);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var ShellMountQuestionDialog = GObject.registerClass({
 | 
			
		||||
    Signals: { 'response': { param_types: [GObject.TYPE_INT] } }
 | 
			
		||||
@@ -304,14 +303,14 @@ var ShellMountPasswordDialog = GObject.registerClass({
 | 
			
		||||
                                                  visible: false }));
 | 
			
		||||
 | 
			
		||||
            this._hiddenVolume = new CheckBox.CheckBox(_("Hidden Volume"));
 | 
			
		||||
            content.messageBox.add(this._hiddenVolume);
 | 
			
		||||
            content.messageBox.add(this._hiddenVolume.actor);
 | 
			
		||||
 | 
			
		||||
            this._systemVolume = new CheckBox.CheckBox(_("Windows System Volume"));
 | 
			
		||||
            content.messageBox.add(this._systemVolume);
 | 
			
		||||
            content.messageBox.add(this._systemVolume.actor);
 | 
			
		||||
 | 
			
		||||
            this._keyfilesCheckbox = new CheckBox.CheckBox(_("Uses Keyfiles"));
 | 
			
		||||
            this._keyfilesCheckbox.connect("clicked", this._onKeyfilesCheckboxClicked.bind(this));
 | 
			
		||||
            content.messageBox.add(this._keyfilesCheckbox);
 | 
			
		||||
            this._keyfilesCheckbox.actor.connect("clicked", this._onKeyfilesCheckboxClicked.bind(this));
 | 
			
		||||
            content.messageBox.add(this._keyfilesCheckbox.actor);
 | 
			
		||||
 | 
			
		||||
            this._keyfilesLabel.clutter_text.set_markup(
 | 
			
		||||
                /* Translators: %s is the Disks application */
 | 
			
		||||
@@ -361,7 +360,7 @@ var ShellMountPasswordDialog = GObject.registerClass({
 | 
			
		||||
        ShellEntry.addContextMenu(this._passwordEntry, { isPassword: true });
 | 
			
		||||
        this.setInitialKeyFocus(this._passwordEntry);
 | 
			
		||||
        this._workSpinner = new Animation.Spinner(WORK_SPINNER_ICON_SIZE, true);
 | 
			
		||||
        this._passwordEntry.secondary_icon = this._workSpinner;
 | 
			
		||||
        this._passwordEntry.secondary_icon = this._workSpinner.actor;
 | 
			
		||||
 | 
			
		||||
        if (rtl) {
 | 
			
		||||
            layout.attach(this._passwordEntry, 0, 1, 1, 1);
 | 
			
		||||
@@ -382,9 +381,9 @@ var ShellMountPasswordDialog = GObject.registerClass({
 | 
			
		||||
 | 
			
		||||
        if (flags & Gio.AskPasswordFlags.SAVING_SUPPORTED) {
 | 
			
		||||
            this._rememberChoice = new CheckBox.CheckBox(_("Remember Password"));
 | 
			
		||||
            this._rememberChoice.checked =
 | 
			
		||||
            this._rememberChoice.actor.checked =
 | 
			
		||||
                global.settings.get_boolean(REMEMBER_MOUNT_PASSWORD_KEY);
 | 
			
		||||
            content.messageBox.add(this._rememberChoice);
 | 
			
		||||
            content.messageBox.add(this._rememberChoice.actor);
 | 
			
		||||
        } else {
 | 
			
		||||
            this._rememberChoice = null;
 | 
			
		||||
        }
 | 
			
		||||
@@ -440,22 +439,22 @@ var ShellMountPasswordDialog = GObject.registerClass({
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        global.settings.set_boolean(REMEMBER_MOUNT_PASSWORD_KEY,
 | 
			
		||||
            this._rememberChoice && this._rememberChoice.checked);
 | 
			
		||||
            this._rememberChoice && this._rememberChoice.actor.checked);
 | 
			
		||||
 | 
			
		||||
        this._workSpinner.play();
 | 
			
		||||
        this.emit('response', 1,
 | 
			
		||||
            this._passwordEntry.get_text(),
 | 
			
		||||
            this._rememberChoice &&
 | 
			
		||||
            this._rememberChoice.checked,
 | 
			
		||||
            this._rememberChoice.actor.checked,
 | 
			
		||||
            this._hiddenVolume &&
 | 
			
		||||
            this._hiddenVolume.checked,
 | 
			
		||||
            this._hiddenVolume.actor.checked,
 | 
			
		||||
            this._systemVolume &&
 | 
			
		||||
            this._systemVolume.checked,
 | 
			
		||||
            this._systemVolume.actor.checked,
 | 
			
		||||
            parseInt(pim));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onKeyfilesCheckboxClicked() {
 | 
			
		||||
        let useKeyfiles = this._keyfilesCheckbox.checked;
 | 
			
		||||
        let useKeyfiles = this._keyfilesCheckbox.actor.checked;
 | 
			
		||||
        this._passwordEntry.reactive = !useKeyfiles;
 | 
			
		||||
        this._passwordEntry.can_focus = !useKeyfiles;
 | 
			
		||||
        this._passwordEntry.clutter_text.editable = !useKeyfiles;
 | 
			
		||||
@@ -464,8 +463,8 @@ var ShellMountPasswordDialog = GObject.registerClass({
 | 
			
		||||
        this._pimEntry.can_focus = !useKeyfiles;
 | 
			
		||||
        this._pimEntry.clutter_text.editable = !useKeyfiles;
 | 
			
		||||
        this._pimEntry.clutter_text.selectable = !useKeyfiles;
 | 
			
		||||
        this._rememberChoice.reactive = !useKeyfiles;
 | 
			
		||||
        this._rememberChoice.can_focus = !useKeyfiles;
 | 
			
		||||
        this._rememberChoice.actor.reactive = !useKeyfiles;
 | 
			
		||||
        this._rememberChoice.actor.can_focus = !useKeyfiles;
 | 
			
		||||
        this._keyfilesLabel.visible = useKeyfiles;
 | 
			
		||||
        this.setButtons(useKeyfiles ? this._usesKeyfilesButtons : this._defaultButtons);
 | 
			
		||||
    }
 | 
			
		||||
@@ -528,7 +527,7 @@ var ShellProcessesDialog = GObject.registerClass({
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            let item = new ListItem(app);
 | 
			
		||||
            this._applicationList.add(item, { x_fill: true });
 | 
			
		||||
            this._applicationList.add(item.actor, { x_fill: true });
 | 
			
		||||
 | 
			
		||||
            item.connect('activate', () => {
 | 
			
		||||
                // use -1 to indicate Cancel
 | 
			
		||||
 
 | 
			
		||||
@@ -22,7 +22,12 @@ var Slider = GObject.registerClass({
 | 
			
		||||
            accessible_role: Atk.Role.SLIDER
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this._releaseId = 0;
 | 
			
		||||
        this.connect('button-press-event', this._startDragging.bind(this));
 | 
			
		||||
        this.connect('touch-event', this._touchDragging.bind(this));
 | 
			
		||||
        this.connect('scroll-event', this._onScrollEvent.bind(this));
 | 
			
		||||
        this.connect('key-press-event', this.onKeyPressEvent.bind(this));
 | 
			
		||||
 | 
			
		||||
        this._releaseId = this._motionId = 0;
 | 
			
		||||
        this._dragging = false;
 | 
			
		||||
 | 
			
		||||
        this._customAccessible.connect('get-minimum-increment', this._getMinimumIncrement.bind(this));
 | 
			
		||||
@@ -57,8 +62,8 @@ var Slider = GObject.registerClass({
 | 
			
		||||
        cr.$dispose();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_button_press_event() {
 | 
			
		||||
        return this.startDragging(Clutter.get_current_event());
 | 
			
		||||
    _startDragging(actor, event) {
 | 
			
		||||
        return this.startDragging(event);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    startDragging(event) {
 | 
			
		||||
@@ -78,6 +83,11 @@ var Slider = GObject.registerClass({
 | 
			
		||||
        this._grabbedDevice = device;
 | 
			
		||||
        this._grabbedSequence = sequence;
 | 
			
		||||
 | 
			
		||||
        if (sequence == null) {
 | 
			
		||||
            this._releaseId = this.connect('button-release-event', this._endDragging.bind(this));
 | 
			
		||||
            this._motionId = this.connect('motion-event', this._motionEvent.bind(this));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // We need to emit 'drag-begin' before moving the handle to make
 | 
			
		||||
        // sure that no 'notify::value' signal is emitted before this one.
 | 
			
		||||
        this.emit('drag-begin');
 | 
			
		||||
@@ -95,6 +105,11 @@ var Slider = GObject.registerClass({
 | 
			
		||||
                this._releaseId = 0;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (this._motionId) {
 | 
			
		||||
                this.disconnect(this._motionId);
 | 
			
		||||
                this._motionId = 0;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (this._grabbedSequence != null)
 | 
			
		||||
                this._grabbedDevice.sequence_ungrab(this._grabbedSequence);
 | 
			
		||||
            else
 | 
			
		||||
@@ -109,15 +124,7 @@ var Slider = GObject.registerClass({
 | 
			
		||||
        return Clutter.EVENT_STOP;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_button_release_event() {
 | 
			
		||||
        if (this._dragging && !this._grabbedSequence)
 | 
			
		||||
            return this._endDragging();
 | 
			
		||||
 | 
			
		||||
        return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_touch_event() {
 | 
			
		||||
        let event = Clutter.get_current_event();
 | 
			
		||||
    _touchDragging(actor, event) {
 | 
			
		||||
        let device = event.get_device();
 | 
			
		||||
        let sequence = event.get_event_sequence();
 | 
			
		||||
 | 
			
		||||
@@ -125,9 +132,9 @@ var Slider = GObject.registerClass({
 | 
			
		||||
            event.type() == Clutter.EventType.TOUCH_BEGIN) {
 | 
			
		||||
            this.startDragging(event);
 | 
			
		||||
            return Clutter.EVENT_STOP;
 | 
			
		||||
        } else if (device.sequence_get_grabbed_actor(sequence) == this) {
 | 
			
		||||
        } else if (device.sequence_get_grabbed_actor(sequence) == actor) {
 | 
			
		||||
            if (event.type() == Clutter.EventType.TOUCH_UPDATE)
 | 
			
		||||
                return this._motionEvent(this, event);
 | 
			
		||||
                return this._motionEvent(actor, event);
 | 
			
		||||
            else if (event.type() == Clutter.EventType.TOUCH_END)
 | 
			
		||||
                return this._endDragging();
 | 
			
		||||
        }
 | 
			
		||||
@@ -158,15 +165,8 @@ var Slider = GObject.registerClass({
 | 
			
		||||
        return Clutter.EVENT_STOP;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_scroll_event() {
 | 
			
		||||
        return this.scroll(Clutter.get_current_event());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_motion_event() {
 | 
			
		||||
        if (this._dragging && !this._grabbedSequence)
 | 
			
		||||
            return this._motionEvent(this, Clutter.get_current_event());
 | 
			
		||||
 | 
			
		||||
        return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
    _onScrollEvent(actor, event) {
 | 
			
		||||
        return this.scroll(event);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _motionEvent(actor, event) {
 | 
			
		||||
@@ -176,8 +176,8 @@ var Slider = GObject.registerClass({
 | 
			
		||||
        return Clutter.EVENT_STOP;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_key_press_event(keyPressEvent) {
 | 
			
		||||
        let key = keyPressEvent.keyval;
 | 
			
		||||
    onKeyPressEvent(actor, event) {
 | 
			
		||||
        let key = event.get_key_symbol();
 | 
			
		||||
        if (key == Clutter.KEY_Right || key == Clutter.KEY_Left) {
 | 
			
		||||
            let delta = key == Clutter.KEY_Right ? 0.1 : -0.1;
 | 
			
		||||
            this.emit('drag-begin');
 | 
			
		||||
 
 | 
			
		||||
@@ -102,7 +102,7 @@ class ATIndicator extends PanelMenu.Button {
 | 
			
		||||
    _buildItemExtended(string, initialValue, writable, onSet) {
 | 
			
		||||
        let widget = new PopupMenu.PopupSwitchMenuItem(string, initialValue);
 | 
			
		||||
        if (!writable)
 | 
			
		||||
            widget.reactive = false;
 | 
			
		||||
            widget.actor.reactive = false;
 | 
			
		||||
        else
 | 
			
		||||
            widget.connect('toggled', item => {
 | 
			
		||||
                onSet(item.state);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/* exported Indicator */
 | 
			
		||||
 | 
			
		||||
const { Gio, GnomeBluetooth, GObject } = imports.gi;
 | 
			
		||||
const { Gio, GnomeBluetooth } = imports.gi;
 | 
			
		||||
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const PanelMenu = imports.ui.panelMenu;
 | 
			
		||||
@@ -17,11 +17,9 @@ const RfkillManagerProxy = Gio.DBusProxy.makeProxyWrapper(RfkillManagerInterface
 | 
			
		||||
 | 
			
		||||
const HAD_BLUETOOTH_DEVICES_SETUP = 'had-bluetooth-devices-setup';
 | 
			
		||||
 | 
			
		||||
var Indicator = GObject.registerClass({
 | 
			
		||||
    GTypeName: 'Bluetooth_Indicator'
 | 
			
		||||
}, class Indicator extends PanelMenu.SystemIndicator {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init();
 | 
			
		||||
var Indicator = class extends PanelMenu.SystemIndicator {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        super();
 | 
			
		||||
 | 
			
		||||
        this._indicator = this._addIndicator();
 | 
			
		||||
        this._indicator.icon_name = 'bluetooth-active-symbolic';
 | 
			
		||||
@@ -135,4 +133,4 @@ var Indicator = GObject.registerClass({
 | 
			
		||||
 | 
			
		||||
        this._toggleItem.label.text = this._proxy.BluetoothAirplaneMode ? _("Turn On") : _("Turn Off");
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -15,11 +15,9 @@ const OBJECT_PATH = '/org/gnome/SettingsDaemon/Power';
 | 
			
		||||
const BrightnessInterface = loadInterfaceXML('org.gnome.SettingsDaemon.Power.Screen');
 | 
			
		||||
const BrightnessProxy = Gio.DBusProxy.makeProxyWrapper(BrightnessInterface);
 | 
			
		||||
 | 
			
		||||
var Indicator = GObject.registerClass({
 | 
			
		||||
    GTypeName: 'Brightness_Indicator'
 | 
			
		||||
}, class Indicator extends PanelMenu.SystemIndicator {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init();
 | 
			
		||||
var Indicator = class extends PanelMenu.SystemIndicator {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        super('display-brightness-symbolic');
 | 
			
		||||
        this._proxy = new BrightnessProxy(Gio.DBus.session, BUS_NAME, OBJECT_PATH,
 | 
			
		||||
                                          (proxy, error) => {
 | 
			
		||||
                                              if (error) {
 | 
			
		||||
@@ -47,7 +45,7 @@ var Indicator = GObject.registerClass({
 | 
			
		||||
            return this._slider.startDragging(event);
 | 
			
		||||
        });
 | 
			
		||||
        this._item.connect('key-press-event', (actor, event) => {
 | 
			
		||||
            return this._slider.emit('key-press-event', event);
 | 
			
		||||
            return this._slider.onKeyPressEvent(actor, event);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
@@ -69,4 +67,4 @@ var Indicator = GObject.registerClass({
 | 
			
		||||
        if (visible)
 | 
			
		||||
            this._changeSlider(this._proxy.Brightness / 100.0);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -923,7 +923,7 @@ class InputSourceIndicator extends PanelMenu.Button {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _buildPropSection(properties) {
 | 
			
		||||
        this._propSeparator.hide();
 | 
			
		||||
        this._propSeparator.actor.hide();
 | 
			
		||||
        this._propSection.actor.hide();
 | 
			
		||||
        this._propSection.removeAll();
 | 
			
		||||
 | 
			
		||||
@@ -931,7 +931,7 @@ class InputSourceIndicator extends PanelMenu.Button {
 | 
			
		||||
 | 
			
		||||
        if (!this._propSection.isEmpty()) {
 | 
			
		||||
            this._propSection.actor.show();
 | 
			
		||||
            this._propSeparator.show();
 | 
			
		||||
            this._propSeparator.actor.show();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -42,11 +42,9 @@ const GeoclueManager = Gio.DBusProxy.makeProxyWrapper(GeoclueIface);
 | 
			
		||||
 | 
			
		||||
var AgentIface = loadInterfaceXML('org.freedesktop.GeoClue2.Agent');
 | 
			
		||||
 | 
			
		||||
var Indicator = GObject.registerClass({
 | 
			
		||||
    GTypeName: 'Location_Indicator'
 | 
			
		||||
}, class Indicator extends PanelMenu.SystemIndicator {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init();
 | 
			
		||||
var Indicator = class extends PanelMenu.SystemIndicator {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        super();
 | 
			
		||||
 | 
			
		||||
        this._settings = new Gio.Settings({ schema_id: LOCATION_SCHEMA });
 | 
			
		||||
        this._settings.connect(`changed::${ENABLED}`,
 | 
			
		||||
@@ -224,7 +222,7 @@ var Indicator = GObject.registerClass({
 | 
			
		||||
 | 
			
		||||
        this._permStoreProxy = proxy;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function clamp(value, min, max) {
 | 
			
		||||
    return Math.max(min, Math.min(max, value));
 | 
			
		||||
 
 | 
			
		||||
@@ -630,6 +630,7 @@ var NMWirelessDialogItem = GObject.registerClass({
 | 
			
		||||
                      can_focus: true,
 | 
			
		||||
                      reactive: true });
 | 
			
		||||
 | 
			
		||||
        this.connect('key-focus-in', () => this.emit('selected'));
 | 
			
		||||
        let action = new Clutter.ClickAction();
 | 
			
		||||
        action.connect('clicked', () => this.grab_key_focus());
 | 
			
		||||
        this.add_action(action);
 | 
			
		||||
@@ -658,10 +659,6 @@ var NMWirelessDialogItem = GObject.registerClass({
 | 
			
		||||
        this._sync();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_key_focus_in() {
 | 
			
		||||
        this.emit('selected');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _sync() {
 | 
			
		||||
        this._signalIcon.icon_name = this._getSignalIcon();
 | 
			
		||||
    }
 | 
			
		||||
@@ -863,7 +860,7 @@ class NMWirelessDialog extends ModalDialog.ModalDialog {
 | 
			
		||||
                                                 y_align: Clutter.ActorAlign.CENTER });
 | 
			
		||||
 | 
			
		||||
        this._noNetworksSpinner = new Animation.Spinner(16);
 | 
			
		||||
        this._noNetworksBox.add_actor(this._noNetworksSpinner);
 | 
			
		||||
        this._noNetworksBox.add_actor(this._noNetworksSpinner.actor);
 | 
			
		||||
        this._noNetworksBox.add_actor(new St.Label({ style_class: 'no-networks-label',
 | 
			
		||||
                                                     text: _("No Networks") }));
 | 
			
		||||
        this._stack.add_child(this._noNetworksBox);
 | 
			
		||||
@@ -1591,11 +1588,9 @@ var DeviceCategory = class extends PopupMenu.PopupMenuSection {
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var NMApplet = GObject.registerClass({
 | 
			
		||||
    GTypeName: 'Network_Indicator'
 | 
			
		||||
}, class Indicator extends PanelMenu.SystemIndicator {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init();
 | 
			
		||||
var NMApplet = class extends PanelMenu.SystemIndicator {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        super();
 | 
			
		||||
 | 
			
		||||
        this._primaryIndicator = this._addIndicator();
 | 
			
		||||
        this._vpnIndicator = this._addIndicator();
 | 
			
		||||
@@ -1711,7 +1706,7 @@ var NMApplet = GObject.registerClass({
 | 
			
		||||
        this._notification.connect('destroy', () => {
 | 
			
		||||
            this._notification = null;
 | 
			
		||||
        });
 | 
			
		||||
        this._source.showNotification(this._notification);
 | 
			
		||||
        this._source.notify(this._notification);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onActivationFailed(_device, _reason) {
 | 
			
		||||
@@ -1944,7 +1939,7 @@ var NMApplet = GObject.registerClass({
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _syncNMState() {
 | 
			
		||||
        this.visible = this._client.nm_running;
 | 
			
		||||
        this.indicators.visible = this._client.nm_running;
 | 
			
		||||
        this.menu.actor.visible = this._client.networking_enabled;
 | 
			
		||||
 | 
			
		||||
        this._updateIcon();
 | 
			
		||||
@@ -2063,4 +2058,4 @@ var NMApplet = GObject.registerClass({
 | 
			
		||||
        this._vpnIndicator.icon_name = this._vpnSection.getIndicatorIcon();
 | 
			
		||||
        this._vpnIndicator.visible = (this._vpnIndicator.icon_name != '');
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/* exported Indicator */
 | 
			
		||||
 | 
			
		||||
const { Gio, GObject } = imports.gi;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const PanelMenu = imports.ui.panelMenu;
 | 
			
		||||
@@ -15,11 +15,9 @@ const OBJECT_PATH = '/org/gnome/SettingsDaemon/Color';
 | 
			
		||||
const ColorInterface = loadInterfaceXML('org.gnome.SettingsDaemon.Color');
 | 
			
		||||
const ColorProxy = Gio.DBusProxy.makeProxyWrapper(ColorInterface);
 | 
			
		||||
 | 
			
		||||
var Indicator = GObject.registerClass({
 | 
			
		||||
    GTypeName: 'NightLight_Indicator'
 | 
			
		||||
}, class Indicator extends PanelMenu.SystemIndicator {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init();
 | 
			
		||||
var Indicator = class extends PanelMenu.SystemIndicator {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        super();
 | 
			
		||||
 | 
			
		||||
        this._indicator = this._addIndicator();
 | 
			
		||||
        this._indicator.icon_name = 'night-light-symbolic';
 | 
			
		||||
@@ -68,4 +66,4 @@ var Indicator = GObject.registerClass({
 | 
			
		||||
            : _("Disable Until Tomorrow");
 | 
			
		||||
        this._item.visible = this._indicator.visible = visible;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/* exported Indicator */
 | 
			
		||||
 | 
			
		||||
const { Clutter, Gio, GObject, St, UPowerGlib: UPower } = imports.gi;
 | 
			
		||||
const { Clutter, Gio, St, UPowerGlib: UPower } = imports.gi;
 | 
			
		||||
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const PanelMenu = imports.ui.panelMenu;
 | 
			
		||||
@@ -17,11 +17,9 @@ const PowerManagerProxy = Gio.DBusProxy.makeProxyWrapper(DisplayDeviceInterface)
 | 
			
		||||
 | 
			
		||||
const SHOW_BATTERY_PERCENTAGE       = 'show-battery-percentage';
 | 
			
		||||
 | 
			
		||||
var Indicator = GObject.registerClass({
 | 
			
		||||
    GTypeName: 'Power_Indicator'
 | 
			
		||||
}, class Indicator extends PanelMenu.SystemIndicator {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init();
 | 
			
		||||
var Indicator = class extends PanelMenu.SystemIndicator {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        super();
 | 
			
		||||
 | 
			
		||||
        this._desktopSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.interface' });
 | 
			
		||||
        this._desktopSettings.connect(`changed::${SHOW_BATTERY_PERCENTAGE}`,
 | 
			
		||||
@@ -30,8 +28,8 @@ var Indicator = GObject.registerClass({
 | 
			
		||||
        this._indicator = this._addIndicator();
 | 
			
		||||
        this._percentageLabel = new St.Label({ y_expand: true,
 | 
			
		||||
                                               y_align: Clutter.ActorAlign.CENTER });
 | 
			
		||||
        this.add(this._percentageLabel, { expand: true, y_fill: true });
 | 
			
		||||
        this.add_style_class_name('power-status');
 | 
			
		||||
        this.indicators.add(this._percentageLabel, { expand: true, y_fill: true });
 | 
			
		||||
        this.indicators.add_style_class_name('power-status');
 | 
			
		||||
 | 
			
		||||
        this._proxy = new PowerManagerProxy(Gio.DBus.system, BUS_NAME, OBJECT_PATH,
 | 
			
		||||
                                            (proxy, error) => {
 | 
			
		||||
@@ -142,4 +140,4 @@ var Indicator = GObject.registerClass({
 | 
			
		||||
        // The status label
 | 
			
		||||
        this._item.label.text = this._getStatus();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -1,16 +1,14 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/* exported RemoteAccessApplet */
 | 
			
		||||
 | 
			
		||||
const { GObject, Meta } = imports.gi;
 | 
			
		||||
const Meta = imports.gi.Meta;
 | 
			
		||||
 | 
			
		||||
const PanelMenu = imports.ui.panelMenu;
 | 
			
		||||
const PopupMenu = imports.ui.popupMenu;
 | 
			
		||||
 | 
			
		||||
var RemoteAccessApplet = GObject.registerClass({
 | 
			
		||||
    GTypeName: 'RemoteAccess_Indicator'
 | 
			
		||||
}, class RemoteAccessApplet extends PanelMenu.SystemIndicator {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init();
 | 
			
		||||
var RemoteAccessApplet = class extends PanelMenu.SystemIndicator {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        super();
 | 
			
		||||
 | 
			
		||||
        let backend = Meta.get_backend();
 | 
			
		||||
        let controller = backend.get_remote_access_controller();
 | 
			
		||||
@@ -77,4 +75,4 @@ var RemoteAccessApplet = GObject.registerClass({
 | 
			
		||||
            this._sync();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/* exported Indicator */
 | 
			
		||||
 | 
			
		||||
const { Gio, GObject } = imports.gi;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
@@ -61,11 +61,9 @@ function getRfkillManager() {
 | 
			
		||||
    return _manager;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var Indicator = GObject.registerClass({
 | 
			
		||||
    GTypeName: 'Rfkill_Indicator'
 | 
			
		||||
}, class Indicator extends PanelMenu.SystemIndicator {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init();
 | 
			
		||||
var Indicator = class extends PanelMenu.SystemIndicator {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        super();
 | 
			
		||||
 | 
			
		||||
        this._manager = getRfkillManager();
 | 
			
		||||
        this._manager.connect('airplane-mode-changed', this._sync.bind(this));
 | 
			
		||||
@@ -108,4 +106,4 @@ var Indicator = GObject.registerClass({
 | 
			
		||||
        else
 | 
			
		||||
            this._offItem.label.text = _("Turn Off");
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -1,16 +1,12 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/* exported Indicator */
 | 
			
		||||
 | 
			
		||||
const GObject = imports.gi.GObject;
 | 
			
		||||
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const PanelMenu = imports.ui.panelMenu;
 | 
			
		||||
 | 
			
		||||
var Indicator = GObject.registerClass({
 | 
			
		||||
    GTypeName: 'Screencast_Indicator'
 | 
			
		||||
}, class Indicator extends PanelMenu.SystemIndicator {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init();
 | 
			
		||||
var Indicator = class extends PanelMenu.SystemIndicator {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        super();
 | 
			
		||||
 | 
			
		||||
        this._indicator = this._addIndicator();
 | 
			
		||||
        this._indicator.icon_name = 'media-record-symbolic';
 | 
			
		||||
@@ -23,4 +19,4 @@ var Indicator = GObject.registerClass({
 | 
			
		||||
    _sync() {
 | 
			
		||||
        this._indicator.visible = Main.screencastService.isRecording;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -10,10 +10,8 @@ const PanelMenu = imports.ui.panelMenu;
 | 
			
		||||
const PopupMenu = imports.ui.popupMenu;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
var AltSwitcher = GObject.registerClass(
 | 
			
		||||
class AltSwitcher extends St.Bin {
 | 
			
		||||
    _init(standard, alternate) {
 | 
			
		||||
        super._init();
 | 
			
		||||
var AltSwitcher = class {
 | 
			
		||||
    constructor(standard, alternate) {
 | 
			
		||||
        this._standard = standard;
 | 
			
		||||
        this._standard.connect('notify::visible', this._sync.bind(this));
 | 
			
		||||
        if (this._standard instanceof St.Button)
 | 
			
		||||
@@ -33,17 +31,9 @@ class AltSwitcher extends St.Bin {
 | 
			
		||||
        this._clickAction = new Clutter.ClickAction();
 | 
			
		||||
        this._clickAction.connect('long-press', this._onLongPress.bind(this));
 | 
			
		||||
 | 
			
		||||
        this.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_map() {
 | 
			
		||||
        super.vfunc_map();
 | 
			
		||||
        this._flipped = false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_unmap() {
 | 
			
		||||
        super.vfunc_unmap();
 | 
			
		||||
        this._flipped = false;
 | 
			
		||||
        this.actor = new St.Bin();
 | 
			
		||||
        this.actor.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
        this.actor.connect('notify::mapped', () => (this._flipped = false));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _sync() {
 | 
			
		||||
@@ -61,11 +51,11 @@ class AltSwitcher extends St.Bin {
 | 
			
		||||
        } else if (this._alternate.visible) {
 | 
			
		||||
            childToShow = this._alternate;
 | 
			
		||||
        } else {
 | 
			
		||||
            this.hide();
 | 
			
		||||
            this.actor.hide();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let childShown = this.get_child();
 | 
			
		||||
        let childShown = this.actor.get_child();
 | 
			
		||||
        if (childShown != childToShow) {
 | 
			
		||||
            if (childShown) {
 | 
			
		||||
                if (childShown.fake_release)
 | 
			
		||||
@@ -74,8 +64,8 @@ class AltSwitcher extends St.Bin {
 | 
			
		||||
            }
 | 
			
		||||
            childToShow.add_action(this._clickAction);
 | 
			
		||||
 | 
			
		||||
            let hasFocus = this.contains(global.stage.get_key_focus());
 | 
			
		||||
            this.set_child(childToShow);
 | 
			
		||||
            let hasFocus = this.actor.contains(global.stage.get_key_focus());
 | 
			
		||||
            this.actor.set_child(childToShow);
 | 
			
		||||
            if (hasFocus)
 | 
			
		||||
                childToShow.grab_key_focus();
 | 
			
		||||
 | 
			
		||||
@@ -84,7 +74,7 @@ class AltSwitcher extends St.Bin {
 | 
			
		||||
            global.sync_pointer();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.show();
 | 
			
		||||
        this.actor.show();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onDestroy() {
 | 
			
		||||
@@ -114,13 +104,11 @@ class AltSwitcher extends St.Bin {
 | 
			
		||||
        this._sync();
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var Indicator = GObject.registerClass({
 | 
			
		||||
    GTypeName: 'System_Indicator'
 | 
			
		||||
}, class Indicator extends PanelMenu.SystemIndicator {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init();
 | 
			
		||||
var Indicator = class extends PanelMenu.SystemIndicator {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        super();
 | 
			
		||||
 | 
			
		||||
        let userManager = AccountsService.UserManager.get_default();
 | 
			
		||||
        this._user = userManager.get_user(GLib.get_user_name());
 | 
			
		||||
@@ -301,7 +289,7 @@ var Indicator = GObject.registerClass({
 | 
			
		||||
                                          bindFlags);
 | 
			
		||||
 | 
			
		||||
        this._altSwitcher = new AltSwitcher(this._powerOffAction, this._suspendAction);
 | 
			
		||||
        item.add(this._altSwitcher, { expand: true, x_fill: false });
 | 
			
		||||
        item.add(this._altSwitcher.actor, { expand: true, x_fill: false });
 | 
			
		||||
 | 
			
		||||
        this.menu.addMenuItem(item);
 | 
			
		||||
 | 
			
		||||
@@ -309,7 +297,7 @@ var Indicator = GObject.registerClass({
 | 
			
		||||
            this._settingsAction,
 | 
			
		||||
            this._orientationLockAction,
 | 
			
		||||
            this._lockScreenAction,
 | 
			
		||||
            this._altSwitcher,
 | 
			
		||||
            this._altSwitcher.actor,
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
        for (let actor of visibilityGroup) {
 | 
			
		||||
@@ -324,4 +312,4 @@ var Indicator = GObject.registerClass({
 | 
			
		||||
        Main.overview.hide();
 | 
			
		||||
        this._settingsApp.activate();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
 | 
			
		||||
// the following is a modified version of bolt/contrib/js/client.js
 | 
			
		||||
 | 
			
		||||
const { Gio, GLib, GObject, Polkit, Shell } = imports.gi;
 | 
			
		||||
const { Gio, GLib, Polkit, Shell } = imports.gi;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
@@ -221,11 +221,9 @@ Signals.addSignalMethods(AuthRobot.prototype);
 | 
			
		||||
 | 
			
		||||
/* eof client.js  */
 | 
			
		||||
 | 
			
		||||
var Indicator = GObject.registerClass({
 | 
			
		||||
    GTypeName: 'Thunderbolt_Indicator'
 | 
			
		||||
}, class Indicator extends PanelMenu.SystemIndicator {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init();
 | 
			
		||||
var Indicator = class extends PanelMenu.SystemIndicator {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        super();
 | 
			
		||||
 | 
			
		||||
        this._indicator = this._addIndicator();
 | 
			
		||||
        this._indicator.icon_name = 'thunderbolt-symbolic';
 | 
			
		||||
@@ -286,7 +284,7 @@ var Indicator = GObject.registerClass({
 | 
			
		||||
            if (app)
 | 
			
		||||
                app.activate();
 | 
			
		||||
        });
 | 
			
		||||
        this._source.showNotification(this._notification);
 | 
			
		||||
        this._source.notify(this._notification);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Session callbacks */
 | 
			
		||||
@@ -336,4 +334,4 @@ var Indicator = GObject.registerClass({
 | 
			
		||||
        const body = _("Could not authorize the Thunderbolt device: %s").format(error.message);
 | 
			
		||||
        this._notify(title, body);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -47,7 +47,7 @@ var StreamSlider = class {
 | 
			
		||||
            return this._slider.startDragging(event);
 | 
			
		||||
        });
 | 
			
		||||
        this.item.connect('key-press-event', (actor, event) => {
 | 
			
		||||
            return this._slider.emit('key-press-event', event);
 | 
			
		||||
            return this._slider.onKeyPressEvent(actor, event);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this._stream = null;
 | 
			
		||||
@@ -299,9 +299,6 @@ var VolumeMenu = class extends PopupMenu.PopupMenuSection {
 | 
			
		||||
        this.addMenuItem(this._output.item);
 | 
			
		||||
 | 
			
		||||
        this._input = new InputStreamSlider(this._control);
 | 
			
		||||
        this._input.item.connect('notify::visible', () => {
 | 
			
		||||
            this.emit('input-visible-changed');
 | 
			
		||||
        });
 | 
			
		||||
        this.addMenuItem(this._input.item);
 | 
			
		||||
 | 
			
		||||
        this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
 | 
			
		||||
@@ -341,44 +338,34 @@ var VolumeMenu = class extends PopupMenu.PopupMenuSection {
 | 
			
		||||
    getMaxLevel() {
 | 
			
		||||
        return this._output.getMaxLevel();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    getInputVisible() {
 | 
			
		||||
        return this._input.item.visible;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var Indicator = GObject.registerClass({
 | 
			
		||||
    GTypeName: 'Volume_Indicator'
 | 
			
		||||
}, class Indicator extends PanelMenu.SystemIndicator {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init();
 | 
			
		||||
var Indicator = class extends PanelMenu.SystemIndicator {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        super();
 | 
			
		||||
 | 
			
		||||
        this._primaryIndicator = this._addIndicator();
 | 
			
		||||
        this._inputIndicator = this._addIndicator();
 | 
			
		||||
 | 
			
		||||
        this._control = getMixerControl();
 | 
			
		||||
        this._volumeMenu = new VolumeMenu(this._control);
 | 
			
		||||
        this._volumeMenu.connect('icon-changed', () => {
 | 
			
		||||
            let icon = this._volumeMenu.getIcon();
 | 
			
		||||
 | 
			
		||||
            if (icon != null)
 | 
			
		||||
            if (icon != null) {
 | 
			
		||||
                this.indicators.show();
 | 
			
		||||
                this._primaryIndicator.icon_name = icon;
 | 
			
		||||
            this._primaryIndicator.visible = icon !== null;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this._inputIndicator.set({
 | 
			
		||||
            icon_name: 'audio-input-microphone-symbolic',
 | 
			
		||||
            visible: this._volumeMenu.getInputVisible(),
 | 
			
		||||
        });
 | 
			
		||||
        this._volumeMenu.connect('input-visible-changed', () => {
 | 
			
		||||
            this._inputIndicator.visible = this._volumeMenu.getInputVisible();
 | 
			
		||||
            } else {
 | 
			
		||||
                this.indicators.hide();
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this.menu.addMenuItem(this._volumeMenu);
 | 
			
		||||
 | 
			
		||||
        this.indicators.connect('scroll-event', this._onScrollEvent.bind(this));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_scroll_event() {
 | 
			
		||||
        let result = this._volumeMenu.scroll(Clutter.get_current_event());
 | 
			
		||||
    _onScrollEvent(actor, event) {
 | 
			
		||||
        let result = this._volumeMenu.scroll(event);
 | 
			
		||||
        if (result == Clutter.EVENT_PROPAGATE || this.menu.actor.mapped)
 | 
			
		||||
            return result;
 | 
			
		||||
 | 
			
		||||
@@ -388,4 +375,4 @@ var Indicator = GObject.registerClass({
 | 
			
		||||
        Main.osdWindowManager.show(-1, gicon, null, level, maxLevel);
 | 
			
		||||
        return result;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -105,6 +105,12 @@ var SwitcherPopup = GObject.registerClass({
 | 
			
		||||
        this._haveModal = true;
 | 
			
		||||
        this._modifierMask = primaryModifier(mask);
 | 
			
		||||
 | 
			
		||||
        this.connect('key-press-event', this._keyPressEvent.bind(this));
 | 
			
		||||
        this.connect('key-release-event', this._keyReleaseEvent.bind(this));
 | 
			
		||||
 | 
			
		||||
        this.connect('button-press-event', this._clickedOutside.bind(this));
 | 
			
		||||
        this.connect('scroll-event', this._scrollEvent.bind(this));
 | 
			
		||||
 | 
			
		||||
        this.add_actor(this._switcherList);
 | 
			
		||||
        this._switcherList.connect('item-activated', this._itemActivated.bind(this));
 | 
			
		||||
        this._switcherList.connect('item-entered', this._itemEntered.bind(this));
 | 
			
		||||
@@ -160,10 +166,9 @@ var SwitcherPopup = GObject.registerClass({
 | 
			
		||||
        throw new GObject.NotImplementedError(`_keyPressHandler in ${this.constructor.name}`);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_key_press_event(keyEvent) {
 | 
			
		||||
        let keysym = keyEvent.keyval;
 | 
			
		||||
        let action = global.display.get_keybinding_action(
 | 
			
		||||
            keyEvent.hardware_keycode, keyEvent.modifier_state);
 | 
			
		||||
    _keyPressEvent(actor, event) {
 | 
			
		||||
        let keysym = event.get_key_symbol();
 | 
			
		||||
        let action = global.display.get_keybinding_action(event.get_key_code(), event.get_state());
 | 
			
		||||
 | 
			
		||||
        this._disableHover();
 | 
			
		||||
 | 
			
		||||
@@ -178,13 +183,13 @@ var SwitcherPopup = GObject.registerClass({
 | 
			
		||||
        return Clutter.EVENT_STOP;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_key_release_event(keyEvent) {
 | 
			
		||||
    _keyReleaseEvent(actor, event) {
 | 
			
		||||
        if (this._modifierMask) {
 | 
			
		||||
            let [x_, y_, mods] = global.get_pointer();
 | 
			
		||||
            let state = mods & this._modifierMask;
 | 
			
		||||
 | 
			
		||||
            if (state == 0)
 | 
			
		||||
                this._finish(keyEvent.time);
 | 
			
		||||
                this._finish(event.get_time());
 | 
			
		||||
        } else {
 | 
			
		||||
            this._resetNoModsTimeout();
 | 
			
		||||
        }
 | 
			
		||||
@@ -192,8 +197,7 @@ var SwitcherPopup = GObject.registerClass({
 | 
			
		||||
        return Clutter.EVENT_STOP;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_button_press_event() {
 | 
			
		||||
        /* We clicked outside */
 | 
			
		||||
    _clickedOutside() {
 | 
			
		||||
        this.fadeAndDestroy();
 | 
			
		||||
        return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
    }
 | 
			
		||||
@@ -205,8 +209,8 @@ var SwitcherPopup = GObject.registerClass({
 | 
			
		||||
            this._select(this._next());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_scroll_event(scrollEvent) {
 | 
			
		||||
        this._scrollHandler(scrollEvent.scroll_direction);
 | 
			
		||||
    _scrollEvent(actor, event) {
 | 
			
		||||
        this._scrollHandler(event.get_scroll_direction());
 | 
			
		||||
        return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,17 +1,376 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/* exported UnlockDialog */
 | 
			
		||||
 | 
			
		||||
const { AccountsService, Atk, Clutter,
 | 
			
		||||
        Gdm, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
 | 
			
		||||
const { AccountsService, Atk, Clutter, Gdm, Gio, GLib,
 | 
			
		||||
        GnomeDesktop, GObject, Meta, Shell, St } = imports.gi;
 | 
			
		||||
 | 
			
		||||
const Layout = imports.ui.layout;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const MessageTray = imports.ui.messageTray;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
 | 
			
		||||
const AuthPrompt = imports.gdm.authPrompt;
 | 
			
		||||
 | 
			
		||||
// The timeout before going back automatically to the lock screen (in seconds)
 | 
			
		||||
const IDLE_TIMEOUT = 2 * 60;
 | 
			
		||||
 | 
			
		||||
var SUMMARY_ICON_SIZE = 24;
 | 
			
		||||
 | 
			
		||||
var Clock = class {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        this.actor = new St.BoxLayout({
 | 
			
		||||
            style_class: 'screen-shield-clock',
 | 
			
		||||
            vertical: true,
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this._time = new St.Label({ style_class: 'screen-shield-clock-time' });
 | 
			
		||||
        this._date = new St.Label({ style_class: 'screen-shield-clock-date' });
 | 
			
		||||
 | 
			
		||||
        this.actor.add(this._time, { x_align: St.Align.MIDDLE });
 | 
			
		||||
        this.actor.add(this._date, { x_align: St.Align.MIDDLE });
 | 
			
		||||
 | 
			
		||||
        this._wallClock = new GnomeDesktop.WallClock({ time_only: true });
 | 
			
		||||
        this._wallClock.connect('notify::clock', this._updateClock.bind(this));
 | 
			
		||||
 | 
			
		||||
        this._updateClock();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _updateClock() {
 | 
			
		||||
        this._time.text = this._wallClock.clock;
 | 
			
		||||
 | 
			
		||||
        let date = new Date();
 | 
			
		||||
        /* Translators: This is a time format for a date in
 | 
			
		||||
           long format */
 | 
			
		||||
        let dateFormat = Shell.util_translate_time_string(N_("%A, %B %d"));
 | 
			
		||||
        this._date.text = date.toLocaleFormat(dateFormat);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    destroy() {
 | 
			
		||||
        this.actor.destroy();
 | 
			
		||||
        this._wallClock.run_dispose();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var NotificationsBox = class {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        this.actor = new St.BoxLayout({ vertical: true,
 | 
			
		||||
                                        name: 'screenShieldNotifications',
 | 
			
		||||
                                        style_class: 'screen-shield-notifications-container' });
 | 
			
		||||
 | 
			
		||||
        this._scrollView = new St.ScrollView({ x_fill: false, x_align: St.Align.START,
 | 
			
		||||
                                               hscrollbar_policy: St.PolicyType.NEVER });
 | 
			
		||||
        this._notificationBox = new St.BoxLayout({ vertical: true,
 | 
			
		||||
                                                   style_class: 'screen-shield-notifications-container' });
 | 
			
		||||
        this._scrollView.add_actor(this._notificationBox);
 | 
			
		||||
 | 
			
		||||
        this.actor.add(this._scrollView, { x_fill: true, x_align: St.Align.START });
 | 
			
		||||
 | 
			
		||||
        this._sources = new Map();
 | 
			
		||||
        Main.messageTray.getSources().forEach(source => {
 | 
			
		||||
            this._sourceAdded(Main.messageTray, source, true);
 | 
			
		||||
        });
 | 
			
		||||
        this._updateVisibility();
 | 
			
		||||
 | 
			
		||||
        this._sourceAddedId = Main.messageTray.connect('source-added', this._sourceAdded.bind(this));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    destroy() {
 | 
			
		||||
        if (this._sourceAddedId) {
 | 
			
		||||
            Main.messageTray.disconnect(this._sourceAddedId);
 | 
			
		||||
            this._sourceAddedId = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let items = this._sources.entries();
 | 
			
		||||
        for (let [source, obj] of items) {
 | 
			
		||||
            this._removeSource(source, obj);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.actor.destroy();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _updateVisibility() {
 | 
			
		||||
        this._notificationBox.visible =
 | 
			
		||||
            this._notificationBox.get_children().some(a => a.visible);
 | 
			
		||||
 | 
			
		||||
        this.actor.visible = this._notificationBox.visible;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _makeNotificationSource(source, box) {
 | 
			
		||||
        let sourceActor = new MessageTray.SourceActor(source, SUMMARY_ICON_SIZE);
 | 
			
		||||
        box.add(sourceActor, { y_fill: true });
 | 
			
		||||
 | 
			
		||||
        let title = new St.Label({
 | 
			
		||||
            text: source.title,
 | 
			
		||||
            style_class: 'screen-shield-notification-label',
 | 
			
		||||
            x_expand: true,
 | 
			
		||||
            y_align: Clutter.ActorAlign.START,
 | 
			
		||||
            y_expand: true,
 | 
			
		||||
            y_align: Clutter.ActorAlign.CENTER,
 | 
			
		||||
        });
 | 
			
		||||
        box.add_child(title);
 | 
			
		||||
 | 
			
		||||
        let count = source.unseenCount;
 | 
			
		||||
        let countLabel = new St.Label({
 | 
			
		||||
            text: '%d'.format(count),
 | 
			
		||||
            style_class: 'screen-shield-notification-count-text',
 | 
			
		||||
            y_expand: true,
 | 
			
		||||
            y_align: Clutter.ActorAlign.CENTER,
 | 
			
		||||
        });
 | 
			
		||||
        box.add_child(countLabel);
 | 
			
		||||
 | 
			
		||||
        box.visible = count != 0;
 | 
			
		||||
        return [title, countLabel];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _makeNotificationDetailedSource(source, box) {
 | 
			
		||||
        let sourceActor = new MessageTray.SourceActor(source, SUMMARY_ICON_SIZE);
 | 
			
		||||
        let sourceBin = new St.Bin({ y_align: St.Align.START,
 | 
			
		||||
                                     x_align: St.Align.START,
 | 
			
		||||
                                     child: sourceActor });
 | 
			
		||||
        box.add(sourceBin);
 | 
			
		||||
 | 
			
		||||
        let textBox = new St.BoxLayout({ vertical: true });
 | 
			
		||||
        box.add(textBox, { y_fill: false, y_align: St.Align.START });
 | 
			
		||||
 | 
			
		||||
        let title = new St.Label({ text: source.title,
 | 
			
		||||
                                   style_class: 'screen-shield-notification-label' });
 | 
			
		||||
        textBox.add(title);
 | 
			
		||||
 | 
			
		||||
        let visible = false;
 | 
			
		||||
        for (let i = 0; i < source.notifications.length; i++) {
 | 
			
		||||
            let n = source.notifications[i];
 | 
			
		||||
 | 
			
		||||
            if (n.acknowledged)
 | 
			
		||||
                continue;
 | 
			
		||||
 | 
			
		||||
            let body = '';
 | 
			
		||||
            if (n.bannerBodyText) {
 | 
			
		||||
                body = n.bannerBodyMarkup
 | 
			
		||||
                    ? n.bannerBodyText
 | 
			
		||||
                    : GLib.markup_escape_text(n.bannerBodyText, -1);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            let label = new St.Label({ style_class: 'screen-shield-notification-count-text' });
 | 
			
		||||
            label.clutter_text.set_markup('<b>' + n.title + '</b> ' + body);
 | 
			
		||||
            textBox.add(label);
 | 
			
		||||
 | 
			
		||||
            visible = true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        box.visible = visible;
 | 
			
		||||
        return [title, null];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _shouldShowDetails(source) {
 | 
			
		||||
        return source.policy.detailsInLockScreen ||
 | 
			
		||||
               source.narrowestPrivacyScope == MessageTray.PrivacyScope.SYSTEM;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _showSource(source, obj, box) {
 | 
			
		||||
        if (obj.detailed) {
 | 
			
		||||
            [obj.titleLabel, obj.countLabel] = this._makeNotificationDetailedSource(source, box);
 | 
			
		||||
        } else {
 | 
			
		||||
            [obj.titleLabel, obj.countLabel] = this._makeNotificationSource(source, box);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        box.visible = obj.visible && (source.unseenCount > 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _sourceAdded(tray, source, initial) {
 | 
			
		||||
        let obj = {
 | 
			
		||||
            visible: source.policy.showInLockScreen,
 | 
			
		||||
            detailed: this._shouldShowDetails(source),
 | 
			
		||||
            sourceDestroyId: 0,
 | 
			
		||||
            sourceCountChangedId: 0,
 | 
			
		||||
            sourceTitleChangedId: 0,
 | 
			
		||||
            sourceUpdatedId: 0,
 | 
			
		||||
            sourceBox: null,
 | 
			
		||||
            titleLabel: null,
 | 
			
		||||
            countLabel: null,
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        obj.sourceBox = new St.BoxLayout({ style_class: 'screen-shield-notification-source',
 | 
			
		||||
                                           x_expand: true });
 | 
			
		||||
        this._showSource(source, obj, obj.sourceBox);
 | 
			
		||||
        this._notificationBox.add(obj.sourceBox, { x_fill: false, x_align: St.Align.START });
 | 
			
		||||
 | 
			
		||||
        obj.sourceCountChangedId = source.connect('count-updated', source => {
 | 
			
		||||
            this._countChanged(source, obj);
 | 
			
		||||
        });
 | 
			
		||||
        obj.sourceTitleChangedId = source.connect('title-changed', source => {
 | 
			
		||||
            this._titleChanged(source, obj);
 | 
			
		||||
        });
 | 
			
		||||
        obj.policyChangedId = source.policy.connect('policy-changed', (policy, key) => {
 | 
			
		||||
            if (key == 'show-in-lock-screen')
 | 
			
		||||
                this._visibleChanged(source, obj);
 | 
			
		||||
            else
 | 
			
		||||
                this._detailedChanged(source, obj);
 | 
			
		||||
        });
 | 
			
		||||
        obj.sourceDestroyId = source.connect('destroy', source => {
 | 
			
		||||
            this._onSourceDestroy(source, obj);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this._sources.set(source, obj);
 | 
			
		||||
 | 
			
		||||
        if (!initial) {
 | 
			
		||||
            // block scrollbars while animating, if they're not needed now
 | 
			
		||||
            let boxHeight = this._notificationBox.height;
 | 
			
		||||
            if (this._scrollView.height >= boxHeight)
 | 
			
		||||
                this._scrollView.vscrollbar_policy = St.PolicyType.NEVER;
 | 
			
		||||
 | 
			
		||||
            let widget = obj.sourceBox;
 | 
			
		||||
            let [, natHeight] = widget.get_preferred_height(-1);
 | 
			
		||||
            widget.height = 0;
 | 
			
		||||
            widget.ease({
 | 
			
		||||
                height: natHeight,
 | 
			
		||||
                mode: Clutter.AnimationMode.EASE_OUT_QUAD,
 | 
			
		||||
                duration: 250,
 | 
			
		||||
                onComplete: () => {
 | 
			
		||||
                    this._scrollView.vscrollbar_policy = St.PolicyType.AUTOMATIC;
 | 
			
		||||
                    widget.set_height(-1);
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            this._updateVisibility();
 | 
			
		||||
            if (obj.sourceBox.visible)
 | 
			
		||||
                this.emit('wake-up-screen');
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _titleChanged(source, obj) {
 | 
			
		||||
        obj.titleLabel.text = source.title;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _countChanged(source, obj) {
 | 
			
		||||
        // A change in the number of notifications may change whether we show
 | 
			
		||||
        // details.
 | 
			
		||||
        let newDetailed = this._shouldShowDetails(source);
 | 
			
		||||
        let oldDetailed = obj.detailed;
 | 
			
		||||
 | 
			
		||||
        obj.detailed = newDetailed;
 | 
			
		||||
 | 
			
		||||
        if (obj.detailed || oldDetailed != newDetailed) {
 | 
			
		||||
            // A new notification was pushed, or a previous notification was destroyed.
 | 
			
		||||
            // Give up, and build the list again.
 | 
			
		||||
 | 
			
		||||
            obj.sourceBox.destroy_all_children();
 | 
			
		||||
            obj.titleLabel = obj.countLabel = null;
 | 
			
		||||
            this._showSource(source, obj, obj.sourceBox);
 | 
			
		||||
        } else {
 | 
			
		||||
            let count = source.unseenCount;
 | 
			
		||||
            obj.countLabel.text = '%d'.format(count);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        obj.sourceBox.visible = obj.visible && (source.unseenCount > 0);
 | 
			
		||||
 | 
			
		||||
        this._updateVisibility();
 | 
			
		||||
        if (obj.sourceBox.visible)
 | 
			
		||||
            this.emit('wake-up-screen');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _visibleChanged(source, obj) {
 | 
			
		||||
        if (obj.visible == source.policy.showInLockScreen)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        obj.visible = source.policy.showInLockScreen;
 | 
			
		||||
        obj.sourceBox.visible = obj.visible && source.unseenCount > 0;
 | 
			
		||||
 | 
			
		||||
        this._updateVisibility();
 | 
			
		||||
        if (obj.sourceBox.visible)
 | 
			
		||||
            this.emit('wake-up-screen');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _detailedChanged(source, obj) {
 | 
			
		||||
        let newDetailed = this._shouldShowDetails(source);
 | 
			
		||||
        if (obj.detailed == newDetailed)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        obj.detailed = newDetailed;
 | 
			
		||||
 | 
			
		||||
        obj.sourceBox.destroy_all_children();
 | 
			
		||||
        obj.titleLabel = obj.countLabel = null;
 | 
			
		||||
        this._showSource(source, obj, obj.sourceBox);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onSourceDestroy(source, obj) {
 | 
			
		||||
        this._removeSource(source, obj);
 | 
			
		||||
        this._updateVisibility();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _removeSource(source, obj) {
 | 
			
		||||
        obj.sourceBox.destroy();
 | 
			
		||||
        obj.sourceBox = obj.titleLabel = obj.countLabel = null;
 | 
			
		||||
 | 
			
		||||
        source.disconnect(obj.sourceDestroyId);
 | 
			
		||||
        source.disconnect(obj.sourceCountChangedId);
 | 
			
		||||
        source.disconnect(obj.sourceTitleChangedId);
 | 
			
		||||
        source.policy.disconnect(obj.policyChangedId);
 | 
			
		||||
 | 
			
		||||
        this._sources.delete(source);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(NotificationsBox.prototype);
 | 
			
		||||
 | 
			
		||||
var UnlockDialogLayout = GObject.registerClass(
 | 
			
		||||
class UnlockDialogLayout extends Clutter.LayoutManager {
 | 
			
		||||
    _init(clockStack, notifications) {
 | 
			
		||||
        super._init();
 | 
			
		||||
 | 
			
		||||
        this._clockStack = clockStack;
 | 
			
		||||
        this._notifications = notifications;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_get_preferred_width(container, forHeight) {
 | 
			
		||||
        return this._clockStack.get_preferred_width(forHeight);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_get_preferred_height(container, forWidth) {
 | 
			
		||||
        return this._clockStack.get_preferred_height(forWidth);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_allocate(container, box, flags) {
 | 
			
		||||
        let [width, height] = box.get_size();
 | 
			
		||||
 | 
			
		||||
        let tenthOfHeight = height / 10.0;
 | 
			
		||||
        let thirdOfHeight = height / 3.0;
 | 
			
		||||
 | 
			
		||||
        let [clockStackWidth, clockStackHeight] =
 | 
			
		||||
            this._clockStack.get_preferred_size();
 | 
			
		||||
 | 
			
		||||
        let [, , notificationsWidth, notificationsHeight] =
 | 
			
		||||
            this._notifications.get_preferred_size();
 | 
			
		||||
 | 
			
		||||
        let columnWidth = Math.max(clockStackWidth, notificationsWidth);
 | 
			
		||||
 | 
			
		||||
        let columnX1 = Math.floor(width / 2.0 - columnWidth / 2.0);
 | 
			
		||||
        let actorBox = new Clutter.ActorBox();
 | 
			
		||||
 | 
			
		||||
        // Notifications
 | 
			
		||||
        let maxNotificationsHeight = Math.min(
 | 
			
		||||
            notificationsHeight,
 | 
			
		||||
            height - tenthOfHeight - clockStackHeight);
 | 
			
		||||
 | 
			
		||||
        actorBox.x1 = columnX1;
 | 
			
		||||
        actorBox.y1 = height - maxNotificationsHeight;
 | 
			
		||||
        actorBox.x2 = columnX1 + columnWidth;
 | 
			
		||||
        actorBox.y2 = actorBox.y1 + maxNotificationsHeight;
 | 
			
		||||
 | 
			
		||||
        this._notifications.allocate(actorBox, flags);
 | 
			
		||||
 | 
			
		||||
        // Clock Stack
 | 
			
		||||
        let clockStackY = Math.min(
 | 
			
		||||
            thirdOfHeight,
 | 
			
		||||
            height - clockStackHeight - maxNotificationsHeight);
 | 
			
		||||
 | 
			
		||||
        actorBox.x1 = columnX1;
 | 
			
		||||
        actorBox.y1 = clockStackY;
 | 
			
		||||
        actorBox.x2 = columnX1 + columnWidth;
 | 
			
		||||
        actorBox.y2 = clockStackY + clockStackHeight;
 | 
			
		||||
 | 
			
		||||
        this._clockStack.allocate(actorBox, flags);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
var UnlockDialog = GObject.registerClass({
 | 
			
		||||
    Signals: { 'failed': {} },
 | 
			
		||||
}, class UnlockDialog extends St.Widget {
 | 
			
		||||
@@ -19,10 +378,16 @@ var UnlockDialog = GObject.registerClass({
 | 
			
		||||
        super._init({
 | 
			
		||||
            accessible_role: Atk.Role.WINDOW,
 | 
			
		||||
            style_class: 'login-dialog',
 | 
			
		||||
            layout_manager: new Clutter.BoxLayout(),
 | 
			
		||||
            reactive: true,
 | 
			
		||||
            visible: false,
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        let tapAction = new Clutter.TapAction();
 | 
			
		||||
        tapAction.connect('tap', () => {
 | 
			
		||||
            this._showAuth();
 | 
			
		||||
        })
 | 
			
		||||
        this.add_action(tapAction);
 | 
			
		||||
 | 
			
		||||
        this.add_constraint(new Layout.MonitorConstraint({ primary: true }));
 | 
			
		||||
        parentActor.add_child(this);
 | 
			
		||||
 | 
			
		||||
@@ -30,21 +395,31 @@ var UnlockDialog = GObject.registerClass({
 | 
			
		||||
        this._userName = GLib.get_user_name();
 | 
			
		||||
        this._user = this._userManager.get_user(this._userName);
 | 
			
		||||
 | 
			
		||||
        this._promptBox = new St.BoxLayout({ vertical: true,
 | 
			
		||||
                                             x_align: Clutter.ActorAlign.CENTER,
 | 
			
		||||
                                             y_align: Clutter.ActorAlign.CENTER,
 | 
			
		||||
                                             x_expand: true,
 | 
			
		||||
                                             y_expand: true });
 | 
			
		||||
        this.add_child(this._promptBox);
 | 
			
		||||
        let clockStack = new Shell.Stack();
 | 
			
		||||
        this.add_child(clockStack);
 | 
			
		||||
 | 
			
		||||
        this._clock = new Clock();
 | 
			
		||||
        clockStack.add_child(this._clock.actor);
 | 
			
		||||
 | 
			
		||||
        this._activePage  = this._clock.actor;
 | 
			
		||||
 | 
			
		||||
        this._authBox = new St.BoxLayout({
 | 
			
		||||
            x_align: Clutter.ActorAlign.CENTER,
 | 
			
		||||
            y_align: Clutter.ActorAlign.CENTER,
 | 
			
		||||
            x_expand: true,
 | 
			
		||||
            y_expand: true,
 | 
			
		||||
            vertical: true,
 | 
			
		||||
            visible: false,
 | 
			
		||||
        });
 | 
			
		||||
        clockStack.add_child(this._authBox);
 | 
			
		||||
 | 
			
		||||
        this._authPrompt = new AuthPrompt.AuthPrompt(new Gdm.Client(), AuthPrompt.AuthPromptMode.UNLOCK_ONLY);
 | 
			
		||||
        this._authPrompt.connect('failed', this._fail.bind(this));
 | 
			
		||||
        this._authPrompt.connect('cancelled', this._fail.bind(this));
 | 
			
		||||
        this._authPrompt.connect('reset', this._onReset.bind(this));
 | 
			
		||||
        this._authPrompt.setPasswordChar('\u25cf');
 | 
			
		||||
        this._authPrompt.nextButton.label = _("Unlock");
 | 
			
		||||
 | 
			
		||||
        this._promptBox.add_child(this._authPrompt);
 | 
			
		||||
        this._authBox.add_child(this._authPrompt.actor);
 | 
			
		||||
 | 
			
		||||
        this.allowCancel = false;
 | 
			
		||||
 | 
			
		||||
@@ -59,11 +434,15 @@ var UnlockDialog = GObject.registerClass({
 | 
			
		||||
                                                    x_align: St.Align.START,
 | 
			
		||||
                                                    x_fill: false });
 | 
			
		||||
            this._otherUserButton.connect('clicked', this._otherUserClicked.bind(this));
 | 
			
		||||
            this._promptBox.add_child(this._otherUserButton);
 | 
			
		||||
            this._authBox.add_child(this._otherUserButton);
 | 
			
		||||
        } else {
 | 
			
		||||
            this._otherUserButton = null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._notificationsBox = new NotificationsBox();
 | 
			
		||||
        this._wakeUpScreenId = this._notificationsBox.connect('wake-up-screen', this._wakeUpScreen.bind(this));
 | 
			
		||||
        this.add_child(this._notificationsBox.actor);
 | 
			
		||||
 | 
			
		||||
        this._authPrompt.reset();
 | 
			
		||||
        this._updateSensitivity(true);
 | 
			
		||||
 | 
			
		||||
@@ -72,9 +451,81 @@ var UnlockDialog = GObject.registerClass({
 | 
			
		||||
        this._idleMonitor = Meta.IdleMonitor.get_core();
 | 
			
		||||
        this._idleWatchId = this._idleMonitor.add_idle_watch(IDLE_TIMEOUT * 1000, this._escape.bind(this));
 | 
			
		||||
 | 
			
		||||
        this.layout_manager = new UnlockDialogLayout(
 | 
			
		||||
            clockStack,
 | 
			
		||||
            this._notificationsBox.actor);
 | 
			
		||||
 | 
			
		||||
        this.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _showClock() {
 | 
			
		||||
        if (this._activePage == this._clock.actor)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._activePage = this._clock.actor;
 | 
			
		||||
        this._clock.actor.show();
 | 
			
		||||
 | 
			
		||||
        this._authBox.ease({
 | 
			
		||||
            opacity: 0,
 | 
			
		||||
            duration: 300,
 | 
			
		||||
            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
 | 
			
		||||
            onComplete: () => this._authBox.hide(),
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this._clock.actor.ease({
 | 
			
		||||
            opacity: 255,
 | 
			
		||||
            duration: 300,
 | 
			
		||||
            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _showAuth() {
 | 
			
		||||
        if (this._activePage == this._authBox)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._activePage = this._authBox;
 | 
			
		||||
        this._authBox.show();
 | 
			
		||||
 | 
			
		||||
        this._clock.actor.ease({
 | 
			
		||||
            opacity: 0,
 | 
			
		||||
            duration: 300,
 | 
			
		||||
            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
 | 
			
		||||
            onComplete: () => this._clock.actor.hide(),
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this._authBox.ease({
 | 
			
		||||
            opacity: 255,
 | 
			
		||||
            duration: 300,
 | 
			
		||||
            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_captured_event(event) {
 | 
			
		||||
        if (event.type() != Clutter.EventType.KEY_PRESS)
 | 
			
		||||
            return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
 | 
			
		||||
        if (this._activePage == this._authBox)
 | 
			
		||||
            return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
 | 
			
		||||
        let symbol = event.get_key_symbol();
 | 
			
		||||
        let unichar = event.get_key_unicode();
 | 
			
		||||
 | 
			
		||||
        let isEnter = (symbol == Clutter.KEY_Return ||
 | 
			
		||||
                       symbol == Clutter.KEY_KP_Enter ||
 | 
			
		||||
                       symbol == Clutter.KEY_ISO_Enter);
 | 
			
		||||
        let isEscape = (symbol == Clutter.KEY_Escape);
 | 
			
		||||
        let isLiftChar = (GLib.unichar_isprint(unichar) &&
 | 
			
		||||
                          (this._activePage == this._clock.actor ||
 | 
			
		||||
                          !GLib.unichar_isgraph(unichar)));
 | 
			
		||||
 | 
			
		||||
        if (!isEnter && !isEscape && !isLiftChar)
 | 
			
		||||
            return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
 | 
			
		||||
        this._showAuth();
 | 
			
		||||
 | 
			
		||||
        return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _updateSensitivity(sensitive) {
 | 
			
		||||
        this._authPrompt.updateSensitivity(sensitive);
 | 
			
		||||
 | 
			
		||||
@@ -85,6 +536,7 @@ var UnlockDialog = GObject.registerClass({
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _fail() {
 | 
			
		||||
        this._showClock();
 | 
			
		||||
        this.emit('failed');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -111,9 +563,24 @@ var UnlockDialog = GObject.registerClass({
 | 
			
		||||
        this._authPrompt.cancel();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _wakeUpScreen() {
 | 
			
		||||
        // FIXME
 | 
			
		||||
        //this._onUserBecameActive();
 | 
			
		||||
        this.emit('wake-up-screen');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onDestroy() {
 | 
			
		||||
        this.popModal();
 | 
			
		||||
 | 
			
		||||
        if (this._notificationsBox) {
 | 
			
		||||
            this._notificationsBox.disconnect(this._wakeUpScreenId);
 | 
			
		||||
            this._notificationsBox.destroy();
 | 
			
		||||
            this._notificationsBox = null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._clock.destroy();
 | 
			
		||||
        this._clock = null;
 | 
			
		||||
 | 
			
		||||
        if (this._idleWatchId) {
 | 
			
		||||
            this._idleMonitor.remove_watch(this._idleWatchId);
 | 
			
		||||
            this._idleWatchId = 0;
 | 
			
		||||
@@ -122,11 +589,10 @@ var UnlockDialog = GObject.registerClass({
 | 
			
		||||
 | 
			
		||||
    cancel() {
 | 
			
		||||
        this._authPrompt.cancel();
 | 
			
		||||
 | 
			
		||||
        this.destroy();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    addCharacter(unichar) {
 | 
			
		||||
        this._showAuth();
 | 
			
		||||
        this._authPrompt.addCharacter(unichar);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -14,47 +14,29 @@ var AVATAR_ICON_SIZE = 64;
 | 
			
		||||
// Copyright (C) 2004-2005 James M. Cape <jcape@ignore-your.tv>.
 | 
			
		||||
// Copyright (C) 2008,2009 Red Hat, Inc.
 | 
			
		||||
 | 
			
		||||
var Avatar = GObject.registerClass({
 | 
			
		||||
    GTypeName: 'UserWidget_Avatar'
 | 
			
		||||
}, class Avatar extends St.Bin {
 | 
			
		||||
    _init(user, params) {
 | 
			
		||||
        let themeContext = St.ThemeContext.get_for_stage(global.stage);
 | 
			
		||||
var Avatar = class {
 | 
			
		||||
    constructor(user, params) {
 | 
			
		||||
        this._user = user;
 | 
			
		||||
        params = Params.parse(params, { reactive: false,
 | 
			
		||||
                                        iconSize: AVATAR_ICON_SIZE,
 | 
			
		||||
                                        styleClass: 'user-icon' });
 | 
			
		||||
 | 
			
		||||
        super._init({
 | 
			
		||||
            style_class: params.styleClass,
 | 
			
		||||
            reactive: params.reactive,
 | 
			
		||||
            width: params.iconSize * themeContext.scaleFactor,
 | 
			
		||||
            height: params.iconSize * themeContext.scaleFactor
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this._iconSize = params.iconSize;
 | 
			
		||||
        this._user = user;
 | 
			
		||||
 | 
			
		||||
        this.bind_property('reactive', this, 'track-hover',
 | 
			
		||||
            GObject.BindingFlags.SYNC_CREATE);
 | 
			
		||||
        this.bind_property('reactive', this, 'can-focus',
 | 
			
		||||
            GObject.BindingFlags.SYNC_CREATE);
 | 
			
		||||
        let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
 | 
			
		||||
        this.actor = new St.Bin({ style_class: params.styleClass,
 | 
			
		||||
                                  track_hover: params.reactive,
 | 
			
		||||
                                  reactive: params.reactive,
 | 
			
		||||
                                  width: this._iconSize * scaleFactor,
 | 
			
		||||
                                  height: this._iconSize * scaleFactor });
 | 
			
		||||
 | 
			
		||||
        // Monitor the scaling factor to make sure we recreate the avatar when needed.
 | 
			
		||||
        this._scaleFactorChangeId =
 | 
			
		||||
            themeContext.connect('notify::scale-factor', this.update.bind(this));
 | 
			
		||||
 | 
			
		||||
        this.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onDestroy() {
 | 
			
		||||
        if (this._scaleFactorChangeId) {
 | 
			
		||||
            let themeContext = St.ThemeContext.get_for_stage(global.stage);
 | 
			
		||||
            themeContext.disconnect(this._scaleFactorChangeId);
 | 
			
		||||
            delete this._scaleFactorChangeId;
 | 
			
		||||
        }
 | 
			
		||||
        let themeContext = St.ThemeContext.get_for_stage(global.stage);
 | 
			
		||||
        themeContext.connect('notify::scale-factor', this.update.bind(this));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    setSensitive(sensitive) {
 | 
			
		||||
        this.reactive = sensitive;
 | 
			
		||||
        this.actor.can_focus = sensitive;
 | 
			
		||||
        this.actor.reactive = sensitive;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    update() {
 | 
			
		||||
@@ -63,21 +45,21 @@ var Avatar = GObject.registerClass({
 | 
			
		||||
            iconFile = null;
 | 
			
		||||
 | 
			
		||||
        if (iconFile) {
 | 
			
		||||
            this.child = null;
 | 
			
		||||
            this.actor.child = null;
 | 
			
		||||
            let { scaleFactor } = St.ThemeContext.get_for_stage(global.stage);
 | 
			
		||||
            this.set_size(
 | 
			
		||||
            this.actor.set_size(
 | 
			
		||||
                this._iconSize * scaleFactor,
 | 
			
		||||
                this._iconSize * scaleFactor);
 | 
			
		||||
            this.style = `
 | 
			
		||||
            this.actor.style = `
 | 
			
		||||
                background-image: url("${iconFile}");
 | 
			
		||||
                background-size: cover;`;
 | 
			
		||||
        } else {
 | 
			
		||||
            this.style = null;
 | 
			
		||||
            this.child = new St.Icon({ icon_name: 'avatar-default-symbolic',
 | 
			
		||||
                                       icon_size: this._iconSize });
 | 
			
		||||
            this.actor.style = null;
 | 
			
		||||
            this.actor.child = new St.Icon({ icon_name: 'avatar-default-symbolic',
 | 
			
		||||
                                             icon_size: this._iconSize });
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var UserWidgetLabel = GObject.registerClass(
 | 
			
		||||
class UserWidgetLabel extends St.Widget {
 | 
			
		||||
@@ -158,22 +140,21 @@ class UserWidgetLabel extends St.Widget {
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
var UserWidget = GObject.registerClass(
 | 
			
		||||
class UserWidget extends St.BoxLayout {
 | 
			
		||||
    _init(user) {
 | 
			
		||||
        super._init({ style_class: 'user-widget', vertical: false });
 | 
			
		||||
 | 
			
		||||
var UserWidget = class {
 | 
			
		||||
    constructor(user) {
 | 
			
		||||
        this._user = user;
 | 
			
		||||
 | 
			
		||||
        this.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
        this.actor = new St.BoxLayout({ style_class: 'user-widget',
 | 
			
		||||
                                        vertical: false });
 | 
			
		||||
        this.actor.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
 | 
			
		||||
        this._avatar = new Avatar(user);
 | 
			
		||||
        this.add_child(this._avatar);
 | 
			
		||||
        this.actor.add_child(this._avatar.actor);
 | 
			
		||||
 | 
			
		||||
        this._label = new UserWidgetLabel(user);
 | 
			
		||||
        this.add_child(this._label);
 | 
			
		||||
        this.actor.add_child(this._label);
 | 
			
		||||
 | 
			
		||||
        this._label.bind_property('label-actor', this, 'label-actor',
 | 
			
		||||
        this._label.bind_property('label-actor', this.actor, 'label-actor',
 | 
			
		||||
                                  GObject.BindingFlags.SYNC_CREATE);
 | 
			
		||||
 | 
			
		||||
        this._userLoadedId = this._user.connect('notify::is-loaded', this._updateUser.bind(this));
 | 
			
		||||
@@ -196,4 +177,4 @@ class UserWidget extends St.BoxLayout {
 | 
			
		||||
    _updateUser() {
 | 
			
		||||
        this._avatar.update();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -123,14 +123,9 @@ var ShowOverviewAction = GObject.registerClass({
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
var ViewSelector = GObject.registerClass({
 | 
			
		||||
    Signals: {
 | 
			
		||||
        'page-changed': {},
 | 
			
		||||
        'page-empty': {},
 | 
			
		||||
    }
 | 
			
		||||
}, class ViewSelector extends Shell.Stack {
 | 
			
		||||
    _init(searchEntry, showAppsButton) {
 | 
			
		||||
        super._init({ name: 'viewSelector' });
 | 
			
		||||
var ViewSelector = class {
 | 
			
		||||
    constructor(searchEntry, showAppsButton) {
 | 
			
		||||
        this.actor = new Shell.Stack({ name: 'viewSelector' });
 | 
			
		||||
 | 
			
		||||
        this._showAppsButton = showAppsButton;
 | 
			
		||||
        this._showAppsButton.connect('notify::checked', this._onShowAppsButtonToggled.bind(this));
 | 
			
		||||
@@ -170,15 +165,15 @@ var ViewSelector = GObject.registerClass({
 | 
			
		||||
        this._capturedEventId = 0;
 | 
			
		||||
 | 
			
		||||
        this._workspacesDisplay = new WorkspacesView.WorkspacesDisplay();
 | 
			
		||||
        this._workspacesPage = this._addPage(this._workspacesDisplay,
 | 
			
		||||
        this._workspacesPage = this._addPage(this._workspacesDisplay.actor,
 | 
			
		||||
                                             _("Windows"), 'focus-windows-symbolic');
 | 
			
		||||
 | 
			
		||||
        this.appDisplay = new AppDisplay.AppDisplay();
 | 
			
		||||
        this._appsPage = this._addPage(this.appDisplay,
 | 
			
		||||
        this._appsPage = this._addPage(this.appDisplay.actor,
 | 
			
		||||
                                       _("Applications"), 'view-app-grid-symbolic');
 | 
			
		||||
 | 
			
		||||
        this._searchResults = new Search.SearchResultsView();
 | 
			
		||||
        this._searchPage = this._addPage(this._searchResults,
 | 
			
		||||
        this._searchResults = new Search.SearchResults();
 | 
			
		||||
        this._searchPage = this._addPage(this._searchResults.actor,
 | 
			
		||||
                                         _("Search"), 'edit-find-symbolic',
 | 
			
		||||
                                         { a11yFocus: this._entry });
 | 
			
		||||
 | 
			
		||||
@@ -189,9 +184,9 @@ var ViewSelector = GObject.registerClass({
 | 
			
		||||
        this._focusTrap.connect('key-focus-in', () => {
 | 
			
		||||
            this._entry.grab_key_focus();
 | 
			
		||||
        });
 | 
			
		||||
        this._searchResults.add_actor(this._focusTrap);
 | 
			
		||||
        this._searchResults.actor.add_actor(this._focusTrap);
 | 
			
		||||
 | 
			
		||||
        global.focus_manager.add_group(this._searchResults);
 | 
			
		||||
        global.focus_manager.add_group(this._searchResults.actor);
 | 
			
		||||
 | 
			
		||||
        this._stageKeyPressId = 0;
 | 
			
		||||
        Main.overview.connect('showing', () => {
 | 
			
		||||
@@ -315,11 +310,11 @@ var ViewSelector = GObject.registerClass({
 | 
			
		||||
            Main.ctrlAltTabManager.addGroup(params.a11yFocus, name, a11yIcon);
 | 
			
		||||
        else
 | 
			
		||||
            Main.ctrlAltTabManager.addGroup(actor, name, a11yIcon, {
 | 
			
		||||
                proxy: this,
 | 
			
		||||
                proxy: this.actor,
 | 
			
		||||
                focusCallback: () => this._a11yFocusPage(page),
 | 
			
		||||
            });
 | 
			
		||||
        page.hide();
 | 
			
		||||
        this.add_actor(page);
 | 
			
		||||
        this.actor.add_actor(page);
 | 
			
		||||
        return page;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -459,7 +454,7 @@ var ViewSelector = GObject.registerClass({
 | 
			
		||||
    _onStageKeyFocusChanged() {
 | 
			
		||||
        let focus = global.stage.get_key_focus();
 | 
			
		||||
        let appearFocused = (this._entry.contains(focus) ||
 | 
			
		||||
                             this._searchResults.contains(focus));
 | 
			
		||||
                             this._searchResults.actor.contains(focus));
 | 
			
		||||
 | 
			
		||||
        this._text.set_cursor_visible(appearFocused);
 | 
			
		||||
 | 
			
		||||
@@ -604,4 +599,5 @@ var ViewSelector = GObject.registerClass({
 | 
			
		||||
        else
 | 
			
		||||
            return ViewPage.SEARCH;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(ViewSelector.prototype);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/* exported WindowAttentionHandler */
 | 
			
		||||
 | 
			
		||||
const { GObject, Shell } = imports.gi;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const MessageTray = imports.ui.messageTray;
 | 
			
		||||
@@ -34,7 +34,7 @@ var WindowAttentionHandler = class {
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let app = this._tracker.get_window_app(window);
 | 
			
		||||
        let source = new WindowAttentionSource(app, window);
 | 
			
		||||
        let source = new Source(app, window);
 | 
			
		||||
        Main.messageTray.add(source);
 | 
			
		||||
 | 
			
		||||
        let [title, banner] = this._getTitleAndBanner(app, window);
 | 
			
		||||
@@ -45,7 +45,7 @@ var WindowAttentionHandler = class {
 | 
			
		||||
        });
 | 
			
		||||
        notification.setForFeedback(true);
 | 
			
		||||
 | 
			
		||||
        source.showNotification(notification);
 | 
			
		||||
        source.notify(notification);
 | 
			
		||||
 | 
			
		||||
        source.signalIDs.push(window.connect('notify::title', () => {
 | 
			
		||||
            let [title, banner] = this._getTitleAndBanner(app, window);
 | 
			
		||||
@@ -54,10 +54,9 @@ var WindowAttentionHandler = class {
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var WindowAttentionSource = GObject.registerClass(
 | 
			
		||||
class WindowAttentionSource extends MessageTray.Source {
 | 
			
		||||
    _init(app, window) {
 | 
			
		||||
        super._init(app.get_name());
 | 
			
		||||
var Source = class WindowAttentionSource extends MessageTray.Source {
 | 
			
		||||
    constructor(app, window) {
 | 
			
		||||
        super(app.get_name());
 | 
			
		||||
 | 
			
		||||
        this._window = window;
 | 
			
		||||
        this._app = app;
 | 
			
		||||
@@ -103,4 +102,4 @@ class WindowAttentionSource extends MessageTray.Source {
 | 
			
		||||
    open() {
 | 
			
		||||
        Main.activateWindow(this._window);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -40,8 +40,6 @@ const GSD_WACOM_OBJECT_PATH = '/org/gnome/SettingsDaemon/Wacom';
 | 
			
		||||
const GsdWacomIface = loadInterfaceXML('org.gnome.SettingsDaemon.Wacom');
 | 
			
		||||
const GsdWacomProxy = Gio.DBusProxy.makeProxyWrapper(GsdWacomIface);
 | 
			
		||||
 | 
			
		||||
const WINDOW_DIMMER_EFFECT_NAME = "gnome-shell-window-dimmer";
 | 
			
		||||
 | 
			
		||||
var DisplayChangeDialog = GObject.registerClass(
 | 
			
		||||
class DisplayChangeDialog extends ModalDialog.ModalDialog {
 | 
			
		||||
    _init(wm) {
 | 
			
		||||
@@ -116,20 +114,21 @@ class DisplayChangeDialog extends ModalDialog.ModalDialog {
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
var WindowDimmer = GObject.registerClass(
 | 
			
		||||
class WindowDimmer extends Clutter.BrightnessContrastEffect {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init({
 | 
			
		||||
            name: WINDOW_DIMMER_EFFECT_NAME,
 | 
			
		||||
var WindowDimmer = class {
 | 
			
		||||
    constructor(actor) {
 | 
			
		||||
        this._brightnessEffect = new Clutter.BrightnessContrastEffect({
 | 
			
		||||
            name: 'dim',
 | 
			
		||||
            enabled: false
 | 
			
		||||
        });
 | 
			
		||||
        actor.add_effect(this._brightnessEffect);
 | 
			
		||||
        this.actor = actor;
 | 
			
		||||
        this._enabled = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _syncEnabled() {
 | 
			
		||||
        let animating = this.actor.get_transition(`@effects.${this.name}.brightness`) != null;
 | 
			
		||||
        let dimmed = this.brightness.red != 127;
 | 
			
		||||
        this.enabled = this._enabled && (animating || dimmed);
 | 
			
		||||
        let animating = this.actor.get_transition('@effects.dim.brightness') != null;
 | 
			
		||||
        let dimmed = this._brightnessEffect.brightness.red != 127;
 | 
			
		||||
        this._brightnessEffect.enabled = this._enabled && (animating || dimmed);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    setEnabled(enabled) {
 | 
			
		||||
@@ -141,7 +140,7 @@ class WindowDimmer extends Clutter.BrightnessContrastEffect {
 | 
			
		||||
        let val = 127 * (1 + (dimmed ? 1 : 0) * DIM_BRIGHTNESS);
 | 
			
		||||
        let color = Clutter.Color.new(val, val, val, 255);
 | 
			
		||||
 | 
			
		||||
        this.actor.ease_property(`@effects.${this.name}.brightness`, color, {
 | 
			
		||||
        this.actor.ease_property('@effects.dim.brightness', color, {
 | 
			
		||||
            mode: Clutter.AnimationMode.LINEAR,
 | 
			
		||||
            duration: (dimmed ? DIM_TIME : UNDIM_TIME) * (animate ? 1 : 0),
 | 
			
		||||
            onComplete: () => this._syncEnabled()
 | 
			
		||||
@@ -149,19 +148,20 @@ class WindowDimmer extends Clutter.BrightnessContrastEffect {
 | 
			
		||||
 | 
			
		||||
        this._syncEnabled();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function getWindowDimmer(actor) {
 | 
			
		||||
    let enabled = Meta.prefs_get_attach_modal_dialogs();
 | 
			
		||||
    let effect = actor.get_effect(WINDOW_DIMMER_EFFECT_NAME);
 | 
			
		||||
    if (actor._windowDimmer)
 | 
			
		||||
        actor._windowDimmer.setEnabled(enabled);
 | 
			
		||||
 | 
			
		||||
    if (effect) {
 | 
			
		||||
        effect.setEnabled(enabled);
 | 
			
		||||
    } else if (enabled) {
 | 
			
		||||
        effect = new WindowDimmer();
 | 
			
		||||
        actor.add_effect(effect);
 | 
			
		||||
    if (enabled) {
 | 
			
		||||
        if (!actor._windowDimmer)
 | 
			
		||||
            actor._windowDimmer = new WindowDimmer(actor);
 | 
			
		||||
        return actor._windowDimmer;
 | 
			
		||||
    } else {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
    return effect;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
@@ -379,22 +379,21 @@ var WorkspaceTracker = class {
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var TilePreview = GObject.registerClass(
 | 
			
		||||
class TilePreview extends St.Widget {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init();
 | 
			
		||||
        global.window_group.add_actor(this);
 | 
			
		||||
var TilePreview = class {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        this.actor = new St.Widget();
 | 
			
		||||
        global.window_group.add_actor(this.actor);
 | 
			
		||||
 | 
			
		||||
        this._reset();
 | 
			
		||||
        this._showing = false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    open(window, tileRect, monitorIndex) {
 | 
			
		||||
    show(window, tileRect, monitorIndex) {
 | 
			
		||||
        let windowActor = window.get_compositor_private();
 | 
			
		||||
        if (!windowActor)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        global.window_group.set_child_below_sibling(this, windowActor);
 | 
			
		||||
        global.window_group.set_child_below_sibling(this.actor, windowActor);
 | 
			
		||||
 | 
			
		||||
        if (this._rect && this._rect.equal(tileRect))
 | 
			
		||||
            return;
 | 
			
		||||
@@ -415,14 +414,14 @@ class TilePreview extends St.Widget {
 | 
			
		||||
                                                   width: monitor.width,
 | 
			
		||||
                                                   height: monitor.height });
 | 
			
		||||
            let [, rect] = window.get_frame_rect().intersect(monitorRect);
 | 
			
		||||
            this.set_size(rect.width, rect.height);
 | 
			
		||||
            this.set_position(rect.x, rect.y);
 | 
			
		||||
            this.opacity = 0;
 | 
			
		||||
            this.actor.set_size(rect.width, rect.height);
 | 
			
		||||
            this.actor.set_position(rect.x, rect.y);
 | 
			
		||||
            this.actor.opacity = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._showing = true;
 | 
			
		||||
        this.show();
 | 
			
		||||
        this.ease({
 | 
			
		||||
        this.actor.show();
 | 
			
		||||
        this.actor.ease({
 | 
			
		||||
            x: tileRect.x,
 | 
			
		||||
            y: tileRect.y,
 | 
			
		||||
            width: tileRect.width,
 | 
			
		||||
@@ -433,12 +432,12 @@ class TilePreview extends St.Widget {
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    close() {
 | 
			
		||||
    hide() {
 | 
			
		||||
        if (!this._showing)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._showing = false;
 | 
			
		||||
        this.ease({
 | 
			
		||||
        this.actor.ease({
 | 
			
		||||
            opacity: 0,
 | 
			
		||||
            duration: WINDOW_ANIMATION_TIME,
 | 
			
		||||
            mode: Clutter.AnimationMode.EASE_OUT_QUAD,
 | 
			
		||||
@@ -447,7 +446,7 @@ class TilePreview extends St.Widget {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _reset() {
 | 
			
		||||
        this.hide();
 | 
			
		||||
        this.actor.hide();
 | 
			
		||||
        this._rect = null;
 | 
			
		||||
        this._monitorIndex = -1;
 | 
			
		||||
    }
 | 
			
		||||
@@ -461,9 +460,9 @@ class TilePreview extends St.Widget {
 | 
			
		||||
        if (this._rect.x + this._rect.width == monitor.x + monitor.width)
 | 
			
		||||
            styles.push('tile-preview-right');
 | 
			
		||||
 | 
			
		||||
        this.style_class = styles.join(' ');
 | 
			
		||||
        this.actor.style_class = styles.join(' ');
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var TouchpadWorkspaceSwitchAction = class {
 | 
			
		||||
    constructor(actor, allowedModes) {
 | 
			
		||||
@@ -670,16 +669,15 @@ var AppSwitchAction = GObject.registerClass({
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
var ResizePopup = GObject.registerClass(
 | 
			
		||||
class ResizePopup extends St.Widget {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init({ layout_manager: new Clutter.BinLayout() });
 | 
			
		||||
var ResizePopup = class {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        this._widget = new St.Widget({ layout_manager: new Clutter.BinLayout() });
 | 
			
		||||
        this._label = new St.Label({ style_class: 'resize-popup',
 | 
			
		||||
                                     x_align: Clutter.ActorAlign.CENTER,
 | 
			
		||||
                                     y_align: Clutter.ActorAlign.CENTER,
 | 
			
		||||
                                     x_expand: true, y_expand: true });
 | 
			
		||||
        this.add_child(this._label);
 | 
			
		||||
        Main.uiGroup.add_actor(this);
 | 
			
		||||
        this._widget.add_child(this._label);
 | 
			
		||||
        Main.uiGroup.add_actor(this._widget);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    set(rect, displayW, displayH) {
 | 
			
		||||
@@ -688,10 +686,15 @@ class ResizePopup extends St.Widget {
 | 
			
		||||
        let text = _("%d × %d").format(displayW, displayH);
 | 
			
		||||
        this._label.set_text(text);
 | 
			
		||||
 | 
			
		||||
        this.set_position(rect.x, rect.y);
 | 
			
		||||
        this.set_size(rect.width, rect.height);
 | 
			
		||||
        this._widget.set_position(rect.x, rect.y);
 | 
			
		||||
        this._widget.set_size(rect.width, rect.height);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
    destroy() {
 | 
			
		||||
        this._widget.destroy();
 | 
			
		||||
        this._widget = null;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var WindowManager = class {
 | 
			
		||||
    constructor() {
 | 
			
		||||
@@ -1086,7 +1089,7 @@ var WindowManager = class {
 | 
			
		||||
        let mode = Shell.ActionMode.ALL & ~Shell.ActionMode.LOCK_SCREEN;
 | 
			
		||||
        let bottomDragAction = new EdgeDragAction.EdgeDragAction(St.Side.BOTTOM, mode);
 | 
			
		||||
        bottomDragAction.connect('activated', () => {
 | 
			
		||||
            Main.keyboard.open(Main.layoutManager.bottomIndex);
 | 
			
		||||
            Main.keyboard.show(Main.layoutManager.bottomIndex);
 | 
			
		||||
        });
 | 
			
		||||
        Main.layoutManager.connect('keyboard-visible-changed', (manager, visible) => {
 | 
			
		||||
            bottomDragAction.cancel();
 | 
			
		||||
@@ -1116,7 +1119,7 @@ var WindowManager = class {
 | 
			
		||||
        this._currentPadOsd = new PadOsd.PadOsd(device, settings, imagePath, editionMode, monitorIndex);
 | 
			
		||||
        this._currentPadOsd.connect('closed', () => (this._currentPadOsd = null));
 | 
			
		||||
 | 
			
		||||
        return this._currentPadOsd;
 | 
			
		||||
        return this._currentPadOsd.actor;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _switchWorkspaceMotion(action, xRel, yRel) {
 | 
			
		||||
@@ -2042,13 +2045,13 @@ var WindowManager = class {
 | 
			
		||||
    _showTilePreview(shellwm, window, tileRect, monitorIndex) {
 | 
			
		||||
        if (!this._tilePreview)
 | 
			
		||||
            this._tilePreview = new TilePreview();
 | 
			
		||||
        this._tilePreview.open(window, tileRect, monitorIndex);
 | 
			
		||||
        this._tilePreview.show(window, tileRect, monitorIndex);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _hideTilePreview() {
 | 
			
		||||
        if (!this._tilePreview)
 | 
			
		||||
            return;
 | 
			
		||||
        this._tilePreview.close();
 | 
			
		||||
        this._tilePreview.hide();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _showWindowMenu(shellwm, window, menu, rect) {
 | 
			
		||||
 
 | 
			
		||||
@@ -84,7 +84,7 @@ class WindowCloneLayout extends Clutter.LayoutManager {
 | 
			
		||||
            if (child == container._windowClone)
 | 
			
		||||
                realWindow = container.realWindow;
 | 
			
		||||
            else
 | 
			
		||||
                realWindow = child.content.window_actor;
 | 
			
		||||
                realWindow = child.source;
 | 
			
		||||
 | 
			
		||||
            child.allocate(this._makeBoxForWindow(realWindow.meta_window),
 | 
			
		||||
                           flags);
 | 
			
		||||
@@ -93,7 +93,6 @@ class WindowCloneLayout extends Clutter.LayoutManager {
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
var WindowClone = GObject.registerClass({
 | 
			
		||||
    GTypeName: 'Workspace_WindowClone',
 | 
			
		||||
    Signals: {
 | 
			
		||||
        'drag-begin': {},
 | 
			
		||||
        'drag-cancelled': {},
 | 
			
		||||
@@ -103,14 +102,14 @@ var WindowClone = GObject.registerClass({
 | 
			
		||||
        'show-chrome': {},
 | 
			
		||||
        'size-changed': {}
 | 
			
		||||
    },
 | 
			
		||||
}, class WindowClone extends St.Widget {
 | 
			
		||||
}, class WorkspaceWindowClone 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.Actor({ content: realWindow.content });
 | 
			
		||||
        this._windowClone = new Clutter.Clone({ source: realWindow });
 | 
			
		||||
        // 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
 | 
			
		||||
@@ -163,6 +162,13 @@ var WindowClone = GObject.registerClass({
 | 
			
		||||
        clickAction.connect('long-press', this._onLongPress.bind(this));
 | 
			
		||||
        this.add_action(clickAction);
 | 
			
		||||
        this.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
        this.connect('key-press-event', this._onKeyPress.bind(this));
 | 
			
		||||
 | 
			
		||||
        this.connect('enter-event', () => this.emit('show-chrome'));
 | 
			
		||||
        this.connect('key-focus-in', () => this.emit('show-chrome'));
 | 
			
		||||
 | 
			
		||||
        this.connect('leave-event', () => this.emit('hide-chrome'));
 | 
			
		||||
        this.connect('key-focus-out', () => this.emit('hide-chrome'));
 | 
			
		||||
 | 
			
		||||
        this._draggable = DND.makeDraggable(this,
 | 
			
		||||
                                            { restoreOnSuccess: true,
 | 
			
		||||
@@ -197,7 +203,7 @@ var WindowClone = GObject.registerClass({
 | 
			
		||||
        // Delete all windows, starting from the bottom-most (most-modal) one
 | 
			
		||||
        let windows = this.get_children();
 | 
			
		||||
        for (let i = windows.length - 1; i >= 1; i--) {
 | 
			
		||||
            let realWindow = windows[i].content.window_actor;
 | 
			
		||||
            let realWindow = windows[i].source;
 | 
			
		||||
            let metaWindow = realWindow.meta_window;
 | 
			
		||||
 | 
			
		||||
            metaWindow.delete(global.get_current_time());
 | 
			
		||||
@@ -229,7 +235,7 @@ var WindowClone = GObject.registerClass({
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _doAddAttachedDialog(metaWin, realWin) {
 | 
			
		||||
        let clone = new Clutter.Actor({ content: realWin.content });
 | 
			
		||||
        let clone = new Clutter.Clone({ source: realWin });
 | 
			
		||||
        clone._sizeChangedId = metaWin.connect('size-changed',
 | 
			
		||||
            this._onMetaWindowSizeChanged.bind(this));
 | 
			
		||||
        clone._posChangedId = metaWin.connect('position-changed',
 | 
			
		||||
@@ -282,7 +288,7 @@ var WindowClone = GObject.registerClass({
 | 
			
		||||
            if (child == this._windowClone)
 | 
			
		||||
                realWindow = this.realWindow;
 | 
			
		||||
            else
 | 
			
		||||
                realWindow = child.content.window_actor;
 | 
			
		||||
                realWindow = child.source;
 | 
			
		||||
 | 
			
		||||
            let metaWindow = realWindow.meta_window;
 | 
			
		||||
            rect = rect.union(metaWindow.get_frame_rect());
 | 
			
		||||
@@ -327,7 +333,7 @@ var WindowClone = GObject.registerClass({
 | 
			
		||||
            if (child == this._windowClone)
 | 
			
		||||
                realWindow = this.realWindow;
 | 
			
		||||
            else
 | 
			
		||||
                realWindow = child.content.window_actor;
 | 
			
		||||
                realWindow = child.source;
 | 
			
		||||
 | 
			
		||||
            realWindow.meta_window.disconnect(child._sizeChangedId);
 | 
			
		||||
            realWindow.meta_window.disconnect(child._posChangedId);
 | 
			
		||||
@@ -362,28 +368,8 @@ var WindowClone = GObject.registerClass({
 | 
			
		||||
        this.emit('selected', global.get_current_time());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_enter_event(crossingEvent) {
 | 
			
		||||
        this.emit('show-chrome');
 | 
			
		||||
        return super.vfunc_enter_event(crossingEvent);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_leave_event(crossingEvent) {
 | 
			
		||||
        this.emit('hide-chrome');
 | 
			
		||||
        return super.vfunc_leave_event(crossingEvent);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_key_focus_in() {
 | 
			
		||||
        super.vfunc_key_focus_in();
 | 
			
		||||
        this.emit('show-chrome');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_key_focus_out() {
 | 
			
		||||
        super.vfunc_key_focus_out();
 | 
			
		||||
        this.emit('hide-chrome');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_key_press_event(keyEvent) {
 | 
			
		||||
        let symbol = keyEvent.keyval;
 | 
			
		||||
    _onKeyPress(actor, event) {
 | 
			
		||||
        let symbol = event.get_key_symbol();
 | 
			
		||||
        let isEnter = (symbol == Clutter.KEY_Return || symbol == Clutter.KEY_KP_Enter);
 | 
			
		||||
        if (isEnter) {
 | 
			
		||||
            this._activate();
 | 
			
		||||
@@ -1108,14 +1094,23 @@ function rectEqual(one, two) {
 | 
			
		||||
            one.height == two.height);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const WorkspaceActor = GObject.registerClass(
 | 
			
		||||
class WorkspaceActor extends St.Widget {
 | 
			
		||||
    vfunc_get_focus_chain() {
 | 
			
		||||
        return this.get_children().filter(c => c.visible).sort((a, b) => {
 | 
			
		||||
            if (a instanceof WindowClone && b instanceof WindowClone)
 | 
			
		||||
                return a.slotId - b.slotId;
 | 
			
		||||
 | 
			
		||||
            return 0;
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @metaWorkspace: a #Meta.Workspace, or null
 | 
			
		||||
 */
 | 
			
		||||
var Workspace = GObject.registerClass(
 | 
			
		||||
class Workspace extends St.Widget {
 | 
			
		||||
    _init(metaWorkspace, monitorIndex) {
 | 
			
		||||
        super._init({ style_class: 'window-picker' });
 | 
			
		||||
 | 
			
		||||
var Workspace = class {
 | 
			
		||||
    constructor(metaWorkspace, monitorIndex) {
 | 
			
		||||
        // When dragging a window, we use this slot for reserve space.
 | 
			
		||||
        this._reservedSlot = null;
 | 
			
		||||
        this._reservedSlotWindow = null;
 | 
			
		||||
@@ -1141,17 +1136,18 @@ class Workspace extends St.Widget {
 | 
			
		||||
        // Without this the drop area will be overlapped.
 | 
			
		||||
        this._windowOverlaysGroup.set_size(0, 0);
 | 
			
		||||
 | 
			
		||||
        this.actor = new WorkspaceActor({ style_class: 'window-picker' });
 | 
			
		||||
        if (monitorIndex != Main.layoutManager.primaryIndex)
 | 
			
		||||
            this.add_style_class_name('external-monitor');
 | 
			
		||||
        this.set_size(0, 0);
 | 
			
		||||
            this.actor.add_style_class_name('external-monitor');
 | 
			
		||||
        this.actor.set_size(0, 0);
 | 
			
		||||
 | 
			
		||||
        this._dropRect = new Clutter.Actor({ opacity: 0 });
 | 
			
		||||
        this._dropRect._delegate = this;
 | 
			
		||||
 | 
			
		||||
        this.add_actor(this._dropRect);
 | 
			
		||||
        this.add_actor(this._windowOverlaysGroup);
 | 
			
		||||
        this.actor.add_actor(this._dropRect);
 | 
			
		||||
        this.actor.add_actor(this._windowOverlaysGroup);
 | 
			
		||||
 | 
			
		||||
        this.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
        this.actor.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
 | 
			
		||||
        let windows = global.get_window_actors().filter(this._isMyWindow, this);
 | 
			
		||||
 | 
			
		||||
@@ -1181,19 +1177,10 @@ class Workspace extends St.Widget {
 | 
			
		||||
 | 
			
		||||
        this._positionWindowsFlags = 0;
 | 
			
		||||
        this._positionWindowsId = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_map() {
 | 
			
		||||
        super.vfunc_map();
 | 
			
		||||
        this._syncActualGeometry();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_get_focus_chain() {
 | 
			
		||||
        return this.get_children().filter(c => c.visible).sort((a, b) => {
 | 
			
		||||
            if (a instanceof WindowClone && b instanceof WindowClone)
 | 
			
		||||
                return a.slotId - b.slotId;
 | 
			
		||||
 | 
			
		||||
            return 0;
 | 
			
		||||
        this.actor.connect('notify::mapped', () => {
 | 
			
		||||
            if (this.actor.mapped)
 | 
			
		||||
                this._syncActualGeometry();
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -1203,7 +1190,7 @@ class Workspace extends St.Widget {
 | 
			
		||||
 | 
			
		||||
        this._fullGeometry = geom;
 | 
			
		||||
 | 
			
		||||
        if (this.mapped)
 | 
			
		||||
        if (this.actor.mapped)
 | 
			
		||||
            this._recalculateWindowPositions(WindowPositionFlags.NONE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -1214,7 +1201,7 @@ class Workspace extends St.Widget {
 | 
			
		||||
        this._actualGeometry = geom;
 | 
			
		||||
        this._actualGeometryDirty = true;
 | 
			
		||||
 | 
			
		||||
        if (this.mapped)
 | 
			
		||||
        if (this.actor.mapped)
 | 
			
		||||
            this._syncActualGeometry();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -1226,7 +1213,7 @@ class Workspace extends St.Widget {
 | 
			
		||||
 | 
			
		||||
        this._actualGeometryLater = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
 | 
			
		||||
            this._actualGeometryLater = 0;
 | 
			
		||||
            if (!this.mapped)
 | 
			
		||||
            if (!this.actor.mapped)
 | 
			
		||||
                return false;
 | 
			
		||||
 | 
			
		||||
            let geom = this._actualGeometry;
 | 
			
		||||
@@ -1517,7 +1504,8 @@ class Workspace extends St.Widget {
 | 
			
		||||
            // Newly-created windows are added to a workspace before
 | 
			
		||||
            // the compositor finds out about them...
 | 
			
		||||
            let id = GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {
 | 
			
		||||
                if (metaWin.get_compositor_private() &&
 | 
			
		||||
                if (this.actor &&
 | 
			
		||||
                    metaWin.get_compositor_private() &&
 | 
			
		||||
                    metaWin.get_workspace() == this.metaWorkspace)
 | 
			
		||||
                    this._doAddWindow(metaWin);
 | 
			
		||||
                return GLib.SOURCE_REMOVE;
 | 
			
		||||
@@ -1553,8 +1541,8 @@ class Workspace extends St.Widget {
 | 
			
		||||
        let [clone, overlay_] = this._addWindowClone(win, false);
 | 
			
		||||
 | 
			
		||||
        if (win._overviewHint) {
 | 
			
		||||
            let x = win._overviewHint.x - this.x;
 | 
			
		||||
            let y = win._overviewHint.y - this.y;
 | 
			
		||||
            let x = win._overviewHint.x - this.actor.x;
 | 
			
		||||
            let y = win._overviewHint.y - this.actor.y;
 | 
			
		||||
            let scale = win._overviewHint.scale;
 | 
			
		||||
            delete win._overviewHint;
 | 
			
		||||
 | 
			
		||||
@@ -1789,6 +1777,10 @@ class Workspace extends St.Widget {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    destroy() {
 | 
			
		||||
        this.actor.destroy();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onDestroy() {
 | 
			
		||||
        if (this._overviewHiddenId) {
 | 
			
		||||
            Main.overview.disconnect(this._overviewHiddenId);
 | 
			
		||||
@@ -1869,11 +1861,11 @@ class Workspace extends St.Widget {
 | 
			
		||||
            this._removeWindowClone(clone.metaWindow);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this.add_actor(clone);
 | 
			
		||||
        this.actor.add_actor(clone);
 | 
			
		||||
 | 
			
		||||
        overlay.connect('chrome-visible', () => {
 | 
			
		||||
            let focus = global.stage.key_focus;
 | 
			
		||||
            if (focus == null || this.contains(focus))
 | 
			
		||||
            if (focus == null || this.actor.contains(focus))
 | 
			
		||||
                clone.grab_key_focus();
 | 
			
		||||
 | 
			
		||||
            this._windowOverlays.forEach(o => {
 | 
			
		||||
@@ -1957,7 +1949,7 @@ class Workspace extends St.Widget {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _getSpacingAndPadding() {
 | 
			
		||||
        let node = this.get_theme_node();
 | 
			
		||||
        let node = this.actor.get_theme_node();
 | 
			
		||||
 | 
			
		||||
        // Window grid spacing
 | 
			
		||||
        let columnSpacing = node.get_length('-horizontal-spacing');
 | 
			
		||||
@@ -2055,4 +2047,5 @@ class Workspace extends St.Widget {
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(Workspace.prototype);
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,7 @@
 | 
			
		||||
/* exported WorkspaceThumbnail, ThumbnailsBox */
 | 
			
		||||
 | 
			
		||||
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
 | 
			
		||||
const Background = imports.ui.background;
 | 
			
		||||
const DND = imports.ui.dnd;
 | 
			
		||||
@@ -43,41 +44,36 @@ class PrimaryActorLayout extends Clutter.FixedLayout {
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
var WindowClone = GObject.registerClass({
 | 
			
		||||
    GTypeName: 'WorkspaceThumbnail_WindowClone',
 | 
			
		||||
    Signals: {
 | 
			
		||||
        'drag-begin': {},
 | 
			
		||||
        'drag-cancelled': {},
 | 
			
		||||
        'drag-end': {},
 | 
			
		||||
        'selected': { param_types: [GObject.TYPE_UINT] },
 | 
			
		||||
    }
 | 
			
		||||
}, class WindowClone extends Clutter.Actor {
 | 
			
		||||
    _init(realWindow) {
 | 
			
		||||
        let clone = new Clutter.Actor({ content: realWindow.content,
 | 
			
		||||
                                        request_mode: Clutter.RequestMode.CONTENT_SIZE });
 | 
			
		||||
        super._init({
 | 
			
		||||
            layout_manager: new PrimaryActorLayout(clone),
 | 
			
		||||
            reactive: true
 | 
			
		||||
        });
 | 
			
		||||
        this._delegate = this;
 | 
			
		||||
var WindowClone = class {
 | 
			
		||||
    constructor(realWindow) {
 | 
			
		||||
        this.clone = new Clutter.Clone({ source: realWindow });
 | 
			
		||||
 | 
			
		||||
        this.add_child(clone);
 | 
			
		||||
        /* Can't use a Shell.GenericContainer because of DND and reparenting... */
 | 
			
		||||
        this.actor = new Clutter.Actor({ layout_manager: new PrimaryActorLayout(this.clone),
 | 
			
		||||
                                         reactive: true });
 | 
			
		||||
        this.actor._delegate = this;
 | 
			
		||||
        this.actor.add_child(this.clone);
 | 
			
		||||
        this.realWindow = realWindow;
 | 
			
		||||
        this.metaWindow = realWindow.meta_window;
 | 
			
		||||
 | 
			
		||||
        clone._updateId = this.realWindow.connect('notify::position',
 | 
			
		||||
                                                  this._onPositionChanged.bind(this));
 | 
			
		||||
        clone._destroyId = this.realWindow.connect('destroy', () => {
 | 
			
		||||
        this.clone._updateId = this.realWindow.connect('notify::position',
 | 
			
		||||
                                                       this._onPositionChanged.bind(this));
 | 
			
		||||
        this.clone._destroyId = this.realWindow.connect('destroy', () => {
 | 
			
		||||
            // First destroy the clone and then destroy everything
 | 
			
		||||
            // This will ensure that we never see it in the _disconnectSignals loop
 | 
			
		||||
            clone.destroy();
 | 
			
		||||
            this.clone.destroy();
 | 
			
		||||
            this.destroy();
 | 
			
		||||
        });
 | 
			
		||||
        this._onPositionChanged();
 | 
			
		||||
 | 
			
		||||
        this.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
        this.actor.connect('button-release-event',
 | 
			
		||||
                           this._onButtonRelease.bind(this));
 | 
			
		||||
        this.actor.connect('touch-event',
 | 
			
		||||
                           this._onTouchEvent.bind(this));
 | 
			
		||||
 | 
			
		||||
        this._draggable = DND.makeDraggable(this,
 | 
			
		||||
        this.actor.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
 | 
			
		||||
        this._draggable = DND.makeDraggable(this.actor,
 | 
			
		||||
                                            { restoreOnSuccess: true,
 | 
			
		||||
                                              dragActorMaxSize: Workspace.WINDOW_DND_SIZE,
 | 
			
		||||
                                              dragActorOpacity: Workspace.DRAGGING_WINDOW_OPACITY });
 | 
			
		||||
@@ -128,9 +124,13 @@ var WindowClone = GObject.registerClass({
 | 
			
		||||
 | 
			
		||||
        let actualAbove = this.getActualStackAbove();
 | 
			
		||||
        if (actualAbove == null)
 | 
			
		||||
            this.lower_bottom();
 | 
			
		||||
            this.actor.lower_bottom();
 | 
			
		||||
        else
 | 
			
		||||
            this.raise(actualAbove);
 | 
			
		||||
            this.actor.raise(actualAbove);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    destroy() {
 | 
			
		||||
        this.actor.destroy();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    addAttachedDialog(win) {
 | 
			
		||||
@@ -138,8 +138,7 @@ var WindowClone = GObject.registerClass({
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _doAddAttachedDialog(metaDialog, realDialog) {
 | 
			
		||||
        let clone = new Clutter.Actor({ content: realDialog.content,
 | 
			
		||||
                                        request_mode: Clutter.RequestMode.CONTENT_SIZE });
 | 
			
		||||
        let clone = new Clutter.Clone({ source: realDialog });
 | 
			
		||||
        this._updateDialogPosition(realDialog, clone);
 | 
			
		||||
 | 
			
		||||
        clone._updateId = realDialog.connect('notify::position', dialog => {
 | 
			
		||||
@@ -148,7 +147,7 @@ var WindowClone = GObject.registerClass({
 | 
			
		||||
        clone._destroyId = realDialog.connect('destroy', () => {
 | 
			
		||||
            clone.destroy();
 | 
			
		||||
        });
 | 
			
		||||
        this.add_child(clone);
 | 
			
		||||
        this.actor.add_child(clone);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _updateDialogPosition(realDialog, cloneDialog) {
 | 
			
		||||
@@ -160,12 +159,12 @@ var WindowClone = GObject.registerClass({
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onPositionChanged() {
 | 
			
		||||
        this.set_position(this.realWindow.x, this.realWindow.y);
 | 
			
		||||
        this.actor.set_position(this.realWindow.x, this.realWindow.y);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _disconnectSignals() {
 | 
			
		||||
        this.get_children().forEach(child => {
 | 
			
		||||
            let realWindow = child.content.window_actor;
 | 
			
		||||
        this.actor.get_children().forEach(child => {
 | 
			
		||||
            let realWindow = child.source;
 | 
			
		||||
 | 
			
		||||
            realWindow.disconnect(child._updateId);
 | 
			
		||||
            realWindow.disconnect(child._destroyId);
 | 
			
		||||
@@ -175,30 +174,28 @@ var WindowClone = GObject.registerClass({
 | 
			
		||||
    _onDestroy() {
 | 
			
		||||
        this._disconnectSignals();
 | 
			
		||||
 | 
			
		||||
        this._delegate = null;
 | 
			
		||||
        this.actor._delegate = null;
 | 
			
		||||
 | 
			
		||||
        if (this.inDrag) {
 | 
			
		||||
            this.emit('drag-end');
 | 
			
		||||
            this.inDrag = false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.disconnectAll();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_button_press_event() {
 | 
			
		||||
        return Clutter.EVENT_STOP;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_button_release_event(buttonEvent) {
 | 
			
		||||
        this.emit('selected', buttonEvent.time);
 | 
			
		||||
    _onButtonRelease(actor, event) {
 | 
			
		||||
        this.emit('selected', event.get_time());
 | 
			
		||||
 | 
			
		||||
        return Clutter.EVENT_STOP;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_touch_event(touchEvent) {
 | 
			
		||||
        if (touchEvent.type != Clutter.EventType.TOUCH_END ||
 | 
			
		||||
            !global.display.is_pointer_emulating_sequence(touchEvent.sequence))
 | 
			
		||||
    _onTouchEvent(actor, event) {
 | 
			
		||||
        if (event.type() != Clutter.EventType.TOUCH_END ||
 | 
			
		||||
            !global.display.is_pointer_emulating_sequence(event.get_event_sequence()))
 | 
			
		||||
            return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
 | 
			
		||||
        this.emit('selected', touchEvent.time);
 | 
			
		||||
        this.emit('selected', event.get_time());
 | 
			
		||||
        return Clutter.EVENT_STOP;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -217,17 +214,18 @@ var WindowClone = GObject.registerClass({
 | 
			
		||||
        // 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.get_parent() != null) {
 | 
			
		||||
        if (this.actor.get_parent() != null) {
 | 
			
		||||
            if (this._stackAbove == null)
 | 
			
		||||
                this.lower_bottom();
 | 
			
		||||
                this.actor.lower_bottom();
 | 
			
		||||
            else
 | 
			
		||||
                this.raise(this._stackAbove);
 | 
			
		||||
                this.actor.raise(this._stackAbove);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        this.emit('drag-end');
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(WindowClone.prototype);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
var ThumbnailState = {
 | 
			
		||||
@@ -342,7 +340,7 @@ var WorkspaceThumbnail = GObject.registerClass({
 | 
			
		||||
                clone.setStackAbove(this._bgManager.backgroundActor);
 | 
			
		||||
            } else {
 | 
			
		||||
                let previousClone = this._windows[i - 1];
 | 
			
		||||
                clone.setStackAbove(previousClone);
 | 
			
		||||
                clone.setStackAbove(previousClone.actor);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@@ -524,15 +522,15 @@ var WorkspaceThumbnail = GObject.registerClass({
 | 
			
		||||
        clone.connect('drag-end', () => {
 | 
			
		||||
            Main.overview.endWindowDrag(clone.metaWindow);
 | 
			
		||||
        });
 | 
			
		||||
        clone.connect('destroy', () => {
 | 
			
		||||
        clone.actor.connect('destroy', () => {
 | 
			
		||||
            this._removeWindowClone(clone.metaWindow);
 | 
			
		||||
        });
 | 
			
		||||
        this._contents.add_actor(clone);
 | 
			
		||||
        this._contents.add_actor(clone.actor);
 | 
			
		||||
 | 
			
		||||
        if (this._windows.length == 0)
 | 
			
		||||
            clone.setStackAbove(this._bgManager.backgroundActor);
 | 
			
		||||
        else
 | 
			
		||||
            clone.setStackAbove(this._windows[this._windows.length - 1]);
 | 
			
		||||
            clone.setStackAbove(this._windows[this._windows.length - 1].actor);
 | 
			
		||||
 | 
			
		||||
        this._windows.push(clone);
 | 
			
		||||
 | 
			
		||||
@@ -670,6 +668,10 @@ var ThumbnailsBox = GObject.registerClass({
 | 
			
		||||
 | 
			
		||||
        this._thumbnails = [];
 | 
			
		||||
 | 
			
		||||
        this.connect('button-press-event', () => Clutter.EVENT_STOP);
 | 
			
		||||
        this.connect('button-release-event', this._onButtonRelease.bind(this));
 | 
			
		||||
        this.connect('touch-event', this._onTouchEvent.bind(this));
 | 
			
		||||
 | 
			
		||||
        Main.overview.connect('showing',
 | 
			
		||||
                              this._createThumbnails.bind(this));
 | 
			
		||||
        Main.overview.connect('hidden',
 | 
			
		||||
@@ -726,17 +728,17 @@ var ThumbnailsBox = GObject.registerClass({
 | 
			
		||||
            thumbnail.activate(time);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_button_release_event(buttonEvent) {
 | 
			
		||||
        let { x, y } = buttonEvent;
 | 
			
		||||
        this._activateThumbnailAtPoint(x, y, buttonEvent.time);
 | 
			
		||||
    _onButtonRelease(actor, event) {
 | 
			
		||||
        let [stageX, stageY] = event.get_coords();
 | 
			
		||||
        this._activateThumbnailAtPoint(stageX, stageY, event.get_time());
 | 
			
		||||
        return Clutter.EVENT_STOP;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_touch_event(touchEvent) {
 | 
			
		||||
        if (touchEvent.type == Clutter.EventType.TOUCH_END &&
 | 
			
		||||
            global.display.is_pointer_emulating_sequence(touchEvent.sequence)) {
 | 
			
		||||
            let { x, y } = touchEvent;
 | 
			
		||||
            this._activateThumbnailAtPoint(x, y, touchEvent.time);
 | 
			
		||||
    _onTouchEvent(actor, event) {
 | 
			
		||||
        if (event.type() == Clutter.EventType.TOUCH_END &&
 | 
			
		||||
            global.display.is_pointer_emulating_sequence(event.get_event_sequence())) {
 | 
			
		||||
            let [stageX, stageY] = event.get_coords();
 | 
			
		||||
            this._activateThumbnailAtPoint(stageX, stageY, event.get_time());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return Clutter.EVENT_STOP;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,8 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/* exported WorkspacesView, WorkspacesDisplay */
 | 
			
		||||
/* exported WorkspacesView */
 | 
			
		||||
 | 
			
		||||
const { Clutter, Gio, GObject, Meta, Shell, St } = imports.gi;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const WindowManager = imports.ui.windowManager;
 | 
			
		||||
@@ -16,16 +17,15 @@ var AnimationType = {
 | 
			
		||||
 | 
			
		||||
const MUTTER_SCHEMA = 'org.gnome.mutter';
 | 
			
		||||
 | 
			
		||||
var WorkspacesViewBase = GObject.registerClass({
 | 
			
		||||
    GTypeFlags: GObject.TypeFlags.ABSTRACT
 | 
			
		||||
}, class WorkspacesViewBase extends St.Widget {
 | 
			
		||||
    _init(monitorIndex) {
 | 
			
		||||
        super._init({ style_class: 'workspaces-view', reactive: true });
 | 
			
		||||
        this.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
        global.focus_manager.add_group(this);
 | 
			
		||||
var WorkspacesViewBase = class {
 | 
			
		||||
    constructor(monitorIndex) {
 | 
			
		||||
        this.actor = new St.Widget({ style_class: 'workspaces-view',
 | 
			
		||||
                                     reactive: true });
 | 
			
		||||
        this.actor.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
        global.focus_manager.add_group(this.actor);
 | 
			
		||||
 | 
			
		||||
        // The actor itself isn't a drop target, so we don't want to pick on its area
 | 
			
		||||
        this.set_size(0, 0);
 | 
			
		||||
        this.actor.set_size(0, 0);
 | 
			
		||||
 | 
			
		||||
        this._monitorIndex = monitorIndex;
 | 
			
		||||
 | 
			
		||||
@@ -60,6 +60,10 @@ var WorkspacesViewBase = GObject.registerClass({
 | 
			
		||||
        this._setReservedSlot(null);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    destroy() {
 | 
			
		||||
        this.actor.destroy();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    setFullGeometry(geom) {
 | 
			
		||||
        this._fullGeometry = geom;
 | 
			
		||||
        this._syncFullGeometry();
 | 
			
		||||
@@ -69,14 +73,13 @@ var WorkspacesViewBase = GObject.registerClass({
 | 
			
		||||
        this._actualGeometry = geom;
 | 
			
		||||
        this._syncActualGeometry();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var WorkspacesView = GObject.registerClass(
 | 
			
		||||
class WorkspacesView extends WorkspacesViewBase {
 | 
			
		||||
    _init(monitorIndex) {
 | 
			
		||||
var WorkspacesView = class extends WorkspacesViewBase {
 | 
			
		||||
    constructor(monitorIndex) {
 | 
			
		||||
        let workspaceManager = global.workspace_manager;
 | 
			
		||||
 | 
			
		||||
        super._init(monitorIndex);
 | 
			
		||||
        super(monitorIndex);
 | 
			
		||||
 | 
			
		||||
        this._animating = false; // tweening
 | 
			
		||||
        this._scrolling = false; // swipe-scrolling
 | 
			
		||||
@@ -109,8 +112,8 @@ class WorkspacesView extends WorkspacesViewBase {
 | 
			
		||||
 | 
			
		||||
        this._overviewShownId =
 | 
			
		||||
            Main.overview.connect('shown', () => {
 | 
			
		||||
                this.set_clip(this._fullGeometry.x, this._fullGeometry.y,
 | 
			
		||||
                              this._fullGeometry.width, this._fullGeometry.height);
 | 
			
		||||
                this.actor.set_clip(this._fullGeometry.x, this._fullGeometry.y,
 | 
			
		||||
                                    this._fullGeometry.width, this._fullGeometry.height);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
        this._switchWorkspaceNotifyId =
 | 
			
		||||
@@ -150,7 +153,7 @@ class WorkspacesView extends WorkspacesViewBase {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    animateFromOverview(animationType) {
 | 
			
		||||
        this.remove_clip();
 | 
			
		||||
        this.actor.remove_clip();
 | 
			
		||||
 | 
			
		||||
        for (let w = 0; w < this._workspaces.length; w++) {
 | 
			
		||||
            if (animationType == AnimationType.ZOOM)
 | 
			
		||||
@@ -184,12 +187,12 @@ class WorkspacesView extends WorkspacesViewBase {
 | 
			
		||||
        for (let w = 0; w < this._workspaces.length; w++) {
 | 
			
		||||
            let workspace = this._workspaces[w];
 | 
			
		||||
 | 
			
		||||
            workspace.remove_all_transitions();
 | 
			
		||||
            workspace.actor.remove_all_transitions();
 | 
			
		||||
 | 
			
		||||
            let params = {};
 | 
			
		||||
            if (workspaceManager.layout_rows == -1)
 | 
			
		||||
                params.y = (w - active) * this._fullGeometry.height;
 | 
			
		||||
            else if (this.text_direction == Clutter.TextDirection.RTL)
 | 
			
		||||
            else if (this.actor.text_direction == Clutter.TextDirection.RTL)
 | 
			
		||||
                params.x = (active - w) * this._fullGeometry.width;
 | 
			
		||||
            else
 | 
			
		||||
                params.x = (w - active) * this._fullGeometry.width;
 | 
			
		||||
@@ -209,9 +212,9 @@ class WorkspacesView extends WorkspacesViewBase {
 | 
			
		||||
                        this._updateVisibility();
 | 
			
		||||
                    };
 | 
			
		||||
                }
 | 
			
		||||
                workspace.ease(easeParams);
 | 
			
		||||
                workspace.actor.ease(easeParams);
 | 
			
		||||
            } else {
 | 
			
		||||
                workspace.set(params);
 | 
			
		||||
                workspace.actor.set(params);
 | 
			
		||||
                if (w == 0)
 | 
			
		||||
                    this._updateVisibility();
 | 
			
		||||
            }
 | 
			
		||||
@@ -225,12 +228,12 @@ class WorkspacesView extends WorkspacesViewBase {
 | 
			
		||||
        for (let w = 0; w < this._workspaces.length; w++) {
 | 
			
		||||
            let workspace = this._workspaces[w];
 | 
			
		||||
            if (this._animating || this._scrolling || this._gestureActive) {
 | 
			
		||||
                workspace.show();
 | 
			
		||||
                workspace.actor.show();
 | 
			
		||||
            } else {
 | 
			
		||||
                if (this._inDrag)
 | 
			
		||||
                    workspace.visible = (Math.abs(w - active) <= 1);
 | 
			
		||||
                    workspace.actor.visible = (Math.abs(w - active) <= 1);
 | 
			
		||||
                else
 | 
			
		||||
                    workspace.visible = (w == active);
 | 
			
		||||
                    workspace.actor.visible = (w == active);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@@ -260,7 +263,7 @@ class WorkspacesView extends WorkspacesViewBase {
 | 
			
		||||
 | 
			
		||||
            if (j >= this._workspaces.length) { /* added */
 | 
			
		||||
                workspace = new Workspace.Workspace(metaWorkspace, this._monitorIndex);
 | 
			
		||||
                this.add_actor(workspace);
 | 
			
		||||
                this.actor.add_actor(workspace.actor);
 | 
			
		||||
                this._workspaces[j] = workspace;
 | 
			
		||||
            } else  {
 | 
			
		||||
                workspace = this._workspaces[j];
 | 
			
		||||
@@ -352,8 +355,8 @@ class WorkspacesView extends WorkspacesViewBase {
 | 
			
		||||
        let last = this._workspaces.length - 1;
 | 
			
		||||
 | 
			
		||||
        if (workspaceManager.layout_rows == -1) {
 | 
			
		||||
            let firstWorkspaceY = this._workspaces[0].y;
 | 
			
		||||
            let lastWorkspaceY = this._workspaces[last].y;
 | 
			
		||||
            let firstWorkspaceY = this._workspaces[0].actor.y;
 | 
			
		||||
            let lastWorkspaceY = this._workspaces[last].actor.y;
 | 
			
		||||
            let workspacesHeight = lastWorkspaceY - firstWorkspaceY;
 | 
			
		||||
 | 
			
		||||
            let currentY = firstWorkspaceY;
 | 
			
		||||
@@ -362,12 +365,12 @@ class WorkspacesView extends WorkspacesViewBase {
 | 
			
		||||
            let dy = newY - currentY;
 | 
			
		||||
 | 
			
		||||
            for (let i = 0; i < this._workspaces.length; i++) {
 | 
			
		||||
                this._workspaces[i].visible = Math.abs(i - adj.value) <= 1;
 | 
			
		||||
                this._workspaces[i].y += dy;
 | 
			
		||||
                this._workspaces[i].actor.visible = Math.abs(i - adj.value) <= 1;
 | 
			
		||||
                this._workspaces[i].actor.y += dy;
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            let firstWorkspaceX = this._workspaces[0].x;
 | 
			
		||||
            let lastWorkspaceX = this._workspaces[last].x;
 | 
			
		||||
            let firstWorkspaceX = this._workspaces[0].actor.x;
 | 
			
		||||
            let lastWorkspaceX = this._workspaces[last].actor.x;
 | 
			
		||||
            let workspacesWidth = lastWorkspaceX - firstWorkspaceX;
 | 
			
		||||
 | 
			
		||||
            let currentX = firstWorkspaceX;
 | 
			
		||||
@@ -376,19 +379,19 @@ class WorkspacesView extends WorkspacesViewBase {
 | 
			
		||||
            let dx = newX - currentX;
 | 
			
		||||
 | 
			
		||||
            for (let i = 0; i < this._workspaces.length; i++) {
 | 
			
		||||
                this._workspaces[i].visible = Math.abs(i - adj.value) <= 1;
 | 
			
		||||
                this._workspaces[i].x += dx;
 | 
			
		||||
                this._workspaces[i].actor.visible = Math.abs(i - adj.value) <= 1;
 | 
			
		||||
                this._workspaces[i].actor.x += dx;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(WorkspacesView.prototype);
 | 
			
		||||
 | 
			
		||||
var ExtraWorkspaceView = GObject.registerClass(
 | 
			
		||||
class ExtraWorkspaceView extends WorkspacesViewBase {
 | 
			
		||||
    _init(monitorIndex) {
 | 
			
		||||
        super._init(monitorIndex);
 | 
			
		||||
var ExtraWorkspaceView = class extends WorkspacesViewBase {
 | 
			
		||||
    constructor(monitorIndex) {
 | 
			
		||||
        super(monitorIndex);
 | 
			
		||||
        this._workspace = new Workspace.Workspace(null, monitorIndex);
 | 
			
		||||
        this.add_actor(this._workspace);
 | 
			
		||||
        this.actor.add_actor(this._workspace.actor);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _setReservedSlot(window) {
 | 
			
		||||
@@ -436,13 +439,21 @@ class ExtraWorkspaceView extends WorkspacesViewBase {
 | 
			
		||||
 | 
			
		||||
    endTouchGesture() {
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var DelegateFocusNavigator = GObject.registerClass(
 | 
			
		||||
class DelegateFocusNavigator extends St.Widget {
 | 
			
		||||
    vfunc_navigate_focus(from, direction) {
 | 
			
		||||
        return this._delegate.navigateFocus(from, direction);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
var WorkspacesDisplay = GObject.registerClass(
 | 
			
		||||
class WorkspacesDisplay extends St.Widget {
 | 
			
		||||
    _init() {
 | 
			
		||||
        super._init({ clip_to_allocation: true });
 | 
			
		||||
        this.connect('notify::allocation', this._updateWorkspacesActualGeometry.bind(this));
 | 
			
		||||
var WorkspacesDisplay = class {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        this.actor = new DelegateFocusNavigator({ clip_to_allocation: true });
 | 
			
		||||
        this.actor._delegate = this;
 | 
			
		||||
        this.actor.connect('notify::allocation', this._updateWorkspacesActualGeometry.bind(this));
 | 
			
		||||
        this.actor.connect('parent-set', this._parentSet.bind(this));
 | 
			
		||||
 | 
			
		||||
        let clickAction = new Clutter.ClickAction();
 | 
			
		||||
        clickAction.connect('clicked', action => {
 | 
			
		||||
@@ -456,7 +467,7 @@ class WorkspacesDisplay extends St.Widget {
 | 
			
		||||
                Main.overview.hide();
 | 
			
		||||
        });
 | 
			
		||||
        Main.overview.addAction(clickAction);
 | 
			
		||||
        this.bind_property('mapped', clickAction, 'enabled', GObject.BindingFlags.SYNC_CREATE);
 | 
			
		||||
        this.actor.bind_property('mapped', clickAction, 'enabled', GObject.BindingFlags.SYNC_CREATE);
 | 
			
		||||
 | 
			
		||||
        let panAction = new Clutter.PanAction({ threshold_trigger_edge: Clutter.GestureTriggerEdge.AFTER });
 | 
			
		||||
        panAction.connect('pan', this._onPan.bind(this));
 | 
			
		||||
@@ -479,7 +490,7 @@ class WorkspacesDisplay extends St.Widget {
 | 
			
		||||
            this._endSwipeScroll();
 | 
			
		||||
        });
 | 
			
		||||
        Main.overview.addAction(panAction);
 | 
			
		||||
        this.bind_property('mapped', panAction, 'enabled', GObject.BindingFlags.SYNC_CREATE);
 | 
			
		||||
        this.actor.bind_property('mapped', panAction, 'enabled', GObject.BindingFlags.SYNC_CREATE);
 | 
			
		||||
 | 
			
		||||
        let allowedModes = Shell.ActionMode.OVERVIEW;
 | 
			
		||||
        let switchGesture = new WindowManager.WorkspaceSwitchAction(allowedModes);
 | 
			
		||||
@@ -487,15 +498,20 @@ class WorkspacesDisplay extends St.Widget {
 | 
			
		||||
        switchGesture.connect('activated', this._onSwitchWorkspaceActivated.bind(this));
 | 
			
		||||
        switchGesture.connect('cancel', this._endTouchGesture.bind(this));
 | 
			
		||||
        Main.overview.addAction(switchGesture);
 | 
			
		||||
        this.bind_property('mapped', switchGesture, 'enabled', GObject.BindingFlags.SYNC_CREATE);
 | 
			
		||||
        this.actor.bind_property('mapped', switchGesture, 'enabled', GObject.BindingFlags.SYNC_CREATE);
 | 
			
		||||
 | 
			
		||||
        switchGesture = new WindowManager.TouchpadWorkspaceSwitchAction(global.stage, allowedModes);
 | 
			
		||||
        switchGesture.connect('motion', this._onSwitchWorkspaceMotion.bind(this));
 | 
			
		||||
        switchGesture.connect('activated', this._onSwitchWorkspaceActivated.bind(this));
 | 
			
		||||
        switchGesture.connect('cancel', this._endTouchGesture.bind(this));
 | 
			
		||||
        this.actor.connect('notify::mapped', () => {
 | 
			
		||||
            switchGesture.enabled = this.actor.mapped;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this._primaryIndex = Main.layoutManager.primaryIndex;
 | 
			
		||||
 | 
			
		||||
        this._workspacesViews = [];
 | 
			
		||||
        switchGesture.enabled = this.actor.mapped;
 | 
			
		||||
 | 
			
		||||
        this._settings = new Gio.Settings({ schema_id: MUTTER_SCHEMA });
 | 
			
		||||
        this._settings.connect('changed::workspaces-only-on-primary',
 | 
			
		||||
@@ -509,12 +525,12 @@ class WorkspacesDisplay extends St.Widget {
 | 
			
		||||
 | 
			
		||||
        this._fullGeometry = null;
 | 
			
		||||
 | 
			
		||||
        this.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
        this.actor.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onDestroy() {
 | 
			
		||||
        if (this._notifyOpacityId) {
 | 
			
		||||
            let parent = this.get_parent();
 | 
			
		||||
            let parent = this.actor.get_parent();
 | 
			
		||||
            if (parent)
 | 
			
		||||
                parent.disconnect(this._notifyOpacityId);
 | 
			
		||||
            this._notifyOpacityId = 0;
 | 
			
		||||
@@ -530,11 +546,11 @@ class WorkspacesDisplay extends St.Widget {
 | 
			
		||||
        let [dist_, dx, dy] = action.get_motion_delta(0);
 | 
			
		||||
        let adjustment = this._scrollAdjustment;
 | 
			
		||||
        if (global.workspace_manager.layout_rows == -1)
 | 
			
		||||
            adjustment.value -= (dy / this.height) * adjustment.page_size;
 | 
			
		||||
        else if (this.text_direction == Clutter.TextDirection.RTL)
 | 
			
		||||
            adjustment.value += (dx / this.width) * adjustment.page_size;
 | 
			
		||||
            adjustment.value -= (dy / this.actor.height) * adjustment.page_size;
 | 
			
		||||
        else if (this.actor.text_direction == Clutter.TextDirection.RTL)
 | 
			
		||||
            adjustment.value += (dx / this.actor.width) * adjustment.page_size;
 | 
			
		||||
        else
 | 
			
		||||
            adjustment.value -= (dx / this.width) * adjustment.page_size;
 | 
			
		||||
            adjustment.value -= (dx / this.actor.width) * adjustment.page_size;
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -567,11 +583,11 @@ class WorkspacesDisplay extends St.Widget {
 | 
			
		||||
        let active = workspaceManager.get_active_workspace_index();
 | 
			
		||||
        let adjustment = this._scrollAdjustment;
 | 
			
		||||
        if (workspaceManager.layout_rows == -1)
 | 
			
		||||
            adjustment.value = (active - yRel / this.height) * adjustment.page_size;
 | 
			
		||||
        else if (this.text_direction == Clutter.TextDirection.RTL)
 | 
			
		||||
            adjustment.value = (active + xRel / this.width) * adjustment.page_size;
 | 
			
		||||
            adjustment.value = (active - yRel / this.actor.height) * adjustment.page_size;
 | 
			
		||||
        else if (this.actor.text_direction == Clutter.TextDirection.RTL)
 | 
			
		||||
            adjustment.value = (active + xRel / this.actor.width) * adjustment.page_size;
 | 
			
		||||
        else
 | 
			
		||||
            adjustment.value = (active - xRel / this.width) * adjustment.page_size;
 | 
			
		||||
            adjustment.value = (active - xRel / this.actor.width) * adjustment.page_size;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onSwitchWorkspaceActivated(action, direction) {
 | 
			
		||||
@@ -584,8 +600,8 @@ class WorkspacesDisplay extends St.Widget {
 | 
			
		||||
        this._endTouchGesture();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_navigate_focus(from, direction) {
 | 
			
		||||
        return this._getPrimaryView().navigate_focus(from, direction, false);
 | 
			
		||||
    navigateFocus(from, direction) {
 | 
			
		||||
        return this._getPrimaryView().actor.navigate_focus(from, direction, false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    show(fadeOnPrimary) {
 | 
			
		||||
@@ -661,7 +677,7 @@ class WorkspacesDisplay extends St.Widget {
 | 
			
		||||
            else
 | 
			
		||||
                view = new WorkspacesView(i);
 | 
			
		||||
 | 
			
		||||
            view.connect('scroll-event', this._onScrollEvent.bind(this));
 | 
			
		||||
            view.actor.connect('scroll-event', this._onScrollEvent.bind(this));
 | 
			
		||||
            if (i == this._primaryIndex) {
 | 
			
		||||
                this._scrollAdjustment = view.scrollAdjustment;
 | 
			
		||||
                this._scrollAdjustment.connect('notify::value',
 | 
			
		||||
@@ -669,13 +685,13 @@ class WorkspacesDisplay extends St.Widget {
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // HACK: Avoid spurious allocation changes while updating views
 | 
			
		||||
            view.hide();
 | 
			
		||||
            view.actor.hide();
 | 
			
		||||
 | 
			
		||||
            this._workspacesViews.push(view);
 | 
			
		||||
            Main.layoutManager.overviewGroup.add_actor(view);
 | 
			
		||||
            Main.layoutManager.overviewGroup.add_actor(view.actor);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._workspacesViews.forEach(v => v.show());
 | 
			
		||||
        this._workspacesViews.forEach(v => v.actor.show());
 | 
			
		||||
 | 
			
		||||
        this._updateWorkspacesFullGeometry();
 | 
			
		||||
        this._updateWorkspacesActualGeometry();
 | 
			
		||||
@@ -712,7 +728,7 @@ class WorkspacesDisplay extends St.Widget {
 | 
			
		||||
        return this._getPrimaryView().getActiveWorkspace().hasMaximizedWindows();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vfunc_parent_set(oldParent) {
 | 
			
		||||
    _parentSet(actor, oldParent) {
 | 
			
		||||
        if (oldParent && this._notifyOpacityId)
 | 
			
		||||
            oldParent.disconnect(this._notifyOpacityId);
 | 
			
		||||
        this._notifyOpacityId = 0;
 | 
			
		||||
@@ -722,20 +738,20 @@ class WorkspacesDisplay extends St.Widget {
 | 
			
		||||
 | 
			
		||||
        this._parentSetLater = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
 | 
			
		||||
            this._parentSetLater = 0;
 | 
			
		||||
            let newParent = this.get_parent();
 | 
			
		||||
            let newParent = this.actor.get_parent();
 | 
			
		||||
            if (!newParent)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            // This is kinda hackish - we want the primary view to
 | 
			
		||||
            // appear as parent of this, though in reality it
 | 
			
		||||
            // appear as parent of this.actor, though in reality it
 | 
			
		||||
            // is added directly to Main.layoutManager.overviewGroup
 | 
			
		||||
            this._notifyOpacityId = newParent.connect('notify::opacity', () => {
 | 
			
		||||
                let opacity = this.get_parent().opacity;
 | 
			
		||||
                let opacity = this.actor.get_parent().opacity;
 | 
			
		||||
                let primaryView = this._getPrimaryView();
 | 
			
		||||
                if (!primaryView)
 | 
			
		||||
                    return;
 | 
			
		||||
                primaryView.opacity = opacity;
 | 
			
		||||
                primaryView.visible = opacity != 0;
 | 
			
		||||
                primaryView.actor.opacity = opacity;
 | 
			
		||||
                primaryView.actor.visible = opacity != 0;
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
@@ -763,8 +779,8 @@ class WorkspacesDisplay extends St.Widget {
 | 
			
		||||
        if (!this._workspacesViews.length)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let [x, y] = this.get_transformed_position();
 | 
			
		||||
        let allocation = this.allocation;
 | 
			
		||||
        let [x, y] = this.actor.get_transformed_position();
 | 
			
		||||
        let allocation = this.actor.allocation;
 | 
			
		||||
        let width = allocation.x2 - allocation.x1;
 | 
			
		||||
        let height = allocation.y2 - allocation.y1;
 | 
			
		||||
        let primaryGeometry = { x: x, y: y, width: width, height: height };
 | 
			
		||||
@@ -782,7 +798,7 @@ class WorkspacesDisplay extends St.Widget {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onScrollEvent(actor, event) {
 | 
			
		||||
        if (!this.mapped)
 | 
			
		||||
        if (!this.actor.mapped)
 | 
			
		||||
            return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
 | 
			
		||||
        if (this._workspacesOnlyOnPrimary &&
 | 
			
		||||
@@ -813,7 +829,7 @@ class WorkspacesDisplay extends St.Widget {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onKeyPressEvent(actor, event) {
 | 
			
		||||
        if (!this.mapped)
 | 
			
		||||
        if (!this.actor.mapped)
 | 
			
		||||
            return Clutter.EVENT_PROPAGATE;
 | 
			
		||||
        let workspaceManager = global.workspace_manager;
 | 
			
		||||
        let activeWs = workspaceManager.get_active_workspace();
 | 
			
		||||
@@ -831,4 +847,5 @@ class WorkspacesDisplay extends St.Widget {
 | 
			
		||||
        Main.wm.actionMoveWorkspace(ws);
 | 
			
		||||
        return Clutter.EVENT_STOP;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(WorkspacesDisplay.prototype);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
project('gnome-shell', 'c',
 | 
			
		||||
  version: '3.35.1',
 | 
			
		||||
  version: '3.34.1',
 | 
			
		||||
  meson_version: '>= 0.47.0',
 | 
			
		||||
  license: 'GPLv2+'
 | 
			
		||||
)
 | 
			
		||||
@@ -26,7 +26,7 @@ gio_req = '>= 2.56.0'
 | 
			
		||||
gi_req = '>= 1.49.1'
 | 
			
		||||
gjs_req = '>= 1.57.3'
 | 
			
		||||
gtk_req = '>= 3.15.0'
 | 
			
		||||
mutter_req = '>= 3.35.1'
 | 
			
		||||
mutter_req = '>= 3.34.0'
 | 
			
		||||
polkit_req = '>= 0.100'
 | 
			
		||||
schemas_req = '>= 3.33.1'
 | 
			
		||||
startup_req = '>= 0.11'
 | 
			
		||||
 
 | 
			
		||||
@@ -95,6 +95,7 @@ libshell_public_headers = [
 | 
			
		||||
  'shell-app.h',
 | 
			
		||||
  'shell-app-system.h',
 | 
			
		||||
  'shell-app-usage.h',
 | 
			
		||||
  'shell-blur-effect.h',
 | 
			
		||||
  'shell-embedded-window.h',
 | 
			
		||||
  'shell-glsl-effect.h',
 | 
			
		||||
  'shell-gtk-embed.h',
 | 
			
		||||
@@ -129,6 +130,7 @@ libshell_sources = [
 | 
			
		||||
  'shell-app.c',
 | 
			
		||||
  'shell-app-system.c',
 | 
			
		||||
  'shell-app-usage.c',
 | 
			
		||||
  'shell-blur-effect.c',
 | 
			
		||||
  'shell-embedded-window.c',
 | 
			
		||||
  'shell-embedded-window-private.h',
 | 
			
		||||
  'shell-global.c',
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										506
									
								
								src/shell-blur-effect.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										506
									
								
								src/shell-blur-effect.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,506 @@
 | 
			
		||||
/* shell-blur-effect.c
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright 2019 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "shell-blur-effect.h"
 | 
			
		||||
 | 
			
		||||
static const gchar *gaussian_blur_glsl_declarations =
 | 
			
		||||
"uniform float blur_radius;                                        \n"
 | 
			
		||||
"uniform float brightness;                                         \n"
 | 
			
		||||
"uniform float pixel_step;                                         \n"
 | 
			
		||||
"uniform int vertical;                                             \n"
 | 
			
		||||
"                                                                  \n"
 | 
			
		||||
"float gaussian (float sigma, float x) {                           \n"
 | 
			
		||||
"  return exp ( - (x * x) / (2.0 * sigma * sigma));                \n"
 | 
			
		||||
"}                                                                 \n"
 | 
			
		||||
"                                                                  \n";
 | 
			
		||||
 | 
			
		||||
static const gchar *gaussian_blur_glsl =
 | 
			
		||||
"  float radius = blur_radius * 2.30348;                           \n"
 | 
			
		||||
"  float total = 0.0;                                              \n"
 | 
			
		||||
"  vec4 ret = vec4 (0);                                            \n"
 | 
			
		||||
"  vec2 uv = vec2(cogl_tex_coord.st);                              \n"
 | 
			
		||||
"                                                                  \n"
 | 
			
		||||
"  int half_radius = max(int(radius / 2.0), 1);                    \n"
 | 
			
		||||
"                                                                  \n"
 | 
			
		||||
"  if (vertical != 0) {                                            \n"
 | 
			
		||||
"    for (int y = -half_radius; y < half_radius; y++) {            \n"
 | 
			
		||||
"      float fy = gaussian (radius / 2.0, float(y));               \n"
 | 
			
		||||
"      float offset_y = float(y) * pixel_step;                     \n"
 | 
			
		||||
"                                                                  \n"
 | 
			
		||||
"      vec4 c = texture2D(cogl_sampler, uv + vec2(0.0, offset_y)); \n"
 | 
			
		||||
"      total += fy;                                                \n"
 | 
			
		||||
"      ret += c * fy;                                              \n"
 | 
			
		||||
"    }                                                             \n"
 | 
			
		||||
"  } else {                                                        \n"
 | 
			
		||||
"    for (int x = -half_radius; x < half_radius; x++) {            \n"
 | 
			
		||||
"      float fx = gaussian (radius / 2.0, float(x));               \n"
 | 
			
		||||
"      float offset_x = float(x) * pixel_step;                     \n"
 | 
			
		||||
"                                                                  \n"
 | 
			
		||||
"      vec4 c = texture2D(cogl_sampler, uv + vec2(offset_x, 0.0)); \n"
 | 
			
		||||
"      total += fx;                                                \n"
 | 
			
		||||
"      ret += c * fx;                                              \n"
 | 
			
		||||
"    }                                                             \n"
 | 
			
		||||
"  }                                                               \n"
 | 
			
		||||
"                                                                  \n"
 | 
			
		||||
"  cogl_texel = vec4 (ret / total);                                \n"
 | 
			
		||||
"  cogl_texel.rgb *= brightness;                                   \n";
 | 
			
		||||
 | 
			
		||||
#define DOWNSCALE_FACTOR 4.0
 | 
			
		||||
 | 
			
		||||
struct _ShellBlurEffect
 | 
			
		||||
{
 | 
			
		||||
  ClutterOffscreenEffect parent_instance;
 | 
			
		||||
 | 
			
		||||
  CoglPipeline *pipeline;
 | 
			
		||||
  int blur_radius_uniform;
 | 
			
		||||
  int brightness_uniform;
 | 
			
		||||
  int pixel_step_uniform;
 | 
			
		||||
  int vertical_uniform;
 | 
			
		||||
 | 
			
		||||
  unsigned int tex_width;
 | 
			
		||||
  unsigned int tex_height;
 | 
			
		||||
 | 
			
		||||
  gboolean vertical;
 | 
			
		||||
  float brightness;
 | 
			
		||||
  int blur_radius;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE (ShellBlurEffect, shell_blur_effect, CLUTTER_TYPE_OFFSCREEN_EFFECT)
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
  PROP_0,
 | 
			
		||||
  PROP_BLUR_RADIUS,
 | 
			
		||||
  PROP_BRIGHTNESS,
 | 
			
		||||
  PROP_VERTICAL,
 | 
			
		||||
  N_PROPS
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static GParamSpec *properties [N_PROPS] = { NULL, };
 | 
			
		||||
 | 
			
		||||
static CoglPipeline*
 | 
			
		||||
create_pipeline (void)
 | 
			
		||||
{
 | 
			
		||||
  static CoglPipeline *base_pipeline = NULL;
 | 
			
		||||
 | 
			
		||||
  if (G_UNLIKELY (base_pipeline == NULL))
 | 
			
		||||
    {
 | 
			
		||||
      CoglSnippet *snippet;
 | 
			
		||||
      CoglContext *ctx =
 | 
			
		||||
        clutter_backend_get_cogl_context (clutter_get_default_backend ());
 | 
			
		||||
 | 
			
		||||
      base_pipeline = cogl_pipeline_new (ctx);
 | 
			
		||||
 | 
			
		||||
      snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_TEXTURE_LOOKUP,
 | 
			
		||||
                                  gaussian_blur_glsl_declarations,
 | 
			
		||||
                                  NULL);
 | 
			
		||||
      cogl_snippet_set_replace (snippet, gaussian_blur_glsl);
 | 
			
		||||
      cogl_pipeline_add_layer_snippet (base_pipeline, 0, snippet);
 | 
			
		||||
      cogl_object_unref (snippet);
 | 
			
		||||
 | 
			
		||||
      cogl_pipeline_set_layer_null_texture (base_pipeline, 0);
 | 
			
		||||
      cogl_pipeline_set_layer_filters (base_pipeline,
 | 
			
		||||
                                       0,
 | 
			
		||||
                                       COGL_PIPELINE_FILTER_LINEAR,
 | 
			
		||||
                                       COGL_PIPELINE_FILTER_LINEAR);
 | 
			
		||||
      cogl_pipeline_set_layer_wrap_mode (base_pipeline,
 | 
			
		||||
                                         0,
 | 
			
		||||
                                         COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return cogl_pipeline_copy (base_pipeline);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
queue_actor_repaint (ShellBlurEffect *self)
 | 
			
		||||
{
 | 
			
		||||
  ClutterActor *actor =
 | 
			
		||||
    clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (self));
 | 
			
		||||
 | 
			
		||||
  if (actor)
 | 
			
		||||
    clutter_actor_queue_redraw (actor);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
update_uniforms (ShellBlurEffect *self)
 | 
			
		||||
{
 | 
			
		||||
  ClutterOffscreenEffect *offscreen_effect =
 | 
			
		||||
    CLUTTER_OFFSCREEN_EFFECT (self);
 | 
			
		||||
  CoglHandle texture;
 | 
			
		||||
 | 
			
		||||
  texture = clutter_offscreen_effect_get_texture (offscreen_effect);
 | 
			
		||||
  self->tex_width = cogl_texture_get_width (texture) * DOWNSCALE_FACTOR;
 | 
			
		||||
  self->tex_height = cogl_texture_get_height (texture) * DOWNSCALE_FACTOR;
 | 
			
		||||
 | 
			
		||||
  if (self->pixel_step_uniform > -1)
 | 
			
		||||
    {
 | 
			
		||||
      ClutterRect rect;
 | 
			
		||||
      float pixel_step;
 | 
			
		||||
 | 
			
		||||
      clutter_offscreen_effect_get_target_rect (CLUTTER_OFFSCREEN_EFFECT (self),
 | 
			
		||||
                                                &rect);
 | 
			
		||||
 | 
			
		||||
      if (self->vertical)
 | 
			
		||||
        pixel_step = 1.f / rect.size.height;
 | 
			
		||||
      else
 | 
			
		||||
        pixel_step = 1.f / rect.size.width;
 | 
			
		||||
 | 
			
		||||
      cogl_pipeline_set_uniform_1f (self->pipeline,
 | 
			
		||||
                                    self->pixel_step_uniform,
 | 
			
		||||
                                    pixel_step / DOWNSCALE_FACTOR);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (self->blur_radius_uniform > -1)
 | 
			
		||||
    {
 | 
			
		||||
      cogl_pipeline_set_uniform_1f (self->pipeline,
 | 
			
		||||
                                    self->blur_radius_uniform,
 | 
			
		||||
                                    self->blur_radius / DOWNSCALE_FACTOR);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (self->brightness_uniform > -1)
 | 
			
		||||
    {
 | 
			
		||||
      cogl_pipeline_set_uniform_1f (self->pipeline,
 | 
			
		||||
                                    self->brightness_uniform,
 | 
			
		||||
                                    self->brightness);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (self->vertical_uniform > -1)
 | 
			
		||||
    {
 | 
			
		||||
      cogl_pipeline_set_uniform_1i (self->pipeline,
 | 
			
		||||
                                    self->vertical_uniform,
 | 
			
		||||
                                    self->vertical);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  cogl_pipeline_set_layer_texture (self->pipeline, 0, texture);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
shell_blur_effect_pre_paint (ClutterEffect *effect)
 | 
			
		||||
{
 | 
			
		||||
  gboolean success;
 | 
			
		||||
 | 
			
		||||
  success = CLUTTER_EFFECT_CLASS (shell_blur_effect_parent_class)->pre_paint (effect);
 | 
			
		||||
 | 
			
		||||
  if (success)
 | 
			
		||||
    {
 | 
			
		||||
      CoglFramebuffer *offscreen = cogl_get_draw_framebuffer ();
 | 
			
		||||
 | 
			
		||||
      /* Texture is downscaled, draw downscaled as well */
 | 
			
		||||
      cogl_framebuffer_scale (offscreen,
 | 
			
		||||
                              1.0 / DOWNSCALE_FACTOR,
 | 
			
		||||
                              1.0 / DOWNSCALE_FACTOR,
 | 
			
		||||
                              1.0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return success;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
shell_blur_effect_paint_target (ClutterOffscreenEffect *effect)
 | 
			
		||||
{
 | 
			
		||||
  ShellBlurEffect *self = SHELL_BLUR_EFFECT (effect);
 | 
			
		||||
  CoglFramebuffer *framebuffer = cogl_get_draw_framebuffer ();
 | 
			
		||||
  ClutterActor *actor;
 | 
			
		||||
  float blur_radius_offset_h;
 | 
			
		||||
  float blur_radius_offset_v;
 | 
			
		||||
  guint8 paint_opacity;
 | 
			
		||||
 | 
			
		||||
  update_uniforms (self);
 | 
			
		||||
 | 
			
		||||
  actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (self));
 | 
			
		||||
  paint_opacity = clutter_actor_get_paint_opacity (actor);
 | 
			
		||||
 | 
			
		||||
  cogl_pipeline_set_color4ub (self->pipeline,
 | 
			
		||||
                              paint_opacity,
 | 
			
		||||
                              paint_opacity,
 | 
			
		||||
                              paint_opacity,
 | 
			
		||||
                              paint_opacity);
 | 
			
		||||
 | 
			
		||||
  blur_radius_offset_h =
 | 
			
		||||
    self->blur_radius / (float) self->tex_width / DOWNSCALE_FACTOR;
 | 
			
		||||
  blur_radius_offset_v =
 | 
			
		||||
    self->blur_radius / (float) self->tex_height / DOWNSCALE_FACTOR;
 | 
			
		||||
 | 
			
		||||
  cogl_framebuffer_draw_textured_rectangle (framebuffer,
 | 
			
		||||
                                            self->pipeline,
 | 
			
		||||
                                            0, 0,
 | 
			
		||||
                                            self->tex_width,
 | 
			
		||||
                                            self->tex_height,
 | 
			
		||||
                                            blur_radius_offset_h,
 | 
			
		||||
                                            blur_radius_offset_v,
 | 
			
		||||
                                            1.f - blur_radius_offset_h,
 | 
			
		||||
                                            1.f - blur_radius_offset_v);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
shell_blur_effect_post_paint (ClutterEffect *effect)
 | 
			
		||||
{
 | 
			
		||||
  CoglFramebuffer *offscreen = cogl_get_draw_framebuffer ();
 | 
			
		||||
 | 
			
		||||
  cogl_framebuffer_scale (offscreen,
 | 
			
		||||
                          DOWNSCALE_FACTOR,
 | 
			
		||||
                          DOWNSCALE_FACTOR,
 | 
			
		||||
                          1.f);
 | 
			
		||||
 | 
			
		||||
  CLUTTER_EFFECT_CLASS (shell_blur_effect_parent_class)->post_paint (effect);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static CoglTexture*
 | 
			
		||||
shell_blur_effect_create_texture (ClutterOffscreenEffect *effect,
 | 
			
		||||
                                  float                   width,
 | 
			
		||||
                                  float                   height)
 | 
			
		||||
{
 | 
			
		||||
  CoglContext *ctx =
 | 
			
		||||
    clutter_backend_get_cogl_context (clutter_get_default_backend ());
 | 
			
		||||
 | 
			
		||||
  return cogl_texture_2d_new_with_size (ctx,
 | 
			
		||||
                                        width / DOWNSCALE_FACTOR,
 | 
			
		||||
                                        height / DOWNSCALE_FACTOR);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
shell_blur_effect_modify_paint_volume (ClutterEffect      *effect,
 | 
			
		||||
                                       ClutterPaintVolume *volume)
 | 
			
		||||
{
 | 
			
		||||
  ShellBlurEffect *self = SHELL_BLUR_EFFECT (effect);
 | 
			
		||||
  ClutterVertex origin;
 | 
			
		||||
  float width;
 | 
			
		||||
  float height;
 | 
			
		||||
 | 
			
		||||
  clutter_paint_volume_get_origin (volume, &origin);
 | 
			
		||||
  width = clutter_paint_volume_get_width (volume);
 | 
			
		||||
  height = clutter_paint_volume_get_height (volume);
 | 
			
		||||
 | 
			
		||||
  if (self->vertical)
 | 
			
		||||
    {
 | 
			
		||||
      origin.y -= self->blur_radius;
 | 
			
		||||
      height += 2 * self->blur_radius;
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      origin.x -= self->blur_radius;
 | 
			
		||||
      width += 2 * self->blur_radius;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  clutter_paint_volume_set_origin (volume, &origin);
 | 
			
		||||
  clutter_paint_volume_set_width (volume, width);
 | 
			
		||||
  clutter_paint_volume_set_height (volume, height);
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
shell_blur_effect_finalize (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
  ShellBlurEffect *self = (ShellBlurEffect *)object;
 | 
			
		||||
 | 
			
		||||
  g_clear_pointer (&self->pipeline, cogl_object_unref);
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (shell_blur_effect_parent_class)->finalize (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
shell_blur_effect_get_property (GObject    *object,
 | 
			
		||||
                                guint       prop_id,
 | 
			
		||||
                                GValue     *value,
 | 
			
		||||
                                GParamSpec *pspec)
 | 
			
		||||
{
 | 
			
		||||
  ShellBlurEffect *self = SHELL_BLUR_EFFECT (object);
 | 
			
		||||
 | 
			
		||||
  switch (prop_id)
 | 
			
		||||
    {
 | 
			
		||||
    case PROP_BLUR_RADIUS:
 | 
			
		||||
      g_value_set_int (value, self->blur_radius);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case PROP_BRIGHTNESS:
 | 
			
		||||
      g_value_set_int (value, self->brightness);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case PROP_VERTICAL:
 | 
			
		||||
      g_value_set_boolean (value, self->vertical);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
shell_blur_effect_set_property (GObject      *object,
 | 
			
		||||
                                guint         prop_id,
 | 
			
		||||
                                const GValue *value,
 | 
			
		||||
                                GParamSpec   *pspec)
 | 
			
		||||
{
 | 
			
		||||
  ShellBlurEffect *self = SHELL_BLUR_EFFECT (object);
 | 
			
		||||
 | 
			
		||||
  switch (prop_id)
 | 
			
		||||
    {
 | 
			
		||||
    case PROP_BLUR_RADIUS:
 | 
			
		||||
      shell_blur_effect_set_blur_radius (self, g_value_get_int (value));
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case PROP_BRIGHTNESS:
 | 
			
		||||
      shell_blur_effect_set_brightness (self, g_value_get_float (value));
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case PROP_VERTICAL:
 | 
			
		||||
      shell_blur_effect_set_vertical (self, g_value_get_boolean (value));
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
shell_blur_effect_class_init (ShellBlurEffectClass *klass)
 | 
			
		||||
{
 | 
			
		||||
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
 | 
			
		||||
  ClutterEffectClass *effect_class = CLUTTER_EFFECT_CLASS (klass);
 | 
			
		||||
  ClutterOffscreenEffectClass *offscreen_class =
 | 
			
		||||
    CLUTTER_OFFSCREEN_EFFECT_CLASS (klass);
 | 
			
		||||
 | 
			
		||||
  object_class->finalize = shell_blur_effect_finalize;
 | 
			
		||||
  object_class->get_property = shell_blur_effect_get_property;
 | 
			
		||||
  object_class->set_property = shell_blur_effect_set_property;
 | 
			
		||||
 | 
			
		||||
  effect_class->pre_paint = shell_blur_effect_pre_paint;
 | 
			
		||||
  effect_class->post_paint = shell_blur_effect_post_paint;
 | 
			
		||||
  effect_class->modify_paint_volume = shell_blur_effect_modify_paint_volume;
 | 
			
		||||
 | 
			
		||||
  offscreen_class->paint_target = shell_blur_effect_paint_target;
 | 
			
		||||
  offscreen_class->create_texture = shell_blur_effect_create_texture;
 | 
			
		||||
 | 
			
		||||
  properties[PROP_BLUR_RADIUS] =
 | 
			
		||||
    g_param_spec_int ("blur-radius",
 | 
			
		||||
                      "Blur radius",
 | 
			
		||||
                      "Blur radius",
 | 
			
		||||
                      0, G_MAXINT, 0,
 | 
			
		||||
                      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
 | 
			
		||||
 | 
			
		||||
  properties[PROP_BRIGHTNESS] =
 | 
			
		||||
    g_param_spec_float ("brightness",
 | 
			
		||||
                        "Brightness",
 | 
			
		||||
                        "Brightness",
 | 
			
		||||
                        0.f, 1.f, 1.f,
 | 
			
		||||
                        G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
 | 
			
		||||
 | 
			
		||||
  properties[PROP_VERTICAL] =
 | 
			
		||||
    g_param_spec_boolean ("vertical",
 | 
			
		||||
                          "Vertical",
 | 
			
		||||
                          "Whether the blur is vertical or horizontal",
 | 
			
		||||
                          FALSE,
 | 
			
		||||
                          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
 | 
			
		||||
 | 
			
		||||
  g_object_class_install_properties (object_class, N_PROPS, properties);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
shell_blur_effect_init (ShellBlurEffect *self)
 | 
			
		||||
{
 | 
			
		||||
  self->blur_radius = 0;
 | 
			
		||||
  self->brightness = 1.f;
 | 
			
		||||
  self->vertical = FALSE;
 | 
			
		||||
  self->pipeline = create_pipeline ();
 | 
			
		||||
 | 
			
		||||
  self->blur_radius_uniform =
 | 
			
		||||
    cogl_pipeline_get_uniform_location (self->pipeline, "blur_radius");
 | 
			
		||||
  self->brightness_uniform =
 | 
			
		||||
    cogl_pipeline_get_uniform_location (self->pipeline, "brightness");
 | 
			
		||||
  self->pixel_step_uniform =
 | 
			
		||||
    cogl_pipeline_get_uniform_location (self->pipeline, "pixel_step");
 | 
			
		||||
  self->vertical_uniform =
 | 
			
		||||
    cogl_pipeline_get_uniform_location (self->pipeline, "vertical");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ShellBlurEffect *
 | 
			
		||||
shell_blur_effect_new (void)
 | 
			
		||||
{
 | 
			
		||||
  return g_object_new (SHELL_TYPE_BLUR_EFFECT, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
shell_blur_effect_get_blur_radius (ShellBlurEffect *self)
 | 
			
		||||
{
 | 
			
		||||
  g_return_val_if_fail (SHELL_IS_BLUR_EFFECT (self), -1);
 | 
			
		||||
 | 
			
		||||
  return self->blur_radius;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
shell_blur_effect_set_blur_radius (ShellBlurEffect *self,
 | 
			
		||||
                                   int              radius)
 | 
			
		||||
{
 | 
			
		||||
  g_return_if_fail (SHELL_IS_BLUR_EFFECT (self));
 | 
			
		||||
 | 
			
		||||
  if (self->blur_radius == radius)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  self->blur_radius = radius;
 | 
			
		||||
  queue_actor_repaint (self);
 | 
			
		||||
 | 
			
		||||
  g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_BLUR_RADIUS]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
float
 | 
			
		||||
shell_blur_effect_get_brightness (ShellBlurEffect *self)
 | 
			
		||||
{
 | 
			
		||||
  g_return_val_if_fail (SHELL_IS_BLUR_EFFECT (self), FALSE);
 | 
			
		||||
 | 
			
		||||
  return self->brightness;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
shell_blur_effect_set_brightness (ShellBlurEffect *self,
 | 
			
		||||
                                  float            brightness)
 | 
			
		||||
{
 | 
			
		||||
  g_return_if_fail (SHELL_IS_BLUR_EFFECT (self));
 | 
			
		||||
 | 
			
		||||
  if (self->brightness == brightness)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  self->brightness = brightness;
 | 
			
		||||
  queue_actor_repaint (self);
 | 
			
		||||
 | 
			
		||||
  g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_BRIGHTNESS]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
shell_blur_effect_get_vertical (ShellBlurEffect *self)
 | 
			
		||||
{
 | 
			
		||||
  g_return_val_if_fail (SHELL_IS_BLUR_EFFECT (self), FALSE);
 | 
			
		||||
 | 
			
		||||
  return self->vertical;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
shell_blur_effect_set_vertical (ShellBlurEffect *self,
 | 
			
		||||
                                gboolean         vertical)
 | 
			
		||||
{
 | 
			
		||||
  g_return_if_fail (SHELL_IS_BLUR_EFFECT (self));
 | 
			
		||||
 | 
			
		||||
  if (self->vertical == vertical)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  self->vertical = vertical;
 | 
			
		||||
  queue_actor_repaint (self);
 | 
			
		||||
 | 
			
		||||
  g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_VERTICAL]);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										45
									
								
								src/shell-blur-effect.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								src/shell-blur-effect.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,45 @@
 | 
			
		||||
/* shell-blur-effect.h
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright 2019 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <clutter/clutter.h>
 | 
			
		||||
 | 
			
		||||
G_BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
#define SHELL_TYPE_BLUR_EFFECT (shell_blur_effect_get_type())
 | 
			
		||||
 | 
			
		||||
G_DECLARE_FINAL_TYPE (ShellBlurEffect, shell_blur_effect, SHELL, BLUR_EFFECT, ClutterOffscreenEffect)
 | 
			
		||||
 | 
			
		||||
ShellBlurEffect *shell_blur_effect_new (void);
 | 
			
		||||
 | 
			
		||||
int shell_blur_effect_get_blur_radius (ShellBlurEffect *self);
 | 
			
		||||
void shell_blur_effect_set_blur_radius (ShellBlurEffect *self,
 | 
			
		||||
                                        int              radius);
 | 
			
		||||
 | 
			
		||||
float shell_blur_effect_get_brightness (ShellBlurEffect *self);
 | 
			
		||||
void shell_blur_effect_set_brightness (ShellBlurEffect *self,
 | 
			
		||||
                                       float            brightness);
 | 
			
		||||
 | 
			
		||||
gboolean shell_blur_effect_get_vertical (ShellBlurEffect *self);
 | 
			
		||||
void shell_blur_effect_set_vertical (ShellBlurEffect *self,
 | 
			
		||||
                                     gboolean         vertical);
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
@@ -457,6 +457,7 @@ grab_window_screenshot (ClutterActor *stage,
 | 
			
		||||
  ClutterActor *window_actor;
 | 
			
		||||
  gfloat actor_x, actor_y;
 | 
			
		||||
  MetaRectangle rect;
 | 
			
		||||
  cairo_rectangle_int_t clip;
 | 
			
		||||
 | 
			
		||||
  window_actor = CLUTTER_ACTOR (meta_window_get_compositor_private (window));
 | 
			
		||||
  clutter_actor_get_position (window_actor, &actor_x, &actor_y);
 | 
			
		||||
@@ -466,10 +467,16 @@ grab_window_screenshot (ClutterActor *stage,
 | 
			
		||||
  if (!priv->include_frame)
 | 
			
		||||
    meta_window_frame_rect_to_client_rect (window, &rect, &rect);
 | 
			
		||||
 | 
			
		||||
  priv->screenshot_area = rect;
 | 
			
		||||
  priv->screenshot_area.x = rect.x;
 | 
			
		||||
  priv->screenshot_area.y = rect.y;
 | 
			
		||||
  clip.x = rect.x - (gint) actor_x;
 | 
			
		||||
  clip.y = rect.y - (gint) actor_y;
 | 
			
		||||
 | 
			
		||||
  clip.width = priv->screenshot_area.width = rect.width;
 | 
			
		||||
  clip.height = priv->screenshot_area.height = rect.height;
 | 
			
		||||
 | 
			
		||||
  priv->image = meta_window_actor_get_image (META_WINDOW_ACTOR (window_actor),
 | 
			
		||||
                                             NULL);
 | 
			
		||||
                                             &clip);
 | 
			
		||||
  priv->datetime = g_date_time_new_now_local ();
 | 
			
		||||
 | 
			
		||||
  if (priv->include_cursor)
 | 
			
		||||
 
 | 
			
		||||
@@ -35,7 +35,8 @@
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
stop_pick (ClutterActor *actor)
 | 
			
		||||
stop_pick (ClutterActor       *actor,
 | 
			
		||||
           const ClutterColor *color)
 | 
			
		||||
{
 | 
			
		||||
  g_signal_stop_emission_by_name (actor, "pick");
 | 
			
		||||
}
 | 
			
		||||
@@ -96,7 +97,7 @@ shell_util_get_transformed_allocation (ClutterActor    *actor,
 | 
			
		||||
  /* Code adapted from clutter-actor.c:
 | 
			
		||||
   * Copyright 2006, 2007, 2008 OpenedHand Ltd
 | 
			
		||||
   */
 | 
			
		||||
  graphene_point3d_t v[4];
 | 
			
		||||
  ClutterVertex v[4];
 | 
			
		||||
  gfloat x_min, x_max, y_min, y_max;
 | 
			
		||||
  guint i;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -443,7 +443,8 @@ st_box_layout_paint (ClutterActor *actor)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
st_box_layout_pick (ClutterActor *actor)
 | 
			
		||||
st_box_layout_pick (ClutterActor       *actor,
 | 
			
		||||
                    const ClutterColor *color)
 | 
			
		||||
{
 | 
			
		||||
  StBoxLayout *self = ST_BOX_LAYOUT (actor);
 | 
			
		||||
  StBoxLayoutPrivate *priv = self->priv;
 | 
			
		||||
@@ -461,7 +462,7 @@ st_box_layout_pick (ClutterActor *actor)
 | 
			
		||||
      cogl_framebuffer_translate (fb, (int)x, (int)y, 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  CLUTTER_ACTOR_CLASS (st_box_layout_parent_class)->pick (actor);
 | 
			
		||||
  CLUTTER_ACTOR_CLASS (st_box_layout_parent_class)->pick (actor, color);
 | 
			
		||||
 | 
			
		||||
  if (x != 0 || y != 0)
 | 
			
		||||
    {
 | 
			
		||||
@@ -505,7 +506,7 @@ st_box_layout_get_paint_volume (ClutterActor       *actor,
 | 
			
		||||
  StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor));
 | 
			
		||||
  ClutterActorBox allocation_box;
 | 
			
		||||
  ClutterActorBox content_box;
 | 
			
		||||
  graphene_point3d_t origin;
 | 
			
		||||
  ClutterVertex origin;
 | 
			
		||||
 | 
			
		||||
  /* Setting the paint volume does not make sense when we don't have any allocation */
 | 
			
		||||
  if (!clutter_actor_has_allocation (actor))
 | 
			
		||||
 
 | 
			
		||||
@@ -40,7 +40,7 @@ struct _StButtonClass
 | 
			
		||||
  void (* transition) (StButton     *button);
 | 
			
		||||
 | 
			
		||||
  /* signals */
 | 
			
		||||
  void (* clicked) (StButton *button, int clicked_button);
 | 
			
		||||
  void (* clicked) (StButton *button);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
StWidget    *st_button_new             (void);
 | 
			
		||||
 
 | 
			
		||||
@@ -48,19 +48,19 @@ static GParamSpec *props[N_PROPS] = { NULL, };
 | 
			
		||||
 | 
			
		||||
struct _StIconPrivate
 | 
			
		||||
{
 | 
			
		||||
  ClutterActor    *icon_texture;
 | 
			
		||||
  ClutterActor    *pending_texture;
 | 
			
		||||
  guint            opacity_handler_id;
 | 
			
		||||
  ClutterActor *icon_texture;
 | 
			
		||||
  ClutterActor *pending_texture;
 | 
			
		||||
  guint         opacity_handler_id;
 | 
			
		||||
 | 
			
		||||
  GIcon           *gicon;
 | 
			
		||||
  gint             prop_icon_size;  /* icon size set as property */
 | 
			
		||||
  gint             theme_icon_size; /* icon size from theme node */
 | 
			
		||||
  gint             icon_size;       /* icon size we are using */
 | 
			
		||||
  GIcon           *fallback_gicon;
 | 
			
		||||
  GIcon        *gicon;
 | 
			
		||||
  gint          prop_icon_size;  /* icon size set as property */
 | 
			
		||||
  gint          theme_icon_size; /* icon size from theme node */
 | 
			
		||||
  gint          icon_size;       /* icon size we are using */
 | 
			
		||||
  GIcon        *fallback_gicon;
 | 
			
		||||
 | 
			
		||||
  CoglPipeline    *shadow_pipeline;
 | 
			
		||||
  StShadow        *shadow_spec;
 | 
			
		||||
  graphene_size_t  shadow_size;
 | 
			
		||||
  CoglPipeline *shadow_pipeline;
 | 
			
		||||
  StShadow     *shadow_spec;
 | 
			
		||||
  ClutterSize   shadow_size;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE_WITH_PRIVATE (StIcon, st_icon, ST_TYPE_WIDGET)
 | 
			
		||||
@@ -290,7 +290,7 @@ st_icon_clear_shadow_pipeline (StIcon *icon)
 | 
			
		||||
  StIconPrivate *priv = icon->priv;
 | 
			
		||||
 | 
			
		||||
  g_clear_pointer (&priv->shadow_pipeline, cogl_object_unref);
 | 
			
		||||
  graphene_size_init (&priv->shadow_size, 0, 0);
 | 
			
		||||
  clutter_size_init (&priv->shadow_size, 0, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -317,7 +317,7 @@ st_icon_update_shadow_pipeline (StIcon *icon)
 | 
			
		||||
                                                   priv->icon_texture);
 | 
			
		||||
 | 
			
		||||
          if (priv->shadow_pipeline)
 | 
			
		||||
            graphene_size_init (&priv->shadow_size, width, height);
 | 
			
		||||
            clutter_size_init (&priv->shadow_size, width, height);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -100,7 +100,7 @@ st_scroll_view_fade_paint_target (ClutterOffscreenEffect *effect)
 | 
			
		||||
 | 
			
		||||
  float fade_area_topleft[2];
 | 
			
		||||
  float fade_area_bottomright[2];
 | 
			
		||||
  graphene_point3d_t verts[4];
 | 
			
		||||
  ClutterVertex verts[4];
 | 
			
		||||
 | 
			
		||||
  clutter_actor_get_paint_box (self->actor, &paint_box);
 | 
			
		||||
  clutter_actor_get_abs_allocation_vertices (self->actor, verts);
 | 
			
		||||
 
 | 
			
		||||
@@ -294,12 +294,13 @@ st_scroll_view_paint (ClutterActor *actor)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
st_scroll_view_pick (ClutterActor *actor)
 | 
			
		||||
st_scroll_view_pick (ClutterActor       *actor,
 | 
			
		||||
                     const ClutterColor *color)
 | 
			
		||||
{
 | 
			
		||||
  StScrollViewPrivate *priv = ST_SCROLL_VIEW (actor)->priv;
 | 
			
		||||
 | 
			
		||||
  /* Chain up so we get a bounding box pained (if we are reactive) */
 | 
			
		||||
  CLUTTER_ACTOR_CLASS (st_scroll_view_parent_class)->pick (actor);
 | 
			
		||||
  CLUTTER_ACTOR_CLASS (st_scroll_view_parent_class)->pick (actor, color);
 | 
			
		||||
 | 
			
		||||
  if (priv->child)
 | 
			
		||||
    clutter_actor_paint (priv->child);
 | 
			
		||||
@@ -962,6 +963,23 @@ st_scroll_view_remove (ClutterContainer *container,
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
st_scroll_view_foreach_with_internals (ClutterContainer *container,
 | 
			
		||||
                                       ClutterCallback   callback,
 | 
			
		||||
                                       gpointer          user_data)
 | 
			
		||||
{
 | 
			
		||||
  StScrollViewPrivate *priv = ST_SCROLL_VIEW (container)->priv;
 | 
			
		||||
 | 
			
		||||
  if (priv->child != NULL)
 | 
			
		||||
    callback (priv->child, user_data);
 | 
			
		||||
 | 
			
		||||
  if (priv->hscroll != NULL)
 | 
			
		||||
    callback (priv->hscroll, user_data);
 | 
			
		||||
 | 
			
		||||
  if (priv->vscroll != NULL)
 | 
			
		||||
    callback (priv->vscroll, user_data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
clutter_container_iface_init (ClutterContainerIface *iface)
 | 
			
		||||
{
 | 
			
		||||
@@ -973,6 +991,7 @@ clutter_container_iface_init (ClutterContainerIface *iface)
 | 
			
		||||
 | 
			
		||||
  iface->add = st_scroll_view_add;
 | 
			
		||||
  iface->remove = st_scroll_view_remove;
 | 
			
		||||
  iface->foreach_with_internals = st_scroll_view_foreach_with_internals;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
StWidget *
 | 
			
		||||
 
 | 
			
		||||
@@ -762,7 +762,7 @@ st_widget_get_paint_volume (ClutterActor *self,
 | 
			
		||||
  ClutterActorBox paint_box, alloc_box;
 | 
			
		||||
  StThemeNode *theme_node;
 | 
			
		||||
  StWidgetPrivate *priv;
 | 
			
		||||
  graphene_point3d_t origin;
 | 
			
		||||
  ClutterVertex origin;
 | 
			
		||||
 | 
			
		||||
  /* Setting the paint volume does not make sense when we don't have any allocation */
 | 
			
		||||
  if (!clutter_actor_has_allocation (self))
 | 
			
		||||
@@ -2062,7 +2062,7 @@ filter_by_position (GList            *children,
 | 
			
		||||
                    StDirectionType   direction)
 | 
			
		||||
{
 | 
			
		||||
  ClutterActorBox cbox;
 | 
			
		||||
  graphene_point3d_t abs_vertices[4];
 | 
			
		||||
  ClutterVertex abs_vertices[4];
 | 
			
		||||
  GList *l, *ret;
 | 
			
		||||
  ClutterActor *child;
 | 
			
		||||
 | 
			
		||||
@@ -2128,7 +2128,7 @@ get_distance (ClutterActor    *actor,
 | 
			
		||||
{
 | 
			
		||||
  int ax, ay, bx, by, dx, dy;
 | 
			
		||||
  ClutterActorBox abox;
 | 
			
		||||
  graphene_point3d_t abs_vertices[4];
 | 
			
		||||
  ClutterVertex abs_vertices[4];
 | 
			
		||||
 | 
			
		||||
  clutter_actor_get_abs_allocation_vertices (actor, abs_vertices);
 | 
			
		||||
  clutter_actor_box_from_vertices (&abox, abs_vertices);
 | 
			
		||||
@@ -2232,7 +2232,7 @@ st_widget_real_navigate_focus (StWidget         *widget,
 | 
			
		||||
  else /* direction is an arrow key, not tab */
 | 
			
		||||
    {
 | 
			
		||||
      ClutterActorBox sort_box;
 | 
			
		||||
      graphene_point3d_t abs_vertices[4];
 | 
			
		||||
      ClutterVertex abs_vertices[4];
 | 
			
		||||
 | 
			
		||||
      /* Compute the allocation box of the previous focused actor. If there
 | 
			
		||||
       * was no previous focus, use the coordinates of the appropriate edge of
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,7 @@ function test() {
 | 
			
		||||
    // Calendar can only be imported after Environment.init()
 | 
			
		||||
    const Calendar = imports.ui.calendar;
 | 
			
		||||
    let calendar = new Calendar.Calendar();
 | 
			
		||||
    vbox.add(calendar,
 | 
			
		||||
    vbox.add(calendar.actor,
 | 
			
		||||
             { expand: true,
 | 
			
		||||
               x_fill: false, x_align: St.Align.MIDDLE,
 | 
			
		||||
               y_fill: false, y_align: St.Align.START });
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user