Compare commits
175 Commits
2.27.1
...
shell-tool
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
83f37da1c1 | ||
|
|
c2706add36 | ||
|
|
0a187b7222 | ||
|
|
3abe92d15d | ||
|
|
45b4d0384c | ||
|
|
083eed140c | ||
|
|
1283f0b160 | ||
|
|
3bbdc1e1e1 | ||
|
|
25f1246b6f | ||
|
|
a37c86636b | ||
|
|
4057cfaa17 | ||
|
|
76443e91cd | ||
|
|
d3c4c1f5ed | ||
|
|
040ddf077c | ||
|
|
f313d38458 | ||
|
|
304b48a15d | ||
|
|
d92b1d8da2 | ||
|
|
df3ac4b25e | ||
|
|
0ce05a04c8 | ||
|
|
c1c4adda02 | ||
|
|
595242c389 | ||
|
|
7e678ef0d2 | ||
|
|
ebbf304899 | ||
|
|
2077485827 | ||
|
|
0c0a0c66e2 | ||
|
|
2412a89445 | ||
|
|
789e268264 | ||
|
|
7507d10223 | ||
|
|
b18a8ebcae | ||
|
|
ed07413c20 | ||
|
|
f94eab803b | ||
|
|
0315a6e4a8 | ||
|
|
48085dd428 | ||
|
|
099b73a0c4 | ||
|
|
b8d46422d5 | ||
|
|
459bdfba78 | ||
|
|
66414ea3f6 | ||
|
|
d453067e24 | ||
|
|
ae320a26fc | ||
|
|
373fa3c325 | ||
|
|
84a6a6faf0 | ||
|
|
9432ddb12e | ||
|
|
d4a2f9e604 | ||
|
|
7f468b36e7 | ||
|
|
349e5b39af | ||
|
|
cad774aca1 | ||
|
|
b25bbf4c0a | ||
|
|
72dd458c80 | ||
|
|
79d5d3dba0 | ||
|
|
c14a4deddf | ||
|
|
4bab511fa5 | ||
|
|
36b11ee8c7 | ||
|
|
3ffc510be7 | ||
|
|
ec92bfba14 | ||
|
|
f5f22b3935 | ||
|
|
159081dcfc | ||
|
|
1da4837d98 | ||
|
|
0f63ae1869 | ||
|
|
32ef951fe0 | ||
|
|
3564d78d30 | ||
|
|
4bff2675ae | ||
|
|
2020d15a1a | ||
|
|
64d8d7a91c | ||
|
|
eb025901c8 | ||
|
|
9fee99bc7a | ||
|
|
67bfbc9b4b | ||
|
|
11d884d724 | ||
|
|
24d42adc04 | ||
|
|
110ef17e2d | ||
|
|
0143512e00 | ||
|
|
4876474be3 | ||
|
|
0e4a86f2e6 | ||
|
|
18dbc5462f | ||
|
|
8f660f563c | ||
|
|
fa316ddd3d | ||
|
|
7703bee284 | ||
|
|
90e6769638 | ||
|
|
0b6d09bbe2 | ||
|
|
3734479cbd | ||
|
|
6cae94edcc | ||
|
|
0918bdd612 | ||
|
|
a75b1abc93 | ||
|
|
e6a08cc9fd | ||
|
|
09c9defbf0 | ||
|
|
3ba6ff4ca9 | ||
|
|
19fa0b5d5b | ||
|
|
79db50500d | ||
|
|
f26c9ab245 | ||
|
|
293adb9bcc | ||
|
|
e79b15c645 | ||
|
|
08603c1524 | ||
|
|
cee7106cb1 | ||
|
|
2c0661d377 | ||
|
|
471006ba67 | ||
|
|
98bd590a5d | ||
|
|
9d88a13d3c | ||
|
|
159690b2d3 | ||
|
|
8a2bfd0e55 | ||
|
|
2ddc7cf00f | ||
|
|
04f10ceb4e | ||
|
|
ceefc5eea4 | ||
|
|
9feda69888 | ||
|
|
33f9895d71 | ||
|
|
2812c21322 | ||
|
|
7ac9fb2dd0 | ||
|
|
05c99241d6 | ||
|
|
9fb8dad80c | ||
|
|
004ad86e9d | ||
|
|
02c65fab8d | ||
|
|
dfe16f4af6 | ||
|
|
e52cb3c213 | ||
|
|
6e31e59b57 | ||
|
|
458778bcfd | ||
|
|
d8cabbee0b | ||
|
|
3029a4086b | ||
|
|
5598de6543 | ||
|
|
913aeae166 | ||
|
|
dddad9e1b5 | ||
|
|
4bfa68d209 | ||
|
|
42e3a93c20 | ||
|
|
05812ef7f9 | ||
|
|
a0df412deb | ||
|
|
678a88dbdb | ||
|
|
5e944c9a3b | ||
|
|
b28b60b47b | ||
|
|
16caa74386 | ||
|
|
470c65d046 | ||
|
|
ef6ea078dd | ||
|
|
37ee16b34d | ||
|
|
5880b3b0ed | ||
|
|
80a5f78eb2 | ||
|
|
4b727ef40d | ||
|
|
d0d79c5b3e | ||
|
|
0882da0a71 | ||
|
|
25410a730e | ||
|
|
22c445cffc | ||
|
|
42bf91fdc4 | ||
|
|
7f88e02a26 | ||
|
|
d540af847a | ||
|
|
2f78907aeb | ||
|
|
d471541495 | ||
|
|
fa5fb6b8a8 | ||
|
|
0a29cf6195 | ||
|
|
b7b4c54ab5 | ||
|
|
52abf266c0 | ||
|
|
11872cfb79 | ||
|
|
21309aa28f | ||
|
|
38d21c8edf | ||
|
|
090908439b | ||
|
|
0a17a28608 | ||
|
|
926643b025 | ||
|
|
1a834f7d8b | ||
|
|
3e54087e42 | ||
|
|
304b377dae | ||
|
|
ac4bcee050 | ||
|
|
553503dace | ||
|
|
90381ceea2 | ||
|
|
687814b6c6 | ||
|
|
6153094057 | ||
|
|
0245a0cd0e | ||
|
|
bcc3dc0711 | ||
|
|
3d499219da | ||
|
|
94b26888cf | ||
|
|
156fdf1fa3 | ||
|
|
2a3f9e8f83 | ||
|
|
849ce371ff | ||
|
|
a76ac5501c | ||
|
|
5803aa7e65 | ||
|
|
0fd6bc5172 | ||
|
|
0e3cea41e0 | ||
|
|
45c600cd25 | ||
|
|
7fb8e2d0ef | ||
|
|
2d5d54f3cd | ||
|
|
949359db5d | ||
|
|
5bd2695863 |
2
.gitignore
vendored
@@ -38,5 +38,7 @@ src/gnomeshell-taskpanel
|
|||||||
src/gnome-shell
|
src/gnome-shell
|
||||||
src/test-recorder
|
src/test-recorder
|
||||||
src/test-recorder.ogg
|
src/test-recorder.ogg
|
||||||
|
src/test-theme
|
||||||
stamp-h1
|
stamp-h1
|
||||||
|
tests/run-test.sh
|
||||||
xmldocs.make
|
xmldocs.make
|
||||||
|
|||||||
17
Makefile.am
@@ -1,13 +1,22 @@
|
|||||||
SUBDIRS = data js src po
|
SUBDIRS = data js src tests po
|
||||||
|
|
||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
.project \
|
.project \
|
||||||
.settings
|
.settings \
|
||||||
|
autogen.sh
|
||||||
|
|
||||||
|
# These are files checked into Git that we don't want to distribute
|
||||||
|
DIST_EXCLUDE = \
|
||||||
|
.gitignore \
|
||||||
|
gnome-shell.doap \
|
||||||
|
MAINTAINERS \
|
||||||
|
tools/build/*
|
||||||
|
|
||||||
distcheck-hook:
|
distcheck-hook:
|
||||||
@echo "Checking disted javascript against files in git"
|
@echo "Checking disted files against files in git"
|
||||||
@failed=false; \
|
@failed=false; \
|
||||||
for f in `cd $(srcdir) && git ls-files js` ; do \
|
exclude=`(for p in $(DIST_EXCLUDE) ; do echo --exclude=$$p ; done)`; \
|
||||||
|
for f in `cd $(srcdir) && git ls-files $$exclude` ; do \
|
||||||
if ! test -e $(distdir)/$$f ; then \
|
if ! test -e $(distdir)/$$f ; then \
|
||||||
echo File missing from distribution: $$f ; \
|
echo File missing from distribution: $$f ; \
|
||||||
failed=true ; \
|
failed=true ; \
|
||||||
|
|||||||
20
README
@@ -0,0 +1,20 @@
|
|||||||
|
GNOME Shell provides core user interface functions for the GNOME 3 desktop,
|
||||||
|
like switching to windows and launching applications. GNOME Shell takes
|
||||||
|
advantage of the capabilities of modern graphics hardware and introduces
|
||||||
|
innovative user interface concepts to provide a visually attractive and
|
||||||
|
easy to use experience.
|
||||||
|
|
||||||
|
For more information about GNOME Shell, including instructions on how
|
||||||
|
to build GNOME Shell from source and how to get involved with the project,
|
||||||
|
see:
|
||||||
|
|
||||||
|
http://live.gnome.org/GnomeShell
|
||||||
|
|
||||||
|
Bugs should be reported at http://bugzilla.gnome.org against the 'gnome-shell'
|
||||||
|
product.
|
||||||
|
|
||||||
|
License
|
||||||
|
=======
|
||||||
|
GNOME Shell is distributed under the terms of the GNU General Public License,
|
||||||
|
version 2 or later. See the COPYING file for details.
|
||||||
|
|
||||||
|
|||||||
10
configure.ac
@@ -1,4 +1,4 @@
|
|||||||
AC_INIT(gnome-shell, 2.27.1)
|
AC_INIT(gnome-shell, 2.27.3)
|
||||||
|
|
||||||
AC_CONFIG_AUX_DIR(config)
|
AC_CONFIG_AUX_DIR(config)
|
||||||
|
|
||||||
@@ -28,6 +28,10 @@ AM_GLIB_GNU_GETTEXT
|
|||||||
AC_PATH_PROG(GCONFTOOL, gconftool-2, no)
|
AC_PATH_PROG(GCONFTOOL, gconftool-2, no)
|
||||||
AM_GCONF_SOURCE_2
|
AM_GCONF_SOURCE_2
|
||||||
|
|
||||||
|
# Get a value to substitute into gnome-shell.in
|
||||||
|
AM_PATH_PYTHON([2.5])
|
||||||
|
AC_SUBST(PYTHON)
|
||||||
|
|
||||||
# We need at least this, since gst_plugin_register_static() was added
|
# We need at least this, since gst_plugin_register_static() was added
|
||||||
# in 0.10.16, but nothing older than 0.10.21 has been tested.
|
# in 0.10.16, but nothing older than 0.10.21 has been tested.
|
||||||
GSTREAMER_MIN_VERSION=0.10.16
|
GSTREAMER_MIN_VERSION=0.10.16
|
||||||
@@ -51,8 +55,9 @@ PKG_CHECK_MODULES(MUTTER_PLUGIN, gio-unix-2.0 gtk+-2.0 dbus-glib-1 mutter-plugin
|
|||||||
gjs-gi-1.0 libgnome-menu $recorder_modules gconf-2.0
|
gjs-gi-1.0 libgnome-menu $recorder_modules gconf-2.0
|
||||||
gdk-x11-2.0 clutter-x11-1.0 clutter-glx-1.0
|
gdk-x11-2.0 clutter-x11-1.0 clutter-glx-1.0
|
||||||
gnome-desktop-2.0 >= 2.26 libstartup-notification-1.0
|
gnome-desktop-2.0 >= 2.26 libstartup-notification-1.0
|
||||||
gobject-introspection-1.0 >= 0.6.4)
|
gobject-introspection-1.0 >= 0.6.5)
|
||||||
PKG_CHECK_MODULES(TIDY, clutter-1.0)
|
PKG_CHECK_MODULES(TIDY, clutter-1.0)
|
||||||
|
PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-2.0 clutter-imcontext-0.1 libcroco-0.6)
|
||||||
PKG_CHECK_MODULES(BIG, clutter-1.0 gtk+-2.0 librsvg-2.0)
|
PKG_CHECK_MODULES(BIG, clutter-1.0 gtk+-2.0 librsvg-2.0)
|
||||||
PKG_CHECK_MODULES(GDMUSER, dbus-glib-1 gtk+-2.0)
|
PKG_CHECK_MODULES(GDMUSER, dbus-glib-1 gtk+-2.0)
|
||||||
PKG_CHECK_MODULES(TRAY, gtk+-2.0)
|
PKG_CHECK_MODULES(TRAY, gtk+-2.0)
|
||||||
@@ -124,5 +129,6 @@ AC_OUTPUT([
|
|||||||
js/misc/Makefile
|
js/misc/Makefile
|
||||||
js/ui/Makefile
|
js/ui/Makefile
|
||||||
src/Makefile
|
src/Makefile
|
||||||
|
tests/Makefile
|
||||||
po/Makefile.in
|
po/Makefile.in
|
||||||
])
|
])
|
||||||
|
|||||||
@@ -12,16 +12,26 @@ gnome-shell.desktop.in: gnome-shell.desktop.in.in
|
|||||||
gnome-shell.desktop: gnome-shell.desktop.in
|
gnome-shell.desktop: gnome-shell.desktop.in
|
||||||
$(AM_V_GEN) sed s/^_// < $< > $@ || rm $@
|
$(AM_V_GEN) sed s/^_// < $< > $@ || rm $@
|
||||||
|
|
||||||
imagedir = $(pkgdatadir)/images
|
imagesdir = $(pkgdatadir)/images
|
||||||
|
dist_images_DATA = \
|
||||||
dist_image_DATA = \
|
add-workspace.svg \
|
||||||
add-workspace.svg \
|
app-well-glow.png \
|
||||||
close.svg \
|
back.svg \
|
||||||
close-black.svg \
|
close.svg \
|
||||||
info.svg \
|
close-black.svg \
|
||||||
magnifier.svg \
|
info.svg \
|
||||||
|
magnifier.svg \
|
||||||
remove-workspace.svg
|
remove-workspace.svg
|
||||||
|
|
||||||
|
themedir = $(pkgdatadir)/theme
|
||||||
|
dist_theme_DATA = \
|
||||||
|
theme/gnome-shell.css \
|
||||||
|
theme/scroll-button-down.png \
|
||||||
|
theme/scroll-button-down-hover.png \
|
||||||
|
theme/scroll-button-up.png \
|
||||||
|
theme/scroll-button-up-hover.png \
|
||||||
|
theme/scroll-vhandle.png
|
||||||
|
|
||||||
schemadir = @GCONF_SCHEMA_FILE_DIR@
|
schemadir = @GCONF_SCHEMA_FILE_DIR@
|
||||||
schema_DATA = gnome-shell.schemas
|
schema_DATA = gnome-shell.schemas
|
||||||
|
|
||||||
|
|||||||
BIN
data/app-well-glow.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
7
data/back.svg
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 13.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 14948) -->
|
||||||
|
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" version="1.0" id="Foreground" x="0px" y="0px" width="12" height="16" viewBox="0 0 12 16" enable-background="new 0 0 29 18" xml:space="preserve" sodipodi:version="0.32" inkscape:version="0.46+devel" sodipodi:docname="back.svg" inkscape:output_extension="org.inkscape.output.svg.inkscape"><metadata id="metadata16"><rdf:RDF><cc:Work rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/><dc:title/></cc:Work></rdf:RDF></metadata><defs id="defs14"><inkscape:perspective sodipodi:type="inkscape:persp3d" inkscape:vp_x="0 : 9 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_z="29 : 9 : 1" inkscape:persp3d-origin="14.5 : 6 : 1" id="perspective18"/></defs><sodipodi:namedview inkscape:window-height="728" inkscape:window-width="1103" inkscape:pageshadow="2" inkscape:pageopacity="1" guidetolerance="10.0" gridtolerance="10.0" objecttolerance="10.0" borderopacity="1.0" bordercolor="#666666" pagecolor="#000000" id="base" showgrid="true" inkscape:zoom="27.260185" inkscape:cx="12.592456" inkscape:cy="8.2696842" inkscape:window-x="145" inkscape:window-y="38" inkscape:current-layer="Foreground" inkscape:snap-global="true" showguides="false"><inkscape:grid type="xygrid" id="grid2391" empspacing="5" visible="true" enabled="true" snapvisiblegridlinesonly="true"/></sodipodi:namedview>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<path style="fill: rgb(255, 255, 255); fill-opacity: 1; stroke: none;" d="M 10,2 10,14 2,8 10,2 z" id="path43"/></svg>
|
||||||
|
After Width: | Height: | Size: 1.9 KiB |
@@ -1,6 +1,21 @@
|
|||||||
<gconfschemafile>
|
<gconfschemafile>
|
||||||
<schemalist>
|
<schemalist>
|
||||||
|
|
||||||
|
<schema>
|
||||||
|
<key>/schemas/desktop/gnome/shell/development_tools</key>
|
||||||
|
<applyto>/desktop/gnome/shell/development_tools</applyto>
|
||||||
|
<owner>gnome-shell</owner>
|
||||||
|
<type>bool</type>
|
||||||
|
<default>true</default>
|
||||||
|
<locale name="C">
|
||||||
|
<short>Enable internal tools useful for developers and testers from Alt-F2</short>
|
||||||
|
<long>
|
||||||
|
Allows access to internal debugging and monitoring tools using
|
||||||
|
the Alt-F2 dialog.
|
||||||
|
</long>
|
||||||
|
</locale>
|
||||||
|
</schema>
|
||||||
|
|
||||||
<schema>
|
<schema>
|
||||||
<key>/schemas/desktop/gnome/shell/app_monitor/enable_monitoring</key>
|
<key>/schemas/desktop/gnome/shell/app_monitor/enable_monitoring</key>
|
||||||
<applyto>/desktop/gnome/shell/app_monitor/enable_monitoring</applyto>
|
<applyto>/desktop/gnome/shell/app_monitor/enable_monitoring</applyto>
|
||||||
|
|||||||
97
data/theme/gnome-shell.css
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
/* Copyright 2009, Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* Portions adapted from Mx's data/style/default.css
|
||||||
|
* Copyright 2009 Intel Corporation
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU Lesser General Public License,
|
||||||
|
* version 2.1, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT ANY
|
||||||
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
StScrollBar
|
||||||
|
{
|
||||||
|
background-color: #354761;
|
||||||
|
padding: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
StScrollView
|
||||||
|
{
|
||||||
|
scrollbar-width: 16px;
|
||||||
|
scrollbar-height: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
StButton#up-stepper
|
||||||
|
{
|
||||||
|
border-image: url("scroll-button-up.png") 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
StButton#up-stepper:hover,
|
||||||
|
StButton#up-stepper:active
|
||||||
|
{
|
||||||
|
border-image: url("scroll-button-up-hover.png") 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
StButton#down-stepper
|
||||||
|
{
|
||||||
|
border-image: url("scroll-button-down.png") 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
StButton#down-stepper:hover,
|
||||||
|
StButton#down-stepper:active
|
||||||
|
{
|
||||||
|
border-image: url("scroll-button-down-hover.png") 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
StScrollBar StButton#vhandle
|
||||||
|
{
|
||||||
|
border-image: url("scroll-vhandle.png") 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
StScrollBar StButton#vhandle:hover
|
||||||
|
{
|
||||||
|
border-image: url("scroll-vhandle.png") 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* LookingGlass */
|
||||||
|
|
||||||
|
#LookingGlassDialog
|
||||||
|
{
|
||||||
|
background-color: rgba(0,0,0,0.85);
|
||||||
|
spacing: 4px;
|
||||||
|
padding: 4px;
|
||||||
|
border: 1px solid rgba(0,0,172,0.85);
|
||||||
|
border-radius: 4px;
|
||||||
|
|
||||||
|
color: #88ff66;
|
||||||
|
}
|
||||||
|
|
||||||
|
#LookingGlassDialog > #Toolbar
|
||||||
|
{
|
||||||
|
border: 1px solid grey;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#LookingGlassDialog StLabel
|
||||||
|
{
|
||||||
|
color: #88ff66;
|
||||||
|
}
|
||||||
|
|
||||||
|
#LookingGlassDialog StEntry
|
||||||
|
{
|
||||||
|
color: #88ff66;
|
||||||
|
}
|
||||||
|
|
||||||
|
#LookingGlassDialog StBoxLayout#EvalBox
|
||||||
|
{
|
||||||
|
padding: 4px;
|
||||||
|
spacing: 4px;
|
||||||
|
}
|
||||||
BIN
data/theme/scroll-button-down-hover.png
Normal file
|
After Width: | Height: | Size: 225 B |
BIN
data/theme/scroll-button-down.png
Normal file
|
After Width: | Height: | Size: 225 B |
BIN
data/theme/scroll-button-up-hover.png
Normal file
|
After Width: | Height: | Size: 211 B |
BIN
data/theme/scroll-button-up.png
Normal file
|
After Width: | Height: | Size: 211 B |
BIN
data/theme/scroll-vhandle.png
Normal file
|
After Width: | Height: | Size: 323 B |
53
gnome-shell.doap
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
<Project xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
|
||||||
|
xmlns:foaf="http://xmlns.com/foaf/0.1/"
|
||||||
|
xmlns:gnome="http://api.gnome.org/doap-extensions#"
|
||||||
|
xmlns="http://usefulinc.com/ns/doap#">
|
||||||
|
|
||||||
|
<name xml:lang="en">GNOME Shell</name>
|
||||||
|
<shortdesc xml:lang="en">Next generation GNOME desktop shell</shortdesc>
|
||||||
|
<!--
|
||||||
|
<homepage rdf:resource="http://live.gnome.org/GnomeShell" />
|
||||||
|
-->
|
||||||
|
<mailing-list rdf:resource="http://mail.gnome.org/mailman/listinfo/gnome-shell-list" />
|
||||||
|
<download-page rdf:resource="http://download.gnome.org/sources/gnome-shell/" />
|
||||||
|
<bug-database rdf:resource="http://bugzilla.gnome.org/browse.cgi?product=gnome-shell" />
|
||||||
|
|
||||||
|
<category rdf:resource="http://api.gnome.org/doap-extensions#desktop" />
|
||||||
|
|
||||||
|
<maintainer>
|
||||||
|
<foaf:Person>
|
||||||
|
<foaf:name>William Jon McCann</foaf:name>
|
||||||
|
<foaf:mbox rdf:resource="mailto:jmccann@redhat.com" />
|
||||||
|
<gnome:userid>mccann</gnome:userid>
|
||||||
|
</foaf:Person>
|
||||||
|
</maintainer>
|
||||||
|
<maintainer>
|
||||||
|
<foaf:Person>
|
||||||
|
<foaf:name>Owen Taylor</foaf:name>
|
||||||
|
<foaf:mbox rdf:resource="mailto:otaylor@redhat.com" />
|
||||||
|
<gnome:userid>otaylor</gnome:userid>
|
||||||
|
</foaf:Person>
|
||||||
|
</maintainer>
|
||||||
|
<maintainer>
|
||||||
|
<foaf:Person>
|
||||||
|
<foaf:name>Colin Walters</foaf:name>
|
||||||
|
<foaf:mbox rdf:resource="mailto:walters@verbum.org" />
|
||||||
|
<gnome:userid>cwalters</gnome:userid>
|
||||||
|
</foaf:Person>
|
||||||
|
</maintainer>
|
||||||
|
<maintainer>
|
||||||
|
<foaf:Person>
|
||||||
|
<foaf:name>Dan Winship</foaf:name>
|
||||||
|
<foaf:mbox rdf:resource="mailto:danw@gnome.org" />
|
||||||
|
<gnome:userid>danw</gnome:userid>
|
||||||
|
</foaf:Person>
|
||||||
|
</maintainer>
|
||||||
|
<maintainer>
|
||||||
|
<foaf:Person>
|
||||||
|
<foaf:name>Marina Zhurakhinskaya</foaf:name>
|
||||||
|
<foaf:mbox rdf:resource="mailto:marinaz@redhat.com" />
|
||||||
|
<gnome:userid>marinaz</gnome:userid>
|
||||||
|
</foaf:Person>
|
||||||
|
</maintainer>
|
||||||
|
</Project>
|
||||||
@@ -9,7 +9,9 @@ dist_jsui_DATA = \
|
|||||||
dash.js \
|
dash.js \
|
||||||
dnd.js \
|
dnd.js \
|
||||||
docDisplay.js \
|
docDisplay.js \
|
||||||
|
environment.js \
|
||||||
genericDisplay.js \
|
genericDisplay.js \
|
||||||
|
lightbox.js \
|
||||||
link.js \
|
link.js \
|
||||||
lookingGlass.js \
|
lookingGlass.js \
|
||||||
main.js \
|
main.js \
|
||||||
@@ -17,6 +19,7 @@ dist_jsui_DATA = \
|
|||||||
panel.js \
|
panel.js \
|
||||||
places.js \
|
places.js \
|
||||||
runDialog.js \
|
runDialog.js \
|
||||||
|
shellDBus.js \
|
||||||
sidebar.js \
|
sidebar.js \
|
||||||
tweener.js \
|
tweener.js \
|
||||||
widget.js \
|
widget.js \
|
||||||
|
|||||||
408
js/ui/altTab.js
@@ -2,33 +2,26 @@
|
|||||||
|
|
||||||
const Big = imports.gi.Big;
|
const Big = imports.gi.Big;
|
||||||
const Clutter = imports.gi.Clutter;
|
const Clutter = imports.gi.Clutter;
|
||||||
|
const Gdk = imports.gi.Gdk;
|
||||||
const Lang = imports.lang;
|
const Lang = imports.lang;
|
||||||
const Meta = imports.gi.Meta;
|
const Meta = imports.gi.Meta;
|
||||||
const Pango = imports.gi.Pango;
|
const Pango = imports.gi.Pango;
|
||||||
const Shell = imports.gi.Shell;
|
const Shell = imports.gi.Shell;
|
||||||
|
|
||||||
|
const AppIcon = imports.ui.appIcon;
|
||||||
|
const Lightbox = imports.ui.lightbox;
|
||||||
const Main = imports.ui.main;
|
const Main = imports.ui.main;
|
||||||
const Tweener = imports.ui.tweener;
|
|
||||||
|
|
||||||
const POPUP_BG_COLOR = new Clutter.Color();
|
const POPUP_BG_COLOR = new Clutter.Color();
|
||||||
POPUP_BG_COLOR.from_pixel(0x00000080);
|
POPUP_BG_COLOR.from_pixel(0x00000080);
|
||||||
const POPUP_INDICATOR_COLOR = new Clutter.Color();
|
const POPUP_APPICON_BORDER_COLOR = new Clutter.Color();
|
||||||
POPUP_INDICATOR_COLOR.from_pixel(0xf0f0f0ff);
|
POPUP_APPICON_BORDER_COLOR.from_pixel(0xffffffff);
|
||||||
const POPUP_TRANSPARENT = new Clutter.Color();
|
|
||||||
POPUP_TRANSPARENT.from_pixel(0x00000000);
|
|
||||||
|
|
||||||
const POPUP_INDICATOR_WIDTH = 4;
|
|
||||||
const POPUP_GRID_SPACING = 8;
|
const POPUP_GRID_SPACING = 8;
|
||||||
const POPUP_ICON_SIZE = 48;
|
const POPUP_ICON_SIZE = 48;
|
||||||
const POPUP_NUM_COLUMNS = 5;
|
const POPUP_NUM_COLUMNS = 5;
|
||||||
|
|
||||||
const POPUP_LABEL_MAX_WIDTH = POPUP_NUM_COLUMNS * (POPUP_ICON_SIZE + POPUP_GRID_SPACING);
|
const POPUP_POINTER_SELECTION_THRESHOLD = 3;
|
||||||
|
|
||||||
const OVERLAY_COLOR = new Clutter.Color();
|
|
||||||
OVERLAY_COLOR.from_pixel(0x00000044);
|
|
||||||
|
|
||||||
const SHOW_TIME = 0.05;
|
|
||||||
const SWITCH_TIME = 0.1;
|
|
||||||
|
|
||||||
function AltTabPopup() {
|
function AltTabPopup() {
|
||||||
this._init();
|
this._init();
|
||||||
@@ -36,13 +29,13 @@ function AltTabPopup() {
|
|||||||
|
|
||||||
AltTabPopup.prototype = {
|
AltTabPopup.prototype = {
|
||||||
_init : function() {
|
_init : function() {
|
||||||
let global = Shell.Global.get();
|
|
||||||
|
|
||||||
this.actor = new Big.Box({ background_color : POPUP_BG_COLOR,
|
this.actor = new Big.Box({ background_color : POPUP_BG_COLOR,
|
||||||
corner_radius: POPUP_GRID_SPACING,
|
corner_radius: POPUP_GRID_SPACING,
|
||||||
padding: POPUP_GRID_SPACING,
|
padding: POPUP_GRID_SPACING,
|
||||||
spacing: POPUP_GRID_SPACING,
|
spacing: POPUP_GRID_SPACING,
|
||||||
orientation: Big.BoxOrientation.VERTICAL });
|
orientation: Big.BoxOrientation.VERTICAL,
|
||||||
|
reactive: true });
|
||||||
|
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
|
||||||
|
|
||||||
// Icon grid. TODO: Investigate Nbtk.Grid once that lands. Currently
|
// Icon grid. TODO: Investigate Nbtk.Grid once that lands. Currently
|
||||||
// just implemented using a chain of Big.Box.
|
// just implemented using a chain of Big.Box.
|
||||||
@@ -53,82 +46,31 @@ AltTabPopup.prototype = {
|
|||||||
gcenterbox.append(this._grid, Big.BoxPackFlags.NONE);
|
gcenterbox.append(this._grid, Big.BoxPackFlags.NONE);
|
||||||
this.actor.append(gcenterbox, Big.BoxPackFlags.NONE);
|
this.actor.append(gcenterbox, Big.BoxPackFlags.NONE);
|
||||||
|
|
||||||
// Selected-window label
|
this._icons = [];
|
||||||
this._label = new Clutter.Text({ font_name: "Sans 16px",
|
this._currentWindows = [];
|
||||||
ellipsize: Pango.EllipsizeMode.END });
|
this._haveModal = false;
|
||||||
|
this._selected = 0;
|
||||||
let labelbox = new Big.Box({ background_color: POPUP_INDICATOR_COLOR,
|
this._highlightedWindow = null;
|
||||||
corner_radius: POPUP_GRID_SPACING / 2,
|
|
||||||
padding: POPUP_GRID_SPACING / 2 });
|
|
||||||
labelbox.append(this._label, Big.BoxPackFlags.NONE);
|
|
||||||
let lcenterbox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
|
||||||
x_align: Big.BoxAlignment.CENTER,
|
|
||||||
width: POPUP_LABEL_MAX_WIDTH + POPUP_GRID_SPACING });
|
|
||||||
lcenterbox.append(labelbox, Big.BoxPackFlags.NONE);
|
|
||||||
this.actor.append(lcenterbox, Big.BoxPackFlags.NONE);
|
|
||||||
|
|
||||||
// Indicator around selected icon
|
|
||||||
this._indicator = new Big.Rectangle({ border_width: POPUP_INDICATOR_WIDTH,
|
|
||||||
corner_radius: POPUP_INDICATOR_WIDTH / 2,
|
|
||||||
border_color: POPUP_INDICATOR_COLOR,
|
|
||||||
color: POPUP_TRANSPARENT });
|
|
||||||
this.actor.append(this._indicator, Big.BoxPackFlags.FIXED);
|
|
||||||
|
|
||||||
this._items = [];
|
|
||||||
this._toplevels = global.window_group.get_children();
|
this._toplevels = global.window_group.get_children();
|
||||||
|
|
||||||
global.stage.add_actor(this.actor);
|
global.stage.add_actor(this.actor);
|
||||||
|
|
||||||
// Dark translucent window used to cover all but the
|
|
||||||
// currently-selected window while Alt-Tabbing. Actually
|
|
||||||
// contains four actors which can we rearrange to create
|
|
||||||
// a hole in the overlay.
|
|
||||||
this._overlay = new Clutter.Group({ reactive: true });
|
|
||||||
this._overlay_top = new Clutter.Rectangle({ color: OVERLAY_COLOR,
|
|
||||||
border_width: 0 });
|
|
||||||
this._overlay_bottom = new Clutter.Rectangle({ color: OVERLAY_COLOR,
|
|
||||||
border_width: 0 });
|
|
||||||
this._overlay_left = new Clutter.Rectangle({ color: OVERLAY_COLOR,
|
|
||||||
border_width: 0 });
|
|
||||||
this._overlay_right = new Clutter.Rectangle({ color: OVERLAY_COLOR,
|
|
||||||
border_width: 0 });
|
|
||||||
this._overlay.add_actor(this._overlay_top);
|
|
||||||
this._overlay.add_actor(this._overlay_bottom);
|
|
||||||
this._overlay.add_actor(this._overlay_left);
|
|
||||||
this._overlay.add_actor(this._overlay_right);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
addWindow : function(win) {
|
_addIcon : function(appIcon) {
|
||||||
let item = { window: win,
|
appIcon.connect('activate', Lang.bind(this, this._appClicked));
|
||||||
metaWindow: win.get_meta_window() };
|
appIcon.connect('activate-window', Lang.bind(this, this._windowClicked));
|
||||||
|
appIcon.connect('highlight-window', Lang.bind(this, this._windowHovered));
|
||||||
|
appIcon.connect('menu-popped-up', Lang.bind(this, this._menuPoppedUp));
|
||||||
|
appIcon.connect('menu-popped-down', Lang.bind(this, this._menuPoppedDown));
|
||||||
|
|
||||||
let pixbuf = item.metaWindow.icon;
|
appIcon.actor.connect('enter-event', Lang.bind(this, this._iconEntered));
|
||||||
item.icon = new Clutter.Texture({ width: POPUP_ICON_SIZE,
|
|
||||||
height: POPUP_ICON_SIZE,
|
|
||||||
keep_aspect_ratio: true });
|
|
||||||
Shell.clutter_texture_set_from_pixbuf(item.icon, pixbuf);
|
|
||||||
|
|
||||||
item.box = new Big.Box({ padding: POPUP_INDICATOR_WIDTH * 2 });
|
// FIXME?
|
||||||
item.box.append(item.icon, Big.BoxPackFlags.NONE);
|
appIcon.actor.border = 2;
|
||||||
|
appIcon.highlight_border_color = POPUP_APPICON_BORDER_COLOR;
|
||||||
|
|
||||||
item.above = null;
|
this._icons.push(appIcon);
|
||||||
for (let i = 1; i < this._toplevels.length; i++) {
|
this._currentWindows.push(appIcon.windows[0]);
|
||||||
if (this._toplevels[i] == win) {
|
|
||||||
item.above = this._toplevels[i - 1];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
item.visible = item.metaWindow.showing_on_its_workspace();
|
|
||||||
|
|
||||||
if (!item.visible) {
|
|
||||||
let rect = new Meta.Rectangle();
|
|
||||||
if (item.metaWindow.get_icon_geometry(rect))
|
|
||||||
item.icon_rect = rect;
|
|
||||||
}
|
|
||||||
|
|
||||||
item.n = this._items.length;
|
|
||||||
this._items.push(item);
|
|
||||||
|
|
||||||
// Add it to the grid
|
// Add it to the grid
|
||||||
if (!this._gridRow || this._gridRow.get_children().length == POPUP_NUM_COLUMNS) {
|
if (!this._gridRow || this._gridRow.get_children().length == POPUP_NUM_COLUMNS) {
|
||||||
@@ -136,150 +78,210 @@ AltTabPopup.prototype = {
|
|||||||
orientation: Big.BoxOrientation.HORIZONTAL });
|
orientation: Big.BoxOrientation.HORIZONTAL });
|
||||||
this._grid.append(this._gridRow, Big.BoxPackFlags.NONE);
|
this._grid.append(this._gridRow, Big.BoxPackFlags.NONE);
|
||||||
}
|
}
|
||||||
this._gridRow.append(item.box, Big.BoxPackFlags.NONE);
|
this._gridRow.append(appIcon.actor, Big.BoxPackFlags.NONE);
|
||||||
},
|
},
|
||||||
|
|
||||||
show : function(initialSelection) {
|
show : function(initialSelection) {
|
||||||
let global = Shell.Global.get();
|
let appMonitor = Shell.AppMonitor.get_default();
|
||||||
|
let apps = appMonitor.get_running_apps ("");
|
||||||
|
|
||||||
global.window_group.add_actor(this._overlay);
|
if (!apps.length)
|
||||||
this._overlay.raise_top();
|
return false;
|
||||||
this._overlay.show();
|
|
||||||
this.actor.opacity = 0;
|
if (!Main.pushModal(this.actor))
|
||||||
Tweener.addTween(this.actor, { opacity: 255,
|
return false;
|
||||||
time: SHOW_TIME,
|
this._haveModal = true;
|
||||||
transition: "easeOutQuad" });
|
|
||||||
|
this._keyPressEventId = global.stage.connect('key-press-event', Lang.bind(this, this._keyPressEvent));
|
||||||
|
this._keyReleaseEventId = global.stage.connect('key-release-event', Lang.bind(this, this._keyReleaseEvent));
|
||||||
|
|
||||||
|
this._motionEventId = this.actor.connect('motion-event', Lang.bind(this, this._mouseMoved));
|
||||||
|
this._mouseActive = false;
|
||||||
|
this._mouseMovement = 0;
|
||||||
|
|
||||||
|
// Contruct the AppIcons, sort by time, add to the popup
|
||||||
|
let icons = [];
|
||||||
|
for (let i = 0; i < apps.length; i++)
|
||||||
|
icons.push(new AppIcon.AppIcon(apps[i], AppIcon.MenuType.BELOW));
|
||||||
|
icons.sort(Lang.bind(this, this._sortAppIcon));
|
||||||
|
for (let i = 0; i < icons.length; i++)
|
||||||
|
this._addIcon(icons[i]);
|
||||||
|
|
||||||
|
// Need to specify explicit width and height because the
|
||||||
|
// window_group may not actually cover the whole screen
|
||||||
|
this._lightbox = new Lightbox.Lightbox(global.window_group,
|
||||||
|
global.screen_width,
|
||||||
|
global.screen_height);
|
||||||
|
|
||||||
this.actor.show_all();
|
this.actor.show_all();
|
||||||
this.actor.x = Math.floor((global.screen_width - this.actor.width) / 2);
|
this.actor.x = Math.floor((global.screen_width - this.actor.width) / 2);
|
||||||
this.actor.y = Math.floor((global.screen_height - this.actor.height) / 2);
|
this.actor.y = Math.floor((global.screen_height - this.actor.height) / 2);
|
||||||
|
|
||||||
this.select(initialSelection);
|
this._updateSelection(initialSelection);
|
||||||
|
|
||||||
|
// There's a race condition; if the user released Alt before
|
||||||
|
// we got the grab, then we won't be notified. (See
|
||||||
|
// https://bugzilla.gnome.org/show_bug.cgi?id=596695 for
|
||||||
|
// details.) So we check now. (Have to do this after calling
|
||||||
|
// _updateSelection.)
|
||||||
|
let [screen, x, y, mods] = Gdk.Display.get_default().get_pointer();
|
||||||
|
if (!(mods & Gdk.ModifierType.MOD1_MASK)) {
|
||||||
|
this._finish();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
_hasVisibleWindows : function(appIcon) {
|
||||||
|
for (let i = 0; i < appIcon.windows.length; i++) {
|
||||||
|
if (appIcon.windows[i].showing_on_its_workspace())
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
_sortAppIcon : function(appIcon1, appIcon2) {
|
||||||
|
let vis1 = this._hasVisibleWindows(appIcon1);
|
||||||
|
let vis2 = this._hasVisibleWindows(appIcon2);
|
||||||
|
|
||||||
|
if (vis1 && !vis2) {
|
||||||
|
return -1;
|
||||||
|
} else if (vis2 && !vis1) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
// The app's most-recently-used window is first
|
||||||
|
// in its list
|
||||||
|
return (appIcon2.windows[0].get_user_time() -
|
||||||
|
appIcon1.windows[0].get_user_time());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_keyPressEvent : function(actor, event) {
|
||||||
|
let keysym = event.get_key_symbol();
|
||||||
|
let backwards = (event.get_state() & Clutter.ModifierType.SHIFT_MASK);
|
||||||
|
|
||||||
|
if (keysym == Clutter.Tab)
|
||||||
|
this._updateSelection(backwards ? -1 : 1);
|
||||||
|
else if (keysym == Clutter.grave)
|
||||||
|
this._updateWindowSelection(backwards ? -1 : 1);
|
||||||
|
else if (keysym == Clutter.Escape)
|
||||||
|
this.destroy();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
_keyReleaseEvent : function(actor, event) {
|
||||||
|
let keysym = event.get_key_symbol();
|
||||||
|
|
||||||
|
if (keysym == Clutter.Alt_L || keysym == Clutter.Alt_R)
|
||||||
|
this._finish();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
_appClicked : function(icon) {
|
||||||
|
Main.activateWindow(icon.windows[0]);
|
||||||
|
this.destroy();
|
||||||
|
},
|
||||||
|
|
||||||
|
_windowClicked : function(icon, window) {
|
||||||
|
if (window)
|
||||||
|
Main.activateWindow(window);
|
||||||
|
this.destroy();
|
||||||
|
},
|
||||||
|
|
||||||
|
_windowHovered : function(icon, window) {
|
||||||
|
if (window)
|
||||||
|
this._highlightWindow(window);
|
||||||
|
},
|
||||||
|
|
||||||
|
_mouseMoved : function(actor, event) {
|
||||||
|
if (++this._mouseMovement < POPUP_POINTER_SELECTION_THRESHOLD)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.actor.disconnect(this._motionEventId);
|
||||||
|
this._mouseActive = true;
|
||||||
|
|
||||||
|
actor = event.get_source();
|
||||||
|
while (actor) {
|
||||||
|
if (actor._delegate instanceof AppIcon.AppIcon) {
|
||||||
|
this._iconEntered(actor, event);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
actor = actor.get_parent();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_iconEntered : function(actor, event) {
|
||||||
|
let index = this._icons.indexOf(actor._delegate);
|
||||||
|
if (this._mouseActive)
|
||||||
|
this._updateSelection(index - this._selected);
|
||||||
|
},
|
||||||
|
|
||||||
|
_finish : function() {
|
||||||
|
if (this._highlightedWindow)
|
||||||
|
Main.activateWindow(this._highlightedWindow);
|
||||||
|
this.destroy();
|
||||||
},
|
},
|
||||||
|
|
||||||
destroy : function() {
|
destroy : function() {
|
||||||
this.actor.destroy();
|
this.actor.destroy();
|
||||||
this._overlay.destroy();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
select : function(n) {
|
_onDestroy : function() {
|
||||||
if (this._selected) {
|
if (this._haveModal)
|
||||||
// Unselect previous
|
Main.popModal(this.actor);
|
||||||
|
|
||||||
if (this._allocationChangedId) {
|
if (this._lightbox)
|
||||||
this._selected.box.disconnect(this._allocationChangedId);
|
this._lightbox.destroy();
|
||||||
delete this._allocationChangedId;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._selected.above)
|
if (this._keyPressEventId)
|
||||||
this._selected.window.raise(this._selected.above);
|
global.stage.disconnect(this._keyPressEventId);
|
||||||
else
|
if (this._keyReleaseEventId)
|
||||||
this._selected.window.lower_bottom();
|
global.stage.disconnect(this._keyReleaseEventId);
|
||||||
}
|
|
||||||
|
|
||||||
let item = this._items[n];
|
|
||||||
let changed = this._selected && item != this._selected;
|
|
||||||
this._selected = item;
|
|
||||||
|
|
||||||
if (this._selected) {
|
|
||||||
this._label.set_size(-1, -1);
|
|
||||||
this._label.text = this._selected.metaWindow.title;
|
|
||||||
if (this._label.width > POPUP_LABEL_MAX_WIDTH)
|
|
||||||
this._label.width = POPUP_LABEL_MAX_WIDTH;
|
|
||||||
|
|
||||||
// Figure out this._selected.box's coordinates in terms of
|
|
||||||
// this.actor
|
|
||||||
let bx = this._selected.box.x, by = this._selected.box.y;
|
|
||||||
let actor = this._selected.box.get_parent();
|
|
||||||
while (actor != this.actor) {
|
|
||||||
bx += actor.x;
|
|
||||||
by += actor.y;
|
|
||||||
actor = actor.get_parent();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changed) {
|
|
||||||
Tweener.addTween(this._indicator,
|
|
||||||
{ x: bx,
|
|
||||||
y: by,
|
|
||||||
width: this._selected.box.width,
|
|
||||||
height: this._selected.box.height,
|
|
||||||
time: SWITCH_TIME,
|
|
||||||
transition: "easeOutQuad" });
|
|
||||||
} else {
|
|
||||||
Tweener.removeTweens(this.indicator);
|
|
||||||
this._indicator.set_position(bx, by);
|
|
||||||
this._indicator.set_size(this._selected.box.width,
|
|
||||||
this._selected.box.height);
|
|
||||||
}
|
|
||||||
this._indicator.show();
|
|
||||||
|
|
||||||
if (this._overlay.visible) {
|
|
||||||
if (this._selected.visible)
|
|
||||||
this._selected.window.raise(this._overlay);
|
|
||||||
this._adjust_overlay();
|
|
||||||
}
|
|
||||||
|
|
||||||
this._allocationChangedId =
|
|
||||||
this._selected.box.connect('notify::allocation',
|
|
||||||
Lang.bind(this, this._allocationChanged));
|
|
||||||
} else {
|
|
||||||
this._label.text = "";
|
|
||||||
this._indicator.hide();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_allocationChanged : function() {
|
_updateSelection : function(delta) {
|
||||||
if (this._selected)
|
this._icons[this._selected].setHighlight(false);
|
||||||
this.select(this._selected.n);
|
if (delta != 0 && this._selectedMenu)
|
||||||
|
this._selectedMenu.popdown();
|
||||||
|
|
||||||
|
this._selected = (this._selected + this._icons.length + delta) % this._icons.length;
|
||||||
|
this._icons[this._selected].setHighlight(true);
|
||||||
|
|
||||||
|
this._highlightWindow(this._currentWindows[this._selected]);
|
||||||
},
|
},
|
||||||
|
|
||||||
_adjust_overlay : function() {
|
_menuPoppedUp : function(icon, menu) {
|
||||||
let global = Shell.Global.get();
|
this._selectedMenu = menu;
|
||||||
|
},
|
||||||
|
|
||||||
if (this._selected && this._selected.icon_rect) {
|
_menuPoppedDown : function(icon, menu) {
|
||||||
// We want to highlight a specific rectangle within the
|
this._selectedMenu = null;
|
||||||
// task bar, so rearrange the pieces of the overlay to
|
},
|
||||||
// cover the whole screen except that rectangle
|
|
||||||
|
|
||||||
let rect = this._selected.icon_rect;
|
_updateWindowSelection : function(delta) {
|
||||||
|
let icon = this._icons[this._selected];
|
||||||
|
|
||||||
this._overlay_top.x = 0;
|
if (!this._selectedMenu)
|
||||||
this._overlay_top.y = 0;
|
icon.popupMenu();
|
||||||
this._overlay_top.width = global.screen_width;
|
if (!this._selectedMenu)
|
||||||
this._overlay_top.height = rect.y;
|
return;
|
||||||
|
|
||||||
this._overlay_left.x = 0;
|
let next = 0;
|
||||||
this._overlay_left.y = rect.y;
|
for (let i = 0; i < icon.windows.length; i++) {
|
||||||
this._overlay_left.width = rect.x;
|
if (icon.windows[i] == this._highlightedWindow) {
|
||||||
this._overlay_left.height = rect.height;
|
next = (i + icon.windows.length + delta) % icon.windows.length;
|
||||||
this._overlay_left.show();
|
break;
|
||||||
|
}
|
||||||
this._overlay_right.x = rect.x + rect.width;
|
|
||||||
this._overlay_right.y = rect.y;
|
|
||||||
this._overlay_right.width = global.screen_width - rect.x - rect.width;
|
|
||||||
this._overlay_right.height = rect.height;
|
|
||||||
this._overlay_right.show();
|
|
||||||
|
|
||||||
this._overlay_bottom.x = 0;
|
|
||||||
this._overlay_bottom.y = rect.y + rect.height;
|
|
||||||
this._overlay_bottom.width = global.screen_width;
|
|
||||||
this._overlay_bottom.height = global.screen_height - rect.y - rect.height;
|
|
||||||
this._overlay_bottom.show();
|
|
||||||
} else {
|
|
||||||
// Either there's no current selection, or the selection
|
|
||||||
// is a visible window. Make the overlay cover the whole
|
|
||||||
// screen. select() will raise the selected window over
|
|
||||||
// the overlay.
|
|
||||||
|
|
||||||
this._overlay_top.x = 0;
|
|
||||||
this._overlay_top.y = 0;
|
|
||||||
this._overlay_top.width = global.screen_width;
|
|
||||||
this._overlay_top.height = global.screen_height;
|
|
||||||
this._overlay_top.show();
|
|
||||||
|
|
||||||
this._overlay_left.hide();
|
|
||||||
this._overlay_right.hide();
|
|
||||||
this._overlay_bottom.hide();
|
|
||||||
}
|
}
|
||||||
|
this._selectedMenu.selectWindow(icon.windows[next]);
|
||||||
|
},
|
||||||
|
|
||||||
|
_highlightWindow : function(metaWin) {
|
||||||
|
this._highlightedWindow = metaWin;
|
||||||
|
this._currentWindows[this._selected] = metaWin;
|
||||||
|
this._lightbox.highlight(this._highlightedWindow.get_compositor_private());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -23,11 +23,11 @@ const ENTERED_MENU_COLOR = new Clutter.Color();
|
|||||||
ENTERED_MENU_COLOR.from_pixel(0x00ff0022);
|
ENTERED_MENU_COLOR.from_pixel(0x00ff0022);
|
||||||
|
|
||||||
const WELL_DEFAULT_COLUMNS = 4;
|
const WELL_DEFAULT_COLUMNS = 4;
|
||||||
const WELL_ITEM_HSPACING = 0;
|
const WELL_ITEM_MIN_HSPACING = 4;
|
||||||
const WELL_ITEM_VSPACING = 4;
|
const WELL_ITEM_VSPACING = 4;
|
||||||
|
|
||||||
const MENU_ICON_SIZE = 24;
|
const MENU_ARROW_SIZE = 12;
|
||||||
const MENU_SPACING = 15;
|
const MENU_SPACING = 7;
|
||||||
|
|
||||||
const MAX_ITEMS = 30;
|
const MAX_ITEMS = 30;
|
||||||
|
|
||||||
@@ -57,7 +57,13 @@ AppDisplayItem.prototype = {
|
|||||||
|
|
||||||
// Opens an application represented by this display item.
|
// Opens an application represented by this display item.
|
||||||
launch : function() {
|
launch : function() {
|
||||||
this._appInfo.launch();
|
let windows = Shell.AppMonitor.get_default().get_windows_for_app(this._appInfo.get_id());
|
||||||
|
if (windows.length > 0) {
|
||||||
|
let mostRecentWindow = windows[0];
|
||||||
|
Main.overview.activateWindow(mostRecentWindow, Main.currentTime());
|
||||||
|
} else {
|
||||||
|
this._appInfo.launch();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
//// Protected method overrides ////
|
//// Protected method overrides ////
|
||||||
@@ -81,8 +87,8 @@ const MENU_UNSELECTED = 0;
|
|||||||
const MENU_SELECTED = 1;
|
const MENU_SELECTED = 1;
|
||||||
const MENU_ENTERED = 2;
|
const MENU_ENTERED = 2;
|
||||||
|
|
||||||
function MenuItem(name, id, iconName) {
|
function MenuItem(name, id) {
|
||||||
this._init(name, id, iconName);
|
this._init(name, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -90,31 +96,19 @@ function MenuItem(name, id, iconName) {
|
|||||||
* Shows the list of menus in the sidebar.
|
* Shows the list of menus in the sidebar.
|
||||||
*/
|
*/
|
||||||
MenuItem.prototype = {
|
MenuItem.prototype = {
|
||||||
_init: function(name, id, iconName) {
|
_init: function(name, id) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
|
||||||
this.actor = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
this.actor = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||||
spacing: 4,
|
spacing: 4,
|
||||||
corner_radius: 4,
|
corner_radius: 4,
|
||||||
padding_right: 4,
|
padding_right: 4,
|
||||||
|
padding_left: 4,
|
||||||
reactive: true });
|
reactive: true });
|
||||||
this.actor.connect('button-press-event', Lang.bind(this, function (a, e) {
|
this.actor.connect('button-press-event', Lang.bind(this, function (a, e) {
|
||||||
this.setState(MENU_SELECTED);
|
this.setState(MENU_SELECTED);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let iconTheme = Gtk.IconTheme.get_default();
|
|
||||||
let pixbuf = null;
|
|
||||||
this._icon = new Clutter.Texture({ width: MENU_ICON_SIZE,
|
|
||||||
height: MENU_ICON_SIZE });
|
|
||||||
// Wine manages not to have an icon
|
|
||||||
try {
|
|
||||||
pixbuf = iconTheme.load_icon(iconName, MENU_ICON_SIZE, 0 /* flags */);
|
|
||||||
} catch (e) {
|
|
||||||
pixbuf = iconTheme.load_icon('gtk-file', MENU_ICON_SIZE, 0);
|
|
||||||
}
|
|
||||||
if (pixbuf != null)
|
|
||||||
Shell.clutter_texture_set_from_pixbuf(this._icon, pixbuf);
|
|
||||||
this.actor.append(this._icon, Big.BoxPackFlags.NONE);
|
|
||||||
this._text = new Clutter.Text({ color: GenericDisplay.ITEM_DISPLAY_NAME_COLOR,
|
this._text = new Clutter.Text({ color: GenericDisplay.ITEM_DISPLAY_NAME_COLOR,
|
||||||
font_name: "Sans 14px",
|
font_name: "Sans 14px",
|
||||||
text: name });
|
text: name });
|
||||||
@@ -122,7 +116,8 @@ MenuItem.prototype = {
|
|||||||
// We use individual boxes for the label and the arrow to ensure that they
|
// We use individual boxes for the label and the arrow to ensure that they
|
||||||
// are aligned vertically. Just setting y_align: Big.BoxAlignment.CENTER
|
// are aligned vertically. Just setting y_align: Big.BoxAlignment.CENTER
|
||||||
// on this.actor does not seem to achieve that.
|
// on this.actor does not seem to achieve that.
|
||||||
let labelBox = new Big.Box({ y_align: Big.BoxAlignment.CENTER });
|
let labelBox = new Big.Box({ y_align: Big.BoxAlignment.CENTER,
|
||||||
|
padding: 4 });
|
||||||
|
|
||||||
labelBox.append(this._text, Big.BoxPackFlags.NONE);
|
labelBox.append(this._text, Big.BoxPackFlags.NONE);
|
||||||
|
|
||||||
@@ -130,8 +125,8 @@ MenuItem.prototype = {
|
|||||||
|
|
||||||
let arrowBox = new Big.Box({ y_align: Big.BoxAlignment.CENTER });
|
let arrowBox = new Big.Box({ y_align: Big.BoxAlignment.CENTER });
|
||||||
|
|
||||||
this._arrow = new Shell.Arrow({ surface_width: MENU_ICON_SIZE / 2,
|
this._arrow = new Shell.Arrow({ surface_width: MENU_ARROW_SIZE,
|
||||||
surface_height: MENU_ICON_SIZE / 2,
|
surface_height: MENU_ARROW_SIZE,
|
||||||
direction: Gtk.ArrowType.RIGHT,
|
direction: Gtk.ArrowType.RIGHT,
|
||||||
opacity: 0 });
|
opacity: 0 });
|
||||||
arrowBox.append(this._arrow, Big.BoxPackFlags.NONE);
|
arrowBox.append(this._arrow, Big.BoxPackFlags.NONE);
|
||||||
@@ -161,21 +156,25 @@ MenuItem.prototype = {
|
|||||||
}
|
}
|
||||||
Signals.addSignalMethods(MenuItem.prototype);
|
Signals.addSignalMethods(MenuItem.prototype);
|
||||||
|
|
||||||
|
|
||||||
/* This class represents a display containing a collection of application items.
|
/* This class represents a display containing a collection of application items.
|
||||||
* The applications are sorted based on their popularity by default, and based on
|
* The applications are sorted based on their popularity by default, and based on
|
||||||
* their name if some search filter is applied.
|
* their name if some search filter is applied.
|
||||||
|
*
|
||||||
|
* showPrefs - a boolean indicating if this AppDisplay should contain preference
|
||||||
|
* applets, rather than applications
|
||||||
*/
|
*/
|
||||||
function AppDisplay() {
|
function AppDisplay(showPrefs) {
|
||||||
this._init();
|
this._init(showPrefs);
|
||||||
}
|
}
|
||||||
|
|
||||||
AppDisplay.prototype = {
|
AppDisplay.prototype = {
|
||||||
__proto__: GenericDisplay.GenericDisplay.prototype,
|
__proto__: GenericDisplay.GenericDisplay.prototype,
|
||||||
|
|
||||||
_init : function() {
|
_init : function(showPrefs) {
|
||||||
GenericDisplay.GenericDisplay.prototype._init.call(this);
|
GenericDisplay.GenericDisplay.prototype._init.call(this);
|
||||||
|
|
||||||
|
this._showPrefs = showPrefs;
|
||||||
|
|
||||||
this._menus = [];
|
this._menus = [];
|
||||||
this._menuDisplays = [];
|
this._menuDisplays = [];
|
||||||
|
|
||||||
@@ -187,17 +186,17 @@ AppDisplay.prototype = {
|
|||||||
this._appsStale = true;
|
this._appsStale = true;
|
||||||
this._appSystem.connect('installed-changed', Lang.bind(this, function(appSys) {
|
this._appSystem.connect('installed-changed', Lang.bind(this, function(appSys) {
|
||||||
this._appsStale = true;
|
this._appsStale = true;
|
||||||
this._redisplay(false);
|
this._redisplay(0);
|
||||||
this._redisplayMenus();
|
this._redisplayMenus();
|
||||||
}));
|
}));
|
||||||
this._appSystem.connect('favorites-changed', Lang.bind(this, function(appSys) {
|
this._appSystem.connect('favorites-changed', Lang.bind(this, function(appSys) {
|
||||||
this._redisplay(false);
|
this._redisplay(0);
|
||||||
}));
|
}));
|
||||||
this._appMonitor.connect('app-added', Lang.bind(this, function(monitor) {
|
this._appMonitor.connect('app-added', Lang.bind(this, function(monitor) {
|
||||||
this._redisplay(false);
|
this._redisplay(0);
|
||||||
}));
|
}));
|
||||||
this._appMonitor.connect('app-removed', Lang.bind(this, function(monitor) {
|
this._appMonitor.connect('app-removed', Lang.bind(this, function(monitor) {
|
||||||
this._redisplay(false);
|
this._redisplay(0);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Load the apps now so it doesn't slow down the first
|
// Load the apps now so it doesn't slow down the first
|
||||||
@@ -285,8 +284,8 @@ AppDisplay.prototype = {
|
|||||||
})).filter(function (e) { return e != null });
|
})).filter(function (e) { return e != null });
|
||||||
},
|
},
|
||||||
|
|
||||||
_addMenuItem: function(name, id, icon, index) {
|
_addMenuItem: function(name, id, index) {
|
||||||
let display = new MenuItem(name, id, icon);
|
let display = new MenuItem(name, id);
|
||||||
this._menuDisplays.push(display);
|
this._menuDisplays.push(display);
|
||||||
display.connect('state-changed', Lang.bind(this, function (display) {
|
display.connect('state-changed', Lang.bind(this, function (display) {
|
||||||
let activated = display.getState() != MENU_UNSELECTED;
|
let activated = display.getState() != MENU_UNSELECTED;
|
||||||
@@ -312,9 +311,13 @@ AppDisplay.prototype = {
|
|||||||
_redisplayMenus: function() {
|
_redisplayMenus: function() {
|
||||||
this._menuDisplay.remove_all();
|
this._menuDisplay.remove_all();
|
||||||
this._addMenuItem(_("Frequent"), null, 'gtk-select-all');
|
this._addMenuItem(_("Frequent"), null, 'gtk-select-all');
|
||||||
|
// Adding an empty box here results in double spacing between
|
||||||
|
// "Frequent" and the other items.
|
||||||
|
let separator_actor = new Big.Box();
|
||||||
|
this._menuDisplay.append(separator_actor, 0);
|
||||||
for (let i = 0; i < this._menus.length; i++) {
|
for (let i = 0; i < this._menus.length; i++) {
|
||||||
let menu = this._menus[i];
|
let menu = this._menus[i];
|
||||||
this._addMenuItem(menu.name, menu.id, menu.icon, i+1);
|
this._addMenuItem(menu.name, menu.id, i+1);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -327,44 +330,47 @@ AppDisplay.prototype = {
|
|||||||
|
|
||||||
// Gets information about all applications by calling Gio.app_info_get_all().
|
// Gets information about all applications by calling Gio.app_info_get_all().
|
||||||
_refreshCache : function() {
|
_refreshCache : function() {
|
||||||
let me = this;
|
|
||||||
if (!this._appsStale)
|
if (!this._appsStale)
|
||||||
return;
|
return true;
|
||||||
this._allItems = {};
|
this._allItems = {};
|
||||||
this._appCategories = {};
|
this._appCategories = {};
|
||||||
|
|
||||||
// Loop over the toplevel menu items, load the set of desktop file ids
|
if (this._showPrefs) {
|
||||||
// associated with each one, skipping empty menus
|
// Get the desktop file ids for settings/preferences.
|
||||||
let allMenus = this._appSystem.get_menus();
|
// These are used for search results, but not in the app menus.
|
||||||
this._menus = [];
|
let settings = this._appSystem.get_all_settings();
|
||||||
for (let i = 0; i < allMenus.length; i++) {
|
for (let i = 0; i < settings.length; i++) {
|
||||||
let menu = allMenus[i];
|
let app = settings[i];
|
||||||
let menuApps = this._appSystem.get_applications_for_menu(menu.id);
|
|
||||||
let hasVisibleApps = menuApps.some(function (app) { return !app.get_is_nodisplay(); });
|
|
||||||
if (!hasVisibleApps) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
this._menus.push(menu);
|
|
||||||
for (let j = 0; j < menuApps.length; j++) {
|
|
||||||
let app = menuApps[j];
|
|
||||||
this._addApp(app);
|
this._addApp(app);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
|
// Loop over the toplevel menu items, load the set of desktop file ids
|
||||||
// Now grab the desktop file ids for settings/preferences.
|
// associated with each one, skipping empty menus
|
||||||
// These show up in search, but not with the rest of apps.
|
let allMenus = this._appSystem.get_menus();
|
||||||
let settings = this._appSystem.get_all_settings();
|
this._menus = [];
|
||||||
for (let i = 0; i < settings.length; i++) {
|
for (let i = 0; i < allMenus.length; i++) {
|
||||||
let app = settings[i];
|
let menu = allMenus[i];
|
||||||
this._addApp(app);
|
let menuApps = this._appSystem.get_applications_for_menu(menu.id);
|
||||||
|
let hasVisibleApps = menuApps.some(function (app) { return !app.get_is_nodisplay(); });
|
||||||
|
if (!hasVisibleApps) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
this._menus.push(menu);
|
||||||
|
for (let j = 0; j < menuApps.length; j++) {
|
||||||
|
let app = menuApps[j];
|
||||||
|
this._addApp(app);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this._appsStale = false;
|
this._appsStale = false;
|
||||||
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
// Stub this out; the app display always has a category selected
|
// Stub this out; the app display always has a category selected
|
||||||
_setDefaultList : function() {
|
_setDefaultList : function() {
|
||||||
this._matchedItems = [];
|
this._matchedItems = {};
|
||||||
|
this._matchedItemKeys = [];
|
||||||
},
|
},
|
||||||
|
|
||||||
// Compares items associated with the item ids based on the alphabetical order
|
// Compares items associated with the item ids based on the alphabetical order
|
||||||
@@ -448,35 +454,40 @@ AppDisplay.prototype = {
|
|||||||
|
|
||||||
Signals.addSignalMethods(AppDisplay.prototype);
|
Signals.addSignalMethods(AppDisplay.prototype);
|
||||||
|
|
||||||
function WellDisplayItem(appInfo, isFavorite) {
|
function BaseWellItem(appInfo, isFavorite, hasMenu) {
|
||||||
this._init(appInfo, isFavorite);
|
this._init(appInfo, isFavorite, hasMenu);
|
||||||
}
|
}
|
||||||
|
|
||||||
WellDisplayItem.prototype = {
|
BaseWellItem.prototype = {
|
||||||
__proto__ : AppIcon.AppIcon.prototype,
|
__proto__: AppIcon.AppIcon.prototype,
|
||||||
|
|
||||||
_init : function(appInfo, isFavorite) {
|
_init: function(appInfo, isFavorite, hasMenu) {
|
||||||
AppIcon.AppIcon.prototype._init.call(this, appInfo);
|
AppIcon.AppIcon.prototype._init.call(this, appInfo, hasMenu ? AppIcon.MenuType.ON_RIGHT : AppIcon.MenuType.NONE);
|
||||||
|
|
||||||
this.isFavorite = isFavorite;
|
this.isFavorite = isFavorite;
|
||||||
|
|
||||||
this.actor.connect('button-release-event', Lang.bind(this, function (b, e) {
|
this._draggable = DND.makeDraggable(this.actor, true);
|
||||||
this._handleActivate();
|
|
||||||
|
// Do these as anonymous functions to avoid conflict with handlers in subclasses
|
||||||
|
this.actor.connect('button-press-event', Lang.bind(this, function(actor, event) {
|
||||||
|
let [stageX, stageY] = event.get_coords();
|
||||||
|
this._dragStartX = stageX;
|
||||||
|
this._dragStartY = stageY;
|
||||||
|
return false;
|
||||||
|
}));
|
||||||
|
this.actor.connect('notify::hover', Lang.bind(this, function () {
|
||||||
|
let hover = this.actor.hover;
|
||||||
|
if (!hover) {
|
||||||
|
if (this.actor.pressed && this._dragStartX != null) {
|
||||||
|
this.actor.fake_release();
|
||||||
|
this._draggable.startDrag(this._dragStartX, this._dragStartY,
|
||||||
|
Main.currentTime());
|
||||||
|
} else {
|
||||||
|
this._dragStartX = null;
|
||||||
|
this._dragStartY = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let draggable = DND.makeDraggable(this.actor);
|
|
||||||
},
|
|
||||||
|
|
||||||
_handleActivate: function () {
|
|
||||||
if (this._windows.length == 0) {
|
|
||||||
this.appInfo.launch();
|
|
||||||
Main.overview.hide();
|
|
||||||
} else {
|
|
||||||
/* Pick the first window and activate it;
|
|
||||||
* In the future, we want to have a menu dropdown here. */
|
|
||||||
let first = this._windows[0];
|
|
||||||
Main.overview.activateWindow(first, Clutter.get_current_event_time());
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
shellWorkspaceLaunch : function() {
|
shellWorkspaceLaunch : function() {
|
||||||
@@ -491,18 +502,98 @@ WellDisplayItem.prototype = {
|
|||||||
this.appInfo.launch();
|
this.appInfo.launch();
|
||||||
},
|
},
|
||||||
|
|
||||||
getDragActor: function(stageX, stageY) {
|
getDragActor: function() {
|
||||||
return this.appInfo.create_icon_texture(this._icon.height);
|
return this.createDragActor();
|
||||||
},
|
},
|
||||||
|
|
||||||
// Returns the original icon that is being used as a source for the cloned texture
|
// Returns the original icon that is being used as a source for the cloned texture
|
||||||
// that represents the item as it is being dragged.
|
// that represents the item as it is being dragged.
|
||||||
getDragActorSource: function() {
|
getDragActorSource: function() {
|
||||||
return this._icon;
|
return this.actor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function RunningWellItem(appInfo, isFavorite) {
|
||||||
|
this._init(appInfo, isFavorite);
|
||||||
|
}
|
||||||
|
|
||||||
|
RunningWellItem.prototype = {
|
||||||
|
__proto__: BaseWellItem.prototype,
|
||||||
|
|
||||||
|
_init: function(appInfo, isFavorite) {
|
||||||
|
BaseWellItem.prototype._init.call(this, appInfo, isFavorite, true);
|
||||||
|
|
||||||
|
this._dragStartX = 0;
|
||||||
|
this._dragStartY = 0;
|
||||||
|
|
||||||
|
this.actor.connect('activate', Lang.bind(this, this._onActivate));
|
||||||
},
|
},
|
||||||
|
|
||||||
setWidth: function(width) {
|
_onActivate: function (actor, event) {
|
||||||
this._nameBox.width = width + GLOW_PADDING * 2;
|
let modifiers = event.get_state();
|
||||||
|
|
||||||
|
if (modifiers & Clutter.ModifierType.CONTROL_MASK) {
|
||||||
|
this.appInfo.launch();
|
||||||
|
} else {
|
||||||
|
this.activateMostRecentWindow();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
activateMostRecentWindow: function () {
|
||||||
|
// The _get_windows_for_app sorts them for us
|
||||||
|
let mostRecentWindow = this.windows[0];
|
||||||
|
Main.overview.activateWindow(mostRecentWindow, Main.currentTime());
|
||||||
|
},
|
||||||
|
|
||||||
|
highlightWindow: function(metaWindow) {
|
||||||
|
Main.overview.getWorkspacesForWindow(metaWindow).setHighlightWindow(metaWindow);
|
||||||
|
},
|
||||||
|
|
||||||
|
activateWindow: function(metaWindow) {
|
||||||
|
if (metaWindow) {
|
||||||
|
this._didActivateWindow = true;
|
||||||
|
Main.overview.activateWindow(metaWindow, Main.currentTime());
|
||||||
|
} else
|
||||||
|
Main.overview.hide();
|
||||||
|
},
|
||||||
|
|
||||||
|
menuPoppedUp: function() {
|
||||||
|
Main.overview.getWorkspacesForWindow(null).setApplicationWindowSelection(this.appInfo.get_id());
|
||||||
|
},
|
||||||
|
|
||||||
|
menuPoppedDown: function() {
|
||||||
|
if (this._didActivateWindow)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Main.overview.getWorkspacesForWindow(null).setApplicationWindowSelection(null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function InactiveWellItem(appInfo, isFavorite) {
|
||||||
|
this._init(appInfo, isFavorite);
|
||||||
|
}
|
||||||
|
|
||||||
|
InactiveWellItem.prototype = {
|
||||||
|
__proto__: BaseWellItem.prototype,
|
||||||
|
|
||||||
|
_init : function(appInfo, isFavorite) {
|
||||||
|
BaseWellItem.prototype._init.call(this, appInfo, isFavorite);
|
||||||
|
|
||||||
|
this.actor.connect('notify::pressed', Lang.bind(this, this._onPressedChanged));
|
||||||
|
this.actor.connect('activate', Lang.bind(this, this._onActivate));
|
||||||
|
},
|
||||||
|
|
||||||
|
_onPressedChanged: function() {
|
||||||
|
this.setHighlight(this.actor.pressed);
|
||||||
|
},
|
||||||
|
|
||||||
|
_onActivate: function() {
|
||||||
|
if (this.windows.length == 0) {
|
||||||
|
this.appInfo.launch();
|
||||||
|
Main.overview.hide();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -532,9 +623,8 @@ WellGrid.prototype = {
|
|||||||
nColumns = children.length;
|
nColumns = children.length;
|
||||||
else
|
else
|
||||||
nColumns = WELL_DEFAULT_COLUMNS;
|
nColumns = WELL_DEFAULT_COLUMNS;
|
||||||
let spacing = Math.max(nColumns - 1, 0) * WELL_ITEM_HSPACING;
|
alloc.min_size = itemMin;
|
||||||
alloc.min_size = itemMin * nColumns + spacing;
|
alloc.natural_size = itemNatural * nColumns;
|
||||||
alloc.natural_size = itemNatural * nColumns + spacing;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_getPreferredHeight: function (grid, forWidth, alloc) {
|
_getPreferredHeight: function (grid, forWidth, alloc) {
|
||||||
@@ -582,7 +672,7 @@ WellGrid.prototype = {
|
|||||||
y += itemHeight + WELL_ITEM_VSPACING;
|
y += itemHeight + WELL_ITEM_VSPACING;
|
||||||
x = box.x1;
|
x = box.x1;
|
||||||
} else {
|
} else {
|
||||||
x += itemWidth + WELL_ITEM_HSPACING;
|
x += itemWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (atSeparator) {
|
if (atSeparator) {
|
||||||
@@ -632,19 +722,28 @@ WellGrid.prototype = {
|
|||||||
let children = this._getItemChildren();
|
let children = this._getItemChildren();
|
||||||
if (children.length == 0)
|
if (children.length == 0)
|
||||||
return [0, WELL_DEFAULT_COLUMNS, 0, 0];
|
return [0, WELL_DEFAULT_COLUMNS, 0, 0];
|
||||||
let nColumns;
|
let nColumns = 0;
|
||||||
if (children.length < WELL_DEFAULT_COLUMNS)
|
let usedWidth = 0;
|
||||||
nColumns = children.length;
|
if (forWidth < 0) {
|
||||||
else
|
|
||||||
nColumns = WELL_DEFAULT_COLUMNS;
|
nColumns = WELL_DEFAULT_COLUMNS;
|
||||||
|
} else {
|
||||||
if (forWidth >= 0 && forWidth < minWidth) {
|
while (nColumns < WELL_DEFAULT_COLUMNS &&
|
||||||
log("WellGrid: trying to allocate for width " + forWidth + " but min is " + minWidth);
|
nColumns < children.length &&
|
||||||
/* FIXME - we should fall back to fewer than WELL_DEFAULT_COLUMNS here */
|
usedWidth + itemMinWidth <= forWidth) {
|
||||||
|
// By including WELL_ITEM_MIN_HSPACING in usedWidth, we are ensuring
|
||||||
|
// that the number of columns we end up with will allow the spacing
|
||||||
|
// between the columns to be at least that value.
|
||||||
|
usedWidth += itemMinWidth + WELL_ITEM_MIN_HSPACING;
|
||||||
|
nColumns++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let horizSpacingTotal = Math.max(nColumns - 1, 0) * WELL_ITEM_HSPACING;
|
if (nColumns == 0) {
|
||||||
let minWidth = itemMinWidth * nColumns + horizSpacingTotal;
|
log("WellGrid: couldn't fit a column in width " + forWidth);
|
||||||
|
/* FIXME - fall back to smaller icon size */
|
||||||
|
}
|
||||||
|
|
||||||
|
let minWidth = itemMinWidth * nColumns;
|
||||||
|
|
||||||
let lastColumnIndex = nColumns - 1;
|
let lastColumnIndex = nColumns - 1;
|
||||||
let separatorColumns = lastColumnIndex - ((lastColumnIndex + this._separatorIndex) % nColumns);
|
let separatorColumns = lastColumnIndex - ((lastColumnIndex + this._separatorIndex) % nColumns);
|
||||||
@@ -654,7 +753,7 @@ WellGrid.prototype = {
|
|||||||
if (forWidth < 0) {
|
if (forWidth < 0) {
|
||||||
itemWidth = itemNaturalWidth;
|
itemWidth = itemNaturalWidth;
|
||||||
} else {
|
} else {
|
||||||
itemWidth = Math.max(forWidth - horizSpacingTotal, 0) / nColumns;
|
itemWidth = Math.floor(forWidth / nColumns);
|
||||||
}
|
}
|
||||||
|
|
||||||
let itemNaturalHeight = 0;
|
let itemNaturalHeight = 0;
|
||||||
@@ -664,7 +763,7 @@ WellGrid.prototype = {
|
|||||||
itemNaturalHeight = childNatural;
|
itemNaturalHeight = childNatural;
|
||||||
}
|
}
|
||||||
|
|
||||||
return [rows, WELL_DEFAULT_COLUMNS, itemWidth, itemNaturalHeight];
|
return [rows, nColumns, itemWidth, itemNaturalHeight];
|
||||||
},
|
},
|
||||||
|
|
||||||
_getItemPreferredWidth: function () {
|
_getItemPreferredWidth: function () {
|
||||||
@@ -755,22 +854,25 @@ AppWell.prototype = {
|
|||||||
this._displays = displays;
|
this._displays = displays;
|
||||||
},
|
},
|
||||||
|
|
||||||
_addApps: function(apps) {
|
_addApps: function(apps, isFavorite) {
|
||||||
for (let i = 0; i < apps.length; i++) {
|
for (let i = 0; i < apps.length; i++) {
|
||||||
let app = apps[i];
|
let app = apps[i];
|
||||||
let display = new WellDisplayItem(app, this.isFavorite);
|
let windows = this._appMonitor.get_windows_for_app(app.get_id());
|
||||||
|
let display;
|
||||||
|
if (windows.length > 0)
|
||||||
|
display = new RunningWellItem(app, isFavorite);
|
||||||
|
else
|
||||||
|
display = new InactiveWellItem(app, isFavorite);
|
||||||
this._grid.actor.add_actor(display.actor);
|
this._grid.actor.add_actor(display.actor);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// Draggable target interface
|
// Draggable target interface
|
||||||
acceptDrop : function(source, actor, x, y, time) {
|
acceptDrop : function(source, actor, x, y, time) {
|
||||||
let global = Shell.Global.get();
|
|
||||||
|
|
||||||
let appSystem = Shell.AppSystem.get_default();
|
let appSystem = Shell.AppSystem.get_default();
|
||||||
|
|
||||||
let app = null;
|
let app = null;
|
||||||
if (source instanceof WellDisplayItem) {
|
if (source instanceof BaseWellItem) {
|
||||||
app = source.appInfo;
|
app = source.appInfo;
|
||||||
} else if (source instanceof AppDisplayItem) {
|
} else if (source instanceof AppDisplayItem) {
|
||||||
app = appSystem.lookup_cached_app(source.getId());
|
app = appSystem.lookup_cached_app(source.getId());
|
||||||
|
|||||||
581
js/ui/appIcon.js
@@ -2,47 +2,100 @@
|
|||||||
|
|
||||||
const Big = imports.gi.Big;
|
const Big = imports.gi.Big;
|
||||||
const Clutter = imports.gi.Clutter;
|
const Clutter = imports.gi.Clutter;
|
||||||
|
const GLib = imports.gi.GLib;
|
||||||
|
const Lang = imports.lang;
|
||||||
|
const Mainloop = imports.mainloop;
|
||||||
const Pango = imports.gi.Pango;
|
const Pango = imports.gi.Pango;
|
||||||
const Shell = imports.gi.Shell;
|
const Shell = imports.gi.Shell;
|
||||||
const Lang = imports.lang;
|
const Signals = imports.signals;
|
||||||
|
const Gettext = imports.gettext.domain('gnome-shell');
|
||||||
|
const _ = Gettext.gettext;
|
||||||
|
|
||||||
const GenericDisplay = imports.ui.genericDisplay;
|
const GenericDisplay = imports.ui.genericDisplay;
|
||||||
const Main = imports.ui.main;
|
const Main = imports.ui.main;
|
||||||
|
const Workspaces = imports.ui.workspaces;
|
||||||
|
|
||||||
const GLOW_COLOR = new Clutter.Color();
|
const GLOW_COLOR = new Clutter.Color();
|
||||||
GLOW_COLOR.from_pixel(0x4f6ba4ff);
|
GLOW_COLOR.from_pixel(0x4f6ba4ff);
|
||||||
const GLOW_PADDING = 5;
|
const GLOW_PADDING_HORIZONTAL = 3;
|
||||||
|
const GLOW_PADDING_VERTICAL = 3;
|
||||||
|
|
||||||
const APP_ICON_SIZE = 48;
|
const APPICON_ICON_SIZE = 48;
|
||||||
|
|
||||||
function AppIcon(appInfo) {
|
const APPICON_PADDING = 1;
|
||||||
this._init(appInfo);
|
const APPICON_BORDER_WIDTH = 1;
|
||||||
|
const APPICON_CORNER_RADIUS = 4;
|
||||||
|
|
||||||
|
const APPICON_MENU_POPUP_TIMEOUT_MS = 600;
|
||||||
|
|
||||||
|
const APPICON_DEFAULT_BORDER_COLOR = new Clutter.Color();
|
||||||
|
APPICON_DEFAULT_BORDER_COLOR.from_pixel(0x787878ff);
|
||||||
|
const APPICON_MENU_BACKGROUND_COLOR = new Clutter.Color();
|
||||||
|
APPICON_MENU_BACKGROUND_COLOR.from_pixel(0x292929ff);
|
||||||
|
const APPICON_MENU_FONT = 'Sans 14px';
|
||||||
|
const APPICON_MENU_COLOR = new Clutter.Color();
|
||||||
|
APPICON_MENU_COLOR.from_pixel(0xffffffff);
|
||||||
|
const APPICON_MENU_SELECTED_COLOR = new Clutter.Color();
|
||||||
|
APPICON_MENU_SELECTED_COLOR.from_pixel(0x005b97ff);
|
||||||
|
const APPICON_MENU_SEPARATOR_COLOR = new Clutter.Color();
|
||||||
|
APPICON_MENU_SEPARATOR_COLOR.from_pixel(0x787878ff);
|
||||||
|
const APPICON_MENU_BORDER_WIDTH = 1;
|
||||||
|
const APPICON_MENU_ARROW_SIZE = 12;
|
||||||
|
const APPICON_MENU_CORNER_RADIUS = 4;
|
||||||
|
const APPICON_MENU_PADDING = 4;
|
||||||
|
|
||||||
|
const TRANSPARENT_COLOR = new Clutter.Color();
|
||||||
|
TRANSPARENT_COLOR.from_pixel(0x00000000);
|
||||||
|
|
||||||
|
const MenuType = { NONE: 0, ON_RIGHT: 1, BELOW: 2 };
|
||||||
|
|
||||||
|
function AppIcon(appInfo, menuType) {
|
||||||
|
this._init(appInfo, menuType || MenuType.NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
AppIcon.prototype = {
|
AppIcon.prototype = {
|
||||||
_init : function(appInfo) {
|
_init : function(appInfo, menuType) {
|
||||||
this.appInfo = appInfo;
|
this.appInfo = appInfo;
|
||||||
|
this._menuType = menuType;
|
||||||
|
|
||||||
this.actor = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
this.actor = new Shell.ButtonBox({ orientation: Big.BoxOrientation.VERTICAL,
|
||||||
corner_radius: 2,
|
border: APPICON_BORDER_WIDTH,
|
||||||
border: 0,
|
corner_radius: APPICON_CORNER_RADIUS,
|
||||||
padding: 1,
|
padding: APPICON_PADDING,
|
||||||
border_color: GenericDisplay.ITEM_DISPLAY_SELECTED_BACKGROUND_COLOR,
|
reactive: true });
|
||||||
reactive: true });
|
|
||||||
this.actor._delegate = this;
|
this.actor._delegate = this;
|
||||||
|
this.highlight_border_color = APPICON_DEFAULT_BORDER_COLOR;
|
||||||
|
|
||||||
|
if (menuType != MenuType.NONE) {
|
||||||
|
this.windows = Shell.AppMonitor.get_default().get_windows_for_app(appInfo.get_id());
|
||||||
|
for (let i = 0; i < this.windows.length; i++) {
|
||||||
|
this.windows[i].connect('notify::user-time', Lang.bind(this, this._resortWindows));
|
||||||
|
}
|
||||||
|
this._resortWindows();
|
||||||
|
|
||||||
|
this.actor.connect('button-press-event', Lang.bind(this, this._updateMenuOnButtonPress));
|
||||||
|
this.actor.connect('notify::hover', Lang.bind(this, this._updateMenuOnHoverChanged));
|
||||||
|
this.actor.connect('activate', Lang.bind(this, this._updateMenuOnActivate));
|
||||||
|
|
||||||
|
this._menuTimeoutId = 0;
|
||||||
|
this._menu = null;
|
||||||
|
} else
|
||||||
|
this.windows = [];
|
||||||
|
|
||||||
let iconBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
let iconBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
||||||
x_align: Big.BoxAlignment.CENTER,
|
x_align: Big.BoxAlignment.CENTER,
|
||||||
y_align: Big.BoxAlignment.CENTER });
|
y_align: Big.BoxAlignment.CENTER,
|
||||||
this._icon = appInfo.create_icon_texture(APP_ICON_SIZE);
|
width: APPICON_ICON_SIZE,
|
||||||
iconBox.append(this._icon, Big.BoxPackFlags.NONE);
|
height: APPICON_ICON_SIZE });
|
||||||
|
this.icon = appInfo.create_icon_texture(APPICON_ICON_SIZE);
|
||||||
|
iconBox.append(this.icon, Big.BoxPackFlags.NONE);
|
||||||
|
|
||||||
this.actor.append(iconBox, Big.BoxPackFlags.EXPAND);
|
this.actor.append(iconBox, Big.BoxPackFlags.EXPAND);
|
||||||
|
|
||||||
this._windows = Shell.AppMonitor.get_default().get_windows_for_app(appInfo.get_id());
|
let nameBox = new Shell.GenericContainer();
|
||||||
|
nameBox.connect('get-preferred-width', Lang.bind(this, this._nameBoxGetPreferredWidth));
|
||||||
let nameBox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
nameBox.connect('get-preferred-height', Lang.bind(this, this._nameBoxGetPreferredHeight));
|
||||||
x_align: Big.BoxAlignment.CENTER });
|
nameBox.connect('allocate', Lang.bind(this, this._nameBoxAllocate));
|
||||||
this._nameBox = nameBox;
|
this._nameBox = nameBox;
|
||||||
|
|
||||||
this._name = new Clutter.Text({ color: GenericDisplay.ITEM_DISPLAY_NAME_COLOR,
|
this._name = new Clutter.Text({ color: GenericDisplay.ITEM_DISPLAY_NAME_COLOR,
|
||||||
@@ -50,34 +103,470 @@ AppIcon.prototype = {
|
|||||||
line_alignment: Pango.Alignment.CENTER,
|
line_alignment: Pango.Alignment.CENTER,
|
||||||
ellipsize: Pango.EllipsizeMode.END,
|
ellipsize: Pango.EllipsizeMode.END,
|
||||||
text: appInfo.get_name() });
|
text: appInfo.get_name() });
|
||||||
nameBox.append(this._name, Big.BoxPackFlags.NONE);
|
nameBox.add_actor(this._name);
|
||||||
if (this._windows.length > 0) {
|
this._glowBox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL });
|
||||||
let glow = new Shell.DrawingArea({});
|
let glowPath = GLib.filename_to_uri(global.imagedir + 'app-well-glow.png', '');
|
||||||
glow.connect('redraw', Lang.bind(this, function (e, tex) {
|
for (let i = 0; i < this.windows.length && i < 3; i++) {
|
||||||
Shell.draw_app_highlight(tex,
|
let glow = Shell.TextureCache.get_default().load_uri_sync(Shell.TextureCachePolicy.FOREVER,
|
||||||
this._windows.length,
|
glowPath, -1, -1);
|
||||||
GLOW_COLOR.red / 255,
|
glow.keep_aspect_ratio = false;
|
||||||
GLOW_COLOR.green / 255,
|
this._glowBox.append(glow, Big.BoxPackFlags.EXPAND);
|
||||||
GLOW_COLOR.blue / 255,
|
|
||||||
GLOW_COLOR.alpha / 255);
|
|
||||||
}));
|
|
||||||
this._name.connect('notify::allocation', Lang.bind(this, function () {
|
|
||||||
let x = this._name.x;
|
|
||||||
let y = this._name.y;
|
|
||||||
let width = this._name.width;
|
|
||||||
let height = this._name.height;
|
|
||||||
// If we're smaller than the allocated box width, pad out the glow a bit
|
|
||||||
// to make it more visible
|
|
||||||
if ((width + GLOW_PADDING * 2) < this._nameBox.width) {
|
|
||||||
width += GLOW_PADDING * 2;
|
|
||||||
x -= GLOW_PADDING;
|
|
||||||
}
|
|
||||||
glow.set_size(width, height);
|
|
||||||
glow.set_position(x, y);
|
|
||||||
}));
|
|
||||||
nameBox.add_actor(glow);
|
|
||||||
glow.lower(this._name);
|
|
||||||
}
|
}
|
||||||
|
this._nameBox.add_actor(this._glowBox);
|
||||||
|
this._glowBox.lower(this._name);
|
||||||
this.actor.append(nameBox, Big.BoxPackFlags.NONE);
|
this.actor.append(nameBox, Big.BoxPackFlags.NONE);
|
||||||
|
},
|
||||||
|
|
||||||
|
_nameBoxGetPreferredWidth: function (nameBox, forHeight, alloc) {
|
||||||
|
let [min, natural] = this._name.get_preferred_width(forHeight);
|
||||||
|
alloc.min_size = min + GLOW_PADDING_HORIZONTAL * 2;
|
||||||
|
alloc.natural_size = natural + GLOW_PADDING_HORIZONTAL * 2;
|
||||||
|
},
|
||||||
|
|
||||||
|
_nameBoxGetPreferredHeight: function (nameBox, forWidth, alloc) {
|
||||||
|
let [min, natural] = this._name.get_preferred_height(forWidth);
|
||||||
|
alloc.min_size = min + GLOW_PADDING_VERTICAL * 2;
|
||||||
|
alloc.natural_size = natural + GLOW_PADDING_VERTICAL * 2;
|
||||||
|
},
|
||||||
|
|
||||||
|
_nameBoxAllocate: function (nameBox, box, flags) {
|
||||||
|
let childBox = new Clutter.ActorBox();
|
||||||
|
let [minWidth, naturalWidth] = this._name.get_preferred_width(-1);
|
||||||
|
let [minHeight, naturalHeight] = this._name.get_preferred_height(-1);
|
||||||
|
let availWidth = box.x2 - box.x1;
|
||||||
|
let availHeight = box.y2 - box.y1;
|
||||||
|
let targetWidth = availWidth;
|
||||||
|
let xPadding = 0;
|
||||||
|
if (naturalWidth < availWidth) {
|
||||||
|
xPadding = Math.floor((availWidth - naturalWidth) / 2);
|
||||||
|
}
|
||||||
|
childBox.x1 = xPadding;
|
||||||
|
childBox.x2 = availWidth - xPadding;
|
||||||
|
childBox.y1 = GLOW_PADDING_VERTICAL;
|
||||||
|
childBox.y2 = availHeight - GLOW_PADDING_VERTICAL;
|
||||||
|
this._name.allocate(childBox, flags);
|
||||||
|
|
||||||
|
// Now the glow
|
||||||
|
if (this._glowBox != null) {
|
||||||
|
let glowPaddingHoriz = Math.max(0, xPadding - GLOW_PADDING_HORIZONTAL);
|
||||||
|
glowPaddingHoriz = Math.max(GLOW_PADDING_HORIZONTAL, glowPaddingHoriz);
|
||||||
|
childBox.x1 = glowPaddingHoriz;
|
||||||
|
childBox.x2 = availWidth - glowPaddingHoriz;
|
||||||
|
childBox.y1 = 0;
|
||||||
|
childBox.y2 = availHeight;
|
||||||
|
this._glowBox.allocate(childBox, flags);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_resortWindows: function() {
|
||||||
|
this.windows.sort(function (a, b) {
|
||||||
|
let visA = a.showing_on_its_workspace();
|
||||||
|
let visB = b.showing_on_its_workspace();
|
||||||
|
|
||||||
|
if (visA && !visB)
|
||||||
|
return -1;
|
||||||
|
else if (visB && !visA)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return b.get_user_time() - a.get_user_time();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// AppIcon itself is not a draggable, but if you want to make
|
||||||
|
// a subclass of it draggable, you can use this method to create
|
||||||
|
// a drag actor
|
||||||
|
createDragActor: function() {
|
||||||
|
return this.appInfo.create_icon_texture(APPICON_ICON_SIZE);
|
||||||
|
},
|
||||||
|
|
||||||
|
setHighlight: function(highlight) {
|
||||||
|
if (highlight) {
|
||||||
|
this.actor.border_color = this.highlight_border_color;
|
||||||
|
} else {
|
||||||
|
this.actor.border_color = TRANSPARENT_COLOR;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_updateMenuOnActivate: function(actor, event) {
|
||||||
|
if (this._menuTimeoutId != 0) {
|
||||||
|
Mainloop.source_remove(this._menuTimeoutId);
|
||||||
|
this._menuTimeoutId = 0;
|
||||||
|
}
|
||||||
|
this.emit('activate');
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
_updateMenuOnHoverChanged: function() {
|
||||||
|
if (!this.actor.hover && this._menuTimeoutId != 0) {
|
||||||
|
Mainloop.source_remove(this._menuTimeoutId);
|
||||||
|
this._menuTimeoutId = 0;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
_updateMenuOnButtonPress: function(actor, event) {
|
||||||
|
if (this._menuTimeoutId != 0)
|
||||||
|
Mainloop.source_remove(this._menuTimeoutId);
|
||||||
|
this._menuTimeoutId = Mainloop.timeout_add(APPICON_MENU_POPUP_TIMEOUT_MS,
|
||||||
|
Lang.bind(this, this.popupMenu));
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
popupMenu: function() {
|
||||||
|
if (this._menuTimeoutId != 0) {
|
||||||
|
Mainloop.source_remove(this._menuTimeoutId);
|
||||||
|
this._menuTimeoutId = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.actor.fake_release();
|
||||||
|
|
||||||
|
if (!this._menu) {
|
||||||
|
this._menu = new AppIconMenu(this, this._menuType);
|
||||||
|
this._menu.connect('highlight-window', Lang.bind(this, function (menu, window) {
|
||||||
|
this.highlightWindow(window);
|
||||||
|
}));
|
||||||
|
this._menu.connect('activate-window', Lang.bind(this, function (menu, window) {
|
||||||
|
this.activateWindow(window);
|
||||||
|
}));
|
||||||
|
this._menu.connect('popup', Lang.bind(this, function (menu, isPoppedUp) {
|
||||||
|
if (isPoppedUp)
|
||||||
|
this.menuPoppedUp();
|
||||||
|
else
|
||||||
|
this.menuPoppedDown();
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
this._menu.popup();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Default implementations; AppDisplay.RunningWellItem overrides these
|
||||||
|
highlightWindow: function(window) {
|
||||||
|
this.emit('highlight-window', window);
|
||||||
|
},
|
||||||
|
|
||||||
|
activateWindow: function(window) {
|
||||||
|
this.emit('activate-window', window);
|
||||||
|
},
|
||||||
|
|
||||||
|
menuPoppedUp: function() {
|
||||||
|
this.emit('menu-popped-up', this._menu);
|
||||||
|
},
|
||||||
|
|
||||||
|
menuPoppedDown: function() {
|
||||||
|
this.emit('menu-popped-down', this._menu);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Signals.addSignalMethods(AppIcon.prototype);
|
||||||
|
|
||||||
|
function AppIconMenu(source, type) {
|
||||||
|
this._init(source, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
AppIconMenu.prototype = {
|
||||||
|
_init: function(source, type) {
|
||||||
|
this._source = source;
|
||||||
|
this._type = type;
|
||||||
|
|
||||||
|
this.actor = new Shell.GenericContainer({ reactive: true });
|
||||||
|
this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
|
||||||
|
this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
|
||||||
|
this.actor.connect('allocate', Lang.bind(this, this._allocate));
|
||||||
|
|
||||||
|
this._windowContainer = new Shell.Menu({ orientation: Big.BoxOrientation.VERTICAL,
|
||||||
|
border_color: source.highlight_border_color,
|
||||||
|
border: APPICON_MENU_BORDER_WIDTH,
|
||||||
|
background_color: APPICON_MENU_BACKGROUND_COLOR,
|
||||||
|
padding: 4,
|
||||||
|
corner_radius: APPICON_MENU_CORNER_RADIUS,
|
||||||
|
width: Main.overview._dash.actor.width * 0.75 });
|
||||||
|
this._windowContainer.connect('unselected', Lang.bind(this, this._onItemUnselected));
|
||||||
|
this._windowContainer.connect('selected', Lang.bind(this, this._onItemSelected));
|
||||||
|
this._windowContainer.connect('cancelled', Lang.bind(this, this._onWindowSelectionCancelled));
|
||||||
|
this._windowContainer.connect('activate', Lang.bind(this, this._onItemActivate));
|
||||||
|
this.actor.add_actor(this._windowContainer);
|
||||||
|
|
||||||
|
// Stay popped up on release over application icon
|
||||||
|
this._windowContainer.set_persistent_source(this._source.actor);
|
||||||
|
|
||||||
|
// Intercept events while the menu has the pointer grab to do window-related effects
|
||||||
|
this._windowContainer.connect('enter-event', Lang.bind(this, this._onMenuEnter));
|
||||||
|
this._windowContainer.connect('leave-event', Lang.bind(this, this._onMenuLeave));
|
||||||
|
this._windowContainer.connect('button-release-event', Lang.bind(this, this._onMenuButtonRelease));
|
||||||
|
|
||||||
|
this._arrow = new Shell.DrawingArea();
|
||||||
|
this._arrow.connect('redraw', Lang.bind(this, function (area, texture) {
|
||||||
|
Shell.draw_box_pointer(texture,
|
||||||
|
this._type == MenuType.ON_RIGHT ? Clutter.Gravity.WEST : Clutter.Gravity.NORTH,
|
||||||
|
source.highlight_border_color,
|
||||||
|
APPICON_MENU_BACKGROUND_COLOR);
|
||||||
|
}));
|
||||||
|
this.actor.add_actor(this._arrow);
|
||||||
|
|
||||||
|
// Chain our visibility and lifecycle to that of the source
|
||||||
|
source.actor.connect('notify::mapped', Lang.bind(this, function () {
|
||||||
|
if (!source.actor.mapped)
|
||||||
|
this._windowContainer.popdown();
|
||||||
|
}));
|
||||||
|
source.actor.connect('destroy', Lang.bind(this, function () { this.actor.destroy(); }));
|
||||||
|
|
||||||
|
global.stage.add_actor(this.actor);
|
||||||
|
},
|
||||||
|
|
||||||
|
_getPreferredWidth: function(actor, forHeight, alloc) {
|
||||||
|
let [min, natural] = this._windowContainer.get_preferred_width(forHeight);
|
||||||
|
if (this._type == MenuType.ON_RIGHT) {
|
||||||
|
min += APPICON_MENU_ARROW_SIZE;
|
||||||
|
natural += APPICON_MENU_ARROW_SIZE;
|
||||||
|
}
|
||||||
|
alloc.min_size = min;
|
||||||
|
alloc.natural_size = natural;
|
||||||
|
},
|
||||||
|
|
||||||
|
_getPreferredHeight: function(actor, forWidth, alloc) {
|
||||||
|
let [min, natural] = this._windowContainer.get_preferred_height(forWidth);
|
||||||
|
if (this._type == MenuType.BELOW) {
|
||||||
|
min += APPICON_MENU_ARROW_SIZE;
|
||||||
|
natural += APPICON_MENU_ARROW_SIZE;
|
||||||
|
}
|
||||||
|
alloc.min_size = min;
|
||||||
|
alloc.natural_size = natural;
|
||||||
|
},
|
||||||
|
|
||||||
|
_allocate: function(actor, box, flags) {
|
||||||
|
let childBox = new Clutter.ActorBox();
|
||||||
|
|
||||||
|
let width = box.x2 - box.x1;
|
||||||
|
let height = box.y2 - box.y1;
|
||||||
|
|
||||||
|
if (this._type == MenuType.ON_RIGHT) {
|
||||||
|
childBox.x1 = 0;
|
||||||
|
childBox.x2 = APPICON_MENU_ARROW_SIZE;
|
||||||
|
childBox.y1 = Math.floor((height / 2) - (APPICON_MENU_ARROW_SIZE / 2));
|
||||||
|
childBox.y2 = childBox.y1 + APPICON_MENU_ARROW_SIZE;
|
||||||
|
this._arrow.allocate(childBox, flags);
|
||||||
|
|
||||||
|
childBox.x1 = APPICON_MENU_ARROW_SIZE - APPICON_MENU_BORDER_WIDTH;
|
||||||
|
childBox.x2 = width;
|
||||||
|
childBox.y1 = 0;
|
||||||
|
childBox.y2 = height;
|
||||||
|
this._windowContainer.allocate(childBox, flags);
|
||||||
|
} else /* MenuType.BELOW */ {
|
||||||
|
childBox.x1 = Math.floor((width / 2) - (APPICON_MENU_ARROW_SIZE / 2));
|
||||||
|
childBox.x2 = childBox.x1 + APPICON_MENU_ARROW_SIZE;
|
||||||
|
childBox.y1 = 0;
|
||||||
|
childBox.y2 = APPICON_MENU_ARROW_SIZE;
|
||||||
|
this._arrow.allocate(childBox, flags);
|
||||||
|
|
||||||
|
childBox.x1 = 0;
|
||||||
|
childBox.x2 = width;
|
||||||
|
childBox.y1 = APPICON_MENU_ARROW_SIZE - APPICON_MENU_BORDER_WIDTH;
|
||||||
|
childBox.y2 = height;
|
||||||
|
this._windowContainer.allocate(childBox, flags);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_redisplay: function() {
|
||||||
|
this._windowContainer.remove_all();
|
||||||
|
|
||||||
|
let windows = this._source.windows;
|
||||||
|
|
||||||
|
this._windowContainer.show();
|
||||||
|
|
||||||
|
let iconsDiffer = false;
|
||||||
|
let texCache = Shell.TextureCache.get_default();
|
||||||
|
let firstIcon = windows[0].mini_icon;
|
||||||
|
for (let i = 1; i < windows.length; i++) {
|
||||||
|
if (!texCache.pixbuf_equal(windows[i].mini_icon, firstIcon)) {
|
||||||
|
iconsDiffer = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let activeWorkspace = global.screen.get_active_workspace();
|
||||||
|
|
||||||
|
let currentWorkspaceWindows = windows.filter(function (w) {
|
||||||
|
return w.get_workspace() == activeWorkspace;
|
||||||
|
});
|
||||||
|
let otherWorkspaceWindows = windows.filter(function (w) {
|
||||||
|
return w.get_workspace() != activeWorkspace;
|
||||||
|
});
|
||||||
|
|
||||||
|
this._appendWindows(currentWorkspaceWindows, iconsDiffer);
|
||||||
|
if (currentWorkspaceWindows.length > 0 && otherWorkspaceWindows.length > 0) {
|
||||||
|
this._appendSeparator();
|
||||||
|
}
|
||||||
|
this._appendWindows(otherWorkspaceWindows, iconsDiffer);
|
||||||
|
|
||||||
|
this._appendSeparator();
|
||||||
|
|
||||||
|
this._newWindowMenuItem = this._appendMenuItem(null, _("New Window"));
|
||||||
|
|
||||||
|
this._highlightedItem = null;
|
||||||
|
},
|
||||||
|
|
||||||
|
_appendSeparator: function () {
|
||||||
|
let box = new Big.Box({ padding_top: 2, padding_bottom: 2 });
|
||||||
|
box.append(new Clutter.Rectangle({ height: 1,
|
||||||
|
color: APPICON_MENU_SEPARATOR_COLOR }),
|
||||||
|
Big.BoxPackFlags.EXPAND);
|
||||||
|
this._windowContainer.append_separator(box, Big.BoxPackFlags.NONE);
|
||||||
|
},
|
||||||
|
|
||||||
|
_appendMenuItem: function(iconTexture, labelText) {
|
||||||
|
/* Use padding here rather than spacing in the box above so that
|
||||||
|
* we have a larger reactive area.
|
||||||
|
*/
|
||||||
|
let box = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||||
|
padding_top: 4,
|
||||||
|
padding_bottom: 4,
|
||||||
|
spacing: 4,
|
||||||
|
reactive: true });
|
||||||
|
let vCenter;
|
||||||
|
if (iconTexture != null) {
|
||||||
|
vCenter = new Big.Box({ y_align: Big.BoxAlignment.CENTER });
|
||||||
|
vCenter.append(iconTexture, Big.BoxPackFlags.NONE);
|
||||||
|
box.append(vCenter, Big.BoxPackFlags.NONE);
|
||||||
|
}
|
||||||
|
vCenter = new Big.Box({ y_align: Big.BoxAlignment.CENTER });
|
||||||
|
let label = new Clutter.Text({ text: labelText,
|
||||||
|
font_name: APPICON_MENU_FONT,
|
||||||
|
ellipsize: Pango.EllipsizeMode.END,
|
||||||
|
color: APPICON_MENU_COLOR });
|
||||||
|
vCenter.append(label, Big.BoxPackFlags.NONE);
|
||||||
|
box.append(vCenter, Big.BoxPackFlags.NONE);
|
||||||
|
this._windowContainer.append(box, Big.BoxPackFlags.NONE);
|
||||||
|
return box;
|
||||||
|
},
|
||||||
|
|
||||||
|
_appendWindows: function (windows, iconsDiffer) {
|
||||||
|
for (let i = 0; i < windows.length; i++) {
|
||||||
|
let metaWindow = windows[i];
|
||||||
|
|
||||||
|
let icon = null;
|
||||||
|
if (iconsDiffer) {
|
||||||
|
icon = Shell.TextureCache.get_default().bind_pixbuf_property(metaWindow, "mini-icon");
|
||||||
|
}
|
||||||
|
let box = this._appendMenuItem(icon, metaWindow.title);
|
||||||
|
box._window = metaWindow;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
popup: function() {
|
||||||
|
let [stageX, stageY] = this._source.actor.get_transformed_position();
|
||||||
|
let [stageWidth, stageHeight] = this._source.actor.get_transformed_size();
|
||||||
|
|
||||||
|
this._redisplay();
|
||||||
|
|
||||||
|
this._windowContainer.popup(0, Main.currentTime());
|
||||||
|
|
||||||
|
this.emit('popup', true);
|
||||||
|
|
||||||
|
let x, y;
|
||||||
|
if (this._type == MenuType.ON_RIGHT) {
|
||||||
|
x = Math.floor(stageX + stageWidth);
|
||||||
|
y = Math.floor(stageY + (stageHeight / 2) - (this.actor.height / 2));
|
||||||
|
} else {
|
||||||
|
x = Math.floor(stageX + (stageWidth / 2) - (this.actor.width / 2));
|
||||||
|
y = Math.floor(stageY + stageHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.actor.set_position(x, y);
|
||||||
|
this.actor.show();
|
||||||
|
},
|
||||||
|
|
||||||
|
popdown: function() {
|
||||||
|
this._windowContainer.popdown();
|
||||||
|
this.emit('popup', false);
|
||||||
|
this.actor.hide();
|
||||||
|
},
|
||||||
|
|
||||||
|
selectWindow: function(metaWindow) {
|
||||||
|
this._selectMenuItemForWindow(metaWindow);
|
||||||
|
},
|
||||||
|
|
||||||
|
_findMetaWindowForActor: function (actor) {
|
||||||
|
if (actor._delegate instanceof Workspaces.WindowClone)
|
||||||
|
return actor._delegate.metaWindow;
|
||||||
|
else if (actor.get_meta_window)
|
||||||
|
return actor.get_meta_window();
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
|
||||||
|
// This function is called while the menu has a pointer grab; what we want
|
||||||
|
// to do is see if the mouse was released over a window representation
|
||||||
|
_onMenuButtonRelease: function (actor, event) {
|
||||||
|
let metaWindow = this._findMetaWindowForActor(event.get_source());
|
||||||
|
if (metaWindow) {
|
||||||
|
this.emit('activate-window', metaWindow);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_updateHighlight: function (item) {
|
||||||
|
if (this._highlightedItem) {
|
||||||
|
this._highlightedItem.background_color = TRANSPARENT_COLOR;
|
||||||
|
this.emit('highlight-window', null);
|
||||||
|
}
|
||||||
|
this._highlightedItem = item;
|
||||||
|
if (this._highlightedItem) {
|
||||||
|
this._highlightedItem.background_color = APPICON_MENU_SELECTED_COLOR;
|
||||||
|
let window = this._highlightedItem._window;
|
||||||
|
if (window)
|
||||||
|
this.emit('highlight-window', window);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_selectMenuItemForWindow: function (metaWindow) {
|
||||||
|
let children = this._windowContainer.get_children();
|
||||||
|
for (let i = 0; i < children.length; i++) {
|
||||||
|
let child = children[i];
|
||||||
|
let menuMetaWindow = child._window;
|
||||||
|
if (menuMetaWindow == metaWindow)
|
||||||
|
this._updateHighlight(child);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// Called while menu has a pointer grab
|
||||||
|
_onMenuEnter: function (actor, event) {
|
||||||
|
let metaWindow = this._findMetaWindowForActor(event.get_source());
|
||||||
|
if (metaWindow) {
|
||||||
|
this._selectMenuItemForWindow(metaWindow);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// Called while menu has a pointer grab
|
||||||
|
_onMenuLeave: function (actor, event) {
|
||||||
|
let metaWindow = this._findMetaWindowForActor(event.get_source());
|
||||||
|
if (metaWindow) {
|
||||||
|
this._updateHighlight(null);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_onItemUnselected: function (actor, child) {
|
||||||
|
this._updateHighlight(null);
|
||||||
|
},
|
||||||
|
|
||||||
|
_onItemSelected: function (actor, child) {
|
||||||
|
this._updateHighlight(child);
|
||||||
|
},
|
||||||
|
|
||||||
|
_onItemActivate: function (actor, child) {
|
||||||
|
if (child._window) {
|
||||||
|
let metaWindow = child._window;
|
||||||
|
this.emit('activate-window', metaWindow);
|
||||||
|
} else if (child == this._newWindowMenuItem) {
|
||||||
|
this._source.appInfo.launch();
|
||||||
|
this.emit('activate-window', null);
|
||||||
|
}
|
||||||
|
this.popdown();
|
||||||
|
},
|
||||||
|
|
||||||
|
_onWindowSelectionCancelled: function () {
|
||||||
|
this.emit('highlight-window', null);
|
||||||
|
this.popdown();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Signals.addSignalMethods(AppIconMenu.prototype);
|
||||||
|
|||||||
102
js/ui/button.js
@@ -22,14 +22,12 @@ const DEFAULT_FONT = 'Sans Bold 16px';
|
|||||||
// Padding on the left and right side of the button.
|
// Padding on the left and right side of the button.
|
||||||
const SIDE_PADDING = 14;
|
const SIDE_PADDING = 14;
|
||||||
|
|
||||||
function Button(widget, buttonColor, pressedButtonColor, textColor, staysPressed, font) {
|
function Button(widget, buttonColor, pressedButtonColor, textColor, font) {
|
||||||
this._init(widget, buttonColor, pressedButtonColor, textColor, staysPressed, font);
|
this._init(widget, buttonColor, pressedButtonColor, textColor, font);
|
||||||
}
|
}
|
||||||
|
|
||||||
Button.prototype = {
|
Button.prototype = {
|
||||||
_init : function(widgetOrText, buttonColor, pressedButtonColor, textColor, staysPressed, font) {
|
_init : function(widgetOrText, buttonColor, pressedButtonColor, textColor, font) {
|
||||||
let me = this;
|
|
||||||
|
|
||||||
this._buttonColor = buttonColor
|
this._buttonColor = buttonColor
|
||||||
if (buttonColor == null)
|
if (buttonColor == null)
|
||||||
this._buttonColor = DEFAULT_BUTTON_COLOR;
|
this._buttonColor = DEFAULT_BUTTON_COLOR;
|
||||||
@@ -42,27 +40,20 @@ Button.prototype = {
|
|||||||
if (textColor == null)
|
if (textColor == null)
|
||||||
this._textColor = DEFAULT_TEXT_COLOR;
|
this._textColor = DEFAULT_TEXT_COLOR;
|
||||||
|
|
||||||
this._staysPressed = staysPressed
|
|
||||||
if (staysPressed == null)
|
|
||||||
this._staysPressed = false;
|
|
||||||
|
|
||||||
this._font = font;
|
this._font = font;
|
||||||
if (font == null)
|
if (font == null)
|
||||||
this._font = DEFAULT_FONT;
|
this._font = DEFAULT_FONT;
|
||||||
|
|
||||||
// if this._staysPressed is true, this._active will be true past the first release of a button, until a subsequent one (the button
|
|
||||||
// is unpressed) or until release() is called explicitly
|
|
||||||
this._active = false;
|
|
||||||
this._isBetweenPressAndRelease = false;
|
this._isBetweenPressAndRelease = false;
|
||||||
this._mouseIsOverButton = false;
|
this._mouseIsOverButton = false;
|
||||||
|
|
||||||
this.button = new Big.Box({ reactive: true,
|
this.actor = new Shell.ButtonBox({ reactive: true,
|
||||||
corner_radius: 5,
|
corner_radius: 5,
|
||||||
padding_left: SIDE_PADDING,
|
padding_left: SIDE_PADDING,
|
||||||
padding_right: SIDE_PADDING,
|
padding_right: SIDE_PADDING,
|
||||||
orientation: Big.BoxOrientation.HORIZONTAL,
|
orientation: Big.BoxOrientation.HORIZONTAL,
|
||||||
y_align: Big.BoxAlignment.CENTER
|
y_align: Big.BoxAlignment.CENTER
|
||||||
});
|
});
|
||||||
if (typeof widgetOrText == 'string') {
|
if (typeof widgetOrText == 'string') {
|
||||||
this._widget = new Clutter.Text({ font_name: this._font,
|
this._widget = new Clutter.Text({ font_name: this._font,
|
||||||
color: this._textColor,
|
color: this._textColor,
|
||||||
@@ -71,61 +62,20 @@ Button.prototype = {
|
|||||||
this._widget = widgetOrText;
|
this._widget = widgetOrText;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.button.append(this._widget, Big.BoxPackFlags.EXPAND);
|
this.actor.append(this._widget, Big.BoxPackFlags.EXPAND);
|
||||||
|
|
||||||
this.button.connect('button-press-event',
|
this.actor.connect('notify::hover', Lang.bind(this, this._updateColors));
|
||||||
function(o, event) {
|
this.actor.connect('notify::pressed', Lang.bind(this, this._updateColors));
|
||||||
me._isBetweenPressAndRelease = true;
|
this.actor.connect('notify::active', Lang.bind(this, this._updateColors));
|
||||||
me.button.backgroundColor = me._pressedButtonColor;
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
this.button.connect('button-release-event',
|
|
||||||
function(o, event) {
|
|
||||||
me._isBetweenPressAndRelease = false;
|
|
||||||
if (!me._staysPressed || me._active) {
|
|
||||||
me.release();
|
|
||||||
} else {
|
|
||||||
me._active = true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
this.button.connect('enter-event',
|
|
||||||
function(o, event) {
|
|
||||||
me._mouseIsOverButton = true;
|
|
||||||
if (!me._active) {
|
|
||||||
me.button.backgroundColor = me._buttonColor;
|
|
||||||
}
|
|
||||||
me.emit('enter-event');
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
this.button.connect('leave-event',
|
|
||||||
function(o, event) {
|
|
||||||
me._isBetweenPressAndRelease = false;
|
|
||||||
me._mouseIsOverButton = false;
|
|
||||||
if (!me._active) {
|
|
||||||
me.button.backgroundColor = null;
|
|
||||||
}
|
|
||||||
me.emit('leave-event');
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
pressIn : function() {
|
_updateColors : function() {
|
||||||
if (!this._isBetweenPressAndRelease && this._staysPressed) {
|
if (this.actor.active || this.actor.pressed)
|
||||||
this._active = true;
|
this.actor.backgroundColor = this._pressedButtonColor;
|
||||||
this.button.backgroundColor = this._pressedButtonColor;
|
else if (this.actor.hover)
|
||||||
}
|
this.actor.backgroundColor = this._buttonColor;
|
||||||
},
|
else
|
||||||
|
this.actor.backgroundColor = null;
|
||||||
release : function() {
|
|
||||||
if (!this._isBetweenPressAndRelease && this._staysPressed) {
|
|
||||||
this._active = false;
|
|
||||||
if (this._mouseIsOverButton) {
|
|
||||||
this.button.backgroundColor = this._buttonColor;
|
|
||||||
} else {
|
|
||||||
this.button.backgroundColor = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -141,11 +91,11 @@ const ANIMATION_TIME = 0.25;
|
|||||||
* size -- size in pixels of both the button and the icon it contains
|
* size -- size in pixels of both the button and the icon it contains
|
||||||
* texture -- optional, must be used if the texture for the icon is already created (else, use setIconFromName)
|
* texture -- optional, must be used if the texture for the icon is already created (else, use setIconFromName)
|
||||||
*/
|
*/
|
||||||
function iconButton(parent, size, texture) {
|
function IconButton(parent, size, texture) {
|
||||||
this._init(parent, size, texture);
|
this._init(parent, size, texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
iconButton.prototype = {
|
IconButton.prototype = {
|
||||||
_init : function(parent, size, texture) {
|
_init : function(parent, size, texture) {
|
||||||
this._size = size;
|
this._size = size;
|
||||||
if (texture)
|
if (texture)
|
||||||
@@ -156,16 +106,15 @@ iconButton.prototype = {
|
|||||||
this.actor.set_opacity(0);
|
this.actor.set_opacity(0);
|
||||||
parent.connect("enter-event", Lang.bind(this, function(actor, event) {
|
parent.connect("enter-event", Lang.bind(this, function(actor, event) {
|
||||||
this._shouldHide = false;
|
this._shouldHide = false;
|
||||||
|
|
||||||
// Nothing to do if the cursor has come back from a child of the parent actor
|
// Nothing to do if the cursor has come back from a child of the parent actor
|
||||||
if (actor.get_children().indexOf(Shell.get_event_related(event)) != -1)
|
if (actor.get_children().indexOf(event.get_related()) != -1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this._fadeIn();
|
this._fadeIn();
|
||||||
}));
|
}));
|
||||||
parent.connect("leave-event", Lang.bind(this, function(actor, event) {
|
parent.connect("leave-event", Lang.bind(this, function(actor, event) {
|
||||||
// Nothing to do if the cursor has merely entered a child of the parent actor
|
// Nothing to do if the cursor has merely entered a child of the parent actor
|
||||||
if (actor.get_children().indexOf(Shell.get_event_related(event)) != -1)
|
if (actor.get_children().indexOf(event.get_related()) != -1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Remember that we should not be visible to hide the button if forceShow is unset
|
// Remember that we should not be visible to hide the button if forceShow is unset
|
||||||
@@ -221,4 +170,3 @@ iconButton.prototype = {
|
|||||||
transition :"easeOutQuad" });
|
transition :"easeOutQuad" });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -18,8 +18,6 @@ function Chrome() {
|
|||||||
|
|
||||||
Chrome.prototype = {
|
Chrome.prototype = {
|
||||||
_init: function() {
|
_init: function() {
|
||||||
let global = Shell.Global.get();
|
|
||||||
|
|
||||||
// The group itself has zero size so it doesn't interfere with DND
|
// The group itself has zero size so it doesn't interfere with DND
|
||||||
this.actor = new Clutter.Group({ width: 0, height: 0 });
|
this.actor = new Clutter.Group({ width: 0, height: 0 });
|
||||||
global.stage.add_actor(this.actor);
|
global.stage.add_actor(this.actor);
|
||||||
@@ -238,7 +236,6 @@ Chrome.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
_windowsRestacked: function() {
|
_windowsRestacked: function() {
|
||||||
let global = Shell.Global.get();
|
|
||||||
let windows = global.get_windows();
|
let windows = global.get_windows();
|
||||||
|
|
||||||
// The chrome layer should be visible unless there is a window
|
// The chrome layer should be visible unless there is a window
|
||||||
@@ -280,7 +277,6 @@ Chrome.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
_updateRegions: function() {
|
_updateRegions: function() {
|
||||||
let global = Shell.Global.get();
|
|
||||||
let rects = [], struts = [], i;
|
let rects = [], struts = [], i;
|
||||||
|
|
||||||
delete this._updateRegionIdle;
|
delete this._updateRegionIdle;
|
||||||
|
|||||||
471
js/ui/dash.js
@@ -70,6 +70,34 @@ const PANE_BORDER_WIDTH = 2;
|
|||||||
const PANE_BACKGROUND_COLOR = new Clutter.Color();
|
const PANE_BACKGROUND_COLOR = new Clutter.Color();
|
||||||
PANE_BACKGROUND_COLOR.from_pixel(0x000000f4);
|
PANE_BACKGROUND_COLOR.from_pixel(0x000000f4);
|
||||||
|
|
||||||
|
const APPS = "apps";
|
||||||
|
const PREFS = "prefs";
|
||||||
|
const DOCS = "docs";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the index in an array of a given length that is obtained
|
||||||
|
* if the provided index is incremented by an increment and the array
|
||||||
|
* is wrapped in if necessary.
|
||||||
|
*
|
||||||
|
* index: prior index, expects 0 <= index < length
|
||||||
|
* increment: the change in index, expects abs(increment) <= length
|
||||||
|
* length: the length of the array
|
||||||
|
*/
|
||||||
|
function _getIndexWrapped(index, increment, length) {
|
||||||
|
return (index + increment + length) % length;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _createDisplay(displayType) {
|
||||||
|
if (displayType == APPS)
|
||||||
|
return new AppDisplay.AppDisplay();
|
||||||
|
else if (displayType == PREFS)
|
||||||
|
return new AppDisplay.AppDisplay(true);
|
||||||
|
else if (displayType == DOCS)
|
||||||
|
return new DocDisplay.DocDisplay();
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
function Pane() {
|
function Pane() {
|
||||||
this._init();
|
this._init();
|
||||||
}
|
}
|
||||||
@@ -92,7 +120,6 @@ Pane.prototype = {
|
|||||||
let chromeTop = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
let chromeTop = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||||
spacing: 6 });
|
spacing: 6 });
|
||||||
|
|
||||||
let global = Shell.Global.get();
|
|
||||||
let closeIconUri = "file://" + global.imagedir + "close.svg";
|
let closeIconUri = "file://" + global.imagedir + "close.svg";
|
||||||
let closeIcon = Shell.TextureCache.get_default().load_uri_sync(Shell.TextureCachePolicy.FOREVER,
|
let closeIcon = Shell.TextureCache.get_default().load_uri_sync(Shell.TextureCachePolicy.FOREVER,
|
||||||
closeIconUri,
|
closeIconUri,
|
||||||
@@ -146,12 +173,12 @@ Pane.prototype = {
|
|||||||
}
|
}
|
||||||
Signals.addSignalMethods(Pane.prototype);
|
Signals.addSignalMethods(Pane.prototype);
|
||||||
|
|
||||||
function ResultArea(displayClass, enableNavigation) {
|
function ResultArea(displayType, enableNavigation) {
|
||||||
this._init(displayClass, enableNavigation);
|
this._init(displayType, enableNavigation);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultArea.prototype = {
|
ResultArea.prototype = {
|
||||||
_init : function(displayClass, enableNavigation) {
|
_init : function(displayType, enableNavigation) {
|
||||||
this.actor = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL });
|
this.actor = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL });
|
||||||
this.resultsContainer = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
this.resultsContainer = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||||
spacing: DEFAULT_PADDING
|
spacing: DEFAULT_PADDING
|
||||||
@@ -160,7 +187,7 @@ ResultArea.prototype = {
|
|||||||
this.navContainer = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL });
|
this.navContainer = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL });
|
||||||
this.resultsContainer.append(this.navContainer, Big.BoxPackFlags.NONE);
|
this.resultsContainer.append(this.navContainer, Big.BoxPackFlags.NONE);
|
||||||
|
|
||||||
this.display = new displayClass();
|
this.display = _createDisplay(displayType);
|
||||||
|
|
||||||
this.navArea = this.display.getNavigationArea();
|
this.navArea = this.display.getNavigationArea();
|
||||||
if (enableNavigation && this.navArea)
|
if (enableNavigation && this.navArea)
|
||||||
@@ -217,10 +244,10 @@ ResultPane.prototype = {
|
|||||||
this._dash = dash;
|
this._dash = dash;
|
||||||
},
|
},
|
||||||
|
|
||||||
// Create an instance of displayClass and pack it into this pane's
|
// Create a display of displayType and pack it into this pane's
|
||||||
// content area. Return the displayClass instance.
|
// content area. Return the display.
|
||||||
packResults: function(displayClass, enableNavigation) {
|
packResults: function(displayType, enableNavigation) {
|
||||||
let resultArea = new ResultArea(displayClass, enableNavigation);
|
let resultArea = new ResultArea(displayType, enableNavigation);
|
||||||
|
|
||||||
createPaneForDetails(this._dash, resultArea.display);
|
createPaneForDetails(this._dash, resultArea.display);
|
||||||
|
|
||||||
@@ -288,7 +315,6 @@ SearchEntry.prototype = {
|
|||||||
padding_right: 4 });
|
padding_right: 4 });
|
||||||
box.append(this._iconBox, Big.BoxPackFlags.END);
|
box.append(this._iconBox, Big.BoxPackFlags.END);
|
||||||
|
|
||||||
let global = Shell.Global.get();
|
|
||||||
let magnifierUri = "file://" + global.imagedir + "magnifier.svg";
|
let magnifierUri = "file://" + global.imagedir + "magnifier.svg";
|
||||||
this._magnifierIcon = Shell.TextureCache.get_default().load_uri_sync(Shell.TextureCachePolicy.FOREVER,
|
this._magnifierIcon = Shell.TextureCache.get_default().load_uri_sync(Shell.TextureCachePolicy.FOREVER,
|
||||||
magnifierUri, 18, 18);
|
magnifierUri, 18, 18);
|
||||||
@@ -371,7 +397,7 @@ MoreLink.prototype = {
|
|||||||
|
|
||||||
let text = new Clutter.Text({ font_name: "Sans 12px",
|
let text = new Clutter.Text({ font_name: "Sans 12px",
|
||||||
color: BRIGHT_TEXT_COLOR,
|
color: BRIGHT_TEXT_COLOR,
|
||||||
text: _("Browse") });
|
text: _("More") });
|
||||||
this.actor.append(text, Big.BoxPackFlags.NONE);
|
this.actor.append(text, Big.BoxPackFlags.NONE);
|
||||||
|
|
||||||
this.actor.connect('button-press-event', Lang.bind(this, function (b, e) {
|
this.actor.connect('button-press-event', Lang.bind(this, function (b, e) {
|
||||||
@@ -393,6 +419,30 @@ MoreLink.prototype = {
|
|||||||
|
|
||||||
Signals.addSignalMethods(MoreLink.prototype);
|
Signals.addSignalMethods(MoreLink.prototype);
|
||||||
|
|
||||||
|
function BackLink() {
|
||||||
|
this._init();
|
||||||
|
}
|
||||||
|
|
||||||
|
BackLink.prototype = {
|
||||||
|
_init : function () {
|
||||||
|
this.actor = new Shell.ButtonBox({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||||
|
padding_right: DEFAULT_PADDING,
|
||||||
|
padding_left: DEFAULT_PADDING,
|
||||||
|
reactive: true,
|
||||||
|
x_align: Big.BoxAlignment.CENTER,
|
||||||
|
y_align: Big.BoxAlignment.CENTER,
|
||||||
|
border_right: SECTION_BORDER,
|
||||||
|
border_color: SECTION_BORDER_COLOR });
|
||||||
|
|
||||||
|
let backIconUri = "file://" + global.imagedir + "back.svg";
|
||||||
|
let backIcon = Shell.TextureCache.get_default().load_uri_sync(Shell.TextureCachePolicy.FOREVER,
|
||||||
|
backIconUri,
|
||||||
|
12,
|
||||||
|
16);
|
||||||
|
this.actor.append(backIcon, Big.BoxPackFlags.NONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function SectionHeader(title, suppressBrowse) {
|
function SectionHeader(title, suppressBrowse) {
|
||||||
this._init(title, suppressBrowse);
|
this._init(title, suppressBrowse);
|
||||||
}
|
}
|
||||||
@@ -416,6 +466,14 @@ SectionHeader.prototype = {
|
|||||||
backgroundGradient.set_size(width, height);
|
backgroundGradient.set_size(width, height);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
this.backLink = new BackLink();
|
||||||
|
this._innerBox.append(this.backLink.actor, Big.BoxPackFlags.NONE);
|
||||||
|
this.backLink.actor.hide();
|
||||||
|
|
||||||
|
this.backLink.actor.connect('activate', Lang.bind(this, function (actor) {
|
||||||
|
this.emit('back-link-activated');
|
||||||
|
}));
|
||||||
|
|
||||||
let textBox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
let textBox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||||
padding_top: DEFAULT_PADDING,
|
padding_top: DEFAULT_PADDING,
|
||||||
padding_bottom: DEFAULT_PADDING });
|
padding_bottom: DEFAULT_PADDING });
|
||||||
@@ -424,15 +482,49 @@ SectionHeader.prototype = {
|
|||||||
text: title });
|
text: title });
|
||||||
textBox.append(this.text, Big.BoxPackFlags.NONE);
|
textBox.append(this.text, Big.BoxPackFlags.NONE);
|
||||||
|
|
||||||
|
this.countText = new Clutter.Text({ color: TEXT_COLOR,
|
||||||
|
font_name: 'Sans Bold 14px' });
|
||||||
|
textBox.append(this.countText, Big.BoxPackFlags.END);
|
||||||
|
this.countText.hide();
|
||||||
|
|
||||||
this._innerBox.append(textBox, Big.BoxPackFlags.EXPAND);
|
this._innerBox.append(textBox, Big.BoxPackFlags.EXPAND);
|
||||||
|
|
||||||
if (!suppressBrowse) {
|
if (!suppressBrowse) {
|
||||||
this.moreLink = new MoreLink();
|
this.moreLink = new MoreLink();
|
||||||
this._innerBox.append(this.moreLink.actor, Big.BoxPackFlags.END);
|
this._innerBox.append(this.moreLink.actor, Big.BoxPackFlags.END);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
setTitle : function(title) {
|
||||||
|
this.text.text = title;
|
||||||
|
},
|
||||||
|
|
||||||
|
setBackLinkVisible : function(visible) {
|
||||||
|
if (visible)
|
||||||
|
this.backLink.actor.show();
|
||||||
|
else
|
||||||
|
this.backLink.actor.hide();
|
||||||
|
},
|
||||||
|
|
||||||
|
setMoreLinkVisible : function(visible) {
|
||||||
|
if (visible)
|
||||||
|
this.moreLink.actor.show();
|
||||||
|
else
|
||||||
|
this.moreLink.actor.hide();
|
||||||
|
},
|
||||||
|
|
||||||
|
setCountText : function(countText) {
|
||||||
|
if (countText == "") {
|
||||||
|
this.countText.hide();
|
||||||
|
} else {
|
||||||
|
this.countText.show();
|
||||||
|
this.countText.text = countText;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Signals.addSignalMethods(SectionHeader.prototype);
|
||||||
|
|
||||||
function SearchSectionHeader(title, onClick) {
|
function SearchSectionHeader(title, onClick) {
|
||||||
this._init(title, onClick);
|
this._init(title, onClick);
|
||||||
}
|
}
|
||||||
@@ -457,37 +549,22 @@ SearchSectionHeader.prototype = {
|
|||||||
box.append(this.countText, Big.BoxPackFlags.END);
|
box.append(this.countText, Big.BoxPackFlags.END);
|
||||||
|
|
||||||
this.tooltip.hide();
|
this.tooltip.hide();
|
||||||
this._showTooltip = true;
|
|
||||||
|
|
||||||
let button = new Button.Button(box, PRELIGHT_COLOR, BACKGROUND_COLOR,
|
let button = new Button.Button(box, PRELIGHT_COLOR, BACKGROUND_COLOR,
|
||||||
TEXT_COLOR, false, null);
|
TEXT_COLOR);
|
||||||
button.button.height = box.height;
|
button.actor.height = box.height;
|
||||||
button.button.padding_left = DEFAULT_PADDING;
|
button.actor.padding_left = DEFAULT_PADDING;
|
||||||
button.button.padding_right = DEFAULT_PADDING;
|
button.actor.padding_right = DEFAULT_PADDING;
|
||||||
|
|
||||||
button.button.connect('button-release-event', onClick);
|
button.actor.connect('activate', onClick);
|
||||||
button.connect('enter-event', Lang.bind(this, this._onButtonEntered));
|
button.actor.connect('notify::hover', Lang.bind(this, this._updateTooltip));
|
||||||
button.connect('leave-event', Lang.bind(this, this._onButtonLeft));
|
this.actor = button.actor;
|
||||||
this.actor = button.button;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_onButtonEntered : function() {
|
_updateTooltip : function(actor) {
|
||||||
if (this._showTooltip)
|
if (actor.hover)
|
||||||
this.tooltip.show();
|
this.tooltip.show();
|
||||||
},
|
else
|
||||||
|
|
||||||
_onButtonLeft : function() {
|
|
||||||
this.tooltip.hide();
|
|
||||||
},
|
|
||||||
|
|
||||||
setShowTooltip : function(showTooltip) {
|
|
||||||
this._showTooltip = showTooltip;
|
|
||||||
// Because we only show tooltip on mouse-over,
|
|
||||||
// we should not just show it here if showTooltip is
|
|
||||||
// set to true, but in the future we could check if
|
|
||||||
// the mouse happens to be over the header and show it
|
|
||||||
// in that case.
|
|
||||||
if (!this._showTooltip)
|
|
||||||
this.tooltip.hide();
|
this.tooltip.hide();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -512,8 +589,6 @@ function Dash() {
|
|||||||
|
|
||||||
Dash.prototype = {
|
Dash.prototype = {
|
||||||
_init : function() {
|
_init : function() {
|
||||||
let global = Shell.Global.get();
|
|
||||||
|
|
||||||
// dash and the popup panes need to be reactive so that the clicks in unoccupied places on them
|
// dash and the popup panes need to be reactive so that the clicks in unoccupied places on them
|
||||||
// are not passed to the transparent background underneath them. This background is used for the workspaces area when
|
// are not passed to the transparent background underneath them. This background is used for the workspaces area when
|
||||||
// the additional dash panes are being shown and it handles clicks by closing the additional panes, so that the user
|
// the additional dash panes are being shown and it handles clicks by closing the additional panes, so that the user
|
||||||
@@ -545,6 +620,7 @@ Dash.prototype = {
|
|||||||
/***** Search *****/
|
/***** Search *****/
|
||||||
|
|
||||||
this._searchActive = false;
|
this._searchActive = false;
|
||||||
|
this._searchPending = false;
|
||||||
this._searchEntry = new SearchEntry();
|
this._searchEntry = new SearchEntry();
|
||||||
this.searchArea.append(this._searchEntry.actor, Big.BoxPackFlags.EXPAND);
|
this.searchArea.append(this._searchEntry.actor, Big.BoxPackFlags.EXPAND);
|
||||||
|
|
||||||
@@ -552,7 +628,9 @@ Dash.prototype = {
|
|||||||
this._searchEntry.entry.connect('text-changed', Lang.bind(this, function (se, prop) {
|
this._searchEntry.entry.connect('text-changed', Lang.bind(this, function (se, prop) {
|
||||||
let text = this._searchEntry.getText();
|
let text = this._searchEntry.getText();
|
||||||
text = text.replace(/^\s+/g, "").replace(/\s+$/g, "")
|
text = text.replace(/^\s+/g, "").replace(/\s+$/g, "")
|
||||||
|
let searchPreviouslyActive = this._searchActive;
|
||||||
this._searchActive = text != '';
|
this._searchActive = text != '';
|
||||||
|
this._searchPending = this._searchActive && !searchPreviouslyActive;
|
||||||
this._updateDashActors();
|
this._updateDashActors();
|
||||||
if (!this._searchActive) {
|
if (!this._searchActive) {
|
||||||
if (this._searchTimeoutId > 0) {
|
if (this._searchTimeoutId > 0) {
|
||||||
@@ -567,29 +645,62 @@ Dash.prototype = {
|
|||||||
this._searchTimeoutId = 0;
|
this._searchTimeoutId = 0;
|
||||||
let text = this._searchEntry.getText();
|
let text = this._searchEntry.getText();
|
||||||
text = text.replace(/^\s+/g, "").replace(/\s+$/g, "");
|
text = text.replace(/^\s+/g, "").replace(/\s+$/g, "");
|
||||||
this._appSearchResultArea.display.setSearch(text);
|
|
||||||
this._docSearchResultArea.display.setSearch(text);
|
|
||||||
|
|
||||||
this._appSearchHeader.countText.text = this._appSearchResultArea.display.getMatchedItemsCount() + "";
|
let selectionSet = false;
|
||||||
this._docSearchHeader.countText.text = this._docSearchResultArea.display.getMatchedItemsCount() + "";
|
|
||||||
|
for (var i = 0; i < this._searchSections.length; i++) {
|
||||||
|
let section = this._searchSections[i];
|
||||||
|
section.resultArea.display.setSearch(text);
|
||||||
|
let itemCount = section.resultArea.display.getMatchedItemsCount();
|
||||||
|
let itemCountText = itemCount + "";
|
||||||
|
section.header.countText.text = itemCountText;
|
||||||
|
|
||||||
|
if (this._searchResultsSingleShownSection == section.type) {
|
||||||
|
this._searchResultsSection.header.setCountText(itemCountText);
|
||||||
|
if (itemCount == 0) {
|
||||||
|
section.resultArea.actor.hide();
|
||||||
|
} else {
|
||||||
|
section.resultArea.actor.show();
|
||||||
|
}
|
||||||
|
} else if (this._searchResultsSingleShownSection == null) {
|
||||||
|
// Don't show the section if it has no results
|
||||||
|
if (itemCount == 0) {
|
||||||
|
section.header.actor.hide();
|
||||||
|
section.resultArea.actor.hide();
|
||||||
|
} else {
|
||||||
|
section.header.actor.show();
|
||||||
|
section.resultArea.actor.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Refresh the selection when a new search is applied.
|
||||||
|
section.resultArea.display.unsetSelected();
|
||||||
|
if (!selectionSet && section.resultArea.display.hasItems() &&
|
||||||
|
(this._searchResultsSingleShownSection == null || this._searchResultsSingleShownSection == section.type)) {
|
||||||
|
section.resultArea.display.selectFirstItem();
|
||||||
|
selectionSet = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}));
|
}));
|
||||||
}));
|
}));
|
||||||
this._searchEntry.entry.connect('activate', Lang.bind(this, function (se) {
|
this._searchEntry.entry.connect('activate', Lang.bind(this, function (se) {
|
||||||
// only one of the displays will have an item selected, so it's ok to
|
// Only one of the displays will have an item selected, so it's ok to
|
||||||
// call activateSelected() on all of them
|
// call activateSelected() on all of them.
|
||||||
this._appSearchResultArea.display.activateSelected();
|
for (var i = 0; i < this._searchSections.length; i++) {
|
||||||
this._docSearchResultArea.display.activateSelected();
|
let section = this._searchSections[i];
|
||||||
|
section.resultArea.display.activateSelected();
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}));
|
}));
|
||||||
this._searchEntry.entry.connect('key-press-event', Lang.bind(this, function (se, e) {
|
this._searchEntry.entry.connect('key-press-event', Lang.bind(this, function (se, e) {
|
||||||
let text = this._searchEntry.getText();
|
let text = this._searchEntry.getText();
|
||||||
let symbol = Shell.get_event_key_symbol(e);
|
let symbol = e.get_key_symbol();
|
||||||
if (symbol == Clutter.Escape) {
|
if (symbol == Clutter.Escape) {
|
||||||
// Escape will keep clearing things back to the desktop.
|
// Escape will keep clearing things back to the desktop.
|
||||||
// If we are showing a particular section of search, go back to all sections.
|
// If we are showing a particular section of search, go back to all sections.
|
||||||
if (this._getOnlyAppSearchShown() || this._getOnlyDocSearchShown())
|
if (this._searchResultsSingleShownSection != null)
|
||||||
this._showAllSearchSections();
|
this._showAllSearchSections();
|
||||||
// If we have an active search, we remove it.
|
// If we have an active search, we remove it.
|
||||||
else if (this._searchActive)
|
else if (this._searchActive)
|
||||||
@@ -608,22 +719,40 @@ Dash.prototype = {
|
|||||||
// too, but there doesn't seem to be any flickering if we first select
|
// too, but there doesn't seem to be any flickering if we first select
|
||||||
// something in one display, but then unset the selection, and move
|
// something in one display, but then unset the selection, and move
|
||||||
// it to the other display, so it's ok to do that.
|
// it to the other display, so it's ok to do that.
|
||||||
if (this._docSearchResultArea.display.hasSelected())
|
for (var i = 0; i < this._searchSections.length; i++) {
|
||||||
this._docSearchResultArea.display.selectUp();
|
let section = this._searchSections[i];
|
||||||
else if (this._appSearchResultArea.display.hasItems())
|
if (section.resultArea.display.hasSelected() && !section.resultArea.display.selectUp()) {
|
||||||
this._appSearchResultArea.display.selectUp();
|
if (this._searchResultsSingleShownSection != section.type) {
|
||||||
else
|
// We need to move the selection to the next section above this section that has items,
|
||||||
this._docSearchResultArea.display.selectUp();
|
// wrapping around at the bottom, if necessary.
|
||||||
|
let newSectionIndex = this._findAnotherSectionWithItems(i, -1);
|
||||||
|
if (newSectionIndex >= 0) {
|
||||||
|
this._searchSections[newSectionIndex].resultArea.display.selectLastItem();
|
||||||
|
section.resultArea.display.unsetSelected();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
} else if (symbol == Clutter.Down) {
|
} else if (symbol == Clutter.Down) {
|
||||||
if (!this._searchActive)
|
if (!this._searchActive)
|
||||||
return true;
|
return true;
|
||||||
if (this._docSearchResultArea.display.hasSelected())
|
for (var i = 0; i < this._searchSections.length; i++) {
|
||||||
this._docSearchResultArea.display.selectDown();
|
let section = this._searchSections[i];
|
||||||
else if (this._appSearchResultArea.display.hasItems())
|
if (section.resultArea.display.hasSelected() && !section.resultArea.display.selectDown()) {
|
||||||
this._appSearchResultArea.display.selectDown();
|
if (this._searchResultsSingleShownSection != section.type) {
|
||||||
else
|
// We need to move the selection to the next section below this section that has items,
|
||||||
this._docSearchResultArea.display.selectDown();
|
// wrapping around at the top, if necessary.
|
||||||
|
let newSectionIndex = this._findAnotherSectionWithItems(i, 1);
|
||||||
|
if (newSectionIndex >= 0) {
|
||||||
|
this._searchSections[newSectionIndex].resultArea.display.selectFirstItem();
|
||||||
|
section.resultArea.display.unsetSelected();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -639,7 +768,7 @@ Dash.prototype = {
|
|||||||
this._appsSection.header.moreLink.connect('activated', Lang.bind(this, function (link) {
|
this._appsSection.header.moreLink.connect('activated', Lang.bind(this, function (link) {
|
||||||
if (this._moreAppsPane == null) {
|
if (this._moreAppsPane == null) {
|
||||||
this._moreAppsPane = new ResultPane(this);
|
this._moreAppsPane = new ResultPane(this);
|
||||||
this._moreAppsPane.packResults(AppDisplay.AppDisplay, true);
|
this._moreAppsPane.packResults(APPS, true);
|
||||||
this._addPane(this._moreAppsPane);
|
this._addPane(this._moreAppsPane);
|
||||||
link.setPane(this._moreAppsPane);
|
link.setPane(this._moreAppsPane);
|
||||||
}
|
}
|
||||||
@@ -660,55 +789,74 @@ Dash.prototype = {
|
|||||||
|
|
||||||
this._docsSection = new Section(_("RECENT DOCUMENTS"));
|
this._docsSection = new Section(_("RECENT DOCUMENTS"));
|
||||||
|
|
||||||
let docDisplay = new DocDisplay.DashDocDisplay();
|
this._docDisplay = new DocDisplay.DashDocDisplay();
|
||||||
this._docsSection.content.append(docDisplay.actor, Big.BoxPackFlags.EXPAND);
|
this._docsSection.content.append(this._docDisplay.actor, Big.BoxPackFlags.EXPAND);
|
||||||
|
|
||||||
this._moreDocsPane = null;
|
this._moreDocsPane = null;
|
||||||
this._docsSection.header.moreLink.connect('activated', Lang.bind(this, function (link) {
|
this._docsSection.header.moreLink.connect('activated', Lang.bind(this, function (link) {
|
||||||
if (this._moreDocsPane == null) {
|
if (this._moreDocsPane == null) {
|
||||||
this._moreDocsPane = new ResultPane(this);
|
this._moreDocsPane = new ResultPane(this);
|
||||||
this._moreDocsPane.packResults(DocDisplay.DocDisplay, true);
|
this._moreDocsPane.packResults(DOCS, true);
|
||||||
this._addPane(this._moreDocsPane);
|
this._addPane(this._moreDocsPane);
|
||||||
link.setPane(this._moreDocsPane);
|
link.setPane(this._moreDocsPane);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
this._docDisplay.connect('changed', Lang.bind(this, function () {
|
||||||
|
this._docsSection.header.setMoreLinkVisible(
|
||||||
|
this._docDisplay.actor.get_children().length > 0);
|
||||||
|
}));
|
||||||
|
this._docDisplay.emit('changed');
|
||||||
|
|
||||||
this.sectionArea.append(this._docsSection.actor, Big.BoxPackFlags.EXPAND);
|
this.sectionArea.append(this._docsSection.actor, Big.BoxPackFlags.EXPAND);
|
||||||
|
|
||||||
/***** Search Results *****/
|
/***** Search Results *****/
|
||||||
|
|
||||||
this._searchResultsSection = new Section(_("SEARCH RESULTS"), true);
|
this._searchResultsSection = new Section(_("SEARCH RESULTS"), true);
|
||||||
|
|
||||||
this._appSearchHeader = new SearchSectionHeader(_("APPLICATIONS"),
|
this._searchResultsSingleShownSection = null;
|
||||||
Lang.bind(this,
|
|
||||||
function () {
|
|
||||||
this._toggleOnlyAppSearchShown();
|
|
||||||
return true;
|
|
||||||
}));
|
|
||||||
this._searchResultsSection.content.append(this._appSearchHeader.actor, Big.BoxPackFlags.NONE);
|
|
||||||
this._appSearchResultArea = new ResultArea(AppDisplay.AppDisplay, false);
|
|
||||||
this._appSearchResultArea.controlBox.hide();
|
|
||||||
this._searchResultsSection.content.append(this._appSearchResultArea.actor, Big.BoxPackFlags.EXPAND);
|
|
||||||
createPaneForDetails(this, this._appSearchResultArea.display);
|
|
||||||
|
|
||||||
this._docSearchHeader = new SearchSectionHeader(_("RECENT DOCUMENTS"),
|
this._searchResultsSection.header.connect('back-link-activated', Lang.bind(this, function () {
|
||||||
Lang.bind(this,
|
this._showAllSearchSections();
|
||||||
function () {
|
}));
|
||||||
this._toggleOnlyDocSearchShown();
|
|
||||||
return true;
|
this._searchSections = [
|
||||||
}));
|
{ type: APPS,
|
||||||
this._searchResultsSection.content.append(this._docSearchHeader.actor, Big.BoxPackFlags.NONE);
|
title: _("APPLICATIONS"),
|
||||||
this._docSearchResultArea = new ResultArea(DocDisplay.DocDisplay, false);
|
header: null,
|
||||||
this._docSearchResultArea.controlBox.hide();
|
resultArea: null
|
||||||
this._searchResultsSection.content.append(this._docSearchResultArea.actor, Big.BoxPackFlags.EXPAND);
|
},
|
||||||
createPaneForDetails(this, this._docSearchResultArea.display);
|
{ type: PREFS,
|
||||||
|
title: _("PREFERENCES"),
|
||||||
|
header: null,
|
||||||
|
resultArea: null
|
||||||
|
},
|
||||||
|
{ type: DOCS,
|
||||||
|
title: _("RECENT DOCUMENTS"),
|
||||||
|
header: null,
|
||||||
|
resultArea: null
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
for (var i = 0; i < this._searchSections.length; i++) {
|
||||||
|
let section = this._searchSections[i];
|
||||||
|
section.header = new SearchSectionHeader(section.title,
|
||||||
|
Lang.bind(this,
|
||||||
|
function () {
|
||||||
|
this._showSingleSearchSection(section.type);
|
||||||
|
}));
|
||||||
|
this._searchResultsSection.content.append(section.header.actor, Big.BoxPackFlags.NONE);
|
||||||
|
section.resultArea = new ResultArea(section.type, false);
|
||||||
|
section.resultArea.controlBox.hide();
|
||||||
|
this._searchResultsSection.content.append(section.resultArea.actor, Big.BoxPackFlags.EXPAND);
|
||||||
|
createPaneForDetails(this, section.resultArea.display);
|
||||||
|
}
|
||||||
|
|
||||||
this.sectionArea.append(this._searchResultsSection.actor, Big.BoxPackFlags.EXPAND);
|
this.sectionArea.append(this._searchResultsSection.actor, Big.BoxPackFlags.EXPAND);
|
||||||
this._searchResultsSection.actor.hide();
|
this._searchResultsSection.actor.hide();
|
||||||
},
|
},
|
||||||
|
|
||||||
show: function() {
|
show: function() {
|
||||||
let global = Shell.Global.get();
|
|
||||||
global.stage.set_key_focus(this._searchEntry.entry);
|
global.stage.set_key_focus(this._searchEntry.entry);
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -739,81 +887,104 @@ Dash.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
_updateDashActors: function() {
|
_updateDashActors: function() {
|
||||||
if (!this._searchActive && this._searchResultsSection.actor.visible) {
|
if (this._searchPending) {
|
||||||
|
this._searchResultsSection.actor.show();
|
||||||
|
for (let i = 0; i < this._searchSections.length; i++) {
|
||||||
|
let section = this._searchSections[i];
|
||||||
|
section.header.actor.hide();
|
||||||
|
section.resultArea.actor.hide();
|
||||||
|
}
|
||||||
|
this._appsSection.actor.hide();
|
||||||
|
this._placesSection.actor.hide();
|
||||||
|
this._docsSection.actor.hide();
|
||||||
|
} else if (this._searchActive) {
|
||||||
|
for (let i = 0; i < this._searchSections.length; i++) {
|
||||||
|
let section = this._searchSections[i];
|
||||||
|
section.header.actor.show();
|
||||||
|
section.resultArea.actor.show();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
this._showAllSearchSections();
|
this._showAllSearchSections();
|
||||||
this._searchResultsSection.actor.hide();
|
this._searchResultsSection.actor.hide();
|
||||||
this._appsSection.actor.show();
|
this._appsSection.actor.show();
|
||||||
this._placesSection.actor.show();
|
this._placesSection.actor.show();
|
||||||
this._docsSection.actor.show();
|
this._docsSection.actor.show();
|
||||||
} else if (this._searchActive && !this._searchResultsSection.actor.visible) {
|
|
||||||
this._searchResultsSection.actor.show();
|
|
||||||
this._appsSection.actor.hide();
|
|
||||||
this._placesSection.actor.hide();
|
|
||||||
this._docsSection.actor.hide();
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_toggleOnlyAppSearchShown: function() {
|
_showSingleSearchSection: function(type) {
|
||||||
if (this._getOnlyAppSearchShown()) {
|
// We currently don't allow going from showing one section to showing another section.
|
||||||
this._setDocSearchShown(true);
|
if (this._searchResultsSingleShownSection != null) {
|
||||||
} else {
|
throw new Error("We were already showing a single search section: '" + this._searchResultsSingleShownSection
|
||||||
this._setDocSearchShown(false);
|
+ "' when _showSingleSearchSection() was called for '" + type + "'");
|
||||||
}
|
}
|
||||||
},
|
for (var i = 0; i < this._searchSections.length; i++) {
|
||||||
|
let section = this._searchSections[i];
|
||||||
_toggleOnlyDocSearchShown: function() {
|
if (section.type == type) {
|
||||||
if (this._getOnlyDocSearchShown()) {
|
// This will be the only section shown.
|
||||||
this._setAppSearchShown(true);
|
section.resultArea.display.selectFirstItem();
|
||||||
} else {
|
section.resultArea.controlBox.show();
|
||||||
this._setAppSearchShown(false);
|
let itemCount = section.resultArea.display.getMatchedItemsCount();
|
||||||
|
let itemCountText = itemCount + "";
|
||||||
|
section.header.actor.hide();
|
||||||
|
this._searchResultsSection.header.setTitle(section.title);
|
||||||
|
this._searchResultsSection.header.setBackLinkVisible(true);
|
||||||
|
this._searchResultsSection.header.setCountText(itemCountText);
|
||||||
|
} else {
|
||||||
|
// We need to hide this section.
|
||||||
|
section.header.actor.hide();
|
||||||
|
section.resultArea.actor.hide();
|
||||||
|
section.resultArea.display.unsetSelected();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
this._searchResultsSingleShownSection = type;
|
||||||
|
|
||||||
// TODO: the following two functions currently rely on us showing the
|
|
||||||
// section header even if there are no results in that section. We'll need
|
|
||||||
// to change the check if we update that behavior. We'll also need to change
|
|
||||||
// the check if we add more sections to search results.
|
|
||||||
_getOnlyAppSearchShown: function() {
|
|
||||||
return this._searchActive && !this._docSearchHeader.actor.visible;
|
|
||||||
},
|
|
||||||
|
|
||||||
_getOnlyDocSearchShown: function() {
|
|
||||||
return this._searchActive && !this._appSearchHeader.actor.visible;
|
|
||||||
},
|
|
||||||
|
|
||||||
_setAppSearchShown: function(show) {
|
|
||||||
if (show) {
|
|
||||||
this._appSearchHeader.actor.show();
|
|
||||||
this._appSearchResultArea.actor.show();
|
|
||||||
this._docSearchResultArea.display.displayPage(0);
|
|
||||||
this._docSearchResultArea.controlBox.hide();
|
|
||||||
this._docSearchHeader.setShowTooltip(true);
|
|
||||||
} else {
|
|
||||||
this._appSearchHeader.actor.hide();
|
|
||||||
this._appSearchResultArea.actor.hide();
|
|
||||||
this._docSearchResultArea.controlBox.show();
|
|
||||||
this._docSearchHeader.setShowTooltip(false);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_setDocSearchShown: function(show) {
|
|
||||||
if (show) {
|
|
||||||
this._docSearchHeader.actor.show();
|
|
||||||
this._docSearchResultArea.actor.show();
|
|
||||||
this._appSearchResultArea.display.displayPage(0);
|
|
||||||
this._appSearchResultArea.controlBox.hide();
|
|
||||||
this._appSearchHeader.setShowTooltip(true);
|
|
||||||
} else {
|
|
||||||
this._docSearchHeader.actor.hide();
|
|
||||||
this._docSearchResultArea.actor.hide();
|
|
||||||
this._appSearchResultArea.controlBox.show();
|
|
||||||
this._appSearchHeader.setShowTooltip(false);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_showAllSearchSections: function() {
|
_showAllSearchSections: function() {
|
||||||
this._setAppSearchShown(true);
|
if (this._searchResultsSingleShownSection != null) {
|
||||||
this._setDocSearchShown(true);
|
let selectionSet = false;
|
||||||
|
for (var i = 0; i < this._searchSections.length; i++) {
|
||||||
|
let section = this._searchSections[i];
|
||||||
|
if (section.type == this._searchResultsSingleShownSection) {
|
||||||
|
// This will no longer be the only section shown.
|
||||||
|
section.resultArea.display.displayPage(0);
|
||||||
|
section.resultArea.controlBox.hide();
|
||||||
|
let itemCount = section.resultArea.display.getMatchedItemsCount();
|
||||||
|
if (itemCount != 0) {
|
||||||
|
section.header.actor.show();
|
||||||
|
section.resultArea.display.selectFirstItem();
|
||||||
|
selectionSet = true;
|
||||||
|
}
|
||||||
|
this._searchResultsSection.header.setTitle(_("SEARCH RESULTS"));
|
||||||
|
this._searchResultsSection.header.setBackLinkVisible(false);
|
||||||
|
this._searchResultsSection.header.setCountText("");
|
||||||
|
} else {
|
||||||
|
// We need to restore this section.
|
||||||
|
let itemCount = section.resultArea.display.getMatchedItemsCount();
|
||||||
|
if (itemCount != 0) {
|
||||||
|
section.header.actor.show();
|
||||||
|
section.resultArea.actor.show();
|
||||||
|
// This ensures that some other section will have the selection if the
|
||||||
|
// single section that was being displayed did not have any items.
|
||||||
|
if (!selectionSet) {
|
||||||
|
section.resultArea.display.selectFirstItem();
|
||||||
|
selectionSet = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this._searchResultsSingleShownSection = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_findAnotherSectionWithItems: function(index, increment) {
|
||||||
|
let pos = _getIndexWrapped(index, increment, this._searchSections.length);
|
||||||
|
while (pos != index) {
|
||||||
|
if (this._searchSections[pos].resultArea.display.hasItems())
|
||||||
|
return pos;
|
||||||
|
pos = _getIndexWrapped(pos, increment, this._searchSections.length);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Signals.addSignalMethods(Dash.prototype);
|
Signals.addSignalMethods(Dash.prototype);
|
||||||
|
|||||||
327
js/ui/dnd.js
@@ -8,15 +8,40 @@ const Tweener = imports.ui.tweener;
|
|||||||
|
|
||||||
const SNAP_BACK_ANIMATION_TIME = 0.25;
|
const SNAP_BACK_ANIMATION_TIME = 0.25;
|
||||||
|
|
||||||
function _Draggable(actor) {
|
let eventHandlerActor = null;
|
||||||
this._init(actor);
|
let currentDraggable = null;
|
||||||
|
|
||||||
|
function _getEventHandlerActor() {
|
||||||
|
if (!eventHandlerActor) {
|
||||||
|
eventHandlerActor = new Clutter.Rectangle();
|
||||||
|
eventHandlerActor.width = 0;
|
||||||
|
eventHandlerActor.height = 0;
|
||||||
|
global.stage.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',
|
||||||
|
function(actor, event) {
|
||||||
|
return currentDraggable._onEvent(actor, event);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return eventHandlerActor;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _Draggable(actor, manualMode) {
|
||||||
|
this._init(actor, manualMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
_Draggable.prototype = {
|
_Draggable.prototype = {
|
||||||
_init : function(actor) {
|
_init : function(actor, manualMode) {
|
||||||
this.actor = actor;
|
this.actor = actor;
|
||||||
this.actor.connect('button-press-event',
|
if (!manualMode)
|
||||||
Lang.bind(this, this._onButtonPress));
|
this.actor.connect('button-press-event',
|
||||||
|
Lang.bind(this, this._onButtonPress));
|
||||||
|
this._onEventId = null;
|
||||||
|
|
||||||
|
this._buttonDown = false; // The mouse button has been pressed and has not yet been released.
|
||||||
|
this._dragInProgress = false; // The drag has been started, and has not been dropped or cancelled yet.
|
||||||
|
this._snapBackInProgress = false; // The drag has been cancelled and the item is in the process of snapping back.
|
||||||
},
|
},
|
||||||
|
|
||||||
_onButtonPress : function (actor, event) {
|
_onButtonPress : function (actor, event) {
|
||||||
@@ -25,7 +50,8 @@ _Draggable.prototype = {
|
|||||||
if (Tweener.getTweenCount(actor))
|
if (Tweener.getTweenCount(actor))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
this._grabActor(actor);
|
this._buttonDown = true;
|
||||||
|
this._grabActor();
|
||||||
|
|
||||||
let [stageX, stageY] = event.get_coords();
|
let [stageX, stageY] = event.get_coords();
|
||||||
this._dragStartX = stageX;
|
this._dragStartX = stageX;
|
||||||
@@ -34,108 +60,168 @@ _Draggable.prototype = {
|
|||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
_grabActor : function (actor) {
|
_grabActor: function() {
|
||||||
Clutter.grab_pointer(actor);
|
Clutter.grab_pointer(this.actor);
|
||||||
|
this._onEventId = this.actor.connect('event',
|
||||||
// We intercept motion and button-release events so that when
|
Lang.bind(this, this._onEvent));
|
||||||
// you release after dragging, the app doesn't see that and
|
|
||||||
// think you just clicked. We connect to 'event' rather than
|
|
||||||
// 'captured-event' because the capturing phase doesn't happen
|
|
||||||
// when you've grabbed the pointer.
|
|
||||||
this._onEventId = actor.connect('event',
|
|
||||||
Lang.bind(this, this._onEvent));
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_ungrabActor : function (actor) {
|
_ungrabActor: function() {
|
||||||
Clutter.ungrab_pointer();
|
Clutter.ungrab_pointer();
|
||||||
actor.disconnect(this._onEventId);
|
this.actor.disconnect(this._onEventId);
|
||||||
|
this._onEventId = null;
|
||||||
},
|
},
|
||||||
|
|
||||||
_onEvent : function (actor, event) {
|
_grabEvents: function() {
|
||||||
if (this._dragActor) {
|
Clutter.grab_pointer(_getEventHandlerActor());
|
||||||
if (actor != this._dragActor )
|
Clutter.grab_keyboard(_getEventHandlerActor());
|
||||||
|
},
|
||||||
|
|
||||||
|
_ungrabEvents: function() {
|
||||||
|
Clutter.ungrab_pointer();
|
||||||
|
Clutter.ungrab_keyboard();
|
||||||
|
},
|
||||||
|
|
||||||
|
_onEvent: function(actor, event) {
|
||||||
|
// We intercept BUTTON_RELEASE event to know that the button was released in case we
|
||||||
|
// didn't start the drag, to drop the draggable in case the drag was in progress, and
|
||||||
|
// to complete the drag and ensure that whatever happens to be under the pointer does
|
||||||
|
// not get triggered if the drag was cancelled with Esc.
|
||||||
|
if (event.type() == Clutter.EventType.BUTTON_RELEASE) {
|
||||||
|
this._buttonDown = false;
|
||||||
|
if (this._dragInProgress) {
|
||||||
|
return this._dragActorDropped(event);
|
||||||
|
} else if (this._dragActor != null && !this._snapBackInProgress) {
|
||||||
|
// Drag must have been cancelled with Esc.
|
||||||
|
this._dragComplete();
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
// Drag has never started.
|
||||||
|
this._ungrabActor();
|
||||||
return false;
|
return false;
|
||||||
} else if (actor != this.actor)
|
}
|
||||||
return false;
|
// 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
|
||||||
|
} else if (event.type() == Clutter.EventType.MOTION) {
|
||||||
|
if (this._dragInProgress) {
|
||||||
|
return this._updateDragPosition(event);
|
||||||
|
} else if (this._dragActor == null) {
|
||||||
|
return this._maybeStartDrag(event);
|
||||||
|
}
|
||||||
|
// We intercept KEY_PRESS event so that we can process Esc key press to cancel
|
||||||
|
// dragging and ignore all other key presses.
|
||||||
|
} else if (event.type() == Clutter.EventType.KEY_PRESS && this._dragInProgress) {
|
||||||
|
let symbol = event.get_key_symbol();
|
||||||
|
if (symbol == Clutter.Escape) {
|
||||||
|
this._cancelDrag(event.get_time());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (event.type() == Clutter.EventType.BUTTON_RELEASE)
|
return false;
|
||||||
return this._onButtonRelease(actor, event);
|
|
||||||
else if (event.type() == Clutter.EventType.MOTION)
|
|
||||||
return this._onMotion(actor, event);
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_onMotion : function (actor, event) {
|
/**
|
||||||
|
* startDrag:
|
||||||
|
* @stageX: X coordinate of event
|
||||||
|
* @stageY: Y coordinate of event
|
||||||
|
* @time: Event timestamp
|
||||||
|
*
|
||||||
|
* Directly initiate a drag and drop operation from the given actor.
|
||||||
|
* This function is useful to call if you've specified manualMode
|
||||||
|
* for the draggable.
|
||||||
|
*/
|
||||||
|
startDrag: function (stageX, stageY, time) {
|
||||||
|
currentDraggable = this;
|
||||||
|
this._dragInProgress = true;
|
||||||
|
|
||||||
|
this.emit('drag-begin', time);
|
||||||
|
if (this._onEventId)
|
||||||
|
this._ungrabActor();
|
||||||
|
this._grabEvents();
|
||||||
|
|
||||||
|
this._dragStartX = stageX;
|
||||||
|
this._dragStartY = stageY;
|
||||||
|
|
||||||
|
if (this.actor._delegate && this.actor._delegate.getDragActor) {
|
||||||
|
this._dragActor = this.actor._delegate.getDragActor(this._dragStartX, this._dragStartY);
|
||||||
|
// Drag actor does not always have to be the same as actor. For example drag actor
|
||||||
|
// can be an image that's part of the actor. So to perform "snap back" correctly we need
|
||||||
|
// to know what was the drag actor source.
|
||||||
|
if (this.actor._delegate.getDragActorSource) {
|
||||||
|
this._dragActorSource = this.actor._delegate.getDragActorSource();
|
||||||
|
// If the user dragged from the source, then position
|
||||||
|
// the dragActor over it. Otherwise, center it
|
||||||
|
// around the pointer
|
||||||
|
let [sourceX, sourceY] = this._dragActorSource.get_transformed_position();
|
||||||
|
let [sourceWidth, sourceHeight] = this._dragActorSource.get_transformed_size();
|
||||||
|
let x, y;
|
||||||
|
if (stageX > sourceX && stageX <= sourceX + sourceWidth &&
|
||||||
|
stageY > sourceY && stageY <= sourceY + sourceHeight) {
|
||||||
|
x = sourceX;
|
||||||
|
y = sourceY;
|
||||||
|
} else {
|
||||||
|
x = stageX - this._dragActor.width / 2;
|
||||||
|
y = stageY - this._dragActor.height / 2;
|
||||||
|
}
|
||||||
|
this._dragActor.set_position(x, y);
|
||||||
|
} else {
|
||||||
|
this._dragActorSource = this.actor;
|
||||||
|
}
|
||||||
|
this._dragOrigParent = undefined;
|
||||||
|
|
||||||
|
this._dragOffsetX = this._dragActor.x - this._dragStartX;
|
||||||
|
this._dragOffsetY = this._dragActor.y - this._dragStartY;
|
||||||
|
} else {
|
||||||
|
this._dragActor = this.actor;
|
||||||
|
this._dragActorSource = undefined;
|
||||||
|
this._dragOrigParent = this.actor.get_parent();
|
||||||
|
this._dragOrigX = this._dragActor.x;
|
||||||
|
this._dragOrigY = this._dragActor.y;
|
||||||
|
this._dragOrigScale = this._dragActor.scale_x;
|
||||||
|
|
||||||
|
let [actorStageX, actorStageY] = this.actor.get_transformed_position();
|
||||||
|
this._dragOffsetX = actorStageX - this._dragStartX;
|
||||||
|
this._dragOffsetY = actorStageY - this._dragStartY;
|
||||||
|
|
||||||
|
// Set the actor's scale such that it will keep the same
|
||||||
|
// transformed size when it's reparented to the stage
|
||||||
|
let [scaledWidth, scaledHeight] = this.actor.get_transformed_size();
|
||||||
|
this.actor.set_scale(scaledWidth / this.actor.width,
|
||||||
|
scaledHeight / this.actor.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._dragActor.reparent(this.actor.get_stage());
|
||||||
|
this._dragActor.raise_top();
|
||||||
|
},
|
||||||
|
|
||||||
|
_maybeStartDrag: function(event) {
|
||||||
let [stageX, stageY] = event.get_coords();
|
let [stageX, stageY] = event.get_coords();
|
||||||
|
|
||||||
// If we haven't begun a drag, see if the user has moved the
|
// See if the user has moved the mouse enough to trigger a drag
|
||||||
// mouse enough to trigger a drag
|
|
||||||
let threshold = Gtk.Settings.get_default().gtk_dnd_drag_threshold;
|
let threshold = Gtk.Settings.get_default().gtk_dnd_drag_threshold;
|
||||||
if (!this._dragActor &&
|
if ((Math.abs(stageX - this._dragStartX) > threshold ||
|
||||||
(Math.abs(stageX - this._dragStartX) > threshold ||
|
|
||||||
Math.abs(stageY - this._dragStartY) > threshold)) {
|
Math.abs(stageY - this._dragStartY) > threshold)) {
|
||||||
this.emit('drag-begin', event.get_time());
|
this.startDrag(stageX, stageY, event.get_time());
|
||||||
|
this._updateDragPosition(event);
|
||||||
if (this.actor._delegate && this.actor._delegate.getDragActor) {
|
|
||||||
this._dragActor = this.actor._delegate.getDragActor(this._dragStartX, this._dragStartY);
|
|
||||||
// Drag actor does not always have to be the same as actor. For example drag actor
|
|
||||||
// can be an image that's part of the actor. So to perform "snap back" correctly we need
|
|
||||||
// to know what was the drag actor source.
|
|
||||||
if (this.actor._delegate.getDragActorSource) {
|
|
||||||
this._dragActorSource = this.actor._delegate.getDragActorSource();
|
|
||||||
// If the user dragged from the source, then position
|
|
||||||
// the dragActor over it. Otherwise, center it
|
|
||||||
// around the pointer
|
|
||||||
let [sourceX, sourceY] = this._dragActorSource.get_transformed_position();
|
|
||||||
let [sourceWidth, sourceHeight] = this._dragActorSource.get_transformed_size();
|
|
||||||
if (stageX > sourceX && stageX <= sourceX + sourceWidth &&
|
|
||||||
stageY > sourceY && stageY <= sourceY + sourceHeight)
|
|
||||||
this._dragActor.set_position(sourceX, sourceY);
|
|
||||||
else
|
|
||||||
this._dragActor.set_position(stageX - this._dragActor.width / 2, stageY - this._dragActor.height / 2);
|
|
||||||
} else {
|
|
||||||
this._dragActorSource = this.actor;
|
|
||||||
}
|
|
||||||
this._dragOrigParent = undefined;
|
|
||||||
this._ungrabActor(actor);
|
|
||||||
this._grabActor(this._dragActor);
|
|
||||||
|
|
||||||
this._dragOffsetX = this._dragActor.x - this._dragStartX;
|
|
||||||
this._dragOffsetY = this._dragActor.y - this._dragStartY;
|
|
||||||
} else {
|
|
||||||
this._dragActor = actor;
|
|
||||||
this._dragActorSource = undefined;
|
|
||||||
this._dragOrigParent = actor.get_parent();
|
|
||||||
this._dragOrigX = this._dragActor.x;
|
|
||||||
this._dragOrigY = this._dragActor.y;
|
|
||||||
this._dragOrigScale = this._dragActor.scale_x;
|
|
||||||
|
|
||||||
let [actorStageX, actorStageY] = actor.get_transformed_position();
|
|
||||||
this._dragOffsetX = actorStageX - this._dragStartX;
|
|
||||||
this._dragOffsetY = actorStageY - this._dragStartY;
|
|
||||||
|
|
||||||
// Set the actor's scale such that it will keep the same
|
|
||||||
// transformed size when it's reparented to the stage
|
|
||||||
let [scaledWidth, scaledHeight] = actor.get_transformed_size();
|
|
||||||
actor.set_scale(scaledWidth / actor.width,
|
|
||||||
scaledHeight / actor.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
this._dragActor.reparent(actor.get_stage());
|
|
||||||
this._dragActor.raise_top();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
_updateDragPosition : function (event) {
|
||||||
|
let [stageX, stageY] = event.get_coords();
|
||||||
|
|
||||||
// If we are dragging, update the position
|
// If we are dragging, update the position
|
||||||
if (this._dragActor) {
|
if (this._dragActor) {
|
||||||
this._dragActor.set_position(stageX + this._dragOffsetX,
|
this._dragActor.set_position(stageX + this._dragOffsetX,
|
||||||
stageY + this._dragOffsetY);
|
stageY + this._dragOffsetY);
|
||||||
// Because we want to find out what other actor is located at the current position of this._dragActor,
|
// Because we want to find out what other actor is located at the current position of this._dragActor,
|
||||||
// we have to temporarily hide this._dragActor.
|
// we have to temporarily hide this._dragActor.
|
||||||
this._dragActor.hide();
|
this._dragActor.hide();
|
||||||
let target = actor.get_stage().get_actor_at_pos(Clutter.PickMode.ALL,
|
let target = this._dragActor.get_stage().get_actor_at_pos(Clutter.PickMode.ALL,
|
||||||
stageX + this._dragOffsetX,
|
stageX + this._dragOffsetX,
|
||||||
stageY + this._dragOffsetY);
|
stageY + this._dragOffsetY);
|
||||||
this._dragActor.show();
|
this._dragActor.show();
|
||||||
while (target) {
|
while (target) {
|
||||||
if (target._delegate && target._delegate.handleDragOver) {
|
if (target._delegate && target._delegate.handleDragOver) {
|
||||||
@@ -143,52 +229,54 @@ _Draggable.prototype = {
|
|||||||
// We currently loop through all parents on drag-over even if one of the children has handled it.
|
// We currently loop through all parents on drag-over even if one of the children has handled it.
|
||||||
// We can check the return value of the function and break the loop if it's true if we don't want
|
// We can check the return value of the function and break the loop if it's true if we don't want
|
||||||
// to continue checking the parents.
|
// to continue checking the parents.
|
||||||
target._delegate.handleDragOver(this.actor._delegate, actor,
|
target._delegate.handleDragOver(this.actor._delegate, this._dragActor,
|
||||||
(stageX + this._dragOffsetX - targX) / target.scale_x,
|
(stageX + this._dragOffsetX - targX) / target.scale_x,
|
||||||
(stageY + this._dragOffsetY - targY) / target.scale_y,
|
(stageY + this._dragOffsetY - targY) / target.scale_y,
|
||||||
event.get_time());
|
event.get_time());
|
||||||
}
|
}
|
||||||
target = target.get_parent();
|
target = target.get_parent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
_onButtonRelease : function (actor, event) {
|
_dragActorDropped: function(event) {
|
||||||
this._ungrabActor(actor);
|
// Find a drop target. Because we want to find out what other actor is located at
|
||||||
|
// the current position of this._dragActor, we have to temporarily hide this._dragActor.
|
||||||
let dragging = (actor == this._dragActor);
|
this._dragActor.hide();
|
||||||
this._dragActor = undefined;
|
|
||||||
|
|
||||||
if (!dragging)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Find a drop target
|
|
||||||
actor.hide();
|
|
||||||
let [dropX, dropY] = event.get_coords();
|
let [dropX, dropY] = event.get_coords();
|
||||||
let target = actor.get_stage().get_actor_at_pos(Clutter.PickMode.ALL,
|
let target = this._dragActor.get_stage().get_actor_at_pos(Clutter.PickMode.ALL,
|
||||||
dropX, dropY);
|
dropX, dropY);
|
||||||
actor.show();
|
this._dragActor.show();
|
||||||
while (target) {
|
while (target) {
|
||||||
if (target._delegate && target._delegate.acceptDrop) {
|
if (target._delegate && target._delegate.acceptDrop) {
|
||||||
let [targX, targY] = target.get_transformed_position();
|
let [targX, targY] = target.get_transformed_position();
|
||||||
if (target._delegate.acceptDrop(this.actor._delegate, actor,
|
if (target._delegate.acceptDrop(this.actor._delegate, this._dragActor,
|
||||||
(dropX - targX) / target.scale_x,
|
(dropX - targX) / target.scale_x,
|
||||||
(dropY - targY) / target.scale_y,
|
(dropY - targY) / target.scale_y,
|
||||||
event.get_time())) {
|
event.get_time())) {
|
||||||
// If it accepted the drop without taking the actor,
|
// If it accepted the drop without taking the actor,
|
||||||
// destroy it.
|
// destroy it.
|
||||||
if (actor.get_parent() == actor.get_stage())
|
if (this._dragActor.get_parent() == this._dragActor.get_stage())
|
||||||
actor.destroy();
|
this._dragActor.destroy();
|
||||||
|
|
||||||
|
this._dragInProgress = false;
|
||||||
this.emit('drag-end', event.get_time(), true);
|
this.emit('drag-end', event.get_time(), true);
|
||||||
|
this._dragComplete();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
target = target.get_parent();
|
target = target.get_parent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._cancelDrag(event.get_time());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
_cancelDrag: function(eventTime) {
|
||||||
|
this._dragInProgress = false;
|
||||||
// Snap back to the actor source if the source is still around, snap back
|
// Snap back to the actor source if the source is still around, snap back
|
||||||
// to the original location if the actor itself was being dragged or the
|
// to the original location if the actor itself was being dragged or the
|
||||||
// source is no longer around.
|
// source is no longer around.
|
||||||
@@ -198,17 +286,17 @@ _Draggable.prototype = {
|
|||||||
[snapBackX, snapBackY] = this._dragActorSource.get_transformed_position();
|
[snapBackX, snapBackY] = this._dragActorSource.get_transformed_position();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._snapBackInProgress = true;
|
||||||
// No target, so snap back
|
// No target, so snap back
|
||||||
Tweener.addTween(actor,
|
Tweener.addTween(this._dragActor,
|
||||||
{ x: snapBackX,
|
{ x: snapBackX,
|
||||||
y: snapBackY,
|
y: snapBackY,
|
||||||
time: SNAP_BACK_ANIMATION_TIME,
|
time: SNAP_BACK_ANIMATION_TIME,
|
||||||
transition: "easeOutQuad",
|
transition: "easeOutQuad",
|
||||||
onComplete: this._onSnapBackComplete,
|
onComplete: this._onSnapBackComplete,
|
||||||
onCompleteScope: this,
|
onCompleteScope: this,
|
||||||
onCompleteParams: [actor, event.get_time()]
|
onCompleteParams: [this._dragActor, eventTime]
|
||||||
});
|
});
|
||||||
return true;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_onSnapBackComplete : function (dragActor, eventTime) {
|
_onSnapBackComplete : function (dragActor, eventTime) {
|
||||||
@@ -220,11 +308,28 @@ _Draggable.prototype = {
|
|||||||
dragActor.destroy();
|
dragActor.destroy();
|
||||||
}
|
}
|
||||||
this.emit('drag-end', eventTime, false);
|
this.emit('drag-end', eventTime, false);
|
||||||
|
|
||||||
|
this._snapBackInProgress = false;
|
||||||
|
if (!this._buttonDown)
|
||||||
|
this._dragComplete();
|
||||||
|
},
|
||||||
|
|
||||||
|
_dragComplete: function() {
|
||||||
|
this._dragActor = undefined;
|
||||||
|
currentDraggable = null;
|
||||||
|
this._ungrabEvents();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Signals.addSignalMethods(_Draggable.prototype);
|
Signals.addSignalMethods(_Draggable.prototype);
|
||||||
|
|
||||||
function makeDraggable(actor) {
|
/**
|
||||||
return new _Draggable(actor);
|
* makeDraggable:
|
||||||
|
* @actor: Source actor
|
||||||
|
* @manualMode: If given, do not automatically start drag and drop on click
|
||||||
|
*
|
||||||
|
* Create an object which controls drag and drop for the given actor.
|
||||||
|
*/
|
||||||
|
function makeDraggable(actor, manualMode) {
|
||||||
|
return new _Draggable(actor, manualMode);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ DocDisplayItem.prototype = {
|
|||||||
_resetTimeDisplay: function(currentSecs) {
|
_resetTimeDisplay: function(currentSecs) {
|
||||||
let lastSecs = this._docInfo.timestamp;
|
let lastSecs = this._docInfo.timestamp;
|
||||||
let timeDelta = currentSecs - lastSecs;
|
let timeDelta = currentSecs - lastSecs;
|
||||||
let [text, nextUpdate] = Shell.Global.get().format_time_relative_pretty(timeDelta);
|
let [text, nextUpdate] = global.format_time_relative_pretty(timeDelta);
|
||||||
this._timeoutTime = currentSecs + nextUpdate;
|
this._timeoutTime = currentSecs + nextUpdate;
|
||||||
this._setDescriptionText(text);
|
this._setDescriptionText(text);
|
||||||
}
|
}
|
||||||
@@ -120,8 +120,6 @@ DocDisplay.prototype = {
|
|||||||
|
|
||||||
_init : function() {
|
_init : function() {
|
||||||
GenericDisplay.GenericDisplay.prototype._init.call(this);
|
GenericDisplay.GenericDisplay.prototype._init.call(this);
|
||||||
let me = this;
|
|
||||||
|
|
||||||
// We keep a single timeout callback for updating last visited times
|
// We keep a single timeout callback for updating last visited times
|
||||||
// for all the items in the display. This avoids creating individual
|
// for all the items in the display. This avoids creating individual
|
||||||
// callbacks for each item in the display. So proper time updates
|
// callbacks for each item in the display. So proper time updates
|
||||||
@@ -132,14 +130,14 @@ DocDisplay.prototype = {
|
|||||||
|
|
||||||
this._docManager = DocInfo.getDocManager();
|
this._docManager = DocInfo.getDocManager();
|
||||||
this._docsStale = true;
|
this._docsStale = true;
|
||||||
this._docManager.connect('changed', function(mgr, userData) {
|
this._docManager.connect('changed', Lang.bind(this, function(mgr, userData) {
|
||||||
me._docsStale = true;
|
this._docsStale = true;
|
||||||
// Changes in local recent files should not happen when we are in the Overview mode,
|
// Changes in local recent files should not happen when we are in the Overview mode,
|
||||||
// but redisplaying right away is cool when we use Zephyr.
|
// but redisplaying right away is cool when we use Zephyr.
|
||||||
// Also, we might be displaying remote documents, like Google Docs, in the future
|
// Also, we might be displaying remote documents, like Google Docs, in the future
|
||||||
// which might be edited by someone else.
|
// which might be edited by someone else.
|
||||||
me._redisplay(false);
|
this._redisplay(false);
|
||||||
});
|
}));
|
||||||
|
|
||||||
this.connect('destroy', Lang.bind(this, function (o) {
|
this.connect('destroy', Lang.bind(this, function (o) {
|
||||||
if (this._updateTimeoutId > 0)
|
if (this._updateTimeoutId > 0)
|
||||||
@@ -152,9 +150,10 @@ DocDisplay.prototype = {
|
|||||||
// Gets the list of recent items from the recent items manager.
|
// Gets the list of recent items from the recent items manager.
|
||||||
_refreshCache : function() {
|
_refreshCache : function() {
|
||||||
if (!this._docsStale)
|
if (!this._docsStale)
|
||||||
return;
|
return true;
|
||||||
this._allItems = this._docManager.getItems();
|
this._allItems = this._docManager.getItems();
|
||||||
this._docsStale = false;
|
this._docsStale = false;
|
||||||
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
// Sets the list of the displayed items based on how recently they were last visited.
|
// Sets the list of the displayed items based on how recently they were last visited.
|
||||||
@@ -173,21 +172,24 @@ DocDisplay.prototype = {
|
|||||||
// them once when they are returned by this._recentManager.get_items() to avoid having to do
|
// them once when they are returned by this._recentManager.get_items() to avoid having to do
|
||||||
// this sorting each time, but the sorting seems to be very fast anyway, so there is no need
|
// this sorting each time, but the sorting seems to be very fast anyway, so there is no need
|
||||||
// to introduce an additional class variable.
|
// to introduce an additional class variable.
|
||||||
this._matchedItems = [];
|
this._matchedItems = {};
|
||||||
|
this._matchedItemKeys = [];
|
||||||
let docIdsToRemove = [];
|
let docIdsToRemove = [];
|
||||||
for (docId in this._allItems) {
|
for (docId in this._allItems) {
|
||||||
// this._allItems[docId].exists() checks if the resource still exists
|
// this._allItems[docId].exists() checks if the resource still exists
|
||||||
if (this._allItems[docId].exists())
|
if (this._allItems[docId].exists()) {
|
||||||
this._matchedItems.push(docId);
|
this._matchedItems[docId] = 1;
|
||||||
else
|
this._matchedItemKeys.push(docId);
|
||||||
|
} else {
|
||||||
docIdsToRemove.push(docId);
|
docIdsToRemove.push(docId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (docId in docIdsToRemove) {
|
for (docId in docIdsToRemove) {
|
||||||
delete this._allItems[docId];
|
delete this._allItems[docId];
|
||||||
}
|
}
|
||||||
|
|
||||||
this._matchedItems.sort(Lang.bind(this, function (a,b) { return this._compareItems(a,b); }));
|
this._matchedItemKeys.sort(Lang.bind(this, this._compareItems));
|
||||||
},
|
},
|
||||||
|
|
||||||
// Compares items associated with the item ids based on how recently the items
|
// Compares items associated with the item ids based on how recently the items
|
||||||
@@ -300,7 +302,7 @@ DashDocDisplayItem.prototype = {
|
|||||||
shellWorkspaceLaunch: function () {
|
shellWorkspaceLaunch: function () {
|
||||||
this._info.launch();
|
this._info.launch();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class used to display two column recent documents in the dash
|
* Class used to display two column recent documents in the dash
|
||||||
@@ -434,5 +436,9 @@ DashDocDisplay.prototype = {
|
|||||||
let display = new DashDocDisplayItem(docInfo);
|
let display = new DashDocDisplayItem(docInfo);
|
||||||
this.actor.add_actor(display.actor);
|
this.actor.add_actor(display.actor);
|
||||||
}
|
}
|
||||||
|
this.emit('changed');
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
Signals.addSignalMethods(DashDocDisplay.prototype);
|
||||||
|
|
||||||
|
|||||||
33
js/ui/environment.js
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
|
const St = imports.gi.St;
|
||||||
|
|
||||||
|
const Tweener = imports.ui.tweener;
|
||||||
|
|
||||||
|
// "monkey patch" in some varargs ClutterContainer methods; we need
|
||||||
|
// to do this per-container class since there is no representation
|
||||||
|
// of interfaces in Javascript
|
||||||
|
function _patchContainerClass(containerClass) {
|
||||||
|
// This one is a straightforward mapping of the C method
|
||||||
|
containerClass.prototype.child_set = function(actor, props) {
|
||||||
|
let meta = this.get_child_meta(actor);
|
||||||
|
for (prop in props)
|
||||||
|
meta[prop] = props[prop];
|
||||||
|
};
|
||||||
|
|
||||||
|
// clutter_container_add() actually is a an add-many-actors
|
||||||
|
// method. We conveniently, but somewhat dubiously, take the
|
||||||
|
// this opportunity to make it do something more useful.
|
||||||
|
containerClass.prototype.add = function(actor, props) {
|
||||||
|
this.add_actor(actor);
|
||||||
|
if (props)
|
||||||
|
this.child_set(actor, props);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
_patchContainerClass(St.BoxLayout);
|
||||||
|
_patchContainerClass(St.Table);
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
Tweener.init();
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@ const Gdk = imports.gi.Gdk;
|
|||||||
const Gtk = imports.gi.Gtk;
|
const Gtk = imports.gi.Gtk;
|
||||||
const Lang = imports.lang;
|
const Lang = imports.lang;
|
||||||
const Mainloop = imports.mainloop;
|
const Mainloop = imports.mainloop;
|
||||||
|
const Meta = imports.gi.Meta;
|
||||||
const Pango = imports.gi.Pango;
|
const Pango = imports.gi.Pango;
|
||||||
const Signals = imports.signals;
|
const Signals = imports.signals;
|
||||||
const Shell = imports.gi.Shell;
|
const Shell = imports.gi.Shell;
|
||||||
@@ -16,6 +17,11 @@ const DND = imports.ui.dnd;
|
|||||||
const Link = imports.ui.link;
|
const Link = imports.ui.link;
|
||||||
const Main = imports.ui.main;
|
const Main = imports.ui.main;
|
||||||
|
|
||||||
|
const RedisplayFlags = { NONE: 0,
|
||||||
|
RESET_CONTROLS: 1 << 0,
|
||||||
|
FULL: 1 << 1,
|
||||||
|
SUBSEARCH: 1 << 2 };
|
||||||
|
|
||||||
const ITEM_DISPLAY_NAME_COLOR = new Clutter.Color();
|
const ITEM_DISPLAY_NAME_COLOR = new Clutter.Color();
|
||||||
ITEM_DISPLAY_NAME_COLOR.from_pixel(0xffffffff);
|
ITEM_DISPLAY_NAME_COLOR.from_pixel(0xffffffff);
|
||||||
const ITEM_DISPLAY_DESCRIPTION_COLOR = new Clutter.Color();
|
const ITEM_DISPLAY_DESCRIPTION_COLOR = new Clutter.Color();
|
||||||
@@ -87,13 +93,12 @@ GenericDisplayItem.prototype = {
|
|||||||
spacing: DEFAULT_PADDING });
|
spacing: DEFAULT_PADDING });
|
||||||
this._infoContent.append(this._infoText, Big.BoxPackFlags.EXPAND);
|
this._infoContent.append(this._infoText, Big.BoxPackFlags.EXPAND);
|
||||||
|
|
||||||
let global = Shell.Global.get();
|
|
||||||
let infoIconUri = "file://" + global.imagedir + "info.svg";
|
let infoIconUri = "file://" + global.imagedir + "info.svg";
|
||||||
let infoIcon = Shell.TextureCache.get_default().load_uri_sync(Shell.TextureCachePolicy.FOREVER,
|
let infoIcon = Shell.TextureCache.get_default().load_uri_sync(Shell.TextureCachePolicy.FOREVER,
|
||||||
infoIconUri,
|
infoIconUri,
|
||||||
INFORMATION_BUTTON_SIZE,
|
INFORMATION_BUTTON_SIZE,
|
||||||
INFORMATION_BUTTON_SIZE);
|
INFORMATION_BUTTON_SIZE);
|
||||||
this._informationButton = new Button.iconButton(this.actor, INFORMATION_BUTTON_SIZE, infoIcon);
|
this._informationButton = new Button.IconButton(this.actor, INFORMATION_BUTTON_SIZE, infoIcon);
|
||||||
let buttonBox = new Big.Box({ width: INFORMATION_BUTTON_SIZE + 2 * DEFAULT_PADDING,
|
let buttonBox = new Big.Box({ width: INFORMATION_BUTTON_SIZE + 2 * DEFAULT_PADDING,
|
||||||
height: INFORMATION_BUTTON_SIZE,
|
height: INFORMATION_BUTTON_SIZE,
|
||||||
padding_left: DEFAULT_PADDING, padding_right: DEFAULT_PADDING,
|
padding_left: DEFAULT_PADDING, padding_right: DEFAULT_PADDING,
|
||||||
@@ -121,6 +126,8 @@ GenericDisplayItem.prototype = {
|
|||||||
this._description = null;
|
this._description = null;
|
||||||
this._icon = null;
|
this._icon = null;
|
||||||
|
|
||||||
|
this._initialLoadComplete = false;
|
||||||
|
|
||||||
// An array of details description actors that we create over time for the item.
|
// An array of details description actors that we create over time for the item.
|
||||||
// It is used for updating the description text inside the details actor when
|
// It is used for updating the description text inside the details actor when
|
||||||
// the description text for the item is updated.
|
// the description text for the item is updated.
|
||||||
@@ -337,9 +344,10 @@ GenericDisplay.prototype = {
|
|||||||
|
|
||||||
// map<itemId, Object> where Object represents the item info
|
// map<itemId, Object> where Object represents the item info
|
||||||
this._allItems = {};
|
this._allItems = {};
|
||||||
// an array of itemIds of items that match the current request
|
// set<itemId>
|
||||||
// in the order in which the items should be displayed
|
this._matchedItems = {};
|
||||||
this._matchedItems = [];
|
// sorted array of items matched by search
|
||||||
|
this._matchedItemKeys = [];
|
||||||
// map<itemId, GenericDisplayItem>
|
// map<itemId, GenericDisplayItem>
|
||||||
this._displayedItems = {};
|
this._displayedItems = {};
|
||||||
this._openDetailIndex = -1;
|
this._openDetailIndex = -1;
|
||||||
@@ -357,8 +365,16 @@ GenericDisplay.prototype = {
|
|||||||
|
|
||||||
// Sets the search string and displays the matching items.
|
// Sets the search string and displays the matching items.
|
||||||
setSearch: function(text) {
|
setSearch: function(text) {
|
||||||
this._search = text.toLowerCase();
|
let lowertext = text.toLowerCase();
|
||||||
this._redisplay(true);
|
if (lowertext == this._search)
|
||||||
|
return;
|
||||||
|
let flags = RedisplayFlags.RESET_CONTROLS;
|
||||||
|
if (this._search != '') {
|
||||||
|
if (lowertext.indexOf(this._search) == 0)
|
||||||
|
flags |= RedisplayFlags.SUBSEARCH;
|
||||||
|
}
|
||||||
|
this._search = lowertext;
|
||||||
|
this._redisplay(flags);
|
||||||
},
|
},
|
||||||
|
|
||||||
// Launches the item that is currently selected, closing the Overview
|
// Launches the item that is currently selected, closing the Overview
|
||||||
@@ -426,16 +442,20 @@ GenericDisplay.prototype = {
|
|||||||
|
|
||||||
// Returns true if the display has any displayed items.
|
// Returns true if the display has any displayed items.
|
||||||
hasItems: function() {
|
hasItems: function() {
|
||||||
return this._list.displayedCount > 0;
|
// TODO: figure out why this._list.displayedCount is returning a
|
||||||
|
// positive number when this._mathedItems.length is 0
|
||||||
|
// This can be triggered if a search string is entered for which there are no matches.
|
||||||
|
// log("this._mathedItems.length: " + this._matchedItems.length + " this._list.displayedCount " + this._list.displayedCount);
|
||||||
|
return this._matchedItemKeys.length > 0;
|
||||||
},
|
},
|
||||||
|
|
||||||
getMatchedItemsCount: function() {
|
getMatchedItemsCount: function() {
|
||||||
return this._matchedItems.length;
|
return this._matchedItemKeys.length;
|
||||||
},
|
},
|
||||||
|
|
||||||
// Load the initial state
|
// Load the initial state
|
||||||
load: function() {
|
load: function() {
|
||||||
this._redisplay(true);
|
this._redisplay(RedisplayFlags.FULL);
|
||||||
},
|
},
|
||||||
|
|
||||||
// Should be called when the display is closed
|
// Should be called when the display is closed
|
||||||
@@ -457,57 +477,23 @@ GenericDisplay.prototype = {
|
|||||||
|
|
||||||
// Displays the page specified by the pageNumber argument.
|
// Displays the page specified by the pageNumber argument.
|
||||||
displayPage: function(pageNumber) {
|
displayPage: function(pageNumber) {
|
||||||
|
// Cleanup from the previous selection, but don't unset this._selectedIndex
|
||||||
|
if (this.hasSelected()) {
|
||||||
|
this._findDisplayedByIndex(this._selectedIndex).markSelected(false);
|
||||||
|
}
|
||||||
this._list.page = pageNumber;
|
this._list.page = pageNumber;
|
||||||
},
|
},
|
||||||
|
|
||||||
//// Protected methods ////
|
//// Protected methods ////
|
||||||
|
|
||||||
/*
|
_redisplayFull: function() {
|
||||||
* Displays items that match the current request and should show up on the current page.
|
|
||||||
* Updates the display control to reflect the matched items set and the page selected.
|
|
||||||
*
|
|
||||||
* resetDisplayControl - indicates if the display control should be re-created because
|
|
||||||
* the results or the space allocated for them changed. If it's false,
|
|
||||||
* the existing display control is used and only the page links are
|
|
||||||
* updated to reflect the current page selection.
|
|
||||||
*/
|
|
||||||
_displayMatchedItems: function(resetDisplayControl) {
|
|
||||||
// When generating a new list to display, we first remove all the old
|
|
||||||
// displayed items which will unset the selection. So we need
|
|
||||||
// to keep a flag which indicates if this display had the selection.
|
|
||||||
let hadSelected = this.hasSelected();
|
|
||||||
|
|
||||||
this._removeAllDisplayItems();
|
this._removeAllDisplayItems();
|
||||||
for (let i = 0; i < this._matchedItems.length; i++) {
|
for (let itemId in this._allItems) {
|
||||||
this._addDisplayItem(this._matchedItems[i]);
|
this._addDisplayItem(itemId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hadSelected) {
|
|
||||||
this._selectedIndex = -1;
|
|
||||||
this.selectFirstItem();
|
|
||||||
}
|
|
||||||
|
|
||||||
// We currently redisplay matching items and raise the sideshow as part of two different callbacks.
|
|
||||||
// Checking what is under the pointer after a timeout allows us to not merge these callbacks into one, at least for now.
|
|
||||||
Mainloop.timeout_add(5,
|
|
||||||
Lang.bind(this,
|
|
||||||
function() {
|
|
||||||
// Check if the pointer is over one of the items and display the information button if it is.
|
|
||||||
let [child, x, y, mask] = Gdk.Screen.get_default().get_root_window().get_pointer();
|
|
||||||
let global = Shell.Global.get();
|
|
||||||
let actor = global.stage.get_actor_at_pos(Clutter.PickMode.REACTIVE,
|
|
||||||
x, y);
|
|
||||||
if (actor != null) {
|
|
||||||
let item = this._findDisplayedByActor(actor);
|
|
||||||
if (item != null) {
|
|
||||||
item.onDrawnUnderPointer();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}));
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Creates a display item based on the information associated with itemId
|
// Creates a display item based on the information associated with itemId
|
||||||
// and adds it to the displayed items.
|
// and adds it to the displayed items.
|
||||||
_addDisplayItem : function(itemId) {
|
_addDisplayItem : function(itemId) {
|
||||||
if (this._displayedItems.hasOwnProperty(itemId)) {
|
if (this._displayedItems.hasOwnProperty(itemId)) {
|
||||||
@@ -578,33 +564,131 @@ GenericDisplay.prototype = {
|
|||||||
this.unsetSelected();
|
this.unsetSelected();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_compareSearchMatch: function(a, b) {
|
||||||
|
let countA = this._matchedItems[a];
|
||||||
|
let countB = this._matchedItems[b];
|
||||||
|
if (countA > countB)
|
||||||
|
return -1;
|
||||||
|
else if (countA < countB)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return this._compareItems(a, b);
|
||||||
|
},
|
||||||
|
|
||||||
|
_setMatches: function(matches) {
|
||||||
|
this._matchedItems = matches;
|
||||||
|
this._matchedItemKeys = [];
|
||||||
|
for (let itemId in this._matchedItems) {
|
||||||
|
this._matchedItemKeys.push(itemId);
|
||||||
|
}
|
||||||
|
this._matchedItemKeys.sort(Lang.bind(this, this._compareSearchMatch));
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* _redisplaySubSearch:
|
||||||
|
* A somewhat more optimized function called when we know
|
||||||
|
* that we're going to be displaying a subset of the items
|
||||||
|
* we already had, in the same order. In that case, we can
|
||||||
|
* just hide the actors that shouldn't be shown.
|
||||||
|
*/
|
||||||
|
_redisplaySubSearch: function() {
|
||||||
|
let matches = this._getSearchMatchedItems(true);
|
||||||
|
|
||||||
|
// Just hide all from the old set,
|
||||||
|
// we'll show the ones we want below
|
||||||
|
for (let itemId in this._displayedItems) {
|
||||||
|
let item = this._displayedItems[itemId];
|
||||||
|
item.actor.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
this._setMatches(matches);
|
||||||
|
|
||||||
|
for (let itemId in matches) {
|
||||||
|
let item = this._displayedItems[itemId];
|
||||||
|
item.actor.show();
|
||||||
|
}
|
||||||
|
this._list.queue_relayout();
|
||||||
|
},
|
||||||
|
|
||||||
|
_redisplayReordering: function() {
|
||||||
|
if (!this._filterActive()) {
|
||||||
|
this._setDefaultList();
|
||||||
|
} else {
|
||||||
|
this._setMatches(this._getSearchMatchedItems(false));
|
||||||
|
}
|
||||||
|
this._list.remove_all();
|
||||||
|
for (let i = 0; i < this._matchedItemKeys.length; i++) {
|
||||||
|
let itemId = this._matchedItemKeys[i];
|
||||||
|
let item = this._displayedItems[itemId];
|
||||||
|
item.actor.show();
|
||||||
|
this._list.add_actor(item.actor);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Updates the displayed items, applying the search string if one exists.
|
* Updates the displayed items, applying the search string if one exists.
|
||||||
*
|
* @flags: Flags controlling redisplay behavior as follows:
|
||||||
* resetPage - indicates if the page selection should be reset when displaying the matching results.
|
* RESET_CONTROLS - indicates if the page selection should be reset when displaying the matching results.
|
||||||
* We reset the page selection when the change in results was initiated by the user by
|
* We reset the page selection when the change in results was initiated by the user by
|
||||||
* entering a different search criteria or by viewing the results list in a different
|
* entering a different search criteria or by viewing the results list in a different
|
||||||
* size mode, but we keep the page selection the same if the results got updated on
|
* size mode, but we keep the page selection the same if the results got updated on
|
||||||
* their own while the user was browsing through the result pages.
|
* their own while the user was browsing through the result pages.
|
||||||
|
* SUBSEARCH - Indicates that the current _search is a superstring of the previous
|
||||||
|
* one, which implies we only need to re-search through previous results.
|
||||||
*/
|
*/
|
||||||
_redisplay: function(resetPage) {
|
_redisplay: function(flags) {
|
||||||
this._refreshCache();
|
let resetPage = (flags & RedisplayFlags.RESET_CONTROLS) > 0;
|
||||||
if (!this._filterActive())
|
let isSubSearch = (flags & RedisplayFlags.SUBSEARCH) > 0;
|
||||||
this._setDefaultList();
|
let fullReload = (flags & RedisplayFlags.FULL) > 0;
|
||||||
else
|
|
||||||
this._doSearchFilter();
|
let hadSelected = this.hasSelected();
|
||||||
|
|
||||||
|
if (!this._initialLoadComplete || !this._refreshCache())
|
||||||
|
fullReload = true;
|
||||||
|
if (fullReload) {
|
||||||
|
this._initialLoadComplete = true;
|
||||||
|
this._redisplayFull();
|
||||||
|
} if (isSubSearch) {
|
||||||
|
this._redisplaySubSearch();
|
||||||
|
} else {
|
||||||
|
this._redisplayReordering();
|
||||||
|
}
|
||||||
|
|
||||||
if (resetPage)
|
if (resetPage)
|
||||||
this._list.page = 0;
|
this._list.page = 0;
|
||||||
|
|
||||||
this._displayMatchedItems(true);
|
if (hadSelected) {
|
||||||
|
this._selectedIndex = -1;
|
||||||
|
this.selectFirstItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
Mainloop.idle_add(Lang.bind(this, this._checkInformationIcon),
|
||||||
|
Meta.PRIORITY_BEFORE_REDRAW);
|
||||||
|
|
||||||
this.emit('redisplayed');
|
this.emit('redisplayed');
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Check if the pointer is over one of the items and display the information button if it is.
|
||||||
|
// We want to do this between finishing our changes to the display and the point where
|
||||||
|
// the display is redrawn.
|
||||||
|
_checkInformationIcon: function() {
|
||||||
|
let [child, x, y, mask] = Gdk.Screen.get_default().get_root_window().get_pointer();
|
||||||
|
let actor = global.stage.get_actor_at_pos(Clutter.PickMode.REACTIVE,
|
||||||
|
x, y);
|
||||||
|
if (actor != null) {
|
||||||
|
let item = this._findDisplayedByActor(actor);
|
||||||
|
if (item != null) {
|
||||||
|
item.onDrawnUnderPointer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
//// Pure virtual protected methods ////
|
//// Pure virtual protected methods ////
|
||||||
|
|
||||||
// Performs the steps needed to have the latest information about the items.
|
// Performs the steps needed to have the latest information about the items.
|
||||||
|
// Implementation should return %true if we are up to date, and %false
|
||||||
|
// if a full reload occurred.
|
||||||
_refreshCache: function() {
|
_refreshCache: function() {
|
||||||
throw new Error("Not implemented");
|
throw new Error("Not implemented");
|
||||||
},
|
},
|
||||||
@@ -636,71 +720,57 @@ GenericDisplay.prototype = {
|
|||||||
|
|
||||||
//// Private methods ////
|
//// Private methods ////
|
||||||
|
|
||||||
_getSearchMatchedItems: function() {
|
_getItemSearchScore: function(itemId, terms) {
|
||||||
let matchedItemsForSearch = {};
|
let item = this._allItems[itemId];
|
||||||
|
let score = 0;
|
||||||
|
for (let i = 0; i < terms.length; i++) {
|
||||||
|
let term = terms[i];
|
||||||
|
if (this._isInfoMatching(item, term)) {
|
||||||
|
score++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return score;
|
||||||
|
},
|
||||||
|
|
||||||
|
_getSearchMatchedItems: function(isSubSearch) {
|
||||||
// Break the search up into terms, and search for each
|
// Break the search up into terms, and search for each
|
||||||
// individual term. Keep track of the number of terms
|
// individual term. Keep track of the number of terms
|
||||||
// each item matched.
|
// each item matched.
|
||||||
let terms = this._search.split(/\s+/);
|
let terms = this._search.split(/\s+/);
|
||||||
for (let i = 0; i < terms.length; i++) {
|
let matchScores = {};
|
||||||
let term = terms[i];
|
|
||||||
for (itemId in this._allItems) {
|
if (isSubSearch) {
|
||||||
let item = this._allItems[itemId];
|
for (let i = 0; i < this._matchedItemKeys.length; i++) {
|
||||||
if (this._isInfoMatching(item, term)) {
|
let itemId = this._matchedItemKeys[i];
|
||||||
let count = matchedItemsForSearch[itemId];
|
let score = this._getItemSearchScore(itemId, terms);
|
||||||
if (!count)
|
if (score > 0)
|
||||||
count = 0;
|
matchScores[itemId] = score;
|
||||||
count += 1;
|
|
||||||
matchedItemsForSearch[itemId] = count;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return matchedItemsForSearch;
|
|
||||||
},
|
|
||||||
|
|
||||||
// Applies the search string to the list of items to find matches,
|
|
||||||
// and displays the matching items.
|
|
||||||
_doSearchFilter: function() {
|
|
||||||
let matchedItemsForSearch;
|
|
||||||
|
|
||||||
if (this._filterActive()) {
|
|
||||||
matchedItemsForSearch = this._getSearchMatchedItems();
|
|
||||||
} else {
|
} else {
|
||||||
matchedItemsForSearch = {};
|
for (let itemId in this._displayedItems) {
|
||||||
for (let itemId in this._allItems) {
|
let score = this._getItemSearchScore(itemId, terms);
|
||||||
matchedItemsForSearch[itemId] = 1;
|
if (score > 0)
|
||||||
|
matchScores[itemId] = score;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return matchScores;
|
||||||
this._matchedItems = [];
|
|
||||||
for (itemId in matchedItemsForSearch) {
|
|
||||||
this._matchedItems.push(itemId);
|
|
||||||
}
|
|
||||||
this._matchedItems.sort(Lang.bind(this, function (a, b) {
|
|
||||||
let countA = matchedItemsForSearch[a];
|
|
||||||
let countB = matchedItemsForSearch[b];
|
|
||||||
if (countA > countB)
|
|
||||||
return -1;
|
|
||||||
else if (countA < countB)
|
|
||||||
return 1;
|
|
||||||
else
|
|
||||||
return this._compareItems(a, b);
|
|
||||||
}));
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Updates the display control to reflect the matched items set and the page selected.
|
* Updates the display control to reflect the matched items set and the page selected.
|
||||||
*
|
*
|
||||||
* resetDisplayControl - indicates if the display control should be re-created because
|
* resetDisplayControl - indicates if the display control should be re-created because
|
||||||
* the results or the space allocated for them changed. If it's false,
|
* the results or the space allocated for them changed. If it's false,
|
||||||
* the existing display control is used and only the page links are
|
* the existing display control is used and only the page links are
|
||||||
* updated to reflect the current page selection.
|
* updated to reflect the current page selection.
|
||||||
*/
|
*/
|
||||||
_updateDisplayControl: function(resetDisplayControl) {
|
_updateDisplayControl: function(resetDisplayControl) {
|
||||||
if (resetDisplayControl) {
|
if (resetDisplayControl) {
|
||||||
this._selectedIndex = -1;
|
|
||||||
this.displayControl.remove_all();
|
this.displayControl.remove_all();
|
||||||
let nPages = this._list.n_pages;
|
let nPages = this._list.n_pages;
|
||||||
|
// Don't show the page indicator if there is only one page.
|
||||||
|
if (nPages == 1)
|
||||||
|
return;
|
||||||
let pageNumber = this._list.page;
|
let pageNumber = this._list.page;
|
||||||
for (let i = 0; i < nPages; i++) {
|
for (let i = 0; i < nPages; i++) {
|
||||||
let pageControl = new Link.Link({ color: (i == pageNumber) ? DISPLAY_CONTROL_SELECTED_COLOR : ITEM_DISPLAY_DESCRIPTION_COLOR,
|
let pageControl = new Link.Link({ color: (i == pageNumber) ? DISPLAY_CONTROL_SELECTED_COLOR : ITEM_DISPLAY_DESCRIPTION_COLOR,
|
||||||
@@ -730,6 +800,9 @@ GenericDisplay.prototype = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (this.hasSelected()) {
|
||||||
|
this.selectFirstItem();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// Returns a display item based on its index in the ordering of the
|
// Returns a display item based on its index in the ordering of the
|
||||||
@@ -754,17 +827,8 @@ GenericDisplay.prototype = {
|
|||||||
// Selects (e.g. highlights) a display item at the provided index,
|
// Selects (e.g. highlights) a display item at the provided index,
|
||||||
// updates this.selectedItemDetails actor, and emits 'selected' signal.
|
// updates this.selectedItemDetails actor, and emits 'selected' signal.
|
||||||
_selectIndex: function(index) {
|
_selectIndex: function(index) {
|
||||||
if (index >= this._list.displayedCount)
|
|
||||||
return
|
|
||||||
|
|
||||||
// If the item is already selected, all we do is toggling the details pane.
|
|
||||||
if (this._selectedIndex == index && index >= 0) {
|
|
||||||
this.emit('details', index);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cleanup from the previous item
|
// Cleanup from the previous item
|
||||||
if (this._selectedIndex >= 0) {
|
if (this.hasSelected()) {
|
||||||
this._findDisplayedByIndex(this._selectedIndex).markSelected(false);
|
this._findDisplayedByIndex(this._selectedIndex).markSelected(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
151
js/ui/lightbox.js
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
|
const Clutter = imports.gi.Clutter;
|
||||||
|
const Lang = imports.lang;
|
||||||
|
|
||||||
|
const Main = imports.ui.main;
|
||||||
|
const Tweener = imports.ui.tweener;
|
||||||
|
|
||||||
|
const SHADE_COLOR = new Clutter.Color();
|
||||||
|
SHADE_COLOR.from_pixel(0x00000044);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lightbox:
|
||||||
|
* @container: parent Clutter.Container
|
||||||
|
* @width: (optional) shade actor width
|
||||||
|
* @height: (optional) shade actor height
|
||||||
|
*
|
||||||
|
* Lightbox creates a dark translucent "shade" actor to hide the
|
||||||
|
* contents of @container, and allows you to specify particular actors
|
||||||
|
* in @container to highlight by bringing them above the shade. It
|
||||||
|
* tracks added and removed actors in @container while the lightboxing
|
||||||
|
* is active, and ensures that all actors are returned to their
|
||||||
|
* original stacking order when the lightboxing is removed. (However,
|
||||||
|
* if actors are restacked by outside code while the lightboxing is
|
||||||
|
* active, the lightbox may later revert them back to their original
|
||||||
|
* order.)
|
||||||
|
*
|
||||||
|
* By default, the shade window will have the height and width of
|
||||||
|
* @container and will track any changes in its size. You can override
|
||||||
|
* this by passing an explicit width and height
|
||||||
|
*/
|
||||||
|
function Lightbox(container, width, height) {
|
||||||
|
this._init(container, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
Lightbox.prototype = {
|
||||||
|
_init : function(container, width, height) {
|
||||||
|
this._container = container;
|
||||||
|
this._children = container.get_children();
|
||||||
|
this.actor = new Clutter.Rectangle({ color: SHADE_COLOR,
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
border_width: 0,
|
||||||
|
reactive: true });
|
||||||
|
|
||||||
|
container.add_actor(this.actor);
|
||||||
|
this.actor.raise_top();
|
||||||
|
|
||||||
|
this._destroySignalId = this.actor.connect('destroy', Lang.bind(this, this.destroy));
|
||||||
|
|
||||||
|
if (width && height) {
|
||||||
|
this.actor.width = width;
|
||||||
|
this.actor.height = height;
|
||||||
|
this._allocationChangedSignalId = 0;
|
||||||
|
} else {
|
||||||
|
this.actor.width = container.width;
|
||||||
|
this.actor.height = container.height;
|
||||||
|
this._allocationChangedSignalId = container.connect('allocation-changed', Lang.bind(this, this._allocationChanged));
|
||||||
|
}
|
||||||
|
|
||||||
|
this._actorAddedSignalId = container.connect('actor-added', Lang.bind(this, this._actorAdded));
|
||||||
|
this._actorRemovedSignalId = container.connect('actor-removed', Lang.bind(this, this._actorRemoved));
|
||||||
|
|
||||||
|
this._highlighted = null;
|
||||||
|
},
|
||||||
|
|
||||||
|
_allocationChanged : function(container, box, flags) {
|
||||||
|
this.actor.width = this._container.width;
|
||||||
|
this.actor.height = this._container.height;
|
||||||
|
},
|
||||||
|
|
||||||
|
_actorAdded : function(container, newChild) {
|
||||||
|
let children = this._container.get_children();
|
||||||
|
let myIndex = children.indexOf(this.actor);
|
||||||
|
let newChildIndex = children.indexOf(newChild);
|
||||||
|
|
||||||
|
if (newChildIndex > myIndex) {
|
||||||
|
// The child was added above the shade (presumably it was
|
||||||
|
// made the new top-most child). Move it below the shade,
|
||||||
|
// and add it to this._children as the new topmost actor.
|
||||||
|
newChild.lower(this.actor);
|
||||||
|
this._children.push(newChild);
|
||||||
|
} else if (newChildIndex == 0) {
|
||||||
|
// Bottom of stack
|
||||||
|
this._children.unshift(newChild);
|
||||||
|
} else {
|
||||||
|
// Somewhere else; insert it into the correct spot
|
||||||
|
let prevChild = this._children.indexOf(children[newChildIndex - 1]);
|
||||||
|
if (prevChild != -1) // paranoia
|
||||||
|
this._children.splice(prevChild + 1, 0, newChild);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_actorRemoved : function(container, child) {
|
||||||
|
let index = this._children.indexOf(child);
|
||||||
|
if (index != -1) // paranoia
|
||||||
|
this._children.splice(index, 1);
|
||||||
|
|
||||||
|
if (child == this._highlighted)
|
||||||
|
this._highlighted = null;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* highlight:
|
||||||
|
* @window: actor to highlight
|
||||||
|
*
|
||||||
|
* Highlights the indicated actor and unhighlights any other
|
||||||
|
* currently-highlighted actor. With no arguments or a false/null
|
||||||
|
* argument, all actors will be unhighlighted.
|
||||||
|
*/
|
||||||
|
highlight : function(window) {
|
||||||
|
if (this._highlighted == window)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Walk this._children raising and lowering actors as needed.
|
||||||
|
// Things get a little tricky if the to-be-raised and
|
||||||
|
// to-be-lowered actors were originally adjacent, in which
|
||||||
|
// case we may need to indicate some *other* actor as the new
|
||||||
|
// sibling of the to-be-lowered one.
|
||||||
|
|
||||||
|
let below = this.actor;
|
||||||
|
for (let i = this._children.length - 1; i >= 0; i--) {
|
||||||
|
if (this._children[i] == window)
|
||||||
|
this._children[i].raise_top();
|
||||||
|
else if (this._children[i] == this._highlighted)
|
||||||
|
this._children[i].lower(below);
|
||||||
|
else
|
||||||
|
below = this._children[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
this._highlighted = window;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* destroy:
|
||||||
|
*
|
||||||
|
* Destroys the lightbox. This is called automatically if the
|
||||||
|
* lightbox's container is destroyed.
|
||||||
|
*/
|
||||||
|
destroy : function() {
|
||||||
|
if (this._allocationChangedSignalId != 0)
|
||||||
|
this._container.disconnect(this._allocationChangedSignalId);
|
||||||
|
this._container.disconnect(this._actorAddedSignalId);
|
||||||
|
this._container.disconnect(this._actorRemovedSignalId);
|
||||||
|
|
||||||
|
this.actor.disconnect(this._destroySignalId);
|
||||||
|
|
||||||
|
this.highlight(null);
|
||||||
|
this.actor.destroy();
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -4,6 +4,7 @@ const Big = imports.gi.Big;
|
|||||||
const Clutter = imports.gi.Clutter;
|
const Clutter = imports.gi.Clutter;
|
||||||
const Gio = imports.gi.Gio;
|
const Gio = imports.gi.Gio;
|
||||||
const Pango = imports.gi.Pango;
|
const Pango = imports.gi.Pango;
|
||||||
|
const St = imports.gi.St;
|
||||||
const Shell = imports.gi.Shell;
|
const Shell = imports.gi.Shell;
|
||||||
const Signals = imports.signals;
|
const Signals = imports.signals;
|
||||||
const Lang = imports.lang;
|
const Lang = imports.lang;
|
||||||
@@ -12,18 +13,7 @@ const Mainloop = imports.mainloop;
|
|||||||
const Tweener = imports.ui.tweener;
|
const Tweener = imports.ui.tweener;
|
||||||
const Main = imports.ui.main;
|
const Main = imports.ui.main;
|
||||||
|
|
||||||
const LG_BORDER_COLOR = new Clutter.Color();
|
/* Imports...feel free to add here as needed */
|
||||||
LG_BORDER_COLOR.from_pixel(0x0000aca0);
|
|
||||||
const LG_BACKGROUND_COLOR = new Clutter.Color();
|
|
||||||
LG_BACKGROUND_COLOR.from_pixel(0x000000d5);
|
|
||||||
const GREY = new Clutter.Color();
|
|
||||||
GREY.from_pixel(0xAFAFAFFF);
|
|
||||||
const MATRIX_GREEN = new Clutter.Color();
|
|
||||||
MATRIX_GREEN.from_pixel(0x88ff66ff);
|
|
||||||
// FIXME pull from GConf
|
|
||||||
const MATRIX_FONT = 'Monospace 10';
|
|
||||||
|
|
||||||
/* Imports...feel free to add here as needed */
|
|
||||||
var commandHeader = "const Clutter = imports.gi.Clutter; " +
|
var commandHeader = "const Clutter = imports.gi.Clutter; " +
|
||||||
"const GLib = imports.gi.GLib; " +
|
"const GLib = imports.gi.GLib; " +
|
||||||
"const Gtk = imports.gi.Gtk; " +
|
"const Gtk = imports.gi.Gtk; " +
|
||||||
@@ -35,7 +25,6 @@ var commandHeader = "const Clutter = imports.gi.Clutter; " +
|
|||||||
"const Tweener = imports.ui.tweener; " +
|
"const Tweener = imports.ui.tweener; " +
|
||||||
/* Utility functions...we should probably be able to use these
|
/* Utility functions...we should probably be able to use these
|
||||||
* in the shell core code too. */
|
* in the shell core code too. */
|
||||||
"const global = Shell.Global.get(); " +
|
|
||||||
"const stage = global.stage; " +
|
"const stage = global.stage; " +
|
||||||
"const color = function(pixel) { let c= new Clutter.Color(); c.from_pixel(pixel); return c; }; " +
|
"const color = function(pixel) { let c= new Clutter.Color(); c.from_pixel(pixel); return c; }; " +
|
||||||
/* Special lookingGlass functions */
|
/* Special lookingGlass functions */
|
||||||
@@ -48,7 +37,7 @@ function Notebook() {
|
|||||||
|
|
||||||
Notebook.prototype = {
|
Notebook.prototype = {
|
||||||
_init: function() {
|
_init: function() {
|
||||||
this.actor = new Big.Box();
|
this.actor = new St.BoxLayout({ vertical: true });
|
||||||
|
|
||||||
this.tabControls = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
this.tabControls = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||||
spacing: 4, padding: 2 });
|
spacing: 4, padding: 2 });
|
||||||
@@ -59,21 +48,24 @@ Notebook.prototype = {
|
|||||||
|
|
||||||
appendPage: function(name, child) {
|
appendPage: function(name, child) {
|
||||||
let labelOuterBox = new Big.Box({ padding: 2 });
|
let labelOuterBox = new Big.Box({ padding: 2 });
|
||||||
let labelBox = new Big.Box({ padding: 2, border_color: MATRIX_GREEN,
|
let labelBox = new St.BoxLayout({ reactive: true });
|
||||||
reactive: true });
|
|
||||||
labelOuterBox.append(labelBox, Big.BoxPackFlags.NONE);
|
labelOuterBox.append(labelBox, Big.BoxPackFlags.NONE);
|
||||||
let label = new Clutter.Text({ color: MATRIX_GREEN,
|
let label = new St.Label({ text: name });
|
||||||
font_name: MATRIX_FONT,
|
|
||||||
text: name });
|
|
||||||
labelBox.connect('button-press-event', Lang.bind(this, function () {
|
labelBox.connect('button-press-event', Lang.bind(this, function () {
|
||||||
this.selectChild(child);
|
this.selectChild(child);
|
||||||
return true;
|
return true;
|
||||||
}));
|
}));
|
||||||
labelBox.append(label, Big.BoxPackFlags.EXPAND);
|
labelBox.add(label, { expand: true });
|
||||||
this._tabs.push([child, labelBox]);
|
|
||||||
child.hide();
|
|
||||||
this.actor.append(child, Big.BoxPackFlags.EXPAND);
|
|
||||||
this.tabControls.append(labelOuterBox, Big.BoxPackFlags.NONE);
|
this.tabControls.append(labelOuterBox, Big.BoxPackFlags.NONE);
|
||||||
|
|
||||||
|
let scrollview = new St.ScrollView({ x_fill: true, y_fill: true });
|
||||||
|
scrollview.get_hscroll_bar().hide();
|
||||||
|
scrollview.add_actor(child);
|
||||||
|
|
||||||
|
this._tabs.push([child, labelBox, scrollview]);
|
||||||
|
scrollview.hide();
|
||||||
|
this.actor.add(scrollview, { expand: true });
|
||||||
|
|
||||||
if (this._selectedIndex == -1)
|
if (this._selectedIndex == -1)
|
||||||
this.selectIndex(0);
|
this.selectIndex(0);
|
||||||
},
|
},
|
||||||
@@ -81,10 +73,10 @@ Notebook.prototype = {
|
|||||||
_unselect: function() {
|
_unselect: function() {
|
||||||
if (this._selectedIndex < 0)
|
if (this._selectedIndex < 0)
|
||||||
return;
|
return;
|
||||||
let [child, labelBox] = this._tabs[this._selectedIndex];
|
let [child, labelBox, scrollview] = this._tabs[this._selectedIndex];
|
||||||
labelBox.padding = 2;
|
labelBox.padding = 2;
|
||||||
labelBox.border = 0;
|
labelBox.border = 0;
|
||||||
child.hide();
|
scrollview.hide();
|
||||||
this._selectedIndex = -1;
|
this._selectedIndex = -1;
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -96,10 +88,10 @@ Notebook.prototype = {
|
|||||||
this.emit('selection', null);
|
this.emit('selection', null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let [child, labelBox] = this._tabs[index];
|
let [child, labelBox, scrollview] = this._tabs[index];
|
||||||
labelBox.padding = 1;
|
labelBox.padding = 1;
|
||||||
labelBox.border = 1;
|
labelBox.border = 1;
|
||||||
child.show();
|
scrollview.show();
|
||||||
this._selectedIndex = index;
|
this._selectedIndex = index;
|
||||||
this.emit('selection', child);
|
this.emit('selection', child);
|
||||||
},
|
},
|
||||||
@@ -109,7 +101,7 @@ Notebook.prototype = {
|
|||||||
this.selectIndex(-1);
|
this.selectIndex(-1);
|
||||||
else {
|
else {
|
||||||
for (let i = 0; i < this._tabs.length; i++) {
|
for (let i = 0; i < this._tabs.length; i++) {
|
||||||
let [tabChild, labelBox] = this._tabs[i];
|
let [tabChild, labelBox, scrollview] = this._tabs[i];
|
||||||
if (tabChild == child) {
|
if (tabChild == child) {
|
||||||
this.selectIndex(i);
|
this.selectIndex(i);
|
||||||
return;
|
return;
|
||||||
@@ -131,20 +123,19 @@ Result.prototype = {
|
|||||||
|
|
||||||
this.actor = new Big.Box();
|
this.actor = new Big.Box();
|
||||||
|
|
||||||
let cmdTxt = new Clutter.Text({ color: MATRIX_GREEN,
|
let cmdTxt = new St.Label({ text: command });
|
||||||
font_name: MATRIX_FONT,
|
cmdTxt.ellipsize = Pango.EllipsizeMode.END;
|
||||||
ellipsize: Pango.EllipsizeMode.END,
|
|
||||||
text: command });
|
|
||||||
this.actor.append(cmdTxt, Big.BoxPackFlags.NONE);
|
this.actor.append(cmdTxt, Big.BoxPackFlags.NONE);
|
||||||
let resultTxt = new Clutter.Text({ color: MATRIX_GREEN,
|
let resultTxt = new St.Label({ text: "r(" + index + ") = " + o });
|
||||||
font_name: MATRIX_FONT,
|
resultTxt.ellipsize = Pango.EllipsizeMode.END;
|
||||||
ellipsize: Pango.EllipsizeMode.END,
|
|
||||||
text: "r(" + index + ") = " + o });
|
|
||||||
this.actor.append(resultTxt, Big.BoxPackFlags.NONE);
|
this.actor.append(resultTxt, Big.BoxPackFlags.NONE);
|
||||||
let line = new Big.Box({ border_color: GREY,
|
let line = new Clutter.Rectangle({ name: "Separator",
|
||||||
border_bottom: 1,
|
height: 1 });
|
||||||
height: 8 });
|
let padBin = new St.Bin({ name: "Separator", x_fill: true, y_fill: true });
|
||||||
this.actor.append(line, Big.BoxPackFlags.NONE);
|
padBin.add_actor(line);
|
||||||
|
this.actor.append(padBin, Big.BoxPackFlags.NONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,17 +150,14 @@ ActorHierarchy.prototype = {
|
|||||||
|
|
||||||
this._parentList = [];
|
this._parentList = [];
|
||||||
|
|
||||||
this.actor = new Big.Box({ spacing: 4,
|
this.actor = new St.BoxLayout({ name: "ActorHierarchy", vertical: true });
|
||||||
border: 1,
|
|
||||||
padding: 4,
|
|
||||||
border_color: GREY });
|
|
||||||
},
|
},
|
||||||
|
|
||||||
setTarget: function(actor) {
|
setTarget: function(actor) {
|
||||||
this._previousTarget = this._target;
|
this._previousTarget = this._target;
|
||||||
this.target = actor;
|
this.target = actor;
|
||||||
|
|
||||||
this.actor.remove_all();
|
this.actor.get_children().forEach(function (child) { child.destroy(); });
|
||||||
|
|
||||||
if (!(actor instanceof Clutter.Actor))
|
if (!(actor instanceof Clutter.Actor))
|
||||||
return;
|
return;
|
||||||
@@ -182,11 +170,9 @@ ActorHierarchy.prototype = {
|
|||||||
while ((parent = parent.get_parent()) != null) {
|
while ((parent = parent.get_parent()) != null) {
|
||||||
this._parentList.push(parent);
|
this._parentList.push(parent);
|
||||||
|
|
||||||
let link = new Clutter.Text({ color: MATRIX_GREEN,
|
let link = new St.Label({ reactive: true,
|
||||||
font_name: MATRIX_FONT,
|
text: "" + parent });
|
||||||
reactive: true,
|
this.actor.add_actor(link);
|
||||||
text: "" + parent });
|
|
||||||
this.actor.append(link, Big.BoxPackFlags.IF_FITS);
|
|
||||||
let parentTarget = parent;
|
let parentTarget = parent;
|
||||||
link.connect('button-press-event', Lang.bind(this, function () {
|
link.connect('button-press-event', Lang.bind(this, function () {
|
||||||
this._selectByActor(parentTarget);
|
this._selectByActor(parentTarget);
|
||||||
@@ -215,16 +201,13 @@ PropertyInspector.prototype = {
|
|||||||
|
|
||||||
this._parentList = [];
|
this._parentList = [];
|
||||||
|
|
||||||
this.actor = new Big.Box({ spacing: 4,
|
this.actor = new St.BoxLayout({ name: "PropertyInspector", vertical: true });
|
||||||
border: 1,
|
|
||||||
padding: 4,
|
|
||||||
border_color: GREY });
|
|
||||||
},
|
},
|
||||||
|
|
||||||
setTarget: function(actor) {
|
setTarget: function(actor) {
|
||||||
this.target = actor;
|
this.target = actor;
|
||||||
|
|
||||||
this.actor.remove_all();
|
this.actor.get_children().forEach(function (child) { child.destroy(); });
|
||||||
|
|
||||||
for (let propName in actor) {
|
for (let propName in actor) {
|
||||||
let valueStr;
|
let valueStr;
|
||||||
@@ -234,11 +217,9 @@ PropertyInspector.prototype = {
|
|||||||
valueStr = '<error>';
|
valueStr = '<error>';
|
||||||
}
|
}
|
||||||
let propText = propName + ": " + valueStr;
|
let propText = propName + ": " + valueStr;
|
||||||
let propDisplay = new Clutter.Text({ color: MATRIX_GREEN,
|
let propDisplay = new St.Label({ reactive: true,
|
||||||
font_name: MATRIX_FONT,
|
text: propText });
|
||||||
reactive: true,
|
this.actor.add_actor(propDisplay);
|
||||||
text: propText });
|
|
||||||
this.actor.append(propDisplay, Big.BoxPackFlags.IF_FITS);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -249,22 +230,17 @@ function Inspector() {
|
|||||||
|
|
||||||
Inspector.prototype = {
|
Inspector.prototype = {
|
||||||
_init: function() {
|
_init: function() {
|
||||||
let global = Shell.Global.get();
|
|
||||||
let width = 150;
|
let width = 150;
|
||||||
let eventHandler = new Big.Box({ background_color: LG_BACKGROUND_COLOR,
|
let eventHandler = new St.BoxLayout({ name: "LookingGlassDialog",
|
||||||
border: 1,
|
vertical: false,
|
||||||
border_color: LG_BORDER_COLOR,
|
y: Math.floor(global.stage.height/2),
|
||||||
corner_radius: 4,
|
reactive: true });
|
||||||
y: global.stage.height/2,
|
|
||||||
reactive: true
|
|
||||||
});
|
|
||||||
eventHandler.connect('notify::allocation', Lang.bind(this, function () {
|
eventHandler.connect('notify::allocation', Lang.bind(this, function () {
|
||||||
eventHandler.x = Math.floor((global.stage.width)/2 - (eventHandler.width)/2);
|
eventHandler.x = Math.floor((global.stage.width)/2 - (eventHandler.width)/2);
|
||||||
}));
|
}));
|
||||||
global.stage.add_actor(eventHandler);
|
global.stage.add_actor(eventHandler);
|
||||||
let displayText = new Clutter.Text({ color: MATRIX_GREEN,
|
let displayText = new St.Label();
|
||||||
font_name: MATRIX_FONT, text: '' });
|
eventHandler.add(displayText, { expand: true });
|
||||||
eventHandler.append(displayText, Big.BoxPackFlags.EXPAND);
|
|
||||||
|
|
||||||
let borderPaintTarget = null;
|
let borderPaintTarget = null;
|
||||||
let borderPaintId = null;
|
let borderPaintId = null;
|
||||||
@@ -274,7 +250,6 @@ Inspector.prototype = {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
eventHandler.connect('button-press-event', Lang.bind(this, function (actor, event) {
|
eventHandler.connect('button-press-event', Lang.bind(this, function (actor, event) {
|
||||||
let global = Shell.Global.get();
|
|
||||||
Clutter.ungrab_pointer(eventHandler);
|
Clutter.ungrab_pointer(eventHandler);
|
||||||
|
|
||||||
let [stageX, stageY] = event.get_coords();
|
let [stageX, stageY] = event.get_coords();
|
||||||
@@ -288,7 +263,6 @@ Inspector.prototype = {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
eventHandler.connect('motion-event', Lang.bind(this, function (actor, event) {
|
eventHandler.connect('motion-event', Lang.bind(this, function (actor, event) {
|
||||||
let global = Shell.Global.get();
|
|
||||||
let [stageX, stageY] = event.get_coords();
|
let [stageX, stageY] = event.get_coords();
|
||||||
let target = global.stage.get_actor_at_pos(Clutter.PickMode.ALL,
|
let target = global.stage.get_actor_at_pos(Clutter.PickMode.ALL,
|
||||||
stageX,
|
stageX,
|
||||||
@@ -312,8 +286,6 @@ function LookingGlass() {
|
|||||||
|
|
||||||
LookingGlass.prototype = {
|
LookingGlass.prototype = {
|
||||||
_init : function() {
|
_init : function() {
|
||||||
let global = Shell.Global.get();
|
|
||||||
|
|
||||||
this._idleHistorySaveId = 0;
|
this._idleHistorySaveId = 0;
|
||||||
let historyPath = global.configdir + "/lookingglass-history.txt";
|
let historyPath = global.configdir + "/lookingglass-history.txt";
|
||||||
this._historyFile = Gio.file_new_for_path(historyPath);
|
this._historyFile = Gio.file_new_for_path(historyPath);
|
||||||
@@ -327,29 +299,26 @@ LookingGlass.prototype = {
|
|||||||
this._offset = 0;
|
this._offset = 0;
|
||||||
this._results = [];
|
this._results = [];
|
||||||
|
|
||||||
// TODO replace with scrolling or something better
|
// Sort of magic, but...eh.
|
||||||
this._maxItems = 10;
|
this._maxItems = 150;
|
||||||
|
|
||||||
|
this.actor = new St.BoxLayout({ name: "LookingGlassDialog",
|
||||||
|
vertical: true,
|
||||||
|
visible: false });
|
||||||
|
|
||||||
|
let gconf = Shell.GConf.get_default();
|
||||||
|
gconf.watch_directory("/desktop/gnome/interface");
|
||||||
|
gconf.connect("changed::/desktop/gnome/interface/monospace_font_name",
|
||||||
|
Lang.bind(this, this._updateFont));
|
||||||
|
this._updateFont();
|
||||||
|
|
||||||
this.actor = new Big.Box({ background_color: LG_BACKGROUND_COLOR,
|
|
||||||
border: 1,
|
|
||||||
border_color: LG_BORDER_COLOR,
|
|
||||||
corner_radius: 4,
|
|
||||||
padding_top: 8,
|
|
||||||
padding_left: 4,
|
|
||||||
padding_right: 4,
|
|
||||||
padding_bottom: 4,
|
|
||||||
spacing: 4,
|
|
||||||
visible: false
|
|
||||||
});
|
|
||||||
global.stage.add_actor(this.actor);
|
global.stage.add_actor(this.actor);
|
||||||
|
|
||||||
let toolbar = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
let toolbar = new St.BoxLayout({ name: "Toolbar" });
|
||||||
border: 1, border_color: GREY,
|
this.actor.add_actor(toolbar);
|
||||||
corner_radius: 4 });
|
|
||||||
this.actor.append(toolbar, Big.BoxPackFlags.NONE);
|
|
||||||
let inspectIcon = Shell.TextureCache.get_default().load_gicon(new Gio.ThemedIcon({ name: 'gtk-color-picker' }),
|
let inspectIcon = Shell.TextureCache.get_default().load_gicon(new Gio.ThemedIcon({ name: 'gtk-color-picker' }),
|
||||||
24);
|
24);
|
||||||
toolbar.append(inspectIcon, Big.BoxPackFlags.NONE);
|
toolbar.add_actor(inspectIcon);
|
||||||
inspectIcon.reactive = true;
|
inspectIcon.reactive = true;
|
||||||
inspectIcon.connect('button-press-event', Lang.bind(this, function () {
|
inspectIcon.connect('button-press-event', Lang.bind(this, function () {
|
||||||
let inspector = new Inspector();
|
let inspector = new Inspector();
|
||||||
@@ -367,32 +336,27 @@ LookingGlass.prototype = {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
let notebook = new Notebook();
|
let notebook = new Notebook();
|
||||||
this.actor.append(notebook.actor, Big.BoxPackFlags.EXPAND);
|
this.actor.add(notebook.actor, { expand: true });
|
||||||
toolbar.append(notebook.tabControls, Big.BoxPackFlags.END);
|
|
||||||
|
|
||||||
this._evalBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
let emptyBox = new St.Bin();
|
||||||
spacing: 4 });
|
toolbar.add(emptyBox, { expand: true });
|
||||||
|
toolbar.add_actor(notebook.tabControls);
|
||||||
|
|
||||||
|
this._evalBox = new St.BoxLayout({ name: "EvalBox", vertical: true });
|
||||||
notebook.appendPage('Evaluator', this._evalBox);
|
notebook.appendPage('Evaluator', this._evalBox);
|
||||||
|
|
||||||
this._resultsArea = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
this._resultsArea = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
||||||
spacing: 4 });
|
spacing: 4 });
|
||||||
this._evalBox.append(this._resultsArea, Big.BoxPackFlags.EXPAND);
|
this._evalBox.add(this._resultsArea, { expand: true });
|
||||||
|
|
||||||
let entryArea = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL });
|
let entryArea = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL });
|
||||||
this._evalBox.append(entryArea, Big.BoxPackFlags.NONE);
|
this._evalBox.add_actor(entryArea);
|
||||||
|
|
||||||
let label = new Clutter.Text({ color: MATRIX_GREEN,
|
let label = new St.Label({ text: 'js>>> ' });
|
||||||
font_name: MATRIX_FONT,
|
|
||||||
text: 'js>>> ' });
|
|
||||||
entryArea.append(label, Big.BoxPackFlags.NONE);
|
entryArea.append(label, Big.BoxPackFlags.NONE);
|
||||||
|
|
||||||
this._entry = new Clutter.Text({ color: MATRIX_GREEN,
|
this._entry = new St.Entry();
|
||||||
font_name: MATRIX_FONT,
|
/* unmapping the edit box will un-focus it, undo that */
|
||||||
editable: true,
|
|
||||||
activatable: true,
|
|
||||||
singleLineMode: true,
|
|
||||||
text: ''});
|
|
||||||
/* kind of a hack */
|
|
||||||
notebook.connect('selection', Lang.bind(this, function (nb, child) {
|
notebook.connect('selection', Lang.bind(this, function (nb, child) {
|
||||||
if (child == this._evalBox)
|
if (child == this._evalBox)
|
||||||
global.stage.set_key_focus(this._entry);
|
global.stage.set_key_focus(this._entry);
|
||||||
@@ -409,7 +373,7 @@ LookingGlass.prototype = {
|
|||||||
notebook.selectIndex(0);
|
notebook.selectIndex(0);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
this._entry.connect('activate', Lang.bind(this, function (o, e) {
|
this._entry.clutter_text.connect('activate', Lang.bind(this, function (o, e) {
|
||||||
let text = o.get_text();
|
let text = o.get_text();
|
||||||
// Ensure we don't get newlines in the command; the history file is
|
// Ensure we don't get newlines in the command; the history file is
|
||||||
// newline-separated.
|
// newline-separated.
|
||||||
@@ -422,8 +386,8 @@ LookingGlass.prototype = {
|
|||||||
this._historyNavIndex = -1;
|
this._historyNavIndex = -1;
|
||||||
return true;
|
return true;
|
||||||
}));
|
}));
|
||||||
this._entry.connect('key-press-event', Lang.bind(this, function(o, e) {
|
this._entry.clutter_text.connect('key-press-event', Lang.bind(this, function(o, e) {
|
||||||
let symbol = Shell.get_event_key_symbol(e);
|
let symbol = e.get_key_symbol();
|
||||||
if (symbol == Clutter.Escape) {
|
if (symbol == Clutter.Escape) {
|
||||||
this.close();
|
this.close();
|
||||||
return true;
|
return true;
|
||||||
@@ -452,6 +416,19 @@ LookingGlass.prototype = {
|
|||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_updateFont: function() {
|
||||||
|
let gconf = Shell.GConf.get_default();
|
||||||
|
let fontName = gconf.get_string("/desktop/gnome/interface/monospace_font_name");
|
||||||
|
// This is mishandled by the scanner - should by Pango.FontDescription_from_string(fontName);
|
||||||
|
// https://bugzilla.gnome.org/show_bug.cgi?id=595889
|
||||||
|
let fontDesc = Pango.Font.description_from_string(fontName);
|
||||||
|
// We ignore everything but size and style; you'd be crazy to set your system-wide
|
||||||
|
// monospace font to be bold/oblique/etc. Could easily be added here.
|
||||||
|
this.actor.style =
|
||||||
|
'font-size: ' + fontDesc.get_size() / 1024. + (fontDesc.get_size_is_absolute() ? 'px' : 'pt') + ';'
|
||||||
|
+ 'font-family: "' + fontDesc.get_family() + '";';
|
||||||
|
},
|
||||||
|
|
||||||
_readHistory: function () {
|
_readHistory: function () {
|
||||||
if (!this._historyFile.query_exists(null))
|
if (!this._historyFile.query_exists(null))
|
||||||
return;
|
return;
|
||||||
@@ -524,8 +501,7 @@ LookingGlass.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
_resizeTo: function(actor) {
|
_resizeTo: function(actor) {
|
||||||
let stage = Shell.Global.get().stage;
|
let stage = global.stage;
|
||||||
let stageWidth = stage.width;
|
|
||||||
let myWidth = stage.width * 0.7;
|
let myWidth = stage.width * 0.7;
|
||||||
let myHeight = stage.height * 0.7;
|
let myHeight = stage.height * 0.7;
|
||||||
let [srcX, srcY] = actor.get_transformed_position();
|
let [srcX, srcY] = actor.get_transformed_position();
|
||||||
@@ -549,16 +525,15 @@ LookingGlass.prototype = {
|
|||||||
if (this._open)
|
if (this._open)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!Main.pushModal(this.actor))
|
||||||
|
return;
|
||||||
|
|
||||||
this.actor.show();
|
this.actor.show();
|
||||||
this.actor.lower(Main.chrome.actor);
|
this.actor.lower(Main.chrome.actor);
|
||||||
this._open = true;
|
this._open = true;
|
||||||
|
|
||||||
Tweener.removeTweens(this.actor);
|
Tweener.removeTweens(this.actor);
|
||||||
|
|
||||||
if (!Main.beginModal())
|
|
||||||
return;
|
|
||||||
|
|
||||||
let global = Shell.Global.get();
|
|
||||||
global.stage.set_key_focus(this._entry);
|
global.stage.set_key_focus(this._entry);
|
||||||
|
|
||||||
Tweener.addTween(this.actor, { time: 0.5,
|
Tweener.addTween(this.actor, { time: 0.5,
|
||||||
@@ -575,7 +550,7 @@ LookingGlass.prototype = {
|
|||||||
this._open = false;
|
this._open = false;
|
||||||
Tweener.removeTweens(this.actor);
|
Tweener.removeTweens(this.actor);
|
||||||
|
|
||||||
Main.endModal();
|
Main.popModal(this.actor);
|
||||||
|
|
||||||
Tweener.addTween(this.actor, { time: 0.5,
|
Tweener.addTween(this.actor, { time: 0.5,
|
||||||
transition: "easeOutQuad",
|
transition: "easeOutQuad",
|
||||||
|
|||||||
204
js/ui/main.js
@@ -1,6 +1,7 @@
|
|||||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
const Clutter = imports.gi.Clutter;
|
const Clutter = imports.gi.Clutter;
|
||||||
|
const DBus = imports.dbus;
|
||||||
const Gdk = imports.gi.Gdk;
|
const Gdk = imports.gi.Gdk;
|
||||||
const Gio = imports.gi.Gio;
|
const Gio = imports.gi.Gio;
|
||||||
const GLib = imports.gi.GLib;
|
const GLib = imports.gi.GLib;
|
||||||
@@ -9,14 +10,16 @@ const Mainloop = imports.mainloop;
|
|||||||
const Meta = imports.gi.Meta;
|
const Meta = imports.gi.Meta;
|
||||||
const Shell = imports.gi.Shell;
|
const Shell = imports.gi.Shell;
|
||||||
const Signals = imports.signals;
|
const Signals = imports.signals;
|
||||||
|
const St = imports.gi.St;
|
||||||
|
|
||||||
const Chrome = imports.ui.chrome;
|
const Chrome = imports.ui.chrome;
|
||||||
|
const Environment = imports.ui.environment;
|
||||||
const Overview = imports.ui.overview;
|
const Overview = imports.ui.overview;
|
||||||
const Panel = imports.ui.panel;
|
const Panel = imports.ui.panel;
|
||||||
const RunDialog = imports.ui.runDialog;
|
const RunDialog = imports.ui.runDialog;
|
||||||
const LookingGlass = imports.ui.lookingGlass;
|
const LookingGlass = imports.ui.lookingGlass;
|
||||||
|
const ShellDBus = imports.ui.shellDBus;
|
||||||
const Sidebar = imports.ui.sidebar;
|
const Sidebar = imports.ui.sidebar;
|
||||||
const Tweener = imports.ui.tweener;
|
|
||||||
const WindowManager = imports.ui.windowManager;
|
const WindowManager = imports.ui.windowManager;
|
||||||
|
|
||||||
const DEFAULT_BACKGROUND_COLOR = new Clutter.Color();
|
const DEFAULT_BACKGROUND_COLOR = new Clutter.Color();
|
||||||
@@ -30,16 +33,27 @@ let runDialog = null;
|
|||||||
let lookingGlass = null;
|
let lookingGlass = null;
|
||||||
let wm = null;
|
let wm = null;
|
||||||
let recorder = null;
|
let recorder = null;
|
||||||
let inModal = false;
|
let shellDBusService = null;
|
||||||
|
let modalCount = 0;
|
||||||
|
let modalActorFocusStack = [];
|
||||||
|
|
||||||
function start() {
|
function start() {
|
||||||
let global = Shell.Global.get();
|
// Add a binding for "global" in the global JS namespace; (gjs
|
||||||
|
// keeps the web browser convention of having that namespace be
|
||||||
|
// called "window".)
|
||||||
|
window.global = Shell.Global.get();
|
||||||
|
|
||||||
Gio.DesktopAppInfo.set_desktop_env("GNOME");
|
Gio.DesktopAppInfo.set_desktop_env("GNOME");
|
||||||
|
|
||||||
global.grab_dbus_service();
|
global.grab_dbus_service();
|
||||||
|
shellDBusService = new ShellDBus.GnomeShell();
|
||||||
|
// Force a connection now; dbus.js will do this internally
|
||||||
|
// if we use its name acquisition stuff but we aren't right
|
||||||
|
// now; to do so we'd need to convert from its async calls
|
||||||
|
// back into sync ones.
|
||||||
|
DBus.session.flush();
|
||||||
|
|
||||||
Tweener.init();
|
Environment.init();
|
||||||
|
|
||||||
// Ensure ShellAppMonitor is initialized; this will
|
// Ensure ShellAppMonitor is initialized; this will
|
||||||
// also initialize ShellAppSystem first. ShellAppSystem
|
// also initialize ShellAppSystem first. ShellAppSystem
|
||||||
@@ -62,12 +76,23 @@ function start() {
|
|||||||
for (let i = 0; i < children.length; i++)
|
for (let i = 0; i < children.length; i++)
|
||||||
children[i].destroy();
|
children[i].destroy();
|
||||||
|
|
||||||
|
let themeContext = St.ThemeContext.get_for_stage (global.stage);
|
||||||
|
let stylesheetPath = global.datadir + "/theme/gnome-shell.css";
|
||||||
|
let theme = new St.Theme ({ application_stylesheet: stylesheetPath });
|
||||||
|
themeContext.set_theme (theme);
|
||||||
|
|
||||||
global.connect('panel-run-dialog', function(panel) {
|
global.connect('panel-run-dialog', function(panel) {
|
||||||
// Make sure not more than one run dialog is shown.
|
// Make sure not more than one run dialog is shown.
|
||||||
if (runDialog == null) {
|
getRunDialog().open();
|
||||||
runDialog = new RunDialog.RunDialog();
|
});
|
||||||
}
|
let shellwm = global.window_manager;
|
||||||
runDialog.open();
|
shellwm.takeover_keybinding("panel_main_menu");
|
||||||
|
shellwm.connect("keybinding::panel_main_menu", function () {
|
||||||
|
overview.toggle();
|
||||||
|
});
|
||||||
|
shellwm.takeover_keybinding("panel_run_dialog");
|
||||||
|
shellwm.connect("keybinding::panel_run_dialog", function () {
|
||||||
|
getRunDialog().open();
|
||||||
});
|
});
|
||||||
|
|
||||||
overview = new Overview.Overview();
|
overview = new Overview.Overview();
|
||||||
@@ -102,7 +127,6 @@ function start() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function _relayout() {
|
function _relayout() {
|
||||||
let global = Shell.Global.get();
|
|
||||||
panel.actor.set_size(global.screen_width, Panel.PANEL_HEIGHT);
|
panel.actor.set_size(global.screen_width, Panel.PANEL_HEIGHT);
|
||||||
overview.relayout();
|
overview.relayout();
|
||||||
}
|
}
|
||||||
@@ -114,8 +138,6 @@ function _relayout() {
|
|||||||
// is called.)
|
// is called.)
|
||||||
function _removeUnusedWorkspaces() {
|
function _removeUnusedWorkspaces() {
|
||||||
|
|
||||||
let global = Shell.Global.get();
|
|
||||||
|
|
||||||
let windows = global.get_windows();
|
let windows = global.get_windows();
|
||||||
let maxWorkspace = 0;
|
let maxWorkspace = 0;
|
||||||
for (let i = 0; i < windows.length; i++) {
|
for (let i = 0; i < windows.length; i++) {
|
||||||
@@ -149,13 +171,13 @@ function _removeUnusedWorkspaces() {
|
|||||||
// should be asking Mutter to resolve the key into an action and then
|
// should be asking Mutter to resolve the key into an action and then
|
||||||
// base our handling based on the action.
|
// base our handling based on the action.
|
||||||
function _globalKeyPressHandler(actor, event) {
|
function _globalKeyPressHandler(actor, event) {
|
||||||
if (!inModal)
|
if (modalCount == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
let type = event.type();
|
let type = event.type();
|
||||||
|
|
||||||
if (type == Clutter.EventType.KEY_PRESS) {
|
if (type == Clutter.EventType.KEY_PRESS) {
|
||||||
let symbol = Shell.get_event_key_symbol (event);
|
let symbol = event.get_key_symbol();
|
||||||
if (symbol == Clutter.Print) {
|
if (symbol == Clutter.Print) {
|
||||||
// We want to be able to take screenshots of the shell at all times
|
// We want to be able to take screenshots of the shell at all times
|
||||||
let gconf = Shell.GConf.get_default();
|
let gconf = Shell.GConf.get_default();
|
||||||
@@ -169,7 +191,7 @@ function _globalKeyPressHandler(actor, event) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else if (type == Clutter.EventType.KEY_RELEASE) {
|
} else if (type == Clutter.EventType.KEY_RELEASE) {
|
||||||
let symbol = Shell.get_event_key_symbol (event);
|
let symbol = event.get_key_symbol();
|
||||||
if (symbol == Clutter.Super_L || symbol == Clutter.Super_R) {
|
if (symbol == Clutter.Super_L || symbol == Clutter.Super_R) {
|
||||||
// The super key is the default for triggering the overview, and should
|
// The super key is the default for triggering the overview, and should
|
||||||
// get us out of the overview when we are already in it.
|
// get us out of the overview when we are already in it.
|
||||||
@@ -177,35 +199,96 @@ function _globalKeyPressHandler(actor, event) {
|
|||||||
overview.hide();
|
overview.hide();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
} else if (symbol == Clutter.F2 && (event.get_state() & Clutter.ModifierType.MOD1_MASK)) {
|
||||||
|
getRunDialog().open();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used to go into a mode where all keyboard and mouse input goes to
|
function _findModal(actor) {
|
||||||
// the stage. Returns true if we successfully grabbed the keyboard and
|
for (let i = 0; i < modalActorFocusStack.length; i++) {
|
||||||
// went modal, false otherwise
|
let [stackActor, stackFocus] = modalActorFocusStack[i];
|
||||||
function beginModal() {
|
if (stackActor == actor) {
|
||||||
let global = Shell.Global.get();
|
return i;
|
||||||
let timestamp = global.screen.get_display().get_current_time();
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pushModal:
|
||||||
|
* @actor: #ClutterActor which will be given keyboard focus
|
||||||
|
*
|
||||||
|
* Ensure we are in a mode where all keyboard and mouse input goes to
|
||||||
|
* the stage. Multiple calls to this function act in a stacking fashion;
|
||||||
|
* the effect will be undone when an equal number of popModal() invocations
|
||||||
|
* have been made.
|
||||||
|
*
|
||||||
|
* Next, record the current Clutter keyboard focus on a stack. If the modal stack
|
||||||
|
* returns to this actor, reset the focus to the actor which was focused
|
||||||
|
* at the time pushModal() was invoked.
|
||||||
|
*
|
||||||
|
* Returns: true iff we successfully acquired a grab or already had one
|
||||||
|
*/
|
||||||
|
function pushModal(actor) {
|
||||||
|
if (modalCount == 0) {
|
||||||
|
if (!global.begin_modal(currentTime())) {
|
||||||
|
log("pushModal: invocation of begin_modal failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!global.begin_modal(timestamp))
|
|
||||||
return false;
|
|
||||||
global.set_stage_input_mode(Shell.StageInputMode.FULLSCREEN);
|
global.set_stage_input_mode(Shell.StageInputMode.FULLSCREEN);
|
||||||
|
|
||||||
inModal = true;
|
modalCount += 1;
|
||||||
|
actor.connect('destroy', function() {
|
||||||
|
let index = _findModal(actor);
|
||||||
|
if (index >= 0)
|
||||||
|
modalActorFocusStack.splice(index, 1);
|
||||||
|
});
|
||||||
|
let curFocus = global.stage.get_key_focus();
|
||||||
|
if (curFocus != null) {
|
||||||
|
curFocus.connect('destroy', function() {
|
||||||
|
let index = _findModal(actor);
|
||||||
|
if (index >= 0)
|
||||||
|
modalActorFocusStack[index][1] = null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
modalActorFocusStack.push([actor, curFocus]);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function endModal() {
|
/**
|
||||||
let global = Shell.Global.get();
|
* popModal:
|
||||||
let timestamp = global.screen.get_display().get_current_time();
|
* @actor: #ClutterActor passed to original invocation of pushModal().
|
||||||
|
*
|
||||||
|
* Reverse the effect of pushModal(). If this invocation is undoing
|
||||||
|
* the topmost invocation, then the focus will be restored to the
|
||||||
|
* previous focus at the time when pushModal() was invoked.
|
||||||
|
*/
|
||||||
|
function popModal(actor) {
|
||||||
|
modalCount -= 1;
|
||||||
|
let focusIndex = _findModal(actor);
|
||||||
|
if (focusIndex >= 0) {
|
||||||
|
if (focusIndex == modalActorFocusStack.length - 1) {
|
||||||
|
let [stackActor, stackFocus] = modalActorFocusStack[focusIndex];
|
||||||
|
global.stage.set_key_focus(stackFocus);
|
||||||
|
} else {
|
||||||
|
// Remove from the middle, shift the focus chain up
|
||||||
|
for (let i = focusIndex; i < modalActorFocusStack.length - 1; i++) {
|
||||||
|
modalActorFocusStack[i + 1][1] = modalActorFocusStack[i][1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
modalActorFocusStack.splice(focusIndex, 1);
|
||||||
|
}
|
||||||
|
if (modalCount > 0)
|
||||||
|
return;
|
||||||
|
|
||||||
global.end_modal(timestamp);
|
global.end_modal(currentTime());
|
||||||
global.set_stage_input_mode(Shell.StageInputMode.NORMAL);
|
global.set_stage_input_mode(Shell.StageInputMode.NORMAL);
|
||||||
inModal = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function createLookingGlass() {
|
function createLookingGlass() {
|
||||||
@@ -216,17 +299,70 @@ function createLookingGlass() {
|
|||||||
return lookingGlass;
|
return lookingGlass;
|
||||||
}
|
}
|
||||||
|
|
||||||
function createAppLaunchContext() {
|
function getRunDialog() {
|
||||||
let global = Shell.Global.get();
|
if (runDialog == null) {
|
||||||
let screen = global.screen;
|
runDialog = new RunDialog.RunDialog();
|
||||||
let display = screen.get_display();
|
}
|
||||||
|
return runDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createAppLaunchContext() {
|
||||||
let context = new Gdk.AppLaunchContext();
|
let context = new Gdk.AppLaunchContext();
|
||||||
context.set_timestamp(display.get_current_time());
|
context.set_timestamp(currentTime());
|
||||||
|
|
||||||
// Make sure that the app is opened on the current workspace even if
|
// Make sure that the app is opened on the current workspace even if
|
||||||
// the user switches before it starts
|
// the user switches before it starts
|
||||||
context.set_desktop(screen.get_active_workspace_index());
|
context.set_desktop(global.screen.get_active_workspace_index());
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* currentTime:
|
||||||
|
*
|
||||||
|
* Gets the current X server time from the current Clutter, Gdk, or X
|
||||||
|
* event. If called from outside an event handler, this may return
|
||||||
|
* %Clutter.CURRENT_TIME (aka 0), or it may return a slightly
|
||||||
|
* out-of-date timestamp.
|
||||||
|
*/
|
||||||
|
function currentTime() {
|
||||||
|
// meta_display_get_current_time() will return the correct time
|
||||||
|
// when handling an X or Gdk event, but will return CurrentTime
|
||||||
|
// from some Clutter event callbacks.
|
||||||
|
//
|
||||||
|
// clutter_get_current_event_time() will return the correct time
|
||||||
|
// from a Clutter event callback, but may return an out-of-date
|
||||||
|
// timestamp if called at other times.
|
||||||
|
//
|
||||||
|
// So we try meta_display_get_current_time() first, since we
|
||||||
|
// can recognize a "wrong" answer from that, and then fall back
|
||||||
|
// to clutter_get_current_event_time().
|
||||||
|
|
||||||
|
let time = global.screen.get_display().get_current_time();
|
||||||
|
if (time != Clutter.CURRENT_TIME)
|
||||||
|
return time;
|
||||||
|
|
||||||
|
return Clutter.get_current_event_time();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* activateWindow:
|
||||||
|
* @window: the Meta.Window to activate
|
||||||
|
* @time: (optional) current event time
|
||||||
|
*
|
||||||
|
* Activates @window, switching to its workspace first if necessary
|
||||||
|
*/
|
||||||
|
function activateWindow(window, time) {
|
||||||
|
let activeWorkspaceNum = global.screen.get_active_workspace_index();
|
||||||
|
let windowWorkspaceNum = window.get_workspace().index();
|
||||||
|
|
||||||
|
if (!time)
|
||||||
|
time = currentTime();
|
||||||
|
|
||||||
|
if (windowWorkspaceNum != activeWorkspaceNum) {
|
||||||
|
let workspace = global.screen.get_workspace_by_index(windowWorkspaceNum);
|
||||||
|
workspace.activate_with_focus(window, time);
|
||||||
|
} else {
|
||||||
|
window.activate(time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -39,6 +39,10 @@ const ANIMATION_TIME = 0.25;
|
|||||||
// will take up the remaining sections of the display.
|
// will take up the remaining sections of the display.
|
||||||
|
|
||||||
const WIDE_SCREEN_CUT_OFF_RATIO = 1.4;
|
const WIDE_SCREEN_CUT_OFF_RATIO = 1.4;
|
||||||
|
// A common netbook resolution is 1024x600, which trips the widescreen
|
||||||
|
// ratio. However that leaves way too few pixels for the dash. So
|
||||||
|
// just treat this as a regular screen.
|
||||||
|
const WIDE_SCREEN_MINIMUM_HEIGHT = 768;
|
||||||
|
|
||||||
const COLUMNS_REGULAR_SCREEN = 4;
|
const COLUMNS_REGULAR_SCREEN = 4;
|
||||||
const ROWS_REGULAR_SCREEN = 8;
|
const ROWS_REGULAR_SCREEN = 8;
|
||||||
@@ -73,6 +77,7 @@ const NUMBER_OF_SECTIONS_IN_SEARCH = 2;
|
|||||||
let wideScreen = false;
|
let wideScreen = false;
|
||||||
let displayGridColumnWidth = null;
|
let displayGridColumnWidth = null;
|
||||||
let displayGridRowHeight = null;
|
let displayGridRowHeight = null;
|
||||||
|
let addRemoveButtonSize = null;
|
||||||
|
|
||||||
function Overview() {
|
function Overview() {
|
||||||
this._init();
|
this._init();
|
||||||
@@ -80,10 +85,6 @@ function Overview() {
|
|||||||
|
|
||||||
Overview.prototype = {
|
Overview.prototype = {
|
||||||
_init : function() {
|
_init : function() {
|
||||||
let me = this;
|
|
||||||
|
|
||||||
let global = Shell.Global.get();
|
|
||||||
|
|
||||||
this._group = new Clutter.Group();
|
this._group = new Clutter.Group();
|
||||||
this._group._delegate = this;
|
this._group._delegate = this;
|
||||||
|
|
||||||
@@ -95,7 +96,15 @@ Overview.prototype = {
|
|||||||
|
|
||||||
this._activeDisplayPane = null;
|
this._activeDisplayPane = null;
|
||||||
|
|
||||||
// Used to catch any clicks when we have an active pane; see the comments
|
// During transitions, we raise this to the top to avoid having the overview
|
||||||
|
// area be reactive; it causes too many issues such as double clicks on
|
||||||
|
// Dash elements, or mouseover handlers in the workspaces.
|
||||||
|
this._coverPane = new Clutter.Rectangle({ opacity: 0,
|
||||||
|
reactive: true });
|
||||||
|
this._group.add_actor(this._coverPane);
|
||||||
|
this._coverPane.connect('event', Lang.bind(this, function (actor, event) { return true; }));
|
||||||
|
|
||||||
|
// Similar to the cover pane but used for dialogs ("panes"); see the comments
|
||||||
// in addPane below.
|
// in addPane below.
|
||||||
this._transparentBackground = new Clutter.Rectangle({ opacity: 0,
|
this._transparentBackground = new Clutter.Rectangle({ opacity: 0,
|
||||||
reactive: true });
|
reactive: true });
|
||||||
@@ -127,13 +136,14 @@ Overview.prototype = {
|
|||||||
this._transparentBackground.lower_bottom();
|
this._transparentBackground.lower_bottom();
|
||||||
this._paneContainer.lower_bottom();
|
this._paneContainer.lower_bottom();
|
||||||
|
|
||||||
|
this._coverPane.lower_bottom();
|
||||||
|
|
||||||
this._workspaces = null;
|
this._workspaces = null;
|
||||||
},
|
},
|
||||||
|
|
||||||
_recalculateGridSizes: function () {
|
_recalculateGridSizes: function () {
|
||||||
let global = Shell.Global.get();
|
wideScreen = (global.screen_width/global.screen_height > WIDE_SCREEN_CUT_OFF_RATIO) &&
|
||||||
|
(global.screen_height >= WIDE_SCREEN_MINIMUM_HEIGHT);
|
||||||
wideScreen = (global.screen_width/global.screen_height > WIDE_SCREEN_CUT_OFF_RATIO);
|
|
||||||
|
|
||||||
// We divide the screen into an imaginary grid which helps us determine the layout of
|
// We divide the screen into an imaginary grid which helps us determine the layout of
|
||||||
// different visual components.
|
// different visual components.
|
||||||
@@ -147,12 +157,14 @@ Overview.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
relayout: function () {
|
relayout: function () {
|
||||||
let global = Shell.Global.get();
|
|
||||||
|
|
||||||
let screenHeight = global.screen_height;
|
let screenHeight = global.screen_height;
|
||||||
let screenWidth = global.screen_width;
|
let screenWidth = global.screen_width;
|
||||||
|
|
||||||
let contentHeight = screenHeight - Panel.PANEL_HEIGHT;
|
let contentY = Panel.PANEL_HEIGHT;
|
||||||
|
let contentHeight = screenHeight - contentY;
|
||||||
|
|
||||||
|
this._coverPane.set_position(0, contentY);
|
||||||
|
this._coverPane.set_size(screenWidth, contentHeight);
|
||||||
|
|
||||||
let workspaceColumnsUsed = wideScreen ? COLUMNS_FOR_WORKSPACES_WIDE_SCREEN : COLUMNS_FOR_WORKSPACES_REGULAR_SCREEN;
|
let workspaceColumnsUsed = wideScreen ? COLUMNS_FOR_WORKSPACES_WIDE_SCREEN : COLUMNS_FOR_WORKSPACES_REGULAR_SCREEN;
|
||||||
let workspaceRowsUsed = wideScreen ? ROWS_FOR_WORKSPACES_WIDE_SCREEN : ROWS_FOR_WORKSPACES_REGULAR_SCREEN;
|
let workspaceRowsUsed = wideScreen ? ROWS_FOR_WORKSPACES_WIDE_SCREEN : ROWS_FOR_WORKSPACES_REGULAR_SCREEN;
|
||||||
@@ -167,22 +179,21 @@ Overview.prototype = {
|
|||||||
this._workspacesX = displayGridColumnWidth + WORKSPACE_GRID_PADDING;
|
this._workspacesX = displayGridColumnWidth + WORKSPACE_GRID_PADDING;
|
||||||
this._workspacesY = displayGridRowHeight + WORKSPACE_GRID_PADDING * (screenHeight / screenWidth);
|
this._workspacesY = displayGridRowHeight + WORKSPACE_GRID_PADDING * (screenHeight / screenWidth);
|
||||||
|
|
||||||
let dashY = Panel.PANEL_HEIGHT;
|
this._dash.actor.set_position(0, contentY);
|
||||||
this._dash.actor.set_position(0, dashY);
|
this._dash.actor.set_size(displayGridColumnWidth, contentHeight);
|
||||||
this._dash.actor.set_size(displayGridColumnWidth, screenHeight - dashY);
|
this._dash.searchArea.height = this._workspacesY - contentY;
|
||||||
this._dash.searchArea.height = this._workspacesY - dashY;
|
|
||||||
this._dash.sectionArea.height = this._workspacesHeight;
|
this._dash.sectionArea.height = this._workspacesHeight;
|
||||||
|
|
||||||
// place the 'Add Workspace' button in the bottom row of the grid
|
// place the 'Add Workspace' button in the bottom row of the grid
|
||||||
this._addButtonSize = Math.floor(displayGridRowHeight * 3/5);
|
addRemoveButtonSize = Math.floor(displayGridRowHeight * 3/5);
|
||||||
this._addButtonX = this._workspacesX + this._workspacesWidth - this._addButtonSize;
|
this._addButtonX = this._workspacesX + this._workspacesWidth - addRemoveButtonSize;
|
||||||
this._addButtonY = screenHeight - Math.floor(displayGridRowHeight * 4/5);
|
this._addButtonY = screenHeight - Math.floor(displayGridRowHeight * 4/5);
|
||||||
|
|
||||||
this._backOver.set_position(0, Panel.PANEL_HEIGHT);
|
this._backOver.set_position(0, contentY);
|
||||||
this._backOver.set_size(global.screen_width, contentHeight);
|
this._backOver.set_size(global.screen_width, contentHeight);
|
||||||
|
|
||||||
this._paneContainer.set_position(this._dash.actor.x + this._dash.actor.width + DEFAULT_PADDING,
|
this._paneContainer.set_position(this._dash.actor.x + this._dash.actor.width + DEFAULT_PADDING,
|
||||||
Panel.PANEL_HEIGHT);
|
contentY);
|
||||||
// Dynamic width
|
// Dynamic width
|
||||||
this._paneContainer.height = contentHeight;
|
this._paneContainer.height = contentHeight;
|
||||||
|
|
||||||
@@ -232,7 +243,7 @@ Overview.prototype = {
|
|||||||
// This allows the user to place the item on any workspace.
|
// This allows the user to place the item on any workspace.
|
||||||
handleDragOver : function(source, actor, x, y, time) {
|
handleDragOver : function(source, actor, x, y, time) {
|
||||||
if (source instanceof GenericDisplay.GenericDisplayItem
|
if (source instanceof GenericDisplay.GenericDisplayItem
|
||||||
|| source instanceof AppDisplay.WellDisplayItem) {
|
|| source instanceof AppDisplay.BaseWellItem) {
|
||||||
if (this._activeDisplayPane != null)
|
if (this._activeDisplayPane != null)
|
||||||
this._activeDisplayPane.close();
|
this._activeDisplayPane.close();
|
||||||
return true;
|
return true;
|
||||||
@@ -271,20 +282,17 @@ Overview.prototype = {
|
|||||||
show : function() {
|
show : function() {
|
||||||
if (this.visible)
|
if (this.visible)
|
||||||
return;
|
return;
|
||||||
if (!Main.beginModal())
|
if (!Main.pushModal(this._dash.actor))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.visible = true;
|
this.visible = true;
|
||||||
this.animationInProgress = true;
|
this.animationInProgress = true;
|
||||||
|
|
||||||
let global = Shell.Global.get();
|
|
||||||
|
|
||||||
this._dash.show();
|
this._dash.show();
|
||||||
|
|
||||||
/* TODO: make this stuff dynamic */
|
/* TODO: make this stuff dynamic */
|
||||||
this._workspaces = new Workspaces.Workspaces(this._workspacesWidth, this._workspacesHeight,
|
this._workspaces = new Workspaces.Workspaces(this._workspacesWidth, this._workspacesHeight,
|
||||||
this._workspacesX, this._workspacesY,
|
this._workspacesX, this._workspacesY);
|
||||||
this._addButtonSize, this._addButtonX, this._addButtonY);
|
|
||||||
this._group.add_actor(this._workspaces.actor);
|
this._group.add_actor(this._workspaces.actor);
|
||||||
|
|
||||||
// The workspaces actor is as big as the screen, so we have to raise the dash above it
|
// The workspaces actor is as big as the screen, so we have to raise the dash above it
|
||||||
@@ -292,6 +300,12 @@ Overview.prototype = {
|
|||||||
// be as big as the screen.
|
// be as big as the screen.
|
||||||
this._dash.actor.raise(this._workspaces.actor);
|
this._dash.actor.raise(this._workspaces.actor);
|
||||||
|
|
||||||
|
// Create (+) button
|
||||||
|
this._addButton = new AddWorkspaceButton(addRemoveButtonSize, this._addButtonX, this._addButtonY, Lang.bind(this, this._acceptNewWorkspaceDrop));
|
||||||
|
this._addButton.actor.connect('button-release-event', Lang.bind(this, this._addNewWorkspace));
|
||||||
|
this._group.add_actor(this._addButton.actor);
|
||||||
|
this._addButton.actor.raise(this._workspaces.actor);
|
||||||
|
|
||||||
// All the the actors in the window group are completely obscured,
|
// All the the actors in the window group are completely obscured,
|
||||||
// hiding the group holding them while the Overview is displayed greatly
|
// hiding the group holding them while the Overview is displayed greatly
|
||||||
// increases performance of the Overview especially when there are many
|
// increases performance of the Overview especially when there are many
|
||||||
@@ -327,15 +341,14 @@ Overview.prototype = {
|
|||||||
time: ANIMATION_TIME
|
time: ANIMATION_TIME
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this._coverPane.raise_top();
|
||||||
this.emit('showing');
|
this.emit('showing');
|
||||||
},
|
},
|
||||||
|
|
||||||
hide : function() {
|
hide: function() {
|
||||||
if (!this.visible || this._hideInProgress)
|
if (!this.visible || this._hideInProgress)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
let global = Shell.Global.get();
|
|
||||||
|
|
||||||
this.animationInProgress = true;
|
this.animationInProgress = true;
|
||||||
this._hideInProgress = true;
|
this._hideInProgress = true;
|
||||||
if (this._activeDisplayPane != null)
|
if (this._activeDisplayPane != null)
|
||||||
@@ -365,6 +378,7 @@ Overview.prototype = {
|
|||||||
time: ANIMATION_TIME
|
time: ANIMATION_TIME
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this._coverPane.raise_top();
|
||||||
this.emit('hiding');
|
this.emit('hiding');
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -375,6 +389,18 @@ Overview.prototype = {
|
|||||||
this.show();
|
this.show();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getWorkspacesForWindow:
|
||||||
|
* @metaWindow: A #MetaWindow
|
||||||
|
*
|
||||||
|
* Returns the Workspaces object associated with the given window.
|
||||||
|
* This method is not be accessible if the overview is not open
|
||||||
|
* and will return %null.
|
||||||
|
*/
|
||||||
|
getWorkspacesForWindow: function(metaWindow) {
|
||||||
|
return this._workspaces;
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* activateWindow:
|
* activateWindow:
|
||||||
* @metaWindow: A #MetaWindow
|
* @metaWindow: A #MetaWindow
|
||||||
@@ -387,7 +413,6 @@ Overview.prototype = {
|
|||||||
*/
|
*/
|
||||||
activateWindow: function (metaWindow, time) {
|
activateWindow: function (metaWindow, time) {
|
||||||
this._workspaces.activateWindowFromOverview(metaWindow, time);
|
this._workspaces.activateWindowFromOverview(metaWindow, time);
|
||||||
this.hide();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
//// Private methods ////
|
//// Private methods ////
|
||||||
@@ -397,13 +422,12 @@ Overview.prototype = {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
this.animationInProgress = false;
|
this.animationInProgress = false;
|
||||||
|
this._coverPane.lower_bottom();
|
||||||
|
|
||||||
this.emit('shown');
|
this.emit('shown');
|
||||||
},
|
},
|
||||||
|
|
||||||
_hideDone: function() {
|
_hideDone: function() {
|
||||||
let global = Shell.Global.get();
|
|
||||||
|
|
||||||
global.window_group.show();
|
global.window_group.show();
|
||||||
|
|
||||||
this._workspaces.destroy();
|
this._workspaces.destroy();
|
||||||
@@ -416,8 +440,47 @@ Overview.prototype = {
|
|||||||
this.animationInProgress = false;
|
this.animationInProgress = false;
|
||||||
this._hideInProgress = false;
|
this._hideInProgress = false;
|
||||||
|
|
||||||
Main.endModal();
|
this._coverPane.lower_bottom();
|
||||||
|
|
||||||
|
Main.popModal(this._dash.actor);
|
||||||
this.emit('hidden');
|
this.emit('hidden');
|
||||||
|
},
|
||||||
|
|
||||||
|
_addNewWorkspace: function() {
|
||||||
|
global.screen.append_new_workspace(false, Main.currentTime());
|
||||||
|
},
|
||||||
|
|
||||||
|
_acceptNewWorkspaceDrop: function(source, dropActor, x, y, time) {
|
||||||
|
this._addNewWorkspace();
|
||||||
|
return this._workspaces.acceptNewWorkspaceDrop(source, dropActor, x, y, time);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Signals.addSignalMethods(Overview.prototype);
|
Signals.addSignalMethods(Overview.prototype);
|
||||||
|
|
||||||
|
function AddWorkspaceButton(buttonSize, buttonX, buttonY, acceptDropCallback) {
|
||||||
|
this._init(buttonSize, buttonX, buttonY, acceptDropCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
AddWorkspaceButton.prototype = {
|
||||||
|
_init: function(buttonSize, buttonX, buttonY, acceptDropCallback) {
|
||||||
|
this.actor = new Clutter.Group({ x: buttonX,
|
||||||
|
y: buttonY,
|
||||||
|
width: global.screen_width - buttonX,
|
||||||
|
height: global.screen_height - buttonY,
|
||||||
|
reactive: true });
|
||||||
|
this.actor._delegate = this;
|
||||||
|
this._acceptDropCallback = acceptDropCallback;
|
||||||
|
|
||||||
|
let plus = new Clutter.Texture({ x: 0,
|
||||||
|
y: 0,
|
||||||
|
width: buttonSize,
|
||||||
|
height: buttonSize });
|
||||||
|
plus.set_from_file(global.imagedir + 'add-workspace.svg');
|
||||||
|
this.actor.add_actor(plus);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Draggable target interface
|
||||||
|
acceptDrop: function(source, actor, x, y, time) {
|
||||||
|
return this._acceptDropCallback(source, actor, x, y, time);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ function AppPanelMenu() {
|
|||||||
|
|
||||||
AppPanelMenu.prototype = {
|
AppPanelMenu.prototype = {
|
||||||
_init: function() {
|
_init: function() {
|
||||||
this._metaDisplay = Shell.Global.get().screen.get_display();
|
this._metaDisplay = global.screen.get_display();
|
||||||
|
|
||||||
this._focusedApp = null;
|
this._focusedApp = null;
|
||||||
this._activeSequence = null;
|
this._activeSequence = null;
|
||||||
@@ -168,8 +168,6 @@ function Panel() {
|
|||||||
|
|
||||||
Panel.prototype = {
|
Panel.prototype = {
|
||||||
_init : function() {
|
_init : function() {
|
||||||
let global = Shell.Global.get();
|
|
||||||
|
|
||||||
|
|
||||||
this.actor = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL
|
this.actor = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL
|
||||||
});
|
});
|
||||||
@@ -269,10 +267,10 @@ Panel.prototype = {
|
|||||||
/* left side */
|
/* left side */
|
||||||
|
|
||||||
this.button = new Button.Button(_("Activities"), PANEL_BUTTON_COLOR, PRESSED_BUTTON_BACKGROUND_COLOR,
|
this.button = new Button.Button(_("Activities"), PANEL_BUTTON_COLOR, PRESSED_BUTTON_BACKGROUND_COLOR,
|
||||||
PANEL_FOREGROUND_COLOR, true, DEFAULT_FONT);
|
PANEL_FOREGROUND_COLOR, DEFAULT_FONT);
|
||||||
this.button.button.height = PANEL_HEIGHT;
|
this.button.actor.height = PANEL_HEIGHT;
|
||||||
|
|
||||||
this._leftBox.append(this.button.button, Big.BoxPackFlags.NONE);
|
this._leftBox.append(this.button.actor, Big.BoxPackFlags.NONE);
|
||||||
|
|
||||||
// We use this flag to mark the case where the user has entered the
|
// We use this flag to mark the case where the user has entered the
|
||||||
// hot corner and has not left both the hot corner and a surrounding
|
// hot corner and has not left both the hot corner and a surrounding
|
||||||
@@ -374,43 +372,46 @@ Panel.prototype = {
|
|||||||
let statusbutton = new Button.Button(statusbox,
|
let statusbutton = new Button.Button(statusbox,
|
||||||
PANEL_BUTTON_COLOR,
|
PANEL_BUTTON_COLOR,
|
||||||
PRESSED_BUTTON_BACKGROUND_COLOR,
|
PRESSED_BUTTON_BACKGROUND_COLOR,
|
||||||
PANEL_FOREGROUND_COLOR,
|
PANEL_FOREGROUND_COLOR);
|
||||||
true);
|
statusbutton.actor.height = PANEL_HEIGHT;
|
||||||
statusbutton.button.height = PANEL_HEIGHT;
|
statusbutton.actor.connect('button-press-event', function (b, e) {
|
||||||
statusbutton.button.connect('button-press-event', function (b, e) {
|
if (e.get_button() == 1 && e.get_click_count() == 1) {
|
||||||
statusmenu.toggle(e);
|
statusmenu.toggle(e);
|
||||||
return false;
|
// The statusmenu might not pop up if it couldn't get a pointer grab
|
||||||
|
if (statusmenu.is_active())
|
||||||
|
statusbutton.actor.active = true;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
// If popping up the menu failed (because there was already a grab in
|
this._rightBox.append(statusbutton.actor, Big.BoxPackFlags.NONE);
|
||||||
// effect from Mutter or another app), then we'll never get a ::deactivated
|
|
||||||
// signal because the menu was never activated, so we need to unhighlight
|
|
||||||
// separately when the user releases the mouse button.
|
|
||||||
//
|
|
||||||
// We depend on connection ordering; this needs to be called after Button's
|
|
||||||
// ::button-release-event handler; that will set the active flag for this
|
|
||||||
// stays-pressed button, then we unset the active flag by calling release().
|
|
||||||
statusbutton.button.connect('button-release-event', function (b, e) {
|
|
||||||
if (!statusmenu.is_active())
|
|
||||||
statusbutton.release();
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
this._rightBox.append(statusbutton.button, Big.BoxPackFlags.NONE);
|
|
||||||
// We get a deactivated event when the popup disappears
|
// We get a deactivated event when the popup disappears
|
||||||
this._statusmenu.connect('deactivated', function (sm) {
|
this._statusmenu.connect('deactivated', function (sm) {
|
||||||
statusbutton.release();
|
statusbutton.actor.active = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO: decide what to do with the rest of the panel in the Overview mode (make it fade-out, become non-reactive, etc.)
|
// TODO: decide what to do with the rest of the panel in the Overview mode (make it fade-out, become non-reactive, etc.)
|
||||||
// We get into the Overview mode on button-press-event as opposed to button-release-event because eventually we'll probably
|
// We get into the Overview mode on button-press-event as opposed to button-release-event because eventually we'll probably
|
||||||
// have the Overview act like a menu that allows the user to release the mouse on the activity the user wants
|
// have the Overview act like a menu that allows the user to release the mouse on the activity the user wants
|
||||||
// to switch to.
|
// to switch to.
|
||||||
this.button.button.connect('button-press-event',
|
this.button.actor.connect('button-press-event', function(b, e) {
|
||||||
Lang.bind(Main.overview, Main.overview.toggle));
|
if (e.get_button() == 1 && e.get_click_count() == 1) {
|
||||||
|
Main.overview.toggle();
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
// In addition to pressing the button, the Overview can be entered and exited by other means, such as
|
// In addition to pressing the button, the Overview can be entered and exited by other means, such as
|
||||||
// pressing the System key, Alt+F1 or Esc. We want the button to be pressed in when the Overview is entered
|
// pressing the System key, Alt+F1 or Esc. We want the button to be pressed in when the Overview is entered
|
||||||
// and to be released when it is exited regardless of how it was triggered.
|
// and to be released when it is exited regardless of how it was triggered.
|
||||||
Main.overview.connect('showing', Lang.bind(this.button, this.button.pressIn));
|
Main.overview.connect('showing', Lang.bind(this, function() {
|
||||||
Main.overview.connect('hiding', Lang.bind(this.button, this.button.release));
|
this.button.actor.active = true;
|
||||||
|
}));
|
||||||
|
Main.overview.connect('hiding', Lang.bind(this, function() {
|
||||||
|
this.button.actor.active = false;
|
||||||
|
}));
|
||||||
|
|
||||||
Main.chrome.addActor(this.actor);
|
Main.chrome.addActor(this.actor);
|
||||||
Main.chrome.setVisibleInOverview(this.actor, true);
|
Main.chrome.setVisibleInOverview(this.actor, true);
|
||||||
@@ -471,14 +472,14 @@ Panel.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
_onHotCornerLeft : function(actor, event) {
|
_onHotCornerLeft : function(actor, event) {
|
||||||
if (Shell.get_event_related(event) != this._hotCornerEnvirons) {
|
if (event.get_related() != this._hotCornerEnvirons) {
|
||||||
this._hotCornerEntered = false;
|
this._hotCornerEntered = false;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
_onHotCornerEnvironsLeft : function(actor, event) {
|
_onHotCornerEnvironsLeft : function(actor, event) {
|
||||||
if (Shell.get_event_related(event) != this._hotCorner) {
|
if (event.get_related() != this._hotCorner) {
|
||||||
this._hotCornerEntered = false;
|
this._hotCornerEntered = false;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -80,6 +80,9 @@ Places.prototype = {
|
|||||||
this._menuBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
this._menuBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
||||||
spacing: PLACES_VSPACING });
|
spacing: PLACES_VSPACING });
|
||||||
this.actor.append(this._menuBox, Big.BoxPackFlags.EXPAND);
|
this.actor.append(this._menuBox, Big.BoxPackFlags.EXPAND);
|
||||||
|
this._devBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
||||||
|
spacing: PLACES_VSPACING });
|
||||||
|
|
||||||
this._dirsBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
this._dirsBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
||||||
spacing: PLACES_VSPACING });
|
spacing: PLACES_VSPACING });
|
||||||
this.actor.append(this._dirsBox, Big.BoxPackFlags.EXPAND);
|
this.actor.append(this._dirsBox, Big.BoxPackFlags.EXPAND);
|
||||||
@@ -98,6 +101,23 @@ Places.prototype = {
|
|||||||
|
|
||||||
this._menuBox.append(home.actor, Big.BoxPackFlags.NONE);
|
this._menuBox.append(home.actor, Big.BoxPackFlags.NONE);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Show devices, code more or less ported from nautilus-places-sidebar.c
|
||||||
|
*/
|
||||||
|
|
||||||
|
this._menuBox.append(this._devBox, Big.BoxPackFlags.NONE);
|
||||||
|
this._volumeMonitor = Gio.VolumeMonitor.get();
|
||||||
|
this._volumeMonitor.connect('volume-added', Lang.bind(this, this._updateDevices));
|
||||||
|
this._volumeMonitor.connect('volume-removed',Lang.bind(this, this._updateDevices));
|
||||||
|
this._volumeMonitor.connect('volume-changed', Lang.bind(this, this._updateDevices));
|
||||||
|
this._volumeMonitor.connect('mount-added', Lang.bind(this, this._updateDevices));
|
||||||
|
this._volumeMonitor.connect('mount-removed', Lang.bind(this, this._updateDevices));
|
||||||
|
this._volumeMonitor.connect('mount-changed', Lang.bind(this, this._updateDevices));
|
||||||
|
this._volumeMonitor.connect('drive-connected', Lang.bind(this, this._updateDevices));
|
||||||
|
this._volumeMonitor.connect('drive-disconnected', Lang.bind(this, this._updateDevices));
|
||||||
|
this._volumeMonitor.connect('drive-changed', Lang.bind(this, this._updateDevices));
|
||||||
|
this._updateDevices();
|
||||||
|
|
||||||
let networkApp = null;
|
let networkApp = null;
|
||||||
try {
|
try {
|
||||||
networkApp = Shell.AppSystem.get_default().load_from_desktop_file('gnome-network-scheme.desktop');
|
networkApp = Shell.AppSystem.get_default().load_from_desktop_file('gnome-network-scheme.desktop');
|
||||||
@@ -151,6 +171,9 @@ Places.prototype = {
|
|||||||
|
|
||||||
this._dirsBox.remove_all();
|
this._dirsBox.remove_all();
|
||||||
|
|
||||||
|
if (!GLib.file_test(this._bookmarksPath, GLib.FileTest.EXISTS))
|
||||||
|
return;
|
||||||
|
|
||||||
let [success, bookmarksContent, len] = GLib.file_get_contents(this._bookmarksPath);
|
let [success, bookmarksContent, len] = GLib.file_get_contents(this._bookmarksPath);
|
||||||
|
|
||||||
if (!success)
|
if (!success)
|
||||||
@@ -194,6 +217,62 @@ Places.prototype = {
|
|||||||
});
|
});
|
||||||
this._dirsBox.append(item.actor, Big.BoxPackFlags.NONE);
|
this._dirsBox.append(item.actor, Big.BoxPackFlags.NONE);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_updateDevices: function() {
|
||||||
|
this._devBox.remove_all();
|
||||||
|
|
||||||
|
/* first go through all connected drives */
|
||||||
|
let drives = this._volumeMonitor.get_connected_drives();
|
||||||
|
for (let i = 0; i < drives.length; i++) {
|
||||||
|
let volumes = drives[i].get_volumes();
|
||||||
|
for(let j = 0; j < volumes.length; j++) {
|
||||||
|
let mount = volumes[j].get_mount();
|
||||||
|
if(mount != null) {
|
||||||
|
this._addMount(mount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add all volumes that is not associated with a drive */
|
||||||
|
let volumes = this._volumeMonitor.get_volumes();
|
||||||
|
for(let i = 0; i < volumes.length; i++) {
|
||||||
|
if(volumes[i].get_drive() != null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
let mount = volumes[i].get_mount();
|
||||||
|
if(mount != null) {
|
||||||
|
this._addMount(mount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add mounts that have no volume (/etc/mtab mounts, ftp, sftp,...) */
|
||||||
|
let mounts = this._volumeMonitor.get_mounts();
|
||||||
|
for(let i = 0; i < mounts.length; i++) {
|
||||||
|
if(mounts[i].is_shadowed())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(mounts[i].get_volume())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
this._addMount(mounts[i]);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_addMount: function(mount) {
|
||||||
|
let mountLabel = mount.get_name();
|
||||||
|
let mountIcon = mount.get_icon();
|
||||||
|
let root = mount.get_root();
|
||||||
|
let mountUri = root.get_uri();
|
||||||
|
let devItem = new PlaceDisplay(mountLabel,
|
||||||
|
function() {
|
||||||
|
return Shell.TextureCache.get_default().load_gicon(mountIcon, PLACES_ICON_SIZE);
|
||||||
|
},
|
||||||
|
function() {
|
||||||
|
Gio.app_info_launch_default_for_uri(mountUri, Main.createAppLaunchContext());
|
||||||
|
});
|
||||||
|
this._devBox.append(devItem.actor, Big.BoxPackFlags.NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
Signals.addSignalMethods(Places.prototype);
|
Signals.addSignalMethods(Places.prototype);
|
||||||
|
|||||||
@@ -5,24 +5,25 @@ const Clutter = imports.gi.Clutter;
|
|||||||
const GLib = imports.gi.GLib;
|
const GLib = imports.gi.GLib;
|
||||||
const Lang = imports.lang;
|
const Lang = imports.lang;
|
||||||
const Mainloop = imports.mainloop;
|
const Mainloop = imports.mainloop;
|
||||||
|
const Meta = imports.gi.Meta;
|
||||||
const Shell = imports.gi.Shell;
|
const Shell = imports.gi.Shell;
|
||||||
const Signals = imports.signals;
|
const Signals = imports.signals;
|
||||||
const Gettext = imports.gettext.domain('gnome-shell');
|
const Gettext = imports.gettext.domain('gnome-shell');
|
||||||
const _ = Gettext.gettext;
|
const _ = Gettext.gettext;
|
||||||
|
|
||||||
|
const Lightbox = imports.ui.lightbox;
|
||||||
const Main = imports.ui.main;
|
const Main = imports.ui.main;
|
||||||
|
|
||||||
const OVERLAY_COLOR = new Clutter.Color();
|
|
||||||
OVERLAY_COLOR.from_pixel(0x00000044);
|
|
||||||
|
|
||||||
const BOX_BACKGROUND_COLOR = new Clutter.Color();
|
const BOX_BACKGROUND_COLOR = new Clutter.Color();
|
||||||
BOX_BACKGROUND_COLOR.from_pixel(0x000000cc);
|
BOX_BACKGROUND_COLOR.from_pixel(0x000000cc);
|
||||||
|
|
||||||
const BOX_TEXT_COLOR = new Clutter.Color();
|
const BOX_TEXT_COLOR = new Clutter.Color();
|
||||||
BOX_TEXT_COLOR.from_pixel(0xffffffff);
|
BOX_TEXT_COLOR.from_pixel(0xffffffff);
|
||||||
|
|
||||||
const BOX_WIDTH = 320;
|
const DIALOG_WIDTH = 320;
|
||||||
const BOX_HEIGHT = 56;
|
const DIALOG_PADDING = 6;
|
||||||
|
const ICON_SIZE = 24;
|
||||||
|
const ICON_BOX_SIZE = 36;
|
||||||
|
|
||||||
function RunDialog() {
|
function RunDialog() {
|
||||||
this._init();
|
this._init();
|
||||||
@@ -30,25 +31,30 @@ function RunDialog() {
|
|||||||
|
|
||||||
RunDialog.prototype = {
|
RunDialog.prototype = {
|
||||||
_init : function() {
|
_init : function() {
|
||||||
let global = Shell.Global.get();
|
|
||||||
|
|
||||||
this._isOpen = false;
|
this._isOpen = false;
|
||||||
|
|
||||||
|
let gconf = Shell.GConf.get_default();
|
||||||
|
gconf.connect('changed::development_tools', Lang.bind(this, function () {
|
||||||
|
this._enableInternalCommands = gconf.get_boolean('development_tools');
|
||||||
|
}));
|
||||||
|
this._enableInternalCommands = gconf.get_boolean('development_tools');
|
||||||
|
|
||||||
this._internalCommands = { 'lg':
|
this._internalCommands = { 'lg':
|
||||||
Lang.bind(this, function() {
|
Lang.bind(this, function() {
|
||||||
// Run in an idle to avoid recursive key grab problems
|
Main.createLookingGlass().open();
|
||||||
Mainloop.idle_add(function() { Main.createLookingGlass().open(); });
|
|
||||||
}),
|
}),
|
||||||
|
|
||||||
'r': Lang.bind(this, function() {
|
'r': Lang.bind(this, function() {
|
||||||
let global = Shell.Global.get();
|
|
||||||
global.reexec_self();
|
global.reexec_self();
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// Developer brain backwards compatibility
|
// Developer brain backwards compatibility
|
||||||
'restart': Lang.bind(this, function() {
|
'restart': Lang.bind(this, function() {
|
||||||
let global = Shell.Global.get();
|
|
||||||
global.reexec_self();
|
global.reexec_self();
|
||||||
|
}),
|
||||||
|
|
||||||
|
'debugexit': Lang.bind(this, function() {
|
||||||
|
Meta.exit(Meta.ExitCode.ERROR);
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -57,52 +63,80 @@ RunDialog.prototype = {
|
|||||||
this._group = new Clutter.Group({ visible: false });
|
this._group = new Clutter.Group({ visible: false });
|
||||||
global.stage.add_actor(this._group);
|
global.stage.add_actor(this._group);
|
||||||
|
|
||||||
this._overlay = new Clutter.Rectangle({ color: OVERLAY_COLOR,
|
this._lightbox = new Lightbox.Lightbox(this._group);
|
||||||
width: global.screen_width,
|
|
||||||
height: global.screen_height,
|
|
||||||
border_width: 0,
|
|
||||||
reactive: true });
|
|
||||||
this._group.add_actor(this._overlay);
|
|
||||||
|
|
||||||
let boxGroup = new Clutter.Group();
|
let boxH = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||||
boxGroup.set_position((global.screen_width - BOX_WIDTH) / 2,
|
x_align: Big.BoxAlignment.CENTER,
|
||||||
(global.screen_height - BOX_HEIGHT) / 2);
|
y_align: Big.BoxAlignment.CENTER,
|
||||||
this._group.add_actor(boxGroup);
|
width: global.screen_width,
|
||||||
|
height: global.screen_height });
|
||||||
|
|
||||||
let box = new Big.Box({ background_color: BOX_BACKGROUND_COLOR,
|
this._group.add_actor(boxH);
|
||||||
corner_radius: 4,
|
this._lightbox.highlight(boxH);
|
||||||
reactive: false,
|
|
||||||
width: BOX_WIDTH,
|
let boxV = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
||||||
height: BOX_HEIGHT
|
y_align: Big.BoxAlignment.CENTER });
|
||||||
});
|
|
||||||
boxGroup.add_actor(box);
|
boxH.append(boxV, Big.BoxPackFlags.NONE);
|
||||||
|
|
||||||
|
|
||||||
|
let dialogBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
||||||
|
background_color: BOX_BACKGROUND_COLOR,
|
||||||
|
corner_radius: 4,
|
||||||
|
reactive: false,
|
||||||
|
padding: DIALOG_PADDING,
|
||||||
|
width: DIALOG_WIDTH });
|
||||||
|
|
||||||
|
boxH.append(dialogBox, Big.BoxPackFlags.NONE);
|
||||||
|
|
||||||
let label = new Clutter.Text({ color: BOX_TEXT_COLOR,
|
let label = new Clutter.Text({ color: BOX_TEXT_COLOR,
|
||||||
font_name: '18px Sans',
|
font_name: '18px Sans',
|
||||||
text: _("Please enter a command:") });
|
text: _("Please enter a command:") });
|
||||||
label.set_position(6, 6);
|
|
||||||
boxGroup.add_actor(label);
|
dialogBox.append(label, Big.BoxPackFlags.EXPAND);
|
||||||
|
|
||||||
this._entry = new Clutter.Text({ color: BOX_TEXT_COLOR,
|
this._entry = new Clutter.Text({ color: BOX_TEXT_COLOR,
|
||||||
font_name: '20px Sans Bold',
|
font_name: '20px Sans Bold',
|
||||||
editable: true,
|
editable: true,
|
||||||
activatable: true,
|
activatable: true,
|
||||||
singleLineMode: true,
|
singleLineMode: true });
|
||||||
text: '',
|
|
||||||
width: BOX_WIDTH - 12,
|
dialogBox.append(this._entry, Big.BoxPackFlags.EXPAND);
|
||||||
height: BOX_HEIGHT - 12 });
|
|
||||||
// TODO: Implement relative positioning using Tidy.
|
this._errorBox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||||
this._entry.set_position(6, 30);
|
padding_top: DIALOG_PADDING });
|
||||||
boxGroup.add_actor(this._entry);
|
|
||||||
|
dialogBox.append(this._errorBox, Big.BoxPackFlags.EXPAND);
|
||||||
|
|
||||||
|
let iconBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
||||||
|
y_align: Big.BoxAlignment.CENTER,
|
||||||
|
x_align: Big.BoxAlignment.CENTER,
|
||||||
|
width: ICON_BOX_SIZE,
|
||||||
|
height: ICON_BOX_SIZE });
|
||||||
|
|
||||||
|
this._errorBox.append(iconBox, Big.BoxPackFlags.NONE);
|
||||||
|
|
||||||
|
this._commandError = false;
|
||||||
|
|
||||||
|
let errorIcon = Shell.TextureCache.get_default().load_icon_name("gtk-dialog-error", ICON_SIZE);
|
||||||
|
iconBox.append(errorIcon, Big.BoxPackFlags.EXPAND);
|
||||||
|
|
||||||
|
this._errorMessage = new Clutter.Text({ color: BOX_TEXT_COLOR,
|
||||||
|
font_name: '18px Sans Bold',
|
||||||
|
line_wrap: true });
|
||||||
|
|
||||||
|
this._errorBox.append(this._errorMessage, Big.BoxPackFlags.EXPAND);
|
||||||
|
|
||||||
|
this._errorBox.hide();
|
||||||
|
|
||||||
this._entry.connect('activate', Lang.bind(this, function (o, e) {
|
this._entry.connect('activate', Lang.bind(this, function (o, e) {
|
||||||
this._run(o.get_text());
|
this._run(o.get_text());
|
||||||
this.close();
|
if (!this._commandError)
|
||||||
return false;
|
this.close();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
this._entry.connect('key-press-event', Lang.bind(this, function(o, e) {
|
this._entry.connect('key-press-event', Lang.bind(this, function(o, e) {
|
||||||
let symbol = Shell.get_event_key_symbol(e);
|
let symbol = e.get_key_symbol();
|
||||||
if (symbol == Clutter.Escape) {
|
if (symbol == Clutter.Escape) {
|
||||||
this.close();
|
this.close();
|
||||||
return true;
|
return true;
|
||||||
@@ -112,17 +146,31 @@ RunDialog.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
_run : function(command) {
|
_run : function(command) {
|
||||||
let f = this._internalCommands[command];
|
let f;
|
||||||
|
if (this._enableInternalCommands)
|
||||||
|
f = this._internalCommands[command];
|
||||||
|
else
|
||||||
|
f = null;
|
||||||
if (f) {
|
if (f) {
|
||||||
f();
|
f();
|
||||||
} else if (command) {
|
} else if (command) {
|
||||||
try {
|
try {
|
||||||
|
this._commandError = false;
|
||||||
let [ok, len, args] = GLib.shell_parse_argv(command);
|
let [ok, len, args] = GLib.shell_parse_argv(command);
|
||||||
let p = new Shell.Process({'args' : args});
|
let p = new Shell.Process({'args' : args});
|
||||||
p.run();
|
p.run();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// TODO: Give the user direct feedback.
|
this._commandError = true;
|
||||||
log('Could not run command ' + command + ': ' + e);
|
/*
|
||||||
|
* The exception contains an error string like:
|
||||||
|
* Error invoking Shell.run: Failed to execute child process "foo"
|
||||||
|
* (No such file or directory)
|
||||||
|
* We are only interested in the actual error, so parse that out.
|
||||||
|
*/
|
||||||
|
let m = /.+\((.+)\)/.exec(e);
|
||||||
|
let errorStr = "Execution of '" + command + "' failed:\n" + m[1];
|
||||||
|
this._errorMessage.set_text(errorStr);
|
||||||
|
this._errorBox.show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -131,13 +179,12 @@ RunDialog.prototype = {
|
|||||||
if (this._isOpen) // Already shown
|
if (this._isOpen) // Already shown
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!Main.beginModal())
|
if (!Main.pushModal(this._group))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this._isOpen = true;
|
this._isOpen = true;
|
||||||
this._group.show();
|
this._group.show();
|
||||||
|
|
||||||
let global = Shell.Global.get();
|
|
||||||
global.stage.set_key_focus(this._entry);
|
global.stage.set_key_focus(this._entry);
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -147,10 +194,13 @@ RunDialog.prototype = {
|
|||||||
|
|
||||||
this._isOpen = false;
|
this._isOpen = false;
|
||||||
|
|
||||||
|
this._errorBox.hide();
|
||||||
|
this._commandError = false;
|
||||||
|
|
||||||
this._group.hide();
|
this._group.hide();
|
||||||
this._entry.text = '';
|
this._entry.text = '';
|
||||||
|
|
||||||
Main.endModal();
|
Main.popModal(this._group);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Signals.addSignalMethods(RunDialog.prototype);
|
Signals.addSignalMethods(RunDialog.prototype);
|
||||||
|
|||||||
72
js/ui/shellDBus.js
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
|
const DBus = imports.dbus;
|
||||||
|
const Lang = imports.lang;
|
||||||
|
const Shell = imports.gi.Shell;
|
||||||
|
const Mainloop = imports.mainloop;
|
||||||
|
|
||||||
|
const Main = imports.ui.main;
|
||||||
|
|
||||||
|
const GnomeShellIface = {
|
||||||
|
name: "org.gnome.Shell",
|
||||||
|
methods: [{ name: "Eval",
|
||||||
|
inSignature: "s",
|
||||||
|
outSignature: "bs"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
signals: [],
|
||||||
|
properties: [{ name: "OverviewActive",
|
||||||
|
signature: "b",
|
||||||
|
access: "readwrite" }]
|
||||||
|
};
|
||||||
|
|
||||||
|
function GnomeShell() {
|
||||||
|
this._init();
|
||||||
|
}
|
||||||
|
|
||||||
|
GnomeShell.prototype = {
|
||||||
|
_init: function() {
|
||||||
|
DBus.session.exportObject('/org/gnome/Shell', this);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Eval:
|
||||||
|
* @code: A string containing JavaScript code
|
||||||
|
*
|
||||||
|
* This function executes arbitrary code in the main
|
||||||
|
* loop, and returns a boolean success and
|
||||||
|
* JSON representation of the object as a string.
|
||||||
|
*
|
||||||
|
* If evaluation completes without throwing an exception,
|
||||||
|
* then the return value will be [true, JSON.stringify(result)].
|
||||||
|
* If evaluation fails, then the return value will be
|
||||||
|
* [false, JSON.stringify(exception)];
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
Eval: function(code) {
|
||||||
|
let returnValue;
|
||||||
|
let success;
|
||||||
|
try {
|
||||||
|
returnValue = JSON.stringify(eval(code));
|
||||||
|
success = true;
|
||||||
|
} catch (e) {
|
||||||
|
returnValue = JSON.stringify(e);
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
return [success, returnValue];
|
||||||
|
},
|
||||||
|
|
||||||
|
get OverviewActive() {
|
||||||
|
return Main.overview.visible;
|
||||||
|
},
|
||||||
|
|
||||||
|
set OverviewActive(visible) {
|
||||||
|
if (visible)
|
||||||
|
Main.overview.show();
|
||||||
|
else
|
||||||
|
Main.overview.hide();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
DBus.conformExport(GnomeShell.prototype, GnomeShellIface);
|
||||||
|
|
||||||
@@ -21,21 +21,12 @@ const SIDEBAR_PADDING = 4;
|
|||||||
const SIDEBAR_COLLAPSED_WIDTH = Widget.COLLAPSED_WIDTH + 3 * WidgetBox.WIDGETBOX_PADDING + SIDEBAR_PADDING;
|
const SIDEBAR_COLLAPSED_WIDTH = Widget.COLLAPSED_WIDTH + 3 * WidgetBox.WIDGETBOX_PADDING + SIDEBAR_PADDING;
|
||||||
const SIDEBAR_EXPANDED_WIDTH = Widget.EXPANDED_WIDTH + 3 * WidgetBox.WIDGETBOX_PADDING + SIDEBAR_PADDING;
|
const SIDEBAR_EXPANDED_WIDTH = Widget.EXPANDED_WIDTH + 3 * WidgetBox.WIDGETBOX_PADDING + SIDEBAR_PADDING;
|
||||||
|
|
||||||
// The maximum height of the sidebar would be extending from just
|
|
||||||
// below the panel to just above the taskbar. Since the taskbar is
|
|
||||||
// just a temporary hack and it would be too hard to do this the right
|
|
||||||
// way, we just hardcode its size.
|
|
||||||
const HARDCODED_TASKBAR_HEIGHT = 24;
|
|
||||||
const MAXIMUM_SIDEBAR_HEIGHT = Shell.Global.get().screen_height - Panel.PANEL_HEIGHT - HARDCODED_TASKBAR_HEIGHT;
|
|
||||||
|
|
||||||
function Sidebar() {
|
function Sidebar() {
|
||||||
this._init();
|
this._init();
|
||||||
}
|
}
|
||||||
|
|
||||||
Sidebar.prototype = {
|
Sidebar.prototype = {
|
||||||
_init : function() {
|
_init : function() {
|
||||||
let global = Shell.Global.get();
|
|
||||||
|
|
||||||
// The top-left corner of the sidebar is fixed at:
|
// The top-left corner of the sidebar is fixed at:
|
||||||
// x = -WidgetBox.WIDGETBOX_PADDING, y = Panel.PANEL_HEIGHT.
|
// x = -WidgetBox.WIDGETBOX_PADDING, y = Panel.PANEL_HEIGHT.
|
||||||
// (The negative X is so that we don't see the rounded
|
// (The negative X is so that we don't see the rounded
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
const Clutter = imports.gi.Clutter;
|
const Clutter = imports.gi.Clutter;
|
||||||
|
const GLib = imports.gi.GLib;
|
||||||
const Lang = imports.lang;
|
const Lang = imports.lang;
|
||||||
const Mainloop = imports.mainloop;
|
const Mainloop = imports.mainloop;
|
||||||
const Signals = imports.signals;
|
const Signals = imports.signals;
|
||||||
@@ -41,9 +42,17 @@ const Tweener = imports.tweener.tweener;
|
|||||||
// calls any of these is almost certainly wrong anyway, because they
|
// calls any of these is almost certainly wrong anyway, because they
|
||||||
// affect the entire application.)
|
// affect the entire application.)
|
||||||
|
|
||||||
|
let slowDownFactor = 1.0;
|
||||||
|
|
||||||
// Called from Main.start
|
// Called from Main.start
|
||||||
function init() {
|
function init() {
|
||||||
|
let slowdownEnv = GLib.getenv("GNOME_SHELL_SLOWDOWN_FACTOR");
|
||||||
|
if (slowdownEnv) {
|
||||||
|
let factor = parseFloat(slowdownEnv);
|
||||||
|
if (!isNaN(factor) && factor > 0.0)
|
||||||
|
slowDownFactor = factor;
|
||||||
|
}
|
||||||
|
|
||||||
Tweener.setFrameTicker(new ClutterFrameTicker());
|
Tweener.setFrameTicker(new ClutterFrameTicker());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,11 +217,10 @@ ClutterFrameTicker.prototype = {
|
|||||||
this._startTime = -1;
|
this._startTime = -1;
|
||||||
this._currentTime = -1;
|
this._currentTime = -1;
|
||||||
|
|
||||||
let me = this;
|
this._timeline.connect('new-frame', Lang.bind(this,
|
||||||
this._timeline.connect('new-frame',
|
|
||||||
function(timeline, frame) {
|
function(timeline, frame) {
|
||||||
me._onNewFrame(frame);
|
this._onNewFrame(frame);
|
||||||
});
|
}));
|
||||||
},
|
},
|
||||||
|
|
||||||
_onNewFrame : function(frame) {
|
_onNewFrame : function(frame) {
|
||||||
@@ -225,7 +233,7 @@ ClutterFrameTicker.prototype = {
|
|||||||
this._startTime = this._timeline.get_elapsed_time();
|
this._startTime = this._timeline.get_elapsed_time();
|
||||||
|
|
||||||
// currentTime is in milliseconds
|
// currentTime is in milliseconds
|
||||||
this._currentTime = this._timeline.get_elapsed_time() - this._startTime;
|
this._currentTime = (this._timeline.get_elapsed_time() - this._startTime) / slowDownFactor;
|
||||||
this.emit('prepare-frame');
|
this.emit('prepare-frame');
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -163,7 +163,6 @@ ClockWidget.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
_updateCairo: function(time) {
|
_updateCairo: function(time) {
|
||||||
let global = Shell.Global.get();
|
|
||||||
Shell.draw_clock(this.collapsedActor,
|
Shell.draw_clock(this.collapsedActor,
|
||||||
time.getHours() % 12,
|
time.getHours() % 12,
|
||||||
time.getMinutes());
|
time.getMinutes());
|
||||||
|
|||||||
@@ -296,7 +296,7 @@ WidgetBox.prototype = {
|
|||||||
this.state == Widget.STATE_POPPING_OUT)) {
|
this.state == Widget.STATE_POPPING_OUT)) {
|
||||||
// If moving into another actor within this._hbox, let the
|
// If moving into another actor within this._hbox, let the
|
||||||
// event be propagated
|
// event be propagated
|
||||||
let into = Shell.get_event_related(event);
|
let into = event.get_related();
|
||||||
while (into) {
|
while (into) {
|
||||||
if (into == this._hbox)
|
if (into == this._hbox)
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
const Clutter = imports.gi.Clutter;
|
const Clutter = imports.gi.Clutter;
|
||||||
|
const Lang = imports.lang;
|
||||||
const Mainloop = imports.mainloop;
|
const Mainloop = imports.mainloop;
|
||||||
const Meta = imports.gi.Meta;
|
const Meta = imports.gi.Meta;
|
||||||
const Shell = imports.gi.Shell;
|
const Shell = imports.gi.Shell;
|
||||||
@@ -17,10 +18,8 @@ function WindowManager() {
|
|||||||
|
|
||||||
WindowManager.prototype = {
|
WindowManager.prototype = {
|
||||||
_init : function() {
|
_init : function() {
|
||||||
let me = this;
|
let shellwm = global.window_manager;
|
||||||
|
|
||||||
this._global = Shell.Global.get();
|
|
||||||
this._shellwm = this._global.window_manager;
|
|
||||||
this._minimizing = [];
|
this._minimizing = [];
|
||||||
this._maximizing = [];
|
this._maximizing = [];
|
||||||
this._unmaximizing = [];
|
this._unmaximizing = [];
|
||||||
@@ -28,60 +27,21 @@ WindowManager.prototype = {
|
|||||||
this._destroying = [];
|
this._destroying = [];
|
||||||
|
|
||||||
this._switchData = null;
|
this._switchData = null;
|
||||||
this._shellwm.connect('switch-workspace',
|
shellwm.connect('switch-workspace', Lang.bind(this, this._switchWorkspace));
|
||||||
function(o, from, to, direction) {
|
shellwm.connect('kill-switch-workspace', Lang.bind(this, this._switchWorkspaceDone));
|
||||||
let actors = me._shellwm.get_switch_workspace_actors();
|
shellwm.connect('minimize', Lang.bind(this, this._minimizeWindow));
|
||||||
me._switchWorkspace(actors, from, to, direction);
|
shellwm.connect('kill-minimize', Lang.bind(this, this._minimizeWindowDone));
|
||||||
});
|
shellwm.connect('maximize', Lang.bind(this, this._maximizeWindow));
|
||||||
this._shellwm.connect('kill-switch-workspace',
|
shellwm.connect('kill-maximize', Lang.bind(this, this._maximizeWindowDone));
|
||||||
function(o) {
|
shellwm.connect('unmaximize', Lang.bind(this, this._unmaximizeWindow));
|
||||||
me._switchWorkspaceDone();
|
shellwm.connect('kill-unmaximize', Lang.bind(this, this._unmaximizeWindowDone));
|
||||||
});
|
shellwm.connect('map', Lang.bind(this, this._mapWindow));
|
||||||
this._shellwm.connect('minimize',
|
shellwm.connect('kill-map', Lang.bind(this, this._mapWindowDone));
|
||||||
function(o, actor) {
|
shellwm.connect('destroy', Lang.bind(this, this._destroyWindow));
|
||||||
me._minimizeWindow(actor);
|
shellwm.connect('kill-destroy', Lang.bind(this, this._destroyWindowDone));
|
||||||
});
|
|
||||||
this._shellwm.connect('kill-minimize',
|
|
||||||
function(o, actor) {
|
|
||||||
me._minimizeWindowDone(actor);
|
|
||||||
});
|
|
||||||
this._shellwm.connect('maximize',
|
|
||||||
function(o, actor, tx, ty, tw, th) {
|
|
||||||
me._maximizeWindow(actor, tx, ty, tw, th);
|
|
||||||
});
|
|
||||||
this._shellwm.connect('kill-maximize',
|
|
||||||
function(o, actor) {
|
|
||||||
me._maximizeWindowDone(actor);
|
|
||||||
});
|
|
||||||
this._shellwm.connect('unmaximize',
|
|
||||||
function(o, actor, tx, ty, tw, th) {
|
|
||||||
me._unmaximizeWindow(actor, tx, ty, tw, th);
|
|
||||||
});
|
|
||||||
this._shellwm.connect('kill-unmaximize',
|
|
||||||
function(o, actor) {
|
|
||||||
me._unmaximizeWindowDone(actor);
|
|
||||||
});
|
|
||||||
this._shellwm.connect('map',
|
|
||||||
function(o, actor) {
|
|
||||||
me._mapWindow(actor);
|
|
||||||
});
|
|
||||||
this._shellwm.connect('kill-map',
|
|
||||||
function(o, actor) {
|
|
||||||
me._mapWindowDone(actor);
|
|
||||||
});
|
|
||||||
this._shellwm.connect('destroy',
|
|
||||||
function(o, actor) {
|
|
||||||
me._destroyWindow(actor);
|
|
||||||
});
|
|
||||||
this._shellwm.connect('kill-destroy',
|
|
||||||
function(o, actor) {
|
|
||||||
me._destroyWindowDone(actor);
|
|
||||||
});
|
|
||||||
|
|
||||||
this._shellwm.connect('begin-alt-tab',
|
shellwm.takeover_keybinding('switch_windows');
|
||||||
function(o, handler) {
|
shellwm.connect('keybinding::switch_windows', Lang.bind(this, this._startAppSwitcher));
|
||||||
me._beginAltTab(handler);
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_shouldAnimate : function(actor) {
|
_shouldAnimate : function(actor) {
|
||||||
@@ -101,9 +61,9 @@ WindowManager.prototype = {
|
|||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
_minimizeWindow : function(actor) {
|
_minimizeWindow : function(shellwm, actor) {
|
||||||
if (!this._shouldAnimate(actor)) {
|
if (!this._shouldAnimate(actor)) {
|
||||||
this._shellwm.completed_minimize(actor);
|
shellwm.completed_minimize(actor);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,49 +81,49 @@ WindowManager.prototype = {
|
|||||||
transition: "easeOutQuad",
|
transition: "easeOutQuad",
|
||||||
onComplete: this._minimizeWindowDone,
|
onComplete: this._minimizeWindowDone,
|
||||||
onCompleteScope: this,
|
onCompleteScope: this,
|
||||||
onCompleteParams: [actor],
|
onCompleteParams: [shellwm, actor],
|
||||||
onOverwrite: this._minimizeWindowOverwritten,
|
onOverwrite: this._minimizeWindowOverwritten,
|
||||||
onOverwriteScope: this,
|
onOverwriteScope: this,
|
||||||
onOverwriteParams: [actor]
|
onOverwriteParams: [shellwm, actor]
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
_minimizeWindowDone : function(actor) {
|
_minimizeWindowDone : function(shellwm, actor) {
|
||||||
if (this._removeEffect(this._minimizing, actor)) {
|
if (this._removeEffect(this._minimizing, actor)) {
|
||||||
Tweener.removeTweens(actor);
|
Tweener.removeTweens(actor);
|
||||||
actor.set_scale(1.0, 1.0);
|
actor.set_scale(1.0, 1.0);
|
||||||
actor.move_anchor_point_from_gravity(Clutter.Gravity.NORTH_WEST);
|
actor.move_anchor_point_from_gravity(Clutter.Gravity.NORTH_WEST);
|
||||||
|
|
||||||
this._shellwm.completed_minimize(actor);
|
shellwm.completed_minimize(actor);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_minimizeWindowOverwritten : function(actor) {
|
_minimizeWindowOverwritten : function(shellwm, actor) {
|
||||||
if (this._removeEffect(this._minimizing, actor)) {
|
if (this._removeEffect(this._minimizing, actor)) {
|
||||||
this._shellwm.completed_minimize(actor);
|
shellwm.completed_minimize(actor);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_maximizeWindow : function(actor, targetX, targetY, targetWidth, targetHeight) {
|
_maximizeWindow : function(shellwm, actor, targetX, targetY, targetWidth, targetHeight) {
|
||||||
this._shellwm.completed_maximize(actor);
|
shellwm.completed_maximize(actor);
|
||||||
},
|
},
|
||||||
|
|
||||||
_maximizeWindowDone : function(actor) {
|
_maximizeWindowDone : function(shellwm, actor) {
|
||||||
},
|
},
|
||||||
|
|
||||||
_maximizeWindowOverwrite : function(actor) {
|
_maximizeWindowOverwrite : function(shellwm, actor) {
|
||||||
},
|
},
|
||||||
|
|
||||||
_unmaximizeWindow : function(actor, targetX, targetY, targetWidth, targetHeight) {
|
_unmaximizeWindow : function(shellwm, actor, targetX, targetY, targetWidth, targetHeight) {
|
||||||
this._shellwm.completed_unmaximize(actor);
|
shellwm.completed_unmaximize(actor);
|
||||||
},
|
},
|
||||||
|
|
||||||
_unmaximizeWindowDone : function(actor) {
|
_unmaximizeWindowDone : function(shellwm, actor) {
|
||||||
},
|
},
|
||||||
|
|
||||||
_mapWindow : function(actor) {
|
_mapWindow : function(shellwm, actor) {
|
||||||
if (!this._shouldAnimate(actor)) {
|
if (!this._shouldAnimate(actor)) {
|
||||||
this._shellwm.completed_map(actor);
|
shellwm.completed_map(actor);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,72 +140,43 @@ WindowManager.prototype = {
|
|||||||
transition: "easeOutQuad",
|
transition: "easeOutQuad",
|
||||||
onComplete: this._mapWindowDone,
|
onComplete: this._mapWindowDone,
|
||||||
onCompleteScope: this,
|
onCompleteScope: this,
|
||||||
onCompleteParams: [actor],
|
onCompleteParams: [shellwm, actor],
|
||||||
onOverwrite: this._mapWindowOverwrite,
|
onOverwrite: this._mapWindowOverwrite,
|
||||||
onOverwriteScope: this,
|
onOverwriteScope: this,
|
||||||
onOverwriteParams: [actor]
|
onOverwriteParams: [shellwm, actor]
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
_mapWindowDone : function(actor) {
|
_mapWindowDone : function(shellwm, actor) {
|
||||||
if (this._removeEffect(this._mapping, actor)) {
|
if (this._removeEffect(this._mapping, actor)) {
|
||||||
Tweener.removeTweens(actor);
|
Tweener.removeTweens(actor);
|
||||||
actor.set_scale(1.0, 1.0);
|
actor.set_scale(1.0, 1.0);
|
||||||
actor.move_anchor_point_from_gravity(Clutter.Gravity.NORTH_WEST);
|
actor.move_anchor_point_from_gravity(Clutter.Gravity.NORTH_WEST);
|
||||||
this._shellwm.completed_map(actor);
|
shellwm.completed_map(actor);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_mapWindowOverwrite : function(actor) {
|
_mapWindowOverwrite : function(shellwm, actor) {
|
||||||
if (this._removeEffect(this._mapping, actor)) {
|
if (this._removeEffect(this._mapping, actor)) {
|
||||||
this._shellwm.completed_map(actor);
|
shellwm.completed_map(actor);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_destroyWindow : function(actor) {
|
_destroyWindow : function(shellwm, actor) {
|
||||||
if (!this._shouldAnimate(actor)) {
|
shellwm.completed_destroy(actor);
|
||||||
this._shellwm.completed_destroy(actor);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
actor.move_anchor_point_from_gravity(Clutter.Gravity.CENTER);
|
|
||||||
|
|
||||||
/* anachronistic 'tv-like' effect - squash on y axis, leave x alone */
|
|
||||||
this._destroying.push(actor);
|
|
||||||
Tweener.addTween(actor,
|
|
||||||
{ scale_x: 1.0,
|
|
||||||
scale_y: 0.0,
|
|
||||||
time: WINDOW_ANIMATION_TIME,
|
|
||||||
transition: "easeOutQuad",
|
|
||||||
onComplete: this._destroyWindowDone,
|
|
||||||
onCompleteScope: this,
|
|
||||||
onCompleteParams: [actor],
|
|
||||||
onOverwrite: this._destroyWindowOverwrite,
|
|
||||||
onOverwriteScope: this,
|
|
||||||
onOverwriteParams: [actor]
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_destroyWindowDone : function(actor) {
|
_destroyWindowDone : function(shellwm, actor) {
|
||||||
if (this._removeEffect(this._destroying, actor)) {
|
|
||||||
this._shellwm.completed_destroy(actor);
|
|
||||||
Tweener.removeTweens(actor);
|
|
||||||
actor.set_scale(1.0, 1.0);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_destroyWindowOverwrite : function(actor) {
|
_switchWorkspace : function(shellwm, from, to, direction) {
|
||||||
if (this._removeEffect(this._destroying, actor)) {
|
|
||||||
this._shellwm.completed_destroy(actor);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_switchWorkspace : function(windows, from, to, direction) {
|
|
||||||
if (!this._shouldAnimate()) {
|
if (!this._shouldAnimate()) {
|
||||||
this._shellwm.completed_switch_workspace();
|
shellwm.completed_switch_workspace();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let windows = shellwm.get_switch_workspace_actors();
|
||||||
|
|
||||||
/* @direction is the direction that the "camera" moves, so the
|
/* @direction is the direction that the "camera" moves, so the
|
||||||
* screen contents have to move one screen's worth in the
|
* screen contents have to move one screen's worth in the
|
||||||
* opposite direction.
|
* opposite direction.
|
||||||
@@ -255,20 +186,20 @@ WindowManager.prototype = {
|
|||||||
if (direction == Meta.MotionDirection.UP ||
|
if (direction == Meta.MotionDirection.UP ||
|
||||||
direction == Meta.MotionDirection.UP_LEFT ||
|
direction == Meta.MotionDirection.UP_LEFT ||
|
||||||
direction == Meta.MotionDirection.UP_RIGHT)
|
direction == Meta.MotionDirection.UP_RIGHT)
|
||||||
yDest = this._global.screen_height;
|
yDest = global.screen_height;
|
||||||
else if (direction == Meta.MotionDirection.DOWN ||
|
else if (direction == Meta.MotionDirection.DOWN ||
|
||||||
direction == Meta.MotionDirection.DOWN_LEFT ||
|
direction == Meta.MotionDirection.DOWN_LEFT ||
|
||||||
direction == Meta.MotionDirection.DOWN_RIGHT)
|
direction == Meta.MotionDirection.DOWN_RIGHT)
|
||||||
yDest = -this._global.screen_height;
|
yDest = -global.screen_height;
|
||||||
|
|
||||||
if (direction == Meta.MotionDirection.LEFT ||
|
if (direction == Meta.MotionDirection.LEFT ||
|
||||||
direction == Meta.MotionDirection.UP_LEFT ||
|
direction == Meta.MotionDirection.UP_LEFT ||
|
||||||
direction == Meta.MotionDirection.DOWN_LEFT)
|
direction == Meta.MotionDirection.DOWN_LEFT)
|
||||||
xDest = this._global.screen_width;
|
xDest = global.screen_width;
|
||||||
else if (direction == Meta.MotionDirection.RIGHT ||
|
else if (direction == Meta.MotionDirection.RIGHT ||
|
||||||
direction == Meta.MotionDirection.UP_RIGHT ||
|
direction == Meta.MotionDirection.UP_RIGHT ||
|
||||||
direction == Meta.MotionDirection.DOWN_RIGHT)
|
direction == Meta.MotionDirection.DOWN_RIGHT)
|
||||||
xDest = -this._global.screen_width;
|
xDest = -global.screen_width;
|
||||||
|
|
||||||
let switchData = {};
|
let switchData = {};
|
||||||
this._switchData = switchData;
|
this._switchData = switchData;
|
||||||
@@ -276,7 +207,7 @@ WindowManager.prototype = {
|
|||||||
switchData.outGroup = new Clutter.Group();
|
switchData.outGroup = new Clutter.Group();
|
||||||
switchData.windows = [];
|
switchData.windows = [];
|
||||||
|
|
||||||
let wgroup = this._global.window_group;
|
let wgroup = global.window_group;
|
||||||
wgroup.add_actor(switchData.inGroup);
|
wgroup.add_actor(switchData.inGroup);
|
||||||
wgroup.add_actor(switchData.outGroup);
|
wgroup.add_actor(switchData.outGroup);
|
||||||
|
|
||||||
@@ -307,7 +238,8 @@ WindowManager.prototype = {
|
|||||||
time: WINDOW_ANIMATION_TIME,
|
time: WINDOW_ANIMATION_TIME,
|
||||||
transition: "easeOutQuad",
|
transition: "easeOutQuad",
|
||||||
onComplete: this._switchWorkspaceDone,
|
onComplete: this._switchWorkspaceDone,
|
||||||
onCompleteScope: this
|
onCompleteScope: this,
|
||||||
|
onCompleteParams: [shellwm]
|
||||||
});
|
});
|
||||||
Tweener.addTween(switchData.inGroup,
|
Tweener.addTween(switchData.inGroup,
|
||||||
{ x: 0,
|
{ x: 0,
|
||||||
@@ -317,7 +249,7 @@ WindowManager.prototype = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
_switchWorkspaceDone : function() {
|
_switchWorkspaceDone : function(shellwm) {
|
||||||
let switchData = this._switchData;
|
let switchData = this._switchData;
|
||||||
if (!switchData)
|
if (!switchData)
|
||||||
return;
|
return;
|
||||||
@@ -336,15 +268,13 @@ WindowManager.prototype = {
|
|||||||
switchData.inGroup.destroy();
|
switchData.inGroup.destroy();
|
||||||
switchData.outGroup.destroy();
|
switchData.outGroup.destroy();
|
||||||
|
|
||||||
this._shellwm.completed_switch_workspace();
|
shellwm.completed_switch_workspace();
|
||||||
},
|
},
|
||||||
|
|
||||||
_beginAltTab : function(handler) {
|
_startAppSwitcher : function(shellwm, binding, window, backwards) {
|
||||||
let popup = new AltTab.AltTabPopup();
|
let tabPopup = new AltTab.AltTabPopup();
|
||||||
|
|
||||||
handler.connect('window-added', function(handler, window) { popup.addWindow(window); });
|
if (!tabPopup.show(backwards ? -1 : 1))
|
||||||
handler.connect('show', function(handler, initialSelection) { popup.show(initialSelection); });
|
tabPopup.destroy();
|
||||||
handler.connect('destroy', function() { popup.destroy(); });
|
}
|
||||||
handler.connect('notify::selected', function() { popup.select(handler.selected); });
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ const Shell = imports.gi.Shell;
|
|||||||
const Signals = imports.signals;
|
const Signals = imports.signals;
|
||||||
|
|
||||||
const DND = imports.ui.dnd;
|
const DND = imports.ui.dnd;
|
||||||
|
const Lightbox = imports.ui.lightbox;
|
||||||
const Main = imports.ui.main;
|
const Main = imports.ui.main;
|
||||||
const Overview = imports.ui.overview;
|
const Overview = imports.ui.overview;
|
||||||
const Panel = imports.ui.panel;
|
const Panel = imports.ui.panel;
|
||||||
@@ -26,6 +27,10 @@ WINDOWCLONE_TITLE_COLOR.from_pixel(0xffffffff);
|
|||||||
const FRAME_COLOR = new Clutter.Color();
|
const FRAME_COLOR = new Clutter.Color();
|
||||||
FRAME_COLOR.from_pixel(0xffffffff);
|
FRAME_COLOR.from_pixel(0xffffffff);
|
||||||
|
|
||||||
|
const SCROLL_SCALE_AMOUNT = 100 / 5;
|
||||||
|
|
||||||
|
const ZOOM_OVERLAY_FADE_TIME = 0.15;
|
||||||
|
|
||||||
// Define a layout scheme for small window counts. For larger
|
// Define a layout scheme for small window counts. For larger
|
||||||
// counts we fall back to an algorithm. We need more schemes here
|
// counts we fall back to an algorithm. We need more schemes here
|
||||||
// unless we have a really good algorithm.
|
// unless we have a really good algorithm.
|
||||||
@@ -39,6 +44,16 @@ const POSITIONS = {
|
|||||||
4: [[0.25, 0.25, 0.47], [0.75, 0.25, 0.47], [0.75, 0.75, 0.47], [0.25, 0.75, 0.47]],
|
4: [[0.25, 0.25, 0.47], [0.75, 0.25, 0.47], [0.75, 0.75, 0.47], [0.25, 0.75, 0.47]],
|
||||||
5: [[0.165, 0.25, 0.32], [0.495, 0.25, 0.32], [0.825, 0.25, 0.32], [0.25, 0.75, 0.32], [0.75, 0.75, 0.32]]
|
5: [[0.165, 0.25, 0.32], [0.495, 0.25, 0.32], [0.825, 0.25, 0.32], [0.25, 0.75, 0.32], [0.75, 0.75, 0.32]]
|
||||||
};
|
};
|
||||||
|
// Used in _orderWindowsPermutations, 5! = 120 which is probably the highest we can go
|
||||||
|
const POSITIONING_PERMUTATIONS_MAX = 5;
|
||||||
|
|
||||||
|
function _interpolate(start, end, step) {
|
||||||
|
return start + (end - start) * step;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _clamp(value, min, max) {
|
||||||
|
return Math.max(min, Math.min(max, value));
|
||||||
|
}
|
||||||
|
|
||||||
// Spacing between workspaces. At the moment, the same spacing is used
|
// Spacing between workspaces. At the moment, the same spacing is used
|
||||||
// in both zoomed-in and zoomed-out views; this is slightly
|
// in both zoomed-in and zoomed-out views; this is slightly
|
||||||
@@ -46,7 +61,38 @@ const POSITIONS = {
|
|||||||
const GRID_SPACING = 15;
|
const GRID_SPACING = 15;
|
||||||
const FRAME_SIZE = GRID_SPACING / 3;
|
const FRAME_SIZE = GRID_SPACING / 3;
|
||||||
|
|
||||||
let buttonSize = false;
|
function ScaledPoint(x, y, scaleX, scaleY) {
|
||||||
|
[this.x, this.y, this.scaleX, this.scaleY] = arguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScaledPoint.prototype = {
|
||||||
|
getPosition : function() {
|
||||||
|
return [this.x, this.y];
|
||||||
|
},
|
||||||
|
|
||||||
|
getScale : function() {
|
||||||
|
return [this.scaleX, this.scaleY];
|
||||||
|
},
|
||||||
|
|
||||||
|
setPosition : function(x, y) {
|
||||||
|
[this.x, this.y] = arguments;
|
||||||
|
},
|
||||||
|
|
||||||
|
setScale : function(scaleX, scaleY) {
|
||||||
|
[this.scaleX, this.scaleY] = arguments;
|
||||||
|
},
|
||||||
|
|
||||||
|
interpPosition : function(other, step) {
|
||||||
|
return [_interpolate(this.x, other.x, step),
|
||||||
|
_interpolate(this.y, other.y, step)];
|
||||||
|
},
|
||||||
|
|
||||||
|
interpScale : function(other, step) {
|
||||||
|
return [_interpolate(this.scaleX, other.scaleX, step),
|
||||||
|
_interpolate(this.scaleY, other.scaleY, step)];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
function WindowClone(realWindow) {
|
function WindowClone(realWindow) {
|
||||||
this._init(realWindow);
|
this._init(realWindow);
|
||||||
@@ -61,12 +107,18 @@ WindowClone.prototype = {
|
|||||||
this.actor._delegate = this;
|
this.actor._delegate = this;
|
||||||
this.realWindow = realWindow;
|
this.realWindow = realWindow;
|
||||||
this.metaWindow = realWindow.meta_window;
|
this.metaWindow = realWindow.meta_window;
|
||||||
|
this.metaWindow._delegate = this;
|
||||||
this.origX = realWindow.x;
|
this.origX = realWindow.x;
|
||||||
this.origY = realWindow.y;
|
this.origY = realWindow.y;
|
||||||
|
|
||||||
|
this._title = null;
|
||||||
|
|
||||||
this.actor.connect('button-release-event',
|
this.actor.connect('button-release-event',
|
||||||
Lang.bind(this, this._onButtonRelease));
|
Lang.bind(this, this._onButtonRelease));
|
||||||
|
|
||||||
|
this.actor.connect('scroll-event',
|
||||||
|
Lang.bind(this, this._onScroll));
|
||||||
|
|
||||||
this.actor.connect('enter-event',
|
this.actor.connect('enter-event',
|
||||||
Lang.bind(this, this._onEnter));
|
Lang.bind(this, this._onEnter));
|
||||||
this.actor.connect('leave-event',
|
this.actor.connect('leave-event',
|
||||||
@@ -79,6 +131,18 @@ WindowClone.prototype = {
|
|||||||
this._inDrag = false;
|
this._inDrag = false;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
setVisibleWithChrome: function(visible) {
|
||||||
|
if (visible) {
|
||||||
|
this.actor.show();
|
||||||
|
if (this._title)
|
||||||
|
this._title.show();
|
||||||
|
} else {
|
||||||
|
this.actor.hide();
|
||||||
|
if (this._title)
|
||||||
|
this._title.hide();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
destroy: function () {
|
destroy: function () {
|
||||||
this.actor.destroy();
|
this.actor.destroy();
|
||||||
if (this._title)
|
if (this._title)
|
||||||
@@ -104,12 +168,87 @@ WindowClone.prototype = {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
this._havePointer = false;
|
this._havePointer = false;
|
||||||
|
|
||||||
if (Tweener.isTweening(this.actor))
|
|
||||||
return;
|
|
||||||
|
|
||||||
actor.raise(this.stackAbove);
|
|
||||||
this._updateTitle();
|
this._updateTitle();
|
||||||
|
|
||||||
|
if (this._zoomStep)
|
||||||
|
this._zoomEnd();
|
||||||
|
},
|
||||||
|
|
||||||
|
_onScroll : function (actor, event) {
|
||||||
|
let direction = event.get_scroll_direction();
|
||||||
|
if (direction == Clutter.ScrollDirection.UP) {
|
||||||
|
if (this._zoomStep == undefined)
|
||||||
|
this._zoomStart();
|
||||||
|
if (this._zoomStep < 100) {
|
||||||
|
this._zoomStep += SCROLL_SCALE_AMOUNT;
|
||||||
|
this._zoomUpdate();
|
||||||
|
}
|
||||||
|
} else if (direction == Clutter.ScrollDirection.DOWN) {
|
||||||
|
if (this._zoomStep > 0) {
|
||||||
|
this._zoomStep -= SCROLL_SCALE_AMOUNT;
|
||||||
|
this._zoomStep = Math.max(0, this._zoomStep);
|
||||||
|
this._zoomUpdate();
|
||||||
|
}
|
||||||
|
if (this._zoomStep <= 0.0)
|
||||||
|
this._zoomEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
_zoomUpdate : function () {
|
||||||
|
[this.actor.x, this.actor.y] = this._zoomGlobalOrig.interpPosition(this._zoomTarget, this._zoomStep / 100);
|
||||||
|
[this.actor.scale_x, this.actor.scale_y] = this._zoomGlobalOrig.interpScale(this._zoomTarget, this._zoomStep / 100);
|
||||||
|
|
||||||
|
let [width, height] = this.actor.get_transformed_size();
|
||||||
|
|
||||||
|
this.actor.x = _clamp(this.actor.x, 0, global.screen_width - width);
|
||||||
|
this.actor.y = _clamp(this.actor.y, Panel.PANEL_HEIGHT, global.screen_height - height);
|
||||||
|
},
|
||||||
|
|
||||||
|
_zoomStart : function () {
|
||||||
|
this._zoomLightbox = new Lightbox.Lightbox(global.stage);
|
||||||
|
|
||||||
|
this._zoomLocalOrig = new ScaledPoint(this.actor.x, this.actor.y, this.actor.scale_x, this.actor.scale_y);
|
||||||
|
this._zoomGlobalOrig = new ScaledPoint();
|
||||||
|
let parent = this._origParent = this.actor.get_parent();
|
||||||
|
let [width, height] = this.actor.get_transformed_size();
|
||||||
|
this._zoomGlobalOrig.setPosition.apply(this._zoomGlobalOrig, this.actor.get_transformed_position());
|
||||||
|
this._zoomGlobalOrig.setScale(width / this.actor.width, height / this.actor.height);
|
||||||
|
|
||||||
|
this.actor.reparent(global.stage);
|
||||||
|
this._zoomLightbox.highlight(this.actor);
|
||||||
|
|
||||||
|
[this.actor.x, this.actor.y] = this._zoomGlobalOrig.getPosition();
|
||||||
|
[this.actor.scale_x, this.actor.scale_y] = this._zoomGlobalOrig.getScale();
|
||||||
|
|
||||||
|
this.actor.raise_top();
|
||||||
|
|
||||||
|
this._zoomTarget = new ScaledPoint(0, 0, 1.0, 1.0);
|
||||||
|
this._zoomTarget.setPosition(this.actor.x - (this.actor.width - width) / 2, this.actor.y - (this.actor.height - height) / 2);
|
||||||
|
this._zoomStep = 0;
|
||||||
|
|
||||||
|
this._hideEventId = Main.overview.connect('hiding', Lang.bind(this, function () { this._zoomEnd(); }));
|
||||||
|
this._zoomUpdate();
|
||||||
|
},
|
||||||
|
|
||||||
|
_zoomEnd : function () {
|
||||||
|
this.actor.reparent(this._origParent);
|
||||||
|
|
||||||
|
[this.actor.x, this.actor.y] = this._zoomLocalOrig.getPosition();
|
||||||
|
[this.actor.scale_x, this.actor.scale_y] = this._zoomLocalOrig.getScale();
|
||||||
|
|
||||||
|
this._adjustTitle();
|
||||||
|
|
||||||
|
this._zoomLightbox.destroy();
|
||||||
|
Main.overview.disconnect(this._hideEventId);
|
||||||
|
|
||||||
|
this._zoomLocalPosition = undefined;
|
||||||
|
this._zoomLocalScale = undefined;
|
||||||
|
this._zoomGlobalPosition = undefined;
|
||||||
|
this._zoomGlobalScale = undefined;
|
||||||
|
this._zoomTargetPosition = undefined;
|
||||||
|
this._zoomStep = undefined;
|
||||||
|
this._zoomLightbox = undefined;
|
||||||
},
|
},
|
||||||
|
|
||||||
_onButtonRelease : function (actor, event) {
|
_onButtonRelease : function (actor, event) {
|
||||||
@@ -231,7 +370,6 @@ DesktopClone.prototype = {
|
|||||||
this.actor = new Clutter.Clone({ source: window.get_texture(),
|
this.actor = new Clutter.Clone({ source: window.get_texture(),
|
||||||
reactive: true });
|
reactive: true });
|
||||||
} else {
|
} else {
|
||||||
let global = Shell.Global.get();
|
|
||||||
this.actor = new Clutter.Rectangle({ color: global.stage.color,
|
this.actor = new Clutter.Rectangle({ color: global.stage.color,
|
||||||
reactive: true,
|
reactive: true,
|
||||||
width: global.screen_width,
|
width: global.screen_width,
|
||||||
@@ -262,9 +400,6 @@ function Workspace(workspaceNum, parentActor) {
|
|||||||
|
|
||||||
Workspace.prototype = {
|
Workspace.prototype = {
|
||||||
_init : function(workspaceNum, parentActor) {
|
_init : function(workspaceNum, parentActor) {
|
||||||
let me = this;
|
|
||||||
let global = Shell.Global.get();
|
|
||||||
|
|
||||||
this.workspaceNum = workspaceNum;
|
this.workspaceNum = workspaceNum;
|
||||||
this._metaWorkspace = global.screen.get_workspace_by_index(workspaceNum);
|
this._metaWorkspace = global.screen.get_workspace_by_index(workspaceNum);
|
||||||
|
|
||||||
@@ -311,6 +446,9 @@ Workspace.prototype = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A filter for what windows we display
|
||||||
|
this._showOnlyWindows = null;
|
||||||
|
|
||||||
// Track window changes
|
// Track window changes
|
||||||
this._windowAddedId = this._metaWorkspace.connect('window-added',
|
this._windowAddedId = this._metaWorkspace.connect('window-added',
|
||||||
Lang.bind(this, this._windowAdded));
|
Lang.bind(this, this._windowAdded));
|
||||||
@@ -326,7 +464,6 @@ Workspace.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
updateRemovable : function() {
|
updateRemovable : function() {
|
||||||
let global = Shell.Global.get();
|
|
||||||
let removable = (this._windows.length == 1 /* just desktop */ &&
|
let removable = (this._windows.length == 1 /* just desktop */ &&
|
||||||
this.workspaceNum != 0 &&
|
this.workspaceNum != 0 &&
|
||||||
this.workspaceNum == global.screen.n_workspaces - 1);
|
this.workspaceNum == global.screen.n_workspaces - 1);
|
||||||
@@ -335,8 +472,8 @@ Workspace.prototype = {
|
|||||||
if (this._removeButton)
|
if (this._removeButton)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this._removeButton = new Clutter.Texture({ width: buttonSize,
|
this._removeButton = new Clutter.Texture({ width: Overview.addRemoveButtonSize,
|
||||||
height: buttonSize,
|
height: Overview.addRemoveButtonSize,
|
||||||
reactive: true
|
reactive: true
|
||||||
});
|
});
|
||||||
this._removeButton.set_from_file(global.imagedir + "remove-workspace.svg");
|
this._removeButton.set_from_file(global.imagedir + "remove-workspace.svg");
|
||||||
@@ -381,11 +518,59 @@ Workspace.prototype = {
|
|||||||
return -1;
|
return -1;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* lookupCloneForMetaWindow:
|
||||||
|
* @metaWindow: A #MetaWindow
|
||||||
|
*
|
||||||
|
* Given a #MetaWindow instance, find the WindowClone object
|
||||||
|
* which represents it in the workspaces display.
|
||||||
|
*/
|
||||||
lookupCloneForMetaWindow: function (metaWindow) {
|
lookupCloneForMetaWindow: function (metaWindow) {
|
||||||
let index = this._lookupIndex (metaWindow);
|
let index = this._lookupIndex (metaWindow);
|
||||||
return index < 0 ? null : this._windows[index];
|
return index < 0 ? null : this._windows[index];
|
||||||
},
|
},
|
||||||
|
|
||||||
|
containsMetaWindow: function (metaWindow) {
|
||||||
|
return this._lookupIndex(metaWindow) >= 0;
|
||||||
|
},
|
||||||
|
|
||||||
|
setShowOnlyWindows: function(showOnlyWindows, reposition) {
|
||||||
|
this._showOnlyWindows = showOnlyWindows;
|
||||||
|
this._resetCloneVisibility();
|
||||||
|
if (reposition)
|
||||||
|
this.positionWindows(false);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* setLightboxMode:
|
||||||
|
* @showLightbox: If true, dim background and allow highlighting a specific window
|
||||||
|
*
|
||||||
|
* This function also resets the highlighted window state.
|
||||||
|
*/
|
||||||
|
setLightboxMode: function (showLightbox) {
|
||||||
|
if (showLightbox) {
|
||||||
|
this._lightbox = new Lightbox.Lightbox(this.actor);
|
||||||
|
} else {
|
||||||
|
this._lightbox.destroy();
|
||||||
|
this._lightbox = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* setHighlightWindow:
|
||||||
|
* @metaWindow: A #MetaWindow
|
||||||
|
*
|
||||||
|
* Draw the user's attention to the given window @metaWindow.
|
||||||
|
*/
|
||||||
|
setHighlightWindow: function (metaWindow) {
|
||||||
|
let actor;
|
||||||
|
if (metaWindow != null) {
|
||||||
|
let clone = this.lookupCloneForMetaWindow(metaWindow);
|
||||||
|
actor = clone.actor;
|
||||||
|
}
|
||||||
|
this._lightbox.highlight(actor);
|
||||||
|
},
|
||||||
|
|
||||||
_adjustRemoveButton : function() {
|
_adjustRemoveButton : function() {
|
||||||
this._removeButton.set_scale(1.0 / this.actor.scale_x,
|
this._removeButton.set_scale(1.0 / this.actor.scale_x,
|
||||||
1.0 / this.actor.scale_y);
|
1.0 / this.actor.scale_y);
|
||||||
@@ -402,7 +587,6 @@ Workspace.prototype = {
|
|||||||
|
|
||||||
// Mark the workspace selected/not-selected
|
// Mark the workspace selected/not-selected
|
||||||
setSelected : function(selected) {
|
setSelected : function(selected) {
|
||||||
let global = Shell.Global.get();
|
|
||||||
// Don't draw a frame if we only have one workspace
|
// Don't draw a frame if we only have one workspace
|
||||||
if (selected && global.screen.n_workspaces > 1) {
|
if (selected && global.screen.n_workspaces > 1) {
|
||||||
if (this._frame)
|
if (this._frame)
|
||||||
@@ -434,35 +618,272 @@ Workspace.prototype = {
|
|||||||
this._desktop.actor.height + 2 * FRAME_SIZE / this.actor.scale_y);
|
this._desktop.actor.height + 2 * FRAME_SIZE / this.actor.scale_y);
|
||||||
},
|
},
|
||||||
|
|
||||||
// Reposition all windows in their zoomed-to-Overview position. if workspaceZooming
|
_resetCloneVisibility: function () {
|
||||||
// is true, then the workspace is moving at the same time and we need to take
|
|
||||||
// that into account
|
|
||||||
positionWindows : function(workspaceZooming) {
|
|
||||||
let global = Shell.Global.get();
|
|
||||||
|
|
||||||
for (let i = 1; i < this._windows.length; i++) {
|
for (let i = 1; i < this._windows.length; i++) {
|
||||||
let clone = this._windows[i];
|
let clone = this._windows[i];
|
||||||
let icon = this._windowIcons[i];
|
let icon = this._windowIcons[i];
|
||||||
clone.stackAbove = this._windows[i - 1].actor;
|
|
||||||
|
|
||||||
let [xCenter, yCenter, fraction] = this._computeWindowPosition(i);
|
if (this._showOnlyWindows != null && !(clone.metaWindow in this._showOnlyWindows)) {
|
||||||
xCenter = xCenter * global.screen_width;
|
clone.setVisibleWithChrome(false);
|
||||||
yCenter = yCenter * global.screen_height;
|
icon.hide();
|
||||||
|
} else {
|
||||||
|
clone.setVisibleWithChrome(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
// clone.actor.width/height aren't reliably set at this point for
|
// Only use this for n <= 20 say
|
||||||
// a new window - they're only set when the window contents are
|
_factorial: function(n) {
|
||||||
// initially updated prior to painting.
|
let result = 1;
|
||||||
let cloneRect = new Meta.Rectangle();
|
for (let i = 2; i <= n; i++)
|
||||||
clone.realWindow.meta_window.get_outer_rect(cloneRect);
|
result *= i;
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
|
||||||
let desiredWidth = global.screen_width * fraction;
|
/**
|
||||||
let desiredHeight = global.screen_height * fraction;
|
* _permutation:
|
||||||
let scale = Math.min(desiredWidth / cloneRect.width, desiredHeight / cloneRect.height, 1.0 / this.scale);
|
* @permutationIndex: An integer from [0, list.length!)
|
||||||
|
* @list: (inout): Array of objects to permute; will be modified in place
|
||||||
|
*
|
||||||
|
* Given an integer between 0 and length of array, re-order the array in-place
|
||||||
|
* into a permutation denoted by the index.
|
||||||
|
*/
|
||||||
|
_permutation: function(permutationIndex, list) {
|
||||||
|
for (let j = 2; j <= list.length; j++) {
|
||||||
|
let firstIndex = (permutationIndex % j);
|
||||||
|
let secondIndex = j - 1;
|
||||||
|
// Swap
|
||||||
|
let tmp = list[firstIndex];
|
||||||
|
list[firstIndex] = list[secondIndex];
|
||||||
|
list[secondIndex] = tmp;
|
||||||
|
permutationIndex = Math.floor(permutationIndex / j);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* _forEachPermutations:
|
||||||
|
* @list: Array
|
||||||
|
* @func: Function which takes a single array argument
|
||||||
|
*
|
||||||
|
* Call @func with each permutation of @list as an argument.
|
||||||
|
*/
|
||||||
|
_forEachPermutations: function(list, func) {
|
||||||
|
let nCombinations = this._factorial(list.length);
|
||||||
|
for (let i = 0; i < nCombinations; i++) {
|
||||||
|
let listCopy = list.concat();
|
||||||
|
this._permutation(i, listCopy);
|
||||||
|
func(listCopy);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* _computeWindowMotion:
|
||||||
|
* @metaWindow: A #MetaWindow
|
||||||
|
* @slot: An element of #POSITIONS
|
||||||
|
* @slotGeometry: Layout of @slot
|
||||||
|
*
|
||||||
|
* Returns a number corresponding to how much perceived motion
|
||||||
|
* would be involved in moving the window to the given slot.
|
||||||
|
* Currently this is the square of the distance between the
|
||||||
|
* centers.
|
||||||
|
*/
|
||||||
|
_computeWindowMotion: function (metaWindow, slot, slotGeometry) {
|
||||||
|
let rect = new Meta.Rectangle();
|
||||||
|
metaWindow.get_outer_rect(rect);
|
||||||
|
|
||||||
|
let [slotX, slotY, slotWidth, slotHeight] = slotGeometry;
|
||||||
|
let distanceSquared;
|
||||||
|
let xDelta, yDelta;
|
||||||
|
|
||||||
|
xDelta = (rect.x + rect.width / 2) - (slotX + slotWidth / 2);
|
||||||
|
yDelta = (rect.y + rect.height / 2) - (slotY + slotHeight / 2);
|
||||||
|
distanceSquared = xDelta * xDelta + yDelta * yDelta;
|
||||||
|
|
||||||
|
return distanceSquared;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* _orderWindowsPermutations:
|
||||||
|
*
|
||||||
|
* Iterate over all permutations of the windows, and determine the
|
||||||
|
* permutation which has the least total motion.
|
||||||
|
*/
|
||||||
|
_orderWindowsPermutations: function (windows, slots, slotGeometries) {
|
||||||
|
let minimumMotionPermutation = null;
|
||||||
|
let minimumMotion = -1;
|
||||||
|
let permIndex = 0;
|
||||||
|
this._forEachPermutations(windows, Lang.bind(this, function (permutation) {
|
||||||
|
let motion = 0;
|
||||||
|
for (let i = 0; i < permutation.length; i++) {
|
||||||
|
let metaWindow = permutation[i];
|
||||||
|
let slot = slots[i];
|
||||||
|
let slotAbsGeometry = slotGeometries[i];
|
||||||
|
|
||||||
|
let delta = this._computeWindowMotion(metaWindow, slot, slotAbsGeometry);
|
||||||
|
|
||||||
|
motion += delta;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (minimumMotionPermutation == null || motion < minimumMotion) {
|
||||||
|
minimumMotionPermutation = permutation;
|
||||||
|
minimumMotion = motion;
|
||||||
|
}
|
||||||
|
permIndex++;
|
||||||
|
}));
|
||||||
|
return minimumMotionPermutation;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* _orderWindowsGreedy:
|
||||||
|
*
|
||||||
|
* Iterate over available slots in order, placing into each one the window
|
||||||
|
* we find with the smallest motion to that slot.
|
||||||
|
*/
|
||||||
|
_orderWindowsGreedy: function(windows, slots, slotGeometries) {
|
||||||
|
let result = [];
|
||||||
|
let slotIndex = 0;
|
||||||
|
// Copy since we mutate below
|
||||||
|
let windowCopy = windows.concat();
|
||||||
|
for (let i = 0; i < slots.length; i++) {
|
||||||
|
let slot = slots[i];
|
||||||
|
let slotGeometry = slotGeometries[i];
|
||||||
|
let minimumMotionIndex = -1;
|
||||||
|
let minimumMotion = -1;
|
||||||
|
for (let j = 0; j < windowCopy.length; j++) {
|
||||||
|
let metaWindow = windowCopy[j];
|
||||||
|
let delta = this._computeWindowMotion(metaWindow, slot, slotGeometry);
|
||||||
|
if (minimumMotionIndex == -1 || delta < minimumMotion) {
|
||||||
|
minimumMotionIndex = j;
|
||||||
|
minimumMotion = delta;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.push(windowCopy[minimumMotionIndex]);
|
||||||
|
windowCopy.splice(minimumMotionIndex, 1);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* _orderWindowsByMotionAndStartup:
|
||||||
|
* @windows: Array of #MetaWindow
|
||||||
|
* @slots: Array of slots
|
||||||
|
*
|
||||||
|
* Returns a copy of @windows, ordered in such a way that they require least motion
|
||||||
|
* to move to the final screen coordinates of @slots. Ties are broken in a stable
|
||||||
|
* fashion by the order in which the windows were created.
|
||||||
|
*/
|
||||||
|
_orderWindowsByMotionAndStartup: function(windows, slots) {
|
||||||
|
let appMonitor = Shell.AppMonitor.get_default();
|
||||||
|
windows.sort(function(w1, w2) {
|
||||||
|
return w2.get_stable_sequence() - w1.get_stable_sequence();
|
||||||
|
});
|
||||||
|
let slotGeometries = slots.map(Lang.bind(this, this._getSlotAbsoluteGeometry));
|
||||||
|
if (windows.length <= POSITIONING_PERMUTATIONS_MAX)
|
||||||
|
return this._orderWindowsPermutations(windows, slots, slotGeometries);
|
||||||
|
else
|
||||||
|
return this._orderWindowsGreedy(windows, slots, slotGeometries);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* _getSlotRelativeGeometry:
|
||||||
|
* @slot: A layout slot
|
||||||
|
*
|
||||||
|
* Returns: the workspace-relative [x, y, width, height]
|
||||||
|
* of a given window layout slot.
|
||||||
|
*/
|
||||||
|
_getSlotRelativeGeometry: function(slot) {
|
||||||
|
let [xCenter, yCenter, fraction] = slot;
|
||||||
|
|
||||||
|
let width = global.screen_width * fraction;
|
||||||
|
let height = global.screen_height * fraction;
|
||||||
|
|
||||||
|
let x = xCenter * global.screen_width - width / 2;
|
||||||
|
let y = yCenter * global.screen_height - height / 2;
|
||||||
|
|
||||||
|
return [x, y, width, height];
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* _getSlotAbsoluteGeometry:
|
||||||
|
* @slot: A layout slot
|
||||||
|
*
|
||||||
|
* Returns: the screen coordiantes [x, y, width, height]
|
||||||
|
* of a given window layout slot.
|
||||||
|
*/
|
||||||
|
_getSlotAbsoluteGeometry: function(slot) {
|
||||||
|
let [x, y, width, height] = this._getSlotRelativeGeometry(slot);
|
||||||
|
return [ this.gridX + x, this.gridY + y,
|
||||||
|
this.scale * width, this.scale * height];
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* _computeWindowRelativeLayout:
|
||||||
|
* @metaWindow: A #MetaWindow
|
||||||
|
* @slot: A layout slot
|
||||||
|
*
|
||||||
|
* Given a window and slot to fit it in, compute its
|
||||||
|
* workspace-relative [x, y, scale] where scale applies
|
||||||
|
* to both X and Y directions.
|
||||||
|
*/
|
||||||
|
_computeWindowRelativeLayout: function(metaWindow, slot) {
|
||||||
|
let [xCenter, yCenter, fraction] = slot;
|
||||||
|
|
||||||
|
xCenter = xCenter * global.screen_width;
|
||||||
|
yCenter = yCenter * global.screen_height;
|
||||||
|
|
||||||
|
let rect = new Meta.Rectangle();
|
||||||
|
metaWindow.get_outer_rect(rect);
|
||||||
|
|
||||||
|
let desiredWidth = global.screen_width * fraction;
|
||||||
|
let desiredHeight = global.screen_height * fraction;
|
||||||
|
let scale = Math.min(desiredWidth / rect.width,
|
||||||
|
desiredHeight / rect.height,
|
||||||
|
1.0 / this.scale);
|
||||||
|
|
||||||
|
let x = xCenter - 0.5 * scale * rect.width;
|
||||||
|
let y = yCenter - 0.5 * scale * rect.height;
|
||||||
|
|
||||||
|
return [x, y, scale];
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* positionWindows:
|
||||||
|
* @workspaceZooming: If true, then the workspace is moving at the same time and we need to take that into account.
|
||||||
|
*/
|
||||||
|
positionWindows : function(workspaceZooming) {
|
||||||
|
let totalVisible = 0;
|
||||||
|
|
||||||
|
let visibleWindows = [];
|
||||||
|
|
||||||
|
for (let i = 1; i < this._windows.length; i++) {
|
||||||
|
let clone = this._windows[i];
|
||||||
|
|
||||||
|
if (this._showOnlyWindows != null && !(clone.metaWindow in this._showOnlyWindows))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
visibleWindows.push(clone.metaWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
let slots = this._computeAllWindowSlots(visibleWindows.length);
|
||||||
|
visibleWindows = this._orderWindowsByMotionAndStartup(visibleWindows, slots);
|
||||||
|
|
||||||
|
let previousWindow = this._windows[0];
|
||||||
|
for (let i = 0; i < visibleWindows.length; i++) {
|
||||||
|
let slot = slots[i];
|
||||||
|
let metaWindow = visibleWindows[i];
|
||||||
|
let mainIndex = this._lookupIndex(metaWindow);
|
||||||
|
let clone = metaWindow._delegate;
|
||||||
|
let icon = this._windowIcons[mainIndex];
|
||||||
|
|
||||||
|
clone.stackAbove = previousWindow.actor;
|
||||||
|
previousWindow = clone;
|
||||||
|
|
||||||
|
let [x, y, scale] = this._computeWindowRelativeLayout(metaWindow, slot);
|
||||||
|
|
||||||
icon.hide();
|
icon.hide();
|
||||||
Tweener.addTween(clone.actor,
|
Tweener.addTween(clone.actor,
|
||||||
{ x: xCenter - 0.5 * scale * cloneRect.width,
|
{ x: x,
|
||||||
y: yCenter - 0.5 * scale * cloneRect.height,
|
y: y,
|
||||||
scale_x: scale,
|
scale_x: scale,
|
||||||
scale_y: scale,
|
scale_y: scale,
|
||||||
workspace_relative: workspaceZooming ? this : null,
|
workspace_relative: workspaceZooming ? this : null,
|
||||||
@@ -508,6 +929,8 @@ Workspace.prototype = {
|
|||||||
for (let i = 1; i < this._windows.length; i++) {
|
for (let i = 1; i < this._windows.length; i++) {
|
||||||
let clone = this._windows[i];
|
let clone = this._windows[i];
|
||||||
let icon = this._windowIcons[i];
|
let icon = this._windowIcons[i];
|
||||||
|
if (this._showOnlyWindows != null && !(clone.metaWindow in this._showOnlyWindows))
|
||||||
|
continue;
|
||||||
this._fadeInWindowIcon(clone, icon);
|
this._fadeInWindowIcon(clone, icon);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -520,7 +943,6 @@ Workspace.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
_windowRemoved : function(metaWorkspace, metaWin) {
|
_windowRemoved : function(metaWorkspace, metaWin) {
|
||||||
let global = Shell.Global.get();
|
|
||||||
let win = metaWin.get_compositor_private();
|
let win = metaWin.get_compositor_private();
|
||||||
|
|
||||||
// find the position of the window in our list
|
// find the position of the window in our list
|
||||||
@@ -672,8 +1094,6 @@ Workspace.prototype = {
|
|||||||
|
|
||||||
// Animates the addition of a new (empty) workspace
|
// Animates the addition of a new (empty) workspace
|
||||||
slideIn : function(oldScale) {
|
slideIn : function(oldScale) {
|
||||||
let global = Shell.Global.get();
|
|
||||||
|
|
||||||
if (this.gridCol > this.gridRow) {
|
if (this.gridCol > this.gridRow) {
|
||||||
this.actor.set_position(global.screen_width, this.gridY);
|
this.actor.set_position(global.screen_width, this.gridY);
|
||||||
this.actor.set_scale(oldScale, oldScale);
|
this.actor.set_scale(oldScale, oldScale);
|
||||||
@@ -695,7 +1115,6 @@ Workspace.prototype = {
|
|||||||
|
|
||||||
// Animates the removal of a workspace
|
// Animates the removal of a workspace
|
||||||
slideOut : function(onComplete) {
|
slideOut : function(onComplete) {
|
||||||
let global = Shell.Global.get();
|
|
||||||
let destX = this.actor.x, destY = this.actor.y;
|
let destX = this.actor.x, destY = this.actor.y;
|
||||||
|
|
||||||
this._hideAllIcons();
|
this._hideAllIcons();
|
||||||
@@ -722,8 +1141,6 @@ Workspace.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
destroy : function() {
|
destroy : function() {
|
||||||
let global = Shell.Global.get();
|
|
||||||
|
|
||||||
Tweener.removeTweens(this.actor);
|
Tweener.removeTweens(this.actor);
|
||||||
this.actor.destroy();
|
this.actor.destroy();
|
||||||
this.actor = null;
|
this.actor = null;
|
||||||
@@ -745,11 +1162,8 @@ Workspace.prototype = {
|
|||||||
|
|
||||||
// Tests if @win should be shown in the Overview
|
// Tests if @win should be shown in the Overview
|
||||||
_isOverviewWindow : function (win) {
|
_isOverviewWindow : function (win) {
|
||||||
let wintype = win.get_window_type();
|
let appMon = Shell.AppMonitor.get_default()
|
||||||
if (wintype == Meta.WindowType.DESKTOP ||
|
return appMon.is_window_usage_tracked(win.get_meta_window());
|
||||||
wintype == Meta.WindowType.DOCK)
|
|
||||||
return false;
|
|
||||||
return !win.is_override_redirect();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_createWindowIcon: function(window) {
|
_createWindowIcon: function(window) {
|
||||||
@@ -797,11 +1211,7 @@ Workspace.prototype = {
|
|||||||
return clone;
|
return clone;
|
||||||
},
|
},
|
||||||
|
|
||||||
_computeWindowPosition : function(index) {
|
_computeWindowSlot : function(windowIndex, numberOfWindows) {
|
||||||
// ignore this._windows[0], which is the desktop
|
|
||||||
let windowIndex = index - 1;
|
|
||||||
let numberOfWindows = this._windows.length - 1;
|
|
||||||
|
|
||||||
if (numberOfWindows in POSITIONS)
|
if (numberOfWindows in POSITIONS)
|
||||||
return POSITIONS[numberOfWindows][windowIndex];
|
return POSITIONS[numberOfWindows][windowIndex];
|
||||||
|
|
||||||
@@ -818,12 +1228,19 @@ Workspace.prototype = {
|
|||||||
return [xCenter, yCenter, fraction];
|
return [xCenter, yCenter, fraction];
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_computeAllWindowSlots: function(totalWindows) {
|
||||||
|
let slots = [];
|
||||||
|
for (let i = 0; i < totalWindows; i++) {
|
||||||
|
slots.push(this._computeWindowSlot(i, totalWindows));
|
||||||
|
}
|
||||||
|
return slots;
|
||||||
|
},
|
||||||
|
|
||||||
_onCloneSelected : function (clone, time) {
|
_onCloneSelected : function (clone, time) {
|
||||||
Main.overview.activateWindow(clone.metaWindow, time);
|
Main.overview.activateWindow(clone.metaWindow, time);
|
||||||
},
|
},
|
||||||
|
|
||||||
_removeSelf : function(actor, event) {
|
_removeSelf : function(actor, event) {
|
||||||
let global = Shell.Global.get();
|
|
||||||
let screen = global.screen;
|
let screen = global.screen;
|
||||||
let workspace = screen.get_workspace_by_index(this.workspaceNum);
|
let workspace = screen.get_workspace_by_index(this.workspaceNum);
|
||||||
|
|
||||||
@@ -833,8 +1250,6 @@ Workspace.prototype = {
|
|||||||
|
|
||||||
// Draggable target interface
|
// Draggable target interface
|
||||||
acceptDrop : function(source, actor, x, y, time) {
|
acceptDrop : function(source, actor, x, y, time) {
|
||||||
let global = Shell.Global.get();
|
|
||||||
|
|
||||||
if (source instanceof WindowClone) {
|
if (source instanceof WindowClone) {
|
||||||
let win = source.realWindow;
|
let win = source.realWindow;
|
||||||
if (this._isMyWindow(win))
|
if (this._isMyWindow(win))
|
||||||
@@ -865,25 +1280,25 @@ Workspace.prototype = {
|
|||||||
|
|
||||||
Signals.addSignalMethods(Workspace.prototype);
|
Signals.addSignalMethods(Workspace.prototype);
|
||||||
|
|
||||||
function Workspaces(width, height, x, y, addButtonSize, addButtonX, addButtonY) {
|
function Workspaces(width, height, x, y) {
|
||||||
this._init(width, height, x, y, addButtonSize, addButtonX, addButtonY);
|
this._init(width, height, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
Workspaces.prototype = {
|
Workspaces.prototype = {
|
||||||
_init : function(width, height, x, y, addButtonSize, addButtonX, addButtonY) {
|
_init : function(width, height, x, y) {
|
||||||
let global = Shell.Global.get();
|
|
||||||
|
|
||||||
this.actor = new Clutter.Group();
|
this.actor = new Clutter.Group();
|
||||||
|
|
||||||
let screenHeight = global.screen_height;
|
|
||||||
|
|
||||||
this._width = width;
|
this._width = width;
|
||||||
this._height = height;
|
this._height = height;
|
||||||
this._x = x;
|
this._x = x;
|
||||||
this._y = y;
|
this._y = y;
|
||||||
|
|
||||||
|
this._windowSelectionAppId = null;
|
||||||
|
|
||||||
this._workspaces = [];
|
this._workspaces = [];
|
||||||
|
|
||||||
|
this._highlightWindow = null;
|
||||||
|
|
||||||
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
|
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
|
||||||
let activeWorkspace;
|
let activeWorkspace;
|
||||||
|
|
||||||
@@ -896,17 +1311,7 @@ Workspaces.prototype = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
activeWorkspace.actor.raise_top();
|
activeWorkspace.actor.raise_top();
|
||||||
this._positionWorkspaces(global, activeWorkspace);
|
this._positionWorkspaces();
|
||||||
|
|
||||||
// Save the button size as a global variable so we can us it to create
|
|
||||||
// matching button sizes for workspace remove buttons.
|
|
||||||
buttonSize = addButtonSize;
|
|
||||||
|
|
||||||
// Create (+) button
|
|
||||||
this.addButton = new AddWorkspaceButton(addButtonSize, addButtonX, addButtonY, Lang.bind(this, this._addWorkspaceAcceptDrop));
|
|
||||||
this.addButton.actor.connect('button-release-event', Lang.bind(this, this._appendNewWorkspace));
|
|
||||||
this.actor.add_actor(this.addButton.actor);
|
|
||||||
this.addButton.actor.lower_bottom();
|
|
||||||
|
|
||||||
let lastWorkspace = this._workspaces[this._workspaces.length - 1];
|
let lastWorkspace = this._workspaces[this._workspaces.length - 1];
|
||||||
lastWorkspace.updateRemovable(true);
|
lastWorkspace.updateRemovable(true);
|
||||||
@@ -930,6 +1335,14 @@ Workspaces.prototype = {
|
|||||||
Lang.bind(this, this._activeWorkspaceChanged));
|
Lang.bind(this, this._activeWorkspaceChanged));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_lookupWorkspaceForMetaWindow: function (metaWindow) {
|
||||||
|
for (let i = 0; i < this._workspaces.length; i++) {
|
||||||
|
if (this._workspaces[i].containsMetaWindow(metaWindow))
|
||||||
|
return this._workspaces[i];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
|
||||||
_lookupCloneForMetaWindow: function (metaWindow) {
|
_lookupCloneForMetaWindow: function (metaWindow) {
|
||||||
for (let i = 0; i < this._workspaces.length; i++) {
|
for (let i = 0; i < this._workspaces.length; i++) {
|
||||||
let clone = this._workspaces[i].lookupCloneForMetaWindow(metaWindow);
|
let clone = this._workspaces[i].lookupCloneForMetaWindow(metaWindow);
|
||||||
@@ -939,29 +1352,88 @@ Workspaces.prototype = {
|
|||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
|
|
||||||
// Should only be called from active Overview context
|
setHighlightWindow: function (metaWindow) {
|
||||||
|
// Looping over all workspaces is easier than keeping track of the last
|
||||||
|
// highlighted window while trying to handle the window or workspace possibly
|
||||||
|
// going away.
|
||||||
|
for (let i = 0; i < this._workspaces.length; i++) {
|
||||||
|
this._workspaces[i].setHighlightWindow(null);
|
||||||
|
}
|
||||||
|
if (metaWindow != null) {
|
||||||
|
let workspace = this._lookupWorkspaceForMetaWindow(metaWindow);
|
||||||
|
workspace.setHighlightWindow(metaWindow);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_clearApplicationWindowSelection: function(reposition) {
|
||||||
|
if (this._windowSelectionAppId == null)
|
||||||
|
return;
|
||||||
|
this._windowSelectionAppId = null;
|
||||||
|
|
||||||
|
for (let i = 0; i < this._workspaces.length; i++) {
|
||||||
|
this._workspaces[i].setLightboxMode(false);
|
||||||
|
this._workspaces[i].setShowOnlyWindows(null, reposition);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* setApplicationWindowSelection:
|
||||||
|
* @appid: Application identifier string
|
||||||
|
*
|
||||||
|
* Enter a mode which shows only the windows owned by the
|
||||||
|
* given application, and allow highlighting of a specific
|
||||||
|
* window with setHighlightWindow().
|
||||||
|
*/
|
||||||
|
setApplicationWindowSelection: function (appId) {
|
||||||
|
if (appId == null) {
|
||||||
|
this._clearApplicationWindowSelection(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (appId == this._windowSelectionAppId)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this._windowSelectionAppId = appId;
|
||||||
|
|
||||||
|
let appSys = Shell.AppMonitor.get_default();
|
||||||
|
|
||||||
|
let showOnlyWindows = {};
|
||||||
|
let windows = appSys.get_windows_for_app(appId);
|
||||||
|
for (let i = 0; i < windows.length; i++) {
|
||||||
|
showOnlyWindows[windows[i]] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < this._workspaces.length; i++) {
|
||||||
|
this._workspaces[i].setLightboxMode(true);
|
||||||
|
this._workspaces[i].setShowOnlyWindows(showOnlyWindows, true);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* activateWindowFromOverview:
|
||||||
|
* @metaWindow: A #MetaWindow
|
||||||
|
* @time: Integer even timestamp
|
||||||
|
*
|
||||||
|
* This function exits the overview, switching to the given @metaWindow.
|
||||||
|
* If an application filter is in effect, it will be cleared.
|
||||||
|
*/
|
||||||
activateWindowFromOverview: function (metaWindow, time) {
|
activateWindowFromOverview: function (metaWindow, time) {
|
||||||
let global = Shell.Global.get();
|
if (this._windowSelectionAppId != null) {
|
||||||
let activeWorkspaceNum = global.screen.get_active_workspace_index();
|
this._clearApplicationWindowSelection(false);
|
||||||
let windowWorkspaceNum = metaWindow.get_workspace().index();
|
}
|
||||||
|
|
||||||
let clone = this._lookupCloneForMetaWindow (metaWindow);
|
let clone = this._lookupCloneForMetaWindow (metaWindow);
|
||||||
clone.actor.raise_top();
|
clone.actor.raise_top();
|
||||||
|
|
||||||
if (windowWorkspaceNum != activeWorkspaceNum) {
|
Main.activateWindow(metaWindow, time);
|
||||||
let workspace = global.screen.get_workspace_by_index(windowWorkspaceNum);
|
Main.overview.hide();
|
||||||
workspace.activate_with_focus(metaWindow, time);
|
|
||||||
} else {
|
|
||||||
metaWindow.activate(time);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
hide : function() {
|
hide : function() {
|
||||||
let global = Shell.Global.get();
|
|
||||||
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
|
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
|
||||||
let activeWorkspace = this._workspaces[activeWorkspaceIndex];
|
let activeWorkspace = this._workspaces[activeWorkspaceIndex];
|
||||||
|
|
||||||
this._positionWorkspaces(global, activeWorkspace);
|
this._positionWorkspaces();
|
||||||
activeWorkspace.actor.raise_top();
|
activeWorkspace.actor.raise_top();
|
||||||
|
|
||||||
for (let w = 0; w < this._workspaces.length; w++)
|
for (let w = 0; w < this._workspaces.length; w++)
|
||||||
@@ -969,8 +1441,6 @@ Workspaces.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
destroy : function() {
|
destroy : function() {
|
||||||
let global = Shell.Global.get();
|
|
||||||
|
|
||||||
for (let w = 0; w < this._workspaces.length; w++)
|
for (let w = 0; w < this._workspaces.length; w++)
|
||||||
this._workspaces[w].destroy();
|
this._workspaces[w].destroy();
|
||||||
this._workspaces = [];
|
this._workspaces = [];
|
||||||
@@ -988,7 +1458,6 @@ Workspaces.prototype = {
|
|||||||
|
|
||||||
// Get the grid position of the active workspace.
|
// Get the grid position of the active workspace.
|
||||||
getActiveWorkspacePosition : function() {
|
getActiveWorkspacePosition : function() {
|
||||||
let global = Shell.Global.get();
|
|
||||||
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
|
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
|
||||||
let activeWorkspace = this._workspaces[activeWorkspaceIndex];
|
let activeWorkspace = this._workspaces[activeWorkspaceIndex];
|
||||||
|
|
||||||
@@ -1005,12 +1474,7 @@ Workspaces.prototype = {
|
|||||||
// first row.)
|
// first row.)
|
||||||
//
|
//
|
||||||
// FIXME: need to make the metacity internal layout agree with this!
|
// FIXME: need to make the metacity internal layout agree with this!
|
||||||
_positionWorkspaces : function(global, activeWorkspace) {
|
_positionWorkspaces : function() {
|
||||||
if (!activeWorkspace) {
|
|
||||||
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
|
|
||||||
activeWorkspace = this._workspaces[activeWorkspaceIndex];
|
|
||||||
}
|
|
||||||
|
|
||||||
let gridWidth = Math.ceil(Math.sqrt(this._workspaces.length));
|
let gridWidth = Math.ceil(Math.sqrt(this._workspaces.length));
|
||||||
let gridHeight = Math.ceil(this._workspaces.length / gridWidth);
|
let gridHeight = Math.ceil(this._workspaces.length / gridWidth);
|
||||||
|
|
||||||
@@ -1048,8 +1512,6 @@ Workspaces.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
_workspacesChanged : function() {
|
_workspacesChanged : function() {
|
||||||
let global = Shell.Global.get();
|
|
||||||
|
|
||||||
let oldNumWorkspaces = this._workspaces.length;
|
let oldNumWorkspaces = this._workspaces.length;
|
||||||
let newNumWorkspaces = global.screen.n_workspaces;
|
let newNumWorkspaces = global.screen.n_workspaces;
|
||||||
|
|
||||||
@@ -1082,7 +1544,7 @@ Workspaces.prototype = {
|
|||||||
newLastWorkspace.updateRemovable();
|
newLastWorkspace.updateRemovable();
|
||||||
|
|
||||||
// Figure out the new layout
|
// Figure out the new layout
|
||||||
this._positionWorkspaces(global);
|
this._positionWorkspaces();
|
||||||
let newScale = this._workspaces[0].scale;
|
let newScale = this._workspaces[0].scale;
|
||||||
let newGridWidth = Math.ceil(Math.sqrt(newNumWorkspaces));
|
let newGridWidth = Math.ceil(Math.sqrt(newNumWorkspaces));
|
||||||
let newGridHeight = Math.ceil(newNumWorkspaces / newGridWidth);
|
let newGridHeight = Math.ceil(newNumWorkspaces / newGridWidth);
|
||||||
@@ -1133,42 +1595,13 @@ Workspaces.prototype = {
|
|||||||
this.actor.add_actor(workspace.actor);
|
this.actor.add_actor(workspace.actor);
|
||||||
},
|
},
|
||||||
|
|
||||||
_appendNewWorkspace : function() {
|
// Handles a drop onto the (+) button; assumes the new workspace
|
||||||
let global = Shell.Global.get();
|
// has already been added
|
||||||
|
acceptNewWorkspaceDrop : function(source, dropActor, x, y, time) {
|
||||||
global.screen.append_new_workspace(false, global.screen.get_display().get_current_time());
|
|
||||||
},
|
|
||||||
|
|
||||||
// Creates a new workspace and drops the dropActor there
|
|
||||||
_addWorkspaceAcceptDrop : function(source, dropActor, x, y, time) {
|
|
||||||
this._appendNewWorkspace();
|
|
||||||
return this._workspaces[this._workspaces.length - 1].acceptDrop(source, dropActor, x, y, time);
|
return this._workspaces[this._workspaces.length - 1].acceptDrop(source, dropActor, x, y, time);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function AddWorkspaceButton(buttonSize, buttonX, buttonY, acceptDropCallback) {
|
|
||||||
this._init(buttonSize, buttonX, buttonY, acceptDropCallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
AddWorkspaceButton.prototype = {
|
|
||||||
_init : function(buttonSize, buttonX, buttonY, acceptDropCallback) {
|
|
||||||
this.actor = new Clutter.Texture({ x: buttonX,
|
|
||||||
y: buttonY,
|
|
||||||
width: buttonSize,
|
|
||||||
height: buttonSize,
|
|
||||||
reactive: true });
|
|
||||||
this._acceptDropCallback = acceptDropCallback;
|
|
||||||
let global = Shell.Global.get();
|
|
||||||
this.actor._delegate = this;
|
|
||||||
this.actor.set_from_file(global.imagedir + 'add-workspace.svg');
|
|
||||||
},
|
|
||||||
|
|
||||||
// Draggable target interface
|
|
||||||
acceptDrop : function(source, actor, x, y, time) {
|
|
||||||
return this._acceptDropCallback(source, actor, x, y, time);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Create a SpecialPropertyModifier to let us move windows in a
|
// Create a SpecialPropertyModifier to let us move windows in a
|
||||||
// straight line on the screen even though their containing workspace
|
// straight line on the screen even though their containing workspace
|
||||||
// is also moving.
|
// is also moving.
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
|
ar
|
||||||
ca
|
ca
|
||||||
cs
|
cs
|
||||||
|
da
|
||||||
de
|
de
|
||||||
|
en_GB
|
||||||
es
|
es
|
||||||
fr
|
fr
|
||||||
ga
|
ga
|
||||||
@@ -10,7 +13,10 @@ it
|
|||||||
ko
|
ko
|
||||||
nb
|
nb
|
||||||
nl
|
nl
|
||||||
|
pa
|
||||||
pl
|
pl
|
||||||
pt_BR
|
pt_BR
|
||||||
|
sl
|
||||||
sv
|
sv
|
||||||
tr
|
tr
|
||||||
|
zh_CN
|
||||||
|
|||||||
201
po/ar.po
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
# SOME DESCRIPTIVE TITLE.
|
||||||
|
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||||
|
# This file is distributed under the same license as the PACKAGE package.
|
||||||
|
# Khaled Hosny <khaledhosny@eglug.org>, 2009.
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: HEAD\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2009-09-25 04:22+0200\n"
|
||||||
|
"PO-Revision-Date: 2009-09-25 04:21+0300\n"
|
||||||
|
"Last-Translator: Khaled Hosny <khaledhosny@eglug.org>\n"
|
||||||
|
"Language-Team: Arabic <doc@arabeyes.org>\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Language: ar\n"
|
||||||
|
"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 "
|
||||||
|
"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n"
|
||||||
|
"X-Generator: Virtaal 0.4.0\n"
|
||||||
|
|
||||||
|
#: ../data/gnome-shell.desktop.in.in.h:1
|
||||||
|
msgid "GNOME Shell"
|
||||||
|
msgstr "صدفة جنوم"
|
||||||
|
|
||||||
|
#: ../data/gnome-shell.desktop.in.in.h:2
|
||||||
|
msgid "Window management and application launching"
|
||||||
|
msgstr "إدارة النوافذ وإطلاق التطبيقات"
|
||||||
|
|
||||||
|
#. left side
|
||||||
|
#: ../js/ui/panel.js:269
|
||||||
|
msgid "Activities"
|
||||||
|
msgstr "الأنشطة"
|
||||||
|
|
||||||
|
#. Translators: This is a time format.
|
||||||
|
#: ../js/ui/panel.js:452
|
||||||
|
msgid "%a %l:%M %p"
|
||||||
|
msgstr "%A %Ol:%OM %p"
|
||||||
|
|
||||||
|
#: ../js/ui/dash.js:283
|
||||||
|
msgid "Find..."
|
||||||
|
msgstr "ابحث..."
|
||||||
|
|
||||||
|
#: ../js/ui/dash.js:400
|
||||||
|
msgid "Browse"
|
||||||
|
msgstr "استعرض"
|
||||||
|
|
||||||
|
#: ../js/ui/dash.js:536
|
||||||
|
msgid "(see all)"
|
||||||
|
msgstr "(انظر الكل)"
|
||||||
|
|
||||||
|
#. **** Applications ****
|
||||||
|
#: ../js/ui/dash.js:753 ../js/ui/dash.js:809
|
||||||
|
msgid "APPLICATIONS"
|
||||||
|
msgstr "التطبيقات"
|
||||||
|
|
||||||
|
#. **** Places ****
|
||||||
|
#. Translators: This is in the sense of locations for documents,
|
||||||
|
#. network locations, etc.
|
||||||
|
#: ../js/ui/dash.js:773
|
||||||
|
msgid "PLACES"
|
||||||
|
msgstr "الأماكن"
|
||||||
|
|
||||||
|
#. **** Documents ****
|
||||||
|
#: ../js/ui/dash.js:780 ../js/ui/dash.js:819
|
||||||
|
msgid "RECENT DOCUMENTS"
|
||||||
|
msgstr "المستندات الحديثة"
|
||||||
|
|
||||||
|
#. **** Search Results ****
|
||||||
|
#: ../js/ui/dash.js:799 ../js/ui/dash.js:931
|
||||||
|
msgid "SEARCH RESULTS"
|
||||||
|
msgstr "نتائج البحث"
|
||||||
|
|
||||||
|
#: ../js/ui/dash.js:814
|
||||||
|
msgid "PREFERENCES"
|
||||||
|
msgstr "التفضيلات"
|
||||||
|
|
||||||
|
#: ../js/ui/runDialog.js:95
|
||||||
|
msgid "Please enter a command:"
|
||||||
|
msgstr "من فضلك اكتب أمرا:"
|
||||||
|
|
||||||
|
#: ../src/shell-global.c:799
|
||||||
|
msgid "Less than a minute ago"
|
||||||
|
msgstr "منذ أقل من دقيقة"
|
||||||
|
|
||||||
|
#: ../src/shell-global.c:802
|
||||||
|
#, c-format
|
||||||
|
msgid "%d minute ago"
|
||||||
|
msgid_plural "%d minutes ago"
|
||||||
|
msgstr[0] "منذ أقل من دقيقة"
|
||||||
|
msgstr[1] "منذ دقيقة"
|
||||||
|
msgstr[2] "منذ دقيقتين"
|
||||||
|
msgstr[3] "منذ %d دقائق"
|
||||||
|
msgstr[4] "منذ %d دقيقة"
|
||||||
|
msgstr[5] "منذ %d دقيقة"
|
||||||
|
|
||||||
|
#: ../src/shell-global.c:805
|
||||||
|
#, c-format
|
||||||
|
msgid "%d hour ago"
|
||||||
|
msgid_plural "%d hours ago"
|
||||||
|
msgstr[0] "منذ أقل من ساعة"
|
||||||
|
msgstr[1] "منذ ساعة"
|
||||||
|
msgstr[2] "منذ ساعتين"
|
||||||
|
msgstr[3] "منذ %d ساعات"
|
||||||
|
msgstr[4] "منذ %d ساعة"
|
||||||
|
msgstr[5] "منذ %d ساعة"
|
||||||
|
|
||||||
|
#: ../src/shell-global.c:808
|
||||||
|
#, c-format
|
||||||
|
msgid "%d day ago"
|
||||||
|
msgid_plural "%d days ago"
|
||||||
|
msgstr[0] "منذ أقل من يوم"
|
||||||
|
msgstr[1] "منذ يوم"
|
||||||
|
msgstr[2] "منذ يومين"
|
||||||
|
msgstr[3] "منذ %d أيام"
|
||||||
|
msgstr[4] "منذ %d يوما"
|
||||||
|
msgstr[5] "منذ %d يوم"
|
||||||
|
|
||||||
|
#: ../src/shell-global.c:811
|
||||||
|
#, c-format
|
||||||
|
msgid "%d week ago"
|
||||||
|
msgid_plural "%d weeks ago"
|
||||||
|
msgstr[0] "منذ أقل من أسبوع"
|
||||||
|
msgstr[1] "منذ أسبوع"
|
||||||
|
msgstr[2] "منذ أسبوعين"
|
||||||
|
msgstr[3] "منذ %d أسابيع"
|
||||||
|
msgstr[4] "منذ %d أسبوعا"
|
||||||
|
msgstr[5] "منذ %d أسبوع"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:156
|
||||||
|
msgid "Unknown"
|
||||||
|
msgstr "مجهول"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:212
|
||||||
|
#, c-format
|
||||||
|
msgid "Can't lock screen: %s"
|
||||||
|
msgstr "تعذّر إيصاد الشاشة: %s"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:227
|
||||||
|
#, c-format
|
||||||
|
msgid "Can't temporarily set screensaver to blank screen: %s"
|
||||||
|
msgstr "تعذّر ضبك حافظة الشاشة مؤقتا لتكون شاشة خالية: %s"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:351
|
||||||
|
#, c-format
|
||||||
|
msgid "Can't logout: %s"
|
||||||
|
msgstr "تعذّر الخروج: %s"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:492
|
||||||
|
msgid "Account Information..."
|
||||||
|
msgstr "معلومات الحساب..."
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:502
|
||||||
|
msgid "Sidebar"
|
||||||
|
msgstr "الشريط الجانبي"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:510
|
||||||
|
msgid "System Preferences..."
|
||||||
|
msgstr "تفضيلات النظام..."
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:525
|
||||||
|
msgid "Lock Screen"
|
||||||
|
msgstr "أوصد الشاشة"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:535
|
||||||
|
msgid "Switch User"
|
||||||
|
msgstr "بدّل المستخدم"
|
||||||
|
|
||||||
|
#. Only show switch user if there are other users
|
||||||
|
#. Log Out
|
||||||
|
#: ../src/shell-status-menu.c:546
|
||||||
|
msgid "Log Out..."
|
||||||
|
msgstr "اخرج..."
|
||||||
|
|
||||||
|
#. Shut down
|
||||||
|
#: ../src/shell-status-menu.c:557
|
||||||
|
msgid "Shut Down..."
|
||||||
|
msgstr "أطفئ..."
|
||||||
|
|
||||||
|
#: ../src/shell-uri-util.c:87
|
||||||
|
msgid "Home Folder"
|
||||||
|
msgstr "مجلد المنزل"
|
||||||
|
|
||||||
|
#. Translators: this is the same string as the one found in
|
||||||
|
#. * nautilus
|
||||||
|
#: ../src/shell-uri-util.c:102
|
||||||
|
msgid "File System"
|
||||||
|
msgstr "نظام الملفات"
|
||||||
|
|
||||||
|
#: ../src/shell-uri-util.c:248
|
||||||
|
msgid "Search"
|
||||||
|
msgstr "ابحث"
|
||||||
|
|
||||||
|
#. Translators: the first string is the name of a gvfs
|
||||||
|
#. * method, and the second string is a path. For
|
||||||
|
#. * example, "Trash: some-directory". It means that the
|
||||||
|
#. * directory called "some-directory" is in the trash.
|
||||||
|
#.
|
||||||
|
#: ../src/shell-uri-util.c:298
|
||||||
|
#, c-format
|
||||||
|
msgid "%1$s: %2$s"
|
||||||
|
msgstr "%1$s: %2$s"
|
||||||
108
po/ca.po
@@ -7,88 +7,99 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: HEAD\n"
|
"Project-Id-Version: HEAD\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2009-08-14 20:38+0200\n"
|
"POT-Creation-Date: 2009-08-30 18:53+0200\n"
|
||||||
"PO-Revision-Date: 2009-08-14 23:59+0100\n"
|
"PO-Revision-Date: 2009-08-30 18:57+0100\n"
|
||||||
"Last-Translator: Siegfried-Angel Gevatter Pujals <rainct@ubuntu.com>\n"
|
"Last-Translator: Siegfried-Angel Gevatter Pujals <rainct@ubuntu.com>\n"
|
||||||
|
"Language-Team: \n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
"Language-Team: \n"
|
|
||||||
|
#: ../data/gnome-shell.desktop.in.in.h:1
|
||||||
|
msgid "GNOME Shell"
|
||||||
|
msgstr "GNOME Shell"
|
||||||
|
|
||||||
|
#: ../data/gnome-shell.desktop.in.in.h:2
|
||||||
|
msgid "Window management and application launching"
|
||||||
|
msgstr "Gestió de finestres i execució d'aplicacions"
|
||||||
|
|
||||||
#. left side
|
#. left side
|
||||||
#: ../js/ui/panel.js:266
|
#: ../js/ui/panel.js:271
|
||||||
msgid "Activities"
|
msgid "Activities"
|
||||||
msgstr "Activitats"
|
msgstr "Activitats"
|
||||||
|
|
||||||
#. Translators: This is a time format.
|
#. Translators: This is a time format.
|
||||||
#: ../js/ui/panel.js:412
|
#: ../js/ui/panel.js:454
|
||||||
msgid "%a %l:%M %p"
|
msgid "%a %l:%M %p"
|
||||||
msgstr "%a %H:%M"
|
msgstr "%a %H:%M"
|
||||||
|
|
||||||
#: ../js/ui/dash.js:235
|
#: ../js/ui/dash.js:256
|
||||||
msgid "Find apps or documents"
|
msgid "Find..."
|
||||||
msgstr "Cerca aplicacions o documents"
|
msgstr "Cerca..."
|
||||||
|
|
||||||
#: ../js/ui/dash.js:336
|
#: ../js/ui/dash.js:374
|
||||||
msgid "Browse"
|
msgid "Browse"
|
||||||
msgstr "Navega"
|
msgstr "Navega"
|
||||||
|
|
||||||
|
#: ../js/ui/dash.js:451
|
||||||
|
msgid "(see all)"
|
||||||
|
msgstr "(mostra tot)"
|
||||||
|
|
||||||
#. **** Applications ****
|
#. **** Applications ****
|
||||||
#: ../js/ui/dash.js:472
|
#: ../js/ui/dash.js:633
|
||||||
#: ../js/ui/dash.js:545
|
#: ../js/ui/dash.js:681
|
||||||
msgid "APPLICATIONS"
|
msgid "APPLICATIONS"
|
||||||
msgstr "APLICACIONS"
|
msgstr "APLICACIONS"
|
||||||
|
|
||||||
#. **** Documents ****
|
|
||||||
#: ../js/ui/dash.js:477
|
|
||||||
#: ../js/ui/dash.js:570
|
|
||||||
msgid "RECENT DOCUMENTS"
|
|
||||||
msgstr "DOCUMENTS RECENTS"
|
|
||||||
|
|
||||||
#. **** Places ****
|
#. **** Places ****
|
||||||
#: ../js/ui/dash.js:563
|
#. Translators: This is in the sense of locations for documents,
|
||||||
|
#. network locations, etc.
|
||||||
|
#: ../js/ui/dash.js:653
|
||||||
msgid "PLACES"
|
msgid "PLACES"
|
||||||
msgstr "LLOCS"
|
msgstr "LLOCS"
|
||||||
|
|
||||||
#: ../js/ui/runDialog.js:74
|
#. **** Documents ****
|
||||||
|
#: ../js/ui/dash.js:660
|
||||||
|
#: ../js/ui/dash.js:692
|
||||||
|
msgid "RECENT DOCUMENTS"
|
||||||
|
msgstr "DOCUMENTS RECENTS"
|
||||||
|
|
||||||
|
#. **** Search Results ****
|
||||||
|
#: ../js/ui/dash.js:679
|
||||||
|
msgid "SEARCH RESULTS"
|
||||||
|
msgstr "RESULTATS DE LA CERCA"
|
||||||
|
|
||||||
|
#: ../js/ui/runDialog.js:82
|
||||||
msgid "Please enter a command:"
|
msgid "Please enter a command:"
|
||||||
msgstr "Introduïu una ordre:"
|
msgstr "Introduïu una ordre:"
|
||||||
|
|
||||||
#: ../src/gdmuser/gdm-user.c:242
|
#: ../src/shell-global.c:840
|
||||||
msgid "Manager"
|
|
||||||
msgstr "Gestor"
|
|
||||||
|
|
||||||
#: ../src/gdmuser/gdm-user.c:243
|
|
||||||
msgid "The user manager object this user is controlled by."
|
|
||||||
msgstr "L'objecte gestor d'usuaris que controla a aquest usuari."
|
|
||||||
|
|
||||||
#: ../src/shell-global.c:841
|
|
||||||
msgid "Less than a minute ago"
|
msgid "Less than a minute ago"
|
||||||
msgstr "Fa menys d'un minut"
|
msgstr "Fa menys d'un minut"
|
||||||
|
|
||||||
#: ../src/shell-global.c:844
|
#: ../src/shell-global.c:843
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d minute ago"
|
msgid "%d minute ago"
|
||||||
msgid_plural "%d minutes ago"
|
msgid_plural "%d minutes ago"
|
||||||
msgstr[0] "Fa %d minut"
|
msgstr[0] "Fa %d minut"
|
||||||
msgstr[1] "Fa %d minuts"
|
msgstr[1] "Fa %d minuts"
|
||||||
|
|
||||||
#: ../src/shell-global.c:847
|
#: ../src/shell-global.c:846
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d hour ago"
|
msgid "%d hour ago"
|
||||||
msgid_plural "%d hours ago"
|
msgid_plural "%d hours ago"
|
||||||
msgstr[0] "Fa %d hora"
|
msgstr[0] "Fa %d hora"
|
||||||
msgstr[1] "Fa %d hores"
|
msgstr[1] "Fa %d hores"
|
||||||
|
|
||||||
#: ../src/shell-global.c:850
|
#: ../src/shell-global.c:849
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d day ago"
|
msgid "%d day ago"
|
||||||
msgid_plural "%d days ago"
|
msgid_plural "%d days ago"
|
||||||
msgstr[0] "Fa %d dia"
|
msgstr[0] "Fa %d dia"
|
||||||
msgstr[1] "Fa %d dies"
|
msgstr[1] "Fa %d dies"
|
||||||
|
|
||||||
#: ../src/shell-global.c:853
|
#: ../src/shell-global.c:852
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d week ago"
|
msgid "%d week ago"
|
||||||
msgid_plural "%d weeks ago"
|
msgid_plural "%d weeks ago"
|
||||||
@@ -107,7 +118,7 @@ msgstr "No es pot blocar la pantalla: %s"
|
|||||||
#: ../src/shell-status-menu.c:227
|
#: ../src/shell-status-menu.c:227
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Can't temporarily set screensaver to blank screen: %s"
|
msgid "Can't temporarily set screensaver to blank screen: %s"
|
||||||
msgstr "No es pot establir temporalment l'estalviador de pantalles a pantalla negra: %s"
|
msgstr "No es pot establir temporalment l'estalvi de pantalla a pantalla negra: %s"
|
||||||
|
|
||||||
#: ../src/shell-status-menu.c:351
|
#: ../src/shell-status-menu.c:351
|
||||||
#, c-format
|
#, c-format
|
||||||
@@ -145,3 +156,34 @@ msgstr "Surt..."
|
|||||||
msgid "Shut Down..."
|
msgid "Shut Down..."
|
||||||
msgstr "Atura..."
|
msgstr "Atura..."
|
||||||
|
|
||||||
|
#: ../src/shell-uri-util.c:87
|
||||||
|
msgid "Home Folder"
|
||||||
|
msgstr "Carpeta d'inici"
|
||||||
|
|
||||||
|
#. Translators: this is the same string as the one found in
|
||||||
|
#. * nautilus
|
||||||
|
#: ../src/shell-uri-util.c:102
|
||||||
|
msgid "File System"
|
||||||
|
msgstr "Sistema de fitxers"
|
||||||
|
|
||||||
|
#: ../src/shell-uri-util.c:248
|
||||||
|
msgid "Search"
|
||||||
|
msgstr "Cerca"
|
||||||
|
|
||||||
|
#. Translators: the first string is the name of a gvfs
|
||||||
|
#. * method, and the second string is a path. For
|
||||||
|
#. * example, "Trash: some-directory". It means that the
|
||||||
|
#. * directory called "some-directory" is in the trash.
|
||||||
|
#.
|
||||||
|
#: ../src/shell-uri-util.c:298
|
||||||
|
#, c-format
|
||||||
|
msgid "%1$s: %2$s"
|
||||||
|
msgstr "%1$s: %2$s"
|
||||||
|
|
||||||
|
#~ msgid "Find apps or documents"
|
||||||
|
#~ msgstr "Cerca aplicacions o documents"
|
||||||
|
#~ msgid "Manager"
|
||||||
|
#~ msgstr "Gestor"
|
||||||
|
#~ msgid "The user manager object this user is controlled by."
|
||||||
|
#~ msgstr "L'objecte gestor d'usuaris que controla a aquest usuari."
|
||||||
|
|
||||||
|
|||||||
123
po/cs.po
@@ -1,15 +1,15 @@
|
|||||||
# Czech translation of gnome-shell.
|
# Czech translation of gnome-shell.
|
||||||
# Copyright (C) 2009 gnome-shell's COPYRIGHT HOLDER
|
# Copyright (C) 2009 the author(s) of gnome-shell.
|
||||||
# This file is distributed under the same license as the gnome-shell package.
|
# This file is distributed under the same license as the gnome-shell package.
|
||||||
# Andre Klapper <ak-47@gmx.net>, 2009.
|
# Andre Klapper <ak-47@gmx.net>, 2009.
|
||||||
#
|
# Petr Kovar <pknbe@volny.cz>, 2009.
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: gnome-shell master\n"
|
"Project-Id-Version: gnome-shell\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2009-08-15 15:25+0200\n"
|
"POT-Creation-Date: 2009-09-22 13:36+0200\n"
|
||||||
"PO-Revision-Date: 2009-08-15 13:23+0000\n"
|
"PO-Revision-Date: 2009-09-22 13:37+0200\n"
|
||||||
"Last-Translator: Andre Klapper <ak-47@gmx.net>\n"
|
"Last-Translator: Andre Klapper <ak-47@gmx.net>, 2009\n"
|
||||||
"Language-Team: Czech <gnome-cs-list@gnome.org>\n"
|
"Language-Team: Czech <gnome-cs-list@gnome.org>\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
@@ -18,95 +18,99 @@ msgstr ""
|
|||||||
|
|
||||||
#: ../data/gnome-shell.desktop.in.in.h:1
|
#: ../data/gnome-shell.desktop.in.in.h:1
|
||||||
msgid "GNOME Shell"
|
msgid "GNOME Shell"
|
||||||
msgstr ""
|
msgstr "Prostředí GNOME Shell"
|
||||||
|
|
||||||
#: ../data/gnome-shell.desktop.in.in.h:2
|
#: ../data/gnome-shell.desktop.in.in.h:2
|
||||||
#, fuzzy
|
|
||||||
msgid "Window management and application launching"
|
msgid "Window management and application launching"
|
||||||
msgstr "Správa oken"
|
msgstr "Správa oken a spouštění aplikací"
|
||||||
|
|
||||||
#. left side
|
#. left side
|
||||||
#: ../js/ui/panel.js:266
|
#: ../js/ui/panel.js:269
|
||||||
msgid "Activities"
|
msgid "Activities"
|
||||||
msgstr ""
|
msgstr "Činnosti"
|
||||||
|
|
||||||
#. Translators: This is a time format.
|
#. Translators: This is a time format.
|
||||||
#: ../js/ui/panel.js:412
|
#: ../js/ui/panel.js:452
|
||||||
msgid "%a %l:%M %p"
|
msgid "%a %l:%M %p"
|
||||||
msgstr ""
|
msgstr "%a, %H:%M"
|
||||||
|
|
||||||
#: ../js/ui/dash.js:235
|
#: ../js/ui/dash.js:283
|
||||||
msgid "Find apps or documents"
|
msgid "Find..."
|
||||||
msgstr ""
|
msgstr "Najít..."
|
||||||
|
|
||||||
#: ../js/ui/dash.js:336
|
#: ../js/ui/dash.js:400
|
||||||
#, fuzzy
|
|
||||||
msgid "Browse"
|
msgid "Browse"
|
||||||
msgstr "Procházet"
|
msgstr "Procházet"
|
||||||
|
|
||||||
|
#: ../js/ui/dash.js:536
|
||||||
|
msgid "(see all)"
|
||||||
|
msgstr "(zobrazit vše)"
|
||||||
|
|
||||||
#. **** Applications ****
|
#. **** Applications ****
|
||||||
#: ../js/ui/dash.js:472 ../js/ui/dash.js:545
|
#: ../js/ui/dash.js:753 ../js/ui/dash.js:809
|
||||||
msgid "APPLICATIONS"
|
msgid "APPLICATIONS"
|
||||||
msgstr "APLIKACE"
|
msgstr "APLIKACE"
|
||||||
|
|
||||||
#. **** Documents ****
|
|
||||||
#: ../js/ui/dash.js:477 ../js/ui/dash.js:570
|
|
||||||
msgid "RECENT DOCUMENTS"
|
|
||||||
msgstr "NEDÁVNÉ DOKUMENTY"
|
|
||||||
|
|
||||||
#. **** Places ****
|
#. **** Places ****
|
||||||
#: ../js/ui/dash.js:563
|
#. Translators: This is in the sense of locations for documents,
|
||||||
|
#. network locations, etc.
|
||||||
|
#: ../js/ui/dash.js:773
|
||||||
msgid "PLACES"
|
msgid "PLACES"
|
||||||
msgstr "MÍSTA"
|
msgstr "MÍSTA"
|
||||||
|
|
||||||
#: ../js/ui/runDialog.js:74
|
#. **** Documents ****
|
||||||
|
#: ../js/ui/dash.js:780 ../js/ui/dash.js:819
|
||||||
|
msgid "RECENT DOCUMENTS"
|
||||||
|
msgstr "NEDÁVNÉ DOKUMENTY"
|
||||||
|
|
||||||
|
#. **** Search Results ****
|
||||||
|
#: ../js/ui/dash.js:799 ../js/ui/dash.js:931
|
||||||
|
msgid "SEARCH RESULTS"
|
||||||
|
msgstr "VÝSLEDKY HLEDÁNÍ"
|
||||||
|
|
||||||
|
#: ../js/ui/dash.js:814
|
||||||
|
msgid "PREFERENCES"
|
||||||
|
msgstr "NASTAVENÍ"
|
||||||
|
|
||||||
|
#: ../js/ui/runDialog.js:101
|
||||||
msgid "Please enter a command:"
|
msgid "Please enter a command:"
|
||||||
msgstr ""
|
msgstr "Zadejte prosím příkaz:"
|
||||||
|
|
||||||
#: ../src/gdmuser/gdm-user.c:242
|
#: ../src/shell-global.c:799
|
||||||
msgid "Manager"
|
|
||||||
msgstr "Správce"
|
|
||||||
|
|
||||||
#: ../src/gdmuser/gdm-user.c:243
|
|
||||||
msgid "The user manager object this user is controlled by."
|
|
||||||
msgstr "Objekt správce uživatele, kterým je tento uživatel ovládán."
|
|
||||||
|
|
||||||
#: ../src/shell-global.c:841
|
|
||||||
#, fuzzy
|
|
||||||
msgid "Less than a minute ago"
|
msgid "Less than a minute ago"
|
||||||
msgstr "Dříve než před minutou"
|
msgstr "Před méně než minutou"
|
||||||
|
|
||||||
#: ../src/shell-global.c:844
|
#: ../src/shell-global.c:802
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d minute ago"
|
msgid "%d minute ago"
|
||||||
msgid_plural "%d minutes ago"
|
msgid_plural "%d minutes ago"
|
||||||
msgstr[0] "%d minuta nazpět"
|
msgstr[0] "Před %d minutou"
|
||||||
msgstr[1] "%d minuty nazpět"
|
msgstr[1] "Před %d minutami"
|
||||||
msgstr[2] "%d minut nazpět"
|
msgstr[2] "Před %d minutami"
|
||||||
|
|
||||||
#: ../src/shell-global.c:847
|
#: ../src/shell-global.c:805
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d hour ago"
|
msgid "%d hour ago"
|
||||||
msgid_plural "%d hours ago"
|
msgid_plural "%d hours ago"
|
||||||
msgstr[0] "%d hodina nazpět"
|
msgstr[0] "Před %d hodinou"
|
||||||
msgstr[1] "%d hodiny nazpět"
|
msgstr[1] "Před %d hodinami"
|
||||||
msgstr[2] "%d hodin nazpět"
|
msgstr[2] "Před %d hodinami"
|
||||||
|
|
||||||
#: ../src/shell-global.c:850
|
#: ../src/shell-global.c:808
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d day ago"
|
msgid "%d day ago"
|
||||||
msgid_plural "%d days ago"
|
msgid_plural "%d days ago"
|
||||||
msgstr[0] "%d den nazpět"
|
msgstr[0] "Před %d dnem"
|
||||||
msgstr[1] "%d dny nazpět"
|
msgstr[1] "Před %d dny"
|
||||||
msgstr[2] "%d dnů nazpět"
|
msgstr[2] "Před %d dny"
|
||||||
|
|
||||||
#: ../src/shell-global.c:853
|
#: ../src/shell-global.c:811
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d week ago"
|
msgid "%d week ago"
|
||||||
msgid_plural "%d weeks ago"
|
msgid_plural "%d weeks ago"
|
||||||
msgstr[0] "%d týden nazpět"
|
msgstr[0] "Před %d týdnem"
|
||||||
msgstr[1] "%d týdny nazpět"
|
msgstr[1] "Před %d týdny"
|
||||||
msgstr[2] "%d týdnů nazpět"
|
msgstr[2] "Před %d týdny"
|
||||||
|
|
||||||
#: ../src/shell-status-menu.c:156
|
#: ../src/shell-status-menu.c:156
|
||||||
msgid "Unknown"
|
msgid "Unknown"
|
||||||
@@ -132,9 +136,8 @@ msgid "Account Information..."
|
|||||||
msgstr "Informace o účtu..."
|
msgstr "Informace o účtu..."
|
||||||
|
|
||||||
#: ../src/shell-status-menu.c:502
|
#: ../src/shell-status-menu.c:502
|
||||||
#, fuzzy
|
|
||||||
msgid "Sidebar"
|
msgid "Sidebar"
|
||||||
msgstr "Boční panel"
|
msgstr "Postranní lišta"
|
||||||
|
|
||||||
#: ../src/shell-status-menu.c:510
|
#: ../src/shell-status-menu.c:510
|
||||||
msgid "System Preferences..."
|
msgid "System Preferences..."
|
||||||
@@ -179,6 +182,12 @@ msgstr "Hledat"
|
|||||||
#. * directory called "some-directory" is in the trash.
|
#. * directory called "some-directory" is in the trash.
|
||||||
#.
|
#.
|
||||||
#: ../src/shell-uri-util.c:298
|
#: ../src/shell-uri-util.c:298
|
||||||
#, fuzzy, c-format
|
#, c-format
|
||||||
msgid "%1$s: %2$s"
|
msgid "%1$s: %2$s"
|
||||||
msgstr "%1$s: %2$s"
|
msgstr "%1$s: %2$s"
|
||||||
|
|
||||||
|
#~ msgid "Manager"
|
||||||
|
#~ msgstr "Správce"
|
||||||
|
|
||||||
|
#~ msgid "The user manager object this user is controlled by."
|
||||||
|
#~ msgstr "Objekt správce uživatele, kterým je tento uživatel ovládán."
|
||||||
|
|||||||
188
po/da.po
Normal file
@@ -0,0 +1,188 @@
|
|||||||
|
# Danish translation of gnome-shell
|
||||||
|
# Copyright (C) 2009 gnome-shell
|
||||||
|
# This file is distributed under the same license as the gnome-shell package.
|
||||||
|
# Kris Thomsen <lakristho@gmail.com>, 2009.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: gnome-shell\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2009-09-04 01:26+0200\n"
|
||||||
|
"PO-Revision-Date: 2009-09-01 21:48+0200\n"
|
||||||
|
"Last-Translator: Kris Thomsen <lakristho@gmail.com>\n"
|
||||||
|
"Language-Team: Danish <dansk@dansk-gruppen.dk>\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||||
|
|
||||||
|
#: ../data/gnome-shell.desktop.in.in.h:1
|
||||||
|
msgid "GNOME Shell"
|
||||||
|
msgstr "Skal til GNOME"
|
||||||
|
|
||||||
|
#: ../data/gnome-shell.desktop.in.in.h:2
|
||||||
|
msgid "Window management and application launching"
|
||||||
|
msgstr "Vinduehåndtering og åbning af programmer"
|
||||||
|
|
||||||
|
#. left side
|
||||||
|
#: ../js/ui/panel.js:271
|
||||||
|
msgid "Activities"
|
||||||
|
msgstr "Aktiviteter"
|
||||||
|
|
||||||
|
#. Translators: This is a time format.
|
||||||
|
#: ../js/ui/panel.js:454
|
||||||
|
msgid "%a %l:%M %p"
|
||||||
|
msgstr "%a %H:%M"
|
||||||
|
|
||||||
|
#: ../js/ui/dash.js:256
|
||||||
|
msgid "Find..."
|
||||||
|
msgstr "Find..."
|
||||||
|
|
||||||
|
#: ../js/ui/dash.js:374
|
||||||
|
msgid "Browse"
|
||||||
|
msgstr "Gennemse"
|
||||||
|
|
||||||
|
#: ../js/ui/dash.js:511
|
||||||
|
msgid "(see all)"
|
||||||
|
msgstr "(se alle)"
|
||||||
|
|
||||||
|
#. **** Applications ****
|
||||||
|
#: ../js/ui/dash.js:705 ../js/ui/dash.js:761 ../js/ui/dash.js:893
|
||||||
|
msgid "APPLICATIONS"
|
||||||
|
msgstr "PROGRAMMER"
|
||||||
|
|
||||||
|
#. **** Places ****
|
||||||
|
#. Translators: This is in the sense of locations for documents,
|
||||||
|
#. network locations, etc.
|
||||||
|
#: ../js/ui/dash.js:725
|
||||||
|
msgid "PLACES"
|
||||||
|
msgstr "STEDER"
|
||||||
|
|
||||||
|
#. **** Documents ****
|
||||||
|
#: ../js/ui/dash.js:732 ../js/ui/dash.js:773 ../js/ui/dash.js:867
|
||||||
|
msgid "RECENT DOCUMENTS"
|
||||||
|
msgstr "SENESTE DOKUMENTER"
|
||||||
|
|
||||||
|
#. **** Search Results ****
|
||||||
|
#: ../js/ui/dash.js:751 ../js/ui/dash.js:856 ../js/ui/dash.js:882
|
||||||
|
msgid "SEARCH RESULTS"
|
||||||
|
msgstr "SØGERESULTATER"
|
||||||
|
|
||||||
|
#: ../js/ui/runDialog.js:82
|
||||||
|
msgid "Please enter a command:"
|
||||||
|
msgstr "Indtast en kommando:"
|
||||||
|
|
||||||
|
#: ../src/shell-global.c:840
|
||||||
|
msgid "Less than a minute ago"
|
||||||
|
msgstr "Mindre end et minut siden"
|
||||||
|
|
||||||
|
#: ../src/shell-global.c:843
|
||||||
|
#, c-format
|
||||||
|
msgid "%d minute ago"
|
||||||
|
msgid_plural "%d minutes ago"
|
||||||
|
msgstr[0] "%d minut siden"
|
||||||
|
msgstr[1] "%d minutter siden"
|
||||||
|
|
||||||
|
#: ../src/shell-global.c:846
|
||||||
|
#, c-format
|
||||||
|
msgid "%d hour ago"
|
||||||
|
msgid_plural "%d hours ago"
|
||||||
|
msgstr[0] "%d time siden"
|
||||||
|
msgstr[1] "%d timer siden"
|
||||||
|
|
||||||
|
#: ../src/shell-global.c:849
|
||||||
|
#, c-format
|
||||||
|
msgid "%d day ago"
|
||||||
|
msgid_plural "%d days ago"
|
||||||
|
msgstr[0] "%d dag siden"
|
||||||
|
msgstr[1] "%d dage siden"
|
||||||
|
|
||||||
|
#: ../src/shell-global.c:852
|
||||||
|
#, c-format
|
||||||
|
msgid "%d week ago"
|
||||||
|
msgid_plural "%d weeks ago"
|
||||||
|
msgstr[0] "%d uge siden"
|
||||||
|
msgstr[1] "%d uger siden"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:156
|
||||||
|
msgid "Unknown"
|
||||||
|
msgstr "Ukendt"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:212
|
||||||
|
#, c-format
|
||||||
|
msgid "Can't lock screen: %s"
|
||||||
|
msgstr "Kan ikke låse skærm: %s"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:227
|
||||||
|
#, c-format
|
||||||
|
msgid "Can't temporarily set screensaver to blank screen: %s"
|
||||||
|
msgstr "Kan ikke midlertidigt sætte pauseskærm til blank skærm: %s"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:351
|
||||||
|
#, c-format
|
||||||
|
msgid "Can't logout: %s"
|
||||||
|
msgstr "Kan ikke logge ud: %s"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:492
|
||||||
|
msgid "Account Information..."
|
||||||
|
msgstr "Kontoinformation..."
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:502
|
||||||
|
msgid "Sidebar"
|
||||||
|
msgstr "Sidebjælke"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:510
|
||||||
|
msgid "System Preferences..."
|
||||||
|
msgstr "Systemindstillinger..."
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:525
|
||||||
|
msgid "Lock Screen"
|
||||||
|
msgstr "Lås skærm"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:535
|
||||||
|
msgid "Switch User"
|
||||||
|
msgstr "Skift bruger"
|
||||||
|
|
||||||
|
#. Only show switch user if there are other users
|
||||||
|
#. Log Out
|
||||||
|
#: ../src/shell-status-menu.c:546
|
||||||
|
msgid "Log Out..."
|
||||||
|
msgstr "Log ud..."
|
||||||
|
|
||||||
|
#. Shut down
|
||||||
|
#: ../src/shell-status-menu.c:557
|
||||||
|
msgid "Shut Down..."
|
||||||
|
msgstr "Luk ned..."
|
||||||
|
|
||||||
|
#: ../src/shell-uri-util.c:87
|
||||||
|
msgid "Home Folder"
|
||||||
|
msgstr "Hjemmemappe"
|
||||||
|
|
||||||
|
#. Translators: this is the same string as the one found in
|
||||||
|
#. * nautilus
|
||||||
|
#: ../src/shell-uri-util.c:102
|
||||||
|
msgid "File System"
|
||||||
|
msgstr "Filsystem"
|
||||||
|
|
||||||
|
#: ../src/shell-uri-util.c:248
|
||||||
|
msgid "Search"
|
||||||
|
msgstr "Søg"
|
||||||
|
|
||||||
|
#. Translators: the first string is the name of a gvfs
|
||||||
|
#. * method, and the second string is a path. For
|
||||||
|
#. * example, "Trash: some-directory". It means that the
|
||||||
|
#. * directory called "some-directory" is in the trash.
|
||||||
|
#.
|
||||||
|
#: ../src/shell-uri-util.c:298
|
||||||
|
#, c-format
|
||||||
|
msgid "%1$s: %2$s"
|
||||||
|
msgstr "%1$s: %2$s"
|
||||||
|
|
||||||
|
#~ msgid "Find apps or documents"
|
||||||
|
#~ msgstr "Find programmer eller dokumenter"
|
||||||
|
|
||||||
|
#~ msgid "Manager"
|
||||||
|
#~ msgstr "Håndtering"
|
||||||
|
|
||||||
|
#~ msgid "The user manager object this user is controlled by."
|
||||||
|
#~ msgstr "Brugerhåndteringsobjektet, denne bruger er styret af."
|
||||||
184
po/en_GB.po
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
# British English translation for gnome-shell.
|
||||||
|
# Copyright (C) 2009 gnome-shell's COPYRIGHT HOLDER
|
||||||
|
# This file is distributed under the same license as the gnome-shell package.
|
||||||
|
# Philip Withnall <philip@tecnocode.co.uk>, 2009.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: gnome-shell master\n"
|
||||||
|
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
|
||||||
|
"shell&component=general\n"
|
||||||
|
"POT-Creation-Date: 2009-09-12 12:41+0000\n"
|
||||||
|
"PO-Revision-Date: 2009-09-12 12:41+0000\n"
|
||||||
|
"Last-Translator: Philip Withnall <philip@tecnocode.co.uk>\n"
|
||||||
|
"Language-Team: British English <en_GB@li.org>\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
|
#: ../data/gnome-shell.desktop.in.in.h:1
|
||||||
|
msgid "GNOME Shell"
|
||||||
|
msgstr "GNOME Shell"
|
||||||
|
|
||||||
|
#: ../data/gnome-shell.desktop.in.in.h:2
|
||||||
|
msgid "Window management and application launching"
|
||||||
|
msgstr "Window management and application launching"
|
||||||
|
|
||||||
|
#. left side
|
||||||
|
#: ../js/ui/panel.js:269
|
||||||
|
msgid "Activities"
|
||||||
|
msgstr "Activities"
|
||||||
|
|
||||||
|
#. Translators: This is a time format.
|
||||||
|
#: ../js/ui/panel.js:452
|
||||||
|
msgid "%a %l:%M %p"
|
||||||
|
msgstr "%a %l:%M %p"
|
||||||
|
|
||||||
|
#: ../js/ui/dash.js:283
|
||||||
|
msgid "Find..."
|
||||||
|
msgstr "Find…"
|
||||||
|
|
||||||
|
#: ../js/ui/dash.js:400
|
||||||
|
msgid "Browse"
|
||||||
|
msgstr "Browse"
|
||||||
|
|
||||||
|
#: ../js/ui/dash.js:536
|
||||||
|
msgid "(see all)"
|
||||||
|
msgstr "(see all)"
|
||||||
|
|
||||||
|
#. **** Applications ****
|
||||||
|
#: ../js/ui/dash.js:753 ../js/ui/dash.js:809
|
||||||
|
msgid "APPLICATIONS"
|
||||||
|
msgstr "APPLICATIONS"
|
||||||
|
|
||||||
|
#. **** Places ****
|
||||||
|
#. Translators: This is in the sense of locations for documents,
|
||||||
|
#. network locations, etc.
|
||||||
|
#: ../js/ui/dash.js:773
|
||||||
|
msgid "PLACES"
|
||||||
|
msgstr "PLACES"
|
||||||
|
|
||||||
|
#. **** Documents ****
|
||||||
|
#: ../js/ui/dash.js:780 ../js/ui/dash.js:819
|
||||||
|
msgid "RECENT DOCUMENTS"
|
||||||
|
msgstr "RECENT DOCUMENTS"
|
||||||
|
|
||||||
|
#. **** Search Results ****
|
||||||
|
#: ../js/ui/dash.js:799 ../js/ui/dash.js:931
|
||||||
|
msgid "SEARCH RESULTS"
|
||||||
|
msgstr "SEARCH RESULTS"
|
||||||
|
|
||||||
|
#: ../js/ui/dash.js:814
|
||||||
|
msgid "PREFERENCES"
|
||||||
|
msgstr "PREFERENCES"
|
||||||
|
|
||||||
|
#: ../js/ui/runDialog.js:90
|
||||||
|
msgid "Please enter a command:"
|
||||||
|
msgstr "Please enter a command:"
|
||||||
|
|
||||||
|
#: ../src/shell-global.c:799
|
||||||
|
msgid "Less than a minute ago"
|
||||||
|
msgstr "Less than a minute ago"
|
||||||
|
|
||||||
|
#: ../src/shell-global.c:802
|
||||||
|
#, c-format
|
||||||
|
msgid "%d minute ago"
|
||||||
|
msgid_plural "%d minutes ago"
|
||||||
|
msgstr[0] "%d minute ago"
|
||||||
|
msgstr[1] "%d minutes ago"
|
||||||
|
|
||||||
|
#: ../src/shell-global.c:805
|
||||||
|
#, c-format
|
||||||
|
msgid "%d hour ago"
|
||||||
|
msgid_plural "%d hours ago"
|
||||||
|
msgstr[0] "%d hour ago"
|
||||||
|
msgstr[1] "%d hours ago"
|
||||||
|
|
||||||
|
#: ../src/shell-global.c:808
|
||||||
|
#, c-format
|
||||||
|
msgid "%d day ago"
|
||||||
|
msgid_plural "%d days ago"
|
||||||
|
msgstr[0] "%d day ago"
|
||||||
|
msgstr[1] "%d days ago"
|
||||||
|
|
||||||
|
#: ../src/shell-global.c:811
|
||||||
|
#, c-format
|
||||||
|
msgid "%d week ago"
|
||||||
|
msgid_plural "%d weeks ago"
|
||||||
|
msgstr[0] "%d week ago"
|
||||||
|
msgstr[1] "%d weeks ago"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:156
|
||||||
|
msgid "Unknown"
|
||||||
|
msgstr "Unknown"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:212
|
||||||
|
#, c-format
|
||||||
|
msgid "Can't lock screen: %s"
|
||||||
|
msgstr "Can't lock screen: %s"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:227
|
||||||
|
#, c-format
|
||||||
|
msgid "Can't temporarily set screensaver to blank screen: %s"
|
||||||
|
msgstr "Can't temporarily set screensaver to blank screen: %s"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:351
|
||||||
|
#, c-format
|
||||||
|
msgid "Can't logout: %s"
|
||||||
|
msgstr "Can't logout: %s"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:492
|
||||||
|
msgid "Account Information..."
|
||||||
|
msgstr "Account Information…"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:502
|
||||||
|
msgid "Sidebar"
|
||||||
|
msgstr "Sidebar"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:510
|
||||||
|
msgid "System Preferences..."
|
||||||
|
msgstr "System Preferences…"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:525
|
||||||
|
msgid "Lock Screen"
|
||||||
|
msgstr "Lock Screen"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:535
|
||||||
|
msgid "Switch User"
|
||||||
|
msgstr "Switch User"
|
||||||
|
|
||||||
|
#. Only show switch user if there are other users
|
||||||
|
#. Log Out
|
||||||
|
#: ../src/shell-status-menu.c:546
|
||||||
|
msgid "Log Out..."
|
||||||
|
msgstr "Log Out…"
|
||||||
|
|
||||||
|
#. Shut down
|
||||||
|
#: ../src/shell-status-menu.c:557
|
||||||
|
msgid "Shut Down..."
|
||||||
|
msgstr "Shut Down…"
|
||||||
|
|
||||||
|
#: ../src/shell-uri-util.c:87
|
||||||
|
msgid "Home Folder"
|
||||||
|
msgstr "Home Folder"
|
||||||
|
|
||||||
|
#. Translators: this is the same string as the one found in
|
||||||
|
#. * nautilus
|
||||||
|
#: ../src/shell-uri-util.c:102
|
||||||
|
msgid "File System"
|
||||||
|
msgstr "File System"
|
||||||
|
|
||||||
|
#: ../src/shell-uri-util.c:248
|
||||||
|
msgid "Search"
|
||||||
|
msgstr "Search"
|
||||||
|
|
||||||
|
#. Translators: the first string is the name of a gvfs
|
||||||
|
#. * method, and the second string is a path. For
|
||||||
|
#. * example, "Trash: some-directory". It means that the
|
||||||
|
#. * directory called "some-directory" is in the trash.
|
||||||
|
#.
|
||||||
|
#: ../src/shell-uri-util.c:298
|
||||||
|
#, c-format
|
||||||
|
msgid "%1$s: %2$s"
|
||||||
|
msgstr "%1$s: %2$s"
|
||||||
63
po/es.po
@@ -8,13 +8,13 @@ msgstr ""
|
|||||||
"Project-Id-Version: gnome-shell master\n"
|
"Project-Id-Version: gnome-shell master\n"
|
||||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
|
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
|
||||||
"shell&component=general\n"
|
"shell&component=general\n"
|
||||||
"POT-Creation-Date: 2009-08-21 22:23+0000\n"
|
"POT-Creation-Date: 2009-09-27 16:05+0000\n"
|
||||||
"PO-Revision-Date: 2009-08-22 12:21+0200\n"
|
"PO-Revision-Date: 2009-09-28 21:58+0200\n"
|
||||||
"Last-Translator: Jorge González <jorgegonz@svn.gnome.org>\n"
|
"Last-Translator: Jorge González <jorgegonz@svn.gnome.org>\n"
|
||||||
"Language-Team: Español <gnome-es-list@gnome.org>\n"
|
"Language-Team: Español <gnome-es-list@gnome.org>\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: UTF-8\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
#: ../data/gnome-shell.desktop.in.in.h:1
|
#: ../data/gnome-shell.desktop.in.in.h:1
|
||||||
@@ -26,80 +26,83 @@ msgid "Window management and application launching"
|
|||||||
msgstr "Gestión de ventanas e inicio de aplicaciones"
|
msgstr "Gestión de ventanas e inicio de aplicaciones"
|
||||||
|
|
||||||
#. left side
|
#. left side
|
||||||
#: ../js/ui/panel.js:266
|
#: ../js/ui/panel.js:269
|
||||||
msgid "Activities"
|
msgid "Activities"
|
||||||
msgstr "Actividades"
|
msgstr "Actividades"
|
||||||
|
|
||||||
#. Translators: This is a time format.
|
#. Translators: This is a time format.
|
||||||
#: ../js/ui/panel.js:433
|
#: ../js/ui/panel.js:452
|
||||||
msgid "%a %l:%M %p"
|
msgid "%a %l:%M %p"
|
||||||
msgstr "%a %H:%M"
|
msgstr "%a %H:%M"
|
||||||
|
|
||||||
#: ../js/ui/dash.js:250
|
#: ../js/ui/dash.js:283
|
||||||
msgid "Find apps or documents"
|
msgid "Find..."
|
||||||
msgstr "Encuentre aplicaciones o documentos"
|
msgstr "Buscar…"
|
||||||
|
|
||||||
#: ../js/ui/dash.js:368
|
#: ../js/ui/dash.js:400
|
||||||
msgid "Browse"
|
msgid "More"
|
||||||
msgstr "Examine"
|
msgstr "Más"
|
||||||
|
|
||||||
|
#: ../js/ui/dash.js:543
|
||||||
|
msgid "(see all)"
|
||||||
|
msgstr "(ver todo)"
|
||||||
|
|
||||||
#. **** Applications ****
|
#. **** Applications ****
|
||||||
#: ../js/ui/dash.js:556 ../js/ui/dash.js:606
|
#: ../js/ui/dash.js:763 ../js/ui/dash.js:825
|
||||||
msgid "APPLICATIONS"
|
msgid "APPLICATIONS"
|
||||||
msgstr "APLICACIONES"
|
msgstr "APLICACIONES"
|
||||||
|
|
||||||
#. **** Places ****
|
#. **** Places ****
|
||||||
#. Translators: This is in the sense of locations for documents,
|
#. Translators: This is in the sense of locations for documents,
|
||||||
#. network locations, etc.
|
#. network locations, etc.
|
||||||
#: ../js/ui/dash.js:576
|
#: ../js/ui/dash.js:783
|
||||||
msgid "PLACES"
|
msgid "PLACES"
|
||||||
msgstr "LUGARES"
|
msgstr "LUGARES"
|
||||||
|
|
||||||
#. **** Documents ****
|
#. **** Documents ****
|
||||||
#: ../js/ui/dash.js:583
|
#: ../js/ui/dash.js:790 ../js/ui/dash.js:835
|
||||||
msgid "RECENT DOCUMENTS"
|
msgid "RECENT DOCUMENTS"
|
||||||
msgstr "DOCUMENTOS RECIENTES"
|
msgstr "DOCUMENTOS RECIENTES"
|
||||||
|
|
||||||
#. **** Search Results ****
|
#. **** Search Results ****
|
||||||
#: ../js/ui/dash.js:602
|
#: ../js/ui/dash.js:815 ../js/ui/dash.js:958
|
||||||
msgid "SEARCH RESULTS"
|
msgid "SEARCH RESULTS"
|
||||||
msgstr "RESULTADOS DE LA BÚSQUEDA"
|
msgstr "RESULTADOS DE LA BÚSQUEDA"
|
||||||
|
|
||||||
#: ../js/ui/dash.js:615
|
#: ../js/ui/dash.js:830
|
||||||
#| msgid "RECENT DOCUMENTS"
|
msgid "PREFERENCES"
|
||||||
msgid "DOCUMENTS"
|
msgstr "PREFERENCIAS"
|
||||||
msgstr "DOCUMENTOS"
|
|
||||||
|
|
||||||
#: ../js/ui/runDialog.js:75
|
#: ../js/ui/runDialog.js:94
|
||||||
msgid "Please enter a command:"
|
msgid "Please enter a command:"
|
||||||
msgstr "Introduzca un comando:"
|
msgstr "Introduzca un comando:"
|
||||||
|
|
||||||
#: ../src/shell-global.c:841
|
#: ../src/shell-global.c:799
|
||||||
msgid "Less than a minute ago"
|
msgid "Less than a minute ago"
|
||||||
msgstr "Hace menos de un minuto"
|
msgstr "Hace menos de un minuto"
|
||||||
|
|
||||||
#: ../src/shell-global.c:844
|
#: ../src/shell-global.c:802
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d minute ago"
|
msgid "%d minute ago"
|
||||||
msgid_plural "%d minutes ago"
|
msgid_plural "%d minutes ago"
|
||||||
msgstr[0] "Hace %d minuto"
|
msgstr[0] "Hace %d minuto"
|
||||||
msgstr[1] "Hace %d minutos"
|
msgstr[1] "Hace %d minutos"
|
||||||
|
|
||||||
#: ../src/shell-global.c:847
|
#: ../src/shell-global.c:805
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d hour ago"
|
msgid "%d hour ago"
|
||||||
msgid_plural "%d hours ago"
|
msgid_plural "%d hours ago"
|
||||||
msgstr[0] "Hace %d hora"
|
msgstr[0] "Hace %d hora"
|
||||||
msgstr[1] "Hace %d horas"
|
msgstr[1] "Hace %d horas"
|
||||||
|
|
||||||
#: ../src/shell-global.c:850
|
#: ../src/shell-global.c:808
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d day ago"
|
msgid "%d day ago"
|
||||||
msgid_plural "%d days ago"
|
msgid_plural "%d days ago"
|
||||||
msgstr[0] "Hace %d día"
|
msgstr[0] "Hace %d día"
|
||||||
msgstr[1] "Hace %d días"
|
msgstr[1] "Hace %d días"
|
||||||
|
|
||||||
#: ../src/shell-global.c:853
|
#: ../src/shell-global.c:811
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d week ago"
|
msgid "%d week ago"
|
||||||
msgid_plural "%d weeks ago"
|
msgid_plural "%d weeks ago"
|
||||||
@@ -182,6 +185,16 @@ msgstr "Buscar"
|
|||||||
msgid "%1$s: %2$s"
|
msgid "%1$s: %2$s"
|
||||||
msgstr "%1$s: %2$s"
|
msgstr "%1$s: %2$s"
|
||||||
|
|
||||||
|
#~ msgid "Browse"
|
||||||
|
#~ msgstr "Examine"
|
||||||
|
|
||||||
|
#~ msgid "Find apps or documents"
|
||||||
|
#~ msgstr "Encuentre aplicaciones o documentos"
|
||||||
|
|
||||||
|
#~| msgid "RECENT DOCUMENTS"
|
||||||
|
#~ msgid "DOCUMENTS"
|
||||||
|
#~ msgstr "DOCUMENTOS"
|
||||||
|
|
||||||
#~ msgid "Manager"
|
#~ msgid "Manager"
|
||||||
#~ msgstr "Gestor"
|
#~ msgstr "Gestor"
|
||||||
|
|
||||||
|
|||||||
177
po/fr.po
@@ -1,21 +1,182 @@
|
|||||||
# French translations for gnome-shell package.
|
# French translations for gnome-shell package.
|
||||||
# Copyright (C) 2009 THE gnome-shell'S COPYRIGHT HOLDER
|
# Copyright (C) 2009 THE gnome-shell'S COPYRIGHT HOLDER
|
||||||
# This file is distributed under the same license as the gnome-shell package.
|
# This file is distributed under the same license as the gnome-shell package.
|
||||||
# Colin Walters <walters@verbum.org>, 2009.
|
#
|
||||||
|
# Mathieu Bridon <bochecha@fedoraproject.org>, 2009.
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: gnome-shell 0.0.1\n"
|
"Project-Id-Version: HEAD\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
|
||||||
"POT-Creation-Date: 2009-07-27 15:09-0400\n"
|
"shell&component=general\n"
|
||||||
"PO-Revision-Date: 2009-07-27 15:23-0400\n"
|
"POT-Creation-Date: 2009-09-09 21:30+0000\n"
|
||||||
"Last-Translator: Colin Walters <walters@verbum.org>\n"
|
"PO-Revision-Date: 2009-09-11 21:40+0200\n"
|
||||||
"Language-Team: French\n"
|
"Last-Translator: Mathieu Bridon <bochecha@fedoraproject.org>\n"
|
||||||
|
"Language-Team: GNOME French Team\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||||
|
|
||||||
#: ../js/ui/panel.js:74
|
#: ../data/gnome-shell.desktop.in.in.h:1
|
||||||
|
msgid "GNOME Shell"
|
||||||
|
msgstr "GNOME Shell"
|
||||||
|
|
||||||
|
#: ../data/gnome-shell.desktop.in.in.h:2
|
||||||
|
msgid "Window management and application launching"
|
||||||
|
msgstr "Gestion des fenêtres et lancement des applications"
|
||||||
|
|
||||||
|
#. left side
|
||||||
|
#: ../js/ui/panel.js:269
|
||||||
msgid "Activities"
|
msgid "Activities"
|
||||||
msgstr "Activités"
|
msgstr "Activités"
|
||||||
|
|
||||||
|
#. Translators: This is a time format.
|
||||||
|
#: ../js/ui/panel.js:452
|
||||||
|
msgid "%a %l:%M %p"
|
||||||
|
msgstr "%a %H:%M"
|
||||||
|
|
||||||
|
#: ../js/ui/dash.js:255
|
||||||
|
msgid "Find..."
|
||||||
|
msgstr "Rechercher..."
|
||||||
|
|
||||||
|
#: ../js/ui/dash.js:372
|
||||||
|
msgid "Browse"
|
||||||
|
msgstr "Parcourir"
|
||||||
|
|
||||||
|
#: ../js/ui/dash.js:508
|
||||||
|
msgid "(see all)"
|
||||||
|
msgstr "(tout afficher)"
|
||||||
|
|
||||||
|
#. **** Applications ****
|
||||||
|
#: ../js/ui/dash.js:700 ../js/ui/dash.js:756 ../js/ui/dash.js:887
|
||||||
|
msgid "APPLICATIONS"
|
||||||
|
msgstr "APPLICATIONS"
|
||||||
|
|
||||||
|
#. **** Places ****
|
||||||
|
#. Translators: This is in the sense of locations for documents,
|
||||||
|
#. network locations, etc.
|
||||||
|
#: ../js/ui/dash.js:720
|
||||||
|
msgid "PLACES"
|
||||||
|
msgstr "RACCOURCIS"
|
||||||
|
|
||||||
|
#. **** Documents ****
|
||||||
|
#: ../js/ui/dash.js:727 ../js/ui/dash.js:768 ../js/ui/dash.js:861
|
||||||
|
msgid "RECENT DOCUMENTS"
|
||||||
|
msgstr "DOCUMENTS RÉCENTS"
|
||||||
|
|
||||||
|
#. **** Search Results ****
|
||||||
|
#: ../js/ui/dash.js:746 ../js/ui/dash.js:850 ../js/ui/dash.js:876
|
||||||
|
msgid "SEARCH RESULTS"
|
||||||
|
msgstr "RÉSULTATS DE LA RECHERCHE"
|
||||||
|
|
||||||
|
#: ../js/ui/runDialog.js:90
|
||||||
|
msgid "Please enter a command:"
|
||||||
|
msgstr "Veuillez saisir une commande :"
|
||||||
|
|
||||||
|
#: ../src/shell-global.c:799
|
||||||
|
msgid "Less than a minute ago"
|
||||||
|
msgstr "Il y a moins d'une minute"
|
||||||
|
|
||||||
|
#: ../src/shell-global.c:802
|
||||||
|
#, c-format
|
||||||
|
msgid "%d minute ago"
|
||||||
|
msgid_plural "%d minutes ago"
|
||||||
|
msgstr[0] "Il y a %d minute"
|
||||||
|
msgstr[1] "Il y a %d minutes"
|
||||||
|
|
||||||
|
#: ../src/shell-global.c:805
|
||||||
|
#, c-format
|
||||||
|
msgid "%d hour ago"
|
||||||
|
msgid_plural "%d hours ago"
|
||||||
|
msgstr[0] "Il y a %d heure"
|
||||||
|
msgstr[1] "Il y a %d heures"
|
||||||
|
|
||||||
|
#: ../src/shell-global.c:808
|
||||||
|
#, c-format
|
||||||
|
msgid "%d day ago"
|
||||||
|
msgid_plural "%d days ago"
|
||||||
|
msgstr[0] "Il y a %d jour"
|
||||||
|
msgstr[1] "Il y a %d jours"
|
||||||
|
|
||||||
|
#: ../src/shell-global.c:811
|
||||||
|
#, c-format
|
||||||
|
msgid "%d week ago"
|
||||||
|
msgid_plural "%d weeks ago"
|
||||||
|
msgstr[0] "Il y a %d semaine"
|
||||||
|
msgstr[1] "Il y a %d semaines"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:156
|
||||||
|
msgid "Unknown"
|
||||||
|
msgstr "Inconnu"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:212
|
||||||
|
#, c-format
|
||||||
|
msgid "Can't lock screen: %s"
|
||||||
|
msgstr "Impossible de verrouiller l'écran : %s"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:227
|
||||||
|
#, c-format
|
||||||
|
msgid "Can't temporarily set screensaver to blank screen: %s"
|
||||||
|
msgstr ""
|
||||||
|
"Impossible de régler temporairement l'écran de veille sur un écran vide : %s"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:351
|
||||||
|
#, c-format
|
||||||
|
msgid "Can't logout: %s"
|
||||||
|
msgstr "Impossible de fermer la session : %s"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:492
|
||||||
|
msgid "Account Information..."
|
||||||
|
msgstr "Informations personnelles..."
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:502
|
||||||
|
msgid "Sidebar"
|
||||||
|
msgstr "Barre latérale"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:510
|
||||||
|
msgid "System Preferences..."
|
||||||
|
msgstr "Préférences du système..."
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:525
|
||||||
|
msgid "Lock Screen"
|
||||||
|
msgstr "Verrouiller l'écran"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:535
|
||||||
|
msgid "Switch User"
|
||||||
|
msgstr "Changer d'utilisateur"
|
||||||
|
|
||||||
|
#. Only show switch user if there are other users
|
||||||
|
#. Log Out
|
||||||
|
#: ../src/shell-status-menu.c:546
|
||||||
|
msgid "Log Out..."
|
||||||
|
msgstr "Fermer la session..."
|
||||||
|
|
||||||
|
#. Shut down
|
||||||
|
#: ../src/shell-status-menu.c:557
|
||||||
|
msgid "Shut Down..."
|
||||||
|
msgstr "Éteindre..."
|
||||||
|
|
||||||
|
#: ../src/shell-uri-util.c:87
|
||||||
|
msgid "Home Folder"
|
||||||
|
msgstr "Dossier personnel"
|
||||||
|
|
||||||
|
#. Translators: this is the same string as the one found in
|
||||||
|
#. * nautilus
|
||||||
|
#: ../src/shell-uri-util.c:102
|
||||||
|
msgid "File System"
|
||||||
|
msgstr "Système de fichiers"
|
||||||
|
|
||||||
|
#: ../src/shell-uri-util.c:248
|
||||||
|
msgid "Search"
|
||||||
|
msgstr "Recherche"
|
||||||
|
|
||||||
|
#. Translators: the first string is the name of a gvfs
|
||||||
|
#. * method, and the second string is a path. For
|
||||||
|
#. * example, "Trash: some-directory". It means that the
|
||||||
|
#. * directory called "some-directory" is in the trash.
|
||||||
|
#.
|
||||||
|
#: ../src/shell-uri-util.c:298
|
||||||
|
#, c-format
|
||||||
|
msgid "%1$s: %2$s"
|
||||||
|
msgstr "%1$s : %2$s"
|
||||||
|
|||||||
56
po/gl.po
@@ -7,8 +7,8 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: gnome-shell master\n"
|
"Project-Id-Version: gnome-shell master\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2009-08-22 16:39+0200\n"
|
"POT-Creation-Date: 2009-09-15 23:06+0200\n"
|
||||||
"PO-Revision-Date: 2009-08-18 21:20+0100\n"
|
"PO-Revision-Date: 2009-09-10 22:32+0100\n"
|
||||||
"Last-Translator: Fran Diéguez <fran.dieguez@glug.es>\n"
|
"Last-Translator: Fran Diéguez <fran.dieguez@glug.es>\n"
|
||||||
"Language-Team: Galician <gnome@mancomun.org>\n"
|
"Language-Team: Galician <gnome@mancomun.org>\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
@@ -25,80 +25,83 @@ msgid "Window management and application launching"
|
|||||||
msgstr "Xestor de xanelas e lanzado de aplicativos"
|
msgstr "Xestor de xanelas e lanzado de aplicativos"
|
||||||
|
|
||||||
#. left side
|
#. left side
|
||||||
#: ../js/ui/panel.js:266
|
#: ../js/ui/panel.js:269
|
||||||
msgid "Activities"
|
msgid "Activities"
|
||||||
msgstr "Actividades"
|
msgstr "Actividades"
|
||||||
|
|
||||||
#. Translators: This is a time format.
|
#. Translators: This is a time format.
|
||||||
#: ../js/ui/panel.js:433
|
#: ../js/ui/panel.js:452
|
||||||
msgid "%a %l:%M %p"
|
msgid "%a %l:%M %p"
|
||||||
msgstr "%a %l:%M %p"
|
msgstr "%a %l:%M %p"
|
||||||
|
|
||||||
#: ../js/ui/dash.js:250
|
#: ../js/ui/dash.js:283
|
||||||
msgid "Find apps or documents"
|
msgid "Find..."
|
||||||
msgstr "Atopar aplicativos ou documentos"
|
msgstr "Buscar..."
|
||||||
|
|
||||||
#: ../js/ui/dash.js:368
|
#: ../js/ui/dash.js:400
|
||||||
msgid "Browse"
|
msgid "Browse"
|
||||||
msgstr "Explorar"
|
msgstr "Explorar"
|
||||||
|
|
||||||
|
#: ../js/ui/dash.js:536
|
||||||
|
msgid "(see all)"
|
||||||
|
msgstr "(ver todos)"
|
||||||
|
|
||||||
#. **** Applications ****
|
#. **** Applications ****
|
||||||
#: ../js/ui/dash.js:556 ../js/ui/dash.js:606
|
#: ../js/ui/dash.js:753 ../js/ui/dash.js:809
|
||||||
msgid "APPLICATIONS"
|
msgid "APPLICATIONS"
|
||||||
msgstr "APLICATIVOS"
|
msgstr "APLICATIVOS"
|
||||||
|
|
||||||
#. **** Places ****
|
#. **** Places ****
|
||||||
#. Translators: This is in the sense of locations for documents,
|
#. Translators: This is in the sense of locations for documents,
|
||||||
#. network locations, etc.
|
#. network locations, etc.
|
||||||
#: ../js/ui/dash.js:576
|
#: ../js/ui/dash.js:773
|
||||||
msgid "PLACES"
|
msgid "PLACES"
|
||||||
msgstr "LUGARES"
|
msgstr "LUGARES"
|
||||||
|
|
||||||
#. **** Documents ****
|
#. **** Documents ****
|
||||||
#: ../js/ui/dash.js:583
|
#: ../js/ui/dash.js:780 ../js/ui/dash.js:819
|
||||||
msgid "RECENT DOCUMENTS"
|
msgid "RECENT DOCUMENTS"
|
||||||
msgstr "DOCUMENTOS RECENTES"
|
msgstr "DOCUMENTOS RECENTES"
|
||||||
|
|
||||||
#. **** Search Results ****
|
#. **** Search Results ****
|
||||||
#: ../js/ui/dash.js:602
|
#: ../js/ui/dash.js:799 ../js/ui/dash.js:931
|
||||||
msgid "SEARCH RESULTS"
|
msgid "SEARCH RESULTS"
|
||||||
|
msgstr "RESULTADOS DA BÚSQUEDA"
|
||||||
|
|
||||||
|
#: ../js/ui/dash.js:814
|
||||||
|
msgid "PREFERENCES"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../js/ui/dash.js:615
|
#: ../js/ui/runDialog.js:96
|
||||||
#, fuzzy
|
|
||||||
msgid "DOCUMENTS"
|
|
||||||
msgstr "DOCUMENTOS RECENTES"
|
|
||||||
|
|
||||||
#: ../js/ui/runDialog.js:75
|
|
||||||
msgid "Please enter a command:"
|
msgid "Please enter a command:"
|
||||||
msgstr "Insira unha orde:"
|
msgstr "Insira unha orde:"
|
||||||
|
|
||||||
#: ../src/shell-global.c:841
|
#: ../src/shell-global.c:799
|
||||||
msgid "Less than a minute ago"
|
msgid "Less than a minute ago"
|
||||||
msgstr "Menos de un minuto"
|
msgstr "Menos de un minuto"
|
||||||
|
|
||||||
#: ../src/shell-global.c:844
|
#: ../src/shell-global.c:802
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d minute ago"
|
msgid "%d minute ago"
|
||||||
msgid_plural "%d minutes ago"
|
msgid_plural "%d minutes ago"
|
||||||
msgstr[0] "fai %d minuto"
|
msgstr[0] "fai %d minuto"
|
||||||
msgstr[1] "fai %d minutos"
|
msgstr[1] "fai %d minutos"
|
||||||
|
|
||||||
#: ../src/shell-global.c:847
|
#: ../src/shell-global.c:805
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d hour ago"
|
msgid "%d hour ago"
|
||||||
msgid_plural "%d hours ago"
|
msgid_plural "%d hours ago"
|
||||||
msgstr[0] "fai %d hora"
|
msgstr[0] "fai %d hora"
|
||||||
msgstr[1] "fai %d horas"
|
msgstr[1] "fai %d horas"
|
||||||
|
|
||||||
#: ../src/shell-global.c:850
|
#: ../src/shell-global.c:808
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d day ago"
|
msgid "%d day ago"
|
||||||
msgid_plural "%d days ago"
|
msgid_plural "%d days ago"
|
||||||
msgstr[0] "fai %d día"
|
msgstr[0] "fai %d día"
|
||||||
msgstr[1] "fai %d días"
|
msgstr[1] "fai %d días"
|
||||||
|
|
||||||
#: ../src/shell-global.c:853
|
#: ../src/shell-global.c:811
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d week ago"
|
msgid "%d week ago"
|
||||||
msgid_plural "%d weeks ago"
|
msgid_plural "%d weeks ago"
|
||||||
@@ -180,5 +183,12 @@ msgstr "Buscar"
|
|||||||
msgid "%1$s: %2$s"
|
msgid "%1$s: %2$s"
|
||||||
msgstr "%1$s: %2$s"
|
msgstr "%1$s: %2$s"
|
||||||
|
|
||||||
|
#~ msgid "Find apps or documents"
|
||||||
|
#~ msgstr "Atopar aplicativos ou documentos"
|
||||||
|
|
||||||
|
#, fuzzy
|
||||||
|
#~ msgid "DOCUMENTS"
|
||||||
|
#~ msgstr "DOCUMENTOS RECENTES"
|
||||||
|
|
||||||
#~ msgid "Manager"
|
#~ msgid "Manager"
|
||||||
#~ msgstr "Xestor"
|
#~ msgstr "Xestor"
|
||||||
|
|||||||
85
po/hu.po
@@ -7,8 +7,8 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: gnome-shell master\n"
|
"Project-Id-Version: gnome-shell master\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2009-08-15 11:35+0200\n"
|
"POT-Creation-Date: 2009-09-28 13:41+0200\n"
|
||||||
"PO-Revision-Date: 2009-08-15 11:35+0200\n"
|
"PO-Revision-Date: 2009-09-28 13:42+0200\n"
|
||||||
"Last-Translator: Gabor Kelemen <kelemeng at gnome dot hu>\n"
|
"Last-Translator: Gabor Kelemen <kelemeng at gnome dot hu>\n"
|
||||||
"Language-Team: Hungarian <gnome at fsf dot hu>\n"
|
"Language-Team: Hungarian <gnome at fsf dot hu>\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
@@ -17,77 +17,92 @@ msgstr ""
|
|||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
"X-Generator: KBabel 1.11.4\n"
|
"X-Generator: KBabel 1.11.4\n"
|
||||||
|
|
||||||
|
#: ../data/gnome-shell.desktop.in.in.h:1
|
||||||
|
msgid "GNOME Shell"
|
||||||
|
msgstr "GNOME Shell"
|
||||||
|
|
||||||
|
#: ../data/gnome-shell.desktop.in.in.h:2
|
||||||
|
msgid "Window management and application launching"
|
||||||
|
msgstr "Ablakkezelés és alkalmazásindítás"
|
||||||
|
|
||||||
#. left side
|
#. left side
|
||||||
#: ../js/ui/panel.js:266
|
#: ../js/ui/panel.js:269
|
||||||
msgid "Activities"
|
msgid "Activities"
|
||||||
msgstr "Tevékenységek"
|
msgstr "Tevékenységek"
|
||||||
|
|
||||||
#. Translators: This is a time format.
|
#. Translators: This is a time format.
|
||||||
#: ../js/ui/panel.js:412
|
#: ../js/ui/panel.js:452
|
||||||
msgid "%a %l:%M %p"
|
msgid "%a %l:%M %p"
|
||||||
msgstr "%a., %k.%M"
|
msgstr "%a., %k.%M"
|
||||||
|
|
||||||
#: ../js/ui/dash.js:235
|
#: ../js/ui/dash.js:283
|
||||||
msgid "Find apps or documents"
|
msgid "Find..."
|
||||||
msgstr "Alkalmazások vagy dokumentumok keresése"
|
msgstr "Keresés…"
|
||||||
|
|
||||||
#: ../js/ui/dash.js:336
|
#: ../js/ui/dash.js:400
|
||||||
msgid "Browse"
|
msgid "More"
|
||||||
msgstr "Tallózás"
|
msgstr "Több"
|
||||||
|
|
||||||
|
#: ../js/ui/dash.js:543
|
||||||
|
msgid "(see all)"
|
||||||
|
msgstr "(összes megjelenítése)"
|
||||||
|
|
||||||
#. **** Applications ****
|
#. **** Applications ****
|
||||||
#: ../js/ui/dash.js:472 ../js/ui/dash.js:545
|
#: ../js/ui/dash.js:763 ../js/ui/dash.js:825
|
||||||
msgid "APPLICATIONS"
|
msgid "APPLICATIONS"
|
||||||
msgstr "ALKALMAZÁSOK"
|
msgstr "ALKALMAZÁSOK"
|
||||||
|
|
||||||
#. **** Documents ****
|
|
||||||
#: ../js/ui/dash.js:477 ../js/ui/dash.js:570
|
|
||||||
msgid "RECENT DOCUMENTS"
|
|
||||||
msgstr "LEGUTÓBBI DOKUMENTUMOK"
|
|
||||||
|
|
||||||
#. **** Places ****
|
#. **** Places ****
|
||||||
#: ../js/ui/dash.js:563
|
#. Translators: This is in the sense of locations for documents,
|
||||||
|
#. network locations, etc.
|
||||||
|
#: ../js/ui/dash.js:783
|
||||||
msgid "PLACES"
|
msgid "PLACES"
|
||||||
msgstr "HELYEK"
|
msgstr "HELYEK"
|
||||||
|
|
||||||
#: ../js/ui/runDialog.js:74
|
#. **** Documents ****
|
||||||
|
#: ../js/ui/dash.js:790 ../js/ui/dash.js:835
|
||||||
|
msgid "RECENT DOCUMENTS"
|
||||||
|
msgstr "LEGUTÓBBI DOKUMENTUMOK"
|
||||||
|
|
||||||
|
#. **** Search Results ****
|
||||||
|
#: ../js/ui/dash.js:815 ../js/ui/dash.js:958
|
||||||
|
msgid "SEARCH RESULTS"
|
||||||
|
msgstr "TALÁLATOK"
|
||||||
|
|
||||||
|
#: ../js/ui/dash.js:830
|
||||||
|
msgid "PREFERENCES"
|
||||||
|
msgstr "BEÁLLÍTÁSOK"
|
||||||
|
|
||||||
|
#: ../js/ui/runDialog.js:94
|
||||||
msgid "Please enter a command:"
|
msgid "Please enter a command:"
|
||||||
msgstr "Adjon meg egy parancsot:"
|
msgstr "Adjon meg egy parancsot:"
|
||||||
|
|
||||||
#: ../src/gdmuser/gdm-user.c:242
|
#: ../src/shell-global.c:799
|
||||||
msgid "Manager"
|
|
||||||
msgstr "Kezelő"
|
|
||||||
|
|
||||||
#: ../src/gdmuser/gdm-user.c:243
|
|
||||||
msgid "The user manager object this user is controlled by."
|
|
||||||
msgstr "A felhasználót kezelő felhasználókezelő objektum."
|
|
||||||
|
|
||||||
#: ../src/shell-global.c:841
|
|
||||||
msgid "Less than a minute ago"
|
msgid "Less than a minute ago"
|
||||||
msgstr "Kevesebb, mint egy perce"
|
msgstr "Kevesebb, mint egy perce"
|
||||||
|
|
||||||
#: ../src/shell-global.c:844
|
#: ../src/shell-global.c:802
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d minute ago"
|
msgid "%d minute ago"
|
||||||
msgid_plural "%d minutes ago"
|
msgid_plural "%d minutes ago"
|
||||||
msgstr[0] "%d perce"
|
msgstr[0] "%d perce"
|
||||||
msgstr[1] "%d perce"
|
msgstr[1] "%d perce"
|
||||||
|
|
||||||
#: ../src/shell-global.c:847
|
#: ../src/shell-global.c:805
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d hour ago"
|
msgid "%d hour ago"
|
||||||
msgid_plural "%d hours ago"
|
msgid_plural "%d hours ago"
|
||||||
msgstr[0] "%d órája"
|
msgstr[0] "%d órája"
|
||||||
msgstr[1] "%d órája"
|
msgstr[1] "%d órája"
|
||||||
|
|
||||||
#: ../src/shell-global.c:850
|
#: ../src/shell-global.c:808
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d day ago"
|
msgid "%d day ago"
|
||||||
msgid_plural "%d days ago"
|
msgid_plural "%d days ago"
|
||||||
msgstr[0] "%d napja"
|
msgstr[0] "%d napja"
|
||||||
msgstr[1] "%d napja"
|
msgstr[1] "%d napja"
|
||||||
|
|
||||||
#: ../src/shell-global.c:853
|
#: ../src/shell-global.c:811
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d week ago"
|
msgid "%d week ago"
|
||||||
msgid_plural "%d weeks ago"
|
msgid_plural "%d weeks ago"
|
||||||
@@ -146,14 +161,6 @@ msgstr "Kijelentkezés…"
|
|||||||
msgid "Shut Down..."
|
msgid "Shut Down..."
|
||||||
msgstr "Leállítás…"
|
msgstr "Leállítás…"
|
||||||
|
|
||||||
#: ../data/gnome-shell.desktop.in.in.h:1
|
|
||||||
msgid "GNOME Shell"
|
|
||||||
msgstr "GNOME Shell"
|
|
||||||
|
|
||||||
#: ../data/gnome-shell.desktop.in.in.h:2
|
|
||||||
msgid "Window management and application launching"
|
|
||||||
msgstr "Ablakkezelés és alkalmazásindítás"
|
|
||||||
|
|
||||||
#: ../src/shell-uri-util.c:87
|
#: ../src/shell-uri-util.c:87
|
||||||
msgid "Home Folder"
|
msgid "Home Folder"
|
||||||
msgstr "Saját mappa"
|
msgstr "Saját mappa"
|
||||||
|
|||||||
59
po/it.po
@@ -6,9 +6,10 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: gnome-shell\n"
|
"Project-Id-Version: gnome-shell\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
|
||||||
"POT-Creation-Date: 2009-08-20 23:25+0200\n"
|
"shell&component=general\n"
|
||||||
"PO-Revision-Date: 2009-08-20 23:26+0200\n"
|
"POT-Creation-Date: 2009-09-05 00:19+0000\n"
|
||||||
|
"PO-Revision-Date: 2009-09-06 18:31+0200\n"
|
||||||
"Last-Translator: Milo Casagrande <milo@ubuntu.com>\n"
|
"Last-Translator: Milo Casagrande <milo@ubuntu.com>\n"
|
||||||
"Language-Team: Italian <tp@lists.linux.it>\n"
|
"Language-Team: Italian <tp@lists.linux.it>\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
@@ -25,72 +26,80 @@ msgid "Window management and application launching"
|
|||||||
msgstr "Gestione finestre e avvio applicazioni"
|
msgstr "Gestione finestre e avvio applicazioni"
|
||||||
|
|
||||||
#. left side
|
#. left side
|
||||||
#: ../js/ui/panel.js:266
|
#: ../js/ui/panel.js:271
|
||||||
msgid "Activities"
|
msgid "Activities"
|
||||||
msgstr "Attività"
|
msgstr "Attività"
|
||||||
|
|
||||||
# (ndt) proviamo col k, se non funge, sappiamo il perché...
|
# (ndt) proviamo col k, se non funge, sappiamo il perché...
|
||||||
#. Translators: This is a time format.
|
#. Translators: This is a time format.
|
||||||
#: ../js/ui/panel.js:433
|
#: ../js/ui/panel.js:454
|
||||||
msgid "%a %l:%M %p"
|
msgid "%a %l:%M %p"
|
||||||
msgstr "%a %k.%M"
|
msgstr "%a %k.%M"
|
||||||
|
|
||||||
# (ndt) è da valutare se è troppo lunga, è in una casella di ricerca
|
#: ../js/ui/dash.js:256
|
||||||
#: ../js/ui/dash.js:251
|
msgid "Find..."
|
||||||
msgid "Find apps or documents"
|
msgstr "Trova..."
|
||||||
msgstr "Trova programmi e documenti"
|
|
||||||
|
|
||||||
#: ../js/ui/dash.js:369
|
#: ../js/ui/dash.js:374
|
||||||
msgid "Browse"
|
msgid "Browse"
|
||||||
msgstr "Esplora"
|
msgstr "Esplora"
|
||||||
|
|
||||||
|
#: ../js/ui/dash.js:511
|
||||||
|
msgid "(see all)"
|
||||||
|
msgstr "(vedi tutto)"
|
||||||
|
|
||||||
#. **** Applications ****
|
#. **** Applications ****
|
||||||
#: ../js/ui/dash.js:505 ../js/ui/dash.js:578
|
#: ../js/ui/dash.js:705 ../js/ui/dash.js:761 ../js/ui/dash.js:893
|
||||||
msgid "APPLICATIONS"
|
msgid "APPLICATIONS"
|
||||||
msgstr "Applicazioni"
|
msgstr "Applicazioni"
|
||||||
|
|
||||||
#. **** Documents ****
|
|
||||||
#: ../js/ui/dash.js:510 ../js/ui/dash.js:605
|
|
||||||
msgid "RECENT DOCUMENTS"
|
|
||||||
msgstr "Documenti recenti"
|
|
||||||
|
|
||||||
#. **** Places ****
|
#. **** Places ****
|
||||||
#. Translators: This is in the sense of locations for documents,
|
#. Translators: This is in the sense of locations for documents,
|
||||||
#. network locations, etc.
|
#. network locations, etc.
|
||||||
#: ../js/ui/dash.js:598
|
#: ../js/ui/dash.js:725
|
||||||
msgid "PLACES"
|
msgid "PLACES"
|
||||||
msgstr "Risorse"
|
msgstr "Risorse"
|
||||||
|
|
||||||
#: ../js/ui/runDialog.js:75
|
#. **** Documents ****
|
||||||
|
#: ../js/ui/dash.js:732 ../js/ui/dash.js:773 ../js/ui/dash.js:867
|
||||||
|
msgid "RECENT DOCUMENTS"
|
||||||
|
msgstr "Documenti recenti"
|
||||||
|
|
||||||
|
#. **** Search Results ****
|
||||||
|
#: ../js/ui/dash.js:751 ../js/ui/dash.js:856 ../js/ui/dash.js:882
|
||||||
|
msgid "SEARCH RESULTS"
|
||||||
|
msgstr "Risultati ricerca"
|
||||||
|
|
||||||
|
#: ../js/ui/runDialog.js:82
|
||||||
msgid "Please enter a command:"
|
msgid "Please enter a command:"
|
||||||
msgstr "Inserire un comando:"
|
msgstr "Inserire un comando:"
|
||||||
|
|
||||||
#: ../src/shell-global.c:841
|
#: ../src/shell-global.c:840
|
||||||
msgid "Less than a minute ago"
|
msgid "Less than a minute ago"
|
||||||
msgstr "Meno di un minuto fa"
|
msgstr "Meno di un minuto fa"
|
||||||
|
|
||||||
#: ../src/shell-global.c:844
|
#: ../src/shell-global.c:843
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d minute ago"
|
msgid "%d minute ago"
|
||||||
msgid_plural "%d minutes ago"
|
msgid_plural "%d minutes ago"
|
||||||
msgstr[0] "%d minuto fa"
|
msgstr[0] "%d minuto fa"
|
||||||
msgstr[1] "%d minuti fa"
|
msgstr[1] "%d minuti fa"
|
||||||
|
|
||||||
#: ../src/shell-global.c:847
|
#: ../src/shell-global.c:846
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d hour ago"
|
msgid "%d hour ago"
|
||||||
msgid_plural "%d hours ago"
|
msgid_plural "%d hours ago"
|
||||||
msgstr[0] "%d ora fa"
|
msgstr[0] "%d ora fa"
|
||||||
msgstr[1] "%d ore fa"
|
msgstr[1] "%d ore fa"
|
||||||
|
|
||||||
#: ../src/shell-global.c:850
|
#: ../src/shell-global.c:849
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d day ago"
|
msgid "%d day ago"
|
||||||
msgid_plural "%d days ago"
|
msgid_plural "%d days ago"
|
||||||
msgstr[0] "%d giorno fa"
|
msgstr[0] "%d giorno fa"
|
||||||
msgstr[1] "%d giorni fa"
|
msgstr[1] "%d giorni fa"
|
||||||
|
|
||||||
#: ../src/shell-global.c:853
|
#: ../src/shell-global.c:852
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d week ago"
|
msgid "%d week ago"
|
||||||
msgid_plural "%d weeks ago"
|
msgid_plural "%d weeks ago"
|
||||||
@@ -175,6 +184,10 @@ msgstr "Cerca"
|
|||||||
msgid "%1$s: %2$s"
|
msgid "%1$s: %2$s"
|
||||||
msgstr "%1$s: %2$s"
|
msgstr "%1$s: %2$s"
|
||||||
|
|
||||||
|
# (ndt) è da valutare se è troppo lunga, è in una casella di ricerca
|
||||||
|
#~ msgid "Find apps or documents"
|
||||||
|
#~ msgstr "Trova programmi e documenti"
|
||||||
|
|
||||||
# (ndt) no idea...
|
# (ndt) no idea...
|
||||||
#~ msgid "Manager"
|
#~ msgid "Manager"
|
||||||
#~ msgstr "Manager"
|
#~ msgstr "Manager"
|
||||||
|
|||||||
44
po/nl.po
@@ -7,8 +7,8 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: gnome-shell master\n"
|
"Project-Id-Version: gnome-shell master\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2009-08-24 22:30+0200\n"
|
"POT-Creation-Date: 2009-08-29 14:37+0200\n"
|
||||||
"PO-Revision-Date: 2009-08-24 22:38+0200\n"
|
"PO-Revision-Date: 2009-08-29 15:10+0200\n"
|
||||||
"Last-Translator: Sander Dijkhuis <sander.dijkhuis@gmail.com>\n"
|
"Last-Translator: Sander Dijkhuis <sander.dijkhuis@gmail.com>\n"
|
||||||
"Language-Team: Dutch <vertaling@vrijschrift.org>\n"
|
"Language-Team: Dutch <vertaling@vrijschrift.org>\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
@@ -25,79 +25,79 @@ msgid "Window management and application launching"
|
|||||||
msgstr "Vensterbeheer en toepassingen starten"
|
msgstr "Vensterbeheer en toepassingen starten"
|
||||||
|
|
||||||
#. left side
|
#. left side
|
||||||
#: ../js/ui/panel.js:266
|
#: ../js/ui/panel.js:271
|
||||||
msgid "Activities"
|
msgid "Activities"
|
||||||
msgstr "Activiteiten"
|
msgstr "Activiteiten"
|
||||||
|
|
||||||
#. Translators: This is a time format.
|
#. Translators: This is a time format.
|
||||||
#: ../js/ui/panel.js:433
|
#: ../js/ui/panel.js:451
|
||||||
msgid "%a %l:%M %p"
|
msgid "%a %l:%M %p"
|
||||||
msgstr "%a %k:%M"
|
msgstr "%a %k:%M"
|
||||||
|
|
||||||
#: ../js/ui/dash.js:250
|
#: ../js/ui/dash.js:256
|
||||||
msgid "Find apps or documents"
|
msgid "Find..."
|
||||||
msgstr "Zoeken"
|
msgstr "Zoeken…"
|
||||||
|
|
||||||
#: ../js/ui/dash.js:368
|
#: ../js/ui/dash.js:374
|
||||||
msgid "Browse"
|
msgid "Browse"
|
||||||
msgstr "Bladeren"
|
msgstr "Bladeren"
|
||||||
|
|
||||||
|
#: ../js/ui/dash.js:451
|
||||||
|
msgid "(see all)"
|
||||||
|
msgstr "(alles tonen)"
|
||||||
|
|
||||||
#. **** Applications ****
|
#. **** Applications ****
|
||||||
#: ../js/ui/dash.js:556 ../js/ui/dash.js:606
|
#: ../js/ui/dash.js:634 ../js/ui/dash.js:682
|
||||||
msgid "APPLICATIONS"
|
msgid "APPLICATIONS"
|
||||||
msgstr "TOEPASSINGEN"
|
msgstr "TOEPASSINGEN"
|
||||||
|
|
||||||
#. **** Places ****
|
#. **** Places ****
|
||||||
#. Translators: This is in the sense of locations for documents,
|
#. Translators: This is in the sense of locations for documents,
|
||||||
#. network locations, etc.
|
#. network locations, etc.
|
||||||
#: ../js/ui/dash.js:576
|
#: ../js/ui/dash.js:654
|
||||||
msgid "PLACES"
|
msgid "PLACES"
|
||||||
msgstr "LOCATIES"
|
msgstr "LOCATIES"
|
||||||
|
|
||||||
#. **** Documents ****
|
#. **** Documents ****
|
||||||
#: ../js/ui/dash.js:583
|
#: ../js/ui/dash.js:661 ../js/ui/dash.js:694
|
||||||
msgid "RECENT DOCUMENTS"
|
msgid "RECENT DOCUMENTS"
|
||||||
msgstr "RECENTE DOCUMENTEN"
|
msgstr "RECENTE DOCUMENTEN"
|
||||||
|
|
||||||
#. **** Search Results ****
|
#. **** Search Results ****
|
||||||
#: ../js/ui/dash.js:602
|
#: ../js/ui/dash.js:680
|
||||||
msgid "SEARCH RESULTS"
|
msgid "SEARCH RESULTS"
|
||||||
msgstr "ZOEKRESULTATEN"
|
msgstr "ZOEKRESULTATEN"
|
||||||
|
|
||||||
#: ../js/ui/dash.js:615
|
#: ../js/ui/runDialog.js:82
|
||||||
msgid "DOCUMENTS"
|
|
||||||
msgstr "DOCUMENTEN"
|
|
||||||
|
|
||||||
#: ../js/ui/runDialog.js:75
|
|
||||||
msgid "Please enter a command:"
|
msgid "Please enter a command:"
|
||||||
msgstr "Voer een opdracht in:"
|
msgstr "Voer een opdracht in:"
|
||||||
|
|
||||||
#: ../src/shell-global.c:841
|
#: ../src/shell-global.c:840
|
||||||
msgid "Less than a minute ago"
|
msgid "Less than a minute ago"
|
||||||
msgstr "Korter dan een minuut geleden"
|
msgstr "Korter dan een minuut geleden"
|
||||||
|
|
||||||
#: ../src/shell-global.c:844
|
#: ../src/shell-global.c:843
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d minute ago"
|
msgid "%d minute ago"
|
||||||
msgid_plural "%d minutes ago"
|
msgid_plural "%d minutes ago"
|
||||||
msgstr[0] "%d minuut geleden"
|
msgstr[0] "%d minuut geleden"
|
||||||
msgstr[1] "%d minuten geleden"
|
msgstr[1] "%d minuten geleden"
|
||||||
|
|
||||||
#: ../src/shell-global.c:847
|
#: ../src/shell-global.c:846
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d hour ago"
|
msgid "%d hour ago"
|
||||||
msgid_plural "%d hours ago"
|
msgid_plural "%d hours ago"
|
||||||
msgstr[0] "%d uur geleden"
|
msgstr[0] "%d uur geleden"
|
||||||
msgstr[1] "%d uur geleden"
|
msgstr[1] "%d uur geleden"
|
||||||
|
|
||||||
#: ../src/shell-global.c:850
|
#: ../src/shell-global.c:849
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d day ago"
|
msgid "%d day ago"
|
||||||
msgid_plural "%d days ago"
|
msgid_plural "%d days ago"
|
||||||
msgstr[0] "%d dag geleden"
|
msgstr[0] "%d dag geleden"
|
||||||
msgstr[1] "%d dagen geleden"
|
msgstr[1] "%d dagen geleden"
|
||||||
|
|
||||||
#: ../src/shell-global.c:853
|
#: ../src/shell-global.c:852
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d week ago"
|
msgid "%d week ago"
|
||||||
msgid_plural "%d weeks ago"
|
msgid_plural "%d weeks ago"
|
||||||
|
|||||||
182
po/pa.po
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
# Punjabi translation for gnome-shell.
|
||||||
|
# Copyright (C) 2009 gnome-shell's COPYRIGHT HOLDER
|
||||||
|
# This file is distributed under the same license as the gnome-shell package.
|
||||||
|
#
|
||||||
|
# A S Alam <aalam@users.sf.net>, 2009.
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: gnome-shell master\n"
|
||||||
|
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug."
|
||||||
|
"cgi?product=gnome-shell&component=general\n"
|
||||||
|
"POT-Creation-Date: 2009-08-31 22:31+0000\n"
|
||||||
|
"PO-Revision-Date: 2009-09-01 06:51+0530\n"
|
||||||
|
"Last-Translator: A S Alam <aalam@users.sf.net>\n"
|
||||||
|
"Language-Team: Punjabi/Panjabi <punjabi-users@lists.sf.net>\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
"X-Generator: Lokalize 1.0\n"
|
||||||
|
|
||||||
|
#: ../data/gnome-shell.desktop.in.in.h:1
|
||||||
|
msgid "GNOME Shell"
|
||||||
|
msgstr "ਗਨੋਮ ਸ਼ੈਲ"
|
||||||
|
|
||||||
|
#: ../data/gnome-shell.desktop.in.in.h:2
|
||||||
|
msgid "Window management and application launching"
|
||||||
|
msgstr "ਵਿੰਡੋ ਪਰਬੰਧ ਅਤੇ ਐਪਲੀਕੇਸ਼ਨ ਚਲਾਓ"
|
||||||
|
|
||||||
|
#. left side
|
||||||
|
#: ../js/ui/panel.js:271
|
||||||
|
msgid "Activities"
|
||||||
|
msgstr "ਸਰਗਰਮੀਆਂ"
|
||||||
|
|
||||||
|
#. Translators: This is a time format.
|
||||||
|
#: ../js/ui/panel.js:454
|
||||||
|
msgid "%a %l:%M %p"
|
||||||
|
msgstr "%a %l:%M %p"
|
||||||
|
|
||||||
|
#: ../js/ui/dash.js:256
|
||||||
|
msgid "Find..."
|
||||||
|
msgstr "ਖੋਜ..."
|
||||||
|
|
||||||
|
#: ../js/ui/dash.js:374
|
||||||
|
msgid "Browse"
|
||||||
|
msgstr "ਝਲਕ"
|
||||||
|
|
||||||
|
#: ../js/ui/dash.js:451
|
||||||
|
msgid "(see all)"
|
||||||
|
msgstr "(ਸਭ ਵੇਖੋ)"
|
||||||
|
|
||||||
|
#. **** Applications ****
|
||||||
|
#: ../js/ui/dash.js:633 ../js/ui/dash.js:681
|
||||||
|
msgid "APPLICATIONS"
|
||||||
|
msgstr "ਐਪਲੀਕੇਸ਼ਨ"
|
||||||
|
|
||||||
|
#. **** Places ****
|
||||||
|
#. Translators: This is in the sense of locations for documents,
|
||||||
|
#. network locations, etc.
|
||||||
|
#: ../js/ui/dash.js:653
|
||||||
|
msgid "PLACES"
|
||||||
|
msgstr "ਥਾਵਾਂ"
|
||||||
|
|
||||||
|
#. **** Documents ****
|
||||||
|
#: ../js/ui/dash.js:660 ../js/ui/dash.js:692
|
||||||
|
msgid "RECENT DOCUMENTS"
|
||||||
|
msgstr "ਤਾਜ਼ਾ ਡੌਕੂਮੈਂਟ"
|
||||||
|
|
||||||
|
#. **** Search Results ****
|
||||||
|
#: ../js/ui/dash.js:679
|
||||||
|
msgid "SEARCH RESULTS"
|
||||||
|
msgstr "ਖੋਜ ਨਤੀਜੇ"
|
||||||
|
|
||||||
|
#: ../js/ui/runDialog.js:82
|
||||||
|
msgid "Please enter a command:"
|
||||||
|
msgstr "ਕਮਾਂਡ ਦਿਓ ਜੀ:"
|
||||||
|
|
||||||
|
#: ../src/shell-global.c:840
|
||||||
|
msgid "Less than a minute ago"
|
||||||
|
msgstr "ਇੱਕ ਮਿੰਟ ਤੋਂ ਘੱਟ ਚਿਰ ਪਹਿਲਾਂ"
|
||||||
|
|
||||||
|
#: ../src/shell-global.c:843
|
||||||
|
#, c-format
|
||||||
|
msgid "%d minute ago"
|
||||||
|
msgid_plural "%d minutes ago"
|
||||||
|
msgstr[0] "%d ਮਿੰਟ ਪਹਿਲਾਂ"
|
||||||
|
msgstr[1] "%d ਮਿੰਟ ਪਹਿਲਾਂ"
|
||||||
|
|
||||||
|
#: ../src/shell-global.c:846
|
||||||
|
#, c-format
|
||||||
|
msgid "%d hour ago"
|
||||||
|
msgid_plural "%d hours ago"
|
||||||
|
msgstr[0] "%d ਘੰਟਾ ਪਹਿਲਾਂ"
|
||||||
|
msgstr[1] "%d ਘੰਟੇ ਪਹਿਲਾਂ"
|
||||||
|
|
||||||
|
#: ../src/shell-global.c:849
|
||||||
|
#, c-format
|
||||||
|
msgid "%d day ago"
|
||||||
|
msgid_plural "%d days ago"
|
||||||
|
msgstr[0] "%d ਦਿਨ ਪਹਿਲਾਂ"
|
||||||
|
msgstr[1] "%d ਦਿਨ ਪਹਿਲਾਂ"
|
||||||
|
|
||||||
|
#: ../src/shell-global.c:852
|
||||||
|
#, c-format
|
||||||
|
msgid "%d week ago"
|
||||||
|
msgid_plural "%d weeks ago"
|
||||||
|
msgstr[0] "%d ਹਫ਼ਤਾ ਪਹਿਲਾਂ"
|
||||||
|
msgstr[1] "%d ਹਫ਼ਤੇ ਪਹਿਲਾਂ"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:156
|
||||||
|
msgid "Unknown"
|
||||||
|
msgstr "ਅਣਜਾਣ"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:212
|
||||||
|
#, c-format
|
||||||
|
msgid "Can't lock screen: %s"
|
||||||
|
msgstr "ਸਕਰੀਨ ਲਾਕ ਨਹੀਂ ਹੋ ਸਕਦੀ: %s"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:227
|
||||||
|
#, c-format
|
||||||
|
msgid "Can't temporarily set screensaver to blank screen: %s"
|
||||||
|
msgstr "ਸਕਰੀਨ ਬੰਦ ਕਰਨ ਲਈ ਆਰਜ਼ੀ ਰੂਪ ਵਿੱਚ ਸਕਰੀਨ-ਸੇਵਰ ਨਹੀਂ ਸੈੱਟ ਕੀਤਾ ਜਾ ਸਕਦਾ: %s"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:351
|
||||||
|
#, c-format
|
||||||
|
msgid "Can't logout: %s"
|
||||||
|
msgstr "ਲਾਗਆਉਟ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ: %s"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:492
|
||||||
|
msgid "Account Information..."
|
||||||
|
msgstr "ਅਕਾਊਂਟ ਜਾਣਕਾਰੀ..."
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:502
|
||||||
|
msgid "Sidebar"
|
||||||
|
msgstr "ਬਾਹੀ"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:510
|
||||||
|
msgid "System Preferences..."
|
||||||
|
msgstr "ਸਿਸਟਮ ਪਸੰਦ..."
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:525
|
||||||
|
msgid "Lock Screen"
|
||||||
|
msgstr "ਸਕਰੀਨ ਲਾਕ ਕਰੋ"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:535
|
||||||
|
msgid "Switch User"
|
||||||
|
msgstr "ਯੂਜ਼ਰ ਬਦਲੋ"
|
||||||
|
|
||||||
|
#. Only show switch user if there are other users
|
||||||
|
#. Log Out
|
||||||
|
#: ../src/shell-status-menu.c:546
|
||||||
|
msgid "Log Out..."
|
||||||
|
msgstr "ਲਾਗਆਉਟ..."
|
||||||
|
|
||||||
|
#. Shut down
|
||||||
|
#: ../src/shell-status-menu.c:557
|
||||||
|
msgid "Shut Down..."
|
||||||
|
msgstr "ਬੰਦ ਕਰੋ..."
|
||||||
|
|
||||||
|
#: ../src/shell-uri-util.c:87
|
||||||
|
msgid "Home Folder"
|
||||||
|
msgstr "ਘਰ ਫੋਲਡਰ"
|
||||||
|
|
||||||
|
#. Translators: this is the same string as the one found in
|
||||||
|
#. * nautilus
|
||||||
|
#: ../src/shell-uri-util.c:102
|
||||||
|
msgid "File System"
|
||||||
|
msgstr "ਫਾਇਲ ਸਿਸਟਮ"
|
||||||
|
|
||||||
|
#: ../src/shell-uri-util.c:248
|
||||||
|
msgid "Search"
|
||||||
|
msgstr "ਖੋਜ"
|
||||||
|
|
||||||
|
#. Translators: the first string is the name of a gvfs
|
||||||
|
#. * method, and the second string is a path. For
|
||||||
|
#. * example, "Trash: some-directory". It means that the
|
||||||
|
#. * directory called "some-directory" is in the trash.
|
||||||
|
#.
|
||||||
|
#: ../src/shell-uri-util.c:298
|
||||||
|
#, c-format
|
||||||
|
msgid "%1$s: %2$s"
|
||||||
|
msgstr "%1$s: %2$s"
|
||||||
|
|
||||||
59
po/pl.po
@@ -8,8 +8,8 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: gnome-shell\n"
|
"Project-Id-Version: gnome-shell\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2009-08-18 23:25+0200\n"
|
"POT-Creation-Date: 2009-09-09 03:06+0200\n"
|
||||||
"PO-Revision-Date: 2009-08-18 23:23+0100\n"
|
"PO-Revision-Date: 2009-09-09 03:02+0100\n"
|
||||||
"Last-Translator: Tomasz Dominikowski <dominikowski@gmail.com>\n"
|
"Last-Translator: Tomasz Dominikowski <dominikowski@gmail.com>\n"
|
||||||
"Language-Team: Polish <gnomepl@aviary.pl>\n"
|
"Language-Team: Polish <gnomepl@aviary.pl>\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
@@ -29,57 +29,58 @@ msgid "Window management and application launching"
|
|||||||
msgstr "Zarządzanie oknami i uruchamianiem programów"
|
msgstr "Zarządzanie oknami i uruchamianiem programów"
|
||||||
|
|
||||||
#. left side
|
#. left side
|
||||||
#: ../js/ui/panel.js:266
|
#: ../js/ui/panel.js:269
|
||||||
msgid "Activities"
|
msgid "Activities"
|
||||||
msgstr "Czynności"
|
msgstr "Czynności"
|
||||||
|
|
||||||
#. Translators: This is a time format.
|
#. Translators: This is a time format.
|
||||||
#: ../js/ui/panel.js:433
|
#: ../js/ui/panel.js:452
|
||||||
msgid "%a %l:%M %p"
|
msgid "%a %l:%M %p"
|
||||||
msgstr "%a, %H:%M"
|
msgstr "%a, %H:%M"
|
||||||
|
|
||||||
#: ../js/ui/dash.js:251
|
#: ../js/ui/dash.js:255
|
||||||
msgid "Find apps or documents"
|
msgid "Find..."
|
||||||
msgstr "Wyszukuje programy lub dokumenty"
|
msgstr "Znajdź..."
|
||||||
|
|
||||||
#: ../js/ui/dash.js:369
|
#: ../js/ui/dash.js:372
|
||||||
msgid "Browse"
|
msgid "Browse"
|
||||||
msgstr "Przeglądaj"
|
msgstr "Przeglądaj"
|
||||||
|
|
||||||
|
#: ../js/ui/dash.js:508
|
||||||
|
msgid "(see all)"
|
||||||
|
msgstr "(wyświetl wszystko)"
|
||||||
|
|
||||||
#. **** Applications ****
|
#. **** Applications ****
|
||||||
#: ../js/ui/dash.js:505 ../js/ui/dash.js:578
|
#: ../js/ui/dash.js:700 ../js/ui/dash.js:756 ../js/ui/dash.js:887
|
||||||
msgid "APPLICATIONS"
|
msgid "APPLICATIONS"
|
||||||
msgstr "Programy"
|
msgstr "Programy"
|
||||||
|
|
||||||
#. **** Documents ****
|
|
||||||
#: ../js/ui/dash.js:510 ../js/ui/dash.js:605
|
|
||||||
msgid "RECENT DOCUMENTS"
|
|
||||||
msgstr "Ostatnie dokumenty"
|
|
||||||
|
|
||||||
#. **** Places ****
|
#. **** Places ****
|
||||||
#. Translators: This is in the sense of locations for documents,
|
#. Translators: This is in the sense of locations for documents,
|
||||||
#. network locations, etc.
|
#. network locations, etc.
|
||||||
#: ../js/ui/dash.js:598
|
#: ../js/ui/dash.js:720
|
||||||
msgid "PLACES"
|
msgid "PLACES"
|
||||||
msgstr "Miejsca"
|
msgstr "Miejsca"
|
||||||
|
|
||||||
#: ../js/ui/runDialog.js:74
|
#. **** Documents ****
|
||||||
|
#: ../js/ui/dash.js:727 ../js/ui/dash.js:768 ../js/ui/dash.js:861
|
||||||
|
msgid "RECENT DOCUMENTS"
|
||||||
|
msgstr "Ostatnie dokumenty"
|
||||||
|
|
||||||
|
#. **** Search Results ****
|
||||||
|
#: ../js/ui/dash.js:746 ../js/ui/dash.js:850 ../js/ui/dash.js:876
|
||||||
|
msgid "SEARCH RESULTS"
|
||||||
|
msgstr "Wyniki wyszukiwania"
|
||||||
|
|
||||||
|
#: ../js/ui/runDialog.js:90
|
||||||
msgid "Please enter a command:"
|
msgid "Please enter a command:"
|
||||||
msgstr "Proszę wprowadzić polecenie:"
|
msgstr "Proszę wprowadzić polecenie:"
|
||||||
|
|
||||||
#: ../src/gdmuser/gdm-user.c:243
|
#: ../src/shell-global.c:799
|
||||||
msgid "Manager"
|
|
||||||
msgstr "Menedżer"
|
|
||||||
|
|
||||||
#: ../src/gdmuser/gdm-user.c:244
|
|
||||||
msgid "The user manager object this user is controlled by."
|
|
||||||
msgstr "Obiekt menedżera użytkowników, który steruje tym użytkownikiem."
|
|
||||||
|
|
||||||
#: ../src/shell-global.c:841
|
|
||||||
msgid "Less than a minute ago"
|
msgid "Less than a minute ago"
|
||||||
msgstr "Mniej niż minutę temu"
|
msgstr "Mniej niż minutę temu"
|
||||||
|
|
||||||
#: ../src/shell-global.c:844
|
#: ../src/shell-global.c:802
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d minute ago"
|
msgid "%d minute ago"
|
||||||
msgid_plural "%d minutes ago"
|
msgid_plural "%d minutes ago"
|
||||||
@@ -87,7 +88,7 @@ msgstr[0] "%d minuta temu"
|
|||||||
msgstr[1] "%d minuty temu"
|
msgstr[1] "%d minuty temu"
|
||||||
msgstr[2] "%d minut temu"
|
msgstr[2] "%d minut temu"
|
||||||
|
|
||||||
#: ../src/shell-global.c:847
|
#: ../src/shell-global.c:805
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d hour ago"
|
msgid "%d hour ago"
|
||||||
msgid_plural "%d hours ago"
|
msgid_plural "%d hours ago"
|
||||||
@@ -95,7 +96,7 @@ msgstr[0] "%d godzina temu"
|
|||||||
msgstr[1] "%d godziny temu"
|
msgstr[1] "%d godziny temu"
|
||||||
msgstr[2] "%d godzin temu"
|
msgstr[2] "%d godzin temu"
|
||||||
|
|
||||||
#: ../src/shell-global.c:850
|
#: ../src/shell-global.c:808
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d day ago"
|
msgid "%d day ago"
|
||||||
msgid_plural "%d days ago"
|
msgid_plural "%d days ago"
|
||||||
@@ -103,7 +104,7 @@ msgstr[0] "%d dzień temu"
|
|||||||
msgstr[1] "%d dni temu"
|
msgstr[1] "%d dni temu"
|
||||||
msgstr[2] "%d dni temu"
|
msgstr[2] "%d dni temu"
|
||||||
|
|
||||||
#: ../src/shell-global.c:853
|
#: ../src/shell-global.c:811
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d week ago"
|
msgid "%d week ago"
|
||||||
msgid_plural "%d weeks ago"
|
msgid_plural "%d weeks ago"
|
||||||
|
|||||||
109
po/pt_BR.po
@@ -2,91 +2,107 @@
|
|||||||
# Copyright (C) 2009 THE gnome-shell'S COPYRIGHT HOLDER
|
# Copyright (C) 2009 THE gnome-shell'S COPYRIGHT HOLDER
|
||||||
# This file is distributed under the same license as the gnome-shell package.
|
# This file is distributed under the same license as the gnome-shell package.
|
||||||
# Og Maciel <ogmaciel@gnome.org>, 2009.
|
# Og Maciel <ogmaciel@gnome.org>, 2009.
|
||||||
|
# Rodrigo Flores <mail@rodrigoflores.org>, 2009.
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: \n"
|
"Project-Id-Version: \n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2009-08-14 17:53-0400\n"
|
"POT-Creation-Date: 2009-09-21 08:39-0300\n"
|
||||||
"PO-Revision-Date: 2009-08-14 17:53-0400\n"
|
"PO-Revision-Date: 2009-09-20 08:41-0300\n"
|
||||||
"Last-Translator: Og Maciel <ogmaciel@gnome.org>\n"
|
"Last-Translator: Rodrigo Flores <mail@rodrigoflores.org>\n"
|
||||||
"Language-Team: Brazilian Portuguese <gnome-pt_br-list@gnome.org>\n"
|
"Language-Team: Brazilian Portuguese <gnome-pt_br-list@gnome.org>\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||||
|
|
||||||
|
#: ../data/gnome-shell.desktop.in.in.h:1
|
||||||
|
msgid "GNOME Shell"
|
||||||
|
msgstr "GNOME Shell"
|
||||||
|
|
||||||
|
#: ../data/gnome-shell.desktop.in.in.h:2
|
||||||
|
msgid "Window management and application launching"
|
||||||
|
msgstr "Gerenciamento de janelas e lançador de aplicações"
|
||||||
|
|
||||||
#. left side
|
#. left side
|
||||||
#: ../js/ui/panel.js:266
|
#: ../js/ui/panel.js:269
|
||||||
msgid "Activities"
|
msgid "Activities"
|
||||||
msgstr "Atividades"
|
msgstr "Atividades"
|
||||||
|
|
||||||
#. Translators: This is a time format.
|
#. Translators: This is a time format.
|
||||||
#: ../js/ui/panel.js:412
|
#: ../js/ui/panel.js:452
|
||||||
msgid "%a %l:%M %p"
|
msgid "%a %l:%M %p"
|
||||||
msgstr "%a %l:%M %p"
|
msgstr "%a %l:%M %p"
|
||||||
|
|
||||||
#: ../js/ui/dash.js:235
|
#: ../js/ui/dash.js:283
|
||||||
msgid "Find apps or documents"
|
msgid "Find..."
|
||||||
msgstr "Localizar aplicativos ou documentos"
|
msgstr "Encontre..."
|
||||||
|
|
||||||
#: ../js/ui/dash.js:336
|
#: ../js/ui/dash.js:400
|
||||||
msgid "Browse"
|
msgid "Browse"
|
||||||
msgstr "Navegar"
|
msgstr "Navegar"
|
||||||
|
|
||||||
|
#: ../js/ui/dash.js:536
|
||||||
|
msgid "(see all)"
|
||||||
|
msgstr "(veja todos)"
|
||||||
|
|
||||||
#. **** Applications ****
|
#. **** Applications ****
|
||||||
#: ../js/ui/dash.js:472 ../js/ui/dash.js:545
|
#: ../js/ui/dash.js:753 ../js/ui/dash.js:809
|
||||||
msgid "APPLICATIONS"
|
msgid "APPLICATIONS"
|
||||||
msgstr "APLICATIVOS"
|
msgstr "APLICATIVOS"
|
||||||
|
|
||||||
#. **** Documents ****
|
|
||||||
#: ../js/ui/dash.js:477 ../js/ui/dash.js:570
|
|
||||||
msgid "RECENT DOCUMENTS"
|
|
||||||
msgstr "DOCUMENTOS RECENTES"
|
|
||||||
|
|
||||||
#. **** Places ****
|
#. **** Places ****
|
||||||
#: ../js/ui/dash.js:563
|
#. Translators: This is in the sense of locations for documents,
|
||||||
|
#. network locations, etc.
|
||||||
|
#: ../js/ui/dash.js:773
|
||||||
msgid "PLACES"
|
msgid "PLACES"
|
||||||
msgstr "LOCAIS"
|
msgstr "LOCAIS"
|
||||||
|
|
||||||
#: ../js/ui/runDialog.js:74
|
#. **** Documents ****
|
||||||
|
#: ../js/ui/dash.js:780 ../js/ui/dash.js:819
|
||||||
|
msgid "RECENT DOCUMENTS"
|
||||||
|
msgstr "DOCUMENTOS RECENTES"
|
||||||
|
|
||||||
|
#. **** Search Results ****
|
||||||
|
#: ../js/ui/dash.js:799 ../js/ui/dash.js:931
|
||||||
|
msgid "SEARCH RESULTS"
|
||||||
|
msgstr "RESULTADOS DA BUSCA"
|
||||||
|
|
||||||
|
#: ../js/ui/dash.js:814
|
||||||
|
msgid "PREFERENCES"
|
||||||
|
msgstr "PREFERÊNCIAS"
|
||||||
|
|
||||||
|
#: ../js/ui/runDialog.js:101
|
||||||
msgid "Please enter a command:"
|
msgid "Please enter a command:"
|
||||||
msgstr "Por favor digite um comando:"
|
msgstr "Por favor digite um comando:"
|
||||||
|
|
||||||
#: ../src/gdmuser/gdm-user.c:242
|
#: ../src/shell-global.c:799
|
||||||
msgid "Manager"
|
|
||||||
msgstr "Gerenciador"
|
|
||||||
|
|
||||||
#: ../src/gdmuser/gdm-user.c:243
|
|
||||||
msgid "The user manager object this user is controlled by."
|
|
||||||
msgstr "O objeto gerenciador de usuários que controla este usuário."
|
|
||||||
|
|
||||||
#: ../src/shell-global.c:841
|
|
||||||
msgid "Less than a minute ago"
|
msgid "Less than a minute ago"
|
||||||
msgstr "Menos de um minuto atrás"
|
msgstr "Menos de um minuto atrás"
|
||||||
|
|
||||||
#: ../src/shell-global.c:844
|
#: ../src/shell-global.c:802
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d minute ago"
|
msgid "%d minute ago"
|
||||||
msgid_plural "%d minutes ago"
|
msgid_plural "%d minutes ago"
|
||||||
msgstr[0] "%d minuto atrás"
|
msgstr[0] "%d minuto atrás"
|
||||||
msgstr[1] "%d minutos atrás"
|
msgstr[1] "%d minutos atrás"
|
||||||
|
|
||||||
#: ../src/shell-global.c:847
|
#: ../src/shell-global.c:805
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d hour ago"
|
msgid "%d hour ago"
|
||||||
msgid_plural "%d hours ago"
|
msgid_plural "%d hours ago"
|
||||||
msgstr[0] "%d hora atrás"
|
msgstr[0] "%d hora atrás"
|
||||||
msgstr[1] "%d horas atrás"
|
msgstr[1] "%d horas atrás"
|
||||||
|
|
||||||
#: ../src/shell-global.c:850
|
#: ../src/shell-global.c:808
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d day ago"
|
msgid "%d day ago"
|
||||||
msgid_plural "%d days ago"
|
msgid_plural "%d days ago"
|
||||||
msgstr[0] "%d dia atrás"
|
msgstr[0] "%d dia atrás"
|
||||||
msgstr[1] "%d dias atrás"
|
msgstr[1] "%d dias atrás"
|
||||||
|
|
||||||
#: ../src/shell-global.c:853
|
#: ../src/shell-global.c:811
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d week ago"
|
msgid "%d week ago"
|
||||||
msgid_plural "%d weeks ago"
|
msgid_plural "%d weeks ago"
|
||||||
@@ -142,3 +158,36 @@ msgstr "Encerrar sessão..."
|
|||||||
#: ../src/shell-status-menu.c:557
|
#: ../src/shell-status-menu.c:557
|
||||||
msgid "Shut Down..."
|
msgid "Shut Down..."
|
||||||
msgstr "Desligar..."
|
msgstr "Desligar..."
|
||||||
|
|
||||||
|
#: ../src/shell-uri-util.c:87
|
||||||
|
msgid "Home Folder"
|
||||||
|
msgstr "Pasta home"
|
||||||
|
|
||||||
|
#. Translators: this is the same string as the one found in
|
||||||
|
#. * nautilus
|
||||||
|
#: ../src/shell-uri-util.c:102
|
||||||
|
msgid "File System"
|
||||||
|
msgstr "Sistema de arquivos"
|
||||||
|
|
||||||
|
#: ../src/shell-uri-util.c:248
|
||||||
|
msgid "Search"
|
||||||
|
msgstr "Procurar"
|
||||||
|
|
||||||
|
#. Translators: the first string is the name of a gvfs
|
||||||
|
#. * method, and the second string is a path. For
|
||||||
|
#. * example, "Trash: some-directory". It means that the
|
||||||
|
#. * directory called "some-directory" is in the trash.
|
||||||
|
#.
|
||||||
|
#: ../src/shell-uri-util.c:298
|
||||||
|
#, c-format
|
||||||
|
msgid "%1$s: %2$s"
|
||||||
|
msgstr "%1$s: %2$s"
|
||||||
|
|
||||||
|
#~ msgid "Find apps or documents"
|
||||||
|
#~ msgstr "Localizar aplicativos ou documentos"
|
||||||
|
|
||||||
|
#~ msgid "Manager"
|
||||||
|
#~ msgstr "Gerenciador"
|
||||||
|
|
||||||
|
#~ msgid "The user manager object this user is controlled by."
|
||||||
|
#~ msgstr "O objeto gerenciador de usuários que controla este usuário."
|
||||||
|
|||||||
198
po/sl.po
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
# Slovenian translation for gnome-shell.
|
||||||
|
# This file is distributed under the same license as the gnome-shell package.
|
||||||
|
# Matej Urbančič <mateju@svn.gnome.org>, 2009.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: gnome-shell master\n"
|
||||||
|
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell&component=general\n"
|
||||||
|
"POT-Creation-Date: 2009-09-21 22:38+0000\n"
|
||||||
|
"PO-Revision-Date: 2009-09-22 10:36+0100\n"
|
||||||
|
"Last-Translator: Matej Urbančič <mateju@svn.gnome.org>\n"
|
||||||
|
"Language-Team: Slovenian <gnome-si@googlegroups.com>\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Language: Slovenian\n"
|
||||||
|
"Plural-Forms: nplurals=4; plural=(n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || n%100==4 ? 3 : 0);\n"
|
||||||
|
"X-Poedit-Language: Slovenian\n"
|
||||||
|
"X-Poedit-Country: SLOVENIA\n"
|
||||||
|
"X-Poedit-SourceCharset: utf-8\n"
|
||||||
|
|
||||||
|
#: ../data/gnome-shell.desktop.in.in.h:1
|
||||||
|
msgid "GNOME Shell"
|
||||||
|
msgstr "Gnome lupina"
|
||||||
|
|
||||||
|
#: ../data/gnome-shell.desktop.in.in.h:2
|
||||||
|
msgid "Window management and application launching"
|
||||||
|
msgstr "Upravljanje oken in zaganjanje programov"
|
||||||
|
|
||||||
|
#. left side
|
||||||
|
#: ../js/ui/panel.js:269
|
||||||
|
msgid "Activities"
|
||||||
|
msgstr "Dejavnosti"
|
||||||
|
|
||||||
|
#. Translators: This is a time format.
|
||||||
|
#: ../js/ui/panel.js:452
|
||||||
|
msgid "%a %l:%M %p"
|
||||||
|
msgstr "%a, %H:%M"
|
||||||
|
|
||||||
|
#: ../js/ui/dash.js:283
|
||||||
|
msgid "Find..."
|
||||||
|
msgstr "Poišči ..."
|
||||||
|
|
||||||
|
#: ../js/ui/dash.js:400
|
||||||
|
msgid "Browse"
|
||||||
|
msgstr "Prebrskaj"
|
||||||
|
|
||||||
|
#: ../js/ui/dash.js:536
|
||||||
|
msgid "(see all)"
|
||||||
|
msgstr "(poglej vse)"
|
||||||
|
|
||||||
|
#. **** Applications ****
|
||||||
|
#: ../js/ui/dash.js:753
|
||||||
|
#: ../js/ui/dash.js:809
|
||||||
|
msgid "APPLICATIONS"
|
||||||
|
msgstr "Programi"
|
||||||
|
|
||||||
|
#. **** Places ****
|
||||||
|
#. Translators: This is in the sense of locations for documents,
|
||||||
|
#. network locations, etc.
|
||||||
|
#: ../js/ui/dash.js:773
|
||||||
|
msgid "PLACES"
|
||||||
|
msgstr "Mesta"
|
||||||
|
|
||||||
|
#. **** Documents ****
|
||||||
|
#: ../js/ui/dash.js:780
|
||||||
|
#: ../js/ui/dash.js:819
|
||||||
|
msgid "RECENT DOCUMENTS"
|
||||||
|
msgstr "Nedavni dokumenti"
|
||||||
|
|
||||||
|
#. **** Search Results ****
|
||||||
|
#: ../js/ui/dash.js:799
|
||||||
|
#: ../js/ui/dash.js:931
|
||||||
|
msgid "SEARCH RESULTS"
|
||||||
|
msgstr "Rezultati iskanja"
|
||||||
|
|
||||||
|
#: ../js/ui/dash.js:814
|
||||||
|
msgid "PREFERENCES"
|
||||||
|
msgstr "Lastnosti"
|
||||||
|
|
||||||
|
#: ../js/ui/runDialog.js:101
|
||||||
|
msgid "Please enter a command:"
|
||||||
|
msgstr "Prosim, vnesite ukaz:"
|
||||||
|
|
||||||
|
#: ../src/shell-global.c:799
|
||||||
|
msgid "Less than a minute ago"
|
||||||
|
msgstr "Pred manj kot eno minuto"
|
||||||
|
|
||||||
|
#: ../src/shell-global.c:802
|
||||||
|
#, c-format
|
||||||
|
msgid "%d minute ago"
|
||||||
|
msgid_plural "%d minutes ago"
|
||||||
|
msgstr[0] "Pred %d minutami"
|
||||||
|
msgstr[1] "Pred %d minuto"
|
||||||
|
msgstr[2] "Pred %d minutama"
|
||||||
|
msgstr[3] "Pred %d minutami"
|
||||||
|
|
||||||
|
#: ../src/shell-global.c:805
|
||||||
|
#, c-format
|
||||||
|
msgid "%d hour ago"
|
||||||
|
msgid_plural "%d hours ago"
|
||||||
|
msgstr[0] "Pred %d urami"
|
||||||
|
msgstr[1] "Pred %d uro"
|
||||||
|
msgstr[2] "Pred %d urama"
|
||||||
|
msgstr[3] "Pred %d urami"
|
||||||
|
|
||||||
|
#: ../src/shell-global.c:808
|
||||||
|
#, c-format
|
||||||
|
msgid "%d day ago"
|
||||||
|
msgid_plural "%d days ago"
|
||||||
|
msgstr[0] "Pred %d dnevi"
|
||||||
|
msgstr[1] "Pred %d dnevom"
|
||||||
|
msgstr[2] "Pred %d dnevoma"
|
||||||
|
msgstr[3] "Pred %d dnevi"
|
||||||
|
|
||||||
|
#: ../src/shell-global.c:811
|
||||||
|
#, c-format
|
||||||
|
msgid "%d week ago"
|
||||||
|
msgid_plural "%d weeks ago"
|
||||||
|
msgstr[0] "Pred %d tedni"
|
||||||
|
msgstr[1] "Pred %d tednom"
|
||||||
|
msgstr[2] "Pred %d tednoma"
|
||||||
|
msgstr[3] "Pred %d tedni"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:156
|
||||||
|
msgid "Unknown"
|
||||||
|
msgstr "Neznano"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:212
|
||||||
|
#, c-format
|
||||||
|
msgid "Can't lock screen: %s"
|
||||||
|
msgstr "Ni mogoče zakleniti zaslona: %s"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:227
|
||||||
|
#, c-format
|
||||||
|
msgid "Can't temporarily set screensaver to blank screen: %s"
|
||||||
|
msgstr "Ni mogoče začasno nastaviti črnega zaslona za ohranjevalnik zaslona: %s"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:351
|
||||||
|
#, c-format
|
||||||
|
msgid "Can't logout: %s"
|
||||||
|
msgstr "Ni se mogoče odjaviti: %s"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:492
|
||||||
|
msgid "Account Information..."
|
||||||
|
msgstr "Podrobnosti računa ..."
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:502
|
||||||
|
msgid "Sidebar"
|
||||||
|
msgstr "_Stranska vrstica"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:510
|
||||||
|
msgid "System Preferences..."
|
||||||
|
msgstr "Sistemske lastnosti ..."
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:525
|
||||||
|
msgid "Lock Screen"
|
||||||
|
msgstr "Zakleni zaslon"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:535
|
||||||
|
msgid "Switch User"
|
||||||
|
msgstr "Preklop uporabnika"
|
||||||
|
|
||||||
|
#. Only show switch user if there are other users
|
||||||
|
#. Log Out
|
||||||
|
#: ../src/shell-status-menu.c:546
|
||||||
|
msgid "Log Out..."
|
||||||
|
msgstr "Odjava ..."
|
||||||
|
|
||||||
|
#. Shut down
|
||||||
|
#: ../src/shell-status-menu.c:557
|
||||||
|
msgid "Shut Down..."
|
||||||
|
msgstr "Izklop ..."
|
||||||
|
|
||||||
|
#: ../src/shell-uri-util.c:87
|
||||||
|
msgid "Home Folder"
|
||||||
|
msgstr "Domača mapa"
|
||||||
|
|
||||||
|
#. Translators: this is the same string as the one found in
|
||||||
|
#. * nautilus
|
||||||
|
#: ../src/shell-uri-util.c:102
|
||||||
|
msgid "File System"
|
||||||
|
msgstr "Datotečni sistem"
|
||||||
|
|
||||||
|
#: ../src/shell-uri-util.c:248
|
||||||
|
msgid "Search"
|
||||||
|
msgstr "Iskanje"
|
||||||
|
|
||||||
|
#. Translators: the first string is the name of a gvfs
|
||||||
|
#. * method, and the second string is a path. For
|
||||||
|
#. * example, "Trash: some-directory". It means that the
|
||||||
|
#. * directory called "some-directory" is in the trash.
|
||||||
|
#.
|
||||||
|
#: ../src/shell-uri-util.c:298
|
||||||
|
#, c-format
|
||||||
|
msgid "%1$s: %2$s"
|
||||||
|
msgstr "%1$s: %2$s"
|
||||||
|
|
||||||
54
po/sv.po
@@ -7,8 +7,8 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: gnome-shell\n"
|
"Project-Id-Version: gnome-shell\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2009-08-25 07:48+0200\n"
|
"POT-Creation-Date: 2009-09-18 13:02+0200\n"
|
||||||
"PO-Revision-Date: 2009-08-25 07:48+0100\n"
|
"PO-Revision-Date: 2009-09-18 13:02+0100\n"
|
||||||
"Last-Translator: Daniel Nylander <po@danielnylander.se>\n"
|
"Last-Translator: Daniel Nylander <po@danielnylander.se>\n"
|
||||||
"Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
|
"Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
@@ -25,80 +25,86 @@ msgid "Window management and application launching"
|
|||||||
msgstr "Fönsterhantering och programstarter"
|
msgstr "Fönsterhantering och programstarter"
|
||||||
|
|
||||||
#. left side
|
#. left side
|
||||||
#: ../js/ui/panel.js:266
|
#: ../js/ui/panel.js:269
|
||||||
msgid "Activities"
|
msgid "Activities"
|
||||||
msgstr "Aktiviteter"
|
msgstr "Aktiviteter"
|
||||||
|
|
||||||
#. Translators: This is a time format.
|
#. Translators: This is a time format.
|
||||||
#: ../js/ui/panel.js:433
|
#: ../js/ui/panel.js:452
|
||||||
msgid "%a %l:%M %p"
|
msgid "%a %l:%M %p"
|
||||||
msgstr "%a %H.%M"
|
msgstr "%a %H.%M"
|
||||||
|
|
||||||
#: ../js/ui/dash.js:250
|
#: ../js/ui/dash.js:283
|
||||||
msgid "Find apps or documents"
|
msgid "Find..."
|
||||||
msgstr "Hitta program eller dokument"
|
msgstr "Sök..."
|
||||||
|
|
||||||
#: ../js/ui/dash.js:368
|
#: ../js/ui/dash.js:400
|
||||||
msgid "Browse"
|
msgid "Browse"
|
||||||
msgstr "Bläddra"
|
msgstr "Bläddra"
|
||||||
|
|
||||||
|
#: ../js/ui/dash.js:536
|
||||||
|
msgid "(see all)"
|
||||||
|
msgstr "(se alla)"
|
||||||
|
|
||||||
#. **** Applications ****
|
#. **** Applications ****
|
||||||
#: ../js/ui/dash.js:556
|
#: ../js/ui/dash.js:753
|
||||||
#: ../js/ui/dash.js:606
|
#: ../js/ui/dash.js:809
|
||||||
msgid "APPLICATIONS"
|
msgid "APPLICATIONS"
|
||||||
msgstr "PROGRAM"
|
msgstr "PROGRAM"
|
||||||
|
|
||||||
#. **** Places ****
|
#. **** Places ****
|
||||||
#. Translators: This is in the sense of locations for documents,
|
#. Translators: This is in the sense of locations for documents,
|
||||||
#. network locations, etc.
|
#. network locations, etc.
|
||||||
#: ../js/ui/dash.js:576
|
#: ../js/ui/dash.js:773
|
||||||
msgid "PLACES"
|
msgid "PLACES"
|
||||||
msgstr "PLATSER"
|
msgstr "PLATSER"
|
||||||
|
|
||||||
#. **** Documents ****
|
#. **** Documents ****
|
||||||
#: ../js/ui/dash.js:583
|
#: ../js/ui/dash.js:780
|
||||||
|
#: ../js/ui/dash.js:819
|
||||||
msgid "RECENT DOCUMENTS"
|
msgid "RECENT DOCUMENTS"
|
||||||
msgstr "SENASTE DOKUMENT"
|
msgstr "SENASTE DOKUMENT"
|
||||||
|
|
||||||
#. **** Search Results ****
|
#. **** Search Results ****
|
||||||
#: ../js/ui/dash.js:602
|
#: ../js/ui/dash.js:799
|
||||||
|
#: ../js/ui/dash.js:931
|
||||||
msgid "SEARCH RESULTS"
|
msgid "SEARCH RESULTS"
|
||||||
msgstr "SÖKRESULTAT"
|
msgstr "SÖKRESULTAT"
|
||||||
|
|
||||||
#: ../js/ui/dash.js:615
|
#: ../js/ui/dash.js:814
|
||||||
msgid "DOCUMENTS"
|
msgid "PREFERENCES"
|
||||||
msgstr "DOKUMENT"
|
msgstr "INSTÄLLNINGAR"
|
||||||
|
|
||||||
#: ../js/ui/runDialog.js:75
|
#: ../js/ui/runDialog.js:101
|
||||||
msgid "Please enter a command:"
|
msgid "Please enter a command:"
|
||||||
msgstr "Ange ett kommando:"
|
msgstr "Ange ett kommando:"
|
||||||
|
|
||||||
#: ../src/shell-global.c:841
|
#: ../src/shell-global.c:799
|
||||||
msgid "Less than a minute ago"
|
msgid "Less than a minute ago"
|
||||||
msgstr "Mindre än en minut sedan"
|
msgstr "Mindre än en minut sedan"
|
||||||
|
|
||||||
#: ../src/shell-global.c:844
|
#: ../src/shell-global.c:802
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d minute ago"
|
msgid "%d minute ago"
|
||||||
msgid_plural "%d minutes ago"
|
msgid_plural "%d minutes ago"
|
||||||
msgstr[0] "%d minut sedan"
|
msgstr[0] "%d minut sedan"
|
||||||
msgstr[1] "%d minuter sedan"
|
msgstr[1] "%d minuter sedan"
|
||||||
|
|
||||||
#: ../src/shell-global.c:847
|
#: ../src/shell-global.c:805
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d hour ago"
|
msgid "%d hour ago"
|
||||||
msgid_plural "%d hours ago"
|
msgid_plural "%d hours ago"
|
||||||
msgstr[0] "%d timme sedan"
|
msgstr[0] "%d timme sedan"
|
||||||
msgstr[1] "%d timmar sedan"
|
msgstr[1] "%d timmar sedan"
|
||||||
|
|
||||||
#: ../src/shell-global.c:850
|
#: ../src/shell-global.c:808
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d day ago"
|
msgid "%d day ago"
|
||||||
msgid_plural "%d days ago"
|
msgid_plural "%d days ago"
|
||||||
msgstr[0] "%d dag sedan"
|
msgstr[0] "%d dag sedan"
|
||||||
msgstr[1] "%d dagar sedan"
|
msgstr[1] "%d dagar sedan"
|
||||||
|
|
||||||
#: ../src/shell-global.c:853
|
#: ../src/shell-global.c:811
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%d week ago"
|
msgid "%d week ago"
|
||||||
msgid_plural "%d weeks ago"
|
msgid_plural "%d weeks ago"
|
||||||
@@ -179,6 +185,10 @@ msgstr "Sök"
|
|||||||
msgid "%1$s: %2$s"
|
msgid "%1$s: %2$s"
|
||||||
msgstr "%1$s: %2$s"
|
msgstr "%1$s: %2$s"
|
||||||
|
|
||||||
|
#~ msgid "Find apps or documents"
|
||||||
|
#~ msgstr "Hitta program eller dokument"
|
||||||
|
#~ msgid "DOCUMENTS"
|
||||||
|
#~ msgstr "DOKUMENT"
|
||||||
#~ msgid "Manager"
|
#~ msgid "Manager"
|
||||||
#~ msgstr "Hanterare"
|
#~ msgstr "Hanterare"
|
||||||
#~ msgid "The user manager object this user is controlled by."
|
#~ msgid "The user manager object this user is controlled by."
|
||||||
|
|||||||
176
po/zh_CN.po
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
# Chinese (China) translation for gnome-shell.
|
||||||
|
# Copyright (C) 2009 gnome-shell's COPYRIGHT HOLDER
|
||||||
|
# This file is distributed under the same license as the gnome-shell package.
|
||||||
|
# Ray Wang <raywang@gnome.org>, 2009.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: gnome-shell master\n"
|
||||||
|
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
|
||||||
|
"shell&component=general\n"
|
||||||
|
"POT-Creation-Date: 2009-08-29 19:32+0000\n"
|
||||||
|
"PO-Revision-Date: 2009-08-30 00:08+0800\n"
|
||||||
|
"Last-Translator: Ray Wang <raywang@gnome.org>\n"
|
||||||
|
"Language-Team: Chinese (Simplified) <i18n-zh@googlegroups.com>\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: utf-8\n"
|
||||||
|
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||||
|
|
||||||
|
#: ../data/gnome-shell.desktop.in.in.h:1
|
||||||
|
msgid "GNOME Shell"
|
||||||
|
msgstr "GNOME Shell"
|
||||||
|
|
||||||
|
#: ../data/gnome-shell.desktop.in.in.h:2
|
||||||
|
msgid "Window management and application launching"
|
||||||
|
msgstr "窗口管理和应用程序启动"
|
||||||
|
|
||||||
|
#. left side
|
||||||
|
#: ../js/ui/panel.js:271
|
||||||
|
msgid "Activities"
|
||||||
|
msgstr "活动"
|
||||||
|
|
||||||
|
#. Translators: This is a time format.
|
||||||
|
#: ../js/ui/panel.js:454
|
||||||
|
msgid "%a %l:%M %p"
|
||||||
|
msgstr "%A %H:%M"
|
||||||
|
|
||||||
|
#: ../js/ui/dash.js:256
|
||||||
|
msgid "Find..."
|
||||||
|
msgstr "查找..."
|
||||||
|
|
||||||
|
#: ../js/ui/dash.js:374
|
||||||
|
msgid "Browse"
|
||||||
|
msgstr "浏览"
|
||||||
|
|
||||||
|
#: ../js/ui/dash.js:451
|
||||||
|
msgid "(see all)"
|
||||||
|
msgstr "(查看所有)"
|
||||||
|
|
||||||
|
#. **** Applications ****
|
||||||
|
#: ../js/ui/dash.js:633 ../js/ui/dash.js:681
|
||||||
|
msgid "APPLICATIONS"
|
||||||
|
msgstr "应用程序"
|
||||||
|
|
||||||
|
#. **** Places ****
|
||||||
|
#. Translators: This is in the sense of locations for documents,
|
||||||
|
#. network locations, etc.
|
||||||
|
#: ../js/ui/dash.js:653
|
||||||
|
msgid "PLACES"
|
||||||
|
msgstr "位置"
|
||||||
|
|
||||||
|
#. **** Documents ****
|
||||||
|
#: ../js/ui/dash.js:660 ../js/ui/dash.js:692
|
||||||
|
msgid "RECENT DOCUMENTS"
|
||||||
|
msgstr "最近的文档"
|
||||||
|
|
||||||
|
#. **** Search Results ****
|
||||||
|
#: ../js/ui/dash.js:679
|
||||||
|
msgid "SEARCH RESULTS"
|
||||||
|
msgstr "搜索结果"
|
||||||
|
|
||||||
|
#: ../js/ui/runDialog.js:82
|
||||||
|
msgid "Please enter a command:"
|
||||||
|
msgstr "请输入一个命令:"
|
||||||
|
|
||||||
|
#: ../src/shell-global.c:840
|
||||||
|
msgid "Less than a minute ago"
|
||||||
|
msgstr "少于一分钟前"
|
||||||
|
|
||||||
|
#: ../src/shell-global.c:843
|
||||||
|
#, c-format
|
||||||
|
msgid "%d minute ago"
|
||||||
|
msgid_plural "%d minutes ago"
|
||||||
|
msgstr[0] "%d 分钟前"
|
||||||
|
|
||||||
|
#: ../src/shell-global.c:846
|
||||||
|
#, c-format
|
||||||
|
msgid "%d hour ago"
|
||||||
|
msgid_plural "%d hours ago"
|
||||||
|
msgstr[0] "%d 小时前"
|
||||||
|
|
||||||
|
#: ../src/shell-global.c:849
|
||||||
|
#, c-format
|
||||||
|
msgid "%d day ago"
|
||||||
|
msgid_plural "%d days ago"
|
||||||
|
msgstr[0] "%d 天前"
|
||||||
|
|
||||||
|
#: ../src/shell-global.c:852
|
||||||
|
#, c-format
|
||||||
|
msgid "%d week ago"
|
||||||
|
msgid_plural "%d weeks ago"
|
||||||
|
msgstr[0] "%d 周前"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:156
|
||||||
|
msgid "Unknown"
|
||||||
|
msgstr "未知"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:212
|
||||||
|
#, c-format
|
||||||
|
msgid "Can't lock screen: %s"
|
||||||
|
msgstr "不能锁住屏幕:%s"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:227
|
||||||
|
#, c-format
|
||||||
|
msgid "Can't temporarily set screensaver to blank screen: %s"
|
||||||
|
msgstr "不能临时将屏幕保护设置成空白屏幕:%s"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:351
|
||||||
|
#, c-format
|
||||||
|
msgid "Can't logout: %s"
|
||||||
|
msgstr "不能退出:%s"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:492
|
||||||
|
msgid "Account Information..."
|
||||||
|
msgstr "帐户信息..."
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:502
|
||||||
|
msgid "Sidebar"
|
||||||
|
msgstr "侧边栏"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:510
|
||||||
|
msgid "System Preferences..."
|
||||||
|
msgstr "系统首选项..."
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:525
|
||||||
|
msgid "Lock Screen"
|
||||||
|
msgstr "锁住屏幕"
|
||||||
|
|
||||||
|
#: ../src/shell-status-menu.c:535
|
||||||
|
msgid "Switch User"
|
||||||
|
msgstr "切换用户"
|
||||||
|
|
||||||
|
#. Only show switch user if there are other users
|
||||||
|
#. Log Out
|
||||||
|
#: ../src/shell-status-menu.c:546
|
||||||
|
msgid "Log Out..."
|
||||||
|
msgstr "退出..."
|
||||||
|
|
||||||
|
#. Shut down
|
||||||
|
#: ../src/shell-status-menu.c:557
|
||||||
|
msgid "Shut Down..."
|
||||||
|
msgstr "关机..."
|
||||||
|
|
||||||
|
#: ../src/shell-uri-util.c:87
|
||||||
|
msgid "Home Folder"
|
||||||
|
msgstr "主文件夹"
|
||||||
|
|
||||||
|
#. Translators: this is the same string as the one found in
|
||||||
|
#. * nautilus
|
||||||
|
#: ../src/shell-uri-util.c:102
|
||||||
|
msgid "File System"
|
||||||
|
msgstr "文件系统"
|
||||||
|
|
||||||
|
#: ../src/shell-uri-util.c:248
|
||||||
|
msgid "Search"
|
||||||
|
msgstr "搜索"
|
||||||
|
|
||||||
|
#. Translators: the first string is the name of a gvfs
|
||||||
|
#. * method, and the second string is a path. For
|
||||||
|
#. * example, "Trash: some-directory". It means that the
|
||||||
|
#. * directory called "some-directory" is in the trash.
|
||||||
|
#.
|
||||||
|
#: ../src/shell-uri-util.c:298
|
||||||
|
#, c-format
|
||||||
|
msgid "%1$s: %2$s"
|
||||||
|
msgstr "%1$s: %2$s"
|
||||||
142
src/Makefile-st.am
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
st_cflags = \
|
||||||
|
-I$(top_srcdir)/src \
|
||||||
|
-DPREFIX=\""$(prefix)"\" \
|
||||||
|
-DLIBDIR=\""$(libdir)"\" \
|
||||||
|
-DG_DISABLE_DEPRECATED \
|
||||||
|
-DG_LOG_DOMAIN=\"St\" \
|
||||||
|
-DST_COMPILATION \
|
||||||
|
-DPACKAGE_DATA_DIR=\"$(pkgdatadir)\" \
|
||||||
|
$(ST_CFLAGS) \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
|
st_built_sources = \
|
||||||
|
st-enum-types.h \
|
||||||
|
st-enum-types.c \
|
||||||
|
st-marshal.h \
|
||||||
|
st-marshal.c
|
||||||
|
|
||||||
|
BUILT_SOURCES += $(st_built_sources)
|
||||||
|
|
||||||
|
EXTRA_DIST += \
|
||||||
|
st/st-marshal.list \
|
||||||
|
st/st-enum-types.h.in \
|
||||||
|
st/st-enum-types.c.in
|
||||||
|
|
||||||
|
CLEANFILES += stamp-st-marshal.h stamp-st-enum-types.h
|
||||||
|
|
||||||
|
st-marshal.h: stamp-st-marshal.h
|
||||||
|
@true
|
||||||
|
stamp-st-marshal.h: Makefile st/st-marshal.list
|
||||||
|
$(AM_V_GEN) $(GLIB_GENMARSHAL) \
|
||||||
|
--prefix=_st_marshal \
|
||||||
|
--header \
|
||||||
|
$(srcdir)/st/st-marshal.list > $@.tmp && \
|
||||||
|
(cmp -s $@.tmp st-marshal.h || cp -f $@.tmp st-marshal.h) && \
|
||||||
|
rm -f $@.tmp && \
|
||||||
|
echo timestamp > $(@F)
|
||||||
|
|
||||||
|
st-marshal.c: Makefile st/st-marshal.list
|
||||||
|
$(AM_V_GEN) (echo "#include \"st-marshal.h\"" ; \
|
||||||
|
$(GLIB_GENMARSHAL) \
|
||||||
|
--prefix=_st_marshal \
|
||||||
|
--body \
|
||||||
|
$(srcdir)/st/st-marshal.list ) > $@.tmp && \
|
||||||
|
cp -f $@.tmp st-marshal.c && \
|
||||||
|
rm -f $@.tmp
|
||||||
|
|
||||||
|
st-enum-types.h: stamp-st-enum-types.h Makefile
|
||||||
|
@true
|
||||||
|
stamp-st-enum-types.h: $(source_h) st/st-enum-types.h.in
|
||||||
|
$(AM_V_GEN) ( cd $(srcdir) && \
|
||||||
|
$(GLIB_MKENUMS) \
|
||||||
|
--template st/st-enum-types.h.in \
|
||||||
|
$(st_source_h) ) >> $@.tmp && \
|
||||||
|
(cmp -s $@.tmp st-enum-types.h || cp $@.tmp st-enum-types.h) && \
|
||||||
|
rm -f $@.tmp && \
|
||||||
|
echo timestamp > $(@F)
|
||||||
|
|
||||||
|
st-enum-types.c: stamp-st-enum-types.h st/st-enum-types.c.in
|
||||||
|
$(AM_V_GEN) ( cd $(srcdir) && \
|
||||||
|
$(GLIB_MKENUMS) \
|
||||||
|
--template st/st-enum-types.c.in \
|
||||||
|
$(st_source_h) ) >> $@.tmp && \
|
||||||
|
cp $@.tmp $@ && \
|
||||||
|
rm -f $@.tmp
|
||||||
|
|
||||||
|
# please, keep this sorted alphabetically
|
||||||
|
st_source_h = \
|
||||||
|
st/st-adjustment.h \
|
||||||
|
st/st-bin.h \
|
||||||
|
st/st-border-image.h \
|
||||||
|
st/st-box-layout.h \
|
||||||
|
st/st-box-layout-child.h \
|
||||||
|
st/st-button.h \
|
||||||
|
st/st-clipboard.h \
|
||||||
|
st/st-entry.h \
|
||||||
|
st/st-label.h \
|
||||||
|
st/st-scrollable.h \
|
||||||
|
st/st-scroll-bar.h \
|
||||||
|
st/st-scroll-view.h \
|
||||||
|
st/st-subtexture.h \
|
||||||
|
st/st-table.h \
|
||||||
|
st/st-table-child.h \
|
||||||
|
st/st-texture-cache.h \
|
||||||
|
st/st-texture-frame.h \
|
||||||
|
st/st-theme.h \
|
||||||
|
st/st-theme-context.h \
|
||||||
|
st/st-theme-node.h \
|
||||||
|
st/st-tooltip.h \
|
||||||
|
st/st-types.h \
|
||||||
|
st/st-widget.h \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
|
st_source_private_h = \
|
||||||
|
st/st-private.h \
|
||||||
|
st/st-table-private.h \
|
||||||
|
st/st-theme-private.h
|
||||||
|
|
||||||
|
# please, keep this sorted alphabetically
|
||||||
|
st_source_c = \
|
||||||
|
st/st-adjustment.c \
|
||||||
|
st/st-bin.c \
|
||||||
|
st/st-border-image.c \
|
||||||
|
st/st-box-layout.c \
|
||||||
|
st/st-box-layout-child.c \
|
||||||
|
st/st-button.c \
|
||||||
|
st/st-clipboard.c \
|
||||||
|
st/st-entry.c \
|
||||||
|
st/st-label.c \
|
||||||
|
st/st-private.c \
|
||||||
|
st/st-scrollable.c \
|
||||||
|
st/st-scroll-bar.c \
|
||||||
|
st/st-scroll-view.c \
|
||||||
|
st/st-subtexture.c \
|
||||||
|
st/st-table.c \
|
||||||
|
st/st-table-child.c \
|
||||||
|
st/st-texture-cache.c \
|
||||||
|
st/st-texture-frame.c \
|
||||||
|
st/st-theme.c \
|
||||||
|
st/st-theme-context.c \
|
||||||
|
st/st-theme-node.c \
|
||||||
|
st/st-tooltip.c \
|
||||||
|
st/st-widget.c \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
|
noinst_LTLIBRARIES += libst-1.0.la
|
||||||
|
|
||||||
|
libst_1_0_la_LIBADD = $(ST_LIBS)
|
||||||
|
libst_1_0_la_SOURCES = \
|
||||||
|
$(st_source_c) \
|
||||||
|
$(st_source_private_c) \
|
||||||
|
$(st_source_h) \
|
||||||
|
$(st_built_sources) \
|
||||||
|
$(NULL)
|
||||||
|
libst_1_0_la_CPPFLAGS = $(st_cflags)
|
||||||
|
libst_1_0_la_LDFLAGS = $(LDADD)
|
||||||
|
|
||||||
|
noinst_PROGRAMS += test-theme
|
||||||
|
|
||||||
|
test_theme_CPPFLAGS = $(st_cflags)
|
||||||
|
test_theme_LDADD = libst-1.0.la
|
||||||
|
|
||||||
|
test_theme_SOURCES = st/test-theme.c
|
||||||
@@ -1,9 +1,12 @@
|
|||||||
NULL =
|
NULL =
|
||||||
BUILT_SOURCES =
|
BUILT_SOURCES =
|
||||||
CLEANFILES =
|
CLEANFILES =
|
||||||
EXTRA_DIST =
|
EXTRA_DIST =
|
||||||
libexec_PROGRAMS =
|
libexec_PROGRAMS =
|
||||||
noinst_LTLIBRARIES =
|
noinst_LTLIBRARIES =
|
||||||
|
noinst_PROGRAMS =
|
||||||
|
|
||||||
|
.AUTOPARALLEL:
|
||||||
|
|
||||||
bin_SCRIPTS = gnome-shell
|
bin_SCRIPTS = gnome-shell
|
||||||
|
|
||||||
@@ -14,6 +17,7 @@ gnome-shell: gnome-shell.in
|
|||||||
-e "s|@libexecdir[@]|$(libexecdir)|" \
|
-e "s|@libexecdir[@]|$(libexecdir)|" \
|
||||||
-e "s|@libdir[@]|$(libdir)|" \
|
-e "s|@libdir[@]|$(libdir)|" \
|
||||||
-e "s|@pkgdatadir[@]|$(pkgdatadir)|" \
|
-e "s|@pkgdatadir[@]|$(pkgdatadir)|" \
|
||||||
|
-e "s|@PYTHON[@]|$(PYTHON)|" \
|
||||||
-e "s|@sysconfdir[@]|$(sysconfdir)|" \
|
-e "s|@sysconfdir[@]|$(sysconfdir)|" \
|
||||||
$< > $@ && chmod a+x $@
|
$< > $@ && chmod a+x $@
|
||||||
CLEANFILES += gnome-shell
|
CLEANFILES += gnome-shell
|
||||||
@@ -21,6 +25,7 @@ EXTRA_DIST += gnome-shell.in
|
|||||||
|
|
||||||
include Makefile-big.am
|
include Makefile-big.am
|
||||||
include Makefile-gdmuser.am
|
include Makefile-gdmuser.am
|
||||||
|
include Makefile-st.am
|
||||||
include Makefile-tray.am
|
include Makefile-tray.am
|
||||||
|
|
||||||
gnome_shell_cflags = \
|
gnome_shell_cflags = \
|
||||||
@@ -49,8 +54,6 @@ CLEANFILES += $(SHELL_STAMP_FILES)
|
|||||||
libgnome_shell_la_SOURCES = \
|
libgnome_shell_la_SOURCES = \
|
||||||
$(shell_built_sources) \
|
$(shell_built_sources) \
|
||||||
gnome-shell-plugin.c \
|
gnome-shell-plugin.c \
|
||||||
shell-alttab.c \
|
|
||||||
shell-alttab.h \
|
|
||||||
shell-app-monitor.c \
|
shell-app-monitor.c \
|
||||||
shell-app-monitor.h \
|
shell-app-monitor.h \
|
||||||
shell-app-system.c \
|
shell-app-system.c \
|
||||||
@@ -72,6 +75,8 @@ libgnome_shell_la_SOURCES = \
|
|||||||
shell-generic-container.h \
|
shell-generic-container.h \
|
||||||
shell-gtk-embed.c \
|
shell-gtk-embed.c \
|
||||||
shell-gtk-embed.h \
|
shell-gtk-embed.h \
|
||||||
|
shell-menu.c \
|
||||||
|
shell-menu.h \
|
||||||
shell-overflow-list.c \
|
shell-overflow-list.c \
|
||||||
shell-overflow-list.h \
|
shell-overflow-list.h \
|
||||||
shell-process.c \
|
shell-process.c \
|
||||||
@@ -91,7 +96,7 @@ libgnome_shell_la_SOURCES = \
|
|||||||
shell-wm.c \
|
shell-wm.c \
|
||||||
shell-wm.h
|
shell-wm.h
|
||||||
|
|
||||||
non_gir_sources = \
|
non_gir_sources = \
|
||||||
shell-embedded-window-private.h
|
shell-embedded-window-private.h
|
||||||
|
|
||||||
shell_recorder_sources = \
|
shell_recorder_sources = \
|
||||||
@@ -109,7 +114,7 @@ if BUILD_RECORDER
|
|||||||
libgnome_shell_la_SOURCES += $(shell_recorder_sources)
|
libgnome_shell_la_SOURCES += $(shell_recorder_sources)
|
||||||
non_gir_sources += $(shell_recorder_non_gir_sources)
|
non_gir_sources += $(shell_recorder_non_gir_sources)
|
||||||
|
|
||||||
noinst_PROGRAMS = test-recorder
|
noinst_PROGRAMS += test-recorder
|
||||||
|
|
||||||
test_recorder_CPPFLAGS = $(TEST_SHELL_RECORDER_CFLAGS)
|
test_recorder_CPPFLAGS = $(TEST_SHELL_RECORDER_CFLAGS)
|
||||||
test_recorder_LDADD = $(TEST_SHELL_RECORDER_LIBS)
|
test_recorder_LDADD = $(TEST_SHELL_RECORDER_LIBS)
|
||||||
@@ -147,22 +152,25 @@ libgnome_shell_la_LIBADD = \
|
|||||||
$(MUTTER_PLUGIN_LIBS) \
|
$(MUTTER_PLUGIN_LIBS) \
|
||||||
$(LIBGNOMEUI_LIBS) \
|
$(LIBGNOMEUI_LIBS) \
|
||||||
libbig-1.0.la \
|
libbig-1.0.la \
|
||||||
|
libst-1.0.la \
|
||||||
libgdmuser-1.0.la \
|
libgdmuser-1.0.la \
|
||||||
libtray.la
|
libtray.la
|
||||||
libgnome_shell_la_CPPFLAGS = $(gnome_shell_cflags)
|
libgnome_shell_la_CPPFLAGS = $(gnome_shell_cflags)
|
||||||
|
|
||||||
typelibdir = $(pkglibdir)
|
typelibdir = $(pkglibdir)
|
||||||
typelib_DATA = Shell-0.1.typelib Big-1.0.typelib
|
typelib_DATA = Shell-0.1.typelib Big-1.0.typelib St-1.0.typelib
|
||||||
|
|
||||||
Shell-0.1.gir: $(mutter) $(G_IR_SCANNER) Big-1.0.gir libgnome-shell.la Makefile
|
Shell-0.1.gir: $(mutter) $(G_IR_SCANNER) Big-1.0.gir St-1.0.gir libgnome-shell.la Makefile
|
||||||
$(AM_V_GEN) $(G_IR_SCANNER) \
|
$(AM_V_GEN) $(G_IR_SCANNER) \
|
||||||
--namespace=Shell \
|
--namespace=Shell \
|
||||||
--nsversion=0.1 \
|
--nsversion=0.1 \
|
||||||
--add-include-path=$(MUTTER_LIB_DIR)/mutter/ \
|
--add-include-path=$(MUTTER_LIB_DIR)/mutter/ \
|
||||||
--include=Clutter-1.0 \
|
--include=Clutter-1.0 \
|
||||||
--include=Meta-2.27 \
|
--include=Meta-2.27 \
|
||||||
|
--libtool="$(LIBTOOL)" \
|
||||||
--add-include-path=$(builddir) \
|
--add-include-path=$(builddir) \
|
||||||
--include=Big-1.0 \
|
--include=Big-1.0 \
|
||||||
|
--include=St-1.0 \
|
||||||
--program=mutter \
|
--program=mutter \
|
||||||
--program-arg=--mutter-plugins=$$(pwd)/libgnome-shell.la \
|
--program-arg=--mutter-plugins=$$(pwd)/libgnome-shell.la \
|
||||||
$(addprefix $(srcdir)/,$(libgnome_shell_la_gir_sources)) \
|
$(addprefix $(srcdir)/,$(libgnome_shell_la_gir_sources)) \
|
||||||
@@ -173,7 +181,7 @@ CLEANFILES += Shell-0.1.gir
|
|||||||
# The dependency on libgnome-shell.la here is because g-ir-compiler opens it
|
# The dependency on libgnome-shell.la here is because g-ir-compiler opens it
|
||||||
# (not the fake library, since we've already done the rewriting)
|
# (not the fake library, since we've already done the rewriting)
|
||||||
Shell-0.1.typelib: libgnome-shell.la Shell-0.1.gir Big-1.0.gir
|
Shell-0.1.typelib: libgnome-shell.la Shell-0.1.gir Big-1.0.gir
|
||||||
$(AM_V_GEN) LD_LIBRARY_PATH=.$${LD_LIBRARY_PATH:+:$$LD_LIBRARY_PATH} \
|
$(AM_V_GEN) \
|
||||||
$(G_IR_COMPILER) \
|
$(G_IR_COMPILER) \
|
||||||
--includedir=. \
|
--includedir=. \
|
||||||
--includedir=$(MUTTER_LIB_DIR)/mutter/ \
|
--includedir=$(MUTTER_LIB_DIR)/mutter/ \
|
||||||
@@ -186,6 +194,7 @@ Big-1.0.gir: $(mutter) $(G_IR_SCANNER) libgnome-shell.la libbig-1.0.la Makefile
|
|||||||
--nsversion=1.0 \
|
--nsversion=1.0 \
|
||||||
--include=Clutter-1.0 \
|
--include=Clutter-1.0 \
|
||||||
--include=GdkPixbuf-2.0 \
|
--include=GdkPixbuf-2.0 \
|
||||||
|
--libtool="$(LIBTOOL)" \
|
||||||
--program=mutter \
|
--program=mutter \
|
||||||
--program-arg=--mutter-plugins=$$(pwd)/libgnome-shell.la \
|
--program-arg=--mutter-plugins=$$(pwd)/libgnome-shell.la \
|
||||||
$(addprefix $(srcdir)/,$(big_source_h)) \
|
$(addprefix $(srcdir)/,$(big_source_h)) \
|
||||||
@@ -196,6 +205,28 @@ Big-1.0.gir: $(mutter) $(G_IR_SCANNER) libgnome-shell.la libbig-1.0.la Makefile
|
|||||||
CLEANFILES += Big-1.0.gir
|
CLEANFILES += Big-1.0.gir
|
||||||
|
|
||||||
Big-1.0.typelib: libbig-1.0.la Big-1.0.gir
|
Big-1.0.typelib: libbig-1.0.la Big-1.0.gir
|
||||||
$(AM_V_GEN) LD_LIBRARY_PATH=.$${LD_LIBRARY_PATH:+:$$LD_LIBRARY_PATH} \
|
$(AM_V_GEN) $(G_IR_COMPILER) Big-1.0.gir -o $@
|
||||||
$(G_IR_COMPILER) Big-1.0.gir -o $@
|
|
||||||
CLEANFILES += Big-1.0.typelib
|
CLEANFILES += Big-1.0.typelib
|
||||||
|
|
||||||
|
St-1.0.gir: $(mutter) $(G_IR_SCANNER) libgnome-shell.la libst-1.0.la Makefile
|
||||||
|
$(AM_V_GEN) $(G_IR_SCANNER) \
|
||||||
|
--namespace=St \
|
||||||
|
--nsversion=1.0 \
|
||||||
|
--include=Clutter-1.0 \
|
||||||
|
--add-include-path=$(builddir) \
|
||||||
|
--libtool="$(LIBTOOL)" \
|
||||||
|
--program=mutter \
|
||||||
|
--program-arg=--mutter-plugins=$$(pwd)/libgnome-shell.la \
|
||||||
|
-DST_COMPILATION \
|
||||||
|
$(addprefix $(srcdir)/,$(st_source_h)) \
|
||||||
|
$(addprefix $(srcdir)/,$(st_source_c)) \
|
||||||
|
$(srcdir)/st-enum-types.h \
|
||||||
|
$(ST_CFLAGS) \
|
||||||
|
-o $@
|
||||||
|
CLEANFILES += St-1.0.gir
|
||||||
|
|
||||||
|
St-1.0.typelib: St-1.0.gir
|
||||||
|
$(AM_V_GEN) $(G_IR_COMPILER) \
|
||||||
|
$< -o $@
|
||||||
|
|
||||||
|
CLEANFILES += St-1.0.typelib
|
||||||
|
|||||||
@@ -268,6 +268,52 @@ corner_get(guint radius,
|
|||||||
return corner;
|
return corner;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* To match the CSS specification, we want the border to look like it was
|
||||||
|
* drawn over the background. But actually drawing the border over the
|
||||||
|
* background will produce slightly bad antialiasing at the edges, so
|
||||||
|
* compute the effective border color instead.
|
||||||
|
*/
|
||||||
|
#define NORM(x) (t = (x) + 127, (t + (t >> 8)) >> 8)
|
||||||
|
#define MULT(c,a) NORM(c*a)
|
||||||
|
|
||||||
|
static void
|
||||||
|
premultiply (ClutterColor *color)
|
||||||
|
{
|
||||||
|
guint t;
|
||||||
|
color->red = MULT (color->red, color->alpha);
|
||||||
|
color->green = MULT (color->green, color->alpha);
|
||||||
|
color->blue = MULT (color->blue, color->alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
unpremultiply (ClutterColor *color)
|
||||||
|
{
|
||||||
|
if (color->alpha != 0) {
|
||||||
|
color->red = (color->red * 255 + 127) / color->alpha;
|
||||||
|
color->green = (color->green * 255 + 127) / color->alpha;
|
||||||
|
color->blue = (color->blue * 255 + 127) / color->alpha;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
over (const ClutterColor *source,
|
||||||
|
const ClutterColor *destination,
|
||||||
|
ClutterColor *result)
|
||||||
|
{
|
||||||
|
guint t;
|
||||||
|
ClutterColor src = *source;
|
||||||
|
ClutterColor dst = *destination;
|
||||||
|
premultiply (&src);
|
||||||
|
premultiply (&dst);
|
||||||
|
|
||||||
|
result->alpha = src.alpha + NORM ((255 - src.alpha) * dst.alpha);
|
||||||
|
result->red = src.red + NORM ((255 - src.alpha) * dst.red);
|
||||||
|
result->green = src.green + NORM ((255 - src.alpha) * dst.green);
|
||||||
|
result->blue = src.blue + NORM ((255 - src.alpha) * dst.blue);
|
||||||
|
|
||||||
|
unpremultiply (result);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
big_rectangle_update_corners(BigRectangle *rectangle)
|
big_rectangle_update_corners(BigRectangle *rectangle)
|
||||||
{
|
{
|
||||||
@@ -278,6 +324,7 @@ big_rectangle_update_corners(BigRectangle *rectangle)
|
|||||||
if (rectangle->radius != 0) {
|
if (rectangle->radius != 0) {
|
||||||
ClutterColor *color;
|
ClutterColor *color;
|
||||||
ClutterColor *border_color;
|
ClutterColor *border_color;
|
||||||
|
ClutterColor effective_border;
|
||||||
guint border_width;
|
guint border_width;
|
||||||
|
|
||||||
g_object_get(rectangle,
|
g_object_get(rectangle,
|
||||||
@@ -286,10 +333,12 @@ big_rectangle_update_corners(BigRectangle *rectangle)
|
|||||||
"color", &color,
|
"color", &color,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
|
over (border_color, color, &effective_border);
|
||||||
|
|
||||||
corner = corner_get(rectangle->radius,
|
corner = corner_get(rectangle->radius,
|
||||||
color,
|
color,
|
||||||
border_width,
|
border_width,
|
||||||
border_color);
|
&effective_border);
|
||||||
|
|
||||||
clutter_color_free(border_color);
|
clutter_color_free(border_color);
|
||||||
clutter_color_free(color);
|
clutter_color_free(color);
|
||||||
@@ -329,12 +378,10 @@ big_rectangle_paint(ClutterActor *actor)
|
|||||||
|
|
||||||
rectangle = BIG_RECTANGLE(actor);
|
rectangle = BIG_RECTANGLE(actor);
|
||||||
|
|
||||||
if (rectangle->radius == 0) {
|
/* We can't chain up, even when we the radius is 0, because of the different
|
||||||
/* In that case we are no different than our parent class,
|
* interpretation of the border/background relationship here than for
|
||||||
* so don't bother */
|
* ClutterRectangle.
|
||||||
CLUTTER_ACTOR_CLASS(big_rectangle_parent_class)->paint(actor);
|
*/
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rectangle->corners_dirty)
|
if (rectangle->corners_dirty)
|
||||||
big_rectangle_update_corners(rectangle);
|
big_rectangle_update_corners(rectangle);
|
||||||
@@ -345,6 +392,9 @@ big_rectangle_paint(ClutterActor *actor)
|
|||||||
"color", &color,
|
"color", &color,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
|
if (border_color->alpha == 0 && color->alpha == 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
actor_opacity = clutter_actor_get_paint_opacity (actor);
|
actor_opacity = clutter_actor_get_paint_opacity (actor);
|
||||||
|
|
||||||
clutter_actor_get_allocation_box(actor, &box);
|
clutter_actor_get_allocation_box(actor, &box);
|
||||||
@@ -358,6 +408,11 @@ big_rectangle_paint(ClutterActor *actor)
|
|||||||
|
|
||||||
radius = rectangle->radius;
|
radius = rectangle->radius;
|
||||||
|
|
||||||
|
/* Optimization; if the border is transparent, it just looks like part of
|
||||||
|
* the background */
|
||||||
|
if (radius == 0 && border_color->alpha == 0)
|
||||||
|
border_width = 0;
|
||||||
|
|
||||||
max = MAX(border_width, radius);
|
max = MAX(border_width, radius);
|
||||||
|
|
||||||
if (radius != 0) {
|
if (radius != 0) {
|
||||||
@@ -393,33 +448,54 @@ big_rectangle_paint(ClutterActor *actor)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (border_width != 0) {
|
if (border_width != 0) {
|
||||||
|
ClutterColor effective_border;
|
||||||
|
over (border_color, color, &effective_border);
|
||||||
|
|
||||||
if (!rectangle->border_material)
|
if (!rectangle->border_material)
|
||||||
rectangle->border_material = cogl_material_new ();
|
rectangle->border_material = cogl_material_new ();
|
||||||
|
|
||||||
cogl_color_set_from_4ub(&tmp_color,
|
cogl_color_set_from_4ub(&tmp_color,
|
||||||
border_color->red,
|
effective_border.red,
|
||||||
border_color->green,
|
effective_border.green,
|
||||||
border_color->blue,
|
effective_border.blue,
|
||||||
actor_opacity * border_color->alpha / 255);
|
actor_opacity * effective_border.alpha / 255);
|
||||||
cogl_color_premultiply (&tmp_color);
|
cogl_color_premultiply (&tmp_color);
|
||||||
cogl_material_set_color(rectangle->border_material, &tmp_color);
|
cogl_material_set_color(rectangle->border_material, &tmp_color);
|
||||||
cogl_set_source(rectangle->border_material);
|
cogl_set_source(rectangle->border_material);
|
||||||
|
|
||||||
/* NORTH */
|
if (radius > 0) { /* skip corners */
|
||||||
cogl_rectangle(max, 0,
|
/* NORTH */
|
||||||
width - max, border_width);
|
cogl_rectangle(max, 0,
|
||||||
|
width - max, border_width);
|
||||||
|
|
||||||
/* EAST */
|
/* EAST */
|
||||||
cogl_rectangle(width - border_width, max,
|
cogl_rectangle(width - border_width, max,
|
||||||
width, height - max);
|
width, height - max);
|
||||||
|
|
||||||
/* SOUTH */
|
/* SOUTH */
|
||||||
cogl_rectangle(max, height - border_width,
|
cogl_rectangle(max, height - border_width,
|
||||||
width - max, height);
|
width - max, height);
|
||||||
|
|
||||||
/* WEST */
|
/* WEST */
|
||||||
cogl_rectangle(0, max,
|
cogl_rectangle(0, max,
|
||||||
border_width, height - max);
|
border_width, height - max);
|
||||||
|
} else { /* include corners */
|
||||||
|
/* NORTH */
|
||||||
|
cogl_rectangle(0, 0,
|
||||||
|
width, border_width);
|
||||||
|
|
||||||
|
/* EAST */
|
||||||
|
cogl_rectangle(width - border_width, border_width,
|
||||||
|
width, height - border_width);
|
||||||
|
|
||||||
|
/* SOUTH */
|
||||||
|
cogl_rectangle(0, height - border_width,
|
||||||
|
width, height);
|
||||||
|
|
||||||
|
/* WEST */
|
||||||
|
cogl_rectangle(0, border_width,
|
||||||
|
border_width, height - border_width);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rectangle->background_material)
|
if (!rectangle->background_material)
|
||||||
@@ -455,6 +531,7 @@ big_rectangle_paint(ClutterActor *actor)
|
|||||||
cogl_rectangle(border_width, max,
|
cogl_rectangle(border_width, max,
|
||||||
width - border_width, height - max);
|
width - border_width, height - max);
|
||||||
|
|
||||||
|
out:
|
||||||
clutter_color_free(border_color);
|
clutter_color_free(border_color);
|
||||||
clutter_color_free(color);
|
clutter_color_free(color);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -192,13 +192,6 @@ gnome_shell_plugin_constructed (GObject *object)
|
|||||||
shell_plugin->gjs_context = gjs_context_new_with_search_path(search_path);
|
shell_plugin->gjs_context = gjs_context_new_with_search_path(search_path);
|
||||||
g_strfreev(search_path);
|
g_strfreev(search_path);
|
||||||
|
|
||||||
shell_plugin->panel_action = XInternAtom (meta_display_get_xdisplay (display),
|
|
||||||
"_GNOME_PANEL_ACTION", FALSE);
|
|
||||||
shell_plugin->panel_action_run_dialog = XInternAtom (meta_display_get_xdisplay (display),
|
|
||||||
"_GNOME_PANEL_ACTION_RUN_DIALOG", FALSE);
|
|
||||||
shell_plugin->panel_action_main_menu = XInternAtom (meta_display_get_xdisplay (display),
|
|
||||||
"_GNOME_PANEL_ACTION_MAIN_MENU", FALSE);
|
|
||||||
|
|
||||||
if (!gjs_context_eval (shell_plugin->gjs_context,
|
if (!gjs_context_eval (shell_plugin->gjs_context,
|
||||||
"const Main = imports.ui.main; Main.start();",
|
"const Main = imports.ui.main; Main.start();",
|
||||||
-1,
|
-1,
|
||||||
@@ -318,48 +311,10 @@ gnome_shell_plugin_kill_effect (MutterPlugin *plugin,
|
|||||||
actor, events);
|
actor, events);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
|
||||||
handle_panel_event (GnomeShellPlugin *shell_plugin,
|
|
||||||
XEvent *xev)
|
|
||||||
{
|
|
||||||
MutterPlugin *plugin = MUTTER_PLUGIN (shell_plugin);
|
|
||||||
MetaScreen *screen;
|
|
||||||
MetaDisplay *display;
|
|
||||||
XClientMessageEvent *xev_client;
|
|
||||||
Window root;
|
|
||||||
|
|
||||||
screen = mutter_plugin_get_screen (plugin);
|
|
||||||
display = meta_screen_get_display (screen);
|
|
||||||
|
|
||||||
if (xev->type != ClientMessage)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
root = meta_screen_get_xroot (screen);
|
|
||||||
|
|
||||||
xev_client = (XClientMessageEvent*) xev;
|
|
||||||
if (!(xev_client->window == root &&
|
|
||||||
xev_client->message_type == shell_plugin->panel_action &&
|
|
||||||
xev_client->format == 32))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
if (xev_client->data.l[0] == shell_plugin->panel_action_run_dialog)
|
|
||||||
g_signal_emit_by_name (shell_global_get (), "panel-run-dialog",
|
|
||||||
(guint32) xev_client->data.l[1]);
|
|
||||||
else if (xev_client->data.l[0] == shell_plugin->panel_action_main_menu)
|
|
||||||
g_signal_emit_by_name (shell_global_get (), "panel-main-menu",
|
|
||||||
(guint32) xev_client->data.l[1]);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gnome_shell_plugin_xevent_filter (MutterPlugin *plugin,
|
gnome_shell_plugin_xevent_filter (MutterPlugin *plugin,
|
||||||
XEvent *xev)
|
XEvent *xev)
|
||||||
{
|
{
|
||||||
GnomeShellPlugin *shell_plugin = GNOME_SHELL_PLUGIN (plugin);
|
|
||||||
|
|
||||||
if (handle_panel_event (shell_plugin, xev))
|
|
||||||
return TRUE;
|
|
||||||
return clutter_x11_handle_event (xev) != CLUTTER_X11_FILTER_CONTINUE;
|
return clutter_x11_handle_event (xev) != CLUTTER_X11_FILTER_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/python
|
#!@PYTHON@
|
||||||
|
|
||||||
import atexit
|
import atexit
|
||||||
import optparse
|
import optparse
|
||||||
@@ -253,6 +253,7 @@ if options.debug:
|
|||||||
normal_exit = False
|
normal_exit = False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
shell = None
|
||||||
if options.xephyr:
|
if options.xephyr:
|
||||||
xephyr = start_xephyr()
|
xephyr = start_xephyr()
|
||||||
# This makes us not grab the org.gnome.Panel name
|
# This makes us not grab the org.gnome.Panel name
|
||||||
@@ -281,7 +282,9 @@ finally:
|
|||||||
except OSError:
|
except OSError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if shell.returncode == 0:
|
if shell is None:
|
||||||
|
print "Failed to start shell"
|
||||||
|
elif shell.returncode == 0:
|
||||||
normal_exit = True
|
normal_exit = True
|
||||||
if options.verbose:
|
if options.verbose:
|
||||||
print "Shell exited normally"
|
print "Shell exited normally"
|
||||||
|
|||||||
@@ -1,64 +0,0 @@
|
|||||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
||||||
|
|
||||||
#include <mutter-plugin.h>
|
|
||||||
|
|
||||||
ClutterActor *
|
|
||||||
mutter_plugin_get_overlay_group (MutterPlugin *plugin)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ClutterActor *
|
|
||||||
mutter_plugin_get_stage (MutterPlugin *plugin)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
GList *
|
|
||||||
mutter_plugin_get_windows (MutterPlugin *plugin)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
mutter_plugin_query_screen_size (MutterPlugin *plugin,
|
|
||||||
int *width,
|
|
||||||
int *height)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
mutter_plugin_set_stage_input_area (MutterPlugin *plugin,
|
|
||||||
gint x, gint y, gint width, gint height)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
MetaScreen *
|
|
||||||
mutter_plugin_get_screen (MutterPlugin *plugin)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ClutterActor *
|
|
||||||
mutter_plugin_get_window_group (MutterPlugin *plugin)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
Display *
|
|
||||||
meta_display_get_xdisplay (MetaDisplay *display)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
MetaDisplay *
|
|
||||||
meta_screen_get_display (MetaScreen *display)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
Window
|
|
||||||
meta_screen_get_xroot (MetaScreen *display)
|
|
||||||
{
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
@@ -1,236 +0,0 @@
|
|||||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
||||||
|
|
||||||
#include "shell-alttab.h"
|
|
||||||
#include "shell-global.h"
|
|
||||||
#include "shell-wm.h"
|
|
||||||
#include <mutter-plugin.h>
|
|
||||||
|
|
||||||
/* Our MetaAltTabHandler implementation; ideally we would implement
|
|
||||||
* this directly from JavaScript, but for now we can't. So we register
|
|
||||||
* this glue class as our MetaAltTabHandler and then when mutter
|
|
||||||
* creates one, we pass it on to ShellWM, which emits a signal to hand
|
|
||||||
* it off to javascript code, which then connects to the signals on
|
|
||||||
* this object.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void shell_alt_tab_handler_interface_init (MetaAltTabHandlerInterface *handler_iface);
|
|
||||||
|
|
||||||
G_DEFINE_TYPE_WITH_CODE (ShellAltTabHandler, shell_alt_tab_handler, G_TYPE_OBJECT,
|
|
||||||
G_IMPLEMENT_INTERFACE (META_TYPE_ALT_TAB_HANDLER,
|
|
||||||
shell_alt_tab_handler_interface_init))
|
|
||||||
|
|
||||||
/* Signals */
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
WINDOW_ADDED,
|
|
||||||
SHOW,
|
|
||||||
DESTROY,
|
|
||||||
|
|
||||||
LAST_SIGNAL
|
|
||||||
};
|
|
||||||
static guint signals [LAST_SIGNAL] = { 0 };
|
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
PROP_SELECTED = 1,
|
|
||||||
PROP_SCREEN,
|
|
||||||
PROP_IMMEDIATE
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
shell_alt_tab_handler_init (ShellAltTabHandler *sth)
|
|
||||||
{
|
|
||||||
sth->windows = g_ptr_array_new ();
|
|
||||||
sth->selected = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
shell_alt_tab_handler_constructed (GObject *object)
|
|
||||||
{
|
|
||||||
ShellGlobal *global = shell_global_get ();
|
|
||||||
ShellWM *wm;
|
|
||||||
|
|
||||||
g_object_get (G_OBJECT (global), "window-manager", &wm, NULL);
|
|
||||||
_shell_wm_begin_alt_tab (wm, SHELL_ALT_TAB_HANDLER (object));
|
|
||||||
g_object_unref (wm);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
shell_alt_tab_handler_set_property (GObject *object,
|
|
||||||
guint prop_id,
|
|
||||||
const GValue *value,
|
|
||||||
GParamSpec *pspec)
|
|
||||||
{
|
|
||||||
ShellAltTabHandler *sth = SHELL_ALT_TAB_HANDLER (object);
|
|
||||||
|
|
||||||
switch (prop_id)
|
|
||||||
{
|
|
||||||
case PROP_SCREEN:
|
|
||||||
/* We don't care */
|
|
||||||
break;
|
|
||||||
case PROP_IMMEDIATE:
|
|
||||||
sth->immediate_mode = g_value_get_boolean (value);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
shell_alt_tab_handler_get_property (GObject *object,
|
|
||||||
guint prop_id,
|
|
||||||
GValue *value,
|
|
||||||
GParamSpec *pspec)
|
|
||||||
{
|
|
||||||
ShellAltTabHandler *sth = SHELL_ALT_TAB_HANDLER (object);
|
|
||||||
|
|
||||||
switch (prop_id)
|
|
||||||
{
|
|
||||||
case PROP_SELECTED:
|
|
||||||
g_value_set_int (value, sth->selected);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
shell_alt_tab_handler_finalize (GObject *object)
|
|
||||||
{
|
|
||||||
ShellAltTabHandler *sth = SHELL_ALT_TAB_HANDLER (object);
|
|
||||||
|
|
||||||
g_ptr_array_free (sth->windows, FALSE);
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (shell_alt_tab_handler_parent_class)->finalize (object);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
shell_alt_tab_handler_add_window (MetaAltTabHandler *handler,
|
|
||||||
MetaWindow *window)
|
|
||||||
{
|
|
||||||
ShellAltTabHandler *sth = SHELL_ALT_TAB_HANDLER (handler);
|
|
||||||
|
|
||||||
g_ptr_array_add (sth->windows, window);
|
|
||||||
g_signal_emit (handler, signals[WINDOW_ADDED], 0,
|
|
||||||
meta_window_get_compositor_private (window));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
shell_alt_tab_handler_show (MetaAltTabHandler *handler,
|
|
||||||
MetaWindow *initial_selection)
|
|
||||||
{
|
|
||||||
ShellAltTabHandler *sth = SHELL_ALT_TAB_HANDLER (handler);
|
|
||||||
int i;
|
|
||||||
|
|
||||||
sth->selected = -1;
|
|
||||||
for (i = 0; i < sth->windows->len; i++)
|
|
||||||
{
|
|
||||||
if (sth->windows->pdata[i] == (gpointer)initial_selection)
|
|
||||||
{
|
|
||||||
sth->selected = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
g_signal_emit (handler, signals[SHOW], 0, sth->selected);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
shell_alt_tab_handler_destroy (MetaAltTabHandler *handler)
|
|
||||||
{
|
|
||||||
g_signal_emit (handler, signals[DESTROY], 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
shell_alt_tab_handler_forward (MetaAltTabHandler *handler)
|
|
||||||
{
|
|
||||||
ShellAltTabHandler *sth = SHELL_ALT_TAB_HANDLER (handler);
|
|
||||||
|
|
||||||
if (sth->selected == sth->windows->len - 1)
|
|
||||||
sth->selected = 0;
|
|
||||||
else
|
|
||||||
sth->selected++;
|
|
||||||
g_object_notify (G_OBJECT (handler), "selected");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
shell_alt_tab_handler_backward (MetaAltTabHandler *handler)
|
|
||||||
{
|
|
||||||
ShellAltTabHandler *sth = SHELL_ALT_TAB_HANDLER (handler);
|
|
||||||
|
|
||||||
if (sth->selected == 0)
|
|
||||||
sth->selected = sth->windows->len - 1;
|
|
||||||
else
|
|
||||||
sth->selected--;
|
|
||||||
g_object_notify (G_OBJECT (handler), "selected");
|
|
||||||
}
|
|
||||||
|
|
||||||
static MetaWindow *
|
|
||||||
shell_alt_tab_handler_get_selected (MetaAltTabHandler *handler)
|
|
||||||
{
|
|
||||||
ShellAltTabHandler *sth = SHELL_ALT_TAB_HANDLER (handler);
|
|
||||||
|
|
||||||
if (sth->selected > -1)
|
|
||||||
return sth->windows->pdata[sth->selected];
|
|
||||||
else
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
shell_alt_tab_handler_class_init (ShellAltTabHandlerClass *klass)
|
|
||||||
{
|
|
||||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
||||||
|
|
||||||
object_class->constructed = shell_alt_tab_handler_constructed;
|
|
||||||
object_class->set_property = shell_alt_tab_handler_set_property;
|
|
||||||
object_class->get_property = shell_alt_tab_handler_get_property;
|
|
||||||
object_class->finalize = shell_alt_tab_handler_finalize;
|
|
||||||
|
|
||||||
g_object_class_override_property (object_class, PROP_SCREEN, "screen");
|
|
||||||
g_object_class_override_property (object_class, PROP_IMMEDIATE, "immediate");
|
|
||||||
g_object_class_install_property (object_class,
|
|
||||||
PROP_SELECTED,
|
|
||||||
g_param_spec_int ("selected",
|
|
||||||
"Selected",
|
|
||||||
"Selected window",
|
|
||||||
-1, G_MAXINT, -1,
|
|
||||||
G_PARAM_READABLE));
|
|
||||||
|
|
||||||
|
|
||||||
signals[WINDOW_ADDED] = g_signal_new ("window-added",
|
|
||||||
G_TYPE_FROM_CLASS (klass),
|
|
||||||
G_SIGNAL_RUN_LAST,
|
|
||||||
0,
|
|
||||||
NULL, NULL,
|
|
||||||
g_cclosure_marshal_VOID__OBJECT,
|
|
||||||
G_TYPE_NONE, 1,
|
|
||||||
MUTTER_TYPE_COMP_WINDOW);
|
|
||||||
signals[SHOW] = g_signal_new ("show",
|
|
||||||
G_TYPE_FROM_CLASS (klass),
|
|
||||||
G_SIGNAL_RUN_LAST,
|
|
||||||
0,
|
|
||||||
NULL, NULL,
|
|
||||||
g_cclosure_marshal_VOID__INT,
|
|
||||||
G_TYPE_NONE, 1,
|
|
||||||
G_TYPE_INT);
|
|
||||||
signals[DESTROY] = g_signal_new ("destroy",
|
|
||||||
G_TYPE_FROM_CLASS (klass),
|
|
||||||
G_SIGNAL_RUN_LAST,
|
|
||||||
0,
|
|
||||||
NULL, NULL,
|
|
||||||
g_cclosure_marshal_VOID__VOID,
|
|
||||||
G_TYPE_NONE, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
shell_alt_tab_handler_interface_init (MetaAltTabHandlerInterface *handler_iface)
|
|
||||||
{
|
|
||||||
handler_iface->add_window = shell_alt_tab_handler_add_window;
|
|
||||||
handler_iface->show = shell_alt_tab_handler_show;
|
|
||||||
handler_iface->destroy = shell_alt_tab_handler_destroy;
|
|
||||||
handler_iface->forward = shell_alt_tab_handler_forward;
|
|
||||||
handler_iface->backward = shell_alt_tab_handler_backward;
|
|
||||||
handler_iface->get_selected = shell_alt_tab_handler_get_selected;
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
||||||
|
|
||||||
#ifndef SHELL_ALT_TAB_HANDLER_H
|
|
||||||
#define SHELL_ALT_TAB_HANDLER_H
|
|
||||||
|
|
||||||
#include <alttabhandler.h>
|
|
||||||
|
|
||||||
#define SHELL_TYPE_ALT_TAB_HANDLER (shell_alt_tab_handler_get_type ())
|
|
||||||
#define SHELL_ALT_TAB_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SHELL_TYPE_ALT_TAB_HANDLER, ShellAltTabHandler))
|
|
||||||
#define SHELL_ALT_TAB_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SHELL_TYPE_ALT_TAB_HANDLER, ShellAltTabHandlerClass))
|
|
||||||
#define SHELL_IS_ALT_TAB_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SHELL_ALT_TAB_HANDLER_TYPE))
|
|
||||||
#define SHELL_IS_ALT_TAB_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SHELL_TYPE_ALT_TAB_HANDLER))
|
|
||||||
#define SHELL_ALT_TAB_HANDLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SHELL_TYPE_ALT_TAB_HANDLER, ShellAltTabHandlerClass))
|
|
||||||
|
|
||||||
typedef struct _ShellAltTabHandler ShellAltTabHandler;
|
|
||||||
typedef struct _ShellAltTabHandlerClass ShellAltTabHandlerClass;
|
|
||||||
|
|
||||||
struct _ShellAltTabHandler {
|
|
||||||
GObject parent_instance;
|
|
||||||
|
|
||||||
GPtrArray *windows;
|
|
||||||
int selected;
|
|
||||||
gboolean immediate_mode;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _ShellAltTabHandlerClass {
|
|
||||||
GObjectClass parent_class;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
GType shell_alt_tab_handler_get_type (void);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -345,7 +345,7 @@ window_is_tracked (MetaWindow *window)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* window_is_usage_tracked:
|
* shell_app_monitor_is_window_usage_tracked:
|
||||||
*
|
*
|
||||||
* Determine if it makes sense to track the given window for application
|
* Determine if it makes sense to track the given window for application
|
||||||
* usage. An example of a window we don't want to track is the root
|
* usage. An example of a window we don't want to track is the root
|
||||||
@@ -358,12 +358,15 @@ window_is_tracked (MetaWindow *window)
|
|||||||
*
|
*
|
||||||
* Returns: %TRUE iff we want to record focus time spent in this window
|
* Returns: %TRUE iff we want to record focus time spent in this window
|
||||||
*/
|
*/
|
||||||
static gboolean
|
gboolean
|
||||||
window_is_usage_tracked (MetaWindow *window)
|
shell_app_monitor_is_window_usage_tracked (MetaWindow *window)
|
||||||
{
|
{
|
||||||
if (!window_is_tracked (window))
|
if (!window_is_tracked (window))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
if (meta_window_is_skip_taskbar (window))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
switch (meta_window_get_window_type (window))
|
switch (meta_window_get_window_type (window))
|
||||||
{
|
{
|
||||||
/* Definitely ignore these. */
|
/* Definitely ignore these. */
|
||||||
@@ -434,9 +437,10 @@ get_app_for_window_direct (MetaWindow *window)
|
|||||||
|
|
||||||
if (id != NULL)
|
if (id != NULL)
|
||||||
result = shell_app_system_load_from_desktop_file (appsys, id, NULL);
|
result = shell_app_system_load_from_desktop_file (appsys, id, NULL);
|
||||||
else
|
|
||||||
result = create_transient_app_for_window (window);
|
|
||||||
}
|
}
|
||||||
|
if (result == NULL)
|
||||||
|
result = create_transient_app_for_window (window);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -562,7 +566,7 @@ get_active_window (ShellAppMonitor *monitor)
|
|||||||
display = meta_screen_get_display (screen);
|
display = meta_screen_get_display (screen);
|
||||||
window = meta_display_get_focus_window (display);
|
window = meta_display_get_focus_window (display);
|
||||||
|
|
||||||
if (window != NULL && window_is_usage_tracked (window))
|
if (window != NULL && shell_app_monitor_is_window_usage_tracked (window))
|
||||||
return window;
|
return window;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -756,7 +760,7 @@ track_window (ShellAppMonitor *self,
|
|||||||
* tracked it doesn't count for the purposes of an application
|
* tracked it doesn't count for the purposes of an application
|
||||||
* running.
|
* running.
|
||||||
*/
|
*/
|
||||||
if (!window_is_usage_tracked (window))
|
if (!shell_app_monitor_is_window_usage_tracked (window))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
usage = get_app_usage_from_window (self, window);
|
usage = get_app_usage_from_window (self, window);
|
||||||
@@ -812,7 +816,7 @@ disassociate_window (ShellAppMonitor *self,
|
|||||||
if (window == self->watched_window)
|
if (window == self->watched_window)
|
||||||
self->watched_window = NULL;
|
self->watched_window = NULL;
|
||||||
|
|
||||||
if (window_is_usage_tracked (window))
|
if (shell_app_monitor_is_window_usage_tracked (window))
|
||||||
{
|
{
|
||||||
AppUsage *usage;
|
AppUsage *usage;
|
||||||
const char *context;
|
const char *context;
|
||||||
@@ -930,7 +934,7 @@ shell_app_monitor_get_windows_for_app (ShellAppMonitor *self,
|
|||||||
ShellAppInfo *app = value;
|
ShellAppInfo *app = value;
|
||||||
const char *id = shell_app_info_get_id (app);
|
const char *id = shell_app_info_get_id (app);
|
||||||
|
|
||||||
if (!window_is_usage_tracked (window))
|
if (!shell_app_monitor_is_window_usage_tracked (window))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (strcmp (id, appid) != 0)
|
if (strcmp (id, appid) != 0)
|
||||||
@@ -1035,6 +1039,7 @@ shell_app_monitor_init (ShellAppMonitor *self)
|
|||||||
path = g_build_filename (shell_config_dir, DATA_FILENAME, NULL);
|
path = g_build_filename (shell_config_dir, DATA_FILENAME, NULL);
|
||||||
g_free (shell_config_dir);
|
g_free (shell_config_dir);
|
||||||
self->configfile = g_file_new_for_path (path);
|
self->configfile = g_file_new_for_path (path);
|
||||||
|
g_free (path);
|
||||||
restore_from_file (self);
|
restore_from_file (self);
|
||||||
|
|
||||||
load_initial_windows (self);
|
load_initial_windows (self);
|
||||||
@@ -1181,7 +1186,7 @@ shell_app_monitor_get_running_apps (ShellAppMonitor *monitor,
|
|||||||
if (strcmp (get_window_context (window), context) != 0)
|
if (strcmp (get_window_context (window), context) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!window_is_usage_tracked (window))
|
if (!shell_app_monitor_is_window_usage_tracked (window))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
id = shell_app_info_get_id (app);
|
id = shell_app_info_get_id (app);
|
||||||
|
|||||||
@@ -44,6 +44,8 @@ GList *shell_app_monitor_get_most_used_apps (ShellAppMonitor *monitor,
|
|||||||
|
|
||||||
GSList *shell_app_monitor_get_windows_for_app (ShellAppMonitor *monitor, const char *appid);
|
GSList *shell_app_monitor_get_windows_for_app (ShellAppMonitor *monitor, const char *appid);
|
||||||
|
|
||||||
|
gboolean shell_app_monitor_is_window_usage_tracked (MetaWindow *window);
|
||||||
|
|
||||||
/* Get whatever's running right now */
|
/* Get whatever's running right now */
|
||||||
GSList *shell_app_monitor_get_running_apps (ShellAppMonitor *monitor, const char *context);
|
GSList *shell_app_monitor_get_running_apps (ShellAppMonitor *monitor, const char *context);
|
||||||
|
|
||||||
|
|||||||
@@ -52,10 +52,13 @@ struct _ShellAppSystemPrivate {
|
|||||||
GList *cached_favorites; /* utf8 */
|
GList *cached_favorites; /* utf8 */
|
||||||
|
|
||||||
gint app_monitor_id;
|
gint app_monitor_id;
|
||||||
|
|
||||||
|
guint app_change_timeout_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void shell_app_system_finalize (GObject *object);
|
static void shell_app_system_finalize (GObject *object);
|
||||||
static void on_tree_changed (GMenuTree *tree, gpointer user_data);
|
static gboolean on_tree_changed (gpointer user_data);
|
||||||
|
static void on_tree_changed_cb (GMenuTree *tree, gpointer user_data);
|
||||||
static void reread_menus (ShellAppSystem *self);
|
static void reread_menus (ShellAppSystem *self);
|
||||||
static void on_favorite_apps_changed (GConfClient *client, guint id, GConfEntry *entry, gpointer user_data);
|
static void on_favorite_apps_changed (GConfClient *client, guint id, GConfEntry *entry, gpointer user_data);
|
||||||
static void reread_favorite_apps (ShellAppSystem *system);
|
static void reread_favorite_apps (ShellAppSystem *system);
|
||||||
@@ -233,8 +236,10 @@ shell_app_system_init (ShellAppSystem *self)
|
|||||||
priv->apps_tree = gmenu_tree_lookup ("applications.menu", GMENU_TREE_FLAGS_INCLUDE_NODISPLAY);
|
priv->apps_tree = gmenu_tree_lookup ("applications.menu", GMENU_TREE_FLAGS_INCLUDE_NODISPLAY);
|
||||||
priv->settings_tree = gmenu_tree_lookup ("settings.menu", GMENU_TREE_FLAGS_NONE);
|
priv->settings_tree = gmenu_tree_lookup ("settings.menu", GMENU_TREE_FLAGS_NONE);
|
||||||
|
|
||||||
gmenu_tree_add_monitor (priv->apps_tree, on_tree_changed, self);
|
priv->app_change_timeout_id = 0;
|
||||||
gmenu_tree_add_monitor (priv->settings_tree, on_tree_changed, self);
|
|
||||||
|
gmenu_tree_add_monitor (priv->apps_tree, on_tree_changed_cb, self);
|
||||||
|
gmenu_tree_add_monitor (priv->settings_tree, on_tree_changed_cb, self);
|
||||||
|
|
||||||
reread_menus (self);
|
reread_menus (self);
|
||||||
|
|
||||||
@@ -251,8 +256,8 @@ shell_app_system_finalize (GObject *object)
|
|||||||
ShellAppSystem *self = SHELL_APP_SYSTEM (object);
|
ShellAppSystem *self = SHELL_APP_SYSTEM (object);
|
||||||
ShellAppSystemPrivate *priv = self->priv;
|
ShellAppSystemPrivate *priv = self->priv;
|
||||||
|
|
||||||
gmenu_tree_remove_monitor (priv->apps_tree, on_tree_changed, self);
|
gmenu_tree_remove_monitor (priv->apps_tree, on_tree_changed_cb, self);
|
||||||
gmenu_tree_remove_monitor (priv->settings_tree, on_tree_changed, self);
|
gmenu_tree_remove_monitor (priv->settings_tree, on_tree_changed_cb, self);
|
||||||
|
|
||||||
gmenu_tree_unref (priv->apps_tree);
|
gmenu_tree_unref (priv->apps_tree);
|
||||||
gmenu_tree_unref (priv->settings_tree);
|
gmenu_tree_unref (priv->settings_tree);
|
||||||
@@ -410,14 +415,39 @@ reread_menus (ShellAppSystem *self)
|
|||||||
cache_by_id (self, self->priv->cached_settings, TRUE);
|
cache_by_id (self, self->priv->cached_settings, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
on_tree_changed (gpointer user_data)
|
||||||
|
{
|
||||||
|
ShellAppSystem *self = SHELL_APP_SYSTEM (user_data);
|
||||||
|
g_signal_emit (self, signals[INSTALLED_CHANGED], 0);
|
||||||
|
reread_menus (self);
|
||||||
|
self->priv->app_change_timeout_id = 0;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_tree_changed (GMenuTree *monitor, gpointer user_data)
|
on_tree_changed_cb (GMenuTree *monitor, gpointer user_data)
|
||||||
{
|
{
|
||||||
ShellAppSystem *self = SHELL_APP_SYSTEM (user_data);
|
ShellAppSystem *self = SHELL_APP_SYSTEM (user_data);
|
||||||
|
|
||||||
g_signal_emit (self, signals[INSTALLED_CHANGED], 0);
|
/* GMenu currently gives us a separate notification on the entire
|
||||||
|
* menu tree for each node in the tree that might potentially have
|
||||||
|
* changed. (See http://bugzilla.gnome.org/show_bug.cgi?id=172046.)
|
||||||
|
* We need to compress these to avoid doing large extra amounts of
|
||||||
|
* work.
|
||||||
|
*
|
||||||
|
* Even when that bug is fixed, compression is still useful; for one
|
||||||
|
* thing we want to need to compress across notifications of changes
|
||||||
|
* to the settings tree. Second we want to compress if multiple
|
||||||
|
* changes are made to the desktop files at different times but in
|
||||||
|
* short succession.
|
||||||
|
*/
|
||||||
|
|
||||||
reread_menus (self);
|
if (self->priv->app_change_timeout_id != 0)
|
||||||
|
return;
|
||||||
|
self->priv->app_change_timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT_IDLE, 3000,
|
||||||
|
(GSourceFunc) on_tree_changed,
|
||||||
|
self, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GList *
|
static GList *
|
||||||
@@ -509,7 +539,7 @@ shell_app_menu_entry_get_type (void)
|
|||||||
* Traverses a toplevel menu, and returns all items under it. Nested items
|
* Traverses a toplevel menu, and returns all items under it. Nested items
|
||||||
* are flattened.
|
* are flattened.
|
||||||
*
|
*
|
||||||
* Return value: (transfer container) (element-type ShellAppInfo): List of applications
|
* Return value: (transfer full) (element-type ShellAppInfo): List of applications
|
||||||
*/
|
*/
|
||||||
GSList *
|
GSList *
|
||||||
shell_app_system_get_applications_for_menu (ShellAppSystem *monitor,
|
shell_app_system_get_applications_for_menu (ShellAppSystem *monitor,
|
||||||
@@ -954,14 +984,18 @@ shell_app_info_create_icon_texture (ShellAppInfo *info, float size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
icon = shell_app_info_get_icon (info);
|
icon = shell_app_info_get_icon (info);
|
||||||
if (!icon)
|
if (icon == NULL)
|
||||||
{
|
{
|
||||||
ret = clutter_texture_new ();
|
ret = clutter_texture_new ();
|
||||||
g_object_set (ret, "opacity", 0, "width", size, "height", size, NULL);
|
g_object_set (ret, "opacity", 0, "width", size, "height", size, NULL);
|
||||||
return ret;
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = shell_texture_cache_load_gicon (shell_texture_cache_get_default (), icon, (int)size);
|
||||||
|
g_object_unref (icon);
|
||||||
}
|
}
|
||||||
|
|
||||||
return shell_texture_cache_load_gicon (shell_texture_cache_get_default (), icon, (int)size);
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
G_DEFINE_TYPE(ShellButtonBox, shell_button_box, BIG_TYPE_BOX);
|
G_DEFINE_TYPE(ShellButtonBox, shell_button_box, BIG_TYPE_BOX);
|
||||||
|
|
||||||
struct _ShellButtonBoxPrivate {
|
struct _ShellButtonBoxPrivate {
|
||||||
|
gboolean active;
|
||||||
gboolean held;
|
gboolean held;
|
||||||
gboolean hover;
|
gboolean hover;
|
||||||
gboolean pressed;
|
gboolean pressed;
|
||||||
@@ -29,12 +30,23 @@ enum
|
|||||||
enum {
|
enum {
|
||||||
PROP_0,
|
PROP_0,
|
||||||
|
|
||||||
|
PROP_ACTIVE,
|
||||||
PROP_HOVER,
|
PROP_HOVER,
|
||||||
PROP_PRESSED,
|
PROP_PRESSED,
|
||||||
};
|
};
|
||||||
|
|
||||||
static guint shell_button_box_signals [LAST_SIGNAL] = { 0 };
|
static guint shell_button_box_signals [LAST_SIGNAL] = { 0 };
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_active (ShellButtonBox *box,
|
||||||
|
gboolean active)
|
||||||
|
{
|
||||||
|
if (box->priv->active == active)
|
||||||
|
return;
|
||||||
|
box->priv->active = active;
|
||||||
|
g_object_notify (G_OBJECT (box), "active");
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
set_hover (ShellButtonBox *box,
|
set_hover (ShellButtonBox *box,
|
||||||
gboolean hover)
|
gboolean hover)
|
||||||
@@ -67,28 +79,34 @@ shell_button_box_contains (ShellButtonBox *box,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
shell_button_box_on_enter (ShellButtonBox *box,
|
shell_button_box_enter_event (ClutterActor *actor,
|
||||||
ClutterEvent *event,
|
ClutterCrossingEvent *event)
|
||||||
gpointer user_data)
|
|
||||||
{
|
{
|
||||||
if (shell_button_box_contains (box, event->crossing.related))
|
ShellButtonBox *box = SHELL_BUTTON_BOX (actor);
|
||||||
|
|
||||||
|
if (shell_button_box_contains (box, event->related))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
if (!shell_button_box_contains (box, clutter_event_get_source (event)))
|
if (!shell_button_box_contains (box, event->source))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
set_hover (box, TRUE);
|
g_object_freeze_notify (G_OBJECT (actor));
|
||||||
|
|
||||||
if (box->priv->held)
|
if (box->priv->held)
|
||||||
set_pressed (box, TRUE);
|
set_pressed (box, TRUE);
|
||||||
|
set_hover (box, TRUE);
|
||||||
|
|
||||||
|
g_object_thaw_notify (G_OBJECT (actor));
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
shell_button_box_on_leave (ShellButtonBox *box,
|
shell_button_box_leave_event (ClutterActor *actor,
|
||||||
ClutterEvent *event,
|
ClutterCrossingEvent *event)
|
||||||
gpointer user_data)
|
|
||||||
{
|
{
|
||||||
if (shell_button_box_contains (box, event->crossing.related))
|
ShellButtonBox *box = SHELL_BUTTON_BOX (actor);
|
||||||
|
|
||||||
|
if (shell_button_box_contains (box, event->related))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
set_hover (box, FALSE);
|
set_hover (box, FALSE);
|
||||||
@@ -98,17 +116,18 @@ shell_button_box_on_leave (ShellButtonBox *box,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
shell_button_box_on_press (ShellButtonBox *box,
|
shell_button_box_button_press_event (ClutterActor *actor,
|
||||||
ClutterEvent *event,
|
ClutterButtonEvent *event)
|
||||||
gpointer user_data)
|
|
||||||
{
|
{
|
||||||
ClutterActor *source;
|
ShellButtonBox *box = SHELL_BUTTON_BOX (actor);
|
||||||
|
|
||||||
|
if (event->button != 1 || event->click_count != 1)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
if (box->priv->held)
|
if (box->priv->held)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
source = clutter_event_get_source (event);
|
if (!shell_button_box_contains (box, event->source))
|
||||||
if (!shell_button_box_contains (box, source))
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
box->priv->held = TRUE;
|
box->priv->held = TRUE;
|
||||||
@@ -120,38 +139,68 @@ shell_button_box_on_press (ShellButtonBox *box,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
shell_button_box_on_release (ShellButtonBox *box,
|
shell_button_box_button_release_event (ClutterActor *actor,
|
||||||
ClutterEvent *event,
|
ClutterButtonEvent *event)
|
||||||
gpointer user_data)
|
|
||||||
{
|
{
|
||||||
ClutterActor *source;
|
ShellButtonBox *box = SHELL_BUTTON_BOX (actor);
|
||||||
|
|
||||||
|
if (event->button != 1 || event->click_count != 1)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
if (!box->priv->held)
|
if (!box->priv->held)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
source = clutter_event_get_source (event);
|
|
||||||
|
|
||||||
box->priv->held = FALSE;
|
box->priv->held = FALSE;
|
||||||
clutter_ungrab_pointer ();
|
clutter_ungrab_pointer ();
|
||||||
|
|
||||||
if (!shell_button_box_contains (box, source))
|
if (!shell_button_box_contains (box, event->source))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
set_pressed (box, FALSE);
|
set_pressed (box, FALSE);
|
||||||
|
|
||||||
g_signal_emit (G_OBJECT (box), shell_button_box_signals[ACTIVATE], 0);
|
g_signal_emit (G_OBJECT (box), shell_button_box_signals[ACTIVATE], 0, event);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* shell_button_box_fake_release:
|
||||||
|
* @box:
|
||||||
|
*
|
||||||
|
* If this button box is holding a pointer grab, this function will
|
||||||
|
* will ungrab it, and reset the pressed state. The effect is
|
||||||
|
* similar to if the user had released the mouse button, but without
|
||||||
|
* emitting the activate signal.
|
||||||
|
*
|
||||||
|
* This function is useful if for example you want to do something after the user
|
||||||
|
* is holding the mouse button for a given period of time, breaking the
|
||||||
|
* grab.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
shell_button_box_fake_release (ShellButtonBox *box)
|
||||||
|
{
|
||||||
|
if (!box->priv->held)
|
||||||
|
return;
|
||||||
|
|
||||||
|
box->priv->held = FALSE;
|
||||||
|
clutter_ungrab_pointer ();
|
||||||
|
|
||||||
|
set_pressed (box, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
shell_button_box_set_property(GObject *object,
|
shell_button_box_set_property(GObject *object,
|
||||||
guint prop_id,
|
guint prop_id,
|
||||||
const GValue *value,
|
const GValue *value,
|
||||||
GParamSpec *pspec)
|
GParamSpec *pspec)
|
||||||
{
|
{
|
||||||
|
ShellButtonBox *box = SHELL_BUTTON_BOX (object);
|
||||||
|
|
||||||
switch (prop_id)
|
switch (prop_id)
|
||||||
{
|
{
|
||||||
|
case PROP_ACTIVE:
|
||||||
|
set_active (box, g_value_get_boolean (value));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
@@ -168,6 +217,9 @@ shell_button_box_get_property(GObject *object,
|
|||||||
|
|
||||||
switch (prop_id)
|
switch (prop_id)
|
||||||
{
|
{
|
||||||
|
case PROP_ACTIVE:
|
||||||
|
g_value_set_boolean (value, box->priv->active);
|
||||||
|
break;
|
||||||
case PROP_PRESSED:
|
case PROP_PRESSED:
|
||||||
g_value_set_boolean (value, box->priv->pressed);
|
g_value_set_boolean (value, box->priv->pressed);
|
||||||
break;
|
break;
|
||||||
@@ -184,13 +236,20 @@ static void
|
|||||||
shell_button_box_class_init (ShellButtonBoxClass *klass)
|
shell_button_box_class_init (ShellButtonBoxClass *klass)
|
||||||
{
|
{
|
||||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||||
|
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||||
|
|
||||||
gobject_class->get_property = shell_button_box_get_property;
|
gobject_class->get_property = shell_button_box_get_property;
|
||||||
gobject_class->set_property = shell_button_box_set_property;
|
gobject_class->set_property = shell_button_box_set_property;
|
||||||
|
|
||||||
|
actor_class->enter_event = shell_button_box_enter_event;
|
||||||
|
actor_class->leave_event = shell_button_box_leave_event;
|
||||||
|
actor_class->button_press_event = shell_button_box_button_press_event;
|
||||||
|
actor_class->button_release_event = shell_button_box_button_release_event;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ShellButtonBox::activate
|
* ShellButtonBox::activate
|
||||||
* @box: The #ShellButtonBox
|
* @box: The #ShellButtonBox
|
||||||
|
* @event: Release event which triggered the activation
|
||||||
*
|
*
|
||||||
* This signal is emitted when the button should take the action
|
* This signal is emitted when the button should take the action
|
||||||
* associated with button click+release.
|
* associated with button click+release.
|
||||||
@@ -202,7 +261,22 @@ shell_button_box_class_init (ShellButtonBoxClass *klass)
|
|||||||
0,
|
0,
|
||||||
NULL, NULL,
|
NULL, NULL,
|
||||||
g_cclosure_marshal_VOID__VOID,
|
g_cclosure_marshal_VOID__VOID,
|
||||||
G_TYPE_NONE, 0);
|
G_TYPE_NONE, 1, CLUTTER_TYPE_EVENT);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ShellButtonBox:active
|
||||||
|
*
|
||||||
|
* The property allows the button to be used as a "toggle button"; it's up to the
|
||||||
|
* application to update the active property in response to the activate signal;
|
||||||
|
* it doesn't happen automatically.
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_ACTIVE,
|
||||||
|
g_param_spec_boolean ("active",
|
||||||
|
"Active",
|
||||||
|
"Whether the button persistently active",
|
||||||
|
FALSE,
|
||||||
|
G_PARAM_READWRITE));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ShellButtonBox:hover
|
* ShellButtonBox:hover
|
||||||
@@ -240,9 +314,4 @@ shell_button_box_init (ShellButtonBox *self)
|
|||||||
{
|
{
|
||||||
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, SHELL_TYPE_BUTTON_BOX,
|
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, SHELL_TYPE_BUTTON_BOX,
|
||||||
ShellButtonBoxPrivate);
|
ShellButtonBoxPrivate);
|
||||||
|
|
||||||
g_signal_connect (G_OBJECT (self), "enter-event", G_CALLBACK(shell_button_box_on_enter), NULL);
|
|
||||||
g_signal_connect (G_OBJECT (self), "leave-event", G_CALLBACK(shell_button_box_on_leave), NULL);
|
|
||||||
g_signal_connect (G_OBJECT (self), "button-press-event", G_CALLBACK(shell_button_box_on_press), NULL);
|
|
||||||
g_signal_connect (G_OBJECT (self), "button-release-event", G_CALLBACK(shell_button_box_on_release), NULL);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,4 +30,6 @@ struct _ShellButtonBoxClass
|
|||||||
|
|
||||||
GType shell_button_box_get_type (void) G_GNUC_CONST;
|
GType shell_button_box_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
void shell_button_box_fake_release (ShellButtonBox *box);
|
||||||
|
|
||||||
#endif /* __SHELL_BUTTON_BOX_H__ */
|
#endif /* __SHELL_BUTTON_BOX_H__ */
|
||||||
|
|||||||
@@ -146,79 +146,46 @@ shell_draw_clock (ClutterCairoTexture *texture,
|
|||||||
cairo_destroy (cr);
|
cairo_destroy (cr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
draw_glow (cairo_t *cr, double red, double green, double blue, double alpha)
|
|
||||||
{
|
|
||||||
cairo_pattern_t *gradient;
|
|
||||||
|
|
||||||
cairo_save (cr);
|
|
||||||
|
|
||||||
gradient = cairo_pattern_create_radial (0.0, 0.0, 0.0, 0.0, 0.0, 1.0);
|
|
||||||
cairo_pattern_add_color_stop_rgba (gradient, 0.0, red, green, blue, alpha);
|
|
||||||
cairo_pattern_add_color_stop_rgba (gradient, 0.7, red, green, blue, alpha * 0.7);
|
|
||||||
cairo_pattern_add_color_stop_rgba (gradient, 1.0, red, green, blue, alpha * 0.3);
|
|
||||||
cairo_set_source (cr, gradient);
|
|
||||||
|
|
||||||
cairo_arc (cr, 0.0, 0.0, 1.0, 0.0, 2.0 * M_PI);
|
|
||||||
cairo_fill (cr);
|
|
||||||
|
|
||||||
cairo_restore (cr);
|
|
||||||
cairo_pattern_destroy (gradient);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
shell_draw_app_highlight (ClutterCairoTexture *texture,
|
shell_draw_box_pointer (ClutterCairoTexture *texture,
|
||||||
int num_windows,
|
ClutterGravity pointing_towards,
|
||||||
double red,
|
ClutterColor *border_color,
|
||||||
double green,
|
ClutterColor *background_color)
|
||||||
double blue,
|
|
||||||
double alpha)
|
|
||||||
{
|
{
|
||||||
cairo_t *cr;
|
|
||||||
guint width, height;
|
guint width, height;
|
||||||
|
cairo_t *cr;
|
||||||
|
|
||||||
g_return_if_fail (num_windows > 0);
|
g_return_if_fail (pointing_towards == CLUTTER_GRAVITY_NORTH ||
|
||||||
|
pointing_towards == CLUTTER_GRAVITY_WEST);
|
||||||
|
|
||||||
clutter_cairo_texture_get_surface_size (texture, &width, &height);
|
clutter_cairo_texture_get_surface_size (texture, &width, &height);
|
||||||
|
|
||||||
clutter_cairo_texture_clear (texture);
|
clutter_cairo_texture_clear (texture);
|
||||||
cr = clutter_cairo_texture_create (texture);
|
cr = clutter_cairo_texture_create (texture);
|
||||||
|
|
||||||
cairo_save (cr);
|
cairo_set_line_width (cr, 1.0);
|
||||||
cairo_translate (cr, width / 2.0, height / 2.0);
|
|
||||||
|
|
||||||
if (num_windows == 1)
|
clutter_cairo_set_source_color (cr, border_color);
|
||||||
|
|
||||||
|
if (pointing_towards == CLUTTER_GRAVITY_WEST)
|
||||||
{
|
{
|
||||||
cairo_scale (cr, width / 2.0, height / 2.0);
|
cairo_move_to (cr, width, 0);
|
||||||
draw_glow (cr, red, green, blue, alpha);
|
cairo_line_to (cr, 0, floor (height * 0.5));
|
||||||
|
cairo_line_to (cr, width, height);
|
||||||
}
|
}
|
||||||
else
|
else /* CLUTTER_GRAVITY_NORTH */
|
||||||
{
|
{
|
||||||
int num_circles, i;
|
cairo_move_to (cr, 0, height);
|
||||||
double scale, highlight_width;
|
cairo_line_to (cr, floor (width * 0.5), 0);
|
||||||
|
cairo_line_to (cr, width, height);
|
||||||
num_circles = num_windows == 2 ? 2 : 3;
|
|
||||||
|
|
||||||
/* The circles will have radius 1.0 (diameter 2.0) and overlap
|
|
||||||
* by 0.2, so the total width of the highlight is:
|
|
||||||
*/
|
|
||||||
highlight_width = 2.0 * num_circles - 0.2 * (num_circles - 1);
|
|
||||||
|
|
||||||
scale = MIN (height / 2.0, width / highlight_width);
|
|
||||||
cairo_scale (cr, scale, scale);
|
|
||||||
|
|
||||||
/* The leftmost circle's left side is at -highlight_width/2, so
|
|
||||||
* its center is that plus 1.
|
|
||||||
*/
|
|
||||||
cairo_translate (cr, -highlight_width / 2.0 + 1.0, 0.0);
|
|
||||||
for (i = 0; i < num_circles; i++)
|
|
||||||
{
|
|
||||||
draw_glow (cr, red, green, blue, alpha);
|
|
||||||
cairo_translate (cr, 1.8, 0.0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cairo_restore (cr);
|
cairo_stroke_preserve (cr);
|
||||||
|
|
||||||
|
clutter_cairo_set_source_color (cr, background_color);
|
||||||
|
|
||||||
|
cairo_fill (cr);
|
||||||
|
|
||||||
cairo_destroy (cr);
|
cairo_destroy (cr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,25 +196,20 @@ hook_paint_red_border (ClutterActor *actor,
|
|||||||
CoglColor color;
|
CoglColor color;
|
||||||
ClutterGeometry geom;
|
ClutterGeometry geom;
|
||||||
float width = 2;
|
float width = 2;
|
||||||
float x2;
|
|
||||||
float y2;
|
|
||||||
|
|
||||||
cogl_color_set_from_4ub (&color, 0xff, 0, 0, 0xc4);
|
cogl_color_set_from_4ub (&color, 0xff, 0, 0, 0xc4);
|
||||||
cogl_set_source_color (&color);
|
cogl_set_source_color (&color);
|
||||||
|
|
||||||
clutter_actor_get_allocation_geometry (actor, &geom);
|
clutter_actor_get_allocation_geometry (actor, &geom);
|
||||||
x2 = geom.x + geom.width;
|
|
||||||
y2 = geom.y + geom.height;
|
|
||||||
|
|
||||||
/** clockwise order **/
|
/** clockwise order **/
|
||||||
cogl_rectangle (geom.x, geom.y,
|
cogl_rectangle (0, 0, geom.width, width);
|
||||||
x2, geom.y + width);
|
cogl_rectangle (geom.width - width, width,
|
||||||
cogl_rectangle (x2 - width, geom.y + width,
|
geom.width, geom.height);
|
||||||
x2, y2);
|
cogl_rectangle (0, geom.height,
|
||||||
cogl_rectangle (x2 - width, y2,
|
geom.width - width, geom.height - width);
|
||||||
geom.x, y2 - width);
|
cogl_rectangle (0, geom.height - width,
|
||||||
cogl_rectangle (geom.x + width, y2 - width,
|
width, width);
|
||||||
geom.x, geom.y + width);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
guint
|
guint
|
||||||
|
|||||||
@@ -13,17 +13,15 @@ ClutterCairoTexture *shell_create_vertical_gradient (ClutterColor *top,
|
|||||||
ClutterCairoTexture *shell_create_horizontal_gradient (ClutterColor *left,
|
ClutterCairoTexture *shell_create_horizontal_gradient (ClutterColor *left,
|
||||||
ClutterColor *right);
|
ClutterColor *right);
|
||||||
|
|
||||||
|
void shell_draw_box_pointer (ClutterCairoTexture *texture,
|
||||||
|
ClutterGravity pointing_towards,
|
||||||
|
ClutterColor *border_color,
|
||||||
|
ClutterColor *background_color);
|
||||||
|
|
||||||
void shell_draw_clock (ClutterCairoTexture *texture,
|
void shell_draw_clock (ClutterCairoTexture *texture,
|
||||||
int hour,
|
int hour,
|
||||||
int minute);
|
int minute);
|
||||||
|
|
||||||
void shell_draw_app_highlight (ClutterCairoTexture *texture,
|
|
||||||
int num_windows,
|
|
||||||
double red,
|
|
||||||
double blue,
|
|
||||||
double green,
|
|
||||||
double alpha);
|
|
||||||
|
|
||||||
guint shell_add_hook_paint_red_border (ClutterActor *actor);
|
guint shell_add_hook_paint_red_border (ClutterActor *actor);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ struct _ShellGlobal {
|
|||||||
|
|
||||||
MutterPlugin *plugin;
|
MutterPlugin *plugin;
|
||||||
ShellWM *wm;
|
ShellWM *wm;
|
||||||
|
const char *datadir;
|
||||||
const char *imagedir;
|
const char *imagedir;
|
||||||
const char *configdir;
|
const char *configdir;
|
||||||
|
|
||||||
@@ -57,6 +58,7 @@ enum {
|
|||||||
PROP_STAGE,
|
PROP_STAGE,
|
||||||
PROP_WINDOW_GROUP,
|
PROP_WINDOW_GROUP,
|
||||||
PROP_WINDOW_MANAGER,
|
PROP_WINDOW_MANAGER,
|
||||||
|
PROP_DATADIR,
|
||||||
PROP_IMAGEDIR,
|
PROP_IMAGEDIR,
|
||||||
PROP_CONFIGDIR,
|
PROP_CONFIGDIR,
|
||||||
};
|
};
|
||||||
@@ -128,6 +130,9 @@ shell_global_get_property(GObject *object,
|
|||||||
case PROP_WINDOW_MANAGER:
|
case PROP_WINDOW_MANAGER:
|
||||||
g_value_set_object (value, global->wm);
|
g_value_set_object (value, global->wm);
|
||||||
break;
|
break;
|
||||||
|
case PROP_DATADIR:
|
||||||
|
g_value_set_string (value, global->datadir);
|
||||||
|
break;
|
||||||
case PROP_IMAGEDIR:
|
case PROP_IMAGEDIR:
|
||||||
g_value_set_string (value, global->imagedir);
|
g_value_set_string (value, global->imagedir);
|
||||||
break;
|
break;
|
||||||
@@ -149,6 +154,7 @@ shell_global_init (ShellGlobal *global)
|
|||||||
|
|
||||||
if (!datadir)
|
if (!datadir)
|
||||||
datadir = GNOME_SHELL_DATADIR;
|
datadir = GNOME_SHELL_DATADIR;
|
||||||
|
global->datadir = datadir;
|
||||||
|
|
||||||
/* We make sure imagedir ends with a '/', since the JS won't have
|
/* We make sure imagedir ends with a '/', since the JS won't have
|
||||||
* access to g_build_filename() and so will end up just
|
* access to g_build_filename() and so will end up just
|
||||||
@@ -254,6 +260,13 @@ shell_global_class_init (ShellGlobalClass *klass)
|
|||||||
"Window management interface",
|
"Window management interface",
|
||||||
SHELL_TYPE_WM,
|
SHELL_TYPE_WM,
|
||||||
G_PARAM_READABLE));
|
G_PARAM_READABLE));
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_DATADIR,
|
||||||
|
g_param_spec_string ("datadir",
|
||||||
|
"Data directory",
|
||||||
|
"Directory containing gnome-shell data files",
|
||||||
|
NULL,
|
||||||
|
G_PARAM_READABLE));
|
||||||
g_object_class_install_property (gobject_class,
|
g_object_class_install_property (gobject_class,
|
||||||
PROP_IMAGEDIR,
|
PROP_IMAGEDIR,
|
||||||
g_param_spec_string ("imagedir",
|
g_param_spec_string ("imagedir",
|
||||||
@@ -295,47 +308,6 @@ shell_clutter_texture_set_from_pixbuf (ClutterTexture *texture,
|
|||||||
0, NULL);
|
0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* shell_get_event_key_symbol:
|
|
||||||
*
|
|
||||||
* Return value: Clutter key value for the key press and release events,
|
|
||||||
* as specified in clutter-keysyms.h
|
|
||||||
*/
|
|
||||||
guint16
|
|
||||||
shell_get_event_key_symbol(ClutterEvent *event)
|
|
||||||
{
|
|
||||||
g_return_val_if_fail(event->type == CLUTTER_KEY_PRESS ||
|
|
||||||
event->type == CLUTTER_KEY_RELEASE, 0);
|
|
||||||
|
|
||||||
return event->key.keyval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* shell_get_button_event_click_count:
|
|
||||||
*
|
|
||||||
* Return value: click count for button press and release events
|
|
||||||
*/
|
|
||||||
guint16
|
|
||||||
shell_get_button_event_click_count(ClutterEvent *event)
|
|
||||||
{
|
|
||||||
g_return_val_if_fail(event->type == CLUTTER_BUTTON_PRESS ||
|
|
||||||
event->type == CLUTTER_BUTTON_RELEASE, 0);
|
|
||||||
return event->button.click_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* shell_get_event_related:
|
|
||||||
*
|
|
||||||
* Return value: (transfer none): related actor
|
|
||||||
*/
|
|
||||||
ClutterActor *
|
|
||||||
shell_get_event_related (ClutterEvent *event)
|
|
||||||
{
|
|
||||||
g_return_val_if_fail (event->type == CLUTTER_ENTER ||
|
|
||||||
event->type == CLUTTER_LEAVE, NULL);
|
|
||||||
return event->crossing.related;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* shell_global_get:
|
* shell_global_get:
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -36,10 +36,6 @@ GType shell_global_get_type (void) G_GNUC_CONST;
|
|||||||
gboolean shell_clutter_texture_set_from_pixbuf (ClutterTexture *texture,
|
gboolean shell_clutter_texture_set_from_pixbuf (ClutterTexture *texture,
|
||||||
GdkPixbuf *pixbuf);
|
GdkPixbuf *pixbuf);
|
||||||
|
|
||||||
guint16 shell_get_event_key_symbol(ClutterEvent *event);
|
|
||||||
|
|
||||||
guint16 shell_get_button_event_click_count(ClutterEvent *event);
|
|
||||||
|
|
||||||
ClutterActor *shell_get_event_related(ClutterEvent *event);
|
ClutterActor *shell_get_event_related(ClutterEvent *event);
|
||||||
|
|
||||||
ShellGlobal *shell_global_get (void);
|
ShellGlobal *shell_global_get (void);
|
||||||
|
|||||||
@@ -2,3 +2,4 @@ VOID:INT,INT,INT
|
|||||||
VOID:OBJECT,INT,INT,INT,INT
|
VOID:OBJECT,INT,INT,INT,INT
|
||||||
VOID:BOXED
|
VOID:BOXED
|
||||||
VOID:BOXED,OBJECT
|
VOID:BOXED,OBJECT
|
||||||
|
VOID:STRING,OBJECT,BOOLEAN
|
||||||
|
|||||||
335
src/shell-menu.c
Normal file
@@ -0,0 +1,335 @@
|
|||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SECTION:shell-menu
|
||||||
|
* @short_description: A box which acts like a popup menu
|
||||||
|
*
|
||||||
|
* A #BigBox subclass which adds methods and signals useful for implementing
|
||||||
|
* popup-menu like actors.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "shell-menu.h"
|
||||||
|
|
||||||
|
G_DEFINE_TYPE(ShellMenu, shell_menu, BIG_TYPE_BOX);
|
||||||
|
|
||||||
|
struct _ShellMenuPrivate {
|
||||||
|
gboolean popped_up;
|
||||||
|
gboolean have_grab;
|
||||||
|
|
||||||
|
gboolean released_on_source;
|
||||||
|
ClutterActor *source_actor;
|
||||||
|
|
||||||
|
ClutterActor *selected;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Signals */
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
UNSELECTED,
|
||||||
|
SELECTED,
|
||||||
|
ACTIVATE,
|
||||||
|
CANCELLED,
|
||||||
|
LAST_SIGNAL
|
||||||
|
};
|
||||||
|
|
||||||
|
static guint shell_menu_signals [LAST_SIGNAL] = { 0 };
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
container_contains (ClutterContainer *container,
|
||||||
|
ClutterActor *actor)
|
||||||
|
{
|
||||||
|
while (actor != NULL && actor != (ClutterActor*)container)
|
||||||
|
{
|
||||||
|
actor = clutter_actor_get_parent (actor);
|
||||||
|
}
|
||||||
|
return actor != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
shell_menu_popdown_nosignal (ShellMenu *box)
|
||||||
|
{
|
||||||
|
box->priv->popped_up = FALSE;
|
||||||
|
if (box->priv->have_grab)
|
||||||
|
clutter_ungrab_pointer ();
|
||||||
|
clutter_actor_hide (CLUTTER_ACTOR (box));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_selected_destroy (ClutterActor *actor,
|
||||||
|
ShellMenu *box)
|
||||||
|
{
|
||||||
|
box->priv->selected = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_selected (ShellMenu *box,
|
||||||
|
ClutterActor *actor)
|
||||||
|
{
|
||||||
|
if (actor == box->priv->selected)
|
||||||
|
return;
|
||||||
|
if (box->priv->selected)
|
||||||
|
{
|
||||||
|
g_signal_handlers_disconnect_by_func (box->priv->selected, G_CALLBACK(on_selected_destroy), box);
|
||||||
|
g_signal_emit (G_OBJECT (box), shell_menu_signals[UNSELECTED], 0, box->priv->selected);
|
||||||
|
}
|
||||||
|
box->priv->selected = actor;
|
||||||
|
if (box->priv->selected)
|
||||||
|
{
|
||||||
|
g_signal_connect (box->priv->selected, "destroy", G_CALLBACK(on_selected_destroy), box);
|
||||||
|
g_signal_emit (G_OBJECT (box), shell_menu_signals[SELECTED], 0, box->priv->selected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
shell_menu_enter_event (ClutterActor *actor,
|
||||||
|
ClutterCrossingEvent *event)
|
||||||
|
{
|
||||||
|
ShellMenu *box = SHELL_MENU (actor);
|
||||||
|
|
||||||
|
if (!container_contains (CLUTTER_CONTAINER (box), event->source))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
if (event->source == (ClutterActor*)box)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
if (g_object_get_data (G_OBJECT (event->source), "shell-is-separator"))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
set_selected (box, event->source);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
shell_menu_leave_event (ClutterActor *actor,
|
||||||
|
ClutterCrossingEvent *event)
|
||||||
|
{
|
||||||
|
ShellMenu *box = SHELL_MENU (actor);
|
||||||
|
|
||||||
|
set_selected (box, NULL);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
shell_menu_button_release_event (ClutterActor *actor,
|
||||||
|
ClutterButtonEvent *event)
|
||||||
|
{
|
||||||
|
ShellMenu *box = SHELL_MENU (actor);
|
||||||
|
|
||||||
|
if (event->button != 1)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (box->priv->source_actor && !box->priv->released_on_source)
|
||||||
|
{
|
||||||
|
if (box->priv->source_actor == event->source ||
|
||||||
|
(CLUTTER_IS_CONTAINER (box->priv->source_actor) &&
|
||||||
|
container_contains (CLUTTER_CONTAINER (box->priv->source_actor), event->source)))
|
||||||
|
{
|
||||||
|
/* On the next release, we want to pop down the menu regardless */
|
||||||
|
box->priv->released_on_source = TRUE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
shell_menu_popdown_nosignal (box);
|
||||||
|
|
||||||
|
if (!container_contains (CLUTTER_CONTAINER (box), event->source))
|
||||||
|
{
|
||||||
|
g_signal_emit (G_OBJECT (box), shell_menu_signals[CANCELLED], 0);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (box->priv->selected == NULL)
|
||||||
|
{
|
||||||
|
g_signal_emit (G_OBJECT (box), shell_menu_signals[CANCELLED], 0);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_signal_emit (G_OBJECT (box), shell_menu_signals[ACTIVATE], 0, box->priv->selected);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
shell_menu_popup (ShellMenu *box,
|
||||||
|
guint button,
|
||||||
|
guint32 activate_time)
|
||||||
|
{
|
||||||
|
if (box->priv->popped_up)
|
||||||
|
return;
|
||||||
|
box->priv->popped_up = TRUE;
|
||||||
|
box->priv->have_grab = TRUE;
|
||||||
|
box->priv->released_on_source = FALSE;
|
||||||
|
clutter_grab_pointer (CLUTTER_ACTOR (box));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* shell_menu_popdown:
|
||||||
|
* @box:
|
||||||
|
*
|
||||||
|
* If the menu is currently active, hide it, emitting the 'cancelled' signal.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
shell_menu_popdown (ShellMenu *box)
|
||||||
|
{
|
||||||
|
if (!box->priv->popped_up)
|
||||||
|
return;
|
||||||
|
shell_menu_popdown_nosignal (box);
|
||||||
|
g_signal_emit (G_OBJECT (box), shell_menu_signals[CANCELLED], 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_source_destroyed (ClutterActor *actor,
|
||||||
|
ShellMenu *box)
|
||||||
|
{
|
||||||
|
box->priv->source_actor = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* shell_menu_set_persistent_source:
|
||||||
|
* @box:
|
||||||
|
* @source: Actor to use as menu origin
|
||||||
|
*
|
||||||
|
* This function changes the menu behavior on button release. Normally
|
||||||
|
* when the mouse is released anywhere, the menu "pops down"; when this
|
||||||
|
* function is called, if the mouse is released over the source actor,
|
||||||
|
* the menu stays.
|
||||||
|
*
|
||||||
|
* The given @source actor must be reactive for this function to work.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
shell_menu_set_persistent_source (ShellMenu *box,
|
||||||
|
ClutterActor *source)
|
||||||
|
{
|
||||||
|
if (box->priv->source_actor)
|
||||||
|
{
|
||||||
|
g_signal_handlers_disconnect_by_func (G_OBJECT (box->priv->source_actor),
|
||||||
|
G_CALLBACK (on_source_destroyed),
|
||||||
|
box);
|
||||||
|
}
|
||||||
|
box->priv->source_actor = source;
|
||||||
|
if (box->priv->source_actor)
|
||||||
|
{
|
||||||
|
g_signal_connect (G_OBJECT (box->priv->source_actor),
|
||||||
|
"destroy",
|
||||||
|
G_CALLBACK (on_source_destroyed),
|
||||||
|
box);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* shell_menu_append_separator:
|
||||||
|
* @box:
|
||||||
|
* @separator: An actor which functions as a menu separator
|
||||||
|
* @flags: Packing flags
|
||||||
|
*
|
||||||
|
* Actors added to the menu with default functions are treated like
|
||||||
|
* menu items; this function will add an actor that should instead
|
||||||
|
* be treated like a menu separator. The current practical effect
|
||||||
|
* is that the separators will not be selectable.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
shell_menu_append_separator (ShellMenu *box,
|
||||||
|
ClutterActor *separator,
|
||||||
|
BigBoxPackFlags flags)
|
||||||
|
{
|
||||||
|
g_object_set_data (G_OBJECT (separator), "shell-is-separator", GUINT_TO_POINTER(TRUE));
|
||||||
|
big_box_append (BIG_BOX (box), separator, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
shell_menu_dispose (GObject *gobject)
|
||||||
|
{
|
||||||
|
ShellMenu *self = SHELL_MENU (gobject);
|
||||||
|
|
||||||
|
shell_menu_set_persistent_source (self, NULL);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (shell_menu_parent_class)->dispose (gobject);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
shell_menu_class_init (ShellMenuClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||||
|
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||||
|
|
||||||
|
gobject_class->dispose = shell_menu_dispose;
|
||||||
|
|
||||||
|
actor_class->enter_event = shell_menu_enter_event;
|
||||||
|
actor_class->leave_event = shell_menu_leave_event;
|
||||||
|
actor_class->button_release_event = shell_menu_button_release_event;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ShellMenu::unselected
|
||||||
|
* @box: The #ShellMenu
|
||||||
|
* @actor: The previously hovered-over menu item
|
||||||
|
*
|
||||||
|
* This signal is emitted when a menu item transitions to
|
||||||
|
* an unselected state.
|
||||||
|
*/
|
||||||
|
shell_menu_signals[UNSELECTED] =
|
||||||
|
g_signal_new ("unselected",
|
||||||
|
G_TYPE_FROM_CLASS (klass),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
0,
|
||||||
|
NULL, NULL,
|
||||||
|
g_cclosure_marshal_VOID__OBJECT,
|
||||||
|
G_TYPE_NONE, 1, CLUTTER_TYPE_ACTOR);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ShellMenu::selected
|
||||||
|
* @box: The #ShellMenu
|
||||||
|
* @actor: The hovered-over menu item
|
||||||
|
*
|
||||||
|
* This signal is emitted when a menu item is in a selected state.
|
||||||
|
*/
|
||||||
|
shell_menu_signals[SELECTED] =
|
||||||
|
g_signal_new ("selected",
|
||||||
|
G_TYPE_FROM_CLASS (klass),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
0,
|
||||||
|
NULL, NULL,
|
||||||
|
g_cclosure_marshal_VOID__OBJECT,
|
||||||
|
G_TYPE_NONE, 1, CLUTTER_TYPE_ACTOR);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ShellMenu::activate
|
||||||
|
* @box: The #ShellMenu
|
||||||
|
* @actor: The clicked menu item
|
||||||
|
*
|
||||||
|
* This signal is emitted when a menu item is selected.
|
||||||
|
*/
|
||||||
|
shell_menu_signals[ACTIVATE] =
|
||||||
|
g_signal_new ("activate",
|
||||||
|
G_TYPE_FROM_CLASS (klass),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
0,
|
||||||
|
NULL, NULL,
|
||||||
|
g_cclosure_marshal_VOID__OBJECT,
|
||||||
|
G_TYPE_NONE, 1, CLUTTER_TYPE_ACTOR);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ShellMenu::cancelled
|
||||||
|
* @box: The #ShellMenu
|
||||||
|
*
|
||||||
|
* This signal is emitted when the menu is closed without an option selected.
|
||||||
|
*/
|
||||||
|
shell_menu_signals[CANCELLED] =
|
||||||
|
g_signal_new ("cancelled",
|
||||||
|
G_TYPE_FROM_CLASS (klass),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
0,
|
||||||
|
NULL, NULL,
|
||||||
|
g_cclosure_marshal_VOID__OBJECT,
|
||||||
|
G_TYPE_NONE, 0);
|
||||||
|
|
||||||
|
g_type_class_add_private (gobject_class, sizeof (ShellMenuPrivate));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
shell_menu_init (ShellMenu *self)
|
||||||
|
{
|
||||||
|
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, SHELL_TYPE_MENU,
|
||||||
|
ShellMenuPrivate);
|
||||||
|
}
|
||||||
41
src/shell-menu.h
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
#ifndef __SHELL_MENU_H__
|
||||||
|
#define __SHELL_MENU_H__
|
||||||
|
|
||||||
|
#include <clutter/clutter.h>
|
||||||
|
#include "big/box.h"
|
||||||
|
|
||||||
|
#define SHELL_TYPE_MENU (shell_menu_get_type ())
|
||||||
|
#define SHELL_MENU(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SHELL_TYPE_MENU, ShellMenu))
|
||||||
|
#define SHELL_MENU_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SHELL_TYPE_MENU, ShellMenuClass))
|
||||||
|
#define SHELL_IS_MENU(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SHELL_TYPE_MENU))
|
||||||
|
#define SHELL_IS_MENU_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SHELL_TYPE_MENU))
|
||||||
|
#define SHELL_MENU_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SHELL_TYPE_MENU, ShellMenuClass))
|
||||||
|
|
||||||
|
typedef struct _ShellMenu ShellMenu;
|
||||||
|
typedef struct _ShellMenuClass ShellMenuClass;
|
||||||
|
|
||||||
|
typedef struct _ShellMenuPrivate ShellMenuPrivate;
|
||||||
|
|
||||||
|
struct _ShellMenu
|
||||||
|
{
|
||||||
|
BigBox parent;
|
||||||
|
|
||||||
|
ShellMenuPrivate *priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _ShellMenuClass
|
||||||
|
{
|
||||||
|
BigBoxClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType shell_menu_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
void shell_menu_popup (ShellMenu *behavior, guint button, guint32 activate_time);
|
||||||
|
|
||||||
|
void shell_menu_set_persistent_source (ShellMenu *behavior, ClutterActor *source);
|
||||||
|
|
||||||
|
void shell_menu_append_separator (ShellMenu *behavior, ClutterActor *separator, BigBoxPackFlags flags);
|
||||||
|
|
||||||
|
void shell_menu_popdown (ShellMenu *behavior);
|
||||||
|
|
||||||
|
#endif /* __SHELL_MENU_H__ */
|
||||||
@@ -24,6 +24,23 @@ struct _ShellOverflowListPrivate {
|
|||||||
guint displayed_count;
|
guint displayed_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static GList *
|
||||||
|
get_visible_children (ShellOverflowList *self)
|
||||||
|
{
|
||||||
|
GList *children, *iter, *next;
|
||||||
|
|
||||||
|
children = clutter_container_get_children (CLUTTER_CONTAINER (self));
|
||||||
|
for (iter = children; iter; iter = next)
|
||||||
|
{
|
||||||
|
ClutterActor *actor = iter->data;
|
||||||
|
next = iter->next;
|
||||||
|
|
||||||
|
if (!CLUTTER_ACTOR_IS_VISIBLE (actor))
|
||||||
|
children = g_list_delete_link (children, iter);
|
||||||
|
}
|
||||||
|
return children;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
recalc_displayed_count (ShellOverflowList *self)
|
recalc_displayed_count (ShellOverflowList *self)
|
||||||
{
|
{
|
||||||
@@ -32,7 +49,7 @@ recalc_displayed_count (ShellOverflowList *self)
|
|||||||
int displayed_count;
|
int displayed_count;
|
||||||
int page, n_pages;
|
int page, n_pages;
|
||||||
|
|
||||||
children = clutter_container_get_children (CLUTTER_CONTAINER (self));
|
children = get_visible_children (self);
|
||||||
n_children = g_list_length (children);
|
n_children = g_list_length (children);
|
||||||
g_list_free (children);
|
g_list_free (children);
|
||||||
|
|
||||||
@@ -136,7 +153,7 @@ shell_overflow_list_allocate (ClutterActor *actor,
|
|||||||
curheight = 0;
|
curheight = 0;
|
||||||
avail_height = box->y2 - box->y1;
|
avail_height = box->y2 - box->y1;
|
||||||
|
|
||||||
children = clutter_container_get_children (CLUTTER_CONTAINER (self));
|
children = get_visible_children (self);
|
||||||
n_children = g_list_length (children);
|
n_children = g_list_length (children);
|
||||||
|
|
||||||
n_fits = 0;
|
n_fits = 0;
|
||||||
@@ -189,7 +206,7 @@ shell_overflow_list_paint (ClutterActor *actor)
|
|||||||
GList *children, *iter;
|
GList *children, *iter;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
children = clutter_container_get_children (CLUTTER_CONTAINER (self));
|
children = get_visible_children (self);
|
||||||
|
|
||||||
if (children == NULL)
|
if (children == NULL)
|
||||||
return;
|
return;
|
||||||
@@ -232,7 +249,7 @@ shell_overflow_list_get_preferred_height (ClutterActor *actor,
|
|||||||
if (natural_height_p)
|
if (natural_height_p)
|
||||||
{
|
{
|
||||||
int n_children;
|
int n_children;
|
||||||
children = clutter_container_get_children (CLUTTER_CONTAINER (self));
|
children = get_visible_children (self);
|
||||||
n_children = g_list_length (children);
|
n_children = g_list_length (children);
|
||||||
if (n_children == 0)
|
if (n_children == 0)
|
||||||
*natural_height_p = 0;
|
*natural_height_p = 0;
|
||||||
@@ -254,7 +271,7 @@ shell_overflow_list_get_preferred_width (ClutterActor *actor,
|
|||||||
GList *iter;
|
GList *iter;
|
||||||
GList *children;
|
GList *children;
|
||||||
|
|
||||||
children = clutter_container_get_children (CLUTTER_CONTAINER (self));
|
children = get_visible_children (self);
|
||||||
|
|
||||||
for (iter = children; iter; iter = iter->next)
|
for (iter = children; iter; iter = iter->next)
|
||||||
{
|
{
|
||||||
@@ -374,7 +391,7 @@ shell_overflow_list_get_displayed_actor (ShellOverflowList *self,
|
|||||||
{
|
{
|
||||||
GList *children, *iter;
|
GList *children, *iter;
|
||||||
|
|
||||||
children = clutter_container_get_children (CLUTTER_CONTAINER (self));
|
children = get_visible_children (self);
|
||||||
|
|
||||||
if (children == NULL)
|
if (children == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -405,7 +422,7 @@ shell_overflow_list_get_actor_index (ShellOverflowList *self,
|
|||||||
int i;
|
int i;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
children = clutter_container_get_children (CLUTTER_CONTAINER (self));
|
children = get_visible_children (self);
|
||||||
|
|
||||||
if (children == NULL)
|
if (children == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
@@ -1,240 +0,0 @@
|
|||||||
#include "shell-panel-window.h"
|
|
||||||
|
|
||||||
#include <gdk/gdkx.h>
|
|
||||||
#include <X11/Xlib.h>
|
|
||||||
|
|
||||||
#define PANEL_HEIGHT 25
|
|
||||||
|
|
||||||
enum {
|
|
||||||
PROP_0,
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
static void shell_panel_window_finalize (GObject *object);
|
|
||||||
static void shell_panel_window_size_request (GtkWidget *self, GtkRequisition *req);
|
|
||||||
static void shell_panel_window_size_allocate (GtkWidget *self, GtkAllocation *allocation);
|
|
||||||
static void shell_panel_window_realize (GtkWidget *self);
|
|
||||||
static void shell_panel_window_show (GtkWidget *self);
|
|
||||||
static void set_strut (ShellPanelWindow *self);
|
|
||||||
static void on_workarea_changed (ShellPanelWindow *self);
|
|
||||||
static void handle_new_workarea (ShellPanelWindow *self);
|
|
||||||
static GdkFilterReturn filter_func (GdkXEvent *xevent,
|
|
||||||
GdkEvent *event,
|
|
||||||
gpointer data);
|
|
||||||
|
|
||||||
G_DEFINE_TYPE(ShellPanelWindow, shell_panel_window, GTK_TYPE_WINDOW);
|
|
||||||
|
|
||||||
struct ShellPanelWindowPrivate {
|
|
||||||
GtkAllocation workarea;
|
|
||||||
guint width;
|
|
||||||
guint height;
|
|
||||||
Atom workarea_atom;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
shell_panel_window_class_init(ShellPanelWindowClass *klass)
|
|
||||||
{
|
|
||||||
GObjectClass *gobject_class = (GObjectClass *)klass;
|
|
||||||
GtkWidgetClass *widget_class = (GtkWidgetClass *)klass;
|
|
||||||
|
|
||||||
gobject_class->finalize = shell_panel_window_finalize;
|
|
||||||
|
|
||||||
widget_class->realize = shell_panel_window_realize;
|
|
||||||
widget_class->size_request = shell_panel_window_size_request;
|
|
||||||
widget_class->size_allocate = shell_panel_window_size_allocate;
|
|
||||||
widget_class->show = shell_panel_window_show;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void shell_panel_window_init (ShellPanelWindow *self)
|
|
||||||
{
|
|
||||||
self->priv = g_new0 (ShellPanelWindowPrivate, 1);
|
|
||||||
|
|
||||||
self->priv->workarea_atom = gdk_x11_get_xatom_by_name_for_display (gdk_display_get_default (), "_NET_WORKAREA");
|
|
||||||
|
|
||||||
gtk_window_set_type_hint (GTK_WINDOW (self), GDK_WINDOW_TYPE_HINT_DOCK);
|
|
||||||
gtk_window_set_focus_on_map (GTK_WINDOW (self), FALSE);
|
|
||||||
gdk_window_add_filter (NULL, filter_func, self);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void shell_panel_window_finalize (GObject *object)
|
|
||||||
{
|
|
||||||
ShellPanelWindow *self = (ShellPanelWindow*)object;
|
|
||||||
|
|
||||||
g_free (self->priv);
|
|
||||||
g_signal_handlers_destroy(object);
|
|
||||||
G_OBJECT_CLASS (shell_panel_window_parent_class)->finalize(object);
|
|
||||||
}
|
|
||||||
|
|
||||||
ShellPanelWindow* shell_panel_window_new(void) {
|
|
||||||
return (ShellPanelWindow*) g_object_new(SHELL_TYPE_PANEL_WINDOW,
|
|
||||||
"type", GTK_WINDOW_TOPLEVEL, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
set_strut (ShellPanelWindow *self)
|
|
||||||
{
|
|
||||||
long *buf;
|
|
||||||
int strut_size;
|
|
||||||
|
|
||||||
strut_size = GTK_WIDGET (self)->allocation.height;
|
|
||||||
|
|
||||||
buf = g_new0 (long, 4);
|
|
||||||
buf[0] = 0; /* left */
|
|
||||||
buf[1] = 0; /* right */
|
|
||||||
buf[2] = 0; /* top */
|
|
||||||
buf[3] = strut_size; /* bottom */
|
|
||||||
gdk_property_change (GTK_WIDGET (self)->window, gdk_atom_intern_static_string ("_NET_WM_STRUT"),
|
|
||||||
gdk_atom_intern_static_string ("CARDINAL"), 32,
|
|
||||||
GDK_PROP_MODE_REPLACE,
|
|
||||||
(guchar*) buf, 4);
|
|
||||||
g_free (buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
shell_panel_window_size_request (GtkWidget *widget, GtkRequisition *requisition)
|
|
||||||
{
|
|
||||||
ShellPanelWindow *self = SHELL_PANEL_WINDOW (widget);
|
|
||||||
GTK_WIDGET_CLASS (shell_panel_window_parent_class)->size_request(widget, requisition);
|
|
||||||
requisition->width = self->priv->width;
|
|
||||||
requisition->height = PANEL_HEIGHT;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
shell_panel_window_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
|
|
||||||
{
|
|
||||||
ShellPanelWindow *self = SHELL_PANEL_WINDOW (widget);
|
|
||||||
GTK_WIDGET_CLASS (shell_panel_window_parent_class)->size_allocate(widget, allocation);
|
|
||||||
if (GTK_WIDGET_REALIZED (self))
|
|
||||||
set_strut (self);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
shell_panel_window_realize (GtkWidget *widget)
|
|
||||||
{
|
|
||||||
ShellPanelWindow *self = SHELL_PANEL_WINDOW (widget);
|
|
||||||
GTK_WIDGET_CLASS (shell_panel_window_parent_class)->realize(widget);
|
|
||||||
set_strut (self);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
shell_panel_window_show (GtkWidget *widget)
|
|
||||||
{
|
|
||||||
ShellPanelWindow *self = SHELL_PANEL_WINDOW (widget);
|
|
||||||
on_workarea_changed (self);
|
|
||||||
GTK_WIDGET_CLASS (shell_panel_window_parent_class)->show(widget);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
handle_new_workarea (ShellPanelWindow *self)
|
|
||||||
{
|
|
||||||
GtkRequisition requisition;
|
|
||||||
int x, y;
|
|
||||||
int width;
|
|
||||||
int height;
|
|
||||||
int x_target, y_target;
|
|
||||||
|
|
||||||
gtk_widget_size_request (GTK_WIDGET (self), &requisition);
|
|
||||||
|
|
||||||
/* If we don't have a workarea, just use monitor */
|
|
||||||
if (self->priv->workarea.width == 0)
|
|
||||||
{
|
|
||||||
int monitor;
|
|
||||||
GdkRectangle monitor_geometry;
|
|
||||||
|
|
||||||
monitor = gdk_screen_get_monitor_at_point (gdk_screen_get_default (),
|
|
||||||
0, 0);
|
|
||||||
gdk_screen_get_monitor_geometry (gdk_screen_get_default (),
|
|
||||||
monitor, &monitor_geometry);
|
|
||||||
x = monitor_geometry.x;
|
|
||||||
y = monitor_geometry.y;
|
|
||||||
width = monitor_geometry.width;
|
|
||||||
height = monitor_geometry.height;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
x = self->priv->workarea.x;
|
|
||||||
y = self->priv->workarea.y;
|
|
||||||
width = self->priv->workarea.width;
|
|
||||||
height = self->priv->workarea.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
x_target = x;
|
|
||||||
y_target = y + height - requisition.height;
|
|
||||||
|
|
||||||
self->priv->width = width;
|
|
||||||
self->priv->height = height;
|
|
||||||
gtk_widget_set_size_request (GTK_WIDGET (self), width - x_target, PANEL_HEIGHT);
|
|
||||||
gtk_window_move (GTK_WINDOW (self), x_target, y_target);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
on_workarea_changed (ShellPanelWindow *self)
|
|
||||||
{
|
|
||||||
gulong bytes_after, nitems;
|
|
||||||
Atom type;
|
|
||||||
gint format;
|
|
||||||
guchar *data;
|
|
||||||
long *data32;
|
|
||||||
Atom workarea = gdk_x11_get_xatom_by_name_for_display (gdk_display_get_default (), "_NET_WORKAREA");
|
|
||||||
|
|
||||||
XGetWindowProperty (GDK_DISPLAY(), GDK_ROOT_WINDOW(),
|
|
||||||
workarea,
|
|
||||||
0, 4, FALSE, workarea,
|
|
||||||
&type, &format, &nitems, &bytes_after, &data);
|
|
||||||
if ((format == 32) && (nitems == 4) && (bytes_after == 0))
|
|
||||||
{
|
|
||||||
int x, y, width, height;
|
|
||||||
data32 = (long*) data;
|
|
||||||
x = data32[0];
|
|
||||||
y = data32[1];
|
|
||||||
width = data32[2];
|
|
||||||
height = data32[3];
|
|
||||||
if (x == self->priv->workarea.x && y == self->priv->workarea.y
|
|
||||||
&& width == self->priv->workarea.width
|
|
||||||
&& height == self->priv->workarea.height)
|
|
||||||
return;
|
|
||||||
|
|
||||||
self->priv->workarea.x = x;
|
|
||||||
self->priv->workarea.y = y;
|
|
||||||
self->priv->workarea.width = width;
|
|
||||||
self->priv->workarea.height = height;
|
|
||||||
|
|
||||||
handle_new_workarea (self);
|
|
||||||
}
|
|
||||||
else if (nitems == 0)
|
|
||||||
{
|
|
||||||
/* We have no workarea set; assume there are no other panels at this time */
|
|
||||||
self->priv->workarea.x = self->priv->workarea.y = 0;
|
|
||||||
self->priv->workarea.width = self->priv->workarea.height = 0;
|
|
||||||
handle_new_workarea (self);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
g_printerr ("unexpected return from XGetWindowProperty: %d %ld %ld\n",
|
|
||||||
format, nitems, bytes_after);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static GdkFilterReturn
|
|
||||||
filter_func (GdkXEvent *gdk_xevent,
|
|
||||||
GdkEvent *event,
|
|
||||||
gpointer data)
|
|
||||||
{
|
|
||||||
ShellPanelWindow *self = SHELL_PANEL_WINDOW (data);
|
|
||||||
GdkFilterReturn ret = GDK_FILTER_CONTINUE;
|
|
||||||
XEvent *xevent = (XEvent *) event;
|
|
||||||
|
|
||||||
switch (xevent->type)
|
|
||||||
{
|
|
||||||
case PropertyNotify:
|
|
||||||
{
|
|
||||||
if (xevent->xproperty.atom != self->priv->workarea_atom)
|
|
||||||
break;
|
|
||||||
on_workarea_changed (self);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
#ifndef __SHELL_PANEL_WINDOW_H__
|
|
||||||
#define __SHELL_PANEL_WINDOW_H__
|
|
||||||
|
|
||||||
#include <gtk/gtk.h>
|
|
||||||
|
|
||||||
#define SHELL_TYPE_PANEL_WINDOW (shell_panel_window_get_type ())
|
|
||||||
#define SHELL_PANEL_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SHELL_TYPE_PANEL_WINDOW, ShellPanelWindow))
|
|
||||||
#define SHELL_PANEL_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SHELL_TYPE_PANEL_WINDOW, ShellPanelWindowClass))
|
|
||||||
#define SHELL_IS_PANEL_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SHELL_TYPE_PANEL_WINDOW))
|
|
||||||
#define SHELL_IS_PANEL_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SHELL_TYPE_PANEL_WINDOW))
|
|
||||||
#define SHELL_PANEL_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SHELL_TYPE_PANEL_WINDOW, ShellPanelWindowClass))
|
|
||||||
|
|
||||||
typedef struct _ShellPanelWindow ShellPanelWindow;
|
|
||||||
typedef struct _ShellPanelWindowClass ShellPanelWindowClass;
|
|
||||||
|
|
||||||
typedef struct ShellPanelWindowPrivate ShellPanelWindowPrivate;
|
|
||||||
|
|
||||||
struct _ShellPanelWindow
|
|
||||||
{
|
|
||||||
GtkWindow parent;
|
|
||||||
|
|
||||||
ShellPanelWindowPrivate *priv;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _ShellPanelWindowClass
|
|
||||||
{
|
|
||||||
GtkWindowClass parent_class;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
GType shell_panel_window_get_type (void) G_GNUC_CONST;
|
|
||||||
ShellPanelWindow* shell_panel_window_new(void);
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* __SHELL_PANEL_WINDOW_H__ */
|
|
||||||
@@ -20,7 +20,13 @@ typedef struct
|
|||||||
|
|
||||||
struct _ShellTextureCachePrivate
|
struct _ShellTextureCachePrivate
|
||||||
{
|
{
|
||||||
|
/* Things that were loaded with a cache policy != NONE */
|
||||||
GHashTable *keyed_cache; /* CacheKey -> CoglTexture* */
|
GHashTable *keyed_cache; /* CacheKey -> CoglTexture* */
|
||||||
|
/* Presently this is used to de-duplicate requests for GIcons,
|
||||||
|
* it could in theory be extended to async URL loading and other
|
||||||
|
* cases too.
|
||||||
|
*/
|
||||||
|
GHashTable *outstanding_requests; /* CacheKey -> AsyncTextureLoadData * */
|
||||||
GnomeDesktopThumbnailFactory *thumbnails;
|
GnomeDesktopThumbnailFactory *thumbnails;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -130,6 +136,8 @@ shell_texture_cache_init (ShellTextureCache *self)
|
|||||||
self->priv = g_new0 (ShellTextureCachePrivate, 1);
|
self->priv = g_new0 (ShellTextureCachePrivate, 1);
|
||||||
self->priv->keyed_cache = g_hash_table_new_full (cache_key_hash, cache_key_equal,
|
self->priv->keyed_cache = g_hash_table_new_full (cache_key_hash, cache_key_equal,
|
||||||
cache_key_destroy, cogl_handle_unref);
|
cache_key_destroy, cogl_handle_unref);
|
||||||
|
self->priv->outstanding_requests = g_hash_table_new_full (cache_key_hash, cache_key_equal,
|
||||||
|
cache_key_destroy, NULL);
|
||||||
self->priv->thumbnails = gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_NORMAL);
|
self->priv->thumbnails = gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -427,7 +435,10 @@ impl_load_thumbnail (ShellTextureCache *cache,
|
|||||||
existing_thumbnail = gnome_desktop_thumbnail_factory_lookup (thumbnail_factory, uri, mtime);
|
existing_thumbnail = gnome_desktop_thumbnail_factory_lookup (thumbnail_factory, uri, mtime);
|
||||||
|
|
||||||
if (existing_thumbnail != NULL)
|
if (existing_thumbnail != NULL)
|
||||||
pixbuf = gdk_pixbuf_new_from_file_at_size (existing_thumbnail, size, size, error);
|
{
|
||||||
|
pixbuf = gdk_pixbuf_new_from_file_at_size (existing_thumbnail, size, size, error);
|
||||||
|
g_free (existing_thumbnail);
|
||||||
|
}
|
||||||
else if (gnome_desktop_thumbnail_factory_has_valid_failed_thumbnail (thumbnail_factory, uri, mtime))
|
else if (gnome_desktop_thumbnail_factory_has_valid_failed_thumbnail (thumbnail_factory, uri, mtime))
|
||||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Has failed thumbnail");
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Has failed thumbnail");
|
||||||
else if (gnome_desktop_thumbnail_factory_can_thumbnail (thumbnail_factory, uri, mime_type, mtime))
|
else if (gnome_desktop_thumbnail_factory_can_thumbnail (thumbnail_factory, uri, mime_type, mtime))
|
||||||
@@ -644,7 +655,7 @@ typedef struct {
|
|||||||
GtkIconInfo *icon_info;
|
GtkIconInfo *icon_info;
|
||||||
guint width;
|
guint width;
|
||||||
guint height;
|
guint height;
|
||||||
ClutterTexture *texture;
|
GSList *textures;
|
||||||
} AsyncTextureLoadData;
|
} AsyncTextureLoadData;
|
||||||
|
|
||||||
static CoglHandle
|
static CoglHandle
|
||||||
@@ -703,15 +714,31 @@ on_pixbuf_loaded (GObject *source,
|
|||||||
GAsyncResult *result,
|
GAsyncResult *result,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
|
GSList *iter;
|
||||||
ShellTextureCache *cache;
|
ShellTextureCache *cache;
|
||||||
AsyncTextureLoadData *data;
|
AsyncTextureLoadData *data;
|
||||||
GdkPixbuf *pixbuf;
|
GdkPixbuf *pixbuf;
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
CoglHandle texdata;
|
CoglHandle texdata = NULL;
|
||||||
CacheKey *key;
|
CacheKey key;
|
||||||
|
|
||||||
data = user_data;
|
data = user_data;
|
||||||
cache = SHELL_TEXTURE_CACHE (source);
|
cache = SHELL_TEXTURE_CACHE (source);
|
||||||
|
|
||||||
|
memset (&key, 0, sizeof(key));
|
||||||
|
key.policy = data->policy;
|
||||||
|
if (data->icon)
|
||||||
|
key.icon = data->icon;
|
||||||
|
else if (data->recent_info && data->thumbnail)
|
||||||
|
key.thumbnail_uri = (char*)gtk_recent_info_get_uri (data->recent_info);
|
||||||
|
else if (data->thumbnail)
|
||||||
|
key.thumbnail_uri = (char*)data->uri;
|
||||||
|
else if (data->uri)
|
||||||
|
key.uri = data->uri;
|
||||||
|
key.size = data->width;
|
||||||
|
|
||||||
|
g_hash_table_remove (cache->priv->outstanding_requests, &key);
|
||||||
|
|
||||||
pixbuf = load_pixbuf_async_finish (cache, result, &error);
|
pixbuf = load_pixbuf_async_finish (cache, result, &error);
|
||||||
if (pixbuf == NULL)
|
if (pixbuf == NULL)
|
||||||
pixbuf = load_pixbuf_fallback(data);
|
pixbuf = load_pixbuf_fallback(data);
|
||||||
@@ -726,29 +753,24 @@ on_pixbuf_loaded (GObject *source,
|
|||||||
{
|
{
|
||||||
gpointer orig_key, value;
|
gpointer orig_key, value;
|
||||||
|
|
||||||
key = g_new0 (CacheKey, 1);
|
if (!g_hash_table_lookup_extended (cache->priv->keyed_cache, &key,
|
||||||
key->policy = data->policy;
|
|
||||||
if (data->icon)
|
|
||||||
key->icon = g_object_ref (data->icon);
|
|
||||||
else if (data->recent_info && data->thumbnail)
|
|
||||||
key->thumbnail_uri = g_strdup (gtk_recent_info_get_uri (data->recent_info));
|
|
||||||
else if (data->thumbnail)
|
|
||||||
key->thumbnail_uri = g_strdup (data->uri);
|
|
||||||
else if (data->uri)
|
|
||||||
key->uri = g_strdup (data->uri);
|
|
||||||
key->size = data->width;
|
|
||||||
|
|
||||||
if (!g_hash_table_lookup_extended (cache->priv->keyed_cache, key,
|
|
||||||
&orig_key, &value))
|
&orig_key, &value))
|
||||||
g_hash_table_insert (cache->priv->keyed_cache, key,
|
{
|
||||||
texdata);
|
cogl_handle_ref (texdata);
|
||||||
else
|
g_hash_table_insert (cache->priv->keyed_cache, cache_key_dup (&key),
|
||||||
cache_key_destroy (key);
|
texdata);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
set_texture_cogl_texture (data->texture, texdata);
|
for (iter = data->textures; iter; iter = iter->next)
|
||||||
|
{
|
||||||
|
ClutterTexture *texture = iter->data;
|
||||||
|
set_texture_cogl_texture (texture, texdata);
|
||||||
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
if (texdata)
|
||||||
|
cogl_handle_unref (texdata);
|
||||||
if (data->icon)
|
if (data->icon)
|
||||||
{
|
{
|
||||||
gtk_icon_info_free (data->icon_info);
|
gtk_icon_info_free (data->icon_info);
|
||||||
@@ -764,7 +786,11 @@ out:
|
|||||||
|
|
||||||
/* Alternatively we could weakref and just do nothing if the texture
|
/* Alternatively we could weakref and just do nothing if the texture
|
||||||
is destroyed */
|
is destroyed */
|
||||||
g_object_unref (data->texture);
|
for (iter = data->textures; iter; iter = iter->next)
|
||||||
|
{
|
||||||
|
ClutterTexture *texture = iter->data;
|
||||||
|
g_object_unref (texture);
|
||||||
|
}
|
||||||
|
|
||||||
g_clear_error (&error);
|
g_clear_error (&error);
|
||||||
g_free (data);
|
g_free (data);
|
||||||
@@ -872,6 +898,59 @@ shell_texture_cache_bind_pixbuf_property (ShellTextureCache *cache,
|
|||||||
return CLUTTER_ACTOR(texture);
|
return CLUTTER_ACTOR(texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* create_texture_and_ensure_request:
|
||||||
|
* @cache:
|
||||||
|
* @key: A filled in #CacheKey
|
||||||
|
* @request: (out): If no request is outstanding, one will be created and returned here
|
||||||
|
* @texture: (out): A new texture, also added to the request
|
||||||
|
*
|
||||||
|
* Check for any outstanding load for the data represented by @key. If there
|
||||||
|
* is already a request pending, append it to that request to avoid loading
|
||||||
|
* the data multiple times.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE iff there is already a request pending
|
||||||
|
*/
|
||||||
|
static gboolean
|
||||||
|
create_texture_and_ensure_request (ShellTextureCache *cache,
|
||||||
|
CacheKey *key,
|
||||||
|
AsyncTextureLoadData **request,
|
||||||
|
ClutterActor **texture)
|
||||||
|
{
|
||||||
|
CoglHandle texdata;
|
||||||
|
AsyncTextureLoadData *pending;
|
||||||
|
gboolean had_pending;
|
||||||
|
|
||||||
|
*texture = (ClutterActor *) create_default_texture (cache);
|
||||||
|
clutter_actor_set_size (*texture, key->size, key->size);
|
||||||
|
|
||||||
|
texdata = g_hash_table_lookup (cache->priv->keyed_cache, key);
|
||||||
|
|
||||||
|
if (texdata != NULL)
|
||||||
|
{
|
||||||
|
/* We had this cached already, just set the texture and we're done. */
|
||||||
|
set_texture_cogl_texture (CLUTTER_TEXTURE (*texture), texdata);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
pending = g_hash_table_lookup (cache->priv->outstanding_requests, key);
|
||||||
|
had_pending = pending != NULL;
|
||||||
|
|
||||||
|
if (pending == NULL)
|
||||||
|
{
|
||||||
|
/* Not cached and no pending request, create it */
|
||||||
|
*request = g_new0 (AsyncTextureLoadData, 1);
|
||||||
|
g_hash_table_insert (cache->priv->outstanding_requests, cache_key_dup (key), *request);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*request = pending;
|
||||||
|
|
||||||
|
/* Regardless of whether there was a pending request, prepend our texture here. */
|
||||||
|
(*request)->textures = g_slist_prepend ((*request)->textures, g_object_ref (*texture));
|
||||||
|
|
||||||
|
return had_pending;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* shell_texture_cache_load_gicon:
|
* shell_texture_cache_load_gicon:
|
||||||
*
|
*
|
||||||
@@ -885,44 +964,43 @@ shell_texture_cache_load_gicon (ShellTextureCache *cache,
|
|||||||
GIcon *icon,
|
GIcon *icon,
|
||||||
gint size)
|
gint size)
|
||||||
{
|
{
|
||||||
ClutterTexture *texture;
|
AsyncTextureLoadData *request;
|
||||||
CoglHandle texdata;
|
ClutterActor *texture;
|
||||||
CacheKey key;
|
CacheKey key;
|
||||||
|
GtkIconTheme *theme;
|
||||||
texture = create_default_texture (cache);
|
GtkIconInfo *info;
|
||||||
clutter_actor_set_size (CLUTTER_ACTOR (texture), size, size);
|
|
||||||
|
|
||||||
memset (&key, 0, sizeof(key));
|
memset (&key, 0, sizeof(key));
|
||||||
key.icon = icon;
|
key.icon = icon;
|
||||||
key.size = size;
|
key.size = size;
|
||||||
texdata = g_hash_table_lookup (cache->priv->keyed_cache, &key);
|
|
||||||
|
|
||||||
if (texdata == NULL)
|
if (create_texture_and_ensure_request (cache, &key, &request, &texture))
|
||||||
|
return texture;
|
||||||
|
|
||||||
|
/* Do theme lookups in the main thread to avoid thread-unsafety */
|
||||||
|
theme = gtk_icon_theme_get_default ();
|
||||||
|
|
||||||
|
info = gtk_icon_theme_lookup_by_gicon (theme, icon, size, GTK_ICON_LOOKUP_USE_BUILTIN);
|
||||||
|
if (info != NULL)
|
||||||
{
|
{
|
||||||
GtkIconTheme *theme;
|
/* hardcoded here for now; we should actually blow this away on
|
||||||
GtkIconInfo *info;
|
* icon theme changes probably */
|
||||||
|
request->policy = SHELL_TEXTURE_CACHE_POLICY_FOREVER;
|
||||||
|
request->icon = g_object_ref (icon);
|
||||||
|
request->icon_info = info;
|
||||||
|
request->width = request->height = size;
|
||||||
|
|
||||||
/* Do theme lookups in the main thread to avoid thread-unsafety */
|
load_icon_pixbuf_async (cache, icon, info, size, NULL, on_pixbuf_loaded, request);
|
||||||
theme = gtk_icon_theme_get_default ();
|
|
||||||
|
|
||||||
info = gtk_icon_theme_lookup_by_gicon (theme, icon, size, GTK_ICON_LOOKUP_USE_BUILTIN);
|
|
||||||
if (info != NULL)
|
|
||||||
{
|
|
||||||
AsyncTextureLoadData *data;
|
|
||||||
data = g_new0 (AsyncTextureLoadData, 1);
|
|
||||||
/* hardcoded here for now; we should actually blow this away on
|
|
||||||
* icon theme changes probably */
|
|
||||||
data->policy = SHELL_TEXTURE_CACHE_POLICY_FOREVER;
|
|
||||||
data->icon = g_object_ref (icon);
|
|
||||||
data->icon_info = info;
|
|
||||||
data->texture = g_object_ref (texture);
|
|
||||||
data->width = data->height = size;
|
|
||||||
load_icon_pixbuf_async (cache, icon, info, size, NULL, on_pixbuf_loaded, data);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
set_texture_cogl_texture (texture, texdata);
|
/* Blah; we failed to find the icon, but we've added our texture to the outstanding
|
||||||
|
* requests. In that case, just undo what create_texture_lookup_status did.
|
||||||
|
*/
|
||||||
|
g_slist_foreach (request->textures, (GFunc) g_object_unref, NULL);
|
||||||
|
g_slist_free (request->textures);
|
||||||
|
g_free (request);
|
||||||
|
g_hash_table_remove (cache->priv->outstanding_requests, &key);
|
||||||
}
|
}
|
||||||
|
|
||||||
return CLUTTER_ACTOR (texture);
|
return CLUTTER_ACTOR (texture);
|
||||||
@@ -983,7 +1061,7 @@ shell_texture_cache_load_uri_async (ShellTextureCache *cache,
|
|||||||
data->uri = g_strdup (uri);
|
data->uri = g_strdup (uri);
|
||||||
data->width = available_width;
|
data->width = available_width;
|
||||||
data->height = available_height;
|
data->height = available_height;
|
||||||
data->texture = g_object_ref (texture);
|
data->textures = g_slist_prepend (data->textures, g_object_ref (texture));
|
||||||
load_uri_pixbuf_async (cache, uri, available_width, available_height, NULL, on_pixbuf_loaded, data);
|
load_uri_pixbuf_async (cache, uri, available_width, available_height, NULL, on_pixbuf_loaded, data);
|
||||||
|
|
||||||
return CLUTTER_ACTOR (texture);
|
return CLUTTER_ACTOR (texture);
|
||||||
@@ -1106,7 +1184,7 @@ shell_texture_cache_load_thumbnail (ShellTextureCache *cache,
|
|||||||
data->thumbnail = TRUE;
|
data->thumbnail = TRUE;
|
||||||
data->width = size;
|
data->width = size;
|
||||||
data->height = size;
|
data->height = size;
|
||||||
data->texture = g_object_ref (texture);
|
data->textures = g_slist_prepend (data->textures, g_object_ref (texture));
|
||||||
load_thumbnail_async (cache, uri, mimetype, size, NULL, on_pixbuf_loaded, data);
|
load_thumbnail_async (cache, uri, mimetype, size, NULL, on_pixbuf_loaded, data);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1182,7 +1260,7 @@ shell_texture_cache_load_recent_thumbnail (ShellTextureCache *cache,
|
|||||||
data->recent_info = gtk_recent_info_ref (info);
|
data->recent_info = gtk_recent_info_ref (info);
|
||||||
data->width = size;
|
data->width = size;
|
||||||
data->height = size;
|
data->height = size;
|
||||||
data->texture = g_object_ref (texture);
|
data->textures = g_slist_prepend (data->textures, g_object_ref (texture));
|
||||||
load_recent_thumbnail_async (cache, info, size, NULL, on_pixbuf_loaded, data);
|
load_recent_thumbnail_async (cache, info, size, NULL, on_pixbuf_loaded, data);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1236,6 +1314,35 @@ shell_texture_cache_evict_recent_thumbnail (ShellTextureCache *cache,
|
|||||||
shell_texture_cache_evict_thumbnail (cache, gtk_recent_info_get_uri (info));
|
shell_texture_cache_evict_thumbnail (cache, gtk_recent_info_get_uri (info));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static size_t
|
||||||
|
pixbuf_byte_size (GdkPixbuf *pixbuf)
|
||||||
|
{
|
||||||
|
/* This bit translated from gtk+/gdk-pixbuf/gdk-pixbuf.c:gdk_pixbuf_copy. The comment
|
||||||
|
* there was:
|
||||||
|
*
|
||||||
|
* Calculate a semi-exact size. Here we copy with full rowstrides;
|
||||||
|
* maybe we should copy each row individually with the minimum
|
||||||
|
* rowstride?
|
||||||
|
*/
|
||||||
|
return (gdk_pixbuf_get_height (pixbuf) - 1) * gdk_pixbuf_get_rowstride (pixbuf) +
|
||||||
|
+ gdk_pixbuf_get_width (pixbuf) * ((gdk_pixbuf_get_n_channels (pixbuf)* gdk_pixbuf_get_bits_per_sample (pixbuf) + 7) / 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* shell_texture_cache_pixbuf_equal:
|
||||||
|
*
|
||||||
|
* Returns: %TRUE iff the given pixbufs are bytewise-equal
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
shell_texture_cache_pixbuf_equal (ShellTextureCache *cache, GdkPixbuf *a, GdkPixbuf *b)
|
||||||
|
{
|
||||||
|
size_t size_a = pixbuf_byte_size (a);
|
||||||
|
size_t size_b = pixbuf_byte_size (b);
|
||||||
|
if (size_a != size_b)
|
||||||
|
return FALSE;
|
||||||
|
return memcmp (gdk_pixbuf_get_pixels (a), gdk_pixbuf_get_pixels (b), size_a) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
static ShellTextureCache *instance = NULL;
|
static ShellTextureCache *instance = NULL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -79,4 +79,6 @@ ClutterActor *shell_texture_cache_load_uri_sync (ShellTextureCache *cache,
|
|||||||
int available_height,
|
int available_height,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
|
gboolean shell_texture_cache_pixbuf_equal (ShellTextureCache *cache, GdkPixbuf *a, GdkPixbuf *b);
|
||||||
|
|
||||||
#endif /* __SHELL_TEXTURE_CACHE_H__ */
|
#endif /* __SHELL_TEXTURE_CACHE_H__ */
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "shell-wm.h"
|
#include "shell-wm.h"
|
||||||
#include "shell-global.h"
|
#include "shell-global.h"
|
||||||
#include "shell-marshal.h"
|
#include "shell-marshal.h"
|
||||||
|
|
||||||
|
#include <keybindings.h>
|
||||||
|
|
||||||
struct _ShellWM {
|
struct _ShellWM {
|
||||||
GObject parent;
|
GObject parent;
|
||||||
|
|
||||||
@@ -27,7 +31,7 @@ enum
|
|||||||
SWITCH_WORKSPACE,
|
SWITCH_WORKSPACE,
|
||||||
KILL_SWITCH_WORKSPACE,
|
KILL_SWITCH_WORKSPACE,
|
||||||
|
|
||||||
BEGIN_ALT_TAB,
|
KEYBINDING,
|
||||||
|
|
||||||
LAST_SIGNAL
|
LAST_SIGNAL
|
||||||
};
|
};
|
||||||
@@ -42,7 +46,6 @@ static guint shell_wm_signals [LAST_SIGNAL] = { 0 };
|
|||||||
static void
|
static void
|
||||||
shell_wm_init (ShellWM *wm)
|
shell_wm_init (ShellWM *wm)
|
||||||
{
|
{
|
||||||
meta_alt_tab_handler_register (SHELL_TYPE_ALT_TAB_HANDLER);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -169,15 +172,32 @@ shell_wm_class_init (ShellWMClass *klass)
|
|||||||
NULL, NULL,
|
NULL, NULL,
|
||||||
g_cclosure_marshal_VOID__VOID,
|
g_cclosure_marshal_VOID__VOID,
|
||||||
G_TYPE_NONE, 0);
|
G_TYPE_NONE, 0);
|
||||||
shell_wm_signals[BEGIN_ALT_TAB] =
|
|
||||||
g_signal_new ("begin-alt-tab",
|
/**
|
||||||
|
* ShellWM::keybinding:
|
||||||
|
* @shellwm: the #ShellWM
|
||||||
|
* @binding: the keybinding name
|
||||||
|
* @window: for window keybindings, the #MetaWindow
|
||||||
|
* @backwards: for "reversible" keybindings, whether or not
|
||||||
|
* the backwards (Shifted) variant was invoked
|
||||||
|
*
|
||||||
|
* Emitted when a keybinding captured via
|
||||||
|
* shell_wm_takeover_keybinding() is invoked. The keybinding name
|
||||||
|
* (which has underscores, not hyphens) is also included as the
|
||||||
|
* detail of the signal name, so you can connect just specific
|
||||||
|
* keybindings.
|
||||||
|
*/
|
||||||
|
shell_wm_signals[KEYBINDING] =
|
||||||
|
g_signal_new ("keybinding",
|
||||||
G_TYPE_FROM_CLASS (klass),
|
G_TYPE_FROM_CLASS (klass),
|
||||||
G_SIGNAL_RUN_LAST,
|
G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
|
||||||
0,
|
0,
|
||||||
NULL, NULL,
|
NULL, NULL,
|
||||||
g_cclosure_marshal_VOID__OBJECT,
|
_shell_marshal_VOID__STRING_OBJECT_BOOLEAN,
|
||||||
G_TYPE_NONE, 1,
|
G_TYPE_NONE, 3,
|
||||||
META_TYPE_ALT_TAB_HANDLER);
|
G_TYPE_STRING,
|
||||||
|
META_TYPE_WINDOW,
|
||||||
|
G_TYPE_BOOLEAN);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -391,14 +411,6 @@ _shell_wm_destroy (ShellWM *wm,
|
|||||||
g_signal_emit (wm, shell_wm_signals[DESTROY], 0, actor);
|
g_signal_emit (wm, shell_wm_signals[DESTROY], 0, actor);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Called from shell-alttab.c */
|
|
||||||
void
|
|
||||||
_shell_wm_begin_alt_tab (ShellWM *wm,
|
|
||||||
ShellAltTabHandler *handler)
|
|
||||||
{
|
|
||||||
g_signal_emit (wm, shell_wm_signals[BEGIN_ALT_TAB], 0, handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* shell_wm_new:
|
* shell_wm_new:
|
||||||
* @plugin: the #MutterPlugin
|
* @plugin: the #MutterPlugin
|
||||||
@@ -417,3 +429,37 @@ shell_wm_new (MutterPlugin *plugin)
|
|||||||
|
|
||||||
return wm;
|
return wm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
shell_wm_key_handler (MetaDisplay *display,
|
||||||
|
MetaScreen *screen,
|
||||||
|
MetaWindow *window,
|
||||||
|
XEvent *event,
|
||||||
|
MetaKeyBinding *binding,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
ShellWM *wm = data;
|
||||||
|
gboolean backwards = (event->xkey.state & ShiftMask);
|
||||||
|
|
||||||
|
g_signal_emit (wm, shell_wm_signals[KEYBINDING],
|
||||||
|
g_quark_from_string (binding->name),
|
||||||
|
binding->name, window, backwards);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* shell_wm_takeover_keybinding:
|
||||||
|
* @wm: the #ShellWM
|
||||||
|
* @binding_name: a mutter keybinding name
|
||||||
|
*
|
||||||
|
* Tells mutter to forward keypresses for @binding_name to the shell
|
||||||
|
* rather than processing them internally. This will cause a
|
||||||
|
* #ShellWM::keybinding signal to be emitted when that key is pressed.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
shell_wm_takeover_keybinding (ShellWM *wm,
|
||||||
|
const char *binding_name)
|
||||||
|
{
|
||||||
|
meta_keybindings_set_custom_handler (binding_name,
|
||||||
|
shell_wm_key_handler,
|
||||||
|
wm, NULL);
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,8 +4,6 @@
|
|||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
#include <mutter-plugin.h>
|
#include <mutter-plugin.h>
|
||||||
|
|
||||||
#include "shell-alttab.h"
|
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
typedef struct _ShellWM ShellWM;
|
typedef struct _ShellWM ShellWM;
|
||||||
@@ -73,10 +71,9 @@ void _shell_wm_kill_effect (ShellWM *wm,
|
|||||||
MutterWindow *actor,
|
MutterWindow *actor,
|
||||||
gulong events);
|
gulong events);
|
||||||
|
|
||||||
/* Called by ShellAltTabHandler */
|
/* Keybinding stuff */
|
||||||
|
void shell_wm_takeover_keybinding (ShellWM *wm,
|
||||||
void _shell_wm_begin_alt_tab (ShellWM *wm,
|
const char *binding_name);
|
||||||
ShellAltTabHandler *handler);
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
|||||||
777
src/st/st-adjustment.c
Normal file
@@ -0,0 +1,777 @@
|
|||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
/*
|
||||||
|
* st-adjustment.c: Adjustment object
|
||||||
|
*
|
||||||
|
* Copyright (C) 2008 OpenedHand
|
||||||
|
* Copyright (c) 2009 Intel Corporation.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU Lesser General Public License,
|
||||||
|
* version 2.1, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT ANY
|
||||||
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Written by: Chris Lord <chris@openedhand.com>, inspired by GtkAdjustment
|
||||||
|
* Port to St by: Robert Staudinger <robsta@openedhand.com>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SECTION:st-adjustment
|
||||||
|
* @short_description: A GObject representing an adjustable bounded value
|
||||||
|
*
|
||||||
|
* The #StAdjustment object represents a range of values bounded between a
|
||||||
|
* minimum and maximum, together with step and page increments and a page size.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include <clutter/clutter.h>
|
||||||
|
|
||||||
|
#include "st-adjustment.h"
|
||||||
|
#include "st-marshal.h"
|
||||||
|
#include "st-private.h"
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (StAdjustment, st_adjustment, G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
#define ADJUSTMENT_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), ST_TYPE_ADJUSTMENT, StAdjustmentPrivate))
|
||||||
|
|
||||||
|
struct _StAdjustmentPrivate
|
||||||
|
{
|
||||||
|
/* Do not sanity-check values while constructing,
|
||||||
|
* not all properties may be set yet. */
|
||||||
|
gboolean is_constructing : 1;
|
||||||
|
|
||||||
|
gdouble lower;
|
||||||
|
gdouble upper;
|
||||||
|
gdouble value;
|
||||||
|
gdouble step_increment;
|
||||||
|
gdouble page_increment;
|
||||||
|
gdouble page_size;
|
||||||
|
|
||||||
|
/* For interpolation */
|
||||||
|
ClutterTimeline *interpolation;
|
||||||
|
gdouble old_position;
|
||||||
|
gdouble new_position;
|
||||||
|
|
||||||
|
/* For elasticity */
|
||||||
|
gboolean elastic;
|
||||||
|
guint bounce_source;
|
||||||
|
ClutterAlpha *bounce_alpha;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0,
|
||||||
|
|
||||||
|
PROP_LOWER,
|
||||||
|
PROP_UPPER,
|
||||||
|
PROP_VALUE,
|
||||||
|
PROP_STEP_INC,
|
||||||
|
PROP_PAGE_INC,
|
||||||
|
PROP_PAGE_SIZE,
|
||||||
|
|
||||||
|
PROP_ELASTIC,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
CHANGED,
|
||||||
|
|
||||||
|
LAST_SIGNAL
|
||||||
|
};
|
||||||
|
|
||||||
|
static guint signals[LAST_SIGNAL] = { 0, };
|
||||||
|
|
||||||
|
static gboolean st_adjustment_set_lower (StAdjustment *adjustment,
|
||||||
|
gdouble lower);
|
||||||
|
static gboolean st_adjustment_set_upper (StAdjustment *adjustment,
|
||||||
|
gdouble upper);
|
||||||
|
static gboolean st_adjustment_set_step_increment (StAdjustment *adjustment,
|
||||||
|
gdouble step);
|
||||||
|
static gboolean st_adjustment_set_page_increment (StAdjustment *adjustment,
|
||||||
|
gdouble page);
|
||||||
|
static gboolean st_adjustment_set_page_size (StAdjustment *adjustment,
|
||||||
|
gdouble size);
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_adjustment_constructed (GObject *object)
|
||||||
|
{
|
||||||
|
GObjectClass *g_class;
|
||||||
|
StAdjustment *self = ST_ADJUSTMENT (object);
|
||||||
|
|
||||||
|
g_class = G_OBJECT_CLASS (st_adjustment_parent_class);
|
||||||
|
/* The docs say we're suppose to chain up, but would crash without
|
||||||
|
* some extra care. */
|
||||||
|
if (g_class && g_class->constructed &&
|
||||||
|
g_class->constructed != st_adjustment_constructed)
|
||||||
|
{
|
||||||
|
g_class->constructed (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
ST_ADJUSTMENT (self)->priv->is_constructing = FALSE;
|
||||||
|
st_adjustment_clamp_page (self, self->priv->lower, self->priv->upper);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_adjustment_get_property (GObject *gobject,
|
||||||
|
guint prop_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
StAdjustmentPrivate *priv = ST_ADJUSTMENT (gobject)->priv;
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_LOWER:
|
||||||
|
g_value_set_double (value, priv->lower);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_UPPER:
|
||||||
|
g_value_set_double (value, priv->upper);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_VALUE:
|
||||||
|
g_value_set_double (value, priv->value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_STEP_INC:
|
||||||
|
g_value_set_double (value, priv->step_increment);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_PAGE_INC:
|
||||||
|
g_value_set_double (value, priv->page_increment);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_PAGE_SIZE:
|
||||||
|
g_value_set_double (value, priv->page_size);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_ELASTIC:
|
||||||
|
g_value_set_boolean (value, priv->elastic);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_adjustment_set_property (GObject *gobject,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
StAdjustment *adj = ST_ADJUSTMENT (gobject);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_LOWER:
|
||||||
|
st_adjustment_set_lower (adj, g_value_get_double (value));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_UPPER:
|
||||||
|
st_adjustment_set_upper (adj, g_value_get_double (value));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_VALUE:
|
||||||
|
st_adjustment_set_value (adj, g_value_get_double (value));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_STEP_INC:
|
||||||
|
st_adjustment_set_step_increment (adj, g_value_get_double (value));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_PAGE_INC:
|
||||||
|
st_adjustment_set_page_increment (adj, g_value_get_double (value));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_PAGE_SIZE:
|
||||||
|
st_adjustment_set_page_size (adj, g_value_get_double (value));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_ELASTIC:
|
||||||
|
st_adjustment_set_elastic (adj, g_value_get_boolean (value));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
stop_interpolation (StAdjustment *adjustment)
|
||||||
|
{
|
||||||
|
StAdjustmentPrivate *priv = adjustment->priv;
|
||||||
|
|
||||||
|
if (priv->interpolation)
|
||||||
|
{
|
||||||
|
clutter_timeline_stop (priv->interpolation);
|
||||||
|
g_object_unref (priv->interpolation);
|
||||||
|
priv->interpolation = NULL;
|
||||||
|
|
||||||
|
if (priv->bounce_alpha)
|
||||||
|
{
|
||||||
|
g_object_unref (priv->bounce_alpha);
|
||||||
|
priv->bounce_alpha = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->bounce_source)
|
||||||
|
{
|
||||||
|
g_source_remove (priv->bounce_source);
|
||||||
|
priv->bounce_source = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_adjustment_dispose (GObject *object)
|
||||||
|
{
|
||||||
|
stop_interpolation (ST_ADJUSTMENT (object));
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (st_adjustment_parent_class)->dispose (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_adjustment_class_init (StAdjustmentClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
g_type_class_add_private (klass, sizeof (StAdjustmentPrivate));
|
||||||
|
|
||||||
|
object_class->constructed = st_adjustment_constructed;
|
||||||
|
object_class->get_property = st_adjustment_get_property;
|
||||||
|
object_class->set_property = st_adjustment_set_property;
|
||||||
|
object_class->dispose = st_adjustment_dispose;
|
||||||
|
|
||||||
|
g_object_class_install_property (object_class,
|
||||||
|
PROP_LOWER,
|
||||||
|
g_param_spec_double ("lower",
|
||||||
|
"Lower",
|
||||||
|
"Lower bound",
|
||||||
|
-G_MAXDOUBLE,
|
||||||
|
G_MAXDOUBLE,
|
||||||
|
0.0,
|
||||||
|
ST_PARAM_READWRITE |
|
||||||
|
G_PARAM_CONSTRUCT));
|
||||||
|
g_object_class_install_property (object_class,
|
||||||
|
PROP_UPPER,
|
||||||
|
g_param_spec_double ("upper",
|
||||||
|
"Upper",
|
||||||
|
"Upper bound",
|
||||||
|
-G_MAXDOUBLE,
|
||||||
|
G_MAXDOUBLE,
|
||||||
|
0.0,
|
||||||
|
ST_PARAM_READWRITE |
|
||||||
|
G_PARAM_CONSTRUCT));
|
||||||
|
g_object_class_install_property (object_class,
|
||||||
|
PROP_VALUE,
|
||||||
|
g_param_spec_double ("value",
|
||||||
|
"Value",
|
||||||
|
"Current value",
|
||||||
|
-G_MAXDOUBLE,
|
||||||
|
G_MAXDOUBLE,
|
||||||
|
0.0,
|
||||||
|
ST_PARAM_READWRITE |
|
||||||
|
G_PARAM_CONSTRUCT));
|
||||||
|
g_object_class_install_property (object_class,
|
||||||
|
PROP_STEP_INC,
|
||||||
|
g_param_spec_double ("step-increment",
|
||||||
|
"Step Increment",
|
||||||
|
"Step increment",
|
||||||
|
0.0,
|
||||||
|
G_MAXDOUBLE,
|
||||||
|
0.0,
|
||||||
|
ST_PARAM_READWRITE |
|
||||||
|
G_PARAM_CONSTRUCT));
|
||||||
|
g_object_class_install_property (object_class,
|
||||||
|
PROP_PAGE_INC,
|
||||||
|
g_param_spec_double ("page-increment",
|
||||||
|
"Page Increment",
|
||||||
|
"Page increment",
|
||||||
|
0.0,
|
||||||
|
G_MAXDOUBLE,
|
||||||
|
0.0,
|
||||||
|
ST_PARAM_READWRITE |
|
||||||
|
G_PARAM_CONSTRUCT));
|
||||||
|
g_object_class_install_property (object_class,
|
||||||
|
PROP_PAGE_SIZE,
|
||||||
|
g_param_spec_double ("page-size",
|
||||||
|
"Page Size",
|
||||||
|
"Page size",
|
||||||
|
0.0,
|
||||||
|
G_MAXDOUBLE,
|
||||||
|
0.0,
|
||||||
|
ST_PARAM_READWRITE |
|
||||||
|
G_PARAM_CONSTRUCT));
|
||||||
|
g_object_class_install_property (object_class,
|
||||||
|
PROP_ELASTIC,
|
||||||
|
g_param_spec_boolean ("elastic",
|
||||||
|
"Elastic",
|
||||||
|
"Make interpolation "
|
||||||
|
"behave in an "
|
||||||
|
"'elastic' way and "
|
||||||
|
"stop clamping value.",
|
||||||
|
FALSE,
|
||||||
|
ST_PARAM_READWRITE |
|
||||||
|
G_PARAM_CONSTRUCT));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* StAdjustment::changed:
|
||||||
|
*
|
||||||
|
* Emitted when any of the adjustment values have changed
|
||||||
|
*/
|
||||||
|
signals[CHANGED] =
|
||||||
|
g_signal_new ("changed",
|
||||||
|
G_TYPE_FROM_CLASS (klass),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
G_STRUCT_OFFSET (StAdjustmentClass, changed),
|
||||||
|
NULL, NULL,
|
||||||
|
_st_marshal_VOID__VOID,
|
||||||
|
G_TYPE_NONE, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_adjustment_init (StAdjustment *self)
|
||||||
|
{
|
||||||
|
self->priv = ADJUSTMENT_PRIVATE (self);
|
||||||
|
|
||||||
|
self->priv->is_constructing = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
StAdjustment *
|
||||||
|
st_adjustment_new (gdouble value,
|
||||||
|
gdouble lower,
|
||||||
|
gdouble upper,
|
||||||
|
gdouble step_increment,
|
||||||
|
gdouble page_increment,
|
||||||
|
gdouble page_size)
|
||||||
|
{
|
||||||
|
return g_object_new (ST_TYPE_ADJUSTMENT,
|
||||||
|
"value", value,
|
||||||
|
"lower", lower,
|
||||||
|
"upper", upper,
|
||||||
|
"step-increment", step_increment,
|
||||||
|
"page-increment", page_increment,
|
||||||
|
"page-size", page_size,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
gdouble
|
||||||
|
st_adjustment_get_value (StAdjustment *adjustment)
|
||||||
|
{
|
||||||
|
StAdjustmentPrivate *priv;
|
||||||
|
|
||||||
|
g_return_val_if_fail (ST_IS_ADJUSTMENT (adjustment), 0);
|
||||||
|
|
||||||
|
priv = adjustment->priv;
|
||||||
|
|
||||||
|
if (priv->interpolation)
|
||||||
|
{
|
||||||
|
return MAX (priv->lower,
|
||||||
|
MIN (priv->upper - priv->page_size,
|
||||||
|
priv->new_position));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return priv->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
st_adjustment_set_value (StAdjustment *adjustment,
|
||||||
|
gdouble value)
|
||||||
|
{
|
||||||
|
StAdjustmentPrivate *priv;
|
||||||
|
|
||||||
|
g_return_if_fail (ST_IS_ADJUSTMENT (adjustment));
|
||||||
|
|
||||||
|
priv = adjustment->priv;
|
||||||
|
|
||||||
|
stop_interpolation (adjustment);
|
||||||
|
|
||||||
|
/* Defer clamp until after construction. */
|
||||||
|
if (!priv->is_constructing)
|
||||||
|
{
|
||||||
|
if (!priv->elastic)
|
||||||
|
value = CLAMP (value,
|
||||||
|
priv->lower,
|
||||||
|
MAX (priv->lower, priv->upper - priv->page_size));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->value != value)
|
||||||
|
{
|
||||||
|
priv->value = value;
|
||||||
|
|
||||||
|
g_object_notify (G_OBJECT (adjustment), "value");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
st_adjustment_clamp_page (StAdjustment *adjustment,
|
||||||
|
gdouble lower,
|
||||||
|
gdouble upper)
|
||||||
|
{
|
||||||
|
StAdjustmentPrivate *priv;
|
||||||
|
gboolean changed;
|
||||||
|
|
||||||
|
g_return_if_fail (ST_IS_ADJUSTMENT (adjustment));
|
||||||
|
|
||||||
|
priv = adjustment->priv;
|
||||||
|
|
||||||
|
stop_interpolation (adjustment);
|
||||||
|
|
||||||
|
lower = CLAMP (lower, priv->lower, priv->upper - priv->page_size);
|
||||||
|
upper = CLAMP (upper, priv->lower + priv->page_size, priv->upper);
|
||||||
|
|
||||||
|
changed = FALSE;
|
||||||
|
|
||||||
|
if (priv->value + priv->page_size > upper)
|
||||||
|
{
|
||||||
|
priv->value = upper - priv->page_size;
|
||||||
|
changed = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->value < lower)
|
||||||
|
{
|
||||||
|
priv->value = lower;
|
||||||
|
changed = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changed)
|
||||||
|
g_object_notify (G_OBJECT (adjustment), "value");
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
st_adjustment_set_lower (StAdjustment *adjustment,
|
||||||
|
gdouble lower)
|
||||||
|
{
|
||||||
|
StAdjustmentPrivate *priv = adjustment->priv;
|
||||||
|
|
||||||
|
if (priv->lower != lower)
|
||||||
|
{
|
||||||
|
priv->lower = lower;
|
||||||
|
|
||||||
|
g_signal_emit (adjustment, signals[CHANGED], 0);
|
||||||
|
|
||||||
|
g_object_notify (G_OBJECT (adjustment), "lower");
|
||||||
|
|
||||||
|
/* Defer clamp until after construction. */
|
||||||
|
if (!priv->is_constructing)
|
||||||
|
st_adjustment_clamp_page (adjustment, priv->lower, priv->upper);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
st_adjustment_set_upper (StAdjustment *adjustment,
|
||||||
|
gdouble upper)
|
||||||
|
{
|
||||||
|
StAdjustmentPrivate *priv = adjustment->priv;
|
||||||
|
|
||||||
|
if (priv->upper != upper)
|
||||||
|
{
|
||||||
|
priv->upper = upper;
|
||||||
|
|
||||||
|
g_signal_emit (adjustment, signals[CHANGED], 0);
|
||||||
|
|
||||||
|
g_object_notify (G_OBJECT (adjustment), "upper");
|
||||||
|
|
||||||
|
/* Defer clamp until after construction. */
|
||||||
|
if (!priv->is_constructing)
|
||||||
|
st_adjustment_clamp_page (adjustment, priv->lower, priv->upper);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
st_adjustment_set_step_increment (StAdjustment *adjustment,
|
||||||
|
gdouble step)
|
||||||
|
{
|
||||||
|
StAdjustmentPrivate *priv = adjustment->priv;
|
||||||
|
|
||||||
|
if (priv->step_increment != step)
|
||||||
|
{
|
||||||
|
priv->step_increment = step;
|
||||||
|
|
||||||
|
g_signal_emit (adjustment, signals[CHANGED], 0);
|
||||||
|
|
||||||
|
g_object_notify (G_OBJECT (adjustment), "step-increment");
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
st_adjustment_set_page_increment (StAdjustment *adjustment,
|
||||||
|
gdouble page)
|
||||||
|
{
|
||||||
|
StAdjustmentPrivate *priv = adjustment->priv;
|
||||||
|
|
||||||
|
if (priv->page_increment != page)
|
||||||
|
{
|
||||||
|
priv->page_increment = page;
|
||||||
|
|
||||||
|
g_signal_emit (adjustment, signals[CHANGED], 0);
|
||||||
|
|
||||||
|
g_object_notify (G_OBJECT (adjustment), "page-increment");
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
st_adjustment_set_page_size (StAdjustment *adjustment,
|
||||||
|
gdouble size)
|
||||||
|
{
|
||||||
|
StAdjustmentPrivate *priv = adjustment->priv;
|
||||||
|
|
||||||
|
if (priv->page_size != size)
|
||||||
|
{
|
||||||
|
priv->page_size = size;
|
||||||
|
|
||||||
|
g_signal_emit (adjustment, signals[CHANGED], 0);
|
||||||
|
|
||||||
|
g_object_notify (G_OBJECT (adjustment), "page_size");
|
||||||
|
|
||||||
|
/* Well explicitely clamp after construction. */
|
||||||
|
if (!priv->is_constructing)
|
||||||
|
st_adjustment_clamp_page (adjustment, priv->lower, priv->upper);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
st_adjustment_set_values (StAdjustment *adjustment,
|
||||||
|
gdouble value,
|
||||||
|
gdouble lower,
|
||||||
|
gdouble upper,
|
||||||
|
gdouble step_increment,
|
||||||
|
gdouble page_increment,
|
||||||
|
gdouble page_size)
|
||||||
|
{
|
||||||
|
StAdjustmentPrivate *priv;
|
||||||
|
gboolean emit_changed = FALSE;
|
||||||
|
|
||||||
|
g_return_if_fail (ST_IS_ADJUSTMENT (adjustment));
|
||||||
|
g_return_if_fail (page_size >= 0 && page_size <= G_MAXDOUBLE);
|
||||||
|
g_return_if_fail (step_increment >= 0 && step_increment <= G_MAXDOUBLE);
|
||||||
|
g_return_if_fail (page_increment >= 0 && page_increment <= G_MAXDOUBLE);
|
||||||
|
|
||||||
|
priv = adjustment->priv;
|
||||||
|
|
||||||
|
stop_interpolation (adjustment);
|
||||||
|
|
||||||
|
emit_changed = FALSE;
|
||||||
|
|
||||||
|
g_object_freeze_notify (G_OBJECT (adjustment));
|
||||||
|
|
||||||
|
emit_changed |= st_adjustment_set_lower (adjustment, lower);
|
||||||
|
emit_changed |= st_adjustment_set_upper (adjustment, upper);
|
||||||
|
emit_changed |= st_adjustment_set_step_increment (adjustment, step_increment);
|
||||||
|
emit_changed |= st_adjustment_set_page_increment (adjustment, page_increment);
|
||||||
|
emit_changed |= st_adjustment_set_page_size (adjustment, page_size);
|
||||||
|
|
||||||
|
if (value != priv->value)
|
||||||
|
{
|
||||||
|
st_adjustment_set_value (adjustment, value);
|
||||||
|
emit_changed = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (emit_changed)
|
||||||
|
g_signal_emit (G_OBJECT (adjustment), signals[CHANGED], 0);
|
||||||
|
|
||||||
|
g_object_thaw_notify (G_OBJECT (adjustment));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
st_adjustment_get_values (StAdjustment *adjustment,
|
||||||
|
gdouble *value,
|
||||||
|
gdouble *lower,
|
||||||
|
gdouble *upper,
|
||||||
|
gdouble *step_increment,
|
||||||
|
gdouble *page_increment,
|
||||||
|
gdouble *page_size)
|
||||||
|
{
|
||||||
|
StAdjustmentPrivate *priv;
|
||||||
|
|
||||||
|
g_return_if_fail (ST_IS_ADJUSTMENT (adjustment));
|
||||||
|
|
||||||
|
priv = adjustment->priv;
|
||||||
|
|
||||||
|
if (lower)
|
||||||
|
*lower = priv->lower;
|
||||||
|
|
||||||
|
if (upper)
|
||||||
|
*upper = priv->upper;
|
||||||
|
|
||||||
|
if (value)
|
||||||
|
*value = st_adjustment_get_value (adjustment);
|
||||||
|
|
||||||
|
if (step_increment)
|
||||||
|
*step_increment = priv->step_increment;
|
||||||
|
|
||||||
|
if (page_increment)
|
||||||
|
*page_increment = priv->page_increment;
|
||||||
|
|
||||||
|
if (page_size)
|
||||||
|
*page_size = priv->page_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
interpolation_new_frame_cb (ClutterTimeline *timeline,
|
||||||
|
guint msecs,
|
||||||
|
StAdjustment *adjustment)
|
||||||
|
{
|
||||||
|
StAdjustmentPrivate *priv = adjustment->priv;
|
||||||
|
|
||||||
|
priv->interpolation = NULL;
|
||||||
|
|
||||||
|
if (priv->elastic)
|
||||||
|
{
|
||||||
|
gdouble progress = clutter_alpha_get_alpha (priv->bounce_alpha) / 1.0;
|
||||||
|
gdouble dx = priv->old_position
|
||||||
|
+ (priv->new_position - priv->old_position)
|
||||||
|
* progress;
|
||||||
|
|
||||||
|
st_adjustment_set_value (adjustment, dx);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
st_adjustment_set_value (adjustment,
|
||||||
|
priv->old_position +
|
||||||
|
(priv->new_position - priv->old_position) *
|
||||||
|
clutter_timeline_get_progress (timeline));
|
||||||
|
|
||||||
|
priv->interpolation = timeline;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
interpolation_completed_cb (ClutterTimeline *timeline,
|
||||||
|
StAdjustment *adjustment)
|
||||||
|
{
|
||||||
|
StAdjustmentPrivate *priv = adjustment->priv;
|
||||||
|
|
||||||
|
stop_interpolation (adjustment);
|
||||||
|
st_adjustment_set_value (adjustment, priv->new_position);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Note, there's super-optimal code that does a similar thing in
|
||||||
|
* clutter-alpha.c
|
||||||
|
*
|
||||||
|
* Tried this instead of CLUTTER_ALPHA_SINE_INC, but I think SINE_INC looks
|
||||||
|
* better. Leaving code here in case this is revisited.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
static guint32
|
||||||
|
bounce_alpha_func (ClutterAlpha *alpha,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
ClutterFixed progress, angle;
|
||||||
|
ClutterTimeline *timeline = clutter_alpha_get_timeline (alpha);
|
||||||
|
|
||||||
|
progress = clutter_timeline_get_progressx (timeline);
|
||||||
|
angle = clutter_qmulx (CFX_PI_2 + CFX_PI_4/2, progress);
|
||||||
|
|
||||||
|
return clutter_sinx (angle) +
|
||||||
|
(CFX_ONE - clutter_sinx (CFX_PI_2 + CFX_PI_4/2));
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
st_adjustment_interpolate (StAdjustment *adjustment,
|
||||||
|
gdouble value,
|
||||||
|
guint duration)
|
||||||
|
{
|
||||||
|
StAdjustmentPrivate *priv = adjustment->priv;
|
||||||
|
|
||||||
|
stop_interpolation (adjustment);
|
||||||
|
|
||||||
|
if (duration <= 1)
|
||||||
|
{
|
||||||
|
st_adjustment_set_value (adjustment, value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->old_position = priv->value;
|
||||||
|
priv->new_position = value;
|
||||||
|
|
||||||
|
priv->interpolation = clutter_timeline_new (duration);
|
||||||
|
|
||||||
|
if (priv->elastic)
|
||||||
|
priv->bounce_alpha = clutter_alpha_new_full (priv->interpolation,
|
||||||
|
CLUTTER_LINEAR);
|
||||||
|
|
||||||
|
g_signal_connect (priv->interpolation,
|
||||||
|
"new-frame",
|
||||||
|
G_CALLBACK (interpolation_new_frame_cb),
|
||||||
|
adjustment);
|
||||||
|
g_signal_connect (priv->interpolation,
|
||||||
|
"completed",
|
||||||
|
G_CALLBACK (interpolation_completed_cb),
|
||||||
|
adjustment);
|
||||||
|
|
||||||
|
clutter_timeline_start (priv->interpolation);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
st_adjustment_get_elastic (StAdjustment *adjustment)
|
||||||
|
{
|
||||||
|
return adjustment->priv->elastic;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
st_adjustment_set_elastic (StAdjustment *adjustment,
|
||||||
|
gboolean elastic)
|
||||||
|
{
|
||||||
|
adjustment->priv->elastic = elastic;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
st_adjustment_clamp (StAdjustment *adjustment,
|
||||||
|
gboolean interpolate,
|
||||||
|
guint duration)
|
||||||
|
{
|
||||||
|
StAdjustmentPrivate *priv = adjustment->priv;
|
||||||
|
gdouble dest = priv->value;
|
||||||
|
|
||||||
|
if (priv->value < priv->lower)
|
||||||
|
dest = priv->lower;
|
||||||
|
|
||||||
|
if (priv->value > priv->upper - priv->page_size)
|
||||||
|
dest = priv->upper - priv->page_size;
|
||||||
|
|
||||||
|
if (dest != priv->value)
|
||||||
|
{
|
||||||
|
if (interpolate)
|
||||||
|
st_adjustment_interpolate (adjustment, dest, duration);
|
||||||
|
else
|
||||||
|
st_adjustment_set_value (adjustment, dest);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
122
src/st/st-adjustment.h
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
/*
|
||||||
|
* st-adjustment.h: Adjustment object
|
||||||
|
*
|
||||||
|
* Copyright 2008 OpenedHand
|
||||||
|
* Copyright 2009 Intel Corporation.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU Lesser General Public License,
|
||||||
|
* version 2.1, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT ANY
|
||||||
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Written by: Chris Lord <chris@openedhand.com>, inspired by GtkAdjustment
|
||||||
|
* Port to St by: Robert Staudinger <robsta@openedhand.com>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(ST_H_INSIDE) && !defined(ST_COMPILATION)
|
||||||
|
#error "Only <st/st.h> can be included directly.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __ST_ADJUSTMENT_H__
|
||||||
|
#define __ST_ADJUSTMENT_H__
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include <clutter/clutter.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define ST_TYPE_ADJUSTMENT (st_adjustment_get_type())
|
||||||
|
#define ST_ADJUSTMENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ST_TYPE_ADJUSTMENT, StAdjustment))
|
||||||
|
#define ST_IS_ADJUSTMENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ST_TYPE_ADJUSTMENT))
|
||||||
|
#define ST_ADJUSTMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), ST_TYPE_ADJUSTMENT, StAdjustmentClass))
|
||||||
|
#define ST_IS_ADJUSTMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ST_TYPE_ADJUSTMENT))
|
||||||
|
#define ST_ADJUSTMENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), ST_TYPE_ADJUSTMENT, StAdjustmentClass))
|
||||||
|
|
||||||
|
typedef struct _StAdjustment StAdjustment;
|
||||||
|
typedef struct _StAdjustmentPrivate StAdjustmentPrivate;
|
||||||
|
typedef struct _StAdjustmentClass StAdjustmentClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* StAdjustment:
|
||||||
|
*
|
||||||
|
* Class for handling an interval between to values. The contents of
|
||||||
|
* the #StAdjustment are private and should be accessed using the
|
||||||
|
* public API.
|
||||||
|
*/
|
||||||
|
struct _StAdjustment
|
||||||
|
{
|
||||||
|
/*< private >*/
|
||||||
|
GObject parent_instance;
|
||||||
|
|
||||||
|
StAdjustmentPrivate *priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* StAdjustmentClass
|
||||||
|
* @changed: Class handler for the ::changed signal.
|
||||||
|
*
|
||||||
|
* Base class for #StAdjustment.
|
||||||
|
*/
|
||||||
|
struct _StAdjustmentClass
|
||||||
|
{
|
||||||
|
/*< private >*/
|
||||||
|
GObjectClass parent_class;
|
||||||
|
|
||||||
|
/*< public >*/
|
||||||
|
void (* changed) (StAdjustment *adjustment);
|
||||||
|
};
|
||||||
|
|
||||||
|
GType st_adjustment_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
StAdjustment *st_adjustment_new (gdouble value,
|
||||||
|
gdouble lower,
|
||||||
|
gdouble upper,
|
||||||
|
gdouble step_increment,
|
||||||
|
gdouble page_increment,
|
||||||
|
gdouble page_size);
|
||||||
|
gdouble st_adjustment_get_value (StAdjustment *adjustment);
|
||||||
|
void st_adjustment_set_value (StAdjustment *adjustment,
|
||||||
|
gdouble value);
|
||||||
|
void st_adjustment_clamp_page (StAdjustment *adjustment,
|
||||||
|
gdouble lower,
|
||||||
|
gdouble upper);
|
||||||
|
void st_adjustment_set_values (StAdjustment *adjustment,
|
||||||
|
gdouble value,
|
||||||
|
gdouble lower,
|
||||||
|
gdouble upper,
|
||||||
|
gdouble step_increment,
|
||||||
|
gdouble page_increment,
|
||||||
|
gdouble page_size);
|
||||||
|
void st_adjustment_get_values (StAdjustment *adjustment,
|
||||||
|
gdouble *value,
|
||||||
|
gdouble *lower,
|
||||||
|
gdouble *upper,
|
||||||
|
gdouble *step_increment,
|
||||||
|
gdouble *page_increment,
|
||||||
|
gdouble *page_size);
|
||||||
|
|
||||||
|
void st_adjustment_interpolate (StAdjustment *adjustment,
|
||||||
|
gdouble value,
|
||||||
|
guint duration);
|
||||||
|
|
||||||
|
gboolean st_adjustment_get_elastic (StAdjustment *adjustment);
|
||||||
|
void st_adjustment_set_elastic (StAdjustment *adjustment,
|
||||||
|
gboolean elastic);
|
||||||
|
|
||||||
|
gboolean st_adjustment_clamp (StAdjustment *adjustment,
|
||||||
|
gboolean interpolate,
|
||||||
|
guint duration);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __ST_ADJUSTMENT_H__ */
|
||||||
748
src/st/st-bin.c
Normal file
@@ -0,0 +1,748 @@
|
|||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
/*
|
||||||
|
* st-bin.c: Basic container actor
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009 Intel Corporation.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU Lesser General Public License,
|
||||||
|
* version 2.1, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT ANY
|
||||||
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Written by: Emmanuele Bassi <ebassi@linux.intel.com>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SECTION:st-bin
|
||||||
|
* @short_description: a simple container with one actor
|
||||||
|
*
|
||||||
|
* #StBin is a simple container capable of having only one
|
||||||
|
* #ClutterActor as a child.
|
||||||
|
*
|
||||||
|
* #StBin inherits from #StWidget, so it is fully themable.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <clutter/clutter.h>
|
||||||
|
|
||||||
|
#include "st-bin.h"
|
||||||
|
#include "st-enum-types.h"
|
||||||
|
#include "st-private.h"
|
||||||
|
|
||||||
|
#define ST_BIN_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ST_TYPE_BIN, StBinPrivate))
|
||||||
|
|
||||||
|
struct _StBinPrivate
|
||||||
|
{
|
||||||
|
ClutterActor *child;
|
||||||
|
|
||||||
|
StAlign x_align;
|
||||||
|
StAlign y_align;
|
||||||
|
|
||||||
|
guint x_fill : 1;
|
||||||
|
guint y_fill : 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0,
|
||||||
|
|
||||||
|
PROP_CHILD,
|
||||||
|
PROP_X_ALIGN,
|
||||||
|
PROP_Y_ALIGN,
|
||||||
|
PROP_X_FILL,
|
||||||
|
PROP_Y_FILL
|
||||||
|
};
|
||||||
|
|
||||||
|
static void clutter_container_iface_init (ClutterContainerIface *iface);
|
||||||
|
|
||||||
|
G_DEFINE_TYPE_WITH_CODE (StBin, st_bin, ST_TYPE_WIDGET,
|
||||||
|
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTAINER,
|
||||||
|
clutter_container_iface_init));
|
||||||
|
|
||||||
|
void
|
||||||
|
_st_bin_get_align_factors (StBin *bin,
|
||||||
|
gdouble *x_align,
|
||||||
|
gdouble *y_align)
|
||||||
|
{
|
||||||
|
StBinPrivate *priv = bin->priv;
|
||||||
|
gdouble factor;
|
||||||
|
|
||||||
|
switch (priv->x_align)
|
||||||
|
{
|
||||||
|
case ST_ALIGN_START:
|
||||||
|
factor = 0.0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ST_ALIGN_MIDDLE:
|
||||||
|
factor = 0.5;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ST_ALIGN_END:
|
||||||
|
factor = 1.0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
factor = 0.0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x_align)
|
||||||
|
*x_align = factor;
|
||||||
|
|
||||||
|
switch (priv->y_align)
|
||||||
|
{
|
||||||
|
case ST_ALIGN_START:
|
||||||
|
factor = 0.0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ST_ALIGN_MIDDLE:
|
||||||
|
factor = 0.5;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ST_ALIGN_END:
|
||||||
|
factor = 1.0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
factor = 0.0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y_align)
|
||||||
|
*y_align = factor;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_bin_add (ClutterContainer *container,
|
||||||
|
ClutterActor *actor)
|
||||||
|
{
|
||||||
|
st_bin_set_child (ST_BIN (container), actor);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_bin_remove (ClutterContainer *container,
|
||||||
|
ClutterActor *actor)
|
||||||
|
{
|
||||||
|
StBinPrivate *priv = ST_BIN (container)->priv;
|
||||||
|
|
||||||
|
if (priv->child == actor)
|
||||||
|
st_bin_set_child (ST_BIN (container), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_bin_foreach (ClutterContainer *container,
|
||||||
|
ClutterCallback callback,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
StBinPrivate *priv = ST_BIN (container)->priv;
|
||||||
|
|
||||||
|
if (priv->child)
|
||||||
|
callback (priv->child, user_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_container_iface_init (ClutterContainerIface *iface)
|
||||||
|
{
|
||||||
|
iface->add = st_bin_add;
|
||||||
|
iface->remove = st_bin_remove;
|
||||||
|
iface->foreach = st_bin_foreach;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_bin_paint (ClutterActor *self)
|
||||||
|
{
|
||||||
|
StBinPrivate *priv = ST_BIN (self)->priv;
|
||||||
|
|
||||||
|
/* allow StWidget to paint the background */
|
||||||
|
CLUTTER_ACTOR_CLASS (st_bin_parent_class)->paint (self);
|
||||||
|
|
||||||
|
/* the pain our child */
|
||||||
|
if (priv->child)
|
||||||
|
clutter_actor_paint (priv->child);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_bin_pick (ClutterActor *self,
|
||||||
|
const ClutterColor *pick_color)
|
||||||
|
{
|
||||||
|
StBinPrivate *priv = ST_BIN (self)->priv;
|
||||||
|
|
||||||
|
/* get the default pick implementation */
|
||||||
|
CLUTTER_ACTOR_CLASS (st_bin_parent_class)->pick (self, pick_color);
|
||||||
|
|
||||||
|
if (priv->child)
|
||||||
|
clutter_actor_paint (priv->child);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_bin_allocate (ClutterActor *self,
|
||||||
|
const ClutterActorBox *box,
|
||||||
|
ClutterAllocationFlags flags)
|
||||||
|
{
|
||||||
|
StBinPrivate *priv = ST_BIN (self)->priv;
|
||||||
|
|
||||||
|
CLUTTER_ACTOR_CLASS (st_bin_parent_class)->allocate (self, box,
|
||||||
|
flags);
|
||||||
|
|
||||||
|
if (priv->child)
|
||||||
|
{
|
||||||
|
StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (self));
|
||||||
|
gfloat natural_width, natural_height;
|
||||||
|
gfloat min_width, min_height;
|
||||||
|
gfloat child_width, child_height;
|
||||||
|
gfloat available_width, available_height;
|
||||||
|
ClutterRequestMode request;
|
||||||
|
ClutterActorBox content_box;
|
||||||
|
ClutterActorBox allocation = { 0, };
|
||||||
|
gdouble x_align, y_align;
|
||||||
|
|
||||||
|
st_theme_node_get_content_box (theme_node, box, &content_box);
|
||||||
|
|
||||||
|
_st_bin_get_align_factors (ST_BIN (self), &x_align, &y_align);
|
||||||
|
|
||||||
|
available_width = content_box.x2 - content_box.x1;
|
||||||
|
available_height = content_box.y2 - content_box.y1;
|
||||||
|
|
||||||
|
if (available_width < 0)
|
||||||
|
available_width = 0;
|
||||||
|
|
||||||
|
if (available_height < 0)
|
||||||
|
available_height = 0;
|
||||||
|
|
||||||
|
if (priv->x_fill)
|
||||||
|
{
|
||||||
|
allocation.x1 = (int) content_box.x1;
|
||||||
|
allocation.x2 = (int) content_box.x2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->y_fill)
|
||||||
|
{
|
||||||
|
allocation.y1 = (int) content_box.y1;
|
||||||
|
allocation.y2 = (int) content_box.y2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if we are filling horizontally and vertically then we're done */
|
||||||
|
if (priv->x_fill && priv->y_fill)
|
||||||
|
{
|
||||||
|
clutter_actor_allocate (priv->child, &allocation, flags);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
request = CLUTTER_REQUEST_HEIGHT_FOR_WIDTH;
|
||||||
|
g_object_get (G_OBJECT (priv->child), "request-mode", &request, NULL);
|
||||||
|
|
||||||
|
if (request == CLUTTER_REQUEST_HEIGHT_FOR_WIDTH)
|
||||||
|
{
|
||||||
|
clutter_actor_get_preferred_width (priv->child, available_height,
|
||||||
|
&min_width,
|
||||||
|
&natural_width);
|
||||||
|
|
||||||
|
child_width = CLAMP (natural_width, min_width, available_width);
|
||||||
|
|
||||||
|
clutter_actor_get_preferred_height (priv->child, child_width,
|
||||||
|
&min_height,
|
||||||
|
&natural_height);
|
||||||
|
|
||||||
|
child_height = CLAMP (natural_height, min_height, available_height);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
clutter_actor_get_preferred_height (priv->child, available_width,
|
||||||
|
&min_height,
|
||||||
|
&natural_height);
|
||||||
|
|
||||||
|
child_height = CLAMP (natural_height, min_height, available_height);
|
||||||
|
|
||||||
|
clutter_actor_get_preferred_width (priv->child, child_height,
|
||||||
|
&min_width,
|
||||||
|
&natural_width);
|
||||||
|
|
||||||
|
child_width = CLAMP (natural_width, min_width, available_width);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!priv->x_fill)
|
||||||
|
{
|
||||||
|
allocation.x1 = content_box.x1 + (int) ((available_width - child_width) * x_align);
|
||||||
|
allocation.x2 = allocation.x1 + child_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!priv->y_fill)
|
||||||
|
{
|
||||||
|
allocation.y1 = content_box.y1 + (int) ((available_height - child_height) * y_align);
|
||||||
|
allocation.y2 = allocation.y1 + child_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
clutter_actor_allocate (priv->child, &allocation, flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_bin_get_preferred_width (ClutterActor *self,
|
||||||
|
gfloat for_height,
|
||||||
|
gfloat *min_width_p,
|
||||||
|
gfloat *natural_width_p)
|
||||||
|
{
|
||||||
|
StBinPrivate *priv = ST_BIN (self)->priv;
|
||||||
|
StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (self));
|
||||||
|
|
||||||
|
st_theme_node_adjust_for_height (theme_node, &for_height);
|
||||||
|
|
||||||
|
if (priv->child == NULL)
|
||||||
|
{
|
||||||
|
if (min_width_p)
|
||||||
|
*min_width_p = 0;
|
||||||
|
|
||||||
|
if (natural_width_p)
|
||||||
|
*natural_width_p = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
clutter_actor_get_preferred_width (priv->child, for_height,
|
||||||
|
min_width_p,
|
||||||
|
natural_width_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
st_theme_node_adjust_preferred_width (theme_node, min_width_p, natural_width_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_bin_get_preferred_height (ClutterActor *self,
|
||||||
|
gfloat for_width,
|
||||||
|
gfloat *min_height_p,
|
||||||
|
gfloat *natural_height_p)
|
||||||
|
{
|
||||||
|
StBinPrivate *priv = ST_BIN (self)->priv;
|
||||||
|
StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (self));
|
||||||
|
|
||||||
|
st_theme_node_adjust_for_width (theme_node, &for_width);
|
||||||
|
|
||||||
|
if (priv->child == NULL)
|
||||||
|
{
|
||||||
|
if (min_height_p)
|
||||||
|
*min_height_p = 0;
|
||||||
|
|
||||||
|
if (natural_height_p)
|
||||||
|
*natural_height_p = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
clutter_actor_get_preferred_height (priv->child, for_width,
|
||||||
|
min_height_p,
|
||||||
|
natural_height_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
st_theme_node_adjust_preferred_height (theme_node, min_height_p, natural_height_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_bin_dispose (GObject *gobject)
|
||||||
|
{
|
||||||
|
StBinPrivate *priv = ST_BIN (gobject)->priv;
|
||||||
|
|
||||||
|
if (priv->child)
|
||||||
|
{
|
||||||
|
clutter_actor_unparent (priv->child);
|
||||||
|
priv->child = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (st_bin_parent_class)->dispose (gobject);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_bin_set_property (GObject *gobject,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
StBin *bin = ST_BIN (gobject);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_CHILD:
|
||||||
|
st_bin_set_child (bin, g_value_get_object (value));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_X_ALIGN:
|
||||||
|
st_bin_set_alignment (bin,
|
||||||
|
g_value_get_enum (value),
|
||||||
|
bin->priv->y_align);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_Y_ALIGN:
|
||||||
|
st_bin_set_alignment (bin,
|
||||||
|
bin->priv->x_align,
|
||||||
|
g_value_get_enum (value));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_X_FILL:
|
||||||
|
st_bin_set_fill (bin,
|
||||||
|
g_value_get_boolean (value),
|
||||||
|
bin->priv->y_fill);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_Y_FILL:
|
||||||
|
st_bin_set_fill (bin,
|
||||||
|
bin->priv->y_fill,
|
||||||
|
g_value_get_boolean (value));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_bin_get_property (GObject *gobject,
|
||||||
|
guint prop_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
StBinPrivate *priv = ST_BIN (gobject)->priv;
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_CHILD:
|
||||||
|
g_value_set_object (value, priv->child);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_X_FILL:
|
||||||
|
g_value_set_boolean (value, priv->x_fill);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_Y_FILL:
|
||||||
|
g_value_set_boolean (value, priv->y_fill);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_X_ALIGN:
|
||||||
|
g_value_set_enum (value, priv->x_align);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_Y_ALIGN:
|
||||||
|
g_value_set_enum (value, priv->y_align);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_bin_class_init (StBinClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||||
|
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||||
|
GParamSpec *pspec;
|
||||||
|
|
||||||
|
g_type_class_add_private (klass, sizeof (StBinPrivate));
|
||||||
|
|
||||||
|
gobject_class->set_property = st_bin_set_property;
|
||||||
|
gobject_class->get_property = st_bin_get_property;
|
||||||
|
gobject_class->dispose = st_bin_dispose;
|
||||||
|
|
||||||
|
actor_class->get_preferred_width = st_bin_get_preferred_width;
|
||||||
|
actor_class->get_preferred_height = st_bin_get_preferred_height;
|
||||||
|
actor_class->allocate = st_bin_allocate;
|
||||||
|
actor_class->paint = st_bin_paint;
|
||||||
|
actor_class->pick = st_bin_pick;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* StBin:child:
|
||||||
|
*
|
||||||
|
* The child #ClutterActor of the #StBin container.
|
||||||
|
*/
|
||||||
|
pspec = g_param_spec_object ("child",
|
||||||
|
"Child",
|
||||||
|
"The child of the Bin",
|
||||||
|
CLUTTER_TYPE_ACTOR,
|
||||||
|
ST_PARAM_READWRITE);
|
||||||
|
g_object_class_install_property (gobject_class, PROP_CHILD, pspec);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* StBin:x-align:
|
||||||
|
*
|
||||||
|
* The horizontal alignment of the #StBin child.
|
||||||
|
*/
|
||||||
|
pspec = g_param_spec_enum ("x-align",
|
||||||
|
"X Align",
|
||||||
|
"The horizontal alignment",
|
||||||
|
ST_TYPE_ALIGN,
|
||||||
|
ST_ALIGN_MIDDLE,
|
||||||
|
ST_PARAM_READWRITE);
|
||||||
|
g_object_class_install_property (gobject_class, PROP_X_ALIGN, pspec);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* StBin:y-align:
|
||||||
|
*
|
||||||
|
* The vertical alignment of the #StBin child.
|
||||||
|
*/
|
||||||
|
pspec = g_param_spec_enum ("y-align",
|
||||||
|
"Y Align",
|
||||||
|
"The vertical alignment",
|
||||||
|
ST_TYPE_ALIGN,
|
||||||
|
ST_ALIGN_MIDDLE,
|
||||||
|
ST_PARAM_READWRITE);
|
||||||
|
g_object_class_install_property (gobject_class, PROP_Y_ALIGN, pspec);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* StBin:x-fill:
|
||||||
|
*
|
||||||
|
* Whether the child should fill the horizontal allocation
|
||||||
|
*/
|
||||||
|
pspec = g_param_spec_boolean ("x-fill",
|
||||||
|
"X Fill",
|
||||||
|
"Whether the child should fill the "
|
||||||
|
"horizontal allocation",
|
||||||
|
FALSE,
|
||||||
|
ST_PARAM_READWRITE);
|
||||||
|
g_object_class_install_property (gobject_class, PROP_X_FILL, pspec);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* StBin:y-fill:
|
||||||
|
*
|
||||||
|
* Whether the child should fill the vertical allocation
|
||||||
|
*/
|
||||||
|
pspec = g_param_spec_boolean ("y-fill",
|
||||||
|
"Y Fill",
|
||||||
|
"Whether the child should fill the "
|
||||||
|
"vertical allocation",
|
||||||
|
FALSE,
|
||||||
|
ST_PARAM_READWRITE);
|
||||||
|
g_object_class_install_property (gobject_class, PROP_Y_FILL, pspec);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_bin_init (StBin *bin)
|
||||||
|
{
|
||||||
|
bin->priv = ST_BIN_GET_PRIVATE (bin);
|
||||||
|
|
||||||
|
bin->priv->x_align = ST_ALIGN_MIDDLE;
|
||||||
|
bin->priv->y_align = ST_ALIGN_MIDDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* st_bin_new:
|
||||||
|
*
|
||||||
|
* Creates a new #StBin, a simple container for one child.
|
||||||
|
*
|
||||||
|
* Return value: the newly created #StBin actor
|
||||||
|
*/
|
||||||
|
StWidget *
|
||||||
|
st_bin_new (void)
|
||||||
|
{
|
||||||
|
return g_object_new (ST_TYPE_BIN, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* st_bin_set_child:
|
||||||
|
* @bin: a #StBin
|
||||||
|
* @child: a #ClutterActor, or %NULL
|
||||||
|
*
|
||||||
|
* Sets @child as the child of @bin.
|
||||||
|
*
|
||||||
|
* If @bin already has a child, the previous child is removed.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
st_bin_set_child (StBin *bin,
|
||||||
|
ClutterActor *child)
|
||||||
|
{
|
||||||
|
StBinPrivate *priv;
|
||||||
|
|
||||||
|
g_return_if_fail (ST_IS_BIN (bin));
|
||||||
|
g_return_if_fail (child == NULL || CLUTTER_IS_ACTOR (child));
|
||||||
|
|
||||||
|
priv = bin->priv;
|
||||||
|
|
||||||
|
if (priv->child == child)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (priv->child)
|
||||||
|
{
|
||||||
|
ClutterActor *old_child = priv->child;
|
||||||
|
|
||||||
|
g_object_ref (old_child);
|
||||||
|
|
||||||
|
priv->child = NULL;
|
||||||
|
clutter_actor_unparent (old_child);
|
||||||
|
|
||||||
|
g_signal_emit_by_name (bin, "actor-removed", old_child);
|
||||||
|
|
||||||
|
g_object_unref (old_child);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (child)
|
||||||
|
{
|
||||||
|
priv->child = child;
|
||||||
|
clutter_actor_set_parent (child, CLUTTER_ACTOR (bin));
|
||||||
|
|
||||||
|
g_signal_emit_by_name (bin, "actor-added", priv->child);
|
||||||
|
}
|
||||||
|
|
||||||
|
clutter_actor_queue_relayout (CLUTTER_ACTOR (bin));
|
||||||
|
|
||||||
|
g_object_notify (G_OBJECT (bin), "child");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* st_bin_get_child:
|
||||||
|
* @bin: a #StBin
|
||||||
|
*
|
||||||
|
* Retrieves a pointer to the child of @bin.
|
||||||
|
*
|
||||||
|
* Return value: (transfer none): a #ClutterActor, or %NULL
|
||||||
|
*/
|
||||||
|
ClutterActor *
|
||||||
|
st_bin_get_child (StBin *bin)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (ST_IS_BIN (bin), NULL);
|
||||||
|
|
||||||
|
return bin->priv->child;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* st_bin_set_alignment:
|
||||||
|
* @bin: a #StBin
|
||||||
|
* @x_align: horizontal alignment
|
||||||
|
* @y_align: vertical alignment
|
||||||
|
*
|
||||||
|
* Sets the horizontal and vertical alignment of the child
|
||||||
|
* inside a #StBin.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
st_bin_set_alignment (StBin *bin,
|
||||||
|
StAlign x_align,
|
||||||
|
StAlign y_align)
|
||||||
|
{
|
||||||
|
StBinPrivate *priv;
|
||||||
|
gboolean changed = FALSE;
|
||||||
|
|
||||||
|
g_return_if_fail (ST_IS_BIN (bin));
|
||||||
|
|
||||||
|
priv = bin->priv;
|
||||||
|
|
||||||
|
g_object_freeze_notify (G_OBJECT (bin));
|
||||||
|
|
||||||
|
if (priv->x_align != x_align)
|
||||||
|
{
|
||||||
|
priv->x_align = x_align;
|
||||||
|
g_object_notify (G_OBJECT (bin), "x-align");
|
||||||
|
changed = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->y_align != y_align)
|
||||||
|
{
|
||||||
|
priv->y_align = y_align;
|
||||||
|
g_object_notify (G_OBJECT (bin), "y-align");
|
||||||
|
changed = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changed)
|
||||||
|
clutter_actor_queue_relayout (CLUTTER_ACTOR (bin));
|
||||||
|
|
||||||
|
g_object_thaw_notify (G_OBJECT (bin));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* st_bin_get_alignment:
|
||||||
|
* @bin: a #StBin
|
||||||
|
* @x_align: return location for the horizontal alignment, or %NULL
|
||||||
|
* @y_align: return location for the vertical alignment, or %NULL
|
||||||
|
*
|
||||||
|
* Retrieves the horizontal and vertical alignment of the child
|
||||||
|
* inside a #StBin, as set by st_bin_set_alignment().
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
st_bin_get_alignment (StBin *bin,
|
||||||
|
StAlign *x_align,
|
||||||
|
StAlign *y_align)
|
||||||
|
{
|
||||||
|
StBinPrivate *priv;
|
||||||
|
|
||||||
|
g_return_if_fail (ST_IS_BIN (bin));
|
||||||
|
|
||||||
|
priv = bin->priv;
|
||||||
|
|
||||||
|
if (x_align)
|
||||||
|
*x_align = priv->x_align;
|
||||||
|
|
||||||
|
if (y_align)
|
||||||
|
*y_align = priv->y_align;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* st_bin_set_fill:
|
||||||
|
* @bin: a #StBin
|
||||||
|
* @x_fill: %TRUE if the child should fill horizontally the @bin
|
||||||
|
* @y_fill: %TRUE if the child should fill vertically the @bin
|
||||||
|
*
|
||||||
|
* Sets whether the child of @bin should fill out the horizontal
|
||||||
|
* and/or vertical allocation of the parent
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
st_bin_set_fill (StBin *bin,
|
||||||
|
gboolean x_fill,
|
||||||
|
gboolean y_fill)
|
||||||
|
{
|
||||||
|
StBinPrivate *priv;
|
||||||
|
gboolean changed = FALSE;
|
||||||
|
|
||||||
|
g_return_if_fail (ST_IS_BIN (bin));
|
||||||
|
|
||||||
|
priv = bin->priv;
|
||||||
|
|
||||||
|
g_object_freeze_notify (G_OBJECT (bin));
|
||||||
|
|
||||||
|
if (priv->x_fill != x_fill)
|
||||||
|
{
|
||||||
|
priv->x_fill = x_fill;
|
||||||
|
changed = TRUE;
|
||||||
|
|
||||||
|
g_object_notify (G_OBJECT (bin), "x-fill");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->y_fill != y_fill)
|
||||||
|
{
|
||||||
|
priv->y_fill = y_fill;
|
||||||
|
changed = TRUE;
|
||||||
|
|
||||||
|
g_object_notify (G_OBJECT (bin), "y-fill");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changed)
|
||||||
|
clutter_actor_queue_relayout (CLUTTER_ACTOR (bin));
|
||||||
|
|
||||||
|
g_object_thaw_notify (G_OBJECT (bin));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* st_bin_get_fill:
|
||||||
|
* @bin: a #StBin
|
||||||
|
* @x_fill: (out): return location for the horizontal fill, or %NULL
|
||||||
|
* @y_fill: (out): return location for the vertical fill, or %NULL
|
||||||
|
*
|
||||||
|
* Retrieves the horizontal and vertical fill settings
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
st_bin_get_fill (StBin *bin,
|
||||||
|
gboolean *x_fill,
|
||||||
|
gboolean *y_fill)
|
||||||
|
{
|
||||||
|
g_return_if_fail (ST_IS_BIN (bin));
|
||||||
|
|
||||||
|
if (x_fill)
|
||||||
|
*x_fill = bin->priv->x_fill;
|
||||||
|
|
||||||
|
if (y_fill)
|
||||||
|
*y_fill = bin->priv->y_fill;
|
||||||
|
}
|
||||||
93
src/st/st-bin.h
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
/*
|
||||||
|
* st-bin.h: Basic container actor
|
||||||
|
*
|
||||||
|
* Copyright 2009, 2008 Intel Corporation.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU Lesser General Public License,
|
||||||
|
* version 2.1, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT ANY
|
||||||
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* Written by: Emmanuele Bassi <ebassi@linux.intel.com>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(ST_H_INSIDE) && !defined(ST_COMPILATION)
|
||||||
|
#error "Only <st/st.h> can be included directly.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __ST_BIN_H__
|
||||||
|
#define __ST_BIN_H__
|
||||||
|
|
||||||
|
#include <st/st-types.h>
|
||||||
|
#include <st/st-widget.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define ST_TYPE_BIN (st_bin_get_type ())
|
||||||
|
#define ST_BIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ST_TYPE_BIN, StBin))
|
||||||
|
#define ST_IS_BIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ST_TYPE_BIN))
|
||||||
|
#define ST_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), ST_TYPE_BIN, StBinClass))
|
||||||
|
#define ST_IS_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ST_TYPE_BIN))
|
||||||
|
#define ST_BIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), ST_TYPE_BIN, StBinClass))
|
||||||
|
|
||||||
|
typedef struct _StBin StBin;
|
||||||
|
typedef struct _StBinPrivate StBinPrivate;
|
||||||
|
typedef struct _StBinClass StBinClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* StBin:
|
||||||
|
*
|
||||||
|
* The #StBin struct contains only private data
|
||||||
|
*/
|
||||||
|
struct _StBin
|
||||||
|
{
|
||||||
|
/*< private >*/
|
||||||
|
StWidget parent_instance;
|
||||||
|
|
||||||
|
StBinPrivate *priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* StBinClass:
|
||||||
|
*
|
||||||
|
* The #StBinClass struct contains only private data
|
||||||
|
*/
|
||||||
|
struct _StBinClass
|
||||||
|
{
|
||||||
|
/*< private >*/
|
||||||
|
StWidgetClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType st_bin_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
StWidget * st_bin_new (void);
|
||||||
|
void st_bin_set_child (StBin *bin,
|
||||||
|
ClutterActor *child);
|
||||||
|
ClutterActor *st_bin_get_child (StBin *bin);
|
||||||
|
void st_bin_set_alignment (StBin *bin,
|
||||||
|
StAlign x_align,
|
||||||
|
StAlign y_align);
|
||||||
|
void st_bin_get_alignment (StBin *bin,
|
||||||
|
StAlign *x_align,
|
||||||
|
StAlign *y_align);
|
||||||
|
void st_bin_set_fill (StBin *bin,
|
||||||
|
gboolean x_fill,
|
||||||
|
gboolean y_fill);
|
||||||
|
void st_bin_get_fill (StBin *bin,
|
||||||
|
gboolean *x_fill,
|
||||||
|
gboolean *y_fill);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __ST_BIN_H__ */
|
||||||
92
src/st/st-border-image.c
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include "st-border-image.h"
|
||||||
|
|
||||||
|
struct _StBorderImage {
|
||||||
|
GObject parent;
|
||||||
|
|
||||||
|
char *filename;
|
||||||
|
int border_top;
|
||||||
|
int border_right;
|
||||||
|
int border_bottom;
|
||||||
|
int border_left;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _StBorderImageClass {
|
||||||
|
GObjectClass parent_class;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (StBorderImage, st_border_image, G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_border_image_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
StBorderImage *image = ST_BORDER_IMAGE (object);
|
||||||
|
|
||||||
|
g_free (image->filename);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (st_border_image_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_border_image_class_init (StBorderImageClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->finalize = st_border_image_finalize;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_border_image_init (StBorderImage *image)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
StBorderImage *
|
||||||
|
st_border_image_new (const char *filename,
|
||||||
|
int border_top,
|
||||||
|
int border_right,
|
||||||
|
int border_bottom,
|
||||||
|
int border_left)
|
||||||
|
{
|
||||||
|
StBorderImage *image;
|
||||||
|
|
||||||
|
image = g_object_new (ST_TYPE_BORDER_IMAGE, NULL);
|
||||||
|
|
||||||
|
image->filename = g_strdup (filename);
|
||||||
|
image->border_top = border_top;
|
||||||
|
image->border_right = border_right;
|
||||||
|
image->border_bottom = border_bottom;
|
||||||
|
image->border_left = border_left;
|
||||||
|
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
st_border_image_get_filename (StBorderImage *image)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (ST_IS_BORDER_IMAGE (image), NULL);
|
||||||
|
|
||||||
|
return image->filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
st_border_image_get_borders (StBorderImage *image,
|
||||||
|
int *border_top,
|
||||||
|
int *border_right,
|
||||||
|
int *border_bottom,
|
||||||
|
int *border_left)
|
||||||
|
{
|
||||||
|
g_return_if_fail (ST_IS_BORDER_IMAGE (image));
|
||||||
|
|
||||||
|
if (border_top)
|
||||||
|
*border_top = image->border_top;
|
||||||
|
if (border_right)
|
||||||
|
*border_right = image->border_right;
|
||||||
|
if (border_bottom)
|
||||||
|
*border_bottom = image->border_bottom;
|
||||||
|
if (border_left)
|
||||||
|
*border_left = image->border_left;
|
||||||
|
}
|
||||||
38
src/st/st-border-image.h
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
#ifndef __ST_BORDER_IMAGE_H__
|
||||||
|
#define __ST_BORDER_IMAGE_H__
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
/* A StBorderImage encapsulates an image with specified unscaled borders on each edge.
|
||||||
|
*/
|
||||||
|
typedef struct _StBorderImage StBorderImage;
|
||||||
|
typedef struct _StBorderImageClass StBorderImageClass;
|
||||||
|
|
||||||
|
#define ST_TYPE_BORDER_IMAGE (st_border_image_get_type ())
|
||||||
|
#define ST_BORDER_IMAGE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), ST_TYPE_BORDER_IMAGE, StBorderImage))
|
||||||
|
#define ST_BORDER_IMAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), ST_TYPE_BORDER_IMAGE, StBorderImageClass))
|
||||||
|
#define ST_IS_BORDER_IMAGE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), ST_TYPE_BORDER_IMAGE))
|
||||||
|
#define ST_IS_BORDER_IMAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ST_TYPE_BORDER_IMAGE))
|
||||||
|
#define ST_BORDER_IMAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), ST_TYPE_BORDER_IMAGE, StBorderImageClass))
|
||||||
|
|
||||||
|
GType st_border_image_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
StBorderImage *st_border_image_new (const char *filename,
|
||||||
|
int border_top,
|
||||||
|
int border_right,
|
||||||
|
int border_bottom,
|
||||||
|
int border_left);
|
||||||
|
|
||||||
|
const char *st_border_image_get_filename (StBorderImage *image);
|
||||||
|
void st_border_image_get_borders (StBorderImage *image,
|
||||||
|
int *border_top,
|
||||||
|
int *border_right,
|
||||||
|
int *border_bottom,
|
||||||
|
int *border_left);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __ST_BORDER_IMAGE_H__ */
|
||||||
190
src/st/st-box-layout-child.c
Normal file
@@ -0,0 +1,190 @@
|
|||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
/*
|
||||||
|
* st-box-layout-child.c: box layout child actor
|
||||||
|
*
|
||||||
|
* Copyright 2009 Intel Corporation
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU Lesser General Public License,
|
||||||
|
* version 2.1, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT ANY
|
||||||
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Written by: Thomas Wood <thomas.wood@intel.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SECTION:st-box-layout-child
|
||||||
|
* @short_description: meta data associated with a #StBoxLayout child.
|
||||||
|
*
|
||||||
|
* #StBoxLayoutChild is a #ClutterChildMeta implementation that stores the
|
||||||
|
* child properties for children inside a #StBoxLayout.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "st-box-layout-child.h"
|
||||||
|
#include "st-private.h"
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (StBoxLayoutChild, st_box_layout_child, CLUTTER_TYPE_CHILD_META)
|
||||||
|
|
||||||
|
#define BOX_LAYOUT_CHILD_PRIVATE(o) \
|
||||||
|
(G_TYPE_INSTANCE_GET_PRIVATE ((o), ST_TYPE_BOX_LAYOUT_CHILD, StBoxLayoutChildPrivate))
|
||||||
|
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0,
|
||||||
|
|
||||||
|
PROP_EXPAND,
|
||||||
|
PROP_X_FILL,
|
||||||
|
PROP_Y_FILL,
|
||||||
|
PROP_X_ALIGN,
|
||||||
|
PROP_Y_ALIGN
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_box_layout_child_get_property (GObject *object,
|
||||||
|
guint property_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
StBoxLayoutChild *child = ST_BOX_LAYOUT_CHILD (object);
|
||||||
|
|
||||||
|
switch (property_id)
|
||||||
|
{
|
||||||
|
case PROP_EXPAND:
|
||||||
|
g_value_set_boolean (value, child->expand);
|
||||||
|
break;
|
||||||
|
case PROP_X_FILL:
|
||||||
|
g_value_set_boolean (value, child->x_fill);
|
||||||
|
break;
|
||||||
|
case PROP_Y_FILL:
|
||||||
|
g_value_set_boolean (value, child->y_fill);
|
||||||
|
break;
|
||||||
|
case PROP_X_ALIGN:
|
||||||
|
g_value_set_enum (value, child->x_align);
|
||||||
|
break;
|
||||||
|
case PROP_Y_ALIGN:
|
||||||
|
g_value_set_enum (value, child->y_align);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_box_layout_child_set_property (GObject *object,
|
||||||
|
guint property_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
StBoxLayoutChild *child = ST_BOX_LAYOUT_CHILD (object);
|
||||||
|
StBoxLayout *box = ST_BOX_LAYOUT (CLUTTER_CHILD_META (object)->container);
|
||||||
|
|
||||||
|
switch (property_id)
|
||||||
|
{
|
||||||
|
case PROP_EXPAND:
|
||||||
|
child->expand = g_value_get_boolean (value);
|
||||||
|
break;
|
||||||
|
case PROP_X_FILL:
|
||||||
|
child->x_fill = g_value_get_boolean (value);
|
||||||
|
break;
|
||||||
|
case PROP_Y_FILL:
|
||||||
|
child->y_fill = g_value_get_boolean (value);
|
||||||
|
break;
|
||||||
|
case PROP_X_ALIGN:
|
||||||
|
child->x_align = g_value_get_enum (value);
|
||||||
|
break;
|
||||||
|
case PROP_Y_ALIGN:
|
||||||
|
child->y_align = g_value_get_enum (value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||||
|
}
|
||||||
|
|
||||||
|
clutter_actor_queue_relayout ((ClutterActor*) box);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_box_layout_child_dispose (GObject *object)
|
||||||
|
{
|
||||||
|
G_OBJECT_CLASS (st_box_layout_child_parent_class)->dispose (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_box_layout_child_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
G_OBJECT_CLASS (st_box_layout_child_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_box_layout_child_class_init (StBoxLayoutChildClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
GParamSpec *pspec;
|
||||||
|
|
||||||
|
object_class->get_property = st_box_layout_child_get_property;
|
||||||
|
object_class->set_property = st_box_layout_child_set_property;
|
||||||
|
object_class->dispose = st_box_layout_child_dispose;
|
||||||
|
object_class->finalize = st_box_layout_child_finalize;
|
||||||
|
|
||||||
|
|
||||||
|
pspec = g_param_spec_boolean ("expand", "Expand",
|
||||||
|
"Allocate the child extra space",
|
||||||
|
FALSE,
|
||||||
|
ST_PARAM_READWRITE);
|
||||||
|
g_object_class_install_property (object_class, PROP_EXPAND, pspec);
|
||||||
|
|
||||||
|
pspec = g_param_spec_boolean ("x-fill", "x-fill",
|
||||||
|
"Whether the child should receive priority "
|
||||||
|
"when the container is allocating spare space "
|
||||||
|
"on the horizontal axis",
|
||||||
|
TRUE,
|
||||||
|
ST_PARAM_READWRITE);
|
||||||
|
g_object_class_install_property (object_class, PROP_X_FILL, pspec);
|
||||||
|
|
||||||
|
pspec = g_param_spec_boolean ("y-fill", "y-fill",
|
||||||
|
"Whether the child should receive priority "
|
||||||
|
"when the container is allocating spare space "
|
||||||
|
"on the vertical axis",
|
||||||
|
TRUE,
|
||||||
|
ST_PARAM_READWRITE);
|
||||||
|
g_object_class_install_property (object_class, PROP_Y_FILL, pspec);
|
||||||
|
|
||||||
|
pspec = g_param_spec_enum ("x-align",
|
||||||
|
"X Alignment",
|
||||||
|
"X alignment of the widget within the cell",
|
||||||
|
ST_TYPE_ALIGN,
|
||||||
|
ST_ALIGN_MIDDLE,
|
||||||
|
ST_PARAM_READWRITE);
|
||||||
|
g_object_class_install_property (object_class, PROP_X_ALIGN, pspec);
|
||||||
|
|
||||||
|
pspec = g_param_spec_enum ("y-align",
|
||||||
|
"Y Alignment",
|
||||||
|
"Y alignment of the widget within the cell",
|
||||||
|
ST_TYPE_ALIGN,
|
||||||
|
ST_ALIGN_MIDDLE,
|
||||||
|
ST_PARAM_READWRITE);
|
||||||
|
g_object_class_install_property (object_class, PROP_Y_ALIGN, pspec);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_box_layout_child_init (StBoxLayoutChild *self)
|
||||||
|
{
|
||||||
|
self->expand = FALSE;
|
||||||
|
|
||||||
|
self->x_fill = TRUE;
|
||||||
|
self->y_fill = TRUE;
|
||||||
|
|
||||||
|
self->x_align = ST_ALIGN_MIDDLE;
|
||||||
|
self->y_align = ST_ALIGN_MIDDLE;
|
||||||
|
}
|
||||||
|
|
||||||
85
src/st/st-box-layout-child.h
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
/*
|
||||||
|
* st-box-layout-child.h: box layout child actor
|
||||||
|
*
|
||||||
|
* Copyright 2009 Intel Corporation
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU Lesser General Public License,
|
||||||
|
* version 2.1, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT ANY
|
||||||
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Written by: Thomas Wood <thomas.wood@intel.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _ST_BOX_LAYOUT_CHILD_H
|
||||||
|
#define _ST_BOX_LAYOUT_CHILD_H
|
||||||
|
|
||||||
|
#include <clutter/clutter.h>
|
||||||
|
#include "st-enum-types.h"
|
||||||
|
#include "st-box-layout.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define ST_TYPE_BOX_LAYOUT_CHILD st_box_layout_child_get_type()
|
||||||
|
|
||||||
|
#define ST_BOX_LAYOUT_CHILD(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_CAST ((obj), \
|
||||||
|
ST_TYPE_BOX_LAYOUT_CHILD, StBoxLayoutChild))
|
||||||
|
|
||||||
|
#define ST_BOX_LAYOUT_CHILD_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_CAST ((klass), \
|
||||||
|
ST_TYPE_BOX_LAYOUT_CHILD, StBoxLayoutChildClass))
|
||||||
|
|
||||||
|
#define ST_IS_BOX_LAYOUT_CHILD(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
|
||||||
|
ST_TYPE_BOX_LAYOUT_CHILD))
|
||||||
|
|
||||||
|
#define ST_IS_BOX_LAYOUT_CHILD_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_TYPE ((klass), \
|
||||||
|
ST_TYPE_BOX_LAYOUT_CHILD))
|
||||||
|
|
||||||
|
#define ST_BOX_LAYOUT_CHILD_GET_CLASS(obj) \
|
||||||
|
(G_TYPE_INSTANCE_GET_CLASS ((obj), \
|
||||||
|
ST_TYPE_BOX_LAYOUT_CHILD, StBoxLayoutChildClass))
|
||||||
|
|
||||||
|
typedef struct _StBoxLayoutChild StBoxLayoutChild;
|
||||||
|
typedef struct _StBoxLayoutChildClass StBoxLayoutChildClass;
|
||||||
|
typedef struct _StBoxLayoutChildPrivate StBoxLayoutChildPrivate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* StBoxLayoutChild:
|
||||||
|
*
|
||||||
|
* The contents of this structure are private and should only be accessed
|
||||||
|
* through the public API.
|
||||||
|
*/
|
||||||
|
struct _StBoxLayoutChild
|
||||||
|
{
|
||||||
|
/*< private >*/
|
||||||
|
ClutterChildMeta parent;
|
||||||
|
|
||||||
|
gboolean expand;
|
||||||
|
gboolean x_fill : 1;
|
||||||
|
gboolean y_fill : 1;
|
||||||
|
StAlign x_align;
|
||||||
|
StAlign y_align;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _StBoxLayoutChildClass
|
||||||
|
{
|
||||||
|
ClutterChildMetaClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType st_box_layout_child_get_type (void);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* _ST_BOX_LAYOUT_CHILD_H */
|
||||||
1227
src/st/st-box-layout.c
Normal file
94
src/st/st-box-layout.h
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
/*
|
||||||
|
* st-box-layout.h: box layout actor
|
||||||
|
*
|
||||||
|
* Copyright 2009 Intel Corporation.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU Lesser General Public License,
|
||||||
|
* version 2.1, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT ANY
|
||||||
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Written by: Thomas Wood <thomas.wood@intel.com>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(ST_H_INSIDE) && !defined(ST_COMPILATION)
|
||||||
|
#error "Only <st/st.h> can be included directly.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _ST_BOX_LAYOUT_H
|
||||||
|
#define _ST_BOX_LAYOUT_H
|
||||||
|
|
||||||
|
#include <st/st-widget.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define ST_TYPE_BOX_LAYOUT st_box_layout_get_type()
|
||||||
|
|
||||||
|
#define ST_BOX_LAYOUT(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_CAST ((obj), \
|
||||||
|
ST_TYPE_BOX_LAYOUT, StBoxLayout))
|
||||||
|
|
||||||
|
#define ST_BOX_LAYOUT_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_CAST ((klass), \
|
||||||
|
ST_TYPE_BOX_LAYOUT, StBoxLayoutClass))
|
||||||
|
|
||||||
|
#define ST_IS_BOX_LAYOUT(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
|
||||||
|
ST_TYPE_BOX_LAYOUT))
|
||||||
|
|
||||||
|
#define ST_IS_BOX_LAYOUT_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_TYPE ((klass), \
|
||||||
|
ST_TYPE_BOX_LAYOUT))
|
||||||
|
|
||||||
|
#define ST_BOX_LAYOUT_GET_CLASS(obj) \
|
||||||
|
(G_TYPE_INSTANCE_GET_CLASS ((obj), \
|
||||||
|
ST_TYPE_BOX_LAYOUT, StBoxLayoutClass))
|
||||||
|
|
||||||
|
typedef struct _StBoxLayout StBoxLayout;
|
||||||
|
typedef struct _StBoxLayoutClass StBoxLayoutClass;
|
||||||
|
typedef struct _StBoxLayoutPrivate StBoxLayoutPrivate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* StBoxLayout:
|
||||||
|
*
|
||||||
|
* The contents of this structure are private and should only be accessed
|
||||||
|
* through the public API.
|
||||||
|
*/
|
||||||
|
struct _StBoxLayout
|
||||||
|
{
|
||||||
|
/*< private >*/
|
||||||
|
StWidget parent;
|
||||||
|
|
||||||
|
StBoxLayoutPrivate *priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _StBoxLayoutClass
|
||||||
|
{
|
||||||
|
StWidgetClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType st_box_layout_get_type (void);
|
||||||
|
|
||||||
|
StWidget *st_box_layout_new (void);
|
||||||
|
|
||||||
|
void st_box_layout_set_vertical (StBoxLayout *box,
|
||||||
|
gboolean vertical);
|
||||||
|
gboolean st_box_layout_get_vertical (StBoxLayout *box);
|
||||||
|
|
||||||
|
void st_box_layout_set_pack_start (StBoxLayout *box,
|
||||||
|
gboolean pack_start);
|
||||||
|
gboolean st_box_layout_get_pack_start (StBoxLayout *box);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* _ST_BOX_LAYOUT_H */
|
||||||
693
src/st/st-button.c
Normal file
@@ -0,0 +1,693 @@
|
|||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
/*
|
||||||
|
* st-button.c: Plain button actor
|
||||||
|
*
|
||||||
|
* Copyright 2007 OpenedHand
|
||||||
|
* Copyright 2008, 2009 Intel Corporation.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU Lesser General Public License,
|
||||||
|
* version 2.1, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT ANY
|
||||||
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Written by: Emmanuele Bassi <ebassi@openedhand.com>
|
||||||
|
* Thomas Wood <thomas@linux.intel.com>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SECTION:st-button
|
||||||
|
* @short_description: Button widget
|
||||||
|
*
|
||||||
|
* A button widget with support for either a text label or icon, toggle mode
|
||||||
|
* and transitions effects between states.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
#include <clutter/clutter.h>
|
||||||
|
|
||||||
|
#include "st-button.h"
|
||||||
|
|
||||||
|
#include "st-marshal.h"
|
||||||
|
#include "st-texture-frame.h"
|
||||||
|
#include "st-texture-cache.h"
|
||||||
|
#include "st-private.h"
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0,
|
||||||
|
|
||||||
|
PROP_LABEL,
|
||||||
|
PROP_TOGGLE_MODE,
|
||||||
|
PROP_CHECKED,
|
||||||
|
PROP_TRANSITION_DURATION
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
CLICKED,
|
||||||
|
|
||||||
|
LAST_SIGNAL
|
||||||
|
};
|
||||||
|
|
||||||
|
#define ST_BUTTON_GET_PRIVATE(obj) \
|
||||||
|
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), ST_TYPE_BUTTON, StButtonPrivate))
|
||||||
|
|
||||||
|
struct _StButtonPrivate
|
||||||
|
{
|
||||||
|
gchar *text;
|
||||||
|
|
||||||
|
ClutterActor *old_bg;
|
||||||
|
gboolean old_bg_parented; /* TRUE if we have adopted old_bg */
|
||||||
|
|
||||||
|
guint8 old_opacity;
|
||||||
|
|
||||||
|
guint is_pressed : 1;
|
||||||
|
guint is_hover : 1;
|
||||||
|
guint is_checked : 1;
|
||||||
|
guint is_toggle : 1;
|
||||||
|
|
||||||
|
gint transition_duration;
|
||||||
|
|
||||||
|
ClutterAnimation *animation;
|
||||||
|
|
||||||
|
gint spacing;
|
||||||
|
};
|
||||||
|
|
||||||
|
static guint button_signals[LAST_SIGNAL] = { 0, };
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (StButton, st_button, ST_TYPE_BIN);
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_button_update_label_style (StButton *button)
|
||||||
|
{
|
||||||
|
ClutterActor *label;
|
||||||
|
StThemeNode *theme_node;
|
||||||
|
ClutterColor color;
|
||||||
|
const PangoFontDescription *font;
|
||||||
|
gchar *font_string = NULL;
|
||||||
|
|
||||||
|
label = st_bin_get_child ((StBin*) button);
|
||||||
|
|
||||||
|
/* check the child is really a label */
|
||||||
|
if (!CLUTTER_IS_TEXT (label))
|
||||||
|
return;
|
||||||
|
|
||||||
|
theme_node = st_widget_get_theme_node (ST_WIDGET (button));
|
||||||
|
|
||||||
|
st_theme_node_get_foreground_color (theme_node, &color);
|
||||||
|
clutter_text_set_color (CLUTTER_TEXT (label), &color);
|
||||||
|
|
||||||
|
font = st_theme_node_get_font (theme_node);
|
||||||
|
font_string = pango_font_description_to_string (font);
|
||||||
|
clutter_text_set_font_name (CLUTTER_TEXT (label), font_string);
|
||||||
|
g_free (font_string);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_button_dispose_old_bg (StButton *button)
|
||||||
|
{
|
||||||
|
StButtonPrivate *priv = button->priv;
|
||||||
|
|
||||||
|
if (priv->old_bg)
|
||||||
|
{
|
||||||
|
if (priv->old_bg_parented)
|
||||||
|
{
|
||||||
|
clutter_actor_unparent (priv->old_bg);
|
||||||
|
priv->old_bg_parented = FALSE;
|
||||||
|
}
|
||||||
|
g_object_unref (priv->old_bg);
|
||||||
|
priv->old_bg = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_animation_completed (ClutterAnimation *animation,
|
||||||
|
StButton *button)
|
||||||
|
{
|
||||||
|
st_button_dispose_old_bg (button);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_button_style_changed (StWidget *widget)
|
||||||
|
{
|
||||||
|
StButton *button = ST_BUTTON (widget);
|
||||||
|
StButtonPrivate *priv = button->priv;
|
||||||
|
StButtonClass *button_class = ST_BUTTON_GET_CLASS (button);
|
||||||
|
StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (button));
|
||||||
|
ClutterActor *bg_image;
|
||||||
|
double spacing;
|
||||||
|
|
||||||
|
st_button_dispose_old_bg (button);
|
||||||
|
|
||||||
|
bg_image = st_widget_get_border_image ((StWidget*) button);
|
||||||
|
if (bg_image)
|
||||||
|
button->priv->old_bg = g_object_ref (bg_image);
|
||||||
|
|
||||||
|
ST_WIDGET_CLASS (st_button_parent_class)->style_changed (widget);
|
||||||
|
|
||||||
|
spacing = 6;
|
||||||
|
st_theme_node_get_length (theme_node, "border-spacing", FALSE, &spacing);
|
||||||
|
priv->spacing = round (spacing);
|
||||||
|
|
||||||
|
/* update the label styling */
|
||||||
|
st_button_update_label_style (button);
|
||||||
|
|
||||||
|
/* run a transition if applicable */
|
||||||
|
if (button_class->transition)
|
||||||
|
{
|
||||||
|
button_class->transition (button, priv->old_bg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (priv->old_bg &&
|
||||||
|
(!st_widget_get_style_pseudo_class (widget)))
|
||||||
|
{
|
||||||
|
ClutterAnimation *animation;
|
||||||
|
if (!clutter_actor_get_parent (priv->old_bg))
|
||||||
|
{
|
||||||
|
clutter_actor_set_parent (priv->old_bg, (ClutterActor*) widget);
|
||||||
|
priv->old_bg_parented = TRUE;
|
||||||
|
}
|
||||||
|
if (priv->transition_duration > 0)
|
||||||
|
{
|
||||||
|
animation = clutter_actor_animate (priv->old_bg,
|
||||||
|
CLUTTER_LINEAR,
|
||||||
|
priv->transition_duration,
|
||||||
|
"opacity", 0,
|
||||||
|
NULL);
|
||||||
|
g_signal_connect (animation, "completed",
|
||||||
|
G_CALLBACK (st_animation_completed), button);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
st_button_dispose_old_bg (button);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_button_real_pressed (StButton *button)
|
||||||
|
{
|
||||||
|
st_widget_set_style_pseudo_class ((StWidget*) button, "active");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_button_real_released (StButton *button)
|
||||||
|
{
|
||||||
|
StButtonPrivate *priv = button->priv;
|
||||||
|
|
||||||
|
if (priv->is_checked)
|
||||||
|
st_widget_set_style_pseudo_class ((StWidget*) button, "checked");
|
||||||
|
else if (!priv->is_hover)
|
||||||
|
st_widget_set_style_pseudo_class ((StWidget*) button, NULL);
|
||||||
|
else
|
||||||
|
st_widget_set_style_pseudo_class ((StWidget*) button, "hover");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
st_button_button_press (ClutterActor *actor,
|
||||||
|
ClutterButtonEvent *event)
|
||||||
|
{
|
||||||
|
st_widget_hide_tooltip (ST_WIDGET (actor));
|
||||||
|
|
||||||
|
if (event->button == 1)
|
||||||
|
{
|
||||||
|
StButton *button = ST_BUTTON (actor);
|
||||||
|
StButtonClass *klass = ST_BUTTON_GET_CLASS (button);
|
||||||
|
|
||||||
|
button->priv->is_pressed = TRUE;
|
||||||
|
|
||||||
|
clutter_grab_pointer (actor);
|
||||||
|
|
||||||
|
if (klass->pressed)
|
||||||
|
klass->pressed (button);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
st_button_button_release (ClutterActor *actor,
|
||||||
|
ClutterButtonEvent *event)
|
||||||
|
{
|
||||||
|
if (event->button == 1)
|
||||||
|
{
|
||||||
|
StButton *button = ST_BUTTON (actor);
|
||||||
|
StButtonClass *klass = ST_BUTTON_GET_CLASS (button);
|
||||||
|
|
||||||
|
if (!button->priv->is_pressed)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
clutter_ungrab_pointer ();
|
||||||
|
|
||||||
|
if (button->priv->is_toggle)
|
||||||
|
{
|
||||||
|
st_button_set_checked (button, !button->priv->is_checked);
|
||||||
|
}
|
||||||
|
|
||||||
|
button->priv->is_pressed = FALSE;
|
||||||
|
|
||||||
|
if (klass->released)
|
||||||
|
klass->released (button);
|
||||||
|
|
||||||
|
g_signal_emit (button, button_signals[CLICKED], 0);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
st_button_enter (ClutterActor *actor,
|
||||||
|
ClutterCrossingEvent *event)
|
||||||
|
{
|
||||||
|
StButton *button = ST_BUTTON (actor);
|
||||||
|
|
||||||
|
if (!button->priv->is_checked)
|
||||||
|
st_widget_set_style_pseudo_class ((StWidget*) button, "hover");
|
||||||
|
|
||||||
|
button->priv->is_hover = 1;
|
||||||
|
|
||||||
|
return CLUTTER_ACTOR_CLASS (st_button_parent_class)->enter_event (actor, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
st_button_leave (ClutterActor *actor,
|
||||||
|
ClutterCrossingEvent *event)
|
||||||
|
{
|
||||||
|
StButton *button = ST_BUTTON (actor);
|
||||||
|
|
||||||
|
button->priv->is_hover = 0;
|
||||||
|
|
||||||
|
if (button->priv->is_pressed)
|
||||||
|
{
|
||||||
|
StButtonClass *klass = ST_BUTTON_GET_CLASS (button);
|
||||||
|
|
||||||
|
clutter_ungrab_pointer ();
|
||||||
|
|
||||||
|
button->priv->is_pressed = FALSE;
|
||||||
|
|
||||||
|
if (klass->released)
|
||||||
|
klass->released (button);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (button->priv->is_checked)
|
||||||
|
st_widget_set_style_pseudo_class ((StWidget*) button, "checked");
|
||||||
|
else
|
||||||
|
st_widget_set_style_pseudo_class ((StWidget*) button, NULL);
|
||||||
|
|
||||||
|
return CLUTTER_ACTOR_CLASS (st_button_parent_class)->leave_event (actor, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_button_set_property (GObject *gobject,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
StButton *button = ST_BUTTON (gobject);
|
||||||
|
StButtonPrivate *priv = ST_BUTTON (gobject)->priv;
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_LABEL:
|
||||||
|
st_button_set_label (button, g_value_get_string (value));
|
||||||
|
break;
|
||||||
|
case PROP_TOGGLE_MODE:
|
||||||
|
st_button_set_toggle_mode (button, g_value_get_boolean (value));
|
||||||
|
break;
|
||||||
|
case PROP_CHECKED:
|
||||||
|
st_button_set_checked (button, g_value_get_boolean (value));
|
||||||
|
break;
|
||||||
|
case PROP_TRANSITION_DURATION:
|
||||||
|
priv->transition_duration = g_value_get_int (value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_button_get_property (GObject *gobject,
|
||||||
|
guint prop_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
StButtonPrivate *priv = ST_BUTTON (gobject)->priv;
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_LABEL:
|
||||||
|
g_value_set_string (value, priv->text);
|
||||||
|
break;
|
||||||
|
case PROP_TOGGLE_MODE:
|
||||||
|
g_value_set_boolean (value, priv->is_toggle);
|
||||||
|
break;
|
||||||
|
case PROP_CHECKED:
|
||||||
|
g_value_set_boolean (value, priv->is_checked);
|
||||||
|
break;
|
||||||
|
case PROP_TRANSITION_DURATION:
|
||||||
|
g_value_set_int (value, priv->transition_duration);
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_button_finalize (GObject *gobject)
|
||||||
|
{
|
||||||
|
StButtonPrivate *priv = ST_BUTTON (gobject)->priv;
|
||||||
|
|
||||||
|
g_free (priv->text);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (st_button_parent_class)->finalize (gobject);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_button_dispose (GObject *gobject)
|
||||||
|
{
|
||||||
|
st_button_dispose_old_bg (ST_BUTTON (gobject));
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (st_button_parent_class)->dispose (gobject);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_button_map (ClutterActor *self)
|
||||||
|
{
|
||||||
|
StButtonPrivate *priv = ST_BUTTON (self)->priv;
|
||||||
|
|
||||||
|
CLUTTER_ACTOR_CLASS (st_button_parent_class)->map (self);
|
||||||
|
|
||||||
|
if (priv->old_bg && priv->old_bg_parented)
|
||||||
|
clutter_actor_map (priv->old_bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_button_unmap (ClutterActor *self)
|
||||||
|
{
|
||||||
|
StButtonPrivate *priv = ST_BUTTON (self)->priv;
|
||||||
|
|
||||||
|
CLUTTER_ACTOR_CLASS (st_button_parent_class)->unmap (self);
|
||||||
|
|
||||||
|
if (priv->old_bg && priv->old_bg_parented)
|
||||||
|
clutter_actor_unmap (priv->old_bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_button_draw_background (StWidget *widget)
|
||||||
|
{
|
||||||
|
StButtonPrivate *priv;
|
||||||
|
|
||||||
|
ST_WIDGET_CLASS (st_button_parent_class)->draw_background (widget);
|
||||||
|
|
||||||
|
priv = ST_BUTTON (widget)->priv;
|
||||||
|
|
||||||
|
if (priv->old_bg && priv->old_bg_parented)
|
||||||
|
clutter_actor_paint (priv->old_bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_button_class_init (StButtonClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||||
|
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||||
|
StWidgetClass *widget_class = ST_WIDGET_CLASS (klass);
|
||||||
|
GParamSpec *pspec;
|
||||||
|
|
||||||
|
g_type_class_add_private (klass, sizeof (StButtonPrivate));
|
||||||
|
|
||||||
|
klass->pressed = st_button_real_pressed;
|
||||||
|
klass->released = st_button_real_released;
|
||||||
|
|
||||||
|
gobject_class->set_property = st_button_set_property;
|
||||||
|
gobject_class->get_property = st_button_get_property;
|
||||||
|
gobject_class->dispose = st_button_dispose;
|
||||||
|
gobject_class->finalize = st_button_finalize;
|
||||||
|
|
||||||
|
actor_class->button_press_event = st_button_button_press;
|
||||||
|
actor_class->button_release_event = st_button_button_release;
|
||||||
|
actor_class->enter_event = st_button_enter;
|
||||||
|
actor_class->leave_event = st_button_leave;
|
||||||
|
|
||||||
|
actor_class->map = st_button_map;
|
||||||
|
actor_class->unmap = st_button_unmap;
|
||||||
|
|
||||||
|
widget_class->draw_background = st_button_draw_background;
|
||||||
|
widget_class->style_changed = st_button_style_changed;
|
||||||
|
|
||||||
|
pspec = g_param_spec_string ("label",
|
||||||
|
"Label",
|
||||||
|
"Label of the button",
|
||||||
|
NULL, G_PARAM_READWRITE);
|
||||||
|
g_object_class_install_property (gobject_class, PROP_LABEL, pspec);
|
||||||
|
|
||||||
|
pspec = g_param_spec_boolean ("toggle-mode",
|
||||||
|
"Toggle Mode",
|
||||||
|
"Enable or disable toggling",
|
||||||
|
FALSE, G_PARAM_READWRITE);
|
||||||
|
g_object_class_install_property (gobject_class, PROP_TOGGLE_MODE, pspec);
|
||||||
|
|
||||||
|
pspec = g_param_spec_boolean ("checked",
|
||||||
|
"Checked",
|
||||||
|
"Indicates if a toggle button is \"on\""
|
||||||
|
" or \"off\"",
|
||||||
|
FALSE, G_PARAM_READWRITE);
|
||||||
|
g_object_class_install_property (gobject_class, PROP_CHECKED, pspec);
|
||||||
|
|
||||||
|
pspec = g_param_spec_int ("transition-duration",
|
||||||
|
"Transition Duration",
|
||||||
|
"Duration of the state transition effect",
|
||||||
|
0, G_MAXINT, 120, G_PARAM_READWRITE);
|
||||||
|
g_object_class_install_property (gobject_class, PROP_TRANSITION_DURATION, pspec);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* StButton::clicked:
|
||||||
|
* @button: the object that received the signal
|
||||||
|
*
|
||||||
|
* Emitted when the user activates the button, either with a mouse press and
|
||||||
|
* release or with the keyboard.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button_signals[CLICKED] =
|
||||||
|
g_signal_new ("clicked",
|
||||||
|
G_TYPE_FROM_CLASS (klass),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
G_STRUCT_OFFSET (StButtonClass, clicked),
|
||||||
|
NULL, NULL,
|
||||||
|
_st_marshal_VOID__VOID,
|
||||||
|
G_TYPE_NONE, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_button_init (StButton *button)
|
||||||
|
{
|
||||||
|
button->priv = ST_BUTTON_GET_PRIVATE (button);
|
||||||
|
button->priv->transition_duration = 120;
|
||||||
|
button->priv->spacing = 6;
|
||||||
|
|
||||||
|
clutter_actor_set_reactive ((ClutterActor *) button, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* st_button_new:
|
||||||
|
*
|
||||||
|
* Create a new button
|
||||||
|
*
|
||||||
|
* Returns: a new #StButton
|
||||||
|
*/
|
||||||
|
StWidget *
|
||||||
|
st_button_new (void)
|
||||||
|
{
|
||||||
|
return g_object_new (ST_TYPE_BUTTON, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* st_button_new_with_label:
|
||||||
|
* @text: text to set the label to
|
||||||
|
*
|
||||||
|
* Create a new #StButton with the specified label
|
||||||
|
*
|
||||||
|
* Returns: a new #StButton
|
||||||
|
*/
|
||||||
|
StWidget *
|
||||||
|
st_button_new_with_label (const gchar *text)
|
||||||
|
{
|
||||||
|
return g_object_new (ST_TYPE_BUTTON, "label", text, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* st_button_get_label:
|
||||||
|
* @button: a #StButton
|
||||||
|
*
|
||||||
|
* Get the text displayed on the button
|
||||||
|
*
|
||||||
|
* Returns: the text for the button. This must not be freed by the application
|
||||||
|
*/
|
||||||
|
G_CONST_RETURN gchar *
|
||||||
|
st_button_get_label (StButton *button)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (ST_IS_BUTTON (button), NULL);
|
||||||
|
|
||||||
|
return button->priv->text;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* st_button_set_label:
|
||||||
|
* @button: a #Stbutton
|
||||||
|
* @text: text to set the label to
|
||||||
|
*
|
||||||
|
* Sets the text displayed on the button
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
st_button_set_label (StButton *button,
|
||||||
|
const gchar *text)
|
||||||
|
{
|
||||||
|
StButtonPrivate *priv;
|
||||||
|
ClutterActor *label;
|
||||||
|
|
||||||
|
g_return_if_fail (ST_IS_BUTTON (button));
|
||||||
|
|
||||||
|
priv = button->priv;
|
||||||
|
|
||||||
|
g_free (priv->text);
|
||||||
|
|
||||||
|
if (text)
|
||||||
|
priv->text = g_strdup (text);
|
||||||
|
else
|
||||||
|
priv->text = g_strdup ("");
|
||||||
|
|
||||||
|
label = st_bin_get_child ((StBin*) button);
|
||||||
|
|
||||||
|
if (label && CLUTTER_IS_TEXT (label))
|
||||||
|
{
|
||||||
|
clutter_text_set_text (CLUTTER_TEXT (label), priv->text);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
label = g_object_new (CLUTTER_TYPE_TEXT,
|
||||||
|
"text", priv->text,
|
||||||
|
"line-alignment", PANGO_ALIGN_CENTER,
|
||||||
|
"ellipsize", PANGO_ELLIPSIZE_END,
|
||||||
|
"use-markup", TRUE,
|
||||||
|
NULL);
|
||||||
|
st_bin_set_child ((StBin*) button, label);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fake a style change so that we reset the style properties on the label */
|
||||||
|
st_widget_style_changed (ST_WIDGET (button));
|
||||||
|
|
||||||
|
g_object_notify (G_OBJECT (button), "label");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* st_button_get_toggle_mode:
|
||||||
|
* @button: a #StButton
|
||||||
|
*
|
||||||
|
* Get the toggle mode status of the button.
|
||||||
|
*
|
||||||
|
* Returns: #TRUE if toggle mode is set, otherwise #FALSE
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
st_button_get_toggle_mode (StButton *button)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (ST_IS_BUTTON (button), FALSE);
|
||||||
|
|
||||||
|
return button->priv->is_toggle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* st_button_set_toggle_mode:
|
||||||
|
* @button: a #Stbutton
|
||||||
|
* @toggle: #TRUE or #FALSE
|
||||||
|
*
|
||||||
|
* Enables or disables toggle mode for the button. In toggle mode, the active
|
||||||
|
* state will be "toggled" when the user clicks the button.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
st_button_set_toggle_mode (StButton *button,
|
||||||
|
gboolean toggle)
|
||||||
|
{
|
||||||
|
g_return_if_fail (ST_IS_BUTTON (button));
|
||||||
|
|
||||||
|
button->priv->is_toggle = toggle;
|
||||||
|
|
||||||
|
g_object_notify (G_OBJECT (button), "toggle-mode");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* st_button_get_checked:
|
||||||
|
* @button: a #StButton
|
||||||
|
*
|
||||||
|
* Get the state of the button that is in toggle mode.
|
||||||
|
*
|
||||||
|
* Returns: #TRUE if the button is checked, or #FALSE if not
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
st_button_get_checked (StButton *button)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (ST_IS_BUTTON (button), FALSE);
|
||||||
|
|
||||||
|
return button->priv->is_checked;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* st_button_set_checked:
|
||||||
|
* @button: a #Stbutton
|
||||||
|
* @checked: #TRUE or #FALSE
|
||||||
|
*
|
||||||
|
* Sets the pressed state of the button. This is only really useful if the
|
||||||
|
* button has #toggle-mode mode set to #TRUE.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
st_button_set_checked (StButton *button,
|
||||||
|
gboolean checked)
|
||||||
|
{
|
||||||
|
g_return_if_fail (ST_IS_BUTTON (button));
|
||||||
|
|
||||||
|
if (button->priv->is_checked != checked)
|
||||||
|
{
|
||||||
|
button->priv->is_checked = checked;
|
||||||
|
|
||||||
|
if (checked)
|
||||||
|
st_widget_set_style_pseudo_class ((StWidget*) button, "checked");
|
||||||
|
else
|
||||||
|
if (button->priv->is_hover)
|
||||||
|
st_widget_set_style_pseudo_class ((StWidget*) button, "hover");
|
||||||
|
else
|
||||||
|
st_widget_set_style_pseudo_class ((StWidget*) button, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_notify (G_OBJECT (button), "checked");
|
||||||
|
}
|
||||||
94
src/st/st-button.h
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
/*
|
||||||
|
* st-button.h: Plain button actor
|
||||||
|
*
|
||||||
|
* Copyright 2007 OpenedHand
|
||||||
|
* Copyright 2008, 2009 Intel Corporation.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU Lesser General Public License,
|
||||||
|
* version 2.1, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT ANY
|
||||||
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* Written by: Emmanuele Bassi <ebassi@openedhand.com>
|
||||||
|
* Thomas Wood <thomas@linux.intel.com>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(ST_H_INSIDE) && !defined(ST_COMPILATION)
|
||||||
|
#error "Only <st/st.h> can be included directly.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __ST_BUTTON_H__
|
||||||
|
#define __ST_BUTTON_H__
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#include <st/st-bin.h>
|
||||||
|
|
||||||
|
#define ST_TYPE_BUTTON (st_button_get_type ())
|
||||||
|
#define ST_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ST_TYPE_BUTTON, StButton))
|
||||||
|
#define ST_IS_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ST_TYPE_BUTTON))
|
||||||
|
#define ST_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), ST_TYPE_BUTTON, StButtonClass))
|
||||||
|
#define ST_IS_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ST_TYPE_BUTTON))
|
||||||
|
#define ST_BUTTON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), ST_TYPE_BUTTON, StButtonClass))
|
||||||
|
|
||||||
|
typedef struct _StButton StButton;
|
||||||
|
typedef struct _StButtonPrivate StButtonPrivate;
|
||||||
|
typedef struct _StButtonClass StButtonClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* StButton:
|
||||||
|
*
|
||||||
|
* The contents of this structure is private and should only be accessed using
|
||||||
|
* the provided API.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct _StButton
|
||||||
|
{
|
||||||
|
/*< private >*/
|
||||||
|
StBin parent_instance;
|
||||||
|
|
||||||
|
StButtonPrivate *priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _StButtonClass
|
||||||
|
{
|
||||||
|
StBinClass parent_class;
|
||||||
|
|
||||||
|
/* vfuncs, not signals */
|
||||||
|
void (* pressed) (StButton *button);
|
||||||
|
void (* released) (StButton *button);
|
||||||
|
void (* transition) (StButton *button,
|
||||||
|
ClutterActor *old_bg);
|
||||||
|
|
||||||
|
/* signals */
|
||||||
|
void (* clicked) (StButton *button);
|
||||||
|
};
|
||||||
|
|
||||||
|
GType st_button_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
StWidget * st_button_new (void);
|
||||||
|
StWidget * st_button_new_with_label (const gchar *text);
|
||||||
|
G_CONST_RETURN gchar *st_button_get_label (StButton *button);
|
||||||
|
void st_button_set_label (StButton *button,
|
||||||
|
const gchar *text);
|
||||||
|
void st_button_set_toggle_mode (StButton *button,
|
||||||
|
gboolean toggle);
|
||||||
|
gboolean st_button_get_toggle_mode (StButton *button);
|
||||||
|
void st_button_set_checked (StButton *button,
|
||||||
|
gboolean checked);
|
||||||
|
gboolean st_button_get_checked (StButton *button);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __ST_BUTTON_H__ */
|
||||||
381
src/st/st-clipboard.c
Normal file
@@ -0,0 +1,381 @@
|
|||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
/*
|
||||||
|
* st-clipboard.c: clipboard object
|
||||||
|
*
|
||||||
|
* Copyright 2009 Intel Corporation.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU Lesser General Public License,
|
||||||
|
* version 2.1, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT ANY
|
||||||
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Written by: Thomas Wood <thomas.wood@intel.com>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SECTION:st-clipboard
|
||||||
|
* @short_description: a simple representation of the X clipboard
|
||||||
|
*
|
||||||
|
* #StCliboard is a very simple object representation of the clipboard
|
||||||
|
* available to applications. Text is always assumed to be UTF-8 and non-text
|
||||||
|
* items are not handled.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "st-clipboard.h"
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <X11/Xatom.h>
|
||||||
|
#include <clutter/x11/clutter-x11.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (StClipboard, st_clipboard, G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
#define CLIPBOARD_PRIVATE(o) \
|
||||||
|
(G_TYPE_INSTANCE_GET_PRIVATE ((o), ST_TYPE_CLIPBOARD, StClipboardPrivate))
|
||||||
|
|
||||||
|
struct _StClipboardPrivate
|
||||||
|
{
|
||||||
|
Window clipboard_window;
|
||||||
|
gchar *clipboard_text;
|
||||||
|
|
||||||
|
Atom *supported_targets;
|
||||||
|
gint n_targets;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct _EventFilterData EventFilterData;
|
||||||
|
struct _EventFilterData
|
||||||
|
{
|
||||||
|
StClipboard *clipboard;
|
||||||
|
StClipboardCallbackFunc callback;
|
||||||
|
gpointer user_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
static Atom __atom_clip = None;
|
||||||
|
static Atom __utf8_string = None;
|
||||||
|
static Atom __atom_targets = None;
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_clipboard_get_property (GObject *object,
|
||||||
|
guint property_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
switch (property_id)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_clipboard_set_property (GObject *object,
|
||||||
|
guint property_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
switch (property_id)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_clipboard_dispose (GObject *object)
|
||||||
|
{
|
||||||
|
G_OBJECT_CLASS (st_clipboard_parent_class)->dispose (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_clipboard_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
StClipboardPrivate *priv = ((StClipboard *) object)->priv;
|
||||||
|
|
||||||
|
g_free (priv->clipboard_text);
|
||||||
|
priv->clipboard_text = NULL;
|
||||||
|
|
||||||
|
g_free (priv->supported_targets);
|
||||||
|
priv->supported_targets = NULL;
|
||||||
|
priv->n_targets = 0;
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (st_clipboard_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ClutterX11FilterReturn
|
||||||
|
st_clipboard_provider (XEvent *xev,
|
||||||
|
ClutterEvent *cev,
|
||||||
|
StClipboard *clipboard)
|
||||||
|
{
|
||||||
|
XSelectionEvent notify_event;
|
||||||
|
XSelectionRequestEvent *req_event;
|
||||||
|
|
||||||
|
if (xev->type != SelectionRequest)
|
||||||
|
return CLUTTER_X11_FILTER_CONTINUE;
|
||||||
|
|
||||||
|
req_event = &xev->xselectionrequest;
|
||||||
|
|
||||||
|
clutter_x11_trap_x_errors ();
|
||||||
|
|
||||||
|
if (req_event->target == __atom_targets)
|
||||||
|
{
|
||||||
|
XChangeProperty (req_event->display,
|
||||||
|
req_event->requestor,
|
||||||
|
req_event->property,
|
||||||
|
XA_ATOM,
|
||||||
|
32,
|
||||||
|
PropModeReplace,
|
||||||
|
(guchar*) clipboard->priv->supported_targets,
|
||||||
|
clipboard->priv->n_targets);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
XChangeProperty (req_event->display,
|
||||||
|
req_event->requestor,
|
||||||
|
req_event->property,
|
||||||
|
req_event->target,
|
||||||
|
8,
|
||||||
|
PropModeReplace,
|
||||||
|
(guchar*) clipboard->priv->clipboard_text,
|
||||||
|
strlen (clipboard->priv->clipboard_text));
|
||||||
|
}
|
||||||
|
|
||||||
|
notify_event.type = SelectionNotify;
|
||||||
|
notify_event.display = req_event->display;
|
||||||
|
notify_event.requestor = req_event->requestor;
|
||||||
|
notify_event.selection = req_event->selection;
|
||||||
|
notify_event.target = req_event->target;
|
||||||
|
notify_event.time = req_event->time;
|
||||||
|
|
||||||
|
if (req_event->property == None)
|
||||||
|
notify_event.property = req_event->target;
|
||||||
|
else
|
||||||
|
notify_event.property = req_event->property;
|
||||||
|
|
||||||
|
/* notify the requestor that they have a copy of the selection */
|
||||||
|
XSendEvent (req_event->display, req_event->requestor, False, 0,
|
||||||
|
(XEvent *) ¬ify_event);
|
||||||
|
/* Make it happen non async */
|
||||||
|
XSync (clutter_x11_get_default_display(), FALSE);
|
||||||
|
|
||||||
|
clutter_x11_untrap_x_errors (); /* FIXME: Warn here on fail ? */
|
||||||
|
|
||||||
|
return CLUTTER_X11_FILTER_REMOVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_clipboard_class_init (StClipboardClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
g_type_class_add_private (klass, sizeof (StClipboardPrivate));
|
||||||
|
|
||||||
|
object_class->get_property = st_clipboard_get_property;
|
||||||
|
object_class->set_property = st_clipboard_set_property;
|
||||||
|
object_class->dispose = st_clipboard_dispose;
|
||||||
|
object_class->finalize = st_clipboard_finalize;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_clipboard_init (StClipboard *self)
|
||||||
|
{
|
||||||
|
Display *dpy;
|
||||||
|
StClipboardPrivate *priv;
|
||||||
|
|
||||||
|
priv = self->priv = CLIPBOARD_PRIVATE (self);
|
||||||
|
|
||||||
|
priv->clipboard_window =
|
||||||
|
XCreateSimpleWindow (clutter_x11_get_default_display (),
|
||||||
|
clutter_x11_get_root_window (),
|
||||||
|
-1, -1, 1, 1, 0, 0, 0);
|
||||||
|
|
||||||
|
dpy = clutter_x11_get_default_display ();
|
||||||
|
|
||||||
|
/* Only create once */
|
||||||
|
if (__atom_clip == None)
|
||||||
|
__atom_clip = XInternAtom (dpy, "CLIPBOARD", 0);
|
||||||
|
|
||||||
|
if (__utf8_string == None)
|
||||||
|
__utf8_string = XInternAtom (dpy, "UTF8_STRING", 0);
|
||||||
|
|
||||||
|
if (__atom_targets == None)
|
||||||
|
__atom_targets = XInternAtom (dpy, "TARGETS", 0);
|
||||||
|
|
||||||
|
priv->n_targets = 2;
|
||||||
|
priv->supported_targets = g_new (Atom, priv->n_targets);
|
||||||
|
|
||||||
|
priv->supported_targets[0] = __utf8_string;
|
||||||
|
priv->supported_targets[1] = __atom_targets;
|
||||||
|
|
||||||
|
clutter_x11_add_filter ((ClutterX11FilterFunc) st_clipboard_provider,
|
||||||
|
self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ClutterX11FilterReturn
|
||||||
|
st_clipboard_x11_event_filter (XEvent *xev,
|
||||||
|
ClutterEvent *cev,
|
||||||
|
EventFilterData *filter_data)
|
||||||
|
{
|
||||||
|
Atom actual_type;
|
||||||
|
int actual_format, result;
|
||||||
|
unsigned long nitems, bytes_after;
|
||||||
|
unsigned char *data = NULL;
|
||||||
|
|
||||||
|
if(xev->type != SelectionNotify)
|
||||||
|
return CLUTTER_X11_FILTER_CONTINUE;
|
||||||
|
|
||||||
|
if (xev->xselection.property == None)
|
||||||
|
{
|
||||||
|
/* clipboard empty */
|
||||||
|
filter_data->callback (filter_data->clipboard,
|
||||||
|
NULL,
|
||||||
|
filter_data->user_data);
|
||||||
|
|
||||||
|
clutter_x11_remove_filter ((ClutterX11FilterFunc) st_clipboard_x11_event_filter,
|
||||||
|
filter_data);
|
||||||
|
g_free (filter_data);
|
||||||
|
return CLUTTER_X11_FILTER_REMOVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
clutter_x11_trap_x_errors ();
|
||||||
|
|
||||||
|
result = XGetWindowProperty (xev->xselection.display,
|
||||||
|
xev->xselection.requestor,
|
||||||
|
xev->xselection.property,
|
||||||
|
0L, G_MAXINT,
|
||||||
|
True,
|
||||||
|
AnyPropertyType,
|
||||||
|
&actual_type,
|
||||||
|
&actual_format,
|
||||||
|
&nitems,
|
||||||
|
&bytes_after,
|
||||||
|
&data);
|
||||||
|
|
||||||
|
if (clutter_x11_untrap_x_errors () || result != Success)
|
||||||
|
{
|
||||||
|
/* FIXME: handle failure better */
|
||||||
|
g_warning ("Clipboard: prop retrival failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
filter_data->callback (filter_data->clipboard, (char*) data,
|
||||||
|
filter_data->user_data);
|
||||||
|
|
||||||
|
clutter_x11_remove_filter
|
||||||
|
((ClutterX11FilterFunc) st_clipboard_x11_event_filter,
|
||||||
|
filter_data);
|
||||||
|
|
||||||
|
g_free (filter_data);
|
||||||
|
|
||||||
|
if (data)
|
||||||
|
XFree (data);
|
||||||
|
|
||||||
|
return CLUTTER_X11_FILTER_REMOVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* st_clipboard_get_default:
|
||||||
|
*
|
||||||
|
* Get the global #StClipboard object that represents the clipboard.
|
||||||
|
*
|
||||||
|
* Returns: (transfer none): a #StClipboard owned by St and must not be
|
||||||
|
* unrefferenced or freed.
|
||||||
|
*/
|
||||||
|
StClipboard*
|
||||||
|
st_clipboard_get_default (void)
|
||||||
|
{
|
||||||
|
static StClipboard *default_clipboard = NULL;
|
||||||
|
|
||||||
|
if (!default_clipboard)
|
||||||
|
{
|
||||||
|
default_clipboard = g_object_new (ST_TYPE_CLIPBOARD, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return default_clipboard;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* st_clipboard_get_text:
|
||||||
|
* @clipboard: A #StCliboard
|
||||||
|
* @callback: function to be called when the text is retreived
|
||||||
|
* @user_data: data to be passed to the callback
|
||||||
|
*
|
||||||
|
* Request the data from the clipboard in text form. @callback is executed
|
||||||
|
* when the data is retreived.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
st_clipboard_get_text (StClipboard *clipboard,
|
||||||
|
StClipboardCallbackFunc callback,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
EventFilterData *data;
|
||||||
|
|
||||||
|
Display *dpy;
|
||||||
|
|
||||||
|
g_return_if_fail (ST_IS_CLIPBOARD (clipboard));
|
||||||
|
g_return_if_fail (callback != NULL);
|
||||||
|
|
||||||
|
data = g_new0 (EventFilterData, 1);
|
||||||
|
data->clipboard = clipboard;
|
||||||
|
data->callback = callback;
|
||||||
|
data->user_data = user_data;
|
||||||
|
|
||||||
|
clutter_x11_add_filter ((ClutterX11FilterFunc) st_clipboard_x11_event_filter,
|
||||||
|
data);
|
||||||
|
|
||||||
|
dpy = clutter_x11_get_default_display ();
|
||||||
|
|
||||||
|
clutter_x11_trap_x_errors (); /* safety on */
|
||||||
|
|
||||||
|
XConvertSelection (dpy,
|
||||||
|
__atom_clip,
|
||||||
|
__utf8_string, __utf8_string,
|
||||||
|
clipboard->priv->clipboard_window,
|
||||||
|
CurrentTime);
|
||||||
|
|
||||||
|
clutter_x11_untrap_x_errors ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* st_clipboard_set_text:
|
||||||
|
* @clipboard: A #StClipboard
|
||||||
|
* @text: text to copy to the clipboard
|
||||||
|
*
|
||||||
|
* Sets text as the current contents of the clipboard.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
st_clipboard_set_text (StClipboard *clipboard,
|
||||||
|
const gchar *text)
|
||||||
|
{
|
||||||
|
StClipboardPrivate *priv;
|
||||||
|
Display *dpy;
|
||||||
|
|
||||||
|
g_return_if_fail (ST_IS_CLIPBOARD (clipboard));
|
||||||
|
g_return_if_fail (text != NULL);
|
||||||
|
|
||||||
|
priv = clipboard->priv;
|
||||||
|
|
||||||
|
/* make a copy of the text */
|
||||||
|
g_free (priv->clipboard_text);
|
||||||
|
priv->clipboard_text = g_strdup (text);
|
||||||
|
|
||||||
|
/* tell X we own the clipboard selection */
|
||||||
|
dpy = clutter_x11_get_default_display ();
|
||||||
|
|
||||||
|
clutter_x11_trap_x_errors ();
|
||||||
|
|
||||||
|
XSetSelectionOwner (dpy, __atom_clip, priv->clipboard_window, CurrentTime);
|
||||||
|
XSync (dpy, FALSE);
|
||||||
|
|
||||||
|
clutter_x11_untrap_x_errors ();
|
||||||
|
}
|
||||||
103
src/st/st-clipboard.h
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
/*
|
||||||
|
* st-clipboard.h: clipboard object
|
||||||
|
*
|
||||||
|
* Copyright 2009 Intel Corporation.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU Lesser General Public License,
|
||||||
|
* version 2.1, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT ANY
|
||||||
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Written by: Thomas Wood <thomas.wood@intel.com>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(ST_H_INSIDE) && !defined(ST_COMPILATION)
|
||||||
|
#error "Only <st/st.h> can be included directly.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _ST_CLIPBOARD_H
|
||||||
|
#define _ST_CLIPBOARD_H
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define ST_TYPE_CLIPBOARD st_clipboard_get_type()
|
||||||
|
|
||||||
|
#define ST_CLIPBOARD(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_CAST ((obj), \
|
||||||
|
ST_TYPE_CLIPBOARD, StClipboard))
|
||||||
|
|
||||||
|
#define ST_CLIPBOARD_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_CAST ((klass), \
|
||||||
|
ST_TYPE_CLIPBOARD, StClipboardClass))
|
||||||
|
|
||||||
|
#define ST_IS_CLIPBOARD(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
|
||||||
|
ST_TYPE_CLIPBOARD))
|
||||||
|
|
||||||
|
#define ST_IS_CLIPBOARD_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_TYPE ((klass), \
|
||||||
|
ST_TYPE_CLIPBOARD))
|
||||||
|
|
||||||
|
#define ST_CLIPBOARD_GET_CLASS(obj) \
|
||||||
|
(G_TYPE_INSTANCE_GET_CLASS ((obj), \
|
||||||
|
ST_TYPE_CLIPBOARD, StClipboardClass))
|
||||||
|
|
||||||
|
typedef struct _StClipboard StClipboard;
|
||||||
|
typedef struct _StClipboardClass StClipboardClass;
|
||||||
|
typedef struct _StClipboardPrivate StClipboardPrivate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* StClipboard:
|
||||||
|
*
|
||||||
|
* The contents of this structure is private and should only be accessed using
|
||||||
|
* the provided API.
|
||||||
|
*/
|
||||||
|
struct _StClipboard
|
||||||
|
{
|
||||||
|
/*< private >*/
|
||||||
|
GObject parent;
|
||||||
|
StClipboardPrivate *priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _StClipboardClass
|
||||||
|
{
|
||||||
|
GObjectClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* StClipboardCallbackFunc:
|
||||||
|
* @clipboard: A #StClipboard
|
||||||
|
* @text: text from the clipboard
|
||||||
|
* @user_data: user data
|
||||||
|
*
|
||||||
|
* Callback function called when text is retrieved from the clipboard.
|
||||||
|
*/
|
||||||
|
typedef void (*StClipboardCallbackFunc) (StClipboard *clipboard,
|
||||||
|
const gchar *text,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
|
GType st_clipboard_get_type (void);
|
||||||
|
|
||||||
|
StClipboard* st_clipboard_get_default (void);
|
||||||
|
|
||||||
|
void st_clipboard_get_text (StClipboard *clipboard,
|
||||||
|
StClipboardCallbackFunc callback,
|
||||||
|
gpointer user_data);
|
||||||
|
void st_clipboard_set_text (StClipboard *clipboard,
|
||||||
|
const gchar *text);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* _ST_CLIPBOARD_H */
|
||||||
899
src/st/st-entry.c
Normal file
@@ -0,0 +1,899 @@
|
|||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
/*
|
||||||
|
* st-entry.c: Plain entry actor
|
||||||
|
*
|
||||||
|
* Copyright 2008, 2009 Intel Corporation
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU Lesser General Public License,
|
||||||
|
* version 2.1, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT ANY
|
||||||
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Written by: Thomas Wood <thomas.wood@intel.com>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SECTION:st-entry
|
||||||
|
* @short_description: Widget for displaying text
|
||||||
|
*
|
||||||
|
* #StEntry is a simple widget for displaying text. It derives from
|
||||||
|
* #StWidget to add extra style and placement functionality over
|
||||||
|
* #ClutterText. The internal #ClutterText is publicly accessibly to allow
|
||||||
|
* applications to set further properties.
|
||||||
|
*
|
||||||
|
* #StEntry supports the following pseudo style states:
|
||||||
|
* <itemizedlist>
|
||||||
|
* <listitem>
|
||||||
|
* <para>focus: the widget has focus</para>
|
||||||
|
* </listitem>
|
||||||
|
* <listitem>
|
||||||
|
* <para>indeterminate: the widget is showing the hint text</para>
|
||||||
|
* </listitem>
|
||||||
|
* </itemizedlist>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
#include <clutter/clutter.h>
|
||||||
|
#include <clutter-imcontext/clutter-imtext.h>
|
||||||
|
|
||||||
|
#include "st-entry.h"
|
||||||
|
|
||||||
|
#include "st-widget.h"
|
||||||
|
#include "st-texture-cache.h"
|
||||||
|
#include "st-marshal.h"
|
||||||
|
#include "st-clipboard.h"
|
||||||
|
|
||||||
|
#define HAS_FOCUS(actor) (clutter_actor_get_stage (actor) && clutter_stage_get_key_focus ((ClutterStage *) clutter_actor_get_stage (actor)) == actor)
|
||||||
|
|
||||||
|
|
||||||
|
/* properties */
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0,
|
||||||
|
|
||||||
|
PROP_CLUTTER_TEXT,
|
||||||
|
PROP_HINT_TEXT,
|
||||||
|
PROP_TEXT,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* signals */
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PRIMARY_ICON_CLICKED,
|
||||||
|
SECONDARY_ICON_CLICKED,
|
||||||
|
|
||||||
|
LAST_SIGNAL
|
||||||
|
};
|
||||||
|
|
||||||
|
#define ST_ENTRY_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ST_TYPE_ENTRY, StEntryPrivate))
|
||||||
|
#define ST_ENTRY_PRIV(x) ((StEntry *) x)->priv
|
||||||
|
|
||||||
|
|
||||||
|
struct _StEntryPrivate
|
||||||
|
{
|
||||||
|
ClutterActor *entry;
|
||||||
|
gchar *hint;
|
||||||
|
|
||||||
|
ClutterActor *primary_icon;
|
||||||
|
ClutterActor *secondary_icon;
|
||||||
|
|
||||||
|
gfloat spacing;
|
||||||
|
};
|
||||||
|
|
||||||
|
static guint entry_signals[LAST_SIGNAL] = { 0, };
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (StEntry, st_entry, ST_TYPE_WIDGET);
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_entry_set_property (GObject *gobject,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
StEntry *entry = ST_ENTRY (gobject);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_HINT_TEXT:
|
||||||
|
st_entry_set_hint_text (entry, g_value_get_string (value));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_TEXT:
|
||||||
|
st_entry_set_text (entry, g_value_get_string (value));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_entry_get_property (GObject *gobject,
|
||||||
|
guint prop_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
StEntryPrivate *priv = ST_ENTRY_PRIV (gobject);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_CLUTTER_TEXT:
|
||||||
|
g_value_set_object (value, priv->entry);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_HINT_TEXT:
|
||||||
|
g_value_set_string (value, priv->hint);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_TEXT:
|
||||||
|
g_value_set_string (value, clutter_text_get_text (CLUTTER_TEXT (priv->entry)));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_entry_dispose (GObject *object)
|
||||||
|
{
|
||||||
|
StEntryPrivate *priv = ST_ENTRY_PRIV (object);
|
||||||
|
|
||||||
|
if (priv->entry)
|
||||||
|
{
|
||||||
|
clutter_actor_unparent (priv->entry);
|
||||||
|
priv->entry = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_entry_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
StEntryPrivate *priv = ST_ENTRY_PRIV (object);
|
||||||
|
|
||||||
|
g_free (priv->hint);
|
||||||
|
priv->hint = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_entry_style_changed (StWidget *self)
|
||||||
|
{
|
||||||
|
StEntryPrivate *priv = ST_ENTRY_PRIV (self);
|
||||||
|
StThemeNode *theme_node;
|
||||||
|
ClutterColor color;
|
||||||
|
const PangoFontDescription *font;
|
||||||
|
gchar *font_string;
|
||||||
|
|
||||||
|
theme_node = st_widget_get_theme_node (self);
|
||||||
|
|
||||||
|
st_theme_node_get_foreground_color (theme_node, &color);
|
||||||
|
clutter_text_set_color (CLUTTER_TEXT (priv->entry), &color);
|
||||||
|
|
||||||
|
if (st_theme_node_get_color (theme_node, "caret-color", FALSE, &color))
|
||||||
|
clutter_text_set_cursor_color (CLUTTER_TEXT (priv->entry), &color);
|
||||||
|
|
||||||
|
if (st_theme_node_get_color (theme_node, "selection-background-color", FALSE, &color))
|
||||||
|
clutter_text_set_selection_color (CLUTTER_TEXT (priv->entry), &color);
|
||||||
|
|
||||||
|
font = st_theme_node_get_font (theme_node);
|
||||||
|
font_string = pango_font_description_to_string (font);
|
||||||
|
clutter_text_set_font_name (CLUTTER_TEXT (priv->entry), font_string);
|
||||||
|
g_free (font_string);
|
||||||
|
|
||||||
|
ST_WIDGET_CLASS (st_entry_parent_class)->style_changed (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_entry_get_preferred_width (ClutterActor *actor,
|
||||||
|
gfloat for_height,
|
||||||
|
gfloat *min_width_p,
|
||||||
|
gfloat *natural_width_p)
|
||||||
|
{
|
||||||
|
StEntryPrivate *priv = ST_ENTRY_PRIV (actor);
|
||||||
|
StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor));
|
||||||
|
gfloat icon_w;
|
||||||
|
|
||||||
|
st_theme_node_adjust_for_height (theme_node, &for_height);
|
||||||
|
|
||||||
|
clutter_actor_get_preferred_width (priv->entry, for_height,
|
||||||
|
min_width_p,
|
||||||
|
natural_width_p);
|
||||||
|
|
||||||
|
if (priv->primary_icon)
|
||||||
|
{
|
||||||
|
clutter_actor_get_preferred_width (priv->primary_icon, -1, NULL, &icon_w);
|
||||||
|
|
||||||
|
if (min_width_p)
|
||||||
|
*min_width_p += icon_w + priv->spacing;
|
||||||
|
|
||||||
|
if (natural_width_p)
|
||||||
|
*natural_width_p += icon_w + priv->spacing;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->secondary_icon)
|
||||||
|
{
|
||||||
|
clutter_actor_get_preferred_width (priv->secondary_icon,
|
||||||
|
-1, NULL, &icon_w);
|
||||||
|
|
||||||
|
if (min_width_p)
|
||||||
|
*min_width_p += icon_w + priv->spacing;
|
||||||
|
|
||||||
|
if (natural_width_p)
|
||||||
|
*natural_width_p += icon_w + priv->spacing;
|
||||||
|
}
|
||||||
|
|
||||||
|
st_theme_node_adjust_preferred_width (theme_node, min_width_p, natural_width_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_entry_get_preferred_height (ClutterActor *actor,
|
||||||
|
gfloat for_width,
|
||||||
|
gfloat *min_height_p,
|
||||||
|
gfloat *natural_height_p)
|
||||||
|
{
|
||||||
|
StEntryPrivate *priv = ST_ENTRY_PRIV (actor);
|
||||||
|
StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor));
|
||||||
|
gfloat icon_h;
|
||||||
|
|
||||||
|
st_theme_node_adjust_for_width (theme_node, &for_width);
|
||||||
|
|
||||||
|
clutter_actor_get_preferred_height (priv->entry, for_width,
|
||||||
|
min_height_p,
|
||||||
|
natural_height_p);
|
||||||
|
|
||||||
|
if (priv->primary_icon)
|
||||||
|
{
|
||||||
|
clutter_actor_get_preferred_height (priv->primary_icon,
|
||||||
|
-1, NULL, &icon_h);
|
||||||
|
|
||||||
|
if (min_height_p && icon_h > *min_height_p)
|
||||||
|
*min_height_p = icon_h;
|
||||||
|
|
||||||
|
if (natural_height_p && icon_h > *natural_height_p)
|
||||||
|
*natural_height_p = icon_h;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->secondary_icon)
|
||||||
|
{
|
||||||
|
clutter_actor_get_preferred_height (priv->secondary_icon,
|
||||||
|
-1, NULL, &icon_h);
|
||||||
|
|
||||||
|
if (min_height_p && icon_h > *min_height_p)
|
||||||
|
*min_height_p = icon_h;
|
||||||
|
|
||||||
|
if (natural_height_p && icon_h > *natural_height_p)
|
||||||
|
*natural_height_p = icon_h;
|
||||||
|
}
|
||||||
|
|
||||||
|
st_theme_node_adjust_preferred_height (theme_node, min_height_p, natural_height_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_entry_allocate (ClutterActor *actor,
|
||||||
|
const ClutterActorBox *box,
|
||||||
|
ClutterAllocationFlags flags)
|
||||||
|
{
|
||||||
|
StEntryPrivate *priv = ST_ENTRY_PRIV (actor);
|
||||||
|
StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor));
|
||||||
|
ClutterActorClass *parent_class;
|
||||||
|
ClutterActorBox content_box, child_box, icon_box;
|
||||||
|
gfloat icon_w, icon_h;
|
||||||
|
gfloat entry_h, min_h, pref_h, avail_h;
|
||||||
|
|
||||||
|
parent_class = CLUTTER_ACTOR_CLASS (st_entry_parent_class);
|
||||||
|
parent_class->allocate (actor, box, flags);
|
||||||
|
|
||||||
|
st_theme_node_get_content_box (theme_node, box, &content_box);
|
||||||
|
|
||||||
|
avail_h = content_box.y2 - content_box.y1;
|
||||||
|
|
||||||
|
child_box.x1 = content_box.x1;
|
||||||
|
child_box.x2 = content_box.x2;
|
||||||
|
|
||||||
|
if (priv->primary_icon)
|
||||||
|
{
|
||||||
|
clutter_actor_get_preferred_width (priv->primary_icon,
|
||||||
|
-1, NULL, &icon_w);
|
||||||
|
clutter_actor_get_preferred_height (priv->primary_icon,
|
||||||
|
-1, NULL, &icon_h);
|
||||||
|
|
||||||
|
icon_box.x1 = content_box.x1;
|
||||||
|
icon_box.x2 = icon_box.x1 + icon_w;
|
||||||
|
|
||||||
|
icon_box.y1 = (int) (content_box.y1 + avail_h / 2 - icon_h / 2);
|
||||||
|
icon_box.y2 = icon_box.y1 + icon_h;
|
||||||
|
|
||||||
|
clutter_actor_allocate (priv->primary_icon,
|
||||||
|
&icon_box,
|
||||||
|
flags);
|
||||||
|
|
||||||
|
/* reduce the size for the entry */
|
||||||
|
child_box.x1 += icon_w + priv->spacing;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->secondary_icon)
|
||||||
|
{
|
||||||
|
clutter_actor_get_preferred_width (priv->secondary_icon,
|
||||||
|
-1, NULL, &icon_w);
|
||||||
|
clutter_actor_get_preferred_height (priv->secondary_icon,
|
||||||
|
-1, NULL, &icon_h);
|
||||||
|
|
||||||
|
icon_box.x2 = content_box.x2;
|
||||||
|
icon_box.x1 = icon_box.x2 - icon_w;
|
||||||
|
|
||||||
|
icon_box.y1 = (int) (content_box.y1 + avail_h / 2 - icon_h / 2);
|
||||||
|
icon_box.y2 = icon_box.y1 + icon_h;
|
||||||
|
|
||||||
|
clutter_actor_allocate (priv->secondary_icon,
|
||||||
|
&icon_box,
|
||||||
|
flags);
|
||||||
|
|
||||||
|
/* reduce the size for the entry */
|
||||||
|
child_box.x2 -= icon_w - priv->spacing;
|
||||||
|
}
|
||||||
|
|
||||||
|
clutter_actor_get_preferred_height (priv->entry, child_box.x2 - child_box.x1,
|
||||||
|
&min_h, &pref_h);
|
||||||
|
|
||||||
|
entry_h = CLAMP (pref_h, min_h, avail_h);
|
||||||
|
|
||||||
|
child_box.y1 = (int) (content_box.y1 + avail_h / 2 - entry_h / 2);
|
||||||
|
child_box.y2 = child_box.y1 + entry_h;
|
||||||
|
|
||||||
|
clutter_actor_allocate (priv->entry, &child_box, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_text_focus_in_cb (ClutterText *text,
|
||||||
|
ClutterActor *actor)
|
||||||
|
{
|
||||||
|
StEntryPrivate *priv = ST_ENTRY_PRIV (actor);
|
||||||
|
|
||||||
|
/* remove the hint if visible */
|
||||||
|
if (priv->hint
|
||||||
|
&& !strcmp (clutter_text_get_text (text), priv->hint))
|
||||||
|
{
|
||||||
|
clutter_text_set_text (text, "");
|
||||||
|
}
|
||||||
|
st_widget_set_style_pseudo_class (ST_WIDGET (actor), "focus");
|
||||||
|
clutter_text_set_cursor_visible (text, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_text_focus_out_cb (ClutterText *text,
|
||||||
|
ClutterActor *actor)
|
||||||
|
{
|
||||||
|
StEntryPrivate *priv = ST_ENTRY_PRIV (actor);
|
||||||
|
|
||||||
|
/* add a hint if the entry is empty */
|
||||||
|
if (priv->hint && !strcmp (clutter_text_get_text (text), ""))
|
||||||
|
{
|
||||||
|
clutter_text_set_text (text, priv->hint);
|
||||||
|
st_widget_set_style_pseudo_class (ST_WIDGET (actor), "indeterminate");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
st_widget_set_style_pseudo_class (ST_WIDGET (actor), NULL);
|
||||||
|
}
|
||||||
|
clutter_text_set_cursor_visible (text, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_entry_paint (ClutterActor *actor)
|
||||||
|
{
|
||||||
|
StEntryPrivate *priv = ST_ENTRY_PRIV (actor);
|
||||||
|
ClutterActorClass *parent_class;
|
||||||
|
|
||||||
|
parent_class = CLUTTER_ACTOR_CLASS (st_entry_parent_class);
|
||||||
|
parent_class->paint (actor);
|
||||||
|
|
||||||
|
clutter_actor_paint (priv->entry);
|
||||||
|
|
||||||
|
if (priv->primary_icon)
|
||||||
|
clutter_actor_paint (priv->primary_icon);
|
||||||
|
|
||||||
|
if (priv->secondary_icon)
|
||||||
|
clutter_actor_paint (priv->secondary_icon);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_entry_pick (ClutterActor *actor,
|
||||||
|
const ClutterColor *c)
|
||||||
|
{
|
||||||
|
StEntryPrivate *priv = ST_ENTRY_PRIV (actor);
|
||||||
|
|
||||||
|
CLUTTER_ACTOR_CLASS (st_entry_parent_class)->pick (actor, c);
|
||||||
|
|
||||||
|
clutter_actor_paint (priv->entry);
|
||||||
|
|
||||||
|
if (priv->primary_icon)
|
||||||
|
clutter_actor_paint (priv->primary_icon);
|
||||||
|
|
||||||
|
if (priv->secondary_icon)
|
||||||
|
clutter_actor_paint (priv->secondary_icon);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_entry_map (ClutterActor *actor)
|
||||||
|
{
|
||||||
|
StEntryPrivate *priv = ST_ENTRY (actor)->priv;
|
||||||
|
|
||||||
|
CLUTTER_ACTOR_CLASS (st_entry_parent_class)->map (actor);
|
||||||
|
|
||||||
|
clutter_actor_map (priv->entry);
|
||||||
|
|
||||||
|
if (priv->primary_icon)
|
||||||
|
clutter_actor_map (priv->primary_icon);
|
||||||
|
|
||||||
|
if (priv->secondary_icon)
|
||||||
|
clutter_actor_map (priv->secondary_icon);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_entry_unmap (ClutterActor *actor)
|
||||||
|
{
|
||||||
|
StEntryPrivate *priv = ST_ENTRY (actor)->priv;
|
||||||
|
|
||||||
|
CLUTTER_ACTOR_CLASS (st_entry_parent_class)->unmap (actor);
|
||||||
|
|
||||||
|
clutter_actor_unmap (priv->entry);
|
||||||
|
|
||||||
|
if (priv->primary_icon)
|
||||||
|
clutter_actor_unmap (priv->primary_icon);
|
||||||
|
|
||||||
|
if (priv->secondary_icon)
|
||||||
|
clutter_actor_unmap (priv->secondary_icon);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_entry_clipboard_callback (StClipboard *clipboard,
|
||||||
|
const gchar *text,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
ClutterText *ctext = (ClutterText*)((StEntry *) data)->priv->entry;
|
||||||
|
gint cursor_pos;
|
||||||
|
|
||||||
|
if (!text)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* delete the current selection before pasting */
|
||||||
|
clutter_text_delete_selection (ctext);
|
||||||
|
|
||||||
|
/* "paste" the clipboard text into the entry */
|
||||||
|
cursor_pos = clutter_text_get_cursor_position (ctext);
|
||||||
|
clutter_text_insert_text (ctext, text, cursor_pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
st_entry_key_press_event (ClutterActor *actor,
|
||||||
|
ClutterKeyEvent *event)
|
||||||
|
{
|
||||||
|
StEntryPrivate *priv = ST_ENTRY_PRIV (actor);
|
||||||
|
|
||||||
|
/* This is expected to handle events that were emitted for the inner
|
||||||
|
ClutterText. They only reach this function if the ClutterText
|
||||||
|
didn't handle them */
|
||||||
|
|
||||||
|
/* paste */
|
||||||
|
if ((event->modifier_state & CLUTTER_CONTROL_MASK)
|
||||||
|
&& event->keyval == CLUTTER_v)
|
||||||
|
{
|
||||||
|
StClipboard *clipboard;
|
||||||
|
|
||||||
|
clipboard = st_clipboard_get_default ();
|
||||||
|
|
||||||
|
st_clipboard_get_text (clipboard, st_entry_clipboard_callback, actor);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* copy */
|
||||||
|
if ((event->modifier_state & CLUTTER_CONTROL_MASK)
|
||||||
|
&& event->keyval == CLUTTER_c)
|
||||||
|
{
|
||||||
|
StClipboard *clipboard;
|
||||||
|
gchar *text;
|
||||||
|
|
||||||
|
clipboard = st_clipboard_get_default ();
|
||||||
|
|
||||||
|
text = clutter_text_get_selection ((ClutterText*) priv->entry);
|
||||||
|
|
||||||
|
if (text && strlen (text))
|
||||||
|
st_clipboard_set_text (clipboard, text);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* cut */
|
||||||
|
if ((event->modifier_state & CLUTTER_CONTROL_MASK)
|
||||||
|
&& event->keyval == CLUTTER_x)
|
||||||
|
{
|
||||||
|
StClipboard *clipboard;
|
||||||
|
gchar *text;
|
||||||
|
|
||||||
|
clipboard = st_clipboard_get_default ();
|
||||||
|
|
||||||
|
text = clutter_text_get_selection ((ClutterText*) priv->entry);
|
||||||
|
|
||||||
|
if (text && strlen (text))
|
||||||
|
{
|
||||||
|
st_clipboard_set_text (clipboard, text);
|
||||||
|
|
||||||
|
/* now delete the text */
|
||||||
|
clutter_text_delete_selection ((ClutterText *) priv->entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_entry_key_focus_in (ClutterActor *actor)
|
||||||
|
{
|
||||||
|
StEntryPrivate *priv = ST_ENTRY_PRIV (actor);
|
||||||
|
|
||||||
|
/* We never want key focus. The ClutterText should be given first
|
||||||
|
pass for all key events */
|
||||||
|
clutter_actor_grab_key_focus (priv->entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_entry_class_init (StEntryClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||||
|
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||||
|
StWidgetClass *widget_class = ST_WIDGET_CLASS (klass);
|
||||||
|
GParamSpec *pspec;
|
||||||
|
|
||||||
|
g_type_class_add_private (klass, sizeof (StEntryPrivate));
|
||||||
|
|
||||||
|
gobject_class->set_property = st_entry_set_property;
|
||||||
|
gobject_class->get_property = st_entry_get_property;
|
||||||
|
gobject_class->finalize = st_entry_finalize;
|
||||||
|
gobject_class->dispose = st_entry_dispose;
|
||||||
|
|
||||||
|
actor_class->get_preferred_width = st_entry_get_preferred_width;
|
||||||
|
actor_class->get_preferred_height = st_entry_get_preferred_height;
|
||||||
|
actor_class->allocate = st_entry_allocate;
|
||||||
|
actor_class->paint = st_entry_paint;
|
||||||
|
actor_class->pick = st_entry_pick;
|
||||||
|
actor_class->map = st_entry_map;
|
||||||
|
actor_class->unmap = st_entry_unmap;
|
||||||
|
|
||||||
|
actor_class->key_press_event = st_entry_key_press_event;
|
||||||
|
actor_class->key_focus_in = st_entry_key_focus_in;
|
||||||
|
|
||||||
|
widget_class->style_changed = st_entry_style_changed;
|
||||||
|
|
||||||
|
pspec = g_param_spec_object ("clutter-text",
|
||||||
|
"Clutter Text",
|
||||||
|
"Internal ClutterText actor",
|
||||||
|
CLUTTER_TYPE_TEXT,
|
||||||
|
G_PARAM_READABLE);
|
||||||
|
g_object_class_install_property (gobject_class, PROP_CLUTTER_TEXT, pspec);
|
||||||
|
|
||||||
|
pspec = g_param_spec_string ("hint-text",
|
||||||
|
"Hint Text",
|
||||||
|
"Text to display when the entry is not focused "
|
||||||
|
"and the text property is empty",
|
||||||
|
NULL, G_PARAM_READWRITE);
|
||||||
|
g_object_class_install_property (gobject_class, PROP_HINT_TEXT, pspec);
|
||||||
|
|
||||||
|
pspec = g_param_spec_string ("text",
|
||||||
|
"Text",
|
||||||
|
"Text of the entry",
|
||||||
|
NULL, G_PARAM_READWRITE);
|
||||||
|
g_object_class_install_property (gobject_class, PROP_TEXT, pspec);
|
||||||
|
|
||||||
|
/* signals */
|
||||||
|
/**
|
||||||
|
* StEntry::primary-icon-clicked:
|
||||||
|
*
|
||||||
|
* Emitted when the primary icon is clicked
|
||||||
|
*/
|
||||||
|
entry_signals[PRIMARY_ICON_CLICKED] =
|
||||||
|
g_signal_new ("primary-icon-clicked",
|
||||||
|
G_TYPE_FROM_CLASS (klass),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
G_STRUCT_OFFSET (StEntryClass, primary_icon_clicked),
|
||||||
|
NULL, NULL,
|
||||||
|
_st_marshal_VOID__VOID,
|
||||||
|
G_TYPE_NONE, 0);
|
||||||
|
/**
|
||||||
|
* StEntry::secondary-icon-clicked:
|
||||||
|
*
|
||||||
|
* Emitted when the secondary icon is clicked
|
||||||
|
*/
|
||||||
|
entry_signals[SECONDARY_ICON_CLICKED] =
|
||||||
|
g_signal_new ("secondary-icon-clicked",
|
||||||
|
G_TYPE_FROM_CLASS (klass),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
G_STRUCT_OFFSET (StEntryClass, secondary_icon_clicked),
|
||||||
|
NULL, NULL,
|
||||||
|
_st_marshal_VOID__VOID,
|
||||||
|
G_TYPE_NONE, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_entry_init (StEntry *entry)
|
||||||
|
{
|
||||||
|
StEntryPrivate *priv;
|
||||||
|
|
||||||
|
priv = entry->priv = ST_ENTRY_GET_PRIVATE (entry);
|
||||||
|
|
||||||
|
priv->entry = g_object_new (CLUTTER_TYPE_IMTEXT,
|
||||||
|
"line-alignment", PANGO_ALIGN_LEFT,
|
||||||
|
"editable", TRUE,
|
||||||
|
"reactive", TRUE,
|
||||||
|
"single-line-mode", TRUE,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
g_signal_connect (priv->entry, "key-focus-in",
|
||||||
|
G_CALLBACK (clutter_text_focus_in_cb), entry);
|
||||||
|
|
||||||
|
g_signal_connect (priv->entry, "key-focus-out",
|
||||||
|
G_CALLBACK (clutter_text_focus_out_cb), entry);
|
||||||
|
|
||||||
|
priv->spacing = 6.0f;
|
||||||
|
|
||||||
|
clutter_actor_set_parent (priv->entry, CLUTTER_ACTOR (entry));
|
||||||
|
clutter_actor_set_reactive ((ClutterActor *) entry, TRUE);
|
||||||
|
|
||||||
|
/* set cursor hidden until we receive focus */
|
||||||
|
clutter_text_set_cursor_visible ((ClutterText *) priv->entry, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* st_entry_new:
|
||||||
|
* @text: text to set the entry to
|
||||||
|
*
|
||||||
|
* Create a new #StEntry with the specified entry
|
||||||
|
*
|
||||||
|
* Returns: a new #StEntry
|
||||||
|
*/
|
||||||
|
StWidget *
|
||||||
|
st_entry_new (const gchar *text)
|
||||||
|
{
|
||||||
|
StWidget *entry;
|
||||||
|
|
||||||
|
/* add the entry to the stage, but don't allow it to be visible */
|
||||||
|
entry = g_object_new (ST_TYPE_ENTRY,
|
||||||
|
"text", text,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* st_entry_get_text:
|
||||||
|
* @entry: a #StEntry
|
||||||
|
*
|
||||||
|
* Get the text displayed on the entry
|
||||||
|
*
|
||||||
|
* Returns: the text for the entry. This must not be freed by the application
|
||||||
|
*/
|
||||||
|
G_CONST_RETURN gchar *
|
||||||
|
st_entry_get_text (StEntry *entry)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (ST_IS_ENTRY (entry), NULL);
|
||||||
|
|
||||||
|
return clutter_text_get_text (CLUTTER_TEXT (entry->priv->entry));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* st_entry_set_text:
|
||||||
|
* @entry: a #StEntry
|
||||||
|
* @text: text to set the entry to
|
||||||
|
*
|
||||||
|
* Sets the text displayed on the entry
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
st_entry_set_text (StEntry *entry,
|
||||||
|
const gchar *text)
|
||||||
|
{
|
||||||
|
StEntryPrivate *priv;
|
||||||
|
|
||||||
|
g_return_if_fail (ST_IS_ENTRY (entry));
|
||||||
|
|
||||||
|
priv = entry->priv;
|
||||||
|
|
||||||
|
/* set a hint if we are blanking the entry */
|
||||||
|
if (priv->hint
|
||||||
|
&& text && !strcmp ("", text)
|
||||||
|
&& !HAS_FOCUS (priv->entry))
|
||||||
|
{
|
||||||
|
text = priv->hint;
|
||||||
|
st_widget_set_style_pseudo_class (ST_WIDGET (entry), "indeterminate");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (HAS_FOCUS (priv->entry))
|
||||||
|
st_widget_set_style_pseudo_class (ST_WIDGET (entry), "focus");
|
||||||
|
else
|
||||||
|
st_widget_set_style_pseudo_class (ST_WIDGET (entry), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
clutter_text_set_text (CLUTTER_TEXT (priv->entry), text);
|
||||||
|
|
||||||
|
g_object_notify (G_OBJECT (entry), "text");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* st_entry_get_clutter_text:
|
||||||
|
* @entry: a #StEntry
|
||||||
|
*
|
||||||
|
* Retrieve the internal #ClutterText so that extra parameters can be set
|
||||||
|
*
|
||||||
|
* Returns: (transfer none): the #ClutterText used by #StEntry. The entry is
|
||||||
|
* owned by the #StEntry and should not be unref'ed by the application.
|
||||||
|
*/
|
||||||
|
ClutterActor*
|
||||||
|
st_entry_get_clutter_text (StEntry *entry)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (ST_ENTRY (entry), NULL);
|
||||||
|
|
||||||
|
return entry->priv->entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* st_entry_set_hint_text:
|
||||||
|
* @entry: a #StEntry
|
||||||
|
* @text: text to set as the entry hint
|
||||||
|
*
|
||||||
|
* Sets the text to display when the entry is empty and unfocused. When the
|
||||||
|
* entry is displaying the hint, it has a pseudo class of "indeterminate".
|
||||||
|
* A value of NULL unsets the hint.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
st_entry_set_hint_text (StEntry *entry,
|
||||||
|
const gchar *text)
|
||||||
|
{
|
||||||
|
StEntryPrivate *priv;
|
||||||
|
|
||||||
|
g_return_if_fail (ST_IS_ENTRY (entry));
|
||||||
|
|
||||||
|
priv = entry->priv;
|
||||||
|
|
||||||
|
g_free (priv->hint);
|
||||||
|
|
||||||
|
priv->hint = g_strdup (text);
|
||||||
|
|
||||||
|
if (!strcmp (clutter_text_get_text (CLUTTER_TEXT (priv->entry)), ""))
|
||||||
|
{
|
||||||
|
clutter_text_set_text (CLUTTER_TEXT (priv->entry), priv->hint);
|
||||||
|
st_widget_set_style_pseudo_class (ST_WIDGET (entry), "indeterminate");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* st_entry_get_hint_text:
|
||||||
|
* @entry: a #StEntry
|
||||||
|
*
|
||||||
|
* Gets the text that is displayed when the entry is empty and unfocused
|
||||||
|
*
|
||||||
|
* Returns: the current value of the hint property. This string is owned by the
|
||||||
|
* #StEntry and should not be freed or modified.
|
||||||
|
*/
|
||||||
|
G_CONST_RETURN
|
||||||
|
gchar *
|
||||||
|
st_entry_get_hint_text (StEntry *entry)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (ST_IS_ENTRY (entry), NULL);
|
||||||
|
|
||||||
|
return entry->priv->hint;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
_st_entry_icon_press_cb (ClutterActor *actor,
|
||||||
|
ClutterButtonEvent *event,
|
||||||
|
StEntry *entry)
|
||||||
|
{
|
||||||
|
StEntryPrivate *priv = entry->priv;
|
||||||
|
|
||||||
|
if (actor == priv->primary_icon)
|
||||||
|
g_signal_emit (entry, entry_signals[PRIMARY_ICON_CLICKED], 0);
|
||||||
|
else
|
||||||
|
g_signal_emit (entry, entry_signals[SECONDARY_ICON_CLICKED], 0);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_st_entry_set_icon_from_file (StEntry *entry,
|
||||||
|
ClutterActor **icon,
|
||||||
|
const gchar *filename)
|
||||||
|
{
|
||||||
|
if (*icon)
|
||||||
|
{
|
||||||
|
g_signal_handlers_disconnect_by_func (*icon,
|
||||||
|
_st_entry_icon_press_cb,
|
||||||
|
entry);
|
||||||
|
clutter_actor_unparent (*icon);
|
||||||
|
*icon = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filename)
|
||||||
|
{
|
||||||
|
StTextureCache *cache;
|
||||||
|
|
||||||
|
cache = st_texture_cache_get_default ();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
*icon = (ClutterActor*) st_texture_cache_get_texture (cache, filename);
|
||||||
|
|
||||||
|
clutter_actor_set_reactive (*icon, TRUE);
|
||||||
|
clutter_actor_set_parent (*icon, CLUTTER_ACTOR (entry));
|
||||||
|
g_signal_connect (*icon, "button-release-event",
|
||||||
|
G_CALLBACK (_st_entry_icon_press_cb), entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
clutter_actor_queue_relayout (CLUTTER_ACTOR (entry));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* st_entry_set_primary_icon_from_file:
|
||||||
|
* @entry: a #StEntry
|
||||||
|
* @filename: filename of an icon
|
||||||
|
*
|
||||||
|
* Set the primary icon of the entry to the given filename
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
st_entry_set_primary_icon_from_file (StEntry *entry,
|
||||||
|
const gchar *filename)
|
||||||
|
{
|
||||||
|
StEntryPrivate *priv;
|
||||||
|
|
||||||
|
g_return_if_fail (ST_IS_ENTRY (entry));
|
||||||
|
|
||||||
|
priv = entry->priv;
|
||||||
|
|
||||||
|
_st_entry_set_icon_from_file (entry, &priv->primary_icon, filename);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* st_entry_set_secondary_icon_from_file:
|
||||||
|
* @entry: a #StEntry
|
||||||
|
* @filename: filename of an icon
|
||||||
|
*
|
||||||
|
* Set the primary icon of the entry to the given filename
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
st_entry_set_secondary_icon_from_file (StEntry *entry,
|
||||||
|
const gchar *filename)
|
||||||
|
{
|
||||||
|
StEntryPrivate *priv;
|
||||||
|
|
||||||
|
g_return_if_fail (ST_IS_ENTRY (entry));
|
||||||
|
|
||||||
|
priv = entry->priv;
|
||||||
|
|
||||||
|
_st_entry_set_icon_from_file (entry, &priv->secondary_icon, filename);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||