diff --git a/Headers/Foundation/NSRunLoop.h b/Headers/Foundation/NSRunLoop.h index 772597ec4..4d8879e4e 100644 --- a/Headers/Foundation/NSRunLoop.h +++ b/Headers/Foundation/NSRunLoop.h @@ -139,9 +139,10 @@ typedef enum { /** * Callback message sent to object when the event it it waiting * for occurs. The 'data' and 'type' valueds are those passed in the - * original -addEvent:type:watcher:forMode: method. + * original -addEvent:type:watcher:forMode: method.
* 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 MSG structure containing the received event. */ - (void) receivedEvent: (void*)data type: (RunLoopEventType)type @@ -202,21 +203,15 @@ typedef enum { #if defined(__MINGW32__) /** - * Interface that add method to set target for win32 messages.
+ * Obsolete interface that add method to set target for win32 messages.
*/ @interface NSRunLoop(mingw32) -/** - * Adds a target to the loop in the specified mode for the - * win32 messages.
- * Only a target+selector is added in one mode. Successive - * calls overwrite the previous.
+/** Deprecated ... will be removed */ - (void) addMsgTarget: (id)target withMethod: (SEL)selector forMode: (NSString*)mode; -/** - * Delete the target of the loop in the specified mode for the - * win32 messages.
+/** Deprecated ... will be removed */ - (void) removeMsgForMode: (NSString*)mode; @end diff --git a/Source/win32/GSRunLoopCtxt.m b/Source/win32/GSRunLoopCtxt.m index 47ec41f99..a82e0b469 100644 --- a/Source/win32/GSRunLoopCtxt.m +++ b/Source/win32/GSRunLoopCtxt.m @@ -83,6 +83,8 @@ static const NSMapTableValueCallBacks WatcherMapValueCallBacks = { case ET_HANDLE: break; + case ET_WINMSG: + break; default: NSLog(@"Ending an event of unkown type (%d)", type); break; @@ -206,7 +208,7 @@ static const NSMapTableValueCallBacks WatcherMapValueCallBacks = } break; case ET_WINMSG: - winMsgMap = (HANDLE)(int)info->data; + handle = (HANDLE)(int)info->data; NSMapInsert(winMsgMap, (void*)handle, info); num_winMsgs++; break; @@ -234,11 +236,11 @@ static const NSMapTableValueCallBacks WatcherMapValueCallBacks = handleArray[i++] = (HANDLE)handle; } NSEndMapTableEnumeration(&hEnum); + num_handles = i; do_wait = YES; do { - num_handles = i; wait_return = MsgWaitForMultipleObjects(num_handles, handleArray, NO, wait_timeout, QS_ALLINPUT); NSDebugMLLog(@"NSRunLoop", @"wait returned %d", wait_return); @@ -251,12 +253,21 @@ static const NSMapTableValueCallBacks WatcherMapValueCallBacks = if (num_winMsgs > 0) { + GSRunLoopWatcher *generic = nil; + unsigned num = num_winMsgs; + hEnum = NSEnumerateMapTable(winMsgMap); while (NSNextMapEnumeratorPair(&hEnum, &handle, (void**)&watcher)) { 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) { i = [contexts count]; @@ -269,28 +280,53 @@ static const NSMapTableValueCallBacks WatcherMapValueCallBacks = [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); NSZoneFree(NSDefaultMallocZone(), handleArray); 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); + NSZoneFree(NSDefaultMallocZone(), handleArray); + completed = YES; + (*generic->handleEvent)(watcher->receiver, + eventSel, watcher->data, watcher->type, + (void*)(gsaddr)&msg, mode); + return NO; + } + } } if (msgTarget != nil) { - [msgTarget performSelector: msgSelector withObject: nil]; NSZoneFree(NSDefaultMallocZone(), handleArray); completed = YES; + [msgTarget performSelector: msgSelector withObject: nil]; return NO; } diff --git a/Source/win32/GSRunLoopWatcher.m b/Source/win32/GSRunLoopWatcher.m index 9f678d9fa..99f93308e 100644 --- a/Source/win32/GSRunLoopWatcher.m +++ b/Source/win32/GSRunLoopWatcher.m @@ -25,6 +25,7 @@ SEL eventSel; /* Initialized in [NSRunLoop +initialize] */ { case ET_RPORT: type = aType; break; case ET_HANDLE: type = aType; break; + case ET_WINMSG: type = aType; break; default: [NSException raise: NSInvalidArgumentException format: @"NSRunLoop - unknown event type"]; diff --git a/Source/win32/NSRunLoopWin32.m b/Source/win32/NSRunLoopWin32.m index e31b5f843..9643365d3 100644 --- a/Source/win32/NSRunLoopWin32.m +++ b/Source/win32/NSRunLoopWin32.m @@ -1,21 +1,17 @@ #include "config.h" #include "GNUstepBase/preface.h" #include "Foundation/NSRunLoop.h" +#include "Foundation/NSDebug.h" #include "../GSRunLoopCtxt.h" @implementation NSRunLoop (mingw32) -/** - * Adds a target to the loop in the specified mode for the - * win32 messages.
- * Only a target+selector is added in one mode. Successive - * calls overwrite the previous.
- */ - (void) addMsgTarget: (id)target withMethod: (SEL)selector forMode: (NSString*)mode { GSRunLoopCtxt *context; + // GSOnceMLog(@"This method is deprecated, use -addEvent:type:watcher:forMode"); context = NSMapGet(_contextMap, mode); if (context == nil) { @@ -26,11 +22,6 @@ context->msgTarget = target; context->msgSelector = selector; } - -/** - * Delete the target of the loop in the specified mode for the - * win32 messages.
- */ - (void) removeMsgForMode: (NSString*)mode { GSRunLoopCtxt *context;