Compare commits

..

1 Commits

Author SHA1 Message Date
Alexander Larsson
b1b0b6cfe8 gross hack to make things work with HiDPI gtk+
We temporatily set GDK_SCALE to 1 when initializing Gtk+ so that
we get the old non-hidpi behaviour.
2013-07-03 15:18:07 +02:00
32 changed files with 1285 additions and 1811 deletions

29
NEWS
View File

@@ -1,32 +1,3 @@
3.9.4
=====
* Fix chat entries not being focused when expanded [Jasper; #698778]
* Fix alignment of "Not Listed?" label [Mathieu; #702307]
* Fix alignment of time stamps in chat notifications [Carlos; #687809]
* Round the ends of slider trough [Jasper; #702825]
* Add support for "box-shadow: none" [Cosimo; #702782]
* Keep chrome below popup windows [Florian; #702338]
* Move the session list to a popup menu [Ray; #702818]
* Fix autorun notifications for "non-native" volumes [Matthias; #703418]
* dnd: Speed up by not picking on each motion event [Jasper; #703443]
* Fix management of asynchronous background loading [Lionel; #703001]
* Rework focus handling [Jasper; #700735]
* Optimize box-shadow rendering [Lionel; #689858]
* Remove support for fixed positioning in BoxLayouts [Florian; #703808]
* Misc bug fixes and cleanups [Adel, Jasper, Florian, Ray, Lionel, Emilio;
#702849, #610279, #703132, #703105, #703160, #703126, #703304, #703403,
#698593, #703442, #703565, #700901, #703874, #703807, #703893, #703909]
Contributors:
Mathieu Bridon, Giovanni Campagna, Cosimo Cecchi, Matthias Clasen,
Fran Diéguez, Adel Gadllah, Lionel Landwerlin, Florian Müllner,
Emilio Pozuelo Monfort, Carlos Soriano, Jasper St. Pierre, Ray Strode
Translations:
Baurzhan Muftakhidinov [kk], Marek Černocký [cs], Daniel Mustieles [es],
Fran Diéguez [gl], Kjartan Maraas [nb], Andika Triwidada [id],
Benjamin Steinwender [de], Nguyễn Thái Ngọc Duy [vi], Trần Ngọc Quân [vi]
3.9.3
=====
* Don't push window thumbs when workspace switcher is hidden [Jasper; #701167]

View File

@@ -1,5 +1,5 @@
AC_PREREQ(2.63)
AC_INIT([gnome-shell],[3.9.4],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
AC_INIT([gnome-shell],[3.9.3],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_SRCDIR([src/shell-global.c])
@@ -63,7 +63,7 @@ AM_CONDITIONAL(BUILD_RECORDER, $build_recorder)
CLUTTER_MIN_VERSION=1.13.4
GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1
GJS_MIN_VERSION=1.35.4
MUTTER_MIN_VERSION=3.9.4
MUTTER_MIN_VERSION=3.9.3
GTK_MIN_VERSION=3.7.9
GIO_MIN_VERSION=2.37.0
LIBECAL_MIN_VERSION=3.5.3

View File

@@ -327,6 +327,10 @@ StScrollBar StButton#vhandle:active {
border-width: 2px;
}
.app-view-control:focus {
padding: 3px;
}
.app-view-control:first-child:ltr:focus,
.app-view-control:last-child:rtl:focus {
border-right-width: 1px;
@@ -907,11 +911,6 @@ StScrollBar StButton#vhandle:active {
padding: 4px 32px;
}
.app-view-control:focus {
padding: 3px 31px;
}
.search-display > StBoxLayout,
.all-apps > StBoxLayout,
.frequent-apps > StBoxLayout {
@@ -1133,7 +1132,7 @@ StScrollBar StButton#vhandle:active {
padding: 4px;
}
.lg-extensions-list {
.lg-extension-list {
padding: 4px;
spacing: 6px;
}
@@ -1161,11 +1160,6 @@ StScrollBar StButton#vhandle:active {
/* Calendar popup */
#calendarArea {
/* this is the total width of the popup */
max-width: 720px;
}
.calendar-vertical-separator {
-stipple-width: 1px;
-stipple-color: #505050;

View File

@@ -504,8 +504,6 @@ const LoginDialog = new Lang.Class({
y_fill: false,
x_align: St.Align.START });
this._promptEntry.grab_key_focus();
this._promptMessage = new St.Label({ visible: false });
this._promptBox.add(this._promptMessage, { x_fill: true });
@@ -599,6 +597,10 @@ const LoginDialog = new Lang.Class({
_updateDisableUserList: function() {
let disableUserList = this._settings.get_boolean(GdmUtil.DISABLE_USER_LIST_KEY);
// If this is the first time around, set initial focus
if (this._disableUserList == undefined && disableUserList)
this.setInitialKeyFocus(this._promptEntry);
if (disableUserList != this._disableUserList) {
this._disableUserList = disableUserList;

View File

@@ -142,40 +142,33 @@ const BackgroundCache = new Lang.Class({
cancellable: null,
onFinished: null });
let fileLoad = { filename: params.filename,
style: params.style,
shouldCopy: false,
monitorIndex: params.monitorIndex,
effects: params.effects,
onFinished: params.onFinished,
cancellable: new Gio.Cancellable(), };
this._pendingFileLoads.push(fileLoad);
if (params.cancellable) {
params.cancellable.connect(Lang.bind(this, function(c) {
fileLoad.cancellable.cancel();
}));
for (let i = 0; i < this._pendingFileLoads.length; i++) {
if (this._pendingFileLoads[i].filename == params.filename &&
this._pendingFileLoads[i].style == params.style) {
this._pendingFileLoads[i].callers.push({ shouldCopy: true,
monitorIndex: params.monitorIndex,
effects: params.effects,
onFinished: params.onFinished });
return;
}
}
this._pendingFileLoads.push({ filename: params.filename,
style: params.style,
callers: [{ shouldCopy: false,
monitorIndex: params.monitorIndex,
effects: params.effects,
onFinished: params.onFinished }] });
let content = new Meta.Background({ meta_screen: global.screen,
monitor: params.monitorIndex,
effects: params.effects });
content.load_file_async(params.filename,
params.style,
fileLoad.cancellable,
params.cancellable,
Lang.bind(this,
function(object, result) {
if (fileLoad.cancellable.is_cancelled()) {
if (params.cancellable && params.cancellable.is_cancelled()) {
if (params.onFinished)
params.onFinished(null);
this._removePendingFileLoad(fileLoad);
return;
}
return;
}
try {
content.load_file_finish(result);
@@ -185,25 +178,22 @@ const BackgroundCache = new Lang.Class({
content = null;
}
let needsCopy = false;
for (let i = 0; i < this._pendingFileLoads.length; i++) {
let pendingLoad = this._pendingFileLoads[i];
if (pendingLoad.filename != params.filename ||
pendingLoad.style != params.style)
continue;
if (pendingLoad.cancellable.is_cancelled())
continue;
for (let j = 0; j < pendingLoad.callers.length; j++) {
if (pendingLoad.callers[j].onFinished) {
if (content && pendingLoad.callers[j].shouldCopy) {
content = object.copy(pendingLoad.callers[j].monitorIndex,
pendingLoad.callers[j].effects);
pendingLoad.cancellable.cancel();
if (pendingLoad.onFinished) {
if (content && needsCopy) {
content = object.copy(pendingLoad.monitorIndex,
pendingLoad.effects);
}
pendingLoad.callers[j].onFinished(content);
}
needsCopy = true;
pendingLoad.onFinished(content);
}
this._pendingFileLoads.splice(i, 1);
@@ -211,15 +201,6 @@ const BackgroundCache = new Lang.Class({
}));
},
_removePendingFileLoad: function(fileLoad) {
for (let i = 0; i < this._pendingFileLoads.length; i++) {
if (this._pendingFileLoads[i].cancellable == fileLoad.cancellable) {
this._pendingFileLoads.splice(i, 1);
break;
}
}
},
getImageContent: function(params) {
params = Params.parse(params, { monitorIndex: 0,
style: null,

View File

@@ -58,10 +58,14 @@ const CtrlAltTabManager = new Lang.Class({
},
focusGroup: function(item, timestamp) {
if (item.focusCallback)
if (item.focusCallback) {
item.focusCallback(timestamp);
else
} else {
if (global.stage_input_mode == Shell.StageInputMode.NORMAL)
global.set_stage_input_mode(Shell.StageInputMode.FOCUSED);
item.root.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
}
},
// Sort the items into a consistent order; panel first, tray last,
@@ -132,6 +136,8 @@ const CtrlAltTabManager = new Lang.Class({
},
_focusWindows: function(timestamp) {
global.set_stage_input_mode(Shell.StageInputMode.NORMAL);
global.stage.key_focus = null;
global.screen.focus_default_window(timestamp);
}
});

View File

@@ -32,9 +32,13 @@ const GrabHelper = new Lang.Class({
this._actors = [];
this._capturedEventId = 0;
this._keyFocusNotifyId = 0;
this._focusWindowChangedId = 0;
this._ignoreRelease = false;
this._isUngrabbingCount = 0;
this._modalCount = 0;
this._grabFocusCount = 0;
},
// addActor:
@@ -114,36 +118,38 @@ const GrabHelper = new Lang.Class({
// grab:
// @params: A bunch of parameters, see below
//
// The general effect of a "grab" is to ensure that the passed in actor
// and all actors inside the grab get exclusive control of the mouse and
// keyboard, with the grab automatically being dropped if the user tries
// to dismiss it. The actor is passed in through @params.actor.
// Grabs the mouse and keyboard, according to the GrabHelper's
// parameters. If @newFocus is not %null, then the keyboard focus
// is moved to the first #StWidget:can-focus widget inside it.
//
// grab() can be called multiple times, with the scope of the grab being
// changed to a different actor every time. A nested grab does not have
// to have its grabbed actor inside the parent grab actors.
// The grab will automatically be dropped if:
// - The user clicks outside the grabbed actors
// - The user types Escape
// - The keyboard focus is moved outside the grabbed actors
// - A window is focused
//
// Grabs can be automatically dropped if the user tries to dismiss it
// in one of two ways: the user clicking outside the currently grabbed
// actor, or the user typing the Escape key.
// If @params.actor is not null, then it will be focused as the
// new actor. If you attempt to grab an already focused actor, the
// request to be focused will be ignored. The actor will not be
// added to the grab stack, so do not call a paired ungrab().
//
// If the user clicks outside the grabbed actors, and the clicked on
// actor is part of a previous grab in the stack, grabs will be popped
// until that grab is active. However, the click event will not be
// replayed to the actor.
// If @params contains { modal: true }, then grab() will push a modal
// on the owner of the GrabHelper. As long as there is at least one
// { modal: true } actor on the grab stack, the grab will be kept.
// When the last { modal: true } actor is ungrabbed, then the modal
// will be dropped. A modal grab can fail if there is already a grab
// in effect from aother application; in this case the function returns
// false and nothing happens. Non-modal grabs can never fail.
//
// If the user types the Escape key, one grab from the grab stack will
// be popped.
//
// When a grab is popped by user interacting as described above, if you
// pass a callback as @params.onUngrab, it will be called with %true.
//
// If @params.focus is not null, we'll set the key focus directly
// to that actor instead of navigating in @params.actor. This is for
// use cases like menus, where we want to grab the menu actor, but keep
// focus on the clicked on menu item.
// If @params contains { grabFocus: true }, then if you call grab()
// while the shell is outside the overview, it will set the stage
// input mode to %Shell.StageInputMode.FOCUSED, and ungrab() will
// revert it back, and re-focus the previously-focused window (if
// another window hasn't been explicitly focused before then).
grab: function(params) {
params = Params.parse(params, { actor: null,
modal: false,
grabFocus: false,
focus: null,
onUngrab: null });
@@ -156,18 +162,24 @@ const GrabHelper = new Lang.Class({
params.savedFocus = focus;
if (!this._takeModalGrab())
if (params.modal && !this._takeModalGrab())
return false;
if (params.grabFocus && !this._takeFocusGrab(hadFocus))
return false;
this._grabStack.push(params);
if (params.focus) {
params.focus.grab_key_focus();
} else if (newFocus && hadFocus) {
} else if (newFocus && (hadFocus || params.grabFocus)) {
if (!newFocus.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false))
newFocus.grab_key_focus();
}
if ((params.grabFocus || params.modal) && !this._capturedEventId)
this._capturedEventId = global.stage.connect('captured-event', Lang.bind(this, this._onCapturedEvent));
return true;
},
@@ -176,8 +188,6 @@ const GrabHelper = new Lang.Class({
if (firstGrab) {
if (!Main.pushModal(this._owner, this._modalParams))
return false;
this._capturedEventId = global.stage.connect('captured-event', Lang.bind(this, this._onCapturedEvent));
}
this._modalCount++;
@@ -189,15 +199,56 @@ const GrabHelper = new Lang.Class({
if (this._modalCount > 0)
return;
global.stage.disconnect(this._capturedEventId);
this._capturedEventId = 0;
this._ignoreRelease = false;
Main.popModal(this._owner);
global.sync_pointer();
},
_takeFocusGrab: function(hadFocus) {
let firstGrab = (this._grabFocusCount == 0);
if (firstGrab) {
let metaDisplay = global.screen.get_display();
this._grabbedFromKeynav = hadFocus;
this._preGrabInputMode = global.stage_input_mode;
if (this._preGrabInputMode == Shell.StageInputMode.NORMAL)
global.set_stage_input_mode(Shell.StageInputMode.FOCUSED);
this._keyFocusNotifyId = global.stage.connect('notify::key-focus', Lang.bind(this, this._onKeyFocusChanged));
this._focusWindowChangedId = metaDisplay.connect('notify::focus-window', Lang.bind(this, this._focusWindowChanged));
}
this._grabFocusCount++;
return true;
},
_releaseFocusGrab: function() {
this._grabFocusCount--;
if (this._grabFocusCount > 0)
return;
if (this._keyFocusNotifyId > 0) {
global.stage.disconnect(this._keyFocusNotifyId);
this._keyFocusNotifyId = 0;
}
if (this._focusWindowChangedId > 0) {
let metaDisplay = global.screen.get_display();
metaDisplay.disconnect(this._focusWindowChangedId);
this._focusWindowChangedId = 0;
}
let prePopInputMode = global.stage_input_mode;
if (this._grabbedFromKeynav) {
if (this._preGrabInputMode == Shell.StageInputMode.FOCUSED &&
prePopInputMode != Shell.StageInputMode.FULLSCREEN)
global.set_stage_input_mode(Shell.StageInputMode.FOCUSED);
}
global.screen.focus_default_window(global.display.get_current_time_roundtrip());
},
// ignoreRelease:
//
// Make sure that the next button release event evaluated by the
@@ -211,14 +262,10 @@ const GrabHelper = new Lang.Class({
// ungrab:
// @params: The parameters for the grab; see below.
//
// Pops @params.actor from the grab stack, potentially dropping
// the grab. If the actor is not on the grab stack, this call is
// ignored with no ill effects.
// Pops an actor from the grab stack, potentially dropping the grab.
//
// If the actor is not at the top of the grab stack, grabs are
// popped until the grabbed actor is at the top of the grab stack.
// The onUngrab callback for every grab is called for every popped
// grab with the parameter %false.
// If the actor that was popped from the grab stack was not the actor
// That was passed in, this call is ignored.
ungrab: function(params) {
params = Params.parse(params, { actor: this.currentGrab.actor,
isUser: false });
@@ -227,6 +274,14 @@ const GrabHelper = new Lang.Class({
if (grabStackIndex < 0)
return;
// We may get key focus changes when calling onUngrab, which
// would cause an extra ungrab() on the next actor in the
// stack, which is wrong. Ignore key focus changes during the
// ungrab, and restore the saved key focus ourselves afterwards.
// We use a count as ungrab() may be re-entrant, as onUngrab()
// may ungrab additional actors.
this._isUngrabbingCount++;
let focus = global.stage.key_focus;
let hadFocus = focus && this._isWithinGrabbedActor(focus);
@@ -241,7 +296,18 @@ const GrabHelper = new Lang.Class({
if (poppedGrab.onUngrab)
poppedGrab.onUngrab(params.isUser);
this._releaseModalGrab();
if (poppedGrab.modal)
this._releaseModalGrab();
if (poppedGrab.grabFocus)
this._releaseFocusGrab();
}
if (!this.grabbed && this._capturedEventId > 0) {
global.stage.disconnect(this._capturedEventId);
this._capturedEventId = 0;
this._ignoreRelease = false;
}
if (hadFocus) {
@@ -249,6 +315,8 @@ const GrabHelper = new Lang.Class({
if (poppedGrab.savedFocus)
poppedGrab.savedFocus.grab_key_focus();
}
this._isUngrabbingCount--;
},
_onCapturedEvent: function(actor, event) {
@@ -269,6 +337,9 @@ const GrabHelper = new Lang.Class({
return true;
}
if (!button && this._modalCount == 0)
return false;
if (this._isWithinGrabbedActor(event.get_source()))
return false;
@@ -285,6 +356,21 @@ const GrabHelper = new Lang.Class({
return true;
}
return true;
return this._modalCount > 0;
},
_onKeyFocusChanged: function() {
if (this._isUngrabbingCount > 0)
return;
let focus = global.stage.key_focus;
if (!focus || !this._isWithinGrabbedActor(focus))
this.ungrab({ isUser: true });
},
_focusWindowChanged: function() {
let metaDisplay = global.screen.get_display();
if (metaDisplay.focus_window != null)
this.ungrab({ isUser: true });
}
});

View File

@@ -528,10 +528,17 @@ const LayoutManager = new Lang.Class({
get focusIndex() {
let i = Main.layoutManager.primaryIndex;
if (global.stage.key_focus != null)
i = this.findIndexForActor(global.stage.key_focus);
else if (global.display.focus_window != null)
i = global.display.focus_window.get_monitor();
if (global.stage_input_mode == Shell.StageInputMode.FOCUSED ||
global.stage_input_mode == Shell.StageInputMode.FULLSCREEN) {
let focusActor = global.stage.key_focus;
if (focusActor)
i = this.findIndexForActor(focusActor);
} else {
let focusWindow = global.display.focus_window;
if (focusWindow)
i = focusWindow.get_monitor();
}
return i;
},
@@ -589,13 +596,9 @@ const LayoutManager = new Lang.Class({
// screen. So, we set no_clear_hint at the end of the animation.
_prepareStartupAnimation: function() {
// During the initial transition, add a simple actor to block all events,
// so they don't get delivered to X11 windows that have been transformed.
this._coverPane = new Clutter.Actor({ opacity: 0,
width: global.screen_width,
height: global.screen_height,
reactive: true });
this.addChrome(this._coverPane);
// Set ourselves to FULLSCREEN input mode while the animation is running
// so events don't get delivered to X11 windows (which are distorted by the animation)
global.stage_input_mode = Shell.StageInputMode.FULLSCREEN;
if (Main.sessionMode.isGreeter) {
this.panelBox.translation_y = -this.panelBox.height;
@@ -665,8 +668,7 @@ const LayoutManager = new Lang.Class({
// we no longer need to clear the stage
global.stage.no_clear_hint = true;
this._coverPane.destroy();
this._coverPane = null;
global.stage_input_mode = Shell.StageInputMode.NORMAL;
this._systemBackground.actor.destroy();
this._systemBackground = null;

View File

@@ -849,9 +849,8 @@ const LookingGlass = new Lang.Class({
this._updateFont();
// We want it to appear to slide out from underneath the panel
Main.uiGroup.add_actor(this.actor);
Main.uiGroup.set_child_below_sibling(this.actor,
Main.layoutManager.panelBox);
Main.layoutManager.panelBox.add_actor(this.actor);
this.actor.lower_bottom();
Main.layoutManager.panelBox.connect('allocation-changed',
Lang.bind(this, this._queueResize));
Main.layoutManager.keyboardBox.connect('allocation-changed',
@@ -1073,7 +1072,7 @@ const LookingGlass = new Lang.Class({
let availableHeight = primary.height - Main.layoutManager.keyboardBox.height;
let myHeight = Math.min(primary.height * 0.7, availableHeight * 0.9);
this.actor.x = (primary.width - myWidth) / 2;
this._hiddenY = Main.layoutManager.panelBox.height - myHeight - 4; // -4 to hide the top corners
this._hiddenY = this.actor.get_parent().height - myHeight - 4; // -4 to hide the top corners
this._targetY = this._hiddenY + myHeight;
this.actor.y = this._hiddenY;
this.actor.width = myWidth;

View File

@@ -356,6 +356,8 @@ function pushModal(actor, params) {
Meta.disable_unredirect_for_screen(global.screen);
}
global.set_stage_input_mode(Shell.StageInputMode.FULLSCREEN);
modalCount += 1;
let actorDestroyId = actor.connect('destroy', function() {
let index = _findModal(actor);
@@ -404,6 +406,7 @@ function popModal(actor, timestamp) {
if (focusIndex < 0) {
global.stage.set_key_focus(null);
global.end_modal(timestamp);
global.set_stage_input_mode(Shell.StageInputMode.NORMAL);
keybindingMode = Shell.KeyBindingMode.NORMAL;
throw new Error('incorrect pop');
@@ -451,6 +454,7 @@ function popModal(actor, timestamp) {
return;
global.end_modal(timestamp);
global.set_stage_input_mode(Shell.StageInputMode.NORMAL);
Meta.enable_unredirect_for_screen(global.screen);
keybindingMode = Shell.KeyBindingMode.NORMAL;
}

View File

@@ -97,65 +97,6 @@ function _fixMarkup(text, allowMarkup) {
return GLib.markup_escape_text(text, -1);
}
const FocusGrabber = new Lang.Class({
Name: 'FocusGrabber',
_init: function(actor) {
this._actor = actor;
this._prevKeyFocusActor = null;
this._focusActorChangedId = 0;
this._focused = false;
},
grabFocus: function() {
if (this._focused)
return;
this._prevFocusedWindow = global.display.focus_window;
this._prevKeyFocusActor = global.stage.get_key_focus();
this._focusActorChangedId = global.stage.connect('notify::key-focus', Lang.bind(this, this._focusActorChanged));
if (!this._actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false))
this._actor.grab_key_focus();
this._focused = true;
},
_focusUngrabbed: function() {
if (!this._focused)
return false;
if (this._focusActorChangedId > 0) {
global.stage.disconnect(this._focusActorChangedId);
this._focusActorChangedId = 0;
}
this._focused = false;
return true;
},
_focusActorChanged: function() {
let focusedActor = global.stage.get_key_focus();
if (!focusedActor || !this._actor.contains(focusedActor))
this._focusUngrabbed();
},
ungrabFocus: function() {
if (!this._focusUngrabbed())
return;
if (this._prevKeyFocusActor) {
global.stage.set_key_focus(this._prevKeyFocusActor);
this._prevKeyFocusActor = null;
} else {
let focusedActor = global.stage.get_key_focus();
if (focusedActor && this._actor.contains(focusedActor))
global.stage.set_key_focus(null);
}
}
});
const URLHighlighter = new Lang.Class({
Name: 'URLHighlighter',
@@ -1633,7 +1574,6 @@ const MessageTray = new Lang.Class({
this._notificationBin.set_y_align(Clutter.ActorAlign.START);
this._notificationWidget.add_actor(this._notificationBin);
this._notificationWidget.hide();
this._notificationFocusGrabber = new FocusGrabber(this._notificationWidget);
this._notificationQueue = [];
this._notification = null;
this._notificationClickedId = 0;
@@ -1683,6 +1623,7 @@ const MessageTray = new Lang.Class({
{ keybindingMode: Shell.KeyBindingMode.MESSAGE_TRAY });
this._grabHelper.addActor(this._summaryBoxPointer.actor);
this._grabHelper.addActor(this.actor);
this._grabHelper.addActor(this._notificationWidget);
Main.layoutManager.connect('keyboard-visible-changed', Lang.bind(this, this._onKeyboardVisibleChanged));
@@ -1808,6 +1749,7 @@ const MessageTray = new Lang.Class({
let [x, y, mask] = global.get_pointer();
this._contextMenu.setPosition(Math.round(x), Math.round(y));
this._grabHelper.grab({ actor: this._contextMenu.actor,
modal: true,
onUngrab: Lang.bind(this, function () {
this._contextMenu.close(BoxPointer.PopupAnimation.FULL);
})
@@ -2374,6 +2316,7 @@ const MessageTray = new Lang.Class({
_showTray: function() {
if (!this._grabHelper.grab({ actor: this.actor,
modal: true,
onUngrab: Lang.bind(this, this._escapeTray) })) {
this._traySummoned = false;
return false;
@@ -2577,7 +2520,19 @@ const MessageTray = new Lang.Class({
},
_hideNotification: function() {
this._notificationFocusGrabber.ungrabFocus();
// 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 });
if (this._notificationExpandedId) {
this._notification.disconnect(this._notificationExpandedId);
@@ -2675,7 +2630,8 @@ const MessageTray = new Lang.Class({
},
_ensureNotificationFocused: function() {
this._notificationFocusGrabber.grabFocus();
this._grabHelper.grab({ actor: this._notification.actor,
grabFocus: true });
},
_onSourceDoneDisplayingContent: function(source, closeTray) {
@@ -2718,6 +2674,7 @@ const MessageTray = new Lang.Class({
this._summaryBoxPointer.bin.child = child;
this._grabHelper.grab({ actor: this._summaryBoxPointer.bin.child,
modal: true,
onUngrab: Lang.bind(this, this._onSummaryBoxPointerUngrabbed) });
this._summaryBoxPointer.actor.opacity = 0;

View File

@@ -79,8 +79,9 @@ const ModalDialog = new Lang.Class({
this.dialogLayout = new St.BoxLayout({ style_class: 'modal-dialog',
vertical: true });
if (params.styleClass != null)
if (params.styleClass != null) {
this.dialogLayout.add_style_class_name(params.styleClass);
}
if (!this._shellReactive) {
this._lightbox = new Lightbox.Lightbox(this._group,
@@ -356,9 +357,8 @@ const ModalDialog = new Lang.Class({
if (this._savedKeyFocus) {
this._savedKeyFocus.grab_key_focus();
this._savedKeyFocus = null;
} else {
} else
this._initialKeyFocus.grab_key_focus();
}
if (!this._shellReactive)
this._eventBlocker.lower_bottom();

View File

@@ -148,7 +148,7 @@ const Overview = new Lang.Class({
// Dash elements, or mouseover handlers in the workspaces.
this._coverPane = new Clutter.Actor({ opacity: 0,
reactive: true });
this._stack.add_actor(this._coverPane);
this._overview.add_actor(this._coverPane);
this._coverPane.connect('event', Lang.bind(this, function (actor, event) { return true; }));
this._stack.add_actor(this._overview);

View File

@@ -449,7 +449,7 @@ const AppMenuButton = new Lang.Class({
// If the app has just lost focus to the panel, pretend
// nothing happened; otherwise you can't keynav to the
// app menu.
if (global.stage.key_focus != null)
if (global.stage_input_mode == Shell.StageInputMode.FOCUSED)
return;
}
this._sync();

View File

@@ -1701,7 +1701,7 @@ const PopupMenuManager = new Lang.Class({
if (open) {
if (this.activeMenu && !this.activeMenu.isChildMenu(menu))
this.activeMenu.close(BoxPointer.PopupAnimation.FADE);
this._grabHelper.grab({ actor: menu.actor, focus: menu.sourceActor,
this._grabHelper.grab({ actor: menu.actor, modal: true, focus: menu.sourceActor,
onUngrab: Lang.bind(this, this._closeMenu, menu) });
} else {
this._grabHelper.ungrab({ actor: menu.actor });

View File

@@ -764,19 +764,6 @@ const ScreenShield = new Lang.Class({
}
}
if (this._lightbox.actor.visible ||
this._isActive) {
// We're either shown and active, or in the process of
// showing.
// The latter is a very unlikely condition (it requires
// idle-delay < 20), but in any case we have nothing
// to do at this point: either isActive is true, or
// it will soon be.
// isActive can also be true if the lightbox is hidden,
// in case the shield is down and the user hasn't unlocked yet
return;
}
if (!this._becomeModal()) {
// We could not become modal, so we can't activate the
// screenshield. The user is probably very upset at this
@@ -790,6 +777,19 @@ const ScreenShield = new Lang.Class({
return;
}
if (this._lightbox.actor.visible ||
this._isActive) {
// We're either shown and active, or in the process of
// showing.
// The latter is a very unlikely condition (it requires
// idle-delay < 20), but in any case we have nothing
// to do at this point: either isActive is true, or
// it will soon be.
// isActive can also be true if the lightbox is hidden,
// in case the shield is down and the user hasn't unlocked yet
return;
}
this._lightbox.show();
if (this._activationTime == 0)

View File

@@ -1528,7 +1528,7 @@ const NMApplet = new Lang.Class({
this._client.connect('notify::manager-running', Lang.bind(this, this._syncNMState));
this._client.connect('notify::networking-enabled', Lang.bind(this, this._syncNMState));
this._client.connect('notify::state', Lang.bind(this, this._syncNMState));
this._client.connect('notify::active-connections', Lang.bind(this, this._syncActiveConnections));
this._client.connect('notify::active-connections', Lang.bind(this, this._updateIcon));
this._client.connect('device-added', Lang.bind(this, this._deviceAdded));
this._client.connect('device-removed', Lang.bind(this, this._deviceRemoved));
this._settings.connect('new-connection', Lang.bind(this, this._newConnection));
@@ -1761,8 +1761,8 @@ const NMApplet = new Lang.Class({
let a = this._activeConnections[i];
if (!a._inited) {
a._notifyDefaultId = a.connect('notify::default', Lang.bind(this, this._syncActiveConnections));
a._notifyDefault6Id = a.connect('notify::default6', Lang.bind(this, this._syncActiveConnections));
a._notifyDefaultId = a.connect('notify::default', Lang.bind(this, this._updateIcon));
a._notifyDefault6Id = a.connect('notify::default6', Lang.bind(this, this._updateIcon));
a._notifyStateId = a.connect('notify::state', Lang.bind(this, this._notifyActivated));
a._inited = true;
@@ -1814,7 +1814,6 @@ const NMApplet = new Lang.Class({
if (this._mainConnection) {
let dev = this._mainConnection._primaryDevice;
this._mainConnectionIconChangedId = dev.connect('icon-changed', Lang.bind(this, this._updateIcon));
this._updateIcon();
}
},
@@ -1825,7 +1824,7 @@ const NMApplet = new Lang.Class({
activeConnection._primaryDevice._notification = null;
}
this._syncActiveConnections();
this._updateIcon();
},
_ignoreConnection: function(connection) {
@@ -1862,7 +1861,7 @@ const NMApplet = new Lang.Class({
_newConnection: function(settings, connection) {
this._addConnection(connection);
this._syncActiveConnections();
this._updateIcon();
},
_connectionRemoved: function(connection) {
@@ -1941,10 +1940,11 @@ const NMApplet = new Lang.Class({
}
this._showNormal();
this._syncActiveConnections();
this._updateIcon();
},
_updateIcon: function() {
this._syncActiveConnections();
let hasApIcon = false;
let hasMobileIcon = false;

344
po/de.po
View File

@@ -19,16 +19,16 @@ msgstr ""
"Project-Id-Version: gnome-shell master\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"shell&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2013-07-04 13:18+0000\n"
"PO-Revision-Date: 2013-07-02 06:35+0100\n"
"Last-Translator: Benjamin Steinwender <b@stbe.at>\n"
"POT-Creation-Date: 2013-05-31 22:35+0000\n"
"PO-Revision-Date: 2013-06-02 09:48+0100\n"
"Last-Translator: Christian Kirbach <christian.kirbach@gmail.com>\n"
"Language-Team: Deutsch <gnome-de@gnome.org>\n"
"Language: de_DE\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 1.5.5\n"
"X-Generator: Poedit 1.5.4\n"
#: ../data/50-gnome-shell-screenshot.xml.in.h:1
msgid "Screenshots"
@@ -387,41 +387,37 @@ msgstr "Erweiterung"
msgid "Select an extension to configure using the combobox above."
msgstr "Wählen Sie oben eine Erweiterung aus, die Sie konfigurieren wollen."
#: ../js/gdm/loginDialog.js:308
msgid "Choose Session"
msgstr "Sitzung wählen"
#: ../js/gdm/loginDialog.js:326
msgid "Session"
msgstr "Sitzung"
#: ../js/gdm/loginDialog.js:371
msgid "Session"
msgstr "Sitzung "
#. translators: this message is shown below the user list on the
#. login screen. It can be activated to reveal an entry for
#. manually entering the username.
#: ../js/gdm/loginDialog.js:528
#: ../js/gdm/loginDialog.js:601
msgid "Not listed?"
msgstr "Nicht aufgeführt?"
#: ../js/gdm/loginDialog.js:810 ../js/ui/components/networkAgent.js:137
#: ../js/gdm/loginDialog.js:776 ../js/ui/components/networkAgent.js:137
#: ../js/ui/components/polkitAgent.js:161 ../js/ui/endSessionDialog.js:376
#: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:399
#: ../js/ui/status/bluetooth.js:449 ../js/ui/unlockDialog.js:95
#: ../js/ui/userMenu.js:884
#: ../js/ui/status/bluetooth.js:415 ../js/ui/unlockDialog.js:96
#: ../js/ui/userMenu.js:938
msgid "Cancel"
msgstr "Abbrechen"
#: ../js/gdm/loginDialog.js:833
#: ../js/gdm/loginDialog.js:791
msgctxt "button"
msgid "Sign In"
msgstr "Anmelden"
#: ../js/gdm/loginDialog.js:833
#: ../js/gdm/loginDialog.js:791
msgid "Next"
msgstr "Nächstes"
#. Translators: this message is shown below the username entry field
#. to clue the user in on how to login to the local network realm
#: ../js/gdm/loginDialog.js:934
#: ../js/gdm/loginDialog.js:888
#, c-format
msgid "(e.g., user or %s)"
msgstr "(z.B. Benutzer oder %s)"
@@ -429,12 +425,12 @@ msgstr "(z.B. Benutzer oder %s)"
#. 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)
#: ../js/gdm/loginDialog.js:938 ../js/ui/components/networkAgent.js:260
#: ../js/gdm/loginDialog.js:892 ../js/ui/components/networkAgent.js:260
#: ../js/ui/components/networkAgent.js:278
msgid "Username: "
msgstr "Benutzername:"
#: ../js/gdm/loginDialog.js:1205
#: ../js/gdm/loginDialog.js:1158
msgid "Login Window"
msgstr "Anmeldefenster"
@@ -443,8 +439,8 @@ msgstr "Anmeldefenster"
msgid "Power"
msgstr "Ausschalten"
#: ../js/gdm/powerMenu.js:93 ../js/ui/userMenu.js:651 ../js/ui/userMenu.js:655
#: ../js/ui/userMenu.js:768
#: ../js/gdm/powerMenu.js:93 ../js/ui/userMenu.js:696 ../js/ui/userMenu.js:700
#: ../js/ui/userMenu.js:816
msgid "Suspend"
msgstr "Bereitschaft"
@@ -452,18 +448,18 @@ msgstr "Bereitschaft"
msgid "Restart"
msgstr "Neu starten"
#: ../js/gdm/powerMenu.js:103 ../js/ui/userMenu.js:653
#: ../js/ui/userMenu.js:655 ../js/ui/userMenu.js:767 ../js/ui/userMenu.js:888
#: ../js/gdm/powerMenu.js:103 ../js/ui/userMenu.js:698
#: ../js/ui/userMenu.js:700 ../js/ui/userMenu.js:815 ../js/ui/userMenu.js:942
msgid "Power Off"
msgstr "Ausschalten"
#: ../js/gdm/util.js:248
#: ../js/gdm/util.js:247
msgid "Authentication error"
msgstr "Legitimationsfehler"
#. Translators: this message is shown below the password entry field
#. to indicate the user can swipe their finger instead
#: ../js/gdm/util.js:365
#: ../js/gdm/util.js:364
msgid "(or swipe finger)"
msgstr "(oder benutzen Sie den Fingerabdruckleser)"
@@ -482,23 +478,23 @@ msgstr "Befehl konnte nicht verarbeitet werden:"
msgid "Execution of '%s' failed:"
msgstr "Ausführung von »%s« ist gescheitert:"
#: ../js/ui/appDisplay.js:397
#: ../js/ui/appDisplay.js:361
msgid "Frequent"
msgstr "Häufig"
#: ../js/ui/appDisplay.js:404
#: ../js/ui/appDisplay.js:368
msgid "All"
msgstr "Alle"
#: ../js/ui/appDisplay.js:996
#: ../js/ui/appDisplay.js:960
msgid "New Window"
msgstr "Neues Fenster"
#: ../js/ui/appDisplay.js:999 ../js/ui/dash.js:284
#: ../js/ui/appDisplay.js:963 ../js/ui/dash.js:284
msgid "Remove from Favorites"
msgstr "Aus Favoriten entfernen"
#: ../js/ui/appDisplay.js:1000
#: ../js/ui/appDisplay.js:964
msgid "Add to Favorites"
msgstr "Zu Favoriten hinzufügen"
@@ -512,7 +508,7 @@ msgstr "%s wurde zu Ihren Favoriten hinzugefügt"
msgid "%s has been removed from your favorites."
msgstr "%s wurde aus Ihren Favoriten entfernt"
#: ../js/ui/backgroundMenu.js:19 ../js/ui/userMenu.js:744
#: ../js/ui/backgroundMenu.js:19 ../js/ui/userMenu.js:789
msgid "Settings"
msgstr "Einstellungen"
@@ -640,35 +636,35 @@ msgid "S"
msgstr "Sa"
#. Translators: Text to show if there are no events
#: ../js/ui/calendar.js:750
#: ../js/ui/calendar.js:735
msgid "Nothing Scheduled"
msgstr "Nichts geplant"
#. Translators: Shown on calendar heading when selected day occurs on current year
#: ../js/ui/calendar.js:768
#: ../js/ui/calendar.js:751
msgctxt "calendar heading"
msgid "%A, %B %d"
msgstr "%A, %d. %B"
#. Translators: Shown on calendar heading when selected day occurs on different year
#: ../js/ui/calendar.js:771
#: ../js/ui/calendar.js:754
msgctxt "calendar heading"
msgid "%A, %B %d, %Y"
msgstr "%a, %d. %B %Y"
#: ../js/ui/calendar.js:782
#: ../js/ui/calendar.js:764
msgid "Today"
msgstr "Heute"
#: ../js/ui/calendar.js:786
#: ../js/ui/calendar.js:768
msgid "Tomorrow"
msgstr "Morgen"
#: ../js/ui/calendar.js:797
#: ../js/ui/calendar.js:779
msgid "This week"
msgstr "Diese Woche"
#: ../js/ui/calendar.js:805
#: ../js/ui/calendar.js:787
msgid "Next week"
msgstr "Nächste Woche"
@@ -857,14 +853,14 @@ msgstr "<b>%d</b>. <b>%B</b> <b>%Y</b>, <b>%H:%M</b> "
#. Translators: this is the other person changing their old IM name to their new
#. IM name.
#: ../js/ui/components/telepathyClient.js:986
#: ../js/ui/components/telepathyClient.js:985
#, c-format
msgid "%s is now known as %s"
msgstr "%s heißt jetzt %s"
#. translators: argument is a room name like
#. * room@jabber.org for example.
#: ../js/ui/components/telepathyClient.js:1089
#: ../js/ui/components/telepathyClient.js:1088
#, c-format
msgid "Invitation to %s"
msgstr "Einladung zum Betreten von %s"
@@ -872,38 +868,38 @@ msgstr "Einladung zum Betreten von %s"
#. translators: first argument is the name of a contact and the second
#. * one the name of a room. "Alice is inviting you to join room@jabber.org
#. * for example.
#: ../js/ui/components/telepathyClient.js:1097
#: ../js/ui/components/telepathyClient.js:1096
#, c-format
msgid "%s is inviting you to join %s"
msgstr "%s lädt Sie ein, %s beizutreten"
#: ../js/ui/components/telepathyClient.js:1099
#: ../js/ui/components/telepathyClient.js:1138
#: ../js/ui/components/telepathyClient.js:1178
#: ../js/ui/components/telepathyClient.js:1241
#: ../js/ui/components/telepathyClient.js:1098
#: ../js/ui/components/telepathyClient.js:1137
#: ../js/ui/components/telepathyClient.js:1177
#: ../js/ui/components/telepathyClient.js:1240
msgid "Decline"
msgstr "Ablehnen"
#: ../js/ui/components/telepathyClient.js:1100
#: ../js/ui/components/telepathyClient.js:1179
#: ../js/ui/components/telepathyClient.js:1242
#: ../js/ui/components/telepathyClient.js:1099
#: ../js/ui/components/telepathyClient.js:1178
#: ../js/ui/components/telepathyClient.js:1241
msgid "Accept"
msgstr "Annehmen"
#. translators: argument is a contact name like Alice for example.
#: ../js/ui/components/telepathyClient.js:1130
#: ../js/ui/components/telepathyClient.js:1129
#, c-format
msgid "Video call from %s"
msgstr "Video-Anruf von %s"
#. translators: argument is a contact name like Alice for example.
#: ../js/ui/components/telepathyClient.js:1133
#: ../js/ui/components/telepathyClient.js:1132
#, c-format
msgid "Call from %s"
msgstr "Anruf von %s"
#. translators: this is a button label (verb), not a noun
#: ../js/ui/components/telepathyClient.js:1140
#: ../js/ui/components/telepathyClient.js:1139
msgid "Answer"
msgstr "Antworten"
@@ -912,113 +908,113 @@ msgstr "Antworten"
#. * file name. The string will be something
#. * like: "Alice is sending you test.ogg"
#.
#: ../js/ui/components/telepathyClient.js:1172
#: ../js/ui/components/telepathyClient.js:1171
#, c-format
msgid "%s is sending you %s"
msgstr "%s sendet Ihnen %s"
#. To translators: The parameter is the contact's alias
#: ../js/ui/components/telepathyClient.js:1207
#: ../js/ui/components/telepathyClient.js:1206
#, c-format
msgid "%s would like permission to see when you are online"
msgstr "%s bittet um das Recht, Ihre Online-Verfügbarkeit sehen zu dürfen"
#: ../js/ui/components/telepathyClient.js:1299
#: ../js/ui/components/telepathyClient.js:1298
msgid "Network error"
msgstr "Netzwerkfehler"
#: ../js/ui/components/telepathyClient.js:1301
#: ../js/ui/components/telepathyClient.js:1300
msgid "Authentication failed"
msgstr "Legitimierung fehlgeschlagen"
#: ../js/ui/components/telepathyClient.js:1303
#: ../js/ui/components/telepathyClient.js:1302
msgid "Encryption error"
msgstr "Verschlüsselungsfehler"
#: ../js/ui/components/telepathyClient.js:1305
#: ../js/ui/components/telepathyClient.js:1304
msgid "Certificate not provided"
msgstr "Zertifikat wurde nicht bereitgestellt"
#: ../js/ui/components/telepathyClient.js:1307
#: ../js/ui/components/telepathyClient.js:1306
msgid "Certificate untrusted"
msgstr "Zertifikat nicht vertrauenswürdig"
#: ../js/ui/components/telepathyClient.js:1309
#: ../js/ui/components/telepathyClient.js:1308
msgid "Certificate expired"
msgstr "Zertifikat abgelaufen"
#: ../js/ui/components/telepathyClient.js:1311
#: ../js/ui/components/telepathyClient.js:1310
msgid "Certificate not activated"
msgstr "Zertifikat nicht aktiviert"
#: ../js/ui/components/telepathyClient.js:1313
#: ../js/ui/components/telepathyClient.js:1312
msgid "Certificate hostname mismatch"
msgstr "Rechnername des Zertifikats stimmt nicht überein"
#: ../js/ui/components/telepathyClient.js:1315
#: ../js/ui/components/telepathyClient.js:1314
msgid "Certificate fingerprint mismatch"
msgstr "Fingerabdruck des Zertifikats stimmt nicht überein"
#: ../js/ui/components/telepathyClient.js:1317
#: ../js/ui/components/telepathyClient.js:1316
msgid "Certificate self-signed"
msgstr "Selbstsigniertes Zertifikat"
#: ../js/ui/components/telepathyClient.js:1319
#: ../js/ui/components/telepathyClient.js:1318
msgid "Status is set to offline"
msgstr "Der Status ist auf »Abgemeldet« gesetzt"
#: ../js/ui/components/telepathyClient.js:1321
#: ../js/ui/components/telepathyClient.js:1320
msgid "Encryption is not available"
msgstr "Verschlüsselung ist nicht verfügbar"
#: ../js/ui/components/telepathyClient.js:1323
#: ../js/ui/components/telepathyClient.js:1322
msgid "Certificate is invalid"
msgstr "Zertifikat ist ungültig"
#: ../js/ui/components/telepathyClient.js:1325
#: ../js/ui/components/telepathyClient.js:1324
msgid "Connection has been refused"
msgstr "Verbindungsaufbau wurde verweigert"
#: ../js/ui/components/telepathyClient.js:1327
#: ../js/ui/components/telepathyClient.js:1326
msgid "Connection can't be established"
msgstr "Verbindung kann nicht hergestellt werden"
#: ../js/ui/components/telepathyClient.js:1329
#: ../js/ui/components/telepathyClient.js:1328
msgid "Connection has been lost"
msgstr "Verbindung wurde unterbrochen"
#: ../js/ui/components/telepathyClient.js:1331
#: ../js/ui/components/telepathyClient.js:1330
msgid "This account is already connected to the server"
msgstr "Dieses Konto ist bereits mit dem Server verbunden"
#: ../js/ui/components/telepathyClient.js:1333
#: ../js/ui/components/telepathyClient.js:1332
msgid ""
"Connection has been replaced by a new connection using the same resource"
msgstr ""
"Die Verbindung wurde durch eine neue Verbindung mit der gleichen Ressource "
"ersetzt"
#: ../js/ui/components/telepathyClient.js:1335
#: ../js/ui/components/telepathyClient.js:1334
msgid "The account already exists on the server"
msgstr "Dieses Konto ist bereits auf dem Server vorhanden"
#: ../js/ui/components/telepathyClient.js:1337
#: ../js/ui/components/telepathyClient.js:1336
msgid "Server is currently too busy to handle the connection"
msgstr ""
"Der Server ist derzeit überlastet und kann die Verbindung nicht annehmen"
#: ../js/ui/components/telepathyClient.js:1339
#: ../js/ui/components/telepathyClient.js:1338
msgid "Certificate has been revoked"
msgstr "Zertifikat wurde zurückgezogen"
#: ../js/ui/components/telepathyClient.js:1341
#: ../js/ui/components/telepathyClient.js:1340
msgid ""
"Certificate uses an insecure cipher algorithm or is cryptographically weak"
msgstr ""
"Das Zertifikat verwendet einen unsicheren Chiffrier-Algorithmus oder ist "
"kryptografisch schwach"
#: ../js/ui/components/telepathyClient.js:1343
#: ../js/ui/components/telepathyClient.js:1342
msgid ""
"The length of the server certificate, or the depth of the server certificate "
"chain, exceed the limits imposed by the cryptography library"
@@ -1027,22 +1023,22 @@ msgstr ""
"überschreiten die durch die kryptografische Bibliothek gegebenen "
"Beschränkungen"
#: ../js/ui/components/telepathyClient.js:1345
#: ../js/ui/components/telepathyClient.js:1344
msgid "Internal error"
msgstr "Interner Fehler"
#. translators: argument is the account name, like
#. * name@jabber.org for example.
#: ../js/ui/components/telepathyClient.js:1355
#: ../js/ui/components/telepathyClient.js:1354
#, c-format
msgid "Unable to connect to %s"
msgstr "Verbindung zu %s fehlgeschlagen"
#: ../js/ui/components/telepathyClient.js:1360
#: ../js/ui/components/telepathyClient.js:1359
msgid "View account"
msgstr "Konto anzeigen"
#: ../js/ui/components/telepathyClient.js:1399
#: ../js/ui/components/telepathyClient.js:1398
msgid "Unknown reason"
msgstr "Unbekannter Grund"
@@ -1057,26 +1053,26 @@ msgstr "Anwendungen anzeigen"
# Würde ich so übernehmen, oder evtl. »Dock«.
#. Translators: this is the name of the dock/favorites area on
#. the left of the overview
#: ../js/ui/dash.js:439
#: ../js/ui/dash.js:429
msgid "Dash"
msgstr "Dash"
#: ../js/ui/dateMenu.js:85
#: ../js/ui/dateMenu.js:86
msgid "Open Calendar"
msgstr "Kalender öffnen"
#: ../js/ui/dateMenu.js:89
#: ../js/ui/dateMenu.js:90
msgid "Open Clocks"
msgstr "Uhren öffnen"
#: ../js/ui/dateMenu.js:96
#: ../js/ui/dateMenu.js:97
msgid "Date & Time Settings"
msgstr "Einstellungen für Datum und Uhrzeit"
#. Translators: This is the date format to use when the calendar popup is
#. * shown - it is shown just below the time in the shell (e.g. "Tue 9:29 AM").
#.
#: ../js/ui/dateMenu.js:201
#: ../js/ui/dateMenu.js:208
msgid "%A %B %e, %Y"
msgstr "%A, %e. %B %Y"
@@ -1292,17 +1288,17 @@ msgstr "Übersicht"
msgid "Type to search…"
msgstr "Suchbegriff eingeben …"
#: ../js/ui/panel.js:567
#: ../js/ui/panel.js:642
msgid "Quit"
msgstr "Beenden"
#. Translators: If there is no suitable word for "Activities"
#. in your language, you can use the word for "Overview".
#: ../js/ui/panel.js:618
#: ../js/ui/panel.js:693
msgid "Activities"
msgstr "Aktivitäten"
#: ../js/ui/panel.js:914
#: ../js/ui/panel.js:989
msgid "Top Bar"
msgstr "Oberes Panel"
@@ -1311,7 +1307,7 @@ msgstr "Oberes Panel"
#. "ON" and "OFF") or "toggle-switch-intl" (for toggle
#. switches containing "◯" and "|"). Other values will
#. simply result in invisible toggle switches.
#: ../js/ui/popupMenu.js:549
#: ../js/ui/popupMenu.js:738
msgid "toggle-switch-us"
msgstr "toggle-switch-intl"
@@ -1339,7 +1335,7 @@ msgid_plural "%d new notifications"
msgstr[0] "%d neue Benachrichtigung"
msgstr[1] "%d neue Benachrichtigungen"
#: ../js/ui/screenShield.js:449 ../js/ui/userMenu.js:759
#: ../js/ui/screenShield.js:449 ../js/ui/userMenu.js:807
msgid "Lock"
msgstr "Sperren"
@@ -1354,11 +1350,11 @@ msgstr "GNOME muss den Bildschirm sperren"
#.
#. XXX: another option is to kick the user into the gdm login
#. screen, where we're not affected by grabs
#: ../js/ui/screenShield.js:788 ../js/ui/screenShield.js:1215
#: ../js/ui/screenShield.js:773 ../js/ui/screenShield.js:1213
msgid "Unable to lock"
msgstr "Sperrung fehlgeschlagen"
#: ../js/ui/screenShield.js:789 ../js/ui/screenShield.js:1216
#: ../js/ui/screenShield.js:774 ../js/ui/screenShield.js:1214
msgid "Lock was blocked by an application"
msgstr "Sperrung wurde von einer Anwendung blockiert"
@@ -1394,7 +1390,7 @@ msgstr "Passwort"
msgid "Remember Password"
msgstr "An Passwort erinnern"
#: ../js/ui/shellMountOperation.js:403 ../js/ui/unlockDialog.js:108
#: ../js/ui/shellMountOperation.js:403 ../js/ui/unlockDialog.js:109
msgid "Unlock"
msgstr "Entsperren"
@@ -1447,9 +1443,9 @@ msgid "Large Text"
msgstr "Große Schrift"
#: ../js/ui/status/bluetooth.js:28 ../js/ui/status/bluetooth.js:32
#: ../js/ui/status/bluetooth.js:290 ../js/ui/status/bluetooth.js:327
#: ../js/ui/status/bluetooth.js:355 ../js/ui/status/bluetooth.js:391
#: ../js/ui/status/bluetooth.js:422 ../js/ui/status/network.js:713
#: ../js/ui/status/bluetooth.js:289 ../js/ui/status/bluetooth.js:321
#: ../js/ui/status/bluetooth.js:357 ../js/ui/status/bluetooth.js:388
#: ../js/ui/status/network.js:739
msgid "Bluetooth"
msgstr "Bluetooth"
@@ -1470,82 +1466,73 @@ msgid "Bluetooth Settings"
msgstr "Bluetooth-Einstellungen"
#. TRANSLATORS: this means that bluetooth was disabled by hardware rfkill
#: ../js/ui/status/bluetooth.js:105 ../js/ui/status/network.js:140
#: ../js/ui/status/bluetooth.js:104 ../js/ui/status/network.js:142
msgid "hardware disabled"
msgstr "Hardware deaktiviert"
#: ../js/ui/status/bluetooth.js:198
#: ../js/ui/status/bluetooth.js:197
msgid "Connection"
msgstr "Verbindung"
#: ../js/ui/status/bluetooth.js:209 ../js/ui/status/network.js:399
#: ../js/ui/status/bluetooth.js:208 ../js/ui/status/network.js:404
msgid "disconnecting..."
msgstr "Verbindungsabbau …"
#: ../js/ui/status/bluetooth.js:222 ../js/ui/status/network.js:405
#: ../js/ui/status/network.js:1298
#: ../js/ui/status/bluetooth.js:221 ../js/ui/status/network.js:410
#: ../js/ui/status/network.js:1343
msgid "connecting..."
msgstr "Verbindungsaufbau …"
#: ../js/ui/status/bluetooth.js:240
#: ../js/ui/status/bluetooth.js:239
msgid "Send Files…"
msgstr "Dateien senden …"
#: ../js/ui/status/bluetooth.js:247
#: ../js/ui/status/bluetooth.js:246
msgid "Keyboard Settings"
msgstr "Tastatureinstellungen"
#: ../js/ui/status/bluetooth.js:250
#: ../js/ui/status/bluetooth.js:249
msgid "Mouse Settings"
msgstr "Maus-Einstellungen"
#: ../js/ui/status/bluetooth.js:255 ../js/ui/status/volume.js:313
#: ../js/ui/status/bluetooth.js:254 ../js/ui/status/volume.js:316
msgid "Sound Settings"
msgstr "Klangeinstellungen"
#: ../js/ui/status/bluetooth.js:328 ../js/ui/status/bluetooth.js:356
#: ../js/ui/status/bluetooth.js:322
#, c-format
msgid "Authorization request from %s"
msgstr "Legitimierungsanfrage von %s"
#: ../js/ui/status/bluetooth.js:334 ../js/ui/status/bluetooth.js:399
#: ../js/ui/status/bluetooth.js:430
#, c-format
msgid "Device %s wants to pair with this computer"
msgstr "Gerät »%s« möchte mit diesem Rechner gekoppelt werden"
#: ../js/ui/status/bluetooth.js:336
msgid "Allow"
msgstr "Erlauben"
#: ../js/ui/status/bluetooth.js:337
msgid "Deny"
msgstr "Verweigern"
#: ../js/ui/status/bluetooth.js:362
#: ../js/ui/status/bluetooth.js:328
#, c-format
msgid "Device %s wants access to the service '%s'"
msgstr "Gerät »%s« bittet um Zugriff auf den Dienst »%s«"
#: ../js/ui/status/bluetooth.js:364
#: ../js/ui/status/bluetooth.js:330
msgid "Always grant access"
msgstr "Immer Zugriff gewähren"
#: ../js/ui/status/bluetooth.js:365
#: ../js/ui/status/bluetooth.js:331
msgid "Grant this time only"
msgstr "Nur dieses Mal gewähren"
#: ../js/ui/status/bluetooth.js:366
#: ../js/ui/status/bluetooth.js:332
msgid "Reject"
msgstr "Abweisen"
#. Translators: argument is the device short name
#: ../js/ui/status/bluetooth.js:393
#: ../js/ui/status/bluetooth.js:359
#, c-format
msgid "Pairing confirmation for %s"
msgstr "Koppelungsbestätigung für %s"
#: ../js/ui/status/bluetooth.js:400
#: ../js/ui/status/bluetooth.js:365 ../js/ui/status/bluetooth.js:396
#, c-format
msgid "Device %s wants to pair with this computer"
msgstr "Gerät »%s« möchte mit diesem Rechner gekoppelt werden"
#: ../js/ui/status/bluetooth.js:366
#, c-format
msgid ""
"Please confirm whether the Passkey '%06d' matches the one on the device."
@@ -1553,24 +1540,24 @@ msgstr ""
"Bitte bestätigen Sie, ob die PIN »%06d« mit der des Gerätes übereinstimmt."
#. Translators: this is the verb, not the noun
#: ../js/ui/status/bluetooth.js:403
#: ../js/ui/status/bluetooth.js:369
msgid "Matches"
msgstr "Stimmt überein"
#: ../js/ui/status/bluetooth.js:404
#: ../js/ui/status/bluetooth.js:370
msgid "Does not match"
msgstr "Stimmt nicht überein"
#: ../js/ui/status/bluetooth.js:423
#: ../js/ui/status/bluetooth.js:389
#, c-format
msgid "Pairing request for %s"
msgstr "Koppelungsanfrage für %s"
#: ../js/ui/status/bluetooth.js:431
#: ../js/ui/status/bluetooth.js:397
msgid "Please enter the PIN mentioned on the device."
msgstr "Bitte geben Sie die auf dem Gerät angezeigte PIN ein."
#: ../js/ui/status/bluetooth.js:448
#: ../js/ui/status/bluetooth.js:414
msgid "OK"
msgstr "OK"
@@ -1590,81 +1577,87 @@ msgstr "Lautstärke, Netzwerk, Batterie"
msgid "<unknown>"
msgstr "<Unbekannt>"
#: ../js/ui/status/network.js:125
#: ../js/ui/status/network.js:127
msgid "Wi-Fi"
msgstr "WLAN"
#. Translators: this indicates that wireless or wwan is disabled by hardware killswitch
#: ../js/ui/status/network.js:162
#: ../js/ui/status/network.js:164
msgid "disabled"
msgstr "Deaktiviert"
#. Translators: this is for network devices that are physically present but are not
#. under NetworkManager's control (and thus cannot be used in the menu)
#: ../js/ui/status/network.js:397
#: ../js/ui/status/network.js:402
msgid "unmanaged"
msgstr "nicht verwaltet"
#. Translators: this is for network connections that require some kind of key or password
#: ../js/ui/status/network.js:408 ../js/ui/status/network.js:1301
#: ../js/ui/status/network.js:413 ../js/ui/status/network.js:1346
msgid "authentication required"
msgstr "Legitimierung erforderlich"
#. Translators: this is for devices that require some kind of firmware or kernel
#. module, which is missing
#: ../js/ui/status/network.js:419
#: ../js/ui/status/network.js:423
msgid "firmware missing"
msgstr "Firmware fehlt"
#. Translators: this is for wired network devices that are physically disconnected
#: ../js/ui/status/network.js:430
msgid "cable unplugged"
msgstr "Kabel nicht angeschlossen"
#. Translators: this is for a network device that cannot be activated (for example it
#. is disabled by rfkill, or it has no coverage
#: ../js/ui/status/network.js:423
#: ../js/ui/status/network.js:435
msgid "unavailable"
msgstr "nicht verfügbar"
#: ../js/ui/status/network.js:425 ../js/ui/status/network.js:1303
#: ../js/ui/status/network.js:437 ../js/ui/status/network.js:1348
msgid "connection failed"
msgstr "Verbindung gescheitert"
#: ../js/ui/status/network.js:478 ../js/ui/status/network.js:1190
#: ../js/ui/status/network.js:490 ../js/ui/status/network.js:1236
#: ../js/ui/status/network.js:1424
msgid "More…"
msgstr "Mehr …"
#. TRANSLATORS: this is the indication that a connection for another logged in user is active,
#. and we cannot access its settings (including the name)
#: ../js/ui/status/network.js:506 ../js/ui/status/network.js:1142
#: ../js/ui/status/network.js:518 ../js/ui/status/network.js:1191
msgid "Connected (private)"
msgstr "Verbunden (privat)"
#: ../js/ui/status/network.js:572
#: ../js/ui/status/network.js:597
msgid "Wired"
msgstr "Kabelgebunden"
#: ../js/ui/status/network.js:592
#: ../js/ui/status/network.js:611
msgid "Mobile broadband"
msgstr "Mobiles Breitband"
#: ../js/ui/status/network.js:1474
#: ../js/ui/status/network.js:1522
msgid "Enable networking"
msgstr "Netzwerk aktivieren"
#: ../js/ui/status/network.js:1522
#: ../js/ui/status/network.js:1583
msgid "Network Settings"
msgstr "Netzwerkeinstellungen"
#: ../js/ui/status/network.js:1539
#: ../js/ui/status/network.js:1600
msgid "Network Manager"
msgstr "Netzwerk-Verwaltung"
#: ../js/ui/status/network.js:1623
#: ../js/ui/status/network.js:1690
msgid "Connection failed"
msgstr "Verbindung gescheitert"
#: ../js/ui/status/network.js:1624
#: ../js/ui/status/network.js:1691
msgid "Activation of network connection failed"
msgstr "Aktivierung der Netzwerkverbindung ist gescheitert"
#: ../js/ui/status/network.js:1938
#: ../js/ui/status/network.js:2047
msgid "Networking is disabled"
msgstr "Netzwerk ist deaktiviert"
@@ -1765,72 +1758,72 @@ msgctxt "device"
msgid "Unknown"
msgstr "Unbekannt"
#: ../js/ui/status/volume.js:121
#: ../js/ui/status/volume.js:124
msgid "Volume changed"
msgstr "Lautstärke geändert"
#. Translators: This is the label for audio volume
#: ../js/ui/status/volume.js:246 ../js/ui/status/volume.js:294
#: ../js/ui/status/volume.js:249 ../js/ui/status/volume.js:297
msgid "Volume"
msgstr "Lautstärke"
#: ../js/ui/status/volume.js:255
#: ../js/ui/status/volume.js:258
msgid "Microphone"
msgstr "Mikrofon"
#: ../js/ui/unlockDialog.js:119
#: ../js/ui/unlockDialog.js:120
msgid "Log in as another user"
msgstr "Als anderer Benutzer anmelden"
#: ../js/ui/unlockDialog.js:140
#: ../js/ui/unlockDialog.js:141
msgid "Unlock Window"
msgstr "Fenster entsperren"
#: ../js/ui/userMenu.js:149
#: ../js/ui/userMenu.js:193
msgid "Available"
msgstr "Verfügbar"
#: ../js/ui/userMenu.js:152
#: ../js/ui/userMenu.js:196
msgid "Busy"
msgstr "Beschäftigt"
#: ../js/ui/userMenu.js:155
#: ../js/ui/userMenu.js:199
msgid "Invisible"
msgstr "Unsichtbar"
#: ../js/ui/userMenu.js:158
#: ../js/ui/userMenu.js:202
msgid "Away"
msgstr "Abwesend"
#: ../js/ui/userMenu.js:161
#: ../js/ui/userMenu.js:205
msgid "Idle"
msgstr "Untätig"
#: ../js/ui/userMenu.js:164
#: ../js/ui/userMenu.js:208
msgid "Offline"
msgstr "Abgemeldet"
#: ../js/ui/userMenu.js:736
#: ../js/ui/userMenu.js:781
msgid "Notifications"
msgstr "Benachrichtigungen"
#: ../js/ui/userMenu.js:749
#: ../js/ui/userMenu.js:797
msgid "Switch User"
msgstr "Benutzer wechseln"
#: ../js/ui/userMenu.js:754
#: ../js/ui/userMenu.js:802
msgid "Log Out"
msgstr "Abmelden"
#: ../js/ui/userMenu.js:774
#: ../js/ui/userMenu.js:822
msgid "Install Updates & Restart"
msgstr "Aktualisierungen installieren und neustarten"
#: ../js/ui/userMenu.js:792
#: ../js/ui/userMenu.js:840
msgid "Your chat status will be set to busy"
msgstr "Ihr Anwesenheitsstatus wird auf »Beschäftigt« gesetzt"
#: ../js/ui/userMenu.js:793
#: ../js/ui/userMenu.js:841
msgid ""
"Notifications are now disabled, including chat messages. Your online status "
"has been adjusted to let others know that you might not see their messages."
@@ -1839,22 +1832,22 @@ msgstr ""
"Ihr Anwesenheitsstatus wurde nun dahingehend geändert, dass andere darüber "
"informiert werden, dass Sie deren Nachrichten nicht sehen könnten."
#: ../js/ui/userMenu.js:834
#: ../js/ui/userMenu.js:888
msgid "Other users are logged in."
msgstr "Andere Benutzer sind angemeldet."
#: ../js/ui/userMenu.js:839
#: ../js/ui/userMenu.js:893
msgid "Shutting down might cause them to lose unsaved work."
msgstr "Herunterfahren könnte Datenverlust herbeiführen."
#. Translators: Remote here refers to a remote session, like a ssh login
#: ../js/ui/userMenu.js:867
#: ../js/ui/userMenu.js:921
#, c-format
msgid "%s (remote)"
msgstr "%s (Entfernt)"
#. Translators: Console here refers to a tty like a VT console
#: ../js/ui/userMenu.js:870
#: ../js/ui/userMenu.js:924
#, c-format
msgid "%s (console)"
msgstr "%s (Konsole)"
@@ -1912,20 +1905,20 @@ msgstr[1] "%u Eingänge"
msgid "System Sounds"
msgstr "Systemklänge"
#: ../src/main.c:353
#: ../src/main.c:372
msgid "Print version"
msgstr "Version ausgeben"
#: ../src/main.c:359
#: ../src/main.c:378
msgid "Mode used by GDM for login screen"
msgstr "Der durch GDM im Anmeldefenster verwendete Modus"
#: ../src/main.c:365
#: ../src/main.c:384
msgid "Use a specific mode, e.g. \"gdm\" for login screen"
msgstr ""
"Einen spezifischen Modus nutzen, wie z.B. »gdm« für den Anmeldebildschirm"
#: ../src/main.c:371
#: ../src/main.c:390
msgid "List possible modes"
msgstr "Die möglichen Modi auflisten"
@@ -1946,9 +1939,6 @@ msgstr "Das Passwort darf nicht leer sein"
msgid "Authentication dialog was dismissed by the user"
msgstr "Der Dialog zur Legitimierung wurde vom Benutzer geschlossen"
#~ msgid "cable unplugged"
#~ msgstr "Kabel nicht angeschlossen"
#~ msgid "Whether to collect stats about applications usage"
#~ msgstr ""
#~ "Legt fest, ob Statistiken über Anwendungsnutzung erfasst werden sollen"

588
po/id.po

File diff suppressed because it is too large Load Diff

132
po/nb.po
View File

@@ -8,8 +8,8 @@ msgid ""
msgstr ""
"Project-Id-Version: gnome-shell 3.9.x\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-07-04 11:09+0200\n"
"PO-Revision-Date: 2013-07-04 11:09+0200\n"
"POT-Creation-Date: 2013-06-17 12:28+0200\n"
"PO-Revision-Date: 2013-06-17 12:29+0200\n"
"Last-Translator: Kjartan Maraas <kmaraas@gnome.org>\n"
"Language-Team: Norwegian bokmål <i18n-nb@lister.ping.uio.no>\n"
"Language: \n"
@@ -331,22 +331,18 @@ msgstr "Utvidelse"
msgid "Select an extension to configure using the combobox above."
msgstr "Velg en utvidelse som skal konfigureres med komboboksen over."
#: ../js/gdm/loginDialog.js:308
msgid "Choose Session"
msgstr "Velg økt"
#: ../js/gdm/loginDialog.js:326
msgid "Session"
msgstr "Økt"
#: ../js/gdm/loginDialog.js:370
msgid "Session"
msgstr "Økt …"
#. translators: this message is shown below the user list on the
#. login screen. It can be activated to reveal an entry for
#. manually entering the username.
#: ../js/gdm/loginDialog.js:528
#: ../js/gdm/loginDialog.js:600
msgid "Not listed?"
msgstr "Ikke listet?"
#: ../js/gdm/loginDialog.js:810 ../js/ui/components/networkAgent.js:137
#: ../js/gdm/loginDialog.js:775 ../js/ui/components/networkAgent.js:137
#: ../js/ui/components/polkitAgent.js:161 ../js/ui/endSessionDialog.js:376
#: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:399
#: ../js/ui/status/bluetooth.js:449 ../js/ui/unlockDialog.js:95
@@ -354,18 +350,18 @@ msgstr "Ikke listet?"
msgid "Cancel"
msgstr "Avbryt"
#: ../js/gdm/loginDialog.js:833
#: ../js/gdm/loginDialog.js:790
msgctxt "button"
msgid "Sign In"
msgstr "Logg inn"
#: ../js/gdm/loginDialog.js:833
#: ../js/gdm/loginDialog.js:790
msgid "Next"
msgstr "Neste"
#. Translators: this message is shown below the username entry field
#. to clue the user in on how to login to the local network realm
#: ../js/gdm/loginDialog.js:934
#: ../js/gdm/loginDialog.js:887
#, c-format
msgid "(e.g., user or %s)"
msgstr "(f.eks. bruker eller %s)"
@@ -373,12 +369,12 @@ msgstr "(f.eks. bruker eller %s)"
#. 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)
#: ../js/gdm/loginDialog.js:938 ../js/ui/components/networkAgent.js:260
#: ../js/gdm/loginDialog.js:891 ../js/ui/components/networkAgent.js:260
#: ../js/ui/components/networkAgent.js:278
msgid "Username: "
msgstr "Brukernavn: "
#: ../js/gdm/loginDialog.js:1205
#: ../js/gdm/loginDialog.js:1157
msgid "Login Window"
msgstr "Innloggingsvindu"
@@ -401,13 +397,13 @@ msgstr "Start på nytt"
msgid "Power Off"
msgstr "Slå av"
#: ../js/gdm/util.js:248
#: ../js/gdm/util.js:247
msgid "Authentication error"
msgstr "Autentiseringsfeil"
#. Translators: this message is shown below the password entry field
#. to indicate the user can swipe their finger instead
#: ../js/gdm/util.js:365
#: ../js/gdm/util.js:364
msgid "(or swipe finger)"
msgstr "(eller dra finger)"
@@ -798,14 +794,14 @@ msgstr "<b>%d</b> <b>%B</b> <b>%Y</b>, <b>%H.%M</b> "
#. Translators: this is the other person changing their old IM name to their new
#. IM name.
#: ../js/ui/components/telepathyClient.js:986
#: ../js/ui/components/telepathyClient.js:985
#, c-format
msgid "%s is now known as %s"
msgstr "%s er nå kjent som %s"
#. translators: argument is a room name like
#. * room@jabber.org for example.
#: ../js/ui/components/telepathyClient.js:1089
#: ../js/ui/components/telepathyClient.js:1088
#, c-format
msgid "Invitation to %s"
msgstr "Invitasjon til %s"
@@ -813,38 +809,38 @@ msgstr "Invitasjon til %s"
#. translators: first argument is the name of a contact and the second
#. * one the name of a room. "Alice is inviting you to join room@jabber.org
#. * for example.
#: ../js/ui/components/telepathyClient.js:1097
#: ../js/ui/components/telepathyClient.js:1096
#, c-format
msgid "%s is inviting you to join %s"
msgstr "%s inviterer deg til å bli med i %s"
#: ../js/ui/components/telepathyClient.js:1099
#: ../js/ui/components/telepathyClient.js:1138
#: ../js/ui/components/telepathyClient.js:1178
#: ../js/ui/components/telepathyClient.js:1241
#: ../js/ui/components/telepathyClient.js:1098
#: ../js/ui/components/telepathyClient.js:1137
#: ../js/ui/components/telepathyClient.js:1177
#: ../js/ui/components/telepathyClient.js:1240
msgid "Decline"
msgstr "Avslå"
#: ../js/ui/components/telepathyClient.js:1100
#: ../js/ui/components/telepathyClient.js:1179
#: ../js/ui/components/telepathyClient.js:1242
#: ../js/ui/components/telepathyClient.js:1099
#: ../js/ui/components/telepathyClient.js:1178
#: ../js/ui/components/telepathyClient.js:1241
msgid "Accept"
msgstr "Godta"
#. translators: argument is a contact name like Alice for example.
#: ../js/ui/components/telepathyClient.js:1130
#: ../js/ui/components/telepathyClient.js:1129
#, c-format
msgid "Video call from %s"
msgstr "Videosamtale fra %s"
#. translators: argument is a contact name like Alice for example.
#: ../js/ui/components/telepathyClient.js:1133
#: ../js/ui/components/telepathyClient.js:1132
#, c-format
msgid "Call from %s"
msgstr "Samtale fra %s"
#. translators: this is a button label (verb), not a noun
#: ../js/ui/components/telepathyClient.js:1140
#: ../js/ui/components/telepathyClient.js:1139
msgid "Answer"
msgstr "Svar"
@@ -853,110 +849,110 @@ msgstr "Svar"
#. * file name. The string will be something
#. * like: "Alice is sending you test.ogg"
#.
#: ../js/ui/components/telepathyClient.js:1172
#: ../js/ui/components/telepathyClient.js:1171
#, c-format
msgid "%s is sending you %s"
msgstr "%s sender deg %s"
#. To translators: The parameter is the contact's alias
#: ../js/ui/components/telepathyClient.js:1207
#: ../js/ui/components/telepathyClient.js:1206
#, c-format
msgid "%s would like permission to see when you are online"
msgstr "%s vil ha rettigheter til å se når du er tilkoblet"
#: ../js/ui/components/telepathyClient.js:1299
#: ../js/ui/components/telepathyClient.js:1298
msgid "Network error"
msgstr "Nettverksfeil"
#: ../js/ui/components/telepathyClient.js:1301
#: ../js/ui/components/telepathyClient.js:1300
msgid "Authentication failed"
msgstr "Autentisering feilet"
#: ../js/ui/components/telepathyClient.js:1303
#: ../js/ui/components/telepathyClient.js:1302
msgid "Encryption error"
msgstr "Feil ved kryptering"
#: ../js/ui/components/telepathyClient.js:1305
#: ../js/ui/components/telepathyClient.js:1304
msgid "Certificate not provided"
msgstr "Sertifikat ikke oppgitt"
#: ../js/ui/components/telepathyClient.js:1307
#: ../js/ui/components/telepathyClient.js:1306
msgid "Certificate untrusted"
msgstr "Stoler ikke på sertifikatet"
#: ../js/ui/components/telepathyClient.js:1309
#: ../js/ui/components/telepathyClient.js:1308
msgid "Certificate expired"
msgstr "Sertifikatet er utløpt"
#: ../js/ui/components/telepathyClient.js:1311
#: ../js/ui/components/telepathyClient.js:1310
msgid "Certificate not activated"
msgstr "Sertifikatet er ikke aktivert"
#: ../js/ui/components/telepathyClient.js:1313
#: ../js/ui/components/telepathyClient.js:1312
msgid "Certificate hostname mismatch"
msgstr "Feil vertsnavn for sertifikat"
#: ../js/ui/components/telepathyClient.js:1315
#: ../js/ui/components/telepathyClient.js:1314
msgid "Certificate fingerprint mismatch"
msgstr "Feil fingeravtrykk for sertifikat"
#: ../js/ui/components/telepathyClient.js:1317
#: ../js/ui/components/telepathyClient.js:1316
msgid "Certificate self-signed"
msgstr "Sertifikatet er selvsignert"
#: ../js/ui/components/telepathyClient.js:1319
#: ../js/ui/components/telepathyClient.js:1318
msgid "Status is set to offline"
msgstr "Status er satt til frakoblet"
#: ../js/ui/components/telepathyClient.js:1321
#: ../js/ui/components/telepathyClient.js:1320
msgid "Encryption is not available"
msgstr "Kryptering er ikke tilgjengelig"
#: ../js/ui/components/telepathyClient.js:1323
#: ../js/ui/components/telepathyClient.js:1322
msgid "Certificate is invalid"
msgstr "Sertifikatet er ugyldig"
#: ../js/ui/components/telepathyClient.js:1325
#: ../js/ui/components/telepathyClient.js:1324
msgid "Connection has been refused"
msgstr "Tilkobling ble nektet"
#: ../js/ui/components/telepathyClient.js:1327
#: ../js/ui/components/telepathyClient.js:1326
msgid "Connection can't be established"
msgstr "Tilkobling kan ikke etableres"
#: ../js/ui/components/telepathyClient.js:1329
#: ../js/ui/components/telepathyClient.js:1328
msgid "Connection has been lost"
msgstr "Tilkobling tapt"
#: ../js/ui/components/telepathyClient.js:1331
#: ../js/ui/components/telepathyClient.js:1330
msgid "This account is already connected to the server"
msgstr "Denne kontoen er allerede koblet til tjeneren"
#: ../js/ui/components/telepathyClient.js:1333
#: ../js/ui/components/telepathyClient.js:1332
msgid ""
"Connection has been replaced by a new connection using the same resource"
msgstr ""
"Tilkoblingen har blitt erstattet av en ny tilkobling som bruker samme ressurs"
#: ../js/ui/components/telepathyClient.js:1335
#: ../js/ui/components/telepathyClient.js:1334
msgid "The account already exists on the server"
msgstr "Kontoen eksisterer allerede på tjeneren"
#: ../js/ui/components/telepathyClient.js:1337
#: ../js/ui/components/telepathyClient.js:1336
msgid "Server is currently too busy to handle the connection"
msgstr "Tjener er for opptatt til å håndtere tilkoblingen"
#: ../js/ui/components/telepathyClient.js:1339
#: ../js/ui/components/telepathyClient.js:1338
msgid "Certificate has been revoked"
msgstr "Sertifikatet er tilbaketrukket"
#: ../js/ui/components/telepathyClient.js:1341
#: ../js/ui/components/telepathyClient.js:1340
msgid ""
"Certificate uses an insecure cipher algorithm or is cryptographically weak"
msgstr ""
"Sertifikatet bruker en usikker sifferalgoritme eller er krytografisk svakt"
#: ../js/ui/components/telepathyClient.js:1343
#: ../js/ui/components/telepathyClient.js:1342
msgid ""
"The length of the server certificate, or the depth of the server certificate "
"chain, exceed the limits imposed by the cryptography library"
@@ -964,22 +960,22 @@ msgstr ""
"Lengden eller dybden på tjenersertifikatet oversteg grensen som er satt i "
"kryptografibiblioteket"
#: ../js/ui/components/telepathyClient.js:1345
#: ../js/ui/components/telepathyClient.js:1344
msgid "Internal error"
msgstr "Intern feil"
#. translators: argument is the account name, like
#. * name@jabber.org for example.
#: ../js/ui/components/telepathyClient.js:1355
#: ../js/ui/components/telepathyClient.js:1354
#, c-format
msgid "Unable to connect to %s"
msgstr "Kan ikke koble til %s"
#: ../js/ui/components/telepathyClient.js:1360
#: ../js/ui/components/telepathyClient.js:1359
msgid "View account"
msgstr "Vis konto"
#: ../js/ui/components/telepathyClient.js:1399
#: ../js/ui/components/telepathyClient.js:1398
msgid "Unknown reason"
msgstr "Ukjent årsak"
@@ -1012,7 +1008,7 @@ msgstr "Innstillinger for dato og klokkeslett"
#. Translators: This is the date format to use when the calendar popup is
#. * shown - it is shown just below the time in the shell (e.g. "Tue 9:29 AM").
#.
#: ../js/ui/dateMenu.js:201
#: ../js/ui/dateMenu.js:202
msgid "%A %B %e, %Y"
msgstr "%a %e %B, %Y"
@@ -1226,17 +1222,17 @@ msgstr "Oversikt"
msgid "Type to search…"
msgstr "Skriv for å søke …"
#: ../js/ui/panel.js:567
#: ../js/ui/panel.js:642
msgid "Quit"
msgstr "Avslutt"
#. Translators: If there is no suitable word for "Activities"
#. in your language, you can use the word for "Overview".
#: ../js/ui/panel.js:618
#: ../js/ui/panel.js:693
msgid "Activities"
msgstr "Aktiviteter"
#: ../js/ui/panel.js:914
#: ../js/ui/panel.js:989
msgid "Top Bar"
msgstr "Topp-panel"
@@ -1245,7 +1241,7 @@ msgstr "Topp-panel"
#. "ON" and "OFF") or "toggle-switch-intl" (for toggle
#. switches containing "◯" and "|"). Other values will
#. simply result in invisible toggle switches.
#: ../js/ui/popupMenu.js:549
#: ../js/ui/popupMenu.js:545
msgid "toggle-switch-us"
msgstr "toggle-switch-intl"
@@ -1285,11 +1281,11 @@ msgstr "GNOME må låse skjermen"
#.
#. XXX: another option is to kick the user into the gdm login
#. screen, where we're not affected by grabs
#: ../js/ui/screenShield.js:775 ../js/ui/screenShield.js:1215
#: ../js/ui/screenShield.js:773 ../js/ui/screenShield.js:1213
msgid "Unable to lock"
msgstr "Kan ikke låse"
#: ../js/ui/screenShield.js:776 ../js/ui/screenShield.js:1216
#: ../js/ui/screenShield.js:774 ../js/ui/screenShield.js:1214
msgid "Lock was blocked by an application"
msgstr "Låsing ble stoppet av et program"
@@ -1594,7 +1590,7 @@ msgstr "Tilkobling feilet"
msgid "Activation of network connection failed"
msgstr "Aktivering av nettverkstilkobling feilet"
#: ../js/ui/status/network.js:1938
#: ../js/ui/status/network.js:1937
msgid "Networking is disabled"
msgstr "Nettverk er slått av"

694
po/vi.po

File diff suppressed because it is too large Load Diff

View File

@@ -386,6 +386,8 @@ main (int argc, char **argv)
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
textdomain (GETTEXT_PACKAGE);
g_setenv ("GDK_SCALE", "1", TRUE);
ctx = meta_get_option_context ();
g_option_context_add_main_entries (ctx, gnome_shell_options, GETTEXT_PACKAGE);
if (!g_option_context_parse (ctx, &argc, &argv, &error))
@@ -435,6 +437,8 @@ main (int argc, char **argv)
_shell_global_init ("session-mode", session_mode, NULL);
g_unsetenv ("GDK_SCALE");
ecode = meta_run ();
if (g_getenv ("GNOME_SHELL_ENABLE_CLEANUP"))

View File

@@ -70,6 +70,7 @@ struct _ShellGlobal {
GtkWindow *grab_notifier;
gboolean gtk_grab_active;
ShellStageInputMode input_mode;
XserverRegion input_region;
GjsContext *js_context;
@@ -93,8 +94,6 @@ struct _ShellGlobal {
guint32 xdnd_timestamp;
gint64 last_gc_end_time;
gboolean has_modal;
};
enum {
@@ -107,6 +106,7 @@ enum {
PROP_SCREEN_WIDTH,
PROP_SCREEN_HEIGHT,
PROP_STAGE,
PROP_STAGE_INPUT_MODE,
PROP_WINDOW_GROUP,
PROP_TOP_WINDOW_GROUP,
PROP_WINDOW_MANAGER,
@@ -141,6 +141,9 @@ shell_global_set_property(GObject *object,
switch (prop_id)
{
case PROP_STAGE_INPUT_MODE:
shell_global_set_stage_input_mode (global, g_value_get_enum (value));
break;
case PROP_SESSION_MODE:
g_clear_pointer (&global->session_mode, g_free);
global->session_mode = g_ascii_strdown (g_value_get_string (value), -1);
@@ -192,6 +195,9 @@ shell_global_get_property(GObject *object,
case PROP_STAGE:
g_value_set_object (value, global->stage);
break;
case PROP_STAGE_INPUT_MODE:
g_value_set_enum (value, global->input_mode);
break;
case PROP_WINDOW_GROUP:
g_value_set_object (value, meta_get_window_group_for_screen (global->meta_screen));
break;
@@ -272,6 +278,8 @@ shell_global_init (ShellGlobal *global)
g_signal_connect (global->grab_notifier, "grab-notify", G_CALLBACK (grab_notify), global);
global->gtk_grab_active = FALSE;
global->input_mode = SHELL_STAGE_INPUT_MODE_NORMAL;
global->sound_context = ca_gtk_context_get ();
ca_context_change_props (global->sound_context,
CA_PROP_APPLICATION_NAME, "GNOME Shell",
@@ -409,6 +417,14 @@ shell_global_class_init (ShellGlobalClass *klass)
"Stage holding the desktop scene graph",
CLUTTER_TYPE_ACTOR,
G_PARAM_READABLE));
g_object_class_install_property (gobject_class,
PROP_STAGE_INPUT_MODE,
g_param_spec_enum ("stage-input-mode",
"Stage input mode",
"The stage input mode",
SHELL_TYPE_STAGE_INPUT_MODE,
SHELL_STAGE_INPUT_MODE_NORMAL,
G_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_WINDOW_GROUP,
g_param_spec_object ("window-group",
@@ -513,18 +529,6 @@ shell_global_get (void)
return the_object;
}
static guint32
get_current_time_maybe_roundtrip (ShellGlobal *global)
{
guint32 time;
time = shell_global_get_current_time (global);
if (time != CurrentTime)
return time;
return meta_display_get_current_time_roundtrip (global->meta_display);
}
static void
focus_window_changed (MetaDisplay *display,
GParamSpec *param,
@@ -532,71 +536,58 @@ focus_window_changed (MetaDisplay *display,
{
ShellGlobal *global = user_data;
if (global->has_modal)
return;
/* If the stage window became unfocused, drop the key focus
* on Clutter's side. */
if (!meta_stage_is_focused (global->meta_screen))
clutter_stage_set_key_focus (global->stage, NULL);
if (global->input_mode == SHELL_STAGE_INPUT_MODE_FOCUSED &&
meta_display_get_focus_window (display) != NULL)
shell_global_set_stage_input_mode (global, SHELL_STAGE_INPUT_MODE_NORMAL);
}
static ClutterActor *
get_key_focused_actor (ShellGlobal *global)
/**
* shell_global_set_stage_input_mode:
* @global: the #ShellGlobal
* @mode: the stage input mode
*
* Sets the input mode of the stage; when @mode is
* %SHELL_STAGE_INPUT_MODE_NORMAL, then the stage accepts clicks in
* the region defined by shell_global_set_stage_input_region() but
* passes through clicks outside that region. When it is
* %SHELL_STAGE_INPUT_MODE_FULLSCREEN, the stage absorbs all input.
*
* When the input mode is %SHELL_STAGE_INPUT_MODE_FOCUSED, the pointer
* is handled as with %SHELL_STAGE_INPUT_MODE_NORMAL, but additionally
* the stage window has the keyboard focus. If the stage loses the
* focus (eg, because the user clicked into a window) the input mode
* will revert to %SHELL_STAGE_INPUT_MODE_NORMAL.
*
* Note that whenever a mutter-internal Gtk widget has a pointer grab,
* the shell goes unresponsive and passes things to the underlying GTK+
* widget to ensure that the widget gets any clicks it is expecting.
*/
void
shell_global_set_stage_input_mode (ShellGlobal *global,
ShellStageInputMode mode)
{
ClutterActor *actor;
MetaScreen *screen;
actor = clutter_stage_get_key_focus (global->stage);
g_return_if_fail (SHELL_IS_GLOBAL (global));
/* If there's no explicit key focus, clutter_stage_get_key_focus()
* returns the stage. This is a terrible API. */
if (actor == CLUTTER_ACTOR (global->stage))
actor = NULL;
return actor;
}
static void
sync_stage_window_focus (ShellGlobal *global)
{
ClutterActor *actor;
if (global->has_modal)
return;
actor = get_key_focused_actor (global);
/* An actor got key focus and the stage needs to be focused. */
if (actor != NULL && !meta_stage_is_focused (global->meta_screen))
meta_focus_stage_window (global->meta_screen,
get_current_time_maybe_roundtrip (global));
/* An actor dropped key focus. Focus the default window. */
else if (actor == NULL && meta_stage_is_focused (global->meta_screen))
meta_screen_focus_default_window (global->meta_screen,
get_current_time_maybe_roundtrip (global));
}
static void
focus_actor_changed (ClutterStage *stage,
GParamSpec *param,
gpointer user_data)
{
ShellGlobal *global = user_data;
sync_stage_window_focus (global);
}
static void
sync_input_region (ShellGlobal *global)
{
MetaScreen *screen = global->meta_screen;
screen = meta_plugin_get_screen (global->plugin);
if (global->gtk_grab_active)
meta_empty_stage_input_region (screen);
else if (global->has_modal)
else if (mode == SHELL_STAGE_INPUT_MODE_FULLSCREEN || !global->input_region)
meta_set_stage_input_region (screen, None);
else
meta_set_stage_input_region (screen, global->input_region);
if (mode == SHELL_STAGE_INPUT_MODE_FOCUSED)
meta_focus_stage_window (global->meta_screen,
shell_global_get_current_time (global));
if (mode != global->input_mode)
{
global->input_mode = mode;
g_object_notify (G_OBJECT (global), "stage-input-mode");
}
}
/**
@@ -691,7 +682,8 @@ shell_global_unset_cursor (ShellGlobal *global)
* describing the input region.
*
* Sets the area of the stage that is responsive to mouse clicks when
* we don't have a modal or grab.
* the stage mode is %SHELL_STAGE_INPUT_MODE_NORMAL (but does not change the
* current stage mode).
*/
void
shell_global_set_stage_input_region (ShellGlobal *global,
@@ -721,7 +713,10 @@ shell_global_set_stage_input_region (ShellGlobal *global,
global->input_region = XFixesCreateRegion (global->xdisplay, rects, nrects);
g_free (rects);
sync_input_region (global);
/* set_stage_input_mode() will figure out whether or not we
* should actually change the input region right now.
*/
shell_global_set_stage_input_mode (global, global->input_mode);
}
/**
@@ -961,8 +956,6 @@ _shell_global_set_plugin (ShellGlobal *global,
"End of stage page repaint",
"");
g_signal_connect (global->stage, "notify::key-focus",
G_CALLBACK (focus_actor_changed), global);
g_signal_connect (global->meta_display, "notify::focus-window",
G_CALLBACK (focus_window_changed), global);
@@ -998,14 +991,7 @@ shell_global_begin_modal (ShellGlobal *global,
guint32 timestamp,
MetaModalOptions options)
{
/* Make it an error to call begin_modal while we already
* have a modal active. */
if (global->has_modal)
return FALSE;
global->has_modal = meta_plugin_begin_modal (global->plugin, global->stage_xwindow, None, options, timestamp);
sync_input_region (global);
return global->has_modal;
return meta_plugin_begin_modal (global->plugin, global->stage_xwindow, None, options, timestamp);
}
/**
@@ -1018,25 +1004,7 @@ void
shell_global_end_modal (ShellGlobal *global,
guint32 timestamp)
{
ClutterActor *actor;
if (!global->has_modal)
return;
meta_plugin_end_modal (global->plugin, timestamp);
global->has_modal = FALSE;
/* If the stage window is unfocused, ensure that there's no
* actor focused on Clutter's side. */
if (!meta_stage_is_focused (global->meta_screen))
clutter_stage_set_key_focus (global->stage, NULL);
/* An actor dropped key focus. Focus the default window. */
else if (get_key_focused_actor (global) && meta_stage_is_focused (global->meta_screen))
meta_screen_focus_default_window (global->meta_screen,
get_current_time_maybe_roundtrip (global));
sync_input_region (global);
}
void
@@ -1254,7 +1222,7 @@ grab_notify (GtkWidget *widget, gboolean was_grabbed, gpointer user_data)
global->gtk_grab_active = !was_grabbed;
/* Update for the new setting of gtk_grab_active */
sync_input_region (global);
shell_global_set_stage_input_mode (global, global->input_mode);
}
/**
@@ -1346,6 +1314,10 @@ shell_global_sync_pointer (ShellGlobal *global)
event.type = CLUTTER_MOTION;
event.time = shell_global_get_current_time (global);
event.flags = 0;
/* This is wrong: we should be setting event.stage to NULL if the
* pointer is not inside the bounds of the stage given the current
* stage_input_mode. For our current purposes however, this works.
*/
event.stage = global->stage;
event.x = x;
event.y = y;

View File

@@ -47,6 +47,14 @@ void shell_global_end_modal (ShellGlobal *global,
void shell_global_freeze_keyboard (ShellGlobal *global,
guint32 timestamp);
typedef enum {
SHELL_STAGE_INPUT_MODE_NORMAL,
SHELL_STAGE_INPUT_MODE_FOCUSED,
SHELL_STAGE_INPUT_MODE_FULLSCREEN
} ShellStageInputMode;
void shell_global_set_stage_input_mode (ShellGlobal *global,
ShellStageInputMode mode);
void shell_global_set_stage_input_region (ShellGlobal *global,
GSList *rectangles);

View File

@@ -285,6 +285,7 @@ get_content_preferred_width (StBoxLayout *self,
{
StBoxLayoutPrivate *priv = self->priv;
gint n_children = 0;
gint n_fixed = 0;
gfloat min_width, natural_width;
ClutterActor *child;
@@ -303,6 +304,12 @@ get_content_preferred_width (StBoxLayout *self,
n_children++;
if (clutter_actor_get_fixed_position_set (child))
{
n_fixed++;
continue;
}
if (priv->is_vertical)
{
_st_actor_get_preferred_width (child, -1, FALSE,
@@ -322,10 +329,10 @@ get_content_preferred_width (StBoxLayout *self,
}
}
if (!priv->is_vertical && n_children > 1)
if (!priv->is_vertical && (n_children - n_fixed) > 1)
{
min_width += priv->spacing * (n_children - 1);
natural_width += priv->spacing * (n_children - 1);
min_width += priv->spacing * (n_children - n_fixed - 1);
natural_width += priv->spacing * (n_children - n_fixed - 1);
}
if (min_width_p)
@@ -360,6 +367,7 @@ get_content_preferred_height (StBoxLayout *self,
{
StBoxLayoutPrivate *priv = self->priv;
gint n_children = 0;
gint n_fixed = 0;
gfloat min_height, natural_height;
ClutterActor *child;
@@ -378,6 +386,12 @@ get_content_preferred_height (StBoxLayout *self,
n_children++;
if (clutter_actor_get_fixed_position_set (child))
{
n_fixed++;
continue;
}
if (priv->is_vertical)
{
clutter_container_child_get ((ClutterContainer*) self, child,
@@ -402,10 +416,10 @@ get_content_preferred_height (StBoxLayout *self,
}
}
if (priv->is_vertical && n_children > 1)
if (priv->is_vertical && (n_children - n_fixed) > 1)
{
min_height += priv->spacing * (n_children - 1);
natural_height += priv->spacing * (n_children - 1);
min_height += priv->spacing * (n_children - n_fixed - 1);
natural_height += priv->spacing * (n_children - n_fixed - 1);
}
if (min_height_p)
@@ -497,9 +511,12 @@ compute_shrinks (StBoxLayout *self,
{
gfloat child_min, child_nat;
gboolean child_fill;
gboolean fixed;
fixed = clutter_actor_get_fixed_position_set (child);
shrinks[i].child_index = i;
if (CLUTTER_ACTOR_IS_VISIBLE (child))
if (CLUTTER_ACTOR_IS_VISIBLE (child) && !fixed)
{
if (priv->is_vertical)
{
@@ -721,13 +738,20 @@ st_box_layout_allocate (ClutterActor *actor,
{
ClutterActorBox child_box;
gfloat child_min, child_nat, child_allocated;
gboolean xfill, yfill, expand;
gboolean xfill, yfill, expand, fixed;
StAlign xalign, yalign;
gdouble xalign_f, yalign_f;
if (!CLUTTER_ACTOR_IS_VISIBLE (child))
goto next_child;
fixed = clutter_actor_get_fixed_position_set (child);
if (fixed)
{
clutter_actor_allocate_preferred_size (child, flags);
goto next_child;
}
clutter_container_child_get ((ClutterContainer*) actor, child,
"x-fill", &xfill,
"y-fill", &yfill,

View File

@@ -1268,7 +1268,8 @@ st_theme_node_prerender_background (StThemeNode *node,
return texture;
}
static void st_theme_node_paint_borders (StThemeNodePaintState *state,
static void st_theme_node_paint_borders (StThemeNode *node,
StThemeNodePaintState *state,
const ClutterActorBox *box,
guint8 paint_opacity);
@@ -1369,11 +1370,9 @@ st_theme_node_load_background_image (StThemeNode *node)
return node->background_texture != COGL_INVALID_HANDLE;
}
static void st_theme_node_prerender_shadow (StThemeNodePaintState *state);
static void
st_theme_node_render_resources (StThemeNodePaintState *state,
StThemeNode *node,
st_theme_node_render_resources (StThemeNode *node,
StThemeNodePaintState *state,
float width,
float height)
{
@@ -1391,7 +1390,6 @@ st_theme_node_render_resources (StThemeNodePaintState *state,
*/
st_theme_node_paint_state_free (state);
state->node = node;
state->alloc_width = width;
state->alloc_height = height;
@@ -1476,82 +1474,40 @@ st_theme_node_render_resources (StThemeNodePaintState *state,
state->box_shadow_material = _st_create_shadow_material (box_shadow_spec,
state->prerendered_texture);
else if (node->background_color.alpha > 0 || has_border)
st_theme_node_prerender_shadow (state);
}
/* If we don't have cached textures yet, check whether we can cache
them. */
if (!node->cached_textures)
{
if (state->prerendered_material == COGL_INVALID_HANDLE &&
width >= node->box_shadow_min_width &&
height >= node->box_shadow_min_height)
{
st_theme_node_paint_state_copy (&node->cached_state, state);
node->cached_textures = TRUE;
CoglHandle buffer, offscreen;
int texture_width = ceil (width);
int texture_height = ceil (height);
buffer = cogl_texture_new_with_size (texture_width,
texture_height,
COGL_TEXTURE_NO_SLICING,
COGL_PIXEL_FORMAT_ANY);
offscreen = cogl_offscreen_new_to_texture (buffer);
if (offscreen != COGL_INVALID_HANDLE)
{
ClutterActorBox box = { 0, 0, width, height };
CoglColor clear_color;
cogl_push_framebuffer (offscreen);
cogl_ortho (0, width, height, 0, 0, 1.0);
cogl_color_set_from_4ub (&clear_color, 0, 0, 0, 0);
cogl_clear (&clear_color, COGL_BUFFER_BIT_COLOR);
st_theme_node_paint_borders (node, state, &box, 0xFF);
cogl_pop_framebuffer ();
cogl_handle_unref (offscreen);
state->box_shadow_material = _st_create_shadow_material (box_shadow_spec,
buffer);
}
cogl_handle_unref (buffer);
}
}
}
static void
st_theme_node_update_resources (StThemeNodePaintState *state,
StThemeNode *node,
float width,
float height)
{
gboolean had_prerendered_texture = FALSE;
gboolean had_box_shadow = FALSE;
StShadow *box_shadow_spec;
g_return_if_fail (width > 0 && height > 0);
/* Free handles we can't reuse */
if (state->prerendered_texture != COGL_INVALID_HANDLE)
{
cogl_handle_unref (state->prerendered_texture);
state->prerendered_texture = COGL_INVALID_HANDLE;
had_prerendered_texture = TRUE;
}
if (state->prerendered_material != COGL_INVALID_HANDLE)
{
cogl_handle_unref (state->prerendered_material);
state->prerendered_material = COGL_INVALID_HANDLE;
if (node->border_slices_texture == COGL_INVALID_HANDLE &&
state->box_shadow_material != COGL_INVALID_HANDLE)
{
cogl_handle_unref (state->box_shadow_material);
state->box_shadow_material = COGL_INVALID_HANDLE;
had_box_shadow = TRUE;
}
}
state->node = node;
state->alloc_width = width;
state->alloc_height = height;
box_shadow_spec = st_theme_node_get_box_shadow (node);
if (had_prerendered_texture)
{
state->prerendered_texture = st_theme_node_prerender_background (node, width, height);
state->prerendered_material = _st_create_texture_material (state->prerendered_texture);
}
else
{
int corner_id;
for (corner_id = 0; corner_id < 4; corner_id++)
if (state->corner_material[corner_id] == COGL_INVALID_HANDLE)
state->corner_material[corner_id] =
st_theme_node_lookup_corner (node, width, height, corner_id);
}
if (had_box_shadow)
state->box_shadow_material = _st_create_shadow_material (box_shadow_spec,
state->prerendered_texture);
}
static void
paint_material_with_opacity (CoglHandle material,
ClutterActorBox *box,
@@ -1571,11 +1527,11 @@ paint_material_with_opacity (CoglHandle material,
}
static void
st_theme_node_paint_borders (StThemeNodePaintState *state,
st_theme_node_paint_borders (StThemeNode *node,
StThemeNodePaintState *state,
const ClutterActorBox *box,
guint8 paint_opacity)
{
StThemeNode *node = state->node;
float width, height;
int border_width[4];
guint border_radius[4];
@@ -1836,353 +1792,6 @@ st_theme_node_paint_borders (StThemeNodePaintState *state,
}
}
static void
st_theme_node_paint_sliced_shadow (StThemeNodePaintState *state,
const ClutterActorBox *box,
guint8 paint_opacity)
{
StThemeNode *node = state->node;
guint border_radius[4];
CoglColor color;
StShadow *box_shadow_spec;
gfloat xoffset, yoffset;
gfloat width, height;
gfloat shadow_width, shadow_height;
gfloat xend, yend, top, bottom, left, right;
gfloat s_top, s_bottom, s_left, s_right;
gfloat shadow_blur_radius, x_spread_factor, y_spread_factor;
float rectangles[8 * 9];
gint idx;
if (paint_opacity == 0)
return;
st_theme_node_reduce_border_radius (node, box->x2 - box->x1, box->y2 - box->y1, border_radius);
box_shadow_spec = st_theme_node_get_box_shadow (node);
/* Compute input & output areas :
*
* yoffset ----------------------------
* | | | |
* | | | |
* | | | |
* top ----------------------------
* | | | |
* | | | |
* | | | |
* bottom ----------------------------
* | | | |
* | | | |
* | | | |
* yend ----------------------------
* xoffset left right xend
*
* s_top = top in offscreen's coordinates (0.0 - 1.0)
* s_bottom = bottom in offscreen's coordinates (0.0 - 1.0)
* s_left = left in offscreen's coordinates (0.0 - 1.0)
* s_right = right in offscreen's coordinates (0.0 - 1.0)
*/
if (box_shadow_spec->blur == 0)
shadow_blur_radius = 0;
else
shadow_blur_radius = (5 * (box_shadow_spec->blur / 2.0)) / 2;
shadow_width = state->box_shadow_width + 2 * shadow_blur_radius;
shadow_height = state->box_shadow_height + 2 * shadow_blur_radius;
/* Compute input regions parameters */
s_top = shadow_blur_radius + box_shadow_spec->blur +
MAX (node->border_radius[ST_CORNER_TOPLEFT],
node->border_radius[ST_CORNER_TOPRIGHT]);
s_bottom = shadow_blur_radius + box_shadow_spec->blur +
MAX (node->border_radius[ST_CORNER_BOTTOMLEFT],
node->border_radius[ST_CORNER_BOTTOMRIGHT]);
s_left = shadow_blur_radius + box_shadow_spec->blur +
MAX (node->border_radius[ST_CORNER_TOPLEFT],
node->border_radius[ST_CORNER_BOTTOMLEFT]);
s_right = shadow_blur_radius + box_shadow_spec->blur +
MAX (node->border_radius[ST_CORNER_TOPRIGHT],
node->border_radius[ST_CORNER_BOTTOMRIGHT]);
/* Compute output regions parameters */
xoffset = box->x1 + box_shadow_spec->xoffset - shadow_blur_radius - box_shadow_spec->spread;
yoffset = box->y1 + box_shadow_spec->yoffset - shadow_blur_radius - box_shadow_spec->spread;
width = box->x2 - box->x1 + 2 * shadow_blur_radius;
height = box->y2 - box->y1 + 2 * shadow_blur_radius;
x_spread_factor = (width + 2 * box_shadow_spec->spread) / width;
y_spread_factor = (height + 2 * box_shadow_spec->spread) / height;
width += 2 * box_shadow_spec->spread;
height += 2 * box_shadow_spec->spread;
xend = xoffset + width;
yend = yoffset + height;
top = s_top * y_spread_factor;
bottom = s_bottom * y_spread_factor;
left = s_left * x_spread_factor;
right = s_right * x_spread_factor;
bottom = height - bottom;
right = width - right;
/* Final adjustments */
s_top /= shadow_height;
s_bottom /= shadow_height;
s_left /= shadow_width;
s_right /= shadow_width;
s_bottom = 1.0 - s_bottom;
s_right = 1.0 - s_right;
top += yoffset;
bottom += yoffset;
left += xoffset;
right += xoffset;
/* Setup pipeline */
cogl_color_set_from_4ub (&color,
box_shadow_spec->color.red * paint_opacity / 255,
box_shadow_spec->color.green * paint_opacity / 255,
box_shadow_spec->color.blue * paint_opacity / 255,
box_shadow_spec->color.alpha * paint_opacity / 255);
cogl_color_premultiply (&color);
cogl_material_set_layer_combine_constant (state->box_shadow_material, 0, &color);
cogl_set_source (state->box_shadow_material);
idx = 0;
if (top > 0)
{
if (left > 0)
{
/* Top left corner */
rectangles[idx++] = xoffset;
rectangles[idx++] = yoffset;
rectangles[idx++] = left;
rectangles[idx++] = top;
rectangles[idx++] = 0;
rectangles[idx++] = 0;
rectangles[idx++] = s_left;
rectangles[idx++] = s_top;
}
/* Top middle */
rectangles[idx++] = left;
rectangles[idx++] = yoffset;
rectangles[idx++] = right;
rectangles[idx++] = top;
rectangles[idx++] = s_left;
rectangles[idx++] = 0;
rectangles[idx++] = s_right;
rectangles[idx++] = s_top;
if (right > 0)
{
/* Top right corner */
rectangles[idx++] = right;
rectangles[idx++] = yoffset;
rectangles[idx++] = xend;
rectangles[idx++] = top;
rectangles[idx++] = s_right;
rectangles[idx++] = 0;
rectangles[idx++] = 1;
rectangles[idx++] = s_top;
}
}
if (left > 0)
{
/* Left middle */
rectangles[idx++] = xoffset;
rectangles[idx++] = top;
rectangles[idx++] = left;
rectangles[idx++] = bottom;
rectangles[idx++] = 0;
rectangles[idx++] = s_top;
rectangles[idx++] = s_left;
rectangles[idx++] = s_bottom;
}
/* Center middle */
rectangles[idx++] = left;
rectangles[idx++] = top;
rectangles[idx++] = right;
rectangles[idx++] = bottom;
rectangles[idx++] = s_left;
rectangles[idx++] = s_top;
rectangles[idx++] = s_right;
rectangles[idx++] = s_bottom;
if (right > 0)
{
/* Right middle */
rectangles[idx++] = right;
rectangles[idx++] = top;
rectangles[idx++] = xend;
rectangles[idx++] = bottom;
rectangles[idx++] = s_right;
rectangles[idx++] = s_top;
rectangles[idx++] = 1;
rectangles[idx++] = s_bottom;
}
if (bottom > 0)
{
if (left > 0)
{
/* Bottom left corner */
rectangles[idx++] = xoffset;
rectangles[idx++] = bottom;
rectangles[idx++] = left;
rectangles[idx++] = yend;
rectangles[idx++] = 0;
rectangles[idx++] = s_bottom;
rectangles[idx++] = s_left;
rectangles[idx++] = 1;
}
/* Bottom middle */
rectangles[idx++] = left;
rectangles[idx++] = bottom;
rectangles[idx++] = right;
rectangles[idx++] = yend;
rectangles[idx++] = s_left;
rectangles[idx++] = s_bottom;
rectangles[idx++] = s_right;
rectangles[idx++] = 1;
if (right > 0)
{
/* Bottom right corner */
rectangles[idx++] = right;
rectangles[idx++] = bottom;
rectangles[idx++] = xend;
rectangles[idx++] = yend;
rectangles[idx++] = s_right;
rectangles[idx++] = s_bottom;
rectangles[idx++] = 1;
rectangles[idx++] = 1;
}
}
cogl_rectangles_with_texture_coords (rectangles, idx / 8);
#if 0
/* Visual feedback on shadow's 9-slice and orignal offscreen buffer,
for debug purposes */
cogl_rectangle (xend, yoffset, xend + shadow_width, yoffset + shadow_height);
cogl_set_source_color4ub (0xff, 0x0, 0x0, 0xff);
cogl_rectangle (xoffset, top, xend, top + 1);
cogl_rectangle (xoffset, bottom, xend, bottom + 1);
cogl_rectangle (left, yoffset, left + 1, yend);
cogl_rectangle (right, yoffset, right + 1, yend);
cogl_rectangle (xend, yoffset, xend + shadow_width, yoffset + 1);
cogl_rectangle (xend, yoffset + shadow_height, xend + shadow_width, yoffset + shadow_height + 1);
cogl_rectangle (xend, yoffset, xend + 1, yoffset + shadow_height);
cogl_rectangle (xend + shadow_width, yoffset, xend + shadow_width + 1, yoffset + shadow_height);
s_top *= shadow_height;
s_bottom *= shadow_height;
s_left *= shadow_width;
s_right *= shadow_width;
cogl_rectangle (xend, yoffset + s_top, xend + shadow_width, yoffset + s_top + 1);
cogl_rectangle (xend, yoffset + s_bottom, xend + shadow_width, yoffset + s_bottom + 1);
cogl_rectangle (xend + s_left, yoffset, xend + s_left + 1, yoffset + shadow_height);
cogl_rectangle (xend + s_right, yoffset, xend + s_right + 1, yoffset + shadow_height);
#endif
}
static void
st_theme_node_prerender_shadow (StThemeNodePaintState *state)
{
StThemeNode *node = state->node;
guint border_radius[4];
int max_borders[4];
int center_radius, corner_id;
CoglHandle buffer, offscreen;
/* Get infos from the node */
if (state->alloc_width < node->box_shadow_min_width ||
state->alloc_height < node->box_shadow_min_height)
st_theme_node_reduce_border_radius (node, state->alloc_width, state->alloc_height, border_radius);
else
for (corner_id = 0; corner_id < 4; corner_id++)
border_radius[corner_id] = node->border_radius[corner_id];
/* Compute maximum borders sizes */
max_borders[ST_SIDE_TOP] = MAX (node->border_radius[ST_CORNER_TOPLEFT],
node->border_radius[ST_CORNER_TOPRIGHT]);
max_borders[ST_SIDE_BOTTOM] = MAX (node->border_radius[ST_CORNER_BOTTOMLEFT],
node->border_radius[ST_CORNER_BOTTOMRIGHT]);
max_borders[ST_SIDE_LEFT] = MAX (node->border_radius[ST_CORNER_TOPLEFT],
node->border_radius[ST_CORNER_BOTTOMLEFT]);
max_borders[ST_SIDE_RIGHT] = MAX (node->border_radius[ST_CORNER_TOPRIGHT],
node->border_radius[ST_CORNER_BOTTOMRIGHT]);
center_radius = (node->box_shadow->blur > 0) ? (2 * node->box_shadow->blur + 1) : 1;
node->box_shadow_min_width = max_borders[ST_SIDE_LEFT] + max_borders[ST_SIDE_RIGHT] + center_radius;
node->box_shadow_min_height = max_borders[ST_SIDE_TOP] + max_borders[ST_SIDE_BOTTOM] + center_radius;
if (state->alloc_width < node->box_shadow_min_width ||
state->alloc_height < node->box_shadow_min_height)
{
state->box_shadow_width = state->alloc_width;
state->box_shadow_height = state->alloc_height;
}
else
{
state->box_shadow_width = node->box_shadow_min_width;
state->box_shadow_height = node->box_shadow_min_height;
}
/* Render offscreen */
buffer = cogl_texture_new_with_size (state->box_shadow_width,
state->box_shadow_height,
COGL_TEXTURE_NO_SLICING,
COGL_PIXEL_FORMAT_ANY);
offscreen = cogl_offscreen_new_to_texture (buffer);
if (offscreen != COGL_INVALID_HANDLE)
{
ClutterActorBox box = { 0, 0, state->box_shadow_width, state->box_shadow_height};
CoglColor clear_color;
cogl_push_framebuffer (offscreen);
cogl_ortho (0, state->box_shadow_width, state->box_shadow_height, 0, 0, 1.0);
cogl_color_set_from_4ub (&clear_color, 0, 0, 0, 0);
cogl_clear (&clear_color, COGL_BUFFER_BIT_COLOR);
st_theme_node_paint_borders (state, &box, 0xFF);
cogl_pop_framebuffer ();
cogl_handle_unref (offscreen);
state->box_shadow_material = _st_create_shadow_material (st_theme_node_get_box_shadow (node),
buffer);
}
cogl_handle_unref (buffer);
}
static void
st_theme_node_paint_sliced_border_image (StThemeNode *node,
float width,
@@ -2336,43 +1945,6 @@ st_theme_node_paint_outline (StThemeNode *node,
cogl_rectangles (rects, 4);
}
static gboolean
st_theme_node_needs_new_box_shadow_for_size (StThemeNodePaintState *state,
StThemeNode *node,
float width,
float height)
{
if (!node->rendered_once)
return TRUE;
/* The allocation hasn't changed, no need to recompute a new
box-shadow. */
if (state->alloc_width == width ||
state->alloc_height == height)
return FALSE;
/* If there is no shadow, no need to recompute a new box-shadow. */
if (node->box_shadow_min_width == 0 ||
node->box_shadow_min_height == 0)
return FALSE;
/* If the new size is inferior to the box-shadow minimum size (we
already know the size has changed), we need to recompute the
box-shadow. */
if (width < node->box_shadow_min_width ||
height < node->box_shadow_min_height)
return TRUE;
/* Now checking whether the size of the node has crossed the minimum
box-shadow size boundary, from below to above the minimum size .
If that's the case, we need to recompute the box-shadow */
if (state->alloc_width < node->box_shadow_min_width ||
state->alloc_height < node->box_shadow_min_height)
return TRUE;
return FALSE;
}
void
st_theme_node_paint (StThemeNode *node,
StThemeNodePaintState *state,
@@ -2392,22 +1964,11 @@ st_theme_node_paint (StThemeNode *node,
if (width <= 0 || height <= 0)
return;
if (st_theme_node_needs_new_box_shadow_for_size (state, node, width, height))
if (state->alloc_width != width || state->alloc_height != height)
{
/* If we had the ability to cache textures on the node, then we
can just copy them over to the paint state and avoid all
rendering. We end up sharing textures a cross different
widgets. */
if (node->rendered_once && node->cached_textures &&
width >= node->box_shadow_min_width && height >= node->box_shadow_min_height)
st_theme_node_paint_state_copy (state, &node->cached_state);
else
st_theme_node_render_resources (state, node, width, height);
node->rendered_once = TRUE;
state->node = node;
st_theme_node_render_resources (node, state, width, height);
}
else if (state->alloc_width != width || state->alloc_height != height)
st_theme_node_update_resources (state, node, width, height);
/* Rough notes about the relationship of borders and backgrounds in CSS3;
* see http://www.w3.org/TR/css3-background/ for more accurate details.
@@ -2436,18 +1997,10 @@ st_theme_node_paint (StThemeNode *node,
*/
if (state->box_shadow_material)
{
if (state->alloc_width < node->box_shadow_min_width ||
state->alloc_height < node->box_shadow_min_height)
_st_paint_shadow_with_opacity (node->box_shadow,
state->box_shadow_material,
&allocation,
paint_opacity);
else
st_theme_node_paint_sliced_shadow (state,
&allocation,
paint_opacity);
}
_st_paint_shadow_with_opacity (node->box_shadow,
state->box_shadow_material,
&allocation,
paint_opacity);
if (state->prerendered_material != COGL_INVALID_HANDLE ||
st_theme_node_load_border_image (node))
@@ -2471,7 +2024,7 @@ st_theme_node_paint (StThemeNode *node,
}
else
{
st_theme_node_paint_borders (state, box, paint_opacity);
st_theme_node_paint_borders (node, state, box, paint_opacity);
}
st_theme_node_paint_outline (node, box, paint_opacity);
@@ -2571,8 +2124,6 @@ st_theme_node_paint_state_copy (StThemeNodePaintState *state,
state->alloc_width = other->alloc_width;
state->alloc_height = other->alloc_height;
state->box_shadow_width = other->box_shadow_width;
state->box_shadow_height = other->box_shadow_height;
if (other->box_shadow_material)
state->box_shadow_material = cogl_handle_ref (other->box_shadow_material);

View File

@@ -99,19 +99,12 @@ struct _StThemeNode {
guint background_image_shadow_computed : 1;
guint text_shadow_computed : 1;
guint link_type : 2;
guint rendered_once : 1;
guint cached_textures : 1;
int box_shadow_min_width;
int box_shadow_min_height;
CoglHandle border_slices_texture;
CoglHandle border_slices_material;
CoglHandle background_texture;
CoglHandle background_material;
CoglHandle background_shadow_material;
StThemeNodePaintState cached_state;
};
struct _StThemeNodeClass {

View File

@@ -54,8 +54,6 @@ st_theme_node_init (StThemeNode *node)
node->background_shadow_material = COGL_INVALID_HANDLE;
node->border_slices_texture = COGL_INVALID_HANDLE;
node->border_slices_material = COGL_INVALID_HANDLE;
st_theme_node_paint_state_init (&node->cached_state);
}
static void
@@ -103,8 +101,6 @@ st_theme_node_dispose (GObject *gobject)
g_signal_handlers_disconnect_by_func (node->theme,
on_custom_stylesheets_changed, node);
st_theme_node_paint_state_free (&node->cached_state);
g_clear_object (&node->theme);
G_OBJECT_CLASS (st_theme_node_parent_class)->dispose (gobject);

View File

@@ -102,9 +102,6 @@ struct _StThemeNodePaintState {
float alloc_width;
float alloc_height;
float box_shadow_width;
float box_shadow_height;
CoglHandle box_shadow_material;
CoglHandle prerendered_texture;
CoglHandle prerendered_material;

View File

@@ -8,7 +8,6 @@ TEST_JS = \
interactive/border-radius.js \
interactive/border-width.js \
interactive/box-layout.js \
interactive/box-shadow-animated.js \
interactive/box-shadows.js \
interactive/calendar.js \
interactive/css-fonts.js \

View File

@@ -45,6 +45,12 @@ function test() {
style: 'border: 1px solid #aaaaaa; '
+ 'background: #cceeff' }));
b2.add(new St.Label({ x: 50,
y: 50,
text: "Fixed",
style: 'border: 1px solid #aaaaaa;'
+ 'background: #ffffcc' }));
////////////////////////////////////////////////////////////////////////////////
function createCollapsableBox(width) {

View File

@@ -1,84 +0,0 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const St = imports.gi.St;
const Mainloop = imports.mainloop;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
const UI = imports.testcommon.ui;
const DELAY = 2000;
function resize_animated(label) {
if (label.width == 100) {
label.save_easing_state();
label.set_easing_mode(Clutter.AnimationMode.EASE_OUT_QUAD);
label.set_easing_duration(DELAY - 50);
label.set_size(500, 500);
label.restore_easing_state();
} else {
label.save_easing_state();
label.set_easing_mode(Clutter.AnimationMode.EASE_OUT_QUAD);
label.set_easing_duration(DELAY - 50);
label.set_size(100, 100);
label.restore_easing_state();
}
}
function get_css_style(shadow_style)
{
return 'border: 20px solid black;' +
'border-radius: 20px;' +
'background-color: white; ' +
'padding: 5px;' + shadow_style;
}
function test() {
let stage = new Clutter.Stage({ width: 1000, height: 600 });
UI.init(stage);
let iter = 0;
let shadowStyles = [ 'box-shadow: 3px 50px 0px 4px rgba(0,0,0,0.5);',
'box-shadow: 3px 4px 10px 4px rgba(0,0,0,0.5);',
'box-shadow: 0px 50px 0px 0px rgba(0,0,0,0.5);',
'box-shadow: 100px 100px 20px 4px rgba(0,0,0,0.5);'];
let label1 = new St.Label({ style: get_css_style(shadowStyles[iter]),
text: shadowStyles[iter],
x: 20,
y: 20,
width: 100,
height: 100
});
stage.add_actor(label1);
let label2 = new St.Label({ style: get_css_style(shadowStyles[iter]),
text: shadowStyles[iter],
x: 500,
y: 20,
width: 100,
height: 100
});
stage.add_actor(label2);
resize_animated(label1);
resize_animated(label2);
Mainloop.timeout_add(DELAY, Lang.bind(this, function() {
log(label1 + label1.get_size());
resize_animated(label1);
resize_animated(label2);
return true;
}));
Mainloop.timeout_add(2 * DELAY, Lang.bind(this, function() {
iter += 1;
iter %= shadowStyles.length;
label1.set_style(get_css_style(shadowStyles[iter]));
label1.set_text(shadowStyles[iter]);
label2.set_style(get_css_style(shadowStyles[iter]));
label2.set_text(shadowStyles[iter]);
return true;
}));
UI.main(stage);
}
test();