Compare commits
33 Commits
wip/gdbus-
...
wip/re-sea
Author | SHA1 | Date | |
---|---|---|---|
555d45f06c | |||
0a8713770b | |||
7d3ea1ac68 | |||
7785710964 | |||
3730dc01cf | |||
66bf0df737 | |||
4590b33f2e | |||
6538f60322 | |||
4b0ba8b7b8 | |||
bc8965fe63 | |||
e7fcce3484 | |||
b1e4d3335c | |||
a3a3f24ed3 | |||
96191a9c96 | |||
f4814d200b | |||
52156930d3 | |||
cbaa999ced | |||
9491f6bd23 | |||
afe8198d4b | |||
6aa8f14285 | |||
e073670c4d | |||
17a3d2c63f | |||
ca38e05ed4 | |||
9841e56ebf | |||
c0d3a14ac2 | |||
d485fcf9ec | |||
ce2c5106f8 | |||
5e96c3dfb4 | |||
a72b642f3e | |||
8507d3c4e4 | |||
c985fdccba | |||
1d7c2b1c26 | |||
ab60c628e7 |
@ -113,9 +113,13 @@
|
||||
<doc:summary>
|
||||
<doc:para>
|
||||
A dictionary describing the given search result, containing
|
||||
'id', 'name' (both strings) and either 'icon' (a serialized
|
||||
GIcon) or 'icon-data' (raw image data as (iiibiiay) - width,
|
||||
height, rowstride, has-alpha, bits per sample, channels, data)
|
||||
'id' and 'name' (both strings). Optionally, either 'gicon' (a
|
||||
serialized GIcon) or 'icon-data' (raw image data as (iiibiiay)
|
||||
- width, height, rowstride, has-alpha, bits per sample,
|
||||
channels, data) can be specified if the result can be better
|
||||
served with a thumbnail of the content (such as with images).
|
||||
A 'description' field (string) may also be specified if more
|
||||
context would help the user find the desired result.
|
||||
</doc:para>
|
||||
</doc:summary>
|
||||
</doc:doc>
|
||||
@ -143,5 +147,25 @@
|
||||
</doc:doc>
|
||||
</arg>
|
||||
</method>
|
||||
|
||||
<method name="LaunchSearch">
|
||||
<doc:doc>
|
||||
<doc:description>
|
||||
<doc:para>
|
||||
Called when the user clicks on the provider icon. The provider
|
||||
application should open and run the active search term itself.
|
||||
</doc:para>
|
||||
</doc:description>
|
||||
</doc:doc>
|
||||
<arg type="as" direction="in">
|
||||
<doc:doc>
|
||||
<doc:summary>
|
||||
<doc:para>
|
||||
The current search term(s).
|
||||
</doc:para>
|
||||
</doc:summary>
|
||||
</doc:doc>
|
||||
</arg>
|
||||
</method>
|
||||
</interface>
|
||||
</node>
|
||||
|
@ -577,6 +577,10 @@ StScrollBar StButton#vhandle:active {
|
||||
spacing: 40px;
|
||||
}
|
||||
|
||||
#overview-group {
|
||||
spacing: 12px;
|
||||
}
|
||||
|
||||
.window-caption {
|
||||
spacing: 25px;
|
||||
}
|
||||
@ -711,7 +715,7 @@ StScrollBar StButton#vhandle:active {
|
||||
|
||||
#searchResultsContent {
|
||||
padding-right: 20px;
|
||||
spacing: 36px;
|
||||
spacing: 16px;
|
||||
}
|
||||
|
||||
#searchResultsContent:rtl {
|
||||
@ -719,6 +723,25 @@ StScrollBar StButton#vhandle:active {
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.search-section {
|
||||
/* This should be equal to #searchResultsContent spacing */
|
||||
spacing: 16px;
|
||||
}
|
||||
|
||||
.search-section-separator {
|
||||
-gradient-height: 1px;
|
||||
-gradient-start: rgba(255,255,255,0);
|
||||
-gradient-end: rgba(255,255,255,0.5);
|
||||
-margin-horizontal: 1.5em;
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
.search-section-content {
|
||||
/* This is the space between the provider icon and the results container */
|
||||
spacing: 25px;
|
||||
}
|
||||
|
||||
.search-statustext,
|
||||
.search-section-header {
|
||||
padding: 4px 12px;
|
||||
spacing: 4px;
|
||||
@ -744,6 +767,14 @@ StScrollBar StButton#vhandle:active {
|
||||
spacing: 4px;
|
||||
}
|
||||
|
||||
.search-providers-box {
|
||||
spacing: 12px;
|
||||
}
|
||||
|
||||
.results-list {
|
||||
spacing: 5px;
|
||||
}
|
||||
|
||||
/* Text labels are an odd number of pixels tall. The uneven top and bottom
|
||||
* padding compensates for this and ensures that the label is vertically
|
||||
* centered */
|
||||
@ -824,7 +855,10 @@ StScrollBar StButton#vhandle:active {
|
||||
|
||||
.app-well-app > .overview-icon,
|
||||
.show-apps > .overview-icon,
|
||||
.search-result-content > .overview-icon {
|
||||
.remove-favorite > .overview-icon,
|
||||
.search-section-icon-bin,
|
||||
.search-result,
|
||||
.grid-search-result-content > .overview-icon {
|
||||
border-radius: 4px;
|
||||
padding: 3px;
|
||||
border: 1px rgba(0,0,0,0);
|
||||
@ -840,7 +874,10 @@ StScrollBar StButton#vhandle:active {
|
||||
|
||||
.app-well-app:hover > .overview-icon,
|
||||
.show-apps:hover > .overview-icon,
|
||||
.search-result-content:hover > .overview-icon {
|
||||
.remove-favorite:hover > .overview-icon,
|
||||
.search-section-icon-bin:hover,
|
||||
.search-result:hover,
|
||||
.grid-search-result-content:hover > .overview-icon {
|
||||
background-color: rgba(255,255,255,0.1);
|
||||
text-shadow: black 0px 2px 2px;
|
||||
transition-duration: 100;
|
||||
@ -875,13 +912,39 @@ StScrollBar StButton#vhandle:active {
|
||||
}
|
||||
|
||||
.app-well-app:focus > .overview-icon,
|
||||
.search-result-content:focus > .overview-icon,
|
||||
.show-apps:focus > .overview-icon,
|
||||
.search-section-icon-bin:focus,
|
||||
.search-result:focus,
|
||||
.grid-search-result-content:focus > .overview-icon,
|
||||
.app-well-app:selected > .overview-icon,
|
||||
.search-result-content:selected > .overview-icon {
|
||||
.search-section-icon-bin:selected,
|
||||
.search-result:selected,
|
||||
.grid-search-result-content:selected > .overview-icon {
|
||||
background-color: rgba(255,255,255,0.33);
|
||||
}
|
||||
|
||||
/* List Results */
|
||||
|
||||
.search-result {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.search-result-content {
|
||||
spacing: 12px;
|
||||
}
|
||||
|
||||
.search-result-details {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.search-result-details-title {
|
||||
font-size: 16pt;
|
||||
}
|
||||
|
||||
.search-result-details-description {
|
||||
font-size: 14pt;
|
||||
}
|
||||
|
||||
/* LookingGlass */
|
||||
|
||||
#LookingGlassDialog {
|
||||
|
@ -41,6 +41,7 @@ nobase_dist_js_DATA = \
|
||||
ui/boxpointer.js \
|
||||
ui/calendar.js \
|
||||
ui/checkBox.js \
|
||||
ui/centerLayout.js \
|
||||
ui/ctrlAltTab.js \
|
||||
ui/dash.js \
|
||||
ui/dateMenu.js \
|
||||
|
@ -21,16 +21,7 @@ const GnomeShellIface = <interface name="org.gnome.Shell.Extensions">
|
||||
</signal>
|
||||
</interface>;
|
||||
|
||||
const GnomeShellProxy = new Gio.DBusProxyClass({
|
||||
Name: 'GnomeShellProxy',
|
||||
Interface: GnomeShellIface,
|
||||
|
||||
_init: function() {
|
||||
this.parent({ g_bus_type: Gio.BusType.SESSION,
|
||||
g_name: 'org.gnome.Shell',
|
||||
g_object_path: '/org/gnome/Shell' });
|
||||
}
|
||||
});
|
||||
const GnomeShellProxy = Gio.DBusProxy.makeProxyWrapper(GnomeShellIface);
|
||||
|
||||
function stripPrefix(string, prefix) {
|
||||
if (string.slice(0, prefix.length) == prefix)
|
||||
@ -200,8 +191,7 @@ const Application = new Lang.Class({
|
||||
|
||||
this._extensionPrefsBin.add(label);
|
||||
|
||||
this._shellProxy = new GnomeShellProxy();
|
||||
this._shellProxy.init(null);
|
||||
this._shellProxy = new GnomeShellProxy(Gio.DBus.session, 'org.gnome.Shell', '/org/gnome/Shell');
|
||||
this._shellProxy.connectSignal('ExtensionStatusChanged', Lang.bind(this, function(proxy, senderName, [uuid, state, error]) {
|
||||
if (ExtensionUtils.extensions[uuid] !== undefined)
|
||||
this._scanExtensions();
|
||||
|
@ -11,14 +11,16 @@ const FprintManagerIface = <interface name='net.reactivated.Fprint.Manager'>
|
||||
</method>
|
||||
</interface>;
|
||||
|
||||
const FprintManager = new Gio.DBusProxyClass({
|
||||
Name: 'FprintManager',
|
||||
Interface: FprintManagerIface,
|
||||
const FprintManagerInfo = Gio.DBusInterfaceInfo.new_for_xml(FprintManagerIface);
|
||||
|
||||
_init: function() {
|
||||
this.parent({ g_bus_type: Gio.BusType.SYSTEM,
|
||||
g_name: 'net.reactivated.Fprint',
|
||||
g_object_path: '/net/reactivated/Fprint/Manager',
|
||||
g_flags: (Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES) });
|
||||
}
|
||||
});
|
||||
function FprintManager() {
|
||||
var self = new Gio.DBusProxy({ g_connection: Gio.DBus.system,
|
||||
g_interface_name: FprintManagerInfo.name,
|
||||
g_interface_info: FprintManagerInfo,
|
||||
g_name: 'net.reactivated.Fprint',
|
||||
g_object_path: '/net/reactivated/Fprint/Manager',
|
||||
g_flags: (Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES) });
|
||||
|
||||
self.init(null);
|
||||
return self;
|
||||
}
|
||||
|
@ -1089,7 +1089,7 @@ const LoginDialog = new Lang.Class({
|
||||
}));
|
||||
},
|
||||
|
||||
_onNotListedClicked: function() {
|
||||
_onNotListedClicked: function(user) {
|
||||
let tasks = [function() {
|
||||
return this._userList.hideItems();
|
||||
},
|
||||
|
@ -35,13 +35,7 @@ const PowerMenuButton = new Lang.Class({
|
||||
/* Translators: accessible name of the power menu in the login screen */
|
||||
this.parent('system-shutdown-symbolic', _("Power"));
|
||||
|
||||
LoginManager.getLoginManager(Lang.bind(this, function(manager) {
|
||||
this._loginManager = manager;
|
||||
|
||||
this._updateHaveShutdown();
|
||||
this._updateHaveRestart();
|
||||
this._updateHaveSuspend();
|
||||
}));
|
||||
this._loginManager = LoginManager.getLoginManager();
|
||||
|
||||
this._settings = new Gio.Settings({ schema: GdmUtil.LOGIN_SCREEN_SCHEMA });
|
||||
this._settings.connect('changed::disable-restart-buttons',
|
||||
@ -70,12 +64,6 @@ const PowerMenuButton = new Lang.Class({
|
||||
},
|
||||
|
||||
_updateHaveShutdown: function() {
|
||||
if (!this._loginManager) {
|
||||
this._haveShutdown = false;
|
||||
this._powerOffItem.actor.visible = false;
|
||||
return;
|
||||
}
|
||||
|
||||
this._loginManager.canPowerOff(Lang.bind(this, function(result) {
|
||||
this._haveShutdown = result;
|
||||
this._powerOffItem.actor.visible = this._haveShutdown;
|
||||
@ -84,12 +72,6 @@ const PowerMenuButton = new Lang.Class({
|
||||
},
|
||||
|
||||
_updateHaveRestart: function() {
|
||||
if (!this._loginManager) {
|
||||
this._haveRestart = false;
|
||||
this._restartItem.actor.visible = false;
|
||||
return;
|
||||
}
|
||||
|
||||
this._loginManager.canReboot(Lang.bind(this, function(result) {
|
||||
this._haveRestart = result;
|
||||
this._restartItem.actor.visible = this._haveRestart;
|
||||
@ -98,12 +80,6 @@ const PowerMenuButton = new Lang.Class({
|
||||
},
|
||||
|
||||
_updateHaveSuspend: function() {
|
||||
if (!this._loginManager) {
|
||||
this._haveSuspend = false;
|
||||
this._suspendItem.actor.visible = false;
|
||||
return;
|
||||
}
|
||||
|
||||
this._loginManager.canSuspend(Lang.bind(this, function(result) {
|
||||
this._haveSuspend = result;
|
||||
this._suspendItem.actor.visible = this._haveSuspend;
|
||||
|
@ -1,7 +1,6 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Lang = imports.lang;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Signals = imports.signals;
|
||||
@ -17,16 +16,7 @@ const ProviderIface = <interface name='org.freedesktop.realmd.Provider'>
|
||||
<arg name="realm" type="ao" direction="out"/>
|
||||
</method>
|
||||
</interface>;
|
||||
const Provider = new Gio.DBusProxyClass({
|
||||
Name: 'RealmdProvider',
|
||||
Interface: ProviderIface,
|
||||
|
||||
_init: function() {
|
||||
this.parent({ g_bus_type: Gio.BusType.SYSTEM,
|
||||
g_name: 'org.freedesktop.realmd',
|
||||
g_object_path: '/org/freedesktop/realmd' });
|
||||
}
|
||||
});
|
||||
const Provider = Gio.DBusProxy.makeProxyWrapper(ProviderIface);
|
||||
|
||||
const ServiceIface = <interface name="org.freedesktop.realmd.Service">
|
||||
<method name="Cancel">
|
||||
@ -41,16 +31,7 @@ const ServiceIface = <interface name="org.freedesktop.realmd.Service">
|
||||
<arg name="operation" type="s"/>
|
||||
</signal>
|
||||
</interface>;
|
||||
const Service = new Gio.DBusProxyClass({
|
||||
Name: 'RealmdService',
|
||||
Interface: ServiceIface,
|
||||
|
||||
_init: function(service) {
|
||||
this.parent({ g_bus_type: Gio.BusType.SYSTEM,
|
||||
g_name: 'org.freedesktop.realmd',
|
||||
g_object_path: service });
|
||||
}
|
||||
});
|
||||
const Service = Gio.DBusProxy.makeProxyWrapper(ServiceIface);
|
||||
|
||||
const RealmIface = <interface name="org.freedesktop.realmd.Realm">
|
||||
<property name="Name" type="s" access="read"/>
|
||||
@ -70,22 +51,16 @@ const RealmIface = <interface name="org.freedesktop.realmd.Realm">
|
||||
<arg name="options" type="a{sv}" direction="in"/>
|
||||
</method>
|
||||
</interface>;
|
||||
const Realm = new Gio.DBusProxyClass({
|
||||
Name: 'RealmdRealm',
|
||||
Interface: RealmIface,
|
||||
|
||||
_init: function(realm) {
|
||||
this.parent({ g_bus_type: Gio.BusType.SYSTEM,
|
||||
g_name: 'org.freedesktop.realmd',
|
||||
g_object_path: realm });
|
||||
}
|
||||
});
|
||||
const Realm = Gio.DBusProxy.makeProxyWrapper(RealmIface);
|
||||
|
||||
const Manager = new Lang.Class({
|
||||
Name: 'Manager',
|
||||
|
||||
_init: function(parentActor) {
|
||||
this._aggregateProvider = new Provider();
|
||||
this._aggregateProvider = Provider(Gio.DBus.system,
|
||||
'org.freedesktop.realmd',
|
||||
'/org/freedesktop/realmd',
|
||||
Lang.bind(this, this._reloadRealms))
|
||||
this._realms = {};
|
||||
|
||||
this._aggregateProvider.connect('g-properties-changed',
|
||||
@ -93,16 +68,6 @@ const Manager = new Lang.Class({
|
||||
if ('Realms' in properties.deep_unpack())
|
||||
this._reloadRealms();
|
||||
}));
|
||||
|
||||
this._aggregateProvider.init_async(GLib.PRIORITY_DEFAULT, null, Lang.bind(this, function(proxy, result) {
|
||||
try {
|
||||
proxy.init_finish(result);
|
||||
} catch(e) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._reloadRealms();
|
||||
}));
|
||||
},
|
||||
|
||||
_reloadRealms: function() {
|
||||
@ -112,8 +77,10 @@ const Manager = new Lang.Class({
|
||||
return;
|
||||
|
||||
for (let i = 0; i < realmPaths.length; i++) {
|
||||
let realm = new Realm(realmPaths[i]);
|
||||
realm.init_async(GLib.PRIORITY_DEFAULT, null, Lang.bind(this, this._onRealmLoaded));
|
||||
let realm = Realm(Gio.DBus.system,
|
||||
'org.freedesktop.realmd',
|
||||
realmPaths[i],
|
||||
Lang.bind(this, this._onRealmLoaded));
|
||||
}
|
||||
},
|
||||
|
||||
@ -130,10 +97,9 @@ const Manager = new Lang.Class({
|
||||
this._updateLoginFormat();
|
||||
},
|
||||
|
||||
_onRealmLoaded: function(realm, result) {
|
||||
try {
|
||||
realm.init_finish(result);
|
||||
} catch(e) { return; }
|
||||
_onRealmLoaded: function(realm, error) {
|
||||
if (error)
|
||||
return;
|
||||
|
||||
this._reloadRealm(realm);
|
||||
|
||||
|
@ -82,8 +82,6 @@ const ShellUserVerifier = new Lang.Class({
|
||||
this._settings = new Gio.Settings({ schema: LOGIN_SCREEN_SCHEMA });
|
||||
|
||||
this._fprintManager = new Fprint.FprintManager();
|
||||
this._fprintManager.init(null);
|
||||
|
||||
this._realmManager = new Realmd.Manager();
|
||||
|
||||
this._failCounter = 0;
|
||||
@ -139,14 +137,11 @@ const ShellUserVerifier = new Lang.Class({
|
||||
if (!this._settings.get_boolean(FINGERPRINT_AUTHENTICATION_KEY))
|
||||
return;
|
||||
|
||||
this._fprintManager.GetDefaultDeviceRemote(this._cancellable, Lang.bind(this, function(manager, result) {
|
||||
try {
|
||||
let device = manager.GetDefaultDeviceFinish(result);
|
||||
this._haveFingerprintReader = !!device;
|
||||
} catch(e) {
|
||||
this._haveFingerprintReader = false;
|
||||
}
|
||||
}));
|
||||
this._fprintManager.GetDefaultDeviceRemote(Gio.DBusCallFlags.NONE, this._cancellable, Lang.bind(this,
|
||||
function(device, error) {
|
||||
if (!error && device)
|
||||
this._haveFingerprintReader = true;
|
||||
}));
|
||||
},
|
||||
|
||||
_reportInitError: function(where, error) {
|
||||
|
@ -21,16 +21,11 @@ const PresenceStatus = {
|
||||
IDLE: 3
|
||||
};
|
||||
|
||||
const Presence = new Gio.DBusProxyClass({
|
||||
Name: 'GnomeSessionPresence',
|
||||
Interface: PresenceIface,
|
||||
|
||||
_init: function() {
|
||||
this.parent({ g_bus_type: Gio.BusType.SESSION,
|
||||
g_name: 'org.gnome.SessionManager',
|
||||
g_object_path: '/org/gnome/SessionManager/Presence' });
|
||||
}
|
||||
});
|
||||
var PresenceProxy = Gio.DBusProxy.makeProxyWrapper(PresenceIface);
|
||||
function Presence(initCallback, cancellable) {
|
||||
return new PresenceProxy(Gio.DBus.session, 'org.gnome.SessionManager',
|
||||
'/org/gnome/SessionManager/Presence', initCallback, cancellable);
|
||||
}
|
||||
|
||||
// Note inhibitors are immutable objects, so they don't
|
||||
// change at runtime (changes always come in the form
|
||||
@ -44,16 +39,10 @@ const InhibitorIface = <interface name="org.gnome.SessionManager.Inhibitor">
|
||||
</method>
|
||||
</interface>;
|
||||
|
||||
const Inhibitor = new Gio.DBusProxyClass({
|
||||
Name: 'GnomeSessionInhibitor',
|
||||
Interface: InhibitorIface,
|
||||
|
||||
_init: function(inhibitor) {
|
||||
this.parent({ g_bus_type: Gio.BusType.SESSION,
|
||||
g_name: 'org.gnome.SessionManager',
|
||||
g_object_path: inhibitor });
|
||||
}
|
||||
});
|
||||
var InhibitorProxy = Gio.DBusProxy.makeProxyWrapper(InhibitorIface);
|
||||
function Inhibitor(objectPath, initCallback, cancellable) {
|
||||
return new InhibitorProxy(Gio.DBus.session, 'org.gnome.SessionManager', objectPath, initCallback, cancellable);
|
||||
}
|
||||
|
||||
// Not the full interface, only the methods we use
|
||||
const SessionManagerIface = <interface name="org.gnome.SessionManager">
|
||||
@ -77,14 +66,7 @@ const SessionManagerIface = <interface name="org.gnome.SessionManager">
|
||||
</signal>
|
||||
</interface>;
|
||||
|
||||
const SessionManager = new Gio.DBusProxyClass({
|
||||
Name: 'GnomeSessionManager',
|
||||
Interface: SessionManagerIface,
|
||||
|
||||
_init: function() {
|
||||
this.parent({ g_bus_type: Gio.BusType.SESSION,
|
||||
g_name: 'org.gnome.SessionManager',
|
||||
g_object_path: '/org/gnome/SessionManager' });
|
||||
},
|
||||
});
|
||||
|
||||
var SessionManagerProxy = Gio.DBusProxy.makeProxyWrapper(SessionManagerIface);
|
||||
function SessionManager(initCallback, cancellable) {
|
||||
return new SessionManagerProxy(Gio.DBus.session, 'org.gnome.SessionManager', '/org/gnome/SessionManager', initCallback, cancellable);
|
||||
}
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
const GLib = imports.gi.GLib;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GObject = imports.gi.GObject;
|
||||
const Lang = imports.lang;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Shell = imports.gi.Shell;
|
||||
@ -34,26 +33,8 @@ const SystemdLoginSessionIface = <interface name='org.freedesktop.login1.Session
|
||||
<signal name='Unlock' />
|
||||
</interface>;
|
||||
|
||||
const SystemdLoginManager = new Gio.DBusProxyClass({
|
||||
Name: 'SystemdLoginManager',
|
||||
Interface: SystemdLoginManagerIface,
|
||||
|
||||
_init: function() {
|
||||
this.parent({ g_bus_type: Gio.BusType.SYSTEM,
|
||||
g_name: 'org.freedesktop.login1',
|
||||
g_object_path: '/org/freedesktop/login1' });
|
||||
}
|
||||
});
|
||||
const SystemdLoginSession = new Gio.DBusProxyClass({
|
||||
Name: 'SystemdLoginSession',
|
||||
Interface: SystemdLoginSessionIface,
|
||||
|
||||
_init: function(session) {
|
||||
this.parent({ g_bus_type: Gio.BusType.SYSTEM,
|
||||
g_name: 'org.freedesktop.login1',
|
||||
g_object_path: session });
|
||||
}
|
||||
});
|
||||
const SystemdLoginManager = Gio.DBusProxy.makeProxyWrapper(SystemdLoginManagerIface);
|
||||
const SystemdLoginSession = Gio.DBusProxy.makeProxyWrapper(SystemdLoginSessionIface);
|
||||
|
||||
const ConsoleKitManagerIface = <interface name='org.freedesktop.ConsoleKit.Manager'>
|
||||
<method name='CanRestart'>
|
||||
@ -80,128 +61,51 @@ const ConsoleKitSessionIface = <interface name='org.freedesktop.ConsoleKit.Sessi
|
||||
<signal name='Unlock' />
|
||||
</interface>;
|
||||
|
||||
const ConsoleKitSession = new Gio.DBusProxyClass({
|
||||
Name: 'ConsoleKitSession',
|
||||
Interface: ConsoleKitSessionIface,
|
||||
|
||||
_init: function(session) {
|
||||
this.parent({ g_bus_type: Gio.BusType.SYSTEM,
|
||||
g_name: 'org.freedesktop.ConsoleKit',
|
||||
g_object_path: session });
|
||||
}
|
||||
});
|
||||
const ConsoleKitManager = new Gio.DBusProxyClass({
|
||||
Name: 'ConsoleKitManager',
|
||||
Interface: ConsoleKitManagerIface,
|
||||
|
||||
_init: function() {
|
||||
this.parent({ g_bus_type: Gio.BusType.SYSTEM,
|
||||
g_name: 'org.freedesktop.ConsoleKit',
|
||||
g_object_path: '/org/freedesktop/ConsoleKit/Manager' });
|
||||
}
|
||||
});
|
||||
const ConsoleKitSession = Gio.DBusProxy.makeProxyWrapper(ConsoleKitSessionIface);
|
||||
const ConsoleKitManager = Gio.DBusProxy.makeProxyWrapper(ConsoleKitManagerIface);
|
||||
|
||||
function haveSystemd() {
|
||||
return GLib.access("/sys/fs/cgroup/systemd", 0) >= 0;
|
||||
}
|
||||
|
||||
let _loginManager = null;
|
||||
let _pendingAsyncCallbacks = [];
|
||||
|
||||
/**
|
||||
* LoginManager:
|
||||
* An abstraction over systemd/logind and ConsoleKit.
|
||||
*
|
||||
*/
|
||||
function getLoginManager(asyncCallback) {
|
||||
function getLoginManager() {
|
||||
if (_loginManager == null) {
|
||||
if (_pendingAsyncCallbacks.length == 0) {
|
||||
let manager;
|
||||
|
||||
if (haveSystemd())
|
||||
manager = new LoginManagerSystemd();
|
||||
else
|
||||
manager = new LoginManagerConsoleKit();
|
||||
|
||||
manager.initAsync(null, function(obj, result) {
|
||||
obj.initFinish(result);
|
||||
|
||||
_loginManager = manager;
|
||||
|
||||
_pendingAsyncCallbacks.forEach(function (f) { f(obj) });
|
||||
_pendingAsyncCallbacks = [];
|
||||
});
|
||||
|
||||
_pendingAsyncCallbacks = [asyncCallback];
|
||||
} else {
|
||||
_pendingAsyncCallbacks.push(asyncCallback);
|
||||
}
|
||||
} else {
|
||||
GLib.idle_add(GLib.PRIORITY_DEFAULT, function() {
|
||||
asyncCallback(_loginManager);
|
||||
});
|
||||
if (haveSystemd())
|
||||
_loginManager = new LoginManagerSystemd();
|
||||
else
|
||||
_loginManager = new LoginManagerConsoleKit();
|
||||
}
|
||||
|
||||
return _loginManager;
|
||||
}
|
||||
|
||||
const LoginManagerSystemd = new Lang.Class({
|
||||
Name: 'LoginManagerSystemd',
|
||||
Extends: GObject.Object,
|
||||
|
||||
_init: function() {
|
||||
this.parent();
|
||||
|
||||
this._proxy = new SystemdLoginManager();
|
||||
},
|
||||
|
||||
initAsync: function(cancellable, asyncCallback) {
|
||||
let simpleResult = Gio.SimpleAsyncResult.new(this, asyncCallback, null);
|
||||
simpleResult.set_check_cancellable(cancellable);
|
||||
|
||||
this._proxy.init_async(GLib.PRIORITY_DEFAULT, cancellable, Lang.bind(this, function(proxy, result) {
|
||||
try {
|
||||
proxy.init_finish(result);
|
||||
|
||||
if (cancellable && cancellable.is_cancelled())
|
||||
return;
|
||||
|
||||
this._fetchCurrentSession(cancellable, simpleResult);
|
||||
} catch(e if e instanceof GLib.Error) {
|
||||
simpleResult.set_from_error(e);
|
||||
simpleResult.complete();
|
||||
}
|
||||
}));
|
||||
},
|
||||
|
||||
initFinish: function(simpleResult) {
|
||||
if (!simpleResult.propagate_error())
|
||||
return simpleResult.get_op_res_gboolean();
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
_fetchCurrentSession: function(cancellable, simpleResult) {
|
||||
this._currentSession = new SystemdLoginSession('/org/freedesktop/login1/session/' +
|
||||
GLib.getenv('XDG_SESSION_ID'));
|
||||
|
||||
this._currentSession.init_async(GLib.PRIORITY_DEFAULT, cancellable, Lang.bind(this, function(proxy, result) {
|
||||
try {
|
||||
proxy.init_finish(result);
|
||||
|
||||
simpleResult.set_op_res_gboolean(true);
|
||||
} catch(e if e instanceof GLib.Error) {
|
||||
simpleResult.set_from_error(e);
|
||||
}
|
||||
|
||||
simpleResult.complete();
|
||||
}));
|
||||
this._proxy = new SystemdLoginManager(Gio.DBus.system,
|
||||
'org.freedesktop.login1',
|
||||
'/org/freedesktop/login1');
|
||||
},
|
||||
|
||||
// Having this function is a bit of a hack since the Systemd and ConsoleKit
|
||||
// session objects have different interfaces - but in both cases there are
|
||||
// Lock/Unlock signals, and that's all we count upon at the moment.
|
||||
//
|
||||
// This is only valid after async initialization
|
||||
getCurrentSessionProxy: function() {
|
||||
if (!this._currentSession) {
|
||||
this._currentSession = new SystemdLoginSession(Gio.DBus.system,
|
||||
'org.freedesktop.login1',
|
||||
'/org/freedesktop/login1/session/' +
|
||||
GLib.getenv('XDG_SESSION_ID'));
|
||||
}
|
||||
|
||||
return this._currentSession;
|
||||
},
|
||||
|
||||
@ -210,126 +114,66 @@ const LoginManagerSystemd = new Lang.Class({
|
||||
},
|
||||
|
||||
canPowerOff: function(asyncCallback) {
|
||||
this._proxy.CanPowerOffRemote(null, function(proxy, result) {
|
||||
let val = false;
|
||||
|
||||
try {
|
||||
val = proxy.CanPowerOffFinish(result)[0] != 'no';
|
||||
} catch(e) { }
|
||||
|
||||
asyncCallback(val);
|
||||
this._proxy.CanPowerOffRemote(function(result, error) {
|
||||
if (error)
|
||||
asyncCallback(false);
|
||||
else
|
||||
asyncCallback(result[0] != 'no');
|
||||
});
|
||||
},
|
||||
|
||||
canReboot: function(asyncCallback) {
|
||||
this._proxy.CanRebootRemote(null, function(proxy, result) {
|
||||
let val = false;
|
||||
|
||||
try {
|
||||
val = proxy.CanRebootFinish(result)[0] != 'no';
|
||||
} catch(e) { }
|
||||
|
||||
asyncCallback(val);
|
||||
this._proxy.CanRebootRemote(function(result, error) {
|
||||
if (error)
|
||||
asyncCallback(false);
|
||||
else
|
||||
asyncCallback(result[0] != 'no');
|
||||
});
|
||||
},
|
||||
|
||||
canSuspend: function(asyncCallback) {
|
||||
this._proxy.CanSuspendRemote(null, function(proxy, result) {
|
||||
let val = false;
|
||||
|
||||
try {
|
||||
val = proxy.CanRebootFinish(result)[0] != 'no';
|
||||
} catch(e) { }
|
||||
|
||||
asyncCallback(val);
|
||||
this._proxy.CanSuspendRemote(function(result, error) {
|
||||
if (error)
|
||||
asyncCallback(false);
|
||||
else
|
||||
asyncCallback(result[0] != 'no');
|
||||
});
|
||||
},
|
||||
|
||||
powerOff: function() {
|
||||
this._proxy.PowerOffRemote(true, null, null);
|
||||
this._proxy.PowerOffRemote(true);
|
||||
},
|
||||
|
||||
reboot: function() {
|
||||
this._proxy.RebootRemote(true, null, null);
|
||||
this._proxy.RebootRemote(true);
|
||||
},
|
||||
|
||||
suspend: function() {
|
||||
this._proxy.SuspendRemote(true, null, null);
|
||||
this._proxy.SuspendRemote(true);
|
||||
}
|
||||
});
|
||||
|
||||
const LoginManagerConsoleKit = new Lang.Class({
|
||||
Name: 'LoginManagerConsoleKit',
|
||||
Extends: GObject.Object,
|
||||
|
||||
_init: function() {
|
||||
this.parent();
|
||||
|
||||
this._proxy = new ConsoleKitManager();
|
||||
this._proxy = new ConsoleKitManager(Gio.DBus.system,
|
||||
'org.freedesktop.ConsoleKit',
|
||||
'/org/freedesktop/ConsoleKit/Manager');
|
||||
this._upClient = new UPowerGlib.Client();
|
||||
},
|
||||
|
||||
initAsync: function(cancellable, asyncCallback) {
|
||||
let simpleResult = Gio.SimpleAsyncResult.new(this, asyncCallback, null);
|
||||
simpleResult.set_check_cancellable(cancellable);
|
||||
|
||||
this._proxy.init_async(GLib.PRIORITY_DEFAULT, cancellable, Lang.bind(this, function(proxy, result) {
|
||||
try {
|
||||
proxy.init_finish(result);
|
||||
|
||||
if (cancellable && cancellable.is_cancelled())
|
||||
return;
|
||||
|
||||
this._fetchCurrentSession(cancellable, simpleResult);
|
||||
} catch(e if e instanceof GLib.Error) {
|
||||
simpleResult.set_from_error(e);
|
||||
simpleResult.complete();
|
||||
}
|
||||
}));
|
||||
},
|
||||
|
||||
initFinish: function(simpleResult) {
|
||||
if (!simpleResult.propagate_error())
|
||||
return simpleResult.get_op_res_gboolean();
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
_fetchCurrentSession: function(cancellable, simpleResult) {
|
||||
this._proxy.GetCurrentSessionRemote(cancellable, Lang.bind(this, function(proxy, result) {
|
||||
try {
|
||||
let [currentSessionId] = proxy.GetCurrentSessionFinish(result);
|
||||
|
||||
if (cancellable && cancellable.is_cancelled())
|
||||
return;
|
||||
|
||||
this._createSessionProxy(currentSessionId, cancellable, simpleResult);
|
||||
} catch(e if e instanceof GLib.Error) {
|
||||
simpleResult.set_from_error(e);
|
||||
simpleResult.complete();
|
||||
}
|
||||
}));
|
||||
},
|
||||
|
||||
_createSessionProxy: function(currentSessionId, cancellable, simpleResult) {
|
||||
this._currentSession = new ConsoleKitSession(currentSessionId);
|
||||
this._currentSession.init_async(GLib.PRIORITY_DEFAULT, cancellable, Lang.bind(this, function(proxy, result) {
|
||||
try {
|
||||
proxy.init_finish(result);
|
||||
|
||||
simpleResult.set_op_res_gboolean(true);
|
||||
} catch(e if e instanceof GLib.Error) {
|
||||
simpleResult.set_from_error(e);
|
||||
}
|
||||
|
||||
simpleResult.complete();
|
||||
}));
|
||||
},
|
||||
|
||||
// Having this function is a bit of a hack since the Systemd and ConsoleKit
|
||||
// session objects have different interfaces - but in both cases there are
|
||||
// Lock/Unlock signals, and that's all we count upon at the moment.
|
||||
getCurrentSessionProxy: function() {
|
||||
if (!this._currentSession) {
|
||||
let [currentSessionId] = this._proxy.GetCurrentSessionSync();
|
||||
this._currentSession = new ConsoleKitSession(Gio.DBus.system,
|
||||
'org.freedesktop.ConsoleKit',
|
||||
currentSessionId);
|
||||
}
|
||||
|
||||
return this._currentSession;
|
||||
},
|
||||
|
||||
@ -341,32 +185,26 @@ const LoginManagerConsoleKit = new Lang.Class({
|
||||
session.connectSignal('ActiveChanged', Lang.bind(this, function(object, senderName, [isActive]) {
|
||||
this._sessionActive = isActive;
|
||||
}));
|
||||
[this._sessionActive] = session.IsActiveSync(null);
|
||||
[this._sessionActive] = session.IsActiveSync();
|
||||
|
||||
return this._sessionActive;
|
||||
},
|
||||
|
||||
canPowerOff: function(asyncCallback) {
|
||||
this._proxy.CanStopRemote(null, function(proxy, result) {
|
||||
let val = false;
|
||||
|
||||
try {
|
||||
[val] = proxy.CanStopFinish(result);
|
||||
} catch(e) { }
|
||||
|
||||
asyncCallback(val);
|
||||
this._proxy.CanStopRemote(function(result, error) {
|
||||
if (error)
|
||||
asyncCallback(false);
|
||||
else
|
||||
asyncCallback(result[0]);
|
||||
});
|
||||
},
|
||||
|
||||
canReboot: function(asyncCallback) {
|
||||
this._proxy.CanRestartRemote(null, function(proxy, result) {
|
||||
let val = false;
|
||||
|
||||
try {
|
||||
[val] = proxy.CanRestartFinish(result);
|
||||
} catch(e) { }
|
||||
|
||||
asyncCallback(val);
|
||||
this._proxy.CanRestartRemote(function(result, error) {
|
||||
if (error)
|
||||
asyncCallback(false);
|
||||
else
|
||||
asyncCallback(result[0]);
|
||||
});
|
||||
},
|
||||
|
||||
@ -378,11 +216,11 @@ const LoginManagerConsoleKit = new Lang.Class({
|
||||
},
|
||||
|
||||
powerOff: function() {
|
||||
this._proxy.StopRemote(null, null);
|
||||
this._proxy.StopRemote();
|
||||
},
|
||||
|
||||
reboot: function() {
|
||||
this._proxy.RestartRemote(null, null);
|
||||
this._proxy.RestartRemote();
|
||||
},
|
||||
|
||||
suspend: function() {
|
||||
|
@ -1,7 +1,6 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Lang = imports.lang;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Signals = imports.signals;
|
||||
@ -27,16 +26,7 @@ const ModemGsmNetworkInterface = <interface name="org.freedesktop.ModemManager.M
|
||||
</signal>
|
||||
</interface>;
|
||||
|
||||
const ModemGsmNetworkProxy = new Gio.DBusProxyClass({
|
||||
Name: 'ModemGsmNetworkProxy',
|
||||
Interface: ModemGsmNetworkInterface,
|
||||
|
||||
_init: function(modem) {
|
||||
this.parent({ g_bus_type: Gio.BusType.SYSTEM,
|
||||
g_name: 'org.freedesktop.ModemManager',
|
||||
g_object_path: modem });
|
||||
}
|
||||
});
|
||||
const ModemGsmNetworkProxy = Gio.DBusProxy.makeProxyWrapper(ModemGsmNetworkInterface);
|
||||
|
||||
const ModemCdmaInterface = <interface name="org.freedesktop.ModemManager.Modem.Cdma">
|
||||
<method name="GetSignalQuality">
|
||||
@ -50,16 +40,7 @@ const ModemCdmaInterface = <interface name="org.freedesktop.ModemManager.Modem.C
|
||||
</signal>
|
||||
</interface>;
|
||||
|
||||
const ModemCdmaProxy = new Gio.DBusProxyClass({
|
||||
Name: 'ModemCdmaProxy',
|
||||
Interface: ModemCdmaInterface,
|
||||
|
||||
_init: function(modem) {
|
||||
this.parent({ g_bus_type: Gio.BusType.SYSTEM,
|
||||
g_name: 'org.freedesktop.ModemManager',
|
||||
g_object_path: modem });
|
||||
},
|
||||
});
|
||||
const ModemCdmaProxy = Gio.DBusProxy.makeProxyWrapper(ModemCdmaInterface);
|
||||
|
||||
let _providersTable;
|
||||
function _getProvidersTable() {
|
||||
@ -73,18 +54,11 @@ const ModemGsm = new Lang.Class({
|
||||
Name: 'ModemGsm',
|
||||
|
||||
_init: function(path) {
|
||||
this._proxy = new ModemGsmNetworkProxy(path);
|
||||
this._proxy.init_async(GLib.PRIORITY_DEFAULT, null, Lang.bind(this, function(obj, result) {
|
||||
obj.init_finish(result);
|
||||
|
||||
this._finishInit();
|
||||
}));
|
||||
this._proxy = new ModemGsmNetworkProxy(Gio.DBus.system, 'org.freedesktop.ModemManager', path);
|
||||
|
||||
this.signal_quality = 0;
|
||||
this.operator_name = null;
|
||||
},
|
||||
|
||||
_finishInit: function() {
|
||||
// Code is duplicated because the function have different signatures
|
||||
this._proxy.connectSignal('SignalQuality', Lang.bind(this, function(proxy, sender, [quality]) {
|
||||
this.signal_quality = quality;
|
||||
@ -94,19 +68,24 @@ const ModemGsm = new Lang.Class({
|
||||
this.operator_name = this._findOperatorName(name, code);
|
||||
this.emit('notify::operator-name');
|
||||
}));
|
||||
this._proxy.GetRegistrationInfoRemote(null, Lang.bind(this, function(proxy, result) {
|
||||
let [status, code, name] = proxy.GetRegistrationInfoFinish(result);
|
||||
this._proxy.GetRegistrationInfoRemote(Lang.bind(this, function([result], err) {
|
||||
if (err) {
|
||||
log(err);
|
||||
return;
|
||||
}
|
||||
|
||||
let [status, code, name] = result;
|
||||
this.operator_name = this._findOperatorName(name, code);
|
||||
this.emit('notify::operator-name');
|
||||
}));
|
||||
this._proxy.GetSignalQualityRemote(null, Lang.bind(this, function(proxy, result) {
|
||||
try {
|
||||
[this.signal_quality] = proxy.GetSignalQualityFinish(result);
|
||||
} catch(e) {
|
||||
this._proxy.GetSignalQualityRemote(Lang.bind(this, function(result, err) {
|
||||
if (err) {
|
||||
// it will return an error if the device is not connected
|
||||
this.signal_quality = 0;
|
||||
} else {
|
||||
let [quality] = result;
|
||||
this.signal_quality = quality;
|
||||
}
|
||||
|
||||
this.emit('notify::signal-quality');
|
||||
}));
|
||||
},
|
||||
@ -178,18 +157,10 @@ const ModemCdma = new Lang.Class({
|
||||
Name: 'ModemCdma',
|
||||
|
||||
_init: function(path) {
|
||||
this._proxy = new ModemCdmaProxy(path);
|
||||
this._proxy.init_async(GLib.PRIORITY_DEFAULT, null, Lang.bind(this, function(obj, result) {
|
||||
obj.init_finish(result);
|
||||
|
||||
this._finishInit();
|
||||
}));
|
||||
this._proxy = new ModemCdmaProxy(Gio.DBus.system, 'org.freedesktop.ModemManager', path);
|
||||
|
||||
this.signal_quality = 0;
|
||||
this.operator_name = null;
|
||||
},
|
||||
|
||||
_finishInit: function() {
|
||||
this._proxy.connectSignal('SignalQuality', Lang.bind(this, function(proxy, sender, params) {
|
||||
this.signal_quality = params[0];
|
||||
this.emit('notify::signal-quality');
|
||||
@ -199,31 +170,30 @@ const ModemCdma = new Lang.Class({
|
||||
if (this.operator_name == null)
|
||||
this._refreshServingSystem();
|
||||
}));
|
||||
this._proxy.GetSignalQualityRemote(null, Lang.bind(this, function(proxy, result) {
|
||||
try {
|
||||
[this.signal_quality] = proxy.GetSignalQualityFinish(result);
|
||||
} catch(e) {
|
||||
this._proxy.GetSignalQualityRemote(Lang.bind(this, function(result, err) {
|
||||
if (err) {
|
||||
// it will return an error if the device is not connected
|
||||
this.signal_quality = 0;
|
||||
} else {
|
||||
let [quality] = result;
|
||||
this.signal_quality = quality;
|
||||
}
|
||||
|
||||
this.emit('notify::signal-quality');
|
||||
}));
|
||||
},
|
||||
|
||||
_refreshServingSystem: function() {
|
||||
this._proxy.GetServingSystemRemote(null, Lang.bind(this, function(proxy, result) {
|
||||
try {
|
||||
let [bandClass, band, name] = proxy.GetServingSystemFinish(result);
|
||||
if (name.length > 0)
|
||||
this.operator_name = this._findProviderForSid(name);
|
||||
else
|
||||
this.operator_name = null;
|
||||
} catch(e) {
|
||||
this._proxy.GetServingSystemRemote(Lang.bind(this, function([result], err) {
|
||||
if (err) {
|
||||
// it will return an error if the device is not connected
|
||||
this.operator_name = null;
|
||||
} else {
|
||||
let [bandClass, band, id] = result;
|
||||
if (name.length > 0)
|
||||
this.operator_name = this._findProviderForSid(id);
|
||||
else
|
||||
this.operator_name = null;
|
||||
}
|
||||
|
||||
this.emit('notify::operator-name');
|
||||
}));
|
||||
},
|
||||
|
@ -1,6 +1,7 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const GMenu = imports.gi.GMenu;
|
||||
@ -371,6 +372,8 @@ const SettingsSearchProvider = new Lang.Class({
|
||||
|
||||
this._appSys = Shell.AppSystem.get_default();
|
||||
this._gnomecc = this._appSys.lookup_app('gnome-control-center.desktop');
|
||||
let appInfo = Gio.DesktopAppInfo.new('gnome-control-center.desktop');
|
||||
this.icon = appInfo.get_icon();
|
||||
},
|
||||
|
||||
getResultMetas: function(prefs, callback) {
|
||||
@ -379,9 +382,7 @@ const SettingsSearchProvider = new Lang.Class({
|
||||
let pref = prefs[i];
|
||||
metas.push({ 'id': pref,
|
||||
'name': pref.get_name(),
|
||||
'createIcon': function(size) {
|
||||
return pref.create_icon_texture(size);
|
||||
}
|
||||
'createIcon': function(size) { return; }
|
||||
});
|
||||
}
|
||||
callback(metas);
|
||||
@ -461,15 +462,15 @@ const AppWellIcon = new Lang.Class({
|
||||
this._draggable.connect('drag-begin', Lang.bind(this,
|
||||
function () {
|
||||
this._removeMenuTimeout();
|
||||
Main.overview.beginItemDrag(this);
|
||||
Main.overview.beginAppDrag(this);
|
||||
}));
|
||||
this._draggable.connect('drag-cancelled', Lang.bind(this,
|
||||
function () {
|
||||
Main.overview.cancelledItemDrag(this);
|
||||
Main.overview.cancelledAppDrag(this);
|
||||
}));
|
||||
this._draggable.connect('drag-end', Lang.bind(this,
|
||||
function () {
|
||||
Main.overview.endItemDrag(this);
|
||||
Main.overview.endAppDrag(this);
|
||||
}));
|
||||
|
||||
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
|
||||
|
@ -1,7 +1,6 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Gio = imports.gi.Gio;
|
||||
const Lang = imports.lang;
|
||||
const St = imports.gi.St;
|
||||
@ -201,17 +200,19 @@ const CalendarServerIface = <interface name="org.gnome.Shell.CalendarServer">
|
||||
<signal name="Changed" />
|
||||
</interface>;
|
||||
|
||||
const CalendarServer = new Gio.DBusProxyClass({
|
||||
Name: 'CalendarServer',
|
||||
Interface: CalendarServerIface,
|
||||
const CalendarServerInfo = Gio.DBusInterfaceInfo.new_for_xml(CalendarServerIface);
|
||||
|
||||
_init: function() {
|
||||
this.parent({ g_bus_type: Gio.BusType.SESSION,
|
||||
g_name: 'org.gnome.Shell.CalendarServer',
|
||||
g_object_path: '/org/gnome/Shell/CalendarServer',
|
||||
g_flags: Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES });
|
||||
}
|
||||
});
|
||||
function CalendarServer() {
|
||||
var self = new Gio.DBusProxy({ g_connection: Gio.DBus.session,
|
||||
g_interface_name: CalendarServerInfo.name,
|
||||
g_interface_info: CalendarServerInfo,
|
||||
g_name: 'org.gnome.Shell.CalendarServer',
|
||||
g_object_path: '/org/gnome/Shell/CalendarServer',
|
||||
g_flags: Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES });
|
||||
|
||||
self.init(null);
|
||||
return self;
|
||||
}
|
||||
|
||||
function _datesEqual(a, b) {
|
||||
if (a < b)
|
||||
@ -241,15 +242,11 @@ const DBusEventSource = new Lang.Class({
|
||||
this._dbusProxy = new CalendarServer();
|
||||
this._dbusProxy.connectSignal('Changed', Lang.bind(this, this._onChanged));
|
||||
|
||||
this._dbusProxy.init_async(GLib.PRIORITY_DEFAULT, null, Lang.bind(this, function(proxy, result) {
|
||||
try {
|
||||
proxy.init_finish(result);
|
||||
} catch(e) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._resetCache();
|
||||
this.emit('changed');
|
||||
this._dbusProxy.connect('notify::g-name-owner', Lang.bind(this, function() {
|
||||
if (this._dbusProxy.g_name_owner)
|
||||
this._onNameAppeared();
|
||||
else
|
||||
this._onNameVanished();
|
||||
}));
|
||||
},
|
||||
|
||||
@ -259,32 +256,37 @@ const DBusEventSource = new Lang.Class({
|
||||
this._lastRequestEnd = null;
|
||||
},
|
||||
|
||||
_onNameAppeared: function(owner) {
|
||||
this._resetCache();
|
||||
this._loadEvents(true);
|
||||
},
|
||||
|
||||
_onNameVanished: function(oldOwner) {
|
||||
this._resetCache();
|
||||
this.emit('changed');
|
||||
},
|
||||
|
||||
_onChanged: function() {
|
||||
this._loadEvents(false);
|
||||
},
|
||||
|
||||
_onEventsReceived: function(proxy, result) {
|
||||
let appointments;
|
||||
try {
|
||||
[appointments] = proxy.call_finish(result).deep_unpack();
|
||||
} catch(e if e instanceof GLib.Error) {
|
||||
// ignore errors coming from DBus
|
||||
appointments = [];
|
||||
}
|
||||
|
||||
_onEventsReceived: function(results, error) {
|
||||
let newEvents = [];
|
||||
for (let n = 0; n < appointments.length; n++) {
|
||||
let a = appointments[n];
|
||||
let date = new Date(a[4] * 1000);
|
||||
let end = new Date(a[5] * 1000);
|
||||
let summary = a[1];
|
||||
let allDay = a[3];
|
||||
let event = new CalendarEvent(date, end, summary, allDay);
|
||||
newEvents.push(event);
|
||||
let appointments = results ? results[0] : null;
|
||||
if (appointments != null) {
|
||||
for (let n = 0; n < appointments.length; n++) {
|
||||
let a = appointments[n];
|
||||
let date = new Date(a[4] * 1000);
|
||||
let end = new Date(a[5] * 1000);
|
||||
let summary = a[1];
|
||||
let allDay = a[3];
|
||||
let event = new CalendarEvent(date, end, summary, allDay);
|
||||
newEvents.push(event);
|
||||
}
|
||||
newEvents.sort(function(event1, event2) {
|
||||
return event1.date.getTime() - event2.date.getTime();
|
||||
});
|
||||
}
|
||||
newEvents.sort(function(event1, event2) {
|
||||
return event1.date.getTime() - event2.date.getTime();
|
||||
});
|
||||
|
||||
this._events = newEvents;
|
||||
this.emit('changed');
|
||||
@ -292,19 +294,14 @@ const DBusEventSource = new Lang.Class({
|
||||
|
||||
_loadEvents: function(forceReload) {
|
||||
if (this._curRequestBegin && this._curRequestEnd){
|
||||
/* Can't use GetEventsRemote because we need to pass the
|
||||
flags here */
|
||||
let callFlags = Gio.DBusCallFlags.NO_AUTO_START;
|
||||
if (forceReload)
|
||||
callFlags = Gio.DBusCallFlags.NONE;
|
||||
this._dbusProxy.call("GetEvents",
|
||||
GLib.Variant.new("(xxb)", [this._curRequestBegin.getTime() / 1000,
|
||||
this._curRequestEnd.getTime() / 1000,
|
||||
forceReload]),
|
||||
callFlags,
|
||||
-1,
|
||||
null,
|
||||
Lang.bind(this, this._onEventsReceived));
|
||||
callFlags = Gio.DBusCallFlags.NONE;
|
||||
this._dbusProxy.GetEventsRemote(this._curRequestBegin.getTime() / 1000,
|
||||
this._curRequestEnd.getTime() / 1000,
|
||||
forceReload,
|
||||
Lang.bind(this, this._onEventsReceived),
|
||||
callFlags);
|
||||
}
|
||||
},
|
||||
|
||||
@ -397,6 +394,7 @@ const Calendar = new Lang.Class({
|
||||
this._eventSourceChangedId = this._eventSource.connect('changed', Lang.bind(this, function() {
|
||||
this._update(false);
|
||||
}));
|
||||
this._update(true);
|
||||
}
|
||||
},
|
||||
|
||||
|
93
js/ui/centerLayout.js
Normal file
93
js/ui/centerLayout.js
Normal file
@ -0,0 +1,93 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Lang = imports.lang;
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const St = imports.gi.St;
|
||||
|
||||
function connectLayoutManager(layoutManager, styleChanged) {
|
||||
let widget, styleChangedId;
|
||||
|
||||
function _styleChanged() {
|
||||
let themeNode = widget.get_theme_node();
|
||||
styleChanged(themeNode, widget);
|
||||
}
|
||||
|
||||
function actorChanged() {
|
||||
if (widget) {
|
||||
widget.disconnect(styleChangedId);
|
||||
styleChangedId = 0;
|
||||
}
|
||||
|
||||
let actor = layoutManager.get_actor();
|
||||
if (actor && actor instanceof St.Widget) {
|
||||
widget = actor;
|
||||
styleChangedId = widget.connect('style-changed', _styleChanged);
|
||||
_styleChanged();
|
||||
}
|
||||
}
|
||||
|
||||
layoutManager.connect('notify::actor', actorChanged);
|
||||
return layoutManager;
|
||||
}
|
||||
|
||||
function connectSpacing(layoutManager) {
|
||||
return connectLayoutManager(layoutManager, function(themeNode, widget) {
|
||||
layoutManager.spacing = themeNode.get_length('spacing');
|
||||
});
|
||||
}
|
||||
|
||||
const CenterLayout = new Lang.Class({
|
||||
Name: 'CenterLayout',
|
||||
Extends: Clutter.BoxLayout,
|
||||
|
||||
vfunc_allocate: function(container, box, flags) {
|
||||
let rtl = container.get_text_direction() == Clutter.TextDirection.RTL;
|
||||
|
||||
let availWidth = box.x2 - box.x1;
|
||||
let availHeight = box.y2 - box.y1;
|
||||
|
||||
// Assume that these are the first three widgets and they are all visible.
|
||||
let [left, center, right] = container.get_children();
|
||||
|
||||
// Only support horizontal layouts for now.
|
||||
let [centerMinWidth, centerNaturalWidth] = center.get_preferred_width(availWidth);
|
||||
|
||||
let sideWidth = (availWidth - centerNaturalWidth) / 2;
|
||||
|
||||
let childBox = new Clutter.ActorBox();
|
||||
childBox.y1 = box.y1;
|
||||
childBox.y2 = box.y1 + availHeight;
|
||||
|
||||
if (left) {
|
||||
let [leftMinWidth, leftNaturalWidth] = left.get_preferred_width(availWidth);
|
||||
let leftSide = Math.min(Math.floor(sideWidth), leftNaturalWidth);
|
||||
if (rtl) {
|
||||
childBox.x1 = availWidth - leftSide;
|
||||
childBox.x2 = availWidth;
|
||||
} else {
|
||||
childBox.x1 = 0;
|
||||
childBox.x2 = leftSide;
|
||||
}
|
||||
childBox.x1 += box.x1;
|
||||
left.allocate(childBox, flags);
|
||||
}
|
||||
|
||||
childBox.x1 = box.x1 + Math.ceil(sideWidth);
|
||||
childBox.x2 = childBox.x1 + centerNaturalWidth;
|
||||
center.allocate(childBox, flags);
|
||||
|
||||
if (right) {
|
||||
let [rightMinWidth, rightNaturalWidth] = right.get_preferred_width(availWidth);
|
||||
let rightSide = Math.min(Math.floor(sideWidth), rightNaturalWidth);
|
||||
if (rtl) {
|
||||
childBox.x1 = 0;
|
||||
childBox.x2 = rightSide;
|
||||
} else {
|
||||
childBox.x1 = availWidth - rightSide;
|
||||
childBox.x2 = availWidth;
|
||||
}
|
||||
childBox.x1 += box.x1;
|
||||
right.allocate(childBox, flags);
|
||||
}
|
||||
}
|
||||
});
|
@ -33,9 +33,7 @@ const AutomountManager = new Lang.Class({
|
||||
Lang.bind(this, this._InhibitorsChanged));
|
||||
this._inhibited = false;
|
||||
|
||||
LoginManager.getLoginManager(Lang.bind(this, function(manager) {
|
||||
this._loginManager = manager;
|
||||
}));
|
||||
this._loginManager = LoginManager.getLoginManager();
|
||||
this._volumeMonitor = Gio.VolumeMonitor.get();
|
||||
},
|
||||
|
||||
@ -87,7 +85,7 @@ const AutomountManager = new Lang.Class({
|
||||
_onDriveConnected: function() {
|
||||
// if we're not in the current ConsoleKit session,
|
||||
// or screensaver is active, don't play sounds
|
||||
if (!this._loginManager || !this._loginManager.sessionActive)
|
||||
if (!this._loginManager.sessionActive)
|
||||
return;
|
||||
|
||||
global.play_theme_sound(0, 'device-added-media');
|
||||
@ -96,7 +94,7 @@ const AutomountManager = new Lang.Class({
|
||||
_onDriveDisconnected: function() {
|
||||
// if we're not in the current ConsoleKit session,
|
||||
// or screensaver is active, don't play sounds
|
||||
if (!this._loginManager || !this._loginManager.sessionActive)
|
||||
if (!this._loginManager.sessionActive)
|
||||
return;
|
||||
|
||||
global.play_theme_sound(0, 'device-removed-media');
|
||||
@ -105,7 +103,7 @@ const AutomountManager = new Lang.Class({
|
||||
_onDriveEjectButton: function(monitor, drive) {
|
||||
// TODO: this code path is not tested, as the GVfs volume monitor
|
||||
// doesn't emit this signal just yet.
|
||||
if (!this._loginManager || !this._loginManager.sessionActive)
|
||||
if (!this._loginManager.sessionActive)
|
||||
return;
|
||||
|
||||
// we force stop/eject in this case, so we don't have to pass a
|
||||
@ -145,7 +143,7 @@ const AutomountManager = new Lang.Class({
|
||||
if (params.checkSession) {
|
||||
// if we're not in the current ConsoleKit session,
|
||||
// don't attempt automount
|
||||
if (!this._loginManager || !this._loginManager.sessionActive)
|
||||
if (!this._loginManager.sessionActive)
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
const Lang = imports.lang;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const St = imports.gi.St;
|
||||
|
||||
const LoginManager = imports.misc.loginManager;
|
||||
@ -83,16 +82,12 @@ const HotplugSnifferIface = <interface name="org.gnome.Shell.HotplugSniffer">
|
||||
</method>
|
||||
</interface>;
|
||||
|
||||
const HotplugSniffer = new Gio.DBusProxyClass({
|
||||
Name: 'HotplugSnifferProxy',
|
||||
Interface: HotplugSnifferIface,
|
||||
|
||||
_init: function() {
|
||||
this.parent({ g_bus_type: Gio.BusType.SESSION,
|
||||
g_name: 'org.gnome.Shell.HotplugSniffer',
|
||||
g_object_path: '/org/gnome/Shell/HotplugSniffer' });
|
||||
}
|
||||
});
|
||||
const HotplugSnifferProxy = Gio.DBusProxy.makeProxyWrapper(HotplugSnifferIface);
|
||||
function HotplugSniffer() {
|
||||
return new HotplugSnifferProxy(Gio.DBus.session,
|
||||
'org.gnome.Shell.HotplugSniffer',
|
||||
'/org/gnome/Shell/HotplugSniffer');
|
||||
}
|
||||
|
||||
const ContentTypeDiscoverer = new Lang.Class({
|
||||
Name: 'ContentTypeDiscoverer',
|
||||
@ -132,14 +127,10 @@ const ContentTypeDiscoverer = new Lang.Class({
|
||||
let root = mount.get_root();
|
||||
|
||||
let hotplugSniffer = new HotplugSniffer();
|
||||
hotplugSniffer.init_async(GLib.PRIORITY_DEFAULT, null, Lang.bind(this, function(proxy, result) {
|
||||
proxy.init_finish(result);
|
||||
|
||||
proxy.SniffURIRemote(root.get_uri(), null, Lang.bind(this, function(proxy, result) {
|
||||
let [contentTypes] = proxy.SniffURIFinish(result);
|
||||
this._emitCallback(mount, contentTypes);
|
||||
}));
|
||||
}));
|
||||
hotplugSniffer.SniffURIRemote(root.get_uri(),
|
||||
Lang.bind(this, function([contentTypes]) {
|
||||
this._emitCallback(mount, contentTypes);
|
||||
}));
|
||||
}
|
||||
},
|
||||
|
||||
@ -171,9 +162,7 @@ const AutorunManager = new Lang.Class({
|
||||
Name: 'AutorunManager',
|
||||
|
||||
_init: function() {
|
||||
LoginManager.getLoginManager(Lang.bind(this, function(manager) {
|
||||
this._loginManager = manager;
|
||||
}));
|
||||
this._loginManager = LoginManager.getLoginManager();
|
||||
|
||||
this._volumeMonitor = Gio.VolumeMonitor.get();
|
||||
|
||||
@ -226,7 +215,7 @@ const AutorunManager = new Lang.Class({
|
||||
_onMountAdded: function(monitor, mount) {
|
||||
// don't do anything if our session is not the currently
|
||||
// active one
|
||||
if (!this._loginManager || !this._loginManager.sessionActive)
|
||||
if (!this._loginManager.sessionActive)
|
||||
return;
|
||||
|
||||
this._processMount(mount, true);
|
||||
|
@ -372,6 +372,9 @@ const Dash = new Lang.Class({
|
||||
this._maxHeight = -1;
|
||||
this.iconSize = 64;
|
||||
this._shownInitially = false;
|
||||
this.visible = false;
|
||||
this._hiddenX;
|
||||
this._targetX;
|
||||
|
||||
this._dragPlaceholder = null;
|
||||
this._dragPlaceholderPos = -1;
|
||||
@ -399,7 +402,8 @@ const Dash = new Lang.Class({
|
||||
function() {
|
||||
if (this._maxHeight != this.actor.height)
|
||||
this._queueRedisplay();
|
||||
this._maxHeight = this.actor.height;
|
||||
if (this.actor.height > this._maxHeight)
|
||||
this._maxHeight = this.actor.height;
|
||||
}));
|
||||
|
||||
this._workId = Main.initializeDeferredWork(this._box, Lang.bind(this, this._redisplay));
|
||||
@ -410,11 +414,11 @@ const Dash = new Lang.Class({
|
||||
AppFavorites.getAppFavorites().connect('changed', Lang.bind(this, this._queueRedisplay));
|
||||
this._appSystem.connect('app-state-changed', Lang.bind(this, this._queueRedisplay));
|
||||
|
||||
Main.overview.connect('item-drag-begin',
|
||||
Main.overview.connect('app-drag-begin',
|
||||
Lang.bind(this, this._onDragBegin));
|
||||
Main.overview.connect('item-drag-end',
|
||||
Main.overview.connect('app-drag-end',
|
||||
Lang.bind(this, this._onDragEnd));
|
||||
Main.overview.connect('item-drag-cancelled',
|
||||
Main.overview.connect('app-drag-cancelled',
|
||||
Lang.bind(this, this._onDragCancelled));
|
||||
Main.overview.connect('window-drag-begin',
|
||||
Lang.bind(this, this._onDragBegin));
|
||||
@ -546,6 +550,17 @@ const Dash = new Lang.Class({
|
||||
}
|
||||
},
|
||||
|
||||
_computeDashX: function() {
|
||||
this._targetX = this.actor.get_x();
|
||||
|
||||
let rtl = (this.actor.get_text_direction() == Clutter.TextDirection.RTL);
|
||||
|
||||
if (rtl)
|
||||
this._hiddenX = this._targetX + this.actor.width;
|
||||
else
|
||||
this._hiddenX = -this.actor.width;
|
||||
},
|
||||
|
||||
_adjustIconSize: function() {
|
||||
// For the icon size, we only consider children which are "proper"
|
||||
// icons (i.e. ignoring drag placeholders) and which are not
|
||||
@ -641,6 +656,8 @@ const Dash = new Lang.Class({
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this._computeDashX();
|
||||
},
|
||||
|
||||
_redisplay: function () {
|
||||
@ -757,6 +774,7 @@ const Dash = new Lang.Class({
|
||||
// of items, to avoid all items zooming in at once
|
||||
if (!this._shownInitially) {
|
||||
this._shownInitially = true;
|
||||
this.visible = true;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -901,6 +919,34 @@ const Dash = new Lang.Class({
|
||||
}));
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
show: function() {
|
||||
if (this.visible)
|
||||
return;
|
||||
|
||||
this.visible = true;
|
||||
|
||||
this.actor.show();
|
||||
Tweener.addTween(this.actor, { translation_x: this._targetX,
|
||||
transition: 'easeOutQuad',
|
||||
time: DASH_ANIMATION_TIME
|
||||
});
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
if (!this.visible)
|
||||
return;
|
||||
|
||||
this.visible = false;
|
||||
|
||||
Tweener.addTween(this.actor, { translation_x: this._hiddenX,
|
||||
transition: 'easeOutQuad',
|
||||
time: DASH_ANIMATION_TIME,
|
||||
onComplete: Lang.bind(this, function () {
|
||||
this.actor.hide();
|
||||
})
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -105,7 +105,7 @@ const restartDialogContent = {
|
||||
endDescription: _("Restarting the system."),
|
||||
confirmButtons: [{ signal: 'ConfirmedReboot',
|
||||
label: C_("button", "Restart") }],
|
||||
iconName: 'view-refresh-symbolic',
|
||||
iconName: 'system-shutdown-symbolic',
|
||||
iconStyleClass: 'end-session-dialog-shutdown-icon'
|
||||
};
|
||||
|
||||
@ -218,34 +218,6 @@ function init() {
|
||||
_endSessionDialog = new EndSessionDialog();
|
||||
}
|
||||
|
||||
const EndSessionExporter = new Gio.DBusImplementerClass({
|
||||
Name: 'EndSessionExporter',
|
||||
Interface: EndSessionDialogIface,
|
||||
|
||||
_init: function() {
|
||||
this.parent();
|
||||
|
||||
this.export(Gio.DBus.session, '/org/gnome/SessionManager/EndSessionDialog');
|
||||
},
|
||||
|
||||
OpenAsync: function(parameters, invocation) {
|
||||
this.emit('open', parameters, invocation);
|
||||
},
|
||||
|
||||
close: function() {
|
||||
this.emit_signal('Closed');
|
||||
},
|
||||
|
||||
cancel: function() {
|
||||
this.emit_signal('Canceled');
|
||||
},
|
||||
|
||||
confirm: function(type) {
|
||||
this.emit_signal(type);
|
||||
},
|
||||
});
|
||||
Signals.addSignalMethods(EndSessionExporter.prototype);
|
||||
|
||||
const EndSessionDialog = new Lang.Class({
|
||||
Name: 'EndSessionDialog',
|
||||
Extends: ModalDialog.ModalDialog,
|
||||
@ -323,8 +295,8 @@ const EndSessionDialog = new Lang.Class({
|
||||
scrollView.hide();
|
||||
}));
|
||||
|
||||
this._exporter = new EndSessionExporter();
|
||||
this._exporter.connect('open', Lang.bind(this, this._onOpenRequest));
|
||||
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(EndSessionDialogIface, this);
|
||||
this._dbusImpl.export(Gio.DBus.session, '/org/gnome/SessionManager/EndSessionDialog');
|
||||
},
|
||||
|
||||
_onDestroy: function() {
|
||||
@ -415,19 +387,19 @@ const EndSessionDialog = new Lang.Class({
|
||||
|
||||
close: function() {
|
||||
this.parent();
|
||||
this._exporter.close();
|
||||
this._dbusImpl.emit_signal('Closed', null);
|
||||
},
|
||||
|
||||
cancel: function() {
|
||||
this._stopTimer();
|
||||
this._exporter.cancel();
|
||||
this._dbusImpl.emit_signal('Canceled', null);
|
||||
this.close(global.get_current_time());
|
||||
},
|
||||
|
||||
_confirm: function(signal) {
|
||||
this._fadeOutDialog();
|
||||
this._stopTimer();
|
||||
this._exporter.confirm(signal);
|
||||
this._dbusImpl.emit_signal(signal, null);
|
||||
},
|
||||
|
||||
_onOpened: function() {
|
||||
@ -480,7 +452,7 @@ const EndSessionDialog = new Lang.Class({
|
||||
this._updateContent();
|
||||
},
|
||||
|
||||
_onOpenRequest: function(exporter, parameters, invocation) {
|
||||
OpenAsync: function(parameters, invocation) {
|
||||
let [type, timestamp, totalSecondsToStayOpen, inhibitorObjectPaths] = parameters;
|
||||
this._totalSecondsToStayOpen = totalSecondsToStayOpen;
|
||||
this._inhibitors = [];
|
||||
@ -494,10 +466,7 @@ const EndSessionDialog = new Lang.Class({
|
||||
}
|
||||
|
||||
for (let i = 0; i < inhibitorObjectPaths.length; i++) {
|
||||
let inhibitor = new GnomeSession.Inhibitor(inhibitorObjectPaths[i]);
|
||||
inhibitor.init_async(GLib.PRIORITY_DEFAULT, null, Lang.bind(this, function(proxy, result) {
|
||||
proxy.init_finish(result);
|
||||
|
||||
let inhibitor = new GnomeSession.Inhibitor(inhibitorObjectPaths[i], Lang.bind(this, function(proxy, error) {
|
||||
this._onInhibitorLoaded(proxy);
|
||||
}));
|
||||
|
||||
|
@ -198,7 +198,11 @@ const IconGrid = new Lang.Class({
|
||||
|
||||
_getPreferredHeight: function (grid, forWidth, alloc) {
|
||||
let children = this._getVisibleChildren();
|
||||
let [nColumns, usedWidth] = this._computeLayout(forWidth);
|
||||
let nColumns;
|
||||
if (forWidth < 0)
|
||||
nColumns = children.length;
|
||||
else
|
||||
nColumns = this._computeLayout(forWidth)[0];
|
||||
let nRows;
|
||||
if (nColumns > 0)
|
||||
nRows = Math.ceil(children.length / nColumns);
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
const Caribou = imports.gi.Caribou;
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const DBus = imports.dbus;
|
||||
const Gdk = imports.gi.Gdk;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
@ -190,14 +191,13 @@ const Key = new Lang.Class({
|
||||
}
|
||||
});
|
||||
|
||||
const Keyboard = new Gio.DBusImplementerClass({
|
||||
const Keyboard = new Lang.Class({
|
||||
// HACK: we can't set Name, because it collides with Name dbus property
|
||||
// Name: 'Keyboard',
|
||||
Interface: CaribouKeyboardIface,
|
||||
|
||||
_init: function () {
|
||||
this.parent();
|
||||
this.export(Gio.DBus.session, '/org/gnome/Caribou/Keyboard');
|
||||
this._impl = Gio.DBusExportedObject.wrapJSObject(CaribouKeyboardIface, this);
|
||||
this._impl.export(Gio.DBus.session, '/org/gnome/Caribou/Keyboard');
|
||||
|
||||
this.actor = null;
|
||||
this._focusInTray = false;
|
||||
|
@ -96,15 +96,14 @@ const ZoomRegionIface = <interface name={ZOOM_SERVICE_NAME}>
|
||||
// '/org/gnome/Magnifier/ZoomRegion/zoomer1', etc.
|
||||
let _zoomRegionInstanceCount = 0;
|
||||
|
||||
const ShellMagnifier = new Gio.DBusImplementerClass({
|
||||
const ShellMagnifier = new Lang.Class({
|
||||
Name: 'ShellMagnifier',
|
||||
Interface: MagnifierIface,
|
||||
|
||||
_init: function() {
|
||||
this.parent();
|
||||
this.export(Gio.DBus.session, MAG_SERVICE_PATH);
|
||||
|
||||
this._zoomers = {};
|
||||
|
||||
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(MagnifierIface, this);
|
||||
this._dbusImpl.export(Gio.DBus.session, MAG_SERVICE_PATH);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -333,15 +332,14 @@ const ShellMagnifier = new Gio.DBusImplementerClass({
|
||||
* @zoomerObjectPath: String that is the path to a DBus ZoomRegion.
|
||||
* @zoomRegion: The actual zoom region associated with the object path.
|
||||
*/
|
||||
const ShellMagnifierZoomRegion = new Gio.DBusImplementerClass({
|
||||
const ShellMagnifierZoomRegion = new Lang.Class({
|
||||
Name: 'ShellMagnifierZoomRegion',
|
||||
Interface: ZoomRegionIface,
|
||||
|
||||
_init: function(zoomerObjectPath, zoomRegion) {
|
||||
this.parent();
|
||||
this.export(Gio.DBus.session, zoomerObjectPath);
|
||||
|
||||
this._zoomRegion = zoomRegion;
|
||||
|
||||
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(ZoomRegionIface, this);
|
||||
this._dbusImpl.export(Gio.DBus.session, zoomerObjectPath);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -419,6 +417,6 @@ const ShellMagnifierZoomRegion = new Gio.DBusImplementerClass({
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
this.unexport();
|
||||
this._dbusImpl.unexport();
|
||||
}
|
||||
});
|
||||
|
@ -1365,16 +1365,13 @@ const MessageTray = new Lang.Class({
|
||||
Name: 'MessageTray',
|
||||
|
||||
_init: function() {
|
||||
this._presence = new GnomeSession.Presence();
|
||||
this._presence.init_async(GLib.PRIORITY_DEFAULT, null, Lang.bind(this, function(proxy, result) {
|
||||
proxy.init_finish(result);
|
||||
|
||||
this._presence = new GnomeSession.Presence(Lang.bind(this, function(proxy, error) {
|
||||
this._onStatusChanged(proxy.status);
|
||||
this._presence.connectSignal('StatusChanged', Lang.bind(this, function(proxy, senderName, [status]) {
|
||||
this._onStatusChanged(status);
|
||||
}));
|
||||
}));
|
||||
this._busy = false;
|
||||
this._presence.connectSignal('StatusChanged', Lang.bind(this, function(proxy, senderName, [status]) {
|
||||
this._onStatusChanged(status);
|
||||
}));
|
||||
|
||||
this.actor = new St.Widget({ name: 'message-tray',
|
||||
reactive: true,
|
||||
@ -1501,7 +1498,7 @@ const MessageTray = new Lang.Class({
|
||||
this._overviewVisible = true;
|
||||
this._grabHelper.ungrab(); // drop modal grab if necessary
|
||||
this.actor.add_style_pseudo_class('overview');
|
||||
this._updateState();
|
||||
this.show();
|
||||
}));
|
||||
Main.overview.connect('hiding', Lang.bind(this,
|
||||
function() {
|
||||
@ -1739,6 +1736,11 @@ const MessageTray = new Lang.Class({
|
||||
this._updateState();
|
||||
},
|
||||
|
||||
show: function() {
|
||||
this._traySummoned = true;
|
||||
this._updateState();
|
||||
},
|
||||
|
||||
_onNotify: function(source, notification) {
|
||||
if (this._summaryBoxPointerItem && this._summaryBoxPointerItem.source == source) {
|
||||
if (this._summaryBoxPointerState == State.HIDING) {
|
||||
@ -1981,7 +1983,7 @@ const MessageTray = new Lang.Class({
|
||||
}
|
||||
|
||||
// Summary
|
||||
let summarySummoned = this._pointerInSummary || this._overviewVisible || this._traySummoned;
|
||||
let summarySummoned = this._pointerInSummary || this._traySummoned;
|
||||
let summaryPinned = this._pointerInTray || summarySummoned || this._locked;
|
||||
let summaryHovered = this._pointerInTray || this._pointerInSummary;
|
||||
|
||||
@ -1989,7 +1991,7 @@ const MessageTray = new Lang.Class({
|
||||
this._notificationState == State.SHOWN);
|
||||
let notificationsDone = !notificationsVisible && !notificationsPending;
|
||||
|
||||
let summaryOptionalInOverview = this._overviewVisible && !this._locked && !summaryHovered;
|
||||
let summaryOptionalInOverview = !this._locked && !summaryHovered;
|
||||
let mustHideSummary = (notificationsPending && (notificationUrgent || summaryOptionalInOverview))
|
||||
|| notificationsVisible || !Main.sessionMode.hasNotifications;
|
||||
|
||||
|
@ -25,19 +25,10 @@ const BusIface = <interface name="org.freedesktop.DBus">
|
||||
</method>
|
||||
</interface>;
|
||||
|
||||
const Bus = new Gio.DBusProxyClass({
|
||||
Name: 'SessionBusProxy',
|
||||
Interface: BusIface,
|
||||
|
||||
_init: function() {
|
||||
this.parent({ g_bus_type: Gio.BusType.SESSION,
|
||||
g_name: 'org.freedesktop.DBus',
|
||||
g_object_path: '/org/freedesktop/DBus',
|
||||
g_flags: (Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES |
|
||||
Gio.DBusProxyFlags.DO_NOT_CONNECT_SIGNALS |
|
||||
Gio.DBusProxyFlags.DO_NOT_AUTO_START) });
|
||||
}
|
||||
});
|
||||
var BusProxy = Gio.DBusProxy.makeProxyWrapper(BusIface);
|
||||
function Bus() {
|
||||
return new BusProxy(Gio.DBus.session, 'org.freedesktop.DBus', '/org/freedesktop/DBus');
|
||||
}
|
||||
|
||||
const NotificationDaemonIface = <interface name="org.freedesktop.Notifications">
|
||||
<method name="Notify">
|
||||
@ -112,20 +103,17 @@ const STANDARD_TRAY_ICON_IMPLEMENTATIONS = {
|
||||
'ibus-ui-gtk': 'keyboard'
|
||||
};
|
||||
|
||||
const NotificationDaemon = new Gio.DBusImplementerClass({
|
||||
const NotificationDaemon = new Lang.Class({
|
||||
Name: 'NotificationDaemon',
|
||||
Interface: NotificationDaemonIface,
|
||||
|
||||
_init: function() {
|
||||
this.parent();
|
||||
this.export(Gio.DBus.session, '/org/freedesktop/Notifications');
|
||||
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(NotificationDaemonIface, this);
|
||||
this._dbusImpl.export(Gio.DBus.session, '/org/freedesktop/Notifications');
|
||||
|
||||
this._sources = [];
|
||||
this._senderToPid = {};
|
||||
this._notifications = {};
|
||||
this._busProxy = new Bus();
|
||||
// This is synchronous but fast because of the flags we use.
|
||||
this._busProxy.init(null);
|
||||
|
||||
this._trayManager = new Shell.TrayManager();
|
||||
this._trayIconAddedId = this._trayManager.connect('tray-icon-added', Lang.bind(this, this._onTrayIconAdded));
|
||||
@ -328,20 +316,18 @@ const NotificationDaemon = new Gio.DBusImplementerClass({
|
||||
return invocation.return_value(GLib.Variant.new('(u)', [id]));;
|
||||
}
|
||||
|
||||
this._busProxy.GetConnectionUnixProcessIDRemote(sender, null, Lang.bind(this, function (proxy, result) {
|
||||
this._busProxy.GetConnectionUnixProcessIDRemote(sender, Lang.bind(this, function (result, excp) {
|
||||
// The app may have updated or removed the notification
|
||||
ndata = this._notifications[id];
|
||||
if (!ndata)
|
||||
return;
|
||||
|
||||
let pid;
|
||||
try {
|
||||
[pid] = proxy.GetConnectionUnixProcessIDFinish(result);
|
||||
} catch(excp) {
|
||||
|
||||
if (excp) {
|
||||
logError(excp, 'Call to GetConnectionUnixProcessID failed');
|
||||
return;
|
||||
}
|
||||
|
||||
let [pid] = result;
|
||||
source = this._getSource(appName, pid, ndata, sender, null);
|
||||
|
||||
// We only store sender-pid entries for persistent sources.
|
||||
@ -501,11 +487,13 @@ const NotificationDaemon = new Gio.DBusImplementerClass({
|
||||
},
|
||||
|
||||
_emitNotificationClosed: function(id, reason) {
|
||||
this.emit_signal('NotificationClosed', id, reason);
|
||||
this._dbusImpl.emit_signal('NotificationClosed',
|
||||
GLib.Variant.new('(uu)', [id, reason]));
|
||||
},
|
||||
|
||||
_emitActionInvoked: function(id, action) {
|
||||
this.emit_signal('ActionInvoked', id, action);
|
||||
this._dbusImpl.emit_signal('ActionInvoked',
|
||||
GLib.Variant.new('(us)', [id, action]));
|
||||
},
|
||||
|
||||
_onTrayIconAdded: function(o, icon) {
|
||||
|
@ -10,6 +10,7 @@ const St = imports.gi.St;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Gdk = imports.gi.Gdk;
|
||||
|
||||
const CenterLayout = imports.ui.centerLayout;
|
||||
const Dash = imports.ui.dash;
|
||||
const DND = imports.ui.dnd;
|
||||
const Main = imports.ui.main;
|
||||
@ -23,9 +24,6 @@ const WorkspaceThumbnail = imports.ui.workspaceThumbnail;
|
||||
// Time for initial animation going into Overview mode
|
||||
const ANIMATION_TIME = 0.25;
|
||||
|
||||
// XXX -- grab this automatically. Hard to do.
|
||||
const DASH_MAX_WIDTH = 96;
|
||||
|
||||
const DND_WINDOW_SWITCH_TIMEOUT = 1250;
|
||||
|
||||
const SwipeScrollDirection = {
|
||||
@ -119,23 +117,18 @@ const Overview = new Lang.Class({
|
||||
this._desktopFade = new St.Bin();
|
||||
global.overlay_group.add_actor(this._desktopFade);
|
||||
|
||||
this._spacing = 0;
|
||||
|
||||
/* Translators: This is the main view to select
|
||||
activities. See also note for "Activities" string. */
|
||||
this._group = new St.Widget({ name: 'overview',
|
||||
accessible_name: _("Overview"),
|
||||
reactive: true });
|
||||
this._group._delegate = this;
|
||||
this._group.connect('style-changed',
|
||||
Lang.bind(this, function() {
|
||||
let node = this._group.get_theme_node();
|
||||
let spacing = node.get_length('spacing');
|
||||
if (spacing != this._spacing) {
|
||||
this._spacing = spacing;
|
||||
this._relayout();
|
||||
}
|
||||
}));
|
||||
this._overview = new St.BoxLayout({ name: 'overview',
|
||||
accessible_name: _("Overview"),
|
||||
reactive: true,
|
||||
vertical: true });
|
||||
this._overview._delegate = this;
|
||||
|
||||
let layout = new CenterLayout.CenterLayout();
|
||||
CenterLayout.connectSpacing(layout);
|
||||
this._group = new St.Widget({ name: 'overview-group',
|
||||
layout_manager: layout });
|
||||
|
||||
this._scrollDirection = SwipeScrollDirection.NONE;
|
||||
this._scrollAdjustment = null;
|
||||
@ -148,18 +141,19 @@ const Overview = new Lang.Class({
|
||||
this._modal = false; // have a modal grab
|
||||
this.animationInProgress = false;
|
||||
this._hideInProgress = false;
|
||||
this.searchActive = false;
|
||||
this.appsActive = false;
|
||||
|
||||
// During transitions, we raise this to the top to avoid having the overview
|
||||
// area be reactive; it causes too many issues such as double clicks on
|
||||
// Dash elements, or mouseover handlers in the workspaces.
|
||||
this._coverPane = new Clutter.Rectangle({ opacity: 0,
|
||||
reactive: true });
|
||||
this._group.add_actor(this._coverPane);
|
||||
this._overview.add_actor(this._coverPane);
|
||||
this._coverPane.connect('event', Lang.bind(this, function (actor, event) { return true; }));
|
||||
|
||||
|
||||
this._group.hide();
|
||||
global.overlay_group.add_actor(this._group);
|
||||
this._overview.hide();
|
||||
global.overlay_group.add_actor(this._overview);
|
||||
|
||||
this._coverPane.hide();
|
||||
|
||||
@ -171,6 +165,8 @@ const Overview = new Lang.Class({
|
||||
Main.xdndHandler.connect('drag-begin', Lang.bind(this, this._onDragBegin));
|
||||
Main.xdndHandler.connect('drag-end', Lang.bind(this, this._onDragEnd));
|
||||
|
||||
global.screen.connect('restacked', Lang.bind(this, this._onRestacked));
|
||||
|
||||
this._windowSwitchTimeoutId = 0;
|
||||
this._windowSwitchTimestamp = 0;
|
||||
this._lastActiveWorkspaceIndex = -1;
|
||||
@ -193,6 +189,13 @@ const Overview = new Lang.Class({
|
||||
|
||||
this._shellInfo = new ShellInfo();
|
||||
|
||||
// Add a clone of the panel to the overview so spacing and such is
|
||||
// automatic
|
||||
this._panelGhost = new St.Bin({ child: new Clutter.Clone({ source: Main.panel.actor }),
|
||||
reactive: false,
|
||||
opacity: 0 });
|
||||
this._overview.add_actor(this._panelGhost);
|
||||
|
||||
this._searchEntry = new St.Entry({ name: 'searchEntry',
|
||||
/* Translators: this is the text displayed
|
||||
in the search entry when no search is
|
||||
@ -201,16 +204,13 @@ const Overview = new Lang.Class({
|
||||
hint_text: _("Type to search..."),
|
||||
track_hover: true,
|
||||
can_focus: true });
|
||||
this._group.add_actor(this._searchEntry);
|
||||
|
||||
this._dash = new Dash.Dash();
|
||||
this._viewSelector = new ViewSelector.ViewSelector(this._searchEntry,
|
||||
this._dash.showAppsButton);
|
||||
this._group.add_actor(this._viewSelector.actor);
|
||||
this._group.add_actor(this._dash.actor);
|
||||
this._searchEntryBin = new St.Bin({ child: this._searchEntry,
|
||||
x_align: St.Align.MIDDLE });
|
||||
this._overview.add_actor(this._searchEntryBin);
|
||||
|
||||
// TODO - recalculate everything when desktop size changes
|
||||
this._dash.actor.add_constraint(this._viewSelector.constrainHeight);
|
||||
this._dash = new Dash.Dash();
|
||||
this._group.add_actor(this._dash.actor);
|
||||
this.dashIconSize = this._dash.iconSize;
|
||||
this._dash.connect('icon-size-changed',
|
||||
Lang.bind(this, function() {
|
||||
@ -221,6 +221,82 @@ const Overview = new Lang.Class({
|
||||
// the left of the overview
|
||||
Main.ctrlAltTabManager.addGroup(this._dash.actor, _("Dash"), 'user-bookmarks-symbolic');
|
||||
|
||||
this._viewSelector = new ViewSelector.ViewSelector(this._searchEntry,
|
||||
this._dash.showAppsButton);
|
||||
this._group.add_actor(this._viewSelector.actor);
|
||||
|
||||
this._thumbnailsBox = new WorkspaceThumbnail.ThumbnailsBox();
|
||||
this._group.add_actor(this._thumbnailsBox.actor);
|
||||
|
||||
// TODO: unique icon
|
||||
Main.ctrlAltTabManager.addGroup(this._thumbnailsBox.actor, _("Workspaces"), 'user-bookmarks-symbolic');
|
||||
|
||||
// Add our same-line elements after the search entry
|
||||
this._overview.add_actor(this._group);
|
||||
|
||||
// Then account for message tray
|
||||
this._messageTrayGhost = new St.Bin({ child: new Clutter.Clone({ source: Main.messageTray.actor }),
|
||||
reactive: false,
|
||||
opacity: 0 });
|
||||
this._overview.add_actor(this._messageTrayGhost);
|
||||
|
||||
this._viewSelector.connect('search-begin', Lang.bind(this,
|
||||
function() {
|
||||
this.searchActive = true;
|
||||
this._dash.hide();
|
||||
this._thumbnailsBox.hide();
|
||||
Main.messageTray.hide();
|
||||
}));
|
||||
this._viewSelector.connect('search-cancelled', Lang.bind(this,
|
||||
function() {
|
||||
this.searchActive = false;
|
||||
this._dash.show();
|
||||
this._thumbnailsBox.show();
|
||||
// search-cancelled is emitted if we leave the overview
|
||||
// directly from searching. That means the message tray will
|
||||
// be shown when we reach the workspace. Don't do this, only
|
||||
// show the message tray on search-cancelled if we are still
|
||||
// in the overview/not transitioning out of it.
|
||||
if (this.visible && !this.animationInProgress)
|
||||
Main.messageTray.show();
|
||||
}));
|
||||
this._viewSelector.connect('apps-button-checked', Lang.bind(this,
|
||||
function(vs, checked) {
|
||||
this.appsActive = checked;
|
||||
if (checked) {
|
||||
this._thumbnailsBox.hide();
|
||||
Main.messageTray.hide();
|
||||
} else {
|
||||
this._thumbnailsBox.show();
|
||||
if (this.visible && !this.animationInProgress)
|
||||
Main.messageTray.show();
|
||||
}
|
||||
}));
|
||||
|
||||
this.connect('app-drag-begin',
|
||||
Lang.bind(this, function () {
|
||||
this._dash.show();
|
||||
this._thumbnailsBox.show();
|
||||
}));
|
||||
this.connect('app-drag-cancelled',
|
||||
Lang.bind(this, function () {
|
||||
if (this.searchActive) {
|
||||
this._dash.hide();
|
||||
this._thumbnailsBox.hide();
|
||||
} else if (this.appsActive) {
|
||||
this._thumbnailsBox.hide();
|
||||
}
|
||||
}));
|
||||
this.connect('app-drag-end',
|
||||
Lang.bind(this, function () {
|
||||
if (this.searchActive) {
|
||||
this._dash.hide();
|
||||
this._thumbnailsBox.hide();
|
||||
} else if (this.appsActive) {
|
||||
this._thumbnailsBox.hide();
|
||||
}
|
||||
}));
|
||||
|
||||
Main.layoutManager.connect('monitors-changed', Lang.bind(this, this._relayout));
|
||||
this._relayout();
|
||||
},
|
||||
@ -486,55 +562,41 @@ const Overview = new Lang.Class({
|
||||
this.hide();
|
||||
|
||||
let primary = Main.layoutManager.primaryMonitor;
|
||||
let rtl = (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL);
|
||||
|
||||
let contentY = Main.panel.actor.height;
|
||||
let contentHeight = primary.height - contentY - Main.messageTray.actor.height;
|
||||
|
||||
this._group.set_position(primary.x, primary.y);
|
||||
this._group.set_size(primary.width, primary.height);
|
||||
this._overview.set_position(primary.x, primary.y);
|
||||
this._overview.set_size(primary.width, primary.height);
|
||||
|
||||
this._coverPane.set_position(0, contentY);
|
||||
this._coverPane.set_size(primary.width, contentHeight);
|
||||
},
|
||||
|
||||
let searchWidth = this._searchEntry.get_width();
|
||||
let searchHeight = this._searchEntry.get_height();
|
||||
let searchX = (primary.width - searchWidth) / 2;
|
||||
let searchY = contentY + this._spacing;
|
||||
_onRestacked: function() {
|
||||
let stack = global.get_window_actors();
|
||||
let stackIndices = {};
|
||||
|
||||
let dashWidth = DASH_MAX_WIDTH;
|
||||
let dashY = searchY + searchHeight + this._spacing;
|
||||
let dashX;
|
||||
if (rtl) {
|
||||
this._dash.actor.set_anchor_point_from_gravity(Clutter.Gravity.NORTH_EAST);
|
||||
dashX = primary.width;
|
||||
} else {
|
||||
dashX = 0;
|
||||
for (let i = 0; i < stack.length; i++) {
|
||||
// Use the stable sequence for an integer to use as a hash key
|
||||
stackIndices[stack[i].get_meta_window().get_stable_sequence()] = i;
|
||||
}
|
||||
|
||||
let viewX = rtl ? 0 : dashWidth + this._spacing;
|
||||
let viewY = searchY + searchHeight + this._spacing;
|
||||
let viewWidth = primary.width - dashWidth - this._spacing;
|
||||
let viewHeight = contentHeight - this._spacing - viewY;
|
||||
|
||||
this._searchEntry.set_position(searchX, searchY);
|
||||
this._dash.actor.set_position(dashX, dashY);
|
||||
this._viewSelector.actor.set_position(viewX, viewY);
|
||||
this._viewSelector.actor.set_size(viewWidth, viewHeight);
|
||||
this.emit('sync-window-stacking', stackIndices);
|
||||
},
|
||||
|
||||
//// Public methods ////
|
||||
|
||||
beginItemDrag: function(source) {
|
||||
this.emit('item-drag-begin');
|
||||
beginAppDrag: function(source) {
|
||||
this.emit('app-drag-begin');
|
||||
},
|
||||
|
||||
cancelledItemDrag: function(source) {
|
||||
this.emit('item-drag-cancelled');
|
||||
cancelledAppDrag: function(source) {
|
||||
this.emit('app-drag-cancelled');
|
||||
},
|
||||
|
||||
endItemDrag: function(source) {
|
||||
this.emit('item-drag-end');
|
||||
endAppDrag: function(source) {
|
||||
this.emit('app-drag-end');
|
||||
},
|
||||
|
||||
beginWindowDrag: function(source) {
|
||||
@ -558,13 +620,13 @@ const Overview = new Lang.Class({
|
||||
if (this._shown)
|
||||
return;
|
||||
// Do this manually instead of using _syncInputMode, to handle failure
|
||||
if (!Main.pushModal(this._group))
|
||||
if (!Main.pushModal(this._overview))
|
||||
return;
|
||||
this._modal = true;
|
||||
this._animateVisible();
|
||||
this._shown = true;
|
||||
|
||||
this._buttonPressId = this._group.connect('button-press-event',
|
||||
this._buttonPressId = this._overview.connect('button-press-event',
|
||||
Lang.bind(this, this._onButtonPress));
|
||||
},
|
||||
|
||||
@ -608,12 +670,12 @@ const Overview = new Lang.Class({
|
||||
// Disable unredirection while in the overview
|
||||
Meta.disable_unredirect_for_screen(global.screen);
|
||||
global.window_group.hide();
|
||||
this._group.show();
|
||||
this._overview.show();
|
||||
this._background.show();
|
||||
this._viewSelector.show();
|
||||
|
||||
this._group.opacity = 0;
|
||||
Tweener.addTween(this._group,
|
||||
this._overview.opacity = 0;
|
||||
Tweener.addTween(this._overview,
|
||||
{ opacity: 255,
|
||||
transition: 'easeOutQuad',
|
||||
time: ANIMATION_TIME,
|
||||
@ -667,7 +729,7 @@ const Overview = new Lang.Class({
|
||||
this._syncInputMode();
|
||||
|
||||
if (this._buttonPressId > 0)
|
||||
this._group.disconnect(this._buttonPressId);
|
||||
this._overview.disconnect(this._buttonPressId);
|
||||
this._buttonPressId = 0;
|
||||
},
|
||||
|
||||
@ -709,20 +771,20 @@ const Overview = new Lang.Class({
|
||||
|
||||
if (this._shown) {
|
||||
if (!this._modal) {
|
||||
if (Main.pushModal(this._group))
|
||||
if (Main.pushModal(this._overview))
|
||||
this._modal = true;
|
||||
else
|
||||
this.hide();
|
||||
}
|
||||
} else if (this._shownTemporarily) {
|
||||
if (this._modal) {
|
||||
Main.popModal(this._group);
|
||||
Main.popModal(this._overview);
|
||||
this._modal = false;
|
||||
}
|
||||
global.stage_input_mode = Shell.StageInputMode.FULLSCREEN;
|
||||
} else {
|
||||
if (this._modal) {
|
||||
Main.popModal(this._group);
|
||||
Main.popModal(this._overview);
|
||||
this._modal = false;
|
||||
}
|
||||
else if (global.stage_input_mode == Shell.StageInputMode.FULLSCREEN)
|
||||
@ -740,7 +802,7 @@ const Overview = new Lang.Class({
|
||||
this._viewSelector.zoomFromOverview();
|
||||
|
||||
// Make other elements fade out.
|
||||
Tweener.addTween(this._group,
|
||||
Tweener.addTween(this._overview,
|
||||
{ opacity: 0,
|
||||
transition: 'easeOutQuad',
|
||||
time: ANIMATION_TIME,
|
||||
@ -782,7 +844,7 @@ const Overview = new Lang.Class({
|
||||
this._viewSelector.hide();
|
||||
this._desktopFade.hide();
|
||||
this._background.hide();
|
||||
this._group.hide();
|
||||
this._overview.hide();
|
||||
|
||||
this.visible = false;
|
||||
this.animationInProgress = false;
|
||||
|
121
js/ui/panel.js
121
js/ui/panel.js
@ -15,6 +15,7 @@ const Signals = imports.signals;
|
||||
const Atk = imports.gi.Atk;
|
||||
|
||||
|
||||
const CenterLayout = imports.ui.centerLayout;
|
||||
const Config = imports.misc.config;
|
||||
const CtrlAltTab = imports.ui.ctrlAltTab;
|
||||
const DND = imports.ui.dnd;
|
||||
@ -931,12 +932,47 @@ try {
|
||||
log('NMApplet is not supported. It is possible that your NetworkManager version is too old');
|
||||
}
|
||||
|
||||
const PanelLayout = new Lang.Class({
|
||||
Name: 'PanelLayout',
|
||||
Extends: CenterLayout.CenterLayout,
|
||||
|
||||
vfunc_allocate: function(container, box, flags) {
|
||||
this.parent(container, box, flags);
|
||||
|
||||
let availWidth = box.x2 - box.x1;
|
||||
let availHeight = box.y2 - box.y1;
|
||||
|
||||
let [left, center, right, leftCorner, rightCorner] = container.get_children();
|
||||
let childBox = new Clutter.ActorBox();
|
||||
|
||||
let cornerMinWidth, cornerMinHeight;
|
||||
let cornerWidth, cornerHeight;
|
||||
|
||||
[cornerMinWidth, cornerWidth] = leftCorner.get_preferred_width(-1);
|
||||
[cornerMinHeight, cornerHeight] = leftCorner.get_preferred_height(-1);
|
||||
childBox.x1 = 0;
|
||||
childBox.x2 = cornerWidth;
|
||||
childBox.y1 = availHeight;
|
||||
childBox.y2 = availHeight + cornerHeight;
|
||||
leftCorner.allocate(childBox, flags);
|
||||
|
||||
[cornerMinWidth, cornerWidth] = rightCorner.get_preferred_width(-1);
|
||||
[cornerMinHeight, cornerHeight] = rightCorner.get_preferred_height(-1);
|
||||
childBox.x1 = availWidth - cornerWidth;
|
||||
childBox.x2 = availWidth;
|
||||
childBox.y1 = availHeight;
|
||||
childBox.y2 = availHeight + cornerHeight;
|
||||
rightCorner.allocate(childBox, flags);
|
||||
}
|
||||
});
|
||||
|
||||
const Panel = new Lang.Class({
|
||||
Name: 'Panel',
|
||||
|
||||
_init : function() {
|
||||
this.actor = new Shell.GenericContainer({ name: 'panel',
|
||||
reactive: true });
|
||||
this.actor = new St.Widget({ name: 'panel',
|
||||
reactive: true,
|
||||
layoutManager: new PanelLayout() });
|
||||
this.actor._delegate = this;
|
||||
|
||||
this.statusArea = {};
|
||||
@ -961,7 +997,6 @@ const Panel = new Lang.Class({
|
||||
this._leftCorner = new PanelCorner(this._rightBox, St.Side.LEFT);
|
||||
else
|
||||
this._leftCorner = new PanelCorner(this._leftBox, St.Side.LEFT);
|
||||
|
||||
this.actor.add_actor(this._leftCorner.actor);
|
||||
|
||||
if (this.actor.get_text_direction() == Clutter.TextDirection.RTL)
|
||||
@ -970,9 +1005,6 @@ const Panel = new Lang.Class({
|
||||
this._rightCorner = new PanelCorner(this._rightBox, St.Side.RIGHT);
|
||||
this.actor.add_actor(this._rightCorner.actor);
|
||||
|
||||
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('button-press-event', Lang.bind(this, this._onButtonPress));
|
||||
|
||||
Main.layoutManager.panelBox.add(this.actor);
|
||||
@ -983,83 +1015,6 @@ const Panel = new Lang.Class({
|
||||
this._updatePanel();
|
||||
},
|
||||
|
||||
_getPreferredWidth: function(actor, forHeight, alloc) {
|
||||
alloc.min_size = -1;
|
||||
alloc.natural_size = Main.layoutManager.primaryMonitor.width;
|
||||
},
|
||||
|
||||
_getPreferredHeight: function(actor, forWidth, alloc) {
|
||||
// We don't need to implement this; it's forced by the CSS
|
||||
alloc.min_size = -1;
|
||||
alloc.natural_size = -1;
|
||||
},
|
||||
|
||||
_allocate: function(actor, box, flags) {
|
||||
let allocWidth = box.x2 - box.x1;
|
||||
let allocHeight = box.y2 - box.y1;
|
||||
|
||||
let [leftMinWidth, leftNaturalWidth] = this._leftBox.get_preferred_width(-1);
|
||||
let [centerMinWidth, centerNaturalWidth] = this._centerBox.get_preferred_width(-1);
|
||||
let [rightMinWidth, rightNaturalWidth] = this._rightBox.get_preferred_width(-1);
|
||||
|
||||
let sideWidth, centerWidth;
|
||||
centerWidth = centerNaturalWidth;
|
||||
sideWidth = (allocWidth - centerWidth) / 2;
|
||||
|
||||
let childBox = new Clutter.ActorBox();
|
||||
|
||||
childBox.y1 = 0;
|
||||
childBox.y2 = allocHeight;
|
||||
if (this.actor.get_text_direction() == Clutter.TextDirection.RTL) {
|
||||
childBox.x1 = allocWidth - Math.min(Math.floor(sideWidth),
|
||||
leftNaturalWidth);
|
||||
childBox.x2 = allocWidth;
|
||||
} else {
|
||||
childBox.x1 = 0;
|
||||
childBox.x2 = Math.min(Math.floor(sideWidth),
|
||||
leftNaturalWidth);
|
||||
}
|
||||
this._leftBox.allocate(childBox, flags);
|
||||
|
||||
childBox.x1 = Math.ceil(sideWidth);
|
||||
childBox.y1 = 0;
|
||||
childBox.x2 = childBox.x1 + centerWidth;
|
||||
childBox.y2 = allocHeight;
|
||||
this._centerBox.allocate(childBox, flags);
|
||||
|
||||
childBox.y1 = 0;
|
||||
childBox.y2 = allocHeight;
|
||||
if (this.actor.get_text_direction() == Clutter.TextDirection.RTL) {
|
||||
childBox.x1 = 0;
|
||||
childBox.x2 = Math.min(Math.floor(sideWidth),
|
||||
rightNaturalWidth);
|
||||
} else {
|
||||
childBox.x1 = allocWidth - Math.min(Math.floor(sideWidth),
|
||||
rightNaturalWidth);
|
||||
childBox.x2 = allocWidth;
|
||||
}
|
||||
this._rightBox.allocate(childBox, flags);
|
||||
|
||||
let cornerMinWidth, cornerMinHeight;
|
||||
let cornerWidth, cornerHeight;
|
||||
|
||||
[cornerMinWidth, cornerWidth] = this._leftCorner.actor.get_preferred_width(-1);
|
||||
[cornerMinHeight, cornerHeight] = this._leftCorner.actor.get_preferred_height(-1);
|
||||
childBox.x1 = 0;
|
||||
childBox.x2 = cornerWidth;
|
||||
childBox.y1 = allocHeight;
|
||||
childBox.y2 = allocHeight + cornerHeight;
|
||||
this._leftCorner.actor.allocate(childBox, flags);
|
||||
|
||||
[cornerMinWidth, cornerWidth] = this._rightCorner.actor.get_preferred_width(-1);
|
||||
[cornerMinHeight, cornerHeight] = this._rightCorner.actor.get_preferred_height(-1);
|
||||
childBox.x1 = allocWidth - cornerWidth;
|
||||
childBox.x2 = allocWidth;
|
||||
childBox.y1 = allocHeight;
|
||||
childBox.y2 = allocHeight + cornerHeight;
|
||||
this._rightCorner.actor.allocate(childBox, flags);
|
||||
},
|
||||
|
||||
_onButtonPress: function(actor, event) {
|
||||
if (event.get_source() != actor)
|
||||
return false;
|
||||
|
@ -404,9 +404,17 @@ const PopupSeparatorMenuItem = new Lang.Class({
|
||||
this.parent({ reactive: false,
|
||||
can_focus: false});
|
||||
|
||||
this._drawingArea = new St.DrawingArea({ style_class: 'popup-separator-menu-item' });
|
||||
this.addActor(this._drawingArea, { span: -1, expand: true });
|
||||
this._drawingArea.connect('repaint', Lang.bind(this, this._onRepaint));
|
||||
this._separator = new HorzSeparator({ style_class: 'popup-separator-menu-item' });
|
||||
this.addActor(this._separator.actor, { span: -1, expand: true });
|
||||
}
|
||||
});
|
||||
|
||||
const HorzSeparator = new Lang.Class({
|
||||
Name: 'HorzSeparator',
|
||||
|
||||
_init: function (params) {
|
||||
this.actor = new St.DrawingArea(params);
|
||||
this.actor.connect('repaint', Lang.bind(this, this._onRepaint));
|
||||
},
|
||||
|
||||
_onRepaint: function(area) {
|
||||
|
@ -27,17 +27,13 @@ const SearchProviderIface = <interface name="org.gnome.Shell.SearchProvider">
|
||||
<method name="ActivateResult">
|
||||
<arg type="s" direction="in" />
|
||||
</method>
|
||||
<method name="LaunchSearch">
|
||||
<arg type="as" direction="in" />
|
||||
</method>
|
||||
</interface>;
|
||||
|
||||
var SearchProviderProxy = new Gio.DBusProxyClass({
|
||||
Name: 'SearchProviderProxy',
|
||||
Interface: SearchProviderIface,
|
||||
var SearchProviderProxy = Gio.DBusProxy.makeProxyWrapper(SearchProviderIface);
|
||||
|
||||
_init: function(params) {
|
||||
params.g_bus_type = Gio.BusType.SESSION;
|
||||
this.parent(params);
|
||||
}
|
||||
});
|
||||
|
||||
function loadRemoteSearchProviders(addProviderCallback) {
|
||||
let dataDirs = GLib.get_system_data_dirs();
|
||||
@ -97,22 +93,13 @@ function loadRemoteSearchProvidersFromDir(dir, loadedProviders, addProviderCallb
|
||||
icon,
|
||||
busName,
|
||||
objectPath);
|
||||
remoteProvider.initAsync(null, function(obj, result) {
|
||||
try {
|
||||
remoteProvider.initFinish(result);
|
||||
} catch(e) {
|
||||
log('Failed to add search provider "%s": %s'.format(title, e.toString()));
|
||||
return;
|
||||
}
|
||||
|
||||
addProviderCallback(remoteProvider);
|
||||
});
|
||||
|
||||
loadedProviders[objectPath] = remoteProvider;
|
||||
} catch(e) {
|
||||
log('Failed to add search provider "%s": %s'.format(title, e.toString()));
|
||||
continue;
|
||||
}
|
||||
|
||||
addProviderCallback(remoteProvider);
|
||||
}
|
||||
}));
|
||||
|
||||
@ -123,39 +110,12 @@ const RemoteSearchProvider = new Lang.Class({
|
||||
Extends: Search.SearchProvider,
|
||||
|
||||
_init: function(title, icon, dbusName, dbusPath) {
|
||||
this._proxy = new SearchProviderProxy(Gio.DBus.session,
|
||||
dbusName, dbusPath);
|
||||
|
||||
this.parent(title.toUpperCase());
|
||||
|
||||
this._proxy = new SearchProviderProxy({ g_name: dbusName,
|
||||
g_object_path: dbusPath });
|
||||
this._cancellable = new Gio.Cancellable();
|
||||
},
|
||||
|
||||
initAsync: function(cancellable, asyncCallback) {
|
||||
// Can't pass "this" as source object, because RemoteSearchProvider
|
||||
// is not a GObject.Object (and in gjs you can't inherit from a JS
|
||||
// type that in turn inherits from GObject)
|
||||
|
||||
let simpleResult = Gio.SimpleAsyncResult.new(null, asyncCallback, null);
|
||||
simpleResult.set_check_cancellable(cancellable);
|
||||
|
||||
this._proxy.init_async(GLib.PRIORITY_DEFAULT, cancellable, Lang.bind(this, function(proxy, result) {
|
||||
try {
|
||||
proxy.init_finish(result);
|
||||
|
||||
simpleResult.set_op_res_gboolean(true);
|
||||
} catch(e if e instanceof GLib.Error) {
|
||||
simpleResult.set_from_error(e);
|
||||
}
|
||||
|
||||
simpleResult.complete();
|
||||
}));
|
||||
},
|
||||
|
||||
initFinish: function(simpleResult) {
|
||||
if (!simpleResult.propagate_error())
|
||||
return simpleResult.get_op_res_gboolean();
|
||||
|
||||
return false;
|
||||
this.icon = icon;
|
||||
},
|
||||
|
||||
createIcon: function(size, meta) {
|
||||
@ -170,22 +130,13 @@ const RemoteSearchProvider = new Lang.Class({
|
||||
width, height, rowStride, size);
|
||||
}
|
||||
|
||||
// Ugh, but we want to fall back to something ...
|
||||
return new St.Icon({ icon_name: 'text-x-generic',
|
||||
icon_size: size });
|
||||
return null;
|
||||
},
|
||||
|
||||
_getResultsFinished: function(proxy, result) {
|
||||
try {
|
||||
// We rely on a small implementation detail of the
|
||||
// GDBus bindings here: all *Finish are equal
|
||||
|
||||
let [results] = proxy.GetInitialResultSetFinish(result);
|
||||
this.searchSystem.pushResults(this, results);
|
||||
} catch(e) {
|
||||
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
|
||||
log('Received error from search provider %s: %s'.format(this.title, String(e)));
|
||||
}
|
||||
_getResultsFinished: function(results, error) {
|
||||
if (error)
|
||||
return;
|
||||
this.searchSystem.pushResults(this, results[0]);
|
||||
},
|
||||
|
||||
getInitialResultSet: function(terms) {
|
||||
@ -193,8 +144,8 @@ const RemoteSearchProvider = new Lang.Class({
|
||||
this._cancellable.reset();
|
||||
try {
|
||||
this._proxy.GetInitialResultSetRemote(terms,
|
||||
this._cancellable,
|
||||
Lang.bind(this, this._getResultsFinished));
|
||||
Lang.bind(this, this._getResultsFinished),
|
||||
this._cancellable);
|
||||
} catch(e) {
|
||||
log('Error calling GetInitialResultSet for provider %s: %s'.format( this.title, e.toString()));
|
||||
this.searchSystem.pushResults(this, []);
|
||||
@ -206,30 +157,30 @@ const RemoteSearchProvider = new Lang.Class({
|
||||
this._cancellable.reset();
|
||||
try {
|
||||
this._proxy.GetSubsearchResultSetRemote(previousResults, newTerms,
|
||||
this._cancellable,
|
||||
Lang.bind(this, this._getResultsFinished))
|
||||
Lang.bind(this, this._getResultsFinished),
|
||||
this._cancellable);
|
||||
} catch(e) {
|
||||
log('Error calling GetSubsearchResultSet for provider %s: %s'.format(this.title, e.toString()));
|
||||
this.searchSystem.pushResults(this, []);
|
||||
}
|
||||
},
|
||||
|
||||
_getResultMetasFinished: function(proxy, result, callback) {
|
||||
try {
|
||||
let [metas] = results.GetResultMetasFinish(result);
|
||||
let resultMetas = [];
|
||||
for (let i = 0; i < metas.length; i++) {
|
||||
for (let prop in metas[i])
|
||||
metas[i][prop] = metas[i][prop].deep_unpack();
|
||||
resultMetas.push({ id: metas[i]['id'],
|
||||
name: metas[i]['name'],
|
||||
createIcon: Lang.bind(this,
|
||||
this.createIcon, metas[i]) });
|
||||
}
|
||||
callback(resultMetas);
|
||||
} catch(e) {
|
||||
_getResultMetasFinished: function(results, error, callback) {
|
||||
if (error) {
|
||||
callback([]);
|
||||
return;
|
||||
}
|
||||
let metas = results[0];
|
||||
let resultMetas = [];
|
||||
for (let i = 0; i < metas.length; i++) {
|
||||
for (let prop in metas[i])
|
||||
metas[i][prop] = metas[i][prop].deep_unpack();
|
||||
resultMetas.push({ id: metas[i]['id'],
|
||||
name: metas[i]['name'],
|
||||
createIcon: Lang.bind(this,
|
||||
this.createIcon, metas[i]) });
|
||||
}
|
||||
callback(resultMetas);
|
||||
},
|
||||
|
||||
getResultMetas: function(ids, callback) {
|
||||
@ -237,8 +188,8 @@ const RemoteSearchProvider = new Lang.Class({
|
||||
this._cancellable.reset();
|
||||
try {
|
||||
this._proxy.GetResultMetasRemote(ids,
|
||||
this._cancellable,
|
||||
Lang.bind(this, this._getResultMetasFinished, callback));
|
||||
Lang.bind(this, this._getResultMetasFinished, callback),
|
||||
this._cancellable);
|
||||
} catch(e) {
|
||||
log('Error calling GetResultMetas for provider %s: %s'.format(this.title, e.toString()));
|
||||
callback([]);
|
||||
@ -246,7 +197,11 @@ const RemoteSearchProvider = new Lang.Class({
|
||||
},
|
||||
|
||||
activateResult: function(id) {
|
||||
this._proxy.ActivateResultRemote(id, null, null);
|
||||
this._proxy.ActivateResultRemote(id);
|
||||
},
|
||||
|
||||
launchSearch: function(terms) {
|
||||
this._proxy.LaunchSearchRemote(terms);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -418,11 +418,10 @@ const ScreenShield = new Lang.Class({
|
||||
|
||||
this._screenSaverDBus = new ShellDBus.ScreenSaverDBus(this);
|
||||
|
||||
LoginManager.getLoginManager(Lang.bind(this, function(manager) {
|
||||
this._loginSession = manager.getCurrentSessionProxy();
|
||||
this._loginSession.connectSignal('Lock', Lang.bind(this, function() { this.lock(false); }));
|
||||
this._loginSession.connectSignal('Unlock', Lang.bind(this, function() { this.unlock(); }));
|
||||
}));
|
||||
this._loginManager = LoginManager.getLoginManager();
|
||||
this._loginSession = this._loginManager.getCurrentSessionProxy();
|
||||
this._loginSession.connectSignal('Lock', Lang.bind(this, function() { this.lock(false); }));
|
||||
this._loginSession.connectSignal('Unlock', Lang.bind(this, function() { this.unlock(); }));
|
||||
|
||||
this._settings = new Gio.Settings({ schema: SCREENSAVER_SCHEMA });
|
||||
|
||||
@ -876,7 +875,6 @@ const ScreenShieldFallback = new Lang.Class({
|
||||
g_flags: (Gio.DBusProxyFlags.DO_NOT_AUTO_START |
|
||||
Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES),
|
||||
});
|
||||
// This is synchronous but it is the fallback case.
|
||||
this._proxy.init(null);
|
||||
|
||||
this._proxy.connect('g-signal', Lang.bind(this, this._onSignal));
|
||||
|
@ -80,23 +80,15 @@ const PerfHelperIface = <interface name="org.gnome.Shell.PerfHelper">
|
||||
<method name="DestroyWindows" />
|
||||
</interface>;
|
||||
|
||||
const PerfHelper = new Gio.DBusProxyClass({
|
||||
Name: 'PerfHelperProxy',
|
||||
Interface: PerfHelperIface,
|
||||
|
||||
_init: function() {
|
||||
this.parent({ g_bus_type: Gio.BusType.SESSION,
|
||||
g_name: 'org.gnome.Shell.PerfHelper',
|
||||
g_object_path: '/org/gnome/Shell/PerfHelper' });
|
||||
}
|
||||
});
|
||||
var PerfHelperProxy = Gio.DBusProxy.makeProxyWrapper(PerfHelperIface);
|
||||
function PerfHelper() {
|
||||
return new PerfHelperProxy(Gio.DBus.session, 'org.gnome.Shell.PerfHelper', '/org/gnome/Shell/PerfHelper');
|
||||
}
|
||||
|
||||
let _perfHelper = null;
|
||||
function _getPerfHelper() {
|
||||
if (_perfHelper == null) {
|
||||
if (_perfHelper == null)
|
||||
_perfHelper = new PerfHelper();
|
||||
_perfHelper.init(null);
|
||||
}
|
||||
|
||||
return _perfHelper;
|
||||
}
|
||||
@ -119,8 +111,7 @@ function createTestWindow(width, height, alpha, maximized) {
|
||||
let perfHelper = _getPerfHelper();
|
||||
|
||||
perfHelper.CreateWindowRemote(width, height, alpha, maximized,
|
||||
null,
|
||||
function(proxy, result) {
|
||||
function(result, excp) {
|
||||
if (cb)
|
||||
cb();
|
||||
});
|
||||
@ -140,7 +131,7 @@ function waitTestWindows() {
|
||||
let cb;
|
||||
let perfHelper = _getPerfHelper();
|
||||
|
||||
perfHelper.WaitWindowsRemote(null, function(proxy, result) {
|
||||
perfHelper.WaitWindowsRemote(function(result, excp) {
|
||||
if (cb)
|
||||
cb();
|
||||
});
|
||||
@ -163,7 +154,7 @@ function destroyTestWindows() {
|
||||
let cb;
|
||||
let perfHelper = _getPerfHelper();
|
||||
|
||||
perfHelper.DestroyWindowsRemote(null, function(proxy, result) {
|
||||
perfHelper.DestroyWindowsRemote(function(result, excp) {
|
||||
if (cb)
|
||||
cb();
|
||||
});
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const GObject = imports.gi.GObject;
|
||||
const Lang = imports.lang;
|
||||
const Signals = imports.signals;
|
||||
const Shell = imports.gi.Shell;
|
||||
@ -76,8 +75,6 @@ const SearchProvider = new Lang.Class({
|
||||
Name: 'SearchProvider',
|
||||
|
||||
_init: function(title) {
|
||||
this.parent();
|
||||
|
||||
this.title = title;
|
||||
this.searchSystem = null;
|
||||
},
|
||||
@ -166,6 +163,16 @@ const SearchProvider = new Lang.Class({
|
||||
*/
|
||||
activateResult: function(id) {
|
||||
throw new Error('Not implemented');
|
||||
},
|
||||
|
||||
/**
|
||||
* launchSearch:
|
||||
* @terms: Current search terms
|
||||
*
|
||||
* Called when the user clicks the provider icon.
|
||||
*/
|
||||
launchSearch: function(terms) {
|
||||
throw new Error('Not implemented');
|
||||
}
|
||||
});
|
||||
Signals.addSignalMethods(SearchProvider.prototype);
|
||||
@ -264,5 +271,11 @@ const SearchSystem = new Lang.Class({
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
launchSearch: function(provider) {
|
||||
let terms = this.getTerms();
|
||||
provider.launchSearch(terms);
|
||||
Main.overview.toggle();
|
||||
}
|
||||
});
|
||||
Signals.addSignalMethods(SearchSystem.prototype);
|
||||
|
@ -4,25 +4,191 @@ const Clutter = imports.gi.Clutter;
|
||||
const Lang = imports.lang;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Signals = imports.signals;
|
||||
const St = imports.gi.St;
|
||||
const Atk = imports.gi.Atk;
|
||||
|
||||
const AppDisplay = imports.ui.appDisplay;
|
||||
const DND = imports.ui.dnd;
|
||||
const IconGrid = imports.ui.iconGrid;
|
||||
const Main = imports.ui.main;
|
||||
const Overview = imports.ui.overview;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
const Search = imports.ui.search;
|
||||
|
||||
const MAX_SEARCH_RESULTS_ROWS = 1;
|
||||
const MAX_SEARCH_RESULTS_ROWS = 3;
|
||||
const MAX_GRID_SEARCH_RESULTS_ROWS = 1;
|
||||
|
||||
|
||||
const SearchResult = new Lang.Class({
|
||||
Name: 'SearchResult',
|
||||
const ListSearchResult = new Lang.Class({
|
||||
Name: 'ListSearchResult',
|
||||
|
||||
ICON_SIZE: 64,
|
||||
|
||||
_init: function(provider, metaInfo, terms) {
|
||||
this.provider = provider;
|
||||
this.metaInfo = metaInfo;
|
||||
this.actor = new St.Button({ style_class: 'search-result',
|
||||
reactive: true,
|
||||
can_focus: true,
|
||||
track_hover: true,
|
||||
x_align: St.Align.START,
|
||||
x_fill: true,
|
||||
y_fill: true });
|
||||
this.actor._delegate = this;
|
||||
|
||||
let content = new St.BoxLayout({ style_class: 'search-result-content',
|
||||
vertical: false });
|
||||
this._content = content;
|
||||
this.actor.set_child(content);
|
||||
|
||||
// An icon for, or thumbnail of, content
|
||||
let icon = this.metaInfo['createIcon'](this.ICON_SIZE);
|
||||
if (icon) {
|
||||
let iconBin = new St.Bin({ style_class: 'search-result-icon',
|
||||
child: icon });
|
||||
content.add(iconBin);
|
||||
}
|
||||
|
||||
let details = new St.BoxLayout({ style_class: 'search-result-details',
|
||||
vertical: true });
|
||||
content.add(details, { x_fill: true,
|
||||
y_fill: false,
|
||||
x_align: St.Align.START,
|
||||
y_align: St.Align.MIDDLE });
|
||||
|
||||
let title = new St.Label({ style_class: 'search-result-details-title',
|
||||
text: this.metaInfo['name'] })
|
||||
details.add(title, { x_fill: true,
|
||||
y_fill: false,
|
||||
x_align: St.Align.START,
|
||||
y_align: St.Align.START });
|
||||
|
||||
// TODO: could highlight terms in the description here, or should
|
||||
// providers provide what should be highlighted?
|
||||
if (this.metaInfo['description']) {
|
||||
let description = new St.Label({ style_class: 'search-result-details-description',
|
||||
text: this.metaInfo['description'] });
|
||||
details.add(description, { x_fill: false,
|
||||
y_fill: true,
|
||||
x_align: St.Align.START,
|
||||
y_align: St.Align.END });
|
||||
}
|
||||
|
||||
this.actor.connect('clicked', Lang.bind(this, this._onResultClicked));
|
||||
},
|
||||
|
||||
setSelected: function(selected) {
|
||||
if (selected)
|
||||
this.actor.add_style_pseudo_class('selected');
|
||||
else
|
||||
this.actor.remove_style_pseudo_class('selected');
|
||||
},
|
||||
|
||||
activate: function() {
|
||||
this.provider.activateResult(this.metaInfo.id);
|
||||
Main.overview.toggle();
|
||||
},
|
||||
|
||||
_onResultClicked: function(actor) {
|
||||
this.activate();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
const ListSearchResults = new Lang.Class({
|
||||
Name: 'ListSearchResults',
|
||||
Extends: Search.SearchResultDisplay,
|
||||
|
||||
_init: function(provider) {
|
||||
this.parent(provider);
|
||||
|
||||
this.actor = new St.BoxLayout({ style_class: 'results-list',
|
||||
vertical: true });
|
||||
this.actor.connect('notify::width', Lang.bind(this, function() {
|
||||
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() {
|
||||
let results = this.getResultsForDisplay();
|
||||
if (results.length == 0)
|
||||
return;
|
||||
|
||||
provider.getResultMetas(results, Lang.bind(this, this.renderResults));
|
||||
}));
|
||||
}));
|
||||
this._notDisplayedResult = [];
|
||||
this._terms = [];
|
||||
this._pendingClear = false;
|
||||
},
|
||||
|
||||
getResultsForDisplay: function() {
|
||||
let alreadyVisible = this._pendingClear ? 0 : this.getVisibleResultCount();
|
||||
let canDisplay = MAX_SEARCH_RESULTS_ROWS - alreadyVisible;
|
||||
|
||||
let numResults = Math.min(this._notDisplayedResult.length, canDisplay);
|
||||
|
||||
return this._notDisplayedResult.splice(0, numResults);
|
||||
},
|
||||
|
||||
getVisibleResultCount: function() {
|
||||
return this.actor.get_n_children();
|
||||
},
|
||||
|
||||
hasMoreResults: function() {
|
||||
return this._notDisplayedResult.length > 0;
|
||||
},
|
||||
|
||||
setResults: function(results, terms) {
|
||||
// copy the lists
|
||||
this._notDisplayedResult = results.slice(0);
|
||||
this._terms = terms.slice(0);
|
||||
this._pendingClear = true;
|
||||
},
|
||||
|
||||
renderResults: function(metas) {
|
||||
for (let i = 0; i < metas.length; i++) {
|
||||
let display = new ListSearchResult(this.provider, metas[i], this._terms);
|
||||
this.addItem(display.actor);
|
||||
|
||||
display.actor.connect('key-focus-in', Lang.bind(this, this._onFocusedProviderChanged));
|
||||
}
|
||||
},
|
||||
|
||||
clear: function () {
|
||||
this.actor.destroy_all_children();
|
||||
this._pendingClear = false;
|
||||
},
|
||||
|
||||
getFirstResult: function() {
|
||||
if (this.getVisibleResultCount() > 0)
|
||||
return this.getItemAtIndex(0)._delegate;
|
||||
else
|
||||
return null;
|
||||
},
|
||||
|
||||
addItem: function(actor, index) {
|
||||
if (index !== undefined)
|
||||
this.actor.insert_child_at_index(actor, index);
|
||||
else
|
||||
this.actor.add_actor(actor);
|
||||
},
|
||||
|
||||
getItemAtIndex: function(index) {
|
||||
return this.actor.get_child_at_index(index);
|
||||
},
|
||||
|
||||
_onFocusedProviderChanged: function() {
|
||||
this.emit('focused-provider-changed');
|
||||
}
|
||||
});
|
||||
Signals.addSignalMethods(ListSearchResults.prototype);
|
||||
|
||||
|
||||
const GridSearchResult = new Lang.Class({
|
||||
Name: 'GridSearchResult',
|
||||
|
||||
_init: function(provider, metaInfo, terms) {
|
||||
this.provider = provider;
|
||||
this.metaInfo = metaInfo;
|
||||
this.actor = new St.Button({ style_class: 'grid-search-result',
|
||||
reactive: true,
|
||||
x_align: St.Align.START,
|
||||
y_fill: true });
|
||||
@ -31,7 +197,7 @@ const SearchResult = new Lang.Class({
|
||||
|
||||
let content = provider.createResultActor(metaInfo, terms);
|
||||
if (content == null) {
|
||||
content = new St.Bin({ style_class: 'search-result-content',
|
||||
content = new St.Bin({ style_class: 'grid-search-result-content',
|
||||
reactive: true,
|
||||
can_focus: true,
|
||||
track_hover: true,
|
||||
@ -45,7 +211,7 @@ const SearchResult = new Lang.Class({
|
||||
if (content._delegate && content._delegate.getDragActorSource)
|
||||
this._dragActorSource = content._delegate.getDragActorSource();
|
||||
}
|
||||
this._content = content;
|
||||
this.content = content;
|
||||
this.actor.set_child(content);
|
||||
|
||||
this.actor.connect('clicked', Lang.bind(this, this._onResultClicked));
|
||||
@ -53,23 +219,23 @@ const SearchResult = new Lang.Class({
|
||||
let draggable = DND.makeDraggable(this.actor);
|
||||
draggable.connect('drag-begin',
|
||||
Lang.bind(this, function() {
|
||||
Main.overview.beginItemDrag(this);
|
||||
Main.overview.beginAppDrag(this);
|
||||
}));
|
||||
draggable.connect('drag-cancelled',
|
||||
Lang.bind(this, function() {
|
||||
Main.overview.cancelledItemDrag(this);
|
||||
Main.overview.cancelledAppDrag(this);
|
||||
}));
|
||||
draggable.connect('drag-end',
|
||||
Lang.bind(this, function() {
|
||||
Main.overview.endItemDrag(this);
|
||||
Main.overview.endAppDrag(this);
|
||||
}));
|
||||
},
|
||||
|
||||
setSelected: function(selected) {
|
||||
if (selected)
|
||||
this._content.add_style_pseudo_class('selected');
|
||||
this.content.add_style_pseudo_class('selected');
|
||||
else
|
||||
this._content.remove_style_pseudo_class('selected');
|
||||
this.content.remove_style_pseudo_class('selected');
|
||||
},
|
||||
|
||||
activate: function() {
|
||||
@ -85,7 +251,7 @@ const SearchResult = new Lang.Class({
|
||||
if (this._dragActorSource)
|
||||
return this._dragActorSource;
|
||||
// not exactly right, but alignment problems are hard to notice
|
||||
return this._content;
|
||||
return this.content;
|
||||
},
|
||||
|
||||
getDragActor: function(stageX, stageY) {
|
||||
@ -108,11 +274,11 @@ const GridSearchResults = new Lang.Class({
|
||||
_init: function(provider, grid) {
|
||||
this.parent(provider);
|
||||
|
||||
this._grid = grid || new IconGrid.IconGrid({ rowLimit: MAX_SEARCH_RESULTS_ROWS,
|
||||
this._grid = grid || new IconGrid.IconGrid({ rowLimit: MAX_GRID_SEARCH_RESULTS_ROWS,
|
||||
xAlign: St.Align.START });
|
||||
this.actor = new St.Bin({ x_align: St.Align.START });
|
||||
|
||||
this.actor = new St.Bin({ x_align: St.Align.MIDDLE });
|
||||
this.actor.set_child(this._grid.actor);
|
||||
|
||||
this._width = 0;
|
||||
this.actor.connect('notify::width', Lang.bind(this, function() {
|
||||
this._width = this.actor.width;
|
||||
@ -130,6 +296,7 @@ const GridSearchResults = new Lang.Class({
|
||||
},
|
||||
|
||||
getResultsForDisplay: function() {
|
||||
this._grid.actor.ensure_style();
|
||||
let alreadyVisible = this._pendingClear ? 0 : this._grid.visibleItemsCount();
|
||||
let canDisplay = this._grid.childrenInRow(this._width) * this._grid.getRowLimit()
|
||||
- alreadyVisible;
|
||||
@ -143,6 +310,10 @@ const GridSearchResults = new Lang.Class({
|
||||
return this._grid.visibleItemsCount();
|
||||
},
|
||||
|
||||
hasMoreResults: function() {
|
||||
return this._notDisplayedResult.length > 0;
|
||||
},
|
||||
|
||||
setResults: function(results, terms) {
|
||||
// copy the lists
|
||||
this._notDisplayedResult = results.slice(0);
|
||||
@ -152,8 +323,10 @@ const GridSearchResults = new Lang.Class({
|
||||
|
||||
renderResults: function(metas) {
|
||||
for (let i = 0; i < metas.length; i++) {
|
||||
let display = new SearchResult(this.provider, metas[i], this._terms);
|
||||
let display = new GridSearchResult(this.provider, metas[i], this._terms);
|
||||
this._grid.addItem(display.actor);
|
||||
|
||||
display.content.connect('key-focus-in', Lang.bind(this, this._onFocusedProviderChanged));
|
||||
}
|
||||
},
|
||||
|
||||
@ -167,11 +340,17 @@ const GridSearchResults = new Lang.Class({
|
||||
return this._grid.getItemAtIndex(0)._delegate;
|
||||
else
|
||||
return null;
|
||||
},
|
||||
|
||||
_onFocusedProviderChanged: function() {
|
||||
this.emit('focused-provider-changed');
|
||||
}
|
||||
});
|
||||
Signals.addSignalMethods(GridSearchResults.prototype);
|
||||
|
||||
const SearchResults = new Lang.Class({
|
||||
Name: 'SearchResults',
|
||||
|
||||
const SearchDisplay = new Lang.Class({
|
||||
Name: 'SearchDisplay',
|
||||
|
||||
_init: function(searchSystem) {
|
||||
this._searchSystem = searchSystem;
|
||||
@ -222,19 +401,43 @@ const SearchResults = new Lang.Class({
|
||||
createProviderMeta: function(provider) {
|
||||
let providerBox = new St.BoxLayout({ style_class: 'search-section',
|
||||
vertical: true });
|
||||
let title = new St.Label({ style_class: 'search-section-header',
|
||||
text: provider.title });
|
||||
providerBox.add(title, { x_fill: false, x_align: St.Align.START });
|
||||
let providerBoxContent = new St.BoxLayout({ style_class: 'search-section-content' });
|
||||
let isAppsProvider = (provider instanceof AppDisplay.AppSearchProvider);
|
||||
|
||||
let providerIcon;
|
||||
if (!isAppsProvider) {
|
||||
let separator = new PopupMenu.HorzSeparator({ style_class: 'search-section-separator' });
|
||||
providerBox.add(separator.actor, { expand: true });
|
||||
|
||||
providerIcon = new ProviderIcon(provider);
|
||||
providerIcon.connect('launch-search', Lang.bind(this, function(providerIcon) {
|
||||
this._searchSystem.launchSearch(providerIcon.provider);
|
||||
}));
|
||||
providerBoxContent.add(providerIcon.actor, { x_fill: false,
|
||||
y_fill: false,
|
||||
x_align: St.Align.START,
|
||||
y_align: St.Align.START });
|
||||
}
|
||||
|
||||
let resultDisplayBin = new St.Bin({ style_class: 'search-section-results',
|
||||
x_fill: true,
|
||||
y_fill: true });
|
||||
providerBox.add(resultDisplayBin, { expand: true });
|
||||
let resultDisplay = new GridSearchResults(provider);
|
||||
providerBoxContent.add(resultDisplayBin, { expand: true });
|
||||
|
||||
providerBox.add(providerBoxContent);
|
||||
|
||||
let resultDisplay;
|
||||
if (isAppsProvider)
|
||||
resultDisplay = new GridSearchResults(provider);
|
||||
else
|
||||
resultDisplay = new ListSearchResults(provider);
|
||||
|
||||
resultDisplay.connect('focused-provider-changed', Lang.bind(this, this._updateProviderIconCanFocus));
|
||||
resultDisplayBin.set_child(resultDisplay.actor);
|
||||
|
||||
this._providerMeta.push({ provider: provider,
|
||||
actor: providerBox,
|
||||
icon: providerIcon,
|
||||
resultDisplay: resultDisplay });
|
||||
this._content.add(providerBox);
|
||||
},
|
||||
@ -255,6 +458,7 @@ const SearchResults = new Lang.Class({
|
||||
let meta = this._providerMeta[i];
|
||||
meta.resultDisplay.clear();
|
||||
meta.actor.hide();
|
||||
if (meta.icon) meta.icon.actor.can_focus = false;
|
||||
}
|
||||
},
|
||||
|
||||
@ -262,6 +466,7 @@ const SearchResults = new Lang.Class({
|
||||
let meta = this._metaForProvider(provider);
|
||||
meta.resultDisplay.clear();
|
||||
meta.actor.hide();
|
||||
if (meta.icon) meta.icon.actor.can_focus = false;
|
||||
},
|
||||
|
||||
reset: function() {
|
||||
@ -284,6 +489,11 @@ const SearchResults = new Lang.Class({
|
||||
return this._providerMeta[this._providers.indexOf(provider)];
|
||||
},
|
||||
|
||||
_metaForProvidersExcept: function(provider) {
|
||||
let skip = this._providers.indexOf(provider);
|
||||
return this._providerMeta.filter(function(meta, index) { return index != skip }, this);
|
||||
},
|
||||
|
||||
_maybeSetInitialSelection: function() {
|
||||
let newDefaultResult = null;
|
||||
|
||||
@ -341,6 +551,9 @@ const SearchResults = new Lang.Class({
|
||||
meta.resultDisplay.setResults(providerResults, terms);
|
||||
let results = meta.resultDisplay.getResultsForDisplay();
|
||||
|
||||
if (meta.icon)
|
||||
meta.icon.moreIcon.visible = meta.resultDisplay.hasMoreResults();
|
||||
|
||||
provider.getResultMetas(results, Lang.bind(this, function(metas) {
|
||||
this._clearDisplayForProvider(provider);
|
||||
meta.actor.show();
|
||||
@ -374,6 +587,15 @@ const SearchResults = new Lang.Class({
|
||||
this._defaultResult.setSelected(highlight);
|
||||
},
|
||||
|
||||
_updateProviderIconCanFocus: function(resultDisplay) {
|
||||
let meta = this._metaForProvider(resultDisplay.provider);
|
||||
if (meta.icon)
|
||||
meta.icon.actor.can_focus = true;
|
||||
|
||||
let others = this._metaForProvidersExcept(resultDisplay.provider);
|
||||
others.forEach(function(meta) { if (meta.icon) meta.icon.actor.can_focus = false; });
|
||||
},
|
||||
|
||||
navigateFocus: function(direction) {
|
||||
let rtl = this.actor.get_text_direction() == Clutter.TextDirection.RTL;
|
||||
if (direction == Gtk.DirectionType.TAB_BACKWARD ||
|
||||
@ -393,3 +615,65 @@ const SearchResults = new Lang.Class({
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const ProviderIcon = new Lang.Class({
|
||||
Name: 'ProviderIcon',
|
||||
|
||||
PROVIDER_ICON_SIZE: 48,
|
||||
|
||||
MORE_ICON_SIZE: 16,
|
||||
|
||||
_init: function(provider) {
|
||||
this.provider = provider;
|
||||
|
||||
this.actor = new St.Button({ style_class: 'search-section-icon-bin',
|
||||
reactive: true,
|
||||
track_hover: true });
|
||||
this.actor.connect('clicked', Lang.bind(this, this._onIconClicked));
|
||||
|
||||
this._content = new St.Widget({ layout_manager: new Clutter.BinLayout() });
|
||||
this.actor.set_child(this._content);
|
||||
|
||||
let rtl = (this.actor.get_text_direction() == Clutter.TextDirection.RTL);
|
||||
|
||||
this.moreIcon = new St.Icon({ style_class: 'search-section-icon-more',
|
||||
icon_size: this.MORE_ICON_SIZE,
|
||||
icon_name: 'list-add-symbolic',
|
||||
visible: false,
|
||||
x_align: rtl ? Clutter.ActorAlign.START : Clutter.ActorAlign.END,
|
||||
y_align: Clutter.ActorAlign.END,
|
||||
// HACK: without these, ClutterBinLayout
|
||||
// ignores alignment properties on the actor
|
||||
x_expand: true,
|
||||
y_expand: true });
|
||||
|
||||
this._iconBin = new St.Bin({ style_class: 'search-section-icon',
|
||||
width: this.PROVIDER_ICON_SIZE,
|
||||
height: this.PROVIDER_ICON_SIZE });
|
||||
|
||||
this._content.add_actor(this._iconBin);
|
||||
this._content.add_actor(this.moreIcon);
|
||||
|
||||
this._createProviderIcon();
|
||||
},
|
||||
|
||||
_createProviderIcon: function() {
|
||||
let icon = new St.Icon({ icon_size: this.PROVIDER_ICON_SIZE });
|
||||
|
||||
if (this.provider.icon)
|
||||
icon.gicon = this.provider.icon;
|
||||
else
|
||||
icon.icon_name = 'application-x-executable';
|
||||
|
||||
this._iconBin.set_child(icon);
|
||||
},
|
||||
|
||||
activate: function() {
|
||||
this.emit('launch-search');
|
||||
},
|
||||
|
||||
_onIconClicked: function(actor) {
|
||||
this.activate();
|
||||
}
|
||||
});
|
||||
Signals.addSignalMethods(ProviderIcon.prototype);
|
||||
|
@ -67,16 +67,14 @@ const ScreenSaverIface = <interface name="org.gnome.ScreenSaver">
|
||||
</signal>
|
||||
</interface>;
|
||||
|
||||
const GnomeShell = new Gio.DBusImplementerClass({
|
||||
const GnomeShell = new Lang.Class({
|
||||
Name: 'GnomeShellDBus',
|
||||
Interface: GnomeShellIface,
|
||||
|
||||
_init: function() {
|
||||
this.parent();
|
||||
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(GnomeShellIface, this);
|
||||
this._dbusImpl.export(Gio.DBus.session, '/org/gnome/Shell');
|
||||
|
||||
this.export(Gio.DBus.session, '/org/gnome/Shell');
|
||||
|
||||
this._extensionsService = new GnomeShellExtensions();
|
||||
this._extensionsSerivce = new GnomeShellExtensions();
|
||||
},
|
||||
|
||||
/**
|
||||
@ -238,14 +236,12 @@ const GnomeShellExtensionsIface = <interface name="org.gnome.Shell.Extensions">
|
||||
<property name="ShellVersion" type="s" access="read" />
|
||||
</interface>;
|
||||
|
||||
const GnomeShellExtensions = new Gio.DBusImplementerClass({
|
||||
const GnomeShellExtensions = new Lang.Class({
|
||||
Name: 'GnomeShellExtensionsDBus',
|
||||
Interface: GnomeShellExtensionsIface,
|
||||
|
||||
_init: function() {
|
||||
this.parent();
|
||||
|
||||
this.export(Gio.DBus.session, '/org/gnome/Shell');
|
||||
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(GnomeShellExtensionsIface, this);
|
||||
this._dbusImpl.export(Gio.DBus.session, '/org/gnome/Shell');
|
||||
ExtensionSystem.connect('extension-state-changed',
|
||||
Lang.bind(this, this._extensionStateChanged));
|
||||
},
|
||||
@ -339,23 +335,25 @@ const GnomeShellExtensions = new Gio.DBusImplementerClass({
|
||||
ShellVersion: Config.PACKAGE_VERSION,
|
||||
|
||||
_extensionStateChanged: function(_, newState) {
|
||||
this.emit_signal('ExtensionStatusChanged', newState.uuid, newState.state, newState.error);
|
||||
this._dbusImpl.emit_signal('ExtensionStatusChanged',
|
||||
GLib.Variant.new('(sis)', [newState.uuid, newState.state, newState.error]));
|
||||
}
|
||||
});
|
||||
|
||||
const ScreenSaverDBus = new Gio.DBusImplementerClass({
|
||||
const ScreenSaverDBus = new Lang.Class({
|
||||
Name: 'ScreenSaverDBus',
|
||||
Interface: ScreenSaverIface,
|
||||
|
||||
_init: function(screenShield) {
|
||||
this.parent();
|
||||
|
||||
this._screenShield = screenShield;
|
||||
screenShield.connect('lock-status-changed', Lang.bind(this, function(shield) {
|
||||
this.emit_signal('ActiveChanged', shield.locked);
|
||||
this._dbusImpl.emit_signal('ActiveChanged', GLib.Variant.new('(b)', [shield.locked]));
|
||||
}));
|
||||
|
||||
this.export(Gio.DBus.session, '/org/gnome/ScreenSaver');
|
||||
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(ScreenSaverIface, this);
|
||||
this._dbusImpl.export(Gio.DBus.session, '/org/gnome/ScreenSaver');
|
||||
|
||||
Gio.DBus.session.own_name('org.gnome.ScreenSaver', Gio.BusNameOwnerFlags.REPLACE, null, null);
|
||||
},
|
||||
|
||||
|
@ -554,16 +554,14 @@ const ShellMountOperationType = {
|
||||
SHOW_PROCESSES: 3
|
||||
};
|
||||
|
||||
const GnomeShellMountOpHandler = new Gio.DBusImplementerClass({
|
||||
const GnomeShellMountOpHandler = new Lang.Class({
|
||||
Name: 'GnomeShellMountOpHandler',
|
||||
Interface: GnomeShellMountOpIface,
|
||||
|
||||
_init: function() {
|
||||
this.parent();
|
||||
|
||||
this.export(Gio.DBus.session, '/org/gtk/MountOperationHandler');
|
||||
Gio.DBus.session.own_name('org.gtk.MountOperationHandler',
|
||||
Gio.BusNameOwnerFlags.REPLACE, null, null);
|
||||
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(GnomeShellMountOpIface, this);
|
||||
this._dbusImpl.export(Gio.DBus.session, '/org/gtk/MountOperationHandler');
|
||||
Gio.bus_own_name_on_connection(Gio.DBus.session, 'org.gtk.MountOperationHandler',
|
||||
Gio.BusNameOwnerFlags.REPLACE, null, null);
|
||||
|
||||
this._dialog = null;
|
||||
this._volumeMonitor = Gio.VolumeMonitor.get();
|
||||
|
@ -1629,44 +1629,7 @@ const NMApplet = new Lang.Class({
|
||||
this.secondaryIcon = this.addIcon(new Gio.ThemedIcon({ name: 'network-vpn-symbolic' }));
|
||||
this.secondaryIcon.hide();
|
||||
|
||||
// Device types
|
||||
this._dtypes = { };
|
||||
this._dtypes[NetworkManager.DeviceType.ETHERNET] = NMDeviceWired;
|
||||
this._dtypes[NetworkManager.DeviceType.WIFI] = NMDeviceWireless;
|
||||
this._dtypes[NetworkManager.DeviceType.MODEM] = NMDeviceModem;
|
||||
this._dtypes[NetworkManager.DeviceType.BT] = NMDeviceBluetooth;
|
||||
// TODO: WiMax support
|
||||
|
||||
// Connection types
|
||||
this._ctypes = { };
|
||||
this._ctypes[NetworkManager.SETTING_WIRELESS_SETTING_NAME] = NMConnectionCategory.WIRELESS;
|
||||
this._ctypes[NetworkManager.SETTING_WIRED_SETTING_NAME] = NMConnectionCategory.WIRED;
|
||||
this._ctypes[NetworkManager.SETTING_PPPOE_SETTING_NAME] = NMConnectionCategory.WIRED;
|
||||
this._ctypes[NetworkManager.SETTING_PPP_SETTING_NAME] = NMConnectionCategory.WIRED;
|
||||
this._ctypes[NetworkManager.SETTING_BLUETOOTH_SETTING_NAME] = NMConnectionCategory.WWAN;
|
||||
this._ctypes[NetworkManager.SETTING_CDMA_SETTING_NAME] = NMConnectionCategory.WWAN;
|
||||
this._ctypes[NetworkManager.SETTING_GSM_SETTING_NAME] = NMConnectionCategory.WWAN;
|
||||
this._ctypes[NetworkManager.SETTING_VPN_SETTING_NAME] = NMConnectionCategory.VPN;
|
||||
|
||||
NMClient.Client.new_async(null, Lang.bind(this, this._clientGot));
|
||||
NMClient.RemoteSettings.new_async(null, null, Lang.bind(this, this._remoteSettingsGot));
|
||||
},
|
||||
|
||||
_clientGot: function(obj, result) {
|
||||
this._client = NMClient.Client.new_finish(result);
|
||||
|
||||
this._tryLateInit();
|
||||
},
|
||||
|
||||
_remoteSettingsGot: function(obj, result) {
|
||||
this._settings = NMClient.RemoteSettings.new_finish(result);
|
||||
|
||||
this._tryLateInit();
|
||||
},
|
||||
|
||||
_tryLateInit: function() {
|
||||
if (!this._client || !this._settings)
|
||||
return;
|
||||
this._client = NMClient.Client.new();
|
||||
|
||||
this._statusSection = new PopupMenu.PopupMenuSection();
|
||||
this._statusItem = new PopupMenu.PopupMenuItem('', { reactive: false });
|
||||
@ -1727,17 +1690,44 @@ const NMApplet = new Lang.Class({
|
||||
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
||||
this.menu.addSettingsAction(_("Network Settings"), 'gnome-network-panel.desktop');
|
||||
|
||||
this._readConnections();
|
||||
this._readDevices();
|
||||
this._syncNMState();
|
||||
// Device types
|
||||
this._dtypes = { };
|
||||
this._dtypes[NetworkManager.DeviceType.ETHERNET] = NMDeviceWired;
|
||||
this._dtypes[NetworkManager.DeviceType.WIFI] = NMDeviceWireless;
|
||||
this._dtypes[NetworkManager.DeviceType.MODEM] = NMDeviceModem;
|
||||
this._dtypes[NetworkManager.DeviceType.BT] = NMDeviceBluetooth;
|
||||
// TODO: WiMax support
|
||||
|
||||
this._client.connect('notify::manager-running', Lang.bind(this, this._syncNMState));
|
||||
this._client.connect('notify::networking-enabled', Lang.bind(this, this._syncNMState));
|
||||
this._client.connect('notify::state', Lang.bind(this, this._syncNMState));
|
||||
this._client.connect('notify::active-connections', Lang.bind(this, this._updateIcon));
|
||||
this._client.connect('device-added', Lang.bind(this, this._deviceAdded));
|
||||
this._client.connect('device-removed', Lang.bind(this, this._deviceRemoved));
|
||||
this._settings.connect('new-connection', Lang.bind(this, this._newConnection));
|
||||
// Connection types
|
||||
this._ctypes = { };
|
||||
this._ctypes[NetworkManager.SETTING_WIRELESS_SETTING_NAME] = NMConnectionCategory.WIRELESS;
|
||||
this._ctypes[NetworkManager.SETTING_WIRED_SETTING_NAME] = NMConnectionCategory.WIRED;
|
||||
this._ctypes[NetworkManager.SETTING_PPPOE_SETTING_NAME] = NMConnectionCategory.WIRED;
|
||||
this._ctypes[NetworkManager.SETTING_PPP_SETTING_NAME] = NMConnectionCategory.WIRED;
|
||||
this._ctypes[NetworkManager.SETTING_BLUETOOTH_SETTING_NAME] = NMConnectionCategory.WWAN;
|
||||
this._ctypes[NetworkManager.SETTING_CDMA_SETTING_NAME] = NMConnectionCategory.WWAN;
|
||||
this._ctypes[NetworkManager.SETTING_GSM_SETTING_NAME] = NMConnectionCategory.WWAN;
|
||||
this._ctypes[NetworkManager.SETTING_VPN_SETTING_NAME] = NMConnectionCategory.VPN;
|
||||
|
||||
this._settings = NMClient.RemoteSettings.new(null);
|
||||
this._connectionsReadId = this._settings.connect('connections-read', Lang.bind(this, function() {
|
||||
this._readConnections();
|
||||
this._readDevices();
|
||||
this._syncNMState();
|
||||
|
||||
// Connect to signals late so that early signals don't find in inconsistent state
|
||||
// and connect only once (this signal handler can be called again if NetworkManager goes up and down)
|
||||
if (!this._inited) {
|
||||
this._inited = true;
|
||||
this._client.connect('notify::manager-running', Lang.bind(this, this._syncNMState));
|
||||
this._client.connect('notify::networking-enabled', Lang.bind(this, this._syncNMState));
|
||||
this._client.connect('notify::state', Lang.bind(this, this._syncNMState));
|
||||
this._client.connect('notify::active-connections', Lang.bind(this, this._updateIcon));
|
||||
this._client.connect('device-added', Lang.bind(this, this._deviceAdded));
|
||||
this._client.connect('device-removed', Lang.bind(this, this._deviceRemoved));
|
||||
this._settings.connect('new-connection', Lang.bind(this, this._newConnection));
|
||||
}
|
||||
}));
|
||||
},
|
||||
|
||||
_ensureSource: function() {
|
||||
|
@ -1,7 +1,6 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Lang = imports.lang;
|
||||
const St = imports.gi.St;
|
||||
|
||||
@ -46,16 +45,7 @@ const PowerManagerInterface = <interface name="org.gnome.SettingsDaemon.Power">
|
||||
<property name="Icon" type="s" access="read" />
|
||||
</interface>;
|
||||
|
||||
const PowerManagerProxy = new Gio.DBusProxyClass({
|
||||
Name: 'PowerManagerProxy',
|
||||
Interface: PowerManagerInterface,
|
||||
|
||||
_init: function() {
|
||||
this.parent({ g_bus_type: Gio.BusType.SESSION,
|
||||
g_name: BUS_NAME,
|
||||
g_object_path: OBJECT_PATH });
|
||||
}
|
||||
});
|
||||
const PowerManagerProxy = Gio.DBusProxy.makeProxyWrapper(PowerManagerInterface);
|
||||
|
||||
const Indicator = new Lang.Class({
|
||||
Name: 'PowerIndicator',
|
||||
@ -64,7 +54,7 @@ const Indicator = new Lang.Class({
|
||||
_init: function() {
|
||||
this.parent('battery-missing-symbolic', _("Battery"));
|
||||
|
||||
this._proxy = new PowerManagerProxy();
|
||||
this._proxy = new PowerManagerProxy(Gio.DBus.session, BUS_NAME, OBJECT_PATH);
|
||||
|
||||
this._deviceItems = [ ];
|
||||
this._hasPrimary = false;
|
||||
@ -83,26 +73,18 @@ const Indicator = new Lang.Class({
|
||||
|
||||
this._proxy.connect('g-properties-changed',
|
||||
Lang.bind(this, this._devicesChanged));
|
||||
this._proxy.init_async(GLib.PRIORITY_DEFAULT, null, Lang.bind(this, function(proxy, result) {
|
||||
proxy.init_finish(result);
|
||||
|
||||
this._devicesChanged();
|
||||
}));
|
||||
this._devicesChanged();
|
||||
},
|
||||
|
||||
_readPrimaryDevice: function() {
|
||||
this._proxy.GetPrimaryDeviceRemote(null, Lang.bind(this, function(proxy, result) {
|
||||
let device_id, device_type, icon, percentage, state, seconds;
|
||||
try {
|
||||
[[device_id, device_type, icon, percentage, state, seconds]] =
|
||||
proxy.GetPrimaryDeviceFinish(result);
|
||||
} catch(e) {
|
||||
this._proxy.GetPrimaryDeviceRemote(Lang.bind(this, function(result, error) {
|
||||
if (error) {
|
||||
this._hasPrimary = false;
|
||||
this._primaryDeviceId = null;
|
||||
this._batteryItem.actor.hide();
|
||||
return;
|
||||
}
|
||||
|
||||
let [[device_id, device_type, icon, percentage, state, seconds]] = result;
|
||||
if (device_type == UPDeviceType.BATTERY) {
|
||||
this._hasPrimary = true;
|
||||
let time = Math.round(seconds / 60);
|
||||
@ -139,18 +121,16 @@ const Indicator = new Lang.Class({
|
||||
},
|
||||
|
||||
_readOtherDevices: function() {
|
||||
this._proxy.GetDevicesRemote(null, Lang.bind(this, function(proxy, result) {
|
||||
this._proxy.GetDevicesRemote(Lang.bind(this, function(result, error) {
|
||||
this._deviceItems.forEach(function(i) { i.destroy(); });
|
||||
this._deviceItems = [];
|
||||
|
||||
let devices;
|
||||
try {
|
||||
[devices] = proxy.GetDevicesFinish(result);
|
||||
} catch(e) {
|
||||
if (error) {
|
||||
return;
|
||||
}
|
||||
|
||||
let position = 0;
|
||||
let [devices] = result;
|
||||
for (let i = 0; i < devices.length; i++) {
|
||||
let [device_id, device_type] = devices[i];
|
||||
if (device_type == UPDeviceType.AC_POWER || device_id == this._primaryDeviceId)
|
||||
|
@ -195,12 +195,8 @@ const IMStatusChooserItem = new Lang.Class({
|
||||
Lang.bind(this, this._changeIMStatus));
|
||||
|
||||
this._presence = new GnomeSession.Presence();
|
||||
this._presence.init_async(GLib.PRIORITY_DEFAULT, null, Lang.bind(this, function(obj, result) {
|
||||
obj.init_finish(result);
|
||||
|
||||
this._presence.connectSignal('StatusChanged', Lang.bind(this, function(proxy, senderName, [status]) {
|
||||
this._sessionStatusChanged(status);
|
||||
}));
|
||||
this._presence.connectSignal('StatusChanged', Lang.bind(this, function(proxy, senderName, [status]) {
|
||||
this._sessionStatusChanged(status);
|
||||
}));
|
||||
|
||||
this._sessionPresenceRestored = false;
|
||||
@ -484,33 +480,14 @@ const UserMenuButton = new Lang.Class({
|
||||
this._userManager = AccountsService.UserManager.get_default();
|
||||
|
||||
this._user = this._userManager.get_user(GLib.get_user_name());
|
||||
|
||||
this._presence = new GnomeSession.Presence();
|
||||
this._presence.init_async(GLib.PRIORITY_DEFAULT, null, Lang.bind(this, function(proxy, result) {
|
||||
proxy.init_finish(result);
|
||||
|
||||
this._updateSwitch(this._presence.status);
|
||||
this._presence.connectSignal('StatusChanged', Lang.bind(this, function (proxy, senderName, [status]) {
|
||||
this._updateSwitch(status);
|
||||
}));
|
||||
}));
|
||||
|
||||
let session = new GnomeSession.SessionManager();
|
||||
session.init_async(GLib.PRIORITY_DEFAULT, null, Lang.bind(this, function(proxy, result) {
|
||||
// This should never fail.
|
||||
proxy.init_finish(result);
|
||||
|
||||
this._session = proxy;
|
||||
this._updateHaveShutdown();
|
||||
}));
|
||||
this._session = new GnomeSession.SessionManager();
|
||||
this._haveShutdown = true;
|
||||
this._haveSuspend = true;
|
||||
|
||||
this._accountMgr = Tp.AccountManager.dup();
|
||||
|
||||
LoginManager.getLoginManager(Lang.bind(this, function(manager) {
|
||||
this._loginManager = manager;
|
||||
}));
|
||||
this._loginManager = LoginManager.getLoginManager();
|
||||
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
|
||||
|
||||
this._iconBox = new St.Bin();
|
||||
@ -556,6 +533,11 @@ const UserMenuButton = new Lang.Class({
|
||||
|
||||
this._createSubMenu();
|
||||
|
||||
this._updateSwitch(this._presence.status);
|
||||
this._presence.connectSignal('StatusChanged', Lang.bind(this, function (proxy, senderName, [status]) {
|
||||
this._updateSwitch(status);
|
||||
}));
|
||||
|
||||
this._userManager.connect('notify::is-loaded',
|
||||
Lang.bind(this, this._updateMultiUser));
|
||||
this._userManager.connect('notify::has-multiple-users',
|
||||
@ -655,29 +637,17 @@ const UserMenuButton = new Lang.Class({
|
||||
},
|
||||
|
||||
_updateHaveShutdown: function() {
|
||||
if (!this._session) {
|
||||
this._haveShutdown = false;
|
||||
return;
|
||||
}
|
||||
|
||||
this._session.CanShutdownRemote(null, Lang.bind(this, function(proxy, result) {
|
||||
try {
|
||||
[this._haveShutdown] = proxy.CanShutdownFinish(result);
|
||||
} catch(e) {
|
||||
this._haveShutdown = false;
|
||||
}
|
||||
|
||||
this._updateInstallUpdates();
|
||||
this._updateSuspendOrPowerOff();
|
||||
}));
|
||||
this._session.CanShutdownRemote(Lang.bind(this,
|
||||
function(result, error) {
|
||||
if (!error) {
|
||||
this._haveShutdown = result[0];
|
||||
this._updateInstallUpdates();
|
||||
this._updateSuspendOrPowerOff();
|
||||
}
|
||||
}));
|
||||
},
|
||||
|
||||
_updateHaveSuspend: function() {
|
||||
if (!this._loginManager) {
|
||||
this._haveSuspend = false;
|
||||
return;
|
||||
}
|
||||
|
||||
this._loginManager.canSuspend(Lang.bind(this,
|
||||
function(result) {
|
||||
this._haveSuspend = result;
|
||||
@ -867,17 +837,14 @@ const UserMenuButton = new Lang.Class({
|
||||
|
||||
_onQuitSessionActivate: function() {
|
||||
Main.overview.hide();
|
||||
|
||||
if (this._session)
|
||||
this._session.LogoutRemote(0, null, null);
|
||||
this._session.LogoutRemote(0);
|
||||
},
|
||||
|
||||
_onInstallUpdatesActivate: function() {
|
||||
Main.overview.hide();
|
||||
Util.spawn(['pkexec', '/usr/libexec/pk-trigger-offline-update']);
|
||||
|
||||
if (this._haveShutdown)
|
||||
this._session.RebootRemote(null, null);
|
||||
this._session.RebootRemote();
|
||||
},
|
||||
|
||||
_onSuspendOrPowerOffActivate: function() {
|
||||
@ -885,8 +852,8 @@ const UserMenuButton = new Lang.Class({
|
||||
|
||||
if (this._haveShutdown &&
|
||||
this._suspendOrPowerOffItem.state == PopupMenu.PopupAlternatingMenuItemState.DEFAULT) {
|
||||
this._session.ShutdownRemote(null, null);
|
||||
} else if (this._haveSuspend) {
|
||||
this._session.ShutdownRemote();
|
||||
} else {
|
||||
if (this._screenSaverSettings.get_boolean(LOCK_ENABLED_KEY)) {
|
||||
let tmpId = Main.screenShield.connect('lock-screen-shown', Lang.bind(this, function() {
|
||||
Main.screenShield.disconnect(tmpId);
|
||||
|
@ -52,7 +52,7 @@ const ViewSelector = new Lang.Class({
|
||||
|
||||
this._activePage = null;
|
||||
|
||||
this.active = false;
|
||||
this.entryNonEmpty = false;
|
||||
this._searchPending = false;
|
||||
this._searchTimeoutId = 0;
|
||||
|
||||
@ -90,7 +90,7 @@ const ViewSelector = new Lang.Class({
|
||||
this._appsPage = this._addPage(this._appDisplay.actor, null,
|
||||
_("Applications"), 'system-run-symbolic');
|
||||
|
||||
this._searchResults = new SearchDisplay.SearchResults(this._searchSystem);
|
||||
this._searchResults = new SearchDisplay.SearchDisplay(this._searchSystem);
|
||||
this._searchPage = this._addPage(this._searchResults.actor, this._entry,
|
||||
_("Search"), 'edit-find-symbolic');
|
||||
|
||||
@ -114,9 +114,6 @@ const ViewSelector = new Lang.Class({
|
||||
|
||||
global.focus_manager.add_group(this._searchResults.actor);
|
||||
|
||||
Main.overview.connect('item-drag-begin',
|
||||
Lang.bind(this, this._resetShowAppsButton));
|
||||
|
||||
this._stageKeyPressId = 0;
|
||||
Main.overview.connect('showing', Lang.bind(this,
|
||||
function () {
|
||||
@ -133,17 +130,6 @@ const ViewSelector = new Lang.Class({
|
||||
}
|
||||
}));
|
||||
|
||||
// Public constraints which may be used to tie actors' height or
|
||||
// vertical position to the current tab's content; as the content's
|
||||
// height and position depend on the view selector's style properties
|
||||
// (e.g. font size, padding, spacing, ...) it would be extremely hard
|
||||
// and ugly to get these from the outside. While it would be possible
|
||||
// to use position and height properties directly, outside code would
|
||||
// need to ensure that the content is properly allocated before
|
||||
// accessing the properties.
|
||||
this.constrainHeight = new Clutter.BindConstraint({ source: this._pageArea,
|
||||
coordinate: Clutter.BindCoordinate.HEIGHT });
|
||||
|
||||
global.display.add_keybinding('toggle-application-view',
|
||||
new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }),
|
||||
Meta.KeyBindingFlags.NONE,
|
||||
@ -230,7 +216,9 @@ const ViewSelector = new Lang.Class({
|
||||
},
|
||||
|
||||
_onShowAppsButtonToggled: function() {
|
||||
if (this.active)
|
||||
this.emit('apps-button-checked', this._showAppsButton.checked);
|
||||
|
||||
if (this.entryNonEmpty)
|
||||
this.reset();
|
||||
else
|
||||
this._showPage(this._showAppsButton.checked ? this._appsPage
|
||||
@ -246,7 +234,7 @@ const ViewSelector = new Lang.Class({
|
||||
let symbol = event.get_key_symbol();
|
||||
|
||||
if (symbol == Clutter.Escape) {
|
||||
if (this.active)
|
||||
if (this.entryNonEmpty)
|
||||
this.reset();
|
||||
else if (this._showAppsButton.checked)
|
||||
this._resetShowAppsButton();
|
||||
@ -254,9 +242,9 @@ const ViewSelector = new Lang.Class({
|
||||
Main.overview.hide();
|
||||
return true;
|
||||
} else if (Clutter.keysym_to_unicode(symbol) ||
|
||||
(symbol == Clutter.BackSpace && this.active)) {
|
||||
(symbol == Clutter.BackSpace && this.entryNonEmpty)) {
|
||||
this.startSearch(event);
|
||||
} else if (!this.active) {
|
||||
} else if (!this.entryNonEmpty) {
|
||||
if (symbol == Clutter.Tab || symbol == Clutter.Down) {
|
||||
this._activePage.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
|
||||
return true;
|
||||
@ -269,6 +257,7 @@ const ViewSelector = new Lang.Class({
|
||||
},
|
||||
|
||||
_searchCancelled: function() {
|
||||
this.emit('search-cancelled');
|
||||
this._showPage(this._showAppsButton.checked ? this._appsPage
|
||||
: this._workspacesPage);
|
||||
|
||||
@ -330,13 +319,14 @@ const ViewSelector = new Lang.Class({
|
||||
},
|
||||
|
||||
_onTextChanged: function (se, prop) {
|
||||
let searchPreviouslyActive = this.active;
|
||||
this.active = this._entry.get_text() != '';
|
||||
this._searchPending = this.active && !searchPreviouslyActive;
|
||||
let searchPreviouslyActive = this.entryNonEmpty;
|
||||
this.entryNonEmpty = this._entry.get_text() != '';
|
||||
this._searchPending = this.entryNonEmpty && !searchPreviouslyActive;
|
||||
if (this._searchPending) {
|
||||
this._searchResults.startingSearch();
|
||||
}
|
||||
if (this.active) {
|
||||
if (this.entryNonEmpty) {
|
||||
this.emit('search-begin');
|
||||
this._entry.set_secondary_icon(this._activeIcon);
|
||||
|
||||
if (this._iconClickedId == 0) {
|
||||
@ -353,7 +343,7 @@ const ViewSelector = new Lang.Class({
|
||||
this._entry.set_secondary_icon(this._inactiveIcon);
|
||||
this._searchCancelled();
|
||||
}
|
||||
if (!this.active) {
|
||||
if (!this.entryNonEmpty) {
|
||||
if (this._searchTimeoutId > 0) {
|
||||
Mainloop.source_remove(this._searchTimeoutId);
|
||||
this._searchTimeoutId = 0;
|
||||
@ -381,7 +371,7 @@ const ViewSelector = new Lang.Class({
|
||||
}
|
||||
this._searchResults.activateDefault();
|
||||
return true;
|
||||
} else if (this.active) {
|
||||
} else if (this.entryNonEmpty) {
|
||||
let arrowNext, nextDirection;
|
||||
if (entry.get_text_direction() == Clutter.TextDirection.RTL) {
|
||||
arrowNext = Clutter.Left;
|
||||
|
@ -1073,6 +1073,9 @@ const Workspace = new Lang.Class({
|
||||
* ANIMATE - Indicates that we need animate changing position.
|
||||
*/
|
||||
positionWindows: function(flags) {
|
||||
if (this.leavingOverview)
|
||||
return;
|
||||
|
||||
this._positionWindowsFlags |= flags;
|
||||
|
||||
if (this._positionWindowsId > 0)
|
||||
|
@ -493,6 +493,7 @@ const ThumbnailsBox = new Lang.Class({
|
||||
_init: function() {
|
||||
this.actor = new Shell.GenericContainer({ reactive: true,
|
||||
style_class: 'workspace-thumbnails',
|
||||
can_focus: true,
|
||||
request_mode: Clutter.RequestMode.WIDTH_FOR_HEIGHT });
|
||||
this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
|
||||
this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
|
||||
@ -526,6 +527,8 @@ const ThumbnailsBox = new Lang.Class({
|
||||
this._dropPlaceholder = new St.Bin({ style_class: 'placeholder' });
|
||||
this.actor.add_actor(this._dropPlaceholder);
|
||||
|
||||
this.visible = true;
|
||||
|
||||
this._targetScale = 0;
|
||||
this._scale = 0;
|
||||
this._pendingScaleUpdate = false;
|
||||
@ -541,12 +544,21 @@ const ThumbnailsBox = new Lang.Class({
|
||||
|
||||
this.actor.connect('button-press-event', function() { return true; });
|
||||
this.actor.connect('button-release-event', Lang.bind(this, this._onButtonRelease));
|
||||
this.actor.connect('scroll-event',
|
||||
Lang.bind(this, this._onScrollEvent));
|
||||
this.actor.connect('key-release-event',
|
||||
Lang.bind(this, this._onKeyRelease));
|
||||
|
||||
Main.overview.connect('item-drag-begin',
|
||||
Main.overview.connect('showing',
|
||||
Lang.bind(this, this._createThumbnails));
|
||||
Main.overview.connect('hidden',
|
||||
Lang.bind(this, this._destroyThumbnails));
|
||||
|
||||
Main.overview.connect('app-drag-begin',
|
||||
Lang.bind(this, this._onDragBegin));
|
||||
Main.overview.connect('item-drag-end',
|
||||
Main.overview.connect('app-drag-end',
|
||||
Lang.bind(this, this._onDragEnd));
|
||||
Main.overview.connect('item-drag-cancelled',
|
||||
Main.overview.connect('app-drag-cancelled',
|
||||
Lang.bind(this, this._onDragCancelled));
|
||||
Main.overview.connect('window-drag-begin',
|
||||
Lang.bind(this, this._onDragBegin));
|
||||
@ -719,10 +731,16 @@ const ThumbnailsBox = new Lang.Class({
|
||||
}
|
||||
},
|
||||
|
||||
show: function() {
|
||||
_createThumbnails: function() {
|
||||
this._switchWorkspaceNotifyId =
|
||||
global.window_manager.connect('switch-workspace',
|
||||
Lang.bind(this, this._activeWorkspaceChanged));
|
||||
this._nWorkspacesNotifyId =
|
||||
global.screen.connect('notify::n-workspaces',
|
||||
Lang.bind(this, this._workspacesChanged));
|
||||
this._syncStackingId =
|
||||
Main.overview.connect('sync-window-stacking',
|
||||
Lang.bind(this, this.syncStacking));
|
||||
|
||||
this._targetScale = 0;
|
||||
this._scale = 0;
|
||||
@ -746,17 +764,86 @@ const ThumbnailsBox = new Lang.Class({
|
||||
this.addThumbnails(0, global.screen.n_workspaces);
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
_destroyThumbnails: function() {
|
||||
if (this._switchWorkspaceNotifyId > 0) {
|
||||
global.window_manager.disconnect(this._switchWorkspaceNotifyId);
|
||||
this._switchWorkspaceNotifyId = 0;
|
||||
}
|
||||
if (this._nWorkspacesNotifyId > 0) {
|
||||
global.screen.disconnect(this._nWorkspacesNotifyId);
|
||||
this._nWorkspacesNotifyId = 0;
|
||||
}
|
||||
if (this._syncStackingId > 0) {
|
||||
Main.overview.disconnect(this._syncStackingId);
|
||||
this._syncStackingId = 0;
|
||||
}
|
||||
|
||||
for (let w = 0; w < this._thumbnails.length; w++)
|
||||
this._thumbnails[w].destroy();
|
||||
this._thumbnails = [];
|
||||
},
|
||||
|
||||
_computeThumbnailsX: function() {
|
||||
this._targetX = this.actor.get_x();
|
||||
|
||||
let rtl = (this.actor.get_text_direction() == Clutter.TextDirection.RTL);
|
||||
|
||||
if (rtl)
|
||||
this._hiddenX = -this.actor.width;
|
||||
else
|
||||
this._hiddenX = this._targetX + this.actor.width;
|
||||
},
|
||||
|
||||
show: function() {
|
||||
if (this.visible)
|
||||
return;
|
||||
|
||||
this.visible = true;
|
||||
|
||||
this.actor.show();
|
||||
Tweener.addTween(this.actor, { translation_x: this._targetX,
|
||||
transition: 'easeOutQuad',
|
||||
time: SLIDE_ANIMATION_TIME
|
||||
});
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
if (!this.visible)
|
||||
return;
|
||||
|
||||
this.visible = false;
|
||||
|
||||
Tweener.addTween(this.actor, { translation_x: this._hiddenX,
|
||||
transition: 'easeOutQuad',
|
||||
time: SLIDE_ANIMATION_TIME,
|
||||
onComplete: Lang.bind(this, function () {
|
||||
this.actor.hide();
|
||||
})
|
||||
});
|
||||
},
|
||||
|
||||
_workspacesChanged: function() {
|
||||
let oldNumWorkspaces = this._thumbnails.length;
|
||||
let newNumWorkspaces = global.screen.n_workspaces;
|
||||
let active = global.screen.get_active_workspace_index();
|
||||
|
||||
if (newNumWorkspaces > oldNumWorkspaces) {
|
||||
this.addThumbnails(oldNumWorkspaces, newNumWorkspaces - oldNumWorkspaces);
|
||||
} else {
|
||||
let removedIndex;
|
||||
let removedNum = oldNumWorkspaces - newNumWorkspaces;
|
||||
for (let w = 0; w < oldNumWorkspaces; w++) {
|
||||
let metaWorkspace = global.screen.get_workspace_by_index(w);
|
||||
if (this._thumbnails[w].metaWorkspace != metaWorkspace) {
|
||||
removedIndex = w;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.removeThumbnails(removedIndex, removedNum);
|
||||
}
|
||||
},
|
||||
|
||||
addThumbnails: function(start, count) {
|
||||
for (let k = start; k < start + count; k++) {
|
||||
let metaWorkspace = global.screen.get_workspace_by_index(k);
|
||||
@ -802,7 +889,7 @@ const ThumbnailsBox = new Lang.Class({
|
||||
this._queueUpdateStates();
|
||||
},
|
||||
|
||||
syncStacking: function(stackIndices) {
|
||||
syncStacking: function(actor, stackIndices) {
|
||||
for (let i = 0; i < this._thumbnails.length; i++)
|
||||
this._thumbnails[i].syncStacking(stackIndices);
|
||||
},
|
||||
@ -924,6 +1011,8 @@ const ThumbnailsBox = new Lang.Class({
|
||||
onCompleteScope: this
|
||||
});
|
||||
});
|
||||
|
||||
this._computeThumbnailsX();
|
||||
},
|
||||
|
||||
_queueUpdateStates: function() {
|
||||
@ -1157,5 +1246,30 @@ const ThumbnailsBox = new Lang.Class({
|
||||
},
|
||||
onCompleteScope: this
|
||||
});
|
||||
},
|
||||
|
||||
_onScrollEvent: function (actor, event) {
|
||||
switch (event.get_scroll_direction()) {
|
||||
case Clutter.ScrollDirection.UP:
|
||||
Main.wm.actionMoveWorkspace(Meta.MotionDirection.UP);
|
||||
break;
|
||||
case Clutter.ScrollDirection.DOWN:
|
||||
Main.wm.actionMoveWorkspace(Meta.MotionDirection.DOWN);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
_onKeyRelease: function (actor, event) {
|
||||
switch (event.get_key_symbol()) {
|
||||
case Clutter.KEY_Up:
|
||||
Main.wm.actionMoveWorkspace(Meta.MotionDirection.UP);
|
||||
break;
|
||||
case Clutter.KEY_Down:
|
||||
Main.wm.actionMoveWorkspace(Meta.MotionDirection.DOWN);
|
||||
break;
|
||||
case Clutter.KEY_Return:
|
||||
Main.overview.toggle();
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -22,8 +22,6 @@ const MAX_WORKSPACES = 16;
|
||||
|
||||
const OVERRIDE_SCHEMA = 'org.gnome.shell.overrides';
|
||||
|
||||
const CONTROLS_POP_IN_TIME = 0.1;
|
||||
|
||||
|
||||
const WorkspacesView = new Lang.Class({
|
||||
Name: 'WorkspacesView',
|
||||
@ -106,9 +104,9 @@ const WorkspacesView = new Lang.Class({
|
||||
global.window_manager.connect('switch-workspace',
|
||||
Lang.bind(this, this._activeWorkspaceChanged));
|
||||
|
||||
this._itemDragBeginId = Main.overview.connect('item-drag-begin',
|
||||
this._appDragBeginId = Main.overview.connect('app-drag-begin',
|
||||
Lang.bind(this, this._dragBegin));
|
||||
this._itemDragEndId = Main.overview.connect('item-drag-end',
|
||||
this._appDragEndId = Main.overview.connect('app-drag-end',
|
||||
Lang.bind(this, this._dragEnd));
|
||||
this._windowDragBeginId = Main.overview.connect('window-drag-begin',
|
||||
Lang.bind(this, this._dragBegin));
|
||||
@ -327,13 +325,13 @@ const WorkspacesView = new Lang.Class({
|
||||
if (this._inDrag)
|
||||
this._dragEnd();
|
||||
|
||||
if (this._itemDragBeginId > 0) {
|
||||
Main.overview.disconnect(this._itemDragBeginId);
|
||||
this._itemDragBeginId = 0;
|
||||
if (this._appDragBeginId > 0) {
|
||||
Main.overview.disconnect(this._appDragBeginId);
|
||||
this._appDragBeginId = 0;
|
||||
}
|
||||
if (this._itemDragEndId > 0) {
|
||||
Main.overview.disconnect(this._itemDragEndId);
|
||||
this._itemDragEndId = 0;
|
||||
if (this._appDragEndId > 0) {
|
||||
Main.overview.disconnect(this._appDragEndId);
|
||||
this._appDragEndId = 0;
|
||||
}
|
||||
if (this._windowDragBeginId > 0) {
|
||||
Main.overview.disconnect(this._windowDragBeginId);
|
||||
@ -460,25 +458,8 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
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',
|
||||
request_mode: Clutter.RequestMode.WIDTH_FOR_HEIGHT,
|
||||
y_align: St.Align.START,
|
||||
y_fill: true });
|
||||
this._controls = controls;
|
||||
this.actor.add_actor(controls);
|
||||
|
||||
controls.reactive = true;
|
||||
controls.track_hover = true;
|
||||
controls.connect('notify::hover',
|
||||
Lang.bind(this, this._onControlsHoverChanged));
|
||||
controls.connect('scroll-event',
|
||||
Lang.bind(this, this._onScrollEvent));
|
||||
|
||||
this._primaryIndex = Main.layoutManager.primaryIndex;
|
||||
|
||||
this._thumbnailsBox = new WorkspaceThumbnail.ThumbnailsBox();
|
||||
controls.add_actor(this._thumbnailsBox.actor);
|
||||
|
||||
this._workspacesViews = null;
|
||||
this._primaryScrollAdjustment = null;
|
||||
|
||||
@ -491,34 +472,14 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
this._inDrag = false;
|
||||
this._cancelledDrag = false;
|
||||
|
||||
this._controlsInitiallyHovered = false;
|
||||
this._alwaysZoomOut = false;
|
||||
this._zoomOut = false;
|
||||
this._zoomFraction = 0;
|
||||
|
||||
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(){
|
||||
this._alwaysZoomOut = true;
|
||||
}));
|
||||
|
||||
Main.xdndHandler.connect('drag-end', Lang.bind(this, function(){
|
||||
this._alwaysZoomOut = false;
|
||||
this._updateAlwaysZoom();
|
||||
}));
|
||||
|
||||
global.screen.connect('notify::n-workspaces',
|
||||
Lang.bind(this, this._workspacesChanged));
|
||||
|
||||
this._switchWorkspaceNotifyId = 0;
|
||||
|
||||
this._itemDragBeginId = 0;
|
||||
this._itemDragCancelledId = 0;
|
||||
this._itemDragEndId = 0;
|
||||
this._appDragBeginId = 0;
|
||||
this._appDragCancelledId = 0;
|
||||
this._appDragEndId = 0;
|
||||
this._windowDragBeginId = 0;
|
||||
this._windowDragCancelledId = 0;
|
||||
this._windowDragEndId = 0;
|
||||
@ -538,41 +499,20 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
},
|
||||
|
||||
show: function() {
|
||||
if(!this._alwaysZoomOut) {
|
||||
let [mouseX, mouseY] = global.get_pointer();
|
||||
let [x, y] = this._controls.get_transformed_position();
|
||||
let [width, height] = this._controls.get_transformed_size();
|
||||
let visibleWidth = this._controls.get_theme_node().get_length('visible-width');
|
||||
let rtl = (Clutter.get_default_text_direction () == Clutter.TextDirection.RTL);
|
||||
if(rtl)
|
||||
x = x + width - visibleWidth;
|
||||
if(mouseX > x - 0.5 && mouseX < x + visibleWidth + 0.5 &&
|
||||
mouseY > y - 0.5 && mouseY < y + height + 0.5)
|
||||
this._controlsInitiallyHovered = true;
|
||||
}
|
||||
|
||||
this._zoomOut = this._alwaysZoomOut;
|
||||
this._zoomFraction = this._alwaysZoomOut ? 1 : 0;
|
||||
this._updateZoom();
|
||||
|
||||
this._controls.show();
|
||||
this._thumbnailsBox.show();
|
||||
this._updateSwitcherVisibility();
|
||||
|
||||
this._updateWorkspacesViews();
|
||||
|
||||
this._restackedNotifyId =
|
||||
global.screen.connect('restacked',
|
||||
Main.overview.connect('sync-window-stacking',
|
||||
Lang.bind(this, this._onRestacked));
|
||||
|
||||
if (this._itemDragBeginId == 0)
|
||||
this._itemDragBeginId = Main.overview.connect('item-drag-begin',
|
||||
if (this._appDragBeginId == 0)
|
||||
this._appDragBeginId = Main.overview.connect('app-drag-begin',
|
||||
Lang.bind(this, this._dragBegin));
|
||||
if (this._itemDragCancelledId == 0)
|
||||
this._itemDragCancelledId = Main.overview.connect('item-drag-cancelled',
|
||||
if (this._appDragCancelledId == 0)
|
||||
this._appDragCancelledId = Main.overview.connect('app-drag-cancelled',
|
||||
Lang.bind(this, this._dragCancelled));
|
||||
if (this._itemDragEndId == 0)
|
||||
this._itemDragEndId = Main.overview.connect('item-drag-end',
|
||||
if (this._appDragEndId == 0)
|
||||
this._appDragEndId = Main.overview.connect('app-drag-end',
|
||||
Lang.bind(this, this._dragEnd));
|
||||
if (this._windowDragBeginId == 0)
|
||||
this._windowDragBeginId = Main.overview.connect('window-drag-begin',
|
||||
@ -583,8 +523,6 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
if (this._windowDragEndId == 0)
|
||||
this._windowDragEndId = Main.overview.connect('window-drag-end',
|
||||
Lang.bind(this, this._dragEnd));
|
||||
|
||||
this._onRestacked();
|
||||
},
|
||||
|
||||
zoomFromOverview: function() {
|
||||
@ -594,27 +532,21 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
this._controls.hide();
|
||||
this._thumbnailsBox.hide();
|
||||
|
||||
if (!this._alwaysZoomOut)
|
||||
this.zoomFraction = 0;
|
||||
|
||||
if (this._restackedNotifyId > 0){
|
||||
global.screen.disconnect(this._restackedNotifyId);
|
||||
Main.overview.disconnect(this._restackedNotifyId);
|
||||
this._restackedNotifyId = 0;
|
||||
}
|
||||
if (this._itemDragBeginId > 0) {
|
||||
Main.overview.disconnect(this._itemDragBeginId);
|
||||
this._itemDragBeginId = 0;
|
||||
if (this._appDragBeginId > 0) {
|
||||
Main.overview.disconnect(this._appDragBeginId);
|
||||
this._appDragBeginId = 0;
|
||||
}
|
||||
if (this._itemDragCancelledId > 0) {
|
||||
Main.overview.disconnect(this._itemDragCancelledId);
|
||||
this._itemDragCancelledId = 0;
|
||||
if (this._appDragCancelledId > 0) {
|
||||
Main.overview.disconnect(this._appDragCancelledId);
|
||||
this._appDragCancelledId = 0;
|
||||
}
|
||||
if (this._itemDragEndId > 0) {
|
||||
Main.overview.disconnect(this._itemDragEndId);
|
||||
this._itemDragEndId = 0;
|
||||
if (this._appDragEndId > 0) {
|
||||
Main.overview.disconnect(this._appDragEndId);
|
||||
this._appDragEndId = 0;
|
||||
}
|
||||
if (this._windowDragBeginId > 0) {
|
||||
Main.overview.disconnect(this._windowDragBeginId);
|
||||
@ -745,73 +677,15 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
return this._getPrimaryView().getActiveWorkspace().hasMaximizedWindows();
|
||||
},
|
||||
|
||||
// zoomFraction property allows us to tween the controls sliding in and out
|
||||
set zoomFraction(fraction) {
|
||||
this._zoomFraction = fraction;
|
||||
this.actor.queue_relayout();
|
||||
},
|
||||
|
||||
get zoomFraction() {
|
||||
return this._zoomFraction;
|
||||
},
|
||||
|
||||
_updateAlwaysZoom: function() {
|
||||
// Always show the pager if workspaces are actually used,
|
||||
// e.g. there are windows on more than one
|
||||
this._alwaysZoomOut = global.screen.n_workspaces > 2;
|
||||
|
||||
if (this._alwaysZoomOut)
|
||||
return;
|
||||
|
||||
let monitors = Main.layoutManager.monitors;
|
||||
let primary = Main.layoutManager.primaryMonitor;
|
||||
|
||||
/* Look for any monitor to the right of the primary, if there is
|
||||
* one, we always keep zoom out, otherwise its hard to reach
|
||||
* the thumbnail area without passing into the next monitor. */
|
||||
for (let i = 0; i < monitors.length; i++) {
|
||||
if (monitors[i].x >= primary.x + primary.width) {
|
||||
this._alwaysZoomOut = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_getPreferredWidth: function (actor, forHeight, alloc) {
|
||||
// pass through the call in case the child needs it, but report 0x0
|
||||
this._controls.get_preferred_width(forHeight);
|
||||
},
|
||||
|
||||
_getPreferredHeight: function (actor, forWidth, alloc) {
|
||||
// pass through the call in case the child needs it, but report 0x0
|
||||
this._controls.get_preferred_height(forWidth);
|
||||
},
|
||||
|
||||
_allocate: function (actor, box, flags) {
|
||||
let childBox = new Clutter.ActorBox();
|
||||
|
||||
let totalWidth = box.x2 - box.x1;
|
||||
|
||||
// width of the controls
|
||||
let [controlsMin, controlsNatural] = this._controls.get_preferred_width(box.y2 - box.y1);
|
||||
|
||||
// Amount of space on the screen we reserve for the visible control
|
||||
let controlsVisible = this._controls.get_theme_node().get_length('visible-width');
|
||||
let controlsReserved = controlsVisible * (1 - this._zoomFraction) + controlsNatural * this._zoomFraction;
|
||||
|
||||
let rtl = (Clutter.get_default_text_direction () == Clutter.TextDirection.RTL);
|
||||
if (rtl) {
|
||||
childBox.x2 = controlsReserved;
|
||||
childBox.x1 = childBox.x2 - controlsNatural;
|
||||
} else {
|
||||
childBox.x1 = totalWidth - controlsReserved;
|
||||
childBox.x2 = childBox.x1 + controlsNatural;
|
||||
}
|
||||
|
||||
childBox.y1 = 0;
|
||||
childBox.y2 = box.y2- box.y1;
|
||||
this._controls.allocate(childBox, flags);
|
||||
|
||||
this._updateWorkspacesGeometry();
|
||||
},
|
||||
|
||||
@ -851,24 +725,15 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
let width = fullWidth;
|
||||
let height = fullHeight;
|
||||
|
||||
let [controlsMin, controlsNatural] = this._controls.get_preferred_width(height);
|
||||
let controlsVisible = this._controls.get_theme_node().get_length('visible-width');
|
||||
|
||||
let [x, y] = this.actor.get_transformed_position();
|
||||
|
||||
let rtl = (Clutter.get_default_text_direction () == Clutter.TextDirection.RTL);
|
||||
|
||||
let clipWidth = width - controlsVisible;
|
||||
let clipWidth = width;
|
||||
let clipHeight = fullHeight;
|
||||
let clipX = rtl ? x + controlsVisible : x;
|
||||
let clipX = x;
|
||||
let clipY = y + (fullHeight - clipHeight) / 2;
|
||||
|
||||
let widthAdjust = this._zoomOut ? controlsNatural : controlsVisible;
|
||||
widthAdjust += Main.overview._spacing;
|
||||
width -= widthAdjust;
|
||||
if (rtl)
|
||||
x += widthAdjust;
|
||||
|
||||
let monitors = Main.layoutManager.monitors;
|
||||
let m = 0;
|
||||
for (let i = 0; i < monitors.length; i++) {
|
||||
@ -891,25 +756,12 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
}
|
||||
},
|
||||
|
||||
_onRestacked: function() {
|
||||
let stack = global.get_window_actors();
|
||||
let stackIndices = {};
|
||||
|
||||
for (let i = 0; i < stack.length; i++) {
|
||||
// Use the stable sequence for an integer to use as a hash key
|
||||
stackIndices[stack[i].get_meta_window().get_stable_sequence()] = i;
|
||||
}
|
||||
|
||||
_onRestacked: function(actor, stackIndices) {
|
||||
for (let i = 0; i < this._workspacesViews.length; i++)
|
||||
this._workspacesViews[i].syncStacking(stackIndices);
|
||||
|
||||
this._thumbnailsBox.syncStacking(stackIndices);
|
||||
},
|
||||
|
||||
_workspacesChanged: function() {
|
||||
this._updateAlwaysZoom();
|
||||
this._updateZoom();
|
||||
|
||||
if (this._workspacesViews == null)
|
||||
return;
|
||||
|
||||
@ -934,8 +786,6 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
}
|
||||
m++;
|
||||
}
|
||||
|
||||
this._thumbnailsBox.addThumbnails(oldNumWorkspaces, newNumWorkspaces - oldNumWorkspaces);
|
||||
} else {
|
||||
// Assume workspaces are only removed sequentially
|
||||
// (e.g. 2,3,4 - not 2,4,7)
|
||||
@ -958,8 +808,6 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
lostWorkspaces[l].destroy();
|
||||
}
|
||||
}
|
||||
|
||||
this._thumbnailsBox.removeThumbnails(removedIndex, removedNum);
|
||||
}
|
||||
|
||||
for (let i = 0; i < this._workspacesViews.length; i++)
|
||||
@ -968,35 +816,6 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
this._updateSwitcherVisibility();
|
||||
},
|
||||
|
||||
_updateZoom : function() {
|
||||
if (Main.overview.animationInProgress)
|
||||
return;
|
||||
|
||||
let shouldZoom = this._alwaysZoomOut || this._controls.hover;
|
||||
if (shouldZoom != this._zoomOut) {
|
||||
this._zoomOut = shouldZoom;
|
||||
this._updateWorkspacesGeometry();
|
||||
|
||||
if (!this._workspacesViews)
|
||||
return;
|
||||
|
||||
Tweener.addTween(this,
|
||||
{ zoomFraction: this._zoomOut ? 1 : 0,
|
||||
time: WORKSPACE_SWITCH_TIME,
|
||||
transition: 'easeOutQuad' });
|
||||
|
||||
for (let i = 0; i < this._workspacesViews.length; i++)
|
||||
this._workspacesViews[i].updateWindowPositions();
|
||||
}
|
||||
},
|
||||
|
||||
_onControlsHoverChanged: function() {
|
||||
if(!this._controls.hover)
|
||||
this._controlsInitiallyHovered = false;
|
||||
if(!this._controlsInitiallyHovered)
|
||||
this._updateZoom();
|
||||
},
|
||||
|
||||
_dragBegin: function() {
|
||||
this._inDrag = true;
|
||||
this._cancelledDrag = false;
|
||||
@ -1012,33 +831,11 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
},
|
||||
|
||||
_onDragMotion: function(dragEvent) {
|
||||
let controlsHovered = this._controls.contains(dragEvent.targetActor);
|
||||
this._controls.set_hover(controlsHovered);
|
||||
|
||||
return DND.DragMotionResult.CONTINUE;
|
||||
},
|
||||
|
||||
_dragEnd: function() {
|
||||
this._inDrag = false;
|
||||
|
||||
// We do this deferred because drag-end is emitted before dnd.js emits
|
||||
// event/leave events that were suppressed during the drag. If we didn't
|
||||
// defer this, we'd zoom out then immediately zoom in because of the
|
||||
// enter event we received. That would normally be invisible but we
|
||||
// might as well avoid it.
|
||||
Meta.later_add(Meta.LaterType.BEFORE_REDRAW,
|
||||
Lang.bind(this, this._updateZoom));
|
||||
},
|
||||
|
||||
_onScrollEvent: function (actor, event) {
|
||||
switch ( event.get_scroll_direction() ) {
|
||||
case Clutter.ScrollDirection.UP:
|
||||
Main.wm.actionMoveWorkspace(Meta.MotionDirection.UP);
|
||||
break;
|
||||
case Clutter.ScrollDirection.DOWN:
|
||||
Main.wm.actionMoveWorkspace(Meta.MotionDirection.DOWN);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
Signals.addSignalMethods(WorkspacesDisplay.prototype);
|
||||
|
30
tests/interactive/center-layout.js
Normal file
30
tests/interactive/center-layout.js
Normal file
@ -0,0 +1,30 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const St = imports.gi.St;
|
||||
|
||||
const CenterLayout = imports.ui.centerLayout;
|
||||
const UI = imports.testcommon.ui;
|
||||
|
||||
function test() {
|
||||
let stage = new Clutter.Stage({ user_resizable: true });
|
||||
UI.init(stage);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
let container = new St.Widget({ style: 'border: 2px solid black;',
|
||||
layout_manager: new CenterLayout.CenterLayout() });
|
||||
container.add_constraint(new Clutter.BindConstraint({ coordinate: Clutter.BindCoordinate.SIZE, source: stage }));
|
||||
stage.add_actor(container);
|
||||
|
||||
let left = new Clutter.Actor({ background_color: Clutter.Color.get_static(Clutter.StaticColor.RED), width: 300 });
|
||||
let center = new Clutter.Actor({ background_color: Clutter.Color.get_static(Clutter.StaticColor.BLUE), width: 100 });
|
||||
let right = new Clutter.Actor({ background_color: Clutter.Color.get_static(Clutter.StaticColor.YELLOW), width: 200 });
|
||||
|
||||
container.add_actor(left);
|
||||
container.add_actor(center);
|
||||
container.add_actor(right);
|
||||
|
||||
UI.main(stage);
|
||||
}
|
||||
test();
|
Reference in New Issue
Block a user