[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)
{