HRESULT DropTargetWin::DragEnter(IDataObject* data_object,
                                  DWORD key_state,
                                  POINTL cursor_position,
                                  DWORD* effect) {
  if (!callback_)
    return E_UNEXPECTED;

  HRESULT hr;
  IDropTargetHelper* drop_helper = DropHelper();
  if (drop_helper) {
	  hr = drop_helper->DragEnter(hWnd_, data_object,
		  reinterpret_cast<POINT*>(&cursor_position), *effect);
  }

  CefRefPtr<CefDragData> drag_data = current_drag_data_;
  if (!drag_data) {
    drag_data = DataObjectToDragData(data_object);
  }

  CefMouseEvent ev = ToMouseEvent(cursor_position, key_state, hWnd_);
  CefBrowserHost::DragOperationsMask mask = DropEffectToDragOperation(*effect);
  mask = callback_->OnDragEnter(drag_data, ev, mask);
  *effect = DragOperationToDropEffect(mask);
  return S_OK;
}
HRESULT DropTargetWin::DragOver(DWORD key_state,
                                POINTL cursor_position,
                                DWORD* effect) {
  if (!callback_)
    return E_UNEXPECTED;
  CefMouseEvent ev = ToMouseEvent(cursor_position, key_state, hWnd_);
  CefBrowserHost::DragOperationsMask mask = DropEffectToDragOperation(*effect);
  mask = callback_->OnDragOver(ev, mask);
  *effect = DragOperationToDropEffect(mask);
  return S_OK;
}
HRESULT DropTargetWin::DragEnter(IDataObject* data_object,
                                  DWORD key_state,
                                  POINTL cursor_position,
                                  DWORD* effect) {
  if (!callback_)
    return E_UNEXPECTED;

  CefRefPtr<CefDragData> drag_data = current_drag_data_;
  if (!drag_data) {
    drag_data = DataObjectToDragData(data_object);
  }
  CefMouseEvent ev = ToMouseEvent(cursor_position, key_state, hWnd_);
  CefBrowserHost::DragOperationsMask mask = DropEffectToDragOperation(*effect);
  mask = callback_->OnDragEnter(drag_data, ev, mask);
  *effect = DragOperationToDropEffect(mask);
  return S_OK;
}
HRESULT DropTargetWin::DragOver(DWORD key_state,
                                POINTL cursor_position,
                                DWORD* effect) {
  if (!callback_)
    return E_UNEXPECTED;

  // Tell the helper that we moved over it so it can update the drag image.
  IDropTargetHelper* drop_helper = DropHelper();
  if (drop_helper)
	  drop_helper->DragOver(reinterpret_cast<POINT*>(&cursor_position), *effect);

  CefMouseEvent ev = ToMouseEvent(cursor_position, key_state, hWnd_);
  CefBrowserHost::DragOperationsMask mask = DropEffectToDragOperation(*effect);
  mask = callback_->OnDragOver(ev, mask);
  *effect = DragOperationToDropEffect(mask);
  return S_OK;
}
CefBrowserHost::DragOperationsMask DropTargetWin::StartDragging(
    CefRefPtr<CefBrowser> browser,
    CefRefPtr<CefDragData> drag_data,
    CefRenderHandler::DragOperationsMask allowed_ops,
    int x, int y) {
  CComPtr<IDataObject> dataObject;
  DWORD resEffect = DROPEFFECT_NONE;
  if (DragDataToDataObject(drag_data, &dataObject)) {
    CComPtr<IDropSource> dropSource = DropSourceWin::Create();
    DWORD effect = DragOperationToDropEffect(allowed_ops);
    current_drag_data_ = drag_data->Clone();
    current_drag_data_->ResetFileContents();
    HRESULT res = DoDragDrop(dataObject, dropSource, effect, &resEffect);
    if (res != DRAGDROP_S_DROP)
      resEffect = DROPEFFECT_NONE;
    current_drag_data_ = NULL;
  }
  return DropEffectToDragOperation(resEffect);
}
CefBrowserHost::DragOperationsMask DropTargetWin::StartDragging(
    CefRefPtr<CefBrowser> browser,
    CefRefPtr<CefDragData> drag_data,
	void* hbitmap,
	int imgcx,
	int imgcy,
	int imgx,
	int imgy,
    CefRenderHandler::DragOperationsMask allowed_ops,
    int x, int y) {
  CComPtr<IDataObject> dataObject;
  DWORD resEffect = DROPEFFECT_NONE;
  if (DragDataToDataObject(drag_data, &dataObject)) {
	  IDragSourceHelper* sourceHelper = DragHelper();
	HRESULT hr;
	if (sourceHelper)
	{
		SHDRAGIMAGE sdi;
		SIZE img_size{ imgcx, imgcy };
		sdi.sizeDragImage = img_size;
		sdi.crColorKey = 0xFFFFFFFF;
		sdi.hbmpDragImage = (HBITMAP)hbitmap;
		POINT img_pt{imgx, imgy};
		sdi.ptOffset = img_pt;
		hr = sourceHelper->InitializeFromBitmap(&sdi, dataObject);
	}
    CComPtr<IDropSource> dropSource = DropSourceWin::Create();
    DWORD effect = DragOperationToDropEffect(allowed_ops);
    current_drag_data_ = drag_data->Clone();
    current_drag_data_->ResetFileContents();
    HRESULT res = DoDragDrop(dataObject, dropSource, effect, &resEffect);
    if (res != DRAGDROP_S_DROP)
      resEffect = DROPEFFECT_NONE;
    current_drag_data_ = NULL;
  }
  return DropEffectToDragOperation(resEffect);
}