From ab8add681efc1ca3bb005d03877a9a43a714dd6f Mon Sep 17 00:00:00 2001 From: Francisco Ryan Tolmasky I Date: Tue, 11 Aug 2009 01:13:33 -0700 Subject: [PATCH] A number of fixes and improvements to the platform window subsystem. Reviewed by me. --- AppKit/CPApplication.j | 7 + AppKit/CPCollectionView.j | 9 +- AppKit/CPDragServer.j | 90 ++++++---- AppKit/CPEvent.j | 12 ++ AppKit/CPMenu.j | 98 ++++++----- AppKit/CPPopUpButton.j | 14 +- AppKit/CPScreen.j | 16 ++ AppKit/CPWindow/CPWindow.j | 185 +++++++++++++++------ AppKit/CPWindow/_CPWindowView.j | 16 +- AppKit/Cib/_CPCibCustomView.j | 2 +- AppKit/Platform/CPPlatform.j | 5 + AppKit/Platform/CPPlatformWindow.j | 55 ++++-- AppKit/Platform/DOM/CPPlatformWindow+DOM.j | 33 ++-- 13 files changed, 376 insertions(+), 166 deletions(-) create mode 100644 AppKit/CPScreen.j diff --git a/AppKit/CPApplication.j b/AppKit/CPApplication.j index 54b424754..901fca539 100644 --- a/AppKit/CPApplication.j +++ b/AppKit/CPApplication.j @@ -403,6 +403,8 @@ CPRunContinuesResponse = -1002; */ - (void)sendEvent:(CPEvent)anEvent { + _currentEvent = anEvent; + // Check if this is a candidate for key equivalent... if ([anEvent type] == CPKeyDown && [anEvent modifierFlags] & (CPCommandKeyMask | CPControlKeyMask) && @@ -670,6 +672,11 @@ CPRunContinuesResponse = -1002; _eventListeners.push(_CPEventListenerMake(aMask, function (anEvent) { objj_msgSend(aTarget, aSelector, anEvent); })); } +- (CPEvent)currentEvent +{ + return _currentEvent; +} + // Managing Sheets /*! diff --git a/AppKit/CPCollectionView.j b/AppKit/CPCollectionView.j index e65435fbe..62069c8e1 100644 --- a/AppKit/CPCollectionView.j +++ b/AppKit/CPCollectionView.j @@ -93,6 +93,8 @@ unsigned _numberOfColumns; id _delegate; + + CPEvent _mouseDownEvent; } - (id)initWithFrame:(CGRect)aFrame @@ -528,13 +530,16 @@ - (void)mouseDown:(CPEvent)anEvent { + _mouseDownEvent = anEvent; + var location = [self convertPoint:[anEvent locationInWindow] fromView:nil], row = FLOOR(location.y / (_itemSize.height + _verticalMargin)), column = FLOOR(location.x / (_itemSize.width + _horizontalMargin)), index = row * _numberOfColumns + column; - + if (index >= 0 && index < _items.length) [self setSelectionIndexes:[CPIndexSet indexSetWithIndex:index]]; + else if (_allowsEmptySelection) [self setSelectionIndexes:[CPIndexSet indexSet]]; } @@ -566,7 +571,7 @@ [self dragView:view at:[[_items[[_selectionIndexes firstIndex]] view] frame].origin offset:CGPointMakeZero() - event:anEvent + event:_mouseDownEvent pasteboard:nil source:self slideBack:YES]; diff --git a/AppKit/CPDragServer.j b/AppKit/CPDragServer.j index a341ddc90..5716dc061 100644 --- a/AppKit/CPDragServer.j +++ b/AppKit/CPDragServer.j @@ -64,6 +64,8 @@ var CPDragServerStartDragging = function(anEvent) var CPDragServerUpdateDragging = function(anEvent) { + var globalLocation = [[anEvent window] convertBaseToGlobal:[anEvent locationInWindow]]; + // If this is a mouse up, then complete the drag. if([anEvent type] == CPLeftMouseUp) { @@ -72,8 +74,8 @@ var CPDragServerUpdateDragging = function(anEvent) CPDragServerAutoscrollInterval = nil; - CPDragServerLocation = [DRAGGING_WINDOW(CPDragServerDestination) convertBridgeToBase:[[anEvent window] convertBaseToBridge:[anEvent locationInWindow]]]; - + CPDragServerLocation = [DRAGGING_WINDOW(CPDragServerDestination) convertGlobalToBase:globalLocation]; + [CPDragServerView removeFromSuperview]; [CPSharedDragServer._dragWindow orderOut:nil]; @@ -107,16 +109,12 @@ var CPDragServerUpdateDragging = function(anEvent) forNextEventMatchingMask:CPMouseMovedMask | CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:0 dequeue:NO]; - var location = [anEvent locationInWindow], - operation = - bridgeLocation = [[anEvent window] convertBaseToBridge:location]; - // We have to convert base to bridge since the drag event comes from the source window, not the drag window. - var draggingDestination = [[CPPlatformWindow primaryPlatformWindow] _dragHitTest:bridgeLocation pasteboard:CPDragServerPasteboard]; - - CPDragServerLocation = [DRAGGING_WINDOW(draggingDestination) convertBridgeToBase:bridgeLocation]; - - if(draggingDestination != CPDragServerDestination) + var draggingDestination = [[CPPlatformWindow primaryPlatformWindow] _dragHitTest:globalLocation pasteboard:CPDragServerPasteboard]; + + CPDragServerLocation = [DRAGGING_WINDOW(draggingDestination) convertGlobalToBase:globalLocation]; + + if(draggingDestination !== CPDragServerDestination) { if (CPDragServerDestination && [CPDragServerDestination respondsToSelector:@selector(draggingExited:)]) [CPDragServerDestination draggingExited:CPDragServerDraggingInfo]; @@ -128,16 +126,16 @@ var CPDragServerUpdateDragging = function(anEvent) } else if (CPDragServerDestination && [CPDragServerDestination respondsToSelector:@selector(draggingUpdated:)]) [CPDragServerDestination draggingUpdated:CPDragServerDraggingInfo]; - - location.x -= CPDragServerOffset.x; - location.y -= CPDragServerOffset.y; - - [CPDragServerView setFrameOrigin:location]; - + + globalLocation.x -= CPDragServerOffset.x; + globalLocation.y -= CPDragServerOffset.y; + + [[CPDragServerView window] setFrameOrigin:globalLocation]; + if (CPDragServerShouldSendDraggedImageMovedTo) - [CPDragServerSource draggedImage:[CPDragServerView image] movedTo:location]; + [CPDragServerSource draggedImage:[CPDragServerView image] movedTo:globalLocation]; else if (CPDragServerShouldSendDraggedViewMovedTo) - [CPDragServerSource draggedView:CPDragServerView movedTo:location]; + [CPDragServerSource draggedView:CPDragServerView movedTo:globalLocation]; } /* @@ -197,7 +195,7 @@ var CPDragServerUpdateDragging = function(anEvent) */ + (void)initialize { - if (self != [CPDragServer class]) + if (self !== [CPDragServer class]) return; CPDragServerDraggingInfo = [[CPDraggingInfo alloc] init]; @@ -220,7 +218,8 @@ var CPDragServerUpdateDragging = function(anEvent) if (self) { - _dragWindow = [[CPWindow alloc] initWithContentRect:CPRectMakeZero() styleMask:CPBorderlessWindowMask]; + _dragWindow = [[CPWindow alloc] initWithContentRect:_CGRectMakeZero() styleMask:CPBorderlessWindowMask]; + [_dragWindow setLevel:CPDraggingWindowLevel]; } @@ -239,29 +238,43 @@ var CPDragServerUpdateDragging = function(anEvent) @param slideBack if \c YES, \c aView slides back to its origin on a failed drop */ -- (void)dragView:(CPView)aView fromWindow:(CPWindow)aWindow at:(CGPoint)viewLocation offset:(CGSize)mouseOffset event:(CPEvent)anEvent pasteboard:(CPPasteboard)aPasteboard source:(id)aSourceObject slideBack:(BOOL)slideBack +- (void)dragView:(CPView)aView fromWindow:(CPWindow)aWindow at:(CGPoint)viewLocation offset:(CGSize)mouseOffset event:(CPEvent)mouseDownEvent pasteboard:(CPPasteboard)aPasteboard source:(id)aSourceObject slideBack:(BOOL)slideBack { - var eventLocation = [anEvent locationInWindow]; - CPDragServerView = aView; CPDragServerSource = aSourceObject; CPDragServerWindow = aWindow; - CPDragServerOffset = CPPointMake(eventLocation.x - viewLocation.x, eventLocation.y - viewLocation.y); CPDragServerPasteboard = [CPPasteboard pasteboardWithName:CPDragPboard];//aPasteboard; -#if PLATFORM(BROWSER) - var platformWindow = [aWindow platformWindow]; + // The offset is based on the distance from where we want the view to be initially from where the mouse is initially + // Hence the use of mouseDownEvent's location and view's location in global coordinates. + var mouseDownWindow = [mouseDownEvent window], + mouseDownEventLocation = [mouseDownEvent locationInWindow]; - // FIXME: We should just have the window be the size of the view and move the window around. - [_dragWindow setPlatformWindow:platformWindow]; - [_dragWindow setFrameSize:[platformWindow contentBounds].size]; -#endif + if (mouseDownEventLocation) + { + if (mouseDownWindow) + mouseDownEventLocation = [mouseDownWindow convertBaseToGlobal:mouseDownEventLocation]; + + CPDragServerOffset = _CGPointMake(mouseDownEventLocation.x - viewLocation.x, mouseDownEventLocation.y - viewLocation.y); + } + else + CPDragServerOffset = _CGPointMakeZero(); + + if ([CPPlatform isBrowser]) + [_dragWindow setPlatformWindow:[aWindow platformWindow]]; + + [aView setFrameOrigin:_CGPointMakeZero()]; + + var mouseLocation = [CPEvent mouseLocation]; + + // Place it where the mouse pointer is. + [_dragWindow setFrameOrigin:_CGPointMake(mouseLocation.x - CPDragServerOffset.x, mouseLocation.y - CPDragServerOffset.y)]; + [_dragWindow setFrameSize:[aView frame].size]; + + [[_dragWindow contentView] addSubview:aView]; [_dragWindow orderFront:self]; - [aView setFrameOrigin:viewLocation]; - [[_dragWindow contentView] addSubview:aView]; - if (CPDragServerIsDraggingImage) { if ([CPDragServerSource respondsToSelector:@selector(draggedImage:beganAt:)]) @@ -286,7 +299,14 @@ var CPDragServerUpdateDragging = function(anEvent) CPDragServerShouldSendDraggedImageEndedAtOperation = NO; } - CPDragServerStartDragging(anEvent); + if (mouseDownWindow) + mouseLocation = [mouseDownWindow convertGlobalToBase:mouseLocation]; + + var updatedEvent = [CPEvent mouseEventWithType:CPLeftMouseDragged location:mouseLocation modifierFlags:[mouseDownEvent modifierFlags] + timestamp:[mouseDownEvent timestamp] windowNumber:[mouseDownEvent windowNumber] context:nil + eventNumber:0 clickCount:[mouseDownEvent clickCount] pressure:[mouseDownEvent pressure]]; + + CPDragServerStartDragging(updatedEvent); } /*! diff --git a/AppKit/CPEvent.j b/AppKit/CPEvent.j index 37ba58358..eb942a79f 100644 --- a/AppKit/CPEvent.j +++ b/AppKit/CPEvent.j @@ -465,6 +465,18 @@ var _CPEventPeriodicEventPeriod = 0, return _keyCode; } ++ (CGPoint)mouseLocation +{ + // FIXME: this is incorrect, we shouldn't depend on the current event. + var event = [CPApp currentEvent], + eventWindow = [event window]; + + if (eventWindow) + return [eventWindow convertBaseToGlobal:[event locationInWindow]]; + + return [event locationInWindow]; +} + - (float)pressure { return _pressure; diff --git a/AppKit/CPMenu.j b/AppKit/CPMenu.j index 35c39fa1b..8d6b8c467 100644 --- a/AppKit/CPMenu.j +++ b/AppKit/CPMenu.j @@ -672,7 +672,7 @@ var _CPMenuBarVisible = NO, [menuWindow setDelegate:self]; [menuWindow setBackgroundStyle:isForMenuBar ? _CPMenuWindowMenuBarBackgroundStyle : _CPMenuWindowPopUpBackgroundStyle]; - [menuWindow setFrameOrigin:[[anEvent window] convertBaseToBridge:[anEvent locationInWindow]]]; + [menuWindow setFrameOrigin:[[anEvent window] convertBaseToGlobal:[anEvent locationInWindow]]]; [menuWindow orderFront:self]; [menuWindow beginTrackingWithEvent:anEvent sessionDelegate:self didEndSelector:@selector(_menuWindowDidFinishTracking:highlightedItem:)]; @@ -904,7 +904,7 @@ var STICKY_TIME_INTERVAL = 500, CPTimeInterval _startTime; int _scrollingState; - CGPoint _lastScreenLocation; + CGPoint _lastGlobalLocation; BOOL _isShowingTopScrollIndicator; BOOL _isShowingBottomScrollIndicator; @@ -921,10 +921,10 @@ var STICKY_TIME_INTERVAL = 500, menuWindow = _CPMenuWindowPool.pop(); else menuWindow = [[_CPMenuWindow alloc] init]; - + [menuWindow setFont:aFont]; [menuWindow setMenu:aMenu]; - + return menuWindow; } @@ -1076,35 +1076,42 @@ var STICKY_TIME_INTERVAL = 500, - (void)constrainToScreen { + // FIXME: There are integral window issues with platform windows. + // FIXME: This gets called far too often. _unconstrainedFrame = CGRectMakeCopy([self frame]); - var screenBounds = CGRectInset([[self platformWindow] contentBounds], 5.0, 5.0), - constrainedFrame = CGRectIntersection(_unconstrainedFrame, screenBounds), - menuViewOrigin = [self convertBaseToBridge:CGPointMake(LEFT_MARGIN, TOP_MARGIN)]; - + var isBrowser = [CPPlatform isBrowser], + visibleFrame = CGRectInset([isBrowser ? [self platformWindow] : [self screen] visibleFrame], 5.0, 5.0), + constrainedFrame = CGRectIntersection(_unconstrainedFrame, visibleFrame); + + // We don't want to simply intersect the visible frame and the unconstrained frame. + // We should be allowing as much of the width to fit as possible (pushing back and forward). constrainedFrame.origin.x = CGRectGetMinX(_unconstrainedFrame); constrainedFrame.size.width = CGRectGetWidth(_unconstrainedFrame); - - if (CGRectGetWidth(constrainedFrame) > CGRectGetWidth(screenBounds)) - constrainedFrame.size.width = CGRectGetWidth(screenBounds); - - if (CGRectGetMaxX(constrainedFrame) > CGRectGetMaxX(screenBounds)) - constrainedFrame.origin.x -= CGRectGetMaxX(constrainedFrame) - CGRectGetMaxX(screenBounds); - - if (CGRectGetMinX(constrainedFrame) < CGRectGetMinX(screenBounds)) - constrainedFrame.origin.x = CGRectGetMinX(screenBounds); - + + if (CGRectGetWidth(constrainedFrame) > CGRectGetWidth(visibleFrame)) + constrainedFrame.size.width = CGRectGetWidth(visibleFrame); + + if (CGRectGetMaxX(constrainedFrame) > CGRectGetMaxX(visibleFrame)) + constrainedFrame.origin.x -= CGRectGetMaxX(constrainedFrame) - CGRectGetMaxX(visibleFrame); + + if (CGRectGetMinX(constrainedFrame) < CGRectGetMinX(visibleFrame)) + constrainedFrame.origin.x = CGRectGetMinX(visibleFrame); + + // This needs to happen before changing the frame. + var menuViewOrigin = [self convertBaseToGlobal:CGPointMake(LEFT_MARGIN, TOP_MARGIN)]; + [super setFrame:constrainedFrame]; - - var topMargin = TOP_MARGIN, + + var moreAbove = menuViewOrigin.y < CGRectGetMinY(constrainedFrame) + TOP_MARGIN, + moreBelow = menuViewOrigin.y + CGRectGetHeight([_menuView frame]) > CGRectGetMaxY(constrainedFrame) - BOTTOM_MARGIN, + + topMargin = TOP_MARGIN, bottomMargin = BOTTOM_MARGIN, contentView = [self contentView], bounds = [contentView bounds]; - - var moreAbove = menuViewOrigin.y < CGRectGetMinY(constrainedFrame) + TOP_MARGIN, - moreBelow = menuViewOrigin.y + CGRectGetHeight([_menuView frame]) > CGRectGetMaxY(constrainedFrame) - BOTTOM_MARGIN; - + if (moreAbove) { topMargin += SCROLL_INDICATOR_HEIGHT; @@ -1113,9 +1120,9 @@ var STICKY_TIME_INTERVAL = 500, [_moreAboveView setFrameOrigin:CGPointMake((CGRectGetWidth(bounds) - CGRectGetWidth(frame)) / 2.0, (TOP_MARGIN + SCROLL_INDICATOR_HEIGHT - CGRectGetHeight(frame)) / 2.0)]; } - + [_moreAboveView setHidden:!moreAbove]; - + if (moreBelow) { bottomMargin += SCROLL_INDICATOR_HEIGHT; @@ -1124,13 +1131,13 @@ var STICKY_TIME_INTERVAL = 500, } [_moreBelowView setHidden:!moreBelow]; - + var clipFrame = CGRectMake(LEFT_MARGIN, topMargin, CGRectGetWidth(constrainedFrame) - LEFT_MARGIN - RIGHT_MARGIN, CGRectGetHeight(constrainedFrame) - topMargin - bottomMargin) - + [_menuClipView setFrame:clipFrame]; [_menuView setFrameSize:CGSizeMake(CGRectGetWidth(clipFrame), CGRectGetHeight([_menuView frame]))]; - - [_menuView scrollPoint:CGPointMake(0.0, [self convertBaseToBridge:clipFrame.origin].y - menuViewOrigin.y)]; + + [_menuView scrollPoint:CGPointMake(0.0, [self convertBaseToGlobal:clipFrame.origin].y - menuViewOrigin.y)]; } - (void)cancelTracking @@ -1154,11 +1161,12 @@ var STICKY_TIME_INTERVAL = 500, { var type = [anEvent type], theWindow = [anEvent window], - screenLocation = theWindow ? [theWindow convertBaseToBridge:[anEvent locationInWindow]] : [anEvent locationInWindow]; - - if (type == CPPeriodic) + globalLocation = theWindow ? [theWindow convertBaseToGlobal:[anEvent locationInWindow]] : [anEvent locationInWindow]; + + if (type === CPPeriodic) { - var constrainedBounds = CGRectInset([[self platformWindow] contentBounds], 5.0, 5.0); + var constraintContext = [CPPlatform isBrowser] ? [self platformWindow] : [self screen]; + constrainedBounds = CGRectInset([constraintContext visibleFrame], 5.0, 5.0); if (_scrollingState == _CPMenuWindowScrollingStateUp) { @@ -1172,13 +1180,13 @@ var STICKY_TIME_INTERVAL = 500, [self setFrame:_unconstrainedFrame]; [self constrainToScreen]; - screenLocation = _lastScreenLocation; + globalLocation = _lastGlobalLocation; } - _lastScreenLocation = screenLocation; + _lastGlobalLocation = globalLocation; var menu = [_menuView menu], - menuLocation = [self convertBridgeToBase:screenLocation], + menuLocation = [self convertGlobalToBase:globalLocation], activeItemIndex = [_menuView itemIndexAtPoint:[_menuView convertPoint:menuLocation fromView:nil]], mouseOverMenuView = [[menu itemAtIndex:activeItemIndex] view]; @@ -1209,7 +1217,7 @@ var STICKY_TIME_INTERVAL = 500, _lastMouseOverMenuView = nil; } - [menu _highlightItemAtIndex:[_menuView itemIndexAtPoint:[_menuView convertPoint:[self convertBridgeToBase:screenLocation] fromView:nil]]]; + [menu _highlightItemAtIndex:[_menuView itemIndexAtPoint:[_menuView convertPoint:[self convertGlobalToBase:globalLocation] fromView:nil]]]; if (type == CPMouseMoved || type == CPLeftMouseDragged || type == CPLeftMouseDown) { @@ -1219,11 +1227,11 @@ var STICKY_TIME_INTERVAL = 500, _scrollingState = _CPMenuWindowScrollingStateNone; // If we're at or above of the top scroll indicator... - if (screenLocation.y < CGRectGetMinY(frame) + TOP_MARGIN + SCROLL_INDICATOR_HEIGHT) + if (globalLocation.y < CGRectGetMinY(frame) + TOP_MARGIN + SCROLL_INDICATOR_HEIGHT) _scrollingState = _CPMenuWindowScrollingStateUp; // If we're at or below the bottom scroll indicator... - else if (screenLocation.y > CGRectGetMaxY(frame) - BOTTOM_MARGIN - SCROLL_INDICATOR_HEIGHT) + else if (globalLocation.y > CGRectGetMaxY(frame) - BOTTOM_MARGIN - SCROLL_INDICATOR_HEIGHT) _scrollingState = _CPMenuWindowScrollingStateDown; if (_scrollingState != oldScrollingState) @@ -1447,10 +1455,12 @@ var _CPMenuBarWindowBackgroundColor = nil, - (id)init { - var platformWindowWidth = CGRectGetWidth([[CPPlatformWindow primaryPlatformWindow] contentBounds]); - - self = [super initWithContentRect:CGRectMake(0.0, 0.0, platformWindowWidth, MENUBAR_HEIGHT) styleMask:CPBorderlessWindowMask]; - + var contentRect = [CPPlatform isBrowser] ? [[CPPlatformWindow primaryPlatformWindow] contentBounds] : [[self screen] visibleFrame]; + + contentRect.size.height = MENUBAR_HEIGHT; + + self = [super initWithContentRect:contentRect styleMask:CPBorderlessWindowMask]; + if (self) { // FIXME: http://280north.lighthouseapp.com/projects/13294-cappuccino/tickets/39-dont-allow-windows-to-go-above-menubar diff --git a/AppKit/CPPopUpButton.j b/AppKit/CPPopUpButton.j index b3776fd77..17700fb28 100644 --- a/AppKit/CPPopUpButton.j +++ b/AppKit/CPPopUpButton.j @@ -650,7 +650,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down"); // Pull Down Menus show up directly below their buttons. if ([self pullsDown]) - var menuOrigin = [theWindow convertBaseToBridge:[self convertPoint:CGPointMake(0.0, CGRectGetMaxY([self bounds])) toView:nil]]; + var menuOrigin = [theWindow convertBaseToGlobal:[self convertPoint:CGPointMake(0.0, CGRectGetMaxY([self bounds])) toView:nil]]; // Pop Up Menus attempt to show up "on top" of the selected item. else @@ -661,21 +661,21 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down"); // 2. Move LEFT by whatever indentation we have (offsetWidths, aka, window margin, item margin, etc). // 3. MOVE UP by the difference in sizes of the content and menu item, this will only work if the content is vertically centered. var contentRect = [self convertRect:[self contentRectForBounds:[self bounds]] toView:nil], - menuOrigin = [theWindow convertBaseToBridge:contentRect.origin], + menuOrigin = [theWindow convertBaseToGlobal:contentRect.origin], menuItemRect = [menuWindow rectForItemAtIndex:_selectedIndex]; menuOrigin.x -= CGRectGetMinX(menuItemRect) + [menuWindow overlapOffsetWidth] + [[[menu itemAtIndex:_selectedIndex] _menuItemView] overlapOffsetWidth]; menuOrigin.y -= CGRectGetMinY(menuItemRect) + (CGRectGetHeight(menuItemRect) - CGRectGetHeight(contentRect)) / 2.0; } - + [menuWindow setFrameOrigin:menuOrigin]; - + var menuMaxX = CGRectGetMaxX([menuWindow frame]), - buttonMaxX = [theWindow convertBaseToBridge:CGPointMake(CGRectGetMaxX([self convertRect:[self bounds] toView:nil]), 0.0)].x; - + buttonMaxX = [theWindow convertBaseToGlobal:CGPointMake(CGRectGetMaxX([self convertRect:[self bounds] toView:nil]), 0.0)].x; + if (menuMaxX < buttonMaxX) [menuWindow setMinWidth:CGRectGetWidth([menuWindow frame]) + buttonMaxX - menuMaxX - ([self pullsDown] ? 0.0 : VISIBLE_MARGIN)]; - + [menuWindow orderFront:self]; [menuWindow beginTrackingWithEvent:anEvent sessionDelegate:self didEndSelector:@selector(menuWindowDidFinishTracking:highlightedItem:)]; } diff --git a/AppKit/CPScreen.j b/AppKit/CPScreen.j new file mode 100644 index 000000000..4d0b7b3c8 --- /dev/null +++ b/AppKit/CPScreen.j @@ -0,0 +1,16 @@ + +@import + + +#import "CoreGraphics/CGGeometry.h" + +@implementation CPScreen : CPObject +{ +} + +- (CGRect)visibleFrame +{ + return _CGRectMake(window.screen.availLeft, window.screen.availTop, window.screen.availWidth, window.screen.availHeight); +} + +@end \ No newline at end of file diff --git a/AppKit/CPWindow/CPWindow.j b/AppKit/CPWindow/CPWindow.j index c8b7612f2..e851f38ba 100644 --- a/AppKit/CPWindow/CPWindow.j +++ b/AppKit/CPWindow/CPWindow.j @@ -27,6 +27,7 @@ @import "CGGeometry.j" @import "CPAnimation.j" @import "CPResponder.j" +@import "CPScreen.j" @import "CPPlatformWindow.j" #include "../Platform/Platform.h" @@ -96,61 +97,61 @@ CPBackgroundWindowLevel = -1; @group CPWindowLevel @global */ -CPNormalWindowLevel = 4; +CPNormalWindowLevel = 0; /* Floating palette type window @group CPWindowLevel @global */ -CPFloatingWindowLevel = 5; +CPFloatingWindowLevel = 3; /* Submenu type window @group CPWindowLevel @global */ -CPSubmenuWindowLevel = 6; +CPSubmenuWindowLevel = 3; /* For a torn-off menu @group CPWindowLevel @global */ -CPTornOffMenuWindowLevel = 6; +CPTornOffMenuWindowLevel = 3; /* For the application's main menu @group CPWindowLevel @global */ -CPMainMenuWindowLevel = 8; +CPMainMenuWindowLevel = 24; /* Status window level @group CPWindowLevel @global */ -CPStatusWindowLevel = 9; +CPStatusWindowLevel = 25; /* Level for a modal panel @group CPWindowLevel @global */ -CPModalPanelWindowLevel = 10; +CPModalPanelWindowLevel = 8; /* Level for a pop up menu @group CPWindowLevel @global */ -CPPopUpMenuWindowLevel = 11; +CPPopUpMenuWindowLevel = 101; /* Level for a window being dragged @group CPWindowLevel @global */ -CPDraggingWindowLevel = 12; +CPDraggingWindowLevel = 500; /* Level for the screens saver @group CPWindowLevel @global */ -CPScreenSaverWindowLevel = 13; +CPScreenSaverWindowLevel = 1000; /* The receiver is removed from the screen list and hidden. @@ -288,6 +289,8 @@ var CPWindowSaveImage = nil, BOOL _autorecalculatesKeyViewLoop; BOOL _keyViewLoopIsDirty; + BOOL _sharesChromeWithPlatformWindow; + // Bridge Support #if PLATFORM(DOM) DOMElement _DOMElement; @@ -336,7 +339,19 @@ CPTexturedBackgroundWindowMask if (self) { - [self setPlatformWindow:[CPPlatformWindow primaryPlatformWindow]]; + var windowViewClass = [[self class] _windowViewClassForStyleMask:aStyleMask]; + + _frame = [windowViewClass frameRectForContentRect:aContentRect]; + + [self _setSharesChromeWithPlatformWindow:![CPPlatform isBrowser]]; + + if ([CPPlatform isBrowser]) + [self setPlatformWindow:[CPPlatformWindow primaryPlatformWindow]]; + else + { + [self setPlatformWindow:[[CPPlatformWindow alloc] initWithContentRect:_frame]]; + [self platformWindow]._only = self; + } _isFullPlatformWindow = NO; _registeredDraggedTypes = [CPSet set]; @@ -347,15 +362,13 @@ CPTexturedBackgroundWindowMask CPApp._windows[_windowNumber] = self; _styleMask = aStyleMask; - _level = CPNormalWindowLevel; - + + [self setLevel:CPNormalWindowLevel]; + _minSize = CGSizeMake(0.0, 0.0); _maxSize = CGSizeMake(1000000.0, 1000000.0); // Create our border view which is the actual root of our view hierarchy. - var windowViewClass = [[self class] _windowViewClassForStyleMask:aStyleMask]; - - _frame = [windowViewClass frameRectForContentRect:aContentRect]; _windowView = [[windowViewClass alloc] initWithFrame:CGRectMake(0.0, 0.0, CGRectGetWidth(_frame), CGRectGetHeight(_frame)) styleMask:aStyleMask]; [_windowView _setWindow:self]; @@ -375,9 +388,12 @@ CPTexturedBackgroundWindowMask _DOMElement.style.visibility = "visible"; _DOMElement.style.zIndex = 0; - CPDOMDisplayServerSetStyleLeftTop(_DOMElement, NULL, _CGRectGetMinX(_frame), _CGRectGetMinY(_frame)); + if (![self _sharesChromeWithPlatformWindow]) + { + CPDOMDisplayServerSetStyleLeftTop(_DOMElement, NULL, _CGRectGetMinX(_frame), _CGRectGetMinY(_frame)); + } + CPDOMDisplayServerSetStyleSize(_DOMElement, 1, 1); - CPDOMDisplayServerAppendChild(_DOMElement, _windowView._DOMElement); #endif @@ -442,22 +458,25 @@ CPTexturedBackgroundWindowMask _windowView = aWindowView; -#if PLATFORM(DOM) if (oldWindowView) { [oldWindowView _setWindow:nil]; [oldWindowView noteToolbarChanged]; +#if PLATFORM(DOM) CPDOMDisplayServerRemoveChild(_DOMElement, oldWindowView._DOMElement); +#endif } if (_windowView) { +#if PLATFORM(DOM) CPDOMDisplayServerAppendChild(_DOMElement, _windowView._DOMElement); +#endif var contentRect = [_contentView convertRect:[_contentView bounds] toView:nil]; - contentRect.origin = [self convertBaseToBridge:contentRect.origin]; + contentRect.origin = [self convertBaseToGlobal:contentRect.origin]; [_windowView _setWindow:self]; [_windowView setNextResponder:self]; @@ -467,7 +486,6 @@ CPTexturedBackgroundWindowMask [self setFrame:[self frameRectForContentRect:contentRect]]; } -#endif } - (void)setFullPlatformWindow:(BOOL)shouldBeFullPlatformWindow @@ -494,7 +512,7 @@ CPTexturedBackgroundWindowMask [self setLevel:CPBackgroundWindowLevel]; [self setHasShadow:NO]; [self setAutoresizingMask:CPWindowWidthSizable | CPWindowHeightSizable]; - [self setFrame:[_platformWindow usableContentFrame]]; + [self setFrame:[_platformWindow visibleFrame]]; } else { @@ -598,16 +616,22 @@ CPTexturedBackgroundWindowMask - (void)setFrameOrigin:(CGPoint)anOrigin { var origin = _frame.origin; - + if (_CGPointEqualToPoint(origin, anOrigin)) return; - + origin.x = anOrigin.x; origin.y = anOrigin.y; + if ([self _sharesChromeWithPlatformWindow]) + [_platformWindow setContentOrigin:origin]; + + else + { #if PLATFORM(DOM) - CPDOMDisplayServerSetStyleLeftTop(_DOMElement, NULL, origin.x, origin.y); + CPDOMDisplayServerSetStyleLeftTop(_DOMElement, NULL, origin.x, origin.y); #endif + } [[CPNotificationCenter defaultCenter] postNotificationName:CPWindowDidMoveNotification object:self]; } @@ -627,9 +651,12 @@ CPTexturedBackgroundWindowMask [_windowView setFrameSize:aSize]; + if ([self _sharesChromeWithPlatformWindow]) + [_platformWindow setContentSize:aSize]; + if (_hasShadow) [_shadowView setFrameSize:_CGSizeMake(SHADOW_MARGIN_LEFT + aSize.width + SHADOW_MARGIN_RIGHT, SHADOW_MARGIN_BOTTOM + aSize.height + SHADOW_MARGIN_TOP + SHADOW_DISTANCE)]; - + if (!_isAnimating && [_delegate respondsToSelector:@selector(windowDidResize:)]) [_delegate windowDidResize:self]; } @@ -671,6 +698,9 @@ CPTexturedBackgroundWindowMask CPApp._keyWindow = nil; } + + if ([self _sharesChromeWithPlatformWindow]) + [_platformWindow orderOut:self]; } /*! @@ -690,6 +720,9 @@ CPTexturedBackgroundWindowMask - (void)setLevel:(int)aLevel { _level = aLevel; + + if ([self _sharesChromeWithPlatformWindow]) + [_platformWindow setLevel:aLevel]; } /*! @@ -881,9 +914,12 @@ CPTexturedBackgroundWindowMask { if (_hasShadow === shouldHaveShadow) return; - + _hasShadow = shouldHaveShadow; - + + if ([self _sharesChromeWithPlatformWindow]) + return [_platformWindow setHasShadow:shouldHaveShadow]; + if (_hasShadow) { var bounds = [_windowView bounds]; @@ -1120,6 +1156,11 @@ CPTexturedBackgroundWindowMask return _representedURL; } +- (CPScreen)screen +{ + return [[CPScreen alloc] init]; +} + // Moving /*! @@ -1175,7 +1216,7 @@ CPTexturedBackgroundWindowMask return; case CPLeftMouseDown: _leftMouseDownView = [_windowView hitTest:point]; - + if (_leftMouseDownView != _firstResponder && [_leftMouseDownView acceptsFirstResponder]) [self makeFirstResponder:_leftMouseDownView]; @@ -1343,7 +1384,7 @@ CPTexturedBackgroundWindowMask */ - (void)dragImage:(CPImage)anImage at:(CGPoint)imageLocation offset:(CGSize)mouseOffset event:(CPEvent)anEvent pasteboard:(CPPasteboard)aPasteboard source:(id)aSourceObject slideBack:(BOOL)slideBack { - [[CPDragServer sharedDragServer] dragImage:anImage fromWindow:self at:[self convertBaseToBridge:imageLocation] offset:mouseOffset event:anEvent pasteboard:aPasteboard source:aSourceObject slideBack:slideBack]; + [[CPDragServer sharedDragServer] dragImage:anImage fromWindow:self at:[self convertBaseToGlobal:imageLocation] offset:mouseOffset event:anEvent pasteboard:aPasteboard source:aSourceObject slideBack:slideBack]; } - (void)_noteRegisteredDraggedTypes:(CPSet)pasteboardTypes @@ -1378,9 +1419,9 @@ CPTexturedBackgroundWindowMask @param aSourceObject the drag operation controller @param slideBack Whether the view should 'slide back' if the drag is rejected */ -- (void)dragView:(CPView)aView at:(CGPoint)imageLocation offset:(CGSize)mouseOffset event:(CPEvent)anEvent pasteboard:(CPPasteboard)aPasteboard source:(id)aSourceObject slideBack:(BOOL)slideBack +- (void)dragView:(CPView)aView at:(CGPoint)viewLocation offset:(CGSize)mouseOffset event:(CPEvent)anEvent pasteboard:(CPPasteboard)aPasteboard source:(id)aSourceObject slideBack:(BOOL)slideBack { - [[CPDragServer sharedDragServer] dragView:aView fromWindow:self at:[self convertBaseToBridge:imageLocation] offset:mouseOffset event:anEvent pasteboard:aPasteboard source:aSourceObject slideBack:slideBack]; + [[CPDragServer sharedDragServer] dragView:aView fromWindow:self at:[self convertBaseToGlobal:viewLocation] offset:mouseOffset event:anEvent pasteboard:aPasteboard source:aSourceObject slideBack:slideBack]; } /*! @@ -1632,7 +1673,7 @@ CPTexturedBackgroundWindowMask [_windowView noteToolbarChanged]; if (_isFullPlatformWindow) - newFrame = [_platformWindow usableContentFrame]; + newFrame = [_platformWindow visibleFrame]; else { newFrame = CGRectMakeCopy([self frame]); @@ -1926,7 +1967,7 @@ var keyViewComparator = function(a, b, context) - (void)resizeWithOldPlatformWindowSize:(CGSize)aSize { if ([self isFullPlatformWindow]) - return [self setFrame:[_platformWindow usableContentFrame]]; + return [self setFrame:[_platformWindow visibleFrame]]; if (_autoresizingMask == CPWindowNotSizable) return; @@ -1967,24 +2008,58 @@ var keyViewComparator = function(a, b, context) return _autoresizingMask; } -/* - @ignore -*/ -- (CGPoint)convertBaseToBridge:(CGPoint)aPoint +- (CGPoint)convertBaseToGlobal:(CGPoint)aPoint { - var origin = [self frame].origin; - - return CGPointMake(aPoint.x + origin.x, aPoint.y + origin.y); + return [CPPlatform isBrowser] ? [self convertBaseToPlatformWindow:aPoint] : [self convertBaseToScreen:aPoint]; } -/* - @ignore -*/ -- (CGPoint)convertBridgeToBase:(CGPoint)aPoint +- (CGPoint)convertGlobalToBase:(CGPoint)aPoint { + return [CPPlatform isBrowser] ? [self convertPlatformWindowToBase:aPoint] : [self convertScreenToBase:aPoint]; +} + +- (CGPoint)convertBaseToPlatformWindow:(CGPoint)aPoint +{ + if ([self _sharesChromeWithPlatformWindow]) + return aPoint; + var origin = [self frame].origin; - - return CGPointMake(aPoint.x - origin.x, aPoint.y - origin.y); + + return _CGPointMake(aPoint.x + origin.x, aPoint.y + origin.y); +} + +- (CGPoint)convertPlatformWindowToBase:(CGPoint)aPoint +{ + if ([self _sharesChromeWithPlatformWindow]) + return aPoint; + + var origin = [self frame].origin; + + return _CGPointMake(aPoint.x - origin.x, aPoint.y - origin.y); +} + +- (CGPoint)convertScreenToBase:(CGPoint)aPoint +{ + return [self convertPlatformWindowToBase:[_platformWindow convertScreenToBase:aPoint]]; +} + +- (CGPoint)convertBaseToScreen:(CGPoint)aPoint +{ + return [_platformWindow convertBaseToScreen:[self convertBaseToPlatformWindow:aPoint]]; +} + +- (void)_setSharesChromeWithPlatformWindow:(BOOL)shouldShareFrameWithPlatformWindow +{ + // We canna' do it captain! We just don't have the power! + if (shouldShareFrameWithPlatformWindow && [CPPlatform isBrowser]) + return; + + _sharesChromeWithPlatformWindow = shouldShareFrameWithPlatformWindow; +} + +- (BOOL)_sharesChromeWithPlatformWindow +{ + return _sharesChromeWithPlatformWindow; } // Undo and Redo Support @@ -2039,6 +2114,22 @@ var keyViewComparator = function(a, b, context) return [self isFullPlatformWindow]; } +/* + @ignore +*/ +- (CGPoint)convertBaseToBridge:(CGPoint)aPoint +{ + return [self convertBaseToPlatformWindow:aPoint]; +} + +/* + @ignore +*/ +- (CGPoint)convertBridgeToBase:(CGPoint)aPoint +{ + return [self convertPlatformWindowToBase:aPoint]; +} + @end var interpolate = function(fromValue, toValue, progress) diff --git a/AppKit/CPWindow/_CPWindowView.j b/AppKit/CPWindow/_CPWindowView.j index fe2d1ca4d..a6d7c50e8 100644 --- a/AppKit/CPWindow/_CPWindowView.j +++ b/AppKit/CPWindow/_CPWindowView.j @@ -100,7 +100,7 @@ var _CPWindowViewResizeIndicatorImage = nil; - (void)mouseDown:(CPEvent)anEvent { var theWindow = [self window]; - + if ((_styleMask & CPResizableWindowMask) && _resizeIndicator) { // FIXME: This should be better @@ -145,7 +145,7 @@ var _CPWindowViewResizeIndicatorImage = nil; var visibleFrame = _cachedScreenFrame; if (!visibleFrame) - visibleFrame = [[CPPlatformWindow primaryPlatformWindow] usableContentFrame]; + visibleFrame = [[CPPlatformWindow primaryPlatformWindow] visibleFrame]; var restrictedPoint = CGPointMake(0, 0); @@ -158,22 +158,24 @@ var _CPWindowViewResizeIndicatorImage = nil; - (void)trackMoveWithEvent:(CPEvent)anEvent { var type = [anEvent type]; - + if (type === CPLeftMouseUp) { _cachedScreenFrame = nil; return; } + else if (type === CPLeftMouseDown) { - _mouseDraggedPoint = [[self window] convertBaseToBridge:[anEvent locationInWindow]]; - _cachedScreenFrame = [[CPPlatformWindow primaryPlatformWindow] usableContentFrame]; + _mouseDraggedPoint = [[self window] convertBaseToGlobal:[anEvent locationInWindow]]; + _cachedScreenFrame = [[CPPlatformWindow primaryPlatformWindow] visibleFrame]; } + else if (type === CPLeftMouseDragged) { var theWindow = [self window], frame = [theWindow frame], - location = [theWindow convertBaseToBridge:[anEvent locationInWindow]], + location = [theWindow convertBaseToGlobal:[anEvent locationInWindow]], origin = [self _pointWithinScreenFrame:CGPointMake(_CGRectGetMinX(frame) + (location.x - _mouseDraggedPoint.x), _CGRectGetMinY(frame) + (location.y - _mouseDraggedPoint.y))]; @@ -322,7 +324,7 @@ var _CPWindowViewResizeIndicatorImage = nil; { var contentRect = [self convertRect:[[theWindow contentView] frame] toView:nil]; - contentRect.origin = [theWindow convertBaseToBridge:contentRect.origin]; + contentRect.origin = [theWindow convertBaseToGlobal:contentRect.origin]; [self setAutoresizesSubviews:NO]; [theWindow setFrame:[theWindow frameRectForContentRect:contentRect]]; diff --git a/AppKit/Cib/_CPCibCustomView.j b/AppKit/Cib/_CPCibCustomView.j index c420a90d4..808cf85fc 100644 --- a/AppKit/Cib/_CPCibCustomView.j +++ b/AppKit/Cib/_CPCibCustomView.j @@ -71,7 +71,7 @@ var _CPCibCustomViewClassNameKey = @"_CPCibCustomViewClassNameKey"; - (id)_cibInstantiate { var theClass = CPClassFromString(_className); - + // If we don't have this class, just use CPView. // FIXME: Should we instead throw an exception? if (!theClass) diff --git a/AppKit/Platform/CPPlatform.j b/AppKit/Platform/CPPlatform.j index 8a75b53ab..9b031b038 100644 --- a/AppKit/Platform/CPPlatform.j +++ b/AppKit/Platform/CPPlatform.j @@ -24,4 +24,9 @@ [CPPlatformWindow setPrimaryPlatformWindow:[[CPPlatformWindow alloc] _init]]; } ++ (BOOL)isBrowser +{ + return YES; +} + @end diff --git a/AppKit/Platform/CPPlatformWindow.j b/AppKit/Platform/CPPlatformWindow.j index 8a6bd2ea5..b62c7b552 100644 --- a/AppKit/Platform/CPPlatformWindow.j +++ b/AppKit/Platform/CPPlatformWindow.j @@ -9,7 +9,10 @@ var PrimaryPlatformWindow = NULL; @implementation CPPlatformWindow : CPObject { - CGRect _contentRect; + CGRect _contentRect; + + CPInteger _level; + BOOL _hasShadow; #if PLATFORM(DOM) DOMWindow _DOMWindow; @@ -86,7 +89,7 @@ var PrimaryPlatformWindow = NULL; return contentBounds; } -- (void)usableContentFrame +- (CGRect)visibleFrame { var frame = [self contentBounds]; @@ -103,6 +106,11 @@ var PrimaryPlatformWindow = NULL; return frame; } +- (void)usableContentFrame +{ + return [self visibleFrame]; +} + - (void)setContentRect:(CGRect)aRect { if (!aRect || _CGRectEqualToRect(_contentRect, aRect)) @@ -144,22 +152,49 @@ var PrimaryPlatformWindow = NULL; { [self setContentRect:[self nativeContentRect]]; } -/* -- (BOOL)isVisible + +- (CGPoint)convertBaseToScreen:(CGPoint)aPoint { - return NO; + var contentRect = [self contentRect]; + + return _CGPointMake(aPoint.x + _CGRectGetMinX(contentRect), aPoint.y + _CGRectGetMinY(contentRect)); } -/* -+ (BOOL)supportsMultipleWindows +- (CGPoint)convertScreenToBase:(CGPoint)aPoint { -#if PLATFORM(BROWSER) - return YES; + var contentRect = [self contentRect]; + + return _CGPointMake(aPoint.x - _CGRectGetMinX(contentRect), aPoint.y - _CGRectGetMinY(contentRect)); +} + +- (BOOL)isVisible +{ +#if PLATFORM(DOM) + return _DOMWindow !== NULL; #else return NO; #endif } -*/ + +- (void)setLevel:(CPInteger)aLevel +{ + _level = aLevel; + +#if PLATFORM(DOM) + if (_DOMWindow && _DOMWindow.cpSetLevel) + _DOMWindow.cpSetLevel(aLevel); +#endif +} + +- (void)setHasShadow:(BOOL)shouldHaveShadow +{ + _hasShadow = shouldHaveShadow; + +#if PLATFORM(DOM) + if (_DOMWindow && _DOMWindow.cpSetHasShadow) + _DOMWindow.cpSetHasShadow(shouldHaveShadow); +#endif +} - (BOOL)supportsFullPlatformWindows { diff --git a/AppKit/Platform/DOM/CPPlatformWindow+DOM.j b/AppKit/Platform/DOM/CPPlatformWindow+DOM.j index c491a9a2a..6f33046a6 100644 --- a/AppKit/Platform/DOM/CPPlatformWindow+DOM.j +++ b/AppKit/Platform/DOM/CPPlatformWindow+DOM.j @@ -81,13 +81,13 @@ var CTRL_KEY_CODE = 17; _DOMWindow = window; _contentRect = _CGRectMakeZero(); + _windowLevels = []; + _windowLayers = [CPDictionary dictionary]; + [self registerDOMWindow]; [self updateFromNativeContentRect]; _charCodes = {}; - - _windowLevels = []; - _windowLayers = [CPDictionary dictionary]; } return self; @@ -220,7 +220,7 @@ var CTRL_KEY_CODE = 17; _DOMWindow.addEventListener("resize", resizeEventCallback, NO); - _DOMWindow.addEventListener("beforeunload", function() + _DOMWindow.addEventListener("unload", function() { [self updateFromNativeContentRect]; @@ -294,23 +294,30 @@ var CTRL_KEY_CODE = 17; } } -- (BOOL)isVisible -{ - return _DOMWindow !== NULL; -} - - (void)orderFront:(id)aSender { if (_DOMWindow) return _DOMWindow.focus(); - _DOMWindow = window.open("", "", "menubar=no,location=no,resizable=yes,scrollbars=no,status=no,left=" + _CGRectGetMinX(_contentRect) + ",top=" + _CGRectGetMinY(_contentRect) + ",width=" + _CGRectGetWidth(_contentRect) + ",height=" + _CGRectGetHeight(_contentRect)); + _DOMWindow = window.open("", "_blank", "menubar=no,location=no,resizable=yes,scrollbars=no,status=no,left=" + _CGRectGetMinX(_contentRect) + ",top=" + _CGRectGetMinY(_contentRect) + ",width=" + _CGRectGetWidth(_contentRect) + ",height=" + _CGRectGetHeight(_contentRect)); + + _DOMWindow.document.write(""); + _DOMWindow.document.close(); + + if (![CPPlatform isBrowser]) + { + _DOMWindow.cpSetLevel(_level); + _DOMWindow.cpSetHasShadow(_hasShadow); + } [self registerDOMWindow]; } - (void)orderOut:(id)aSender { + if (!_DOMWindow) + return; + _DOMWindow.close(); } @@ -616,7 +623,7 @@ var CTRL_KEY_CODE = 17; var type = _overriddenEventType || aDOMEvent.type; // IE's event order is down, up, up, dblclick, so we have create these events artificially. - if (type === CPDOMEventDoubleClick) + if (type === @"dblclick") { _overriddenEventType = CPDOMEventMouseDown; [self _bridgeMouseEvent:aDOMEvent]; @@ -655,7 +662,7 @@ var CTRL_KEY_CODE = 17; } if (windowNumber) - location = [CPApp._windows[windowNumber] convertBridgeToBase:location]; + location = [CPApp._windows[windowNumber] convertPlatformWindowToBase:location]; if (type === "mouseup") { @@ -817,7 +824,7 @@ var CTRL_KEY_CODE = 17; } - (CPWindow)hitTest:(CPPoint)location -{ +{if (self._only) return self._only; var levels = _windowLevels, layers = _windowLayers, levelCount = levels.length,