Previously the sheet was made key at the beginning of the animation. It turns out events would not reliably make it to the sheet during animation. The other problem is that if a text field was the first responder, at the beginning of the animation it is offscreen, which means it refuses first responder and sets the first responder to nil.
Now we no longer try to make the sheet key before the animation ends, avoiding the text field problem.
Previously, popovers did not properly stay below the menu bar.
This commit ensures they stay within whatever is the usable content frame for the platform window.
When a transient popover was closed by clicking, in some cases it would not detach from its parent, leaving it in the window list. This caused problems later on.
This commit ensures the popover is detached from its parent when it is ordered out.
Previously, if a window had a sheet, a mouse move event was passed to the sheet and then filtered. This disabled resize cursors for the parent window of a sheet.
This commit allows mouse move events to continue to the parent window so that resize cursors will work on the parent window as well.
Sheets are like child windows, they can never become main. Previously, when an attempt was made to make a sheet the main window, its parent window did not become main as it should have. Thus the title bar would remain dimmed, even though the sheet was the key window.
With this commit, when a sheet is made main, it defers to the parent window.
Previously, if an event occurred during the sheet opening animation that would close the sheet, the animation was not properly cleaned up and the subsequent closing animation would die horribly.
The animation is always cleaned up with this commit.
It is possible to resize the parent window of a sheet while it is open. Previously, the sheet's top shadow was not adjusted when the parent window was resized, which could lead to it being out of synch.
Now the sheet shadow is adjusted whenever the parent window's size changes.
Previously, sheets were only repositioned if the parent window's setFrameOrigin: method was called. This did not cover all possible cases for parent window repositioning.
Now the sheet is repositioned any time the parent window's origin changes.
Previously, Cappuccino was using preprocessor macros internally for the CGPoint/Size/Rect/Inset/Affine functions, as well as for CPRange. These macros had the same name as the corresponding function, but began with _. The functions were actually defined using the macros.
The motivation behind using macros was to increase performance by reducing function calls. However, there were a number of problems with this approach:
- There was an artificial dichotomy between _CG macros and the corresponding CG functions. We never completely replaced CG function calls with _CG macros. In fact, they were often mixed up in the same file. There was an extra burden on the programmer to remember to use the macro instead of the function.
- If a method call was passed as an argument to a macro, performance could actually be significantly *worse* than a function call. For example, _CGGetRectMakeCopy([view frame]) would expand to `{ origin:{ x:[view frame].origin.x, y:[view frame].origin.y }, size:{ width:[view frame].size.width, height:[view frame].size.height } }`. So instead of a single objj_msgSend and a single simple function call, we ended up with 4 objj_msgSend calls, which are way more expensive than simple function calls.
- Because of this expansion problem, to use macros efficiently required us to remember to use variables for all macro parameters. This didn't happen, and shouldn't have to happen.
- Finally, with modern Javascript engines, function call overhead is so small that it really isn't worth using the macros.
This commit eliminates the _CGGeometry, CGAffineTransformation and CPRange macros and replaces them with function calls.
BREAKING CHANGE:
The macros are no longer available. They could only be used with compiled code, but if there is any user code that used them, they will have to be replaced with the corresponding functions.
The AttachedSheet2 demo was calling runModalForWindow:, which caused the sheet to appear briefly as an application modal.
That call was removed, beginSheet: does everything.
Also:
- Wrapped _attachSheetWindow method into _attachSheet:modalDelegate: method.
- Just to be safe, in CPWindow -_sheetShouldAnimateIn:, the sheet is moved offscreen before being ordered front.
Previously, clicking outside a menu on a control would not close the menu. Also clicking on the menu header again would open a second menu.
This error was caused by the control receiving the click and starting its own tracking, depriving the menu of the mouse up event it was awaiting.
The behaviour to wait for the mouse up was wrong to begin with. Menus should close on mouse down.
This fix closes the menu on left mouse down anywhere but the menu, while still allowing the click to pass through to any control underneath the cursor.
Fixes#1833.
Without this fix, CPTabView would still make view hierarchy changes in `initWithCoder:` despite the fix in f805b6b. Making view hierarchy changes before a cib is fully decoded can easily result in a corrupted hierarchy.
In this case, the decoding of a tab view item view, A, lead to the decoder to try to decode A's next responder, which was the tab view, B. B then tried to set the selected tab, which involved adding A as a subview. But since A wasn't done decoding, A._superview would change later in the process, corrupting this change.
This fix delays `_updateItems` to `awakeFromCib` at which time changing the view hierarchy is safe.
Refs #1409.
Currently, if a window controller has a document, its title is put in menubar. I cannot remember any Cocoa application that ever did this.
This commit removes the synchronizing of the document title with the menubar title.
After bbfaac5, all kinds of strange behavior occurred with window sizing and moving due to overzealous constraining.
Cocoa does not constrain the frame of hidden windows. When a hidden window is ordered in, it is constrained to the usable screen content rect. A visible window has its height constrained when its frame is set. Its origin is constrained such that a minimum margin at the left, right and top is visible, and the top is constrained to be below the menu bar.
This commit fixes a number of problems related to window moving and resizing that were introduced by bbfaac5:
- Sheets are not constrained at all.
- Moving a window does not constrain its size.
In addition, when a window is moved, tracking is relative to the initial click point, which provides proper behavior when the movement is constrained and the mouse keeps moving.
Previously, there were two instances in which a browser would forcibly scroll a text field into view, out of Cappuccino's control:
- A text field is first responder in the key window, is partially or fully offscreen, and you click somewhere else within the same window. If the target of the click does not accept first responder, the text field is refocused.
- A text field is first responder in a non-key window, is partially or fully offscreen, and you make its window the key window. In that case the text field is made first responder and is focused.
In both cases, focusing the text field causes the browser to scroll the viewport out of Cappuccino's control such that the text field is completely onscreen.
With this commit, before a text field is focused, it is checked to ensure it is completely within the usable content rect of the platform window. If not, it refuses first responder. If the window is becoming key, the first responder is set to nil.
Previously, all window subclasses were constrained to the usable screen content. Unfortunately that included the menu bar window, which ended up appearing below itself!
This commit introduces an ivar that indicates whether instances of the window subclass should be constrained or not.
Previously, no bounds were placed on the placement or sizing of windows, which allowed them to extend beyond the usable screen content (the area bounded by the menu bar at the top and the platform window on the other sides).
Cocoa enforces the following restrictions:
- When a window is ordered in, it is forced within the usable screen content (below the menu bar) and its size and width are clipped to the usable screen content as well.
- If a window is already visible, any methods that move or resize the window will ensure the top and bottom of the window are within the usable screen content. The width is unchanged.
This commit implements Cocoa's restrictions in CPWindow.
Fixes#1690
Previously, calling setPostsFrameChangedNotifications:YES or setPostsBoundsChangedNotifications:YES would immediately result in the notification being sent. Cocoa will only send in this context if:
- setPosts[Frame/Bounds]ChangedNotifications:NO was called.
- The frame/bounds changed between that call and the call to setPosts[Frame/Bounds]ChangedNotifications:YES.
We are currently not tracking pending changes, so this commit removes the sending of the notification completely in those methods.
Fixes#1076
Previously, Cappuccino would resize in such a way that a view's size ratio to its superview would not be maintained.
This commit ensures that size ratios are maintained during resizing.
Patch contributed by @davidkhess
Fixes#357
Previously, when a sheet was resized, there were a number of problems:
- Sheets in Cocoa resize their width symmetrically, such that they always remain centered. This was not happening in Cappuccino.
- When a sheet is resized wider than its parent window, the shadow at the top of the sheet was growing wider than the bounds of the parent window's title bar, which makes no sense since the shadow is supposed to be cast by the title bar.
- Sheets had no top border, so when they were resized wider than the parent window, the top edge looked like it was cut off. In Cocoa, sheets have a top border that sits under the title bar of the parent window, and which is visible when the sheet is resized wider than the parent window.
This commit addresses these problems as follows:
- Sheet width is now resized symmetrically.
- Sheet resizing is pinned to the screen bounds.
- The top sheet shadow is pinned to the width of the parent window's content view.
- Sheets now have a top border.
In addition to these changes, a redundant sheet top shadow was eliminated from one of the _CPWindowView subclasses.
Fixes#1846
Previously sheet animation was performed by sizing the sheet from zero to full height when animating in, and then back to zero height when animating out. This caused problems with the resize algorithms, which are not designed to deal with sizing from zero.
Analyzing Cocoa behavior revealed that sheets slide in and out with no resizing.
With this commit, a general purpose mechanism for clipping a window to a rect was added to CPDOMWindowLayer. Clipping was put in CPDOMWindowLayer because that is the class that deals with windows at the global level. CPWindow uses the clipping mechanism to slide the sheet in and out, thus avoiding all resizing problems.
Fixes#1840
Previously the attached sheet shadow (that appears below the title bar of the window a sheet is attached to) was 9x8, and it was quite dark.
With this commit the width has been reduced to 1 (to reduce the image size) and it has been lightened up.
Also changed "height-shadow" theme attribute to "shadow-height".
Previously, sheets could be resized from the top, which would destroy the illusion of being attached to the top of the parent window.
With this commit, sheets are prevented from being resized by the user from the top edge.
Fixed: mouseEntered and mouseExited mixed up for custom views in menu
Previously, when clicking and dragging inside a menu, mouseEntered and mouseExited were sent to the wrong views.
This commit correctly sends mouseExited to the previous hovered view, then mouseEntered to the new hovered view.
Fixed: using keyboard navigation in empty CPCollectionView threw exception
Previously, if an empty CPCollectionView was first responder and keyboard navigation was used, a CPInvalidArgumentException (Range {-1, 1} is out of bounds) was thrown.
This commit checks for an empty collection, eliminating the exception.
Without this fix, a platform window could be resized by clicking just under the menu bar and dragging downwards, even that platform windows are supposed to be the size of the browser window by definition.
Without this fix, the presence of a modal ancestor window to a token field would lock down the autocomplete menu from mouse interaction.
This fix ensures the token field autocomplete menu accepts mouse events even during the presence of modal widows, just like other auxiliary windows such as pop up menus.
Without this fix, opening a transient popover would allow windows other than the modal window (or its children) to be interacted with.
In general, setCallback:forNextEventMatchingMask: did not work right if more than 1 callback was installed.
In the popover case the modal window would install its "any event" callback to control the event loop, but then the popover would add a second callback for mouse down to detect clicks outside of it. This would disrupt the modal event handling and allow mouse clicks (and presumably other events) to escape the modal event catcher.
This fix makes multiple nextEvent callbacks work as one would expect, with later ones taking priority over older ones and reinserted callbacks remaining at a stable priority.
This allows the modal window callback to be at the "bottom" of the handler stack and the popover event handler to be "on top" of that, and to remain that way. In theory more layers of event handling could be layered on top such as 2 simultaneous popovers.
This fix also fixes the dequeue argument in forNextEvent callbacks.
Without this fix, a transient popover would close if the autocomplete menu of a token field contained in it was clicked.
This happened because the popover considered the click to be on a different window. Although not tested, it's likely the same thing would happen if the menu of a combo pop or a pop up button was clicked.
This fix makes it so that any child window of a popover can be clicked without the popover closing.