Implement orderedWindows/orderedDocument using direct retrieval of z-order. Implement runModal to execute on main thread if not. Fix NSCell/NSButtonCell title value storage behavior. Create platform window on main thread. Fix memory leak in drag&drop for Win32. Finer grained locking on cgl/window flushing

This commit is contained in:
Christopher Lloyd 2011-03-28 16:19:16 -04:00
parent 2dab550273
commit 6b86753a5e
19 changed files with 145 additions and 128 deletions

View File

@ -88,8 +88,8 @@ typedef enum {
NSDockTile *_dockTile;
NSMutableArray *_modalStack;
NSMutableArray *_orderedDocuments;
NSMutableArray *_orderedWindows;
NSMutableArray *_orderedDocuments; // get rid of
NSMutableArray *_orderedWindows; // get rid of
NSTimer *_attentionTimer;
}
@ -210,8 +210,6 @@ typedef enum {
-(void)_windowDidBecomeActive:(NSWindow *)window;
-(void)_windowWillBecomeDeactive:(NSWindow *)window;
-(void)_windowDidBecomeDeactive:(NSWindow *)window;
-(void)_windowOrderingChange:(NSWindowOrderingMode)place forWindow:(NSWindow *)window relativeTo:(NSWindow *)relativeWindow;
-(void)_updateOrderedDocuments;
@end

View File

@ -131,8 +131,6 @@ id NSApp=nil;
_display=[[NSDisplay currentDisplay] retain];
_windows=[NSMutableArray new];
_orderedWindows=[NSMutableArray new];
_orderedDocuments=[NSMutableArray new];
_mainMenu=nil;
_dockTile=[[NSDockTile alloc] initWithOwner:self];
@ -248,13 +246,20 @@ id NSApp=nil;
}
-(NSArray *)orderedDocuments {
return _orderedDocuments;
NSMutableArray *result=[NSMutableArray array];
NSArray *orderedWindows=[self orderedWindows];
for(NSWindow *checkWindow in orderedWindows){
NSDocument *checkDocument=[[checkWindow windowController] document];
if(checkDocument!=nil)
[result addObject:checkDocument];
}
return result;
}
-(NSArray *)orderedWindows {
#if 0
return _orderedWindows;
#else
extern NSArray *CGSOrderedWindowNumbers();
NSMutableArray *result=[NSMutableArray array];
@ -268,7 +273,6 @@ id NSApp=nil;
}
return result;
#endif
}
-(void)preventWindowOrdering {
@ -746,8 +750,9 @@ id NSApp=nil;
[_modalStack addObject:session];
[window _hideMenuViewIfNeeded];
if(![window isVisible])
if(![window isVisible]){
[window center];
}
[window makeKeyAndOrderFront:self];
return session;
@ -792,19 +797,34 @@ id NSApp=nil;
[[_modalStack lastObject] stopModalWithCode:code];
}
-(int)runModalForWindow:(NSWindow *)window {
-(void)_mainThreadRunModalForWindow:(NSMutableDictionary *)values {
NSWindow *window=[values objectForKey:@"NSWindow"];
NSModalSession session=[self beginModalSessionForWindow:window];
int result;
while((result=[NSApp runModalSession:session])==NSRunContinuesResponse)
while((result=[NSApp runModalSession:session])==NSRunContinuesResponse){
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}
[self endModalSession:session];
return result;
[values setObject:[NSNumber numberWithInteger:result] forKey:@"result"];
}
-(int)runModalForWindow:(NSWindow *)window {
NSMutableDictionary *values=[NSMutableDictionary dictionary];
[values setObject:window forKey:@"NSWindow"];
[self performSelectorOnMainThread:@selector(_mainThreadRunModalForWindow:) withObject:values waitUntilDone:YES modes:[NSArray arrayWithObject:NSDefaultRunLoopMode]];
NSNumber *result=[values objectForKey:@"result"];
return [result integerValue];
}
-(void)stopModal {
[self stopModalWithCode:NSRunStoppedResponse];
}
@ -1096,66 +1116,6 @@ standardAboutPanel] retain];
[_windows addObject:window];
}
-(void)_windowOrderingChange:(NSWindowOrderingMode)place forWindow:(NSWindow *)window relativeTo:(NSWindow *)relativeWindow {
NSUInteger index, count;
[_orderedWindows removeObjectIdenticalTo: window];
switch (place) {
case NSWindowAbove:
if (relativeWindow == nil) {
index = 0;
} else {
index = [_orderedWindows indexOfObject: relativeWindow];
if (index == NSNotFound) {
index = 0;
}
}
[_orderedWindows insertObject: window atIndex: index];
break;
case NSWindowBelow:
if (relativeWindow == nil) {
[_orderedWindows addObject: window];
} else {
index = [_orderedWindows indexOfObject: relativeWindow];
if (index == NSNotFound) {
[_orderedWindows addObject: window];
} else {
[_orderedWindows insertObject: window atIndex: index+1];
}
}
break;
default:
break;
}
if ([[window windowController] document]) {
[self _updateOrderedDocuments];
}
}
-(void)_updateOrderedDocuments {
NSUInteger i, count = [_orderedWindows count];
NSWindowController *controller;
NSDocument *document;
NSWindow *window;
[_orderedDocuments removeAllObjects];
for (i = 0; i < count; i++) {
window = [_orderedWindows objectAtIndex: i];
controller = [window windowController];
document = [controller document];
if (document) {
[_orderedDocuments addObject: document];
}
}
}
-(void)_windowWillBecomeActive:(NSWindow *)window {
[_attentionTimer invalidate];
_attentionTimer=nil;

View File

@ -59,7 +59,6 @@ typedef enum {
} NSGradientType;
@interface NSButtonCell : NSActionCell {
id _titleOrAttributedTitle;
NSImage *_normalImage;
NSString *_alternateTitle;
NSImage *_alternateImage;

View File

@ -90,6 +90,7 @@ enum {
NSWritingDirection _writingDirection;
int _cellType;
NSFormatter *_formatter;
id _titleOrAttributedTitle;
id _representedObject;
NSControlSize _controlSize;
NSFocusRingType _focusRingType;

View File

@ -292,7 +292,10 @@ NSString * const NSWindowDidAnimateNotification=@"NSWindowDidAnimateNotification
[_platformWindow setTitle:title];
}
-(CGWindow *)platformWindow {
/*
There are issues when creating a Win32 handle on a non-main thread, so we always do it on the main thread
*/
-(void)_createPlatformWindowOnMainThread {
if(_platformWindow==nil){
if([self isKindOfClass:[NSPanel class]])
_platformWindow=[[[NSDisplay currentDisplay] panelWithFrame: _frame styleMask:_styleMask backingType:_backingType] retain];
@ -306,6 +309,12 @@ NSString * const NSWindowDidAnimateNotification=@"NSWindowDidAnimateNotification
[[NSDraggingManager draggingManager] registerWindow:self dragTypes:nil];
}
}
-(CGWindow *)platformWindow {
if(_platformWindow==nil){
[self performSelectorOnMainThread:@selector(_createPlatformWindowOnMainThread) withObject:nil waitUntilDone:YES modes:[NSArray arrayWithObject:NSDefaultRunLoopMode]];
}
return _platformWindow;
}
@ -1838,11 +1847,11 @@ NSString * const NSWindowDidAnimateNotification=@"NSWindowDidAnimateNotification
may be the right place to do this, maybe not, further investigation is
required
*/
[self displayIfNeeded];
// this is here since it would seem that doing this any earlier will not work.
if(![self isKindOfClass:[NSPanel class]] && ![self isExcludedFromWindowsMenu]) {
[NSApp changeWindowsItem:self title:_title filename:NO];
[NSApp _windowOrderingChange: NSWindowAbove forWindow: self relativeTo: [NSApp windowWithWindowNumber:relativeTo]];
}
break;
@ -1861,7 +1870,6 @@ NSString * const NSWindowDidAnimateNotification=@"NSWindowDidAnimateNotification
// this is here since it would seem that doing this any earlier will not work.
if(![self isKindOfClass:[NSPanel class]] && ![self isExcludedFromWindowsMenu]) {
[NSApp changeWindowsItem:self title:_title filename:NO];
[NSApp _windowOrderingChange: NSWindowBelow forWindow: self relativeTo: [NSApp windowWithWindowNumber:relativeTo]];
}
break;
@ -1870,7 +1878,6 @@ NSString * const NSWindowDidAnimateNotification=@"NSWindowDidAnimateNotification
[[self platformWindow] hideWindow];
if (![self isKindOfClass:[NSPanel class]]) {
[NSApp removeWindowsItem:self];
[NSApp _windowOrderingChange: NSWindowOut forWindow: self relativeTo: nil];
}
break;
}

View File

@ -157,7 +157,6 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
-(void)setDocument:(NSDocument *)document {
_document=document;
[NSApp _updateOrderedDocuments];
}
-(id)document {

View File

@ -0,0 +1,7 @@
#import <AppKit/NSWindow.h>
@interface NSWindow(scripting)
-(NSInteger)orderedIndex;
@end

View File

@ -0,0 +1,18 @@
#import <AppKit/NSWindowScripting.h>
#import <AppKit/NSApplication.h>
@implementation NSWindow(scripting)
-(NSInteger)orderedIndex {
NSInteger result=[[NSApp orderedWindows] indexOfObjectIdenticalTo:self];
/* Documentation says orderedIndex is zero based, but tests say it is 1 based
Possible there is a window at 0 which is not in -[NSApp windows] ? Either way, available windows are 1 based.
*/
if(result!=NSNotFound)
result+=1;
return result;
}
@end

View File

@ -362,13 +362,16 @@ if(NSDebugEnabled) NSCLog("%s %d %s %p",__FILE__,__LINE__,__PRETTY_FUNCTION__,co
If we SwapBuffers() and read from the front buffer we get junk because the swapbuffers may not be
complete. Read from GL_BACK.
*/
CGLLockContext(context);
CGLLockContext(context);
CGLSetCurrentContext(context);
CGLSetCurrentContext(context);
[context->overlay flushBuffer];
CGLUnlockContext(context);
[context->overlay readBuffer];
CGLUnlockContext(context);
[[context->overlay window] flushOverlay:context->overlay];
return kCGLNoError;
}

View File

@ -1041,7 +1041,7 @@ NSArray *CGSOrderedWindowNumbers(){
while(check!=NULL){
Win32Window *platformWindow=GetProp(check,"self");
if(platformWindow!=nil)
if(platformWindow!=nil && [platformWindow isKindOfClass:[Win32Window class]])
[result addObject:[NSNumber numberWithInteger:[platformWindow windowNumber]]];
check=GetNextWindow(check,GW_HWNDNEXT);

View File

@ -29,6 +29,9 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
-(void)registerWindow:(NSWindow *)window dragTypes:(NSArray *)dragTypes {
Win32IDropTargetServer *target=[[[Win32IDropTargetServer alloc] initWithWindow:(Win32Window *)[window platformWindow]] autorelease];
if(target==nil) // RegisterDragDrop fails sometimes, unresolved.
return;
[_dropTargets addObject:target];
}

View File

@ -22,9 +22,12 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
[super initAsIDropTarget];
_window=window;
if((result=RegisterDragDrop([_window windowHandle],[self iUknown]))!=S_OK)
NSLog(@"RegisterDragDrop failed with %d",result);
if((result=RegisterDragDrop([_window windowHandle],[self iUknown]))!=S_OK){
NSLog(@"RegisterDragDrop failed with %d, handle=%p",result,[_window windowHandle]);
[super dealloc];
return nil;
}
return self;
}

View File

@ -135,7 +135,7 @@ static IEnumFORMATETCVtbl IEnumFORMATETCVTable={
-initWithVtable:(void *)vtable interfaceIdentifier:(LPOLESTR)identifier {
_capacity=1;
_count=1;
_interfaces=NSZoneMalloc([self zone],sizeof(Win32COMObject)*_capacity);
_interfaces=NSZoneMalloc(NULL,sizeof(Win32COMObject)*_capacity);
_interfaces[0].vtable=vtable;
_interfaces[0].object=self;
if(IIDFromString(identifier,&_interfaces[0].iid)!=S_OK){
@ -144,6 +144,12 @@ static IEnumFORMATETCVtbl IEnumFORMATETCVTable={
return self;
}
-(void)dealloc {
if(_interfaces!=NULL)
NSZoneFree(NULL,_interfaces);
[super dealloc];
}
-initAsIDropTarget {
return [self initWithVtable:&IDropTargetVTable
interfaceIdentifier:OLESTR("{00000122-0000-0000-C000-000000000046}")];

View File

@ -187,7 +187,10 @@ static const char *Win32ClassNameForStyleMask(unsigned styleMask,bool hasShadow)
_handle=NULL;
}
-initWithFrame:(CGRect)frame styleMask:(unsigned)styleMask isPanel:(BOOL)isPanel backingType:(CGSBackingStoreType)backingType {
FOUNDATION_EXPORT id NSThreadMainThreadId();
-initWithFrame:(CGRect)frame styleMask:(unsigned)styleMask isPanel:(BOOL)isPanel backingType:(CGSBackingStoreType)backingType {
InitializeCriticalSection(&_lock);
_frame=frame;
_level=kCGNormalWindowLevel;
@ -620,7 +623,7 @@ i=count;
O2Rect overFrame=[overlay frame];
O2Surface_DIBSection *overSurface=[overlay validSurface];
if(backingSurface!=nil && overFrame.size.width>0 && overFrame.size.height>0){
if(backingSurface!=nil){
BLENDFUNCTION blend;
blend.BlendOp=AC_SRC_OVER;
@ -634,16 +637,17 @@ i=count;
}
}
[self flushBuffer];
[self unlock];
[self flushBuffer];
}
-(void)disableFlushWindow {
// _disableFlushWindow++;
_disableFlushWindow++;
}
-(void)enableFlushWindow {
// _disableFlushWindow--;
_disableFlushWindow--;
}
-(void)flushBuffer {
@ -653,7 +657,6 @@ i=count;
return;
O2Point fromPoint;
if([self isLayeredWindow]){
if(_backingContext!=nil){
O2Surface_DIBSection *surface=[self resultSurface:&fromPoint];
@ -802,6 +805,7 @@ i=count;
[_delegate platformWindowWillMove:self];
[self _GetWindowRectDidSize:NO];
[_delegate platformWindowDidMove:self];
return 0;
}

View File

@ -29,7 +29,7 @@ void CGLGenBuffers(GLsizei n,GLuint *buffers) {
}
void CGLDeleteBuffers(GLsizei n,const GLuint *buffers) {
PFNGLDELETEBUFFERSPROC function=(PFNGLGENBUFFERSPROC)wglGetProcAddress("glDeleteBuffers");
PFNGLDELETEBUFFERSPROC function=(PFNGLDELETEBUFFERSPROC)wglGetProcAddress("glDeleteBuffers");
if(function==NULL){
if(NSDebugEnabled)

View File

@ -29,7 +29,7 @@
-(void)setOpaque:(BOOL)value;
-(void)flushBuffer;
-(void)readBuffer;
-(O2Surface *)validSurface;
@end

View File

@ -67,7 +67,7 @@
return;
// 0's are silently ignored per spec.
if(_bufferObjects!=NULL) // nVidia driver will crash if bufferObjects is NULL, does not conform to spec.
if(_numberOfBuffers>0 && _bufferObjects!=NULL) // nVidia driver will crash if bufferObjects is NULL, does not conform to spec.
CGLDeleteBuffers(_numberOfBuffers,_bufferObjects);
if(_bufferObjects!=NULL)
@ -135,10 +135,7 @@ static inline uint32_t premultiplyPixel(uint32_t value){
return _surface;
}
-(void)flushBuffer {
if(_width==0 || _height==0){
return;
}
-(void)readBuffer {
[self validateBuffersIfNeeded];
@ -219,9 +216,7 @@ static inline uint32_t premultiplyPixel(uint32_t value){
row+=rowCount;
}
CGLBindBuffer(GL_PIXEL_PACK_BUFFER,0);
[_window flushOverlay:self];
#if 0
if(_usePixelBuffer){
CGLBindBuffer(GL_PIXEL_PACK_BUFFER,0);

View File

@ -661,30 +661,34 @@ static NSMapTable *pathToObject=NULL;
if([table length]==0)
table=@"Localizable";
dictionary=[_localizedTables objectForKey:table];
// NSLocalizedString needs to be thread safe.
if(dictionary==nil){
NSString *path;
NSString *contents=nil;
@synchronized(self){
dictionary=[_localizedTables objectForKey:table];
if(_localizedTables==nil)
_localizedTables=[[NSMutableDictionary alloc] init];
if(dictionary==nil){
NSString *path;
NSString *contents=nil;
if(_localizedTables==nil)
_localizedTables=[[NSMutableDictionary alloc] init];
if((path=[self pathForResource:table ofType:@"strings"])!=nil)
if((contents=[NSString stringWithContentsOfFile:path])!=nil){
NS_DURING
dictionary=[contents propertyListFromStringsFileFormat];
NS_HANDLER
dictionary=nil;
NS_ENDHANDLER
}
if((path=[self pathForResource:table ofType:@"strings"])!=nil)
if((contents=[NSString stringWithContentsOfFile:path])!=nil){
NS_DURING
dictionary=[contents propertyListFromStringsFileFormat];
NS_HANDLER
dictionary=nil;
NS_ENDHANDLER
}
if(dictionary==nil)
dictionary=[NSDictionary dictionary];
if(dictionary==nil)
dictionary=[NSDictionary dictionary];
[_localizedTables setObject:dictionary forKey:table];
[_localizedTables setObject:dictionary forKey:table];
}
}
if((result=[dictionary objectForKey:key])==nil)
result=(value!=nil && [value isEqual:@""] == NO)?value:key;

View File

@ -115,11 +115,21 @@ void O2DeviceContextEstablishDeviceSpacePath_gdi(HDC dc,O2Path *path,O2AffineTra
EndPath(dc);
}
void O2DeviceContextClipReset_gdi(HDC dc) {
void O2DeviceContextClipReset_gdi(HDC dc) {
// These two should effectively be the same, an the latter is preferred. But needs testing. Possibly not working (e.g. AC)
#if 1
HRGN region=CreateRectRgn(0,0,GetDeviceCaps(dc,HORZRES),GetDeviceCaps(dc,VERTRES));
if(!SelectClipRgn(dc,region)){
if(NSDebugEnabled)
NSLog(@"SelectClipRgn failed (%i), HORZRES=%i,VERTRES=%i", GetLastError(),GetDeviceCaps(dc,HORZRES),GetDeviceCaps(dc,VERTRES));
}
DeleteObject(region);
#else
if(!SelectClipRgn(dc,NULL)){
if(NSDebugEnabled)
NSLog(@"SelectClipRgn failed (%i), HORZRES=%i,VERTRES=%i", GetLastError(),GetDeviceCaps(dc,HORZRES),GetDeviceCaps(dc,VERTRES));
}
#endif
}
void O2DeviceContextClipToPath_gdi(HDC dc,O2Path *path,O2AffineTransform xform,O2AffineTransform deviceXFORM,BOOL evenOdd){