API  1.0.0
CPWindow.j
Go to the documentation of this file.
1 /*
2  * CPWindow.j
3  * AppKit
4  *
5  * Created by Francisco Tolmasky.
6  * Copyright 2008, 280 North, Inc.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 
24 #if PLATFORM(BROWSER)
25 #endif
26 
27 
28 @global CPApp
29 @global _CPPlatformWindowWillCloseNotification
30 
31 @typedef _CPWindowFullPlatformWindowSession
32 
33 
34 @protocol CPWindowDelegate <CPObject>
35 
36 @optional
37 - (BOOL)windowShouldClose:(CPWindow)aWindow;
38 - (CGSize)windowWillResize:(CPWindow)sender toSize:(CGSize)aSize;
39 - (CPUndoManager)windowWillReturnUndoManager:(CPWindow)window;
40 - (void)windowDidBecomeKey:(CPNotification)aNotification;
41 - (void)windowDidBecomeMain:(CPNotification)aNotification;
42 - (void)windowDidDeminiaturize:(CPNotification)notification;
43 - (void)windowDidEndSheet:(CPNotification)aNotification;
44 - (void)windowDidMiniaturize:(CPNotification)notification;
45 - (void)windowDidMove:(CPNotification)aNotification;
46 - (void)windowDidResignKey:(CPNotification)aNotification;
47 - (void)windowDidResignMain:(CPNotification)aNotification;
48 - (void)windowDidResize:(CPNotification)aNotification;
49 - (void)windowWillMiniaturize:(CPNotification)notification;
50 - (void)windowWillBeginSheet:(CPNotification)aNotification;
51 - (void)windowWillClose:(CPWindow)aWindow;
52 
53 @end
54 
59 
60 
62 
64  CPWindowResizeStyleGlobalChangeNotification = @"CPWindowResizeStyleGlobalChangeNotification",
65 
68 
69 /*
70  Keys for which action messages will be sent by default when unhandled, e.g. complete:.
71 */
73  CPLeftArrowFunctionKey,
74  CPRightArrowFunctionKey,
75  CPUpArrowFunctionKey,
76  CPDownArrowFunctionKey,
77  CPPageUpFunctionKey,
78  CPPageDownFunctionKey,
79  CPHomeFunctionKey,
80  CPEndFunctionKey,
81  CPEscapeFunctionKey
82  ];
83 
139 @implementation CPWindow : CPResponder
140 {
141  CPPlatformWindow _platformWindow;
142 
143  int _windowNumber;
144  unsigned _styleMask;
145  CGRect _frame;
146  int _level;
147  BOOL _isVisible;
148  BOOL _hasBeenOrderedIn;
149  BOOL _isMiniaturized;
150  BOOL _isAnimating;
151  BOOL _hasShadow;
152  BOOL _isMovableByWindowBackground;
153  BOOL _isMovable;
154  BOOL _constrainsToUsableScreen;
155  unsigned _shadowStyle;
156  BOOL _showsResizeIndicator;
157 
158  int _positioningMask;
159  CGRect _positioningScreenRect;
160 
161  BOOL _isDocumentEdited;
162  BOOL _isDocumentSaving;
163 
164  CPImageView _shadowView;
165 
166  CPView _windowView;
167  CPView _contentView;
168  CPView _toolbarView;
169 
170  BOOL _handlingTrackingAreaEvent;
171  BOOL _restartHandlingTrackingAreaEvent;
172  CPArray _previousMouseEnteredStack;
173  CPArray _previousCursorUpdateStack;
174  CPArray _mouseEnteredStack;
175  CPArray _cursorUpdateStack;
176  CPArray _queuedEvents;
177  CPArray _trackingAreaViews;
178  id _activeCursorTrackingArea;
179  CPArray _queuedTrackingEvents;
180  CPView _leftMouseDownView;
181  CPView _rightMouseDownView;
182 
183  CPToolbar _toolbar;
184  CPResponder _firstResponder;
185  CPResponder _initialFirstResponder;
186  BOOL _hasBecomeKeyWindow;
187  id <CPWindowDelegate> _delegate;
188  unsigned _implementedDelegateMethods;
189 
190  CPString _title;
191 
192  BOOL _acceptsMouseMovedEvents;
193  BOOL _ignoresMouseEvents;
194 
195  CPWindowController _windowController;
196 
197  CGSize _minSize;
198  CGSize _maxSize;
199 
200  CPUndoManager _undoManager;
201  CPURL _representedURL;
202 
203  CPSet _registeredDraggedTypes;
204  CPArray _registeredDraggedTypesArray;
205  CPCountedSet _inclusiveRegisteredDraggedTypes;
206 
207  CPButton _defaultButton;
208  BOOL _defaultButtonEnabled;
209  BOOL _defaultButtonDisabledTemporarily;
210 
211  BOOL _autorecalculatesKeyViewLoop;
212  BOOL _keyViewLoopIsDirty;
213 
214  BOOL _sharesChromeWithPlatformWindow;
215 
216  // Bridge Support
217 #if PLATFORM(DOM)
218  DOMElement _DOMElement;
219 #endif
220 
221  unsigned _autoresizingMask;
222 
223  BOOL _isFullPlatformWindow;
224  _CPWindowFullPlatformWindowSession _fullPlatformWindowSession;
225 
226  CPWindow _parentWindow;
227  CPArray _childWindows;
228  CPWindowOrderingMode _childOrdering;
229 
230  CPDictionary _sheetContext;
231  CPWindow _parentView;
232  BOOL _isSheet;
233  _CPWindowFrameAnimation _frameAnimation;
234  _CPWindowFrameAnimationDelegate _frameAnimationDelegate;
235 }
236 
237 + (Class)_binderClassForBinding:(CPString)aBinding
238 {
239  if ([aBinding hasPrefix:CPDisplayPatternTitleBinding])
240  return [CPTitleWithPatternBinding class];
241 
242  return [super _binderClassForBinding:aBinding];
243 }
244 
245 - (id)init
246 {
247  return [self initWithContentRect:CGRectMakeZero() styleMask:CPTitledWindowMask];
248 }
249 
265 - (id)initWithContentRect:(CGRect)aContentRect styleMask:(unsigned)aStyleMask
266 {
267  self = [super init];
268 
269  if (self)
270  {
271  var windowViewClass = [[self class] _windowViewClassForStyleMask:aStyleMask];
272 
273  _frame = [windowViewClass frameRectForContentRect:aContentRect];
274  _constrainsToUsableScreen = YES;
275 
276  [self _setSharesChromeWithPlatformWindow:![CPPlatform isBrowser]];
277 
278  if ([CPPlatform isBrowser])
280  else
281  {
282  // give zero sized borderless bridge windows a default size.
283  if ((aStyleMask & CPBorderlessBridgeWindowMask) && aContentRect.size.width === 0 && aContentRect.size.height === 0)
284  {
285  var visibleFrame = [[[CPScreen alloc] init] visibleFrame];
286  _frame.size.height = MIN(768.0, visibleFrame.size.height);
287  _frame.size.width = MIN(1024.0, visibleFrame.size.width);
288  _frame.origin.x = (visibleFrame.size.width - _frame.size.width) / 2;
289  _frame.origin.y = (visibleFrame.size.height - _frame.size.height) / 2;
290  }
291 
293  [self platformWindow]._only = self;
294  }
295 
296  _isFullPlatformWindow = NO;
297  _registeredDraggedTypes = [CPSet set];
298  _registeredDraggedTypesArray = [];
299  _acceptsMouseMovedEvents = YES;
300  _isMovable = YES;
301  _hasBeenOrderedIn = NO;
302 
303  _parentWindow = nil;
304  _childWindows = [];
305  _childOrdering = CPWindowOut;
306 
307  _isSheet = NO;
308  _sheetContext = nil;
309  _parentView = nil;
310  _frameAnimation = nil;
311  _frameAnimationDelegate = nil;
312 
313  // Set up our window number.
314  _windowNumber = [CPApp._windows count];
315  CPApp._windows[_windowNumber] = self;
316 
317  _styleMask = aStyleMask;
318 
319  [self setLevel:CPNormalWindowLevel];
320 
321  _handlingTrackingAreaEvent = NO;
322  _restartHandlingTrackingAreaEvent = NO;
323  _trackingAreaViews = [];
324  _previousMouseEnteredStack = [];
325  _previousCursorUpdateStack = [];
326  _mouseEnteredStack = [];
327  _cursorUpdateStack = [];
328  _queuedEvents = [];
329  _queuedTrackingEvents = [];
330  _activeCursorTrackingArea = nil;
331 
332  // Create our border view which is the actual root of our view hierarchy.
333  _windowView = [[windowViewClass alloc] initWithFrame:CGRectMake(0.0, 0.0, CGRectGetWidth(_frame), CGRectGetHeight(_frame)) styleMask:aStyleMask];
334 
335  [_windowView _setWindow:self];
336  [_windowView setNextResponder:self];
337 
338  // Size calculation needs _windowView
339  _minSize = [self _calculateMinSizeForProposedSize:CGSizeMake(0.0, 0.0)];
340  _maxSize = CGSizeMake(1000000.0, 1000000.0);
341 
342  [self setMovableByWindowBackground:aStyleMask & CPHUDBackgroundWindowMask];
343 
344  // Create a generic content view.
345  [self setContentView:[[CPView alloc] initWithFrame:CGRectMakeZero()]];
346 
347  _firstResponder = self;
348 
349 #if PLATFORM(DOM)
350  _DOMElement = document.createElement("div");
351 
352  _DOMElement.style.position = "absolute";
353  _DOMElement.style.visibility = "visible";
354  _DOMElement.style.zIndex = 0;
355 
356  if (![self _sharesChromeWithPlatformWindow])
357  {
358  CPDOMDisplayServerSetStyleLeftTop(_DOMElement, NULL, CGRectGetMinX(_frame), CGRectGetMinY(_frame));
359  }
360 
361  CPDOMDisplayServerSetStyleSize(_DOMElement, 1, 1);
362  CPDOMDisplayServerAppendChild(_DOMElement, _windowView._DOMElement);
363 #endif
364 
365  [self setNextResponder:CPApp];
366 
367  [self setHasShadow:aStyleMask !== CPBorderlessWindowMask];
368 
369  if (aStyleMask & CPBorderlessBridgeWindowMask)
370  [self setFullPlatformWindow:YES];
371 
372  _autorecalculatesKeyViewLoop = NO;
373  _defaultButtonEnabled = YES;
374  _defaultButtonDisabledTemporarily = NO;
375  _keyViewLoopIsDirty = NO;
376  _hasBecomeKeyWindow = NO;
377 
378  [self setShowsResizeIndicator:_styleMask & CPResizableWindowMask];
379 
382  name:CPWindowResizeStyleGlobalChangeNotification
383  object:nil];
384  }
385 
386  return self;
387 }
388 
389 - (CPPlatformWindow)platformWindow
390 {
391  return _platformWindow;
392 }
393 
399 - (void)setPlatformWindow:(CPPlatformWindow)aPlatformWindow
400 {
401  var wasVisible = [self isVisible];
402 
403  // we have to close it first, otherwise we get a DOM exception.
404  if (wasVisible)
405  [self close];
406 
407  _platformWindow = aPlatformWindow;
408  [_platformWindow _setTitle:_title window:self];
409 
410  if (wasVisible)
411  [self orderFront:self];
412 }
413 
414 
418 + (Class)_windowViewClassForStyleMask:(unsigned)aStyleMask
419 {
420  if (aStyleMask & CPHUDBackgroundWindowMask)
421  return _CPHUDWindowView;
422 
423  else if (aStyleMask === CPBorderlessWindowMask)
424  return _CPBorderlessWindowView;
425 
426  else if (aStyleMask & CPDocModalWindowMask)
427  return _CPDocModalWindowView;
428 
429  else if (aStyleMask & _CPModalWindowMask)
430  return _CPModalWindowView;
431 
432  return _CPStandardWindowView;
433 }
434 
435 + (Class)_windowViewClassForFullPlatformWindowStyleMask:(unsigned)aStyleMask
436 {
437  return _CPBorderlessBridgeWindowView;
438 }
439 
440 - (void)awakeFromCib
441 {
442  // At this time we know the final screen (or browser) size
443  // and can apply the positioning mask, if any, from the nib.
444  if (_positioningScreenRect)
445  {
446  var actualScreenRect = [CPPlatform isBrowser] ? [_platformWindow contentBounds] : [[self screen] visibleFrame],
447  frame = [self frame],
448  origin = frame.origin;
449 
450  if (actualScreenRect)
451  {
452  if ((_positioningMask & CPWindowPositionFlexibleLeft) && (_positioningMask & CPWindowPositionFlexibleRight))
453  {
454  // Proportional Horizontal.
455  origin.x *= (actualScreenRect.size.width / _positioningScreenRect.size.width);
456  }
457  else if (_positioningMask & CPWindowPositionFlexibleLeft)
458  {
459  // Fixed from Right
460  origin.x += actualScreenRect.size.width - _positioningScreenRect.size.width;
461  }
462  else if (_positioningMask & CPWindowPositionFlexibleRight)
463  {
464  // Fixed from Left
465  }
466 
467  if ((_positioningMask & CPWindowPositionFlexibleTop) && (_positioningMask & CPWindowPositionFlexibleBottom))
468  {
469  // Proportional Vertical.
470  origin.y *= (actualScreenRect.size.height / _positioningScreenRect.size.height);
471  }
472  else if (_positioningMask & CPWindowPositionFlexibleTop)
473  {
474  // Fixed from Bottom
475  origin.y += actualScreenRect.size.height - _positioningScreenRect.size.height;
476  }
477  else if (_positioningMask & CPWindowPositionFlexibleBottom)
478  {
479  // Fixed from Top
480  }
481 
482  [self setFrameOrigin:origin];
483  }
484  }
485 
486  /*
487  Calculate the key view loop if necessary. Note that Cocoa does not call recalculateKeyViewLoop when awaking a nib. If a key view loop was set in the cib, we have to chain it to the content view.
488  */
489  if ([self _hasKeyViewLoop:[_contentView subviews]])
490  {
491  var views = [self _viewsSortedByPosition],
492  count = [views count];
493 
494  // The first view is the content view.
495  // Find the first subview that has a next key view.
496  for (var i = 1; i < count; ++i)
497  {
498  var view = views[i];
499 
500  if ([view nextKeyView])
501  {
502  [_contentView setNextKeyView:view];
503  break;
504  }
505  }
506  }
507  else
508  {
509  // Cooca does NOT call the public method recalculateKeyViewLoop for nibs,
510  // but it does calculate the loop.
511  [self _doRecalculateKeyViewLoop];
512  }
513 }
514 
515 - (void)_setWindowView:(CPView)aWindowView
516 {
517  if (_windowView === aWindowView)
518  return;
519 
520  var oldWindowView = _windowView;
521 
522  _windowView = aWindowView;
523 
524  if (oldWindowView)
525  {
526  [oldWindowView _setWindow:nil];
527  [oldWindowView noteToolbarChanged];
528 
529 #if PLATFORM(DOM)
530  CPDOMDisplayServerRemoveChild(_DOMElement, oldWindowView._DOMElement);
531 #endif
532  }
533 
534  if (_windowView)
535  {
536 #if PLATFORM(DOM)
537  CPDOMDisplayServerAppendChild(_DOMElement, _windowView._DOMElement);
538 #endif
539 
540  var contentRect = [_contentView convertRect:[_contentView bounds] toView:nil];
541 
542  contentRect.origin = [self convertBaseToGlobal:contentRect.origin];
543 
544  [_windowView _setWindow:self];
545  [_windowView setNextResponder:self];
546  [_windowView addSubview:_contentView];
547  [_windowView setTitle:_title];
548  [_windowView noteToolbarChanged];
549  [_windowView setShowsResizeIndicator:[self showsResizeIndicator]];
550 
551  [self setFrame:[self frameRectForContentRect:contentRect]];
552  }
553 }
554 
555 - (CPView)_windowView
556 {
557  return _windowView;
558 }
559 
566 - (void)setFullPlatformWindow:(BOOL)shouldBeFullPlatformWindow
567 {
568  if (![_platformWindow supportsFullPlatformWindows])
569  return;
570 
571  shouldBeFullPlatformWindow = !!shouldBeFullPlatformWindow;
572 
573  if (_isFullPlatformWindow === shouldBeFullPlatformWindow)
574  return;
575 
576  _isFullPlatformWindow = shouldBeFullPlatformWindow;
577 
578  if (_isFullPlatformWindow)
579  {
580  _fullPlatformWindowSession = _CPWindowFullPlatformWindowSessionMake(_windowView, [self contentRectForFrameRect:[self frame]], [self hasShadow], [self level]);
581 
582  var fullPlatformWindowViewClass = [[self class] _windowViewClassForFullPlatformWindowStyleMask:_styleMask],
583  windowView = [[fullPlatformWindowViewClass alloc] initWithFrame:CGRectMakeZero() styleMask:_styleMask];
584 
585  if (_platformWindow != [CPPlatformWindow primaryPlatformWindow] && [_platformWindow _hasInitializeInstanceWithWindow])
586  [_platformWindow setContentRect:[self frame]];
587 
588  [self _setWindowView:windowView];
589 
590  [self setLevel:CPBackgroundWindowLevel];
591  [self setHasShadow:NO];
592  [self setAutoresizingMask:CPWindowWidthSizable | CPWindowHeightSizable];
593  [self setFrame:[_platformWindow visibleFrame]];
594  }
595  else
596  {
597  var windowView = _fullPlatformWindowSession.windowView;
598 
599  [self _setWindowView:windowView];
600 
601  [self setLevel:_fullPlatformWindowSession.level];
602  [self setHasShadow:_fullPlatformWindowSession.hasShadow];
603  [self setAutoresizingMask:CPWindowNotSizable];
604 
605  [self setFrame:[windowView frameRectForContentRect:_fullPlatformWindowSession.contentRect]];
606  }
607 }
608 
612 - (BOOL)isFullPlatformWindow
613 {
614  return _isFullPlatformWindow;
615 }
616 
620 - (unsigned)styleMask
621 {
622  return _styleMask;
623 }
624 
642 + (CGRect)frameRectForContentRect:(CGRect)aContentRect styleMask:(unsigned)aStyleMask
643 {
644  return [[[self class] _windowViewClassForStyleMask:aStyleMask] frameRectForContentRect:aContentRect];
645 }
646 
651 - (CGRect)contentRectForFrameRect:(CGRect)aFrame
652 {
653  return [_windowView contentRectForFrameRect:aFrame];
654 }
655 
661 - (CGRect)frameRectForContentRect:(CGRect)aContentRect
662 {
663  return [_windowView frameRectForContentRect:aContentRect];
664 }
665 
669 - (CGRect)frame
670 {
671  return CGRectMakeCopy(_frame);
672 }
673 
681 - (void)setFrame:(CGRect)aFrame display:(BOOL)shouldDisplay animate:(BOOL)shouldAnimate
682 {
683  [self _setFrame:aFrame display:shouldDisplay animate:shouldAnimate constrainWidth:NO constrainHeight:YES];
684 }
685 
686 - (void)_setFrame:(CGRect)aFrame display:(BOOL)shouldDisplay animate:(BOOL)shouldAnimate constrainWidth:(BOOL)shouldConstrainWidth constrainHeight:(BOOL)shouldConstrainHeight
687 {
688  var frame = CGRectMakeCopy(aFrame),
689  value = frame.origin.x,
690  delta = value - FLOOR(value);
691 
692  if (delta)
693  frame.origin.x = value > 0.879 ? CEIL(value) : FLOOR(value);
694 
695  value = frame.origin.y;
696  delta = value - FLOOR(value);
697 
698  if (delta)
699  frame.origin.y = value > 0.879 ? CEIL(value) : FLOOR(value);
700 
701  value = frame.size.width;
702  delta = value - FLOOR(value);
703 
704  if (delta)
705  frame.size.width = value > 0.15 ? CEIL(value) : FLOOR(value);
706 
707  value = frame.size.height;
708  delta = value - FLOOR(value);
709 
710  if (delta)
711  frame.size.height = value > 0.15 ? CEIL(value) : FLOOR(value);
712 
713  frame = [self _constrainFrame:frame toUsableScreenWidth:shouldConstrainWidth andHeight:shouldConstrainHeight];
714 
715  if (shouldAnimate)
716  {
717  [_frameAnimation stopAnimation];
718  _frameAnimation = [[_CPWindowFrameAnimation alloc] initWithWindow:self targetFrame:frame];
719  [_frameAnimation setDelegate:[self _frameAnimationDelegate]];
720  [_frameAnimation startAnimation];
721  }
722  else
723  {
724  var origin = _frame.origin,
725  newOrigin = frame.origin,
726  originMoved = !CGPointEqualToPoint(origin, newOrigin);
727 
728  if (originMoved)
729  {
730  delta = CGPointMake(newOrigin.x - origin.x, newOrigin.y - origin.y);
731  origin.x = newOrigin.x;
732  origin.y = newOrigin.y;
733 
734 #if PLATFORM(DOM)
735  if (![self _sharesChromeWithPlatformWindow])
736  {
737  CPDOMDisplayServerSetStyleLeftTop(_DOMElement, NULL, origin.x, origin.y);
738  }
739 #endif
740 
741  // reposition sheet
742  if ([self attachedSheet])
743  [self _setAttachedSheetFrameOrigin];
744 
745  [[CPNotificationCenter defaultCenter] postNotificationName:CPWindowDidMoveNotification object:self];
746  }
747 
748  var size = _frame.size,
749  newSize = frame.size;
750 
751  if (!CGSizeEqualToSize(size, newSize))
752  {
753  size.width = newSize.width;
754  size.height = newSize.height;
755 
756  if (!_isAnimating)
757  size = [self _sendDelegateWindowWillResizeToSize:size];
758 
759  [_windowView setFrameSize:size];
760 
761  if (_hasShadow)
762  [_shadowView setNeedsLayout];
763 
764  if (!_isAnimating)
765  [[CPNotificationCenter defaultCenter] postNotificationName:CPWindowDidResizeNotification object:self];
766  }
767 
768  if ([self _sharesChromeWithPlatformWindow])
769  [_platformWindow setContentRect:_frame];
770 
771  if (originMoved)
772  [self _moveChildWindows:delta];
773  }
774 
775  if ([_platformWindow _canUpdateContentRect] && _isFullPlatformWindow && _platformWindow != [CPPlatformWindow primaryPlatformWindow])
776  [_platformWindow setContentRect:aFrame];
777 }
778 
779 - (id)_frameAnimationDelegate
780 {
781  if (_frameAnimationDelegate == nil)
782  _frameAnimationDelegate = [[_CPWindowFrameAnimationDelegate alloc] initWithWindow:self];
783 
784  return _frameAnimationDelegate;
785 }
786 /*
787  Constrain a frame so that the window remains at least partially visible on screen,
788  moving or resizing the frame as necessary.
789 */
790 - (CGRect)_constrainFrame:(CGRect)aFrame toUsableScreenWidth:(BOOL)constrainWidth andHeight:(BOOL)constrainHeight
791 {
792  var frame = CGRectMakeCopy(aFrame);
793 
794  if (!_constrainsToUsableScreen || !_isVisible)
795  return frame;
796 
797  var usableRect = [_platformWindow usableContentFrame];
798 
799  if (constrainWidth)
800  {
801  // First move the frame right to ensure the left side is within the usable rect.
802  frame.origin.x = MAX(frame.origin.x, usableRect.origin.x);
803 
804  // Now move the frame left so that the right side is within the usable rect.
805  var maxX = MIN(CGRectGetMaxX(frame), CGRectGetMaxX(usableRect));
806  frame.origin.x = maxX - frame.size.width;
807 
808  // Finally, adjust the left + width to ensure the left side is within the usable rect.
809  var usableWidth = CGRectGetWidth(usableRect);
810 
811  if (CGRectGetWidth(frame) > usableWidth)
812  {
813  frame.origin.x = CGRectGetMinX(usableRect);
814  frame.size.width = MAX(usableWidth, _minSize.width);
815  }
816  }
817 
818  if (constrainHeight)
819  {
820  // First move the frame down to ensure the top is within the usable rect.
821  frame.origin.y = MAX(frame.origin.y, usableRect.origin.y);
822 
823  // Now move the frame up so that the bottom is within the usable rect.
824  var maxY = MIN(CGRectGetMaxY(frame), CGRectGetMaxY(usableRect));
825  frame.origin.y = maxY - frame.size.height;
826 
827  // Finally, adjust the top + height to ensure the top is within the usable rect.
828  var usableHeight = CGRectGetHeight(usableRect);
829 
830  if (CGRectGetHeight(frame) > usableHeight)
831  {
832  frame.origin.y = CGRectGetMinY(usableRect);
833  frame.size.height = MAX(usableHeight, _minSize.height);
834  }
835  }
836 
837  return frame;
838 }
839 
840 /*
841  Constrain the origin of a frame such that:
842 
843  - The window view's minimum resize width is kept onscreen at the left/right of the window.
844  - The top of the window is kept below the top of the usable content.
845  - The top of the contentView + CPWindowMinVisibleVerticalMargin is kept above the bottom of the usable content.
846 */
847 - (CGRect)_constrainOriginOfFrame:(CGRect)aFrame
848 {
849  var frame = CGRectMakeCopy(aFrame);
850 
851  if (!_constrainsToUsableScreen || !_isVisible)
852  return frame;
853 
854  var usableRect = [_platformWindow usableContentFrame],
855  minimumSize = [_windowView _minimumResizeSize];
856 
857  // First constrain x so that at least CPWindowMinVisibleHorizontalMargin is visible on the right
858  frame.origin.x = MAX(frame.origin.x, CGRectGetMinX(usableRect) + minimumSize.width - CGRectGetWidth(frame));
859 
860  // Now constrain x so that at least CPWindowMinVisibleHorizontalMargin is visible on the left
861  frame.origin.x = MIN(frame.origin.x, CGRectGetMaxX(usableRect) - minimumSize.width);
862 
863  // Now constrain y so that it is below the top of the usable content
864  frame.origin.y = MAX(frame.origin.y, CGRectGetMinY(usableRect));
865 
866  // Finally constrain y so that at least CPWindowMinVisibleHorizontalMargin is visible at the bottom
867  frame.origin.y = MIN(frame.origin.y, CGRectGetMaxY(usableRect) - CGRectGetMinY([_contentView frame]) - CPWindowMinVisibleVerticalMargin);
868 
869  return frame;
870 }
871 
872 - (void)_moveChildWindows:(CGPoint)delta
873 {
874  [_childWindows enumerateObjectsUsingBlock:function(childWindow)
875  {
876  var origin = [childWindow frame].origin;
877 
878  [childWindow setFrameOrigin:CGPointMake(origin.x + delta.x, origin.y + delta.y)];
879  }
880  ];
881 }
882 
888 - (void)setFrame:(CGRect)aFrame display:(BOOL)shouldDisplay
889 {
890  [self setFrame:aFrame display:shouldDisplay animate:NO];
891 }
892 
897 - (void)setFrame:(CGRect)aFrame
898 {
899  [self setFrame:aFrame display:YES animate:NO];
900 }
901 
906 - (void)setFrameOrigin:(CGPoint)anOrigin
907 {
908  var frame = [self _constrainOriginOfFrame:CGRectMake(anOrigin.x, anOrigin.y, _frame.size.width, _frame.size.height)];
909  [self _setFrame:frame display:YES animate:NO constrainWidth:NO constrainHeight:NO];
910 }
911 
916 - (void)setFrameSize:(CGSize)aSize
917 {
918  [self setFrame:CGRectMake(CGRectGetMinX(_frame), CGRectGetMinY(_frame), aSize.width, aSize.height) display:YES animate:NO];
919 }
920 
925 - (void)orderFront:(id)aSender
926 {
927  [self orderWindow:CPWindowAbove relativeTo:0];
928 }
929 
930 - (void)_orderFront
931 {
932 
933 #if PLATFORM(DOM)
934 
935  if (!_isVisible)
936  [_platformWindow _setShouldUpdateContentRect:NO];
937 
938  // -dw- if a sheet is clicked, the parent window should come up too
939  if (_isSheet)
940  [_parentView orderFront:self];
941 
942  // Save the boolean since it will be updated in the method order:window:relativeTo:
943  var wasVisible = _isVisible;
944 
945  [_platformWindow orderFront:self];
946  [_platformWindow order:CPWindowAbove window:self relativeTo:nil];
947 
948  // setFrame is set after ordering the window as this method can send some notifications
949  if (!wasVisible)
950  [self _setFrame:_frame display:YES animate:NO constrainWidth:YES constrainHeight:YES];
951 #endif
952 
953  if (!CPApp._keyWindow)
954  [self makeKeyWindow];
955 
956  if ([self isKeyWindow] && (_firstResponder === self || !_firstResponder))
957  [self makeFirstResponder:_initialFirstResponder];
958 
959  if (!CPApp._mainWindow)
960  [self makeMainWindow];
961 
962  [_platformWindow _setShouldUpdateContentRect:YES];
963 
964  if ([self attachedSheet])
965  [_platformWindow order:CPWindowAbove window:[self attachedSheet] relativeTo:nil];
966 }
967 
968 /*
969  Called when a parent window orders in a child window directly.
970  without going through the ordering methods in CPWindow.
971 */
972 - (void)_parentDidOrderInChild
973 {
974 }
975 
976 /*
977  Called when the window is displayed in the DOM
978 */
979 - (void)_windowWillBeAddedToTheDOM
980 {
983  name:_CPPlatformWindowWillCloseNotification
984  object:_platformWindow];
985 
986  [[self contentView] _addObservers];
987 }
988 
989 /*
990  Called when the window is removed in the DOM
991 */
992 - (void)_windowWillBeRemovedFromTheDOM
993 {
994  [[CPNotificationCenter defaultCenter] removeObserver:self name:_CPPlatformWindowWillCloseNotification object:nil];
995 
996  [[self contentView] _removeObservers];
997  _hasBecomeKeyWindow = NO;
998 }
999 
1000 
1001 /*
1002  Makes the receiver the last window in the screen ordering.
1003  @param aSender the object that requested this
1004  @ignore
1005 */
1006 - (void)orderBack:(id)aSender
1007 {
1008  [self orderWindow:CPWindowBelow relativeTo:0];
1009 }
1010 
1011 - (void)_orderBack
1012 {
1013  // FIXME: Implement this
1014 }
1015 
1020 - (void)orderOut:(id)aSender
1021 {
1022  [self orderWindow:CPWindowOut relativeTo:0];
1023 }
1024 
1025 - (void)_orderOutRecursively:(BOOL)recursive
1026 {
1027  if (!_isVisible)
1028  return;
1029 
1030  if ([self isSheet])
1031  {
1032  // -dw- as in Cocoa, orderOut: detaches the sheet and animates out
1033  [self._parentView _detachSheetWindow];
1034  return;
1035  }
1036 
1037  if (recursive)
1038  [_childWindows makeObjectsPerformSelector:@selector(_orderOutRecursively:) withObject:recursive];
1039 
1040 #if PLATFORM(DOM)
1041  if ([self _sharesChromeWithPlatformWindow])
1042  [_platformWindow orderOut:self];
1043 
1044  if (_isFullPlatformWindow && _platformWindow != [CPPlatformWindow primaryPlatformWindow])
1045  [_platformWindow orderOut:self];
1046 
1047  [_platformWindow order:CPWindowOut window:self relativeTo:nil];
1048 #endif
1049 
1050  [self makeFirstResponder:nil];
1051  [self _updateMainAndKeyWindows];
1052 }
1053 
1059 - (void)orderWindow:(CPWindowOrderingMode)orderingMode relativeTo:(int)otherWindowNumber
1060 {
1061  if (orderingMode === CPWindowOut)
1062  {
1063  // Directly ordering out will detach a child window
1064  [_parentWindow removeChildWindow:self];
1065 
1066  // In Cocoa, a window orders out its child windows only if it has no parent
1067  [self _orderOutRecursively:!_parentWindow];
1068  }
1069  else if (orderingMode === CPWindowAbove && otherWindowNumber === 0)
1070  [self _orderFront];
1071  else if (orderingMode === CPWindowBelow && otherWindowNumber === 0)
1072  [self _orderBack];
1073 #if PLATFORM(DOM)
1074  else
1075  [_platformWindow order:orderingMode window:self relativeTo:CPApp._windows[otherWindowNumber]];
1076 #endif
1077 }
1078 
1083 - (void)setLevel:(int)aLevel
1084 {
1085  if (aLevel === _level)
1086  return;
1087 
1088  [_platformWindow moveWindow:self fromLevel:_level toLevel:aLevel];
1089 
1090  _level = aLevel;
1091  [_childWindows makeObjectsPerformSelector:@selector(setLevel:) withObject:_level];
1092 
1093  if ([self _sharesChromeWithPlatformWindow])
1094  [_platformWindow setLevel:aLevel];
1095 }
1096 
1100 - (int)level
1101 {
1102  return _level;
1103 }
1104 
1108 - (BOOL)isVisible
1109 {
1110  return _isVisible;
1111 }
1112 
1118 + (void)setGlobalResizeStyle:(int)aStyle
1119 {
1120  if (CPWindowResizeStyle === aStyle)
1121  return;
1122 
1123  CPWindowResizeStyle = aStyle;
1124  [[CPNotificationCenter defaultCenter] postNotificationName:CPWindowResizeStyleGlobalChangeNotification object:nil];
1125 }
1126 
1131 + (void)setConstrainWindowsToUsableScreen:(BOOL)shouldConstrain
1132 {
1133  CPWindowConstrainToScreen = shouldConstrain;
1134 }
1135 
1139 + (BOOL)constrainWindowsToUsableScreen
1140 {
1142 }
1143 
1144 - (void)_didReceiveResizeStyleChange:(CPNotification)aNotification
1145 {
1146  [_windowView setShowsResizeIndicator:_styleMask & CPResizableWindowMask];
1147 }
1148 
1152 + (int)globalResizeStyle
1153 {
1154  return CPWindowResizeStyle;
1155 }
1156 
1160 - (BOOL)showsResizeIndicator
1161 {
1162  return _showsResizeIndicator;
1163 }
1164 
1169 - (void)setShowsResizeIndicator:(BOOL)shouldShowResizeIndicator
1170 {
1171  shouldShowResizeIndicator = !!shouldShowResizeIndicator;
1172 
1173  if (_showsResizeIndicator === shouldShowResizeIndicator)
1174  return;
1175 
1176  _showsResizeIndicator = shouldShowResizeIndicator;
1177  [_windowView setShowsResizeIndicator:[self showsResizeIndicator]];
1178 }
1179 
1183 - (CGSize)resizeIndicatorOffset
1184 {
1185  return [_windowView resizeIndicatorOffset];
1186 }
1187 
1192 - (void)setResizeIndicatorOffset:(CGSize)anOffset
1193 {
1194  [_windowView setResizeIndicatorOffset:anOffset];
1195 }
1196 
1202 - (void)setContentView:(CPView)aView
1203 {
1204  if (_contentView && _contentView !== aView)
1205  [_contentView removeFromSuperview];
1206 
1207  var bounds = CGRectMake(0.0, 0.0, CGRectGetWidth(_frame), CGRectGetHeight(_frame));
1208 
1209  _contentView = aView;
1210  [_contentView setFrame:[self contentRectForFrameRect:bounds]];
1211 
1212  [_contentView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
1213  [_windowView addSubview:_contentView];
1214 
1215  /*
1216  If the initial first responder has been set to something other than
1217  the window, set it to the window because it will no longer be valid.
1218  */
1219  if (_initialFirstResponder && _initialFirstResponder !== self)
1220  _initialFirstResponder = self;
1221 }
1222 
1226 - (CPView)contentView
1227 {
1228  return _contentView;
1229 }
1230 
1235 - (void)setAlphaValue:(float)aValue
1236 {
1237  [_windowView setAlphaValue:aValue];
1238 }
1239 
1243 - (float)alphaValue
1244 {
1245  return [_windowView alphaValue];
1246 }
1247 
1252 - (void)setBackgroundColor:(CPColor)aColor
1253 {
1254  [_windowView setBackgroundColor:aColor];
1255 }
1256 
1261 {
1262  return [_windowView backgroundColor];
1263 }
1264 
1272 - (void)setMinSize:(CGSize)aSize
1273 {
1274  if (CGSizeEqualToSize(_minSize, aSize))
1275  return;
1276 
1277  _minSize = [self _calculateMinSizeForProposedSize:aSize];
1278 
1279  var size = CGSizeMakeCopy([self frame].size),
1280  needsFrameChange = NO;
1281 
1282  if (size.width < _minSize.width)
1283  {
1284  size.width = _minSize.width;
1285  needsFrameChange = YES;
1286  }
1287 
1288  if (size.height < _minSize.height)
1289  {
1290  size.height = _minSize.height;
1291  needsFrameChange = YES;
1292  }
1293 
1294  if (needsFrameChange)
1295  [self setFrameSize:size];
1296 }
1297 
1301 - (CGSize)minSize
1302 {
1303  return _minSize;
1304 }
1305 
1307 - (CGSize)_calculateMinSizeForProposedSize:(CGSize)proposedSize
1308 {
1309  var contentFrame = [self contentRectForFrameRect:_frame],
1310  minHeight = CGRectGetHeight(_frame) - CGRectGetHeight(contentFrame);
1311 
1312  return CGSizeMake(MAX(proposedSize.width, 0), MAX(proposedSize.height, minHeight));
1313 }
1314 
1321 - (void)setMaxSize:(CGSize)aSize
1322 {
1323  if (CGSizeEqualToSize(_maxSize, aSize))
1324  return;
1325 
1326  _maxSize = CGSizeMakeCopy(aSize);
1327 
1328  var size = CGSizeMakeCopy([self frame].size),
1329  needsFrameChange = NO;
1330 
1331  if (size.width > _maxSize.width)
1332  {
1333  size.width = _maxSize.width;
1334  needsFrameChange = YES;
1335  }
1336 
1337  if (size.height > _maxSize.height)
1338  {
1339  size.height = _maxSize.height;
1340  needsFrameChange = YES;
1341  }
1342 
1343  if (needsFrameChange)
1344  [self setFrameSize:size];
1345 }
1346 
1350 - (CGSize)maxSize
1351 {
1352  return _maxSize;
1353 }
1354 
1358 - (BOOL)hasShadow
1359 {
1360  return _hasShadow;
1361 }
1362 
1363 - (void)_updateShadow
1364 {
1365  if ([self _sharesChromeWithPlatformWindow])
1366  {
1367  if (_shadowView)
1368  {
1369 #if PLATFORM(DOM)
1370  CPDOMDisplayServerRemoveChild(_DOMElement, _shadowView._DOMElement);
1371 #endif
1372  _shadowView = nil;
1373  }
1374 
1375  [_platformWindow setHasShadow:_hasShadow];
1376 
1377  return;
1378  }
1379 
1380  if (_hasShadow && !_shadowView)
1381  {
1382  _shadowView = [[_CPShadowWindowView alloc] initWithFrame:CGRectMakeZero()];
1383 
1384  [_shadowView setWindowView:_windowView];
1385  [_shadowView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
1386  [_shadowView setNeedsLayout];
1387 
1388 #if PLATFORM(DOM)
1389  CPDOMDisplayServerInsertBefore(_DOMElement, _shadowView._DOMElement, _windowView._DOMElement);
1390 #endif
1391  }
1392  else if (!_hasShadow && _shadowView)
1393  {
1394 #if PLATFORM(DOM)
1395  CPDOMDisplayServerRemoveChild(_DOMElement, _shadowView._DOMElement);
1396 #endif
1397  _shadowView = nil;
1398  }
1399 }
1400 
1405 - (void)setHasShadow:(BOOL)shouldHaveShadow
1406 {
1407  if (_hasShadow === shouldHaveShadow)
1408  return;
1409 
1410  _hasShadow = shouldHaveShadow;
1411 
1412  [self _updateShadow];
1413 }
1414 
1426 - (void)setShadowStyle:(unsigned)aStyle
1427 {
1428  _shadowStyle = aStyle;
1429 
1430  [[self platformWindow] setShadowStyle:_shadowStyle];
1431 }
1432 
1437 - (void)setDelegate:(id <CPWindowDelegate>)aDelegate
1438 {
1439  if (_delegate === aDelegate)
1440  return;
1441 
1442  var defaultCenter = [CPNotificationCenter defaultCenter];
1443 
1444  [defaultCenter removeObserver:_delegate name:CPWindowDidResignKeyNotification object:self];
1445  [defaultCenter removeObserver:_delegate name:CPWindowDidBecomeKeyNotification object:self];
1446  [defaultCenter removeObserver:_delegate name:CPWindowDidBecomeMainNotification object:self];
1447  [defaultCenter removeObserver:_delegate name:CPWindowDidResignMainNotification object:self];
1448  [defaultCenter removeObserver:_delegate name:CPWindowDidMoveNotification object:self];
1449  [defaultCenter removeObserver:_delegate name:CPWindowDidResizeNotification object:self];
1450  [defaultCenter removeObserver:_delegate name:CPWindowWillBeginSheetNotification object:self];
1451  [defaultCenter removeObserver:_delegate name:CPWindowDidEndSheetNotification object:self];
1452  [defaultCenter removeObserver:_delegate name:CPWindowDidMiniaturizeNotification object:self];
1453  [defaultCenter removeObserver:_delegate name:CPWindowDidDeminiaturizeNotification object:self];
1454  [defaultCenter removeObserver:_delegate name:CPWindowWillMiniaturizeNotification object:self];
1455 
1456  _delegate = aDelegate;
1457  _implementedDelegateMethods = 0;
1458 
1459  if ([_delegate respondsToSelector:@selector(windowShouldClose:)])
1460  _implementedDelegateMethods |= CPWindowDelegate_windowShouldClose_;
1461 
1462  if ([_delegate respondsToSelector:@selector(windowWillReturnUndoManager:)])
1463  _implementedDelegateMethods |= CPWindowDelegate_windowWillReturnUndoManager_;
1464 
1465  if ([_delegate respondsToSelector:@selector(windowWillClose:)])
1466  _implementedDelegateMethods |= CPWindowDelegate_windowWillClose_;
1467 
1468  if ([_delegate respondsToSelector:@selector(windowWillResize:toSize:)])
1469  _implementedDelegateMethods |= CPWindowDelegate_windowWillResize_toSize_;
1470 
1471  if ([_delegate respondsToSelector:@selector(windowDidResignKey:)])
1472  [defaultCenter
1473  addObserver:_delegate
1474  selector:@selector(windowDidResignKey:)
1475  name:CPWindowDidResignKeyNotification
1476  object:self];
1477 
1478  if ([_delegate respondsToSelector:@selector(windowDidBecomeKey:)])
1479  [defaultCenter
1480  addObserver:_delegate
1481  selector:@selector(windowDidBecomeKey:)
1482  name:CPWindowDidBecomeKeyNotification
1483  object:self];
1484 
1485  if ([_delegate respondsToSelector:@selector(windowDidBecomeMain:)])
1486  [defaultCenter
1487  addObserver:_delegate
1488  selector:@selector(windowDidBecomeMain:)
1489  name:CPWindowDidBecomeMainNotification
1490  object:self];
1491 
1492  if ([_delegate respondsToSelector:@selector(windowDidResignMain:)])
1493  [defaultCenter
1494  addObserver:_delegate
1495  selector:@selector(windowDidResignMain:)
1496  name:CPWindowDidResignMainNotification
1497  object:self];
1498 
1499  if ([_delegate respondsToSelector:@selector(windowDidMove:)])
1500  [defaultCenter
1501  addObserver:_delegate
1502  selector:@selector(windowDidMove:)
1503  name:CPWindowDidMoveNotification
1504  object:self];
1505 
1506  if ([_delegate respondsToSelector:@selector(windowDidResize:)])
1507  [defaultCenter
1508  addObserver:_delegate
1509  selector:@selector(windowDidResize:)
1510  name:CPWindowDidResizeNotification
1511  object:self];
1512 
1513  if ([_delegate respondsToSelector:@selector(windowWillBeginSheet:)])
1514  [defaultCenter
1515  addObserver:_delegate
1516  selector:@selector(windowWillBeginSheet:)
1517  name:CPWindowWillBeginSheetNotification
1518  object:self];
1519 
1520  if ([_delegate respondsToSelector:@selector(windowDidEndSheet:)])
1521  [defaultCenter
1522  addObserver:_delegate
1523  selector:@selector(windowDidEndSheet:)
1524  name:CPWindowDidEndSheetNotification
1525  object:self];
1526 
1527  if ([_delegate respondsToSelector:@selector(windowDidMiniaturize:)])
1528  [defaultCenter
1529  addObserver:_delegate
1530  selector:@selector(windowDidMiniaturize:)
1531  name:CPWindowDidMiniaturizeNotification
1532  object:self];
1533 
1534  if ([_delegate respondsToSelector:@selector(windowWillMiniaturize:)])
1535  [defaultCenter
1536  addObserver:_delegate
1537  selector:@selector(windowWillMiniaturize:)
1538  name:CPWindowWillMiniaturizeNotification
1539  object:self];
1540 
1541  if ([_delegate respondsToSelector:@selector(windowDidDeminiaturize:)])
1542  [defaultCenter
1543  addObserver:_delegate
1544  selector:@selector(windowDidDeminiaturize:)
1545  name:CPWindowDidDeminiaturizeNotification
1546  object:self];
1547 }
1548 
1553 {
1554  return _delegate;
1555 }
1556 
1561 - (void)setWindowController:(CPWindowController)aWindowController
1562 {
1563  _windowController = aWindowController;
1564 }
1565 
1569 - (CPWindowController)windowController
1570 {
1571  return _windowController;
1572 }
1573 
1574 - (void)doCommandBySelector:(SEL)aSelector
1575 {
1576  if ([_delegate respondsToSelector:aSelector])
1577  [_delegate performSelector:aSelector];
1578  else
1579  [super doCommandBySelector:aSelector];
1580 }
1581 
1582 - (BOOL)acceptsFirstResponder
1583 {
1584  return NO;
1585 }
1586 
1587 - (CPView)initialFirstResponder
1588 {
1589  return _initialFirstResponder;
1590 }
1591 
1592 - (void)setInitialFirstResponder:(CPView)aView
1593 {
1594  _initialFirstResponder = aView;
1595 }
1596 
1597 - (void)_setupFirstResponder
1598 {
1599  /*
1600  When the window is first made the key window, if the first responder is the window, use the initial first responder if there is one. If there is a first responder and it is not the window, ignore the initial first responder.
1601  */
1602  if (!_hasBecomeKeyWindow)
1603  {
1604  if (_firstResponder === self)
1605  {
1606  if (_initialFirstResponder)
1607  [self makeFirstResponder:_initialFirstResponder];
1608  else
1609  {
1610  // Make the first valid key view the first responder
1611  var view = [_contentView nextValidKeyView];
1612 
1613  if (view)
1614  [self makeFirstResponder:view];
1615  }
1616 
1617  return;
1618  }
1619  }
1620 
1621  if (_firstResponder)
1622  [self makeFirstResponder:_firstResponder];
1623 }
1624 
1632 - (BOOL)makeFirstResponder:(CPResponder)aResponder
1633 {
1634  if (_firstResponder === aResponder)
1635  return YES;
1636 
1637  if (![_firstResponder resignFirstResponder])
1638  return NO;
1639 
1640  if (!aResponder || ![aResponder acceptsFirstResponder] || ![aResponder becomeFirstResponder])
1641  {
1642  _firstResponder = self;
1643 
1644  return NO;
1645  }
1646 
1647  _firstResponder = aResponder;
1648 
1649  [[CPNotificationCenter defaultCenter] postNotificationName:_CPWindowDidChangeFirstResponderNotification object:self];
1650 
1651  return YES;
1652 }
1653 
1657 - (CPResponder)firstResponder
1658 {
1659  return _firstResponder;
1660 }
1661 
1662 - (BOOL)acceptsMouseMovedEvents
1663 {
1664  return _acceptsMouseMovedEvents;
1665 }
1666 
1667 - (void)setAcceptsMouseMovedEvents:(BOOL)shouldAcceptMouseMovedEvents
1668 {
1669  _acceptsMouseMovedEvents = shouldAcceptMouseMovedEvents;
1670 }
1671 
1672 - (BOOL)ignoresMouseEvents
1673 {
1674  return _ignoresMouseEvents;
1675 }
1676 
1677 - (void)setIgnoresMouseEvents:(BOOL)shouldIgnoreMouseEvents
1678 {
1679  _ignoresMouseEvents = shouldIgnoreMouseEvents;
1680 }
1681 
1682 - (void)_mouseExitedResizeRect
1683 {
1684  [[CPCursor arrowCursor] set];
1685 }
1686 
1687 // Managing Titles
1688 
1692 - (CPString)title
1693 {
1694  return _title;
1695 }
1696 
1700 - (void)setTitle:(CPString)aTitle
1701 {
1702  _title = aTitle;
1703 
1704  [_windowView setTitle:aTitle];
1705  [_platformWindow _setTitle:_title window:self];
1706 }
1707 
1711 - (void)setTitleWithRepresentedFilename:(CPString)aFilePath
1712 {
1713  [self setRepresentedFilename:aFilePath];
1714  [self setTitle:[aFilePath lastPathComponent]];
1715 }
1716 
1720 - (void)setRepresentedFilename:(CPString)aFilePath
1721 {
1722  // FIXME: urls vs filepaths and all.
1723  [self setRepresentedURL:[CPURL URLWithString:aFilePath]];
1724 }
1725 
1729 - (CPString)representedFilename
1730 {
1731  return [_representedURL absoluteString];
1732 }
1733 
1737 - (void)setRepresentedURL:(CPURL)aURL
1738 {
1739  _representedURL = aURL;
1740 }
1741 
1745 - (CPURL)representedURL
1746 {
1747  return _representedURL;
1748 }
1749 
1750 - (CPScreen)screen
1751 {
1752  return [[CPScreen alloc] init];
1753 }
1754 
1755 // Moving
1756 
1761 - (void)setMovableByWindowBackground:(BOOL)shouldBeMovableByWindowBackground
1762 {
1763  _isMovableByWindowBackground = shouldBeMovableByWindowBackground;
1764 }
1765 
1769 - (BOOL)isMovableByWindowBackground
1770 {
1771  return _isMovableByWindowBackground;
1772 }
1773 
1778 - (void)setMovable:(BOOL)shouldBeMovable
1779 {
1780  _isMovable = shouldBeMovable;
1781 }
1782 
1786 - (void)isMovable
1787 {
1788  return _isMovable;
1789 }
1790 
1794 - (void)center
1795 {
1796  if (_isFullPlatformWindow)
1797  return;
1798 
1799  var size = [self frame].size,
1800  containerSize = [CPPlatform isBrowser] ? [_platformWindow contentBounds].size : [[self screen] visibleFrame].size;
1801 
1802  var origin = CGPointMake((containerSize.width - size.width) / 2.0, (containerSize.height - size.height) / 2.0);
1803 
1804  if (origin.x < 0.0)
1805  origin.x = 0.0;
1806 
1807  if (origin.y < 0.0)
1808  origin.y = 0.0;
1809 
1810  [self setFrameOrigin:origin];
1811 }
1812 
1817 - (void)sendEvent:(CPEvent)anEvent
1818 {
1819  var type = [anEvent type],
1820  sheet = [self attachedSheet];
1821 
1822  // If a sheet is attached events get filtered here.
1823  // It is not clear what events should be passed to the view, perhaps all?
1824  // CPLeftMouseDown is needed for window moving and resizing to work.
1825  // CPMouseMoved is needed for rollover effects on title bar buttons.
1826 
1827  if (sheet && _sheetContext["isAttached"])
1828  {
1829  switch (type)
1830  {
1831  case CPLeftMouseDown:
1832 
1833  [_windowView mouseDown:anEvent];
1834 
1835  // -dw- if the window is clicked, the sheet should come to front, and become key,
1836  // and the window should be immediately behind
1837  [sheet makeKeyAndOrderFront:self];
1838 
1839  return;
1840 
1841  case CPMouseMoved:
1842  // Allow these through to the parent
1843  break;
1844 
1845  default:
1846  // Everything else is filtered
1847  return;
1848  }
1849  }
1850 
1851  var point = [anEvent locationInWindow];
1852 
1853  switch (type)
1854  {
1855  case CPAppKitDefined:
1856  return [CPApp activateIgnoringOtherApps:YES];
1857 
1858  case CPFlagsChanged:
1859  return [[self firstResponder] flagsChanged:anEvent];
1860 
1861  case CPKeyUp:
1862  return [[self firstResponder] keyUp:anEvent];
1863 
1864  case CPKeyDown:
1865  if ([anEvent charactersIgnoringModifiers] === CPTabCharacter)
1866  {
1867  if ([anEvent modifierFlags] & CPShiftKeyMask)
1868  [self selectPreviousKeyView:self];
1869  else
1870  [self selectNextKeyView:self];
1871 #if PLATFORM(DOM)
1872  // Make sure the browser doesn't try to do its own tab handling.
1873  // This is important or the browser might blur the shared text field or token field input field,
1874  // even that we just moved it to a new first responder.
1875  [[[anEvent window] platformWindow] _propagateCurrentDOMEvent:NO];
1876 #endif
1877  return;
1878  }
1879  else if ([anEvent charactersIgnoringModifiers] === CPBackTabCharacter)
1880  {
1881  var didTabBack = [self selectPreviousKeyView:self];
1882 
1883  if (didTabBack)
1884  {
1885 #if PLATFORM(DOM)
1886  // Make sure the browser doesn't try to do its own tab handling.
1887  // This is important or the browser might blur the shared text field or token field input field,
1888  // even that we just moved it to a new first responder.
1889  [[[anEvent window] platformWindow] _propagateCurrentDOMEvent:NO];
1890 #endif
1891 
1892  }
1893  return didTabBack;
1894  }
1895  else if ([anEvent charactersIgnoringModifiers] == CPEscapeFunctionKey && [self _processKeyboardUIKey:anEvent])
1896  {
1897  return;
1898  }
1899 
1900  [[self firstResponder] keyDown:anEvent];
1901 
1902  // Trigger the default button if needed
1903  if (_defaultButtonEnabled && !_defaultButtonDisabledTemporarily)
1904  {
1905  var defaultButton = [self defaultButton],
1906  keyEquivalent = [defaultButton keyEquivalent],
1907  modifierMask = [defaultButton keyEquivalentModifierMask];
1908 
1909  if ([anEvent _triggersKeyEquivalent:keyEquivalent withModifierMask:modifierMask])
1910  [[self defaultButton] performClick:self];
1911  }
1912 
1913  _defaultButtonDisabledTemporarily = NO;
1914 
1915  return;
1916 
1917  case CPScrollWheel:
1918  return [[_windowView hitTest:point] scrollWheel:anEvent];
1919 
1920  case CPLeftMouseUp:
1921  case CPRightMouseUp:
1922  var hitTestedView = _leftMouseDownView,
1923  selector = type == CPRightMouseUp ? @selector(rightMouseUp:) : @selector(mouseUp:);
1924 
1925  if (!hitTestedView)
1926  hitTestedView = [_windowView hitTest:point];
1927 
1928  [hitTestedView performSelector:selector withObject:anEvent];
1929 
1930  _leftMouseDownView = nil;
1931 
1932  // If mouseUp ends a drag operation, send delayed events for tracking views under the mouse, then flush delayed events
1933  [self _flushTrackingEventQueueForMouseAt:point];
1934 
1935  return;
1936 
1937  case CPLeftMouseDown:
1938  case CPRightMouseDown:
1939  // This will return _windowView if it is within a resize region
1940  _leftMouseDownView = [_windowView hitTest:point];
1941 
1942  if (_leftMouseDownView !== _firstResponder && [_leftMouseDownView acceptsFirstResponder])
1943  [self makeFirstResponder:_leftMouseDownView];
1944 
1945  var keyWindow = [CPApp keyWindow];
1946 
1947  // This is only when we move from a platform to another one
1948  if ([keyWindow platformWindow] != [self platformWindow])
1949  [self makeKeyAndOrderFront:self];
1950 
1951  [CPApp activateIgnoringOtherApps:YES];
1952 
1953  var theWindow = [anEvent window],
1954  selector = type == CPRightMouseDown ? @selector(rightMouseDown:) : @selector(mouseDown:);
1955 
1956  if (([theWindow _isFrontmostWindow] && [theWindow isKeyWindow]) || ([theWindow becomesKeyOnlyIfNeeded] && ![_leftMouseDownView needsPanelToBecomeKey]))
1957  return [_leftMouseDownView performSelector:selector withObject:anEvent];
1958  else
1959  {
1960  // FIXME: delayed ordering?
1961  [self makeKeyAndOrderFront:self];
1962 
1963  if ([_leftMouseDownView acceptsFirstMouse:anEvent])
1964  return [_leftMouseDownView performSelector:selector withObject:anEvent];
1965  }
1966  break;
1967 
1968  case CPLeftMouseDragged:
1969  case CPRightMouseDragged:
1970  // First, we search for any tracking area requesting CPTrackingEnabledDuringMouseDrag.
1971  // At the same time, we update the entered stack.
1972  [self _handleTrackingAreaEvent:anEvent];
1973 
1974  // Normal mouseDragged workflow
1975  if (!_leftMouseDownView)
1976  return [[_windowView hitTest:point] mouseDragged:anEvent];
1977 
1978  var selector;
1979 
1980  if (type == CPRightMouseDragged)
1981  {
1982  selector = @selector(rightMouseDragged:);
1983  if (![_leftMouseDownView respondsToSelector:selector])
1984  selector = nil;
1985  }
1986 
1987  if (!selector)
1988  selector = @selector(mouseDragged:);
1989 
1990  return [_leftMouseDownView performSelector:selector withObject:anEvent];
1991 
1992  case CPMouseMoved:
1993 
1994  // Ignore mouse moves for parents of sheets
1995  if (!_acceptsMouseMovedEvents || sheet)
1996  return;
1997 
1998  [self _handleTrackingAreaEvent:anEvent];
1999  }
2000 }
2001 
2002 - (void)_startLiveResize
2003 {
2005  postNotificationName:CPWindowWillStartLiveResizeNotification
2006  object:self];
2007 }
2008 
2009 - (void)_endLiveResize
2010 {
2012  postNotificationName:CPWindowDidEndLiveResizeNotification
2013  object:self];
2014 }
2015 
2016 - (BOOL)_inLiveResize
2017 {
2018  return [_windowView _isTracking];
2019 }
2020 
2024 - (int)windowNumber
2025 {
2026  return _windowNumber;
2027 }
2028 
2034 - (void)becomeKeyWindow
2035 {
2036  CPApp._keyWindow = self;
2037 
2038  if (_firstResponder !== self && [_firstResponder respondsToSelector:@selector(becomeKeyWindow)])
2039  [_firstResponder becomeKeyWindow];
2040 
2041  if (!_hasBecomeKeyWindow)
2042  {
2043  // The first time a window is loaded, if it does not have a key view loop
2044  // established, calculate it now.
2045  if (![self _hasKeyViewLoop:[_contentView subviews]])
2046  [self recalculateKeyViewLoop];
2047  }
2048 
2049  [self _setupFirstResponder];
2050  _hasBecomeKeyWindow = YES;
2051  _platformWindow._currentKeyWindow = self;
2052 
2053  [_windowView noteKeyWindowStateChanged];
2054  [_contentView _notifyWindowDidBecomeKey];
2055 
2057  postNotificationName:CPWindowDidBecomeKeyNotification
2058  object:self];
2059 }
2060 
2065 - (BOOL)canBecomeKeyWindow
2066 {
2067  /*
2068  In Cocoa only titled windows return YES here by default. But the main browser
2069  window in Cappuccino doesn't have a title bar even that it's both titled and
2070  resizable, so we return YES when isFullPlatformWindow too.
2071 
2072  Note that Cocoa will return NO for a non-titled, resizable window. The Cocoa documention
2073  says it will return YES if there is a "resize bar", but in practice
2074  that is not the same as the resizable mask.
2075  */
2076  return (_styleMask & CPTitledWindowMask) || [self isFullPlatformWindow] || _isSheet;
2077 }
2078 
2079  /* @ignore */
2080 - (BOOL)_isFrontmostWindow
2081 {
2082  if ([self isFullBridge])
2083  return YES;
2084 
2085  var orderedWindows = [CPApp orderedWindows];
2086 
2087  if ([orderedWindows count] == 0)
2088  return YES;
2089 
2090  if ([orderedWindows objectAtIndex:0] === self)
2091  return YES;
2092 
2093  // this is necessary, because the CPMainMenuWindow is always the first object in orderedWindows, even if another window is in front of it
2094  if ([[orderedWindows objectAtIndex:0] level] === CPMainMenuWindowLevel &&
2095  [orderedWindows count] > 1 && [orderedWindows objectAtIndex:1] === self)
2096  return YES;
2097 
2098  return NO;
2099 }
2100 
2104 - (BOOL)isKeyWindow
2105 {
2106  return [CPApp keyWindow] == self;
2107 }
2108 
2113 - (void)makeKeyAndOrderFront:(id)aSender
2114 {
2115  [self orderFront:self];
2116 
2117  [self makeKeyWindow];
2118  [self makeMainWindow];
2119 }
2120 
2124 - (void)makeKeyWindow
2125 {
2126  if ([CPApp keyWindow] === self || ![self canBecomeKeyWindow])
2127  return;
2128 
2129  [[CPApp keyWindow] resignKeyWindow];
2130  [self becomeKeyWindow];
2131 }
2132 
2136 - (void)resignKeyWindow
2137 {
2138  if (_firstResponder !== self && [_firstResponder respondsToSelector:@selector(resignKeyWindow)])
2139  [_firstResponder resignKeyWindow];
2140 
2141  if (CPApp._keyWindow === self)
2142  CPApp._keyWindow = nil;
2143 
2144  _platformWindow._currentKeyWindow = nil;
2145  [_windowView noteKeyWindowStateChanged];
2146  [_contentView _notifyWindowDidResignKey];
2147 
2149  postNotificationName:CPWindowDidResignKeyNotification
2150  object:self];
2151 }
2152 
2163 - (void)dragImage:(CPImage)anImage at:(CGPoint)imageLocation offset:(CGSize)mouseOffset event:(CPEvent)anEvent pasteboard:(CPPasteboard)aPasteboard source:(id)aSourceObject slideBack:(BOOL)slideBack
2164 {
2165  [[CPDragServer sharedDragServer] dragImage:anImage fromWindow:self at:[self convertBaseToGlobal:imageLocation] offset:mouseOffset event:anEvent pasteboard:aPasteboard source:aSourceObject slideBack:slideBack];
2166 }
2167 
2168 - (void)_noteRegisteredDraggedTypes:(CPSet)pasteboardTypes
2169 {
2170  if (!pasteboardTypes)
2171  return;
2172 
2173  if (!_inclusiveRegisteredDraggedTypes)
2174  _inclusiveRegisteredDraggedTypes = [CPCountedSet set];
2175 
2176  [_inclusiveRegisteredDraggedTypes unionSet:pasteboardTypes];
2177 }
2178 
2179 - (void)_noteUnregisteredDraggedTypes:(CPSet)pasteboardTypes
2180 {
2181  if (!pasteboardTypes)
2182  return;
2183 
2184  [_inclusiveRegisteredDraggedTypes minusSet:pasteboardTypes];
2185 
2186  if ([_inclusiveRegisteredDraggedTypes count] === 0)
2187  _inclusiveRegisteredDraggedTypes = nil;
2188 }
2189 
2200 - (void)dragView:(CPView)aView at:(CGPoint)viewLocation offset:(CGSize)mouseOffset event:(CPEvent)anEvent pasteboard:(CPPasteboard)aPasteboard source:(id)aSourceObject slideBack:(BOOL)slideBack
2201 {
2202  [[CPDragServer sharedDragServer] dragView:aView fromWindow:self at:[self convertBaseToGlobal:viewLocation] offset:mouseOffset event:anEvent pasteboard:aPasteboard source:aSourceObject slideBack:slideBack];
2203 }
2204 
2209 - (void)registerForDraggedTypes:(CPArray)pasteboardTypes
2210 {
2211  if (!pasteboardTypes)
2212  return;
2213 
2214  [self _noteUnregisteredDraggedTypes:_registeredDraggedTypes];
2215  [_registeredDraggedTypes addObjectsFromArray:pasteboardTypes];
2216  [self _noteRegisteredDraggedTypes:_registeredDraggedTypes];
2217 
2218  _registeredDraggedTypesArray = nil;
2219 }
2220 
2225 - (CPArray)registeredDraggedTypes
2226 {
2227  if (!_registeredDraggedTypesArray)
2228  _registeredDraggedTypesArray = [_registeredDraggedTypes allObjects];
2229 
2230  return _registeredDraggedTypesArray;
2231 }
2232 
2236 - (void)unregisterDraggedTypes
2237 {
2238  [self _noteUnregisteredDraggedTypes:_registeredDraggedTypes];
2239 
2240  _registeredDraggedTypes = [CPSet set];
2241  _registeredDraggedTypesArray = [];
2242 }
2243 
2244 // Accessing Editing Status
2245 
2250 - (void)setDocumentEdited:(BOOL)isDocumentEdited
2251 {
2252  if (_isDocumentEdited == isDocumentEdited)
2253  return;
2254 
2255  _isDocumentEdited = isDocumentEdited;
2256 
2257  [CPMenu _setMenuBarIconImageAlphaValue:_isDocumentEdited ? 0.5 : 1.0];
2258 
2259  [_windowView setDocumentEdited:isDocumentEdited];
2260 }
2261 
2265 - (BOOL)isDocumentEdited
2266 {
2267  return _isDocumentEdited;
2268 }
2269 
2270 - (void)setDocumentSaving:(BOOL)isDocumentSaving
2271 {
2272  if (_isDocumentSaving == isDocumentSaving)
2273  return;
2274 
2275  _isDocumentSaving = isDocumentSaving;
2276 
2277  [self _synchronizeSaveMenuWithDocumentSaving];
2278 
2279  [_windowView windowDidChangeDocumentSaving];
2280 }
2281 
2282 - (BOOL)isDocumentSaving
2283 {
2284  return _isDocumentSaving;
2285 }
2286 
2287 /* @ignore */
2288 - (void)_synchronizeSaveMenuWithDocumentSaving
2289 {
2290  if (![self isMainWindow])
2291  return;
2292 
2293  var mainMenu = [CPApp mainMenu],
2294  index = [mainMenu indexOfItemWithTitle:_isDocumentSaving ? @"Save" : @"Saving..."];
2295 
2296  if (index == CPNotFound)
2297  return;
2298 
2299  var item = [mainMenu itemAtIndex:index];
2300 
2301  if (_isDocumentSaving)
2302  {
2303  CPWindowSaveImage = [item image];
2304 
2305  [item setTitle:@"Saving..."];
2306  [item setImage:[[CPTheme defaultTheme] valueForAttributeWithName:@"spinning-regular-gif" forClass:CPProgressIndicator]];
2307  [item setEnabled:NO];
2308  }
2309  else
2310  {
2311  [item setTitle:@"Save"];
2312  [item setImage:CPWindowSaveImage];
2313  [item setEnabled:YES];
2314  }
2315 }
2316 
2317 // Minimizing Windows
2318 
2323 - (void)performMiniaturize:(id)aSender
2324 {
2325  //FIXME show stuff
2326  [self miniaturize:aSender];
2327 }
2328 
2333 - (void)miniaturize:(id)sender
2334 {
2335  [[CPNotificationCenter defaultCenter] postNotificationName:CPWindowWillMiniaturizeNotification object:self];
2336 
2337  [[self platformWindow] miniaturize:sender];
2338 
2339  [self _updateMainAndKeyWindows];
2340 
2341  [[CPNotificationCenter defaultCenter] postNotificationName:CPWindowDidMiniaturizeNotification object:self];
2342 
2343  _isMiniaturized = YES;
2344 }
2345 
2349 - (void)deminiaturize:(id)sender
2350 {
2351  [[self platformWindow] deminiaturize:sender];
2352 
2353  [[CPNotificationCenter defaultCenter] postNotificationName:CPWindowDidDeminiaturizeNotification object:self];
2354 
2355  _isMiniaturized = NO;
2356 }
2357 
2361 - (void)isMiniaturized
2362 {
2363  return _isMiniaturized;
2364 }
2365 
2366 // Closing Windows
2367 
2372 - (void)performClose:(id)aSender
2373 {
2374  if (!(_styleMask & CPClosableWindowMask))
2375  return;
2376 
2377  if ([self isFullPlatformWindow])
2378  {
2379  var event = [CPApp currentEvent];
2380 
2381  if ([event type] === CPKeyDown && [event characters] === "w" && ([event modifierFlags] & CPPlatformActionKeyMask))
2382  {
2383  [[self platformWindow] _propagateCurrentDOMEvent:YES];
2384  return;
2385  }
2386  }
2387 
2388  // The Cocoa docs say that if both the delegate and the window implement
2389  // windowShouldClose:, only the delegate receives the message.
2390  if ([self _delegateRespondsToWindowShouldClose])
2391  {
2392  if (![self _sendDelegateWindowShouldClose])
2393  return;
2394  }
2395  else if ([self respondsToSelector:@selector(windowShouldClose:)])
2396  {
2397  if (![self windowShouldClose:self])
2398  return;
2399  }
2400 
2401  var documents = [_windowController documents];
2402 
2403  if ([documents count])
2404  {
2405  var index = [documents indexOfObject:[_windowController document]];
2406 
2407  [documents[index] shouldCloseWindowController:_windowController
2408  delegate:self
2409  shouldCloseSelector:@selector(_windowControllerContainingDocument:shouldClose:contextInfo:)
2410  contextInfo:{documents:[documents copy], visited:0, index:index}];
2411  }
2412  else
2413  [self close];
2414 }
2415 
2416 - (void)_windowControllerContainingDocument:(CPDocument)document shouldClose:(BOOL)shouldClose contextInfo:(Object)context
2417 {
2418  if (shouldClose)
2419  {
2420  var windowController = [self windowController],
2421  documents = context.documents,
2422  count = [documents count],
2423  visited = ++context.visited,
2424  index = ++context.index % count;
2425 
2426  [document removeWindowController:windowController];
2427 
2428  if (visited < count)
2429  {
2430  [windowController setDocument:documents[index]];
2431 
2432  [documents[index] shouldCloseWindowController:_windowController
2433  delegate:self
2434  shouldCloseSelector:@selector(_windowControllerContainingDocument:shouldClose:contextInfo:)
2435  contextInfo:context];
2436  }
2437  else
2438  [self close];
2439  }
2440 }
2441 
2446 - (void)close
2447 {
2448  [self _sendDelegateWindowWillClose];
2449 
2450  [[CPNotificationCenter defaultCenter] postNotificationName:CPWindowWillCloseNotification object:self];
2451 
2452  [_parentWindow removeChildWindow:self];
2453  [self _orderOutRecursively:NO];
2454  [self _detachFromChildrenClosing:!_parentWindow];
2455 }
2456 
2457 - (void)_detachFromChildrenClosing:(BOOL)shouldCloseChildren
2458 {
2459  // When a window is closed, it must detach itself from all children
2460  [_childWindows enumerateObjectsUsingBlock:function(child)
2461  {
2462  [child setParentWindow:nil];
2463  }
2464  ];
2465 
2466  if (shouldCloseChildren)
2467  {
2468  [_childWindows enumerateObjectsUsingBlock:function(child)
2469  {
2470  // Cocoa does NOT call close or orderOut when closing child windows,
2471  // they are summarily closed.
2472  [child _orderOutRecursively:NO];
2473  [child _detachFromChildrenClosing:![child parentWindow]];
2474  }
2475  ];
2476  }
2477 
2478  _childWindows = [];
2479 }
2480 
2481 // Managing Main Status
2485 - (BOOL)isMainWindow
2486 {
2487  return [CPApp mainWindow] === self;
2488 }
2489 
2493 - (BOOL)canBecomeMainWindow
2494 {
2495  // Note that the Cocoa documentation says that this method returns YES if
2496  // the window is visible and has a title bar or a "resize mechanism". It turns
2497  // out a "resize mechanism" is not the same as having the resize mask set.
2498  // In practice a window must have a title bar to become main, but we make
2499  // an exception for a full platform window.
2500  return ([self isVisible] && ((_styleMask & CPTitledWindowMask) || _isFullPlatformWindow));
2501 }
2502 
2506 - (void)makeMainWindow
2507 {
2508  // Sheets cannot be main. Their parent window becomes main.
2509  if (_isSheet)
2510  {
2511  [_parentView makeMainWindow];
2512  return;
2513  }
2514 
2515  if ([CPApp mainWindow] === self || ![self canBecomeMainWindow])
2516  return;
2517 
2518  [[CPApp mainWindow] resignMainWindow];
2519  [self becomeMainWindow];
2520 }
2521 
2525 - (void)becomeMainWindow
2526 {
2527  CPApp._mainWindow = self;
2528  _platformWindow._currentMainWindow = self;
2529 
2530  [self _synchronizeSaveMenuWithDocumentSaving];
2531 
2532  [_windowView noteMainWindowStateChanged];
2533 
2535  postNotificationName:CPWindowDidBecomeMainNotification
2536  object:self];
2537 }
2538 
2542 - (void)resignMainWindow
2543 {
2545  postNotificationName:CPWindowDidResignMainNotification
2546  object:self];
2547 
2548  if (CPApp._mainWindow === self)
2549  CPApp._mainWindow = nil;
2550 
2551  _platformWindow._currentMainWindow = nil;
2552  [_windowView noteMainWindowStateChanged];
2553 }
2554 
2555 - (void)_updateMainAndKeyWindows
2556 {
2557  var allWindows = [CPApp orderedWindows],
2558  windowCount = [allWindows count];
2559 
2560  if ([self isKeyWindow])
2561  {
2562  var keyWindow = [CPApp keyWindow];
2563  [self resignKeyWindow];
2564 
2565  if (keyWindow && keyWindow !== self && [keyWindow canBecomeKeyWindow])
2566  [keyWindow makeKeyWindow];
2567  else
2568  {
2569  var mainMenu = [CPApp mainMenu],
2570  menuBarClass = objj_getClass("_CPMenuBarWindow"),
2571  menuWindow;
2572 
2573  for (var i = 0; i < windowCount; i++)
2574  {
2575  var currentWindow = allWindows[i];
2576 
2577  if ([currentWindow isKindOfClass:menuBarClass])
2578  menuWindow = currentWindow;
2579 
2580  if (currentWindow === self || currentWindow === menuWindow)
2581  continue;
2582 
2583  if ([currentWindow isVisible] && [currentWindow canBecomeKeyWindow] && [currentWindow platformWindow] == [keyWindow platformWindow])
2584  {
2585  [currentWindow makeKeyWindow];
2586  break;
2587  }
2588  }
2589 
2590  if (![CPApp keyWindow])
2591  [menuWindow makeKeyWindow];
2592  }
2593  }
2594 
2595  if ([self isMainWindow])
2596  {
2597  var mainWindow = [CPApp mainWindow];
2598  [self resignMainWindow];
2599 
2600  if (mainWindow && mainWindow !== self && [mainWindow canBecomeMainWindow])
2601  [mainWindow makeMainWindow];
2602  else
2603  {
2604  var mainMenu = [CPApp mainMenu],
2605  menuBarClass = objj_getClass("_CPMenuBarWindow"),
2606  menuWindow;
2607 
2608  for (var i = 0; i < windowCount; i++)
2609  {
2610  var currentWindow = allWindows[i];
2611 
2612  if ([currentWindow isKindOfClass:menuBarClass])
2613  menuWindow = currentWindow;
2614 
2615  if (currentWindow === self || currentWindow === menuWindow)
2616  continue;
2617 
2618  if ([currentWindow isVisible] && [currentWindow canBecomeMainWindow])
2619  {
2620  [currentWindow makeMainWindow];
2621  break;
2622  }
2623  }
2624  }
2625  }
2626 }
2627 
2628 // Managing Toolbars
2632 - (CPToolbar)toolbar
2633 {
2634  return _toolbar;
2635 }
2636 
2641 - (void)setToolbar:(CPToolbar)aToolbar
2642 {
2643  if (_toolbar === aToolbar)
2644  return;
2645 
2646  // If this has an owner, dump it!
2647  [[aToolbar _window] setToolbar:nil];
2648 
2649  // This is no longer our toolbar.
2650  [_toolbar _setWindow:nil];
2651 
2652  _toolbar = aToolbar;
2653 
2654  // THIS is our toolbar.
2655  [_toolbar _setWindow:self];
2656 
2657  [self _noteToolbarChanged];
2658 }
2659 
2660 - (void)toggleToolbarShown:(id)aSender
2661 {
2662  var toolbar = [self toolbar];
2663 
2664  [toolbar setVisible:![toolbar isVisible]];
2665 }
2666 
2667 - (void)_noteToolbarChanged
2668 {
2669  var frame = CGRectMakeCopy([self frame]),
2670  newFrame;
2671 
2672  [_windowView noteToolbarChanged];
2673 
2674  if (_isFullPlatformWindow)
2675  newFrame = [_platformWindow visibleFrame];
2676  else
2677  {
2678  newFrame = CGRectMakeCopy([self frame]);
2679 
2680  newFrame.origin = frame.origin;
2681  }
2682 
2683  [self setFrame:newFrame];
2684  /*
2685  [_windowView setAnimatingToolbar:YES];
2686  [self setFrame:frame];
2687  [self setFrame:newFrame display:YES animate:YES];
2688  [_windowView setAnimatingToolbar:NO];
2689  */
2690 }
2691 
2695 - (CPArray)childWindows
2696 {
2697  return _childWindows;
2698 }
2699 
2700 - (void)addChildWindow:(CPWindow)childWindow ordered:(CPWindowOrderingMode)orderingMode
2701 {
2702  // Don't add the child if it is already in our list
2703  if ([_childWindows indexOfObject:childWindow] >= 0)
2704  return;
2705 
2706  if (orderingMode === CPWindowAbove || orderingMode === CPWindowBelow)
2707  [_childWindows addObject:childWindow];
2708  else
2709  [CPException raise:CPInvalidArgumentException
2710  reason:_cmd + @" unrecognized ordering mode " + orderingMode];
2711 
2712  [childWindow setParentWindow:self];
2713  [childWindow _setChildOrdering:orderingMode];
2714  [childWindow setLevel:[self level]];
2715 
2716  if ([self isVisible] && ![childWindow isVisible])
2717  [childWindow orderWindow:orderingMode relativeTo:_windowNumber];
2718 }
2719 
2720 - (void)removeChildWindow:(CPWindow)childWindow
2721 {
2722  var index = [_childWindows indexOfObject:childWindow];
2723 
2724  if (index === CPNotFound)
2725  return;
2726 
2727  [_childWindows removeObjectAtIndex:index];
2728  [childWindow setParentWindow:nil];
2729 }
2730 
2731 - (CPWindow)parentWindow
2732 {
2733  return _parentWindow;
2734 }
2735 
2741 - (BOOL)_hasAncestorWindow:(CPWindow)anAncestor
2742 {
2743  if (!_parentWindow || !anAncestor)
2744  return NO;
2745 
2746  if (anAncestor === _parentWindow)
2747  return YES;
2748 
2749  return [_parentWindow _hasAncestorWindow:anAncestor];
2750 }
2751 
2752 - (CPWindow)setParentWindow:(CPWindow)parentWindow
2753 {
2754  _parentWindow = parentWindow;
2755 }
2756 
2757 - (void)_setFrame:(CGRect)aFrame delegate:(id)delegate duration:(int)duration curve:(CPAnimationCurve)curve
2758 {
2759  [_frameAnimation stopAnimation];
2760  _frameAnimation = [[_CPWindowFrameAnimation alloc] initWithWindow:self targetFrame:aFrame];
2761  [_frameAnimation setDelegate:delegate];
2762  [_frameAnimation setAnimationCurve:curve];
2763  [_frameAnimation setDuration:duration];
2764  [_frameAnimation startAnimation];
2765 }
2766 
2767 - (CPTimeInterval)animationResizeTime:(CGRect)newWindowFrame
2768 {
2769  return CPWindowResizeTime;
2770 }
2771 
2772 - (void)_setAttachedSheetFrameOrigin
2773 {
2774  // Position the sheet above the contentRect.
2775  var attachedSheet = [self attachedSheet],
2776  contentRect = [_contentView frame],
2777  sheetFrame = CGRectMakeCopy([attachedSheet frame]);
2778 
2779  sheetFrame.origin.y = CGRectGetMinY(_frame) + CGRectGetMinY(contentRect);
2780  sheetFrame.origin.x = CGRectGetMinX(_frame) + FLOOR((CGRectGetWidth(_frame) - CGRectGetWidth(sheetFrame)) / 2.0);
2781 
2782  [attachedSheet setFrame:sheetFrame display:YES animate:NO];
2783 }
2784 
2785 - (void)_previousSheetIsClosedNotification:(CPNotification)aNotification
2786 {
2787  [[CPNotificationCenter defaultCenter] removeObserver:self name:CPWindowDidEndSheetNotification object:self];
2788 
2789  var sheet = _sheetContext[@"nextSheet"],
2790  modalDelegate = _sheetContext[@"nextModalDelegate"],
2791  endSelector = _sheetContext[@"nextEndSelector"],
2792  contextInfo = _sheetContext[@"nextContextInfo"];
2793 
2794  // Needed, because when the notification CPWindowDidEndSheetNotification is sent, the sheetContext is not up to date...
2795  setTimeout(function()
2796  {
2797  [sheet._windowView _enableSheet:YES inWindow:self];
2798  [self _attachSheet:sheet modalDelegate:modalDelegate didEndSelector:endSelector contextInfo:contextInfo];
2799  }, 0)
2800 }
2801 
2802 /*
2803  Starting point for sheet session, called from CPApplication beginSheet:
2804 */
2805 - (void)_attachSheet:(CPWindow)aSheet modalDelegate:(id)aModalDelegate
2806  didEndSelector:(SEL)didEndSelector contextInfo:(id)contextInfo
2807 {
2808  if (_sheetContext)
2809  {
2810  // Here we wait till the current sheet is closed
2811  if (_sheetContext[@"isClosing"])
2812  {
2813  // Here we save the next sheet to open
2814  _sheetContext[@"nextSheet"] = aSheet;
2815  _sheetContext[@"nextModalDelegate"] = aModalDelegate;
2816  _sheetContext[@"nextEndSelector"] = didEndSelector;
2817  _sheetContext[@"nextContextInfo"] = contextInfo;
2818 
2819  [[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(_previousSheetIsClosedNotification:) name:CPWindowDidEndSheetNotification object:self];
2820  return;
2821  }
2822  else
2823  {
2824  [CPException raise:CPInternalInconsistencyException
2825  reason:@"The target window of beginSheet: already has a sheet, did you forget orderOut: ?"];
2826  return;
2827  }
2828  }
2829 
2830  _sheetContext = {
2831  "sheet": aSheet,
2832  "modalDelegate": aModalDelegate,
2833  "endSelector": didEndSelector,
2834  "contextInfo": contextInfo,
2835  "returnCode": -1,
2836  "opened": NO,
2837  "isAttached": YES,
2838  "savedConstrains": aSheet._constrainsToUsableScreen
2839  };
2840 
2841  // Sheets are not constrained, they are controlled by their parent
2842  aSheet._constrainsToUsableScreen = NO;
2843 
2844  // A timer seems to be necessary for the animation to work correctly
2846  target:self
2847  selector:@selector(_sheetShouldAnimateIn:)
2848  userInfo:nil
2849  repeats:NO];
2850 }
2851 
2852 /*
2853  Called to end the sheet. Note that orderOut: is needed to animate the sheet out, as in Cocoa.
2854  The sheet isn't completely gone until _cleanupSheetWindow gets called.
2855 */
2856 - (void)_endSheet
2857 {
2858  var delegate = _sheetContext["modalDelegate"],
2859  endSelector = _sheetContext["endSelector"];
2860 
2861  // If the sheet has been ordered out, defer didEndSelector until after sheet animates out.
2862  // This must be done since we cannot block and wait for the animation to complete.
2863  if (delegate && endSelector)
2864  {
2865  if (_sheetContext["isAttached"])
2866  delegate.isa.objj_msgSend3(delegate, endSelector, _sheetContext["sheet"], _sheetContext["returnCode"],
2867  _sheetContext["contextInfo"]);
2868  else
2869  _sheetContext["deferDidEndSelector"] = YES;
2870  }
2871 }
2872 
2873 /*
2874  Called to animate the sheet out. If called while animating in, schedules an animate
2875  out at completion
2876 */
2877 - (void)_detachSheetWindow
2878 {
2879  if (_sheetContext["isClosing"])
2880  return;
2881 
2882  _sheetContext["isAttached"] = NO;
2883  _sheetContext["isClosing"] = YES;
2884  _sheetContext["opened"] = NO;
2885 
2886  // A timer seems to be necessary for the animation to work correctly.
2887  // It would be ideal to block here and spin the event loop, until attach is complete.
2889  target:self
2890  selector:@selector(_sheetShouldAnimateOut:)
2891  userInfo:nil
2892  repeats:NO];
2893 }
2894 
2895 /*
2896  Called to cleanup sheet, when we are definitely done with it
2897 */
2898 - (void)_cleanupSheetWindow
2899 {
2900  var sheet = _sheetContext["sheet"],
2901  deferDidEnd = _sheetContext["deferDidEndSelector"];
2902 
2903  // If the parent window is modal, the sheet started its own modal session
2904  if (sheet._isModal)
2905  [CPApp stopModal];
2906 
2907  [self _removeClipForSheet:sheet];
2908 
2909  // Restore the state of window before it was sheetified
2910  sheet._isSheet = NO;
2911  [sheet._windowView _enableSheet:NO inWindow:self];
2912  sheet._constrainsToUsableScreen = _sheetContext["savedConstrains"];
2913 
2914  // Close it
2915  [sheet orderOut:self];
2916 
2917  [[CPNotificationCenter defaultCenter] postNotificationName:CPWindowDidEndSheetNotification object:self];
2918 
2919  if (deferDidEnd)
2920  {
2921  var delegate = _sheetContext["modalDelegate"],
2922  selector = _sheetContext["endSelector"],
2923  returnCode = _sheetContext["returnCode"],
2924  contextInfo = _sheetContext["contextInfo"];
2925 
2926  // Context must be destroyed, since didEnd might want to attach another sheet
2927  _sheetContext = nil;
2928  sheet._parentView = nil;
2929 
2930  if (delegate != null)
2931  delegate.isa.objj_msgSend3(delegate, selector, sheet, returnCode, contextInfo);
2932  }
2933  else
2934  {
2935  _sheetContext = nil;
2936  sheet._parentView = nil;
2937  }
2938 }
2939 
2940 /* @ignore */
2941 - (void)animationDidEnd:(id)anim
2942 {
2943  var sheet = _sheetContext["sheet"];
2944 
2945  if (anim._window != sheet)
2946  return;
2947 
2949  target:self
2950  selector:@selector(_sheetAnimationDidEnd:)
2951  userInfo:nil
2952  repeats:NO];
2953 }
2954 
2955 - (void)_sheetShouldAnimateIn:(CPTimer)timer
2956 {
2957  // Can't open sheet while opening or closing animation is going on
2958  if (_sheetContext["isOpening"] || _sheetContext["isClosing"])
2959  return;
2960 
2961  var sheet = _sheetContext["sheet"];
2962  sheet._isSheet = YES;
2963  sheet._parentView = self;
2964 
2965  [[CPNotificationCenter defaultCenter] postNotificationName:CPWindowWillBeginSheetNotification object:self];
2966 
2967  // If sheet is attached to a modal window, the sheet runs
2968  // as if itself and the parent window are modal
2969  sheet._isModal = NO;
2970 
2971  if ([CPApp modalWindow] === self)
2972  {
2973  [CPApp runModalForWindow:sheet];
2974  sheet._isModal = YES;
2975  }
2976 
2977  // The sheet starts hidden just above the top of a clip rect
2978  // TODO : Make properly for the -1 in endY
2979  var sheetFrame = [sheet frame],
2980  sheetShadowFrame = sheet._hasShadow ? [sheet._shadowView frame] : sheetFrame,
2981  frame = [self frame],
2982  originX = frame.origin.x + FLOOR((frame.size.width - sheetFrame.size.width) / 2),
2983  startFrame = CGRectMake(originX, -sheetShadowFrame.size.height, sheetFrame.size.width, sheetFrame.size.height),
2984  endY = -1 + [_windowView bodyOffset] - [[self contentView] frame].origin.y,
2985  endFrame = CGRectMake(originX, endY, sheetFrame.size.width, sheetFrame.size.height);
2986 
2987  if (_toolbar && [_windowView showsToolbar] && [self isFullPlatformWindow])
2988  {
2989  endY += [[_toolbar _toolbarView] frameSize].height;
2990  endFrame = CGRectMake(originX, endY, sheetFrame.size.width, sheetFrame.size.height);
2991  }
2992 
2993  // Move the sheet offscreen before ordering front so it doesn't appear briefly
2994  [sheet setFrameOrigin:CGPointMake(0, -13000)];
2995 
2996  // Because clipping does funny thing with the DOM, we have to orderFront before clipping
2997  [sheet orderFront:self];
2998  [self _clipSheet:sheet];
2999 
3000  [sheet setFrame:startFrame display:YES animate:NO];
3001 
3002  _sheetContext["opened"] = YES;
3003  _sheetContext["shouldClose"] = NO;
3004  _sheetContext["isOpening"] = YES;
3005 
3006  [sheet _setFrame:endFrame delegate:self duration:[self animationResizeTime:endFrame] curve:CPAnimationEaseOut];
3007 }
3008 
3009 - (void)_sheetShouldAnimateOut:(CPTimer)timer
3010 {
3011  if (_sheetContext["isOpening"])
3012  {
3013  // Allow sheet to be closed while opening, it will close when animate in completes
3014  _sheetContext["shouldClose"] = YES;
3015  return;
3016  }
3017 
3018  // The parent window can be orderedOut to disable the sheet animate out, as in Cocoa
3019  if ([self isVisible])
3020  {
3021  var sheet = _sheetContext["sheet"],
3022  sheetFrame = [sheet frame],
3023  fullHeight = sheet._hasShadow ? [sheet._shadowView frame].size.height : sheetFrame.size.height,
3024  endFrame = CGRectMakeCopy(sheetFrame),
3025  contentOrigin = [self convertBaseToGlobal:[[self contentView] frame].origin];
3026 
3027  // Don't constrain sheets, they are controlled by the parent
3028  sheet._constrainsToUsableScreen = NO;
3029 
3030  [sheet setFrameOrigin:CGPointMake(sheetFrame.origin.x, sheetFrame.origin.y - contentOrigin.y)];
3031  [self _clipSheet:sheet];
3032 
3033  endFrame.origin.y = -fullHeight;
3034  [sheet _setFrame:endFrame delegate:self duration:[self animationResizeTime:endFrame] curve:CPAnimationEaseIn];
3035  }
3036  else
3037  {
3038  [self _sheetAnimationDidEnd:nil];
3039  }
3040 }
3041 
3042 - (void)_sheetAnimationDidEnd:(CPTimer)timer
3043 {
3044  var sheet = _sheetContext["sheet"];
3045 
3046  _sheetContext["isOpening"] = NO;
3047  _sheetContext["isClosing"] = NO;
3048 
3049  if (_sheetContext["opened"] === YES)
3050  {
3051  var sheetFrame = [sheet frame],
3052  sheetOrigin = CGPointMakeCopy(sheetFrame.origin);
3053 
3054  [self _removeClipForSheet:sheet];
3055  [sheet setFrameOrigin:CGPointMake(sheetOrigin.x, [sheet frame].origin.y + sheetOrigin.y)];
3056 
3057  // we wanted to close the sheet while it animated in, do that now
3058  if (_sheetContext["shouldClose"] === YES)
3059  [self _detachSheetWindow];
3060  else
3061  [sheet makeKeyWindow];
3062  }
3063  else
3064  {
3065  // sheet is closed and not visible
3066  [self _cleanupSheetWindow];
3067  }
3068 }
3069 
3070 - (void)_clipSheet:(CPWindow)aSheet
3071 {
3072  var clipRect = [_platformWindow contentBounds];
3073  clipRect.origin.y = [self frame].origin.y + [[self contentView] frame].origin.y;
3074 
3075  [[_platformWindow layerAtLevel:_level create:NO] clipWindow:aSheet toRect:clipRect];
3076 }
3077 
3078 - (void)_removeClipForSheet:(CPWindow)aSheet
3079 {
3080  [[_platformWindow layerAtLevel:_level create:NO] removeClipForWindow:aSheet];
3081 }
3082 
3086 - (CPWindow)attachedSheet
3087 {
3088  if (_sheetContext === nil)
3089  return nil;
3090 
3091  return _sheetContext["sheet"];
3092 }
3093 
3097 - (BOOL)isSheet
3098 {
3099  return _isSheet;
3100 }
3101 
3102 //
3103 /*
3104  Used privately.
3105  @ignore
3106 */
3107 - (BOOL)becomesKeyOnlyIfNeeded
3108 {
3109  return NO;
3110 }
3111 
3116 - (BOOL)worksWhenModal
3117 {
3118  return NO;
3119 }
3120 
3121 - (BOOL)performKeyEquivalent:(CPEvent)anEvent
3122 {
3123  // FIXME: should we be starting at the root, in other words _windowView?
3124  // The evidence seems to point to no...
3125  return [_contentView performKeyEquivalent:anEvent];
3126 }
3127 
3128 - (void)keyDown:(CPEvent)anEvent
3129 {
3130  // It's not clear why we do performKeyEquivalent again here...
3131  // Perhaps to allow something to happen between sendEvent: and keyDown:?
3132  if ([anEvent _couldBeKeyEquivalent] && [self performKeyEquivalent:anEvent])
3133  return;
3134 
3135  // Apple's documentation is inconsistent with their behavior here. According to the docs
3136  // an event going of the responder chain is passed to the input system as a last resort.
3137  // However, the only methods I could get Cocoa to call automatically are
3138  // moveUp: moveDown: moveLeft: moveRight: pageUp: pageDown: and complete:
3139  // Unhandled events just travel further up the responder chain _past_ the window.
3140  if (![self _processKeyboardUIKey:anEvent])
3141  [super keyDown:anEvent];
3142 }
3143 
3144 /*
3145  @ignore
3146  Interprets the key event for action messages and sends the action message down the responder chain
3147  Cocoa only sends moveDown:, moveUp:, moveLeft:, moveRight:, pageUp:, pageDown: and complete: messages.
3148  We deviate from this by sending (the default) scrollPageUp:, scrollPageDown:, scrollToBeginningOfDocument: and scrollToEndOfDocument: for pageUp, pageDown, home and end keys.
3149  @param anEvent the event to handle.
3150  @return YES if the key event was handled, NO if no responder handled the key event
3151 */
3152 - (BOOL)_processKeyboardUIKey:(CPEvent)anEvent
3153 {
3154  var character = [anEvent charactersIgnoringModifiers];
3155 
3156  if (![CPWindowActionMessageKeys containsObject:character])
3157  return NO;
3158 
3159  var selectors = [CPKeyBinding selectorsForKey:character modifierFlags:0];
3160 
3161  if ([selectors count] <= 0)
3162  return NO;
3163 
3164  var selector = [selectors objectAtIndex:0];
3165 
3166  return [[self firstResponder] tryToPerform:selector with:self];
3167 }
3168 
3169 - (void)_dirtyKeyViewLoop
3170 {
3171  if (_autorecalculatesKeyViewLoop)
3172  _keyViewLoopIsDirty = YES;
3173 }
3174 
3175 /*
3176  Recursively traverse an array of views (depth last) until we find one that has a next or previous key view set. Return nil if none can be found.
3177 
3178  We don't use _viewsSortedByPosition here because it is wasteful to enumerate the entire view hierarchy when we will probably find a key view at the top level.
3179 */
3180 - (BOOL)_hasKeyViewLoop:(CPArray)theViews
3181 {
3182  var i,
3183  count = [theViews count];
3184 
3185  for (i = 0; i < count; ++i)
3186  {
3187  var view = theViews[i];
3188 
3189  if ([view nextKeyView] || [view previousKeyView])
3190  return YES;
3191  }
3192 
3193  for (i = 0; i < count; ++i)
3194  {
3195  var subviews = [theViews[i] subviews];
3196 
3197  if ([subviews count] && [self _hasKeyViewLoop:subviews])
3198  return YES;
3199  }
3200 
3201  return NO;
3202 }
3203 
3211 - (void)recalculateKeyViewLoop
3212 {
3213  [self _doRecalculateKeyViewLoop];
3214 }
3215 
3216 - (CPArray)_viewsSortedByPosition
3217 {
3218  var views = [CPArray arrayWithObject:_contentView];
3219 
3220  views = views.concat([self _subviewsSortedByPosition:[_contentView subviews]]);
3221 
3222  return views;
3223 }
3224 
3225 - (CPArray)_subviewsSortedByPosition:(CPArray)theSubviews
3226 {
3227  /*
3228  We first sort the subviews according to geometric order.
3229  Then we go through each subview, and if it has subviews,
3230  they are sorted and inserted after the superview. This
3231  is done recursively.
3232  */
3233  theSubviews = [theSubviews copy];
3234  [theSubviews sortUsingFunction:keyViewComparator context:nil];
3235 
3236  var sortedViews = [];
3237 
3238  for (var i = 0, count = [theSubviews count]; i < count; ++i)
3239  {
3240  var view = theSubviews[i],
3241  subviews = [view subviews];
3242 
3243  sortedViews.push(view);
3244 
3245  if ([subviews count])
3246  sortedViews = sortedViews.concat([self _subviewsSortedByPosition:subviews]);
3247  }
3248 
3249  return sortedViews;
3250 }
3251 
3252 - (void)_doRecalculateKeyViewLoop
3253 {
3254  var views = [self _viewsSortedByPosition];
3255 
3256  for (var index = 0, count = [views count]; index < count; ++index)
3257  [views[index] setNextKeyView:views[(index + 1) % count]];
3258 
3259  _keyViewLoopIsDirty = NO;
3260 }
3261 
3262 - (void)setAutorecalculatesKeyViewLoop:(BOOL)shouldRecalculate
3263 {
3264  if (_autorecalculatesKeyViewLoop === shouldRecalculate)
3265  return;
3266 
3267  _autorecalculatesKeyViewLoop = shouldRecalculate;
3268 }
3269 
3270 - (BOOL)autorecalculatesKeyViewLoop
3271 {
3272  return _autorecalculatesKeyViewLoop;
3273 }
3274 
3275 - (void)selectNextKeyView:(id)sender
3276 {
3277  if (_keyViewLoopIsDirty)
3278  [self _doRecalculateKeyViewLoop];
3279 
3280  var nextValidKeyView = nil;
3281 
3282  if ([_firstResponder isKindOfClass:[CPView class]])
3283  nextValidKeyView = [_firstResponder nextValidKeyView];
3284 
3285  if (!nextValidKeyView)
3286  {
3287  if ([_initialFirstResponder acceptsFirstResponder])
3288  nextValidKeyView = _initialFirstResponder;
3289  else
3290  nextValidKeyView = [_initialFirstResponder nextValidKeyView];
3291  }
3292 
3293  if (nextValidKeyView)
3294  [self makeFirstResponder:nextValidKeyView];
3295 }
3296 
3297 - (void)selectPreviousKeyView:(id)sender
3298 {
3299  if (_keyViewLoopIsDirty)
3300  [self _doRecalculateKeyViewLoop];
3301 
3302  var previousValidKeyView = nil;
3303 
3304  if ([_firstResponder isKindOfClass:[CPView class]])
3305  previousValidKeyView = [_firstResponder previousValidKeyView];
3306 
3307  if (!previousValidKeyView)
3308  {
3309  if ([_initialFirstResponder acceptsFirstResponder])
3310  previousValidKeyView = _initialFirstResponder;
3311  else
3312  previousValidKeyView = [_initialFirstResponder previousValidKeyView];
3313  }
3314 
3315  if (previousValidKeyView)
3316  [self makeFirstResponder:previousValidKeyView];
3317 }
3318 
3319 - (void)selectKeyViewFollowingView:(CPView)aView
3320 {
3321  if (_keyViewLoopIsDirty)
3322  [self _doRecalculateKeyViewLoop];
3323 
3324  var nextValidKeyView = [aView nextValidKeyView];
3325 
3326  if ([nextValidKeyView isKindOfClass:[CPView class]])
3327  [self makeFirstResponder:nextValidKeyView];
3328 }
3329 
3330 - (void)selectKeyViewPrecedingView:(CPView)aView
3331 {
3332  if (_keyViewLoopIsDirty)
3333  [self _doRecalculateKeyViewLoop];
3334 
3335  var previousValidKeyView = [aView previousValidKeyView];
3336 
3337  if ([previousValidKeyView isKindOfClass:[CPView class]])
3338  [self makeFirstResponder:previousValidKeyView];
3339 }
3340 
3346 - (void)setDefaultButtonCell:(CPButton)aButton
3347 {
3348  [self setDefaultButton:aButton];
3349 }
3350 
3355 - (CPButton)defaultButtonCell
3356 {
3357  return [self defaultButton];
3358 }
3359 
3366 - (void)setDefaultButton:(CPButton)aButton
3367 {
3368  if (_defaultButton === aButton)
3369  return;
3370 
3371  if ([_defaultButton keyEquivalent] === CPCarriageReturnCharacter)
3372  [_defaultButton setKeyEquivalent:nil];
3373 
3374  _defaultButton = aButton;
3375 
3376  if ([_defaultButton keyEquivalent] !== CPCarriageReturnCharacter)
3377  [_defaultButton setKeyEquivalent:CPCarriageReturnCharacter];
3378 }
3379 
3383 - (CPButton)defaultButton
3384 {
3385  return _defaultButton;
3386 }
3387 
3391 - (void)enableKeyEquivalentForDefaultButton
3392 {
3393  _defaultButtonEnabled = YES;
3394 }
3395 
3400 - (void)enableKeyEquivalentForDefaultButtonCell
3401 {
3403 }
3404 
3408 - (void)disableKeyEquivalentForDefaultButton
3409 {
3410  _defaultButtonEnabled = NO;
3411 }
3412 
3413 - (void)_temporarilyDisableKeyEquivalentForDefaultButton
3414 {
3415  _defaultButtonDisabledTemporarily = YES;
3416 }
3417 
3422 - (void)disableKeyEquivalentForDefaultButtonCell
3423 {
3425 }
3426 
3427 - (void)setValue:(id)aValue forKey:(CPString)aKey
3428 {
3429  if (aKey === CPDisplayPatternTitleBinding)
3430  [self setTitle:aValue || @""];
3431  else
3432  [super setValue:aValue forKey:aKey];
3433 }
3434 
3435 - (void)_didReceivePlatformWindowWillCloseNotification:(CPNotification)aNotification
3436 {
3437  if ([aNotification object] != _platformWindow)
3438  return;
3439 
3440  [self close];
3441 }
3442 
3443 @end
3444 
3445 var keyViewComparator = function(lhs, rhs, context)
3446 {
3447  var lhsBounds = [lhs convertRect:[lhs bounds] toView:nil],
3448  rhsBounds = [rhs convertRect:[rhs bounds] toView:nil],
3449  lhsY = CGRectGetMinY(lhsBounds),
3450  rhsY = CGRectGetMinY(rhsBounds),
3451  lhsX = CGRectGetMinX(lhsBounds),
3452  rhsX = CGRectGetMinX(rhsBounds),
3453  intersectsVertically = MIN(CGRectGetMaxY(lhsBounds), CGRectGetMaxY(rhsBounds)) - MAX(lhsY, rhsY);
3454 
3455  // If two views are "on the same line" (intersect vertically), then rely on the x comparison.
3456  if (intersectsVertically > 0)
3457  {
3458  if (lhsX < rhsX)
3459  return CPOrderedAscending;
3460 
3461  if (lhsX === rhsX)
3462  return CPOrderedSame;
3463 
3464  return CPOrderedDescending;
3465  }
3466 
3467  if (lhsY < rhsY)
3468  return CPOrderedAscending;
3469 
3470  if (lhsY === rhsY)
3471  return CPOrderedSame;
3472 
3473  return CPOrderedDescending;
3474 };
3475 
3476 
3478 
3483 - (BOOL)_delegateRespondsToWindowWillUndoManager
3484 {
3485  return _implementedDelegateMethods & CPWindowDelegate_windowWillReturnUndoManager_;
3486 }
3487 
3492 - (BOOL)_delegateRespondsToWindowShouldClose
3493 {
3494  return _implementedDelegateMethods & CPWindowDelegate_windowShouldClose_
3495 }
3496 
3501 - (BOOL)_sendDelegateWindowShouldClose
3502 {
3503  if (!(_implementedDelegateMethods & CPWindowDelegate_windowShouldClose_))
3504  return YES;
3505 
3506  return [_delegate windowShouldClose:self];
3507 }
3508 
3513 - (BOOL)_sendDelegateWindowWillReturnUndoManager
3514 {
3515  if (!(_implementedDelegateMethods & CPWindowDelegate_windowWillReturnUndoManager_))
3516  return nil;
3517 
3518  return [_delegate windowWillReturnUndoManager:self];
3519 }
3520 
3525 - (void)_sendDelegateWindowWillClose
3526 {
3527  if (!(_implementedDelegateMethods & CPWindowDelegate_windowWillClose_))
3528  return;
3529 
3530  [_delegate windowWillClose:self];
3531 }
3532 
3537 - (CGSize)_sendDelegateWindowWillResizeToSize:(CGSize)aSize
3538 {
3539  if (!(_implementedDelegateMethods & CPWindowDelegate_windowWillResize_toSize_))
3540  return aSize;
3541 
3542  return [_delegate windowWillResize:self toSize:aSize];
3543 }
3544 
3545 @end
3546 
3547 
3549 
3550 /*
3551  @ignore
3552 */
3553 - (void)resizeWithOldPlatformWindowSize:(CGSize)aSize
3554 {
3555  if ([self isFullPlatformWindow])
3556  return [self setFrame:[_platformWindow visibleFrame]];
3557 
3558  // If this window is constrainable and we are globally ignoring constraining, ignore the platform resize
3559  if ((_constrainsToUsableScreen && !CPWindowConstrainToScreen) || _autoresizingMask === CPWindowNotSizable)
3560  return;
3561 
3562  var frame = [_platformWindow contentBounds],
3563  newFrame = CGRectMakeCopy(_frame),
3564  dX = (CGRectGetWidth(frame) - aSize.width) /
3565  (((_autoresizingMask & CPWindowMinXMargin) ? 1 : 0) + (_autoresizingMask & CPWindowWidthSizable ? 1 : 0) + (_autoresizingMask & CPWindowMaxXMargin ? 1 : 0)),
3566  dY = (CGRectGetHeight(frame) - aSize.height) /
3567  ((_autoresizingMask & CPWindowMinYMargin ? 1 : 0) + (_autoresizingMask & CPWindowHeightSizable ? 1 : 0) + (_autoresizingMask & CPWindowMaxYMargin ? 1 : 0));
3568 
3569  if (_autoresizingMask & CPWindowMinXMargin)
3570  newFrame.origin.x += dX;
3571 
3572  if (_autoresizingMask & CPWindowWidthSizable)
3573  newFrame.size.width += dX;
3574 
3575  if (_autoresizingMask & CPWindowMinYMargin)
3576  newFrame.origin.y += dY;
3577 
3578  if (_autoresizingMask & CPWindowHeightSizable)
3579  newFrame.size.height += dY;
3580 
3581  [self _setFrame:newFrame display:YES animate:NO constrainWidth:YES constrainHeight:YES];
3582 }
3583 
3584 /*
3585  @ignore
3586 */
3587 - (void)setAutoresizingMask:(unsigned)anAutoresizingMask
3588 {
3589  _autoresizingMask = anAutoresizingMask;
3590 }
3591 
3592 /*
3593  @ignore
3594 */
3595 - (unsigned)autoresizingMask
3596 {
3597  return _autoresizingMask;
3598 }
3599 
3603 - (CGPoint)convertBaseToGlobal:(CGPoint)aPoint
3604 {
3605  return [CPPlatform isBrowser] ? [self convertBaseToPlatformWindow:aPoint] : [self convertBaseToScreen:aPoint];
3606 }
3607 
3612 - (CGPoint)_nativeScrollOffset
3613 {
3614 #if PLATFORM(DOM)
3615  return CGPointMake(_windowView._DOMElement.scrollLeft, _windowView._DOMElement.scrollTop);
3616 #else
3617  CGPointMake(0, 0);
3618 #endif
3619 
3620 }
3621 
3625 - (CGPoint)convertGlobalToBase:(CGPoint)aPoint
3626 {
3627  return [CPPlatform isBrowser] ? [self convertPlatformWindowToBase:aPoint] : [self convertScreenToBase:aPoint];
3628 }
3629 
3633 - (CGPoint)convertBaseToPlatformWindow:(CGPoint)aPoint
3634 {
3635  if ([self _sharesChromeWithPlatformWindow])
3636  return CGPointMakeCopy(aPoint);
3637 
3638  var origin = [self frame].origin,
3639  scrollOffset = [self _nativeScrollOffset];
3640 
3641  return CGPointMake(aPoint.x + origin.x - scrollOffset.x, aPoint.y + origin.y - scrollOffset.y);
3642 }
3643 
3647 - (CGPoint)convertPlatformWindowToBase:(CGPoint)aPoint
3648 {
3649  if ([self _sharesChromeWithPlatformWindow])
3650  return CGPointMakeCopy(aPoint);
3651 
3652  var origin = [self frame].origin,
3653  scrollOffset = [self _nativeScrollOffset];
3654 
3655  return CGPointMake(aPoint.x - origin.x + scrollOffset.x, aPoint.y - origin.y + scrollOffset.y);
3656 }
3657 
3658 - (CGPoint)convertScreenToBase:(CGPoint)aPoint
3659 {
3660  return [self convertPlatformWindowToBase:[_platformWindow convertScreenToBase:aPoint]];
3661 }
3662 
3663 - (CGPoint)convertBaseToScreen:(CGPoint)aPoint
3664 {
3665  return [_platformWindow convertBaseToScreen:[self convertBaseToPlatformWindow:aPoint]];
3666 }
3667 
3668 - (void)_setSharesChromeWithPlatformWindow:(BOOL)shouldShareFrameWithPlatformWindow
3669 {
3670  // We canna' do it captain! We just don't have the power!
3671  if (shouldShareFrameWithPlatformWindow && [CPPlatform isBrowser])
3672  return;
3673 
3674  _sharesChromeWithPlatformWindow = shouldShareFrameWithPlatformWindow;
3675 
3676  [self _updateShadow];
3677 }
3678 
3679 - (BOOL)_sharesChromeWithPlatformWindow
3680 {
3681  return _sharesChromeWithPlatformWindow;
3682 }
3683 
3684 // Undo and Redo Support
3688 - (CPUndoManager)undoManager
3689 {
3690  // If we've ever created an undo manager, return it.
3691  if (_undoManager)
3692  return _undoManager;
3693 
3694  // If not, check to see if the document has one.
3695  var documentUndoManager = [[_windowController document] undoManager];
3696 
3697  if (documentUndoManager)
3698  return documentUndoManager;
3699 
3700  // If not, check to see if the delegate has one.
3701  if ([self _delegateRespondsToWindowWillUndoManager])
3702  return [self _sendDelegateWindowWillReturnUndoManager];
3703 
3704  // If not, create one.
3705  if (!_undoManager)
3706  _undoManager = [[CPUndoManager alloc] init];
3707 
3708  return _undoManager;
3709 }
3710 
3715 - (void)undo:(id)aSender
3716 {
3717  [[self undoManager] undo];
3718 }
3719 
3724 - (void)redo:(id)aSender
3725 {
3726  [[self undoManager] redo];
3727 }
3728 
3729 - (BOOL)containsPoint:(CGPoint)aPoint
3730 {
3731  return CGRectContainsPoint(_frame, aPoint);
3732 }
3733 
3734 /* aPoint should be global */
3735 - (BOOL)_isValidMousePoint:(CGPoint)aPoint
3736 {
3737  // If we are using the new resizing mode, mouse events are valid
3738  // outside the window's frame for non-full platform windows.
3739  var mouseFrame = (!_isFullPlatformWindow && (_styleMask & CPResizableWindowMask) && (CPWindowResizeStyle === CPWindowResizeStyleModern)) ? CGRectInset(_frame, -_CPWindowViewResizeSlop, -_CPWindowViewResizeSlop) : _frame;
3740 
3741  return CGRectContainsPoint(mouseFrame, aPoint);
3742 }
3743 
3744 @end
3745 
3746 @implementation CPWindow (Deprecated)
3751 - (void)setFullBridge:(BOOL)shouldBeFullBridge
3752 {
3753  _CPReportLenientDeprecation([self class], _cmd, @selector(setFullPlatformWindow:));
3754 
3755  [self setFullPlatformWindow:shouldBeFullBridge];
3756 }
3757 
3762 - (BOOL)isFullBridge
3763 {
3764  return [self isFullPlatformWindow];
3765 }
3766 
3767 /*
3768  @ignore
3769 */
3770 - (CGPoint)convertBaseToBridge:(CGPoint)aPoint
3771 {
3772  return [self convertBaseToPlatformWindow:aPoint];
3773 }
3774 
3775 /*
3776  @ignore
3777 */
3778 - (CGPoint)convertBridgeToBase:(CGPoint)aPoint
3779 {
3780  return [self convertPlatformWindowToBase:aPoint];
3781 }
3782 
3783 @end
3784 
3785 var interpolate = function(fromValue, toValue, progress)
3786 {
3787  return fromValue + (toValue - fromValue) * progress;
3788 };
3789 
3790 /* @ignore */
3791 @implementation _CPWindowFrameAnimation : CPAnimation
3792 {
3793  CPWindow _window;
3794 
3795  CGRect _startFrame;
3796  CGRect _targetFrame;
3797 }
3798 
3799 - (id)initWithWindow:(CPWindow)aWindow targetFrame:(CGRect)aTargetFrame
3800 {
3801  self = [super initWithDuration:[aWindow animationResizeTime:aTargetFrame] animationCurve:CPAnimationLinear];
3802 
3803  if (self)
3804  {
3805  _window = aWindow;
3806 
3807  _targetFrame = CGRectMakeCopy(aTargetFrame);
3808  _startFrame = CGRectMakeCopy([_window frame]);
3809  }
3810 
3811  return self;
3812 }
3813 
3814 - (void)setCurrentProgress:(float)aProgress
3815 {
3816  [super setCurrentProgress:aProgress];
3817 
3818  var value = [self currentValue];
3819 
3820  if (value == 1.0)
3821  [_window _setAnimating:NO];
3822 
3823  var newFrame = CGRectMake(
3824  interpolate(CGRectGetMinX(_startFrame), CGRectGetMinX(_targetFrame), value),
3825  interpolate(CGRectGetMinY(_startFrame), CGRectGetMinY(_targetFrame), value),
3826  interpolate(CGRectGetWidth(_startFrame), CGRectGetWidth(_targetFrame), value),
3827  interpolate(CGRectGetHeight(_startFrame), CGRectGetHeight(_targetFrame), value));
3828 
3829  [_window setFrame:newFrame display:YES animate:NO];
3830 }
3831 
3832 @end
3833 
3834 @implementation _CPWindowFrameAnimationDelegate : CPObject
3835 {
3836  CPWindow _window;
3837 }
3838 
3839 - (id)initWithWindow:(CPWindow)aWindow
3840 {
3841  self = [super init];
3842 
3843  _window = aWindow;
3844 
3845  return self;
3846 }
3847 
3848 - (BOOL)animationShouldStart:(CPAnimation)animation
3849 {
3850  [_window _setAnimating:YES];
3851  [_window _startLiveResize];
3852 
3853  return YES;
3854 }
3855 
3856 - (void)animationDidStop:(CPAnimation)animation
3857 {
3858  [_window _setAnimating:NO];
3859  [_window _endLiveResize];
3860 }
3861 
3862 - (void)animationDidEnd:(CPAnimation)animation
3863 {
3864  [_window _setAnimating:NO];
3865  [_window _endLiveResize];
3866 }
3867 
3868 @end
3869 
3871 
3872 /* @ignore */
3873 - (id)_dragHitTest:(CGPoint)aPoint pasteboard:(CPPasteboard)aPasteboard
3874 {
3875  // If none of our views or ourselves has registered for drag events...
3876  if (!_inclusiveRegisteredDraggedTypes)
3877  return nil;
3878 
3879 // We don't need to do this because the only place this gets called
3880 // -_dragHitTest: in CPPlatformWindow does this already. Perhaps to
3881 // be safe?
3882 // if (![self containsPoint:aPoint])
3883 // return nil;
3884 
3885  var adjustedPoint = [self convertPlatformWindowToBase:aPoint],
3886  hitView = [_windowView hitTest:adjustedPoint];
3887 
3888  while (hitView && ![aPasteboard availableTypeFromArray:[hitView registeredDraggedTypes]])
3889  hitView = [hitView superview];
3890 
3891  if (hitView)
3892  return hitView;
3893 
3894  if ([aPasteboard availableTypeFromArray:[self registeredDraggedTypes]])
3895  return self;
3896 
3897  return nil;
3898 }
3899 
3900 @end
3901 
3903 
3904 - (void)_addTrackingAreaView:(CPView)aView
3905 {
3906  var trackingAreas = [aView trackingAreas];
3907 
3908  for (var i = 0; i < trackingAreas.length; i++)
3909  [self _addTrackingArea:trackingAreas[i]];
3910 }
3911 
3912 - (void)_removeTrackingAreaView:(CPView)aView
3913 {
3914  var trackingAreas = [aView trackingAreas];
3915 
3916  for (var i = 0; i < trackingAreas.length; i++)
3917  [self _removeTrackingArea:trackingAreas[i]];
3918 }
3919 
3920 - (void)_addTrackingArea:(CPTrackingArea)trackingArea
3921 {
3922  var trackingAreaView = [trackingArea view];
3923 
3924  if (![_trackingAreaViews containsObjectIdenticalTo:trackingAreaView])
3925  [_trackingAreaViews addObject:trackingAreaView];
3926 
3927  // If CPTrackingAssumeInside option is set, insert the tracking area in the events management system
3928  // in order to have the first event sent only when mouse leaves the tracking area
3929 
3930  [self _insertTrackingArea:trackingArea assumeInside:([trackingArea options] & CPTrackingAssumeInside)];
3931 }
3932 
3933 - (void)_removeTrackingArea:(CPTrackingArea)trackingArea
3934 {
3935  // If mouse is in the tracking area, we remove it from the stack to avoid to fire a future mouseExited event
3936 
3937  [self _purgeTrackingArea:trackingArea];
3938 
3939  var trackingAreaView = [trackingArea view];
3940 
3941  [_trackingAreaViews removeObjectIdenticalTo:trackingAreaView];
3942 }
3943 
3944 - (void)_insertTrackingArea:(CPTrackingArea)trackingArea assumeInside:(BOOL)assumeInside
3945 {
3946  if (_handlingTrackingAreaEvent)
3947  _restartHandlingTrackingAreaEvent = YES;
3948 
3949  if (assumeInside)
3950  {
3951  if (_handlingTrackingAreaEvent)
3952  [_mouseEnteredStack addObject:trackingArea];
3953  else
3954  [_previousMouseEnteredStack addObject:trackingArea];
3955  }
3956 }
3957 
3958 - (void)_purgeTrackingArea:(CPTrackingArea)trackingArea
3959 {
3960  if (_handlingTrackingAreaEvent)
3961  {
3962  [_mouseEnteredStack removeObjectIdenticalTo:trackingArea];
3963 
3964  var i = _queuedEvents.length;
3965 
3966  while (i--)
3967  if ([_queuedEvents[i] trackingArea] === trackingArea)
3968  [_queuedEvents removeObjectAtIndex:i];
3969 
3970  _cursorUpdateStack = [];
3971  _activeCursorTrackingArea = nil;
3972  }
3973  else
3974  {
3975  [_previousMouseEnteredStack removeObjectIdenticalTo:trackingArea];
3976  [_previousCursorUpdateStack removeObjectIdenticalTo:trackingArea];
3977  }
3978 }
3979 
3980 - (void)_handleTrackingAreaEvent:(CPEvent)anEvent
3981 {
3982  _handlingTrackingAreaEvent = YES;
3983 
3984  var point = [anEvent locationInWindow],
3985  dragging = ([anEvent type] !== CPMouseMoved);
3986 
3987  do
3988  {
3989  // Initialize this run
3990  _restartHandlingTrackingAreaEvent = NO;
3991 
3992  _mouseEnteredStack = [];
3993  _cursorUpdateStack = [];
3994 
3995  // Important remark: we must queue events to avoid running conditions when a view uses a mouse event to modify view hierarchy
3996 
3997  _queuedEvents = [];
3998 
3999  // Handle mouse entering tracking areas (and calc _mouseEnteredStack and _cursorUpdateStack)
4000 
4001  [self _handleMouseMovedAndEnteredEventsForEvent:anEvent atPoint:point dragging:dragging];
4002 
4003  // Handle mouse exiting tracking areas
4004 
4005  [self _handleMouseExitedEventsForEvent:anEvent atPoint:point dragging:dragging];
4006 
4007  // Cursor update
4008 
4009  if (_cursorUpdateStack.length > 0)
4010  {
4011  [self _handleCursorUpdateEventsForEvent:anEvent atPoint:point dragging:dragging];
4012  }
4013  else if (!dragging)
4014  {
4015  // Here, we are outside the window content view tracking area, so let _windowView set the cursor (resize cursor, ...)
4016 
4017  [_windowView setCursorForLocation:point resizing:NO];
4018  _activeCursorTrackingArea = nil;
4019  }
4020 
4021  // Send all queued events
4022  // Important remark : as an event can modify the view hierarchy, the events queue could be modified while processing it
4023 
4024  while (_queuedEvents.length > 0)
4025  {
4026  var queuedEvent = _queuedEvents[0],
4027  trackingArea = [queuedEvent trackingArea],
4028  trackingOwner = [trackingArea owner];
4029 
4030  switch ([queuedEvent type])
4031  {
4032  case CPMouseEntered:
4033  [trackingOwner mouseEntered:queuedEvent];
4034  break;
4035 
4036  case CPMouseExited:
4037  [trackingOwner mouseExited:queuedEvent];
4038  break;
4039 
4040  case CPCursorUpdate:
4041  [trackingOwner cursorUpdate:queuedEvent];
4042  break;
4043  }
4044 
4045  if (queuedEvent === _queuedEvents[0])
4046  [_queuedEvents removeObjectAtIndex:0];
4047  }
4048 
4049  // Prepare for next call
4050 
4051  _previousMouseEnteredStack = _mouseEnteredStack;
4052  _previousCursorUpdateStack = _cursorUpdateStack;
4053  }
4054  while (_restartHandlingTrackingAreaEvent)
4055 
4056  _handlingTrackingAreaEvent = NO;
4057 }
4058 
4059 - (void)_handleMouseMovedAndEnteredEventsForEvent:(CPEvent)anEvent atPoint:(CGPoint)point dragging:(BOOL)dragging
4060 {
4061  var isKeyWindow = [self isKeyWindow];
4062 
4063  for (var i = 0; i < _trackingAreaViews.length; i++)
4064  {
4065  var aView = _trackingAreaViews[i],
4066  trackingAreas = [aView trackingAreas];
4067 
4068  if ([aView isHidden])
4069  continue;
4070 
4071  for (var j = 0; j < trackingAreas.length; j++)
4072  {
4073  var aTrackingArea = trackingAreas[j],
4074  trackingOptions = [aTrackingArea options],
4075  trackingImplementedMethods = [aTrackingArea implementedOwnerMethods];
4076 
4077  if (!(((trackingOptions & CPTrackingActiveAlways) ||
4078  (trackingOptions & CPTrackingActiveInActiveApp) ||
4079  ((trackingOptions & CPTrackingActiveInKeyWindow) && isKeyWindow) ||
4080  ((trackingOptions & CPTrackingActiveWhenFirstResponder) && isKeyWindow && (_firstResponder === aView))) &&
4081  (CGRectContainsPoint([aTrackingArea windowRect], point))))
4082  {
4083  continue;
4084  }
4085 
4086  [_mouseEnteredStack addObject:aTrackingArea];
4087 
4088  if ([_previousMouseEnteredStack containsObjectIdenticalTo:aTrackingArea])
4089  {
4090  // Mouse was already in this rect so it's a mouseMoved
4091 
4092  if (!dragging && (trackingOptions & CPTrackingMouseMoved) && (trackingImplementedMethods & CPTrackingOwnerImplementsMouseMoved))
4093  [[aTrackingArea owner] mouseMoved:anEvent];
4094  }
4095  else if ((trackingOptions & CPTrackingMouseEnteredAndExited) && (trackingImplementedMethods & CPTrackingOwnerImplementsMouseEntered))
4096  {
4097  var mouseEnteredEvent = [CPEvent enterExitEventWithType:CPMouseEntered
4098  location:point
4099  modifierFlags:[anEvent modifierFlags]
4100  timestamp:[anEvent timestamp]
4101  windowNumber:_windowNumber
4102  context:nil
4103  eventNumber:-1
4104  trackingArea:aTrackingArea];
4105 
4106  if (dragging && !(trackingOptions & CPTrackingEnabledDuringMouseDrag))
4107  [self _queueTrackingEvent:mouseEnteredEvent];
4108  else
4109  [_queuedEvents addObject:mouseEnteredEvent];
4110  }
4111 
4112  if ((trackingOptions & CPTrackingCursorUpdate) && (trackingImplementedMethods & CPTrackingOwnerImplementsCursorUpdate))
4113  [_cursorUpdateStack addObject:aTrackingArea];
4114  }
4115  }
4116 }
4117 
4118 - (void)_handleMouseExitedEventsForEvent:(CPEvent)anEvent atPoint:(CGPoint)point dragging:(BOOL)dragging
4119 {
4120  // Search for exited views (were in _previousMouseEnteredStack but no more in _mouseEnteredStack)
4121 
4122  for (var i = 0; i < _previousMouseEnteredStack.length; i++)
4123  {
4124  var aTrackingArea = _previousMouseEnteredStack[i],
4125  trackingOptions = [aTrackingArea options];
4126 
4127  if ([_mouseEnteredStack containsObjectIdenticalTo:aTrackingArea])
4128  continue;
4129 
4130  // Mouse is no more in this area so it's a mouseExited
4131 
4132  if ((trackingOptions & CPTrackingMouseEnteredAndExited) && ([aTrackingArea implementedOwnerMethods] & CPTrackingOwnerImplementsMouseExited))
4133  {
4134  var theView = [aTrackingArea owner],
4135  mouseExitedEvent = [CPEvent enterExitEventWithType:CPMouseExited
4136  location:point
4137  modifierFlags:[anEvent modifierFlags]
4138  timestamp:[anEvent timestamp]
4139  windowNumber:_windowNumber
4140  context:nil
4141  eventNumber:-1
4142  trackingArea:aTrackingArea];
4143 
4144  if (dragging && !(trackingOptions & CPTrackingEnabledDuringMouseDrag))
4145  [self _queueTrackingEvent:mouseExitedEvent];
4146  else
4147  [_queuedEvents addObject:mouseExitedEvent];
4148  }
4149 
4150  // If this is the active cursor area, we reset _previousCursorUpdateStack so a new active area will be computed
4151 
4152  if (aTrackingArea === _activeCursorTrackingArea)
4153  {
4154  _previousCursorUpdateStack = [];
4155  _activeCursorTrackingArea = nil;
4156  }
4157  }
4158 }
4159 
4160 - (void)_handleCursorUpdateEventsForEvent:(CPEvent)anEvent atPoint:(CGPoint)point dragging:(BOOL)dragging
4161 {
4162  var overlappingTrackingAreas = [];
4163 
4164  for (var i = 0; i < _cursorUpdateStack.length; i++)
4165  {
4166  var aTrackingArea = _cursorUpdateStack[i];
4167 
4168  if ((![_previousCursorUpdateStack containsObjectIdenticalTo:aTrackingArea]) || (aTrackingArea === _activeCursorTrackingArea))
4169  [overlappingTrackingAreas addObject:aTrackingArea];
4170  }
4171 
4172  if (overlappingTrackingAreas.length === 0)
4173  return;
4174 
4175  var frontmostTrackingArea = overlappingTrackingAreas[0],
4176  frontmostView = [frontmostTrackingArea view];
4177 
4178  for (var i = 1; i < overlappingTrackingAreas.length; i++)
4179  {
4180  var aTrackingArea = overlappingTrackingAreas[i],
4181  aView = [aTrackingArea view];
4182 
4183  // First, if aView is _windowView, skip to next overlapping tracking area
4184  // as _windowView can't be the frontmost view if there's multiple overlapping tracking areas.
4185 
4186  if (aView === _windowView)
4187  continue;
4188 
4189  // Then, if frontmostView is _windowView, aView must become frontmostView
4190 
4191  if (frontmostView === _windowView)
4192  {
4193  frontmostTrackingArea = aTrackingArea;
4194  frontmostView = aView;
4195 
4196  continue;
4197  }
4198 
4199  // Next verify if aView is a subview of frontmostView
4200  // If so, it's our new frontmost view
4201 
4202  var searchingView = aView;
4203 
4204  while ((searchingView !== _contentView) && ([searchingView superview] !== frontmostView))
4205  searchingView = [searchingView superview];
4206 
4207  if (searchingView !== _contentView)
4208  {
4209  frontmostTrackingArea = aTrackingArea;
4210  frontmostView = aView;
4211 
4212  continue;
4213  }
4214 
4215  // aView is not a subview of frontmostView
4216  // Search in view hierarchy which one will be over the other
4217  // (this is done by comparing their draw order)
4218 
4219  var firstView = frontmostView,
4220  firstSuperview = [firstView superview];
4221 
4222  while (firstView !== _contentView)
4223  {
4224  var secondView = aView,
4225  secondSuperview = [secondView superview];
4226 
4227  while ((secondSuperview !== _contentView) && (firstSuperview !== secondSuperview))
4228  {
4229  secondView = secondSuperview;
4230  secondSuperview = [secondView superview];
4231  }
4232 
4233  if (firstSuperview === secondSuperview)
4234  break;
4235 
4236  firstView = firstSuperview;
4237  firstSuperview = [firstView superview];
4238  }
4239 
4240  if (firstSuperview !== secondSuperview)
4241  [CPException raise:CPInternalInconsistencyException reason:"Problem with view hierarchy"];
4242 
4243  var firstSuperviewSubviews = [firstSuperview subviews],
4244  firstViewIndex = [firstSuperviewSubviews indexOfObject:firstView],
4245  secondViewIndex = [firstSuperviewSubviews indexOfObject:secondView];
4246 
4247  if (secondViewIndex > firstViewIndex)
4248  {
4249  frontmostTrackingArea = aTrackingArea;
4250  frontmostView = aView;
4251  }
4252  }
4253 
4254  if (frontmostTrackingArea !== _activeCursorTrackingArea)
4255  {
4256  var cursorUpdateEvent = [CPEvent enterExitEventWithType:CPCursorUpdate
4257  location:point
4258  modifierFlags:[anEvent modifierFlags]
4259  timestamp:[anEvent timestamp]
4260  windowNumber:_windowNumber
4261  context:nil
4262  eventNumber:-1
4263  trackingArea:frontmostTrackingArea];
4264 
4265  if (dragging)
4266  [self _queueTrackingEvent:cursorUpdateEvent];
4267  else
4268  [_queuedEvents addObject:cursorUpdateEvent];
4269 
4270  _activeCursorTrackingArea = frontmostTrackingArea;
4271  }
4272 }
4273 
4274 - (void)_queueTrackingEvent:(CPEvent)anEvent
4275 {
4276  // This will put a tracking event in the _queuedTrackingEvents queue.
4277  //
4278  // We optimize this queue with this policy:
4279  // - if mouseEntered, search if queue contains a previous mouseExited for the same tracking area. If so, discard both.
4280  // - if mouseExited, search if queue contains a previous mouseEntered for the same tracking area. If so, discard both.
4281  //
4282  // This is not the Cocoa way of doing as it would send every event, but the final result should be the same.
4283 
4284  var eventType = [anEvent type],
4285  trackingArea = [anEvent trackingArea];
4286 
4287  switch ([anEvent type])
4288  {
4289  case CPMouseEntered:
4290  for (var i = 0; i < _queuedTrackingEvents.length; i++)
4291  {
4292  var queuedEvent = _queuedTrackingEvents[i];
4293 
4294  if (([queuedEvent trackingArea] === trackingArea) && ([queuedEvent type] === CPMouseExited))
4295  {
4296  [_queuedTrackingEvents removeObjectAtIndex:i];
4297  return;
4298  }
4299  }
4300 
4301  [_queuedTrackingEvents addObject:anEvent];
4302  break;
4303 
4304  case CPMouseExited:
4305  for (var i = 0; i < _queuedTrackingEvents.length; i++)
4306  {
4307  var queuedEvent = _queuedTrackingEvents[i];
4308 
4309  if (([queuedEvent trackingArea] === trackingArea) && ([queuedEvent type] === CPMouseEntered))
4310  {
4311  [_queuedTrackingEvents removeObjectAtIndex:i];
4312  return;
4313  }
4314  }
4315 
4316  [_queuedTrackingEvents addObject:anEvent];
4317  break;
4318 
4319  case CPCursorUpdate:
4320  [_queuedTrackingEvents addObject:anEvent];
4321  break;
4322  }
4323 }
4324 
4325 - (void)_flushTrackingEventQueueForMouseAt:(CGPoint)point
4326 {
4327  for (var i = 0; i < _queuedTrackingEvents.length; i++)
4328  {
4329  var queuedEvent = _queuedTrackingEvents[i],
4330  trackingArea = [queuedEvent trackingArea],
4331  trackingOwner = [trackingArea owner];
4332 
4333  switch ([queuedEvent type])
4334  {
4335  case CPMouseEntered:
4336  [trackingOwner mouseEntered:queuedEvent];
4337  break;
4338 
4339  case CPMouseExited:
4340  [trackingOwner mouseExited:queuedEvent];
4341  break;
4342 
4343  case CPCursorUpdate:
4344  [trackingOwner updateTrackingAreas];
4345 
4346  if (CGRectContainsPoint([trackingArea windowRect], point))
4347  [trackingOwner cursorUpdate:queuedEvent];
4348 
4349  break;
4350  }
4351  }
4352 
4353  _queuedTrackingEvents = [];
4354 }
4355 
4356 @end
4357 
4358 function _CPWindowFullPlatformWindowSessionMake(aWindowView, aContentRect, hasShadow, aLevel)
4359 {
4360  return { windowView:aWindowView, contentRect:aContentRect, hasShadow:hasShadow, level:aLevel };
4361 }
4362 
4364 
4368 - (void)_setAnimating:(BOOL)aValue
4369 {
4370  _isAnimating = aValue;
4371 }
4372 
4376 - (void)_setChildOrdering:(CPWindowOrderingMode)aValue
4377 {
4378  _childOrdering = aValue;
4379 }
4380 
4381 @end
void setHasShadow:(BOOL shouldHaveShadow)
Definition: CPWindow.j:1405
Used to implement exception handling (creating & raising).
Definition: CPException.h:2
BOOL makeFirstResponder:(CPResponder aResponder)
Definition: CPWindow.j:1632
void setFrame:(CGRect aFrame)
Definition: CPWindow.j:897
CPOrderedAscending
Definition: CPObjJRuntime.j:48
CPToolbar toolbar()
Definition: CPWindow.j:2632
Definition: CPMenu.h:2
BOOL isHidden()
Definition: CALayer.j:597
var CPWindowResizeTime
Definition: CPWindow.j:63
CPWindow setParentWindow:(CPWindow parentWindow)
Definition: CPWindow.j:2752
CPView previousValidKeyView()
Definition: CPView.j:3102
CGPoint convertBaseToPlatformWindow:(CGPoint aPoint)
Definition: CPWindow.j:3633
CPBorderlessWindowMask
id init()
Definition: CALayer.j:126
var CPWindowDelegate_windowShouldClose_
Definition: CPWindow.j:55
CPWindowPositionFlexibleTop
CGRect frame
void removeWindowController:(CPWindowController aWindowController)
Definition: CPDocument.j:311
CPWindowMinXMargin
void makeMainWindow()
Definition: CPWindow.j:2506
CPOrderedSame
Definition: CPObjJRuntime.j:54
CPTrackingOwnerImplementsCursorUpdate
CPWindowResizeStyleModern
CPCursor arrowCursor()
Definition: CPCursor.j:246
var CPWindowSaveImage
Definition: CPWindow.j:61
CPWindowPositionFlexibleRight
CPMouseExited
void setRepresentedFilename:(CPString aFilePath)
Definition: CPWindow.j:1720
CPTrackingMouseMoved
void becomeMainWindow()
Definition: CPWindow.j:2525
void setShowsResizeIndicator:(BOOL shouldShowResizeIndicator)
Definition: CPWindow.j:1169
CGPoint convertBaseToScreen:(CGPoint aPoint)
Definition: CPWindow.j:3663
void addObserver:selector:name:object:(id anObserver, [selector] SEL aSelector, [name] CPString aNotificationName, [object] id anObject)
void setTitle:(CPString aTitle)
Definition: CPWindow.j:1700
CPScreen screen()
Definition: CPWindow.j:1750
CPResponder firstResponder()
Definition: CPWindow.j:1657
CGPoint locationInWindow()
Definition: CPEvent.j:290
id initWithContentRect:(CGRect aRect)
var CPWindowActionMessageKeys
Definition: CPWindow.j:72
CPTrackingAreaOptions options()
id delegate()
Definition: CALayer.j:965
CPWindowBelow
void setPlatformWindow:(CPPlatformWindow aPlatformWindow)
Definition: CPWindow.j:399
int width
var CPWindowResizeStyleGlobalChangeNotification
Definition: CPWindow.j:64
CPWindowMaxYMargin
void postNotificationName:object:(CPString aNotificationName, [object] id anObject)
void raise:reason:(CPString aName, [reason] CPString aReason)
Definition: CPException.j:66
CPBorderlessBridgeWindowMask
CPString charactersIgnoringModifiers()
Definition: CPEvent.j:392
CPEventType type()
Definition: CPEvent.j:325
var CPWindowMinVisibleHorizontalMargin
Definition: CPWindow.j:66
void miniaturize:(id sender)
CPArray selectorsForKey:modifierFlags:(CPString aKey, [modifierFlags] unsigned aFlag)
Definition: CPKeyBinding.j:180
CPWindow attachedSheet()
Definition: CPWindow.j:3086
CPTrackingActiveInKeyWindow
unsigned modifierFlags()
Definition: CPEvent.j:309
void keyDown:(CPEvent anEvent)
Definition: CPResponder.j:222
BOOL isFullPlatformWindow()
Definition: CPWindow.j:612
CGRect visibleFrame()
Definition: CPScreen.j:42
CPTrackingActiveInActiveApp
CPWindowHeightSizable
CPNotificationCenter defaultCenter()
A mutable key-value pair collection.
Definition: CPDictionary.h:2
void dragImage:fromWindow:at:offset:event:pasteboard:source:slideBack:(CPImage anImage, [fromWindow] CPWindow aWindow, [at] CGPoint imageLocation, [offset] CGSize mouseOffset, [event] CPEvent anEvent, [pasteboard] CPPasteboard aPasteboard, [source] id aSourceObject, [slideBack] BOOL slideBack)
Definition: CPDragServer.j:427
CPTrackingActiveWhenFirstResponder
CPWindowResizeStyle
void setShadowStyle:(int aStyle)
void setFrameSize:(CGSize aSize)
Definition: CPWindow.j:916
CPTitledWindowMask
void setFrame:display:animate:(CGRect aFrame, [display] BOOL shouldDisplay, [animate] BOOL shouldAnimate)
Definition: CPWindow.j:681
CPCursorUpdate
CGRect bounds()
Definition: CALayer.j:203
CPMouseMoved
id initWithContentRect:styleMask:(CGRect aContentRect, [styleMask] unsigned aStyleMask)
Definition: CPWindow.j:265
void orderFront:(id aSender)
Definition: CPWindow.j:925
void close()
Definition: CPWindow.j:2446
CPWindowPositionFlexibleLeft
CPTabCharacter
Definition: CPText.j:51
CPMouseEntered
void flagsChanged:(CPEvent anEvent)
Definition: CPResponder.j:240
An immutable string (collection of characters).
Definition: CPString.h:2
CPUndoManager undoManager()
Definition: CPWindow.j:3688
Definition: CPImage.h:2
CPRightMouseDragged
CPOrderedDescending
Definition: CPObjJRuntime.j:60
CPEscapeFunctionKey
CPFlagsChanged
CGPoint convertBaseToGlobal:(CGPoint aPoint)
Definition: CPWindow.j:3603
CPView nextValidKeyView()
Definition: CPView.j:3076
void selectNextKeyView:(id sender)
Definition: CPWindow.j:3275
CPWindowConstrainToScreen
CPTrackingOwnerImplementsMouseMoved
void miniaturize:(id sender)
Definition: CPWindow.j:2333
CPKeyDown
CPWindowNotSizable
var keyViewComparator
Definition: CPWindow.j:3445
CGPoint convertPlatformWindowToBase:(CGPoint aPoint)
Definition: CPWindow.j:3647
CPDragServer sharedDragServer()
Definition: CPDragServer.j:142
void doCommandBySelector:(SEL aSelector)
Definition: CPResponder.j:304
void makeKeyAndOrderFront:(id aSender)
Definition: CPWindow.j:2113
void disableKeyEquivalentForDefaultButton()
Definition: CPWindow.j:3408
CPResizableWindowMask
BOOL isVisible()
Definition: CPWindow.j:1108
CPWindow window()
Definition: CPEvent.j:341
CPBackTabCharacter
Definition: CPText.j:55
CPLeftMouseUp
CPShiftKeyMask
void performClick:(id sender)
Definition: CPButton.j:860
CPTrackingOwnerImplementsMouseExited
CPColor backgroundColor()
Definition: CALayer.j:629
void dragView:fromWindow:at:offset:event:pasteboard:source:slideBack:(CPView aView, [fromWindow] CPWindow aWindow, [at] CGPoint viewLocation, [offset] CGSize mouseOffset, [event] CPEvent mouseDownEvent, [pasteboard] CPPasteboard aPasteboard, [source] id aSourceObject, [slideBack] BOOL slideBack)
Definition: CPDragServer.j:346
A notification that can be posted to a CPNotificationCenter.
Definition: CPNotification.h:2
CPTimer scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:(CPTimeInterval seconds, [target] id aTarget, [selector] SEL aSelector, [userInfo] id userInfo, [repeats] BOOL shouldRepeat)
Definition: CPTimer.j:58
void setDefaultButton:(CPButton aButton)
Definition: CPWindow.j:3366
void recalculateKeyViewLoop()
Definition: CPWindow.j:3211
CPTheme defaultTheme()
Definition: CPTheme.j:44
void setAutoresizingMask:(unsigned anAutoresizingMask)
Definition: CPWindow.j:3587
CPInternalInconsistencyException
Definition: CPException.j:28
CPClosableWindowMask
void becomeKeyWindow()
Definition: CPWindow.j:2034
CPTimeInterval timestamp()
Definition: CPEvent.j:317
An mutable collection which may contain a specific object numerous times.
Definition: CPCountedSet.h:2
CGRect frame()
Definition: CPWindow.j:669
id enterExitEventWithType:location:modifierFlags:timestamp:windowNumber:context:eventNumber:trackingArea:(CPEventType anEventType, [location] CGPoint aPoint, [modifierFlags] unsigned modifierFlags, [timestamp] CPTimeInterval aTimestamp, [windowNumber] int aWindowNumber, [context] CPGraphicsContext aGraphicsContext, [eventNumber] int anEventNumber, [trackingArea] CPTrackingArea aTrackingArea)
Definition: CPEvent.j:152
void setFrameOrigin:(CGPoint anOrigin)
Definition: CPWindow.j:906
A general mechanism for user action "undo".
Definition: CPUndoManager.h:2
CPString lastPathComponent()
Definition: CPString.j:824
CPPlatformActionKeyMask
A timer object that can send a message after the given time interval.
Definition: CPTimer.h:2
CPLeftMouseDragged
void enableKeyEquivalentForDefaultButton()
Definition: CPWindow.j:3391
void setLevel:(int aLevel)
Definition: CPWindow.j:1083
void keyUp:(CPEvent anEvent)
Definition: CPResponder.j:231
CPNotFound
Definition: CPObjJRuntime.j:62
void setMovableByWindowBackground:(BOOL shouldBeMovableByWindowBackground)
Definition: CPWindow.j:1761
void setValue:forKey:(id aValue, [forKey] CPString aKey)
id init()
Definition: CPObject.j:145
CPTrackingAreaOptions CPTrackingMouseEnteredAndExited
Sends messages (CPNotification) between objects.
void selectPreviousKeyView:(id sender)
Definition: CPWindow.j:3297
Definition: CPTheme.h:2
void makeKeyWindow()
Definition: CPWindow.j:2124
CPWindowMinYMargin
var CPWindowMinVisibleVerticalMargin
Definition: CPWindow.j:67
CPRightMouseUp
CPDocModalWindowMask
Definition: CPPanel.j:29
void setFullPlatformWindow:(BOOL shouldBeFullPlatformWindow)
Definition: CPWindow.j:566
var CPWindowDelegate_windowWillClose_
Definition: CPWindow.j:57
CPWindowWidthSizable
void setNextResponder:(CPResponder aResponder)
Definition: CPResponder.j:83
CPLeftMouseDown
int level()
Definition: CPWindow.j:1100
CPCarriageReturnCharacter
Definition: CPText.j:54
void deminiaturize:(id sender)
void removeObserver:name:object:(id anObserver, [name] CPString aNotificationName, [object] id anObject)
void set()
Definition: CPCursor.j:128
CPTrackingEnabledDuringMouseDrag
Definition: CPEvent.h:2
Class class()
Definition: CPObject.j:179
void orderWindow:relativeTo:(CPWindowOrderingMode orderingMode, [relativeTo] int otherWindowNumber)
Definition: CPWindow.j:1059
CGRect contentRectForFrameRect:(CGRect aFrame)
Definition: CPWindow.j:651
CPPlatformWindow platformWindow()
Definition: CPWindow.j:389
BOOL isBrowser()
Definition: CPPlatform.j:33
id URLWithString:(CPString URLString)
Definition: CPURL.j:78
CPAppKitDefined
id valueForAttributeWithName:forClass:(CPString aName, [forClass] id aClass)
Definition: CPTheme.j:218
void setRepresentedURL:(CPURL aURL)
Definition: CPWindow.j:1737
CGPoint convertScreenToBase:(CGPoint aPoint)
Definition: CPWindow.j:3658
CPTrackingOwnerImplementsMouseEntered
Definition: CPURL.h:2
var interpolate
Definition: CPWindow.j:3785
CPWindowOrderingMode CPWindowAbove
CPRightMouseDown
CPTrackingArea trackingArea()
Definition: CPEvent.j:631
BOOL showsResizeIndicator()
Definition: CPWindow.j:1160
CPButton defaultButton()
Definition: CPWindow.j:3383
CPWindowMaxXMargin
var CPWindowDelegate_windowWillResize_toSize_
Definition: CPWindow.j:58
CPMainMenuWindowLevel
CPWindowPositionFlexibleBottom
void setContentView:(CPView aView)
Definition: CPWindow.j:1202
CPPlatformWindow primaryPlatformWindow()
CPTimeInterval animationResizeTime:(CGRect newWindowFrame)
Definition: CPWindow.j:2767
id alloc()
Definition: CPObject.j:130
Definition: CPView.j:137
CPTrackingCursorUpdate
var CPWindowDelegate_windowWillReturnUndoManager_
Definition: CPWindow.j:56
CPScrollWheel
CPHUDBackgroundWindowMask
CPTrackingActiveAlways