mirror of
				https://bitbucket.org/chromiumembedded/cef
				synced 2025-06-05 21:39:12 +02:00 
			
		
		
		
	The cursor change can now be handled by the client with both windowed and off-screen rendering. Returning true from OnCursorChange will disable the default cursor change behavior. This is functionally equivalent to the CefBrowserHost::SetMouseCursorChangeDisabled method, so that method has been removed.
		
			
				
	
	
		
			1918 lines
		
	
	
		
			58 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			1918 lines
		
	
	
		
			58 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
// 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 "tests/cefclient/browser/browser_window_osr_mac.h"
 | 
						|
 | 
						|
#include <Cocoa/Cocoa.h>
 | 
						|
#include <OpenGL/gl.h>
 | 
						|
#import <objc/runtime.h>
 | 
						|
 | 
						|
#include "include/base/cef_logging.h"
 | 
						|
#include "include/cef_parser.h"
 | 
						|
#include "include/wrapper/cef_closure_task.h"
 | 
						|
#include "tests/cefclient/browser/bytes_write_handler.h"
 | 
						|
#include "tests/cefclient/browser/main_context.h"
 | 
						|
#include "tests/cefclient/browser/osr_accessibility_helper.h"
 | 
						|
#include "tests/cefclient/browser/osr_accessibility_node.h"
 | 
						|
#include "tests/cefclient/browser/text_input_client_osr_mac.h"
 | 
						|
#include "tests/shared/browser/geometry_util.h"
 | 
						|
#include "tests/shared/browser/main_message_loop.h"
 | 
						|
 | 
						|
#import <AppKit/NSAccessibility.h>
 | 
						|
 | 
						|
@interface BrowserOpenGLView
 | 
						|
    : NSOpenGLView <NSDraggingSource, NSDraggingDestination, NSAccessibility> {
 | 
						|
 @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_;
 | 
						|
 | 
						|
  float device_scale_factor_;
 | 
						|
 | 
						|
  // Drag and drop.
 | 
						|
  CefRefPtr<CefDragData> current_drag_data_;
 | 
						|
  NSDragOperation current_drag_op_;
 | 
						|
  NSDragOperation current_allowed_ops_;
 | 
						|
  NSPasteboard* pasteboard_;
 | 
						|
  NSString* fileUTI_;
 | 
						|
 | 
						|
  // For intreacting with IME.
 | 
						|
  NSTextInputContext* text_input_context_osr_mac_;
 | 
						|
  CefTextInputClientOSRMac* text_input_client_;
 | 
						|
 | 
						|
  // Manages Accessibility Tree
 | 
						|
  client::OsrAccessibilityHelper* accessibility_helper_;
 | 
						|
 | 
						|
  // Event monitor for scroll wheel end event.
 | 
						|
  id endWheelMonitor_;
 | 
						|
}
 | 
						|
 | 
						|
@end  // @interface BrowserOpenGLView
 | 
						|
 | 
						|
namespace {
 | 
						|
 | 
						|
NSString* const kCEFDragDummyPboardType = @"org.CEF.drag-dummy-type";
 | 
						|
NSString* const kNSURLTitlePboardType = @"public.url-name";
 | 
						|
 | 
						|
class ScopedGLContext {
 | 
						|
 public:
 | 
						|
  ScopedGLContext(BrowserOpenGLView* view, bool swap_buffers)
 | 
						|
      : swap_buffers_(swap_buffers) {
 | 
						|
    context_ = [view openGLContext];
 | 
						|
    [context_ makeCurrentContext];
 | 
						|
  }
 | 
						|
  ~ScopedGLContext() {
 | 
						|
    [NSOpenGLContext clearCurrentContext];
 | 
						|
    if (swap_buffers_)
 | 
						|
      [context_ flushBuffer];
 | 
						|
  }
 | 
						|
 | 
						|
 private:
 | 
						|
  NSOpenGLContext* context_;
 | 
						|
  const bool swap_buffers_;
 | 
						|
};
 | 
						|
 | 
						|
NSPoint ConvertPointFromWindowToScreen(NSWindow* window, NSPoint point) {
 | 
						|
  NSRect point_rect = NSMakeRect(point.x, point.y, 0, 0);
 | 
						|
  return [window convertRectToScreen:point_rect].origin;
 | 
						|
}
 | 
						|
 | 
						|
}  // namespace
 | 
						|
 | 
						|
@implementation BrowserOpenGLView
 | 
						|
 | 
						|
- (id)initWithFrame:(NSRect)frame
 | 
						|
    andBrowserWindow:(client::BrowserWindowOsrMac*)browser_window
 | 
						|
         andRenderer:(client::OsrRenderer*)renderer {
 | 
						|
  NSOpenGLPixelFormat* pixelFormat = [[NSOpenGLPixelFormat alloc]
 | 
						|
      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;
 | 
						|
    renderer_ = renderer;
 | 
						|
    rotating_ = false;
 | 
						|
    endWheelMonitor_ = nil;
 | 
						|
    device_scale_factor_ = 1.0f;
 | 
						|
 | 
						|
    tracking_area_ = [[NSTrackingArea alloc]
 | 
						|
        initWithRect:frame
 | 
						|
             options:NSTrackingMouseMoved | NSTrackingActiveInActiveApp |
 | 
						|
                     NSTrackingInVisibleRect
 | 
						|
               owner:self
 | 
						|
            userInfo:nil];
 | 
						|
    [self addTrackingArea:tracking_area_];
 | 
						|
 | 
						|
    // enable HiDPI buffer
 | 
						|
    [self setWantsBestResolutionOpenGLSurface:YES];
 | 
						|
 | 
						|
    [self resetDragDrop];
 | 
						|
 | 
						|
    NSArray* types = [NSArray
 | 
						|
        arrayWithObjects:kCEFDragDummyPboardType, NSStringPboardType,
 | 
						|
                         NSFilenamesPboardType, NSPasteboardTypeString, nil];
 | 
						|
    [self registerForDraggedTypes:types];
 | 
						|
  }
 | 
						|
 | 
						|
  return self;
 | 
						|
}
 | 
						|
 | 
						|
- (void)dealloc {
 | 
						|
  [[NSNotificationCenter defaultCenter]
 | 
						|
      removeObserver:self
 | 
						|
                name:NSWindowDidChangeBackingPropertiesNotification
 | 
						|
              object:nil];
 | 
						|
#if !__has_feature(objc_arc)
 | 
						|
  if (text_input_context_osr_mac_) {
 | 
						|
    [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_client_)
 | 
						|
    [text_input_client_ detach];
 | 
						|
}
 | 
						|
 | 
						|
- (CefRefPtr<CefBrowser>)getBrowser {
 | 
						|
  if (browser_window_)
 | 
						|
    return browser_window_->GetBrowser();
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
- (void)setFrame:(NSRect)frameRect {
 | 
						|
  CefRefPtr<CefBrowser> browser = [self getBrowser];
 | 
						|
  if (!browser.get())
 | 
						|
    return;
 | 
						|
 | 
						|
  [super setFrame:frameRect];
 | 
						|
  browser->GetHost()->WasResized();
 | 
						|
}
 | 
						|
 | 
						|
- (void)sendMouseClick:(NSEvent*)event
 | 
						|
                button:(CefBrowserHost::MouseButtonType)type
 | 
						|
                  isUp:(bool)isUp {
 | 
						|
  CefRefPtr<CefBrowser> browser = [self getBrowser];
 | 
						|
  if (!browser.get())
 | 
						|
    return;
 | 
						|
 | 
						|
  CefMouseEvent mouseEvent;
 | 
						|
  [self getMouseEvent:mouseEvent forEvent:event];
 | 
						|
 | 
						|
  // |point| is in OS X view coordinates.
 | 
						|
  NSPoint point = [self getClickPointForEvent:event];
 | 
						|
 | 
						|
  // Convert to device coordinates.
 | 
						|
  point = [self convertPointToBackingInternal:point];
 | 
						|
 | 
						|
  if (!isUp) {
 | 
						|
    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]);
 | 
						|
}
 | 
						|
 | 
						|
- (void)mouseDown:(NSEvent*)event {
 | 
						|
  [self sendMouseClick:event button:MBT_LEFT isUp:false];
 | 
						|
}
 | 
						|
 | 
						|
- (void)rightMouseDown:(NSEvent*)event {
 | 
						|
  if ([event modifierFlags] & NSShiftKeyMask) {
 | 
						|
    // Start rotation effect.
 | 
						|
    last_mouse_pos_ = cur_mouse_pos_ = [self getClickPointForEvent:event];
 | 
						|
    rotating_ = true;
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  [self sendMouseClick:event button:MBT_RIGHT isUp:false];
 | 
						|
}
 | 
						|
 | 
						|
- (void)otherMouseDown:(NSEvent*)event {
 | 
						|
  [self sendMouseClick:event button:MBT_MIDDLE isUp:false];
 | 
						|
}
 | 
						|
 | 
						|
- (void)mouseUp:(NSEvent*)event {
 | 
						|
  [self sendMouseClick:event button:MBT_LEFT isUp:true];
 | 
						|
}
 | 
						|
 | 
						|
- (void)rightMouseUp:(NSEvent*)event {
 | 
						|
  if (rotating_) {
 | 
						|
    // End rotation effect.
 | 
						|
    renderer_->SetSpin(0, 0);
 | 
						|
    rotating_ = false;
 | 
						|
    [self setNeedsDisplay:YES];
 | 
						|
    return;
 | 
						|
  }
 | 
						|
  [self sendMouseClick:event button:MBT_RIGHT isUp:true];
 | 
						|
}
 | 
						|
 | 
						|
- (void)otherMouseUp:(NSEvent*)event {
 | 
						|
  [self sendMouseClick:event button:MBT_MIDDLE isUp:true];
 | 
						|
}
 | 
						|
 | 
						|
- (void)mouseMoved:(NSEvent*)event {
 | 
						|
  CefRefPtr<CefBrowser> browser = [self getBrowser];
 | 
						|
  if (!browser.get())
 | 
						|
    return;
 | 
						|
 | 
						|
  if (rotating_) {
 | 
						|
    // Apply rotation effect.
 | 
						|
    cur_mouse_pos_ = [self getClickPointForEvent:event];
 | 
						|
    ;
 | 
						|
    renderer_->IncrementSpin((cur_mouse_pos_.x - last_mouse_pos_.x),
 | 
						|
                             (cur_mouse_pos_.y - last_mouse_pos_.y));
 | 
						|
    last_mouse_pos_ = cur_mouse_pos_;
 | 
						|
    [self setNeedsDisplay:YES];
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  CefMouseEvent mouseEvent;
 | 
						|
  [self getMouseEvent:mouseEvent forEvent:event];
 | 
						|
 | 
						|
  browser->GetHost()->SendMouseMoveEvent(mouseEvent, false);
 | 
						|
}
 | 
						|
 | 
						|
- (void)mouseDragged:(NSEvent*)event {
 | 
						|
  [self mouseMoved:event];
 | 
						|
}
 | 
						|
 | 
						|
- (void)rightMouseDragged:(NSEvent*)event {
 | 
						|
  [self mouseMoved:event];
 | 
						|
}
 | 
						|
 | 
						|
- (void)otherMouseDragged:(NSEvent*)event {
 | 
						|
  [self mouseMoved:event];
 | 
						|
}
 | 
						|
 | 
						|
- (void)mouseEntered:(NSEvent*)event {
 | 
						|
  [self mouseMoved:event];
 | 
						|
}
 | 
						|
 | 
						|
- (void)mouseExited:(NSEvent*)event {
 | 
						|
  CefRefPtr<CefBrowser> browser = [self getBrowser];
 | 
						|
  if (!browser.get())
 | 
						|
    return;
 | 
						|
 | 
						|
  CefMouseEvent mouseEvent;
 | 
						|
  [self getMouseEvent:mouseEvent forEvent:event];
 | 
						|
 | 
						|
  browser->GetHost()->SendMouseMoveEvent(mouseEvent, true);
 | 
						|
}
 | 
						|
 | 
						|
- (void)keyDown:(NSEvent*)event {
 | 
						|
  CefRefPtr<CefBrowser> browser = [self getBrowser];
 | 
						|
  if (!browser.get() || !text_input_context_osr_mac_)
 | 
						|
    return;
 | 
						|
 | 
						|
  if ([event type] != NSFlagsChanged) {
 | 
						|
    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.
 | 
						|
      [text_input_context_osr_mac_ handleEvent:event];
 | 
						|
 | 
						|
      CefKeyEvent keyEvent;
 | 
						|
      [self getKeyEvent:keyEvent forEvent:event];
 | 
						|
 | 
						|
      [text_input_client_ HandleKeyEventAfterTextInputClient:keyEvent];
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // Check for Caps lock and Toggle Touch Emulation
 | 
						|
  if (client::MainContext::Get()->TouchEventsEnabled())
 | 
						|
    [self toggleTouchEmulation:event];
 | 
						|
}
 | 
						|
 | 
						|
// OSX does not have touch screens, so we emulate it by mapping multitouch
 | 
						|
// events on TrackPad to Touch Events on Screen. To ensure it does not
 | 
						|
// interfere with other Trackpad events, this mapping is only enabled if
 | 
						|
// touch-events=enabled commandline is passed and caps lock key is on.
 | 
						|
- (void)toggleTouchEmulation:(NSEvent*)event {
 | 
						|
  if ([event type] == NSFlagsChanged && [event keyCode] == 0x39) {
 | 
						|
    NSUInteger flags = [event modifierFlags];
 | 
						|
    BOOL touch_enabled = flags & NSAlphaShiftKeyMask ? YES : NO;
 | 
						|
    [self setAcceptsTouchEvents:touch_enabled];
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
- (cef_touch_event_type_t)getTouchPhase:(NSTouchPhase)phase {
 | 
						|
  cef_touch_event_type_t event_type = CEF_TET_RELEASED;
 | 
						|
  switch (phase) {
 | 
						|
    case NSTouchPhaseBegan:
 | 
						|
      event_type = CEF_TET_PRESSED;
 | 
						|
      break;
 | 
						|
    case NSTouchPhaseMoved:
 | 
						|
      event_type = CEF_TET_MOVED;
 | 
						|
      break;
 | 
						|
    case NSTouchPhaseEnded:
 | 
						|
      event_type = CEF_TET_RELEASED;
 | 
						|
      break;
 | 
						|
    case NSTouchPhaseCancelled:
 | 
						|
      event_type = CEF_TET_CANCELLED;
 | 
						|
      break;
 | 
						|
    default:
 | 
						|
      break;
 | 
						|
  }
 | 
						|
  return event_type;
 | 
						|
}
 | 
						|
 | 
						|
// Translate NSTouch events to CefTouchEvents and send to browser.
 | 
						|
- (void)sendTouchEvent:(NSEvent*)event touchPhase:(NSTouchPhase)phase {
 | 
						|
  int modifiers = [self getModifiersForEvent:event];
 | 
						|
  CefRefPtr<CefBrowser> browser = [self getBrowser];
 | 
						|
 | 
						|
  NSSet* touches = [event touchesMatchingPhase:phase inView:self];
 | 
						|
 | 
						|
  for (NSTouch* touch in touches) {
 | 
						|
    // Convert NSTouch to CefTouchEvent.
 | 
						|
    CefTouchEvent touch_event;
 | 
						|
 | 
						|
    // NSTouch.identity is unique during the life of the touch
 | 
						|
    touch_event.id = touch.identity.hash;
 | 
						|
    touch_event.type = [self getTouchPhase:phase];
 | 
						|
 | 
						|
    NSPoint scaled_pos = [touch normalizedPosition];
 | 
						|
    NSSize view_size = [self bounds].size;
 | 
						|
 | 
						|
    // Map point on Touch Device to View coordinates.
 | 
						|
    NSPoint touch_point = NSMakePoint(scaled_pos.x * view_size.width,
 | 
						|
                                      scaled_pos.y * view_size.height);
 | 
						|
 | 
						|
    NSPoint contentLocal = [self convertPoint:touch_point fromView:nil];
 | 
						|
    NSPoint point;
 | 
						|
    point.x = contentLocal.x;
 | 
						|
    point.y = [self frame].size.height - contentLocal.y;  // Flip y.
 | 
						|
 | 
						|
    // Convert to device coordinates.
 | 
						|
    point = [self convertPointToBackingInternal:point];
 | 
						|
 | 
						|
    int device_x = point.x;
 | 
						|
    int device_y = point.y;
 | 
						|
 | 
						|
    const float device_scale_factor = [self getDeviceScaleFactor];
 | 
						|
    // Convert to browser view coordinates.
 | 
						|
    touch_event.x = client::DeviceToLogical(device_x, device_scale_factor);
 | 
						|
    touch_event.y = client::DeviceToLogical(device_y, device_scale_factor);
 | 
						|
 | 
						|
    touch_event.radius_x = 0;
 | 
						|
    touch_event.radius_y = 0;
 | 
						|
 | 
						|
    touch_event.rotation_angle = 0;
 | 
						|
    touch_event.pressure = 0;
 | 
						|
 | 
						|
    touch_event.modifiers = modifiers;
 | 
						|
 | 
						|
    // Notify the browser of touch event.
 | 
						|
    browser->GetHost()->SendTouchEvent(touch_event);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
- (void)touchesBeganWithEvent:(NSEvent*)event {
 | 
						|
  [self sendTouchEvent:event touchPhase:NSTouchPhaseBegan];
 | 
						|
}
 | 
						|
 | 
						|
- (void)touchesMovedWithEvent:(NSEvent*)event {
 | 
						|
  [self sendTouchEvent:event touchPhase:NSTouchPhaseMoved];
 | 
						|
}
 | 
						|
 | 
						|
- (void)touchesEndedWithEvent:(NSEvent*)event {
 | 
						|
  [self sendTouchEvent:event touchPhase:NSTouchPhaseEnded];
 | 
						|
}
 | 
						|
 | 
						|
- (void)touchesCancelledWithEvent:(NSEvent*)event {
 | 
						|
  [self sendTouchEvent:event touchPhase:NSTouchPhaseCancelled];
 | 
						|
}
 | 
						|
 | 
						|
- (void)keyUp:(NSEvent*)event {
 | 
						|
  CefRefPtr<CefBrowser> browser = [self getBrowser];
 | 
						|
  if (!browser.get())
 | 
						|
    return;
 | 
						|
 | 
						|
  CefKeyEvent keyEvent;
 | 
						|
  [self getKeyEvent:keyEvent forEvent:event];
 | 
						|
 | 
						|
  keyEvent.type = KEYEVENT_KEYUP;
 | 
						|
  browser->GetHost()->SendKeyEvent(keyEvent);
 | 
						|
}
 | 
						|
 | 
						|
- (void)flagsChanged:(NSEvent*)event {
 | 
						|
  if ([self isKeyUpEvent:event])
 | 
						|
    [self keyUp:event];
 | 
						|
  else
 | 
						|
    [self keyDown:event];
 | 
						|
}
 | 
						|
 | 
						|
- (void)shortCircuitScrollWheelEvent:(NSEvent*)event {
 | 
						|
  if ([event phase] != NSEventPhaseEnded &&
 | 
						|
      [event phase] != NSEventPhaseCancelled)
 | 
						|
    return;
 | 
						|
 | 
						|
  [self sendScrollWheelEvet:event];
 | 
						|
 | 
						|
  if (endWheelMonitor_) {
 | 
						|
    [NSEvent removeMonitor:endWheelMonitor_];
 | 
						|
    endWheelMonitor_ = nil;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
- (void)scrollWheel:(NSEvent*)event {
 | 
						|
  // 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
 | 
						|
  // view when the scrolling ends. Also it avoids sending duplicate scroll
 | 
						|
  // events to the renderer.
 | 
						|
  if ([event phase] == NSEventPhaseBegan && !endWheelMonitor_) {
 | 
						|
    endWheelMonitor_ = [NSEvent
 | 
						|
        addLocalMonitorForEventsMatchingMask:NSScrollWheelMask
 | 
						|
                                     handler:^(NSEvent* blockEvent) {
 | 
						|
                                       [self shortCircuitScrollWheelEvent:
 | 
						|
                                                 blockEvent];
 | 
						|
                                       return blockEvent;
 | 
						|
                                     }];
 | 
						|
  }
 | 
						|
 | 
						|
  [self sendScrollWheelEvet:event];
 | 
						|
}
 | 
						|
 | 
						|
- (void)sendScrollWheelEvet:(NSEvent*)event {
 | 
						|
  CefRefPtr<CefBrowser> browser = [self getBrowser];
 | 
						|
  if (!browser.get())
 | 
						|
    return;
 | 
						|
 | 
						|
  CGEventRef cgEvent = [event CGEvent];
 | 
						|
  DCHECK(cgEvent);
 | 
						|
 | 
						|
  int deltaX =
 | 
						|
      CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventPointDeltaAxis2);
 | 
						|
  int deltaY =
 | 
						|
      CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventPointDeltaAxis1);
 | 
						|
 | 
						|
  CefMouseEvent mouseEvent;
 | 
						|
  [self getMouseEvent:mouseEvent forEvent:event];
 | 
						|
 | 
						|
  browser->GetHost()->SendMouseWheelEvent(mouseEvent, deltaX, deltaY);
 | 
						|
}
 | 
						|
 | 
						|
- (BOOL)canBecomeKeyView {
 | 
						|
  CefRefPtr<CefBrowser> browser = [self getBrowser];
 | 
						|
  return (browser.get() != NULL);
 | 
						|
}
 | 
						|
 | 
						|
- (BOOL)acceptsFirstResponder {
 | 
						|
  CefRefPtr<CefBrowser> browser = [self getBrowser];
 | 
						|
  return (browser.get() != NULL);
 | 
						|
}
 | 
						|
 | 
						|
- (BOOL)becomeFirstResponder {
 | 
						|
  CefRefPtr<CefBrowser> browser = [self getBrowser];
 | 
						|
  if (browser.get()) {
 | 
						|
    browser->GetHost()->SendFocusEvent(true);
 | 
						|
    return [super becomeFirstResponder];
 | 
						|
  }
 | 
						|
 | 
						|
  return NO;
 | 
						|
}
 | 
						|
 | 
						|
- (BOOL)resignFirstResponder {
 | 
						|
  CefRefPtr<CefBrowser> browser = [self getBrowser];
 | 
						|
  if (browser.get()) {
 | 
						|
    browser->GetHost()->SendFocusEvent(false);
 | 
						|
    return [super resignFirstResponder];
 | 
						|
  }
 | 
						|
 | 
						|
  return NO;
 | 
						|
}
 | 
						|
 | 
						|
- (void)undo:(id)sender {
 | 
						|
  CefRefPtr<CefBrowser> browser = [self getBrowser];
 | 
						|
  if (browser.get())
 | 
						|
    browser->GetFocusedFrame()->Undo();
 | 
						|
}
 | 
						|
 | 
						|
- (void)redo:(id)sender {
 | 
						|
  CefRefPtr<CefBrowser> browser = [self getBrowser];
 | 
						|
  if (browser.get())
 | 
						|
    browser->GetFocusedFrame()->Redo();
 | 
						|
}
 | 
						|
 | 
						|
- (void)cut:(id)sender {
 | 
						|
  CefRefPtr<CefBrowser> browser = [self getBrowser];
 | 
						|
  if (browser.get())
 | 
						|
    browser->GetFocusedFrame()->Cut();
 | 
						|
}
 | 
						|
 | 
						|
- (void)copy:(id)sender {
 | 
						|
  CefRefPtr<CefBrowser> browser = [self getBrowser];
 | 
						|
  if (browser.get())
 | 
						|
    browser->GetFocusedFrame()->Copy();
 | 
						|
}
 | 
						|
 | 
						|
- (void)paste:(id)sender {
 | 
						|
  CefRefPtr<CefBrowser> browser = [self getBrowser];
 | 
						|
  if (browser.get())
 | 
						|
    browser->GetFocusedFrame()->Paste();
 | 
						|
}
 | 
						|
 | 
						|
- (void)delete:(id)sender {
 | 
						|
  CefRefPtr<CefBrowser> browser = [self getBrowser];
 | 
						|
  if (browser.get())
 | 
						|
    browser->GetFocusedFrame()->Delete();
 | 
						|
}
 | 
						|
 | 
						|
- (void)selectAll:(id)sender {
 | 
						|
  CefRefPtr<CefBrowser> browser = [self getBrowser];
 | 
						|
  if (browser.get())
 | 
						|
    browser->GetFocusedFrame()->SelectAll();
 | 
						|
}
 | 
						|
 | 
						|
- (NSPoint)getClickPointForEvent:(NSEvent*)event {
 | 
						|
  NSPoint windowLocal = [event locationInWindow];
 | 
						|
  NSPoint contentLocal = [self convertPoint:windowLocal fromView:nil];
 | 
						|
 | 
						|
  NSPoint point;
 | 
						|
  point.x = contentLocal.x;
 | 
						|
  point.y = [self frame].size.height - contentLocal.y;  // Flip y.
 | 
						|
  return point;
 | 
						|
}
 | 
						|
 | 
						|
- (void)getKeyEvent:(CefKeyEvent&)keyEvent forEvent:(NSEvent*)event {
 | 
						|
  if ([event type] == NSKeyDown || [event type] == NSKeyUp) {
 | 
						|
    NSString* s = [event characters];
 | 
						|
    if ([s length] > 0)
 | 
						|
      keyEvent.character = [s characterAtIndex:0];
 | 
						|
 | 
						|
    s = [event charactersIgnoringModifiers];
 | 
						|
    if ([s length] > 0)
 | 
						|
      keyEvent.unmodified_character = [s characterAtIndex:0];
 | 
						|
  }
 | 
						|
 | 
						|
  if ([event type] == NSFlagsChanged) {
 | 
						|
    keyEvent.character = 0;
 | 
						|
    keyEvent.unmodified_character = 0;
 | 
						|
  }
 | 
						|
 | 
						|
  keyEvent.native_key_code = [event keyCode];
 | 
						|
 | 
						|
  keyEvent.modifiers = [self getModifiersForEvent:event];
 | 
						|
}
 | 
						|
 | 
						|
- (NSTextInputContext*)inputContext {
 | 
						|
  if (!text_input_context_osr_mac_) {
 | 
						|
    text_input_client_ =
 | 
						|
        [[CefTextInputClientOSRMac alloc] initWithBrowser:[self getBrowser]];
 | 
						|
    text_input_context_osr_mac_ =
 | 
						|
        [[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_;
 | 
						|
}
 | 
						|
 | 
						|
- (void)getMouseEvent:(CefMouseEvent&)mouseEvent forEvent:(NSEvent*)event {
 | 
						|
  const float device_scale_factor = [self getDeviceScaleFactor];
 | 
						|
 | 
						|
  // |point| is in OS X view coordinates.
 | 
						|
  NSPoint point = [self getClickPointForEvent:event];
 | 
						|
 | 
						|
  // Convert to device coordinates.
 | 
						|
  point = [self convertPointToBackingInternal:point];
 | 
						|
 | 
						|
  int device_x = point.x;
 | 
						|
  int device_y = point.y;
 | 
						|
  if ([self isOverPopupWidgetX:device_x andY:device_y])
 | 
						|
    [self applyPopupOffsetToX:device_x andY:device_y];
 | 
						|
 | 
						|
  // Convert to browser view coordinates.
 | 
						|
  mouseEvent.x = client::DeviceToLogical(device_x, device_scale_factor);
 | 
						|
  mouseEvent.y = client::DeviceToLogical(device_y, device_scale_factor);
 | 
						|
 | 
						|
  mouseEvent.modifiers = [self getModifiersForEvent:event];
 | 
						|
}
 | 
						|
 | 
						|
- (void)getMouseEvent:(CefMouseEvent&)mouseEvent
 | 
						|
          forDragInfo:(id<NSDraggingInfo>)info {
 | 
						|
  const float device_scale_factor = [self getDeviceScaleFactor];
 | 
						|
 | 
						|
  // |point| is in OS X view coordinates.
 | 
						|
  NSPoint windowPoint = [info draggingLocation];
 | 
						|
  NSPoint point = [self flipWindowPointToView:windowPoint];
 | 
						|
 | 
						|
  // Convert to device coordinates.
 | 
						|
  point = [self convertPointToBackingInternal:point];
 | 
						|
 | 
						|
  // Convert to browser view coordinates.
 | 
						|
  mouseEvent.x = client::DeviceToLogical(point.x, device_scale_factor);
 | 
						|
  mouseEvent.y = client::DeviceToLogical(point.y, device_scale_factor);
 | 
						|
 | 
						|
  mouseEvent.modifiers = [NSEvent modifierFlags];
 | 
						|
}
 | 
						|
 | 
						|
- (int)getModifiersForEvent:(NSEvent*)event {
 | 
						|
  int modifiers = 0;
 | 
						|
 | 
						|
  if ([event modifierFlags] & NSControlKeyMask)
 | 
						|
    modifiers |= EVENTFLAG_CONTROL_DOWN;
 | 
						|
  if ([event modifierFlags] & NSShiftKeyMask)
 | 
						|
    modifiers |= EVENTFLAG_SHIFT_DOWN;
 | 
						|
  if ([event modifierFlags] & NSAlternateKeyMask)
 | 
						|
    modifiers |= EVENTFLAG_ALT_DOWN;
 | 
						|
  if ([event modifierFlags] & NSCommandKeyMask)
 | 
						|
    modifiers |= EVENTFLAG_COMMAND_DOWN;
 | 
						|
  if ([event modifierFlags] & NSAlphaShiftKeyMask)
 | 
						|
    modifiers |= EVENTFLAG_CAPS_LOCK_ON;
 | 
						|
 | 
						|
  if ([event type] == NSKeyUp || [event type] == NSKeyDown ||
 | 
						|
      [event type] == NSFlagsChanged) {
 | 
						|
    // Only perform this check for key events
 | 
						|
    if ([self isKeyPadEvent:event])
 | 
						|
      modifiers |= EVENTFLAG_IS_KEY_PAD;
 | 
						|
  }
 | 
						|
 | 
						|
  // OS X does not have a modifier for NumLock, so I'm not entirely sure how to
 | 
						|
  // set EVENTFLAG_NUM_LOCK_ON;
 | 
						|
  //
 | 
						|
  // There is no EVENTFLAG for the function key either.
 | 
						|
 | 
						|
  // Mouse buttons
 | 
						|
  switch ([event type]) {
 | 
						|
    case NSLeftMouseDragged:
 | 
						|
    case NSLeftMouseDown:
 | 
						|
    case NSLeftMouseUp:
 | 
						|
      modifiers |= EVENTFLAG_LEFT_MOUSE_BUTTON;
 | 
						|
      break;
 | 
						|
    case NSRightMouseDragged:
 | 
						|
    case NSRightMouseDown:
 | 
						|
    case NSRightMouseUp:
 | 
						|
      modifiers |= EVENTFLAG_RIGHT_MOUSE_BUTTON;
 | 
						|
      break;
 | 
						|
    case NSOtherMouseDragged:
 | 
						|
    case NSOtherMouseDown:
 | 
						|
    case NSOtherMouseUp:
 | 
						|
      modifiers |= EVENTFLAG_MIDDLE_MOUSE_BUTTON;
 | 
						|
      break;
 | 
						|
    default:
 | 
						|
      break;
 | 
						|
  }
 | 
						|
 | 
						|
  return modifiers;
 | 
						|
}
 | 
						|
 | 
						|
- (BOOL)isKeyUpEvent:(NSEvent*)event {
 | 
						|
  if ([event type] != NSFlagsChanged)
 | 
						|
    return [event type] == NSKeyUp;
 | 
						|
 | 
						|
  // FIXME: This logic fails if the user presses both Shift keys at once, for
 | 
						|
  // example: we treat releasing one of them as keyDown.
 | 
						|
  switch ([event keyCode]) {
 | 
						|
    case 54:  // Right Command
 | 
						|
    case 55:  // Left Command
 | 
						|
      return ([event modifierFlags] & NSCommandKeyMask) == 0;
 | 
						|
 | 
						|
    case 57:  // Capslock
 | 
						|
      return ([event modifierFlags] & NSAlphaShiftKeyMask) == 0;
 | 
						|
 | 
						|
    case 56:  // Left Shift
 | 
						|
    case 60:  // Right Shift
 | 
						|
      return ([event modifierFlags] & NSShiftKeyMask) == 0;
 | 
						|
 | 
						|
    case 58:  // Left Alt
 | 
						|
    case 61:  // Right Alt
 | 
						|
      return ([event modifierFlags] & NSAlternateKeyMask) == 0;
 | 
						|
 | 
						|
    case 59:  // Left Ctrl
 | 
						|
    case 62:  // Right Ctrl
 | 
						|
      return ([event modifierFlags] & NSControlKeyMask) == 0;
 | 
						|
 | 
						|
    case 63:  // Function
 | 
						|
      return ([event modifierFlags] & NSFunctionKeyMask) == 0;
 | 
						|
  }
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
- (BOOL)isKeyPadEvent:(NSEvent*)event {
 | 
						|
  if ([event modifierFlags] & NSNumericPadKeyMask)
 | 
						|
    return true;
 | 
						|
 | 
						|
  switch ([event keyCode]) {
 | 
						|
    case 71:  // Clear
 | 
						|
    case 81:  // =
 | 
						|
    case 75:  // /
 | 
						|
    case 67:  // *
 | 
						|
    case 78:  // -
 | 
						|
    case 69:  // +
 | 
						|
    case 76:  // Enter
 | 
						|
    case 65:  // .
 | 
						|
    case 82:  // 0
 | 
						|
    case 83:  // 1
 | 
						|
    case 84:  // 2
 | 
						|
    case 85:  // 3
 | 
						|
    case 86:  // 4
 | 
						|
    case 87:  // 5
 | 
						|
    case 88:  // 6
 | 
						|
    case 89:  // 7
 | 
						|
    case 91:  // 8
 | 
						|
    case 92:  // 9
 | 
						|
      return true;
 | 
						|
  }
 | 
						|
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
- (void)windowDidChangeBackingProperties:(NSNotification*)notification {
 | 
						|
  // This delegate method is only called on 10.7 and later, so don't worry about
 | 
						|
  // other backing changes calling it on 10.6 or earlier
 | 
						|
  [self resetDeviceScaleFactor];
 | 
						|
}
 | 
						|
 | 
						|
- (void)drawRect:(NSRect)dirtyRect {
 | 
						|
  CefRefPtr<CefBrowser> browser = [self getBrowser];
 | 
						|
  if ([self inLiveResize] || !browser.get()) {
 | 
						|
    // Fill with the background color.
 | 
						|
    const cef_color_t background_color =
 | 
						|
        client::MainContext::Get()->GetBackgroundColor();
 | 
						|
    NSColor* color = [NSColor
 | 
						|
        colorWithCalibratedRed:float(CefColorGetR(background_color)) / 255.0f
 | 
						|
                         green:float(CefColorGetG(background_color)) / 255.0f
 | 
						|
                          blue:float(CefColorGetB(background_color)) / 255.0f
 | 
						|
                         alpha:1.f];
 | 
						|
    [color setFill];
 | 
						|
    NSRectFill(dirtyRect);
 | 
						|
  }
 | 
						|
 | 
						|
  // The Invalidate below fixes flicker when resizing.
 | 
						|
  if ([self inLiveResize] && browser.get())
 | 
						|
    browser->GetHost()->Invalidate(PET_VIEW);
 | 
						|
}
 | 
						|
 | 
						|
// Drag and drop
 | 
						|
 | 
						|
- (BOOL)startDragging:(CefRefPtr<CefDragData>)drag_data
 | 
						|
           allowedOps:(NSDragOperation)ops
 | 
						|
                point:(NSPoint)position {
 | 
						|
  DCHECK(!pasteboard_);
 | 
						|
  DCHECK(!fileUTI_);
 | 
						|
  DCHECK(!current_drag_data_.get());
 | 
						|
 | 
						|
  [self resetDragDrop];
 | 
						|
 | 
						|
  current_allowed_ops_ = ops;
 | 
						|
  current_drag_data_ = drag_data;
 | 
						|
 | 
						|
  [self fillPasteboard];
 | 
						|
 | 
						|
  NSEvent* currentEvent = [[NSApplication sharedApplication] currentEvent];
 | 
						|
  NSWindow* window = [self window];
 | 
						|
  NSTimeInterval eventTime = [currentEvent timestamp];
 | 
						|
 | 
						|
  NSEvent* dragEvent = [NSEvent mouseEventWithType:NSLeftMouseDragged
 | 
						|
                                          location:position
 | 
						|
                                     modifierFlags:NSLeftMouseDraggedMask
 | 
						|
                                         timestamp:eventTime
 | 
						|
                                      windowNumber:[window windowNumber]
 | 
						|
                                           context:nil
 | 
						|
                                       eventNumber:0
 | 
						|
                                        clickCount:1
 | 
						|
                                          pressure:1.0];
 | 
						|
 | 
						|
  // TODO(cef): Pass a non-nil value to dragImage (see issue #1715). For now
 | 
						|
  // work around the "callee requires a non-null argument" error that occurs
 | 
						|
  // when building with the 10.11 SDK.
 | 
						|
  id nilArg = nil;
 | 
						|
  [window dragImage:nilArg
 | 
						|
                 at:position
 | 
						|
             offset:NSZeroSize
 | 
						|
              event:dragEvent
 | 
						|
         pasteboard:pasteboard_
 | 
						|
             source:self
 | 
						|
          slideBack:YES];
 | 
						|
  return YES;
 | 
						|
}
 | 
						|
 | 
						|
- (void)setCurrentDragOp:(NSDragOperation)op {
 | 
						|
  current_drag_op_ = op;
 | 
						|
}
 | 
						|
 | 
						|
// NSDraggingSource Protocol
 | 
						|
 | 
						|
- (NSDragOperation)draggingSession:(NSDraggingSession*)session
 | 
						|
    sourceOperationMaskForDraggingContext:(NSDraggingContext)context {
 | 
						|
  switch (context) {
 | 
						|
    case NSDraggingContextOutsideApplication:
 | 
						|
      return current_allowed_ops_;
 | 
						|
 | 
						|
    case NSDraggingContextWithinApplication:
 | 
						|
    default:
 | 
						|
      return current_allowed_ops_;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
- (NSArray*)namesOfPromisedFilesDroppedAtDestination:(NSURL*)dropDest {
 | 
						|
  if (![dropDest isFileURL])
 | 
						|
    return nil;
 | 
						|
 | 
						|
  if (!current_drag_data_)
 | 
						|
    return nil;
 | 
						|
 | 
						|
  size_t expected_size = current_drag_data_->GetFileContents(NULL);
 | 
						|
  if (expected_size == 0)
 | 
						|
    return nil;
 | 
						|
 | 
						|
  std::string path = [[dropDest path] UTF8String];
 | 
						|
  path.append("/");
 | 
						|
  path.append(current_drag_data_->GetFileName().ToString());
 | 
						|
 | 
						|
  CefRefPtr<CefStreamWriter> writer = CefStreamWriter::CreateForFile(path);
 | 
						|
  if (!writer)
 | 
						|
    return nil;
 | 
						|
 | 
						|
  if (current_drag_data_->GetFileContents(writer) != expected_size)
 | 
						|
    return nil;
 | 
						|
 | 
						|
  return @[ [NSString stringWithUTF8String:path.c_str()] ];
 | 
						|
}
 | 
						|
 | 
						|
- (void)draggedImage:(NSImage*)anImage
 | 
						|
             endedAt:(NSPoint)screenPoint
 | 
						|
           operation:(NSDragOperation)operation {
 | 
						|
  CefRefPtr<CefBrowser> browser = [self getBrowser];
 | 
						|
  if (!browser.get())
 | 
						|
    return;
 | 
						|
 | 
						|
  if (operation == (NSDragOperationMove | NSDragOperationCopy))
 | 
						|
    operation &= ~NSDragOperationMove;
 | 
						|
 | 
						|
  NSPoint windowPoint = [[self window] convertScreenToBase:screenPoint];
 | 
						|
  NSPoint pt = [self flipWindowPointToView:windowPoint];
 | 
						|
  CefRenderHandler::DragOperation op =
 | 
						|
      static_cast<CefRenderHandler::DragOperation>(operation);
 | 
						|
  browser->GetHost()->DragSourceEndedAt(pt.x, pt.y, op);
 | 
						|
  browser->GetHost()->DragSourceSystemDragEnded();
 | 
						|
  [self resetDragDrop];
 | 
						|
}
 | 
						|
 | 
						|
// NSDraggingDestination Protocol
 | 
						|
 | 
						|
- (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)info {
 | 
						|
  CefRefPtr<CefBrowser> browser = [self getBrowser];
 | 
						|
  if (!browser.get())
 | 
						|
    return NSDragOperationNone;
 | 
						|
 | 
						|
  CefRefPtr<CefDragData> drag_data;
 | 
						|
  if (!current_drag_data_) {
 | 
						|
    drag_data = CefDragData::Create();
 | 
						|
    [self populateDropData:drag_data fromPasteboard:[info draggingPasteboard]];
 | 
						|
  } else {
 | 
						|
    drag_data = current_drag_data_->Clone();
 | 
						|
    drag_data->ResetFileContents();
 | 
						|
  }
 | 
						|
 | 
						|
  CefMouseEvent mouseEvent;
 | 
						|
  [self getMouseEvent:mouseEvent forDragInfo:info];
 | 
						|
 | 
						|
  NSDragOperation mask = [info draggingSourceOperationMask];
 | 
						|
  CefBrowserHost::DragOperationsMask allowed_ops =
 | 
						|
      static_cast<CefBrowserHost::DragOperationsMask>(mask);
 | 
						|
 | 
						|
  browser->GetHost()->DragTargetDragEnter(drag_data, mouseEvent, allowed_ops);
 | 
						|
  browser->GetHost()->DragTargetDragOver(mouseEvent, allowed_ops);
 | 
						|
 | 
						|
  current_drag_op_ = NSDragOperationCopy;
 | 
						|
  return current_drag_op_;
 | 
						|
}
 | 
						|
 | 
						|
- (void)draggingExited:(id<NSDraggingInfo>)sender {
 | 
						|
  CefRefPtr<CefBrowser> browser = [self getBrowser];
 | 
						|
  if (browser.get())
 | 
						|
    browser->GetHost()->DragTargetDragLeave();
 | 
						|
}
 | 
						|
 | 
						|
- (BOOL)prepareForDragOperation:(id<NSDraggingInfo>)info {
 | 
						|
  return YES;
 | 
						|
}
 | 
						|
 | 
						|
- (BOOL)performDragOperation:(id<NSDraggingInfo>)info {
 | 
						|
  CefRefPtr<CefBrowser> browser = [self getBrowser];
 | 
						|
  if (!browser.get())
 | 
						|
    return NO;
 | 
						|
 | 
						|
  CefMouseEvent mouseEvent;
 | 
						|
  [self getMouseEvent:mouseEvent forDragInfo:info];
 | 
						|
 | 
						|
  browser->GetHost()->DragTargetDrop(mouseEvent);
 | 
						|
 | 
						|
  return YES;
 | 
						|
}
 | 
						|
 | 
						|
- (NSDragOperation)draggingUpdated:(id<NSDraggingInfo>)info {
 | 
						|
  CefRefPtr<CefBrowser> browser = [self getBrowser];
 | 
						|
  if (!browser.get())
 | 
						|
    return NSDragOperationNone;
 | 
						|
 | 
						|
  CefMouseEvent mouseEvent;
 | 
						|
  [self getMouseEvent:mouseEvent forDragInfo:info];
 | 
						|
 | 
						|
  NSDragOperation mask = [info draggingSourceOperationMask];
 | 
						|
  CefBrowserHost::DragOperationsMask allowed_ops =
 | 
						|
      static_cast<CefBrowserHost::DragOperationsMask>(mask);
 | 
						|
 | 
						|
  browser->GetHost()->DragTargetDragOver(mouseEvent, allowed_ops);
 | 
						|
 | 
						|
  return current_drag_op_;
 | 
						|
}
 | 
						|
 | 
						|
// NSPasteboardOwner Protocol
 | 
						|
 | 
						|
- (void)pasteboard:(NSPasteboard*)pboard provideDataForType:(NSString*)type {
 | 
						|
  if (!current_drag_data_) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  // URL.
 | 
						|
  if ([type isEqualToString:NSURLPboardType]) {
 | 
						|
    DCHECK(current_drag_data_->IsLink());
 | 
						|
    NSString* strUrl =
 | 
						|
        [NSString stringWithUTF8String:current_drag_data_->GetLinkURL()
 | 
						|
                                           .ToString()
 | 
						|
                                           .c_str()];
 | 
						|
    NSURL* url = [NSURL URLWithString:strUrl];
 | 
						|
    [url writeToPasteboard:pboard];
 | 
						|
    // URL title.
 | 
						|
  } else if ([type isEqualToString:kNSURLTitlePboardType]) {
 | 
						|
    NSString* strTitle =
 | 
						|
        [NSString stringWithUTF8String:current_drag_data_->GetLinkTitle()
 | 
						|
                                           .ToString()
 | 
						|
                                           .c_str()];
 | 
						|
    [pboard setString:strTitle forType:kNSURLTitlePboardType];
 | 
						|
 | 
						|
    // File contents.
 | 
						|
  } else if ([type isEqualToString:fileUTI_]) {
 | 
						|
    size_t size = current_drag_data_->GetFileContents(NULL);
 | 
						|
    DCHECK_GT(size, 0U);
 | 
						|
    CefRefPtr<client::BytesWriteHandler> handler =
 | 
						|
        new client::BytesWriteHandler(size);
 | 
						|
    CefRefPtr<CefStreamWriter> writer =
 | 
						|
        CefStreamWriter::CreateForHandler(handler.get());
 | 
						|
    current_drag_data_->GetFileContents(writer);
 | 
						|
    DCHECK_EQ(handler->GetDataSize(), static_cast<int64>(size));
 | 
						|
 | 
						|
    [pboard setData:[NSData dataWithBytes:handler->GetData()
 | 
						|
                                   length:handler->GetDataSize()]
 | 
						|
            forType:fileUTI_];
 | 
						|
 | 
						|
    // Plain text.
 | 
						|
  } else if ([type isEqualToString:NSStringPboardType]) {
 | 
						|
    NSString* strTitle =
 | 
						|
        [NSString stringWithUTF8String:current_drag_data_->GetFragmentText()
 | 
						|
                                           .ToString()
 | 
						|
                                           .c_str()];
 | 
						|
    [pboard setString:strTitle forType:NSStringPboardType];
 | 
						|
 | 
						|
  } else if ([type isEqualToString:kCEFDragDummyPboardType]) {
 | 
						|
    // The dummy type _was_ promised and someone decided to call the bluff.
 | 
						|
    [pboard setData:[NSData data] forType:kCEFDragDummyPboardType];
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
// NSAccessibility Protocol implementation.
 | 
						|
- (BOOL)accessibilityIsIgnored {
 | 
						|
  if (!accessibility_helper_)
 | 
						|
    return YES;
 | 
						|
  else
 | 
						|
    return NO;
 | 
						|
}
 | 
						|
 | 
						|
- (id)accessibilityAttributeValue:(NSString*)attribute {
 | 
						|
  if (!accessibility_helper_)
 | 
						|
    return [super accessibilityAttributeValue:attribute];
 | 
						|
  if ([attribute isEqualToString:NSAccessibilityRoleAttribute]) {
 | 
						|
    return NSAccessibilityGroupRole;
 | 
						|
  } else if ([attribute isEqualToString:NSAccessibilityDescriptionAttribute]) {
 | 
						|
    client::OsrAXNode* node = accessibility_helper_->GetRootNode();
 | 
						|
    std::string desc = node ? node->AxDescription() : "";
 | 
						|
    return [NSString stringWithUTF8String:desc.c_str()];
 | 
						|
  } else if ([attribute isEqualToString:NSAccessibilityValueAttribute]) {
 | 
						|
    client::OsrAXNode* node = accessibility_helper_->GetRootNode();
 | 
						|
    std::string desc = node ? node->AxValue() : "";
 | 
						|
    return [NSString stringWithUTF8String:desc.c_str()];
 | 
						|
  } else if ([attribute
 | 
						|
                 isEqualToString:NSAccessibilityRoleDescriptionAttribute]) {
 | 
						|
    return NSAccessibilityRoleDescriptionForUIElement(self);
 | 
						|
  } else if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) {
 | 
						|
    client::OsrAXNode* node = accessibility_helper_->GetRootNode();
 | 
						|
    // Add Root as first Kid
 | 
						|
    NSMutableArray* kids = [NSMutableArray arrayWithCapacity:1];
 | 
						|
    NSObject* child = CAST_CEF_NATIVE_ACCESSIBLE_TO_NSOBJECT(
 | 
						|
        node->GetNativeAccessibleObject(NULL));
 | 
						|
    [kids addObject:child];
 | 
						|
    return NSAccessibilityUnignoredChildren(kids);
 | 
						|
  } else {
 | 
						|
    return [super accessibilityAttributeValue:attribute];
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
- (id)accessibilityFocusedUIElement {
 | 
						|
  if (accessibility_helper_) {
 | 
						|
    client::OsrAXNode* node = accessibility_helper_->GetFocusedNode();
 | 
						|
    return node ? CAST_CEF_NATIVE_ACCESSIBLE_TO_NSOBJECT(
 | 
						|
                      node->GetNativeAccessibleObject(NULL))
 | 
						|
                : nil;
 | 
						|
  }
 | 
						|
  return nil;
 | 
						|
}
 | 
						|
 | 
						|
// Utility methods.
 | 
						|
- (void)resetDragDrop {
 | 
						|
  current_drag_op_ = NSDragOperationNone;
 | 
						|
  current_allowed_ops_ = NSDragOperationNone;
 | 
						|
  current_drag_data_ = NULL;
 | 
						|
  if (fileUTI_) {
 | 
						|
#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];
 | 
						|
#if !__has_feature(objc_arc)
 | 
						|
  [pasteboard_ retain];
 | 
						|
#endif  // !__has_feature(objc_arc)
 | 
						|
 | 
						|
  [pasteboard_ declareTypes:@[ kCEFDragDummyPboardType ] owner:self];
 | 
						|
 | 
						|
  // URL (and title).
 | 
						|
  if (current_drag_data_->IsLink()) {
 | 
						|
    [pasteboard_ addTypes:@[ NSURLPboardType, kNSURLTitlePboardType ]
 | 
						|
                    owner:self];
 | 
						|
  }
 | 
						|
 | 
						|
  // MIME type.
 | 
						|
  CefString mimeType;
 | 
						|
  size_t contents_size = current_drag_data_->GetFileContents(NULL);
 | 
						|
  CefString download_metadata = current_drag_data_->GetLinkMetadata();
 | 
						|
  CefString file_name = current_drag_data_->GetFileName();
 | 
						|
 | 
						|
  // File.
 | 
						|
  if (contents_size > 0) {
 | 
						|
    std::string file_name = current_drag_data_->GetFileName().ToString();
 | 
						|
    size_t sep = file_name.find_last_of(".");
 | 
						|
    CefString extension = file_name.substr(sep + 1);
 | 
						|
 | 
						|
    mimeType = CefGetMimeType(extension);
 | 
						|
 | 
						|
    if (!mimeType.empty()) {
 | 
						|
      CFStringRef mimeTypeCF;
 | 
						|
      mimeTypeCF = CFStringCreateWithCString(kCFAllocatorDefault,
 | 
						|
                                             mimeType.ToString().c_str(),
 | 
						|
                                             kCFStringEncodingUTF8);
 | 
						|
      fileUTI_ = (__bridge NSString*)UTTypeCreatePreferredIdentifierForTag(
 | 
						|
          kUTTagClassMIMEType, mimeTypeCF, NULL);
 | 
						|
      CFRelease(mimeTypeCF);
 | 
						|
      // File (HFS) promise.
 | 
						|
      NSArray* fileUTIList = @[ fileUTI_ ];
 | 
						|
      [pasteboard_ addTypes:@[ NSFilesPromisePboardType ] owner:self];
 | 
						|
      [pasteboard_ setPropertyList:fileUTIList
 | 
						|
                           forType:NSFilesPromisePboardType];
 | 
						|
 | 
						|
      [pasteboard_ addTypes:fileUTIList owner:self];
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // Plain text.
 | 
						|
  if (!current_drag_data_->GetFragmentText().empty()) {
 | 
						|
    [pasteboard_ addTypes:@[ NSStringPboardType ] owner:self];
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
- (void)populateDropData:(CefRefPtr<CefDragData>)data
 | 
						|
          fromPasteboard:(NSPasteboard*)pboard {
 | 
						|
  DCHECK(data);
 | 
						|
  DCHECK(pboard);
 | 
						|
  DCHECK(data && !data->IsReadOnly());
 | 
						|
  NSArray* types = [pboard types];
 | 
						|
 | 
						|
  // Get plain text.
 | 
						|
  if ([types containsObject:NSStringPboardType]) {
 | 
						|
    data->SetFragmentText(
 | 
						|
        [[pboard stringForType:NSStringPboardType] UTF8String]);
 | 
						|
  }
 | 
						|
 | 
						|
  // Get files.
 | 
						|
  if ([types containsObject:NSFilenamesPboardType]) {
 | 
						|
    NSArray* files = [pboard propertyListForType:NSFilenamesPboardType];
 | 
						|
    if ([files isKindOfClass:[NSArray class]] && [files count]) {
 | 
						|
      for (NSUInteger i = 0; i < [files count]; i++) {
 | 
						|
        NSString* filename = [files objectAtIndex:i];
 | 
						|
        BOOL exists =
 | 
						|
            [[NSFileManager defaultManager] fileExistsAtPath:filename];
 | 
						|
        if (exists) {
 | 
						|
          data->AddFile([filename UTF8String], CefString());
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
- (NSPoint)flipWindowPointToView:(const NSPoint&)windowPoint {
 | 
						|
  NSPoint viewPoint = [self convertPoint:windowPoint fromView:nil];
 | 
						|
  NSRect viewFrame = [self frame];
 | 
						|
  viewPoint.y = viewFrame.size.height - viewPoint.y;
 | 
						|
  return viewPoint;
 | 
						|
}
 | 
						|
 | 
						|
- (void)resetDeviceScaleFactor {
 | 
						|
  float device_scale_factor = 1.0f;
 | 
						|
  NSWindow* window = [self window];
 | 
						|
  if (window)
 | 
						|
    device_scale_factor = [window backingScaleFactor];
 | 
						|
  [self setDeviceScaleFactor:device_scale_factor];
 | 
						|
}
 | 
						|
 | 
						|
- (void)setDeviceScaleFactor:(float)device_scale_factor {
 | 
						|
  if (device_scale_factor == device_scale_factor_)
 | 
						|
    return;
 | 
						|
 | 
						|
  // Apply some sanity checks.
 | 
						|
  if (device_scale_factor < 1.0f || device_scale_factor > 4.0f)
 | 
						|
    return;
 | 
						|
 | 
						|
  device_scale_factor_ = device_scale_factor;
 | 
						|
 | 
						|
  CefRefPtr<CefBrowser> browser = [self getBrowser];
 | 
						|
  if (browser) {
 | 
						|
    browser->GetHost()->NotifyScreenInfoChanged();
 | 
						|
    browser->GetHost()->WasResized();
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
- (float)getDeviceScaleFactor {
 | 
						|
  return device_scale_factor_;
 | 
						|
}
 | 
						|
 | 
						|
- (void)viewDidChangeBackingProperties {
 | 
						|
  const CGFloat device_scale_factor = [self getDeviceScaleFactor];
 | 
						|
 | 
						|
  if (device_scale_factor == device_scale_factor_)
 | 
						|
    return;
 | 
						|
 | 
						|
  CefRefPtr<CefBrowser> browser = [self getBrowser];
 | 
						|
  if (browser) {
 | 
						|
    browser->GetHost()->NotifyScreenInfoChanged();
 | 
						|
    browser->GetHost()->WasResized();
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
- (bool)isOverPopupWidgetX:(int)x andY:(int)y {
 | 
						|
  CefRect rc = renderer_->popup_rect();
 | 
						|
  int popup_right = rc.x + rc.width;
 | 
						|
  int popup_bottom = rc.y + rc.height;
 | 
						|
  return (x >= rc.x) && (x < popup_right) && (y >= rc.y) && (y < popup_bottom);
 | 
						|
}
 | 
						|
 | 
						|
- (int)getPopupXOffset {
 | 
						|
  return renderer_->original_popup_rect().x - renderer_->popup_rect().x;
 | 
						|
}
 | 
						|
 | 
						|
- (int)getPopupYOffset {
 | 
						|
  return renderer_->original_popup_rect().y - renderer_->popup_rect().y;
 | 
						|
}
 | 
						|
 | 
						|
- (void)applyPopupOffsetToX:(int&)x andY:(int&)y {
 | 
						|
  if ([self isOverPopupWidgetX:x andY:y]) {
 | 
						|
    x += [self getPopupXOffset];
 | 
						|
    y += [self getPopupYOffset];
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
// Convert from scaled coordinates to view coordinates.
 | 
						|
- (NSPoint)convertPointFromBackingInternal:(NSPoint)aPoint {
 | 
						|
  return [self convertPointFromBacking:aPoint];
 | 
						|
}
 | 
						|
 | 
						|
// Convert from view coordinates to scaled coordinates.
 | 
						|
- (NSPoint)convertPointToBackingInternal:(NSPoint)aPoint {
 | 
						|
  return [self convertPointToBacking:aPoint];
 | 
						|
}
 | 
						|
 | 
						|
// Convert from scaled coordinates to view coordinates.
 | 
						|
- (NSRect)convertRectFromBackingInternal:(NSRect)aRect {
 | 
						|
  return [self convertRectFromBacking:aRect];
 | 
						|
}
 | 
						|
 | 
						|
// Convert from view coordinates to scaled coordinates.
 | 
						|
- (NSRect)convertRectToBackingInternal:(NSRect)aRect {
 | 
						|
  return [self convertRectToBacking:aRect];
 | 
						|
}
 | 
						|
 | 
						|
- (void)ChangeCompositionRange:(CefRange)range
 | 
						|
              character_bounds:(const CefRenderHandler::RectList&)bounds {
 | 
						|
  if (text_input_client_)
 | 
						|
    [text_input_client_ ChangeCompositionRange:range character_bounds:bounds];
 | 
						|
}
 | 
						|
 | 
						|
- (void)UpdateAccessibilityTree:(CefRefPtr<CefValue>)value {
 | 
						|
  if (!accessibility_helper_) {
 | 
						|
    accessibility_helper_ =
 | 
						|
        new client::OsrAccessibilityHelper(value, [self getBrowser]);
 | 
						|
  } else {
 | 
						|
    accessibility_helper_->UpdateAccessibilityTree(value);
 | 
						|
  }
 | 
						|
 | 
						|
  if (accessibility_helper_) {
 | 
						|
    NSAccessibilityPostNotification(self,
 | 
						|
                                    NSAccessibilityValueChangedNotification);
 | 
						|
  }
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
- (void)UpdateAccessibilityLocation:(CefRefPtr<CefValue>)value {
 | 
						|
  if (accessibility_helper_) {
 | 
						|
    accessibility_helper_->UpdateAccessibilityLocation(value);
 | 
						|
  }
 | 
						|
 | 
						|
  if (accessibility_helper_) {
 | 
						|
    NSAccessibilityPostNotification(self,
 | 
						|
                                    NSAccessibilityValueChangedNotification);
 | 
						|
  }
 | 
						|
  return;
 | 
						|
}
 | 
						|
@end
 | 
						|
 | 
						|
namespace client {
 | 
						|
 | 
						|
class BrowserWindowOsrMacImpl {
 | 
						|
 public:
 | 
						|
  BrowserWindowOsrMacImpl(BrowserWindow::Delegate* delegate,
 | 
						|
                          const std::string& startup_url,
 | 
						|
                          const OsrRendererSettings& settings,
 | 
						|
                          BrowserWindowOsrMac& browser_window);
 | 
						|
  ~BrowserWindowOsrMacImpl();
 | 
						|
 | 
						|
  // BrowserWindow methods.
 | 
						|
  void CreateBrowser(ClientWindowHandle parent_handle,
 | 
						|
                     const CefRect& rect,
 | 
						|
                     const CefBrowserSettings& settings,
 | 
						|
                     CefRefPtr<CefDictionaryValue> extra_info,
 | 
						|
                     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,
 | 
						|
                      cef_cursor_type_t 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|.
 | 
						|
    [native_browser_view_ detach];
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void BrowserWindowOsrMacImpl::CreateBrowser(
 | 
						|
    ClientWindowHandle parent_handle,
 | 
						|
    const CefRect& rect,
 | 
						|
    const CefBrowserSettings& settings,
 | 
						|
    CefRefPtr<CefDictionaryValue> extra_info,
 | 
						|
    CefRefPtr<CefRequestContext> request_context) {
 | 
						|
  REQUIRE_MAIN_THREAD();
 | 
						|
 | 
						|
  // Create the native NSView.
 | 
						|
  Create(parent_handle, rect);
 | 
						|
 | 
						|
  CefWindowInfo window_info;
 | 
						|
  window_info.SetAsWindowless(
 | 
						|
      CAST_NSVIEW_TO_CEF_WINDOW_HANDLE(native_browser_view_));
 | 
						|
 | 
						|
  // Create the browser asynchronously.
 | 
						|
  CefBrowserHost::CreateBrowser(window_info, browser_window_.client_handler_,
 | 
						|
                                browser_window_.client_handler_->startup_url(),
 | 
						|
                                settings, extra_info, request_context);
 | 
						|
}
 | 
						|
 | 
						|
void BrowserWindowOsrMacImpl::GetPopupConfig(CefWindowHandle temp_handle,
 | 
						|
                                             CefWindowInfo& windowInfo,
 | 
						|
                                             CefRefPtr<CefClient>& client,
 | 
						|
                                             CefBrowserSettings& settings) {
 | 
						|
  CEF_REQUIRE_UI_THREAD();
 | 
						|
 | 
						|
  windowInfo.SetAsWindowless(temp_handle);
 | 
						|
  client = browser_window_.client_handler_;
 | 
						|
}
 | 
						|
 | 
						|
void BrowserWindowOsrMacImpl::ShowPopup(ClientWindowHandle parent_handle,
 | 
						|
                                        int x,
 | 
						|
                                        int y,
 | 
						|
                                        size_t width,
 | 
						|
                                        size_t height) {
 | 
						|
  REQUIRE_MAIN_THREAD();
 | 
						|
  DCHECK(browser_window_.browser_.get());
 | 
						|
 | 
						|
  // Create the native NSView.
 | 
						|
  Create(parent_handle,
 | 
						|
         CefRect(x, y, static_cast<int>(width), static_cast<int>(height)));
 | 
						|
 | 
						|
  // Send resize notification so the compositor is assigned the correct
 | 
						|
  // viewport size and begins rendering.
 | 
						|
  browser_window_.browser_->GetHost()->WasResized();
 | 
						|
 | 
						|
  Show();
 | 
						|
}
 | 
						|
 | 
						|
void BrowserWindowOsrMacImpl::Show() {
 | 
						|
  REQUIRE_MAIN_THREAD();
 | 
						|
 | 
						|
  if (hidden_) {
 | 
						|
    // Set the browser as visible.
 | 
						|
    browser_window_.browser_->GetHost()->WasHidden(false);
 | 
						|
    hidden_ = false;
 | 
						|
  }
 | 
						|
 | 
						|
  // Give focus to the browser.
 | 
						|
  browser_window_.browser_->GetHost()->SendFocusEvent(true);
 | 
						|
}
 | 
						|
 | 
						|
void BrowserWindowOsrMacImpl::Hide() {
 | 
						|
  REQUIRE_MAIN_THREAD();
 | 
						|
 | 
						|
  if (!browser_window_.browser_.get())
 | 
						|
    return;
 | 
						|
 | 
						|
  // Remove focus from the browser.
 | 
						|
  browser_window_.browser_->GetHost()->SendFocusEvent(false);
 | 
						|
 | 
						|
  if (!hidden_) {
 | 
						|
    // Set the browser as hidden.
 | 
						|
    browser_window_.browser_->GetHost()->WasHidden(true);
 | 
						|
    hidden_ = true;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
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 BrowserWindowOsrMacImpl::SetFocus(bool focus) {
 | 
						|
  REQUIRE_MAIN_THREAD();
 | 
						|
  if (native_browser_view_)
 | 
						|
    [native_browser_view_.window makeFirstResponder:native_browser_view_];
 | 
						|
}
 | 
						|
 | 
						|
void BrowserWindowOsrMacImpl::SetDeviceScaleFactor(float device_scale_factor) {
 | 
						|
  REQUIRE_MAIN_THREAD();
 | 
						|
  if (native_browser_view_)
 | 
						|
    [native_browser_view_ setDeviceScaleFactor:device_scale_factor];
 | 
						|
}
 | 
						|
 | 
						|
float BrowserWindowOsrMacImpl::GetDeviceScaleFactor() const {
 | 
						|
  REQUIRE_MAIN_THREAD();
 | 
						|
  if (native_browser_view_)
 | 
						|
    return [native_browser_view_ getDeviceScaleFactor];
 | 
						|
  return 1.0f;
 | 
						|
}
 | 
						|
 | 
						|
ClientWindowHandle BrowserWindowOsrMacImpl::GetWindowHandle() const {
 | 
						|
  REQUIRE_MAIN_THREAD();
 | 
						|
  return CAST_NSVIEW_TO_CEF_WINDOW_HANDLE(native_browser_view_);
 | 
						|
}
 | 
						|
 | 
						|
void BrowserWindowOsrMacImpl::OnAfterCreated(CefRefPtr<CefBrowser> browser) {
 | 
						|
  CEF_REQUIRE_UI_THREAD();
 | 
						|
}
 | 
						|
 | 
						|
void BrowserWindowOsrMacImpl::OnBeforeClose(CefRefPtr<CefBrowser> browser) {
 | 
						|
  CEF_REQUIRE_UI_THREAD();
 | 
						|
  REQUIRE_MAIN_THREAD();
 | 
						|
 | 
						|
  // Detach |this| from the ClientHandlerOsr.
 | 
						|
  static_cast<ClientHandlerOsr*>(browser_window_.client_handler_.get())
 | 
						|
      ->DetachOsrDelegate();
 | 
						|
}
 | 
						|
 | 
						|
bool BrowserWindowOsrMacImpl::GetRootScreenRect(CefRefPtr<CefBrowser> browser,
 | 
						|
                                                CefRect& rect) {
 | 
						|
  CEF_REQUIRE_UI_THREAD();
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
void BrowserWindowOsrMacImpl::GetViewRect(CefRefPtr<CefBrowser> browser,
 | 
						|
                                          CefRect& rect) {
 | 
						|
  CEF_REQUIRE_UI_THREAD();
 | 
						|
  REQUIRE_MAIN_THREAD();
 | 
						|
 | 
						|
  rect.x = rect.y = 0;
 | 
						|
 | 
						|
  if (!native_browser_view_) {
 | 
						|
    // Never return an empty rectangle.
 | 
						|
    rect.width = rect.height = 1;
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  const float device_scale_factor = [native_browser_view_ getDeviceScaleFactor];
 | 
						|
 | 
						|
  // |bounds| is in OS X view coordinates.
 | 
						|
  NSRect bounds = native_browser_view_.bounds;
 | 
						|
 | 
						|
  // Convert to device coordinates.
 | 
						|
  bounds = [native_browser_view_ convertRectToBackingInternal:bounds];
 | 
						|
 | 
						|
  // Convert to browser view coordinates.
 | 
						|
  rect.width = DeviceToLogical(bounds.size.width, device_scale_factor);
 | 
						|
  if (rect.width == 0)
 | 
						|
    rect.width = 1;
 | 
						|
  rect.height = DeviceToLogical(bounds.size.height, device_scale_factor);
 | 
						|
  if (rect.height == 0)
 | 
						|
    rect.height = 1;
 | 
						|
}
 | 
						|
 | 
						|
bool BrowserWindowOsrMacImpl::GetScreenPoint(CefRefPtr<CefBrowser> browser,
 | 
						|
                                             int viewX,
 | 
						|
                                             int viewY,
 | 
						|
                                             int& screenX,
 | 
						|
                                             int& screenY) {
 | 
						|
  CEF_REQUIRE_UI_THREAD();
 | 
						|
  REQUIRE_MAIN_THREAD();
 | 
						|
 | 
						|
  if (!native_browser_view_)
 | 
						|
    return false;
 | 
						|
 | 
						|
  const float device_scale_factor = [native_browser_view_ getDeviceScaleFactor];
 | 
						|
 | 
						|
  // (viewX, viewX) is in browser view coordinates.
 | 
						|
  // Convert to device coordinates.
 | 
						|
  NSPoint view_pt = NSMakePoint(LogicalToDevice(viewX, device_scale_factor),
 | 
						|
                                LogicalToDevice(viewY, device_scale_factor));
 | 
						|
 | 
						|
  // Convert to OS X view coordinates.
 | 
						|
  view_pt = [native_browser_view_ convertPointFromBackingInternal:view_pt];
 | 
						|
 | 
						|
  // Reverse the Y component.
 | 
						|
  const NSRect bounds = native_browser_view_.bounds;
 | 
						|
  view_pt.y = bounds.size.height - view_pt.y;
 | 
						|
 | 
						|
  // Convert to screen coordinates.
 | 
						|
  NSPoint window_pt = [native_browser_view_ convertPoint:view_pt toView:nil];
 | 
						|
  NSPoint screen_pt =
 | 
						|
      ConvertPointFromWindowToScreen(native_browser_view_.window, window_pt);
 | 
						|
 | 
						|
  screenX = screen_pt.x;
 | 
						|
  screenY = screen_pt.y;
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
bool BrowserWindowOsrMacImpl::GetScreenInfo(CefRefPtr<CefBrowser> browser,
 | 
						|
                                            CefScreenInfo& screen_info) {
 | 
						|
  CEF_REQUIRE_UI_THREAD();
 | 
						|
  REQUIRE_MAIN_THREAD();
 | 
						|
 | 
						|
  if (!native_browser_view_)
 | 
						|
    return false;
 | 
						|
 | 
						|
  CefRect view_rect;
 | 
						|
  GetViewRect(browser, view_rect);
 | 
						|
 | 
						|
  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.
 | 
						|
  screen_info.rect = view_rect;
 | 
						|
  screen_info.available_rect = view_rect;
 | 
						|
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
void BrowserWindowOsrMacImpl::OnPopupShow(CefRefPtr<CefBrowser> browser,
 | 
						|
                                          bool show) {
 | 
						|
  CEF_REQUIRE_UI_THREAD();
 | 
						|
  REQUIRE_MAIN_THREAD();
 | 
						|
 | 
						|
  if (!native_browser_view_)
 | 
						|
    return;
 | 
						|
 | 
						|
  if (!show) {
 | 
						|
    renderer_.ClearPopupRects();
 | 
						|
    browser->GetHost()->Invalidate(PET_VIEW);
 | 
						|
  }
 | 
						|
  renderer_.OnPopupShow(browser, show);
 | 
						|
}
 | 
						|
 | 
						|
void BrowserWindowOsrMacImpl::OnPopupSize(CefRefPtr<CefBrowser> browser,
 | 
						|
                                          const CefRect& rect) {
 | 
						|
  CEF_REQUIRE_UI_THREAD();
 | 
						|
  REQUIRE_MAIN_THREAD();
 | 
						|
 | 
						|
  if (!native_browser_view_)
 | 
						|
    return;
 | 
						|
 | 
						|
  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);
 | 
						|
 | 
						|
  renderer_.OnPopupSize(browser, device_rect);
 | 
						|
}
 | 
						|
 | 
						|
void BrowserWindowOsrMacImpl::OnPaint(
 | 
						|
    CefRefPtr<CefBrowser> browser,
 | 
						|
    CefRenderHandler::PaintElementType type,
 | 
						|
    const CefRenderHandler::RectList& dirtyRects,
 | 
						|
    const void* buffer,
 | 
						|
    int width,
 | 
						|
    int height) {
 | 
						|
  CEF_REQUIRE_UI_THREAD();
 | 
						|
  REQUIRE_MAIN_THREAD();
 | 
						|
 | 
						|
  if (!native_browser_view_)
 | 
						|
    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(native_browser_view_, 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 BrowserWindowOsrMacImpl::OnCursorChange(
 | 
						|
    CefRefPtr<CefBrowser> browser,
 | 
						|
    CefCursorHandle cursor,
 | 
						|
    cef_cursor_type_t type,
 | 
						|
    const CefCursorInfo& custom_cursor_info) {
 | 
						|
  CEF_REQUIRE_UI_THREAD();
 | 
						|
  REQUIRE_MAIN_THREAD();
 | 
						|
 | 
						|
  [CAST_CEF_CURSOR_HANDLE_TO_NSCURSOR(cursor) set];
 | 
						|
}
 | 
						|
 | 
						|
bool BrowserWindowOsrMacImpl::StartDragging(
 | 
						|
    CefRefPtr<CefBrowser> browser,
 | 
						|
    CefRefPtr<CefDragData> drag_data,
 | 
						|
    CefRenderHandler::DragOperationsMask allowed_ops,
 | 
						|
    int x,
 | 
						|
    int y) {
 | 
						|
  CEF_REQUIRE_UI_THREAD();
 | 
						|
  REQUIRE_MAIN_THREAD();
 | 
						|
 | 
						|
  if (!native_browser_view_)
 | 
						|
    return false;
 | 
						|
 | 
						|
  static float device_scale_factor =
 | 
						|
      [native_browser_view_ getDeviceScaleFactor];
 | 
						|
 | 
						|
  // |point| is in browser view coordinates.
 | 
						|
  NSPoint point = NSMakePoint(x, y);
 | 
						|
 | 
						|
  // Convert to device coordinates.
 | 
						|
  point.x = LogicalToDevice(point.x, device_scale_factor);
 | 
						|
  point.y = LogicalToDevice(point.y, device_scale_factor);
 | 
						|
 | 
						|
  // Convert to OS X view coordinates.
 | 
						|
  point = [native_browser_view_ convertPointFromBackingInternal:point];
 | 
						|
 | 
						|
  return [native_browser_view_
 | 
						|
      startDragging:drag_data
 | 
						|
         allowedOps:static_cast<NSDragOperation>(allowed_ops)
 | 
						|
              point:point];
 | 
						|
}
 | 
						|
 | 
						|
void BrowserWindowOsrMacImpl::UpdateDragCursor(
 | 
						|
    CefRefPtr<CefBrowser> browser,
 | 
						|
    CefRenderHandler::DragOperation operation) {
 | 
						|
  CEF_REQUIRE_UI_THREAD();
 | 
						|
  REQUIRE_MAIN_THREAD();
 | 
						|
 | 
						|
  if (native_browser_view_)
 | 
						|
    [native_browser_view_ setCurrentDragOp:operation];
 | 
						|
}
 | 
						|
 | 
						|
void BrowserWindowOsrMacImpl::OnImeCompositionRangeChanged(
 | 
						|
    CefRefPtr<CefBrowser> browser,
 | 
						|
    const CefRange& selection_range,
 | 
						|
    const CefRenderHandler::RectList& bounds) {
 | 
						|
  CEF_REQUIRE_UI_THREAD();
 | 
						|
 | 
						|
  if (native_browser_view_) {
 | 
						|
    [native_browser_view_ ChangeCompositionRange:selection_range
 | 
						|
                                character_bounds:bounds];
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void BrowserWindowOsrMacImpl::UpdateAccessibilityTree(
 | 
						|
    CefRefPtr<CefValue> value) {
 | 
						|
  CEF_REQUIRE_UI_THREAD();
 | 
						|
 | 
						|
  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<CefDictionaryValue> extra_info,
 | 
						|
    CefRefPtr<CefRequestContext> request_context) {
 | 
						|
  impl_->CreateBrowser(parent_handle, rect, settings, extra_info,
 | 
						|
                       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,
 | 
						|
    cef_cursor_type_t 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(
 | 
						|
    CefRefPtr<CefValue> value) {
 | 
						|
  impl_->UpdateAccessibilityLocation(value);
 | 
						|
}
 | 
						|
 | 
						|
}  // namespace client
 |