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来查看。

下面是运行效果图:

ppapi_simple

通过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示例
0 0