Compare commits
209 Commits
3.11.2
...
wip/overvi
Author | SHA1 | Date | |
---|---|---|---|
1afb04d1e4 | |||
51e63233ce | |||
a7d7f94892 | |||
427f516d45 | |||
cbb88ffdbb | |||
71670bad3b | |||
a2e4153fa0 | |||
2fba8e29e0 | |||
de1bb4e203 | |||
b4680a5c25 | |||
d44f40d105 | |||
8d5771e302 | |||
fb31f99aed | |||
b97f3a9ecf | |||
ac22172a6e | |||
57367380f5 | |||
7101cc3170 | |||
7051411be7 | |||
bb8397b9b1 | |||
bb8fa61cb4 | |||
10147ee331 | |||
3779ac2c8a | |||
bdad4db9ec | |||
36c69124f7 | |||
7c8c811134 | |||
ccfc9f3ab0 | |||
d163b92e0b | |||
887a21afb9 | |||
634adc9f71 | |||
974f01cef7 | |||
ef9ade3548 | |||
24fdb73b44 | |||
ba06a87ba8 | |||
e6be483755 | |||
a36bfced47 | |||
4faf421d5a | |||
a739455414 | |||
73f6e75d8d | |||
17e7f8057a | |||
b62c157680 | |||
816f5162f9 | |||
9d8f8277aa | |||
cca14053a4 | |||
427790f005 | |||
17845bf71e | |||
452f5ab3ba | |||
335744e78a | |||
c9e24439b2 | |||
61c697b6db | |||
3227d4f3ed | |||
7e27afb645 | |||
9ba4790b4d | |||
3a26f7f4d5 | |||
8b99617513 | |||
587655f063 | |||
7e9ecf4eb2 | |||
5413010c60 | |||
7d13cf1587 | |||
24cd13935a | |||
1ae7dbec67 | |||
2b0a2ab3bc | |||
4ed0f3e5f0 | |||
9cacc703dd | |||
9ae70c6519 | |||
02b38fed49 | |||
b2a65f809f | |||
2931869522 | |||
11d8640ba6 | |||
65ff947b5e | |||
2dd7db4808 | |||
1d7354696e | |||
cbceac4c8a | |||
297877fbe2 | |||
0d92451c49 | |||
c8a58dcb69 | |||
a4dea25d76 | |||
bfb0235fc6 | |||
6dcc3d637f | |||
9bb4d17e31 | |||
9df09db5fe | |||
d8e28ec274 | |||
d3905734c1 | |||
8fe7f923ec | |||
933f38390b | |||
a4e019442f | |||
d1c4e60636 | |||
765d0228c0 | |||
2d2020a20d | |||
03ab282f67 | |||
7f94cb1cad | |||
a2a303bd72 | |||
d34bf9a14d | |||
68faba6bde | |||
5c5b9cfd96 | |||
9d683f4767 | |||
f2912bad95 | |||
c8adfe0131 | |||
8b7e637e74 | |||
43cffd7c4a | |||
f3dad3765e | |||
70c25141fc | |||
b1b81a2672 | |||
46197bf262 | |||
58ec409e7f | |||
c2d68599de | |||
65f00f3af2 | |||
6544326ffd | |||
a23c206ccb | |||
1b152e6bd0 | |||
d9624d9882 | |||
178b8471cc | |||
719d2092a7 | |||
2f3a4675da | |||
9513be664b | |||
64d8b7853a | |||
4174e57c13 | |||
88b395599a | |||
b6d682c92c | |||
3b02894341 | |||
f3feb13dfe | |||
114d8d0aba | |||
503a843bb3 | |||
c4d91aff40 | |||
2ffe5faf6e | |||
5d2a03aa82 | |||
f4c83d1221 | |||
100e91714b | |||
dafb7b5259 | |||
92906e217c | |||
5c7b721879 | |||
c27dcb0414 | |||
7fcae1e974 | |||
cc4659f5c6 | |||
9fce12d6b4 | |||
deb2f30b37 | |||
751a3f0e94 | |||
fee2a07e08 | |||
17726abb0a | |||
01f740ce69 | |||
b168ccb605 | |||
04a31a52ae | |||
6a236fb91e | |||
619fa1bff8 | |||
53b37e8d0c | |||
f8eb8adfbe | |||
3c2aecb81f | |||
efca9e11d6 | |||
49189e0e43 | |||
ea86c9bafb | |||
c361b6a85c | |||
c7ff45045c | |||
090af35ea1 | |||
8e668ca633 | |||
4d9a16f33b | |||
c9f2a0f694 | |||
46bac3069e | |||
d21aa0d85f | |||
3e87d699eb | |||
23aa216908 | |||
e34e681157 | |||
acd543fe4b | |||
c2df5939d6 | |||
b52e74b615 | |||
ec2bb039ae | |||
aeb9f5775f | |||
47a20756b9 | |||
a7aba1d585 | |||
c89af0cea4 | |||
9d3a109946 | |||
079f1e6fff | |||
7249b11899 | |||
4cfb000812 | |||
5262a41619 | |||
887590730d | |||
adb49bdf0b | |||
7f3aadc157 | |||
eb1c85f3f5 | |||
dbdc884c96 | |||
5166354e34 | |||
04ea95049a | |||
ec62e49001 | |||
6fb21850d8 | |||
98b50fd942 | |||
729c962b7c | |||
ebc15e60a8 | |||
85f2d94253 | |||
981a536cb5 | |||
abf7c333b1 | |||
b2f547e934 | |||
0870a25e2f | |||
1091e577a5 | |||
151ad16fe6 | |||
e325258091 | |||
1139a02b40 | |||
4b90953226 | |||
d77fc01580 | |||
216d84faeb | |||
0c9d95f183 | |||
913739d732 | |||
7ecb5af587 | |||
87f0e79749 | |||
c85145d73c | |||
eea689841b | |||
e50a59361d | |||
9862185bda | |||
fe05d35bbb | |||
ba602c17d4 | |||
831bd07b0d | |||
175c5d9fc3 |
COPYINGNEWS
browser-plugin
configure.acdata
docs/reference/shell
js
gdm
js-resources.gresource.xmlmisc
ui
altTab.jsanimation.jsappDisplay.jsbackground.jsbackgroundMenu.jsboxpointer.jscalendar.js
components
dash.jsdateMenu.jsdnd.jsendSessionDialog.jsextensionDownloader.jsgrabHelper.jsibusCandidatePopup.jsiconGrid.jskeyboard.jslayout.jslightbox.jslookingGlass.jsmagnifier.jsmain.jsmessageTray.jsmodalDialog.jsnotificationDaemon.jsosdWindow.jsoverview.jsoverviewControls.jspanel.jspanelMenu.jspointerWatcher.jspopupMenu.jsremoteSearch.jsrunDialog.jsscreenShield.jsscreencast.jsscreenshot.jsscripting.jssessionMode.jsshellDBus.jsshellEntry.jsslider.jsstatus
switcherPopup.jsunlockDialog.jsuserWidget.jsviewSelector.jswindowAttentionHandler.jswindowManager.jsworkspace.jsworkspaceSwitcherPopup.jsworkspaceThumbnail.jsworkspacesView.jsxdndHandler.jspo
an.poar.poas.pocs.pode.poel.poes.poet.pofi.pogl.pohe.poid.poit.pokk.polt.ponb.ponl.popt_BR.poru.posk.posl.potg.potr.pozh_CN.po
src
Makefile.am
calendar-server
data-to-c.plgnome-shell-extension-prefs.cgnome-shell-extension-prefs.ingnome-shell-plugin.cgtkactionmuxer.cgtkactionmuxer.hgtkactionobserver.cgtkactionobserver.hgtkmenutracker.cgtkmenutracker.hgtkmenutrackeritem.cgtkmenutrackeritem.hhotplug-sniffer
main.crun-js-test.cshell-app-private.hshell-app-system.cshell-app-system.hshell-app-usage.cshell-app-usage.hshell-app.cshell-app.hshell-global.cshell-global.hshell-glsl-quad.cshell-glsl-quad.hshell-menu-tracker.cshell-menu-tracker.hshell-mount-operation.cshell-mount-operation.hshell-network-agent.cshell-secure-text-buffer.cshell-secure-text-buffer.hshell-tray-icon.cshell-util.cshell-util.hshell-window-tracker.cshell-window-tracker.hst
tray
tools/build
41
COPYING
41
COPYING
@ -1,12 +1,12 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
@ -15,7 +15,7 @@ software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
@ -55,8 +55,8 @@ patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
@ -110,7 +110,7 @@ above, provided that you also meet all of these conditions:
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
@ -168,7 +168,7 @@ access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
@ -225,7 +225,7 @@ impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
@ -255,7 +255,7 @@ make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
@ -277,9 +277,9 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
@ -303,17 +303,16 @@ the "copyright" line and a pointer to where the full notice is found.
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
@ -336,5 +335,5 @@ necessary. Here is a sample; alter the names:
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
|
58
NEWS
58
NEWS
@ -1,3 +1,61 @@
|
||||
3.11.4
|
||||
======
|
||||
* Fix removal of workspacaes that are not at the end [Giovanni; #721417]
|
||||
* Allow session mode to be specified in the environment [Ray; #720894]
|
||||
* Special-case launching of terminals [Debarshi; #695010]
|
||||
* Always show arrow if app switcher is scrollable [Jonh; #711467]
|
||||
* Implement new app folders system [Jasper; #722117]
|
||||
* Remove arrow from background menu [Tarun; #699608]
|
||||
* Misc bug fixes and cleanups [Giovanni, Andika, Florian, Ray; #721039,
|
||||
#721439, #721507, #721629, #721868, #722210]
|
||||
|
||||
Contributors:
|
||||
Giovanni Campagna, Piotr Drąg, Tarun Kumar Joshi, Florian Müllner,
|
||||
Debarshi Ray, Jasper St. Pierre, Ray Strode, Andika Triwidada, Jonh Wendell
|
||||
|
||||
Translations:
|
||||
Dušan Kazik [sk], Tong Hui [zh_CN], Benjamin Steinwender [de],
|
||||
Matej Urbančič [sl], Jorge Pérez Pérez [an], Kjartan Maraas [nb],
|
||||
Milo Casagrande [it], Rafael Ferreira [pt_BR], Marek Černocký [cs],
|
||||
Daniel Mustieles [es], Adorilson Bezerra [pt_BR], Christian Kirbach [de],
|
||||
Aurimas Černius [lt], Andika Triwidada [id], Baurzhan Muftakhidinov [kk],
|
||||
Victor Ibragimov [tg], Yosef Or Boczko [he], Dimitris Spingos [el],
|
||||
Fran Diéguez [gl]
|
||||
|
||||
3.11.3
|
||||
======
|
||||
* Fix fade effect of desktop icons [Florian; #707671]
|
||||
* Fix issues with background management code [Jasper; #709313]
|
||||
* Use new Glib facilities for application search [Jasper; #711631]
|
||||
* Add focus indication to session menu button [Sebastien; #710539]
|
||||
* Fix hover tracking for StEntries [Jasper; #706749]
|
||||
* Fix reentrancy issue in message tray [Jasper; #711694]
|
||||
* Tone down zoom animation on login/unlock [Jasper; #712362]
|
||||
* Allow specifying monitor for OSD [Carlos; #712664]
|
||||
* Fix resetting prompt on user switch [Ray; #710456]
|
||||
* Stop using gnome-bluetooth-applet [Bastien; #719341]
|
||||
* Add support for EAP-FAST password requests [Dan; #719813]
|
||||
* Fix entry focus of chat notifications [Jasper; #709853]
|
||||
* Make window previews keyboard navigatable [Jasper; #644306]
|
||||
* Fix app switcher order with dialog windows [Florian; #719824]
|
||||
* Allow remote search providers without icons [Debarshi; #719965]
|
||||
* Fix various alignment issues in RTL locales [Yosef; #712638, #712596,
|
||||
#712594, #712600, #712579]
|
||||
* Misc. bug fixes and cleanups [Jasper, Florian, Giovanni, Dan; #712727,
|
||||
#712753, #719378, #719730, #719803, #710115, #720017, #719815, #719567,
|
||||
#720298]
|
||||
|
||||
Contributors:
|
||||
Giovanni Campagna, Carlos Garnacho, Sebastien Lafargue, Tim Lunn,
|
||||
Florian Müllner, Bastien Nocera, Yosef Or Boczko, Debarshi Ray,
|
||||
Jasper St. Pierre, Ray Strode, Dan Williams
|
||||
|
||||
Translations:
|
||||
Kjartan Maraas [nb], Reinout van Schouwen [nl], Rafael Ferreira [pt_BR],
|
||||
Mattias Põldaru [et], Emin Tufan Çetin [tr], Jiri Grönroos [fi],
|
||||
Khaled Hosny [ar], Fran Diéguez [gl], Victor Ibragimov [tg],
|
||||
Daniel Mustieles [es]
|
||||
|
||||
3.11.2
|
||||
======
|
||||
* Cache search result display actors [Jasper; #704912]
|
||||
|
@ -13,9 +13,7 @@
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors:
|
||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||
|
22
configure.ac
22
configure.ac
@ -1,5 +1,5 @@
|
||||
AC_PREREQ(2.63)
|
||||
AC_INIT([gnome-shell],[3.11.2],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
|
||||
AC_INIT([gnome-shell],[3.11.4],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
|
||||
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_CONFIG_SRCDIR([src/shell-global.c])
|
||||
@ -73,9 +73,9 @@ AS_IF([test x$enable_systemd != xno], [
|
||||
|
||||
AC_MSG_RESULT($enable_systemd)
|
||||
|
||||
CLUTTER_MIN_VERSION=1.13.4
|
||||
CLUTTER_MIN_VERSION=1.15.90
|
||||
GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1
|
||||
GJS_MIN_VERSION=1.38.1
|
||||
GJS_MIN_VERSION=1.39.0
|
||||
MUTTER_MIN_VERSION=3.11.1
|
||||
GTK_MIN_VERSION=3.7.9
|
||||
GIO_MIN_VERSION=2.37.0
|
||||
@ -140,19 +140,11 @@ AS_IF([test x$enable_browser_plugin = xyes], [
|
||||
])
|
||||
AM_CONDITIONAL(BUILD_BROWSER_PLUGIN, test x$enable_browser_plugin = xyes)
|
||||
|
||||
AC_MSG_CHECKING([for bluetooth support])
|
||||
PKG_CHECK_EXISTS([gnome-bluetooth-1.0 >= 3.9.0],
|
||||
[BLUETOOTH_DIR=`$PKG_CONFIG --variable=applet_libdir gnome-bluetooth-1.0`
|
||||
BLUETOOTH_LIBS=`$PKG_CONFIG --variable=applet_libs gnome-bluetooth-1.0`
|
||||
AC_SUBST([BLUETOOTH_LIBS],["$BLUETOOTH_LIBS"])
|
||||
AC_SUBST([BLUETOOTH_DIR],["$BLUETOOTH_DIR"])
|
||||
AC_DEFINE_UNQUOTED([BLUETOOTH_DIR],["$BLUETOOTH_DIR"],[Path to installed GnomeBluetooth typelib and library])
|
||||
AC_DEFINE([HAVE_BLUETOOTH],[1],[Define if you have libgnome-bluetooth-applet])
|
||||
AC_SUBST([HAVE_BLUETOOTH],[1])
|
||||
AC_MSG_RESULT([yes])],
|
||||
PKG_CHECK_MODULES(BLUETOOTH, gnome-bluetooth-1.0 >= 3.9.0,
|
||||
[AC_DEFINE([HAVE_BLUETOOTH],[1],[Define if you have libgnome-bluetooth-applet])
|
||||
AC_SUBST([HAVE_BLUETOOTH],[1])],
|
||||
[AC_DEFINE([HAVE_BLUETOOTH],[0])
|
||||
AC_SUBST([HAVE_BLUETOOTH],[0])
|
||||
AC_MSG_RESULT([no])])
|
||||
AC_SUBST([HAVE_BLUETOOTH],[0])])
|
||||
|
||||
PKG_CHECK_MODULES(CALENDAR_SERVER, libecal-1.2 >= $LIBECAL_MIN_VERSION libedataserver-1.2 >= $LIBEDATASERVER_MIN_VERSION gio-2.0)
|
||||
AC_SUBST(CALENDAR_SERVER_CFLAGS)
|
||||
|
@ -13,12 +13,12 @@
|
||||
</key>
|
||||
<key name="enabled-extensions" type="as">
|
||||
<default>[]</default>
|
||||
<_summary>Uuids of extensions to enable</_summary>
|
||||
<_summary>UUIDs of extensions to enable</_summary>
|
||||
<_description>
|
||||
GNOME Shell extensions have a uuid property; this key lists extensions
|
||||
GNOME Shell extensions have a UUID property; this key lists extensions
|
||||
which should be loaded. Any extension that wants to be loaded needs
|
||||
to be in this list. You can also manipulate this list with the
|
||||
EnableExtension and DisableExtension DBus methods on org.gnome.Shell.
|
||||
EnableExtension and DisableExtension D-Bus methods on org.gnome.Shell.
|
||||
</_description>
|
||||
</key>
|
||||
<key name="favorite-apps" type="as">
|
||||
@ -29,14 +29,6 @@
|
||||
will be displayed in the favorites area.
|
||||
</_description>
|
||||
</key>
|
||||
<key name="app-folder-categories" type="as">
|
||||
<default>[ 'Utilities', 'Sundry' ]</default>
|
||||
<_summary>List of categories that should be displayed as folders</_summary>
|
||||
<_description>
|
||||
Each category name in this list will be represented as folder in the
|
||||
application view, rather than being displayed inline in the main view.
|
||||
</_description>
|
||||
</key>
|
||||
<key name="app-picker-view" type="u">
|
||||
<default>0</default>
|
||||
<summary>App Picker View</summary>
|
||||
@ -54,10 +46,10 @@
|
||||
</key>
|
||||
<key name="always-show-log-out" type="b">
|
||||
<default>false</default>
|
||||
<_summary>Always show the 'Log out' menuitem in the user menu.</_summary>
|
||||
<_summary>Always show the 'Log out' menu item in the user menu.</_summary>
|
||||
<_description>
|
||||
This key overrides the automatic hiding of the 'Log out'
|
||||
menuitem in single-user, single-session situations.
|
||||
menu item in single-user, single-session situations.
|
||||
</_description>
|
||||
</key>
|
||||
<key name="remember-mount-password" type="b">
|
||||
@ -124,6 +116,11 @@
|
||||
Keybinding to focus the active notification.
|
||||
</_description>
|
||||
</key>
|
||||
<key name="pause-resume-tweens" type="as">
|
||||
<default>[]</default>
|
||||
<summary>Keybinding that pauses and resumes all running tweens, for debugging purposes</summary>
|
||||
<description></description>
|
||||
</key>
|
||||
</schema>
|
||||
|
||||
<schema id="org.gnome.shell.keyboard" path="/org/gnome/shell/keyboard/"
|
||||
|
@ -1944,6 +1944,7 @@ StScrollBar StButton#vhandle:active {
|
||||
|
||||
.end-session-dialog-description:rtl {
|
||||
padding-right: 17px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.end-session-dialog-logout-icon {
|
||||
@ -1976,6 +1977,10 @@ StScrollBar StButton#vhandle:active {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.end-session-dialog-list-header:rtl {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.end-session-dialog-app-list-item,
|
||||
.end-session-dialog-session-list-item {
|
||||
spacing: 1em;
|
||||
@ -2095,6 +2100,10 @@ StScrollBar StButton#vhandle:active {
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.prompt-dialog-description:rtl {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.prompt-dialog-password-box {
|
||||
spacing: 1em;
|
||||
padding-bottom: 1em;
|
||||
@ -2321,6 +2330,8 @@ StScrollBar StButton#vhandle:active {
|
||||
.login-dialog-user-list-item {
|
||||
border-radius: 5px;
|
||||
padding: .2em;
|
||||
color: #bfbfbf;
|
||||
text-shadow: black 0px 2px 2px;
|
||||
}
|
||||
|
||||
.login-dialog-user-list-item:ltr {
|
||||
@ -2331,24 +2342,6 @@ StScrollBar StButton#vhandle:active {
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
.login-dialog-user-list-item .login-dialog-user-list-item-name {
|
||||
font-size: 20px;
|
||||
padding-left: 18px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.login-dialog-user-list:expanded .login-dialog-user-list-item {
|
||||
color: #bfbfbf;
|
||||
}
|
||||
|
||||
.login-dialog-user-list-item,
|
||||
.login-dialog-user-list-item:hover .login-dialog-user-list-item-name,
|
||||
.login-dialog-user-list:expanded .login-dialog-user-list-item:focus .login-dialog-user-list-item-name,
|
||||
.login-dialog-user-list:expanded .login-dialog-user-list-item:logged-in {
|
||||
color: #bfbfbf;
|
||||
text-shadow: black 0px 2px 2px;
|
||||
}
|
||||
|
||||
.login-dialog-user-list-item:hover {
|
||||
background-color: rgba(255,255,255,0.1);
|
||||
}
|
||||
@ -2375,13 +2368,6 @@ StScrollBar StButton#vhandle:active {
|
||||
background-color: #8b8b8b;
|
||||
}
|
||||
|
||||
.login-dialog-user-list-item-icon {
|
||||
border: 2px solid #8b8b8b;
|
||||
border-radius: 3px;
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
}
|
||||
|
||||
.login-dialog-not-listed-label {
|
||||
font-size: 10.5pt;
|
||||
font-weight: bold;
|
||||
@ -2432,6 +2418,7 @@ StScrollBar StButton#vhandle:active {
|
||||
}
|
||||
|
||||
.login-dialog-session-list-button:hover,
|
||||
.login-dialog-session-list-button:focus,
|
||||
.login-dialog-session-list-button:active {
|
||||
color: white;
|
||||
}
|
||||
@ -2501,11 +2488,18 @@ StScrollBar StButton#vhandle:active {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
text-align: left;
|
||||
padding-left: 18px;
|
||||
color:white;
|
||||
text-shadow: black 0px 4px 3px 0px;
|
||||
}
|
||||
|
||||
.user-widget-label:ltr {
|
||||
padding-left: 18px;
|
||||
}
|
||||
|
||||
.user-widget-label:rtl {
|
||||
padding-right: 18px;
|
||||
}
|
||||
|
||||
/* Screen shield */
|
||||
|
||||
#panel.lock-screen,
|
||||
@ -2518,7 +2512,7 @@ StScrollBar StButton#vhandle:active {
|
||||
box-shadow: 0px 4px 8px rgba(0,0,0,0.9);
|
||||
}
|
||||
|
||||
#lockDialogGroup {
|
||||
#systemGroup {
|
||||
background: #2e3436 url(noise-texture.png);
|
||||
background-repeat: repeat;
|
||||
}
|
||||
@ -2630,4 +2624,5 @@ StScrollBar StButton#vhandle:active {
|
||||
|
||||
.background-menu {
|
||||
-boxpointer-gap: 4px;
|
||||
-arrow-rise: 0px;
|
||||
}
|
||||
|
@ -112,7 +112,7 @@ expand_content_files=
|
||||
# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
|
||||
# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
|
||||
GTKDOC_CFLAGS=$(GNOME_SHELL_CFLAGS)
|
||||
GTKDOC_LIBS=$(GNOME_SHELL_LIBS) $(BLUETOOTH_LIBS) $(top_builddir)/src/libgnome-shell-menu.la $(top_builddir)/src/libgnome-shell-base.la $(top_builddir)/src/libgnome-shell.la
|
||||
GTKDOC_LIBS=$(GNOME_SHELL_LIBS) $(top_builddir)/src/libgnome-shell-menu.la $(top_builddir)/src/libgnome-shell-base.la $(top_builddir)/src/libgnome-shell.la
|
||||
|
||||
# This includes the standard gtk-doc make rules, copied by gtkdocize.
|
||||
include $(top_srcdir)/gtk-doc.make
|
||||
|
@ -80,6 +80,7 @@ const AuthPrompt = new Lang.Class({
|
||||
if (event.get_key_symbol() == Clutter.KEY_Escape) {
|
||||
this.cancel();
|
||||
}
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
}));
|
||||
|
||||
this._userWell = new St.Bin({ x_fill: true,
|
||||
@ -93,7 +94,7 @@ const AuthPrompt = new Lang.Class({
|
||||
|
||||
this.actor.add(this._label,
|
||||
{ expand: true,
|
||||
x_fill: true,
|
||||
x_fill: false,
|
||||
y_fill: true,
|
||||
x_align: St.Align.START });
|
||||
this._entry = new St.Entry({ style_class: 'login-dialog-prompt-entry',
|
||||
@ -111,7 +112,7 @@ const AuthPrompt = new Lang.Class({
|
||||
this._message = new St.Label({ opacity: 0,
|
||||
styleClass: 'login-dialog-message' });
|
||||
this._message.clutter_text.line_wrap = true;
|
||||
this.actor.add(this._message, { x_fill: true, y_align: St.Align.START });
|
||||
this.actor.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 });
|
||||
@ -263,10 +264,8 @@ const AuthPrompt = new Lang.Class({
|
||||
},
|
||||
|
||||
_onReset: function() {
|
||||
if (this.verificationStatus != AuthPromptStatus.VERIFICATION_SUCCEEDED) {
|
||||
this.verificationStatus = AuthPromptStatus.NOT_VERIFYING;
|
||||
this.reset();
|
||||
}
|
||||
this.verificationStatus = AuthPromptStatus.NOT_VERIFYING;
|
||||
this.reset();
|
||||
},
|
||||
|
||||
addActorToDefaultButtonWell: function(actor) {
|
||||
|
@ -13,9 +13,7 @@
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
const Lang = imports.lang;
|
||||
|
@ -13,9 +13,7 @@
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
const AccountsService = imports.gi.AccountsService;
|
||||
@ -276,7 +274,7 @@ const SessionMenuButton = new Lang.Class({
|
||||
this.actor = new St.Bin({ child: this._button });
|
||||
|
||||
this._menu = new PopupMenu.PopupMenu(this._button, 0, St.Side.TOP);
|
||||
Main.uiGroup.add_actor(this._menu.actor);
|
||||
Main.layoutManager.menuGroup.add_actor(this._menu.actor);
|
||||
this._menu.actor.hide();
|
||||
|
||||
this._menu.connect('open-state-changed',
|
||||
@ -456,18 +454,6 @@ const LoginDialog = new Lang.Class({
|
||||
this.actor.add_child(this._logoBin);
|
||||
this._updateLogo();
|
||||
|
||||
if (!this._userManager.is_loaded)
|
||||
this._userManagerLoadedId = this._userManager.connect('notify::is-loaded',
|
||||
Lang.bind(this, function() {
|
||||
if (this._userManager.is_loaded) {
|
||||
this._loadUserList();
|
||||
this._userManager.disconnect(this._userManagerLoadedId);
|
||||
this._userManagerLoadedId = 0;
|
||||
}
|
||||
}));
|
||||
else
|
||||
this._loadUserList();
|
||||
|
||||
this._userList.connect('activate',
|
||||
Lang.bind(this, function(userList, item) {
|
||||
this._onUserListActivated(item);
|
||||
@ -483,6 +469,18 @@ const LoginDialog = new Lang.Class({
|
||||
this._sessionMenuButton.actor.show();
|
||||
this._authPrompt.addActorToDefaultButtonWell(this._sessionMenuButton.actor);
|
||||
|
||||
if (!this._userManager.is_loaded)
|
||||
this._userManagerLoadedId = this._userManager.connect('notify::is-loaded',
|
||||
Lang.bind(this, function() {
|
||||
if (this._userManager.is_loaded) {
|
||||
this._loadUserList();
|
||||
this._userManager.disconnect(this._userManagerLoadedId);
|
||||
this._userManagerLoadedId = 0;
|
||||
}
|
||||
}));
|
||||
else
|
||||
GLib.idle_add(GLib.PRIORITY_DEFAULT, Lang.bind(this, this._loadUserList));
|
||||
|
||||
},
|
||||
|
||||
_updateDisableUserList: function() {
|
||||
@ -644,7 +642,7 @@ const LoginDialog = new Lang.Class({
|
||||
onComplete: function() {
|
||||
Mainloop.idle_add(Lang.bind(this, function() {
|
||||
this._greeter.call_start_session_when_ready_sync(serviceName, true, null);
|
||||
return false;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
}));
|
||||
},
|
||||
onCompleteScope: this });
|
||||
@ -699,6 +697,7 @@ const LoginDialog = new Lang.Class({
|
||||
function() {
|
||||
this._timedLoginAnimationTime -= _TIMED_LOGIN_IDLE_THRESHOLD;
|
||||
hold.release();
|
||||
return GLib.SOURCE_REMOVE;
|
||||
});
|
||||
return hold;
|
||||
},
|
||||
@ -763,7 +762,7 @@ const LoginDialog = new Lang.Class({
|
||||
global.stage.connect('captured-event',
|
||||
Lang.bind(this, function(actor, event) {
|
||||
if (this._timedLoginDelay == undefined)
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
||||
if (event.type() == Clutter.EventType.KEY_PRESS ||
|
||||
event.type() == Clutter.EventType.BUTTON_PRESS) {
|
||||
@ -776,7 +775,7 @@ const LoginDialog = new Lang.Class({
|
||||
this._resetTimedLogin();
|
||||
}
|
||||
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
}));
|
||||
},
|
||||
|
||||
@ -885,6 +884,10 @@ const LoginDialog = new Lang.Class({
|
||||
Main.ctrlAltTabManager.removeGroup(this.dialogLayout);
|
||||
},
|
||||
|
||||
cancel: function() {
|
||||
this._authPrompt.cancel();
|
||||
},
|
||||
|
||||
addCharacter: function(unichar) {
|
||||
this._authPrompt.addCharacter(unichar);
|
||||
},
|
||||
|
@ -250,6 +250,7 @@ const ShellUserVerifier = new Lang.Class({
|
||||
Lang.bind(this, function() {
|
||||
this._messageQueueTimeoutId = 0;
|
||||
this._queueMessageTimeout();
|
||||
return GLib.SOURCE_REMOVE;
|
||||
}));
|
||||
},
|
||||
|
||||
|
@ -8,12 +8,13 @@
|
||||
<file>gdm/oVirt.js</file>
|
||||
<file>gdm/realmd.js</file>
|
||||
<file>gdm/util.js</file>
|
||||
|
||||
<file>extensionPrefs/main.js</file>
|
||||
|
||||
<file>misc/config.js</file>
|
||||
<file>misc/extensionUtils.js</file>
|
||||
<file>misc/fileUtils.js</file>
|
||||
<file>misc/gnomeSession.js</file>
|
||||
<file>misc/hash.js</file>
|
||||
<file>misc/history.js</file>
|
||||
<file>misc/jsParse.js</file>
|
||||
<file>misc/loginManager.js</file>
|
||||
@ -22,7 +23,9 @@
|
||||
<file>misc/params.js</file>
|
||||
<file>misc/smartcardManager.js</file>
|
||||
<file>misc/util.js</file>
|
||||
|
||||
<file>perf/core.js</file>
|
||||
|
||||
<file>ui/altTab.js</file>
|
||||
<file>ui/animation.js</file>
|
||||
<file>ui/appDisplay.js</file>
|
||||
@ -37,12 +40,12 @@
|
||||
<file>ui/dateMenu.js</file>
|
||||
<file>ui/dnd.js</file>
|
||||
<file>ui/endSessionDialog.js</file>
|
||||
<file>ui/extensionSystem.js</file>
|
||||
<file>ui/extensionDownloader.js</file>
|
||||
<file>ui/environment.js</file>
|
||||
<file>ui/extensionDownloader.js</file>
|
||||
<file>ui/extensionSystem.js</file>
|
||||
<file>ui/focusCaretTracker.js</file>
|
||||
<file>ui/ibusCandidatePopup.js</file>
|
||||
<file>ui/grabHelper.js</file>
|
||||
<file>ui/ibusCandidatePopup.js</file>
|
||||
<file>ui/iconGrid.js</file>
|
||||
<file>ui/keyboard.js</file>
|
||||
<file>ui/layout.js</file>
|
||||
@ -53,11 +56,6 @@
|
||||
<file>ui/main.js</file>
|
||||
<file>ui/messageTray.js</file>
|
||||
<file>ui/modalDialog.js</file>
|
||||
<file>ui/separator.js</file>
|
||||
<file>ui/sessionMode.js</file>
|
||||
<file>ui/shellEntry.js</file>
|
||||
<file>ui/shellMountOperation.js</file>
|
||||
<file>ui/slider.js</file>
|
||||
<file>ui/notificationDaemon.js</file>
|
||||
<file>ui/osdWindow.js</file>
|
||||
<file>ui/overview.js</file>
|
||||
@ -66,25 +64,20 @@
|
||||
<file>ui/panelMenu.js</file>
|
||||
<file>ui/pointerWatcher.js</file>
|
||||
<file>ui/popupMenu.js</file>
|
||||
<file>ui/remoteSearch.js</file>
|
||||
<file>ui/remoteMenu.js</file>
|
||||
<file>ui/remoteSearch.js</file>
|
||||
<file>ui/runDialog.js</file>
|
||||
<file>ui/screenShield.js</file>
|
||||
<file>ui/screencast.js</file>
|
||||
<file>ui/screenshot.js</file>
|
||||
<file>ui/screenShield.js</file>
|
||||
<file>ui/scripting.js</file>
|
||||
<file>ui/search.js</file>
|
||||
<file>ui/separator.js</file>
|
||||
<file>ui/sessionMode.js</file>
|
||||
<file>ui/shellDBus.js</file>
|
||||
<file>ui/status/accessibility.js</file>
|
||||
<file>ui/status/brightness.js</file>
|
||||
<file>ui/status/keyboard.js</file>
|
||||
<file>ui/status/network.js</file>
|
||||
<file>ui/status/power.js</file>
|
||||
<file>ui/status/rfkill.js</file>
|
||||
<file>ui/status/volume.js</file>
|
||||
<file>ui/status/bluetooth.js</file>
|
||||
<file>ui/status/screencast.js</file>
|
||||
<file>ui/status/system.js</file>
|
||||
<file>ui/shellEntry.js</file>
|
||||
<file>ui/shellMountOperation.js</file>
|
||||
<file>ui/slider.js</file>
|
||||
<file>ui/switcherPopup.js</file>
|
||||
<file>ui/tweener.js</file>
|
||||
<file>ui/unlockDialog.js</file>
|
||||
@ -93,10 +86,11 @@
|
||||
<file>ui/windowAttentionHandler.js</file>
|
||||
<file>ui/windowManager.js</file>
|
||||
<file>ui/workspace.js</file>
|
||||
<file>ui/workspaceSwitcherPopup.js</file>
|
||||
<file>ui/workspaceThumbnail.js</file>
|
||||
<file>ui/workspacesView.js</file>
|
||||
<file>ui/workspaceSwitcherPopup.js</file>
|
||||
<file>ui/xdndHandler.js</file>
|
||||
|
||||
<file>ui/components/__init__.js</file>
|
||||
<file>ui/components/autorunManager.js</file>
|
||||
<file>ui/components/automountManager.js</file>
|
||||
@ -104,5 +98,17 @@
|
||||
<file>ui/components/polkitAgent.js</file>
|
||||
<file>ui/components/telepathyClient.js</file>
|
||||
<file>ui/components/keyring.js</file>
|
||||
|
||||
<file>ui/status/accessibility.js</file>
|
||||
<file>ui/status/brightness.js</file>
|
||||
<file>ui/status/location.js</file>
|
||||
<file>ui/status/keyboard.js</file>
|
||||
<file>ui/status/network.js</file>
|
||||
<file>ui/status/power.js</file>
|
||||
<file>ui/status/rfkill.js</file>
|
||||
<file>ui/status/volume.js</file>
|
||||
<file>ui/status/bluetooth.js</file>
|
||||
<file>ui/status/screencast.js</file>
|
||||
<file>ui/status/system.js</file>
|
||||
</gresource>
|
||||
</gresources>
|
||||
|
@ -5,26 +5,6 @@ const GLib = imports.gi.GLib;
|
||||
const Lang = imports.lang;
|
||||
const Params = imports.misc.params;
|
||||
|
||||
function listDirAsync(file, callback) {
|
||||
let allFiles = [];
|
||||
file.enumerate_children_async('standard::name,standard::type',
|
||||
Gio.FileQueryInfoFlags.NONE,
|
||||
GLib.PRIORITY_LOW, null, function (obj, res) {
|
||||
let enumerator = obj.enumerate_children_finish(res);
|
||||
function onNextFileComplete(obj, res) {
|
||||
let files = obj.next_files_finish(res);
|
||||
if (files.length) {
|
||||
allFiles = allFiles.concat(files);
|
||||
enumerator.next_files_async(100, GLib.PRIORITY_LOW, null, onNextFileComplete);
|
||||
} else {
|
||||
enumerator.close(null);
|
||||
callback(allFiles);
|
||||
}
|
||||
}
|
||||
enumerator.next_files_async(100, GLib.PRIORITY_LOW, null, onNextFileComplete);
|
||||
});
|
||||
}
|
||||
|
||||
function collectFromDatadirs(subdir, includeUserDir, processFile) {
|
||||
let dataDirs = GLib.get_system_data_dirs();
|
||||
if (includeUserDir)
|
||||
|
144
js/misc/hash.js
144
js/misc/hash.js
@ -1,144 +0,0 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Lang = imports.lang;
|
||||
const System = imports.system;
|
||||
|
||||
const Params = imports.misc.params;
|
||||
|
||||
// This is an implementation of EcmaScript SameValue algorithm,
|
||||
// which returns true if two values are not observably distinguishable.
|
||||
// It was taken from http://wiki.ecmascript.org/doku.php?id=harmony:egal
|
||||
//
|
||||
// In the future, we may want to use the 'is' operator instead.
|
||||
function _sameValue(x, y) {
|
||||
if (x === y) {
|
||||
// 0 === -0, but they are not identical
|
||||
return x !== 0 || 1 / x === 1 / y;
|
||||
}
|
||||
|
||||
// NaN !== NaN, but they are identical.
|
||||
// NaNs are the only non-reflexive value, i.e., if x !== x,
|
||||
// then x is a NaN.
|
||||
// isNaN is broken: it converts its argument to number, so
|
||||
// isNaN("foo") => true
|
||||
return x !== x && y !== y;
|
||||
}
|
||||
|
||||
const _hashers = {
|
||||
object: function(o) { return o ? System.addressOf(o) : 'null'; },
|
||||
function: function(f) { return System.addressOf(f); },
|
||||
string: function(s) { return s; },
|
||||
number: function(n) { return String(n); },
|
||||
undefined: function() { return 'undefined'; },
|
||||
};
|
||||
|
||||
/* Map is meant to be similar in usage to ES6 Map, which is
|
||||
described at http://wiki.ecmascript.org/doku.php?id=harmony:simple_maps_and_sets,
|
||||
without requiring more than ES5 + Gjs extensions.
|
||||
|
||||
Known differences from other implementations:
|
||||
Polyfills around the web usually implement HashMaps for
|
||||
primitive values and reversed WeakMaps for object keys,
|
||||
but we want real maps with real O(1) semantics in all cases,
|
||||
and the easiest way is to have different hashers for different
|
||||
types.
|
||||
|
||||
Known differences from the ES6 specification:
|
||||
- Map is a Lang.Class, not a ES6 class, so inheritance,
|
||||
prototype, sealing, etc. work differently.
|
||||
- items(), keys() and values() don't return iterators,
|
||||
they return actual arrays, so they incur a full copy everytime
|
||||
they're called, and they don't see changes if you mutate
|
||||
the table while iterating
|
||||
(admittedly, the ES6 spec is a bit unclear on this, and
|
||||
the reference code would just blow up)
|
||||
*/
|
||||
const Map = new Lang.Class({
|
||||
Name: 'Map',
|
||||
|
||||
_init: function(iterable) {
|
||||
this._pool = { };
|
||||
this._size = 0;
|
||||
|
||||
if (iterable) {
|
||||
for (let i = 0; i < iterable.length; i++) {
|
||||
let [key, value] = iterable[i];
|
||||
this.set(key, value);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_hashKey: function(key) {
|
||||
let type = typeof(key);
|
||||
return type + ':' + _hashers[type](key);
|
||||
},
|
||||
|
||||
_internalGet: function(key) {
|
||||
let hash = this._hashKey(key);
|
||||
let node = this._pool[hash];
|
||||
|
||||
if (node && _sameValue(node.key, key))
|
||||
return [true, node.value];
|
||||
else
|
||||
return [false, null];
|
||||
},
|
||||
|
||||
get: function(key) {
|
||||
return this._internalGet(key)[1];
|
||||
},
|
||||
|
||||
has: function(key) {
|
||||
return this._internalGet(key)[0];
|
||||
},
|
||||
|
||||
set: function(key, value) {
|
||||
let hash = this._hashKey(key);
|
||||
let node = this._pool[hash];
|
||||
|
||||
if (node) {
|
||||
node.key = key;
|
||||
node.value = value;
|
||||
} else {
|
||||
this._pool[hash] = { key: key, value: value };
|
||||
this._size++;
|
||||
}
|
||||
},
|
||||
|
||||
delete: function(key) {
|
||||
let hash = this._hashKey(key);
|
||||
let node = this._pool[hash];
|
||||
|
||||
if (node && _sameValue(node.key, key)) {
|
||||
delete this._pool[hash];
|
||||
this._size--;
|
||||
return [node.key, node.value];
|
||||
} else {
|
||||
return [null, null];
|
||||
}
|
||||
},
|
||||
|
||||
keys: function() {
|
||||
let pool = this._pool;
|
||||
return Object.getOwnPropertyNames(pool).map(function(hash) {
|
||||
return pool[hash].key;
|
||||
});
|
||||
},
|
||||
|
||||
values: function() {
|
||||
let pool = this._pool;
|
||||
return Object.getOwnPropertyNames(pool).map(function(hash) {
|
||||
return pool[hash].value;
|
||||
});
|
||||
},
|
||||
|
||||
items: function() {
|
||||
let pool = this._pool;
|
||||
return Object.getOwnPropertyNames(pool).map(function(hash) {
|
||||
return [pool[hash].key, pool[hash].value];
|
||||
});
|
||||
},
|
||||
|
||||
size: function() {
|
||||
return this._size;
|
||||
},
|
||||
});
|
@ -89,7 +89,7 @@ const HistoryManager = new Lang.Class({
|
||||
} else if (symbol == Clutter.KEY_Down) {
|
||||
return this._setNextItem(entry.get_text());
|
||||
}
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
},
|
||||
|
||||
_indexChanged: function() {
|
||||
|
@ -89,7 +89,7 @@ function spawnApp(argv) {
|
||||
let app = Gio.AppInfo.create_from_commandline(argv.join(' '), null,
|
||||
Gio.AppInfoCreateFlags.SUPPORTS_STARTUP_NOTIFICATION);
|
||||
|
||||
let context = global.create_app_launch_context();
|
||||
let context = global.create_app_launch_context(0, -1);
|
||||
app.launch([], context);
|
||||
} catch(err) {
|
||||
_handleSpawnError(argv[0], err);
|
||||
@ -153,7 +153,7 @@ function trySpawnCommandLine(command_line) {
|
||||
}
|
||||
|
||||
function _handleSpawnError(command, err) {
|
||||
let title = _("Execution of '%s' failed:").format(command);
|
||||
let title = _("Execution of “%s” failed:").format(command);
|
||||
Main.notifyError(title, err.message);
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Lang = imports.lang;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Meta = imports.gi.Meta;
|
||||
@ -312,7 +313,7 @@ const AppSwitcherPopup = new Lang.Class({
|
||||
this._createThumbnails();
|
||||
this._thumbnailTimeoutId = 0;
|
||||
this._thumbnailsFocused = false;
|
||||
return false;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
},
|
||||
|
||||
_destroyThumbnails : function() {
|
||||
@ -459,9 +460,10 @@ const AppSwitcher = new Lang.Class({
|
||||
appIcon.cachedWindows = allWindows.filter(function(w) {
|
||||
return windowTracker.get_window_app (w) == appIcon.app;
|
||||
});
|
||||
if (workspace == null || appIcon.cachedWindows.length > 0) {
|
||||
if (appIcon.cachedWindows.length > 0)
|
||||
this._addIcon(appIcon);
|
||||
}
|
||||
else if (workspace == null)
|
||||
throw new Error('%s appears to be running, but doesn\'t have any windows'.format(appIcon.app.get_name()));
|
||||
}
|
||||
|
||||
this._curApp = -1;
|
||||
@ -547,7 +549,7 @@ const AppSwitcher = new Lang.Class({
|
||||
Lang.bind(this, function () {
|
||||
this._enterItem(index);
|
||||
this._mouseTimeOutId = 0;
|
||||
return false;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
}));
|
||||
} else
|
||||
this._itemEntered(index);
|
||||
|
@ -1,5 +1,6 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const GLib = imports.gi.GLib;
|
||||
const Lang = imports.lang;
|
||||
const Mainloop = imports.mainloop;
|
||||
const St = imports.gi.St;
|
||||
@ -59,7 +60,7 @@ const Animation = new Lang.Class({
|
||||
|
||||
_update: function() {
|
||||
this._showFrame(this._frame + 1);
|
||||
return true;
|
||||
return GLib.SOURCE_CONTINUE;
|
||||
},
|
||||
|
||||
_animationsLoaded: function() {
|
||||
|
@ -5,7 +5,6 @@ const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const GObject = imports.gi.GObject;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const GMenu = imports.gi.GMenu;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Lang = imports.lang;
|
||||
const Signals = imports.signals;
|
||||
@ -47,24 +46,45 @@ const INDICATORS_ANIMATION_MAX_TIME = 0.75;
|
||||
const PAGE_SWITCH_TRESHOLD = 0.2;
|
||||
const PAGE_SWITCH_TIME = 0.3;
|
||||
|
||||
// Recursively load a GMenuTreeDirectory; we could put this in ShellAppSystem too
|
||||
function _loadCategory(dir, view) {
|
||||
let iter = dir.iter();
|
||||
let appSystem = Shell.AppSystem.get_default();
|
||||
let nextType;
|
||||
while ((nextType = iter.next()) != GMenu.TreeItemType.INVALID) {
|
||||
if (nextType == GMenu.TreeItemType.ENTRY) {
|
||||
let entry = iter.get_entry();
|
||||
let appInfo = entry.get_app_info();
|
||||
let app = appSystem.lookup_app(entry.get_desktop_file_id());
|
||||
if (appInfo.should_show())
|
||||
view.addApp(app);
|
||||
} else if (nextType == GMenu.TreeItemType.DIRECTORY) {
|
||||
let itemDir = iter.get_directory();
|
||||
_loadCategory(itemDir, view);
|
||||
function _getCategories(info) {
|
||||
let categoriesStr = info.get_categories();
|
||||
if (!categoriesStr)
|
||||
return [];
|
||||
return categoriesStr.split(';');
|
||||
}
|
||||
|
||||
function _isTerminal(app) {
|
||||
let info = app.get_app_info();
|
||||
if (!info)
|
||||
return false;
|
||||
let categories = _getCategories(info);
|
||||
return categories.indexOf('TerminalEmulator') > -1;
|
||||
}
|
||||
|
||||
function _listsIntersect(a, b) {
|
||||
for (let itemA of a)
|
||||
if (b.indexOf(itemA) >= 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
function _getFolderName(folder) {
|
||||
let name = folder.get_string('name');
|
||||
|
||||
if (folder.get_boolean('translate')) {
|
||||
let keyfile = new GLib.KeyFile();
|
||||
let path = 'desktop-directories/' + name;
|
||||
|
||||
try {
|
||||
keyfile.load_from_data_dirs(path, GLib.KeyFileFlags.NONE);
|
||||
name = keyfile.get_locale_string('Desktop Entry', 'Name', null);
|
||||
} catch(e) {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
const BaseAppView = new Lang.Class({
|
||||
Name: 'BaseAppView',
|
||||
@ -97,40 +117,33 @@ const BaseAppView = new Lang.Class({
|
||||
this._allItems = [];
|
||||
},
|
||||
|
||||
_getItemId: function(item) {
|
||||
throw new Error('Not implemented');
|
||||
_redisplay: function() {
|
||||
this.removeAll();
|
||||
this._loadApps();
|
||||
},
|
||||
|
||||
_createItemIcon: function(item) {
|
||||
throw new Error('Not implemented');
|
||||
getAllItems: function() {
|
||||
return this._allItems;
|
||||
},
|
||||
|
||||
addItem: function(icon) {
|
||||
let id = icon.id;
|
||||
if (this._items[id] !== undefined)
|
||||
return;
|
||||
|
||||
this._allItems.push(icon);
|
||||
this._items[id] = icon;
|
||||
},
|
||||
|
||||
_compareItems: function(a, b) {
|
||||
throw new Error('Not implemented');
|
||||
},
|
||||
|
||||
_addItem: function(item) {
|
||||
let id = this._getItemId(item);
|
||||
if (this._items[id] !== undefined)
|
||||
return null;
|
||||
|
||||
let itemIcon = this._createItemIcon(item);
|
||||
this._allItems.push(item);
|
||||
this._items[id] = itemIcon;
|
||||
|
||||
return itemIcon;
|
||||
return a.name.localeCompare(b.name);
|
||||
},
|
||||
|
||||
loadGrid: function() {
|
||||
this._allItems.sort(Lang.bind(this, this._compareItems));
|
||||
|
||||
for (let i = 0; i < this._allItems.length; i++) {
|
||||
let id = this._getItemId(this._allItems[i]);
|
||||
if (!id)
|
||||
continue;
|
||||
this._grid.addItem(this._items[id]);
|
||||
}
|
||||
|
||||
this._allItems.sort(this._compareItems);
|
||||
this._allItems.forEach(Lang.bind(this, function(item) {
|
||||
this._grid.addItem(item);
|
||||
}));
|
||||
this.emit('view-loaded');
|
||||
},
|
||||
|
||||
@ -281,7 +294,7 @@ const AllView = new Lang.Class({
|
||||
this._pageIndicators.actor.connect('scroll-event', Lang.bind(this, this._onScroll));
|
||||
this.actor.add_actor(this._pageIndicators.actor);
|
||||
|
||||
this._folderIcons = [];
|
||||
this.folderIcons = [];
|
||||
|
||||
this._stack = new St.Widget({ layout_manager: new Clutter.BinLayout() });
|
||||
let box = new St.BoxLayout({ vertical: true });
|
||||
@ -346,6 +359,76 @@ const AllView = new Lang.Class({
|
||||
this._keyPressEventId = 0;
|
||||
}
|
||||
}));
|
||||
|
||||
this._redisplayWorkId = Main.initializeDeferredWork(this.actor, Lang.bind(this, this._redisplay));
|
||||
|
||||
Shell.AppSystem.get_default().connect('installed-changed', Lang.bind(this, function() {
|
||||
Main.queueDeferredWork(this._redisplayWorkId);
|
||||
}));
|
||||
this._folderSettings = new Gio.Settings({ schema: 'org.gnome.desktop.app-folders' });
|
||||
this._folderSettings.connect('changed::folder-children', Lang.bind(this, function() {
|
||||
Main.queueDeferredWork(this._redisplayWorkId);
|
||||
}));
|
||||
},
|
||||
|
||||
removeAll: function() {
|
||||
this.folderIcons = [];
|
||||
this.parent();
|
||||
},
|
||||
|
||||
_itemNameChanged: function(item) {
|
||||
// If an item's name changed, we can pluck it out of where it's
|
||||
// supposed to be and reinsert it where it's sorted.
|
||||
let oldIdx = this._allItems.indexOf(item);
|
||||
this._allItems.splice(oldIdx, 1);
|
||||
let newIdx = Util.insertSorted(this._allItems, item, this._compareItems);
|
||||
|
||||
this._grid.removeItem(item);
|
||||
this._grid.addItem(item, newIdx);
|
||||
},
|
||||
|
||||
_refilterApps: function() {
|
||||
this._allItems.forEach(function(icon) {
|
||||
if (icon instanceof AppIcon)
|
||||
icon.actor.visible = true;
|
||||
});
|
||||
|
||||
this.folderIcons.forEach(Lang.bind(this, function(folder) {
|
||||
let folderApps = folder.getAppIds();
|
||||
folderApps.forEach(Lang.bind(this, function(appId) {
|
||||
let appIcon = this._items[appId];
|
||||
appIcon.actor.visible = false;
|
||||
}));
|
||||
}));
|
||||
},
|
||||
|
||||
_loadApps: function() {
|
||||
let apps = Gio.AppInfo.get_all().filter(function(appInfo) {
|
||||
return appInfo.should_show();
|
||||
}).map(function(app) {
|
||||
return app.get_id();
|
||||
});
|
||||
|
||||
let appSys = Shell.AppSystem.get_default();
|
||||
|
||||
let folders = this._folderSettings.get_strv('folder-children');
|
||||
folders.forEach(Lang.bind(this, function(id) {
|
||||
let path = this._folderSettings.path + 'folders/' + id + '/';
|
||||
let icon = new FolderIcon(id, path, this);
|
||||
icon.connect('name-changed', Lang.bind(this, this._itemNameChanged));
|
||||
icon.connect('apps-changed', Lang.bind(this, this._refilterApps));
|
||||
this.addItem(icon);
|
||||
this.folderIcons.push(icon);
|
||||
}));
|
||||
|
||||
apps.forEach(Lang.bind(this, function(appId) {
|
||||
let app = appSys.lookup_app(appId);
|
||||
let icon = new AppIcon(app);
|
||||
this.addItem(icon);
|
||||
}));
|
||||
|
||||
this.loadGrid();
|
||||
this._refilterApps();
|
||||
},
|
||||
|
||||
getCurrentPageY: function() {
|
||||
@ -415,7 +498,7 @@ const AllView = new Lang.Class({
|
||||
|
||||
_onScroll: function(actor, event) {
|
||||
if (this._displayingPopup)
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
|
||||
let direction = event.get_scroll_direction();
|
||||
if (direction == Clutter.ScrollDirection.UP)
|
||||
@ -423,7 +506,7 @@ const AllView = new Lang.Class({
|
||||
else if (direction == Clutter.ScrollDirection.DOWN)
|
||||
this.goToPage(this._currentPage + 1);
|
||||
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
},
|
||||
|
||||
_onPan: function(action) {
|
||||
@ -454,63 +537,17 @@ const AllView = new Lang.Class({
|
||||
|
||||
_onKeyPressEvent: function(actor, event) {
|
||||
if (this._displayingPopup)
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
|
||||
if (event.get_key_symbol() == Clutter.Page_Up) {
|
||||
this.goToPage(this._currentPage - 1);
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
} else if (event.get_key_symbol() == Clutter.Page_Down) {
|
||||
this.goToPage(this._currentPage + 1);
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
_getItemId: function(item) {
|
||||
if (item instanceof Shell.App)
|
||||
return item.get_id();
|
||||
else if (item instanceof GMenu.TreeDirectory)
|
||||
return item.get_menu_id();
|
||||
else
|
||||
return null;
|
||||
},
|
||||
|
||||
_createItemIcon: function(item) {
|
||||
if (item instanceof Shell.App)
|
||||
return new AppIcon(item);
|
||||
else if (item instanceof GMenu.TreeDirectory)
|
||||
return new FolderIcon(item, this);
|
||||
else
|
||||
return null;
|
||||
},
|
||||
|
||||
_compareItems: function(itemA, itemB) {
|
||||
// bit of a hack: rely on both ShellApp and GMenuTreeDirectory
|
||||
// having a get_name() method
|
||||
let nameA = GLib.utf8_collate_key(itemA.get_name(), -1);
|
||||
let nameB = GLib.utf8_collate_key(itemB.get_name(), -1);
|
||||
return (nameA > nameB) ? 1 : (nameA < nameB ? -1 : 0);
|
||||
},
|
||||
|
||||
removeAll: function() {
|
||||
this._folderIcons = [];
|
||||
this.parent();
|
||||
},
|
||||
|
||||
addApp: function(app) {
|
||||
let appIcon = this._addItem(app);
|
||||
if (appIcon)
|
||||
appIcon.actor.connect('key-focus-in',
|
||||
Lang.bind(this, this._ensureIconVisible));
|
||||
},
|
||||
|
||||
addFolder: function(dir) {
|
||||
let folderIcon = this._addItem(dir);
|
||||
this._folderIcons.push(folderIcon);
|
||||
if (folderIcon)
|
||||
folderIcon.actor.connect('key-focus-in',
|
||||
Lang.bind(this, this._ensureIconVisible));
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
},
|
||||
|
||||
addFolderPopup: function(popup) {
|
||||
@ -577,8 +614,8 @@ const AllView = new Lang.Class({
|
||||
this._availWidth = availWidth;
|
||||
this._availHeight = availHeight;
|
||||
// Update folder views
|
||||
for (let i = 0; i < this._folderIcons.length; i++)
|
||||
this._folderIcons[i].adaptToSize(availWidth, availHeight);
|
||||
for (let i = 0; i < this.folderIcons.length; i++)
|
||||
this.folderIcons[i].adaptToSize(availWidth, availHeight);
|
||||
}
|
||||
});
|
||||
Signals.addSignalMethods(AllView.prototype);
|
||||
@ -607,17 +644,18 @@ const FrequentView = new Lang.Class({
|
||||
this._noFrequentAppsLabel.hide();
|
||||
|
||||
this._usage = Shell.AppUsage.get_default();
|
||||
|
||||
this.actor.connect('notify::mapped', Lang.bind(this, function() {
|
||||
if (this.actor.mapped)
|
||||
this._redisplay();
|
||||
}));
|
||||
},
|
||||
|
||||
hasUsefulData: function() {
|
||||
return this._usage.get_most_used("").length >= MIN_FREQUENT_APPS_COUNT;
|
||||
},
|
||||
|
||||
removeAll: function() {
|
||||
this._grid.destroyAll();
|
||||
},
|
||||
|
||||
loadApps: function() {
|
||||
_loadApps: function() {
|
||||
let mostUsed = this._usage.get_most_used ("");
|
||||
let hasUsefulData = this.hasUsefulData();
|
||||
this._noFrequentAppsLabel.visible = !hasUsefulData;
|
||||
@ -695,15 +733,6 @@ const AppDisplay = new Lang.Class({
|
||||
Name: 'AppDisplay',
|
||||
|
||||
_init: function() {
|
||||
Shell.AppSystem.get_default().connect('installed-changed', Lang.bind(this, function() {
|
||||
Main.queueDeferredWork(this._allAppsWorkId);
|
||||
}));
|
||||
Main.overview.connect('showing', Lang.bind(this, function() {
|
||||
Main.queueDeferredWork(this._frequentAppsWorkId);
|
||||
}));
|
||||
global.settings.connect('changed::app-folder-categories', Lang.bind(this, function() {
|
||||
Main.queueDeferredWork(this._allAppsWorkId);
|
||||
}));
|
||||
this._privacySettings = new Gio.Settings({ schema: 'org.gnome.desktop.privacy' });
|
||||
this._privacySettings.connect('changed::remember-app-usage',
|
||||
Lang.bind(this, this._updateFrequentVisibility));
|
||||
@ -757,15 +786,6 @@ const AppDisplay = new Lang.Class({
|
||||
initialView = Views.ALL;
|
||||
this._showView(initialView);
|
||||
this._updateFrequentVisibility();
|
||||
|
||||
// We need a dummy actor to catch the keyboard focus if the
|
||||
// user Ctrl-Alt-Tabs here before the deferred work creates
|
||||
// our real contents
|
||||
this._focusDummy = new St.Bin({ can_focus: true });
|
||||
this._viewStack.add_actor(this._focusDummy);
|
||||
|
||||
this._allAppsWorkId = Main.initializeDeferredWork(this.actor, Lang.bind(this, this._redisplayAllApps));
|
||||
this._frequentAppsWorkId = Main.initializeDeferredWork(this.actor, Lang.bind(this, this._redisplayFrequentApps));
|
||||
},
|
||||
|
||||
_showView: function(activeIndex) {
|
||||
@ -799,51 +819,6 @@ const AppDisplay = new Lang.Class({
|
||||
this._showView(Views.ALL);
|
||||
},
|
||||
|
||||
_redisplay: function() {
|
||||
this._redisplayFrequentApps();
|
||||
this._redisplayAllApps();
|
||||
},
|
||||
|
||||
_redisplayFrequentApps: function() {
|
||||
let view = this._views[Views.FREQUENT].view;
|
||||
|
||||
view.removeAll();
|
||||
view.loadApps();
|
||||
},
|
||||
|
||||
_redisplayAllApps: function() {
|
||||
let view = this._views[Views.ALL].view;
|
||||
|
||||
view.removeAll();
|
||||
|
||||
let tree = new GMenu.Tree({ menu_basename: "applications.menu" });
|
||||
tree.load_sync();
|
||||
let root = tree.get_root_directory();
|
||||
|
||||
let iter = root.iter();
|
||||
let nextType;
|
||||
let folderCategories = global.settings.get_strv('app-folder-categories');
|
||||
while ((nextType = iter.next()) != GMenu.TreeItemType.INVALID) {
|
||||
if (nextType == GMenu.TreeItemType.DIRECTORY) {
|
||||
let dir = iter.get_directory();
|
||||
|
||||
if (folderCategories.indexOf(dir.get_menu_id()) != -1)
|
||||
view.addFolder(dir);
|
||||
else
|
||||
_loadCategory(dir, view);
|
||||
}
|
||||
}
|
||||
view.loadGrid();
|
||||
|
||||
if (this._focusDummy) {
|
||||
let focused = this._focusDummy.has_key_focus();
|
||||
this._focusDummy.destroy();
|
||||
this._focusDummy = null;
|
||||
if (focused)
|
||||
this.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
|
||||
}
|
||||
},
|
||||
|
||||
selectApp: function(id) {
|
||||
this._showView(Views.ALL);
|
||||
this._views[Views.ALL].view.selectApp(id);
|
||||
@ -889,18 +864,31 @@ const AppSearchProvider = new Lang.Class({
|
||||
},
|
||||
|
||||
getInitialResultSet: function(terms, callback, cancellable) {
|
||||
callback(this._appSys.initial_search(terms));
|
||||
let query = terms.join(' ');
|
||||
let groups = Gio.DesktopAppInfo.search(query);
|
||||
let usage = Shell.AppUsage.get_default();
|
||||
let results = [];
|
||||
groups.forEach(function(group) {
|
||||
group = group.filter(function(appID) {
|
||||
let app = Gio.DesktopAppInfo.new(appID);
|
||||
return app && app.should_show();
|
||||
});
|
||||
results = results.concat(group.sort(function(a, b) {
|
||||
return usage.compare('', a, b);
|
||||
}));
|
||||
});
|
||||
callback(results);
|
||||
},
|
||||
|
||||
getSubsearchResultSet: function(previousResults, terms, callback, cancellable) {
|
||||
callback(this._appSys.subsearch(previousResults, terms));
|
||||
this.getInitialResultSet(terms, callback, cancellable);
|
||||
},
|
||||
|
||||
activateResult: function(result) {
|
||||
let app = this._appSys.lookup_app(result);
|
||||
let event = Clutter.get_current_event();
|
||||
let modifiers = event ? event.get_state() : 0;
|
||||
let openNewWindow = modifiers & Clutter.ModifierType.CONTROL_MASK;
|
||||
let openNewWindow = (modifiers & Clutter.ModifierType.CONTROL_MASK) || _isTerminal(app);
|
||||
|
||||
if (openNewWindow)
|
||||
app.open_new_window(-1);
|
||||
@ -943,22 +931,6 @@ const FolderView = new Lang.Class({
|
||||
this.actor.add_action(action);
|
||||
},
|
||||
|
||||
_getItemId: function(item) {
|
||||
return item.get_id();
|
||||
},
|
||||
|
||||
_createItemIcon: function(item) {
|
||||
return new AppIcon(item);
|
||||
},
|
||||
|
||||
_compareItems: function(a, b) {
|
||||
return a.compare_by_name(b);
|
||||
},
|
||||
|
||||
addApp: function(app) {
|
||||
this._addItem(app);
|
||||
},
|
||||
|
||||
createFolderIcon: function(size) {
|
||||
let icon = new St.Widget({ layout_manager: new Clutter.BinLayout(),
|
||||
style_class: 'app-folder-icon',
|
||||
@ -967,7 +939,7 @@ const FolderView = new Lang.Class({
|
||||
|
||||
let aligns = [ Clutter.ActorAlign.START, Clutter.ActorAlign.END ];
|
||||
for (let i = 0; i < Math.min(this._allItems.length, 4); i++) {
|
||||
let texture = this._allItems[i].create_icon_texture(subSize);
|
||||
let texture = this._allItems[i].app.create_icon_texture(subSize);
|
||||
let bin = new St.Bin({ child: texture,
|
||||
x_expand: true, y_expand: true });
|
||||
bin.set_x_align(aligns[i % 2]);
|
||||
@ -1044,10 +1016,12 @@ const FolderView = new Lang.Class({
|
||||
const FolderIcon = new Lang.Class({
|
||||
Name: 'FolderIcon',
|
||||
|
||||
_init: function(dir, parentView) {
|
||||
this._dir = dir;
|
||||
_init: function(id, path, parentView) {
|
||||
this.id = id;
|
||||
this._parentView = parentView;
|
||||
|
||||
this._folder = new Gio.Settings({ schema_id: 'org.gnome.desktop.app-folders.folder',
|
||||
path: path });
|
||||
this.actor = new St.Button({ style_class: 'app-well-app app-folder',
|
||||
button_mask: St.ButtonMask.ONE,
|
||||
toggle_mode: true,
|
||||
@ -1058,15 +1032,11 @@ const FolderIcon = new Lang.Class({
|
||||
// whether we need to update arrow side, position etc.
|
||||
this._popupInvalidated = false;
|
||||
|
||||
let label = this._dir.get_name();
|
||||
this.icon = new IconGrid.BaseIcon(label,
|
||||
{ createIcon: Lang.bind(this, this._createIcon), setSizeManually: true });
|
||||
this.icon = new IconGrid.BaseIcon('', { createIcon: Lang.bind(this, this._createIcon), setSizeManually: true });
|
||||
this.actor.set_child(this.icon.actor);
|
||||
this.actor.label_actor = this.icon.label;
|
||||
|
||||
this.view = new FolderView();
|
||||
_loadCategory(dir, this.view);
|
||||
this.view.loadGrid();
|
||||
|
||||
this.actor.connect('clicked', Lang.bind(this,
|
||||
function() {
|
||||
@ -1079,6 +1049,63 @@ const FolderIcon = new Lang.Class({
|
||||
if (!this.actor.mapped && this._popup)
|
||||
this._popup.popdown();
|
||||
}));
|
||||
|
||||
this._folder.connect('changed', Lang.bind(this, this._redisplay));
|
||||
this._redisplay();
|
||||
},
|
||||
|
||||
getAppIds: function() {
|
||||
return this.view.getAllItems().map(function(item) {
|
||||
return item.id;
|
||||
});
|
||||
},
|
||||
|
||||
_updateName: function() {
|
||||
let name = _getFolderName(this._folder);
|
||||
if (this.name == name)
|
||||
return;
|
||||
|
||||
this.name = name;
|
||||
this.icon.label.text = this.name;
|
||||
this.emit('name-changed');
|
||||
},
|
||||
|
||||
_redisplay: function() {
|
||||
this._updateName();
|
||||
|
||||
this.view.removeAll();
|
||||
|
||||
let excludedApps = this._folder.get_strv('excluded-apps');
|
||||
let appSys = Shell.AppSystem.get_default();
|
||||
let addAppId = (function addAppId(appId) {
|
||||
if (excludedApps.indexOf(appId) >= 0)
|
||||
return;
|
||||
|
||||
let app = appSys.lookup_app(appId);
|
||||
if (!app)
|
||||
return;
|
||||
|
||||
if (!app.get_app_info().should_show())
|
||||
return;
|
||||
|
||||
let icon = new AppIcon(app);
|
||||
this.view.addItem(icon);
|
||||
}).bind(this);
|
||||
|
||||
let folderApps = this._folder.get_strv('apps');
|
||||
folderApps.forEach(addAppId);
|
||||
|
||||
let folderCategories = this._folder.get_strv('categories');
|
||||
Gio.AppInfo.get_all().forEach(function(appInfo) {
|
||||
let appCategories = _getCategories(appInfo);
|
||||
if (!_listsIntersect(folderCategories, appCategories))
|
||||
return;
|
||||
|
||||
addAppId(appInfo.get_id());
|
||||
});
|
||||
|
||||
this.view.loadGrid();
|
||||
this.emit('apps-changed');
|
||||
},
|
||||
|
||||
_createIcon: function(iconSize) {
|
||||
@ -1157,6 +1184,7 @@ const FolderIcon = new Lang.Class({
|
||||
this._popupInvalidated = true;
|
||||
},
|
||||
});
|
||||
Signals.addSignalMethods(FolderIcon.prototype);
|
||||
|
||||
const AppFolderPopup = new Lang.Class({
|
||||
Name: 'AppFolderPopup',
|
||||
@ -1210,13 +1238,13 @@ const AppFolderPopup = new Lang.Class({
|
||||
|
||||
_onKeyPress: function(actor, event) {
|
||||
if (!this._isOpen)
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
||||
if (event.get_key_symbol() != Clutter.KEY_Escape)
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
||||
this.popdown();
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
},
|
||||
|
||||
toggle: function() {
|
||||
@ -1275,6 +1303,9 @@ const AppIcon = new Lang.Class({
|
||||
|
||||
_init : function(app, iconParams) {
|
||||
this.app = app;
|
||||
this.id = app.get_id();
|
||||
this.name = app.get_name();
|
||||
|
||||
this.actor = new St.Button({ style_class: 'app-well-app',
|
||||
reactive: true,
|
||||
button_mask: St.ButtonMask.ONE | St.ButtonMask.TWO,
|
||||
@ -1357,13 +1388,13 @@ const AppIcon = new Lang.Class({
|
||||
Lang.bind(this, function() {
|
||||
this._menuTimeoutId = 0;
|
||||
this.popupMenu();
|
||||
return false;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
}));
|
||||
} else if (button == 3) {
|
||||
this.popupMenu();
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
}
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
},
|
||||
|
||||
_onClicked: function(actor, button) {
|
||||
@ -1375,7 +1406,6 @@ const AppIcon = new Lang.Class({
|
||||
// Last workspace is always empty
|
||||
let launchWorkspace = global.screen.get_workspace_by_index(global.screen.n_workspaces - 1);
|
||||
launchWorkspace.activate(global.get_current_time());
|
||||
this.emit('launching');
|
||||
this.app.open_new_window(-1);
|
||||
Main.overview.hide();
|
||||
}
|
||||
@ -1434,11 +1464,11 @@ const AppIcon = new Lang.Class({
|
||||
},
|
||||
|
||||
_onActivate: function (event) {
|
||||
this.emit('launching');
|
||||
let modifiers = event.get_state();
|
||||
|
||||
if (modifiers & Clutter.ModifierType.CONTROL_MASK
|
||||
&& this.app.state == Shell.AppState.RUNNING) {
|
||||
if ((modifiers & Clutter.ModifierType.CONTROL_MASK
|
||||
&& this.app.state == Shell.AppState.RUNNING)
|
||||
|| _isTerminal(this.app)) {
|
||||
this.app.open_new_window(-1);
|
||||
} else {
|
||||
this.app.activate();
|
||||
@ -1486,8 +1516,6 @@ const AppIconMenu = new Lang.Class({
|
||||
|
||||
this._source = source;
|
||||
|
||||
this.connect('activate', Lang.bind(this, this._onActivate));
|
||||
|
||||
this.actor.add_style_class_name('app-well-menu');
|
||||
|
||||
// Chain our visibility and lifecycle to that of the source
|
||||
@ -1497,13 +1525,15 @@ const AppIconMenu = new Lang.Class({
|
||||
}));
|
||||
source.actor.connect('destroy', Lang.bind(this, function () { this.actor.destroy(); }));
|
||||
|
||||
Main.uiGroup.add_actor(this.actor);
|
||||
Main.layoutManager.menuGroup.add_actor(this.actor);
|
||||
},
|
||||
|
||||
_redisplay: function() {
|
||||
this.removeAll();
|
||||
|
||||
let windows = this._source.app.get_windows();
|
||||
let windows = this._source.app.get_windows().filter(function(w) {
|
||||
return !w.skip_taskbar;
|
||||
});
|
||||
|
||||
// Display the app windows menu items and the separator between windows
|
||||
// of the current desktop and other windows.
|
||||
@ -1511,25 +1541,54 @@ const AppIconMenu = new Lang.Class({
|
||||
let separatorShown = windows.length > 0 && windows[0].get_workspace() != activeWorkspace;
|
||||
|
||||
for (let i = 0; i < windows.length; i++) {
|
||||
if (!separatorShown && windows[i].get_workspace() != activeWorkspace) {
|
||||
let window = windows[i];
|
||||
if (!separatorShown && window.get_workspace() != activeWorkspace) {
|
||||
this._appendSeparator();
|
||||
separatorShown = true;
|
||||
}
|
||||
let item = this._appendMenuItem(windows[i].title);
|
||||
item._window = windows[i];
|
||||
let item = this._appendMenuItem(window.title);
|
||||
item.connect('activate', Lang.bind(this, function() {
|
||||
this.emit('activate-window', window);
|
||||
}));
|
||||
}
|
||||
|
||||
if (!this._source.app.is_window_backed()) {
|
||||
if (windows.length > 0)
|
||||
this._appendSeparator();
|
||||
this._appendSeparator();
|
||||
|
||||
this._newWindowMenuItem = this._appendMenuItem(_("New Window"));
|
||||
this._newWindowMenuItem.connect('activate', Lang.bind(this, function() {
|
||||
this._source.app.open_new_window(-1);
|
||||
this.emit('activate-window', null);
|
||||
}));
|
||||
this._appendSeparator();
|
||||
|
||||
let appInfo = this._source.app.get_app_info();
|
||||
let actions = appInfo.list_actions();
|
||||
for (let i = 0; i < actions.length; i++) {
|
||||
let action = actions[i];
|
||||
let item = this._appendMenuItem(appInfo.get_action_name(action));
|
||||
item.connect('activate', Lang.bind(this, function(emitter, event) {
|
||||
this._source.app.launch_action(action, event.get_time(), -1);
|
||||
this.emit('activate-window', null);
|
||||
}));
|
||||
}
|
||||
this._appendSeparator();
|
||||
|
||||
let isFavorite = AppFavorites.getAppFavorites().isFavorite(this._source.app.get_id());
|
||||
|
||||
this._newWindowMenuItem = this._appendMenuItem(_("New Window"));
|
||||
this._appendSeparator();
|
||||
|
||||
this._toggleFavoriteMenuItem = this._appendMenuItem(isFavorite ? _("Remove from Favorites")
|
||||
: _("Add to Favorites"));
|
||||
if (isFavorite) {
|
||||
let item = this._appendMenuItem(_("Remove from Favorites"));
|
||||
item.connect('activate', Lang.bind(this, function() {
|
||||
let favs = AppFavorites.getAppFavorites();
|
||||
favs.removeFavorite(this._source.app.get_id());
|
||||
}));
|
||||
} else {
|
||||
let item = this._appendMenuItem(_("Add to Favorites"));
|
||||
item.connect('activate', Lang.bind(this, function() {
|
||||
let favs = AppFavorites.getAppFavorites();
|
||||
favs.addFavorite(this._source.app.get_id());
|
||||
}));
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@ -1548,24 +1607,6 @@ const AppIconMenu = new Lang.Class({
|
||||
popup: function(activatingButton) {
|
||||
this._redisplay();
|
||||
this.open();
|
||||
},
|
||||
|
||||
_onActivate: function (actor, child) {
|
||||
if (child._window) {
|
||||
let metaWindow = child._window;
|
||||
this.emit('activate-window', metaWindow);
|
||||
} else if (child == this._newWindowMenuItem) {
|
||||
this._source.app.open_new_window(-1);
|
||||
this.emit('activate-window', null);
|
||||
} else if (child == this._toggleFavoriteMenuItem) {
|
||||
let favs = AppFavorites.getAppFavorites();
|
||||
let isFavorite = favs.isFavorite(this._source.app.get_id());
|
||||
if (isFavorite)
|
||||
favs.removeFavorite(this._source.app.get_id());
|
||||
else
|
||||
favs.addFavorite(this._source.app.get_id());
|
||||
}
|
||||
this.close();
|
||||
}
|
||||
});
|
||||
Signals.addSignalMethods(AppIconMenu.prototype);
|
||||
|
@ -50,11 +50,9 @@ const BackgroundCache = new Lang.Class({
|
||||
effects: Meta.BackgroundEffects.NONE });
|
||||
|
||||
let content = null;
|
||||
|
||||
let candidateContent = null;
|
||||
for (let i = 0; i < this._patterns.length; i++) {
|
||||
if (!this._patterns[i])
|
||||
continue;
|
||||
|
||||
if (this._patterns[i].get_shading() != params.shadingType)
|
||||
continue;
|
||||
|
||||
@ -88,7 +86,6 @@ const BackgroundCache = new Lang.Class({
|
||||
}
|
||||
|
||||
this._patterns.push(content);
|
||||
|
||||
return content;
|
||||
},
|
||||
|
||||
@ -116,9 +113,9 @@ const BackgroundCache = new Lang.Class({
|
||||
|
||||
_removeContent: function(contentList, content) {
|
||||
let index = contentList.indexOf(content);
|
||||
|
||||
if (index >= 0)
|
||||
contentList.splice(index, 1);
|
||||
if (index < 0)
|
||||
throw new Error("Trying to remove invalid content: " + content);
|
||||
contentList.splice(index, 1);
|
||||
},
|
||||
|
||||
removePatternContent: function(content) {
|
||||
@ -128,12 +125,53 @@ const BackgroundCache = new Lang.Class({
|
||||
removeImageContent: function(content) {
|
||||
let filename = content.get_filename();
|
||||
|
||||
if (filename && this._fileMonitors[filename])
|
||||
let hasOtherUsers = this._images.some(function(content) { return filename == content.get_filename(); });
|
||||
if (!hasOtherUsers)
|
||||
delete this._fileMonitors[filename];
|
||||
|
||||
this._removeContent(this._images, content);
|
||||
},
|
||||
|
||||
_loadImageContentInternal: function(filename, style) {
|
||||
let cancellable = new Gio.Cancellable();
|
||||
let content = new Meta.Background({ meta_screen: global.screen });
|
||||
|
||||
let info = { filename: filename,
|
||||
style: style,
|
||||
cancellable: cancellable,
|
||||
callers: [] };
|
||||
|
||||
content.load_file_async(filename, style, cancellable, Lang.bind(this, function(object, result) {
|
||||
if (cancellable.is_cancelled())
|
||||
return;
|
||||
|
||||
try {
|
||||
content.load_file_finish(result);
|
||||
} catch(e) {
|
||||
content = null;
|
||||
}
|
||||
|
||||
if (content) {
|
||||
this._monitorFile(filename);
|
||||
info.callers.forEach(Lang.bind(this, function(caller) {
|
||||
let newContent = content.copy(caller.monitorIndex, caller.effects);
|
||||
this._images.push(newContent);
|
||||
caller.onFinished(newContent);
|
||||
}));
|
||||
} else {
|
||||
info.callers.forEach(Lang.bind(this, function(caller) {
|
||||
caller.onFinished(null);
|
||||
}));
|
||||
}
|
||||
|
||||
let idx = this._pendingFileLoads.indexOf(info);
|
||||
this._pendingFileLoads.splice(idx, 1);
|
||||
}));
|
||||
|
||||
this._pendingFileLoads.push(info);
|
||||
return info;
|
||||
},
|
||||
|
||||
_loadImageContent: function(params) {
|
||||
params = Params.parse(params, { monitorIndex: 0,
|
||||
style: null,
|
||||
@ -142,63 +180,38 @@ const BackgroundCache = new Lang.Class({
|
||||
cancellable: null,
|
||||
onFinished: null });
|
||||
|
||||
let caller = { monitorIndex: params.monitorIndex,
|
||||
effects: params.effects,
|
||||
cancellable: params.cancellable,
|
||||
onFinished: params.onFinished };
|
||||
|
||||
let info = null;
|
||||
for (let i = 0; i < this._pendingFileLoads.length; i++) {
|
||||
if (this._pendingFileLoads[i].filename == params.filename &&
|
||||
this._pendingFileLoads[i].style == params.style) {
|
||||
this._pendingFileLoads[i].callers.push({ shouldCopy: true,
|
||||
monitorIndex: params.monitorIndex,
|
||||
effects: params.effects,
|
||||
onFinished: params.onFinished });
|
||||
return;
|
||||
let pendingLoad = this._pendingFileLoads[i];
|
||||
if (pendingLoad.filename == params.filename && pendingLoad.style == params.style) {
|
||||
info = pendingLoad;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this._pendingFileLoads.push({ filename: params.filename,
|
||||
style: params.style,
|
||||
callers: [{ shouldCopy: false,
|
||||
monitorIndex: params.monitorIndex,
|
||||
effects: params.effects,
|
||||
onFinished: params.onFinished }] });
|
||||
if (!info)
|
||||
info = this._loadImageContentInternal(params.filename, params.style);
|
||||
|
||||
let content = new Meta.Background({ meta_screen: global.screen,
|
||||
monitor: params.monitorIndex,
|
||||
effects: params.effects });
|
||||
info.callers.push(caller);
|
||||
|
||||
content.load_file_async(params.filename,
|
||||
params.style,
|
||||
params.cancellable,
|
||||
Lang.bind(this,
|
||||
function(object, result) {
|
||||
try {
|
||||
content.load_file_finish(result);
|
||||
if (caller.cancellable) {
|
||||
caller.cancellable.connect(Lang.bind(this, function() {
|
||||
let idx = info.callers.indexOf(caller);
|
||||
info.callers.splice(idx, 1);
|
||||
|
||||
this._monitorFile(params.filename);
|
||||
this._images.push(content);
|
||||
} catch(e) {
|
||||
content = null;
|
||||
}
|
||||
if (info.callers.length == 0) {
|
||||
info.cancellable.cancel();
|
||||
|
||||
for (let i = 0; i < this._pendingFileLoads.length; i++) {
|
||||
let pendingLoad = this._pendingFileLoads[i];
|
||||
if (pendingLoad.filename != params.filename ||
|
||||
pendingLoad.style != params.style)
|
||||
continue;
|
||||
|
||||
for (let j = 0; j < pendingLoad.callers.length; j++) {
|
||||
if (pendingLoad.callers[j].onFinished) {
|
||||
if (content && pendingLoad.callers[j].shouldCopy) {
|
||||
content = object.copy(pendingLoad.callers[j].monitorIndex,
|
||||
pendingLoad.callers[j].effects);
|
||||
|
||||
}
|
||||
|
||||
pendingLoad.callers[j].onFinished(content);
|
||||
}
|
||||
}
|
||||
|
||||
this._pendingFileLoads.splice(i, 1);
|
||||
}
|
||||
}));
|
||||
let idx = this._pendingFileLoads.indexOf(info);
|
||||
this._pendingFileLoads.splice(idx, 1);
|
||||
}
|
||||
}));
|
||||
}
|
||||
},
|
||||
|
||||
getImageContent: function(params) {
|
||||
@ -210,11 +223,9 @@ const BackgroundCache = new Lang.Class({
|
||||
onFinished: null });
|
||||
|
||||
let content = null;
|
||||
|
||||
let candidateContent = null;
|
||||
for (let i = 0; i < this._images.length; i++) {
|
||||
if (!this._images[i])
|
||||
continue;
|
||||
|
||||
if (this._images[i].get_style() != params.style)
|
||||
continue;
|
||||
|
||||
@ -222,7 +233,7 @@ const BackgroundCache = new Lang.Class({
|
||||
continue;
|
||||
|
||||
if (params.style == GDesktopEnums.BackgroundStyle.SPANNED &&
|
||||
this._images[i].monitor_index != this._monitorIndex)
|
||||
this._images[i].monitor != params.monitorIndex)
|
||||
continue;
|
||||
|
||||
candidateContent = this._images[i];
|
||||
@ -250,7 +261,6 @@ const BackgroundCache = new Lang.Class({
|
||||
monitorIndex: params.monitorIndex,
|
||||
cancellable: params.cancellable,
|
||||
onFinished: params.onFinished });
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
@ -262,6 +272,7 @@ const BackgroundCache = new Lang.Class({
|
||||
if (params.onLoaded) {
|
||||
GLib.idle_add(GLib.PRIORITY_DEFAULT, Lang.bind(this, function() {
|
||||
params.onLoaded(this._animation);
|
||||
return GLib.SOURCE_REMOVE;
|
||||
}));
|
||||
}
|
||||
}
|
||||
@ -276,6 +287,7 @@ const BackgroundCache = new Lang.Class({
|
||||
if (params.onLoaded) {
|
||||
GLib.idle_add(GLib.PRIORITY_DEFAULT, Lang.bind(this, function() {
|
||||
params.onLoaded(this._animation);
|
||||
return GLib.SOURCE_REMOVE;
|
||||
}));
|
||||
}
|
||||
}));
|
||||
@ -375,7 +387,7 @@ const Background = new Lang.Class({
|
||||
|
||||
GLib.idle_add(GLib.PRIORITY_DEFAULT, Lang.bind(this, function() {
|
||||
this.emit('loaded');
|
||||
return false;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
}));
|
||||
},
|
||||
|
||||
@ -414,27 +426,26 @@ const Background = new Lang.Class({
|
||||
this._fileWatches[filename] = signalId;
|
||||
},
|
||||
|
||||
_addImage: function(content, index, filename) {
|
||||
content.brightness = this._brightness;
|
||||
content.vignette_sharpness = this._vignetteSharpness;
|
||||
_ensureImage: function(index) {
|
||||
if (this._images[index])
|
||||
return;
|
||||
|
||||
let actor = new Meta.BackgroundActor();
|
||||
actor.content = content;
|
||||
|
||||
// The background pattern is the first actor in
|
||||
// the group, and all images should be above that.
|
||||
this.actor.insert_child_at_index(actor, index + 1);
|
||||
|
||||
this._images[index] = actor;
|
||||
this._watchCacheFile(filename);
|
||||
},
|
||||
|
||||
_updateImage: function(content, index, filename) {
|
||||
_updateImage: function(index, content, filename) {
|
||||
content.brightness = this._brightness;
|
||||
content.vignette_sharpness = this._vignetteSharpness;
|
||||
|
||||
this._cache.removeImageContent(this._images[index].content);
|
||||
this._images[index].content = content;
|
||||
let image = this._images[index];
|
||||
if (image.content)
|
||||
this._cache.removeImageContent(content);
|
||||
image.content = content;
|
||||
this._watchCacheFile(filename);
|
||||
},
|
||||
|
||||
@ -482,11 +493,8 @@ const Background = new Lang.Class({
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this._images[i]) {
|
||||
this._addImage(content, i, files[i]);
|
||||
} else {
|
||||
this._updateImage(content, i, files[i]);
|
||||
}
|
||||
this._ensureImage(i);
|
||||
this._updateImage(i, content, files[i]);
|
||||
|
||||
if (numPendingImages == 0) {
|
||||
this._setLoaded();
|
||||
@ -521,7 +529,7 @@ const Background = new Lang.Class({
|
||||
Lang.bind(this, function() {
|
||||
this._updateAnimationTimeoutId = 0;
|
||||
this._updateAnimation();
|
||||
return false;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
}));
|
||||
},
|
||||
|
||||
@ -541,30 +549,33 @@ const Background = new Lang.Class({
|
||||
});
|
||||
},
|
||||
|
||||
_loadFile: function(filename) {
|
||||
_loadImage: function(filename) {
|
||||
this._cache.getImageContent({ monitorIndex: this._monitorIndex,
|
||||
effects: this._effects,
|
||||
style: this._style,
|
||||
filename: filename,
|
||||
cancellable: this._cancellable,
|
||||
onFinished: Lang.bind(this, function(content) {
|
||||
if (!content) {
|
||||
if (!this._cancellable.is_cancelled())
|
||||
this._loadAnimation(filename);
|
||||
return;
|
||||
if (content) {
|
||||
this._ensureImage(0);
|
||||
this._updateImage(0, content, filename);
|
||||
}
|
||||
|
||||
this._addImage(content, 0, filename);
|
||||
this._setLoaded();
|
||||
})
|
||||
});
|
||||
},
|
||||
|
||||
_loadFile: function(filename) {
|
||||
if (filename.endsWith('.xml'))
|
||||
this._loadAnimation(filename);
|
||||
else
|
||||
this._loadImage(filename);
|
||||
},
|
||||
|
||||
_load: function () {
|
||||
this._cache = getBackgroundCache();
|
||||
|
||||
this._loadPattern(this._cache);
|
||||
this._loadPattern();
|
||||
|
||||
this._style = this._settings.get_enum(BACKGROUND_STYLE_KEY);
|
||||
if (this._style == GDesktopEnums.BackgroundStyle.NONE) {
|
||||
@ -623,25 +634,6 @@ const Background = new Lang.Class({
|
||||
});
|
||||
Signals.addSignalMethods(Background.prototype);
|
||||
|
||||
const SystemBackground = new Lang.Class({
|
||||
Name: 'SystemBackground',
|
||||
|
||||
_init: function() {
|
||||
this._cache = getBackgroundCache();
|
||||
this.actor = new Meta.BackgroundActor();
|
||||
|
||||
this._cache.getImageContent({ style: GDesktopEnums.BackgroundStyle.WALLPAPER,
|
||||
filename: global.datadir + '/theme/noise-texture.png',
|
||||
effects: Meta.BackgroundEffects.NONE,
|
||||
onFinished: Lang.bind(this, function(content) {
|
||||
this.actor.content = content;
|
||||
this.emit('loaded');
|
||||
})
|
||||
});
|
||||
}
|
||||
});
|
||||
Signals.addSignalMethods(SystemBackground.prototype);
|
||||
|
||||
const Animation = new Lang.Class({
|
||||
Name: 'Animation',
|
||||
|
||||
@ -726,29 +718,30 @@ const BackgroundManager = new Lang.Class({
|
||||
}
|
||||
},
|
||||
|
||||
_updateBackground: function(background, monitorIndex) {
|
||||
let newBackground = this._createBackground(monitorIndex);
|
||||
newBackground.vignetteSharpness = background.vignetteSharpness;
|
||||
newBackground.brightness = background.brightness;
|
||||
newBackground.visible = background.visible;
|
||||
_updateBackground: function() {
|
||||
let newBackground = this._createBackground();
|
||||
newBackground.vignetteSharpness = this.background.vignetteSharpness;
|
||||
newBackground.brightness = this.background.brightness;
|
||||
newBackground.visible = this.background.visible;
|
||||
|
||||
newBackground.loadedSignalId = newBackground.connect('loaded',
|
||||
Lang.bind(this, function() {
|
||||
newBackground.disconnect(newBackground.loadedSignalId);
|
||||
newBackground.loadedSignalId = 0;
|
||||
Tweener.addTween(background.actor,
|
||||
Tweener.addTween(this.background.actor,
|
||||
{ opacity: 0,
|
||||
time: FADE_ANIMATION_TIME,
|
||||
transition: 'easeOutQuad',
|
||||
onComplete: Lang.bind(this, function() {
|
||||
if (this._newBackground == newBackground) {
|
||||
this.background = newBackground;
|
||||
this._newBackground = null;
|
||||
} else {
|
||||
if (this._newBackground != newBackground) {
|
||||
/* Not interesting, we queued another load */
|
||||
newBackground.actor.destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
background.actor.destroy();
|
||||
this.background.actor.destroy();
|
||||
this.background = newBackground;
|
||||
this._newBackground = null;
|
||||
|
||||
this.emit('changed');
|
||||
})
|
||||
@ -776,7 +769,7 @@ const BackgroundManager = new Lang.Class({
|
||||
background.changeSignalId = background.connect('changed', Lang.bind(this, function() {
|
||||
background.disconnect(background.changeSignalId);
|
||||
background.changeSignalId = 0;
|
||||
this._updateBackground(background, this._monitorIndex);
|
||||
this._updateBackground();
|
||||
}));
|
||||
|
||||
background.actor.connect('destroy', Lang.bind(this, function() {
|
||||
|
@ -13,8 +13,8 @@ const BackgroundMenu = new Lang.Class({
|
||||
Name: 'BackgroundMenu',
|
||||
Extends: PopupMenu.PopupMenu,
|
||||
|
||||
_init: function(source) {
|
||||
this.parent(source, 0, St.Side.TOP);
|
||||
_init: function(layoutManager) {
|
||||
this.parent(layoutManager.dummyCursor, 0, St.Side.TOP);
|
||||
|
||||
this.addSettingsAction(_("Settings"), 'gnome-control-center.desktop');
|
||||
this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
||||
@ -22,23 +22,20 @@ const BackgroundMenu = new Lang.Class({
|
||||
|
||||
this.actor.add_style_class_name('background-menu');
|
||||
|
||||
Main.uiGroup.add_actor(this.actor);
|
||||
layoutManager.menuGroup.add_actor(this.actor);
|
||||
this.actor.hide();
|
||||
}
|
||||
});
|
||||
|
||||
function addBackgroundMenu(actor) {
|
||||
let cursor = new St.Bin({ opacity: 0 });
|
||||
Main.uiGroup.add_actor(cursor);
|
||||
|
||||
function addBackgroundMenu(actor, layoutManager) {
|
||||
actor.reactive = true;
|
||||
actor._backgroundMenu = new BackgroundMenu(cursor);
|
||||
actor._backgroundMenu = new BackgroundMenu(layoutManager);
|
||||
actor._backgroundManager = new PopupMenu.PopupMenuManager({ actor: actor });
|
||||
actor._backgroundManager.addMenu(actor._backgroundMenu);
|
||||
|
||||
function openMenu() {
|
||||
let [x, y] = global.get_pointer();
|
||||
cursor.set_position(x, y);
|
||||
Main.layoutManager.setDummyCursorPosition(x, y);
|
||||
actor._backgroundMenu.open(BoxPointer.PopupAnimation.NONE);
|
||||
}
|
||||
|
||||
@ -59,10 +56,8 @@ function addBackgroundMenu(actor) {
|
||||
actor.add_action(clickAction);
|
||||
|
||||
actor.connect('destroy', function() {
|
||||
actor._backgroundMenu.destroy();
|
||||
actor._backgroundMenu = null;
|
||||
actor._backgroundManager = null;
|
||||
|
||||
cursor.destroy();
|
||||
});
|
||||
actor._backgroundMenu.destroy();
|
||||
actor._backgroundMenu = null;
|
||||
actor._backgroundManager = null;
|
||||
});
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ const BoxPointer = new Lang.Class({
|
||||
_muteInput: function() {
|
||||
if (this._capturedEventId == 0)
|
||||
this._capturedEventId = this.actor.connect('captured-event',
|
||||
function() { return true; });
|
||||
function() { return Clutter.EVENT_STOP; });
|
||||
},
|
||||
|
||||
_unmuteInput: function() {
|
||||
@ -121,6 +121,9 @@ const BoxPointer = new Lang.Class({
|
||||
},
|
||||
|
||||
hide: function(animate, onComplete) {
|
||||
if (!this.actor.visible)
|
||||
return;
|
||||
|
||||
let xOffset = 0;
|
||||
let yOffset = 0;
|
||||
let themeNode = this.actor.get_theme_node();
|
||||
@ -284,38 +287,40 @@ const BoxPointer = new Lang.Class({
|
||||
let skipBottomLeft = false;
|
||||
let skipBottomRight = false;
|
||||
|
||||
switch (this._arrowSide) {
|
||||
case St.Side.TOP:
|
||||
if (this._arrowOrigin == x1)
|
||||
skipTopLeft = true;
|
||||
else if (this._arrowOrigin == x2)
|
||||
skipTopRight = true;
|
||||
break;
|
||||
if (rise) {
|
||||
switch (this._arrowSide) {
|
||||
case St.Side.TOP:
|
||||
if (this._arrowOrigin == x1)
|
||||
skipTopLeft = true;
|
||||
else if (this._arrowOrigin == x2)
|
||||
skipTopRight = true;
|
||||
break;
|
||||
|
||||
case St.Side.RIGHT:
|
||||
if (this._arrowOrigin == y1)
|
||||
skipTopRight = true;
|
||||
else if (this._arrowOrigin == y2)
|
||||
skipBottomRight = true;
|
||||
break;
|
||||
case St.Side.RIGHT:
|
||||
if (this._arrowOrigin == y1)
|
||||
skipTopRight = true;
|
||||
else if (this._arrowOrigin == y2)
|
||||
skipBottomRight = true;
|
||||
break;
|
||||
|
||||
case St.Side.BOTTOM:
|
||||
if (this._arrowOrigin == x1)
|
||||
skipBottomLeft = true;
|
||||
else if (this._arrowOrigin == x2)
|
||||
skipBottomRight = true;
|
||||
break;
|
||||
case St.Side.BOTTOM:
|
||||
if (this._arrowOrigin == x1)
|
||||
skipBottomLeft = true;
|
||||
else if (this._arrowOrigin == x2)
|
||||
skipBottomRight = true;
|
||||
break;
|
||||
|
||||
case St.Side.LEFT:
|
||||
if (this._arrowOrigin == y1)
|
||||
skipTopLeft = true;
|
||||
else if (this._arrowOrigin == y2)
|
||||
skipBottomLeft = true;
|
||||
break;
|
||||
case St.Side.LEFT:
|
||||
if (this._arrowOrigin == y1)
|
||||
skipTopLeft = true;
|
||||
else if (this._arrowOrigin == y2)
|
||||
skipBottomLeft = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cr.moveTo(x1 + borderRadius, y1);
|
||||
if (this._arrowSide == St.Side.TOP) {
|
||||
if (this._arrowSide == St.Side.TOP && rise) {
|
||||
if (skipTopLeft) {
|
||||
cr.moveTo(x1, y2 - borderRadius);
|
||||
cr.lineTo(x1, y1 - rise);
|
||||
@ -337,7 +342,7 @@ const BoxPointer = new Lang.Class({
|
||||
3*Math.PI/2, Math.PI*2);
|
||||
}
|
||||
|
||||
if (this._arrowSide == St.Side.RIGHT) {
|
||||
if (this._arrowSide == St.Side.RIGHT && rise) {
|
||||
if (skipTopRight) {
|
||||
cr.lineTo(x2 + rise, y1);
|
||||
cr.lineTo(x2 + rise, y1 + halfBase);
|
||||
@ -358,7 +363,7 @@ const BoxPointer = new Lang.Class({
|
||||
0, Math.PI/2);
|
||||
}
|
||||
|
||||
if (this._arrowSide == St.Side.BOTTOM) {
|
||||
if (this._arrowSide == St.Side.BOTTOM && rise) {
|
||||
if (skipBottomLeft) {
|
||||
cr.lineTo(x1 + halfBase, y2);
|
||||
cr.lineTo(x1, y2 + rise);
|
||||
@ -379,7 +384,7 @@ const BoxPointer = new Lang.Class({
|
||||
Math.PI/2, Math.PI);
|
||||
}
|
||||
|
||||
if (this._arrowSide == St.Side.LEFT) {
|
||||
if (this._arrowSide == St.Side.LEFT && rise) {
|
||||
if (skipTopLeft) {
|
||||
cr.lineTo(x1, y1 + halfBase);
|
||||
cr.lineTo(x1 - rise, y1);
|
||||
|
@ -17,16 +17,18 @@ const SHOW_WEEKDATE_KEY = 'show-weekdate';
|
||||
// in org.gnome.desktop.interface
|
||||
const CLOCK_FORMAT_KEY = 'clock-format';
|
||||
|
||||
function _sameDay(dateA, dateB) {
|
||||
return (dateA.getDate() == dateB.getDate() &&
|
||||
dateA.getMonth() == dateB.getMonth() &&
|
||||
dateA.getYear() == dateB.getYear());
|
||||
}
|
||||
|
||||
function _sameYear(dateA, dateB) {
|
||||
return (dateA.getYear() == dateB.getYear());
|
||||
}
|
||||
|
||||
function _sameMonth(dateA, dateB) {
|
||||
return _sameYear(dateA, dateB) && (dateA.getMonth() == dateB.getMonth());
|
||||
}
|
||||
|
||||
function _sameDay(dateA, dateB) {
|
||||
return _sameMonth(dateA, dateB) && (dateA.getDate() == dateB.getDate());
|
||||
}
|
||||
|
||||
/* TODO: maybe needs config - right now we assume that Saturday and
|
||||
* Sunday are non-work days (not true in e.g. Israel, it's Sunday and
|
||||
* Monday there)
|
||||
@ -329,25 +331,22 @@ const DBusEventSource = new Lang.Class({
|
||||
return;
|
||||
|
||||
if (this._curRequestBegin && this._curRequestEnd){
|
||||
let callFlags = Gio.DBusCallFlags.NO_AUTO_START;
|
||||
if (forceReload)
|
||||
callFlags = Gio.DBusCallFlags.NONE;
|
||||
this._dbusProxy.GetEventsRemote(this._curRequestBegin.getTime() / 1000,
|
||||
this._curRequestEnd.getTime() / 1000,
|
||||
forceReload,
|
||||
Lang.bind(this, this._onEventsReceived),
|
||||
callFlags);
|
||||
Gio.DBusCallFlags.NONE);
|
||||
}
|
||||
},
|
||||
|
||||
requestRange: function(begin, end, forceReload) {
|
||||
if (forceReload || !(_datesEqual(begin, this._lastRequestBegin) && _datesEqual(end, this._lastRequestEnd))) {
|
||||
requestRange: function(begin, end) {
|
||||
if (!(_datesEqual(begin, this._lastRequestBegin) && _datesEqual(end, this._lastRequestEnd))) {
|
||||
this.isLoading = true;
|
||||
this._lastRequestBegin = begin;
|
||||
this._lastRequestEnd = end;
|
||||
this._curRequestBegin = begin;
|
||||
this._curRequestEnd = end;
|
||||
this._loadEvents(forceReload);
|
||||
this._loadEvents(false);
|
||||
}
|
||||
},
|
||||
|
||||
@ -419,21 +418,19 @@ const Calendar = new Lang.Class({
|
||||
setEventSource: function(eventSource) {
|
||||
this._eventSource = eventSource;
|
||||
this._eventSource.connect('changed', Lang.bind(this, function() {
|
||||
this._update(false);
|
||||
this._update();
|
||||
}));
|
||||
this._update(true);
|
||||
this._update();
|
||||
},
|
||||
|
||||
// Sets the calendar to show a specific date
|
||||
setDate: function(date, forceReload) {
|
||||
if (!_sameDay(date, this._selectedDate)) {
|
||||
this._selectedDate = date;
|
||||
this._update(forceReload);
|
||||
this.emit('selected-date-changed', new Date(this._selectedDate));
|
||||
} else {
|
||||
if (forceReload)
|
||||
this._update(forceReload);
|
||||
}
|
||||
setDate: function(date) {
|
||||
if (_sameDay(date, this._selectedDate))
|
||||
return;
|
||||
|
||||
this._selectedDate = date;
|
||||
this._update();
|
||||
this.emit('selected-date-changed', new Date(this._selectedDate));
|
||||
},
|
||||
|
||||
_buildHeader: function() {
|
||||
@ -497,6 +494,7 @@ const Calendar = new Lang.Class({
|
||||
this._onNextMonthButtonClicked();
|
||||
break;
|
||||
}
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
},
|
||||
|
||||
_onPrevMonthButtonClicked: function() {
|
||||
@ -520,7 +518,7 @@ const Calendar = new Lang.Class({
|
||||
|
||||
this._backButton.grab_key_focus();
|
||||
|
||||
this.setDate(newDate, false);
|
||||
this.setDate(newDate);
|
||||
},
|
||||
|
||||
_onNextMonthButtonClicked: function() {
|
||||
@ -544,28 +542,25 @@ const Calendar = new Lang.Class({
|
||||
|
||||
this._forwardButton.grab_key_focus();
|
||||
|
||||
this.setDate(newDate, false);
|
||||
this.setDate(newDate);
|
||||
},
|
||||
|
||||
_onSettingsChange: function() {
|
||||
this._useWeekdate = this._settings.get_boolean(SHOW_WEEKDATE_KEY);
|
||||
this._buildHeader();
|
||||
this._update(false);
|
||||
this._update();
|
||||
},
|
||||
|
||||
_update: function(forceReload) {
|
||||
_rebuildCalendar: function() {
|
||||
let now = new Date();
|
||||
|
||||
if (_sameYear(this._selectedDate, now))
|
||||
this._monthLabel.text = this._selectedDate.toLocaleFormat(this._headerFormatWithoutYear);
|
||||
else
|
||||
this._monthLabel.text = this._selectedDate.toLocaleFormat(this._headerFormat);
|
||||
|
||||
// Remove everything but the topBox and the weekday labels
|
||||
let children = this.actor.get_children();
|
||||
for (let i = this._firstDayIndex; i < children.length; i++)
|
||||
children[i].destroy();
|
||||
|
||||
this._buttons = [];
|
||||
|
||||
// Start at the beginning of the week before the start of the month
|
||||
//
|
||||
// We want to show always 6 weeks (to keep the calendar menu at the same
|
||||
@ -583,11 +578,13 @@ const Calendar = new Lang.Class({
|
||||
// Actually computing the number of weeks is complex, but we know that the
|
||||
// problematic categories (2 and 4) always start on week start, and that
|
||||
// all months at the end have 6 weeks.
|
||||
|
||||
let beginDate = new Date(this._selectedDate);
|
||||
beginDate.setDate(1);
|
||||
beginDate.setSeconds(0);
|
||||
beginDate.setHours(12);
|
||||
|
||||
this._calendarBegin = new Date(beginDate);
|
||||
|
||||
let year = beginDate.getYear();
|
||||
|
||||
let daysToWeekStart = (7 + beginDate.getDay() - this._weekStart) % 7;
|
||||
@ -608,23 +605,18 @@ const Calendar = new Lang.Class({
|
||||
if (this._eventSource.isDummy)
|
||||
button.reactive = false;
|
||||
|
||||
let iterStr = iter.toUTCString();
|
||||
button._date = new Date(iter);
|
||||
button.connect('clicked', Lang.bind(this, function() {
|
||||
this._shouldDateGrabFocus = true;
|
||||
|
||||
let newlySelectedDate = new Date(iterStr);
|
||||
this.setDate(newlySelectedDate, false);
|
||||
|
||||
this._shouldDateGrabFocus = false;
|
||||
this.setDate(button._date);
|
||||
}));
|
||||
|
||||
let hasEvents = this._eventSource.hasEvents(iter);
|
||||
let styleClass = 'calendar-day-base calendar-day';
|
||||
|
||||
if (_isWorkDay(iter))
|
||||
styleClass += ' calendar-work-day'
|
||||
styleClass += ' calendar-work-day';
|
||||
else
|
||||
styleClass += ' calendar-nonwork-day'
|
||||
styleClass += ' calendar-nonwork-day';
|
||||
|
||||
// Hack used in lieu of border-collapse - see gnome-shell.css
|
||||
if (row == 2)
|
||||
@ -641,7 +633,7 @@ const Calendar = new Lang.Class({
|
||||
styleClass += ' calendar-other-month-day';
|
||||
|
||||
if (hasEvents)
|
||||
styleClass += ' calendar-day-with-events'
|
||||
styleClass += ' calendar-day-with-events';
|
||||
|
||||
button.style_class = styleClass;
|
||||
|
||||
@ -649,12 +641,7 @@ const Calendar = new Lang.Class({
|
||||
this.actor.add(button,
|
||||
{ row: row, col: offsetCols + (7 + iter.getDay() - this._weekStart) % 7 });
|
||||
|
||||
if (_sameDay(this._selectedDate, iter)) {
|
||||
button.add_style_pseudo_class('active');
|
||||
|
||||
if (this._shouldDateGrabFocus)
|
||||
button.grab_key_focus();
|
||||
}
|
||||
this._buttons.push(button);
|
||||
|
||||
if (this._useWeekdate && iter.getDay() == 4) {
|
||||
let label = new St.Label({ text: _getCalendarWeekForDate(iter).toString(),
|
||||
@ -668,9 +655,29 @@ const Calendar = new Lang.Class({
|
||||
if (iter.getDay() == this._weekStart)
|
||||
row++;
|
||||
}
|
||||
|
||||
// Signal to the event source that we are interested in events
|
||||
// only from this date range
|
||||
this._eventSource.requestRange(beginDate, iter, forceReload);
|
||||
this._eventSource.requestRange(beginDate, iter);
|
||||
},
|
||||
|
||||
_update: function() {
|
||||
let now = new Date();
|
||||
|
||||
if (_sameYear(this._selectedDate, now))
|
||||
this._monthLabel.text = this._selectedDate.toLocaleFormat(this._headerFormatWithoutYear);
|
||||
else
|
||||
this._monthLabel.text = this._selectedDate.toLocaleFormat(this._headerFormat);
|
||||
|
||||
if (!this._calendarBegin || !_sameMonth(this._selectedDate, this._calendarBegin))
|
||||
this._rebuildCalendar();
|
||||
|
||||
this._buttons.forEach(Lang.bind(this, function(button) {
|
||||
if (_sameDay(button._date, this._selectedDate))
|
||||
button.add_style_pseudo_class('active');
|
||||
else
|
||||
button.remove_style_pseudo_class('active');
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -77,7 +77,7 @@ const AutomountManager = new Lang.Class({
|
||||
}));
|
||||
|
||||
this._mountAllId = 0;
|
||||
return false;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
},
|
||||
|
||||
_onDriveConnected: function() {
|
||||
@ -236,7 +236,7 @@ const AutomountManager = new Lang.Class({
|
||||
_allowAutorunExpire: function(volume) {
|
||||
Mainloop.timeout_add_seconds(AUTORUN_EXPIRE_TIMEOUT_SECS, function() {
|
||||
volume.allowAutorun = false;
|
||||
return false;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -64,7 +64,7 @@ function startAppForMount(app, mount) {
|
||||
|
||||
try {
|
||||
retval = app.launch(files,
|
||||
global.create_app_launch_context())
|
||||
global.create_app_launch_context(0, -1))
|
||||
} catch (e) {
|
||||
log('Unable to launch the application ' + app.get_name()
|
||||
+ ': ' + e.toString());
|
||||
|
@ -45,7 +45,9 @@ const KeyringDialog = new Lang.Class({
|
||||
this.prompt.bind_property('message', subject, 'text', GObject.BindingFlags.SYNC_CREATE);
|
||||
|
||||
this._messageBox.add(subject,
|
||||
{ y_fill: false,
|
||||
{ x_fill: false,
|
||||
y_fill: false,
|
||||
x_align: St.Align.START,
|
||||
y_align: St.Align.START });
|
||||
|
||||
let description = new St.Label({ style_class: 'prompt-dialog-description' });
|
||||
@ -136,6 +138,7 @@ const KeyringDialog = new Lang.Class({
|
||||
warning.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
|
||||
warning.clutter_text.line_wrap = true;
|
||||
layout.pack(warning, 1, row);
|
||||
layout.child_set(warning, { x_fill: false, x_align: Clutter.TableAlignment.START });
|
||||
this.prompt.bind_property('warning-visible', warning, 'visible', GObject.BindingFlags.SYNC_CREATE);
|
||||
this.prompt.bind_property('warning', warning, 'text', GObject.BindingFlags.SYNC_CREATE);
|
||||
|
||||
|
@ -255,6 +255,7 @@ const NetworkSecretDialog = new Lang.Class({
|
||||
case 'leap':
|
||||
case 'ttls':
|
||||
case 'peap':
|
||||
case 'fast':
|
||||
// TTLS and PEAP are actually much more complicated, but this complication
|
||||
// is not visible here since we only care about phase2 authentication
|
||||
// (and don't even care of which one)
|
||||
@ -308,7 +309,7 @@ const NetworkSecretDialog = new Lang.Class({
|
||||
wirelessSetting = this._connection.get_setting_wireless();
|
||||
ssid = NetworkManager.utils_ssid_to_utf8(wirelessSetting.get_ssid());
|
||||
content.title = _("Authentication required by wireless network");
|
||||
content.message = _("Passwords or encryption keys are required to access the wireless network '%s'.").format(ssid);
|
||||
content.message = _("Passwords or encryption keys are required to access the wireless network “%s”.").format(ssid);
|
||||
this._getWirelessSecrets(content.secrets, wirelessSetting);
|
||||
break;
|
||||
case '802-3-ethernet':
|
||||
@ -335,7 +336,7 @@ const NetworkSecretDialog = new Lang.Class({
|
||||
case 'cdma':
|
||||
case 'bluetooth':
|
||||
content.title = _("Mobile broadband network password");
|
||||
content.message = _("A password is required to connect to '%s'.").format(connectionSetting.get_id());
|
||||
content.message = _("A password is required to connect to “%s”.").format(connectionSetting.get_id());
|
||||
this._getMobileSecrets(content.secrets, connectionType);
|
||||
break;
|
||||
default:
|
||||
|
@ -54,7 +54,9 @@ const AuthenticationDialog = new Lang.Class({
|
||||
text: _("Authentication Required") });
|
||||
|
||||
messageBox.add(this._subjectLabel,
|
||||
{ y_fill: false,
|
||||
{ x_fill: false,
|
||||
y_fill: false,
|
||||
x_align: St.Align.START,
|
||||
y_align: St.Align.START });
|
||||
|
||||
this._descriptionLabel = new St.Label({ style_class: 'prompt-dialog-description',
|
||||
@ -63,7 +65,9 @@ const AuthenticationDialog = new Lang.Class({
|
||||
this._descriptionLabel.clutter_text.line_wrap = true;
|
||||
|
||||
messageBox.add(this._descriptionLabel,
|
||||
{ y_fill: true,
|
||||
{ x_fill: false,
|
||||
y_fill: true,
|
||||
x_align: St.Align.START,
|
||||
y_align: St.Align.START });
|
||||
|
||||
if (userNames.length > 1) {
|
||||
@ -95,7 +99,8 @@ const AuthenticationDialog = new Lang.Class({
|
||||
if (userIsRoot) {
|
||||
let userLabel = new St.Label(({ style_class: 'polkit-dialog-user-root-label',
|
||||
text: userRealName }));
|
||||
messageBox.add(userLabel);
|
||||
messageBox.add(userLabel, { x_fill: false,
|
||||
x_align: St.Align.START });
|
||||
} else {
|
||||
let userBox = new St.BoxLayout({ style_class: 'polkit-dialog-user-layout',
|
||||
vertical: false });
|
||||
@ -137,7 +142,7 @@ const AuthenticationDialog = new Lang.Class({
|
||||
this._errorMessageLabel = new St.Label({ style_class: 'prompt-dialog-error-label' });
|
||||
this._errorMessageLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
|
||||
this._errorMessageLabel.clutter_text.line_wrap = true;
|
||||
messageBox.add(this._errorMessageLabel);
|
||||
messageBox.add(this._errorMessageLabel, { x_fill: false, x_align: St.Align.START });
|
||||
this._errorMessageLabel.hide();
|
||||
|
||||
this._infoMessageLabel = new St.Label({ style_class: 'prompt-dialog-info-label' });
|
||||
|
@ -621,7 +621,11 @@ const ChatSource = new Lang.Class({
|
||||
this.notify();
|
||||
},
|
||||
|
||||
_channelClosed: function() {
|
||||
destroy: function(reason) {
|
||||
if (this._destroyed)
|
||||
return;
|
||||
|
||||
this._destroyed = true;
|
||||
this._channel.disconnect(this._closedId);
|
||||
this._channel.disconnect(this._receivedId);
|
||||
this._channel.disconnect(this._pendingId);
|
||||
@ -631,7 +635,14 @@ const ChatSource = new Lang.Class({
|
||||
this._contact.disconnect(this._notifyAvatarId);
|
||||
this._contact.disconnect(this._presenceChangedId);
|
||||
|
||||
this.destroy();
|
||||
if (this._timestampTimeoutId)
|
||||
Mainloop.source_remove(this._timestampTimeoutId);
|
||||
|
||||
this.parent(reason);
|
||||
},
|
||||
|
||||
_channelClosed: function() {
|
||||
this.destroy(MessageTray.NotificationDestroyedReason.SOURCE_CLOSED);
|
||||
},
|
||||
|
||||
/* All messages are new messages for Telepathy sources */
|
||||
@ -675,7 +686,7 @@ const ChatSource = new Lang.Class({
|
||||
|
||||
this._notifyTimeoutId = 0;
|
||||
|
||||
return false;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
},
|
||||
|
||||
// This is called for both messages we send from
|
||||
@ -975,7 +986,7 @@ const ChatNotification = new Lang.Class({
|
||||
|
||||
this._filterMessages();
|
||||
|
||||
return false;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
},
|
||||
|
||||
appendAliasChange: function(oldAlias, newAlias) {
|
||||
@ -1013,7 +1024,7 @@ const ChatNotification = new Lang.Class({
|
||||
|
||||
this.source.setChatState(Tp.ChannelChatState.PAUSED);
|
||||
|
||||
return false;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
},
|
||||
|
||||
_onEntryChanged: function() {
|
||||
@ -1339,7 +1350,7 @@ const AccountNotification = new Lang.Class({
|
||||
let cmd = 'empathy-accounts --select-account=' +
|
||||
account.get_path_suffix();
|
||||
let app_info = Gio.app_info_create_from_commandline(cmd, null, 0);
|
||||
app_info.launch([], global.create_app_launch_context());
|
||||
app_info.launch([], global.create_app_launch_context(0, -1));
|
||||
}));
|
||||
|
||||
this._enabledId = account.connect('notify::enabled',
|
||||
|
@ -1,6 +1,7 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Signals = imports.signals;
|
||||
const Lang = imports.lang;
|
||||
const Meta = imports.gi.Meta;
|
||||
@ -577,7 +578,7 @@ const Dash = new Lang.Class({
|
||||
this._labelShowing = true;
|
||||
item.showLabel();
|
||||
this._showLabelTimeoutId = 0;
|
||||
return false;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
}));
|
||||
if (this._resetHoverTimeoutId > 0) {
|
||||
Mainloop.source_remove(this._resetHoverTimeoutId);
|
||||
@ -594,7 +595,7 @@ const Dash = new Lang.Class({
|
||||
Lang.bind(this, function() {
|
||||
this._labelShowing = false;
|
||||
this._resetHoverTimeoutId = 0;
|
||||
return false;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
@ -113,22 +113,7 @@ const DateMenuButton = new Lang.Class({
|
||||
this.menu.connect('open-state-changed', Lang.bind(this, function(menu, isOpen) {
|
||||
if (isOpen) {
|
||||
let now = new Date();
|
||||
/* Passing true to setDate() forces events to be reloaded. We
|
||||
* want this behavior, because
|
||||
*
|
||||
* o It will cause activation of the calendar server which is
|
||||
* useful if it has crashed
|
||||
*
|
||||
* o It will cause the calendar server to reload events which
|
||||
* is useful if dynamic updates are not supported or not
|
||||
* properly working
|
||||
*
|
||||
* Since this only happens when the menu is opened, the cost
|
||||
* isn't very big.
|
||||
*/
|
||||
this._calendar.setDate(now, true);
|
||||
// No need to update this._eventList as ::selected-date-changed
|
||||
// signal will fire
|
||||
this._calendar.setDate(now);
|
||||
}
|
||||
}));
|
||||
|
||||
@ -226,7 +211,7 @@ const DateMenuButton = new Lang.Class({
|
||||
let app = this._getCalendarApp();
|
||||
if (app.get_id() == 'evolution.desktop')
|
||||
app = Gio.DesktopAppInfo.new('evolution-calendar.desktop');
|
||||
app.launch([], global.create_app_launch_context());
|
||||
app.launch([], global.create_app_launch_context(0, -1));
|
||||
},
|
||||
|
||||
_onOpenClocksActivate: function() {
|
||||
|
32
js/ui/dnd.js
32
js/ui/dnd.js
@ -46,7 +46,7 @@ let dragMonitors = [];
|
||||
function _getEventHandlerActor() {
|
||||
if (!eventHandlerActor) {
|
||||
eventHandlerActor = new Clutter.Actor({ width: 0, height: 0 });
|
||||
Main.uiGroup.add_actor(eventHandlerActor);
|
||||
Main.layoutManager.sessionGroup.add_actor(eventHandlerActor);
|
||||
// We connect to 'event' rather than 'captured-event' because the capturing phase doesn't happen
|
||||
// when you've grabbed the pointer.
|
||||
eventHandlerActor.connect('event',
|
||||
@ -106,10 +106,10 @@ const _Draggable = new Lang.Class({
|
||||
|
||||
_onButtonPress : function (actor, event) {
|
||||
if (event.get_button() != 1)
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
||||
if (Tweener.getTweenCount(actor))
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
||||
this._buttonDown = true;
|
||||
this._grabActor();
|
||||
@ -118,7 +118,7 @@ const _Draggable = new Lang.Class({
|
||||
this._dragStartX = stageX;
|
||||
this._dragStartY = stageY;
|
||||
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
},
|
||||
|
||||
_grabActor: function() {
|
||||
@ -164,11 +164,11 @@ const _Draggable = new Lang.Class({
|
||||
} else if (this._dragActor != null && !this._animationInProgress) {
|
||||
// Drag must have been cancelled with Esc.
|
||||
this._dragComplete();
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
} else {
|
||||
// Drag has never started.
|
||||
this._ungrabActor();
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
}
|
||||
// We intercept MOTION event to figure out if the drag has started and to draw
|
||||
// this._dragActor under the pointer when dragging is in progress
|
||||
@ -184,11 +184,11 @@ const _Draggable = new Lang.Class({
|
||||
let symbol = event.get_key_symbol();
|
||||
if (symbol == Clutter.Escape) {
|
||||
this._cancelDrag(event.get_time());
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
},
|
||||
|
||||
/**
|
||||
@ -236,7 +236,7 @@ const _Draggable = new Lang.Class({
|
||||
|
||||
if (this.actor._delegate && this.actor._delegate.getDragActor) {
|
||||
this._dragActor = this.actor._delegate.getDragActor();
|
||||
Main.uiGroup.add_child(this._dragActor);
|
||||
Main.layoutManager.sessionGroup.add_child(this._dragActor);
|
||||
this._dragActor.raise_top();
|
||||
Shell.util_set_hidden_from_pick(this._dragActor, true);
|
||||
|
||||
@ -276,7 +276,7 @@ const _Draggable = new Lang.Class({
|
||||
this._dragOrigScale = this._dragActor.scale_x;
|
||||
|
||||
// Set the actor's scale such that it will keep the same
|
||||
// transformed size when it's reparented to the uiGroup
|
||||
// transformed size when it's reparented to the sessionGroup
|
||||
let [scaledWidth, scaledHeight] = this.actor.get_transformed_size();
|
||||
this._dragActor.set_scale(scaledWidth / this.actor.width,
|
||||
scaledHeight / this.actor.height);
|
||||
@ -286,7 +286,7 @@ const _Draggable = new Lang.Class({
|
||||
this._dragOffsetY = actorStageY - this._dragStartY;
|
||||
|
||||
this._dragOrigParent.remove_actor(this._dragActor);
|
||||
Main.uiGroup.add_child(this._dragActor);
|
||||
Main.layoutManager.sessionGroup.add_child(this._dragActor);
|
||||
this._dragActor.raise_top();
|
||||
Shell.util_set_hidden_from_pick(this._dragActor, true);
|
||||
}
|
||||
@ -362,7 +362,7 @@ const _Draggable = new Lang.Class({
|
||||
let result = motionFunc(dragEvent);
|
||||
if (result != DragMotionResult.CONTINUE) {
|
||||
global.screen.set_cursor(DRAG_CURSOR_MAP[result]);
|
||||
return false;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -380,13 +380,13 @@ const _Draggable = new Lang.Class({
|
||||
0);
|
||||
if (result != DragMotionResult.CONTINUE) {
|
||||
global.screen.set_cursor(DRAG_CURSOR_MAP[result]);
|
||||
return false;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
}
|
||||
}
|
||||
target = target.get_parent();
|
||||
}
|
||||
global.screen.set_cursor(Meta.Cursor.DND_IN_DRAG);
|
||||
return false;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
},
|
||||
|
||||
_queueUpdateDragHover: function() {
|
||||
@ -448,7 +448,7 @@ const _Draggable = new Lang.Class({
|
||||
event.get_time())) {
|
||||
// If it accepted the drop without taking the actor,
|
||||
// handle it ourselves.
|
||||
if (this._dragActor.get_parent() == Main.uiGroup) {
|
||||
if (this._dragActor.get_parent() == Main.layoutManager.sessionGroup) {
|
||||
if (this._restoreOnSuccess) {
|
||||
this._restoreDragActor(event.get_time());
|
||||
return true;
|
||||
@ -557,7 +557,7 @@ const _Draggable = new Lang.Class({
|
||||
|
||||
_onAnimationComplete : function (dragActor, eventTime) {
|
||||
if (this._dragOrigParent) {
|
||||
Main.uiGroup.remove_child(this._dragActor);
|
||||
Main.layoutManager.sessionGroup.remove_child(this._dragActor);
|
||||
this._dragOrigParent.add_actor(this._dragActor);
|
||||
dragActor.set_scale(this._dragOrigScale, this._dragOrigScale);
|
||||
dragActor.set_position(this._dragOrigX, this._dragOrigY);
|
||||
|
@ -13,9 +13,7 @@
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
const Lang = imports.lang;
|
||||
@ -249,7 +247,9 @@ const EndSessionDialog = new Lang.Class({
|
||||
this._subjectLabel = new St.Label({ style_class: 'end-session-dialog-subject' });
|
||||
|
||||
messageLayout.add(this._subjectLabel,
|
||||
{ y_fill: false,
|
||||
{ x_fill: false,
|
||||
y_fill: false,
|
||||
x_align: St.Align.START,
|
||||
y_align: St.Align.START });
|
||||
|
||||
this._descriptionLabel = new St.Label({ style_class: 'end-session-dialog-description' });
|
||||
@ -409,7 +409,7 @@ const EndSessionDialog = new Lang.Class({
|
||||
this._secondsLeft = this._totalSecondsToStayOpen - secondsElapsed;
|
||||
if (this._secondsLeft > 0) {
|
||||
this._sync();
|
||||
return true;
|
||||
return GLib.SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
let dialogContent = DialogContent[this._type];
|
||||
@ -417,7 +417,7 @@ const EndSessionDialog = new Lang.Class({
|
||||
this._confirm(button.signal);
|
||||
this._timerId = 0;
|
||||
|
||||
return false;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
}));
|
||||
},
|
||||
|
||||
|
@ -201,7 +201,7 @@ const InstallExtensionDialog = new Lang.Class({
|
||||
default: true
|
||||
}]);
|
||||
|
||||
let message = _("Download and install '%s' from extensions.gnome.org?").format(info.name);
|
||||
let message = _("Download and install “%s” from extensions.gnome.org?").format(info.name);
|
||||
|
||||
let box = new St.BoxLayout();
|
||||
this.contentLayout.add(box);
|
||||
|
@ -280,7 +280,7 @@ const GrabHelper = new Lang.Class({
|
||||
if (type == Clutter.EventType.KEY_PRESS &&
|
||||
event.get_key_symbol() == Clutter.KEY_Escape) {
|
||||
this.ungrab({ isUser: true });
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
}
|
||||
|
||||
let press = type == Clutter.EventType.BUTTON_PRESS;
|
||||
@ -289,14 +289,14 @@ const GrabHelper = new Lang.Class({
|
||||
|
||||
if (release && this._ignoreRelease) {
|
||||
this._ignoreRelease = false;
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
}
|
||||
|
||||
if (this._isWithinGrabbedActor(event.get_source()))
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
||||
if (Main.keyboard.shouldTakeEvent(event))
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
||||
if (button) {
|
||||
// If we have a press event, ignore the next event,
|
||||
@ -305,9 +305,9 @@ const GrabHelper = new Lang.Class({
|
||||
this._ignoreRelease = true;
|
||||
let i = this._actorInGrabStack(event.get_source()) + 1;
|
||||
this.ungrab({ actor: this._grabStack[i].actor, isUser: true });
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
}
|
||||
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
},
|
||||
});
|
||||
|
@ -32,6 +32,7 @@ const CandidateArea = new Lang.Class({
|
||||
let j = i;
|
||||
box.connect('button-release-event', Lang.bind(this, function(actor, event) {
|
||||
this.emit('candidate-clicked', j, event.get_button(), event.get_state());
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
}));
|
||||
}
|
||||
|
||||
@ -114,9 +115,6 @@ const CandidatePopup = new Lang.Class({
|
||||
Name: 'CandidatePopup',
|
||||
|
||||
_init: function() {
|
||||
this._cursor = new St.Bin({ opacity: 0 });
|
||||
Main.uiGroup.add_actor(this._cursor);
|
||||
|
||||
this._boxPointer = new BoxPointer.BoxPointer(St.Side.TOP);
|
||||
this._boxPointer.actor.visible = false;
|
||||
this._boxPointer.actor.style_class = 'candidate-popup-boxpointer';
|
||||
@ -157,10 +155,9 @@ const CandidatePopup = new Lang.Class({
|
||||
|
||||
panelService.connect('set-cursor-location',
|
||||
Lang.bind(this, function(ps, x, y, w, h) {
|
||||
this._cursor.set_position(x, y);
|
||||
this._cursor.set_size(w, h);
|
||||
Main.layoutManager.setDummyCursorPosition(x, y);
|
||||
if (this._boxPointer.actor.visible)
|
||||
this._boxPointer.setPosition(this._cursor, 0);
|
||||
this._boxPointer.setPosition(Main.layoutManager.dummyCursor, 0);
|
||||
}));
|
||||
panelService.connect('update-preedit-text',
|
||||
Lang.bind(this, function(ps, text, cursorPosition, visible) {
|
||||
@ -252,7 +249,7 @@ const CandidatePopup = new Lang.Class({
|
||||
this._candidateArea.actor.visible);
|
||||
|
||||
if (isVisible) {
|
||||
this._boxPointer.setPosition(this._cursor, 0);
|
||||
this._boxPointer.setPosition(Main.layoutManager.dummyCursor, 0);
|
||||
this._boxPointer.show(BoxPointer.PopupAnimation.NONE);
|
||||
this._boxPointer.actor.raise_top();
|
||||
} else {
|
||||
|
@ -433,6 +433,10 @@ const IconGrid = new Lang.Class({
|
||||
this._grid.add_actor(item.actor);
|
||||
},
|
||||
|
||||
removeItem: function(item) {
|
||||
this._grid.remove_child(item.actor);
|
||||
},
|
||||
|
||||
getItemAtIndex: function(index) {
|
||||
return this._grid.get_child_at_index(index);
|
||||
},
|
||||
|
@ -82,8 +82,16 @@ const Key = new Lang.Class({
|
||||
style_class: 'keyboard-key' });
|
||||
|
||||
button.key_width = this._key.width;
|
||||
button.connect('button-press-event', Lang.bind(this, function () { this._key.press(); }));
|
||||
button.connect('button-release-event', Lang.bind(this, function () { this._key.release(); }));
|
||||
button.connect('button-press-event', Lang.bind(this,
|
||||
function () {
|
||||
this._key.press();
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
}));
|
||||
button.connect('button-release-event', Lang.bind(this,
|
||||
function () {
|
||||
this._key.release();
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
}));
|
||||
|
||||
return button;
|
||||
},
|
||||
@ -106,8 +114,16 @@ const Key = new Lang.Class({
|
||||
let label = this._getUnichar(extended_key);
|
||||
let key = new St.Button({ label: label, style_class: 'keyboard-key' });
|
||||
key.extended_key = extended_key;
|
||||
key.connect('button-press-event', Lang.bind(this, function () { extended_key.press(); }));
|
||||
key.connect('button-release-event', Lang.bind(this, function () { extended_key.release(); }));
|
||||
key.connect('button-press-event', Lang.bind(this,
|
||||
function () {
|
||||
extended_key.press();
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
}));
|
||||
key.connect('button-release-event', Lang.bind(this,
|
||||
function () {
|
||||
extended_key.release();
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
}));
|
||||
this._extended_keyboard.add(key);
|
||||
}
|
||||
this._boxPointer.bin.add_actor(this._extended_keyboard);
|
||||
@ -252,7 +268,10 @@ const Keyboard = new Lang.Class({
|
||||
|
||||
if (!this._showIdleId)
|
||||
this._showIdleId = GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE,
|
||||
Lang.bind(this, function() { this.Show(time); }));
|
||||
Lang.bind(this, function() {
|
||||
this.Show(time);
|
||||
return GLib.SOURCE_REMOVE;
|
||||
}));
|
||||
},
|
||||
|
||||
_createLayersForGroup: function (gname) {
|
||||
@ -294,7 +313,7 @@ const Keyboard = new Lang.Class({
|
||||
else if (release && this._capturedPress)
|
||||
this._hideSubkeys();
|
||||
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
},
|
||||
|
||||
_addRows : function (keys, layout) {
|
||||
@ -438,7 +457,6 @@ const Keyboard = new Lang.Class({
|
||||
_createSource: function () {
|
||||
if (this._source == null) {
|
||||
this._source = new KeyboardSource(this);
|
||||
this._source.setTransient(true);
|
||||
Main.messageTray.add(this._source);
|
||||
}
|
||||
},
|
||||
@ -480,6 +498,7 @@ const Keyboard = new Lang.Class({
|
||||
Lang.bind(this, function() {
|
||||
this._clearKeyboardRestTimer();
|
||||
this._show(monitor);
|
||||
return GLib.SOURCE_REMOVE;
|
||||
}));
|
||||
},
|
||||
|
||||
@ -505,6 +524,7 @@ const Keyboard = new Lang.Class({
|
||||
Lang.bind(this, function() {
|
||||
this._clearKeyboardRestTimer();
|
||||
this._hide();
|
||||
return GLib.SOURCE_REMOVE;
|
||||
}));
|
||||
},
|
||||
|
||||
|
226
js/ui/layout.js
226
js/ui/layout.js
@ -162,9 +162,9 @@ const LayoutManager = new Lang.Class({
|
||||
this._startingUp = true;
|
||||
|
||||
// Normally, the stage is always covered so Clutter doesn't need to clear
|
||||
// it; however it becomes visible during the startup animation
|
||||
// See the comment below for a longer explanation
|
||||
// it; however it becomes visible when using the magnifier.
|
||||
global.stage.color = DEFAULT_BACKGROUND_COLOR;
|
||||
global.stage.no_clear_hint = true;
|
||||
|
||||
// Set up stage hierarchy to group all UI actors under one container.
|
||||
this.uiGroup = new Shell.GenericContainer({ name: 'uiGroup' });
|
||||
@ -184,29 +184,27 @@ const LayoutManager = new Lang.Class({
|
||||
let height = global.stage.height;
|
||||
[alloc.min_size, alloc.natural_size] = [height, height];
|
||||
});
|
||||
global.stage.add_child(this.uiGroup);
|
||||
|
||||
this.systemGroup = new St.Widget({ name: 'systemGroup',
|
||||
layout_manager: new Clutter.BinLayout() });
|
||||
this.uiGroup.add_actor(this.systemGroup);
|
||||
|
||||
this.sessionGroup = new St.Widget({ name: 'sessionGroup' });
|
||||
this.uiGroup.add_child(this.sessionGroup);
|
||||
|
||||
global.stage.remove_actor(global.window_group);
|
||||
this.uiGroup.add_actor(global.window_group);
|
||||
|
||||
global.stage.add_child(this.uiGroup);
|
||||
this.sessionGroup.add_actor(global.window_group);
|
||||
|
||||
this.overviewGroup = new St.Widget({ name: 'overviewGroup',
|
||||
visible: false });
|
||||
this.addChrome(this.overviewGroup);
|
||||
|
||||
this.screenShieldGroup = new St.Widget({ name: 'screenShieldGroup',
|
||||
visible: false,
|
||||
clip_to_allocation: true,
|
||||
layout_manager: new Clutter.BinLayout(),
|
||||
});
|
||||
this.addChrome(this.screenShieldGroup);
|
||||
|
||||
this.panelBox = new St.BoxLayout({ name: 'panelBox',
|
||||
vertical: true });
|
||||
this.addChrome(this.panelBox, { affectsStruts: true,
|
||||
trackFullscreen: true });
|
||||
this.panelBox.connect('allocation-changed',
|
||||
Lang.bind(this, this._panelBoxChanged));
|
||||
this.uiGroup.add_child(this.screenShieldGroup);
|
||||
|
||||
this.trayBox = new St.Widget({ name: 'trayBox',
|
||||
layout_manager: new Clutter.BinLayout() });
|
||||
@ -219,8 +217,39 @@ const LayoutManager = new Lang.Class({
|
||||
this.addChrome(this.keyboardBox);
|
||||
this._keyboardHeightNotifyId = 0;
|
||||
|
||||
global.stage.remove_actor(global.top_window_group);
|
||||
this.uiGroup.add_actor(global.top_window_group);
|
||||
this.osdGroup = new St.Widget();
|
||||
this.sessionGroup.add_child(this.osdGroup);
|
||||
|
||||
this.switcherPopupGroup = new St.Widget();
|
||||
this.sessionGroup.add_child(this.switcherPopupGroup);
|
||||
|
||||
this.dialogGroup = new St.Widget();
|
||||
this.sessionGroup.add_child(this.dialogGroup);
|
||||
|
||||
// A dummy actor that tracks the mouse or text cursor, based on the
|
||||
// position set in setDummyCursorPosition.
|
||||
this.dummyCursor = new St.Widget({ width: 0, height: 0 });
|
||||
this.uiGroup.add_child(this.dummyCursor);
|
||||
|
||||
// The panel group isn't in the session, as it needs to go above the screen
|
||||
// shield, and it isn't animated in the login animation.
|
||||
this.panelGroup = new St.Widget({ name: 'panelGroup' });
|
||||
this.uiGroup.add_child(this.panelGroup);
|
||||
this._trackActor(this.panelGroup, { affectsStruts: true,
|
||||
trackFullscreen: true });
|
||||
this.panelGroup.connect('allocation-changed',
|
||||
Lang.bind(this, this._panelGroupChanged));
|
||||
|
||||
this.overlayGroup = new St.Widget({ name: 'overlayGroup' });
|
||||
this.uiGroup.add_child(this.overlayGroup);
|
||||
|
||||
this.menuGroup = new St.Widget();
|
||||
this.overlayGroup.add_child(this.menuGroup);
|
||||
|
||||
this._topSessionGroup = new St.Widget();
|
||||
this.overlayGroup.add_child(this._topSessionGroup);
|
||||
global.stage.remove_child(global.top_window_group);
|
||||
this._topSessionGroup.add_child(global.top_window_group);
|
||||
|
||||
this._backgroundGroup = new Meta.BackgroundGroup();
|
||||
global.window_group.add_child(this._backgroundGroup);
|
||||
@ -242,8 +271,7 @@ const LayoutManager = new Lang.Class({
|
||||
// This is called by Main after everything else is constructed
|
||||
init: function() {
|
||||
Main.sessionMode.connect('updated', Lang.bind(this, this._sessionUpdated));
|
||||
|
||||
this._loadBackground();
|
||||
this._prepareStartupAnimation();
|
||||
},
|
||||
|
||||
showOverview: function() {
|
||||
@ -252,6 +280,9 @@ const LayoutManager = new Lang.Class({
|
||||
this._inOverview = true;
|
||||
this._updateVisibility();
|
||||
this._updateRegions();
|
||||
|
||||
global.window_group.hide();
|
||||
global.top_window_group.hide();
|
||||
},
|
||||
|
||||
hideOverview: function() {
|
||||
@ -260,6 +291,9 @@ const LayoutManager = new Lang.Class({
|
||||
this._inOverview = false;
|
||||
this._updateVisibility();
|
||||
this._queueUpdateRegions();
|
||||
|
||||
global.window_group.show();
|
||||
global.top_window_group.show();
|
||||
},
|
||||
|
||||
_sessionUpdated: function() {
|
||||
@ -301,7 +335,7 @@ const LayoutManager = new Lang.Class({
|
||||
});
|
||||
this.hotCorners = [];
|
||||
|
||||
let size = this.panelBox.height;
|
||||
let size = this.panelGroup.height;
|
||||
|
||||
// build new hot corners
|
||||
for (let i = 0; i < this.monitors.length; i++) {
|
||||
@ -352,26 +386,26 @@ const LayoutManager = new Lang.Class({
|
||||
this.emit('hot-corners-changed');
|
||||
},
|
||||
|
||||
_createBackground: function(monitorIndex) {
|
||||
_addBackgroundMenu: function(bgManager) {
|
||||
BackgroundMenu.addBackgroundMenu(bgManager.background.actor, this);
|
||||
},
|
||||
|
||||
_createBackgroundManager: function(monitorIndex) {
|
||||
let bgManager = new Background.BackgroundManager({ container: this._backgroundGroup,
|
||||
layoutManager: this,
|
||||
monitorIndex: monitorIndex });
|
||||
BackgroundMenu.addBackgroundMenu(bgManager.background.actor);
|
||||
|
||||
bgManager.connect('changed', Lang.bind(this, function() {
|
||||
BackgroundMenu.addBackgroundMenu(bgManager.background.actor);
|
||||
}));
|
||||
bgManager.connect('changed', Lang.bind(this, this._addBackgroundMenu));
|
||||
this._addBackgroundMenu(bgManager);
|
||||
|
||||
this._bgManagers[monitorIndex] = bgManager;
|
||||
|
||||
return bgManager.background;
|
||||
return bgManager;
|
||||
},
|
||||
|
||||
_createSecondaryBackgrounds: function() {
|
||||
_showSecondaryBackgrounds: function() {
|
||||
for (let i = 0; i < this.monitors.length; i++) {
|
||||
if (i != this.primaryIndex) {
|
||||
let background = this._createBackground(i);
|
||||
|
||||
let background = this._bgManagers[i].background;
|
||||
background.actor.show();
|
||||
background.actor.opacity = 0;
|
||||
Tweener.addTween(background.actor,
|
||||
{ opacity: 255,
|
||||
@ -381,10 +415,6 @@ const LayoutManager = new Lang.Class({
|
||||
}
|
||||
},
|
||||
|
||||
_createPrimaryBackground: function() {
|
||||
this._createBackground(this.primaryIndex);
|
||||
},
|
||||
|
||||
_updateBackgrounds: function() {
|
||||
let i;
|
||||
for (i = 0; i < this._bgManagers.length; i++)
|
||||
@ -395,20 +425,21 @@ const LayoutManager = new Lang.Class({
|
||||
if (Main.sessionMode.isGreeter)
|
||||
return;
|
||||
|
||||
if (this._startingUp)
|
||||
return;
|
||||
|
||||
for (let i = 0; i < this.monitors.length; i++) {
|
||||
this._createBackground(i);
|
||||
let bgManager = this._createBackgroundManager(i);
|
||||
this._bgManagers.push(bgManager);
|
||||
|
||||
if (i != this.primaryIndex && this._startingUp)
|
||||
bgManager.background.actor.hide();
|
||||
}
|
||||
},
|
||||
|
||||
_updateBoxes: function() {
|
||||
this.screenShieldGroup.set_position(0, 0);
|
||||
this.screenShieldGroup.set_size(global.screen_width, global.screen_height);
|
||||
this.systemGroup.set_position(0, 0);
|
||||
this.systemGroup.set_size(global.screen_width, global.screen_height);
|
||||
|
||||
this.panelBox.set_position(this.primaryMonitor.x, this.primaryMonitor.y);
|
||||
this.panelBox.set_size(this.primaryMonitor.width, -1);
|
||||
this.panelGroup.set_position(this.primaryMonitor.x, this.primaryMonitor.y);
|
||||
this.panelGroup.set_size(this.primaryMonitor.width, -1);
|
||||
|
||||
if (this.keyboardIndex < 0)
|
||||
this.keyboardIndex = this.primaryIndex;
|
||||
@ -418,10 +449,10 @@ const LayoutManager = new Lang.Class({
|
||||
this.trayBox.set_size(this.bottomMonitor.width, -1);
|
||||
},
|
||||
|
||||
_panelBoxChanged: function() {
|
||||
_panelGroupChanged: function() {
|
||||
this._updatePanelBarrier();
|
||||
|
||||
let size = this.panelBox.height;
|
||||
let size = this.panelGroup.height;
|
||||
this.hotCorners.forEach(function(corner) {
|
||||
if (corner)
|
||||
corner.setBarrierSize(size);
|
||||
@ -434,12 +465,12 @@ const LayoutManager = new Lang.Class({
|
||||
this._rightPanelBarrier = null;
|
||||
}
|
||||
|
||||
if (this.panelBox.height) {
|
||||
if (this.panelGroup.height) {
|
||||
let primary = this.primaryMonitor;
|
||||
|
||||
this._rightPanelBarrier = new Meta.Barrier({ display: global.display,
|
||||
x1: primary.x + primary.width, y1: primary.y,
|
||||
x2: primary.x + primary.width, y2: primary.y + this.panelBox.height,
|
||||
x2: primary.x + primary.width, y2: primary.y + this.panelGroup.height,
|
||||
directions: Meta.BarrierDirection.NEGATIVE_X });
|
||||
}
|
||||
},
|
||||
@ -545,25 +576,6 @@ const LayoutManager = new Lang.Class({
|
||||
return this._keyboardIndex;
|
||||
},
|
||||
|
||||
_loadBackground: function() {
|
||||
this._systemBackground = new Background.SystemBackground();
|
||||
this._systemBackground.actor.hide();
|
||||
|
||||
global.stage.insert_child_below(this._systemBackground.actor, null);
|
||||
|
||||
let constraint = new Clutter.BindConstraint({ source: global.stage,
|
||||
coordinate: Clutter.BindCoordinate.ALL });
|
||||
this._systemBackground.actor.add_constraint(constraint);
|
||||
|
||||
let signalId = this._systemBackground.connect('loaded', Lang.bind(this, function() {
|
||||
this._systemBackground.disconnect(signalId);
|
||||
this._systemBackground.actor.show();
|
||||
global.stage.show();
|
||||
|
||||
this._prepareStartupAnimation();
|
||||
}));
|
||||
},
|
||||
|
||||
// Startup Animations
|
||||
//
|
||||
// We have two different animations, depending on whether we're a greeter
|
||||
@ -584,6 +596,8 @@ const LayoutManager = new Lang.Class({
|
||||
// screen. So, we set no_clear_hint at the end of the animation.
|
||||
|
||||
_prepareStartupAnimation: function() {
|
||||
global.stage.show();
|
||||
|
||||
// During the initial transition, add a simple actor to block all events,
|
||||
// so they don't get delivered to X11 windows that have been transformed.
|
||||
this._coverPane = new Clutter.Actor({ opacity: 0,
|
||||
@ -593,9 +607,9 @@ const LayoutManager = new Lang.Class({
|
||||
this.addChrome(this._coverPane);
|
||||
|
||||
if (Main.sessionMode.isGreeter) {
|
||||
this.panelBox.translation_y = -this.panelBox.height;
|
||||
this.panelGroup.translation_y = -this.panelGroup.height;
|
||||
} else {
|
||||
this._createPrimaryBackground();
|
||||
this._updateBackgrounds();
|
||||
|
||||
// We need to force an update of the regions now before we scale
|
||||
// the UI group to get the coorect allocation for the struts.
|
||||
@ -608,10 +622,10 @@ const LayoutManager = new Lang.Class({
|
||||
let x = monitor.x + monitor.width / 2.0;
|
||||
let y = monitor.y + monitor.height / 2.0;
|
||||
|
||||
this.uiGroup.set_pivot_point(x / global.screen_width,
|
||||
y / global.screen_height);
|
||||
this.uiGroup.scale_x = this.uiGroup.scale_y = 0.5;
|
||||
this.uiGroup.opacity = 0;
|
||||
this.sessionGroup.set_pivot_point(x / global.screen_width,
|
||||
y / global.screen_height);
|
||||
this.sessionGroup.scale_x = this.sessionGroup.scale_y = 0.75;
|
||||
this.sessionGroup.opacity = 0;
|
||||
global.window_group.set_clip(monitor.x, monitor.y, monitor.width, monitor.height);
|
||||
}
|
||||
|
||||
@ -625,7 +639,7 @@ const LayoutManager = new Lang.Class({
|
||||
// when the system is bogged down
|
||||
GLib.idle_add(GLib.PRIORITY_LOW, Lang.bind(this, function() {
|
||||
this._startupAnimation();
|
||||
return false;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
}));
|
||||
},
|
||||
|
||||
@ -637,7 +651,7 @@ const LayoutManager = new Lang.Class({
|
||||
},
|
||||
|
||||
_startupAnimationGreeter: function() {
|
||||
Tweener.addTween(this.panelBox,
|
||||
Tweener.addTween(this.panelGroup,
|
||||
{ translation_y: 0,
|
||||
time: STARTUP_ANIMATION_TIME,
|
||||
transition: 'easeOutQuad',
|
||||
@ -646,7 +660,7 @@ const LayoutManager = new Lang.Class({
|
||||
},
|
||||
|
||||
_startupAnimationSession: function() {
|
||||
Tweener.addTween(this.uiGroup,
|
||||
Tweener.addTween(this.sessionGroup,
|
||||
{ scale_x: 1,
|
||||
scale_y: 1,
|
||||
opacity: 255,
|
||||
@ -657,23 +671,16 @@ const LayoutManager = new Lang.Class({
|
||||
},
|
||||
|
||||
_startupAnimationComplete: function() {
|
||||
// At this point, the UI group is covering everything, so
|
||||
// we no longer need to clear the stage
|
||||
global.stage.no_clear_hint = true;
|
||||
|
||||
this._coverPane.destroy();
|
||||
this._coverPane = null;
|
||||
|
||||
this._systemBackground.actor.destroy();
|
||||
this._systemBackground = null;
|
||||
|
||||
this._startingUp = false;
|
||||
|
||||
this.trayBox.show();
|
||||
this.keyboardBox.show();
|
||||
|
||||
if (!Main.sessionMode.isGreeter) {
|
||||
this._createSecondaryBackgrounds();
|
||||
this._showSecondaryBackgrounds();
|
||||
global.window_group.remove_clip();
|
||||
}
|
||||
|
||||
@ -723,6 +730,20 @@ const LayoutManager = new Lang.Class({
|
||||
this._updateRegions();
|
||||
},
|
||||
|
||||
// setDummyCursorPosition:
|
||||
//
|
||||
// The cursor dummy is a standard widget commonly used for popup
|
||||
// menus and box pointers to track, as the box pointer API only
|
||||
// tracks actors. If you want to pop up a menu based on where the
|
||||
// user clicked, or where the text cursor is, the cursor dummy
|
||||
// is what you should use. Given that the menu should not track
|
||||
// the actual mouse pointer as it moves, you need to call this
|
||||
// function before you show the menu to ensure it is at the right
|
||||
// position.
|
||||
setDummyCursorPosition: function(x, y) {
|
||||
this.dummyCursor.set_position(Math.round(x), Math.round(y));
|
||||
},
|
||||
|
||||
// addChrome:
|
||||
// @actor: an actor to add to the chrome
|
||||
// @params: (optional) additional params
|
||||
@ -742,9 +763,9 @@ const LayoutManager = new Lang.Class({
|
||||
// monitor (it will be hidden whenever a fullscreen window is visible,
|
||||
// and shown otherwise)
|
||||
addChrome: function(actor, params) {
|
||||
this.uiGroup.add_actor(actor);
|
||||
if (this.uiGroup.contains(global.top_window_group))
|
||||
this.uiGroup.set_child_below_sibling(actor, global.top_window_group);
|
||||
this.sessionGroup.add_actor(actor);
|
||||
if (this.sessionGroup.contains(global.top_window_group))
|
||||
this.sessionGroup.set_child_below_sibling(actor, global.top_window_group);
|
||||
this._trackActor(actor, params);
|
||||
},
|
||||
|
||||
@ -795,7 +816,7 @@ const LayoutManager = new Lang.Class({
|
||||
//
|
||||
// Removes @actor from the chrome
|
||||
removeChrome: function(actor) {
|
||||
this.uiGroup.remove_actor(actor);
|
||||
this.sessionGroup.remove_actor(actor);
|
||||
this._untrackActor(actor);
|
||||
},
|
||||
|
||||
@ -814,13 +835,10 @@ const LayoutManager = new Lang.Class({
|
||||
|
||||
let actorData = Params.parse(params, defaultParams);
|
||||
actorData.actor = actor;
|
||||
actorData.isToplevel = actor.get_parent() == this.uiGroup;
|
||||
actorData.visibleId = actor.connect('notify::visible',
|
||||
Lang.bind(this, this._queueUpdateRegions));
|
||||
actorData.allocationId = actor.connect('notify::allocation',
|
||||
Lang.bind(this, this._queueUpdateRegions));
|
||||
actorData.parentSetId = actor.connect('parent-set',
|
||||
Lang.bind(this, this._actorReparented));
|
||||
// Note that destroying actor will unset its parent, so we don't
|
||||
// need to connect to 'destroy' too.
|
||||
|
||||
@ -843,29 +861,13 @@ const LayoutManager = new Lang.Class({
|
||||
this._queueUpdateRegions();
|
||||
},
|
||||
|
||||
_actorReparented: function(actor, oldParent) {
|
||||
let newParent = actor.get_parent();
|
||||
if (!newParent) {
|
||||
this._untrackActor(actor);
|
||||
} else {
|
||||
let i = this._findActor(actor);
|
||||
let actorData = this._trackedActors[i];
|
||||
actorData.isToplevel = (newParent == this.uiGroup);
|
||||
}
|
||||
},
|
||||
|
||||
_updateVisibility: function() {
|
||||
let windowsVisible = Main.sessionMode.hasWindows && !this._inOverview;
|
||||
|
||||
global.window_group.visible = windowsVisible;
|
||||
global.top_window_group.visible = windowsVisible;
|
||||
|
||||
for (let i = 0; i < this._trackedActors.length; i++) {
|
||||
let actorData = this._trackedActors[i], visible;
|
||||
if (!actorData.trackFullscreen)
|
||||
continue;
|
||||
if (!actorData.isToplevel)
|
||||
continue;
|
||||
|
||||
if (!windowsVisible)
|
||||
visible = true;
|
||||
@ -1042,7 +1044,7 @@ const LayoutManager = new Lang.Class({
|
||||
workspace.set_builtin_struts(struts);
|
||||
}
|
||||
|
||||
return false;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
}
|
||||
});
|
||||
Signals.addSignalMethods(LayoutManager.prototype);
|
||||
@ -1080,9 +1082,9 @@ const HotCorner = new Lang.Class({
|
||||
this._ripple2 = new St.BoxLayout({ style_class: 'ripple-box', opacity: 0, visible: false });
|
||||
this._ripple3 = new St.BoxLayout({ style_class: 'ripple-box', opacity: 0, visible: false });
|
||||
|
||||
layoutManager.uiGroup.add_actor(this._ripple1);
|
||||
layoutManager.uiGroup.add_actor(this._ripple2);
|
||||
layoutManager.uiGroup.add_actor(this._ripple3);
|
||||
layoutManager.sessionGroup.add_actor(this._ripple1);
|
||||
layoutManager.sessionGroup.add_actor(this._ripple2);
|
||||
layoutManager.sessionGroup.add_actor(this._ripple3);
|
||||
},
|
||||
|
||||
setBarrierSize: function(size) {
|
||||
@ -1229,20 +1231,20 @@ const HotCorner = new Lang.Class({
|
||||
this._entered = true;
|
||||
this._toggleOverview();
|
||||
}
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
},
|
||||
|
||||
_onCornerLeft : function(actor, event) {
|
||||
if (event.get_related() != this.actor)
|
||||
this._entered = false;
|
||||
// Consume event, otherwise this will confuse onEnvironsLeft
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
},
|
||||
|
||||
_onEnvironsLeft : function(actor, event) {
|
||||
if (event.get_related() != this._corner)
|
||||
this._entered = false;
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -5,12 +5,38 @@ const Lang = imports.lang;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Signals = imports.signals;
|
||||
const St = imports.gi.St;
|
||||
const Shell = imports.gi.Shell;
|
||||
|
||||
const Params = imports.misc.params;
|
||||
const Tweener = imports.ui.tweener;
|
||||
|
||||
const DEFAULT_FADE_FACTOR = 0.4;
|
||||
|
||||
const GLSL_DIM_EFFECT_DECLARATIONS = '\
|
||||
float compute_dim_factor (const vec2 coords) {\
|
||||
vec2 dist = coords - vec2(0.5, 0.5); \
|
||||
float elipse_radius = 0.5; \
|
||||
/* interpolate darkening value, based on distance from screen center */ \
|
||||
float val = min(length(dist), elipse_radius); \
|
||||
return mix(0.3, 1.0, val / elipse_radius) * 0.4; \
|
||||
}';
|
||||
const GLSL_DIM_EFFECT_CODE = '\
|
||||
float a = compute_dim_factor (cogl_tex_coord0_in.xy);\
|
||||
cogl_color_out = vec4(0, 0, 0, cogl_color_in.a * a);'
|
||||
;
|
||||
|
||||
const RadialShaderQuad = new Lang.Class({
|
||||
Name: 'RadialShaderQuad',
|
||||
Extends: Shell.GLSLQuad,
|
||||
|
||||
vfunc_build_pipeline: function() {
|
||||
this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT,
|
||||
GLSL_DIM_EFFECT_DECLARATIONS,
|
||||
GLSL_DIM_EFFECT_CODE,
|
||||
true);
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Lightbox:
|
||||
* @container: parent Clutter.Container
|
||||
@ -43,15 +69,21 @@ const Lightbox = new Lang.Class({
|
||||
width: null,
|
||||
height: null,
|
||||
fadeFactor: DEFAULT_FADE_FACTOR,
|
||||
radialEffect: false,
|
||||
});
|
||||
|
||||
this._container = container;
|
||||
this._children = container.get_children();
|
||||
this._fadeFactor = params.fadeFactor;
|
||||
this.actor = new St.Bin({ x: 0,
|
||||
y: 0,
|
||||
style_class: 'lightbox',
|
||||
reactive: params.inhibitEvents });
|
||||
if (params.radialEffect)
|
||||
this.actor = new RadialShaderQuad({ x: 0,
|
||||
y: 0,
|
||||
reactive: params.inhibitEvents });
|
||||
else
|
||||
this.actor = new St.Bin({ x: 0,
|
||||
y: 0,
|
||||
style_class: 'lightbox',
|
||||
reactive: params.inhibitEvents });
|
||||
|
||||
container.add_actor(this.actor);
|
||||
this.actor.raise_top();
|
||||
|
@ -109,6 +109,7 @@ const AutoComplete = new Lang.Class({
|
||||
}
|
||||
this._lastTabTime = currTime;
|
||||
}
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
},
|
||||
|
||||
// Insert characters of text not already included in head at cursor position. i.e., if text="abc" and head="a",
|
||||
@ -502,7 +503,7 @@ const Inspector = new Lang.Class({
|
||||
let container = new Shell.GenericContainer({ width: 0,
|
||||
height: 0 });
|
||||
container.connect('allocate', Lang.bind(this, this._allocate));
|
||||
Main.uiGroup.add_actor(container);
|
||||
Main.layoutManager.sessionGroup.add_actor(container);
|
||||
|
||||
let eventHandler = new St.BoxLayout({ name: 'LookingGlassDialog',
|
||||
vertical: false,
|
||||
@ -558,7 +559,7 @@ const Inspector = new Lang.Class({
|
||||
_onKeyPressEvent: function (actor, event) {
|
||||
if (event.get_key_symbol() == Clutter.Escape)
|
||||
this._close();
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
},
|
||||
|
||||
_onButtonPressEvent: function (actor, event) {
|
||||
@ -567,7 +568,7 @@ const Inspector = new Lang.Class({
|
||||
this.emit('target', this._target, stageX, stageY);
|
||||
}
|
||||
this._close();
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
},
|
||||
|
||||
_onScrollEvent: function (actor, event) {
|
||||
@ -601,12 +602,12 @@ const Inspector = new Lang.Class({
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
},
|
||||
|
||||
_onMotionEvent: function (actor, event) {
|
||||
this._update(event);
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
},
|
||||
|
||||
_update: function(event) {
|
||||
@ -669,13 +670,13 @@ const Extensions = new Lang.Class({
|
||||
_onViewSource: function (actor) {
|
||||
let extension = actor._extension;
|
||||
let uri = extension.dir.get_uri();
|
||||
Gio.app_info_launch_default_for_uri(uri, global.create_app_launch_context());
|
||||
Gio.app_info_launch_default_for_uri(uri, global.create_app_launch_context(0, -1));
|
||||
this._lookingGlass.close();
|
||||
},
|
||||
|
||||
_onWebPage: function (actor) {
|
||||
let extension = actor._extension;
|
||||
Gio.app_info_launch_default_for_uri(extension.metadata.url, global.create_app_launch_context());
|
||||
Gio.app_info_launch_default_for_uri(extension.metadata.url, global.create_app_launch_context(0, -1));
|
||||
this._lookingGlass.close();
|
||||
},
|
||||
|
||||
@ -800,16 +801,14 @@ const LookingGlass = new Lang.Class({
|
||||
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.layoutManager.panelBox);
|
||||
Main.layoutManager.panelBox.connect('allocation-changed',
|
||||
Lang.bind(this, this._queueResize));
|
||||
Main.layoutManager.sessionGroup.add_actor(this.actor);
|
||||
Main.layoutManager.panelGroup.connect('allocation-changed',
|
||||
Lang.bind(this, this._queueResize));
|
||||
Main.layoutManager.keyboardBox.connect('allocation-changed',
|
||||
Lang.bind(this, this._queueResize));
|
||||
|
||||
this._objInspector = new ObjInspector(this);
|
||||
Main.uiGroup.add_actor(this._objInspector.actor);
|
||||
Main.layoutManager.sessionGroup.add_actor(this._objInspector.actor);
|
||||
this._objInspector.actor.hide();
|
||||
|
||||
let toolbar = new St.BoxLayout({ name: 'Toolbar' });
|
||||
@ -828,7 +827,7 @@ const LookingGlass = new Lang.Class({
|
||||
global.stage.set_key_focus(this._entry);
|
||||
}));
|
||||
this.actor.hide();
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
}));
|
||||
|
||||
let gcIcon = new St.Icon({ icon_name: 'gnome-fs-trash-full',
|
||||
@ -841,7 +840,9 @@ const LookingGlass = new Lang.Class({
|
||||
this._timeoutId = Mainloop.timeout_add(500, Lang.bind(this, function () {
|
||||
gcIcon.icon_name = 'gnome-fs-trash-full';
|
||||
Mainloop.source_remove(this._timeoutId);
|
||||
return GLib.SOURCE_REMOVE;
|
||||
}));
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
}));
|
||||
|
||||
let notebook = new Notebook();
|
||||
@ -1034,7 +1035,7 @@ const LookingGlass = new Lang.Class({
|
||||
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._hiddenY = primary.y + Main.layoutManager.panelBox.height - myHeight - 4; // -4 to hide the top corners
|
||||
this._hiddenY = primary.y + Main.layoutManager.panelGroup.height - myHeight - 4; // -4 to hide the top corners
|
||||
this._targetY = this._hiddenY + myHeight;
|
||||
this.actor.y = this._hiddenY;
|
||||
this.actor.width = myWidth;
|
||||
@ -1063,7 +1064,7 @@ const LookingGlass = new Lang.Class({
|
||||
} else {
|
||||
this.close();
|
||||
}
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
}
|
||||
// Ctrl+PgUp and Ctrl+PgDown switches tabs in the notebook view
|
||||
if (modifierState & Clutter.ModifierType.CONTROL_MASK) {
|
||||
@ -1073,7 +1074,7 @@ const LookingGlass = new Lang.Class({
|
||||
this._notebook.nextTab();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
},
|
||||
|
||||
open : function() {
|
||||
|
@ -1184,7 +1184,7 @@ const ZoomRegion = new Lang.Class({
|
||||
|
||||
// Clone the group that contains all of UI on the screen. This is the
|
||||
// chrome, the windows, etc.
|
||||
this._uiGroupClone = new Clutter.Clone({ source: Main.uiGroup });
|
||||
this._uiGroupClone = new Clutter.Clone({ source: Main.layoutManager.uiGroup });
|
||||
mainGroup.add_actor(this._uiGroupClone);
|
||||
|
||||
// Add either the given mouseSourceActor to the ZoomRegion, or a clone of
|
||||
|
@ -64,7 +64,6 @@ let screencastService = null;
|
||||
let modalCount = 0;
|
||||
let keybindingMode = Shell.KeyBindingMode.NONE;
|
||||
let modalActorFocusStack = [];
|
||||
let uiGroup = null;
|
||||
let magnifier = null;
|
||||
let xdndHandler = null;
|
||||
let keyboard = null;
|
||||
@ -150,11 +149,6 @@ function _initializeUI() {
|
||||
// Setup the stage hierarchy early
|
||||
layoutManager = new Layout.LayoutManager();
|
||||
|
||||
// Various parts of the codebase still refers to Main.uiGroup
|
||||
// instead using the layoutManager. This keeps that code
|
||||
// working until it's updated.
|
||||
uiGroup = layoutManager.uiGroup;
|
||||
|
||||
screencastService = new Screencast.ScreencastService();
|
||||
xdndHandler = new XdndHandler.XdndHandler();
|
||||
ctrlAltTabManager = new CtrlAltTab.CtrlAltTabManager();
|
||||
@ -172,6 +166,19 @@ function _initializeUI() {
|
||||
windowAttentionHandler = new WindowAttentionHandler.WindowAttentionHandler();
|
||||
componentManager = new Components.ComponentManager();
|
||||
|
||||
if (sessionMode.isGreeter && screenShield) {
|
||||
layoutManager.connect('startup-prepared', function() {
|
||||
screenShield.showDialog();
|
||||
});
|
||||
}
|
||||
|
||||
layoutManager.connect('startup-complete', function() {
|
||||
if (keybindingMode == Shell.KeyBindingMode.NONE)
|
||||
keybindingMode = Shell.KeyBindingMode.NORMAL;
|
||||
if (screenShield)
|
||||
screenShield.lockIfWasLocked();
|
||||
});
|
||||
|
||||
layoutManager.init();
|
||||
overview.init();
|
||||
|
||||
@ -202,21 +209,6 @@ function _initializeUI() {
|
||||
|
||||
ExtensionDownloader.init();
|
||||
ExtensionSystem.init();
|
||||
|
||||
if (sessionMode.isGreeter && screenShield) {
|
||||
layoutManager.connect('startup-prepared', function() {
|
||||
screenShield.showDialog();
|
||||
});
|
||||
}
|
||||
|
||||
layoutManager.connect('startup-complete', function() {
|
||||
if (keybindingMode == Shell.KeyBindingMode.NONE) {
|
||||
keybindingMode = Shell.KeyBindingMode.NORMAL;
|
||||
}
|
||||
if (screenShield) {
|
||||
screenShield.lockIfWasLocked();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function _loadDefaultStylesheet() {
|
||||
@ -609,7 +601,7 @@ function queueDeferredWork(workId) {
|
||||
_deferredTimeoutId = Mainloop.timeout_add_seconds(DEFERRED_TIMEOUT_SECONDS, function () {
|
||||
_runAllDeferredWork();
|
||||
_deferredTimeoutId = 0;
|
||||
return false;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,6 @@ const BoxPointer = imports.ui.boxpointer;
|
||||
const CtrlAltTab = imports.ui.ctrlAltTab;
|
||||
const GnomeSession = imports.misc.gnomeSession;
|
||||
const GrabHelper = imports.ui.grabHelper;
|
||||
const Hash = imports.misc.hash;
|
||||
const Lightbox = imports.ui.lightbox;
|
||||
const Main = imports.ui.main;
|
||||
const PointerWatcher = imports.ui.pointerWatcher;
|
||||
@ -76,7 +75,7 @@ const Urgency = {
|
||||
NORMAL: 1,
|
||||
HIGH: 2,
|
||||
CRITICAL: 3
|
||||
}
|
||||
};
|
||||
|
||||
function _fixMarkup(text, allowMarkup) {
|
||||
if (allowMarkup) {
|
||||
@ -187,7 +186,7 @@ const URLHighlighter = new Lang.Class({
|
||||
// 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 false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
||||
// Keep Notification.actor from seeing this and taking
|
||||
// a pointer grab, which would block our button-release-event
|
||||
@ -196,7 +195,7 @@ const URLHighlighter = new Lang.Class({
|
||||
}));
|
||||
this.actor.connect('button-release-event', Lang.bind(this, function (actor, event) {
|
||||
if (!actor.visible || actor.get_paint_opacity() == 0)
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
||||
let urlId = this._findUrlAtPos(event);
|
||||
if (urlId != -1) {
|
||||
@ -204,14 +203,14 @@ const URLHighlighter = new Lang.Class({
|
||||
if (url.indexOf(':') == -1)
|
||||
url = 'http://' + url;
|
||||
|
||||
Gio.app_info_launch_default_for_uri(url, global.create_app_launch_context());
|
||||
return true;
|
||||
Gio.app_info_launch_default_for_uri(url, global.create_app_launch_context(0, -1));
|
||||
return Clutter.EVENT_STOP;
|
||||
}
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
}));
|
||||
this.actor.connect('motion-event', Lang.bind(this, function(actor, event) {
|
||||
if (!actor.visible || actor.get_paint_opacity() == 0)
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
||||
let urlId = this._findUrlAtPos(event);
|
||||
if (urlId != -1 && !this._cursorChanged) {
|
||||
@ -221,16 +220,17 @@ const URLHighlighter = new Lang.Class({
|
||||
global.screen.set_cursor(Meta.Cursor.DEFAULT);
|
||||
this._cursorChanged = false;
|
||||
}
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
}));
|
||||
this.actor.connect('leave-event', Lang.bind(this, function() {
|
||||
if (!this.actor.visible || this.actor.get_paint_opacity() == 0)
|
||||
return;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
||||
if (this._cursorChanged) {
|
||||
this._cursorChanged = false;
|
||||
global.screen.set_cursor(Meta.Cursor.DEFAULT);
|
||||
}
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
}));
|
||||
},
|
||||
|
||||
@ -1001,6 +1001,9 @@ const Notification = new Lang.Class({
|
||||
Meta.later_add(Meta.LaterType.BEFORE_REDRAW,
|
||||
Lang.bind(this,
|
||||
function() {
|
||||
if (this._destroyed)
|
||||
return false;
|
||||
|
||||
if (this._canExpandContent()) {
|
||||
this._addBannerBody();
|
||||
this._table.add_style_class_name('multi-line-notification');
|
||||
@ -1159,7 +1162,7 @@ const SourceActor = new Lang.Class({
|
||||
}));
|
||||
this._actorDestroyed = false;
|
||||
|
||||
this._counterLabel = new St.Label( {x_align: Clutter.ActorAlign.CENTER,
|
||||
this._counterLabel = new St.Label({ x_align: Clutter.ActorAlign.CENTER,
|
||||
x_expand: true,
|
||||
y_align: Clutter.ActorAlign.CENTER,
|
||||
y_expand: true });
|
||||
@ -1263,7 +1266,6 @@ const Source = new Lang.Class({
|
||||
this.title = title;
|
||||
this.iconName = iconName;
|
||||
|
||||
this.isTransient = false;
|
||||
this.isChat = false;
|
||||
this.isMuted = false;
|
||||
this.keepTrayOnSummaryClick = false;
|
||||
@ -1323,10 +1325,6 @@ const Source = new Lang.Class({
|
||||
return rightClickMenu;
|
||||
},
|
||||
|
||||
setTransient: function(isTransient) {
|
||||
this.isTransient = isTransient;
|
||||
},
|
||||
|
||||
setTitle: function(newTitle) {
|
||||
this.title = newTitle;
|
||||
this.emit('title-changed');
|
||||
@ -1528,9 +1526,9 @@ const SummaryItem = new Lang.Class({
|
||||
_onKeyPress: function(actor, event) {
|
||||
if (event.get_key_symbol() == Clutter.KEY_Up) {
|
||||
actor.emit('clicked', 1);
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
}
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
},
|
||||
|
||||
prepareNotificationStackForShowing: function() {
|
||||
@ -1613,7 +1611,7 @@ const MessageTrayMenu = new Lang.Class({
|
||||
this._accountManager.prepare_async(null, Lang.bind(this, this._onIMPresenceChanged));
|
||||
|
||||
this.actor.hide();
|
||||
Main.layoutManager.addChrome(this.actor);
|
||||
Main.layoutManager.menuGroup.add_child(this.actor);
|
||||
|
||||
this._busyItem = new PopupMenu.PopupSwitchMenuItem(_("Notifications"));
|
||||
this._busyItem.connect('toggled', Lang.bind(this, this._updatePresence));
|
||||
@ -1625,7 +1623,7 @@ const MessageTrayMenu = new Lang.Class({
|
||||
this._clearItem = this.addAction(_("Clear Messages"), function() {
|
||||
let toDestroy = tray.getSources().filter(function(source) {
|
||||
return source.isClearable;
|
||||
})
|
||||
});
|
||||
|
||||
toDestroy.forEach(function(source) {
|
||||
source.destroy();
|
||||
@ -1788,6 +1786,7 @@ const MessageTray = new Lang.Class({
|
||||
this._setClickedSummaryItem(null);
|
||||
this._updateState();
|
||||
actor.grab_key_focus();
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
}));
|
||||
global.focus_manager.add_group(this.actor);
|
||||
this._summary = new St.BoxLayout({ style_class: 'message-tray-summary',
|
||||
@ -1902,7 +1901,7 @@ const MessageTray = new Lang.Class({
|
||||
Shell.KeyBindingMode.OVERVIEW,
|
||||
Lang.bind(this, this._expandActiveNotification));
|
||||
|
||||
this._sources = new Hash.Map();
|
||||
this._sources = new Map();
|
||||
this._chatSummaryItemsCount = 0;
|
||||
|
||||
this._trayDwellTimeoutId = 0;
|
||||
@ -1939,7 +1938,7 @@ const MessageTray = new Lang.Class({
|
||||
},
|
||||
|
||||
_updateNoMessagesLabel: function() {
|
||||
this._noMessages.visible = this._sources.size() == 0;
|
||||
this._noMessages.visible = this._sources.size == 0;
|
||||
},
|
||||
|
||||
_sessionUpdated: function() {
|
||||
@ -1993,32 +1992,32 @@ const MessageTray = new Lang.Class({
|
||||
this._trayDwellTimeoutId = 0;
|
||||
|
||||
if (Main.layoutManager.bottomMonitor.inFullscreen)
|
||||
return false;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
|
||||
// We don't want to open the tray when a modal dialog
|
||||
// is up, so we check the modal count for that. When we are in the
|
||||
// overview we have to take the overview's modal push into account
|
||||
if (Main.modalCount > (Main.overview.visible ? 1 : 0))
|
||||
return false;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
|
||||
// If the user interacted with the focus window since we started the tray
|
||||
// dwell (by clicking or typing), don't activate the message tray
|
||||
let focusWindow = global.display.focus_window;
|
||||
let currentUserTime = focusWindow ? focusWindow.user_time : 0;
|
||||
if (currentUserTime != this._trayDwellUserTime)
|
||||
return false;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
|
||||
this.openTray();
|
||||
return false;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
},
|
||||
|
||||
_onNotificationKeyRelease: function(actor, event) {
|
||||
if (event.get_key_symbol() == Clutter.KEY_Escape && event.get_state() == 0) {
|
||||
this._closeNotification();
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
}
|
||||
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
},
|
||||
|
||||
_closeNotification: function() {
|
||||
@ -2102,7 +2101,8 @@ const MessageTray = new Lang.Class({
|
||||
},
|
||||
|
||||
_removeSource: function(source) {
|
||||
let [, obj] = this._sources.delete(source);
|
||||
let obj = this._sources.get(source);
|
||||
this._sources.delete(source);
|
||||
let summaryItem = obj.summaryItem;
|
||||
|
||||
if (source.isChat)
|
||||
@ -2123,7 +2123,7 @@ const MessageTray = new Lang.Class({
|
||||
},
|
||||
|
||||
getSources: function() {
|
||||
return this._sources.keys();
|
||||
return [k for (k of this._sources.keys())];
|
||||
},
|
||||
|
||||
_onSourceEnableChanged: function(policy, source) {
|
||||
@ -2339,7 +2339,7 @@ const MessageTray = new Lang.Class({
|
||||
this._updateNotificationTimeout(0);
|
||||
this._updateState();
|
||||
}
|
||||
return false;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
},
|
||||
|
||||
_escapeTray: function() {
|
||||
@ -2356,6 +2356,13 @@ const MessageTray = new Lang.Class({
|
||||
// _updateState() figures out what (if anything) needs to be done
|
||||
// at the present time.
|
||||
_updateState: function() {
|
||||
// If our state changes caused _updateState to be called,
|
||||
// just exit now to prevent reentrancy issues.
|
||||
if (this._updatingState)
|
||||
return;
|
||||
|
||||
this._updatingState = true;
|
||||
|
||||
// Filter out acknowledged notifications.
|
||||
this._notificationQueue = this._notificationQueue.filter(function(n) {
|
||||
return !n.acknowledged;
|
||||
@ -2375,7 +2382,7 @@ const MessageTray = new Lang.Class({
|
||||
} else if (this._notificationState == State.SHOWN) {
|
||||
let expired = (this._userActiveWhileNotificationShown &&
|
||||
this._notificationTimeoutId == 0 &&
|
||||
!(this._notification.urgency == Urgency.CRITICAL) &&
|
||||
this._notification.urgency != Urgency.CRITICAL &&
|
||||
!this._notification.focused &&
|
||||
!this._pointerInNotification);
|
||||
let mustClose = (this._notificationRemoved || !hasNotifications || expired || this._traySummoned);
|
||||
@ -2432,11 +2439,12 @@ const MessageTray = new Lang.Class({
|
||||
this._desktopCloneState == State.SHOWN);
|
||||
let desktopCloneShouldBeVisible = (trayShouldBeVisible);
|
||||
|
||||
if (!desktopCloneIsVisible && desktopCloneShouldBeVisible) {
|
||||
if (!desktopCloneIsVisible && desktopCloneShouldBeVisible)
|
||||
this._showDesktopClone();
|
||||
} else if (desktopCloneIsVisible && !desktopCloneShouldBeVisible) {
|
||||
else if (desktopCloneIsVisible && !desktopCloneShouldBeVisible)
|
||||
this._hideDesktopClone();
|
||||
}
|
||||
|
||||
this._updatingState = false;
|
||||
},
|
||||
|
||||
_tween: function(actor, statevar, value, params) {
|
||||
@ -2504,7 +2512,7 @@ const MessageTray = new Lang.Class({
|
||||
let cloneSource = Main.overview.visible ? Main.layoutManager.overviewGroup : global.window_group;
|
||||
this._desktopClone = new Clutter.Clone({ source: cloneSource,
|
||||
clip: new Clutter.Geometry(this._bottomMonitorGeometry) });
|
||||
Main.uiGroup.insert_child_above(this._desktopClone, cloneSource);
|
||||
Main.layoutManager.sessionGroup.insert_child_above(this._desktopClone, cloneSource);
|
||||
this._desktopClone.x = 0;
|
||||
this._desktopClone.y = 0;
|
||||
this._desktopClone.show();
|
||||
@ -2664,7 +2672,7 @@ const MessageTray = new Lang.Class({
|
||||
|
||||
this._lastSeenMouseX = x;
|
||||
this._lastSeenMouseY = y;
|
||||
return false;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
},
|
||||
|
||||
_hideNotification: function(animate) {
|
||||
@ -2801,13 +2809,13 @@ const MessageTray = new Lang.Class({
|
||||
Lang.bind(this, this._onSourceDoneDisplayingContent));
|
||||
|
||||
this._summaryBoxPointer.bin.child = child;
|
||||
this._grabHelper.grab({ actor: this._summaryBoxPointer.bin.child,
|
||||
onUngrab: Lang.bind(this, this._onSummaryBoxPointerUngrabbed) });
|
||||
|
||||
this._summaryBoxPointer.actor.opacity = 0;
|
||||
this._summaryBoxPointer.actor.show();
|
||||
this._adjustSummaryBoxPointerPosition();
|
||||
|
||||
this._grabHelper.grab({ actor: this._summaryBoxPointer.bin.child,
|
||||
onUngrab: Lang.bind(this, this._onSummaryBoxPointerUngrabbed) });
|
||||
|
||||
this._summaryBoxPointerState = State.SHOWING;
|
||||
this._summaryBoxPointer.show(BoxPointer.PopupAnimation.FULL, Lang.bind(this, function() {
|
||||
this._summaryBoxPointerState = State.SHOWN;
|
||||
@ -2862,13 +2870,13 @@ const MessageTray = new Lang.Class({
|
||||
case Clutter.KEY_Escape:
|
||||
this._setClickedSummaryItem(null);
|
||||
this._updateState();
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
case Clutter.KEY_Delete:
|
||||
this._clickedSummaryItem.source.destroy();
|
||||
this._escapeTray();
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
}
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
},
|
||||
|
||||
_onSummaryBoxPointerUngrabbed: function() {
|
||||
@ -2906,8 +2914,6 @@ const MessageTray = new Lang.Class({
|
||||
this._summaryBoxPointerItem.doneShowingNotificationStack();
|
||||
this._summaryBoxPointerItem = null;
|
||||
|
||||
if (source.isTransient && !this._reNotifyAfterHideNotification)
|
||||
source.destroy(NotificationDestroyedReason.EXPIRED);
|
||||
if (this._reNotifyAfterHideNotification) {
|
||||
this._onNotify(this._reNotifyAfterHideNotification.source, this._reNotifyAfterHideNotification);
|
||||
this._reNotifyAfterHideNotification = null;
|
||||
@ -2926,7 +2932,6 @@ const SystemNotificationSource = new Lang.Class({
|
||||
|
||||
_init: function() {
|
||||
this.parent(_("System Information"), 'dialog-information-symbolic');
|
||||
this.setTransient(true);
|
||||
},
|
||||
|
||||
open: function() {
|
||||
|
@ -41,7 +41,7 @@ const ModalDialog = new Lang.Class({
|
||||
_init: function(params) {
|
||||
params = Params.parse(params, { shellReactive: false,
|
||||
styleClass: null,
|
||||
parentActor: Main.uiGroup,
|
||||
parentActor: Main.layoutManager.dialogGroup,
|
||||
keybindingMode: Shell.KeyBindingMode.SYSTEM_MODAL,
|
||||
shouldFadeIn: true,
|
||||
destroyOnClose: true });
|
||||
@ -89,7 +89,8 @@ const ModalDialog = new Lang.Class({
|
||||
|
||||
if (!this._shellReactive) {
|
||||
this._lightbox = new Lightbox.Lightbox(this._group,
|
||||
{ inhibitEvents: true });
|
||||
{ inhibitEvents: true,
|
||||
radialEffect: true });
|
||||
this._lightbox.highlight(this._backgroundBin);
|
||||
|
||||
this._eventBlocker = new Clutter.Actor({ reactive: true });
|
||||
@ -229,6 +230,7 @@ const ModalDialog = new Lang.Class({
|
||||
|
||||
_onKeyPressEvent: function(object, event) {
|
||||
this._pressedKey = event.get_key_symbol();
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
},
|
||||
|
||||
_onKeyReleaseEvent: function(object, event) {
|
||||
@ -237,21 +239,21 @@ const ModalDialog = new Lang.Class({
|
||||
|
||||
let symbol = event.get_key_symbol();
|
||||
if (symbol != pressedKey)
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
||||
let buttonInfo = this._buttonKeys[symbol];
|
||||
if (!buttonInfo)
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
||||
let button = buttonInfo['button'];
|
||||
let action = buttonInfo['action'];
|
||||
|
||||
if (action && button.reactive) {
|
||||
action();
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
}
|
||||
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
},
|
||||
|
||||
_onGroupDestroy: function() {
|
||||
|
@ -181,12 +181,10 @@ const FdoNotificationDaemon = new Lang.Class({
|
||||
},
|
||||
|
||||
// Returns the source associated with ndata.notification if it is set.
|
||||
// Otherwise, returns the source associated with the title and pid if
|
||||
// such source is stored in this._sources and the notification is not
|
||||
// transient. If the existing or requested source is associated with
|
||||
// a tray icon and passed in pid matches a pid of an existing source,
|
||||
// the title match is ignored to enable representing a tray icon and
|
||||
// notifications from the same application with a single source.
|
||||
// If the existing or requested source is associated with a tray icon
|
||||
// and passed in pid matches a pid of an existing source, the title
|
||||
// match is ignored to enable representing a tray icon and notifications
|
||||
// from the same application with a single source.
|
||||
//
|
||||
// If no existing source is found, a new source is created as long as
|
||||
// pid is provided.
|
||||
@ -204,32 +202,20 @@ const FdoNotificationDaemon = new Lang.Class({
|
||||
if (ndata && ndata.notification)
|
||||
return ndata.notification.source;
|
||||
|
||||
let isForTransientNotification = (ndata && ndata.hints['transient'] == true);
|
||||
|
||||
// We don't want to override a persistent notification
|
||||
// with a transient one from the same sender, so we
|
||||
// always create a new source object for new transient notifications
|
||||
// and never add it to this._sources .
|
||||
if (!isForTransientNotification) {
|
||||
let source = this._lookupSource(title, pid, trayIcon);
|
||||
if (source) {
|
||||
source.setTitle(title);
|
||||
return source;
|
||||
}
|
||||
let source = this._lookupSource(title, pid, trayIcon);
|
||||
if (source) {
|
||||
source.setTitle(title);
|
||||
return source;
|
||||
}
|
||||
|
||||
let source = new FdoNotificationDaemonSource(title, pid, sender, trayIcon, ndata ? ndata.hints['desktop-entry'] : null);
|
||||
source.setTransient(isForTransientNotification);
|
||||
|
||||
if (!isForTransientNotification) {
|
||||
this._sources.push(source);
|
||||
source.connect('destroy', Lang.bind(this,
|
||||
function() {
|
||||
let index = this._sources.indexOf(source);
|
||||
if (index >= 0)
|
||||
this._sources.splice(index, 1);
|
||||
}));
|
||||
}
|
||||
this._sources.push(source);
|
||||
source.connect('destroy', Lang.bind(this, function() {
|
||||
let index = this._sources.indexOf(source);
|
||||
if (index >= 0)
|
||||
this._sources.splice(index, 1);
|
||||
}));
|
||||
|
||||
Main.messageTray.add(source);
|
||||
return source;
|
||||
@ -261,7 +247,7 @@ const FdoNotificationDaemon = new Lang.Class({
|
||||
Mainloop.idle_add(Lang.bind(this,
|
||||
function () {
|
||||
this._emitNotificationClosed(id, NotificationClosedReason.DISMISSED);
|
||||
return false;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
}));
|
||||
return invocation.return_value(GLib.Variant.new('(u)', [id]));
|
||||
}
|
||||
@ -336,20 +322,10 @@ const FdoNotificationDaemon = new Lang.Class({
|
||||
let [pid] = result;
|
||||
source = this._getSource(appName, pid, ndata, sender, null);
|
||||
|
||||
// We only store sender-pid entries for persistent sources.
|
||||
// Removing the entries once the source is destroyed
|
||||
// would result in the entries associated with transient
|
||||
// sources removed once the notification is shown anyway.
|
||||
// However, keeping these pairs would mean that we would
|
||||
// possibly remove an entry associated with a persistent
|
||||
// source when a transient source for the same sender is
|
||||
// distroyed.
|
||||
if (!source.isTransient) {
|
||||
this._senderToPid[sender] = pid;
|
||||
source.connect('destroy', Lang.bind(this, function() {
|
||||
delete this._senderToPid[sender];
|
||||
}));
|
||||
}
|
||||
this._senderToPid[sender] = pid;
|
||||
source.connect('destroy', Lang.bind(this, function() {
|
||||
delete this._senderToPid[sender];
|
||||
}));
|
||||
this._notifyForSource(source, ndata);
|
||||
}));
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const GLib = imports.gi.GLib;
|
||||
const St = imports.gi.St;
|
||||
|
||||
const Lang = imports.lang;
|
||||
@ -65,6 +66,7 @@ const LevelBar = new Lang.Class({
|
||||
cr.arc(radius, h - radius, radius, 0.5 * Math.PI, Math.PI);
|
||||
cr.arc(radius, radius, radius, Math.PI, 1.5 * Math.PI);
|
||||
cr.fill();
|
||||
cr.$dispose();
|
||||
}
|
||||
});
|
||||
|
||||
@ -77,7 +79,8 @@ const OsdWindow = new Lang.Class({
|
||||
y_expand: true,
|
||||
x_align: Clutter.ActorAlign.CENTER,
|
||||
y_align: Clutter.ActorAlign.CENTER });
|
||||
this.actor.add_constraint(new Layout.MonitorConstraint({ primary: true }));
|
||||
this._currentMonitor = undefined;
|
||||
this.setMonitor (-1);
|
||||
this._box = new St.BoxLayout({ style_class: 'osd-window',
|
||||
vertical: true });
|
||||
this.actor.add_actor(this._box);
|
||||
@ -107,7 +110,7 @@ const OsdWindow = new Lang.Class({
|
||||
Lang.bind(this, this._monitorsChanged));
|
||||
this._monitorsChanged();
|
||||
|
||||
Main.uiGroup.add_child(this.actor);
|
||||
Main.layoutManager.osdGroup.add_child(this.actor);
|
||||
},
|
||||
|
||||
setIcon: function(icon) {
|
||||
@ -122,13 +125,15 @@ const OsdWindow = new Lang.Class({
|
||||
|
||||
setLevel: function(level) {
|
||||
this._level.actor.visible = (level != undefined);
|
||||
if (this.actor.visible)
|
||||
Tweener.addTween(this._level,
|
||||
{ level: level,
|
||||
time: LEVEL_ANIMATION_TIME,
|
||||
transition: 'easeOutQuad' });
|
||||
else
|
||||
this._level.level = level;
|
||||
if (level) {
|
||||
if (this.actor.visible)
|
||||
Tweener.addTween(this._level,
|
||||
{ level: level,
|
||||
time: LEVEL_ANIMATION_TIME,
|
||||
transition: 'easeOutQuad' });
|
||||
else
|
||||
this._level.level = level;
|
||||
}
|
||||
},
|
||||
|
||||
show: function() {
|
||||
@ -172,6 +177,7 @@ const OsdWindow = new Lang.Class({
|
||||
Meta.enable_unredirect_for_screen(global.screen);
|
||||
})
|
||||
});
|
||||
return GLib.SOURCE_REMOVE;
|
||||
},
|
||||
|
||||
_reset: function() {
|
||||
@ -182,7 +188,13 @@ const OsdWindow = new Lang.Class({
|
||||
|
||||
_monitorsChanged: function() {
|
||||
/* assume 110x110 on a 640x480 display and scale from there */
|
||||
let monitor = Main.layoutManager.primaryMonitor;
|
||||
let monitor;
|
||||
|
||||
if (this._currentMonitor >= 0)
|
||||
monitor = Main.layoutManager.monitors[this._currentMonitor];
|
||||
else
|
||||
monitor = Main.layoutManager.primaryMonitor;
|
||||
|
||||
let scalew = monitor.width / 640.0;
|
||||
let scaleh = monitor.height / 480.0;
|
||||
let scale = Math.min(scalew, scaleh);
|
||||
@ -206,5 +218,23 @@ const OsdWindow = new Lang.Class({
|
||||
let minHeight = this._popupSize - horizontalPadding - topBorder - bottomBorder;
|
||||
|
||||
this._box.style = 'min-height: %dpx;'.format(Math.max(minWidth, minHeight));
|
||||
},
|
||||
|
||||
setMonitor: function(index) {
|
||||
let constraint;
|
||||
|
||||
if (index < 0)
|
||||
index = -1;
|
||||
if (this._currentMonitor == index)
|
||||
return;
|
||||
|
||||
if (index < 0)
|
||||
constraint = new Layout.MonitorConstraint({ primary: true });
|
||||
else
|
||||
constraint = new Layout.MonitorConstraint({ index: index });
|
||||
|
||||
this.actor.clear_constraints();
|
||||
this.actor.add_constraint(constraint);
|
||||
this._currentMonitor = index;
|
||||
}
|
||||
});
|
||||
|
@ -1,6 +1,7 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Mainloop = imports.mainloop;
|
||||
@ -112,9 +113,6 @@ const Overview = new Lang.Class({
|
||||
// rendering options without duplicating the texture data.
|
||||
let monitor = Main.layoutManager.primaryMonitor;
|
||||
|
||||
this._desktopFade = new St.Bin();
|
||||
Main.layoutManager.overviewGroup.add_child(this._desktopFade);
|
||||
|
||||
let layout = new Clutter.BinLayout();
|
||||
this._stack = new Clutter.Actor({ layout_manager: layout });
|
||||
this._stack.add_constraint(new LayoutManager.MonitorConstraint({ primary: true }));
|
||||
@ -133,6 +131,9 @@ const Overview = new Lang.Class({
|
||||
Main.layoutManager.overviewGroup.add_child(this._backgroundGroup);
|
||||
this._bgManagers = [];
|
||||
|
||||
this._desktopFade = new St.Widget();
|
||||
Main.layoutManager.overviewGroup.add_child(this._desktopFade);
|
||||
|
||||
this._activationTime = 0;
|
||||
|
||||
this.visible = false; // animating to overview, in overview, animating out
|
||||
@ -147,7 +148,7 @@ const Overview = new Lang.Class({
|
||||
this._coverPane = new Clutter.Actor({ opacity: 0,
|
||||
reactive: true });
|
||||
Main.layoutManager.overviewGroup.add_child(this._coverPane);
|
||||
this._coverPane.connect('event', Lang.bind(this, function (actor, event) { return true; }));
|
||||
this._coverPane.connect('event', Lang.bind(this, function (actor, event) { return Clutter.EVENT_STOP; }));
|
||||
|
||||
this._stack.add_actor(this._overview);
|
||||
Main.layoutManager.overviewGroup.add_child(this._stack);
|
||||
@ -369,7 +370,7 @@ const Overview = new Lang.Class({
|
||||
this._windowSwitchTimestamp);
|
||||
this.hide();
|
||||
this._lastHoveredWindow = null;
|
||||
return false;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
}));
|
||||
}
|
||||
|
||||
@ -378,6 +379,7 @@ const Overview = new Lang.Class({
|
||||
|
||||
_onScrollEvent: function(actor, event) {
|
||||
this.emit('scroll-event', event);
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
},
|
||||
|
||||
addAction: function(action) {
|
||||
@ -491,8 +493,8 @@ const Overview = new Lang.Class({
|
||||
},
|
||||
|
||||
fadeOutDesktop: function() {
|
||||
if (!this._desktopFade.child)
|
||||
this._desktopFade.child = this._getDesktopClone();
|
||||
if (!this._desktopFade.get_n_children())
|
||||
this._desktopFade.add_child(this._getDesktopClone());
|
||||
|
||||
this._desktopFade.opacity = 255;
|
||||
this._desktopFade.show();
|
||||
@ -620,7 +622,7 @@ const Overview = new Lang.Class({
|
||||
this.animationInProgress = true;
|
||||
this.visibleTarget = false;
|
||||
|
||||
this.viewSelector.zoomFromOverview();
|
||||
this.viewSelector.leaveOverview();
|
||||
|
||||
// Make other elements fade out.
|
||||
Tweener.addTween(this._stack,
|
||||
|
@ -460,9 +460,6 @@ const MessagesIndicator = new Lang.Class({
|
||||
if (source.trayIcon)
|
||||
return;
|
||||
|
||||
if (source.isTransient)
|
||||
return;
|
||||
|
||||
source.connect('count-updated', Lang.bind(this, this._updateCount));
|
||||
this._sources.push(source);
|
||||
this._updateCount();
|
||||
|
@ -602,14 +602,15 @@ const ActivitiesButton = new Lang.Class({
|
||||
_onCapturedEvent: function(actor, event) {
|
||||
if (event.type() == Clutter.EventType.BUTTON_PRESS) {
|
||||
if (!Main.overview.shouldToggleByCornerOrButton())
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
}
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
},
|
||||
|
||||
_onButtonRelease: function() {
|
||||
Main.overview.toggle();
|
||||
this.menu.close();
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
},
|
||||
|
||||
_onKeyRelease: function(actor, event) {
|
||||
@ -617,6 +618,7 @@ const ActivitiesButton = new Lang.Class({
|
||||
if (symbol == Clutter.KEY_Return || symbol == Clutter.KEY_space) {
|
||||
Main.overview.toggle();
|
||||
}
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
},
|
||||
|
||||
_xdndToggleOverview: function(actor) {
|
||||
@ -628,6 +630,7 @@ const ActivitiesButton = new Lang.Class({
|
||||
|
||||
Mainloop.source_remove(this._xdndTimeOut);
|
||||
this._xdndTimeOut = 0;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
}
|
||||
});
|
||||
|
||||
@ -822,8 +825,10 @@ const AggregateMenu = new Lang.Class({
|
||||
this._brightness = new imports.ui.status.brightness.Indicator();
|
||||
this._system = new imports.ui.status.system.Indicator();
|
||||
this._screencast = new imports.ui.status.screencast.Indicator();
|
||||
this._location = new imports.ui.status.location.Indicator();
|
||||
|
||||
this._indicators.add_child(this._screencast.indicators);
|
||||
this._indicators.add_child(this._location.indicators);
|
||||
this._indicators.add_child(this._network.indicators);
|
||||
if (this._bluetooth) {
|
||||
this._indicators.add_child(this._bluetooth.indicators);
|
||||
@ -896,7 +901,7 @@ const Panel = new Lang.Class({
|
||||
this.actor.remove_style_pseudo_class('overview');
|
||||
}));
|
||||
|
||||
Main.layoutManager.panelBox.add(this.actor);
|
||||
Main.layoutManager.panelGroup.add_child(this.actor);
|
||||
Main.ctrlAltTabManager.addGroup(this.actor, _("Top Bar"), 'emblem-system-symbolic',
|
||||
{ sortGroup: CtrlAltTab.SortGroup.TOP });
|
||||
|
||||
@ -983,23 +988,23 @@ const Panel = new Lang.Class({
|
||||
|
||||
_onButtonPress: function(actor, event) {
|
||||
if (Main.modalCount > 0)
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
||||
if (event.get_source() != actor)
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
||||
let button = event.get_button();
|
||||
if (button != 1)
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
||||
let focusWindow = global.display.focus_window;
|
||||
if (!focusWindow)
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
||||
let dragWindow = focusWindow.is_attached_dialog() ? focusWindow.get_transient_for()
|
||||
: focusWindow;
|
||||
if (!dragWindow)
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
||||
let rect = dragWindow.get_outer_rect();
|
||||
let [stageX, stageY] = event.get_coords();
|
||||
@ -1008,7 +1013,7 @@ const Panel = new Lang.Class({
|
||||
stageX > rect.x && stageX < rect.x + rect.width;
|
||||
|
||||
if (!allowDrag)
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
||||
global.display.begin_grab_op(global.screen,
|
||||
dragWindow,
|
||||
@ -1020,7 +1025,7 @@ const Panel = new Lang.Class({
|
||||
event.get_time(),
|
||||
stageX, stageY);
|
||||
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
},
|
||||
|
||||
toggleAppMenu: function() {
|
||||
|
@ -130,36 +130,37 @@ const Button = new Lang.Class({
|
||||
this.menu.connect('open-state-changed', Lang.bind(this, this._onOpenStateChanged));
|
||||
this.menu.actor.connect('key-press-event', Lang.bind(this, this._onMenuKeyPress));
|
||||
|
||||
Main.uiGroup.add_actor(this.menu.actor);
|
||||
Main.layoutManager.menuGroup.add_child(this.menu.actor);
|
||||
this.menu.actor.hide();
|
||||
}
|
||||
},
|
||||
|
||||
_onButtonPress: function(actor, event) {
|
||||
if (!this.menu)
|
||||
return;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
||||
this.menu.toggle();
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
},
|
||||
|
||||
_onSourceKeyPress: function(actor, event) {
|
||||
if (!this.menu)
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
||||
let symbol = event.get_key_symbol();
|
||||
if (symbol == Clutter.KEY_space || symbol == Clutter.KEY_Return) {
|
||||
this.menu.toggle();
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
} else if (symbol == Clutter.KEY_Escape && this.menu.isOpen) {
|
||||
this.menu.close();
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
} else if (symbol == Clutter.KEY_Down) {
|
||||
if (!this.menu.isOpen)
|
||||
this.menu.toggle();
|
||||
this.menu.actor.navigate_focus(this.actor, Gtk.DirectionType.DOWN, false);
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
} else
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
},
|
||||
|
||||
_onVisibilityChanged: function() {
|
||||
@ -172,7 +173,7 @@ const Button = new Lang.Class({
|
||||
|
||||
_onMenuKeyPress: function(actor, event) {
|
||||
if (global.focus_manager.navigate_from_event(event))
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
|
||||
let symbol = event.get_key_symbol();
|
||||
if (symbol == Clutter.KEY_Left || symbol == Clutter.KEY_Right) {
|
||||
@ -180,10 +181,10 @@ const Button = new Lang.Class({
|
||||
if (group) {
|
||||
let direction = (symbol == Clutter.KEY_Left) ? Gtk.DirectionType.LEFT : Gtk.DirectionType.RIGHT;
|
||||
group.navigate_focus(this.actor, direction, false);
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
},
|
||||
|
||||
_onOpenStateChanged: function(menu, open) {
|
||||
|
@ -1,5 +1,6 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const GLib = imports.gi.GLib;
|
||||
const Lang = imports.lang;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Meta = imports.gi.Meta;
|
||||
@ -110,7 +111,7 @@ const PointerWatcher = new Lang.Class({
|
||||
|
||||
_onTimeout: function() {
|
||||
this._updatePointer();
|
||||
return true;
|
||||
return GLib.SOURCE_CONTINUE;
|
||||
},
|
||||
|
||||
_updatePointer: function() {
|
||||
|
@ -126,7 +126,7 @@ const PopupBaseMenuItem = new Lang.Class({
|
||||
|
||||
_onButtonReleaseEvent: function (actor, event) {
|
||||
this.activate(event);
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
},
|
||||
|
||||
_onKeyPressEvent: function (actor, event) {
|
||||
@ -134,9 +134,9 @@ const PopupBaseMenuItem = new Lang.Class({
|
||||
|
||||
if (symbol == Clutter.KEY_space || symbol == Clutter.KEY_Return) {
|
||||
this.activate(event);
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
}
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
},
|
||||
|
||||
_onKeyFocusIn: function (actor) {
|
||||
@ -928,10 +928,10 @@ const PopupSubMenu = new Lang.Class({
|
||||
if (this.isOpen && event.get_key_symbol() == Clutter.KEY_Left) {
|
||||
this.close(BoxPointer.PopupAnimation.FULL);
|
||||
this.sourceActor._delegate.setActive(true);
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
}
|
||||
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
}
|
||||
});
|
||||
|
||||
@ -1056,10 +1056,10 @@ const PopupSubMenuMenuItem = new Lang.Class({
|
||||
if (symbol == Clutter.KEY_Right) {
|
||||
this._setOpenState(true);
|
||||
this.menu.actor.navigate_focus(null, Gtk.DirectionType.DOWN, false);
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
} else if (symbol == Clutter.KEY_Left && this._getOpenState()) {
|
||||
this._setOpenState(false);
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
}
|
||||
|
||||
return this.parent(actor, event);
|
||||
@ -1071,6 +1071,7 @@ const PopupSubMenuMenuItem = new Lang.Class({
|
||||
|
||||
_onButtonReleaseEvent: function(actor) {
|
||||
this._setOpenState(!this._getOpenState());
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
}
|
||||
});
|
||||
|
||||
@ -1102,7 +1103,7 @@ const PopupMenuManager = new Lang.Class({
|
||||
if (source) {
|
||||
if (!menu.blockSourceEvents)
|
||||
this._grabHelper.addActor(source);
|
||||
menudata.enterId = source.connect('enter-event', Lang.bind(this, function() { this._onMenuSourceEnter(menu); }));
|
||||
menudata.enterId = source.connect('enter-event', Lang.bind(this, function() { return this._onMenuSourceEnter(menu); }));
|
||||
menudata.focusInId = source.connect('key-focus-in', Lang.bind(this, function() { this._onMenuSourceEnter(menu); }));
|
||||
}
|
||||
|
||||
@ -1164,13 +1165,13 @@ const PopupMenuManager = new Lang.Class({
|
||||
|
||||
_onMenuSourceEnter: function(menu) {
|
||||
if (!this._grabHelper.grabbed)
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
||||
if (this._grabHelper.isActorGrabbed(menu.actor))
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
||||
this._changeMenu(menu);
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
},
|
||||
|
||||
_onMenuDestroy: function(menu) {
|
||||
|
@ -191,7 +191,9 @@ const RemoteSearchProvider = new Lang.Class({
|
||||
},
|
||||
|
||||
createIcon: function(size, meta) {
|
||||
let gicon;
|
||||
let gicon = null;
|
||||
let icon = null;
|
||||
|
||||
if (meta['icon']) {
|
||||
gicon = Gio.icon_deserialize(meta['icon']);
|
||||
} else if (meta['gicon']) {
|
||||
@ -203,8 +205,10 @@ const RemoteSearchProvider = new Lang.Class({
|
||||
bitsPerSample, width, height, rowStride);
|
||||
}
|
||||
|
||||
return new St.Icon({ gicon: gicon,
|
||||
icon_size: size });
|
||||
if (gicon)
|
||||
icon = new St.Icon({ gicon: gicon,
|
||||
icon_size: size });
|
||||
return icon;
|
||||
},
|
||||
|
||||
filterResults: function(results, maxNumber) {
|
||||
@ -279,7 +283,7 @@ const RemoteSearchProvider = new Lang.Class({
|
||||
// the provider is not compatible with the new version of the interface, launch
|
||||
// the app itself but warn so we can catch the error in logs
|
||||
log('Search provider ' + this.appInfo.get_id() + ' does not implement LaunchSearch');
|
||||
this.appInfo.launch([], global.create_app_launch_context());
|
||||
this.appInfo.launch([], global.create_app_launch_context(0, -1));
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -73,7 +73,9 @@ const RunDialog = new Lang.Class({
|
||||
let label = new St.Label({ style_class: 'run-dialog-label',
|
||||
text: _("Enter a Command") });
|
||||
|
||||
this.contentLayout.add(label, { y_align: St.Align.START });
|
||||
this.contentLayout.add(label, { x_fill: false,
|
||||
x_align: St.Align.START,
|
||||
y_align: St.Align.START });
|
||||
|
||||
let entry = new St.Entry({ style_class: 'run-dialog-entry',
|
||||
can_focus: true });
|
||||
@ -101,6 +103,8 @@ const RunDialog = new Lang.Class({
|
||||
this._errorMessage.clutter_text.line_wrap = true;
|
||||
|
||||
this._errorBox.add(this._errorMessage, { expand: true,
|
||||
x_align: St.Align.START,
|
||||
x_fill: false,
|
||||
y_align: St.Align.MIDDLE,
|
||||
y_fill: false });
|
||||
|
||||
@ -124,7 +128,7 @@ const RunDialog = new Lang.Class({
|
||||
!this.pushModal())
|
||||
this.close();
|
||||
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
}
|
||||
if (symbol == Clutter.Tab) {
|
||||
let text = o.get_text();
|
||||
@ -138,9 +142,9 @@ const RunDialog = new Lang.Class({
|
||||
o.insert_text(postfix, -1);
|
||||
o.set_cursor_position(text.length + postfix.length);
|
||||
}
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
}
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
}));
|
||||
},
|
||||
|
||||
@ -229,7 +233,7 @@ const RunDialog = new Lang.Class({
|
||||
let file = Gio.file_new_for_path(path);
|
||||
try {
|
||||
Gio.app_info_launch_default_for_uri(file.get_uri(),
|
||||
global.create_app_launch_context());
|
||||
global.create_app_launch_context(0, -1));
|
||||
} catch (e) {
|
||||
// The exception from gjs contains an error string like:
|
||||
// Error invoking Gio.app_info_launch_default_for_uri: No application
|
||||
|
@ -17,7 +17,6 @@ const TweenerEquations = imports.tweener.equations;
|
||||
|
||||
const Background = imports.ui.background;
|
||||
const GnomeSession = imports.misc.gnomeSession;
|
||||
const Hash = imports.misc.hash;
|
||||
const Layout = imports.ui.layout;
|
||||
const OVirt = imports.gdm.oVirt;
|
||||
const LoginManager = imports.misc.loginManager;
|
||||
@ -115,7 +114,7 @@ const NotificationsBox = new Lang.Class({
|
||||
this.actor.add(this._musicBin);
|
||||
this.actor.add(this._scrollView, { x_fill: true, x_align: St.Align.START });
|
||||
|
||||
this._sources = new Hash.Map();
|
||||
this._sources = new Map();
|
||||
Main.messageTray.getSources().forEach(Lang.bind(this, function(source) {
|
||||
this._sourceAdded(Main.messageTray, source, true);
|
||||
}));
|
||||
@ -130,9 +129,8 @@ const NotificationsBox = new Lang.Class({
|
||||
this._sourceAddedId = 0;
|
||||
}
|
||||
|
||||
let items = this._sources.items();
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
let [source, obj] = items[i];
|
||||
let items = this._sources.entries();
|
||||
for (let [source, obj] of items) {
|
||||
this._removeSource(source, obj);
|
||||
}
|
||||
|
||||
@ -240,10 +238,6 @@ const NotificationsBox = new Lang.Class({
|
||||
},
|
||||
|
||||
_sourceAdded: function(tray, source, initial) {
|
||||
// Ignore transient sources
|
||||
if (source.isTransient)
|
||||
return;
|
||||
|
||||
let obj = {
|
||||
visible: source.policy.showInLockScreen,
|
||||
detailed: source.policy.detailsInLockScreen,
|
||||
@ -419,6 +413,7 @@ const Arrow = new Lang.Class({
|
||||
cr.lineTo(w/2, thickness);
|
||||
cr.lineTo(w - thickness / 2, h - thickness / 2);
|
||||
cr.stroke();
|
||||
cr.$dispose();
|
||||
},
|
||||
|
||||
vfunc_style_changed: function() {
|
||||
@ -461,8 +456,6 @@ const ScreenShield = new Lang.Class({
|
||||
Name: 'ScreenShield',
|
||||
|
||||
_init: function() {
|
||||
this.actor = Main.layoutManager.screenShieldGroup;
|
||||
|
||||
this._lockScreenState = MessageTray.State.HIDDEN;
|
||||
this._lockScreenGroup = new St.Widget({ x_expand: true,
|
||||
y_expand: true,
|
||||
@ -471,6 +464,7 @@ const ScreenShield = new Lang.Class({
|
||||
name: 'lockScreenGroup',
|
||||
visible: false,
|
||||
});
|
||||
|
||||
this._lockScreenGroup.connect('key-press-event',
|
||||
Lang.bind(this, this._onLockScreenKeyPress));
|
||||
this._lockScreenGroup.connect('scroll-event',
|
||||
@ -521,10 +515,9 @@ const ScreenShield = new Lang.Class({
|
||||
reactive: true,
|
||||
pivot_point: new Clutter.Point({ x: 0.5, y: 0.5 }),
|
||||
name: 'lockDialogGroup' });
|
||||
Main.layoutManager.systemGroup.add_child(this._lockDialogGroup);
|
||||
|
||||
this.actor.add_actor(this._lockDialogGroup);
|
||||
this.actor.add_actor(this._lockScreenGroup);
|
||||
|
||||
Main.layoutManager.screenShieldGroup.add_child(this._lockScreenGroup);
|
||||
this._presence = new GnomeSession.Presence(Lang.bind(this, function(proxy, error) {
|
||||
if (error) {
|
||||
logError(error, 'Error while reading gnome-session presence');
|
||||
@ -582,19 +575,27 @@ const ScreenShield = new Lang.Class({
|
||||
// The "long" lightbox is used for the longer (20 seconds) fade from session
|
||||
// to idle status, the "short" is used for quickly fading to black when locking
|
||||
// manually
|
||||
this._longLightbox = new Lightbox.Lightbox(Main.uiGroup,
|
||||
this._longLightbox = new Lightbox.Lightbox(Main.layoutManager.overlayGroup,
|
||||
{ inhibitEvents: true,
|
||||
fadeFactor: 1 });
|
||||
this._longLightbox.connect('shown', Lang.bind(this, this._onLongLightboxShown));
|
||||
this._shortLightbox = new Lightbox.Lightbox(Main.uiGroup,
|
||||
this._shortLightbox = new Lightbox.Lightbox(Main.layoutManager.overlayGroup,
|
||||
{ inhibitEvents: true,
|
||||
fadeFactor: 1 });
|
||||
this._shortLightbox.connect('shown', Lang.bind(this, this._onShortLightboxShown));
|
||||
|
||||
Main.layoutManager.connect('monitors-changed', Lang.bind(this, this._monitorsChanged));
|
||||
this._monitorsChanged();
|
||||
|
||||
this.idleMonitor = Meta.IdleMonitor.get_core();
|
||||
this._cursorTracker = Meta.CursorTracker.get_for_screen(global.screen);
|
||||
},
|
||||
|
||||
_monitorsChanged: function() {
|
||||
this._longLightbox.actor.set_size(global.screen_width, global.screen_height);
|
||||
this._shortLightbox.actor.set_size(global.screen_width, global.screen_height);
|
||||
},
|
||||
|
||||
_createBackground: function(monitorIndex) {
|
||||
let monitor = Main.layoutManager.monitors[monitorIndex];
|
||||
let widget = new St.Widget({ style_class: 'screen-shield-background',
|
||||
@ -652,14 +653,14 @@ const ScreenShield = new Lang.Class({
|
||||
if (this._isModal)
|
||||
return true;
|
||||
|
||||
this._isModal = Main.pushModal(this.actor, { keybindingMode: Shell.KeyBindingMode.LOCK_SCREEN });
|
||||
this._isModal = Main.pushModal(this._lockDialogGroup, { keybindingMode: Shell.KeyBindingMode.LOCK_SCREEN });
|
||||
if (this._isModal)
|
||||
return true;
|
||||
|
||||
// We failed to get a pointer grab, it means that
|
||||
// something else has it. Try with a keyboard grab only
|
||||
this._isModal = Main.pushModal(this.actor, { options: Meta.ModalOptions.POINTER_ALREADY_GRABBED,
|
||||
keybindingMode: Shell.KeyBindingMode.LOCK_SCREEN });
|
||||
this._isModal = Main.pushModal(this._lockDialogGroup, { options: Meta.ModalOptions.POINTER_ALREADY_GRABBED,
|
||||
keybindingMode: Shell.KeyBindingMode.LOCK_SCREEN });
|
||||
return this._isModal;
|
||||
},
|
||||
|
||||
@ -673,11 +674,11 @@ const ScreenShield = new Lang.Class({
|
||||
// down after cancel.
|
||||
|
||||
if (this._lockScreenState != MessageTray.State.SHOWN)
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
||||
let isEnter = (symbol == Clutter.KEY_Return || symbol == Clutter.KEY_KP_Enter);
|
||||
if (!isEnter && !(GLib.unichar_isprint(unichar) || symbol == Clutter.KEY_Escape))
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
||||
if (this._isLocked &&
|
||||
this._ensureUnlockDialog(true, true) &&
|
||||
@ -685,12 +686,12 @@ const ScreenShield = new Lang.Class({
|
||||
this._dialog.addCharacter(unichar);
|
||||
|
||||
this._liftShield(true, 0);
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
},
|
||||
|
||||
_onLockScreenScroll: function(actor, event) {
|
||||
if (this._lockScreenState != MessageTray.State.SHOWN)
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
||||
let delta = 0;
|
||||
if (event.get_scroll_direction() == Clutter.ScrollDirection.UP)
|
||||
@ -705,7 +706,7 @@ const ScreenShield = new Lang.Class({
|
||||
this._liftShield(true, 0);
|
||||
}
|
||||
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
},
|
||||
|
||||
_inhibitSuspend: function() {
|
||||
@ -756,7 +757,7 @@ const ScreenShield = new Lang.Class({
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
return GLib.SOURCE_CONTINUE;
|
||||
},
|
||||
|
||||
_onDragBegin: function() {
|
||||
@ -852,7 +853,7 @@ const ScreenShield = new Lang.Class({
|
||||
Lang.bind(this, function() {
|
||||
this._lockTimeoutId = 0;
|
||||
this.lock(false);
|
||||
return false;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
}));
|
||||
}
|
||||
|
||||
@ -917,7 +918,7 @@ const ScreenShield = new Lang.Class({
|
||||
return false;
|
||||
}));
|
||||
|
||||
this.actor.show();
|
||||
this._lockDialogGroup.show();
|
||||
this._isGreeter = Main.sessionMode.isGreeter;
|
||||
this._isLocked = true;
|
||||
if (this._ensureUnlockDialog(true, true))
|
||||
@ -1007,6 +1008,7 @@ const ScreenShield = new Lang.Class({
|
||||
return;
|
||||
|
||||
this._ensureLockScreen();
|
||||
this._lockDialogGroup.hide();
|
||||
this._lockDialogGroup.scale_x = 1;
|
||||
this._lockDialogGroup.scale_y = 1;
|
||||
|
||||
@ -1101,12 +1103,14 @@ const ScreenShield = new Lang.Class({
|
||||
global.stage.disconnect(motionId);
|
||||
}
|
||||
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
}));
|
||||
this._cursorTracker.set_pointer_visible(false);
|
||||
|
||||
this._lockScreenState = MessageTray.State.SHOWN;
|
||||
this._lockDialogGroup.show();
|
||||
this._lockScreenGroup.fixed_position_set = false;
|
||||
this._lockScreenState = MessageTray.State.SHOWN;
|
||||
Main.layoutManager.sessionGroup.hide();
|
||||
this._lockScreenScrollCounter = 0;
|
||||
|
||||
if (params.fadeToBlack && params.animateFade) {
|
||||
@ -1114,6 +1118,7 @@ const ScreenShield = new Lang.Class({
|
||||
|
||||
Mainloop.timeout_add(1000 * MANUAL_FADE_TIME, Lang.bind(this, function() {
|
||||
this._activateFade(this._shortLightbox, MANUAL_FADE_TIME);
|
||||
return GLib.SOURCE_REMOVE;
|
||||
}));
|
||||
} else {
|
||||
if (params.fadeToBlack)
|
||||
@ -1228,10 +1233,11 @@ const ScreenShield = new Lang.Class({
|
||||
this._dialog.popModal();
|
||||
|
||||
if (this._isModal) {
|
||||
Main.popModal(this.actor);
|
||||
Main.popModal(this._lockDialogGroup);
|
||||
this._isModal = false;
|
||||
}
|
||||
|
||||
Main.layoutManager.sessionGroup.show();
|
||||
Tweener.addTween(this._lockDialogGroup, {
|
||||
scale_x: 0,
|
||||
scale_y: 0,
|
||||
@ -1250,7 +1256,7 @@ const ScreenShield = new Lang.Class({
|
||||
|
||||
this._longLightbox.hide();
|
||||
this._shortLightbox.hide();
|
||||
this.actor.hide();
|
||||
this._lockScreenGroup.hide();
|
||||
|
||||
if (this._becameActiveId != 0) {
|
||||
this.idleMonitor.remove_watch(this._becameActiveId);
|
||||
@ -1274,7 +1280,7 @@ const ScreenShield = new Lang.Class({
|
||||
if (this._activationTime == 0)
|
||||
this._activationTime = GLib.get_monotonic_time();
|
||||
|
||||
this.actor.show();
|
||||
this._lockScreenGroup.show();
|
||||
|
||||
if (Main.sessionMode.currentMode != 'unlock-dialog' &&
|
||||
Main.sessionMode.currentMode != 'lock-screen') {
|
||||
|
@ -6,7 +6,6 @@ const Lang = imports.lang;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Signals = imports.signals;
|
||||
|
||||
const Hash = imports.misc.hash;
|
||||
const Main = imports.ui.main;
|
||||
|
||||
const ScreencastIface = '<node> \
|
||||
@ -42,13 +41,13 @@ const ScreencastService = new Lang.Class({
|
||||
|
||||
Gio.DBus.session.own_name('org.gnome.Shell.Screencast', Gio.BusNameOwnerFlags.REPLACE, null, null);
|
||||
|
||||
this._recorders = new Hash.Map();
|
||||
this._recorders = new Map();
|
||||
|
||||
Main.sessionMode.connect('updated', Lang.bind(this, this._sessionUpdated));
|
||||
},
|
||||
|
||||
get isRecording() {
|
||||
return this._recorders.size() > 0;
|
||||
return this._recorders.size > 0;
|
||||
},
|
||||
|
||||
_ensureRecorderForSender: function(sender) {
|
||||
@ -69,8 +68,7 @@ const ScreencastService = new Lang.Class({
|
||||
if (Main.sessionMode.allowScreencast)
|
||||
return;
|
||||
|
||||
for (let sender in this._recorders.keys())
|
||||
this._recorders.delete(sender);
|
||||
this._recorders.clear();
|
||||
this.emit('updated');
|
||||
},
|
||||
|
||||
|
@ -146,7 +146,7 @@ const SelectArea = new Lang.Class({
|
||||
reactive: true,
|
||||
x: 0,
|
||||
y: 0 });
|
||||
Main.uiGroup.add_actor(this._group);
|
||||
Main.layoutManager.osdGroup.add_actor(this._group);
|
||||
|
||||
this._group.connect('button-press-event',
|
||||
Lang.bind(this, this._onButtonPress));
|
||||
@ -206,12 +206,12 @@ const SelectArea = new Lang.Class({
|
||||
if (event.get_key_symbol() == Clutter.Escape)
|
||||
this._destroy(null, false);
|
||||
|
||||
return;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
},
|
||||
|
||||
_onMotionEvent: function(actor, event) {
|
||||
if (this._startX == -1 || this._startY == -1)
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
||||
[this._lastX, this._lastY] = event.get_coords();
|
||||
let geometry = this._getGeometry();
|
||||
@ -219,19 +219,19 @@ const SelectArea = new Lang.Class({
|
||||
this._rubberband.set_position(geometry.x, geometry.y);
|
||||
this._rubberband.set_size(geometry.width, geometry.height);
|
||||
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
},
|
||||
|
||||
_onButtonPress: function(actor, event) {
|
||||
[this._startX, this._startY] = event.get_coords();
|
||||
this._rubberband.set_position(this._startX, this._startY);
|
||||
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
},
|
||||
|
||||
_onButtonRelease: function(actor, event) {
|
||||
this._destroy(this._getGeometry(), true);
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
},
|
||||
|
||||
_destroy: function(geometry, fade) {
|
||||
@ -259,9 +259,9 @@ const Flashspot = new Lang.Class({
|
||||
Extends: Lightbox.Lightbox,
|
||||
|
||||
_init: function(area) {
|
||||
this.parent(Main.uiGroup, { inhibitEvents: true,
|
||||
width: area.width,
|
||||
height: area.height });
|
||||
this.parent(Main.layoutManager.osdGroup, { inhibitEvents: true,
|
||||
width: area.width,
|
||||
height: area.height });
|
||||
|
||||
this.actor.style_class = 'flashspot';
|
||||
this.actor.set_position(area.x, area.y);
|
||||
|
@ -1,6 +1,7 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Shell = imports.gi.Shell;
|
||||
@ -41,7 +42,7 @@ function sleep(milliseconds) {
|
||||
Mainloop.timeout_add(milliseconds, function() {
|
||||
if (cb)
|
||||
cb();
|
||||
return false;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
});
|
||||
|
||||
return function(callback) {
|
||||
|
@ -120,22 +120,22 @@ function _loadMode(file, info) {
|
||||
|
||||
_modes[modeName] = {};
|
||||
let propBlacklist = ['unlockDialog'];
|
||||
for (let prop in loadedData[DEFAULT_MODE]) {
|
||||
for (let prop in _modes[DEFAULT_MODE]) {
|
||||
if (newMode[prop] !== undefined &&
|
||||
propBlacklist.indexOf(prop) == -1)
|
||||
loadedData[modeName][prop] = newMode[prop];
|
||||
_modes[modeName][prop] = newMode[prop];
|
||||
}
|
||||
_modes[modeName]['isPrimary'] = true;
|
||||
}
|
||||
|
||||
function _getModes() {
|
||||
function _loadModes() {
|
||||
FileUtils.collectFromDatadirs('modes', false, _loadMode);
|
||||
}
|
||||
|
||||
function listModes() {
|
||||
let modes = _getModes();
|
||||
modes.forEach(function() {
|
||||
let names = Object.getOwnPropertyNames(modes);
|
||||
_loadModes();
|
||||
Mainloop.idle_add(function() {
|
||||
let names = Object.getOwnPropertyNames(_modes);
|
||||
for (let i = 0; i < names.length; i++)
|
||||
if (_modes[names[i]].isPrimary)
|
||||
print(names[i]);
|
||||
@ -148,6 +148,7 @@ const SessionMode = new Lang.Class({
|
||||
Name: 'SessionMode',
|
||||
|
||||
_init: function() {
|
||||
_loadModes();
|
||||
let isPrimary = (_modes[global.session_mode] &&
|
||||
_modes[global.session_mode].isPrimary);
|
||||
let mode = isPrimary ? global.session_mode : 'user';
|
||||
|
@ -10,7 +10,6 @@ const Config = imports.misc.config;
|
||||
const ExtensionSystem = imports.ui.extensionSystem;
|
||||
const ExtensionDownloader = imports.ui.extensionDownloader;
|
||||
const ExtensionUtils = imports.misc.extensionUtils;
|
||||
const Hash = imports.misc.hash;
|
||||
const Main = imports.ui.main;
|
||||
const Screenshot = imports.ui.screenshot;
|
||||
const ViewSelector = imports.ui.viewSelector;
|
||||
@ -83,8 +82,8 @@ const GnomeShell = new Lang.Class({
|
||||
this._extensionsService = new GnomeShellExtensions();
|
||||
this._screenshotService = new Screenshot.ScreenshotService();
|
||||
|
||||
this._grabbedAccelerators = new Hash.Map();
|
||||
this._grabbers = new Hash.Map();
|
||||
this._grabbedAccelerators = new Map();
|
||||
this._grabbers = new Map();
|
||||
|
||||
global.display.connect('accelerator-activated', Lang.bind(this,
|
||||
function(display, action, deviceid, timestamp) {
|
||||
@ -133,11 +132,16 @@ const GnomeShell = new Lang.Class({
|
||||
for (let param in params)
|
||||
params[param] = params[param].deep_unpack();
|
||||
|
||||
let monitorIndex = -1;
|
||||
if (params['monitor'])
|
||||
monitorIndex = params['monitor'];
|
||||
|
||||
let icon = null;
|
||||
if (params['icon'])
|
||||
icon = Gio.Icon.new_for_string(params['icon']);
|
||||
|
||||
Main.osdWindow.setIcon(icon);
|
||||
Main.osdWindow.setMonitor (monitorIndex);
|
||||
Main.osdWindow.setLabel(params['label']);
|
||||
Main.osdWindow.setLevel(params['level']);
|
||||
|
||||
@ -223,9 +227,8 @@ const GnomeShell = new Lang.Class({
|
||||
},
|
||||
|
||||
_onGrabberBusNameVanished: function(connection, name) {
|
||||
let grabs = this._grabbedAccelerators.items();
|
||||
for (let i = 0; i < grabs.length; i++) {
|
||||
let [action, sender] = grabs[i];
|
||||
let grabs = this._grabbedAccelerators.entries();
|
||||
for (let [action, sender] of grabs) {
|
||||
if (sender == name)
|
||||
this._ungrabAccelerator(action);
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ const EntryMenu = new Lang.Class({
|
||||
|
||||
this._passwordItem = null;
|
||||
|
||||
Main.uiGroup.add_actor(this.actor);
|
||||
Main.layoutManager.menuGroup.add_actor(this.actor);
|
||||
this.actor.hide();
|
||||
},
|
||||
|
||||
@ -132,14 +132,14 @@ function _setMenuAlignment(entry, stageX) {
|
||||
function _onButtonPressEvent(actor, event, entry) {
|
||||
if (entry.menu.isOpen) {
|
||||
entry.menu.close(BoxPointer.PopupAnimation.FULL);
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
} else if (event.get_button() == 3) {
|
||||
let [stageX, stageY] = event.get_coords();
|
||||
_setMenuAlignment(entry, stageX);
|
||||
entry.menu.open(BoxPointer.PopupAnimation.FULL);
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
}
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
};
|
||||
|
||||
function _onPopup(actor, entry) {
|
||||
|
@ -111,12 +111,12 @@ const Slider = new Lang.Class({
|
||||
},
|
||||
|
||||
_startDragging: function(actor, event) {
|
||||
this.startDragging(event);
|
||||
return this.startDragging(event);
|
||||
},
|
||||
|
||||
startDragging: function(event) {
|
||||
if (this._dragging)
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
||||
this._dragging = true;
|
||||
|
||||
@ -129,7 +129,7 @@ const Slider = new Lang.Class({
|
||||
let absX, absY;
|
||||
[absX, absY] = event.get_coords();
|
||||
this._moveHandle(absX, absY);
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
},
|
||||
|
||||
_endDragging: function() {
|
||||
@ -143,7 +143,7 @@ const Slider = new Lang.Class({
|
||||
|
||||
this.emit('drag-end');
|
||||
}
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
},
|
||||
|
||||
scroll: function(event) {
|
||||
@ -151,7 +151,7 @@ const Slider = new Lang.Class({
|
||||
let delta;
|
||||
|
||||
if (event.is_pointer_emulated())
|
||||
return;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
||||
if (direction == Clutter.ScrollDirection.DOWN) {
|
||||
delta = -SLIDER_SCROLL_STEP;
|
||||
@ -168,17 +168,18 @@ const Slider = new Lang.Class({
|
||||
|
||||
this.actor.queue_repaint();
|
||||
this.emit('value-changed', this._value);
|
||||
return Clutter.EVENT_STOP;
|
||||
},
|
||||
|
||||
_onScrollEvent: function(actor, event) {
|
||||
this.scroll(event);
|
||||
return this.scroll(event);
|
||||
},
|
||||
|
||||
_motionEvent: function(actor, event) {
|
||||
let absX, absY;
|
||||
[absX, absY] = event.get_coords();
|
||||
this._moveHandle(absX, absY);
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
},
|
||||
|
||||
onKeyPressEvent: function (actor, event) {
|
||||
@ -189,9 +190,9 @@ const Slider = new Lang.Class({
|
||||
this.actor.queue_repaint();
|
||||
this.emit('value-changed', this._value);
|
||||
this.emit('drag-end');
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
}
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
},
|
||||
|
||||
_moveHandle: function(absX, absY) {
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Lang = imports.lang;
|
||||
const Mainloop = imports.mainloop;
|
||||
const St = imports.gi.St;
|
||||
@ -94,7 +95,7 @@ const ATIndicator = new Lang.Class({
|
||||
|
||||
this.actor.visible = alwaysShow || items.some(function(f) { return !!f.state; });
|
||||
|
||||
return false;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
},
|
||||
|
||||
_queueSyncMenuVisibility: function() {
|
||||
|
@ -2,16 +2,26 @@
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const GLib = imports.gi.GLib;
|
||||
const GnomeBluetoothApplet = imports.gi.GnomeBluetoothApplet;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GnomeBluetooth = imports.gi.GnomeBluetooth;
|
||||
const Lang = imports.lang;
|
||||
const St = imports.gi.St;
|
||||
|
||||
const Main = imports.ui.main;
|
||||
const MessageTray = imports.ui.messageTray;
|
||||
const PanelMenu = imports.ui.panelMenu;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
|
||||
const BUS_NAME = 'org.gnome.SettingsDaemon.Rfkill';
|
||||
const OBJECT_PATH = '/org/gnome/SettingsDaemon/Rfkill';
|
||||
|
||||
const RfkillManagerInterface = '<node> \
|
||||
<interface name="org.gnome.SettingsDaemon.Rfkill"> \
|
||||
<property name="BluetoothAirplaneMode" type="b" access="readwrite" /> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
const RfkillManagerProxy = Gio.DBusProxy.makeProxyWrapper(RfkillManagerInterface);
|
||||
|
||||
const Indicator = new Lang.Class({
|
||||
Name: 'BTIndicator',
|
||||
Extends: PanelMenu.SystemIndicator,
|
||||
@ -22,32 +32,63 @@ const Indicator = new Lang.Class({
|
||||
this._indicator = this._addIndicator();
|
||||
this._indicator.icon_name = 'bluetooth-active-symbolic';
|
||||
|
||||
this._proxy = new RfkillManagerProxy(Gio.DBus.session, BUS_NAME, OBJECT_PATH,
|
||||
Lang.bind(this, function(proxy, error) {
|
||||
if (error) {
|
||||
log(error.message);
|
||||
return;
|
||||
}
|
||||
}));
|
||||
|
||||
// The Bluetooth menu only appears when Bluetooth is in use,
|
||||
// so just statically build it with a "Turn Off" menu item.
|
||||
this._item = new PopupMenu.PopupSubMenuMenuItem(_("Bluetooth"), true);
|
||||
this._item.icon.icon_name = 'bluetooth-active-symbolic';
|
||||
this._item.menu.addAction(_("Turn Off"), Lang.bind(this, function() {
|
||||
this._applet.killswitch_state = GnomeBluetooth.KillswitchState.SOFT_BLOCKED;
|
||||
this._proxy.BluetoothAirplaneMode = true;
|
||||
}));
|
||||
this._item.menu.addSettingsAction(_("Bluetooth Settings"), 'gnome-bluetooth-panel.desktop');
|
||||
this.menu.addMenuItem(this._item);
|
||||
|
||||
this._applet = new GnomeBluetoothApplet.Applet();
|
||||
this._applet.connect('devices-changed', Lang.bind(this, this._sync));
|
||||
this._client = new GnomeBluetooth.Client();
|
||||
this._model = this._client.get_model();
|
||||
this._model.connect('row-changed', Lang.bind(this, this._sync));
|
||||
this._model.connect('row-deleted', Lang.bind(this, this._sync));
|
||||
this._model.connect('row-inserted', Lang.bind(this, this._sync));
|
||||
this._sync();
|
||||
},
|
||||
|
||||
this._applet.connect('pincode-request', Lang.bind(this, this._pinRequest));
|
||||
this._applet.connect('confirm-request', Lang.bind(this, this._confirmRequest));
|
||||
this._applet.connect('auth-request', Lang.bind(this, this._authRequest));
|
||||
this._applet.connect('auth-service-request', Lang.bind(this, this._authServiceRequest));
|
||||
this._applet.connect('cancel-request', Lang.bind(this, this._cancelRequest));
|
||||
_getDefaultAdapter: function() {
|
||||
let [ret, iter] = this._model.get_iter_first();
|
||||
while (ret) {
|
||||
let isDefault = this._model.get_value(iter,
|
||||
GnomeBluetooth.Column.DEFAULT);
|
||||
if (isDefault)
|
||||
return iter;
|
||||
ret = this._model.iter_next(iter);
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
_getNConnectedDevices: function() {
|
||||
let adapter = this._getDefaultAdapter();
|
||||
if (!adapter)
|
||||
return 0;
|
||||
|
||||
let nDevices = 0;
|
||||
let [ret, iter] = this._model.iter_children(adapter);
|
||||
while (ret) {
|
||||
let isConnected = this._model.get_value(iter,
|
||||
GnomeBluetooth.Column.CONNECTED);
|
||||
if (isConnected)
|
||||
nDevices++;
|
||||
ret = this._model.iter_next(iter);
|
||||
}
|
||||
return nDevices;
|
||||
},
|
||||
|
||||
_sync: function() {
|
||||
let connectedDevices = this._applet.get_devices().filter(function(device) {
|
||||
return device.connected;
|
||||
});
|
||||
let nDevices = connectedDevices.length;
|
||||
let nDevices = this._getNConnectedDevices();
|
||||
|
||||
let on = nDevices > 0;
|
||||
this._indicator.visible = on;
|
||||
@ -56,204 +97,4 @@ const Indicator = new Lang.Class({
|
||||
if (on)
|
||||
this._item.status.text = ngettext("%d Connected Device", "%d Connected Devices", nDevices).format(nDevices);
|
||||
},
|
||||
|
||||
_ensureSource: function() {
|
||||
if (!this._source) {
|
||||
this._source = new MessageTray.Source(_("Bluetooth"), 'bluetooth-active');
|
||||
this._source.policy = new MessageTray.NotificationApplicationPolicy('gnome-bluetooth-panel');
|
||||
Main.messageTray.add(this._source);
|
||||
}
|
||||
},
|
||||
|
||||
_authRequest: function(applet, device_path, name, long_name) {
|
||||
this._ensureSource();
|
||||
this._source.notify(new AuthNotification(this._source, this._applet, device_path, name, long_name));
|
||||
},
|
||||
|
||||
_authServiceRequest: function(applet, device_path, name, long_name, uuid) {
|
||||
this._ensureSource();
|
||||
this._source.notify(new AuthServiceNotification(this._source, this._applet, device_path, name, long_name, uuid));
|
||||
},
|
||||
|
||||
_confirmRequest: function(applet, device_path, name, long_name, pin) {
|
||||
this._ensureSource();
|
||||
this._source.notify(new ConfirmNotification(this._source, this._applet, device_path, name, long_name, pin));
|
||||
},
|
||||
|
||||
_pinRequest: function(applet, device_path, name, long_name, numeric) {
|
||||
this._ensureSource();
|
||||
this._source.notify(new PinNotification(this._source, this._applet, device_path, name, long_name, numeric));
|
||||
},
|
||||
|
||||
_cancelRequest: function() {
|
||||
this._source.destroy();
|
||||
}
|
||||
});
|
||||
|
||||
const AuthNotification = new Lang.Class({
|
||||
Name: 'AuthNotification',
|
||||
Extends: MessageTray.Notification,
|
||||
|
||||
_init: function(source, applet, device_path, name, long_name) {
|
||||
this.parent(source,
|
||||
_("Bluetooth"),
|
||||
_("Authorization request from %s").format(name),
|
||||
{ customContent: true });
|
||||
this.setResident(true);
|
||||
|
||||
this._applet = applet;
|
||||
this._devicePath = device_path;
|
||||
this.addBody(_("Device %s wants to pair with this computer").format(long_name));
|
||||
|
||||
this.addAction('allow', _("Allow"));
|
||||
this.addAction('deny', _("Deny"));
|
||||
|
||||
this.connect('action-invoked', Lang.bind(this, function(self, action) {
|
||||
if (action == 'allow')
|
||||
this._applet.agent_reply_confirm(this._devicePath, true);
|
||||
else
|
||||
this._applet.agent_reply_confirm(this._devicePath, false);
|
||||
this.destroy();
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
||||
const AuthServiceNotification = new Lang.Class({
|
||||
Name: 'AuthServiceNotification',
|
||||
Extends: MessageTray.Notification,
|
||||
|
||||
_init: function(source, applet, device_path, name, long_name, uuid) {
|
||||
this.parent(source,
|
||||
_("Bluetooth"),
|
||||
_("Authorization request from %s").format(name),
|
||||
{ customContent: true });
|
||||
this.setResident(true);
|
||||
|
||||
this._applet = applet;
|
||||
this._devicePath = device_path;
|
||||
this.addBody(_("Device %s wants access to the service '%s'").format(long_name, uuid));
|
||||
|
||||
this.addAction('always-grant', _("Always grant access"));
|
||||
this.addAction('grant', _("Grant this time only"));
|
||||
this.addAction('reject', _("Reject"));
|
||||
|
||||
this.connect('action-invoked', Lang.bind(this, function(self, action) {
|
||||
switch (action) {
|
||||
case 'always-grant':
|
||||
this._applet.agent_reply_auth_service(this._devicePath, true, true);
|
||||
break;
|
||||
case 'grant':
|
||||
this._applet.agent_reply_auth_service(this._devicePath, true, false);
|
||||
break;
|
||||
case 'reject':
|
||||
default:
|
||||
this._applet.agent_reply_auth_service(this._devicePath, false, false);
|
||||
}
|
||||
this.destroy();
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
||||
const ConfirmNotification = new Lang.Class({
|
||||
Name: 'ConfirmNotification',
|
||||
Extends: MessageTray.Notification,
|
||||
|
||||
_init: function(source, applet, device_path, name, long_name, pin) {
|
||||
this.parent(source,
|
||||
_("Bluetooth"),
|
||||
/* Translators: argument is the device short name */
|
||||
_("Pairing confirmation for %s").format(name),
|
||||
{ customContent: true });
|
||||
this.setResident(true);
|
||||
|
||||
this._applet = applet;
|
||||
this._devicePath = device_path;
|
||||
this.addBody(_("Device %s wants to pair with this computer").format(long_name));
|
||||
this.addBody(_("Please confirm whether the Passkey '%06d' matches the one on the device.").format(pin));
|
||||
|
||||
/* Translators: this is the verb, not the noun */
|
||||
this.addAction('matches', _("Matches"));
|
||||
this.addAction('does-not-match', _("Does not match"));
|
||||
|
||||
this.connect('action-invoked', Lang.bind(this, function(self, action) {
|
||||
if (action == 'matches')
|
||||
this._applet.agent_reply_confirm(this._devicePath, true);
|
||||
else
|
||||
this._applet.agent_reply_confirm(this._devicePath, false);
|
||||
this.destroy();
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
||||
const PinNotification = new Lang.Class({
|
||||
Name: 'PinNotification',
|
||||
Extends: MessageTray.Notification,
|
||||
|
||||
_init: function(source, applet, device_path, name, long_name, numeric) {
|
||||
this.parent(source,
|
||||
_("Bluetooth"),
|
||||
_("Pairing request for %s").format(name),
|
||||
{ customContent: true });
|
||||
this.setResident(true);
|
||||
|
||||
this._applet = applet;
|
||||
this._devicePath = device_path;
|
||||
this._numeric = numeric;
|
||||
this.addBody(_("Device %s wants to pair with this computer").format(long_name));
|
||||
this.addBody(_("Please enter the PIN mentioned on the device."));
|
||||
|
||||
this._entry = new St.Entry();
|
||||
this._entry.connect('key-release-event', Lang.bind(this, function(entry, event) {
|
||||
let key = event.get_key_symbol();
|
||||
if (key == Clutter.KEY_Return) {
|
||||
if (this._canActivateOkButton())
|
||||
this._ok();
|
||||
return true;
|
||||
} else if (key == Clutter.KEY_Escape) {
|
||||
this._cancel();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}));
|
||||
this.addActor(this._entry);
|
||||
|
||||
let okButton = this.addAction(_("OK"), Lang.bind(this, this._ok));
|
||||
this.addAction(_("Cancel"), Lang.bind(this, this._cancel));
|
||||
|
||||
okButton.reactive = this._canActivateOkButton();
|
||||
this._entry.clutter_text.connect('text-changed', Lang.bind(this, function() {
|
||||
okButton.reactive = this._canActivateOkButton();
|
||||
}));
|
||||
},
|
||||
|
||||
_ok: function() {
|
||||
if (this._numeric) {
|
||||
let num = parseInt(this._entry.text, 10);
|
||||
if (isNaN(num)) {
|
||||
// user reply was empty, or was invalid
|
||||
// cancel the operation
|
||||
num = -1;
|
||||
}
|
||||
this._applet.agent_reply_passkey(this._devicePath, num);
|
||||
} else {
|
||||
this._applet.agent_reply_pincode(this._devicePath, this._entry.text);
|
||||
}
|
||||
this.destroy();
|
||||
},
|
||||
|
||||
_cancel: function() {
|
||||
if (this._numeric)
|
||||
this._applet.agent_reply_passkey(this._devicePath, -1);
|
||||
else
|
||||
this._applet.agent_reply_pincode(this._devicePath, null);
|
||||
this.destroy();
|
||||
},
|
||||
|
||||
_canActivateOkButton: function() {
|
||||
// PINs have a fixed length of 6
|
||||
if (this._numeric)
|
||||
return this._entry.clutter_text.text.length == 6;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
@ -48,7 +48,7 @@ const Indicator = new Lang.Class({
|
||||
this._item.actor.add(icon);
|
||||
this._item.actor.add(this._slider.actor, { expand: true });
|
||||
this._item.actor.connect('button-press-event', Lang.bind(this, function(actor, event) {
|
||||
this._slider.startDragging(event);
|
||||
return this._slider.startDragging(event);
|
||||
}));
|
||||
this._item.actor.connect('key-press-event', Lang.bind(this, function(actor, event) {
|
||||
return this._slider.onKeyPressEvent(actor, event);
|
||||
|
58
js/ui/status/location.js
Normal file
58
js/ui/status/location.js
Normal file
@ -0,0 +1,58 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Gio = imports.gi.Gio;
|
||||
const Lang = imports.lang;
|
||||
|
||||
const PanelMenu = imports.ui.panelMenu;
|
||||
|
||||
var GeoclueIface = '<node> \
|
||||
<interface name="org.freedesktop.GeoClue2.Manager"> \
|
||||
<property name="InUse" type="b" access="read"/> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
const GeoclueManager = Gio.DBusProxy.makeProxyWrapper(GeoclueIface);
|
||||
|
||||
const Indicator = new Lang.Class({
|
||||
Name: 'LocationIndicator',
|
||||
Extends: PanelMenu.SystemIndicator,
|
||||
|
||||
_init: function() {
|
||||
this.parent();
|
||||
|
||||
this._indicator = this._addIndicator();
|
||||
this._indicator.icon_name = 'find-location-symbolic';
|
||||
this._sync();
|
||||
|
||||
this._watchId = Gio.bus_watch_name(Gio.BusType.SYSTEM,
|
||||
'org.freedesktop.GeoClue2',
|
||||
0,
|
||||
Lang.bind(this, this._onGeoclueAppeared),
|
||||
Lang.bind(this, this._onGeoclueVanished));
|
||||
},
|
||||
|
||||
_sync: function() {
|
||||
if (this._proxy == null) {
|
||||
this._indicator.visible = false;
|
||||
return;
|
||||
}
|
||||
|
||||
this._indicator.visible = this._proxy.InUse;
|
||||
},
|
||||
|
||||
_onGeoclueAppeared: function() {
|
||||
// FIXME: This should be done async
|
||||
this._proxy = new GeoclueManager(Gio.DBus.system,
|
||||
'org.freedesktop.GeoClue2',
|
||||
'/org/freedesktop/GeoClue2/Manager');
|
||||
this._proxy.connect('g-properties-changed', Lang.bind(this, this._sync));
|
||||
|
||||
this._sync();
|
||||
},
|
||||
|
||||
_onGeoclueVanished: function() {
|
||||
this._proxy = null;
|
||||
|
||||
this._sync();
|
||||
}
|
||||
});
|
@ -11,7 +11,6 @@ const NMGtk = imports.gi.NMGtk;
|
||||
const Signals = imports.signals;
|
||||
const St = imports.gi.St;
|
||||
|
||||
const Hash = imports.misc.hash;
|
||||
const Main = imports.ui.main;
|
||||
const PanelMenu = imports.ui.panelMenu;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
@ -22,6 +21,7 @@ const Util = imports.misc.util;
|
||||
|
||||
const NMConnectionCategory = {
|
||||
INVALID: 'invalid',
|
||||
WIRED: 'wired',
|
||||
WIRELESS: 'wireless',
|
||||
WWAN: 'wwan',
|
||||
VPN: 'vpn'
|
||||
@ -176,7 +176,7 @@ const NMConnectionSection = new Lang.Class({
|
||||
_init: function(client) {
|
||||
this._client = client;
|
||||
|
||||
this._connectionItems = new Hash.Map();
|
||||
this._connectionItems = new Map();
|
||||
this._connections = [];
|
||||
|
||||
this._labelSection = new PopupMenu.PopupMenuSection();
|
||||
@ -194,7 +194,7 @@ const NMConnectionSection = new Lang.Class({
|
||||
},
|
||||
|
||||
_sync: function() {
|
||||
let nItems = this._connectionItems.size();
|
||||
let nItems = this._connectionItems.size;
|
||||
|
||||
this._switchSection.actor.visible = (nItems > 1);
|
||||
this._labelSection.actor.visible = (nItems == 1);
|
||||
@ -213,8 +213,7 @@ const NMConnectionSection = new Lang.Class({
|
||||
|
||||
_getStatus: function() {
|
||||
let values = this._connectionItems.values();
|
||||
for (let i = 0; i < values.length; i++) {
|
||||
let item = values[i];
|
||||
for (let item of values) {
|
||||
if (item.isActive())
|
||||
return item.getName();
|
||||
}
|
||||
@ -298,6 +297,11 @@ const NMConnectionDevice = new Lang.Class({
|
||||
this._activeConnectionChangedId = this._device.connect('notify::active-connection', Lang.bind(this, this._activeConnectionChanged));
|
||||
},
|
||||
|
||||
_autoConnect: function() {
|
||||
let connection = new NetworkManager.Connection();
|
||||
this._client.add_and_activate_connection(connection, this._device, null, null);
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
if (this._stateChangedId) {
|
||||
GObject.Object.prototype.disconnect.call(this._device, this._stateChangedId);
|
||||
@ -305,7 +309,7 @@ const NMConnectionDevice = new Lang.Class({
|
||||
}
|
||||
if (this._activeConnectionChangedId) {
|
||||
GObject.Object.prototype.disconnect.call(this._device, this._activeConnectionChangedId);
|
||||
this._stateChangedId = 0;
|
||||
this._activeConnectionChangedId = 0;
|
||||
}
|
||||
|
||||
this.parent();
|
||||
@ -365,7 +369,7 @@ const NMConnectionDevice = new Lang.Class({
|
||||
},
|
||||
|
||||
_sync: function() {
|
||||
let nItems = this._connectionItems.size();
|
||||
let nItems = this._connectionItems.size;
|
||||
this._autoConnectItem.actor.visible = (nItems == 0);
|
||||
this.parent();
|
||||
},
|
||||
@ -415,6 +419,48 @@ const NMConnectionDevice = new Lang.Class({
|
||||
},
|
||||
});
|
||||
|
||||
const NMDeviceWired = new Lang.Class({
|
||||
Name: 'NMDeviceWired',
|
||||
Extends: NMConnectionDevice,
|
||||
category: NMConnectionCategory.WIRED,
|
||||
|
||||
_init: function(client, device, settings) {
|
||||
this.parent(client, device, settings);
|
||||
|
||||
this.item.menu.addMenuItem(createSettingsAction(_("Wired Settings"), device));
|
||||
},
|
||||
|
||||
_isConnected: function() {
|
||||
if (!this._device.active_connection)
|
||||
return false;
|
||||
|
||||
let state = this._device.active_connection.state;
|
||||
return state >= NetworkManager.ActiveConnectionState.ACTIVATING;
|
||||
},
|
||||
|
||||
_sync: function() {
|
||||
this.item.actor.visible = this._isConnected();
|
||||
this.parent();
|
||||
},
|
||||
|
||||
_getMenuIcon: function() {
|
||||
if (this._device.active_connection)
|
||||
return this.getIndicatorIcon();
|
||||
else
|
||||
return 'network-wired-disconnected-symbolic';
|
||||
},
|
||||
|
||||
getIndicatorIcon: function() {
|
||||
let state = this._device.active_connection.state;
|
||||
if (state == NetworkManager.ActiveConnectionState.ACTIVATING)
|
||||
return 'network-wired-acquiring-symbolic';
|
||||
else if (state == NetworkManager.ActiveConnectionState.ACTIVATED)
|
||||
return 'network-wired-symbolic';
|
||||
else
|
||||
return 'network-wired-disconnected-symbolic';
|
||||
}
|
||||
});
|
||||
|
||||
const NMDeviceModem = new Lang.Class({
|
||||
Name: 'NMDeviceModem',
|
||||
Extends: NMConnectionDevice,
|
||||
@ -512,18 +558,6 @@ const NMDeviceBluetooth = new Lang.Class({
|
||||
this.item.menu.addMenuItem(createSettingsAction(_("Mobile Broadband Settings"), device));
|
||||
},
|
||||
|
||||
_autoConnect: function() {
|
||||
// FIXME: DUN devices are configured like modems, so
|
||||
// We need to spawn the mobile wizard
|
||||
// but the network panel doesn't support bluetooth at the moment
|
||||
// so we just create an empty connection and hope
|
||||
// that this phone supports PAN
|
||||
|
||||
let connection = new NetworkManager.Connection();
|
||||
this._client.add_and_activate_connection(connection, this._device, null, null);
|
||||
return true;
|
||||
},
|
||||
|
||||
_getMenuIcon: function() {
|
||||
if (this._device.active_connection)
|
||||
return this.getIndicatorIcon();
|
||||
@ -611,7 +645,7 @@ const NMWirelessDialog = new Lang.Class({
|
||||
Name: 'NMWirelessDialog',
|
||||
Extends: ModalDialog.ModalDialog,
|
||||
|
||||
_init: function(client, device, settings) {
|
||||
_init: function(client, device) {
|
||||
this.parent({ styleClass: 'nm-dialog' });
|
||||
|
||||
this._client = client;
|
||||
@ -620,10 +654,7 @@ const NMWirelessDialog = new Lang.Class({
|
||||
this._networks = [];
|
||||
this._buildLayout();
|
||||
|
||||
let connections = settings.list_connections();
|
||||
this._connections = connections.filter(Lang.bind(this, function(connection) {
|
||||
return device.connection_valid(connection);
|
||||
}));
|
||||
this._connections = device.get_available_connections();
|
||||
|
||||
this._apAddedId = device.connect('access-point-added', Lang.bind(this, this._accessPointAdded));
|
||||
this._apRemovedId = device.connect('access-point-removed', Lang.bind(this, this._accessPointRemoved));
|
||||
@ -735,16 +766,11 @@ const NMWirelessDialog = new Lang.Class({
|
||||
|
||||
_connect: function() {
|
||||
let network = this._selectedNetwork;
|
||||
let accessPoints = network.accessPoints;
|
||||
if (network.connections.length > 0) {
|
||||
let connection = network.connections[0];
|
||||
for (let i = 0; i < accessPoints.length; i++) {
|
||||
if (accessPoints[i].connection_valid(connection)) {
|
||||
this._client.activate_connection(connection, this._device, accessPoints[i].dbus_path, null);
|
||||
break;
|
||||
}
|
||||
}
|
||||
this._client.activate_connection(connection, this._device, null, null);
|
||||
} else {
|
||||
let accessPoints = network.accessPoints;
|
||||
if ((accessPoints[0]._secType == NMAccessPointSecurity.WPA2_ENT)
|
||||
|| (accessPoints[0]._secType == NMAccessPointSecurity.WPA_ENT)) {
|
||||
// 802.1x-enabled APs require further configuration, so they're
|
||||
@ -978,10 +1004,9 @@ const NMDeviceWireless = new Lang.Class({
|
||||
Name: 'NMDeviceWireless',
|
||||
category: NMConnectionCategory.WIRELESS,
|
||||
|
||||
_init: function(client, device, settings) {
|
||||
_init: function(client, device) {
|
||||
this._client = client;
|
||||
this._device = device;
|
||||
this._settings = settings;
|
||||
|
||||
this._description = '';
|
||||
|
||||
@ -1049,7 +1074,7 @@ const NMDeviceWireless = new Lang.Class({
|
||||
},
|
||||
|
||||
_showDialog: function() {
|
||||
this._dialog = new NMWirelessDialog(this._client, this._device, this._settings);
|
||||
this._dialog = new NMWirelessDialog(this._client, this._device);
|
||||
this._dialog.connect('closed', Lang.bind(this, this._dialogClosed));
|
||||
this._dialog.open();
|
||||
},
|
||||
@ -1217,7 +1242,7 @@ const NMVPNSection = new Lang.Class({
|
||||
},
|
||||
|
||||
_sync: function() {
|
||||
let nItems = this._connectionItems.size();
|
||||
let nItems = this._connectionItems.size;
|
||||
this.item.actor.visible = (nItems > 0);
|
||||
this.parent();
|
||||
},
|
||||
@ -1239,9 +1264,10 @@ const NMVPNSection = new Lang.Class({
|
||||
},
|
||||
|
||||
setActiveConnections: function(vpnConnections) {
|
||||
this._connectionItems.values().forEach(function(item) {
|
||||
let connections = this._connectionItems.values();
|
||||
for (let item of connections) {
|
||||
item.setActiveConnection(null);
|
||||
});
|
||||
}
|
||||
vpnConnections.forEach(Lang.bind(this, function(a) {
|
||||
let item = this._connectionItems.get(a._connection.get_uuid());
|
||||
item.setActiveConnection(a);
|
||||
@ -1254,8 +1280,7 @@ const NMVPNSection = new Lang.Class({
|
||||
|
||||
getIndicatorIcon: function() {
|
||||
let items = this._connectionItems.values();
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
let item = items[i];
|
||||
for (let item of items) {
|
||||
let icon = item.getIndicatorIcon();
|
||||
if (icon)
|
||||
return icon;
|
||||
@ -1277,6 +1302,7 @@ const NMApplet = new Lang.Class({
|
||||
|
||||
// Device types
|
||||
this._dtypes = { };
|
||||
this._dtypes[NetworkManager.DeviceType.ETHERNET] = NMDeviceWired;
|
||||
this._dtypes[NetworkManager.DeviceType.WIFI] = NMDeviceWireless;
|
||||
this._dtypes[NetworkManager.DeviceType.MODEM] = NMDeviceModem;
|
||||
this._dtypes[NetworkManager.DeviceType.BT] = NMDeviceBluetooth;
|
||||
@ -1284,6 +1310,7 @@ const NMApplet = new Lang.Class({
|
||||
|
||||
// Connection types
|
||||
this._ctypes = { };
|
||||
this._ctypes[NetworkManager.SETTING_WIRED_SETTING_NAME] = NMConnectionCategory.WIRED;
|
||||
this._ctypes[NetworkManager.SETTING_WIRELESS_SETTING_NAME] = NMConnectionCategory.WIRELESS;
|
||||
this._ctypes[NetworkManager.SETTING_BLUETOOTH_SETTING_NAME] = NMConnectionCategory.WWAN;
|
||||
this._ctypes[NetworkManager.SETTING_CDMA_SETTING_NAME] = NMConnectionCategory.WWAN;
|
||||
@ -1306,6 +1333,15 @@ const NMApplet = new Lang.Class({
|
||||
this._tryLateInit();
|
||||
},
|
||||
|
||||
_createDeviceCategory: function() {
|
||||
let category = {
|
||||
section: new PopupMenu.PopupMenuSection(),
|
||||
devices: [ ],
|
||||
};
|
||||
this.menu.addMenuItem(category.section);
|
||||
return category;
|
||||
},
|
||||
|
||||
_tryLateInit: function() {
|
||||
if (!this._client || !this._settings)
|
||||
return;
|
||||
@ -1321,17 +1357,9 @@ const NMApplet = new Lang.Class({
|
||||
this._nmDevices = [];
|
||||
this._devices = { };
|
||||
|
||||
this._devices.wireless = {
|
||||
section: new PopupMenu.PopupMenuSection(),
|
||||
devices: [ ],
|
||||
};
|
||||
this.menu.addMenuItem(this._devices.wireless.section);
|
||||
|
||||
this._devices.wwan = {
|
||||
section: new PopupMenu.PopupMenuSection(),
|
||||
devices: [ ],
|
||||
};
|
||||
this.menu.addMenuItem(this._devices.wwan.section);
|
||||
this._devices.wired = this._createDeviceCategory();
|
||||
this._devices.wireless = this._createDeviceCategory();
|
||||
this._devices.wwan = this._createDeviceCategory();
|
||||
|
||||
this._vpnSection = new NMVPNSection(this._client);
|
||||
this._vpnSection.connect('activation-failed', Lang.bind(this, this._onActivationFailed));
|
||||
|
@ -81,7 +81,7 @@ const AltSwitcher = new Lang.Class({
|
||||
this._sync();
|
||||
}
|
||||
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -42,7 +42,7 @@ const StreamSlider = new Lang.Class({
|
||||
this.item.actor.add(this._icon);
|
||||
this.item.actor.add(this._slider.actor, { expand: true });
|
||||
this.item.actor.connect('button-press-event', Lang.bind(this, function(actor, event) {
|
||||
this._slider.startDragging(event);
|
||||
return this._slider.startDragging(event);
|
||||
}));
|
||||
this.item.actor.connect('key-press-event', Lang.bind(this, function(actor, event) {
|
||||
return this._slider.onKeyPressEvent(actor, event);
|
||||
@ -94,7 +94,7 @@ const StreamSlider = new Lang.Class({
|
||||
},
|
||||
|
||||
scroll: function(event) {
|
||||
this._slider.scroll(event);
|
||||
return this._slider.scroll(event);
|
||||
},
|
||||
|
||||
setValue: function(value) {
|
||||
@ -276,7 +276,7 @@ const VolumeMenu = new Lang.Class({
|
||||
},
|
||||
|
||||
scroll: function(event) {
|
||||
this._output.scroll(event);
|
||||
return this._output.scroll(event);
|
||||
},
|
||||
|
||||
_onControlStateChanged: function() {
|
||||
@ -329,6 +329,6 @@ const Indicator = new Lang.Class({
|
||||
},
|
||||
|
||||
_onScrollEvent: function(actor, event) {
|
||||
this._volumeMenu.scroll(event);
|
||||
return this._volumeMenu.scroll(event);
|
||||
}
|
||||
});
|
||||
|
@ -1,6 +1,7 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Lang = imports.lang;
|
||||
const Mainloop = imports.mainloop;
|
||||
@ -53,7 +54,7 @@ const SwitcherPopup = new Lang.Class({
|
||||
this.actor.connect('allocate', Lang.bind(this, this._allocate));
|
||||
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
|
||||
|
||||
Main.uiGroup.add_actor(this.actor);
|
||||
Main.layoutManager.switcherPopupGroup.add_child(this.actor);
|
||||
|
||||
this._haveModal = false;
|
||||
this._modifierMask = 0;
|
||||
@ -163,6 +164,7 @@ const SwitcherPopup = new Lang.Class({
|
||||
Main.osdWindow.cancel();
|
||||
this.actor.opacity = 255;
|
||||
this._initialDelayTimeoutId = 0;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
}));
|
||||
return true;
|
||||
},
|
||||
@ -192,7 +194,7 @@ const SwitcherPopup = new Lang.Class({
|
||||
else
|
||||
this._keyPressHandler(keysym, backwards, action);
|
||||
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
},
|
||||
|
||||
_keyReleaseEvent: function(actor, event) {
|
||||
@ -202,11 +204,12 @@ const SwitcherPopup = new Lang.Class({
|
||||
if (state == 0)
|
||||
this._finish(event.get_time());
|
||||
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
},
|
||||
|
||||
_clickedOutside: function(actor, event) {
|
||||
this.destroy();
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
},
|
||||
|
||||
_scrollHandler: function(direction) {
|
||||
@ -218,6 +221,7 @@ const SwitcherPopup = new Lang.Class({
|
||||
|
||||
_scrollEvent: function(actor, event) {
|
||||
this._scrollHandler(event.get_scroll_direction());
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
},
|
||||
|
||||
_itemActivatedHandler: function(n) {
|
||||
@ -251,6 +255,7 @@ const SwitcherPopup = new Lang.Class({
|
||||
_mouseTimedOut: function() {
|
||||
this._motionTimeoutId = 0;
|
||||
this.mouseActive = true;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
},
|
||||
|
||||
_popModal: function() {
|
||||
@ -400,6 +405,7 @@ const SwitcherList = new Lang.Class({
|
||||
|
||||
_onItemEnter: function (index) {
|
||||
this._itemEntered(index);
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
},
|
||||
|
||||
highlight: function(index, justOutline) {
|
||||
@ -446,10 +452,9 @@ const SwitcherList = new Lang.Class({
|
||||
time: POPUP_SCROLL_TIME,
|
||||
transition: 'easeOutQuad',
|
||||
onComplete: Lang.bind(this, function () {
|
||||
if (this._highlighted == 0) {
|
||||
if (this._highlighted == 0)
|
||||
this._scrollableLeft = false;
|
||||
this.actor.queue_relayout();
|
||||
}
|
||||
this.actor.queue_relayout();
|
||||
})
|
||||
});
|
||||
},
|
||||
@ -471,10 +476,9 @@ const SwitcherList = new Lang.Class({
|
||||
time: POPUP_SCROLL_TIME,
|
||||
transition: 'easeOutQuad',
|
||||
onComplete: Lang.bind(this, function () {
|
||||
if (this._highlighted == this._items.length - 1) {
|
||||
if (this._highlighted == this._items.length - 1)
|
||||
this._scrollableRight = false;
|
||||
this.actor.queue_relayout();
|
||||
}
|
||||
this.actor.queue_relayout();
|
||||
})
|
||||
});
|
||||
},
|
||||
@ -509,7 +513,7 @@ const SwitcherList = new Lang.Class({
|
||||
_getPreferredWidth: function (actor, forHeight, alloc) {
|
||||
let [maxChildMin, maxChildNat] = this._maxChildWidth(forHeight);
|
||||
|
||||
let totalSpacing = this._list.spacing * (this._items.length - 1);
|
||||
let totalSpacing = Math.max(this._list.spacing * (this._items.length - 1), 0);
|
||||
alloc.min_size = this._items.length * maxChildMin + totalSpacing;
|
||||
alloc.natural_size = alloc.min_size;
|
||||
this._minSize = alloc.min_size;
|
||||
@ -539,7 +543,7 @@ const SwitcherList = new Lang.Class({
|
||||
let childHeight = box.y2 - box.y1;
|
||||
|
||||
let [maxChildMin, maxChildNat] = this._maxChildWidth(childHeight);
|
||||
let totalSpacing = this._list.spacing * (this._items.length - 1);
|
||||
let totalSpacing = Math.max(this._list.spacing * (this._items.length - 1), 0);
|
||||
|
||||
let childWidth = Math.floor(Math.max(0, box.x2 - box.x1 - totalSpacing) / this._items.length);
|
||||
|
||||
|
@ -71,7 +71,7 @@ const UnlockDialog = new Lang.Class({
|
||||
child: otherUserLabel,
|
||||
reactive: true,
|
||||
x_align: St.Align.START,
|
||||
x_fill: true });
|
||||
x_fill: false });
|
||||
this._otherUserButton.connect('clicked', Lang.bind(this, this._otherUserClicked));
|
||||
this._promptBox.add_child(this._otherUserButton);
|
||||
} else {
|
||||
|
@ -79,9 +79,16 @@ const UserWidgetLabel = new Lang.Class({
|
||||
this._userLoadedId = this._user.connect('notify::is-loaded', Lang.bind(this, this._updateUser));
|
||||
this._userChangedId = this._user.connect('changed', Lang.bind(this, this._updateUser));
|
||||
this._updateUser();
|
||||
|
||||
// We can't override the destroy vfunc because that might be called during
|
||||
// object finalization, and we can't call any JS inside a GC finalize callback,
|
||||
// so we use a signal, that will be disconnected by GObject the first time
|
||||
// the actor is destroyed (which is guaranteed to be as part of a normal
|
||||
// destroy() call from JS, possibly from some ancestor)
|
||||
this.connect('destroy', Lang.bind(this, this._onDestroy));
|
||||
},
|
||||
|
||||
vfunc_destroy: function() {
|
||||
_onDestroy: function() {
|
||||
if (this._userLoadedId != 0) {
|
||||
this._user.disconnect(this._userLoadedId);
|
||||
this._userLoadedId = 0;
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Meta = imports.gi.Meta;
|
||||
@ -117,13 +118,11 @@ const ViewSelector = new Lang.Class({
|
||||
this._stageKeyPressId = 0;
|
||||
Main.overview.connect('showing', Lang.bind(this,
|
||||
function () {
|
||||
this._resetShowAppsButton();
|
||||
this._stageKeyPressId = global.stage.connect('key-press-event',
|
||||
Lang.bind(this, this._onStageKeyPress));
|
||||
}));
|
||||
Main.overview.connect('hiding', Lang.bind(this,
|
||||
function () {
|
||||
this._resetShowAppsButton();
|
||||
if (this._stageKeyPressId != 0) {
|
||||
global.stage.disconnect(this._stageKeyPressId);
|
||||
this._stageKeyPressId = 0;
|
||||
@ -157,24 +156,28 @@ const ViewSelector = new Lang.Class({
|
||||
},
|
||||
|
||||
show: function() {
|
||||
this._activePage = this._workspacesPage;
|
||||
|
||||
this.reset();
|
||||
this._appsPage.hide();
|
||||
this._searchPage.hide();
|
||||
|
||||
this._showAppsBlocked = true;
|
||||
this._showAppsButton.checked = false;
|
||||
this._showAppsBlocked = false;
|
||||
|
||||
this._workspacesPage.opacity = 255;
|
||||
this._workspacesDisplay.show();
|
||||
this._activePage = null;
|
||||
this._syncActivePage();
|
||||
|
||||
if (!this._workspacesDisplay.activeWorkspaceHasMaximizedWindows())
|
||||
Main.overview.fadeOutDesktop();
|
||||
|
||||
this._showPage(this._workspacesPage, true);
|
||||
},
|
||||
|
||||
zoomFromOverview: function() {
|
||||
this._workspacesDisplay.zoomFromOverview();
|
||||
|
||||
leaveOverview: function() {
|
||||
if (!this._workspacesDisplay.activeWorkspaceHasMaximizedWindows())
|
||||
Main.overview.fadeInDesktop();
|
||||
|
||||
// If we're not on the windows page, don't zoom back the primary monitor.
|
||||
let zoomPrimary = (this._activePage == this._workspacesPage);
|
||||
this._workspacesDisplay.leaveOverview(zoomPrimary);
|
||||
},
|
||||
|
||||
setWorkspacesFullGeometry: function(geom) {
|
||||
@ -183,12 +186,16 @@ const ViewSelector = new Lang.Class({
|
||||
|
||||
hide: function() {
|
||||
this._workspacesDisplay.hide();
|
||||
if (this._activePage)
|
||||
this._activePage.hide();
|
||||
this._activePage = null;
|
||||
},
|
||||
|
||||
_addPage: function(actor, name, a11yIcon, params) {
|
||||
params = Params.parse(params, { a11yFocus: null });
|
||||
|
||||
let page = new St.Bin({ child: actor,
|
||||
visible: false,
|
||||
x_align: St.Align.START,
|
||||
y_align: St.Align.START,
|
||||
x_fill: true,
|
||||
@ -203,6 +210,7 @@ const ViewSelector = new Lang.Class({
|
||||
this._a11yFocusPage(page);
|
||||
})
|
||||
});;
|
||||
page.hide();
|
||||
this.actor.add_actor(page);
|
||||
return page;
|
||||
},
|
||||
@ -212,16 +220,16 @@ const ViewSelector = new Lang.Class({
|
||||
oldPage.hide();
|
||||
|
||||
this.emit('page-empty');
|
||||
|
||||
this._activePage.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
|
||||
this._activePage.show();
|
||||
Tweener.addTween(this._activePage,
|
||||
{ opacity: 255,
|
||||
time: OverviewControls.SIDE_CONTROLS_ANIMATION_TIME,
|
||||
transition: 'easeOutQuad'
|
||||
});
|
||||
{ opacity: 255,
|
||||
time: OverviewControls.SIDE_CONTROLS_ANIMATION_TIME,
|
||||
transition: 'easeOutQuad'
|
||||
});
|
||||
},
|
||||
|
||||
_showPage: function(page, noFade) {
|
||||
_setActivePage: function(page) {
|
||||
if (page == this._activePage)
|
||||
return;
|
||||
|
||||
@ -229,7 +237,7 @@ const ViewSelector = new Lang.Class({
|
||||
this._activePage = page;
|
||||
this.emit('page-changed');
|
||||
|
||||
if (oldPage && !noFade)
|
||||
if (oldPage)
|
||||
Tweener.addTween(oldPage,
|
||||
{ opacity: 0,
|
||||
time: OverviewControls.SIDE_CONTROLS_ANIMATION_TIME,
|
||||
@ -248,27 +256,32 @@ const ViewSelector = new Lang.Class({
|
||||
page.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
|
||||
},
|
||||
|
||||
_onShowAppsButtonToggled: function() {
|
||||
if (this._showAppsBlocked)
|
||||
return;
|
||||
|
||||
this._showPage(this._showAppsButton.checked ?
|
||||
this._appsPage : this._workspacesPage);
|
||||
_getActivePage: function() {
|
||||
if (this._searchActive)
|
||||
return this._searchPage;
|
||||
else if (this._showAppsButton.checked)
|
||||
return this._appsPage;
|
||||
else
|
||||
return this._workspacesPage;
|
||||
},
|
||||
|
||||
_resetShowAppsButton: function() {
|
||||
this._showAppsBlocked = true;
|
||||
this._showAppsButton.checked = false;
|
||||
this._showAppsBlocked = false;
|
||||
_syncActivePage: function() {
|
||||
let activePage = this._getActivePage();
|
||||
if (activePage == this._activePage)
|
||||
return;
|
||||
this._setActivePage(activePage);
|
||||
},
|
||||
|
||||
this._showPage(this._workspacesPage, true);
|
||||
_onShowAppsButtonToggled: function() {
|
||||
if (!this._showAppsBlocked)
|
||||
this._syncActivePage();
|
||||
},
|
||||
|
||||
_onStageKeyPress: function(actor, event) {
|
||||
// Ignore events while anything but the overview has
|
||||
// pushed a modal (system modals, looking glass, ...)
|
||||
if (Main.modalCount > 1)
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
||||
let modifiers = event.get_state();
|
||||
let symbol = event.get_key_symbol();
|
||||
@ -280,33 +293,11 @@ const ViewSelector = new Lang.Class({
|
||||
this._showAppsButton.checked = false;
|
||||
else
|
||||
Main.overview.hide();
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
} else if (this._shouldTriggerSearch(symbol)) {
|
||||
this.startSearch(event);
|
||||
} else if (!this._searchActive) {
|
||||
if (symbol == Clutter.Tab || symbol == Clutter.Down) {
|
||||
this._activePage.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
|
||||
return true;
|
||||
} else if (symbol == Clutter.ISO_Left_Tab) {
|
||||
this._activePage.navigate_focus(null, Gtk.DirectionType.TAB_BACKWARD, false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
_searchCancelled: function() {
|
||||
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
|
||||
// two 'text-changed' signals, one for deleting the previous
|
||||
// text and one for the new one - the second one is handled
|
||||
// incorrectly when we remove focus
|
||||
// (https://bugzilla.gnome.org/show_bug.cgi?id=636341) */
|
||||
if (this._text.text != '')
|
||||
this.reset();
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
},
|
||||
|
||||
reset: function () {
|
||||
@ -399,8 +390,18 @@ const ViewSelector = new Lang.Class({
|
||||
}
|
||||
|
||||
this._entry.set_secondary_icon(null);
|
||||
this._searchCancelled();
|
||||
|
||||
// Leave the entry focused when it doesn't have any text;
|
||||
// when replacing a selected search term, Clutter emits
|
||||
// two 'text-changed' signals, one for deleting the previous
|
||||
// text and one for the new one - the second one is handled
|
||||
// incorrectly when we remove focus
|
||||
// (https://bugzilla.gnome.org/show_bug.cgi?id=636341) */
|
||||
if (this._text.text != '')
|
||||
this.reset();
|
||||
}
|
||||
|
||||
this._syncActivePage();
|
||||
},
|
||||
|
||||
_onKeyPress: function(entry, event) {
|
||||
@ -408,7 +409,7 @@ const ViewSelector = new Lang.Class({
|
||||
if (symbol == Clutter.Escape) {
|
||||
if (this._isActivated()) {
|
||||
this.reset();
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
}
|
||||
} else if (this._searchActive) {
|
||||
let arrowNext, nextDirection;
|
||||
@ -422,18 +423,18 @@ const ViewSelector = new Lang.Class({
|
||||
|
||||
if (symbol == Clutter.Tab) {
|
||||
this._searchResults.navigateFocus(Gtk.DirectionType.TAB_FORWARD);
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
} else if (symbol == Clutter.ISO_Left_Tab) {
|
||||
this._focusTrap.can_focus = false;
|
||||
this._searchResults.navigateFocus(Gtk.DirectionType.TAB_BACKWARD);
|
||||
this._focusTrap.can_focus = true;
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
} else if (symbol == Clutter.Down) {
|
||||
this._searchResults.navigateFocus(Gtk.DirectionType.DOWN);
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
} else if (symbol == arrowNext && this._text.position == -1) {
|
||||
this._searchResults.navigateFocus(nextDirection);
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
} else if (symbol == Clutter.Return || symbol == Clutter.KP_Enter) {
|
||||
// We can't connect to 'activate' here because search providers
|
||||
// might want to do something with the modifiers in activateDefault.
|
||||
@ -442,10 +443,10 @@ const ViewSelector = new Lang.Class({
|
||||
this._doSearch();
|
||||
}
|
||||
this._searchResults.activateDefault();
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
},
|
||||
|
||||
_onCapturedEvent: function(actor, event) {
|
||||
@ -460,16 +461,16 @@ const ViewSelector = new Lang.Class({
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
},
|
||||
|
||||
_doSearch: function () {
|
||||
this._searchTimeoutId = 0;
|
||||
|
||||
let terms = getTermsForSearchString(this._entry.get_text());
|
||||
|
||||
this._searchResults.setTerms(terms);
|
||||
this._showPage(this._searchPage);
|
||||
|
||||
return GLib.SOURCE_REMOVE;
|
||||
},
|
||||
|
||||
getActivePage: function() {
|
||||
@ -481,13 +482,6 @@ const ViewSelector = new Lang.Class({
|
||||
return ViewPage.SEARCH;
|
||||
},
|
||||
|
||||
setActivePage: function(page) {
|
||||
if (page == ViewPage.WINDOWS)
|
||||
this._showPage(this._workspacesPage);
|
||||
else
|
||||
this._showPage(this._appsPage);
|
||||
},
|
||||
|
||||
fadeIn: function() {
|
||||
let actor = this._activePage;
|
||||
Tweener.addTween(actor, { opacity: 255,
|
||||
|
@ -16,7 +16,7 @@ const WindowAttentionHandler = new Lang.Class({
|
||||
|
||||
_getTitleAndBanner: function(app, window) {
|
||||
let title = app.get_name();
|
||||
let banner = _("'%s' is ready").format(window.get_title());
|
||||
let banner = _("“%s” is ready").format(window.get_title());
|
||||
return [title, banner]
|
||||
},
|
||||
|
||||
|
@ -106,11 +106,11 @@ const DisplayChangeDialog = new Lang.Class({
|
||||
/* mutter already takes care of failing at timeout */
|
||||
this._timeoutId = 0;
|
||||
this.close();
|
||||
return false;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
this._descriptionLabel.text = this._formatCountDown();
|
||||
return true;
|
||||
return GLib.SOURCE_CONTINUE;
|
||||
},
|
||||
|
||||
_onFailure: function() {
|
||||
@ -232,12 +232,13 @@ const WorkspaceTracker = new Lang.Class({
|
||||
|
||||
let windows = global.get_window_actors();
|
||||
for (i = 0; i < windows.length; i++) {
|
||||
let win = windows[i];
|
||||
let actor = windows[i];
|
||||
let win = actor.get_meta_window();
|
||||
|
||||
if (win.get_meta_window().is_on_all_workspaces())
|
||||
if (win.is_on_all_workspaces())
|
||||
continue;
|
||||
|
||||
let workspaceIndex = win.get_workspace();
|
||||
let workspaceIndex = win.get_workspace().index();
|
||||
emptyWorkspaces[workspaceIndex] = false;
|
||||
}
|
||||
|
||||
@ -278,7 +279,7 @@ const WorkspaceTracker = new Lang.Class({
|
||||
workspace._keepAliveId = Mainloop.timeout_add(duration, Lang.bind(this, function() {
|
||||
workspace._keepAliveId = 0;
|
||||
this._queueCheckWorkspaces();
|
||||
return false;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
}));
|
||||
},
|
||||
|
||||
@ -290,7 +291,7 @@ const WorkspaceTracker = new Lang.Class({
|
||||
workspace._lastRemovedWindow = null;
|
||||
this._queueCheckWorkspaces();
|
||||
}
|
||||
return false;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
}));
|
||||
},
|
||||
|
||||
@ -555,6 +556,12 @@ const WindowManager = new Lang.Class({
|
||||
Shell.KeyBindingMode.LOGIN_SCREEN,
|
||||
Lang.bind(this, this._startA11ySwitcher));
|
||||
|
||||
this.addKeybinding('pause-resume-tweens',
|
||||
new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }),
|
||||
Meta.KeyBindingFlags.NONE,
|
||||
Shell.KeyBindingMode.ALL,
|
||||
Lang.bind(this, this._toggleTweens));
|
||||
|
||||
this.addKeybinding('open-application-menu',
|
||||
new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }),
|
||||
Meta.KeyBindingFlags.NONE,
|
||||
@ -742,15 +749,13 @@ const WindowManager = new Lang.Class({
|
||||
if (shouldDim && !window._dimmed) {
|
||||
window._dimmed = true;
|
||||
this._dimmedWindows.push(window);
|
||||
if (!Main.overview.visible)
|
||||
this._dimWindow(window);
|
||||
this._dimWindow(window);
|
||||
} else if (!shouldDim && window._dimmed) {
|
||||
window._dimmed = false;
|
||||
this._dimmedWindows = this._dimmedWindows.filter(function(win) {
|
||||
return win != window;
|
||||
});
|
||||
if (!Main.overview.visible)
|
||||
this._undimWindow(window);
|
||||
this._undimWindow(window);
|
||||
}
|
||||
},
|
||||
|
||||
@ -975,25 +980,29 @@ const WindowManager = new Lang.Class({
|
||||
wgroup.add_actor(switchData.movingWindowBin);
|
||||
|
||||
for (let i = 0; i < windows.length; i++) {
|
||||
let window = windows[i];
|
||||
let actor = windows[i];
|
||||
let window = actor.get_meta_window();
|
||||
|
||||
if (!window.meta_window.showing_on_its_workspace())
|
||||
if (!window.showing_on_its_workspace())
|
||||
continue;
|
||||
|
||||
if (this._movingWindow && window.meta_window == this._movingWindow) {
|
||||
switchData.movingWindow = { window: window,
|
||||
parent: window.get_parent() };
|
||||
if (window.is_on_all_workspaces())
|
||||
continue;
|
||||
|
||||
let record = { window: actor,
|
||||
parent: actor.get_parent() };
|
||||
|
||||
if (this._movingWindow && window == this._movingWindow) {
|
||||
switchData.movingWindow = record;
|
||||
switchData.windows.push(switchData.movingWindow);
|
||||
window.reparent(switchData.movingWindowBin);
|
||||
} else if (window.get_workspace() == from) {
|
||||
switchData.windows.push({ window: window,
|
||||
parent: window.get_parent() });
|
||||
window.reparent(switchData.outGroup);
|
||||
} else if (window.get_workspace() == to) {
|
||||
switchData.windows.push({ window: window,
|
||||
parent: window.get_parent() });
|
||||
window.reparent(switchData.inGroup);
|
||||
window.show();
|
||||
actor.reparent(switchData.movingWindowBin);
|
||||
} else if (window.get_workspace().index() == from) {
|
||||
switchData.windows.push(record);
|
||||
actor.reparent(switchData.outGroup);
|
||||
} else if (window.get_workspace().index() == to) {
|
||||
switchData.windows.push(record);
|
||||
actor.reparent(switchData.inGroup);
|
||||
actor.show();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1083,6 +1092,15 @@ const WindowManager = new Lang.Class({
|
||||
Main.panel.toggleAppMenu();
|
||||
},
|
||||
|
||||
_toggleTweens: function() {
|
||||
this._tweensPaused = !this._tweensPaused;
|
||||
const OrigTweener = imports.tweener.tweener;
|
||||
if (this._tweensPaused)
|
||||
OrigTweener.pauseAllTweens();
|
||||
else
|
||||
OrigTweener.resumeAllTweens();
|
||||
},
|
||||
|
||||
_showWorkspaceSwitcher : function(display, screen, window, binding) {
|
||||
if (!Main.sessionMode.hasWorkspaces)
|
||||
return;
|
||||
|
@ -1,6 +1,7 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Lang = imports.lang;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Meta = imports.gi.Meta;
|
||||
@ -13,6 +14,7 @@ const DND = imports.ui.dnd;
|
||||
const Main = imports.ui.main;
|
||||
const Overview = imports.ui.overview;
|
||||
const Tweener = imports.ui.tweener;
|
||||
const WindowManager = imports.ui.windowManager;
|
||||
|
||||
const WINDOW_DND_SIZE = 256;
|
||||
|
||||
@ -34,6 +36,68 @@ function _interpolate(start, end, step) {
|
||||
return start + (end - start) * step;
|
||||
}
|
||||
|
||||
const WindowCloneLayout = new Lang.Class({
|
||||
Name: 'WindowCloneLayout',
|
||||
Extends: Clutter.LayoutManager,
|
||||
|
||||
_init: function(boundingBox) {
|
||||
this.parent();
|
||||
|
||||
this._boundingBox = boundingBox;
|
||||
},
|
||||
|
||||
get boundingBox() {
|
||||
return this._boundingBox;
|
||||
},
|
||||
|
||||
set boundingBox(b) {
|
||||
this._boundingBox = b;
|
||||
this.layout_changed();
|
||||
},
|
||||
|
||||
_makeBoxForWindow: function(window) {
|
||||
// We need to adjust the position of the actor because of the
|
||||
// consequences of invisible borders -- in reality, the texture
|
||||
// has an extra set of "padding" around it that we need to trim
|
||||
// down.
|
||||
|
||||
// The outer rect (from which we compute the bounding box)
|
||||
// paradoxically is the smaller rectangle, containing the positions
|
||||
// of the visible frame. The input rect contains everything,
|
||||
// including the invisible border padding.
|
||||
let inputRect = window.get_input_rect();
|
||||
|
||||
let box = new Clutter.ActorBox();
|
||||
|
||||
box.set_origin(inputRect.x - this._boundingBox.x,
|
||||
inputRect.y - this._boundingBox.y);
|
||||
box.set_size(inputRect.width, inputRect.height);
|
||||
|
||||
return box;
|
||||
},
|
||||
|
||||
vfunc_get_preferred_height: function(container, forWidth) {
|
||||
return [this._boundingBox.height, this._boundingBox.height];
|
||||
},
|
||||
|
||||
vfunc_get_preferred_width: function(container, forHeight) {
|
||||
return [this._boundingBox.width, this._boundingBox.width];
|
||||
},
|
||||
|
||||
vfunc_allocate: function(container, box, flags) {
|
||||
let clone = container.get_children().forEach(function (child) {
|
||||
let realWindow;
|
||||
if (child == container._delegate._windowClone)
|
||||
realWindow = container._delegate.realWindow;
|
||||
else
|
||||
realWindow = child.source;
|
||||
|
||||
child.allocate(this._makeBoxForWindow(realWindow.meta_window),
|
||||
flags);
|
||||
}, this);
|
||||
},
|
||||
});
|
||||
|
||||
const WindowClone = new Lang.Class({
|
||||
Name: 'WindowClone',
|
||||
|
||||
@ -43,10 +107,7 @@ const WindowClone = new Lang.Class({
|
||||
this.metaWindow._delegate = this;
|
||||
this._workspace = workspace;
|
||||
|
||||
let [borderX, borderY] = this._getInvisibleBorderPadding();
|
||||
this._windowClone = new Clutter.Clone({ source: realWindow.get_texture(),
|
||||
x: -borderX,
|
||||
y: -borderY });
|
||||
this._windowClone = new Clutter.Clone({ source: realWindow.get_texture() });
|
||||
// We expect this.actor 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
|
||||
@ -54,20 +115,13 @@ const WindowClone = new Lang.Class({
|
||||
// To avoid this, we hide it from pick.
|
||||
Shell.util_set_hidden_from_pick(this._windowClone, true);
|
||||
|
||||
this.origX = realWindow.x + borderX;
|
||||
this.origY = realWindow.y + borderY;
|
||||
|
||||
let outerRect = realWindow.meta_window.get_outer_rect();
|
||||
|
||||
// The MetaShapedTexture that we clone has a size that includes
|
||||
// the invisible border; this is inconvenient; rather than trying
|
||||
// to compensate all over the place we insert a ClutterActor into
|
||||
// the hierarchy that is sized to only the visible portion.
|
||||
this.actor = new Clutter.Actor({ reactive: true,
|
||||
x: this.origX,
|
||||
y: this.origY,
|
||||
width: outerRect.width,
|
||||
height: outerRect.height });
|
||||
this.actor = new St.Widget({ reactive: true,
|
||||
can_focus: true,
|
||||
layout_manager: new WindowCloneLayout() });
|
||||
|
||||
this.actor.add_child(this._windowClone);
|
||||
|
||||
@ -77,18 +131,27 @@ const WindowClone = new Lang.Class({
|
||||
this._dragSlot = [0, 0, 0, 0];
|
||||
this._stackAbove = null;
|
||||
|
||||
this._sizeChangedId = this.realWindow.connect('size-changed',
|
||||
this._windowClone._updateId = this.realWindow.connect('size-changed',
|
||||
Lang.bind(this, this._onRealWindowSizeChanged));
|
||||
this._realWindowDestroyId = this.realWindow.connect('destroy',
|
||||
Lang.bind(this, this._disconnectRealWindowSignals));
|
||||
this._windowClone._destroyId = this.realWindow.connect('destroy', Lang.bind(this, function() {
|
||||
// First destroy the clone and then destroy everything
|
||||
// This will ensure that we never see it in the _disconnectSignals loop
|
||||
this._windowClone.destroy();
|
||||
this.destroy();
|
||||
}));
|
||||
|
||||
this._updateAttachedDialogs();
|
||||
this._computeBoundingBox();
|
||||
this.actor.x = this._boundingBox.x;
|
||||
this.actor.y = this._boundingBox.y;
|
||||
|
||||
let clickAction = new Clutter.ClickAction();
|
||||
clickAction.connect('clicked', Lang.bind(this, this._onClicked));
|
||||
clickAction.connect('long-press', Lang.bind(this, this._onLongPress));
|
||||
|
||||
this.actor.add_action(clickAction);
|
||||
|
||||
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
|
||||
this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPress));
|
||||
this.actor.connect('enter-event', Lang.bind(this, this._onEnter));
|
||||
|
||||
this._draggable = DND.makeDraggable(this.actor,
|
||||
{ restoreOnSuccess: true,
|
||||
@ -114,6 +177,83 @@ const WindowClone = new Lang.Class({
|
||||
return this._slot;
|
||||
},
|
||||
|
||||
deleteAll: function() {
|
||||
// Delete all windows, starting from the bottom-most (most-modal) one
|
||||
|
||||
let windows = this.actor.get_children();
|
||||
for (let i = windows.length - 1; i >= 1; i--) {
|
||||
let realWindow = windows[i].source;
|
||||
let metaWindow = realWindow.meta_window;
|
||||
|
||||
metaWindow.delete(global.get_current_time());
|
||||
}
|
||||
|
||||
this.metaWindow.delete(global.get_current_time());
|
||||
},
|
||||
|
||||
addAttachedDialog: function(win) {
|
||||
this._doAddAttachedDialog(win, win.get_compositor_private());
|
||||
this._computeBoundingBox();
|
||||
this.emit('size-changed');
|
||||
},
|
||||
|
||||
_doAddAttachedDialog: function(metaWin, realWin) {
|
||||
let clone = new Clutter.Clone({ source: realWin });
|
||||
clone._updateId = realWin.connect('size-changed', Lang.bind(this, function() {
|
||||
this._computeBoundingBox();
|
||||
this.emit('size-changed');
|
||||
}));
|
||||
clone._destroyId = realWin.connect('destroy', Lang.bind(this, function() {
|
||||
clone.destroy();
|
||||
|
||||
this._computeBoundingBox();
|
||||
this.emit('size-changed');
|
||||
}));
|
||||
this.actor.add_child(clone);
|
||||
},
|
||||
|
||||
_updateAttachedDialogs: function() {
|
||||
let iter = Lang.bind(this, function(win) {
|
||||
let actor = win.get_compositor_private();
|
||||
|
||||
if (!actor)
|
||||
return false;
|
||||
if (!win.is_attached_dialog())
|
||||
return false;
|
||||
|
||||
this._doAddAttachedDialog(win, actor);
|
||||
win.foreach_transient(iter);
|
||||
return true;
|
||||
});
|
||||
this.metaWindow.foreach_transient(iter);
|
||||
},
|
||||
|
||||
get boundingBox() {
|
||||
return this._boundingBox;
|
||||
},
|
||||
|
||||
getOriginalPosition: function() {
|
||||
return [this._boundingBox.x, this._boundingBox.y];
|
||||
},
|
||||
|
||||
_computeBoundingBox: function() {
|
||||
let rect = this.metaWindow.get_outer_rect();
|
||||
|
||||
this.actor.get_children().forEach(function (child) {
|
||||
let realWindow;
|
||||
if (child == this._windowClone)
|
||||
realWindow = this.realWindow;
|
||||
else
|
||||
realWindow = child.source;
|
||||
|
||||
let metaWindow = realWindow.meta_window;
|
||||
rect = rect.union(metaWindow.get_outer_rect());
|
||||
}, this);
|
||||
|
||||
this._boundingBox = rect;
|
||||
this.actor.layout_manager.boundingBox = rect;
|
||||
},
|
||||
|
||||
// Find the actor just below us, respecting reparenting done
|
||||
// by DND code
|
||||
getActualStackAbove: function() {
|
||||
@ -147,44 +287,26 @@ const WindowClone = new Lang.Class({
|
||||
this.actor.destroy();
|
||||
},
|
||||
|
||||
_disconnectRealWindowSignals: function() {
|
||||
if (this._sizeChangedId > 0)
|
||||
this.realWindow.disconnect(this._sizeChangedId);
|
||||
this._sizeChangedId = 0;
|
||||
_disconnectSignals: function() {
|
||||
this.actor.get_children().forEach(Lang.bind(this, function (child) {
|
||||
let realWindow;
|
||||
if (child == this._windowClone)
|
||||
realWindow = this.realWindow;
|
||||
else
|
||||
realWindow = child.source;
|
||||
|
||||
if (this._realWindowDestroyId > 0)
|
||||
this.realWindow.disconnect(this._realWindowDestroyId);
|
||||
this._realWindowDestroyId = 0;
|
||||
},
|
||||
|
||||
_getInvisibleBorderPadding: function() {
|
||||
// We need to adjust the position of the actor because of the
|
||||
// consequences of invisible borders -- in reality, the texture
|
||||
// has an extra set of "padding" around it that we need to trim
|
||||
// down.
|
||||
|
||||
// The outer rect paradoxically is the smaller rectangle,
|
||||
// containing the positions of the visible frame. The input
|
||||
// rect contains everything, including the invisible border
|
||||
// padding.
|
||||
let outerRect = this.metaWindow.get_outer_rect();
|
||||
let inputRect = this.metaWindow.get_input_rect();
|
||||
let [borderX, borderY] = [outerRect.x - inputRect.x,
|
||||
outerRect.y - inputRect.y];
|
||||
|
||||
return [borderX, borderY];
|
||||
realWindow.disconnect(child._updateId);
|
||||
realWindow.disconnect(child._destroyId);
|
||||
}));
|
||||
},
|
||||
|
||||
_onRealWindowSizeChanged: function() {
|
||||
let [borderX, borderY] = this._getInvisibleBorderPadding();
|
||||
let outerRect = this.metaWindow.get_outer_rect();
|
||||
this.actor.set_size(outerRect.width, outerRect.height);
|
||||
this._windowClone.set_position(-borderX, -borderY);
|
||||
this._computeBoundingBox();
|
||||
this.emit('size-changed');
|
||||
},
|
||||
|
||||
_onDestroy: function() {
|
||||
this._disconnectRealWindowSignals();
|
||||
this._disconnectSignals();
|
||||
|
||||
this.metaWindow._delegate = null;
|
||||
this.actor._delegate = null;
|
||||
@ -197,11 +319,30 @@ const WindowClone = new Lang.Class({
|
||||
this.disconnectAll();
|
||||
},
|
||||
|
||||
_onClicked: function(action, actor) {
|
||||
_activate: function() {
|
||||
this._selected = true;
|
||||
this.emit('selected', global.get_current_time());
|
||||
},
|
||||
|
||||
_onKeyPress: function(actor, event) {
|
||||
let symbol = event.get_key_symbol();
|
||||
let isEnter = (symbol == Clutter.KEY_Return || symbol == Clutter.KEY_KP_Enter);
|
||||
if (isEnter) {
|
||||
this._activate();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
_onEnter: function() {
|
||||
this.actor.grab_key_focus();
|
||||
},
|
||||
|
||||
_onClicked: function(action, actor) {
|
||||
this._activate();
|
||||
},
|
||||
|
||||
_onLongPress: function(action, actor, state) {
|
||||
// Take advantage of the Clutter policy to consider
|
||||
// a long-press canceled when the pointer movement
|
||||
@ -301,6 +442,10 @@ const WindowOverlay = new Lang.Class({
|
||||
Lang.bind(this, this._onEnter));
|
||||
windowClone.actor.connect('leave-event',
|
||||
Lang.bind(this, this._onLeave));
|
||||
windowClone.actor.connect('key-focus-in',
|
||||
Lang.bind(this, this._onEnter));
|
||||
windowClone.actor.connect('key-focus-out',
|
||||
Lang.bind(this, this._onLeave));
|
||||
|
||||
this._windowAddedId = 0;
|
||||
|
||||
@ -429,7 +574,7 @@ const WindowOverlay = new Lang.Class({
|
||||
Lang.bind(this,
|
||||
this._onWindowAdded));
|
||||
|
||||
metaWindow.delete(global.get_current_time());
|
||||
this._windowClone.deleteAll();
|
||||
},
|
||||
|
||||
_windowCanClose: function() {
|
||||
@ -448,7 +593,7 @@ const WindowOverlay = new Lang.Class({
|
||||
Mainloop.idle_add(Lang.bind(this,
|
||||
function() {
|
||||
this._windowClone.emit('selected');
|
||||
return false;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
}));
|
||||
}
|
||||
},
|
||||
@ -512,15 +657,17 @@ const WindowOverlay = new Lang.Class({
|
||||
// as the close button will be shown as needed when the overlays
|
||||
// are shown again
|
||||
if (this._hidden)
|
||||
return;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
||||
this._animateVisible();
|
||||
this.emit('show-close-button');
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
},
|
||||
|
||||
_onLeave: function() {
|
||||
if (this._idleToggleCloseId == 0)
|
||||
this._idleToggleCloseId = Mainloop.timeout_add(750, Lang.bind(this, this._idleToggleCloseButton));
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
},
|
||||
|
||||
_idleToggleCloseButton: function() {
|
||||
@ -530,7 +677,7 @@ const WindowOverlay = new Lang.Class({
|
||||
!this.closeButton.has_pointer)
|
||||
this._animateInvisible();
|
||||
|
||||
return false;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
},
|
||||
|
||||
hideCloseButton: function() {
|
||||
@ -1198,18 +1345,18 @@ const Workspace = new Lang.Class({
|
||||
// store current cursor position
|
||||
this._cursorX = x;
|
||||
this._cursorY = y;
|
||||
return true;
|
||||
return GLib.SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
let actorUnderPointer = global.stage.get_actor_at_pos(Clutter.PickMode.REACTIVE, x, y);
|
||||
for (let i = 0; i < this._windows.length; i++) {
|
||||
if (this._windows[i].actor == actorUnderPointer)
|
||||
return true;
|
||||
return GLib.SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
this._recalculateWindowPositions(WindowPositionFlags.ANIMATE);
|
||||
this._repositionWindowsId = 0;
|
||||
return false;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
},
|
||||
|
||||
_doRemoveWindow : function(metaWin) {
|
||||
@ -1284,7 +1431,7 @@ const Workspace = new Lang.Class({
|
||||
metaWin.get_compositor_private() &&
|
||||
metaWin.get_workspace() == this.metaWorkspace)
|
||||
this._doAddWindow(metaWin);
|
||||
return false;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
}));
|
||||
return;
|
||||
}
|
||||
@ -1294,9 +1441,29 @@ const Workspace = new Lang.Class({
|
||||
if (this._lookupIndex (metaWin) != -1)
|
||||
return;
|
||||
|
||||
if (!this._isMyWindow(win) || !this._isOverviewWindow(win))
|
||||
if (!this._isMyWindow(win))
|
||||
return;
|
||||
|
||||
if (!this._isOverviewWindow(win)) {
|
||||
if (metaWin.is_attached_dialog()) {
|
||||
let parent = metaWin.get_transient_for();
|
||||
while (parent.is_attached_dialog())
|
||||
parent = metaWin.get_transient_for();
|
||||
|
||||
let idx = this._lookupIndex (parent);
|
||||
if (idx < 0) {
|
||||
// parent was not created yet, it will take care
|
||||
// of the dialog when created
|
||||
return;
|
||||
}
|
||||
|
||||
let clone = this._windows[idx];
|
||||
clone.addAttachedDialog(metaWin);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
let [clone, overlay] = this._addWindowClone(win, false);
|
||||
|
||||
if (win._overviewHint) {
|
||||
@ -1354,39 +1521,46 @@ const Workspace = new Lang.Class({
|
||||
this._recalculateWindowPositions(WindowPositionFlags.ANIMATE | WindowPositionFlags.INITIAL);
|
||||
},
|
||||
|
||||
// Animates the return from Overview mode
|
||||
zoomFromOverview : function() {
|
||||
_leavingOverview: function() {
|
||||
let currentWorkspace = global.screen.get_active_workspace();
|
||||
if (this.metaWorkspace != null && this.metaWorkspace != currentWorkspace)
|
||||
return false;
|
||||
|
||||
this.leavingOverview = true;
|
||||
this._overviewHiddenId = Main.overview.connect('hidden', Lang.bind(this,
|
||||
this._doneLeavingOverview));
|
||||
|
||||
for (let i = 0; i < this._windows.length; i++) {
|
||||
let clone = this._windows[i];
|
||||
Tweener.removeTweens(clone.actor);
|
||||
|
||||
let overlay = this._windowOverlays[i];
|
||||
if (overlay)
|
||||
overlay.hide();
|
||||
}
|
||||
|
||||
if (this._repositionWindowsId > 0) {
|
||||
Mainloop.source_remove(this._repositionWindowsId);
|
||||
this._repositionWindowsId = 0;
|
||||
}
|
||||
this._overviewHiddenId = Main.overview.connect('hidden', Lang.bind(this,
|
||||
this._doneLeavingOverview));
|
||||
|
||||
if (this.metaWorkspace != null && this.metaWorkspace != currentWorkspace)
|
||||
return true;
|
||||
},
|
||||
|
||||
// Animates the return from Overview mode
|
||||
zoomFromOverview : function() {
|
||||
if (!this._leavingOverview())
|
||||
return;
|
||||
|
||||
// Position and scale the windows.
|
||||
for (let i = 0; i < this._windows.length; i++) {
|
||||
let clone = this._windows[i];
|
||||
let overlay = this._windowOverlays[i];
|
||||
|
||||
if (overlay)
|
||||
overlay.hide();
|
||||
|
||||
if (clone.metaWindow.showing_on_its_workspace()) {
|
||||
let [origX, origY] = clone.getOriginalPosition();
|
||||
|
||||
Tweener.addTween(clone.actor,
|
||||
{ x: clone.origX,
|
||||
y: clone.origY,
|
||||
{ x: origX,
|
||||
y: origY,
|
||||
scale_x: 1.0,
|
||||
scale_y: 1.0,
|
||||
time: Overview.ANIMATION_TIME,
|
||||
@ -1406,6 +1580,31 @@ const Workspace = new Lang.Class({
|
||||
}
|
||||
},
|
||||
|
||||
fadeFromOverview: function() {
|
||||
if (!this._leavingOverview())
|
||||
return;
|
||||
|
||||
for (let i = 0; i < this._windows.length; i++) {
|
||||
let clone = this._windows[i];
|
||||
|
||||
if (clone.metaWindow.showing_on_its_workspace()) {
|
||||
clone.actor.x = clone.origX;
|
||||
clone.actor.y = clone.origY;
|
||||
clone.actor.scale_x = 1.0;
|
||||
clone.actor.scale_y = 1.0;
|
||||
clone.actor.opacity = 0;
|
||||
|
||||
Tweener.addTween(clone.actor,
|
||||
{ opacity: 255,
|
||||
time: Overview.ANIMATION_TIME,
|
||||
transition: 'easeOutQuad'
|
||||
});
|
||||
} else {
|
||||
clone.actor.hide();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
destroy : function() {
|
||||
this.actor.destroy();
|
||||
},
|
||||
@ -1450,8 +1649,7 @@ const Workspace = new Lang.Class({
|
||||
|
||||
// Tests if @win should be shown in the Overview
|
||||
_isOverviewWindow : function (win) {
|
||||
let tracker = Shell.WindowTracker.get_default();
|
||||
return tracker.is_window_interesting(win.get_meta_window());
|
||||
return !win.get_meta_window().skip_taskbar;
|
||||
},
|
||||
|
||||
// Create a clone of a (non-desktop) window and add it to the window list
|
||||
|
@ -1,6 +1,7 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Lang = imports.lang;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Meta = imports.gi.Meta;
|
||||
@ -24,7 +25,7 @@ const WorkspaceSwitcherPopup = new Lang.Class({
|
||||
width: global.screen_width,
|
||||
height: global.screen_height,
|
||||
style_class: 'workspace-switcher-group' });
|
||||
Main.uiGroup.add_actor(this.actor);
|
||||
Main.layoutManager.osdGroup.add_child(this.actor);
|
||||
|
||||
this._container = new St.BoxLayout({ style_class: 'workspace-switcher-container' });
|
||||
this._list = new Shell.GenericContainer({ style_class: 'workspace-switcher' });
|
||||
@ -156,6 +157,7 @@ const WorkspaceSwitcherPopup = new Lang.Class({
|
||||
onComplete: function() { this.destroy(); },
|
||||
onCompleteScope: this
|
||||
});
|
||||
return GLib.SOURCE_REMOVE;
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Lang = imports.lang;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Meta = imports.gi.Meta;
|
||||
@ -13,6 +14,7 @@ const Background = imports.ui.background;
|
||||
const DND = imports.ui.dnd;
|
||||
const Main = imports.ui.main;
|
||||
const Tweener = imports.ui.tweener;
|
||||
const WindowManager = imports.ui.windowManager;
|
||||
const Workspace = imports.ui.workspace;
|
||||
const WorkspacesView = imports.ui.workspacesView;
|
||||
|
||||
@ -31,20 +33,49 @@ const WORKSPACE_KEEP_ALIVE_TIME = 100;
|
||||
|
||||
const OVERRIDE_SCHEMA = 'org.gnome.shell.overrides';
|
||||
|
||||
/* A layout manager that requests size only for primary_actor, but then allocates
|
||||
all using a fixed layout */
|
||||
const PrimaryActorLayout = new Lang.Class({
|
||||
Name: 'PrimaryActorLayout',
|
||||
Extends: Clutter.FixedLayout,
|
||||
|
||||
_init: function(primaryActor) {
|
||||
this.parent();
|
||||
|
||||
this.primaryActor = primaryActor;
|
||||
},
|
||||
|
||||
vfunc_get_preferred_width: function(forHeight) {
|
||||
return this.primaryActor.get_preferred_width(forHeight);
|
||||
},
|
||||
|
||||
vfunc_get_preferred_height: function(forWidth) {
|
||||
return this.primaryActor.get_preferred_height(forWidth);
|
||||
},
|
||||
});
|
||||
|
||||
const WindowClone = new Lang.Class({
|
||||
Name: 'WindowClone',
|
||||
|
||||
_init : function(realWindow) {
|
||||
this.actor = new Clutter.Clone({ source: realWindow.get_texture(),
|
||||
this.clone = new Clutter.Clone({ source: realWindow });
|
||||
|
||||
/* Can't use a Shell.GenericContainer because of DND and reparenting... */
|
||||
this.actor = new Clutter.Actor({ layout_manager: new PrimaryActorLayout(this.clone),
|
||||
reactive: true });
|
||||
this.actor._delegate = this;
|
||||
this.actor.add_child(this.clone);
|
||||
this.realWindow = realWindow;
|
||||
this.metaWindow = realWindow.meta_window;
|
||||
|
||||
this._positionChangedId = this.realWindow.connect('position-changed',
|
||||
Lang.bind(this, this._onPositionChanged));
|
||||
this._realWindowDestroyedId = this.realWindow.connect('destroy',
|
||||
Lang.bind(this, this._disconnectRealWindowSignals));
|
||||
this.clone._updateId = this.realWindow.connect('position-changed',
|
||||
Lang.bind(this, this._onPositionChanged));
|
||||
this.clone._destroyId = this.realWindow.connect('destroy', Lang.bind(this, function() {
|
||||
// First destroy the clone and then destroy everything
|
||||
// This will ensure that we never see it in the _disconnectSignals loop
|
||||
this.clone.destroy();
|
||||
this.destroy();
|
||||
}));
|
||||
this._onPositionChanged();
|
||||
|
||||
this.actor.connect('button-release-event',
|
||||
@ -60,6 +91,21 @@ const WindowClone = new Lang.Class({
|
||||
this._draggable.connect('drag-cancelled', Lang.bind(this, this._onDragCancelled));
|
||||
this._draggable.connect('drag-end', Lang.bind(this, this._onDragEnd));
|
||||
this.inDrag = false;
|
||||
|
||||
let iter = Lang.bind(this, function(win) {
|
||||
let actor = win.get_compositor_private();
|
||||
|
||||
if (!actor)
|
||||
return false;
|
||||
if (!win.is_attached_dialog())
|
||||
return false;
|
||||
|
||||
this._doAddAttachedDialog(win, actor);
|
||||
win.foreach_transient(iter);
|
||||
|
||||
return true;
|
||||
});
|
||||
this.metaWindow.foreach_transient(iter);
|
||||
},
|
||||
|
||||
// Find the actor just below us, respecting reparenting done
|
||||
@ -97,25 +143,46 @@ const WindowClone = new Lang.Class({
|
||||
this.actor.destroy();
|
||||
},
|
||||
|
||||
addAttachedDialog: function(win) {
|
||||
this._doAddAttachedDialog(win, win.get_compositor_private());
|
||||
},
|
||||
|
||||
_doAddAttachedDialog: function(metaDialog, realDialog) {
|
||||
let clone = new Clutter.Clone({ source: realDialog });
|
||||
this._updateDialogPosition(realDialog, clone);
|
||||
|
||||
clone._updateId = realDialog.connect('position-changed',
|
||||
Lang.bind(this, this._updateDialogPosition, clone));
|
||||
clone._destroyId = realDialog.connect('destroy', Lang.bind(this, function() {
|
||||
clone.destroy();
|
||||
}));
|
||||
this.actor.add_child(clone);
|
||||
},
|
||||
|
||||
_updateDialogPosition: function(realDialog, cloneDialog) {
|
||||
let metaDialog = realDialog.meta_window;
|
||||
let dialogRect = metaDialog.get_outer_rect();
|
||||
let rect = this.metaWindow.get_outer_rect();
|
||||
|
||||
cloneDialog.set_position(dialogRect.x - rect.x, dialogRect.y - rect.y);
|
||||
},
|
||||
|
||||
_onPositionChanged: function() {
|
||||
let rect = this.metaWindow.get_outer_rect();
|
||||
this.actor.set_position(this.realWindow.x, this.realWindow.y);
|
||||
},
|
||||
|
||||
_disconnectRealWindowSignals: function() {
|
||||
if (this._positionChangedId != 0) {
|
||||
this.realWindow.disconnect(this._positionChangedId);
|
||||
this._positionChangedId = 0;
|
||||
}
|
||||
_disconnectSignals: function() {
|
||||
this.actor.get_children().forEach(function(child) {
|
||||
let realWindow = child.source;
|
||||
|
||||
if (this._realWindowDestroyedId != 0) {
|
||||
this.realWindow.disconnect(this._realWindowDestroyedId);
|
||||
this._realWindowDestroyedId = 0;
|
||||
}
|
||||
realWindow.disconnect(child._updateId);
|
||||
realWindow.disconnect(child._destroyId);
|
||||
});
|
||||
},
|
||||
|
||||
_onDestroy: function() {
|
||||
this._disconnectRealWindowSignals();
|
||||
this._disconnectSignals();
|
||||
|
||||
this.actor._delegate = null;
|
||||
|
||||
@ -130,7 +197,7 @@ const WindowClone = new Lang.Class({
|
||||
_onButtonRelease : function (actor, event) {
|
||||
this.emit('selected', event.get_time());
|
||||
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
},
|
||||
|
||||
_onDragBegin : function (draggable, time) {
|
||||
@ -325,7 +392,7 @@ const WorkspaceThumbnail = new Lang.Class({
|
||||
metaWin.get_compositor_private() &&
|
||||
metaWin.get_workspace() == this.metaWorkspace)
|
||||
this._doAddWindow(metaWin);
|
||||
return false;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
}));
|
||||
return;
|
||||
}
|
||||
@ -343,10 +410,26 @@ const WorkspaceThumbnail = new Lang.Class({
|
||||
if (this._lookupIndex (metaWin) != -1)
|
||||
return;
|
||||
|
||||
if (!this._isMyWindow(win) || !this._isOverviewWindow(win))
|
||||
if (!this._isMyWindow(win))
|
||||
return;
|
||||
|
||||
let clone = this._addWindowClone(win);
|
||||
if (this._isOverviewWindow(win)) {
|
||||
this._addWindowClone(win);
|
||||
} else if (metaWin.is_attached_dialog()) {
|
||||
let parent = metaWin.get_transient_for();
|
||||
while (parent.is_attached_dialog())
|
||||
parent = metaWin.get_transient_for();
|
||||
|
||||
let idx = this._lookupIndex (parent);
|
||||
if (idx < 0) {
|
||||
// parent was not created yet, it will take care
|
||||
// of the dialog when created
|
||||
return;
|
||||
}
|
||||
|
||||
let clone = this._windows[idx];
|
||||
clone.addAttachedDialog(metaWin);
|
||||
}
|
||||
},
|
||||
|
||||
_windowAdded : function(metaWorkspace, metaWin) {
|
||||
@ -424,8 +507,7 @@ const WorkspaceThumbnail = new Lang.Class({
|
||||
|
||||
// Tests if @win should be shown in the Overview
|
||||
_isOverviewWindow : function (win) {
|
||||
let tracker = Shell.WindowTracker.get_default();
|
||||
return tracker.is_window_interesting(win.get_meta_window()) &&
|
||||
return !win.get_meta_window().skip_taskbar &&
|
||||
win.get_meta_window().showing_on_its_workspace();
|
||||
},
|
||||
|
||||
@ -561,7 +643,7 @@ const ThumbnailsBox = new Lang.Class({
|
||||
|
||||
this._thumbnails = [];
|
||||
|
||||
this.actor.connect('button-press-event', function() { return true; });
|
||||
this.actor.connect('button-press-event', function() { return Clutter.EVENT_STOP; });
|
||||
this.actor.connect('button-release-event', Lang.bind(this, this._onButtonRelease));
|
||||
|
||||
Main.overview.connect('showing',
|
||||
@ -606,7 +688,7 @@ const ThumbnailsBox = new Lang.Class({
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
},
|
||||
|
||||
_onDragBegin: function() {
|
||||
|
@ -30,6 +30,7 @@ const WorkspacesViewBase = new Lang.Class({
|
||||
this.actor = new St.Widget({ style_class: 'workspaces-view',
|
||||
reactive: true });
|
||||
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
|
||||
global.focus_manager.add_group(this.actor);
|
||||
|
||||
// The actor itself isn't a drop target, so we don't want to pick on its area
|
||||
this.actor.set_size(0, 0);
|
||||
@ -144,11 +145,22 @@ const WorkspacesView = new Lang.Class({
|
||||
this._updateWorkspaceActors(false);
|
||||
},
|
||||
|
||||
zoomFromOverview: function() {
|
||||
_leaveOverview: function() {
|
||||
this.actor.remove_clip();
|
||||
},
|
||||
|
||||
for (let w = 0; w < this._workspaces.length; w++)
|
||||
this._workspaces[w].zoomFromOverview();
|
||||
zoomFromOverview: function() {
|
||||
this._leaveOverview();
|
||||
this._workspaces.forEach(function(w) {
|
||||
w.zoomFromOverview();
|
||||
});
|
||||
},
|
||||
|
||||
fadeFromOverview: function() {
|
||||
this._leaveOverview();
|
||||
this._workspaces.forEach(function(w) {
|
||||
w.fadeFromOverview();
|
||||
});
|
||||
},
|
||||
|
||||
syncStacking: function(stackIndices) {
|
||||
@ -236,29 +248,32 @@ const WorkspacesView = new Lang.Class({
|
||||
},
|
||||
|
||||
_updateWorkspaces: function() {
|
||||
let oldNumWorkspaces = this._workspaces.length;
|
||||
let newNumWorkspaces = global.screen.n_workspaces;
|
||||
|
||||
this.scrollAdjustment.upper = newNumWorkspaces;
|
||||
|
||||
if (newNumWorkspaces > oldNumWorkspaces) {
|
||||
for (let w = oldNumWorkspaces; w < newNumWorkspaces; w++) {
|
||||
let metaWorkspace = global.screen.get_workspace_by_index(w);
|
||||
let workspace = new Workspace.Workspace(metaWorkspace, this._monitorIndex);
|
||||
this._workspaces.push(workspace);
|
||||
this.actor.add_actor(workspace.actor);
|
||||
}
|
||||
let needsUpdate = false;
|
||||
for (let j = 0; j < newNumWorkspaces; j++) {
|
||||
let metaWorkspace = global.screen.get_workspace_by_index(j);
|
||||
let workspace;
|
||||
|
||||
if (this._fullGeometry)
|
||||
this._updateWorkspaceActors(false);
|
||||
} else if (newNumWorkspaces < oldNumWorkspaces) {
|
||||
let nRemoved = (newNumWorkspaces - oldNumWorkspaces);
|
||||
let removed = this._workspaces.splice(oldNumWorkspaces, nRemoved);
|
||||
removed.forEach(function(workspace) {
|
||||
workspace.destroy();
|
||||
});
|
||||
if (j >= this._workspaces.length) { /* added */
|
||||
workspace = new Workspace.Workspace(metaWorkspace, this._monitorIndex);
|
||||
this.actor.add_actor(workspace.actor);
|
||||
this._workspaces[j] = workspace;
|
||||
} else {
|
||||
workspace = this._workspaces[j];
|
||||
|
||||
if (workspace.metaWorkspace != metaWorkspace) { /* removed */
|
||||
workspace.destroy();
|
||||
this._workspaces.splice(j, 1);
|
||||
} /* else kept */
|
||||
}
|
||||
}
|
||||
|
||||
if (this._fullGeometry)
|
||||
this._updateWorkspaceActors(false);
|
||||
|
||||
this._syncGeometry();
|
||||
},
|
||||
|
||||
@ -361,6 +376,10 @@ const ExtraWorkspaceView = new Lang.Class({
|
||||
this._workspace.zoomFromOverview();
|
||||
},
|
||||
|
||||
fadeFromOverview: function() {
|
||||
this._workspace.fadeFromOverview();
|
||||
},
|
||||
|
||||
syncStacking: function(stackIndices) {
|
||||
this._workspace.syncStacking(stackIndices);
|
||||
},
|
||||
@ -371,11 +390,21 @@ const ExtraWorkspaceView = new Lang.Class({
|
||||
},
|
||||
});
|
||||
|
||||
const DelegateFocusNavigator = new Lang.Class({
|
||||
Name: 'DelegateFocusNavigator',
|
||||
Extends: St.Widget,
|
||||
|
||||
vfunc_navigate_focus: function(from, direction) {
|
||||
return this._delegate.navigateFocus(from, direction);
|
||||
},
|
||||
});
|
||||
|
||||
const WorkspacesDisplay = new Lang.Class({
|
||||
Name: 'WorkspacesDisplay',
|
||||
|
||||
_init: function() {
|
||||
this.actor = new St.Widget({ clip_to_allocation: true });
|
||||
this.actor = new DelegateFocusNavigator({ clip_to_allocation: true });
|
||||
this.actor._delegate = this;
|
||||
this.actor.connect('notify::allocation', Lang.bind(this, this._updateWorkspacesActualGeometry));
|
||||
this.actor.connect('parent-set', Lang.bind(this, this._parentSet));
|
||||
|
||||
@ -391,7 +420,7 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
Main.overview.addAction(clickAction);
|
||||
this.actor.bind_property('mapped', clickAction, 'enabled', GObject.BindingFlags.SYNC_CREATE);
|
||||
|
||||
let panAction = new Clutter.PanAction();
|
||||
let panAction = new Clutter.PanAction({ threshold_trigger_edge: Clutter.GestureTriggerEdge.AFTER });
|
||||
panAction.connect('pan', Lang.bind(this, this._onPan));
|
||||
panAction.connect('gesture-begin', Lang.bind(this, function() {
|
||||
for (let i = 0; i < this._workspacesViews.length; i++)
|
||||
@ -399,7 +428,6 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
return true;
|
||||
}));
|
||||
panAction.connect('gesture-cancel', Lang.bind(this, function() {
|
||||
clickAction.release();
|
||||
for (let i = 0; i < this._workspacesViews.length; i++)
|
||||
this._workspacesViews[i].endSwipeScroll();
|
||||
}));
|
||||
@ -437,6 +465,10 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
return false;
|
||||
},
|
||||
|
||||
navigateFocus: function(from, direction) {
|
||||
return this._getPrimaryView().actor.navigate_focus(from, direction, false);
|
||||
},
|
||||
|
||||
show: function() {
|
||||
this._updateWorkspacesViews();
|
||||
for (let i = 0; i < this._workspacesViews.length; i++)
|
||||
@ -449,9 +481,18 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
this._scrollEventId = Main.overview.connect('scroll-event', Lang.bind(this, this._onScrollEvent));
|
||||
},
|
||||
|
||||
zoomFromOverview: function() {
|
||||
for (let i = 0; i < this._workspacesViews.length; i++)
|
||||
this._workspacesViews[i].zoomFromOverview();
|
||||
leaveOverview: function(zoomPrimary) {
|
||||
for (let i = 0; i < this._workspacesViews.length; i++) {
|
||||
let view = this._workspacesViews[i];
|
||||
if (i == this._primaryIndex) {
|
||||
if (zoomPrimary)
|
||||
view.zoomFromOverview();
|
||||
else
|
||||
view.fadeFromOverview();
|
||||
} else {
|
||||
view.zoomFromOverview();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
@ -599,7 +640,7 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
|
||||
_onScrollEvent: function(actor, event) {
|
||||
if (!this.actor.mapped)
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
let activeWs = global.screen.get_active_workspace();
|
||||
let ws;
|
||||
switch (event.get_scroll_direction()) {
|
||||
@ -610,10 +651,10 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
ws = activeWs.get_neighbor(Meta.MotionDirection.DOWN);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
}
|
||||
Main.wm.actionMoveWorkspace(ws);
|
||||
return true;
|
||||
return Clutter.EVENT_STOP;
|
||||
}
|
||||
});
|
||||
Signals.addSignalMethods(WorkspacesDisplay.prototype);
|
||||
|
@ -18,7 +18,7 @@ const XdndHandler = new Lang.Class({
|
||||
|
||||
// Used as a drag actor in case we don't have a cursor window clone
|
||||
this._dummy = new Clutter.Actor({ width: 1, height: 1, opacity: 0 });
|
||||
Main.uiGroup.add_actor(this._dummy);
|
||||
Main.layoutManager.sessionGroup.add_actor(this._dummy);
|
||||
this._dummy.hide();
|
||||
|
||||
if (!Meta.is_wayland_compositor())
|
||||
@ -62,14 +62,14 @@ const XdndHandler = new Lang.Class({
|
||||
let cursorWindow = windows[windows.length - 1];
|
||||
|
||||
// FIXME: more reliable way?
|
||||
if (!cursorWindow.is_override_redirect())
|
||||
if (!cursorWindow.get_meta_window().is_override_redirect())
|
||||
return;
|
||||
|
||||
let constraint_position = new Clutter.BindConstraint({ coordinate : Clutter.BindCoordinate.POSITION,
|
||||
source: cursorWindow});
|
||||
|
||||
this._cursorWindowClone = new Clutter.Clone({ source: cursorWindow });
|
||||
Main.uiGroup.add_actor(this._cursorWindowClone);
|
||||
Main.layoutManager.sessionGroup.add_actor(this._cursorWindowClone);
|
||||
|
||||
// Make sure that the clone has the same position as the source
|
||||
this._cursorWindowClone.add_constraint(constraint_position);
|
||||
|
219
po/et.po
219
po/et.po
@ -13,8 +13,8 @@ msgstr ""
|
||||
"Project-Id-Version: gnome-shell MASTER\n"
|
||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
|
||||
"shell&keywords=I18N+L10N&component=general\n"
|
||||
"POT-Creation-Date: 2013-09-30 11:41+0000\n"
|
||||
"PO-Revision-Date: 2013-10-01 16:40+0300\n"
|
||||
"POT-Creation-Date: 2014-01-14 01:18+0000\n"
|
||||
"PO-Revision-Date: 2014-01-14 13:33+0300\n"
|
||||
"Last-Translator: Mattias Põldaru <mahfiaz@gmail.com>\n"
|
||||
"Language-Team: Estonian <>\n"
|
||||
"Language: et\n"
|
||||
@ -68,14 +68,14 @@ msgstr ""
|
||||
"Lubab ligipääsu sisemistele silumise ja monitoorimise tööriistadele Alt-F2 "
|
||||
"dialoogi kaudu."
|
||||
|
||||
msgid "Uuids of extensions to enable"
|
||||
msgid "UUIDs of extensions to enable"
|
||||
msgstr "Lubatavate laienduste UUID-d"
|
||||
|
||||
msgid ""
|
||||
"GNOME Shell extensions have a uuid property; this key lists extensions which "
|
||||
"GNOME Shell extensions have a UUID property; this key lists extensions which "
|
||||
"should be loaded. Any extension that wants to be loaded needs to be in this "
|
||||
"list. You can also manipulate this list with the EnableExtension and "
|
||||
"DisableExtension DBus methods on org.gnome.Shell."
|
||||
"DisableExtension D-Bus methods on org.gnome.Shell."
|
||||
msgstr ""
|
||||
"GNOME Shelli laiendustel on UUID omadus; selles võtmes loetletud laiendused "
|
||||
"tuleks laadida. Seda loendit saab muuta kasutades EnableExtension ja "
|
||||
@ -106,11 +106,11 @@ msgstr "Käsudialoogi (Alt-F2) ajalugu"
|
||||
msgid "History for the looking glass dialog"
|
||||
msgstr "Otsingudialoogi ajalugu"
|
||||
|
||||
msgid "Always show the 'Log out' menuitem in the user menu."
|
||||
msgid "Always show the 'Log out' menu item in the user menu."
|
||||
msgstr "Kasutajamenüüs näidatakse alati 'Logi välja' menüükirjet."
|
||||
|
||||
msgid ""
|
||||
"This key overrides the automatic hiding of the 'Log out' menuitem in single-"
|
||||
"This key overrides the automatic hiding of the 'Log out' menu item in single-"
|
||||
"user, single-session situations."
|
||||
msgstr ""
|
||||
"See võti keelab automaatse 'Logi välja' menüükirje peitmise, kui arvutis on "
|
||||
@ -218,6 +218,13 @@ msgstr "Tööalad peamisel monitoril"
|
||||
msgid "Delay focus changes in mouse mode until the pointer stops moving"
|
||||
msgstr "Hiire all asuv aken saab fookuse alles hiire peatumisel"
|
||||
|
||||
#, javascript-format
|
||||
msgid "There was an error loading the preferences dialog for %s:"
|
||||
msgstr "%s jaoks eelistuste dialoogi laadimisel esines viga:"
|
||||
|
||||
msgid "Extension"
|
||||
msgstr "Laiendus"
|
||||
|
||||
msgid "Select an extension to configure using the combobox above."
|
||||
msgstr "Vali seadistatav laiendus kasutades ülemist valikukasti."
|
||||
|
||||
@ -240,6 +247,7 @@ msgstr "Seansi valimine"
|
||||
msgid "Not listed?"
|
||||
msgstr "Pole loendis?"
|
||||
|
||||
#, javascript-format
|
||||
msgid "(e.g., user or %s)"
|
||||
msgstr "(nt 'user' või %s)"
|
||||
|
||||
@ -261,6 +269,7 @@ msgstr "Käsku ei leitud"
|
||||
msgid "Could not parse command:"
|
||||
msgstr "Käsku pole võimalik analüüsida:"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Execution of '%s' failed:"
|
||||
msgstr "'%s' käivitamine nurjus:"
|
||||
|
||||
@ -282,9 +291,11 @@ msgstr "Eemalda lemmikutest"
|
||||
msgid "Add to Favorites"
|
||||
msgstr "Lisa lemmikutesse"
|
||||
|
||||
#, javascript-format
|
||||
msgid "%s has been added to your favorites."
|
||||
msgstr "%s lisati lemmikutesse."
|
||||
|
||||
#, javascript-format
|
||||
msgid "%s has been removed from your favorites."
|
||||
msgstr "%s eemaldati lemmikutest."
|
||||
|
||||
@ -437,6 +448,7 @@ msgstr "Väline ketas eemaldati"
|
||||
msgid "Removable Devices"
|
||||
msgstr "Eemaldatavad seadmed"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Open with %s"
|
||||
msgstr "Ava programmiga %s"
|
||||
|
||||
@ -470,6 +482,7 @@ msgstr "Teenus: "
|
||||
msgid "Authentication required by wireless network"
|
||||
msgstr "Juhtmeta võrgu jaoks on vajalik autentimine"
|
||||
|
||||
#, javascript-format
|
||||
msgid ""
|
||||
"Passwords or encryption keys are required to access the wireless network "
|
||||
"'%s'."
|
||||
@ -497,6 +510,7 @@ msgstr "PIN: "
|
||||
msgid "Mobile broadband network password"
|
||||
msgstr "Mobiiliühenduse võrgu parool"
|
||||
|
||||
#, javascript-format
|
||||
msgid "A password is required to connect to '%s'."
|
||||
msgstr "'%s' ühenduse loomiseks on vaja parooli."
|
||||
|
||||
@ -552,17 +566,20 @@ msgstr "<b>%d. %B %Y</b>, <b>%H:%M</b>"
|
||||
|
||||
#. Translators: this is the other person changing their old IM name to their new
|
||||
#. IM name. */
|
||||
#, javascript-format
|
||||
msgid "%s is now known as %s"
|
||||
msgstr "%s nimi on nüüd %s"
|
||||
|
||||
#. translators: argument is a room name like
|
||||
#. * room@jabber.org for example. */
|
||||
#, javascript-format
|
||||
msgid "Invitation to %s"
|
||||
msgstr "Kutse: %s"
|
||||
|
||||
#. translators: first argument is the name of a contact and the second
|
||||
#. * one the name of a room. "Alice is inviting you to join room@jabber.org
|
||||
#. * for example. */
|
||||
#, javascript-format
|
||||
msgid "%s is inviting you to join %s"
|
||||
msgstr "%s kutsub sind liituma: %s"
|
||||
|
||||
@ -573,10 +590,12 @@ msgid "Accept"
|
||||
msgstr "Nõustu"
|
||||
|
||||
#. translators: argument is a contact name like Alice for example. */
|
||||
#, javascript-format
|
||||
msgid "Video call from %s"
|
||||
msgstr "%s tahab alustada videokõnet"
|
||||
|
||||
#. translators: argument is a contact name like Alice for example. */
|
||||
#, javascript-format
|
||||
msgid "Call from %s"
|
||||
msgstr "%s helistab"
|
||||
|
||||
@ -589,10 +608,12 @@ msgstr "Vasta"
|
||||
#. * file name. The string will be something
|
||||
#. * like: "Alice is sending you test.ogg"
|
||||
#. */
|
||||
#, javascript-format
|
||||
msgid "%s is sending you %s"
|
||||
msgstr "%s saadab sulle %s"
|
||||
|
||||
#. To translators: The parameter is the contact's alias */
|
||||
#, javascript-format
|
||||
msgid "%s would like permission to see when you are online"
|
||||
msgstr "%s palub sinu luba, et näha, kui sa oled võrgus"
|
||||
|
||||
@ -677,6 +698,7 @@ msgstr "Sisemine viga"
|
||||
|
||||
#. translators: argument is the account name, like
|
||||
#. * name@jabber.org for example. */
|
||||
#, javascript-format
|
||||
msgid "Unable to connect to %s"
|
||||
msgstr "Pole võimalik ühenduda võrguga %s"
|
||||
|
||||
@ -710,6 +732,7 @@ msgstr "Kuupäeva ja kella sätted"
|
||||
msgid "%A %B %e, %Y"
|
||||
msgstr "%A, %d. %B %Y"
|
||||
|
||||
#, javascript-format
|
||||
msgctxt "title"
|
||||
msgid "Log Out %s"
|
||||
msgstr "%s väljalogimine"
|
||||
@ -718,11 +741,13 @@ msgctxt "title"
|
||||
msgid "Log Out"
|
||||
msgstr "Väljalogimine"
|
||||
|
||||
#, javascript-format
|
||||
msgid "%s will be logged out automatically in %d second."
|
||||
msgid_plural "%s will be logged out automatically in %d seconds."
|
||||
msgstr[0] "%s logitakse %d sekundi pärast automaatselt välja."
|
||||
msgstr[1] "%s logitakse %d sekundi pärast automaatselt välja."
|
||||
|
||||
#, javascript-format
|
||||
msgid "You will be logged out automatically in %d second."
|
||||
msgid_plural "You will be logged out automatically in %d seconds."
|
||||
msgstr[0] "Sind logitakse %d sekundi pärast automaatselt välja."
|
||||
@ -736,6 +761,7 @@ msgctxt "title"
|
||||
msgid "Power Off"
|
||||
msgstr "Väljalülitamine"
|
||||
|
||||
#, javascript-format
|
||||
msgid "The system will power off automatically in %d second."
|
||||
msgid_plural "The system will power off automatically in %d seconds."
|
||||
msgstr[0] "%d sekundi pärast lülitub süsteem automaatselt välja."
|
||||
@ -753,6 +779,7 @@ msgctxt "title"
|
||||
msgid "Restart"
|
||||
msgstr "Taaskäivitamine"
|
||||
|
||||
#, javascript-format
|
||||
msgid "The system will restart automatically in %d second."
|
||||
msgid_plural "The system will restart automatically in %d seconds."
|
||||
msgstr[0] "Süsteem taaskäivitub automaatselt %d sekundi pärast."
|
||||
@ -762,6 +789,7 @@ msgctxt "title"
|
||||
msgid "Restart & Install Updates"
|
||||
msgstr "Taaskäivitamine ja uuenduste paigaldamine"
|
||||
|
||||
#, javascript-format
|
||||
msgid "The system will automatically restart and install updates in %d second."
|
||||
msgid_plural ""
|
||||
"The system will automatically restart and install updates in %d seconds."
|
||||
@ -779,16 +807,19 @@ msgid "Other users are logged in."
|
||||
msgstr "Teised kasutajad on sisse logitud."
|
||||
|
||||
#. Translators: Remote here refers to a remote session, like a ssh login */
|
||||
#, javascript-format
|
||||
msgid "%s (remote)"
|
||||
msgstr "%s (kaugühendus)"
|
||||
|
||||
#. Translators: Console here refers to a tty like a VT console */
|
||||
#, javascript-format
|
||||
msgid "%s (console)"
|
||||
msgstr "%s (konsool)"
|
||||
|
||||
msgid "Install"
|
||||
msgstr "Paigalda"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Download and install '%s' from extensions.gnome.org?"
|
||||
msgstr "Kas laadida alla ja paigaldada '%s' aadressilt extensions.gnome.org?"
|
||||
|
||||
@ -799,6 +830,7 @@ msgid "No extensions installed"
|
||||
msgstr "Ühtegi laiendust pole paigaldatud"
|
||||
|
||||
#. Translators: argument is an extension UUID. */
|
||||
#, javascript-format
|
||||
msgid "%s has not emitted any errors."
|
||||
msgstr "%s ei ole väljastanud ühtegi veateadet."
|
||||
|
||||
@ -811,6 +843,8 @@ msgstr "Näita vigu"
|
||||
msgid "Enabled"
|
||||
msgstr "Lubatud"
|
||||
|
||||
#. Translators: this is for a network device that cannot be activated
|
||||
#. because it's disabled by rfkill (airplane mode) */
|
||||
#. translators:
|
||||
#. * The device has been disabled
|
||||
msgid "Disabled"
|
||||
@ -837,6 +871,9 @@ msgstr "Ava"
|
||||
msgid "Remove"
|
||||
msgstr "Eemalda"
|
||||
|
||||
msgid "Notifications"
|
||||
msgstr "Märguanded"
|
||||
|
||||
msgid "Clear Messages"
|
||||
msgstr "Kustuta teated"
|
||||
|
||||
@ -859,6 +896,7 @@ msgctxt "program"
|
||||
msgid "Unknown"
|
||||
msgstr "Tundmatu"
|
||||
|
||||
#, javascript-format
|
||||
msgid "%d new message"
|
||||
msgid_plural "%d new messages"
|
||||
msgstr[0] "%d uus sõnum"
|
||||
@ -902,6 +940,7 @@ msgstr "Sulge"
|
||||
msgid "%A, %B %d"
|
||||
msgstr "%A, %d. %B"
|
||||
|
||||
#, javascript-format
|
||||
msgid "%d new notification"
|
||||
msgid_plural "%d new notifications"
|
||||
msgstr[0] "%d uus märguanne"
|
||||
@ -985,71 +1024,24 @@ msgstr "Lülita välja"
|
||||
msgid "Bluetooth Settings"
|
||||
msgstr "Bluetoothi sätted"
|
||||
|
||||
#, javascript-format
|
||||
msgid "%d Connected Device"
|
||||
msgid_plural "%d Connected Devices"
|
||||
msgstr[0] "%d ühendatud seade"
|
||||
msgstr[1] "%d ühendatud seadet"
|
||||
|
||||
msgid "Authorization request from %s"
|
||||
msgstr "Autoriseerimise päring seadmelt %s"
|
||||
|
||||
msgid "Device %s wants to pair with this computer"
|
||||
msgstr "Seade '%s' tahab selle arvutiga paarduda"
|
||||
|
||||
msgid "Allow"
|
||||
msgstr "Luba"
|
||||
|
||||
msgid "Deny"
|
||||
msgstr "Keela"
|
||||
|
||||
msgid "Device %s wants access to the service '%s'"
|
||||
msgstr "Seade %s soovib ligipääsu teenusele '%s'"
|
||||
|
||||
msgid "Always grant access"
|
||||
msgstr "Luba alati"
|
||||
|
||||
msgid "Grant this time only"
|
||||
msgstr "Luba ainult seekord"
|
||||
|
||||
msgid "Reject"
|
||||
msgstr "Lükka tagasi"
|
||||
|
||||
#. Translators: argument is the device short name */
|
||||
msgid "Pairing confirmation for %s"
|
||||
msgstr "Paardumise kinnitus seadmele %s"
|
||||
|
||||
msgid ""
|
||||
"Please confirm whether the Passkey '%06d' matches the one on the device."
|
||||
msgstr "Palun kontrolli, kas parool '%06d' kattub seadme parooliga."
|
||||
|
||||
#. Translators: this is the verb, not the noun */
|
||||
msgid "Matches"
|
||||
msgstr "Kattub"
|
||||
|
||||
msgid "Does not match"
|
||||
msgstr "Ei kattu"
|
||||
|
||||
msgid "Pairing request for %s"
|
||||
msgstr "Seadmega %s paardumise päring"
|
||||
|
||||
msgid "Please enter the PIN mentioned on the device."
|
||||
msgstr "Palun sisesta seadme poolt öeldav PIN-kood."
|
||||
|
||||
msgid "OK"
|
||||
msgstr "Olgu"
|
||||
|
||||
msgid "Brightness"
|
||||
msgstr "Heledus"
|
||||
|
||||
msgid "Show Keyboard Layout"
|
||||
msgstr "Klaviatuuripaigutuse kuvamine"
|
||||
|
||||
msgid "<unknown>"
|
||||
msgstr "<tundmatu>"
|
||||
|
||||
msgid "Off"
|
||||
msgstr "Väljas"
|
||||
|
||||
msgid "Network Settings"
|
||||
msgstr "Võrgusätted"
|
||||
|
||||
#. Translators: this is for network devices that are physically present but are not
|
||||
#. under NetworkManager's control (and thus cannot be used in the menu) */
|
||||
msgid "unmanaged"
|
||||
@ -1078,6 +1070,12 @@ msgstr "pole saadaval"
|
||||
msgid "connection failed"
|
||||
msgstr "ühendumine nurjus"
|
||||
|
||||
msgid "Mobile Broadband Settings"
|
||||
msgstr "Mobiiliühenduse sätted"
|
||||
|
||||
msgid "Hardware Disabled"
|
||||
msgstr "Riistvara on keelatud"
|
||||
|
||||
msgid "Wi-Fi Networks"
|
||||
msgstr "Wi-Fi võrgud"
|
||||
|
||||
@ -1090,9 +1088,15 @@ msgstr "Võrke pole"
|
||||
msgid "Select Network"
|
||||
msgstr "Võrgu valimine"
|
||||
|
||||
msgid "Wi-Fi Settings"
|
||||
msgstr "Wi-Fi sätted"
|
||||
|
||||
msgid "Turn On"
|
||||
msgstr "Lülita sisse"
|
||||
|
||||
msgid "Not Connected"
|
||||
msgstr "Pole ühenduses"
|
||||
|
||||
msgid "VPN"
|
||||
msgstr "VPN"
|
||||
|
||||
@ -1105,9 +1109,6 @@ msgstr "Ühendus nurjus"
|
||||
msgid "Activation of network connection failed"
|
||||
msgstr "Võrguühenduse aktiveerimine nurjus"
|
||||
|
||||
msgid "Battery"
|
||||
msgstr "Aku"
|
||||
|
||||
msgid "Power Settings"
|
||||
msgstr "Toitesätted..."
|
||||
|
||||
@ -1117,18 +1118,29 @@ msgstr "Täiesti täis"
|
||||
msgid "Estimating…"
|
||||
msgstr "Andmete kogumine…"
|
||||
|
||||
#, javascript-format
|
||||
msgid "%d∶%02d Remaining (%d%%)"
|
||||
msgstr "%d∶%02d jäänud (%d%%)"
|
||||
|
||||
#, javascript-format
|
||||
msgid "%d∶%02d Until Full (%d%%)"
|
||||
msgstr "%d∶%02d täitumiseni (%d%%)"
|
||||
|
||||
msgid "UPS"
|
||||
msgstr "UPS"
|
||||
|
||||
msgid "Battery"
|
||||
msgstr "Aku"
|
||||
|
||||
msgid "Airplane Mode"
|
||||
msgstr "Lennukirežiim"
|
||||
|
||||
msgid "On"
|
||||
msgstr "Sees"
|
||||
|
||||
msgid "Network Settings"
|
||||
msgstr "Võrgusätted"
|
||||
|
||||
msgid "Switch User"
|
||||
msgstr "Vaheta kasutajat"
|
||||
|
||||
@ -1165,16 +1177,7 @@ msgstr "Rakendused"
|
||||
msgid "Search"
|
||||
msgstr "Otsing"
|
||||
|
||||
msgid ""
|
||||
"Sorry, no wisdom for you today:\n"
|
||||
"%s"
|
||||
msgstr ""
|
||||
"Vabandust, tänaseks tarkuseteri pole:\n"
|
||||
"%s"
|
||||
|
||||
msgid "%s the Oracle says"
|
||||
msgstr "Oraakel %s ütleb"
|
||||
|
||||
#, javascript-format
|
||||
msgid "'%s' is ready"
|
||||
msgstr "'%s' on valmis"
|
||||
|
||||
@ -1190,6 +1193,7 @@ msgstr "Taasta sätted"
|
||||
msgid "Keep Changes"
|
||||
msgstr "Säilita muudatused"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Settings changes will revert in %d second"
|
||||
msgid_plural "Settings changes will revert in %d seconds"
|
||||
msgstr[0] "Sätete muudatused ennistatakse %d sekundi pärast"
|
||||
@ -1242,11 +1246,61 @@ msgstr "Parool ei saa olla tühi"
|
||||
msgid "Authentication dialog was dismissed by the user"
|
||||
msgstr "Kasutaja katkestas autentimisdialoogi"
|
||||
|
||||
#~ msgid "There was an error loading the preferences dialog for %s:"
|
||||
#~ msgstr "%s jaoks eelistuste dialoogi laadimisel esines viga:"
|
||||
#~ msgid "Authorization request from %s"
|
||||
#~ msgstr "Autoriseerimise päring seadmelt %s"
|
||||
|
||||
#~ msgid "Extension"
|
||||
#~ msgstr "Laiendus"
|
||||
#~ msgid "Device %s wants to pair with this computer"
|
||||
#~ msgstr "Seade '%s' tahab selle arvutiga paarduda"
|
||||
|
||||
#~ msgid "Allow"
|
||||
#~ msgstr "Luba"
|
||||
|
||||
#~ msgid "Deny"
|
||||
#~ msgstr "Keela"
|
||||
|
||||
#~ msgid "Device %s wants access to the service '%s'"
|
||||
#~ msgstr "Seade %s soovib ligipääsu teenusele '%s'"
|
||||
|
||||
#~ msgid "Always grant access"
|
||||
#~ msgstr "Luba alati"
|
||||
|
||||
#~ msgid "Grant this time only"
|
||||
#~ msgstr "Luba ainult seekord"
|
||||
|
||||
#~ msgid "Reject"
|
||||
#~ msgstr "Lükka tagasi"
|
||||
|
||||
#~ msgid "Pairing confirmation for %s"
|
||||
#~ msgstr "Paardumise kinnitus seadmele %s"
|
||||
|
||||
#~ msgid ""
|
||||
#~ "Please confirm whether the Passkey '%06d' matches the one on the device."
|
||||
#~ msgstr "Palun kontrolli, kas parool '%06d' kattub seadme parooliga."
|
||||
|
||||
#~ msgid "Matches"
|
||||
#~ msgstr "Kattub"
|
||||
|
||||
#~ msgid "Does not match"
|
||||
#~ msgstr "Ei kattu"
|
||||
|
||||
#~ msgid "Pairing request for %s"
|
||||
#~ msgstr "Seadmega %s paardumise päring"
|
||||
|
||||
#~ msgid "Please enter the PIN mentioned on the device."
|
||||
#~ msgstr "Palun sisesta seadme poolt öeldav PIN-kood."
|
||||
|
||||
#~ msgid "OK"
|
||||
#~ msgstr "Olgu"
|
||||
|
||||
#~ msgid ""
|
||||
#~ "Sorry, no wisdom for you today:\n"
|
||||
#~ "%s"
|
||||
#~ msgstr ""
|
||||
#~ "Vabandust, tänaseks tarkuseteri pole:\n"
|
||||
#~ "%s"
|
||||
|
||||
#~ msgid "%s the Oracle says"
|
||||
#~ msgstr "Oraakel %s ütleb"
|
||||
|
||||
#~ msgctxt "event list time"
|
||||
#~ msgid "%H\\u2236%M"
|
||||
@ -1256,9 +1310,6 @@ msgstr "Kasutaja katkestas autentimisdialoogi"
|
||||
#~ msgid "%l\\u2236%M\\u2009%p"
|
||||
#~ msgstr "%l\\u2236%M\\u2009%p"
|
||||
|
||||
#~ msgid "Show Keyboard Layout"
|
||||
#~ msgstr "Klaviatuuripaigutuse kuvamine"
|
||||
|
||||
#~ msgid "Settings Menu"
|
||||
#~ msgstr "Sätete menüü"
|
||||
|
||||
@ -1400,9 +1451,6 @@ msgstr "Kasutaja katkestas autentimisdialoogi"
|
||||
#~ msgid "Set Up a New Device…"
|
||||
#~ msgstr "Uue seadme häälestamine…"
|
||||
|
||||
#~ msgid "hardware disabled"
|
||||
#~ msgstr "riistvara on keelatud"
|
||||
|
||||
#~ msgid "Connection"
|
||||
#~ msgstr "Ühendus"
|
||||
|
||||
@ -1439,9 +1487,6 @@ msgstr "Kasutaja katkestas autentimisdialoogi"
|
||||
#~ msgid "Auto Ethernet"
|
||||
#~ msgstr "Automaatne ethernet"
|
||||
|
||||
#~ msgid "Mobile broadband"
|
||||
#~ msgstr "Mobiiliühendus"
|
||||
|
||||
#~ msgid "Auto broadband"
|
||||
#~ msgstr "Automaatne lairibaühendus"
|
||||
|
||||
@ -1496,9 +1541,6 @@ msgstr "Kasutaja katkestas autentimisdialoogi"
|
||||
#~ msgid "Laptop Battery"
|
||||
#~ msgstr "Sülearvuti aku"
|
||||
|
||||
#~ msgid "UPS"
|
||||
#~ msgstr "UPS"
|
||||
|
||||
#~ msgid "Monitor"
|
||||
#~ msgstr "Monitor"
|
||||
|
||||
@ -1539,9 +1581,6 @@ msgstr "Kasutaja katkestas autentimisdialoogi"
|
||||
#~ msgid "Idle"
|
||||
#~ msgstr "Jõude"
|
||||
|
||||
#~ msgid "Notifications"
|
||||
#~ msgstr "Märguanded"
|
||||
|
||||
#~ msgid "Your chat status will be set to busy"
|
||||
#~ msgstr "Sinu vestluse olekuks määratakse hõivatud"
|
||||
|
||||
|
854
po/pt_BR.po
854
po/pt_BR.po
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user