summaryrefslogtreecommitdiffstats
path: root/o3d
diff options
context:
space:
mode:
authormaf@google.com <maf@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-10 01:15:35 +0000
committermaf@google.com <maf@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-10 01:15:35 +0000
commit59813099e93f2a9165870f42b7eb5ab39304c8bd (patch)
tree9e547f7d1d2635104b389bccfe1b7b811d49161a /o3d
parent461ce4745fc15a6f434699d5a7dcc0591ce952cd (diff)
downloadchromium_src-59813099e93f2a9165870f42b7eb5ab39304c8bd.zip
chromium_src-59813099e93f2a9165870f42b7eb5ab39304c8bd.tar.gz
chromium_src-59813099e93f2a9165870f42b7eb5ab39304c8bd.tar.bz2
Make O3D fullscreen mode support resolution switching on Mac.
First cut - a bit glitchy when leaving fullscreen currently as we get unwanted browser window resizing when the resolution requested is lower than the current window size. Review URL: http://codereview.chromium.org/118471 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@18013 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'o3d')
-rw-r--r--o3d/plugin/build.scons1
-rw-r--r--o3d/plugin/cross/o3d_glue.cc5
-rw-r--r--o3d/plugin/cross/o3d_glue.h1
-rw-r--r--o3d/plugin/mac/main_mac.mm49
-rw-r--r--o3d/plugin/mac/plugin_mac.mm239
5 files changed, 250 insertions, 45 deletions
diff --git a/o3d/plugin/build.scons b/o3d/plugin/build.scons
index 3ff6a97..40c8719 100644
--- a/o3d/plugin/build.scons
+++ b/o3d/plugin/build.scons
@@ -140,6 +140,7 @@ if env.Bit('mac'):
'Breakpad',
'Cocoa',
'IOKit',
+ 'QuickTime',
],
CCFLAGS = ['-F$MAC_BREAKPAD_DIR',
'-F$CG_DIR'],
diff --git a/o3d/plugin/cross/o3d_glue.cc b/o3d/plugin/cross/o3d_glue.cc
index 0a7ddd4..f760e1b 100644
--- a/o3d/plugin/cross/o3d_glue.cc
+++ b/o3d/plugin/cross/o3d_glue.cc
@@ -114,6 +114,7 @@ PluginObject::PluginObject(NPP npp)
painted_once_(false),
#endif
#ifdef OS_MACOSX
+ mac_fullscreen_state_(NULL),
renderer_is_software_(false),
scroll_is_in_progress_(false),
drawing_model_(NPDrawingModelQuickDraw),
@@ -668,6 +669,9 @@ int PluginObject::height() const {
return 0;
}
+
+// On Mac there is a different implementation in plugin_mac.mm.
+#ifndef OS_MACOSX
void PluginObject::GetDisplayModes(std::vector<o3d::DisplayMode> *modes) {
if (renderer()) {
renderer()->GetDisplayModes(modes);
@@ -675,6 +679,7 @@ void PluginObject::GetDisplayModes(std::vector<o3d::DisplayMode> *modes) {
modes->clear();
}
}
+#endif
void PluginObject::RedirectToFile(const char *url) {
char cmd[] = "window.location = 'file:///%s';";
diff --git a/o3d/plugin/cross/o3d_glue.h b/o3d/plugin/cross/o3d_glue.h
index 019488a..ebe2a44 100644
--- a/o3d/plugin/cross/o3d_glue.h
+++ b/o3d/plugin/cross/o3d_glue.h
@@ -218,6 +218,7 @@ 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
diff --git a/o3d/plugin/mac/main_mac.mm b/o3d/plugin/mac/main_mac.mm
index 30f750c..17f1039 100644
--- a/o3d/plugin/mac/main_mac.mm
+++ b/o3d/plugin/mac/main_mac.mm
@@ -93,6 +93,17 @@ void RenderOnDemandCallbackHandler::Run() {
obj_->SetWantsRedraw(true);
}
+static unsigned char GetMacEventKeyChar(const EventRecord *the_event) {
+ unsigned char the_char = the_event->message & charCodeMask;
+ return the_char;
+}
+
+static unsigned char GetMacEventKeyCode(const EventRecord *the_event) {
+ unsigned char the_key_code = (the_event->message & keyCodeMask) >> 8;
+ return the_key_code;
+}
+
+
// Cocoa key events for things like arrow key presses can have strange unicode
// values in the 0xF700-0xF747 range, eg NSUpArrowFunctionKey is 0xF700.
// These values are defined in NSEvent.h.
@@ -201,12 +212,10 @@ static void DispatchKeyboardEvent(PluginObject* obj,
// Javascript.
static void DispatchMacKeyboardEvent(PluginObject* obj,
EventRecord* the_event) {
- unsigned char theKeyCode = (the_event->message & keyCodeMask) >> 8;
-
DispatchKeyboardEvent(obj,
the_event->what,
- the_event->message & charCodeMask,
- theKeyCode,
+ GetMacEventKeyChar(the_event),
+ GetMacEventKeyCode(the_event),
the_event->modifiers);
}
@@ -561,8 +570,7 @@ bool HandleMacEvent(EventRecord* the_event, NPP instance) {
break;
case keyDown:
// Hard-coded trapdoor to get out of fullscreen mode if user hits escape.
- unsigned char theChar = the_event->message & charCodeMask;
- if (theChar == '\e' && fullscreen_window) {
+ if ((GetMacEventKeyChar(the_event) == '\e') && fullscreen_window) {
obj->CancelFullscreenDisplay();
break;
} // otherwise fall through
@@ -840,6 +848,9 @@ extern "C" {
assert(window != NULL);
+ if (window->window == NULL)
+ return NPERR_NO_ERROR;
+
obj->last_plugin_loc_.h = window->x;
obj->last_plugin_loc_.v = window->y;
@@ -857,14 +868,17 @@ extern "C" {
break;
}
case NPDrawingModelCoreGraphics: {
- NP_CGContext* np_cg = reinterpret_cast<NP_CGContext*>(window->window);
- if (obj->event_model_ == NPEventModelCocoa) {
- NSWindow * ns_window = reinterpret_cast<NSWindow*>(np_cg->window);
- new_window = reinterpret_cast<WindowRef>([ns_window windowRef]);
- } else {
- new_window = np_cg->window;
+ // Safari 4 sets window->window to NULL when in Cocoa event mode.
+ if (window->window != NULL) {
+ NP_CGContext* np_cg = reinterpret_cast<NP_CGContext*>(window->window);
+ if (obj->event_model_ == NPEventModelCocoa) {
+ NSWindow * ns_window = reinterpret_cast<NSWindow*>(np_cg->window);
+ new_window = reinterpret_cast<WindowRef>([ns_window windowRef]);
+ } else {
+ new_window = np_cg->window;
+ }
+ obj->mac_2d_context_ = np_cg->context;
}
- obj->mac_2d_context_ = np_cg->context;
break;
}
case NPDrawingModelQuickDraw: {
@@ -1048,8 +1062,13 @@ extern "C" {
obj->last_buffer_rect_[3] = clipHeight;
obj->mac_surface_hidden_ = false;
+ // If in fullscreen, just remember the desired change in geometry so
+ // we restore to the right rectangle.
+ if (obj->GetFullscreenMacWindow() != NULL)
+ return NPERR_NO_ERROR;
+
aglSetInteger(obj->mac_agl_context_, AGL_BUFFER_RECT,
- obj->last_buffer_rect_);
+ obj->last_buffer_rect_);
aglEnable(obj->mac_agl_context_, AGL_BUFFER_RECT);
}
@@ -1082,8 +1101,6 @@ extern "C" {
obj->client()->SetRenderOnDemandCallback(
new RenderOnDemandCallbackHandler(obj));
-
-
obj->renderer()->SetClientOriginOffset(gl_x_origin, gl_y_origin);
obj->Resize(window->width, window->height);
diff --git a/o3d/plugin/mac/plugin_mac.mm b/o3d/plugin/mac/plugin_mac.mm
index f245f3e..94327b4 100644
--- a/o3d/plugin/mac/plugin_mac.mm
+++ b/o3d/plugin/mac/plugin_mac.mm
@@ -34,6 +34,7 @@
#include "plugin_mac.h"
#include <Breakpad/Breakpad.h>
#include <Cocoa/Cocoa.h>
+#include <QuickTime/QuickTime.h>
#include "plugin/cross/o3d_glue.h"
#include "plugin/cross/main.h"
#include "core/mac/display_window_mac.h"
@@ -525,6 +526,14 @@ static void DrawToOverlayWindow(WindowRef overlayWindow) {
}
+static void SetWindowLevel(WindowRef window, int level) {
+ WindowGroupRef wGroup = NULL;
+ WindowGroupAttributes attrs = 0;
+ CreateWindowGroup(attrs, &wGroup);
+ SetWindowGroupLevel(wGroup, level);
+ SetWindowGroup(window, wGroup);
+}
+
static WindowRef CreateOverlayWindow(void) {
Rect bounds = CGRect2Rect(CGDisplayBounds(CGMainDisplayID()));
WindowClass wClass = kOverlayWindowClass;
@@ -539,7 +548,6 @@ static WindowRef CreateOverlayWindow(void) {
kEventClassWindow, kEventWindowShown
};
-
err = CreateNewWindow(wClass,
overlayAttributes,
&bounds,
@@ -547,10 +555,12 @@ static WindowRef CreateOverlayWindow(void) {
if (err)
return NULL;
- ShowWindow(window);
+ SetWindowLevel(window, CGShieldingWindowLevel() + 1);
InstallEventHandler(GetWindowEventTarget(window), HandleOverlayWindow,
sizeof(eventTypes)/sizeof(eventTypes[0]), eventTypes,
NULL, NULL);
+ ShowWindow(window);
+
return window;
}
@@ -717,10 +727,11 @@ static OSStatus HandleFullscreenWindow(EventHandlerCallRef inHandlerCallRef,
}
}
-static WindowRef CreateFullscreenWindow(PluginObject *obj,
+
+static WindowRef CreateFullscreenWindow(WindowRef window,
+ PluginObject *obj,
int mode_id) {
Rect bounds = CGRect2Rect(CGDisplayBounds(CGMainDisplayID()));
- WindowRef window = NULL;
OSStatus err = noErr;
EventTypeSpec eventTypes[] = {
kEventClassKeyboard, kEventRawKeyDown,
@@ -734,13 +745,16 @@ static WindowRef CreateFullscreenWindow(PluginObject *obj,
kEventClassMouse, kEventMouseWheelMoved
};
- err = CreateNewWindow(kSimpleWindowClass,
- kWindowStandardHandlerAttribute,
- &bounds,
- &window);
+ if (window == NULL)
+ err = CreateNewWindow(kSimpleWindowClass,
+ kWindowStandardHandlerAttribute,
+ &bounds,
+ &window);
if (err)
return NULL;
+ SetWindowLevel(window, CGShieldingWindowLevel() + 1);
+
InstallEventHandler(GetWindowEventTarget(window), HandleFullscreenWindow,
sizeof(eventTypes)/sizeof(eventTypes[0]), eventTypes,
obj->npp(), NULL);
@@ -749,28 +763,191 @@ static WindowRef CreateFullscreenWindow(PluginObject *obj,
}
void CleanupFullscreenWindow(PluginObject *obj) {
- if (obj->GetFullscreenMacWindow()) {
- DisposeWindow(obj->GetFullscreenMacWindow());
- obj->SetFullscreenMacWindow(NULL);
+ WindowRef fs_window = obj->GetFullscreenMacWindow();
+ WindowRef fs_o_window = obj->GetFullscreenOverlayMacWindow();
+
+ obj->SetFullscreenMacWindow(NULL);
+ obj->SetFullscreenOverlayMacWindow(NULL);
+
+ if (fs_window) {
+ ReleaseWindowGroup(GetWindowGroup(fs_window));
+ DisposeWindow(fs_window);
+ }
+
+ if(fs_o_window) {
+ ReleaseWindowGroup(GetWindowGroup(fs_o_window));
+ DisposeWindow(fs_o_window);
+ }
+}
+
+#pragma mark ____SCREEN_RESOLUTION_MANAGEMENT
+
+
+// Constant kO3D_MODE_OFFSET is added to the position in the array returned by
+// CGDisplayAvailableModes to make it an ID. This makes IDs distinguishable from
+// array positions when debugging, and also means that ID 0 can have a special
+// meaning (current mode) rather than meaning the first resolution in the list.
+const int kO3D_MODE_OFFSET = 100;
+
+// Extracts data from the Core Graphics screen mode data passed in.
+// Returns false if the mode is an undesirable one, ie if it is not safe for
+// the current screen hardware, is stretched, or is interlaced.
+// Returns various information about the mode in the var parameters passed.
+static bool ExtractDisplayModeData(NSDictionary *mode_dict,
+ int *width,
+ int *height,
+ int *refresh_rate,
+ int *bits_per_pixel) {
+
+ *width = [[mode_dict objectForKey:(id)kCGDisplayWidth] intValue];
+ *height = [[mode_dict objectForKey:(id)kCGDisplayHeight] intValue];
+ *refresh_rate = [[mode_dict objectForKey:(id)kCGDisplayRefreshRate] intValue];
+ *bits_per_pixel =
+ [[mode_dict objectForKey:(id)kCGDisplayBitsPerPixel] intValue];
+
+ if (![mode_dict objectForKey:(id)kCGDisplayModeIsSafeForHardware])
+ return false;
+
+ if ([mode_dict objectForKey:(id)kCGDisplayModeIsStretched])
+ return false;
+
+ if ([mode_dict objectForKey:(id)kCGDisplayModeIsInterlaced])
+ return false;
+
+ return true;
+}
+
+void PluginObject::GetDisplayModes(std::vector<o3d::DisplayMode> *modes) {
+ NSArray* mac_modes = (NSArray*)CGDisplayAvailableModes(CGMainDisplayID());
+ int num_modes = [mac_modes count];
+ std::vector<o3d::DisplayMode> modes_found;
+
+ for (int i = 0; i < num_modes; ++i) {
+ int width = 0;
+ int height = 0;
+ int refresh_rate = 0;
+ int bpp = 0;
+
+ if (ExtractDisplayModeData([mac_modes objectAtIndex:i],
+ &width,
+ &height,
+ &refresh_rate,
+ &bpp) && bpp == 32)
+ modes_found.push_back(o3d::DisplayMode(width, height, refresh_rate,
+ i + kO3D_MODE_OFFSET));
+ }
+
+ modes->swap(modes_found);
+}
+
+
+// Returns information on a display mode, which is mode n - kO3D_MODE_OFFSET
+// in the raw list returned by CGDisplayAvailableModes on the main screen,
+// with kO3D_MODE_OFFSET + 0 being the first entry in the array.
+static bool GetDisplayMode(int id, o3d::DisplayMode *mode) {
+ NSArray *mac_modes = (NSArray*) CGDisplayAvailableModes(CGMainDisplayID());
+ int num_modes = [mac_modes count];
+ int array_offset = id - kO3D_MODE_OFFSET;
+
+ if (array_offset >= 0 && array_offset < num_modes) {
+ int width = 0;
+ int height = 0;
+ int refresh_rate = 0;
+ int bpp = 0;
+
+ ExtractDisplayModeData([mac_modes objectAtIndex:array_offset],
+ &width, &height, &refresh_rate, &bpp);
+ mode->Set(width, height, refresh_rate, id);
+ return true;
}
- if (obj->GetFullscreenOverlayMacWindow()) {
- DisposeWindow(obj->GetFullscreenOverlayMacWindow());
- obj->SetFullscreenOverlayMacWindow(NULL);
+ return false;
+}
+
+static int GetCGDisplayModeID(NSDictionary* mode_dict) {
+ return [[mode_dict valueForKey:@"Mode"] intValue];
+}
+
+// Returns DisplayMode data for the current state of the main display.
+static void GetCurrentDisplayMode(o3d::DisplayMode *mode) {
+ int width = 0;
+ int height = 0;
+ int refresh_rate = 0;
+ int bpp = 0;
+ int mode_id = 0;
+
+ NSDictionary* current_mode =
+ (NSDictionary*)CGDisplayCurrentMode(CGMainDisplayID());
+
+ // To get the O3D mode id of the current mode, we need to find it in the list
+ // of all modes, since the id we use is it's index + kO3D_MODE_OFFSET.
+
+ // Get the CG id of current mode so that we will recognize it.
+ int current_cg_id = GetCGDisplayModeID(current_mode);
+
+ // Get list of all modes.
+ NSArray *modes = (NSArray*)CGDisplayAvailableModes(CGMainDisplayID());
+ int num_modes = [modes count];
+
+ // Find current mode in that list, and compute the O3D id for it.
+ for (int x = 0 ; x < num_modes ; x++) {
+ if (GetCGDisplayModeID([modes objectAtIndex:x]) == current_cg_id) {
+ mode_id = x + kO3D_MODE_OFFSET;
+ break;
+ }
}
+
+ ExtractDisplayModeData(current_mode, &width, &height, &refresh_rate, &bpp);
+ mode->Set(width, height, refresh_rate, mode_id);
}
+#pragma mark ____FULLSCREEN_SWITCHING
+
bool PluginObject::RequestFullscreenDisplay() {
-#ifndef NDEBUG // TODO: Remove after all security is in.
// If already in fullscreen mode, do nothing.
if (GetFullscreenMacWindow())
return false;
- SetSystemUIMode(kUIModeAllSuppressed, kUIOptionAutoShowMenuBar);
- SetFullscreenMacWindow(
- CreateFullscreenWindow(this, fullscreen_region_mode_id_));
+ int target_width = 0;
+ int target_height = 0;
+ if (fullscreen_region_valid_) {
+ o3d::DisplayMode the_mode;
+ if (GetDisplayMode(fullscreen_region_mode_id_, &the_mode)) {
+ target_width = the_mode.width();
+ target_height = the_mode.height();
+ }
+ }
+
+ // check which mode we are in now
+ o3d::DisplayMode current_mode;
+ GetCurrentDisplayMode(&current_mode);
+
+ WindowRef fullscreen_window = NULL;
+
+ // Determine if screen mode switching is actually required.
+ if (target_width != 0 &&
+ target_height != 0 &&
+ target_width != current_mode.width() &&
+ target_height != current_mode.height()) {
+ short short_target_width = target_width;
+ short short_target_height = target_height;
+ BeginFullScreen(&mac_fullscreen_state_,
+ GetMainDevice(),
+ &short_target_width,
+ &short_target_height,
+ &fullscreen_window,
+ NULL,
+ fullScreenCaptureAllDisplays);
+ } else {
+ SetSystemUIMode(kUIModeAllSuppressed, kUIOptionAutoShowMenuBar);
+ mac_fullscreen_state_ = NULL;
+ }
+
+ SetFullscreenMacWindow(CreateFullscreenWindow(NULL,
+ this,
+ fullscreen_region_mode_id_));
Rect bounds = {0,0,0,0};
GetWindowBounds(GetFullscreenMacWindow(), kWindowContentRgn, &bounds);
@@ -779,33 +956,40 @@ bool PluginObject::RequestFullscreenDisplay() {
renderer()->SetClientOriginOffset(0, 0);
renderer_->Resize(bounds.right - bounds.left, bounds.bottom - bounds.top);
+
const double kFadeOutTime = 3.0;
SetFullscreenOverlayMacWindow(CreateOverlayWindow());
+
DrawToOverlayWindow(GetFullscreenOverlayMacWindow());
TransitionWindowOptions options = {0, kFadeOutTime, NULL, NULL};
TransitionWindowWithOptions(GetFullscreenOverlayMacWindow(),
kWindowFadeTransitionEffect,
kWindowHideTransitionAction,
NULL, true, &options);
+
return true;
-#else
- return false;
-#endif
}
void PluginObject::CancelFullscreenDisplay() {
-#ifndef NDEBUG // TODO: Remove after user-prompt feature goes in.
-
// if not in fullscreen mode, do nothing
if (!GetFullscreenMacWindow())
return;
- //fullscreen_ = false;
SetWindowForAGLContext(mac_agl_context_, mac_window_);
+
+ CleanupFullscreenWindow(this);
+
+ renderer_->Resize(prev_width_, prev_height_);
aglSetInteger(mac_agl_context_, AGL_BUFFER_RECT, last_buffer_rect_);
aglEnable(mac_agl_context_, AGL_BUFFER_RECT);
- renderer_->Resize(prev_width_, prev_height_);
- CleanupFullscreenWindow(this);
+
+ if (mac_fullscreen_state_) {
+ EndFullScreen(mac_fullscreen_state_, 0);
+ mac_fullscreen_state_ = NULL;
+ } else {
+ SetSystemUIMode(kUIModeNormal, 0);
+ }
+
// Somehow the browser window does not automatically activate again
// when we close the fullscreen window, so explicitly reactivate it.
@@ -815,8 +999,5 @@ void PluginObject::CancelFullscreenDisplay() {
} else {
SelectWindow(mac_window_);
}
-
- SetSystemUIMode(kUIModeNormal, 0);
-#endif
}