mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-10-12 19:47:07 +00:00
Support for resizing windows on all sides
This commit is contained in:
1 parent
dcdcd8e41a
commit
deb6224cf8
13 files changed
+1184
-146
No files matched your search
+171
-111
@@ -186,6 +186,11 @@ CPWindowShadowStyleStandard = 0;
|
||||
CPWindowShadowStyleMenu = 1;
|
||||
CPWindowShadowStylePanel = 2;
|
||||
|
||||
CPWindowResizeStyleModern = 0;
|
||||
CPWindowResizeStyleLegacy = 1;
|
||||
CPWindowResizeStyle = CPWindowResizeStyleModern;
|
||||
CPWindowResizeSlop = 5;
|
||||
|
||||
var SHADOW_MARGIN_LEFT = 20.0,
|
||||
SHADOW_MARGIN_RIGHT = 19.0,
|
||||
SHADOW_MARGIN_TOP = 10.0,
|
||||
@@ -197,7 +202,8 @@ var SHADOW_MARGIN_LEFT = 20.0,
|
||||
var CPWindowSaveImage = nil,
|
||||
CPWindowSavingImage = nil,
|
||||
|
||||
CPWindowResizeTime = 0.2;
|
||||
CPWindowResizeTime = 0.2,
|
||||
CPWindowResizeStyleGlobalChangeNotification = @"CPWindowResizeStyleGlobalChangeNotification";
|
||||
|
||||
/*
|
||||
Keys for which action messages will be sent by default when unhandled, e.g. complete:.
|
||||
@@ -477,6 +483,11 @@ CPTexturedBackgroundWindowMask
|
||||
_keyViewLoopIsDirty = YES;
|
||||
|
||||
[self setShowsResizeIndicator:_styleMask & CPResizableWindowMask];
|
||||
|
||||
[[CPNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(_didReceiveResizeStyleChange:)
|
||||
name:CPWindowResizeStyleGlobalChangeNotification
|
||||
object:nil];
|
||||
}
|
||||
|
||||
return self;
|
||||
@@ -996,6 +1007,33 @@ CPTexturedBackgroundWindowMask
|
||||
return _isVisible;
|
||||
}
|
||||
|
||||
/*!
|
||||
Globally sets whether windows resize following the legacy style (using a resize thumb
|
||||
in the bottom right corner), or the modern style (no resize thumb, resizing
|
||||
can be done on all edges).
|
||||
*/
|
||||
+ (void)setGlobalResizeStyle:(int)aStyle
|
||||
{
|
||||
if (CPWindowResizeStyle === aStyle)
|
||||
return;
|
||||
|
||||
CPWindowResizeStyle = aStyle;
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPWindowResizeStyleGlobalChangeNotification object:nil];
|
||||
}
|
||||
|
||||
- (void)_didReceiveResizeStyleChange:(CPNotification)aNotification
|
||||
{
|
||||
[_windowView setShowsResizeIndicator:_styleMask & CPResizableWindowMask];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the global window resizing style.
|
||||
*/
|
||||
+ (int)globalResizeStyle
|
||||
{
|
||||
return CPWindowResizeStyle;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns \c YES if the window's resize indicator is showing. \c NO otherwise.
|
||||
*/
|
||||
@@ -1642,6 +1680,7 @@ CPTexturedBackgroundWindowMask
|
||||
// CPLeftMouseDown is needed for window moving and resizing to work.
|
||||
// CPMouseMoved is needed for rollover effects on title bar buttons.
|
||||
var sheet = [self attachedSheet];
|
||||
|
||||
if (sheet)
|
||||
{
|
||||
switch (type)
|
||||
@@ -1663,162 +1702,173 @@ CPTexturedBackgroundWindowMask
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case CPFlagsChanged: return [[self firstResponder] flagsChanged:anEvent];
|
||||
case CPFlagsChanged:
|
||||
return [[self firstResponder] flagsChanged:anEvent];
|
||||
|
||||
case CPKeyUp: return [[self firstResponder] keyUp:anEvent];
|
||||
case CPKeyUp:
|
||||
return [[self firstResponder] keyUp:anEvent];
|
||||
|
||||
case CPKeyDown: if ([anEvent charactersIgnoringModifiers] === CPTabCharacter)
|
||||
{
|
||||
if ([anEvent modifierFlags] & CPShiftKeyMask)
|
||||
[self selectPreviousKeyView:self];
|
||||
else
|
||||
[self selectNextKeyView:self];
|
||||
case CPKeyDown:
|
||||
if ([anEvent charactersIgnoringModifiers] === CPTabCharacter)
|
||||
{
|
||||
if ([anEvent modifierFlags] & CPShiftKeyMask)
|
||||
[self selectPreviousKeyView:self];
|
||||
else
|
||||
[self selectNextKeyView:self];
|
||||
#if PLATFORM(DOM)
|
||||
// Make sure the browser doesn't try to do its own tab handling.
|
||||
// This is important or the browser might blur the shared text field or token field input field,
|
||||
// even that we just moved it to a new first responder.
|
||||
[[[anEvent window] platformWindow] _propagateCurrentDOMEvent:NO]
|
||||
// Make sure the browser doesn't try to do its own tab handling.
|
||||
// This is important or the browser might blur the shared text field or token field input field,
|
||||
// even that we just moved it to a new first responder.
|
||||
[[[anEvent window] platformWindow] _propagateCurrentDOMEvent:NO]
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
else if ([anEvent charactersIgnoringModifiers] === CPBackTabCharacter)
|
||||
{
|
||||
var didTabBack = [self selectPreviousKeyView:self];
|
||||
if (didTabBack)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if ([anEvent charactersIgnoringModifiers] === CPBackTabCharacter)
|
||||
{
|
||||
var didTabBack = [self selectPreviousKeyView:self];
|
||||
|
||||
if (didTabBack)
|
||||
{
|
||||
#if PLATFORM(DOM)
|
||||
// Make sure the browser doesn't try to do its own tab handling.
|
||||
// This is important or the browser might blur the shared text field or token field input field,
|
||||
// even that we just moved it to a new first responder.
|
||||
[[[anEvent window] platformWindow] _propagateCurrentDOMEvent:NO]
|
||||
// Make sure the browser doesn't try to do its own tab handling.
|
||||
// This is important or the browser might blur the shared text field or token field input field,
|
||||
// even that we just moved it to a new first responder.
|
||||
[[[anEvent window] platformWindow] _propagateCurrentDOMEvent:NO]
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return didTabBack;
|
||||
}
|
||||
return didTabBack;
|
||||
}
|
||||
|
||||
[[self firstResponder] keyDown:anEvent];
|
||||
[[self firstResponder] keyDown:anEvent];
|
||||
|
||||
// Trigger the default button if needed
|
||||
// FIXME: Is this only applicable in a sheet? See isse: #722.
|
||||
if (![self disableKeyEquivalentForDefaultButton])
|
||||
{
|
||||
var defaultButton = [self defaultButton],
|
||||
keyEquivalent = [defaultButton keyEquivalent],
|
||||
modifierMask = [defaultButton keyEquivalentModifierMask];
|
||||
// Trigger the default button if needed
|
||||
// FIXME: Is this only applicable in a sheet? See isse: #722.
|
||||
if (![self disableKeyEquivalentForDefaultButton])
|
||||
{
|
||||
var defaultButton = [self defaultButton],
|
||||
keyEquivalent = [defaultButton keyEquivalent],
|
||||
modifierMask = [defaultButton keyEquivalentModifierMask];
|
||||
|
||||
if ([anEvent _triggersKeyEquivalent:keyEquivalent withModifierMask:modifierMask])
|
||||
[[self defaultButton] performClick:self];
|
||||
}
|
||||
if ([anEvent _triggersKeyEquivalent:keyEquivalent withModifierMask:modifierMask])
|
||||
[[self defaultButton] performClick:self];
|
||||
}
|
||||
|
||||
return;
|
||||
return;
|
||||
|
||||
case CPScrollWheel: return [[_windowView hitTest:point] scrollWheel:anEvent];
|
||||
case CPScrollWheel:
|
||||
return [[_windowView hitTest:point] scrollWheel:anEvent];
|
||||
|
||||
case CPLeftMouseUp:
|
||||
case CPRightMouseUp: var hitTestedView = _leftMouseDownView,
|
||||
selector = type == CPRightMouseUp ? @selector(rightMouseUp:) : @selector(mouseUp:);
|
||||
case CPRightMouseUp:
|
||||
var hitTestedView = _leftMouseDownView,
|
||||
selector = type == CPRightMouseUp ? @selector(rightMouseUp:) : @selector(mouseUp:);
|
||||
|
||||
if (!hitTestedView)
|
||||
hitTestedView = [_windowView hitTest:point];
|
||||
if (!hitTestedView)
|
||||
hitTestedView = [_windowView hitTest:point];
|
||||
|
||||
[hitTestedView performSelector:selector withObject:anEvent];
|
||||
[hitTestedView performSelector:selector withObject:anEvent];
|
||||
|
||||
_leftMouseDownView = nil;
|
||||
_leftMouseDownView = nil;
|
||||
|
||||
return;
|
||||
|
||||
return;
|
||||
case CPLeftMouseDown:
|
||||
case CPRightMouseDown: _leftMouseDownView = [_windowView hitTest:point];
|
||||
case CPRightMouseDown:
|
||||
_leftMouseDownView = [_windowView hitTest:point] || _windowView;
|
||||
|
||||
if (_leftMouseDownView != _firstResponder && [_leftMouseDownView acceptsFirstResponder])
|
||||
[self makeFirstResponder:_leftMouseDownView];
|
||||
if (_leftMouseDownView != _firstResponder && [_leftMouseDownView acceptsFirstResponder])
|
||||
[self makeFirstResponder:_leftMouseDownView];
|
||||
|
||||
[CPApp activateIgnoringOtherApps:YES];
|
||||
[CPApp activateIgnoringOtherApps:YES];
|
||||
|
||||
var theWindow = [anEvent window],
|
||||
selector = type == CPRightMouseDown ? @selector(rightMouseDown:) : @selector(mouseDown:);
|
||||
var theWindow = [anEvent window],
|
||||
selector = type == CPRightMouseDown ? @selector(rightMouseDown:) : @selector(mouseDown:);
|
||||
|
||||
if ([theWindow isKeyWindow] || [theWindow becomesKeyOnlyIfNeeded] && ![_leftMouseDownView needsPanelToBecomeKey])
|
||||
return [_leftMouseDownView performSelector:selector withObject:anEvent];
|
||||
else
|
||||
{
|
||||
// FIXME: delayed ordering?
|
||||
[self makeKeyAndOrderFront:self];
|
||||
if ([theWindow isKeyWindow] || [theWindow becomesKeyOnlyIfNeeded] && ![_leftMouseDownView needsPanelToBecomeKey])
|
||||
return [_leftMouseDownView performSelector:selector withObject:anEvent];
|
||||
else
|
||||
{
|
||||
// FIXME: delayed ordering?
|
||||
[self makeKeyAndOrderFront:self];
|
||||
|
||||
if ([_leftMouseDownView acceptsFirstMouse:anEvent])
|
||||
return [_leftMouseDownView performSelector:selector withObject:anEvent];
|
||||
}
|
||||
break;
|
||||
if ([_leftMouseDownView acceptsFirstMouse:anEvent])
|
||||
return [_leftMouseDownView performSelector:selector withObject:anEvent];
|
||||
}
|
||||
break;
|
||||
|
||||
case CPLeftMouseDragged:
|
||||
case CPRightMouseDragged: if (!_leftMouseDownView)
|
||||
return [[_windowView hitTest:point] mouseDragged:anEvent];
|
||||
case CPRightMouseDragged:
|
||||
if (!_leftMouseDownView)
|
||||
return [[_windowView hitTest:point] mouseDragged:anEvent];
|
||||
|
||||
var selector;
|
||||
if (type == CPRightMouseDragged)
|
||||
{
|
||||
selector = @selector(rightMouseDragged:)
|
||||
if (![_leftMouseDownView respondsToSelector:selector])
|
||||
selector = nil;
|
||||
}
|
||||
var selector;
|
||||
|
||||
if (!selector)
|
||||
selector = @selector(mouseDragged:)
|
||||
if (type == CPRightMouseDragged)
|
||||
{
|
||||
selector = @selector(rightMouseDragged:)
|
||||
if (![_leftMouseDownView respondsToSelector:selector])
|
||||
selector = nil;
|
||||
}
|
||||
|
||||
return [_leftMouseDownView performSelector:selector withObject:anEvent];
|
||||
if (!selector)
|
||||
selector = @selector(mouseDragged:)
|
||||
|
||||
case CPMouseMoved: if (!_acceptsMouseMovedEvents)
|
||||
return;
|
||||
return [_leftMouseDownView performSelector:selector withObject:anEvent];
|
||||
|
||||
if (!_mouseEnteredStack)
|
||||
_mouseEnteredStack = [];
|
||||
case CPMouseMoved:
|
||||
if (!_acceptsMouseMovedEvents)
|
||||
return;
|
||||
|
||||
var hitTestView = [_windowView hitTest:point];
|
||||
if (!_mouseEnteredStack)
|
||||
_mouseEnteredStack = [];
|
||||
|
||||
if ([_mouseEnteredStack count] && [_mouseEnteredStack lastObject] === hitTestView)
|
||||
return [hitTestView mouseMoved:anEvent];
|
||||
var hitTestView = [_windowView hitTest:point];
|
||||
|
||||
var view = hitTestView,
|
||||
mouseEnteredStack = [];
|
||||
if ([_mouseEnteredStack count] && [_mouseEnteredStack lastObject] === hitTestView)
|
||||
return [hitTestView mouseMoved:anEvent];
|
||||
|
||||
while (view)
|
||||
{
|
||||
mouseEnteredStack.unshift(view);
|
||||
var view = hitTestView,
|
||||
mouseEnteredStack = [];
|
||||
|
||||
view = [view superview];
|
||||
}
|
||||
while (view)
|
||||
{
|
||||
mouseEnteredStack.unshift(view);
|
||||
|
||||
var deviation = MIN(_mouseEnteredStack.length, mouseEnteredStack.length);
|
||||
view = [view superview];
|
||||
}
|
||||
|
||||
while (deviation--)
|
||||
if (_mouseEnteredStack[deviation] === mouseEnteredStack[deviation])
|
||||
break;
|
||||
var deviation = MIN(_mouseEnteredStack.length, mouseEnteredStack.length);
|
||||
|
||||
var index = deviation + 1,
|
||||
count = _mouseEnteredStack.length;
|
||||
while (deviation--)
|
||||
if (_mouseEnteredStack[deviation] === mouseEnteredStack[deviation])
|
||||
break;
|
||||
|
||||
if (index < count)
|
||||
{
|
||||
var event = [CPEvent mouseEventWithType:CPMouseExited location:point modifierFlags:[anEvent modifierFlags] timestamp:[anEvent timestamp] windowNumber:_windowNumber context:nil eventNumber:-1 clickCount:1 pressure:0];
|
||||
var index = deviation + 1,
|
||||
count = _mouseEnteredStack.length;
|
||||
|
||||
for (; index < count; ++index)
|
||||
[_mouseEnteredStack[index] mouseExited:event];
|
||||
}
|
||||
if (index < count)
|
||||
{
|
||||
var event = [CPEvent mouseEventWithType:CPMouseExited location:point modifierFlags:[anEvent modifierFlags] timestamp:[anEvent timestamp] windowNumber:_windowNumber context:nil eventNumber:-1 clickCount:1 pressure:0];
|
||||
|
||||
index = deviation + 1;
|
||||
count = mouseEnteredStack.length;
|
||||
for (; index < count; ++index)
|
||||
[_mouseEnteredStack[index] mouseExited:event];
|
||||
}
|
||||
|
||||
if (index < count)
|
||||
{
|
||||
var event = [CPEvent mouseEventWithType:CPMouseEntered location:point modifierFlags:[anEvent modifierFlags] timestamp:[anEvent timestamp] windowNumber:_windowNumber context:nil eventNumber:-1 clickCount:1 pressure:0];
|
||||
index = deviation + 1;
|
||||
count = mouseEnteredStack.length;
|
||||
|
||||
for (; index < count; ++index)
|
||||
[mouseEnteredStack[index] mouseEntered:event];
|
||||
}
|
||||
if (index < count)
|
||||
{
|
||||
var event = [CPEvent mouseEventWithType:CPMouseEntered location:point modifierFlags:[anEvent modifierFlags] timestamp:[anEvent timestamp] windowNumber:_windowNumber context:nil eventNumber:-1 clickCount:1 pressure:0];
|
||||
|
||||
_mouseEnteredStack = mouseEnteredStack;
|
||||
for (; index < count; ++index)
|
||||
[mouseEnteredStack[index] mouseEntered:event];
|
||||
}
|
||||
|
||||
[hitTestView mouseMoved:anEvent];
|
||||
_mouseEnteredStack = mouseEnteredStack;
|
||||
|
||||
[hitTestView mouseMoved:anEvent];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2158,6 +2208,7 @@ CPTexturedBackgroundWindowMask
|
||||
return;
|
||||
|
||||
var documents = [_windowController documents];
|
||||
|
||||
if ([documents count])
|
||||
{
|
||||
var index = [documents indexOfObject:[_windowController document]];
|
||||
@@ -3229,6 +3280,15 @@ var keyViewComparator = function(lhs, rhs, context)
|
||||
return CGRectContainsPoint(_frame, aPoint);
|
||||
}
|
||||
|
||||
- (BOOL)_isValidMousePoint:(CGPoint)aPoint
|
||||
{
|
||||
// If we are using the new resizing mode, mouse events are valid
|
||||
// outside the window's frame.
|
||||
var mouseFrame = ((_styleMask & CPResizableWindowMask) && (CPWindowResizeStyle === CPWindowResizeStyleModern)) ? _CGRectInset(_frame, -CPWindowResizeSlop, -CPWindowResizeSlop) : _frame;
|
||||
|
||||
return CGRectContainsPoint(mouseFrame, aPoint);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation CPWindow (Deprecated)
|
||||
|
||||
Reference in new issue
Block a user