diff options
author | maf@google.com <maf@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-25 22:59:41 +0000 |
---|---|---|
committer | maf@google.com <maf@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-25 22:59:41 +0000 |
commit | 98514f26dd2386c2811a5a568d993e8d75d6c33d (patch) | |
tree | 3722e7140e7073ad0390ef660abe9a9f9993553a /o3d/plugin | |
parent | 6f2fc3d53467400baba7c718ef95b4b86d98412f (diff) | |
download | chromium_src-98514f26dd2386c2811a5a568d993e8d75d6c33d.zip chromium_src-98514f26dd2386c2811a5a568d993e8d75d6c33d.tar.gz chromium_src-98514f26dd2386c2811a5a568d993e8d75d6c33d.tar.bz2 |
New user experience for the fullscreen message on Mac.
It's now a translucent window that slides down into the top right of the screen, hangs around for a while and then slides up up and away.
Review URL: http://codereview.chromium.org/147135
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@19300 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'o3d/plugin')
-rw-r--r-- | o3d/plugin/build.scons | 3 | ||||
-rw-r--r-- | o3d/plugin/cross/o3d_glue.cc | 1 | ||||
-rw-r--r-- | o3d/plugin/cross/o3d_glue.h | 18 | ||||
-rw-r--r-- | o3d/plugin/mac/plugin_mac.mm | 193 |
4 files changed, 153 insertions, 62 deletions
diff --git a/o3d/plugin/build.scons b/o3d/plugin/build.scons index 9bd29dd..aac7f16 100644 --- a/o3d/plugin/build.scons +++ b/o3d/plugin/build.scons @@ -335,8 +335,7 @@ if env.Bit('mac'): env['MAC_INSTALLER_DIR'] = env['SCONSTRUCT_DIR'] + '/../o3d-internal/mac_installer' env['MAC_INSTALLER_PROJECT'] = 'o3d.packproj' - print "Installer is " + env['MAC_INSTALLER_PROJECT'] - # Default is make the installer. + # Default is to make the installer. make_installer = int(ARGUMENTS.get('MAKE_INSTALLER', 1)) and os.path.exists(env['MAC_INSTALLER_DIR'] + '/' + env['MAC_INSTALLER_PROJECT']) diff --git a/o3d/plugin/cross/o3d_glue.cc b/o3d/plugin/cross/o3d_glue.cc index cc21c45..b14cd3b 100644 --- a/o3d/plugin/cross/o3d_glue.cc +++ b/o3d/plugin/cross/o3d_glue.cc @@ -130,6 +130,7 @@ PluginObject::PluginObject(NPP npp) mac_cgl_context_(0), last_mac_event_time_(0), wants_redraw_(false), + time_to_hide_overlay_(0.0), #endif #ifdef OS_LINUX display_(NULL), diff --git a/o3d/plugin/cross/o3d_glue.h b/o3d/plugin/cross/o3d_glue.h index 6c6eacc..625770e 100644 --- a/o3d/plugin/cross/o3d_glue.h +++ b/o3d/plugin/cross/o3d_glue.h @@ -187,7 +187,6 @@ class PluginObject: public NPObject { void set_got_dblclick(bool got_dblclick) { got_dblclick_ = got_dblclick; } #endif #ifdef OS_MACOSX - void SetFullscreenOverlayMacWindow(WindowRef window) { mac_fullscreen_overlay_window_ = window; } @@ -218,12 +217,9 @@ class PluginObject: public NPObject { bool SetRendererIsSoftware(bool state) {renderer_is_software_ = state;} bool renderer_is_software_; - Ptr mac_fullscreen_state_; NPDrawingModel drawing_model_; NPEventModel event_model_; WindowRef mac_window_; // may be NULL in the Chrome case - WindowRef mac_fullscreen_window_; // NULL if not in fullscreen modee - WindowRef mac_fullscreen_overlay_window_; // NULL if not in fullscreen mode // these vars needed for the Safari tab switch detection hack CFDateRef last_mac_event_time_; bool wants_redraw_; @@ -238,7 +234,19 @@ class PluginObject: public NPObject { // either can be NULL depending on drawing_model AGLContext mac_agl_context_; CGLContextObj mac_cgl_context_; -#endif + + // Fullscreen related stuff. + + // FullscreenIdle gets repeatedly called while we are in fullscreen mode. + // Currently its only task is to hide the fullscreen message at the right + // time. + void FullscreenIdle(); + double time_to_hide_overlay_; + WindowRef mac_fullscreen_window_; // NULL if not in fullscreen modee + WindowRef mac_fullscreen_overlay_window_; // NULL if not in fullscreen mode + Ptr mac_fullscreen_state_; + +#endif // OS_MACOSX #ifdef OS_LINUX Display *display_; Window window_; diff --git a/o3d/plugin/mac/plugin_mac.mm b/o3d/plugin/mac/plugin_mac.mm index aa66ca2..7d63a0c 100644 --- a/o3d/plugin/mac/plugin_mac.mm +++ b/o3d/plugin/mac/plugin_mac.mm @@ -44,6 +44,8 @@ BreakpadRef gBreakpadRef = NULL; using glue::_o3d::PluginObject; using o3d::DisplayWindowMac; +static void DrawToOverlayWindow(WindowRef overlayWindow); + // Returns the version number of the running Mac browser, as parsed from // the short version string in the plist of the app's bundle. bool GetBrowserVersionInfo(int *returned_major, @@ -215,12 +217,18 @@ void RenderTimer::TimerCallback(CFRunLoopTimerRef timer, void* info) { ManageSafariTabSwitching(obj); obj->client()->Tick(); + bool in_fullscreen = obj->GetFullscreenMacWindow(); + + if (in_fullscreen) { + obj->FullscreenIdle(); + } + // We're visible if (a) we are in fullscreen mode or (b) our cliprect // height and width are both a sensible size, ie > 1 pixel. // We don't check for 0 as we have to size to 1 x 1 on occasion rather than // 0 x 0 to avoid crashing the Apple software renderer, but do not want to // actually draw to a 1 x 1 pixel area. - bool plugin_visible = obj->GetFullscreenMacWindow() || + bool plugin_visible = in_fullscreen || (obj->last_buffer_rect_[2] > 1 && obj->last_buffer_rect_[3] > 1); if (plugin_visible && obj->WantsRedraw()) { @@ -385,11 +393,6 @@ static void MySetLayoutControl(ATSUTextLayout layout, ATSUSetLayoutControls(layout, 1, tags, sizes, values); } -static OSStatus HandleOverlayWindow(EventHandlerCallRef inHandlerCallRef, - EventRef inEvent, - void *inUserData) { - return noErr; -} static void PaintRoundedCGRect(CGContextRef context, CGRect rect, @@ -426,57 +429,106 @@ static SInt32 GetIntEventParam(EventRef inEvent, EventParamName inName) { #pragma mark ____OVERLAY_WINDOW +static OSStatus HandleOverlayWindow(EventHandlerCallRef inHandlerCallRef, + EventRef inEvent, + void *inUserData) { + OSType event_class = GetEventClass(inEvent); + OSType event_kind = GetEventKind(inEvent); -static void DrawToOverlayWindow(WindowRef overlayWindow) { -#define kTextWindowHeight 40 + if (event_class == kEventClassWindow && + event_kind == kEventWindowPaint) { + WindowRef theWindow = NULL; + GetEventParameter(inEvent, kEventParamDirectObject, + typeWindowRef, NULL, + sizeof(theWindow), NULL, + &theWindow); + if (theWindow) { + CallNextEventHandler(inHandlerCallRef, inEvent); + DrawToOverlayWindow(theWindow); + } + } - CGContextRef overlayContext = NULL; - OSStatus result = noErr; - // TODO this will need to be a localized string - char * display_text = "Press Esc to exit full screen mode."; + return noErr; +} - UniChar* display_text_16 = NULL; - CFStringRef display_text_cfstr = NULL; - int textLength = 0; - QDBeginCGContext(GetWindowPort(overlayWindow), &overlayContext); +// Returns the unicode 16 chars that we need to display as the fullscreen +// message. Should be disposed with free() after use. +static UniChar * GetFullscreenDisplayText(int *returned_length) { + // TODO this will need to be a localized string. + NSString* ns_display_text = @"Press ESC to exit fullscreen."; + int count = [ns_display_text length]; + UniChar* display_text_16 = (UniChar*) calloc(count, sizeof(UniChar)); - display_text_cfstr = CFStringCreateWithCString(kCFAllocatorDefault, - display_text, - kCFStringEncodingUTF8); - textLength = CFStringGetLength(display_text_cfstr); - display_text_16 = (UniChar*)calloc(textLength + 1, sizeof(*display_text_16)); - CFStringGetCharacters(display_text_cfstr, - CFRangeMake(0, textLength), - display_text_16); + [ns_display_text getCharacters:display_text_16]; + *returned_length = count; + return display_text_16; +} -#define kOverlayWindowFontName "Helvetica" +static void DrawToOverlayWindow(WindowRef overlayWindow) { + CGContextRef overlayContext = NULL; + OSStatus result = noErr; CGFloat kWhiteOpaque[] = {1.0, 1.0, 1.0, 1.0}; CGFloat kBlackOpaque[] = {0.0, 0.0, 0.0, 1.0}; CGFloat kGreyNotOpaque[] = {0.5, 0.5, 0.5, 0.5}; + CGFloat kBlackNotOpaque[] = {0.0, 0.0, 0.0, 0.5}; + Rect bounds = {0, 0, 0, 0}; + const char* kOverlayWindowFontName = "Arial"; + const int kPointSize = 22; + const float kShadowRadius = 5.0; + const float kRoundRectRadius = 9.0; + const float kTextLeftMargin = 15.0; + const float kTextBottomMargin = 22.0; - Rect bounds = {0,0,100,100}; + QDBeginCGContext(GetWindowPort(overlayWindow), &overlayContext); GetWindowBounds(overlayWindow, kWindowContentRgn, &bounds); - CGRect cgTotalRect = Rect2CGRect(bounds); + // Make the global rect local. + bounds.right -= bounds.left; + bounds.left = 0; + bounds.bottom -= bounds.top; + bounds.top = 0; + CGRect cgTotalRect = Rect2CGRect(bounds); CGContextSetShouldSmoothFonts(overlayContext, true); CGContextClearRect(overlayContext, cgTotalRect); CGColorSpaceRef myColorSpace = CGColorSpaceCreateDeviceRGB(); - CGColorRef textShadow = CGColorCreate(myColorSpace, kBlackOpaque); - CGColorRef roundRectBackColor = CGColorCreate(myColorSpace, kGreyNotOpaque); + CGColorRef shadow = CGColorCreate(myColorSpace, kBlackNotOpaque); + CGColorRef roundRectBackColor = CGColorCreate(myColorSpace, kBlackNotOpaque); CGSize shadowOffset = {0.0,0.0}; CGContextSetFillColor(overlayContext, kWhiteOpaque); CGContextSetStrokeColor(overlayContext, kWhiteOpaque); - if (strlen(display_text)) { + // Draw the round rect background. + CGContextSaveGState(overlayContext); + CGContextSetFillColorWithColor(overlayContext, roundRectBackColor); + CGRect cg_rounded_area = + CGRectMake(// Offset from left and bottom to give shadow its space. + kShadowRadius, kShadowRadius, + // Increase width and height so rounded corners + // will be clipped out, except at bottom left. + (bounds.right - bounds.left) + 30, + (bounds.bottom - bounds.top) + 30); + // Save state before applying shadow. + CGContextSetShadowWithColor(overlayContext, shadowOffset, + kShadowRadius, shadow); + PaintRoundedCGRect(overlayContext, cg_rounded_area, kRoundRectRadius, true); + // Restore graphics state to remove shadow. + CGContextRestoreGState(overlayContext); + + // Draw the text. + int text_length = 0; + UniChar* display_text = GetFullscreenDisplayText(&text_length); + + if ((text_length > 0) && (display_text != NULL)) { ATSUStyle style; ATSUTextLayout layout; ATSUFontID font; - Fixed pointSize = Long2Fix(36); + Fixed pointSize = Long2Fix(kPointSize); + Boolean is_bold = true; ATSUCreateStyle(&style); ATSUFindFontFromName(kOverlayWindowFontName, strlen(kOverlayWindowFontName), @@ -485,11 +537,13 @@ static void DrawToOverlayWindow(WindowRef overlayWindow) { MySetAttribute(style, kATSUFontTag, sizeof(font), &font); MySetAttribute(style, kATSUSizeTag, sizeof(pointSize), &pointSize); + MySetAttribute(style, kATSUQDBoldfaceTag, sizeof(Boolean), &is_bold); + ATSUCreateTextLayout(&layout); - ATSUSetTextPointerLocation(layout, display_text_16, + ATSUSetTextPointerLocation(layout, display_text, kATSUFromTextBeginning, kATSUToTextEnd, - textLength); + text_length); ATSUSetRunStyle(layout, style, kATSUFromTextBeginning, kATSUToTextEnd); MySetLayoutControl(layout, kATSUCGContextTag, @@ -499,28 +553,19 @@ static void DrawToOverlayWindow(WindowRef overlayWindow) { // other than a series of squares. ATSUSetTransientFontMatching(layout, true); - CGContextSetFillColorWithColor(overlayContext, roundRectBackColor); - CGRect mine = CGRectMake((bounds.right/2.0) - 400.0, - (bounds.bottom/2.0)-30.0, 800.0, 80.0); - PaintRoundedCGRect(overlayContext, mine, 16.0, true); CGContextSetFillColor(overlayContext, kWhiteOpaque); - - CGContextSaveGState(overlayContext); - CGContextSetShadowWithColor(overlayContext, shadowOffset, 4.0, textShadow); ATSUDrawText(layout, kATSUFromTextBeginning, kATSUToTextEnd, - X2Fix((bounds.right/2.0) - 300.0), X2Fix(bounds.bottom/2.0)); - CGContextRestoreGState(overlayContext); - + X2Fix(kShadowRadius + kTextLeftMargin), + X2Fix(kShadowRadius + kTextBottomMargin)); ATSUDisposeStyle(style); ATSUDisposeTextLayout(layout); + free(display_text); } - CGColorRelease(roundRectBackColor); - CGColorRelease (textShadow); + CGColorRelease(shadow); CGColorSpaceRelease (myColorSpace); - CFReleaseIfNotNull(display_text_cfstr); QDEndCGContext(GetWindowPort(overlayWindow), &overlayContext); } @@ -534,8 +579,26 @@ static void SetWindowLevel(WindowRef window, int level) { SetWindowGroup(window, wGroup); } + +static Rect GetOverlayWindowRect(bool visible) { +#define kOverlayHeight 60 +#define kOverlayWidth 340 + Rect screen_bounds = CGRect2Rect(CGDisplayBounds(CGMainDisplayID())); + Rect hidden_window_bounds = {screen_bounds.top - kOverlayHeight, + screen_bounds.right - kOverlayWidth, + screen_bounds.top, + screen_bounds.right}; + Rect visible_window_bounds = {screen_bounds.top, + screen_bounds.right - kOverlayWidth, + screen_bounds.top + kOverlayHeight, + screen_bounds.right}; + + return (visible) ? visible_window_bounds : hidden_window_bounds; +} + + static WindowRef CreateOverlayWindow(void) { - Rect bounds = CGRect2Rect(CGDisplayBounds(CGMainDisplayID())); + Rect window_bounds = GetOverlayWindowRect(false); WindowClass wClass = kOverlayWindowClass; WindowRef window = NULL; OSStatus err = noErr; @@ -544,13 +607,13 @@ static WindowRef CreateOverlayWindow(void) { kWindowNoActivatesAttribute | kWindowStandardHandlerAttribute; EventTypeSpec eventTypes[] = { - kEventClassWindow, kEventWindowDrawContent, + kEventClassWindow, kEventWindowPaint, kEventClassWindow, kEventWindowShown }; err = CreateNewWindow(wClass, overlayAttributes, - &bounds, + &window_bounds, &window); if (err) return NULL; @@ -919,6 +982,8 @@ void PluginObject::GetDisplayModes(std::vector<o3d::DisplayMode> *modes) { #pragma mark ____FULLSCREEN_SWITCHING +#define kTransitionTime 1.0 + bool PluginObject::RequestFullscreenDisplay() { // If already in fullscreen mode, do nothing. if (GetFullscreenMacWindow()) @@ -975,15 +1040,19 @@ bool PluginObject::RequestFullscreenDisplay() { fullscreen_ = true; client()->SendResizeEvent(renderer_->width(), renderer_->height(), true); - const double kFadeOutTime = 3.0; SetFullscreenOverlayMacWindow(CreateOverlayWindow()); - + ShowWindow(GetFullscreenOverlayMacWindow()); DrawToOverlayWindow(GetFullscreenOverlayMacWindow()); - TransitionWindowOptions options = {0, kFadeOutTime, NULL, NULL}; + TransitionWindowOptions options = {0, kTransitionTime, NULL, NULL}; + CGRect shown_rect = Rect2CGRect(GetOverlayWindowRect(true)); + + // Hide the overlay text 4 seconds from now. + time_to_hide_overlay_ = [NSDate timeIntervalSinceReferenceDate] + 4.0; + TransitionWindowWithOptions(GetFullscreenOverlayMacWindow(), - kWindowFadeTransitionEffect, - kWindowHideTransitionAction, - NULL, true, &options); + kWindowSlideTransitionEffect, + kWindowMoveTransitionAction, + &shown_rect, true, &options); return true; } @@ -1021,3 +1090,17 @@ void PluginObject::CancelFullscreenDisplay() { } } +void PluginObject::FullscreenIdle() { + if ((mac_fullscreen_overlay_window_ != NULL) && + (time_to_hide_overlay_ != 0.0) && + (time_to_hide_overlay_ < [NSDate timeIntervalSinceReferenceDate])) { + time_to_hide_overlay_ = 0.0; + TransitionWindowOptions options = {0, kTransitionTime, NULL, NULL}; + CGRect hidden_rect = Rect2CGRect(GetOverlayWindowRect(false)); + TransitionWindowWithOptions(mac_fullscreen_overlay_window_, + kWindowSlideTransitionEffect, + kWindowMoveTransitionAction, + &hidden_rect, true, &options); + } +} + |