Skip to content

Commit

Permalink
Implementation of popups in CefSharp.Wpf/WebView.cpp
Browse files Browse the repository at this point in the history
  • Loading branch information
dvarchev committed Jul 6, 2012
1 parent cedab75 commit e7510ff
Show file tree
Hide file tree
Showing 5 changed files with 230 additions and 23 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -13,6 +13,7 @@ _ReSharper*

obj/
bin/
Debug/
CefSharp/app.aps
TestResult.xml
debug.log
199 changes: 181 additions & 18 deletions CefSharp.Wpf/WebView.cpp
Expand Up @@ -23,8 +23,9 @@ namespace Wpf
gcnew PropertyChangedEventHandler(this, &WebView::BrowserCore_PropertyChanged);

_scriptCore = new ScriptCore();

_paintDelegate = gcnew ActionHandler(this, &WebView::SetBitmap);
_paintPopupDelegate = gcnew ActionHandler(this, &WebView::SetPopupBitmap);
_resizePopupDelegate = gcnew ActionHandler(this, &WebView::SetPopupSizeAndPositionImpl);

ToolTip = _toolTip =
gcnew System::Windows::Controls::ToolTip();
Expand Down Expand Up @@ -152,6 +153,24 @@ namespace Wpf
bitmap->Invalidate();
}

void WebView::SetPopupBitmap()
{
InteropBitmap^ bitmap = _popupIbitmap;

if(bitmap == nullptr)
{
_popupImage->Source = nullptr;
GC::Collect(1);

int stride = _popupWidth * PixelFormats::Bgr32.BitsPerPixel / 8;
bitmap = (InteropBitmap^)Interop::Imaging::CreateBitmapSourceFromMemorySection(
(IntPtr)_popupFileMappingHandle, _popupWidth, _popupHeight, PixelFormats::Bgr32, stride, 0);
_popupImage->Source = bitmap;
_popupIbitmap = bitmap;
}

bitmap->Invalidate();
}
void WebView::OnPreviewKey(KeyEventArgs^ e)
{
CefRefPtr<CefBrowser> browser;
Expand Down Expand Up @@ -202,6 +221,7 @@ namespace Wpf
{
Point point = _matrix->Transform(Point(size.Width, size.Height));
browser->SetSize(PET_VIEW, (int)point.X, (int)point.Y);
HidePopup();
}
else
{
Expand Down Expand Up @@ -230,6 +250,8 @@ namespace Wpf
{
browser->SendFocusEvent(false);
}

HidePopup();

ContentControl::OnLostFocus(e);
}
Expand Down Expand Up @@ -274,7 +296,7 @@ namespace Wpf
void WebView::OnMouseUp(MouseButtonEventArgs^ e)
{
OnMouseButton(e);
Mouse::Capture(nullptr);
Mouse::Capture(nullptr);
}

void WebView::OnMouseLeave(MouseEventArgs^ e)
Expand Down Expand Up @@ -303,6 +325,7 @@ namespace Wpf
{
browser->GetMainFrame()->LoadURL(toNative(url));
}

}

void WebView::LoadHtml(String^ html)
Expand Down Expand Up @@ -584,10 +607,33 @@ namespace Wpf
source->AddHook(gcnew Interop::HwndSourceHook(this, &WebView::SourceHook));

Content = _image = gcnew Image();

_popup = gcnew Popup();

_popup->Child = _popupImage = gcnew Image();

_popup->MouseDown += gcnew MouseButtonEventHandler(this, &WebView::OnPopupMouseDown);
_popup->MouseUp += gcnew MouseButtonEventHandler(this, &WebView::OnPopupMouseUp);
_popup->MouseMove += gcnew MouseEventHandler(this, &WebView::OnPopupMouseMove);
_popup->MouseLeave += gcnew MouseEventHandler(this, &WebView::OnPopupMouseLeave);
_popup->MouseWheel += gcnew MouseWheelEventHandler(this, &WebView::OnPopupMouseWheel);

_popup->PlacementTarget = this;
_popup->Placement = PlacementMode::Relative;

Window^ currentWindow = Window::GetWindow(this);
currentWindow->LocationChanged += gcnew EventHandler(this, &WebView::OnWindowLocationChanged);
currentWindow->Deactivated += gcnew EventHandler(this, &WebView::OnWindowLocationChanged);


_image->Stretch = Stretch::None;
_image->HorizontalAlignment = ::HorizontalAlignment::Left;
_image->VerticalAlignment = ::VerticalAlignment::Top;

_popupImage->Stretch = Stretch::None;
_popupImage->HorizontalAlignment = ::HorizontalAlignment::Left;
_popupImage->VerticalAlignment = ::VerticalAlignment::Top;

_matrix = source->CompositionTarget->TransformToDevice;
}

Expand Down Expand Up @@ -615,46 +661,163 @@ namespace Wpf

void WebView::SetBuffer(int width, int height, const void* buffer)
{
if (!_backBufferHandle || _width != width || _height != height)
int currentWidth = _width, currentHeight = _height;
HANDLE fileMappingHandle = _fileMappingHandle, backBufferHandle = _backBufferHandle;
InteropBitmap^ ibitmap = _ibitmap;

SetBuffer( currentWidth, currentHeight, width, height, fileMappingHandle, backBufferHandle, ibitmap, _paintDelegate, buffer);

_ibitmap = ibitmap;
_fileMappingHandle = fileMappingHandle;
_backBufferHandle = backBufferHandle;

_width = currentWidth;
_height = currentHeight;
}

void WebView::SetPopupBuffer(int width, int height, const void* buffer)
{
int currentWidth = _popupWidth, currentHeight = _popupHeight;
HANDLE fileMappingHandle = _popupFileMappingHandle, backBufferHandle = _popupBackBufferHandle;
InteropBitmap^ ibitmap = _popupIbitmap;

SetBuffer( currentWidth, currentHeight, width, height, fileMappingHandle, backBufferHandle, ibitmap, _paintPopupDelegate, buffer);

_popupIbitmap = ibitmap;
_popupFileMappingHandle = fileMappingHandle;
_popupBackBufferHandle = backBufferHandle;

_popupWidth = currentWidth;
_popupHeight = currentHeight;
}


void WebView::SetBuffer(int &currentWidth, int& currentHeight,
int width, int height,
HANDLE& fileMappingHandle,
HANDLE& backBufferHandle,
InteropBitmap^& ibitmap,
ActionHandler^ paintDelegate,
const void* buffer)
{
if (!backBufferHandle || currentWidth != width || currentHeight != height)
{
_ibitmap = nullptr;
ibitmap = nullptr;

if (_backBufferHandle)
if (backBufferHandle)
{
UnmapViewOfFile(_backBufferHandle);
_backBufferHandle = NULL;
UnmapViewOfFile(backBufferHandle);
backBufferHandle = NULL;
}

if (_fileMappingHandle)
if (fileMappingHandle)
{
CloseHandle(_fileMappingHandle);
_fileMappingHandle = NULL;
CloseHandle(fileMappingHandle);
fileMappingHandle = NULL;
}

int pixels = width * height;
int bytes = pixels * PixelFormats::Bgr32.BitsPerPixel / 8;

_fileMappingHandle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, bytes, NULL);
if(!_fileMappingHandle)
fileMappingHandle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, bytes, NULL);
if(!fileMappingHandle)
{
return;
}

_backBufferHandle = MapViewOfFile(_fileMappingHandle, FILE_MAP_ALL_ACCESS, 0, 0, bytes);
if(!_backBufferHandle)
backBufferHandle = MapViewOfFile(fileMappingHandle, FILE_MAP_ALL_ACCESS, 0, 0, bytes);
if(!backBufferHandle)
{
return;
}

_width = width;
_height = height;
currentWidth = width;
currentHeight = height;
}

int stride = width * PixelFormats::Bgr32.BitsPerPixel / 8;
CopyMemory(_backBufferHandle, (void*) buffer, height * stride);
CopyMemory(backBufferHandle, (void*) buffer, height * stride);

if(!Dispatcher->HasShutdownStarted) {
Dispatcher->BeginInvoke(DispatcherPriority::Render, _paintDelegate);
Dispatcher->BeginInvoke(DispatcherPriority::Render, paintDelegate);
}
}

void WebView::SetPopupSizeAndPosition(const CefRect& rect)
{
_popupX = rect.x;
_popupY = rect.y;
_popupWidth = rect.width;
_popupHeight = rect.height;

if(!Dispatcher->HasShutdownStarted) {
Dispatcher->BeginInvoke(DispatcherPriority::Render, _resizePopupDelegate);
}
}

void WebView::SetPopupIsOpen(bool isOpen){
if(!Dispatcher->HasShutdownStarted) {
Dispatcher->BeginInvoke(gcnew Action<bool>(this, &WebView::ShowHidePopup), DispatcherPriority::Render, isOpen);
}
}

void WebView::SetPopupSizeAndPositionImpl()
{
_popup->Width = _popupWidth;
_popup->Height = _popupHeight;

_popup->HorizontalOffset = _popupX;
_popup->VerticalOffset = _popupY;

}
void WebView::ShowHidePopup(bool isOpened)
{
_popup->IsOpen = isOpened;
}


void WebView::OnPopupMouseMove(Object^ sender, MouseEventArgs^ e)
{
OnMouseMove(e);
}

void WebView::OnPopupMouseWheel(Object^ sender, MouseWheelEventArgs^ e)
{
OnMouseWheel(e);
}

void WebView::OnPopupMouseDown(Object^ sender,MouseButtonEventArgs^ e)
{
OnMouseDown(e);
}

void WebView::OnPopupMouseUp(Object^ sender,MouseButtonEventArgs^ e)
{
OnMouseUp(e);
}

void WebView::OnPopupMouseLeave(Object^ sender,MouseEventArgs^ e)
{
OnMouseLeave(e);
}

void WebView::OnWindowLocationChanged(Object^ sender, EventArgs^ e)
{
HidePopup();
}

void WebView::HidePopup()
{
CefRefPtr<CefBrowser> browser;
if (TryGetCefBrowser(browser))
{
if(_popup != nullptr && _popup->IsOpen)
{
// This is the only decent way I found to hide popup properly so that clicking again on the a drop down (<select>)
// opens it.
browser->SendMouseClickEvent(-1,-1, CefBrowser::MouseButtonType::MBT_LEFT, false, 1 );
}
}
}

}}
38 changes: 36 additions & 2 deletions CefSharp.Wpf/WebView.h
Expand Up @@ -33,16 +33,23 @@ namespace Wpf
MCefRefPtr<RenderClientAdapter> _clientAdapter;
BrowserCore^ _browserCore;
MCefRefPtr<ScriptCore> _scriptCore;


Popup^ _popup;

Image^ _popupImage;
Image^ _image;
Matrix^ _matrix;
::ToolTip^ _toolTip;
DispatcherTimer^ _timer;

int _width, _height;
int _width, _height, _popupWidth, _popupHeight, _popupX, _popupY;
InteropBitmap^ _ibitmap;
InteropBitmap^ _popupIbitmap;
HANDLE _fileMappingHandle, _backBufferHandle;
HANDLE _popupFileMappingHandle, _popupBackBufferHandle;
ActionHandler^ _resizePopupDelegate;
ActionHandler^ _paintDelegate;
ActionHandler^ _paintPopupDelegate;

void Initialize(String^ address, BrowserSettings^ settings);
bool TryGetCefBrowser(CefRefPtr<CefBrowser>& browser);
Expand All @@ -53,15 +60,37 @@ namespace Wpf
void SetTooltipText(String^ text);
IntPtr SourceHook(IntPtr hWnd, int message, IntPtr wParam, IntPtr lParam, bool% handled);
void SetBitmap();

void SetBuffer(int& currentWidth, int& currentHeight,
int width, int height,
HANDLE& fileMappingHandle,
HANDLE& backBufferHandle,
InteropBitmap^& ibitmap,
ActionHandler^ paintDelegate,
const void* buffer);

void SetPopupBitmap();
void OnPreviewKey(KeyEventArgs^ e);
void OnMouseButton(MouseButtonEventArgs^ e);

void ShowHidePopup(bool isOpened);
void SetPopupSizeAndPositionImpl();

void OnPopupMouseMove(Object^ sender, MouseEventArgs^ e);
void OnPopupMouseWheel(Object^ sender,MouseWheelEventArgs^ e) ;
void OnPopupMouseDown(Object^ sender,MouseButtonEventArgs^ e) ;
void OnPopupMouseUp(Object^ sender, MouseButtonEventArgs^ e) ;
void OnPopupMouseLeave(Object^ sender, MouseEventArgs^ e) ;
void OnWindowLocationChanged(Object^ sender, EventArgs^ e) ;
void HidePopup();

protected:
virtual Size ArrangeOverride(Size size) override;
virtual void OnGotFocus(RoutedEventArgs^ e) override;
virtual void OnLostFocus(RoutedEventArgs^ e) override;
virtual void OnPreviewKeyDown(KeyEventArgs^ e) override;
virtual void OnPreviewKeyUp(KeyEventArgs^ e) override;

virtual void OnMouseMove(MouseEventArgs^ e) override;
virtual void OnMouseWheel(MouseWheelEventArgs^ e) override;
virtual void OnMouseDown(MouseButtonEventArgs^ e) override;
Expand Down Expand Up @@ -228,5 +257,10 @@ namespace Wpf
virtual void OnApplyTemplate() override;
virtual void SetCursor(CefCursorHandle cursor);
virtual void SetBuffer(int width, int height, const void* buffer);
virtual void SetPopupBuffer(int width, int height, const void* buffer);

virtual void SetPopupIsOpen(bool isOpen);
virtual void SetPopupSizeAndPosition(const CefRect& rect);

};
}}
6 changes: 6 additions & 0 deletions CefSharp/IRenderWebBrowser.h
Expand Up @@ -3,12 +3,18 @@

#include "IWebBrowser.h"


namespace CefSharp
{
public interface class IRenderWebBrowser : IWebBrowser
{
public:
void SetCursor(CefCursorHandle cursor);
void SetBuffer(int width, int height, const void* buffer);

void SetPopupBuffer(int width, int height, const void* buffer);
void SetPopupIsOpen(bool isOpen);

void SetPopupSizeAndPosition(const CefRect& rect);
};
}

0 comments on commit e7510ff

Please sign in to comment.