131
133
// This means we pump the main loop dozens of times a second resulting in many screen
132
134
// redraws and significantly slow down the running task.
135
137
Gdk.Threads.Enter();
138
Stopwatch sw = new Stopwatch ();
137
141
// Check for less than zero in case there's a system time change
138
142
var diff = DateTime.UtcNow - lastPendingEvents;
139
143
if (diff > TimeSpan.FromMilliseconds (500) || diff < TimeSpan.Zero) {
140
144
lastPendingEvents = DateTime.UtcNow;
141
while (Gtk.Application.EventsPending () && --n > 0) {
145
while (Gtk.Application.EventsPending () && sw.ElapsedMilliseconds < maxLength) {
142
146
Gtk.Application.RunIteration (false);
146
152
Gdk.Threads.Leave();
147
153
guiDispatcher ();
321
327
LoggingService.LogError ("{0} {1}\nCaller stack not available. Define the environment variable MONODEVELOP_DISPATCH_DEBUG to enable caller stack capture.", errormsg, msg.Exception.ToString ());
333
/// Runs a delegate at regular intervals
336
/// An animation object. It can be disposed to stop the animation.
338
/// <param name='animation'>
339
/// The delegate to run. The return value if the number of milliseconds to wait until the delegate is run again.
340
/// The execution will stop if the deletgate returns 0
342
public static IDisposable RunAnimation (Func<int> animation)
344
var ainfo = new AnimationInfo () {
345
AnimationFunc = animation,
346
NextDueTime = DateTime.Now
349
activeAnimations.Add (ainfo);
351
// Don't immediately run the animation if we are going to do it in less than 20ms
352
if (animationHandle == 0 || currentAnimationSpan > 20)
353
ProcessAnimations ();
357
static List<AnimationInfo> activeAnimations = new List<AnimationInfo> ();
358
static uint animationHandle;
359
static DateTime nextDueTime;
360
static int currentAnimationSpan;
362
class AnimationInfo: IDisposable {
363
public Func<int> AnimationFunc;
364
public DateTime NextDueTime;
366
public void Dispose ()
368
DispatchService.StopAnimation (this);
372
static bool ProcessAnimations ()
374
List<AnimationInfo> toDelete = null;
376
DateTime now = DateTime.Now;
377
nextDueTime = DateTime.MaxValue;
379
foreach (var a in activeAnimations) {
380
if (a.NextDueTime <= now) {
381
int ms = a.AnimationFunc ();
383
if (toDelete == null)
384
toDelete = new List<AnimationInfo> ();
386
a.NextDueTime = DateTime.MaxValue;
388
a.NextDueTime = DateTime.Now + TimeSpan.FromMilliseconds (ms);
390
if (a.NextDueTime < nextDueTime)
391
nextDueTime = a.NextDueTime;
394
if (toDelete != null) {
395
foreach (var a in toDelete)
396
activeAnimations.Remove (a);
399
if (nextDueTime == DateTime.MaxValue) {
400
// No more animations
405
int nms = (int) (nextDueTime - DateTime.Now).TotalMilliseconds;
409
// Don't re-schedule if the current time span is more or less the same as the previous one
410
if (animationHandle != 0 && Math.Abs (nms - currentAnimationSpan) <= 3)
413
currentAnimationSpan = nms;
414
animationHandle = GLib.Timeout.Add ((uint)currentAnimationSpan, ProcessAnimations);
418
static void StopAnimation (AnimationInfo a)
420
activeAnimations.Remove (a);
421
if (activeAnimations.Count == 0 && animationHandle != 0) {
422
GLib.Source.Remove (animationHandle);
325
430
public delegate void MessageHandler ();