mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-10-07 17:38:02 +00:00
Fixed: missing theme image, window sizing/moving was broken.
Afterbbfaac5, all kinds of strange behavior occurred with window sizing and moving due to overzealous constraining. Cocoa does not constrain the frame of hidden windows. When a hidden window is ordered in, it is constrained to the usable screen content rect. A visible window has its height constrained when its frame is set. Its origin is constrained such that a minimum margin at the left, right and top is visible, and the top is constrained to be below the menu bar. This commit fixes a number of problems related to window moving and resizing that were introduced bybbfaac5: - Sheets are not constrained at all. - Moving a window does not constrain its size. In addition, when a window is moved, tracking is relative to the initial click point, which provides proper behavior when the movement is constrained and the mouse keeps moving.
This commit is contained in:
1 parent
481f7c61b8
commit
54bc851159
4 files changed
+108
-71
No files matched your search
+89
-36
@@ -56,7 +56,10 @@
|
||||
var CPWindowSaveImage = nil,
|
||||
|
||||
CPWindowResizeTime = 0.2,
|
||||
CPWindowResizeStyleGlobalChangeNotification = @"CPWindowResizeStyleGlobalChangeNotification";
|
||||
CPWindowResizeStyleGlobalChangeNotification = @"CPWindowResizeStyleGlobalChangeNotification",
|
||||
|
||||
CPWindowMinVisibleHorizontalMargin = 40,
|
||||
CPWindowMinVisibleVerticalMargin = 2;
|
||||
|
||||
/*
|
||||
Keys for which action messages will be sent by default when unhandled, e.g. complete:.
|
||||
@@ -642,50 +645,49 @@ CPTexturedBackgroundWindowMask
|
||||
*/
|
||||
- (void)setFrame:(CGRect)aFrame display:(BOOL)shouldDisplay animate:(BOOL)shouldAnimate
|
||||
{
|
||||
if (_CGRectEqualToRect(aFrame, _frame))
|
||||
return;
|
||||
[self _setFrame:aFrame display:shouldDisplay animate:shouldAnimate constrainWidth:NO constrainHeight:YES];
|
||||
}
|
||||
|
||||
aFrame = _CGRectMakeCopy(aFrame);
|
||||
|
||||
var value = aFrame.origin.x,
|
||||
- (void)_setFrame:(CGRect)aFrame display:(BOOL)shouldDisplay animate:(BOOL)shouldAnimate constrainWidth:(BOOL)shouldConstrainWidth constrainHeight:(BOOL)shouldConstrainHeight
|
||||
{
|
||||
var frame = CGRectMakeCopy(aFrame),
|
||||
value = frame.origin.x,
|
||||
delta = value - FLOOR(value);
|
||||
|
||||
if (delta)
|
||||
aFrame.origin.x = value > 0.879 ? CEIL(value) : FLOOR(value);
|
||||
frame.origin.x = value > 0.879 ? CEIL(value) : FLOOR(value);
|
||||
|
||||
value = aFrame.origin.y;
|
||||
value = frame.origin.y;
|
||||
delta = value - FLOOR(value);
|
||||
|
||||
if (delta)
|
||||
aFrame.origin.y = value > 0.879 ? CEIL(value) : FLOOR(value);
|
||||
frame.origin.y = value > 0.879 ? CEIL(value) : FLOOR(value);
|
||||
|
||||
value = aFrame.size.width;
|
||||
value = frame.size.width;
|
||||
delta = value - FLOOR(value);
|
||||
|
||||
if (delta)
|
||||
aFrame.size.width = value > 0.15 ? CEIL(value) : FLOOR(value);
|
||||
frame.size.width = value > 0.15 ? CEIL(value) : FLOOR(value);
|
||||
|
||||
value = aFrame.size.height;
|
||||
value = frame.size.height;
|
||||
delta = value - FLOOR(value);
|
||||
|
||||
if (delta)
|
||||
aFrame.size.height = value > 0.15 ? CEIL(value) : FLOOR(value);
|
||||
frame.size.height = value > 0.15 ? CEIL(value) : FLOOR(value);
|
||||
|
||||
// In Cocoa, if a window is already visible, only its height is pinned
|
||||
if (_isVisible)
|
||||
aFrame = [self _pinFrame:aFrame toUsableScreenWidth:NO andHeight:YES];
|
||||
frame = [self _constrainFrame:frame toUsableScreenWidth:shouldConstrainWidth andHeight:shouldConstrainHeight];
|
||||
|
||||
if (shouldAnimate)
|
||||
{
|
||||
[_frameAnimation stopAnimation];
|
||||
_frameAnimation = [[_CPWindowFrameAnimation alloc] initWithWindow:self targetFrame:aFrame];
|
||||
_frameAnimation = [[_CPWindowFrameAnimation alloc] initWithWindow:self targetFrame:frame];
|
||||
|
||||
[_frameAnimation startAnimation];
|
||||
}
|
||||
else
|
||||
{
|
||||
var origin = _frame.origin,
|
||||
newOrigin = aFrame.origin,
|
||||
newOrigin = frame.origin,
|
||||
originMoved = !_CGPointEqualToPoint(origin, newOrigin);
|
||||
|
||||
if (originMoved)
|
||||
@@ -705,7 +707,7 @@ CPTexturedBackgroundWindowMask
|
||||
}
|
||||
|
||||
var size = _frame.size,
|
||||
newSize = aFrame.size;
|
||||
newSize = frame.size;
|
||||
|
||||
if (!_CGSizeEqualToSize(size, newSize))
|
||||
{
|
||||
@@ -729,33 +731,80 @@ CPTexturedBackgroundWindowMask
|
||||
}
|
||||
}
|
||||
|
||||
- (CGRect)_pinFrame:(CGRect)aFrame toUsableScreenWidth:(BOOL)pinWidth andHeight:(BOOL)pinHeight
|
||||
- (CGRect)_constrainFrame:(CGRect)aFrame toUsableScreenWidth:(BOOL)constrainWidth andHeight:(BOOL)constrainHeight
|
||||
{
|
||||
if (!_constrainsToUsableScreen)
|
||||
return CGRectMakeCopy(aFrame);
|
||||
var frame = CGRectMakeCopy(aFrame);
|
||||
|
||||
var usableRect = [_platformWindow usableContentFrame],
|
||||
frame = _CGRectMakeCopy(aFrame);
|
||||
if (!_constrainsToUsableScreen || !_isVisible)
|
||||
return frame;
|
||||
|
||||
if (pinWidth)
|
||||
var usableRect = [_platformWindow usableContentFrame];
|
||||
|
||||
if (constrainWidth)
|
||||
{
|
||||
// First move the frame right to ensure the left side is within the usable rect.
|
||||
frame.origin.x = MAX(frame.origin.x, usableRect.origin.x);
|
||||
|
||||
var maxX = MIN(_CGRectGetMaxX(frame), _CGRectGetMaxX(usableRect));
|
||||
frame.size.width = maxX - frame.origin.x;
|
||||
// Now move the frame left so that the right side is within the usable rect.
|
||||
var maxX = MIN(CGRectGetMaxX(frame), CGRectGetMaxX(usableRect));
|
||||
frame.origin.x = maxX - frame.size.width;
|
||||
|
||||
// Finally, adjust the left + width to ensure the left side is within the usable rect.
|
||||
var usableWidth = CGRectGetWidth(usableRect);
|
||||
|
||||
if (CGRectGetWidth(frame) > usableWidth)
|
||||
{
|
||||
frame.origin.x = CGRectGetMinX(usableRect);
|
||||
frame.size.width = usableWidth;
|
||||
}
|
||||
}
|
||||
|
||||
if (pinHeight)
|
||||
if (constrainHeight)
|
||||
{
|
||||
// First move the frame down to ensure the top is within the usable rect.
|
||||
frame.origin.y = MAX(frame.origin.y, usableRect.origin.y);
|
||||
|
||||
var maxY = MIN(_CGRectGetMaxY(frame), _CGRectGetMaxY(usableRect));
|
||||
frame.size.height = maxY - frame.origin.y;
|
||||
// Now move the frame up so that the bottom is within the usable rect.
|
||||
var maxY = MIN(CGRectGetMaxY(frame), CGRectGetMaxY(usableRect));
|
||||
frame.origin.y = maxY - frame.size.height;
|
||||
|
||||
// Finally, adjust the top + height to ensure the top is within the usable rect.
|
||||
var usableHeight = CGRectGetHeight(usableRect);
|
||||
|
||||
if (CGRectGetHeight(frame) > usableHeight)
|
||||
{
|
||||
frame.origin.y = CGRectGetMinY(usableRect);
|
||||
frame.size.height = usableHeight;
|
||||
}
|
||||
}
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
- (CGRect)_constrainOriginOfFrame:(CGRect)aFrame
|
||||
{
|
||||
var frame = CGRectMakeCopy(aFrame);
|
||||
|
||||
if (!_constrainsToUsableScreen || !_isVisible)
|
||||
return frame;
|
||||
|
||||
/*
|
||||
- CPWindowMinVisibleHorizontalMargin is kept onscreen at the left/right of the window.
|
||||
- The top of the window is kept below the top of the usable content.
|
||||
- The top of the contentView + CPWindowMinVisibleVerticalMargin is kept above the bottom of the usable content.
|
||||
*/
|
||||
var usableRect = [_platformWindow usableContentFrame],
|
||||
maxUsableY = CGRectGetMaxY(usableRect) - CGRectGetMinY([_contentView frame]) - CPWindowMinVisibleVerticalMargin;
|
||||
|
||||
frame.origin.x = MAX(frame.origin.x, CGRectGetMinX(usableRect) + CPWindowMinVisibleHorizontalMargin - CGRectGetWidth(frame));
|
||||
frame.origin.x = MIN(frame.origin.x, CGRectGetMaxX(usableRect) - CPWindowMinVisibleHorizontalMargin);
|
||||
|
||||
frame.origin.y = MAX(frame.origin.y, CGRectGetMinY(usableRect));
|
||||
frame.origin.y = MIN(frame.origin.y, maxUsableY);
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
- (void)_moveChildWindows:(CGPoint)delta
|
||||
{
|
||||
[_childWindows enumerateObjectsUsingBlock:function(childWindow)
|
||||
@@ -792,7 +841,8 @@ CPTexturedBackgroundWindowMask
|
||||
*/
|
||||
- (void)setFrameOrigin:(CGPoint)anOrigin
|
||||
{
|
||||
[self setFrame:_CGRectMake(anOrigin.x, anOrigin.y, _CGRectGetWidth(_frame), _CGRectGetHeight(_frame)) display:YES animate:NO];
|
||||
var frame = [self _constrainOriginOfFrame:CGRectMake(anOrigin.x, anOrigin.y, _frame.size.width, _frame.size.height)];
|
||||
[self _setFrame:frame display:YES animate:NO constrainWidth:NO constrainHeight:NO];
|
||||
|
||||
// reposition sheet
|
||||
if ([self attachedSheet])
|
||||
@@ -824,8 +874,8 @@ CPTexturedBackgroundWindowMask
|
||||
if ([self isSheet])
|
||||
[_parentView orderFront:self];
|
||||
|
||||
// Cocoa pins windows to the usable screen content during orderFront
|
||||
[self setFrame:[self _pinFrame:_frame toUsableScreenWidth:YES andHeight:YES]];
|
||||
if (!_isVisible)
|
||||
[self _setFrame:_frame display:YES animate:NO constrainWidth:YES constrainHeight:YES];
|
||||
|
||||
[_platformWindow orderFront:self];
|
||||
[_platformWindow order:CPWindowAbove window:self relativeTo:nil];
|
||||
@@ -2557,8 +2607,7 @@ CPTexturedBackgroundWindowMask
|
||||
var sheetFrame = [aSheet frame];
|
||||
|
||||
_sheetContext = {"sheet": aSheet, "modalDelegate": aModalDelegate, "endSelector": aDidEndSelector,
|
||||
"contextInfo": aContextInfo, "returnCode": -1,
|
||||
"opened": NO};
|
||||
"contextInfo": aContextInfo, "returnCode": -1, "opened": NO, "savedConstrains": aSheet._constrainsToUsableScreen};
|
||||
|
||||
[self _attachSheetWindow];
|
||||
}
|
||||
@@ -2570,6 +2619,7 @@ CPTexturedBackgroundWindowMask
|
||||
- (void)_attachSheetWindow
|
||||
{
|
||||
_sheetContext["isAttached"] = YES;
|
||||
_sheetContext["sheet"]._constrainsToUsableScreen = NO;
|
||||
|
||||
// it would be ideal to block here and spin an event loop, until attach is complete
|
||||
[CPTimer scheduledTimerWithTimeInterval:0.0
|
||||
@@ -2633,6 +2683,7 @@ CPTexturedBackgroundWindowMask
|
||||
// Restore the state of window before it was sheetified
|
||||
sheet._isSheet = NO;
|
||||
[sheet._windowView _enableSheet:NO inWindow:self];
|
||||
sheet._constrainsToUsableScreen = _sheetContext["savedConstrains"];
|
||||
|
||||
// Close it
|
||||
[sheet orderOut:self];
|
||||
@@ -2707,7 +2758,6 @@ CPTexturedBackgroundWindowMask
|
||||
endFrame = _CGRectMake(originX, endY, sheetFrame.size.width, sheetFrame.size.height);
|
||||
|
||||
[sheet orderFront:self];
|
||||
|
||||
[self _clipSheet:sheet];
|
||||
[sheet setFrame:startFrame display:YES animate:NO];
|
||||
|
||||
@@ -2747,6 +2797,9 @@ CPTexturedBackgroundWindowMask
|
||||
endFrame = _CGRectMakeCopy(sheetFrame),
|
||||
contentOrigin = [self convertBaseToGlobal:[[self contentView] frame].origin];
|
||||
|
||||
// Don't constrain sheets, they are controlled by the parent
|
||||
sheet._constrainsToUsableScreen = NO;
|
||||
|
||||
[sheet setFrameOrigin:_CGPointMake(sheetFrame.origin.x, sheetFrame.origin.y - contentOrigin.y)];
|
||||
[self _clipSheet:sheet];
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ _CPWindowViewResizeSlop = 3;
|
||||
CGSize _toolbarOffset;
|
||||
// BOOL _isAnimatingToolbar;
|
||||
|
||||
CGRect _resizeFrame;
|
||||
CGRect _cachedFrame;
|
||||
int _resizeRegion;
|
||||
CGPoint _mouseDraggedPoint;
|
||||
|
||||
@@ -467,17 +467,17 @@ _CPWindowViewResizeSlop = 3;
|
||||
if (type === CPLeftMouseDown)
|
||||
{
|
||||
_mouseDraggedPoint = _CGPointMake(globalLocation.x, globalLocation.y);
|
||||
_resizeFrame = _CGRectMakeCopy(frame);
|
||||
_cachedFrame = _CGRectMakeCopy(frame);
|
||||
_cachedScreenFrame = [[CPPlatformWindow primaryPlatformWindow] visibleFrame];
|
||||
}
|
||||
else if (type === CPLeftMouseDragged)
|
||||
{
|
||||
var deltaX = globalLocation.x - _mouseDraggedPoint.x,
|
||||
deltaY = globalLocation.y - _mouseDraggedPoint.y,
|
||||
startX = _CGRectGetMinX(_resizeFrame),
|
||||
startY = _CGRectGetMinY(_resizeFrame),
|
||||
startWidth = _CGRectGetWidth(_resizeFrame),
|
||||
startHeight = _CGRectGetHeight(_resizeFrame),
|
||||
startX = _CGRectGetMinX(_cachedFrame),
|
||||
startY = _CGRectGetMinY(_cachedFrame),
|
||||
startWidth = _CGRectGetWidth(_cachedFrame),
|
||||
startHeight = _CGRectGetHeight(_cachedFrame),
|
||||
newX,
|
||||
newY,
|
||||
newWidth,
|
||||
@@ -631,61 +631,40 @@ _CPWindowViewResizeSlop = 3;
|
||||
newHeight = startHeight;
|
||||
}
|
||||
|
||||
[theWindow setFrame:_CGRectMake(newX, newY, newWidth, newHeight)];
|
||||
[theWindow _setFrame:_CGRectMake(newX, newY, newWidth, newHeight) display:YES animate:NO constrainWidth:NO constrainHeight:NO];
|
||||
[self setCursorForLocation:location resizing:YES];
|
||||
}
|
||||
|
||||
[CPApp setTarget:self selector:@selector(trackResizeWithEvent:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
|
||||
}
|
||||
|
||||
- (CGPoint)_pointWithinScreenFrame:(CGPoint)aPoint
|
||||
{
|
||||
// FIXME: this is WRONG, all of this is WRONG
|
||||
if (![CPPlatform isBrowser])
|
||||
return aPoint;
|
||||
|
||||
var visibleFrame = _cachedScreenFrame;
|
||||
|
||||
if (!visibleFrame)
|
||||
visibleFrame = [[CPPlatformWindow primaryPlatformWindow] visibleFrame];
|
||||
|
||||
var restrictedPoint = _CGPointMake(0, 0);
|
||||
|
||||
restrictedPoint.x = MIN(MAX(aPoint.x, -_frame.size.width + 4.0), _CGRectGetMaxX(visibleFrame) - 4.0);
|
||||
restrictedPoint.y = MIN(MAX(aPoint.y, _CGRectGetMinY(visibleFrame)), _CGRectGetMaxY(visibleFrame) - 8.0);
|
||||
|
||||
return restrictedPoint;
|
||||
}
|
||||
|
||||
- (void)trackMoveWithEvent:(CPEvent)anEvent
|
||||
{
|
||||
if (![[self window] isMovable])
|
||||
var theWindow = [self window];
|
||||
|
||||
if (![theWindow isMovable])
|
||||
return;
|
||||
|
||||
var type = [anEvent type];
|
||||
|
||||
if (type === CPLeftMouseUp)
|
||||
{
|
||||
_cachedScreenFrame = nil;
|
||||
return;
|
||||
}
|
||||
else if (type === CPLeftMouseDown)
|
||||
{
|
||||
_mouseDraggedPoint = [[self window] convertBaseToGlobal:[anEvent locationInWindow]];
|
||||
_cachedScreenFrame = [[CPPlatformWindow primaryPlatformWindow] visibleFrame];
|
||||
_mouseDraggedPoint = [theWindow convertBaseToGlobal:[anEvent locationInWindow]];
|
||||
_cachedFrame = _CGRectMakeCopy([theWindow frame]);
|
||||
}
|
||||
else if (type === CPLeftMouseDragged)
|
||||
{
|
||||
var theWindow = [self window],
|
||||
frame = [theWindow frame],
|
||||
location = [theWindow convertBaseToGlobal:[anEvent locationInWindow]],
|
||||
deltaX = location.x - _mouseDraggedPoint.x,
|
||||
deltaY = location.y - _mouseDraggedPoint.y,
|
||||
origin = [self _pointWithinScreenFrame:_CGPointMake(frame.origin.x + deltaX,
|
||||
frame.origin.y + deltaY)];
|
||||
[theWindow setFrameOrigin:origin];
|
||||
origin = _CGPointMake(_cachedFrame.origin.x + deltaX, _cachedFrame.origin.y + deltaY);
|
||||
|
||||
_mouseDraggedPoint = [self _pointWithinScreenFrame:location];
|
||||
[theWindow setFrameOrigin:origin];
|
||||
}
|
||||
|
||||
[CPApp setTarget:self selector:@selector(trackMoveWithEvent:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 72 B After Width: | Height: | Size: 612 B |
@@ -1,3 +1,8 @@
|
||||
@import <AppKit/CPAlert.j>
|
||||
@import <AppKit/CPApplication.j>
|
||||
@import <AppKit/CPPopover.j>
|
||||
@import <AppKit/CPViewController.j>
|
||||
@import <AppKit/CPWindowController.j>
|
||||
|
||||
@implementation SheetWindowController : CPWindowController
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user