bug-gnustep
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] NSSavePanel.m -beginSheetForDirectory::::::


From: Alexander Malmberg
Subject: Re: [PATCH] NSSavePanel.m -beginSheetForDirectory::::::
Date: Sun, 14 Mar 2004 01:42:00 +0100

Fred Kiefer wrote:
> Alexander Malmberg wrote:
> > This sounds like a misunderstanding. I wasn't talking about apple's
[snip]
> 
> Ok, now I see the other way your sentence could be read and was surely
> meant to be understood. Sorry for reading this different.

Sorry about the confusion. /me makes note to write clearer...

> As for the technical issue, what you wanted to document, as stated in
> one of your previous mails, is fully suffient.

OK. I'll go ahead and do that. :)

> There is one thing, that I really don't understand, which is why the
> Apple documentation make a big difference between -abortModal and all
> the -stopModalWithCode: calls. There must be a bit more to this.

I think it's because of NSRunLoop quirks. Currently, GNUstep's NSRunLoop
won't start a new run loop iteration when a timer is triggered. Instead,
the timer's action runs, but the run loop continues blocking for input
without running any performers, etc.

This means that there are a bunch of things you can't reliably do in
timers. -stopModalWithCode: is one of them; the stop won't be noticed
until the next iteration, and there won't be a next iteration until
something happens to a file descriptor. -abortModal uses exceptions to
try to get around this. My guess is that cocoa/OPENSTEP has/had similar
(in their effect on timers, at least) quirks in their NSRunLoop
implementations.

(This also breaks periodic events, which is why NSTextView's
auto-scrolling is jittery. I believe that it also breaks periodic
updating of views in subtle ways, but I haven't tested that yet.)

I think the best way of fixing this is to fix timers in NSRunLoop (iow,
making them first class NSRunLoop citizens). I've attached a patch that
does this. I've been using it locally for a few months without any
problems. It makes NSTextView's auto-scrolling nice and smooth, and it
means that we don't need to treat -abortModal in any special way.
However, this is tricky stuff, so comments are welcome! :)

- Alexander Malmberg
Index: NSRunLoop.m
===================================================================
RCS file: /cvsroot/gnustep/gnustep/core/base/Source/NSRunLoop.m,v
retrieving revision 1.111
diff -u -r1.111 NSRunLoop.m
--- NSRunLoop.m 28 Oct 2003 11:10:23 -0000      1.111
+++ NSRunLoop.m 14 Mar 2004 00:42:49 -0000
@@ -1705,13 +1705,12 @@
  */
 - (NSDate*) limitDateForMode: (NSString*)mode
 {
-  extern NSTimer       *GSHousekeeper();
+  extern NSTimer       *GSHousekeeper(void);
   GSRunLoopCtxt                *context = NSMapGet(_contextMap, mode);
   NSDate               *when = nil;
 
   if (context != nil)
     {
-      NSTimer          *min_timer = nil;
       GSRunLoopWatcher *min_watcher = nil;
       NSString         *savedMode = _currentMode;
       CREATE_AUTORELEASE_POOL(arp);
@@ -1724,7 +1723,7 @@
 
          while (GSIArrayCount(timers) != 0)
            {
-             min_timer = GSIArrayItemAtIndex(timers, 0).obj;
+             NSTimer *min_timer = GSIArrayItemAtIndex(timers, 0).obj;
              if (timerInvalidated(min_timer) == YES)
                {
                  GSIArrayRemoveItemAtIndex(timers, 0);
@@ -1732,6 +1731,9 @@
                  continue;
                }
 
+             if (!when)
+               when = [timerDate(min_timer) copy];
+
              if ([timerDate(min_timer) timeIntervalSinceNow] > 0)
                {
                  break;
@@ -1749,7 +1751,6 @@
                {
                  RELEASE(min_timer);
                }
-             min_timer = nil;
              GSNotifyASAP();           /* Post notifications. */
            }
 
@@ -1825,12 +1826,11 @@
 
          /*
           * If there is nothing being watched, and no valid timers
-          * other than the housekeeper, we set min_timer to nil so
+          * other than the housekeeper, we set when to nil so
           * that the housekeeper timer does not keep the runloop
           * active.  It's a special case set up in NSThread.m
           */
-         if (min_watcher == nil && min_timer != nil
-           && min_timer == GSHousekeeper())
+         if (min_watcher == nil && when)
            {
              unsigned count = GSIArrayCount(timers);
 
@@ -1844,7 +1844,7 @@
                }
              if (GSIArrayCount(timers) == 1)
                {
-                 min_timer = nil;
+                 DESTROY(when);
                }
            }
 
@@ -1860,19 +1860,22 @@
       RELEASE(arp);
 
       /*
-       * If there are timers - set limit date to the earliest of them.
+       * If there are timers, when is already set to the limit date of the
+       * earliest of them (and retained!).
        * If there are watchers, set the limit date to that of the earliest
        * watcher (or leave it as the date of the earliest timer if that is
        * before the watchers limit).
        */
-      if (min_timer != nil)
+      if (when)
        {
-         when = timerDate(min_timer);
          if (min_watcher != nil
            && [min_watcher->_date compare: when] == NSOrderedAscending)
            {
+             RELEASE(when);
              when = min_watcher->_date;
            }
+         else
+           AUTORELEASE(when);
        }
       else if (min_watcher != nil)
        {

reply via email to

[Prev in Thread] Current Thread [Next in Thread]