Compare commits
11 Commits
3.3.3
...
wip/menus-
Author | SHA1 | Date | |
---|---|---|---|
![]() |
94d01bed12 | ||
![]() |
9daf358122 | ||
![]() |
b4b3f5a669 | ||
![]() |
5290a9dd08 | ||
![]() |
ab4a7c5237 | ||
![]() |
95e5c5cfb1 | ||
![]() |
757fb5796e | ||
![]() |
75e9fa9cfb | ||
![]() |
8997aa45b1 | ||
![]() |
f884dbbfb2 | ||
![]() |
d0c36bb732 |
41
NEWS
41
NEWS
@@ -1,44 +1,3 @@
|
||||
3.3.3
|
||||
=====
|
||||
* https://live.gnome.org/EveryDetailMatters
|
||||
- Stop flashing the window labels on actions in overview [Zan; #644861]
|
||||
- Improve the look of window captions in the overview [Marc; #664487]
|
||||
- Move dash tooltips beside the icon [Seif, Stefano; #666166]
|
||||
* Support application menus exported from applications via new GLib API
|
||||
and D-Bus protocol. [Giovanni, Colin, Matthias, Cosimo]
|
||||
* For removable device prompts, show "Open with Rhythmbox], rather
|
||||
than "Open with Rhythmbox Music Player' [Florian; #664561]
|
||||
* Switch to activating the message tray only with a hot corner rather
|
||||
than a full row of pixels, allowing mouse events to apps [Rui; #663366]
|
||||
* Fully handle the case where the workspaces-only-on-primary
|
||||
GSetting is set to false [Florian; #652580]
|
||||
* Add support for background-size CSS property to St [Quentin; #633462]
|
||||
* Port to new GJS Lang.Class framework [Giovanni; #664436]
|
||||
* Finish port to GDBus [Giovanni; #664436]
|
||||
* Stop using the deprecated Clutter default stage [Florian, Jasper; #664052]
|
||||
* Fix bugs that kept browser plugin from working in WebKit-based browser
|
||||
[Jasper; #666444]
|
||||
* Fix typo that made uninstalling extensions not work [Jasper]
|
||||
* Fix crash in browser plugin if shell is not run [Jürg]
|
||||
* Reintroduce piscine paschal ovum [Giovanni; #666606]
|
||||
* Network menu bug fixes
|
||||
Giovanni; #664124, #665194, #665680, #666429, #666614]
|
||||
* Misc bug fixes [Florian, Jasper, Jonny, Marina, Ron; #647587, #659272,
|
||||
#665261, #666020, #666243]
|
||||
|
||||
Contributors:
|
||||
Jürg Billeter, Giovanni Campagna, Stefano Candori, Cosimo Cecchi,
|
||||
Matthias Clasen, Zan Dobersek, Quentin Glidic, Jonny Lamb, Ryan Lortie,
|
||||
Seif Lotfy, Rui Matos, Florian Müllner, Bastien Nocera, Jasper St. Pierre,
|
||||
Marc Plano-Lesay, Colin Walters, Ron Yorsten, Marina Zhurakhinskaya
|
||||
|
||||
Translations:
|
||||
Petr Kovar [cz], Kris Thomsen [dk], Daniel Mustieles [es],
|
||||
Ville-Pekka Vainio [fi], Yaron Shahrabani [he], Žygimantas Beručka [lt],
|
||||
Jovan Naumovski [mk], Kjartan Maraas [nb], "Andreas N" [nn],
|
||||
Lucian Adrian Grijincu [ro], Matej Urbančič [sl], Praveen Illa [te],
|
||||
Muhammet Kara [tr], Daniel Korostil [uk], Aron Xu [zh_CN]
|
||||
|
||||
3.3.2
|
||||
=====
|
||||
* Port D-Bus usage in the shell to GDBus [Giovanni, Marc-Antoine, Florian,
|
||||
|
@@ -455,7 +455,7 @@ plugin_enable_extension (PluginObject *obj,
|
||||
NPString uuid,
|
||||
gboolean enabled)
|
||||
{
|
||||
gchar *uuid_str = g_strndup (uuid.UTF8Characters, uuid.UTF8Length);
|
||||
const gchar *uuid_str = uuid.UTF8Characters;
|
||||
if (!uuid_is_valid (uuid_str))
|
||||
return FALSE;
|
||||
|
||||
@@ -468,8 +468,6 @@ plugin_enable_extension (PluginObject *obj,
|
||||
NULL, /* callback */
|
||||
NULL /* user_data */);
|
||||
|
||||
g_free (uuid_str);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -478,32 +476,21 @@ plugin_install_extension (PluginObject *obj,
|
||||
NPString uuid,
|
||||
NPString version_tag)
|
||||
{
|
||||
gchar *uuid_str = g_strndup (uuid.UTF8Characters, uuid.UTF8Length);
|
||||
gchar *version_tag_str;
|
||||
|
||||
const gchar *uuid_str = uuid.UTF8Characters;
|
||||
if (!uuid_is_valid (uuid_str))
|
||||
{
|
||||
g_free (uuid_str);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
version_tag_str = g_strndup (version_tag.UTF8Characters,
|
||||
version_tag.UTF8Length);
|
||||
return FALSE;
|
||||
|
||||
g_dbus_proxy_call (obj->proxy,
|
||||
"InstallRemoteExtension",
|
||||
g_variant_new ("(ss)",
|
||||
uuid_str,
|
||||
version_tag_str),
|
||||
version_tag.UTF8Characters),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1, /* timeout */
|
||||
NULL, /* cancellable */
|
||||
NULL, /* callback */
|
||||
NULL /* user_data */);
|
||||
|
||||
g_free (uuid_str);
|
||||
g_free (version_tag_str);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -514,14 +501,11 @@ plugin_uninstall_extension (PluginObject *obj,
|
||||
{
|
||||
GError *error = NULL;
|
||||
GVariant *res;
|
||||
gchar *uuid_str;
|
||||
const gchar *uuid_str;
|
||||
|
||||
uuid_str = g_strndup (uuid.UTF8Characters, uuid.UTF8Length);
|
||||
uuid_str = uuid.UTF8Characters;
|
||||
if (!uuid_is_valid (uuid_str))
|
||||
{
|
||||
g_free (uuid_str);
|
||||
return FALSE;
|
||||
}
|
||||
return FALSE;
|
||||
|
||||
res = g_dbus_proxy_call_sync (obj->proxy,
|
||||
"UninstallExtension",
|
||||
@@ -532,8 +516,6 @@ plugin_uninstall_extension (PluginObject *obj,
|
||||
NULL, /* cancellable */
|
||||
&error);
|
||||
|
||||
g_free (uuid_str);
|
||||
|
||||
if (!res)
|
||||
{
|
||||
g_warning ("Failed to uninstall extension: %s", error->message);
|
||||
@@ -551,14 +533,11 @@ plugin_get_info (PluginObject *obj,
|
||||
{
|
||||
GError *error = NULL;
|
||||
GVariant *res;
|
||||
gchar *uuid_str;
|
||||
const gchar *uuid_str;
|
||||
|
||||
uuid_str = g_strndup (uuid.UTF8Characters, uuid.UTF8Length);
|
||||
uuid_str = uuid.UTF8Characters;
|
||||
if (!uuid_is_valid (uuid_str))
|
||||
{
|
||||
g_free (uuid_str);
|
||||
return FALSE;
|
||||
}
|
||||
return FALSE;
|
||||
|
||||
res = g_dbus_proxy_call_sync (obj->proxy,
|
||||
"GetExtensionInfo",
|
||||
@@ -568,8 +547,6 @@ plugin_get_info (PluginObject *obj,
|
||||
NULL, /* cancellable */
|
||||
&error);
|
||||
|
||||
g_free (uuid_str);
|
||||
|
||||
if (!res)
|
||||
{
|
||||
g_warning ("Failed to retrieve extension metadata: %s", error->message);
|
||||
@@ -587,14 +564,11 @@ plugin_get_errors (PluginObject *obj,
|
||||
{
|
||||
GError *error = NULL;
|
||||
GVariant *res;
|
||||
gchar *uuid_str;
|
||||
const gchar *uuid_str;
|
||||
|
||||
uuid_str = g_strndup (uuid.UTF8Characters, uuid.UTF8Length);
|
||||
uuid_str = uuid.UTF8Characters;
|
||||
if (!uuid_is_valid (uuid_str))
|
||||
{
|
||||
g_free (uuid_str);
|
||||
return FALSE;
|
||||
}
|
||||
return FALSE;
|
||||
|
||||
res = g_dbus_proxy_call_sync (obj->proxy,
|
||||
"GetExtensionErrors",
|
||||
@@ -604,8 +578,6 @@ plugin_get_errors (PluginObject *obj,
|
||||
NULL, /* cancellable */
|
||||
&error);
|
||||
|
||||
g_free (uuid_str);
|
||||
|
||||
if (!res)
|
||||
{
|
||||
g_warning ("Failed to retrieve errors: %s", error->message);
|
||||
@@ -661,8 +633,7 @@ plugin_get_shell_version (PluginObject *obj,
|
||||
STRINGN_TO_NPVARIANT (buffer, length, *result);
|
||||
|
||||
out:
|
||||
if (res)
|
||||
g_variant_unref (res);
|
||||
g_variant_unref (res);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
AC_PREREQ(2.63)
|
||||
AC_INIT([gnome-shell],[3.3.3],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
|
||||
AC_INIT([gnome-shell],[3.3.2],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
|
||||
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_CONFIG_SRCDIR([src/shell-global.c])
|
||||
@@ -63,7 +63,7 @@ AM_CONDITIONAL(BUILD_RECORDER, $build_recorder)
|
||||
CLUTTER_MIN_VERSION=1.7.5
|
||||
GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1
|
||||
GJS_MIN_VERSION=1.29.18
|
||||
MUTTER_MIN_VERSION=3.3.3
|
||||
MUTTER_MIN_VERSION=3.3.2
|
||||
FOLKS_MIN_VERSION=0.5.2
|
||||
GTK_MIN_VERSION=3.0.0
|
||||
GIO_MIN_VERSION=2.31.0
|
||||
|
@@ -60,7 +60,6 @@ StScrollBar StBin#trough {
|
||||
StScrollBar StButton#vhandle
|
||||
{
|
||||
background-image: url("scroll-vhandle.svg");
|
||||
background-size: contain;
|
||||
background-color: #252525;
|
||||
border: 1px solid #080808;
|
||||
border-radius: 8px;
|
||||
@@ -69,7 +68,6 @@ StScrollBar StButton#vhandle
|
||||
StScrollBar StButton#hhandle
|
||||
{
|
||||
background-image: url("scroll-hhandle.svg");
|
||||
background-size: contain;
|
||||
background-color: #252525;
|
||||
border: 1px solid #080808;
|
||||
border-radius: 8px;
|
||||
@@ -226,20 +224,16 @@ StTooltip StLabel {
|
||||
|
||||
.toggle-switch-us {
|
||||
background-image: url("toggle-off-us.svg");
|
||||
background-size: contain;
|
||||
}
|
||||
.toggle-switch-us:checked {
|
||||
background-image: url("toggle-on-us.svg");
|
||||
background-size: contain;
|
||||
}
|
||||
|
||||
.toggle-switch-intl {
|
||||
background-image: url("toggle-off-intl.svg");
|
||||
background-size: contain;
|
||||
}
|
||||
.toggle-switch-intl:checked {
|
||||
background-image: url("toggle-on-intl.svg");
|
||||
background-size: contain;
|
||||
}
|
||||
|
||||
.nm-menu-item-icons {
|
||||
@@ -362,7 +356,6 @@ StTooltip StLabel {
|
||||
.panel-button:focus {
|
||||
border-image: url("panel-button-border.svg") 10 10 0 2;
|
||||
background-image: url("panel-button-highlight-wide.svg");
|
||||
background-size: contain;
|
||||
color: white;
|
||||
text-shadow: black 0px 2px 2px;
|
||||
}
|
||||
@@ -371,7 +364,6 @@ StTooltip StLabel {
|
||||
.panel-status-button:checked,
|
||||
.panel-status-button:focus {
|
||||
background-image: url("panel-button-highlight-narrow.svg");
|
||||
background-size: contain;
|
||||
}
|
||||
|
||||
.panel-button:active > .system-status-icon,
|
||||
@@ -475,17 +467,16 @@ StTooltip StLabel {
|
||||
}
|
||||
|
||||
.window-caption {
|
||||
background: rgba(0,0,0,0.5);
|
||||
border-radius: 8px;
|
||||
background: rgba(0,0,0,0.8);
|
||||
border: 1px solid rgba(128,128,128,0.40);
|
||||
border-radius: 10px;
|
||||
font-size: 9pt;
|
||||
font-weight: bold;
|
||||
padding: 6px 12px;
|
||||
-shell-caption-spacing: 12px;
|
||||
padding: 2px 8px;
|
||||
-shell-caption-spacing: 4px;
|
||||
}
|
||||
|
||||
.window-close {
|
||||
background-image: url("close-window.svg");
|
||||
background-size: 34px;
|
||||
height: 34px;
|
||||
width: 34px;
|
||||
-shell-close-overlap: 20px;
|
||||
@@ -520,7 +511,6 @@ StTooltip StLabel {
|
||||
|
||||
.placeholder {
|
||||
background-image: url("dash-placeholder.svg");
|
||||
background-size: contain;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
@@ -655,17 +645,6 @@ StTooltip StLabel {
|
||||
font-size: 11pt;
|
||||
}
|
||||
|
||||
.dash-label {
|
||||
border-radius: 7px;
|
||||
padding: 4px 12px;
|
||||
background-color: rgba(0,0,0,0.5);
|
||||
color: #ffffff;
|
||||
font-size: 0.9em;
|
||||
font-weight: bold;;
|
||||
text-align: center;
|
||||
-x-offset: 8px;
|
||||
}
|
||||
|
||||
/* Apps */
|
||||
|
||||
.icon-grid {
|
||||
@@ -707,13 +686,11 @@ StTooltip StLabel {
|
||||
.app-filter:selected {
|
||||
color: #ffffff;
|
||||
background-image: url("filter-selected-ltr.svg");
|
||||
background-size: contain;
|
||||
background-position: 190px 10px;
|
||||
}
|
||||
|
||||
.app-filter:selected:rtl {
|
||||
background-image: url("filter-selected-rtl.svg");
|
||||
background-size: contain;
|
||||
background-position: 10px 10px;
|
||||
}
|
||||
|
||||
@@ -794,7 +771,6 @@ StTooltip StLabel {
|
||||
.app-well-app.running > .overview-icon {
|
||||
text-shadow: black 0px 2px 2px;
|
||||
background-image: url("running-indicator.svg");
|
||||
background-size: contain;
|
||||
}
|
||||
|
||||
.contact:selected,
|
||||
@@ -1456,7 +1432,6 @@ StTooltip StLabel {
|
||||
|
||||
.summary-source-button:selected .summary-source {
|
||||
background-image: url("panel-button-highlight-narrow.svg");
|
||||
background-size: contain;
|
||||
border-image: url("source-button-border.svg") 10 10 0 1;
|
||||
}
|
||||
|
||||
@@ -1467,7 +1442,6 @@ StTooltip StLabel {
|
||||
|
||||
.summary-source-button:expanded:selected {
|
||||
background-image: url("panel-button-highlight-wide.svg");
|
||||
background-size: contain;
|
||||
border-image: url("source-button-border.svg") 10 10 0 1;
|
||||
}
|
||||
|
||||
@@ -1581,7 +1555,6 @@ StTooltip StLabel {
|
||||
width: 52px;
|
||||
height: 52px;
|
||||
background-image: url("corner-ripple-ltr.png");
|
||||
background-size: contain;
|
||||
}
|
||||
|
||||
.ripple-box:rtl {
|
||||
@@ -1623,7 +1596,6 @@ StTooltip StLabel {
|
||||
border: 0px;
|
||||
background: rgba(255,255,255,0.5);
|
||||
background-image: url("ws-switch-arrow-up.svg");
|
||||
background-size: contain;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
@@ -1632,7 +1604,6 @@ StTooltip StLabel {
|
||||
border: 0px;
|
||||
background: rgba(255,255,255,0.5);
|
||||
background-image: url("ws-switch-arrow-down.svg");
|
||||
background-size: contain;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
|
@@ -18,10 +18,11 @@ DOC_MODULE=shell
|
||||
# The top-level SGML file. You can change this if you want to.
|
||||
DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml
|
||||
|
||||
# Directories containing the source code
|
||||
# Directories containing the source code, relative to $(srcdir).
|
||||
# gtk-doc will search all .c and .h files beneath these paths
|
||||
# for inline comments documenting functions and macros.
|
||||
DOC_SOURCE_DIR=$(top_srcdir)/src
|
||||
# e.g. DOC_SOURCE_DIR=../../../gtk ../../../gdk
|
||||
DOC_SOURCE_DIR=../../../src
|
||||
|
||||
# Extra options to pass to gtkdoc-scangobj. Not normally needed.
|
||||
SCANGOBJ_OPTIONS=
|
||||
@@ -57,16 +58,7 @@ EXTRA_HFILES=
|
||||
|
||||
# Header files or dirs to ignore when scanning. Use base file/dir names
|
||||
# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h private_code
|
||||
IGNORE_HFILES= \
|
||||
calendar-server \
|
||||
gvc \
|
||||
hotplug-sniffer \
|
||||
st \
|
||||
tray \
|
||||
gactionmuxer.h \
|
||||
gactionobservable.h \
|
||||
gactionobserver.h \
|
||||
shell-recorder-src.h
|
||||
IGNORE_HFILES=calendar-server gvc hotplug-sniffer st tray
|
||||
|
||||
# Images to copy into HTML directory.
|
||||
# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
|
||||
@@ -87,7 +79,7 @@ expand_content_files=
|
||||
# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
|
||||
# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
|
||||
GTKDOC_CFLAGS=$(GNOME_SHELL_CFLAGS)
|
||||
GTKDOC_LIBS=$(GNOME_SHELL_LIBS) $(BLUETOOTH_LIBS) $(top_builddir)/src/libgnome-shell.la
|
||||
GTKDOC_LIBS=$(GNOME_SHELL_LIBS) $(top_builddir)/src/libgnome-shell.la
|
||||
|
||||
# This includes the standard gtk-doc make rules, copied by gtkdocize.
|
||||
include $(top_srcdir)/gtk-doc.make
|
||||
|
@@ -18,10 +18,11 @@ DOC_MODULE=st
|
||||
# The top-level SGML file. You can change this if you want to.
|
||||
DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml
|
||||
|
||||
# Directories containing the source code
|
||||
# Directories containing the source code, relative to $(srcdir).
|
||||
# gtk-doc will search all .c and .h files beneath these paths
|
||||
# for inline comments documenting functions and macros.
|
||||
DOC_SOURCE_DIR=$(top_srcdir)/src/st
|
||||
# e.g. DOC_SOURCE_DIR=../../../gtk ../../../gdk
|
||||
DOC_SOURCE_DIR=../../../src/st
|
||||
|
||||
# Extra options to pass to gtkdoc-scangobj. Not normally needed.
|
||||
SCANGOBJ_OPTIONS=
|
||||
|
@@ -72,7 +72,6 @@ nobase_dist_js_DATA = \
|
||||
ui/tweener.js \
|
||||
ui/userMenu.js \
|
||||
ui/viewSelector.js \
|
||||
ui/wanda.js \
|
||||
ui/windowAttentionHandler.js \
|
||||
ui/windowManager.js \
|
||||
ui/workspace.js \
|
||||
|
@@ -38,7 +38,7 @@ function recursivelyDeleteDir(dir) {
|
||||
let child = dir.get_child(info.get_name());
|
||||
if (type == Gio.FileType.REGULAR)
|
||||
deleteGFile(child);
|
||||
else if (type == Gio.FileType.DIRECTORY)
|
||||
else if (type == Gio.TypeType.DIRECTORY)
|
||||
recursivelyDeleteDir(child);
|
||||
}
|
||||
|
||||
|
@@ -232,53 +232,3 @@ function fixupPCIDescription(desc) {
|
||||
|
||||
return out.join(' ');
|
||||
}
|
||||
|
||||
// lowerBound:
|
||||
// @array: an array or array-like object, already sorted
|
||||
// according to @cmp
|
||||
// @val: the value to add
|
||||
// @cmp: a comparator (or undefined to compare as numbers)
|
||||
//
|
||||
// Returns the position of the first element that is not
|
||||
// lower than @val, according to @cmp.
|
||||
// That is, returns the first position at which it
|
||||
// is possible to insert @val without violating the
|
||||
// order.
|
||||
// This is quite like an ordinary binary search, except
|
||||
// that it doesn't stop at first element comparing equal.
|
||||
|
||||
function lowerBound(array, val, cmp) {
|
||||
let min, max, mid, v;
|
||||
cmp = cmp || function(a, b) { return a - b; };
|
||||
|
||||
if (array.length == 0)
|
||||
return 0;
|
||||
|
||||
min = 0; max = array.length;
|
||||
while (min < (max - 1)) {
|
||||
mid = Math.floor((min + max) / 2);
|
||||
v = cmp(array[mid], val);
|
||||
|
||||
if (v < 0)
|
||||
min = mid + 1;
|
||||
else
|
||||
max = mid;
|
||||
}
|
||||
|
||||
return (min == max || cmp(array[min], val) < 0) ? max : min;
|
||||
}
|
||||
|
||||
// insertSorted:
|
||||
// @array: an array sorted according to @cmp
|
||||
// @val: a value to insert
|
||||
// @cmp: the sorting function
|
||||
//
|
||||
// Inserts @val into @array, preserving the
|
||||
// sorting invariants.
|
||||
// Returns the position at which it was inserted
|
||||
function insertSorted(array, val, cmp) {
|
||||
let pos = lowerBound(array, val, cmp);
|
||||
array.splice(pos, 0, val);
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
@@ -470,7 +470,6 @@ const AppWellIcon = new Lang.Class({
|
||||
Lang.bind(this,
|
||||
this._onStateChanged));
|
||||
this._onStateChanged();
|
||||
this.isMenuUp = false;
|
||||
},
|
||||
|
||||
_onDestroy: function() {
|
||||
@@ -552,8 +551,8 @@ const AppWellIcon = new Lang.Class({
|
||||
this._menuManager.addMenu(this._menu);
|
||||
}
|
||||
|
||||
this.isMenuUp = true;
|
||||
this.actor.set_hover(true);
|
||||
this.actor.show_tooltip();
|
||||
this._menu.popup();
|
||||
|
||||
return false;
|
||||
@@ -569,7 +568,6 @@ const AppWellIcon = new Lang.Class({
|
||||
|
||||
_onMenuPoppedDown: function() {
|
||||
this.actor.sync_hover();
|
||||
this.isMenuUp = false;
|
||||
},
|
||||
|
||||
_onActivate: function (event) {
|
||||
|
@@ -557,7 +557,7 @@ const AutorunTransientNotification = new Lang.Class({
|
||||
|
||||
let label = new St.Bin({ y_align: St.Align.MIDDLE,
|
||||
child: new St.Label
|
||||
({ text: _("Open with %s").format(app.get_name()) })
|
||||
({ text: _("Open with %s").format(app.get_display_name()) })
|
||||
});
|
||||
box.add(label);
|
||||
|
||||
|
@@ -6,7 +6,6 @@ const Lang = imports.lang;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Shell = imports.gi.Shell;
|
||||
const St = imports.gi.St;
|
||||
const Mainloop = imports.mainloop;
|
||||
|
||||
const AppDisplay = imports.ui.appDisplay;
|
||||
const AppFavorites = imports.ui.appFavorites;
|
||||
@@ -17,9 +16,6 @@ const Tweener = imports.ui.tweener;
|
||||
const Workspace = imports.ui.workspace;
|
||||
|
||||
const DASH_ANIMATION_TIME = 0.2;
|
||||
const DASH_ITEM_LABEL_SHOW_TIME = 0.15;
|
||||
const DASH_ITEM_LABEL_HIDE_TIME = 0.1;
|
||||
const DASH_ITEM_HOVER_TIMEOUT = 300;
|
||||
|
||||
// A container like StBin, but taking the child's scale into account
|
||||
// when requesting a size
|
||||
@@ -36,8 +32,6 @@ const DashItemContainer = new Lang.Class({
|
||||
Lang.bind(this, this._allocate));
|
||||
this.actor._delegate = this;
|
||||
|
||||
this._label = null;
|
||||
|
||||
this.child = null;
|
||||
this._childScale = 1;
|
||||
this._childOpacity = 255;
|
||||
@@ -90,60 +84,6 @@ const DashItemContainer = new Lang.Class({
|
||||
alloc.natural_size = natWidth * this.child.scale_y;
|
||||
},
|
||||
|
||||
showLabel: function() {
|
||||
if (this._label == null)
|
||||
return;
|
||||
|
||||
this._label.opacity = 0;
|
||||
this._label.show();
|
||||
|
||||
let [stageX, stageY] = this.actor.get_transformed_position();
|
||||
|
||||
let itemHeight = this.actor.allocation.y2 - this.actor.allocation.y1;
|
||||
|
||||
let labelHeight = this._label.get_height();
|
||||
let yOffset = Math.floor((itemHeight - labelHeight) / 2)
|
||||
|
||||
let y = stageY + yOffset;
|
||||
|
||||
let node = this._label.get_theme_node();
|
||||
let xOffset = node.get_length('-x-offset');
|
||||
|
||||
let x;
|
||||
if (St.Widget.get_default_direction () == St.TextDirection.RTL)
|
||||
x = stageX - this._label.get_width() - xOffset;
|
||||
else
|
||||
x = stageX + this.actor.get_width() + xOffset;
|
||||
|
||||
this._label.set_position(x, y);
|
||||
Tweener.addTween(this._label,
|
||||
{ opacity: 255,
|
||||
time: DASH_ITEM_LABEL_SHOW_TIME,
|
||||
transition: 'easeOutQuad',
|
||||
});
|
||||
},
|
||||
|
||||
setLabelText: function(text) {
|
||||
if (this._label == null)
|
||||
this._label = new St.Label({ style_class: 'dash-label'});
|
||||
|
||||
this._label.set_text(text);
|
||||
Main.layoutManager.addChrome(this._label);
|
||||
this._label.hide();
|
||||
},
|
||||
|
||||
hideLabel: function () {
|
||||
this._label.opacity = 255;
|
||||
Tweener.addTween(this._label,
|
||||
{ opacity: 0,
|
||||
time: DASH_ITEM_LABEL_HIDE_TIME,
|
||||
transition: 'easeOutQuad',
|
||||
onComplete: Lang.bind(this, function() {
|
||||
this._label.hide();
|
||||
})
|
||||
});
|
||||
},
|
||||
|
||||
setChild: function(actor) {
|
||||
if (this.child == actor)
|
||||
return;
|
||||
@@ -298,7 +238,6 @@ const Dash = new Lang.Class({
|
||||
this._dragPlaceholderPos = -1;
|
||||
this._animatingPlaceholdersCount = 0;
|
||||
this._favRemoveTarget = null;
|
||||
this._labelTimeoutId = 0;
|
||||
|
||||
this._box = new St.BoxLayout({ name: 'dash',
|
||||
vertical: true,
|
||||
@@ -432,35 +371,14 @@ const Dash = new Lang.Class({
|
||||
Lang.bind(this, function() {
|
||||
display.actor.opacity = 255;
|
||||
}));
|
||||
display.actor.set_tooltip_text(app.get_name());
|
||||
|
||||
let item = new DashItemContainer();
|
||||
item.setChild(display.actor);
|
||||
|
||||
item.setLabelText(app.get_name());
|
||||
|
||||
display.icon.setIconSize(this.iconSize);
|
||||
display.actor.connect('notify::hover',
|
||||
Lang.bind(this, function() {
|
||||
this._onHover(item, display)
|
||||
}));
|
||||
return item;
|
||||
},
|
||||
|
||||
_onHover: function (item, display) {
|
||||
if (display.actor.get_hover() && !display.isMenuUp) {
|
||||
if (this._labelTimeoutId == 0) {
|
||||
this._labelTimeoutId = Mainloop.timeout_add(DASH_ITEM_HOVER_TIMEOUT,
|
||||
Lang.bind(this, function() {
|
||||
item.showLabel();
|
||||
return false;
|
||||
}));
|
||||
}
|
||||
} else {
|
||||
if (this._labelTimeoutId > 0)
|
||||
Mainloop.source_remove(this._labelTimeoutId);
|
||||
this._labelTimeoutId = 0;
|
||||
item.hideLabel();
|
||||
}
|
||||
return item;
|
||||
},
|
||||
|
||||
_adjustIconSize: function() {
|
||||
|
@@ -202,7 +202,7 @@ function gotExtensionZipFile(session, message, uuid) {
|
||||
global.settings.set_strv(ENABLED_EXTENSIONS_KEY, enabledExtensions);
|
||||
}
|
||||
|
||||
loadExtension(dir, ExtensionType.PER_USER, true);
|
||||
loadExtension(dir, true, ExtensionType.PER_USER);
|
||||
});
|
||||
}
|
||||
|
||||
|
@@ -35,8 +35,7 @@ const BaseIcon = new Lang.Class({
|
||||
this.actor.set_child(box);
|
||||
|
||||
this.iconSize = ICON_SIZE;
|
||||
this._iconBin = new St.Bin({ x_align: St.Align.MIDDLE,
|
||||
y_align: St.Align.MIDDLE });
|
||||
this._iconBin = new St.Bin();
|
||||
|
||||
box.add_actor(this._iconBin);
|
||||
|
||||
@@ -126,12 +125,12 @@ const BaseIcon = new Lang.Class({
|
||||
this.iconSize = size;
|
||||
this.icon = this.createIcon(this.iconSize);
|
||||
|
||||
this._iconBin.child = this.icon;
|
||||
|
||||
// The icon returned by createIcon() might actually be smaller than
|
||||
// the requested icon size (for instance StTextureCache does this
|
||||
// for fallback icons), so set the size explicitly.
|
||||
this._iconBin.set_size(this.iconSize, this.iconSize);
|
||||
this.icon.set_size(this.iconSize, this.iconSize);
|
||||
|
||||
this._iconBin.child = this.icon;
|
||||
},
|
||||
|
||||
_onStyleChanged: function() {
|
||||
@@ -146,11 +145,6 @@ const BaseIcon = new Lang.Class({
|
||||
size = found ? len : ICON_SIZE;
|
||||
}
|
||||
|
||||
// don't create icons unnecessarily
|
||||
if (size == this.iconSize &&
|
||||
this._iconBin.child)
|
||||
return;
|
||||
|
||||
this._createIconTexture(size);
|
||||
}
|
||||
});
|
||||
|
@@ -433,9 +433,9 @@ const HotCorner = new Lang.Class({
|
||||
Lang.bind(this, this._onCornerLeft));
|
||||
|
||||
// Cache the three ripples instead of dynamically creating and destroying them.
|
||||
this._ripple1 = new St.BoxLayout({ style_class: 'ripple-box', opacity: 0, visible: false });
|
||||
this._ripple2 = new St.BoxLayout({ style_class: 'ripple-box', opacity: 0, visible: false });
|
||||
this._ripple3 = new St.BoxLayout({ style_class: 'ripple-box', opacity: 0, visible: false });
|
||||
this._ripple1 = new St.BoxLayout({ style_class: 'ripple-box', opacity: 0 });
|
||||
this._ripple2 = new St.BoxLayout({ style_class: 'ripple-box', opacity: 0 });
|
||||
this._ripple3 = new St.BoxLayout({ style_class: 'ripple-box', opacity: 0 });
|
||||
|
||||
Main.uiGroup.add_actor(this._ripple1);
|
||||
Main.uiGroup.add_actor(this._ripple2);
|
||||
|
@@ -44,7 +44,7 @@ const Magnifier = new Lang.Class({
|
||||
this._zoomRegions = [];
|
||||
|
||||
// Create small clutter tree for the magnified mouse.
|
||||
let xfixesCursor = Shell.XFixesCursor.get_for_stage(global.stage);
|
||||
let xfixesCursor = Shell.XFixesCursor.get_default();
|
||||
this._mouseSprite = new Clutter.Texture();
|
||||
xfixesCursor.update_texture_image(this._mouseSprite);
|
||||
this._cursorRoot = new Clutter.Group();
|
||||
|
@@ -1430,16 +1430,8 @@ const MessageTray = new Lang.Class({
|
||||
this._notificationRemoved = false;
|
||||
this._reNotifyAfterHideNotification = null;
|
||||
|
||||
this._corner = new Clutter.Rectangle({ width: 1,
|
||||
height: 1,
|
||||
opacity: 0,
|
||||
reactive: true });
|
||||
this._corner.connect('enter-event', Lang.bind(this, this._onCornerEnter));
|
||||
Main.layoutManager.trayBox.add_actor(this._corner);
|
||||
Main.layoutManager.trackChrome(this._corner);
|
||||
|
||||
Main.layoutManager.trayBox.add_actor(this.actor);
|
||||
this.actor.y = this.actor.height;
|
||||
this.actor.y = -1;
|
||||
Main.layoutManager.trackChrome(this.actor);
|
||||
Main.layoutManager.trackChrome(this._notificationBin);
|
||||
|
||||
@@ -1478,24 +1470,12 @@ const MessageTray = new Lang.Class({
|
||||
this._chatSummaryItemsCount = 0;
|
||||
},
|
||||
|
||||
_onCornerEnter: function(actor, event) {
|
||||
this._pointerInSummary = true;
|
||||
this._updateState();
|
||||
},
|
||||
|
||||
_setSizePosition: function() {
|
||||
let monitor = Main.layoutManager.bottomMonitor;
|
||||
this._notificationBin.x = 0;
|
||||
this._notificationBin.width = monitor.width;
|
||||
this._summaryBin.x = 0;
|
||||
this._summaryBin.width = monitor.width;
|
||||
|
||||
if (St.Widget.get_default_direction() == St.TextDirection.RTL)
|
||||
this._corner.x = 0;
|
||||
else
|
||||
this._corner.x = Main.layoutManager.trayBox.width - 1;
|
||||
|
||||
this._corner.y = Main.layoutManager.trayBox.height - 1;
|
||||
},
|
||||
|
||||
contains: function(source) {
|
||||
@@ -2096,7 +2076,7 @@ const MessageTray = new Lang.Class({
|
||||
|
||||
_hideTray: function() {
|
||||
this._tween(this.actor, '_trayState', State.HIDDEN,
|
||||
{ y: this.actor.height,
|
||||
{ y: -1,
|
||||
time: ANIMATION_TIME,
|
||||
transition: 'easeOutQuad'
|
||||
});
|
||||
|
@@ -94,7 +94,7 @@ const NotificationDaemon = new Lang.Class({
|
||||
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(NotificationDaemonIface, this);
|
||||
this._dbusImpl.export(Gio.DBus.session, '/org/freedesktop/Notifications');
|
||||
|
||||
this._sources = [];
|
||||
this._sources = {};
|
||||
this._senderToPid = {};
|
||||
this._notifications = {};
|
||||
this._busProxy = new Bus();
|
||||
@@ -152,30 +152,14 @@ const NotificationDaemon = new Lang.Class({
|
||||
}
|
||||
},
|
||||
|
||||
_lookupSource: function(title, pid, trayIcon) {
|
||||
for (let i = 0; i < this._sources.length; i++) {
|
||||
let source = this._sources[i];
|
||||
if (source.pid == pid &&
|
||||
(source.initialTitle == title || source.trayIcon || trayIcon))
|
||||
return source;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
// Returns the source associated with ndata.notification if it is set.
|
||||
// Otherwise, returns the source associated with the title and pid if
|
||||
// such source is stored in this._sources and the notification is not
|
||||
// transient. If the existing or requested source is associated with
|
||||
// a tray icon and passed in pid matches a pid of an existing source,
|
||||
// the title match is ignored to enable representing a tray icon and
|
||||
// notifications from the same application with a single source.
|
||||
//
|
||||
// If no existing source is found, a new source is created as long as
|
||||
// pid is provided.
|
||||
// Otherwise, returns the source associated with the pid if one is
|
||||
// stored in this._sources and the notification is not transient.
|
||||
// Otherwise, creates a new source as long as pid is provided.
|
||||
//
|
||||
// Either a pid or ndata.notification is needed to retrieve or
|
||||
// create a source.
|
||||
_getSource: function(title, pid, ndata, sender, trayIcon) {
|
||||
_getSource: function(title, pid, ndata, sender) {
|
||||
if (!pid && !(ndata && ndata.notification))
|
||||
return null;
|
||||
|
||||
@@ -192,24 +176,20 @@ const NotificationDaemon = new Lang.Class({
|
||||
// with a transient one from the same sender, so we
|
||||
// always create a new source object for new transient notifications
|
||||
// and never add it to this._sources .
|
||||
if (!isForTransientNotification) {
|
||||
let source = this._lookupSource(title, pid, trayIcon);
|
||||
if (source) {
|
||||
source.setTitle(title);
|
||||
return source;
|
||||
}
|
||||
if (!isForTransientNotification && this._sources[pid]) {
|
||||
let source = this._sources[pid];
|
||||
source.setTitle(title);
|
||||
return source;
|
||||
}
|
||||
|
||||
let source = new Source(title, pid, sender, trayIcon);
|
||||
let source = new Source(title, pid, sender);
|
||||
source.setTransient(isForTransientNotification);
|
||||
|
||||
if (!isForTransientNotification) {
|
||||
this._sources.push(source);
|
||||
this._sources[pid] = source;
|
||||
source.connect('destroy', Lang.bind(this,
|
||||
function() {
|
||||
let index = this._sources.indexOf(source);
|
||||
if (index >= 0)
|
||||
this._sources.splice(index, 1);
|
||||
delete this._sources[pid];
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -288,7 +268,7 @@ const NotificationDaemon = new Lang.Class({
|
||||
let sender = invocation.get_sender();
|
||||
let pid = this._senderToPid[sender];
|
||||
|
||||
let source = this._getSource(appName, pid, ndata, sender, null);
|
||||
let source = this._getSource(appName, pid, ndata, sender);
|
||||
|
||||
if (source) {
|
||||
this._notifyForSource(source, ndata);
|
||||
@@ -314,7 +294,7 @@ const NotificationDaemon = new Lang.Class({
|
||||
}
|
||||
|
||||
let [pid] = result;
|
||||
source = this._getSource(appName, pid, ndata, sender, null);
|
||||
source = this._getSource(appName, pid, ndata, sender);
|
||||
|
||||
// We only store sender-pid entries for persistent sources.
|
||||
// Removing the entries once the source is destroyed
|
||||
@@ -463,8 +443,8 @@ const NotificationDaemon = new Lang.Class({
|
||||
if (!tracker.focus_app)
|
||||
return;
|
||||
|
||||
for (let i = 0; i < this._sources.length; i++) {
|
||||
let source = this._sources[i];
|
||||
for (let id in this._sources) {
|
||||
let source = this._sources[id];
|
||||
if (source.app == tracker.focus_app) {
|
||||
source.destroyNonResidentNotifications();
|
||||
return;
|
||||
@@ -483,11 +463,12 @@ const NotificationDaemon = new Lang.Class({
|
||||
},
|
||||
|
||||
_onTrayIconAdded: function(o, icon) {
|
||||
let source = this._getSource(icon.title || icon.wm_class || _("Unknown"), icon.pid, null, null, icon);
|
||||
let source = this._getSource(icon.title || icon.wm_class || _("Unknown"), icon.pid, null, null);
|
||||
source.setTrayIcon(icon);
|
||||
},
|
||||
|
||||
_onTrayIconRemoved: function(o, icon) {
|
||||
let source = this._lookupSource(icon.pid, null, true);
|
||||
let source = this._sources[icon.pid];
|
||||
if (source)
|
||||
source.destroy();
|
||||
}
|
||||
@@ -497,12 +478,10 @@ const Source = new Lang.Class({
|
||||
Name: 'NotificationDaemonSource',
|
||||
Extends: MessageTray.Source,
|
||||
|
||||
_init: function(title, pid, sender, trayIcon) {
|
||||
_init: function(title, pid, sender) {
|
||||
this.parent(title);
|
||||
|
||||
this.initialTitle = title;
|
||||
|
||||
this.pid = pid;
|
||||
this._pid = pid;
|
||||
if (sender)
|
||||
this._nameWatcherId = Gio.DBus.session.watch_name(sender,
|
||||
Gio.BusNameWatcherFlags.NONE,
|
||||
@@ -516,12 +495,7 @@ const Source = new Lang.Class({
|
||||
this.title = this.app.get_name();
|
||||
else
|
||||
this.useNotificationIcon = true;
|
||||
|
||||
this.trayIcon = trayIcon;
|
||||
if (this.trayIcon) {
|
||||
this._setSummaryIcon(this.trayIcon);
|
||||
this.useNotificationIcon = false;
|
||||
}
|
||||
this._trayIcon = null;
|
||||
},
|
||||
|
||||
_onNameVanished: function() {
|
||||
@@ -548,7 +522,7 @@ const Source = new Lang.Class({
|
||||
},
|
||||
|
||||
handleSummaryClick: function() {
|
||||
if (!this.trayIcon)
|
||||
if (!this._trayIcon)
|
||||
return false;
|
||||
|
||||
let event = Clutter.get_current_event();
|
||||
@@ -569,11 +543,11 @@ const Source = new Lang.Class({
|
||||
let id = global.connect('notify::stage-input-mode', Lang.bind(this,
|
||||
function () {
|
||||
global.disconnect(id);
|
||||
this.trayIcon.click(event);
|
||||
this._trayIcon.click(event);
|
||||
}));
|
||||
Main.overview.hide();
|
||||
} else {
|
||||
this.trayIcon.click(event);
|
||||
this._trayIcon.click(event);
|
||||
}
|
||||
return true;
|
||||
},
|
||||
@@ -582,25 +556,31 @@ const Source = new Lang.Class({
|
||||
if (this.app)
|
||||
return;
|
||||
|
||||
this.app = Shell.WindowTracker.get_default().get_app_from_pid(this.pid);
|
||||
this.app = Shell.WindowTracker.get_default().get_app_from_pid(this._pid);
|
||||
if (!this.app)
|
||||
return;
|
||||
|
||||
// Only override the icon if we were previously using
|
||||
// notification-based icons (ie, not a trayicon) or if it was unset before
|
||||
if (!this.trayIcon) {
|
||||
if (!this._trayIcon) {
|
||||
this.useNotificationIcon = false;
|
||||
this._setSummaryIcon(this.app.create_icon_texture (this.ICON_SIZE));
|
||||
}
|
||||
},
|
||||
|
||||
setTrayIcon: function(icon) {
|
||||
this._setSummaryIcon(icon);
|
||||
this.useNotificationIcon = false;
|
||||
this._trayIcon = icon;
|
||||
},
|
||||
|
||||
open: function(notification) {
|
||||
this.destroyNonResidentNotifications();
|
||||
this.openApp();
|
||||
},
|
||||
|
||||
_lastNotificationRemoved: function() {
|
||||
if (!this.trayIcon)
|
||||
if (!this._trayIcon)
|
||||
this.destroy();
|
||||
},
|
||||
|
||||
|
@@ -23,7 +23,6 @@ const Params = imports.misc.params;
|
||||
const PlaceDisplay = imports.ui.placeDisplay;
|
||||
const Tweener = imports.ui.tweener;
|
||||
const ViewSelector = imports.ui.viewSelector;
|
||||
const Wanda = imports.ui.wanda;
|
||||
const WorkspacesView = imports.ui.workspacesView;
|
||||
const WorkspaceThumbnail = imports.ui.workspaceThumbnail;
|
||||
|
||||
@@ -109,6 +108,7 @@ const Overview = new Lang.Class({
|
||||
if (this.isDummy) {
|
||||
this.animationInProgress = false;
|
||||
this.visible = false;
|
||||
this.workspaces = null;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -180,6 +180,8 @@ const Overview = new Lang.Class({
|
||||
this._lastActiveWorkspaceIndex = -1;
|
||||
this._lastHoveredWindow = null;
|
||||
this._needsFakePointerEvent = false;
|
||||
|
||||
this.workspaces = null;
|
||||
},
|
||||
|
||||
// The members we construct that are implemented in JS might
|
||||
@@ -202,8 +204,6 @@ const Overview = new Lang.Class({
|
||||
this._viewSelector.addViewTab('applications', _("Applications"), appView.actor, 'system-run');
|
||||
|
||||
// Default search providers
|
||||
// Wanda comes obviously first
|
||||
this.addSearchProvider(new Wanda.WandaSearchProvider());
|
||||
this.addSearchProvider(new AppDisplay.AppSearchProvider());
|
||||
this.addSearchProvider(new AppDisplay.SettingsSearchProvider());
|
||||
this.addSearchProvider(new PlaceDisplay.PlaceSearchProvider());
|
||||
@@ -587,10 +587,13 @@ const Overview = new Lang.Class({
|
||||
|
||||
this._workspacesDisplay.show();
|
||||
|
||||
this.workspaces = this._workspacesDisplay.workspacesView;
|
||||
global.overlay_group.add_actor(this.workspaces.actor);
|
||||
|
||||
if (!this._desktopFade.child)
|
||||
this._desktopFade.child = this._getDesktopClone();
|
||||
|
||||
if (!this._workspacesDisplay.activeWorkspaceHasMaximizedWindows()) {
|
||||
if (!this.workspaces.getActiveWorkspace().hasMaximizedWindows()) {
|
||||
this._desktopFade.opacity = 255;
|
||||
this._desktopFade.show();
|
||||
Tweener.addTween(this._desktopFade,
|
||||
@@ -725,7 +728,7 @@ const Overview = new Lang.Class({
|
||||
this.animationInProgress = true;
|
||||
this._hideInProgress = true;
|
||||
|
||||
if (!this._workspacesDisplay.activeWorkspaceHasMaximizedWindows()) {
|
||||
if (!this.workspaces.getActiveWorkspace().hasMaximizedWindows()) {
|
||||
this._desktopFade.opacity = 0;
|
||||
this._desktopFade.show();
|
||||
Tweener.addTween(this._desktopFade,
|
||||
@@ -734,7 +737,7 @@ const Overview = new Lang.Class({
|
||||
transition: 'easeOutQuad' });
|
||||
}
|
||||
|
||||
this._workspacesDisplay.zoomFromOverview();
|
||||
this.workspaces.hide();
|
||||
|
||||
// Make other elements fade out.
|
||||
Tweener.addTween(this._group,
|
||||
@@ -776,6 +779,9 @@ const Overview = new Lang.Class({
|
||||
|
||||
global.window_group.show();
|
||||
|
||||
this.workspaces.destroy();
|
||||
this.workspaces = null;
|
||||
|
||||
this._workspacesDisplay.hide();
|
||||
|
||||
this._desktopFade.hide();
|
||||
|
@@ -939,12 +939,7 @@ const PopupMenuBase = new Lang.Class({
|
||||
this.emit('activate', menuItem);
|
||||
this.close(true);
|
||||
}));
|
||||
// the weird name is to avoid a conflict with some random property
|
||||
// the menuItem may have, called destroyId
|
||||
// (FIXME: in the future it may make sense to have container objects
|
||||
// like PopupMenuManager does)
|
||||
menuItem._popupMenuDestroyId = menuItem.connect('destroy', Lang.bind(this, function(menuItem) {
|
||||
menuItem.disconnect(menuItem._popupMenuDestroyId);
|
||||
menuItem.connect('destroy', Lang.bind(this, function(emitter) {
|
||||
menuItem.disconnect(menuItem._activateId);
|
||||
menuItem.disconnect(menuItem._activeChangeId);
|
||||
menuItem.disconnect(menuItem._sensitiveChangeId);
|
||||
|
@@ -30,6 +30,7 @@ const Indicator = new Lang.Class({
|
||||
_init: function() {
|
||||
this.parent('bluetooth-disabled', null);
|
||||
|
||||
GLib.spawn_command_line_sync ('pkill -f "^bluetooth-applet$"');
|
||||
this._applet = new GnomeBluetoothApplet.Applet();
|
||||
|
||||
this._killswitch = new PopupMenu.PopupSwitchMenuItem(_("Bluetooth"), false);
|
||||
|
@@ -249,11 +249,9 @@ const NMWirelessSectionTitleMenuItem = new Lang.Class({
|
||||
updateForDevice: function(device) {
|
||||
// we show the switch
|
||||
// - if there not just one device
|
||||
// - if the switch is off (but it can be turned on)
|
||||
// - if the switch is off
|
||||
// - if the device is activated or disconnected
|
||||
if (!this._hardwareEnabled) {
|
||||
this.setStatus(_("hardware disabled"));
|
||||
} else if (device && this._softwareEnabled) {
|
||||
if (device && this._softwareEnabled && this._hardwareEnabled) {
|
||||
let text = device.getStatusLabel();
|
||||
this.setStatus(text);
|
||||
} else
|
||||
@@ -329,7 +327,7 @@ const NMDevice = new Lang.Class({
|
||||
}
|
||||
this.section = new PopupMenu.PopupMenuSection();
|
||||
|
||||
this._deferredWorkId = Main.initializeDeferredWork(this.section.actor, Lang.bind(this, this._createSection));
|
||||
this._createSection();
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
@@ -396,29 +394,16 @@ const NMDevice = new Lang.Class({
|
||||
this._activeConnection = activeConnection;
|
||||
|
||||
this._clearSection();
|
||||
this._queueCreateSection();
|
||||
this._createSection();
|
||||
},
|
||||
|
||||
checkConnection: function(connection) {
|
||||
let pos = this._findConnection(connection._uuid);
|
||||
let exists = pos != -1;
|
||||
let exists = this._findConnection(connection._uuid) != -1;
|
||||
let valid = this.connectionValid(connection);
|
||||
|
||||
if (exists && !valid)
|
||||
this.removeConnection(connection);
|
||||
else if (!exists && valid)
|
||||
this.addConnection(connection);
|
||||
else if (exists && valid) {
|
||||
// propagate changes and update the UI
|
||||
|
||||
if (this._connections[pos].timestamp != connection._timestamp) {
|
||||
this._connections[pos].timestamp = connection._timestamp;
|
||||
this._connections.sort(this._connectionSortFunction);
|
||||
|
||||
this._clearSection();
|
||||
this._queueCreateSection();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
addConnection: function(connection) {
|
||||
@@ -433,7 +418,7 @@ const NMDevice = new Lang.Class({
|
||||
this._connections.sort(this._connectionSortFunction);
|
||||
|
||||
this._clearSection();
|
||||
this._queueCreateSection();
|
||||
this._createSection();
|
||||
},
|
||||
|
||||
removeConnection: function(connection) {
|
||||
@@ -457,7 +442,7 @@ const NMDevice = new Lang.Class({
|
||||
// (or in the case of NMDeviceWired, we want to hide
|
||||
// the only explicit connection)
|
||||
this._clearSection();
|
||||
this._queueCreateSection();
|
||||
this._createSection();
|
||||
}
|
||||
},
|
||||
|
||||
@@ -541,11 +526,6 @@ const NMDevice = new Lang.Class({
|
||||
return -1;
|
||||
},
|
||||
|
||||
_queueCreateSection: function() {
|
||||
this._clearSection();
|
||||
Main.queueDeferredWork(this._deferredWorkId);
|
||||
},
|
||||
|
||||
_clearSection: function() {
|
||||
// Clear everything
|
||||
this.section.removeAll();
|
||||
@@ -640,7 +620,7 @@ const NMDevice = new Lang.Class({
|
||||
this._updateStatusItem();
|
||||
|
||||
this._clearSection();
|
||||
this._queueCreateSection();
|
||||
this._createSection();
|
||||
this.emit('state-changed');
|
||||
},
|
||||
|
||||
@@ -884,12 +864,7 @@ const NMDeviceBluetooth = new Lang.Class({
|
||||
this._autoConnectionName = this._makeConnectionName(this.device);
|
||||
|
||||
this._clearSection();
|
||||
this._queueCreateSection();
|
||||
this._updateStatusItem();
|
||||
},
|
||||
|
||||
_getDescription: function() {
|
||||
return this.device.name || _("Bluetooth");
|
||||
this._createSection();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1234,6 +1209,7 @@ const NMDeviceWireless = new Lang.Class({
|
||||
accessPoints: [ accessPoint ]
|
||||
};
|
||||
apObj.ssidText = ssidToLabel(apObj.ssid);
|
||||
needsupdate = true;
|
||||
}
|
||||
|
||||
// check if this enables new connections for this group
|
||||
@@ -1248,13 +1224,37 @@ const NMDeviceWireless = new Lang.Class({
|
||||
}
|
||||
}
|
||||
|
||||
if (pos == -1 || needsupdate) {
|
||||
if (needsupdate) {
|
||||
if (apObj.item)
|
||||
apObj.item.destroy();
|
||||
|
||||
if (pos != -1)
|
||||
this._networks.splice(pos, 1);
|
||||
pos = Util.insertSorted(this._networks, apObj, this._networkSortFunction);
|
||||
|
||||
this._clearSection();
|
||||
this._queueCreateSection();
|
||||
if (this._networks.length == 0) {
|
||||
// only network in the list
|
||||
this._networks.push(apObj);
|
||||
this._clearSection();
|
||||
this._createSection();
|
||||
return;
|
||||
}
|
||||
|
||||
// skip networks that should appear earlier
|
||||
let menuPos = 0;
|
||||
for (pos = 0;
|
||||
pos < this._networks.length &&
|
||||
this._networkSortFunction(this._networks[pos], apObj) < 0; ++pos) {
|
||||
if (this._networks[pos] != this._activeNetwork)
|
||||
menuPos++;
|
||||
}
|
||||
|
||||
// (re-)add the network
|
||||
this._networks.splice(pos, 0, apObj);
|
||||
|
||||
if (this._shouldShowConnectionList()) {
|
||||
menuPos += (this._activeConnectionItem ? 1 : 0);
|
||||
this._createNetworkItem(apObj, menuPos);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1341,7 +1341,7 @@ const NMDeviceWireless = new Lang.Class({
|
||||
let obj = this._connections[pos];
|
||||
this._connections.splice(pos, 1);
|
||||
|
||||
let forceupdate = false;
|
||||
let anyauto = false, forceupdate = false;
|
||||
for (let i = 0; i < this._networks.length; i++) {
|
||||
let apObj = this._networks[i];
|
||||
let connections = apObj.connections;
|
||||
@@ -1349,14 +1349,16 @@ const NMDeviceWireless = new Lang.Class({
|
||||
if (connections[k]._uuid == connection._uuid) {
|
||||
// remove the connection from the access point group
|
||||
connections.splice(k);
|
||||
forceupdate = forceupdate || connections.length == 0;
|
||||
anyauto = connections.length == 0;
|
||||
|
||||
if (forceupdate)
|
||||
if (anyauto) {
|
||||
// this potentially changes the sorting order
|
||||
forceupdate = true;
|
||||
break;
|
||||
|
||||
}
|
||||
if (apObj.item) {
|
||||
if (apObj.item instanceof PopupMenu.PopupSubMenuMenuItem) {
|
||||
let items = apObj.item.menu._getMenuItems();
|
||||
let items = apObj.item.menu.getMenuItems();
|
||||
if (items.length == 2) {
|
||||
// we need to update the connection list to convert this to a normal item
|
||||
forceupdate = true;
|
||||
@@ -1378,10 +1380,10 @@ const NMDeviceWireless = new Lang.Class({
|
||||
}
|
||||
}
|
||||
|
||||
if (forceupdate) {
|
||||
if (forceupdate || anyauto) {
|
||||
this._networks.sort(this._networkSortFunction);
|
||||
this._clearSection();
|
||||
this._queueCreateSection();
|
||||
this._createSection();
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1414,13 +1416,13 @@ const NMDeviceWireless = new Lang.Class({
|
||||
if (forceupdate) {
|
||||
this._networks.sort(this._networkSortFunction);
|
||||
this._clearSection();
|
||||
this._queueCreateSection();
|
||||
this._createSection();
|
||||
}
|
||||
},
|
||||
|
||||
_createActiveConnectionItem: function() {
|
||||
let icon, title;
|
||||
if (this._activeConnection && this._activeConnection._connection) {
|
||||
if (this._activeConnection._connection) {
|
||||
let connection = this._activeConnection._connection;
|
||||
if (this._activeNetwork)
|
||||
this._activeConnectionItem = new NMNetworkMenuItem(this._activeNetwork.accessPoints, undefined,
|
||||
@@ -1513,7 +1515,7 @@ const NMDeviceWireless = new Lang.Class({
|
||||
if (!this._shouldShowConnectionList())
|
||||
return;
|
||||
|
||||
if (this._activeNetwork) {
|
||||
if(this._activeConnection) {
|
||||
this._createActiveConnectionItem();
|
||||
this.section.addMenuItem(this._activeConnectionItem);
|
||||
}
|
||||
@@ -1522,10 +1524,8 @@ const NMDeviceWireless = new Lang.Class({
|
||||
|
||||
for(let j = 0; j < this._networks.length; j++) {
|
||||
let apObj = this._networks[j];
|
||||
if (apObj == this._activeNetwork) {
|
||||
activeOffset--;
|
||||
if (apObj == this._activeNetwork)
|
||||
continue;
|
||||
}
|
||||
|
||||
this._createNetworkItem(apObj, j + activeOffset);
|
||||
}
|
||||
|
@@ -197,11 +197,11 @@ const Client = new Lang.Class({
|
||||
|
||||
_handleChannels: function(handler, account, conn, channels,
|
||||
requests, user_action_time, context) {
|
||||
this._handlingChannels(account, conn, channels, true);
|
||||
this._handlingChannels(account, conn, channels);
|
||||
context.accept();
|
||||
},
|
||||
|
||||
_handlingChannels: function(account, conn, channels, notify) {
|
||||
_handlingChannels: function(account, conn, channels) {
|
||||
let len = channels.length;
|
||||
for (let i = 0; i < len; i++) {
|
||||
let channel = channels[i];
|
||||
@@ -212,18 +212,7 @@ const Client = new Lang.Class({
|
||||
continue;
|
||||
}
|
||||
|
||||
// 'notify' will be true when coming from an actual HandleChannels
|
||||
// call, and not when from a successful Claim call. The point is
|
||||
// we don't want to notify for a channel we just claimed which
|
||||
// has no new messages (for example, a new channel which only has
|
||||
// a delivery notification). We rely on _displayPendingMessages()
|
||||
// and _messageReceived() to notify for new messages.
|
||||
|
||||
// But we should still notify from HandleChannels because the
|
||||
// Telepathy spec states that handlers must foreground channels
|
||||
// in HandleChannels calls which are already being handled.
|
||||
|
||||
if (notify && this._tpClient.is_handling_channel(channel)) {
|
||||
if (this._tpClient.is_handling_channel(channel)) {
|
||||
// We are already handling the channel, display the source
|
||||
let source = this._chatSources[channel.get_object_path()];
|
||||
if (source)
|
||||
@@ -296,7 +285,7 @@ const Client = new Lang.Class({
|
||||
Lang.bind(this, function(dispatchOp, result) {
|
||||
try {
|
||||
dispatchOp.claim_with_finish(result);
|
||||
this._handlingChannels(account, conn, [channel], false);
|
||||
this._handlingChannels(account, conn, [channel]);
|
||||
} catch (err) {
|
||||
throw new Error('Failed to Claim channel: ' + err);
|
||||
}}));
|
||||
@@ -513,9 +502,15 @@ const ChatSource = new Lang.Class({
|
||||
this._notification.setUrgency(MessageTray.Urgency.HIGH);
|
||||
this._notifyTimeoutId = 0;
|
||||
|
||||
// We ack messages when the user expands the new notification or views the summary
|
||||
// notification, in which case the notification is also expanded.
|
||||
this._notification.connect('expanded', Lang.bind(this, this._ackMessages));
|
||||
// We ack messages when the message box is collapsed if user has
|
||||
// interacted with it before and so read the messages:
|
||||
// - user clicked on it the tray
|
||||
// - user expanded the notification by hovering over the toaster notification
|
||||
this._shouldAck = false;
|
||||
|
||||
this.connect('summary-item-clicked', Lang.bind(this, this._summaryItemClicked));
|
||||
this._notification.connect('expanded', Lang.bind(this, this._notificationExpanded));
|
||||
this._notification.connect('collapsed', Lang.bind(this, this._notificationCollapsed));
|
||||
|
||||
this._presence = contact.get_presence_type();
|
||||
|
||||
@@ -779,6 +774,24 @@ const ChatSource = new Lang.Class({
|
||||
// 'pending-message-removed' for each one.
|
||||
this._channel.ack_all_pending_messages_async(Lang.bind(this, function(src, result) {
|
||||
this._channel.ack_all_pending_messages_finish(result);}));
|
||||
},
|
||||
|
||||
_summaryItemClicked: function(source, button) {
|
||||
if (button != 1)
|
||||
return;
|
||||
|
||||
this._shouldAck = true;
|
||||
},
|
||||
|
||||
_notificationExpanded: function() {
|
||||
this._shouldAck = true;
|
||||
},
|
||||
|
||||
_notificationCollapsed: function() {
|
||||
if (this._shouldAck)
|
||||
this._ackMessages();
|
||||
|
||||
this._shouldAck = false;
|
||||
}
|
||||
});
|
||||
|
||||
|
@@ -419,6 +419,29 @@ const ViewSelector = new Lang.Class({
|
||||
// not when setting the initially selected one.
|
||||
if (!tab.visible)
|
||||
tab.show(!firstSwitch);
|
||||
|
||||
// Pull a Meg Ryan:
|
||||
if (!firstSwitch && Main.overview.workspaces) {
|
||||
if (tab != this._tabs[0]) {
|
||||
Tweener.addTween(Main.overview.workspaces.actor,
|
||||
{ opacity: 0,
|
||||
time: 0.1,
|
||||
transition: 'easeOutQuad',
|
||||
onComplete: Lang.bind(this,
|
||||
function() {
|
||||
Main.overview.workspaces.actor.hide();
|
||||
Main.overview.workspaces.actor.opacity = 255;
|
||||
})
|
||||
});
|
||||
} else {
|
||||
Main.overview.workspaces.actor.opacity = 0;
|
||||
Main.overview.workspaces.actor.show();
|
||||
Tweener.addTween(Main.overview.workspaces.actor,
|
||||
{ opacity: 255,
|
||||
time: 0.1,
|
||||
transition: 'easeOutQuad' });
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
switchTab: function(id) {
|
||||
|
210
js/ui/wanda.js
210
js/ui/wanda.js
@@ -1,210 +0,0 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const GdkPixbuf = imports.gi.GdkPixbuf;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Lang = imports.lang;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Signals = imports.signals;
|
||||
const St = imports.gi.St;
|
||||
|
||||
const IconGrid = imports.ui.iconGrid;
|
||||
const Main = imports.ui.main;
|
||||
const Search = imports.ui.search;
|
||||
|
||||
// we could make these gsettings
|
||||
const FISH_NAME = 'wanda';
|
||||
const FISH_SPEED = 300;
|
||||
const FISH_COMMAND = 'fortune';
|
||||
|
||||
const GNOME_PANEL_PIXMAPDIR = '../gnome-panel/pixmaps';
|
||||
const FISH_GROUP = 'Fish Animation';
|
||||
|
||||
const MAGIC_FISH_KEY = 'free the fish';
|
||||
|
||||
const WandaIcon = new Lang.Class({
|
||||
Name: 'WandaIcon',
|
||||
Extends: IconGrid.BaseIcon,
|
||||
|
||||
_init : function(fish, label, params) {
|
||||
this._fish = fish;
|
||||
let file = GLib.build_filenamev([global.datadir, GNOME_PANEL_PIXMAPDIR, fish + '.fish']);
|
||||
|
||||
if (GLib.file_test(file, GLib.FileTest.EXISTS)) {
|
||||
this._keyfile = new GLib.KeyFile();
|
||||
this._keyfile.load_from_file(file, GLib.KeyFileFlags.NONE);
|
||||
|
||||
this._imageFile = GLib.build_filenamev([global.datadir, GNOME_PANEL_PIXMAPDIR,
|
||||
this._keyfile.get_string(FISH_GROUP, 'image')]);
|
||||
|
||||
let tmpPixbuf = GdkPixbuf.Pixbuf.new_from_file(this._imageFile);
|
||||
|
||||
this._imgHeight = tmpPixbuf.height;
|
||||
this._imgWidth = tmpPixbuf.width / this._keyfile.get_integer(FISH_GROUP, 'frames');
|
||||
} else {
|
||||
this._imageFile = null;
|
||||
}
|
||||
|
||||
this.parent(label, params);
|
||||
},
|
||||
|
||||
createIcon: function(iconSize) {
|
||||
if (this._animations)
|
||||
this._animations.destroy();
|
||||
|
||||
if (!this._imageFile) {
|
||||
return new St.Icon({ icon_name: 'face-smile',
|
||||
icon_type: St.IconType.FULLCOLOR,
|
||||
icon_size: iconSize
|
||||
});
|
||||
}
|
||||
|
||||
this._animations = St.TextureCache.get_default().load_sliced_image(this._imageFile, this._imgWidth, this._imgHeight);
|
||||
this._animations.connect('destroy', Lang.bind(this, function() {
|
||||
if (this._timeoutId)
|
||||
GLib.source_remove(this._timeoutId);
|
||||
this._timeoutId = 0;
|
||||
this._animations = null;
|
||||
}));
|
||||
this._animations.connect('notify::mapped', Lang.bind(this, function() {
|
||||
if (this._animations.mapped && !this._timeoutId) {
|
||||
this._timeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, FISH_SPEED, Lang.bind(this, this._update));
|
||||
|
||||
this._i = 0;
|
||||
this._update();
|
||||
} else if (!this._animations.mapped && this._timeoutId) {
|
||||
GLib.source_remove(this._timeoutId);
|
||||
this._timeoutId = 0;
|
||||
}
|
||||
}));
|
||||
|
||||
this._i = 0;
|
||||
|
||||
return this._animations;
|
||||
},
|
||||
|
||||
_update: function() {
|
||||
let n = this._animations.get_n_children();
|
||||
if (n == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
this._animations.get_nth_child(this._i).hide();
|
||||
this._i = (this._i + 1) % n;
|
||||
this._animations.get_nth_child(this._i).show();
|
||||
|
||||
return true;
|
||||
},
|
||||
});
|
||||
|
||||
const WandaIconBin = new Lang.Class({
|
||||
Name: 'WandaIconBin',
|
||||
|
||||
_init: function(fish, label, params) {
|
||||
this.actor = new St.Bin({ style_class: 'search-result-content',
|
||||
reactive: true,
|
||||
track_hover: true });
|
||||
this.icon = new WandaIcon(fish, label, params);
|
||||
|
||||
this.actor.child = this.icon.actor;
|
||||
this.actor.label_actor = this.icon.label;
|
||||
},
|
||||
});
|
||||
|
||||
const FortuneDialog = new Lang.Class({
|
||||
Name: 'FortuneDialog',
|
||||
|
||||
_init: function(name, command) {
|
||||
let text;
|
||||
|
||||
try {
|
||||
let [res, stdout, stderr, status] = GLib.spawn_command_line_sync(command);
|
||||
text = String.fromCharCode.apply(null, stdout);
|
||||
} catch(e) {
|
||||
text = _("Sorry, no wisdom for you today:\n%s").format(e.message);
|
||||
}
|
||||
|
||||
this._title = new St.Label({ style_class: 'polkit-dialog-headline',
|
||||
text: _("%s the Oracle says").format(name) });
|
||||
this._label = new St.Label({ style_class: 'polkit-dialog-description',
|
||||
text: text });
|
||||
this._label.clutter_text.line_wrap = true;
|
||||
|
||||
this._box = new St.BoxLayout({ vertical: true,
|
||||
style_class: 'polkit-dialog' // this is just to force a reasonable width
|
||||
});
|
||||
this._box.add(this._title, { align: St.Align.MIDDLE });
|
||||
this._box.add(this._label, { expand: true });
|
||||
|
||||
this._button = new St.Button({ button_mask: St.ButtonMask.ONE,
|
||||
style_class: 'modal-dialog',
|
||||
reactive: true });
|
||||
this._button.connect('clicked', Lang.bind(this, this.destroy));
|
||||
this._button.child = this._box;
|
||||
|
||||
let monitor = Main.layoutManager.primaryMonitor;
|
||||
|
||||
Main.layoutManager.addChrome(this._button);
|
||||
this._button.set_position(Math.floor(monitor.width / 2 - this._button.width / 2),
|
||||
Math.floor(monitor.height / 2 - this._button.height / 2));
|
||||
|
||||
GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 10, Lang.bind(this, this.destroy));
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
this._button.destroy();
|
||||
}
|
||||
});
|
||||
|
||||
function capitalize(str) {
|
||||
return str[0].toUpperCase() + str.substring(1, str.length);
|
||||
}
|
||||
|
||||
const WandaSearchProvider = new Lang.Class({
|
||||
Name: 'WandaSearchProvider',
|
||||
Extends: Search.SearchProvider,
|
||||
|
||||
_init: function() {
|
||||
this.parent(_("Your favorite Easter Egg"));
|
||||
},
|
||||
|
||||
getResultMeta: function(fish) {
|
||||
return { 'id': fish,
|
||||
'name': capitalize(fish),
|
||||
'createIcon': function(iconSize) {
|
||||
// for DND only (maybe could be improved)
|
||||
// DON'T use St.Icon here, it crashes the shell
|
||||
// (dnd.js code assumes it can query the actor size
|
||||
// without parenting it, while StWidget accesses
|
||||
// StThemeNode in get_preferred_width/height, which
|
||||
// triggers an assertion failure)
|
||||
return St.TextureCache.get_default().load_icon_name(null,
|
||||
'face-smile',
|
||||
St.IconType.FULLCOLOR,
|
||||
iconSize);
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
getInitialResultSet: function(terms) {
|
||||
if (terms.join(' ') == MAGIC_FISH_KEY) {
|
||||
return [ FISH_NAME ];
|
||||
}
|
||||
return [];
|
||||
},
|
||||
|
||||
getSubsearchResultSet: function(previousResults, terms) {
|
||||
return this.getInitialResultSet(terms);
|
||||
},
|
||||
|
||||
activateResult: function(fish, params) {
|
||||
if (this._dialog)
|
||||
this._dialog.destroy();
|
||||
this._dialog = new FortuneDialog(capitalize(fish), FISH_COMMAND);
|
||||
},
|
||||
|
||||
createResultActor: function (resultMeta, terms) {
|
||||
let icon = new WandaIconBin(resultMeta.id, resultMeta.name);
|
||||
return icon.actor;
|
||||
}
|
||||
});
|
@@ -94,11 +94,10 @@ const ScaledPoint = new Lang.Class({
|
||||
const WindowClone = new Lang.Class({
|
||||
Name: 'WindowClone',
|
||||
|
||||
_init : function(realWindow, workspace) {
|
||||
_init : function(realWindow) {
|
||||
this.realWindow = realWindow;
|
||||
this.metaWindow = realWindow.meta_window;
|
||||
this.metaWindow._delegate = this;
|
||||
this._workspace = workspace;
|
||||
|
||||
let [borderX, borderY] = this._getInvisibleBorderPadding();
|
||||
this._windowClone = new Clutter.Clone({ source: realWindow.get_texture(),
|
||||
@@ -384,12 +383,19 @@ const WindowClone = new Lang.Class({
|
||||
this.emit('drag-begin');
|
||||
},
|
||||
|
||||
_getWorkspaceActor : function() {
|
||||
let index = this.metaWindow.get_workspace().index();
|
||||
return Main.overview.workspaces.getWorkspaceByIndex(index);
|
||||
},
|
||||
|
||||
handleDragOver : function(source, actor, x, y, time) {
|
||||
return this._workspace.handleDragOver(source, actor, x, y, time);
|
||||
let workspace = this._getWorkspaceActor();
|
||||
return workspace.handleDragOver(source, actor, x, y, time);
|
||||
},
|
||||
|
||||
acceptDrop : function(source, actor, x, y, time) {
|
||||
this._workspace.acceptDrop(source, actor, x, y, time);
|
||||
let workspace = this._getWorkspaceActor();
|
||||
workspace.acceptDrop(source, actor, x, y, time);
|
||||
},
|
||||
|
||||
_onDragCancelled : function (draggable, time) {
|
||||
@@ -488,9 +494,6 @@ const WindowOverlay = new Lang.Class({
|
||||
},
|
||||
|
||||
fadeIn: function() {
|
||||
if (!this._hidden)
|
||||
return;
|
||||
|
||||
this.show();
|
||||
this.title.opacity = 0;
|
||||
this._parentActor.raise_top();
|
||||
@@ -519,7 +522,7 @@ const WindowOverlay = new Lang.Class({
|
||||
// get_transformed_position() and get_transformed_size(),
|
||||
// as windowClone might be moving.
|
||||
// See Workspace._showWindowOverlay
|
||||
updatePositions: function(cloneX, cloneY, cloneWidth, cloneHeight, animate) {
|
||||
updatePositions: function(cloneX, cloneY, cloneWidth, cloneHeight) {
|
||||
let button = this.closeButton;
|
||||
let title = this.title;
|
||||
|
||||
@@ -541,34 +544,15 @@ const WindowOverlay = new Lang.Class({
|
||||
else
|
||||
buttonX = cloneX + (cloneWidth - button._overlap);
|
||||
|
||||
if (animate)
|
||||
this._animateOverlayActor(button, Math.floor(buttonX), Math.floor(buttonY), button.width);
|
||||
else
|
||||
button.set_position(Math.floor(buttonX), Math.floor(buttonY));
|
||||
button.set_position(Math.floor(buttonX), Math.floor(buttonY));
|
||||
|
||||
if (!title.fullWidth)
|
||||
title.fullWidth = title.width;
|
||||
let titleWidth = Math.min(title.fullWidth, cloneWidth);
|
||||
title.width = Math.min(title.fullWidth, cloneWidth);
|
||||
|
||||
let titleX = cloneX + (cloneWidth - titleWidth) / 2;
|
||||
let titleX = cloneX + (cloneWidth - title.width) / 2;
|
||||
let titleY = cloneY + cloneHeight + title._spacing;
|
||||
|
||||
if (animate)
|
||||
this._animateOverlayActor(title, Math.floor(titleX), Math.floor(titleY), titleWidth);
|
||||
else {
|
||||
title.width = titleWidth;
|
||||
title.set_position(Math.floor(titleX), Math.floor(titleY));
|
||||
}
|
||||
},
|
||||
|
||||
_animateOverlayActor: function(actor, x, y, width) {
|
||||
Tweener.addTween(actor,
|
||||
{ x: x,
|
||||
y: y,
|
||||
width: width,
|
||||
time: Overview.ANIMATION_TIME,
|
||||
transition: 'easeOutQuad'
|
||||
});
|
||||
title.set_position(Math.floor(titleX), Math.floor(titleY));
|
||||
},
|
||||
|
||||
_closeWindow: function(actor) {
|
||||
@@ -1033,7 +1017,7 @@ const Workspace = new Lang.Class({
|
||||
|
||||
let [x, y, scale] = this._computeWindowLayout(metaWindow, slot);
|
||||
|
||||
if (overlay && initialPositioning)
|
||||
if (overlay)
|
||||
overlay.hide();
|
||||
if (animate && isOnCurrentWorkspace) {
|
||||
if (!metaWindow.showing_on_its_workspace()) {
|
||||
@@ -1056,11 +1040,20 @@ const Workspace = new Lang.Class({
|
||||
});
|
||||
}
|
||||
|
||||
this._animateClone(clone, overlay, x, y, scale, initialPositioning);
|
||||
Tweener.addTween(clone.actor,
|
||||
{ x: x,
|
||||
y: y,
|
||||
scale_x: scale,
|
||||
scale_y: scale,
|
||||
time: Overview.ANIMATION_TIME,
|
||||
transition: 'easeOutQuad',
|
||||
onComplete: Lang.bind(this, function() {
|
||||
this._showWindowOverlay(clone, overlay, true);
|
||||
})
|
||||
});
|
||||
} else {
|
||||
clone.actor.set_position(x, y);
|
||||
clone.actor.set_scale(scale, scale);
|
||||
this._updateWindowOverlayPositions(clone, overlay, x, y, scale, false);
|
||||
this._showWindowOverlay(clone, overlay, isOnCurrentWorkspace);
|
||||
}
|
||||
}
|
||||
@@ -1082,35 +1075,23 @@ const Workspace = new Lang.Class({
|
||||
}
|
||||
},
|
||||
|
||||
_animateClone: function(clone, overlay, x, y, scale, initialPositioning) {
|
||||
Tweener.addTween(clone.actor,
|
||||
{ x: x,
|
||||
y: y,
|
||||
scale_x: scale,
|
||||
scale_y: scale,
|
||||
time: Overview.ANIMATION_TIME,
|
||||
transition: 'easeOutQuad',
|
||||
onComplete: Lang.bind(this, function() {
|
||||
this._showWindowOverlay(clone, overlay, true);
|
||||
})
|
||||
});
|
||||
|
||||
this._updateWindowOverlayPositions(clone, overlay, x, y, scale, true);
|
||||
},
|
||||
|
||||
_updateWindowOverlayPositions: function(clone, overlay, x, y, scale, animate) {
|
||||
let [cloneWidth, cloneHeight] = clone.actor.get_size();
|
||||
cloneWidth = scale * cloneWidth;
|
||||
cloneHeight = scale * cloneHeight;
|
||||
if (overlay)
|
||||
overlay.updatePositions(x, y, cloneWidth, cloneHeight, animate);
|
||||
},
|
||||
|
||||
_showWindowOverlay: function(clone, overlay, fade) {
|
||||
if (clone.inDrag)
|
||||
return;
|
||||
|
||||
// This is a little messy and complicated because when we
|
||||
// start the fade-in we may not have done the final positioning
|
||||
// of the workspaces. (Tweener doesn't necessarily finish
|
||||
// all animations before calling onComplete callbacks.)
|
||||
// So we need to manually compute where the window will
|
||||
// be after the workspace animation finishes.
|
||||
let [cloneX, cloneY] = clone.actor.get_position();
|
||||
let [cloneWidth, cloneHeight] = clone.actor.get_size();
|
||||
cloneWidth = clone.actor.scale_x * cloneWidth;
|
||||
cloneHeight = clone.actor.scale_y * cloneHeight;
|
||||
|
||||
if (overlay) {
|
||||
overlay.updatePositions(cloneX, cloneY, cloneWidth, cloneHeight);
|
||||
if (fade)
|
||||
overlay.fadeIn();
|
||||
else
|
||||
@@ -1128,16 +1109,6 @@ const Workspace = new Lang.Class({
|
||||
}
|
||||
},
|
||||
|
||||
_hideAllOverlays: function() {
|
||||
for (let i = 0; i < this._windows.length; i++) {
|
||||
let clone = this._windows[i];
|
||||
Tweener.removeTweens(clone.actor);
|
||||
let overlay = this._windowOverlays[i];
|
||||
if (overlay)
|
||||
overlay.hide();
|
||||
}
|
||||
},
|
||||
|
||||
_delayedWindowRepositioning: function() {
|
||||
if (this._windowIsZooming)
|
||||
return true;
|
||||
@@ -1159,6 +1130,18 @@ const Workspace = new Lang.Class({
|
||||
return false;
|
||||
},
|
||||
|
||||
showWindowsOverlays: function() {
|
||||
if (this.leavingOverview)
|
||||
return;
|
||||
|
||||
this._windowOverlaysGroup.show();
|
||||
this._showAllOverlays();
|
||||
},
|
||||
|
||||
hideWindowsOverlays: function() {
|
||||
this._windowOverlaysGroup.hide();
|
||||
},
|
||||
|
||||
_doRemoveWindow : function(metaWin) {
|
||||
let win = metaWin.get_compositor_private();
|
||||
|
||||
@@ -1312,7 +1295,7 @@ const Workspace = new Lang.Class({
|
||||
|
||||
this.leavingOverview = true;
|
||||
|
||||
this._hideAllOverlays();
|
||||
this.hideWindowsOverlays();
|
||||
|
||||
if (this._repositionWindowsId > 0) {
|
||||
Mainloop.source_remove(this._repositionWindowsId);
|
||||
@@ -1403,7 +1386,7 @@ const Workspace = new Lang.Class({
|
||||
|
||||
// Create a clone of a (non-desktop) window and add it to the window list
|
||||
_addWindowClone : function(win) {
|
||||
let clone = new WindowClone(win, this);
|
||||
let clone = new WindowClone(win);
|
||||
let overlay = new WindowOverlay(clone, this._windowOverlaysGroup);
|
||||
|
||||
clone.connect('selected',
|
||||
|
@@ -51,7 +51,6 @@ const WindowClone = new Lang.Class({
|
||||
dragActorMaxSize: Workspace.WINDOW_DND_SIZE,
|
||||
dragActorOpacity: Workspace.DRAGGING_WINDOW_OPACITY });
|
||||
this._draggable.connect('drag-begin', Lang.bind(this, this._onDragBegin));
|
||||
this._draggable.connect('drag-cancelled', Lang.bind(this, this._onDragCancelled));
|
||||
this._draggable.connect('drag-end', Lang.bind(this, this._onDragEnd));
|
||||
this.inDrag = false;
|
||||
},
|
||||
@@ -109,10 +108,6 @@ const WindowClone = new Lang.Class({
|
||||
this.emit('drag-begin');
|
||||
},
|
||||
|
||||
_onDragCancelled : function (draggable, time) {
|
||||
this.emit('drag-cancelled');
|
||||
},
|
||||
|
||||
_onDragEnd : function (draggable, time, snapback) {
|
||||
this.inDrag = false;
|
||||
|
||||
@@ -391,10 +386,6 @@ const WorkspaceThumbnail = new Lang.Class({
|
||||
Lang.bind(this, function(clone) {
|
||||
Main.overview.beginWindowDrag();
|
||||
}));
|
||||
clone.connect('drag-cancelled',
|
||||
Lang.bind(this, function(clone) {
|
||||
Main.overview.cancelledWindowDrag();
|
||||
}));
|
||||
clone.connect('drag-end',
|
||||
Lang.bind(this, function(clone) {
|
||||
Main.overview.endWindowDrag();
|
||||
|
@@ -1,7 +1,6 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Gio = imports.gi.Gio;
|
||||
const Lang = imports.lang;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Meta = imports.gi.Meta;
|
||||
@@ -20,7 +19,6 @@ const WORKSPACE_SWITCH_TIME = 0.25;
|
||||
// Note that mutter has a compile-time limit of 36
|
||||
const MAX_WORKSPACES = 16;
|
||||
|
||||
const OVERRIDE_SCHEMA = 'org.gnome.shell.overrides';
|
||||
|
||||
const CONTROLS_POP_IN_TIME = 0.1;
|
||||
|
||||
@@ -42,6 +40,8 @@ const WorkspacesView = new Lang.Class({
|
||||
this._spacing = node.get_length('spacing');
|
||||
this._updateWorkspaceActors(false);
|
||||
}));
|
||||
this.actor.connect('notify::mapped',
|
||||
Lang.bind(this, this._onMappedChanged));
|
||||
|
||||
this._width = 0;
|
||||
this._height = 0;
|
||||
@@ -59,11 +59,6 @@ const WorkspacesView = new Lang.Class({
|
||||
this._zoomOut = false; // zoom to a larger area
|
||||
this._inDrag = false; // dragging a window
|
||||
|
||||
this._settings = new Gio.Settings({ schema: OVERRIDE_SCHEMA });
|
||||
this._updateExtraWorkspacesId =
|
||||
this._settings.connect('changed::workspaces-only-on-primary',
|
||||
Lang.bind(this, this._updateExtraWorkspaces));
|
||||
|
||||
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
|
||||
this._workspaces = workspaces;
|
||||
|
||||
@@ -72,7 +67,17 @@ const WorkspacesView = new Lang.Class({
|
||||
this._workspaces[w].actor.reparent(this.actor);
|
||||
this._workspaces[activeWorkspaceIndex].actor.raise_top();
|
||||
|
||||
this._updateExtraWorkspaces();
|
||||
this._extraWorkspaces = [];
|
||||
let monitors = Main.layoutManager.monitors;
|
||||
let m = 0;
|
||||
for (let i = 0; i < monitors.length; i++) {
|
||||
if (i == Main.layoutManager.primaryIndex)
|
||||
continue;
|
||||
let ws = new Workspace.Workspace(null, i);
|
||||
this._extraWorkspaces[m++] = ws;
|
||||
ws.setGeometry(monitors[i].x, monitors[i].y, monitors[i].width, monitors[i].height);
|
||||
global.overlay_group.add_actor(ws.actor);
|
||||
}
|
||||
|
||||
// Position/scale the desktop windows and their children after the
|
||||
// workspaces have been created. This cannot be done first because
|
||||
@@ -83,8 +88,6 @@ const WorkspacesView = new Lang.Class({
|
||||
Lang.bind(this, function() {
|
||||
for (let w = 0; w < this._workspaces.length; w++)
|
||||
this._workspaces[w].zoomToOverview();
|
||||
if (!this._extraWorkspaces)
|
||||
return;
|
||||
for (let w = 0; w < this._extraWorkspaces.length; w++)
|
||||
this._extraWorkspaces[w].zoomToOverview();
|
||||
}));
|
||||
@@ -95,14 +98,14 @@ const WorkspacesView = new Lang.Class({
|
||||
this._clipWidth, this._clipHeight);
|
||||
}));
|
||||
|
||||
this.scrollAdjustment = new St.Adjustment({ value: activeWorkspaceIndex,
|
||||
lower: 0,
|
||||
page_increment: 1,
|
||||
page_size: 1,
|
||||
step_increment: 0,
|
||||
upper: this._workspaces.length });
|
||||
this.scrollAdjustment.connect('notify::value',
|
||||
Lang.bind(this, this._onScroll));
|
||||
this._scrollAdjustment = new St.Adjustment({ value: activeWorkspaceIndex,
|
||||
lower: 0,
|
||||
page_increment: 1,
|
||||
page_size: 1,
|
||||
step_increment: 0,
|
||||
upper: this._workspaces.length });
|
||||
this._scrollAdjustment.connect('notify::value',
|
||||
Lang.bind(this, this._onScroll));
|
||||
|
||||
this._switchWorkspaceNotifyId =
|
||||
global.window_manager.connect('switch-workspace',
|
||||
@@ -116,35 +119,8 @@ const WorkspacesView = new Lang.Class({
|
||||
Lang.bind(this, this._dragBegin));
|
||||
this._windowDragEndId = Main.overview.connect('window-drag-end',
|
||||
Lang.bind(this, this._dragEnd));
|
||||
},
|
||||
|
||||
_updateExtraWorkspaces: function() {
|
||||
this._destroyExtraWorkspaces();
|
||||
|
||||
if (!this._settings.get_boolean('workspaces-only-on-primary'))
|
||||
return;
|
||||
|
||||
this._extraWorkspaces = [];
|
||||
let monitors = Main.layoutManager.monitors;
|
||||
for (let i = 0; i < monitors.length; i++) {
|
||||
if (i == Main.layoutManager.primaryIndex)
|
||||
continue;
|
||||
|
||||
let ws = new Workspace.Workspace(null, i);
|
||||
ws.setGeometry(monitors[i].x, monitors[i].y,
|
||||
monitors[i].width, monitors[i].height);
|
||||
global.overlay_group.add_actor(ws.actor);
|
||||
this._extraWorkspaces.push(ws);
|
||||
}
|
||||
},
|
||||
|
||||
_destroyExtraWorkspaces: function() {
|
||||
if (!this._extraWorkspaces)
|
||||
return;
|
||||
|
||||
for (let m = 0; m < this._extraWorkspaces.length; m++)
|
||||
this._extraWorkspaces[m].destroy();
|
||||
this._extraWorkspaces = null;
|
||||
this._swipeScrollBeginId = 0;
|
||||
this._swipeScrollEndId = 0;
|
||||
},
|
||||
|
||||
setGeometry: function(x, y, width, height, spacing) {
|
||||
@@ -181,6 +157,10 @@ const WorkspacesView = new Lang.Class({
|
||||
return this._workspaces[active];
|
||||
},
|
||||
|
||||
getWorkspaceByIndex: function(index) {
|
||||
return this._workspaces[index];
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
|
||||
let activeWorkspace = this._workspaces[activeWorkspaceIndex];
|
||||
@@ -191,8 +171,6 @@ const WorkspacesView = new Lang.Class({
|
||||
|
||||
for (let w = 0; w < this._workspaces.length; w++)
|
||||
this._workspaces[w].zoomFromOverview();
|
||||
if (!this._extraWorkspaces)
|
||||
return;
|
||||
for (let w = 0; w < this._extraWorkspaces.length; w++)
|
||||
this._extraWorkspaces[w].zoomFromOverview();
|
||||
},
|
||||
@@ -204,8 +182,6 @@ const WorkspacesView = new Lang.Class({
|
||||
syncStacking: function(stackIndices) {
|
||||
for (let i = 0; i < this._workspaces.length; i++)
|
||||
this._workspaces[i].syncStacking(stackIndices);
|
||||
if (!this._extraWorkspaces)
|
||||
return;
|
||||
for (let i = 0; i < this._extraWorkspaces.length; i++)
|
||||
this._extraWorkspaces[i].syncStacking(stackIndices);
|
||||
},
|
||||
@@ -267,8 +243,10 @@ const WorkspacesView = new Lang.Class({
|
||||
for (let w = 0; w < this._workspaces.length; w++) {
|
||||
let workspace = this._workspaces[w];
|
||||
if (this._animating || this._scrolling) {
|
||||
workspace.hideWindowsOverlays();
|
||||
workspace.actor.show();
|
||||
} else {
|
||||
workspace.showWindowsOverlays();
|
||||
if (this._inDrag)
|
||||
workspace.actor.visible = (Math.abs(w - active) <= 1);
|
||||
else
|
||||
@@ -284,7 +262,7 @@ const WorkspacesView = new Lang.Class({
|
||||
this._animatingScroll = true;
|
||||
|
||||
if (showAnimation) {
|
||||
Tweener.addTween(this.scrollAdjustment, {
|
||||
Tweener.addTween(this._scrollAdjustment, {
|
||||
value: index,
|
||||
time: WORKSPACE_SWITCH_TIME,
|
||||
transition: 'easeOutQuad',
|
||||
@@ -294,7 +272,7 @@ const WorkspacesView = new Lang.Class({
|
||||
})
|
||||
});
|
||||
} else {
|
||||
this.scrollAdjustment.value = index;
|
||||
this._scrollAdjustment.value = index;
|
||||
this._animatingScroll = false;
|
||||
}
|
||||
},
|
||||
@@ -302,7 +280,7 @@ const WorkspacesView = new Lang.Class({
|
||||
updateWorkspaces: function(oldNumWorkspaces, newNumWorkspaces) {
|
||||
let active = global.screen.get_active_workspace_index();
|
||||
|
||||
Tweener.addTween(this.scrollAdjustment,
|
||||
Tweener.addTween(this._scrollAdjustment,
|
||||
{ upper: newNumWorkspaces,
|
||||
time: WORKSPACE_SWITCH_TIME,
|
||||
transition: 'easeOutQuad'
|
||||
@@ -329,12 +307,12 @@ const WorkspacesView = new Lang.Class({
|
||||
},
|
||||
|
||||
_onDestroy: function() {
|
||||
this._destroyExtraWorkspaces();
|
||||
this.scrollAdjustment.run_dispose();
|
||||
for (let i = 0; i < this._extraWorkspaces.length; i++)
|
||||
this._extraWorkspaces[i].destroy();
|
||||
this._scrollAdjustment.run_dispose();
|
||||
Main.overview.disconnect(this._overviewShowingId);
|
||||
Main.overview.disconnect(this._overviewShownId);
|
||||
global.window_manager.disconnect(this._switchWorkspaceNotifyId);
|
||||
this._settings.disconnect(this._updateExtraWorkspacesId);
|
||||
|
||||
if (this._inDrag)
|
||||
this._dragEnd();
|
||||
@@ -357,6 +335,21 @@ const WorkspacesView = new Lang.Class({
|
||||
}
|
||||
},
|
||||
|
||||
_onMappedChanged: function() {
|
||||
if (this.actor.mapped) {
|
||||
let direction = Overview.SwipeScrollDirection.VERTICAL;
|
||||
Main.overview.setScrollAdjustment(this._scrollAdjustment,
|
||||
direction);
|
||||
this._swipeScrollBeginId = Main.overview.connect('swipe-scroll-begin',
|
||||
Lang.bind(this, this._swipeScrollBegin));
|
||||
this._swipeScrollEndId = Main.overview.connect('swipe-scroll-end',
|
||||
Lang.bind(this, this._swipeScrollEnd));
|
||||
} else {
|
||||
Main.overview.disconnect(this._swipeScrollBeginId);
|
||||
Main.overview.disconnect(this._swipeScrollEndId);
|
||||
}
|
||||
},
|
||||
|
||||
_dragBegin: function() {
|
||||
if (this._scrolling)
|
||||
return;
|
||||
@@ -378,9 +371,6 @@ const WorkspacesView = new Lang.Class({
|
||||
this._firstDragMotion = false;
|
||||
for (let i = 0; i < this._workspaces.length; i++)
|
||||
this._workspaces[i].setReservedSlot(dragEvent.dragActor._delegate);
|
||||
if (!this._extraWorkspaces)
|
||||
return DND.DragMotionResult.CONTINUE;
|
||||
|
||||
for (let i = 0; i < this._extraWorkspaces.length; i++)
|
||||
this._extraWorkspaces[i].setReservedSlot(dragEvent.dragActor._delegate);
|
||||
}
|
||||
@@ -394,18 +384,15 @@ const WorkspacesView = new Lang.Class({
|
||||
|
||||
for (let i = 0; i < this._workspaces.length; i++)
|
||||
this._workspaces[i].setReservedSlot(null);
|
||||
|
||||
if (!this._extraWorkspaces)
|
||||
return;
|
||||
for (let i = 0; i < this._extraWorkspaces.length; i++)
|
||||
this._extraWorkspaces[i].setReservedSlot(null);
|
||||
},
|
||||
|
||||
startSwipeScroll: function() {
|
||||
_swipeScrollBegin: function() {
|
||||
this._scrolling = true;
|
||||
},
|
||||
|
||||
endSwipeScroll: function(result) {
|
||||
_swipeScrollEnd: function(overview, result) {
|
||||
this._scrolling = false;
|
||||
|
||||
if (result == Overview.SwipeScrollResult.CLICK) {
|
||||
@@ -454,6 +441,7 @@ const WorkspacesView = new Lang.Class({
|
||||
let dy = newY - currentY;
|
||||
|
||||
for (let i = 0; i < this._workspaces.length; i++) {
|
||||
this._workspaces[i].hideWindowsOverlays();
|
||||
this._workspaces[i].actor.visible = Math.abs(i - adj.value) <= 1;
|
||||
this._workspaces[i].actor.y += dy;
|
||||
}
|
||||
@@ -474,8 +462,6 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
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.actor.connect('notify::mapped', Lang.bind(this, this._setupSwipeScrolling));
|
||||
this.actor.connect('parent-set', Lang.bind(this, this._parentSet));
|
||||
this.actor.set_clip_to_allocation(true);
|
||||
|
||||
let controls = new St.Bin({ style_class: 'workspace-controls',
|
||||
@@ -492,19 +478,12 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
controls.connect('scroll-event',
|
||||
Lang.bind(this, this._onScrollEvent));
|
||||
|
||||
this._primaryIndex = Main.layoutManager.primaryIndex;
|
||||
this._monitorIndex = Main.layoutManager.primaryIndex;
|
||||
|
||||
this._thumbnailsBox = new WorkspaceThumbnail.ThumbnailsBox();
|
||||
controls.add_actor(this._thumbnailsBox.actor);
|
||||
|
||||
this._workspacesViews = null;
|
||||
this._primaryScrollAdjustment = null;
|
||||
|
||||
this._settings = new Gio.Settings({ schema: OVERRIDE_SCHEMA });
|
||||
this._settings.connect('changed::workspaces-only-on-primary',
|
||||
Lang.bind(this,
|
||||
this._workspacesOnlyOnPrimaryChanged));
|
||||
this._workspacesOnlyOnPrimaryChanged();
|
||||
this.workspacesView = null;
|
||||
|
||||
this._inDrag = false;
|
||||
this._cancelledDrag = false;
|
||||
@@ -515,8 +494,6 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
|
||||
this._updateAlwaysZoom();
|
||||
|
||||
// If we stop hiding the overview on layout changes, we will need to
|
||||
// update the _workspacesViews here
|
||||
Main.layoutManager.connect('monitors-changed', Lang.bind(this, this._updateAlwaysZoom));
|
||||
|
||||
Main.xdndHandler.connect('drag-begin', Lang.bind(this, function(){
|
||||
@@ -537,9 +514,6 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
this._windowDragBeginId = 0;
|
||||
this._windowDragCancelledId = 0;
|
||||
this._windowDragEndId = 0;
|
||||
this._notifyOpacityId = 0;
|
||||
this._swipeScrollBeginId = 0;
|
||||
this._swipeScrollEndId = 0;
|
||||
},
|
||||
|
||||
show: function() {
|
||||
@@ -550,7 +524,16 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
this._controls.show();
|
||||
this._thumbnailsBox.show();
|
||||
|
||||
this._updateWorkspacesViews();
|
||||
this._workspaces = [];
|
||||
for (let i = 0; i < global.screen.n_workspaces; i++) {
|
||||
let metaWorkspace = global.screen.get_workspace_by_index(i);
|
||||
this._workspaces[i] = new Workspace.Workspace(metaWorkspace, this._monitorIndex);
|
||||
}
|
||||
|
||||
if (this.workspacesView)
|
||||
this.workspacesView.destroy();
|
||||
this.workspacesView = new WorkspacesView(this._workspaces);
|
||||
this._updateWorkspacesGeometry();
|
||||
|
||||
this._restackedNotifyId =
|
||||
global.screen.connect('restacked',
|
||||
@@ -581,12 +564,6 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
this._onRestacked();
|
||||
},
|
||||
|
||||
zoomFromOverview: function() {
|
||||
for (let i = 0; i < this._workspacesViews.length; i++) {
|
||||
this._workspacesViews[i].hide();
|
||||
}
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
this._controls.hide();
|
||||
this._thumbnailsBox.hide();
|
||||
@@ -620,120 +597,12 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
this._windowDragEndId = 0;
|
||||
}
|
||||
|
||||
for (let i = 0; i < this._workspacesViews.length; i++)
|
||||
this._workspacesViews[i].destroy();
|
||||
this._workspacesViews = null;
|
||||
|
||||
for (let i = 0; i < this._workspaces.length; i++)
|
||||
for (let w = 0; w < this._workspaces[i].length; w++) {
|
||||
this._workspaces[i][w].disconnectAll();
|
||||
this._workspaces[i][w].destroy();
|
||||
}
|
||||
},
|
||||
|
||||
_setupSwipeScrolling: function() {
|
||||
if (this._swipeScrollBeginId)
|
||||
Main.overview.disconnect(this._swipeScrollBeginId);
|
||||
this._swipeScrollBeginId = 0;
|
||||
|
||||
if (this._swipeScrollEndId)
|
||||
Main.overview.disconnect(this._swipeScrollEndId);
|
||||
this._swipeScrollEndId = 0;
|
||||
|
||||
if (!this.actor.mapped)
|
||||
return;
|
||||
|
||||
let direction = Overview.SwipeScrollDirection.VERTICAL;
|
||||
Main.overview.setScrollAdjustment(this._scrollAdjustment,
|
||||
direction);
|
||||
this._swipeScrollBeginId = Main.overview.connect('swipe-scroll-begin',
|
||||
Lang.bind(this, function() {
|
||||
for (let i = 0; i < this._workspacesViews.length; i++)
|
||||
this._workspacesViews[i].startSwipeScroll();
|
||||
}));
|
||||
this._swipeScrollEndId = Main.overview.connect('swipe-scroll-end',
|
||||
Lang.bind(this, function(overview, result) {
|
||||
for (let i = 0; i < this._workspacesViews.length; i++)
|
||||
this._workspacesViews[i].endSwipeScroll(result);
|
||||
}));
|
||||
},
|
||||
|
||||
_workspacesOnlyOnPrimaryChanged: function() {
|
||||
this._workspacesOnlyOnPrimary = this._settings.get_boolean('workspaces-only-on-primary');
|
||||
|
||||
if (!Main.overview.visible)
|
||||
return;
|
||||
|
||||
this._updateWorkspacesViews();
|
||||
},
|
||||
|
||||
_updateWorkspacesViews: function() {
|
||||
if (this._workspacesViews)
|
||||
for (let i = 0; i < this._workspacesViews.length; i++)
|
||||
this._workspacesViews[i].destroy();
|
||||
|
||||
if (this._workspaces)
|
||||
for (let i = 0; i < this._workspaces.length; i++)
|
||||
for (let w = 0; w < this._workspaces[i].length; w++)
|
||||
this._workspaces[i][w].destroy();
|
||||
|
||||
this._workspacesViews = [];
|
||||
this._workspaces = [];
|
||||
let monitors = Main.layoutManager.monitors;
|
||||
for (let i = 0; i < monitors.length; i++) {
|
||||
if (this._workspacesOnlyOnPrimary && i != this._primaryIndex)
|
||||
continue; // we are only interested in the primary monitor
|
||||
|
||||
let monitorWorkspaces = [];
|
||||
for (let w = 0; w < global.screen.n_workspaces; w++) {
|
||||
let metaWorkspace = global.screen.get_workspace_by_index(w);
|
||||
monitorWorkspaces.push(new Workspace.Workspace(metaWorkspace, i));
|
||||
}
|
||||
|
||||
this._workspaces.push(monitorWorkspaces);
|
||||
|
||||
let view = new WorkspacesView(monitorWorkspaces);
|
||||
if (this._workspacesOnlyOnPrimary || i == this._primaryIndex) {
|
||||
this._scrollAdjustment = view.scrollAdjustment;
|
||||
this._scrollAdjustment.connect('notify::value',
|
||||
Lang.bind(this, this._scrollValueChanged));
|
||||
this._setupSwipeScrolling();
|
||||
}
|
||||
this._workspacesViews.push(view);
|
||||
this.workspacesView.destroy();
|
||||
this.workspacesView = null;
|
||||
for (let w = 0; w < this._workspaces.length; w++) {
|
||||
this._workspaces[w].disconnectAll();
|
||||
this._workspaces[w].destroy();
|
||||
}
|
||||
|
||||
this._updateWorkspacesGeometry();
|
||||
|
||||
for (let i = 0; i < this._workspacesViews.length; i++)
|
||||
global.overlay_group.add_actor(this._workspacesViews[i].actor);
|
||||
},
|
||||
|
||||
_scrollValueChanged: function() {
|
||||
if (this._workspacesOnlyOnPrimary)
|
||||
return;
|
||||
|
||||
for (let i = 0; i < this._workspacesViews.length; i++) {
|
||||
if (i == this._primaryIndex)
|
||||
continue;
|
||||
|
||||
let adjustment = this._workspacesViews[i].scrollAdjustment;
|
||||
// the adjustments work in terms of workspaces, so the
|
||||
// values map directly
|
||||
adjustment.value = this._scrollAdjustment.value;
|
||||
}
|
||||
},
|
||||
|
||||
_getPrimaryView: function() {
|
||||
if (!this._workspacesViews)
|
||||
return null;
|
||||
if (this._workspacesOnlyOnPrimary)
|
||||
return this._workspacesViews[0];
|
||||
else
|
||||
return this._workspacesViews[this._primaryIndex];
|
||||
},
|
||||
|
||||
activeWorkspaceHasMaximizedWindows: function() {
|
||||
return this._getPrimaryView().getActiveWorkspace().hasMaximizedWindows();
|
||||
},
|
||||
|
||||
// zoomFraction property allows us to tween the controls sliding in and out
|
||||
@@ -806,37 +675,8 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
this._updateWorkspacesGeometry();
|
||||
},
|
||||
|
||||
_parentSet: function(actor, oldParent) {
|
||||
if (oldParent && this._notifyOpacityId)
|
||||
oldParent.disconnect(this._notifyOpacityId);
|
||||
this._notifyOpacityId = 0;
|
||||
|
||||
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this,
|
||||
function() {
|
||||
let newParent = this.actor.get_parent();
|
||||
if (!newParent)
|
||||
return;
|
||||
|
||||
// This is kinda hackish - we want the primary view to
|
||||
// appear as parent of this.actor, though in reality it
|
||||
// is added directly to overlay_group
|
||||
this._notifyOpacityId = newParent.connect('notify::opacity',
|
||||
Lang.bind(this, function() {
|
||||
let opacity = this.actor.get_parent().opacity;
|
||||
let primaryView = this._getPrimaryView();
|
||||
if (!primaryView)
|
||||
return;
|
||||
primaryView.actor.opacity = opacity;
|
||||
if (opacity == 0)
|
||||
primaryView.actor.hide();
|
||||
else
|
||||
primaryView.actor.show();
|
||||
}));
|
||||
}));
|
||||
},
|
||||
|
||||
_updateWorkspacesGeometry: function() {
|
||||
if (!this._workspacesViews)
|
||||
if (!this.workspacesView)
|
||||
return;
|
||||
|
||||
let fullWidth = this.actor.allocation.x2 - this.actor.allocation.x1;
|
||||
@@ -857,6 +697,8 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
let clipX = rtl ? x + controlsVisible : x;
|
||||
let clipY = y + (fullHeight - clipHeight) / 2;
|
||||
|
||||
this.workspacesView.setClipRect(clipX, clipY, clipWidth, clipHeight);
|
||||
|
||||
if (this._zoomOut) {
|
||||
width -= controlsNatural;
|
||||
if (rtl)
|
||||
@@ -871,28 +713,7 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
let difference = fullHeight - height;
|
||||
y += difference / 2;
|
||||
|
||||
|
||||
let monitors = Main.layoutManager.monitors;
|
||||
let m = 0;
|
||||
for (let i = 0; i < monitors.length; i++) {
|
||||
if (i == this._primaryIndex) {
|
||||
this._workspacesViews[m].setClipRect(clipX, clipY,
|
||||
clipWidth, clipHeight);
|
||||
this._workspacesViews[m].setGeometry(x, y, width, height,
|
||||
difference);
|
||||
m++;
|
||||
} else if (!this._workspacesOnlyOnPrimary) {
|
||||
this._workspacesViews[m].setClipRect(monitors[i].x,
|
||||
monitors[i].y,
|
||||
monitors[i].width,
|
||||
monitors[i].height);
|
||||
this._workspacesViews[m].setGeometry(monitors[i].x,
|
||||
monitors[i].y,
|
||||
monitors[i].width,
|
||||
monitors[i].height, 0);
|
||||
m++;
|
||||
}
|
||||
}
|
||||
this.workspacesView.setGeometry(x, y, width, height, difference);
|
||||
},
|
||||
|
||||
_onRestacked: function() {
|
||||
@@ -904,14 +725,12 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
stackIndices[stack[i].get_meta_window().get_stable_sequence()] = i;
|
||||
}
|
||||
|
||||
for (let i = 0; i < this._workspacesViews.length; i++)
|
||||
this._workspacesViews[i].syncStacking(stackIndices);
|
||||
|
||||
this.workspacesView.syncStacking(stackIndices);
|
||||
this._thumbnailsBox.syncStacking(stackIndices);
|
||||
},
|
||||
|
||||
_workspacesChanged: function() {
|
||||
let oldNumWorkspaces = this._workspaces[0].length;
|
||||
let oldNumWorkspaces = this._workspaces.length;
|
||||
let newNumWorkspaces = global.screen.n_workspaces;
|
||||
let active = global.screen.get_active_workspace_index();
|
||||
|
||||
@@ -921,24 +740,15 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
this._updateAlwaysZoom();
|
||||
this._updateZoom();
|
||||
|
||||
if (this._workspacesViews == null)
|
||||
if (this.workspacesView == null)
|
||||
return;
|
||||
|
||||
let lostWorkspaces = [];
|
||||
if (newNumWorkspaces > oldNumWorkspaces) {
|
||||
let monitors = Main.layoutManager.monitors;
|
||||
let m = 0;
|
||||
for (let i = 0; i < monitors.length; i++) {
|
||||
if (this._workspacesOnlyOnPrimaryChanged &&
|
||||
i != this._primaryIndex)
|
||||
continue;
|
||||
|
||||
// Assume workspaces are only added at the end
|
||||
for (let w = oldNumWorkspaces; w < newNumWorkspaces; w++) {
|
||||
let metaWorkspace = global.screen.get_workspace_by_index(w);
|
||||
this._workspaces[m++][w] =
|
||||
new Workspace.Workspace(metaWorkspace, i);
|
||||
}
|
||||
// Assume workspaces are only added at the end
|
||||
for (let w = oldNumWorkspaces; w < newNumWorkspaces; w++) {
|
||||
let metaWorkspace = global.screen.get_workspace_by_index(w);
|
||||
this._workspaces[w] = new Workspace.Workspace(metaWorkspace, this._monitorIndex);
|
||||
}
|
||||
|
||||
this._thumbnailsBox.addThumbnails(oldNumWorkspaces, newNumWorkspaces - oldNumWorkspaces);
|
||||
@@ -949,28 +759,25 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
let removedNum = oldNumWorkspaces - newNumWorkspaces;
|
||||
for (let w = 0; w < oldNumWorkspaces; w++) {
|
||||
let metaWorkspace = global.screen.get_workspace_by_index(w);
|
||||
if (this._workspaces[0][w].metaWorkspace != metaWorkspace) {
|
||||
if (this._workspaces[w].metaWorkspace != metaWorkspace) {
|
||||
removedIndex = w;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < this._workspaces.length; i++) {
|
||||
lostWorkspaces = this._workspaces[i].splice(removedIndex,
|
||||
removedNum);
|
||||
lostWorkspaces = this._workspaces.splice(removedIndex,
|
||||
removedNum);
|
||||
|
||||
for (let l = 0; l < lostWorkspaces.length; l++) {
|
||||
lostWorkspaces[l].disconnectAll();
|
||||
lostWorkspaces[l].destroy();
|
||||
}
|
||||
for (let l = 0; l < lostWorkspaces.length; l++) {
|
||||
lostWorkspaces[l].disconnectAll();
|
||||
lostWorkspaces[l].destroy();
|
||||
}
|
||||
|
||||
this._thumbnailsBox.removeThumbmails(removedIndex, removedNum);
|
||||
}
|
||||
|
||||
for (let i = 0; i < this._workspacesViews.length; i++)
|
||||
this._workspacesViews[i].updateWorkspaces(oldNumWorkspaces,
|
||||
newNumWorkspaces);
|
||||
this.workspacesView.updateWorkspaces(oldNumWorkspaces,
|
||||
newNumWorkspaces);
|
||||
},
|
||||
|
||||
_updateZoom : function() {
|
||||
@@ -982,7 +789,7 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
this._zoomOut = shouldZoom;
|
||||
this._updateWorkspacesGeometry();
|
||||
|
||||
if (!this._workspacesViews)
|
||||
if (!this.workspacesView)
|
||||
return;
|
||||
|
||||
Tweener.addTween(this,
|
||||
@@ -990,8 +797,7 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
time: WORKSPACE_SWITCH_TIME,
|
||||
transition: 'easeOutQuad' });
|
||||
|
||||
for (let i = 0; i < this._workspacesViews.length; i++)
|
||||
this._workspacesViews[i].updateWindowPositions();
|
||||
this.workspacesView.updateWindowPositions();
|
||||
}
|
||||
},
|
||||
|
||||
|
@@ -35,7 +35,6 @@ kn
|
||||
ku
|
||||
lt
|
||||
lv
|
||||
mk
|
||||
mr
|
||||
ms
|
||||
nb
|
||||
|
@@ -36,7 +36,6 @@ js/ui/status/volume.js
|
||||
js/ui/telepathyClient.js
|
||||
js/ui/userMenu.js
|
||||
js/ui/viewSelector.js
|
||||
js/ui/wanda.js
|
||||
js/ui/windowAttentionHandler.js
|
||||
src/gvc/gvc-mixer-control.c
|
||||
src/main.c
|
||||
|
4
po/it.po
4
po/it.po
@@ -11,7 +11,7 @@ msgstr ""
|
||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
|
||||
"shell&keywords=I18N+L10N&component=general\n"
|
||||
"POT-Creation-Date: 2011-10-04 20:49+0000\n"
|
||||
"PO-Revision-Date: 2012-01-04 10:19+0100\n"
|
||||
"PO-Revision-Date: 2011-10-17 10:30+0200\n"
|
||||
"Last-Translator: Luca Ferretti <lferrett@gnome.org>\n"
|
||||
"Language-Team: Italian <tp@lists.linux.it>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@@ -583,7 +583,7 @@ msgstr[1] "Il sistema verrà spento automaticamente tra %d secondi."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:87
|
||||
msgid "Powering off the system."
|
||||
msgstr "Spegnimento del sistema."
|
||||
msgstr "pegnimento del sistema."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:98
|
||||
msgid "Click Restart to quit these applications and restart the system."
|
||||
|
723
po/zh_CN.po
723
po/zh_CN.po
File diff suppressed because it is too large
Load Diff
@@ -179,8 +179,6 @@ gnome_shell_real_CPPFLAGS = $(gnome_shell_cflags)
|
||||
gnome_shell_real_LDADD = libgnome-shell.la $(libgnome_shell_la_LIBADD)
|
||||
gnome_shell_real_DEPENDENCIES = libgnome-shell.la
|
||||
|
||||
EXTRA_DIST += test-gapplication.js
|
||||
|
||||
########################################
|
||||
|
||||
shell_recorder_sources = \
|
||||
|
@@ -323,7 +323,7 @@ gnome_shell_plugin_xevent_filter (MetaPlugin *plugin,
|
||||
#endif
|
||||
|
||||
if ((xev->xany.type == EnterNotify || xev->xany.type == LeaveNotify)
|
||||
&& xev->xcrossing.window == clutter_x11_get_stage_window (CLUTTER_STAGE (meta_plugin_get_stage (plugin))))
|
||||
&& xev->xcrossing.window == clutter_x11_get_stage_window (CLUTTER_STAGE (clutter_stage_get_default ())))
|
||||
{
|
||||
/* If the pointer enters a child of the stage window (eg, a
|
||||
* trayicon), we want to consider it to still be in the stage,
|
||||
|
249
src/main.c
249
src/main.c
@@ -8,6 +8,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <cogl-pango/cogl-pango.h>
|
||||
#include <clutter/clutter.h>
|
||||
#include <clutter/x11/clutter-x11.h>
|
||||
#include <gdk/gdk.h>
|
||||
@@ -158,6 +159,157 @@ shell_dbus_init (gboolean replace)
|
||||
g_object_unref (session);
|
||||
}
|
||||
|
||||
static void
|
||||
constrain_tooltip (StTooltip *tooltip,
|
||||
const ClutterGeometry *geometry,
|
||||
ClutterGeometry *adjusted_geometry,
|
||||
gpointer data)
|
||||
{
|
||||
const ClutterGeometry *tip_area = st_tooltip_get_tip_area (tooltip);
|
||||
ShellGlobal *global = shell_global_get ();
|
||||
MetaScreen *screen = shell_global_get_screen (global);
|
||||
int n_monitors = meta_screen_get_n_monitors (screen);
|
||||
int i;
|
||||
|
||||
*adjusted_geometry = *geometry;
|
||||
|
||||
/* A point that determines what screen we'll constrain to */
|
||||
int x = tip_area->x + tip_area->width / 2;
|
||||
int y = tip_area->y + tip_area->height / 2;
|
||||
|
||||
for (i = 0; i < n_monitors; i++)
|
||||
{
|
||||
MetaRectangle rect;
|
||||
meta_screen_get_monitor_geometry (screen, i, &rect);
|
||||
if (x >= rect.x && x < rect.x + rect.width &&
|
||||
y >= rect.y && y < rect.y + rect.height)
|
||||
{
|
||||
if (adjusted_geometry->x + adjusted_geometry->width > rect.x + rect.width)
|
||||
adjusted_geometry->x = rect.x + rect.width - adjusted_geometry->width;
|
||||
if (adjusted_geometry->x < rect.x)
|
||||
adjusted_geometry->x = rect.x;
|
||||
|
||||
if (adjusted_geometry->y + adjusted_geometry->height > rect.y + rect.height)
|
||||
adjusted_geometry->y = rect.y + rect.height - adjusted_geometry->height;
|
||||
if (adjusted_geometry->y < rect.y)
|
||||
adjusted_geometry->y = rect.y;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
update_font_options (GtkSettings *settings)
|
||||
{
|
||||
StThemeContext *context;
|
||||
ClutterStage *stage;
|
||||
ClutterBackend *backend;
|
||||
gint dpi;
|
||||
gint hinting;
|
||||
gchar *hint_style_str;
|
||||
cairo_hint_style_t hint_style = CAIRO_HINT_STYLE_NONE;
|
||||
gint antialias;
|
||||
cairo_antialias_t antialias_mode = CAIRO_ANTIALIAS_NONE;
|
||||
cairo_font_options_t *options;
|
||||
|
||||
g_object_get (settings,
|
||||
"gtk-xft-dpi", &dpi,
|
||||
"gtk-xft-antialias", &antialias,
|
||||
"gtk-xft-hinting", &hinting,
|
||||
"gtk-xft-hintstyle", &hint_style_str,
|
||||
NULL);
|
||||
|
||||
stage = CLUTTER_STAGE (clutter_stage_get_default ());
|
||||
context = st_theme_context_get_for_stage (stage);
|
||||
|
||||
if (dpi != -1)
|
||||
/* GTK stores resolution as 1024 * dots/inch */
|
||||
st_theme_context_set_resolution (context, dpi / 1024);
|
||||
else
|
||||
st_theme_context_set_default_resolution (context);
|
||||
|
||||
st_tooltip_set_constrain_func (stage, constrain_tooltip, NULL, NULL);
|
||||
|
||||
/* Clutter (as of 0.9) passes comprehensively wrong font options
|
||||
* override whatever set_font_flags() did above.
|
||||
*
|
||||
* http://bugzilla.openedhand.com/show_bug.cgi?id=1456
|
||||
*/
|
||||
backend = clutter_get_default_backend ();
|
||||
options = cairo_font_options_create ();
|
||||
|
||||
cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_ON);
|
||||
|
||||
if (hinting >= 0 && !hinting)
|
||||
{
|
||||
hint_style = CAIRO_HINT_STYLE_NONE;
|
||||
}
|
||||
else if (hint_style_str)
|
||||
{
|
||||
if (strcmp (hint_style_str, "hintnone") == 0)
|
||||
hint_style = CAIRO_HINT_STYLE_NONE;
|
||||
else if (strcmp (hint_style_str, "hintslight") == 0)
|
||||
hint_style = CAIRO_HINT_STYLE_SLIGHT;
|
||||
else if (strcmp (hint_style_str, "hintmedium") == 0)
|
||||
hint_style = CAIRO_HINT_STYLE_MEDIUM;
|
||||
else if (strcmp (hint_style_str, "hintfull") == 0)
|
||||
hint_style = CAIRO_HINT_STYLE_FULL;
|
||||
}
|
||||
|
||||
g_free (hint_style_str);
|
||||
|
||||
cairo_font_options_set_hint_style (options, hint_style);
|
||||
|
||||
/* We don't want to turn on subpixel anti-aliasing; since Clutter
|
||||
* doesn't currently have the code to support ARGB masks,
|
||||
* generating them then squashing them back to A8 is pointless.
|
||||
*/
|
||||
antialias_mode = (antialias < 0 || antialias) ? CAIRO_ANTIALIAS_GRAY
|
||||
: CAIRO_ANTIALIAS_NONE;
|
||||
|
||||
cairo_font_options_set_antialias (options, antialias_mode);
|
||||
|
||||
clutter_backend_set_font_options (backend, options);
|
||||
cairo_font_options_destroy (options);
|
||||
}
|
||||
|
||||
static void
|
||||
settings_notify_cb (GtkSettings *settings,
|
||||
GParamSpec *pspec,
|
||||
gpointer data)
|
||||
{
|
||||
update_font_options (settings);
|
||||
}
|
||||
|
||||
static void
|
||||
shell_fonts_init (void)
|
||||
{
|
||||
GtkSettings *settings;
|
||||
CoglPangoFontMap *fontmap;
|
||||
|
||||
/* Disable text mipmapping; it causes problems on pre-GEM Intel
|
||||
* drivers and we should just be rendering text at the right
|
||||
* size rather than scaling it. If we do effects where we dynamically
|
||||
* zoom labels, then we might want to reconsider.
|
||||
*/
|
||||
fontmap = COGL_PANGO_FONT_MAP (clutter_get_font_map ());
|
||||
cogl_pango_font_map_set_use_mipmapping (fontmap, FALSE);
|
||||
|
||||
settings = gtk_settings_get_default ();
|
||||
g_object_connect (settings,
|
||||
"signal::notify::gtk-xft-dpi",
|
||||
G_CALLBACK (settings_notify_cb), NULL,
|
||||
"signal::notify::gtk-xft-antialias",
|
||||
G_CALLBACK (settings_notify_cb), NULL,
|
||||
"signal::notify::gtk-xft-hinting",
|
||||
G_CALLBACK (settings_notify_cb), NULL,
|
||||
"signal::notify::gtk-xft-hintstyle",
|
||||
G_CALLBACK (settings_notify_cb), NULL,
|
||||
NULL);
|
||||
update_font_options (settings);
|
||||
}
|
||||
|
||||
static void
|
||||
shell_prefs_init (void)
|
||||
{
|
||||
@@ -171,6 +323,100 @@ shell_prefs_init (void)
|
||||
OVERRIDES_SCHEMA);
|
||||
}
|
||||
|
||||
/* This is an IBus workaround. The flow of events with IBus is that every time
|
||||
* it gets gets a key event, it:
|
||||
*
|
||||
* Sends it to the daemon via D-Bus asynchronously
|
||||
* When it gets an reply, synthesizes a new GdkEvent and puts it into the
|
||||
* GDK event queue with gdk_event_put(), including
|
||||
* IBUS_FORWARD_MASK = 1 << 25 in the state to prevent a loop.
|
||||
*
|
||||
* (Normally, IBus uses the GTK+ key snooper mechanism to get the key
|
||||
* events early, but since our key events aren't visible to GTK+ key snoopers,
|
||||
* IBus will instead get the events via the standard
|
||||
* GtkIMContext.filter_keypress() mechanism.)
|
||||
*
|
||||
* There are a number of potential problems here; probably the worst
|
||||
* problem is that IBus doesn't forward the timestamp with the event
|
||||
* so that every key event that gets delivered ends up with
|
||||
* GDK_CURRENT_TIME. This creates some very subtle bugs; for example
|
||||
* if you have IBus running and a keystroke is used to trigger
|
||||
* launching an application, focus stealing prevention won't work
|
||||
* right. http://code.google.com/p/ibus/issues/detail?id=1184
|
||||
*
|
||||
* In any case, our normal flow of key events is:
|
||||
*
|
||||
* GDK filter function => clutter_x11_handle_event => clutter actor
|
||||
*
|
||||
* So, if we see a key event that gets delivered via the GDK event handler
|
||||
* function - then we know it must be one of these synthesized events, and
|
||||
* we should push it back to clutter.
|
||||
*
|
||||
* To summarize, the full key event flow with IBus is:
|
||||
*
|
||||
* GDK filter function
|
||||
* => Mutter
|
||||
* => gnome_shell_plugin_xevent_filter()
|
||||
* => clutter_x11_handle_event()
|
||||
* => clutter event delivery to actor
|
||||
* => gtk_im_context_filter_event()
|
||||
* => sent to IBus daemon
|
||||
* => response received from IBus daemon
|
||||
* => gdk_event_put()
|
||||
* => GDK event handler
|
||||
* => <this function>
|
||||
* => clutter_event_put()
|
||||
* => clutter event delivery to actor
|
||||
*
|
||||
* Anything else we see here we just pass on to the normal GDK event handler
|
||||
* gtk_main_do_event().
|
||||
*/
|
||||
static void
|
||||
gnome_shell_gdk_event_handler (GdkEvent *event_gdk,
|
||||
gpointer data)
|
||||
{
|
||||
if (event_gdk->type == GDK_KEY_PRESS || event_gdk->type == GDK_KEY_RELEASE)
|
||||
{
|
||||
ClutterActor *stage;
|
||||
Window stage_xwindow;
|
||||
|
||||
stage = clutter_stage_get_default ();
|
||||
stage_xwindow = clutter_x11_get_stage_window (CLUTTER_STAGE (stage));
|
||||
|
||||
if (GDK_WINDOW_XID (event_gdk->key.window) == stage_xwindow)
|
||||
{
|
||||
ClutterDeviceManager *device_manager = clutter_device_manager_get_default ();
|
||||
ClutterInputDevice *keyboard = clutter_device_manager_get_core_device (device_manager,
|
||||
CLUTTER_KEYBOARD_DEVICE);
|
||||
|
||||
ClutterEvent *event_clutter = clutter_event_new ((event_gdk->type == GDK_KEY_PRESS) ?
|
||||
CLUTTER_KEY_PRESS : CLUTTER_KEY_RELEASE);
|
||||
event_clutter->key.time = event_gdk->key.time;
|
||||
event_clutter->key.flags = CLUTTER_EVENT_NONE;
|
||||
event_clutter->key.stage = CLUTTER_STAGE (stage);
|
||||
event_clutter->key.source = NULL;
|
||||
|
||||
/* This depends on ClutterModifierType and GdkModifierType being
|
||||
* identical, which they are currently. (They both match the X
|
||||
* modifier state in the low 16-bits and have the same extensions.) */
|
||||
event_clutter->key.modifier_state = event_gdk->key.state;
|
||||
|
||||
event_clutter->key.keyval = event_gdk->key.keyval;
|
||||
event_clutter->key.hardware_keycode = event_gdk->key.hardware_keycode;
|
||||
event_clutter->key.unicode_value = gdk_keyval_to_unicode (event_clutter->key.keyval);
|
||||
event_clutter->key.device = keyboard;
|
||||
|
||||
clutter_event_put (event_clutter);
|
||||
clutter_event_free (event_clutter);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
gtk_main_do_event (event_gdk);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
malloc_statistics_callback (ShellPerfLog *perf_log,
|
||||
gpointer data)
|
||||
@@ -313,9 +559,12 @@ main (int argc, char **argv)
|
||||
|
||||
shell_dbus_init (meta_get_replace_current_wm ());
|
||||
shell_a11y_init ();
|
||||
shell_fonts_init ();
|
||||
shell_perf_log_init ();
|
||||
shell_prefs_init ();
|
||||
|
||||
gdk_event_handler_set (gnome_shell_gdk_event_handler, NULL, NULL);
|
||||
|
||||
g_irepository_prepend_search_path (GNOME_SHELL_PKGLIBDIR);
|
||||
#if HAVE_BLUETOOTH
|
||||
g_irepository_prepend_search_path (BLUETOOTH_DIR);
|
||||
|
@@ -63,6 +63,7 @@ int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
GOptionContext *context;
|
||||
ClutterActor *stage;
|
||||
GError *error = NULL;
|
||||
ShellGlobal *global;
|
||||
GjsContext *js_context;
|
||||
@@ -123,8 +124,9 @@ main(int argc, char **argv)
|
||||
filename = argv[1];
|
||||
}
|
||||
|
||||
stage = clutter_stage_get_default ();
|
||||
title = g_filename_display_basename (filename);
|
||||
g_set_prgname (title);
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), title);
|
||||
g_free (title);
|
||||
|
||||
#if HAVE_BLUETOOTH
|
||||
|
@@ -577,9 +577,6 @@ shell_app_update_window_actions (ShellApp *app, MetaWindow *window)
|
||||
g_object_set_data_full (G_OBJECT (window), "actions", actions, g_object_unref);
|
||||
}
|
||||
|
||||
if (!app->running_state->muxer)
|
||||
app->running_state->muxer = g_action_muxer_new ();
|
||||
|
||||
g_action_muxer_insert (app->running_state->muxer, "win", actions);
|
||||
g_object_notify (G_OBJECT (app), "action-group");
|
||||
}
|
||||
@@ -1095,10 +1092,7 @@ on_dbus_proxy_gotten (GObject *initable,
|
||||
g_dbus_proxy_get_connection (state->app_proxy),
|
||||
g_dbus_proxy_get_name (state->app_proxy),
|
||||
g_dbus_proxy_get_object_path (state->app_proxy));
|
||||
|
||||
if (!state->muxer)
|
||||
state->muxer = g_action_muxer_new ();
|
||||
|
||||
state->muxer = g_action_muxer_new ();
|
||||
g_action_muxer_insert (state->muxer, "app", state->remote_actions);
|
||||
g_strfreev (g_action_group_list_actions (state->remote_actions));
|
||||
|
||||
|
@@ -15,7 +15,6 @@
|
||||
#endif
|
||||
|
||||
#include <X11/extensions/Xfixes.h>
|
||||
#include <cogl-pango/cogl-pango.h>
|
||||
#include <canberra.h>
|
||||
#include <clutter/glx/clutter-glx.h>
|
||||
#include <clutter/x11/clutter-x11.h>
|
||||
@@ -794,249 +793,6 @@ global_stage_after_paint (ClutterStage *stage,
|
||||
"clutter.stagePaintDone");
|
||||
}
|
||||
|
||||
static void
|
||||
constrain_tooltip (StTooltip *tooltip,
|
||||
const ClutterGeometry *geometry,
|
||||
ClutterGeometry *adjusted_geometry,
|
||||
gpointer data)
|
||||
{
|
||||
const ClutterGeometry *tip_area = st_tooltip_get_tip_area (tooltip);
|
||||
ShellGlobal *global = shell_global_get ();
|
||||
MetaScreen *screen = shell_global_get_screen (global);
|
||||
int n_monitors = meta_screen_get_n_monitors (screen);
|
||||
int i;
|
||||
|
||||
*adjusted_geometry = *geometry;
|
||||
|
||||
/* A point that determines what screen we'll constrain to */
|
||||
int x = tip_area->x + tip_area->width / 2;
|
||||
int y = tip_area->y + tip_area->height / 2;
|
||||
|
||||
for (i = 0; i < n_monitors; i++)
|
||||
{
|
||||
MetaRectangle rect;
|
||||
meta_screen_get_monitor_geometry (screen, i, &rect);
|
||||
if (x >= rect.x && x < rect.x + rect.width &&
|
||||
y >= rect.y && y < rect.y + rect.height)
|
||||
{
|
||||
if (adjusted_geometry->x + adjusted_geometry->width > rect.x + rect.width)
|
||||
adjusted_geometry->x = rect.x + rect.width - adjusted_geometry->width;
|
||||
if (adjusted_geometry->x < rect.x)
|
||||
adjusted_geometry->x = rect.x;
|
||||
|
||||
if (adjusted_geometry->y + adjusted_geometry->height > rect.y + rect.height)
|
||||
adjusted_geometry->y = rect.y + rect.height - adjusted_geometry->height;
|
||||
if (adjusted_geometry->y < rect.y)
|
||||
adjusted_geometry->y = rect.y;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
update_font_options (GtkSettings *settings,
|
||||
ClutterStage *stage)
|
||||
{
|
||||
StThemeContext *context;
|
||||
ClutterBackend *backend;
|
||||
gint dpi;
|
||||
gint hinting;
|
||||
gchar *hint_style_str;
|
||||
cairo_hint_style_t hint_style = CAIRO_HINT_STYLE_NONE;
|
||||
gint antialias;
|
||||
cairo_antialias_t antialias_mode = CAIRO_ANTIALIAS_NONE;
|
||||
cairo_font_options_t *options;
|
||||
|
||||
g_object_get (settings,
|
||||
"gtk-xft-dpi", &dpi,
|
||||
"gtk-xft-antialias", &antialias,
|
||||
"gtk-xft-hinting", &hinting,
|
||||
"gtk-xft-hintstyle", &hint_style_str,
|
||||
NULL);
|
||||
|
||||
context = st_theme_context_get_for_stage (stage);
|
||||
|
||||
if (dpi != -1)
|
||||
/* GTK stores resolution as 1024 * dots/inch */
|
||||
st_theme_context_set_resolution (context, dpi / 1024);
|
||||
else
|
||||
st_theme_context_set_default_resolution (context);
|
||||
|
||||
st_tooltip_set_constrain_func (stage, constrain_tooltip, NULL, NULL);
|
||||
|
||||
/* Clutter (as of 0.9) passes comprehensively wrong font options
|
||||
* override whatever set_font_flags() did above.
|
||||
*
|
||||
* http://bugzilla.openedhand.com/show_bug.cgi?id=1456
|
||||
*/
|
||||
backend = clutter_get_default_backend ();
|
||||
options = cairo_font_options_create ();
|
||||
|
||||
cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_ON);
|
||||
|
||||
if (hinting >= 0 && !hinting)
|
||||
{
|
||||
hint_style = CAIRO_HINT_STYLE_NONE;
|
||||
}
|
||||
else if (hint_style_str)
|
||||
{
|
||||
if (strcmp (hint_style_str, "hintnone") == 0)
|
||||
hint_style = CAIRO_HINT_STYLE_NONE;
|
||||
else if (strcmp (hint_style_str, "hintslight") == 0)
|
||||
hint_style = CAIRO_HINT_STYLE_SLIGHT;
|
||||
else if (strcmp (hint_style_str, "hintmedium") == 0)
|
||||
hint_style = CAIRO_HINT_STYLE_MEDIUM;
|
||||
else if (strcmp (hint_style_str, "hintfull") == 0)
|
||||
hint_style = CAIRO_HINT_STYLE_FULL;
|
||||
}
|
||||
|
||||
g_free (hint_style_str);
|
||||
|
||||
cairo_font_options_set_hint_style (options, hint_style);
|
||||
|
||||
/* We don't want to turn on subpixel anti-aliasing; since Clutter
|
||||
* doesn't currently have the code to support ARGB masks,
|
||||
* generating them then squashing them back to A8 is pointless.
|
||||
*/
|
||||
antialias_mode = (antialias < 0 || antialias) ? CAIRO_ANTIALIAS_GRAY
|
||||
: CAIRO_ANTIALIAS_NONE;
|
||||
|
||||
cairo_font_options_set_antialias (options, antialias_mode);
|
||||
|
||||
clutter_backend_set_font_options (backend, options);
|
||||
cairo_font_options_destroy (options);
|
||||
}
|
||||
|
||||
static void
|
||||
settings_notify_cb (GtkSettings *settings,
|
||||
GParamSpec *pspec,
|
||||
gpointer data)
|
||||
{
|
||||
update_font_options (settings, CLUTTER_STAGE (data));
|
||||
}
|
||||
|
||||
static void
|
||||
shell_fonts_init (ClutterStage *stage)
|
||||
{
|
||||
GtkSettings *settings;
|
||||
CoglPangoFontMap *fontmap;
|
||||
|
||||
/* Disable text mipmapping; it causes problems on pre-GEM Intel
|
||||
* drivers and we should just be rendering text at the right
|
||||
* size rather than scaling it. If we do effects where we dynamically
|
||||
* zoom labels, then we might want to reconsider.
|
||||
*/
|
||||
fontmap = COGL_PANGO_FONT_MAP (clutter_get_font_map ());
|
||||
cogl_pango_font_map_set_use_mipmapping (fontmap, FALSE);
|
||||
|
||||
settings = gtk_settings_get_default ();
|
||||
g_object_connect (settings,
|
||||
"signal::notify::gtk-xft-dpi",
|
||||
G_CALLBACK (settings_notify_cb), stage,
|
||||
"signal::notify::gtk-xft-antialias",
|
||||
G_CALLBACK (settings_notify_cb), stage,
|
||||
"signal::notify::gtk-xft-hinting",
|
||||
G_CALLBACK (settings_notify_cb), stage,
|
||||
"signal::notify::gtk-xft-hintstyle",
|
||||
G_CALLBACK (settings_notify_cb), stage,
|
||||
NULL);
|
||||
update_font_options (settings, stage);
|
||||
}
|
||||
|
||||
/* This is an IBus workaround. The flow of events with IBus is that every time
|
||||
* it gets gets a key event, it:
|
||||
*
|
||||
* Sends it to the daemon via D-Bus asynchronously
|
||||
* When it gets an reply, synthesizes a new GdkEvent and puts it into the
|
||||
* GDK event queue with gdk_event_put(), including
|
||||
* IBUS_FORWARD_MASK = 1 << 25 in the state to prevent a loop.
|
||||
*
|
||||
* (Normally, IBus uses the GTK+ key snooper mechanism to get the key
|
||||
* events early, but since our key events aren't visible to GTK+ key snoopers,
|
||||
* IBus will instead get the events via the standard
|
||||
* GtkIMContext.filter_keypress() mechanism.)
|
||||
*
|
||||
* There are a number of potential problems here; probably the worst
|
||||
* problem is that IBus doesn't forward the timestamp with the event
|
||||
* so that every key event that gets delivered ends up with
|
||||
* GDK_CURRENT_TIME. This creates some very subtle bugs; for example
|
||||
* if you have IBus running and a keystroke is used to trigger
|
||||
* launching an application, focus stealing prevention won't work
|
||||
* right. http://code.google.com/p/ibus/issues/detail?id=1184
|
||||
*
|
||||
* In any case, our normal flow of key events is:
|
||||
*
|
||||
* GDK filter function => clutter_x11_handle_event => clutter actor
|
||||
*
|
||||
* So, if we see a key event that gets delivered via the GDK event handler
|
||||
* function - then we know it must be one of these synthesized events, and
|
||||
* we should push it back to clutter.
|
||||
*
|
||||
* To summarize, the full key event flow with IBus is:
|
||||
*
|
||||
* GDK filter function
|
||||
* => Mutter
|
||||
* => gnome_shell_plugin_xevent_filter()
|
||||
* => clutter_x11_handle_event()
|
||||
* => clutter event delivery to actor
|
||||
* => gtk_im_context_filter_event()
|
||||
* => sent to IBus daemon
|
||||
* => response received from IBus daemon
|
||||
* => gdk_event_put()
|
||||
* => GDK event handler
|
||||
* => <this function>
|
||||
* => clutter_event_put()
|
||||
* => clutter event delivery to actor
|
||||
*
|
||||
* Anything else we see here we just pass on to the normal GDK event handler
|
||||
* gtk_main_do_event().
|
||||
*/
|
||||
static void
|
||||
gnome_shell_gdk_event_handler (GdkEvent *event_gdk,
|
||||
gpointer data)
|
||||
{
|
||||
if (event_gdk->type == GDK_KEY_PRESS || event_gdk->type == GDK_KEY_RELEASE)
|
||||
{
|
||||
ClutterActor *stage;
|
||||
Window stage_xwindow;
|
||||
|
||||
stage = CLUTTER_ACTOR (data);
|
||||
stage_xwindow = clutter_x11_get_stage_window (CLUTTER_STAGE (stage));
|
||||
|
||||
if (GDK_WINDOW_XID (event_gdk->key.window) == stage_xwindow)
|
||||
{
|
||||
ClutterDeviceManager *device_manager = clutter_device_manager_get_default ();
|
||||
ClutterInputDevice *keyboard = clutter_device_manager_get_core_device (device_manager,
|
||||
CLUTTER_KEYBOARD_DEVICE);
|
||||
|
||||
ClutterEvent *event_clutter = clutter_event_new ((event_gdk->type == GDK_KEY_PRESS) ?
|
||||
CLUTTER_KEY_PRESS : CLUTTER_KEY_RELEASE);
|
||||
event_clutter->key.time = event_gdk->key.time;
|
||||
event_clutter->key.flags = CLUTTER_EVENT_NONE;
|
||||
event_clutter->key.stage = CLUTTER_STAGE (stage);
|
||||
event_clutter->key.source = NULL;
|
||||
|
||||
/* This depends on ClutterModifierType and GdkModifierType being
|
||||
* identical, which they are currently. (They both match the X
|
||||
* modifier state in the low 16-bits and have the same extensions.) */
|
||||
event_clutter->key.modifier_state = event_gdk->key.state;
|
||||
|
||||
event_clutter->key.keyval = event_gdk->key.keyval;
|
||||
event_clutter->key.hardware_keycode = event_gdk->key.hardware_keycode;
|
||||
event_clutter->key.unicode_value = gdk_keyval_to_unicode (event_clutter->key.keyval);
|
||||
event_clutter->key.device = keyboard;
|
||||
|
||||
clutter_event_put (event_clutter);
|
||||
clutter_event_free (event_clutter);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
gtk_main_do_event (event_gdk);
|
||||
}
|
||||
|
||||
void
|
||||
_shell_global_set_plugin (ShellGlobal *global,
|
||||
MetaPlugin *plugin)
|
||||
@@ -1082,10 +838,6 @@ _shell_global_set_plugin (ShellGlobal *global,
|
||||
g_signal_connect (global->meta_display, "notify::focus-window",
|
||||
G_CALLBACK (focus_window_changed), global);
|
||||
|
||||
shell_fonts_init (global->stage);
|
||||
|
||||
gdk_event_handler_set (gnome_shell_gdk_event_handler, global->stage, NULL);
|
||||
|
||||
global->focus_manager = st_focus_manager_get_for_stage (global->stage);
|
||||
}
|
||||
|
||||
|
@@ -321,29 +321,19 @@ shell_xfixes_cursor_class_init (ShellXFixesCursorClass *klass)
|
||||
}
|
||||
|
||||
/**
|
||||
* shell_xfixes_cursor_get_for_stage:
|
||||
* @stage: (transfer none): The #ClutterStage to get the cursor for
|
||||
* shell_xfixes_cursor_get_default:
|
||||
*
|
||||
* Return value: (transfer none): A #ShellXFixesCursor instance
|
||||
* Return value: (transfer none): The global #ShellXFixesCursor singleton
|
||||
*/
|
||||
ShellXFixesCursor *
|
||||
shell_xfixes_cursor_get_for_stage (ClutterStage *stage)
|
||||
shell_xfixes_cursor_get_default ()
|
||||
{
|
||||
ShellXFixesCursor *instance;
|
||||
static GQuark xfixes_cursor_quark;
|
||||
|
||||
if (G_UNLIKELY (xfixes_cursor_quark == 0))
|
||||
xfixes_cursor_quark = g_quark_from_static_string ("gnome-shell-xfixes-cursor");
|
||||
|
||||
instance = g_object_get_qdata (G_OBJECT (stage), xfixes_cursor_quark);
|
||||
static ShellXFixesCursor *instance = NULL;
|
||||
|
||||
if (instance == NULL)
|
||||
{
|
||||
instance = g_object_new (SHELL_TYPE_XFIXES_CURSOR,
|
||||
"stage", stage,
|
||||
NULL);
|
||||
g_object_set_qdata (G_OBJECT (stage), xfixes_cursor_quark, instance);
|
||||
}
|
||||
instance = g_object_new (SHELL_TYPE_XFIXES_CURSOR,
|
||||
"stage", clutter_stage_get_default (),
|
||||
NULL);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
@@ -19,7 +19,7 @@ typedef struct _ShellXFixesCursorClass ShellXFixesCursorClass;
|
||||
|
||||
GType shell_xfixes_cursor_get_type (void) G_GNUC_CONST;
|
||||
|
||||
ShellXFixesCursor *shell_xfixes_cursor_get_for_stage (ClutterStage *stage);
|
||||
ShellXFixesCursor *shell_xfixes_cursor_get_default (void);
|
||||
|
||||
void shell_xfixes_cursor_show (ShellXFixesCursor *xfixes_cursor);
|
||||
void shell_xfixes_cursor_hide (ShellXFixesCursor *xfixes_cursor);
|
||||
|
@@ -174,20 +174,6 @@ st_icon_dispose (GObject *gobject)
|
||||
G_OBJECT_CLASS (st_icon_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
static void
|
||||
st_icon_finalize (GObject *gobject)
|
||||
{
|
||||
StIconPrivate *priv = ST_ICON (gobject)->priv;
|
||||
|
||||
if (priv->icon_name)
|
||||
{
|
||||
g_free (priv->icon_name);
|
||||
priv->icon_name = NULL;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (st_icon_parent_class)->finalize (gobject);
|
||||
}
|
||||
|
||||
static void
|
||||
st_icon_get_preferred_height (ClutterActor *actor,
|
||||
gfloat for_width,
|
||||
@@ -331,7 +317,6 @@ st_icon_class_init (StIconClass *klass)
|
||||
object_class->get_property = st_icon_get_property;
|
||||
object_class->set_property = st_icon_set_property;
|
||||
object_class->dispose = st_icon_dispose;
|
||||
object_class->finalize = st_icon_finalize;
|
||||
|
||||
actor_class->get_preferred_height = st_icon_get_preferred_height;
|
||||
actor_class->get_preferred_width = st_icon_get_preferred_width;
|
||||
|
@@ -1226,9 +1226,9 @@ load_sliced_image (GSimpleAsyncResult *result,
|
||||
|
||||
width = gdk_pixbuf_get_width (pix);
|
||||
height = gdk_pixbuf_get_height (pix);
|
||||
for (y = 0; y < height; y += data->grid_height)
|
||||
for (y = 0; y < height; y += data->grid_width)
|
||||
{
|
||||
for (x = 0; x < width; x += data->grid_width)
|
||||
for (x = 0; x < width; x += data->grid_height)
|
||||
{
|
||||
GdkPixbuf *pixbuf = gdk_pixbuf_new_subpixbuf (pix, x, y, data->grid_width, data->grid_height);
|
||||
g_assert (pixbuf != NULL);
|
||||
|
@@ -5,7 +5,6 @@
|
||||
* Copyright 2009, 2010 Red Hat, Inc.
|
||||
* Copyright 2009, 2010 Florian Müllner
|
||||
* Copyright 2010 Intel Corporation.
|
||||
* Copyright 2011 Quentin "Sardem FF7" Glidic
|
||||
*
|
||||
* Contains code derived from:
|
||||
* rectangle.c: Rounded rectangle.
|
||||
@@ -391,110 +390,69 @@ st_theme_node_lookup_corner (StThemeNode *node,
|
||||
return material;
|
||||
}
|
||||
|
||||
static void
|
||||
get_background_scale (StThemeNode *node,
|
||||
gdouble painting_area_width,
|
||||
gdouble painting_area_height,
|
||||
gdouble background_image_width,
|
||||
gdouble background_image_height,
|
||||
gdouble *scale_w,
|
||||
gdouble *scale_h)
|
||||
{
|
||||
*scale_w = -1.0;
|
||||
*scale_h = -1.0;
|
||||
|
||||
switch (node->background_size)
|
||||
{
|
||||
case ST_BACKGROUND_SIZE_AUTO:
|
||||
*scale_w = 1.0;
|
||||
break;
|
||||
case ST_BACKGROUND_SIZE_CONTAIN:
|
||||
if (background_image_width > background_image_height)
|
||||
*scale_w = painting_area_width / background_image_width;
|
||||
else
|
||||
*scale_w = painting_area_height / background_image_height;
|
||||
break;
|
||||
case ST_BACKGROUND_SIZE_COVER:
|
||||
if (background_image_width < background_image_height)
|
||||
*scale_w = painting_area_width / background_image_width;
|
||||
else
|
||||
*scale_w = painting_area_height / background_image_height;
|
||||
break;
|
||||
case ST_BACKGROUND_SIZE_FIXED:
|
||||
if (node->background_size_w > -1)
|
||||
{
|
||||
*scale_w = node->background_size_w / background_image_width;
|
||||
if (node->background_size_h > -1)
|
||||
*scale_h = node->background_size_h / background_image_height;
|
||||
}
|
||||
else if (node->background_size_h > -1)
|
||||
*scale_w = node->background_size_h / background_image_height;
|
||||
break;
|
||||
}
|
||||
if (*scale_h < 0.0)
|
||||
*scale_h = *scale_w;
|
||||
}
|
||||
|
||||
static void
|
||||
get_background_coordinates (StThemeNode *node,
|
||||
gdouble painting_area_width,
|
||||
gdouble painting_area_height,
|
||||
gdouble background_image_width,
|
||||
gdouble background_image_height,
|
||||
gdouble *x,
|
||||
gdouble *y)
|
||||
{
|
||||
/* honor the specified position if any */
|
||||
if (node->background_position_set)
|
||||
{
|
||||
*x = node->background_position_x;
|
||||
*y = node->background_position_y;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* center the background on the widget */
|
||||
*x = (painting_area_width / 2.0) - (background_image_width / 2.0);
|
||||
*y = (painting_area_height / 2.0) - (background_image_height / 2.0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
get_background_position (StThemeNode *self,
|
||||
const ClutterActorBox *allocation,
|
||||
ClutterActorBox *result)
|
||||
{
|
||||
gdouble painting_area_width, painting_area_height;
|
||||
gdouble background_image_width, background_image_height;
|
||||
gdouble x, y;
|
||||
gdouble scale_w, scale_h;
|
||||
gfloat w, h;
|
||||
|
||||
/* get the background image size */
|
||||
background_image_width = allocation->x2 - allocation->x1;
|
||||
background_image_height = allocation->y2 - allocation->y1;
|
||||
result->x1 = result->y1 = 0;
|
||||
result->x2 = allocation->x2 - allocation->x1;
|
||||
result->y2 = allocation->y2 - allocation->y1;
|
||||
|
||||
/* get the painting area size */
|
||||
painting_area_width = cogl_texture_get_width (self->background_texture);
|
||||
painting_area_height = cogl_texture_get_height (self->background_texture);
|
||||
w = cogl_texture_get_width (self->background_texture);
|
||||
h = cogl_texture_get_height (self->background_texture);
|
||||
|
||||
/* scale if requested */
|
||||
get_background_scale (self,
|
||||
painting_area_width, painting_area_height,
|
||||
background_image_width, background_image_height,
|
||||
&scale_w, &scale_h);
|
||||
background_image_width *= scale_w;
|
||||
background_image_height *= scale_h;
|
||||
/* scale the background into the allocated bounds, when not being absolutely positioned */
|
||||
if ((w > result->x2 || h > result->y2) && !self->background_position_set)
|
||||
{
|
||||
gint new_h, new_w, offset;
|
||||
gint box_w, box_h;
|
||||
|
||||
/* get coordinates */
|
||||
get_background_coordinates (self,
|
||||
painting_area_width, painting_area_height,
|
||||
background_image_width, background_image_height,
|
||||
&x, &y);
|
||||
box_w = (int) result->x2;
|
||||
box_h = (int) result->y2;
|
||||
|
||||
/* place the background image */
|
||||
result->x1 = x;
|
||||
result->y1 = y;
|
||||
result->x2 = result->x1 + background_image_width;
|
||||
result->y2 = result->y1 + background_image_height;
|
||||
/* scale to fit */
|
||||
new_h = (int)((h / w) * ((gfloat) box_w));
|
||||
new_w = (int)((w / h) * ((gfloat) box_h));
|
||||
|
||||
if (new_h > box_h)
|
||||
{
|
||||
/* center for new width */
|
||||
offset = ((box_w) - new_w) * 0.5;
|
||||
result->x1 = offset;
|
||||
result->x2 = offset + new_w;
|
||||
|
||||
result->y2 = box_h;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* center for new height */
|
||||
offset = ((box_h) - new_h) * 0.5;
|
||||
result->y1 = offset;
|
||||
result->y2 = offset + new_h;
|
||||
|
||||
result->x2 = box_w;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* honor the specified position if any */
|
||||
if (self->background_position_set)
|
||||
{
|
||||
result->x1 = self->background_position_x;
|
||||
result->y1 = self->background_position_y;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* center the background on the widget */
|
||||
result->x1 = (int)(((allocation->x2 - allocation->x1) / 2) - (w / 2));
|
||||
result->y1 = (int)(((allocation->y2 - allocation->y1) / 2) - (h / 2));
|
||||
}
|
||||
result->x2 = result->x1 + w;
|
||||
result->y2 = result->y1 + h;
|
||||
}
|
||||
}
|
||||
|
||||
/* Use of this function marks code which doesn't support
|
||||
@@ -575,13 +533,12 @@ create_cairo_pattern_of_background_image (StThemeNode *node,
|
||||
cairo_content_t content;
|
||||
cairo_matrix_t matrix;
|
||||
const char *file;
|
||||
double height_ratio, width_ratio;
|
||||
int file_width;
|
||||
int file_height;
|
||||
|
||||
StTextureCache *texture_cache;
|
||||
|
||||
gdouble background_image_width, background_image_height;
|
||||
gdouble x, y;
|
||||
gdouble scale_w, scale_h;
|
||||
|
||||
file = st_theme_node_get_background_image (node);
|
||||
|
||||
texture_cache = st_texture_cache_get_default ();
|
||||
@@ -596,39 +553,90 @@ create_cairo_pattern_of_background_image (StThemeNode *node,
|
||||
content = cairo_surface_get_content (surface);
|
||||
pattern = cairo_pattern_create_for_surface (surface);
|
||||
|
||||
background_image_width = cairo_image_surface_get_width (surface);
|
||||
background_image_height = cairo_image_surface_get_height (surface);
|
||||
file_width = cairo_image_surface_get_width (surface);
|
||||
file_height = cairo_image_surface_get_height (surface);
|
||||
|
||||
height_ratio = file_height / node->alloc_height;
|
||||
width_ratio = file_width / node->alloc_width;
|
||||
|
||||
*needs_background_fill = TRUE;
|
||||
if ((file_width > node->alloc_width || file_height > node->alloc_height)
|
||||
&& !node->background_position_set)
|
||||
{
|
||||
double scale_factor;
|
||||
double x_offset, y_offset;
|
||||
|
||||
cairo_matrix_init_identity (&matrix);
|
||||
if (width_ratio > height_ratio)
|
||||
{
|
||||
double scaled_height;
|
||||
|
||||
get_background_scale (node,
|
||||
node->alloc_width, node->alloc_height,
|
||||
background_image_width, background_image_height,
|
||||
&scale_w, &scale_h);
|
||||
if ((scale_w != 1) || (scale_h != 1))
|
||||
cairo_matrix_scale (&matrix, 1.0/scale_w, 1.0/scale_h);
|
||||
background_image_width *= scale_w;
|
||||
background_image_height *= scale_h;
|
||||
/* center vertically */
|
||||
|
||||
get_background_coordinates (node,
|
||||
node->alloc_width, node->alloc_height,
|
||||
background_image_width, background_image_height,
|
||||
&x, &y);
|
||||
cairo_matrix_translate (&matrix, -x, -y);
|
||||
scale_factor = width_ratio;
|
||||
scaled_height = file_height / scale_factor;
|
||||
|
||||
/* If it's opaque, fills up the entire allocated
|
||||
* area, then don't bother doing a background fill first
|
||||
*/
|
||||
if (content != CAIRO_CONTENT_COLOR_ALPHA
|
||||
&& x >= 0
|
||||
&& -x + background_image_width >= node->alloc_width
|
||||
&& y >= 0
|
||||
&& -y + background_image_height >= node->alloc_height)
|
||||
*needs_background_fill = FALSE;
|
||||
x_offset = 0.;
|
||||
y_offset = - (node->alloc_height / 2. - scaled_height / 2.);
|
||||
}
|
||||
else
|
||||
{
|
||||
double scaled_width;
|
||||
|
||||
cairo_pattern_set_matrix (pattern, &matrix);
|
||||
/* center horizontally */
|
||||
|
||||
scale_factor = height_ratio;
|
||||
scaled_width = file_width / scale_factor;
|
||||
|
||||
y_offset = 0.;
|
||||
x_offset = - (node->alloc_width / 2. - scaled_width / 2.);
|
||||
}
|
||||
|
||||
cairo_matrix_init_scale (&matrix, scale_factor, scale_factor);
|
||||
cairo_matrix_translate (&matrix, x_offset, y_offset);
|
||||
|
||||
cairo_pattern_set_matrix (pattern, &matrix);
|
||||
|
||||
/* If it's opaque, and when scaled, fills up the entire allocated
|
||||
* area, then don't bother doing a background fill first
|
||||
*/
|
||||
if (content != CAIRO_CONTENT_COLOR_ALPHA && width_ratio == height_ratio)
|
||||
*needs_background_fill = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
double x_offset, y_offset;
|
||||
|
||||
if (node->background_position_set)
|
||||
{
|
||||
x_offset = -node->background_position_x;
|
||||
y_offset = -node->background_position_y;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (node->alloc_width > file_width)
|
||||
x_offset = - (node->alloc_width / 2.0 - file_width / 2.0);
|
||||
else
|
||||
x_offset = - (file_width / 2.0 - node->alloc_width / 2.0);
|
||||
|
||||
if (node->alloc_height > file_height)
|
||||
y_offset = - (node->alloc_height / 2.0 - file_height / 2.0);
|
||||
else
|
||||
y_offset = - (file_height / 2.0 - node->alloc_height / 2.0);
|
||||
}
|
||||
|
||||
/* If it's opaque, and when translated, fills up the entire allocated
|
||||
* area, then don't bother doing a background fill first
|
||||
*/
|
||||
if (content != CAIRO_CONTENT_COLOR_ALPHA
|
||||
&& -x_offset <= 0
|
||||
&& -x_offset + file_width >= node->alloc_width
|
||||
&& -y_offset <= 0
|
||||
&& -y_offset + file_height >= node->alloc_height)
|
||||
*needs_background_fill = FALSE;
|
||||
|
||||
cairo_matrix_init_translate (&matrix, x_offset, y_offset);
|
||||
cairo_pattern_set_matrix (pattern, &matrix);
|
||||
}
|
||||
|
||||
return pattern;
|
||||
}
|
||||
|
@@ -3,7 +3,6 @@
|
||||
* st-theme-node-private.h: private structures and functions for StThemeNode
|
||||
*
|
||||
* Copyright 2009, 2010 Red Hat, Inc.
|
||||
* Copyright 2011 Quentin "Sardem FF7" Glidic
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
@@ -25,7 +24,6 @@
|
||||
#include <gdk/gdk.h>
|
||||
|
||||
#include "st-theme-node.h"
|
||||
#include "st-types.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@@ -46,9 +44,6 @@ struct _StThemeNode {
|
||||
int background_position_x;
|
||||
int background_position_y;
|
||||
gboolean background_position_set : 1;
|
||||
StBackgroundSize background_size;
|
||||
gint background_size_w;
|
||||
gint background_size_h;
|
||||
|
||||
ClutterColor foreground_color;
|
||||
ClutterColor border_color[4];
|
||||
|
@@ -7,7 +7,6 @@
|
||||
* Copyright 2009, 2010 Florian Müllner
|
||||
* Copyright 2010 Adel Gadllah
|
||||
* Copyright 2010 Giovanni Campagna
|
||||
* Copyright 2011 Quentin "Sardem FF7" Glidic
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
@@ -91,12 +90,6 @@ st_theme_node_dispose (GObject *gobject)
|
||||
node->border_image = NULL;
|
||||
}
|
||||
|
||||
if (node->icon_colors)
|
||||
{
|
||||
st_icon_colors_unref (node->icon_colors);
|
||||
node->icon_colors = NULL;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (st_theme_node_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
@@ -1580,7 +1573,6 @@ _st_theme_node_ensure_background (StThemeNode *node)
|
||||
node->background_color = TRANSPARENT_COLOR;
|
||||
node->background_gradient_type = ST_GRADIENT_NONE;
|
||||
node->background_position_set = FALSE;
|
||||
node->background_size = ST_BACKGROUND_SIZE_AUTO;
|
||||
|
||||
ensure_properties (node);
|
||||
|
||||
@@ -1608,7 +1600,6 @@ _st_theme_node_ensure_background (StThemeNode *node)
|
||||
g_free (node->background_image);
|
||||
node->background_image = NULL;
|
||||
node->background_position_set = FALSE;
|
||||
node->background_size = ST_BACKGROUND_SIZE_AUTO;
|
||||
|
||||
for (term = decl->value; term; term = term->next)
|
||||
{
|
||||
@@ -1665,44 +1656,6 @@ _st_theme_node_ensure_background (StThemeNode *node)
|
||||
else
|
||||
node->background_position_set = TRUE;
|
||||
}
|
||||
else if (strcmp (property_name, "-size") == 0)
|
||||
{
|
||||
if (decl->value->type == TERM_IDENT)
|
||||
{
|
||||
if (strcmp (decl->value->content.str->stryng->str, "contain") == 0)
|
||||
node->background_size = ST_BACKGROUND_SIZE_CONTAIN;
|
||||
else if (strcmp (decl->value->content.str->stryng->str, "cover") == 0)
|
||||
node->background_size = ST_BACKGROUND_SIZE_COVER;
|
||||
else if ((strcmp (decl->value->content.str->stryng->str, "auto") == 0) && (decl->value->next) && (decl->value->next->type == TERM_NUMBER))
|
||||
{
|
||||
GetFromTermResult result = get_length_from_term_int (node, decl->value->next, FALSE, &node->background_size_h);
|
||||
|
||||
node->background_size_w = -1;
|
||||
node->background_size = (result == VALUE_FOUND) ? ST_BACKGROUND_SIZE_FIXED : ST_BACKGROUND_SIZE_AUTO;
|
||||
}
|
||||
else
|
||||
node->background_size = ST_BACKGROUND_SIZE_AUTO;
|
||||
}
|
||||
else if (decl->value->type == TERM_NUMBER)
|
||||
{
|
||||
GetFromTermResult result = get_length_from_term_int (node, decl->value, FALSE, &node->background_size_w);
|
||||
if (result == VALUE_NOT_FOUND)
|
||||
continue;
|
||||
|
||||
node->background_size = ST_BACKGROUND_SIZE_FIXED;
|
||||
|
||||
if ((decl->value->next) && (decl->value->next->type == TERM_NUMBER))
|
||||
{
|
||||
result = get_length_from_term_int (node, decl->value->next, FALSE, &node->background_size_h);
|
||||
|
||||
if (result == VALUE_FOUND)
|
||||
continue;
|
||||
}
|
||||
node->background_size_h = -1;
|
||||
}
|
||||
else
|
||||
node->background_size = ST_BACKGROUND_SIZE_AUTO;
|
||||
}
|
||||
else if (strcmp (property_name, "-color") == 0)
|
||||
{
|
||||
GetFromTermResult result;
|
||||
|
@@ -49,13 +49,6 @@ typedef enum {
|
||||
ST_ICON_DOCUMENT
|
||||
} StIconType;
|
||||
|
||||
typedef enum {
|
||||
ST_BACKGROUND_SIZE_AUTO,
|
||||
ST_BACKGROUND_SIZE_CONTAIN,
|
||||
ST_BACKGROUND_SIZE_COVER,
|
||||
ST_BACKGROUND_SIZE_FIXED
|
||||
} StBackgroundSize;
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __ST_TYPES_H__ */
|
||||
|
@@ -432,7 +432,7 @@ main (int argc, char **argv)
|
||||
theme = st_theme_new ("st/test-theme.css",
|
||||
NULL, NULL);
|
||||
|
||||
stage = clutter_stage_new ();
|
||||
stage = clutter_stage_get_default ();
|
||||
context = st_theme_context_get_for_stage (CLUTTER_STAGE (stage));
|
||||
st_theme_context_set_theme (context, theme);
|
||||
st_theme_context_set_resolution (context, 96.);
|
||||
|
@@ -36,8 +36,7 @@ int main (int argc, char **argv)
|
||||
clutter_color_from_string (&red, "red");
|
||||
clutter_color_from_string (&green, "green");
|
||||
clutter_color_from_string (&blue, "blue");
|
||||
stage = clutter_stage_new ();
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
stage = clutter_stage_get_default ();
|
||||
|
||||
text = g_object_new (CLUTTER_TYPE_TEXT,
|
||||
"text", "Red",
|
||||
|
@@ -2,7 +2,6 @@ noinst_SCRIPTS = run-test.sh
|
||||
EXTRA_DIST = run-test.sh.in
|
||||
|
||||
TEST_JS = \
|
||||
interactive/background-size.js \
|
||||
interactive/borders.js \
|
||||
interactive/border-radius.js \
|
||||
interactive/border-width.js \
|
||||
@@ -17,14 +16,10 @@ TEST_JS = \
|
||||
interactive/scroll-view-sizing.js \
|
||||
interactive/table.js \
|
||||
interactive/transitions.js \
|
||||
testcommon/100-200.svg \
|
||||
testcommon/200-100.svg \
|
||||
testcommon/200-200.svg \
|
||||
testcommon/border-image.png \
|
||||
testcommon/face-plain.png \
|
||||
testcommon/ui.js \
|
||||
unit/format.js \
|
||||
unit/insertSorted.js \
|
||||
unit/markup.js \
|
||||
unit/jsParse.js \
|
||||
unit/url.js
|
||||
|
@@ -1,89 +0,0 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const St = imports.gi.St;
|
||||
|
||||
const UI = imports.testcommon.ui;
|
||||
|
||||
UI.init();
|
||||
let stage = Clutter.Stage.get_default();
|
||||
stage.width = 1024;
|
||||
stage.height = 768;
|
||||
|
||||
let vbox = new St.BoxLayout({ width: stage.width,
|
||||
height: stage.height,
|
||||
style: 'background: #ffee88;' });
|
||||
stage.add_actor(vbox);
|
||||
|
||||
let scroll = new St.ScrollView();
|
||||
vbox.add(scroll, { expand: true });
|
||||
|
||||
let vbox = new St.BoxLayout({ vertical: true,
|
||||
style: 'padding: 10px;'
|
||||
+ 'spacing: 20px;' });
|
||||
scroll.add_actor(vbox);
|
||||
|
||||
let tbox = null;
|
||||
|
||||
function addTestCase(image, size, backgroundSize) {
|
||||
let obin = new St.Bin({ style: 'border: 3px solid green;' });
|
||||
tbox.add(obin);
|
||||
|
||||
let bin = new St.Bin({ style_class: 'background-image-' + image,
|
||||
width: size.width,
|
||||
height: size.height,
|
||||
style: 'border: 1px solid transparent;'
|
||||
+ 'background-size: ' + backgroundSize + ';',
|
||||
x_fill: true,
|
||||
y_fill: true
|
||||
});
|
||||
obin.set_child(bin);
|
||||
|
||||
bin.set_child(new St.Label({ text: backgroundSize,
|
||||
style: 'font-size: 15px;'
|
||||
+ 'text-align: center;'
|
||||
}));
|
||||
}
|
||||
|
||||
function addTestLine(image, size, backgroundSizes) {
|
||||
vbox.add(new St.Label({ text: image + '.svg / ' + size.width + '×' + size.height,
|
||||
style: 'font-size: 15px;'
|
||||
+ 'text-align: center;'
|
||||
}));
|
||||
|
||||
tbox = new St.BoxLayout({ style: 'spacing: 20px;' });
|
||||
vbox.add(tbox);
|
||||
|
||||
if (backgroundSizes.length == 2)
|
||||
addTestCase(image, size, "auto");
|
||||
for each (let s in backgroundSizes)
|
||||
addTestCase(image, size, s);
|
||||
}
|
||||
|
||||
let size1 = { width: 200, height: 200 }
|
||||
let size2 = { width: 250, height: 250 }
|
||||
let size3 = { width: 100, height: 100 }
|
||||
|
||||
// fixed size
|
||||
addTestLine('200-200', size1, ["200px 200px", "100px 100px", "100px 200px"]);
|
||||
|
||||
// same size
|
||||
addTestLine('200-200', size1, ["contain", "cover"]);
|
||||
// smaller
|
||||
addTestLine('200-200', size2, ["contain", "cover"]);
|
||||
// larger
|
||||
addTestLine('200-200', size3, ["contain", "cover"]);
|
||||
|
||||
|
||||
addTestLine('200-100', size1, ["contain", "cover"]);
|
||||
addTestLine('200-100', size2, ["contain", "cover"]);
|
||||
addTestLine('200-100', size3, ["contain", "cover"]);
|
||||
|
||||
|
||||
addTestLine('100-200', size1, ["contain", "cover"]);
|
||||
addTestLine('100-200', size2, ["contain", "cover"]);
|
||||
addTestLine('100-200', size3, ["contain", "cover"]);
|
||||
|
||||
stage.show();
|
||||
Clutter.main();
|
||||
stage.destroy();
|
@@ -1,21 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 100 200" width="100" height="200">
|
||||
<path
|
||||
d="
|
||||
M 2,2 h 96 v 196 h -96 v -196
|
||||
M 8,8 h 84 v 184 h -84 v -184
|
||||
"
|
||||
fill="white"
|
||||
stroke="blue"
|
||||
stroke-width="2"
|
||||
stroke-linecap="square"
|
||||
/>
|
||||
<path
|
||||
d="
|
||||
M 10,10 h 20 v 20 h -20 v -20
|
||||
"
|
||||
fill="green"
|
||||
/>
|
||||
</svg>
|
Before Width: | Height: | Size: 518 B |
@@ -1,21 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 200 100" width="200" height="100">
|
||||
<path
|
||||
d="
|
||||
M 2,2 h 196 v 96 h -196 v -96
|
||||
M 8,8 h 184 v 84 h -184 v -84
|
||||
"
|
||||
fill="white"
|
||||
stroke="blue"
|
||||
stroke-width="2"
|
||||
stroke-linecap="square"
|
||||
/>
|
||||
<path
|
||||
d="
|
||||
M 10,10 h 20 v 20 h -20 v -20
|
||||
"
|
||||
fill="green"
|
||||
/>
|
||||
</svg>
|
Before Width: | Height: | Size: 518 B |
@@ -1,21 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 200 200" width="200" height="200">
|
||||
<path
|
||||
d="
|
||||
M 2,2 h 196 v 196 h -196 v -196
|
||||
M 8,8 h 184 v 184 h -184 v -184
|
||||
"
|
||||
fill="white"
|
||||
stroke="blue"
|
||||
stroke-width="2"
|
||||
stroke-linecap="square"
|
||||
/>
|
||||
<path
|
||||
d="
|
||||
M 10,10 h 20 v 20 h -20 v -20
|
||||
"
|
||||
fill="green"
|
||||
/>
|
||||
</svg>
|
Before Width: | Height: | Size: 522 B |
@@ -37,18 +37,6 @@ stage {
|
||||
border-image: url('border-image.png') 16;
|
||||
}
|
||||
|
||||
.background-image-200-200 {
|
||||
background-image: url('200-200.svg');
|
||||
}
|
||||
|
||||
.background-image-100-200 {
|
||||
background-image: url('100-200.svg');
|
||||
}
|
||||
|
||||
.background-image-200-100 {
|
||||
background-image: url('200-100.svg');
|
||||
}
|
||||
|
||||
.background-gradient {
|
||||
background-gradient-start: rgba(127, 255, 127, .6);
|
||||
background-gradient-end: rgba(127, 127, 255, .6);
|
||||
|
@@ -1,76 +0,0 @@
|
||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||
|
||||
// Test cases for Util.insertSorted
|
||||
|
||||
const JsUnit = imports.jsUnit;
|
||||
|
||||
// Needed so that Util can bring some UI stuff
|
||||
// we don't actually use
|
||||
const Environment = imports.ui.environment;
|
||||
Environment.init();
|
||||
const Util = imports.misc.util;
|
||||
|
||||
function assertArrayEquals(errorMessage, array1, array2) {
|
||||
JsUnit.assertEquals(errorMessage + ' length',
|
||||
array1.length, array2.length);
|
||||
for (let j = 0; j < array1.length; j++) {
|
||||
JsUnit.assertEquals(errorMessage + ' item ' + j,
|
||||
array1[j], array2[j]);
|
||||
}
|
||||
}
|
||||
|
||||
function cmp(one, two) {
|
||||
return one-two;
|
||||
}
|
||||
|
||||
let arrayInt = [1, 2, 3, 5, 6];
|
||||
Util.insertSorted(arrayInt, 4, cmp);
|
||||
|
||||
assertArrayEquals('first test', [1,2,3,4,5,6], arrayInt);
|
||||
|
||||
// no comparator, integer sorting is implied
|
||||
Util.insertSorted(arrayInt, 3);
|
||||
|
||||
assertArrayEquals('second test', [1,2,3,3,4,5,6], arrayInt);
|
||||
|
||||
let obj1 = { a: 1 };
|
||||
let obj2 = { a: 2, b: 0 };
|
||||
let obj3 = { a: 2, b: 1 };
|
||||
let obj4 = { a: 3 };
|
||||
|
||||
function objCmp(one, two) {
|
||||
return one.a - two.a;
|
||||
}
|
||||
|
||||
let arrayObj = [obj1, obj3, obj4];
|
||||
|
||||
// obj2 compares equivalent to obj3, should be
|
||||
// inserted before
|
||||
Util.insertSorted(arrayObj, obj2, objCmp);
|
||||
|
||||
assertArrayEquals('object test', [obj1, obj2, obj3, obj4], arrayObj);
|
||||
|
||||
function checkedCmp(one, two) {
|
||||
if (typeof one != 'number' ||
|
||||
typeof two != 'number')
|
||||
throw new TypeError('Invalid type passed to checkedCmp');
|
||||
|
||||
return one-two;
|
||||
}
|
||||
|
||||
let arrayEmpty = [];
|
||||
|
||||
// check that no comparisons are made when
|
||||
// inserting in a empty array
|
||||
Util.insertSorted(arrayEmpty, 3, checkedCmp);
|
||||
|
||||
// Insert at the end and check that we don't
|
||||
// access past it
|
||||
Util.insertSorted(arrayEmpty, 4, checkedCmp);
|
||||
Util.insertSorted(arrayEmpty, 5, checkedCmp);
|
||||
|
||||
// Some more insertions
|
||||
Util.insertSorted(arrayEmpty, 2, checkedCmp);
|
||||
Util.insertSorted(arrayEmpty, 1, checkedCmp);
|
||||
|
||||
assertArrayEquals('checkedCmp test', [1, 2, 3, 4, 5], arrayEmpty);
|
Reference in New Issue
Block a user