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;