// 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,
                      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|.
    [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,
    CefRenderHandler::CursorType 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,
    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(
    CefRefPtr<CefValue> value) {
  impl_->UpdateAccessibilityLocation(value);
}

}  // namespace client
