zoukankan      html  css  js  c++  java
  • PPAPI插件的全屏切换处理

    有时你会想让PPAPI插件全屏(比方播放视频时),这次来看看怎么做。

    PPAPI和CEF App两側都要处理。

    foruok原创,转载请注明出处。欢迎关注foruok的订阅号“程序视界”(programmer_sight)。

    PPAPI插件中的处理

    要支持全屏切换。PPAPI插件这側,有两处须要处理:

    • 使用PPB_Fullscreen。调用SetFullscreen方法
    • 在PPP_Instance的DidChangeView方法中重建Graphics 2D或Graphics 3D

    PPB_Fullscreen接口

    在PPP_InitializeModule方法里增加以下代码:

    ppb_fullscreen = (const PPB_Fullscreen*)get_browser_interface(PPB_FULLSCREEN_INTERFACE);
    

    获取到PPB_Fullscreen接口后,能够在合适的地方写下相似以下的代码来完毕全屏切换:

    ...
    // fs defined somewhere
    ppb_fullscreen->SetFullscreen(pp_inst, fs == PP_TRUE ? PP_FALSE : PP_TRUE);
    ...
    

    须要注意的是。SetFullscreen是异步的。当你调用SetFullscreen(pp_inst, PP_TRUE)之后,并不会立即进入进入全屏状态,此时你调用PPB_Fullscreen的GetScreenSize方法,获取到的可能是一个中间状态。所以,在接下来的DidChangeView方法中,须要应对这样的中间状态。

    DidChangeView重建图形上下文

    DidChangeView中,须要先释放之前创建image data,释放Graphics 2D。相似以下的代码:

    PP_Resouce image; //somewhere
    ppb_image_data->Unmap(image);
    ppb_core->Release(image);
    ppb_instance->BindGraphics(pp_inst, NULL);
    ppb_core->Release(graphics);
    

    然后再又一次创建一遍。详细能够參考PPAPI插件与浏览器的交互过程及其他文章。

    CEF APP側响应全屏操作

    当我们在PPAPI中调用PPB_Fullscreen的SetFullscreen方法时。事实上会发生好几件事儿。基本的有两件:

    1. CEF APP的browser进程处理全屏切换
    2. 全屏完毕后,PPAPI側收到DidChangeView消息

    如今就来看browser进程的处理。

    CefDisplayHandler类有一个与全屏相关的方法须要重写:

    virtual void OnFullscreenModeChange(CefRefPtr<CefBrowser> browser,
        bool fullscreen)
    

    在这种方法里,你能够让窗体全屏或恢复。

    有一点须要注意。有的浏览器实现,收到全屏模式变化消息时。(Windows上)会相似以下这样处理:

    ShowWindow(browser->GetHost()->GetWindowHandle(), fullscreen ? SW_MAXIMIZE : SW_RESTORE);
    

    这样的处理。全屏相应窗体最大化,非全屏就回到最大化前的状态。可能导致一定的问题,比方PPAPI觉得是全屏。获取的screen size是整个屏幕的尺寸。而浏览器窗体实际上仅仅占领了任务栏之外的地方。这样的话。PPAPI插件就会被切边,显示不完整。

    chromium的源代码里,pepper_plugin_instance_impl.cc中。就针对这样的情况。特别处理了flash插件。当检測到当前PPAPI插件时flash时,hook了一下,GetScreenSize返回实际窗体区域大小。

    这样flash插件就工作正常了。但我们写的则不会哈。

    所以,假设你真想全屏。能够參考以下的代码:

    void ClientHandler::OnFullscreenModeChange(CefRefPtr<CefBrowser> browser, bool fullscreen)
    {
        HWND hwndBrowser = browser->GetHost()->GetWindowHandle();
        if (fullscreen)
        {
            RECT rc;
            GetWindowRect(hwndBrowser, &rc);
            m_browserRects[hwndBrowser] = rc;
    
            HWND hwndDesktop = GetDesktopWindow();
            RECT rcDesktop;
            GetWindowRect(hwndDesktop, &rcDesktop);
    
            SetWindowLongPtr(hwndBrowser, GWL_STYLE, WS_VISIBLE);
            SetWindowPos(hwndBrowser, HWND_TOPMOST, 0, 0, rcDesktop.right, rcDesktop.bottom, SWP_SHOWWINDOW);
        }
        else
        {
            RECT rc = m_browserRects[hwndBrowser];
            SetWindowLongPtr(hwndBrowser, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE);
            SetWindowPos(hwndBrowser, HWND_NOTOPMOST, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, SWP_SHOWWINDOW);
        }
    }
    

    上面的代码。每次切换到全屏模式前,先保存窗体位置。

    从全屏退出时,再恢复。


    就这样吧。

    其他參考文章详见我的专栏:【CEF与PPAPI开发】。

  • 相关阅读:
    Django_rest_framework
    Django之FBV / CBV和中间件
    数据库之MySQL补充
    数据库之Python操作MySQL
    数据库之MySQL进阶
    数据库之初识MySQL
    2-3、配置Filebeat
    2-2、安装Filebeat
    2-1、FileBeat入门
    5、Filebeat工作原理
  • 原文地址:https://www.cnblogs.com/yjbjingcha/p/7263330.html
Copyright © 2011-2022 走看看