PPAPI插件的绘图与输入事件处理
来源:互联网 发布:淘宝商城质检报告 编辑:程序博客网 时间:2024/06/11 04:48
在PPAPI插件与浏览器的交互过程一文中学习了PPAPI插件与浏览器的交互流程、渲染逻辑、输入事件的处理逻辑,这次我们改造一下graphics_2d_example示例,加入处理鼠标事件的逻辑,演示一下PPAPI插件想要处理输入事件时的代码流程。
foruok原创,如需转载请关注foruok的微信订阅号“程序视界”联系foruok。
工程
新建一个Win32项目,类型选DLL,去掉预编译头文件stdafx.h和stdafx.cpp,并且在项目属性–>配置属性–>C/C++–>预编译头,把预编译头选项的值设置为不使用预编译头。
使用UNICODE字符集,运行库选择MT。
项目名就叫ppapi_simple吧,把ppapi的上一级目录添加到附加包含目录里。
把graphics_2d_example.c拷贝过来,改名为ppapi_simple.c。内容修改成下面的样子:
/* Copyright (c) 2012 The Chromium Authors. All rights reserved.* Use of this source code is governed by a BSD-style license that can be* found in the LICENSE file.* * 2016-1-10, edited by foruok.* 如需转载,请关注微信订阅号“程序视界”,回复foruok获取其联系方式**/#include <stdint.h>#include <stdlib.h>#include <string.h>#include <Windows.h>#include <tchar.h>#include "ppapi/c/pp_completion_callback.h"#include "ppapi/c/pp_errors.h"#include "ppapi/c/pp_instance.h"#include "ppapi/c/pp_module.h"#include "ppapi/c/pp_rect.h"#include "ppapi/c/pp_var.h"#include "ppapi/c/ppb.h"#include "ppapi/c/ppb_core.h"#include "ppapi/c/ppb_graphics_2d.h"#include "ppapi/c/ppb_image_data.h"#include "ppapi/c/ppb_instance.h"#include "ppapi/c/ppb_view.h"#include "ppapi/c/ppp.h"#include "ppapi/c/ppp_instance.h"#include "ppapi/c/ppb_input_event.h"#include "ppapi/c/ppp_input_event.h"PPB_GetInterface g_get_browser_interface = NULL;const PPB_Core* g_core_interface;const PPB_Graphics2D* g_graphics_2d_interface;const PPB_ImageData* g_image_data_interface;const PPB_Instance* g_instance_interface;const PPB_View* g_view_interface;// [1]const PPB_InputEvent *g_input_interface;const PPB_MouseInputEvent *g_mouse_interface;/* PPP_Instance implementation -----------------------------------------------*/struct InstanceInfo { PP_Instance pp_instance; struct PP_Size last_size; PP_Resource graphics; struct InstanceInfo* next;};/** Linked list of all live instances. */struct InstanceInfo* all_instances = NULL;/** Returns a refed resource corresponding to the created graphics 2d. */PP_Resource MakeAndBindGraphics2D(PP_Instance instance, const struct PP_Size* size) { PP_Resource graphics; graphics = g_graphics_2d_interface->Create(instance, size, PP_FALSE); if (!graphics) return 0; if (!g_instance_interface->BindGraphics(instance, graphics)) { g_core_interface->ReleaseResource(graphics); return 0; } return graphics;}void FlushCompletionCallback(void* user_data, int32_t result) { /* Don't need to do anything here. */}unsigned int g_colors[4] = { 0xFF0000FF, 0xFFFF00FF, 0xFF00FFFF, 0xFFEA00FF };unsigned int g_color_index = 0;void Repaint(struct InstanceInfo* instance, const struct PP_Size* size) { PP_Resource image; struct PP_ImageDataDesc image_desc; uint32_t* image_data; int num_words, i; /* Ensure the graphics 2d is ready. */ if (!instance->graphics) { instance->graphics = MakeAndBindGraphics2D(instance->pp_instance, size); if (!instance->graphics) return; } /* Create image data to paint into. */ image = g_image_data_interface->Create( instance->pp_instance, PP_IMAGEDATAFORMAT_BGRA_PREMUL, size, PP_TRUE); if (!image) return; g_image_data_interface->Describe(image, &image_desc); /* Fill the image with blue. */ image_data = (uint32_t*)g_image_data_interface->Map(image); if (!image_data) { g_core_interface->ReleaseResource(image); return; } num_words = image_desc.stride * size->height / 4; // [6] g_color_index++; if (g_color_index >= sizeof(g_colors) / sizeof(g_colors[0])) g_color_index = 0; for (i = 0; i < num_words; i++) image_data[i] = g_colors[g_color_index]; /* Paint image to graphics 2d. */ g_graphics_2d_interface->ReplaceContents(instance->graphics, image); g_graphics_2d_interface->Flush(instance->graphics, PP_MakeCompletionCallback(&FlushCompletionCallback, NULL)); g_core_interface->ReleaseResource(image);}/** Returns the info for the given instance, or NULL if it's not found. */struct InstanceInfo* FindInstance(PP_Instance instance) { struct InstanceInfo* cur = all_instances; while (cur) { if (cur->pp_instance == instance) return cur; cur = cur->next; } return NULL;}PP_Bool Instance_DidCreate(PP_Instance instance, uint32_t argc, const char* argn[], const char* argv[]) { struct InstanceInfo* info = (struct InstanceInfo*)malloc(sizeof(struct InstanceInfo)); info->pp_instance = instance; info->last_size.width = 0; info->last_size.height = 0; info->graphics = 0; /* Insert into linked list of live instances. */ info->next = all_instances; all_instances = info; // [5] g_input_interface->RequestInputEvents(instance, PP_INPUTEVENT_CLASS_MOUSE); g_input_interface->RequestFilteringInputEvents(instance, PP_INPUTEVENT_CLASS_MOUSE); OutputDebugString(_T("Instance_DidCreate\r\n")); return PP_TRUE;}void Instance_DidDestroy(PP_Instance instance) { /* Find the matching item in the linked list, delete it, and patch the * links. */ struct InstanceInfo** prev_ptr = &all_instances; struct InstanceInfo* cur = all_instances; while (cur) { if (instance == cur->pp_instance) { *prev_ptr = cur->next; g_core_interface->ReleaseResource(cur->graphics); free(cur); return; } prev_ptr = &cur->next; cur = cur->next; }}void Instance_DidChangeView(PP_Instance pp_instance, PP_Resource view) { struct PP_Rect position; struct InstanceInfo* info = FindInstance(pp_instance); if (!info) return; if (g_view_interface->GetRect(view, &position) == PP_FALSE) return; if (info->last_size.width != position.size.width || info->last_size.height != position.size.height) { /* Got a resize, repaint the plugin. */ Repaint(info, &position.size); info->last_size.width = position.size.width; info->last_size.height = position.size.height; } OutputDebugString(_T("Instance_DidChangeView\r\n"));}void Instance_DidChangeFocus(PP_Instance pp_instance, PP_Bool has_focus) {}PP_Bool Instance_HandleDocumentLoad(PP_Instance pp_instance, PP_Resource pp_url_loader) { return PP_FALSE;}static PPP_Instance instance_interface = { &Instance_DidCreate, &Instance_DidDestroy, &Instance_DidChangeView, &Instance_DidChangeFocus, &Instance_HandleDocumentLoad};// [3]PP_Bool InputEvent_HandleInputEvent(PP_Instance instance, PP_Resource input_event){ struct PP_Point pt; TCHAR szLog[512] = { 0 }; switch (g_input_interface->GetType(input_event)) { case PP_INPUTEVENT_TYPE_MOUSEDOWN: pt = g_mouse_interface->GetPosition(input_event); _stprintf_s(szLog, 512, _T("InputEvent_HandleInputEvent, mouse down at [%d, %d]\r\n"), pt.x, pt.y); OutputDebugString(szLog); break; /* case PP_INPUTEVENT_TYPE_MOUSEUP: OutputDebugString(_T("InputEvent_HandleInputEvent, mouse up\r\n")); break; case PP_INPUTEVENT_TYPE_MOUSEMOVE: OutputDebugString(_T("InputEvent_HandleInputEvent, mouse move\r\n")); break; case PP_INPUTEVENT_TYPE_MOUSEENTER: OutputDebugString(_T("InputEvent_HandleInputEvent, mouse enter\r\n")); break; case PP_INPUTEVENT_TYPE_MOUSELEAVE: OutputDebugString(_T("InputEvent_HandleInputEvent, mouse leave\r\n")); break; */ default: return PP_FALSE; } struct InstanceInfo* info = FindInstance(instance); if (info && info->last_size.width > 0) { Repaint(info, &info->last_size); } return PP_TRUE;}// [3]static PPP_InputEvent input_interface = { &InputEvent_HandleInputEvent};/* Global entrypoints --------------------------------------------------------*/PP_EXPORT int32_t PPP_InitializeModule(PP_Module module, PPB_GetInterface get_browser_interface) { g_get_browser_interface = get_browser_interface; g_core_interface = (const PPB_Core*) get_browser_interface(PPB_CORE_INTERFACE); g_instance_interface = (const PPB_Instance*) get_browser_interface(PPB_INSTANCE_INTERFACE); g_image_data_interface = (const PPB_ImageData*) get_browser_interface(PPB_IMAGEDATA_INTERFACE); g_graphics_2d_interface = (const PPB_Graphics2D*) get_browser_interface(PPB_GRAPHICS_2D_INTERFACE); g_view_interface = (const PPB_View*) get_browser_interface(PPB_VIEW_INTERFACE); // [2] g_input_interface = (const PPB_InputEvent*)get_browser_interface(PPB_INPUT_EVENT_INTERFACE); g_mouse_interface = (const PPB_MouseInputEvent*)get_browser_interface(PPB_MOUSE_INPUT_EVENT_INTERFACE); if (!g_core_interface || !g_instance_interface || !g_image_data_interface || !g_graphics_2d_interface || !g_view_interface || !g_input_interface || !g_mouse_interface) return -1; OutputDebugString(_T("PPP_InitializeModule\r\n")); return PP_OK;}PP_EXPORT void PPP_ShutdownModule() {}PP_EXPORT const void* PPP_GetInterface(const char* interface_name) { if (strcmp(interface_name, PPP_INSTANCE_INTERFACE) == 0) { OutputDebugString(_T("PPP_GetInterface, instance_interface\r\n")); return &instance_interface; } // [4] else if (strcmp(interface_name, PPP_INPUT_EVENT_INTERFACE) == 0) { OutputDebugString(_T("PPP_GetInterface, input_interface\r\n")); return &input_interface; } return NULL;}
代码改动说明
ppapi_simple.c相对graphics_2d_example.c来讲,主要有6处改动,已在前面的源代码中使用[1]、[2]之类的符号标注出来了。大部分改动是为处理鼠标事件加入的代码,有两处是绘图相关的改动。
先说要处理鼠标事件需要添加的代码及流程。
[1] 这里声明了两个全局变量,g_input_interface和g_mouse_interface,它们将会在PPP_InitializeModule方法中被初始化(标号为[2]处的改动)。g_input_interface是浏览器暴露出来的输入事件接口,插件要请求处理某类事件就通过它。g_mouse_interface是鼠标事件,可以根据事件资源ID获取对应的详细信息,如位置、按下的鼠标按键等。
[3] 这处改动声明了插件测的输入处理接口。一个结构体,一个函数。
[4] 这里会被浏览器调用到,我们新添加的PPP_InputEvent就是在这里返回给浏览器。浏览器拿到PPP_InputEvent后就可以把事件传递给这个接口的HandleInputEvent方法,也就是我们实现的InputEvent_HandleInputEvent方法。在InputEvent_HandleInputEvent方法里,鼠标左键按下时我们调用Repaint()来重绘。
[5] 当插件对象实例创建时,我们向浏览器的输入事件接口请求处理鼠标事件。浏览器收到这个请求,才会派发事件给我们的插件实例对象。
[6] 渲染(绘图)函数。绘图过程,在PPAPI插件与浏览器的交互过程中已介绍过了,不多说了。这里添加的代码,主要是为了让示例随着鼠标点击有变化。通过一个颜色数组和索引,变换插件实例对象对应视图区域的颜色。
我还在关键处插入了一些日志代码,可以通过DbgView来查看。
下面是运行效果图:
通过CEF运行时使用的命令参数如下:
–ppapi-out-of-process –register-pepper-plugins=”D:\projects\cef_binary_3.2357.1271.g8e0674e_windows32\Release\stub.dll;application/x-ppapi-simple” –url=file:///d:/projects/cef_binary_3.2357.1271.g8e0674e_windows32/Release/simple.html
simple.html和stub.html类似,改了下title和embed标签的type。
好啦,新的示例主要就这些内容了,处理输入事件的流程应该也清楚了。
相关文章参考:
- CEF Windows开发环境搭建
- CEF加载PPAPI插件
- VS2013编译最简单的PPAPI插件
- 理解PPAPI的设计
- PPAPI插件与浏览器的交互过程
- Windows下从源码编译CEF
- 编译PPAPI的media_stream_video示例
- PPAPI插件的绘图与输入事件处理
- PPAPI插件的全屏切换处理
- PPAPI插件与浏览器的交互过程
- PPAPI插件与浏览器的通信
- 在PPAPI插件中使用Skia绘图
- VS2013编译最简单的PPAPI插件
- PPAPI插件的动态创建、修改、删除
- 绘图技术与事件处理机制---鼠标事件
- CEF加载PPAPI插件
- PPAPI 插件编写
- PPAPI插件开发指南
- PPAPI插件开发指南
- 【Java】Java绘图技术与事件处理机制
- cef3 加载flash ppapi插件
- NPAPI和PPAPI插件开发
- PPAPI中使用OpenGL ES绘图
- QT事件处理及绘图
- 理解PPAPI的设计
- 行为型模式-中介者mediator
- 行为型模式-备忘录memento
- operator new, new operator, delete new, new delete
- 行为型模式-观察者observer
- 解决Codeforces访问慢的本地方法
- PPAPI插件的绘图与输入事件处理
- IOS-IOS应用的核心(一)
- 【杭电oj】1215 - 七夕节(打表,水)
- 归档,解档
- C++中预处理(条件编译)
- 常用的Command对象的各属性和方法
- 正则表达式基本语法
- iOS笔记之项目构成及方法调用
- IOS-Quartz2D API简单入门