From c44f6f7efbe46eb57c28c1227c43332adf8b3eff Mon Sep 17 00:00:00 2001 From: Marshall Greenblatt Date: Fri, 30 Jan 2015 18:07:13 +0000 Subject: [PATCH] cefclient: Mac: Introduce RootWindow concept and associated window/client object hierarchy (issue #1500). git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@2006 5089003a-bbd8-11dd-ad1f-f1f9622dbc98 --- cef_paths2.gypi | 47 +- tests/cefclient/browser_window.h | 2 +- tests/cefclient/browser_window_osr_gtk.cc | 4 +- tests/cefclient/browser_window_osr_gtk.h | 2 +- tests/cefclient/browser_window_osr_mac.h | 94 ++ ...idget_mac.mm => browser_window_osr_mac.mm} | 902 ++++++++++-------- tests/cefclient/browser_window_osr_win.cc | 4 +- tests/cefclient/browser_window_osr_win.h | 2 +- tests/cefclient/browser_window_std_gtk.cc | 8 +- tests/cefclient/browser_window_std_gtk.h | 2 +- tests/cefclient/browser_window_std_mac.h | 44 + tests/cefclient/browser_window_std_mac.mm | 94 ++ tests/cefclient/browser_window_std_win.cc | 8 +- tests/cefclient/browser_window_std_win.h | 2 +- tests/cefclient/cefclient_mac.mm | 401 +------- tests/cefclient/client_handler_shared.cc | 188 ---- tests/cefclient/client_handler_shared.h | 113 --- tests/cefclient/client_handler_shared_gtk.cc | 105 -- tests/cefclient/client_handler_shared_mac.mm | 53 - tests/cefclient/client_types.h | 12 + tests/cefclient/main_context.h | 4 - tests/cefclient/main_context_impl.cc | 6 - tests/cefclient/main_context_impl.h | 7 - tests/cefclient/osr_renderer.cc | 2 + tests/cefclient/osr_widget_mac.h | 151 --- tests/cefclient/root_window.cc | 18 + tests/cefclient/root_window.h | 10 + tests/cefclient/root_window_gtk.cc | 6 +- tests/cefclient/root_window_mac.h | 99 ++ tests/cefclient/root_window_mac.mm | 617 ++++++++++++ tests/cefclient/root_window_manager.h | 4 + tests/cefclient/root_window_win.cc | 6 +- tests/cefclient/temp_window_mac.h | 33 + tests/cefclient/temp_window_mac.mm | 46 + tests/cefclient/temp_window_win.h | 2 +- tests/cefclient/temp_window_x11.h | 2 +- 36 files changed, 1676 insertions(+), 1424 deletions(-) create mode 100644 tests/cefclient/browser_window_osr_mac.h rename tests/cefclient/{osr_widget_mac.mm => browser_window_osr_mac.mm} (67%) create mode 100644 tests/cefclient/browser_window_std_mac.h create mode 100644 tests/cefclient/browser_window_std_mac.mm delete mode 100644 tests/cefclient/client_handler_shared.cc delete mode 100644 tests/cefclient/client_handler_shared.h delete mode 100644 tests/cefclient/client_handler_shared_gtk.cc delete mode 100644 tests/cefclient/client_handler_shared_mac.mm delete mode 100644 tests/cefclient/osr_widget_mac.h create mode 100644 tests/cefclient/root_window.cc create mode 100644 tests/cefclient/root_window_mac.h create mode 100644 tests/cefclient/root_window_mac.mm create mode 100644 tests/cefclient/temp_window_mac.h create mode 100644 tests/cefclient/temp_window_mac.mm diff --git a/cef_paths2.gypi b/cef_paths2.gypi index 84b9b78d8..0d2717597 100644 --- a/cef_paths2.gypi +++ b/cef_paths2.gypi @@ -149,6 +149,8 @@ 'cefclient_sources_common': [ 'tests/cefclient/binding_test.cc', 'tests/cefclient/binding_test.h', + 'tests/cefclient/browser_window.cc', + 'tests/cefclient/browser_window.h', 'tests/cefclient/bytes_write_handler.cc', 'tests/cefclient/bytes_write_handler.h', 'tests/cefclient/client_app.cc', @@ -156,6 +158,12 @@ 'tests/cefclient/client_app_delegates.cc', 'tests/cefclient/client_handler.cc', 'tests/cefclient/client_handler.h', + 'tests/cefclient/client_handler_osr.cc', + 'tests/cefclient/client_handler_osr.h', + 'tests/cefclient/client_handler_single.cc', + 'tests/cefclient/client_handler_single.h', + 'tests/cefclient/client_handler_std.cc', + 'tests/cefclient/client_handler_std.h', 'tests/cefclient/client_renderer.cc', 'tests/cefclient/client_renderer.h', 'tests/cefclient/client_switches.cc', @@ -179,6 +187,10 @@ 'tests/cefclient/performance_test_setup.h', 'tests/cefclient/performance_test_tests.cc', 'tests/cefclient/resource_util.h', + 'tests/cefclient/root_window.cc', + 'tests/cefclient/root_window.h', + 'tests/cefclient/root_window_manager.cc', + 'tests/cefclient/root_window_manager.h', 'tests/cefclient/scheme_test.cc', 'tests/cefclient/scheme_test.h', 'tests/cefclient/test_runner.cc', @@ -188,8 +200,6 @@ '<@(cefclient_bundle_resources_common)', ], 'cefclient_sources_win': [ - 'tests/cefclient/browser_window.cc', - 'tests/cefclient/browser_window.h', 'tests/cefclient/browser_window_osr_win.cc', 'tests/cefclient/browser_window_osr_win.h', 'tests/cefclient/browser_window_std_win.cc', @@ -197,12 +207,6 @@ 'tests/cefclient/cefclient.exe.manifest', 'tests/cefclient/cefclient.rc', 'tests/cefclient/cefclient_win.cc', - 'tests/cefclient/client_handler_osr.cc', - 'tests/cefclient/client_handler_osr.h', - 'tests/cefclient/client_handler_single.cc', - 'tests/cefclient/client_handler_single.h', - 'tests/cefclient/client_handler_std.cc', - 'tests/cefclient/client_handler_std.h', 'tests/cefclient/main_context_impl_win.cc', 'tests/cefclient/main_message_loop_multithreaded_win.cc', 'tests/cefclient/main_message_loop_multithreaded_win.h', @@ -214,9 +218,6 @@ 'tests/cefclient/res/cefclient.ico', 'tests/cefclient/res/small.ico', 'tests/cefclient/resource_util_win.cc', - 'tests/cefclient/root_window.h', - 'tests/cefclient/root_window_manager.cc', - 'tests/cefclient/root_window_manager.h', 'tests/cefclient/root_window_win.cc', 'tests/cefclient/root_window_win.h', 'tests/cefclient/temp_window_win.cc', @@ -226,15 +227,18 @@ 'tests/cefclient/window_test_win.cc', ], 'cefclient_sources_mac': [ + 'tests/cefclient/browser_window_osr_mac.h', + 'tests/cefclient/browser_window_osr_mac.mm', + 'tests/cefclient/browser_window_std_mac.h', + 'tests/cefclient/browser_window_std_mac.mm', 'tests/cefclient/cefclient_mac.mm', - 'tests/cefclient/client_handler_shared.cc', - 'tests/cefclient/client_handler_shared.h', - 'tests/cefclient/client_handler_shared_mac.mm', 'tests/cefclient/main_context_impl_posix.cc', - 'tests/cefclient/osr_widget_mac.h', - 'tests/cefclient/osr_widget_mac.mm', 'tests/cefclient/resource_util_mac.mm', 'tests/cefclient/resource_util_posix.cc', + 'tests/cefclient/root_window_mac.h', + 'tests/cefclient/root_window_mac.mm', + 'tests/cefclient/temp_window_mac.h', + 'tests/cefclient/temp_window_mac.mm', 'tests/cefclient/window_test_mac.mm', ], 'cefclient_sources_mac_helper': [ @@ -280,18 +284,10 @@ ], 'cefclient_sources_linux': [ 'tests/cefclient/cefclient_gtk.cc', - 'tests/cefclient/browser_window.cc', - 'tests/cefclient/browser_window.h', 'tests/cefclient/browser_window_osr_gtk.cc', 'tests/cefclient/browser_window_osr_gtk.h', 'tests/cefclient/browser_window_std_gtk.cc', 'tests/cefclient/browser_window_std_gtk.h', - 'tests/cefclient/client_handler_osr.cc', - 'tests/cefclient/client_handler_osr.h', - 'tests/cefclient/client_handler_single.cc', - 'tests/cefclient/client_handler_single.h', - 'tests/cefclient/client_handler_std.cc', - 'tests/cefclient/client_handler_std.h', 'tests/cefclient/dialog_handler_gtk.cc', 'tests/cefclient/dialog_handler_gtk.h', 'tests/cefclient/main_context_impl_posix.cc', @@ -299,9 +295,6 @@ 'tests/cefclient/print_handler_gtk.h', 'tests/cefclient/resource_util_linux.cc', 'tests/cefclient/resource_util_posix.cc', - 'tests/cefclient/root_window.h', - 'tests/cefclient/root_window_manager.cc', - 'tests/cefclient/root_window_manager.h', 'tests/cefclient/root_window_gtk.cc', 'tests/cefclient/root_window_gtk.h', 'tests/cefclient/temp_window_x11.cc', diff --git a/tests/cefclient/browser_window.h b/tests/cefclient/browser_window.h index 73f8e613c..6b5c3deca 100644 --- a/tests/cefclient/browser_window.h +++ b/tests/cefclient/browser_window.h @@ -71,7 +71,7 @@ class BrowserWindow : public ClientHandlerSingle::Delegate { virtual void SetBounds(int x, int y, size_t width, size_t height) = 0; // Set focus to the window. - virtual void SetFocus() = 0; + virtual void SetFocus(bool focus) = 0; // Returns the window handle. virtual ClientWindowHandle GetWindowHandle() const = 0; diff --git a/tests/cefclient/browser_window_osr_gtk.cc b/tests/cefclient/browser_window_osr_gtk.cc index 11b90198e..2d9a8c023 100644 --- a/tests/cefclient/browser_window_osr_gtk.cc +++ b/tests/cefclient/browser_window_osr_gtk.cc @@ -1011,9 +1011,9 @@ void BrowserWindowOsrGtk::SetBounds(int x, int y, size_t width, size_t height) { // Nothing to do here. GTK will take care of positioning in the container. } -void BrowserWindowOsrGtk::SetFocus() { +void BrowserWindowOsrGtk::SetFocus(bool focus) { REQUIRE_MAIN_THREAD(); - if (glarea_) + if (glarea_ && focus) gtk_widget_grab_focus(glarea_); } diff --git a/tests/cefclient/browser_window_osr_gtk.h b/tests/cefclient/browser_window_osr_gtk.h index d330b4a9d..fde002c6d 100644 --- a/tests/cefclient/browser_window_osr_gtk.h +++ b/tests/cefclient/browser_window_osr_gtk.h @@ -37,7 +37,7 @@ class BrowserWindowOsrGtk : public BrowserWindow, void Show() OVERRIDE; void Hide() OVERRIDE; void SetBounds(int x, int y, size_t width, size_t height) OVERRIDE; - void SetFocus() OVERRIDE; + void SetFocus(bool focus) OVERRIDE; ClientWindowHandle GetWindowHandle() const OVERRIDE; // ClientHandlerOsr::OsrDelegate methods. diff --git a/tests/cefclient/browser_window_osr_mac.h b/tests/cefclient/browser_window_osr_mac.h new file mode 100644 index 000000000..7e066ff98 --- /dev/null +++ b/tests/cefclient/browser_window_osr_mac.h @@ -0,0 +1,94 @@ +// Copyright (c) 2015 The Chromium Embedded Framework 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 CEF_TESTS_CEFCLIENT_BROWSER_WINDOW_OSR_MAC_H_ +#define CEF_TESTS_CEFCLIENT_BROWSER_WINDOW_OSR_MAC_H_ + +#include "cefclient/browser_window.h" +#include "cefclient/client_handler_osr.h" +#include "cefclient/osr_renderer.h" + +namespace client { + +// Represents a native child window hosting a single off-screen browser +// instance. The methods of this class must be called on the main thread unless +// otherwise indicated. +class BrowserWindowOsrMac : public BrowserWindow, + public ClientHandlerOsr::OsrDelegate { + public: + // Constructor may be called on any thread. + // |delegate| must outlive this object. + BrowserWindowOsrMac(BrowserWindow::Delegate* delegate, + const std::string& startup_url, + bool transparent, + bool show_update_rect); + ~BrowserWindowOsrMac(); + + // BrowserWindow methods. + void CreateBrowser(ClientWindowHandle parent_handle, + const CefRect& rect, + const CefBrowserSettings& settings) OVERRIDE; + void GetPopupConfig(CefWindowHandle temp_handle, + CefWindowInfo& windowInfo, + CefRefPtr& client, + CefBrowserSettings& settings) OVERRIDE; + void ShowPopup(ClientWindowHandle parent_handle, + int x, int y, size_t width, size_t height) OVERRIDE; + void Show() OVERRIDE; + void Hide() OVERRIDE; + void SetBounds(int x, int y, size_t width, size_t height) OVERRIDE; + void SetFocus(bool focus) OVERRIDE; + ClientWindowHandle GetWindowHandle() const OVERRIDE; + + // ClientHandlerOsr::OsrDelegate methods. + void OnAfterCreated(CefRefPtr browser) OVERRIDE; + void OnBeforeClose(CefRefPtr browser) OVERRIDE; + bool GetRootScreenRect(CefRefPtr browser, + CefRect& rect) OVERRIDE; + bool GetViewRect(CefRefPtr browser, + CefRect& rect) OVERRIDE; + bool GetScreenPoint(CefRefPtr browser, + int viewX, + int viewY, + int& screenX, + int& screenY) OVERRIDE; + bool GetScreenInfo(CefRefPtr browser, + CefScreenInfo& screen_info) OVERRIDE; + void OnPopupShow(CefRefPtr browser, bool show) OVERRIDE; + void OnPopupSize(CefRefPtr browser, + const CefRect& rect) OVERRIDE; + void OnPaint(CefRefPtr browser, + CefRenderHandler::PaintElementType type, + const CefRenderHandler::RectList& dirtyRects, + const void* buffer, + int width, + int height) OVERRIDE; + void OnCursorChange(CefRefPtr browser, + CefCursorHandle cursor, + CefRenderHandler::CursorType type, + const CefCursorInfo& custom_cursor_info) OVERRIDE; + bool StartDragging(CefRefPtr browser, + CefRefPtr drag_data, + CefRenderHandler::DragOperationsMask allowed_ops, + int x, int y) OVERRIDE; + void UpdateDragCursor(CefRefPtr browser, + CefRenderHandler::DragOperation operation) OVERRIDE; + + private: + // Create the NSView. + void Create(ClientWindowHandle parent_handle, const CefRect& rect); + + // The below members will only be accessed on the main thread which should be + // the same as the CEF UI thread. + OsrRenderer renderer_; + ClientWindowHandle nsview_; + bool hidden_; + bool painting_popup_; + + DISALLOW_COPY_AND_ASSIGN(BrowserWindowOsrMac); +}; + +} // namespace client + +#endif // CEF_TESTS_CEFCLIENT_BROWSER_WINDOW_OSR_MAC_H_ diff --git a/tests/cefclient/osr_widget_mac.mm b/tests/cefclient/browser_window_osr_mac.mm similarity index 67% rename from tests/cefclient/osr_widget_mac.mm rename to tests/cefclient/browser_window_osr_mac.mm index 628c24b60..dbfc90baa 100644 --- a/tests/cefclient/osr_widget_mac.mm +++ b/tests/cefclient/browser_window_osr_mac.mm @@ -1,23 +1,80 @@ -// Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights -// reserved. Use of this source code is governed by a BSD-style license -// that can be found in the LICENSE file. +// Copyright (c) 2015 The Chromium Embedded Framework 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 +#include "cefclient/browser_window_osr_mac.h" + +#include #import #include -#include - -#include "cefclient/osr_widget_mac.h" - -#include "include/cef_application_mac.h" -#include "include/cef_browser.h" -#include "include/cef_client.h" +#include "include/base/cef_logging.h" #include "include/cef_url.h" -#include "include/wrapper/cef_helpers.h" +#include "include/wrapper/cef_closure_task.h" #include "cefclient/bytes_write_handler.h" -#include "cefclient/osr_renderer.h" -#include "cefclient/resource_util.h" +#include "cefclient/main_message_loop.h" + +@interface BrowserOpenGLView + : NSOpenGLView { + @private + NSTrackingArea* tracking_area_; + client::BrowserWindowOsrMac* browser_window_; + client::OsrRenderer* renderer_; + NSPoint last_mouse_pos_; + NSPoint cur_mouse_pos_; + bool rotating_; + + bool was_last_mouse_down_on_view_; + + // Drag and drop + CefRefPtr current_drag_data_; + NSDragOperation current_drag_op_; + NSDragOperation current_allowed_ops_; + NSPasteboard* pasteboard_; + CFStringRef fileUTI_; + + // Event monitor for scroll wheel end event. + id endWheelMonitor_; +} + +- (id)initWithFrame:(NSRect)frame + andBrowserWindow:(client::BrowserWindowOsrMac*)browser_window + andRenderer:(client::OsrRenderer*)renderer; +- (void)detach; + +- (CefRefPtr)getBrowser; +- (NSPoint)getClickPointForEvent:(NSEvent*)event; +- (void)getKeyEvent:(CefKeyEvent&)keyEvent forEvent:(NSEvent*)event; +- (void)getMouseEvent:(CefMouseEvent&)mouseEvent forEvent:(NSEvent*)event; +- (int)getModifiersForEvent:(NSEvent*)event; +- (BOOL)isKeyUpEvent:(NSEvent*)event; +- (BOOL)isKeyPadEvent:(NSEvent*)event; +- (BOOL)startDragging:(CefRefPtr)drag_data + allowedOps:(NSDragOperation)ops point:(NSPoint)p; +- (void)setCurrentDragOp:(NSDragOperation)op; + +- (void)resetDragDrop; +- (void)fillPasteboard; +- (void)populateDropData:(CefRefPtr)data + fromPasteboard:(NSPasteboard*)pboard; +- (NSPoint)flipWindowPointToView:(const NSPoint&)windowPoint; +- (float)getDeviceScaleFactor; +- (void)windowDidChangeBackingProperties:(NSNotification*)notification; + +- (bool)isOverPopupWidgetX:(int)x andY:(int)y; +- (void)applyPopupOffsetToX:(int&)x andY:(int&)y; +- (int)getPopupXOffset; +- (int)getPopupYOffset; + +- (void)sendMouseClick:(NSEvent*)event + button:(CefBrowserHost::MouseButtonType)type + isUp:(bool)isUp; + +- (CefRect)convertRectToBackingInternal:(const CefRect&)rect; +- (CefRect)convertRectFromBackingInternal:(const CefRect&)rect; + +@end + namespace { @@ -44,9 +101,21 @@ BOOL SupportsBackingPropertiesChangedNotification() { return methodDescription.name != NULL || methodDescription.types != NULL; } +CefRect convertRect(const NSRect& target, const NSRect& frame) { + NSRect rect = target; + rect.origin.y = NSMaxY(frame) - NSMaxY(target); + return CefRect(rect.origin.x, + rect.origin.y, + rect.size.width, + rect.size.height); +} + +NSString* const kCEFDragDummyPboardType = @"org.CEF.drag-dummy-type"; +NSString* const kNSURLTitlePboardType = @"public.url-name"; + class ScopedGLContext { public: - ScopedGLContext(ClientOpenGLView* view, bool swap_buffers) + ScopedGLContext(BrowserOpenGLView* view, bool swap_buffers) : swap_buffers_(swap_buffers) { context_ = [view openGLContext]; [context_ makeCurrentContext]; @@ -61,253 +130,18 @@ class ScopedGLContext { const bool swap_buffers_; }; -} // namespace - -@interface ClientOpenGLView () -- (void)resetDragDrop; -- (void)fillPasteboard; -- (void)populateDropData:(CefRefPtr)data - fromPasteboard:(NSPasteboard*)pboard; -- (NSPoint)flipWindowPointToView:(const NSPoint&)windowPoint; -- (float)getDeviceScaleFactor; -- (void)windowDidChangeBackingProperties:(NSNotification*)notification; - -- (bool) isOverPopupWidgetX: (int) x andY: (int) y; -- (void) applyPopupOffsetToX: (int&) x andY: (int&) y; -- (int) getPopupXOffset; -- (int) getPopupYOffset; - -- (void) sendMouseClick: (NSEvent *)event - button: (CefBrowserHost::MouseButtonType)type - isUp: (bool)isUp; - -- (CefRect) convertRectToBackingInternal: (const CefRect&) rect; -- (CefRect) convertRectFromBackingInternal: (const CefRect&) rect; - -@property (readwrite, atomic) bool was_last_mouse_down_on_view; -@end - -namespace { - -static CefRect convertRect(const NSRect& target, const NSRect& frame) { - NSRect rect = target; - rect.origin.y = NSMaxY(frame) - NSMaxY(target); - return CefRect(rect.origin.x, - rect.origin.y, - rect.size.width, - rect.size.height); +BrowserOpenGLView* GLView(NSView* view) { + return static_cast(view); } -static NSString* const kCEFDragDummyPboardType = @"org.CEF.drag-dummy-type"; -static NSString* const kNSURLTitlePboardType = @"public.url-name"; - } // namespace -namespace client { -ClientOSRHandler::ClientOSRHandler(ClientOpenGLView* view, - OSRBrowserProvider* browser_provider) - : view_(view), - painting_popup_(false) { - [view_ retain]; - view_->browser_provider_ = browser_provider; +@implementation BrowserOpenGLView - // Backing property notifications crash on 10.6 when building with the 10.7 - // SDK, see http://crbug.com/260595. - static BOOL supportsBackingPropertiesNotification = - SupportsBackingPropertiesChangedNotification(); - if (supportsBackingPropertiesNotification) { - [[NSNotificationCenter defaultCenter] - addObserver:view_ - selector:@selector(windowDidChangeBackingProperties:) - name:NSWindowDidChangeBackingPropertiesNotification - object:[view_ window]]; - } -} - -ClientOSRHandler:: ~ClientOSRHandler() { - static BOOL supportsBackingPropertiesNotification = - SupportsBackingPropertiesChangedNotification(); - - if (supportsBackingPropertiesNotification) { - [[NSNotificationCenter defaultCenter] - removeObserver:view_ - name:NSWindowDidChangeBackingPropertiesNotification - object:[view_ window]]; - } -} - -void ClientOSRHandler::Disconnect() { - [view_ release]; - view_ = nil; -} - -// CefRenderHandler methods -void ClientOSRHandler::OnBeforeClose(CefRefPtr browser) { - if (view_) - view_->browser_provider_ = NULL; -} - -bool ClientOSRHandler::GetViewRect(CefRefPtr browser, - CefRect& rect) { - CEF_REQUIRE_UI_THREAD(); - - if (!view_) - return false; - - // The simulated screen and view rectangle are the same. This is necessary - // for popup menus to be located and sized inside the view. - const NSRect bounds = [view_ bounds]; - rect.x = rect.y = 0; - rect.width = bounds.size.width; - rect.height = bounds.size.height; - return true; -} - -bool ClientOSRHandler::GetScreenPoint(CefRefPtr browser, - int viewX, - int viewY, - int& screenX, - int& screenY) { - CEF_REQUIRE_UI_THREAD(); - - if (!view_) - return false; - - // Convert the point from view coordinates to actual screen coordinates. - NSRect bounds = [view_ bounds]; - NSPoint view_pt = NSMakePoint(viewX, bounds.size.height - viewY); - NSPoint window_pt = [view_ convertPoint:view_pt toView:nil]; - NSPoint screen_pt = [[view_ window] convertBaseToScreen:window_pt]; - screenX = screen_pt.x; - screenY = screen_pt.y; - return true; -} - -bool ClientOSRHandler::GetScreenInfo(CefRefPtr browser, - CefScreenInfo& screen_info) { - CEF_REQUIRE_UI_THREAD(); - - if (!view_) - return false; - - NSWindow* window = [view_ window]; - if (!window) - return false; - - screen_info.device_scale_factor = [view_ getDeviceScaleFactor]; - - NSScreen* screen = [window screen]; - if (!screen) - screen = [NSScreen deepestScreen]; - - screen_info.depth = NSBitsPerPixelFromDepth([screen depth]); - screen_info.depth_per_component = NSBitsPerSampleFromDepth([screen depth]); - screen_info.is_monochrome = - [[screen colorSpace] colorSpaceModel] == NSGrayColorSpaceModel; - // screen_info.is_monochrome = true; - screen_info.rect = convertRect([screen frame], [screen frame]); - screen_info.available_rect = - convertRect([screen visibleFrame], [screen frame]); - - return true; -} - -void ClientOSRHandler::OnPopupShow(CefRefPtr browser, - bool show) { - CEF_REQUIRE_UI_THREAD(); - - if (!view_) - return; - - if (!show) { - // Clear the popup rectangles, so that the paint triggered by Invalidate - // will not repaint the popup content over the OpenGL view. - view_->renderer_->ClearPopupRects(); - browser->GetHost()->Invalidate(PET_VIEW); - } - - view_->renderer_->OnPopupShow(browser, show); -} - -void ClientOSRHandler::OnPopupSize(CefRefPtr browser, - const CefRect& rect) { - CEF_REQUIRE_UI_THREAD(); - - if (!view_) - return; - - view_->renderer_->OnPopupSize(browser, - [view_ convertRectToBackingInternal:rect]); -} - -void ClientOSRHandler::OnPaint(CefRefPtr browser, - PaintElementType type, - const RectList& dirtyRects, - const void* buffer, - int width, int height) { - CEF_REQUIRE_UI_THREAD(); - - if (!view_) - return; - - if (painting_popup_) { - view_->renderer_->OnPaint(browser, type, dirtyRects, buffer, width, height); - return; - } - - ScopedGLContext scoped_gl_context(view_, true); - - view_->renderer_->OnPaint(browser, type, dirtyRects, buffer, width, height); - - if (type == PET_VIEW && !view_->renderer_->popup_rect().IsEmpty()) { - painting_popup_ = true; - browser->GetHost()->Invalidate(PET_POPUP); - painting_popup_ = false; - } - - view_->renderer_->Render(); -} - -void ClientOSRHandler::OnCursorChange(CefRefPtr browser, - CefCursorHandle cursor, - CursorType type, - const CefCursorInfo& custom_cursor_info) { - CEF_REQUIRE_UI_THREAD(); - [cursor set]; -} - -bool ClientOSRHandler::StartDragging(CefRefPtr browser, - CefRefPtr drag_data, - CefRenderHandler::DragOperationsMask allowed_ops, - int x, int y) { - CEF_REQUIRE_UI_THREAD(); - if (!view_) - return false; - return [view_ startDragging:drag_data - allowed_ops:static_cast(allowed_ops) - point:NSMakePoint(x, y)]; -} - -void ClientOSRHandler::UpdateDragCursor(CefRefPtr browser, - CefRenderHandler::DragOperation operation) { - CEF_REQUIRE_UI_THREAD(); - if (!view_) - return; - view_->current_drag_op_ = operation; -} - -void ClientOSRHandler::SetLoading(bool isLoading) { -} - -} // namespace client - -@implementation ClientOpenGLView - -@synthesize was_last_mouse_down_on_view = was_last_mouse_down_on_view_; - -- (id)initWithFrame:(NSRect)frame andTransparency:(bool)transparency - andShowUpdateRect:(bool)show_update_rect { +- (id)initWithFrame:(NSRect)frame + andBrowserWindow:(client::BrowserWindowOsrMac*)browser_window + andRenderer:(client::OsrRenderer*)renderer { NSOpenGLPixelFormat * pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:(NSOpenGLPixelFormatAttribute[]) { @@ -318,9 +152,9 @@ void ClientOSRHandler::SetLoading(bool isLoading) { 0}]; [pixelFormat autorelease]; - self = [super initWithFrame:frame pixelFormat:pixelFormat]; - if (self) { - renderer_ = new client::OsrRenderer(transparency, show_update_rect); + if (self = [super initWithFrame:frame pixelFormat:pixelFormat]) { + browser_window_ = browser_window; + renderer_ = renderer; rotating_ = false; endWheelMonitor_ = nil; @@ -332,86 +166,90 @@ void ClientOSRHandler::SetLoading(bool isLoading) { owner:self userInfo:nil]; [self addTrackingArea:tracking_area_]; + + if ([self respondsToSelector: + @selector(setWantsBestResolutionOpenGLSurface:)]) { + // enable HiDPI buffer + [self setWantsBestResolutionOpenGLSurface:YES]; + } + + [self resetDragDrop]; + + NSArray* types = [NSArray arrayWithObjects: + kCEFDragDummyPboardType, + NSStringPboardType, + NSFilenamesPboardType, + NSPasteboardTypeString, + nil]; + [self registerForDraggedTypes:types]; } - if ([self respondsToSelector: - @selector(setWantsBestResolutionOpenGLSurface:)]) { - // enable HiDPI buffer - [self setWantsBestResolutionOpenGLSurface:YES]; - } - - [self resetDragDrop]; - - NSArray* types = [NSArray arrayWithObjects: - kCEFDragDummyPboardType, - NSStringPboardType, - NSFilenamesPboardType, - NSPasteboardTypeString, - nil]; - [self registerForDraggedTypes:types]; - return self; } - (void)dealloc { - CefRefPtr browser = [self getBrowser]; - if (browser) { - static_cast( - browser->GetHost()->GetClient()->GetRenderHandler().get())->Disconnect(); - browser->GetHost()->CloseBrowser(true); - browser = NULL; + static BOOL supportsBackingPropertiesNotification = + SupportsBackingPropertiesChangedNotification(); + if (supportsBackingPropertiesNotification) { + [[NSNotificationCenter defaultCenter] + removeObserver:self + name:NSWindowDidChangeBackingPropertiesNotification + object:nil]; } - if (renderer_) - delete renderer_; [super dealloc]; } +- (void)detach { + renderer_ = NULL; + browser_window_ = NULL; +} + - (CefRefPtr)getBrowser { - if (browser_provider_) - return browser_provider_->GetBrowser(); + if (browser_window_) + return browser_window_->GetBrowser(); return NULL; } - (void)setFrame:(NSRect)frameRect { CefRefPtr browser = [self getBrowser]; - if (!browser) + if (!browser.get()) return; [super setFrame:frameRect]; browser->GetHost()->WasResized(); } -- (void) sendMouseClick:(NSEvent *)event - button: (CefBrowserHost::MouseButtonType)type - isUp: (bool)isUp { +- (void) sendMouseClick:(NSEvent*)event + button:(CefBrowserHost::MouseButtonType)type + isUp:(bool)isUp { CefRefPtr browser = [self getBrowser]; - if (!browser) + if (!browser.get()) return; CefMouseEvent mouseEvent; [self getMouseEvent: mouseEvent forEvent: event]; NSPoint point = [self getClickPointForEvent:event]; if (!isUp) - self.was_last_mouse_down_on_view = ![self isOverPopupWidgetX: point.x - andY: point.y]; - else if (self.was_last_mouse_down_on_view && + was_last_mouse_down_on_view_ = ![self isOverPopupWidgetX: point.x + andY: point.y]; + else if (was_last_mouse_down_on_view_ && [self isOverPopupWidgetX:point.x andY: point.y] && ([self getPopupXOffset] || [self getPopupYOffset])) { return; } browser->GetHost()->SendMouseClickEvent(mouseEvent, - type, - isUp, - [event clickCount]); + type, + isUp, + [event clickCount]); } -- (void)mouseDown:(NSEvent *)event { +- (void)mouseDown:(NSEvent*)event { [self sendMouseClick: event button:MBT_LEFT isUp:false]; } -- (void)rightMouseDown:(NSEvent *)event { +- (void)rightMouseDown:(NSEvent*)event { if ([event modifierFlags] & NSShiftKeyMask) { // Start rotation effect. last_mouse_pos_ = cur_mouse_pos_ = [self getClickPointForEvent:event]; @@ -422,15 +260,15 @@ void ClientOSRHandler::SetLoading(bool isLoading) { [self sendMouseClick: event button:MBT_RIGHT isUp:false]; } -- (void)otherMouseDown:(NSEvent *)event { +- (void)otherMouseDown:(NSEvent*)event { [self sendMouseClick: event button:MBT_MIDDLE isUp:false]; } -- (void)mouseUp:(NSEvent *)event { +- (void)mouseUp:(NSEvent*)event { [self sendMouseClick: event button: MBT_LEFT isUp: true]; } -- (void)rightMouseUp:(NSEvent *)event { +- (void)rightMouseUp:(NSEvent*)event { if (rotating_) { // End rotation effect. renderer_->SetSpin(0, 0); @@ -441,13 +279,13 @@ void ClientOSRHandler::SetLoading(bool isLoading) { [self sendMouseClick: event button: MBT_RIGHT isUp: true]; } -- (void)otherMouseUp:(NSEvent *)event { +- (void)otherMouseUp:(NSEvent*)event { [self sendMouseClick: event button: MBT_MIDDLE isUp: true]; } -- (void)mouseMoved:(NSEvent *)event { +- (void)mouseMoved:(NSEvent*)event { CefRefPtr browser = [self getBrowser]; - if (!browser) + if (!browser.get()) return; if (rotating_) { @@ -465,25 +303,25 @@ void ClientOSRHandler::SetLoading(bool isLoading) { browser->GetHost()->SendMouseMoveEvent(mouseEvent, false); } -- (void)mouseDragged:(NSEvent *)event { +- (void)mouseDragged:(NSEvent*)event { [self mouseMoved:event]; } -- (void)rightMouseDragged:(NSEvent *)event { +- (void)rightMouseDragged:(NSEvent*)event { [self mouseMoved:event]; } -- (void)otherMouseDragged:(NSEvent *)event { +- (void)otherMouseDragged:(NSEvent*)event { [self mouseMoved:event]; } -- (void)mouseEntered:(NSEvent *)event { +- (void)mouseEntered:(NSEvent*)event { [self mouseMoved:event]; } -- (void)mouseExited:(NSEvent *)event { +- (void)mouseExited:(NSEvent*)event { CefRefPtr browser = [self getBrowser]; - if (!browser) + if (!browser.get()) return; CefMouseEvent mouseEvent; @@ -491,9 +329,9 @@ void ClientOSRHandler::SetLoading(bool isLoading) { browser->GetHost()->SendMouseMoveEvent(mouseEvent, true); } -- (void)keyDown:(NSEvent *)event { +- (void)keyDown:(NSEvent*)event { CefRefPtr browser = [self getBrowser]; - if (!browser) + if (!browser.get()) return; if ([event type] != NSFlagsChanged) { @@ -508,9 +346,9 @@ void ClientOSRHandler::SetLoading(bool isLoading) { } } -- (void)keyUp:(NSEvent *)event { +- (void)keyUp:(NSEvent*)event { CefRefPtr browser = [self getBrowser]; - if (!browser) + if (!browser.get()) return; CefKeyEvent keyEvent; @@ -520,7 +358,7 @@ void ClientOSRHandler::SetLoading(bool isLoading) { browser->GetHost()->SendKeyEvent(keyEvent); } -- (void)flagsChanged:(NSEvent *)event { +- (void)flagsChanged:(NSEvent*)event { if ([self isKeyUpEvent:event]) [self keyUp:event]; else @@ -541,7 +379,7 @@ void ClientOSRHandler::SetLoading(bool isLoading) { } } -- (void)scrollWheel:(NSEvent *)event { +- (void)scrollWheel:(NSEvent*)event { // Phase is only supported in OS-X 10.7 and newer. // Use an NSEvent monitor to listen for the wheel-end end. This ensures that // the event is received even when the mouse cursor is no longer over the @@ -560,9 +398,9 @@ void ClientOSRHandler::SetLoading(bool isLoading) { [self sendScrollWheelEvet:event]; } -- (void)sendScrollWheelEvet:(NSEvent *)event { +- (void)sendScrollWheelEvet:(NSEvent*)event { CefRefPtr browser = [self getBrowser]; - if (!browser) + if (!browser.get()) return; CGEventRef cgEvent = [event CGEvent]; @@ -580,17 +418,17 @@ void ClientOSRHandler::SetLoading(bool isLoading) { - (BOOL)canBecomeKeyView { CefRefPtr browser = [self getBrowser]; - return (browser != NULL); + return (browser.get() != NULL); } - (BOOL)acceptsFirstResponder { CefRefPtr browser = [self getBrowser]; - return (browser != NULL); + return (browser.get() != NULL); } - (BOOL)becomeFirstResponder { CefRefPtr browser = [self getBrowser]; - if (browser) { + if (browser.get()) { browser->GetHost()->SendFocusEvent(true); return [super becomeFirstResponder]; } @@ -600,7 +438,7 @@ void ClientOSRHandler::SetLoading(bool isLoading) { - (BOOL)resignFirstResponder { CefRefPtr browser = [self getBrowser]; - if (browser) { + if (browser.get()) { browser->GetHost()->SendFocusEvent(false); return [super resignFirstResponder]; } @@ -610,43 +448,43 @@ void ClientOSRHandler::SetLoading(bool isLoading) { - (void)undo:(id)sender { CefRefPtr browser = [self getBrowser]; - if (browser) + if (browser.get()) browser->GetFocusedFrame()->Undo(); } - (void)redo:(id)sender { CefRefPtr browser = [self getBrowser]; - if (browser) + if (browser.get()) browser->GetFocusedFrame()->Redo(); } - (void)cut:(id)sender { CefRefPtr browser = [self getBrowser]; - if (browser) + if (browser.get()) browser->GetFocusedFrame()->Cut(); } - (void)copy:(id)sender { CefRefPtr browser = [self getBrowser]; - if (browser) + if (browser.get()) browser->GetFocusedFrame()->Copy(); } - (void)paste:(id)sender { CefRefPtr browser = [self getBrowser]; - if (browser) + if (browser.get()) browser->GetFocusedFrame()->Paste(); } - (void)delete:(id)sender { CefRefPtr browser = [self getBrowser]; - if (browser) + if (browser.get()) browser->GetFocusedFrame()->Delete(); } - (void)selectAll:(id)sender { CefRefPtr browser = [self getBrowser]; - if (browser) + if (browser.get()) browser->GetFocusedFrame()->SelectAll(); } @@ -683,7 +521,7 @@ void ClientOSRHandler::SetLoading(bool isLoading) { - (NSTextInputContext*)inputContext { CefRefPtr browser = [self getBrowser]; - if (browser) + if (browser.get()) return browser->GetHost()->GetNSTextInputContext(); return NULL; } @@ -818,10 +656,8 @@ void ClientOSRHandler::SetLoading(bool isLoading) { [[notification userInfo] objectForKey:NSBackingPropertyOldScaleFactorKey]; if (newBackingScaleFactor != [oldBackingScaleFactor doubleValue]) { CefRefPtr browser = [self getBrowser]; - if (!browser) - return; - - browser->GetHost()->NotifyScreenInfoChanged(); + if (browser.get()) + browser->GetHost()->NotifyScreenInfoChanged(); } } @@ -829,17 +665,15 @@ void ClientOSRHandler::SetLoading(bool isLoading) { // The Invalidate below fixes flicker when resizing if ([self inLiveResize]) { CefRefPtr browser = [self getBrowser]; - if (!browser) - return; - - browser->GetHost()->Invalidate(PET_VIEW); + if (browser.get()) + browser->GetHost()->Invalidate(PET_VIEW); } } // Drag and drop - (BOOL)startDragging:(CefRefPtr)drag_data - allowed_ops:(NSDragOperation)ops + allowedOps:(NSDragOperation)ops point:(NSPoint)position { DCHECK(!pasteboard_); DCHECK(!fileUTI_); @@ -852,7 +686,7 @@ void ClientOSRHandler::SetLoading(bool isLoading) { [self fillPasteboard]; - NSEvent* currentEvent = [NSApp currentEvent]; + NSEvent* currentEvent = [[NSApplication sharedApplication] currentEvent]; NSWindow* window = [self window]; NSTimeInterval eventTime = [currentEvent timestamp]; @@ -876,6 +710,10 @@ void ClientOSRHandler::SetLoading(bool isLoading) { return YES; } +- (void)setCurrentDragOp:(NSDragOperation)op { + current_drag_op_ = op; +} + // NSDraggingSource Protocol - (NSDragOperation)draggingSession:(NSDraggingSession *)session @@ -918,6 +756,9 @@ void ClientOSRHandler::SetLoading(bool isLoading) { - (void)draggedImage:(NSImage*)anImage endedAt:(NSPoint)screenPoint operation:(NSDragOperation)operation { + CefRefPtr browser = [self getBrowser]; + if (!browser.get()) + return; if (operation == (NSDragOperationMove | NSDragOperationCopy)) operation &= ~NSDragOperationMove; @@ -926,14 +767,18 @@ void ClientOSRHandler::SetLoading(bool isLoading) { NSPoint pt = [self flipWindowPointToView:windowPoint]; CefRenderHandler::DragOperation op = static_cast(operation); - browser_provider_->GetBrowser()->GetHost()->DragSourceEndedAt(pt.x, pt.y, op); - browser_provider_->GetBrowser()->GetHost()->DragSourceSystemDragEnded(); + browser->GetHost()->DragSourceEndedAt(pt.x, pt.y, op); + browser->GetHost()->DragSourceSystemDragEnded(); [self resetDragDrop]; } // NSDraggingDestination Protocol - (NSDragOperation)draggingEntered:(id )info { + CefRefPtr browser = [self getBrowser]; + if (!browser.get()) + return NSDragOperationNone; + CefRefPtr drag_data; if (!current_drag_data_) { drag_data = CefDragData::Create(); @@ -953,17 +798,17 @@ void ClientOSRHandler::SetLoading(bool isLoading) { ev.modifiers = [NSEvent modifierFlags]; CefBrowserHost::DragOperationsMask allowed_ops = static_cast(mask); - browser_provider_->GetBrowser()->GetHost()->DragTargetDragEnter( - drag_data, ev, allowed_ops); - browser_provider_->GetBrowser()->GetHost()->DragTargetDragOver(ev, - allowed_ops); + browser->GetHost()->DragTargetDragEnter(drag_data, ev, allowed_ops); + browser->GetHost()->DragTargetDragOver(ev, allowed_ops); current_drag_op_ = NSDragOperationCopy; return current_drag_op_; } - (void)draggingExited:(id )sender { - browser_provider_->GetBrowser()->GetHost()->DragTargetDragLeave(); + CefRefPtr browser = [self getBrowser]; + if (browser.get()) + browser->GetHost()->DragTargetDragLeave(); } - (BOOL)prepareForDragOperation:(id )info { @@ -971,17 +816,26 @@ void ClientOSRHandler::SetLoading(bool isLoading) { } - (BOOL)performDragOperation:(id )info { + CefRefPtr browser = [self getBrowser]; + if (!browser.get()) + return NO; + NSPoint windowPoint = [info draggingLocation]; NSPoint viewPoint = [self flipWindowPointToView:windowPoint]; CefMouseEvent ev; ev.x = viewPoint.x; ev.y = viewPoint.y; ev.modifiers = [NSEvent modifierFlags]; - browser_provider_->GetBrowser()->GetHost()->DragTargetDrop(ev); + browser->GetHost()->DragTargetDrop(ev); + return YES; } - (NSDragOperation)draggingUpdated:(id)info { + CefRefPtr browser = [self getBrowser]; + if (!browser.get()) + return NSDragOperationNone; + NSPoint windowPoint = [info draggingLocation]; NSPoint viewPoint = [self flipWindowPointToView:windowPoint]; NSDragOperation mask = [info draggingSourceOperationMask]; @@ -991,8 +845,7 @@ void ClientOSRHandler::SetLoading(bool isLoading) { ev.modifiers = [NSEvent modifierFlags]; CefBrowserHost::DragOperationsMask allowed_ops = static_cast(mask); - browser_provider_->GetBrowser()->GetHost()->DragTargetDragOver(ev, - allowed_ops); + browser->GetHost()->DragTargetDragOver(ev, allowed_ops); return current_drag_op_; } @@ -1044,10 +897,9 @@ void ClientOSRHandler::SetLoading(bool isLoading) { forType:kCEFDragDummyPboardType]; } - } -// Utility - private +// Utility methods. - (void)resetDragDrop { current_drag_op_ = NSDragOperationNone; current_allowed_ops_ = NSDragOperationNone; @@ -1163,7 +1015,7 @@ void ClientOSRHandler::SetLoading(bool isLoading) { return deviceScaleFactor; } -- (bool) isOverPopupWidgetX: (int) x andY: (int) y { +- (bool)isOverPopupWidgetX:(int)x andY:(int)y { CefRect rc = [self convertRectFromBackingInternal:renderer_->popup_rect()]; int popup_right = rc.x + rc.width; int popup_bottom = rc.y + rc.height; @@ -1171,7 +1023,7 @@ void ClientOSRHandler::SetLoading(bool isLoading) { (y >= rc.y) && (y < popup_bottom); } -- (int) getPopupXOffset { +- (int)getPopupXOffset { int original_x = [self convertRectFromBackingInternal:renderer_->original_popup_rect()].x; int popup_x = @@ -1180,7 +1032,7 @@ void ClientOSRHandler::SetLoading(bool isLoading) { return original_x - popup_x; } -- (int) getPopupYOffset { +- (int)getPopupYOffset { int original_y = [self convertRectFromBackingInternal:renderer_->original_popup_rect()].y; int popup_y = @@ -1189,7 +1041,7 @@ void ClientOSRHandler::SetLoading(bool isLoading) { return original_y - popup_y; } -- (void) applyPopupOffsetToX: (int&) x andY: (int&) y { +- (void)applyPopupOffsetToX:(int&)x andY:(int&)y { if ([self isOverPopupWidgetX:x andY:y]) { x += [self getPopupXOffset]; y += [self getPopupYOffset]; @@ -1197,7 +1049,7 @@ void ClientOSRHandler::SetLoading(bool isLoading) { } // Convert the rect from view coordinates to scaled coordinates. -- (CefRect) convertRectToBackingInternal: (const CefRect&) rect { +- (CefRect) convertRectToBackingInternal:(const CefRect&)rect { if ([self respondsToSelector:@selector(convertRectToBacking:)]) { NSRect view_rect = NSMakeRect(rect.x, rect.y, rect.width, rect.height); NSRect scaled_rect = [self convertRectToBacking:view_rect]; @@ -1226,36 +1078,324 @@ void ClientOSRHandler::SetLoading(bool isLoading) { @end + namespace client { -CefRefPtr OSRWindow::Create(OSRBrowserProvider* browser_provider, - bool transparent, - bool show_update_rect, - CefWindowHandle parentView, - const CefRect& frame) { - return new OSRWindow(browser_provider, transparent, show_update_rect, - parentView, frame); +BrowserWindowOsrMac::BrowserWindowOsrMac(BrowserWindow::Delegate* delegate, + const std::string& startup_url, + bool transparent, + bool show_update_rect) + : BrowserWindow(delegate), + renderer_(transparent, show_update_rect), + nsview_(NULL), + hidden_(false), + painting_popup_(false) { + client_handler_ = new ClientHandlerOsr(this, this, startup_url); } -OSRWindow::OSRWindow(OSRBrowserProvider* browser_provider, - bool transparent, - bool show_update_rect, - CefWindowHandle parentView, - const CefRect& frame) { - NSRect window_rect = NSMakeRect(frame.x, frame.y, frame.width, frame.height); - ClientOpenGLView* view = - [[ClientOpenGLView alloc] initWithFrame:window_rect - andTransparency:transparent - andShowUpdateRect:show_update_rect]; - this->view_ = view; - [parentView addSubview:view]; - [view setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)]; - [view setAutoresizesSubviews: true]; - - this->render_client = new ClientOSRHandler(view, browser_provider); +BrowserWindowOsrMac::~BrowserWindowOsrMac() { + if (nsview_) { + // Disassociate the view with |this|. + [GLView(nsview_) detach]; + } } -OSRWindow::~OSRWindow() { +void BrowserWindowOsrMac::CreateBrowser(ClientWindowHandle parent_handle, + const CefRect& rect, + const CefBrowserSettings& settings) { + REQUIRE_MAIN_THREAD(); + + // Create the native NSView. + Create(parent_handle, rect); + + CefWindowInfo window_info; + window_info.SetAsWindowless(nsview_, renderer_.IsTransparent()); + + // Create the browser asynchronously. + CefBrowserHost::CreateBrowser(window_info, client_handler_, + client_handler_->startup_url(), + settings, NULL); +} + +void BrowserWindowOsrMac::GetPopupConfig(CefWindowHandle temp_handle, + CefWindowInfo& windowInfo, + CefRefPtr& client, + CefBrowserSettings& settings) { + // Note: This method may be called on any thread. + windowInfo.SetAsWindowless(temp_handle, renderer_.IsTransparent()); + client = client_handler_; +} + +void BrowserWindowOsrMac::ShowPopup(ClientWindowHandle parent_handle, + int x, int y, size_t width, size_t height) { + REQUIRE_MAIN_THREAD(); + DCHECK(browser_.get()); + + // Create the native NSView. + Create(parent_handle, + CefRect(x, y, static_cast(width), static_cast(height))); + + // Send resize notification so the compositor is assigned the correct + // viewport size and begins rendering. + browser_->GetHost()->WasResized(); + + Show(); +} + +void BrowserWindowOsrMac::Show() { + REQUIRE_MAIN_THREAD(); + + if (hidden_) { + // Set the browser as visible. + browser_->GetHost()->SetWindowVisibility(true); + hidden_ = false; + } + + // Give focus to the browser. + browser_->GetHost()->SendFocusEvent(true); +} + +void BrowserWindowOsrMac::Hide() { + REQUIRE_MAIN_THREAD(); + + if (!browser_.get()) + return; + + // Remove focus from the browser. + browser_->GetHost()->SendFocusEvent(false); + + if (!hidden_) { + // Set the browser as hidden. + browser_->GetHost()->SetWindowVisibility(false); + hidden_ = true; + } +} + +void BrowserWindowOsrMac::SetBounds(int x, int y, size_t width, size_t height) { + REQUIRE_MAIN_THREAD(); + // Nothing to do here. GTK will take care of positioning in the container. +} + +void BrowserWindowOsrMac::SetFocus(bool focus) { + REQUIRE_MAIN_THREAD(); + if (nsview_) + [[nsview_ window] makeFirstResponder:nsview_]; +} + +ClientWindowHandle BrowserWindowOsrMac::GetWindowHandle() const { + REQUIRE_MAIN_THREAD(); + return nsview_; +} + +void BrowserWindowOsrMac::OnAfterCreated(CefRefPtr browser) { + CEF_REQUIRE_UI_THREAD(); +} + +void BrowserWindowOsrMac::OnBeforeClose(CefRefPtr browser) { + CEF_REQUIRE_UI_THREAD(); + REQUIRE_MAIN_THREAD(); + + // Detach |this| from the ClientHandlerOsr. + static_cast(client_handler_.get())->DetachOsrDelegate(); +} + +bool BrowserWindowOsrMac::GetRootScreenRect(CefRefPtr browser, + CefRect& rect) { + CEF_REQUIRE_UI_THREAD(); + return false; +} + +bool BrowserWindowOsrMac::GetViewRect(CefRefPtr browser, + CefRect& rect) { + CEF_REQUIRE_UI_THREAD(); + REQUIRE_MAIN_THREAD(); + + if (!nsview_) + return false; + + // The simulated screen and view rectangle are the same. This is necessary + // for popup menus to be located and sized inside the view. + const NSRect bounds = [nsview_ bounds]; + rect.x = rect.y = 0; + rect.width = bounds.size.width; + rect.height = bounds.size.height; + return true; +} + +bool BrowserWindowOsrMac::GetScreenPoint(CefRefPtr browser, + int viewX, + int viewY, + int& screenX, + int& screenY) { + CEF_REQUIRE_UI_THREAD(); + REQUIRE_MAIN_THREAD(); + + if (!nsview_) + return false; + + // Convert the point from view coordinates to actual screen coordinates. + NSRect bounds = [nsview_ bounds]; + NSPoint view_pt = NSMakePoint(viewX, bounds.size.height - viewY); + NSPoint window_pt = [nsview_ convertPoint:view_pt toView:nil]; + NSPoint screen_pt = [[nsview_ window] convertBaseToScreen:window_pt]; + screenX = screen_pt.x; + screenY = screen_pt.y; + return true; +} + +bool BrowserWindowOsrMac::GetScreenInfo(CefRefPtr browser, + CefScreenInfo& screen_info) { + CEF_REQUIRE_UI_THREAD(); + REQUIRE_MAIN_THREAD(); + + if (!nsview_) + return false; + + NSWindow* window = [nsview_ window]; + if (!window) + return false; + + screen_info.device_scale_factor = [GLView(nsview_) getDeviceScaleFactor]; + + NSScreen* screen = [window screen]; + if (!screen) + screen = [NSScreen deepestScreen]; + + screen_info.depth = NSBitsPerPixelFromDepth([screen depth]); + screen_info.depth_per_component = NSBitsPerSampleFromDepth([screen depth]); + screen_info.is_monochrome = + [[screen colorSpace] colorSpaceModel] == NSGrayColorSpaceModel; + screen_info.rect = convertRect([screen frame], [screen frame]); + screen_info.available_rect = + convertRect([screen visibleFrame], [screen frame]); + + return true; +} + +void BrowserWindowOsrMac::OnPopupShow(CefRefPtr browser, + bool show) { + CEF_REQUIRE_UI_THREAD(); + REQUIRE_MAIN_THREAD(); + + if (!nsview_) + return; + + if (!show) { + renderer_.ClearPopupRects(); + browser->GetHost()->Invalidate(PET_VIEW); + } + renderer_.OnPopupShow(browser, show); +} + +void BrowserWindowOsrMac::OnPopupSize(CefRefPtr browser, + const CefRect& rect) { + CEF_REQUIRE_UI_THREAD(); + REQUIRE_MAIN_THREAD(); + + if (!nsview_) + return; + + renderer_.OnPopupSize(browser, + [GLView(nsview_) convertRectToBackingInternal:rect]); +} + +void BrowserWindowOsrMac::OnPaint( + CefRefPtr browser, + CefRenderHandler::PaintElementType type, + const CefRenderHandler::RectList& dirtyRects, + const void* buffer, + int width, + int height) { + CEF_REQUIRE_UI_THREAD(); + REQUIRE_MAIN_THREAD(); + + if (!nsview_) + return; + + if (width <= 2 && height <= 2) { + // Ignore really small buffer sizes while the widget is starting up. + return; + } + + if (painting_popup_) { + renderer_.OnPaint(browser, type, dirtyRects, buffer, width, height); + return; + } + + ScopedGLContext scoped_gl_context(GLView(nsview_), true); + + renderer_.OnPaint(browser, type, dirtyRects, buffer, width, height); + if (type == PET_VIEW && !renderer_.popup_rect().IsEmpty()) { + painting_popup_ = true; + browser->GetHost()->Invalidate(PET_POPUP); + painting_popup_ = false; + } + renderer_.Render(); +} + +void BrowserWindowOsrMac::OnCursorChange( + CefRefPtr browser, + CefCursorHandle cursor, + CefRenderHandler::CursorType type, + const CefCursorInfo& custom_cursor_info) { + CEF_REQUIRE_UI_THREAD(); + REQUIRE_MAIN_THREAD(); + + [cursor set]; +} + +bool BrowserWindowOsrMac::StartDragging( + CefRefPtr browser, + CefRefPtr drag_data, + CefRenderHandler::DragOperationsMask allowed_ops, + int x, int y) { + CEF_REQUIRE_UI_THREAD(); + REQUIRE_MAIN_THREAD(); + + if (!nsview_) + return false; + + return [GLView(nsview_) + startDragging:drag_data + allowedOps:static_cast(allowed_ops) + point:NSMakePoint(x, y)]; +} + +void BrowserWindowOsrMac::UpdateDragCursor( + CefRefPtr browser, + CefRenderHandler::DragOperation operation) { + CEF_REQUIRE_UI_THREAD(); + REQUIRE_MAIN_THREAD(); + + if (nsview_) + [GLView(nsview_) setCurrentDragOp:operation]; +} + +void BrowserWindowOsrMac::Create(ClientWindowHandle parent_handle, + const CefRect& rect) { + REQUIRE_MAIN_THREAD(); + DCHECK(!nsview_); + + NSRect window_rect = NSMakeRect(rect.x, rect.y, rect.width, rect.height); + nsview_ = + [[BrowserOpenGLView alloc] initWithFrame:window_rect + andBrowserWindow:this + andRenderer:&renderer_]; + [nsview_ setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)]; + [nsview_ setAutoresizesSubviews: true]; + [parent_handle addSubview:nsview_]; + + // Backing property notifications crash on 10.6 when building with the 10.7 + // SDK, see http://crbug.com/260595. + static BOOL supportsBackingPropertiesNotification = + SupportsBackingPropertiesChangedNotification(); + if (supportsBackingPropertiesNotification) { + [[NSNotificationCenter defaultCenter] + addObserver:nsview_ + selector:@selector(windowDidChangeBackingProperties:) + name:NSWindowDidChangeBackingPropertiesNotification + object:[nsview_ window]]; + } } } // namespace client diff --git a/tests/cefclient/browser_window_osr_win.cc b/tests/cefclient/browser_window_osr_win.cc index 73d620eae..9fc8b6ac6 100644 --- a/tests/cefclient/browser_window_osr_win.cc +++ b/tests/cefclient/browser_window_osr_win.cc @@ -64,9 +64,9 @@ void BrowserWindowOsrWin::SetBounds(int x, int y, size_t width, size_t height) { osr_window_->SetBounds(x, y, width, height); } -void BrowserWindowOsrWin::SetFocus() { +void BrowserWindowOsrWin::SetFocus(bool focus) { REQUIRE_MAIN_THREAD(); - if (osr_window_) + if (osr_window_ && focus) osr_window_->SetFocus(); } diff --git a/tests/cefclient/browser_window_osr_win.h b/tests/cefclient/browser_window_osr_win.h index 076a204df..1a1aaa403 100644 --- a/tests/cefclient/browser_window_osr_win.h +++ b/tests/cefclient/browser_window_osr_win.h @@ -36,7 +36,7 @@ class BrowserWindowOsrWin : public BrowserWindow, void Show() OVERRIDE; void Hide() OVERRIDE; void SetBounds(int x, int y, size_t width, size_t height) OVERRIDE; - void SetFocus() OVERRIDE; + void SetFocus(bool focus) OVERRIDE; ClientWindowHandle GetWindowHandle() const OVERRIDE; private: diff --git a/tests/cefclient/browser_window_std_gtk.cc b/tests/cefclient/browser_window_std_gtk.cc index 57c99bf67..25645a99f 100644 --- a/tests/cefclient/browser_window_std_gtk.cc +++ b/tests/cefclient/browser_window_std_gtk.cc @@ -165,13 +165,11 @@ void BrowserWindowStdGtk::SetBounds(int x, int y, size_t width, size_t height) { } } -void BrowserWindowStdGtk::SetFocus() { +void BrowserWindowStdGtk::SetFocus(bool focus) { REQUIRE_MAIN_THREAD(); - if (browser_) { - // Give focus to the browser window. - browser_->GetHost()->SetFocus(true); - } + if (browser_) + browser_->GetHost()->SetFocus(focus); } ClientWindowHandle BrowserWindowStdGtk::GetWindowHandle() const { diff --git a/tests/cefclient/browser_window_std_gtk.h b/tests/cefclient/browser_window_std_gtk.h index 7c44594e8..c78776848 100644 --- a/tests/cefclient/browser_window_std_gtk.h +++ b/tests/cefclient/browser_window_std_gtk.h @@ -32,7 +32,7 @@ class BrowserWindowStdGtk : public BrowserWindow { void Show() OVERRIDE; void Hide() OVERRIDE; void SetBounds(int x, int y, size_t width, size_t height) OVERRIDE; - void SetFocus() OVERRIDE; + void SetFocus(bool focus) OVERRIDE; ClientWindowHandle GetWindowHandle() const OVERRIDE; private: diff --git a/tests/cefclient/browser_window_std_mac.h b/tests/cefclient/browser_window_std_mac.h new file mode 100644 index 000000000..bba0de1a8 --- /dev/null +++ b/tests/cefclient/browser_window_std_mac.h @@ -0,0 +1,44 @@ +// Copyright (c) 2015 The Chromium Embedded Framework 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 CEF_TESTS_CEFCLIENT_BROWSER_WINDOW_STD_MAC_H_ +#define CEF_TESTS_CEFCLIENT_BROWSER_WINDOW_STD_MAC_H_ + +#include "cefclient/browser_window.h" + +namespace client { + +// Represents a native child window hosting a single windowed browser instance. +// The methods of this class must be called on the main thread unless otherwise +// indicated. +class BrowserWindowStdMac : public BrowserWindow { + public: + // Constructor may be called on any thread. + // |delegate| must outlive this object. + BrowserWindowStdMac(Delegate* delegate, + const std::string& startup_url); + + // BrowserWindow methods. + void CreateBrowser(ClientWindowHandle parent_handle, + const CefRect& rect, + const CefBrowserSettings& settings) OVERRIDE; + void GetPopupConfig(CefWindowHandle temp_handle, + CefWindowInfo& windowInfo, + CefRefPtr& client, + CefBrowserSettings& settings) OVERRIDE; + void ShowPopup(ClientWindowHandle parent_handle, + int x, int y, size_t width, size_t height) OVERRIDE; + void Show() OVERRIDE; + void Hide() OVERRIDE; + void SetBounds(int x, int y, size_t width, size_t height) OVERRIDE; + void SetFocus(bool focus) OVERRIDE; + ClientWindowHandle GetWindowHandle() const OVERRIDE; + + private: + DISALLOW_COPY_AND_ASSIGN(BrowserWindowStdMac); +}; + +} // namespace client + +#endif // CEF_TESTS_CEFCLIENT_BROWSER_WINDOW_STD_MAC_H_ diff --git a/tests/cefclient/browser_window_std_mac.mm b/tests/cefclient/browser_window_std_mac.mm new file mode 100644 index 000000000..c0c1a40bc --- /dev/null +++ b/tests/cefclient/browser_window_std_mac.mm @@ -0,0 +1,94 @@ +// Copyright (c) 2015 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +#include "cefclient/browser_window_std_mac.h" + +#include + +#include "include/base/cef_logging.h" +#include "include/cef_app.h" +#include "cefclient/client_handler_std.h" +#include "cefclient/main_message_loop.h" + +namespace client { + +BrowserWindowStdMac::BrowserWindowStdMac(Delegate* delegate, + const std::string& startup_url) + : BrowserWindow(delegate) { + client_handler_ = new ClientHandlerStd(this, startup_url); +} + +void BrowserWindowStdMac::CreateBrowser(ClientWindowHandle parent_handle, + const CefRect& rect, + const CefBrowserSettings& settings) { + REQUIRE_MAIN_THREAD(); + + CefWindowInfo window_info; + window_info.SetAsChild(parent_handle, + rect.x, rect.y, rect.width, rect.height); + + CefBrowserHost::CreateBrowser(window_info, client_handler_, + client_handler_->startup_url(), + settings, NULL); +} + +void BrowserWindowStdMac::GetPopupConfig(CefWindowHandle temp_handle, + CefWindowInfo& windowInfo, + CefRefPtr& client, + CefBrowserSettings& settings) { + // Note: This method may be called on any thread. + // The window will be properly sized after the browser is created. + windowInfo.SetAsChild(temp_handle, 0, 0, 0, 0); + client = client_handler_; +} + +void BrowserWindowStdMac::ShowPopup(ClientWindowHandle parent_handle, + int x, int y, size_t width, size_t height) { + REQUIRE_MAIN_THREAD(); + + NSView* browser_view = GetWindowHandle(); + + // Re-parent |browser_view| to |parent_handle|. + [browser_view removeFromSuperview]; + [parent_handle addSubview:browser_view]; + + NSSize size = NSMakeSize(static_cast(width), static_cast(height)); + [browser_view setFrameSize:size]; +} + +void BrowserWindowStdMac::Show() { + REQUIRE_MAIN_THREAD(); + + if (browser_) + browser_->GetHost()->SetWindowVisibility(true); +} + +void BrowserWindowStdMac::Hide() { + REQUIRE_MAIN_THREAD(); + + if (browser_) + browser_->GetHost()->SetWindowVisibility(false); +} + +void BrowserWindowStdMac::SetBounds(int x, int y, size_t width, size_t height) { + REQUIRE_MAIN_THREAD(); + // Nothing to do here. Cocoa will size the browser for us. +} + +void BrowserWindowStdMac::SetFocus(bool focus) { + REQUIRE_MAIN_THREAD(); + + if (browser_) + browser_->GetHost()->SetFocus(focus); +} + +ClientWindowHandle BrowserWindowStdMac::GetWindowHandle() const { + REQUIRE_MAIN_THREAD(); + + if (browser_) + return browser_->GetHost()->GetWindowHandle(); + return NULL; +} + +} // namespace client diff --git a/tests/cefclient/browser_window_std_win.cc b/tests/cefclient/browser_window_std_win.cc index 32a698b4c..6fb7b0851 100644 --- a/tests/cefclient/browser_window_std_win.cc +++ b/tests/cefclient/browser_window_std_win.cc @@ -85,13 +85,11 @@ void BrowserWindowStdWin::SetBounds(int x, int y, size_t width, size_t height) { } } -void BrowserWindowStdWin::SetFocus() { +void BrowserWindowStdWin::SetFocus(bool focus) { REQUIRE_MAIN_THREAD(); - if (browser_) { - // Give focus to the browser window. - browser_->GetHost()->SetFocus(true); - } + if (browser_) + browser_->GetHost()->SetFocus(focus); } ClientWindowHandle BrowserWindowStdWin::GetWindowHandle() const { diff --git a/tests/cefclient/browser_window_std_win.h b/tests/cefclient/browser_window_std_win.h index a6305150e..eb942aa4e 100644 --- a/tests/cefclient/browser_window_std_win.h +++ b/tests/cefclient/browser_window_std_win.h @@ -32,7 +32,7 @@ class BrowserWindowStdWin : public BrowserWindow { void Show() OVERRIDE; void Hide() OVERRIDE; void SetBounds(int x, int y, size_t width, size_t height) OVERRIDE; - void SetFocus() OVERRIDE; + void SetFocus(bool focus) OVERRIDE; ClientWindowHandle GetWindowHandle() const OVERRIDE; private: diff --git a/tests/cefclient/cefclient_mac.mm b/tests/cefclient/cefclient_mac.mm index 4a9fc30f5..460d60ece 100644 --- a/tests/cefclient/cefclient_mac.mm +++ b/tests/cefclient/cefclient_mac.mm @@ -4,58 +4,18 @@ // found in the LICENSE file. #import -#include #include "include/cef_app.h" #import "include/cef_application_mac.h" -#include "include/cef_browser.h" -#include "include/cef_frame.h" #include "cefclient/client_app.h" -#include "cefclient/client_handler.h" #include "cefclient/client_switches.h" #include "cefclient/main_context_impl.h" #include "cefclient/main_message_loop_std.h" -#include "cefclient/osr_widget_mac.h" #include "cefclient/resource.h" -#include "cefclient/resource_util.h" +#include "cefclient/root_window.h" #include "cefclient/test_runner.h" namespace { -// The global ClientHandlerShared reference. -CefRefPtr g_handler; - -// Used by off-screen rendering to find the associated CefBrowser. -class MainBrowserProvider : public client::OSRBrowserProvider { - virtual CefRefPtr GetBrowser() { - if (g_handler.get()) - return g_handler->GetBrowser(); - - return NULL; - } -} g_main_browser_provider; - - -// Sizes for URL bar layout -#define BUTTON_HEIGHT 22 -#define BUTTON_WIDTH 72 -#define BUTTON_MARGIN 8 -#define URLBAR_HEIGHT 32 - -// Content area size for newly created windows. -const int kWindowWidth = 800; -const int kWindowHeight = 600; - - -NSButton* MakeButton(NSRect* rect, NSString* title, NSView* parent) { - NSButton* button = [[[NSButton alloc] initWithFrame:*rect] autorelease]; - [button setTitle:title]; - [button setBezelStyle:NSSmallSquareBezelStyle]; - [button setAutoresizingMask:(NSViewMaxXMargin | NSViewMinYMargin)]; - [parent addSubview:button]; - rect->origin.x += BUTTON_WIDTH; - return button; -} - void AddMenuItem(NSMenu *menu, NSString* label, int idval) { NSMenuItem* item = [menu addItemWithTitle:label action:@selector(menuItemSelected:) @@ -66,7 +26,13 @@ void AddMenuItem(NSMenu *menu, NSString* label, int idval) { } // namespace // Receives notifications from the application. Will delete itself when done. -@interface ClientAppDelegate : NSObject +@interface ClientAppDelegate : NSObject { + @private + bool with_osr_; +} + +@property (nonatomic, readwrite) bool with_osr; + - (void)createApplication:(id)object; - (void)tryToTerminateApplication:(NSApplication*)app; - (IBAction)menuItemSelected:(id)sender; @@ -74,12 +40,15 @@ void AddMenuItem(NSMenu *menu, NSString* label, int idval) { // Provide the CefAppProtocol implementation required by CEF. @interface ClientApplication : NSApplication { -@private + @private BOOL handlingSendEvent_; } @end @implementation ClientApplication + +@synthesize with_osr = with_osr_; + - (BOOL)isHandlingSendEvent { return handlingSendEvent_; } @@ -131,222 +100,25 @@ void AddMenuItem(NSMenu *menu, NSString* label, int idval) { // The standard |-applicationShouldTerminate:| is not supported, and code paths // leading to it must be redirected. - (void)terminate:(id)sender { - ClientAppDelegate* delegate = - static_cast([NSApp delegate]); + ClientAppDelegate* delegate = static_cast( + [[NSApplication sharedApplication] delegate]); [delegate tryToTerminateApplication:self]; // Return, don't exit. The application is responsible for exiting on its own. } @end - -// Receives notifications from controls and the browser window. Will delete -// itself when done. -@interface ClientWindowDelegate : NSObject { - @private - NSWindow* window_; -} -- (id)initWithWindow:(NSWindow*)window; -- (IBAction)goBack:(id)sender; -- (IBAction)goForward:(id)sender; -- (IBAction)reload:(id)sender; -- (IBAction)stopLoading:(id)sender; -- (IBAction)takeURLStringValueFrom:(NSTextField *)sender; -- (void)alert:(NSString*)title withMessage:(NSString*)message; -@end - -@implementation ClientWindowDelegate - -- (id)initWithWindow:(NSWindow*)window { - if (self = [super init]) { - window_ = window; - [window_ setDelegate:self]; - - // Register for application hide/unhide notifications. - [[NSNotificationCenter defaultCenter] - addObserver:self - selector:@selector(applicationDidHide:) - name:NSApplicationDidHideNotification - object:nil]; - [[NSNotificationCenter defaultCenter] - addObserver:self - selector:@selector(applicationDidUnhide:) - name:NSApplicationDidUnhideNotification - object:nil]; - } - return self; -} - -- (void)dealloc { - [[NSNotificationCenter defaultCenter] removeObserver:self]; - - [super dealloc]; -} - -- (IBAction)goBack:(id)sender { - if (g_handler.get() && g_handler->GetBrowserId()) - g_handler->GetBrowser()->GoBack(); -} - -- (IBAction)goForward:(id)sender { - if (g_handler.get() && g_handler->GetBrowserId()) - g_handler->GetBrowser()->GoForward(); -} - -- (IBAction)reload:(id)sender { - if (g_handler.get() && g_handler->GetBrowserId()) - g_handler->GetBrowser()->Reload(); -} - -- (IBAction)stopLoading:(id)sender { - if (g_handler.get() && g_handler->GetBrowserId()) - g_handler->GetBrowser()->StopLoad(); -} - -- (IBAction)takeURLStringValueFrom:(NSTextField *)sender { - if (!g_handler.get() || !g_handler->GetBrowserId()) - return; - - NSString *url = [sender stringValue]; - - // if it doesn't already have a prefix, add http. If we can't parse it, - // just don't bother rather than making things worse. - NSURL* tempUrl = [NSURL URLWithString:url]; - if (tempUrl && ![tempUrl scheme]) - url = [@"http://" stringByAppendingString:url]; - - std::string urlStr = [url UTF8String]; - g_handler->GetBrowser()->GetMainFrame()->LoadURL(urlStr); -} - -- (void)alert:(NSString*)title withMessage:(NSString*)message { - NSAlert *alert = [NSAlert alertWithMessageText:title - defaultButton:@"OK" - alternateButton:nil - otherButton:nil - informativeTextWithFormat:@"%@", message]; - [alert runModal]; -} - -// Called when we are activated (when we gain focus). -- (void)windowDidBecomeKey:(NSNotification*)notification { - if (g_handler.get()) { - CefRefPtr browser = g_handler->GetBrowser(); - if (browser.get()) { - if (g_handler->is_osr()) { - browser->GetHost()->SendFocusEvent(true); - } else { - browser->GetHost()->SetFocus(true); - } - } - } -} - -// Called when we are deactivated (when we lose focus). -- (void)windowDidResignKey:(NSNotification*)notification { - if (g_handler.get()) { - CefRefPtr browser = g_handler->GetBrowser(); - if (browser.get()) { - if (g_handler->is_osr()) { - browser->GetHost()->SendFocusEvent(false); - } else { - browser->GetHost()->SetFocus(false); - } - } - } -} - -// Called when we have been minimized. -- (void)windowDidMiniaturize:(NSNotification *)notification { - if (g_handler.get()) { - CefRefPtr browser = g_handler->GetBrowser(); - if (browser.get()) - browser->GetHost()->SetWindowVisibility(false); - } -} - -// Called when we have been unminimized. -- (void)windowDidDeminiaturize:(NSNotification *)notification { - if (g_handler.get()) { - CefRefPtr browser = g_handler->GetBrowser(); - if (browser.get()) - browser->GetHost()->SetWindowVisibility(true); - } -} - -// Called when the application has been hidden. -- (void)applicationDidHide:(NSNotification *)notification { - // If the window is miniaturized then nothing has really changed. - if (![window_ isMiniaturized]) { - if (g_handler.get()) { - CefRefPtr browser = g_handler->GetBrowser(); - if (browser.get()) - browser->GetHost()->SetWindowVisibility(false); - } - } -} - -// Called when the application has been unhidden. -- (void)applicationDidUnhide:(NSNotification *)notification { - // If the window is miniaturized then nothing has really changed. - if (![window_ isMiniaturized]) { - if (g_handler.get()) { - CefRefPtr browser = g_handler->GetBrowser(); - if (browser.get()) - browser->GetHost()->SetWindowVisibility(true); - } - } -} - -// Called when the window is about to close. Perform the self-destruction -// sequence by getting rid of the window. By returning YES, we allow the window -// to be removed from the screen. -- (BOOL)windowShouldClose:(id)window { - if (g_handler.get() && !g_handler->IsClosing()) { - CefRefPtr browser = g_handler->GetBrowser(); - if (browser.get()) { - // Notify the browser window that we would like to close it. This - // will result in a call to ClientHandler::DoClose() if the - // JavaScript 'onbeforeunload' event handler allows it. - browser->GetHost()->CloseBrowser(false); - - // Cancel the close. - return NO; - } - } - - // Try to make the window go away. - [window autorelease]; - - // Clean ourselves up after clearing the stack of anything that might have the - // window on it. - [self performSelectorOnMainThread:@selector(cleanup:) - withObject:window - waitUntilDone:NO]; - - // Allow the close. - return YES; -} - -// Deletes itself. -- (void)cleanup:(id)window { - [self release]; -} - -@end - - @implementation ClientAppDelegate // Create the application on the UI thread. - (void)createApplication:(id)object { - [NSApplication sharedApplication]; + NSApplication* application = [NSApplication sharedApplication]; [NSBundle loadNibNamed:@"MainMenu" owner:NSApp]; // Set the delegate for application events. - [NSApp setDelegate:self]; + [application setDelegate:self]; // Add the Tests menu. - NSMenu* menubar = [NSApp mainMenu]; + NSMenu* menubar = [application mainMenu]; NSMenuItem *testItem = [[[NSMenuItem alloc] initWithTitle:@"Tests" action:nil keyEquivalent:@""] autorelease]; @@ -366,127 +138,32 @@ void AddMenuItem(NSMenu *menu, NSString* label, int idval) { [testItem setSubmenu:testMenu]; [menubar addItem:testItem]; - // Create the main application window. - NSRect screen_rect = [[NSScreen mainScreen] visibleFrame]; - NSRect window_rect = { {0, screen_rect.size.height - kWindowHeight}, - {kWindowWidth, kWindowHeight} }; - NSWindow* mainWnd = [[UnderlayOpenGLHostingWindow alloc] - initWithContentRect:window_rect - styleMask:(NSTitledWindowMask | - NSClosableWindowMask | - NSMiniaturizableWindowMask | - NSResizableWindowMask ) - backing:NSBackingStoreBuffered - defer:NO]; - [mainWnd setTitle:@"cefclient"]; - - // Create the delegate for control and browser window events. - ClientWindowDelegate* delegate = - [[ClientWindowDelegate alloc] initWithWindow:mainWnd]; - - // Rely on the window delegate to clean us up rather than immediately - // releasing when the window gets closed. We use the delegate to do - // everything from the autorelease pool so the window isn't on the stack - // during cleanup (ie, a window close from javascript). - [mainWnd setReleasedWhenClosed:NO]; - - NSView* contentView = [mainWnd contentView]; - - // Create the buttons. - NSRect button_rect = [contentView bounds]; - button_rect.origin.y = window_rect.size.height - URLBAR_HEIGHT + - (URLBAR_HEIGHT - BUTTON_HEIGHT) / 2; - button_rect.size.height = BUTTON_HEIGHT; - button_rect.origin.x += BUTTON_MARGIN; - button_rect.size.width = BUTTON_WIDTH; - - NSButton* backButton = MakeButton(&button_rect, @"Back", contentView); - [backButton setTarget:delegate]; - [backButton setAction:@selector(goBack:)]; - [backButton setEnabled:NO]; - - NSButton* forwardButton = MakeButton(&button_rect, @"Forward", contentView); - [forwardButton setTarget:delegate]; - [forwardButton setAction:@selector(goForward:)]; - [forwardButton setEnabled:NO]; - - NSButton* reloadButton = MakeButton(&button_rect, @"Reload", contentView); - [reloadButton setTarget:delegate]; - [reloadButton setAction:@selector(reload:)]; - [reloadButton setEnabled:NO]; - - NSButton* stopButton = MakeButton(&button_rect, @"Stop", contentView); - [stopButton setTarget:delegate]; - [stopButton setAction:@selector(stopLoading:)]; - [stopButton setEnabled:NO]; - - // Create the URL text field. - button_rect.origin.x += BUTTON_MARGIN; - button_rect.size.width = [contentView bounds].size.width - - button_rect.origin.x - BUTTON_MARGIN; - NSTextField* editWnd = [[NSTextField alloc] initWithFrame:button_rect]; - [contentView addSubview:editWnd]; - [editWnd setAutoresizingMask:(NSViewWidthSizable | NSViewMinYMargin)]; - [editWnd setTarget:delegate]; - [editWnd setAction:@selector(takeURLStringValueFrom:)]; - [editWnd setEnabled:NO]; - [[editWnd cell] setWraps:NO]; - [[editWnd cell] setScrollable:YES]; - - // Create the handler. - g_handler = new client::ClientHandlerShared(); - g_handler->SetMainWindowHandle(contentView); - g_handler->SetUXWindowHandles(editWnd, backButton, forwardButton, - reloadButton, stopButton); - - // Create the browser view. - CefWindowInfo window_info; - CefBrowserSettings settings; - - // Populate the browser settings based on command line arguments. - client::MainContext::Get()->PopulateBrowserSettings(&settings); - - if (g_handler->is_osr()) { - CefRefPtr command_line = - CefCommandLine::GetGlobalCommandLine(); - const bool transparent = - command_line->HasSwitch(client::switches::kTransparentPaintingEnabled); - const bool show_update_rect = - command_line->HasSwitch(client::switches::kShowUpdateRect); - - CefRefPtr osr_window = - client::OSRWindow::Create(&g_main_browser_provider, transparent, - show_update_rect, contentView, - CefRect(0, 0, kWindowWidth, kWindowHeight)); - window_info.SetAsWindowless(osr_window->GetWindowHandle(), transparent); - g_handler->SetOSRHandler(osr_window->GetRenderHandler().get()); - } else { - // Initialize window info to the defaults for a child window. - window_info.SetAsChild(contentView, 0, 0, kWindowWidth, kWindowHeight); - } - - CefBrowserHost::CreateBrowser(window_info, g_handler.get(), - g_handler->startup_url(), settings, NULL); - - // Show the window. - [mainWnd makeKeyAndOrderFront: nil]; - - // Size the window. - NSRect r = [mainWnd contentRectForFrameRect:[mainWnd frame]]; - r.size.width = kWindowWidth; - r.size.height = kWindowHeight + URLBAR_HEIGHT; - [mainWnd setFrame:[mainWnd frameRectForContentRect:r] display:YES]; + // Create the first window. + client::MainContext::Get()->GetRootWindowManager()->CreateRootWindow( + true, // Show controls. + with_osr_, // Use off-screen rendering. + CefRect(), // Use default system size. + std::string()); // Use default URL. } - (void)tryToTerminateApplication:(NSApplication*)app { - if (g_handler.get() && !g_handler->IsClosing()) - g_handler->CloseAllBrowsers(false); + client::MainContext::Get()->GetRootWindowManager()->CloseAllWindows(false); } - (IBAction)menuItemSelected:(id)sender { - NSMenuItem *item = (NSMenuItem*)sender; - if (g_handler.get() && g_handler->GetBrowserId()) - client::test_runner::RunTest(g_handler->GetBrowser(), [item tag]); + // Retrieve the active RootWindow. + NSWindow* key_window = [[NSApplication sharedApplication] keyWindow]; + if (!key_window) + return; + + scoped_refptr root_window = + client::RootWindow::GetForNSWindow(key_window); + + CefRefPtr browser = root_window->GetBrowser(); + if (browser.get()) { + NSMenuItem *item = (NSMenuItem*)sender; + client::test_runner::RunTest(browser, [item tag]); + } } - (NSApplicationTerminateReply)applicationShouldTerminate: @@ -528,7 +205,8 @@ int RunMain(int argc, char* argv[]) { test_runner::RegisterSchemeHandlers(); // Create the application delegate and window. - NSObject* delegate = [[ClientAppDelegate alloc] init]; + ClientAppDelegate* delegate = [[ClientAppDelegate alloc] init]; + delegate->with_osr = settings.windowless_rendering_enabled ? true : false; [delegate performSelectorOnMainThread:@selector(createApplication:) withObject:nil waitUntilDone:NO]; @@ -540,7 +218,6 @@ int RunMain(int argc, char* argv[]) { context->Shutdown(); // Release objects in reverse order of creation. - g_handler = NULL; [delegate release]; message_loop.reset(); context.reset(); diff --git a/tests/cefclient/client_handler_shared.cc b/tests/cefclient/client_handler_shared.cc deleted file mode 100644 index b6735a79f..000000000 --- a/tests/cefclient/client_handler_shared.cc +++ /dev/null @@ -1,188 +0,0 @@ -// Copyright (c) 2015 The Chromium Embedded Framework Authors. All rights -// reserved. Use of this source code is governed by a BSD-style license that -// can be found in the LICENSE file. - -#include "cefclient/client_handler_shared.h" - -#include -#include -#include - -#include "include/base/cef_bind.h" -#include "include/cef_command_line.h" -#include "include/wrapper/cef_closure_task.h" -#include "cefclient/client_switches.h" -#include "cefclient/main_context.h" -#include "cefclient/main_message_loop.h" -#include "cefclient/test_runner.h" - -namespace client { - -ClientHandlerShared::ClientHandlerShared() - : ClientHandler(MainContext::Get()->GetMainURL(), - CefCommandLine::GetGlobalCommandLine()->HasSwitch( - switches::kOffScreenRenderingEnabled)), - is_closing_(false), - browser_id_(0), - edit_handle_(NULL), - back_handle_(NULL), - forward_handle_(NULL), - stop_handle_(NULL), - reload_handle_(NULL) { -} - -ClientHandlerShared::~ClientHandlerShared() { -} - -void ClientHandlerShared::BrowserCreated(CefRefPtr browser) { - CEF_REQUIRE_UI_THREAD(); - - if (browser_id_ == 0) { - // Keep references to the browser hosted in the main window. - browser_id_ = browser->GetIdentifier(); - browser_ = browser; - } else if (browser->IsPopup()) { - // Add to the list of popup browsers. - popup_browsers_.push_back(browser); - - // Give focus to the popup browser. Perform asynchronously because the - // parent window may attempt to keep focus after launching the popup. - CefPostTask(TID_UI, - base::Bind(&CefBrowserHost::SetFocus, browser->GetHost().get(), true)); - } -} - -void ClientHandlerShared::BrowserClosing(CefRefPtr browser) { - CEF_REQUIRE_UI_THREAD(); - - // Closing the main window requires special handling. See the DoClose() - // documentation in the CEF header for a detailed destription of this - // process. - if (browser_id_ == browser->GetIdentifier()) { - // Set a flag to indicate that the window close should be allowed. - is_closing_ = true; - } -} - -void ClientHandlerShared::BrowserClosed(CefRefPtr browser) { - CEF_REQUIRE_UI_THREAD(); - - if (browser_id_ == browser->GetIdentifier()) { - // Free the browser pointer so that the browser can be destroyed. - browser_ = NULL; - - if (osr_handler_.get()) { - osr_handler_->OnBeforeClose(browser); - osr_handler_ = NULL; - } - - browser_id_ = 0; - } else if (browser->IsPopup()) { - // Remove from the browser popup list. - BrowserList::iterator bit = popup_browsers_.begin(); - for (; bit != popup_browsers_.end(); ++bit) { - if ((*bit)->IsSame(browser)) { - popup_browsers_.erase(bit); - break; - } - } - } - - if (GetBrowserCount() == 0) { - // Quit the main message loop. - MainMessageLoop::Get()->Quit(); - } -} - -bool ClientHandlerShared::CreatePopupWindow( - CefRefPtr browser, - bool is_devtools, - const CefPopupFeatures& popupFeatures, - CefWindowInfo& windowInfo, - CefRefPtr& client, - CefBrowserSettings& settings) { - // Note: This method will be called on multiple threads. - - if (is_devtools) { - CEF_REQUIRE_UI_THREAD(); - - // Create DevTools as a windowed popup browser using the same client. -#if defined(OS_WIN) - windowInfo.SetAsPopup(GetMainWindowHandle(), "DevTools"); -#endif - client = this; - } else if (is_osr()) { - CefPostTask(TID_UI, - base::Bind(test_runner::Alert, browser, - "Popup windows are disabled with off-screen rendering.")); - - // Cancel popups in off-screen rendering mode. - return false; - } - - return true; -} - -void ClientHandlerShared::SetUXWindowHandles( - ClientWindowHandle editHandle, - ClientWindowHandle backHandle, - ClientWindowHandle forwardHandle, - ClientWindowHandle reloadHandle, - ClientWindowHandle stopHandle) { - CEF_REQUIRE_UI_THREAD(); - - edit_handle_ = editHandle; - back_handle_ = backHandle; - forward_handle_ = forwardHandle; - reload_handle_ = reloadHandle; - stop_handle_ = stopHandle; -} - -CefRefPtr - ClientHandlerShared::GetOSRHandler() const { - CEF_REQUIRE_UI_THREAD(); - - return osr_handler_; -} - -void ClientHandlerShared::SetOSRHandler(CefRefPtr handler) { - CEF_REQUIRE_UI_THREAD(); - - osr_handler_ = handler; -} - -CefRefPtr ClientHandlerShared::GetBrowser() const { - CEF_REQUIRE_UI_THREAD(); - - return browser_; -} - -int ClientHandlerShared::GetBrowserId() const { - CEF_REQUIRE_UI_THREAD(); - - return browser_id_; -} - -void ClientHandlerShared::CloseAllBrowsers(bool force_close) { - CEF_REQUIRE_UI_THREAD(); - - if (!popup_browsers_.empty()) { - // Request that any popup browsers close. - BrowserList::const_iterator it = popup_browsers_.begin(); - for (; it != popup_browsers_.end(); ++it) - (*it)->GetHost()->CloseBrowser(force_close); - } - - if (browser_.get()) { - // Request that the main browser close. - browser_->GetHost()->CloseBrowser(force_close); - } -} - -bool ClientHandlerShared::IsClosing() const { - CEF_REQUIRE_UI_THREAD(); - - return is_closing_; -} - -} // namespace client diff --git a/tests/cefclient/client_handler_shared.h b/tests/cefclient/client_handler_shared.h deleted file mode 100644 index 93a32abbc..000000000 --- a/tests/cefclient/client_handler_shared.h +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright (c) 2015 The Chromium Embedded Framework 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 CEF_TESTS_CEFCLIENT_CLIENT_HANDLER_SHARED_H_ -#define CEF_TESTS_CEFCLIENT_CLIENT_HANDLER_SHARED_H_ -#pragma once - -#include -#include - -#include "cefclient/client_handler.h" - -namespace client { - -// Client handler implementation that is shared by all existing browsers. All -// methods must be called on the CEF UI thread unless otherwise indicated. -class ClientHandlerShared : public ClientHandler { - public: - // Interface implemented to handle off-screen rendering. - class RenderHandler : public CefRenderHandler { - public: - virtual void OnBeforeClose(CefRefPtr browser) =0; - }; - - ClientHandlerShared(); - ~ClientHandlerShared(); - - // CefClient methods - CefRefPtr GetRenderHandler() OVERRIDE { - return osr_handler_; - } - - // ClientHandler methods - void BrowserCreated(CefRefPtr browser) OVERRIDE; - void BrowserClosing(CefRefPtr browser) OVERRIDE; - void BrowserClosed(CefRefPtr browser) OVERRIDE; - void SetAddress(CefRefPtr browser, - const CefString& url) OVERRIDE; - void SetTitle(CefRefPtr browser, - const CefString& title) OVERRIDE; - void SetLoadingState(CefRefPtr browser, - bool isLoading, - bool canGoBack, - bool canGoForward) OVERRIDE; - bool CreatePopupWindow( - CefRefPtr browser, - bool is_devtools, - const CefPopupFeatures& popupFeatures, - CefWindowInfo& windowInfo, - CefRefPtr& client, - CefBrowserSettings& settings) OVERRIDE; - - void SetUXWindowHandles(ClientWindowHandle editHandle, - ClientWindowHandle backHandle, - ClientWindowHandle forwardHandle, - ClientWindowHandle reloadHandle, - ClientWindowHandle stopHandle); - - CefRefPtr GetOSRHandler() const; - void SetOSRHandler(CefRefPtr handler); - - // Get the main (non-popup) browser associated with this client. - CefRefPtr GetBrowser() const; - - // Get the main (non-popup) browser ID. Will return non-0 if the main browser - // currently exists. - int GetBrowserId() const; - - // Request that all existing browser windows close. - void CloseAllBrowsers(bool force_close); - - // Returns true if the main browser window is currently closing. Used in - // combination with DoClose() and the OS close notification to properly handle - // 'onbeforeunload' JavaScript events during window close. - bool IsClosing() const; - - private: - // The following members will only be accessed on the CEF UI thread. - - // The handler for off-screen rendering, if any. - CefRefPtr osr_handler_; - - // The child browser window. - CefRefPtr browser_; - - // True if the main browser window is currently closing. - bool is_closing_; - - // The child browser id. - int browser_id_; - - // List of any popup browser windows. - typedef std::list > BrowserList; - BrowserList popup_browsers_; - - // The edit window handle. - ClientWindowHandle edit_handle_; - - // The button window handles. - ClientWindowHandle back_handle_; - ClientWindowHandle forward_handle_; - ClientWindowHandle stop_handle_; - ClientWindowHandle reload_handle_; - - // Include the default reference counting implementation. - IMPLEMENT_REFCOUNTING(ClientHandlerShared); - DISALLOW_COPY_AND_ASSIGN(ClientHandlerShared); -}; - -} // namespace client - -#endif // CEF_TESTS_CEFCLIENT_CLIENT_HANDLER_SHARED_H_ diff --git a/tests/cefclient/client_handler_shared_gtk.cc b/tests/cefclient/client_handler_shared_gtk.cc deleted file mode 100644 index 0e4f232bb..000000000 --- a/tests/cefclient/client_handler_shared_gtk.cc +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights -// reserved. Use of this source code is governed by a BSD-style license that -// can be found in the LICENSE file. - -#include -#include -#include -#include -#undef Success // Definition conflicts with cef_message_router.h - -#include - -#include "cefclient/client_handler_shared.h" -#include "include/cef_browser.h" - -namespace client { - -void ClientHandlerShared::SetAddress(CefRefPtr browser, - const CefString& url) { - CEF_REQUIRE_UI_THREAD(); - - if (browser_id_ == browser->GetIdentifier()) { - // Set the edit window text. - std::string urlStr(url); - gtk_entry_set_text(GTK_ENTRY(edit_handle_), urlStr.c_str()); - } -} - -void ClientHandlerShared::SetTitle(CefRefPtr browser, - const CefString& title) { - CEF_REQUIRE_UI_THREAD(); - - std::string titleStr(title); - - if (!browser->IsPopup()) { - // Set the GTK parent window title. - GtkWidget* window = gtk_widget_get_ancestor(GetMainWindowHandle(), - GTK_TYPE_WINDOW); - gtk_window_set_title(GTK_WINDOW(window), titleStr.c_str()); - } else { - // Retrieve the X11 display shared with Chromium. - ::Display* display = cef_get_xdisplay(); - DCHECK(display); - - // Retrieve the X11 window handle for the browser. - ::Window window = browser->GetHost()->GetWindowHandle(); - DCHECK(window != kNullWindowHandle); - - // Retrieve the atoms required by the below XChangeProperty call. - const char* kAtoms[] = { - "_NET_WM_NAME", - "UTF8_STRING" - }; - Atom atoms[2]; - int result = XInternAtoms(display, const_cast(kAtoms), 2, false, - atoms); - if (!result) - NOTREACHED(); - - // Set the window title. - XChangeProperty(display, - window, - atoms[0], - atoms[1], - 8, - PropModeReplace, - reinterpret_cast(titleStr.c_str()), - titleStr.size()); - - // TODO(erg): This is technically wrong. So XStoreName and friends expect - // this in Host Portable Character Encoding instead of UTF-8, which I - // believe is Compound Text. This shouldn't matter 90% of the time since - // this is the fallback to the UTF8 property above. - XStoreName(display, browser->GetHost()->GetWindowHandle(), - titleStr.c_str()); - } -} - -void ClientHandlerShared::SetLoadingState(CefRefPtr browser, - bool isLoading, - bool canGoBack, - bool canGoForward) { - CEF_REQUIRE_UI_THREAD(); - - // Nothing to do for popup windows. - if (browser_id_ != browser->GetIdentifier()) - return; - - if (isLoading) - gtk_widget_set_sensitive(GTK_WIDGET(stop_handle_), true); - else - gtk_widget_set_sensitive(GTK_WIDGET(stop_handle_), false); - - if (canGoBack) - gtk_widget_set_sensitive(GTK_WIDGET(back_handle_), true); - else - gtk_widget_set_sensitive(GTK_WIDGET(back_handle_), false); - - if (canGoForward) - gtk_widget_set_sensitive(GTK_WIDGET(forward_handle_), true); - else - gtk_widget_set_sensitive(GTK_WIDGET(forward_handle_), false); -} - -} // namespace client diff --git a/tests/cefclient/client_handler_shared_mac.mm b/tests/cefclient/client_handler_shared_mac.mm deleted file mode 100644 index 951122453..000000000 --- a/tests/cefclient/client_handler_shared_mac.mm +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) 2011 The Chromium Embedded Framework 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 - -#include "cefclient/client_handler_shared.h" -#include "include/cef_browser.h" - -namespace client { - -void ClientHandlerShared::SetAddress(CefRefPtr browser, - const CefString& url) { - CEF_REQUIRE_UI_THREAD(); - - if (browser_id_ == browser->GetIdentifier()) { - // Set edit window text for the main window. - NSTextField* textField = (NSTextField*)edit_handle_; - std::string urlStr(url); - NSString* str = [NSString stringWithUTF8String:urlStr.c_str()]; - [textField setStringValue:str]; - } -} - -void ClientHandlerShared::SetTitle(CefRefPtr browser, - const CefString& title) { - CEF_REQUIRE_UI_THREAD(); - - // Set the frame window title bar. - NSView* view = (NSView*)browser->GetHost()->GetWindowHandle(); - NSWindow* window = [view window]; - std::string titleStr(title); - NSString* str = [NSString stringWithUTF8String:titleStr.c_str()]; - [window setTitle:str]; -} - -void ClientHandlerShared::SetLoadingState(CefRefPtr browser, - bool isLoading, - bool canGoBack, - bool canGoForward) { - CEF_REQUIRE_UI_THREAD(); - - if (browser_id_ == browser->GetIdentifier()) { - // Set UX control state for the main window. - [(NSTextField*)edit_handle_ setEnabled:YES]; - [(NSButton*)reload_handle_ setEnabled:!isLoading]; - [(NSButton*)stop_handle_ setEnabled:isLoading]; - [(NSButton*)back_handle_ setEnabled:canGoBack]; - [(NSButton*)forward_handle_ setEnabled:canGoForward]; - } -} - -} // namespace client diff --git a/tests/cefclient/client_types.h b/tests/cefclient/client_types.h index 57c6c09f0..9cfcbf1cd 100644 --- a/tests/cefclient/client_types.h +++ b/tests/cefclient/client_types.h @@ -16,5 +16,17 @@ #define ClientWindowHandle CefWindowHandle #endif +#if defined(OS_MACOSX) +// Forward declaration of ObjC types used by cefclient and not provided by +// include/internal/cef_types_mac.h. +#ifdef __cplusplus +#ifdef __OBJC__ +@class NSWindow; +#else +class NSWindow; +#endif +#endif +#endif // defined OS_MACOSX + #endif // CEF_TESTS_CEFCLIENT_CLIENT_TYPES_H_ diff --git a/tests/cefclient/main_context.h b/tests/cefclient/main_context.h index 176920bc0..c0e05b56d 100644 --- a/tests/cefclient/main_context.h +++ b/tests/cefclient/main_context.h @@ -12,9 +12,7 @@ namespace client { -#if defined(OS_WIN) || defined(OS_LINUX) class RootWindowManager; -#endif // Used to store global context in the browser process. The methods of this // class are thread-safe unless otherwise indicated. @@ -39,10 +37,8 @@ class MainContext { virtual void PopulateSettings(CefSettings* settings) = 0; virtual void PopulateBrowserSettings(CefBrowserSettings* settings) = 0; -#if defined(OS_WIN) || defined(OS_LINUX) // Returns the object used to create/manage RootWindow instances. virtual RootWindowManager* GetRootWindowManager() = 0; -#endif protected: MainContext(); diff --git a/tests/cefclient/main_context_impl.cc b/tests/cefclient/main_context_impl.cc index 7b2c88bd8..1f6e0a6d3 100644 --- a/tests/cefclient/main_context_impl.cc +++ b/tests/cefclient/main_context_impl.cc @@ -70,12 +70,10 @@ void MainContextImpl::PopulateBrowserSettings(CefBrowserSettings* settings) { } } -#if defined(OS_WIN) || defined(OS_LINUX) RootWindowManager* MainContextImpl::GetRootWindowManager() { DCHECK(InValidState()); return root_window_manager_.get(); } -#endif bool MainContextImpl::Initialize(const CefMainArgs& args, const CefSettings& settings, @@ -88,12 +86,10 @@ bool MainContextImpl::Initialize(const CefMainArgs& args, if (!CefInitialize(args, settings, application, windows_sandbox_info)) return false; -#if defined(OS_WIN) || defined(OS_LINUX) // Need to create the RootWindowManager after calling CefInitialize because // TempWindowX11 uses cef_get_xdisplay(). root_window_manager_.reset( new RootWindowManager(terminate_when_all_windows_closed_)); -#endif initialized_ = true; @@ -105,9 +101,7 @@ void MainContextImpl::Shutdown() { DCHECK(initialized_); DCHECK(!shutdown_); -#if defined(OS_WIN) || defined(OS_LINUX) root_window_manager_.reset(); -#endif CefShutdown(); diff --git a/tests/cefclient/main_context_impl.h b/tests/cefclient/main_context_impl.h index 75661d6f2..25d9a51b4 100644 --- a/tests/cefclient/main_context_impl.h +++ b/tests/cefclient/main_context_impl.h @@ -10,10 +10,7 @@ #include "include/cef_app.h" #include "include/cef_command_line.h" #include "cefclient/main_context.h" - -#if defined(OS_WIN) || defined(OS_LINUX) #include "cefclient/root_window_manager.h" -#endif namespace client { @@ -31,9 +28,7 @@ class MainContextImpl : public MainContext { std::string GetMainURL() OVERRIDE; void PopulateSettings(CefSettings* settings) OVERRIDE; void PopulateBrowserSettings(CefBrowserSettings* settings) OVERRIDE; -#if defined(OS_WIN) || defined(OS_LINUX) RootWindowManager* GetRootWindowManager() OVERRIDE; -#endif // Initialize CEF and associated main context state. This method must be // called on the same thread that created this object. @@ -69,9 +64,7 @@ class MainContextImpl : public MainContext { CefRefPtr command_line_; std::string main_url_; -#if defined(OS_WIN) || defined(OS_LINUX) scoped_ptr root_window_manager_; -#endif // Used to verify that methods are called on the correct thread. base::ThreadChecker thread_checker_; diff --git a/tests/cefclient/osr_renderer.cc b/tests/cefclient/osr_renderer.cc index 29885d1f3..bf63788bb 100644 --- a/tests/cefclient/osr_renderer.cc +++ b/tests/cefclient/osr_renderer.cc @@ -283,6 +283,8 @@ void OsrRenderer::OnPaint(CefRefPtr browser, CefRenderHandler::RectList::const_iterator i = dirtyRects.begin(); for (; i != dirtyRects.end(); ++i) { const CefRect& rect = *i; + DCHECK(rect.x + rect.width <= view_width_); + DCHECK(rect.y + rect.height <= view_height_); glPixelStorei(GL_UNPACK_SKIP_PIXELS, rect.x); VERIFY_NO_ERROR; glPixelStorei(GL_UNPACK_SKIP_ROWS, rect.y); VERIFY_NO_ERROR; glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x, rect.y, rect.width, diff --git a/tests/cefclient/osr_widget_mac.h b/tests/cefclient/osr_widget_mac.h deleted file mode 100644 index 68fe1fe19..000000000 --- a/tests/cefclient/osr_widget_mac.h +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright (c) 2013 The Chromium Embedded Framework 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 CEF_TESTS_CEFCLIENT_OSR_WIDGET_MAC_H_ -#define CEF_TESTS_CEFCLIENT_OSR_WIDGET_MAC_H_ - -#include "include/cef_client.h" -#include "cefclient/client_handler_shared.h" - -namespace client { -class OSRBrowserProvider; -class OsrRenderer; -} - -// The client OpenGL view. -@interface ClientOpenGLView - : NSOpenGLView { -@public - NSTrackingArea* tracking_area_; - client::OSRBrowserProvider* browser_provider_; - client::OsrRenderer* renderer_; - NSPoint last_mouse_pos_; - NSPoint cur_mouse_pos_; - bool rotating_; - - bool was_last_mouse_down_on_view_; - - // Drag and drop - CefRefPtr current_drag_data_; - NSDragOperation current_drag_op_; - NSDragOperation current_allowed_ops_; - NSPasteboard* pasteboard_; - CFStringRef fileUTI_; - - // Event monitor for scroll wheel end event. - id endWheelMonitor_; -} - -- (id)initWithFrame:(NSRect)frame andTransparency:(bool)transparency - andShowUpdateRect:(bool)show_update_rect; -- (NSPoint)getClickPointForEvent:(NSEvent*)event; -- (void)getKeyEvent:(CefKeyEvent&)keyEvent forEvent:(NSEvent*)event; -- (void)getMouseEvent:(CefMouseEvent&)mouseEvent forEvent:(NSEvent*)event; -- (int)getModifiersForEvent:(NSEvent*)event; -- (BOOL)isKeyUpEvent:(NSEvent*)event; -- (BOOL)isKeyPadEvent:(NSEvent*)event; -- (CefRefPtr)getBrowser; -- (BOOL)startDragging:(CefRefPtr)drag_data - allowed_ops:(NSDragOperation)ops point:(NSPoint)p; -@end - -namespace client { - -class OSRBrowserProvider { - public: - virtual CefRefPtr GetBrowser() =0; - - protected: - virtual ~OSRBrowserProvider() {} -}; - -// Handler for off-screen rendering windows. -class ClientOSRHandler : public ClientHandlerShared::RenderHandler { - public: - explicit ClientOSRHandler(ClientOpenGLView* view, - OSRBrowserProvider* browser_provider); - ~ClientOSRHandler(); - - void Disconnect(); - - // ClientHandlerShared::RenderHandler methods - void OnBeforeClose(CefRefPtr browser) OVERRIDE; - - // CefRenderHandler methods - bool GetViewRect(CefRefPtr browser, - CefRect& rect) OVERRIDE; - bool GetScreenPoint(CefRefPtr browser, - int viewX, - int viewY, - int& screenX, - int& screenY) OVERRIDE; - bool GetScreenInfo(CefRefPtr browser, - CefScreenInfo& screen_info) OVERRIDE; - void OnPopupShow(CefRefPtr browser, - bool show) OVERRIDE; - void OnPopupSize(CefRefPtr browser, - const CefRect& rect) OVERRIDE; - void OnPaint(CefRefPtr browser, - PaintElementType type, - const RectList& dirtyRects, - const void* buffer, - int width, int height) OVERRIDE; - void OnCursorChange(CefRefPtr browser, - CefCursorHandle cursor, - CursorType type, - const CefCursorInfo& custom_cursor_info) OVERRIDE; - bool StartDragging(CefRefPtr browser, - CefRefPtr drag_data, - CefRenderHandler::DragOperationsMask allowed_ops, - int x, int y) OVERRIDE; - void UpdateDragCursor( - CefRefPtr browser, - CefRenderHandler::DragOperation operation) OVERRIDE; - - CefWindowHandle view() { return view_; } - - private: - void SetLoading(bool isLoading); - - ClientOpenGLView* view_; - - bool painting_popup_; - - // Include the default reference counting implementation. - IMPLEMENT_REFCOUNTING(ClientOSRHandler); -}; - -class OSRWindow { - public: - static CefRefPtr Create(OSRBrowserProvider* browser_provider, - bool transparent, - bool show_update_rect, - CefWindowHandle parentView, - const CefRect& frame); - - CefRefPtr GetRenderHandler() { - return render_client.get(); - } - - CefWindowHandle GetWindowHandle() { return view_; } - - private: - OSRWindow(OSRBrowserProvider* browser_provider, - bool transparent, - bool show_update_rect, - CefWindowHandle parentView, - const CefRect& frame); - ~OSRWindow(); - - CefRefPtr render_client; - CefWindowHandle view_; - - IMPLEMENT_REFCOUNTING(OSRWindow); - DISALLOW_COPY_AND_ASSIGN(OSRWindow); -}; - -} // namespace client - -#endif // CEF_TESTS_CEFCLIENT_OSR_WIDGET_MAC_H_ - diff --git a/tests/cefclient/root_window.cc b/tests/cefclient/root_window.cc new file mode 100644 index 000000000..5ccbf1ca4 --- /dev/null +++ b/tests/cefclient/root_window.cc @@ -0,0 +1,18 @@ +// Copyright (c) 2015 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +#include "cefclient/root_window.h" + +#include "cefclient/main_context.h" +#include "cefclient/root_window_manager.h" + +namespace client { + +// static +scoped_refptr GetForBrowser(int browser_id) { + return MainContext::Get()->GetRootWindowManager()->GetWindowForBrowser( + browser_id); +} + +} // namespace client diff --git a/tests/cefclient/root_window.h b/tests/cefclient/root_window.h index 9643d28f6..5d615f0fc 100644 --- a/tests/cefclient/root_window.h +++ b/tests/cefclient/root_window.h @@ -42,6 +42,16 @@ class RootWindow : // instead of calling this method directly. static scoped_refptr Create(); + // Returns the RootWindow associated with the specified |browser_id|. Must be + // called on the main thread. + static scoped_refptr GetForBrowser(int browser_id); + +#if defined(OS_MACOSX) + // Returns the RootWindow associated with the specified |window|. Must be + // called on the main thread. + static scoped_refptr GetForNSWindow(NSWindow* window); +#endif + // Initialize as a normal window. This will create and show a browser window. // This method may be called on any thread. // |delegate| must be non-NULL and outlive this object. diff --git a/tests/cefclient/root_window_gtk.cc b/tests/cefclient/root_window_gtk.cc index 6efaeaf16..23595fc80 100644 --- a/tests/cefclient/root_window_gtk.cc +++ b/tests/cefclient/root_window_gtk.cc @@ -345,8 +345,8 @@ void RootWindowGtk::OnBrowserWindowDestroyed() { if (!window_destroyed_) { // The browser was destroyed first. This could be due to the use of // off-screen rendering or execution of JavaScript window.close(). - // Close the RootWindow asynchronously. - Close(false); + // Close the RootWindow. + Close(true); } browser_destroyed_ = true; @@ -395,7 +395,7 @@ gboolean RootWindowGtk::WindowFocusIn(GtkWidget* widget, GdkEventFocus* event, RootWindowGtk* self) { if (event->in && self->browser_window_.get()) { - self->browser_window_->SetFocus(); + self->browser_window_->SetFocus(true); // Return true for a windowed browser so that focus is not passed to GTK. return self->with_osr_ ? FALSE : TRUE; } diff --git a/tests/cefclient/root_window_mac.h b/tests/cefclient/root_window_mac.h new file mode 100644 index 000000000..1c08a56a8 --- /dev/null +++ b/tests/cefclient/root_window_mac.h @@ -0,0 +1,99 @@ +// Copyright (c) 2015 The Chromium Embedded Framework 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 CEF_TESTS_CEFCLIENT_ROOT_WINDOW_MAC_H_ +#define CEF_TESTS_CEFCLIENT_ROOT_WINDOW_MAC_H_ + +#include +#include + +#include "include/base/cef_scoped_ptr.h" +#include "cefclient/browser_window.h" +#include "cefclient/root_window.h" + +namespace client { + +// OS X implementation of a top-level native window in the browser process. +// The methods of this class must be called on the main thread unless otherwise +// indicated. +class RootWindowMac : public RootWindow, + public BrowserWindow::Delegate { + public: + // Constructor may be called on any thread. + RootWindowMac(); + ~RootWindowMac(); + + // RootWindow methods. + void Init(RootWindow::Delegate* delegate, + bool with_controls, + bool with_osr, + const CefRect& rect, + const CefBrowserSettings& settings, + const std::string& url) OVERRIDE; + void InitAsPopup(RootWindow::Delegate* delegate, + bool with_controls, + bool with_osr, + const CefPopupFeatures& popupFeatures, + CefWindowInfo& windowInfo, + CefRefPtr& client, + CefBrowserSettings& settings) OVERRIDE; + void Show(ShowMode mode) OVERRIDE; + void Hide() OVERRIDE; + void SetBounds(int x, int y, size_t width, size_t height) OVERRIDE; + void Close(bool force) OVERRIDE; + CefRefPtr GetBrowser() const OVERRIDE; + ClientWindowHandle GetWindowHandle() const OVERRIDE; + + // Called by RootWindowDelegate after the associated NSWindow has been + // destroyed. + void WindowDestroyed(); + + BrowserWindow* browser_window() const { return browser_window_.get(); } + + private: + void CreateBrowserWindow(const std::string& startup_url); + void CreateRootWindow(const CefBrowserSettings& settings); + + // BrowserWindow::Delegate methods. + void OnBrowserCreated(CefRefPtr browser) OVERRIDE; + void OnBrowserWindowDestroyed() OVERRIDE; + void OnSetAddress(const std::string& url) OVERRIDE; + void OnSetTitle(const std::string& title) OVERRIDE; + void OnSetLoadingState(bool isLoading, + bool canGoBack, + bool canGoForward) OVERRIDE; + + void NotifyDestroyedIfDone(); + + // After initialization all members are only accessed on the main thread. + // Members set during initialization. + RootWindow::Delegate* delegate_; + bool with_controls_; + bool with_osr_; + bool is_popup_; + CefRect start_rect_; + scoped_ptr browser_window_; + bool initialized_; + + // Main window. + NSWindow* window_; + + // Buttons. + NSButton* back_button_; + NSButton* forward_button_; + NSButton* reload_button_; + NSButton* stop_button_; + + // URL text field. + NSTextField* url_textfield_; + + bool window_destroyed_; + bool browser_destroyed_; + + DISALLOW_COPY_AND_ASSIGN(RootWindowMac); +}; + +} // namespace client + +#endif // CEF_TESTS_CEFCLIENT_ROOT_WINDOW_MAC_H_ diff --git a/tests/cefclient/root_window_mac.mm b/tests/cefclient/root_window_mac.mm new file mode 100644 index 000000000..819ac3553 --- /dev/null +++ b/tests/cefclient/root_window_mac.mm @@ -0,0 +1,617 @@ +// Copyright (c) 2015 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +#include "cefclient/root_window_mac.h" + +#include "include/base/cef_bind.h" +#include "include/cef_app.h" +#include "include/cef_application_mac.h" +#include "cefclient/browser_window_osr_mac.h" +#include "cefclient/browser_window_std_mac.h" +#include "cefclient/client_switches.h" +#include "cefclient/main_message_loop.h" +#include "cefclient/temp_window_mac.h" + +// Receives notifications from controls and the browser window. Will delete +// itself when done. +@interface RootWindowDelegate : NSObject { + @private + NSWindow* window_; + client::RootWindowMac* root_window_; + bool force_close_; +} + +@property (nonatomic, readonly) client::RootWindowMac* root_window; +@property (nonatomic, readwrite) bool force_close; + +- (id)initWithWindow:(NSWindow*)window + andRootWindow:(client::RootWindowMac*)root_window; +- (IBAction)goBack:(id)sender; +- (IBAction)goForward:(id)sender; +- (IBAction)reload:(id)sender; +- (IBAction)stopLoading:(id)sender; +- (IBAction)takeURLStringValueFrom:(NSTextField *)sender; +@end + +@implementation RootWindowDelegate + +@synthesize root_window = root_window_; +@synthesize force_close = force_close_; + +- (id)initWithWindow:(NSWindow*)window + andRootWindow:(client::RootWindowMac*)root_window { + if (self = [super init]) { + window_ = window; + [window_ setDelegate:self]; + root_window_ = root_window; + force_close_ = false; + + // Register for application hide/unhide notifications. + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(applicationDidHide:) + name:NSApplicationDidHideNotification + object:nil]; + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(applicationDidUnhide:) + name:NSApplicationDidUnhideNotification + object:nil]; + } + return self; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; + + [super dealloc]; +} + +- (IBAction)goBack:(id)sender { + CefRefPtr browser = root_window_->GetBrowser(); + if (browser.get()) + browser->GoBack(); +} + +- (IBAction)goForward:(id)sender { + CefRefPtr browser = root_window_->GetBrowser(); + if (browser.get()) + browser->GoForward(); +} + +- (IBAction)reload:(id)sender { + CefRefPtr browser = root_window_->GetBrowser(); + if (browser.get()) + browser->Reload(); +} + +- (IBAction)stopLoading:(id)sender { + CefRefPtr browser = root_window_->GetBrowser(); + if (browser.get()) + browser->StopLoad(); +} + +- (IBAction)takeURLStringValueFrom:(NSTextField *)sender { + CefRefPtr browser = root_window_->GetBrowser(); + if (!browser.get()) + return; + + NSString *url = [sender stringValue]; + + // if it doesn't already have a prefix, add http. If we can't parse it, + // just don't bother rather than making things worse. + NSURL* tempUrl = [NSURL URLWithString:url]; + if (tempUrl && ![tempUrl scheme]) + url = [@"http://" stringByAppendingString:url]; + + std::string urlStr = [url UTF8String]; + browser->GetMainFrame()->LoadURL(urlStr); +} + +// Called when we are activated (when we gain focus). +- (void)windowDidBecomeKey:(NSNotification*)notification { + client::BrowserWindow* browser_window = root_window_->browser_window(); + if (browser_window) + browser_window->SetFocus(true); +} + +// Called when we are deactivated (when we lose focus). +- (void)windowDidResignKey:(NSNotification*)notification { + client::BrowserWindow* browser_window = root_window_->browser_window(); + if (browser_window) + browser_window->SetFocus(false); +} + +// Called when we have been minimized. +- (void)windowDidMiniaturize:(NSNotification *)notification { + client::BrowserWindow* browser_window = root_window_->browser_window(); + if (browser_window) + browser_window->Hide(); +} + +// Called when we have been unminimized. +- (void)windowDidDeminiaturize:(NSNotification *)notification { + client::BrowserWindow* browser_window = root_window_->browser_window(); + if (browser_window) + browser_window->Show(); +} + +// Called when the application has been hidden. +- (void)applicationDidHide:(NSNotification *)notification { + // If the window is miniaturized then nothing has really changed. + if (![window_ isMiniaturized]) { + client::BrowserWindow* browser_window = root_window_->browser_window(); + if (browser_window) + browser_window->Hide(); + } +} + +// Called when the application has been unhidden. +- (void)applicationDidUnhide:(NSNotification *)notification { + // If the window is miniaturized then nothing has really changed. + if (![window_ isMiniaturized]) { + client::BrowserWindow* browser_window = root_window_->browser_window(); + if (browser_window) + browser_window->Show(); + } +} + +// Called when the window is about to close. Perform the self-destruction +// sequence by getting rid of the window. By returning YES, we allow the window +// to be removed from the screen. +- (BOOL)windowShouldClose:(id)window { + if (!force_close_) { + client::BrowserWindow* browser_window = root_window_->browser_window(); + if (browser_window && !browser_window->IsClosing()) { + CefRefPtr browser = browser_window->GetBrowser(); + if (browser.get()) { + // Notify the browser window that we would like to close it. This + // will result in a call to ClientHandler::DoClose() if the + // JavaScript 'onbeforeunload' event handler allows it. + browser->GetHost()->CloseBrowser(false); + + // Cancel the close. + return NO; + } + } + } + + // Try to make the window go away. + [window autorelease]; + + // Clean ourselves up after clearing the stack of anything that might have the + // window on it. + [self performSelectorOnMainThread:@selector(cleanup:) + withObject:window + waitUntilDone:NO]; + + // Allow the close. + return YES; +} + +// Deletes itself. +- (void)cleanup:(id)window { + root_window_->WindowDestroyed(); + [self release]; +} + +@end + + +namespace client { + +namespace { + +// Sizes for URL bar layout. +#define BUTTON_HEIGHT 22 +#define BUTTON_WIDTH 72 +#define BUTTON_MARGIN 8 +#define URLBAR_HEIGHT 32 + +NSButton* MakeButton(NSRect* rect, NSString* title, NSView* parent) { + NSButton* button = [[[NSButton alloc] initWithFrame:*rect] autorelease]; + [button setTitle:title]; + [button setBezelStyle:NSSmallSquareBezelStyle]; + [button setAutoresizingMask:(NSViewMaxXMargin | NSViewMinYMargin)]; + [parent addSubview:button]; + rect->origin.x += BUTTON_WIDTH; + return button; +} + +NSRect GetScreenRectForWindow(NSWindow* window) { + NSScreen* screen = [window screen]; + if (screen == nil) + screen = [NSScreen mainScreen]; + return [screen visibleFrame]; +} + +} // namespace + +RootWindowMac::RootWindowMac() + : delegate_(NULL), + with_controls_(false), + with_osr_(false), + is_popup_(false), + initialized_(false), + window_(nil), + back_button_(nil), + forward_button_(nil), + reload_button_(nil), + stop_button_(nil), + url_textfield_(nil), + window_destroyed_(false), + browser_destroyed_(false) { +} + +RootWindowMac::~RootWindowMac() { + REQUIRE_MAIN_THREAD(); + + // The window and browser should already have been destroyed. + DCHECK(window_destroyed_); + DCHECK(browser_destroyed_); +} + +void RootWindowMac::Init(RootWindow::Delegate* delegate, + bool with_controls, + bool with_osr, + const CefRect& bounds, + const CefBrowserSettings& settings, + const std::string& url) { + DCHECK(delegate); + DCHECK(!initialized_); + + delegate_ = delegate; + with_controls_ = with_controls; + with_osr_ = with_osr; + start_rect_ = bounds; + + CreateBrowserWindow(url); + + initialized_ = true; + + // Create the native root window on the main thread. + if (CURRENTLY_ON_MAIN_THREAD()) { + CreateRootWindow(settings); + } else { + MAIN_POST_CLOSURE( + base::Bind(&RootWindowMac::CreateRootWindow, this, settings)); + } +} + +void RootWindowMac::InitAsPopup(RootWindow::Delegate* delegate, + bool with_controls, + bool with_osr, + const CefPopupFeatures& popupFeatures, + CefWindowInfo& windowInfo, + CefRefPtr& client, + CefBrowserSettings& settings) { + DCHECK(delegate); + DCHECK(!initialized_); + + delegate_ = delegate; + with_controls_ = with_controls; + with_osr_ = with_osr; + is_popup_ = true; + + if (popupFeatures.xSet) + start_rect_.x = popupFeatures.x; + if (popupFeatures.ySet) + start_rect_.y = popupFeatures.y; + if (popupFeatures.widthSet) + start_rect_.width = popupFeatures.width; + if (popupFeatures.heightSet) + start_rect_.height = popupFeatures.height; + + CreateBrowserWindow(std::string()); + + initialized_ = true; + + // The new popup is initially parented to a temporary window. The native root + // window will be created after the browser is created and the popup window + // will be re-parented to it at that time. + browser_window_->GetPopupConfig(TempWindowMac::GetWindowHandle(), + windowInfo, client, settings); +} + +void RootWindowMac::Show(ShowMode mode) { + REQUIRE_MAIN_THREAD(); + + if (!window_) + return; + + const bool is_visible = [window_ isVisible]; + const bool is_minimized = [window_ isMiniaturized]; + const bool is_maximized = [window_ isZoomed]; + + if ((mode == ShowMinimized && is_minimized) || + (mode == ShowMaximized && is_maximized) || + (mode == ShowNormal && is_visible)) { + // The window is already in the desired state. + return; + } + + // Undo the previous state since it's not the desired state. + if (is_minimized) + [window_ deminiaturize:nil]; + else if (is_maximized) + [window_ performZoom:nil]; + + // Window visibility may change after (for example) deminiaturizing the + // window. + if (![window_ isVisible]) + [window_ makeKeyAndOrderFront: nil]; + + if (mode == ShowMinimized) + [window_ performMiniaturize:nil]; + else if (mode == ShowMaximized) + [window_ performZoom:nil]; +} + +void RootWindowMac::Hide() { + REQUIRE_MAIN_THREAD(); + + if (!window_) + return; + + // Undo miniaturization, if any, so the window will actually be hidden. + if ([window_ isMiniaturized]) + [window_ deminiaturize:nil]; + + // Hide the window. + [window_ orderOut:nil]; +} + +void RootWindowMac::SetBounds(int x, int y, size_t width, size_t height) { + REQUIRE_MAIN_THREAD(); + + if (!window_) + return; + + NSRect screen_rect = GetScreenRectForWindow(window_); + + // Desired content rectangle. + NSRect content_rect; + content_rect.size.width = static_cast(width); + content_rect.size.height = static_cast(height) + + (with_controls_ ? URLBAR_HEIGHT : 0); + + // Convert to a frame rectangle. + NSRect frame_rect = [window_ frameRectForContentRect:content_rect]; + frame_rect.origin.x = x; + frame_rect.origin.y = screen_rect.size.height - y; + + [window_ setFrame:frame_rect display:YES]; +} + +void RootWindowMac::Close(bool force) { + REQUIRE_MAIN_THREAD(); + + if (window_) { + static_cast([window_ delegate]).force_close = force; + [window_ performClose:nil]; + } +} + +CefRefPtr RootWindowMac::GetBrowser() const { + REQUIRE_MAIN_THREAD(); + + if (browser_window_) + return browser_window_->GetBrowser(); + return NULL; +} + +ClientWindowHandle RootWindowMac::GetWindowHandle() const { + REQUIRE_MAIN_THREAD(); + return [window_ contentView]; +} + +void RootWindowMac::WindowDestroyed() { + window_ = nil; + window_destroyed_ = true; + NotifyDestroyedIfDone(); +} + +void RootWindowMac::CreateBrowserWindow(const std::string& startup_url) { + if (with_osr_) { + CefRefPtr command_line = + CefCommandLine::GetGlobalCommandLine(); + const bool transparent = + command_line->HasSwitch(switches::kTransparentPaintingEnabled); + const bool show_update_rect = + command_line->HasSwitch(switches::kShowUpdateRect); + browser_window_.reset(new BrowserWindowOsrMac(this, startup_url, + transparent, + show_update_rect)); + } else { + browser_window_.reset(new BrowserWindowStdMac(this, startup_url)); + } +} + +void RootWindowMac::CreateRootWindow(const CefBrowserSettings& settings) { + REQUIRE_MAIN_THREAD(); + DCHECK(!window_); + + // TODO(port): If no x,y position is specified the window will always appear + // in the upper-left corner. Maybe there's a better default place to put it? + int x = start_rect_.x; + int y = start_rect_.y; + int width, height; + if (start_rect_.IsEmpty()) { + // TODO(port): Also, maybe there's a better way to choose the default size. + width = 800; + height = 600; + } else { + width = start_rect_.width; + height = start_rect_.height; + } + + // Create the main window. + NSRect screen_rect = [[NSScreen mainScreen] visibleFrame]; + NSRect window_rect = + NSMakeRect(x, screen_rect.size.height - y, width, height); + window_ = [[UnderlayOpenGLHostingWindow alloc] + initWithContentRect:window_rect + styleMask:(NSTitledWindowMask | + NSClosableWindowMask | + NSMiniaturizableWindowMask | + NSResizableWindowMask ) + backing:NSBackingStoreBuffered + defer:NO]; + [window_ setTitle:@"cefclient"]; + + // Create the delegate for control and browser window events. + RootWindowDelegate* delegate = + [[RootWindowDelegate alloc] initWithWindow:window_ andRootWindow:this]; + + // Rely on the window delegate to clean us up rather than immediately + // releasing when the window gets closed. We use the delegate to do + // everything from the autorelease pool so the window isn't on the stack + // during cleanup (ie, a window close from javascript). + [window_ setReleasedWhenClosed:NO]; + + NSView* contentView = [window_ contentView]; + NSRect contentBounds = [contentView bounds]; + + if (with_controls_) { + // Create the buttons. + NSRect button_rect = contentBounds; + button_rect.origin.y = window_rect.size.height - URLBAR_HEIGHT + + (URLBAR_HEIGHT - BUTTON_HEIGHT) / 2; + button_rect.size.height = BUTTON_HEIGHT; + button_rect.origin.x += BUTTON_MARGIN; + button_rect.size.width = BUTTON_WIDTH; + + contentBounds.size.height -= URLBAR_HEIGHT; + + back_button_ = MakeButton(&button_rect, @"Back", contentView); + [back_button_ setTarget:delegate]; + [back_button_ setAction:@selector(goBack:)]; + [back_button_ setEnabled:NO]; + + forward_button_ = MakeButton(&button_rect, @"Forward", contentView); + [forward_button_ setTarget:delegate]; + [forward_button_ setAction:@selector(goForward:)]; + [forward_button_ setEnabled:NO]; + + reload_button_ = MakeButton(&button_rect, @"Reload", contentView); + [reload_button_ setTarget:delegate]; + [reload_button_ setAction:@selector(reload:)]; + [reload_button_ setEnabled:NO]; + + stop_button_ = MakeButton(&button_rect, @"Stop", contentView); + [stop_button_ setTarget:delegate]; + [stop_button_ setAction:@selector(stopLoading:)]; + [stop_button_ setEnabled:NO]; + + // Create the URL text field. + button_rect.origin.x += BUTTON_MARGIN; + button_rect.size.width = [contentView bounds].size.width - + button_rect.origin.x - BUTTON_MARGIN; + url_textfield_ = [[NSTextField alloc] initWithFrame:button_rect]; + [contentView addSubview:url_textfield_]; + [url_textfield_ setAutoresizingMask: + (NSViewWidthSizable | NSViewMinYMargin)]; + [url_textfield_ setTarget:delegate]; + [url_textfield_ setAction:@selector(takeURLStringValueFrom:)]; + [url_textfield_ setEnabled:NO]; + [[url_textfield_ cell] setWraps:NO]; + [[url_textfield_ cell] setScrollable:YES]; + } + + if (!is_popup_) { + // Create the browser window. + browser_window_->CreateBrowser(contentView, CefRect(0, 0, width, height), + settings); + } else { + // With popups we already have a browser window. Parent the browser window + // to the root window and show it in the correct location. + browser_window_->ShowPopup(contentView, 0, 0, contentBounds.size.width, + contentBounds.size.height); + } + + // Show the window. + Show(ShowNormal); + + // Size the window. + SetBounds(x, y, width, height); +} + +void RootWindowMac::OnBrowserCreated(CefRefPtr browser) { + REQUIRE_MAIN_THREAD(); + + // For popup browsers create the root window once the browser has been + // created. + if (is_popup_) + CreateRootWindow(CefBrowserSettings()); +} + +void RootWindowMac::OnBrowserWindowDestroyed() { + REQUIRE_MAIN_THREAD(); + + browser_window_.reset(); + + if (!window_destroyed_) { + // The browser was destroyed first. This could be due to the use of + // off-screen rendering or execution of JavaScript window.close(). + // Close the RootWindow. + Close(true); + } + + browser_destroyed_ = true; + NotifyDestroyedIfDone(); +} + +void RootWindowMac::OnSetAddress(const std::string& url) { + REQUIRE_MAIN_THREAD(); + + if (url_textfield_) { + std::string urlStr(url); + NSString* str = [NSString stringWithUTF8String:urlStr.c_str()]; + [url_textfield_ setStringValue:str]; + } +} + +void RootWindowMac::OnSetTitle(const std::string& title) { + REQUIRE_MAIN_THREAD(); + + if (window_) { + std::string titleStr(title); + NSString* str = [NSString stringWithUTF8String:titleStr.c_str()]; + [window_ setTitle:str]; + } +} + +void RootWindowMac::OnSetLoadingState(bool isLoading, + bool canGoBack, + bool canGoForward) { + REQUIRE_MAIN_THREAD(); + + if (with_controls_) { + [url_textfield_ setEnabled:YES]; + [reload_button_ setEnabled:!isLoading]; + [stop_button_ setEnabled:isLoading]; + [back_button_ setEnabled:canGoBack]; + [forward_button_ setEnabled:canGoForward]; + } +} + +void RootWindowMac::NotifyDestroyedIfDone() { + // Notify once both the window and the browser have been destroyed. + if (window_destroyed_ && browser_destroyed_) + delegate_->OnRootWindowDestroyed(this); +} + +// static +scoped_refptr RootWindow::Create() { + return new RootWindowMac(); +} + +// static +scoped_refptr RootWindow::GetForNSWindow(NSWindow* window) { + RootWindowDelegate* delegate = + static_cast([window delegate]); + return [delegate root_window]; +} + +} // namespace client diff --git a/tests/cefclient/root_window_manager.h b/tests/cefclient/root_window_manager.h index 7487b57e9..6e26f215b 100644 --- a/tests/cefclient/root_window_manager.h +++ b/tests/cefclient/root_window_manager.h @@ -15,6 +15,8 @@ #include "cefclient/temp_window_win.h" #elif defined(OS_LINUX) #include "cefclient/temp_window_x11.h" +#elif defined(OS_MACOSX) +#include "cefclient/temp_window_mac.h" #endif namespace client { @@ -83,6 +85,8 @@ class RootWindowManager : public RootWindow::Delegate { TempWindowWin temp_window_win_; #elif defined(OS_LINUX) TempWindowX11 temp_window_x11_; +#elif defined(OS_MACOSX) + TempWindowMac temp_window_mac_; #endif DISALLOW_COPY_AND_ASSIGN(RootWindowManager); diff --git a/tests/cefclient/root_window_win.cc b/tests/cefclient/root_window_win.cc index a1c09ba05..0accdd70a 100644 --- a/tests/cefclient/root_window_win.cc +++ b/tests/cefclient/root_window_win.cc @@ -512,7 +512,7 @@ void RootWindowWin::OnPaint() { void RootWindowWin::OnFocus() { if (browser_window_) - browser_window_->SetFocus(); + browser_window_->SetFocus(true); } void RootWindowWin::OnSize(bool minimized) { @@ -703,8 +703,8 @@ void RootWindowWin::OnBrowserWindowDestroyed() { if (!window_destroyed_) { // The browser was destroyed first. This could be due to the use of // off-screen rendering or execution of JavaScript window.close(). - // Close the RootWindow asynchronously. - Close(false); + // Close the RootWindow. + Close(true); } browser_destroyed_ = true; diff --git a/tests/cefclient/temp_window_mac.h b/tests/cefclient/temp_window_mac.h new file mode 100644 index 000000000..6510a820a --- /dev/null +++ b/tests/cefclient/temp_window_mac.h @@ -0,0 +1,33 @@ +// Copyright (c) 2015 The Chromium Embedded Framework 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 CEF_TESTS_CEFCLIENT_TEMP_WINDOW_MAC_H_ +#define CEF_TESTS_CEFCLIENT_TEMP_WINDOW_MAC_H_ + +#include "cefclient/client_types.h" + +namespace client { + +// Represents a singleton hidden window that acts at temporary parent for +// popup browsers. +class TempWindowMac { + public: + // Returns the singleton window handle. + static CefWindowHandle GetWindowHandle(); + + private: + // A single instance will be created/owned by RootWindowManager. + friend class RootWindowManager; + + TempWindowMac(); + ~TempWindowMac(); + + NSWindow* window_; + + DISALLOW_COPY_AND_ASSIGN(TempWindowMac); +}; + +} // namespace client + +#endif // CEF_TESTS_CEFCLIENT_TEMP_WINDOW_MAC_H_ diff --git a/tests/cefclient/temp_window_mac.mm b/tests/cefclient/temp_window_mac.mm new file mode 100644 index 000000000..84e941988 --- /dev/null +++ b/tests/cefclient/temp_window_mac.mm @@ -0,0 +1,46 @@ +// Copyright (c) 2015 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +#include "cefclient/temp_window_mac.h" + +#include + +#include "include/base/cef_logging.h" +#include "include/cef_app.h" + +namespace client { + +namespace { + +TempWindowMac* g_temp_window = NULL; + +} // namespace + +TempWindowMac::TempWindowMac() + : window_(nil) { + DCHECK(!g_temp_window); + g_temp_window = this; + + // Create a borderless non-visible 1x1 window. + window_ = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 1, 1) + styleMask:NSBorderlessWindowMask + backing:NSBackingStoreBuffered + defer:NO]; + CHECK(window_); +} + +TempWindowMac::~TempWindowMac() { + g_temp_window = NULL; + DCHECK(window_); + + [window_ close]; +} + +// static +CefWindowHandle TempWindowMac::GetWindowHandle() { + DCHECK(g_temp_window); + return [g_temp_window->window_ contentView]; +} + +} // namespace client diff --git a/tests/cefclient/temp_window_win.h b/tests/cefclient/temp_window_win.h index 545d38d82..a3c1526d3 100644 --- a/tests/cefclient/temp_window_win.h +++ b/tests/cefclient/temp_window_win.h @@ -5,7 +5,7 @@ #ifndef CEF_TESTS_CEFCLIENT_TEMP_WINDOW_WIN_H_ #define CEF_TESTS_CEFCLIENT_TEMP_WINDOW_WIN_H_ -#include "cefclient/main_message_loop.h" +#include "include/cef_base.h" namespace client { diff --git a/tests/cefclient/temp_window_x11.h b/tests/cefclient/temp_window_x11.h index 2dba6df16..b5adc6efc 100644 --- a/tests/cefclient/temp_window_x11.h +++ b/tests/cefclient/temp_window_x11.h @@ -5,7 +5,7 @@ #ifndef CEF_TESTS_CEFCLIENT_TEMP_WINDOW_X11_H_ #define CEF_TESTS_CEFCLIENT_TEMP_WINDOW_X11_H_ -#include "cefclient/main_message_loop.h" +#include "include/cef_base.h" namespace client {