summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkbr@google.com <kbr@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-05-19 21:58:47 +0000
committerkbr@google.com <kbr@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-05-19 21:58:47 +0000
commit82fa5dd3894c873f8cf852a7921c5f8dea70477a (patch)
tree10e637e1885c50ae8470f4ecb6b7b5ffdcf9995d
parentb560bed97395fec57d5c91f26433504bcf8c6d90 (diff)
downloadchromium_src-82fa5dd3894c873f8cf852a7921c5f8dea70477a.zip
chromium_src-82fa5dd3894c873f8cf852a7921c5f8dea70477a.tar.gz
chromium_src-82fa5dd3894c873f8cf852a7921c5f8dea70477a.tar.bz2
Refactored full-screen code under FullscreenWindowMac base class and
overlay window code into OverlayWindowMac class. This is an intermediate step toward a Cocoa and CGL implementation. Verified that mouse and key events continue to work in full-screen mode with full-screen sample and a modified render-mode.html in Firefox 3.6.3 on Mac OS X, where O3D continues to use the Quickdraw drawing model. BUG=http://code.google.com/p/o3d/issues/detail?id=221 TEST=none Review URL: http://codereview.chromium.org/2129015 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@47733 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--o3d/plugin/cross/o3d_glue.cc8
-rw-r--r--o3d/plugin/cross/o3d_glue.h45
-rw-r--r--o3d/plugin/mac/fullscreen_window_mac.h82
-rw-r--r--o3d/plugin/mac/fullscreen_window_mac.mm388
-rw-r--r--o3d/plugin/mac/main_mac.mm15
-rw-r--r--o3d/plugin/mac/overlay_window_mac.h62
-rw-r--r--o3d/plugin/mac/overlay_window_mac.mm286
-rw-r--r--o3d/plugin/mac/plugin_mac.h3
-rw-r--r--o3d/plugin/mac/plugin_mac.mm537
-rw-r--r--o3d/plugin/plugin.gyp4
10 files changed, 861 insertions, 569 deletions
diff --git a/o3d/plugin/cross/o3d_glue.cc b/o3d/plugin/cross/o3d_glue.cc
index a2b7ef5..35c0a14 100644
--- a/o3d/plugin/cross/o3d_glue.cc
+++ b/o3d/plugin/cross/o3d_glue.cc
@@ -124,16 +124,11 @@ 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),
event_model_(NPEventModelCarbon),
mac_window_(0),
- mac_fullscreen_window_(0),
-#ifdef O3D_PLUGIN_ENABLE_FULLSCREEN_MSG
- mac_fullscreen_overlay_window_(0),
-#endif
mac_window_selected_tab_(0),
mac_cocoa_window_(0),
mac_surface_hidden_(0),
@@ -143,9 +138,6 @@ PluginObject::PluginObject(NPP npp)
mac_cgl_pbuffer_(0),
last_mac_event_time_(0),
gl_layer_(NULL),
-#ifdef O3D_PLUGIN_ENABLE_FULLSCREEN_MSG
- time_to_hide_overlay_(0.0),
-#endif
#endif // OS_MACOSX
#ifdef OS_LINUX
display_(NULL),
diff --git a/o3d/plugin/cross/o3d_glue.h b/o3d/plugin/cross/o3d_glue.h
index 4448ecd..109b7c7 100644
--- a/o3d/plugin/cross/o3d_glue.h
+++ b/o3d/plugin/cross/o3d_glue.h
@@ -70,6 +70,9 @@
#include "core/cross/texture.h"
#include "plugin/cross/main_thread_task_poster.h"
#include "plugin/cross/np_v8_bridge.h"
+#ifdef OS_MACOSX
+#include "plugin/mac/fullscreen_window_mac.h"
+#endif
#include "client_glue.h"
#include "third_party/nixysa/static_glue/npapi/common.h"
@@ -134,6 +137,9 @@ using o3d::RenderSurface;
using o3d::RenderDepthStencilSurface;
using o3d::ServiceLocator;
using o3d::Texture2D;
+#ifdef OS_MACOSX
+using o3d::FullscreenWindowMac;
+#endif
class NPAPIObject: public NPObject {
NPP npp_;
@@ -233,22 +239,18 @@ class PluginObject: public NPObject {
GdkEvent *configure);
void SetDisplay(Display *display);
#elif defined(OS_MACOSX)
-#ifdef O3D_PLUGIN_ENABLE_FULLSCREEN_MSG
- void SetFullscreenOverlayMacWindow(WindowRef window) {
- mac_fullscreen_overlay_window_ = window;
- }
-
- WindowRef GetFullscreenOverlayMacWindow() {
- return mac_fullscreen_overlay_window_;
+ FullscreenWindowMac* GetFullscreenMacWindow() {
+ return mac_fullscreen_window_.get();
}
-#endif
- void SetFullscreenMacWindow(WindowRef window) {
- mac_fullscreen_window_ = window;
+ // Assumes ownership of the passed pointer. Passing NULL deletes the
+ // last non-NULL value set.
+ void SetFullscreenMacWindow(FullscreenWindowMac* window) {
+ mac_fullscreen_window_.reset(window);
}
- WindowRef GetFullscreenMacWindow() {
- return mac_fullscreen_window_;
+ WindowRef GetMacWindow() {
+ return mac_window_;
}
bool ScrollIsInProgress() { return scroll_is_in_progress_; }
@@ -259,6 +261,10 @@ class PluginObject: public NPObject {
bool SetRendererIsSoftware(bool state);
bool renderer_is_software_;
+ AGLContext GetMacAGLContext() {
+ return mac_agl_context_;
+ }
+
NPDrawingModel drawing_model_;
NPEventModel event_model_;
WindowRef mac_window_; // may be NULL in the Chrome case
@@ -281,19 +287,8 @@ class PluginObject: public NPObject {
CGLPBufferObj mac_cgl_pbuffer_;
// Fullscreen related stuff.
-
-#ifdef O3D_PLUGIN_ENABLE_FULLSCREEN_MSG
- // 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_;
-#endif
- WindowRef mac_fullscreen_window_; // NULL if not in fullscreen modee
-#ifdef O3D_PLUGIN_ENABLE_FULLSCREEN_MSG
- WindowRef mac_fullscreen_overlay_window_; // NULL if not in fullscreen mode
-#endif
- Ptr mac_fullscreen_state_;
+ // NULL if not in fullscreen mode.
+ scoped_ptr<FullscreenWindowMac> mac_fullscreen_window_;
#endif // OS_MACOSX
#ifdef OS_LINUX
diff --git a/o3d/plugin/mac/fullscreen_window_mac.h b/o3d/plugin/mac/fullscreen_window_mac.h
new file mode 100644
index 0000000..693150d
--- /dev/null
+++ b/o3d/plugin/mac/fullscreen_window_mac.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2010, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef O3D_PLUGIN_MAC_FULLSCREEN_WINDOW_MAC_H_
+#define O3D_PLUGIN_MAC_FULLSCREEN_WINDOW_MAC_H_
+
+#include <OpenGL/OpenGL.h>
+
+#include "base/basictypes.h"
+#include "base/scoped_ptr.h"
+
+#include "plugin/mac/overlay_window_mac.h"
+
+// Abstract base class for the full-screen window. Provides the
+// ability to easily choose between Carbon and Cocoa implementations.
+
+namespace glue {
+namespace _o3d {
+class PluginObject;
+} // namespace _o3d
+} // namespace glue
+
+namespace o3d {
+
+class FullscreenWindowMac {
+ public:
+ static FullscreenWindowMac* Create(glue::_o3d::PluginObject* obj,
+ int target_width,
+ int target_height);
+ virtual ~FullscreenWindowMac();
+
+ virtual bool Initialize(int target_width,
+ int target_height);
+ virtual void IdleCallback();
+ virtual bool Shutdown(const GLint* last_buffer_rect);
+
+ virtual CGRect GetWindowBounds() const = 0;
+ virtual bool IsActive() const = 0;
+
+ protected:
+ FullscreenWindowMac() {}
+
+ private:
+#ifdef O3D_PLUGIN_ENABLE_FULLSCREEN_MSG
+ scoped_ptr<OverlayWindowMac> overlay_window_;
+#endif
+
+ DISALLOW_COPY_AND_ASSIGN(FullscreenWindowMac);
+};
+
+} // namespace o3d
+
+#endif // O3D_PLUGIN_MAC_FULLSCREEN_WINDOW_MAC_H_
+
diff --git a/o3d/plugin/mac/fullscreen_window_mac.mm b/o3d/plugin/mac/fullscreen_window_mac.mm
new file mode 100644
index 0000000..6824894
--- /dev/null
+++ b/o3d/plugin/mac/fullscreen_window_mac.mm
@@ -0,0 +1,388 @@
+/*
+ * Copyright 2010, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "fullscreen_window_mac.h"
+
+#include <QuickTime/QuickTime.h>
+
+#import "graphics_utils_mac.h"
+#import "overlay_window_mac.h"
+#import "plugin_mac.h"
+#import "core/cross/display_mode.h"
+#import "plugin/cross/o3d_glue.h"
+#import "plugin/mac/graphics_utils_mac.h"
+
+using glue::_o3d::PluginObject;
+
+namespace o3d {
+
+//----------------------------------------------------------------------
+// Carbon full-screen implementation.
+//
+
+// Convenience function for fetching SInt32 parameters from Carbon EventRefs.
+static SInt32 GetIntEventParam(EventRef inEvent, EventParamName inName) {
+ SInt32 value = 0;
+ return (GetEventParameter(inEvent, inName, typeSInt32, NULL, sizeof(value),
+ NULL, &value) == noErr) ? value : 0;
+}
+
+
+// Maps the MacOS button numbers to the constants used by our
+// event mechanism. Not quite as obvious as you might think, as the Mac
+// thinks the numbering should go left, right, middle and our W3C-influenced
+// system goes left, middle, right.
+// Defaults to left-button if passed a strange value. Pass Cocoa mouse button
+// codes as-is (they start at 0), pass Carbon button codes - 1.
+o3d::Event::Button MacOSMouseButtonNumberToO3DButton(int inButton) {
+
+ switch(inButton) {
+ case 0:
+ return o3d::Event::BUTTON_LEFT;
+ case 1:
+ return o3d::Event::BUTTON_RIGHT;
+ case 2:
+ return o3d::Event::BUTTON_MIDDLE;
+ case 3:
+ return o3d::Event::BUTTON_4;
+ case 4:
+ return o3d::Event::BUTTON_5;
+ }
+
+ return o3d::Event::BUTTON_LEFT;
+}
+
+
+// Handles the CarbonEvents that we get sent for the fullscreen mode window.
+// Most of these can be converted to EventRecord events and handled by the
+// HandleMacEvent() function in main_mac.mm, but some have no equivalent in
+// that space, scroll-wheel events for example, and so must be handled here.
+static OSStatus HandleFullscreenWindow(EventHandlerCallRef inHandlerCallRef,
+ EventRef inEvent,
+ void *inUserData) {
+ OSType event_class = GetEventClass(inEvent);
+ OSType event_kind = GetEventKind(inEvent);
+ NPP instance = (NPP)inUserData;
+ PluginObject* obj = (PluginObject*)(instance->pdata);
+ HIPoint mouse_loc = { 0.0, 0.0 };
+ bool is_scroll_event = event_class == kEventClassMouse &&
+ (event_kind == kEventMouseScroll ||
+ event_kind == kEventMouseWheelMoved);
+
+ // If it's any kind of mouse event, get the global mouse loc.
+ if (event_class == kEventClassMouse) {
+ GetEventParameter(inEvent, kEventParamMouseLocation,
+ typeHIPoint, NULL,
+ sizeof(mouse_loc), NULL,
+ &mouse_loc);
+ }
+
+ // Handle the two kinds of scroll message we understand.
+ if (is_scroll_event) {
+ SInt32 x_scroll = 0;
+ SInt32 y_scroll = 0;
+ EventMouseWheelAxis axis = kEventMouseWheelAxisY;
+
+ switch (event_kind) {
+ // The newer kind of scroll event, as sent when two-finger
+ // dragging on a touchpad.
+ case kEventMouseScroll:
+ x_scroll = GetIntEventParam(inEvent,
+ kEventParamMouseWheelSmoothHorizontalDelta);
+ y_scroll = GetIntEventParam(inEvent,
+ kEventParamMouseWheelSmoothVerticalDelta);
+
+ // only pass x or y value - pass whichever is larger
+ if (x_scroll && y_scroll) {
+ if (abs(x_scroll) > abs(y_scroll))
+ y_scroll = 0;
+ else
+ x_scroll = 0;
+ }
+ break;
+ // The older kind of scroll event, as sent when using the wheel on
+ // a third-party mouse.
+ case kEventMouseWheelMoved:
+ GetEventParameter(inEvent, kEventParamMouseWheelAxis,
+ typeMouseWheelAxis, NULL,
+ sizeof(axis), NULL,
+ &axis);
+
+ if (axis == kEventMouseWheelAxisY) {
+ y_scroll = GetIntEventParam(inEvent,
+ kEventParamMouseWheelDelta);
+ } else {
+ x_scroll = GetIntEventParam(inEvent,
+ kEventParamMouseWheelDelta);
+ }
+ break;
+ }
+
+ // Dispatch the event now that we have all the data.
+ if (x_scroll || y_scroll) {
+ o3d::Event event(o3d::Event::TYPE_WHEEL);
+ event.set_delta(x_scroll, y_scroll);
+ // Global and local locs are the same, in this case,
+ // as we have a fullscreen window at 0,0.
+ event.set_position(mouse_loc.x, mouse_loc.y,
+ mouse_loc.x, mouse_loc.y, true);
+ obj->client()->AddEventToQueue(event);
+ }
+ return noErr;
+ } else if (event_class == kEventClassMouse &&
+ (event_kind == kEventMouseDown || event_kind == kEventMouseUp)) {
+
+ o3d::Event::Type type = (event_kind == kEventMouseDown) ?
+ o3d::Event::TYPE_MOUSEDOWN :
+ o3d::Event::TYPE_MOUSEUP;
+ o3d::Event event(type);
+ event.set_position(mouse_loc.x, mouse_loc.y,
+ mouse_loc.x, mouse_loc.y, true);
+
+ EventMouseButton button = 0;
+ GetEventParameter(inEvent, kEventParamMouseButton,
+ typeMouseButton, NULL,
+ sizeof(button), NULL,
+ &button);
+ // Carbon mouse button numbers start at 1, so subtract 1 here -
+ // Cocoa mouse buttons, by contrast, start at 0).
+ event.set_button(MacOSMouseButtonNumberToO3DButton(button - 1));
+
+ // add the modifiers to the event, if any
+ UInt32 carbonMods = GetIntEventParam(inEvent,
+ kEventParamKeyModifiers);
+ if (carbonMods) {
+ int modifier_state = 0;
+ if (carbonMods & controlKey) {
+ modifier_state |= o3d::Event::MODIFIER_CTRL;
+ }
+ if (carbonMods & shiftKey) {
+ modifier_state |= o3d::Event::MODIFIER_SHIFT;
+ }
+ if (carbonMods & optionKey) {
+ modifier_state |= o3d::Event::MODIFIER_ALT;
+ }
+ if (carbonMods & cmdKey) {
+ modifier_state |= o3d::Event::MODIFIER_META;
+ }
+
+ event.set_modifier_state(modifier_state);
+ }
+
+ obj->client()->AddEventToQueue(event);
+ } else { // not a scroll event or a click
+
+ // All other events are currently handled by being converted to an
+ // old-style EventRecord as passed by the classic NPAPI interface
+ // and dispatched through our common routine.
+ EventRecord eventRecord;
+
+ if (ConvertEventRefToEventRecord(inEvent, &eventRecord)) {
+ HandleMacEvent(&eventRecord, (NPP)inUserData);
+ return noErr;
+ } else {
+ return eventNotHandledErr;
+ }
+ }
+ return noErr;
+}
+
+
+static WindowRef CreateFullscreenWindow(WindowRef window,
+ PluginObject *obj) {
+ Rect bounds = CGRect2Rect(CGDisplayBounds(CGMainDisplayID()));
+ OSStatus err = noErr;
+ EventTypeSpec eventTypes[] = {
+ {kEventClassKeyboard, kEventRawKeyDown},
+ {kEventClassKeyboard, kEventRawKeyRepeat},
+ {kEventClassKeyboard, kEventRawKeyUp},
+ {kEventClassMouse, kEventMouseDown},
+ {kEventClassMouse, kEventMouseUp},
+ {kEventClassMouse, kEventMouseMoved},
+ {kEventClassMouse, kEventMouseDragged},
+ {kEventClassMouse, kEventMouseScroll},
+ {kEventClassMouse, kEventMouseWheelMoved}
+ };
+
+ 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);
+ ShowWindow(window);
+ return window;
+}
+
+class CarbonFullscreenWindowMac : public FullscreenWindowMac {
+ public:
+ CarbonFullscreenWindowMac(PluginObject* obj);
+ virtual ~CarbonFullscreenWindowMac();
+
+ virtual bool Initialize(int target_width, int target_height);
+ virtual bool Shutdown(const GLint* last_buffer_rect);
+ virtual CGRect GetWindowBounds() const;
+ virtual bool IsActive() const;
+
+ private:
+ PluginObject* obj_;
+ WindowRef fullscreen_window_;
+ Ptr fullscreen_state_;
+
+ DISALLOW_COPY_AND_ASSIGN(CarbonFullscreenWindowMac);
+};
+
+CarbonFullscreenWindowMac::CarbonFullscreenWindowMac(PluginObject* obj)
+ : obj_(obj),
+ fullscreen_window_(NULL),
+ fullscreen_state_(NULL) {
+}
+
+CarbonFullscreenWindowMac::~CarbonFullscreenWindowMac() {
+}
+
+bool CarbonFullscreenWindowMac::Initialize(int target_width,
+ int target_height) {
+ // check which mode we are in now
+ o3d::DisplayMode current_mode;
+ GetCurrentDisplayMode(&current_mode);
+
+ WindowRef temp_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(&fullscreen_state_,
+ nil, // Value of nil selects the main screen.
+ &short_target_width,
+ &short_target_height,
+ &temp_window,
+ NULL,
+ fullScreenCaptureAllDisplays);
+ } else {
+ SetSystemUIMode(kUIModeAllSuppressed, kUIOptionAutoShowMenuBar);
+ fullscreen_state_ = NULL;
+ }
+
+ fullscreen_window_ = CreateFullscreenWindow(NULL, obj_);
+ SetWindowForAGLContext(obj_->GetMacAGLContext(), fullscreen_window_);
+ aglDisable(obj_->GetMacAGLContext(), AGL_BUFFER_RECT);
+ // This must be done after all of the above setup in order for the
+ // overlay window to appear on top.
+ FullscreenWindowMac::Initialize(target_width, target_height);
+ return true;
+}
+
+bool CarbonFullscreenWindowMac::Shutdown(const GLint* last_buffer_rect) {
+ FullscreenWindowMac::Shutdown(last_buffer_rect);
+ SetWindowForAGLContext(obj_->GetMacAGLContext(), obj_->GetMacWindow());
+ aglSetInteger(obj_->GetMacAGLContext(), AGL_BUFFER_RECT, last_buffer_rect);
+ aglEnable(obj_->GetMacAGLContext(), AGL_BUFFER_RECT);
+ if (fullscreen_window_) {
+ HideWindow(fullscreen_window_);
+ ReleaseWindowGroup(GetWindowGroup(fullscreen_window_));
+ DisposeWindow(fullscreen_window_);
+ fullscreen_window_ = NULL;
+ }
+ if (fullscreen_state_) {
+ EndFullScreen(fullscreen_state_, 0);
+ fullscreen_state_ = NULL;
+ } else {
+ SetSystemUIMode(kUIModeNormal, 0);
+ }
+ return true;
+}
+
+CGRect CarbonFullscreenWindowMac::GetWindowBounds() const {
+ Rect bounds = {0,0,0,0};
+ ::GetWindowBounds(fullscreen_window_, kWindowContentRgn, &bounds);
+ return Rect2CGRect(bounds);
+}
+
+bool CarbonFullscreenWindowMac::IsActive() const {
+ return fullscreen_window_ == ActiveNonFloatingWindow();
+}
+
+//----------------------------------------------------------------------
+// FullscreenWindowMac implementation.
+//
+
+FullscreenWindowMac* FullscreenWindowMac::Create(
+ glue::_o3d::PluginObject* obj,
+ int target_width,
+ int target_height) {
+ FullscreenWindowMac* window = new CarbonFullscreenWindowMac(obj);
+ if (!window->Initialize(target_width, target_height)) {
+ delete window;
+ return NULL;
+ }
+
+ return window;
+}
+
+FullscreenWindowMac::~FullscreenWindowMac() {
+}
+
+bool FullscreenWindowMac::Initialize(int target_width, int target_height) {
+#ifdef O3D_PLUGIN_ENABLE_FULLSCREEN_MSG
+ overlay_window_.reset(new OverlayWindowMac());
+#endif
+ return true;
+}
+
+void FullscreenWindowMac::IdleCallback() {
+#ifdef O3D_PLUGIN_ENABLE_FULLSCREEN_MSG
+ if (overlay_window_.get()) {
+ overlay_window_->IdleCallback();
+ }
+#endif
+}
+
+bool FullscreenWindowMac::Shutdown(const GLint* last_buffer_rect) {
+#ifdef O3D_PLUGIN_ENABLE_FULLSCREEN_MSG
+ overlay_window_.reset();
+#endif
+ return true;
+}
+
+} // namespace o3d
+
diff --git a/o3d/plugin/mac/main_mac.mm b/o3d/plugin/mac/main_mac.mm
index 617c906..86ae0de 100644
--- a/o3d/plugin/mac/main_mac.mm
+++ b/o3d/plugin/mac/main_mac.mm
@@ -56,6 +56,7 @@
#include "plugin/cross/whitelist.h"
#include "plugin/mac/plugin_mac.h"
#include "plugin/mac/graphics_utils_mac.h"
+#include "plugin/mac/fullscreen_window_mac.h"
#import "plugin/mac/o3d_layer.h"
@@ -69,6 +70,7 @@ using glue::StreamManager;
using o3d::Bitmap;
using o3d::DisplayWindowMac;
using o3d::Event;
+using o3d::FullscreenWindowMac;
using o3d::Renderer;
namespace {
@@ -305,9 +307,8 @@ void HandleMouseEvent(PluginObject* obj,
int x, y;
// now make x and y plugin relative coords
if (obj->GetFullscreenMacWindow()) {
- Rect wBounds;
- GetWindowBounds(obj->GetFullscreenMacWindow(), kWindowGlobalPortRgn,
- &wBounds);
+ Rect wBounds = o3d::CGRect2Rect(
+ obj->GetFullscreenMacWindow()->GetWindowBounds());
x = screen_x - wBounds.left;
y = screen_y - wBounds.top;
in_plugin = true;
@@ -470,7 +471,7 @@ EventModifiers CocoaToEventRecordModifiers(NSUInteger inMods) {
// This API will also be required for a carbon-free 64 bit version for 10.6.
bool HandleCocoaEvent(NPP instance, NPCocoaEvent* the_event) {
PluginObject* obj = static_cast<PluginObject*>(instance->pdata);
- WindowRef fullscreen_window = obj->GetFullscreenMacWindow();
+ FullscreenWindowMac* fullscreen_window = obj->GetFullscreenMacWindow();
bool handled = false;
if (g_logger) g_logger->UpdateLogging();
@@ -552,7 +553,7 @@ bool HandleCocoaEvent(NPP instance, NPCocoaEvent* the_event) {
// because another app has been called to the front.
// TODO: We'll have problems with this when dealing with e.g.
// Japanese text input IME windows.
- if (fullscreen_window && fullscreen_window != ActiveNonFloatingWindow()) {
+ if (fullscreen_window && !fullscreen_window->IsActive()) {
obj->CancelFullscreenDisplay();
}
@@ -846,7 +847,7 @@ NPError PlatformNPPGetValue(NPP instance, NPPVariable variable, void *value) {
bool HandleMacEvent(EventRecord* the_event, NPP instance) {
PluginObject* obj = static_cast<PluginObject*>(instance->pdata);
bool handled = false;
- WindowRef fullscreen_window = obj->GetFullscreenMacWindow();
+ FullscreenWindowMac* fullscreen_window = obj->GetFullscreenMacWindow();
if (g_logger) g_logger->UpdateLogging();
@@ -877,7 +878,7 @@ bool HandleMacEvent(EventRecord* the_event, NPP instance) {
// of the fullscreen window and we need to exit fullscreen mode.
// This can happen because another browser window has come forward, or
// because another app has been called to the front.
- if (fullscreen_window && fullscreen_window != ActiveNonFloatingWindow()) {
+ if (fullscreen_window && !fullscreen_window->IsActive()) {
obj->CancelFullscreenDisplay();
}
diff --git a/o3d/plugin/mac/overlay_window_mac.h b/o3d/plugin/mac/overlay_window_mac.h
new file mode 100644
index 0000000..f848b8b
--- /dev/null
+++ b/o3d/plugin/mac/overlay_window_mac.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2010, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef O3D_PLUGIN_MAC_OVERLAY_WINDOW_MAC_H_
+#define O3D_PLUGIN_MAC_OVERLAY_WINDOW_MAC_H_
+
+#include <Carbon/Carbon.h>
+
+#include "base/basictypes.h"
+
+// Draws the text indicating how to get out of full-screen mode.
+
+namespace o3d {
+
+class OverlayWindowMac {
+ public:
+ OverlayWindowMac();
+ ~OverlayWindowMac();
+
+ // Runs the idle callback for this overlay window, which just
+ // transitions the window on to and off of the screen.
+ void IdleCallback();
+
+ private:
+ WindowRef overlay_window_;
+ double time_to_hide_overlay_;
+
+ DISALLOW_COPY_AND_ASSIGN(OverlayWindowMac);
+};
+
+} // namespace o3d
+
+#endif // O3D_PLUGIN_MAC_OVERLAY_WINDOW_MAC_H_
+
diff --git a/o3d/plugin/mac/overlay_window_mac.mm b/o3d/plugin/mac/overlay_window_mac.mm
new file mode 100644
index 0000000..ea3af06
--- /dev/null
+++ b/o3d/plugin/mac/overlay_window_mac.mm
@@ -0,0 +1,286 @@
+/*
+ * Copyright 2010, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "overlay_window_mac.h"
+
+#import "plugin/mac/graphics_utils_mac.h"
+
+#ifdef O3D_PLUGIN_ENABLE_FULLSCREEN_MSG
+
+#define kTransitionTime 1.0
+
+namespace o3d {
+
+// A little wrapper for ATSUSetAttributes to make calling it with one attribute
+// less annoying.
+static void MySetAttribute(ATSUStyle style,
+ ATSUAttributeTag tag,
+ ByteCount size,
+ ATSUAttributeValuePtr value) {
+
+ ATSUAttributeTag tags[2] = {tag, 0};
+ ByteCount sizes[2] = {size, 0};
+ ATSUAttributeValuePtr values[2] = {value, 0};
+
+ ATSUSetAttributes(style, 1, tags, sizes, values);
+}
+
+// A little wrapper for ATSUSetLayoutControls to make calling it with one
+// attribute less annoying.
+static void MySetLayoutControl(ATSUTextLayout layout,
+ ATSUAttributeTag tag,
+ ByteCount size,
+ ATSUAttributeValuePtr value) {
+
+ ATSUAttributeTag tags[2] = {tag, 0};
+ ByteCount sizes[2] = {size, 0};
+ ATSUAttributeValuePtr values[2] = {value, 0};
+
+ ATSUSetLayoutControls(layout, 1, tags, sizes, values);
+}
+
+// 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));
+
+ [ns_display_text getCharacters:display_text_16];
+ *returned_length = count;
+ return display_text_16;
+}
+
+
+static void DrawToOverlayWindow(WindowRef overlayWindow) {
+ CGContextRef overlayContext = NULL;
+ CGFloat kWhiteOpaque[] = {1.0, 1.0, 1.0, 1.0};
+ 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;
+
+ QDBeginCGContext(GetWindowPort(overlayWindow), &overlayContext);
+ GetWindowBounds(overlayWindow, kWindowContentRgn, &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 shadow = CGColorCreate(myColorSpace, kBlackNotOpaque);
+ CGColorRef roundRectBackColor = CGColorCreate(myColorSpace, kBlackNotOpaque);
+ CGSize shadowOffset = {0.0,0.0};
+
+ CGContextSetFillColor(overlayContext, kWhiteOpaque);
+ CGContextSetStrokeColor(overlayContext, kWhiteOpaque);
+
+ // 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(kPointSize);
+ Boolean is_bold = true;
+
+ ATSUCreateStyle(&style);
+ ATSUFindFontFromName(kOverlayWindowFontName, strlen(kOverlayWindowFontName),
+ kFontFullName, kFontNoPlatformCode, kFontNoScriptCode,
+ kFontNoLanguageCode, &font);
+
+ 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,
+ kATSUFromTextBeginning, kATSUToTextEnd,
+ text_length);
+ ATSUSetRunStyle(layout, style, kATSUFromTextBeginning, kATSUToTextEnd);
+
+ MySetLayoutControl(layout, kATSUCGContextTag,
+ sizeof(CGContextRef), &overlayContext);
+
+ // Need to enable this for languages like Japanese to draw as something
+ // other than a series of squares.
+ ATSUSetTransientFontMatching(layout, true);
+
+
+ CGContextSetFillColor(overlayContext, kWhiteOpaque);
+ ATSUDrawText(layout, kATSUFromTextBeginning, kATSUToTextEnd,
+ X2Fix(kShadowRadius + kTextLeftMargin),
+ X2Fix(kShadowRadius + kTextBottomMargin));
+ ATSUDisposeStyle(style);
+ ATSUDisposeTextLayout(layout);
+ free(display_text);
+ }
+
+ CGColorRelease(roundRectBackColor);
+ CGColorRelease(shadow);
+ CGColorSpaceRelease (myColorSpace);
+
+ QDEndCGContext(GetWindowPort(overlayWindow), &overlayContext);
+}
+
+static OSStatus HandleOverlayWindow(EventHandlerCallRef inHandlerCallRef,
+ EventRef inEvent,
+ void *inUserData) {
+ OSType event_class = GetEventClass(inEvent);
+ OSType event_kind = GetEventKind(inEvent);
+
+ 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);
+ }
+ }
+
+ return noErr;
+}
+
+
+
+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 window_bounds = GetOverlayWindowRect(false);
+ WindowClass wClass = kOverlayWindowClass;
+ WindowRef window = NULL;
+ OSStatus err = noErr;
+ WindowAttributes overlayAttributes = kWindowNoShadowAttribute |
+ kWindowIgnoreClicksAttribute |
+ kWindowNoActivatesAttribute |
+ kWindowStandardHandlerAttribute;
+ EventTypeSpec eventTypes[] = {
+ {kEventClassWindow, kEventWindowPaint},
+ {kEventClassWindow, kEventWindowShown}
+ };
+
+ err = CreateNewWindow(wClass,
+ overlayAttributes,
+ &window_bounds,
+ &window);
+ if (err)
+ return NULL;
+
+ SetWindowLevel(window, CGShieldingWindowLevel() + 1);
+ InstallEventHandler(GetWindowEventTarget(window), HandleOverlayWindow,
+ sizeof(eventTypes)/sizeof(eventTypes[0]), eventTypes,
+ NULL, NULL);
+ return window;
+}
+
+OverlayWindowMac::OverlayWindowMac()
+ : overlay_window_(NULL),
+ time_to_hide_overlay_(0.0) {
+ overlay_window_ = CreateOverlayWindow();
+ ShowWindow(overlay_window_);
+ o3d::SlideWindowToRect(overlay_window_,
+ Rect2CGRect(GetOverlayWindowRect(true)),
+ kTransitionTime);
+
+ // Hide the overlay text 4 seconds from now.
+ time_to_hide_overlay_ = [NSDate timeIntervalSinceReferenceDate] + 4.0;
+}
+
+OverlayWindowMac::~OverlayWindowMac() {
+ HideWindow(overlay_window_);
+ ReleaseWindowGroup(GetWindowGroup(overlay_window_));
+ DisposeWindow(overlay_window_);
+}
+
+void OverlayWindowMac::IdleCallback() {
+ if ((overlay_window_ != NULL) &&
+ (time_to_hide_overlay_ != 0.0) &&
+ (time_to_hide_overlay_ < [NSDate timeIntervalSinceReferenceDate])) {
+ time_to_hide_overlay_ = 0.0;
+ SlideWindowToRect(overlay_window_,
+ Rect2CGRect(GetOverlayWindowRect(false)),
+ kTransitionTime);
+ }
+}
+
+} // namespace o3d
+
+#endif // O3D_PLUGIN_ENABLE_FULLSCREEN_MSG
diff --git a/o3d/plugin/mac/plugin_mac.h b/o3d/plugin/mac/plugin_mac.h
index 7f3faa0..ebf9c3a 100644
--- a/o3d/plugin/mac/plugin_mac.h
+++ b/o3d/plugin/mac/plugin_mac.h
@@ -43,6 +43,8 @@
namespace o3d {
+class DisplayMode;
+
// RenderTimer maintains an animation timer (nominally running at 60fps)
//
// Keeps track of the current NPP instances running in the browser and then
@@ -83,6 +85,7 @@ void ReleaseSafariBrowserWindow(void* browserWindow);
// Some miscellaneous helper functions...
+void GetCurrentDisplayMode(DisplayMode *mode);
void CFReleaseIfNotNull(CFTypeRef cf);
diff --git a/o3d/plugin/mac/plugin_mac.mm b/o3d/plugin/mac/plugin_mac.mm
index 4ab3127..057d43d 100644
--- a/o3d/plugin/mac/plugin_mac.mm
+++ b/o3d/plugin/mac/plugin_mac.mm
@@ -252,11 +252,9 @@ void RenderTimer::TimerCallback(CFRunLoopTimerRef timer, void* info) {
bool in_fullscreen = obj->GetFullscreenMacWindow();
-#ifdef O3D_PLUGIN_ENABLE_FULLSCREEN_MSG
if (in_fullscreen) {
- obj->FullscreenIdle();
+ obj->GetFullscreenMacWindow()->IdleCallback();
}
-#endif
// We're visible if (a) we are in fullscreen mode, (b) our cliprect
// height and width are both a sensible size, ie > 1 pixel, or (c) if
@@ -370,458 +368,6 @@ char* CreatePosixFilePathFromHFSFilePath(const char* hfsPath) {
-// Convenience function for fetching SInt32 parameters from Carbon EventRefs.
-static SInt32 GetIntEventParam(EventRef inEvent, EventParamName inName) {
- SInt32 value = 0;
- return (GetEventParameter(inEvent, inName, typeSInt32, NULL, sizeof(value),
- NULL, &value) == noErr) ? value : 0;
-}
-
-
-#pragma mark ____OVERLAY_WINDOW
-
-#ifdef O3D_PLUGIN_ENABLE_FULLSCREEN_MSG
-
-// A little wrapper for ATSUSetAttributes to make calling it with one attribute
-// less annoying.
-static void MySetAttribute(ATSUStyle style,
- ATSUAttributeTag tag,
- ByteCount size,
- ATSUAttributeValuePtr value) {
-
- ATSUAttributeTag tags[2] = {tag, 0};
- ByteCount sizes[2] = {size, 0};
- ATSUAttributeValuePtr values[2] = {value, 0};
-
- ATSUSetAttributes(style, 1, tags, sizes, values);
-}
-
-// A little wrapper for ATSUSetLayoutControls to make calling it with one
-// attribute less annoying.
-static void MySetLayoutControl(ATSUTextLayout layout,
- ATSUAttributeTag tag,
- ByteCount size,
- ATSUAttributeValuePtr value) {
-
- ATSUAttributeTag tags[2] = {tag, 0};
- ByteCount sizes[2] = {size, 0};
- ATSUAttributeValuePtr values[2] = {value, 0};
-
- ATSUSetLayoutControls(layout, 1, tags, sizes, values);
-}
-
-// 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));
-
- [ns_display_text getCharacters:display_text_16];
- *returned_length = count;
- return display_text_16;
-}
-
-
-static void DrawToOverlayWindow(WindowRef overlayWindow) {
- CGContextRef overlayContext = NULL;
- CGFloat kWhiteOpaque[] = {1.0, 1.0, 1.0, 1.0};
- 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;
-
- QDBeginCGContext(GetWindowPort(overlayWindow), &overlayContext);
- GetWindowBounds(overlayWindow, kWindowContentRgn, &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 shadow = CGColorCreate(myColorSpace, kBlackNotOpaque);
- CGColorRef roundRectBackColor = CGColorCreate(myColorSpace, kBlackNotOpaque);
- CGSize shadowOffset = {0.0,0.0};
-
- CGContextSetFillColor(overlayContext, kWhiteOpaque);
- CGContextSetStrokeColor(overlayContext, kWhiteOpaque);
-
- // 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(kPointSize);
- Boolean is_bold = true;
-
- ATSUCreateStyle(&style);
- ATSUFindFontFromName(kOverlayWindowFontName, strlen(kOverlayWindowFontName),
- kFontFullName, kFontNoPlatformCode, kFontNoScriptCode,
- kFontNoLanguageCode, &font);
-
- 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,
- kATSUFromTextBeginning, kATSUToTextEnd,
- text_length);
- ATSUSetRunStyle(layout, style, kATSUFromTextBeginning, kATSUToTextEnd);
-
- MySetLayoutControl(layout, kATSUCGContextTag,
- sizeof(CGContextRef), &overlayContext);
-
- // Need to enable this for languages like Japanese to draw as something
- // other than a series of squares.
- ATSUSetTransientFontMatching(layout, true);
-
-
- CGContextSetFillColor(overlayContext, kWhiteOpaque);
- ATSUDrawText(layout, kATSUFromTextBeginning, kATSUToTextEnd,
- X2Fix(kShadowRadius + kTextLeftMargin),
- X2Fix(kShadowRadius + kTextBottomMargin));
- ATSUDisposeStyle(style);
- ATSUDisposeTextLayout(layout);
- free(display_text);
- }
-
- CGColorRelease(roundRectBackColor);
- CGColorRelease(shadow);
- CGColorSpaceRelease (myColorSpace);
-
- QDEndCGContext(GetWindowPort(overlayWindow), &overlayContext);
-}
-
-static OSStatus HandleOverlayWindow(EventHandlerCallRef inHandlerCallRef,
- EventRef inEvent,
- void *inUserData) {
- OSType event_class = GetEventClass(inEvent);
- OSType event_kind = GetEventKind(inEvent);
-
- 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);
- }
- }
-
- return noErr;
-}
-
-
-
-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 window_bounds = GetOverlayWindowRect(false);
- WindowClass wClass = kOverlayWindowClass;
- WindowRef window = NULL;
- OSStatus err = noErr;
- WindowAttributes overlayAttributes = kWindowNoShadowAttribute |
- kWindowIgnoreClicksAttribute |
- kWindowNoActivatesAttribute |
- kWindowStandardHandlerAttribute;
- EventTypeSpec eventTypes[] = {
- {kEventClassWindow, kEventWindowPaint},
- {kEventClassWindow, kEventWindowShown}
- };
-
- err = CreateNewWindow(wClass,
- overlayAttributes,
- &window_bounds,
- &window);
- if (err)
- return NULL;
-
- SetWindowLevel(window, CGShieldingWindowLevel() + 1);
- InstallEventHandler(GetWindowEventTarget(window), HandleOverlayWindow,
- sizeof(eventTypes)/sizeof(eventTypes[0]), eventTypes,
- NULL, NULL);
- ShowWindow(window);
-
- return window;
-}
-
-#endif // O3D_PLUGIN_ENABLE_FULLSCREEN_MSG
-
-
-// Maps the MacOS button numbers to the constants used by our
-// event mechanism. Not quite as obvious as you might think, as the Mac
-// thinks the numbering should go left, right, middle and our W3C-influenced
-// system goes left, middle, right.
-// Defaults to left-button if passed a strange value. Pass Cocoa mouse button
-// codes as-is (they start at 0), pass Carbon button codes - 1.
-o3d::Event::Button MacOSMouseButtonNumberToO3DButton(int inButton) {
-
- switch(inButton) {
- case 0:
- return o3d::Event::BUTTON_LEFT;
- case 1:
- return o3d::Event::BUTTON_RIGHT;
- case 2:
- return o3d::Event::BUTTON_MIDDLE;
- case 3:
- return o3d::Event::BUTTON_4;
- case 4:
- return o3d::Event::BUTTON_5;
- }
-
- return o3d::Event::BUTTON_LEFT;
-}
-
-
-#pragma mark ____FULLSCREEN_WINDOW
-
-
-// Handles the CarbonEvents that we get sent for the fullscreen mode window.
-// Most of these can be converted to EventRecord events and handled by the
-// HandleMacEvent() function in main_mac.mm, but some have no equivalent in
-// that space, scroll-wheel events for example, and so must be handled here.
-static OSStatus HandleFullscreenWindow(EventHandlerCallRef inHandlerCallRef,
- EventRef inEvent,
- void *inUserData) {
- OSType event_class = GetEventClass(inEvent);
- OSType event_kind = GetEventKind(inEvent);
- NPP instance = (NPP)inUserData;
- PluginObject* obj = (PluginObject*)(instance->pdata);
- HIPoint mouse_loc = { 0.0, 0.0 };
- bool is_scroll_event = event_class == kEventClassMouse &&
- (event_kind == kEventMouseScroll ||
- event_kind == kEventMouseWheelMoved);
-
- // If it's any kind of mouse event, get the global mouse loc.
- if (event_class == kEventClassMouse) {
- GetEventParameter(inEvent, kEventParamMouseLocation,
- typeHIPoint, NULL,
- sizeof(mouse_loc), NULL,
- &mouse_loc);
- }
-
- // Handle the two kinds of scroll message we understand.
- if (is_scroll_event) {
- SInt32 x_scroll = 0;
- SInt32 y_scroll = 0;
- EventMouseWheelAxis axis = kEventMouseWheelAxisY;
-
- switch (event_kind) {
- // The newer kind of scroll event, as sent when two-finger
- // dragging on a touchpad.
- case kEventMouseScroll:
- x_scroll = GetIntEventParam(inEvent,
- kEventParamMouseWheelSmoothHorizontalDelta);
- y_scroll = GetIntEventParam(inEvent,
- kEventParamMouseWheelSmoothVerticalDelta);
-
- // only pass x or y value - pass whichever is larger
- if (x_scroll && y_scroll) {
- if (abs(x_scroll) > abs(y_scroll))
- y_scroll = 0;
- else
- x_scroll = 0;
- }
- break;
- // The older kind of scroll event, as sent when using the wheel on
- // a third-party mouse.
- case kEventMouseWheelMoved:
- GetEventParameter(inEvent, kEventParamMouseWheelAxis,
- typeMouseWheelAxis, NULL,
- sizeof(axis), NULL,
- &axis);
-
- if (axis == kEventMouseWheelAxisY) {
- y_scroll = GetIntEventParam(inEvent,
- kEventParamMouseWheelDelta);
- } else {
- x_scroll = GetIntEventParam(inEvent,
- kEventParamMouseWheelDelta);
- }
- break;
- }
-
- // Dispatch the event now that we have all the data.
- if (x_scroll || y_scroll) {
- o3d::Event event(o3d::Event::TYPE_WHEEL);
- event.set_delta(x_scroll, y_scroll);
- // Global and local locs are the same, in this case,
- // as we have a fullscreen window at 0,0.
- event.set_position(mouse_loc.x, mouse_loc.y,
- mouse_loc.x, mouse_loc.y, true);
- obj->client()->AddEventToQueue(event);
- }
- return noErr;
- } else if (event_class == kEventClassMouse &&
- (event_kind == kEventMouseDown || event_kind == kEventMouseUp)) {
-
- o3d::Event::Type type = (event_kind == kEventMouseDown) ?
- o3d::Event::TYPE_MOUSEDOWN :
- o3d::Event::TYPE_MOUSEUP;
- o3d::Event event(type);
- event.set_position(mouse_loc.x, mouse_loc.y,
- mouse_loc.x, mouse_loc.y, true);
-
- EventMouseButton button = 0;
- GetEventParameter(inEvent, kEventParamMouseButton,
- typeMouseButton, NULL,
- sizeof(button), NULL,
- &button);
- // Carbon mouse button numbers start at 1, so subtract 1 here -
- // Cocoa mouse buttons, by contrast, start at 0).
- event.set_button(MacOSMouseButtonNumberToO3DButton(button - 1));
-
- // add the modifiers to the event, if any
- UInt32 carbonMods = GetIntEventParam(inEvent,
- kEventParamKeyModifiers);
- if (carbonMods) {
- int modifier_state = 0;
- if (carbonMods & controlKey) {
- modifier_state |= o3d::Event::MODIFIER_CTRL;
- }
- if (carbonMods & shiftKey) {
- modifier_state |= o3d::Event::MODIFIER_SHIFT;
- }
- if (carbonMods & optionKey) {
- modifier_state |= o3d::Event::MODIFIER_ALT;
- }
- if (carbonMods & cmdKey) {
- modifier_state |= o3d::Event::MODIFIER_META;
- }
-
- event.set_modifier_state(modifier_state);
- }
-
- obj->client()->AddEventToQueue(event);
- } else { // not a scroll event or a click
-
- // All other events are currently handled by being converted to an
- // old-style EventRecord as passed by the classic NPAPI interface
- // and dispatched through our common routine.
- EventRecord eventRecord;
-
- if (ConvertEventRefToEventRecord(inEvent, &eventRecord)) {
- HandleMacEvent(&eventRecord, (NPP)inUserData);
- return noErr;
- } else {
- return eventNotHandledErr;
- }
- }
- return noErr;
-}
-
-
-static WindowRef CreateFullscreenWindow(WindowRef window,
- PluginObject *obj,
- int mode_id) {
- Rect bounds = CGRect2Rect(CGDisplayBounds(CGMainDisplayID()));
- OSStatus err = noErr;
- EventTypeSpec eventTypes[] = {
- {kEventClassKeyboard, kEventRawKeyDown},
- {kEventClassKeyboard, kEventRawKeyRepeat},
- {kEventClassKeyboard, kEventRawKeyUp},
- {kEventClassMouse, kEventMouseDown},
- {kEventClassMouse, kEventMouseUp},
- {kEventClassMouse, kEventMouseMoved},
- {kEventClassMouse, kEventMouseDragged},
- {kEventClassMouse, kEventMouseScroll},
- {kEventClassMouse, kEventMouseWheelMoved}
- };
-
- 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);
- ShowWindow(window);
- return window;
-}
-
-void CleanupFullscreenWindow(PluginObject *obj) {
- WindowRef fs_window = obj->GetFullscreenMacWindow();
-#ifdef O3D_PLUGIN_ENABLE_FULLSCREEN_MSG
- WindowRef fs_o_window = obj->GetFullscreenOverlayMacWindow();
-#endif
-
- obj->SetFullscreenMacWindow(NULL);
-#ifdef O3D_PLUGIN_ENABLE_FULLSCREEN_MSG
- obj->SetFullscreenOverlayMacWindow(NULL);
-#endif
-
- if (fs_window) {
- HideWindow(fs_window);
- ReleaseWindowGroup(GetWindowGroup(fs_window));
- DisposeWindow(fs_window);
- }
-
-#ifdef O3D_PLUGIN_ENABLE_FULLSCREEN_MSG
- if(fs_o_window) {
- HideWindow(fs_o_window);
- ReleaseWindowGroup(GetWindowGroup(fs_o_window));
- DisposeWindow(fs_o_window);
- }
-#endif
-}
-
#pragma mark ____SCREEN_RESOLUTION_MANAGEMENT
@@ -889,7 +435,7 @@ static int GetCGDisplayModeID(NSDictionary* mode_dict) {
}
// Returns DisplayMode data for the current state of the main display.
-static void GetCurrentDisplayMode(o3d::DisplayMode *mode) {
+void GetCurrentDisplayMode(o3d::DisplayMode *mode) {
int width = 0;
int height = 0;
int refresh_rate = 0;
@@ -962,8 +508,6 @@ void PluginObject::GetDisplayModes(std::vector<o3d::DisplayMode> *modes) {
#pragma mark ____FULLSCREEN_SWITCHING
-#define kTransitionTime 1.0
-
namespace glue {
namespace _o3d {
@@ -984,57 +528,17 @@ bool PluginObject::RequestFullscreenDisplay() {
}
}
- // 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_,
- nil, // Value of nil selects the main screen.
- &short_target_width,
- &short_target_height,
- &fullscreen_window,
- NULL,
- fullScreenCaptureAllDisplays);
- } else {
- SetSystemUIMode(kUIModeAllSuppressed, kUIOptionAutoShowMenuBar);
- mac_fullscreen_state_ = NULL;
- }
-
- SetFullscreenMacWindow(o3d::CreateFullscreenWindow(
- NULL,
- this,
- fullscreen_region_mode_id_));
- Rect bounds = {0,0,0,0};
- GetWindowBounds(GetFullscreenMacWindow(), kWindowContentRgn, &bounds);
+ FullscreenWindowMac* fullscreen_window =
+ FullscreenWindowMac::Create(this, target_width, target_height);
+ SetFullscreenMacWindow(fullscreen_window);
+ Rect bounds = o3d::CGRect2Rect(fullscreen_window->GetWindowBounds());
- o3d::SetWindowForAGLContext(mac_agl_context_, GetFullscreenMacWindow());
- aglDisable(mac_agl_context_, AGL_BUFFER_RECT);
renderer()->SetClientOriginOffset(0, 0);
renderer_->Resize(bounds.right - bounds.left, bounds.bottom - bounds.top);
fullscreen_ = true;
client()->SendResizeEvent(renderer_->width(), renderer_->height(), true);
-#ifdef O3D_PLUGIN_ENABLE_FULLSCREEN_MSG
- SetFullscreenOverlayMacWindow(o3d::CreateOverlayWindow());
- ShowWindow(mac_fullscreen_overlay_window_);
- o3d::SlideWindowToRect(mac_fullscreen_overlay_window_,
- o3d::Rect2CGRect(o3d::GetOverlayWindowRect(true)),
- kTransitionTime);
-
- // Hide the overlay text 4 seconds from now.
- time_to_hide_overlay_ = [NSDate timeIntervalSinceReferenceDate] + 4.0;
-#endif
-
return true;
}
@@ -1043,24 +547,12 @@ void PluginObject::CancelFullscreenDisplay() {
if (!GetFullscreenMacWindow())
return;
- o3d::SetWindowForAGLContext(mac_agl_context_, mac_window_);
-
- o3d::CleanupFullscreenWindow(this);
-
+ GetFullscreenMacWindow()->Shutdown(last_buffer_rect_);
+ SetFullscreenMacWindow(NULL);
renderer_->Resize(prev_width_, prev_height_);
- aglSetInteger(mac_agl_context_, AGL_BUFFER_RECT, last_buffer_rect_);
- aglEnable(mac_agl_context_, AGL_BUFFER_RECT);
-
- if (mac_fullscreen_state_) {
- EndFullScreen(mac_fullscreen_state_, 0);
- mac_fullscreen_state_ = NULL;
- } else {
- SetSystemUIMode(kUIModeNormal, 0);
- }
fullscreen_ = false;
client()->SendResizeEvent(prev_width_, prev_height_, false);
-
// Somehow the browser window does not automatically activate again
// when we close the fullscreen window, so explicitly reactivate it.
if (mac_cocoa_window_) {
@@ -1071,18 +563,5 @@ void PluginObject::CancelFullscreenDisplay() {
}
}
-#ifdef O3D_PLUGIN_ENABLE_FULLSCREEN_MSG
-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;
- o3d::SlideWindowToRect(mac_fullscreen_overlay_window_,
- o3d::Rect2CGRect(o3d::GetOverlayWindowRect(false)),
- kTransitionTime);
- }
-}
-#endif
-
} // namespace glue
} // namespace o3d
diff --git a/o3d/plugin/plugin.gyp b/o3d/plugin/plugin.gyp
index bfab2b0..e7092e7 100644
--- a/o3d/plugin/plugin.gyp
+++ b/o3d/plugin/plugin.gyp
@@ -161,8 +161,12 @@
],
'sources': [
'mac/config_mac.mm',
+ 'mac/fullscreen_window_mac.h',
+ 'mac/fullscreen_window_mac.mm',
'mac/o3d_layer.mm',
'mac/o3d_plugin.r',
+ 'mac/overlay_window_mac.h',
+ 'mac/overlay_window_mac.mm',
'mac/plugin_logging-mac.mm',
'mac/plugin_mac.h',
'mac/plugin_mac.mm',