Compare commits
56 Commits
wip/media-
...
3.7.2.1-br
Author | SHA1 | Date | |
---|---|---|---|
![]() |
b45b241ce8 | ||
![]() |
4233ca2983 | ||
![]() |
5200da6eec | ||
![]() |
b0523860d9 | ||
![]() |
1a1215527f | ||
![]() |
360c018c9e | ||
![]() |
7bed964ab2 | ||
![]() |
989d0a5682 | ||
![]() |
b121c25184 | ||
![]() |
e0d127b3e4 | ||
![]() |
a0c56c74e1 | ||
![]() |
f4b61a7f24 | ||
![]() |
b2400fb883 | ||
![]() |
f25832d1b6 | ||
![]() |
cf363171aa | ||
![]() |
38c8569d16 | ||
![]() |
9791d15f39 | ||
![]() |
80e7f5832b | ||
![]() |
6e46ddaad3 | ||
![]() |
8499e4aab2 | ||
![]() |
5eae1851a1 | ||
![]() |
c48a246ccb | ||
![]() |
f084011a61 | ||
![]() |
bd40cf194c | ||
![]() |
2434af7e8a | ||
![]() |
ced7fa9f01 | ||
![]() |
28b559e812 | ||
![]() |
76d776245b | ||
![]() |
0d9f70492e | ||
![]() |
b58f502dd6 | ||
![]() |
5f367248c5 | ||
![]() |
c2065cc3e2 | ||
![]() |
034408971d | ||
![]() |
490206b5b2 | ||
![]() |
d8540819af | ||
![]() |
d1a9aec526 | ||
![]() |
e4b681a5a5 | ||
![]() |
52036871d1 | ||
![]() |
4fc6a804f5 | ||
![]() |
08d2ca300a | ||
![]() |
dc2ec0a8f9 | ||
![]() |
2cfed952bb | ||
![]() |
a7da137778 | ||
![]() |
5ae2f87ce9 | ||
![]() |
c4f6619fbd | ||
![]() |
65edbc1424 | ||
![]() |
1f2d7fa28f | ||
![]() |
2407a0c4e2 | ||
![]() |
7f8bfcc939 | ||
![]() |
fae4cb9e56 | ||
![]() |
063bbb02f2 | ||
![]() |
15e1470c50 | ||
![]() |
f602993aa9 | ||
![]() |
271508c0a8 | ||
![]() |
50f96d1c9c | ||
![]() |
809544800b |
67
NEWS
67
NEWS
@@ -1,3 +1,70 @@
|
|||||||
|
3.7.2.1
|
||||||
|
=======
|
||||||
|
* Revert 490206b to not depend on NMGTK-0.9.7, which hasn't been released yet
|
||||||
|
|
||||||
|
3.7.2
|
||||||
|
=====
|
||||||
|
* Enforce RTL in he for messages that might end up as LTR [Florian; #686630]
|
||||||
|
* gdm: Move logo into the panel [Florian; #685852]
|
||||||
|
* Hide notifications when closed button is clicked [Jasper, Florian; #682237]
|
||||||
|
* Tweak screenShield animations [Rui; #686745]
|
||||||
|
* Restore Fittsability of summary items in message tray [Florian; #686474]
|
||||||
|
* Save screencasts as recent item [Ray; #680647]
|
||||||
|
* overview: Resize window captions on content change [Giovanni, Alex; #620874]
|
||||||
|
* App search: Match GenericName too [Matthias; #687121]
|
||||||
|
* runDialog: Better match style of other modal dialogs [Florian, Allan; #687127]
|
||||||
|
* Improve the button insensitive style [Stéphane; #687110]
|
||||||
|
* network: Don't use a global switch for all VPN connections [Giovanni; #682929]
|
||||||
|
* appMenu: Update on icon theme changes [Florian; #687224]
|
||||||
|
* Show 'Log out' in more situations [Matthias; #686736]
|
||||||
|
* Add a setting to force the 'Log out' menuitem [Matthias; #686057]
|
||||||
|
* overview: Improve styling of search box [Stéphane; #686479]
|
||||||
|
* Implement 'disable-user-list' in login screen [Ray; #660660]
|
||||||
|
* Fix auto-scroll to bottom in chat notifications [Sjoerd; #686571]
|
||||||
|
* Show feedback notifications when user is busy [Stéphane; #662900]
|
||||||
|
* Disable login button when there is no input [Stéphane; #687112]
|
||||||
|
* Use non-linear overview shade for background [Giovanni, Pierre-Eric; #669798]
|
||||||
|
* Reduce blocking in compositor thread [Simon, Jasper; #687465]
|
||||||
|
* network: new country-specific type to gather providers [Aleksander; #687356]
|
||||||
|
* Update man page [Matthias; #680601]
|
||||||
|
* st-entry: Change the pointer cursor on enter/leave events [Thomas; #687130]
|
||||||
|
* screenShield: Blur and desaturate the background [Giovanni, Cosimo; #682536]
|
||||||
|
* Change height of chat notifications to have more context [Carlos; #665255]
|
||||||
|
* screenShield: Account for motion velocity when hiding [Giovanni; #682537]
|
||||||
|
* screenShield: hide the cursor while the lock screen is on [Giovanni; #682535]
|
||||||
|
* Support remote search provider settings [Cosimo; #687491]
|
||||||
|
* unlockDialog: Improve label of confirmation button [Stéphane; #687656]
|
||||||
|
* userMenu: Rename "System Settings" item to "Settings" [Elad; #687738]
|
||||||
|
* messageTray: Add keybinding to focus current notification [Stéphane; #652082]
|
||||||
|
* Remove shell-screen-grabber [Neil; #685915]
|
||||||
|
* main: Stop using Metacity's keybinding files [Florian; #687672]
|
||||||
|
* Bluetooth: Remove ObexFTP functionality [Bastien; #688160]
|
||||||
|
* a11y: Also set WM theme when HighContrast is switched on [Cosimo; #688256]
|
||||||
|
* network: Rework multiple NIC support [Giovanni; #677142]
|
||||||
|
* Rework keybindings to allow selective blocking/processing [Florian; #688202]
|
||||||
|
* recorder: Show indicator on primary monitor [Adel; #688470]
|
||||||
|
* recorder: Set frame duration to fix broken video headers [Adel; #688487]
|
||||||
|
* Misc. bugfixes and cleanups [Florian, Jasper, Giovanni, Matthew, Stéphane,
|
||||||
|
Allan, Daiki, Owen, Alejandro, Jean-François, Cosimo, Sebastian, Adel, Alban;
|
||||||
|
#686484, #686728, #686805, #686574, #686763, #682428, #687132, #685239,
|
||||||
|
#687189, #687226, #658091, #670687, #687457, #687242, #687287, #687020,
|
||||||
|
#686583, #661194, #687491, #657315, #687958, #683986, #688089, #687708,
|
||||||
|
#686530, #684810, #688181, #688475, #688557, #688507, #638351]
|
||||||
|
|
||||||
|
Contributors:
|
||||||
|
Elad Alfassa, Matthew Barnes, Alban Browaeys, Giovanni Campagna,
|
||||||
|
Cosimo Cecchi, Matthias Clasen, Allan Day, Stéphane Démurget,
|
||||||
|
Jean-François Fortin Tam, Adel Gadllah, Alex Hultman, Sebastian Keller,
|
||||||
|
Rui Matos, Simon McVittie, Aleksander Morgado, Florian Müllner,
|
||||||
|
Bastien Nocera, Pierre-Eric Pelloux-Prayer, Alejandro Piñeiro, Neil Roberts,
|
||||||
|
Sjoerd Simons, Carlos Soriano Sánchez, Jasper St. Pierre, Ray Strode,
|
||||||
|
Owen Taylor, Daiki Ueno, Thomas Wood
|
||||||
|
|
||||||
|
Translations:
|
||||||
|
Dušan Kazik [sk], Pavol Klačanský [sk], Piotr Drąg [pl], Yuri Myasoedov [ru],
|
||||||
|
Marek Černocký [cs], Kjartan Maraas [nb], Wolfgang Stöggl [de],
|
||||||
|
Yaron Shahrabani [he], Fran Diéguez [gl], Mattias Põldaru [et]
|
||||||
|
|
||||||
3.7.1
|
3.7.1
|
||||||
=====
|
=====
|
||||||
* Add shortcut to open application view directly [Jeremy; #685738]
|
* Add shortcut to open application view directly [Jeremy; #685738]
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
AC_PREREQ(2.63)
|
AC_PREREQ(2.63)
|
||||||
AC_INIT([gnome-shell],[3.7.1],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
|
AC_INIT([gnome-shell],[3.7.2.1],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
|
||||||
|
|
||||||
AC_CONFIG_HEADERS([config.h])
|
AC_CONFIG_HEADERS([config.h])
|
||||||
AC_CONFIG_SRCDIR([src/shell-global.c])
|
AC_CONFIG_SRCDIR([src/shell-global.c])
|
||||||
@@ -65,7 +65,7 @@ AM_CONDITIONAL(BUILD_RECORDER, $build_recorder)
|
|||||||
CLUTTER_MIN_VERSION=1.11.11
|
CLUTTER_MIN_VERSION=1.11.11
|
||||||
GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1
|
GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1
|
||||||
GJS_MIN_VERSION=1.33.2
|
GJS_MIN_VERSION=1.33.2
|
||||||
MUTTER_MIN_VERSION=3.7.1
|
MUTTER_MIN_VERSION=3.7.2
|
||||||
GTK_MIN_VERSION=3.3.9
|
GTK_MIN_VERSION=3.3.9
|
||||||
GIO_MIN_VERSION=2.35.0
|
GIO_MIN_VERSION=2.35.0
|
||||||
LIBECAL_MIN_VERSION=3.5.3
|
LIBECAL_MIN_VERSION=3.5.3
|
||||||
@@ -124,7 +124,7 @@ PKG_CHECK_MODULES(GNOME_SHELL_JS, gio-2.0 gjs-internals-1.0 >= $GJS_MIN_VERSION)
|
|||||||
PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-3.0 libcroco-0.6 >= 0.6.8 x11)
|
PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-3.0 libcroco-0.6 >= 0.6.8 x11)
|
||||||
PKG_CHECK_MODULES(TRAY, gtk+-3.0)
|
PKG_CHECK_MODULES(TRAY, gtk+-3.0)
|
||||||
PKG_CHECK_MODULES(GVC, libpulse libpulse-mainloop-glib gobject-2.0)
|
PKG_CHECK_MODULES(GVC, libpulse libpulse-mainloop-glib gobject-2.0)
|
||||||
PKG_CHECK_MODULES(DESKTOP_SCHEMAS, gsettings-desktop-schemas >= 3.5.4)
|
PKG_CHECK_MODULES(DESKTOP_SCHEMAS, gsettings-desktop-schemas >= 3.7.2)
|
||||||
|
|
||||||
AC_MSG_CHECKING([for bluetooth support])
|
AC_MSG_CHECKING([for bluetooth support])
|
||||||
PKG_CHECK_EXISTS([gnome-bluetooth-1.0 >= 3.1.0],
|
PKG_CHECK_EXISTS([gnome-bluetooth-1.0 >= 3.1.0],
|
||||||
|
@@ -2129,7 +2129,7 @@ StScrollBar StButton#vhandle:active {
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
padding-left: 15px;
|
padding-left: 15px;
|
||||||
text-shadow: black 4px 4px 3px 0px;
|
text-shadow: black 0px 4px 3px 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-dialog-prompt-layout {
|
.login-dialog-prompt-layout {
|
||||||
@@ -2325,17 +2325,3 @@ StScrollBar StButton#vhandle:active {
|
|||||||
padding-bottom: 0px;
|
padding-bottom: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.osd-window {
|
|
||||||
color: #ededed;
|
|
||||||
background-color: rgba(33, 37, 38, 0.80);
|
|
||||||
border-radius: 15px;
|
|
||||||
text-shadow: 0 1px rgba(0, 0, 0, 0.75);
|
|
||||||
|
|
||||||
padding: 40px;
|
|
||||||
spacing: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.osd-progress-bar {
|
|
||||||
height: 0.8em;
|
|
||||||
border: 1px solid;
|
|
||||||
}
|
|
||||||
|
@@ -100,7 +100,6 @@ nobase_dist_js_DATA = \
|
|||||||
ui/components/__init__.js \
|
ui/components/__init__.js \
|
||||||
ui/components/autorunManager.js \
|
ui/components/autorunManager.js \
|
||||||
ui/components/automountManager.js \
|
ui/components/automountManager.js \
|
||||||
ui/components/mediaKeysManager.js \
|
|
||||||
ui/components/networkAgent.js \
|
ui/components/networkAgent.js \
|
||||||
ui/components/polkitAgent.js \
|
ui/components/polkitAgent.js \
|
||||||
ui/components/recorder.js \
|
ui/components/recorder.js \
|
||||||
|
@@ -660,6 +660,7 @@ const LoginDialog = new Lang.Class({
|
|||||||
this.parent({ shellReactive: true,
|
this.parent({ shellReactive: true,
|
||||||
styleClass: 'login-dialog',
|
styleClass: 'login-dialog',
|
||||||
parentActor: parentActor,
|
parentActor: parentActor,
|
||||||
|
keybindingMode: Main.KeybindingMode.LOGIN_SCREEN,
|
||||||
shouldFadeIn: false });
|
shouldFadeIn: false });
|
||||||
this.connect('destroy',
|
this.connect('destroy',
|
||||||
Lang.bind(this, this._onDestroy));
|
Lang.bind(this, this._onDestroy));
|
||||||
@@ -1287,7 +1288,7 @@ const LoginDialog = new Lang.Class({
|
|||||||
_onOpened: function() {
|
_onOpened: function() {
|
||||||
Main.ctrlAltTabManager.addGroup(this.dialogLayout,
|
Main.ctrlAltTabManager.addGroup(this.dialogLayout,
|
||||||
_("Login Window"),
|
_("Login Window"),
|
||||||
'dialog-password',
|
'dialog-password-symbolic',
|
||||||
{ sortGroup: CtrlAltTab.SortGroup.MIDDLE });
|
{ sortGroup: CtrlAltTab.SortGroup.MIDDLE });
|
||||||
|
|
||||||
},
|
},
|
||||||
@@ -1295,6 +1296,6 @@ const LoginDialog = new Lang.Class({
|
|||||||
close: function() {
|
close: function() {
|
||||||
this.parent();
|
this.parent();
|
||||||
|
|
||||||
Main.ctrlAltTabManager.removeGroup(this._group);
|
Main.ctrlAltTabManager.removeGroup(this.dialogLayout);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@@ -17,9 +17,6 @@ const SystemdLoginManagerIface = <interface name='org.freedesktop.login1.Manager
|
|||||||
<method name='Suspend'>
|
<method name='Suspend'>
|
||||||
<arg type='b' direction='in'/>
|
<arg type='b' direction='in'/>
|
||||||
</method>
|
</method>
|
||||||
<method name='Hibernate'>
|
|
||||||
<arg type='b' direction='in'/>
|
|
||||||
</method>
|
|
||||||
<method name='CanPowerOff'>
|
<method name='CanPowerOff'>
|
||||||
<arg type='s' direction='out'/>
|
<arg type='s' direction='out'/>
|
||||||
</method>
|
</method>
|
||||||
@@ -29,9 +26,6 @@ const SystemdLoginManagerIface = <interface name='org.freedesktop.login1.Manager
|
|||||||
<method name='CanSuspend'>
|
<method name='CanSuspend'>
|
||||||
<arg type='s' direction='out'/>
|
<arg type='s' direction='out'/>
|
||||||
</method>
|
</method>
|
||||||
<method name='CanHibernate'>
|
|
||||||
<arg type='s' direction='out'/>
|
|
||||||
</method>
|
|
||||||
</interface>;
|
</interface>;
|
||||||
|
|
||||||
const SystemdLoginSessionIface = <interface name='org.freedesktop.login1.Session'>
|
const SystemdLoginSessionIface = <interface name='org.freedesktop.login1.Session'>
|
||||||
@@ -146,15 +140,6 @@ const LoginManagerSystemd = new Lang.Class({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
canHibernate: function(asyncCallback) {
|
|
||||||
this._proxy.CanSuspendRemote(function(result, error) {
|
|
||||||
if (error)
|
|
||||||
asyncCallback(false);
|
|
||||||
else
|
|
||||||
asyncCallback(result[0] != 'no');
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
powerOff: function() {
|
powerOff: function() {
|
||||||
this._proxy.PowerOffRemote(true);
|
this._proxy.PowerOffRemote(true);
|
||||||
},
|
},
|
||||||
@@ -165,10 +150,6 @@ const LoginManagerSystemd = new Lang.Class({
|
|||||||
|
|
||||||
suspend: function() {
|
suspend: function() {
|
||||||
this._proxy.SuspendRemote(true);
|
this._proxy.SuspendRemote(true);
|
||||||
},
|
|
||||||
|
|
||||||
hibernate: function() {
|
|
||||||
this._proxy.HibernateRemote(true);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -234,13 +215,6 @@ const LoginManagerConsoleKit = new Lang.Class({
|
|||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
|
|
||||||
canHibernate: function(asyncCallback) {
|
|
||||||
Mainloop.idle_add(Lang.bind(this, function() {
|
|
||||||
asyncCallback(this._upClient.get_can_hibernate());
|
|
||||||
return false;
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
|
|
||||||
powerOff: function() {
|
powerOff: function() {
|
||||||
this._proxy.StopRemote();
|
this._proxy.StopRemote();
|
||||||
},
|
},
|
||||||
@@ -251,9 +225,5 @@ const LoginManagerConsoleKit = new Lang.Class({
|
|||||||
|
|
||||||
suspend: function() {
|
suspend: function() {
|
||||||
this._upClient.suspend_sync(null);
|
this._upClient.suspend_sync(null);
|
||||||
},
|
|
||||||
|
|
||||||
hibernate: function() {
|
|
||||||
this._upClient.hibernate_sync(null);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@@ -288,31 +288,3 @@ function insertSorted(array, val, cmp) {
|
|||||||
|
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* wrapKeybinding:
|
|
||||||
*
|
|
||||||
* Wrap a keybinding handler so that
|
|
||||||
* it ignores an invocation if the shell is modal, but
|
|
||||||
* not when the overview is active, or when global
|
|
||||||
* keybindings are allowed by session mode.
|
|
||||||
* This function is only useful for keybindings installed
|
|
||||||
* with Meta.KeybindingFlags.HANDLE_WHEN_GRABBED
|
|
||||||
*/
|
|
||||||
function wrapKeybinding(handler, onlyInOverview) {
|
|
||||||
return function() {
|
|
||||||
let handle;
|
|
||||||
|
|
||||||
if (onlyInOverview) {
|
|
||||||
handle = Main.sessionMode.allowKeybindingsWhenModal ||
|
|
||||||
Main.modalCount == (Main.overview.visible ? 1 : 0);
|
|
||||||
} else {
|
|
||||||
handle = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (handle)
|
|
||||||
return handler.apply(this, arguments);
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@@ -172,7 +172,7 @@ const AltTabPopup = new Lang.Class({
|
|||||||
|
|
||||||
if (!Main.pushModal(this.actor)) {
|
if (!Main.pushModal(this.actor)) {
|
||||||
// Probably someone else has a pointer grab, try again with keyboard only
|
// Probably someone else has a pointer grab, try again with keyboard only
|
||||||
if (!Main.pushModal(this.actor, global.get_current_time(), Meta.ModalOptions.POINTER_ALREADY_GRABBED)) {
|
if (!Main.pushModal(this.actor, { options: Meta.ModalOptions.POINTER_ALREADY_GRABBED })) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -199,7 +199,7 @@ const AltTabPopup = new Lang.Class({
|
|||||||
this.actor.get_allocation_box();
|
this.actor.get_allocation_box();
|
||||||
|
|
||||||
// Make the initial selection
|
// Make the initial selection
|
||||||
if (binding == 'internal-keybinding-switch-group') {
|
if (binding == 'switch-group') {
|
||||||
if (backward) {
|
if (backward) {
|
||||||
this._select(0, this._appIcons[0].cachedWindows.length - 1);
|
this._select(0, this._appIcons[0].cachedWindows.length - 1);
|
||||||
} else {
|
} else {
|
||||||
@@ -208,9 +208,9 @@ const AltTabPopup = new Lang.Class({
|
|||||||
else
|
else
|
||||||
this._select(0, 0);
|
this._select(0, 0);
|
||||||
}
|
}
|
||||||
} else if (binding == 'internal-keybinding-switch-group-backward') {
|
} else if (binding == 'switch-group-backward') {
|
||||||
this._select(0, this._appIcons[0].cachedWindows.length - 1);
|
this._select(0, this._appIcons[0].cachedWindows.length - 1);
|
||||||
} else if (binding == 'internal-keybinding-switch-windows-backward') {
|
} else if (binding == 'switch-windows-backward') {
|
||||||
this._select(this._appIcons.length - 1);
|
this._select(this._appIcons.length - 1);
|
||||||
} else if (this._appIcons.length == 1) {
|
} else if (this._appIcons.length == 1) {
|
||||||
this._select(0);
|
this._select(0);
|
||||||
|
@@ -1,647 +0,0 @@
|
|||||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
|
||||||
|
|
||||||
const Clutter = imports.gi.Clutter;
|
|
||||||
const Gdk = imports.gi.Gdk;
|
|
||||||
const GLib = imports.gi.GLib;
|
|
||||||
const Gio = imports.gi.Gio;
|
|
||||||
const Lang = imports.lang;
|
|
||||||
const Meta = imports.gi.Meta;
|
|
||||||
const Shell = imports.gi.Shell;
|
|
||||||
const St = imports.gi.St;
|
|
||||||
|
|
||||||
const Main = imports.ui.main;
|
|
||||||
const MessageTray = imports.ui.messageTray;
|
|
||||||
const ShellMountOperation = imports.ui.shellMountOperation;
|
|
||||||
const Tweener = imports.ui.tweener;
|
|
||||||
const Util = imports.misc.util;
|
|
||||||
|
|
||||||
const INTERFACE_SETTINGS = 'org.gnome.desktop.interface';
|
|
||||||
const POWER_SETTINGS = 'org.gnome.settings-daemon.plugins.power';
|
|
||||||
const XSETTINGS_SETTINGS = 'org.gnome.settings-daemon.plugins.xsettings';
|
|
||||||
const TOUCHPAD_SETTINGS = 'org.gnome.settings-daemon.peripherals.touchpad';
|
|
||||||
const KEYBINDING_SETTINGS = 'org.gnome.settings-daemon.plugins.media-keys';
|
|
||||||
const CUSTOM_KEYBINDING_SETTINGS = 'org.gnome.settings-daemon.plugins.media-keys.custom-keybinding';
|
|
||||||
const A11Y_SETTINGS = 'org.gnome.desktop.a11y.applications';
|
|
||||||
const MAGNIFIER_SETTINGS = 'org.gnome.desktop.a11y.magnifier';
|
|
||||||
const INPUT_SOURCE_SETTINGS = 'org.gnome.desktop.input-sources';
|
|
||||||
|
|
||||||
const MediaKeysInterface = <interface name='org.gnome.SettingsDaemon.MediaKeys'>
|
|
||||||
<method name='GrabMediaPlayerKeys'>
|
|
||||||
<arg name='application' direction='in' type='s'/>
|
|
||||||
<arg name='time' direction='in' type='u'/>
|
|
||||||
</method>
|
|
||||||
<method name='ReleaseMediaPlayerKeys'>
|
|
||||||
<arg name='application' direction='in' type='s'/>
|
|
||||||
</method>
|
|
||||||
<signal name='MediaPlayerKeyPressed'>
|
|
||||||
<arg name='application' type='s'/>
|
|
||||||
<arg name='key' type='s'/>
|
|
||||||
</signal>
|
|
||||||
</interface>;
|
|
||||||
|
|
||||||
/* [ actionName, setting, hardcodedKeysym, overviewOnly, args ] */
|
|
||||||
/* (overviewOnly means that the keybinding is handled when the shell is not
|
|
||||||
modal, or when the overview is active, but not when other modal operations
|
|
||||||
are active; otherwise the keybinding is always handled) */
|
|
||||||
const DEFAULT_KEYBINDINGS = [
|
|
||||||
[ 'doTouchpadToggle', null, 'XF86TouchpadToggle', false ],
|
|
||||||
[ 'doTouchpadSet', null, 'XF86TouchpadOn', false, [ true ] ],
|
|
||||||
[ 'doTouchpadSet', null, 'XF86TouchpadOff', false, [ false ] ],
|
|
||||||
[ 'doMute', 'volume-mute', null, false, [ false ] ],
|
|
||||||
[ 'doVolumeAdjust', 'volume-down', null, false, [ Clutter.ScrollDirection.DOWN, false ] ],
|
|
||||||
[ 'doVolumeAdjust', 'volume-up', null, false, [ Clutter.ScrollDirection.UP, false ] ],
|
|
||||||
[ 'doMute', null, '<Alt>XF86AudioMute', false, [ true ] ],
|
|
||||||
[ 'doVolumeAdjust', null, '<Alt>XF86AudioLowerVolume', false, [ Clutter.ScrollDirection.DOWN, true ] ],
|
|
||||||
[ 'doVolumeAdjust', null, '<Alt>XF86AudioRaiseVolume', false, [ Clutter.ScrollDirection.UP, true ] ],
|
|
||||||
[ 'doLogout', 'logout', null, true ],
|
|
||||||
[ 'doEject', 'eject', null, false ],
|
|
||||||
[ 'doHome', 'home', null, true ],
|
|
||||||
[ 'doLaunchMimeHandler', 'media', null, true, [ 'application/x-vorbis+ogg' ] ],
|
|
||||||
[ 'doLaunchApp', 'calculator', null, true, [ 'gcalcltool.desktop' ] ],
|
|
||||||
[ 'doLaunchApp', 'search', null, true, [ 'tracker-needle.desktop' ] ],
|
|
||||||
[ 'doLaunchMimeHandler', 'email', null, true, [ 'x-scheme-handler/mailto' ] ],
|
|
||||||
[ 'doScreensaver', 'screensaver', null, true ],
|
|
||||||
[ 'doScreensaver', null, 'XF86ScreenSaver', true ],
|
|
||||||
[ 'doLaunchApp', 'help', null, true, [ 'yelp.desktop' ] ],
|
|
||||||
[ 'doSpawn', 'screenshot', null, true, [ ['gnome-screenshot'] ] ],
|
|
||||||
[ 'doSpawn', 'window-screenshot', null, true, [ ['gnome-screenshot', '--window'] ] ],
|
|
||||||
[ 'doSpawn', 'area-screenshot', null, true, [ ['gnome-screenshot', '--area'] ] ],
|
|
||||||
[ 'doSpawn', 'screenshot-clip', null, true, [ ['gnome-screenshot', '--clipboard'] ] ],
|
|
||||||
[ 'doSpawn', 'window-screenshot-clip', null, true, [ ['gnome-screenshot', '--window', '--clipboard'] ] ],
|
|
||||||
[ 'doSpawn', 'area-screenshot-clip', null, true, [ ['gnome-screenshot', '--area', '--clipboard'] ] ],
|
|
||||||
[ 'doLaunchMimeHandler', 'www', null, true, [ 'x-scheme-handler/http' ] ],
|
|
||||||
[ 'doMediaKey', 'play', null, true, [ 'Play' ] ],
|
|
||||||
[ 'doMediaKey', 'pause', null, true, [ 'Pause' ] ],
|
|
||||||
[ 'doMediaKey', 'stop', null, true, [ 'Stop' ] ],
|
|
||||||
[ 'doMediaKey', 'previous', null, true, [ 'Previous' ] ],
|
|
||||||
[ 'doMediaKey', 'next', null, true, [ 'Next' ] ],
|
|
||||||
[ 'doMediaKey', null, 'XF86AudioRewind', true, [ 'Rewind' ] ],
|
|
||||||
[ 'doMediaKey', null, 'XF86AudioForward', true, [ 'FastForward' ] ],
|
|
||||||
[ 'doMediaKey', null, 'XF86AudioRepeat', true, [ 'Repeat' ] ],
|
|
||||||
[ 'doMediaKey', null, 'XF86AudioRandomPlay', true, [ 'Shuffle' ] ],
|
|
||||||
[ 'doXRandRAction', null, '<Super>p', false, [ 'VideoModeSwitch' ] ],
|
|
||||||
/* Key code of the XF86Display key (Fn-F7 on Thinkpads, Fn-F4 on HP machines, etc.) */
|
|
||||||
[ 'doXRandRAction', null, 'XF86Display', false, [ 'VideoModeSwitch' ] ],
|
|
||||||
/* Key code of the XF86RotateWindows key (present on some tablets) */
|
|
||||||
[ 'doXRandRAction', null, 'XF86RotateWindows', false, [ 'Rotate' ] ],
|
|
||||||
[ 'doA11yAction', 'magnifier', null, true, [ 'screen-magnifier-enabled' ] ],
|
|
||||||
[ 'doA11yAction', 'screenreader', null, true, [ 'screen-reader-enabled' ] ],
|
|
||||||
[ 'doA11yAction', 'on-screen-keyboard', null, true, [ 'screen-keyboard-enabled' ] ],
|
|
||||||
[ 'doTextSize', 'increase-text-size', null, true, [ 1 ] ],
|
|
||||||
[ 'doTextSize', 'decrease-text-size', null, true, [ -1 ] ],
|
|
||||||
[ 'doToggleContrast', 'toggle-contrast', null, true ],
|
|
||||||
[ 'doMagnifierZoom', 'magnifier-zoom-in', null, true, [ 1 ] ],
|
|
||||||
[ 'doMagnifierZoom', 'magnifier-zoom-out', null, true, [ -1 ] ],
|
|
||||||
[ 'doPowerAction', null, 'XF86PowerOff', true, [ 'button-power' ] ],
|
|
||||||
/* the kernel / Xorg names really are like this... */
|
|
||||||
[ 'doPowerAction', null, 'XF86Suspend', false, [ 'button-sleep' ] ],
|
|
||||||
[ 'doPowerAction', null, 'XF86Sleep', false, [ 'button-suspend' ] ],
|
|
||||||
[ 'doPowerAction', null, 'XF86Hibernate', false, [ 'button-hibernate' ] ],
|
|
||||||
[ 'doBrightness', null, 'XF86MonBrightnessUp', false, [ 'Screen', 'StepUp' ] ],
|
|
||||||
[ 'doBrightness', null, 'XF86MonBrightnessDown', false, [ 'Screen', 'StepDown' ] ],
|
|
||||||
[ 'doBrightness', null, 'XF86KbdBrightnessUp', false, [ 'Keyboard', 'StepUp' ] ],
|
|
||||||
[ 'doBrightness', null, 'XF86KbdBrightnessDown', false, [ 'Keyboard', 'StepDown' ] ],
|
|
||||||
[ 'doBrightnessToggle', null, 'XF86KbdLightOnOff', false, ],
|
|
||||||
[ 'doInputSource', 'switch-input-source', null, false, [ +1 ] ],
|
|
||||||
[ 'doInputSource', 'switch-input-source-backward', null, false, [ -1 ] ],
|
|
||||||
[ 'doLaunchApp', null, 'XF86Battery', true, [ 'gnome-power-statistics.desktop' ] ]
|
|
||||||
];
|
|
||||||
|
|
||||||
var osdWin;
|
|
||||||
const OSDWindow = new Lang.Class({
|
|
||||||
Name: 'OSDWindow',
|
|
||||||
|
|
||||||
FADE_TIMEOUT: 1500,
|
|
||||||
FADE_DURATION: 100,
|
|
||||||
|
|
||||||
_init: function(iconName, value) {
|
|
||||||
/* assume 130x130 on a 640x480 display and scale from there */
|
|
||||||
let monitor = Main.layoutManager.primaryMonitor;
|
|
||||||
let scalew = monitor.width / 640.0;
|
|
||||||
let scaleh = monitor.height / 480.0;
|
|
||||||
let scale = Math.min(scalew, scaleh);
|
|
||||||
let size = 130 * Math.max(1, scale);
|
|
||||||
|
|
||||||
this.actor = new St.BoxLayout({ style_class: 'osd-window',
|
|
||||||
vertical: true,
|
|
||||||
reactive: false,
|
|
||||||
visible: false,
|
|
||||||
width: size,
|
|
||||||
height: size,
|
|
||||||
});
|
|
||||||
|
|
||||||
this._icon = new St.Icon({ icon_name: iconName,
|
|
||||||
icon_size: size / 2,
|
|
||||||
});
|
|
||||||
this.actor.add(this._icon, { expand: true,
|
|
||||||
x_align: St.Align.MIDDLE,
|
|
||||||
y_align: St.Align.MIDDLE });
|
|
||||||
|
|
||||||
this._value = value;
|
|
||||||
this._progressBar = new St.DrawingArea({ style_class: 'osd-progress-bar' });
|
|
||||||
this._progressBar.connect('repaint', Lang.bind(this, this._drawProgress));
|
|
||||||
this.actor.add(this._progressBar, { expand: true, x_fill: true, y_fill: false });
|
|
||||||
this._progressBar.visible = value !== undefined;
|
|
||||||
|
|
||||||
Main.layoutManager.addChrome(this.actor);
|
|
||||||
|
|
||||||
/* Position in the middle of primary monitor */
|
|
||||||
let [width, height] = this.actor.get_size();
|
|
||||||
this.actor.x = ((monitor.width - width) / 2) + monitor.x;
|
|
||||||
this.actor.y = monitor.y + (monitor.height / 2) + (monitor.height / 2 - height) / 2;
|
|
||||||
},
|
|
||||||
|
|
||||||
show: function() {
|
|
||||||
this.actor.show();
|
|
||||||
Tweener.addTween(this.actor,
|
|
||||||
{ opacity: 255,
|
|
||||||
time: this.FADE_DURATION / 1000,
|
|
||||||
transition: 'easeInQuad' });
|
|
||||||
|
|
||||||
if (this._timeoutId)
|
|
||||||
GLib.source_remove(this._timeoutId);
|
|
||||||
|
|
||||||
this._timeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, this.FADE_TIMEOUT, Lang.bind(this, this.hide));
|
|
||||||
},
|
|
||||||
|
|
||||||
hide: function() {
|
|
||||||
Tweener.addTween(this.actor,
|
|
||||||
{ opacity: 0,
|
|
||||||
time: this.FADE_DURATION / 1000,
|
|
||||||
transition: 'easeOutQuad',
|
|
||||||
onComplete: function() {
|
|
||||||
this.actor.destroy();
|
|
||||||
this.actor = null;
|
|
||||||
osdWin = null;
|
|
||||||
},
|
|
||||||
onCompleteScope: this });
|
|
||||||
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
|
|
||||||
setIcon: function(name) {
|
|
||||||
this._icon.icon_name = name;
|
|
||||||
},
|
|
||||||
|
|
||||||
setValue: function(value) {
|
|
||||||
if (value == this._value)
|
|
||||||
return;
|
|
||||||
|
|
||||||
this._value = value;
|
|
||||||
this._progressBar.visible = value !== undefined;
|
|
||||||
this._progressBar.queue_repaint();
|
|
||||||
},
|
|
||||||
|
|
||||||
_drawProgress: function(area) {
|
|
||||||
let cr = area.get_context();
|
|
||||||
|
|
||||||
let themeNode = this.actor.get_theme_node();
|
|
||||||
let color = themeNode.get_foreground_color();
|
|
||||||
Clutter.cairo_set_source_color(cr, color);
|
|
||||||
|
|
||||||
let [width, height] = area.get_surface_size();
|
|
||||||
width = width * this._value;
|
|
||||||
|
|
||||||
cr.moveTo(0,0);
|
|
||||||
cr.lineTo(width, 0);
|
|
||||||
cr.lineTo(width, height);
|
|
||||||
cr.lineTo(0, height);
|
|
||||||
cr.fill();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function showOSD(icon, value) {
|
|
||||||
if (osdWin) {
|
|
||||||
osdWin.setIcon(icon);
|
|
||||||
osdWin.setValue(value);
|
|
||||||
} else {
|
|
||||||
osdWin = new OSDWindow(icon, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
osdWin.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
const MediaKeysGrabber = new Lang.Class({
|
|
||||||
Name: 'MediaKeysGrabber',
|
|
||||||
|
|
||||||
_init: function() {
|
|
||||||
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(MediaKeysInterface, this);
|
|
||||||
this._apps = [];
|
|
||||||
},
|
|
||||||
|
|
||||||
enable: function() {
|
|
||||||
this._dbusImpl.export(Gio.DBus.session, '/org/gnome/SettingsDaemon/MediaKeys');
|
|
||||||
},
|
|
||||||
|
|
||||||
disable: function() {
|
|
||||||
this._dbusImpl.unexport();
|
|
||||||
},
|
|
||||||
|
|
||||||
GrabMediaPlayerKeysAsync: function(parameters, invocation) {
|
|
||||||
let [appName, time] = parameters;
|
|
||||||
|
|
||||||
/* I'm not sure of this code, but it is in gnome-settings-daemon
|
|
||||||
(letting alone that the introspection is wrong in glib...)
|
|
||||||
*/
|
|
||||||
if (time == Gdk.CURRENT_TIME) {
|
|
||||||
let tv = new GLib.TimeVal;
|
|
||||||
GLib.get_current_time(tv);
|
|
||||||
time = tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
let pos = -1;
|
|
||||||
for (let i = 0; i < this._apps.length; i++) {
|
|
||||||
if (this._apps[i].appName == appName) {
|
|
||||||
pos = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pos != -1)
|
|
||||||
this._freeMediaPlayer(pos);
|
|
||||||
|
|
||||||
let app = {
|
|
||||||
appName: appName,
|
|
||||||
name: invocation.get_sender(),
|
|
||||||
time: time,
|
|
||||||
watchId: Gio.DBus.session.watch_name(invocation.get_sender(),
|
|
||||||
Gio.BusNameWatcherFlags.NONE,
|
|
||||||
null,
|
|
||||||
Lang.bind(this, this._onNameVanished)),
|
|
||||||
};
|
|
||||||
Util.insertSorted(this._apps, app, function(a, b) {
|
|
||||||
return b.time-a.time;
|
|
||||||
});
|
|
||||||
|
|
||||||
invocation.return_value(GLib.Variant.new('()', []));
|
|
||||||
},
|
|
||||||
|
|
||||||
ReleaseMediaPlayerAsync: function(parameters, invocation) {
|
|
||||||
let name = invocation.get_sender();
|
|
||||||
let [appName] = parameters;
|
|
||||||
|
|
||||||
let pos = -1;
|
|
||||||
for (let i = 0; i < this._apps.length; i++) {
|
|
||||||
if (this._apps[i].appName == appName) {
|
|
||||||
pos = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pos == -1) {
|
|
||||||
for (let i = 0; i < this._apps.length; i++) {
|
|
||||||
if (this._apps[i].name == name) {
|
|
||||||
pos = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pos != -1)
|
|
||||||
this._freeMediaPlayer(pos);
|
|
||||||
|
|
||||||
invocation.return_value(GLib.Variant.new('()', []));
|
|
||||||
},
|
|
||||||
|
|
||||||
_freeMediaPlayer: function(pos) {
|
|
||||||
let app = this._apps[pos];
|
|
||||||
Gio.bus_unwatch_name(app.watchId)
|
|
||||||
|
|
||||||
this._apps.splice(pos, 1);
|
|
||||||
},
|
|
||||||
|
|
||||||
mediaKeyPressed: function(key) {
|
|
||||||
if (this._apps.length == 0) {
|
|
||||||
showOSD('action-unavailable-symbolic');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let app = this._apps[0];
|
|
||||||
Gio.DBus.session.emit_signal(app.name,
|
|
||||||
'/org/gnome/SettingsDaemon/MediaKeys',
|
|
||||||
'org.gnome.SettingsDaemon.MediaKeys',
|
|
||||||
'MediaPlayerKeyPressed',
|
|
||||||
GLib.Variant.new('(ss)', [app.appName || '',
|
|
||||||
key]));
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const MediaKeysManager = new Lang.Class({
|
|
||||||
Name: 'MediaKeysManager',
|
|
||||||
|
|
||||||
_init: function() {
|
|
||||||
this._a11yControl = Main.panel.statusArea.a11y;
|
|
||||||
this._volumeControl = Main.panel.statusArea.volume;
|
|
||||||
this._userMenu = Main.panel.statusArea.userMenu;
|
|
||||||
this._mediaPlayerKeys = new MediaKeysGrabber();
|
|
||||||
|
|
||||||
this._keybindingSettings = new Gio.Settings({ schema: KEYBINDING_SETTINGS });
|
|
||||||
},
|
|
||||||
|
|
||||||
enable: function() {
|
|
||||||
for (let i = 0; i < DEFAULT_KEYBINDINGS.length; i++) {
|
|
||||||
let [action, setting, keyval, overviewOnly, args] = DEFAULT_KEYBINDINGS[i];
|
|
||||||
let func = this[action];
|
|
||||||
if (!func) {
|
|
||||||
log('Keybinding action %s is missing'.format(action));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let name = setting ? setting : 'media-keys-keybindings-%d'.format(i);
|
|
||||||
let ok;
|
|
||||||
func = Util.wrapKeybinding(Lang.bind.apply(null, [this, func].concat(args)), overviewOnly);
|
|
||||||
if (setting)
|
|
||||||
ok = global.display.add_keybinding(setting, this._keybindingSettings,
|
|
||||||
Meta.KeyBindingFlags.BUILTIN |
|
|
||||||
Meta.KeyBindingFlags.IS_SINGLE |
|
|
||||||
Meta.KeyBindingFlags.HANDLE_WHEN_GRABBED, func);
|
|
||||||
else
|
|
||||||
ok = global.display.add_grabbed_key(name, keyval,
|
|
||||||
Meta.KeyBindingFlags.HANDLE_WHEN_GRABBED, func);
|
|
||||||
|
|
||||||
if (!ok)
|
|
||||||
log('Installing keybinding %s failed'.format(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
this._customKeybindings = [];
|
|
||||||
this._changedId = this._keybindingSettings.connect('changed::custom-keybindings',
|
|
||||||
Lang.bind(this, this._reloadCustomKeybindings));
|
|
||||||
this._reloadCustomKeybindings();
|
|
||||||
|
|
||||||
this._mediaPlayerKeys.enable();
|
|
||||||
},
|
|
||||||
|
|
||||||
disable: function() {
|
|
||||||
for (let i = 0; i < DEFAULT_KEYBINDINGS.length; i++) {
|
|
||||||
let [action, setting, keyval, overviewOnly, args] = DEFAULT_KEYBINDINGS[i];
|
|
||||||
|
|
||||||
let name = setting ? setting : 'media-keys-keybindings-%d'.format(i);
|
|
||||||
if (setting)
|
|
||||||
global.display.remove_keybinding(setting, this._keybindingSettings);
|
|
||||||
else
|
|
||||||
global.display.remove_grabbed_key(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
this._clearCustomKeybindings();
|
|
||||||
this._keybindingSettings.disconnect(this._changedId);
|
|
||||||
|
|
||||||
this._mediaPlayerKeys.disable();
|
|
||||||
},
|
|
||||||
|
|
||||||
_clearCustomKeybindings: function() {
|
|
||||||
for (let i = 0; i < this._customKeybindings.length; i++)
|
|
||||||
global.display.remove_keybinding('binding', this._customKeybindings[i]);
|
|
||||||
|
|
||||||
this._customKeybindings = [];
|
|
||||||
},
|
|
||||||
|
|
||||||
_reloadCustomKeybindings: function() {
|
|
||||||
this._clearCustomKeybindings();
|
|
||||||
|
|
||||||
let paths = this._keybindingSettings.get_strv('custom-keybindings');
|
|
||||||
for (let i = 0; i < paths.length; i++) {
|
|
||||||
let setting = new Gio.Settings({ schema: CUSTOM_KEYBINDING_SETTINGS,
|
|
||||||
path: paths[i] });
|
|
||||||
let func = Util.wrapKeybinding(Lang.bind(this, this.doCustom, setting), true);
|
|
||||||
|
|
||||||
global.display.add_keybinding('binding', setting,
|
|
||||||
Meta.KeyBindingFlags.IS_SINGLE |
|
|
||||||
Meta.KeyBindingFlags.HANDLE_WHEN_GRABBED, func);
|
|
||||||
this._customKeybindings.push(setting);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
doCustom: function(display, screen, window, binding, settings) {
|
|
||||||
let command = settings.get_string('command');
|
|
||||||
Util.spawnCommandLine(command);
|
|
||||||
},
|
|
||||||
|
|
||||||
doTouchpadToggle: function(display, screen, window, binding) {
|
|
||||||
let settings = new Gio.Settings({ schema: TOUCHPAD_SETTINGS });
|
|
||||||
let enabled = settings.get_boolean('touchpad-enabled');
|
|
||||||
|
|
||||||
this.doTouchpadSet(display, screen, window, binding, !enabled);
|
|
||||||
settings.set_boolean(!enabled);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
doTouchpadSet: function(display, screen, window, binding, enabled) {
|
|
||||||
showOSD(enabled ? 'input-touchpad-symbolic' : 'touchpad-disabled-symbolic');
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
doMute: function(display, screen, window, binding, quiet) {
|
|
||||||
let [icon, value] = this._volumeControl.volumeMenu.toggleMute(quiet);
|
|
||||||
showOSD(icon, value);
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
doVolumeAdjust: function(display, screen, window, binding, direction, quiet) {
|
|
||||||
let [icon, value] = this._volumeControl.volumeMenu.scroll(direction, quiet);
|
|
||||||
showOSD(icon, value);
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
doLogout: function(display, screen, window, binding) {
|
|
||||||
this._userMenu.logOut();
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
doEject: function(display, screen, window, binding) {
|
|
||||||
let volumeMonitor = Gio.VolumeMonitor.get();
|
|
||||||
|
|
||||||
let drives = volumeMonitor.get_connected_drives();
|
|
||||||
let score = 0, drive;
|
|
||||||
for (let i = 0; i < drives.length; i++) {
|
|
||||||
if (!drives[i].can_eject())
|
|
||||||
continue;
|
|
||||||
if (!drives[i].is_media_removable())
|
|
||||||
continue;
|
|
||||||
if (score < 1) {
|
|
||||||
drive = drives[i];
|
|
||||||
score = 1;
|
|
||||||
}
|
|
||||||
if (!drives[i].has_media())
|
|
||||||
continue;
|
|
||||||
if (score < 2) {
|
|
||||||
drive = drives[i];
|
|
||||||
score = 2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
showOSD('media-eject-custom-symbolic');
|
|
||||||
|
|
||||||
if (!drive)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
let mountOp = new ShellMountOperation.ShellMountOperation(drive);
|
|
||||||
drive.eject_with_operation(Gio.MountUnmountFlags.FORCE,
|
|
||||||
mountOp.mountOp, null, null);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
doHome: function() {
|
|
||||||
let homeFile = Gio.file_new_for_path (GLib.get_home_dir());
|
|
||||||
let homeUri = homeFile.get_uri();
|
|
||||||
Gio.app_info_launch_default_for_uri(homeUri, null);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
doLaunchMimeHandler: function(display, screen, window, binding, mimeType) {
|
|
||||||
let gioApp = Gio.AppInfo.get_default_for_type(mimeType, false);
|
|
||||||
if (gioApp != null) {
|
|
||||||
let app = Shell.AppSystem.get_default().lookup_app(gioApp.get_id());
|
|
||||||
app.open_new_window(-1);
|
|
||||||
} else {
|
|
||||||
log('Could not find default application for \'%s\' mime-type'.format(mimeType));
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
doLaunchApp: function(display, screen, window, binding, appId) {
|
|
||||||
let app = Shell.AppSystem.get_default().lookup_app(appId);
|
|
||||||
app.open_new_window(-1);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
doScreensaver: function() {
|
|
||||||
// FIXME: handled in house, to the screenshield!
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
doSpawn: function(display, screen, window, binding, argv) {
|
|
||||||
Util.spawn(argv);
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
doMediaKey: function(display, screen, window, binding, key) {
|
|
||||||
this._mediaPlayerKeys.mediaKeyPressed(key);
|
|
||||||
},
|
|
||||||
|
|
||||||
_onXRandRFinished: function(connection, result) {
|
|
||||||
connection.call_finish(result);
|
|
||||||
this._XRandRCancellable = null;
|
|
||||||
},
|
|
||||||
|
|
||||||
doXRandRAction: function(display, screen, window, binding, action) {
|
|
||||||
if (this._XRandRCancellable)
|
|
||||||
this._XRandRCancellable.cancel();
|
|
||||||
|
|
||||||
this._XRandRCancellable = new Gio.Cancellable();
|
|
||||||
Gio.DBus.session.call('org.gnome.SettingsDaemon',
|
|
||||||
'/org/gnome/SettingsDaemon/XRANDR',
|
|
||||||
'org.gnome.SettingsDaemon.XRANDR_2',
|
|
||||||
action,
|
|
||||||
GLib.Variant.new('(x)', [global.get_current_time()]),
|
|
||||||
null, /* reply type */
|
|
||||||
Gio.DBusCallFlags.NONE,
|
|
||||||
-1,
|
|
||||||
this._XRandRCancellable,
|
|
||||||
Lang.bind(this, this._onXRandRFinished));
|
|
||||||
},
|
|
||||||
|
|
||||||
doA11yAction: function(display, screen, window, binding, key) {
|
|
||||||
let settings = new Gio.Settings({ schema: A11Y_SETTINGS });
|
|
||||||
let enabled = settings.get_boolean(key);
|
|
||||||
settings.set_boolean(key, !enabled);
|
|
||||||
},
|
|
||||||
|
|
||||||
doTextSize: function(display, screen, window, binding, multiplier) {
|
|
||||||
// Same values used in the Seeing tab of the Universal Access panel
|
|
||||||
const FACTORS = [ 0.75, 1.0, 1.25, 1.5 ];
|
|
||||||
|
|
||||||
// Figure out the current DPI scaling factor
|
|
||||||
let settings = new Gio.Settings({ schema: INTERFACE_SETTINGS });
|
|
||||||
let factor = settings.get_double('text-scaling-factor');
|
|
||||||
factor += multiplier * 0.25;
|
|
||||||
|
|
||||||
/* Try to find a matching value */
|
|
||||||
let distance = 1e6;
|
|
||||||
let best = 1.0;
|
|
||||||
for (let i = 0; i < FACTORS.length; i++) {
|
|
||||||
let d = Math.abs(factor - FACTORS[i]);
|
|
||||||
if (d < distance) {
|
|
||||||
best = factors[i];
|
|
||||||
distance = d;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (best == 1.0)
|
|
||||||
settings.reset('text-scaling-factor');
|
|
||||||
else
|
|
||||||
settings.set_double('text-scaling-factor', best);
|
|
||||||
},
|
|
||||||
|
|
||||||
doToggleContrast: function(display, screen, window, binding) {
|
|
||||||
this._a11yControl.toggleHighContrast();
|
|
||||||
},
|
|
||||||
|
|
||||||
doMagnifierZoom: function(display, screen, window, binding, offset) {
|
|
||||||
let settings = new Gio.Settings({ schema: MAGNIFIER_SETTINGS });
|
|
||||||
|
|
||||||
let value = settings.get_value('mag-factor');
|
|
||||||
value = Math.round(value + offset);
|
|
||||||
settings.set_value('mag-factor', value);
|
|
||||||
},
|
|
||||||
|
|
||||||
doPowerAction: function(display, screen, window, binding, action) {
|
|
||||||
let settings = new Gio.Settings({ schema: POWER_SETTINGS });
|
|
||||||
switch (settings.get_string(action)) {
|
|
||||||
case 'suspend':
|
|
||||||
this._userMenu.suspend();
|
|
||||||
break;
|
|
||||||
case 'interactive':
|
|
||||||
case 'shutdown':
|
|
||||||
this._userMenu.shutdown();
|
|
||||||
break;
|
|
||||||
case 'hibernate':
|
|
||||||
this._userMenu.hibernate();
|
|
||||||
break;
|
|
||||||
case 'blank':
|
|
||||||
case 'default':
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_onBrightnessFinished: function(connection, result, kind) {
|
|
||||||
let [percentage] = connection.call_finish(result).deep_unpack();
|
|
||||||
|
|
||||||
let icon = kind == 'Keyboard' ? 'keyboard-brightness-symbolic' : 'display-brightness-symbolic';
|
|
||||||
showOSD(icon, percentage / 100);
|
|
||||||
},
|
|
||||||
|
|
||||||
doBrightness: function(display, screen, window, binding, kind, action) {
|
|
||||||
let iface = 'org.gnome.SettingsDaemon.Power.' + kind;
|
|
||||||
let objectPath = '/org/gnome/SettingsDaemon/Power';
|
|
||||||
|
|
||||||
Gio.DBus.session.call('org.gnome.SettingsDaemon',
|
|
||||||
objectPath, iface, action,
|
|
||||||
null, null, /* parameters, reply type */
|
|
||||||
Gio.DBusCallFlags.NONE, -1, null,
|
|
||||||
Lang.bind(this, this._onBrightnessFinished, kind));
|
|
||||||
},
|
|
||||||
|
|
||||||
doInputSource: function(display, screen, window, binding, offset) {
|
|
||||||
let settings = new Gio.Settings({ schema: INPUT_SOURCE_SETTINGS });
|
|
||||||
|
|
||||||
let current = settings.get_uint('current');
|
|
||||||
let max = settings.get_strv('sources').length - 1;
|
|
||||||
|
|
||||||
current += offset;
|
|
||||||
if (current < 0)
|
|
||||||
current = 0;
|
|
||||||
else if (current > max)
|
|
||||||
current = max;
|
|
||||||
|
|
||||||
settings.set_uint('current', current);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const Component = MediaKeysManager;
|
|
@@ -49,7 +49,7 @@ const AuthenticationDialog = new Lang.Class({
|
|||||||
let messageBox = new St.BoxLayout({ style_class: 'prompt-dialog-message-layout',
|
let messageBox = new St.BoxLayout({ style_class: 'prompt-dialog-message-layout',
|
||||||
vertical: true });
|
vertical: true });
|
||||||
mainContentBox.add(messageBox,
|
mainContentBox.add(messageBox,
|
||||||
{ y_align: St.Align.START });
|
{ expand: true, y_align: St.Align.START });
|
||||||
|
|
||||||
this._subjectLabel = new St.Label({ style_class: 'prompt-dialog-headline',
|
this._subjectLabel = new St.Label({ style_class: 'prompt-dialog-headline',
|
||||||
text: _("Authentication Required") });
|
text: _("Authentication Required") });
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
|
|
||||||
const Lang = imports.lang;
|
const Lang = imports.lang;
|
||||||
|
const Main = imports.ui.main;
|
||||||
|
|
||||||
const Gio = imports.gi.Gio;
|
const Gio = imports.gi.Gio;
|
||||||
const Meta = imports.gi.Meta;
|
const Meta = imports.gi.Meta;
|
||||||
@@ -16,13 +17,16 @@ const Recorder = new Lang.Class({
|
|||||||
},
|
},
|
||||||
|
|
||||||
enable: function() {
|
enable: function() {
|
||||||
global.display.add_keybinding('toggle-recording',
|
Main.wm.addKeybinding('toggle-recording',
|
||||||
this._bindingSettings,
|
this._bindingSettings,
|
||||||
Meta.KeyBindingFlags.NONE, Lang.bind(this, this._toggleRecorder));
|
Meta.KeyBindingFlags.NONE,
|
||||||
|
Main.KeybindingMode.NORMAL |
|
||||||
|
Main.KeybindingMode.OVERVIEW,
|
||||||
|
Lang.bind(this, this._toggleRecorder));
|
||||||
},
|
},
|
||||||
|
|
||||||
disable: function() {
|
disable: function() {
|
||||||
global.display.remove_keybinding('toggle-recording');
|
Main.wm.removeKeybinding('toggle-recording');
|
||||||
},
|
},
|
||||||
|
|
||||||
_ensureRecorder: function() {
|
_ensureRecorder: function() {
|
||||||
@@ -52,8 +56,6 @@ const Recorder = new Lang.Class({
|
|||||||
Meta.disable_unredirect_for_screen(global.screen);
|
Meta.disable_unredirect_for_screen(global.screen);
|
||||||
recorder.record();
|
recorder.record();
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -637,8 +637,10 @@ const Dash = new Lang.Class({
|
|||||||
icon.setIconSize(this.iconSize);
|
icon.setIconSize(this.iconSize);
|
||||||
|
|
||||||
// Don't animate the icon size change when the overview
|
// Don't animate the icon size change when the overview
|
||||||
// is not visible or when initially filling the dash
|
// is transitioning, not visible or when initially filling
|
||||||
if (!Main.overview.visible || !this._shownInitially)
|
// the dash
|
||||||
|
if (!Main.overview.visible || Main.overview.animationInProgress ||
|
||||||
|
!this._shownInitially)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
let [targetWidth, targetHeight] = icon.icon.get_size();
|
let [targetWidth, targetHeight] = icon.icon.get_size();
|
||||||
@@ -762,8 +764,9 @@ const Dash = new Lang.Class({
|
|||||||
for (let i = 0; i < removedActors.length; i++) {
|
for (let i = 0; i < removedActors.length; i++) {
|
||||||
let item = removedActors[i]._delegate;
|
let item = removedActors[i]._delegate;
|
||||||
|
|
||||||
// Don't animate item removal when the overview is hidden
|
// Don't animate item removal when the overview is transitioning
|
||||||
if (Main.overview.visible)
|
// or hidden
|
||||||
|
if (Main.overview.visible && !Main.overview.animationInProgress)
|
||||||
item.animateOutAndDestroy();
|
item.animateOutAndDestroy();
|
||||||
else
|
else
|
||||||
item.destroy();
|
item.destroy();
|
||||||
@@ -778,8 +781,9 @@ const Dash = new Lang.Class({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't animate item addition when the overview is hidden
|
// Don't animate item addition when the overview is transitioning
|
||||||
if (!Main.overview.visible)
|
// or hidden
|
||||||
|
if (!Main.overview.visible || Main.overview.animationInProgress)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (let i = 0; i < addedItems.length; i++)
|
for (let i = 0; i < addedItems.length; i++)
|
||||||
|
@@ -23,6 +23,7 @@ function _navigateActor(actor) {
|
|||||||
|
|
||||||
// GrabHelper:
|
// GrabHelper:
|
||||||
// @owner: the actor that owns the GrabHelper
|
// @owner: the actor that owns the GrabHelper
|
||||||
|
// @params: optional parameters to pass to Main.pushModal()
|
||||||
//
|
//
|
||||||
// Creates a new GrabHelper object, for dealing with keyboard and pointer grabs
|
// Creates a new GrabHelper object, for dealing with keyboard and pointer grabs
|
||||||
// associated with a set of actors.
|
// associated with a set of actors.
|
||||||
@@ -34,8 +35,9 @@ function _navigateActor(actor) {
|
|||||||
const GrabHelper = new Lang.Class({
|
const GrabHelper = new Lang.Class({
|
||||||
Name: 'GrabHelper',
|
Name: 'GrabHelper',
|
||||||
|
|
||||||
_init: function(owner) {
|
_init: function(owner, params) {
|
||||||
this._owner = owner;
|
this._owner = owner;
|
||||||
|
this._modalParams = params;
|
||||||
|
|
||||||
this._grabStack = [];
|
this._grabStack = [];
|
||||||
|
|
||||||
@@ -165,7 +167,7 @@ const GrabHelper = new Lang.Class({
|
|||||||
_takeModalGrab: function() {
|
_takeModalGrab: function() {
|
||||||
let firstGrab = (this._modalCount == 0);
|
let firstGrab = (this._modalCount == 0);
|
||||||
if (firstGrab) {
|
if (firstGrab) {
|
||||||
if (!Main.pushModal(this._owner))
|
if (!Main.pushModal(this._owner, this._modalParams))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
this._capturedEventId = global.stage.connect('captured-event', Lang.bind(this, this._onCapturedEvent));
|
this._capturedEventId = global.stage.connect('captured-event', Lang.bind(this, this._onCapturedEvent));
|
||||||
|
@@ -1129,7 +1129,7 @@ const LookingGlass = new Lang.Class({
|
|||||||
if (this._open)
|
if (this._open)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!Main.pushModal(this._entry))
|
if (!Main.pushModal(this._entry, { keybindingMode: Main.KeybindingMode.LOOKING_GLASS }))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this._notebook.selectIndex(0);
|
this._notebook.selectIndex(0);
|
||||||
|
@@ -20,6 +20,7 @@ const Keyboard = imports.ui.keyboard;
|
|||||||
const MessageTray = imports.ui.messageTray;
|
const MessageTray = imports.ui.messageTray;
|
||||||
const Overview = imports.ui.overview;
|
const Overview = imports.ui.overview;
|
||||||
const Panel = imports.ui.panel;
|
const Panel = imports.ui.panel;
|
||||||
|
const Params = imports.misc.params;
|
||||||
const RunDialog = imports.ui.runDialog;
|
const RunDialog = imports.ui.runDialog;
|
||||||
const Layout = imports.ui.layout;
|
const Layout = imports.ui.layout;
|
||||||
const LookingGlass = imports.ui.lookingGlass;
|
const LookingGlass = imports.ui.lookingGlass;
|
||||||
@@ -39,6 +40,18 @@ const Util = imports.misc.util;
|
|||||||
const OVERRIDES_SCHEMA = 'org.gnome.shell.overrides';
|
const OVERRIDES_SCHEMA = 'org.gnome.shell.overrides';
|
||||||
const DEFAULT_BACKGROUND_COLOR = Clutter.Color.from_pixel(0x2e3436ff);
|
const DEFAULT_BACKGROUND_COLOR = Clutter.Color.from_pixel(0x2e3436ff);
|
||||||
|
|
||||||
|
const KeybindingMode = {
|
||||||
|
NONE: 0, // block all keybindings
|
||||||
|
NORMAL: 1 << 0, // window mode
|
||||||
|
OVERVIEW: 1 << 1,
|
||||||
|
LOCK_SCREEN: 1 << 2,
|
||||||
|
UNLOCK_SCREEN: 1 << 3,
|
||||||
|
LOGIN_SCREEN: 1 << 4,
|
||||||
|
MESSAGE_TRAY: 1 << 5,
|
||||||
|
SYSTEM_MODAL: 1 << 6,
|
||||||
|
LOOKING_GLASS: 1 << 7
|
||||||
|
};
|
||||||
|
|
||||||
let componentManager = null;
|
let componentManager = null;
|
||||||
let panel = null;
|
let panel = null;
|
||||||
let overview = null;
|
let overview = null;
|
||||||
@@ -55,6 +68,7 @@ let shellDBusService = null;
|
|||||||
let shellMountOpDBusService = null;
|
let shellMountOpDBusService = null;
|
||||||
let screenSaverDBus = null;
|
let screenSaverDBus = null;
|
||||||
let modalCount = 0;
|
let modalCount = 0;
|
||||||
|
let keybindingMode = KeybindingMode.NORMAL;
|
||||||
let modalActorFocusStack = [];
|
let modalActorFocusStack = [];
|
||||||
let uiGroup = null;
|
let uiGroup = null;
|
||||||
let magnifier = null;
|
let magnifier = null;
|
||||||
@@ -69,7 +83,17 @@ let _overridesSettings = null;
|
|||||||
let background = null;
|
let background = null;
|
||||||
|
|
||||||
function _sessionUpdated() {
|
function _sessionUpdated() {
|
||||||
Meta.keybindings_set_custom_handler('internal-keybinding-panel-run-dialog', sessionMode.hasRunDialog ? Util.wrapKeybinding(openRunDialog, true) : null);
|
wm.setCustomKeybindingHandler('panel-main-menu',
|
||||||
|
KeybindingMode.NORMAL |
|
||||||
|
KeybindingMode.OVERVIEW,
|
||||||
|
sessionMode.hasOverview ? Lang.bind(overview, overview.toggle) : null);
|
||||||
|
wm.allowKeybinding('overlay-key', KeybindingMode.NORMAL |
|
||||||
|
KeybindingMode.OVERVIEW);
|
||||||
|
|
||||||
|
wm.setCustomKeybindingHandler('panel-run-dialog',
|
||||||
|
KeybindingMode.NORMAL |
|
||||||
|
KeybindingMode.OVERVIEW,
|
||||||
|
sessionMode.hasRunDialog ? openRunDialog : null);
|
||||||
if (sessionMode.isGreeter)
|
if (sessionMode.isGreeter)
|
||||||
screenShield.showDialog();
|
screenShield.showDialog();
|
||||||
}
|
}
|
||||||
@@ -155,15 +179,7 @@ function start() {
|
|||||||
|
|
||||||
global.screen.override_workspace_layout(Meta.ScreenCorner.TOPLEFT,
|
global.screen.override_workspace_layout(Meta.ScreenCorner.TOPLEFT,
|
||||||
false, -1, 1);
|
false, -1, 1);
|
||||||
Meta.keybindings_set_custom_handler('internal-keybinding-panel-main-menu', Util.wrapKeybinding(Lang.bind(overview, function() {
|
global.display.connect('overlay-key', Lang.bind(overview, overview.toggle));
|
||||||
this.toggle();
|
|
||||||
return true;
|
|
||||||
}), true));
|
|
||||||
global.display.connect('overlay-key', Util.wrapKeybinding(Lang.bind(overview, function() {
|
|
||||||
this.toggle();
|
|
||||||
return true;
|
|
||||||
}), true));
|
|
||||||
|
|
||||||
sessionMode.connect('update', _sessionUpdated);
|
sessionMode.connect('update', _sessionUpdated);
|
||||||
_sessionUpdated();
|
_sessionUpdated();
|
||||||
|
|
||||||
@@ -484,7 +500,7 @@ function isInModalStack(actor) {
|
|||||||
/**
|
/**
|
||||||
* pushModal:
|
* pushModal:
|
||||||
* @actor: #ClutterActor which will be given keyboard focus
|
* @actor: #ClutterActor which will be given keyboard focus
|
||||||
* @timestamp: optional timestamp
|
* @params: optional parameters
|
||||||
*
|
*
|
||||||
* Ensure we are in a mode where all keyboard and mouse input goes to
|
* Ensure we are in a mode where all keyboard and mouse input goes to
|
||||||
* the stage, and focus @actor. Multiple calls to this function act in
|
* the stage, and focus @actor. Multiple calls to this function act in
|
||||||
@@ -495,21 +511,27 @@ function isInModalStack(actor) {
|
|||||||
* modal stack returns to this actor, reset the focus to the actor
|
* modal stack returns to this actor, reset the focus to the actor
|
||||||
* which was focused at the time pushModal() was invoked.
|
* which was focused at the time pushModal() was invoked.
|
||||||
*
|
*
|
||||||
* @timestamp is optionally used to associate the call with a specific user
|
* @params may be used to provide the following parameters:
|
||||||
* initiated event. If not provided then the value of
|
* - timestamp: used to associate the call with a specific user initiated
|
||||||
* global.get_current_time() is assumed.
|
* event. If not provided then the value of
|
||||||
|
* global.get_current_time() is assumed.
|
||||||
*
|
*
|
||||||
* @options: optional Meta.ModalOptions flags to indicate that the
|
* - options: Meta.ModalOptions flags to indicate that the pointer is
|
||||||
* pointer is alrady grabbed
|
* already grabbed
|
||||||
|
*
|
||||||
|
* - keybindingMode: used to set the current Main.KeybindingMode to filter
|
||||||
|
* global keybindings; the default of NONE will filter
|
||||||
|
* out all keybindings
|
||||||
*
|
*
|
||||||
* Returns: true iff we successfully acquired a grab or already had one
|
* Returns: true iff we successfully acquired a grab or already had one
|
||||||
*/
|
*/
|
||||||
function pushModal(actor, timestamp, options) {
|
function pushModal(actor, params) {
|
||||||
if (timestamp == undefined)
|
params = Params.parse(params, { timestamp: global.get_current_time(),
|
||||||
timestamp = global.get_current_time();
|
options: 0,
|
||||||
|
keybindingMode: KeybindingMode.NONE });
|
||||||
|
|
||||||
if (modalCount == 0) {
|
if (modalCount == 0) {
|
||||||
if (!global.begin_modal(timestamp, options ? options : 0)) {
|
if (!global.begin_modal(params.timestamp, params.options)) {
|
||||||
log('pushModal: invocation of begin_modal failed');
|
log('pushModal: invocation of begin_modal failed');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -536,8 +558,10 @@ function pushModal(actor, timestamp, options) {
|
|||||||
modalActorFocusStack.push({ actor: actor,
|
modalActorFocusStack.push({ actor: actor,
|
||||||
focus: curFocus,
|
focus: curFocus,
|
||||||
destroyId: actorDestroyId,
|
destroyId: actorDestroyId,
|
||||||
focusDestroyId: curFocusDestroyId });
|
focusDestroyId: curFocusDestroyId,
|
||||||
|
keybindingMode: keybindingMode });
|
||||||
|
|
||||||
|
keybindingMode = params.keybindingMode;
|
||||||
global.stage.set_key_focus(actor);
|
global.stage.set_key_focus(actor);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -564,6 +588,7 @@ function popModal(actor, timestamp) {
|
|||||||
global.stage.set_key_focus(null);
|
global.stage.set_key_focus(null);
|
||||||
global.end_modal(timestamp);
|
global.end_modal(timestamp);
|
||||||
global.set_stage_input_mode(Shell.StageInputMode.NORMAL);
|
global.set_stage_input_mode(Shell.StageInputMode.NORMAL);
|
||||||
|
keybindingMode = KeybindingMode.NORMAL;
|
||||||
|
|
||||||
throw new Error('incorrect pop');
|
throw new Error('incorrect pop');
|
||||||
}
|
}
|
||||||
@@ -576,6 +601,7 @@ function popModal(actor, timestamp) {
|
|||||||
if (focusIndex == modalActorFocusStack.length - 1) {
|
if (focusIndex == modalActorFocusStack.length - 1) {
|
||||||
if (record.focus)
|
if (record.focus)
|
||||||
record.focus.disconnect(record.focusDestroyId);
|
record.focus.disconnect(record.focusDestroyId);
|
||||||
|
keybindingMode = record.keybindingMode;
|
||||||
global.stage.set_key_focus(record.focus);
|
global.stage.set_key_focus(record.focus);
|
||||||
} else {
|
} else {
|
||||||
let t = modalActorFocusStack[modalActorFocusStack.length - 1];
|
let t = modalActorFocusStack[modalActorFocusStack.length - 1];
|
||||||
@@ -585,6 +611,7 @@ function popModal(actor, timestamp) {
|
|||||||
for (let i = modalActorFocusStack.length - 1; i > focusIndex; i--) {
|
for (let i = modalActorFocusStack.length - 1; i > focusIndex; i--) {
|
||||||
modalActorFocusStack[i].focus = modalActorFocusStack[i - 1].focus;
|
modalActorFocusStack[i].focus = modalActorFocusStack[i - 1].focus;
|
||||||
modalActorFocusStack[i].focusDestroyId = modalActorFocusStack[i - 1].focusDestroyId;
|
modalActorFocusStack[i].focusDestroyId = modalActorFocusStack[i - 1].focusDestroyId;
|
||||||
|
modalActorFocusStack[i].keybindingMode = modalActorFocusStack[i - 1].keybindingMode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
modalActorFocusStack.splice(focusIndex, 1);
|
modalActorFocusStack.splice(focusIndex, 1);
|
||||||
@@ -595,6 +622,7 @@ function popModal(actor, timestamp) {
|
|||||||
global.end_modal(timestamp);
|
global.end_modal(timestamp);
|
||||||
global.set_stage_input_mode(Shell.StageInputMode.NORMAL);
|
global.set_stage_input_mode(Shell.StageInputMode.NORMAL);
|
||||||
Meta.enable_unredirect_for_screen(global.screen);
|
Meta.enable_unredirect_for_screen(global.screen);
|
||||||
|
keybindingMode = KeybindingMode.NORMAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
function createLookingGlass() {
|
function createLookingGlass() {
|
||||||
@@ -609,8 +637,6 @@ function openRunDialog() {
|
|||||||
runDialog = new RunDialog.RunDialog();
|
runDialog = new RunDialog.RunDialog();
|
||||||
}
|
}
|
||||||
runDialog.open();
|
runDialog.open();
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -1453,7 +1453,8 @@ const MessageTray = new Lang.Class({
|
|||||||
|
|
||||||
this.idleMonitor = new GnomeDesktop.IdleMonitor();
|
this.idleMonitor = new GnomeDesktop.IdleMonitor();
|
||||||
|
|
||||||
this._grabHelper = new GrabHelper.GrabHelper(this.actor);
|
this._grabHelper = new GrabHelper.GrabHelper(this.actor,
|
||||||
|
{ keybindingMode: Main.KeybindingMode.MESSAGE_TRAY });
|
||||||
this._grabHelper.addActor(this._summaryBoxPointer.actor);
|
this._grabHelper.addActor(this._summaryBoxPointer.actor);
|
||||||
this._grabHelper.addActor(this.actor);
|
this._grabHelper.addActor(this.actor);
|
||||||
if (Main.panel.statusArea.activities)
|
if (Main.panel.statusArea.activities)
|
||||||
@@ -1517,14 +1518,20 @@ const MessageTray = new Lang.Class({
|
|||||||
|
|
||||||
Main.sessionMode.connect('updated', Lang.bind(this, this._sessionUpdated));
|
Main.sessionMode.connect('updated', Lang.bind(this, this._sessionUpdated));
|
||||||
|
|
||||||
global.display.add_keybinding('toggle-message-tray',
|
Main.wm.addKeybinding('toggle-message-tray',
|
||||||
new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }),
|
new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }),
|
||||||
Meta.KeyBindingFlags.NONE,
|
Meta.KeyBindingFlags.NONE,
|
||||||
Lang.bind(this, this.toggleAndNavigate));
|
Main.KeybindingMode.NORMAL |
|
||||||
global.display.add_keybinding('focus-active-notification',
|
Main.KeybindingMode.MESSAGE_TRAY |
|
||||||
new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }),
|
Main.KeybindingMode.OVERVIEW,
|
||||||
Meta.KeyBindingFlags.NONE,
|
Lang.bind(this, this.toggleAndNavigate));
|
||||||
Lang.bind(this, this._expandActiveNotification));
|
Main.wm.addKeybinding('focus-active-notification',
|
||||||
|
new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }),
|
||||||
|
Meta.KeyBindingFlags.NONE,
|
||||||
|
Main.KeybindingMode.NORMAL |
|
||||||
|
Main.KeybindingMode.MESSAGE_TRAY |
|
||||||
|
Main.KeybindingMode.OVERVIEW,
|
||||||
|
Lang.bind(this, this._expandActiveNotification));
|
||||||
|
|
||||||
this._summaryItems = [];
|
this._summaryItems = [];
|
||||||
this._chatSummaryItemsCount = 0;
|
this._chatSummaryItemsCount = 0;
|
||||||
@@ -2310,6 +2317,18 @@ const MessageTray = new Lang.Class({
|
|||||||
},
|
},
|
||||||
|
|
||||||
_hideNotification: function() {
|
_hideNotification: function() {
|
||||||
|
// HACK!
|
||||||
|
// There seems to be a reentrancy issue in calling .ungrab() here,
|
||||||
|
// which causes _updateState to be called before _notificationState
|
||||||
|
// becomes HIDING. That hides the notification again, nullifying the
|
||||||
|
// object but not setting _notificationState (and that's the weird part)
|
||||||
|
// As then _notificationState is stuck into SHOWN but _notification
|
||||||
|
// is null, every new _updateState fails and the message tray is
|
||||||
|
// lost forever.
|
||||||
|
//
|
||||||
|
// See more at https://bugzilla.gnome.org/show_bug.cgi?id=683986
|
||||||
|
this._notificationState = State.HIDING;
|
||||||
|
|
||||||
this._grabHelper.ungrab({ actor: this._notification.actor });
|
this._grabHelper.ungrab({ actor: this._notification.actor });
|
||||||
|
|
||||||
if (this._idleMonitorBecameActiveId) {
|
if (this._idleMonitorBecameActiveId) {
|
||||||
@@ -2386,8 +2405,13 @@ const MessageTray = new Lang.Class({
|
|||||||
if (this._notificationWidget.y < expandedY) {
|
if (this._notificationWidget.y < expandedY) {
|
||||||
this._notificationWidget.y = expandedY;
|
this._notificationWidget.y = expandedY;
|
||||||
} else if (this._notification.y != expandedY) {
|
} else if (this._notification.y != expandedY) {
|
||||||
|
// Tween also opacity here, to override a possible tween that's
|
||||||
|
// currently hiding the notification. This will ensure that the
|
||||||
|
// notification is not removed when the onComplete handler for this
|
||||||
|
// one triggers.
|
||||||
this._tween(this._notificationWidget, '_notificationState', State.SHOWN,
|
this._tween(this._notificationWidget, '_notificationState', State.SHOWN,
|
||||||
{ y: expandedY,
|
{ y: expandedY,
|
||||||
|
opacity: 255,
|
||||||
time: ANIMATION_TIME,
|
time: ANIMATION_TIME,
|
||||||
transition: 'easeOutQuad'
|
transition: 'easeOutQuad'
|
||||||
});
|
});
|
||||||
|
@@ -37,10 +37,12 @@ const ModalDialog = new Lang.Class({
|
|||||||
params = Params.parse(params, { shellReactive: false,
|
params = Params.parse(params, { shellReactive: false,
|
||||||
styleClass: null,
|
styleClass: null,
|
||||||
parentActor: Main.uiGroup,
|
parentActor: Main.uiGroup,
|
||||||
|
keybindingMode: Main.KeybindingMode.SYSTEM_MODAL,
|
||||||
shouldFadeIn: true });
|
shouldFadeIn: true });
|
||||||
|
|
||||||
this.state = State.CLOSED;
|
this.state = State.CLOSED;
|
||||||
this._hasModal = false;
|
this._hasModal = false;
|
||||||
|
this._keybindingMode = params.keybindingMode;
|
||||||
this._shellReactive = params.shellReactive;
|
this._shellReactive = params.shellReactive;
|
||||||
this._shouldFadeIn = params.shouldFadeIn;
|
this._shouldFadeIn = params.shouldFadeIn;
|
||||||
|
|
||||||
@@ -226,7 +228,7 @@ const ModalDialog = new Lang.Class({
|
|||||||
if (this.state == State.OPENED || this.state == State.OPENING)
|
if (this.state == State.OPENED || this.state == State.OPENING)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!this.pushModal(timestamp))
|
if (!this.pushModal({ timestamp: timestamp }))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
this._fadeOpen(onPrimary);
|
this._fadeOpen(onPrimary);
|
||||||
@@ -276,7 +278,8 @@ const ModalDialog = new Lang.Class({
|
|||||||
pushModal: function (timestamp) {
|
pushModal: function (timestamp) {
|
||||||
if (this._hasModal)
|
if (this._hasModal)
|
||||||
return true;
|
return true;
|
||||||
if (!Main.pushModal(this._group, timestamp))
|
if (!Main.pushModal(this._group, { timestamp: timestamp,
|
||||||
|
keybindingMode: this._keybindingMode }))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
this._hasModal = true;
|
this._hasModal = true;
|
||||||
|
@@ -591,7 +591,7 @@ const Overview = new Lang.Class({
|
|||||||
if (this._shown)
|
if (this._shown)
|
||||||
return;
|
return;
|
||||||
// Do this manually instead of using _syncInputMode, to handle failure
|
// Do this manually instead of using _syncInputMode, to handle failure
|
||||||
if (!Main.pushModal(this._group))
|
if (!Main.pushModal(this._group, { keybindingMode: Main.KeybindingMode.OVERVIEW }))
|
||||||
return;
|
return;
|
||||||
this._modal = true;
|
this._modal = true;
|
||||||
this._animateVisible();
|
this._animateVisible();
|
||||||
@@ -742,7 +742,8 @@ const Overview = new Lang.Class({
|
|||||||
|
|
||||||
if (this._shown) {
|
if (this._shown) {
|
||||||
if (!this._modal) {
|
if (!this._modal) {
|
||||||
if (Main.pushModal(this._group))
|
if (Main.pushModal(this._group,
|
||||||
|
{ keybindingMode: Main.KeybindingMode.OVERVIEW }))
|
||||||
this._modal = true;
|
this._modal = true;
|
||||||
else
|
else
|
||||||
this.hide();
|
this.hide();
|
||||||
|
@@ -82,26 +82,34 @@ const AnimatedIcon = new Lang.Class({
|
|||||||
_init: function(name, size) {
|
_init: function(name, size) {
|
||||||
this.actor = new St.Bin({ visible: false });
|
this.actor = new St.Bin({ visible: false });
|
||||||
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
|
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
|
||||||
this.actor.connect('notify::visible', Lang.bind(this, this._onVisibleNotify));
|
|
||||||
|
|
||||||
|
this._isLoaded = false;
|
||||||
|
this._isPlaying = false;
|
||||||
this._timeoutId = 0;
|
this._timeoutId = 0;
|
||||||
this._frame = 0;
|
this._frame = 0;
|
||||||
this._animations = St.TextureCache.get_default().load_sliced_image (global.datadir + '/theme/' + name, size, size);
|
this._animations = St.TextureCache.get_default().load_sliced_image (global.datadir + '/theme/' + name, size, size,
|
||||||
|
Lang.bind(this, this._animationsLoaded));
|
||||||
this.actor.set_child(this._animations);
|
this.actor.set_child(this._animations);
|
||||||
},
|
},
|
||||||
|
|
||||||
_disconnectTimeout: function() {
|
play: function() {
|
||||||
|
if (this._isLoaded && this._timeoutId == 0) {
|
||||||
|
if (this._frame == 0)
|
||||||
|
this._showFrame(0);
|
||||||
|
|
||||||
|
this._timeoutId = Mainloop.timeout_add(ANIMATED_ICON_UPDATE_TIMEOUT, Lang.bind(this, this._update));
|
||||||
|
}
|
||||||
|
|
||||||
|
this._isPlaying = true;
|
||||||
|
},
|
||||||
|
|
||||||
|
stop: function() {
|
||||||
if (this._timeoutId > 0) {
|
if (this._timeoutId > 0) {
|
||||||
Mainloop.source_remove(this._timeoutId);
|
Mainloop.source_remove(this._timeoutId);
|
||||||
this._timeoutId = 0;
|
this._timeoutId = 0;
|
||||||
}
|
}
|
||||||
},
|
|
||||||
|
|
||||||
_onVisibleNotify: function() {
|
this._isPlaying = false;
|
||||||
if (this.actor.visible)
|
|
||||||
this._timeoutId = Mainloop.timeout_add(ANIMATED_ICON_UPDATE_TIMEOUT, Lang.bind(this, this._update));
|
|
||||||
else
|
|
||||||
this._disconnectTimeout();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_showFrame: function(frame) {
|
_showFrame: function(frame) {
|
||||||
@@ -121,8 +129,17 @@ const AnimatedIcon = new Lang.Class({
|
|||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_animationsLoaded: function() {
|
||||||
|
this._isLoaded = true;
|
||||||
|
|
||||||
|
if (this._isPlaying) {
|
||||||
|
this._showFrame(0);
|
||||||
|
this._timeoutId = Mainloop.timeout_add(ANIMATED_ICON_UPDATE_TIMEOUT, Lang.bind(this, this._update));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
_onDestroy: function() {
|
_onDestroy: function() {
|
||||||
this._disconnectTimeout();
|
this.stop();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -367,6 +384,7 @@ const AppMenuButton = new Lang.Class({
|
|||||||
transition: "easeOutQuad",
|
transition: "easeOutQuad",
|
||||||
onCompleteScope: this,
|
onCompleteScope: this,
|
||||||
onComplete: function() {
|
onComplete: function() {
|
||||||
|
this._spinner.stop();
|
||||||
this._spinner.actor.opacity = 255;
|
this._spinner.actor.opacity = 255;
|
||||||
this._spinner.actor.hide();
|
this._spinner.actor.hide();
|
||||||
}
|
}
|
||||||
@@ -376,6 +394,7 @@ const AppMenuButton = new Lang.Class({
|
|||||||
startAnimation: function() {
|
startAnimation: function() {
|
||||||
this._stop = false;
|
this._stop = false;
|
||||||
this.actor.reactive = false;
|
this.actor.reactive = false;
|
||||||
|
this._spinner.play();
|
||||||
this._spinner.actor.show();
|
this._spinner.actor.show();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@@ -31,10 +31,13 @@ const SearchProviderIface = <interface name="org.gnome.Shell.SearchProvider">
|
|||||||
|
|
||||||
var SearchProviderProxy = Gio.DBusProxy.makeProxyWrapper(SearchProviderIface);
|
var SearchProviderProxy = Gio.DBusProxy.makeProxyWrapper(SearchProviderIface);
|
||||||
|
|
||||||
|
|
||||||
function loadRemoteSearchProviders(addProviderCallback) {
|
function loadRemoteSearchProviders(addProviderCallback) {
|
||||||
|
let loadState = { loadedProviders: [],
|
||||||
|
objectPaths: {},
|
||||||
|
numLoading: 0,
|
||||||
|
addProviderCallback: addProviderCallback };
|
||||||
|
|
||||||
let dataDirs = GLib.get_system_data_dirs();
|
let dataDirs = GLib.get_system_data_dirs();
|
||||||
let loadedProviders = {};
|
|
||||||
for (let i = 0; i < dataDirs.length; i++) {
|
for (let i = 0; i < dataDirs.length; i++) {
|
||||||
let path = GLib.build_filenamev([dataDirs[i], 'gnome-shell', 'search-providers']);
|
let path = GLib.build_filenamev([dataDirs[i], 'gnome-shell', 'search-providers']);
|
||||||
let dir = Gio.file_new_for_path(path);
|
let dir = Gio.file_new_for_path(path);
|
||||||
@@ -52,12 +55,13 @@ function loadRemoteSearchProviders(addProviderCallback) {
|
|||||||
if (!exists)
|
if (!exists)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
loadRemoteSearchProvidersFromDir(dir, loadedProviders, addProviderCallback);
|
loadState.numLoading++;
|
||||||
|
loadRemoteSearchProvidersFromDir(dir, loadState);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function loadRemoteSearchProvidersFromDir(dir, loadedProviders, addProviderCallback) {
|
function loadRemoteSearchProvidersFromDir(dir, loadState) {
|
||||||
let dirPath = dir.get_path();
|
let dirPath = dir.get_path();
|
||||||
FileUtils.listDirAsync(dir, Lang.bind(this, function(files) {
|
FileUtils.listDirAsync(dir, Lang.bind(this, function(files) {
|
||||||
for (let i = 0; i < files.length; i++) {
|
for (let i = 0; i < files.length; i++) {
|
||||||
@@ -79,7 +83,7 @@ function loadRemoteSearchProvidersFromDir(dir, loadedProviders, addProviderCallb
|
|||||||
let busName = keyfile.get_string(group, 'BusName');
|
let busName = keyfile.get_string(group, 'BusName');
|
||||||
let objectPath = keyfile.get_string(group, 'ObjectPath');
|
let objectPath = keyfile.get_string(group, 'ObjectPath');
|
||||||
|
|
||||||
if (loadedProviders[objectPath])
|
if (loadState.objectPaths[objectPath])
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
let appInfo = null;
|
let appInfo = null;
|
||||||
@@ -91,31 +95,82 @@ function loadRemoteSearchProvidersFromDir(dir, loadedProviders, addProviderCallb
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
remoteProvider = new RemoteSearchProvider(appInfo.get_name(),
|
remoteProvider = new RemoteSearchProvider(appInfo,
|
||||||
appInfo.get_icon(),
|
|
||||||
busName,
|
busName,
|
||||||
objectPath);
|
objectPath);
|
||||||
loadedProviders[objectPath] = remoteProvider;
|
loadState.objectPaths[objectPath] = remoteProvider;
|
||||||
|
loadState.loadedProviders.push(remoteProvider);
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
log('Failed to add search provider %s: %s'.format(path, e.toString()));
|
log('Failed to add search provider %s: %s'.format(path, e.toString()));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
addProviderCallback(remoteProvider);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
remoteProvidersDirLoaded(loadState);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function remoteProvidersDirLoaded(loadState) {
|
||||||
|
loadState.numLoading--;
|
||||||
|
if (loadState.numLoading > 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
let searchSettings = new Gio.Settings({ schema: Search.SEARCH_PROVIDERS_SCHEMA });
|
||||||
|
let sortOrder = searchSettings.get_strv('sort-order');
|
||||||
|
let numSorted = sortOrder.length;
|
||||||
|
|
||||||
|
loadState.loadedProviders.sort(
|
||||||
|
function(providerA, providerB) {
|
||||||
|
let idxA, idxB;
|
||||||
|
let appIdA, appIdB;
|
||||||
|
|
||||||
|
appIdA = providerA.appInfo.get_id();
|
||||||
|
appIdB = providerB.appInfo.get_id();
|
||||||
|
|
||||||
|
idxA = sortOrder.indexOf(appIdA);
|
||||||
|
idxB = sortOrder.indexOf(appIdB);
|
||||||
|
|
||||||
|
// if no provider is found in the order, use alphabetical order
|
||||||
|
if ((idxA == -1) && (idxB == -1))
|
||||||
|
return GLib.utf8_collate(providerA.title, providerB.title);
|
||||||
|
|
||||||
|
if (numSorted > 1) {
|
||||||
|
// if providerA is the last, it goes after everything
|
||||||
|
if ((idxA + 1) == numSorted)
|
||||||
|
return 1;
|
||||||
|
// if providerB is the last, it goes after everything
|
||||||
|
else if ((idxB + 1) == numSorted)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if providerA isn't found, it's sorted after providerB
|
||||||
|
if (idxA == -1)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
// if providerB isn't found, it's sorted after providerA
|
||||||
|
if (idxB == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
// finally, if both providers are found, return their order in the list
|
||||||
|
return (idxA - idxB);
|
||||||
|
});
|
||||||
|
|
||||||
|
loadState.loadedProviders.forEach(
|
||||||
|
function(provider) {
|
||||||
|
loadState.addProviderCallback(provider);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const RemoteSearchProvider = new Lang.Class({
|
const RemoteSearchProvider = new Lang.Class({
|
||||||
Name: 'RemoteSearchProvider',
|
Name: 'RemoteSearchProvider',
|
||||||
Extends: Search.SearchProvider,
|
Extends: Search.SearchProvider,
|
||||||
|
|
||||||
_init: function(title, icon, dbusName, dbusPath) {
|
_init: function(appInfo, dbusName, dbusPath) {
|
||||||
this._proxy = new SearchProviderProxy(Gio.DBus.session,
|
this._proxy = new SearchProviderProxy(Gio.DBus.session,
|
||||||
dbusName, dbusPath, Lang.bind(this, this._onProxyConstructed));
|
dbusName, dbusPath, Lang.bind(this, this._onProxyConstructed));
|
||||||
|
|
||||||
this.parent(title.toUpperCase());
|
this.parent(appInfo.get_name().toUpperCase(), appInfo, true);
|
||||||
this._cancellable = new Gio.Cancellable();
|
this._cancellable = new Gio.Cancellable();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@@ -51,10 +51,11 @@ const SHORT_FADE_TIME = 0.3;
|
|||||||
|
|
||||||
function sample(offx, offy) {
|
function sample(offx, offy) {
|
||||||
return 'texel += texture2D (sampler, tex_coord.st + pixel_step * ' +
|
return 'texel += texture2D (sampler, tex_coord.st + pixel_step * ' +
|
||||||
'vec2 (' + offx + ',' + offy + ') * 2.0);\n'
|
'vec2 (' + offx + ',' + offy + '));\n'
|
||||||
}
|
}
|
||||||
const GLSL_BLUR_EFFECT_DECLARATIONS = ' \
|
const GLSL_BLUR_EFFECT_DECLARATIONS = ' \
|
||||||
uniform vec2 pixel_step;\n \
|
uniform vec2 pixel_step;\n \
|
||||||
|
uniform float desaturation;\n \
|
||||||
vec4 apply_blur(in sampler2D sampler, in vec2 tex_coord) {\n \
|
vec4 apply_blur(in sampler2D sampler, in vec2 tex_coord) {\n \
|
||||||
vec4 texel;\n \
|
vec4 texel;\n \
|
||||||
texel = texture2D (sampler, tex_coord.st);\n'
|
texel = texture2D (sampler, tex_coord.st);\n'
|
||||||
@@ -62,7 +63,6 @@ vec4 apply_blur(in sampler2D sampler, in vec2 tex_coord) {\n \
|
|||||||
+ sample( 0.0, -1.0)
|
+ sample( 0.0, -1.0)
|
||||||
+ sample(+1.0, -1.0)
|
+ sample(+1.0, -1.0)
|
||||||
+ sample(-1.0, 0.0)
|
+ sample(-1.0, 0.0)
|
||||||
+ sample( 0.0, 0.0)
|
|
||||||
+ sample(+1.0, 0.0)
|
+ sample(+1.0, 0.0)
|
||||||
+ sample(-1.0, +1.0)
|
+ sample(-1.0, +1.0)
|
||||||
+ sample( 0.0, +1.0)
|
+ sample( 0.0, +1.0)
|
||||||
@@ -70,7 +70,7 @@ vec4 apply_blur(in sampler2D sampler, in vec2 tex_coord) {\n \
|
|||||||
texel /= 9.0;\n \
|
texel /= 9.0;\n \
|
||||||
return texel;\n \
|
return texel;\n \
|
||||||
}\n \
|
}\n \
|
||||||
vec3 desaturate (const vec3 color, const float desaturation)\n \
|
vec3 desaturate (const vec3 color)\n \
|
||||||
{\n \
|
{\n \
|
||||||
const vec3 gray_conv = vec3 (0.299, 0.587, 0.114);\n \
|
const vec3 gray_conv = vec3 (0.299, 0.587, 0.114);\n \
|
||||||
vec3 gray = vec3 (dot (gray_conv, color));\n \
|
vec3 gray = vec3 (dot (gray_conv, color));\n \
|
||||||
@@ -78,7 +78,7 @@ vec3 desaturate (const vec3 color, const float desaturation)\n \
|
|||||||
}';
|
}';
|
||||||
const GLSL_BLUR_EFFECT_CODE = ' \
|
const GLSL_BLUR_EFFECT_CODE = ' \
|
||||||
cogl_texel = apply_blur(cogl_sampler, cogl_tex_coord.st);\n \
|
cogl_texel = apply_blur(cogl_sampler, cogl_tex_coord.st);\n \
|
||||||
cogl_texel.rgb = desaturate(cogl_texel.rgb, 0.6);\n';
|
cogl_texel.rgb = desaturate(cogl_texel.rgb);\n';
|
||||||
|
|
||||||
|
|
||||||
const Clock = new Lang.Class({
|
const Clock = new Lang.Class({
|
||||||
@@ -398,6 +398,7 @@ const ScreenShield = new Lang.Class({
|
|||||||
Lang.bind(this, this._onLockScreenKeyRelease));
|
Lang.bind(this, this._onLockScreenKeyRelease));
|
||||||
this._lockScreenGroup.connect('scroll-event',
|
this._lockScreenGroup.connect('scroll-event',
|
||||||
Lang.bind(this, this._onLockScreenScroll));
|
Lang.bind(this, this._onLockScreenScroll));
|
||||||
|
Main.ctrlAltTabManager.addGroup(this._lockScreenGroup, _("Lock"), 'changes-prevent-symbolic');
|
||||||
|
|
||||||
this._lockScreenContents = new St.Widget({ layout_manager: new Clutter.BinLayout(),
|
this._lockScreenContents = new St.Widget({ layout_manager: new Clutter.BinLayout(),
|
||||||
name: 'lockScreenContents' });
|
name: 'lockScreenContents' });
|
||||||
@@ -408,6 +409,12 @@ const ScreenShield = new Lang.Class({
|
|||||||
GLSL_BLUR_EFFECT_DECLARATIONS,
|
GLSL_BLUR_EFFECT_DECLARATIONS,
|
||||||
GLSL_BLUR_EFFECT_CODE,
|
GLSL_BLUR_EFFECT_CODE,
|
||||||
true);
|
true);
|
||||||
|
backgroundActor.set_uniform_float('desaturation',
|
||||||
|
1, 1, [0.6]);
|
||||||
|
backgroundActor.connect('notify::size', function(actor) {
|
||||||
|
actor.set_uniform_float('pixel_step', 2, 1, [1/actor.width, 1/actor.height]);
|
||||||
|
});
|
||||||
|
|
||||||
this._background = new St.Bin({ style_class: 'screen-shield-background',
|
this._background = new St.Bin({ style_class: 'screen-shield-background',
|
||||||
child: backgroundActor });
|
child: backgroundActor });
|
||||||
this._lockScreenGroup.add_actor(this._background);
|
this._lockScreenGroup.add_actor(this._background);
|
||||||
@@ -611,7 +618,7 @@ const ScreenShield = new Lang.Class({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!this._isModal) {
|
if (!this._isModal) {
|
||||||
Main.pushModal(this.actor);
|
Main.pushModal(this.actor, { keybindingMode: Main.KeybindingMode.LOCK_SCREEN });
|
||||||
this._isModal = true;
|
this._isModal = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -713,13 +720,15 @@ const ScreenShield = new Lang.Class({
|
|||||||
_ensureUnlockDialog: function(onPrimary) {
|
_ensureUnlockDialog: function(onPrimary) {
|
||||||
if (!this._dialog) {
|
if (!this._dialog) {
|
||||||
let constructor = Main.sessionMode.unlockDialog;
|
let constructor = Main.sessionMode.unlockDialog;
|
||||||
this._dialog = new constructor(this._lockDialogGroup);
|
if (!constructor) {
|
||||||
if (!this._dialog) {
|
|
||||||
// This session mode has no locking capabilities
|
// This session mode has no locking capabilities
|
||||||
this.unlock();
|
this.unlock();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._dialog = new constructor(this._lockDialogGroup);
|
||||||
|
|
||||||
|
|
||||||
let time = global.get_current_time();
|
let time = global.get_current_time();
|
||||||
this._dialog.connect('loaded', Lang.bind(this, function() {
|
this._dialog.connect('loaded', Lang.bind(this, function() {
|
||||||
if (!this._dialog.open(time, onPrimary)) {
|
if (!this._dialog.open(time, onPrimary)) {
|
||||||
@@ -918,7 +927,7 @@ const ScreenShield = new Lang.Class({
|
|||||||
|
|
||||||
lock: function(animate) {
|
lock: function(animate) {
|
||||||
if (!this._isModal) {
|
if (!this._isModal) {
|
||||||
Main.pushModal(this.actor);
|
Main.pushModal(this.actor, { keybindingMode: Main.KeybindingMode.LOCK_SCREEN });
|
||||||
this._isModal = true;
|
this._isModal = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -10,6 +10,8 @@ const Util = imports.misc.util;
|
|||||||
const FileUtils = imports.misc.fileUtils;
|
const FileUtils = imports.misc.fileUtils;
|
||||||
const Main = imports.ui.main;
|
const Main = imports.ui.main;
|
||||||
|
|
||||||
|
const SEARCH_PROVIDERS_SCHEMA = 'org.gnome.desktop.search-providers';
|
||||||
|
|
||||||
// Not currently referenced by the search API, but
|
// Not currently referenced by the search API, but
|
||||||
// this enumeration can be useful for provider
|
// this enumeration can be useful for provider
|
||||||
// implementations.
|
// implementations.
|
||||||
@@ -74,9 +76,11 @@ const SearchResultDisplay = new Lang.Class({
|
|||||||
const SearchProvider = new Lang.Class({
|
const SearchProvider = new Lang.Class({
|
||||||
Name: 'SearchProvider',
|
Name: 'SearchProvider',
|
||||||
|
|
||||||
_init: function(title) {
|
_init: function(title, appInfo, isRemoteProvider) {
|
||||||
this.title = title;
|
this.title = title;
|
||||||
|
this.appInfo = appInfo;
|
||||||
this.searchSystem = null;
|
this.searchSystem = null;
|
||||||
|
this.isRemoteProvider = !!isRemoteProvider;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -172,12 +176,16 @@ const SearchSystem = new Lang.Class({
|
|||||||
|
|
||||||
_init: function() {
|
_init: function() {
|
||||||
this._providers = [];
|
this._providers = [];
|
||||||
|
this._remoteProviders = [];
|
||||||
this.reset();
|
this.reset();
|
||||||
},
|
},
|
||||||
|
|
||||||
registerProvider: function (provider) {
|
registerProvider: function (provider) {
|
||||||
provider.searchSystem = this;
|
provider.searchSystem = this;
|
||||||
this._providers.push(provider);
|
this._providers.push(provider);
|
||||||
|
|
||||||
|
if (provider.isRemoteProvider)
|
||||||
|
this._remoteProviders.push(provider);
|
||||||
},
|
},
|
||||||
|
|
||||||
unregisterProvider: function (provider) {
|
unregisterProvider: function (provider) {
|
||||||
@@ -186,12 +194,20 @@ const SearchSystem = new Lang.Class({
|
|||||||
return;
|
return;
|
||||||
provider.searchSystem = null;
|
provider.searchSystem = null;
|
||||||
this._providers.splice(index, 1);
|
this._providers.splice(index, 1);
|
||||||
|
|
||||||
|
let remoteIndex = this._remoteProviders.indexOf(provider);
|
||||||
|
if (remoteIndex != -1)
|
||||||
|
this._remoteProviders.splice(index, 1);
|
||||||
},
|
},
|
||||||
|
|
||||||
getProviders: function() {
|
getProviders: function() {
|
||||||
return this._providers;
|
return this._providers;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getRemoteProviders: function() {
|
||||||
|
return this._remoteProviders;
|
||||||
|
},
|
||||||
|
|
||||||
getTerms: function() {
|
getTerms: function() {
|
||||||
return this._previousTerms;
|
return this._previousTerms;
|
||||||
},
|
},
|
||||||
|
@@ -14,7 +14,6 @@ const _modes = {
|
|||||||
showCalendarEvents: false,
|
showCalendarEvents: false,
|
||||||
allowSettings: false,
|
allowSettings: false,
|
||||||
allowExtensions: false,
|
allowExtensions: false,
|
||||||
allowKeybindingsWhenModal: false,
|
|
||||||
hasRunDialog: false,
|
hasRunDialog: false,
|
||||||
hasWorkspaces: false,
|
hasWorkspaces: false,
|
||||||
hasWindows: false,
|
hasWindows: false,
|
||||||
@@ -32,12 +31,11 @@ const _modes = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
'gdm': {
|
'gdm': {
|
||||||
allowKeybindingsWhenModal: true,
|
|
||||||
hasNotifications: true,
|
hasNotifications: true,
|
||||||
isGreeter: true,
|
isGreeter: true,
|
||||||
isPrimary: true,
|
isPrimary: true,
|
||||||
unlockDialog: imports.gdm.loginDialog.LoginDialog,
|
unlockDialog: imports.gdm.loginDialog.LoginDialog,
|
||||||
components: ['polkitAgent', 'mediaKeysManager'],
|
components: ['polkitAgent'],
|
||||||
panel: {
|
panel: {
|
||||||
left: ['logo'],
|
left: ['logo'],
|
||||||
center: ['dateMenu'],
|
center: ['dateMenu'],
|
||||||
@@ -50,7 +48,7 @@ const _modes = {
|
|||||||
isLocked: true,
|
isLocked: true,
|
||||||
isGreeter: undefined,
|
isGreeter: undefined,
|
||||||
unlockDialog: undefined,
|
unlockDialog: undefined,
|
||||||
components: ['polkitAgent', 'telepathyClient', 'mediaKeysManager'],
|
components: ['polkitAgent', 'telepathyClient'],
|
||||||
panel: {
|
panel: {
|
||||||
left: ['userMenu'],
|
left: ['userMenu'],
|
||||||
center: [],
|
center: [],
|
||||||
@@ -61,7 +59,7 @@ const _modes = {
|
|||||||
'unlock-dialog': {
|
'unlock-dialog': {
|
||||||
isLocked: true,
|
isLocked: true,
|
||||||
unlockDialog: undefined,
|
unlockDialog: undefined,
|
||||||
components: ['polkitAgent', 'telepathyClient', 'mediaKeysManager'],
|
components: ['polkitAgent', 'telepathyClient'],
|
||||||
panel: {
|
panel: {
|
||||||
left: ['userMenu'],
|
left: ['userMenu'],
|
||||||
center: [],
|
center: [],
|
||||||
@@ -71,7 +69,7 @@ const _modes = {
|
|||||||
|
|
||||||
'initial-setup': {
|
'initial-setup': {
|
||||||
isPrimary: true,
|
isPrimary: true,
|
||||||
components: ['keyring', 'mediaKeysManager'],
|
components: ['keyring'],
|
||||||
panel: {
|
panel: {
|
||||||
left: [],
|
left: [],
|
||||||
center: ['dateMenu'],
|
center: ['dateMenu'],
|
||||||
@@ -91,9 +89,8 @@ const _modes = {
|
|||||||
isLocked: false,
|
isLocked: false,
|
||||||
isPrimary: true,
|
isPrimary: true,
|
||||||
unlockDialog: imports.ui.unlockDialog.UnlockDialog,
|
unlockDialog: imports.ui.unlockDialog.UnlockDialog,
|
||||||
components: ['networkAgent', 'polkitAgent', 'telepathyClient', 'keyring',
|
components: ['networkAgent', 'polkitAgent', 'telepathyClient',
|
||||||
'recorder', 'autorunManager', 'automountManager',
|
'keyring', 'recorder', 'autorunManager', 'automountManager'],
|
||||||
'mediaKeysManager'],
|
|
||||||
panel: {
|
panel: {
|
||||||
left: ['activities', 'appMenu'],
|
left: ['activities', 'appMenu'],
|
||||||
center: ['dateMenu'],
|
center: ['dateMenu'],
|
||||||
|
@@ -27,6 +27,7 @@ const KEY_VISUAL_BELL = 'visual-bell';
|
|||||||
const DESKTOP_INTERFACE_SCHEMA = 'org.gnome.desktop.interface';
|
const DESKTOP_INTERFACE_SCHEMA = 'org.gnome.desktop.interface';
|
||||||
const KEY_GTK_THEME = 'gtk-theme';
|
const KEY_GTK_THEME = 'gtk-theme';
|
||||||
const KEY_ICON_THEME = 'icon-theme';
|
const KEY_ICON_THEME = 'icon-theme';
|
||||||
|
const KEY_WM_THEME = 'theme';
|
||||||
const KEY_TEXT_SCALING_FACTOR = 'text-scaling-factor';
|
const KEY_TEXT_SCALING_FACTOR = 'text-scaling-factor';
|
||||||
|
|
||||||
const HIGH_CONTRAST_THEME = 'HighContrast';
|
const HIGH_CONTRAST_THEME = 'HighContrast';
|
||||||
@@ -38,8 +39,8 @@ const ATIndicator = new Lang.Class({
|
|||||||
_init: function() {
|
_init: function() {
|
||||||
this.parent('preferences-desktop-accessibility-symbolic', _("Accessibility"));
|
this.parent('preferences-desktop-accessibility-symbolic', _("Accessibility"));
|
||||||
|
|
||||||
this._highContrast = this._buildHCItem();
|
let highContrast = this._buildHCItem();
|
||||||
this.menu.addMenuItem(this._highContrast);
|
this.menu.addMenuItem(highContrast);
|
||||||
|
|
||||||
let magnifier = this._buildItem(_("Zoom"), APPLICATIONS_SCHEMA,
|
let magnifier = this._buildItem(_("Zoom"), APPLICATIONS_SCHEMA,
|
||||||
'screen-magnifier-enabled');
|
'screen-magnifier-enabled');
|
||||||
@@ -101,28 +102,35 @@ const ATIndicator = new Lang.Class({
|
|||||||
},
|
},
|
||||||
|
|
||||||
_buildHCItem: function() {
|
_buildHCItem: function() {
|
||||||
let settings = new Gio.Settings({ schema: DESKTOP_INTERFACE_SCHEMA });
|
let interfaceSettings = new Gio.Settings({ schema: DESKTOP_INTERFACE_SCHEMA });
|
||||||
let gtkTheme = settings.get_string(KEY_GTK_THEME);
|
let wmSettings = new Gio.Settings({ schema: WM_SCHEMA });
|
||||||
let iconTheme = settings.get_string(KEY_ICON_THEME);
|
let gtkTheme = interfaceSettings.get_string(KEY_GTK_THEME);
|
||||||
|
let iconTheme = interfaceSettings.get_string(KEY_ICON_THEME);
|
||||||
|
let wmTheme = wmSettings.get_string(KEY_WM_THEME);
|
||||||
let hasHC = (gtkTheme == HIGH_CONTRAST_THEME);
|
let hasHC = (gtkTheme == HIGH_CONTRAST_THEME);
|
||||||
let highContrast = this._buildItemExtended(
|
let highContrast = this._buildItemExtended(
|
||||||
_("High Contrast"),
|
_("High Contrast"),
|
||||||
hasHC,
|
hasHC,
|
||||||
settings.is_writable(KEY_GTK_THEME) && settings.is_writable(KEY_ICON_THEME),
|
interfaceSettings.is_writable(KEY_GTK_THEME) &&
|
||||||
|
interfaceSettings.is_writable(KEY_ICON_THEME) &&
|
||||||
|
wmSettings.is_writable(KEY_WM_THEME),
|
||||||
function (enabled) {
|
function (enabled) {
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
settings.set_string(KEY_GTK_THEME, HIGH_CONTRAST_THEME);
|
interfaceSettings.set_string(KEY_GTK_THEME, HIGH_CONTRAST_THEME);
|
||||||
settings.set_string(KEY_ICON_THEME, HIGH_CONTRAST_THEME);
|
interfaceSettings.set_string(KEY_ICON_THEME, HIGH_CONTRAST_THEME);
|
||||||
|
wmSettings.set_string(KEY_WM_THEME, HIGH_CONTRAST_THEME);
|
||||||
} else if(!hasHC) {
|
} else if(!hasHC) {
|
||||||
settings.set_string(KEY_GTK_THEME, gtkTheme);
|
interfaceSettings.set_string(KEY_GTK_THEME, gtkTheme);
|
||||||
settings.set_string(KEY_ICON_THEME, iconTheme);
|
interfaceSettings.set_string(KEY_ICON_THEME, iconTheme);
|
||||||
|
wmSettings.set_string(KEY_WM_THEME, wmTheme);
|
||||||
} else {
|
} else {
|
||||||
settings.reset(KEY_GTK_THEME);
|
interfaceSettings.reset(KEY_GTK_THEME);
|
||||||
settings.reset(KEY_ICON_THEME);
|
interfaceSettings.reset(KEY_ICON_THEME);
|
||||||
|
wmSettings.reset(KEY_WM_THEME);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
settings.connect('changed::' + KEY_GTK_THEME, function() {
|
interfaceSettings.connect('changed::' + KEY_GTK_THEME, function() {
|
||||||
let value = settings.get_string(KEY_GTK_THEME);
|
let value = interfaceSettings.get_string(KEY_GTK_THEME);
|
||||||
if (value == HIGH_CONTRAST_THEME) {
|
if (value == HIGH_CONTRAST_THEME) {
|
||||||
highContrast.setToggleState(true);
|
highContrast.setToggleState(true);
|
||||||
} else {
|
} else {
|
||||||
@@ -130,11 +138,16 @@ const ATIndicator = new Lang.Class({
|
|||||||
gtkTheme = value;
|
gtkTheme = value;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
settings.connect('changed::' + KEY_ICON_THEME, function() {
|
interfaceSettings.connect('changed::' + KEY_ICON_THEME, function() {
|
||||||
let value = settings.get_string(KEY_ICON_THEME);
|
let value = interfaceSettings.get_string(KEY_ICON_THEME);
|
||||||
if (value != HIGH_CONTRAST_THEME)
|
if (value != HIGH_CONTRAST_THEME)
|
||||||
iconTheme = value;
|
iconTheme = value;
|
||||||
});
|
});
|
||||||
|
wmSettings.connect('changed::' + KEY_WM_THEME, function() {
|
||||||
|
let value = wmSettings.get_string(KEY_WM_THEME);
|
||||||
|
if (value != HIGH_CONTRAST_THEME)
|
||||||
|
wmTheme = value;
|
||||||
|
});
|
||||||
return highContrast;
|
return highContrast;
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -159,9 +172,5 @@ const ATIndicator = new Lang.Class({
|
|||||||
widget.setToggleState(active);
|
widget.setToggleState(active);
|
||||||
});
|
});
|
||||||
return widget;
|
return widget;
|
||||||
},
|
}
|
||||||
|
|
||||||
toggleHighContrast: function() {
|
|
||||||
this._highContrast.toggle();
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
@@ -239,22 +239,6 @@ const Indicator = new Lang.Class({
|
|||||||
this._applet.send_to_address(device.bdaddr, device.alias);
|
this._applet.send_to_address(device.bdaddr, device.alias);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
if (device.capabilities & GnomeBluetoothApplet.Capabilities.OBEX_FILE_TRANSFER) {
|
|
||||||
item.menu.addAction(_("Browse Files..."), Lang.bind(this, function(event) {
|
|
||||||
this._applet.browse_address(device.bdaddr, event.get_time(),
|
|
||||||
Lang.bind(this, function(applet, result) {
|
|
||||||
try {
|
|
||||||
applet.browse_address_finish(result);
|
|
||||||
} catch (e) {
|
|
||||||
this._ensureSource();
|
|
||||||
this._source.notify(new MessageTray.Notification(this._source,
|
|
||||||
_("Bluetooth"),
|
|
||||||
_("Error browsing device"),
|
|
||||||
{ body: _("The requested device cannot be browsed, error is '%s'").format(e) }));
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (device.type) {
|
switch (device.type) {
|
||||||
case GnomeBluetoothApplet.Type.KEYBOARD:
|
case GnomeBluetoothApplet.Type.KEYBOARD:
|
||||||
@@ -369,6 +353,7 @@ const ConfirmNotification = new Lang.Class({
|
|||||||
_init: function(source, applet, device_path, name, long_name, pin) {
|
_init: function(source, applet, device_path, name, long_name, pin) {
|
||||||
this.parent(source,
|
this.parent(source,
|
||||||
_("Bluetooth"),
|
_("Bluetooth"),
|
||||||
|
/* Translators: argument is the device short name */
|
||||||
_("Pairing confirmation for %s").format(name),
|
_("Pairing confirmation for %s").format(name),
|
||||||
{ customContent: true });
|
{ customContent: true });
|
||||||
this.setResident(true);
|
this.setResident(true);
|
||||||
@@ -378,6 +363,7 @@ const ConfirmNotification = new Lang.Class({
|
|||||||
this.addBody(_("Device %s wants to pair with this computer").format(long_name));
|
this.addBody(_("Device %s wants to pair with this computer").format(long_name));
|
||||||
this.addBody(_("Please confirm whether the PIN '%06d' matches the one on the device.").format(pin));
|
this.addBody(_("Please confirm whether the PIN '%06d' matches the one on the device.").format(pin));
|
||||||
|
|
||||||
|
/* Translators: this is the verb, not the noun */
|
||||||
this.addButton('matches', _("Matches"));
|
this.addButton('matches', _("Matches"));
|
||||||
this.addButton('does-not-match', _("Does not match"));
|
this.addButton('does-not-match', _("Does not match"));
|
||||||
|
|
||||||
|
@@ -66,21 +66,7 @@ const VolumeMenu = new Lang.Class({
|
|||||||
this._onControlStateChanged();
|
this._onControlStateChanged();
|
||||||
},
|
},
|
||||||
|
|
||||||
toggleMute: function(quiet) {
|
scroll: function(direction) {
|
||||||
let muted = this._output.is_muted;
|
|
||||||
this._output.change_is_muted(!muted);
|
|
||||||
|
|
||||||
if (muted && !quiet)
|
|
||||||
this._notifyVolumeChange();
|
|
||||||
|
|
||||||
if (!muted)
|
|
||||||
return ['audio-volume-muted-symbolic', 0];
|
|
||||||
else
|
|
||||||
return [this._volumeToIcon(this._output.volume),
|
|
||||||
this._output.volume / this._volumeMax];
|
|
||||||
},
|
|
||||||
|
|
||||||
scroll: function(direction, quiet) {
|
|
||||||
let currentVolume = this._output.volume;
|
let currentVolume = this._output.volume;
|
||||||
|
|
||||||
if (direction == Clutter.ScrollDirection.DOWN) {
|
if (direction == Clutter.ScrollDirection.DOWN) {
|
||||||
@@ -99,14 +85,7 @@ const VolumeMenu = new Lang.Class({
|
|||||||
this._output.push_volume();
|
this._output.push_volume();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!quiet)
|
this._notifyVolumeChange();
|
||||||
this._notifyVolumeChange();
|
|
||||||
|
|
||||||
if (this._output.is_muted)
|
|
||||||
return ['audio-volume-muted-symbolic', 0];
|
|
||||||
else
|
|
||||||
return [this._volumeToIcon(this._output.volume),
|
|
||||||
this._output.volume / this._volumeMax];
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_onControlStateChanged: function() {
|
_onControlStateChanged: function() {
|
||||||
@@ -242,14 +221,14 @@ const Indicator = new Lang.Class({
|
|||||||
this.parent('audio-volume-muted-symbolic', _("Volume"));
|
this.parent('audio-volume-muted-symbolic', _("Volume"));
|
||||||
|
|
||||||
this._control = getMixerControl();
|
this._control = getMixerControl();
|
||||||
this.volumeMenu = new VolumeMenu(this._control);
|
this._volumeMenu = new VolumeMenu(this._control);
|
||||||
this.volumeMenu.connect('icon-changed', Lang.bind(this, function(menu, icon) {
|
this._volumeMenu.connect('icon-changed', Lang.bind(this, function(menu, icon) {
|
||||||
this._hasPulseAudio = (icon != null);
|
this._hasPulseAudio = (icon != null);
|
||||||
this.setIcon(icon);
|
this.setIcon(icon);
|
||||||
this._syncVisibility();
|
this._syncVisibility();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
this.menu.addMenuItem(this.volumeMenu);
|
this.menu.addMenuItem(this._volumeMenu);
|
||||||
|
|
||||||
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
||||||
this.menu.addSettingsAction(_("Sound Settings"), 'gnome-sound-panel.desktop');
|
this.menu.addSettingsAction(_("Sound Settings"), 'gnome-sound-panel.desktop');
|
||||||
@@ -263,6 +242,6 @@ const Indicator = new Lang.Class({
|
|||||||
},
|
},
|
||||||
|
|
||||||
_onScrollEvent: function(actor, event) {
|
_onScrollEvent: function(actor, event) {
|
||||||
this.volumeMenu.scroll(event.get_scroll_direction(), false);
|
this._volumeMenu.scroll(event.get_scroll_direction());
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
|
@@ -113,6 +113,7 @@ const UnlockDialog = new Lang.Class({
|
|||||||
_init: function(parentActor) {
|
_init: function(parentActor) {
|
||||||
this.parent({ shellReactive: true,
|
this.parent({ shellReactive: true,
|
||||||
styleClass: 'login-dialog',
|
styleClass: 'login-dialog',
|
||||||
|
keybindingMode: Main.KeybindingMode.UNLOCK_SCREEN,
|
||||||
parentActor: parentActor
|
parentActor: parentActor
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -199,6 +200,8 @@ const UnlockDialog = new Lang.Class({
|
|||||||
return false;
|
return false;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
Main.ctrlAltTabManager.addGroup(this.dialogLayout, _("Unlock Window"), 'dialog-password-symbolic');
|
||||||
|
|
||||||
this._idleMonitor = new GnomeDesktop.IdleMonitor();
|
this._idleMonitor = new GnomeDesktop.IdleMonitor();
|
||||||
this._idleWatchId = this._idleMonitor.add_watch(IDLE_TIMEOUT * 1000, Lang.bind(this, this._escape));
|
this._idleWatchId = this._idleMonitor.add_watch(IDLE_TIMEOUT * 1000, Lang.bind(this, this._escape));
|
||||||
},
|
},
|
||||||
|
@@ -572,7 +572,6 @@ const UserMenuButton = new Lang.Class({
|
|||||||
|
|
||||||
this._updateHaveShutdown();
|
this._updateHaveShutdown();
|
||||||
this._updateHaveSuspend();
|
this._updateHaveSuspend();
|
||||||
this._updateHaveHibernate();
|
|
||||||
}));
|
}));
|
||||||
this._lockdownSettings.connect('changed::' + DISABLE_LOG_OUT_KEY,
|
this._lockdownSettings.connect('changed::' + DISABLE_LOG_OUT_KEY,
|
||||||
Lang.bind(this, this._updateHaveShutdown));
|
Lang.bind(this, this._updateHaveShutdown));
|
||||||
@@ -656,13 +655,6 @@ const UserMenuButton = new Lang.Class({
|
|||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
|
|
||||||
_updateHaveHibernate: function() {
|
|
||||||
this._loginManager.canHibernate(Lang.bind(this,
|
|
||||||
function(result) {
|
|
||||||
this._haveHibernate = result;
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
|
|
||||||
_updateSuspendOrPowerOff: function() {
|
_updateSuspendOrPowerOff: function() {
|
||||||
if (!this._suspendOrPowerOffItem)
|
if (!this._suspendOrPowerOffItem)
|
||||||
return;
|
return;
|
||||||
@@ -774,7 +766,7 @@ const UserMenuButton = new Lang.Class({
|
|||||||
this._loginScreenItem = item;
|
this._loginScreenItem = item;
|
||||||
|
|
||||||
item = new PopupMenu.PopupMenuItem(_("Log Out"));
|
item = new PopupMenu.PopupMenuItem(_("Log Out"));
|
||||||
item.connect('activate', Lang.bind(this, this.logOut));
|
item.connect('activate', Lang.bind(this, this._onQuitSessionActivate));
|
||||||
this.menu.addMenuItem(item);
|
this.menu.addMenuItem(item);
|
||||||
this._logoutItem = item;
|
this._logoutItem = item;
|
||||||
|
|
||||||
@@ -843,7 +835,7 @@ const UserMenuButton = new Lang.Class({
|
|||||||
Gdm.goto_login_session_sync(null);
|
Gdm.goto_login_session_sync(null);
|
||||||
},
|
},
|
||||||
|
|
||||||
logOut: function() {
|
_onQuitSessionActivate: function() {
|
||||||
Main.overview.hide();
|
Main.overview.hide();
|
||||||
this._session.LogoutRemote(0);
|
this._session.LogoutRemote(0);
|
||||||
},
|
},
|
||||||
@@ -855,60 +847,25 @@ const UserMenuButton = new Lang.Class({
|
|||||||
this._session.RebootRemote();
|
this._session.RebootRemote();
|
||||||
},
|
},
|
||||||
|
|
||||||
shutdown: function() {
|
|
||||||
this._session.ShutdownRemote();
|
|
||||||
},
|
|
||||||
|
|
||||||
suspend: function() {
|
|
||||||
if (!this._haveSuspend)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Ensure we only suspend after locking the screen
|
|
||||||
if (this._screenSaverSettings.get_boolean(LOCK_ENABLED_KEY)) {
|
|
||||||
let tmpId = Main.screenShield.connect('lock-screen-shown', Lang.bind(this, function() {
|
|
||||||
Main.screenShield.disconnect(tmpId);
|
|
||||||
|
|
||||||
this._loginManager.suspend();
|
|
||||||
}));
|
|
||||||
|
|
||||||
this.menu.close(BoxPointer.PopupAnimation.NONE);
|
|
||||||
Main.screenShield.lock(true);
|
|
||||||
} else {
|
|
||||||
this._loginManager.suspend();
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
hibernate: function() {
|
|
||||||
if (!this._haveHibernate)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Ensure we only suspend after locking the screen
|
|
||||||
if (this._screenSaverSettings.get_boolean(LOCK_ENABLED_KEY)) {
|
|
||||||
let tmpId = Main.screenShield.connect('lock-screen-shown', Lang.bind(this, function() {
|
|
||||||
Main.screenShield.disconnect(tmpId);
|
|
||||||
|
|
||||||
this._loginManager.hibernate();
|
|
||||||
}));
|
|
||||||
|
|
||||||
this.menu.close(BoxPointer.PopupAnimation.NONE);
|
|
||||||
Main.screenShield.lock(true);
|
|
||||||
} else {
|
|
||||||
this._loginManager.hibernate();
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
_onSuspendOrPowerOffActivate: function() {
|
_onSuspendOrPowerOffActivate: function() {
|
||||||
Main.overview.hide();
|
Main.overview.hide();
|
||||||
|
|
||||||
if (this._haveShutdown &&
|
if (this._haveShutdown &&
|
||||||
this._suspendOrPowerOffItem.state == PopupMenu.PopupAlternatingMenuItemState.DEFAULT) {
|
this._suspendOrPowerOffItem.state == PopupMenu.PopupAlternatingMenuItemState.DEFAULT) {
|
||||||
this.shutdown();
|
this._session.ShutdownRemote();
|
||||||
} else {
|
} else {
|
||||||
this.suspend();
|
if (this._screenSaverSettings.get_boolean(LOCK_ENABLED_KEY)) {
|
||||||
|
let tmpId = Main.screenShield.connect('lock-screen-shown', Lang.bind(this, function() {
|
||||||
|
Main.screenShield.disconnect(tmpId);
|
||||||
|
|
||||||
|
this._loginManager.suspend();
|
||||||
|
}));
|
||||||
|
|
||||||
|
this.menu.close(BoxPointer.PopupAnimation.NONE);
|
||||||
|
Main.screenShield.lock(true);
|
||||||
|
} else {
|
||||||
|
this._loginManager.suspend();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@@ -94,6 +94,11 @@ const ViewSelector = new Lang.Class({
|
|||||||
this._searchPage = this._addPage(this._searchResults.actor, this._entry,
|
this._searchPage = this._addPage(this._searchResults.actor, this._entry,
|
||||||
_("Search"), 'edit-find-symbolic');
|
_("Search"), 'edit-find-symbolic');
|
||||||
|
|
||||||
|
this._searchSettings = new Gio.Settings({ schema: Search.SEARCH_PROVIDERS_SCHEMA });
|
||||||
|
this._searchSettings.connect('changed::disabled', Lang.bind(this, this._reloadRemoteProviders));
|
||||||
|
this._searchSettings.connect('changed::disable-external', Lang.bind(this, this._reloadRemoteProviders));
|
||||||
|
this._searchSettings.connect('changed::sort-order', Lang.bind(this, this._reloadRemoteProviders));
|
||||||
|
|
||||||
// Default search providers
|
// Default search providers
|
||||||
// Wanda comes obviously first
|
// Wanda comes obviously first
|
||||||
this.addSearchProvider(new Wanda.WandaSearchProvider());
|
this.addSearchProvider(new Wanda.WandaSearchProvider());
|
||||||
@@ -144,15 +149,17 @@ const ViewSelector = new Lang.Class({
|
|||||||
this.constrainHeight = new Clutter.BindConstraint({ source: this._pageArea,
|
this.constrainHeight = new Clutter.BindConstraint({ source: this._pageArea,
|
||||||
coordinate: Clutter.BindCoordinate.HEIGHT });
|
coordinate: Clutter.BindCoordinate.HEIGHT });
|
||||||
|
|
||||||
global.display.add_keybinding('toggle-application-view',
|
Main.wm.addKeybinding('toggle-application-view',
|
||||||
new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }),
|
new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }),
|
||||||
Meta.KeyBindingFlags.NONE,
|
Meta.KeyBindingFlags.NONE,
|
||||||
Lang.bind(this, this._showWithAppsPage));
|
Main.KeybindingMode.NORMAL |
|
||||||
|
Main.KeybindingMode.OVERVIEW,
|
||||||
|
Lang.bind(this, this._toggleAppsPage));
|
||||||
},
|
},
|
||||||
|
|
||||||
_showWithAppsPage: function() {
|
_toggleAppsPage: function() {
|
||||||
Main.overview.show();
|
Main.overview.show();
|
||||||
this._showAppsButton.set_checked(true);
|
this._showAppsButton.checked = !this._showAppsButton.checked;
|
||||||
},
|
},
|
||||||
|
|
||||||
show: function() {
|
show: function() {
|
||||||
@@ -433,7 +440,32 @@ const ViewSelector = new Lang.Class({
|
|||||||
this._showPage(this._searchPage);
|
this._showPage(this._searchPage);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_shouldUseSearchProvider: function(provider) {
|
||||||
|
// the disable-external GSetting only affects remote providers
|
||||||
|
if (!provider.isRemoteProvider)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (this._searchSettings.get_boolean('disable-external'))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
let appId = provider.appInfo.get_id();
|
||||||
|
let disable = this._searchSettings.get_strv('disabled');
|
||||||
|
return disable.indexOf(appId) == -1;
|
||||||
|
},
|
||||||
|
|
||||||
|
_reloadRemoteProviders: function() {
|
||||||
|
// removeSearchProvider() modifies the provider list we iterate on,
|
||||||
|
// so make a copy first
|
||||||
|
let remoteProviders = this._searchSystem.getRemoteProviders().slice(0);
|
||||||
|
|
||||||
|
remoteProviders.forEach(Lang.bind(this, this.removeSearchProvider));
|
||||||
|
RemoteSearch.loadRemoteSearchProviders(Lang.bind(this, this.addSearchProvider));
|
||||||
|
},
|
||||||
|
|
||||||
addSearchProvider: function(provider) {
|
addSearchProvider: function(provider) {
|
||||||
|
if (!this._shouldUseSearchProvider(provider))
|
||||||
|
return;
|
||||||
|
|
||||||
this._searchSystem.registerProvider(provider);
|
this._searchSystem.registerProvider(provider);
|
||||||
this._searchResults.createProviderMeta(provider);
|
this._searchResults.createProviderMeta(provider);
|
||||||
},
|
},
|
||||||
|
@@ -12,7 +12,6 @@ const AltTab = imports.ui.altTab;
|
|||||||
const WorkspaceSwitcherPopup = imports.ui.workspaceSwitcherPopup;
|
const WorkspaceSwitcherPopup = imports.ui.workspaceSwitcherPopup;
|
||||||
const Main = imports.ui.main;
|
const Main = imports.ui.main;
|
||||||
const Tweener = imports.ui.tweener;
|
const Tweener = imports.ui.tweener;
|
||||||
const Util = imports.misc.util;
|
|
||||||
|
|
||||||
const SHELL_KEYBINDINGS_SCHEMA = 'org.gnome.shell.keybindings';
|
const SHELL_KEYBINDINGS_SCHEMA = 'org.gnome.shell.keybindings';
|
||||||
const WINDOW_ANIMATION_TIME = 0.25;
|
const WINDOW_ANIMATION_TIME = 0.25;
|
||||||
@@ -84,6 +83,8 @@ const WindowManager = new Lang.Class({
|
|||||||
|
|
||||||
this._animationBlockCount = 0;
|
this._animationBlockCount = 0;
|
||||||
|
|
||||||
|
this._allowedKeybindings = {};
|
||||||
|
|
||||||
this._switchData = null;
|
this._switchData = null;
|
||||||
this._shellwm.connect('kill-switch-workspace', Lang.bind(this, this._switchWorkspaceDone));
|
this._shellwm.connect('kill-switch-workspace', Lang.bind(this, this._switchWorkspaceDone));
|
||||||
this._shellwm.connect('kill-window-effects', Lang.bind(this, function (shellwm, actor) {
|
this._shellwm.connect('kill-window-effects', Lang.bind(this, function (shellwm, actor) {
|
||||||
@@ -100,38 +101,66 @@ const WindowManager = new Lang.Class({
|
|||||||
this._shellwm.connect('unmaximize', Lang.bind(this, this._unmaximizeWindow));
|
this._shellwm.connect('unmaximize', Lang.bind(this, this._unmaximizeWindow));
|
||||||
this._shellwm.connect('map', Lang.bind(this, this._mapWindow));
|
this._shellwm.connect('map', Lang.bind(this, this._mapWindow));
|
||||||
this._shellwm.connect('destroy', Lang.bind(this, this._destroyWindow));
|
this._shellwm.connect('destroy', Lang.bind(this, this._destroyWindow));
|
||||||
|
this._shellwm.connect('filter-keybinding', Lang.bind(this, this._filterKeybinding));
|
||||||
|
|
||||||
this._workspaceSwitcherPopup = null;
|
this._workspaceSwitcherPopup = null;
|
||||||
Meta.keybindings_set_custom_handler('internal-keybinding-switch-to-workspace-left',
|
this.setCustomKeybindingHandler('switch-to-workspace-left',
|
||||||
Util.wrapKeybinding(Lang.bind(this, this._showWorkspaceSwitcher), true));
|
Main.KeybindingMode.NORMAL |
|
||||||
Meta.keybindings_set_custom_handler('internal-keybinding-switch-to-workspace-right',
|
Main.KeybindingMode.OVERVIEW,
|
||||||
Util.wrapKeybinding(Lang.bind(this, this._showWorkspaceSwitcher), true));
|
Lang.bind(this, this._showWorkspaceSwitcher));
|
||||||
Meta.keybindings_set_custom_handler('internal-keybinding-switch-to-workspace-up',
|
this.setCustomKeybindingHandler('switch-to-workspace-right',
|
||||||
Util.wrapKeybinding(Lang.bind(this, this._showWorkspaceSwitcher), true));
|
Main.KeybindingMode.NORMAL |
|
||||||
Meta.keybindings_set_custom_handler('internal-keybinding-switch-to-workspace-down',
|
Main.KeybindingMode.OVERVIEW,
|
||||||
Util.wrapKeybinding(Lang.bind(this, this._showWorkspaceSwitcher), true));
|
Lang.bind(this, this._showWorkspaceSwitcher));
|
||||||
Meta.keybindings_set_custom_handler('internal-keybinding-move-to-workspace-left',
|
this.setCustomKeybindingHandler('switch-to-workspace-up',
|
||||||
Lang.bind(this, this._showWorkspaceSwitcher));
|
Main.KeybindingMode.NORMAL |
|
||||||
Meta.keybindings_set_custom_handler('internal-keybinding-move-to-workspace-right',
|
Main.KeybindingMode.OVERVIEW,
|
||||||
Lang.bind(this, this._showWorkspaceSwitcher));
|
Lang.bind(this, this._showWorkspaceSwitcher));
|
||||||
Meta.keybindings_set_custom_handler('internal-keybinding-move-to-workspace-up',
|
this.setCustomKeybindingHandler('switch-to-workspace-down',
|
||||||
Lang.bind(this, this._showWorkspaceSwitcher));
|
Main.KeybindingMode.NORMAL |
|
||||||
Meta.keybindings_set_custom_handler('internal-keybinding-move-to-workspace-down',
|
Main.KeybindingMode.OVERVIEW,
|
||||||
Lang.bind(this, this._showWorkspaceSwitcher));
|
Lang.bind(this, this._showWorkspaceSwitcher));
|
||||||
Meta.keybindings_set_custom_handler('internal-keybinding-switch-windows',
|
this.setCustomKeybindingHandler('move-to-workspace-left',
|
||||||
Lang.bind(this, this._startAppSwitcher));
|
Main.KeybindingMode.NORMAL |
|
||||||
Meta.keybindings_set_custom_handler('internal-keybinding-switch-group',
|
Main.KeybindingMode.OVERVIEW,
|
||||||
Lang.bind(this, this._startAppSwitcher));
|
Lang.bind(this, this._showWorkspaceSwitcher));
|
||||||
Meta.keybindings_set_custom_handler('internal-keybinding-switch-windows-backward',
|
this.setCustomKeybindingHandler('move-to-workspace-right',
|
||||||
Lang.bind(this, this._startAppSwitcher));
|
Main.KeybindingMode.NORMAL |
|
||||||
Meta.keybindings_set_custom_handler('internal-keybinding-switch-group-backward',
|
Main.KeybindingMode.OVERVIEW,
|
||||||
Lang.bind(this, this._startAppSwitcher));
|
Lang.bind(this, this._showWorkspaceSwitcher));
|
||||||
Meta.keybindings_set_custom_handler('internal-keybinding-switch-panels',
|
this.setCustomKeybindingHandler('move-to-workspace-up',
|
||||||
Util.wrapKeybinding(Lang.bind(this, this._startA11ySwitcher), true));
|
Main.KeybindingMode.NORMAL |
|
||||||
global.display.add_keybinding('open-application-menu',
|
Main.KeybindingMode.OVERVIEW,
|
||||||
new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }),
|
Lang.bind(this, this._showWorkspaceSwitcher));
|
||||||
Meta.KeyBindingFlags.NONE,
|
this.setCustomKeybindingHandler('move-to-workspace-down',
|
||||||
Lang.bind(this, this._openAppMenu));
|
Main.KeybindingMode.NORMAL |
|
||||||
|
Main.KeybindingMode.OVERVIEW,
|
||||||
|
Lang.bind(this, this._showWorkspaceSwitcher));
|
||||||
|
this.setCustomKeybindingHandler('switch-windows',
|
||||||
|
Main.KeybindingMode.NORMAL,
|
||||||
|
Lang.bind(this, this._startAppSwitcher));
|
||||||
|
this.setCustomKeybindingHandler('switch-group',
|
||||||
|
Main.KeybindingMode.NORMAL,
|
||||||
|
Lang.bind(this, this._startAppSwitcher));
|
||||||
|
this.setCustomKeybindingHandler('switch-windows-backward',
|
||||||
|
Main.KeybindingMode.NORMAL,
|
||||||
|
Lang.bind(this, this._startAppSwitcher));
|
||||||
|
this.setCustomKeybindingHandler('switch-group-backward',
|
||||||
|
Main.KeybindingMode.NORMAL,
|
||||||
|
Lang.bind(this, this._startAppSwitcher));
|
||||||
|
this.setCustomKeybindingHandler('switch-panels',
|
||||||
|
Main.KeybindingMode.NORMAL |
|
||||||
|
Main.KeybindingMode.OVERVIEW |
|
||||||
|
Main.KeybindingMode.LOCK_SCREEN |
|
||||||
|
Main.KeybindingMode.UNLOCK_SCREEN |
|
||||||
|
Main.KeybindingMode.LOGIN_SCREEN,
|
||||||
|
Lang.bind(this, this._startA11ySwitcher));
|
||||||
|
|
||||||
|
this.addKeybinding('open-application-menu',
|
||||||
|
new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }),
|
||||||
|
Meta.KeyBindingFlags.NONE,
|
||||||
|
Main.KeybindingMode.NORMAL,
|
||||||
|
Lang.bind(this, this._openAppMenu));
|
||||||
|
|
||||||
Main.overview.connect('showing', Lang.bind(this, function() {
|
Main.overview.connect('showing', Lang.bind(this, function() {
|
||||||
for (let i = 0; i < this._dimmedWindows.length; i++)
|
for (let i = 0; i < this._dimmedWindows.length; i++)
|
||||||
@@ -143,6 +172,25 @@ const WindowManager = new Lang.Class({
|
|||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
setCustomKeybindingHandler: function(name, modes, handler) {
|
||||||
|
if (Meta.keybindings_set_custom_handler(name, handler))
|
||||||
|
this.allowKeybinding(name, modes);
|
||||||
|
},
|
||||||
|
|
||||||
|
addKeybinding: function(name, settings, flags, modes, handler) {
|
||||||
|
if (global.display.add_keybinding(name, settings, flags, handler))
|
||||||
|
this.allowKeybinding(name, modes);
|
||||||
|
},
|
||||||
|
|
||||||
|
removeKeybinding: function(name) {
|
||||||
|
if (global.display.remove_keybinding(name))
|
||||||
|
this.allowKeybinding(name, Main.KeybindingMode.NONE);
|
||||||
|
},
|
||||||
|
|
||||||
|
allowKeybinding: function(name, modes) {
|
||||||
|
this._allowedKeybindings[name] = modes;
|
||||||
|
},
|
||||||
|
|
||||||
blockAnimations: function() {
|
blockAnimations: function() {
|
||||||
this._animationBlockCount++;
|
this._animationBlockCount++;
|
||||||
},
|
},
|
||||||
@@ -425,6 +473,21 @@ const WindowManager = new Lang.Class({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_filterKeybinding: function(shellwm, binding) {
|
||||||
|
if (Main.keybindingMode == Main.KeybindingMode.NONE)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// There's little sense in implementing a keybinding in mutter and
|
||||||
|
// not having it work in NORMAL mode; handle this case generically
|
||||||
|
// so we don't have to explicitly allow all builtin keybindings in
|
||||||
|
// NORMAL mode.
|
||||||
|
if (Main.keybindingMode == Main.KeybindingMode.NORMAL &&
|
||||||
|
binding.is_builtin())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return !(this._allowedKeybindings[binding.get_name()] & Main.keybindingMode);
|
||||||
|
},
|
||||||
|
|
||||||
_switchWorkspace : function(shellwm, from, to, direction) {
|
_switchWorkspace : function(shellwm, from, to, direction) {
|
||||||
if (!this._shouldAnimate()) {
|
if (!this._shouldAnimate()) {
|
||||||
shellwm.completed_switch_workspace();
|
shellwm.completed_switch_workspace();
|
||||||
@@ -553,32 +616,30 @@ const WindowManager = new Lang.Class({
|
|||||||
let backwards = modifiers & Meta.VirtualModifier.SHIFT_MASK;
|
let backwards = modifiers & Meta.VirtualModifier.SHIFT_MASK;
|
||||||
if (!tabPopup.show(backwards, binding.get_name(), binding.get_mask()))
|
if (!tabPopup.show(backwards, binding.get_name(), binding.get_mask()))
|
||||||
tabPopup.destroy();
|
tabPopup.destroy();
|
||||||
return true;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_startA11ySwitcher : function(display, screen, window, binding) {
|
_startA11ySwitcher : function(display, screen, window, binding) {
|
||||||
let modifiers = binding.get_modifiers();
|
let modifiers = binding.get_modifiers();
|
||||||
let backwards = modifiers & Meta.VirtualModifier.SHIFT_MASK;
|
let backwards = modifiers & Meta.VirtualModifier.SHIFT_MASK;
|
||||||
Main.ctrlAltTabManager.popup(backwards, binding.get_mask());
|
Main.ctrlAltTabManager.popup(backwards, binding.get_mask());
|
||||||
return true;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_openAppMenu : function(display, screen, window, event, binding) {
|
_openAppMenu : function(display, screen, window, event, binding) {
|
||||||
Main.panel.openAppMenu();
|
Main.panel.openAppMenu();
|
||||||
return true;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_showWorkspaceSwitcher : function(display, screen, window, binding) {
|
_showWorkspaceSwitcher : function(display, screen, window, binding) {
|
||||||
if (screen.n_workspaces == 1)
|
if (screen.n_workspaces == 1)
|
||||||
return false;
|
return;
|
||||||
|
|
||||||
let [,,action,,,direction] = binding.get_name().split('-');
|
let [action,,,direction] = binding.get_name().split('-');
|
||||||
let direction = Meta.MotionDirection[direction.toUpperCase()];
|
let direction = Meta.MotionDirection[direction.toUpperCase()];
|
||||||
let newWs;
|
let newWs;
|
||||||
|
|
||||||
|
|
||||||
if (direction != Meta.MotionDirection.UP &&
|
if (direction != Meta.MotionDirection.UP &&
|
||||||
direction != Meta.MotionDirection.DOWN)
|
direction != Meta.MotionDirection.DOWN)
|
||||||
return false;
|
return;
|
||||||
|
|
||||||
if (action == 'switch')
|
if (action == 'switch')
|
||||||
newWs = this.actionMoveWorkspace(direction);
|
newWs = this.actionMoveWorkspace(direction);
|
||||||
@@ -594,8 +655,6 @@ const WindowManager = new Lang.Class({
|
|||||||
}
|
}
|
||||||
this._workspaceSwitcherPopup.display(direction, newWs.index());
|
this._workspaceSwitcherPopup.display(direction, newWs.index());
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
actionMoveWorkspace: function(direction) {
|
actionMoveWorkspace: function(direction) {
|
||||||
|
158
po/et.po
158
po/et.po
@@ -13,8 +13,8 @@ msgstr ""
|
|||||||
"Project-Id-Version: gnome-shell MASTER\n"
|
"Project-Id-Version: gnome-shell MASTER\n"
|
||||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
|
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
|
||||||
"shell&keywords=I18N+L10N&component=general\n"
|
"shell&keywords=I18N+L10N&component=general\n"
|
||||||
"POT-Creation-Date: 2012-09-22 22:24+0000\n"
|
"POT-Creation-Date: 2012-11-16 18:27+0000\n"
|
||||||
"PO-Revision-Date: 2012-09-23 08:48+0300\n"
|
"PO-Revision-Date: 2012-11-16 20:40+0300\n"
|
||||||
"Last-Translator: Mattias Põldaru <mahfiaz@gmail.com>\n"
|
"Last-Translator: Mattias Põldaru <mahfiaz@gmail.com>\n"
|
||||||
"Language-Team: Estonian <>\n"
|
"Language-Team: Estonian <>\n"
|
||||||
"Language: et\n"
|
"Language: et\n"
|
||||||
@@ -37,6 +37,15 @@ msgstr "Arvuti"
|
|||||||
msgid "Show the message tray"
|
msgid "Show the message tray"
|
||||||
msgstr "Teateala näitamine"
|
msgstr "Teateala näitamine"
|
||||||
|
|
||||||
|
msgid "Focus the active notification"
|
||||||
|
msgstr "Aktiivse märguande fokuseerimine"
|
||||||
|
|
||||||
|
msgid "Show all applications"
|
||||||
|
msgstr "Kõigi rakenduste kuvamine"
|
||||||
|
|
||||||
|
msgid "Open the application menu"
|
||||||
|
msgstr "Rakenduste menüü avamine"
|
||||||
|
|
||||||
msgid "GNOME Shell"
|
msgid "GNOME Shell"
|
||||||
msgstr "GNOME Shell"
|
msgstr "GNOME Shell"
|
||||||
|
|
||||||
@@ -116,6 +125,16 @@ msgstr ""
|
|||||||
"Kasutatakse kasutaja poolt viimati vahetult määratud kiirsuhtluse oleku "
|
"Kasutatakse kasutaja poolt viimati vahetult määratud kiirsuhtluse oleku "
|
||||||
"salvestamiseks. See väärtus pärineb GsmPresenceStatus nummerdusest."
|
"salvestamiseks. See väärtus pärineb GsmPresenceStatus nummerdusest."
|
||||||
|
|
||||||
|
msgid "Always show the 'Log out' menuitem in the user menu."
|
||||||
|
msgstr "Kasutajamenüüs näidatakse alati 'Logi välja' menüükirjet."
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"This key overrides the automatic hiding of the 'Log out' menuitem in single-"
|
||||||
|
"user, single-session situations."
|
||||||
|
msgstr ""
|
||||||
|
"See võti keelab automaatse 'Logi välja' menüükirje peitmise, kui arvutis on "
|
||||||
|
"üks kasutaja ning avatud üks seanss."
|
||||||
|
|
||||||
msgid "Show the week date in the calendar"
|
msgid "Show the week date in the calendar"
|
||||||
msgstr "Kalendris näidatakse kuupäeva nädalavormingus"
|
msgstr "Kalendris näidatakse kuupäeva nädalavormingus"
|
||||||
|
|
||||||
@@ -128,12 +147,25 @@ msgstr "Rakenduste menüü avamise kiirklahv"
|
|||||||
msgid "Keybinding to open the application menu."
|
msgid "Keybinding to open the application menu."
|
||||||
msgstr "Kiirklahv rakenduste menüü avamiseks."
|
msgstr "Kiirklahv rakenduste menüü avamiseks."
|
||||||
|
|
||||||
|
msgid "Keybinding to open the \"Show Applications\" view"
|
||||||
|
msgstr "\"Rakenduste vaate\" avamise kiirklahv"
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"Keybinding to open the \"Show Applications\" view of the Activities Overview."
|
||||||
|
msgstr "\"Rakenduste vaate\" avamise kiirklahv tegevuste ülevaates."
|
||||||
|
|
||||||
msgid "Keybinding to toggle the visibility of the message tray"
|
msgid "Keybinding to toggle the visibility of the message tray"
|
||||||
msgstr "Teateala nähtavuse muutmise kiirklahv"
|
msgstr "Teateala nähtavuse muutmise kiirklahv"
|
||||||
|
|
||||||
msgid "Keybinding to toggle the visibility of the message tray."
|
msgid "Keybinding to toggle the visibility of the message tray."
|
||||||
msgstr "Kiirklahv teateala nähtavuse muutmiseks."
|
msgstr "Kiirklahv teateala nähtavuse muutmiseks."
|
||||||
|
|
||||||
|
msgid "Keybinding to focus the active notification"
|
||||||
|
msgstr "Aktiivse teate fokuseerimise kiirklahv"
|
||||||
|
|
||||||
|
msgid "Keybinding to focus the active notification."
|
||||||
|
msgstr "Aktiivse teate fokuseerimise kiirklahv."
|
||||||
|
|
||||||
msgid "Keybinding to toggle the screen recorder"
|
msgid "Keybinding to toggle the screen recorder"
|
||||||
msgstr "Erkaanilindistaja lülitamise kiirklahv"
|
msgstr "Erkaanilindistaja lülitamise kiirklahv"
|
||||||
|
|
||||||
@@ -195,6 +227,34 @@ msgstr ""
|
|||||||
"konteinervormingusse salvestades tuleks ka sellele vormingule vastav laiend "
|
"konteinervormingusse salvestades tuleks ka sellele vormingule vastav laiend "
|
||||||
"määrata."
|
"määrata."
|
||||||
|
|
||||||
|
msgid "Attach modal dialog to the parent window"
|
||||||
|
msgstr "Modaaldialoog kuulub vanemakna juurde"
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"This key overrides the key in org.gnome.mutter when running GNOME Shell."
|
||||||
|
msgstr ""
|
||||||
|
"See võti on ülimuslik võtme org.gnome.mutter suhtes, kui kasutatakse GNOME "
|
||||||
|
"Shelli."
|
||||||
|
|
||||||
|
msgid "Arrangement of buttons on the titlebar"
|
||||||
|
msgstr "Nuppude järjekord tiitliribal"
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"This key overrides the key in org.gnome.desktop.wm.preferences when running "
|
||||||
|
"GNOME Shell."
|
||||||
|
msgstr ""
|
||||||
|
"See võti on ülimuslik võtme org.gnome.desktop.wm.preferences suhtes, kui "
|
||||||
|
"kasutatakse GNOME Shelli."
|
||||||
|
|
||||||
|
msgid "Enable edge tiling when dropping windows on screen edges"
|
||||||
|
msgstr "Akende lohistamisel ekraani serva lubatakse serva paigutamine"
|
||||||
|
|
||||||
|
msgid "Workspaces are managed dynamically"
|
||||||
|
msgstr "Tööalasid hallatakse dünaamiliselt"
|
||||||
|
|
||||||
|
msgid "Workspaces only on primary monitor"
|
||||||
|
msgstr "Tööalad peamisel monitoril"
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "There was an error loading the preferences dialog for %s:"
|
msgid "There was an error loading the preferences dialog for %s:"
|
||||||
msgstr "%s jaoks eelistuste dialoogi laadimisel esines viga:"
|
msgstr "%s jaoks eelistuste dialoogi laadimisel esines viga:"
|
||||||
@@ -225,9 +285,22 @@ msgctxt "button"
|
|||||||
msgid "Sign In"
|
msgid "Sign In"
|
||||||
msgstr "Logi sisse"
|
msgstr "Logi sisse"
|
||||||
|
|
||||||
|
msgid "Next"
|
||||||
|
msgstr "Järgmine"
|
||||||
|
|
||||||
|
#. TTLS and PEAP are actually much more complicated, but this complication
|
||||||
|
#. is not visible here since we only care about phase2 authentication
|
||||||
|
#. (and don't even care of which one)
|
||||||
|
msgid "Username: "
|
||||||
|
msgstr "Kasutajanimi: "
|
||||||
|
|
||||||
msgid "Login Window"
|
msgid "Login Window"
|
||||||
msgstr "Sisselogimisaken"
|
msgstr "Sisselogimisaken"
|
||||||
|
|
||||||
|
#. Translators: accessible name of the power menu in the login screen
|
||||||
|
msgid "Power"
|
||||||
|
msgstr "Vool"
|
||||||
|
|
||||||
msgid "Suspend"
|
msgid "Suspend"
|
||||||
msgstr "Uinak"
|
msgstr "Uinak"
|
||||||
|
|
||||||
@@ -437,12 +510,6 @@ msgstr "Parool: "
|
|||||||
msgid "Key: "
|
msgid "Key: "
|
||||||
msgstr "Võti: "
|
msgstr "Võti: "
|
||||||
|
|
||||||
#. TTLS and PEAP are actually much more complicated, but this complication
|
|
||||||
#. is not visible here since we only care about phase2 authentication
|
|
||||||
#. (and don't even care of which one)
|
|
||||||
msgid "Username: "
|
|
||||||
msgstr "Kasutajanimi: "
|
|
||||||
|
|
||||||
msgid "Identity: "
|
msgid "Identity: "
|
||||||
msgstr "Identiteet: "
|
msgstr "Identiteet: "
|
||||||
|
|
||||||
@@ -533,24 +600,27 @@ msgstr "Heli peale"
|
|||||||
msgid "Mute"
|
msgid "Mute"
|
||||||
msgstr "Heli maha"
|
msgstr "Heli maha"
|
||||||
|
|
||||||
#. Translators: this is a time format string followed by a date.
|
#. Translators: this is a time format string followed by the word "Yesterday". i.e. "14:30 on Yesterday"
|
||||||
#. If applicable, replace %X with a strftime format valid for your
|
|
||||||
#. locale, without seconds.
|
|
||||||
#, no-c-format
|
#, no-c-format
|
||||||
msgid "Sent at <b>%X</b> on <b>%A</b>"
|
msgid "<b>%H:%M</b> on Yesterday"
|
||||||
msgstr "Saadetud: <b>%A</b>, <b>%X</b>"
|
msgstr "Eile <b>%H:%M</b>"
|
||||||
|
|
||||||
#. Translators: this is a time format in the style of "Wednesday, May 25",
|
#. Translators: this is a time format string followed by a week day name. i.e. "14:30 on Monday
|
||||||
#. shown when you get a chat message in the same year.
|
|
||||||
#, no-c-format
|
#, no-c-format
|
||||||
msgid "Sent on <b>%A</b>, <b>%B %d</b>"
|
msgid "<b>%H:%M</b> on <b>%A</b>"
|
||||||
msgstr "Saadeti <b>%A</b>, <b>%B %d</b>"
|
msgstr "<b>%H:%M</b>, <b>%A</b>"
|
||||||
|
|
||||||
#. Translators: this is a time format in the style of "Wednesday, May 25, 2012",
|
#. Translators: this is a time format in the style of "14:30 on Wednesday, May 25",
|
||||||
#. shown when you get a chat message in a different year.
|
#. shown when you get a chat message in the same year
|
||||||
#, no-c-format
|
#, no-c-format
|
||||||
msgid "Sent on <b>%A</b>, <b>%B %d</b>, %Y"
|
msgid "<b>%H:%M</b> on <b>%A</b>, <b>%B</b> <b>%d</b>"
|
||||||
msgstr "Saadeti <b>%A</b>, <b>%B %d</b>, %Y"
|
msgstr "<b>%H:%M</b>, <b>%A</b>, <b>%d. %B</b>"
|
||||||
|
|
||||||
|
#. Translators: this is a time format in the style of "14:30 on Wednesday, May 25, 2012",
|
||||||
|
#. shown when you get a chat message in a different year
|
||||||
|
#, no-c-format
|
||||||
|
msgid "<b>%H:%M</b> on <b>%A</b>, <b>%B</b> <b>%d</b>, %Y"
|
||||||
|
msgstr "<b>%H:%M</b>, <b>%A</b>, <b>%d. %B</b> %Y"
|
||||||
|
|
||||||
#. Translators: this is the other person changing their old IM name to their new
|
#. Translators: this is the other person changing their old IM name to their new
|
||||||
#. IM name.
|
#. IM name.
|
||||||
@@ -587,9 +657,6 @@ msgstr "%s tahab alustada videokõnet"
|
|||||||
msgid "Call from %s"
|
msgid "Call from %s"
|
||||||
msgstr "%s helistab"
|
msgstr "%s helistab"
|
||||||
|
|
||||||
msgid "Reject"
|
|
||||||
msgstr "Lükka tagasi"
|
|
||||||
|
|
||||||
#. translators: this is a button label (verb), not a noun
|
#. translators: this is a button label (verb), not a noun
|
||||||
msgid "Answer"
|
msgid "Answer"
|
||||||
msgstr "Vasta"
|
msgstr "Vasta"
|
||||||
@@ -897,8 +964,11 @@ msgstr "Ülemine riba"
|
|||||||
msgid "toggle-switch-us"
|
msgid "toggle-switch-us"
|
||||||
msgstr "toggle-switch-intl"
|
msgstr "toggle-switch-intl"
|
||||||
|
|
||||||
msgid "Please enter a command:"
|
msgid "Enter a Command"
|
||||||
msgstr "Palun sisesta käsk:"
|
msgstr "Palun sisesta käsk"
|
||||||
|
|
||||||
|
msgid "Close"
|
||||||
|
msgstr "Sulge"
|
||||||
|
|
||||||
#. Translators: This is a time format for a date in
|
#. Translators: This is a time format for a date in
|
||||||
#. long format
|
#. long format
|
||||||
@@ -1011,16 +1081,6 @@ msgstr "ühendumine..."
|
|||||||
msgid "Send Files..."
|
msgid "Send Files..."
|
||||||
msgstr "Failide saatmine..."
|
msgstr "Failide saatmine..."
|
||||||
|
|
||||||
msgid "Browse Files..."
|
|
||||||
msgstr "Failide sirvimine..."
|
|
||||||
|
|
||||||
msgid "Error browsing device"
|
|
||||||
msgstr "Viga seadme sirvimisel"
|
|
||||||
|
|
||||||
#, c-format
|
|
||||||
msgid "The requested device cannot be browsed, error is '%s'"
|
|
||||||
msgstr "Küsitud seadet pole võimalik sirvida, viga on '%s'"
|
|
||||||
|
|
||||||
msgid "Keyboard Settings"
|
msgid "Keyboard Settings"
|
||||||
msgstr "Klaviatuurisätted"
|
msgstr "Klaviatuurisätted"
|
||||||
|
|
||||||
@@ -1044,6 +1104,9 @@ msgstr "Luba alati"
|
|||||||
msgid "Grant this time only"
|
msgid "Grant this time only"
|
||||||
msgstr "Luba ainult seekord"
|
msgstr "Luba ainult seekord"
|
||||||
|
|
||||||
|
msgid "Reject"
|
||||||
|
msgstr "Lükka tagasi"
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Pairing confirmation for %s"
|
msgid "Pairing confirmation for %s"
|
||||||
msgstr "Paardumise kinnitus seadmele %s"
|
msgstr "Paardumise kinnitus seadmele %s"
|
||||||
@@ -1154,9 +1217,6 @@ msgstr "Juhtmeta"
|
|||||||
msgid "Mobile broadband"
|
msgid "Mobile broadband"
|
||||||
msgstr "Mobiiliühendus"
|
msgstr "Mobiiliühendus"
|
||||||
|
|
||||||
msgid "VPN Connections"
|
|
||||||
msgstr "VPN-ühendused"
|
|
||||||
|
|
||||||
msgid "Network Settings"
|
msgid "Network Settings"
|
||||||
msgstr "Võrgusätted"
|
msgstr "Võrgusätted"
|
||||||
|
|
||||||
@@ -1274,20 +1334,17 @@ msgstr "Eemal"
|
|||||||
msgid "Idle"
|
msgid "Idle"
|
||||||
msgstr "Jõude"
|
msgstr "Jõude"
|
||||||
|
|
||||||
msgid "Unavailable"
|
msgid "Offline"
|
||||||
msgstr "Pole saadaval"
|
msgstr "Ühendamata"
|
||||||
|
|
||||||
msgid "Switch User"
|
|
||||||
msgstr "Vaheta kasutajat"
|
|
||||||
|
|
||||||
msgid "Switch Session"
|
|
||||||
msgstr "Vaheta seanssi"
|
|
||||||
|
|
||||||
msgid "Notifications"
|
msgid "Notifications"
|
||||||
msgstr "Märguanded"
|
msgstr "Märguanded"
|
||||||
|
|
||||||
msgid "System Settings"
|
msgid "Settings"
|
||||||
msgstr "Süsteemi sätted"
|
msgstr "Sätted"
|
||||||
|
|
||||||
|
msgid "Switch User"
|
||||||
|
msgstr "Vaheta kasutajat"
|
||||||
|
|
||||||
msgid "Log Out"
|
msgid "Log Out"
|
||||||
msgstr "Logi välja"
|
msgstr "Logi välja"
|
||||||
@@ -1404,9 +1461,6 @@ msgstr "Kasutaja katkestas autentimisdialoogi"
|
|||||||
#~ msgid "If true, display date in the clock, in addition to time."
|
#~ msgid "If true, display date in the clock, in addition to time."
|
||||||
#~ msgstr "Kui määratud, siis kuvatakse kellaaja kõrval ka kuupäeva."
|
#~ msgstr "Kui määratud, siis kuvatakse kellaaja kõrval ka kuupäeva."
|
||||||
|
|
||||||
#~ msgid "Offline"
|
|
||||||
#~ msgstr "Ühendamata"
|
|
||||||
|
|
||||||
#~ msgid "CONTACTS"
|
#~ msgid "CONTACTS"
|
||||||
#~ msgstr "KONTAKTID"
|
#~ msgstr "KONTAKTID"
|
||||||
|
|
||||||
|
@@ -119,7 +119,6 @@ shell_public_headers_h = \
|
|||||||
shell-network-agent.h \
|
shell-network-agent.h \
|
||||||
shell-perf-log.h \
|
shell-perf-log.h \
|
||||||
shell-screenshot.h \
|
shell-screenshot.h \
|
||||||
shell-screen-grabber.h \
|
|
||||||
shell-slicer.h \
|
shell-slicer.h \
|
||||||
shell-stack.h \
|
shell-stack.h \
|
||||||
shell-tp-client.h \
|
shell-tp-client.h \
|
||||||
@@ -167,7 +166,6 @@ libgnome_shell_la_SOURCES = \
|
|||||||
shell-polkit-authentication-agent.h \
|
shell-polkit-authentication-agent.h \
|
||||||
shell-polkit-authentication-agent.c \
|
shell-polkit-authentication-agent.c \
|
||||||
shell-screenshot.c \
|
shell-screenshot.c \
|
||||||
shell-screen-grabber.c \
|
|
||||||
shell-secure-text-buffer.c \
|
shell-secure-text-buffer.c \
|
||||||
shell-secure-text-buffer.h \
|
shell-secure-text-buffer.h \
|
||||||
shell-slicer.c \
|
shell-slicer.c \
|
||||||
@@ -232,8 +230,6 @@ test_recorder_LDADD = $(TEST_SHELL_RECORDER_LIBS)
|
|||||||
|
|
||||||
test_recorder_SOURCES = \
|
test_recorder_SOURCES = \
|
||||||
$(shell_recorder_sources) $(shell_recorder_private_sources) \
|
$(shell_recorder_sources) $(shell_recorder_private_sources) \
|
||||||
shell-screen-grabber.c \
|
|
||||||
shell-screen-grabber.h \
|
|
||||||
test-recorder.c
|
test-recorder.c
|
||||||
endif BUILD_RECORDER
|
endif BUILD_RECORDER
|
||||||
|
|
||||||
|
@@ -1035,8 +1035,6 @@ main (int argc,
|
|||||||
name_owner_id = 0;
|
name_owner_id = 0;
|
||||||
stdin_channel = NULL;
|
stdin_channel = NULL;
|
||||||
|
|
||||||
g_type_init ();
|
|
||||||
|
|
||||||
introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
|
introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
|
||||||
g_assert (introspection_data != NULL);
|
g_assert (introspection_data != NULL);
|
||||||
|
|
||||||
|
@@ -72,6 +72,9 @@ static void gnome_shell_plugin_kill_switch_workspace (MetaPlugin *plugin);
|
|||||||
|
|
||||||
static gboolean gnome_shell_plugin_xevent_filter (MetaPlugin *plugin,
|
static gboolean gnome_shell_plugin_xevent_filter (MetaPlugin *plugin,
|
||||||
XEvent *event);
|
XEvent *event);
|
||||||
|
|
||||||
|
static gboolean gnome_shell_plugin_keybinding_filter (MetaPlugin *plugin,
|
||||||
|
MetaKeyBinding *binding);
|
||||||
static const MetaPluginInfo *gnome_shell_plugin_plugin_info (MetaPlugin *plugin);
|
static const MetaPluginInfo *gnome_shell_plugin_plugin_info (MetaPlugin *plugin);
|
||||||
|
|
||||||
|
|
||||||
@@ -126,8 +129,9 @@ gnome_shell_plugin_class_init (GnomeShellPluginClass *klass)
|
|||||||
plugin_class->kill_window_effects = gnome_shell_plugin_kill_window_effects;
|
plugin_class->kill_window_effects = gnome_shell_plugin_kill_window_effects;
|
||||||
plugin_class->kill_switch_workspace = gnome_shell_plugin_kill_switch_workspace;
|
plugin_class->kill_switch_workspace = gnome_shell_plugin_kill_switch_workspace;
|
||||||
|
|
||||||
plugin_class->xevent_filter = gnome_shell_plugin_xevent_filter;
|
plugin_class->xevent_filter = gnome_shell_plugin_xevent_filter;
|
||||||
plugin_class->plugin_info = gnome_shell_plugin_plugin_info;
|
plugin_class->keybinding_filter = gnome_shell_plugin_keybinding_filter;
|
||||||
|
plugin_class->plugin_info = gnome_shell_plugin_plugin_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -337,6 +341,13 @@ gnome_shell_plugin_xevent_filter (MetaPlugin *plugin,
|
|||||||
return clutter_x11_handle_event (xev) != CLUTTER_X11_FILTER_CONTINUE;
|
return clutter_x11_handle_event (xev) != CLUTTER_X11_FILTER_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gnome_shell_plugin_keybinding_filter (MetaPlugin *plugin,
|
||||||
|
MetaKeyBinding *binding)
|
||||||
|
{
|
||||||
|
return _shell_wm_filter_keybinding (get_shell_wm (), binding);
|
||||||
|
}
|
||||||
|
|
||||||
static const
|
static const
|
||||||
MetaPluginInfo *gnome_shell_plugin_plugin_info (MetaPlugin *plugin)
|
MetaPluginInfo *gnome_shell_plugin_plugin_info (MetaPlugin *plugin)
|
||||||
{
|
{
|
||||||
|
@@ -38,7 +38,7 @@ extern GType gnome_shell_plugin_get_type (void);
|
|||||||
#define OVERRIDES_SCHEMA "org.gnome.shell.overrides"
|
#define OVERRIDES_SCHEMA "org.gnome.shell.overrides"
|
||||||
|
|
||||||
#define WM_NAME "GNOME Shell"
|
#define WM_NAME "GNOME Shell"
|
||||||
#define GNOME_WM_KEYBINDINGS "Metacity,Mutter,GNOME Shell"
|
#define GNOME_WM_KEYBINDINGS "Mutter,GNOME Shell"
|
||||||
|
|
||||||
static gboolean is_gdm_mode = FALSE;
|
static gboolean is_gdm_mode = FALSE;
|
||||||
static char *session_mode = NULL;
|
static char *session_mode = NULL;
|
||||||
|
@@ -14,6 +14,9 @@ struct _ShellRecorderSrc
|
|||||||
GMutex mutex_data;
|
GMutex mutex_data;
|
||||||
GMutex *mutex;
|
GMutex *mutex;
|
||||||
|
|
||||||
|
GstClock *clock;
|
||||||
|
GstClockTime last_frame_time;
|
||||||
|
|
||||||
GstCaps *caps;
|
GstCaps *caps;
|
||||||
GAsyncQueue *queue;
|
GAsyncQueue *queue;
|
||||||
gboolean closed;
|
gboolean closed;
|
||||||
@@ -41,6 +44,10 @@ static void
|
|||||||
shell_recorder_src_init (ShellRecorderSrc *src)
|
shell_recorder_src_init (ShellRecorderSrc *src)
|
||||||
{
|
{
|
||||||
gst_base_src_set_format (GST_BASE_SRC (src), GST_FORMAT_TIME);
|
gst_base_src_set_format (GST_BASE_SRC (src), GST_FORMAT_TIME);
|
||||||
|
gst_base_src_set_live (GST_BASE_SRC (src), TRUE);
|
||||||
|
|
||||||
|
src->clock = gst_system_clock_obtain ();
|
||||||
|
src->last_frame_time = 0;
|
||||||
|
|
||||||
src->queue = g_async_queue_new ();
|
src->queue = g_async_queue_new ();
|
||||||
src->mutex = &src->mutex_data;
|
src->mutex = &src->mutex_data;
|
||||||
@@ -89,6 +96,10 @@ shell_recorder_src_create (GstPushSrc *push_src,
|
|||||||
return GST_FLOW_EOS;
|
return GST_FLOW_EOS;
|
||||||
|
|
||||||
buffer = g_async_queue_pop (src->queue);
|
buffer = g_async_queue_pop (src->queue);
|
||||||
|
|
||||||
|
if (src->last_frame_time == 0)
|
||||||
|
src->last_frame_time = gst_clock_get_time (GST_CLOCK (src->clock));
|
||||||
|
|
||||||
if (buffer == RECORDER_QUEUE_END)
|
if (buffer == RECORDER_QUEUE_END)
|
||||||
{
|
{
|
||||||
/* Returning UNEXPECTED here will cause a EOS message to be sent */
|
/* Returning UNEXPECTED here will cause a EOS message to be sent */
|
||||||
@@ -100,6 +111,9 @@ shell_recorder_src_create (GstPushSrc *push_src,
|
|||||||
- (int)(gst_buffer_get_size(buffer) / 1024));
|
- (int)(gst_buffer_get_size(buffer) / 1024));
|
||||||
|
|
||||||
*buffer_out = buffer;
|
*buffer_out = buffer;
|
||||||
|
GST_BUFFER_DURATION(*buffer_out) = GST_CLOCK_DIFF (src->last_frame_time, gst_clock_get_time (GST_CLOCK (src->clock)));
|
||||||
|
|
||||||
|
src->last_frame_time = gst_clock_get_time (GST_CLOCK (src->clock));
|
||||||
|
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
}
|
}
|
||||||
@@ -141,6 +155,8 @@ shell_recorder_src_finalize (GObject *object)
|
|||||||
|
|
||||||
g_mutex_clear (src->mutex);
|
g_mutex_clear (src->mutex);
|
||||||
|
|
||||||
|
gst_object_unref (src->clock);
|
||||||
|
|
||||||
G_OBJECT_CLASS (shell_recorder_src_parent_class)->finalize (object);
|
G_OBJECT_CLASS (shell_recorder_src_parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -12,10 +12,10 @@
|
|||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
|
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
|
#include <gdk/gdk.h>
|
||||||
|
|
||||||
#include "shell-recorder-src.h"
|
#include "shell-recorder-src.h"
|
||||||
#include "shell-recorder.h"
|
#include "shell-recorder.h"
|
||||||
#include "shell-screen-grabber.h"
|
|
||||||
|
|
||||||
#include <clutter/x11/clutter-x11.h>
|
#include <clutter/x11/clutter-x11.h>
|
||||||
#include <X11/extensions/Xfixes.h>
|
#include <X11/extensions/Xfixes.h>
|
||||||
@@ -48,7 +48,7 @@ struct _ShellRecorder {
|
|||||||
int stage_width;
|
int stage_width;
|
||||||
int stage_height;
|
int stage_height;
|
||||||
|
|
||||||
ShellScreenGrabber *grabber;
|
GdkScreen *gdk_screen;
|
||||||
|
|
||||||
gboolean have_pointer;
|
gboolean have_pointer;
|
||||||
int pointer_x;
|
int pointer_x;
|
||||||
@@ -259,11 +259,11 @@ shell_recorder_init (ShellRecorder *recorder)
|
|||||||
|
|
||||||
shell_recorder_src_register ();
|
shell_recorder_src_register ();
|
||||||
|
|
||||||
|
recorder->gdk_screen = gdk_screen_get_default ();
|
||||||
|
|
||||||
recorder->recording_icon = create_recording_icon ();
|
recorder->recording_icon = create_recording_icon ();
|
||||||
recorder->memory_target = get_memory_target();
|
recorder->memory_target = get_memory_target();
|
||||||
|
|
||||||
recorder->grabber = shell_screen_grabber_new ();
|
|
||||||
|
|
||||||
recorder->state = RECORDER_STATE_CLOSED;
|
recorder->state = RECORDER_STATE_CLOSED;
|
||||||
recorder->framerate = DEFAULT_FRAMES_PER_SECOND;
|
recorder->framerate = DEFAULT_FRAMES_PER_SECOND;
|
||||||
}
|
}
|
||||||
@@ -283,8 +283,6 @@ shell_recorder_finalize (GObject *object)
|
|||||||
recorder_set_pipeline (recorder, NULL);
|
recorder_set_pipeline (recorder, NULL);
|
||||||
recorder_set_file_template (recorder, NULL);
|
recorder_set_file_template (recorder, NULL);
|
||||||
|
|
||||||
g_object_unref (recorder->grabber);
|
|
||||||
|
|
||||||
cogl_handle_unref (recorder->recording_icon);
|
cogl_handle_unref (recorder->recording_icon);
|
||||||
|
|
||||||
G_OBJECT_CLASS (shell_recorder_parent_class)->finalize (object);
|
G_OBJECT_CLASS (shell_recorder_parent_class)->finalize (object);
|
||||||
@@ -462,6 +460,12 @@ static void
|
|||||||
recorder_draw_buffer_meter (ShellRecorder *recorder)
|
recorder_draw_buffer_meter (ShellRecorder *recorder)
|
||||||
{
|
{
|
||||||
int fill_level;
|
int fill_level;
|
||||||
|
GdkRectangle primary_monitor;
|
||||||
|
float rects[16];
|
||||||
|
|
||||||
|
gdk_screen_get_monitor_geometry (recorder->gdk_screen,
|
||||||
|
gdk_screen_get_primary_monitor (recorder->gdk_screen),
|
||||||
|
&primary_monitor);
|
||||||
|
|
||||||
recorder_update_memory_used (recorder, FALSE);
|
recorder_update_memory_used (recorder, FALSE);
|
||||||
|
|
||||||
@@ -476,14 +480,27 @@ recorder_draw_buffer_meter (ShellRecorder *recorder)
|
|||||||
fill_level = MIN (60, (recorder->memory_used * 60) / recorder->memory_target);
|
fill_level = MIN (60, (recorder->memory_used * 60) / recorder->memory_target);
|
||||||
|
|
||||||
/* A hollow rectangle filled from the left to fill_level */
|
/* A hollow rectangle filled from the left to fill_level */
|
||||||
cogl_rectangle (recorder->stage_width - 64, recorder->stage_height - 10,
|
rects[0] = primary_monitor.x + primary_monitor.width - 64;
|
||||||
recorder->stage_width - 2, recorder->stage_height - 9);
|
rects[1] = primary_monitor.y + primary_monitor.height - 10;
|
||||||
cogl_rectangle (recorder->stage_width - 64, recorder->stage_height - 9,
|
rects[2] = primary_monitor.x + primary_monitor.width - 2;
|
||||||
recorder->stage_width - (63 - fill_level), recorder->stage_height - 3);
|
rects[3] = primary_monitor.y + primary_monitor.height - 9;
|
||||||
cogl_rectangle (recorder->stage_width - 3, recorder->stage_height - 9,
|
|
||||||
recorder->stage_width - 2, recorder->stage_height - 3);
|
rects[4] = primary_monitor.x + primary_monitor.width - 64;
|
||||||
cogl_rectangle (recorder->stage_width - 64, recorder->stage_height - 3,
|
rects[5] = primary_monitor.y + primary_monitor.height - 9;
|
||||||
recorder->stage_width - 2, recorder->stage_height - 2);
|
rects[6] = primary_monitor.x + primary_monitor.width - (63 - fill_level);
|
||||||
|
rects[7] = primary_monitor.y + primary_monitor.height - 3;
|
||||||
|
|
||||||
|
rects[8] = primary_monitor.x + primary_monitor.width - 3;
|
||||||
|
rects[9] = primary_monitor.y + primary_monitor.height - 9;
|
||||||
|
rects[10] = primary_monitor.x + primary_monitor.width - 2;
|
||||||
|
rects[11] = primary_monitor.y + primary_monitor.height - 3;
|
||||||
|
|
||||||
|
rects[12] = primary_monitor.x + primary_monitor.width - 64;
|
||||||
|
rects[13] = primary_monitor.y + primary_monitor.height - 3;
|
||||||
|
rects[14] = primary_monitor.x + primary_monitor.width - 2;
|
||||||
|
rects[15] = primary_monitor.y + primary_monitor.height - 2;
|
||||||
|
|
||||||
|
cogl_rectangles (rects, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We want to time-stamp each frame based on the actual time it was
|
/* We want to time-stamp each frame based on the actual time it was
|
||||||
@@ -533,8 +550,13 @@ recorder_record_frame (ShellRecorder *recorder)
|
|||||||
|
|
||||||
size = recorder->stage_width * recorder->stage_height * 4;
|
size = recorder->stage_width * recorder->stage_height * 4;
|
||||||
|
|
||||||
data = shell_screen_grabber_grab (recorder->grabber,
|
data = g_malloc (recorder->stage_width * 4 * recorder->stage_height);
|
||||||
0, 0, recorder->stage_width, recorder->stage_height);
|
cogl_read_pixels (0, 0, /* x/y */
|
||||||
|
recorder->stage_width,
|
||||||
|
recorder->stage_height,
|
||||||
|
COGL_READ_PIXELS_COLOR_BUFFER,
|
||||||
|
CLUTTER_CAIRO_FORMAT_ARGB32,
|
||||||
|
data);
|
||||||
|
|
||||||
buffer = gst_buffer_new();
|
buffer = gst_buffer_new();
|
||||||
gst_buffer_insert_memory (buffer, -1,
|
gst_buffer_insert_memory (buffer, -1,
|
||||||
@@ -562,12 +584,17 @@ recorder_on_stage_paint (ClutterActor *actor,
|
|||||||
{
|
{
|
||||||
if (recorder->state == RECORDER_STATE_RECORDING)
|
if (recorder->state == RECORDER_STATE_RECORDING)
|
||||||
{
|
{
|
||||||
|
GdkRectangle primary_monitor;
|
||||||
|
|
||||||
|
gdk_screen_get_monitor_geometry (recorder->gdk_screen,
|
||||||
|
gdk_screen_get_primary_monitor (recorder->gdk_screen),
|
||||||
|
&primary_monitor);
|
||||||
if (!recorder->only_paint)
|
if (!recorder->only_paint)
|
||||||
recorder_record_frame (recorder);
|
recorder_record_frame (recorder);
|
||||||
|
|
||||||
cogl_set_source_texture (recorder->recording_icon);
|
cogl_set_source_texture (recorder->recording_icon);
|
||||||
cogl_rectangle (recorder->stage_width - 32, recorder->stage_height - 42,
|
cogl_rectangle (primary_monitor.x + primary_monitor.width - 32, primary_monitor.y + primary_monitor.height - 42,
|
||||||
recorder->stage_width, recorder->stage_height - 10);
|
primary_monitor.x + primary_monitor.width, primary_monitor.y + primary_monitor.height - 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (recorder->state == RECORDER_STATE_RECORDING || recorder->memory_used != 0)
|
if (recorder->state == RECORDER_STATE_RECORDING || recorder->memory_used != 0)
|
||||||
@@ -1703,9 +1730,6 @@ shell_recorder_close (ShellRecorder *recorder)
|
|||||||
recorder->repaint_hook_id = 0;
|
recorder->repaint_hook_id = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
recorder_remove_redraw_timeout (recorder);
|
|
||||||
recorder_close_pipeline (recorder);
|
|
||||||
|
|
||||||
recorder->state = RECORDER_STATE_CLOSED;
|
recorder->state = RECORDER_STATE_CLOSED;
|
||||||
|
|
||||||
/* Release the refcount we took when we started recording */
|
/* Release the refcount we took when we started recording */
|
||||||
|
@@ -1,210 +0,0 @@
|
|||||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <clutter/clutter.h>
|
|
||||||
#include <cogl/cogl.h>
|
|
||||||
#include <GL/gl.h>
|
|
||||||
#include <GL/glx.h>
|
|
||||||
#include <GL/glext.h>
|
|
||||||
|
|
||||||
#include "shell-screen-grabber.h"
|
|
||||||
|
|
||||||
PFNGLBINDBUFFERARBPROC pf_glBindBufferARB;
|
|
||||||
PFNGLBUFFERDATAARBPROC pf_glBufferDataARB;
|
|
||||||
PFNGLDELETEBUFFERSARBPROC pf_glDeleteBuffersARB;
|
|
||||||
PFNGLGENBUFFERSARBPROC pf_glGenBuffersARB;
|
|
||||||
PFNGLMAPBUFFERARBPROC pf_glMapBufferARB;
|
|
||||||
PFNGLUNMAPBUFFERARBPROC pf_glUnmapBufferARB;
|
|
||||||
|
|
||||||
struct _ShellScreenGrabberClass
|
|
||||||
{
|
|
||||||
GObjectClass parent_class;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _ShellScreenGrabber
|
|
||||||
{
|
|
||||||
GObject parent_instance;
|
|
||||||
|
|
||||||
int have_pixel_buffers;
|
|
||||||
int have_pack_invert;
|
|
||||||
int width, height;
|
|
||||||
GLuint pixel_buffer;
|
|
||||||
};
|
|
||||||
|
|
||||||
G_DEFINE_TYPE(ShellScreenGrabber, shell_screen_grabber, G_TYPE_OBJECT);
|
|
||||||
|
|
||||||
static void
|
|
||||||
shell_screen_grabber_finalize (GObject *gobject)
|
|
||||||
{
|
|
||||||
ShellScreenGrabber *grabber = SHELL_SCREEN_GRABBER (gobject);
|
|
||||||
|
|
||||||
if (grabber->pixel_buffer != 0)
|
|
||||||
pf_glDeleteBuffersARB (1, &grabber->pixel_buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
shell_screen_grabber_class_init (ShellScreenGrabberClass *grabber_class)
|
|
||||||
{
|
|
||||||
GObjectClass *gobject_class = G_OBJECT_CLASS (grabber_class);
|
|
||||||
|
|
||||||
gobject_class->finalize = shell_screen_grabber_finalize;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
shell_screen_grabber_init (ShellScreenGrabber *grabber)
|
|
||||||
{
|
|
||||||
grabber->have_pixel_buffers = -1;
|
|
||||||
grabber->width = -1;
|
|
||||||
grabber->height= -1;
|
|
||||||
grabber->pixel_buffer = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ShellScreenGrabber *
|
|
||||||
shell_screen_grabber_new (void)
|
|
||||||
{
|
|
||||||
return g_object_new (SHELL_TYPE_SCREEN_GRABBER, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* shell_screen_grabber_grab:
|
|
||||||
* x: X coordinate of the rectangle to grab
|
|
||||||
* y: Y coordinate of the rectangle to grab
|
|
||||||
* width: width of the rectangle to grab
|
|
||||||
* height: heigth of the rectangle to grab
|
|
||||||
*
|
|
||||||
* Grabs pixel data from a portion of the screen.
|
|
||||||
*
|
|
||||||
* Return value: buffer holding the grabbed data. The data is stored as 32-bit
|
|
||||||
* words with native-endian xRGB pixels (i.e., the same as CAIRO_FORMAT_RGB24)
|
|
||||||
* with no padding on the rows. So, the size of the buffer is width * height * 4
|
|
||||||
* bytes. Free with g_free().
|
|
||||||
**/
|
|
||||||
guchar *
|
|
||||||
shell_screen_grabber_grab (ShellScreenGrabber *grabber,
|
|
||||||
int x,
|
|
||||||
int y,
|
|
||||||
int width,
|
|
||||||
int height)
|
|
||||||
{
|
|
||||||
guchar *data;
|
|
||||||
gsize row_bytes;
|
|
||||||
gsize data_size;
|
|
||||||
|
|
||||||
row_bytes = width * 4;
|
|
||||||
data_size = row_bytes * height;
|
|
||||||
data = g_malloc (data_size);
|
|
||||||
|
|
||||||
if (grabber->have_pixel_buffers == -1)
|
|
||||||
{
|
|
||||||
const GLubyte* extensions = glGetString (GL_EXTENSIONS);
|
|
||||||
grabber->have_pixel_buffers = strstr ((const char *)extensions, "GL_EXT_pixel_buffer_object") != NULL;
|
|
||||||
grabber->have_pack_invert = strstr ((const char *)extensions, "GL_MESA_pack_invert") != NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (grabber->have_pixel_buffers)
|
|
||||||
{
|
|
||||||
GLubyte *mapped_data;
|
|
||||||
GLint old_swap_bytes, old_lsb_first, old_row_length, old_skip_pixels, old_skip_rows, old_alignment;
|
|
||||||
GLint old_pack_invert = GL_FALSE;
|
|
||||||
GLint vp_size[4];
|
|
||||||
guchar *src_row, *dest_row;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
cogl_flush ();
|
|
||||||
|
|
||||||
if (pf_glBindBufferARB == NULL)
|
|
||||||
{
|
|
||||||
pf_glBindBufferARB = (PFNGLBINDBUFFERARBPROC) cogl_get_proc_address ("glBindBufferARB");
|
|
||||||
pf_glBufferDataARB = (PFNGLBUFFERDATAARBPROC) cogl_get_proc_address ("glBufferDataARB");
|
|
||||||
pf_glDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC) cogl_get_proc_address ("glDeleteBuffersARB");
|
|
||||||
pf_glGenBuffersARB = (PFNGLGENBUFFERSARBPROC) cogl_get_proc_address ("glGenBuffersARB");
|
|
||||||
pf_glMapBufferARB = (PFNGLMAPBUFFERARBPROC) cogl_get_proc_address ("glMapBufferARB");
|
|
||||||
pf_glUnmapBufferARB = (PFNGLUNMAPBUFFERARBPROC) cogl_get_proc_address ("glUnmapBufferARB");
|
|
||||||
}
|
|
||||||
|
|
||||||
glGetIntegerv (GL_PACK_SWAP_BYTES, &old_swap_bytes);
|
|
||||||
glGetIntegerv (GL_PACK_LSB_FIRST, &old_lsb_first);
|
|
||||||
glGetIntegerv (GL_PACK_ROW_LENGTH, &old_row_length);
|
|
||||||
glGetIntegerv (GL_PACK_SKIP_PIXELS, &old_skip_pixels);
|
|
||||||
glGetIntegerv (GL_PACK_SKIP_ROWS, &old_skip_rows);
|
|
||||||
glGetIntegerv (GL_PACK_ALIGNMENT, &old_alignment);
|
|
||||||
|
|
||||||
glPixelStorei (GL_PACK_SWAP_BYTES, GL_FALSE);
|
|
||||||
glPixelStorei (GL_PACK_LSB_FIRST, GL_FALSE);
|
|
||||||
glPixelStorei (GL_PACK_ROW_LENGTH, 0);
|
|
||||||
glPixelStorei (GL_PACK_SKIP_PIXELS, 0);
|
|
||||||
glPixelStorei (GL_PACK_SKIP_ROWS, 0);
|
|
||||||
glPixelStorei (GL_PACK_ALIGNMENT, 1);
|
|
||||||
|
|
||||||
if (grabber->have_pack_invert)
|
|
||||||
{
|
|
||||||
glGetIntegerv (GL_PACK_INVERT_MESA, &old_pack_invert);
|
|
||||||
glPixelStorei (GL_PACK_INVERT_MESA, GL_FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (grabber->pixel_buffer != 0 &&
|
|
||||||
(grabber->width != width ||
|
|
||||||
grabber->height != height))
|
|
||||||
{
|
|
||||||
pf_glDeleteBuffersARB (1, &grabber->pixel_buffer);
|
|
||||||
grabber->pixel_buffer = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (grabber->pixel_buffer == 0)
|
|
||||||
{
|
|
||||||
pf_glGenBuffersARB (1, &grabber->pixel_buffer);
|
|
||||||
|
|
||||||
pf_glBindBufferARB (GL_PIXEL_PACK_BUFFER_ARB, grabber->pixel_buffer);
|
|
||||||
pf_glBufferDataARB (GL_PIXEL_PACK_BUFFER_ARB, data_size, 0, GL_STREAM_READ_ARB);
|
|
||||||
|
|
||||||
grabber->width = width;
|
|
||||||
grabber->height = height;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pf_glBindBufferARB (GL_PIXEL_PACK_BUFFER_ARB, grabber->pixel_buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* In OpenGL, (x,y) specifies the bottom-left corner rather than the
|
|
||||||
* top-left */
|
|
||||||
glGetIntegerv (GL_VIEWPORT, vp_size);
|
|
||||||
y = vp_size[3] - (y + height);
|
|
||||||
glReadPixels (x, y, width, height, GL_BGRA, GL_UNSIGNED_BYTE, 0);
|
|
||||||
|
|
||||||
mapped_data = pf_glMapBufferARB (GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB);
|
|
||||||
|
|
||||||
src_row = mapped_data + (height - 1) * row_bytes;
|
|
||||||
dest_row = data;
|
|
||||||
|
|
||||||
for (i = 0; i < height; i++)
|
|
||||||
{
|
|
||||||
memcpy (dest_row, src_row, row_bytes);
|
|
||||||
src_row -= row_bytes;
|
|
||||||
dest_row += row_bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
pf_glUnmapBufferARB (GL_PIXEL_PACK_BUFFER_ARB);
|
|
||||||
pf_glBindBufferARB (GL_PIXEL_PACK_BUFFER_ARB, 0);
|
|
||||||
|
|
||||||
glPixelStorei (GL_PACK_SWAP_BYTES, old_swap_bytes);
|
|
||||||
glPixelStorei (GL_PACK_LSB_FIRST, old_lsb_first);
|
|
||||||
glPixelStorei (GL_PACK_ROW_LENGTH, old_row_length);
|
|
||||||
glPixelStorei (GL_PACK_SKIP_PIXELS, old_skip_pixels);
|
|
||||||
glPixelStorei (GL_PACK_SKIP_ROWS, old_skip_rows);
|
|
||||||
glPixelStorei (GL_PACK_ALIGNMENT, old_alignment);
|
|
||||||
|
|
||||||
if (grabber->have_pack_invert)
|
|
||||||
glPixelStorei (GL_PACK_INVERT_MESA, old_pack_invert);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cogl_read_pixels (x, y,
|
|
||||||
width, height,
|
|
||||||
COGL_READ_PIXELS_COLOR_BUFFER,
|
|
||||||
CLUTTER_CAIRO_FORMAT_ARGB32,
|
|
||||||
data);
|
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
@@ -1,44 +0,0 @@
|
|||||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
||||||
#ifndef __SHELL_SCREEN_GRABBER_H__
|
|
||||||
#define __SHELL_SCREEN_GRABBER_H__
|
|
||||||
|
|
||||||
#include <glib-object.h>
|
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SECTION:shell-screen-grabber
|
|
||||||
* @short_description: Grab pixel data from the screen
|
|
||||||
*
|
|
||||||
* The #ShellScreenGrabber object is used to download previous drawn
|
|
||||||
* content to the screen. It internally uses pixel-buffer objects if
|
|
||||||
* available, otherwise falls back to cogl_read_pixels().
|
|
||||||
*
|
|
||||||
* If you are repeatedly grabbing images of the same size from the
|
|
||||||
* screen, it makes sense to create one #ShellScreenGrabber and keep
|
|
||||||
* it around. Otherwise, it's fine to simply create one as needed and
|
|
||||||
* then get rid of it.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct _ShellScreenGrabber ShellScreenGrabber;
|
|
||||||
typedef struct _ShellScreenGrabberClass ShellScreenGrabberClass;
|
|
||||||
|
|
||||||
#define SHELL_TYPE_SCREEN_GRABBER (shell_screen_grabber_get_type ())
|
|
||||||
#define SHELL_SCREEN_GRABBER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), SHELL_TYPE_SCREEN_GRABBER, ShellScreenGrabber))
|
|
||||||
#define SHELL_SCREEN_GRABBER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SHELL_TYPE_SCREEN_GRABBER, ShellScreenGrabberClass))
|
|
||||||
#define SHELL_IS_SCREEN_GRABBER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), SHELL_TYPE_SCREEN_GRABBER))
|
|
||||||
#define SHELL_IS_SCREEN_GRABBER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SHELL_TYPE_SCREEN_GRABBER))
|
|
||||||
#define SHELL_SCREEN_GRABBER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SHELL_TYPE_SCREEN_GRABBER, ShellScreenGrabberClass))
|
|
||||||
|
|
||||||
GType shell_screen_grabber_get_type (void) G_GNUC_CONST;
|
|
||||||
|
|
||||||
ShellScreenGrabber *shell_screen_grabber_new (void);
|
|
||||||
guchar * shell_screen_grabber_grab (ShellScreenGrabber *grabber,
|
|
||||||
int x,
|
|
||||||
int y,
|
|
||||||
int width,
|
|
||||||
int height);
|
|
||||||
|
|
||||||
G_END_DECLS
|
|
||||||
|
|
||||||
#endif /* __SHELL_SCREEN_GRABBER_H__ */
|
|
@@ -1,5 +1,8 @@
|
|||||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
|
||||||
|
#define COGL_ENABLE_EXPERIMENTAL_API
|
||||||
|
#define CLUTTER_ENABLE_EXPERIMENTAL_API
|
||||||
|
|
||||||
#include <X11/extensions/Xfixes.h>
|
#include <X11/extensions/Xfixes.h>
|
||||||
#include <clutter/x11/clutter-x11.h>
|
#include <clutter/x11/clutter-x11.h>
|
||||||
#include <clutter/clutter.h>
|
#include <clutter/clutter.h>
|
||||||
@@ -10,7 +13,6 @@
|
|||||||
#include <meta/meta-shaped-texture.h>
|
#include <meta/meta-shaped-texture.h>
|
||||||
|
|
||||||
#include "shell-global.h"
|
#include "shell-global.h"
|
||||||
#include "shell-screen-grabber.h"
|
|
||||||
#include "shell-screenshot.h"
|
#include "shell-screenshot.h"
|
||||||
|
|
||||||
struct _ShellScreenshotClass
|
struct _ShellScreenshotClass
|
||||||
@@ -90,18 +92,33 @@ do_grab_screenshot (_screenshot_data *screenshot_data,
|
|||||||
int width,
|
int width,
|
||||||
int height)
|
int height)
|
||||||
{
|
{
|
||||||
ShellScreenGrabber *grabber;
|
CoglBitmap *bitmap;
|
||||||
static const cairo_user_data_key_t key;
|
ClutterBackend *backend;
|
||||||
|
CoglContext *context;
|
||||||
|
int stride;
|
||||||
guchar *data;
|
guchar *data;
|
||||||
|
|
||||||
grabber = shell_screen_grabber_new ();
|
backend = clutter_get_default_backend ();
|
||||||
data = shell_screen_grabber_grab (grabber, x, y, width, height);
|
context = clutter_backend_get_cogl_context (backend);
|
||||||
g_object_unref (grabber);
|
|
||||||
|
|
||||||
screenshot_data->image = cairo_image_surface_create_for_data (data, CAIRO_FORMAT_RGB24,
|
screenshot_data->image = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
|
||||||
width, height, width * 4);
|
width, height);
|
||||||
cairo_surface_set_user_data (screenshot_data->image, &key,
|
|
||||||
data, (cairo_destroy_func_t)g_free);
|
|
||||||
|
data = cairo_image_surface_get_data (screenshot_data->image);
|
||||||
|
stride = cairo_image_surface_get_stride (screenshot_data->image);
|
||||||
|
|
||||||
|
bitmap = cogl_bitmap_new_for_data (context,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
CLUTTER_CAIRO_FORMAT_ARGB32,
|
||||||
|
stride,
|
||||||
|
data);
|
||||||
|
cogl_framebuffer_read_pixels_into_bitmap (cogl_get_draw_framebuffer (),
|
||||||
|
x, y,
|
||||||
|
COGL_READ_PIXELS_COLOR_BUFFER,
|
||||||
|
bitmap);
|
||||||
|
cogl_object_unref (bitmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@@ -35,6 +35,9 @@ void _shell_wm_kill_window_effects (ShellWM *wm,
|
|||||||
MetaWindowActor *actor);
|
MetaWindowActor *actor);
|
||||||
void _shell_wm_kill_switch_workspace (ShellWM *wm);
|
void _shell_wm_kill_switch_workspace (ShellWM *wm);
|
||||||
|
|
||||||
|
gboolean _shell_wm_filter_keybinding (ShellWM *wm,
|
||||||
|
MetaKeyBinding *binding);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __SHELL_WM_PRIVATE_H__ */
|
#endif /* __SHELL_WM_PRIVATE_H__ */
|
||||||
|
@@ -26,6 +26,7 @@ enum
|
|||||||
SWITCH_WORKSPACE,
|
SWITCH_WORKSPACE,
|
||||||
KILL_SWITCH_WORKSPACE,
|
KILL_SWITCH_WORKSPACE,
|
||||||
KILL_WINDOW_EFFECTS,
|
KILL_WINDOW_EFFECTS,
|
||||||
|
FILTER_KEYBINDING,
|
||||||
|
|
||||||
LAST_SIGNAL
|
LAST_SIGNAL
|
||||||
};
|
};
|
||||||
@@ -115,6 +116,14 @@ shell_wm_class_init (ShellWMClass *klass)
|
|||||||
NULL, NULL, NULL,
|
NULL, NULL, NULL,
|
||||||
G_TYPE_NONE, 1,
|
G_TYPE_NONE, 1,
|
||||||
META_TYPE_WINDOW_ACTOR);
|
META_TYPE_WINDOW_ACTOR);
|
||||||
|
shell_wm_signals[FILTER_KEYBINDING] =
|
||||||
|
g_signal_new ("filter-keybinding",
|
||||||
|
G_TYPE_FROM_CLASS (klass),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
0,
|
||||||
|
g_signal_accumulator_true_handled, NULL, NULL,
|
||||||
|
G_TYPE_BOOLEAN, 1,
|
||||||
|
META_TYPE_KEY_BINDING);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -267,6 +276,17 @@ _shell_wm_destroy (ShellWM *wm,
|
|||||||
g_signal_emit (wm, shell_wm_signals[DESTROY], 0, actor);
|
g_signal_emit (wm, shell_wm_signals[DESTROY], 0, actor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
_shell_wm_filter_keybinding (ShellWM *wm,
|
||||||
|
MetaKeyBinding *binding)
|
||||||
|
{
|
||||||
|
gboolean rv;
|
||||||
|
|
||||||
|
g_signal_emit (wm, shell_wm_signals[FILTER_KEYBINDING], 0, binding, &rv);
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* shell_wm_new:
|
* shell_wm_new:
|
||||||
* @plugin: the #MetaPlugin
|
* @plugin: the #MetaPlugin
|
||||||
|
@@ -1073,6 +1073,8 @@ typedef struct {
|
|||||||
gchar *path;
|
gchar *path;
|
||||||
gint grid_width, grid_height;
|
gint grid_width, grid_height;
|
||||||
ClutterActor *actor;
|
ClutterActor *actor;
|
||||||
|
GFunc load_callback;
|
||||||
|
gpointer load_callback_data;
|
||||||
} AsyncImageData;
|
} AsyncImageData;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -1089,6 +1091,7 @@ on_sliced_image_loaded (GObject *source_object,
|
|||||||
GAsyncResult *res,
|
GAsyncResult *res,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
|
GObject *cache = source_object;
|
||||||
AsyncImageData *data = (AsyncImageData *)user_data;
|
AsyncImageData *data = (AsyncImageData *)user_data;
|
||||||
GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
|
GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
|
||||||
GList *list;
|
GList *list;
|
||||||
@@ -1102,6 +1105,9 @@ on_sliced_image_loaded (GObject *source_object,
|
|||||||
clutter_actor_hide (actor);
|
clutter_actor_hide (actor);
|
||||||
clutter_actor_add_child (data->actor, actor);
|
clutter_actor_add_child (data->actor, actor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data->load_callback != NULL)
|
||||||
|
data->load_callback (cache, data->load_callback_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -1156,6 +1162,8 @@ load_sliced_image (GSimpleAsyncResult *result,
|
|||||||
* @path: Path to a filename
|
* @path: Path to a filename
|
||||||
* @grid_width: Width in pixels
|
* @grid_width: Width in pixels
|
||||||
* @grid_height: Height in pixels
|
* @grid_height: Height in pixels
|
||||||
|
* @load_callback: (scope async) (allow-none): Function called when the image is loaded, or %NULL
|
||||||
|
* @user_data: Data to pass to the load callback
|
||||||
*
|
*
|
||||||
* This function reads a single image file which contains multiple images internally.
|
* This function reads a single image file which contains multiple images internally.
|
||||||
* The image file will be divided using @grid_width and @grid_height;
|
* The image file will be divided using @grid_width and @grid_height;
|
||||||
@@ -1165,10 +1173,12 @@ load_sliced_image (GSimpleAsyncResult *result,
|
|||||||
* Returns: (transfer none): A new #ClutterActor
|
* Returns: (transfer none): A new #ClutterActor
|
||||||
*/
|
*/
|
||||||
ClutterActor *
|
ClutterActor *
|
||||||
st_texture_cache_load_sliced_image (StTextureCache *cache,
|
st_texture_cache_load_sliced_image (StTextureCache *cache,
|
||||||
const gchar *path,
|
const gchar *path,
|
||||||
gint grid_width,
|
gint grid_width,
|
||||||
gint grid_height)
|
gint grid_height,
|
||||||
|
GFunc load_callback,
|
||||||
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
AsyncImageData *data;
|
AsyncImageData *data;
|
||||||
GSimpleAsyncResult *result;
|
GSimpleAsyncResult *result;
|
||||||
@@ -1179,6 +1189,8 @@ st_texture_cache_load_sliced_image (StTextureCache *cache,
|
|||||||
data->grid_height = grid_height;
|
data->grid_height = grid_height;
|
||||||
data->path = g_strdup (path);
|
data->path = g_strdup (path);
|
||||||
data->actor = actor;
|
data->actor = actor;
|
||||||
|
data->load_callback = load_callback;
|
||||||
|
data->load_callback_data = user_data;
|
||||||
g_object_ref (G_OBJECT (actor));
|
g_object_ref (G_OBJECT (actor));
|
||||||
|
|
||||||
result = g_simple_async_result_new (G_OBJECT (cache), on_sliced_image_loaded, data, st_texture_cache_load_sliced_image);
|
result = g_simple_async_result_new (G_OBJECT (cache), on_sliced_image_loaded, data, st_texture_cache_load_sliced_image);
|
||||||
|
@@ -69,10 +69,12 @@ GType st_texture_cache_get_type (void) G_GNUC_CONST;
|
|||||||
StTextureCache* st_texture_cache_get_default (void);
|
StTextureCache* st_texture_cache_get_default (void);
|
||||||
|
|
||||||
ClutterActor *
|
ClutterActor *
|
||||||
st_texture_cache_load_sliced_image (StTextureCache *cache,
|
st_texture_cache_load_sliced_image (StTextureCache *cache,
|
||||||
const gchar *path,
|
const gchar *path,
|
||||||
gint grid_width,
|
gint grid_width,
|
||||||
gint grid_height);
|
gint grid_height,
|
||||||
|
GFunc load_callback,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
ClutterActor *st_texture_cache_bind_pixbuf_property (StTextureCache *cache,
|
ClutterActor *st_texture_cache_bind_pixbuf_property (StTextureCache *cache,
|
||||||
GObject *object,
|
GObject *object,
|
||||||
|
@@ -31,6 +31,9 @@ struct _StThemeContext {
|
|||||||
PangoFontDescription *font;
|
PangoFontDescription *font;
|
||||||
StThemeNode *root_node;
|
StThemeNode *root_node;
|
||||||
StTheme *theme;
|
StTheme *theme;
|
||||||
|
|
||||||
|
/* set of StThemeNode */
|
||||||
|
GHashTable *nodes;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _StThemeContextClass {
|
struct _StThemeContextClass {
|
||||||
@@ -66,6 +69,8 @@ st_theme_context_finalize (GObject *object)
|
|||||||
(gpointer) st_theme_context_changed,
|
(gpointer) st_theme_context_changed,
|
||||||
context);
|
context);
|
||||||
|
|
||||||
|
if (context->nodes)
|
||||||
|
g_hash_table_unref (context->nodes);
|
||||||
if (context->root_node)
|
if (context->root_node)
|
||||||
g_object_unref (context->root_node);
|
g_object_unref (context->root_node);
|
||||||
if (context->theme)
|
if (context->theme)
|
||||||
@@ -105,6 +110,10 @@ st_theme_context_init (StThemeContext *context)
|
|||||||
"resolution-changed",
|
"resolution-changed",
|
||||||
G_CALLBACK (st_theme_context_changed),
|
G_CALLBACK (st_theme_context_changed),
|
||||||
context);
|
context);
|
||||||
|
|
||||||
|
context->nodes = g_hash_table_new_full ((GHashFunc) st_theme_node_hash,
|
||||||
|
(GEqualFunc) st_theme_node_equal,
|
||||||
|
g_object_unref, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -146,6 +155,7 @@ st_theme_context_changed (StThemeContext *context)
|
|||||||
{
|
{
|
||||||
StThemeNode *old_root = context->root_node;
|
StThemeNode *old_root = context->root_node;
|
||||||
context->root_node = NULL;
|
context->root_node = NULL;
|
||||||
|
g_hash_table_remove_all (context->nodes);
|
||||||
|
|
||||||
emit_changed (context);
|
emit_changed (context);
|
||||||
|
|
||||||
@@ -299,3 +309,27 @@ st_theme_context_get_root_node (StThemeContext *context)
|
|||||||
|
|
||||||
return context->root_node;
|
return context->root_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* st_theme_context_intern_node:
|
||||||
|
* @context: a #StThemeContext
|
||||||
|
* @node: a #StThemeNode
|
||||||
|
*
|
||||||
|
* Return an existing node matching @node, or if that isn't possible,
|
||||||
|
* @node itself.
|
||||||
|
*
|
||||||
|
* Return value: (transfer none): a node with the same properties as @node
|
||||||
|
*/
|
||||||
|
StThemeNode *
|
||||||
|
st_theme_context_intern_node (StThemeContext *context,
|
||||||
|
StThemeNode *node)
|
||||||
|
{
|
||||||
|
StThemeNode *mine = g_hash_table_lookup (context->nodes, node);
|
||||||
|
|
||||||
|
/* this might be node or not - it doesn't actually matter */
|
||||||
|
if (mine != NULL)
|
||||||
|
return mine;
|
||||||
|
|
||||||
|
g_hash_table_add (context->nodes, g_object_ref (node));
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
@@ -62,6 +62,9 @@ const PangoFontDescription *st_theme_context_get_font (StThemeContext
|
|||||||
|
|
||||||
StThemeNode * st_theme_context_get_root_node (StThemeContext *context);
|
StThemeNode * st_theme_context_get_root_node (StThemeContext *context);
|
||||||
|
|
||||||
|
StThemeNode * st_theme_context_intern_node (StThemeContext *context,
|
||||||
|
StThemeNode *node);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __ST_THEME_CONTEXT_H__ */
|
#endif /* __ST_THEME_CONTEXT_H__ */
|
||||||
|
@@ -1553,7 +1553,7 @@ st_theme_node_paint_borders (StThemeNode *node,
|
|||||||
{
|
{
|
||||||
ClutterColor effective_border;
|
ClutterColor effective_border;
|
||||||
gboolean skip_corner_1, skip_corner_2;
|
gboolean skip_corner_1, skip_corner_2;
|
||||||
float x1, y1, x2, y2;
|
float rects[16];
|
||||||
|
|
||||||
over (&border_color, &node->background_color, &effective_border);
|
over (&border_color, &node->background_color, &effective_border);
|
||||||
alpha = paint_opacity * effective_border.alpha / 255;
|
alpha = paint_opacity * effective_border.alpha / 255;
|
||||||
@@ -1569,46 +1569,44 @@ st_theme_node_paint_borders (StThemeNode *node,
|
|||||||
skip_corner_1 = border_radius[ST_CORNER_TOPLEFT] > 0;
|
skip_corner_1 = border_radius[ST_CORNER_TOPLEFT] > 0;
|
||||||
skip_corner_2 = border_radius[ST_CORNER_TOPRIGHT] > 0;
|
skip_corner_2 = border_radius[ST_CORNER_TOPRIGHT] > 0;
|
||||||
|
|
||||||
x1 = skip_corner_1 ? max_width_radius[ST_CORNER_TOPLEFT] : 0;
|
rects[0] = skip_corner_1 ? max_width_radius[ST_CORNER_TOPLEFT] : 0;
|
||||||
y1 = 0;
|
rects[1] = 0;
|
||||||
x2 = skip_corner_2 ? width - max_width_radius[ST_CORNER_TOPRIGHT] : width;
|
rects[2] = skip_corner_2 ? width - max_width_radius[ST_CORNER_TOPRIGHT] : width;
|
||||||
y2 = border_width[ST_SIDE_TOP];
|
rects[3] = border_width[ST_SIDE_TOP];
|
||||||
cogl_rectangle (x1, y1, x2, y2);
|
|
||||||
|
|
||||||
/* EAST */
|
/* EAST */
|
||||||
skip_corner_1 = border_radius[ST_CORNER_TOPRIGHT] > 0;
|
skip_corner_1 = border_radius[ST_CORNER_TOPRIGHT] > 0;
|
||||||
skip_corner_2 = border_radius[ST_CORNER_BOTTOMRIGHT] > 0;
|
skip_corner_2 = border_radius[ST_CORNER_BOTTOMRIGHT] > 0;
|
||||||
|
|
||||||
x1 = width - border_width[ST_SIDE_RIGHT];
|
rects[4] = width - border_width[ST_SIDE_RIGHT];
|
||||||
y1 = skip_corner_1 ? max_width_radius[ST_CORNER_TOPRIGHT]
|
rects[5] = skip_corner_1 ? max_width_radius[ST_CORNER_TOPRIGHT]
|
||||||
: border_width[ST_SIDE_TOP];
|
: border_width[ST_SIDE_TOP];
|
||||||
x2 = width;
|
rects[6] = width;
|
||||||
y2 = skip_corner_2 ? height - max_width_radius[ST_CORNER_BOTTOMRIGHT]
|
rects[7] = skip_corner_2 ? height - max_width_radius[ST_CORNER_BOTTOMRIGHT]
|
||||||
: height - border_width[ST_SIDE_BOTTOM];
|
: height - border_width[ST_SIDE_BOTTOM];
|
||||||
cogl_rectangle (x1, y1, x2, y2);
|
|
||||||
|
|
||||||
/* SOUTH */
|
/* SOUTH */
|
||||||
skip_corner_1 = border_radius[ST_CORNER_BOTTOMLEFT] > 0;
|
skip_corner_1 = border_radius[ST_CORNER_BOTTOMLEFT] > 0;
|
||||||
skip_corner_2 = border_radius[ST_CORNER_BOTTOMRIGHT] > 0;
|
skip_corner_2 = border_radius[ST_CORNER_BOTTOMRIGHT] > 0;
|
||||||
|
|
||||||
x1 = skip_corner_1 ? max_width_radius[ST_CORNER_BOTTOMLEFT] : 0;
|
rects[8] = skip_corner_1 ? max_width_radius[ST_CORNER_BOTTOMLEFT] : 0;
|
||||||
y1 = height - border_width[ST_SIDE_BOTTOM];
|
rects[9] = height - border_width[ST_SIDE_BOTTOM];
|
||||||
x2 = skip_corner_2 ? width - max_width_radius[ST_CORNER_BOTTOMRIGHT]
|
rects[10] = skip_corner_2 ? width - max_width_radius[ST_CORNER_BOTTOMRIGHT]
|
||||||
: width;
|
: width;
|
||||||
y2 = height;
|
rects[11] = height;
|
||||||
cogl_rectangle (x1, y1, x2, y2);
|
|
||||||
|
|
||||||
/* WEST */
|
/* WEST */
|
||||||
skip_corner_1 = border_radius[ST_CORNER_TOPLEFT] > 0;
|
skip_corner_1 = border_radius[ST_CORNER_TOPLEFT] > 0;
|
||||||
skip_corner_2 = border_radius[ST_CORNER_BOTTOMLEFT] > 0;
|
skip_corner_2 = border_radius[ST_CORNER_BOTTOMLEFT] > 0;
|
||||||
|
|
||||||
x1 = 0;
|
rects[12] = 0;
|
||||||
y1 = skip_corner_1 ? max_width_radius[ST_CORNER_TOPLEFT]
|
rects[13] = skip_corner_1 ? max_width_radius[ST_CORNER_TOPLEFT]
|
||||||
: border_width[ST_SIDE_TOP];
|
: border_width[ST_SIDE_TOP];
|
||||||
x2 = border_width[ST_SIDE_LEFT];
|
rects[14] = border_width[ST_SIDE_LEFT];
|
||||||
y2 = skip_corner_2 ? height - max_width_radius[ST_CORNER_BOTTOMLEFT]
|
rects[15] = skip_corner_2 ? height - max_width_radius[ST_CORNER_BOTTOMLEFT]
|
||||||
: height - border_width[ST_SIDE_BOTTOM];
|
: height - border_width[ST_SIDE_BOTTOM];
|
||||||
cogl_rectangle (x1, y1, x2, y2);
|
|
||||||
|
cogl_rectangles (rects, 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1875,6 +1873,7 @@ st_theme_node_paint_outline (StThemeNode *node,
|
|||||||
{
|
{
|
||||||
float width, height;
|
float width, height;
|
||||||
int outline_width;
|
int outline_width;
|
||||||
|
float rects[16];
|
||||||
ClutterColor outline_color, effective_outline;
|
ClutterColor outline_color, effective_outline;
|
||||||
|
|
||||||
width = box->x2 - box->x1;
|
width = box->x2 - box->x1;
|
||||||
@@ -1899,20 +1898,30 @@ st_theme_node_paint_outline (StThemeNode *node,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* NORTH */
|
/* NORTH */
|
||||||
cogl_rectangle (-outline_width, -outline_width,
|
rects[0] = -outline_width;
|
||||||
width + outline_width, 0);
|
rects[1] = -outline_width;
|
||||||
|
rects[2] = width + outline_width;
|
||||||
|
rects[3] = 0;
|
||||||
|
|
||||||
/* EAST */
|
/* EAST */
|
||||||
cogl_rectangle (width, 0,
|
rects[4] = width;
|
||||||
width + outline_width, height);
|
rects[5] = 0;
|
||||||
|
rects[6] = width + outline_width;
|
||||||
|
rects[7] = height;
|
||||||
|
|
||||||
/* SOUTH */
|
/* SOUTH */
|
||||||
cogl_rectangle (-outline_width, height,
|
rects[8] = -outline_width;
|
||||||
width + outline_width, height + outline_width);
|
rects[9] = height;
|
||||||
|
rects[10] = width + outline_width;
|
||||||
|
rects[11] = height + outline_width;
|
||||||
|
|
||||||
/* WEST */
|
/* WEST */
|
||||||
cogl_rectangle (-outline_width, 0,
|
rects[12] = -outline_width;
|
||||||
0, height);
|
rects[13] = 0;
|
||||||
|
rects[14] = 0;
|
||||||
|
rects[15] = height;
|
||||||
|
|
||||||
|
cogl_rectangles (rects, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -2060,6 +2069,9 @@ st_theme_node_copy_cached_paint_state (StThemeNode *node,
|
|||||||
g_return_if_fail (ST_IS_THEME_NODE (node));
|
g_return_if_fail (ST_IS_THEME_NODE (node));
|
||||||
g_return_if_fail (ST_IS_THEME_NODE (other));
|
g_return_if_fail (ST_IS_THEME_NODE (other));
|
||||||
|
|
||||||
|
if (node == other)
|
||||||
|
return;
|
||||||
|
|
||||||
/* Check omitted for speed: */
|
/* Check omitted for speed: */
|
||||||
/* g_return_if_fail (st_theme_node_paint_equal (node, other)); */
|
/* g_return_if_fail (st_theme_node_paint_equal (node, other)); */
|
||||||
|
|
||||||
|
@@ -77,8 +77,8 @@ struct _StThemeNode {
|
|||||||
|
|
||||||
GType element_type;
|
GType element_type;
|
||||||
char *element_id;
|
char *element_id;
|
||||||
char *element_class;
|
GStrv element_classes;
|
||||||
char *pseudo_class;
|
GStrv pseudo_classes;
|
||||||
char *inline_style;
|
char *inline_style;
|
||||||
|
|
||||||
CRDeclaration **properties;
|
CRDeclaration **properties;
|
||||||
|
@@ -41,7 +41,6 @@ struct _StThemeNodeTransitionPrivate {
|
|||||||
|
|
||||||
CoglHandle material;
|
CoglHandle material;
|
||||||
|
|
||||||
ClutterAlpha *alpha;
|
|
||||||
ClutterTimeline *timeline;
|
ClutterTimeline *timeline;
|
||||||
|
|
||||||
guint timeline_completed_id;
|
guint timeline_completed_id;
|
||||||
@@ -91,7 +90,6 @@ st_theme_node_transition_new (StThemeNode *from_node,
|
|||||||
transition->priv->old_theme_node = g_object_ref (from_node);
|
transition->priv->old_theme_node = g_object_ref (from_node);
|
||||||
transition->priv->new_theme_node = g_object_ref (to_node);
|
transition->priv->new_theme_node = g_object_ref (to_node);
|
||||||
|
|
||||||
transition->priv->alpha = clutter_alpha_new ();
|
|
||||||
transition->priv->timeline = clutter_timeline_new (duration);
|
transition->priv->timeline = clutter_timeline_new (duration);
|
||||||
|
|
||||||
transition->priv->timeline_completed_id =
|
transition->priv->timeline_completed_id =
|
||||||
@@ -101,9 +99,7 @@ st_theme_node_transition_new (StThemeNode *from_node,
|
|||||||
g_signal_connect (transition->priv->timeline, "new-frame",
|
g_signal_connect (transition->priv->timeline, "new-frame",
|
||||||
G_CALLBACK (on_timeline_new_frame), transition);
|
G_CALLBACK (on_timeline_new_frame), transition);
|
||||||
|
|
||||||
clutter_alpha_set_mode (transition->priv->alpha, CLUTTER_EASE_IN_OUT_QUAD);
|
clutter_timeline_set_progress_mode (transition->priv->timeline, CLUTTER_EASE_IN_OUT_QUAD);
|
||||||
clutter_alpha_set_timeline (transition->priv->alpha,
|
|
||||||
transition->priv->timeline);
|
|
||||||
|
|
||||||
clutter_timeline_start (transition->priv->timeline);
|
clutter_timeline_start (transition->priv->timeline);
|
||||||
|
|
||||||
@@ -334,7 +330,7 @@ st_theme_node_transition_paint (StThemeNodeTransition *transition,
|
|||||||
}
|
}
|
||||||
|
|
||||||
cogl_color_set_from_4f (&constant, 0., 0., 0.,
|
cogl_color_set_from_4f (&constant, 0., 0., 0.,
|
||||||
clutter_alpha_get_alpha (priv->alpha));
|
clutter_timeline_get_progress (priv->timeline));
|
||||||
cogl_material_set_layer_combine_constant (priv->material, 1, &constant);
|
cogl_material_set_layer_combine_constant (priv->material, 1, &constant);
|
||||||
|
|
||||||
cogl_material_set_color4ub (priv->material,
|
cogl_material_set_color4ub (priv->material,
|
||||||
@@ -412,12 +408,6 @@ st_theme_node_transition_dispose (GObject *object)
|
|||||||
priv->timeline_completed_id = 0;
|
priv->timeline_completed_id = 0;
|
||||||
priv->timeline_new_frame_id = 0;
|
priv->timeline_new_frame_id = 0;
|
||||||
|
|
||||||
if (priv->alpha)
|
|
||||||
{
|
|
||||||
g_object_unref (priv->alpha);
|
|
||||||
priv->alpha = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (st_theme_node_transition_parent_class)->dispose (object);
|
G_OBJECT_CLASS (st_theme_node_transition_parent_class)->dispose (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -436,8 +426,6 @@ st_theme_node_transition_init (StThemeNodeTransition *transition)
|
|||||||
transition->priv->new_offscreen = NULL;
|
transition->priv->new_offscreen = NULL;
|
||||||
|
|
||||||
transition->priv->needs_setup = TRUE;
|
transition->priv->needs_setup = TRUE;
|
||||||
|
|
||||||
transition->priv->alpha = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@@ -96,8 +96,8 @@ st_theme_node_finalize (GObject *object)
|
|||||||
StThemeNode *node = ST_THEME_NODE (object);
|
StThemeNode *node = ST_THEME_NODE (object);
|
||||||
|
|
||||||
g_free (node->element_id);
|
g_free (node->element_id);
|
||||||
g_free (node->element_class);
|
g_strfreev (node->element_classes);
|
||||||
g_free (node->pseudo_class);
|
g_strfreev (node->pseudo_classes);
|
||||||
g_free (node->inline_style);
|
g_free (node->inline_style);
|
||||||
|
|
||||||
if (node->properties)
|
if (node->properties)
|
||||||
@@ -145,6 +145,33 @@ st_theme_node_finalize (GObject *object)
|
|||||||
G_OBJECT_CLASS (st_theme_node_parent_class)->finalize (object);
|
G_OBJECT_CLASS (st_theme_node_parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GStrv
|
||||||
|
split_on_whitespace (const gchar *s)
|
||||||
|
{
|
||||||
|
gchar *cur;
|
||||||
|
gchar *l;
|
||||||
|
gchar *temp;
|
||||||
|
GPtrArray *arr;
|
||||||
|
|
||||||
|
if (s == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
arr = g_ptr_array_new ();
|
||||||
|
l = g_strdup (s);
|
||||||
|
|
||||||
|
cur = strtok_r (l, " \t\f\r\n", &temp);
|
||||||
|
|
||||||
|
while (cur != NULL)
|
||||||
|
{
|
||||||
|
g_ptr_array_add (arr, g_strdup (cur));
|
||||||
|
cur = strtok_r (NULL, " \t\f\r\n", &temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (l);
|
||||||
|
g_ptr_array_add (arr, NULL);
|
||||||
|
return (GStrv) g_ptr_array_free (arr, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* st_theme_node_new:
|
* st_theme_node_new:
|
||||||
* @context: the context representing global state for this themed tree
|
* @context: the context representing global state for this themed tree
|
||||||
@@ -201,8 +228,8 @@ st_theme_node_new (StThemeContext *context,
|
|||||||
|
|
||||||
node->element_type = element_type;
|
node->element_type = element_type;
|
||||||
node->element_id = g_strdup (element_id);
|
node->element_id = g_strdup (element_id);
|
||||||
node->element_class = g_strdup (element_class);
|
node->element_classes = split_on_whitespace (element_class);
|
||||||
node->pseudo_class = g_strdup (pseudo_class);
|
node->pseudo_classes = split_on_whitespace (pseudo_class);
|
||||||
node->inline_style = g_strdup (inline_style);
|
node->inline_style = g_strdup (inline_style);
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
@@ -257,20 +284,30 @@ st_theme_node_get_element_id (StThemeNode *node)
|
|||||||
return node->element_id;
|
return node->element_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *
|
/**
|
||||||
st_theme_node_get_element_class (StThemeNode *node)
|
* st_theme_node_get_element_classes:
|
||||||
|
*
|
||||||
|
* Returns: (transfer none): the element's classes
|
||||||
|
*/
|
||||||
|
GStrv
|
||||||
|
st_theme_node_get_element_classes (StThemeNode *node)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (ST_IS_THEME_NODE (node), NULL);
|
g_return_val_if_fail (ST_IS_THEME_NODE (node), NULL);
|
||||||
|
|
||||||
return node->element_class;
|
return node->element_classes;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *
|
/**
|
||||||
st_theme_node_get_pseudo_class (StThemeNode *node)
|
* st_theme_node_get_pseudo_classes:
|
||||||
|
*
|
||||||
|
* Returns: (transfer none): the element's pseudo-classes
|
||||||
|
*/
|
||||||
|
GStrv
|
||||||
|
st_theme_node_get_pseudo_classes (StThemeNode *node)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (ST_IS_THEME_NODE (node), NULL);
|
g_return_val_if_fail (ST_IS_THEME_NODE (node), NULL);
|
||||||
|
|
||||||
return node->pseudo_class;
|
return node->pseudo_classes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -304,16 +341,91 @@ gboolean
|
|||||||
st_theme_node_equal (StThemeNode *node_a, StThemeNode *node_b)
|
st_theme_node_equal (StThemeNode *node_a, StThemeNode *node_b)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (ST_IS_THEME_NODE (node_a), FALSE);
|
g_return_val_if_fail (ST_IS_THEME_NODE (node_a), FALSE);
|
||||||
|
|
||||||
|
if (node_a == node_b)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
g_return_val_if_fail (ST_IS_THEME_NODE (node_b), FALSE);
|
g_return_val_if_fail (ST_IS_THEME_NODE (node_b), FALSE);
|
||||||
|
|
||||||
return node_a->parent_node == node_b->parent_node &&
|
if (node_a->parent_node != node_b->parent_node ||
|
||||||
node_a->context == node_b->context &&
|
node_a->context != node_b->context ||
|
||||||
node_a->theme == node_b->theme &&
|
node_a->theme != node_b->theme ||
|
||||||
node_a->element_type == node_b->element_type &&
|
node_a->element_type != node_b->element_type ||
|
||||||
!g_strcmp0 (node_a->element_id, node_b->element_id) &&
|
g_strcmp0 (node_a->element_id, node_b->element_id) ||
|
||||||
!g_strcmp0 (node_a->element_class, node_b->element_class) &&
|
g_strcmp0 (node_a->inline_style, node_b->inline_style))
|
||||||
!g_strcmp0 (node_a->pseudo_class, node_b->pseudo_class) &&
|
return FALSE;
|
||||||
!g_strcmp0 (node_a->inline_style, node_b->inline_style);
|
|
||||||
|
if ((node_a->element_classes == NULL) != (node_b->element_classes == NULL))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if ((node_a->pseudo_classes == NULL) != (node_b->pseudo_classes == NULL))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (node_a->element_classes != NULL)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; ; i++)
|
||||||
|
{
|
||||||
|
if (g_strcmp0 (node_a->element_classes[i],
|
||||||
|
node_b->element_classes[i]))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (node_a->element_classes[i] == NULL)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node_a->pseudo_classes != NULL)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; ; i++)
|
||||||
|
{
|
||||||
|
if (g_strcmp0 (node_a->pseudo_classes[i],
|
||||||
|
node_b->pseudo_classes[i]))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (node_a->pseudo_classes[i] == NULL)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
guint
|
||||||
|
st_theme_node_hash (StThemeNode *node)
|
||||||
|
{
|
||||||
|
guint hash = GPOINTER_TO_UINT (node->parent_node);
|
||||||
|
|
||||||
|
hash = hash * 33 + GPOINTER_TO_UINT (node->context);
|
||||||
|
hash = hash * 33 + GPOINTER_TO_UINT (node->theme);
|
||||||
|
hash = hash * 33 + ((guint) node->element_type);
|
||||||
|
|
||||||
|
if (node->element_id != NULL)
|
||||||
|
hash = hash * 33 + g_str_hash (node->element_id);
|
||||||
|
|
||||||
|
if (node->inline_style != NULL)
|
||||||
|
hash = hash * 33 + g_str_hash (node->inline_style);
|
||||||
|
|
||||||
|
if (node->element_classes != NULL)
|
||||||
|
{
|
||||||
|
gchar **it;
|
||||||
|
|
||||||
|
for (it = node->element_classes; *it != NULL; it++)
|
||||||
|
hash = hash * 33 + g_str_hash (*it) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node->pseudo_classes != NULL)
|
||||||
|
{
|
||||||
|
gchar **it;
|
||||||
|
|
||||||
|
for (it = node->pseudo_classes; *it != NULL; it++)
|
||||||
|
hash = hash * 33 + g_str_hash (*it) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -3440,6 +3552,10 @@ st_theme_node_geometry_equal (StThemeNode *node,
|
|||||||
StSide side;
|
StSide side;
|
||||||
|
|
||||||
g_return_val_if_fail (ST_IS_THEME_NODE (node), FALSE);
|
g_return_val_if_fail (ST_IS_THEME_NODE (node), FALSE);
|
||||||
|
|
||||||
|
if (node == other)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
g_return_val_if_fail (ST_IS_THEME_NODE (other), FALSE);
|
g_return_val_if_fail (ST_IS_THEME_NODE (other), FALSE);
|
||||||
|
|
||||||
_st_theme_node_ensure_geometry (node);
|
_st_theme_node_ensure_geometry (node);
|
||||||
@@ -3484,6 +3600,10 @@ st_theme_node_paint_equal (StThemeNode *node,
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
g_return_val_if_fail (ST_IS_THEME_NODE (node), FALSE);
|
g_return_val_if_fail (ST_IS_THEME_NODE (node), FALSE);
|
||||||
|
|
||||||
|
if (node == other)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
g_return_val_if_fail (ST_IS_THEME_NODE (other), FALSE);
|
g_return_val_if_fail (ST_IS_THEME_NODE (other), FALSE);
|
||||||
|
|
||||||
_st_theme_node_ensure_background (node);
|
_st_theme_node_ensure_background (node);
|
||||||
|
@@ -110,11 +110,12 @@ StThemeNode *st_theme_node_get_parent (StThemeNode *node);
|
|||||||
StTheme *st_theme_node_get_theme (StThemeNode *node);
|
StTheme *st_theme_node_get_theme (StThemeNode *node);
|
||||||
|
|
||||||
gboolean st_theme_node_equal (StThemeNode *node_a, StThemeNode *node_b);
|
gboolean st_theme_node_equal (StThemeNode *node_a, StThemeNode *node_b);
|
||||||
|
guint st_theme_node_hash (StThemeNode *node);
|
||||||
|
|
||||||
GType st_theme_node_get_element_type (StThemeNode *node);
|
GType st_theme_node_get_element_type (StThemeNode *node);
|
||||||
const char *st_theme_node_get_element_id (StThemeNode *node);
|
const char *st_theme_node_get_element_id (StThemeNode *node);
|
||||||
const char *st_theme_node_get_element_class (StThemeNode *node);
|
GStrv st_theme_node_get_element_classes (StThemeNode *node);
|
||||||
const char *st_theme_node_get_pseudo_class (StThemeNode *node);
|
GStrv st_theme_node_get_pseudo_classes (StThemeNode *node);
|
||||||
|
|
||||||
/* Generic getters ... these are not cached so are less efficient. The other
|
/* Generic getters ... these are not cached so are less efficient. The other
|
||||||
* reason for adding the more specific version is that we can handle the
|
* reason for adding the more specific version is that we can handle the
|
||||||
|
@@ -448,28 +448,20 @@ st_theme_new (const char *application_stylesheet,
|
|||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
string_in_list (GString *stryng,
|
string_in_list (GString *stryng,
|
||||||
const char *list)
|
GStrv list)
|
||||||
{
|
{
|
||||||
char *cur;
|
gchar **it;
|
||||||
char *l = g_strdup (list);
|
|
||||||
char *temp;
|
|
||||||
gboolean found = FALSE;
|
|
||||||
|
|
||||||
cur = strtok_r (l, " \t\f\r\n", &temp);
|
if (list == NULL)
|
||||||
while (cur != NULL)
|
return FALSE;
|
||||||
|
|
||||||
|
for (it = list; *it != NULL; it++)
|
||||||
{
|
{
|
||||||
if (!strqcmp (cur, stryng->str, stryng->len))
|
if (!strqcmp (*it, stryng->str, stryng->len))
|
||||||
{
|
return TRUE;
|
||||||
found = TRUE;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
cur = strtok_r (NULL, " \t\f\r\n", &temp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
return FALSE;
|
||||||
g_free (l);
|
|
||||||
return found;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@@ -477,7 +469,7 @@ pseudo_class_add_sel_matches_style (StTheme *a_this,
|
|||||||
CRAdditionalSel *a_add_sel,
|
CRAdditionalSel *a_add_sel,
|
||||||
StThemeNode *a_node)
|
StThemeNode *a_node)
|
||||||
{
|
{
|
||||||
const char *node_pseudo_class;
|
GStrv node_pseudo_classes;
|
||||||
|
|
||||||
g_return_val_if_fail (a_this
|
g_return_val_if_fail (a_this
|
||||||
&& a_add_sel
|
&& a_add_sel
|
||||||
@@ -487,12 +479,10 @@ pseudo_class_add_sel_matches_style (StTheme *a_this,
|
|||||||
&& a_add_sel->content.pseudo->name->stryng->str
|
&& a_add_sel->content.pseudo->name->stryng->str
|
||||||
&& a_node, FALSE);
|
&& a_node, FALSE);
|
||||||
|
|
||||||
node_pseudo_class = st_theme_node_get_pseudo_class (a_node);
|
node_pseudo_classes = st_theme_node_get_pseudo_classes (a_node);
|
||||||
|
|
||||||
if (node_pseudo_class == NULL)
|
return string_in_list (a_add_sel->content.pseudo->name->stryng,
|
||||||
return FALSE;
|
node_pseudo_classes);
|
||||||
|
|
||||||
return string_in_list (a_add_sel->content.pseudo->name->stryng, node_pseudo_class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -507,7 +497,7 @@ static gboolean
|
|||||||
class_add_sel_matches_style (CRAdditionalSel *a_add_sel,
|
class_add_sel_matches_style (CRAdditionalSel *a_add_sel,
|
||||||
StThemeNode *a_node)
|
StThemeNode *a_node)
|
||||||
{
|
{
|
||||||
const char *element_class;
|
GStrv element_classes;
|
||||||
|
|
||||||
g_return_val_if_fail (a_add_sel
|
g_return_val_if_fail (a_add_sel
|
||||||
&& a_add_sel->type == CLASS_ADD_SELECTOR
|
&& a_add_sel->type == CLASS_ADD_SELECTOR
|
||||||
@@ -516,11 +506,10 @@ class_add_sel_matches_style (CRAdditionalSel *a_add_sel,
|
|||||||
&& a_add_sel->content.class_name->stryng->str
|
&& a_add_sel->content.class_name->stryng->str
|
||||||
&& a_node, FALSE);
|
&& a_node, FALSE);
|
||||||
|
|
||||||
element_class = st_theme_node_get_element_class (a_node);
|
element_classes = st_theme_node_get_element_classes (a_node);
|
||||||
if (element_class == NULL)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
return string_in_list (a_add_sel->content.class_name->stryng, element_class);
|
return string_in_list (a_add_sel->content.class_name->stryng,
|
||||||
|
element_classes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -589,6 +589,8 @@ st_widget_get_theme_node (StWidget *widget)
|
|||||||
|
|
||||||
if (priv->theme_node == NULL)
|
if (priv->theme_node == NULL)
|
||||||
{
|
{
|
||||||
|
StThemeContext *context;
|
||||||
|
StThemeNode *tmp_node;
|
||||||
StThemeNode *parent_node = NULL;
|
StThemeNode *parent_node = NULL;
|
||||||
ClutterStage *stage = NULL;
|
ClutterStage *stage = NULL;
|
||||||
ClutterActor *parent;
|
ClutterActor *parent;
|
||||||
@@ -629,16 +631,20 @@ st_widget_get_theme_node (StWidget *widget)
|
|||||||
else
|
else
|
||||||
pseudo_class = direction_pseudo_class;
|
pseudo_class = direction_pseudo_class;
|
||||||
|
|
||||||
priv->theme_node = st_theme_node_new (st_theme_context_get_for_stage (stage),
|
context = st_theme_context_get_for_stage (stage);
|
||||||
parent_node, priv->theme,
|
tmp_node = st_theme_node_new (context, parent_node, priv->theme,
|
||||||
G_OBJECT_TYPE (widget),
|
G_OBJECT_TYPE (widget),
|
||||||
clutter_actor_get_name (CLUTTER_ACTOR (widget)),
|
clutter_actor_get_name (CLUTTER_ACTOR (widget)),
|
||||||
priv->style_class,
|
priv->style_class,
|
||||||
pseudo_class,
|
pseudo_class,
|
||||||
priv->inline_style);
|
priv->inline_style);
|
||||||
|
|
||||||
if (pseudo_class != direction_pseudo_class)
|
if (pseudo_class != direction_pseudo_class)
|
||||||
g_free (pseudo_class);
|
g_free (pseudo_class);
|
||||||
|
|
||||||
|
priv->theme_node = g_object_ref (st_theme_context_intern_node (context,
|
||||||
|
tmp_node));
|
||||||
|
g_object_unref (tmp_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
return priv->theme_node;
|
return priv->theme_node;
|
||||||
@@ -1526,6 +1532,12 @@ st_widget_recompute_style (StWidget *widget,
|
|||||||
int transition_duration;
|
int transition_duration;
|
||||||
gboolean paint_equal;
|
gboolean paint_equal;
|
||||||
|
|
||||||
|
if (new_theme_node == old_theme_node)
|
||||||
|
{
|
||||||
|
widget->priv->is_style_dirty = FALSE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!old_theme_node ||
|
if (!old_theme_node ||
|
||||||
!st_theme_node_geometry_equal (old_theme_node, new_theme_node))
|
!st_theme_node_geometry_equal (old_theme_node, new_theme_node))
|
||||||
clutter_actor_queue_relayout ((ClutterActor *) widget);
|
clutter_actor_queue_relayout ((ClutterActor *) widget);
|
||||||
|
@@ -47,7 +47,7 @@ on_stage_realized (ClutterActor *stage,
|
|||||||
gpointer data)
|
gpointer data)
|
||||||
{
|
{
|
||||||
recorder = shell_recorder_new (CLUTTER_STAGE (stage));
|
recorder = shell_recorder_new (CLUTTER_STAGE (stage));
|
||||||
shell_recorder_set_file_template (recorder, "test-recorder.ogg");
|
shell_recorder_set_file_template (recorder, "test-recorder.webm");
|
||||||
shell_recorder_record (recorder);
|
shell_recorder_record (recorder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user