加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

PPAPI插件的全屏切换处理

发布时间:2020-12-15 20:06:29 所属栏目:百科 来源:网络整理
导读:有时你会想让PPAPI插件全屏(比如播放视频时),这次来看看怎么做。 PPAPI和CEF App两侧都要处理。 foruok原创,转载请注明出处。欢迎关注foruok的订阅号“程序视界”(programmer_sight)。 PPAPI插件中的处理 要支持全屏切换,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,rcDesktop.right,rcDesktop.bottom,SWP_SHOWWINDOW);
    }
    else
    {
        RECT rc = m_browserRects[hwndBrowser];
        SetWindowLongPtr(hwndBrowser,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开发】。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读