PPAPI插件的全屏切换处理
2016-03-08 15:44
183 查看
有时你会想让PPAPI插件全屏(比如播放视频时),这次来看看怎么做。
PPAPI和CEF App两侧都要处理。
foruok原创,转载请注明出处。欢迎关注foruok的订阅号“程序视界”(programmer_sight)。
使用PPB_Fullscreen,调用SetFullscreen方法
在PPP_Instance的DidChangeView方法中重建Graphics 2D或Graphics 3D
获取到PPB_Fullscreen接口后,可以在合适的地方写下类似下面的代码来完成全屏切换:
需要注意的是,SetFullscreen是异步的,当你调用SetFullscreen(pp_inst, PP_TRUE)之后,并不会马上进入进入全屏状态,此时你调用PPB_Fullscreen的GetScreenSize方法,获取到的可能是一个中间状态。所以,在接下来的DidChangeView方法中,需要应对这种中间状态。
然后再重新创建一遍,具体可以参考PPAPI插件与浏览器的交互过程及其它文章。
CEF APP的browser进程处理全屏切换
全屏完成后,PPAPI侧收到DidChangeView消息
现在就来看browser进程的处理。
CefDisplayHandler类有一个与全屏相关的方法需要重写:
在这个方法里,你可以让窗口全屏或恢复。
有一点需要注意,有的浏览器实现,收到全屏模式变化消息时,(Windows上)会类似下面这样处理:
这种处理,全屏对应窗口最大化,非全屏就回到最大化前的状态。可能导致一定的问题,比如PPAPI认为是全屏,获取的screen size是整个屏幕的尺寸,而浏览器窗口实际上只占据了任务栏之外的地方,这样的话,PPAPI插件就会被切边,显示不完整。
chromium的源码里,pepper_plugin_instance_impl.cc中,就针对这种情况,特别处理了flash插件。当检测到当前PPAPI插件时flash时,hook了一下,GetScreenSize返回实际窗口区域大小。这样flash插件就工作正常了。但我们写的则不会哈。
所以,如果你真想全屏,可以参考下面的代码:
上面的代码,每次切换到全屏模式前,先保存窗口位置。从全屏退出时,再恢复。
就这样吧。
其他参考文章详见我的专栏:【CEF与PPAPI开发】。
PPAPI和CEF App两侧都要处理。
foruok原创,转载请注明出处。欢迎关注foruok的订阅号“程序视界”(programmer_sight)。
PPAPI插件中的处理
要支持全屏切换,PPAPI插件这侧,有两处需要处理:使用PPB_Fullscreen,调用SetFullscreen方法
在PPP_Instance的DidChangeView方法中重建Graphics 2D或Graphics 3D
PPB_Fullscreen接口
在PPP_InitializeModule方法里加入下面代码:[code]ppb_fullscreen = (const PPB_Fullscreen*)get_browser_interface(PPB_FULLSCREEN_INTERFACE);
获取到PPB_Fullscreen接口后,可以在合适的地方写下类似下面的代码来完成全屏切换:
[code]... // 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。类似下面的代码:[code]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方法时,其实会发生好几件事儿,主要的有两件:CEF APP的browser进程处理全屏切换
全屏完成后,PPAPI侧收到DidChangeView消息
现在就来看browser进程的处理。
CefDisplayHandler类有一个与全屏相关的方法需要重写:
[code]virtual void OnFullscreenModeChange(CefRefPtr<CefBrowser> browser, bool fullscreen)
在这个方法里,你可以让窗口全屏或恢复。
有一点需要注意,有的浏览器实现,收到全屏模式变化消息时,(Windows上)会类似下面这样处理:
[code]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插件就工作正常了。但我们写的则不会哈。
所以,如果你真想全屏,可以参考下面的代码:
[code]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开发】。
相关文章推荐
- Bootstrap~多级导航(级联导航)的实现
- 在linux环境下安装redis
- 1030. Travel Plan (30)寻找最短路径
- HttpClient使用详解
- 微信token失败原因
- Linux 的文件类型
- PAT (Basic Level)1032. 挖掘机技术哪家强
- 什么是兼容性測试?怎样做好兼容性測试?
- Android 逐帧动画
- 手动创建单例
- iOS url schemes应用
- iptables交互配置shell脚本
- android--屏幕旋转方法总结
- 移动端a链接按下背景变色js
- UGUI 3d坐标转UI坐标
- 大浪淘沙面试题
- java se 多线程下载
- C++ 使用2个栈实现队列的方法(可直接编译)
- linux无锁话编程,原子
- Xcode7 插件制作入门