mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-23 00:41:02 +00:00
Apply fix for situtation where we block unnecessarily because we have queued
windows messages which have already arrived. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@22270 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
53cd80e4c4
commit
17a02dbff8
2 changed files with 149 additions and 157 deletions
|
@ -1,3 +1,9 @@
|
|||
2006-01-09 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/win32/GSRunLoopCtxt.m: Apply patch by Jeremy Bettis with
|
||||
fixups for intentation/formatting and minor correction to avoid waiting
|
||||
for an event when we have handled one in the current run of the loop.
|
||||
|
||||
2006-01-09 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/NSPropertyList.m: When generating binary plist, fix bug
|
||||
|
|
|
@ -136,6 +136,135 @@ static const NSMapTableValueCallBacks WatcherMapValueCallBacks =
|
|||
return self;
|
||||
}
|
||||
|
||||
/*
|
||||
* If there is no msgTarget || there is a generic watcher (watching hwnd == 0),
|
||||
* loop through all events, and send them to the correct
|
||||
* watcher (if there are any) and then process the rest right here.
|
||||
* else if there is a msgTarget,
|
||||
* then loop through watchers and process for their
|
||||
* hwnd's only. Then call msgTarget to clean up the rest of them.
|
||||
* Return a flag to say whether any messages were handled.
|
||||
*/
|
||||
- (BOOL) processAllWindowsMessages:(int)num_winMsgs within: (NSArray*)contexts
|
||||
{
|
||||
MSG msg;
|
||||
GSRunLoopWatcher *generic = nil;
|
||||
unsigned i;
|
||||
BOOL handled = NO;
|
||||
|
||||
if (num_winMsgs > 0)
|
||||
{
|
||||
generic = NSMapGet(winMsgMap,0);
|
||||
}
|
||||
|
||||
if (msgTarget == nil || (generic != nil && generic->_invalidated == NO))
|
||||
{
|
||||
while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
|
||||
{
|
||||
if (msg.message == WM_QUIT)
|
||||
{
|
||||
Class c = NSClassFromString(@"NSApplication");
|
||||
|
||||
if (c == 0)
|
||||
{
|
||||
[NSException raise: NSGenericException
|
||||
format: @"Received WM_QUIT"];
|
||||
}
|
||||
else
|
||||
{
|
||||
SEL s = NSSelectorFromString(@"sharedApplication");
|
||||
id o = [c performSelector: s];
|
||||
|
||||
s = NSSelectorFromString(@"terminate:");
|
||||
[o performSelector: s withObject: nil];
|
||||
}
|
||||
}
|
||||
|
||||
if (num_winMsgs > 0)
|
||||
{
|
||||
HANDLE handle;
|
||||
GSRunLoopWatcher *watcher;
|
||||
|
||||
handle = msg.hwnd;
|
||||
watcher = (GSRunLoopWatcher*)NSMapGet(winMsgMap,
|
||||
(void*)handle);
|
||||
if (watcher == nil || watcher->_invalidated == YES)
|
||||
{
|
||||
handle = 0; // Generic
|
||||
watcher
|
||||
= (GSRunLoopWatcher*)NSMapGet(winMsgMap, (void*)handle);
|
||||
}
|
||||
if (watcher != nil && watcher->_invalidated == NO)
|
||||
{
|
||||
i = [contexts count];
|
||||
while (i-- > 0)
|
||||
{
|
||||
GSRunLoopCtxt *c = [contexts objectAtIndex: i];
|
||||
|
||||
if (c != self)
|
||||
{
|
||||
[c endEvent: (void*)handle type: ET_WINMSG];
|
||||
}
|
||||
}
|
||||
completed = YES;
|
||||
handled = YES;
|
||||
/*
|
||||
* The watcher is still valid - so call the
|
||||
* receiver's event handling method.
|
||||
*/
|
||||
(*watcher->handleEvent)(watcher->receiver,
|
||||
eventSel, watcher->data, watcher->type,
|
||||
(void*)(gsaddr)&msg, mode);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (num_winMsgs > 0)
|
||||
{
|
||||
unsigned num = num_winMsgs;
|
||||
NSMapEnumerator hEnum;
|
||||
HANDLE handle;
|
||||
GSRunLoopWatcher *watcher;
|
||||
|
||||
hEnum = NSEnumerateMapTable(winMsgMap);
|
||||
while (NSNextMapEnumeratorPair(&hEnum, &handle, (void**)&watcher))
|
||||
{
|
||||
if (watcher->_invalidated == NO)
|
||||
{
|
||||
while (PeekMessage(&msg, handle, 0, 0, PM_REMOVE))
|
||||
{
|
||||
i = [contexts count];
|
||||
while (i-- > 0)
|
||||
{
|
||||
GSRunLoopCtxt *c = [contexts objectAtIndex: i];
|
||||
|
||||
if (c != self)
|
||||
{
|
||||
[c endEvent: (void*)handle type: ET_WINMSG];
|
||||
}
|
||||
}
|
||||
completed = YES;
|
||||
handled = YES;
|
||||
(*watcher->handleEvent)(watcher->receiver,
|
||||
eventSel, watcher->data, watcher->type,
|
||||
(void*)(gsaddr)&msg, mode);
|
||||
}
|
||||
}
|
||||
num--;
|
||||
}
|
||||
NSEndMapTableEnumeration(&hEnum);
|
||||
}
|
||||
completed = YES;
|
||||
[msgTarget performSelector: msgSelector withObject: nil];
|
||||
}
|
||||
return handled;
|
||||
}
|
||||
|
||||
- (BOOL) pollUntil: (int)milliseconds within: (NSArray*)contexts
|
||||
{
|
||||
NSMapEnumerator hEnum;
|
||||
|
@ -147,7 +276,6 @@ static const NSMapTableValueCallBacks WatcherMapValueCallBacks =
|
|||
void *handle;
|
||||
int wait_timeout;
|
||||
DWORD wait_return;
|
||||
BOOL do_wait;
|
||||
|
||||
// Set timeout how much time should wait
|
||||
if (milliseconds >= 0)
|
||||
|
@ -243,166 +371,24 @@ static const NSMapTableValueCallBacks WatcherMapValueCallBacks =
|
|||
NSEndMapTableEnumeration(&hEnum);
|
||||
num_handles = i;
|
||||
|
||||
do_wait = YES;
|
||||
do
|
||||
/* Clear all the windows messages first before we wait,
|
||||
* since MsgWaitForMultipleObjects only signals on NEW messages
|
||||
*/
|
||||
if ([self processAllWindowsMessages: num_winMsgs within: contexts] == YES)
|
||||
{
|
||||
wait_return = MsgWaitForMultipleObjects(num_handles, handleArray,
|
||||
NO, wait_timeout, QS_ALLINPUT);
|
||||
NSDebugMLLog(@"NSRunLoop", @"wait returned %d", wait_return);
|
||||
wait_timeout = 0; // Processed something ... no need to wait.
|
||||
}
|
||||
|
||||
wait_return = MsgWaitForMultipleObjects(num_handles, handleArray,
|
||||
NO, wait_timeout, QS_ALLINPUT);
|
||||
NSDebugMLLog(@"NSRunLoop", @"wait returned %d", wait_return);
|
||||
|
||||
// if there are windows message
|
||||
if (wait_return == WAIT_OBJECT_0 + num_handles)
|
||||
{
|
||||
MSG msg;
|
||||
INT bRet;
|
||||
|
||||
if (msgTarget == nil)
|
||||
{
|
||||
bRet = PeekMessage(&msg, 0, 0, 0, PM_REMOVE);
|
||||
if (bRet != 0)
|
||||
{
|
||||
if (msg.message == WM_QUIT)
|
||||
{
|
||||
Class c = NSClassFromString(@"NSApplication");
|
||||
|
||||
if (c == 0)
|
||||
{
|
||||
[NSException raise: NSGenericException
|
||||
format: @"Received WM_QUIT"];
|
||||
}
|
||||
else
|
||||
{
|
||||
SEL s = NSSelectorFromString(@"sharedApplication");
|
||||
id o = [c performSelector: s];
|
||||
|
||||
s = NSSelectorFromString(@"terminate:");
|
||||
[o performSelector: s withObject: nil];
|
||||
}
|
||||
}
|
||||
|
||||
if (num_winMsgs > 0)
|
||||
{
|
||||
HANDLE handle;
|
||||
|
||||
handle = msg.hwnd;
|
||||
watcher = (GSRunLoopWatcher*)NSMapGet(winMsgMap,
|
||||
(void*)handle);
|
||||
if (watcher == nil || watcher->_invalidated == YES)
|
||||
{
|
||||
handle = 0; // Generic
|
||||
watcher = (GSRunLoopWatcher*)NSMapGet(winMsgMap,
|
||||
(void*)handle);
|
||||
}
|
||||
if (watcher != nil && watcher->_invalidated == NO)
|
||||
{
|
||||
i = [contexts count];
|
||||
while (i-- > 0)
|
||||
{
|
||||
GSRunLoopCtxt *c = [contexts objectAtIndex: i];
|
||||
|
||||
if (c != self)
|
||||
{
|
||||
[c endEvent: (void*)handle type: ET_WINMSG];
|
||||
}
|
||||
}
|
||||
completed = YES;
|
||||
/*
|
||||
* The watcher is still valid - so call the
|
||||
* receiver's event handling method.
|
||||
*/
|
||||
(*watcher->handleEvent)(watcher->receiver,
|
||||
eventSel, watcher->data, watcher->type,
|
||||
(void*)(gsaddr)&msg, mode);
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (num_winMsgs > 0)
|
||||
{
|
||||
GSRunLoopWatcher *generic = nil;
|
||||
unsigned num = num_winMsgs;
|
||||
|
||||
hEnum = NSEnumerateMapTable(winMsgMap);
|
||||
while (NSNextMapEnumeratorPair(&hEnum, &handle,
|
||||
(void**)&watcher))
|
||||
{
|
||||
if (watcher->_invalidated == NO)
|
||||
{
|
||||
if (handle == 0 && num > 1)
|
||||
{
|
||||
// Let window specific watchers have first attempt.
|
||||
generic = watcher;
|
||||
continue;
|
||||
}
|
||||
bRet = PeekMessage(&msg, handle, 0, 0, PM_REMOVE);
|
||||
if (bRet != 0)
|
||||
{
|
||||
i = [contexts count];
|
||||
while (i-- > 0)
|
||||
{
|
||||
GSRunLoopCtxt *c = [contexts objectAtIndex: i];
|
||||
|
||||
if (c != self)
|
||||
{
|
||||
[c endEvent: (void*)handle
|
||||
type: ET_WINMSG];
|
||||
}
|
||||
}
|
||||
NSEndMapTableEnumeration(&hEnum);
|
||||
completed = YES;
|
||||
/*
|
||||
* The watcher is still valid - so call the
|
||||
* receiver's event handling method.
|
||||
*/
|
||||
(*watcher->handleEvent)(watcher->receiver,
|
||||
eventSel, watcher->data, watcher->type,
|
||||
(void*)(gsaddr)&msg, mode);
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
num--;
|
||||
}
|
||||
NSEndMapTableEnumeration(&hEnum);
|
||||
if (generic != nil && generic->_invalidated == NO)
|
||||
{
|
||||
bRet = PeekMessage(&msg, 0, 0, 0, PM_REMOVE);
|
||||
if (bRet != 0)
|
||||
{
|
||||
i = [contexts count];
|
||||
while (i-- > 0)
|
||||
{
|
||||
GSRunLoopCtxt *c = [contexts objectAtIndex: i];
|
||||
|
||||
if (c != self)
|
||||
{
|
||||
[c endEvent: (void*)0 type: ET_WINMSG];
|
||||
}
|
||||
}
|
||||
NSEndMapTableEnumeration(&hEnum);
|
||||
completed = YES;
|
||||
(*generic->handleEvent)(watcher->receiver,
|
||||
eventSel, watcher->data, watcher->type,
|
||||
(void*)(gsaddr)&msg, mode);
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
}
|
||||
completed = YES;
|
||||
[msgTarget performSelector: msgSelector withObject: nil];
|
||||
return NO;
|
||||
}
|
||||
--wait_timeout;
|
||||
}
|
||||
else
|
||||
{
|
||||
do_wait = NO;
|
||||
}
|
||||
if (wait_return == WAIT_OBJECT_0 + num_handles)
|
||||
{
|
||||
[self processAllWindowsMessages: num_winMsgs within: contexts];
|
||||
return NO;
|
||||
}
|
||||
while (do_wait && (wait_timeout >= 0));
|
||||
|
||||
// check wait errors
|
||||
if (wait_return == WAIT_FAILED)
|
||||
|
|
Loading…
Reference in a new issue