summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjeremya@chromium.org <jeremya@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-17 02:10:56 +0000
committerjeremya@chromium.org <jeremya@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-17 02:10:56 +0000
commit5925dff83699508b5e2735afb0297dfb310e159d (patch)
tree380f74c027fd6a4ebefdae27c6cee159cbabf4e7
parent66e1bd084a4818f624ee133f56163d0a71e472a3 (diff)
downloadchromium_src-5925dff83699508b5e2735afb0297dfb310e159d.zip
chromium_src-5925dff83699508b5e2735afb0297dfb310e159d.tar.gz
chromium_src-5925dff83699508b5e2735afb0297dfb310e159d.tar.bz2
Implement a bubble that appears at the top of the screen when a tab enters
fullscreen mode via webkitRequestFullScreen(), telling the user how to exit fullscreen. This is implemented as an NSView rather than an NSWindow because the floating chrome that appears in presentation mode should overlap the bubble. Content-initiated fullscreen mode makes use of 'presentation mode' on the Mac: the mode in which the UI is hidden, accessible by moving the cursor to the top of the screen. On Snow Leopard, this mode is synonymous with fullscreen mode. On Lion, however, fullscreen mode does not imply presentation mode: in non-presentation fullscreen mode, the chrome is permanently shown. It is possible to switch between presentation mode and fullscreen mode using the presentation mode UI control. When a tab initiates fullscreen mode on Lion, we enter presentation mode if not in presentation mode already. When the user exits fullscreen mode using Chrome UI (i.e. keyboard shortcuts, menu items, buttons, switching tabs, etc.) we return the user to the mode they were in before the tab entered fullscreen. BUG=14471 TEST=Enter fullscreen mode using webkitRequestFullScreen. You should see a bubble pop down from the top of the screen. Need to test the Lion logic somehow, with no Lion trybots. BUG=96883 Original review http://codereview.chromium.org/7890056/ TBR=thakis Review URL: http://codereview.chromium.org/7920024 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@101624 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/app/nibs/FullscreenExitBubble.xib1122
-rw-r--r--chrome/browser/ui/browser.cc23
-rw-r--r--chrome/browser/ui/browser.h10
-rw-r--r--chrome/browser/ui/browser_browsertest.cc33
-rw-r--r--chrome/browser/ui/cocoa/browser_window_controller.h3
-rw-r--r--chrome/browser/ui/cocoa/browser_window_controller.mm23
-rw-r--r--chrome/browser/ui/cocoa/browser_window_controller_private.h4
-rw-r--r--chrome/browser/ui/cocoa/browser_window_controller_private.mm29
-rw-r--r--chrome/browser/ui/cocoa/fullscreen_exit_bubble_controller.h46
-rw-r--r--chrome/browser/ui/cocoa/fullscreen_exit_bubble_controller.mm208
-rw-r--r--chrome/browser/ui/cocoa/fullscreen_exit_bubble_controller_unittest.mm73
-rw-r--r--chrome/browser/ui/cocoa/fullscreen_exit_bubble_view.h22
-rw-r--r--chrome/browser/ui/cocoa/fullscreen_exit_bubble_view.mm92
-rw-r--r--chrome/chrome_browser.gypi4
-rw-r--r--chrome/chrome_dll.gypi1
-rw-r--r--chrome/chrome_tests.gypi1
16 files changed, 1682 insertions, 12 deletions
diff --git a/chrome/app/nibs/FullscreenExitBubble.xib b/chrome/app/nibs/FullscreenExitBubble.xib
new file mode 100644
index 0000000..eade4b3
--- /dev/null
+++ b/chrome/app/nibs/FullscreenExitBubble.xib
@@ -0,0 +1,1122 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
+ <data>
+ <int key="IBDocument.SystemTarget">1050</int>
+ <string key="IBDocument.SystemVersion">10K549</string>
+ <string key="IBDocument.InterfaceBuilderVersion">823</string>
+ <string key="IBDocument.AppKitVersion">1038.36</string>
+ <string key="IBDocument.HIToolboxVersion">461.00</string>
+ <object class="NSMutableDictionary" key="IBDocument.PluginVersions">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="NS.object.0">823</string>
+ </object>
+ <object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <integer value="44"/>
+ </object>
+ <object class="NSArray" key="IBDocument.PluginDependencies">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ </object>
+ <object class="NSMutableDictionary" key="IBDocument.Metadata">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys" id="0">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSCustomObject" id="1001">
+ <string key="NSClassName">FullscreenExitBubbleController</string>
+ </object>
+ <object class="NSCustomObject" id="1003">
+ <string key="NSClassName">FirstResponder</string>
+ </object>
+ <object class="NSCustomObject" id="1004">
+ <string key="NSClassName">NSApplication</string>
+ </object>
+ <object class="NSCustomView" id="374699732">
+ <reference key="NSNextResponder"/>
+ <int key="NSvFlags">290</int>
+ <object class="NSMutableArray" key="NSSubviews">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSCustomView" id="919318747">
+ <reference key="NSNextResponder" ref="374699732"/>
+ <int key="NSvFlags">258</int>
+ <object class="NSMutableArray" key="NSSubviews">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSTextField" id="271414804">
+ <reference key="NSNextResponder" ref="919318747"/>
+ <int key="NSvFlags">290</int>
+ <string key="NSFrame">{{8, 8}, {446, 22}}</string>
+ <reference key="NSSuperview" ref="919318747"/>
+ <bool key="NSEnabled">YES</bool>
+ <object class="NSTextFieldCell" key="NSCell" id="526614140">
+ <int key="NSCellFlags">67239488</int>
+ <int key="NSCellFlags2">138414080</int>
+ <string key="NSContents">Exit fullscreen text</string>
+ <object class="NSFont" key="NSSupport">
+ <string key="NSName">LucidaGrande</string>
+ <double key="NSSize">18</double>
+ <int key="NSfFlags">16</int>
+ </object>
+ <reference key="NSControlView" ref="271414804"/>
+ <object class="NSColor" key="NSBackgroundColor">
+ <int key="NSColorSpace">6</int>
+ <string key="NSCatalogName">System</string>
+ <string key="NSColorName">controlColor</string>
+ <object class="NSColor" key="NSColor">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MC42NjY2NjY2NjY3AA</bytes>
+ </object>
+ </object>
+ <object class="NSColor" key="NSTextColor">
+ <int key="NSColorSpace">6</int>
+ <string key="NSCatalogName">System</string>
+ <string key="NSColorName">controlTextColor</string>
+ <object class="NSColor" key="NSColor">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MAA</bytes>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ <string key="NSFrame">{{0, -2}, {462, 38}}</string>
+ <reference key="NSSuperview" ref="374699732"/>
+ <string key="NSClassName">FullscreenExitBubbleView</string>
+ </object>
+ </object>
+ <string key="NSFrameSize">{462, 36}</string>
+ <reference key="NSSuperview"/>
+ <string key="NSClassName">AnimatableView</string>
+ </object>
+ </object>
+ <object class="IBObjectContainer" key="IBDocument.Objects">
+ <object class="NSMutableArray" key="connectionRecords">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">view</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="374699732"/>
+ </object>
+ <int key="connectionID">31</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">delegate_</string>
+ <reference key="source" ref="374699732"/>
+ <reference key="destination" ref="1001"/>
+ </object>
+ <int key="connectionID">33</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">delegate</string>
+ <reference key="source" ref="271414804"/>
+ <reference key="destination" ref="1001"/>
+ </object>
+ <int key="connectionID">38</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">exitLabelPlaceholder_</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="271414804"/>
+ </object>
+ <int key="connectionID">45</int>
+ </object>
+ </object>
+ <object class="IBMutableOrderedSet" key="objectRecords">
+ <object class="NSArray" key="orderedObjects">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBObjectRecord">
+ <int key="objectID">0</int>
+ <reference key="object" ref="0"/>
+ <reference key="children" ref="1000"/>
+ <nil key="parent"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-2</int>
+ <reference key="object" ref="1001"/>
+ <reference key="parent" ref="0"/>
+ <string key="objectName">File's Owner</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-1</int>
+ <reference key="object" ref="1003"/>
+ <reference key="parent" ref="0"/>
+ <string key="objectName">First Responder</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-3</int>
+ <reference key="object" ref="1004"/>
+ <reference key="parent" ref="0"/>
+ <string key="objectName">Application</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">30</int>
+ <reference key="object" ref="374699732"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="919318747"/>
+ </object>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">44</int>
+ <reference key="object" ref="919318747"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="271414804"/>
+ </object>
+ <reference key="parent" ref="374699732"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">36</int>
+ <reference key="object" ref="271414804"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="526614140"/>
+ </object>
+ <reference key="parent" ref="919318747"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">37</int>
+ <reference key="object" ref="526614140"/>
+ <reference key="parent" ref="271414804"/>
+ </object>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="flattenedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>-1.IBPluginDependency</string>
+ <string>-2.IBPluginDependency</string>
+ <string>-3.IBPluginDependency</string>
+ <string>30.IBEditorWindowLastContentRect</string>
+ <string>30.IBPluginDependency</string>
+ <string>30.IBViewEditorWindowController.showingLayoutRectangles</string>
+ <string>36.IBPluginDependency</string>
+ <string>36.IBViewBoundsToFrameTransform</string>
+ <string>37.IBPluginDependency</string>
+ <string>44.IBPluginDependency</string>
+ <string>44.IBViewBoundsToFrameTransform</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>{{902, 979}, {462, 36}}</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <boolean value="YES"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <object class="NSAffineTransform">
+ <bytes key="NSTransformStruct">P4AAAL+AAABBiAAAwcgAAA</bytes>
+ </object>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <object class="NSAffineTransform"/>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="unlocalizedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference key="dict.sortedKeys" ref="0"/>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <nil key="activeLocalization"/>
+ <object class="NSMutableDictionary" key="localizations">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference key="dict.sortedKeys" ref="0"/>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <nil key="sourceID"/>
+ <int key="maxID">49</int>
+ </object>
+ <object class="IBClassDescriber" key="IBDocument.Classes">
+ <object class="NSMutableArray" key="referencedPartialClassDescriptions">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBPartialClassDescription">
+ <string key="className">AnimatableView</string>
+ <string key="superclassName">BackgroundGradientView</string>
+ <object class="NSMutableDictionary" key="outlets">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>delegate_</string>
+ <string>resizeDelegate_</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>id</string>
+ <string>id</string>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="toOneOutletInfosByName">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>delegate_</string>
+ <string>resizeDelegate_</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBToOneOutletInfo">
+ <string key="name">delegate_</string>
+ <string key="candidateClassName">id</string>
+ </object>
+ <object class="IBToOneOutletInfo">
+ <string key="name">resizeDelegate_</string>
+ <string key="candidateClassName">id</string>
+ </object>
+ </object>
+ </object>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">browser/ui/cocoa/animatable_view.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">BackgroundGradientView</string>
+ <string key="superclassName">NSView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">browser/ui/cocoa/background_gradient_view.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">FullscreenExitBubbleController</string>
+ <string key="superclassName">NSViewController</string>
+ <object class="NSMutableDictionary" key="actions">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>allow:</string>
+ <string>deny:</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>id</string>
+ <string>id</string>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="actionInfosByName">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>allow:</string>
+ <string>deny:</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBActionInfo">
+ <string key="name">allow:</string>
+ <string key="candidateClassName">id</string>
+ </object>
+ <object class="IBActionInfo">
+ <string key="name">deny:</string>
+ <string key="candidateClassName">id</string>
+ </object>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="outlets">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>allowButton_</string>
+ <string>denyButton_</string>
+ <string>exitLabelPlaceholder_</string>
+ <string>siteInfoLabel_</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>NSButton</string>
+ <string>NSButton</string>
+ <string>NSTextField</string>
+ <string>NSTextField</string>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="toOneOutletInfosByName">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>allowButton_</string>
+ <string>denyButton_</string>
+ <string>exitLabelPlaceholder_</string>
+ <string>siteInfoLabel_</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBToOneOutletInfo">
+ <string key="name">allowButton_</string>
+ <string key="candidateClassName">NSButton</string>
+ </object>
+ <object class="IBToOneOutletInfo">
+ <string key="name">denyButton_</string>
+ <string key="candidateClassName">NSButton</string>
+ </object>
+ <object class="IBToOneOutletInfo">
+ <string key="name">exitLabelPlaceholder_</string>
+ <string key="candidateClassName">NSTextField</string>
+ </object>
+ <object class="IBToOneOutletInfo">
+ <string key="name">siteInfoLabel_</string>
+ <string key="candidateClassName">NSTextField</string>
+ </object>
+ </object>
+ </object>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">browser/ui/cocoa/fullscreen_exit_bubble_controller.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">../third_party/GTM/Foundation/GTMNSObject+KeyValueObserving.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">browser/renderer_host/accelerated_plugin_view_mac.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">browser/ui/cocoa/objc_zombie.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">browser/ui/cocoa/status_bubble_mac.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">browser/ui/cocoa/tabs/tab_strip_model_observer_bridge.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">browser/ui/cocoa/nsview_additions.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">browser/ui/cocoa/view_id_util.h</string>
+ </object>
+ </object>
+ </object>
+ <object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.1+">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBPartialClassDescription">
+ <string key="className">FullscreenExitBubbleView</string>
+ <string key="superclassName">BackgroundGradientView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBDocumentRelativeSource</string>
+ <string key="minorKey">../../browser/ui/cocoa/fullscreen_exit_bubble_view.h</string>
+ </object>
+ </object>
+ </object>
+ <object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSActionCell</string>
+ <string key="superclassName">NSCell</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSActionCell.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSApplication</string>
+ <string key="superclassName">NSResponder</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier" id="94936516">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSApplication.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSApplication</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier" id="520242494">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSApplicationScripting.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSApplication</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier" id="745176575">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSColorPanel.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSApplication</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSHelpManager.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSApplication</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSPageLayout.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSButton</string>
+ <string key="superclassName">NSControl</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSButton.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSCell</string>
+ <string key="superclassName">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSCell.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSControl</string>
+ <string key="superclassName">NSView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier" id="655578352">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSControl.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSFormatter</string>
+ <string key="superclassName">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSFormatter.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSMenu</string>
+ <string key="superclassName">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier" id="1001211166">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSMenu.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AddressBook.framework/Headers/ABActions.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSAccessibility.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSAlert.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSAnimation.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <reference key="sourceIdentifier" ref="94936516"/>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <reference key="sourceIdentifier" ref="520242494"/>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSBrowser.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <reference key="sourceIdentifier" ref="745176575"/>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSComboBox.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSComboBoxCell.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <reference key="sourceIdentifier" ref="655578352"/>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSDatePickerCell.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSDictionaryController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSDragging.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSDrawer.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSFontManager.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSFontPanel.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSImage.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSKeyValueBinding.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <reference key="sourceIdentifier" ref="1001211166"/>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSNibLoading.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSOutlineView.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSPasteboard.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSRuleEditor.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSSavePanel.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSSound.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSSpeechRecognizer.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSSpeechSynthesizer.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSSplitView.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSTabView.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSTableView.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSText.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSTextStorage.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSTextView.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSTokenField.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSTokenFieldCell.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSToolbar.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSToolbarItem.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier" id="935537092">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSView.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSWindow.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSArchiver.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSClassDescription.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSConnection.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSError.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSFileManager.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSKeyValueCoding.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSKeyValueObserving.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSKeyedArchiver.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSMetadata.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSNetServices.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSObject.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSObjectScripting.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSPort.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSPortCoder.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSRunLoop.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSScriptClassDescription.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSScriptKeyValueCoding.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSScriptObjectSpecifiers.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSScriptWhoseTests.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSSpellServer.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSStream.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSThread.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSURL.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSURLConnection.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSURLDownload.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSXMLParser.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Print.framework/Headers/PDEPluginInterface.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">QuartzCore.framework/Headers/CAAnimation.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">QuartzCore.framework/Headers/CALayer.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">QuartzCore.framework/Headers/CIImageProvider.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">SecurityInterface.framework/Headers/SFAuthorizationView.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">SecurityInterface.framework/Headers/SFCertificatePanel.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">SecurityInterface.framework/Headers/SFChooseIdentityPanel.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSResponder</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSInterfaceStyle.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSResponder</string>
+ <string key="superclassName">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSResponder.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSTextField</string>
+ <string key="superclassName">NSControl</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSTextField.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSTextFieldCell</string>
+ <string key="superclassName">NSActionCell</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSTextFieldCell.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSClipView.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSMenuItem.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSRulerView.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSView</string>
+ <string key="superclassName">NSResponder</string>
+ <reference key="sourceIdentifier" ref="935537092"/>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSViewController</string>
+ <string key="superclassName">NSResponder</string>
+ <object class="NSMutableDictionary" key="outlets">
+ <string key="NS.key.0">view</string>
+ <string key="NS.object.0">NSView</string>
+ </object>
+ <object class="NSMutableDictionary" key="toOneOutletInfosByName">
+ <string key="NS.key.0">view</string>
+ <object class="IBToOneOutletInfo" key="NS.object.0">
+ <string key="name">view</string>
+ <string key="candidateClassName">NSView</string>
+ </object>
+ </object>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSViewController.h</string>
+ </object>
+ </object>
+ </object>
+ </object>
+ <int key="IBDocument.localizationMode">0</int>
+ <string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string>
+ <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencies">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.macosx</string>
+ <integer value="1050" key="NS.object.0"/>
+ </object>
+ <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencyDefaults">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.macosx</string>
+ <integer value="1050" key="NS.object.0"/>
+ </object>
+ <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3</string>
+ <integer value="3000" key="NS.object.0"/>
+ </object>
+ <bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
+ <string key="IBDocument.LastKnownRelativeProjectPath">../../chrome.xcodeproj</string>
+ <int key="IBDocument.defaultPropertyAccessControl">3</int>
+ </data>
+</archive>
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc
index e408ab9..2ef6be3 100644
--- a/chrome/browser/ui/browser.cc
+++ b/chrome/browser/ui/browser.cc
@@ -1314,7 +1314,13 @@ void Browser::WindowFullscreenStateChanged() {
MessageLoop::current()->PostTask(
FROM_HERE, method_factory_.NewRunnableMethod(
&Browser::NotifyFullscreenChange));
- if (!window_->IsFullscreen())
+ bool notify_tab_of_exit;
+#if defined(OS_MACOSX)
+ notify_tab_of_exit = !window_->InPresentationMode();
+#else
+ notify_tab_of_exit = !window_->IsFullscreen();
+#endif
+ if (notify_tab_of_exit)
NotifyTabOfFullscreenExitIfNecessary();
}
@@ -3809,10 +3815,21 @@ void Browser::ToggleFullscreenModeForTab(TabContents* tab,
return;
fullscreened_tab_ = enter_fullscreen ?
TabContentsWrapper::GetCurrentWrapperForContents(tab) : NULL;
- if (enter_fullscreen && !window_->IsFullscreen())
+ bool in_correct_mode_for_tab_fullscreen;
+#if defined(OS_MACOSX)
+ in_correct_mode_for_tab_fullscreen = window_->InPresentationMode();
+#else
+ in_correct_mode_for_tab_fullscreen = window_->IsFullscreen();
+#endif
+ if (enter_fullscreen && !in_correct_mode_for_tab_fullscreen)
tab_caused_fullscreen_ = true;
- if (tab_caused_fullscreen_)
+ if (tab_caused_fullscreen_) {
+#if defined(OS_MACOSX)
+ TogglePresentationMode();
+#else
ToggleFullscreenMode();
+#endif
+ }
}
void Browser::JSOutOfMemory(TabContents* tab) {
diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h
index c11dd61..171b272 100644
--- a/chrome/browser/ui/browser.h
+++ b/chrome/browser/ui/browser.h
@@ -831,6 +831,10 @@ class Browser : public TabHandlerDelegate,
bool is_app() const;
bool is_devtools() const;
+ // True when the current tab is in fullscreen mode, requested by
+ // webkitRequestFullScreen.
+ bool is_fullscreen_for_tab() const { return fullscreened_tab_ != NULL; }
+
protected:
// Wrapper for the factory method in BrowserWindow. This allows subclasses to
// set their own window.
@@ -844,6 +848,7 @@ class Browser : public TabHandlerDelegate,
FRIEND_TEST_ALL_PREFIXES(BrowserTest, AppIdSwitch);
FRIEND_TEST_ALL_PREFIXES(BrowserTest, TestNewTabExitsFullscreen);
FRIEND_TEST_ALL_PREFIXES(BrowserTest, TestTabExitsItselfFromFullscreen);
+ FRIEND_TEST_ALL_PREFIXES(BrowserTest, TabEntersPresentationModeFromWindowed);
FRIEND_TEST_ALL_PREFIXES(BrowserInitTest, OpenAppShortcutNoPref);
FRIEND_TEST_ALL_PREFIXES(BrowserInitTest, OpenAppShortcutWindowPref);
FRIEND_TEST_ALL_PREFIXES(BrowserInitTest, OpenAppShortcutTabPref);
@@ -1413,10 +1418,11 @@ class Browser : public TabHandlerDelegate,
BookmarkBar::State bookmark_bar_state_;
- // Tab to notify when the browser exits fullscreen mode.
+ // If there is currently a tab in fullscreen mode (entered via
+ // webkitRequestFullScreen), this is its wrapper.
TabContentsWrapper* fullscreened_tab_;
- // True if the current tab is in fullscreen mode.
+ // True if the current tab entered fullscreen mode via webkitRequestFullScreen
bool tab_caused_fullscreen_;
DISALLOW_COPY_AND_ASSIGN(Browser);
diff --git a/chrome/browser/ui/browser_browsertest.cc b/chrome/browser/ui/browser_browsertest.cc
index 61b2020..d1933a4 100644
--- a/chrome/browser/ui/browser_browsertest.cc
+++ b/chrome/browser/ui/browser_browsertest.cc
@@ -6,6 +6,9 @@
#include "base/compiler_specific.h"
#include "base/file_path.h"
+#if defined(OS_MACOSX)
+#include "base/mac/mac_util.h"
+#endif
#include "base/sys_info.h"
#include "base/utf_string_conversions.h"
#include "chrome/app/chrome_command_ids.h"
@@ -824,6 +827,36 @@ IN_PROC_BROWSER_TEST_F(BrowserTest, TestTabExitsItselfFromFullscreen) {
ASSERT_FALSE(browser()->window()->IsFullscreen());
}
+#if defined(OS_MACOSX)
+IN_PROC_BROWSER_TEST_F(BrowserTest, TabEntersPresentationModeFromWindowed) {
+ ASSERT_TRUE(test_server()->Start());
+
+ AddTabAtIndex(0, GURL("about:blank"), PageTransition::TYPED);
+
+ TabContents* fullscreen_tab = browser()->GetSelectedTabContents();
+
+ EXPECT_FALSE(browser()->window()->IsFullscreen());
+ EXPECT_FALSE(browser()->window()->InPresentationMode());
+ browser()->ToggleFullscreenModeForTab(fullscreen_tab, true);
+ ui_test_utils::WaitForNotification(chrome::NOTIFICATION_FULLSCREEN_CHANGED);
+ ASSERT_TRUE(browser()->window()->IsFullscreen());
+ ASSERT_TRUE(browser()->window()->InPresentationMode());
+ browser()->TogglePresentationMode();
+ ui_test_utils::WaitForNotification(chrome::NOTIFICATION_FULLSCREEN_CHANGED);
+ ASSERT_FALSE(browser()->window()->IsFullscreen());
+ ASSERT_FALSE(browser()->window()->InPresentationMode());
+
+ if (base::mac::IsOSLionOrLater()) {
+ // Test that tab fullscreen mode doesn't make presentation mode the default
+ // on Lion.
+ browser()->ToggleFullscreenMode();
+ ui_test_utils::WaitForNotification(chrome::NOTIFICATION_FULLSCREEN_CHANGED);
+ ASSERT_TRUE(browser()->window()->IsFullscreen());
+ ASSERT_FALSE(browser()->window()->InPresentationMode());
+ }
+}
+#endif
+
// Chromeos defaults to restoring the last session, so this test isn't
// applicable.
#if !defined(OS_CHROMEOS)
diff --git a/chrome/browser/ui/cocoa/browser_window_controller.h b/chrome/browser/ui/cocoa/browser_window_controller.h
index 897dad0..a7ecea6 100644
--- a/chrome/browser/ui/cocoa/browser_window_controller.h
+++ b/chrome/browser/ui/cocoa/browser_window_controller.h
@@ -19,6 +19,7 @@
#import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.h"
#import "chrome/browser/ui/cocoa/bookmarks/bookmark_bubble_controller.h"
#import "chrome/browser/ui/cocoa/browser_command_executor.h"
+#import "chrome/browser/ui/cocoa/fullscreen_exit_bubble_controller.h"
#import "chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.h"
#import "chrome/browser/ui/cocoa/tabs/tab_strip_controller.h"
#import "chrome/browser/ui/cocoa/tabs/tab_window_controller.h"
@@ -73,6 +74,8 @@ class TabContents;
scoped_nsobject<SidebarController> sidebarController_;
scoped_nsobject<PreviewableContentsController> previewableContentsController_;
scoped_nsobject<PresentationModeController> presentationModeController_;
+ scoped_nsobject<FullscreenExitBubbleController>
+ fullscreenExitBubbleController_;
// Strong. StatusBubble is a special case of a strong reference that
// we don't wrap in a scoped_ptr because it is acting the same
diff --git a/chrome/browser/ui/cocoa/browser_window_controller.mm b/chrome/browser/ui/cocoa/browser_window_controller.mm
index 3508698..dba32f7 100644
--- a/chrome/browser/ui/cocoa/browser_window_controller.mm
+++ b/chrome/browser/ui/cocoa/browser_window_controller.mm
@@ -1943,13 +1943,18 @@ willAnimateFromState:(bookmarks::VisualState)oldState
enteredPresentationModeFromFullscreen_ = YES;
if ([[self window] isKindOfClass:[FramedBrowserWindow class]])
[static_cast<FramedBrowserWindow*>([self window]) toggleSystemFullScreen];
- return;
+ } else {
+ if (fullscreen)
+ [self enterFullscreenForSnowLeopardOrEarlier];
+ else
+ [self exitFullscreenForSnowLeopardOrEarlier];
}
- if (fullscreen)
- [self enterFullscreenForSnowLeopardOrEarlier];
- else
- [self exitFullscreenForSnowLeopardOrEarlier];
+ if (fullscreen) {
+ [self showFullscreenExitBubbleIfNecessary];
+ } else {
+ [self destroyFullscreenExitBubbleIfNecessary];
+ }
}
- (BOOL)isFullscreen {
@@ -1980,7 +1985,9 @@ willAnimateFromState:(bookmarks::VisualState)oldState
if (presentationMode) {
BOOL fullscreen = [self isFullscreen];
- [self setShouldUsePresentationModeWhenEnteringFullscreen:YES];
+ BOOL fullscreen_for_tab = browser_->is_fullscreen_for_tab();
+ if (!fullscreen_for_tab)
+ [self setShouldUsePresentationModeWhenEnteringFullscreen:YES];
enteredPresentationModeFromFullscreen_ = fullscreen;
if (fullscreen) {
@@ -2002,6 +2009,8 @@ willAnimateFromState:(bookmarks::VisualState)oldState
if ([window isKindOfClass:[FramedBrowserWindow class]])
[static_cast<FramedBrowserWindow*>(window) toggleSystemFullScreen];
}
+
+ [self showFullscreenExitBubbleIfNecessary];
} else {
if (enteredPresentationModeFromFullscreen_) {
// The window is currently in fullscreen mode, but the user is choosing to
@@ -2019,6 +2028,8 @@ willAnimateFromState:(bookmarks::VisualState)oldState
if ([window isKindOfClass:[FramedBrowserWindow class]])
[static_cast<FramedBrowserWindow*>(window) toggleSystemFullScreen];
}
+
+ [self destroyFullscreenExitBubbleIfNecessary];
}
}
diff --git a/chrome/browser/ui/cocoa/browser_window_controller_private.h b/chrome/browser/ui/cocoa/browser_window_controller_private.h
index 39b1f38..0cb3e3f 100644
--- a/chrome/browser/ui/cocoa/browser_window_controller_private.h
+++ b/chrome/browser/ui/cocoa/browser_window_controller_private.h
@@ -43,6 +43,10 @@
// call even when not in presentation mode.
- (CGFloat)floatingBarHeight;
+// Shows the informational "how to exit fullscreen" bubble.
+- (void)showFullscreenExitBubbleIfNecessary;
+- (void)destroyFullscreenExitBubbleIfNecessary;
+
// Lays out the presentation mode toggle button at the top right corner of the
// overlay. Creates the button if needed, and removes it if it is not needed.
// This method is safe to call on all OS versions.
diff --git a/chrome/browser/ui/cocoa/browser_window_controller_private.mm b/chrome/browser/ui/cocoa/browser_window_controller_private.mm
index 3a4b410..247eb06 100644
--- a/chrome/browser/ui/cocoa/browser_window_controller_private.mm
+++ b/chrome/browser/ui/cocoa/browser_window_controller_private.mm
@@ -683,7 +683,9 @@ willPositionSheet:(NSWindow*)sheet
return;
if (presentationMode) {
- BOOL showDropdown = forceDropdown || [self floatingBarHasFocus];
+ BOOL fullscreen_for_tab = browser_->is_fullscreen_for_tab();
+ BOOL showDropdown = !fullscreen_for_tab &&
+ (forceDropdown || [self floatingBarHasFocus]);
NSView* contentView = [[self window] contentView];
presentationModeController_.reset(
[[PresentationModeController alloc] initWithBrowserController:self]);
@@ -790,6 +792,30 @@ willPositionSheet:(NSWindow*)sheet
: [toolbarController_ view]];
}
+- (void)showFullscreenExitBubbleIfNecessary {
+ if (!browser_->is_fullscreen_for_tab()) {
+ return;
+ }
+
+ [presentationModeController_ ensureOverlayHiddenWithAnimation:NO delay:NO];
+
+ fullscreenExitBubbleController_.reset(
+ [[FullscreenExitBubbleController alloc] initWithOwner:self
+ browser:browser_.get()]);
+ NSView* contentView = [[self window] contentView];
+ CGFloat maxWidth = NSWidth([contentView frame]);
+ CGFloat maxY = NSMaxY([[[self window] contentView] frame]);
+ [fullscreenExitBubbleController_
+ positionInWindowAtTop:maxY width:maxWidth];
+ [contentView addSubview:[fullscreenExitBubbleController_ view]
+ positioned:NSWindowAbove relativeTo:[self tabContentArea]];
+}
+
+- (void)destroyFullscreenExitBubbleIfNecessary {
+ [[fullscreenExitBubbleController_ view] removeFromSuperview];
+ fullscreenExitBubbleController_.reset();
+}
+
- (void)contentViewDidResize:(NSNotification*)notification {
[self layoutSubviews];
}
@@ -827,6 +853,7 @@ willPositionSheet:(NSWindow*)sheet
NSWindow* window = [self window];
savedRegularWindowFrame_ = [window frame];
BOOL mode = [self shouldUsePresentationModeWhenEnteringFullscreen];
+ mode = mode || browser_->is_fullscreen_for_tab();
[self setPresentationModeInternal:mode forceDropdown:NO];
}
diff --git a/chrome/browser/ui/cocoa/fullscreen_exit_bubble_controller.h b/chrome/browser/ui/cocoa/fullscreen_exit_bubble_controller.h
new file mode 100644
index 0000000..7bb8220
--- /dev/null
+++ b/chrome/browser/ui/cocoa/fullscreen_exit_bubble_controller.h
@@ -0,0 +1,46 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <Cocoa/Cocoa.h>
+
+#import "base/mac/cocoa_protocols.h"
+#include "base/memory/scoped_nsobject.h"
+#include "googleurl/src/gurl.h"
+
+@class AnimatableView;
+class TabContentsWrapper;
+@class BrowserWindowController;
+class Browser;
+
+// The FullscreenExitBubbleController manages the bubble that tells the user
+// how to escape fullscreen mode. The bubble only appears when a tab requests
+// fullscreen mode via webkitRequestFullScreen().
+@interface FullscreenExitBubbleController :
+ NSViewController<NSTextViewDelegate> {
+ @private
+ BrowserWindowController* owner_; // weak
+ Browser* browser_; // weak
+
+ @protected
+ IBOutlet NSTextField* exitLabelPlaceholder_;
+
+ // Text fields don't work as well with embedded links as text views, but
+ // text views cannot conveniently be created in IB. The xib file contains
+ // a text field |exitLabelPlaceholder_| that's replaced by this text view
+ // |exitLabel_| in -awakeFromNib.
+ scoped_nsobject<NSTextView> exitLabel_;
+
+ scoped_nsobject<NSTimer> hideTimer_;
+ scoped_nsobject<NSAnimation> hideAnimation_;
+};
+
+- (id)initWithOwner:(BrowserWindowController*)owner browser:(Browser*)browser;
+
+// Positions the fullscreen exit bubble in the top-center of the window.
+- (void)positionInWindowAtTop:(CGFloat)maxY width:(CGFloat)maxWidth;
+
+// Returns a pointer to this controller's view, cast as an AnimatableView.
+- (AnimatableView*)animatableView;
+
+@end
diff --git a/chrome/browser/ui/cocoa/fullscreen_exit_bubble_controller.mm b/chrome/browser/ui/cocoa/fullscreen_exit_bubble_controller.mm
new file mode 100644
index 0000000..b3829bd
--- /dev/null
+++ b/chrome/browser/ui/cocoa/fullscreen_exit_bubble_controller.mm
@@ -0,0 +1,208 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/logging.h" // for NOTREACHED()
+#include "base/mac/mac_util.h"
+#include "base/sys_string_conversions.h"
+#include "chrome/app/chrome_command_ids.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
+#import "chrome/browser/ui/cocoa/animatable_view.h"
+#import "chrome/browser/ui/cocoa/browser_window_controller.h"
+#include "chrome/browser/ui/cocoa/event_utils.h"
+#import "chrome/browser/ui/cocoa/fullscreen_exit_bubble_controller.h"
+#import "chrome/browser/ui/cocoa/hyperlink_text_view.h"
+#include "grit/generated_resources.h"
+#include "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
+#import "third_party/GTM/AppKit/GTMNSAnimation+Duration.h"
+#include "ui/base/models/accelerator_cocoa.h"
+#include "ui/base/l10n/l10n_util_mac.h"
+
+const int kPaddingPx = 8;
+const int kInitialDelayMs = 3800;
+const int kSlideOutDurationMs = 700;
+
+@interface FullscreenExitBubbleController (PrivateMethods)
+// Sets |exitLabel_| based on |exitLabelPlaceholder_|,
+// sets |exitLabelPlaceholder_| to nil.
+- (void)initializeLabel;
+
+- (void)hideSoon;
+
+// Returns the Accelerator for the Toggle Fullscreen menu item.
++ (ui::AcceleratorCocoa)acceleratorForToggleFullscreen;
+
+// Returns a string representation fit for display of
+// +acceleratorForToggleFullscreen.
++ (NSString*)keyCommandString;
+
++ (NSString*)keyCombinationForAccelerator:(const ui::AcceleratorCocoa&)item;
+@end
+
+@implementation FullscreenExitBubbleController
+
+- (id)initWithOwner:(BrowserWindowController*)owner browser:(Browser*)browser {
+ if ((self = [super initWithNibName:@"FullscreenExitBubble"
+ bundle:base::mac::MainAppBundle()])) {
+ browser_ = browser;
+ owner_ = owner;
+ }
+ return self;
+}
+
+- (void)awakeFromNib {
+ [self initializeLabel];
+ [self hideSoon];
+}
+
+- (void)positionInWindowAtTop:(CGFloat)maxY width:(CGFloat)maxWidth {
+ NSRect bubbleFrame = [[self view] frame];
+ bubbleFrame.origin.x = (int)(maxWidth/2 - NSWidth(bubbleFrame)/2);
+ bubbleFrame.origin.y = maxY - NSHeight(bubbleFrame);
+ [[self view] setFrame:bubbleFrame];
+}
+
+// Called when someone clicks on the embedded link.
+- (BOOL) textView:(NSTextView*)textView
+ clickedOnLink:(id)link
+ atIndex:(NSUInteger)charIndex {
+ browser_->ExecuteCommand(IDC_FULLSCREEN);
+ return YES;
+}
+
+- (void)hideTimerFired:(NSTimer*)timer {
+ NSRect endFrame = [[self view] frame];
+ endFrame.origin.y += endFrame.size.height;
+ endFrame.size.height = 0;
+ NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:
+ [self view], NSViewAnimationTargetKey,
+ [NSValue valueWithRect:endFrame], NSViewAnimationEndFrameKey, nil];
+
+ NSViewAnimation* animation =
+ [[NSViewAnimation alloc]
+ initWithViewAnimations:[NSArray arrayWithObjects:dict, nil]];
+ [animation gtm_setDuration:kSlideOutDurationMs/1000.0
+ eventMask:NSLeftMouseUpMask];
+ [animation setDelegate:self];
+ [animation startAnimation];
+ hideAnimation_.reset(animation);
+}
+
+- (void)animationDidEnd:(NSAnimation*)animation {
+ if (animation == hideAnimation_.get()) {
+ hideAnimation_.reset();
+ }
+}
+
+- (AnimatableView*)animatableView {
+ return static_cast<AnimatableView*>([self view]);
+}
+
+- (void)dealloc {
+ [hideAnimation_.get() stopAnimation];
+ [hideTimer_ invalidate];
+ [super dealloc];
+}
+
+@end
+
+@implementation FullscreenExitBubbleController (PrivateMethods)
+
+- (void)initializeLabel {
+ // Replace the label placeholder NSTextField with the real label NSTextView.
+ // The former doesn't show links in a nice way, but the latter can't be added
+ // in IB without a containing scroll view, so create the NSTextView
+ // programmatically.
+ exitLabel_.reset([[HyperlinkTextView alloc]
+ initWithFrame:[exitLabelPlaceholder_ frame]]);
+ [exitLabel_.get() setAutoresizingMask:
+ [exitLabelPlaceholder_ autoresizingMask]];
+ [[exitLabelPlaceholder_ superview]
+ replaceSubview:exitLabelPlaceholder_ with:exitLabel_.get()];
+ exitLabelPlaceholder_ = nil; // Now released.
+ [exitLabel_.get() setDelegate:self];
+
+ NSString *message = l10n_util::GetNSStringF(IDS_EXIT_FULLSCREEN_MODE,
+ base::SysNSStringToUTF16([[self class] keyCommandString]));
+
+ [(HyperlinkTextView*)exitLabel_.get()
+ setMessageAndLink:@""
+ withLink:message
+ atOffset:0
+ font:[NSFont systemFontOfSize:18]
+ messageColor:[NSColor whiteColor]
+ linkColor:[NSColor whiteColor]];
+
+ [exitLabel_.get() sizeToFit];
+ NSLayoutManager* layoutManager = [exitLabel_.get() layoutManager];
+ NSTextContainer* textContainer = [exitLabel_.get() textContainer];
+ [layoutManager ensureLayoutForTextContainer:textContainer];
+ NSRect textFrame = [layoutManager usedRectForTextContainer:textContainer];
+ NSRect frame = [[self view] frame];
+ NSSize textSize = textFrame.size;
+ frame.size.width = textSize.width + 2 * kPaddingPx;
+ [[self view] setFrame:frame];
+ textFrame.origin.x = textFrame.origin.y = kPaddingPx;
+ [exitLabel_.get() setFrame:textFrame];
+}
+
+// This looks at the Main Menu and determines what the user has set as the
+// key combination for quit. It then gets the modifiers and builds an object
+// to hold the data.
++ (ui::AcceleratorCocoa)acceleratorForToggleFullscreen {
+ NSMenu* mainMenu = [NSApp mainMenu];
+ // Get the application menu (i.e. Chromium).
+ for (NSMenuItem* menu in [mainMenu itemArray]) {
+ for (NSMenuItem* item in [[menu submenu] itemArray]) {
+ // Find the toggle presentation mode item.
+ if ([item tag] == IDC_PRESENTATION_MODE) {
+ return ui::AcceleratorCocoa([item keyEquivalent],
+ [item keyEquivalentModifierMask]);
+ }
+ }
+ }
+ // Default to Cmd+Shift+F.
+ return ui::AcceleratorCocoa(@"f", NSCommandKeyMask|NSShiftKeyMask);
+}
+
+// This looks at the Main Menu and determines what the user has set as the
+// key combination for quit. It then gets the modifiers and builds a string
+// to display them.
++ (NSString*)keyCommandString {
+ ui::AcceleratorCocoa accelerator =
+ [[self class] acceleratorForToggleFullscreen];
+ return [[self class] keyCombinationForAccelerator:accelerator];
+}
+
++ (NSString*)keyCombinationForAccelerator:(const ui::AcceleratorCocoa&)item {
+ NSMutableString* string = [NSMutableString string];
+ NSUInteger modifiers = item.modifiers();
+
+ if (modifiers & NSCommandKeyMask)
+ [string appendString:@"\u2318"];
+ if (modifiers & NSControlKeyMask)
+ [string appendString:@"\u2303"];
+ if (modifiers & NSAlternateKeyMask)
+ [string appendString:@"\u2325"];
+ BOOL isUpperCase = [[NSCharacterSet uppercaseLetterCharacterSet]
+ characterIsMember:[item.characters() characterAtIndex:0]];
+ if (modifiers & NSShiftKeyMask || isUpperCase)
+ [string appendString:@"\u21E7"];
+
+ [string appendString:[item.characters() uppercaseString]];
+ return string;
+}
+
+- (void)hideSoon {
+ hideTimer_.reset(
+ [[NSTimer scheduledTimerWithTimeInterval:kInitialDelayMs/1000.0
+ target:self
+ selector:@selector(hideTimerFired:)
+ userInfo:nil
+ repeats:NO] retain]);
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/fullscreen_exit_bubble_controller_unittest.mm b/chrome/browser/ui/cocoa/fullscreen_exit_bubble_controller_unittest.mm
new file mode 100644
index 0000000..c5b6121
--- /dev/null
+++ b/chrome/browser/ui/cocoa/fullscreen_exit_bubble_controller_unittest.mm
@@ -0,0 +1,73 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "chrome/browser/ui/cocoa/fullscreen_exit_bubble_controller.h"
+
+#include "chrome/browser/ui/cocoa/cocoa_profile_test.h"
+#include "testing/gtest_mac.h"
+#include "ui/base/models/accelerator_cocoa.h"
+
+@interface FullscreenExitBubbleController(JustForTesting)
+// Already defined.
++ (NSString*)keyCommandString;
++ (NSString*)keyCombinationForAccelerator:(const ui::AcceleratorCocoa&)item;
+@end
+
+@interface FullscreenExitBubbleController(ExposedForTesting)
+- (NSTextField*)exitLabelPlaceholder;
+- (NSTextView*)exitLabel;
+@end
+
+@implementation FullscreenExitBubbleController(ExposedForTesting)
+- (NSTextField*)exitLabelPlaceholder {
+ return exitLabelPlaceholder_;
+}
+
+- (NSTextView*)exitLabel {
+ return exitLabel_;
+}
+@end
+
+class FullscreenExitBubbleControllerTest : public CocoaTest {
+ public:
+ virtual void SetUp() {
+ CocoaTest::SetUp();
+
+ controller_.reset(
+ [[FullscreenExitBubbleController alloc] initWithOwner:nil browser:nil]);
+ EXPECT_TRUE([controller_ view]);
+
+ [[test_window() contentView] addSubview:[controller_ view]];
+ }
+
+ scoped_nsobject<FullscreenExitBubbleController> controller_;
+};
+
+TEST_VIEW(FullscreenExitBubbleControllerTest, [controller_ view])
+
+TEST_F(FullscreenExitBubbleControllerTest, LabelWasReplaced) {
+ EXPECT_FALSE([controller_ exitLabelPlaceholder]);
+ EXPECT_TRUE([controller_ exitLabel]);
+}
+
+TEST_F(FullscreenExitBubbleControllerTest, LabelContainsShortcut) {
+ NSString* shortcut = [FullscreenExitBubbleController keyCommandString];
+ EXPECT_GT([shortcut length], 0U);
+
+ NSString* message = [[[controller_ exitLabel] textStorage] string];
+
+ NSRange range = [message rangeOfString:shortcut];
+ EXPECT_NE(NSNotFound, range.location);
+}
+
+TEST_F(FullscreenExitBubbleControllerTest, ShortcutText) {
+ ui::AcceleratorCocoa cmd_F(@"F", NSCommandKeyMask);
+ ui::AcceleratorCocoa cmd_shift_f(@"f", NSCommandKeyMask|NSShiftKeyMask);
+ NSString* cmd_F_text = [FullscreenExitBubbleController
+ keyCombinationForAccelerator:cmd_F];
+ NSString* cmd_shift_f_text = [FullscreenExitBubbleController
+ keyCombinationForAccelerator:cmd_shift_f];
+ EXPECT_NSEQ(cmd_shift_f_text, cmd_F_text);
+ EXPECT_NSEQ(@"\u2318\u21E7F", cmd_shift_f_text);
+}
diff --git a/chrome/browser/ui/cocoa/fullscreen_exit_bubble_view.h b/chrome/browser/ui/cocoa/fullscreen_exit_bubble_view.h
new file mode 100644
index 0000000..d389dcb
--- /dev/null
+++ b/chrome/browser/ui/cocoa/fullscreen_exit_bubble_view.h
@@ -0,0 +1,22 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_COCOA_FULLSCREEN_EXIT_BUBBLE_VIEW_H_
+#define CHROME_BROWSER_UI_COCOA_FULLSCREEN_EXIT_BUBBLE_VIEW_H_
+#pragma once
+
+#import <Cocoa/Cocoa.h>
+
+#include "chrome/browser/ui/cocoa/background_gradient_view.h"
+
+// A view that handles painting the background for the Fullscreen Exit Bubble.
+@interface FullscreenExitBubbleView : BackgroundGradientView
+
+// Specifies that mouse events over this view should be ignored by the
+// render host.
+- (BOOL)nonWebContentView;
+
+@end
+
+#endif // CHROME_BROWSER_UI_COCOA_FULLSCREEN_EXIT_BUBBLE_VIEW_H_
diff --git a/chrome/browser/ui/cocoa/fullscreen_exit_bubble_view.mm b/chrome/browser/ui/cocoa/fullscreen_exit_bubble_view.mm
new file mode 100644
index 0000000..a66af63
--- /dev/null
+++ b/chrome/browser/ui/cocoa/fullscreen_exit_bubble_view.mm
@@ -0,0 +1,92 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "chrome/browser/ui/cocoa/fullscreen_exit_bubble_view.h"
+
+#import "chrome/browser/ui/cocoa/nsview_additions.h"
+#import "chrome/browser/ui/cocoa/themed_window.h"
+#import "chrome/browser/ui/cocoa/url_drop_target.h"
+#import "chrome/browser/ui/cocoa/view_id_util.h"
+#include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
+
+CGFloat kCurveSize = 8;
+
+@implementation FullscreenExitBubbleView
+
+- (void)drawRect:(NSRect)rect {
+ const CGFloat lineWidth = [self cr_lineWidth];
+
+ rect = NSOffsetRect([self bounds], 0, lineWidth*2);
+
+ NSPoint topLeft = NSMakePoint(NSMinX(rect), NSMaxY(rect));
+ NSPoint topRight = NSMakePoint(NSMaxX(rect), NSMaxY(rect));
+ NSPoint midLeft =
+ NSMakePoint(NSMinX(rect), NSMinY(rect) + kCurveSize);
+ NSPoint midRight =
+ NSMakePoint(NSMaxX(rect), NSMinY(rect) + kCurveSize);
+ NSPoint bottomLeft =
+ NSMakePoint(NSMinX(rect) + kCurveSize, NSMinY(rect));
+ NSPoint bottomRight =
+ NSMakePoint(NSMaxX(rect) - kCurveSize, NSMinY(rect));
+
+ NSBezierPath* path = [NSBezierPath bezierPath];
+ [path moveToPoint:topLeft];
+ [path appendBezierPathWithArcWithCenter:NSMakePoint(bottomLeft.x, midLeft.y)
+ radius:kCurveSize startAngle:180 endAngle:270];
+
+ [path lineToPoint:bottomRight];
+ [path appendBezierPathWithArcWithCenter:NSMakePoint(bottomRight.x, midRight.y)
+ radius:kCurveSize startAngle:270 endAngle:360];
+ [path lineToPoint:topRight];
+
+ {
+ gfx::ScopedNSGraphicsContextSaveGState scopedGState;
+ [path addClip];
+
+ const NSRect bounds = [self bounds];
+
+ [[NSColor colorWithDeviceWhite:0 alpha:0.7] set];
+ NSRectFillUsingOperation(bounds, NSCompositeSourceOver);
+ }
+
+}
+
+// Eat all mouse events, to prevent clicks from falling through to views below.
+- (void)mouseDown:(NSEvent *)theEvent {
+}
+
+- (void)rightMouseDown:(NSEvent *)theEvent {
+}
+
+- (void)otherMouseDown:(NSEvent *)theEvent {
+}
+
+- (void)mouseUp:(NSEvent *)theEvent {
+}
+
+- (void)rightMouseUp:(NSEvent *)theEvent {
+}
+
+- (void)otherMouseUp:(NSEvent *)theEvent {
+}
+
+- (void)mouseMoved:(NSEvent *)theEvent {
+}
+
+- (void)mouseDragged:(NSEvent *)theEvent {
+}
+
+- (void)rightMouseDragged:(NSEvent *)theEvent {
+}
+
+- (void)otherMouseDragged:(NSEvent *)theEvent {
+}
+
+// Specifies that mouse events over this view should be ignored by the
+// render host.
+- (BOOL)nonWebContentView {
+ return YES;
+}
+
+@end
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 9afbc3f..83e41fe 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -2514,6 +2514,10 @@
'browser/ui/cocoa/focus_tracker.mm',
'browser/ui/cocoa/framed_browser_window.h',
'browser/ui/cocoa/framed_browser_window.mm',
+ 'browser/ui/cocoa/fullscreen_exit_bubble_controller.h',
+ 'browser/ui/cocoa/fullscreen_exit_bubble_controller.mm',
+ 'browser/ui/cocoa/fullscreen_exit_bubble_view.h',
+ 'browser/ui/cocoa/fullscreen_exit_bubble_view.mm',
'browser/ui/cocoa/fullscreen_window.h',
'browser/ui/cocoa/fullscreen_window.mm',
'browser/ui/cocoa/global_error_bubble_controller.h',
diff --git a/chrome/chrome_dll.gypi b/chrome/chrome_dll.gypi
index 5dda655..1acacd3 100644
--- a/chrome/chrome_dll.gypi
+++ b/chrome/chrome_dll.gypi
@@ -245,6 +245,7 @@
'app/nibs/FindBar.xib',
'app/nibs/FirstRunBubble.xib',
'app/nibs/FirstRunDialog.xib',
+ 'app/nibs/FullscreenExitBubble.xib',
'app/nibs/GlobalErrorBubble.xib',
'app/nibs/HungRendererDialog.xib',
'app/nibs/HttpAuthLoginSheet.xib',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 823211c..679597c 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1609,6 +1609,7 @@
'browser/ui/cocoa/focus_tracker_unittest.mm',
'browser/ui/cocoa/framed_browser_window_unittest.mm',
'browser/ui/cocoa/fullscreen_window_unittest.mm',
+ 'browser/ui/cocoa/fullscreen_exit_bubble_controller_unittest.mm',
'browser/ui/cocoa/gradient_button_cell_unittest.mm',
'browser/ui/cocoa/history_menu_bridge_unittest.mm',
'browser/ui/cocoa/history_menu_cocoa_controller_unittest.mm',