macOS: Add support for building clients with ARC enabled (fixes issue #2623).

Under ARC (Automatic Reference Counting), assigning to an Objective-C
pointer has different semantics than assigning to a void* pointer.
This makes it dangerous to treat the same memory address as an
Objective-C pointer in some cases and as a "regular C pointer" in
other cases.

This change removes the conditional type defines and instead uses
void* everywhere. Explicit type casting in combination with ARC
annotations makes it safe to get typed Objective-C pointers from the
void* pointers.

This change enables ARC by default in the CEF binary distribution CMake
configuration for the cefclient and cefsimple sample applications. It can be
disabled by adding `-DOPTION_USE_ARC=Off` to the CMake command line.

ARC is not supported when building Chromium due to the substantial
number of changes that would be required in the Chromium code base.
This commit is contained in:
Jesper Papmehl-Dufay 2019-04-23 17:17:56 +00:00 committed by Marshall Greenblatt
parent 491253fa03
commit 019611c764
22 changed files with 1414 additions and 980 deletions

View File

@ -37,29 +37,37 @@
#include "include/internal/cef_string.h"
// Handle types.
#ifdef __cplusplus
#ifdef __OBJC__
@class NSCursor;
@class NSEvent;
@class NSView;
#else
class NSCursor;
class NSEvent;
struct NSView;
#endif
#define cef_cursor_handle_t NSCursor*
#define cef_event_handle_t NSEvent*
#define cef_window_handle_t NSView*
#else
// Actually NSCursor*
#define cef_cursor_handle_t void*
// Acutally NSEvent*
#define cef_event_handle_t void*
// Actually NSView*
#define cef_window_handle_t void*
#endif
#define kNullCursorHandle NULL
#define kNullEventHandle NULL
#define kNullWindowHandle NULL
#ifdef __OBJC__
#if __has_feature(objc_arc)
#define CAST_CEF_CURSOR_HANDLE_TO_NSCURSOR(handle) ((__bridge NSCursor*)handle)
#define CAST_CEF_EVENT_HANDLE_TO_NSEVENT(handle) ((__bridge NSEvent*)handle)
#define CAST_CEF_WINDOW_HANDLE_TO_NSVIEW(handle) ((__bridge NSView*)handle)
#define CAST_NSCURSOR_TO_CEF_CURSOR_HANDLE(cursor) ((__bridge void*)cursor)
#define CAST_NSEVENT_TO_CEF_EVENT_HANDLE(event) ((__bridge void*)event)
#define CAST_NSVIEW_TO_CEF_WINDOW_HANDLE(view) ((__bridge void*)view)
#else // __has_feature(objc_arc)
#define CAST_CEF_CURSOR_HANDLE_TO_NSCURSOR(handle) ((NSCursor*)handle)
#define CAST_CEF_EVENT_HANDLE_TO_NSEVENT(handle) ((NSEvent*)handle)
#define CAST_CEF_WINDOW_HANDLE_TO_NSVIEW(handle) ((NSView*)handle)
#define CAST_NSCURSOR_TO_CEF_CURSOR_HANDLE(cursor) ((void*)cursor)
#define CAST_NSEVENT_TO_CEF_EVENT_HANDLE(event) ((void*)event)
#define CAST_NSVIEW_TO_CEF_WINDOW_HANDLE(view) ((void*)view)
#endif // __has_feature(objc_arc)
#endif // __OBJC__
#ifdef __cplusplus
extern "C" {
#endif

View File

@ -56,7 +56,7 @@
@end
// Receives notifications from the browser window. Will delete itself when done.
@interface CefWindowDelegate : NSObject<NSWindowDelegate> {
@interface CefWindowDelegate : NSObject <NSWindowDelegate> {
@private
CefBrowserHostImpl* browser_; // weak
NSWindow* window_;
@ -165,7 +165,8 @@ bool CefBrowserPlatformDelegateNativeMac::CreateHostWindow() {
NSWindow* newWnd = nil;
NSView* parentView = window_info_.parent_view;
NSView* parentView =
CAST_CEF_WINDOW_HANDLE_TO_NSVIEW(window_info_.parent_view);
NSRect contentRect = {{window_info_.x, window_info_.y},
{window_info_.width, window_info_.height}};
if (parentView == nil) {
@ -239,9 +240,9 @@ bool CefBrowserPlatformDelegateNativeMac::CreateHostWindow() {
}
void CefBrowserPlatformDelegateNativeMac::CloseHostWindow() {
if (window_info_.view != nil) {
[[window_info_.view window]
performSelectorOnMainThread:@selector(performClose:)
NSView* nsview = CAST_CEF_WINDOW_HANDLE_TO_NSVIEW(window_info_.view);
if (nsview != nil) {
[[nsview window] performSelectorOnMainThread:@selector(performClose:)
withObject:nil
waitUntilDone:NO];
}
@ -275,7 +276,7 @@ gfx::Point CefBrowserPlatformDelegateNativeMac::GetScreenPoint(
if (windowless_handler_)
return windowless_handler_->GetParentScreenPoint(view);
NSView* nsview = window_info_.parent_view;
NSView* nsview = CAST_CEF_WINDOW_HANDLE_TO_NSVIEW(window_info_.parent_view);
if (nsview) {
NSRect bounds = [nsview bounds];
NSPoint view_pt = {view.x(), bounds.size.height - view.y()};
@ -336,8 +337,8 @@ void CefBrowserPlatformDelegateNativeMac::TranslateKeyEvent(
[[[NSString alloc] initWithCharacters:&key_event.unmodified_character
length:1] autorelease];
NSString* characters =
[[[NSString alloc] initWithCharacters:&key_event.character length:1]
autorelease];
[[[NSString alloc] initWithCharacters:&key_event.character
length:1] autorelease];
NSEvent* synthetic_event =
[NSEvent keyEventWithType:event_type

View File

@ -387,7 +387,7 @@ void CefFileDialogRunnerMac::Run(CefBrowserHostImpl* browser,
const FileChooserParams& params,
RunFileChooserCallback callback) {
int filter_index = params.selected_accept_filter;
NSView* owner = browser->GetWindowHandle();
NSView* owner = CAST_CEF_WINDOW_HANDLE_TO_NSVIEW(browser->GetWindowHandle());
if (params.mode == blink::mojom::FileChooserParams::Mode::kOpen ||
params.mode == blink::mojom::FileChooserParams::Mode::kOpenMultiple ||

View File

@ -152,6 +152,16 @@ endif()
#
if(OS_MACOSX)
option(OPTION_USE_ARC "Build with ARC (automatic Reference Counting) on macOS." ON)
if(OPTION_USE_ARC)
list(APPEND CEF_COMPILER_FLAGS
-fobjc-arc
)
set_target_properties(${target} PROPERTIES
CLANG_ENABLE_OBJC_ARC "YES"
)
endif()
# All sources required by the "cefclient" target. Generates an app bundle that
# is used only for the browser process.
set(CEFCLIENT_SRCS

View File

@ -13,6 +13,8 @@
namespace client {
class BrowserWindowOsrMacImpl;
// 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.
@ -88,17 +90,11 @@ class BrowserWindowOsrMac : public BrowserWindow,
void UpdateAccessibilityLocation(CefRefPtr<CefValue> value) 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_;
scoped_ptr<BrowserWindowOsrMacImpl> impl_;
DISALLOW_COPY_AND_ASSIGN(BrowserWindowOsrMac);
friend class BrowserWindowOsrMacImpl;
};
} // namespace client

View File

@ -21,17 +21,6 @@
#import <AppKit/NSAccessibility.h>
namespace {
CefTextInputClientOSRMac* GetInputClientFromContext(
const NSTextInputContext* context) {
if (!context)
return NULL;
return reinterpret_cast<CefTextInputClientOSRMac*>([context client]);
}
} // namespace
@interface BrowserOpenGLView
: NSOpenGLView <NSDraggingSource, NSDraggingDestination, NSAccessibility> {
@private
@ -51,10 +40,11 @@ CefTextInputClientOSRMac* GetInputClientFromContext(
NSDragOperation current_drag_op_;
NSDragOperation current_allowed_ops_;
NSPasteboard* pasteboard_;
CFStringRef fileUTI_;
NSString* fileUTI_;
// For intreacting with IME.
NSTextInputContext* text_input_context_osr_mac_;
CefTextInputClientOSRMac* text_input_client_;
// Manages Accessibility Tree
client::OsrAccessibilityHelper* accessibility_helper_;
@ -63,54 +53,7 @@ CefTextInputClientOSRMac* GetInputClientFromContext(
id endWheelMonitor_;
}
- (id)initWithFrame:(NSRect)frame
andBrowserWindow:(client::BrowserWindowOsrMac*)browser_window
andRenderer:(client::OsrRenderer*)renderer;
- (void)detach;
- (CefRefPtr<CefBrowser>)getBrowser;
- (NSPoint)getClickPointForEvent:(NSEvent*)event;
- (void)getKeyEvent:(CefKeyEvent&)keyEvent forEvent:(NSEvent*)event;
- (void)getMouseEvent:(CefMouseEvent&)mouseEvent forEvent:(NSEvent*)event;
- (void)getMouseEvent:(CefMouseEvent&)mouseEvent
forDragInfo:(id<NSDraggingInfo>)info;
- (int)getModifiersForEvent:(NSEvent*)event;
- (BOOL)isKeyUpEvent:(NSEvent*)event;
- (BOOL)isKeyPadEvent:(NSEvent*)event;
- (BOOL)startDragging:(CefRefPtr<CefDragData>)drag_data
allowedOps:(NSDragOperation)ops
point:(NSPoint)p;
- (void)setCurrentDragOp:(NSDragOperation)op;
- (void)resetDragDrop;
- (void)fillPasteboard;
- (void)populateDropData:(CefRefPtr<CefDragData>)data
fromPasteboard:(NSPasteboard*)pboard;
- (NSPoint)flipWindowPointToView:(const NSPoint&)windowPoint;
- (void)resetDeviceScaleFactor;
- (void)setDeviceScaleFactor:(float)device_scale_factor;
- (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;
- (NSPoint)convertPointFromBackingInternal:(NSPoint)aPoint;
- (NSPoint)convertPointToBackingInternal:(NSPoint)aPoint;
- (NSRect)convertRectFromBackingInternal:(NSRect)aRect;
- (NSRect)convertRectToBackingInternal:(NSRect)aRect;
- (void)ChangeCompositionRange:(CefRange)range
character_bounds:
(const CefRenderHandler::RectList&)character_bounds;
- (void)UpdateAccessibilityTree:(CefRefPtr<CefValue>)value;
- (void)UpdateAccessibilityLocation:(CefRefPtr<CefValue>)value;
@end
@end // @interface BrowserOpenGLView
namespace {
@ -135,10 +78,6 @@ class ScopedGLContext {
const bool swap_buffers_;
};
BrowserOpenGLView* GLView(NSView* view) {
return static_cast<BrowserOpenGLView*>(view);
}
NSPoint ConvertPointFromWindowToScreen(NSWindow* window, NSPoint point) {
NSRect point_rect = NSMakeRect(point.x, point.y, 0, 0);
return [window convertRectToScreen:point_rect].origin;
@ -155,7 +94,9 @@ NSPoint ConvertPointFromWindowToScreen(NSWindow* window, NSPoint point) {
initWithAttributes:(NSOpenGLPixelFormatAttribute[]){
NSOpenGLPFADoubleBuffer, NSOpenGLPFADepthSize, 32,
0}];
#if !__has_feature(objc_arc)
[pixelFormat autorelease];
#endif // !__has_feature(objc_arc)
if (self = [super initWithFrame:frame pixelFormat:pixelFormat]) {
browser_window_ = browser_window;
@ -191,20 +132,20 @@ NSPoint ConvertPointFromWindowToScreen(NSWindow* window, NSPoint point) {
removeObserver:self
name:NSWindowDidChangeBackingPropertiesNotification
object:nil];
#if !__has_feature(objc_arc)
if (text_input_context_osr_mac_) {
[GetInputClientFromContext(text_input_context_osr_mac_) release];
[text_input_client_ release];
[text_input_context_osr_mac_ release];
}
[super dealloc];
#endif // !__has_feature(objc_arc)
}
- (void)detach {
renderer_ = NULL;
browser_window_ = NULL;
if (text_input_context_osr_mac_)
[GetInputClientFromContext(text_input_context_osr_mac_) detach];
if (text_input_client_)
[text_input_client_ detach];
}
- (CefRefPtr<CefBrowser>)getBrowser {
@ -344,11 +285,8 @@ NSPoint ConvertPointFromWindowToScreen(NSWindow* window, NSPoint point) {
return;
if ([event type] != NSFlagsChanged) {
CefTextInputClientOSRMac* client =
GetInputClientFromContext(text_input_context_osr_mac_);
if (client) {
[client HandleKeyEventBeforeTextInputClient:event];
if (text_input_client_) {
[text_input_client_ HandleKeyEventBeforeTextInputClient:event];
// The return value of this method seems to always be set to YES, thus we
// ignore it and ask the host view whether IME is active or not.
@ -357,7 +295,7 @@ NSPoint ConvertPointFromWindowToScreen(NSWindow* window, NSPoint point) {
CefKeyEvent keyEvent;
[self getKeyEvent:keyEvent forEvent:event];
[client HandleKeyEventAfterTextInputClient:keyEvent];
[text_input_client_ HandleKeyEventAfterTextInputClient:keyEvent];
}
}
@ -640,12 +578,14 @@ NSPoint ConvertPointFromWindowToScreen(NSWindow* window, NSPoint point) {
- (NSTextInputContext*)inputContext {
if (!text_input_context_osr_mac_) {
CefTextInputClientOSRMac* text_input_client =
[[[CefTextInputClientOSRMac alloc] initWithBrowser:[self getBrowser]]
retain];
text_input_client_ =
[[CefTextInputClientOSRMac alloc] initWithBrowser:[self getBrowser]];
text_input_context_osr_mac_ =
[[[NSTextInputContext alloc] initWithClient:text_input_client] retain];
[[NSTextInputContext alloc] initWithClient:text_input_client_];
#if !__has_feature(objc_arc)
[text_input_client_ retain];
[text_input_context_osr_mac_ retain];
#endif // !__has_feature(objc_arc)
}
return text_input_context_osr_mac_;
@ -1028,7 +968,7 @@ NSPoint ConvertPointFromWindowToScreen(NSWindow* window, NSPoint point) {
[pboard setString:strTitle forType:kNSURLTitlePboardType];
// File contents.
} else if ([type isEqualToString:(NSString*)fileUTI_]) {
} else if ([type isEqualToString:fileUTI_]) {
size_t size = current_drag_data_->GetFileContents(NULL);
DCHECK_GT(size, 0U);
CefRefPtr<client::BytesWriteHandler> handler =
@ -1040,7 +980,7 @@ NSPoint ConvertPointFromWindowToScreen(NSWindow* window, NSPoint point) {
[pboard setData:[NSData dataWithBytes:handler->GetData()
length:handler->GetDataSize()]
forType:(NSString*)fileUTI_];
forType:fileUTI_];
// Plain text.
} else if ([type isEqualToString:NSStringPboardType]) {
@ -1084,7 +1024,8 @@ NSPoint ConvertPointFromWindowToScreen(NSWindow* window, NSPoint point) {
client::OsrAXNode* node = accessibility_helper_->GetRootNode();
// Add Root as first Kid
NSMutableArray* kids = [NSMutableArray arrayWithCapacity:1];
NSObject* child = node->GetNativeAccessibleObject(NULL);
NSObject* child = CAST_CEF_NATIVE_ACCESSIBLE_TO_NSOBJECT(
node->GetNativeAccessibleObject(NULL));
[kids addObject:child];
return NSAccessibilityUnignoredChildren(kids);
} else {
@ -1095,7 +1036,9 @@ NSPoint ConvertPointFromWindowToScreen(NSWindow* window, NSPoint point) {
- (id)accessibilityFocusedUIElement {
if (accessibility_helper_) {
client::OsrAXNode* node = accessibility_helper_->GetFocusedNode();
return node ? node->GetNativeAccessibleObject(NULL) : nil;
return node ? CAST_CEF_NATIVE_ACCESSIBLE_TO_NSOBJECT(
node->GetNativeAccessibleObject(NULL))
: nil;
}
return nil;
}
@ -1106,18 +1049,25 @@ NSPoint ConvertPointFromWindowToScreen(NSWindow* window, NSPoint point) {
current_allowed_ops_ = NSDragOperationNone;
current_drag_data_ = NULL;
if (fileUTI_) {
CFRelease(fileUTI_);
fileUTI_ = NULL;
#if !__has_feature(objc_arc)
[fileUTI_ release];
#endif // !__has_feature(objc_arc)
fileUTI_ = nil;
}
if (pasteboard_) {
#if !__has_feature(objc_arc)
[pasteboard_ release];
#endif // !__has_feature(objc_arc)
pasteboard_ = nil;
}
}
- (void)fillPasteboard {
DCHECK(!pasteboard_);
pasteboard_ = [[NSPasteboard pasteboardWithName:NSDragPboard] retain];
pasteboard_ = [NSPasteboard pasteboardWithName:NSDragPboard];
#if !__has_feature(objc_arc)
[pasteboard_ retain];
#endif // !__has_feature(objc_arc)
[pasteboard_ declareTypes:@[ kCEFDragDummyPboardType ] owner:self];
@ -1146,11 +1096,11 @@ NSPoint ConvertPointFromWindowToScreen(NSWindow* window, NSPoint point) {
mimeTypeCF = CFStringCreateWithCString(kCFAllocatorDefault,
mimeType.ToString().c_str(),
kCFStringEncodingUTF8);
fileUTI_ = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType,
mimeTypeCF, NULL);
fileUTI_ = (__bridge NSString*)UTTypeCreatePreferredIdentifierForTag(
kUTTagClassMIMEType, mimeTypeCF, NULL);
CFRelease(mimeTypeCF);
// File (HFS) promise.
NSArray* fileUTIList = @[ (NSString*)fileUTI_ ];
NSArray* fileUTIList = @[ fileUTI_ ];
[pasteboard_ addTypes:@[ NSFilesPromisePboardType ] owner:self];
[pasteboard_ setPropertyList:fileUTIList
forType:NSFilesPromisePboardType];
@ -1287,10 +1237,8 @@ NSPoint ConvertPointFromWindowToScreen(NSWindow* window, NSPoint point) {
- (void)ChangeCompositionRange:(CefRange)range
character_bounds:(const CefRenderHandler::RectList&)bounds {
CefTextInputClientOSRMac* client =
GetInputClientFromContext(text_input_context_osr_mac_);
if (client)
[client ChangeCompositionRange:range character_bounds:bounds];
if (text_input_client_)
[text_input_client_ ChangeCompositionRange:range character_bounds:bounds];
}
- (void)UpdateAccessibilityTree:(CefRefPtr<CefValue>)value {
@ -1323,25 +1271,106 @@ NSPoint ConvertPointFromWindowToScreen(NSWindow* window, NSPoint point) {
namespace client {
BrowserWindowOsrMac::BrowserWindowOsrMac(BrowserWindow::Delegate* delegate,
class BrowserWindowOsrMacImpl {
public:
BrowserWindowOsrMacImpl(BrowserWindow::Delegate* delegate,
const std::string& startup_url,
const OsrRendererSettings& settings)
: BrowserWindow(delegate),
renderer_(settings),
nsview_(NULL),
hidden_(false),
painting_popup_(false) {
client_handler_ = new ClientHandlerOsr(this, this, startup_url);
}
const OsrRendererSettings& settings,
BrowserWindowOsrMac& browser_window);
~BrowserWindowOsrMacImpl();
BrowserWindowOsrMac::~BrowserWindowOsrMac() {
if (nsview_) {
// BrowserWindow methods.
void CreateBrowser(ClientWindowHandle parent_handle,
const CefRect& rect,
const CefBrowserSettings& settings,
CefRefPtr<CefRequestContext> request_context);
void GetPopupConfig(CefWindowHandle temp_handle,
CefWindowInfo& windowInfo,
CefRefPtr<CefClient>& client,
CefBrowserSettings& settings);
void ShowPopup(ClientWindowHandle parent_handle,
int x,
int y,
size_t width,
size_t height);
void Show();
void Hide();
void SetBounds(int x, int y, size_t width, size_t height);
void SetFocus(bool focus);
void SetDeviceScaleFactor(float device_scale_factor);
float GetDeviceScaleFactor() const;
ClientWindowHandle GetWindowHandle() const;
// ClientHandlerOsr::OsrDelegate methods.
void OnAfterCreated(CefRefPtr<CefBrowser> browser);
void OnBeforeClose(CefRefPtr<CefBrowser> browser);
bool GetRootScreenRect(CefRefPtr<CefBrowser> browser, CefRect& rect);
void GetViewRect(CefRefPtr<CefBrowser> browser, CefRect& rect);
bool GetScreenPoint(CefRefPtr<CefBrowser> browser,
int viewX,
int viewY,
int& screenX,
int& screenY);
bool GetScreenInfo(CefRefPtr<CefBrowser> browser, CefScreenInfo& screen_info);
void OnPopupShow(CefRefPtr<CefBrowser> browser, bool show);
void OnPopupSize(CefRefPtr<CefBrowser> browser, const CefRect& rect);
void OnPaint(CefRefPtr<CefBrowser> browser,
CefRenderHandler::PaintElementType type,
const CefRenderHandler::RectList& dirtyRects,
const void* buffer,
int width,
int height);
void OnCursorChange(CefRefPtr<CefBrowser> browser,
CefCursorHandle cursor,
CefRenderHandler::CursorType type,
const CefCursorInfo& custom_cursor_info);
bool StartDragging(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefDragData> drag_data,
CefRenderHandler::DragOperationsMask allowed_ops,
int x,
int y);
void UpdateDragCursor(CefRefPtr<CefBrowser> browser,
CefRenderHandler::DragOperation operation);
void OnImeCompositionRangeChanged(
CefRefPtr<CefBrowser> browser,
const CefRange& selection_range,
const CefRenderHandler::RectList& character_bounds);
void UpdateAccessibilityTree(CefRefPtr<CefValue> value);
void UpdateAccessibilityLocation(CefRefPtr<CefValue> value);
private:
// Create the NSView.
void Create(ClientWindowHandle parent_handle, const CefRect& rect);
BrowserWindowOsrMac& browser_window_;
// The below members will only be accessed on the main thread which should be
// the same as the CEF UI thread.
OsrRenderer renderer_;
BrowserOpenGLView* native_browser_view_;
bool hidden_;
bool painting_popup_;
};
BrowserWindowOsrMacImpl::BrowserWindowOsrMacImpl(
BrowserWindow::Delegate* delegate,
const std::string& startup_url,
const OsrRendererSettings& settings,
BrowserWindowOsrMac& browser_window)
: browser_window_(browser_window),
renderer_(settings),
native_browser_view_(nil),
hidden_(false),
painting_popup_(false) {}
BrowserWindowOsrMacImpl::~BrowserWindowOsrMacImpl() {
if (native_browser_view_) {
// Disassociate the view with |this|.
[GLView(nsview_) detach];
[native_browser_view_ detach];
}
}
void BrowserWindowOsrMac::CreateBrowser(
void BrowserWindowOsrMacImpl::CreateBrowser(
ClientWindowHandle parent_handle,
const CefRect& rect,
const CefBrowserSettings& settings,
@ -1352,31 +1381,32 @@ void BrowserWindowOsrMac::CreateBrowser(
Create(parent_handle, rect);
CefWindowInfo window_info;
window_info.SetAsWindowless(nsview_);
window_info.SetAsWindowless(
CAST_NSVIEW_TO_CEF_WINDOW_HANDLE(native_browser_view_));
// Create the browser asynchronously.
CefBrowserHost::CreateBrowser(window_info, client_handler_,
client_handler_->startup_url(), settings,
request_context);
CefBrowserHost::CreateBrowser(window_info, browser_window_.client_handler_,
browser_window_.client_handler_->startup_url(),
settings, request_context);
}
void BrowserWindowOsrMac::GetPopupConfig(CefWindowHandle temp_handle,
void BrowserWindowOsrMacImpl::GetPopupConfig(CefWindowHandle temp_handle,
CefWindowInfo& windowInfo,
CefRefPtr<CefClient>& client,
CefBrowserSettings& settings) {
CEF_REQUIRE_UI_THREAD();
windowInfo.SetAsWindowless(temp_handle);
client = client_handler_;
client = browser_window_.client_handler_;
}
void BrowserWindowOsrMac::ShowPopup(ClientWindowHandle parent_handle,
void BrowserWindowOsrMacImpl::ShowPopup(ClientWindowHandle parent_handle,
int x,
int y,
size_t width,
size_t height) {
REQUIRE_MAIN_THREAD();
DCHECK(browser_.get());
DCHECK(browser_window_.browser_.get());
// Create the native NSView.
Create(parent_handle,
@ -1384,107 +1414,111 @@ void BrowserWindowOsrMac::ShowPopup(ClientWindowHandle parent_handle,
// Send resize notification so the compositor is assigned the correct
// viewport size and begins rendering.
browser_->GetHost()->WasResized();
browser_window_.browser_->GetHost()->WasResized();
Show();
}
void BrowserWindowOsrMac::Show() {
void BrowserWindowOsrMacImpl::Show() {
REQUIRE_MAIN_THREAD();
if (hidden_) {
// Set the browser as visible.
browser_->GetHost()->WasHidden(false);
browser_window_.browser_->GetHost()->WasHidden(false);
hidden_ = false;
}
// Give focus to the browser.
browser_->GetHost()->SendFocusEvent(true);
browser_window_.browser_->GetHost()->SendFocusEvent(true);
}
void BrowserWindowOsrMac::Hide() {
void BrowserWindowOsrMacImpl::Hide() {
REQUIRE_MAIN_THREAD();
if (!browser_.get())
if (!browser_window_.browser_.get())
return;
// Remove focus from the browser.
browser_->GetHost()->SendFocusEvent(false);
browser_window_.browser_->GetHost()->SendFocusEvent(false);
if (!hidden_) {
// Set the browser as hidden.
browser_->GetHost()->WasHidden(true);
browser_window_.browser_->GetHost()->WasHidden(true);
hidden_ = true;
}
}
void BrowserWindowOsrMac::SetBounds(int x, int y, size_t width, size_t height) {
void BrowserWindowOsrMacImpl::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) {
void BrowserWindowOsrMacImpl::SetFocus(bool focus) {
REQUIRE_MAIN_THREAD();
if (nsview_)
[[nsview_ window] makeFirstResponder:nsview_];
if (native_browser_view_)
[native_browser_view_.window makeFirstResponder:native_browser_view_];
}
void BrowserWindowOsrMac::SetDeviceScaleFactor(float device_scale_factor) {
void BrowserWindowOsrMacImpl::SetDeviceScaleFactor(float device_scale_factor) {
REQUIRE_MAIN_THREAD();
if (nsview_)
[GLView(nsview_) setDeviceScaleFactor:device_scale_factor];
if (native_browser_view_)
[native_browser_view_ setDeviceScaleFactor:device_scale_factor];
}
float BrowserWindowOsrMac::GetDeviceScaleFactor() const {
float BrowserWindowOsrMacImpl::GetDeviceScaleFactor() const {
REQUIRE_MAIN_THREAD();
if (nsview_)
return [GLView(nsview_) getDeviceScaleFactor];
if (native_browser_view_)
return [native_browser_view_ getDeviceScaleFactor];
return 1.0f;
}
ClientWindowHandle BrowserWindowOsrMac::GetWindowHandle() const {
ClientWindowHandle BrowserWindowOsrMacImpl::GetWindowHandle() const {
REQUIRE_MAIN_THREAD();
return nsview_;
return CAST_NSVIEW_TO_CEF_WINDOW_HANDLE(native_browser_view_);
}
void BrowserWindowOsrMac::OnAfterCreated(CefRefPtr<CefBrowser> browser) {
void BrowserWindowOsrMacImpl::OnAfterCreated(CefRefPtr<CefBrowser> browser) {
CEF_REQUIRE_UI_THREAD();
}
void BrowserWindowOsrMac::OnBeforeClose(CefRefPtr<CefBrowser> browser) {
void BrowserWindowOsrMacImpl::OnBeforeClose(CefRefPtr<CefBrowser> browser) {
CEF_REQUIRE_UI_THREAD();
REQUIRE_MAIN_THREAD();
// Detach |this| from the ClientHandlerOsr.
static_cast<ClientHandlerOsr*>(client_handler_.get())->DetachOsrDelegate();
static_cast<ClientHandlerOsr*>(browser_window_.client_handler_.get())
->DetachOsrDelegate();
}
bool BrowserWindowOsrMac::GetRootScreenRect(CefRefPtr<CefBrowser> browser,
bool BrowserWindowOsrMacImpl::GetRootScreenRect(CefRefPtr<CefBrowser> browser,
CefRect& rect) {
CEF_REQUIRE_UI_THREAD();
return false;
}
void BrowserWindowOsrMac::GetViewRect(CefRefPtr<CefBrowser> browser,
void BrowserWindowOsrMacImpl::GetViewRect(CefRefPtr<CefBrowser> browser,
CefRect& rect) {
CEF_REQUIRE_UI_THREAD();
REQUIRE_MAIN_THREAD();
rect.x = rect.y = 0;
if (!nsview_) {
if (!native_browser_view_) {
// Never return an empty rectangle.
rect.width = rect.height = 1;
return;
}
const float device_scale_factor = [GLView(nsview_) getDeviceScaleFactor];
const float device_scale_factor = [native_browser_view_ getDeviceScaleFactor];
// |bounds| is in OS X view coordinates.
NSRect bounds = [nsview_ bounds];
NSRect bounds = native_browser_view_.bounds;
// Convert to device coordinates.
bounds = [GLView(nsview_) convertRectToBackingInternal:bounds];
bounds = [native_browser_view_ convertRectToBackingInternal:bounds];
// Convert to browser view coordinates.
rect.width = DeviceToLogical(bounds.size.width, device_scale_factor);
@ -1495,7 +1529,7 @@ void BrowserWindowOsrMac::GetViewRect(CefRefPtr<CefBrowser> browser,
rect.height = 1;
}
bool BrowserWindowOsrMac::GetScreenPoint(CefRefPtr<CefBrowser> browser,
bool BrowserWindowOsrMacImpl::GetScreenPoint(CefRefPtr<CefBrowser> browser,
int viewX,
int viewY,
int& screenX,
@ -1503,10 +1537,10 @@ bool BrowserWindowOsrMac::GetScreenPoint(CefRefPtr<CefBrowser> browser,
CEF_REQUIRE_UI_THREAD();
REQUIRE_MAIN_THREAD();
if (!nsview_)
if (!native_browser_view_)
return false;
const float device_scale_factor = [GLView(nsview_) getDeviceScaleFactor];
const float device_scale_factor = [native_browser_view_ getDeviceScaleFactor];
// (viewX, viewX) is in browser view coordinates.
// Convert to device coordinates.
@ -1514,34 +1548,34 @@ bool BrowserWindowOsrMac::GetScreenPoint(CefRefPtr<CefBrowser> browser,
LogicalToDevice(viewY, device_scale_factor));
// Convert to OS X view coordinates.
view_pt = [GLView(nsview_) convertPointFromBackingInternal:view_pt];
view_pt = [native_browser_view_ convertPointFromBackingInternal:view_pt];
// Reverse the Y component.
const NSRect bounds = [nsview_ bounds];
const NSRect bounds = native_browser_view_.bounds;
view_pt.y = bounds.size.height - view_pt.y;
// Convert to screen coordinates.
NSPoint window_pt = [nsview_ convertPoint:view_pt toView:nil];
NSPoint window_pt = [native_browser_view_ convertPoint:view_pt toView:nil];
NSPoint screen_pt =
ConvertPointFromWindowToScreen([nsview_ window], window_pt);
ConvertPointFromWindowToScreen(native_browser_view_.window, window_pt);
screenX = screen_pt.x;
screenY = screen_pt.y;
return true;
}
bool BrowserWindowOsrMac::GetScreenInfo(CefRefPtr<CefBrowser> browser,
bool BrowserWindowOsrMacImpl::GetScreenInfo(CefRefPtr<CefBrowser> browser,
CefScreenInfo& screen_info) {
CEF_REQUIRE_UI_THREAD();
REQUIRE_MAIN_THREAD();
if (!nsview_)
if (!native_browser_view_)
return false;
CefRect view_rect;
GetViewRect(browser, view_rect);
screen_info.device_scale_factor = [GLView(nsview_) getDeviceScaleFactor];
screen_info.device_scale_factor = [native_browser_view_ getDeviceScaleFactor];
// The screen info rectangles are used by the renderer to create and position
// popups. Keep popups inside the view rectangle.
@ -1551,12 +1585,12 @@ bool BrowserWindowOsrMac::GetScreenInfo(CefRefPtr<CefBrowser> browser,
return true;
}
void BrowserWindowOsrMac::OnPopupShow(CefRefPtr<CefBrowser> browser,
void BrowserWindowOsrMacImpl::OnPopupShow(CefRefPtr<CefBrowser> browser,
bool show) {
CEF_REQUIRE_UI_THREAD();
REQUIRE_MAIN_THREAD();
if (!nsview_)
if (!native_browser_view_)
return;
if (!show) {
@ -1566,15 +1600,15 @@ void BrowserWindowOsrMac::OnPopupShow(CefRefPtr<CefBrowser> browser,
renderer_.OnPopupShow(browser, show);
}
void BrowserWindowOsrMac::OnPopupSize(CefRefPtr<CefBrowser> browser,
void BrowserWindowOsrMacImpl::OnPopupSize(CefRefPtr<CefBrowser> browser,
const CefRect& rect) {
CEF_REQUIRE_UI_THREAD();
REQUIRE_MAIN_THREAD();
if (!nsview_)
if (!native_browser_view_)
return;
const float device_scale_factor = [GLView(nsview_) getDeviceScaleFactor];
const float device_scale_factor = [native_browser_view_ getDeviceScaleFactor];
// |rect| is in browser view coordinates. Convert to device coordinates.
CefRect device_rect = LogicalToDevice(rect, device_scale_factor);
@ -1582,7 +1616,8 @@ void BrowserWindowOsrMac::OnPopupSize(CefRefPtr<CefBrowser> browser,
renderer_.OnPopupSize(browser, device_rect);
}
void BrowserWindowOsrMac::OnPaint(CefRefPtr<CefBrowser> browser,
void BrowserWindowOsrMacImpl::OnPaint(
CefRefPtr<CefBrowser> browser,
CefRenderHandler::PaintElementType type,
const CefRenderHandler::RectList& dirtyRects,
const void* buffer,
@ -1591,7 +1626,7 @@ void BrowserWindowOsrMac::OnPaint(CefRefPtr<CefBrowser> browser,
CEF_REQUIRE_UI_THREAD();
REQUIRE_MAIN_THREAD();
if (!nsview_)
if (!native_browser_view_)
return;
if (width <= 2 && height <= 2) {
@ -1604,7 +1639,7 @@ void BrowserWindowOsrMac::OnPaint(CefRefPtr<CefBrowser> browser,
return;
}
ScopedGLContext scoped_gl_context(GLView(nsview_), true);
ScopedGLContext scoped_gl_context(native_browser_view_, true);
renderer_.OnPaint(browser, type, dirtyRects, buffer, width, height);
if (type == PET_VIEW && !renderer_.popup_rect().IsEmpty()) {
@ -1615,7 +1650,7 @@ void BrowserWindowOsrMac::OnPaint(CefRefPtr<CefBrowser> browser,
renderer_.Render();
}
void BrowserWindowOsrMac::OnCursorChange(
void BrowserWindowOsrMacImpl::OnCursorChange(
CefRefPtr<CefBrowser> browser,
CefCursorHandle cursor,
CefRenderHandler::CursorType type,
@ -1623,10 +1658,10 @@ void BrowserWindowOsrMac::OnCursorChange(
CEF_REQUIRE_UI_THREAD();
REQUIRE_MAIN_THREAD();
[cursor set];
[CAST_CEF_CURSOR_HANDLE_TO_NSCURSOR(cursor) set];
}
bool BrowserWindowOsrMac::StartDragging(
bool BrowserWindowOsrMacImpl::StartDragging(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefDragData> drag_data,
CefRenderHandler::DragOperationsMask allowed_ops,
@ -1635,10 +1670,11 @@ bool BrowserWindowOsrMac::StartDragging(
CEF_REQUIRE_UI_THREAD();
REQUIRE_MAIN_THREAD();
if (!nsview_)
if (!native_browser_view_)
return false;
static float device_scale_factor = [GLView(nsview_) getDeviceScaleFactor];
static float device_scale_factor =
[native_browser_view_ getDeviceScaleFactor];
// |point| is in browser view coordinates.
NSPoint point = NSMakePoint(x, y);
@ -1648,74 +1684,230 @@ bool BrowserWindowOsrMac::StartDragging(
point.y = LogicalToDevice(point.y, device_scale_factor);
// Convert to OS X view coordinates.
point = [GLView(nsview_) convertPointFromBackingInternal:point];
point = [native_browser_view_ convertPointFromBackingInternal:point];
return
[GLView(nsview_) startDragging:drag_data
return [native_browser_view_
startDragging:drag_data
allowedOps:static_cast<NSDragOperation>(allowed_ops)
point:point];
}
void BrowserWindowOsrMac::UpdateDragCursor(
void BrowserWindowOsrMacImpl::UpdateDragCursor(
CefRefPtr<CefBrowser> browser,
CefRenderHandler::DragOperation operation) {
CEF_REQUIRE_UI_THREAD();
REQUIRE_MAIN_THREAD();
if (nsview_)
[GLView(nsview_) setCurrentDragOp:operation];
if (native_browser_view_)
[native_browser_view_ setCurrentDragOp:operation];
}
void BrowserWindowOsrMac::OnImeCompositionRangeChanged(
void BrowserWindowOsrMacImpl::OnImeCompositionRangeChanged(
CefRefPtr<CefBrowser> browser,
const CefRange& selection_range,
const CefRenderHandler::RectList& bounds) {
CEF_REQUIRE_UI_THREAD();
if (nsview_) {
[GLView(nsview_) ChangeCompositionRange:selection_range
if (native_browser_view_) {
[native_browser_view_ ChangeCompositionRange:selection_range
character_bounds:bounds];
}
}
void BrowserWindowOsrMac::UpdateAccessibilityTree(CefRefPtr<CefValue> value) {
void BrowserWindowOsrMacImpl::UpdateAccessibilityTree(
CefRefPtr<CefValue> value) {
CEF_REQUIRE_UI_THREAD();
if (nsview_) {
[GLView(nsview_) UpdateAccessibilityTree:value];
if (native_browser_view_) {
[native_browser_view_ UpdateAccessibilityTree:value];
}
}
void BrowserWindowOsrMacImpl::UpdateAccessibilityLocation(
CefRefPtr<CefValue> value) {
CEF_REQUIRE_UI_THREAD();
if (native_browser_view_) {
[native_browser_view_ UpdateAccessibilityLocation:value];
}
}
void BrowserWindowOsrMacImpl::Create(ClientWindowHandle parent_handle,
const CefRect& rect) {
REQUIRE_MAIN_THREAD();
DCHECK(!native_browser_view_);
NSRect window_rect = NSMakeRect(rect.x, rect.y, rect.width, rect.height);
native_browser_view_ =
[[BrowserOpenGLView alloc] initWithFrame:window_rect
andBrowserWindow:&browser_window_
andRenderer:&renderer_];
native_browser_view_.autoresizingMask =
(NSViewWidthSizable | NSViewHeightSizable);
native_browser_view_.autoresizesSubviews = YES;
[CAST_CEF_WINDOW_HANDLE_TO_NSVIEW(parent_handle)
addSubview:native_browser_view_];
// Determine the default scale factor.
[native_browser_view_ resetDeviceScaleFactor];
[[NSNotificationCenter defaultCenter]
addObserver:native_browser_view_
selector:@selector(windowDidChangeBackingProperties:)
name:NSWindowDidChangeBackingPropertiesNotification
object:native_browser_view_.window];
}
BrowserWindowOsrMac::BrowserWindowOsrMac(BrowserWindow::Delegate* delegate,
const std::string& startup_url,
const OsrRendererSettings& settings)
: BrowserWindow(delegate) {
client_handler_ = new ClientHandlerOsr(this, this, startup_url);
impl_.reset(
new BrowserWindowOsrMacImpl(delegate, startup_url, settings, *this));
}
BrowserWindowOsrMac::~BrowserWindowOsrMac() {}
void BrowserWindowOsrMac::CreateBrowser(
ClientWindowHandle parent_handle,
const CefRect& rect,
const CefBrowserSettings& settings,
CefRefPtr<CefRequestContext> request_context) {
impl_->CreateBrowser(parent_handle, rect, settings, request_context);
}
void BrowserWindowOsrMac::GetPopupConfig(CefWindowHandle temp_handle,
CefWindowInfo& windowInfo,
CefRefPtr<CefClient>& client,
CefBrowserSettings& settings) {
impl_->GetPopupConfig(temp_handle, windowInfo, client, settings);
}
void BrowserWindowOsrMac::ShowPopup(ClientWindowHandle parent_handle,
int x,
int y,
size_t width,
size_t height) {
impl_->ShowPopup(parent_handle, x, y, width, height);
}
void BrowserWindowOsrMac::Show() {
impl_->Show();
}
void BrowserWindowOsrMac::Hide() {
impl_->Hide();
}
void BrowserWindowOsrMac::SetBounds(int x, int y, size_t width, size_t height) {
impl_->SetBounds(x, y, width, height);
}
void BrowserWindowOsrMac::SetFocus(bool focus) {
impl_->SetFocus(focus);
}
void BrowserWindowOsrMac::SetDeviceScaleFactor(float device_scale_factor) {
impl_->SetDeviceScaleFactor(device_scale_factor);
}
float BrowserWindowOsrMac::GetDeviceScaleFactor() const {
return impl_->GetDeviceScaleFactor();
}
ClientWindowHandle BrowserWindowOsrMac::GetWindowHandle() const {
return impl_->GetWindowHandle();
}
void BrowserWindowOsrMac::OnAfterCreated(CefRefPtr<CefBrowser> browser) {
impl_->OnAfterCreated(browser);
}
void BrowserWindowOsrMac::OnBeforeClose(CefRefPtr<CefBrowser> browser) {
impl_->OnBeforeClose(browser);
}
bool BrowserWindowOsrMac::GetRootScreenRect(CefRefPtr<CefBrowser> browser,
CefRect& rect) {
return impl_->GetRootScreenRect(browser, rect);
}
void BrowserWindowOsrMac::GetViewRect(CefRefPtr<CefBrowser> browser,
CefRect& rect) {
impl_->GetViewRect(browser, rect);
}
bool BrowserWindowOsrMac::GetScreenPoint(CefRefPtr<CefBrowser> browser,
int viewX,
int viewY,
int& screenX,
int& screenY) {
return impl_->GetScreenPoint(browser, viewX, viewY, screenX, screenY);
}
bool BrowserWindowOsrMac::GetScreenInfo(CefRefPtr<CefBrowser> browser,
CefScreenInfo& screen_info) {
return impl_->GetScreenInfo(browser, screen_info);
}
void BrowserWindowOsrMac::OnPopupShow(CefRefPtr<CefBrowser> browser,
bool show) {
impl_->OnPopupShow(browser, show);
}
void BrowserWindowOsrMac::OnPopupSize(CefRefPtr<CefBrowser> browser,
const CefRect& rect) {
impl_->OnPopupSize(browser, rect);
}
void BrowserWindowOsrMac::OnPaint(CefRefPtr<CefBrowser> browser,
CefRenderHandler::PaintElementType type,
const CefRenderHandler::RectList& dirtyRects,
const void* buffer,
int width,
int height) {
impl_->OnPaint(browser, type, dirtyRects, buffer, width, height);
}
void BrowserWindowOsrMac::OnCursorChange(
CefRefPtr<CefBrowser> browser,
CefCursorHandle cursor,
CefRenderHandler::CursorType type,
const CefCursorInfo& custom_cursor_info) {
impl_->OnCursorChange(browser, cursor, type, custom_cursor_info);
}
bool BrowserWindowOsrMac::StartDragging(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefDragData> drag_data,
CefRenderHandler::DragOperationsMask allowed_ops,
int x,
int y) {
return impl_->StartDragging(browser, drag_data, allowed_ops, x, y);
}
void BrowserWindowOsrMac::UpdateDragCursor(
CefRefPtr<CefBrowser> browser,
CefRenderHandler::DragOperation operation) {
impl_->UpdateDragCursor(browser, operation);
}
void BrowserWindowOsrMac::OnImeCompositionRangeChanged(
CefRefPtr<CefBrowser> browser,
const CefRange& selection_range,
const CefRenderHandler::RectList& character_bounds) {
impl_->OnImeCompositionRangeChanged(browser, selection_range,
character_bounds);
}
void BrowserWindowOsrMac::UpdateAccessibilityTree(CefRefPtr<CefValue> value) {
impl_->UpdateAccessibilityTree(value);
}
void BrowserWindowOsrMac::UpdateAccessibilityLocation(
scoped_refptr<CefValue> value) {
CEF_REQUIRE_UI_THREAD();
if (nsview_) {
[GLView(nsview_) UpdateAccessibilityLocation:value];
}
}
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_];
// Determine the default scale factor.
[GLView(nsview_) resetDeviceScaleFactor];
[[NSNotificationCenter defaultCenter]
addObserver:nsview_
selector:@selector(windowDidChangeBackingProperties:)
name:NSWindowDidChangeBackingPropertiesNotification
object:[nsview_ window]];
CefRefPtr<CefValue> value) {
impl_->UpdateAccessibilityLocation(value);
}
} // namespace client

View File

@ -52,11 +52,11 @@ void BrowserWindowStdMac::ShowPopup(ClientWindowHandle parent_handle,
size_t height) {
REQUIRE_MAIN_THREAD();
NSView* browser_view = GetWindowHandle();
NSView* browser_view = CAST_CEF_WINDOW_HANDLE_TO_NSVIEW(GetWindowHandle());
// Re-parent |browser_view| to |parent_handle|.
[browser_view removeFromSuperview];
[parent_handle addSubview:browser_view];
[CAST_CEF_WINDOW_HANDLE_TO_NSVIEW(parent_handle) addSubview:browser_view];
NSSize size = NSMakeSize(static_cast<int>(width), static_cast<int>(height));
[browser_view setFrameSize:size];

View File

@ -18,15 +18,12 @@
#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
#define ClientNativeMacWindow void*
#ifdef __OBJC__
@class NSWindow;
#else
class NSWindow;
#endif
#endif
#define CAST_CLIENT_NATIVE_MAC_WINDOW_TO_NSWINDOW(native) \
(__bridge NSWindow*)native
#define CAST_NSWINDOW_TO_CLIENT_NATIVE_MAC_WINDOW(window) (__bridge void*)window
#endif // __OBJC__
#endif // defined OS_MACOSX
#endif // CEF_TESTS_CEFCLIENT_BROWSER_CLIENT_TYPES_H_

View File

@ -11,12 +11,19 @@
#include "include/cef_browser.h"
#if defined(OS_MACOSX)
#ifdef __OBJC__
@class NSObject;
#else
class NSObject;
#endif
typedef NSObject CefNativeAccessible;
typedef void CefNativeAccessible;
#if __OBJC__
#if __has_feature(objc_arc)
#define CAST_CEF_NATIVE_ACCESSIBLE_TO_NSOBJECT(accessible) \
(__bridge NSObject*)accessible
#define CAST_NSOBJECT_TO_CEF_NATIVE_ACCESSIBLE(object) \
(__bridge CefNativeAccessible*)object
#else // __has_feature(objc_arc)
#define CAST_CEF_NATIVE_ACCESSIBLE_TO_NSOBJECT(accessible) (NSObject*)accessible
#define CAST_NSOBJECT_TO_CEF_NATIVE_ACCESSIBLE(object) \
(__bridge CefNativeAccessible*)object
#endif // __has_feature(objc_arc)
#endif // __OBJC__
#elif defined(OS_WIN)
struct IAccessible;
typedef IAccessible CefNativeAccessible;

View File

@ -320,7 +320,9 @@ inline int MiddleY(const CefRect& rect) {
NSMutableArray* kids = [NSMutableArray arrayWithCapacity:numChilds];
for (int index = 0; index < numChilds; index++) {
client::OsrAXNode* child = node_->ChildAtIndex(index);
[kids addObject:child ? child->GetNativeAccessibleObject(node_) : nil];
[kids addObject:child ? CAST_CEF_NATIVE_ACCESSIBLE_TO_NSOBJECT(
child->GetNativeAccessibleObject(node_))
: nil];
}
return kids;
}
@ -332,7 +334,7 @@ inline int MiddleY(const CefRect& rect) {
NSPoint origin = NSMakePoint(cef_rect.x, cef_rect.y);
NSSize size = NSMakeSize(cef_rect.width, cef_rect.height);
NSView* view = node_->GetWindowHandle();
NSView* view = CAST_CEF_WINDOW_HANDLE_TO_NSVIEW(node_->GetWindowHandle());
origin.y = NSHeight([view bounds]) - origin.y;
NSPoint originInWindow = [view convertPoint:origin toView:nil];
@ -348,7 +350,7 @@ inline int MiddleY(const CefRect& rect) {
CefRect cef_rect = node_->AxLocation();
NSRect rect =
NSMakeRect(cef_rect.x, cef_rect.y, cef_rect.width, cef_rect.height);
NSView* view = node_->GetWindowHandle();
NSView* view = CAST_CEF_WINDOW_HANDLE_TO_NSVIEW(node_->GetWindowHandle());
rect = [[view window] convertRectToScreen:rect];
return rect.size;
}
@ -384,6 +386,7 @@ inline int MiddleY(const CefRect& rect) {
}
- (id)accessibilityAttributeValue:(NSString*)attribute {
NSObject* typed_parent = CAST_CEF_NATIVE_ACCESSIBLE_TO_NSOBJECT(parent_);
if (!node_)
return nil;
if ([attribute isEqualToString:NSAccessibilityRoleAttribute]) {
@ -397,16 +400,17 @@ inline int MiddleY(const CefRect& rect) {
accessibilityAttributeValue:NSAccessibilityFocusedUIElementAttribute];
return [NSNumber numberWithBool:[focusedElement isEqual:self]];
} else if ([attribute isEqualToString:NSAccessibilityParentAttribute]) {
return NSAccessibilityUnignoredAncestor(parent_);
return NSAccessibilityUnignoredAncestor(typed_parent);
} else if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) {
return NSAccessibilityUnignoredChildren([self getKids]);
} else if ([attribute isEqualToString:NSAccessibilityWindowAttribute]) {
// We're in the same window as our parent.
return [parent_ accessibilityAttributeValue:NSAccessibilityWindowAttribute];
return [typed_parent
accessibilityAttributeValue:NSAccessibilityWindowAttribute];
} else if ([attribute
isEqualToString:NSAccessibilityTopLevelUIElementAttribute]) {
// We're in the same top level element as our parent.
return [parent_
return [typed_parent
accessibilityAttributeValue:NSAccessibilityTopLevelUIElementAttribute];
} else if ([attribute isEqualToString:NSAccessibilityPositionAttribute]) {
return [NSValue valueWithPoint:[self position]];
@ -460,17 +464,18 @@ inline int MiddleY(const CefRect& rect) {
namespace client {
void OsrAXNode::NotifyAccessibilityEvent(std::string event_type) const {
NSView* view = CAST_CEF_WINDOW_HANDLE_TO_NSVIEW(GetWindowHandle());
if (event_type == "focus") {
NSAccessibilityPostNotification(
GetWindowHandle(), NSAccessibilityFocusedUIElementChangedNotification);
view, NSAccessibilityFocusedUIElementChangedNotification);
} else if (event_type == "textChanged") {
NSAccessibilityPostNotification(GetWindowHandle(),
NSAccessibilityPostNotification(view,
NSAccessibilityTitleChangedNotification);
} else if (event_type == "valueChanged") {
NSAccessibilityPostNotification(GetWindowHandle(),
NSAccessibilityPostNotification(view,
NSAccessibilityValueChangedNotification);
} else if (event_type == "textSelectionChanged") {
NSAccessibilityPostNotification(GetWindowHandle(),
NSAccessibilityPostNotification(view,
NSAccessibilityValueChangedNotification);
}
}
@ -478,7 +483,8 @@ void OsrAXNode::NotifyAccessibilityEvent(std::string event_type) const {
void OsrAXNode::Destroy() {
if (platform_accessibility_) {
NSAccessibilityPostNotification(
platform_accessibility_, NSAccessibilityUIElementDestroyedNotification);
CAST_CEF_NATIVE_ACCESSIBLE_TO_NSOBJECT(platform_accessibility_),
NSAccessibilityUIElementDestroyedNotification);
}
delete this;
@ -488,7 +494,8 @@ void OsrAXNode::Destroy() {
CefNativeAccessible* OsrAXNode::GetNativeAccessibleObject(
client::OsrAXNode* parent) {
if (!platform_accessibility_) {
platform_accessibility_ = [OsrAXNodeObject elementWithNode:this];
platform_accessibility_ = CAST_NSOBJECT_TO_CEF_NATIVE_ACCESSIBLE(
[OsrAXNodeObject elementWithNode:this]);
SetParent(parent);
}
return platform_accessibility_;

View File

@ -17,6 +17,10 @@
#include "tests/cefclient/browser/image_cache.h"
#include "tests/shared/browser/main_message_loop.h"
#if defined(OS_MACOSX) && __OBJC__
@class NSWindow;
#endif // defined(OS_MACOSX) && __OBJC__
namespace client {
// Used to configure how a RootWindow is created.
@ -117,7 +121,7 @@ class RootWindow
// called on the main thread.
static scoped_refptr<RootWindow> GetForBrowser(int browser_id);
#if defined(OS_MACOSX)
#if defined(OS_MACOSX) && __OBJC__
// Returns the RootWindow associated with the specified |window|. Must be
// called on the main thread.
static scoped_refptr<RootWindow> GetForNSWindow(NSWindow* window);

View File

@ -12,18 +12,10 @@
#include "tests/cefclient/browser/browser_window.h"
#include "tests/cefclient/browser/root_window.h"
#ifdef __OBJC__
@class NSWindow;
@class NSButton;
@class NSTextField;
#else
class NSWindow;
class NSButton;
class NSTextField;
#endif
namespace client {
class RootWindowMacImpl;
// 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.
@ -33,6 +25,9 @@ class RootWindowMac : public RootWindow, public BrowserWindow::Delegate {
RootWindowMac();
~RootWindowMac();
BrowserWindow* browser_window() const;
RootWindow::Delegate* delegate() const;
// RootWindow methods.
void Init(RootWindow::Delegate* delegate,
const RootWindowConfig& config,
@ -55,18 +50,6 @@ class RootWindowMac : public RootWindow, public BrowserWindow::Delegate {
bool WithWindowlessRendering() const OVERRIDE;
bool WithExtension() const OVERRIDE;
// Called by RootWindowDelegate after the associated NSWindow has been
// destroyed.
void WindowDestroyed();
BrowserWindow* browser_window() const { return browser_window_.get(); }
RootWindow::Delegate* delegate() const { return delegate_; }
private:
void CreateBrowserWindow(const std::string& startup_url);
void CreateRootWindow(const CefBrowserSettings& settings,
bool initially_hidden);
// BrowserWindow::Delegate methods.
void OnBrowserCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
void OnBrowserWindowDestroyed() OVERRIDE;
@ -80,34 +63,14 @@ class RootWindowMac : public RootWindow, public BrowserWindow::Delegate {
void OnSetDraggableRegions(
const std::vector<CefDraggableRegion>& regions) OVERRIDE;
void NotifyDestroyedIfDone();
void OnNativeWindowClosed();
// After initialization all members are only accessed on the main thread.
// Members set during initialization.
bool with_controls_;
bool with_osr_;
bool with_extension_;
bool is_popup_;
CefRect start_rect_;
scoped_ptr<BrowserWindow> 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_;
private:
CefRefPtr<RootWindowMacImpl> impl_;
DISALLOW_COPY_AND_ASSIGN(RootWindowMac);
friend class RootWindowMacImpl;
};
} // namespace client

File diff suppressed because it is too large Load Diff

View File

@ -10,6 +10,8 @@
namespace client {
class TempWindowMacImpl;
// Represents a singleton hidden window that acts as a temporary parent for
// popup browsers. Only accessed on the UI thread.
class TempWindowMac {
@ -26,7 +28,7 @@ class TempWindowMac {
TempWindowMac();
~TempWindowMac();
NSWindow* window_;
scoped_ptr<TempWindowMacImpl> impl_;
DISALLOW_COPY_AND_ASSIGN(TempWindowMac);
};

View File

@ -17,29 +17,43 @@ TempWindowMac* g_temp_window = NULL;
} // namespace
TempWindowMac::TempWindowMac() : window_(nil) {
DCHECK(!g_temp_window);
g_temp_window = this;
class TempWindowMacImpl {
public:
TempWindowMacImpl() {
// Create a borderless non-visible 1x1 window.
window_ = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 1, 1)
styleMask:NSBorderlessWindowMask
backing:NSBackingStoreBuffered
defer:NO];
CHECK(window_);
}
~TempWindowMacImpl() {
DCHECK(window_);
[window_ close];
}
private:
NSWindow* window_;
friend class TempWindowMac;
};
TempWindowMac::TempWindowMac() {
DCHECK(!g_temp_window);
impl_.reset(new TempWindowMacImpl);
g_temp_window = this;
}
TempWindowMac::~TempWindowMac() {
impl_.reset();
g_temp_window = NULL;
DCHECK(window_);
[window_ close];
}
// static
CefWindowHandle TempWindowMac::GetWindowHandle() {
DCHECK(g_temp_window);
return [g_temp_window->window_ contentView];
return CAST_NSVIEW_TO_CEF_WINDOW_HANDLE(
g_temp_window->impl_->window_.contentView);
}
} // namespace client

View File

@ -15,7 +15,8 @@ namespace window_test {
namespace {
NSWindow* GetWindow(CefRefPtr<CefBrowser> browser) {
NSView* view = (NSView*)browser->GetHost()->GetWindowHandle();
NSView* view =
CAST_CEF_WINDOW_HANDLE_TO_NSVIEW(browser->GetHost()->GetWindowHandle());
return [view window];
}

View File

@ -355,26 +355,29 @@ int RunMain(int argc, char* argv[]) {
if (!library_loader.LoadInMain())
return 1;
int result = -1;
CefMainArgs main_args(argc, argv);
// Initialize the AutoRelease pool.
NSAutoreleasePool* autopool = [[NSAutoreleasePool alloc] init];
@autoreleasepool {
// Initialize the ClientApplication instance.
[ClientApplication sharedApplication];
// Parse command-line arguments.
CefRefPtr<CefCommandLine> command_line = CefCommandLine::CreateCommandLine();
CefRefPtr<CefCommandLine> command_line =
CefCommandLine::CreateCommandLine();
command_line->InitFromArgv(argc, argv);
// Create a ClientApp of the correct type.
CefRefPtr<CefApp> app;
ClientApp::ProcessType process_type = ClientApp::GetProcessType(command_line);
ClientApp::ProcessType process_type =
ClientApp::GetProcessType(command_line);
if (process_type == ClientApp::BrowserProcess)
app = new ClientAppBrowser();
// Create the main context object.
scoped_ptr<MainContextImpl> context(new MainContextImpl(command_line, true));
scoped_ptr<MainContextImpl> context(
new MainContextImpl(command_line, true));
CefSettings settings;
@ -410,16 +413,19 @@ int RunMain(int argc, char* argv[]) {
waitUntilDone:NO];
// Run the message loop. This will block until Quit() is called.
int result = message_loop->Run();
result = message_loop->Run();
// Shut down CEF.
context->Shutdown();
// Release objects in reverse order of creation.
#if !__has_feature(objc_arc)
[delegate release];
#endif // !__has_feature(objc_arc)
delegate = nil;
message_loop.reset();
context.reset();
[autopool release];
} // @autoreleasepool
return result;
}

View File

@ -87,6 +87,16 @@ endif()
#
if(OS_MACOSX)
option(OPTION_USE_ARC "Build with ARC (automatic Reference Counting) on macOS." ON)
if(OPTION_USE_ARC)
list(APPEND CEF_COMPILER_FLAGS
-fobjc-arc
)
set_target_properties(${target} PROPERTIES
CLANG_ENABLE_OBJC_ARC "YES"
)
endif()
# Output paths for the app bundles.
set(CEF_APP "${CEF_TARGET_OUT_DIR}/${CEF_TARGET}.app")
set(CEF_HELPER_APP "${CEF_TARGET_OUT_DIR}/${CEF_HELPER_OUTPUT_NAME}.app")

View File

@ -12,13 +12,13 @@
#include "tests/cefsimple/simple_handler.h"
// Receives notifications from the application.
@interface SimpleAppDelegate : NSObject<NSApplicationDelegate>
@interface SimpleAppDelegate : NSObject <NSApplicationDelegate>
- (void)createApplication:(id)object;
- (void)tryToTerminateApplication:(NSApplication*)app;
@end
// Provide the CefAppProtocol implementation required by CEF.
@interface SimpleApplication : NSApplication<CefAppProtocol> {
@interface SimpleApplication : NSApplication <CefAppProtocol> {
@private
BOOL handlingSendEvent_;
}
@ -119,18 +119,16 @@ int main(int argc, char* argv[]) {
// Provide CEF with command-line arguments.
CefMainArgs main_args(argc, argv);
// Initialize the AutoRelease pool.
NSAutoreleasePool* autopool = [[NSAutoreleasePool alloc] init];
@autoreleasepool {
// Initialize the SimpleApplication instance.
[SimpleApplication sharedApplication];
// Specify CEF global settings here.
CefSettings settings;
// When generating projects with CMake the CEF_USE_SANDBOX value will be defined
// automatically. Pass -DUSE_SANDBOX=OFF to the CMake command-line to disable
// use of the sandbox.
// When generating projects with CMake the CEF_USE_SANDBOX value will be
// defined automatically. Pass -DUSE_SANDBOX=OFF to the CMake command-line
// to disable use of the sandbox.
#if !defined(CEF_USE_SANDBOX)
settings.no_sandbox = true;
#endif
@ -157,10 +155,11 @@ int main(int argc, char* argv[]) {
CefShutdown();
// Release the delegate.
#if !__has_feature(objc_arc)
[delegate release];
// Release the AutoRelease pool.
[autopool release];
#endif // !__has_feature(objc_arc)
delegate = nil;
} // @autoreleasepool
return 0;
}

View File

@ -10,7 +10,8 @@
void SimpleHandler::PlatformTitleChange(CefRefPtr<CefBrowser> browser,
const CefString& title) {
NSView* view = (NSView*)browser->GetHost()->GetWindowHandle();
NSView* view =
CAST_CEF_WINDOW_HANDLE_TO_NSVIEW(browser->GetHost()->GetWindowHandle());
NSWindow* window = [view window];
std::string titleStr(title);
NSString* str = [NSString stringWithUTF8String:titleStr.c_str()];

View File

@ -12,7 +12,7 @@ CefWindowHandle GetFakeView() {
NSScreen* mainScreen = [NSScreen mainScreen];
NSRect screenRect = [mainScreen visibleFrame];
NSView* fakeView = [[NSView alloc] initWithFrame:screenRect];
return fakeView;
return CAST_NSVIEW_TO_CEF_WINDOW_HANDLE(fakeView);
}
} // namespace osr_unittests

View File

@ -82,14 +82,21 @@ class MainMessageLoopExternalPumpMac : public MainMessageLoopExternalPump {
namespace client {
MainMessageLoopExternalPumpMac::MainMessageLoopExternalPumpMac()
: owner_thread_([[NSThread currentThread] retain]), timer_(nil) {
event_handler_ = [[[EventHandler alloc] initWithPump:this] retain];
: owner_thread_([NSThread currentThread]), timer_(nil) {
#if !__has_feature(objc_arc)
[owner_thread_ retain];
#endif // !__has_feature(objc_arc)
event_handler_ = [[EventHandler alloc] initWithPump:this];
}
MainMessageLoopExternalPumpMac::~MainMessageLoopExternalPumpMac() {
KillTimer();
#if !__has_feature(objc_arc)
[owner_thread_ release];
[event_handler_ release];
#endif // !__has_feature(objc_arc)
owner_thread_ = nil;
event_handler_ = nil;
}
void MainMessageLoopExternalPumpMac::Quit() {
@ -140,11 +147,14 @@ void MainMessageLoopExternalPumpMac::SetTimer(int64 delay_ms) {
DCHECK(!timer_);
const double delay_s = static_cast<double>(delay_ms) / 1000.0;
timer_ = [[NSTimer timerWithTimeInterval:delay_s
timer_ = [NSTimer timerWithTimeInterval:delay_s
target:event_handler_
selector:@selector(timerTimeout:)
userInfo:nil
repeats:NO] retain];
repeats:NO];
#if !__has_feature(objc_arc)
[timer_ retain];
#endif // !__has_feature(objc_arc)
// Add the timer to default and tracking runloop modes.
NSRunLoop* owner_runloop = [NSRunLoop currentRunLoop];
@ -155,7 +165,9 @@ void MainMessageLoopExternalPumpMac::SetTimer(int64 delay_ms) {
void MainMessageLoopExternalPumpMac::KillTimer() {
if (timer_ != nil) {
[timer_ invalidate];
#if !__has_feature(objc_arc)
[timer_ release];
#endif // !__has_feature(objc_arc)
timer_ = nil;
}
}