1

I'm building a web browser in a C# .NET Windows Form Application and wanted to add support for fullscreen usage (mainly on HTML5 videos).

So that when users press the fullscreen button on a video like a youtube video, the video would take up the full screen.

The browser uses a GeckoFx control to view the interweb. How would I go about doing this?

Peacock
  • 302
  • 1
  • 13

1 Answers1

3

Set the Browser Control Dock property to Dock.Fill.
You can get the Screen size where you program is currently displayed and use its Bounds to size your Form.

Subscribe to the Resize event. When the Form is maximized, remove the border (which will remove the title bar, too), set the FormWindowState back to FormWindowState.Normal (otherwise you won't be able to use the full screen size) then resize it as needed.

You application should be DPIAware (if it's not see here).
You should also handle the F11 key to allow the user to maximize/normalize the Form's window.

using System;
using System.Drawing;
using System.Windows.Forms;
using Gecko;
using Screen = System.Windows.Forms.Screen;

public partial class Form1 : Form
{
    bool IsMaximized = false;
    bool TheaterClicked = false;
    Rectangle previousPosition = Rectangle.Empty;
    string UserAgent = "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0";
    public Form1()
    {
        InitializeComponent();
        Xpcom.Initialize("Firefox");
        GeckoPreferences.User["full-screen-api.enabled"] = true;
        GeckoPreferences.Default["full-screen-api.enabled"] = true;
        GeckoPreferences.User["general.useragent.override"] = UserAgent;
        GeckoPreferences.Default["general.useragent.override"] = UserAgent;
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        previousPosition = Bounds;
        geckoWebBrowser1.Navigate("[Some URL]");
        geckoWebBrowser1.GetDocShellAttribute().SetFullscreenAllowed(true);
    }

    private void Form1_Resize(object sender, EventArgs e)
    {
        if (WindowState == FormWindowState.Maximized) { 
            SetWindowState(WindowState, false);
        }
        else if (!IsMaximized) { 
            previousPosition = Bounds;
        }
    }

    private void geckoWebBrowser1_DomMouseDown(object sender, DomMouseEventArgs e)
    {
        if (geckoWebBrowser1.Url.Host.Contains("youtu")) {
            GeckoHtmlElement elm = (GeckoHtmlElement)e.Target.CastToGeckoElement();
            switch (elm.ClassName)
            {
                case "ytp-fullscreen-button ytp-button":
                    if (geckoWebBrowser1.Document.GetElementsByClassName("ytp-size-button ytp-button").FirstOrDefault() is GeckoHtmlElement theater) {
                        if (!TheaterClicked) {
                            theater.Click();
                            TheaterClicked = true;
                        }
                    }
                    break;
                case "ytp-size-button ytp-button":
                    TheaterClicked = !TheaterClicked;
                    break;
                default:
                    break;
            }
        }
    }

    private void SetWindowState(FormWindowState state, bool setSize)
    {
        if (state == FormWindowState.Maximized) {
            IsMaximized = true;
            if (setSize) previousPosition = Bounds;
            WindowState = FormWindowState.Normal;
            FormBorderStyle = FormBorderStyle.None;
            Location = Point.Empty;
            Size = Screen.FromHandle(Handle).Bounds.Size;
        }
        else {
            FormBorderStyle = FormBorderStyle.Sizable;
            Bounds = previousPosition;
            IsMaximized = false;
        }
    }

    protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
    {
        base.ProcessCmdKey(ref msg, keyData);
        if (keyData == Keys.F11) {
            SetWindowState(IsMaximized ? FormWindowState.Normal : FormWindowState.Maximized, true);
            return true;
        }
        else {
            return false;
        }
    }
}
Jimi
  • 29,621
  • 8
  • 43
  • 61
  • Thank you, how would I trigger this when a fullscreen button is pressed on a YouTube video in my browser? @Jimi – Peacock Feb 04 '19 at 00:18
  • I updated the code. It implements what I wrote about before (the F11 key). It should also help in restoring the Form Size when the WindowState is changed using different methods. About the Full Screen button on the YouTube video, I'm not sure how to get that `click`, but I'll find out... – Jimi Feb 04 '19 at 01:08
  • Awesome, thanks! I know how to get a button click from a page, but I'm more concerned about specifically when a *fullscreen* button click is triggered and how to make the video actually resize. – Peacock Feb 04 '19 at 01:11
  • Updated again. I've noticed that some versions of GeckoFx don't handle the `mozFullScreen` command (the `FullscreenChange` event is never raised). Try the updated code: if the version you use doesn't activate the FullScreen mode, It will set the video to theater mode. Maybe it's good enough, untill this is fixed. – Jimi Feb 04 '19 at 23:58
  • Well, I meant, this happens with Youtube, not with other HTML5 video players. – Jimi Feb 05 '19 at 08:34
  • Thanks for your detailed support, but when I tried that code an error was thrown towards the `this.TheaterClicked` part. Are you able to spell out the full `[object].TheaterClicked` rather than the `this` so that I can troubleshoot the issue? Thanks again. – Peacock Feb 07 '19 at 01:11
  • `this`, of course, is the Form itself. `TheaterClicked` is just a boolean field used to keep track of the status of the YouTube Player's Theater button, when clicked in the Browser. You need to use all the code you see here: as you can see, it's a whole Form. – Jimi Feb 07 '19 at 01:15
  • Oh, of course, you are right. I had left out that line above, thanks for the clarification, I will retry! @Jimi – Peacock Feb 07 '19 at 01:49
  • so the script worked great! Really well, the main issue now though is that in theater mode, the video does not cover the full screen. I'm sorry to put you through so much trouble but I greatly appreciate your help! – Peacock Feb 07 '19 at 01:55
  • Yes, I know. As I wrote, the latest versions of GeckoFx have this problem with YouTube's Player container. Not with other HTML5 video players. The YouTube's script doesn't raise the `FullscreenChange` event. Both version `60.x` and version `45.x` show this behaviour. The previous version (33, maybe) does not. As already said, just for YouTube. If you try other online sources, it will work with most of them (all those I tried, actually). Btw, the .Net standard WebBrowser control works well with YouTube. – Jimi Feb 07 '19 at 02:01
  • Thanks so much, your knowledge really helped me. I guess there is no permanent solution for GeckoFx then but I appreciate you trying anyways. I will keep looking and hopefully, one day find a method that fully works. – Peacock Feb 07 '19 at 02:27
  • Well, I'm interested in this feature, too. If I find something that can trigger the event of YouTube's `toggleFullScreen` script of the latest version of GeckoFx, or the guys there fix it, I'll let you know. – Jimi Feb 07 '19 at 02:33
  • Maybe you both are not wrong. Maybe it's intentional misconduct by Google: [See here](https://www.osnews.com/story/30937/google-denies-altering-youtube-code-to-break-microsoft-edge/). – zx485 Feb 09 '19 at 23:03
  • this.geckoWebBrowser1.GetDocShellAttribute() returns null so I can't set SetFullscreenAllowed(true); to it. What did I do wrong? Thanks in advance – Max Dove May 23 '19 at 13:31
  • @Max Dove The code you see here is based on GeckoFx v. `60.0.26.0`, compiled targeting `x86` with .Net Framework 4.7.2. Don't target either `x64` or `AnyCPU`. The Gecko version can change a lot. They don't care that much about compatibility among versions. – Jimi May 23 '19 at 13:34
  • @Jimi Thanks! I'm using 60.0.26.0 too, but my application can only run on x64. – Max Dove May 23 '19 at 13:38
  • Switched project to x86 and got Geckofx60.32 from nuget (60.0.26) Now geckoWebBrowser1.GetDocShellAttribute() returns non-null value, but SetFullscreenAllowed(true) throws Catastrophic failure (Exception from HRESULT: 0x8000FFFF (E_UNEXPECTED)) – Max Dove May 23 '19 at 13:53
  • @Max Dove Have you set, as described, `GeckoPreferences.User["full-screen-api.enabled"] = true;` (the `default` setting, too) before navigating? You can set `SetFullscreenAllowed(true)` only after you have navigated a web page (thus, the Document is created). A suggestion: if you can, move to [CefSharp](https://github.com/cefsharp/CefSharp). It provides more support, updates, source code and probably more help from StackOverflow users. GeckoFx is a beast hard to tame. – Jimi May 23 '19 at 14:03