Debug/fix new window specific handling code ... allow generic (null)

window handle only if window specific code is not called.


git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@21921 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
CaS 2005-10-30 12:08:54 +00:00
parent a2e1c719cc
commit 7cf5a73522
4 changed files with 56 additions and 33 deletions

View file

@ -139,9 +139,10 @@ typedef enum {
/** /**
* Callback message sent to object when the event it it waiting * Callback message sent to object when the event it it waiting
* for occurs. The 'data' and 'type' valueds are those passed in the * for occurs. The 'data' and 'type' valueds are those passed in the
* original -addEvent:type:watcher:forMode: method. * original -addEvent:type:watcher:forMode: method.<br />
* The 'extra' value may be additional data returned depending * The 'extra' value may be additional data returned depending
* on the type of event. * on the type of event. In the case of ET_WINMSG 'extra' is a pointer
* to a windows <code>MSG</code> structure containing the received event.
*/ */
- (void) receivedEvent: (void*)data - (void) receivedEvent: (void*)data
type: (RunLoopEventType)type type: (RunLoopEventType)type
@ -202,21 +203,15 @@ typedef enum {
#if defined(__MINGW32__) #if defined(__MINGW32__)
/** /**
* Interface that add method to set target for win32 messages.<br /> * Obsolete interface that add method to set target for win32 messages.<br />
*/ */
@interface NSRunLoop(mingw32) @interface NSRunLoop(mingw32)
/** /** Deprecated ... will be removed
* Adds a target to the loop in the specified mode for the
* win32 messages.<br />
* Only a target+selector is added in one mode. Successive
* calls overwrite the previous.<br />
*/ */
- (void) addMsgTarget: (id)target - (void) addMsgTarget: (id)target
withMethod: (SEL)selector withMethod: (SEL)selector
forMode: (NSString*)mode; forMode: (NSString*)mode;
/** /** Deprecated ... will be removed
* Delete the target of the loop in the specified mode for the
* win32 messages.<br />
*/ */
- (void) removeMsgForMode: (NSString*)mode; - (void) removeMsgForMode: (NSString*)mode;
@end @end

View file

@ -83,6 +83,8 @@ static const NSMapTableValueCallBacks WatcherMapValueCallBacks =
{ {
case ET_HANDLE: case ET_HANDLE:
break; break;
case ET_WINMSG:
break;
default: default:
NSLog(@"Ending an event of unkown type (%d)", type); NSLog(@"Ending an event of unkown type (%d)", type);
break; break;
@ -206,7 +208,7 @@ static const NSMapTableValueCallBacks WatcherMapValueCallBacks =
} }
break; break;
case ET_WINMSG: case ET_WINMSG:
winMsgMap = (HANDLE)(int)info->data; handle = (HANDLE)(int)info->data;
NSMapInsert(winMsgMap, (void*)handle, info); NSMapInsert(winMsgMap, (void*)handle, info);
num_winMsgs++; num_winMsgs++;
break; break;
@ -234,11 +236,11 @@ static const NSMapTableValueCallBacks WatcherMapValueCallBacks =
handleArray[i++] = (HANDLE)handle; handleArray[i++] = (HANDLE)handle;
} }
NSEndMapTableEnumeration(&hEnum); NSEndMapTableEnumeration(&hEnum);
num_handles = i;
do_wait = YES; do_wait = YES;
do do
{ {
num_handles = i;
wait_return = MsgWaitForMultipleObjects(num_handles, handleArray, wait_return = MsgWaitForMultipleObjects(num_handles, handleArray,
NO, wait_timeout, QS_ALLINPUT); NO, wait_timeout, QS_ALLINPUT);
NSDebugMLLog(@"NSRunLoop", @"wait returned %d", wait_return); NSDebugMLLog(@"NSRunLoop", @"wait returned %d", wait_return);
@ -251,12 +253,21 @@ static const NSMapTableValueCallBacks WatcherMapValueCallBacks =
if (num_winMsgs > 0) if (num_winMsgs > 0)
{ {
GSRunLoopWatcher *generic = nil;
unsigned num = num_winMsgs;
hEnum = NSEnumerateMapTable(winMsgMap); hEnum = NSEnumerateMapTable(winMsgMap);
while (NSNextMapEnumeratorPair(&hEnum, &handle, (void**)&watcher)) while (NSNextMapEnumeratorPair(&hEnum, &handle, (void**)&watcher))
{ {
if (watcher->_invalidated == NO) if (watcher->_invalidated == NO)
{ {
bRet = PeekMessage(&msg, handle, 0, 0, PM_NOREMOVE); 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) if (bRet != 0)
{ {
i = [contexts count]; i = [contexts count];
@ -269,28 +280,53 @@ static const NSMapTableValueCallBacks WatcherMapValueCallBacks =
[c endEvent: (void*)handle type: ET_WINMSG]; [c endEvent: (void*)handle type: ET_WINMSG];
} }
} }
/*
* The watcher is still valid - so call its receivers
* event handling method.
*/
(*watcher->handleEvent)(watcher->receiver,
eventSel, watcher->data, watcher->type,
(void*)(gsaddr)handle, mode);
NSEndMapTableEnumeration(&hEnum); NSEndMapTableEnumeration(&hEnum);
NSZoneFree(NSDefaultMallocZone(), handleArray); NSZoneFree(NSDefaultMallocZone(), handleArray);
completed = YES; 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; return NO;
} }
} }
num--;
} }
NSEndMapTableEnumeration(&hEnum); 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);
NSZoneFree(NSDefaultMallocZone(), handleArray);
completed = YES;
(*generic->handleEvent)(watcher->receiver,
eventSel, watcher->data, watcher->type,
(void*)(gsaddr)&msg, mode);
return NO;
}
}
} }
if (msgTarget != nil) if (msgTarget != nil)
{ {
[msgTarget performSelector: msgSelector withObject: nil];
NSZoneFree(NSDefaultMallocZone(), handleArray); NSZoneFree(NSDefaultMallocZone(), handleArray);
completed = YES; completed = YES;
[msgTarget performSelector: msgSelector withObject: nil];
return NO; return NO;
} }

View file

@ -25,6 +25,7 @@ SEL eventSel; /* Initialized in [NSRunLoop +initialize] */
{ {
case ET_RPORT: type = aType; break; case ET_RPORT: type = aType; break;
case ET_HANDLE: type = aType; break; case ET_HANDLE: type = aType; break;
case ET_WINMSG: type = aType; break;
default: default:
[NSException raise: NSInvalidArgumentException [NSException raise: NSInvalidArgumentException
format: @"NSRunLoop - unknown event type"]; format: @"NSRunLoop - unknown event type"];

View file

@ -1,21 +1,17 @@
#include "config.h" #include "config.h"
#include "GNUstepBase/preface.h" #include "GNUstepBase/preface.h"
#include "Foundation/NSRunLoop.h" #include "Foundation/NSRunLoop.h"
#include "Foundation/NSDebug.h"
#include "../GSRunLoopCtxt.h" #include "../GSRunLoopCtxt.h"
@implementation NSRunLoop (mingw32) @implementation NSRunLoop (mingw32)
/**
* Adds a target to the loop in the specified mode for the
* win32 messages.<br />
* Only a target+selector is added in one mode. Successive
* calls overwrite the previous.<br />
*/
- (void) addMsgTarget: (id)target - (void) addMsgTarget: (id)target
withMethod: (SEL)selector withMethod: (SEL)selector
forMode: (NSString*)mode forMode: (NSString*)mode
{ {
GSRunLoopCtxt *context; GSRunLoopCtxt *context;
// GSOnceMLog(@"This method is deprecated, use -addEvent:type:watcher:forMode");
context = NSMapGet(_contextMap, mode); context = NSMapGet(_contextMap, mode);
if (context == nil) if (context == nil)
{ {
@ -26,11 +22,6 @@
context->msgTarget = target; context->msgTarget = target;
context->msgSelector = selector; context->msgSelector = selector;
} }
/**
* Delete the target of the loop in the specified mode for the
* win32 messages.<br />
*/
- (void) removeMsgForMode: (NSString*)mode - (void) removeMsgForMode: (NSString*)mode
{ {
GSRunLoopCtxt *context; GSRunLoopCtxt *context;