Compare commits

..

20 Commits

Author SHA1 Message Date
Jasper St. Pierre
64bacc6286 popupMenu: Port to GrabHelper
https://bugzilla.gnome.org/show_bug.cgi?id=689109
2012-11-26 15:13:04 -05:00
Jasper St. Pierre
50fec9e1f8 grabHelper: Drop to the actor clicked on
This is necessary for child popups in menus, e.g. while in a combo box,
clicking outside of the user menu should drop the entire menu, but
clicking on the user menu itself should only drop the combo box.
2012-11-26 15:13:04 -05:00
Jasper St. Pierre
b03f7564e3 grabHelper: Treat the current grabbed actor as a grabbed actor
This should be obvious, but I guess it wasn't necessary for the
message tray case.
2012-11-26 15:13:04 -05:00
Jasper St. Pierre
ef9006fa65 grabHelper: Use captured-event for escape ungrabs
I have no idea why we used 'event' rather than 'captured-event' before.
'event' has some really strange quirks that came up when porting PopupMenu
to the GrabHelper
2012-11-26 15:13:04 -05:00
Jasper St. Pierre
485d16ca4e overview: Remove custom swipe scrolling implementation
https://bugzilla.gnome.org/show_bug.cgi?id=689062
2012-11-26 15:13:04 -05:00
Jasper St. Pierre
1e40264ee4 workspacesView: Don't use the overview swipe scrolling system
Switch to a ClutterPanAction instead too.

https://bugzilla.gnome.org/show_bug.cgi?id=689062
2012-11-26 15:13:04 -05:00
Jasper St. Pierre
ae22bde368 workspacesView: Clean up scroll code a bit
There's no code path that results in us not animating.

https://bugzilla.gnome.org/show_bug.cgi?id=689062
2012-11-26 15:13:04 -05:00
Jasper St. Pierre
32502af652 searchDisplay, appDisplay: Use ClutterPanAction for re-swipe scrolling
The sooner we can kill off the custom overview swipe scroll code, the
better.

https://bugzilla.gnome.org/show_bug.cgi?id=689062
2012-11-26 15:13:03 -05:00
Jasper St. Pierre
7d693cbd17 viewSelector: Set the active page immediately
This prevents some focus management issues.

https://bugzilla.gnome.org/show_bug.cgi?id=689062
2012-11-26 15:13:03 -05:00
Jasper St. Pierre
d86e57a8d9 layout: Dummy hack for now because the X server is amazing
dummy demo garbage
2012-11-26 15:12:52 -05:00
Jasper St. Pierre
75985ae0ce messageTray: Remove dwell to open
This is now covered by pointer barriers.
2012-11-26 15:12:52 -05:00
Jasper St. Pierre
7ee897ead5 layout: Don't show the tray if the user is just skirting the barrier
If the user is just pushing their mouse along the barrier's edge, rather
than pushing down onto the barrier, we shouldn't show the tray. Do this
by keeping track of the distance traveled perpendicular to the barrier,
and releasing the accumulated pressure if we pass a threshold.
2012-11-26 15:12:52 -05:00
Jasper St. Pierre
7c371392da layout: Trigger the message tray by downward pressure
https://bugzilla.gnome.org/show_bug.cgi?id=677215
2012-11-26 15:12:52 -05:00
Jasper St. Pierre
ab549f763d layout: Port to the new mutter-based barrier wrappers
... and remove our old ones.

https://bugzilla.gnome.org/show_bug.cgi?id=677215
2012-11-26 15:12:52 -05:00
Jasper St. Pierre
ea25331a55 messageTray: Remove an unused instance variable 2012-11-26 15:12:52 -05:00
Jasper St. Pierre
c6bc1526fa workspace: Add smooth scrolling support to zoom windows
https://bugzilla.gnome.org/show_bug.cgi?id=687573
2012-11-26 15:12:43 -05:00
Jasper St. Pierre
871ae3f9b2 volume: Add smooth scrolling support to adjust output volume
https://bugzilla.gnome.org/show_bug.cgi?id=687573
2012-11-26 15:12:43 -05:00
Jasper St. Pierre
8ebbf442cd popupMenu: Add smooth scrolling support for sliders
Allowing smooth scrolling on the Y axis to accurately adjust the value
of the slider.

https://bugzilla.gnome.org/show_bug.cgi?id=687573
2012-11-26 15:12:43 -05:00
Jasper St. Pierre
b936f094d1 st-scroll-view: Throw away emulated pointer events
These are sent by the X server and have large deltas. They really
should be filtered out by Clutter (or the X server) somehow, but we
don't have the means to do that yet.

https://bugzilla.gnome.org/show_bug.cgi?id=687573
2012-11-26 15:12:43 -05:00
Jasper St. Pierre
165265f4fb st-scroll-view: Add proper smooth scrolling
The code here before was added as dummy code to satisfy an error
in the missing switch, and wasn't ever tested due to the lack of XI2
in mutter. Use the same math as GtkRange does to calculate scroll bar
positions from raw XI2 deltas to allow for proper smooth scrolling.

https://bugzilla.gnome.org/show_bug.cgi?id=687573
2012-11-26 15:12:42 -05:00
26 changed files with 470 additions and 827 deletions

View File

@@ -114,14 +114,6 @@ AC_SUBST([GNOME_KEYBINDINGS_KEYSDIR])
GOBJECT_INTROSPECTION_CHECK([$GOBJECT_INTROSPECTION_MIN_VERSION])
saved_CFLAGS=$CFLAGS
saved_LIBS=$LIBS
CFLAGS=$GNOME_SHELL_CFLAGS
LIBS=$GNOME_SHELL_LIBS
AC_CHECK_FUNCS(JS_NewGlobalObject XFixesCreatePointerBarrier)
CFLAGS=$saved_CFLAGS
LIBS=$saved_LIBS
PKG_CHECK_MODULES(GNOME_SHELL_JS, gio-2.0 gjs-internals-1.0 >= $GJS_MIN_VERSION)
PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-3.0 libcroco-0.6 >= 0.6.8 x11)
PKG_CHECK_MODULES(TRAY, gtk+-3.0)

View File

@@ -54,9 +54,7 @@ keys_in_files = \
$(NULL)
keys_DATA = $(keys_in_files:.xml.in=.xml)
gsettings_SCHEMAS = \
org.gnome.shell.gschema.xml \
org.gnome.shell-foo.gschema.xml
gsettings_SCHEMAS = org.gnome.shell.gschema.xml
@INTLTOOL_XML_NOMERGE_RULE@
@@ -83,8 +81,7 @@ EXTRA_DIST = \
$(menu_DATA) \
$(convert_DATA) \
$(keys_in_files) \
org.gnome.shell.gschema.xml.in.in \
org.gnome.shell-foo.gschema.xml.in.in
org.gnome.shell.gschema.xml.in.in
CLEANFILES = \
gnome-shell.desktop.in \
@@ -94,6 +91,4 @@ CLEANFILES = \
$(gsettings_SCHEMAS) \
gschemas.compiled \
org.gnome.shell.gschema.valid \
org.gnome.shell.gschema.xml.in \
org.gnome.shell-foo.gschema.valid \
org.gnome.shell-foo.gschema.xml.in
org.gnome.shell.gschema.xml.in

View File

@@ -1,13 +0,0 @@
<schemalist>
<schema id="org.gnome.shell-foo.overrides" path="/org/gnome/shell-foo/overrides/"
gettext-domain="@GETTEXT_PACKAGE@">
<key name="button-layout" type="s">
<default>":minimize,close"</default>
<_summary>Arrangement of buttons on the titlebar</_summary>
<_description>
This key overrides the key in org.gnome.desktop.wm.preferences when
running GNOME Shell in Foo mode.
</_description>
</key>
</schema>
</schemalist>

View File

@@ -48,18 +48,16 @@ const AlphabeticalView = new Lang.Class({
style_class: 'vfade' });
this.actor.add_actor(box);
this.actor.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
this.actor.connect('notify::mapped', Lang.bind(this,
function() {
if (!this.actor.mapped)
return;
let action = new Clutter.PanAction({ interpolate: true });
action.connect('pan', Lang.bind(this, this._onPan));
this.actor.add_action(action);
},
let adjustment = this.actor.vscroll.adjustment;
let direction = Overview.SwipeScrollDirection.VERTICAL;
Main.overview.setScrollAdjustment(adjustment, direction);
// Reset scroll on mapping
adjustment.value = 0;
}));
_onPan: function(action) {
let [dist, dx, dy] = action.get_motion_delta(0);
let adjustment = this.actor.vscroll.adjustment;
adjustment.value -= (dy / this.actor.height) * adjustment.page_size;
return false;
},
removeAll: function() {

View File

@@ -730,7 +730,8 @@ const ChatSource = new Lang.Class({
_ackMessages: function() {
// Don't clear our messages here, tp-glib will send a
// 'pending-message-removed' for each one.
this._channel.ack_all_pending_messages_async(null);
this._channel.ack_all_pending_messages_async(Lang.bind(this, function(src, result) {
this._channel.ack_all_pending_messages_finish(result);}));
}
});

View File

@@ -43,7 +43,6 @@ const GrabHelper = new Lang.Class({
this._actors = [];
this._capturedEventId = 0;
this._eventId = 0;
this._keyFocusNotifyId = 0;
this._focusWindowChangedId = 0;
this._ignoreRelease = false;
@@ -77,10 +76,25 @@ const GrabHelper = new Lang.Class({
}
},
_actorInGrabStack: function(actor) {
while (actor) {
for (let i = 0; i < this._grabStack.length; i++) {
let grab = this._grabStack[i];
if (grab.actor == actor)
return i;
}
actor = actor.get_parent();
}
return -1;
},
_isWithinGrabbedActor: function(actor) {
let currentActor = this.currentGrab.actor;
while (actor) {
if (this._actors.indexOf(actor) != -1)
return true;
if (actor == currentActor)
return true;
actor = actor.get_parent();
}
return false;
@@ -90,6 +104,14 @@ const GrabHelper = new Lang.Class({
return this._grabStack[this._grabStack.length - 1] || {};
},
get grabbed() {
return this._grabStack.length > 0;
},
get grabStack() {
return this._grabStack;
},
_findStackIndex: function(actor) {
if (!actor)
return -1;
@@ -171,7 +193,6 @@ const GrabHelper = new Lang.Class({
return false;
this._capturedEventId = global.stage.connect('captured-event', Lang.bind(this, this._onCapturedEvent));
this._eventId = global.stage.connect('event', Lang.bind(this, this._onEvent));
}
this._modalCount++;
@@ -188,11 +209,6 @@ const GrabHelper = new Lang.Class({
this._capturedEventId = 0;
}
if (this._eventId > 0) {
global.stage.disconnect(this._eventId);
this._eventId = 0;
}
Main.popModal(this._owner);
global.sync_pointer();
},
@@ -323,27 +339,22 @@ const GrabHelper = new Lang.Class({
if (Main.keyboard.shouldTakeEvent(event))
return false;
if (button) {
// If we have a press event, ignore the next event,
// which should be a release event.
if (press)
this._ignoreRelease = true;
this.ungrab({ actor: this._grabStack[0].actor });
}
return this._modalCount > 0;
},
// We catch 'event' rather than 'key-press-event' so that we get
// a chance to run before the overview's own Escape check
_onEvent: function(actor, event) {
if (event.type() == Clutter.EventType.KEY_PRESS &&
if (type == Clutter.EventType.KEY_PRESS &&
event.get_key_symbol() == Clutter.KEY_Escape) {
this.ungrab();
return true;
}
return false;
if (button) {
// If we have a press event, ignore the next event,
// which should be a release event.
if (press)
this._ignoreRelease = true;
let i = this._actorInGrabStack(event.get_source()) + 1;
this.ungrab({ actor: this._grabStack[i].actor });
}
return this._modalCount > 0;
},
_onKeyFocusChanged: function() {

View File

@@ -19,6 +19,12 @@ const STARTUP_ANIMATION_TIME = 0.2;
const KEYBOARD_ANIMATION_TIME = 0.5;
const PLYMOUTH_TRANSITION_TIME = 1;
const MESSAGE_TRAY_PRESSURE_THRESHOLD = 200;
// The maximium amount that the user is allowed to travel
// perpendicular to the barrier before we release the accumulated
// pressure.
const MESSAGE_TRAY_MAX_SKIRT = 100;
const MonitorConstraint = new Lang.Class({
Name: 'MonitorConstraint',
Extends: Clutter.Constraint,
@@ -106,9 +112,9 @@ const LayoutManager = new Lang.Class({
this._keyboardIndex = -1;
this._hotCorners = [];
this._background = null;
this._leftPanelBarrier = 0;
this._rightPanelBarrier = 0;
this._trayBarrier = 0;
this._leftPanelBarrier = null;
this._rightPanelBarrier = null;
this._trayBarrier = null;
this._chrome = new Chrome(this);
@@ -129,6 +135,8 @@ const LayoutManager = new Lang.Class({
this.trayBox = new St.Widget({ name: 'trayBox',
layout_manager: new Clutter.BinLayout() });
this.addChrome(this.trayBox);
this.trayBox.connect('allocation-changed',
Lang.bind(this, this._updateTrayBarrier));
this.keyboardBox = new St.BoxLayout({ name: 'keyboardBox',
reactive: true,
@@ -257,24 +265,50 @@ const LayoutManager = new Lang.Class({
},
_updatePanelBarriers: function() {
if (this._leftPanelBarrier)
global.destroy_pointer_barrier(this._leftPanelBarrier);
if (this._rightPanelBarrier)
global.destroy_pointer_barrier(this._rightPanelBarrier);
if (this._leftPanelBarrier) {
this._leftPanelBarrier.destroy();
this._leftPanelBarrier = null;
}
if (this._rightPanelBarrier) {
this._rightPanelBarrier.destroy();
this._rightPanelBarrier = null;
}
if (this.panelBox.height) {
let primary = this.primaryMonitor;
this._leftPanelBarrier =
global.create_pointer_barrier(primary.x, primary.y,
primary.x, primary.y + this.panelBox.height,
1 /* BarrierPositiveX */);
this._rightPanelBarrier =
global.create_pointer_barrier(primary.x + primary.width, primary.y,
primary.x + primary.width, primary.y + this.panelBox.height,
4 /* BarrierNegativeX */);
} else {
this._leftPanelBarrier = 0;
this._rightPanelBarrier = 0;
this._leftPanelBarrier = new Meta.Barrier({ display: global.display,
x1: primary.x, y1: primary.y,
x2: primary.x, y2: primary.y + this.panelBox.height,
directions: Meta.BarrierDirection.POSITIVE_X });
this._rightPanelBarrier = new Meta.Barrier({ display: global.display,
x1: primary.x + primary.width, y1: primary.y,
x2: primary.x + primary.width, y2: primary.y + this.panelBox.height,
directions: Meta.BarrierDirection.NEGATIVE_X });
}
},
_updateTrayBarrier: function() {
let monitor = this.bottomMonitor;
if (this._trayBarrier) {
this._trayBarrier.destroy();
this._trayBarrier = null;
}
if (Main.messageTray) {
this._trayBarrier = new Meta.Barrier({ display: global.display,
x1: monitor.x, x2: monitor.x + monitor.width,
y1: monitor.y + monitor.height - 1, y2: monitor.y + monitor.height - 1,
directions: Meta.BarrierDirection.NEGATIVE_Y });
this._trayPressure = new PressureBarrier(this._trayBarrier,
MESSAGE_TRAY_PRESSURE_THRESHOLD,
MESSAGE_TRAY_MAX_SKIRT);
this._trayPressure.connect('trigger', function() {
Main.messageTray.openTray();
});
}
},
@@ -1127,5 +1161,69 @@ const Chrome = new Lang.Class({
return false;
}
});
Signals.addSignalMethods(Chrome.prototype);
const PressureBarrier = new Lang.Class({
Name: 'TrayPressure',
_init: function(barrier, pressureThreshold, perpThreshold) {
this._barrier = barrier;
this._pressureThreshold = pressureThreshold;
this._perpThreshold = perpThreshold;
this._getVelocityAndPerp = this._makeGetVelocityAndPerp(barrier);
this._reset(0);
this._barrierHitId = this._barrier.connect('hit', Lang.bind(this, this._onBarrierHit));
},
destroy: function() {
this._barrier.disconnect(this._barrierHitId);
this._barrier = null;
},
_reset: function(eventId) {
this._currentEventId = eventId;
this._currentPressure = 0;
this._perpAccumulator = 0;
},
_makeGetVelocityAndPerp: function(barrier) {
if (barrier.y1 === barrier.y2) {
return function(event) {
return [Math.abs(event.dy), event.dx];
};
} else {
return function(event) {
return [Math.abs(event.dx), event.dy];
};
}
},
_onBarrierHit: function(barrier, event) {
// Event IDs are incremented every time the user stops
// hitting the barrier. So, if the event ID switches,
// reset the current state, and start over.
if (this._currentEventId != event.event_id) {
this._reset(event.event_id);
}
let [velocity, perp] = this._getVelocityAndPerp(event);
this._perpAccumulator += perp;
// If the user travels too far in the direction perpendicular
// to the barrier, start over from scratch -- the user is simply
// trying to skirt along the barrier.
if (Math.abs(this._perpAccumulator) >= this._perpThreshold) {
this._reset(0);
return;
}
this._currentPressure += velocity;
if (this._currentPressure >= this._pressureThreshold) {
this.emit('trigger');
this._reset(0);
}
}
});
Signals.addSignalMethods(PressureBarrier.prototype);

View File

@@ -109,8 +109,6 @@ function start() {
Gio.DesktopAppInfo.set_desktop_env('GNOME');
sessionMode = new SessionMode.SessionMode();
Meta.prefs_override_preference_schema(sessionMode.buttonLayout[0], sessionMode.buttonLayout[1]);
shellDBusService = new ShellDBus.GnomeShell();
shellMountOpDBusService = new ShellMountOperation.GnomeShellMountOpHandler();

View File

@@ -40,11 +40,6 @@ const LONGER_HIDE_TIMEOUT = 0.6;
// range from the point where it left the tray.
const MOUSE_LEFT_ACTOR_THRESHOLD = 20;
// Time the user needs to leave the mouse on the bottom pixel row to open the tray
const TRAY_DWELL_TIME = 1000; // ms
// Time resolution when tracking the mouse to catch the open tray dwell
const TRAY_DWELL_CHECK_INTERVAL = 100; // ms
const IDLE_TIME = 1000;
const State = {
@@ -1441,7 +1436,6 @@ const MessageTray = new Lang.Class({
this._clickedSummaryItem = null;
this._clickedSummaryItemMouseButton = -1;
this._clickedSummaryItemAllocationChangedId = 0;
this._pointerBarrier = 0;
this._closeButton = makeCloseButton();
this._closeButton.hide();
@@ -1537,12 +1531,6 @@ const MessageTray = new Lang.Class({
this._summaryItems = [];
this._chatSummaryItemsCount = 0;
let pointerWatcher = PointerWatcher.getPointerWatcher();
pointerWatcher.addWatch(TRAY_DWELL_CHECK_INTERVAL, Lang.bind(this, this._checkTrayDwell));
this._trayDwellTimeoutId = 0;
this._trayDwelling = false;
this._trayDwellUserTime = 0;
this._sessionUpdated();
this._updateNoMessagesLabel();
},
@@ -1572,52 +1560,7 @@ const MessageTray = new Lang.Class({
this._updateState();
},
_checkTrayDwell: function(x, y) {
let monitor = Main.layoutManager.bottomMonitor;
let shouldDwell = (x >= monitor.x && x <= monitor.x + monitor.width &&
y == monitor.y + monitor.height - 1);
if (shouldDwell) {
// We only set up dwell timeout when the user is not hovering over the tray
// (!this.actor.hover). This avoids bringing up the message tray after the
// user clicks on a notification with the pointer on the bottom pixel
// of the monitor. The _trayDwelling variable is used so that we only try to
// fire off one tray dwell - if it fails (because, say, the user has the mouse down),
// we don't try again until the user moves the mouse up and down again.
if (!this._trayDwelling && !this.actor.hover && this._trayDwellTimeoutId == 0) {
// Save the interaction timestamp so we can detect user input
let focusWindow = global.display.focus_window;
this._trayDwellUserTime = focusWindow ? focusWindow.user_time : 0;
this._trayDwellTimeoutId = Mainloop.timeout_add(TRAY_DWELL_TIME,
Lang.bind(this, this._trayDwellTimeout));
}
this._trayDwelling = true;
} else {
this._cancelTrayDwell();
this._trayDwelling = false;
}
},
_cancelTrayDwell: function() {
if (this._trayDwellTimeoutId != 0) {
Mainloop.source_remove(this._trayDwellTimeoutId);
this._trayDwellTimeoutId = 0;
}
},
_trayDwellTimeout: function() {
this._trayDwellTimeoutId = 0;
if (Main.modalCount > 0)
return false;
// If the user interacted with the focus window since we started the tray
// dwell (by clicking or typing), don't activate the message tray
let focusWindow = global.display.focus_window;
let currentUserTime = focusWindow ? focusWindow.user_time : 0;
if (currentUserTime != this._trayDwellUserTime)
return false;
openTray: function() {
this._traySummoned = true;
this._updateState();
@@ -1849,9 +1792,6 @@ const MessageTray = new Lang.Class({
_onTrayHoverChanged: function() {
if (this.actor.hover) {
// No dwell inside notifications at the bottom of the screen
this._cancelTrayDwell();
// Don't do anything if the one pixel area at the bottom is hovered over while the tray is hidden.
if (this._trayState == State.HIDDEN && this._notificationState == State.HIDDEN)
return;

View File

@@ -46,18 +46,6 @@ const GLSL_DIM_EFFECT_CODE = '\
cogl_color_out.xyz = cogl_color_out.xyz * (1.0 - a); \
cogl_color_out.a = 1.0;';
const SwipeScrollDirection = {
NONE: 0,
HORIZONTAL: 1,
VERTICAL: 2
};
const SwipeScrollResult = {
CANCEL: 0,
SWIPE: 1,
CLICK: 2
};
const ShellInfo = new Lang.Class({
Name: 'ShellInfo',
@@ -165,8 +153,6 @@ const Overview = new Lang.Class({
}
}));
this._scrollDirection = SwipeScrollDirection.NONE;
this._scrollAdjustment = null;
this._capturedEventId = 0;
this._buttonPressId = 0;
@@ -341,159 +327,11 @@ const Overview = new Lang.Class({
return DND.DragMotionResult.CONTINUE;
},
setScrollAdjustment: function(adjustment, direction) {
addAction: function(action) {
if (this.isDummy)
return;
this._scrollAdjustment = adjustment;
if (this._scrollAdjustment == null)
this._scrollDirection = SwipeScrollDirection.NONE;
else
this._scrollDirection = direction;
},
_onButtonPress: function(actor, event) {
if (this._scrollDirection == SwipeScrollDirection.NONE
|| event.get_button() != 1)
return;
let [stageX, stageY] = event.get_coords();
this._dragStartX = this._dragX = stageX;
this._dragStartY = this._dragY = stageY;
this._dragStartValue = this._scrollAdjustment.value;
this._lastMotionTime = -1; // used to track "stopping" while swipe-scrolling
this._capturedEventId = global.stage.connect('captured-event',
Lang.bind(this, this._onCapturedEvent));
this.emit('swipe-scroll-begin');
},
_onCapturedEvent: function(actor, event) {
let stageX, stageY;
let threshold = Gtk.Settings.get_default().gtk_dnd_drag_threshold;
switch(event.type()) {
case Clutter.EventType.BUTTON_RELEASE:
[stageX, stageY] = event.get_coords();
// default to snapping back to the original value
let newValue = this._dragStartValue;
let minValue = this._scrollAdjustment.lower;
let maxValue = this._scrollAdjustment.upper - this._scrollAdjustment.page_size;
let direction;
if (this._scrollDirection == SwipeScrollDirection.HORIZONTAL) {
direction = stageX > this._dragStartX ? -1 : 1;
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
direction *= -1;
} else {
direction = stageY > this._dragStartY ? -1 : 1;
}
// We default to scroll a full page size; both the first
// and the last page may be smaller though, so we need to
// adjust difference in those cases.
let difference = direction * this._scrollAdjustment.page_size;
if (this._dragStartValue + difference > maxValue)
difference = maxValue - this._dragStartValue;
else if (this._dragStartValue + difference < minValue)
difference = minValue - this._dragStartValue;
// If the user has moved more than half the scroll
// difference, we want to "settle" to the new value
// even if the user stops dragging rather "throws" by
// releasing during the drag.
let distance = this._dragStartValue - this._scrollAdjustment.value;
let noStop = Math.abs(distance / difference) > 0.5;
// We detect if the user is stopped by comparing the
// timestamp of the button release with the timestamp of
// the last motion. Experimentally, a difference of 0 or 1
// millisecond indicates that the mouse is in motion, a
// larger difference indicates that the mouse is stopped.
if ((this._lastMotionTime > 0 &&
this._lastMotionTime > event.get_time() - 2) ||
noStop) {
if (this._dragStartValue + difference >= minValue &&
this._dragStartValue + difference <= maxValue)
newValue += difference;
}
let result;
// See if the user has moved the mouse enough to trigger
// a drag
if (Math.abs(stageX - this._dragStartX) < threshold &&
Math.abs(stageY - this._dragStartY) < threshold) {
// no motion? It's a click!
result = SwipeScrollResult.CLICK;
this.emit('swipe-scroll-end', result);
} else {
if (newValue == this._dragStartValue)
result = SwipeScrollResult.CANCEL;
else
result = SwipeScrollResult.SWIPE;
// The event capture handler is disconnected
// while scrolling to the final position, so
// to avoid undesired prelights we raise
// the cover pane.
this._coverPane.raise_top();
this._coverPane.show();
Tweener.addTween(this._scrollAdjustment,
{ value: newValue,
time: ANIMATION_TIME,
transition: 'easeOutQuad',
onCompleteScope: this,
onComplete: function() {
this._coverPane.hide();
this.emit('swipe-scroll-end',
result);
}
});
}
global.stage.disconnect(this._capturedEventId);
this._capturedEventId = 0;
return result != SwipeScrollResult.CLICK;
case Clutter.EventType.MOTION:
[stageX, stageY] = event.get_coords();
let dx = this._dragX - stageX;
let dy = this._dragY - stageY;
let primary = Main.layoutManager.primaryMonitor;
this._dragX = stageX;
this._dragY = stageY;
this._lastMotionTime = event.get_time();
// See if the user has moved the mouse enough to trigger
// a drag
if (Math.abs(stageX - this._dragStartX) < threshold &&
Math.abs(stageY - this._dragStartY) < threshold)
return true;
if (this._scrollDirection == SwipeScrollDirection.HORIZONTAL) {
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
this._scrollAdjustment.value -= (dx / primary.width) * this._scrollAdjustment.page_size;
else
this._scrollAdjustment.value += (dx / primary.width) * this._scrollAdjustment.page_size;
} else {
this._scrollAdjustment.value += (dy / primary.height) * this._scrollAdjustment.page_size;
}
return true;
// Block enter/leave events to avoid prelights
// during swipe-scroll
case Clutter.EventType.ENTER:
case Clutter.EventType.LEAVE:
return true;
}
return false;
this._group.add_action(action);
},
_getDesktopClone: function() {
@@ -596,9 +434,6 @@ const Overview = new Lang.Class({
this._modal = true;
this._animateVisible();
this._shown = true;
this._buttonPressId = this._group.connect('button-press-event',
Lang.bind(this, this._onButtonPress));
},
fadeInDesktop: function() {
@@ -698,10 +533,6 @@ const Overview = new Lang.Class({
this._shown = false;
this._syncInputMode();
if (this._buttonPressId > 0)
this._group.disconnect(this._buttonPressId);
this._buttonPressId = 0;
},
// hideTemporarily:

View File

@@ -75,19 +75,19 @@ function _unpremultiply(color) {
blue: blue, alpha: color.alpha });
};
const Animation = new Lang.Class({
Name: 'Animation',
_init: function(filename, width, height, speed) {
this.actor = new St.Bin();
const AnimatedIcon = new Lang.Class({
Name: 'AnimatedIcon',
_init: function(name, size) {
this.actor = new St.Bin({ visible: false });
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
this._speed = speed;
this._isLoaded = false;
this._isPlaying = false;
this._timeoutId = 0;
this._frame = 0;
this._animations = St.TextureCache.get_default().load_sliced_image (filename, width, height,
this._animations = St.TextureCache.get_default().load_sliced_image (global.datadir + '/theme/' + name, size, size,
Lang.bind(this, this._animationsLoaded));
this.actor.set_child(this._animations);
},
@@ -97,7 +97,7 @@ const Animation = new Lang.Class({
if (this._frame == 0)
this._showFrame(0);
this._timeoutId = Mainloop.timeout_add(this._speed, Lang.bind(this, this._update));
this._timeoutId = Mainloop.timeout_add(ANIMATED_ICON_UPDATE_TIMEOUT, Lang.bind(this, this._update));
}
this._isPlaying = true;
@@ -132,8 +132,10 @@ const Animation = new Lang.Class({
_animationsLoaded: function() {
this._isLoaded = true;
if (this._isPlaying)
this.play();
if (this._isPlaying) {
this._showFrame(0);
this._timeoutId = Mainloop.timeout_add(ANIMATED_ICON_UPDATE_TIMEOUT, Lang.bind(this, this._update));
}
},
_onDestroy: function() {
@@ -141,15 +143,6 @@ const Animation = new Lang.Class({
}
});
const AnimatedIcon = new Lang.Class({
Name: 'AnimatedIcon',
Extends: Animation,
_init: function(name, size) {
this.parent(global.datadir + '/theme/' + name, size, size, ANIMATED_ICON_UPDATE_TIMEOUT);
}
});
const TextShadower = new Lang.Class({
Name: 'TextShadower',
@@ -301,7 +294,6 @@ const AppMenuButton = new Lang.Class({
this._spinner = new AnimatedIcon('process-working.svg',
PANEL_ICON_SIZE);
this._container.add_actor(this._spinner.actor);
this._spinner.actor.hide();
this._spinner.actor.lower_bottom();
let tracker = Shell.WindowTracker.get_default();

View File

@@ -12,6 +12,7 @@ const St = imports.gi.St;
const Atk = imports.gi.Atk;
const BoxPointer = imports.ui.boxpointer;
const GrabHelper = imports.ui.grabHelper;
const Main = imports.ui.main;
const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
@@ -658,14 +659,23 @@ const PopupSliderMenuItem = new Lang.Class({
_onScrollEvent: function (actor, event) {
let direction = event.get_scroll_direction();
let delta;
if (event.is_pointer_emulated())
return;
if (direction == Clutter.ScrollDirection.DOWN) {
this._value = Math.max(0, this._value - SLIDER_SCROLL_STEP);
}
else if (direction == Clutter.ScrollDirection.UP) {
this._value = Math.min(1, this._value + SLIDER_SCROLL_STEP);
delta = -SLIDER_SCROLL_STEP;
} else if (direction == Clutter.ScrollDirection.UP) {
delta = +SLIDER_SCROLL_STEP;
} else if (direction == Clutter.ScrollDirection.SMOOTH) {
let [dx, dy] = event.get_scroll_delta();
// Even though the slider is horizontal, use dy to match
// the UP/DOWN above.
delta = -dy / 10;
}
this._value = Math.min(Math.max(0, this._value + delta), 1);
this._slider.queue_repaint();
this.emit('value-changed', this._value);
},
@@ -1204,7 +1214,6 @@ const PopupMenu = new Lang.Class({
this.actor = this._boxPointer.actor;
this.actor._delegate = this;
this.actor.style_class = 'popup-menu-boxpointer';
this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent));
this._boxWrapper = new Shell.GenericContainer();
this._boxWrapper.connect('get-preferred-width', Lang.bind(this, this._boxGetPreferredWidth));
@@ -1234,15 +1243,6 @@ const PopupMenu = new Lang.Class({
this.box.allocate(box, flags);
},
_onKeyPressEvent: function(actor, event) {
if (event.get_key_symbol() == Clutter.Escape) {
this.close(BoxPointer.PopupAnimation.FULL);
return true;
}
return false;
},
setArrowOrigin: function(origin) {
this._boxPointer.setArrowOrigin(origin);
},
@@ -1537,7 +1537,6 @@ const PopupComboMenu = new Lang.Class({
this.actor = this.box;
this.actor._delegate = this;
this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent));
this.actor.connect('key-focus-in', Lang.bind(this, this._onKeyFocusIn));
sourceActor.connect('style-changed',
Lang.bind(this, this._onSourceActorStyleChanged));
@@ -1545,15 +1544,6 @@ const PopupComboMenu = new Lang.Class({
global.focus_manager.add_group(this.actor);
},
_onKeyPressEvent: function(actor, event) {
if (event.get_key_symbol() == Clutter.Escape) {
this.close(BoxPointer.PopupAnimation.FULL);
return true;
}
return false;
},
_onKeyFocusIn: function(actor) {
let items = this._getMenuItems();
let activeItem = items[this._activeItemPos];
@@ -2044,17 +2034,8 @@ const PopupMenuManager = new Lang.Class({
_init: function(owner) {
this._owner = owner;
this.grabbed = false;
this._eventCaptureId = 0;
this._enterEventId = 0;
this._leaveEventId = 0;
this._keyFocusNotifyId = 0;
this._activeMenu = null;
this._grabHelper = new GrabHelper.GrabHelper(owner.actor);
this._menus = [];
this._menuStack = [];
this._preGrabInputMode = null;
this._grabbedFromKeynav = false;
},
addMenu: function(menu, position) {
@@ -2073,6 +2054,8 @@ const PopupMenuManager = new Lang.Class({
let source = menu.sourceActor;
if (source) {
if (!menu.blockSourceEvents)
this._grabHelper.addActor(source);
menudata.enterId = source.connect('enter-event', Lang.bind(this, function() { this._onMenuSourceEnter(menu); }));
menudata.focusInId = source.connect('key-focus-in', Lang.bind(this, function() { this._onMenuSourceEnter(menu); }));
}
@@ -2085,7 +2068,7 @@ const PopupMenuManager = new Lang.Class({
removeMenu: function(menu) {
if (menu == this._activeMenu)
this._closeMenu();
this._closeMenu(menu);
let position = this._findMenu(menu);
if (position == -1) // not a menu we manage
@@ -2102,79 +2085,25 @@ const PopupMenuManager = new Lang.Class({
if (menudata.focusInId)
menu.sourceActor.disconnect(menudata.focusInId);
if (menu.sourceActor)
this._grabHelper.removeActor(menu.sourceActor);
this._menus.splice(position, 1);
},
_grab: function() {
Main.pushModal(this._owner.actor);
this._eventCaptureId = global.stage.connect('captured-event', Lang.bind(this, this._onEventCapture));
// captured-event doesn't see enter/leave events
this._enterEventId = global.stage.connect('enter-event', Lang.bind(this, this._onEventCapture));
this._leaveEventId = global.stage.connect('leave-event', Lang.bind(this, this._onEventCapture));
this._keyFocusNotifyId = global.stage.connect('notify::key-focus', Lang.bind(this, this._onKeyFocusChanged));
this.grabbed = true;
},
_ungrab: function() {
global.stage.disconnect(this._eventCaptureId);
this._eventCaptureId = 0;
global.stage.disconnect(this._enterEventId);
this._enterEventId = 0;
global.stage.disconnect(this._leaveEventId);
this._leaveEventId = 0;
global.stage.disconnect(this._keyFocusNotifyId);
this._keyFocusNotifyId = 0;
this.grabbed = false;
Main.popModal(this._owner.actor);
get activeMenu() {
let actor = this._grabHelper.currentGrab.actor;
if (actor)
return actor._delegate;
else
return null;
},
_onMenuOpenState: function(menu, open) {
if (open) {
if (this._activeMenu && this._activeMenu.isChildMenu(menu)) {
this._menuStack.push(this._activeMenu);
menu.actor.grab_key_focus();
}
this._activeMenu = menu;
this._grabHelper.grab({ actor: menu.actor, modal: true,
onUngrab: Lang.bind(this, this._closeMenu, menu) });
} else {
if (this._menuStack.length > 0) {
this._activeMenu = this._menuStack.pop();
if (menu.sourceActor)
menu.sourceActor.grab_key_focus();
this._didPop = true;
}
}
// Check what the focus was before calling pushModal/popModal
let focus = global.stage.key_focus;
let hadFocus = focus && this._activeMenuContains(focus);
if (open) {
if (!this.grabbed) {
this._preGrabInputMode = global.stage_input_mode;
this._grabbedFromKeynav = hadFocus;
this._grab();
}
if (hadFocus)
focus.grab_key_focus();
else
menu.actor.grab_key_focus();
} else if (menu == this._activeMenu) {
if (this.grabbed)
this._ungrab();
this._activeMenu = null;
if (this._grabbedFromKeynav) {
if (this._preGrabInputMode == Shell.StageInputMode.FOCUSED)
global.stage_input_mode = Shell.StageInputMode.FOCUSED;
if (hadFocus && menu.sourceActor)
menu.sourceActor.grab_key_focus();
else if (focus)
focus.grab_key_focus();
}
this._grabHelper.ungrab({ actor: menu.actor });
}
},
@@ -2186,87 +2115,37 @@ const PopupMenuManager = new Lang.Class({
this.removeMenu(childMenu);
},
// change the currently-open menu without dropping grab
_changeMenu: function(newMenu) {
if (this._activeMenu) {
// _onOpenMenuState will drop the grab if it sees
// this._activeMenu being closed; so clear _activeMenu
// before closing it to keep that from happening
let oldMenu = this._activeMenu;
this._activeMenu = null;
for (let i = this._menuStack.length - 1; i >= 0; i--)
this._menuStack[i].close(BoxPointer.PopupAnimation.FADE);
oldMenu.close(BoxPointer.PopupAnimation.FADE);
newMenu.open(BoxPointer.PopupAnimation.FADE);
} else
newMenu.open(BoxPointer.PopupAnimation.FULL);
if (this.activeMenu) {
this._closeMenu(this.activeMenu);
newMenu.open(false);
} else {
newMenu.open(true);
}
},
_onMenuSourceEnter: function(menu) {
if (!this.grabbed || menu == this._activeMenu)
if (!this._grabHelper.grabbed)
return false;
if (this._activeMenu && this._activeMenu.isChildMenu(menu))
if (this._grabHelper.isActorGrabbed(menu.actor))
return false;
if (this._menuStack.indexOf(menu) != -1)
return false;
if (this._menuStack.length > 0 && this._menuStack[0].isChildMenu(menu))
let isChildMenu = this._grabHelper.grabStack.some(function(grab) {
let existingMenu = grab.actor._delegate;
return existingMenu.isChildMenu(menu);
});
if (isChildMenu)
return false;
this._changeMenu(menu);
return false;
},
_onKeyFocusChanged: function() {
if (!this.grabbed || !this._activeMenu)
return;
let focus = global.stage.key_focus;
if (focus) {
if (this._activeMenuContains(focus))
return;
if (this._menuStack.length > 0)
return;
if (focus._delegate && focus._delegate.menu &&
this._findMenu(focus._delegate.menu) != -1)
return;
}
this._closeMenu();
},
_onMenuDestroy: function(menu) {
this.removeMenu(menu);
},
_activeMenuContains: function(actor) {
return this._activeMenu != null
&& (this._activeMenu.actor.contains(actor) ||
(this._activeMenu.sourceActor && this._activeMenu.sourceActor.contains(actor)));
},
_eventIsOnActiveMenu: function(event) {
return this._activeMenuContains(event.get_source());
},
_shouldBlockEvent: function(event) {
let src = event.get_source();
if (this._activeMenu != null && this._activeMenu.actor.contains(src))
return false;
for (let i = 0; i < this._menus.length; i++) {
let menu = this._menus[i].menu;
if (menu.sourceActor && !menu.blockSourceEvents && menu.sourceActor.contains(src)) {
return false;
}
}
return true;
},
_findMenu: function(item) {
for (let i = 0; i < this._menus.length; i++) {
let menudata = this._menus[i];
@@ -2276,41 +2155,7 @@ const PopupMenuManager = new Lang.Class({
return -1;
},
_onEventCapture: function(actor, event) {
if (!this.grabbed)
return false;
if (this._owner.menuEventFilter &&
this._owner.menuEventFilter(event))
return true;
if (this._didPop) {
this._didPop = false;
return true;
}
let activeMenuContains = this._eventIsOnActiveMenu(event);
let eventType = event.type();
if (eventType == Clutter.EventType.BUTTON_RELEASE) {
if (activeMenuContains) {
return false;
} else {
this._closeMenu();
return true;
}
} else if (eventType == Clutter.EventType.BUTTON_PRESS && !activeMenuContains) {
this._closeMenu();
return true;
} else if (!this._shouldBlockEvent(event)) {
return false;
}
return true;
},
_closeMenu: function() {
if (this._activeMenu != null)
this._activeMenu.close(BoxPointer.PopupAnimation.FULL);
_closeMenu: function(menu) {
menu.close(BoxPointer.PopupAnimation.FULL);
}
});

View File

@@ -194,15 +194,9 @@ const SearchResults = new Lang.Class({
expand: true,
x_align: St.Align.START,
y_align: St.Align.START });
this.actor.connect('notify::mapped', Lang.bind(this,
function() {
if (!this.actor.mapped)
return;
let adjustment = scrollView.vscroll.adjustment;
let direction = Overview.SwipeScrollDirection.VERTICAL;
Main.overview.setScrollAdjustment(adjustment, direction);
}));
let action = new Clutter.PanAction({ interpolate: true });
action.connect('pan', Lang.bind(this, this._onPan));
this.actor.add_action(action);
this._statusText = new St.Label({ style_class: 'search-statustext' });
this._statusBin = new St.Bin({ x_align: St.Align.MIDDLE,
@@ -219,6 +213,13 @@ const SearchResults = new Lang.Class({
this._defaultResult = null;
},
_onPan: function(action) {
let [dist, dx, dy] = action.get_motion_delta(0);
let adjustment = this.actor.vscroll.adjustment;
adjustment.value -= (dy / this.actor.height) * adjustment.page_size;
return false;
},
createProviderMeta: function(provider) {
let providerBox = new St.BoxLayout({ style_class: 'search-section',
vertical: true });

View File

@@ -21,7 +21,6 @@ const _modes = {
isLocked: false,
isGreeter: false,
isPrimary: false,
buttonLayout: ['button-layout', 'org.gnome.shell.overrides'],
unlockDialog: null,
components: [],
panel: {
@@ -102,29 +101,6 @@ const _modes = {
right: ['a11y', 'keyboard', 'volume', 'bluetooth',
'network', 'battery', 'userMenu']
}
},
'foo': {
hasOverview: true,
showCalendarEvents: true,
allowSettings: true,
allowExtensions: true,
hasRunDialog: true,
hasWorkspaces: true,
hasWindows: true,
hasNotifications: true,
isLocked: false,
isPrimary: true,
buttonLayout: ['button-layout', 'org.gnome.shell-foo.overrides'],
unlockDialog: imports.ui.unlockDialog.UnlockDialog,
components: ['networkAgent', 'polkitAgent', 'telepathyClient',
'keyring', 'recorder', 'autorunManager', 'automountManager'],
panel: {
left: ['activities', 'appMenu'],
center: ['dateMenu'],
right: ['a11y', 'keyboard', 'volume', 'bluetooth',
'network', 'battery', 'userMenu']
}
}
};

View File

@@ -66,24 +66,32 @@ const VolumeMenu = new Lang.Class({
this._onControlStateChanged();
},
scroll: function(direction) {
scroll: function(event) {
let direction = event.get_scroll_direction();
let currentVolume = this._output.volume;
let delta;
if (event.is_pointer_emulated())
return;
if (direction == Clutter.ScrollDirection.DOWN) {
let prev_muted = this._output.is_muted;
this._output.volume = Math.max(0, currentVolume - this._volumeMax * VOLUME_ADJUSTMENT_STEP);
if (this._output.volume < 1) {
this._output.volume = 0;
if (!prev_muted)
this._output.change_is_muted(true);
}
this._output.push_volume();
delta = -VOLUME_ADJUSTMENT_STEP;
} else if (direction == Clutter.ScrollDirection.UP) {
delta = +VOLUME_ADJUSTMENT_STEP;
} else if (direction == Clutter.ScrollDirection.SMOOTH) {
let [dx, dy] = event.get_scroll_delta();
// Use the same math as in the slider.
delta = -dy / 10;
}
else if (direction == Clutter.ScrollDirection.UP) {
this._output.volume = Math.min(this._volumeMax, currentVolume + this._volumeMax * VOLUME_ADJUSTMENT_STEP);
this._output.change_is_muted(false);
this._output.push_volume();
let prev_muted = this._output.is_muted;
this._output.volume = Math.max(0, currentVolume + this._volumeMax * delta);
if (this._output.volume < 1) {
this._output.volume = 0;
if (!prev_muted)
this._output.change_is_muted(true);
}
this._output.push_volume();
this._notifyVolumeChange();
},
@@ -242,6 +250,6 @@ const Indicator = new Lang.Class({
},
_onScrollEvent: function(actor, event) {
this._volumeMenu.scroll(event.get_scroll_direction());
this._volumeMenu.scroll(event);
}
});

View File

@@ -172,6 +172,7 @@ const UnlockDialog = new Lang.Class({
this._workSpinner = new Panel.AnimatedIcon('process-working.svg', LoginDialog.WORK_SPINNER_ICON_SIZE);
this._workSpinner.actor.opacity = 0;
this._workSpinner.actor.show();
this.allowCancel = false;
this.buttonLayout.visible = true;

View File

@@ -211,18 +211,19 @@ const ViewSelector = new Lang.Class({
return;
if(this._activePage) {
let oldPage = this._activePage;
Tweener.addTween(this._activePage,
{ opacity: 0,
time: 0.1,
transition: 'easeOutQuad',
onComplete: Lang.bind(this,
function() {
this._activePage.hide();
this._activePage = page;
oldPage.hide();
})
});
}
this._activePage = page;
page.show();
Tweener.addTween(page,
{ opacity: 255,

View File

@@ -9,7 +9,6 @@ const St = imports.gi.St;
const IconGrid = imports.ui.iconGrid;
const Layout = imports.ui.layout;
const Main = imports.ui.main;
const Panel = imports.ui.panel;
const Search = imports.ui.search;
// we could make these gsettings
@@ -54,9 +53,20 @@ const WandaIcon = new Lang.Class({
icon_size: iconSize });
}
this._animations = new Panel.Animation(this._imageFile, this._imgWidth, this._imgHeight, FISH_SPEED);
this._animations.play();
return this._animations.actor;
this._animations = St.TextureCache.get_default().load_sliced_image(this._imageFile, this._imgWidth, this._imgHeight);
this._animations.connect('notify::mapped', Lang.bind(this, function() {
if (this._animations.mapped && !this._timeoutId) {
this._timeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, FISH_SPEED, Lang.bind(this, this._update));
this._i = 0;
this._update();
} else if (!this._animations.mapped && this._timeoutId) {
GLib.source_remove(this._timeoutId);
this._timeoutId = 0;
}
}));
return this._animations;
},
_createIconTexture: function(size) {
@@ -64,7 +74,20 @@ const WandaIcon = new Lang.Class({
return;
this.parent(size);
}
},
_update: function() {
let n = this._animations.get_n_children();
if (n == 0) {
return true;
}
this._animations.get_child_at_index(this._i).hide();
this._i = (this._i + 1) % n;
this._animations.get_child_at_index(this._i).show();
return true;
},
});
const WandaIconBin = new Lang.Class({

View File

@@ -30,6 +30,9 @@ const CLOSE_BUTTON_FADE_TIME = 0.1;
const DRAGGING_WINDOW_OPACITY = 100;
const BUTTON_LAYOUT_SCHEMA = 'org.gnome.shell.overrides';
const BUTTON_LAYOUT_KEY = 'button-layout';
// When calculating a layout, we calculate the scale of windows and the percent
// of the available area the new layout uses. If the values for the new layout,
// when weighted with the values as below, are worse than the previous layout's,
@@ -262,23 +265,37 @@ const WindowClone = new Lang.Class({
_onScroll : function (actor, event) {
let direction = event.get_scroll_direction();
if (direction == Clutter.ScrollDirection.UP) {
let delta;
if (event.is_pointer_emulated())
return;
if (direction == Clutter.ScrollDirection.DOWN) {
delta = -SCROLL_SCALE_AMOUNT;
} else if (direction == Clutter.ScrollDirection.UP) {
delta = +SCROLL_SCALE_AMOUNT;
} else if (direction == Clutter.ScrollDirection.SMOOTH) {
let [dx, dy] = event.get_scroll_delta();
delta = -dy * 10;
}
if (delta > 0) {
if (this._zoomStep == undefined)
this._zoomStart();
if (this._zoomStep < 100) {
this._zoomStep += SCROLL_SCALE_AMOUNT;
this._zoomStep += delta;
this._zoomStep = Math.min(100, this._zoomStep);
this._zoomUpdate();
}
} else if (direction == Clutter.ScrollDirection.DOWN) {
} else if (delta < 0) {
if (this._zoomStep > 0) {
this._zoomStep -= SCROLL_SCALE_AMOUNT;
this._zoomStep += delta;
this._zoomStep = Math.max(0, this._zoomStep);
this._zoomUpdate();
}
if (this._zoomStep <= 0.0)
this._zoomEnd();
}
},
_zoomUpdate : function () {
@@ -551,8 +568,8 @@ const WindowOverlay = new Lang.Class({
let button = this.closeButton;
let title = this.title;
let settings = new Gio.Settings({ schema: Main.sessionMode.buttonLayout[1] });
let layout = settings.get_string(Main.sessionMode.buttonLayout[0]);
let settings = new Gio.Settings({ schema: BUTTON_LAYOUT_SCHEMA });
let layout = settings.get_string(BUTTON_LAYOUT_KEY);
let rtl = Clutter.get_default_text_direction() == Clutter.TextDirection.RTL;
let split = layout.split(":");

View File

@@ -128,11 +128,8 @@ const WorkspacesView = new Lang.Class({
continue;
let ws = new Workspace.Workspace(null, i);
let overviewSpacing = Main.overview._spacing;
ws.setGeometry(monitors[i].x + overviewSpacing/2,
monitors[i].y + overviewSpacing/2,
monitors[i].width - overviewSpacing,
monitors[i].height - overviewSpacing);
ws.setGeometry(monitors[i].x, monitors[i].y,
monitors[i].width, monitors[i].height);
global.overlay_group.add_actor(ws.actor);
this._extraWorkspaces.push(ws);
}
@@ -208,11 +205,11 @@ const WorkspacesView = new Lang.Class({
this._workspaces[w].positionWindows(Workspace.WindowPositionFlags.ANIMATE);
},
_scrollToActive: function(showAnimation) {
_scrollToActive: function() {
let active = global.screen.get_active_workspace_index();
this._updateWorkspaceActors(showAnimation);
this._updateScrollAdjustment(active, showAnimation);
this._updateWorkspaceActors(true);
this._updateScrollAdjustment(active);
},
// Update workspace actors parameters
@@ -270,26 +267,21 @@ const WorkspacesView = new Lang.Class({
}
},
_updateScrollAdjustment: function(index, showAnimation) {
_updateScrollAdjustment: function(index) {
if (this._scrolling)
return;
this._animatingScroll = true;
if (showAnimation) {
Tweener.addTween(this.scrollAdjustment, {
value: index,
time: WORKSPACE_SWITCH_TIME,
transition: 'easeOutQuad',
onComplete: Lang.bind(this,
function() {
this._animatingScroll = false;
})
});
} else {
this.scrollAdjustment.value = index;
this._animatingScroll = false;
}
Tweener.addTween(this.scrollAdjustment, {
value: index,
time: WORKSPACE_SWITCH_TIME,
transition: 'easeOutQuad',
onComplete: Lang.bind(this,
function() {
this._animatingScroll = false;
})
});
},
updateWorkspaces: function(oldNumWorkspaces, newNumWorkspaces) {
@@ -316,7 +308,7 @@ const WorkspacesView = new Lang.Class({
if (this._scrolling)
return;
this._scrollToActive(true);
this._scrollToActive();
},
_onDestroy: function() {
@@ -390,24 +382,11 @@ const WorkspacesView = new Lang.Class({
this._scrolling = true;
},
endSwipeScroll: function(result) {
endSwipeScroll: function() {
this._scrolling = false;
if (result == Overview.SwipeScrollResult.CLICK) {
let [x, y, mod] = global.get_pointer();
let actor = global.stage.get_actor_at_pos(Clutter.PickMode.ALL,
x, y);
// Only switch to the workspace when there's no application
// windows open. The problem is that it's too easy to miss
// an app window and get the wrong one focused.
let active = global.screen.get_active_workspace_index();
if (this._workspaces[active].isEmpty() &&
this.actor.contains(actor))
Main.overview.hide();
}
// Make sure title captions etc are shown as necessary
this._scrollToActive();
this._updateVisibility();
},
@@ -459,9 +438,23 @@ const WorkspacesDisplay = new Lang.Class({
this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
this.actor.connect('allocate', Lang.bind(this, this._allocate));
this.actor.connect('notify::mapped', Lang.bind(this, this._setupSwipeScrolling));
this.actor.connect('parent-set', Lang.bind(this, this._parentSet));
this.actor.set_clip_to_allocation(true);
let action = new Clutter.PanAction();
action.connect('pan', Lang.bind(this, this._onPan));
action.connect('gesture-begin', Lang.bind(this, function() {
for (let i = 0; i < this._workspacesViews.length; i++)
this._workspacesViews[i].startSwipeScroll();
return true;
}));
action.connect('gesture-end', Lang.bind(this, function() {
for (let i = 0; i < this._workspacesViews.length; i++)
this._workspacesViews[i].endSwipeScroll();
}));
Main.overview.addAction(action);
this.actor.connect('notify::mapped', Lang.bind(this, function() {
action.enabled = this.actor.mapped;
}));
let controls = new St.Bin({ style_class: 'workspace-controls',
request_mode: Clutter.RequestMode.WIDTH_FOR_HEIGHT,
@@ -534,6 +527,13 @@ const WorkspacesDisplay = new Lang.Class({
Lang.bind(this, this._updateSwitcherVisibility));
},
_onPan: function(action) {
let [dist, dx, dy] = action.get_motion_delta(0);
let adjustment = this._scrollAdjustment;
adjustment.value -= (dy / this.actor.height) * adjustment.page_size;
return false;
},
_updateSwitcherVisibility: function() {
this._thumbnailsBox.actor.visible =
this._settings.get_boolean('dynamic-workspaces') ||
@@ -643,33 +643,6 @@ const WorkspacesDisplay = new Lang.Class({
}
},
_setupSwipeScrolling: function() {
if (this._swipeScrollBeginId)
Main.overview.disconnect(this._swipeScrollBeginId);
this._swipeScrollBeginId = 0;
if (this._swipeScrollEndId)
Main.overview.disconnect(this._swipeScrollEndId);
this._swipeScrollEndId = 0;
if (!this.actor.mapped)
return;
let direction = Overview.SwipeScrollDirection.VERTICAL;
Main.overview.setScrollAdjustment(this._scrollAdjustment,
direction);
this._swipeScrollBeginId = Main.overview.connect('swipe-scroll-begin',
Lang.bind(this, function() {
for (let i = 0; i < this._workspacesViews.length; i++)
this._workspacesViews[i].startSwipeScroll();
}));
this._swipeScrollEndId = Main.overview.connect('swipe-scroll-end',
Lang.bind(this, function(overview, result) {
for (let i = 0; i < this._workspacesViews.length; i++)
this._workspacesViews[i].endSwipeScroll(result);
}));
},
_workspacesOnlyOnPrimaryChanged: function() {
this._workspacesOnlyOnPrimary = this._settings.get_boolean('workspaces-only-on-primary');
@@ -709,7 +682,6 @@ const WorkspacesDisplay = new Lang.Class({
this._scrollAdjustment = view.scrollAdjustment;
this._scrollAdjustment.connect('notify::value',
Lang.bind(this, this._scrollValueChanged));
this._setupSwipeScrolling();
}
this._workspacesViews.push(view);
}

136
po/as.po
View File

@@ -9,8 +9,8 @@ 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: 2012-11-26 14:01+0000\n"
"PO-Revision-Date: 2012-11-27 14:40+0530\n"
"POT-Creation-Date: 2012-11-26 09:33+0000\n"
"PO-Revision-Date: 2012-11-26 15:51+0530\n"
"Last-Translator: Nilamdyuti Goswami <ngoswami@redhat.com>\n"
"Language-Team: as_IN <kde-i18n-doc@kde.org>\n"
"Language: as_IN\n"
@@ -165,6 +165,7 @@ msgstr ""
"স্বচালিতভাৱে লুকুৱা অভাৰৰাইড কৰে।"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:15
#| msgid "Always show the 'Log out' menuitem in the user menu."
msgid "Show full name in the user menu"
msgstr "ব্যৱহাৰকাৰী মেনুত সম্পূৰ্ণ নাম দেখুৱাওক"
@@ -748,54 +749,58 @@ msgstr "কল"
msgid "File Transfer"
msgstr "ফাইল স্থানান্তৰ"
#: ../js/ui/components/telepathyClient.js:417
msgid "Chat"
msgstr "চেট"
#: ../js/ui/components/telepathyClient.js:394
msgid "Subscription request"
msgstr "স্বাক্ষৰণ অনুৰোধ"
#: ../js/ui/components/telepathyClient.js:477
#: ../js/ui/components/telepathyClient.js:430
msgid "Connection error"
msgstr "সংযোগ ত্ৰুটি"
#: ../js/ui/components/telepathyClient.js:491
msgid "Unmute"
msgstr "অমৌন কৰক"
#: ../js/ui/components/telepathyClient.js:477
#: ../js/ui/components/telepathyClient.js:491
msgid "Mute"
msgstr "মোন কৰক"
#. Translators: this is a time format string followed by the word "Yesterday". i.e. "14:30 on Yesterday"
#: ../js/ui/components/telepathyClient.js:932
#: ../js/ui/components/telepathyClient.js:946
#, no-c-format
msgid "<b>%H:%M</b> on Yesterday"
msgstr "<b>%H:%M</b> যোৱাকালী"
#. Translators: this is a time format string followed by a week day name. i.e. "14:30 on Monday
#: ../js/ui/components/telepathyClient.js:938
#: ../js/ui/components/telepathyClient.js:952
#, no-c-format
msgid "<b>%H:%M</b> on <b>%A</b>"
msgstr "<b>%A</b> ত <b>%H:%M</b>"
#. Translators: this is a time format in the style of "14:30 on Wednesday, May 25",
#. shown when you get a chat message in the same year
#: ../js/ui/components/telepathyClient.js:944
#: ../js/ui/components/telepathyClient.js:958
#, no-c-format
msgid "<b>%H:%M</b> on <b>%A</b>, <b>%B</b> <b>%d</b>"
msgstr "<b>%A</b> ত <b>%H:%M</b>, <b>%B</b> <b>%d</b>"
#. Translators: this is a time format in the style of "14:30 on Wednesday, May 25, 2012",
#. shown when you get a chat message in a different year
#: ../js/ui/components/telepathyClient.js:949
#: ../js/ui/components/telepathyClient.js:963
#, no-c-format
msgid "<b>%H:%M</b> on <b>%A</b>, <b>%B</b> <b>%d</b>, %Y"
msgstr "<b>%A</b> ত <b>%H:%M</b>, <b>%B</b> <b>%d</b>, %Y"
#. Translators: this is the other person changing their old IM name to their new
#. IM name.
#: ../js/ui/components/telepathyClient.js:977
#: ../js/ui/components/telepathyClient.js:991
#, c-format
msgid "%s is now known as %s"
msgstr "%s এতিয়া %s হিচাপে জনাজাত"
#. translators: argument is a room name like
#. * room@jabber.org for example.
#: ../js/ui/components/telepathyClient.js:1076
#: ../js/ui/components/telepathyClient.js:1090
#, c-format
msgid "Invitation to %s"
msgstr "%s লে নিমন্ত্ৰণ"
@@ -803,38 +808,38 @@ msgstr "%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:1084
#: ../js/ui/components/telepathyClient.js:1098
#, c-format
msgid "%s is inviting you to join %s"
msgstr "%s এ আপোনাক %s ত অংশগ্ৰহণ কৰিবলে আমন্ত্ৰণ জনাইছে"
#: ../js/ui/components/telepathyClient.js:1086
#: ../js/ui/components/telepathyClient.js:1125
#: ../js/ui/components/telepathyClient.js:1165
#: ../js/ui/components/telepathyClient.js:1228
#: ../js/ui/components/telepathyClient.js:1100
#: ../js/ui/components/telepathyClient.js:1139
#: ../js/ui/components/telepathyClient.js:1179
#: ../js/ui/components/telepathyClient.js:1242
msgid "Decline"
msgstr "নাকচ কৰক"
#: ../js/ui/components/telepathyClient.js:1087
#: ../js/ui/components/telepathyClient.js:1166
#: ../js/ui/components/telepathyClient.js:1229
#: ../js/ui/components/telepathyClient.js:1101
#: ../js/ui/components/telepathyClient.js:1180
#: ../js/ui/components/telepathyClient.js:1243
msgid "Accept"
msgstr "গ্ৰহন কৰক"
#. translators: argument is a contact name like Alice for example.
#: ../js/ui/components/telepathyClient.js:1117
#: ../js/ui/components/telepathyClient.js:1131
#, c-format
msgid "Video call from %s"
msgstr "%s ৰ পৰা ভিডিঅ' কল"
#. translators: argument is a contact name like Alice for example.
#: ../js/ui/components/telepathyClient.js:1120
#: ../js/ui/components/telepathyClient.js:1134
#, c-format
msgid "Call from %s"
msgstr "%s ৰ পৰা কল"
#. translators: this is a button label (verb), not a noun
#: ../js/ui/components/telepathyClient.js:1127
#: ../js/ui/components/telepathyClient.js:1141
msgid "Answer"
msgstr "উত্তৰ দিয়ক"
@@ -843,110 +848,110 @@ msgstr "উত্তৰ দিয়ক"
#. * file name. The string will be something
#. * like: "Alice is sending you test.ogg"
#.
#: ../js/ui/components/telepathyClient.js:1159
#: ../js/ui/components/telepathyClient.js:1173
#, c-format
msgid "%s is sending you %s"
msgstr "%s এ আপোনাক %s পঠাই আছে"
#. To translators: The parameter is the contact's alias
#: ../js/ui/components/telepathyClient.js:1194
#: ../js/ui/components/telepathyClient.js:1208
#, c-format
msgid "%s would like permission to see when you are online"
msgstr "আপুনি কেতিয়া অনলাইন আছে চাবলে %s এ অনুমতি বিচাৰিব"
#: ../js/ui/components/telepathyClient.js:1286
#: ../js/ui/components/telepathyClient.js:1300
msgid "Network error"
msgstr "নেটৱাৰ্ক ত্ৰুটি"
#: ../js/ui/components/telepathyClient.js:1288
#: ../js/ui/components/telepathyClient.js:1302
msgid "Authentication failed"
msgstr "প্ৰমাণীকৰণ ব্যৰ্থ"
#: ../js/ui/components/telepathyClient.js:1290
#: ../js/ui/components/telepathyClient.js:1304
msgid "Encryption error"
msgstr "ইনক্ৰিপষণ ত্ৰুটি"
#: ../js/ui/components/telepathyClient.js:1292
#: ../js/ui/components/telepathyClient.js:1306
msgid "Certificate not provided"
msgstr "প্ৰমাণপত্ৰ প্ৰদান কৰা হোৱা নাই"
#: ../js/ui/components/telepathyClient.js:1294
#: ../js/ui/components/telepathyClient.js:1308
msgid "Certificate untrusted"
msgstr "প্ৰমাণপত্ৰক ভৰষা কৰিব নোৱাৰি"
#: ../js/ui/components/telepathyClient.js:1296
#: ../js/ui/components/telepathyClient.js:1310
msgid "Certificate expired"
msgstr "প্ৰমাণপত্ৰৰ অৱসান ঘটিছে"
#: ../js/ui/components/telepathyClient.js:1298
#: ../js/ui/components/telepathyClient.js:1312
msgid "Certificate not activated"
msgstr "প্ৰমাণপত্ৰ সক্ৰিয় কৰা হোৱা নাই"
#: ../js/ui/components/telepathyClient.js:1300
#: ../js/ui/components/telepathyClient.js:1314
msgid "Certificate hostname mismatch"
msgstr "প্ৰমাণপত্ৰ হস্টনাম অমিল"
#: ../js/ui/components/telepathyClient.js:1302
#: ../js/ui/components/telepathyClient.js:1316
msgid "Certificate fingerprint mismatch"
msgstr "প্ৰমাণপত্ৰ ফিংগাৰপ্ৰিন্ট অমিল"
#: ../js/ui/components/telepathyClient.js:1304
#: ../js/ui/components/telepathyClient.js:1318
msgid "Certificate self-signed"
msgstr "প্ৰমাণপত্ৰ স্ব-স্বাক্ষৰীত"
#: ../js/ui/components/telepathyClient.js:1306
#: ../js/ui/components/telepathyClient.js:1320
msgid "Status is set to offline"
msgstr "অৱস্থা অফলাইনলে সংহতি কৰা হৈছে"
#: ../js/ui/components/telepathyClient.js:1308
#: ../js/ui/components/telepathyClient.js:1322
msgid "Encryption is not available"
msgstr "ইনক্ৰিপষণ উপলব্ধ নহয়"
#: ../js/ui/components/telepathyClient.js:1310
#: ../js/ui/components/telepathyClient.js:1324
msgid "Certificate is invalid"
msgstr "প্ৰমাণপত্ৰ অবৈধ"
#: ../js/ui/components/telepathyClient.js:1312
#: ../js/ui/components/telepathyClient.js:1326
msgid "Connection has been refused"
msgstr "সংযোগ নাকচ কৰা হৈছে"
#: ../js/ui/components/telepathyClient.js:1314
#: ../js/ui/components/telepathyClient.js:1328
msgid "Connection can't be established"
msgstr "সংযোগ স্থাপন কৰিব নোৱাৰি"
#: ../js/ui/components/telepathyClient.js:1316
#: ../js/ui/components/telepathyClient.js:1330
msgid "Connection has been lost"
msgstr "সংযোগ হেৰাইছে"
#: ../js/ui/components/telepathyClient.js:1318
#: ../js/ui/components/telepathyClient.js:1332
msgid "This account is already connected to the server"
msgstr "এই একাওন্ট ইতিমধ্যে চাৰ্ভাৰৰ সৈতে সংযোগিত"
#: ../js/ui/components/telepathyClient.js:1320
#: ../js/ui/components/telepathyClient.js:1334
msgid ""
"Connection has been replaced by a new connection using the same resource"
msgstr "সংযোগক একে সম্পদ ব্যৱহাৰ কৰি এটা নতুন সংযোগৰে প্ৰতিস্থাপন কৰা হৈছে"
#: ../js/ui/components/telepathyClient.js:1322
#: ../js/ui/components/telepathyClient.js:1336
msgid "The account already exists on the server"
msgstr "একাওন্ট ইতিমধ্যে চাৰ্ভাৰত উপস্থিত"
#: ../js/ui/components/telepathyClient.js:1324
#: ../js/ui/components/telepathyClient.js:1338
msgid "Server is currently too busy to handle the connection"
msgstr "চাৰ্ভাৰ সংযোগ ব্যৱস্থাপনা কৰিবলে বৰ্তমানে অতি ব্যস্ত"
#: ../js/ui/components/telepathyClient.js:1326
#: ../js/ui/components/telepathyClient.js:1340
msgid "Certificate has been revoked"
msgstr "প্ৰমাণপত্ৰ প্ৰত্যাহাৰ কৰা হৈছে"
#: ../js/ui/components/telepathyClient.js:1328
#: ../js/ui/components/telepathyClient.js:1342
msgid ""
"Certificate uses an insecure cipher algorithm or is cryptographically weak"
msgstr ""
"প্ৰমাণপত্ৰয় এটা অসুৰক্ষিত চিফাৰ এলগৰিথম ব্যৱহাৰ কৰে অথবা ক্ৰিপ্টোগ্ৰাফিয়ভাৱে "
"দুৰ্বল"
#: ../js/ui/components/telepathyClient.js:1330
#: ../js/ui/components/telepathyClient.js:1344
msgid ""
"The length of the server certificate, or the depth of the server certificate "
"chain, exceed the limits imposed by the cryptography library"
@@ -955,23 +960,26 @@ msgstr ""
"ক্ৰিপ্টোগ্ৰাফী "
"লাইব্ৰেৰীয়ে প্ৰণয়ন কৰা সীমাসমূহত অতিক্ৰম কৰে"
#: ../js/ui/components/telepathyClient.js:1332
#: ../js/ui/components/telepathyClient.js:1346
msgid "Internal error"
msgstr "অভ্যন্তৰীক ত্ৰুটি"
#. translators: argument is the account name, like
#. * name@jabber.org for example.
#: ../js/ui/components/telepathyClient.js:1342
#: ../js/ui/components/telepathyClient.js:1356
#, c-format
msgid "Unable to connect to %s"
msgstr "%s ৰ সৈতে সংযোগ কৰিবলে অক্ষম"
msgid "Connection to %s failed"
msgstr "%s ে সংযোগ ব্যৰ্থ"
#: ../js/ui/components/telepathyClient.js:1347
#| msgid "Edit account"
msgid "View account"
msgstr "একাওন্ট দৰ্শন কৰক"
#: ../js/ui/components/telepathyClient.js:1365
msgid "Reconnect"
msgstr "পুনৰ সংযোগ কৰক"
#: ../js/ui/components/telepathyClient.js:1387
#: ../js/ui/components/telepathyClient.js:1366
msgid "Edit account"
msgstr "একাওন্ট সম্পাদন কৰক"
#: ../js/ui/components/telepathyClient.js:1411
msgid "Unknown reason"
msgstr "অজ্ঞাত কাৰণ"
@@ -1844,18 +1852,6 @@ msgstr "অবিকল্পিত"
msgid "Authentication dialog was dismissed by the user"
msgstr "প্ৰমাণীকৰণ ডাইলগ ব্যৱহাৰকাৰী দ্বাৰা নাকচ কৰা হৈছিল"
#~ msgid "Subscription request"
#~ msgstr "স্বাক্ষৰণ অনুৰোধ"
#~ msgid "Connection error"
#~ msgstr "সংযোগ ত্ৰুটি"
#~ msgid "Connection to %s failed"
#~ msgstr "%s লে সংযোগ ব্যৰ্থ"
#~ msgid "Reconnect"
#~ msgstr "পুনৰ সংযোগ কৰক"
#~ msgid "Browse Files..."
#~ msgstr "ফাইলসমূহ ব্ৰাউছ কৰক..."

View File

@@ -174,6 +174,8 @@ shell_prefs_init (void)
OVERRIDES_SCHEMA);
meta_prefs_override_preference_schema ("workspaces-only-on-primary",
OVERRIDES_SCHEMA);
meta_prefs_override_preference_schema ("button-layout",
OVERRIDES_SCHEMA);
meta_prefs_override_preference_schema ("edge-tiling",
OVERRIDES_SCHEMA);
meta_prefs_override_preference_schema ("focus-change-on-pointer-rest",

View File

@@ -1007,54 +1007,6 @@ shell_global_end_modal (ShellGlobal *global,
meta_plugin_end_modal (global->plugin, timestamp);
}
/**
* shell_global_create_pointer_barrier:
* @global: a #ShellGlobal
* @x1: left X coordinate
* @y1: top Y coordinate
* @x2: right X coordinate
* @y2: bottom Y coordinate
* @directions: The directions we're allowed to pass through
*
* If supported by X creates a pointer barrier.
*
* Return value: value you can pass to shell_global_destroy_pointer_barrier()
*/
guint32
shell_global_create_pointer_barrier (ShellGlobal *global,
int x1, int y1, int x2, int y2,
int directions)
{
#if HAVE_XFIXESCREATEPOINTERBARRIER
return (guint32)
XFixesCreatePointerBarrier (global->xdisplay,
DefaultRootWindow (global->xdisplay),
x1, y1,
x2, y2,
directions,
0, NULL);
#else
return 0;
#endif
}
/**
* shell_global_destroy_pointer_barrier:
* @global: a #ShellGlobal
* @barrier: a pointer barrier
*
* Destroys the @barrier created by shell_global_create_pointer_barrier().
*/
void
shell_global_destroy_pointer_barrier (ShellGlobal *global, guint32 barrier)
{
#if HAVE_XFIXESCREATEPOINTERBARRIER
g_return_if_fail (barrier > 0);
XFixesDestroyPointerBarrier (global->xdisplay, (PointerBarrier)barrier);
#endif
}
/* Code to close all file descriptors before we exec; copied from gspawn.c in GLib.
*
* Authors: Padraig O'Briain, Matthias Clasen, Lennart Poettering

View File

@@ -70,15 +70,6 @@ void shell_global_set_cursor (ShellGlobal *global,
ShellCursor type);
void shell_global_unset_cursor (ShellGlobal *global);
guint32 shell_global_create_pointer_barrier (ShellGlobal *global,
int x1,
int y1,
int x2,
int y2,
int directions);
void shell_global_destroy_pointer_barrier (ShellGlobal *global,
guint32 barrier);
void shell_global_get_pointer (ShellGlobal *global,
int *x,
int *y,

View File

@@ -665,6 +665,45 @@ st_scroll_view_allocate (ClutterActor *actor,
}
static void
adjust_with_delta (StAdjustment *adj,
gdouble delta)
{
gdouble new_value, page_size, scroll_unit;
g_object_get (adj,
"page-size", &page_size,
NULL);
scroll_unit = pow (page_size, 2.0 / 3.0);
new_value = st_adjustment_get_value (adj) + delta * scroll_unit;
st_adjustment_set_value (adj, new_value);
}
static void
adjust_with_direction (StAdjustment *adj,
ClutterScrollDirection direction)
{
gdouble delta;
switch (direction)
{
case CLUTTER_SCROLL_UP:
case CLUTTER_SCROLL_LEFT:
delta = -1.0;
break;
case CLUTTER_SCROLL_RIGHT:
case CLUTTER_SCROLL_DOWN:
delta = 1.0;
break;
case CLUTTER_SCROLL_SMOOTH:
g_assert_not_reached ();
break;
}
adjust_with_delta (adj, delta);
}
static void
st_scroll_view_style_changed (StWidget *widget)
{
@@ -687,57 +726,32 @@ st_scroll_view_scroll_event (ClutterActor *self,
ClutterScrollEvent *event)
{
StScrollViewPrivate *priv = ST_SCROLL_VIEW (self)->priv;
gdouble value, step, hvalue, vvalue, delta_x, delta_y;
/* don't handle scroll events if requested not to */
if (!priv->mouse_scroll)
return FALSE;
switch (event->direction)
{
case CLUTTER_SCROLL_SMOOTH:
clutter_event_get_scroll_delta ((ClutterEvent *)event,
&delta_x, &delta_y);
g_object_get (priv->hadjustment,
"value", &hvalue,
NULL);
g_object_get (priv->vadjustment,
"value", &vvalue,
NULL);
break;
case CLUTTER_SCROLL_UP:
case CLUTTER_SCROLL_DOWN:
g_object_get (priv->vadjustment,
"step-increment", &step,
"value", &value,
NULL);
break;
case CLUTTER_SCROLL_LEFT:
case CLUTTER_SCROLL_RIGHT:
g_object_get (priv->hadjustment,
"step-increment", &step,
"value", &value,
NULL);
break;
}
/* throw away this garbage event. we want smooth scrolling. */
if (clutter_event_is_pointer_emulated ((ClutterEvent *) event))
return TRUE;
switch (event->direction)
{
case CLUTTER_SCROLL_SMOOTH:
st_adjustment_set_value (priv->hadjustment, hvalue + delta_x);
st_adjustment_set_value (priv->vadjustment, vvalue + delta_y);
{
gdouble delta_x, delta_y;
clutter_event_get_scroll_delta ((ClutterEvent *)event, &delta_x, &delta_y);
adjust_with_delta (priv->hadjustment, delta_x);
adjust_with_delta (priv->vadjustment, delta_y);
}
break;
case CLUTTER_SCROLL_UP:
st_adjustment_set_value (priv->vadjustment, value - step);
break;
case CLUTTER_SCROLL_DOWN:
st_adjustment_set_value (priv->vadjustment, value + step);
adjust_with_direction (priv->vadjustment, event->direction);
break;
case CLUTTER_SCROLL_LEFT:
st_adjustment_set_value (priv->hadjustment, value - step);
break;
case CLUTTER_SCROLL_RIGHT:
st_adjustment_set_value (priv->hadjustment, value + step);
adjust_with_direction (priv->hadjustment, event->direction);
break;
}

View File

@@ -316,6 +316,7 @@ st_widget_dispose (GObject *gobject)
if (priv->theme_node)
{
g_object_run_dispose (G_OBJECT (priv->theme_node));
g_object_unref (priv->theme_node);
priv->theme_node = NULL;
}