WebWindow icon indicating copy to clipboard operation
WebWindow copied to clipboard

Full screen and maximize support

Open westbrma opened this issue 4 years ago • 2 comments

westbrma avatar Feb 16 '20 13:02 westbrma

WebWindow.h

WebWindow(AutoString title, WebWindow* parent, WebMessageReceivedCallback webMessageReceivedCallback, bool fullscreen, int x, int y, int width, int height);

WebWindow.Windows.cpp

WebWindow::WebWindow(AutoString title, WebWindow* parent, WebMessageReceivedCallback webMessageReceivedCallback, bool fullscreen, int x = CW_USEDEFAULT, int y = CW_USEDEFAULT, int width = CW_USEDEFAULT, int height = CW_USEDEFAULT)
{
	// Create the window
	_webMessageReceivedCallback = webMessageReceivedCallback;
	_parent = parent;

	if (fullscreen)
	{
		x = 0;
		y = 0;
		width = GetSystemMetrics(SM_CXSCREEN);
		height = GetSystemMetrics(SM_CYSCREEN);
	}

	_hWnd = CreateWindowEx(
		0,                              // Optional window styles.
		CLASS_NAME,                     // Window class
		title,							// Window text
		fullscreen ? WS_POPUP : WS_OVERLAPPEDWINDOW,	// Window style

		// Size and position
		x, y, width, height,

		parent ? parent->_hWnd : NULL,       // Parent window
		NULL,       // Menu
		_hInstance, // Instance handle
		this        // Additional application data
	);
	hwndToWebWindow[_hWnd] = this;
}

WebWindow.Linux.cpp

WebWindow::WebWindow(AutoString title, WebWindow* parent, WebMessageReceivedCallback webMessageReceivedCallback, bool fullscreen, int x, int y, int width, int height) : _webview(nullptr)
{
	_webMessageReceivedCallback = webMessageReceivedCallback;

	// It makes xlib thread safe.
	// Needed for get_position.
	XInitThreads();

	gtk_init(0, NULL);
	_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

	if (fullscreen)
	{
		GdkRectangle geometry = { 0 };
		gdk_monitor_get_geometry(gdk_display_get_primary_monitor(gdk_display_get_default()), &geometry);

		x = 0;
		y = 0;
		width = geometry.width;
		height = geometry.height;

		gtk_window_fullscreen(GTK_WINDOW(_window));
	}

	gtk_window_move(GTK_WINDOW(_window), x, y);
	gtk_window_set_default_size(GTK_WINDOW(_window), width, height);
	SetTitle(title);

	if (parent == NULL)
	{
		g_signal_connect(G_OBJECT(_window), "destroy",
			G_CALLBACK(+[](GtkWidget* w, gpointer arg) { gtk_main_quit(); }),
			this);
		g_signal_connect(G_OBJECT(_window), "size-allocate",
			G_CALLBACK(on_size_allocate),
			this);
		g_signal_connect(G_OBJECT(_window), "configure-event",
			G_CALLBACK(on_configure_event),
			this);
	}
}

Exports.cpp

EXPORTED WebWindow* WebWindow_ctor(AutoString title, WebWindow* parent, WebMessageReceivedCallback webMessageReceivedCallback, bool fullscreen, int x, int y, int width, int height)
{
	return new WebWindow(title, parent, webMessageReceivedCallback, fullscreen, x, y, width, height);
}

WebWindow.cs

    [DllImport(DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)] static extern IntPtr WebWindow_ctor(string title, IntPtr parentWebWindow, OnWebMessageReceivedCallback webMessageReceivedCallback, bool fullscreen, int x, int y, int width, int height);

    public WebWindow(string title, Action<WebWindowOptions> configure, bool fullscreen = false, int x = 0, int y = 0, int width = 800, int height = 600)
    {
        _ownerThreadId = Thread.CurrentThread.ManagedThreadId;

        if (configure is null)
        {
            throw new ArgumentNullException(nameof(configure));
        }

        var options = new WebWindowOptions();
        configure.Invoke(options);

        WriteTitleField(title);

        var onWebMessageReceivedDelegate = (OnWebMessageReceivedCallback)ReceiveWebMessage;
        _gcHandlesToFree.Add(GCHandle.Alloc(onWebMessageReceivedDelegate));

        var parentPtr = options.Parent?._nativeWebWindow ?? default;
        _nativeWebWindow = WebWindow_ctor(_title, parentPtr, onWebMessageReceivedDelegate, fullscreen, x, y, width, height);

        foreach (var (schemeName, handler) in options.SchemeHandlers)
        {
            AddCustomScheme(schemeName, handler);
        }

        var onResizedDelegate = (ResizedCallback)OnResized;
        _gcHandlesToFree.Add(GCHandle.Alloc(onResizedDelegate));
        WebWindow_SetResizedCallback(_nativeWebWindow, onResizedDelegate);

        var onMovedDelegate = (MovedCallback)OnMoved;
        _gcHandlesToFree.Add(GCHandle.Alloc(onMovedDelegate));
        WebWindow_SetMovedCallback(_nativeWebWindow, onMovedDelegate);

        // Auto-show to simplify the API, but more importantly because you can't
        // do things like navigate until it has been shown
        Show();
    }

ComponentsDesktop.cs

    public static void Run<TStartup>(string windowTitle, string hostHtmlPath, bool fullscreen = false, int x = 0, int y = 0, int width = 800, int height = 600)
    {
        DesktopSynchronizationContext.UnhandledException += (sender, exception) =>
        {
            UnhandledException(exception);
        };

        WebWindow = new WebWindow(windowTitle, options =>
        {
            var contentRootAbsolute = Path.GetDirectoryName(Path.GetFullPath(hostHtmlPath));

            options.SchemeHandlers.Add(BlazorAppScheme, (string url, out string contentType) =>
            {
                // TODO: Only intercept for the hostname 'app' and passthrough for others
                // TODO: Prevent directory traversal?
                var appFile = Path.Combine(contentRootAbsolute, new Uri(url).AbsolutePath.Substring(1));
                if (appFile == contentRootAbsolute)
                {
                    appFile = hostHtmlPath;
                }

                contentType = GetContentType(appFile);
                return File.Exists(appFile) ? File.OpenRead(appFile) : null;
            });

            // framework:// is resolved as embedded resources
            options.SchemeHandlers.Add("framework", (string url, out string contentType) =>
            {
                contentType = GetContentType(url);
                return SupplyFrameworkFile(url);
            });
        }, fullscreen, x, y, width, height);

        CancellationTokenSource appLifetimeCts = new CancellationTokenSource();
        Task.Factory.StartNew(async () =>
        {
            try
            {
                var ipc = new IPC(WebWindow);
                await RunAsync<TStartup>(ipc, appLifetimeCts.Token);
            }
            catch (Exception ex)
            {
                UnhandledException(ex);
                throw;
            }
        });

        try
        {
            WebWindow.NavigateToUrl(BlazorAppScheme + "://app/");
            WebWindow.WaitForExit();
        }
        finally
        {
            appLifetimeCts.Cancel();
        }
    }

Jinjinov avatar Feb 26 '20 07:02 Jinjinov

What is the status of this issue?

dima117 avatar Oct 09 '20 22:10 dima117