Compare commits
	
		
			124 Commits
		
	
	
		
			wip/exalm/
			...
			gbsneto/co
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | d6345a5c8b | ||
|   | 628b34e96f | ||
|   | 5743b52ec8 | ||
|   | 55b57421dc | ||
|   | 320df13b65 | ||
|   | e4920b2f80 | ||
|   | c9fbae3408 | ||
|   | a3c6217875 | ||
|   | db7726c5bf | ||
|   | 0b91dee5a9 | ||
|   | 3838220961 | ||
|   | 9bb12f6f87 | ||
|   | 4dea1f801a | ||
|   | 91a5133116 | ||
|   | c4c5c4fd5c | ||
|   | f67b409fc1 | ||
|   | 22fe4e92c7 | ||
|   | 91eb84fa4e | ||
|   | 4e1492c926 | ||
|   | ed97f61750 | ||
|   | b5676a2a5c | ||
|   | 7059dcced3 | ||
|   | c7e0c7eb79 | ||
|   | ff775213a5 | ||
|   | 7f9c709c85 | ||
|   | 74d7d3e259 | ||
|   | 0353a5bf2c | ||
|   | ab6a629955 | ||
|   | 6cad251187 | ||
|   | d7c569c692 | ||
|   | 0615370930 | ||
|   | 7a92a9ba21 | ||
|   | 0199857c5b | ||
|   | 59e3a1a816 | ||
|   | 6533690fff | ||
|   | d0d1845bb6 | ||
|   | 20f4fc7c87 | ||
|   | b4128967a1 | ||
|   | 38ad1d7c13 | ||
|   | f78136182f | ||
|   | 11d46cf5b3 | ||
|   | 7326e7a9fa | ||
|   | a65164e540 | ||
|   | 279024afc2 | ||
|   | ef8000d2e6 | ||
|   | 986600ab31 | ||
|   | 3d39b32a0b | ||
|   | 6205d5eb27 | ||
|   | a722b4c51d | ||
|   | 31fe517007 | ||
|   | 31d915a38a | ||
|   | e00878ab75 | ||
|   | 3b5675b79a | ||
|   | ee97512bcc | ||
|   | 085531b43d | ||
|   | 9e8b97d474 | ||
|   | a3a7953704 | ||
|   | 92c0171aeb | ||
|   | 6a6d66486d | ||
|   | 1cc766d636 | ||
|   | 60cad01880 | ||
|   | 63c9a6efd0 | ||
|   | 1d1b42756f | ||
|   | a95601afdb | ||
|   | 2dbdf792db | ||
|   | e23ce37e62 | ||
|   | a05cb76e0d | ||
|   | 60cab56f86 | ||
|   | 70a5c3875c | ||
|   | 0fdbde9101 | ||
|   | 2156577333 | ||
|   | f3e09b2b2f | ||
|   | 6180f59c13 | ||
|   | 506b75fc7f | ||
|   | a0d0a17d68 | ||
|   | 92e5713e29 | ||
|   | 856c32db91 | ||
|   | 7b45ffa511 | ||
|   | b6754d7db7 | ||
|   | 2a9977a5b3 | ||
|   | dab60d5580 | ||
|   | 8e3aac8ed7 | ||
|   | 147cb53140 | ||
|   | 54f369404a | ||
|   | af1aabff75 | ||
|   | d6ba6dc554 | ||
|   | 42188b7698 | ||
|   | 48adb2ef4b | ||
|   | f8e648b7e3 | ||
|   | daa5452af2 | ||
|   | 259874d731 | ||
|   | 23344701de | ||
|   | 00e95de114 | ||
|   | 942758bb30 | ||
|   | e0947b01bd | ||
|   | cf00231aa8 | ||
|   | 5c3f4f5f8b | ||
|   | 5f10047b58 | ||
|   | 3094f86334 | ||
|   | 8ffea9d5c5 | ||
|   | 4f3c8b8d69 | ||
|   | edf6bd6909 | ||
|   | 3e58af10ca | ||
|   | 9e55d262f9 | ||
|   | 252e694979 | ||
|   | efed695eca | ||
|   | b446667df6 | ||
|   | 133a1e7bef | ||
|   | 5b3935fa43 | ||
|   | 471165ca9b | ||
|   | 111f87a1b2 | ||
|   | 93525539c2 | ||
|   | a77377efe7 | ||
|   | 81ab2865f7 | ||
|   | e585f7d97b | ||
|   | 1a32e3e74a | ||
|   | 8d6820c4df | ||
|   | 2546445884 | ||
|   | e44b7df078 | ||
|   | 3a9eaa39ea | ||
|   | af87bd8c87 | ||
|   | 4bfb4a0e3d | ||
|   | d1a6601e60 | ||
|   | 817aec5466 | 
							
								
								
									
										19
									
								
								HACKING.md
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								HACKING.md
									
									
									
									
									
								
							| @@ -186,15 +186,27 @@ 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` and `_delegate` | ||||
| ## `actor` (deprecated) 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, we usually have a wrapper class | ||||
| that has a property called `actor`. We call this wrapper class the "delegate". | ||||
| 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". | ||||
|  | ||||
| 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() { | ||||
| @@ -215,6 +227,7 @@ 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 | ||||
|  | ||||
|   | ||||
							
								
								
									
										48
									
								
								NEWS
									
									
									
									
									
								
							
							
						
						
									
										48
									
								
								NEWS
									
									
									
									
									
								
							| @@ -1,3 +1,51 @@ | ||||
| 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] | ||||
| * Allow editing app folder names [Georges, Marco; !675, !720] | ||||
| * Skip property transitions while hidden [Florian; !708] | ||||
| * Make menu animations more consistent [Florian, GB_2; #1595, !717] | ||||
| * Improve performance when enabling/disabling all extensions [Jonas D.; !96] | ||||
| * Fix extra icons appearing in "Frequent" view animation [Georges; !696] | ||||
| * Fix fading out desktop icons [Harshula; #1616] | ||||
| * Fix box-shadow glitch with prerendered resources [Daniel; #1186] | ||||
| * Fix accidentally skipped animations [Florian; #1572] | ||||
| * Fix screenshots and window animations when scaled [Robert; !728] | ||||
| * Don't leak NOTIFY_SOCKET environment variable to applications [Benjamin; !741] | ||||
| * Fix lock-up on X11 when ibus is already running on startup [Marco; #1712] | ||||
| * Fix screen dimming on idle [Marco; #1683] | ||||
| * Do not notify systemd before initialization is complete [Iain; !750] | ||||
| * Support SAE secrets in network agent [Lubomir; !751] | ||||
| * Fix various regressions with dynamic workspaces [Florian; #1497] | ||||
| * Fixed crashes [Florian, Marco; #1678, !746] | ||||
| * Misc. bug fixes and cleanups [Marco, Jonas D., Florian, Iain, Georges, | ||||
|   Jonas Å., Martin, Takao, Carlos; !700, !705, !709, !711, !707, #1538, !710, | ||||
|   !713, !699, !715, !718, !716, !719, !721, #1243, !725, !731, #1614, !683, | ||||
|   !732, !121, !735, !736, !740, #573, #1641, #1571] | ||||
|  | ||||
| Contributors: | ||||
|   Marco Trevisan (Treviño), Benjamin Berg, Jonas Dreßler, Takao Fujiwara, GB_2, | ||||
|   Carlos Garnacho, Harshula Jayasuriya, Iain Lane, Robert Mader, | ||||
|   Daniel García Moreno, Florian Müllner, Georges Basile Stavracas Neto, | ||||
|   Lubomir Rintel, Martin Zurowietz, Jonas Ådahl | ||||
|  | ||||
| Translators: | ||||
|   Rafael Fontenelle [pt_BR], Fran Dieguez [gl], Balázs Úr [hu], | ||||
|   Milo Casagrande [it], Daniel Șerbănescu [ro], Kukuh Syafaat [id], | ||||
|   Jiri Grönroos [fi], Daniel Mustieles [es], Piotr Drąg [pl], | ||||
|   Anders Jonsson [sv], Marek Černocký [cs], Jordi Mas [ca], | ||||
|   Aurimas Černius [lt], Christian Kirbach [de], Emin Tufan Çetin [tr], | ||||
|   Enrico Nicoletto [pt_BR], Danial Behzadi [fa], Марко Костић [sr], | ||||
|   Alexandre Franke [fr], Charles Monzat [fr], Kjartan Maraas [nb], | ||||
|   Ryuta Fujii [ja], Nathan Follens [nl], Dušan Kazik [sk], Fabio Tomat [fur], | ||||
|   Matej Urbančič [sl], Ask Hjorth Larsen [da], Alan Mortensen [da] | ||||
|  | ||||
| 3.34.0 | ||||
| ====== | ||||
| * Handle startup/shutdown of misc X11 services [Carlos; !680] | ||||
|   | ||||
| @@ -610,13 +610,12 @@ StScrollBar { | ||||
|     border-bottom-style: solid; | ||||
|   } | ||||
|  | ||||
|  | ||||
| // Rename popup | ||||
|  | ||||
| .rename-folder-popup-box { | ||||
|   spacing: 6px; | ||||
|   margin-left: 12px; | ||||
|   margin-right: 12px; | ||||
| .rename-folder-popup { | ||||
|   .rename-folder-popup-item { | ||||
|     spacing: 6px; | ||||
|     &:ltr, &:rtl { padding: 0, 12px; } | ||||
|   } | ||||
| } | ||||
|  | ||||
| // Background menu | ||||
| @@ -750,7 +749,7 @@ StScrollBar { | ||||
|  | ||||
|   .ws-switcher-active-up, .ws-switcher-active-down, | ||||
|   .ws-switcher-active-left, .ws-switcher-active-right { | ||||
|     height: 50px; | ||||
|     height: 52px; | ||||
|     background-color: $selected_bg_color; | ||||
|     color: $selected_fg_color; | ||||
|     background-size: 32px; | ||||
|   | ||||
| @@ -31,34 +31,34 @@ its dependencies to build from tarballs.</description> | ||||
|   <programming-language>JavaScript</programming-language> | ||||
|   <programming-language>C</programming-language> | ||||
|  | ||||
|   <maintainer> | ||||
|   <author> | ||||
|     <foaf:Person> | ||||
|       <foaf:name>William Jon McCann</foaf:name> | ||||
|       <foaf:mbox rdf:resource="mailto:jmccann@redhat.com" /> | ||||
|       <gnome:userid>mccann</gnome:userid> | ||||
|     </foaf:Person> | ||||
|   </maintainer> | ||||
|   <maintainer> | ||||
|   </author> | ||||
|   <author> | ||||
|     <foaf:Person> | ||||
|       <foaf:name>Owen Taylor</foaf:name> | ||||
|       <foaf:mbox rdf:resource="mailto:otaylor@redhat.com" /> | ||||
|       <gnome:userid>otaylor</gnome:userid> | ||||
|     </foaf:Person> | ||||
|   </maintainer> | ||||
|   <maintainer> | ||||
|   </author> | ||||
|   <author> | ||||
|     <foaf:Person> | ||||
|       <foaf:name>Colin Walters</foaf:name> | ||||
|       <foaf:mbox rdf:resource="mailto:walters@verbum.org" /> | ||||
|       <gnome:userid>walters</gnome:userid> | ||||
|     </foaf:Person> | ||||
|   </maintainer> | ||||
|   <maintainer> | ||||
|   </author> | ||||
|   <author> | ||||
|     <foaf:Person> | ||||
|       <foaf:name>Marina Zhurakhinskaya</foaf:name> | ||||
|       <foaf:mbox rdf:resource="mailto:marinaz@redhat.com" /> | ||||
|       <gnome:userid>marinaz</gnome:userid> | ||||
|     </foaf:Person> | ||||
|   </maintainer> | ||||
|   </author> | ||||
|   <maintainer> | ||||
|     <foaf:Person> | ||||
|       <foaf:name>Florian Müllner</foaf:name> | ||||
|   | ||||
| @@ -285,8 +285,9 @@ var Application = GObject.registerClass({ | ||||
|                     log(`Failed to connect to shell proxy: ${e}`); | ||||
|                     this._mainStack.add_named(new NoShellPlaceholder(), 'noshell'); | ||||
|                     this._mainStack.visible_child_name = 'noshell'; | ||||
|                 } else | ||||
|                 } else { | ||||
|                     throw e; | ||||
|                 } | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported AuthPrompt */ | ||||
|  | ||||
| const { Clutter, Pango, Shell, St } = imports.gi; | ||||
| const Signals = imports.signals; | ||||
| const { Clutter, GObject, Pango, Shell, St } = imports.gi; | ||||
|  | ||||
| const Animation = imports.ui.animation; | ||||
| const Batch = imports.gdm.batch; | ||||
| @@ -33,8 +33,21 @@ var BeginRequestType = { | ||||
|     DONT_PROVIDE_USERNAME: 1 | ||||
| }; | ||||
|  | ||||
| var AuthPrompt = class { | ||||
|     constructor(gdmClient, mode) { | ||||
| 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 | ||||
|         }); | ||||
|  | ||||
|         this.verificationStatus = AuthPromptStatus.NOT_VERIFYING; | ||||
|  | ||||
|         this._gdmClient = gdmClient; | ||||
| @@ -67,38 +80,33 @@ var AuthPrompt = class { | ||||
|             } | ||||
|         }); | ||||
|  | ||||
|         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.connect('destroy', this._onDestroy.bind(this)); | ||||
|  | ||||
|         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._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._label = new St.Label({ style_class: 'login-dialog-prompt-label' }); | ||||
|  | ||||
|         this.actor.add(this._label, | ||||
|                        { expand: true, | ||||
|                          x_fill: false, | ||||
|                          y_fill: true, | ||||
|                          x_align: St.Align.START }); | ||||
|         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._entry, | ||||
|                        { expand: true, | ||||
|                          x_fill: true, | ||||
|                          y_fill: false, | ||||
|                          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(); | ||||
|  | ||||
| @@ -106,14 +114,15 @@ var AuthPrompt = class { | ||||
|                                        styleClass: 'login-dialog-message' }); | ||||
|         this._message.clutter_text.line_wrap = true; | ||||
|         this._message.clutter_text.ellipsize = Pango.EllipsizeMode.NONE; | ||||
|         this.actor.add(this._message, { x_fill: false, x_align: St.Align.START, y_align: St.Align.START }); | ||||
|         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.actor.add(this._buttonBox, | ||||
|                        { expand: true, | ||||
|                          x_align: St.Align.MIDDLE, | ||||
|                          y_align: St.Align.END }); | ||||
|         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; | ||||
| @@ -121,9 +130,9 @@ var AuthPrompt = class { | ||||
|         this._initButtons(); | ||||
|  | ||||
|         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); | ||||
|         this._spinner.opacity = 0; | ||||
|         this._spinner.show(); | ||||
|         this._defaultButtonWell.add_child(this._spinner); | ||||
|     } | ||||
|  | ||||
|     _onDestroy() { | ||||
| @@ -131,6 +140,12 @@ var AuthPrompt = class { | ||||
|         this._userVerifier = null; | ||||
|     } | ||||
|  | ||||
|     vfunc_key_press_event(keyPressEvent) { | ||||
|         if (keyPressEvent.keyval == Clutter.KEY_Escape) | ||||
|             this.cancel(); | ||||
|         return Clutter.EVENT_PROPAGATE; | ||||
|     } | ||||
|  | ||||
|     _initButtons() { | ||||
|         this.cancelButton = new St.Button({ style_class: 'modal-dialog-button button', | ||||
|                                             button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE, | ||||
| @@ -269,13 +284,13 @@ var AuthPrompt = class { | ||||
|             oldActor.remove_all_transitions(); | ||||
|  | ||||
|         let wasSpinner; | ||||
|         if (oldActor == this._spinner.actor) | ||||
|         if (oldActor == this._spinner) | ||||
|             wasSpinner = true; | ||||
|         else | ||||
|             wasSpinner = false; | ||||
|  | ||||
|         let isSpinner; | ||||
|         if (actor == this._spinner.actor) | ||||
|         if (actor == this._spinner) | ||||
|             isSpinner = true; | ||||
|         else | ||||
|             isSpinner = false; | ||||
| @@ -323,7 +338,7 @@ var AuthPrompt = class { | ||||
|     } | ||||
|  | ||||
|     startSpinning() { | ||||
|         this.setActorInDefaultButtonWell(this._spinner.actor, true); | ||||
|         this.setActorInDefaultButtonWell(this._spinner, true); | ||||
|     } | ||||
|  | ||||
|     stopSpinning() { | ||||
| @@ -404,9 +419,9 @@ var AuthPrompt = class { | ||||
|         this._entry.clutter_text.editable = sensitive; | ||||
|     } | ||||
|  | ||||
|     hide() { | ||||
|     vfunc_hide() { | ||||
|         this.setActorInDefaultButtonWell(null, true); | ||||
|         this.actor.hide(); | ||||
|         super.vfunc_hide(); | ||||
|         this._message.opacity = 0; | ||||
|  | ||||
|         this.setUser(null); | ||||
| @@ -422,7 +437,7 @@ var AuthPrompt = class { | ||||
|  | ||||
|         if (user) { | ||||
|             let userWidget = new UserWidget.UserWidget(user); | ||||
|             this._userWell.set_child(userWidget.actor); | ||||
|             this._userWell.set_child(userWidget); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -507,5 +522,4 @@ var AuthPrompt = class { | ||||
|         this.reset(); | ||||
|         this.emit('cancelled'); | ||||
|     } | ||||
| }; | ||||
| Signals.addSignalMethods(AuthPrompt.prototype); | ||||
| }); | ||||
|   | ||||
| @@ -202,7 +202,6 @@ var ConsecutiveBatch = class extends Batch { | ||||
|                 hold.disconnect(signalId); | ||||
|                 this.nextTask(); | ||||
|             }); | ||||
|             return; | ||||
|         } else { | ||||
|             // This task finished, process the next one | ||||
|             this.nextTask(); | ||||
|   | ||||
| @@ -19,7 +19,6 @@ | ||||
|  | ||||
| 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; | ||||
| @@ -39,72 +38,80 @@ const _TIMED_LOGIN_IDLE_THRESHOLD = 5.0; | ||||
| const _LOGO_ICON_HEIGHT = 48; | ||||
| const _MAX_BOTTOM_MENU_ITEMS = 5; | ||||
|  | ||||
| var UserListItem = class { | ||||
|     constructor(user) { | ||||
| 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 | ||||
|         }); | ||||
|  | ||||
|         this.user = user; | ||||
|         this._userChangedId = this.user.connect('changed', | ||||
|                                                 this._onUserChanged.bind(this)); | ||||
|  | ||||
|         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.connect('destroy', this._onDestroy.bind(this)); | ||||
|         this.connect('notify::hover', () => { | ||||
|             this._setSelected(this.hover); | ||||
|         }); | ||||
|  | ||||
|         this._userWidget = new UserWidget.UserWidget(this.user); | ||||
|         layout.add(this._userWidget.actor); | ||||
|         layout.add(this._userWidget); | ||||
|  | ||||
|         this._userWidget.actor.bind_property('label-actor', this.actor, 'label-actor', | ||||
|                                              GObject.BindingFlags.SYNC_CREATE); | ||||
|         this._userWidget.bind_property('label-actor', this, '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.actor.add_style_pseudo_class('logged-in'); | ||||
|             this.add_style_pseudo_class('logged-in'); | ||||
|         else | ||||
|             this.actor.remove_style_pseudo_class('logged-in'); | ||||
|             this.remove_style_pseudo_class('logged-in'); | ||||
|     } | ||||
|  | ||||
|     _onDestroy() { | ||||
|         this.user.disconnect(this._userChangedId); | ||||
|     } | ||||
|  | ||||
|     _onClicked() { | ||||
|     vfunc_clicked() { | ||||
|         this.emit('activate'); | ||||
|     } | ||||
|  | ||||
|     _setSelected(selected) { | ||||
|         if (selected) { | ||||
|             this.actor.add_style_pseudo_class('selected'); | ||||
|             this.actor.grab_key_focus(); | ||||
|             this.add_style_pseudo_class('selected'); | ||||
|             this.grab_key_focus(); | ||||
|         } else { | ||||
|             this.actor.remove_style_pseudo_class('selected'); | ||||
|             this.remove_style_pseudo_class('selected'); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -145,23 +152,30 @@ var UserListItem = class { | ||||
|         this._timedLoginIndicator.visible = false; | ||||
|         this._timedLoginIndicator.scale_x = 0.; | ||||
|     } | ||||
| }; | ||||
| Signals.addSignalMethods(UserListItem.prototype); | ||||
| }); | ||||
|  | ||||
| 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); | ||||
| 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); | ||||
|  | ||||
|         this._box = new St.BoxLayout({ vertical: true, | ||||
|                                        style_class: 'login-dialog-user-list', | ||||
|                                        pseudo_class: 'expanded' }); | ||||
|  | ||||
|         this.actor.add_actor(this._box); | ||||
|         this.add_actor(this._box); | ||||
|         this._items = {}; | ||||
|     } | ||||
|  | ||||
|         this.actor.connect('key-focus-in', this._moveFocusToItems.bind(this)); | ||||
|     vfunc_key_focus_in() { | ||||
|         this._moveFocusToItems(); | ||||
|     } | ||||
|  | ||||
|     _moveFocusToItems() { | ||||
| @@ -170,10 +184,10 @@ var UserList = class { | ||||
|         if (!hasItems) | ||||
|             return; | ||||
|  | ||||
|         if (global.stage.get_key_focus() != this.actor) | ||||
|         if (global.stage.get_key_focus() != this) | ||||
|             return; | ||||
|  | ||||
|         let focusSet = this.actor.navigate_focus(null, St.DirectionType.TAB_FORWARD, false); | ||||
|         let focusSet = this.navigate_focus(null, St.DirectionType.TAB_FORWARD, false); | ||||
|         if (!focusSet) { | ||||
|             Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => { | ||||
|                 this._moveFocusToItems(); | ||||
| @@ -194,14 +208,14 @@ var UserList = class { | ||||
|  | ||||
|         for (let userName in this._items) { | ||||
|             let item = this._items[userName]; | ||||
|             item.actor.sync_hover(); | ||||
|             item.sync_hover(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     scrollToItem(item) { | ||||
|         let box = item.actor.get_allocation_box(); | ||||
|         let box = item.get_allocation_box(); | ||||
|  | ||||
|         let adjustment = this.actor.get_vscroll_bar().get_adjustment(); | ||||
|         let adjustment = this.get_vscroll_bar().get_adjustment(); | ||||
|  | ||||
|         let value = (box.y1 + adjustment.step_increment / 2.0) - (adjustment.page_size / 2.0); | ||||
|         adjustment.ease(value, { | ||||
| @@ -211,9 +225,9 @@ var UserList = class { | ||||
|     } | ||||
|  | ||||
|     jumpToItem(item) { | ||||
|         let box = item.actor.get_allocation_box(); | ||||
|         let box = item.get_allocation_box(); | ||||
|  | ||||
|         let adjustment = this.actor.get_vscroll_bar().get_adjustment(); | ||||
|         let adjustment = this.get_vscroll_bar().get_adjustment(); | ||||
|  | ||||
|         let value = (box.y1 + adjustment.step_increment / 2.0) - (adjustment.page_size / 2.0); | ||||
|  | ||||
| @@ -251,14 +265,14 @@ var UserList = class { | ||||
|         this.removeUser(user); | ||||
|  | ||||
|         let item = new UserListItem(user); | ||||
|         this._box.add(item.actor, { x_fill: true }); | ||||
|         this._box.add(item, { x_fill: true }); | ||||
|  | ||||
|         this._items[userName] = item; | ||||
|  | ||||
|         item.connect('activate', this._onItemActivated.bind(this)); | ||||
|  | ||||
|         // Try to keep the focused item front-and-center | ||||
|         item.actor.connect('key-focus-in', () => this.scrollToItem(item)); | ||||
|         item.connect('key-focus-in', () => this.scrollToItem(item)); | ||||
|  | ||||
|         this._moveFocusToItems(); | ||||
|  | ||||
| @@ -279,33 +293,38 @@ var UserList = class { | ||||
|         if (!item) | ||||
|             return; | ||||
|  | ||||
|         item.actor.destroy(); | ||||
|         item.destroy(); | ||||
|         delete this._items[userName]; | ||||
|     } | ||||
|  | ||||
|     numItems() { | ||||
|         return Object.keys(this._items).length; | ||||
|     } | ||||
| }; | ||||
| Signals.addSignalMethods(UserList.prototype); | ||||
| }); | ||||
|  | ||||
| var SessionMenuButton = class { | ||||
|     constructor() { | ||||
| var SessionMenuButton = GObject.registerClass({ | ||||
|     GTypeName: 'LoginDialog_SessionMenuButton', | ||||
|     Signals: { 'session-activated': { param_types: [GObject.TYPE_STRING] } } | ||||
| }, class SessionMenuButton extends St.Bin { | ||||
|     _init() { | ||||
|         let gearIcon = new St.Icon({ icon_name: 'emblem-system-symbolic' }); | ||||
|         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 }); | ||||
|         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.actor = new St.Bin({ child: this._button }); | ||||
|         super._init({ child: button }); | ||||
|         this._button = button; | ||||
|  | ||||
|         let side = St.Side.TOP; | ||||
|         let align = 0; | ||||
|         if (Gdm.get_session_ids().length > _MAX_BOTTOM_MENU_ITEMS) { | ||||
|             if (this.actor.text_direction == Clutter.TextDirection.RTL) | ||||
|             if (this.text_direction == Clutter.TextDirection.RTL) | ||||
|                 side = St.Side.RIGHT; | ||||
|             else | ||||
|                 side = St.Side.LEFT; | ||||
| @@ -384,15 +403,13 @@ var SessionMenuButton = class { | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
| }; | ||||
| 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); | ||||
|  | ||||
| @@ -426,7 +443,7 @@ var LoginDialog = GObject.registerClass({ | ||||
|         this.add_child(this._userSelectionBox); | ||||
|  | ||||
|         this._userList = new UserList(); | ||||
|         this._userSelectionBox.add(this._userList.actor, | ||||
|         this._userSelectionBox.add(this._userList, | ||||
|                                    { expand: true, | ||||
|                                      x_fill: true, | ||||
|                                      y_fill: true }); | ||||
| @@ -435,7 +452,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.actor); | ||||
|         this.add_child(this._authPrompt); | ||||
|  | ||||
|         // translators: this message is shown below the user list on the | ||||
|         // login screen. It can be activated to reveal an entry for | ||||
| @@ -494,9 +511,9 @@ var LoginDialog = GObject.registerClass({ | ||||
|             (list, sessionId) => { | ||||
|                 this._greeter.call_select_session_sync (sessionId, null); | ||||
|             }); | ||||
|         this._sessionMenuButton.actor.opacity = 0; | ||||
|         this._sessionMenuButton.actor.show(); | ||||
|         this._authPrompt.addActorToDefaultButtonWell(this._sessionMenuButton.actor); | ||||
|         this._sessionMenuButton.opacity = 0; | ||||
|         this._sessionMenuButton.show(); | ||||
|         this._authPrompt.addActorToDefaultButtonWell(this._sessionMenuButton); | ||||
|  | ||||
|         this._disableUserList = undefined; | ||||
|         this._userListLoaded = false; | ||||
| @@ -579,8 +596,8 @@ var LoginDialog = GObject.registerClass({ | ||||
|  | ||||
|         let authPromptAllocation = null; | ||||
|         let authPromptWidth = 0; | ||||
|         if (this._authPrompt.actor.visible) { | ||||
|             authPromptAllocation = this._getCenterActorAllocation(dialogBox, this._authPrompt.actor); | ||||
|         if (this._authPrompt.visible) { | ||||
|             authPromptAllocation = this._getCenterActorAllocation(dialogBox, this._authPrompt); | ||||
|             authPromptWidth = authPromptAllocation.x2 - authPromptAllocation.x1; | ||||
|         } | ||||
|  | ||||
| @@ -690,7 +707,7 @@ var LoginDialog = GObject.registerClass({ | ||||
|         } | ||||
|  | ||||
|         if (authPromptAllocation) | ||||
|             this._authPrompt.actor.allocate(authPromptAllocation, flags); | ||||
|             this._authPrompt.allocate(authPromptAllocation, flags); | ||||
|  | ||||
|         if (userSelectionAllocation) | ||||
|             this._userSelectionBox.allocate(userSelectionAllocation, flags); | ||||
| @@ -794,7 +811,7 @@ var LoginDialog = GObject.registerClass({ | ||||
|     _onPrompted() { | ||||
|         if (this._shouldShowSessionMenuButton()) { | ||||
|             this._sessionMenuButton.updateSensitivity(true); | ||||
|             this._authPrompt.setActorInDefaultButtonWell(this._sessionMenuButton.actor); | ||||
|             this._authPrompt.setActorInDefaultButtonWell(this._sessionMenuButton); | ||||
|         } else { | ||||
|             this._sessionMenuButton.updateSensitivity(false); | ||||
|         } | ||||
| @@ -854,11 +871,11 @@ var LoginDialog = GObject.registerClass({ | ||||
|     } | ||||
|  | ||||
|     _showPrompt() { | ||||
|         if (this._authPrompt.actor.visible) | ||||
|         if (this._authPrompt.visible) | ||||
|             return; | ||||
|         this._authPrompt.actor.opacity = 0; | ||||
|         this._authPrompt.actor.show(); | ||||
|         this._authPrompt.actor.ease({ | ||||
|         this._authPrompt.opacity = 0; | ||||
|         this._authPrompt.show(); | ||||
|         this._authPrompt.ease({ | ||||
|             opacity: 255, | ||||
|             duration: _FADE_ANIMATION_TIME, | ||||
|             mode: Clutter.AnimationMode.EASE_OUT_QUAD | ||||
| @@ -921,7 +938,7 @@ var LoginDialog = GObject.registerClass({ | ||||
|             return; | ||||
|  | ||||
|         this._bindOpacity(); | ||||
|         this.actor.ease({ | ||||
|         this.ease({ | ||||
|             opacity: 255, | ||||
|             duration: _FADE_ANIMATION_TIME, | ||||
|             mode: Clutter.AnimationMode.EASE_OUT_QUAD, | ||||
| @@ -944,7 +961,7 @@ var LoginDialog = GObject.registerClass({ | ||||
|  | ||||
|     _startSession(serviceName) { | ||||
|         this._bindOpacity(); | ||||
|         this.actor.ease({ | ||||
|         this.ease({ | ||||
|             opacity: 0, | ||||
|             duration: _FADE_ANIMATION_TIME, | ||||
|             mode: Clutter.AnimationMode.EASE_OUT_QUAD, | ||||
| @@ -1045,12 +1062,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.actor.visible) | ||||
|                              this._authPrompt.visible) | ||||
|                              this._authPrompt.cancel(); | ||||
|  | ||||
|                          if (delay > _TIMED_LOGIN_IDLE_THRESHOLD || firstRun) { | ||||
|                              this._userList.scrollToItem(loginItem); | ||||
|                              loginItem.actor.grab_key_focus(); | ||||
|                              loginItem.grab_key_focus(); | ||||
|                          } | ||||
|                      }, | ||||
|  | ||||
| @@ -1111,7 +1128,7 @@ var LoginDialog = GObject.registerClass({ | ||||
|         this._sessionMenuButton.close(); | ||||
|         this._setUserListExpanded(true); | ||||
|         this._notListedButton.show(); | ||||
|         this._userList.actor.grab_key_focus(); | ||||
|         this._userList.grab_key_focus(); | ||||
|     } | ||||
|  | ||||
|     _beginVerificationForItem(item) { | ||||
| @@ -1219,7 +1236,7 @@ var LoginDialog = GObject.registerClass({ | ||||
|                                         _("Login Window"), | ||||
|                                         'dialog-password-symbolic', | ||||
|                                         { sortGroup: CtrlAltTab.SortGroup.MIDDLE }); | ||||
|         this._userList.actor.grab_key_focus(); | ||||
|         this._userList.grab_key_focus(); | ||||
|         this.show(); | ||||
|         this.opacity = 0; | ||||
|  | ||||
|   | ||||
| @@ -28,7 +28,7 @@ var HistoryManager = class { | ||||
|         this._entry = params.entry; | ||||
|  | ||||
|         if (this._entry) { | ||||
|             this._entry.connect('key-press-event',  | ||||
|             this._entry.connect('key-press-event', | ||||
|                                 this._onEntryKeyPress.bind(this)); | ||||
|         } | ||||
|     } | ||||
|   | ||||
| @@ -72,6 +72,16 @@ var IBusManager = class { | ||||
|     } | ||||
|  | ||||
|     _clear() { | ||||
|         if (this._cancellable) { | ||||
|             this._cancellable.cancel(); | ||||
|             this._cancellable = null; | ||||
|         } | ||||
|  | ||||
|         if (this._preloadEnginesId) { | ||||
|             GLib.source_remove(this._preloadEnginesId); | ||||
|             this._preloadEnginesId = 0; | ||||
|         } | ||||
|  | ||||
|         if (this._panelService) | ||||
|             this._panelService.destroy(); | ||||
|  | ||||
| @@ -86,28 +96,41 @@ var IBusManager = class { | ||||
|     } | ||||
|  | ||||
|     _onConnected() { | ||||
|         this._ibus.list_engines_async(-1, null, this._initEngines.bind(this)); | ||||
|         this._cancellable = new Gio.Cancellable(); | ||||
|         this._ibus.list_engines_async(-1, this._cancellable, | ||||
|             this._initEngines.bind(this)); | ||||
|         this._ibus.request_name_async(IBus.SERVICE_PANEL, | ||||
|                                       IBus.BusNameFlag.REPLACE_EXISTING, | ||||
|                                       -1, null, | ||||
|                                       this._initPanelService.bind(this)); | ||||
|             IBus.BusNameFlag.REPLACE_EXISTING, -1, this._cancellable, | ||||
|             this._initPanelService.bind(this)); | ||||
|     } | ||||
|  | ||||
|     _initEngines(ibus, result) { | ||||
|         let enginesList = this._ibus.list_engines_async_finish(result); | ||||
|         if (enginesList) { | ||||
|         try { | ||||
|             let enginesList = this._ibus.list_engines_async_finish(result); | ||||
|             for (let i = 0; i < enginesList.length; ++i) { | ||||
|                 let name = enginesList[i].get_name(); | ||||
|                 this._engines.set(name, enginesList[i]); | ||||
|             } | ||||
|             this._updateReadiness(); | ||||
|         } else { | ||||
|         } catch (e) { | ||||
|             if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) | ||||
|                 return; | ||||
|  | ||||
|             logError(e); | ||||
|             this._clear(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     _initPanelService(ibus, result) { | ||||
|         let success = this._ibus.request_name_async_finish(result); | ||||
|         let success = false; | ||||
|         try { | ||||
|             success = !!this._ibus.request_name_async_finish(result); | ||||
|         } catch (e) { | ||||
|             if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) | ||||
|                 return; | ||||
|             logError(e); | ||||
|         } | ||||
|  | ||||
|         if (success) { | ||||
|             this._panelService = new IBus.PanelService({ connection: this._ibus.get_connection(), | ||||
|                                                          object_path: IBus.PATH_PANEL }); | ||||
| @@ -134,7 +157,7 @@ var IBusManager = class { | ||||
|             } catch (e) { | ||||
|             } | ||||
|             // If an engine is already active we need to get its properties | ||||
|             this._ibus.get_global_engine_async(-1, null, (i, result) => { | ||||
|             this._ibus.get_global_engine_async(-1, this._cancellable, (_bus, result) => { | ||||
|                 let engine; | ||||
|                 try { | ||||
|                     engine = this._ibus.get_global_engine_async_finish(result); | ||||
| @@ -206,8 +229,18 @@ var IBusManager = class { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         this._ibus.set_global_engine_async(id, this._MAX_INPUT_SOURCE_ACTIVATION_TIME, | ||||
|                                            null, callback || null); | ||||
|         this._ibus.set_global_engine_async(id, | ||||
|             this._MAX_INPUT_SOURCE_ACTIVATION_TIME, | ||||
|             this._cancellable, (_bus, res) => { | ||||
|                 try { | ||||
|                     this._ibus.set_global_engine_async_finish(res); | ||||
|                 } catch (e) { | ||||
|                     if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) | ||||
|                         logError(e); | ||||
|                 } | ||||
|                 if (callback) | ||||
|                     callback(); | ||||
|             }); | ||||
|     } | ||||
|  | ||||
|     preloadEngines(ids) { | ||||
| @@ -227,7 +260,7 @@ var IBusManager = class { | ||||
|                     this._ibus.preload_engines_async( | ||||
|                         ids, | ||||
|                         -1, | ||||
|                         null, | ||||
|                         this._cancellable, | ||||
|                         null); | ||||
|                     this._preloadEnginesId = 0; | ||||
|                     return GLib.SOURCE_REMOVE; | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported InputMethod */ | ||||
| const { Clutter, GLib, GObject, IBus } = imports.gi; | ||||
| const { Clutter, GLib, Gio, GObject, IBus } = imports.gi; | ||||
|  | ||||
| const Keyboard = imports.ui.status.keyboard; | ||||
|  | ||||
| @@ -36,15 +36,7 @@ class InputMethod extends Clutter.InputMethod { | ||||
|     } | ||||
|  | ||||
|     _updateCapabilities() { | ||||
|         let caps = 0; | ||||
|  | ||||
|         if (this.can_show_preedit) | ||||
|             caps |= IBus.Capabilite.PREEDIT_TEXT; | ||||
|  | ||||
|         if (this._currentFocus) | ||||
|             caps |= IBus.Capabilite.FOCUS | IBus.Capabilite.SURROUNDING_TEXT; | ||||
|         else | ||||
|             caps |= IBus.Capabilite.PREEDIT_TEXT | IBus.Capabilite.AUXILIARY_TEXT | IBus.Capabilite.LOOKUP_TABLE | IBus.Capabilite.PROPERTY; | ||||
|         let caps = IBus.Capabilite.PREEDIT_TEXT | IBus.Capabilite.FOCUS | IBus.Capabilite.SURROUNDING_TEXT; | ||||
|  | ||||
|         if (this._context) | ||||
|             this._context.set_capabilities(caps); | ||||
| @@ -55,12 +47,22 @@ class InputMethod extends Clutter.InputMethod { | ||||
|     } | ||||
|  | ||||
|     _onConnected() { | ||||
|         this._ibus.create_input_context_async ('gnome-shell', -1, null, | ||||
|                                                this._setContext.bind(this)); | ||||
|         this._cancellable = new Gio.Cancellable(); | ||||
|         this._ibus.create_input_context_async ('gnome-shell', -1, | ||||
|             this._cancellable, this._setContext.bind(this)); | ||||
|     } | ||||
|  | ||||
|     _setContext(bus, res) { | ||||
|         this._context = this._ibus.create_input_context_async_finish(res); | ||||
|         try { | ||||
|             this._context = this._ibus.create_input_context_async_finish(res); | ||||
|         } catch (e) { | ||||
|             if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) { | ||||
|                 logError(e); | ||||
|                 this._clear(); | ||||
|             } | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         this._context.connect('commit-text', this._onCommitText.bind(this)); | ||||
|         this._context.connect('delete-surrounding-text', this._onDeleteSurroundingText.bind(this)); | ||||
|         this._context.connect('update-preedit-text', this._onUpdatePreeditText.bind(this)); | ||||
| @@ -72,6 +74,11 @@ class InputMethod extends Clutter.InputMethod { | ||||
|     } | ||||
|  | ||||
|     _clear() { | ||||
|         if (this._cancellable) { | ||||
|             this._cancellable.cancel(); | ||||
|             this._cancellable = null; | ||||
|         } | ||||
|  | ||||
|         this._context = null; | ||||
|         this._hints = 0; | ||||
|         this._purpose = 0; | ||||
| @@ -137,7 +144,6 @@ class InputMethod extends Clutter.InputMethod { | ||||
|         this._currentFocus = focus; | ||||
|         if (this._context) { | ||||
|             this._context.focus_in(); | ||||
|             this._updateCapabilities(); | ||||
|             this._emitRequestSurrounding(); | ||||
|         } | ||||
|  | ||||
| @@ -149,10 +155,8 @@ class InputMethod extends Clutter.InputMethod { | ||||
|  | ||||
|     vfunc_focus_out() { | ||||
|         this._currentFocus = null; | ||||
|         if (this._context) { | ||||
|         if (this._context) | ||||
|             this._context.focus_out(); | ||||
|             this._updateCapabilities(); | ||||
|         } | ||||
|  | ||||
|         if (this._preeditStr) { | ||||
|             // Unset any preedit text | ||||
| @@ -255,17 +259,19 @@ class InputMethod extends Clutter.InputMethod { | ||||
|         if (event.type() == Clutter.EventType.KEY_RELEASE) | ||||
|             state |= IBus.ModifierType.RELEASE_MASK; | ||||
|  | ||||
|         this._context.process_key_event_async(event.get_key_symbol(), | ||||
|                                               event.get_key_code() - 8, // Convert XKB keycodes to evcodes | ||||
|                                               state, -1, null, | ||||
|                                               (context, res) => { | ||||
|                                                   try { | ||||
|                                                       let retval = context.process_key_event_async_finish(res); | ||||
|                                                       this.notify_key_event(event, retval); | ||||
|                                                   } catch (e) { | ||||
|                                                       log(`Error processing key on IM: ${e.message}`); | ||||
|                                                   } | ||||
|                                               }); | ||||
|         this._context.process_key_event_async( | ||||
|             event.get_key_symbol(), | ||||
|             event.get_key_code() - 8, // Convert XKB keycodes to evcodes | ||||
|             state, -1, this._cancellable, | ||||
|             (context, res) => { | ||||
|                 try { | ||||
|                     let retval = context.process_key_event_async_finish(res); | ||||
|                     this.notify_key_event(event, retval); | ||||
|                 } catch (e) { | ||||
|                     if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) | ||||
|                         log(`Error processing key on IM: ${e.message}`); | ||||
|                 } | ||||
|             }); | ||||
|         return true; | ||||
|     } | ||||
| }); | ||||
|   | ||||
| @@ -127,7 +127,8 @@ var IntrospectService = class { | ||||
|         let apps = this._appSystem.get_running(); | ||||
|         let windowsList = {}; | ||||
|  | ||||
|         if (!this._isIntrospectEnabled()) { | ||||
|         if (!this._isIntrospectEnabled() && | ||||
|             !this._isSenderWhitelisted(invocation.get_sender())) { | ||||
|             invocation.return_error_literal(Gio.DBusError, | ||||
|                                             Gio.DBusError.ACCESS_DENIED, | ||||
|                                             'App introspection not allowed'); | ||||
|   | ||||
| @@ -172,7 +172,7 @@ function getPropertyNamesFromExpression(expr, commandHeader = '') { | ||||
|  | ||||
|         // Make sure propsUnique contains one key for every | ||||
|         // property so we end up with a unique list of properties | ||||
|         allProps.map(p => propsUnique[p] = null); | ||||
|         allProps.map(p => (propsUnique[p] = null)); | ||||
|     } | ||||
|     return Object.keys(propsUnique).sort(); | ||||
| } | ||||
|   | ||||
| @@ -84,9 +84,9 @@ function _findProviderForSid(sid) { | ||||
| } | ||||
|  | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Support for the old ModemManager interface (MM < 0.7) | ||||
| //------------------------------------------------------------------------------ | ||||
| // ----------------------------------------------------- // | ||||
| // Support for the old ModemManager interface (MM < 0.7) // | ||||
| // ----------------------------------------------------- // | ||||
|  | ||||
|  | ||||
| // The following are not the complete interfaces, just the methods we need | ||||
| @@ -182,9 +182,9 @@ var ModemCdma = class { | ||||
| Signals.addSignalMethods(ModemCdma.prototype); | ||||
|  | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Support for the new ModemManager1 interface (MM >= 0.7) | ||||
| //------------------------------------------------------------------------------ | ||||
| // ------------------------------------------------------- // | ||||
| // Support for the new ModemManager1 interface (MM >= 0.7) // | ||||
| // ------------------------------------------------------- // | ||||
|  | ||||
| const BroadbandModemInterface = loadInterfaceXML('org.freedesktop.ModemManager1.Modem'); | ||||
| const BroadbandModemProxy = Gio.DBusProxy.makeProxyWrapper(BroadbandModemInterface); | ||||
|   | ||||
| @@ -244,8 +244,9 @@ const SystemActions = GObject.registerClass({ | ||||
|  | ||||
|     _updateOrientationLockIcon() { | ||||
|         let locked = this._orientationSettings.get_boolean('orientation-lock'); | ||||
|         let iconName = locked ? 'rotation-locked-symbolic' | ||||
|                               : 'rotation-allowed-symbolic'; | ||||
|         let iconName = locked | ||||
|             ? 'rotation-locked-symbolic' | ||||
|             : 'rotation-allowed-symbolic'; | ||||
|         this._actions.get(LOCK_ORIENTATION_ACTION_ID).iconName = iconName; | ||||
|  | ||||
|         this.notify('orientation-lock-icon'); | ||||
| @@ -268,7 +269,7 @@ const SystemActions = GObject.registerClass({ | ||||
|  | ||||
|     getMatchingActions(terms) { | ||||
|         // terms is a list of strings | ||||
|         terms = terms.map((term) => term.toLowerCase()); | ||||
|         terms = terms.map(term => term.toLowerCase()); | ||||
|  | ||||
|         let results = []; | ||||
|  | ||||
|   | ||||
| @@ -14,7 +14,7 @@ var SCROLL_TIME = 100; | ||||
| // http://daringfireball.net/2010/07/improved_regex_for_matching_urls | ||||
| const _balancedParens = '\\([^\\s()<>]+\\)'; | ||||
| const _leadingJunk = '[\\s`(\\[{\'\\"<\u00AB\u201C\u2018]'; | ||||
| const _notTrailingJunk = '[^\\s`!()\\[\\]{};:\'\\".,<>?\u00AB\u00BB\u201C\u201D\u2018\u2019]'; | ||||
| const _notTrailingJunk = '[^\\s`!()\\[\\]{};:\'\\".,<>?\u00AB\u00BB\u200E\u200F\u201C\u201D\u2018\u2019\u202A\u202C]'; | ||||
|  | ||||
| const _urlRegexp = new RegExp( | ||||
|     `(^|${_leadingJunk})` + | ||||
|   | ||||
| @@ -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(); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -57,7 +57,7 @@ function waitAndDraw(milliseconds) { | ||||
|             cb(); | ||||
|     }); | ||||
|  | ||||
|     return callback => cb = callback; | ||||
|     return callback => (cb = callback); | ||||
| } | ||||
|  | ||||
| function waitSignal(object, signal) { | ||||
| @@ -69,7 +69,7 @@ function waitSignal(object, signal) { | ||||
|             cb(); | ||||
|     }); | ||||
|  | ||||
|     return callback => cb = callback; | ||||
|     return callback => (cb = callback); | ||||
| } | ||||
|  | ||||
| function extractBootTimestamp() { | ||||
| @@ -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'); | ||||
| @@ -137,9 +137,9 @@ function *run() { | ||||
|     Main.overview.hide(); | ||||
|     yield Scripting.waitLeisure(); | ||||
|  | ||||
|     //////////////////////////////////////// | ||||
|     // Tests of redraw speed | ||||
|     //////////////////////////////////////// | ||||
|     // --------------------- // | ||||
|     // Tests of redraw speed // | ||||
|     // --------------------- // | ||||
|  | ||||
|     global.frame_timestamps = true; | ||||
|     global.frame_finish_timestamp = true; | ||||
| @@ -186,8 +186,6 @@ function *run() { | ||||
|  | ||||
|     yield Scripting.sleep(1000); | ||||
|  | ||||
|     //////////////////////////////////////// | ||||
|  | ||||
|     let appSys = Shell.AppSystem.get_default(); | ||||
|     let app = appSys.lookup_app('org.gnome.gedit.desktop'); | ||||
|  | ||||
|   | ||||
| @@ -56,8 +56,8 @@ class AccessDialog extends ModalDialog.ModalDialog { | ||||
|  | ||||
|             let check = new CheckBox.CheckBox(); | ||||
|             check.getLabelActor().text = name; | ||||
|             check.actor.checked = selected == "true"; | ||||
|             content.insertBeforeBody(check.actor); | ||||
|             check.checked = selected == "true"; | ||||
|             content.insertBeforeBody(check); | ||||
|  | ||||
|             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.actor.checked ? 'true' : 'false'; | ||||
|                 let checked = check.checked ? 'true' : 'false'; | ||||
|                 results[id] = new GLib.Variant('s', checked); | ||||
|             } | ||||
|         } | ||||
| @@ -147,7 +147,7 @@ var AccessDialogDBus = class { | ||||
|                                       subtitle, body, options); | ||||
|         dialog.open(); | ||||
|  | ||||
|         dialog.connect('closed', () => this._accessDialog = null); | ||||
|         dialog.connect('closed', () => (this._accessDialog = null)); | ||||
|  | ||||
|         this._accessDialog = dialog; | ||||
|     } | ||||
|   | ||||
| @@ -28,14 +28,20 @@ var AppIconMode = { | ||||
| function _createWindowClone(window, size) { | ||||
|     let [width, height] = window.get_size(); | ||||
|     let scale = Math.min(1.0, size / width, size / height); | ||||
|     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 }); | ||||
|  | ||||
|     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, | ||||
|     }); | ||||
| } | ||||
|  | ||||
| function getWindows(workspace) { | ||||
| @@ -405,27 +411,26 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup { | ||||
|     } | ||||
| }); | ||||
|  | ||||
| class CyclerHighlight { | ||||
|     constructor() { | ||||
| var CyclerHighlight = GObject.registerClass( | ||||
| class CyclerHighlight extends St.Widget { | ||||
|     _init() { | ||||
|         super._init({ layout_manager: new Clutter.BinLayout() }); | ||||
|         this._window = null; | ||||
|  | ||||
|         this.actor = new St.Widget({ layout_manager: new Clutter.BinLayout() }); | ||||
|  | ||||
|         this._clone = new Clutter.Clone(); | ||||
|         this.actor.add_actor(this._clone); | ||||
|         this._clone = new Clutter.Actor(); | ||||
|         this.add_actor(this._clone); | ||||
|  | ||||
|         this._highlight = new St.Widget({ style_class: 'cycler-highlight' }); | ||||
|         this.actor.add_actor(this._highlight); | ||||
|         this.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.actor.add_constraint(constraint); | ||||
|         this.add_constraint(constraint); | ||||
|  | ||||
|         this.actor.connect('notify::allocation', | ||||
|                            this._onAllocationChanged.bind(this)); | ||||
|         this.actor.connect('destroy', this._onDestroy.bind(this)); | ||||
|         this.connect('notify::allocation', this._onAllocationChanged.bind(this)); | ||||
|         this.connect('destroy', this._onDestroy.bind(this)); | ||||
|     } | ||||
|  | ||||
|     set window(w) { | ||||
| @@ -434,16 +439,16 @@ class CyclerHighlight { | ||||
|  | ||||
|         this._window = w; | ||||
|  | ||||
|         if (this._clone.source) | ||||
|             this._clone.source.sync_visibility(); | ||||
|         if (this._clone.content) | ||||
|             this._clone.content.window_actor.sync_visibility(); | ||||
|  | ||||
|         let windowActor = this._window ? this._window.get_compositor_private() | ||||
|                                        : null; | ||||
|         let windowActor = this._window | ||||
|             ? this._window.get_compositor_private() : null; | ||||
|  | ||||
|         if (windowActor) | ||||
|             windowActor.hide(); | ||||
|  | ||||
|         this._clone.source = windowActor; | ||||
|         this._clone.content = windowActor.content; | ||||
|     } | ||||
|  | ||||
|     _onAllocationChanged() { | ||||
| @@ -451,7 +456,7 @@ class CyclerHighlight { | ||||
|             this._highlight.set_size(0, 0); | ||||
|             this._highlight.hide(); | ||||
|         } else { | ||||
|             let [x, y] = this.actor.allocation.get_origin(); | ||||
|             let [x, y] = this.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); | ||||
| @@ -462,7 +467,7 @@ class CyclerHighlight { | ||||
|     _onDestroy() { | ||||
|         this.window = null; | ||||
|     } | ||||
| } | ||||
| }); | ||||
|  | ||||
| // We don't show an actual popup, so just provide what SwitcherPopup | ||||
| // expects instead of inheriting from SwitcherList | ||||
| @@ -489,7 +494,7 @@ var CyclerPopup = GObject.registerClass({ | ||||
|             return; | ||||
|  | ||||
|         this._highlight = new CyclerHighlight(); | ||||
|         global.window_group.add_actor(this._highlight.actor); | ||||
|         global.window_group.add_actor(this._highlight); | ||||
|  | ||||
|         this._switcherList = new CyclerList(); | ||||
|         this._switcherList.connect('item-highlighted', (list, index) => { | ||||
| @@ -499,7 +504,7 @@ var CyclerPopup = GObject.registerClass({ | ||||
|  | ||||
|     _highlightItem(index, _justOutline) { | ||||
|         this._highlight.window = this._items[index]; | ||||
|         global.window_group.set_child_above_sibling(this._highlight.actor, null); | ||||
|         global.window_group.set_child_above_sibling(this._highlight, null); | ||||
|     } | ||||
|  | ||||
|     _finish() { | ||||
| @@ -529,7 +534,7 @@ var CyclerPopup = GObject.registerClass({ | ||||
|     } | ||||
|  | ||||
|     _onDestroy() { | ||||
|         this._highlight.actor.destroy(); | ||||
|         this._highlight.destroy(); | ||||
|  | ||||
|         super._onDestroy(); | ||||
|     } | ||||
| @@ -877,9 +882,9 @@ class ThumbnailList extends SwitcherPopup.SwitcherList { | ||||
|     _init(windows) { | ||||
|         super._init(false); | ||||
|  | ||||
|         this._labels = new Array(); | ||||
|         this._thumbnailBins = new Array(); | ||||
|         this._clones = new Array(); | ||||
|         this._labels = []; | ||||
|         this._thumbnailBins = []; | ||||
|         this._clones = []; | ||||
|         this._windows = windows; | ||||
|  | ||||
|         for (let i = 0; i < windows.length; i++) { | ||||
| @@ -940,7 +945,7 @@ class ThumbnailList extends SwitcherPopup.SwitcherList { | ||||
|         } | ||||
|  | ||||
|         // Make sure we only do this once | ||||
|         this._thumbnailBins = new Array(); | ||||
|         this._thumbnailBins = []; | ||||
|     } | ||||
|  | ||||
|     _removeThumbnail(source, clone) { | ||||
| @@ -1014,9 +1019,9 @@ class WindowIcon extends St.BoxLayout { | ||||
|     } | ||||
|  | ||||
|     _createAppIcon(app, size) { | ||||
|         let appIcon = app ? app.create_icon_texture(size) | ||||
|                           : new St.Icon({ icon_name: 'icon-missing', | ||||
|                                           icon_size: size }); | ||||
|         let appIcon = app | ||||
|             ? app.create_icon_texture(size) | ||||
|             : new St.Icon({ icon_name: 'icon-missing', icon_size: size }); | ||||
|         appIcon.x_expand = appIcon.y_expand = true; | ||||
|         appIcon.x_align = appIcon.y_align = Clutter.ActorAlign.END; | ||||
|  | ||||
| @@ -1043,7 +1048,7 @@ class WindowList extends SwitcherPopup.SwitcherList { | ||||
|             this.addItem(icon, icon.label); | ||||
|             this.icons.push(icon); | ||||
|  | ||||
|             icon._unmanagedSignalId = icon.window.connect('unmanaged', (window) => { | ||||
|             icon._unmanagedSignalId = icon.window.connect('unmanaged', window => { | ||||
|                 this._removeWindow(window); | ||||
|             }); | ||||
|         } | ||||
|   | ||||
| @@ -1,19 +1,18 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported Animation, AnimatedIcon, Spinner */ | ||||
|  | ||||
| const { Clutter, GLib, Gio, St } = imports.gi; | ||||
| const { Clutter, GLib, GObject, Gio, St } = imports.gi; | ||||
|  | ||||
| var ANIMATED_ICON_UPDATE_TIMEOUT = 16; | ||||
| var SPINNER_ANIMATION_TIME = 300; | ||||
| var SPINNER_ANIMATION_DELAY = 1000; | ||||
|  | ||||
| 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', | ||||
| 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', | ||||
|             this._loadFile.bind(this, file, width, height)); | ||||
|  | ||||
|         let themeContext = St.ThemeContext.get_for_stage(global.stage); | ||||
| @@ -52,14 +51,14 @@ var Animation = class { | ||||
|     } | ||||
|  | ||||
|     _loadFile(file, width, height) { | ||||
|         let [validResourceScale, resourceScale] = this.actor.get_resource_scale(); | ||||
|         let [validResourceScale, resourceScale] = this.get_resource_scale(); | ||||
|         let wasPlaying = this._isPlaying; | ||||
|  | ||||
|         if (this._isPlaying) | ||||
|             this.stop(); | ||||
|  | ||||
|         this._isLoaded = false; | ||||
|         this.actor.destroy_all_children(); | ||||
|         this.destroy_all_children(); | ||||
|  | ||||
|         if (!validResourceScale) { | ||||
|             if (wasPlaying) | ||||
| @@ -72,7 +71,7 @@ var Animation = class { | ||||
|         this._animations = textureCache.load_sliced_image(file, width, height, | ||||
|                                                           scaleFactor, resourceScale, | ||||
|                                                           this._animationsLoaded.bind(this)); | ||||
|         this.actor.set_child(this._animations); | ||||
|         this.set_child(this._animations); | ||||
|  | ||||
|         if (wasPlaying) | ||||
|             this.play(); | ||||
| @@ -99,7 +98,7 @@ var Animation = class { | ||||
|         if (!this._isLoaded) | ||||
|             return; | ||||
|  | ||||
|         let [width, height] = this.actor.get_size(); | ||||
|         let [width, height] = this.get_size(); | ||||
|  | ||||
|         for (let i = 0; i < this._animations.get_n_children(); ++i) | ||||
|             this._animations.get_child_at_index(i).set_size(width, height); | ||||
| @@ -122,20 +121,22 @@ var Animation = class { | ||||
|             themeContext.disconnect(this._scaleChangedId); | ||||
|         this._scaleChangedId = 0; | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|  | ||||
| var AnimatedIcon = class extends Animation { | ||||
|     constructor(file, size) { | ||||
|         super(file, size, size, ANIMATED_ICON_UPDATE_TIMEOUT); | ||||
| var AnimatedIcon = GObject.registerClass( | ||||
| class AnimatedIcon extends Animation { | ||||
|     _init(file, size) { | ||||
|         super._init(file, size, size, ANIMATED_ICON_UPDATE_TIMEOUT); | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|  | ||||
| var Spinner = class extends AnimatedIcon { | ||||
|     constructor(size, animate = false) { | ||||
| var Spinner = GObject.registerClass( | ||||
| class Spinner extends AnimatedIcon { | ||||
|     _init(size, animate = false) { | ||||
|         let file = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/process-working.svg'); | ||||
|         super(file, size); | ||||
|         super._init(file, size); | ||||
|  | ||||
|         this.actor.opacity = 0; | ||||
|         this.opacity = 0; | ||||
|         this._animate = animate; | ||||
|     } | ||||
|  | ||||
| @@ -145,35 +146,35 @@ var Spinner = class extends AnimatedIcon { | ||||
|     } | ||||
|  | ||||
|     play() { | ||||
|         this.actor.remove_all_transitions(); | ||||
|         this.remove_all_transitions(); | ||||
|  | ||||
|         if (this._animate) { | ||||
|             super.play(); | ||||
|             this.actor.ease({ | ||||
|             this.ease({ | ||||
|                 opacity: 255, | ||||
|                 delay: SPINNER_ANIMATION_DELAY, | ||||
|                 duration: SPINNER_ANIMATION_TIME, | ||||
|                 mode: Clutter.AnimationMode.LINEAR | ||||
|             }); | ||||
|         } else { | ||||
|             this.actor.opacity = 255; | ||||
|             this.opacity = 255; | ||||
|             super.play(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     stop() { | ||||
|         this.actor.remove_all_transitions(); | ||||
|         this.remove_all_transitions(); | ||||
|  | ||||
|         if (this._animate) { | ||||
|             this.actor.ease({ | ||||
|             this.ease({ | ||||
|                 opacity: 0, | ||||
|                 time: SPINNER_ANIMATION_TIME, | ||||
|                 transition: 'linear', | ||||
|                 duration: SPINNER_ANIMATION_TIME, | ||||
|                 mode: Clutter.AnimationMode.LINEAR, | ||||
|                 onComplete: () => super.stop() | ||||
|             }); | ||||
|         } else { | ||||
|             this.actor.opacity = 0; | ||||
|             this.opacity = 0; | ||||
|             super.stop(); | ||||
|         } | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -161,7 +161,7 @@ var AudioDeviceSelectionDBus = class AudioDeviceSelectionDBus { | ||||
|  | ||||
|         let [deviceNames] = params; | ||||
|         let devices = 0; | ||||
|         deviceNames.forEach(n => devices |= AudioDevice[n.toUpperCase()]); | ||||
|         deviceNames.forEach(n => (devices |= AudioDevice[n.toUpperCase()])); | ||||
|  | ||||
|         let dialog; | ||||
|         try { | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // -*- 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 | ||||
| @@ -93,7 +94,7 @@ | ||||
| //     MetaBackgroundImage         MetaBackgroundImage | ||||
| //     MetaBackgroundImage         MetaBackgroundImage | ||||
|  | ||||
| const { Clutter, GDesktopEnums, Gio, GLib, GnomeDesktop, Meta } = imports.gi; | ||||
| const { Clutter, GDesktopEnums, Gio, GLib, GObject, GnomeDesktop, Meta } = imports.gi; | ||||
| const Signals = imports.signals; | ||||
|  | ||||
| const LoginManager = imports.misc.loginManager; | ||||
| @@ -220,16 +221,17 @@ function getBackgroundCache() { | ||||
|     return _backgroundCache; | ||||
| } | ||||
|  | ||||
| var Background = class Background { | ||||
|     constructor(params) { | ||||
| var Background = GObject.registerClass({ | ||||
|     Signals: { 'loaded': {}, 'bg-changed': {} } | ||||
| }, class Background extends Meta.Background { | ||||
|     _init(params) { | ||||
|         params = Params.parse(params, { monitorIndex: 0, | ||||
|                                         layoutManager: Main.layoutManager, | ||||
|                                         settings: null, | ||||
|                                         file: null, | ||||
|                                         style: null }); | ||||
|  | ||||
|         this.background = new Meta.Background({ meta_display: global.display }); | ||||
|         this.background._delegate = this; | ||||
|         super._init({ meta_display: global.display }); | ||||
|  | ||||
|         this._settings = params.settings; | ||||
|         this._file = params.file; | ||||
| @@ -262,8 +264,6 @@ var Background = class Background { | ||||
|     } | ||||
|  | ||||
|     destroy() { | ||||
|         this.background = null; | ||||
|  | ||||
|         this._cancellable.cancel(); | ||||
|         this._removeAnimationTimeout(); | ||||
|  | ||||
| @@ -300,9 +300,11 @@ var Background = class Background { | ||||
|  | ||||
|         this._changedIdleId = GLib.idle_add(GLib.PRIORITY_DEFAULT, () => { | ||||
|             this._changedIdleId = 0; | ||||
|             this.emit('changed'); | ||||
|             this.emit('bg-changed'); | ||||
|             return GLib.SOURCE_REMOVE; | ||||
|         }); | ||||
|         GLib.Source.set_name_by_id(this._changedIdleId, | ||||
|             '[gnome-shell] Background._emitChangedSignal'); | ||||
|     } | ||||
|  | ||||
|     updateResolution() { | ||||
| @@ -328,7 +330,7 @@ var Background = class Background { | ||||
|             this.emit('loaded'); | ||||
|             return GLib.SOURCE_REMOVE; | ||||
|         }); | ||||
|         GLib.Source.set_name_by_id(id, '[gnome-shell] this.emit'); | ||||
|         GLib.Source.set_name_by_id(id, '[gnome-shell] Background._setLoaded Idle'); | ||||
|     } | ||||
|  | ||||
|     _loadPattern() { | ||||
| @@ -342,9 +344,9 @@ var Background = class Background { | ||||
|         let shadingType = this._settings.get_enum(COLOR_SHADING_TYPE_KEY); | ||||
|  | ||||
|         if (shadingType == GDesktopEnums.BackgroundShading.SOLID) | ||||
|             this.background.set_color(color); | ||||
|             this.set_color(color); | ||||
|         else | ||||
|             this.background.set_gradient(shadingType, color, secondColor); | ||||
|             this.set_gradient(shadingType, color, secondColor); | ||||
|     } | ||||
|  | ||||
|     _watchFile(file) { | ||||
| @@ -380,13 +382,13 @@ var Background = class Background { | ||||
|         let finish = () => { | ||||
|             this._setLoaded(); | ||||
|             if (files.length > 1) { | ||||
|                 this.background.set_blend(files[0], files[1], | ||||
|                                           this._animation.transitionProgress, | ||||
|                                           this._style); | ||||
|                 this.set_blend(files[0], files[1], | ||||
|                                this._animation.transitionProgress, | ||||
|                                this._style); | ||||
|             } else if (files.length > 0) { | ||||
|                 this.background.set_file(files[0], this._style); | ||||
|                 this.set_file(files[0], this._style); | ||||
|             } else { | ||||
|                 this.background.set_file(null, this._style); | ||||
|                 this.set_file(null, this._style); | ||||
|             } | ||||
|             this._queueUpdateAnimation(); | ||||
|         }; | ||||
| @@ -459,7 +461,7 @@ var Background = class Background { | ||||
|     } | ||||
|  | ||||
|     _loadImage(file) { | ||||
|         this.background.set_file(file, this._style); | ||||
|         this.set_file(file, this._style); | ||||
|         this._watchFile(file); | ||||
|  | ||||
|         let cache = Meta.BackgroundImageCache.get_default(); | ||||
| @@ -493,13 +495,14 @@ var Background = class Background { | ||||
|  | ||||
|         this._loadFile(this._file); | ||||
|     } | ||||
| }; | ||||
| Signals.addSignalMethods(Background.prototype); | ||||
| }); | ||||
|  | ||||
| let _systemBackground; | ||||
|  | ||||
| var SystemBackground = class SystemBackground { | ||||
|     constructor() { | ||||
| var SystemBackground = GObject.registerClass({ | ||||
|     Signals: { 'loaded': {} } | ||||
| }, class SystemBackground extends Meta.BackgroundActor { | ||||
|     _init() { | ||||
|         let file = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/noise-texture.png'); | ||||
|  | ||||
|         if (_systemBackground == null) { | ||||
| @@ -508,9 +511,11 @@ var SystemBackground = class SystemBackground { | ||||
|             _systemBackground.set_file(file, GDesktopEnums.BackgroundStyle.WALLPAPER); | ||||
|         } | ||||
|  | ||||
|         this.actor = new Meta.BackgroundActor({ meta_display: global.display, | ||||
|                                                 monitor: 0, | ||||
|                                                 background: _systemBackground }); | ||||
|         super._init({ | ||||
|             meta_display: global.display, | ||||
|             monitor: 0, | ||||
|             background: _systemBackground | ||||
|         }); | ||||
|  | ||||
|         let cache = Meta.BackgroundImageCache.get_default(); | ||||
|         let image = cache.load(file); | ||||
| @@ -529,8 +534,7 @@ var SystemBackground = class SystemBackground { | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
| }; | ||||
| Signals.addSignalMethods(SystemBackground.prototype); | ||||
| }); | ||||
|  | ||||
| var BackgroundSource = class BackgroundSource { | ||||
|     constructor(layoutManager, settingsSchema) { | ||||
| @@ -566,7 +570,7 @@ var BackgroundSource = class BackgroundSource { | ||||
|  | ||||
|         // We don't watch changes to settings here, | ||||
|         // instead we rely on Background to watch those | ||||
|         // and emit 'changed' at the right time | ||||
|         // and emit 'bg-changed' at the right time | ||||
|  | ||||
|         if (this._overrideImage != null) { | ||||
|             file = Gio.File.new_for_path(this._overrideImage); | ||||
| @@ -595,7 +599,7 @@ var BackgroundSource = class BackgroundSource { | ||||
|                 style: style | ||||
|             }); | ||||
|  | ||||
|             background._changedId = background.connect('changed', () => { | ||||
|             background._changedId = background.connect('bg-changed', () => { | ||||
|                 background.disconnect(background._changedId); | ||||
|                 background.destroy(); | ||||
|                 delete this._backgrounds[monitorIndex]; | ||||
| @@ -732,7 +736,7 @@ var BackgroundManager = class BackgroundManager { | ||||
|  | ||||
|         this._newBackgroundActor = newBackgroundActor; | ||||
|  | ||||
|         let background = newBackgroundActor.background._delegate; | ||||
|         let background = newBackgroundActor.background; | ||||
|  | ||||
|         if (background.isLoaded) { | ||||
|             this._swapBackgroundActor(); | ||||
| @@ -752,7 +756,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, | ||||
| @@ -766,7 +770,7 @@ var BackgroundManager = class BackgroundManager { | ||||
|             backgroundActor.lower_bottom(); | ||||
|         } | ||||
|  | ||||
|         let changeSignalId = background.connect('changed', () => { | ||||
|         let changeSignalId = background.connect('bg-changed', () => { | ||||
|             background.disconnect(changeSignalId); | ||||
|             changeSignalId = null; | ||||
|             this._updateBackgroundActor(); | ||||
|   | ||||
| @@ -46,12 +46,18 @@ var BoxPointer = GObject.registerClass({ | ||||
|         this.add_actor(this._border); | ||||
|         this.bin.raise(this._border); | ||||
|         this._sourceAlignment = 0.5; | ||||
|         this._capturedEventId = 0; | ||||
|         this._muteInput(); | ||||
|         this._muteInput = true; | ||||
|  | ||||
|         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); | ||||
| @@ -63,19 +69,6 @@ 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'); | ||||
| @@ -112,7 +105,7 @@ var BoxPointer = GObject.registerClass({ | ||||
|             duration: animationTime, | ||||
|             mode: Clutter.AnimationMode.LINEAR, | ||||
|             onComplete: () => { | ||||
|                 this._unmuteInput(); | ||||
|                 this._muteInput = false; | ||||
|                 if (onComplete) | ||||
|                     onComplete(); | ||||
|             } | ||||
| @@ -147,7 +140,7 @@ var BoxPointer = GObject.registerClass({ | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         this._muteInput(); | ||||
|         this._muteInput = true; | ||||
|  | ||||
|         this.remove_all_transitions(); | ||||
|         this.ease({ | ||||
| @@ -172,8 +165,8 @@ var BoxPointer = GObject.registerClass({ | ||||
|         let borderWidth = themeNode.get_length('-arrow-border-width'); | ||||
|         minSize += borderWidth * 2; | ||||
|         natSize += borderWidth * 2; | ||||
|         if ((!isWidth && (this._arrowSide == St.Side.TOP || this._arrowSide == St.Side.BOTTOM)) | ||||
|             || (isWidth && (this._arrowSide == St.Side.LEFT || this._arrowSide == St.Side.RIGHT))) { | ||||
|         if ((!isWidth && (this._arrowSide == St.Side.TOP || this._arrowSide == St.Side.BOTTOM)) || | ||||
|             (isWidth && (this._arrowSide == St.Side.LEFT || this._arrowSide == St.Side.RIGHT))) { | ||||
|             let rise = themeNode.get_length('-arrow-rise'); | ||||
|             minSize += rise; | ||||
|             natSize += rise; | ||||
|   | ||||
| @@ -313,8 +313,10 @@ var DBusEventSource = class DBusEventSource { | ||||
| }; | ||||
| Signals.addSignalMethods(DBusEventSource.prototype); | ||||
|  | ||||
| var Calendar = class Calendar { | ||||
|     constructor() { | ||||
| var Calendar = GObject.registerClass({ | ||||
|     Signals: { 'selected-date-changed': { param_types: [GLib.DateTime.$gtype] } } | ||||
| }, class Calendar extends St.Widget { | ||||
|     _init() { | ||||
|         this._weekStart = Shell.util_get_week_start(); | ||||
|         this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.calendar' }); | ||||
|  | ||||
| @@ -344,12 +346,11 @@ var Calendar = class Calendar { | ||||
|  | ||||
|         this._shouldDateGrabFocus = false; | ||||
|  | ||||
|         this.actor = new St.Widget({ style_class: 'calendar', | ||||
|                                      layout_manager: new Clutter.TableLayout(), | ||||
|                                      reactive: true }); | ||||
|  | ||||
|         this.actor.connect('scroll-event', | ||||
|                            this._onScroll.bind(this)); | ||||
|         super._init({ | ||||
|             style_class: 'calendar', | ||||
|             layout_manager: new Clutter.TableLayout(), | ||||
|             reactive: true | ||||
|         }); | ||||
|  | ||||
|         this._buildHeader (); | ||||
|     } | ||||
| @@ -373,7 +374,10 @@ var Calendar = class Calendar { | ||||
|  | ||||
|         this._selectedDate = date; | ||||
|         this._update(); | ||||
|         this.emit('selected-date-changed', new Date(this._selectedDate)); | ||||
|  | ||||
|         let datetime = GLib.DateTime.new_from_unix_local( | ||||
|             this._selectedDate.getTime() / 1000); | ||||
|         this.emit('selected-date-changed', datetime); | ||||
|     } | ||||
|  | ||||
|     updateTimeZone() { | ||||
| @@ -384,9 +388,9 @@ var Calendar = class Calendar { | ||||
|     } | ||||
|  | ||||
|     _buildHeader() { | ||||
|         let layout = this.actor.layout_manager; | ||||
|         let layout = this.layout_manager; | ||||
|         let offsetCols = this._useWeekdate ? 1 : 0; | ||||
|         this.actor.destroy_all_children(); | ||||
|         this.destroy_all_children(); | ||||
|  | ||||
|         // Top line of the calendar '<| September 2009 |>' | ||||
|         this._topBox = new St.BoxLayout(); | ||||
| @@ -428,7 +432,7 @@ var Calendar = class Calendar { | ||||
|                                        can_focus: true }); | ||||
|             label.accessible_name = iter.toLocaleFormat('%A'); | ||||
|             let col; | ||||
|             if (this.actor.get_text_direction() == Clutter.TextDirection.RTL) | ||||
|             if (this.get_text_direction() == Clutter.TextDirection.RTL) | ||||
|                 col = 6 - (7 + iter.getDay() - this._weekStart) % 7; | ||||
|             else | ||||
|                 col = offsetCols + (7 + iter.getDay() - this._weekStart) % 7; | ||||
| @@ -437,11 +441,11 @@ var Calendar = class Calendar { | ||||
|         } | ||||
|  | ||||
|         // All the children after this are days, and get removed when we update the calendar | ||||
|         this._firstDayIndex = this.actor.get_n_children(); | ||||
|         this._firstDayIndex = this.get_n_children(); | ||||
|     } | ||||
|  | ||||
|     _onScroll(actor, event) { | ||||
|         switch (event.get_scroll_direction()) { | ||||
|     vfunc_scroll_event(scrollEvent) { | ||||
|         switch (scrollEvent.direction) { | ||||
|         case Clutter.ScrollDirection.UP: | ||||
|         case Clutter.ScrollDirection.LEFT: | ||||
|             this._onPrevMonthButtonClicked(); | ||||
| @@ -511,7 +515,7 @@ var Calendar = class Calendar { | ||||
|         let now = new Date(); | ||||
|  | ||||
|         // Remove everything but the topBox and the weekday labels | ||||
|         let children = this.actor.get_children(); | ||||
|         let children = this.get_children(); | ||||
|         for (let i = this._firstDayIndex; i < children.length; i++) | ||||
|             children[i].destroy(); | ||||
|  | ||||
| @@ -548,7 +552,7 @@ var Calendar = class Calendar { | ||||
|  | ||||
|         beginDate.setTime(beginDate.getTime() - (weekPadding + daysToWeekStart) * MSECS_IN_DAY); | ||||
|  | ||||
|         let layout = this.actor.layout_manager; | ||||
|         let layout = this.layout_manager; | ||||
|         let iter = new Date(beginDate); | ||||
|         let row = 2; | ||||
|         // nRows here means 6 weeks + one header + one navbar | ||||
| @@ -581,8 +585,9 @@ var Calendar = class Calendar { | ||||
|             if (row == 2) | ||||
|                 styleClass = `calendar-day-top ${styleClass}`; | ||||
|  | ||||
|             let leftMost = rtl ? iter.getDay() == (this._weekStart + 6) % 7 | ||||
|                                : iter.getDay() == this._weekStart; | ||||
|             let leftMost = rtl | ||||
|                 ? iter.getDay() == (this._weekStart + 6) % 7 | ||||
|                 : iter.getDay() == this._weekStart; | ||||
|             if (leftMost) | ||||
|                 styleClass = `calendar-day-left ${styleClass}`; | ||||
|  | ||||
| @@ -647,12 +652,12 @@ var Calendar = class Calendar { | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| }; | ||||
| Signals.addSignalMethods(Calendar.prototype); | ||||
| }); | ||||
|  | ||||
| var EventMessage = class EventMessage extends MessageList.Message { | ||||
|     constructor(event, date) { | ||||
|         super('', event.summary); | ||||
| var EventMessage = GObject.registerClass( | ||||
| class EventMessage extends MessageList.Message { | ||||
|     _init(event, date) { | ||||
|         super._init('', event.summary); | ||||
|  | ||||
|         this._event = event; | ||||
|         this._date = date; | ||||
| @@ -661,11 +666,12 @@ var EventMessage = class EventMessage extends MessageList.Message { | ||||
|  | ||||
|         this._icon = new St.Icon({ icon_name: 'x-office-calendar-symbolic' }); | ||||
|         this.setIcon(this._icon); | ||||
|     } | ||||
|  | ||||
|         this.actor.connect('style-changed', () => { | ||||
|             let iconVisible = this.actor.get_parent().has_style_pseudo_class('first-child'); | ||||
|             this._icon.opacity = (iconVisible ? 255 : 0); | ||||
|         }); | ||||
|     vfunc_style_changed() { | ||||
|         let iconVisible = this.get_parent().has_style_pseudo_class('first-child'); | ||||
|         this._icon.opacity = (iconVisible ? 255 : 0); | ||||
|         super.vfunc_style_changed(); | ||||
|     } | ||||
|  | ||||
|     _formatEventTime() { | ||||
| @@ -680,8 +686,9 @@ var EventMessage = class EventMessage extends MessageList.Message { | ||||
|              */ | ||||
|             title = C_("event list time", "All Day"); | ||||
|         } else { | ||||
|             let date = this._event.date >= periodBegin ? this._event.date | ||||
|                                                        : this._event.end; | ||||
|             let date = this._event.date >= periodBegin | ||||
|                 ? this._event.date | ||||
|                 : this._event.end; | ||||
|             title = Util.formatTime(date, { timeOnly: true }); | ||||
|         } | ||||
|  | ||||
| @@ -700,12 +707,12 @@ var EventMessage = class EventMessage extends MessageList.Message { | ||||
|         } | ||||
|         return title; | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|  | ||||
| var NotificationMessage = | ||||
| var NotificationMessage = GObject.registerClass( | ||||
| class NotificationMessage extends MessageList.Message { | ||||
|     constructor(notification) { | ||||
|         super(notification.title, notification.bannerBodyText); | ||||
|     _init(notification) { | ||||
|         super._init(notification.title, notification.bannerBodyText); | ||||
|         this.setUseBodyMarkup(notification.bannerBodyMarkup); | ||||
|  | ||||
|         this.notification = notification; | ||||
| @@ -742,7 +749,7 @@ class NotificationMessage extends MessageList.Message { | ||||
|         this.setUseBodyMarkup(n.bannerBodyMarkup); | ||||
|     } | ||||
|  | ||||
|     _onClicked() { | ||||
|     vfunc_clicked() { | ||||
|         this.notification.activate(); | ||||
|     } | ||||
|  | ||||
| @@ -764,11 +771,12 @@ class NotificationMessage extends MessageList.Message { | ||||
|     canClose() { | ||||
|         return true; | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|  | ||||
| var EventsSection = class EventsSection extends MessageList.MessageListSection { | ||||
|     constructor() { | ||||
|         super(); | ||||
| var EventsSection = GObject.registerClass( | ||||
| class EventsSection extends MessageList.MessageListSection { | ||||
|     _init() { | ||||
|         super._init(); | ||||
|  | ||||
|         this._desktopSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.interface' }); | ||||
|         this._desktopSettings.connect('changed', this._reloadEvents.bind(this)); | ||||
| @@ -780,7 +788,7 @@ var EventsSection = class EventsSection extends MessageList.MessageListSection { | ||||
|                                       label: '', | ||||
|                                       x_align: St.Align.START, | ||||
|                                       can_focus: true }); | ||||
|         this.actor.insert_child_below(this._title, null); | ||||
|         this.insert_child_below(this._title, null); | ||||
|  | ||||
|         this._title.connect('clicked', this._onTitleClicked.bind(this)); | ||||
|         this._title.connect('key-focus-in', this._onKeyFocusIn.bind(this)); | ||||
| @@ -899,12 +907,29 @@ var EventsSection = class EventsSection extends MessageList.MessageListSection { | ||||
|  | ||||
|         super._sync(); | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|  | ||||
| var NotificationSection = | ||||
| 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( | ||||
| class NotificationSection extends MessageList.MessageListSection { | ||||
|     constructor() { | ||||
|         super(); | ||||
|     _init() { | ||||
|         super._init(); | ||||
|  | ||||
|         this._sources = new Map(); | ||||
|         this._nUrgent = 0; | ||||
| @@ -913,8 +938,6 @@ 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() { | ||||
| @@ -922,17 +945,6 @@ 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, | ||||
| @@ -950,13 +962,13 @@ class NotificationSection extends MessageList.MessageListSection { | ||||
|  | ||||
|     _onNotificationAdded(source, notification) { | ||||
|         let message = new NotificationMessage(notification); | ||||
|         message.setSecondaryActor(this._createTimeLabel(notification.datetime)); | ||||
|         message.setSecondaryActor(new TimeLabel(notification.datetime)); | ||||
|  | ||||
|         let isUrgent = notification.urgency == MessageTray.Urgency.CRITICAL; | ||||
|  | ||||
|         let updatedId = notification.connect('updated', () => { | ||||
|             message.setSecondaryActor(this._createTimeLabel(notification.datetime)); | ||||
|             this.moveMessage(message, isUrgent ? 0 : this._nUrgent, this.actor.mapped); | ||||
|             message.setSecondaryActor(new TimeLabel(notification.datetime)); | ||||
|             this.moveMessage(message, isUrgent ? 0 : this._nUrgent, this.mapped); | ||||
|         }); | ||||
|         let destroyId = notification.connect('destroy', () => { | ||||
|             notification.disconnect(destroyId); | ||||
| @@ -976,7 +988,7 @@ class NotificationSection extends MessageList.MessageListSection { | ||||
|         } | ||||
|  | ||||
|         let index = isUrgent ? 0 : this._nUrgent; | ||||
|         this.addMessageAtIndex(message, index, this.actor.mapped); | ||||
|         this.addMessageAtIndex(message, index, this.mapped); | ||||
|     } | ||||
|  | ||||
|     _onSourceDestroy(source, obj) { | ||||
| @@ -986,25 +998,23 @@ class NotificationSection extends MessageList.MessageListSection { | ||||
|         this._sources.delete(source); | ||||
|     } | ||||
|  | ||||
|     _onMapped() { | ||||
|         if (!this.actor.mapped) | ||||
|             return; | ||||
|  | ||||
|         for (let message of this._messages.keys()) | ||||
|     vfunc_map() { | ||||
|         this._messages.forEach(message => { | ||||
|             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'); | ||||
| @@ -1013,10 +1023,10 @@ var Placeholder = class Placeholder { | ||||
|         this._otherIcon = new Gio.FileIcon({ file: otherFile }); | ||||
|  | ||||
|         this._icon = new St.Icon(); | ||||
|         this.actor.add_actor(this._icon); | ||||
|         this.add_actor(this._icon); | ||||
|  | ||||
|         this._label = new St.Label(); | ||||
|         this.actor.add_actor(this._label); | ||||
|         this.add_actor(this._label); | ||||
|  | ||||
|         this._sync(); | ||||
|     } | ||||
| @@ -1043,20 +1053,24 @@ var Placeholder = class Placeholder { | ||||
|             this._label.text = _("No Events"); | ||||
|         } | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|  | ||||
| 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 }); | ||||
| 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 | ||||
|         }); | ||||
|  | ||||
|         this._placeholder = new Placeholder(); | ||||
|         this.actor.add_actor(this._placeholder.actor); | ||||
|         this.add_actor(this._placeholder); | ||||
|  | ||||
|         let box = new St.BoxLayout({ vertical: true, | ||||
|                                      x_expand: true, y_expand: true }); | ||||
|         this.actor.add_actor(box); | ||||
|         this.add_actor(box); | ||||
|  | ||||
|         this._scrollView = new St.ScrollView({ style_class: 'vfade', | ||||
|                                                overlay_scrollbars: true, | ||||
| @@ -1070,12 +1084,11 @@ var CalendarMessageList = class CalendarMessageList { | ||||
|                                             can_focus: true }); | ||||
|         this._clearButton.set_x_align(Clutter.ActorAlign.END); | ||||
|         this._clearButton.connect('clicked', () => { | ||||
|             let sections = [...this._sections.keys()]; | ||||
|             sections.forEach((s) => s.clear()); | ||||
|             this._sectionList.get_children().forEach(s => s.clear()); | ||||
|         }); | ||||
|         box.add_actor(this._clearButton); | ||||
|  | ||||
|         this._placeholder.actor.bind_property('visible', | ||||
|         this._placeholder.bind_property('visible', | ||||
|             this._clearButton, 'visible', | ||||
|             GObject.BindingFlags.INVERT_BOOLEAN); | ||||
|  | ||||
| @@ -1083,8 +1096,9 @@ var CalendarMessageList = class CalendarMessageList { | ||||
|                                                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); | ||||
| @@ -1099,58 +1113,35 @@ var CalendarMessageList = class CalendarMessageList { | ||||
|     } | ||||
|  | ||||
|     _addSection(section) { | ||||
|         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)); | ||||
|         let connectionsIds = []; | ||||
|  | ||||
|         this._sections.set(section, obj); | ||||
|         this._sectionList.add_actor(section.actor); | ||||
|         this._sync(); | ||||
|     } | ||||
|         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); | ||||
|         })); | ||||
|  | ||||
|     _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); | ||||
|         connectionsIds.push(section.connect('destroy', (section) => { | ||||
|             connectionsIds.forEach(id => section.disconnect(id)); | ||||
|             this._sectionList.remove_actor(section); | ||||
|         })); | ||||
|  | ||||
|         this._sections.delete(section); | ||||
|         this._sectionList.remove_actor(section.actor); | ||||
|         this._sync(); | ||||
|     } | ||||
|  | ||||
|     _onKeyFocusIn(section, actor) { | ||||
|         Util.ensureActorVisibleInScrollView(this._scrollView, actor); | ||||
|         this._sectionList.add_actor(section); | ||||
|     } | ||||
|  | ||||
|     _sync() { | ||||
|         let sections = [...this._sections.keys()]; | ||||
|         let sections = this._sectionList.get_children(); | ||||
|         let visible = sections.some(s => s.allowed); | ||||
|         this.actor.visible = visible; | ||||
|         this.visible = visible; | ||||
|         if (!visible) | ||||
|             return; | ||||
|  | ||||
|         let empty = sections.every(s => s.empty || !s.actor.visible); | ||||
|         this._placeholder.actor.visible = empty; | ||||
|         let empty = sections.every(s => s.empty || !s.visible); | ||||
|         this._placeholder.visible = empty; | ||||
|  | ||||
|         let canClear = sections.some(s => s.canClear && s.actor.visible); | ||||
|         let canClear = sections.some(s => s.canClear && s.visible); | ||||
|         this._clearButton.reactive = canClear; | ||||
|     } | ||||
|  | ||||
| @@ -1159,8 +1150,7 @@ var CalendarMessageList = class CalendarMessageList { | ||||
|     } | ||||
|  | ||||
|     setDate(date) { | ||||
|         for (let section of this._sections.keys()) | ||||
|             section.setDate(date); | ||||
|         this._sectionList.get_children().forEach(s => s.setDate(date)); | ||||
|         this._placeholder.setDate(date); | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|   | ||||
| @@ -1,16 +1,19 @@ | ||||
| /* exported CheckBox */ | ||||
| const { Clutter, Pango, St } = imports.gi; | ||||
| const { Clutter, GObject, Pango, St } = imports.gi; | ||||
|  | ||||
| var CheckBox = class CheckBox { | ||||
|     constructor(label) { | ||||
| var CheckBox = GObject.registerClass( | ||||
| class CheckBox extends St.Button { | ||||
|     _init(label) { | ||||
|         let container = new St.BoxLayout(); | ||||
|         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 }); | ||||
|         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._box = new St.Bin(); | ||||
|         this._box.set_y_align(Clutter.ActorAlign.START); | ||||
| @@ -32,4 +35,4 @@ var CheckBox = class CheckBox { | ||||
|     getLabelActor() { | ||||
|         return this._label; | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|   | ||||
| @@ -156,7 +156,7 @@ var AutomountManager = class { | ||||
|             !volume.should_automount() || | ||||
|             !volume.can_mount()) { | ||||
|             // allow the autorun to run anyway; this can happen if the | ||||
|             // mount gets added programmatically later, even if  | ||||
|             // mount gets added programmatically later, even if | ||||
|             // should_automount() or can_mount() are false, like for | ||||
|             // blank optical media. | ||||
|             this._allowAutorun(volume); | ||||
| @@ -222,14 +222,14 @@ var AutomountManager = class { | ||||
|             GLib.source_remove(volume._allowAutorunExpireId); | ||||
|             delete volume._allowAutorunExpireId; | ||||
|         } | ||||
|         this._volumeQueue =  | ||||
|         this._volumeQueue = | ||||
|             this._volumeQueue.filter(element => (element != volume)); | ||||
|     } | ||||
|  | ||||
|     _reaskPassword(volume) { | ||||
|         let prevOperation = this._activeOperations.get(volume); | ||||
|         let existingDialog = prevOperation ? prevOperation.borrowDialog() : null; | ||||
|         let operation =  | ||||
|         let operation = | ||||
|             new ShellMountOperation.ShellMountOperation(volume, | ||||
|                                                         { existingDialog: existingDialog }); | ||||
|         this._mountVolume(volume, operation); | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported Component */ | ||||
|  | ||||
| const { Gio, St } = imports.gi; | ||||
| const { Gio, GObject, St } = imports.gi; | ||||
|  | ||||
| const GnomeSession = imports.misc.gnomeSession; | ||||
| const Main = imports.ui.main; | ||||
| @@ -63,7 +63,7 @@ function startAppForMount(app, mount) { | ||||
|     files.push(root); | ||||
|  | ||||
|     try { | ||||
|         retval = app.launch(files,  | ||||
|         retval = app.launch(files, | ||||
|                             global.create_app_launch_context(0, -1)); | ||||
|     } catch (e) { | ||||
|         log(`Unable to launch the application ${app.get_name()}: ${e}`); | ||||
| @@ -72,8 +72,6 @@ function startAppForMount(app, mount) { | ||||
|     return retval; | ||||
| } | ||||
|  | ||||
| /******************************************/ | ||||
|  | ||||
| const HotplugSnifferIface = loadInterfaceXML('org.gnome.Shell.HotplugSniffer'); | ||||
| const HotplugSnifferProxy = Gio.DBusProxy.makeProxyWrapper(HotplugSnifferIface); | ||||
| function HotplugSniffer() { | ||||
| @@ -117,9 +115,9 @@ var ContentTypeDiscoverer = class { | ||||
|  | ||||
|             let hotplugSniffer = new HotplugSniffer(); | ||||
|             hotplugSniffer.SniffURIRemote(root.get_uri(), | ||||
|                  ([contentTypes]) => { | ||||
|                      this._emitCallback(mount, contentTypes); | ||||
|                  }); | ||||
|                 ([contentTypes]) => { | ||||
|                     this._emitCallback(mount, contentTypes); | ||||
|                 }); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -215,11 +213,11 @@ var AutorunDispatcher = class { | ||||
|     } | ||||
|  | ||||
|     _addSource(mount, apps) { | ||||
|         // if we already have a source showing for this  | ||||
|         // if we already have a source showing for this | ||||
|         // mount, return | ||||
|         if (this._getSourceForMount(mount)) | ||||
|             return; | ||||
|       | ||||
|  | ||||
|         // add a new source | ||||
|         this._sources.push(new AutorunSource(this._manager, mount, apps)); | ||||
|     } | ||||
| @@ -264,7 +262,7 @@ var AutorunDispatcher = class { | ||||
|  | ||||
|     removeMount(mount) { | ||||
|         let source = this._getSourceForMount(mount); | ||||
|          | ||||
|  | ||||
|         // if we aren't tracking this mount, don't do anything | ||||
|         if (!source) | ||||
|             return; | ||||
| @@ -274,9 +272,10 @@ var AutorunDispatcher = class { | ||||
|     } | ||||
| }; | ||||
|  | ||||
| var AutorunSource = class extends MessageTray.Source { | ||||
|     constructor(manager, mount, apps) { | ||||
|         super(mount.get_name()); | ||||
| var AutorunSource = GObject.registerClass( | ||||
| class AutorunSource extends MessageTray.Source { | ||||
|     _init(manager, mount, apps) { | ||||
|         super._init(mount.get_name()); | ||||
|  | ||||
|         this._manager = manager; | ||||
|         this.mount = mount; | ||||
| @@ -286,7 +285,7 @@ var AutorunSource = class extends MessageTray.Source { | ||||
|  | ||||
|         // add ourselves as a source, and popup the notification | ||||
|         Main.messageTray.add(this); | ||||
|         this.notify(this._notification); | ||||
|         this.showNotification(this._notification); | ||||
|     } | ||||
|  | ||||
|     getIcon() { | ||||
| @@ -296,11 +295,12 @@ var AutorunSource = class extends MessageTray.Source { | ||||
|     _createPolicy() { | ||||
|         return new MessageTray.NotificationApplicationPolicy('org.gnome.Nautilus'); | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|  | ||||
| var AutorunNotification = class extends MessageTray.Notification { | ||||
|     constructor(manager, source) { | ||||
|         super(source, source.title); | ||||
| var AutorunNotification = GObject.registerClass( | ||||
| class AutorunNotification extends MessageTray.Notification { | ||||
|     _init(manager, source) { | ||||
|         super._init(source, source.title); | ||||
|  | ||||
|         this._manager = manager; | ||||
|         this._mount = source.mount; | ||||
| @@ -352,6 +352,6 @@ var AutorunNotification = class 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.actor, 0, row, 1, 1); | ||||
|                 layout.attach(this._workSpinner, 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.actor, 2, row, 1, 1); | ||||
|                 layout.attach(this._workSpinner, 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.actor, 'checked', GObject.BindingFlags.SYNC_CREATE | GObject.BindingFlags.BIDIRECTIONAL); | ||||
|             layout.attach(choice.actor, rtl ? 0 : 1, row, 1, 1); | ||||
|             this.prompt.bind_property('choice-chosen', choice, 'checked', GObject.BindingFlags.SYNC_CREATE | GObject.BindingFlags.BIDIRECTIONAL); | ||||
|             layout.attach(choice, rtl ? 0 : 1, row, 1, 1); | ||||
|             row++; | ||||
|         } | ||||
|  | ||||
| @@ -232,8 +232,9 @@ var KeyringPrompter = class { | ||||
|     constructor() { | ||||
|         this._prompter = new Gcr.SystemPrompter(); | ||||
|         this._prompter.connect('new-prompt', () => { | ||||
|             let dialog = this._enabled ? new KeyringDialog() | ||||
|                                        : new KeyringDummyDialog(); | ||||
|             let dialog = this._enabled | ||||
|                 ? new KeyringDialog() | ||||
|                 : new KeyringDummyDialog(); | ||||
|             this._currentPrompt = dialog.prompt; | ||||
|             return this._currentPrompt; | ||||
|         }); | ||||
|   | ||||
| @@ -164,9 +164,9 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog { | ||||
|         if (value.length == 64) { | ||||
|             // must be composed of hexadecimal digits only | ||||
|             for (let i = 0; i < 64; i++) { | ||||
|                 if (!((value[i] >= 'a' && value[i] <= 'f') | ||||
|                       || (value[i] >= 'A' && value[i] <= 'F') | ||||
|                       || (value[i] >= '0' && value[i] <= '9'))) | ||||
|                 if (!((value[i] >= 'a' && value[i] <= 'f') || | ||||
|                       (value[i] >= 'A' && value[i] <= 'F') || | ||||
|                       (value[i] >= '0' && value[i] <= '9'))) | ||||
|                     return false; | ||||
|             } | ||||
|             return true; | ||||
| @@ -180,15 +180,15 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog { | ||||
|         if (secret.wep_key_type == NM.WepKeyType.KEY) { | ||||
|             if (value.length == 10 || value.length == 26) { | ||||
|                 for (let i = 0; i < value.length; i++) { | ||||
|                     if (!((value[i] >= 'a' && value[i] <= 'f') | ||||
|                           || (value[i] >= 'A' && value[i] <= 'F') | ||||
|                           || (value[i] >= '0' && value[i] <= '9'))) | ||||
|                     if (!((value[i] >= 'a' && value[i] <= 'f') || | ||||
|                           (value[i] >= 'A' && value[i] <= 'F') || | ||||
|                           (value[i] >= '0' && value[i] <= '9'))) | ||||
|                         return false; | ||||
|                 } | ||||
|             } else if (value.length == 5 || value.length == 13) { | ||||
|                 for (let i = 0; i < value.length; i++) { | ||||
|                     if (!((value[i] >= 'a' && value[i] <= 'z') | ||||
|                           || (value[i] >= 'A' && value[i] <= 'Z'))) | ||||
|                     if (!((value[i] >= 'a' && value[i] <= 'z') || | ||||
|                           (value[i] >= 'A' && value[i] <= 'Z'))) | ||||
|                         return false; | ||||
|                 } | ||||
|             } else { | ||||
| @@ -213,6 +213,7 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog { | ||||
|         // First the easy ones | ||||
|         case 'wpa-none': | ||||
|         case 'wpa-psk': | ||||
|         case 'sae': | ||||
|             secrets.push({ label: _("Password: "), key: 'psk', | ||||
|                            value: wirelessSecuritySetting.psk || '', | ||||
|                            validate: this._validateWpaPsk, password: true }); | ||||
| @@ -624,7 +625,7 @@ var NetworkAgent = class { | ||||
|         this._pluginDir = Gio.file_new_for_path(Config.VPNDIR); | ||||
|         try { | ||||
|             let monitor = this._pluginDir.monitor(Gio.FileMonitorFlags.NONE, null); | ||||
|             monitor.connect('changed', () => this._vpnCacheBuilt = false); | ||||
|             monitor.connect('changed', () => (this._vpnCacheBuilt = false)); | ||||
|         } catch (e) { | ||||
|             log(`Failed to create monitor for VPN plugin dir: ${e.message}`); | ||||
|         } | ||||
| @@ -733,7 +734,7 @@ var NetworkAgent = class { | ||||
|         }); | ||||
|  | ||||
|         Main.messageTray.add(source); | ||||
|         source.notify(notification); | ||||
|         source.showNotification(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.actor.hide(); | ||||
|             userBox.add(this._userAvatar.actor, | ||||
|             this._userAvatar.hide(); | ||||
|             userBox.add(this._userAvatar, | ||||
|                         { 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.actor); | ||||
|         this._passwordBox.add(this._workSpinner); | ||||
|  | ||||
|         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.actor.show(); | ||||
|             this._userAvatar.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.notify(); | ||||
|                     source.showNotification(); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| @@ -266,9 +266,10 @@ class TelepathyClient extends Tp.BaseClient { | ||||
|     } | ||||
| }) : null; | ||||
|  | ||||
| var ChatSource = class extends MessageTray.Source { | ||||
|     constructor(account, conn, channel, contact, client) { | ||||
|         super(contact.get_alias()); | ||||
| var ChatSource = HAVE_TP ? GObject.registerClass( | ||||
| class ChatSource extends MessageTray.Source { | ||||
|     _init(account, conn, channel, contact, client) { | ||||
|         super._init(contact.get_alias()); | ||||
|  | ||||
|         this._account = account; | ||||
|         this._contact = contact; | ||||
| @@ -326,7 +327,7 @@ var ChatSource = class 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.actor.connect('destroy', () => { | ||||
|         this._banner.connect('destroy', () => { | ||||
|             this._banner.disconnect(id); | ||||
|             this._banner = null; | ||||
|         }); | ||||
| @@ -476,7 +477,7 @@ var ChatSource = class extends MessageTray.Source { | ||||
|             this._notification.appendMessage(pendingMessages[i], true); | ||||
|  | ||||
|         if (pendingMessages.length > 0) | ||||
|             this.notify(); | ||||
|             this.showNotification(); | ||||
|     } | ||||
|  | ||||
|     destroy(reason) { | ||||
| @@ -553,7 +554,7 @@ var ChatSource = class extends MessageTray.Source { | ||||
|  | ||||
|     _notifyTimeout() { | ||||
|         if (this._pendingMessages.length != 0) | ||||
|             this.notify(); | ||||
|             this.showNotification(); | ||||
|  | ||||
|         this._notifyTimeoutId = 0; | ||||
|  | ||||
| @@ -568,8 +569,8 @@ var ChatSource = class extends MessageTray.Source { | ||||
|         this._notification.appendMessage(message); | ||||
|     } | ||||
|  | ||||
|     notify() { | ||||
|         super.notify(this._notification); | ||||
|     showNotification() { | ||||
|         super.showNotification(this._notification); | ||||
|     } | ||||
|  | ||||
|     respond(text) { | ||||
| @@ -583,7 +584,7 @@ var ChatSource = class extends MessageTray.Source { | ||||
|  | ||||
|         let msg = Tp.ClientMessage.new_text(type, text); | ||||
|         this._channel.send_message_async(msg, 0, (src, result) => { | ||||
|             this._channel.send_message_finish(result);  | ||||
|             this._channel.send_message_finish(result); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
| @@ -625,12 +626,18 @@ var ChatSource = class extends MessageTray.Source { | ||||
|         // 'pending-message-removed' for each one. | ||||
|         this._channel.ack_all_pending_messages_async(null); | ||||
|     } | ||||
| }; | ||||
| }) : null; | ||||
|  | ||||
| var ChatNotification = class extends MessageTray.Notification { | ||||
|     constructor(source) { | ||||
|         super(source, source.title, null, | ||||
|               { secondaryGIcon: source.getSecondaryIcon() }); | ||||
| 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() }); | ||||
|         this.setUrgency(MessageTray.Urgency.HIGH); | ||||
|         this.setResident(true); | ||||
|  | ||||
| @@ -653,7 +660,7 @@ var ChatNotification = class extends MessageTray.Notification { | ||||
|      *   sender: the name of the sender, | ||||
|      *   timestamp: the time the message was sent | ||||
|      *   direction: a #NotificationDirection | ||||
|      *  | ||||
|      * | ||||
|      * @noTimestamp: Whether to add a timestamp. If %true, no timestamp | ||||
|      *   will be added, regardless of the difference since the | ||||
|      *   last timestamp | ||||
| @@ -673,8 +680,8 @@ var ChatNotification = class extends MessageTray.Notification { | ||||
|                         { datetime: GLib.DateTime.new_from_unix_local (message.timestamp), | ||||
|                           bannerMarkup: true }); | ||||
|  | ||||
|         let group = (message.direction == NotificationDirection.RECEIVED ? | ||||
|                      'received' : 'sent'); | ||||
|         let group = (message.direction == NotificationDirection.RECEIVED | ||||
|             ? 'received' : 'sent'); | ||||
|  | ||||
|         this._append({ body: messageBody, | ||||
|                        group: group, | ||||
| @@ -696,8 +703,8 @@ var ChatNotification = class extends MessageTray.Notification { | ||||
|         // SCROLLBACK_RECENT_LENGTH previous messages. Otherwise | ||||
|         // we'll keep SCROLLBACK_IDLE_LENGTH messages. | ||||
|  | ||||
|         let maxLength = (lastMessageTime < currentTime - SCROLLBACK_RECENT_TIME) ? | ||||
|             SCROLLBACK_IDLE_LENGTH : SCROLLBACK_RECENT_LENGTH; | ||||
|         let maxLength = (lastMessageTime < currentTime - SCROLLBACK_RECENT_TIME) | ||||
|             ? SCROLLBACK_IDLE_LENGTH : SCROLLBACK_RECENT_LENGTH; | ||||
|  | ||||
|         let filteredHistory = this.messages.filter(item => item.realMessage); | ||||
|         if (filteredHistory.length > maxLength) { | ||||
| @@ -782,7 +789,7 @@ var ChatNotification = class extends MessageTray.Notification { | ||||
|  | ||||
|         this._filterMessages(); | ||||
|     } | ||||
| }; | ||||
| }) : null; | ||||
|  | ||||
| var ChatLineBox = GObject.registerClass( | ||||
| class ChatLineBox extends St.BoxLayout { | ||||
| @@ -792,9 +799,10 @@ class ChatLineBox extends St.BoxLayout { | ||||
|     } | ||||
| }); | ||||
|  | ||||
| var ChatNotificationBanner = class extends MessageTray.NotificationBanner { | ||||
|     constructor(notification) { | ||||
|         super(notification); | ||||
| var ChatNotificationBanner = GObject.registerClass( | ||||
| class ChatNotificationBanner extends MessageTray.NotificationBanner { | ||||
|     _init(notification) { | ||||
|         super._init(notification); | ||||
|  | ||||
|         this._responseEntry = new St.Entry({ style_class: 'chat-response', | ||||
|                                              x_expand: true, | ||||
| @@ -879,8 +887,7 @@ var ChatNotificationBanner = class extends MessageTray.NotificationBanner { | ||||
|     } | ||||
|  | ||||
|     _addMessage(message) { | ||||
|         let highlighter = new MessageList.URLHighlighter(message.body, true, true); | ||||
|         let body = highlighter.actor; | ||||
|         let body = new MessageList.URLHighlighter(message.body, true, true); | ||||
|  | ||||
|         let styles = message.styles; | ||||
|         for (let i = 0; i < styles.length; i++) | ||||
| @@ -968,6 +975,6 @@ var ChatNotificationBanner = class 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, Meta, Shell, St } = imports.gi; | ||||
| const Signals = imports.signals; | ||||
| const { Clutter, GLib, GObject, | ||||
|         Graphene, Meta, Shell, St } = imports.gi; | ||||
|  | ||||
| const AppDisplay = imports.ui.appDisplay; | ||||
| const AppFavorites = imports.ui.appFavorites; | ||||
| @@ -23,9 +23,10 @@ function getAppFromSource(source) { | ||||
|     } | ||||
| } | ||||
|  | ||||
| var DashIcon = class DashIcon extends AppDisplay.AppIcon { | ||||
|     constructor(app) { | ||||
|         super(app, { | ||||
| var DashIcon = GObject.registerClass( | ||||
| class DashIcon extends AppDisplay.AppIcon { | ||||
|     _init(app) { | ||||
|         super._init(app, { | ||||
|             setSizeManually: true, | ||||
|             showLabel: false | ||||
|         }); | ||||
| @@ -45,7 +46,7 @@ var DashIcon = class DashIcon extends AppDisplay.AppIcon { | ||||
|     acceptDrop() { | ||||
|         return false; | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|  | ||||
| // A container like StBin, but taking the child's scale into account | ||||
| // when requesting a size | ||||
| @@ -53,7 +54,7 @@ var DashItemContainer = GObject.registerClass( | ||||
| class DashItemContainer extends St.Widget { | ||||
|     _init() { | ||||
|         super._init({ style_class: 'dash-item-container', | ||||
|                       pivot_point: new Clutter.Point({ x: .5, y: .5 }), | ||||
|                       pivot_point: new Graphene.Point({ x: .5, y: .5 }), | ||||
|                       scale_x: 0, | ||||
|                       scale_y: 0, | ||||
|                       opacity: 0, | ||||
| @@ -330,8 +331,10 @@ class DashActor extends St.Widget { | ||||
|  | ||||
| const baseIconSizes = [16, 22, 24, 32, 48, 64]; | ||||
|  | ||||
| var Dash = class Dash { | ||||
|     constructor() { | ||||
| var Dash = GObject.registerClass({ | ||||
|     Signals: { 'icon-size-changed': {} } | ||||
| }, class Dash extends St.Bin { | ||||
|     _init() { | ||||
|         this._maxHeight = -1; | ||||
|         this.iconSize = 64; | ||||
|         this._shownInitially = false; | ||||
| @@ -359,11 +362,11 @@ var Dash = class Dash { | ||||
|  | ||||
|         this._container.add_actor(this._showAppsIcon); | ||||
|  | ||||
|         this.actor = new St.Bin({ child: this._container }); | ||||
|         this.actor.connect('notify::height', () => { | ||||
|             if (this._maxHeight != this.actor.height) | ||||
|         super._init({ child: this._container }); | ||||
|         this.connect('notify::height', () => { | ||||
|             if (this._maxHeight != this.height) | ||||
|                 this._queueRedisplay(); | ||||
|             this._maxHeight = this.actor.height; | ||||
|             this._maxHeight = this.height; | ||||
|         }); | ||||
|  | ||||
|         this._workId = Main.initializeDeferredWork(this._box, this._redisplay.bind(this)); | ||||
| @@ -386,7 +389,7 @@ var Dash = class Dash { | ||||
|  | ||||
|         // Translators: this is the name of the dock/favorites area on | ||||
|         // the left of the overview | ||||
|         Main.ctrlAltTabManager.addGroup(this.actor, _("Dash"), 'user-bookmarks-symbolic'); | ||||
|         Main.ctrlAltTabManager.addGroup(this, _("Dash"), 'user-bookmarks-symbolic'); | ||||
|     } | ||||
|  | ||||
|     _onDragBegin() { | ||||
| @@ -481,11 +484,11 @@ var Dash = class Dash { | ||||
|                         }); | ||||
|  | ||||
|         let item = new DashItemContainer(); | ||||
|         item.setChild(appIcon.actor); | ||||
|         item.setChild(appIcon); | ||||
|  | ||||
|         // Override default AppIcon label_actor, now the | ||||
|         // accessible_name is set at DashItemContainer.setLabelText | ||||
|         appIcon.actor.label_actor = null; | ||||
|         appIcon.label_actor = null; | ||||
|         item.setLabelText(app.get_name()); | ||||
|  | ||||
|         appIcon.icon.setIconSize(this.iconSize); | ||||
| @@ -623,7 +626,7 @@ var Dash = class Dash { | ||||
|             icon.icon.ease({ | ||||
|                 width: targetWidth, | ||||
|                 height: targetHeight, | ||||
|                 time: DASH_ANIMATION_TIME, | ||||
|                 duration: DASH_ANIMATION_TIME, | ||||
|                 mode: Clutter.AnimationMode.EASE_OUT_QUAD | ||||
|             }); | ||||
|         } | ||||
| @@ -703,8 +706,8 @@ var Dash = class Dash { | ||||
|             } | ||||
|  | ||||
|             // App moved | ||||
|             let nextApp = newApps.length > newIndex + 1 ? newApps[newIndex + 1] | ||||
|                                                         : null; | ||||
|             let nextApp = newApps.length > newIndex + 1 | ||||
|                 ? newApps[newIndex + 1] : null; | ||||
|             let insertHere = nextApp && nextApp == oldApp; | ||||
|             let alreadyRemoved = removedActors.reduce((result, actor) => { | ||||
|                 let removedApp = actor.child._delegate.app; | ||||
| @@ -902,5 +905,4 @@ var Dash = class Dash { | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
| }; | ||||
| Signals.addSignalMethods(Dash.prototype); | ||||
| }); | ||||
|   | ||||
| @@ -25,24 +25,26 @@ function _isToday(date) { | ||||
|            now.getDate() == date.getDate(); | ||||
| } | ||||
|  | ||||
| var TodayButton = class TodayButton { | ||||
|     constructor(calendar) { | ||||
| 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) { | ||||
|         // 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. | ||||
|         this.actor = new St.Button({ | ||||
|         super._init({ | ||||
|             style_class: 'datemenu-today-button', | ||||
|             x_align: St.Align.START, | ||||
|             x_expand: true, | ||||
|             can_focus: true, | ||||
|             reactive: false, | ||||
|         }); | ||||
|         this.actor.connect('clicked', () => { | ||||
|             this._calendar.setDate(new Date(), false); | ||||
|             reactive: false | ||||
|         }); | ||||
|  | ||||
|         let hbox = new St.BoxLayout({ vertical: true }); | ||||
|         this.actor.add_actor(hbox); | ||||
|         this.add_actor(hbox); | ||||
|  | ||||
|         this._dayLabel = new St.Label({ style_class: 'day-label', | ||||
|                                         x_align: Clutter.ActorAlign.START }); | ||||
| @@ -52,13 +54,17 @@ var TodayButton = class TodayButton { | ||||
|         hbox.add_actor(this._dateLabel); | ||||
|  | ||||
|         this._calendar = calendar; | ||||
|         this._calendar.connect('selected-date-changed', (calendar, date) => { | ||||
|         this._calendar.connect('selected-date-changed', (_calendar, datetime) => { | ||||
|             // Make the button reactive only if the selected date is not the | ||||
|             // current date. | ||||
|             this.actor.reactive = !_isToday(date); | ||||
|             this.reactive = !_isToday(_gDateTimeToDate(datetime)); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     vfunc_clicked() { | ||||
|         this._calendar.setDate(new Date(), false); | ||||
|     } | ||||
|  | ||||
|     setDate(date) { | ||||
|         this._dayLabel.set_text(date.toLocaleFormat('%A')); | ||||
|  | ||||
| @@ -75,34 +81,29 @@ var TodayButton = class TodayButton { | ||||
|          * date, e.g. "Tuesday February 17 2015". | ||||
|          */ | ||||
|         dateFormat = Shell.util_translate_time_string (N_("%A %B %e %Y")); | ||||
|         this.actor.accessible_name = date.toLocaleFormat(dateFormat); | ||||
|         this.accessible_name = date.toLocaleFormat(dateFormat); | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|  | ||||
| var WorldClocksSection = class WorldClocksSection { | ||||
|     constructor() { | ||||
| var WorldClocksSection = GObject.registerClass( | ||||
| class WorldClocksSection extends St.Button { | ||||
|     _init() { | ||||
|         super._init({ | ||||
|             style_class: 'world-clocks-button', | ||||
|             x_fill: true, | ||||
|             can_focus: true | ||||
|         }); | ||||
|         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.actor.child = this._grid; | ||||
|         this.child = this._grid; | ||||
|  | ||||
|         this._clocksApp = null; | ||||
|         this._clocksProxy = new ClocksProxy( | ||||
| @@ -125,9 +126,17 @@ var WorldClocksSection = class WorldClocksSection { | ||||
|         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.actor.visible = this._clocksApp != null; | ||||
|         this.visible = this._clocksApp != null; | ||||
|     } | ||||
|  | ||||
|     _clocksChanged() { | ||||
| @@ -148,13 +157,14 @@ var WorldClocksSection = class WorldClocksSection { | ||||
|         }); | ||||
|  | ||||
|         let layout = this._grid.layout_manager; | ||||
|         let title = (this._locations.length == 0) ? _("Add world clocks…") | ||||
|                                                   : _("World Clocks"); | ||||
|         let title = (this._locations.length == 0) | ||||
|             ? _("Add world clocks…") | ||||
|             : _("World Clocks"); | ||||
|         let header = new St.Label({ style_class: 'world-clocks-header', | ||||
|                                     x_align: Clutter.ActorAlign.START, | ||||
|                                     text: title }); | ||||
|         layout.attach(header, 0, 0, 2, 1); | ||||
|         this.actor.label_actor = header; | ||||
|         this.label_actor = header; | ||||
|  | ||||
|         let localOffset = GLib.DateTime.new_now_local().get_utc_offset(); | ||||
|  | ||||
| @@ -235,30 +245,23 @@ var WorldClocksSection = class WorldClocksSection { | ||||
|         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.actor.child = box; | ||||
|         this.child = box; | ||||
|  | ||||
|         let titleBox = new St.BoxLayout(); | ||||
|         titleBox.add_child(new St.Label({ style_class: 'weather-header', | ||||
| @@ -281,6 +284,18 @@ var WeatherSection = class WeatherSection { | ||||
|         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(); | ||||
| @@ -371,23 +386,27 @@ var WeatherSection = class WeatherSection { | ||||
|     } | ||||
|  | ||||
|     _sync() { | ||||
|         this.actor.visible = this._weatherClient.available; | ||||
|         this.visible = this._weatherClient.available; | ||||
|  | ||||
|         if (!this.actor.visible) | ||||
|         if (!this.visible) | ||||
|             return; | ||||
|  | ||||
|         this._titleLocation.visible = this._weatherClient.hasLocation; | ||||
|  | ||||
|         this._updateForecasts(); | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|  | ||||
| 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 }); | ||||
| 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 | ||||
|         }); | ||||
|  | ||||
|         this._sources = []; | ||||
|  | ||||
| @@ -400,7 +419,7 @@ var MessagesIndicator = class MessagesIndicator { | ||||
|     } | ||||
|  | ||||
|     _onSourceAdded(tray, source) { | ||||
|         source.connect('count-updated', this._updateCount.bind(this)); | ||||
|         source.connect('notify::count', this._updateCount.bind(this)); | ||||
|         this._sources.push(source); | ||||
|         this._updateCount(); | ||||
|     } | ||||
| @@ -412,12 +431,12 @@ var MessagesIndicator = class MessagesIndicator { | ||||
|  | ||||
|     _updateCount() { | ||||
|         let count = 0; | ||||
|         this._sources.forEach(source => count += source.unseenCount); | ||||
|         this._sources.forEach(source => (count += source.unseenCount)); | ||||
|         count -= Main.messageTray.queueCount; | ||||
|  | ||||
|         this.actor.visible = (count > 0); | ||||
|         this.visible = (count > 0); | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|  | ||||
| var IndicatorPad = GObject.registerClass( | ||||
| class IndicatorPad extends St.Widget { | ||||
| @@ -510,9 +529,9 @@ class DateMenuButton extends PanelMenu.Button { | ||||
|         this._indicator = new MessagesIndicator(); | ||||
|  | ||||
|         let box = new St.BoxLayout(); | ||||
|         box.add_actor(new IndicatorPad(this._indicator.actor)); | ||||
|         box.add_actor(new IndicatorPad(this._indicator)); | ||||
|         box.add_actor(this._clockDisplay); | ||||
|         box.add_actor(this._indicator.actor); | ||||
|         box.add_actor(this._indicator); | ||||
|  | ||||
|         this.label_actor = this._clockDisplay; | ||||
|         this.add_actor(box); | ||||
| @@ -528,11 +547,11 @@ class DateMenuButton extends PanelMenu.Button { | ||||
|         bin.add_actor(hbox); | ||||
|  | ||||
|         this._calendar = new Calendar.Calendar(); | ||||
|         this._calendar.connect('selected-date-changed', | ||||
|                                (calendar, date) => { | ||||
|                                    layout.frozen = !_isToday(date); | ||||
|                                    this._messageList.setDate(date); | ||||
|                                }); | ||||
|         this._calendar.connect('selected-date-changed', (_calendar, datetime) => { | ||||
|             let date = _gDateTimeToDate(datetime); | ||||
|             layout.frozen = !_isToday(date); | ||||
|             this._messageList.setDate(date); | ||||
|         }); | ||||
|  | ||||
|         this.menu.connect('open-state-changed', (menu, isOpen) => { | ||||
|             // Whenever the menu is opened, select today | ||||
| @@ -546,19 +565,19 @@ class DateMenuButton extends PanelMenu.Button { | ||||
|  | ||||
|         // Fill up the first column | ||||
|         this._messageList = new Calendar.CalendarMessageList(); | ||||
|         hbox.add(this._messageList.actor, { expand: true, y_fill: false, y_align: St.Align.START }); | ||||
|         hbox.add(this._messageList, { expand: true, y_fill: false, y_align: St.Align.START }); | ||||
|  | ||||
|         // Fill up the second column | ||||
|         let boxLayout = new CalendarColumnLayout(this._calendar.actor); | ||||
|         let boxLayout = new CalendarColumnLayout(this._calendar); | ||||
|         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.actor); | ||||
|         vbox.add_actor(this._date); | ||||
|  | ||||
|         vbox.add_actor(this._calendar.actor); | ||||
|         vbox.add_actor(this._calendar); | ||||
|  | ||||
|         this._displaysSection = new St.ScrollView({ style_class: 'datemenu-displays-section vfade', | ||||
|                                                     x_expand: true, x_fill: true, | ||||
| @@ -571,10 +590,10 @@ class DateMenuButton extends PanelMenu.Button { | ||||
|         this._displaysSection.add_actor(displaysBox); | ||||
|  | ||||
|         this._clocksItem = new WorldClocksSection(); | ||||
|         displaysBox.add(this._clocksItem.actor, { x_fill: true }); | ||||
|         displaysBox.add(this._clocksItem, { x_fill: true }); | ||||
|  | ||||
|         this._weatherItem = new WeatherSection(); | ||||
|         displaysBox.add(this._weatherItem.actor, { x_fill: true }); | ||||
|         displaysBox.add(this._weatherItem, { 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.actor.show(); | ||||
|         checkBox.show(); | ||||
|     } else { | ||||
|         label.set_text(''); | ||||
|         checkBox.actor.hide(); | ||||
|         checkBox.hide(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -297,8 +297,8 @@ class EndSessionDialog extends ModalDialog.ModalDialog { | ||||
|                             y_align: St.Align.START }); | ||||
|  | ||||
|         this._checkBox = new CheckBox.CheckBox(); | ||||
|         this._checkBox.actor.connect('clicked', this._sync.bind(this)); | ||||
|         messageLayout.add(this._checkBox.actor); | ||||
|         this._checkBox.connect('clicked', this._sync.bind(this)); | ||||
|         messageLayout.add(this._checkBox); | ||||
|  | ||||
|         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.actor.checked) | ||||
|         if (dialogContent.subjectWithUpdates && this._checkBox.checked) | ||||
|             subject = dialogContent.subjectWithUpdates; | ||||
|  | ||||
|         if (dialogContent.showBatteryWarning) { | ||||
|             // Warn when running on battery power | ||||
|             if (this._powerProxy.OnBattery && this._checkBox.actor.checked) | ||||
|             if (this._powerProxy.OnBattery && this._checkBox.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.actor; | ||||
|             this._iconBin.child = avatarWidget; | ||||
|             avatarWidget.update(); | ||||
|         } | ||||
|  | ||||
| @@ -485,13 +485,13 @@ class EndSessionDialog extends ModalDialog.ModalDialog { | ||||
|         }; | ||||
|  | ||||
|         // Offline update not available; just emit the signal | ||||
|         if (!this._checkBox.actor.visible) { | ||||
|         if (!this._checkBox.visible) { | ||||
|             callback(); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         // Trigger the offline update as requested | ||||
|         if (this._checkBox.actor.checked) { | ||||
|         if (this._checkBox.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); | ||||
|         actor.add(avatar); | ||||
|  | ||||
|         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.actor.visible = (dialogContent.checkBoxText && updatePrepared && updatesAllowed); | ||||
|         this._checkBox.actor.checked = (updatePrepared && updateTriggered); | ||||
|         this._checkBox.visible = (dialogContent.checkBoxText && updatePrepared && updatesAllowed); | ||||
|         this._checkBox.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.actor.visible || updatePrepared && updateTriggered && !updatesAllowed)); | ||||
|                                         (this._checkBox.visible || updatePrepared && updateTriggered && !updatesAllowed)); | ||||
|  | ||||
|         this._updateButtons(); | ||||
|  | ||||
|   | ||||
| @@ -109,8 +109,6 @@ function _easeActor(actor, params) { | ||||
|         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); | ||||
|  | ||||
| @@ -121,7 +119,14 @@ function _easeActor(actor, params) { | ||||
|     actor.set(params); | ||||
|     actor.restore_easing_state(); | ||||
|  | ||||
|     let transition = actor.get_transition(animatedProps[0]); | ||||
|     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.connect('stopped', (t, finished) => callback(finished)); | ||||
|     else | ||||
| @@ -143,8 +148,6 @@ function _easeActorProperty(actor, propName, target, params) { | ||||
|     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); | ||||
|  | ||||
| @@ -155,6 +158,7 @@ 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; | ||||
| @@ -170,6 +174,11 @@ function _easeActorProperty(actor, propName, target, params) { | ||||
|  | ||||
|     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)); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -286,7 +286,7 @@ var ExtensionManager = class { | ||||
|     reloadExtension(oldExtension) { | ||||
|         // Grab the things we'll need to pass to createExtensionObject | ||||
|         // to reload it. | ||||
|         let { uuid: uuid, dir: dir, type: type } = oldExtension; | ||||
|         let { uuid, dir, type } = oldExtension; | ||||
|  | ||||
|         // Then unload the old extension. | ||||
|         this.unloadExtension(oldExtension); | ||||
|   | ||||
| @@ -1,8 +1,7 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported CandidatePopup */ | ||||
|  | ||||
| const { Clutter, IBus, St } = imports.gi; | ||||
| const Signals = imports.signals; | ||||
| const { Clutter, GObject, IBus, St } = imports.gi; | ||||
|  | ||||
| const BoxPointer = imports.ui.boxpointer; | ||||
| const Main = imports.ui.main; | ||||
| @@ -12,11 +11,23 @@ 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 = class CandidateArea { | ||||
|     constructor() { | ||||
|         this.actor = new St.BoxLayout({ vertical: true, | ||||
|                                         reactive: true, | ||||
|                                         visible: false }); | ||||
| 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 | ||||
|         }); | ||||
|         this._candidateBoxes = []; | ||||
|         for (let i = 0; i < MAX_CANDIDATES_PER_PAGE; ++i) { | ||||
|             let box = new St.BoxLayout({ style_class: 'candidate-box', | ||||
| @@ -27,7 +38,7 @@ var CandidateArea = class CandidateArea { | ||||
|             box.add(box._indexLabel, { y_fill: false }); | ||||
|             box.add(box._candidateLabel, { y_fill: false }); | ||||
|             this._candidateBoxes.push(box); | ||||
|             this.actor.add(box); | ||||
|             this.add(box); | ||||
|  | ||||
|             let j = i; | ||||
|             box.connect('button-release-event', (actor, event) => { | ||||
| @@ -36,19 +47,6 @@ var CandidateArea = class CandidateArea { | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         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' }); | ||||
| @@ -59,7 +57,7 @@ var CandidateArea = class CandidateArea { | ||||
|         this._nextButton.child = new St.Icon({ style_class: 'candidate-page-button-icon' }); | ||||
|         this._buttonBox.add(this._nextButton, { expand: true }); | ||||
|  | ||||
|         this.actor.add(this._buttonBox); | ||||
|         this.add(this._buttonBox); | ||||
|  | ||||
|         this._previousButton.connect('clicked', () => { | ||||
|             this.emit('previous-page'); | ||||
| @@ -72,6 +70,18 @@ var CandidateArea = class CandidateArea { | ||||
|         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; | ||||
| @@ -79,15 +89,15 @@ var CandidateArea = class CandidateArea { | ||||
|         this._orientation = orientation; | ||||
|  | ||||
|         if (this._orientation == IBus.Orientation.HORIZONTAL) { | ||||
|             this.actor.vertical = false; | ||||
|             this.actor.remove_style_class_name('vertical'); | ||||
|             this.actor.add_style_class_name('horizontal'); | ||||
|             this.vertical = false; | ||||
|             this.remove_style_class_name('vertical'); | ||||
|             this.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.actor.vertical = true; | ||||
|             this.actor.add_style_class_name('vertical'); | ||||
|             this.actor.remove_style_class_name('horizontal'); | ||||
|             this.vertical = true; | ||||
|             this.add_style_class_name('vertical'); | ||||
|             this.remove_style_class_name('horizontal'); | ||||
|             this._previousButton.child.icon_name = 'go-up-symbolic'; | ||||
|             this._nextButton.child.icon_name = 'go-down-symbolic'; | ||||
|         } | ||||
| @@ -121,19 +131,23 @@ var CandidateArea = class CandidateArea { | ||||
|         this._previousButton.reactive = wrapsAround || page > 0; | ||||
|         this._nextButton.reactive = wrapsAround || page < nPages - 1; | ||||
|     } | ||||
| }; | ||||
| Signals.addSignalMethods(CandidateArea.prototype); | ||||
| }); | ||||
|  | ||||
| var CandidatePopup = class CandidatePopup { | ||||
|     constructor() { | ||||
|         this._boxPointer = new BoxPointer.BoxPointer(St.Side.TOP); | ||||
|         this._boxPointer.visible = false; | ||||
|         this._boxPointer.style_class = 'candidate-popup-boxpointer'; | ||||
|         Main.layoutManager.addChrome(this._boxPointer); | ||||
| var CandidatePopup = GObject.registerClass( | ||||
| class IbusCandidatePopup extends BoxPointer.BoxPointer { | ||||
|     _init() { | ||||
|         super._init(St.Side.TOP); | ||||
|         this.visible = false; | ||||
|         this.style_class = 'candidate-popup-boxpointer'; | ||||
|  | ||||
|         this._dummyCursor = new St.Widget({ opacity: 0 }); | ||||
|         Main.layoutManager.uiGroup.add_actor(this._dummyCursor); | ||||
|  | ||||
|         Main.layoutManager.addChrome(this); | ||||
|  | ||||
|         let box = new St.BoxLayout({ style_class: 'candidate-popup-content', | ||||
|                                      vertical: true }); | ||||
|         this._boxPointer.bin.set_child(box); | ||||
|         this.bin.set_child(box); | ||||
|  | ||||
|         this._preeditText = new St.Label({ style_class: 'candidate-popup-text', | ||||
|                                            visible: false }); | ||||
| @@ -144,7 +158,7 @@ var CandidatePopup = class CandidatePopup { | ||||
|         box.add(this._auxText); | ||||
|  | ||||
|         this._candidateArea = new CandidateArea(); | ||||
|         box.add(this._candidateArea.actor); | ||||
|         box.add(this._candidateArea); | ||||
|  | ||||
|         this._candidateArea.connect('previous-page', () => { | ||||
|             this._panelService.page_up(); | ||||
| @@ -222,7 +236,7 @@ var CandidatePopup = class CandidatePopup { | ||||
|             this._updateVisibility(); | ||||
|         }); | ||||
|         panelService.connect('update-lookup-table', (_ps, lookupTable, visible) => { | ||||
|             this._candidateArea.actor.visible = visible; | ||||
|             this._candidateArea.visible = visible; | ||||
|             this._updateVisibility(); | ||||
|  | ||||
|             let nCandidates = lookupTable.get_number_of_candidates(); | ||||
| @@ -258,37 +272,39 @@ var CandidatePopup = class CandidatePopup { | ||||
|             this._candidateArea.updateButtons(lookupTable.is_round(), page, nPages); | ||||
|         }); | ||||
|         panelService.connect('show-lookup-table', () => { | ||||
|             this._candidateArea.actor.show(); | ||||
|             this._candidateArea.show(); | ||||
|             this._updateVisibility(); | ||||
|         }); | ||||
|         panelService.connect('hide-lookup-table', () => { | ||||
|             this._candidateArea.actor.hide(); | ||||
|             this._candidateArea.hide(); | ||||
|             this._updateVisibility(); | ||||
|         }); | ||||
|         panelService.connect('focus-out', () => { | ||||
|             this._boxPointer.close(BoxPointer.PopupAnimation.NONE); | ||||
|             this.close(BoxPointer.PopupAnimation.NONE); | ||||
|             Main.keyboard.resetSuggestions(); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     _setDummyCursorGeometry(x, y, w, h) { | ||||
|         Main.layoutManager.setDummyCursorGeometry(x, y, w, h); | ||||
|         if (this._boxPointer.visible) | ||||
|             this._boxPointer.setPosition(Main.layoutManager.dummyCursor, 0); | ||||
|         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); | ||||
|     } | ||||
|  | ||||
|     _updateVisibility() { | ||||
|         let isVisible = (!Main.keyboard.visible && | ||||
|                          (this._preeditText.visible || | ||||
|                           this._auxText.visible || | ||||
|                           this._candidateArea.actor.visible)); | ||||
|                           this._candidateArea.visible)); | ||||
|  | ||||
|         if (isVisible) { | ||||
|             this._boxPointer.setPosition(Main.layoutManager.dummyCursor, 0); | ||||
|             this._boxPointer.open(BoxPointer.PopupAnimation.NONE); | ||||
|             this._boxPointer.raise_top(); | ||||
|             this.setPosition(this._dummyCursor, 0); | ||||
|             this.open(BoxPointer.PopupAnimation.NONE); | ||||
|             this.raise_top(); | ||||
|         } else { | ||||
|             this._boxPointer.close(BoxPointer.PopupAnimation.NONE); | ||||
|             this.close(BoxPointer.PopupAnimation.NONE); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -298,4 +314,4 @@ var CandidatePopup = class CandidatePopup { | ||||
|             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, Meta, St } = imports.gi; | ||||
| const { Clutter, GLib, GObject, Graphene, Meta, St } = imports.gi; | ||||
|  | ||||
| const Params = imports.misc.params; | ||||
| const Main = imports.ui.main; | ||||
| @@ -142,6 +142,10 @@ class BaseIcon extends St.Bin { | ||||
|         zoomOutActor(this.child); | ||||
|     } | ||||
|  | ||||
|     animateZoomOutAtPos(x, y) { | ||||
|         zoomOutActorAtPos(this.child, x, y); | ||||
|     } | ||||
|  | ||||
|     update() { | ||||
|         this._createIconTexture(this.iconSize); | ||||
|     } | ||||
| @@ -152,10 +156,15 @@ function clamp(value, min, max) { | ||||
| } | ||||
|  | ||||
| function zoomOutActor(actor) { | ||||
|     let [x, y] = actor.get_transformed_position(); | ||||
|     zoomOutActorAtPos(actor, x, y); | ||||
| } | ||||
|  | ||||
| function zoomOutActorAtPos(actor, x, y) { | ||||
|     let actorClone = new Clutter.Clone({ source: actor, | ||||
|                                          reactive: false }); | ||||
|     let [width, height] = actor.get_transformed_size(); | ||||
|     let [x, y] = actor.get_transformed_position(); | ||||
|  | ||||
|     actorClone.set_size(width, height); | ||||
|     actorClone.set_position(x, y); | ||||
|     actorClone.opacity = 255; | ||||
| @@ -222,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); | ||||
| @@ -273,9 +282,9 @@ var IconGrid = GObject.registerClass({ | ||||
|             return [0, 0]; | ||||
|  | ||||
|         let nChildren = this.get_n_children(); | ||||
|         let nColumns = this._colLimit ? Math.min(this._colLimit, | ||||
|                                                  nChildren) | ||||
|                                       : nChildren; | ||||
|         let nColumns = this._colLimit | ||||
|             ? Math.min(this._colLimit, nChildren) | ||||
|             : nChildren; | ||||
|         let totalSpacing = Math.max(0, nColumns - 1) * this._getSpacing(); | ||||
|         // Kind of a lie, but not really an issue right now.  If | ||||
|         // we wanted to support some sort of hidden/overflow that would | ||||
| @@ -393,7 +402,7 @@ var IconGrid = GObject.registerClass({ | ||||
|         let allocationBox = this.get_allocation_box(); | ||||
|         let paintBox = themeNode.get_paint_box(allocationBox); | ||||
|  | ||||
|         let origin = new Clutter.Vertex(); | ||||
|         let origin = new Graphene.Point3D(); | ||||
|         origin.x = paintBox.x1 - allocationBox.x1; | ||||
|         origin.y = paintBox.y1 - allocationBox.y1; | ||||
|         origin.z = 0.0; | ||||
| @@ -708,13 +717,13 @@ var IconGrid = GObject.registerClass({ | ||||
|  | ||||
|         this._items.push(item); | ||||
|         if (index !== undefined) | ||||
|             this.insert_child_at_index(item.actor, index); | ||||
|             this.insert_child_at_index(item, index); | ||||
|         else | ||||
|             this.add_actor(item.actor); | ||||
|             this.add_actor(item); | ||||
|     } | ||||
|  | ||||
|     removeItem(item) { | ||||
|         this.remove_child(item.actor); | ||||
|         this.remove_child(item); | ||||
|     } | ||||
|  | ||||
|     getItemAtIndex(index) { | ||||
| @@ -787,8 +796,9 @@ var IconGrid = GObject.registerClass({ | ||||
|             let neededWidth = this.usedWidthForNColumns(this._minColumns) - availWidth; | ||||
|             let neededHeight = this.usedHeightForNRows(this._minRows) - availHeight; | ||||
|  | ||||
|             let neededSpacePerItem = (neededWidth > neededHeight) ? Math.ceil(neededWidth / this._minColumns) | ||||
|                                                                   : Math.ceil(neededHeight / this._minRows); | ||||
|             let neededSpacePerItem = (neededWidth > neededHeight) | ||||
|                 ? Math.ceil(neededWidth / this._minColumns) | ||||
|                 : Math.ceil(neededHeight / this._minRows); | ||||
|             this._fixedHItemSize = Math.max(this._hItemSize - neededSpacePerItem, MIN_ICON_SIZE); | ||||
|             this._fixedVItemSize = Math.max(this._vItemSize - neededSpacePerItem, MIN_ICON_SIZE); | ||||
|  | ||||
| @@ -953,7 +963,7 @@ var PaginatedIconGrid = GObject.registerClass({ | ||||
|     */ | ||||
|     openExtraSpace(sourceItem, side, nRows) { | ||||
|         let children = this._getVisibleChildren(); | ||||
|         let index = children.indexOf(sourceItem.actor); | ||||
|         let index = children.indexOf(sourceItem); | ||||
|         if (index == -1) | ||||
|             throw new Error('Item not found.'); | ||||
|  | ||||
| @@ -963,8 +973,7 @@ var PaginatedIconGrid = GObject.registerClass({ | ||||
|         let childrenPerRow = this._childrenPerPage / this._rowsPerPage; | ||||
|         let sourceRow = Math.floor((index - pageOffset) / childrenPerRow); | ||||
|  | ||||
|         let nRowsAbove = (side == St.Side.TOP) ? sourceRow + 1 | ||||
|                                                : sourceRow; | ||||
|         let nRowsAbove = (side == St.Side.TOP) ? sourceRow + 1 : sourceRow; | ||||
|         let nRowsBelow = this._rowsPerPage - nRowsAbove; | ||||
|  | ||||
|         let nRowsUp, nRowsDown; | ||||
|   | ||||
| @@ -76,8 +76,9 @@ var InhibitShortcutsDialog = GObject.registerClass({ | ||||
|         let name = this._app ? this._app.get_name() : this._window.title; | ||||
|  | ||||
|         /* Translators: %s is an application name like "Settings" */ | ||||
|         let title = name ? _("%s wants to inhibit shortcuts").format(name) | ||||
|                          : _("Application wants to inhibit shortcuts"); | ||||
|         let title = name | ||||
|             ? _("%s wants to inhibit shortcuts").format(name) | ||||
|             : _("Application wants to inhibit shortcuts"); | ||||
|         let icon = new Gio.ThemedIcon({ name: 'dialog-warning-symbolic' }); | ||||
|  | ||||
|         let contentParams = { icon, title }; | ||||
|   | ||||
| @@ -28,23 +28,23 @@ class KbdA11yDialog extends GObject.Object { | ||||
|         if (whatChanged & Clutter.KeyboardA11yFlags.SLOW_KEYS_ENABLED) { | ||||
|             key = KEY_SLOW_KEYS_ENABLED; | ||||
|             enabled = (newFlags & Clutter.KeyboardA11yFlags.SLOW_KEYS_ENABLED) > 0; | ||||
|             title = enabled ? | ||||
|                     _("Slow Keys Turned On") : | ||||
|                     _("Slow Keys Turned Off"); | ||||
|             title = enabled | ||||
|                 ? _("Slow Keys Turned On") | ||||
|                 : _("Slow Keys Turned Off"); | ||||
|             body = _("You just held down the Shift key for 8 seconds. This is the shortcut " + | ||||
|                      "for the Slow Keys feature, which affects the way your keyboard works."); | ||||
|  | ||||
|         } else  if (whatChanged & Clutter.KeyboardA11yFlags.STICKY_KEYS_ENABLED) { | ||||
|             key = KEY_STICKY_KEYS_ENABLED; | ||||
|             enabled = (newFlags & Clutter.KeyboardA11yFlags.STICKY_KEYS_ENABLED) > 0; | ||||
|             title = enabled ? | ||||
|                     _("Sticky Keys Turned On") : | ||||
|                     _("Sticky Keys Turned Off"); | ||||
|             body = enabled ? | ||||
|                    _("You just pressed the Shift key 5 times in a row. This is the shortcut " + | ||||
|                      "for the Sticky Keys feature, which affects the way your keyboard works.") : | ||||
|                    _("You just pressed two keys at once, or pressed the Shift key 5 times in a row. " + | ||||
|                      "This turns off the Sticky Keys feature, which affects the way your keyboard works."); | ||||
|             title = enabled | ||||
|                 ? _("Sticky Keys Turned On") | ||||
|                 : _("Sticky Keys Turned Off"); | ||||
|             body = enabled | ||||
|                 ? _("You just pressed the Shift key 5 times in a row. This is the shortcut " + | ||||
|                   "for the Sticky Keys feature, which affects the way your keyboard works.") | ||||
|                 : _("You just pressed two keys at once, or pressed the Shift key 5 times in a row. " + | ||||
|                   "This turns off the Sticky Keys feature, which affects the way your keyboard works."); | ||||
|         } else { | ||||
|             return; | ||||
|         } | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported Keyboard */ | ||||
| /* exported KeyboardManager */ | ||||
|  | ||||
| const { Clutter, Gio, GLib, GObject, Meta, St } = imports.gi; | ||||
| const Signals = imports.signals; | ||||
| @@ -89,8 +89,11 @@ 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; | ||||
| @@ -104,9 +107,10 @@ class KeyContainer extends St.Widget { | ||||
|         this._currentRow++; | ||||
|         this._currentCol = 0; | ||||
|  | ||||
|         let row = new Object(); | ||||
|         row.keys = []; | ||||
|         row.width = 0; | ||||
|         let row = { | ||||
|             keys: [], | ||||
|             width: 0, | ||||
|         }; | ||||
|         this._rows.push(row); | ||||
|     } | ||||
|  | ||||
| @@ -160,24 +164,23 @@ class KeyContainer extends St.Widget { | ||||
|     } | ||||
| }); | ||||
|  | ||||
| var Suggestions = class { | ||||
|     constructor() { | ||||
|         this.actor = new St.BoxLayout({ style_class: 'word-suggestions', | ||||
|                                         vertical: false }); | ||||
|         this.actor.show(); | ||||
| var Suggestions = GObject.registerClass( | ||||
| class Suggestions extends St.BoxLayout { | ||||
|     _init() { | ||||
|         super._init({ style_class: 'word-suggestions', vertical: false }); | ||||
|         this.show(); | ||||
|     } | ||||
|  | ||||
|     add(word, callback) { | ||||
|         let button = new St.Button({ label: word }); | ||||
|         button.connect('clicked', callback); | ||||
|         this.actor.add(button); | ||||
|         this.add(button); | ||||
|     } | ||||
|  | ||||
|     clear() { | ||||
|         this.actor.remove_all_children(); | ||||
|         this.remove_all_children(); | ||||
|     } | ||||
| }; | ||||
| Signals.addSignalMethods(Suggestions.prototype); | ||||
| }); | ||||
|  | ||||
| var LanguageSelectionPopup = class extends PopupMenu.PopupMenu { | ||||
|     constructor(actor) { | ||||
| @@ -242,17 +245,25 @@ var LanguageSelectionPopup = class extends PopupMenu.PopupMenu { | ||||
|     } | ||||
| }; | ||||
|  | ||||
| var Key = class Key { | ||||
|     constructor(key, extendedKeys) { | ||||
| 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' }); | ||||
|  | ||||
|         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.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.add(this.keyButton, { expand: true, x_fill: true }); | ||||
|         this.connect('destroy', this._onDestroy.bind(this)); | ||||
|  | ||||
|         this._extended_keys = extendedKeys; | ||||
|         this._extended_keyboard = null; | ||||
| @@ -460,8 +471,7 @@ var Key = class Key { | ||||
|         else | ||||
|             this.keyButton.remove_style_pseudo_class('latched'); | ||||
|     } | ||||
| }; | ||||
| Signals.addSignalMethods(Key.prototype); | ||||
| }); | ||||
|  | ||||
| var KeyboardModel = class { | ||||
|     constructor(groupName) { | ||||
| @@ -589,7 +599,6 @@ var EmojiPager = GObject.registerClass({ | ||||
|             reactive: true, | ||||
|             clip_to_allocation: true | ||||
|         }); | ||||
|  | ||||
|         this._sections = sections; | ||||
|         this._nCols = nCols; | ||||
|         this._nRows = nRows; | ||||
| @@ -800,7 +809,7 @@ var EmojiPager = GObject.registerClass({ | ||||
|                 this.emit('emoji', str); | ||||
|             }); | ||||
|  | ||||
|             gridLayout.attach(key.actor, col, row, 1, 1); | ||||
|             gridLayout.attach(key, col, row, 1, 1); | ||||
|  | ||||
|             col++; | ||||
|             if (col >= this._nCols) { | ||||
| @@ -842,7 +851,7 @@ var EmojiPager = GObject.registerClass({ | ||||
|         } | ||||
|  | ||||
|         let page = this._pages[nPage]; | ||||
|         this.emit('page-changed', page.section, page.page, page.nPages); | ||||
|         this.emit('page-changed', page.section.label, page.page, page.nPages); | ||||
|     } | ||||
|  | ||||
|     setCurrentSection(section, nPage) { | ||||
| @@ -857,8 +866,21 @@ var EmojiPager = GObject.registerClass({ | ||||
|     } | ||||
| }); | ||||
|  | ||||
| var EmojiSelection = class EmojiSelection { | ||||
|     constructor() { | ||||
| 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 | ||||
|         }); | ||||
|  | ||||
|         this._sections = [ | ||||
|             { first: 'grinning face', label: '🙂️' }, | ||||
|             { first: 'selfie', label: '👍️' }, | ||||
| @@ -873,38 +895,44 @@ var EmojiSelection = class EmojiSelection { | ||||
|  | ||||
|         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, section, page, nPages) => { | ||||
|             this._onPageChanged(section, page, nPages); | ||||
|         this._emojiPager.connect('page-changed', (pager, sectionLabel, page, nPages) => { | ||||
|             this._onPageChanged(sectionLabel, page, nPages); | ||||
|         }); | ||||
|         this._emojiPager.connect('emoji', (pager, str) => { | ||||
|             this.emit('emoji-selected', str); | ||||
|         }); | ||||
|         this.actor.add(this._emojiPager.actor, { expand: true }); | ||||
|         this.add(this._emojiPager, { expand: true }); | ||||
|  | ||||
|         this._pageIndicator = new PageIndicators.PageIndicators(false); | ||||
|         this.actor.add(this._pageIndicator, { expand: true, x_fill: false, y_fill: false }); | ||||
|         this._pageIndicator = new PageIndicators.PageIndicators( | ||||
|             Clutter.Orientation.HORIZONTAL | ||||
|         ); | ||||
|         this.add(this._pageIndicator, { expand: true, x_fill: false, y_fill: false }); | ||||
|         this._pageIndicator.setReactive(false); | ||||
|  | ||||
|         let bottomRow = this._createBottomRow(); | ||||
|         this.actor.add(bottomRow, { expand: true, x_fill: false, y_fill: false }); | ||||
|         this.add(bottomRow, { expand: true, x_fill: false, y_fill: false }); | ||||
|  | ||||
|         this._emojiPager.setCurrentPage(0); | ||||
|     } | ||||
|  | ||||
|     _onPageChanged(section, page, nPages) { | ||||
|     vfunc_map() { | ||||
|         this._emojiPager.setCurrentPage(0); | ||||
|         super.vfunc_map(); | ||||
|     } | ||||
|  | ||||
|     vfunc_unmap() { | ||||
|         super.vfunc_unmap(); | ||||
|         this._emojiPager.setCurrentPage(0); | ||||
|     } | ||||
|  | ||||
|     _onPageChanged(sectionLabel, 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(section == sect); | ||||
|             sect.button.setLatched(sectionLabel == sect.label); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -960,14 +988,14 @@ var EmojiSelection = class EmojiSelection { | ||||
|         key = new Key('ABC', []); | ||||
|         key.keyButton.add_style_class_name('default-key'); | ||||
|         key.connect('released', () => this.emit('toggle')); | ||||
|         row.appendKey(key.actor, 1.5); | ||||
|         row.appendKey(key, 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.actor); | ||||
|             row.appendKey(key); | ||||
|  | ||||
|             section.button = key; | ||||
|         } | ||||
| @@ -976,9 +1004,9 @@ var EmojiSelection = class EmojiSelection { | ||||
|         key.keyButton.add_style_class_name('default-key'); | ||||
|         key.keyButton.add_style_class_name('hide-key'); | ||||
|         key.connect('released', () => { | ||||
|             this.emit('hide'); | ||||
|             this.emit('close-request'); | ||||
|         }); | ||||
|         row.appendKey(key.actor); | ||||
|         row.appendKey(key); | ||||
|         row.layoutButtons(); | ||||
|  | ||||
|         let actor = new AspectContainer({ layout_manager: new Clutter.BinLayout(), | ||||
| @@ -992,11 +1020,14 @@ var EmojiSelection = class EmojiSelection { | ||||
|  | ||||
|         return actor; | ||||
|     } | ||||
| }; | ||||
| Signals.addSignalMethods(EmojiSelection.prototype); | ||||
| }); | ||||
|  | ||||
| var Keypad = class Keypad { | ||||
|     constructor() { | ||||
| var Keypad = GObject.registerClass({ | ||||
|     Signals: { | ||||
|         'keyval': { param_types: [GObject.TYPE_UINT] }, | ||||
|     } | ||||
| }, class Keypad extends AspectContainer { | ||||
|     _init() { | ||||
|         let keys = [ | ||||
|             { label: '1', keyval: Clutter.KEY_1, left: 0, top: 0 }, | ||||
|             { label: '2', keyval: Clutter.KEY_2, left: 1, top: 0 }, | ||||
| @@ -1012,14 +1043,17 @@ var Keypad = class Keypad { | ||||
|             { keyval: Clutter.KEY_Return, extraClassName: 'enter-key', left: 3, top: 1, height: 2 }, | ||||
|         ]; | ||||
|  | ||||
|         this.actor = new AspectContainer({ layout_manager: new Clutter.BinLayout(), | ||||
|                                            x_expand: true, y_expand: true }); | ||||
|         super._init({ | ||||
|             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.actor.add_child(this._box); | ||||
|         this.add_child(this._box); | ||||
|  | ||||
|         for (let i = 0; i < keys.length; i++) { | ||||
|             let cur = keys[i]; | ||||
| @@ -1031,86 +1065,32 @@ var Keypad = class Keypad { | ||||
|             let w, h; | ||||
|             w = cur.width || 1; | ||||
|             h = cur.height || 1; | ||||
|             gridLayout.attach(key.actor, cur.left, cur.top, w, h); | ||||
|             gridLayout.attach(key, cur.left, cur.top, w, h); | ||||
|  | ||||
|             key.connect('released', () => { | ||||
|                 this.emit('keyval', cur.keyval); | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
| }; | ||||
| Signals.addSignalMethods(Keypad.prototype); | ||||
| }); | ||||
|  | ||||
| var Keyboard = class Keyboard { | ||||
| var KeyboardManager = class KeyBoardManager { | ||||
|     constructor() { | ||||
|         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._keyboard = null; | ||||
|         this._a11yApplicationsSettings = new Gio.Settings({ schema_id: A11Y_APPLICATIONS_SCHEMA }); | ||||
|         this._a11yApplicationsSettings.connect('changed', this._syncEnabled.bind(this)); | ||||
|  | ||||
|         this._lastDeviceId = null; | ||||
|         this._suggestions = null; | ||||
|         this._emojiKeyVisible = Meta.is_wayland_compositor(); | ||||
|         Meta.get_backend().connect('last-device-changed', (backend, deviceId) => { | ||||
|             let manager = Clutter.DeviceManager.get_default(); | ||||
|             let device = manager.get_device(deviceId); | ||||
|  | ||||
|         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; | ||||
|             if (device.get_device_name().indexOf('XTEST') < 0) { | ||||
|                 this._lastDeviceId = deviceId; | ||||
|                 this._syncEnabled(); | ||||
|             } | ||||
|         }); | ||||
|         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() { | ||||
| @@ -1127,38 +1107,143 @@ var Keyboard = class Keyboard { | ||||
|     } | ||||
|  | ||||
|     _syncEnabled() { | ||||
|         let wasEnabled = this._enabled; | ||||
|         this._enableKeyboard = this._a11yApplicationsSettings.get_boolean(SHOW_KEYBOARD); | ||||
|         this._enabled = this._enableKeyboard || this._lastDeviceIsTouchscreen(); | ||||
|         if (!this._enabled && !this._keyboardController) | ||||
|         let enableKeyboard = this._a11yApplicationsSettings.get_boolean(SHOW_KEYBOARD); | ||||
|         let enabled = enableKeyboard || this._lastDeviceIsTouchscreen(); | ||||
|         if (!enabled && !this._keyboard) | ||||
|             return; | ||||
|  | ||||
|         if (this._enabled && !this._keyboardController) | ||||
|             this._setupKeyboard(); | ||||
|         else if (!this._enabled) | ||||
|             this.setCursorLocation(null); | ||||
|  | ||||
|         if (!this._enabled && wasEnabled) | ||||
|         if (enabled && !this._keyboard) { | ||||
|             this._keyboard = new Keyboard(); | ||||
|         } else if (!enabled && this._keyboard) { | ||||
|             this._keyboard.setCursorLocation(null); | ||||
|             Main.layoutManager.hideKeyboard(true); | ||||
|             this._keyboard.destroy(); | ||||
|             this._keyboard = null; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     _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); | ||||
|     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; | ||||
|  | ||||
|         this._clearShowIdle(); | ||||
|         this._keyboard = null; | ||||
|         this.actor.destroy(); | ||||
|         this.actor = null; | ||||
|  | ||||
|         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); | ||||
|  | ||||
|         if (this._languagePopup) { | ||||
|             this._languagePopup.destroy(); | ||||
| @@ -1167,9 +1252,8 @@ var Keyboard = class Keyboard { | ||||
|     } | ||||
|  | ||||
|     _setupKeyboard() { | ||||
|         this.actor = new St.BoxLayout({ name: 'keyboard', vertical: true, reactive: true }); | ||||
|         Main.layoutManager.keyboardBox.add_actor(this.actor); | ||||
|         Main.layoutManager.trackChrome(this.actor); | ||||
|         Main.layoutManager.keyboardBox.add_actor(this); | ||||
|         Main.layoutManager.trackChrome(this); | ||||
|  | ||||
|         this._keyboardController = new KeyboardController(); | ||||
|  | ||||
| @@ -1177,30 +1261,28 @@ var Keyboard = class Keyboard { | ||||
|         this._currentPage = null; | ||||
|  | ||||
|         this._suggestions = new Suggestions(); | ||||
|         this.actor.add(this._suggestions.actor, | ||||
|                        { x_align: St.Align.MIDDLE, | ||||
|                          x_fill: false }); | ||||
|         this.add(this._suggestions, { x_align: St.Align.MIDDLE, x_fill: false }); | ||||
|  | ||||
|         this._aspectContainer = new AspectContainer({ layout_manager: new Clutter.BinLayout() }); | ||||
|         this.actor.add(this._aspectContainer, { expand: true }); | ||||
|         this.add(this._aspectContainer, { expand: true }); | ||||
|  | ||||
|         this._emojiSelection = new EmojiSelection(); | ||||
|         this._emojiSelection.connect('toggle', this._toggleEmoji.bind(this)); | ||||
|         this._emojiSelection.connect('hide', () => this.hide()); | ||||
|         this._emojiSelection.connect('close-request', () => this.close()); | ||||
|         this._emojiSelection.connect('emoji-selected', (selection, emoji) => { | ||||
|             this._keyboardController.commitString(emoji); | ||||
|         }); | ||||
|  | ||||
|         this._aspectContainer.add_child(this._emojiSelection.actor); | ||||
|         this._emojiSelection.actor.hide(); | ||||
|         this._aspectContainer.add_child(this._emojiSelection); | ||||
|         this._emojiSelection.hide(); | ||||
|  | ||||
|         this._keypad = new Keypad(); | ||||
|         this._keypad.connect('keyval', (keypad, keyval) => { | ||||
|         this._connectSignal(this._keypad, 'keyval', (_keypad, keyval) => { | ||||
|             this._keyboardController.keyvalPress(keyval); | ||||
|             this._keyboardController.keyvalRelease(keyval); | ||||
|         }); | ||||
|         this._aspectContainer.add_child(this._keypad.actor); | ||||
|         this._keypad.actor.hide(); | ||||
|         this._aspectContainer.add_child(this._keypad); | ||||
|         this._keypad.hide(); | ||||
|         this._keypadVisible = false; | ||||
|  | ||||
|         this._ensureKeysForGroup(this._keyboardController.getCurrentGroup()); | ||||
| @@ -1209,16 +1291,22 @@ var Keyboard = class Keyboard { | ||||
|         // Keyboard models are defined in LTR, we must override | ||||
|         // the locale setting in order to avoid flipping the | ||||
|         // keyboard on RTL locales. | ||||
|         this.actor.text_direction = Clutter.TextDirection.LTR; | ||||
|         this.text_direction = Clutter.TextDirection.LTR; | ||||
|  | ||||
|         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)); | ||||
|         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)); | ||||
|  | ||||
|         if (Meta.is_wayland_compositor()) | ||||
|             this._emojiKeyVisibleId = this._keyboardController.connect('emoji-visible', this._onEmojiKeyVisible.bind(this)); | ||||
|             this._connectSignal(this._keyboardController, 'emoji-visible', | ||||
|                 this._onEmojiKeyVisible.bind(this)); | ||||
|  | ||||
|         this._relayout(); | ||||
|     } | ||||
| @@ -1234,17 +1322,17 @@ var Keyboard = class Keyboard { | ||||
|             return; | ||||
|  | ||||
|         if (!(focus instanceof Clutter.Text)) { | ||||
|             this.hide(); | ||||
|             this.close(); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (!this._showIdleId) { | ||||
|             this._showIdleId = GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => { | ||||
|                 this.show(Main.layoutManager.focusIndex); | ||||
|                 this.open(Main.layoutManager.focusIndex); | ||||
|                 this._showIdleId = 0; | ||||
|                 return GLib.SOURCE_REMOVE; | ||||
|             }); | ||||
|             GLib.Source.set_name_by_id(this._showIdleId, '[gnome-shell] this.show'); | ||||
|             GLib.Source.set_name_by_id(this._showIdleId, '[gnome-shell] this.open'); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -1308,7 +1396,7 @@ var Keyboard = class Keyboard { | ||||
|                     this._setActiveLayer(0); | ||||
|             }); | ||||
|  | ||||
|             layout.appendKey(button.actor, button.keyButton.keyWidth); | ||||
|             layout.appendKey(button, button.keyButton.keyWidth); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -1356,7 +1444,7 @@ var Keyboard = class Keyboard { | ||||
|                 if (keyval != null) | ||||
|                     this._keyboardController.keyvalRelease(keyval); | ||||
|                 else if (action == 'hide') | ||||
|                     this.hide(); | ||||
|                     this.close(); | ||||
|                 else if (action == 'languageMenu') | ||||
|                     this._popupLanguageMenu(actor); | ||||
|                 else if (action == 'emoji') | ||||
| @@ -1379,7 +1467,7 @@ var Keyboard = class Keyboard { | ||||
|                     /* Only hide the key actor, so the container still takes space */ | ||||
|                     extraButton.keyButton.hide(); | ||||
|                 } else { | ||||
|                     extraButton.actor.hide(); | ||||
|                     extraButton.hide(); | ||||
|                 } | ||||
|                 extraButton.setWidth(1.5); | ||||
|             } else if (key.right && numKeys > 8) { | ||||
| @@ -1390,7 +1478,7 @@ var Keyboard = class Keyboard { | ||||
|                 extraButton.setWidth(1.5); | ||||
|             } | ||||
|  | ||||
|             layout.appendKey(extraButton.actor, extraButton.keyButton.keyWidth); | ||||
|             layout.appendKey(extraButton, extraButton.keyButton.keyWidth); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -1401,7 +1489,7 @@ var Keyboard = class Keyboard { | ||||
|  | ||||
|     _setEmojiActive(active) { | ||||
|         this._emojiActive = active; | ||||
|         this._emojiSelection.actor.visible = this._emojiActive; | ||||
|         this._emojiSelection.visible = this._emojiActive; | ||||
|         this._updateCurrentPageVisible(); | ||||
|     } | ||||
|  | ||||
| @@ -1469,12 +1557,12 @@ var Keyboard = class Keyboard { | ||||
|     _relayout() { | ||||
|         let monitor = Main.layoutManager.keyboardMonitor; | ||||
|  | ||||
|         if (this.actor == null || monitor == null) | ||||
|         if (!monitor) | ||||
|             return; | ||||
|  | ||||
|         let maxHeight = monitor.height / 3; | ||||
|         this.actor.width = monitor.width; | ||||
|         this.actor.height = maxHeight; | ||||
|         this.width = monitor.width; | ||||
|         this.height = maxHeight; | ||||
|     } | ||||
|  | ||||
|     _onGroupChanged() { | ||||
| @@ -1483,7 +1571,7 @@ var Keyboard = class Keyboard { | ||||
|     } | ||||
|  | ||||
|     _onKeyboardGroupsChanged() { | ||||
|         let nonGroupActors = [this._emojiSelection.actor, this._keypad.actor]; | ||||
|         let nonGroupActors = [this._emojiSelection, this._keypad]; | ||||
|         this._aspectContainer.get_children().filter(c => !nonGroupActors.includes(c)).forEach(c => { | ||||
|             c.destroy(); | ||||
|         }); | ||||
| @@ -1497,7 +1585,7 @@ var Keyboard = class Keyboard { | ||||
|             return; | ||||
|  | ||||
|         this._keypadVisible = visible; | ||||
|         this._keypad.actor.visible = this._keypadVisible; | ||||
|         this._keypad.visible = this._keypadVisible; | ||||
|         this._updateCurrentPageVisible(); | ||||
|     } | ||||
|  | ||||
| @@ -1522,9 +1610,9 @@ var Keyboard = class Keyboard { | ||||
|             return; | ||||
|  | ||||
|         if (enabled) | ||||
|             this.show(Main.layoutManager.focusIndex); | ||||
|             this.open(Main.layoutManager.focusIndex); | ||||
|         else | ||||
|             this.hide(); | ||||
|             this.close(); | ||||
|     } | ||||
|  | ||||
|     _setActiveLayer(activeLevel) { | ||||
| @@ -1551,12 +1639,6 @@ var Keyboard = class Keyboard { | ||||
|         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; | ||||
| @@ -1564,10 +1646,7 @@ var Keyboard = class Keyboard { | ||||
|         this._keyboardRestingId = 0; | ||||
|     } | ||||
|  | ||||
|     show(monitor) { | ||||
|         if (!this._enabled) | ||||
|             return; | ||||
|  | ||||
|     open(monitor) { | ||||
|         this._clearShowIdle(); | ||||
|         this._keyboardRequested = true; | ||||
|  | ||||
| @@ -1584,13 +1663,13 @@ var Keyboard = class Keyboard { | ||||
|                                                    KEYBOARD_REST_TIME, | ||||
|                                                    () => { | ||||
|                                                        this._clearKeyboardRestTimer(); | ||||
|                                                        this._show(monitor); | ||||
|                                                        this._open(monitor); | ||||
|                                                        return GLib.SOURCE_REMOVE; | ||||
|                                                    }); | ||||
|         GLib.Source.set_name_by_id(this._keyboardRestingId, '[gnome-shell] this._clearKeyboardRestTimer'); | ||||
|     } | ||||
|  | ||||
|     _show(monitor) { | ||||
|     _open(monitor) { | ||||
|         if (!this._keyboardRequested) | ||||
|             return; | ||||
|  | ||||
| @@ -1606,10 +1685,7 @@ var Keyboard = class Keyboard { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     hide() { | ||||
|         if (!this._enabled) | ||||
|             return; | ||||
|  | ||||
|     close() { | ||||
|         this._clearShowIdle(); | ||||
|         this._keyboardRequested = false; | ||||
|  | ||||
| @@ -1621,13 +1697,13 @@ var Keyboard = class Keyboard { | ||||
|                                                    KEYBOARD_REST_TIME, | ||||
|                                                    () => { | ||||
|                                                        this._clearKeyboardRestTimer(); | ||||
|                                                        this._hide(); | ||||
|                                                        this._close(); | ||||
|                                                        return GLib.SOURCE_REMOVE; | ||||
|                                                    }); | ||||
|         GLib.Source.set_name_by_id(this._keyboardRestingId, '[gnome-shell] this._clearKeyboardRestTimer'); | ||||
|     } | ||||
|  | ||||
|     _hide() { | ||||
|     _close() { | ||||
|         if (this._keyboardRequested) | ||||
|             return; | ||||
|  | ||||
| @@ -1644,7 +1720,7 @@ var Keyboard = class Keyboard { | ||||
|         if (!this._suggestions) | ||||
|             return; | ||||
|         this._suggestions.add(text, callback); | ||||
|         this._suggestions.actor.show(); | ||||
|         this._suggestions.show(); | ||||
|     } | ||||
|  | ||||
|     _clearShowIdle() { | ||||
| @@ -1721,7 +1797,7 @@ var Keyboard = class Keyboard { | ||||
|  | ||||
|         this._oskFocusWindow = window; | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|  | ||||
| var KeyboardController = class { | ||||
|     constructor() { | ||||
|   | ||||
| @@ -606,17 +606,17 @@ var LayoutManager = GObject.registerClass({ | ||||
|             return; | ||||
|         } | ||||
|         this._systemBackground = new Background.SystemBackground(); | ||||
|         this._systemBackground.actor.hide(); | ||||
|         this._systemBackground.hide(); | ||||
|  | ||||
|         global.stage.insert_child_below(this._systemBackground.actor, null); | ||||
|         global.stage.insert_child_below(this._systemBackground, null); | ||||
|  | ||||
|         let constraint = new Clutter.BindConstraint({ source: global.stage, | ||||
|                                                       coordinate: Clutter.BindCoordinate.ALL }); | ||||
|         this._systemBackground.actor.add_constraint(constraint); | ||||
|         this._systemBackground.add_constraint(constraint); | ||||
|  | ||||
|         let signalId = this._systemBackground.connect('loaded', () => { | ||||
|             this._systemBackground.disconnect(signalId); | ||||
|             this._systemBackground.actor.show(); | ||||
|             this._systemBackground.show(); | ||||
|             global.stage.show(); | ||||
|  | ||||
|             this._prepareStartupAnimation(); | ||||
| @@ -722,7 +722,7 @@ var LayoutManager = GObject.registerClass({ | ||||
|         this._coverPane.destroy(); | ||||
|         this._coverPane = null; | ||||
|  | ||||
|         this._systemBackground.actor.destroy(); | ||||
|         this._systemBackground.destroy(); | ||||
|         this._systemBackground = null; | ||||
|  | ||||
|         this._startingUp = false; | ||||
| @@ -771,8 +771,7 @@ var LayoutManager = GObject.registerClass({ | ||||
|         this.keyboardBox.ease({ | ||||
|             anchor_y: 0, | ||||
|             opacity: 0, | ||||
|             duration: immediate ? 0 | ||||
|                                 : KEYBOARD_ANIMATION_TIME, | ||||
|             duration: immediate ? 0 : KEYBOARD_ANIMATION_TIME, | ||||
|             mode: Clutter.AnimationMode.EASE_IN_QUAD, | ||||
|             onComplete: () => { | ||||
|                 this._hideKeyboardComplete(); | ||||
| @@ -856,8 +855,9 @@ var LayoutManager = GObject.registerClass({ | ||||
|             index = this._findActor(ancestor); | ||||
|         } | ||||
|  | ||||
|         let ancestorData = ancestor ? this._trackedActors[index] | ||||
|                                     : defaultParams; | ||||
|         let ancestorData = ancestor | ||||
|             ? this._trackedActors[index] | ||||
|             : defaultParams; | ||||
|         // We can't use Params.parse here because we want to drop | ||||
|         // the extra values like ancestorData.actor | ||||
|         for (let prop in defaultParams) { | ||||
| @@ -1015,11 +1015,6 @@ var LayoutManager = GObject.registerClass({ | ||||
|         if (Main.modalCount > 0) | ||||
|             return GLib.SOURCE_REMOVE; | ||||
|  | ||||
|         // Bug workaround - get_transformed_position()/get_transformed_size() don't work after | ||||
|         // a change in stage size until the first pick or paint. | ||||
|         // https://bugzilla.gnome.org/show_bug.cgi?id=761565 | ||||
|         global.stage.get_actor_at_pos(Clutter.PickMode.ALL, 0, 0); | ||||
|  | ||||
|         let rects = [], struts = [], i; | ||||
|         let isPopupMenuVisible = global.top_window_group.get_children().some(isPopupMetaWindow); | ||||
|         let wantsInputRegion = !isPopupMenuVisible; | ||||
| @@ -1075,16 +1070,17 @@ var LayoutManager = GObject.registerClass({ | ||||
|                         side = Meta.Side.RIGHT; | ||||
|                     else | ||||
|                         continue; | ||||
|                 } else if (x1 <= monitor.x) | ||||
|                 } else if (x1 <= monitor.x) { | ||||
|                     side = Meta.Side.LEFT; | ||||
|                 else if (y1 <= monitor.y) | ||||
|                 } else if (y1 <= monitor.y) { | ||||
|                     side = Meta.Side.TOP; | ||||
|                 else if (x2 >= monitor.x + monitor.width) | ||||
|                 } else if (x2 >= monitor.x + monitor.width) { | ||||
|                     side = Meta.Side.RIGHT; | ||||
|                 else if (y2 >= monitor.y + monitor.height) | ||||
|                 } else if (y2 >= monitor.y + monitor.height) { | ||||
|                     side = Meta.Side.BOTTOM; | ||||
|                 else | ||||
|                 } else { | ||||
|                     continue; | ||||
|                 } | ||||
|  | ||||
|                 let strutRect = new Meta.Rectangle({ x: x1, y: y1, width: x2 - x1, height: y2 - y1 }); | ||||
|                 let strut = new Meta.Strut({ rect: strutRect, side: side }); | ||||
| @@ -1116,8 +1112,11 @@ var LayoutManager = GObject.registerClass({ | ||||
| // | ||||
| // This class manages a "hot corner" that can toggle switching to | ||||
| // overview. | ||||
| var HotCorner = class HotCorner { | ||||
|     constructor(layoutManager, monitor, x, y) { | ||||
| var HotCorner = GObject.registerClass( | ||||
| class HotCorner extends Clutter.Actor { | ||||
|     _init(layoutManager, monitor, x, y) { | ||||
|         super._init(); | ||||
|  | ||||
|         // 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 | ||||
| @@ -1146,6 +1145,8 @@ var HotCorner = class HotCorner { | ||||
|  | ||||
|         this._ripples = new Ripples.Ripples(px, py, 'ripple-box'); | ||||
|         this._ripples.addTo(layoutManager.uiGroup); | ||||
|  | ||||
|         this.connect('destroy', this._onDestroy.bind(this)); | ||||
|     } | ||||
|  | ||||
|     setBarrierSize(size) { | ||||
| @@ -1185,11 +1186,14 @@ var HotCorner = class HotCorner { | ||||
|  | ||||
|     _setupFallbackCornerIfNeeded(layoutManager) { | ||||
|         if (!global.display.supports_extended_barriers()) { | ||||
|             this.actor = new Clutter.Actor({ name: 'hot-corner-environs', | ||||
|                                              x: this._x, y: this._y, | ||||
|                                              width: 3, | ||||
|                                              height: 3, | ||||
|                                              reactive: true }); | ||||
|             this.set({ | ||||
|                 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, | ||||
| @@ -1198,19 +1202,16 @@ var HotCorner = class HotCorner { | ||||
|                                                reactive: true }); | ||||
|             this._corner._delegate = this; | ||||
|  | ||||
|             this.actor.add_child(this._corner); | ||||
|             layoutManager.addChrome(this.actor); | ||||
|             this.add_child(this._corner); | ||||
|             layoutManager.addChrome(this); | ||||
|  | ||||
|             if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL) { | ||||
|                 this._corner.set_position(this.actor.width - this._corner.width, 0); | ||||
|                 this.actor.set_anchor_point_from_gravity(Clutter.Gravity.NORTH_EAST); | ||||
|                 this._corner.set_position(this.width - this._corner.width, 0); | ||||
|                 this.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', | ||||
| @@ -1218,14 +1219,11 @@ var HotCorner = class HotCorner { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     destroy() { | ||||
|     _onDestroy() { | ||||
|         this.setBarrierSize(0); | ||||
|         this._pressureBarrier.destroy(); | ||||
|         this._pressureBarrier = null; | ||||
|  | ||||
|         if (this.actor) | ||||
|             this.actor.destroy(); | ||||
|  | ||||
|         this._ripples.destroy(); | ||||
|     } | ||||
|  | ||||
| @@ -1257,18 +1255,18 @@ var HotCorner = class HotCorner { | ||||
|     } | ||||
|  | ||||
|     _onCornerLeft(actor, event) { | ||||
|         if (event.get_related() != this.actor) | ||||
|         if (event.get_related() != this) | ||||
|             this._entered = false; | ||||
|         // Consume event, otherwise this will confuse onEnvironsLeft | ||||
|         return Clutter.EVENT_STOP; | ||||
|     } | ||||
|  | ||||
|     _onEnvironsLeft(actor, event) { | ||||
|         if (event.get_related() != this._corner) | ||||
|     vfunc_leave_event(crossingEvent) { | ||||
|         if (crossingEvent.related != this._corner) | ||||
|             this._entered = false; | ||||
|         return Clutter.EVENT_PROPAGATE; | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|  | ||||
| var PressureBarrier = class PressureBarrier { | ||||
|     constructor(threshold, timeout, actionMode) { | ||||
|   | ||||
| @@ -2,7 +2,6 @@ | ||||
| /* exported Lightbox */ | ||||
|  | ||||
| const { Clutter, GObject, Shell, St } = imports.gi; | ||||
| const Signals = imports.signals; | ||||
|  | ||||
| const Params = imports.misc.params; | ||||
|  | ||||
| @@ -89,8 +88,8 @@ var RadialShaderEffect = GObject.registerClass({ | ||||
|  *           - inhibitEvents: whether to inhibit events for @container | ||||
|  *           - width: shade actor width | ||||
|  *           - height: shade actor height | ||||
|  *           - fadeInTime: milliseconds used to fade in | ||||
|  *           - fadeOutTime: milliseconds used to fade out | ||||
|  *           - fadeFactor: fading opacity factor | ||||
|  *           - radialEffect: whether to enable the GLSL radial effect | ||||
|  * | ||||
|  * Lightbox creates a dark translucent "shade" actor to hide the | ||||
|  * contents of @container, and allows you to specify particular actors | ||||
| @@ -106,8 +105,13 @@ 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 = class Lightbox { | ||||
|     constructor(container, 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) { | ||||
|         params = Params.parse(params, { | ||||
|             inhibitEvents: false, | ||||
|             width: null, | ||||
| @@ -116,32 +120,34 @@ var Lightbox = class Lightbox { | ||||
|             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.actor.add_effect(new RadialShaderEffect({ name: 'radial' })); | ||||
|             this.add_effect(new RadialShaderEffect({ name: 'radial' })); | ||||
|         else | ||||
|             this.actor.set({ opacity: 0, style_class: 'lightbox' }); | ||||
|             this.set({ opacity: 0, style_class: 'lightbox' }); | ||||
|  | ||||
|         container.add_actor(this.actor); | ||||
|         this.actor.raise_top(); | ||||
|         this.actor.hide(); | ||||
|         this.shown = false; | ||||
|         container.add_actor(this); | ||||
|         this.raise_top(); | ||||
|  | ||||
|         this.actor.connect('destroy', this._onDestroy.bind(this)); | ||||
|         this.connect('destroy', this._onDestroy.bind(this)); | ||||
|  | ||||
|         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); | ||||
|         if (!params.width || !params.height) { | ||||
|             this.add_constraint(new Clutter.BindConstraint({ | ||||
|                 source: container, | ||||
|                 coordinate: Clutter.BindCoordinate.ALL | ||||
|             })); | ||||
|         } | ||||
|  | ||||
|         this._actorAddedSignalId = container.connect('actor-added', this._actorAdded.bind(this)); | ||||
| @@ -150,16 +156,20 @@ var Lightbox = class Lightbox { | ||||
|         this._highlighted = null; | ||||
|     } | ||||
|  | ||||
|     get active() { | ||||
|         return this._active; | ||||
|     } | ||||
|  | ||||
|     _actorAdded(container, newChild) { | ||||
|         let children = this._container.get_children(); | ||||
|         let myIndex = children.indexOf(this.actor); | ||||
|         let myIndex = children.indexOf(this); | ||||
|         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. | ||||
|             newChild.lower(this.actor); | ||||
|             this._container.set_child_above_sibling(this, newChild); | ||||
|             this._children.push(newChild); | ||||
|         } else if (newChildIndex == 0) { | ||||
|             // Bottom of stack | ||||
| @@ -172,8 +182,8 @@ var Lightbox = class Lightbox { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     show(fadeInTime) { | ||||
|         this.actor.remove_all_transitions(); | ||||
|     lightOn(fadeInTime) { | ||||
|         this.remove_all_transitions(); | ||||
|  | ||||
|         let easeProps = { | ||||
|             duration: fadeInTime || 0, | ||||
| @@ -181,44 +191,46 @@ var Lightbox = class Lightbox { | ||||
|         }; | ||||
|  | ||||
|         let onComplete = () => { | ||||
|             this.shown = true; | ||||
|             this.emit('shown'); | ||||
|             this._active = true; | ||||
|             this.notify('active'); | ||||
|         }; | ||||
|  | ||||
|         this.show(); | ||||
|  | ||||
|         if (this._radialEffect) { | ||||
|             this.actor.ease_property( | ||||
|             this.ease_property( | ||||
|                 '@effects.radial.brightness', VIGNETTE_BRIGHTNESS, easeProps); | ||||
|             this.actor.ease_property( | ||||
|             this.ease_property( | ||||
|                 '@effects.radial.sharpness', VIGNETTE_SHARPNESS, | ||||
|                 Object.assign({ onComplete }, easeProps)); | ||||
|         } else { | ||||
|             this.actor.ease(Object.assign(easeProps, { | ||||
|             this.ease(Object.assign(easeProps, { | ||||
|                 opacity: 255 * this._fadeFactor, | ||||
|                 onComplete | ||||
|             })); | ||||
|         } | ||||
|  | ||||
|         this.actor.show(); | ||||
|     } | ||||
|  | ||||
|     hide(fadeOutTime) { | ||||
|         this.shown = false; | ||||
|         this.actor.remove_all_transitions(); | ||||
|     lightOff(fadeOutTime) { | ||||
|         this.remove_all_transitions(); | ||||
|  | ||||
|         this._active = false; | ||||
|         this.notify('active'); | ||||
|  | ||||
|         let easeProps = { | ||||
|             duration: fadeOutTime || 0, | ||||
|             mode: Clutter.AnimationMode.EASE_OUT_QUAD | ||||
|         }; | ||||
|  | ||||
|         let onComplete = () => this.actor.hide(); | ||||
|         let onComplete = () => this.hide(); | ||||
|  | ||||
|         if (this._radialEffect) { | ||||
|             this.actor.ease_property( | ||||
|             this.ease_property( | ||||
|                 '@effects.radial.brightness', 1.0, easeProps); | ||||
|             this.actor.ease_property( | ||||
|             this.ease_property( | ||||
|                 '@effects.radial.sharpness', 0.0, Object.assign({ onComplete }, easeProps)); | ||||
|         } else { | ||||
|             this.actor.ease(Object.assign(easeProps, { opacity: 0, onComplete })); | ||||
|             this.ease(Object.assign(easeProps, { opacity: 0, onComplete })); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -249,7 +261,7 @@ var Lightbox = class Lightbox { | ||||
|         // case we may need to indicate some *other* actor as the new | ||||
|         // sibling of the to-be-lowered one. | ||||
|  | ||||
|         let below = this.actor; | ||||
|         let below = this; | ||||
|         for (let i = this._children.length - 1; i >= 0; i--) { | ||||
|             if (this._children[i] == window) | ||||
|                 this._children[i].raise_top(); | ||||
| @@ -262,15 +274,6 @@ var Lightbox = class Lightbox { | ||||
|         this._highlighted = window; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * destroy: | ||||
|      * | ||||
|      * Destroys the lightbox. | ||||
|      */ | ||||
|     destroy() { | ||||
|         this.actor.destroy(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * _onDestroy: | ||||
|      * | ||||
| @@ -278,10 +281,15 @@ var Lightbox = class Lightbox { | ||||
|      * by destroying its container or by explicitly calling this.destroy(). | ||||
|      */ | ||||
|     _onDestroy() { | ||||
|         this._container.disconnect(this._actorAddedSignalId); | ||||
|         this._container.disconnect(this._actorRemovedSignalId); | ||||
|         if (this._actorAddedSignalId) { | ||||
|             this._container.disconnect(this._actorAddedSignalId); | ||||
|             this._actorAddedSignalId = 0; | ||||
|         } | ||||
|         if (this._actorRemovedSignalId) { | ||||
|             this._container.disconnect(this._actorRemovedSignalId); | ||||
|             this._actorRemovedSignalId = 0; | ||||
|         } | ||||
|  | ||||
|         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, Meta, Pango, Shell, St } = imports.gi; | ||||
| const { Clutter, Cogl, Gio, GLib, GObject, | ||||
|         Graphene, Meta, Pango, Shell, St } = imports.gi; | ||||
| const Signals = imports.signals; | ||||
| const System = imports.system; | ||||
|  | ||||
| @@ -110,9 +110,11 @@ var AutoComplete = class AutoComplete { | ||||
| Signals.addSignalMethods(AutoComplete.prototype); | ||||
|  | ||||
|  | ||||
| var Notebook = class Notebook { | ||||
|     constructor() { | ||||
|         this.actor = new St.BoxLayout({ vertical: true }); | ||||
| var Notebook = GObject.registerClass({ | ||||
|     Signals: { 'selection': { param_types: [Clutter.Actor.$gtype] } }, | ||||
| }, class Notebook extends St.BoxLayout { | ||||
|     _init() { | ||||
|         super._init({ vertical: true }); | ||||
|  | ||||
|         this.tabControls = new St.BoxLayout({ style_class: 'labels' }); | ||||
|  | ||||
| @@ -143,7 +145,7 @@ var Notebook = class Notebook { | ||||
|                         _scrollToBottom: false }; | ||||
|         this._tabs.push(tabData); | ||||
|         scrollview.hide(); | ||||
|         this.actor.add(scrollview, { expand: true }); | ||||
|         this.add(scrollview, { expand: true }); | ||||
|  | ||||
|         let vAdjust = scrollview.vscroll.adjustment; | ||||
|         vAdjust.connect('changed', () => this._onAdjustScopeChanged(tabData)); | ||||
| @@ -174,7 +176,7 @@ var Notebook = class Notebook { | ||||
|         // 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.actor.grab_key_focus(); | ||||
|             this.grab_key_focus(); | ||||
|  | ||||
|         this._unselect(); | ||||
|  | ||||
| @@ -234,8 +236,7 @@ var Notebook = class Notebook { | ||||
|  | ||||
|         this.selectIndex(prevIndex); | ||||
|     } | ||||
| }; | ||||
| Signals.addSignalMethods(Notebook.prototype); | ||||
| }); | ||||
|  | ||||
| function objectToString(o) { | ||||
|     if (typeof o == typeof objectToString) { | ||||
| @@ -246,57 +247,64 @@ function objectToString(o) { | ||||
|     } | ||||
| } | ||||
|  | ||||
| var ObjLink = class ObjLink { | ||||
|     constructor(lookingGlass, o, title) { | ||||
| var ObjLink = GObject.registerClass( | ||||
| class ObjLink extends St.Button { | ||||
|     _init(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; | ||||
|     } | ||||
|  | ||||
|     _onClicked() { | ||||
|         this._lookingGlass.inspectObject(this._obj, this.actor); | ||||
|     vfunc_clicked() { | ||||
|         this._lookingGlass.inspectObject(this._obj, this); | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|  | ||||
| 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.actor.add(cmdTxt); | ||||
|         this.add(cmdTxt); | ||||
|         let box = new St.BoxLayout({}); | ||||
|         this.actor.add(box); | ||||
|         this.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.actor); | ||||
|         box.add(objLink); | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|  | ||||
| var WindowList = class WindowList { | ||||
|     constructor(lookingGlass) { | ||||
|         this.actor = new St.BoxLayout({ name: 'Windows', vertical: true, style: 'spacing: 8px' }); | ||||
| var WindowList = GObject.registerClass({ | ||||
|     GTypeName: 'LookingClass_WindowList' | ||||
| }, class WindowList extends St.BoxLayout { | ||||
|     _init(lookingGlass) { | ||||
|         super._init({ name: 'Windows', vertical: true, style: 'spacing: 8px' }); | ||||
|         let tracker = Shell.WindowTracker.get_default(); | ||||
|         this._updateId = Main.initializeDeferredWork(this.actor, this._updateWindowList.bind(this)); | ||||
|         this._updateId = Main.initializeDeferredWork(this, this._updateWindowList.bind(this)); | ||||
|         global.display.connect('window-created', this._updateWindowList.bind(this)); | ||||
|         tracker.connect('tracked-windows-changed', this._updateWindowList.bind(this)); | ||||
|  | ||||
| @@ -307,7 +315,7 @@ var WindowList = class WindowList { | ||||
|         if (!this._lookingGlass.isOpen) | ||||
|             return; | ||||
|  | ||||
|         this.actor.destroy_all_children(); | ||||
|         this.destroy_all_children(); | ||||
|         let windows = global.get_window_actors(); | ||||
|         let tracker = Shell.WindowTracker.get_default(); | ||||
|         for (let i = 0; i < windows.length; i++) { | ||||
| @@ -318,9 +326,9 @@ var WindowList = class WindowList { | ||||
|                 metaWindow._lookingGlassManaged = true; | ||||
|             } | ||||
|             let box = new St.BoxLayout({ vertical: true }); | ||||
|             this.actor.add(box); | ||||
|             this.add(box); | ||||
|             let windowLink = new ObjLink(this._lookingGlass, metaWindow, metaWindow.title); | ||||
|             box.add(windowLink.actor, { x_align: St.Align.START, x_fill: false }); | ||||
|             box.add(windowLink, { 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()}` })); | ||||
| @@ -331,7 +339,7 @@ var WindowList = class WindowList { | ||||
|                 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.actor, { y_fill: false }); | ||||
|                 propBox.add(appLink, { y_fill: false }); | ||||
|                 propBox.add(icon, { y_fill: false }); | ||||
|             } else { | ||||
|                 propsBox.add(new St.Label({ text: '<untracked>' })); | ||||
| @@ -342,23 +350,27 @@ var WindowList = class WindowList { | ||||
|     update() { | ||||
|         this._updateWindowList(); | ||||
|     } | ||||
| }; | ||||
| Signals.addSignalMethods(WindowList.prototype); | ||||
| }); | ||||
|  | ||||
| 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 | ||||
|         }); | ||||
|  | ||||
| var ObjInspector = class ObjInspector { | ||||
|     constructor(lookingGlass) { | ||||
|         this._obj = null; | ||||
|         this._previousObj = null; | ||||
|  | ||||
|         this._parentList = []; | ||||
|  | ||||
|         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.get_hscroll_bar().hide(); | ||||
|         this._container = new St.BoxLayout({ name: 'LookingGlassPropertyInspector', | ||||
|                                              style_class: 'lg-dialog', | ||||
|                                              vertical: true }); | ||||
|         this.actor.add_actor(this._container); | ||||
|         this.add_actor(this._container); | ||||
|  | ||||
|         this._lookingGlass = lookingGlass; | ||||
|     } | ||||
| @@ -404,7 +416,7 @@ var ObjInspector = class ObjInspector { | ||||
|                 let link; | ||||
|                 try { | ||||
|                     let prop = obj[propName]; | ||||
|                     link = new ObjLink(this._lookingGlass, prop).actor; | ||||
|                     link = new ObjLink(this._lookingGlass, prop); | ||||
|                 } catch (e) { | ||||
|                     link = new St.Label({ text: '<error>' }); | ||||
|                 } | ||||
| @@ -421,17 +433,17 @@ var ObjInspector = class ObjInspector { | ||||
|             return; | ||||
|         this._previousObj = null; | ||||
|         this._open = true; | ||||
|         this.actor.show(); | ||||
|         this.show(); | ||||
|         if (sourceActor) { | ||||
|             this.actor.set_scale(0, 0); | ||||
|             this.actor.ease({ | ||||
|             this.set_scale(0, 0); | ||||
|             this.ease({ | ||||
|                 scale_x: 1, | ||||
|                 scale_y: 1, | ||||
|                 mode: Clutter.AnimationMode.EASE_OUT_QUAD, | ||||
|                 time: 200 | ||||
|                 duration: 200 | ||||
|             }); | ||||
|         } else { | ||||
|             this.actor.set_scale(1, 1); | ||||
|             this.set_scale(1, 1); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -439,7 +451,7 @@ var ObjInspector = class ObjInspector { | ||||
|         if (!this._open) | ||||
|             return; | ||||
|         this._open = false; | ||||
|         this.actor.hide(); | ||||
|         this.hide(); | ||||
|         this._previousObj = null; | ||||
|         this._obj = null; | ||||
|     } | ||||
| @@ -453,7 +465,7 @@ var ObjInspector = class ObjInspector { | ||||
|     _onBack() { | ||||
|         this.selectObject(this._previousObj, true); | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|  | ||||
| var RedBorderEffect = GObject.registerClass( | ||||
| class RedBorderEffect extends Clutter.Effect { | ||||
| @@ -484,8 +496,7 @@ 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); | ||||
|  | ||||
| @@ -620,18 +631,20 @@ var Inspector = GObject.registerClass({ | ||||
|     } | ||||
| }); | ||||
|  | ||||
| var Extensions = class Extensions { | ||||
|     constructor(lookingGlass) { | ||||
| var Extensions = GObject.registerClass({ | ||||
|     GTypeName: 'LookingClass_Extensions' | ||||
| }, class Extensions extends St.BoxLayout { | ||||
|     _init(lookingGlass) { | ||||
|         super._init({ vertical: true, name: 'lookingGlassExtensions' }); | ||||
|  | ||||
|         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.actor.add(this._extensionsList); | ||||
|         this.add(this._extensionsList); | ||||
|  | ||||
|         Main.extensionManager.getUuids().forEach(uuid => { | ||||
|             this._loadExtension(null, uuid); | ||||
| @@ -759,10 +772,19 @@ var Extensions = class Extensions { | ||||
|  | ||||
|         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(); | ||||
|  | ||||
| @@ -770,26 +792,18 @@ var LookingGlass = class LookingGlass { | ||||
|  | ||||
|         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.actor); | ||||
|         Main.uiGroup.set_child_below_sibling(this.actor, | ||||
|         Main.uiGroup.add_actor(this); | ||||
|         Main.uiGroup.set_child_below_sibling(this, | ||||
|                                              Main.layoutManager.panelBox); | ||||
|         Main.layoutManager.panelBox.connect('allocation-changed', | ||||
|                                             this._queueResize.bind(this)); | ||||
| @@ -797,11 +811,11 @@ var LookingGlass = class LookingGlass { | ||||
|                                                this._queueResize.bind(this)); | ||||
|  | ||||
|         this._objInspector = new ObjInspector(this); | ||||
|         Main.uiGroup.add_actor(this._objInspector.actor); | ||||
|         this._objInspector.actor.hide(); | ||||
|         Main.uiGroup.add_actor(this._objInspector); | ||||
|         this._objInspector.hide(); | ||||
|  | ||||
|         let toolbar = new St.BoxLayout({ name: 'Toolbar' }); | ||||
|         this.actor.add_actor(toolbar); | ||||
|         this.add_actor(toolbar); | ||||
|         let inspectIcon = new St.Icon({ icon_name: 'gtk-color-picker', | ||||
|                                         icon_size: 24 }); | ||||
|         toolbar.add_actor(inspectIcon); | ||||
| @@ -812,10 +826,10 @@ var LookingGlass = class LookingGlass { | ||||
|                 this._pushResult(`inspect(${Math.round(stageX)}, ${Math.round(stageY)})`, target); | ||||
|             }); | ||||
|             inspector.connect('closed', () => { | ||||
|                 this.actor.show(); | ||||
|                 this.show(); | ||||
|                 global.stage.set_key_focus(this._entry); | ||||
|             }); | ||||
|             this.actor.hide(); | ||||
|             this.hide(); | ||||
|             return Clutter.EVENT_STOP; | ||||
|         }); | ||||
|  | ||||
| @@ -837,7 +851,7 @@ var LookingGlass = class LookingGlass { | ||||
|  | ||||
|         let notebook = new Notebook(); | ||||
|         this._notebook = notebook; | ||||
|         this.actor.add(notebook.actor, { expand: true }); | ||||
|         this.add(notebook, { expand: true }); | ||||
|  | ||||
|         let emptyBox = new St.Bin(); | ||||
|         toolbar.add(emptyBox, { expand: true }); | ||||
| @@ -860,10 +874,10 @@ var LookingGlass = class LookingGlass { | ||||
|         this._entryArea.add(this._entry, { expand: true }); | ||||
|  | ||||
|         this._windowList = new WindowList(this); | ||||
|         notebook.appendPage('Windows', this._windowList.actor); | ||||
|         notebook.appendPage('Windows', this._windowList); | ||||
|  | ||||
|         this._extensions = new Extensions(this); | ||||
|         notebook.appendPage('Extensions', this._extensions.actor); | ||||
|         notebook.appendPage('Extensions', this._extensions); | ||||
|  | ||||
|         this._entry.clutter_text.connect('activate', (o, _e) => { | ||||
|             // Hide any completions we are currently showing | ||||
| @@ -881,7 +895,7 @@ var LookingGlass = class LookingGlass { | ||||
|             return true; | ||||
|         }); | ||||
|  | ||||
|         this._history = new History.HistoryManager({ gsettingsKey: HISTORY_KEY,  | ||||
|         this._history = new History.HistoryManager({ gsettingsKey: HISTORY_KEY, | ||||
|                                                      entry: this._entry.clutter_text }); | ||||
|  | ||||
|         this._autoComplete = new AutoComplete(this._entry); | ||||
| @@ -905,7 +919,7 @@ var LookingGlass = class LookingGlass { | ||||
|         // 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.actor.style = ` | ||||
|         this.style = ` | ||||
|             font-size: ${size}${unit}; | ||||
|             font-family: "${fontDesc.get_family()}";`; | ||||
|     } | ||||
| @@ -919,17 +933,14 @@ var LookingGlass = class LookingGlass { | ||||
|     } | ||||
|  | ||||
|     _pushResult(command, obj) { | ||||
|         let index = this._results.length + this._offset; | ||||
|         let index = this._resultsArea.get_n_children() + this._offset; | ||||
|         let result = new Result(this, CHEVRON + command, obj, index); | ||||
|         this._results.push(result); | ||||
|         this._resultsArea.add(result.actor); | ||||
|         this._resultsArea.add(result); | ||||
|         if (obj instanceof Clutter.Actor) | ||||
|             this.setBorderPaintTarget(obj); | ||||
|  | ||||
|         let children = this._resultsArea.get_children(); | ||||
|         if (children.length > this._maxItems) { | ||||
|             this._results.shift(); | ||||
|             children[0].destroy(); | ||||
|         if (this._resultsArea.get_n_children() > this._maxItems) { | ||||
|             this._resultsArea.get_first_child().destroy(); | ||||
|             this._offset++; | ||||
|         } | ||||
|         this._it = obj; | ||||
| @@ -1016,7 +1027,7 @@ var LookingGlass = class LookingGlass { | ||||
|  | ||||
|     getResult(idx) { | ||||
|         try { | ||||
|             return this._results[idx - this._offset].o; | ||||
|             return this._resultsArea.get_child_at_index(idx - this._offset).o; | ||||
|         } catch (e) { | ||||
|             throw new Error(`Unknown result at index ${idx}`); | ||||
|         } | ||||
| @@ -1041,15 +1052,15 @@ var LookingGlass = class LookingGlass { | ||||
|         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.actor.x = primary.x + (primary.width - myWidth) / 2; | ||||
|         this.x = primary.x + (primary.width - myWidth) / 2; | ||||
|         this._hiddenY = primary.y + Main.layoutManager.panelBox.height - myHeight; | ||||
|         this._targetY = this._hiddenY + myHeight; | ||||
|         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)); | ||||
|         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)); | ||||
|     } | ||||
|  | ||||
|     insertObject(obj) { | ||||
| @@ -1062,11 +1073,10 @@ var LookingGlass = class LookingGlass { | ||||
|     } | ||||
|  | ||||
|     // Handle key events which are relevant for all tabs of the LookingGlass | ||||
|     _globalKeyPressEvent(actor, event) { | ||||
|         let symbol = event.get_key_symbol(); | ||||
|         let modifierState = event.get_state(); | ||||
|     vfunc_key_press_event(keyPressEvent) { | ||||
|         let symbol = keyPressEvent.keyval; | ||||
|         if (symbol == Clutter.Escape) { | ||||
|             if (this._objInspector.actor.visible) { | ||||
|             if (this._objInspector.visible) { | ||||
|                 this._objInspector.close(); | ||||
|             } else { | ||||
|                 this.close(); | ||||
| @@ -1074,7 +1084,7 @@ var LookingGlass = class LookingGlass { | ||||
|             return Clutter.EVENT_STOP; | ||||
|         } | ||||
|         // Ctrl+PgUp and Ctrl+PgDown switches tabs in the notebook view | ||||
|         if (modifierState & Clutter.ModifierType.CONTROL_MASK) { | ||||
|         if (keyPressEvent.modifier_state & Clutter.ModifierType.CONTROL_MASK) { | ||||
|             if (symbol == Clutter.KEY_Page_Up) { | ||||
|                 this._notebook.prevTab(); | ||||
|             } else if (symbol == Clutter.KEY_Page_Down) { | ||||
| @@ -1092,16 +1102,16 @@ var LookingGlass = class LookingGlass { | ||||
|             return; | ||||
|  | ||||
|         this._notebook.selectIndex(0); | ||||
|         this.actor.show(); | ||||
|         this.show(); | ||||
|         this._open = true; | ||||
|         this._history.lastItem(); | ||||
|  | ||||
|         this.actor.remove_all_transitions(); | ||||
|         this.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.actor.ease({ | ||||
|         this.ease({ | ||||
|             y: this._targetY, | ||||
|             duration, | ||||
|             mode: Clutter.AnimationMode.EASE_OUT_QUAD | ||||
| @@ -1114,10 +1124,10 @@ var LookingGlass = class LookingGlass { | ||||
|         if (!this._open) | ||||
|             return; | ||||
|  | ||||
|         this._objInspector.actor.hide(); | ||||
|         this._objInspector.hide(); | ||||
|  | ||||
|         this._open = false; | ||||
|         this.actor.remove_all_transitions(); | ||||
|         this.remove_all_transitions(); | ||||
|  | ||||
|         this.setBorderPaintTarget(null); | ||||
|  | ||||
| @@ -1126,16 +1136,15 @@ var LookingGlass = class LookingGlass { | ||||
|         let settings = St.Settings.get(); | ||||
|         let duration = Math.min(LG_ANIMATION_TIME / settings.slow_down_factor, | ||||
|                                 LG_ANIMATION_TIME); | ||||
|         this.actor.ease({ | ||||
|         this.ease({ | ||||
|             y: this._hiddenY, | ||||
|             duration, | ||||
|             mode: Clutter.AnimationMode.EASE_OUT_QUAD, | ||||
|             onComplete: () => this.actor.hide() | ||||
|             onComplete: () => this.hide() | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     get isOpen() { | ||||
|         return this._open; | ||||
|     } | ||||
| }; | ||||
| Signals.addSignalMethods(LookingGlass.prototype); | ||||
| }); | ||||
|   | ||||
| @@ -264,7 +264,7 @@ var Magnifier = class Magnifier { | ||||
|         zoomRegion.setViewPort(viewPort); | ||||
|  | ||||
|         // We ignore the redundant width/height on the ROI | ||||
|         let fixedROI = new Object(roi); | ||||
|         let fixedROI = Object.create(roi); | ||||
|         fixedROI.width = viewPort.width / xMagFactor; | ||||
|         fixedROI.height = viewPort.height / yMagFactor; | ||||
|         zoomRegion.setROI(fixedROI); | ||||
| @@ -451,15 +451,11 @@ var Magnifier = class Magnifier { | ||||
|      * @clip:   Flag to indicate whether to clip the crosshairs. | ||||
|      */ | ||||
|     setCrosshairsClip(clip) { | ||||
|         if (clip) { | ||||
|             if (this._crossHairs) | ||||
|                 this._crossHairs.setClip(CROSSHAIRS_CLIP_SIZE); | ||||
|         } else { | ||||
|             // Setting no clipping on crosshairs means a zero sized clip | ||||
|             // rectangle. | ||||
|             if (this._crossHairs) | ||||
|                 this._crossHairs.setClip([0, 0]); | ||||
|         } | ||||
|         if (!this._crossHairs) | ||||
|             return; | ||||
|  | ||||
|         // Setting no clipping on crosshairs means a zero sized clip rectangle. | ||||
|         this._crossHairs.setClip(clip ? CROSSHAIRS_CLIP_SIZE : [0, 0]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -1294,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()).actor; | ||||
|         this._background = new Background.SystemBackground(); | ||||
|         mainGroup.add_actor(this._background); | ||||
|  | ||||
|         // Clone the group that contains all of UI on the screen.  This is the | ||||
| @@ -1591,8 +1587,9 @@ var ZoomRegion = class ZoomRegion { | ||||
|     } | ||||
| }; | ||||
|  | ||||
| var Crosshairs = class Crosshairs { | ||||
|     constructor() { | ||||
| var Crosshairs = GObject.registerClass( | ||||
| class Crosshairs extends Clutter.Actor { | ||||
|     _init() { | ||||
|  | ||||
|         // Set the group containing the crosshairs to three times the desktop | ||||
|         // size in case the crosshairs need to appear to be infinite in | ||||
| @@ -1600,7 +1597,7 @@ var Crosshairs = class Crosshairs { | ||||
|         let groupWidth = global.screen_width * 3; | ||||
|         let groupHeight = global.screen_height * 3; | ||||
|  | ||||
|         this._actor = new Clutter.Actor({ | ||||
|         super._init({ | ||||
|             clip_to_allocation: false, | ||||
|             width: groupWidth, | ||||
|             height: groupHeight | ||||
| @@ -1609,10 +1606,10 @@ var Crosshairs = class Crosshairs { | ||||
|         this._horizRightHair = new Clutter.Actor(); | ||||
|         this._vertTopHair = new Clutter.Actor(); | ||||
|         this._vertBottomHair = new Clutter.Actor(); | ||||
|         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.add_actor(this._horizLeftHair); | ||||
|         this.add_actor(this._horizRightHair); | ||||
|         this.add_actor(this._vertTopHair); | ||||
|         this.add_actor(this._vertBottomHair); | ||||
|         this._clipSize = [0, 0]; | ||||
|         this._clones = []; | ||||
|         this.reCenter(); | ||||
| @@ -1622,7 +1619,7 @@ var Crosshairs = class Crosshairs { | ||||
|     } | ||||
|  | ||||
|     _monitorsChanged() { | ||||
|         this._actor.set_size(global.screen_width * 3, global.screen_height * 3); | ||||
|         this.set_size(global.screen_width * 3, global.screen_height * 3); | ||||
|         this.reCenter(); | ||||
|     } | ||||
|  | ||||
| @@ -1643,12 +1640,15 @@ var Crosshairs = class Crosshairs { | ||||
|         if (zoomRegion && magnifiedMouse) { | ||||
|             let container = magnifiedMouse.get_parent(); | ||||
|             if (container) { | ||||
|                 crosshairsActor = this._actor; | ||||
|                 if (this._actor.get_parent() != null) { | ||||
|                     crosshairsActor = new Clutter.Clone({ source: this._actor }); | ||||
|                 crosshairsActor = this; | ||||
|                 if (this.get_parent() != null) { | ||||
|                     crosshairsActor = new Clutter.Clone({ source: this }); | ||||
|                     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 +1667,7 @@ var Crosshairs = class Crosshairs { | ||||
|      * child actor if it was just a clone of the crosshairs actor. | ||||
|      */ | ||||
|     removeFromParent(childActor) { | ||||
|         if (childActor == this._actor) | ||||
|         if (childActor == this) | ||||
|             childActor.get_parent().remove_actor(childActor); | ||||
|         else | ||||
|             childActor.destroy(); | ||||
| @@ -1777,28 +1777,6 @@ var Crosshairs = class Crosshairs { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 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 | ||||
| @@ -1807,7 +1785,7 @@ var Crosshairs = class Crosshairs { | ||||
|      * @clipSize:  Optional.  If present, an array of the form [width, height]. | ||||
|      */ | ||||
|     reCenter(clipSize) { | ||||
|         let [groupWidth, groupHeight] = this._actor.get_size(); | ||||
|         let [groupWidth, groupHeight] = this.get_size(); | ||||
|         let leftLength = this._horizLeftHair.get_width(); | ||||
|         let topLength = this._vertTopHair.get_height(); | ||||
|         let thickness = this._horizLeftHair.get_height(); | ||||
| @@ -1829,7 +1807,7 @@ var Crosshairs = class Crosshairs { | ||||
|         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.Keyboard(); | ||||
|     keyboard = new Keyboard.KeyboardManager(); | ||||
|     notificationDaemon = new NotificationDaemon.NotificationDaemon(); | ||||
|     windowAttentionHandler = new WindowAttentionHandler.WindowAttentionHandler(); | ||||
|     componentManager = new Components.ComponentManager(); | ||||
| @@ -229,7 +229,11 @@ function _initializeUI() { | ||||
|     EndSessionDialog.init(); | ||||
|  | ||||
|     // We're ready for the session manager to move to the next phase | ||||
|     Meta.register_with_session(); | ||||
|     GLib.idle_add(GLib.PRIORITY_DEFAULT, () => { | ||||
|         Shell.util_sd_notify(); | ||||
|         Meta.register_with_session(); | ||||
|         return GLib.SOURCE_REMOVE; | ||||
|     }); | ||||
|  | ||||
|     _startDate = new Date(); | ||||
|  | ||||
| @@ -258,6 +262,19 @@ 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"); | ||||
| @@ -386,7 +403,7 @@ function notify(msg, details) { | ||||
|     messageTray.add(source); | ||||
|     let notification = new MessageTray.Notification(source, msg, details); | ||||
|     notification.setTransient(true); | ||||
|     source.notify(notification); | ||||
|     source.showNotification(notification); | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -705,7 +722,6 @@ function queueDeferredWork(workId) { | ||||
|         _deferredWorkQueue.push(workId); | ||||
|     if (data.actor.mapped) { | ||||
|         _queueBeforeRedraw(workId); | ||||
|         return; | ||||
|     } else if (_deferredTimeoutId == 0) { | ||||
|         _deferredTimeoutId = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, DEFERRED_TIMEOUT_SECONDS, () => { | ||||
|             _runAllDeferredWork(); | ||||
|   | ||||
| @@ -1,7 +1,8 @@ | ||||
| const { Atk, Clutter, Gio, GLib, GObject, Meta, Pango, St } = imports.gi; | ||||
| /* exported MessageListSection */ | ||||
| const { Atk, Clutter, Gio, GLib, | ||||
|         GObject, Graphene, 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; | ||||
| @@ -31,13 +32,18 @@ function _fixMarkup(text, allowMarkup) { | ||||
|     return GLib.markup_escape_text(text, -1); | ||||
| } | ||||
|  | ||||
| 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 }); | ||||
| 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 | ||||
|         }); | ||||
|         this._linkColor = '#ccccff'; | ||||
|         this.actor.connect('style-changed', () => { | ||||
|             let [hasColor, color] = this.actor.get_theme_node().lookup_color('link-color', false); | ||||
|         this.connect('style-changed', () => { | ||||
|             let [hasColor, color] = this.get_theme_node().lookup_color('link-color', false); | ||||
|             if (hasColor) { | ||||
|                 let linkColor = color.to_string().substr(0, 7); | ||||
|                 if (linkColor != this._linkColor) { | ||||
| @@ -46,70 +52,75 @@ var URLHighlighter = class URLHighlighter { | ||||
|                 } | ||||
|             } | ||||
|         }); | ||||
|         this.actor.clutter_text.line_wrap = lineWrap; | ||||
|         this.actor.clutter_text.line_wrap_mode = Pango.WrapMode.WORD_CHAR; | ||||
|         this.clutter_text.line_wrap = lineWrap; | ||||
|         this.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; | ||||
|     } | ||||
|  | ||||
|             // 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; | ||||
|             } | ||||
|     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) | ||||
|             return Clutter.EVENT_PROPAGATE; | ||||
|         }); | ||||
|         this.actor.connect('motion-event', (actor, event) => { | ||||
|             if (!actor.visible || actor.get_paint_opacity() == 0) | ||||
|                 return Clutter.EVENT_PROPAGATE; | ||||
|  | ||||
|             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; | ||||
|         // 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; | ||||
|     } | ||||
|  | ||||
|             if (this._cursorChanged) { | ||||
|                 this._cursorChanged = false; | ||||
|                 global.display.set_cursor(Meta.Cursor.DEFAULT); | ||||
|             } | ||||
|     vfunc_button_release_event(buttonEvent) { | ||||
|         if (!this.visible || this.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) | ||||
|             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.actor.clutter_text.set_markup(text); | ||||
|         this.clutter_text.set_markup(text); | ||||
|         /* clutter_text.text contain text without markup */ | ||||
|         this._urls = Util.findUrls(this.actor.clutter_text.text); | ||||
|         this._urls = Util.findUrls(this.clutter_text.text); | ||||
|         this._highlightUrls(); | ||||
|     } | ||||
|  | ||||
| @@ -125,16 +136,15 @@ var URLHighlighter = class URLHighlighter { | ||||
|             pos = url.pos + url.url.length; | ||||
|         } | ||||
|         markup += this._text.substr(pos); | ||||
|         this.actor.clutter_text.set_markup(markup); | ||||
|         this.clutter_text.set_markup(markup); | ||||
|     } | ||||
|  | ||||
|     _findUrlAtPos(event) { | ||||
|         let success_; | ||||
|         let [x, y] = event.get_coords(); | ||||
|         [success_, x, y] = this.actor.transform_stage_point(x, y); | ||||
|         let { x, y } = event; | ||||
|         [, x, y] = this.transform_stage_point(x, y); | ||||
|         let findPos = -1; | ||||
|         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); | ||||
|         for (let i = 0; i < this.clutter_text.text.length; i++) { | ||||
|             let [, px, py, lineHeight] = this.clutter_text.position_to_coords(i); | ||||
|             if (py > y || py + lineHeight < y || x < px) | ||||
|                 continue; | ||||
|             findPos = i; | ||||
| @@ -147,7 +157,7 @@ var URLHighlighter = class URLHighlighter { | ||||
|         } | ||||
|         return -1; | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|  | ||||
| var ScaleLayout = GObject.registerClass( | ||||
| class ScaleLayout extends Clutter.BinLayout { | ||||
| @@ -283,21 +293,29 @@ var LabelExpanderLayout = GObject.registerClass({ | ||||
|     } | ||||
| }); | ||||
|  | ||||
| var Message = class Message { | ||||
|     constructor(title, body) { | ||||
|         this.expanded = false; | ||||
|  | ||||
| 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 | ||||
|         }); | ||||
|  | ||||
|         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.actor.set_child(vbox); | ||||
|         this.set_child(vbox); | ||||
|  | ||||
|         let hbox = new St.BoxLayout(); | ||||
|         vbox.add_actor(hbox); | ||||
| @@ -341,15 +359,14 @@ var Message = class Message { | ||||
|         contentBox.add_actor(this._bodyStack); | ||||
|  | ||||
|         this.bodyLabel = new URLHighlighter('', false, this._useBodyMarkup); | ||||
|         this.bodyLabel.actor.add_style_class_name('message-body'); | ||||
|         this._bodyStack.add_actor(this.bodyLabel.actor); | ||||
|         this.bodyLabel.add_style_class_name('message-body'); | ||||
|         this._bodyStack.add_actor(this.bodyLabel); | ||||
|         this.setBody(body); | ||||
|  | ||||
|         this._closeButton.connect('clicked', this.close.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)); | ||||
|         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)); | ||||
|         this._sync(); | ||||
|     } | ||||
|  | ||||
| @@ -435,7 +452,7 @@ var Message = class Message { | ||||
|         if (this._bodyStack.get_n_children() < 2) { | ||||
|             this._expandedLabel = new URLHighlighter(this._bodyText, | ||||
|                                                      true, this._useBodyMarkup); | ||||
|             this.setExpandedBody(this._expandedLabel.actor); | ||||
|             this.setExpandedBody(this._expandedLabel); | ||||
|         } | ||||
|  | ||||
|         if (animate) { | ||||
| @@ -488,19 +505,16 @@ var Message = class Message { | ||||
|     } | ||||
|  | ||||
|     _sync() { | ||||
|         let visible = this.actor.hover && this.canClose(); | ||||
|         let visible = this.hover && this.canClose(); | ||||
|         this._closeButton.opacity = visible ? 255 : 0; | ||||
|         this._closeButton.reactive = visible; | ||||
|     } | ||||
|  | ||||
|     _onClicked() { | ||||
|     } | ||||
|  | ||||
|     _onDestroy() { | ||||
|     } | ||||
|  | ||||
|     _onKeyPressed(a, event) { | ||||
|         let keysym = event.get_key_symbol(); | ||||
|     vfunc_key_press_event(keyEvent) { | ||||
|         let keysym = keyEvent.keyval; | ||||
|  | ||||
|         if (keysym == Clutter.KEY_Delete || | ||||
|             keysym == Clutter.KEY_KP_Delete) { | ||||
| @@ -509,37 +523,66 @@ var Message = class Message { | ||||
|         } | ||||
|         return Clutter.EVENT_PROPAGATE; | ||||
|     } | ||||
| }; | ||||
| Signals.addSignalMethods(Message.prototype); | ||||
| }); | ||||
|  | ||||
| var MessageListSection = class MessageListSection { | ||||
|     constructor() { | ||||
|         this.actor = new St.BoxLayout({ style_class: 'message-list-section', | ||||
|                                         clip_to_allocation: true, | ||||
|                                         x_expand: true, vertical: true }); | ||||
| 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 | ||||
|         }); | ||||
|  | ||||
|         this._list = new St.BoxLayout({ style_class: 'message-list-section-list', | ||||
|                                         vertical: true }); | ||||
|         this.actor.add_actor(this._list); | ||||
|         this.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.actor.connect('destroy', () => { | ||||
|         this.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(); | ||||
|     } | ||||
|  | ||||
|     _onKeyFocusIn(actor) { | ||||
|         this.emit('key-focus-in', actor); | ||||
|     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); | ||||
|     } | ||||
|  | ||||
|     get allowed() { | ||||
| @@ -558,58 +601,62 @@ var MessageListSection = class MessageListSection { | ||||
|     } | ||||
|  | ||||
|     addMessageAtIndex(message, index, animate) { | ||||
|         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); | ||||
|         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 }), | ||||
|         }); | ||||
|         obj.closeId = message.connect('close', () => { | ||||
|         listItem._connectionsIds = []; | ||||
|  | ||||
|         listItem._connectionsIds.push(message.connect('key-focus-in', | ||||
|             this._onKeyFocusIn.bind(this))); | ||||
|         listItem._connectionsIds.push(message.connect('close', () => { | ||||
|             this.removeMessage(message, true); | ||||
|         }); | ||||
|         })); | ||||
|         listItem._connectionsIds.push(message.connect('destroy', () => { | ||||
|             listItem._connectionsIds.forEach(id => message.disconnect(id)); | ||||
|             listItem.destroy(); | ||||
|         })); | ||||
|  | ||||
|         this._messages.set(message, obj); | ||||
|         obj.container.add_actor(message.actor); | ||||
|         this._list.insert_child_at_index(listItem, index); | ||||
|  | ||||
|         this._list.insert_child_at_index(obj.container, index); | ||||
|  | ||||
|         if (animate) | ||||
|             obj.container.ease({ | ||||
|         if (animate) { | ||||
|             listItem.set({ scale_x: 0, scale_y: 0 }); | ||||
|             listItem.ease({ | ||||
|                 scale_x: 1, | ||||
|                 scale_y: 1, | ||||
|                 duration: MESSAGE_ANIMATION_TIME, | ||||
|                 mode: Clutter.AnimationMode.EASE_OUT_QUAD | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     moveMessage(message, index, animate) { | ||||
|         let obj = this._messages.get(message); | ||||
|         if (!this._messages.includes(message)) | ||||
|             throw new Error(`Impossible to move the untracked message ${message}`); | ||||
|  | ||||
|         let listItem = message.get_parent(); | ||||
|  | ||||
|         if (!animate) { | ||||
|             this._list.set_child_at_index(obj.container, index); | ||||
|             this._list.set_child_at_index(listItem, index); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         let onComplete = () => { | ||||
|             this._list.set_child_at_index(obj.container, index); | ||||
|             obj.container.ease({ | ||||
|             this._list.set_child_at_index(listItem, index); | ||||
|             listItem.ease({ | ||||
|                 scale_x: 1, | ||||
|                 scale_y: 1, | ||||
|                 duration: MESSAGE_ANIMATION_TIME, | ||||
|                 mode: Clutter.AnimationMode.EASE_OUT_QUAD | ||||
|             }); | ||||
|         }; | ||||
|         obj.container.ease({ | ||||
|         listItem.ease({ | ||||
|             scale_x: 0, | ||||
|             scale_y: 0, | ||||
|             duration: MESSAGE_ANIMATION_TIME, | ||||
| @@ -619,33 +666,31 @@ var MessageListSection = class MessageListSection { | ||||
|     } | ||||
|  | ||||
|     removeMessage(message, animate) { | ||||
|         let obj = this._messages.get(message); | ||||
|         if (!this._messages.includes(message)) | ||||
|             throw new Error(`Impossible to remove the untracked message ${message}`); | ||||
|  | ||||
|         message.actor.disconnect(obj.destroyId); | ||||
|         message.actor.disconnect(obj.keyFocusId); | ||||
|         message.disconnect(obj.closeId); | ||||
|  | ||||
|         this._messages.delete(message); | ||||
|         let listItem = message.get_parent(); | ||||
|         listItem._connectionsIds.forEach(id => message.disconnect(id)); | ||||
|  | ||||
|         if (animate) { | ||||
|             obj.container.ease({ | ||||
|             listItem.ease({ | ||||
|                 scale_x: 0, | ||||
|                 scale_y: 0, | ||||
|                 duration: MESSAGE_ANIMATION_TIME, | ||||
|                 mode: Clutter.AnimationMode.EASE_OUT_QUAD, | ||||
|                 onComplete: () => { | ||||
|                     obj.container.destroy(); | ||||
|                     listItem.destroy(); | ||||
|                     global.sync_pointer(); | ||||
|                 } | ||||
|             }); | ||||
|         } else { | ||||
|             obj.container.destroy(); | ||||
|             listItem.destroy(); | ||||
|             global.sync_pointer(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     clear() { | ||||
|         let messages = [...this._messages.keys()].filter(msg => msg.canClose()); | ||||
|         let messages = this._messages.filter(msg => msg.canClose()); | ||||
|  | ||||
|         // If there are few messages, letting them all zoom out looks OK | ||||
|         if (messages.length < 2) { | ||||
| @@ -658,9 +703,8 @@ var MessageListSection = class MessageListSection { | ||||
|             let delay = MESSAGE_ANIMATION_TIME / Math.max(messages.length, 5); | ||||
|             for (let i = 0; i < messages.length; i++) { | ||||
|                 let message = messages[i]; | ||||
|                 let obj = this._messages.get(message); | ||||
|                 obj.container.ease({ | ||||
|                     anchor_x: this._list.width, | ||||
|                 message.get_parent().ease({ | ||||
|                     translation_x: this._list.width, | ||||
|                     opacity: 0, | ||||
|                     duration: MESSAGE_ANIMATION_TIME, | ||||
|                     delay: i * delay, | ||||
| @@ -671,33 +715,25 @@ var MessageListSection = class MessageListSection { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     _canClear() { | ||||
|         for (let message of this._messages.keys()) | ||||
|             if (message.canClose()) | ||||
|                 return true; | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     _shouldShow() { | ||||
|         return !this.empty; | ||||
|     } | ||||
|  | ||||
|     _sync() { | ||||
|         let empty = this._list.get_n_children() == 0; | ||||
|         let changed = this.empty !== empty; | ||||
|         this.empty = empty; | ||||
|         let messages = this._messages; | ||||
|         let empty = messages.length == 0; | ||||
|  | ||||
|         if (changed) | ||||
|             this.emit('empty-changed'); | ||||
|         if (this._empty != empty) { | ||||
|             this._empty = empty; | ||||
|             this.notify('empty'); | ||||
|         } | ||||
|  | ||||
|         let canClear = this._canClear(); | ||||
|         changed = this.canClear !== canClear; | ||||
|         this.canClear = canClear; | ||||
|         let canClear = messages.some(m => m.canClose()); | ||||
|         if (this._canClear != canClear) { | ||||
|             this._canClear = canClear; | ||||
|             this.notify('can-clear'); | ||||
|         } | ||||
|  | ||||
|         if (changed) | ||||
|             this.emit('can-clear-changed'); | ||||
|  | ||||
|         this.actor.visible = this.allowed && this._shouldShow(); | ||||
|         this.visible = this.allowed && this._shouldShow(); | ||||
|     } | ||||
| }; | ||||
| Signals.addSignalMethods(MessageListSection.prototype); | ||||
| }); | ||||
|   | ||||
| @@ -4,7 +4,6 @@ | ||||
|    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; | ||||
| @@ -134,72 +133,84 @@ 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 = 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); | ||||
|         }); | ||||
| 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), | ||||
|     } | ||||
|  | ||||
| }, class NotificationPolicy extends GObject.Object { | ||||
|     // Do nothing for the default policy. These methods are only useful for the | ||||
|     // GSettings policy. | ||||
|     store() { } | ||||
|  | ||||
|     destroy() { } | ||||
|  | ||||
|     get enable() { | ||||
|         return this._enable; | ||||
|     destroy() { | ||||
|         this.run_dispose(); | ||||
|     } | ||||
|  | ||||
|     get enableSound() { | ||||
|         return this._enableSound; | ||||
|         return this.enable_sound; | ||||
|     } | ||||
|  | ||||
|     get showBanners() { | ||||
|         return this._showBanners; | ||||
|         return this.show_banners; | ||||
|     } | ||||
|  | ||||
|     get forceExpanded() { | ||||
|         return this._forceExpanded; | ||||
|         return this.force_expanded; | ||||
|     } | ||||
|  | ||||
|     get showInLockScreen() { | ||||
|         return this._showInLockScreen; | ||||
|         return this.show_in_lock_screen; | ||||
|     } | ||||
|  | ||||
|     get detailsInLockScreen() { | ||||
|         return this._detailsInLockScreen; | ||||
|         return this.details_in_lock_screen; | ||||
|     } | ||||
| }; | ||||
| Signals.addSignalMethods(NotificationPolicy.prototype); | ||||
| }); | ||||
|  | ||||
| var NotificationGenericPolicy = | ||||
| class NotificationGenericPolicy extends NotificationPolicy { | ||||
|     constructor() { | ||||
|         super(); | ||||
| var NotificationGenericPolicy = GObject.registerClass({ | ||||
|     GTypeName: 'MessageTray_NotificationGenericPolicy' | ||||
| }, class NotificationGenericPolicy extends NotificationPolicy { | ||||
|     _init() { | ||||
|         super._init(); | ||||
|         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) { | ||||
|         this.emit('policy-changed', key); | ||||
|         if (this.constructor.find_property(key)) | ||||
|             this.notify(key); | ||||
|     } | ||||
|  | ||||
|     get showBanners() { | ||||
| @@ -209,12 +220,13 @@ class NotificationGenericPolicy extends NotificationPolicy { | ||||
|     get showInLockScreen() { | ||||
|         return this._masterSettings.get_boolean('show-in-lock-screen'); | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|  | ||||
| var NotificationApplicationPolicy = | ||||
| class NotificationApplicationPolicy extends NotificationPolicy { | ||||
|     constructor(id) { | ||||
|         super(); | ||||
| var NotificationApplicationPolicy = GObject.registerClass({ | ||||
|     GTypeName: 'MessageTray_NotificationApplicationPolicy' | ||||
| }, class NotificationApplicationPolicy extends NotificationPolicy { | ||||
|     _init(id) { | ||||
|         super._init(); | ||||
|  | ||||
|         this.id = id; | ||||
|         this._canonicalId = this._canonicalizeId(id); | ||||
| @@ -240,12 +252,13 @@ class NotificationApplicationPolicy extends NotificationPolicy { | ||||
|     destroy() { | ||||
|         this._masterSettings.run_dispose(); | ||||
|         this._settings.run_dispose(); | ||||
|  | ||||
|         super.destroy(); | ||||
|     } | ||||
|  | ||||
|     _changed(settings, key) { | ||||
|         this.emit('policy-changed', key); | ||||
|         if (key == 'enable') | ||||
|             this.emit('enable-changed'); | ||||
|         if (this.constructor.find_property(key)) | ||||
|             this.notify(key); | ||||
|     } | ||||
|  | ||||
|     _canonicalizeId(id) { | ||||
| @@ -279,7 +292,7 @@ class NotificationApplicationPolicy extends NotificationPolicy { | ||||
|     get detailsInLockScreen() { | ||||
|         return this._settings.get_boolean('details-in-lock-screen'); | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|  | ||||
| // Notification: | ||||
| // @source: the notification's Source | ||||
| @@ -335,13 +348,27 @@ class NotificationApplicationPolicy extends NotificationPolicy { | ||||
| // event sound is played when the notification is shown (if the policy for | ||||
| // @source allows playing sounds). | ||||
| // | ||||
| // [1] https://developer.gnome.org/notification-spec/#markup  | ||||
| var Notification = class Notification { | ||||
|     constructor(source, title, banner, params) { | ||||
| // [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(); | ||||
|  | ||||
|         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; | ||||
| @@ -353,6 +380,7 @@ var Notification = class Notification { | ||||
|         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 | ||||
| @@ -422,7 +450,7 @@ var Notification = class Notification { | ||||
|         if (this._acknowledged == v) | ||||
|             return; | ||||
|         this._acknowledged = v; | ||||
|         this.emit('acknowledged-changed'); | ||||
|         this.notify('acknowledged'); | ||||
|     } | ||||
|  | ||||
|     setUrgency(urgency) { | ||||
| @@ -431,6 +459,15 @@ var Notification = class Notification { | ||||
|  | ||||
|     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) { | ||||
| @@ -472,23 +509,30 @@ var Notification = class Notification { | ||||
|  | ||||
|     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 = | ||||
| class NotificationBanner extends Calendar.NotificationMessage { | ||||
|     constructor(notification) { | ||||
|         super(notification); | ||||
| var NotificationBanner = GObject.registerClass({ | ||||
|     Signals: { | ||||
|         'done-displaying': {}, | ||||
|         'unfocused': {}, | ||||
|     } | ||||
| }, class NotificationBanner extends Calendar.NotificationMessage { | ||||
|     _init(notification) { | ||||
|         super._init(notification); | ||||
|  | ||||
|         this.actor.can_focus = false; | ||||
|         this.actor.add_style_class_name('notification-banner'); | ||||
|         this.can_focus = false; | ||||
|         this.add_style_class_name('notification-banner'); | ||||
|  | ||||
|         this._buttonBox = null; | ||||
|  | ||||
| @@ -575,7 +619,7 @@ class NotificationBanner extends Calendar.NotificationMessage { | ||||
|  | ||||
|         return this.addButton(button, callback); | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|  | ||||
| var SourceActor = GObject.registerClass( | ||||
| class SourceActor extends St.Widget { | ||||
| @@ -640,7 +684,7 @@ class SourceActorWithLabel extends SourceActor { | ||||
|  | ||||
|         this.add_actor(this._counterBin); | ||||
|  | ||||
|         this._countUpdatedId = this._source.connect('count-updated', this._updateCount.bind(this)); | ||||
|         this._countUpdatedId = this._source.connect('notify::count', this._updateCount.bind(this)); | ||||
|         this._updateCount(); | ||||
|  | ||||
|         this.connect('destroy', () => { | ||||
| @@ -688,11 +732,34 @@ class SourceActorWithLabel extends SourceActor { | ||||
|     } | ||||
| }); | ||||
|  | ||||
| var Source = class Source { | ||||
|     constructor(title, iconName) { | ||||
| 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 }); | ||||
|  | ||||
|         this.SOURCE_ICON_SIZE = 48; | ||||
|  | ||||
|         this.title = title; | ||||
|         this.iconName = iconName; | ||||
|  | ||||
|         this.isChat = false; | ||||
| @@ -727,7 +794,7 @@ var Source = class Source { | ||||
|     } | ||||
|  | ||||
|     countUpdated() { | ||||
|         this.emit('count-updated'); | ||||
|         super.notify('count'); | ||||
|     } | ||||
|  | ||||
|     _createPolicy() { | ||||
| @@ -735,13 +802,17 @@ var Source = class Source { | ||||
|     } | ||||
|  | ||||
|     get narrowestPrivacyScope() { | ||||
|         return this.notifications.every(n => n.privacyScope == PrivacyScope.SYSTEM) ? PrivacyScope.SYSTEM | ||||
|                                                                                     : PrivacyScope.USER; | ||||
|         return this.notifications.every(n => n.privacyScope == PrivacyScope.SYSTEM) | ||||
|             ? PrivacyScope.SYSTEM | ||||
|             : PrivacyScope.USER; | ||||
|     } | ||||
|  | ||||
|     setTitle(newTitle) { | ||||
|         if (this.title == newTitle) | ||||
|             return; | ||||
|  | ||||
|         this.title = newTitle; | ||||
|         this.emit('title-changed'); | ||||
|         this.notify('title'); | ||||
|     } | ||||
|  | ||||
|     createBanner(notification) { | ||||
| @@ -766,10 +837,10 @@ var Source = class Source { | ||||
|             return; | ||||
|  | ||||
|         this.notifications.splice(index, 1); | ||||
|         this.countUpdated(); | ||||
|  | ||||
|         if (this.notifications.length == 0) | ||||
|             this.destroy(); | ||||
|  | ||||
|         this.countUpdated(); | ||||
|     } | ||||
|  | ||||
|     pushNotification(notification) { | ||||
| @@ -780,24 +851,39 @@ var Source = class Source { | ||||
|             this.notifications.shift().destroy(NotificationDestroyedReason.EXPIRED); | ||||
|  | ||||
|         notification.connect('destroy', this._onNotificationDestroy.bind(this)); | ||||
|         notification.connect('acknowledged-changed', this.countUpdated.bind(this)); | ||||
|         notification.connect('notify::acknowledged', this.countUpdated.bind(this)); | ||||
|         this.notifications.push(notification); | ||||
|         this.emit('notification-added', notification); | ||||
|  | ||||
|         this.countUpdated(); | ||||
|     } | ||||
|  | ||||
|     notify(notification) { | ||||
|     showNotification(notification) { | ||||
|         notification.acknowledged = false; | ||||
|         this.pushNotification(notification); | ||||
|  | ||||
|         if (this.policy.showBanners || notification.urgency == Urgency.CRITICAL) { | ||||
|             this.emit('notify', notification); | ||||
|             this.emit('notification-show', 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(); | ||||
|  | ||||
| @@ -808,6 +894,8 @@ var Source = class Source { | ||||
|             notifications[i].destroy(reason); | ||||
|  | ||||
|         this.emit('destroy', reason); | ||||
|  | ||||
|         this.run_dispose(); | ||||
|     } | ||||
|  | ||||
|     iconUpdated() { | ||||
| @@ -822,14 +910,23 @@ var Source = class Source { | ||||
|         for (let i = this.notifications.length - 1; i >= 0; i--) | ||||
|             if (!this.notifications[i].resident) | ||||
|                 this.notifications[i].destroy(); | ||||
|  | ||||
|         this.countUpdated(); | ||||
|     } | ||||
| }; | ||||
| Signals.addSignalMethods(Source.prototype); | ||||
| }); | ||||
|  | ||||
| var MessageTray = GObject.registerClass({ | ||||
|     Signals: { | ||||
|         'queue-changed': {}, | ||||
|         'source-added': { param_types: [Source.$gtype] }, | ||||
|         'source-removed': { param_types: [Source.$gtype] }, | ||||
|     } | ||||
| }, class MessageTray extends St.Widget { | ||||
|     _init() { | ||||
|         super._init({ | ||||
|             visible: false, | ||||
|             clip_to_allocation: true, | ||||
|             layout_manager: new Clutter.BinLayout() | ||||
|         }); | ||||
|  | ||||
| var MessageTray = class MessageTray { | ||||
|     constructor() { | ||||
|         this._presence = new GnomeSession.Presence((proxy, _error) => { | ||||
|             this._onStatusChanged(proxy.status); | ||||
|         }); | ||||
| @@ -846,18 +943,15 @@ var MessageTray = class MessageTray { | ||||
|             // so fix up Clutter's view of the pointer position in | ||||
|             // that case. | ||||
|             let related = ev.get_related(); | ||||
|             if (!related || this.actor.contains(related)) | ||||
|             if (!related || this.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.actor.add_constraint(constraint); | ||||
|         this.add_constraint(constraint); | ||||
|  | ||||
|         this._bannerBin = new St.Widget({ name: 'notification-container', | ||||
|                                           reactive: true, | ||||
| @@ -871,7 +965,7 @@ var MessageTray = class MessageTray { | ||||
|                                 this._onNotificationKeyRelease.bind(this)); | ||||
|         this._bannerBin.connect('notify::hover', | ||||
|                                 this._onNotificationHoverChanged.bind(this)); | ||||
|         this.actor.add_actor(this._bannerBin); | ||||
|         this.add_actor(this._bannerBin); | ||||
|  | ||||
|         this._notificationFocusGrabber = new FocusGrabber(this._bannerBin); | ||||
|         this._notificationQueue = []; | ||||
| @@ -900,7 +994,7 @@ var MessageTray = class MessageTray { | ||||
|         this._notificationTimeoutId = 0; | ||||
|         this._notificationRemoved = false; | ||||
|  | ||||
|         Main.layoutManager.addChrome(this.actor, { affectsInputRegion: false }); | ||||
|         Main.layoutManager.addChrome(this, { affectsInputRegion: false }); | ||||
|         Main.layoutManager.trackChrome(this._bannerBin, { affectsInputRegion: true }); | ||||
|  | ||||
|         global.display.connect('in-fullscreen-changed', this._updateState.bind(this)); | ||||
| @@ -943,11 +1037,11 @@ var MessageTray = class MessageTray { | ||||
|     } | ||||
|  | ||||
|     _onDragBegin() { | ||||
|         Shell.util_set_hidden_from_pick(this.actor, true); | ||||
|         Shell.util_set_hidden_from_pick(this, true); | ||||
|     } | ||||
|  | ||||
|     _onDragEnd() { | ||||
|         Shell.util_set_hidden_from_pick(this.actor, false); | ||||
|         Shell.util_set_hidden_from_pick(this, false); | ||||
|     } | ||||
|  | ||||
|     get bannerAlignment() { | ||||
| @@ -996,22 +1090,22 @@ var MessageTray = class MessageTray { | ||||
|         // Register that we got a notification for this source | ||||
|         source.policy.store(); | ||||
|  | ||||
|         source.policy.connect('enable-changed', () => { | ||||
|         source.policy.connect('notify::enable', () => { | ||||
|             this._onSourceEnableChanged(source.policy, source); | ||||
|         }); | ||||
|         source.policy.connect('policy-changed', this._updateState.bind(this)); | ||||
|         source.policy.connect('notify', this._updateState.bind(this)); | ||||
|         this._onSourceEnableChanged(source.policy, source); | ||||
|     } | ||||
|  | ||||
|     _addSource(source) { | ||||
|         let obj = { | ||||
|             notifyId: 0, | ||||
|             showId: 0, | ||||
|             destroyId: 0, | ||||
|         }; | ||||
|  | ||||
|         this._sources.set(source, obj); | ||||
|  | ||||
|         obj.notifyId = source.connect('notify', this._onNotify.bind(this)); | ||||
|         obj.showId = source.connect('notification-show', this._onNotificationShow.bind(this)); | ||||
|         obj.destroyId = source.connect('destroy', this._onSourceDestroy.bind(this)); | ||||
|  | ||||
|         this.emit('source-added', source); | ||||
| @@ -1021,7 +1115,7 @@ var MessageTray = class MessageTray { | ||||
|         let obj = this._sources.get(source); | ||||
|         this._sources.delete(source); | ||||
|  | ||||
|         source.disconnect(obj.notifyId); | ||||
|         source.disconnect(obj.showId); | ||||
|         source.disconnect(obj.destroyId); | ||||
|  | ||||
|         this.emit('source-removed', source); | ||||
| @@ -1062,7 +1156,7 @@ var MessageTray = class MessageTray { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     _onNotify(source, notification) { | ||||
|     _onNotificationShow(_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. | ||||
| @@ -1194,7 +1288,7 @@ var MessageTray = class MessageTray { | ||||
|     // at the present time. | ||||
|     _updateState() { | ||||
|         let hasMonitor = Main.layoutManager.primaryMonitor != null; | ||||
|         this.actor.visible = !this._bannerBlocked && hasMonitor && this._banner != null; | ||||
|         this.visible = !this._bannerBlocked && hasMonitor && this._banner != null; | ||||
|         if (this._bannerBlocked || !hasMonitor) | ||||
|             return; | ||||
|  | ||||
| @@ -1274,11 +1368,11 @@ var MessageTray = class MessageTray { | ||||
|             this._updateState(); | ||||
|         }); | ||||
|  | ||||
|         this._bannerBin.add_actor(this._banner.actor); | ||||
|         this._bannerBin.add_actor(this._banner); | ||||
|  | ||||
|         this._bannerBin.opacity = 0; | ||||
|         this._bannerBin.y = -this._banner.actor.height; | ||||
|         this.actor.show(); | ||||
|         this._bannerBin.y = -this._banner.height; | ||||
|         this.show(); | ||||
|  | ||||
|         Meta.disable_unredirect_for_display(global.display); | ||||
|         this._updateShowingNotification(); | ||||
| @@ -1425,16 +1519,16 @@ var MessageTray = class MessageTray { | ||||
|     _hideNotificationCompleted() { | ||||
|         let notification = this._notification; | ||||
|         this._notification = null; | ||||
|         if (notification.isTransient) | ||||
|         if (!this._notificationRemoved && notification.isTransient) | ||||
|             notification.destroy(NotificationDestroyedReason.EXPIRED); | ||||
|  | ||||
|         this._pointerInNotification = false; | ||||
|         this._notificationRemoved = false; | ||||
|         Meta.enable_unredirect_for_display(global.display); | ||||
|  | ||||
|         this._banner.actor.destroy(); | ||||
|         this._banner.destroy(); | ||||
|         this._banner = null; | ||||
|         this.actor.hide(); | ||||
|         this.hide(); | ||||
|     } | ||||
|  | ||||
|     _expandActiveNotification() { | ||||
| @@ -1456,15 +1550,15 @@ var MessageTray = class MessageTray { | ||||
|     _ensureBannerFocused() { | ||||
|         this._notificationFocusGrabber.grabFocus(); | ||||
|     } | ||||
| }; | ||||
| Signals.addSignalMethods(MessageTray.prototype); | ||||
| }); | ||||
|  | ||||
| var SystemNotificationSource = class SystemNotificationSource extends Source { | ||||
|     constructor() { | ||||
|         super(_("System Information"), 'dialog-information-symbolic'); | ||||
| var SystemNotificationSource = GObject.registerClass( | ||||
| class SystemNotificationSource extends Source { | ||||
|     _init() { | ||||
|         super._init(_("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.show(); | ||||
|             this._lightbox.lightOn(); | ||||
|         this.opacity = 0; | ||||
|         this.show(); | ||||
|         this.ease({ | ||||
| @@ -253,7 +253,7 @@ var ModalDialog = GObject.registerClass({ | ||||
|             opacity: 0, | ||||
|             duration: FADE_OUT_DIALOG_TIME, | ||||
|             mode: Clutter.AnimationMode.EASE_OUT_QUAD, | ||||
|             onComplete: () => this.state = State.FADED_OUT | ||||
|             onComplete: () => (this.state = State.FADED_OUT) | ||||
|         }); | ||||
|     } | ||||
| }); | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| /* exported MediaSection */ | ||||
| const { Gio, Shell, St } = imports.gi; | ||||
| const { Gio, GObject, Shell, St } = imports.gi; | ||||
| const Signals = imports.signals; | ||||
|  | ||||
| const Calendar = imports.ui.calendar; | ||||
| @@ -19,9 +19,10 @@ const MprisPlayerProxy = Gio.DBusProxy.makeProxyWrapper(MprisPlayerIface); | ||||
|  | ||||
| const MPRIS_PLAYER_PREFIX = 'org.mpris.MediaPlayer2.'; | ||||
|  | ||||
| var MediaMessage = class MediaMessage extends MessageList.Message { | ||||
|     constructor(player) { | ||||
|         super('', ''); | ||||
| var MediaMessage = GObject.registerClass( | ||||
| class MediaMessage extends MessageList.Message { | ||||
|     _init(player) { | ||||
|         super._init('', ''); | ||||
|  | ||||
|         this._player = player; | ||||
|  | ||||
| @@ -48,7 +49,7 @@ var MediaMessage = class MediaMessage extends MessageList.Message { | ||||
|         this._update(); | ||||
|     } | ||||
|  | ||||
|     _onClicked() { | ||||
|     vfunc_clicked() { | ||||
|         this._player.raise(); | ||||
|         Main.panel.closeCalendar(); | ||||
|     } | ||||
| @@ -71,14 +72,15 @@ var MediaMessage = class MediaMessage extends MessageList.Message { | ||||
|         } | ||||
|  | ||||
|         let isPlaying = this._player.status == 'Playing'; | ||||
|         let iconName = isPlaying ? 'media-playback-pause-symbolic' | ||||
|                                  : 'media-playback-start-symbolic'; | ||||
|         let iconName = isPlaying | ||||
|             ? 'media-playback-pause-symbolic' | ||||
|             : 'media-playback-start-symbolic'; | ||||
|         this._playPauseButton.child.icon_name = iconName; | ||||
|  | ||||
|         this._updateNavButton(this._prevButton, this._player.canGoPrevious); | ||||
|         this._updateNavButton(this._nextButton, this._player.canGoNext); | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|  | ||||
| var MprisPlayer = class MprisPlayer { | ||||
|     constructor(busName) { | ||||
| @@ -193,9 +195,10 @@ var MprisPlayer = class MprisPlayer { | ||||
| }; | ||||
| Signals.addSignalMethods(MprisPlayer.prototype); | ||||
|  | ||||
| var MediaSection = class MediaSection extends MessageList.MessageListSection { | ||||
|     constructor() { | ||||
|         super(); | ||||
| var MediaSection = GObject.registerClass( | ||||
| class MediaSection extends MessageList.MessageListSection { | ||||
|     _init() { | ||||
|         super._init(); | ||||
|  | ||||
|         this._players = new Map(); | ||||
|  | ||||
| @@ -246,4 +249,4 @@ var MediaSection = 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, Shell, St } = imports.gi; | ||||
| const { GdkPixbuf, Gio, GLib, GObject, Shell, St } = imports.gi; | ||||
|  | ||||
| const Config = imports.misc.config; | ||||
| const Main = imports.ui.main; | ||||
| @@ -346,8 +346,9 @@ var FdoNotificationDaemon = class FdoNotificationDaemon { | ||||
|         notification.setTransient(!!hints['transient']); | ||||
|  | ||||
|         let privacyScope = (hints['x-gnome-privacy-scope'] || 'user'); | ||||
|         notification.setPrivacyScope(privacyScope == 'system' ? MessageTray.PrivacyScope.SYSTEM | ||||
|                                                               : MessageTray.PrivacyScope.USER); | ||||
|         notification.setPrivacyScope(privacyScope == 'system' | ||||
|             ? MessageTray.PrivacyScope.SYSTEM | ||||
|             : MessageTray.PrivacyScope.USER); | ||||
|  | ||||
|         let sourceGIcon = source.useNotificationIcon ? gicon : null; | ||||
|         source.processNotification(notification, sourceGIcon); | ||||
| @@ -411,10 +412,10 @@ var FdoNotificationDaemon = class FdoNotificationDaemon { | ||||
|     } | ||||
| }; | ||||
|  | ||||
| var FdoNotificationDaemonSource = | ||||
| var FdoNotificationDaemonSource = GObject.registerClass( | ||||
| class FdoNotificationDaemonSource extends MessageTray.Source { | ||||
|     constructor(title, pid, sender, appId) { | ||||
|         super(title); | ||||
|     _init(title, pid, sender, appId) { | ||||
|         super._init(title); | ||||
|  | ||||
|         this.pid = pid; | ||||
|         this.app = this._getApp(appId); | ||||
| @@ -463,7 +464,7 @@ class FdoNotificationDaemonSource extends MessageTray.Source { | ||||
|         if (notification.resident && this.app && tracker.focus_app == this.app) | ||||
|             this.pushNotification(notification); | ||||
|         else | ||||
|             this.notify(notification); | ||||
|             this.showNotification(notification); | ||||
|     } | ||||
|  | ||||
|     _getApp(appId) { | ||||
| @@ -525,7 +526,7 @@ class FdoNotificationDaemonSource extends MessageTray.Source { | ||||
|             return null; | ||||
|         } | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|  | ||||
| const PRIORITY_URGENCY_MAP = { | ||||
|     low: MessageTray.Urgency.LOW, | ||||
| @@ -534,28 +535,29 @@ const PRIORITY_URGENCY_MAP = { | ||||
|     urgent: MessageTray.Urgency.CRITICAL | ||||
| }; | ||||
|  | ||||
| var GtkNotificationDaemonNotification = | ||||
| var GtkNotificationDaemonNotification = GObject.registerClass( | ||||
| class GtkNotificationDaemonNotification extends MessageTray.Notification { | ||||
|     constructor(source, notification) { | ||||
|         super(source); | ||||
|     _init(source, notification) { | ||||
|         super._init(source); | ||||
|         this._serialized = GLib.Variant.new('a{sv}', notification); | ||||
|  | ||||
|         let { "title": title, | ||||
|               "body": body, | ||||
|               "icon": gicon, | ||||
|               "urgent": urgent, | ||||
|               "priority": priority, | ||||
|               "buttons": buttons, | ||||
|         let { title, | ||||
|               body, | ||||
|               icon: gicon, | ||||
|               urgent, | ||||
|               priority, | ||||
|               buttons, | ||||
|               "default-action": defaultAction, | ||||
|               "default-action-target": defaultActionTarget, | ||||
|               "timestamp": time } = notification; | ||||
|               timestamp: time } = notification; | ||||
|  | ||||
|         if (priority) { | ||||
|             let urgency = PRIORITY_URGENCY_MAP[priority.unpack()]; | ||||
|             this.setUrgency(urgency != undefined ? urgency : MessageTray.Urgency.NORMAL); | ||||
|         } else if (urgent) { | ||||
|             this.setUrgency(urgent.unpack() ? MessageTray.Urgency.CRITICAL | ||||
|                             : MessageTray.Urgency.NORMAL); | ||||
|             this.setUrgency(urgent.unpack() | ||||
|                 ? MessageTray.Urgency.CRITICAL | ||||
|                 : MessageTray.Urgency.NORMAL); | ||||
|         } else { | ||||
|             this.setUrgency(MessageTray.Urgency.NORMAL); | ||||
|         } | ||||
| @@ -588,8 +590,8 @@ class GtkNotificationDaemonNotification extends MessageTray.Notification { | ||||
|     } | ||||
|  | ||||
|     _onButtonClicked(button) { | ||||
|         let { 'action': action, 'target': actionTarget } = button; | ||||
|         this._activateAction(action.unpack(), actionTarget); | ||||
|         let { action, target } = button; | ||||
|         this._activateAction(action.unpack(), target); | ||||
|     } | ||||
|  | ||||
|     activate() { | ||||
| @@ -600,7 +602,7 @@ class GtkNotificationDaemonNotification extends MessageTray.Notification { | ||||
|     serialize() { | ||||
|         return this._serialized; | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|  | ||||
| const FdoApplicationIface = loadInterfaceXML('org.freedesktop.Application'); | ||||
| const FdoApplicationProxy = Gio.DBusProxy.makeProxyWrapper(FdoApplicationIface); | ||||
| @@ -616,9 +618,9 @@ function getPlatformData() { | ||||
|  | ||||
| function InvalidAppError() {} | ||||
|  | ||||
| var GtkNotificationDaemonAppSource =  | ||||
| var GtkNotificationDaemonAppSource = GObject.registerClass( | ||||
| class GtkNotificationDaemonAppSource extends MessageTray.Source { | ||||
|     constructor(appId) { | ||||
|     _init(appId) { | ||||
|         let objectPath = objectPathFromAppId(appId); | ||||
|         if (!GLib.Variant.is_object_path(objectPath)) | ||||
|             throw new InvalidAppError(); | ||||
| @@ -627,7 +629,7 @@ class GtkNotificationDaemonAppSource extends MessageTray.Source { | ||||
|         if (!app) | ||||
|             throw new InvalidAppError(); | ||||
|  | ||||
|         super(app.get_name()); | ||||
|         super._init(app.get_name()); | ||||
|  | ||||
|         this._appId = appId; | ||||
|         this._app = app; | ||||
| @@ -688,7 +690,7 @@ class GtkNotificationDaemonAppSource extends MessageTray.Source { | ||||
|         this._notifications[notificationId] = notification; | ||||
|  | ||||
|         if (showBanner) | ||||
|             this.notify(notification); | ||||
|             this.showNotification(notification); | ||||
|         else | ||||
|             this.pushNotification(notification); | ||||
|  | ||||
| @@ -714,7 +716,7 @@ class GtkNotificationDaemonAppSource extends MessageTray.Source { | ||||
|         } | ||||
|         return [this._appId, notifications]; | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|  | ||||
| const GtkNotificationsIface = loadInterfaceXML('org.gtk.Notifications'); | ||||
|  | ||||
| @@ -740,7 +742,7 @@ var GtkNotificationDaemon = class GtkNotificationDaemon { | ||||
|             delete this._sources[appId]; | ||||
|             this._saveNotifications(); | ||||
|         }); | ||||
|         source.connect('count-updated', this._saveNotifications.bind(this)); | ||||
|         source.connect('notify::count', this._saveNotifications.bind(this)); | ||||
|         Main.messageTray.add(source); | ||||
|         this._sources[appId] = source; | ||||
|         return source; | ||||
|   | ||||
| @@ -1,30 +1,33 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported OsdMonitorLabeler */ | ||||
|  | ||||
| const { Clutter, Gio, Meta, St } = imports.gi; | ||||
| const { Clutter, Gio, GObject, Meta, St } = imports.gi; | ||||
|  | ||||
| const Main = imports.ui.main; | ||||
|  | ||||
| var OsdMonitorLabel = class { | ||||
|     constructor(monitor, label) { | ||||
|         this._actor = new St.Widget({ x_expand: true, | ||||
|                                       y_expand: true }); | ||||
| var OsdMonitorLabel = GObject.registerClass( | ||||
| class OsdMonitorLabel extends St.Widget { | ||||
|     _init(monitor, label) { | ||||
|         super._init({ x_expand: true, y_expand: true }); | ||||
|  | ||||
|         this._monitor = monitor; | ||||
|  | ||||
|         this._box = new St.BoxLayout({ style_class: 'osd-window', | ||||
|                                        vertical: true }); | ||||
|         this._actor.add_actor(this._box); | ||||
|         this.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._actor); | ||||
|         Main.uiGroup.set_child_above_sibling(this._actor, null); | ||||
|         Main.uiGroup.add_child(this); | ||||
|         Main.uiGroup.set_child_above_sibling(this, null); | ||||
|         this._position(); | ||||
|  | ||||
|         Meta.disable_unredirect_for_display(global.display); | ||||
|         this.connect('destroy', () => { | ||||
|             Meta.enable_unredirect_for_display(global.display); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     _position() { | ||||
| @@ -37,12 +40,7 @@ var OsdMonitorLabel = class { | ||||
|  | ||||
|         this._box.y = workArea.y; | ||||
|     } | ||||
|  | ||||
|     destroy() { | ||||
|         this._actor.destroy(); | ||||
|         Meta.enable_unredirect_for_display(global.display); | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|  | ||||
| var OsdMonitorLabeler = class { | ||||
|     constructor() { | ||||
|   | ||||
| @@ -41,22 +41,25 @@ class OsdWindowConstraint extends Clutter.Constraint { | ||||
|     } | ||||
| }); | ||||
|  | ||||
| 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 }); | ||||
| 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 | ||||
|         }); | ||||
|  | ||||
|         this._monitorIndex = monitorIndex; | ||||
|         let constraint = new Layout.MonitorConstraint({ index: monitorIndex }); | ||||
|         this.actor.add_constraint(constraint); | ||||
|         this.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.actor.add_actor(this._box); | ||||
|         this.add_actor(this._box); | ||||
|  | ||||
|         this._icon = new St.Icon(); | ||||
|         this._box.add(this._icon, { expand: true }); | ||||
| @@ -73,7 +76,7 @@ var OsdWindow = class { | ||||
|         this._hideTimeoutId = 0; | ||||
|         this._reset(); | ||||
|  | ||||
|         this.actor.connect('destroy', this._onDestroy.bind(this)); | ||||
|         this.connect('destroy', this._onDestroy.bind(this)); | ||||
|  | ||||
|         this._monitorsChangedId = | ||||
|             Main.layoutManager.connect('monitors-changed', | ||||
| @@ -83,7 +86,7 @@ var OsdWindow = class { | ||||
|             themeContext.connect('notify::scale-factor', | ||||
|                                  this._relayout.bind(this)); | ||||
|         this._relayout(); | ||||
|         Main.uiGroup.add_child(this.actor); | ||||
|         Main.uiGroup.add_child(this); | ||||
|     } | ||||
|  | ||||
|     _onDestroy() { | ||||
| @@ -110,7 +113,7 @@ var OsdWindow = class { | ||||
|     setLevel(value) { | ||||
|         this._level.visible = (value != undefined); | ||||
|         if (value != undefined) { | ||||
|             if (this.actor.visible) | ||||
|             if (this.visible) | ||||
|                 this._level.ease_property('value', value, { | ||||
|                     mode: Clutter.AnimationMode.EASE_OUT_QUAD, | ||||
|                     duration: LEVEL_ANIMATION_TIME | ||||
| @@ -128,13 +131,13 @@ var OsdWindow = class { | ||||
|         if (!this._icon.gicon) | ||||
|             return; | ||||
|  | ||||
|         if (!this.actor.visible) { | ||||
|         if (!this.visible) { | ||||
|             Meta.disable_unredirect_for_display(global.display); | ||||
|             this.actor.show(); | ||||
|             this.actor.opacity = 0; | ||||
|             this.actor.get_parent().set_child_above_sibling(this.actor, null); | ||||
|             super.show(); | ||||
|             this.opacity = 0; | ||||
|             this.get_parent().set_child_above_sibling(this, null); | ||||
|  | ||||
|             this.actor.ease({ | ||||
|             this.ease({ | ||||
|                 opacity: 255, | ||||
|                 duration: FADE_TIME, | ||||
|                 mode: Clutter.AnimationMode.EASE_OUT_QUAD | ||||
| @@ -158,7 +161,7 @@ var OsdWindow = class { | ||||
|  | ||||
|     _hide() { | ||||
|         this._hideTimeoutId = 0; | ||||
|         this.actor.ease({ | ||||
|         this.ease({ | ||||
|             opacity: 0, | ||||
|             duration: FADE_TIME, | ||||
|             mode: Clutter.AnimationMode.EASE_OUT_QUAD, | ||||
| @@ -171,7 +174,7 @@ var OsdWindow = class { | ||||
|     } | ||||
|  | ||||
|     _reset() { | ||||
|         this.actor.hide(); | ||||
|         super.hide(); | ||||
|         this.setLabel(null); | ||||
|         this.setMaxLevel(null); | ||||
|         this.setLevel(null); | ||||
| @@ -193,7 +196,7 @@ var OsdWindow = class { | ||||
|         this._box.translation_y = Math.round(monitor.height / 4); | ||||
|         this._boxConstraint.minSize = popupSize; | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|  | ||||
| var OsdWindowManager = class { | ||||
|     constructor() { | ||||
| @@ -210,7 +213,7 @@ var OsdWindowManager = class { | ||||
|         } | ||||
|  | ||||
|         for (let i = Main.layoutManager.monitors.length; i < this._osdWindows.length; i++) { | ||||
|             this._osdWindows[i].actor.destroy(); | ||||
|             this._osdWindows[i].destroy(); | ||||
|             this._osdWindows[i] = null; | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported Overview */ | ||||
|  | ||||
| const { Clutter, GLib, Meta, Shell, St } = imports.gi; | ||||
| const { Clutter, GLib, GObject, Meta, Shell, St } = imports.gi; | ||||
| const Signals = imports.signals; | ||||
|  | ||||
| const Background = imports.ui.background; | ||||
| @@ -72,36 +72,108 @@ var ShellInfo = class { | ||||
|         if (undoCallback) | ||||
|             notification.addAction(_("Undo"), this._onUndoClicked.bind(this)); | ||||
|  | ||||
|         this._source.notify(notification); | ||||
|         this._source.showNotification(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._overviewCreated) | ||||
|         if (this._overview) | ||||
|             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 | ||||
| @@ -116,11 +188,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 | ||||
| @@ -129,9 +201,6 @@ 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 | ||||
| @@ -213,41 +282,12 @@ 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(); | ||||
|     } | ||||
| @@ -360,8 +400,12 @@ var Overview = class { | ||||
|             return null; | ||||
|  | ||||
|         let window = windows[0]; | ||||
|         let clone = new Clutter.Clone({ source: window, | ||||
|                                         x: window.x, y: window.y }); | ||||
|         let clone = new Clutter.Actor({ | ||||
|             source: window.content, | ||||
|             request_mode: Clutter.RequestMode.CONTENT_SIZE, | ||||
|             x: window.x, | ||||
|             y: window.y, | ||||
|         }); | ||||
|         clone.source.connect('destroy', () => { | ||||
|             clone.destroy(); | ||||
|         }); | ||||
| @@ -426,7 +470,7 @@ var Overview = class { | ||||
|  | ||||
|     focusSearch() { | ||||
|         this.show(); | ||||
|         this._searchEntry.grab_key_focus(); | ||||
|         this._overview.searchEntry.grab_key_focus(); | ||||
|     } | ||||
|  | ||||
|     fadeInDesktop() { | ||||
| @@ -452,7 +496,7 @@ var Overview = class { | ||||
|         this._desktopFade.show(); | ||||
|         this._desktopFade.ease({ | ||||
|             opacity: 0, | ||||
|             mode: Clutter.Animates.EASE_OUT_QUAD, | ||||
|             mode: Clutter.AnimationMode.EASE_OUT_QUAD, | ||||
|             duration: ANIMATION_TIME | ||||
|         }); | ||||
|     } | ||||
| @@ -464,11 +508,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 == 0 || | ||||
|         if (!this._activationTime || | ||||
|             GLib.get_monotonic_time() / GLib.USEC_PER_SEC - this._activationTime > OVERVIEW_ACTIVATION_TIMEOUT) | ||||
|             return true; | ||||
|         return false; | ||||
| @@ -478,7 +522,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) { | ||||
| @@ -520,12 +564,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); | ||||
| @@ -546,7 +590,7 @@ var Overview = class { | ||||
|     } | ||||
|  | ||||
|     _showDone() { | ||||
|         this.animationInProgress = false; | ||||
|         this._animationInProgress = false; | ||||
|         this._desktopFade.hide(); | ||||
|         this._coverPane.hide(); | ||||
|  | ||||
| @@ -586,11 +630,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(); | ||||
|  | ||||
| @@ -616,8 +660,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 | ||||
| @@ -633,14 +677,17 @@ var Overview = class { | ||||
|         if (this.isDummy) | ||||
|             return; | ||||
|  | ||||
|         if (this.visible) | ||||
|         if (this._visible) | ||||
|             this.hide(); | ||||
|         else | ||||
|             this.show(); | ||||
|     } | ||||
|  | ||||
|     getShowAppsButton() { | ||||
|         return this._dash.showAppsButton; | ||||
|         logError(new Error('Usage of Overview.\'getShowAppsButton\' is deprecated, ' + | ||||
|             'use \'dash.showAppsButton\' property instead')); | ||||
|  | ||||
|         return this.dash.showAppsButton; | ||||
|     } | ||||
| }; | ||||
| Signals.addSignalMethods(Overview.prototype); | ||||
|   | ||||
| @@ -14,8 +14,8 @@ var SIDE_CONTROLS_ANIMATION_TIME = 160; | ||||
| function getRtlSlideDirection(direction, actor) { | ||||
|     let rtl = (actor.text_direction == Clutter.TextDirection.RTL); | ||||
|     if (rtl) | ||||
|         direction = (direction == SlideDirection.LEFT) ? | ||||
|             SlideDirection.RIGHT : SlideDirection.LEFT; | ||||
|         direction = (direction == SlideDirection.LEFT) | ||||
|             ? SlideDirection.RIGHT : SlideDirection.LEFT; | ||||
|  | ||||
|     return direction; | ||||
| } | ||||
| @@ -67,8 +67,9 @@ var SlideLayout = GObject.registerClass({ | ||||
|         // flags only determine what to do if the allocated box is bigger | ||||
|         // than the actor's box. | ||||
|         let realDirection = getRtlSlideDirection(this._direction, child); | ||||
|         let alignX = (realDirection == SlideDirection.LEFT) ? (availWidth - natWidth) | ||||
|                                                             : (availWidth - natWidth * this._slideX); | ||||
|         let alignX = (realDirection == SlideDirection.LEFT) | ||||
|             ? availWidth - natWidth | ||||
|             : availWidth - natWidth * this._slideX; | ||||
|  | ||||
|         let actorBox = new Clutter.ActorBox(); | ||||
|         actorBox.x1 = box.x1 + alignX + this._translationX; | ||||
| @@ -117,18 +118,21 @@ var SlideLayout = GObject.registerClass({ | ||||
|     } | ||||
| }); | ||||
|  | ||||
| var SlidingControl = class { | ||||
|     constructor(params) { | ||||
| var SlidingControl = GObject.registerClass( | ||||
| class SlidingControl extends St.Widget { | ||||
|     _init(params) { | ||||
|         params = Params.parse(params, { slideDirection: SlideDirection.LEFT }); | ||||
|  | ||||
|         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 }); | ||||
|         super._init({ | ||||
|             layout_manager: this.layout, | ||||
|             style_class: 'overview-controls', | ||||
|             clip_to_allocation: true | ||||
|         }); | ||||
|  | ||||
|         this._visible = true; | ||||
|         this._inDrag = false; | ||||
|  | ||||
|         Main.overview.connect('hiding', this._onOverviewHiding.bind(this)); | ||||
|  | ||||
| @@ -146,20 +150,20 @@ var SlidingControl = class { | ||||
|     } | ||||
|  | ||||
|     _updateSlide() { | ||||
|         this.actor.ease_property('@layout.slide-x', this._getSlide(), { | ||||
|         this.ease_property('@layout.slide-x', this._getSlide(), { | ||||
|             mode: Clutter.AnimationMode.EASE_OUT_QUAD, | ||||
|             duration: SIDE_CONTROLS_ANIMATION_TIME, | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     getVisibleWidth() { | ||||
|         let child = this.actor.get_first_child(); | ||||
|         let child = this.get_first_child(); | ||||
|         let [, , natWidth] = child.get_preferred_size(); | ||||
|         return natWidth; | ||||
|     } | ||||
|  | ||||
|     _getTranslation() { | ||||
|         let child = this.actor.get_first_child(); | ||||
|         let child = this.get_first_child(); | ||||
|         let direction = getRtlSlideDirection(this.layout.slideDirection, child); | ||||
|         let visibleWidth = this.getVisibleWidth(); | ||||
|  | ||||
| @@ -185,7 +189,7 @@ var SlidingControl = class { | ||||
|             return; | ||||
|  | ||||
|         this.layout.translation_x = translationStart; | ||||
|         this.actor.ease_property('@layout.translation-x', translationEnd, { | ||||
|         this.ease_property('@layout.translation-x', translationEnd, { | ||||
|             mode: Clutter.AnimationMode.EASE_OUT_QUAD, | ||||
|             duration: SIDE_CONTROLS_ANIMATION_TIME, | ||||
|         }); | ||||
| @@ -217,7 +221,7 @@ var SlidingControl = class { | ||||
|     } | ||||
|  | ||||
|     fadeIn() { | ||||
|         this.actor.ease({ | ||||
|         this.ease({ | ||||
|             opacity: 255, | ||||
|             duration: SIDE_CONTROLS_ANIMATION_TIME / 2, | ||||
|             mode: Clutter.AnimationMode.EASE_IN_QUAD | ||||
| @@ -225,7 +229,7 @@ var SlidingControl = class { | ||||
|     } | ||||
|  | ||||
|     fadeHalf() { | ||||
|         this.actor.ease({ | ||||
|         this.ease({ | ||||
|             opacity: 128, | ||||
|             duration: SIDE_CONTROLS_ANIMATION_TIME / 2, | ||||
|             mode: Clutter.AnimationMode.EASE_OUT_QUAD | ||||
| @@ -248,37 +252,38 @@ var SlidingControl = class { | ||||
|         // 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.actor.remove_transition('@layout.slide-x'); | ||||
|         this.remove_transition('@layout.slide-x'); | ||||
|         this.layout.slide_x = this._getSlide(); | ||||
|         this._updateTranslation(); | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|  | ||||
| var ThumbnailsSlider = class extends SlidingControl { | ||||
|     constructor(thumbnailsBox) { | ||||
|         super({ slideDirection: SlideDirection.RIGHT }); | ||||
| var ThumbnailsSlider = GObject.registerClass( | ||||
| class ThumbnailsSlider extends SlidingControl { | ||||
|     _init(thumbnailsBox) { | ||||
|         super._init({ slideDirection: SlideDirection.RIGHT }); | ||||
|  | ||||
|         this._thumbnailsBox = 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); | ||||
|         this.request_mode = Clutter.RequestMode.WIDTH_FOR_HEIGHT; | ||||
|         this.reactive = true; | ||||
|         this.track_hover = true; | ||||
|         this.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.actor.connect('notify::hover', this._updateSlide.bind(this)); | ||||
|         this._thumbnailsBox.bind_property('visible', this.actor, 'visible', GObject.BindingFlags.SYNC_CREATE); | ||||
|         this.connect('notify::hover', this._updateSlide.bind(this)); | ||||
|         this._thumbnailsBox.bind_property('visible', this, '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.actor.hover || | ||||
|         let alwaysZoomOut = this.hover || | ||||
|                             this._inDrag || | ||||
|                             !Meta.prefs_get_dynamic_workspaces() || | ||||
|                             workspaceManager.n_workspaces > 2 || | ||||
| @@ -303,12 +308,12 @@ var ThumbnailsSlider = class extends SlidingControl { | ||||
|     } | ||||
|  | ||||
|     getNonExpandedWidth() { | ||||
|         let child = this.actor.get_first_child(); | ||||
|         let child = this.get_first_child(); | ||||
|         return child.get_theme_node().get_length('visible-width'); | ||||
|     } | ||||
|  | ||||
|     _onDragEnd() { | ||||
|         this.actor.sync_hover(); | ||||
|         this.sync_hover(); | ||||
|         super._onDragEnd(); | ||||
|     } | ||||
|  | ||||
| @@ -320,7 +325,7 @@ var ThumbnailsSlider = class extends SlidingControl { | ||||
|         if (alwaysZoomOut) | ||||
|             return 1; | ||||
|  | ||||
|         let child = this.actor.get_first_child(); | ||||
|         let child = this.get_first_child(); | ||||
|         let preferredHeight = child.get_preferred_height(-1)[1]; | ||||
|         let expandedWidth = child.get_preferred_width(preferredHeight)[1]; | ||||
|  | ||||
| @@ -334,24 +339,25 @@ var ThumbnailsSlider = class extends SlidingControl { | ||||
|         else | ||||
|             return this.getNonExpandedWidth(); | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|  | ||||
| var DashSlider = class extends SlidingControl { | ||||
|     constructor(dash) { | ||||
|         super({ slideDirection: SlideDirection.LEFT }); | ||||
| var DashSlider = GObject.registerClass( | ||||
| class DashSlider extends SlidingControl { | ||||
|     _init(dash) { | ||||
|         super._init({ 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.actor.x_expand = true; | ||||
|         this._dash.x_expand = true; | ||||
|  | ||||
|         this.actor.x_expand = true; | ||||
|         this.actor.x_align = Clutter.ActorAlign.START; | ||||
|         this.actor.y_expand = true; | ||||
|         this.x_expand = true; | ||||
|         this.x_align = Clutter.ActorAlign.START; | ||||
|         this.y_expand = true; | ||||
|  | ||||
|         this.actor.add_actor(this._dash.actor); | ||||
|         this.add_actor(this._dash); | ||||
|  | ||||
|         this._dash.connect('icon-size-changed', this._updateSlide.bind(this)); | ||||
|     } | ||||
| @@ -370,7 +376,7 @@ var DashSlider = class extends SlidingControl { | ||||
|     _onWindowDragEnd() { | ||||
|         this.fadeIn(); | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|  | ||||
| var DashSpacer = GObject.registerClass( | ||||
| class DashSpacer extends St.Widget { | ||||
| @@ -415,12 +421,21 @@ var ControlsLayout = GObject.registerClass({ | ||||
|     } | ||||
| }); | ||||
|  | ||||
| var ControlsManager = class { | ||||
|     constructor(searchEntry) { | ||||
| 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 | ||||
|         }); | ||||
|  | ||||
|         this.dash = new Dash.Dash(); | ||||
|         this._dashSlider = new DashSlider(this.dash); | ||||
|         this._dashSpacer = new DashSpacer(); | ||||
|         this._dashSpacer.setDashActor(this._dashSlider.actor); | ||||
|         this._dashSpacer.setDashActor(this._dashSlider); | ||||
|  | ||||
|         this._thumbnailsBox = new WorkspaceThumbnail.ThumbnailsBox(); | ||||
|         this._thumbnailsSlider = new ThumbnailsSlider(this._thumbnailsBox); | ||||
| @@ -430,20 +445,15 @@ var ControlsManager = class { | ||||
|         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.actor.add_actor(this._group); | ||||
|         this.add_actor(this._group); | ||||
|  | ||||
|         this.actor.add_actor(this._dashSlider.actor); | ||||
|         this.add_actor(this._dashSlider); | ||||
|  | ||||
|         this._group.add_actor(this._dashSpacer); | ||||
|         this._group.add(this.viewSelector.actor, { x_fill: true, | ||||
|                                                    expand: true }); | ||||
|         this._group.add_actor(this._thumbnailsSlider.actor); | ||||
|         this._group.add(this.viewSelector, { x_fill: true, expand: true }); | ||||
|         this._group.add_actor(this._thumbnailsSlider); | ||||
|  | ||||
|         layout.connect('allocation-changed', this._updateWorkspacesGeometry.bind(this)); | ||||
|  | ||||
| @@ -451,18 +461,18 @@ var ControlsManager = class { | ||||
|     } | ||||
|  | ||||
|     _updateWorkspacesGeometry() { | ||||
|         let [x, y] = this.actor.get_transformed_position(); | ||||
|         let [width, height] = this.actor.get_transformed_size(); | ||||
|         let [x, y] = this.get_transformed_position(); | ||||
|         let [width, height] = this.get_transformed_size(); | ||||
|         let geometry = { x: x, y: y, width: width, height: height }; | ||||
|  | ||||
|         let spacing = this.actor.get_theme_node().get_length('spacing'); | ||||
|         let spacing = this.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.actor.get_text_direction() == Clutter.TextDirection.LTR) | ||||
|         if (this.get_text_direction() == Clutter.TextDirection.LTR) | ||||
|             geometry.x += dashWidth; | ||||
|         else | ||||
|             geometry.x += thumbnailsWidth; | ||||
| @@ -509,4 +519,4 @@ var ControlsManager = class { | ||||
|  | ||||
|         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 PadOsdService */ | ||||
| /* exported PadOsd, PadOsdService */ | ||||
|  | ||||
| const { Atk, Clutter, GDesktopEnums, Gio, | ||||
|         GLib, GObject, Gtk, Meta, Rsvg, St } = imports.gi; | ||||
| @@ -22,40 +22,45 @@ const CCW = 1; | ||||
| const UP = 0; | ||||
| const DOWN = 1; | ||||
|  | ||||
| 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 }); | ||||
| 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 | ||||
|         }); | ||||
|         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.actor.set_child(arrow); | ||||
|         this.set_child(arrow); | ||||
|         this._ensureMenu(groupDevices); | ||||
|  | ||||
|         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); | ||||
|             } | ||||
|         }); | ||||
|         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); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     _ensureMenu(devices) { | ||||
|         this._padChooserMenu =  new PopupMenu.PopupMenu(this.actor, 0.5, St.Side.TOP); | ||||
|         this._padChooserMenu =  new PopupMenu.PopupMenu(this, 0.5, St.Side.TOP); | ||||
|         this._padChooserMenu.connect('menu-closed', () => { | ||||
|             this.actor.set_checked(false); | ||||
|             this.set_checked(false); | ||||
|         }); | ||||
|         this._padChooserMenu.actor.hide(); | ||||
|         Main.uiGroup.add_actor(this._padChooserMenu.actor); | ||||
| @@ -78,24 +83,20 @@ var PadChooser = class { | ||||
|     update(devices) { | ||||
|         if (this._padChooserMenu) | ||||
|             this._padChooserMenu.actor.destroy(); | ||||
|         this.actor.set_checked(false); | ||||
|         this.set_checked(false); | ||||
|         this._ensureMenu(devices); | ||||
|     } | ||||
| }); | ||||
|  | ||||
|     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)); | ||||
| 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' }); | ||||
|     } | ||||
|  | ||||
|     _onCapturedEvent(actor, event) { | ||||
|     vfunc_captured_event(event) { | ||||
|         if (event.type() != Clutter.EventType.KEY_PRESS) | ||||
|             return Clutter.EVENT_PROPAGATE; | ||||
|  | ||||
| @@ -103,23 +104,24 @@ var KeybindingEntry = class { | ||||
|                                                     event.get_key_symbol(), | ||||
|                                                     event.get_key_code(), | ||||
|                                                     event.get_state()); | ||||
|         this.actor.set_text(str); | ||||
|         this.set_text(str); | ||||
|         this.emit('keybinding-edited', str); | ||||
|         return Clutter.EVENT_STOP; | ||||
|     } | ||||
| }; | ||||
| Signals.addSignalMethods(KeybindingEntry.prototype); | ||||
| }); | ||||
|  | ||||
| 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); | ||||
| 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); | ||||
|  | ||||
|         let boxLayout = new Clutter.BoxLayout({ orientation: Clutter.Orientation.HORIZONTAL, | ||||
|                                                 spacing: 6 }); | ||||
|         let box = new St.Widget({ layout_manager: boxLayout }); | ||||
|         this.actor.set_child(box); | ||||
|         this.set_child(box); | ||||
|  | ||||
|         this._label = new St.Label({ style_class: 'combo-box-label' }); | ||||
|         box.add_child(this._label); | ||||
| @@ -131,9 +133,9 @@ var ActionComboBox = class { | ||||
|                                   y_align: Clutter.ActorAlign.CENTER }); | ||||
|         box.add_child(arrow); | ||||
|  | ||||
|         this._editMenu = new PopupMenu.PopupMenu(this.actor, 0, St.Side.TOP); | ||||
|         this._editMenu = new PopupMenu.PopupMenu(this, 0, St.Side.TOP); | ||||
|         this._editMenu.connect('menu-closed', () => { | ||||
|             this.actor.set_checked(false); | ||||
|             this.set_checked(false); | ||||
|         }); | ||||
|         this._editMenu.actor.hide(); | ||||
|         Main.uiGroup.add_actor(this._editMenu.actor); | ||||
| @@ -179,8 +181,8 @@ var ActionComboBox = class { | ||||
|         this._editMenu.close(true); | ||||
|     } | ||||
|  | ||||
|     _onButtonClicked() { | ||||
|         if (this.actor.get_checked()) | ||||
|     vfunc_clicked() { | ||||
|         if (this.get_checked()) | ||||
|             this.popup(); | ||||
|         else | ||||
|             this.popdown(); | ||||
| @@ -189,38 +191,40 @@ var ActionComboBox = class { | ||||
|     setButtonActionsActive(active) { | ||||
|         this._buttonItems.forEach(item => item.setSensitive(active)); | ||||
|     } | ||||
| }; | ||||
| Signals.addSignalMethods(ActionComboBox.prototype); | ||||
| }); | ||||
|  | ||||
| var ActionEditor = class { | ||||
|     constructor() { | ||||
| var ActionEditor = GObject.registerClass({ | ||||
|     GTypeName: 'PadOsd_ActionEditor', | ||||
|     Signals: { 'done': {} } | ||||
| }, class ActionEditor extends St.Widget { | ||||
|     _init() { | ||||
|         let boxLayout = new Clutter.BoxLayout({ orientation: Clutter.Orientation.HORIZONTAL, | ||||
|                                                 spacing: 12 }); | ||||
|  | ||||
|         this.actor = new St.Widget({ layout_manager: boxLayout }); | ||||
|         super._init({ layout_manager: boxLayout }); | ||||
|  | ||||
|         this._actionComboBox = new ActionComboBox(); | ||||
|         this._actionComboBox.connect('action-selected', this._onActionSelected.bind(this)); | ||||
|         this.actor.add_actor(this._actionComboBox.actor); | ||||
|         this.add_actor(this._actionComboBox); | ||||
|  | ||||
|         this._keybindingEdit = new KeybindingEntry(); | ||||
|         this._keybindingEdit.connect('keybinding-edited', this._onKeybindingEdited.bind(this)); | ||||
|         this.actor.add_actor(this._keybindingEdit.actor); | ||||
|         this.add_actor(this._keybindingEdit); | ||||
|  | ||||
|         this._doneButton = new St.Button({ label: _("Done"), | ||||
|                                            style_class: 'button', | ||||
|                                            x_expand: false }); | ||||
|         this._doneButton.connect('clicked', this._onEditingDone.bind(this)); | ||||
|         this.actor.add_actor(this._doneButton); | ||||
|         this.add_actor(this._doneButton); | ||||
|     } | ||||
|  | ||||
|     _updateKeybindingEntryState() { | ||||
|         if (this._currentAction == GDesktopEnums.PadButtonAction.KEYBINDING) { | ||||
|             this._keybindingEdit.actor.set_text(this._currentKeybinding); | ||||
|             this._keybindingEdit.actor.show(); | ||||
|             this._keybindingEdit.actor.grab_key_focus(); | ||||
|             this._keybindingEdit.set_text(this._currentKeybinding); | ||||
|             this._keybindingEdit.show(); | ||||
|             this._keybindingEdit.grab_key_focus(); | ||||
|         } else { | ||||
|             this._keybindingEdit.actor.hide(); | ||||
|             this._keybindingEdit.hide(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -238,7 +242,7 @@ var ActionEditor = class { | ||||
|  | ||||
|     close() { | ||||
|         this._actionComboBox.popdown(); | ||||
|         this.actor.hide(); | ||||
|         this.hide(); | ||||
|     } | ||||
|  | ||||
|     _onKeybindingEdited(entry, keybinding) { | ||||
| @@ -272,8 +276,7 @@ var ActionEditor = class { | ||||
|         this.close(); | ||||
|         this.emit('done'); | ||||
|     } | ||||
| }; | ||||
| Signals.addSignalMethods(ActionEditor.prototype); | ||||
| }); | ||||
|  | ||||
| var PadDiagram = GObject.registerClass({ | ||||
|     Properties: { | ||||
| @@ -615,8 +618,18 @@ var PadDiagram = GObject.registerClass({ | ||||
|     } | ||||
| }); | ||||
|  | ||||
| var PadOsd = class { | ||||
|     constructor(padDevice, settings, imagePath, editionMode, monitorIndex) { | ||||
| 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 | ||||
|         }); | ||||
|  | ||||
|         this.padDevice = padDevice; | ||||
|         this._groupPads = [padDevice]; | ||||
|         this._settings = settings; | ||||
| @@ -653,23 +666,18 @@ var PadOsd = class { | ||||
|                 this._groupPads.push(device); | ||||
|         }); | ||||
|  | ||||
|         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.connect('destroy', this._onDestroy.bind(this)); | ||||
|         Main.uiGroup.add_actor(this); | ||||
|  | ||||
|         this._monitorIndex = monitorIndex; | ||||
|         let constraint = new Layout.MonitorConstraint({ index: monitorIndex }); | ||||
|         this.actor.add_constraint(constraint); | ||||
|         this.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.actor.add_actor(this._titleBox); | ||||
|         this.add_actor(this._titleBox); | ||||
|  | ||||
|         let labelBox = new St.BoxLayout({ style_class: 'pad-osd-title-menu-box', | ||||
|                                           vertical: true }); | ||||
| @@ -690,10 +698,10 @@ var PadOsd = class { | ||||
|  | ||||
|         this._padDiagram = new PadDiagram({ image: this._imagePath, | ||||
|                                             left_handed: settings.get_boolean('left-handed'), | ||||
|                                             editor_actor: this._actionEditor.actor, | ||||
|                                             editor_actor: this._actionEditor, | ||||
|                                             x_expand: true, | ||||
|                                             y_expand: true }); | ||||
|         this.actor.add_actor(this._padDiagram); | ||||
|         this.add_actor(this._padDiagram); | ||||
|  | ||||
|         // FIXME: Fix num buttons. | ||||
|         let i = 0; | ||||
| @@ -724,7 +732,7 @@ var PadOsd = class { | ||||
|                                         x_expand: true, | ||||
|                                         x_align: Clutter.ActorAlign.CENTER, | ||||
|                                         y_align: Clutter.ActorAlign.CENTER }); | ||||
|         this.actor.add_actor(buttonBox); | ||||
|         this.add_actor(buttonBox); | ||||
|         this._editButton = new St.Button({ label: _("Edit…"), | ||||
|                                            style_class: 'button', | ||||
|                                            x_align: Clutter.ActorAlign.CENTER, | ||||
| @@ -735,7 +743,7 @@ var PadOsd = class { | ||||
|         buttonBox.add_actor(this._editButton); | ||||
|  | ||||
|         this._syncEditionMode(); | ||||
|         Main.pushModal(this.actor); | ||||
|         Main.pushModal(this); | ||||
|     } | ||||
|  | ||||
|     _updatePadChooser() { | ||||
| @@ -745,7 +753,7 @@ var PadOsd = class { | ||||
|                 this._padChooser.connect('pad-selected', (chooser, pad) => { | ||||
|                     this._requestForOtherPad(pad); | ||||
|                 }); | ||||
|                 this._titleBox.add_child(this._padChooser.actor); | ||||
|                 this._titleBox.add_child(this._padChooser); | ||||
|             } else { | ||||
|                 this._padChooser.update(this._groupPads); | ||||
|             } | ||||
| @@ -918,12 +926,8 @@ var PadOsd = class { | ||||
|         this._syncEditionMode(); | ||||
|     } | ||||
|  | ||||
|     destroy() { | ||||
|         this.actor.destroy(); | ||||
|     } | ||||
|  | ||||
|     _onDestroy() { | ||||
|         Main.popModal(this.actor); | ||||
|         Main.popModal(this); | ||||
|         this._actionEditor.close(); | ||||
|  | ||||
|         let deviceManager = Clutter.DeviceManager.get_default(); | ||||
| @@ -941,11 +945,9 @@ var PadOsd = class { | ||||
|             this._capturedEventId = 0; | ||||
|         } | ||||
|  | ||||
|         this.actor = null; | ||||
|         this.emit('closed'); | ||||
|     } | ||||
| }; | ||||
| Signals.addSignalMethods(PadOsd.prototype); | ||||
| }); | ||||
|  | ||||
| const PadOsdIface = loadInterfaceXML('org.gnome.Shell.Wacom.PadOsd'); | ||||
|  | ||||
|   | ||||
| @@ -20,14 +20,17 @@ var ANIMATION_DELAY = 100; | ||||
| var PageIndicators = GObject.registerClass({ | ||||
|     Signals: { 'page-activated': { param_types: [GObject.TYPE_INT] } } | ||||
| }, class PageIndicators extends St.BoxLayout { | ||||
|     _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 }); | ||||
|     _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 | ||||
|         }); | ||||
|         this._nPages = 0; | ||||
|         this._currentPage = undefined; | ||||
|         this._reactive = true; | ||||
| @@ -93,18 +96,26 @@ var PageIndicators = GObject.registerClass({ | ||||
| var AnimatedPageIndicators = GObject.registerClass( | ||||
| class AnimatedPageIndicators extends PageIndicators { | ||||
|     _init() { | ||||
|         super._init(true); | ||||
|         super._init(); | ||||
|         this.connect('destroy', this._onDestroy.bind(this)); | ||||
|     } | ||||
|  | ||||
|         this.connect('notify::mapped', () => { | ||||
|             if (!this.mapped) | ||||
|                 return; | ||||
|     _onDestroy() { | ||||
|         if (this.animateLater) { | ||||
|             Meta.later_remove(this.animateLater); | ||||
|             this.animateLater = 0; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|             // 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; | ||||
|             }); | ||||
|     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; | ||||
|         }); | ||||
|     } | ||||
|  | ||||
| @@ -126,12 +137,14 @@ class AnimatedPageIndicators extends PageIndicators { | ||||
|             offset = children[0].width; | ||||
|  | ||||
|         let isAnimationIn = animationDirection == AnimationDirection.IN; | ||||
|         let delay = isAnimationIn ? INDICATORS_ANIMATION_DELAY : | ||||
|                                     INDICATORS_ANIMATION_DELAY_OUT; | ||||
|         let delay = isAnimationIn | ||||
|             ? INDICATORS_ANIMATION_DELAY | ||||
|             : INDICATORS_ANIMATION_DELAY_OUT; | ||||
|         let baseTime = isAnimationIn ? INDICATORS_BASE_TIME : INDICATORS_BASE_TIME_OUT; | ||||
|         let totalAnimationTime = baseTime + delay * this._nPages; | ||||
|         let maxTime = isAnimationIn ? INDICATORS_ANIMATION_MAX_TIME : | ||||
|                                       INDICATORS_ANIMATION_MAX_TIME_OUT; | ||||
|         let maxTime = isAnimationIn | ||||
|             ? INDICATORS_ANIMATION_MAX_TIME | ||||
|             : INDICATORS_ANIMATION_MAX_TIME_OUT; | ||||
|         if (totalAnimationTime > maxTime) | ||||
|             delay -= (totalAnimationTime - maxTime) / this._nPages; | ||||
|  | ||||
|   | ||||
							
								
								
									
										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.actor); | ||||
|         this._container.add_actor(this._spinner); | ||||
|  | ||||
|         let menu = new AppMenu(this); | ||||
|         this.setMenu(menu); | ||||
| @@ -430,9 +430,6 @@ 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); | ||||
| @@ -459,7 +456,7 @@ class ActivitiesButton extends PanelMenu.Button { | ||||
|         return DND.DragMotionResult.CONTINUE; | ||||
|     } | ||||
|  | ||||
|     _onCapturedEvent(actor, event) { | ||||
|     vfunc_captured_event(event) { | ||||
|         if (event.type() == Clutter.EventType.BUTTON_PRESS || | ||||
|             event.type() == Clutter.EventType.TOUCH_BEGIN) { | ||||
|             if (!Main.overview.shouldToggleByCornerOrButton()) | ||||
| @@ -468,9 +465,7 @@ class ActivitiesButton extends PanelMenu.Button { | ||||
|         return Clutter.EVENT_PROPAGATE; | ||||
|     } | ||||
|  | ||||
|     _onEvent(actor, event) { | ||||
|         super._onEvent(actor, event); | ||||
|  | ||||
|     vfunc_event(event) { | ||||
|         if (event.type() == Clutter.EventType.TOUCH_END || | ||||
|             event.type() == Clutter.EventType.BUTTON_RELEASE) | ||||
|             if (Main.overview.shouldToggleByCornerOrButton()) | ||||
| @@ -479,13 +474,16 @@ class ActivitiesButton extends PanelMenu.Button { | ||||
|         return Clutter.EVENT_PROPAGATE; | ||||
|     } | ||||
|  | ||||
|     _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(); | ||||
|     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(); | ||||
|             } | ||||
|         } | ||||
|         return Clutter.EVENT_PROPAGATE; | ||||
|         return ret; | ||||
|     } | ||||
|  | ||||
|     _xdndToggleOverview() { | ||||
| @@ -501,13 +499,12 @@ class ActivitiesButton extends PanelMenu.Button { | ||||
|     } | ||||
| }); | ||||
|  | ||||
| var PanelCorner = class { | ||||
|     constructor(side) { | ||||
| var PanelCorner = GObject.registerClass( | ||||
| class PanelCorner extends St.DrawingArea { | ||||
|     _init(side) { | ||||
|         this._side = side; | ||||
|  | ||||
|         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)); | ||||
|         super._init({ style_class: 'panel-corner' }); | ||||
|     } | ||||
|  | ||||
|     _findRightmostButton(container) { | ||||
| @@ -597,7 +594,7 @@ var PanelCorner = class { | ||||
|             this._buttonStyleChangedSignalId = button.connect('style-changed', | ||||
|                 () => { | ||||
|                     let pseudoClass = button.get_style_pseudo_class(); | ||||
|                     this.actor.set_style_pseudo_class(pseudoClass); | ||||
|                     this.set_style_pseudo_class(pseudoClass); | ||||
|                 }); | ||||
|  | ||||
|             // The corner doesn't support theme transitions, so override | ||||
| @@ -606,8 +603,8 @@ var PanelCorner = class { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     _repaint() { | ||||
|         let node = this.actor.get_theme_node(); | ||||
|     vfunc_repaint() { | ||||
|         let node = this.get_theme_node(); | ||||
|  | ||||
|         let cornerRadius = node.get_length("-panel-corner-radius"); | ||||
|         let borderWidth = node.get_length('-panel-corner-border-width'); | ||||
| @@ -618,7 +615,7 @@ var PanelCorner = class { | ||||
|         let overlap = borderColor.alpha != 0; | ||||
|         let offsetY = overlap ? 0 : borderWidth; | ||||
|  | ||||
|         let cr = this.actor.get_context(); | ||||
|         let cr = this.get_context(); | ||||
|         cr.setOperator(Cairo.Operator.SOURCE); | ||||
|  | ||||
|         cr.moveTo(0, offsetY); | ||||
| @@ -654,16 +651,17 @@ var PanelCorner = class { | ||||
|         cr.$dispose(); | ||||
|     } | ||||
|  | ||||
|     _styleChanged() { | ||||
|         let node = this.actor.get_theme_node(); | ||||
|     vfunc_style_changed() { | ||||
|         super.vfunc_style_changed(); | ||||
|         let node = this.get_theme_node(); | ||||
|  | ||||
|         let cornerRadius = node.get_length("-panel-corner-radius"); | ||||
|         let borderWidth = node.get_length('-panel-corner-border-width'); | ||||
|  | ||||
|         this.actor.set_size(cornerRadius, borderWidth + cornerRadius); | ||||
|         this.actor.set_anchor_point(0, borderWidth); | ||||
|         this.set_size(cornerRadius, borderWidth + cornerRadius); | ||||
|         this.set_anchor_point(0, borderWidth); | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|  | ||||
| var AggregateLayout = GObject.registerClass( | ||||
| class AggregateLayout extends Clutter.BoxLayout { | ||||
| @@ -728,20 +726,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.indicators); | ||||
|         this._indicators.add_child(this._screencast.indicators); | ||||
|         this._indicators.add_child(this._location.indicators); | ||||
|         this._indicators.add_child(this._nightLight.indicators); | ||||
|         this._indicators.add_child(this._thunderbolt); | ||||
|         this._indicators.add_child(this._screencast); | ||||
|         this._indicators.add_child(this._location); | ||||
|         this._indicators.add_child(this._nightLight); | ||||
|         if (this._network) { | ||||
|             this._indicators.add_child(this._network.indicators); | ||||
|             this._indicators.add_child(this._network); | ||||
|         } | ||||
|         if (this._bluetooth) { | ||||
|             this._indicators.add_child(this._bluetooth.indicators); | ||||
|             this._indicators.add_child(this._bluetooth); | ||||
|         } | ||||
|         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(this._remoteAccess); | ||||
|         this._indicators.add_child(this._rfkill); | ||||
|         this._indicators.add_child(this._volume); | ||||
|         this._indicators.add_child(this._power); | ||||
|         this._indicators.add_child(PopupMenu.arrowIcon(St.Side.BOTTOM)); | ||||
|  | ||||
|         this.menu.addMenuItem(this._volume.menu); | ||||
| @@ -799,14 +797,10 @@ class Panel extends St.Widget { | ||||
|         this.add_child(this._rightBox); | ||||
|  | ||||
|         this._leftCorner = new PanelCorner(St.Side.LEFT); | ||||
|         this.add_child(this._leftCorner.actor); | ||||
|         this.add_child(this._leftCorner); | ||||
|  | ||||
|         this._rightCorner = new PanelCorner(St.Side.RIGHT); | ||||
|         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)); | ||||
|         this.add_child(this._rightCorner); | ||||
|  | ||||
|         Main.overview.connect('showing', () => { | ||||
|             this.add_style_pseudo_class('overview'); | ||||
| @@ -895,62 +889,65 @@ class Panel extends St.Widget { | ||||
|  | ||||
|         let cornerWidth, cornerHeight; | ||||
|  | ||||
|         [, cornerWidth] = this._leftCorner.actor.get_preferred_width(-1); | ||||
|         [, cornerHeight] = this._leftCorner.actor.get_preferred_height(-1); | ||||
|         [, cornerWidth] = this._leftCorner.get_preferred_width(-1); | ||||
|         [, cornerHeight] = this._leftCorner.get_preferred_height(-1); | ||||
|         childBox.x1 = 0; | ||||
|         childBox.x2 = cornerWidth; | ||||
|         childBox.y1 = allocHeight; | ||||
|         childBox.y2 = allocHeight + cornerHeight; | ||||
|         this._leftCorner.actor.allocate(childBox, flags); | ||||
|         this._leftCorner.allocate(childBox, flags); | ||||
|  | ||||
|         [, cornerWidth] = this._rightCorner.actor.get_preferred_width(-1); | ||||
|         [, cornerHeight] = this._rightCorner.actor.get_preferred_height(-1); | ||||
|         [, cornerWidth] = this._rightCorner.get_preferred_width(-1); | ||||
|         [, cornerHeight] = this._rightCorner.get_preferred_height(-1); | ||||
|         childBox.x1 = allocWidth - cornerWidth; | ||||
|         childBox.x2 = allocWidth; | ||||
|         childBox.y1 = allocHeight; | ||||
|         childBox.y2 = allocHeight + cornerHeight; | ||||
|         this._rightCorner.actor.allocate(childBox, flags); | ||||
|         this._rightCorner.allocate(childBox, flags); | ||||
|     } | ||||
|  | ||||
|     _onButtonPress(actor, event) { | ||||
|     _tryDragWindow(event) { | ||||
|         if (Main.modalCount > 0) | ||||
|             return Clutter.EVENT_PROPAGATE; | ||||
|  | ||||
|         if (event.get_source() != actor) | ||||
|         if (event.source != this) | ||||
|             return Clutter.EVENT_PROPAGATE; | ||||
|  | ||||
|         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); | ||||
|         let { x, y } = event; | ||||
|         let dragWindow = this._getDraggableWindowForPosition(x); | ||||
|  | ||||
|         if (!dragWindow) | ||||
|             return 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; | ||||
|         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; | ||||
|     } | ||||
|  | ||||
|     _onKeyPress(actor, event) { | ||||
|         let symbol = event.get_key_symbol(); | ||||
|     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; | ||||
|         if (symbol == Clutter.KEY_Escape) { | ||||
|             global.display.focus_default_window(event.get_time()); | ||||
|             global.display.focus_default_window(keyEvent.time); | ||||
|             return Clutter.EVENT_STOP; | ||||
|         } | ||||
|  | ||||
| @@ -1114,14 +1111,14 @@ class Panel extends St.Widget { | ||||
|  | ||||
|     _addStyleClassName(className) { | ||||
|         this.add_style_class_name(className); | ||||
|         this._rightCorner.actor.add_style_class_name(className); | ||||
|         this._leftCorner.actor.add_style_class_name(className); | ||||
|         this._rightCorner.add_style_class_name(className); | ||||
|         this._leftCorner.add_style_class_name(className); | ||||
|     } | ||||
|  | ||||
|     _removeStyleClassName(className) { | ||||
|         this.remove_style_class_name(className); | ||||
|         this._rightCorner.actor.remove_style_class_name(className); | ||||
|         this._leftCorner.actor.remove_style_class_name(className); | ||||
|         this._rightCorner.remove_style_class_name(className); | ||||
|         this._leftCorner.remove_style_class_name(className); | ||||
|     } | ||||
|  | ||||
|     _onMenuSet(indicator) { | ||||
|   | ||||
| @@ -2,7 +2,6 @@ | ||||
| /* exported Button, SystemIndicator */ | ||||
|  | ||||
| const { Atk, Clutter, GObject, St } = imports.gi; | ||||
| const Signals = imports.signals; | ||||
|  | ||||
| const Main = imports.ui.main; | ||||
| const Params = imports.misc.params; | ||||
| @@ -101,9 +100,6 @@ 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 | ||||
| @@ -132,7 +128,7 @@ var Button = GObject.registerClass({ | ||||
|         this.emit('menu-set'); | ||||
|     } | ||||
|  | ||||
|     _onEvent(actor, event) { | ||||
|     vfunc_event(event) { | ||||
|         if (this.menu && | ||||
|             (event.type() == Clutter.EventType.TOUCH_BEGIN || | ||||
|              event.type() == Clutter.EventType.BUTTON_PRESS)) | ||||
| @@ -141,11 +137,10 @@ var Button = GObject.registerClass({ | ||||
|         return Clutter.EVENT_PROPAGATE; | ||||
|     } | ||||
|  | ||||
|     _onVisibilityChanged() { | ||||
|         if (!this.menu) | ||||
|             return; | ||||
|     vfunc_hide() { | ||||
|         super.vfunc_hide(); | ||||
|  | ||||
|         if (!this.visible) | ||||
|         if (this.menu) | ||||
|             this.menu.close(); | ||||
|     } | ||||
|  | ||||
| @@ -200,24 +195,34 @@ var Button = GObject.registerClass({ | ||||
|  * of an icon and a menu section, which will be composed into the | ||||
|  * aggregate menu. | ||||
|  */ | ||||
| var SystemIndicator = class { | ||||
|     constructor() { | ||||
|         this.indicators = new St.BoxLayout({ style_class: 'panel-status-indicators-box', | ||||
|                                              reactive: true }); | ||||
|         this.indicators.hide(); | ||||
| 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 | ||||
|         }); | ||||
|         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.indicators.visible = this.indicators.get_children().some(a => a.visible); | ||||
|         this.visible = this.get_children().some(a => a.visible); | ||||
|     } | ||||
|  | ||||
|     _addIndicator() { | ||||
|         let icon = new St.Icon({ style_class: 'system-status-icon' }); | ||||
|         this.indicators.add_actor(icon); | ||||
|         this.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, Shell, St } = imports.gi; | ||||
| const { Atk, Clutter, Gio, GObject, Graphene, Shell, St } = imports.gi; | ||||
| const Signals = imports.signals; | ||||
|  | ||||
| const BoxPointer = imports.ui.boxpointer; | ||||
| @@ -15,6 +15,7 @@ var Ornament = { | ||||
|     NONE: 0, | ||||
|     DOT: 1, | ||||
|     CHECK: 2, | ||||
|     HIDDEN: 3, | ||||
| }; | ||||
|  | ||||
| function isPopupMenuItemVisible(child) { | ||||
| @@ -96,12 +97,6 @@ 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); | ||||
|     } | ||||
| @@ -123,32 +118,44 @@ var PopupBaseMenuItem = GObject.registerClass({ | ||||
|         this._parent = parent; | ||||
|     } | ||||
|  | ||||
|     _onButtonPressEvent() { | ||||
|     vfunc_button_press_event(buttonEvent) { | ||||
|         if (!this._activatable) | ||||
|             return super.vfunc_button_press_event(buttonEvent); | ||||
|  | ||||
|         // This is the CSS active state | ||||
|         this.add_style_pseudo_class('active'); | ||||
|         return Clutter.EVENT_PROPAGATE; | ||||
|     } | ||||
|  | ||||
|     _onButtonReleaseEvent(actor, event) { | ||||
|     vfunc_button_release_event(buttonEvent) { | ||||
|         if (!this._activatable) | ||||
|             return super.vfunc_button_release_event(buttonEvent); | ||||
|  | ||||
|         this.remove_style_pseudo_class('active'); | ||||
|         this.activate(event); | ||||
|         this.activate(Clutter.get_current_event()); | ||||
|         return Clutter.EVENT_STOP; | ||||
|     } | ||||
|  | ||||
|     _onTouchEvent(actor, event) { | ||||
|         if (event.type() == Clutter.EventType.TOUCH_END) { | ||||
|     vfunc_touch_event(touchEvent) { | ||||
|         if (!this._activatable) | ||||
|             return super.vfunc_touch_event(touchEvent); | ||||
|  | ||||
|         if (touchEvent.type == Clutter.EventType.TOUCH_END) { | ||||
|             this.remove_style_pseudo_class('active'); | ||||
|             this.activate(event); | ||||
|             this.activate(Clutter.get_current_event()); | ||||
|             return Clutter.EVENT_STOP; | ||||
|         } else if (event.type() == Clutter.EventType.TOUCH_BEGIN) { | ||||
|         } else if (touchEvent.type == Clutter.EventType.TOUCH_BEGIN) { | ||||
|             // This is the CSS active state | ||||
|             this.add_style_pseudo_class('active'); | ||||
|         } | ||||
|         return Clutter.EVENT_PROPAGATE; | ||||
|     } | ||||
|  | ||||
|     _onKeyPressEvent(actor, event) { | ||||
|         let state = event.get_state(); | ||||
|     vfunc_key_press_event(keyEvent) { | ||||
|         if (!this._activatable) | ||||
|             return super.vfunc_key_press_event(keyEvent); | ||||
|  | ||||
|         let state = keyEvent.modifier_state; | ||||
|  | ||||
|         // if user has a modifier down (except capslock and numlock) | ||||
|         // then don't handle the key press here | ||||
| @@ -159,9 +166,9 @@ var PopupBaseMenuItem = GObject.registerClass({ | ||||
|         if (state) | ||||
|             return Clutter.EVENT_PROPAGATE; | ||||
|  | ||||
|         let symbol = event.get_key_symbol(); | ||||
|         let symbol = keyEvent.keyval; | ||||
|         if (symbol == Clutter.KEY_space || symbol == Clutter.KEY_Return) { | ||||
|             this.activate(event); | ||||
|             this.activate(Clutter.get_current_event()); | ||||
|             return Clutter.EVENT_STOP; | ||||
|         } | ||||
|         return Clutter.EVENT_PROPAGATE; | ||||
| @@ -248,10 +255,12 @@ var PopupBaseMenuItem = GObject.registerClass({ | ||||
|         } else if (ornament == Ornament.CHECK) { | ||||
|             this._ornamentLabel.text = '\u2713'; | ||||
|             this.add_accessible_state(Atk.StateType.CHECKED); | ||||
|         } else if (ornament == Ornament.NONE) { | ||||
|         } else if (ornament == Ornament.NONE || ornament == Ornament.HIDDEN) { | ||||
|             this._ornamentLabel.text = ''; | ||||
|             this.remove_accessible_state(Atk.StateType.CHECKED); | ||||
|         } | ||||
|  | ||||
|         this._ornamentLabel.visible = ornament != Ornament.HIDDEN; | ||||
|     } | ||||
| }); | ||||
|  | ||||
| @@ -425,6 +434,7 @@ var PopupMenuBase = class { | ||||
|             throw new TypeError(`Cannot instantiate abstract class ${this.constructor.name}`); | ||||
|  | ||||
|         this.sourceActor = sourceActor; | ||||
|         this.focusActor = sourceActor; | ||||
|         this._parent = null; | ||||
|  | ||||
|         if (styleClass !== undefined) { | ||||
| @@ -549,7 +559,7 @@ var PopupMenuBase = class { | ||||
|     } | ||||
|  | ||||
|     _connectItemSignals(menuItem) { | ||||
|         menuItem._activeChangeId = menuItem.connect('notify::active', (menuItem) => { | ||||
|         menuItem._activeChangeId = menuItem.connect('notify::active', menuItem => { | ||||
|             let active = menuItem.active; | ||||
|             if (active && this._activeMenuItem != menuItem) { | ||||
|                 if (this._activeMenuItem) | ||||
| @@ -613,8 +623,8 @@ var PopupMenuBase = class { | ||||
|         while (childBeforeIndex >= 0 && !isPopupMenuItemVisible(children[childBeforeIndex])) | ||||
|             childBeforeIndex--; | ||||
|  | ||||
|         if (childBeforeIndex < 0 | ||||
|             || children[childBeforeIndex]._delegate instanceof PopupSeparatorMenuItem) { | ||||
|         if (childBeforeIndex < 0 || | ||||
|             children[childBeforeIndex]._delegate instanceof PopupSeparatorMenuItem) { | ||||
|             menuItem.actor.hide(); | ||||
|             return; | ||||
|         } | ||||
| @@ -624,8 +634,8 @@ var PopupMenuBase = class { | ||||
|         while (childAfterIndex < children.length && !isPopupMenuItemVisible(children[childAfterIndex])) | ||||
|             childAfterIndex++; | ||||
|  | ||||
|         if (childAfterIndex >= children.length | ||||
|             || children[childAfterIndex]._delegate instanceof PopupSeparatorMenuItem) { | ||||
|         if (childAfterIndex >= children.length || | ||||
|             children[childAfterIndex]._delegate instanceof PopupSeparatorMenuItem) { | ||||
|             menuItem.actor.hide(); | ||||
|             return; | ||||
|         } | ||||
| @@ -718,10 +728,11 @@ var PopupMenuBase = class { | ||||
|                 this.disconnect(openStateChangeId); | ||||
|                 menuItem.disconnect(destroyId); | ||||
|             }); | ||||
|         } else if (menuItem instanceof PopupBaseMenuItem) | ||||
|         } else if (menuItem instanceof PopupBaseMenuItem) { | ||||
|             this._connectItemSignals(menuItem); | ||||
|         else | ||||
|         } else { | ||||
|             throw TypeError("Invalid argument to PopupMenuBase.addMenuItem()"); | ||||
|         } | ||||
|  | ||||
|         menuItem._setParent(this); | ||||
|  | ||||
| @@ -1125,7 +1136,7 @@ class PopupSubMenuMenuItem extends PopupBaseMenuItem { | ||||
|         this.add(expander, { expand: true }); | ||||
|  | ||||
|         this._triangle = arrowIcon(St.Side.RIGHT); | ||||
|         this._triangle.pivot_point = new Clutter.Point({ x: 0.5, y: 0.6 }); | ||||
|         this._triangle.pivot_point = new Graphene.Point({ x: 0.5, y: 0.6 }); | ||||
|  | ||||
|         this._triangleBin = new St.Widget({ y_expand: true, | ||||
|                                             y_align: Clutter.ActorAlign.CENTER }); | ||||
| @@ -1180,8 +1191,8 @@ class PopupSubMenuMenuItem extends PopupBaseMenuItem { | ||||
|         return this.menu.isOpen; | ||||
|     } | ||||
|  | ||||
|     _onKeyPressEvent(actor, event) { | ||||
|         let symbol = event.get_key_symbol(); | ||||
|     vfunc_key_press_event(keyPressEvent) { | ||||
|         let symbol = keyPressEvent.keyval; | ||||
|  | ||||
|         if (symbol == Clutter.KEY_Right) { | ||||
|             this._setOpenState(true); | ||||
| @@ -1192,14 +1203,14 @@ class PopupSubMenuMenuItem extends PopupBaseMenuItem { | ||||
|             return Clutter.EVENT_STOP; | ||||
|         } | ||||
|  | ||||
|         return super._onKeyPressEvent(actor, event); | ||||
|         return super.vfunc_key_press_event(keyPressEvent); | ||||
|     } | ||||
|  | ||||
|     activate(_event) { | ||||
|         this._setOpenState(true); | ||||
|     } | ||||
|  | ||||
|     _onButtonReleaseEvent() { | ||||
|     vfunc_button_release_event() { | ||||
|         // Since we override the parent, we need to manage what the parent does | ||||
|         // with the active style class | ||||
|         this.remove_style_pseudo_class('active'); | ||||
| @@ -1207,8 +1218,8 @@ class PopupSubMenuMenuItem extends PopupBaseMenuItem { | ||||
|         return Clutter.EVENT_PROPAGATE; | ||||
|     } | ||||
|  | ||||
|     _onTouchEvent(actor, event) { | ||||
|         if (event.type() == Clutter.EventType.TOUCH_END) { | ||||
|     vfunc_touch_event(touchEvent) { | ||||
|         if (touchEvent.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'); | ||||
| @@ -1296,18 +1307,20 @@ var PopupMenuManager = class { | ||||
|         if (open) { | ||||
|             if (this.activeMenu) | ||||
|                 this.activeMenu.close(BoxPointer.PopupAnimation.FADE); | ||||
|             this._grabHelper.grab({ actor: menu.actor, focus: menu.sourceActor, | ||||
|                                     onUngrab: isUser => { | ||||
|                                         this._closeMenu(isUser, menu); | ||||
|                                     } }); | ||||
|             this._grabHelper.grab({ | ||||
|                 actor: menu.actor, | ||||
|                 focus: menu.focusActor, | ||||
|                 onUngrab: isUser => this._closeMenu(isUser, menu), | ||||
|             }); | ||||
|         } else { | ||||
|             this._grabHelper.ungrab({ actor: menu.actor }); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     _changeMenu(newMenu) { | ||||
|         newMenu.open(this.activeMenu ? BoxPointer.PopupAnimation.FADE | ||||
|                                      : BoxPointer.PopupAnimation.FULL); | ||||
|         newMenu.open(this.activeMenu | ||||
|             ? BoxPointer.PopupAnimation.FADE | ||||
|             : BoxPointer.PopupAnimation.FULL); | ||||
|     } | ||||
|  | ||||
|     _onMenuSourceEnter(menu) { | ||||
|   | ||||
| @@ -67,7 +67,7 @@ var Ripples = class Ripples { | ||||
|             delay, | ||||
|             duration, | ||||
|             mode: Clutter.AnimationMode.LINEAR, | ||||
|             onComplete: () => ripple.visible = false | ||||
|             onComplete: () => (ripple.visible = false) | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -104,7 +104,7 @@ class RunDialog extends ModalDialog.ModalDialog { | ||||
|  | ||||
|         this._history = new History.HistoryManager({ gsettingsKey: HISTORY_KEY, | ||||
|                                                      entry: this._entryText }); | ||||
|         this._entryText.connect('activate', (o) => { | ||||
|         this._entryText.connect('activate', o => { | ||||
|             this.popModal(); | ||||
|             this._run(o.get_text(), | ||||
|                       Clutter.get_current_event().get_state() & Clutter.ModifierType.CONTROL_MASK); | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
|  | ||||
| const { AccountsService, Clutter, Cogl, Gio, GLib, | ||||
|         GnomeDesktop, GObject, Meta, Shell, St } = imports.gi; | ||||
|         GnomeDesktop, GObject, Graphene, Meta, Shell, St } = imports.gi; | ||||
| const Cairo = imports.cairo; | ||||
| const Signals = imports.signals; | ||||
|  | ||||
| @@ -17,6 +17,8 @@ const MessageTray = imports.ui.messageTray; | ||||
| const ShellDBus = imports.ui.shellDBus; | ||||
| const SmartcardManager = imports.misc.smartcardManager; | ||||
|  | ||||
| const { adjustAnimationTime } = imports.ui.environment; | ||||
|  | ||||
| const SCREENSAVER_SCHEMA = 'org.gnome.desktop.screensaver'; | ||||
| const LOCK_ENABLED_KEY = 'lock-enabled'; | ||||
| const LOCK_DELAY_KEY = 'lock-delay'; | ||||
| @@ -46,21 +48,23 @@ var STANDARD_FADE_TIME = 10000; | ||||
| var MANUAL_FADE_TIME = 300; | ||||
| var CURTAIN_SLIDE_TIME = 300; | ||||
|  | ||||
| var Clock = class { | ||||
|     constructor() { | ||||
|         this.actor = new St.BoxLayout({ style_class: 'screen-shield-clock', | ||||
|                                         vertical: true }); | ||||
| var Clock = GObject.registerClass( | ||||
| class ScreenShieldClock extends St.BoxLayout { | ||||
|     _init() { | ||||
|         super._init({ 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.add(this._time, { x_align: St.Align.MIDDLE }); | ||||
|         this.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(); | ||||
|  | ||||
|         this.connect('destroy', this._onDestroy.bind(this)); | ||||
|     } | ||||
|  | ||||
|     _updateClock() { | ||||
| @@ -73,17 +77,20 @@ var Clock = class { | ||||
|         this._date.text = date.toLocaleFormat(dateFormat); | ||||
|     } | ||||
|  | ||||
|     destroy() { | ||||
|         this.actor.destroy(); | ||||
|     _onDestroy() { | ||||
|         this._wallClock.run_dispose(); | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|  | ||||
| var NotificationsBox = class { | ||||
|     constructor() { | ||||
|         this.actor = new St.BoxLayout({ vertical: true, | ||||
|                                         name: 'screenShieldNotifications', | ||||
|                                         style_class: 'screen-shield-notifications-container' }); | ||||
| var NotificationsBox = GObject.registerClass({ | ||||
|     Signals: { 'wake-up-screen': {} } | ||||
| }, class NotificationsBox extends St.BoxLayout { | ||||
|     _init() { | ||||
|         super._init({ | ||||
|             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 }); | ||||
| @@ -91,7 +98,7 @@ var NotificationsBox = class { | ||||
|                                                    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.add(this._scrollView, { x_fill: true, x_align: St.Align.START }); | ||||
|  | ||||
|         this._sources = new Map(); | ||||
|         Main.messageTray.getSources().forEach(source => { | ||||
| @@ -100,9 +107,11 @@ var NotificationsBox = class { | ||||
|         this._updateVisibility(); | ||||
|  | ||||
|         this._sourceAddedId = Main.messageTray.connect('source-added', this._sourceAdded.bind(this)); | ||||
|  | ||||
|         this.connect('destroy', this._onDestroy.bind(this)); | ||||
|     } | ||||
|  | ||||
|     destroy() { | ||||
|     _onDestroy() { | ||||
|         if (this._sourceAddedId) { | ||||
|             Main.messageTray.disconnect(this._sourceAddedId); | ||||
|             this._sourceAddedId = 0; | ||||
| @@ -112,15 +121,13 @@ var NotificationsBox = class { | ||||
|         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; | ||||
|         this.visible = this._notificationBox.visible; | ||||
|     } | ||||
|  | ||||
|     _makeNotificationCountText(count, isChat) { | ||||
| @@ -173,8 +180,9 @@ var NotificationsBox = class { | ||||
|  | ||||
|             let body = ''; | ||||
|             if (n.bannerBodyText) { | ||||
|                 body = n.bannerBodyMarkup ? n.bannerBodyText | ||||
|                                           : GLib.markup_escape_text(n.bannerBodyText, -1); | ||||
|                 body = n.bannerBodyMarkup | ||||
|                     ? n.bannerBodyText | ||||
|                     : GLib.markup_escape_text(n.bannerBodyText, -1); | ||||
|             } | ||||
|  | ||||
|             let label = new St.Label({ style_class: 'screen-shield-notification-count-text' }); | ||||
| @@ -221,14 +229,14 @@ var NotificationsBox = class { | ||||
|         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 => { | ||||
|         obj.sourceCountChangedId = source.connect('notify::count', source => { | ||||
|             this._countChanged(source, obj); | ||||
|         }); | ||||
|         obj.sourceTitleChangedId = source.connect('title-changed', source => { | ||||
|         obj.sourceTitleChangedId = source.connect('notify::title', source => { | ||||
|             this._titleChanged(source, obj); | ||||
|         }); | ||||
|         obj.policyChangedId = source.policy.connect('policy-changed', (policy, key) => { | ||||
|             if (key == 'show-in-lock-screen') | ||||
|         obj.policyChangedId = source.policy.connect('notify', (policy, pspec) => { | ||||
|             if (pspec.name == 'show-in-lock-screen') | ||||
|                 this._visibleChanged(source, obj); | ||||
|             else | ||||
|                 this._detailedChanged(source, obj); | ||||
| @@ -335,8 +343,7 @@ var NotificationsBox = class { | ||||
|  | ||||
|         this._sources.delete(source); | ||||
|     } | ||||
| }; | ||||
| Signals.addSignalMethods(NotificationsBox.prototype); | ||||
| }); | ||||
|  | ||||
| var Arrow = GObject.registerClass( | ||||
| class ScreenShieldArrow extends St.Bin { | ||||
| @@ -485,7 +492,7 @@ var ScreenShield = class { | ||||
|         this._lockDialogGroup = new St.Widget({ x_expand: true, | ||||
|                                                 y_expand: true, | ||||
|                                                 reactive: true, | ||||
|                                                 pivot_point: new Clutter.Point({ x: 0.5, y: 0.5 }), | ||||
|                                                 pivot_point: new Graphene.Point({ x: 0.5, y: 0.5 }), | ||||
|                                                 name: 'lockDialogGroup' }); | ||||
|  | ||||
|         this.actor.add_actor(this._lockDialogGroup); | ||||
| @@ -556,11 +563,11 @@ var ScreenShield = class { | ||||
|         this._longLightbox = new Lightbox.Lightbox(Main.uiGroup, | ||||
|                                                    { inhibitEvents: true, | ||||
|                                                      fadeFactor: 1 }); | ||||
|         this._longLightbox.connect('shown', this._onLongLightboxShown.bind(this)); | ||||
|         this._longLightbox.connect('notify::active', this._onLongLightbox.bind(this)); | ||||
|         this._shortLightbox = new Lightbox.Lightbox(Main.uiGroup, | ||||
|                                                     { inhibitEvents: true, | ||||
|                                                       fadeFactor: 1 }); | ||||
|         this._shortLightbox.connect('shown', this._onShortLightboxShown.bind(this)); | ||||
|         this._shortLightbox.connect('notify::active', this._onShortLightbox.bind(this)); | ||||
|  | ||||
|         this.idleMonitor = Meta.IdleMonitor.get_core(); | ||||
|         this._cursorTracker = Meta.CursorTracker.get_for_display(global.display); | ||||
| @@ -806,7 +813,7 @@ var ScreenShield = class { | ||||
|  | ||||
|         this._maybeCancelDialog(); | ||||
|  | ||||
|         if (this._longLightbox.actor.visible) { | ||||
|         if (this._longLightbox.visible) { | ||||
|             // We're in the process of showing. | ||||
|             return; | ||||
|         } | ||||
| @@ -831,7 +838,7 @@ var ScreenShield = class { | ||||
|  | ||||
|         if (shouldLock) { | ||||
|             let lockTimeout = Math.max( | ||||
|                 STANDARD_FADE_TIME, | ||||
|                 adjustAnimationTime(STANDARD_FADE_TIME), | ||||
|                 this._settings.get_uint(LOCK_DELAY_KEY) * 1000); | ||||
|             this._lockTimeoutId = GLib.timeout_add( | ||||
|                 GLib.PRIORITY_DEFAULT, | ||||
| @@ -848,8 +855,8 @@ var ScreenShield = class { | ||||
|     } | ||||
|  | ||||
|     _activateFade(lightbox, time) { | ||||
|         Main.uiGroup.set_child_above_sibling(lightbox.actor, null); | ||||
|         lightbox.show(time); | ||||
|         Main.uiGroup.set_child_above_sibling(lightbox, null); | ||||
|         lightbox.lightOn(time); | ||||
|  | ||||
|         if (this._becameActiveId == 0) | ||||
|             this._becameActiveId = this.idleMonitor.add_user_active_watch(this._onUserBecameActive.bind(this)); | ||||
| @@ -878,19 +885,21 @@ var ScreenShield = class { | ||||
|         this._becameActiveId = 0; | ||||
|  | ||||
|         if (this._isActive || this._isLocked) { | ||||
|             this._longLightbox.hide(); | ||||
|             this._shortLightbox.hide(); | ||||
|             this._longLightbox.lightOff(); | ||||
|             this._shortLightbox.lightOff(); | ||||
|         } else { | ||||
|             this.deactivate(false); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     _onLongLightboxShown() { | ||||
|         this.activate(false); | ||||
|     _onLongLightbox(lightBox) { | ||||
|         if (lightBox.active) | ||||
|             this.activate(false); | ||||
|     } | ||||
|  | ||||
|     _onShortLightboxShown() { | ||||
|         this._completeLockScreenShown(); | ||||
|     _onShortLightbox(lightBox) { | ||||
|         if (lightBox.active) | ||||
|             this._completeLockScreenShown(); | ||||
|     } | ||||
|  | ||||
|     showDialog() { | ||||
| @@ -915,8 +924,8 @@ var ScreenShield = class { | ||||
|         this._lockScreenGroup.hide(); | ||||
|  | ||||
|         if (this._dialog) { | ||||
|             this._dialog.actor.grab_key_focus(); | ||||
|             this._dialog.actor.navigate_focus(null, St.DirectionType.TAB_FORWARD, false); | ||||
|             this._dialog.grab_key_focus(); | ||||
|             this._dialog.navigate_focus(null, St.DirectionType.TAB_FORWARD, false); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -964,7 +973,6 @@ var ScreenShield = class { | ||||
|  | ||||
|             this._dialog = new constructor(this._lockDialogGroup); | ||||
|  | ||||
|  | ||||
|             let time = global.get_current_time(); | ||||
|             if (!this._dialog.open(time, onPrimary)) { | ||||
|                 // This is kind of an impossible error: we're already modal | ||||
| @@ -1130,16 +1138,20 @@ var ScreenShield = class { | ||||
|                                                          vertical: true, | ||||
|                                                          style_class: 'screen-shield-contents-box' }); | ||||
|         this._clock = new Clock(); | ||||
|         this._lockScreenContentsBox.add(this._clock.actor, { x_fill: true, | ||||
|                                                              y_fill: true }); | ||||
|         this._lockScreenContentsBox.add(this._clock, { | ||||
|             x_fill: true, | ||||
|             y_fill: true | ||||
|         }); | ||||
|  | ||||
|         this._lockScreenContents.add_actor(this._lockScreenContentsBox); | ||||
|  | ||||
|         this._notificationsBox = new NotificationsBox(); | ||||
|         this._wakeUpScreenId = this._notificationsBox.connect('wake-up-screen', this._wakeUpScreen.bind(this)); | ||||
|         this._lockScreenContentsBox.add(this._notificationsBox.actor, { x_fill: true, | ||||
|                                                                         y_fill: true, | ||||
|                                                                         expand: true }); | ||||
|         this._lockScreenContentsBox.add(this._notificationsBox, { | ||||
|             x_fill: true, | ||||
|             y_fill: true, | ||||
|             expand: true | ||||
|         }); | ||||
|  | ||||
|         this._hasLockScreen = true; | ||||
|     } | ||||
| @@ -1232,8 +1244,8 @@ var ScreenShield = class { | ||||
|             this._dialog = null; | ||||
|         } | ||||
|  | ||||
|         this._longLightbox.hide(); | ||||
|         this._shortLightbox.hide(); | ||||
|         this._longLightbox.lightOff(); | ||||
|         this._shortLightbox.lightOff(); | ||||
|         this.actor.hide(); | ||||
|  | ||||
|         if (this._becameActiveId != 0) { | ||||
|   | ||||
| @@ -1,8 +1,7 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported ScreenshotService */ | ||||
|  | ||||
| const { Clutter, Gio, GLib, Meta, Shell, St } = imports.gi; | ||||
| const Signals = imports.signals; | ||||
| const { Clutter, Graphene, Gio, GObject, GLib, Meta, Shell, St } = imports.gi; | ||||
|  | ||||
| const GrabHelper = imports.ui.grabHelper; | ||||
| const Lightbox = imports.ui.lightbox; | ||||
| @@ -116,8 +115,8 @@ var ScreenshotService = class { | ||||
|                 try { | ||||
|                     let [result, area, filenameUsed] = | ||||
|                         screenshot.screenshot_area_finish(res); | ||||
|                     this._onScreenshotComplete(result, area, filenameUsed, | ||||
|                                                flash, invocation); | ||||
|                     this._onScreenshotComplete( | ||||
|                         result, area, filenameUsed, flash, invocation); | ||||
|                 } catch (e) { | ||||
|                     invocation.return_gerror (e); | ||||
|                 } | ||||
| @@ -134,8 +133,8 @@ var ScreenshotService = class { | ||||
|                 try { | ||||
|                     let [result, area, filenameUsed] = | ||||
|                         screenshot.screenshot_window_finish(res); | ||||
|                     this._onScreenshotComplete(result, area, filenameUsed, | ||||
|                                                flash, invocation); | ||||
|                     this._onScreenshotComplete( | ||||
|                         result, area, filenameUsed, flash, invocation); | ||||
|                 } catch (e) { | ||||
|                     invocation.return_gerror (e); | ||||
|                 } | ||||
| @@ -152,8 +151,8 @@ var ScreenshotService = class { | ||||
|                 try { | ||||
|                     let [result, area, filenameUsed] = | ||||
|                         screenshot.screenshot_finish(res); | ||||
|                     this._onScreenshotComplete(result, area, filenameUsed, | ||||
|                                                flash, invocation); | ||||
|                     this._onScreenshotComplete( | ||||
|                         result, area, filenameUsed, flash, invocation); | ||||
|                 } catch (e) { | ||||
|                     invocation.return_gerror (e); | ||||
|                 } | ||||
| @@ -198,7 +197,7 @@ var ScreenshotService = class { | ||||
|                 let screenshot = this._createScreenshot(invocation, false); | ||||
|                 if (!screenshot) | ||||
|                     return; | ||||
|                 screenshot.pick_color(...coords, (o, res) => { | ||||
|                 screenshot.pick_color(coords.x, coords.y, (_o, res) => { | ||||
|                     let [success_, color] = screenshot.pick_color_finish(res); | ||||
|                     let { red, green, blue } = color; | ||||
|                     let retval = GLib.Variant.new('(a{sv})', [{ | ||||
| @@ -219,62 +218,62 @@ var ScreenshotService = class { | ||||
|     } | ||||
| }; | ||||
|  | ||||
| var SelectArea = class { | ||||
|     constructor() { | ||||
| var SelectArea = GObject.registerClass({ | ||||
|     GTypeName: 'Screenshot_SelectArea', | ||||
|     Signals: { 'finished': { param_types: [Meta.Rectangle.$gtype] } } | ||||
| }, class SelectArea extends St.Widget { | ||||
|     _init() { | ||||
|         this._startX = -1; | ||||
|         this._startY = -1; | ||||
|         this._lastX = 0; | ||||
|         this._lastY = 0; | ||||
|         this._result = null; | ||||
|  | ||||
|         this._group = new St.Widget({ visible: false, | ||||
|                                       reactive: true, | ||||
|                                       x: 0, | ||||
|                                       y: 0 }); | ||||
|         Main.uiGroup.add_actor(this._group); | ||||
|         super._init({ | ||||
|             visible: false, | ||||
|             reactive: true, | ||||
|             x: 0, | ||||
|             y: 0 | ||||
|         }); | ||||
|         Main.uiGroup.add_actor(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)); | ||||
|         this._grabHelper = new GrabHelper.GrabHelper(this); | ||||
|  | ||||
|         let constraint = new Clutter.BindConstraint({ source: global.stage, | ||||
|                                                       coordinate: Clutter.BindCoordinate.ALL }); | ||||
|         this._group.add_constraint(constraint); | ||||
|         this.add_constraint(constraint); | ||||
|  | ||||
|         this._rubberband = new St.Widget({ | ||||
|             style_class: 'select-area-rubberband', | ||||
|             visible: false | ||||
|         }); | ||||
|         this._group.add_actor(this._rubberband); | ||||
|         this.add_actor(this._rubberband); | ||||
|     } | ||||
|  | ||||
|     show() { | ||||
|         if (!this._grabHelper.grab({ actor: this._group, | ||||
|     vfunc_show() { | ||||
|         if (!this._grabHelper.grab({ actor: this, | ||||
|                                      onUngrab: this._onUngrab.bind(this) })) | ||||
|             return; | ||||
|  | ||||
|         global.display.set_cursor(Meta.Cursor.CROSSHAIR); | ||||
|         Main.uiGroup.set_child_above_sibling(this._group, null); | ||||
|         this._group.visible = true; | ||||
|         Main.uiGroup.set_child_above_sibling(this, null); | ||||
|         super.vfunc_show(); | ||||
|     } | ||||
|  | ||||
|     _getGeometry() { | ||||
|         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 }; | ||||
|         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 | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     _onMotionEvent(actor, event) { | ||||
|     vfunc_motion_event(motionEvent) { | ||||
|         if (this._startX == -1 || this._startY == -1 || this._result) | ||||
|             return Clutter.EVENT_PROPAGATE; | ||||
|  | ||||
|         [this._lastX, this._lastY] = event.get_coords(); | ||||
|         [this._lastX, this._lastY] = [motionEvent.x, motionEvent.y]; | ||||
|         this._lastX = Math.floor(this._lastX); | ||||
|         this._lastY = Math.floor(this._lastY); | ||||
|         let geometry = this._getGeometry(); | ||||
| @@ -286,8 +285,8 @@ var SelectArea = class { | ||||
|         return Clutter.EVENT_PROPAGATE; | ||||
|     } | ||||
|  | ||||
|     _onButtonPress(actor, event) { | ||||
|         [this._startX, this._startY] = event.get_coords(); | ||||
|     vfunc_button_press_event(buttonEvent) { | ||||
|         [this._startX, this._startY] = [buttonEvent.x, buttonEvent.y]; | ||||
|         this._startX = Math.floor(this._startX); | ||||
|         this._startY = Math.floor(this._startY); | ||||
|         this._rubberband.set_position(this._startX, this._startY); | ||||
| @@ -295,9 +294,9 @@ var SelectArea = class { | ||||
|         return Clutter.EVENT_PROPAGATE; | ||||
|     } | ||||
|  | ||||
|     _onButtonRelease() { | ||||
|     vfunc_button_release_event() { | ||||
|         this._result = this._getGeometry(); | ||||
|         this._group.ease({ | ||||
|         this.ease({ | ||||
|             opacity: 0, | ||||
|             duration: 200, | ||||
|             mode: Clutter.AnimationMode.EASE_OUT_QUAD, | ||||
| @@ -311,43 +310,43 @@ var SelectArea = class { | ||||
|         this.emit('finished', this._result); | ||||
|  | ||||
|         GLib.idle_add(GLib.PRIORITY_DEFAULT, () => { | ||||
|             this._group.destroy(); | ||||
|             this.destroy(); | ||||
|             return GLib.SOURCE_REMOVE; | ||||
|         }); | ||||
|     } | ||||
| }; | ||||
| Signals.addSignalMethods(SelectArea.prototype); | ||||
| }); | ||||
|  | ||||
| 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 }); | ||||
|  | ||||
| var PickPixel = class { | ||||
|     constructor() { | ||||
|         this._result = null; | ||||
|  | ||||
|         this._group = new St.Widget({ visible: false, | ||||
|                                       reactive: true }); | ||||
|         Main.uiGroup.add_actor(this._group); | ||||
|         Main.uiGroup.add_actor(this); | ||||
|  | ||||
|         this._grabHelper = new GrabHelper.GrabHelper(this._group); | ||||
|  | ||||
|         this._group.connect('button-release-event', | ||||
|                             this._onButtonRelease.bind(this)); | ||||
|         this._grabHelper = new GrabHelper.GrabHelper(this); | ||||
|  | ||||
|         let constraint = new Clutter.BindConstraint({ source: global.stage, | ||||
|                                                       coordinate: Clutter.BindCoordinate.ALL }); | ||||
|         this._group.add_constraint(constraint); | ||||
|         this.add_constraint(constraint); | ||||
|     } | ||||
|  | ||||
|     show() { | ||||
|         if (!this._grabHelper.grab({ actor: this._group, | ||||
|     vfunc_show() { | ||||
|         if (!this._grabHelper.grab({ actor: this, | ||||
|                                      onUngrab: this._onUngrab.bind(this) })) | ||||
|             return; | ||||
|  | ||||
|         global.display.set_cursor(Meta.Cursor.CROSSHAIR); | ||||
|         Main.uiGroup.set_child_above_sibling(this._group, null); | ||||
|         this._group.visible = true; | ||||
|         Main.uiGroup.set_child_above_sibling(this, null); | ||||
|         super.vfunc_show(); | ||||
|     } | ||||
|  | ||||
|     _onButtonRelease(actor, event) { | ||||
|         this._result = event.get_coords(); | ||||
|     vfunc_button_release_event(buttonEvent) { | ||||
|         let { x, y } = buttonEvent; | ||||
|         this._result = new Graphene.Point({ x, y }); | ||||
|         this._grabHelper.ungrab(); | ||||
|         return Clutter.EVENT_PROPAGATE; | ||||
|     } | ||||
| @@ -357,29 +356,29 @@ var PickPixel = class { | ||||
|         this.emit('finished', this._result); | ||||
|  | ||||
|         GLib.idle_add(GLib.PRIORITY_DEFAULT, () => { | ||||
|             this._group.destroy(); | ||||
|             this.destroy(); | ||||
|             return GLib.SOURCE_REMOVE; | ||||
|         }); | ||||
|     } | ||||
| }; | ||||
| Signals.addSignalMethods(PickPixel.prototype); | ||||
| }); | ||||
|  | ||||
| var FLASHSPOT_ANIMATION_OUT_TIME = 500; // milliseconds | ||||
|  | ||||
| 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); | ||||
| 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); | ||||
|     } | ||||
|  | ||||
|     fire(doneCallback) { | ||||
|         this.actor.show(); | ||||
|         this.actor.opacity = 255; | ||||
|         this.actor.ease({ | ||||
|         this.set({ visible: true, opacity: 255 }); | ||||
|         this.ease({ | ||||
|             opacity: 0, | ||||
|             duration: FLASHSPOT_ANIMATION_OUT_TIME, | ||||
|             mode: Clutter.AnimationMode.EASE_OUT_QUAD, | ||||
| @@ -390,4 +389,4 @@ var Flashspot = class extends Lightbox.Lightbox { | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|   | ||||
| @@ -317,7 +317,7 @@ async function runPerfScript(scriptModule, outputFile) { | ||||
|  | ||||
|     for (let step of scriptModule.run()) { | ||||
|         try { | ||||
|             await step; | ||||
|             await step; // eslint-disable-line no-await-in-loop | ||||
|         } catch (err) { | ||||
|             log(`Script failed: ${err}\n${err.stack}`); | ||||
|             Meta.exit(Meta.ExitCode.ERROR); | ||||
|   | ||||
							
								
								
									
										238
									
								
								js/ui/search.js
									
									
									
									
									
								
							
							
						
						
									
										238
									
								
								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,39 +32,56 @@ class MaxWidthBox extends St.BoxLayout { | ||||
|     } | ||||
| }); | ||||
|  | ||||
| var SearchResult = class { | ||||
|     constructor(provider, metaInfo, resultsView) { | ||||
| 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) { | ||||
|         this.provider = provider; | ||||
|         this.metaInfo = metaInfo; | ||||
|         this._resultsView = resultsView; | ||||
|  | ||||
|         this.actor = new St.Button({ reactive: true, | ||||
|                                      can_focus: true, | ||||
|                                      track_hover: true, | ||||
|                                      x_align: St.Align.START, | ||||
|                                      y_fill: true }); | ||||
|         super._init({ | ||||
|             reactive: true, | ||||
|             can_focus: true, | ||||
|             track_hover: true, | ||||
|             x_align: St.Align.START, | ||||
|             y_fill: true | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|         this.actor._delegate = this; | ||||
|         this.actor.connect('clicked', this.activate.bind(this)); | ||||
|     vfunc_clicked() { | ||||
|         this.activate(); | ||||
|     } | ||||
|  | ||||
|     activate() { | ||||
|         this.emit('activate', this.metaInfo.id); | ||||
|         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(); | ||||
|     } | ||||
| }; | ||||
| Signals.addSignalMethods(SearchResult.prototype); | ||||
| }); | ||||
|  | ||||
| var ListSearchResult = class extends SearchResult { | ||||
| var ListSearchResult = GObject.registerClass( | ||||
| class ListSearchResult extends SearchResult { | ||||
|     _init(provider, metaInfo, resultsView) { | ||||
|         super._init(provider, metaInfo, resultsView); | ||||
|  | ||||
|     constructor(provider, metaInfo, resultsView) { | ||||
|         super(provider, metaInfo, resultsView); | ||||
|  | ||||
|         this.actor.style_class = 'list-search-result'; | ||||
|         this.actor.x_fill = true; | ||||
|         this.style_class = 'list-search-result'; | ||||
|         this.x_fill = true; | ||||
|  | ||||
|         let content = new St.BoxLayout({ style_class: 'list-search-result-content', | ||||
|                                          vertical: false }); | ||||
|         this.actor.set_child(content); | ||||
|         this.set_child(content); | ||||
|  | ||||
|         this._termsChangedId = 0; | ||||
|  | ||||
| @@ -87,7 +104,7 @@ var ListSearchResult = class extends SearchResult { | ||||
|                               x_align: St.Align.START, | ||||
|                               y_align: St.Align.MIDDLE }); | ||||
|  | ||||
|         this.actor.label_actor = title; | ||||
|         this.label_actor = title; | ||||
|  | ||||
|         if (this.metaInfo['description']) { | ||||
|             this._descriptionLabel = new St.Label({ style_class: 'list-search-result-description' }); | ||||
| @@ -103,7 +120,7 @@ var ListSearchResult = class extends SearchResult { | ||||
|             this._highlightTerms(); | ||||
|         } | ||||
|  | ||||
|         this.actor.connect('destroy', this._onDestroy.bind(this)); | ||||
|         this.connect('destroy', this._onDestroy.bind(this)); | ||||
|     } | ||||
|  | ||||
|     get ICON_SIZE() { | ||||
| @@ -120,50 +137,53 @@ var ListSearchResult = class extends SearchResult { | ||||
|             this._resultsView.disconnect(this._termsChangedId); | ||||
|         this._termsChangedId = 0; | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|  | ||||
| var GridSearchResult = class extends SearchResult { | ||||
|     constructor(provider, metaInfo, resultsView) { | ||||
|         super(provider, metaInfo, resultsView); | ||||
| var GridSearchResult = GObject.registerClass( | ||||
| class GridSearchResult extends SearchResult { | ||||
|     _init(provider, metaInfo, resultsView) { | ||||
|         super._init(provider, metaInfo, resultsView); | ||||
|  | ||||
|         this.actor.style_class = 'grid-search-result'; | ||||
|         this.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.actor.set_child(content); | ||||
|         this.actor.label_actor = this.icon.label; | ||||
|         this.set_child(content); | ||||
|         this.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.actor = new St.BoxLayout({ style_class: 'search-section', | ||||
|                                         vertical: true }); | ||||
|         this._focusChild = null; | ||||
|  | ||||
|         this._resultDisplayBin = new St.Bin({ x_fill: true, | ||||
|                                               y_fill: true }); | ||||
|         this.actor.add(this._resultDisplayBin, { expand: true }); | ||||
|         this.add(this._resultDisplayBin, { expand: true }); | ||||
|  | ||||
|         let separator = new St.Widget({ style_class: 'search-section-separator' }); | ||||
|         this.actor.add(separator); | ||||
|         this.add(separator); | ||||
|  | ||||
|         this._resultDisplays = {}; | ||||
|  | ||||
|         this._clipboard = St.Clipboard.get_default(); | ||||
|  | ||||
|         this._cancellable = new Gio.Cancellable(); | ||||
|  | ||||
|         this.actor.connect('destroy', this._onDestroy.bind(this)); | ||||
|     } | ||||
|  | ||||
|     destroy() { | ||||
|         this.actor.destroy(); | ||||
|         this.connect('destroy', this._onDestroy.bind(this)); | ||||
|     } | ||||
|  | ||||
|     _onDestroy() { | ||||
| @@ -180,21 +200,21 @@ var SearchResultsBase = class { | ||||
|     clear() { | ||||
|         this._cancellable.cancel(); | ||||
|         for (let resultId in this._resultDisplays) | ||||
|             this._resultDisplays[resultId].actor.destroy(); | ||||
|             this._resultDisplays[resultId].destroy(); | ||||
|         this._resultDisplays = {}; | ||||
|         this._clearResultDisplay(); | ||||
|         this.actor.hide(); | ||||
|         this.hide(); | ||||
|     } | ||||
|  | ||||
|     get focusChild() { | ||||
|         return this._focusChild; | ||||
|     } | ||||
|  | ||||
|     _keyFocusIn(actor) { | ||||
|         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(); | ||||
|         if (this._focusChild == actor) | ||||
|             return; | ||||
|         this._focusChild = actor; | ||||
|         this.notify('focus-child'); | ||||
|     } | ||||
|  | ||||
|     _setMoreCount(_count) { | ||||
| @@ -233,8 +253,9 @@ var SearchResultsBase = class { | ||||
|                 metasNeeded.forEach((resultId, i) => { | ||||
|                     let meta = metas[i]; | ||||
|                     let display = this._createResultDisplay(meta); | ||||
|                     display.connect('activate', this._activateResult.bind(this)); | ||||
|                     display.actor.connect('key-focus-in', this._keyFocusIn.bind(this)); | ||||
|                     if (!(display instanceof SearchResultInterface)) | ||||
|                         throw new Error(`${display} is not a valid search result`); | ||||
|                     display.connect('key-focus-in', this._keyFocusIn.bind(this)); | ||||
|                     this._resultDisplays[resultId] = display; | ||||
|                 }); | ||||
|                 callback(true); | ||||
| @@ -246,7 +267,7 @@ var SearchResultsBase = class { | ||||
|         this._terms = terms; | ||||
|         if (providerResults.length == 0) { | ||||
|             this._clearResultDisplay(); | ||||
|             this.actor.hide(); | ||||
|             this.hide(); | ||||
|             callback(); | ||||
|         } else { | ||||
|             let maxResults = this._getMaxDisplayedResults(); | ||||
| @@ -265,22 +286,23 @@ var SearchResultsBase = class { | ||||
|                 // To avoid CSS transitions causing flickering when | ||||
|                 // the first search result stays the same, we hide the | ||||
|                 // content while filling in the results. | ||||
|                 this.actor.hide(); | ||||
|                 this.hide(); | ||||
|                 this._clearResultDisplay(); | ||||
|                 results.forEach(resultId => { | ||||
|                     this._addItem(this._resultDisplays[resultId]); | ||||
|                 }); | ||||
|                 this._setMoreCount(this.provider.canLaunchSearch ? moreCount : 0); | ||||
|                 this.actor.show(); | ||||
|                 this.show(); | ||||
|                 callback(); | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|  | ||||
| var ListSearchResults = class extends SearchResultsBase { | ||||
|     constructor(provider, resultsView) { | ||||
|         super(provider, resultsView); | ||||
| var ListSearchResults = GObject.registerClass( | ||||
| class ListSearchResults extends SearchResultsBase { | ||||
|     _init(provider, resultsView) { | ||||
|         super._init(provider, resultsView); | ||||
|  | ||||
|         this._container = new St.BoxLayout({ style_class: 'search-section-content' }); | ||||
|         this.providerInfo = new ProviderInfo(provider); | ||||
| @@ -321,21 +343,21 @@ var ListSearchResults = class extends SearchResultsBase { | ||||
|     } | ||||
|  | ||||
|     _addItem(display) { | ||||
|         this._content.add_actor(display.actor); | ||||
|         this._content.add_actor(display); | ||||
|     } | ||||
|  | ||||
|     getFirstResult() { | ||||
|         if (this._content.get_n_children() > 0) | ||||
|             return this._content.get_child_at_index(0)._delegate; | ||||
|             return this._content.get_child_at_index(0); | ||||
|         else | ||||
|             return null; | ||||
|     } | ||||
| }; | ||||
| Signals.addSignalMethods(ListSearchResults.prototype); | ||||
| }); | ||||
|  | ||||
| var GridSearchResults = class extends SearchResultsBase { | ||||
|     constructor(provider, resultsView) { | ||||
|         super(provider, resultsView); | ||||
| var GridSearchResults = GObject.registerClass( | ||||
| class GridSearchResults extends SearchResultsBase { | ||||
|     _init(provider, resultsView) { | ||||
|         super._init(provider, resultsView); | ||||
|  | ||||
|         this._grid = new IconGrid.IconGrid({ rowLimit: MAX_GRID_SEARCH_RESULTS_ROWS, | ||||
|                                              xAlign: St.Align.START }); | ||||
| @@ -357,7 +379,7 @@ var GridSearchResults = class extends SearchResultsBase { | ||||
|  | ||||
|     updateSearch(...args) { | ||||
|         if (this._notifyAllocationId) | ||||
|             this.actor.disconnect(this._notifyAllocationId); | ||||
|             this.disconnect(this._notifyAllocationId); | ||||
|         if (this._updateSearchLater) { | ||||
|             Meta.later_remove(this._updateSearchLater); | ||||
|             delete this._updateSearchLater; | ||||
| @@ -365,7 +387,7 @@ var GridSearchResults = class extends SearchResultsBase { | ||||
|  | ||||
|         // Make sure the maximum number of results calculated by | ||||
|         // _getMaxDisplayedResults() is updated after width changes. | ||||
|         this._notifyAllocationId = this.actor.connect('notify::allocation', () => { | ||||
|         this._notifyAllocationId = this.connect('notify::allocation', () => { | ||||
|             if (this._updateSearchLater) | ||||
|                 return; | ||||
|             this._updateSearchLater = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => { | ||||
| @@ -379,7 +401,7 @@ var GridSearchResults = class extends SearchResultsBase { | ||||
|     } | ||||
|  | ||||
|     _getMaxDisplayedResults() { | ||||
|         let width = this.actor.allocation.x2 - this.actor.allocation.x1; | ||||
|         let width = this.allocation.get_width(); | ||||
|         if (width == 0) | ||||
|             return -1; | ||||
|  | ||||
| @@ -402,17 +424,17 @@ var GridSearchResults = class extends SearchResultsBase { | ||||
|  | ||||
|     getFirstResult() { | ||||
|         if (this._grid.visibleItemsCount() > 0) | ||||
|             return this._grid.getItemAtIndex(0)._delegate; | ||||
|             return this._grid.getItemAtIndex(0); | ||||
|         else | ||||
|             return null; | ||||
|     } | ||||
| }; | ||||
| Signals.addSignalMethods(GridSearchResults.prototype); | ||||
| }); | ||||
|  | ||||
| var SearchResults = class { | ||||
|     constructor() { | ||||
|         this.actor = new St.BoxLayout({ name: 'searchResults', | ||||
|                                         vertical: true }); | ||||
| var SearchResultsView = GObject.registerClass({ | ||||
|     Signals: { 'terms-changed': {} } | ||||
| }, class SearchResultsView extends St.BoxLayout { | ||||
|     _init() { | ||||
|         super._init({ name: 'searchResults', vertical: true }); | ||||
|  | ||||
|         this._content = new MaxWidthBox({ name: 'searchResultsContent', | ||||
|                                           vertical: true }); | ||||
| @@ -428,16 +450,18 @@ var SearchResults = class { | ||||
|         action.connect('pan', this._onPan.bind(this)); | ||||
|         this._scrollView.add_action(action); | ||||
|  | ||||
|         this.actor.add(this._scrollView, { x_fill: true, | ||||
|                                            y_fill: true, | ||||
|                                            expand: true, | ||||
|                                            x_align: St.Align.START, | ||||
|                                            y_align: St.Align.START }); | ||||
|         this.add(this._scrollView, { | ||||
|             x_fill: true, | ||||
|             y_fill: true, | ||||
|             expand: true, | ||||
|             x_align: St.Align.START, | ||||
|             y_align: St.Align.STAR | ||||
|         }); | ||||
|  | ||||
|         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.actor.add(this._statusBin, { expand: true }); | ||||
|         this.add(this._statusBin, { expand: true }); | ||||
|         this._statusBin.add_actor(this._statusText); | ||||
|  | ||||
|         this._highlightDefault = false; | ||||
| @@ -467,6 +491,10 @@ var SearchResults = class { | ||||
|         this._reloadRemoteProviders(); | ||||
|     } | ||||
|  | ||||
|     get terms() { | ||||
|         return this._terms; | ||||
|     } | ||||
|  | ||||
|     _reloadRemoteProviders() { | ||||
|         let remoteProviders = this._providers.filter(p => p.isRemoteProvider); | ||||
|         remoteProviders.forEach(provider => { | ||||
| @@ -591,12 +619,12 @@ var SearchResults = class { | ||||
|     _onPan(action) { | ||||
|         let [dist_, dx_, dy] = action.get_motion_delta(0); | ||||
|         let adjustment = this._scrollView.vscroll.adjustment; | ||||
|         adjustment.value -= (dy / this.actor.height) * adjustment.page_size; | ||||
|         adjustment.value -= (dy / this.height) * adjustment.page_size; | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     _keyFocusIn(provider, actor) { | ||||
|         Util.ensureActorVisibleInScrollView(this._scrollView, actor); | ||||
|     _focusChildChanged(provider) { | ||||
|         Util.ensureActorVisibleInScrollView(this._scrollView, provider.focusChild); | ||||
|     } | ||||
|  | ||||
|     _ensureProviderDisplay(provider) { | ||||
| @@ -609,9 +637,9 @@ var SearchResults = class { | ||||
|         else | ||||
|             providerDisplay = new GridSearchResults(provider, this); | ||||
|  | ||||
|         providerDisplay.connect('key-focus-in', this._keyFocusIn.bind(this)); | ||||
|         providerDisplay.actor.hide(); | ||||
|         this._content.add(providerDisplay.actor); | ||||
|         providerDisplay.connect('notify::focus-child', this._focusChildChanged.bind(this)); | ||||
|         providerDisplay.hide(); | ||||
|         this._content.add(providerDisplay); | ||||
|         provider.display = providerDisplay; | ||||
|     } | ||||
|  | ||||
| @@ -629,7 +657,7 @@ var SearchResults = class { | ||||
|             let provider = providers[i]; | ||||
|             let display = provider.display; | ||||
|  | ||||
|             if (!display.actor.visible) | ||||
|             if (!display.visible) | ||||
|                 continue; | ||||
|  | ||||
|             let firstResult = display.getFirstResult(); | ||||
| @@ -704,21 +732,22 @@ var SearchResults = class { | ||||
|             this._doSearch(); | ||||
|  | ||||
|         if (this._defaultResult) | ||||
|             this._defaultResult.actor.popup_menu(); | ||||
|             this._defaultResult.popup_menu(); | ||||
|     } | ||||
|  | ||||
|     navigateFocus(direction) { | ||||
|         let rtl = this.actor.get_text_direction() == Clutter.TextDirection.RTL; | ||||
|         let rtl = this.get_text_direction() == Clutter.TextDirection.RTL; | ||||
|         if (direction == St.DirectionType.TAB_BACKWARD || | ||||
|             direction == (rtl ? St.DirectionType.RIGHT | ||||
|                               : St.DirectionType.LEFT) || | ||||
|             direction == (rtl | ||||
|                 ? St.DirectionType.RIGHT | ||||
|                 : St.DirectionType.LEFT) || | ||||
|             direction == St.DirectionType.UP) { | ||||
|             this.actor.navigate_focus(null, direction, false); | ||||
|             this.navigate_focus(null, direction, false); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         let from = this._defaultResult ? this._defaultResult.actor : null; | ||||
|         this.actor.navigate_focus(from, direction, false); | ||||
|         let from = this._defaultResult ? this._defaultResult : null; | ||||
|         this.navigate_focus(from, direction, false); | ||||
|     } | ||||
|  | ||||
|     _setSelected(result, selected) { | ||||
| @@ -726,10 +755,10 @@ var SearchResults = class { | ||||
|             return; | ||||
|  | ||||
|         if (selected) { | ||||
|             result.actor.add_style_pseudo_class('selected'); | ||||
|             Util.ensureActorVisibleInScrollView(this._scrollView, result.actor); | ||||
|             result.add_style_pseudo_class('selected'); | ||||
|             Util.ensureActorVisibleInScrollView(this._scrollView, result); | ||||
|         } else { | ||||
|             result.actor.remove_style_pseudo_class('selected'); | ||||
|             result.remove_style_pseudo_class('selected'); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -742,8 +771,7 @@ var SearchResults = class { | ||||
|  | ||||
|         return description.replace(this._highlightRegex, '<b>$1</b>'); | ||||
|     } | ||||
| }; | ||||
| Signals.addSignalMethods(SearchResults.prototype); | ||||
| }); | ||||
|  | ||||
| var ProviderInfo = GObject.registerClass( | ||||
| class ProviderInfo extends St.Button { | ||||
|   | ||||
| @@ -92,11 +92,11 @@ const _modes = { | ||||
|         isLocked: false, | ||||
|         isPrimary: true, | ||||
|         unlockDialog: imports.ui.unlockDialog.UnlockDialog, | ||||
|         components: Config.HAVE_NETWORKMANAGER ? | ||||
|                     ['networkAgent', 'polkitAgent', 'telepathyClient', | ||||
|                      'keyring', 'autorunManager', 'automountManager'] : | ||||
|                     ['polkitAgent', 'telepathyClient', | ||||
|                      'keyring', 'autorunManager', 'automountManager'], | ||||
|         components: Config.HAVE_NETWORKMANAGER | ||||
|             ? ['networkAgent', 'polkitAgent', 'telepathyClient', | ||||
|                'keyring', 'autorunManager', 'automountManager'] | ||||
|             : ['polkitAgent', 'telepathyClient', | ||||
|                'keyring', 'autorunManager', 'automountManager'], | ||||
|  | ||||
|         panel: { | ||||
|             left: ['activities', 'appMenu'], | ||||
|   | ||||
| @@ -151,9 +151,13 @@ var GnomeShell = class { | ||||
|         let connection = this._dbusImpl.get_connection(); | ||||
|         let info = this._dbusImpl.get_info(); | ||||
|         let params = { 'device-id': GLib.Variant.new('u', device.get_device_id()), | ||||
|                        'device-node': GLib.Variant.new('s', device.get_device_node()), | ||||
|                        'timestamp': GLib.Variant.new('u', timestamp), | ||||
|                        'action-mode': GLib.Variant.new('u', Main.actionMode) }; | ||||
|  | ||||
|         let deviceNode = device.get_device_node(); | ||||
|         if (deviceNode) | ||||
|             params['device-node'] = GLib.Variant.new('s', deviceNode); | ||||
|  | ||||
|         connection.emit_signal(destination, | ||||
|                                this._dbusImpl.get_object_path(), | ||||
|                                info ? info.name : null, | ||||
|   | ||||
| @@ -2,7 +2,6 @@ | ||||
| /* 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; | ||||
| @@ -44,18 +43,22 @@ function _setLabelsForMessage(content, message) { | ||||
|  | ||||
| /* -------------------------------------------------------- */ | ||||
|  | ||||
| var ListItem = class { | ||||
|     constructor(app) { | ||||
|         this._app = app; | ||||
|  | ||||
| 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 | ||||
|         }); | ||||
|  | ||||
|         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._app = app; | ||||
|  | ||||
|         this._icon = this._app.create_icon_texture(LIST_ITEM_ICON_SIZE); | ||||
|  | ||||
| @@ -68,16 +71,13 @@ var ListItem = class { | ||||
|         let labelBin = new St.Bin({ y_align: St.Align.MIDDLE, | ||||
|                                     child: this._nameLabel }); | ||||
|         layout.add(labelBin); | ||||
|  | ||||
|         this.actor.connect('clicked', this._onClicked.bind(this)); | ||||
|     } | ||||
|  | ||||
|     _onClicked() { | ||||
|     vfunc_clicked() { | ||||
|         this.emit('activate'); | ||||
|         this._app.activate(); | ||||
|     } | ||||
| }; | ||||
| Signals.addSignalMethods(ListItem.prototype); | ||||
| }); | ||||
|  | ||||
| var ShellMountOperation = class { | ||||
|     constructor(source, params) { | ||||
| @@ -202,7 +202,7 @@ var ShellMountOperation = class { | ||||
|     _onShowUnmountProgress(op, message, timeLeft, bytesLeft) { | ||||
|         if (!this._notifier) | ||||
|             this._notifier = new ShellUnmountNotifier(); | ||||
|              | ||||
|  | ||||
|         if (bytesLeft == 0) | ||||
|             this._notifier.done(message); | ||||
|         else | ||||
| @@ -219,9 +219,10 @@ var ShellMountOperation = class { | ||||
|     } | ||||
| }; | ||||
|  | ||||
| var ShellUnmountNotifier = class extends MessageTray.Source { | ||||
|     constructor() { | ||||
|         super('', 'media-removable'); | ||||
| var ShellUnmountNotifier = GObject.registerClass( | ||||
| class ShellUnmountNotifier extends MessageTray.Source { | ||||
|     _init() { | ||||
|         super._init('', 'media-removable'); | ||||
|  | ||||
|         this._notification = null; | ||||
|         Main.messageTray.add(this); | ||||
| @@ -238,7 +239,7 @@ var ShellUnmountNotifier = class extends MessageTray.Source { | ||||
|             this._notification.update(header, text); | ||||
|         } | ||||
|  | ||||
|         this.notify(this._notification); | ||||
|         this.showNotification(this._notification); | ||||
|     } | ||||
|  | ||||
|     done(message) { | ||||
| @@ -251,10 +252,10 @@ var ShellUnmountNotifier = class extends MessageTray.Source { | ||||
|             let notification = new MessageTray.Notification(this, message, null); | ||||
|             notification.setTransient(true); | ||||
|  | ||||
|             this.notify(notification); | ||||
|             this.showNotification(notification); | ||||
|         } | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|  | ||||
| var ShellMountQuestionDialog = GObject.registerClass({ | ||||
|     Signals: { 'response': { param_types: [GObject.TYPE_INT] } } | ||||
| @@ -303,14 +304,14 @@ var ShellMountPasswordDialog = GObject.registerClass({ | ||||
|                                                   visible: false })); | ||||
|  | ||||
|             this._hiddenVolume = new CheckBox.CheckBox(_("Hidden Volume")); | ||||
|             content.messageBox.add(this._hiddenVolume.actor); | ||||
|             content.messageBox.add(this._hiddenVolume); | ||||
|  | ||||
|             this._systemVolume = new CheckBox.CheckBox(_("Windows System Volume")); | ||||
|             content.messageBox.add(this._systemVolume.actor); | ||||
|             content.messageBox.add(this._systemVolume); | ||||
|  | ||||
|             this._keyfilesCheckbox = new CheckBox.CheckBox(_("Uses Keyfiles")); | ||||
|             this._keyfilesCheckbox.actor.connect("clicked", this._onKeyfilesCheckboxClicked.bind(this)); | ||||
|             content.messageBox.add(this._keyfilesCheckbox.actor); | ||||
|             this._keyfilesCheckbox.connect("clicked", this._onKeyfilesCheckboxClicked.bind(this)); | ||||
|             content.messageBox.add(this._keyfilesCheckbox); | ||||
|  | ||||
|             this._keyfilesLabel.clutter_text.set_markup( | ||||
|                 /* Translators: %s is the Disks application */ | ||||
| @@ -360,7 +361,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.actor; | ||||
|         this._passwordEntry.secondary_icon = this._workSpinner; | ||||
|  | ||||
|         if (rtl) { | ||||
|             layout.attach(this._passwordEntry, 0, 1, 1, 1); | ||||
| @@ -381,9 +382,9 @@ var ShellMountPasswordDialog = GObject.registerClass({ | ||||
|  | ||||
|         if (flags & Gio.AskPasswordFlags.SAVING_SUPPORTED) { | ||||
|             this._rememberChoice = new CheckBox.CheckBox(_("Remember Password")); | ||||
|             this._rememberChoice.actor.checked = | ||||
|             this._rememberChoice.checked = | ||||
|                 global.settings.get_boolean(REMEMBER_MOUNT_PASSWORD_KEY); | ||||
|             content.messageBox.add(this._rememberChoice.actor); | ||||
|             content.messageBox.add(this._rememberChoice); | ||||
|         } else { | ||||
|             this._rememberChoice = null; | ||||
|         } | ||||
| @@ -439,22 +440,22 @@ var ShellMountPasswordDialog = GObject.registerClass({ | ||||
|         } | ||||
|  | ||||
|         global.settings.set_boolean(REMEMBER_MOUNT_PASSWORD_KEY, | ||||
|             this._rememberChoice && this._rememberChoice.actor.checked); | ||||
|             this._rememberChoice && this._rememberChoice.checked); | ||||
|  | ||||
|         this._workSpinner.play(); | ||||
|         this.emit('response', 1, | ||||
|             this._passwordEntry.get_text(), | ||||
|             this._rememberChoice && | ||||
|             this._rememberChoice.actor.checked, | ||||
|             this._rememberChoice.checked, | ||||
|             this._hiddenVolume && | ||||
|             this._hiddenVolume.actor.checked, | ||||
|             this._hiddenVolume.checked, | ||||
|             this._systemVolume && | ||||
|             this._systemVolume.actor.checked, | ||||
|             this._systemVolume.checked, | ||||
|             parseInt(pim)); | ||||
|     } | ||||
|  | ||||
|     _onKeyfilesCheckboxClicked() { | ||||
|         let useKeyfiles = this._keyfilesCheckbox.actor.checked; | ||||
|         let useKeyfiles = this._keyfilesCheckbox.checked; | ||||
|         this._passwordEntry.reactive = !useKeyfiles; | ||||
|         this._passwordEntry.can_focus = !useKeyfiles; | ||||
|         this._passwordEntry.clutter_text.editable = !useKeyfiles; | ||||
| @@ -463,8 +464,8 @@ var ShellMountPasswordDialog = GObject.registerClass({ | ||||
|         this._pimEntry.can_focus = !useKeyfiles; | ||||
|         this._pimEntry.clutter_text.editable = !useKeyfiles; | ||||
|         this._pimEntry.clutter_text.selectable = !useKeyfiles; | ||||
|         this._rememberChoice.actor.reactive = !useKeyfiles; | ||||
|         this._rememberChoice.actor.can_focus = !useKeyfiles; | ||||
|         this._rememberChoice.reactive = !useKeyfiles; | ||||
|         this._rememberChoice.can_focus = !useKeyfiles; | ||||
|         this._keyfilesLabel.visible = useKeyfiles; | ||||
|         this.setButtons(useKeyfiles ? this._usesKeyfilesButtons : this._defaultButtons); | ||||
|     } | ||||
| @@ -527,7 +528,7 @@ var ShellProcessesDialog = GObject.registerClass({ | ||||
|                 return; | ||||
|  | ||||
|             let item = new ListItem(app); | ||||
|             this._applicationList.add(item.actor, { x_fill: true }); | ||||
|             this._applicationList.add(item, { x_fill: true }); | ||||
|  | ||||
|             item.connect('activate', () => { | ||||
|                 // use -1 to indicate Cancel | ||||
|   | ||||
| @@ -22,12 +22,7 @@ var Slider = GObject.registerClass({ | ||||
|             accessible_role: Atk.Role.SLIDER | ||||
|         }); | ||||
|  | ||||
|         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._releaseId = 0; | ||||
|         this._dragging = false; | ||||
|  | ||||
|         this._customAccessible.connect('get-minimum-increment', this._getMinimumIncrement.bind(this)); | ||||
| @@ -62,8 +57,8 @@ var Slider = GObject.registerClass({ | ||||
|         cr.$dispose(); | ||||
|     } | ||||
|  | ||||
|     _startDragging(actor, event) { | ||||
|         return this.startDragging(event); | ||||
|     vfunc_button_press_event() { | ||||
|         return this.startDragging(Clutter.get_current_event()); | ||||
|     } | ||||
|  | ||||
|     startDragging(event) { | ||||
| @@ -83,11 +78,6 @@ 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'); | ||||
| @@ -100,10 +90,10 @@ var Slider = GObject.registerClass({ | ||||
|  | ||||
|     _endDragging() { | ||||
|         if (this._dragging) { | ||||
|             if (this._releaseId) | ||||
|             if (this._releaseId) { | ||||
|                 this.disconnect(this._releaseId); | ||||
|             if (this._motionId) | ||||
|                 this.disconnect(this._motionId); | ||||
|                 this._releaseId = 0; | ||||
|             } | ||||
|  | ||||
|             if (this._grabbedSequence != null) | ||||
|                 this._grabbedDevice.sequence_ungrab(this._grabbedSequence); | ||||
| @@ -119,7 +109,15 @@ var Slider = GObject.registerClass({ | ||||
|         return Clutter.EVENT_STOP; | ||||
|     } | ||||
|  | ||||
|     _touchDragging(actor, event) { | ||||
|     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(); | ||||
|         let device = event.get_device(); | ||||
|         let sequence = event.get_event_sequence(); | ||||
|  | ||||
| @@ -127,9 +125,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) == actor) { | ||||
|         } else if (device.sequence_get_grabbed_actor(sequence) == this) { | ||||
|             if (event.type() == Clutter.EventType.TOUCH_UPDATE) | ||||
|                 return this._motionEvent(actor, event); | ||||
|                 return this._motionEvent(this, event); | ||||
|             else if (event.type() == Clutter.EventType.TOUCH_END) | ||||
|                 return this._endDragging(); | ||||
|         } | ||||
| @@ -160,8 +158,15 @@ var Slider = GObject.registerClass({ | ||||
|         return Clutter.EVENT_STOP; | ||||
|     } | ||||
|  | ||||
|     _onScrollEvent(actor, event) { | ||||
|         return this.scroll(event); | ||||
|     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; | ||||
|     } | ||||
|  | ||||
|     _motionEvent(actor, event) { | ||||
| @@ -171,8 +176,8 @@ var Slider = GObject.registerClass({ | ||||
|         return Clutter.EVENT_STOP; | ||||
|     } | ||||
|  | ||||
|     onKeyPressEvent(actor, event) { | ||||
|         let key = event.get_key_symbol(); | ||||
|     vfunc_key_press_event(keyPressEvent) { | ||||
|         let key = keyPressEvent.keyval; | ||||
|         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.actor.reactive = false; | ||||
|             widget.reactive = false; | ||||
|         else | ||||
|             widget.connect('toggled', item => { | ||||
|                 onSet(item.state); | ||||
| @@ -179,8 +179,8 @@ class ATIndicator extends PanelMenu.Button { | ||||
|             settings.is_writable(KEY_TEXT_SCALING_FACTOR), | ||||
|             enabled => { | ||||
|                 if (enabled) | ||||
|                     settings.set_double(KEY_TEXT_SCALING_FACTOR, | ||||
|                                         DPI_FACTOR_LARGE); | ||||
|                     settings.set_double( | ||||
|                         KEY_TEXT_SCALING_FACTOR, DPI_FACTOR_LARGE); | ||||
|                 else | ||||
|                     settings.reset(KEY_TEXT_SCALING_FACTOR); | ||||
|             }); | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported Indicator */ | ||||
|  | ||||
| const { Gio, GnomeBluetooth } = imports.gi; | ||||
| const { Gio, GnomeBluetooth, GObject } = imports.gi; | ||||
|  | ||||
| const Main = imports.ui.main; | ||||
| const PanelMenu = imports.ui.panelMenu; | ||||
| @@ -17,9 +17,11 @@ const RfkillManagerProxy = Gio.DBusProxy.makeProxyWrapper(RfkillManagerInterface | ||||
|  | ||||
| const HAD_BLUETOOTH_DEVICES_SETUP = 'had-bluetooth-devices-setup'; | ||||
|  | ||||
| var Indicator = class extends PanelMenu.SystemIndicator { | ||||
|     constructor() { | ||||
|         super(); | ||||
| var Indicator = GObject.registerClass({ | ||||
|     GTypeName: 'Bluetooth_Indicator' | ||||
| }, class Indicator extends PanelMenu.SystemIndicator { | ||||
|     _init() { | ||||
|         super._init(); | ||||
|  | ||||
|         this._indicator = this._addIndicator(); | ||||
|         this._indicator.icon_name = 'bluetooth-active-symbolic'; | ||||
| @@ -133,4 +135,4 @@ var Indicator = class extends PanelMenu.SystemIndicator { | ||||
|  | ||||
|         this._toggleItem.label.text = this._proxy.BluetoothAirplaneMode ? _("Turn On") : _("Turn Off"); | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|   | ||||
| @@ -15,9 +15,11 @@ const OBJECT_PATH = '/org/gnome/SettingsDaemon/Power'; | ||||
| const BrightnessInterface = loadInterfaceXML('org.gnome.SettingsDaemon.Power.Screen'); | ||||
| const BrightnessProxy = Gio.DBusProxy.makeProxyWrapper(BrightnessInterface); | ||||
|  | ||||
| var Indicator = class extends PanelMenu.SystemIndicator { | ||||
|     constructor() { | ||||
|         super('display-brightness-symbolic'); | ||||
| var Indicator = GObject.registerClass({ | ||||
|     GTypeName: 'Brightness_Indicator' | ||||
| }, class Indicator extends PanelMenu.SystemIndicator { | ||||
|     _init() { | ||||
|         super._init(); | ||||
|         this._proxy = new BrightnessProxy(Gio.DBus.session, BUS_NAME, OBJECT_PATH, | ||||
|                                           (proxy, error) => { | ||||
|                                               if (error) { | ||||
| @@ -45,7 +47,7 @@ var Indicator = class extends PanelMenu.SystemIndicator { | ||||
|             return this._slider.startDragging(event); | ||||
|         }); | ||||
|         this._item.connect('key-press-event', (actor, event) => { | ||||
|             return this._slider.onKeyPressEvent(actor, event); | ||||
|             return this._slider.emit('key-press-event', event); | ||||
|         }); | ||||
|  | ||||
|     } | ||||
| @@ -67,4 +69,4 @@ var Indicator = class extends PanelMenu.SystemIndicator { | ||||
|         if (visible) | ||||
|             this._changeSlider(this._proxy.Brightness / 100.0); | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|   | ||||
| @@ -923,7 +923,7 @@ class InputSourceIndicator extends PanelMenu.Button { | ||||
|     } | ||||
|  | ||||
|     _buildPropSection(properties) { | ||||
|         this._propSeparator.actor.hide(); | ||||
|         this._propSeparator.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.actor.show(); | ||||
|             this._propSeparator.show(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -976,8 +976,8 @@ class InputSourceIndicator extends PanelMenu.Button { | ||||
|                 item.prop = prop; | ||||
|                 radioGroup.push(item); | ||||
|                 item.radioGroup = radioGroup; | ||||
|                 item.setOrnament(prop.get_state() == IBus.PropState.CHECKED ? | ||||
|                                  PopupMenu.Ornament.DOT : PopupMenu.Ornament.NONE); | ||||
|                 item.setOrnament(prop.get_state() == IBus.PropState.CHECKED | ||||
|                     ? PopupMenu.Ornament.DOT : PopupMenu.Ornament.NONE); | ||||
|                 item.connect('activate', () => { | ||||
|                     if (item.prop.get_state() == IBus.PropState.CHECKED) | ||||
|                         return; | ||||
|   | ||||
| @@ -42,9 +42,11 @@ const GeoclueManager = Gio.DBusProxy.makeProxyWrapper(GeoclueIface); | ||||
|  | ||||
| var AgentIface = loadInterfaceXML('org.freedesktop.GeoClue2.Agent'); | ||||
|  | ||||
| var Indicator = class extends PanelMenu.SystemIndicator { | ||||
|     constructor() { | ||||
|         super(); | ||||
| var Indicator = GObject.registerClass({ | ||||
|     GTypeName: 'Location_Indicator' | ||||
| }, class Indicator extends PanelMenu.SystemIndicator { | ||||
|     _init() { | ||||
|         super._init(); | ||||
|  | ||||
|         this._settings = new Gio.Settings({ schema_id: LOCATION_SCHEMA }); | ||||
|         this._settings.connect(`changed::${ENABLED}`, | ||||
| @@ -168,8 +170,9 @@ var Indicator = class extends PanelMenu.SystemIndicator { | ||||
|  | ||||
|     _updateMenuLabels() { | ||||
|         if (this._settings.get_boolean(ENABLED)) { | ||||
|             this._item.label.text = this._indicator.visible ? _("Location In Use") | ||||
|                                                             : _("Location Enabled"); | ||||
|             this._item.label.text = this._indicator.visible | ||||
|                 ? _("Location In Use") | ||||
|                 : _("Location Enabled"); | ||||
|             this._onOffAction.label.text = _("Disable"); | ||||
|         } else { | ||||
|             this._item.label.text = _("Location Disabled"); | ||||
| @@ -221,7 +224,7 @@ var Indicator = class extends PanelMenu.SystemIndicator { | ||||
|  | ||||
|         this._permStoreProxy = proxy; | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|  | ||||
| function clamp(value, min, max) { | ||||
|     return Math.max(min, Math.min(max, value)); | ||||
|   | ||||
| @@ -630,7 +630,6 @@ 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); | ||||
| @@ -659,6 +658,10 @@ var NMWirelessDialogItem = GObject.registerClass({ | ||||
|         this._sync(); | ||||
|     } | ||||
|  | ||||
|     vfunc_key_focus_in() { | ||||
|         this.emit('selected'); | ||||
|     } | ||||
|  | ||||
|     _sync() { | ||||
|         this._signalIcon.icon_name = this._getSignalIcon(); | ||||
|     } | ||||
| @@ -860,7 +863,7 @@ class NMWirelessDialog extends ModalDialog.ModalDialog { | ||||
|                                                  y_align: Clutter.ActorAlign.CENTER }); | ||||
|  | ||||
|         this._noNetworksSpinner = new Animation.Spinner(16); | ||||
|         this._noNetworksBox.add_actor(this._noNetworksSpinner.actor); | ||||
|         this._noNetworksBox.add_actor(this._noNetworksSpinner); | ||||
|         this._noNetworksBox.add_actor(new St.Label({ style_class: 'no-networks-label', | ||||
|                                                      text: _("No Networks") })); | ||||
|         this._stack.add_child(this._noNetworksBox); | ||||
| @@ -909,8 +912,8 @@ class NMWirelessDialog extends ModalDialog.ModalDialog { | ||||
|             this._client.activate_connection_async(connection, this._device, null, null, null); | ||||
|         } else { | ||||
|             let accessPoints = network.accessPoints; | ||||
|             if ((accessPoints[0]._secType == NMAccessPointSecurity.WPA2_ENT) | ||||
|                 || (accessPoints[0]._secType == NMAccessPointSecurity.WPA_ENT)) { | ||||
|             if ((accessPoints[0]._secType == NMAccessPointSecurity.WPA2_ENT) || | ||||
|                 (accessPoints[0]._secType == NMAccessPointSecurity.WPA_ENT)) { | ||||
|                 // 802.1x-enabled APs require further configuration, so they're | ||||
|                 // handled in gnome-control-center | ||||
|                 Util.spawn(['gnome-control-center', 'wifi', 'connect-8021x-wifi', | ||||
| @@ -1588,9 +1591,11 @@ var DeviceCategory = class extends PopupMenu.PopupMenuSection { | ||||
|     } | ||||
| }; | ||||
|  | ||||
| var NMApplet = class extends PanelMenu.SystemIndicator { | ||||
|     constructor() { | ||||
|         super(); | ||||
| var NMApplet = GObject.registerClass({ | ||||
|     GTypeName: 'Network_Indicator' | ||||
| }, class Indicator extends PanelMenu.SystemIndicator { | ||||
|     _init() { | ||||
|         super._init(); | ||||
|  | ||||
|         this._primaryIndicator = this._addIndicator(); | ||||
|         this._vpnIndicator = this._addIndicator(); | ||||
| @@ -1676,7 +1681,7 @@ var NMApplet = class extends PanelMenu.SystemIndicator { | ||||
|                                                   'network-transmit-receive'); | ||||
|             this._source.policy = new MessageTray.NotificationApplicationPolicy('gnome-network-panel'); | ||||
|  | ||||
|             this._source.connect('destroy', () => this._source = null); | ||||
|             this._source.connect('destroy', () => (this._source = null)); | ||||
|             Main.messageTray.add(this._source); | ||||
|         } | ||||
|     } | ||||
| @@ -1706,7 +1711,7 @@ var NMApplet = class extends PanelMenu.SystemIndicator { | ||||
|         this._notification.connect('destroy', () => { | ||||
|             this._notification = null; | ||||
|         }); | ||||
|         this._source.notify(this._notification); | ||||
|         this._source.showNotification(this._notification); | ||||
|     } | ||||
|  | ||||
|     _onActivationFailed(_device, _reason) { | ||||
| @@ -1939,7 +1944,7 @@ var NMApplet = class extends PanelMenu.SystemIndicator { | ||||
|     } | ||||
|  | ||||
|     _syncNMState() { | ||||
|         this.indicators.visible = this._client.nm_running; | ||||
|         this.visible = this._client.nm_running; | ||||
|         this.menu.actor.visible = this._client.networking_enabled; | ||||
|  | ||||
|         this._updateIcon(); | ||||
| @@ -1976,7 +1981,6 @@ var NMApplet = class extends PanelMenu.SystemIndicator { | ||||
|             // or we get to full connectivity through other means | ||||
|         } else if (result == PortalHelperResult.COMPLETED) { | ||||
|             this._closeConnectivityCheck(path); | ||||
|             return; | ||||
|         } else if (result == PortalHelperResult.RECHECK) { | ||||
|             this._client.check_connectivity_async(null, (client, result) => { | ||||
|                 try { | ||||
| @@ -2059,4 +2063,4 @@ var NMApplet = class extends PanelMenu.SystemIndicator { | ||||
|         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 = imports.gi.Gio; | ||||
| const { Gio, GObject } = imports.gi; | ||||
|  | ||||
| const Main = imports.ui.main; | ||||
| const PanelMenu = imports.ui.panelMenu; | ||||
| @@ -15,9 +15,11 @@ const OBJECT_PATH = '/org/gnome/SettingsDaemon/Color'; | ||||
| const ColorInterface = loadInterfaceXML('org.gnome.SettingsDaemon.Color'); | ||||
| const ColorProxy = Gio.DBusProxy.makeProxyWrapper(ColorInterface); | ||||
|  | ||||
| var Indicator = class extends PanelMenu.SystemIndicator { | ||||
|     constructor() { | ||||
|         super(); | ||||
| var Indicator = GObject.registerClass({ | ||||
|     GTypeName: 'NightLight_Indicator' | ||||
| }, class Indicator extends PanelMenu.SystemIndicator { | ||||
|     _init() { | ||||
|         super._init(); | ||||
|  | ||||
|         this._indicator = this._addIndicator(); | ||||
|         this._indicator.icon_name = 'night-light-symbolic'; | ||||
| @@ -58,10 +60,12 @@ var Indicator = class extends PanelMenu.SystemIndicator { | ||||
|         let visible = this._proxy.NightLightActive; | ||||
|         let disabled = this._proxy.DisabledUntilTomorrow; | ||||
|  | ||||
|         this._item.label.text = disabled ? _("Night Light Disabled") | ||||
|                                          : _("Night Light On"); | ||||
|         this._disableItem.label.text = disabled ? _("Resume") | ||||
|                                                 : _("Disable Until Tomorrow"); | ||||
|         this._item.label.text = disabled | ||||
|             ? _("Night Light Disabled") | ||||
|             : _("Night Light On"); | ||||
|         this._disableItem.label.text = disabled | ||||
|             ? _("Resume") | ||||
|             : _("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, St, UPowerGlib: UPower } = imports.gi; | ||||
| const { Clutter, Gio, GObject, St, UPowerGlib: UPower } = imports.gi; | ||||
|  | ||||
| const Main = imports.ui.main; | ||||
| const PanelMenu = imports.ui.panelMenu; | ||||
| @@ -17,9 +17,11 @@ const PowerManagerProxy = Gio.DBusProxy.makeProxyWrapper(DisplayDeviceInterface) | ||||
|  | ||||
| const SHOW_BATTERY_PERCENTAGE       = 'show-battery-percentage'; | ||||
|  | ||||
| var Indicator = class extends PanelMenu.SystemIndicator { | ||||
|     constructor() { | ||||
|         super(); | ||||
| var Indicator = GObject.registerClass({ | ||||
|     GTypeName: 'Power_Indicator' | ||||
| }, class Indicator extends PanelMenu.SystemIndicator { | ||||
|     _init() { | ||||
|         super._init(); | ||||
|  | ||||
|         this._desktopSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.interface' }); | ||||
|         this._desktopSettings.connect(`changed::${SHOW_BATTERY_PERCENTAGE}`, | ||||
| @@ -28,8 +30,8 @@ var Indicator = class extends PanelMenu.SystemIndicator { | ||||
|         this._indicator = this._addIndicator(); | ||||
|         this._percentageLabel = new St.Label({ y_expand: true, | ||||
|                                                y_align: Clutter.ActorAlign.CENTER }); | ||||
|         this.indicators.add(this._percentageLabel, { expand: true, y_fill: true }); | ||||
|         this.indicators.add_style_class_name('power-status'); | ||||
|         this.add(this._percentageLabel, { expand: true, y_fill: true }); | ||||
|         this.add_style_class_name('power-status'); | ||||
|  | ||||
|         this._proxy = new PowerManagerProxy(Gio.DBus.system, BUS_NAME, OBJECT_PATH, | ||||
|                                             (proxy, error) => { | ||||
| @@ -140,4 +142,4 @@ var Indicator = class extends PanelMenu.SystemIndicator { | ||||
|         // The status label | ||||
|         this._item.label.text = this._getStatus(); | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|   | ||||
| @@ -1,14 +1,16 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported RemoteAccessApplet */ | ||||
|  | ||||
| const Meta = imports.gi.Meta; | ||||
| const { GObject, Meta } = imports.gi; | ||||
|  | ||||
| const PanelMenu = imports.ui.panelMenu; | ||||
| const PopupMenu = imports.ui.popupMenu; | ||||
|  | ||||
| var RemoteAccessApplet = class extends PanelMenu.SystemIndicator { | ||||
|     constructor() { | ||||
|         super(); | ||||
| var RemoteAccessApplet = GObject.registerClass({ | ||||
|     GTypeName: 'RemoteAccess_Indicator' | ||||
| }, class RemoteAccessApplet extends PanelMenu.SystemIndicator { | ||||
|     _init() { | ||||
|         super._init(); | ||||
|  | ||||
|         let backend = Meta.get_backend(); | ||||
|         let controller = backend.get_remote_access_controller(); | ||||
| @@ -75,4 +77,4 @@ var RemoteAccessApplet = class extends PanelMenu.SystemIndicator { | ||||
|             this._sync(); | ||||
|         } | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported Indicator */ | ||||
|  | ||||
| const Gio = imports.gi.Gio; | ||||
| const { Gio, GObject } = imports.gi; | ||||
| const Signals = imports.signals; | ||||
|  | ||||
| const Main = imports.ui.main; | ||||
| @@ -61,9 +61,11 @@ function getRfkillManager() { | ||||
|     return _manager; | ||||
| } | ||||
|  | ||||
| var Indicator = class extends PanelMenu.SystemIndicator { | ||||
|     constructor() { | ||||
|         super(); | ||||
| var Indicator = GObject.registerClass({ | ||||
|     GTypeName: 'Rfkill_Indicator' | ||||
| }, class Indicator extends PanelMenu.SystemIndicator { | ||||
|     _init() { | ||||
|         super._init(); | ||||
|  | ||||
|         this._manager = getRfkillManager(); | ||||
|         this._manager.connect('airplane-mode-changed', this._sync.bind(this)); | ||||
| @@ -106,4 +108,4 @@ var Indicator = class extends PanelMenu.SystemIndicator { | ||||
|         else | ||||
|             this._offItem.label.text = _("Turn Off"); | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|   | ||||
| @@ -1,12 +1,16 @@ | ||||
| // -*- 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 = class extends PanelMenu.SystemIndicator { | ||||
|     constructor() { | ||||
|         super(); | ||||
| var Indicator = GObject.registerClass({ | ||||
|     GTypeName: 'Screencast_Indicator' | ||||
| }, class Indicator extends PanelMenu.SystemIndicator { | ||||
|     _init() { | ||||
|         super._init(); | ||||
|  | ||||
|         this._indicator = this._addIndicator(); | ||||
|         this._indicator.icon_name = 'media-record-symbolic'; | ||||
| @@ -19,4 +23,4 @@ var Indicator = class extends PanelMenu.SystemIndicator { | ||||
|     _sync() { | ||||
|         this._indicator.visible = Main.screencastService.isRecording; | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|   | ||||
| @@ -10,8 +10,10 @@ const PanelMenu = imports.ui.panelMenu; | ||||
| const PopupMenu = imports.ui.popupMenu; | ||||
|  | ||||
|  | ||||
| var AltSwitcher = class { | ||||
|     constructor(standard, alternate) { | ||||
| var AltSwitcher = GObject.registerClass( | ||||
| class AltSwitcher extends St.Bin { | ||||
|     _init(standard, alternate) { | ||||
|         super._init(); | ||||
|         this._standard = standard; | ||||
|         this._standard.connect('notify::visible', this._sync.bind(this)); | ||||
|         if (this._standard instanceof St.Button) | ||||
| @@ -31,9 +33,17 @@ var AltSwitcher = class { | ||||
|         this._clickAction = new Clutter.ClickAction(); | ||||
|         this._clickAction.connect('long-press', this._onLongPress.bind(this)); | ||||
|  | ||||
|         this.actor = new St.Bin(); | ||||
|         this.actor.connect('destroy', this._onDestroy.bind(this)); | ||||
|         this.actor.connect('notify::mapped', () => this._flipped = false); | ||||
|         this.connect('destroy', this._onDestroy.bind(this)); | ||||
|     } | ||||
|  | ||||
|     vfunc_map() { | ||||
|         super.vfunc_map(); | ||||
|         this._flipped = false; | ||||
|     } | ||||
|  | ||||
|     vfunc_unmap() { | ||||
|         super.vfunc_unmap(); | ||||
|         this._flipped = false; | ||||
|     } | ||||
|  | ||||
|     _sync() { | ||||
| @@ -51,11 +61,11 @@ var AltSwitcher = class { | ||||
|         } else if (this._alternate.visible) { | ||||
|             childToShow = this._alternate; | ||||
|         } else { | ||||
|             this.actor.hide(); | ||||
|             this.hide(); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         let childShown = this.actor.get_child(); | ||||
|         let childShown = this.get_child(); | ||||
|         if (childShown != childToShow) { | ||||
|             if (childShown) { | ||||
|                 if (childShown.fake_release) | ||||
| @@ -64,8 +74,8 @@ var AltSwitcher = class { | ||||
|             } | ||||
|             childToShow.add_action(this._clickAction); | ||||
|  | ||||
|             let hasFocus = this.actor.contains(global.stage.get_key_focus()); | ||||
|             this.actor.set_child(childToShow); | ||||
|             let hasFocus = this.contains(global.stage.get_key_focus()); | ||||
|             this.set_child(childToShow); | ||||
|             if (hasFocus) | ||||
|                 childToShow.grab_key_focus(); | ||||
|  | ||||
| @@ -74,7 +84,7 @@ var AltSwitcher = class { | ||||
|             global.sync_pointer(); | ||||
|         } | ||||
|  | ||||
|         this.actor.show(); | ||||
|         this.show(); | ||||
|     } | ||||
|  | ||||
|     _onDestroy() { | ||||
| @@ -104,11 +114,13 @@ var AltSwitcher = class { | ||||
|         this._sync(); | ||||
|         return true; | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|  | ||||
| var Indicator = class extends PanelMenu.SystemIndicator { | ||||
|     constructor() { | ||||
|         super(); | ||||
| var Indicator = GObject.registerClass({ | ||||
|     GTypeName: 'System_Indicator' | ||||
| }, class Indicator extends PanelMenu.SystemIndicator { | ||||
|     _init() { | ||||
|         super._init(); | ||||
|  | ||||
|         let userManager = AccountsService.UserManager.get_default(); | ||||
|         this._user = userManager.get_user(GLib.get_user_name()); | ||||
| @@ -289,7 +301,7 @@ var Indicator = class extends PanelMenu.SystemIndicator { | ||||
|                                           bindFlags); | ||||
|  | ||||
|         this._altSwitcher = new AltSwitcher(this._powerOffAction, this._suspendAction); | ||||
|         item.add(this._altSwitcher.actor, { expand: true, x_fill: false }); | ||||
|         item.add(this._altSwitcher, { expand: true, x_fill: false }); | ||||
|  | ||||
|         this.menu.addMenuItem(item); | ||||
|  | ||||
| @@ -297,7 +309,7 @@ var Indicator = class extends PanelMenu.SystemIndicator { | ||||
|             this._settingsAction, | ||||
|             this._orientationLockAction, | ||||
|             this._lockScreenAction, | ||||
|             this._altSwitcher.actor, | ||||
|             this._altSwitcher, | ||||
|         ]; | ||||
|  | ||||
|         for (let actor of visibilityGroup) { | ||||
| @@ -312,4 +324,4 @@ var Indicator = class extends PanelMenu.SystemIndicator { | ||||
|         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, Polkit, Shell } = imports.gi; | ||||
| const { Gio, GLib, GObject, Polkit, Shell } = imports.gi; | ||||
| const Signals = imports.signals; | ||||
|  | ||||
| const Main = imports.ui.main; | ||||
| @@ -156,12 +156,12 @@ var AuthRobot = class { | ||||
|  | ||||
|         /* check if authorization is enabled in the daemon. if not | ||||
|          * we won't even bother authorizing, because we will only | ||||
|          * get an error back. The exact contents of AuthMode might  | ||||
|          * get an error back. The exact contents of AuthMode might | ||||
|          * change in the future, but must contain AuthMode.ENABLED | ||||
|          * if it is enabled. */ | ||||
|         if (!cli.authMode.split('|').includes(AuthMode.ENABLED)) | ||||
|             return; | ||||
|          | ||||
|  | ||||
|         /* check if we should enroll the device */ | ||||
|         let res = [false]; | ||||
|         this.emit('enroll-device', dev, res); | ||||
| @@ -221,9 +221,11 @@ Signals.addSignalMethods(AuthRobot.prototype); | ||||
|  | ||||
| /* eof client.js  */ | ||||
|  | ||||
| var Indicator = class extends PanelMenu.SystemIndicator { | ||||
|     constructor() { | ||||
|         super(); | ||||
| var Indicator = GObject.registerClass({ | ||||
|     GTypeName: 'Thunderbolt_Indicator' | ||||
| }, class Indicator extends PanelMenu.SystemIndicator { | ||||
|     _init() { | ||||
|         super._init(); | ||||
|  | ||||
|         this._indicator = this._addIndicator(); | ||||
|         this._indicator.icon_name = 'thunderbolt-symbolic'; | ||||
| @@ -260,7 +262,7 @@ var Indicator = class extends PanelMenu.SystemIndicator { | ||||
|         if (!this._source) { | ||||
|             this._source = new MessageTray.Source(_("Thunderbolt"), | ||||
|                                                   'thunderbolt-symbolic'); | ||||
|             this._source.connect('destroy', () => this._source = null); | ||||
|             this._source.connect('destroy', () => (this._source = null)); | ||||
|  | ||||
|             Main.messageTray.add(this._source); | ||||
|         } | ||||
| @@ -284,7 +286,7 @@ var Indicator = class extends PanelMenu.SystemIndicator { | ||||
|             if (app) | ||||
|                 app.activate(); | ||||
|         }); | ||||
|         this._source.notify(this._notification); | ||||
|         this._source.showNotification(this._notification); | ||||
|     } | ||||
|  | ||||
|     /* Session callbacks */ | ||||
| @@ -334,4 +336,4 @@ var Indicator = class extends PanelMenu.SystemIndicator { | ||||
|         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.onKeyPressEvent(actor, event); | ||||
|             return this._slider.emit('key-press-event', event); | ||||
|         }); | ||||
|  | ||||
|         this._stream = null; | ||||
| @@ -228,9 +228,9 @@ var OutputStreamSlider = class extends StreamSlider { | ||||
|     } | ||||
|  | ||||
|     _updateSliderIcon() { | ||||
|         this._icon.icon_name = (this._hasHeadphones ? | ||||
|                                 'audio-headphones-symbolic' : | ||||
|                                 'audio-speakers-symbolic'); | ||||
|         this._icon.icon_name = (this._hasHeadphones | ||||
|             ? 'audio-headphones-symbolic' | ||||
|             : 'audio-speakers-symbolic'); | ||||
|     } | ||||
|  | ||||
|     _portChanged() { | ||||
| @@ -259,18 +259,17 @@ var InputStreamSlider = class extends StreamSlider { | ||||
|     _maybeShowInput() { | ||||
|         // only show input widgets if any application is recording audio | ||||
|         let showInput = false; | ||||
|         let recordingApps = this._control.get_source_outputs(); | ||||
|         if (this._stream && recordingApps) { | ||||
|             for (let i = 0; i < recordingApps.length; i++) { | ||||
|                 let outputStream = recordingApps[i]; | ||||
|                 let id = outputStream.get_application_id(); | ||||
|                 // but skip gnome-volume-control and pavucontrol | ||||
|                 // (that appear as recording because they show the input level) | ||||
|                 if (!id || (id != 'org.gnome.VolumeControl' && id != 'org.PulseAudio.pavucontrol')) { | ||||
|                     showInput = true; | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|         if (this._stream) { | ||||
|             // skip gnome-volume-control and pavucontrol which appear | ||||
|             // as recording because they show the input level | ||||
|             let skippedApps = [ | ||||
|                 'org.gnome.VolumeControl', | ||||
|                 'org.PulseAudio.pavucontrol' | ||||
|             ]; | ||||
|  | ||||
|             showInput = this._control.get_source_outputs().some(output => { | ||||
|                 return !skippedApps.includes(output.get_application_id()); | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         this._showInput = showInput; | ||||
| @@ -300,6 +299,9 @@ 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()); | ||||
| @@ -339,34 +341,44 @@ var VolumeMenu = class extends PopupMenu.PopupMenuSection { | ||||
|     getMaxLevel() { | ||||
|         return this._output.getMaxLevel(); | ||||
|     } | ||||
|  | ||||
|     getInputVisible() { | ||||
|         return this._input.item.visible; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| var Indicator = class extends PanelMenu.SystemIndicator { | ||||
|     constructor() { | ||||
|         super(); | ||||
| var Indicator = GObject.registerClass({ | ||||
|     GTypeName: 'Volume_Indicator' | ||||
| }, class Indicator extends PanelMenu.SystemIndicator { | ||||
|     _init() { | ||||
|         super._init(); | ||||
|  | ||||
|         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) { | ||||
|                 this.indicators.show(); | ||||
|             if (icon != null) | ||||
|                 this._primaryIndicator.icon_name = icon; | ||||
|             } else { | ||||
|                 this.indicators.hide(); | ||||
|             } | ||||
|             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(); | ||||
|         }); | ||||
|  | ||||
|         this.menu.addMenuItem(this._volumeMenu); | ||||
|  | ||||
|         this.indicators.connect('scroll-event', this._onScrollEvent.bind(this)); | ||||
|     } | ||||
|  | ||||
|     _onScrollEvent(actor, event) { | ||||
|         let result = this._volumeMenu.scroll(event); | ||||
|     vfunc_scroll_event() { | ||||
|         let result = this._volumeMenu.scroll(Clutter.get_current_event()); | ||||
|         if (result == Clutter.EVENT_PROPAGATE || this.menu.actor.mapped) | ||||
|             return result; | ||||
|  | ||||
| @@ -376,4 +388,4 @@ var Indicator = class extends PanelMenu.SystemIndicator { | ||||
|         Main.osdWindowManager.show(-1, gicon, null, level, maxLevel); | ||||
|         return result; | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|   | ||||
| @@ -105,12 +105,6 @@ 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)); | ||||
| @@ -166,9 +160,10 @@ var SwitcherPopup = GObject.registerClass({ | ||||
|         throw new GObject.NotImplementedError(`_keyPressHandler in ${this.constructor.name}`); | ||||
|     } | ||||
|  | ||||
|     _keyPressEvent(actor, event) { | ||||
|         let keysym = event.get_key_symbol(); | ||||
|         let action = global.display.get_keybinding_action(event.get_key_code(), event.get_state()); | ||||
|     vfunc_key_press_event(keyEvent) { | ||||
|         let keysym = keyEvent.keyval; | ||||
|         let action = global.display.get_keybinding_action( | ||||
|             keyEvent.hardware_keycode, keyEvent.modifier_state); | ||||
|  | ||||
|         this._disableHover(); | ||||
|  | ||||
| @@ -183,13 +178,13 @@ var SwitcherPopup = GObject.registerClass({ | ||||
|         return Clutter.EVENT_STOP; | ||||
|     } | ||||
|  | ||||
|     _keyReleaseEvent(actor, event) { | ||||
|     vfunc_key_release_event(keyEvent) { | ||||
|         if (this._modifierMask) { | ||||
|             let [x_, y_, mods] = global.get_pointer(); | ||||
|             let state = mods & this._modifierMask; | ||||
|  | ||||
|             if (state == 0) | ||||
|                 this._finish(event.get_time()); | ||||
|                 this._finish(keyEvent.time); | ||||
|         } else { | ||||
|             this._resetNoModsTimeout(); | ||||
|         } | ||||
| @@ -197,7 +192,8 @@ var SwitcherPopup = GObject.registerClass({ | ||||
|         return Clutter.EVENT_STOP; | ||||
|     } | ||||
|  | ||||
|     _clickedOutside() { | ||||
|     vfunc_button_press_event() { | ||||
|         /* We clicked outside */ | ||||
|         this.fadeAndDestroy(); | ||||
|         return Clutter.EVENT_PROPAGATE; | ||||
|     } | ||||
| @@ -209,8 +205,8 @@ var SwitcherPopup = GObject.registerClass({ | ||||
|             this._select(this._next()); | ||||
|     } | ||||
|  | ||||
|     _scrollEvent(actor, event) { | ||||
|         this._scrollHandler(event.get_scroll_direction()); | ||||
|     vfunc_scroll_event(scrollEvent) { | ||||
|         this._scrollHandler(scrollEvent.scroll_direction); | ||||
|         return Clutter.EVENT_PROPAGATE; | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -2,8 +2,7 @@ | ||||
| /* exported UnlockDialog */ | ||||
|  | ||||
| const { AccountsService, Atk, Clutter, | ||||
|         Gdm, Gio, GLib, Meta, Shell, St } = imports.gi; | ||||
| const Signals = imports.signals; | ||||
|         Gdm, Gio, GLib, GObject, Meta, Shell, St } = imports.gi; | ||||
|  | ||||
| const Layout = imports.ui.layout; | ||||
| const Main = imports.ui.main; | ||||
| @@ -13,15 +12,19 @@ const AuthPrompt = imports.gdm.authPrompt; | ||||
| // The timeout before going back automatically to the lock screen (in seconds) | ||||
| const IDLE_TIMEOUT = 2 * 60; | ||||
|  | ||||
| var UnlockDialog = class { | ||||
|     constructor(parentActor) { | ||||
|         this.actor = new St.Widget({ accessible_role: Atk.Role.WINDOW, | ||||
|                                      style_class: 'login-dialog', | ||||
|                                      layout_manager: new Clutter.BoxLayout(), | ||||
|                                      visible: false }); | ||||
| var UnlockDialog = GObject.registerClass({ | ||||
|     Signals: { 'failed': {} }, | ||||
| }, class UnlockDialog extends St.Widget { | ||||
|     _init(parentActor) { | ||||
|         super._init({ | ||||
|             accessible_role: Atk.Role.WINDOW, | ||||
|             style_class: 'login-dialog', | ||||
|             layout_manager: new Clutter.BoxLayout(), | ||||
|             visible: false, | ||||
|         }); | ||||
|  | ||||
|         this.actor.add_constraint(new Layout.MonitorConstraint({ primary: true })); | ||||
|         parentActor.add_child(this.actor); | ||||
|         this.add_constraint(new Layout.MonitorConstraint({ primary: true })); | ||||
|         parentActor.add_child(this); | ||||
|  | ||||
|         this._userManager = AccountsService.UserManager.get_default(); | ||||
|         this._userName = GLib.get_user_name(); | ||||
| @@ -32,7 +35,7 @@ var UnlockDialog = class { | ||||
|                                              y_align: Clutter.ActorAlign.CENTER, | ||||
|                                              x_expand: true, | ||||
|                                              y_expand: true }); | ||||
|         this.actor.add_child(this._promptBox); | ||||
|         this.add_child(this._promptBox); | ||||
|  | ||||
|         this._authPrompt = new AuthPrompt.AuthPrompt(new Gdm.Client(), AuthPrompt.AuthPromptMode.UNLOCK_ONLY); | ||||
|         this._authPrompt.connect('failed', this._fail.bind(this)); | ||||
| @@ -41,7 +44,7 @@ var UnlockDialog = class { | ||||
|         this._authPrompt.setPasswordChar('\u25cf'); | ||||
|         this._authPrompt.nextButton.label = _("Unlock"); | ||||
|  | ||||
|         this._promptBox.add_child(this._authPrompt.actor); | ||||
|         this._promptBox.add_child(this._authPrompt); | ||||
|  | ||||
|         this.allowCancel = false; | ||||
|  | ||||
| @@ -64,10 +67,12 @@ var UnlockDialog = class { | ||||
|         this._authPrompt.reset(); | ||||
|         this._updateSensitivity(true); | ||||
|  | ||||
|         Main.ctrlAltTabManager.addGroup(this.actor, _("Unlock Window"), 'dialog-password-symbolic'); | ||||
|         Main.ctrlAltTabManager.addGroup(this, _("Unlock Window"), 'dialog-password-symbolic'); | ||||
|  | ||||
|         this._idleMonitor = Meta.IdleMonitor.get_core(); | ||||
|         this._idleWatchId = this._idleMonitor.add_idle_watch(IDLE_TIMEOUT * 1000, this._escape.bind(this)); | ||||
|  | ||||
|         this.connect('destroy', this._onDestroy.bind(this)); | ||||
|     } | ||||
|  | ||||
|     _updateSensitivity(sensitive) { | ||||
| @@ -106,9 +111,8 @@ var UnlockDialog = class { | ||||
|         this._authPrompt.cancel(); | ||||
|     } | ||||
|  | ||||
|     destroy() { | ||||
|     _onDestroy() { | ||||
|         this.popModal(); | ||||
|         this.actor.destroy(); | ||||
|  | ||||
|         if (this._idleWatchId) { | ||||
|             this._idleMonitor.remove_watch(this._idleWatchId); | ||||
| @@ -131,13 +135,16 @@ var UnlockDialog = class { | ||||
|     } | ||||
|  | ||||
|     open(timestamp) { | ||||
|         this.actor.show(); | ||||
|         this.show(); | ||||
|  | ||||
|         if (this._isModal) | ||||
|             return true; | ||||
|  | ||||
|         if (!Main.pushModal(this.actor, { timestamp: timestamp, | ||||
|                                           actionMode: Shell.ActionMode.UNLOCK_SCREEN })) | ||||
|         let modalParams = { | ||||
|             timestamp, | ||||
|             actionMode: Shell.ActionMode.UNLOCK_SCREEN, | ||||
|         }; | ||||
|         if (!Main.pushModal(this, modalParams)) | ||||
|             return false; | ||||
|  | ||||
|         this._isModal = true; | ||||
| @@ -147,9 +154,8 @@ var UnlockDialog = class { | ||||
|  | ||||
|     popModal(timestamp) { | ||||
|         if (this._isModal) { | ||||
|             Main.popModal(this.actor, timestamp); | ||||
|             Main.popModal(this, timestamp); | ||||
|             this._isModal = false; | ||||
|         } | ||||
|     } | ||||
| }; | ||||
| Signals.addSignalMethods(UnlockDialog.prototype); | ||||
| }); | ||||
|   | ||||
| @@ -14,29 +14,47 @@ 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 = class { | ||||
|     constructor(user, params) { | ||||
|         this._user = user; | ||||
| var Avatar = GObject.registerClass({ | ||||
|     GTypeName: 'UserWidget_Avatar' | ||||
| }, class Avatar extends St.Bin { | ||||
|     _init(user, params) { | ||||
|         let themeContext = St.ThemeContext.get_for_stage(global.stage); | ||||
|         params = Params.parse(params, { reactive: false, | ||||
|                                         iconSize: AVATAR_ICON_SIZE, | ||||
|                                         styleClass: 'user-icon' }); | ||||
|         this._iconSize = params.iconSize; | ||||
|  | ||||
|         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 }); | ||||
|         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); | ||||
|  | ||||
|         // Monitor the scaling factor to make sure we recreate the avatar when needed. | ||||
|         let themeContext = St.ThemeContext.get_for_stage(global.stage); | ||||
|         themeContext.connect('notify::scale-factor', this.update.bind(this)); | ||||
|         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; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     setSensitive(sensitive) { | ||||
|         this.actor.can_focus = sensitive; | ||||
|         this.actor.reactive = sensitive; | ||||
|         this.reactive = sensitive; | ||||
|     } | ||||
|  | ||||
|     update() { | ||||
| @@ -45,21 +63,21 @@ var Avatar = class { | ||||
|             iconFile = null; | ||||
|  | ||||
|         if (iconFile) { | ||||
|             this.actor.child = null; | ||||
|             this.child = null; | ||||
|             let { scaleFactor } = St.ThemeContext.get_for_stage(global.stage); | ||||
|             this.actor.set_size( | ||||
|             this.set_size( | ||||
|                 this._iconSize * scaleFactor, | ||||
|                 this._iconSize * scaleFactor); | ||||
|             this.actor.style = ` | ||||
|             this.style = ` | ||||
|                 background-image: url("${iconFile}"); | ||||
|                 background-size: cover;`; | ||||
|         } else { | ||||
|             this.actor.style = null; | ||||
|             this.actor.child = new St.Icon({ icon_name: 'avatar-default-symbolic', | ||||
|                                              icon_size: this._iconSize }); | ||||
|             this.style = null; | ||||
|             this.child = new St.Icon({ icon_name: 'avatar-default-symbolic', | ||||
|                                        icon_size: this._iconSize }); | ||||
|         } | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|  | ||||
| var UserWidgetLabel = GObject.registerClass( | ||||
| class UserWidgetLabel extends St.Widget { | ||||
| @@ -140,21 +158,22 @@ class UserWidgetLabel extends St.Widget { | ||||
|     } | ||||
| }); | ||||
|  | ||||
| var UserWidget = class { | ||||
|     constructor(user) { | ||||
| var UserWidget = GObject.registerClass( | ||||
| class UserWidget extends St.BoxLayout { | ||||
|     _init(user) { | ||||
|         super._init({ style_class: 'user-widget', vertical: false }); | ||||
|  | ||||
|         this._user = user; | ||||
|  | ||||
|         this.actor = new St.BoxLayout({ style_class: 'user-widget', | ||||
|                                         vertical: false }); | ||||
|         this.actor.connect('destroy', this._onDestroy.bind(this)); | ||||
|         this.connect('destroy', this._onDestroy.bind(this)); | ||||
|  | ||||
|         this._avatar = new Avatar(user); | ||||
|         this.actor.add_child(this._avatar.actor); | ||||
|         this.add_child(this._avatar); | ||||
|  | ||||
|         this._label = new UserWidgetLabel(user); | ||||
|         this.actor.add_child(this._label); | ||||
|         this.add_child(this._label); | ||||
|  | ||||
|         this._label.bind_property('label-actor', this.actor, 'label-actor', | ||||
|         this._label.bind_property('label-actor', this, 'label-actor', | ||||
|                                   GObject.BindingFlags.SYNC_CREATE); | ||||
|  | ||||
|         this._userLoadedId = this._user.connect('notify::is-loaded', this._updateUser.bind(this)); | ||||
| @@ -177,4 +196,4 @@ var UserWidget = class { | ||||
|     _updateUser() { | ||||
|         this._avatar.update(); | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|   | ||||
| @@ -123,9 +123,14 @@ var ShowOverviewAction = GObject.registerClass({ | ||||
|     } | ||||
| }); | ||||
|  | ||||
| var ViewSelector = class { | ||||
|     constructor(searchEntry, showAppsButton) { | ||||
|         this.actor = new Shell.Stack({ name: 'viewSelector' }); | ||||
| var ViewSelector = GObject.registerClass({ | ||||
|     Signals: { | ||||
|         'page-changed': {}, | ||||
|         'page-empty': {}, | ||||
|     } | ||||
| }, class ViewSelector extends Shell.Stack { | ||||
|     _init(searchEntry, showAppsButton) { | ||||
|         super._init({ name: 'viewSelector' }); | ||||
|  | ||||
|         this._showAppsButton = showAppsButton; | ||||
|         this._showAppsButton.connect('notify::checked', this._onShowAppsButtonToggled.bind(this)); | ||||
| @@ -165,15 +170,15 @@ var ViewSelector = class { | ||||
|         this._capturedEventId = 0; | ||||
|  | ||||
|         this._workspacesDisplay = new WorkspacesView.WorkspacesDisplay(); | ||||
|         this._workspacesPage = this._addPage(this._workspacesDisplay.actor, | ||||
|         this._workspacesPage = this._addPage(this._workspacesDisplay, | ||||
|                                              _("Windows"), 'focus-windows-symbolic'); | ||||
|  | ||||
|         this.appDisplay = new AppDisplay.AppDisplay(); | ||||
|         this._appsPage = this._addPage(this.appDisplay.actor, | ||||
|         this._appsPage = this._addPage(this.appDisplay, | ||||
|                                        _("Applications"), 'view-app-grid-symbolic'); | ||||
|  | ||||
|         this._searchResults = new Search.SearchResults(); | ||||
|         this._searchPage = this._addPage(this._searchResults.actor, | ||||
|         this._searchResults = new Search.SearchResultsView(); | ||||
|         this._searchPage = this._addPage(this._searchResults, | ||||
|                                          _("Search"), 'edit-find-symbolic', | ||||
|                                          { a11yFocus: this._entry }); | ||||
|  | ||||
| @@ -184,9 +189,9 @@ var ViewSelector = class { | ||||
|         this._focusTrap.connect('key-focus-in', () => { | ||||
|             this._entry.grab_key_focus(); | ||||
|         }); | ||||
|         this._searchResults.actor.add_actor(this._focusTrap); | ||||
|         this._searchResults.add_actor(this._focusTrap); | ||||
|  | ||||
|         global.focus_manager.add_group(this._searchResults.actor); | ||||
|         global.focus_manager.add_group(this._searchResults); | ||||
|  | ||||
|         this._stageKeyPressId = 0; | ||||
|         Main.overview.connect('showing', () => { | ||||
| @@ -310,11 +315,11 @@ var ViewSelector = class { | ||||
|             Main.ctrlAltTabManager.addGroup(params.a11yFocus, name, a11yIcon); | ||||
|         else | ||||
|             Main.ctrlAltTabManager.addGroup(actor, name, a11yIcon, { | ||||
|                 proxy: this.actor, | ||||
|                 proxy: this, | ||||
|                 focusCallback: () => this._a11yFocusPage(page), | ||||
|             }); | ||||
|         page.hide(); | ||||
|         this.actor.add_actor(page); | ||||
|         this.add_actor(page); | ||||
|         return page; | ||||
|     } | ||||
|  | ||||
| @@ -389,8 +394,8 @@ var ViewSelector = class { | ||||
|     } | ||||
|  | ||||
|     _onShowAppsButtonToggled() { | ||||
|         this._showPage(this._showAppsButton.checked ? | ||||
|                        this._appsPage : this._workspacesPage); | ||||
|         this._showPage(this._showAppsButton.checked | ||||
|             ? this._appsPage : this._workspacesPage); | ||||
|     } | ||||
|  | ||||
|     _onStageKeyPress(actor, event) { | ||||
| @@ -424,8 +429,9 @@ var ViewSelector = class { | ||||
|     } | ||||
|  | ||||
|     _searchCancelled() { | ||||
|         this._showPage(this._showAppsButton.checked ? this._appsPage | ||||
|                                                     : this._workspacesPage); | ||||
|         this._showPage(this._showAppsButton.checked | ||||
|             ? this._appsPage | ||||
|             : this._workspacesPage); | ||||
|  | ||||
|         // Leave the entry focused when it doesn't have any text; | ||||
|         // when replacing a selected search term, Clutter emits | ||||
| @@ -453,7 +459,7 @@ var ViewSelector = class { | ||||
|     _onStageKeyFocusChanged() { | ||||
|         let focus = global.stage.get_key_focus(); | ||||
|         let appearFocused = (this._entry.contains(focus) || | ||||
|                              this._searchResults.actor.contains(focus)); | ||||
|                              this._searchResults.contains(focus)); | ||||
|  | ||||
|         this._text.set_cursor_visible(appearFocused); | ||||
|  | ||||
| @@ -576,6 +582,7 @@ var ViewSelector = class { | ||||
|         if (event.type() == Clutter.EventType.BUTTON_PRESS) { | ||||
|             let source = event.get_source(); | ||||
|             if (source != this._text && | ||||
|                 this._text.has_key_focus() && | ||||
|                 this._text.text == '' && | ||||
|                 !this._text.has_preedit () && | ||||
|                 !Main.layoutManager.keyboardBox.contains(source)) { | ||||
| @@ -597,5 +604,4 @@ var ViewSelector = class { | ||||
|         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 Shell = imports.gi.Shell; | ||||
| const { GObject, Shell } = imports.gi; | ||||
|  | ||||
| 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 Source(app, window); | ||||
|         let source = new WindowAttentionSource(app, window); | ||||
|         Main.messageTray.add(source); | ||||
|  | ||||
|         let [title, banner] = this._getTitleAndBanner(app, window); | ||||
| @@ -45,7 +45,7 @@ var WindowAttentionHandler = class { | ||||
|         }); | ||||
|         notification.setForFeedback(true); | ||||
|  | ||||
|         source.notify(notification); | ||||
|         source.showNotification(notification); | ||||
|  | ||||
|         source.signalIDs.push(window.connect('notify::title', () => { | ||||
|             let [title, banner] = this._getTitleAndBanner(app, window); | ||||
| @@ -54,9 +54,10 @@ var WindowAttentionHandler = class { | ||||
|     } | ||||
| }; | ||||
|  | ||||
| var Source = class WindowAttentionSource extends MessageTray.Source { | ||||
|     constructor(app, window) { | ||||
|         super(app.get_name()); | ||||
| var WindowAttentionSource = GObject.registerClass( | ||||
| class WindowAttentionSource extends MessageTray.Source { | ||||
|     _init(app, window) { | ||||
|         super._init(app.get_name()); | ||||
|  | ||||
|         this._window = window; | ||||
|         this._app = app; | ||||
| @@ -102,4 +103,4 @@ var Source = class WindowAttentionSource extends MessageTray.Source { | ||||
|     open() { | ||||
|         Main.activateWindow(this._window); | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|   | ||||
| @@ -40,6 +40,8 @@ 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) { | ||||
| @@ -114,21 +116,20 @@ class DisplayChangeDialog extends ModalDialog.ModalDialog { | ||||
|     } | ||||
| }); | ||||
|  | ||||
| var WindowDimmer = class { | ||||
|     constructor(actor) { | ||||
|         this._brightnessEffect = new Clutter.BrightnessContrastEffect({ | ||||
|             name: 'dim', | ||||
| var WindowDimmer = GObject.registerClass( | ||||
| class WindowDimmer extends Clutter.BrightnessContrastEffect { | ||||
|     _init() { | ||||
|         super._init({ | ||||
|             name: WINDOW_DIMMER_EFFECT_NAME, | ||||
|             enabled: false | ||||
|         }); | ||||
|         actor.add_effect(this._brightnessEffect); | ||||
|         this.actor = actor; | ||||
|         this._enabled = true; | ||||
|     } | ||||
|  | ||||
|     _syncEnabled() { | ||||
|         let animating = this.actor.get_transition('@effects.dim.brightness') != null; | ||||
|         let dimmed = this._brightnessEffect.brightness.red != 127; | ||||
|         this._brightnessEffect.enabled = this._enabled && (animating || dimmed); | ||||
|         let animating = this.actor.get_transition(`@effects.${this.name}.brightness`) != null; | ||||
|         let dimmed = this.brightness.red != 127; | ||||
|         this.enabled = this._enabled && (animating || dimmed); | ||||
|     } | ||||
|  | ||||
|     setEnabled(enabled) { | ||||
| @@ -140,7 +141,7 @@ var WindowDimmer = class { | ||||
|         let val = 127 * (1 + (dimmed ? 1 : 0) * DIM_BRIGHTNESS); | ||||
|         let color = Clutter.Color.new(val, val, val, 255); | ||||
|  | ||||
|         this.actor.ease_property('@effects.dim.brightness', color, { | ||||
|         this.actor.ease_property(`@effects.${this.name}.brightness`, color, { | ||||
|             mode: Clutter.AnimationMode.LINEAR, | ||||
|             duration: (dimmed ? DIM_TIME : UNDIM_TIME) * (animate ? 1 : 0), | ||||
|             onComplete: () => this._syncEnabled() | ||||
| @@ -148,20 +149,19 @@ var WindowDimmer = class { | ||||
|  | ||||
|         this._syncEnabled(); | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|  | ||||
| function getWindowDimmer(actor) { | ||||
|     let enabled = Meta.prefs_get_attach_modal_dialogs(); | ||||
|     if (actor._windowDimmer) | ||||
|         actor._windowDimmer.setEnabled(enabled); | ||||
|     let effect = actor.get_effect(WINDOW_DIMMER_EFFECT_NAME); | ||||
|  | ||||
|     if (enabled) { | ||||
|         if (!actor._windowDimmer) | ||||
|             actor._windowDimmer = new WindowDimmer(actor); | ||||
|         return actor._windowDimmer; | ||||
|     } else { | ||||
|         return null; | ||||
|     if (effect) { | ||||
|         effect.setEnabled(enabled); | ||||
|     } else if (enabled) { | ||||
|         effect = new WindowDimmer(); | ||||
|         actor.add_effect(effect); | ||||
|     } | ||||
|     return effect; | ||||
| } | ||||
|  | ||||
| /* | ||||
| @@ -187,6 +187,9 @@ var WorkspaceTracker = class { | ||||
|         let workspaceManager = global.workspace_manager; | ||||
|         workspaceManager.connect('notify::n-workspaces', | ||||
|                                  this._nWorkspacesChanged.bind(this)); | ||||
|         workspaceManager.connect('workspaces-reordered', () => { | ||||
|             this._workspaces.sort((a, b) => a.index() - b.index()); | ||||
|         }); | ||||
|         global.window_manager.connect('switch-workspace', | ||||
|                                       this._queueCheckWorkspaces.bind(this)); | ||||
|  | ||||
| @@ -376,21 +379,22 @@ var WorkspaceTracker = class { | ||||
|     } | ||||
| }; | ||||
|  | ||||
| var TilePreview = class { | ||||
|     constructor() { | ||||
|         this.actor = new St.Widget(); | ||||
|         global.window_group.add_actor(this.actor); | ||||
| var TilePreview = GObject.registerClass( | ||||
| class TilePreview extends St.Widget { | ||||
|     _init() { | ||||
|         super._init(); | ||||
|         global.window_group.add_actor(this); | ||||
|  | ||||
|         this._reset(); | ||||
|         this._showing = false; | ||||
|     } | ||||
|  | ||||
|     show(window, tileRect, monitorIndex) { | ||||
|     open(window, tileRect, monitorIndex) { | ||||
|         let windowActor = window.get_compositor_private(); | ||||
|         if (!windowActor) | ||||
|             return; | ||||
|  | ||||
|         global.window_group.set_child_below_sibling(this.actor, windowActor); | ||||
|         global.window_group.set_child_below_sibling(this, windowActor); | ||||
|  | ||||
|         if (this._rect && this._rect.equal(tileRect)) | ||||
|             return; | ||||
| @@ -411,14 +415,14 @@ var TilePreview = class { | ||||
|                                                    width: monitor.width, | ||||
|                                                    height: monitor.height }); | ||||
|             let [, rect] = window.get_frame_rect().intersect(monitorRect); | ||||
|             this.actor.set_size(rect.width, rect.height); | ||||
|             this.actor.set_position(rect.x, rect.y); | ||||
|             this.actor.opacity = 0; | ||||
|             this.set_size(rect.width, rect.height); | ||||
|             this.set_position(rect.x, rect.y); | ||||
|             this.opacity = 0; | ||||
|         } | ||||
|  | ||||
|         this._showing = true; | ||||
|         this.actor.show(); | ||||
|         this.actor.ease({ | ||||
|         this.show(); | ||||
|         this.ease({ | ||||
|             x: tileRect.x, | ||||
|             y: tileRect.y, | ||||
|             width: tileRect.width, | ||||
| @@ -429,12 +433,12 @@ var TilePreview = class { | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     hide() { | ||||
|     close() { | ||||
|         if (!this._showing) | ||||
|             return; | ||||
|  | ||||
|         this._showing = false; | ||||
|         this.actor.ease({ | ||||
|         this.ease({ | ||||
|             opacity: 0, | ||||
|             duration: WINDOW_ANIMATION_TIME, | ||||
|             mode: Clutter.AnimationMode.EASE_OUT_QUAD, | ||||
| @@ -443,7 +447,7 @@ var TilePreview = class { | ||||
|     } | ||||
|  | ||||
|     _reset() { | ||||
|         this.actor.hide(); | ||||
|         this.hide(); | ||||
|         this._rect = null; | ||||
|         this._monitorIndex = -1; | ||||
|     } | ||||
| @@ -457,9 +461,9 @@ var TilePreview = class { | ||||
|         if (this._rect.x + this._rect.width == monitor.x + monitor.width) | ||||
|             styles.push('tile-preview-right'); | ||||
|  | ||||
|         this.actor.style_class = styles.join(' '); | ||||
|         this.style_class = styles.join(' '); | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|  | ||||
| var TouchpadWorkspaceSwitchAction = class { | ||||
|     constructor(actor, allowedModes) { | ||||
| @@ -630,9 +634,9 @@ var AppSwitchAction = GObject.registerClass({ | ||||
|         let nPoints = this.get_n_current_points(); | ||||
|         let event = this.get_last_event (nPoints - 1); | ||||
|  | ||||
|         if (nPoints == 3) | ||||
|         if (nPoints == 3) { | ||||
|             this._longPressStartTime = event.get_time(); | ||||
|         else if (nPoints == 4) { | ||||
|         } else if (nPoints == 4) { | ||||
|             // Check whether the 4th finger press happens after a 3-finger long press, | ||||
|             // this only needs to be checked on the first 4th finger press | ||||
|             if (this._longPressStartTime != null && | ||||
| @@ -666,15 +670,16 @@ var AppSwitchAction = GObject.registerClass({ | ||||
|     } | ||||
| }); | ||||
|  | ||||
| var ResizePopup = class { | ||||
|     constructor() { | ||||
|         this._widget = new St.Widget({ layout_manager: new Clutter.BinLayout() }); | ||||
| var ResizePopup = GObject.registerClass( | ||||
| class ResizePopup extends St.Widget { | ||||
|     _init() { | ||||
|         super._init({ 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._widget.add_child(this._label); | ||||
|         Main.uiGroup.add_actor(this._widget); | ||||
|         this.add_child(this._label); | ||||
|         Main.uiGroup.add_actor(this); | ||||
|     } | ||||
|  | ||||
|     set(rect, displayW, displayH) { | ||||
| @@ -683,15 +688,10 @@ var ResizePopup = class { | ||||
|         let text = _("%d × %d").format(displayW, displayH); | ||||
|         this._label.set_text(text); | ||||
|  | ||||
|         this._widget.set_position(rect.x, rect.y); | ||||
|         this._widget.set_size(rect.width, rect.height); | ||||
|         this.set_position(rect.x, rect.y); | ||||
|         this.set_size(rect.width, rect.height); | ||||
|     } | ||||
|  | ||||
|     destroy() { | ||||
|         this._widget.destroy(); | ||||
|         this._widget = null; | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|  | ||||
| var WindowManager = class { | ||||
|     constructor() { | ||||
| @@ -713,7 +713,7 @@ var WindowManager = class { | ||||
|         this._isWorkspacePrepended = false; | ||||
|  | ||||
|         this._switchData = null; | ||||
|         this._shellwm.connect('kill-switch-workspace', (shellwm) => { | ||||
|         this._shellwm.connect('kill-switch-workspace', shellwm => { | ||||
|             if (this._switchData) { | ||||
|                 if (this._switchData.inProgress) | ||||
|                     this._switchWorkspaceDone(shellwm); | ||||
| @@ -1022,7 +1022,6 @@ var WindowManager = class { | ||||
|                                                 (proxy, error) => { | ||||
|                                                     if (error) { | ||||
|                                                         log(error.message); | ||||
|                                                         return; | ||||
|                                                     } | ||||
|                                                 }); | ||||
|  | ||||
| @@ -1087,7 +1086,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.show(Main.layoutManager.bottomIndex); | ||||
|             Main.keyboard.open(Main.layoutManager.bottomIndex); | ||||
|         }); | ||||
|         Main.layoutManager.connect('keyboard-visible-changed', (manager, visible) => { | ||||
|             bottomDragAction.cancel(); | ||||
| @@ -1115,9 +1114,9 @@ var WindowManager = class { | ||||
|  | ||||
|     _showPadOsd(display, device, settings, imagePath, editionMode, monitorIndex) { | ||||
|         this._currentPadOsd = new PadOsd.PadOsd(device, settings, imagePath, editionMode, monitorIndex); | ||||
|         this._currentPadOsd.connect('closed', () => this._currentPadOsd = null); | ||||
|         this._currentPadOsd.connect('closed', () => (this._currentPadOsd = null)); | ||||
|  | ||||
|         return this._currentPadOsd.actor; | ||||
|         return this._currentPadOsd; | ||||
|     } | ||||
|  | ||||
|     _switchWorkspaceMotion(action, xRel, yRel) { | ||||
| @@ -1210,9 +1209,41 @@ var WindowManager = class { | ||||
|         if (!Meta.prefs_get_dynamic_workspaces()) | ||||
|             return; | ||||
|  | ||||
|         let newWs = workspaceManager.append_new_workspace( | ||||
|             false, global.get_current_time()); | ||||
|         workspaceManager.reorder_workspace(newWs, pos); | ||||
|         workspaceManager.append_new_workspace(false, global.get_current_time()); | ||||
|  | ||||
|         let windows = global.get_window_actors().map(a => a.meta_window); | ||||
|  | ||||
|         // To create a new workspace, we slide all the windows on workspaces | ||||
|         // below us to the next workspace, leaving a blank workspace for us | ||||
|         // to recycle. | ||||
|         windows.forEach(window => { | ||||
|             // If the window is attached to an ancestor, we don't need/want | ||||
|             // to move it | ||||
|             if (window.get_transient_for() != null) | ||||
|                 return; | ||||
|             // Same for OR windows | ||||
|             if (window.is_override_redirect()) | ||||
|                 return; | ||||
|             // Sticky windows don't need moving, in fact moving would | ||||
|             // unstick them | ||||
|             if (window.on_all_workspaces) | ||||
|                 return; | ||||
|             // Windows on workspaces below pos don't need moving | ||||
|             let index = window.get_workspace().index(); | ||||
|             if (index < pos) | ||||
|                 return; | ||||
|             window.change_workspace_by_index(index + 1, true); | ||||
|         }); | ||||
|  | ||||
|         // If the new workspace was inserted before the active workspace, | ||||
|         // activate the workspace to which its windows went | ||||
|         let activeIndex = workspaceManager.get_active_workspace_index(); | ||||
|         if (activeIndex >= pos) { | ||||
|             let newWs = workspaceManager.get_workspace_by_index(activeIndex + 1); | ||||
|             this._blockAnimations = true; | ||||
|             newWs.activate(global.get_current_time()); | ||||
|             this._blockAnimations = false; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     keepWorkspaceAlive(workspace, duration) { | ||||
| @@ -1682,7 +1713,6 @@ var WindowManager = class { | ||||
|             break; | ||||
|         default: | ||||
|             shellwm.completed_map(actor); | ||||
|             return; | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -1763,7 +1793,6 @@ var WindowManager = class { | ||||
|             break; | ||||
|         default: | ||||
|             shellwm.completed_destroy(actor); | ||||
|             return; | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -2013,13 +2042,13 @@ var WindowManager = class { | ||||
|     _showTilePreview(shellwm, window, tileRect, monitorIndex) { | ||||
|         if (!this._tilePreview) | ||||
|             this._tilePreview = new TilePreview(); | ||||
|         this._tilePreview.show(window, tileRect, monitorIndex); | ||||
|         this._tilePreview.open(window, tileRect, monitorIndex); | ||||
|     } | ||||
|  | ||||
|     _hideTilePreview() { | ||||
|         if (!this._tilePreview) | ||||
|             return; | ||||
|         this._tilePreview.hide(); | ||||
|         this._tilePreview.close(); | ||||
|     } | ||||
|  | ||||
|     _showWindowMenu(shellwm, window, menu, rect) { | ||||
|   | ||||
| @@ -178,7 +178,7 @@ var WindowMenu = class extends PopupMenu.PopupMenu { | ||||
|         } | ||||
|  | ||||
|         let waitId = 0; | ||||
|         let id = global.display.connect('grab-op-end', (display) => { | ||||
|         let id = global.display.connect('grab-op-end', display => { | ||||
|             display.disconnect(id); | ||||
|             GLib.source_remove(waitId); | ||||
|  | ||||
|   | ||||
| @@ -84,7 +84,7 @@ class WindowCloneLayout extends Clutter.LayoutManager { | ||||
|             if (child == container._windowClone) | ||||
|                 realWindow = container.realWindow; | ||||
|             else | ||||
|                 realWindow = child.source; | ||||
|                 realWindow = child.content.window_actor; | ||||
|  | ||||
|             child.allocate(this._makeBoxForWindow(realWindow.meta_window), | ||||
|                            flags); | ||||
| @@ -93,6 +93,7 @@ class WindowCloneLayout extends Clutter.LayoutManager { | ||||
| }); | ||||
|  | ||||
| var WindowClone = GObject.registerClass({ | ||||
|     GTypeName: 'Workspace_WindowClone', | ||||
|     Signals: { | ||||
|         'drag-begin': {}, | ||||
|         'drag-cancelled': {}, | ||||
| @@ -102,14 +103,14 @@ var WindowClone = GObject.registerClass({ | ||||
|         'show-chrome': {}, | ||||
|         'size-changed': {} | ||||
|     }, | ||||
| }, class WorkspaceWindowClone extends St.Widget { | ||||
| }, class WindowClone extends St.Widget { | ||||
|     _init(realWindow, workspace) { | ||||
|         this.realWindow = realWindow; | ||||
|         this.metaWindow = realWindow.meta_window; | ||||
|         this.metaWindow._delegate = this; | ||||
|         this._workspace = workspace; | ||||
|  | ||||
|         this._windowClone = new Clutter.Clone({ source: realWindow }); | ||||
|         this._windowClone = new Clutter.Actor({ content: realWindow.content }); | ||||
|         // 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 | ||||
| @@ -162,13 +163,6 @@ 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, | ||||
| @@ -203,7 +197,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].source; | ||||
|             let realWindow = windows[i].content.window_actor; | ||||
|             let metaWindow = realWindow.meta_window; | ||||
|  | ||||
|             metaWindow.delete(global.get_current_time()); | ||||
| @@ -235,7 +229,7 @@ var WindowClone = GObject.registerClass({ | ||||
|     } | ||||
|  | ||||
|     _doAddAttachedDialog(metaWin, realWin) { | ||||
|         let clone = new Clutter.Clone({ source: realWin }); | ||||
|         let clone = new Clutter.Actor({ content: realWin.content }); | ||||
|         clone._sizeChangedId = metaWin.connect('size-changed', | ||||
|             this._onMetaWindowSizeChanged.bind(this)); | ||||
|         clone._posChangedId = metaWin.connect('position-changed', | ||||
| @@ -288,7 +282,7 @@ var WindowClone = GObject.registerClass({ | ||||
|             if (child == this._windowClone) | ||||
|                 realWindow = this.realWindow; | ||||
|             else | ||||
|                 realWindow = child.source; | ||||
|                 realWindow = child.content.window_actor; | ||||
|  | ||||
|             let metaWindow = realWindow.meta_window; | ||||
|             rect = rect.union(metaWindow.get_frame_rect()); | ||||
| @@ -333,7 +327,7 @@ var WindowClone = GObject.registerClass({ | ||||
|             if (child == this._windowClone) | ||||
|                 realWindow = this.realWindow; | ||||
|             else | ||||
|                 realWindow = child.source; | ||||
|                 realWindow = child.content.window_actor; | ||||
|  | ||||
|             realWindow.meta_window.disconnect(child._sizeChangedId); | ||||
|             realWindow.meta_window.disconnect(child._posChangedId); | ||||
| @@ -368,8 +362,28 @@ var WindowClone = GObject.registerClass({ | ||||
|         this.emit('selected', global.get_current_time()); | ||||
|     } | ||||
|  | ||||
|     _onKeyPress(actor, event) { | ||||
|         let symbol = event.get_key_symbol(); | ||||
|     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; | ||||
|         let isEnter = (symbol == Clutter.KEY_Return || symbol == Clutter.KEY_KP_Enter); | ||||
|         if (isEnter) { | ||||
|             this._activate(); | ||||
| @@ -412,8 +426,6 @@ var WindowClone = GObject.registerClass({ | ||||
|  | ||||
|     _onDragBegin(_draggable, _time) { | ||||
|         this._dragSlot = this._slot; | ||||
|         [this.dragOrigX, this.dragOrigY] = this.get_position(); | ||||
|         this.dragOrigScale = this.scale_x; | ||||
|         this.inDrag = true; | ||||
|         this.emit('drag-begin'); | ||||
|     } | ||||
| @@ -423,7 +435,7 @@ var WindowClone = GObject.registerClass({ | ||||
|     } | ||||
|  | ||||
|     acceptDrop(source, actor, x, y, time) { | ||||
|         this._workspace.acceptDrop(source, actor, x, y, time); | ||||
|         return this._workspace.acceptDrop(source, actor, x, y, time); | ||||
|     } | ||||
|  | ||||
|     _onDragCancelled(_draggable, _time) { | ||||
| @@ -468,7 +480,8 @@ var WindowOverlay = class { | ||||
|         this.border = new St.Bin({ style_class: 'window-clone-border' }); | ||||
|  | ||||
|         this.title = new St.Label({ style_class: 'window-caption', | ||||
|                                     text: this._getCaption() }); | ||||
|                                     text: this._getCaption(), | ||||
|                                     reactive: true }); | ||||
|         this.title.clutter_text.ellipsize = Pango.EllipsizeMode.END; | ||||
|         windowClone.label_actor = this.title; | ||||
|  | ||||
| @@ -493,7 +506,6 @@ var WindowOverlay = class { | ||||
|         this.closeButton.hide(); | ||||
|  | ||||
|         // Don't block drop targets | ||||
|         Shell.util_set_hidden_from_pick(this.title, true); | ||||
|         Shell.util_set_hidden_from_pick(this.border, true); | ||||
|  | ||||
|         parentActor.add_actor(this.border); | ||||
| @@ -686,19 +698,22 @@ var WindowOverlay = class { | ||||
|     } | ||||
|  | ||||
|     _onHideChrome() { | ||||
|         if (this._idleHideOverlayId == 0) { | ||||
|             this._idleHideOverlayId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, WINDOW_OVERLAY_IDLE_HIDE_TIMEOUT, this._idleHideOverlay.bind(this)); | ||||
|             GLib.Source.set_name_by_id(this._idleHideOverlayId, '[gnome-shell] this._idleHideOverlay'); | ||||
|         } | ||||
|         if (this._idleHideOverlayId > 0) | ||||
|             GLib.source_remove(this._idleHideOverlayId); | ||||
|  | ||||
|         this._idleHideOverlayId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, WINDOW_OVERLAY_IDLE_HIDE_TIMEOUT, this._idleHideOverlay.bind(this)); | ||||
|         GLib.Source.set_name_by_id(this._idleHideOverlayId, '[gnome-shell] this._idleHideOverlay'); | ||||
|     } | ||||
|  | ||||
|     _idleHideOverlay() { | ||||
|         this._idleHideOverlayId = 0; | ||||
|         if (this.closeButton['has-pointer'] || | ||||
|             this.title['has-pointer']) | ||||
|             return GLib.SOURCE_CONTINUE; | ||||
|  | ||||
|         if (!this._windowClone['has-pointer'] && | ||||
|             !this.closeButton['has-pointer']) | ||||
|         if (!this._windowClone['has-pointer']) | ||||
|             this._animateInvisible(); | ||||
|  | ||||
|         this._idleHideOverlayId = 0; | ||||
|         return GLib.SOURCE_REMOVE; | ||||
|     } | ||||
|  | ||||
| @@ -903,7 +918,7 @@ var LayoutStrategy = class { | ||||
|     computeWindowSlots(layout, area) { | ||||
|         this._computeRowSizes(layout); | ||||
|  | ||||
|         let { rows: rows, scale: scale } = layout; | ||||
|         let { rows, scale } = layout; | ||||
|  | ||||
|         let slots = []; | ||||
|  | ||||
| @@ -978,7 +993,7 @@ var LayoutStrategy = class { | ||||
|  | ||||
| var UnalignedLayoutStrategy = class extends LayoutStrategy { | ||||
|     _computeRowSizes(layout) { | ||||
|         let { rows: rows, scale: scale } = layout; | ||||
|         let { rows, scale } = layout; | ||||
|         for (let i = 0; i < rows.length; i++) { | ||||
|             let row = rows[i]; | ||||
|             row.width = row.fullWidth * scale + (row.windows.length - 1) * this._columnSpacing; | ||||
| @@ -1093,23 +1108,14 @@ 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 = class { | ||||
|     constructor(metaWorkspace, monitorIndex) { | ||||
| var Workspace = GObject.registerClass( | ||||
| class Workspace extends St.Widget { | ||||
|     _init(metaWorkspace, monitorIndex) { | ||||
|         super._init({ style_class: 'window-picker' }); | ||||
|  | ||||
|         // When dragging a window, we use this slot for reserve space. | ||||
|         this._reservedSlot = null; | ||||
|         this._reservedSlotWindow = null; | ||||
| @@ -1135,18 +1141,17 @@ var Workspace = class { | ||||
|         // 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.actor.add_style_class_name('external-monitor'); | ||||
|         this.actor.set_size(0, 0); | ||||
|             this.add_style_class_name('external-monitor'); | ||||
|         this.set_size(0, 0); | ||||
|  | ||||
|         this._dropRect = new Clutter.Actor({ opacity: 0 }); | ||||
|         this._dropRect._delegate = this; | ||||
|  | ||||
|         this.actor.add_actor(this._dropRect); | ||||
|         this.actor.add_actor(this._windowOverlaysGroup); | ||||
|         this.add_actor(this._dropRect); | ||||
|         this.add_actor(this._windowOverlaysGroup); | ||||
|  | ||||
|         this.actor.connect('destroy', this._onDestroy.bind(this)); | ||||
|         this.connect('destroy', this._onDestroy.bind(this)); | ||||
|  | ||||
|         let windows = global.get_window_actors().filter(this._isMyWindow, this); | ||||
|  | ||||
| @@ -1176,10 +1181,19 @@ var Workspace = class { | ||||
|  | ||||
|         this._positionWindowsFlags = 0; | ||||
|         this._positionWindowsId = 0; | ||||
|     } | ||||
|  | ||||
|         this.actor.connect('notify::mapped', () => { | ||||
|             if (this.actor.mapped) | ||||
|                 this._syncActualGeometry(); | ||||
|     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; | ||||
|         }); | ||||
|     } | ||||
|  | ||||
| @@ -1189,7 +1203,7 @@ var Workspace = class { | ||||
|  | ||||
|         this._fullGeometry = geom; | ||||
|  | ||||
|         if (this.actor.mapped) | ||||
|         if (this.mapped) | ||||
|             this._recalculateWindowPositions(WindowPositionFlags.NONE); | ||||
|     } | ||||
|  | ||||
| @@ -1200,7 +1214,7 @@ var Workspace = class { | ||||
|         this._actualGeometry = geom; | ||||
|         this._actualGeometryDirty = true; | ||||
|  | ||||
|         if (this.actor.mapped) | ||||
|         if (this.mapped) | ||||
|             this._syncActualGeometry(); | ||||
|     } | ||||
|  | ||||
| @@ -1212,7 +1226,7 @@ var Workspace = class { | ||||
|  | ||||
|         this._actualGeometryLater = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => { | ||||
|             this._actualGeometryLater = 0; | ||||
|             if (!this.actor.mapped) | ||||
|             if (!this.mapped) | ||||
|                 return false; | ||||
|  | ||||
|             let geom = this._actualGeometry; | ||||
| @@ -1503,8 +1517,7 @@ var Workspace = class { | ||||
|             // Newly-created windows are added to a workspace before | ||||
|             // the compositor finds out about them... | ||||
|             let id = GLib.idle_add(GLib.PRIORITY_DEFAULT, () => { | ||||
|                 if (this.actor && | ||||
|                     metaWin.get_compositor_private() && | ||||
|                 if (metaWin.get_compositor_private() && | ||||
|                     metaWin.get_workspace() == this.metaWorkspace) | ||||
|                     this._doAddWindow(metaWin); | ||||
|                 return GLib.SOURCE_REMOVE; | ||||
| @@ -1540,8 +1553,8 @@ var Workspace = class { | ||||
|         let [clone, overlay_] = this._addWindowClone(win, false); | ||||
|  | ||||
|         if (win._overviewHint) { | ||||
|             let x = win._overviewHint.x - this.actor.x; | ||||
|             let y = win._overviewHint.y - this.actor.y; | ||||
|             let x = win._overviewHint.x - this.x; | ||||
|             let y = win._overviewHint.y - this.y; | ||||
|             let scale = win._overviewHint.scale; | ||||
|             delete win._overviewHint; | ||||
|  | ||||
| @@ -1776,10 +1789,6 @@ var Workspace = class { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     destroy() { | ||||
|         this.actor.destroy(); | ||||
|     } | ||||
|  | ||||
|     _onDestroy() { | ||||
|         if (this._overviewHiddenId) { | ||||
|             Main.overview.disconnect(this._overviewHiddenId); | ||||
| @@ -1860,11 +1869,11 @@ var Workspace = class { | ||||
|             this._removeWindowClone(clone.metaWindow); | ||||
|         }); | ||||
|  | ||||
|         this.actor.add_actor(clone); | ||||
|         this.add_actor(clone); | ||||
|  | ||||
|         overlay.connect('chrome-visible', () => { | ||||
|             let focus = global.stage.key_focus; | ||||
|             if (focus == null || this.actor.contains(focus)) | ||||
|             if (focus == null || this.contains(focus)) | ||||
|                 clone.grab_key_focus(); | ||||
|  | ||||
|             this._windowOverlays.forEach(o => { | ||||
| @@ -1948,7 +1957,7 @@ var Workspace = class { | ||||
|     } | ||||
|  | ||||
|     _getSpacingAndPadding() { | ||||
|         let node = this.actor.get_theme_node(); | ||||
|         let node = this.get_theme_node(); | ||||
|  | ||||
|         // Window grid spacing | ||||
|         let columnSpacing = node.get_length('-horizontal-spacing'); | ||||
| @@ -1993,13 +2002,20 @@ var Workspace = class { | ||||
|     handleDragOver(source, _actor, _x, _y, _time) { | ||||
|         if (source.realWindow && !this._isMyWindow(source.realWindow)) | ||||
|             return DND.DragMotionResult.MOVE_DROP; | ||||
|         if (source.shellWorkspaceLaunch) | ||||
|         if (source.app && source.app.can_open_new_window()) | ||||
|             return DND.DragMotionResult.COPY_DROP; | ||||
|         if (!source.app && source.shellWorkspaceLaunch) | ||||
|             return DND.DragMotionResult.COPY_DROP; | ||||
|  | ||||
|         return DND.DragMotionResult.CONTINUE; | ||||
|     } | ||||
|  | ||||
|     acceptDrop(source, actor, x, y, time) { | ||||
|         let workspaceManager = global.workspace_manager; | ||||
|         let workspaceIndex = this.metaWorkspace | ||||
|             ? this.metaWorkspace.index() | ||||
|             : workspaceManager.get_active_workspace_index(); | ||||
|  | ||||
|         if (source.realWindow) { | ||||
|             let win = source.realWindow; | ||||
|             if (this._isMyWindow(win)) | ||||
| @@ -2021,17 +2037,22 @@ var Workspace = class { | ||||
|             if (metaWindow.get_monitor() != this.monitorIndex) | ||||
|                 metaWindow.move_to_monitor(this.monitorIndex); | ||||
|  | ||||
|             let workspaceManager = global.workspace_manager; | ||||
|             let index = this.metaWorkspace ? this.metaWorkspace.index() : workspaceManager.get_active_workspace_index(); | ||||
|             metaWindow.change_workspace_by_index(index, false); | ||||
|             metaWindow.change_workspace_by_index(workspaceIndex, false); | ||||
|             return true; | ||||
|         } else if (source.shellWorkspaceLaunch) { | ||||
|             source.shellWorkspaceLaunch({ workspace: this.metaWorkspace ? this.metaWorkspace.index() : -1, | ||||
|         } else if (source.app && source.app.can_open_new_window()) { | ||||
|             if (source.animateLaunchAtPos) | ||||
|                 source.animateLaunchAtPos(actor.x, actor.y); | ||||
|  | ||||
|             source.app.open_new_window(workspaceIndex); | ||||
|             return true; | ||||
|         } else if (!source.app && source.shellWorkspaceLaunch) { | ||||
|             // While unused in our own drag sources, shellWorkspaceLaunch allows | ||||
|             // extensions to define custom actions for their drag sources. | ||||
|             source.shellWorkspaceLaunch({ workspace: workspaceIndex, | ||||
|                                           timestamp: time }); | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         return false; | ||||
|     } | ||||
| }; | ||||
| Signals.addSignalMethods(Workspace.prototype); | ||||
| }); | ||||
|   | ||||
| @@ -2,7 +2,6 @@ | ||||
| /* 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; | ||||
| @@ -44,36 +43,41 @@ class PrimaryActorLayout extends Clutter.FixedLayout { | ||||
|     } | ||||
| }); | ||||
|  | ||||
| var WindowClone = class { | ||||
|     constructor(realWindow) { | ||||
|         this.clone = new Clutter.Clone({ source: realWindow }); | ||||
| 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; | ||||
|  | ||||
|         /* 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.add_child(clone); | ||||
|         this.realWindow = realWindow; | ||||
|         this.metaWindow = realWindow.meta_window; | ||||
|  | ||||
|         this.clone._updateId = this.realWindow.connect('notify::position', | ||||
|                                                        this._onPositionChanged.bind(this)); | ||||
|         this.clone._destroyId = this.realWindow.connect('destroy', () => { | ||||
|         clone._updateId = this.realWindow.connect('notify::position', | ||||
|                                                   this._onPositionChanged.bind(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 | ||||
|             this.clone.destroy(); | ||||
|             clone.destroy(); | ||||
|             this.destroy(); | ||||
|         }); | ||||
|         this._onPositionChanged(); | ||||
|  | ||||
|         this.actor.connect('button-release-event', | ||||
|                            this._onButtonRelease.bind(this)); | ||||
|         this.actor.connect('touch-event', | ||||
|                            this._onTouchEvent.bind(this)); | ||||
|         this.connect('destroy', this._onDestroy.bind(this)); | ||||
|  | ||||
|         this.actor.connect('destroy', this._onDestroy.bind(this)); | ||||
|  | ||||
|         this._draggable = DND.makeDraggable(this.actor, | ||||
|         this._draggable = DND.makeDraggable(this, | ||||
|                                             { restoreOnSuccess: true, | ||||
|                                               dragActorMaxSize: Workspace.WINDOW_DND_SIZE, | ||||
|                                               dragActorOpacity: Workspace.DRAGGING_WINDOW_OPACITY }); | ||||
| @@ -124,13 +128,9 @@ var WindowClone = class { | ||||
|  | ||||
|         let actualAbove = this.getActualStackAbove(); | ||||
|         if (actualAbove == null) | ||||
|             this.actor.lower_bottom(); | ||||
|             this.lower_bottom(); | ||||
|         else | ||||
|             this.actor.raise(actualAbove); | ||||
|     } | ||||
|  | ||||
|     destroy() { | ||||
|         this.actor.destroy(); | ||||
|             this.raise(actualAbove); | ||||
|     } | ||||
|  | ||||
|     addAttachedDialog(win) { | ||||
| @@ -138,7 +138,8 @@ var WindowClone = class { | ||||
|     } | ||||
|  | ||||
|     _doAddAttachedDialog(metaDialog, realDialog) { | ||||
|         let clone = new Clutter.Clone({ source: realDialog }); | ||||
|         let clone = new Clutter.Actor({ content: realDialog.content, | ||||
|                                         request_mode: Clutter.RequestMode.CONTENT_SIZE }); | ||||
|         this._updateDialogPosition(realDialog, clone); | ||||
|  | ||||
|         clone._updateId = realDialog.connect('notify::position', dialog => { | ||||
| @@ -147,7 +148,7 @@ var WindowClone = class { | ||||
|         clone._destroyId = realDialog.connect('destroy', () => { | ||||
|             clone.destroy(); | ||||
|         }); | ||||
|         this.actor.add_child(clone); | ||||
|         this.add_child(clone); | ||||
|     } | ||||
|  | ||||
|     _updateDialogPosition(realDialog, cloneDialog) { | ||||
| @@ -159,12 +160,12 @@ var WindowClone = class { | ||||
|     } | ||||
|  | ||||
|     _onPositionChanged() { | ||||
|         this.actor.set_position(this.realWindow.x, this.realWindow.y); | ||||
|         this.set_position(this.realWindow.x, this.realWindow.y); | ||||
|     } | ||||
|  | ||||
|     _disconnectSignals() { | ||||
|         this.actor.get_children().forEach(child => { | ||||
|             let realWindow = child.source; | ||||
|         this.get_children().forEach(child => { | ||||
|             let realWindow = child.content.window_actor; | ||||
|  | ||||
|             realWindow.disconnect(child._updateId); | ||||
|             realWindow.disconnect(child._destroyId); | ||||
| @@ -174,28 +175,30 @@ var WindowClone = class { | ||||
|     _onDestroy() { | ||||
|         this._disconnectSignals(); | ||||
|  | ||||
|         this.actor._delegate = null; | ||||
|         this._delegate = null; | ||||
|  | ||||
|         if (this.inDrag) { | ||||
|             this.emit('drag-end'); | ||||
|             this.inDrag = false; | ||||
|         } | ||||
|  | ||||
|         this.disconnectAll(); | ||||
|     } | ||||
|  | ||||
|     _onButtonRelease(actor, event) { | ||||
|         this.emit('selected', event.get_time()); | ||||
|     vfunc_button_press_event() { | ||||
|         return Clutter.EVENT_STOP; | ||||
|     } | ||||
|  | ||||
|     vfunc_button_release_event(buttonEvent) { | ||||
|         this.emit('selected', buttonEvent.time); | ||||
|  | ||||
|         return Clutter.EVENT_STOP; | ||||
|     } | ||||
|  | ||||
|     _onTouchEvent(actor, event) { | ||||
|         if (event.type() != Clutter.EventType.TOUCH_END || | ||||
|             !global.display.is_pointer_emulating_sequence(event.get_event_sequence())) | ||||
|     vfunc_touch_event(touchEvent) { | ||||
|         if (touchEvent.type != Clutter.EventType.TOUCH_END || | ||||
|             !global.display.is_pointer_emulating_sequence(touchEvent.sequence)) | ||||
|             return Clutter.EVENT_PROPAGATE; | ||||
|  | ||||
|         this.emit('selected', event.get_time()); | ||||
|         this.emit('selected', touchEvent.time); | ||||
|         return Clutter.EVENT_STOP; | ||||
|     } | ||||
|  | ||||
| @@ -214,18 +217,17 @@ var WindowClone = class { | ||||
|         // We may not have a parent if DnD completed successfully, in | ||||
|         // which case our clone will shortly be destroyed and replaced | ||||
|         // with a new one on the target workspace. | ||||
|         if (this.actor.get_parent() != null) { | ||||
|         if (this.get_parent() != null) { | ||||
|             if (this._stackAbove == null) | ||||
|                 this.actor.lower_bottom(); | ||||
|                 this.lower_bottom(); | ||||
|             else | ||||
|                 this.actor.raise(this._stackAbove); | ||||
|                 this.raise(this._stackAbove); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         this.emit('drag-end'); | ||||
|     } | ||||
| }; | ||||
| Signals.addSignalMethods(WindowClone.prototype); | ||||
| }); | ||||
|  | ||||
|  | ||||
| var ThumbnailState = { | ||||
| @@ -340,7 +342,7 @@ var WorkspaceThumbnail = GObject.registerClass({ | ||||
|                 clone.setStackAbove(this._bgManager.backgroundActor); | ||||
|             } else { | ||||
|                 let previousClone = this._windows[i - 1]; | ||||
|                 clone.setStackAbove(previousClone.actor); | ||||
|                 clone.setStackAbove(previousClone); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| @@ -522,15 +524,15 @@ var WorkspaceThumbnail = GObject.registerClass({ | ||||
|         clone.connect('drag-end', () => { | ||||
|             Main.overview.endWindowDrag(clone.metaWindow); | ||||
|         }); | ||||
|         clone.actor.connect('destroy', () => { | ||||
|         clone.connect('destroy', () => { | ||||
|             this._removeWindowClone(clone.metaWindow); | ||||
|         }); | ||||
|         this._contents.add_actor(clone.actor); | ||||
|         this._contents.add_actor(clone); | ||||
|  | ||||
|         if (this._windows.length == 0) | ||||
|             clone.setStackAbove(this._bgManager.backgroundActor); | ||||
|         else | ||||
|             clone.setStackAbove(this._windows[this._windows.length - 1].actor); | ||||
|             clone.setStackAbove(this._windows[this._windows.length - 1]); | ||||
|  | ||||
|         this._windows.push(clone); | ||||
|  | ||||
| @@ -561,7 +563,7 @@ var WorkspaceThumbnail = GObject.registerClass({ | ||||
|     } | ||||
|  | ||||
|     // Draggable target interface used only by ThumbnailsBox | ||||
|     handleDragOverInternal(source, time) { | ||||
|     handleDragOverInternal(source, actor, time) { | ||||
|         if (source == Main.xdndHandler) { | ||||
|             this.metaWorkspace.activate(time); | ||||
|             return DND.DragMotionResult.CONTINUE; | ||||
| @@ -572,13 +574,15 @@ var WorkspaceThumbnail = GObject.registerClass({ | ||||
|  | ||||
|         if (source.realWindow && !this._isMyWindow(source.realWindow)) | ||||
|             return DND.DragMotionResult.MOVE_DROP; | ||||
|         if (source.shellWorkspaceLaunch) | ||||
|         if (source.app && source.app.can_open_new_window()) | ||||
|             return DND.DragMotionResult.COPY_DROP; | ||||
|         if (!source.app && source.shellWorkspaceLaunch) | ||||
|             return DND.DragMotionResult.COPY_DROP; | ||||
|  | ||||
|         return DND.DragMotionResult.CONTINUE; | ||||
|     } | ||||
|  | ||||
|     acceptDropInternal(source, time) { | ||||
|     acceptDropInternal(source, actor, time) { | ||||
|         if (this.state > ThumbnailState.NORMAL) | ||||
|             return false; | ||||
|  | ||||
| @@ -597,8 +601,16 @@ var WorkspaceThumbnail = GObject.registerClass({ | ||||
|  | ||||
|             metaWindow.change_workspace_by_index(this.metaWorkspace.index(), false); | ||||
|             return true; | ||||
|         } else if (source.shellWorkspaceLaunch) { | ||||
|             source.shellWorkspaceLaunch({ workspace: this.metaWorkspace ? this.metaWorkspace.index() : -1, | ||||
|         } else if (source.app && source.app.can_open_new_window()) { | ||||
|             if (source.animateLaunchAtPos) | ||||
|                 source.animateLaunchAtPos(actor.x, actor.y); | ||||
|  | ||||
|             source.app.open_new_window(this.metaWorkspace.index()); | ||||
|             return true; | ||||
|         } else if (!source.app && source.shellWorkspaceLaunch) { | ||||
|             // While unused in our own drag sources, shellWorkspaceLaunch allows | ||||
|             // extensions to define custom actions for their drag sources. | ||||
|             source.shellWorkspaceLaunch({ workspace: this.metaWorkspace.index(), | ||||
|                                           timestamp: time }); | ||||
|             return true; | ||||
|         } | ||||
| @@ -658,10 +670,6 @@ 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', | ||||
| @@ -718,17 +726,17 @@ var ThumbnailsBox = GObject.registerClass({ | ||||
|             thumbnail.activate(time); | ||||
|     } | ||||
|  | ||||
|     _onButtonRelease(actor, event) { | ||||
|         let [stageX, stageY] = event.get_coords(); | ||||
|         this._activateThumbnailAtPoint(stageX, stageY, event.get_time()); | ||||
|     vfunc_button_release_event(buttonEvent) { | ||||
|         let { x, y } = buttonEvent; | ||||
|         this._activateThumbnailAtPoint(x, y, buttonEvent.time); | ||||
|         return Clutter.EVENT_STOP; | ||||
|     } | ||||
|  | ||||
|     _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()); | ||||
|     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); | ||||
|         } | ||||
|  | ||||
|         return Clutter.EVENT_STOP; | ||||
| @@ -779,7 +787,10 @@ var ThumbnailsBox = GObject.registerClass({ | ||||
|  | ||||
|     // Draggable target interface | ||||
|     handleDragOver(source, actor, x, y, time) { | ||||
|         if (!source.realWindow && !source.shellWorkspaceLaunch && source != Main.xdndHandler) | ||||
|         if (!source.realWindow && | ||||
|             (!source.app || !source.app.can_open_new_window()) && | ||||
|             (source.app || !source.shellWorkspaceLaunch) && | ||||
|             source != Main.xdndHandler) | ||||
|             return DND.DragMotionResult.CONTINUE; | ||||
|  | ||||
|         let canCreateWorkspaces = Meta.prefs_get_dynamic_workspaces(); | ||||
| @@ -825,7 +836,7 @@ var ThumbnailsBox = GObject.registerClass({ | ||||
|         } | ||||
|  | ||||
|         if (this._dropWorkspace != -1) | ||||
|             return this._thumbnails[this._dropWorkspace].handleDragOverInternal(source, time); | ||||
|             return this._thumbnails[this._dropWorkspace].handleDragOverInternal(source, actor, time); | ||||
|         else if (this._dropPlaceholderPos != -1) | ||||
|             return source.realWindow ? DND.DragMotionResult.MOVE_DROP : DND.DragMotionResult.COPY_DROP; | ||||
|         else | ||||
| @@ -834,9 +845,11 @@ var ThumbnailsBox = GObject.registerClass({ | ||||
|  | ||||
|     acceptDrop(source, actor, x, y, time) { | ||||
|         if (this._dropWorkspace != -1) { | ||||
|             return this._thumbnails[this._dropWorkspace].acceptDropInternal(source, time); | ||||
|             return this._thumbnails[this._dropWorkspace].acceptDropInternal(source, actor, time); | ||||
|         } else if (this._dropPlaceholderPos != -1) { | ||||
|             if (!source.realWindow && !source.shellWorkspaceLaunch) | ||||
|             if (!source.realWindow && | ||||
|                 (!source.app || !source.app.can_open_new_window()) && | ||||
|                 (source.app || !source.shellWorkspaceLaunch)) | ||||
|                 return false; | ||||
|  | ||||
|             let isWindow = !!source.realWindow; | ||||
| @@ -853,9 +866,19 @@ var ThumbnailsBox = GObject.registerClass({ | ||||
|                 if (source.metaWindow.get_monitor() != thumbMonitor) | ||||
|                     source.metaWindow.move_to_monitor(thumbMonitor); | ||||
|                 source.metaWindow.change_workspace_by_index(newWorkspaceIndex, true); | ||||
|             } else if (source.shellWorkspaceLaunch) { | ||||
|             } else if (source.app && source.app.can_open_new_window()) { | ||||
|                 if (source.animateLaunchAtPos) | ||||
|                     source.animateLaunchAtPos(actor.x, actor.y); | ||||
|  | ||||
|                 source.app.open_new_window(newWorkspaceIndex); | ||||
|             } else if (!source.app && source.shellWorkspaceLaunch) { | ||||
|                 // While unused in our own drag sources, shellWorkspaceLaunch allows | ||||
|                 // extensions to define custom actions for their drag sources. | ||||
|                 source.shellWorkspaceLaunch({ workspace: newWorkspaceIndex, | ||||
|                                               timestamp: time }); | ||||
|             } | ||||
|  | ||||
|             if (source.app || (!source.app && source.shellWorkspaceLaunch)) { | ||||
|                 // This new workspace will be automatically removed if the application fails | ||||
|                 // to open its first window within some time, as tracked by Shell.WindowTracker. | ||||
|                 // Here, we only add a very brief timeout to avoid the _immediate_ removal of the | ||||
|   | ||||
| @@ -1,8 +1,7 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* exported WorkspacesView */ | ||||
| /* exported WorkspacesView, WorkspacesDisplay */ | ||||
|  | ||||
| const { Clutter, Gio, GObject, Meta, Shell, St } = imports.gi; | ||||
| const Signals = imports.signals; | ||||
|  | ||||
| const Main = imports.ui.main; | ||||
| const WindowManager = imports.ui.windowManager; | ||||
| @@ -17,15 +16,16 @@ var AnimationType = { | ||||
|  | ||||
| const MUTTER_SCHEMA = 'org.gnome.mutter'; | ||||
|  | ||||
| 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); | ||||
| 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); | ||||
|  | ||||
|         // The actor itself isn't a drop target, so we don't want to pick on its area | ||||
|         this.actor.set_size(0, 0); | ||||
|         this.set_size(0, 0); | ||||
|  | ||||
|         this._monitorIndex = monitorIndex; | ||||
|  | ||||
| @@ -60,10 +60,6 @@ var WorkspacesViewBase = class { | ||||
|         this._setReservedSlot(null); | ||||
|     } | ||||
|  | ||||
|     destroy() { | ||||
|         this.actor.destroy(); | ||||
|     } | ||||
|  | ||||
|     setFullGeometry(geom) { | ||||
|         this._fullGeometry = geom; | ||||
|         this._syncFullGeometry(); | ||||
| @@ -73,13 +69,14 @@ var WorkspacesViewBase = class { | ||||
|         this._actualGeometry = geom; | ||||
|         this._syncActualGeometry(); | ||||
|     } | ||||
| }; | ||||
| }); | ||||
|  | ||||
| var WorkspacesView = class extends WorkspacesViewBase { | ||||
|     constructor(monitorIndex) { | ||||
| var WorkspacesView = GObject.registerClass( | ||||
| class WorkspacesView extends WorkspacesViewBase { | ||||
|     _init(monitorIndex) { | ||||
|         let workspaceManager = global.workspace_manager; | ||||
|  | ||||
|         super(monitorIndex); | ||||
|         super._init(monitorIndex); | ||||
|  | ||||
|         this._animating = false; // tweening | ||||
|         this._scrolling = false; // swipe-scrolling | ||||
| @@ -112,8 +109,8 @@ var WorkspacesView = class extends WorkspacesViewBase { | ||||
|  | ||||
|         this._overviewShownId = | ||||
|             Main.overview.connect('shown', () => { | ||||
|                 this.actor.set_clip(this._fullGeometry.x, this._fullGeometry.y, | ||||
|                                     this._fullGeometry.width, this._fullGeometry.height); | ||||
|                 this.set_clip(this._fullGeometry.x, this._fullGeometry.y, | ||||
|                               this._fullGeometry.width, this._fullGeometry.height); | ||||
|             }); | ||||
|  | ||||
|         this._switchWorkspaceNotifyId = | ||||
| @@ -153,7 +150,7 @@ var WorkspacesView = class extends WorkspacesViewBase { | ||||
|     } | ||||
|  | ||||
|     animateFromOverview(animationType) { | ||||
|         this.actor.remove_clip(); | ||||
|         this.remove_clip(); | ||||
|  | ||||
|         for (let w = 0; w < this._workspaces.length; w++) { | ||||
|             if (animationType == AnimationType.ZOOM) | ||||
| @@ -187,12 +184,12 @@ var WorkspacesView = class extends WorkspacesViewBase { | ||||
|         for (let w = 0; w < this._workspaces.length; w++) { | ||||
|             let workspace = this._workspaces[w]; | ||||
|  | ||||
|             workspace.actor.remove_all_transitions(); | ||||
|             workspace.remove_all_transitions(); | ||||
|  | ||||
|             let params = {}; | ||||
|             if (workspaceManager.layout_rows == -1) | ||||
|                 params.y = (w - active) * this._fullGeometry.height; | ||||
|             else if (this.actor.text_direction == Clutter.TextDirection.RTL) | ||||
|             else if (this.text_direction == Clutter.TextDirection.RTL) | ||||
|                 params.x = (active - w) * this._fullGeometry.width; | ||||
|             else | ||||
|                 params.x = (w - active) * this._fullGeometry.width; | ||||
| @@ -212,9 +209,9 @@ var WorkspacesView = class extends WorkspacesViewBase { | ||||
|                         this._updateVisibility(); | ||||
|                     }; | ||||
|                 } | ||||
|                 workspace.actor.ease(easeParams); | ||||
|                 workspace.ease(easeParams); | ||||
|             } else { | ||||
|                 workspace.actor.set(params); | ||||
|                 workspace.set(params); | ||||
|                 if (w == 0) | ||||
|                     this._updateVisibility(); | ||||
|             } | ||||
| @@ -228,12 +225,12 @@ var WorkspacesView = class extends WorkspacesViewBase { | ||||
|         for (let w = 0; w < this._workspaces.length; w++) { | ||||
|             let workspace = this._workspaces[w]; | ||||
|             if (this._animating || this._scrolling || this._gestureActive) { | ||||
|                 workspace.actor.show(); | ||||
|                 workspace.show(); | ||||
|             } else { | ||||
|                 if (this._inDrag) | ||||
|                     workspace.actor.visible = (Math.abs(w - active) <= 1); | ||||
|                     workspace.visible = (Math.abs(w - active) <= 1); | ||||
|                 else | ||||
|                     workspace.actor.visible = (w == active); | ||||
|                     workspace.visible = (w == active); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| @@ -247,7 +244,7 @@ var WorkspacesView = class extends WorkspacesViewBase { | ||||
|         this.scrollAdjustment.ease(index, { | ||||
|             mode: Clutter.AnimationMode.EASE_OUT_QUAD, | ||||
|             duration: WORKSPACE_SWITCH_TIME, | ||||
|             onComplete: () => this._animatingScroll = false | ||||
|             onComplete: () => (this._animatingScroll = false) | ||||
|         }); | ||||
|     } | ||||
|  | ||||
| @@ -263,7 +260,7 @@ var WorkspacesView = class extends WorkspacesViewBase { | ||||
|  | ||||
|             if (j >= this._workspaces.length) { /* added */ | ||||
|                 workspace = new Workspace.Workspace(metaWorkspace, this._monitorIndex); | ||||
|                 this.actor.add_actor(workspace.actor); | ||||
|                 this.add_actor(workspace); | ||||
|                 this._workspaces[j] = workspace; | ||||
|             } else  { | ||||
|                 workspace = this._workspaces[j]; | ||||
| @@ -355,8 +352,8 @@ var WorkspacesView = class extends WorkspacesViewBase { | ||||
|         let last = this._workspaces.length - 1; | ||||
|  | ||||
|         if (workspaceManager.layout_rows == -1) { | ||||
|             let firstWorkspaceY = this._workspaces[0].actor.y; | ||||
|             let lastWorkspaceY = this._workspaces[last].actor.y; | ||||
|             let firstWorkspaceY = this._workspaces[0].y; | ||||
|             let lastWorkspaceY = this._workspaces[last].y; | ||||
|             let workspacesHeight = lastWorkspaceY - firstWorkspaceY; | ||||
|  | ||||
|             let currentY = firstWorkspaceY; | ||||
| @@ -365,12 +362,12 @@ var WorkspacesView = class extends WorkspacesViewBase { | ||||
|             let dy = newY - currentY; | ||||
|  | ||||
|             for (let i = 0; i < this._workspaces.length; i++) { | ||||
|                 this._workspaces[i].actor.visible = Math.abs(i - adj.value) <= 1; | ||||
|                 this._workspaces[i].actor.y += dy; | ||||
|                 this._workspaces[i].visible = Math.abs(i - adj.value) <= 1; | ||||
|                 this._workspaces[i].y += dy; | ||||
|             } | ||||
|         } else { | ||||
|             let firstWorkspaceX = this._workspaces[0].actor.x; | ||||
|             let lastWorkspaceX = this._workspaces[last].actor.x; | ||||
|             let firstWorkspaceX = this._workspaces[0].x; | ||||
|             let lastWorkspaceX = this._workspaces[last].x; | ||||
|             let workspacesWidth = lastWorkspaceX - firstWorkspaceX; | ||||
|  | ||||
|             let currentX = firstWorkspaceX; | ||||
| @@ -379,19 +376,19 @@ var WorkspacesView = class extends WorkspacesViewBase { | ||||
|             let dx = newX - currentX; | ||||
|  | ||||
|             for (let i = 0; i < this._workspaces.length; i++) { | ||||
|                 this._workspaces[i].actor.visible = Math.abs(i - adj.value) <= 1; | ||||
|                 this._workspaces[i].actor.x += dx; | ||||
|                 this._workspaces[i].visible = Math.abs(i - adj.value) <= 1; | ||||
|                 this._workspaces[i].x += dx; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| }; | ||||
| Signals.addSignalMethods(WorkspacesView.prototype); | ||||
| }); | ||||
|  | ||||
| var ExtraWorkspaceView = class extends WorkspacesViewBase { | ||||
|     constructor(monitorIndex) { | ||||
|         super(monitorIndex); | ||||
| var ExtraWorkspaceView = GObject.registerClass( | ||||
| class ExtraWorkspaceView extends WorkspacesViewBase { | ||||
|     _init(monitorIndex) { | ||||
|         super._init(monitorIndex); | ||||
|         this._workspace = new Workspace.Workspace(null, monitorIndex); | ||||
|         this.actor.add_actor(this._workspace.actor); | ||||
|         this.add_actor(this._workspace); | ||||
|     } | ||||
|  | ||||
|     _setReservedSlot(window) { | ||||
| @@ -439,21 +436,13 @@ var ExtraWorkspaceView = class 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 = 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)); | ||||
| var WorkspacesDisplay = GObject.registerClass( | ||||
| class WorkspacesDisplay extends St.Widget { | ||||
|     _init() { | ||||
|         super._init({ clip_to_allocation: true }); | ||||
|         this.connect('notify::allocation', this._updateWorkspacesActualGeometry.bind(this)); | ||||
|  | ||||
|         let clickAction = new Clutter.ClickAction(); | ||||
|         clickAction.connect('clicked', action => { | ||||
| @@ -467,7 +456,7 @@ var WorkspacesDisplay = class { | ||||
|                 Main.overview.hide(); | ||||
|         }); | ||||
|         Main.overview.addAction(clickAction); | ||||
|         this.actor.bind_property('mapped', clickAction, 'enabled', GObject.BindingFlags.SYNC_CREATE); | ||||
|         this.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)); | ||||
| @@ -490,7 +479,7 @@ var WorkspacesDisplay = class { | ||||
|             this._endSwipeScroll(); | ||||
|         }); | ||||
|         Main.overview.addAction(panAction); | ||||
|         this.actor.bind_property('mapped', panAction, 'enabled', GObject.BindingFlags.SYNC_CREATE); | ||||
|         this.bind_property('mapped', panAction, 'enabled', GObject.BindingFlags.SYNC_CREATE); | ||||
|  | ||||
|         let allowedModes = Shell.ActionMode.OVERVIEW; | ||||
|         let switchGesture = new WindowManager.WorkspaceSwitchAction(allowedModes); | ||||
| @@ -498,20 +487,15 @@ var WorkspacesDisplay = class { | ||||
|         switchGesture.connect('activated', this._onSwitchWorkspaceActivated.bind(this)); | ||||
|         switchGesture.connect('cancel', this._endTouchGesture.bind(this)); | ||||
|         Main.overview.addAction(switchGesture); | ||||
|         this.actor.bind_property('mapped', switchGesture, 'enabled', GObject.BindingFlags.SYNC_CREATE); | ||||
|         this.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', | ||||
| @@ -525,12 +509,12 @@ var WorkspacesDisplay = class { | ||||
|  | ||||
|         this._fullGeometry = null; | ||||
|  | ||||
|         this.actor.connect('destroy', this._onDestroy.bind(this)); | ||||
|         this.connect('destroy', this._onDestroy.bind(this)); | ||||
|     } | ||||
|  | ||||
|     _onDestroy() { | ||||
|         if (this._notifyOpacityId) { | ||||
|             let parent = this.actor.get_parent(); | ||||
|             let parent = this.get_parent(); | ||||
|             if (parent) | ||||
|                 parent.disconnect(this._notifyOpacityId); | ||||
|             this._notifyOpacityId = 0; | ||||
| @@ -546,11 +530,11 @@ var WorkspacesDisplay = class { | ||||
|         let [dist_, dx, dy] = action.get_motion_delta(0); | ||||
|         let adjustment = this._scrollAdjustment; | ||||
|         if (global.workspace_manager.layout_rows == -1) | ||||
|             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; | ||||
|             adjustment.value -= (dy / this.height) * adjustment.page_size; | ||||
|         else if (this.text_direction == Clutter.TextDirection.RTL) | ||||
|             adjustment.value += (dx / this.width) * adjustment.page_size; | ||||
|         else | ||||
|             adjustment.value -= (dx / this.actor.width) * adjustment.page_size; | ||||
|             adjustment.value -= (dx / this.width) * adjustment.page_size; | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
| @@ -583,11 +567,11 @@ var WorkspacesDisplay = class { | ||||
|         let active = workspaceManager.get_active_workspace_index(); | ||||
|         let adjustment = this._scrollAdjustment; | ||||
|         if (workspaceManager.layout_rows == -1) | ||||
|             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; | ||||
|             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; | ||||
|         else | ||||
|             adjustment.value = (active - xRel / this.actor.width) * adjustment.page_size; | ||||
|             adjustment.value = (active - xRel / this.width) * adjustment.page_size; | ||||
|     } | ||||
|  | ||||
|     _onSwitchWorkspaceActivated(action, direction) { | ||||
| @@ -600,8 +584,8 @@ var WorkspacesDisplay = class { | ||||
|         this._endTouchGesture(); | ||||
|     } | ||||
|  | ||||
|     navigateFocus(from, direction) { | ||||
|         return this._getPrimaryView().actor.navigate_focus(from, direction, false); | ||||
|     vfunc_navigate_focus(from, direction) { | ||||
|         return this._getPrimaryView().navigate_focus(from, direction, false); | ||||
|     } | ||||
|  | ||||
|     show(fadeOnPrimary) { | ||||
| @@ -677,7 +661,7 @@ var WorkspacesDisplay = class { | ||||
|             else | ||||
|                 view = new WorkspacesView(i); | ||||
|  | ||||
|             view.actor.connect('scroll-event', this._onScrollEvent.bind(this)); | ||||
|             view.connect('scroll-event', this._onScrollEvent.bind(this)); | ||||
|             if (i == this._primaryIndex) { | ||||
|                 this._scrollAdjustment = view.scrollAdjustment; | ||||
|                 this._scrollAdjustment.connect('notify::value', | ||||
| @@ -685,13 +669,13 @@ var WorkspacesDisplay = class { | ||||
|             } | ||||
|  | ||||
|             // HACK: Avoid spurious allocation changes while updating views | ||||
|             view.actor.hide(); | ||||
|             view.hide(); | ||||
|  | ||||
|             this._workspacesViews.push(view); | ||||
|             Main.layoutManager.overviewGroup.add_actor(view.actor); | ||||
|             Main.layoutManager.overviewGroup.add_actor(view); | ||||
|         } | ||||
|  | ||||
|         this._workspacesViews.forEach(v => v.actor.show()); | ||||
|         this._workspacesViews.forEach(v => v.show()); | ||||
|  | ||||
|         this._updateWorkspacesFullGeometry(); | ||||
|         this._updateWorkspacesActualGeometry(); | ||||
| @@ -728,7 +712,7 @@ var WorkspacesDisplay = class { | ||||
|         return this._getPrimaryView().getActiveWorkspace().hasMaximizedWindows(); | ||||
|     } | ||||
|  | ||||
|     _parentSet(actor, oldParent) { | ||||
|     vfunc_parent_set(oldParent) { | ||||
|         if (oldParent && this._notifyOpacityId) | ||||
|             oldParent.disconnect(this._notifyOpacityId); | ||||
|         this._notifyOpacityId = 0; | ||||
| @@ -738,20 +722,20 @@ var WorkspacesDisplay = class { | ||||
|  | ||||
|         this._parentSetLater = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => { | ||||
|             this._parentSetLater = 0; | ||||
|             let newParent = this.actor.get_parent(); | ||||
|             let newParent = this.get_parent(); | ||||
|             if (!newParent) | ||||
|                 return; | ||||
|  | ||||
|             // This is kinda hackish - we want the primary view to | ||||
|             // appear as parent of this.actor, though in reality it | ||||
|             // appear as parent of this, though in reality it | ||||
|             // is added directly to Main.layoutManager.overviewGroup | ||||
|             this._notifyOpacityId = newParent.connect('notify::opacity', () => { | ||||
|                 let opacity = this.actor.get_parent().opacity; | ||||
|                 let opacity = this.get_parent().opacity; | ||||
|                 let primaryView = this._getPrimaryView(); | ||||
|                 if (!primaryView) | ||||
|                     return; | ||||
|                 primaryView.actor.opacity = opacity; | ||||
|                 primaryView.actor.visible = opacity != 0; | ||||
|                 primaryView.opacity = opacity; | ||||
|                 primaryView.visible = opacity != 0; | ||||
|             }); | ||||
|         }); | ||||
|     } | ||||
| @@ -779,8 +763,8 @@ var WorkspacesDisplay = class { | ||||
|         if (!this._workspacesViews.length) | ||||
|             return; | ||||
|  | ||||
|         let [x, y] = this.actor.get_transformed_position(); | ||||
|         let allocation = this.actor.allocation; | ||||
|         let [x, y] = this.get_transformed_position(); | ||||
|         let allocation = this.allocation; | ||||
|         let width = allocation.x2 - allocation.x1; | ||||
|         let height = allocation.y2 - allocation.y1; | ||||
|         let primaryGeometry = { x: x, y: y, width: width, height: height }; | ||||
| @@ -798,7 +782,7 @@ var WorkspacesDisplay = class { | ||||
|     } | ||||
|  | ||||
|     _onScrollEvent(actor, event) { | ||||
|         if (!this.actor.mapped) | ||||
|         if (!this.mapped) | ||||
|             return Clutter.EVENT_PROPAGATE; | ||||
|  | ||||
|         if (this._workspacesOnlyOnPrimary && | ||||
| @@ -829,7 +813,7 @@ var WorkspacesDisplay = class { | ||||
|     } | ||||
|  | ||||
|     _onKeyPressEvent(actor, event) { | ||||
|         if (!this.actor.mapped) | ||||
|         if (!this.mapped) | ||||
|             return Clutter.EVENT_PROPAGATE; | ||||
|         let workspaceManager = global.workspace_manager; | ||||
|         let activeWs = workspaceManager.get_active_workspace(); | ||||
| @@ -847,5 +831,4 @@ var WorkspacesDisplay = class { | ||||
|         Main.wm.actionMoveWorkspace(ws); | ||||
|         return Clutter.EVENT_STOP; | ||||
|     } | ||||
| }; | ||||
| Signals.addSignalMethods(WorkspacesDisplay.prototype); | ||||
| }); | ||||
|   | ||||
| @@ -5,8 +5,6 @@ | ||||
|             4, | ||||
|             { | ||||
|                 "ignoredNodes": [ | ||||
|                     "ConditionalExpression", | ||||
|                     "CallExpression > ArrowFunctionExpression", | ||||
|                     "CallExpression[callee.object.name=GObject][callee.property.name=registerClass] > ClassExpression:first-child" | ||||
|                 ], | ||||
|                 "CallExpression": { "arguments": "first" }, | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| project('gnome-shell', 'c', | ||||
|   version: '3.34.0', | ||||
|   version: '3.35.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.34.0' | ||||
| mutter_req = '>= 3.35.1' | ||||
| polkit_req = '>= 0.100' | ||||
| schemas_req = '>= 3.33.1' | ||||
| startup_req = '>= 0.11' | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user