Skip to content

Commit

Permalink
WPF - Add Experimental LifeSpanHandler capable of hosting pop-ups as …
Browse files Browse the repository at this point in the history
…Tabs/Controls

Issue #4285
  • Loading branch information
amaitland committed Oct 25, 2022
1 parent 299f63e commit ec8e340
Show file tree
Hide file tree
Showing 5 changed files with 459 additions and 139 deletions.
136 changes: 0 additions & 136 deletions CefSharp.Wpf.Example/Handlers/ExperimentalLifespanHandler.cs

This file was deleted.

67 changes: 64 additions & 3 deletions CefSharp.Wpf.Example/Views/BrowserTabView.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,70 @@ public BrowserTabView()
};

browser.DisplayHandler = new DisplayHandler();
//This LifeSpanHandler implementaion demos hosting a popup in a ChromiumWebBrowser
//instance, it's still considered Experimental
//browser.LifeSpanHandler = new ExperimentalLifespanHandler();
// This LifeSpanHandler implementaion demos hosting a popup in a ChromiumWebBrowser
// instance, it's still considered Experimental. The ChromiumWebBrowser
// is shown in a new Window. This could just as easily be a Tab/ContentControl/etc
/*
browser.LifeSpanHandler = CefSharp.Wpf.Experimental.LifeSpanHandler
.Create()
.OnPopupCreated((ctrl, targetUrl, targetFrameName, windowInfo) =>
{
var windowX = (windowInfo.X == int.MinValue) ? double.NaN : windowInfo.X;
var windowY = (windowInfo.Y == int.MinValue) ? double.NaN : windowInfo.Y;
var windowWidth = (windowInfo.Width == int.MinValue) ? double.NaN : windowInfo.Width;
var windowHeight = (windowInfo.Height == int.MinValue) ? double.NaN : windowInfo.Height;
var popup = new System.Windows.Window
{
Left = windowX,
Top = windowY,
Width = windowWidth,
Height = windowHeight,
Content = ctrl,
Owner = Window.GetWindow(browser),
Title = targetFrameName
};
popup.Closed += (o, e) =>
{
var w = o as System.Windows.Window;
if (w != null && w.Content is IWebBrowser)
{
(w.Content as IWebBrowser)?.Dispose();
w.Content = null;
}
};
})
.OnPopupBrowserCreated((ctrl, browser) =>
{
ctrl.Dispatcher.Invoke(() =>
{
var owner = System.Windows.Window.GetWindow(ctrl);
if (owner != null && owner.Content == ctrl)
{
owner.Show();
}
});
})
.OnPopupDestroyed((ctrl, popupBrowser) =>
{
//If browser is disposed then we don't need to remove the tab
if (!ctrl.IsDisposed)
{
ctrl.Dispatcher.Invoke(() =>
{
var owner = System.Windows.Window.GetWindow(ctrl);
if (owner != null && owner.Content == ctrl)
{
owner.Close();
}
});
}
}).Build();
*/

browser.MenuHandler = new MenuHandler(addDevtoolsMenuItems:true);

//Enable experimental Accessibility support
Expand Down
91 changes: 91 additions & 0 deletions CefSharp.Wpf/Experimental/LifeSpanHandlerBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// Copyright © 2022 The CefSharp Authors. All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

namespace CefSharp.Wpf.Experimental
{
/// <summary>
/// Fluent <see cref="LifeSpanHandler"/> Builder
/// </summary>
public class LifeSpanHandlerBuilder
{
private readonly LifeSpanHandler handler;

/// <summary>
/// LifeSpanHandlerBuilder
/// </summary>
/// <param name="chromiumWebBrowserCreatedDelegate">
/// When specified the delegate will be used to create the <see cref="ChromiumWebBrowser"/>
/// instance. Allowing users to create their own custom instance that extends <see cref="ChromiumWebBrowser"/>
/// </param>
public LifeSpanHandlerBuilder(CreatePopupChromiumWebBrowser chromiumWebBrowserCreatedDelegate)
{
handler = new LifeSpanHandler(chromiumWebBrowserCreatedDelegate);
}

/// <summary>
/// The <see cref="OnBeforePopupCreatedDelegate"/> will be called <b>before</b> the popup has been created and
/// can be used to cancel popup creation if required, modify <see cref="IBrowserSettings"/> and disable javascript.
/// </summary>
/// <param name="onBeforePopupCreated">Action to be invoked before popup is created.</param>
/// <returns><see cref="LifeSpanHandlerBuilder"/> instance allowing you to chain method calls together</returns>
public LifeSpanHandlerBuilder OnBeforePopupCreated(OnBeforePopupCreatedDelegate onBeforePopupCreated)
{
handler.OnBeforePopupCreated(onBeforePopupCreated);

return this;
}

/// <summary>
/// The <see cref="OnPopupCreatedDelegate"/> will be called when the<see cref="ChromiumWebBrowser"/> has been
/// created. When the <see cref="OnPopupCreatedDelegate"/> is called you must add the control to it's intended parent.
/// </summary>
/// <param name="onPopupCreated">Action to be invoked when the Popup is to be destroyed.</param>
/// <returns><see cref="LifeSpanHandlerBuilder"/> instance allowing you to chain method calls together</returns>
public LifeSpanHandlerBuilder OnPopupCreated(OnPopupCreatedDelegate onPopupCreated)
{
handler.OnPopupCreated(onPopupCreated);

return this;
}

/// <summary>
/// The <see cref="OnPopupBrowserCreatedDelegate"/> will be called when the<see cref="IBrowser"/> has been
/// created. The <see cref="IBrowser"/> instance is valid until <see cref="OnPopupDestroyed(OnPopupDestroyedDelegate)"/>
/// is called. <see cref="IBrowser"/> provides low level access to the CEF Browser, you can access frames, view source,
/// perform navigation (via frame) etc.
/// </summary>
/// <param name="onPopupBrowserCreated">Action to be invoked when the <see cref="IBrowser"/> has been created.</param>
/// <returns><see cref="LifeSpanHandlerBuilder"/> instance allowing you to chain method calls together</returns>
public LifeSpanHandlerBuilder OnPopupBrowserCreated(OnPopupBrowserCreatedDelegate onPopupBrowserCreated)
{
handler.OnPopupBrowserCreated(onPopupBrowserCreated);

return this;
}

/// <summary>
/// The <see cref="OnPopupDestroyedDelegate"/> will be called when the <see cref="ChromiumWebBrowser"/> is to be
/// removed from it's parent.
/// When the <see cref="OnPopupDestroyedDelegate"/> is called you must remove/dispose of the <see cref="ChromiumWebBrowser"/>.
/// </summary>
/// <param name="onPopupDestroyed">Action to be invoked when the Popup is to be destroyed.</param>
/// <returns><see cref="LifeSpanHandlerBuilder"/> instance allowing you to chain method calls together</returns>
public LifeSpanHandlerBuilder OnPopupDestroyed(OnPopupDestroyedDelegate onPopupDestroyed)
{
handler.OnPopupDestroyed(onPopupDestroyed);

return this;
}

/// <summary>
/// Creates an <see cref="ILifeSpanHandler"/> implementation
/// that can be used to host popups as tabs/controls.
/// </summary>
/// <returns>a <see cref="ILifeSpanHandler"/> instance</returns>
public ILifeSpanHandler Build()
{
return handler;
}
}
}
Loading

0 comments on commit ec8e340

Please sign in to comment.