cefclient:

- Add the User Interface App Example that demonstrates two-way JavaScript communication between the page and an embedded plugin implemented using OpenGL.

git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@40 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
Marshall Greenblatt 2009-08-21 19:43:37 +00:00
parent 2b7e69d200
commit d7c54d6514
13 changed files with 585 additions and 21 deletions

View File

@ -11,6 +11,7 @@
#include "resource_util.h" #include "resource_util.h"
#include "scheme_test.h" #include "scheme_test.h"
#include "string_util.h" #include "string_util.h"
#include "uiplugin_test.h"
#include <sstream> #include <sstream>
@ -56,6 +57,9 @@ int APIENTRY _tWinMain(HINSTANCE hInstance,
// Register the internal client plugin. // Register the internal client plugin.
InitPluginTest(); InitPluginTest();
// Register the internal UI client plugin.
InitUIPluginTest();
// Register the V8 extension handler. // Register the V8 extension handler.
InitExtensionTest(); InitExtensionTest();
@ -341,6 +345,9 @@ public:
std::wstring& mimeType, std::wstring& mimeType,
int loadFlags) int loadFlags)
{ {
DWORD dwSize;
LPBYTE pBytes;
std::wstring url = request->GetURL(); std::wstring url = request->GetURL();
if(url == L"http://tests/request") { if(url == L"http://tests/request") {
// Show the request contents // Show the request contents
@ -349,15 +356,27 @@ public:
resourceStream = CefStreamReader::CreateForData( resourceStream = CefStreamReader::CreateForData(
(void*)dump.c_str(), dump.size() * sizeof(wchar_t)); (void*)dump.c_str(), dump.size() * sizeof(wchar_t));
mimeType = L"text/plain"; mimeType = L"text/plain";
} else if(wcsstr(url.c_str(), L"logo.gif") != NULL) { } else if(url == L"http://tests/uiapp") {
// Show the uiapp contents
if(LoadBinaryResource(IDS_UIPLUGIN, dwSize, pBytes)) {
resourceStream = CefStreamReader::CreateForHandler(
new ClientReadHandler(pBytes, dwSize));
mimeType = L"text/html";
}
} else if(wcsstr(url.c_str(), L"/logo.gif") != NULL) {
// Any time we find "logo.gif" in the URL substitute in our own image // Any time we find "logo.gif" in the URL substitute in our own image
DWORD dwSize;
LPBYTE pBytes;
if(LoadBinaryResource(IDS_LOGO, dwSize, pBytes)) { if(LoadBinaryResource(IDS_LOGO, dwSize, pBytes)) {
resourceStream = CefStreamReader::CreateForHandler( resourceStream = CefStreamReader::CreateForHandler(
new ClientReadHandler(pBytes, dwSize)); new ClientReadHandler(pBytes, dwSize));
mimeType = L"image/jpg"; mimeType = L"image/jpg";
} }
} else if(wcsstr(url.c_str(), L"/logoball.png") != NULL) {
// Load the "logoball.png" image resource.
if(LoadBinaryResource(IDS_LOGOBALL, dwSize, pBytes)) {
resourceStream = CefStreamReader::CreateForHandler(
new ClientReadHandler(pBytes, dwSize));
mimeType = L"image/png";
}
} }
return RV_CONTINUE; return RV_CONTINUE;
} }
@ -485,6 +504,9 @@ public:
{ {
// Add the V8 bindings. // Add the V8 bindings.
InitBindingTest(browser, frame, object); InitBindingTest(browser, frame, object);
// Add the UI app V8 bindings.
InitUIBindingTest(browser, frame, object);
return RV_HANDLED; return RV_HANDLED;
} }
@ -515,6 +537,7 @@ public:
m_MainHwnd = hwnd; m_MainHwnd = hwnd;
Unlock(); Unlock();
} }
HWND GetMainHwnd() { return m_MainHwnd; }
void SetEditHwnd(HWND hwnd) void SetEditHwnd(HWND hwnd)
{ {
@ -554,6 +577,23 @@ protected:
bool m_bCanGoForward; bool m_bCanGoForward;
}; };
// global handler instance
CefRefPtr<ClientHandler> g_handler;
CefRefPtr<CefBrowser> AppGetBrowser()
{
if(!g_handler.get())
return NULL;
return g_handler->GetBrowser();
}
HWND AppGetMainHwnd()
{
if(!g_handler.get())
return NULL;
return g_handler->GetMainHwnd();
}
// //
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM) // FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
@ -562,7 +602,6 @@ protected:
// //
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{ {
static CefRefPtr<ClientHandler> handler;
static HWND backWnd = NULL, forwardWnd = NULL, reloadWnd = NULL, static HWND backWnd = NULL, forwardWnd = NULL, reloadWnd = NULL,
stopWnd = NULL, editWnd = NULL; stopWnd = NULL, editWnd = NULL;
static WNDPROC editWndOldProc = NULL; static WNDPROC editWndOldProc = NULL;
@ -577,10 +616,10 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
switch (message) switch (message)
{ {
case WM_CHAR: case WM_CHAR:
if (wParam == VK_RETURN && handler.get()) if (wParam == VK_RETURN && g_handler.get())
{ {
// When the user hits the enter key load the URL // When the user hits the enter key load the URL
CefRefPtr<CefBrowser> browser = handler->GetBrowser(); CefRefPtr<CefBrowser> browser = g_handler->GetBrowser();
wchar_t strPtr[MAX_URL_LENGTH] = {0}; wchar_t strPtr[MAX_URL_LENGTH] = {0};
*((LPWORD)strPtr) = MAX_URL_LENGTH; *((LPWORD)strPtr) = MAX_URL_LENGTH;
LRESULT strLen = SendMessage(hWnd, EM_GETLINE, 0, (LPARAM)strPtr); LRESULT strLen = SendMessage(hWnd, EM_GETLINE, 0, (LPARAM)strPtr);
@ -603,8 +642,8 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
case WM_CREATE: case WM_CREATE:
{ {
// Create the single static handler class instance // Create the single static handler class instance
handler = new ClientHandler(); g_handler = new ClientHandler();
handler->SetMainHwnd(hWnd); g_handler->SetMainHwnd(hWnd);
// Create the child windows used for navigation // Create the child windows used for navigation
RECT rect; RECT rect;
@ -650,7 +689,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
reinterpret_cast<WNDPROC>(GetWindowLongPtr(editWnd, GWLP_WNDPROC)); reinterpret_cast<WNDPROC>(GetWindowLongPtr(editWnd, GWLP_WNDPROC));
SetWindowLongPtr(editWnd, GWLP_WNDPROC, SetWindowLongPtr(editWnd, GWLP_WNDPROC,
reinterpret_cast<LONG_PTR>(WndProc)); reinterpret_cast<LONG_PTR>(WndProc));
handler->SetEditHwnd(editWnd); g_handler->SetEditHwnd(editWnd);
rect.top += URLBAR_HEIGHT; rect.top += URLBAR_HEIGHT;
@ -661,7 +700,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
// Creat the new child child browser window // Creat the new child child browser window
CefBrowser::CreateBrowser(info, false, CefBrowser::CreateBrowser(info, false,
static_cast<CefRefPtr<CefHandler>>(handler), static_cast<CefRefPtr<CefHandler>>(g_handler),
L"http://www.google.com"); L"http://www.google.com");
// Start the timer that will be used to update child window state // Start the timer that will be used to update child window state
@ -670,11 +709,11 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
return 0; return 0;
case WM_TIMER: case WM_TIMER:
if(handler.get() && handler->GetBrowserHwnd()) if(g_handler.get() && g_handler->GetBrowserHwnd())
{ {
// Retrieve the current navigation state // Retrieve the current navigation state
bool isLoading, canGoBack, canGoForward; bool isLoading, canGoBack, canGoForward;
handler->GetNavState(isLoading, canGoBack, canGoForward); g_handler->GetNavState(isLoading, canGoBack, canGoForward);
// Update the status of child windows // Update the status of child windows
EnableWindow(editWnd, TRUE); EnableWindow(editWnd, TRUE);
@ -688,8 +727,8 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
case WM_COMMAND: case WM_COMMAND:
{ {
CefRefPtr<CefBrowser> browser; CefRefPtr<CefBrowser> browser;
if(handler.get()) if(g_handler.get())
browser = handler->GetBrowser(); browser = g_handler->GetBrowser();
wmId = LOWORD(wParam); wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam); wmEvent = HIWORD(wParam);
@ -779,6 +818,10 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
if(browser.get()) if(browser.get())
RunSchemeTest(browser); RunSchemeTest(browser);
return 0; return 0;
case ID_TESTS_UIAPP: // Test the UI app
if(browser.get())
RunUIPluginTest(browser);
return 0;
} }
} }
break; break;
@ -789,15 +832,15 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
return 0; return 0;
case WM_SETFOCUS: case WM_SETFOCUS:
if(handler.get() && handler->GetBrowserHwnd()) if(g_handler.get() && g_handler->GetBrowserHwnd())
{ {
// Pass focus to the browser window // Pass focus to the browser window
PostMessage(handler->GetBrowserHwnd(), WM_SETFOCUS, wParam, NULL); PostMessage(g_handler->GetBrowserHwnd(), WM_SETFOCUS, wParam, NULL);
} }
return 0; return 0;
case WM_SIZE: case WM_SIZE:
if(handler.get() && handler->GetBrowserHwnd()) if(g_handler.get() && g_handler->GetBrowserHwnd())
{ {
// Resize the browser window and address bar to match the new frame // Resize the browser window and address bar to match the new frame
// window size // window size
@ -810,7 +853,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
HDWP hdwp = BeginDeferWindowPos(1); HDWP hdwp = BeginDeferWindowPos(1);
hdwp = DeferWindowPos(hdwp, editWnd, NULL, urloffset, hdwp = DeferWindowPos(hdwp, editWnd, NULL, urloffset,
0, rect.right - urloffset, URLBAR_HEIGHT, SWP_NOZORDER); 0, rect.right - urloffset, URLBAR_HEIGHT, SWP_NOZORDER);
hdwp = DeferWindowPos(hdwp, handler->GetBrowserHwnd(), NULL, hdwp = DeferWindowPos(hdwp, g_handler->GetBrowserHwnd(), NULL,
rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
SWP_NOZORDER); SWP_NOZORDER);
EndDeferWindowPos(hdwp); EndDeferWindowPos(hdwp);
@ -818,7 +861,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
break; break;
case WM_ERASEBKGND: case WM_ERASEBKGND:
if(handler.get() && handler->GetBrowserHwnd()) if(g_handler.get() && g_handler->GetBrowserHwnd())
{ {
// Dont erase the background if the browser window has been loaded // Dont erase the background if the browser window has been loaded
// (this avoids flashing) // (this avoids flashing)

View File

@ -5,3 +5,10 @@
#pragma once #pragma once
#include "resource.h" #include "resource.h"
#include "cef.h"
// Return the main browser window instance.
CefRefPtr<CefBrowser> AppGetBrowser();
// Return the main application window handle.
HWND AppGetMainHwnd();

View File

@ -29,6 +29,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
// //
IDS_LOGO BINARY "res\logo.jpg" IDS_LOGO BINARY "res\logo.jpg"
IDS_UIPLUGIN BINARY "res\uiplugin.html"
IDS_LOGOBALL BINARY "res\logoball.png"
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// //
@ -64,6 +66,7 @@ BEGIN
MENUITEM "Popup Window", ID_TESTS_POPUP MENUITEM "Popup Window", ID_TESTS_POPUP
MENUITEM "Request", ID_TESTS_REQUEST MENUITEM "Request", ID_TESTS_REQUEST
MENUITEM "Scheme Handler", ID_TESTS_SCHEME_HANDLER MENUITEM "Scheme Handler", ID_TESTS_SCHEME_HANDLER
MENUITEM "UI App Example", ID_TESTS_UIAPP
END END
END END

View File

@ -265,6 +265,22 @@
RelativePath=".\string_util.h" RelativePath=".\string_util.h"
> >
</File> </File>
<File
RelativePath=".\uiplugin.cpp"
>
</File>
<File
RelativePath=".\uiplugin.h"
>
</File>
<File
RelativePath=".\uiplugin_test.cpp"
>
</File>
<File
RelativePath=".\uiplugin_test.h"
>
</File>
</Files> </Files>
<Globals> <Globals>
</Globals> </Globals>

View File

@ -12,7 +12,7 @@
/> />
<Tool <Tool
Name="VCLinkerTool" Name="VCLinkerTool"
AdditionalDependencies="comctl32.lib shlwapi.lib rpcrt4.lib winmm.lib" AdditionalDependencies="comctl32.lib shlwapi.lib rpcrt4.lib winmm.lib opengl32.lib glu32.lib"
AdditionalLibraryDirectories="&quot;$(OutDir)&quot;" AdditionalLibraryDirectories="&quot;$(OutDir)&quot;"
/> />
<Tool <Tool

View File

@ -9,7 +9,7 @@
// Initialized in NP_Initialize. // Initialized in NP_Initialize.
NPNetscapeFuncs* g_browser = NULL; NPNetscapeFuncs* g_browser = NULL;
static
NPError NPP_New(NPMIMEType plugin_type, NPP instance, uint16 mode, int16 argc, NPError NPP_New(NPMIMEType plugin_type, NPP instance, uint16 mode, int16 argc,
char* argn[], char* argv[], NPSavedData* saved) { char* argn[], char* argv[], NPSavedData* saved) {
if (instance == NULL) if (instance == NULL)
@ -22,6 +22,7 @@ NPError NPP_New(NPMIMEType plugin_type, NPP instance, uint16 mode, int16 argc,
return NPERR_NO_ERROR; return NPERR_NO_ERROR;
} }
static
NPError NPP_Destroy(NPP instance, NPSavedData** save) { NPError NPP_Destroy(NPP instance, NPSavedData** save) {
ClientPlugin* plugin_impl = reinterpret_cast<ClientPlugin*>(instance->pdata); ClientPlugin* plugin_impl = reinterpret_cast<ClientPlugin*>(instance->pdata);
@ -33,6 +34,7 @@ NPError NPP_Destroy(NPP instance, NPSavedData** save) {
return NPERR_NO_ERROR; return NPERR_NO_ERROR;
} }
static
NPError NPP_SetWindow(NPP instance, NPWindow* window_info) { NPError NPP_SetWindow(NPP instance, NPWindow* window_info) {
if (instance == NULL) if (instance == NULL)
return NPERR_INVALID_INSTANCE_ERROR; return NPERR_INVALID_INSTANCE_ERROR;

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

View File

@ -0,0 +1,57 @@
<html>
<head>
<title>User Interface App Example</title>
</head>
<body bottommargin="2" rightmargin="0" leftmargin="0" topmargin="0" marginwidth="0" marginheight="0" style="font-family: Verdana, Arial;">
<div align="center">
<table border="0" cellpadding="0" cellspacing="0" width="99.9%" height="100%">
<tr>
<td height="100%" align="center" valign="top">
<table border="0" cellpadding="2" cellspacing="0">
<tr>
<td colspan="2" style="font-size: 18pt;">User Interface App Example</td>
</tr>
<tr>
<td colspan="2" style="font-size: 8pt;"><i>An embedded OpenGL plugin window that communicates with the Chromium browser control via JavaScript calls.</i>
<a href="#" onclick="window.uiapp.viewSource(); return false;">View Page Source</a></td>
</tr>
<tr>
<td colspan="2" height="10"></td>
</tr>
<tr>
<td width="100" valign="top"><img src="logoball.png" width="100" height="101"></td>
<td style="font-size: 10pt;"><span style="font-size: 12pt;">You can make the square rotate!</span>
<ul>
<li>Click the square with the left mouse button or click the <b>Decrement Rotation</b> button to decrement the rotation value.</li>
<li>Click the square with the right mouse button or click the <b>Increment Rotation</b> button to increment the rotation value.</li>
<li>Click the <b>Reset Rotation</b> button to reset the rotation value to zero.</li>
</ul>
</td>
</tr>
</table>
<div style="padding: 2px; margin: 5px; border: red 1px solid; width: 350px;">
<embed type="application/x-client-ui-plugin" width=350 height=350></embed>
</div>
<form name="control">
Rotation Value: <input type="text" name="rotation_field" value="0" size="5" readonly>
<br/><input type="button" value="Decrement Rotation" onclick="window.uiapp.modifyRotation(-2.0);">
<input type="button" value="Increment Rotation" onclick="window.uiapp.modifyRotation(2.0);">
<input type="button" value="Reset Rotation" name="reset_button" onclick="window.uiapp.resetRotation();" disabled>
</form>
</td>
</tr>
</table>
</div>
<script language="JavaScript">
// Called by the application after rotation has been changed.
// |val| is the new rotation value.
function notifyNewRotation(val)
{
document.control.rotation_field.value = val;
document.control.reset_button.disabled = (val == 0);
}
</script>
</body>
</html>

View File

@ -28,8 +28,11 @@
#define ID_TESTS_POPUP 32775 #define ID_TESTS_POPUP 32775
#define ID_TESTS_REQUEST 32776 #define ID_TESTS_REQUEST 32776
#define ID_TESTS_SCHEME_HANDLER 32777 #define ID_TESTS_SCHEME_HANDLER 32777
#define ID_TESTS_UIAPP 32778
#define IDC_STATIC -1 #define IDC_STATIC -1
#define IDS_LOGO 1000 #define IDS_LOGO 1000
#define IDS_UIPLUGIN 1001
#define IDS_LOGOBALL 1002
// Next default values for new objects // Next default values for new objects
// //

View File

@ -0,0 +1,284 @@
// Copyright (c) 2009 The Chromium Embedded Framework Authors.
// Portions copyright (c) 2006-2008 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.
#include "stdafx.h"
#include "uiplugin.h"
#include "cefclient.h"
#include <gl/gl.h>
#include <sstream>
// Initialized in NP_Initialize.
NPNetscapeFuncs* g_uibrowser = NULL;
// Global values.
float g_rotationspeed = 0.0f;
float g_theta = 0.0f;
// Class holding pointers for the client plugin window.
class ClientPlugin
{
public:
ClientPlugin()
{
hWnd = NULL;
hDC = NULL;
hRC = NULL;
}
HWND hWnd;
HDC hDC;
HGLRC hRC;
};
// Forward declarations of functions included in this code module:
LRESULT CALLBACK PluginWndProc(HWND hWnd, UINT message, WPARAM wParam,
LPARAM lParam);
void EnableOpenGL(HWND hWnd, HDC * hDC, HGLRC * hRC);
void DisableOpenGL(HWND hWnd, HDC hDC, HGLRC hRC);
static
NPError NPP_New(NPMIMEType plugin_type, NPP instance, uint16 mode, int16 argc,
char* argn[], char* argv[], NPSavedData* saved) {
if (instance == NULL)
return NPERR_INVALID_INSTANCE_ERROR;
ClientPlugin *plugin = new ClientPlugin;
instance->pdata = reinterpret_cast<void*>(plugin);
return NPERR_NO_ERROR;
}
static
NPError NPP_Destroy(NPP instance, NPSavedData** save) {
ClientPlugin *plugin = reinterpret_cast<ClientPlugin*>(instance->pdata);
if (plugin) {
if(plugin->hWnd) {
DestroyWindow(plugin->hWnd);
DisableOpenGL(plugin->hWnd, plugin->hDC, plugin->hRC);
}
delete plugin;
g_rotationspeed = 0.0f;
g_theta = 0.0f;
}
return NPERR_NO_ERROR;
}
static
NPError NPP_SetWindow(NPP instance, NPWindow* window_info) {
if (instance == NULL)
return NPERR_INVALID_INSTANCE_ERROR;
if (window_info == NULL)
return NPERR_GENERIC_ERROR;
ClientPlugin *plugin = reinterpret_cast<ClientPlugin*>(instance->pdata);
HWND parent_hwnd = reinterpret_cast<HWND>(window_info->window);
if (plugin->hWnd == NULL)
{
WNDCLASS wc;
HINSTANCE hInstance = GetModuleHandle(NULL);
// Register the window class.
wc.style = CS_OWNDC;
wc.lpfnWndProc = PluginWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = L"ClientUIPlugin";
RegisterClass(&wc);
// Create the main window.
plugin->hWnd = CreateWindow(L"ClientUIPlugin", L"Client UI Plugin",
WS_CHILD, 0, 0, 0, 0, parent_hwnd, NULL, hInstance, NULL);
// Enable OpenGL drawing for the window.
EnableOpenGL(plugin->hWnd, &(plugin->hDC), &(plugin->hRC));
}
// Position the window and make sure it's visible.
RECT parent_rect;
GetClientRect(parent_hwnd, &parent_rect);
SetWindowPos(plugin->hWnd, NULL, parent_rect.left, parent_rect.top,
parent_rect.right - parent_rect.left,
parent_rect.bottom - parent_rect.top, SWP_SHOWWINDOW);
UpdateWindow(plugin->hWnd);
ShowWindow(plugin->hWnd, SW_SHOW);
return NPERR_NO_ERROR;
}
NPError API_CALL NP_UIGetEntryPoints(NPPluginFuncs* pFuncs)
{
pFuncs->newp = NPP_New;
pFuncs->destroy = NPP_Destroy;
pFuncs->setwindow = NPP_SetWindow;
return NPERR_NO_ERROR;
}
NPError API_CALL NP_UIInitialize(NPNetscapeFuncs* pFuncs)
{
g_uibrowser = pFuncs;
return NPERR_NO_ERROR;
}
NPError API_CALL NP_UIShutdown(void)
{
g_uibrowser = NULL;
return NPERR_NO_ERROR;
}
// Send the notification to the browser as a JavaScript function call.
static void NotifyNewRotation(float value)
{
std::wstringstream buf;
buf << L"notifyNewRotation(" << value << L");";
AppGetBrowser()->GetMainFrame()->ExecuteJavaScript(buf.str(), std::wstring(),
0);
}
void ModifyRotation(float value)
{
g_rotationspeed += value;
NotifyNewRotation(g_rotationspeed);
}
void ResetRotation()
{
g_rotationspeed = 0.0;
NotifyNewRotation(g_rotationspeed);
}
// Nice little fly polygon borrowed from the OpenGL Red Book.
const GLubyte fly[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0x80, 0x01, 0xC0, 0x06, 0xC0, 0x03, 0x60,
0x04, 0x60, 0x06, 0x20, 0x04, 0x30, 0x0C, 0x20,
0x04, 0x18, 0x18, 0x20, 0x04, 0x0C, 0x30, 0x20,
0x04, 0x06, 0x60, 0x20, 0x44, 0x03, 0xC0, 0x22,
0x44, 0x01, 0x80, 0x22, 0x44, 0x01, 0x80, 0x22,
0x44, 0x01, 0x80, 0x22, 0x44, 0x01, 0x80, 0x22,
0x44, 0x01, 0x80, 0x22, 0x44, 0x01, 0x80, 0x22,
0x66, 0x01, 0x80, 0x66, 0x33, 0x01, 0x80, 0xCC,
0x19, 0x81, 0x81, 0x98, 0x0C, 0xC1, 0x83, 0x30,
0x07, 0xe1, 0x87, 0xe0, 0x03, 0x3f, 0xfc, 0xc0,
0x03, 0x31, 0x8c, 0xc0, 0x03, 0x33, 0xcc, 0xc0,
0x06, 0x64, 0x26, 0x60, 0x0c, 0xcc, 0x33, 0x30,
0x18, 0xcc, 0x33, 0x18, 0x10, 0xc4, 0x23, 0x08,
0x10, 0x63, 0xC6, 0x08, 0x10, 0x30, 0x0c, 0x08,
0x10, 0x18, 0x18, 0x08, 0x10, 0x00, 0x00, 0x08};
// Plugin window procedure.
LRESULT CALLBACK PluginWndProc(HWND hWnd, UINT message, WPARAM wParam,
LPARAM lParam)
{
HDC hDC;
int width, height;
switch(message)
{
case WM_CREATE:
// Start the timer that's used for redrawing.
SetTimer(hWnd, 1, 1, NULL);
return 0;
case WM_DESTROY:
// Stop the timer that's used for redrawing.
KillTimer(hWnd, 1);
return 0;
case WM_LBUTTONDOWN:
// Decrement rotation speed.
ModifyRotation(-2.0f);
return 0;
case WM_RBUTTONDOWN:
// Increment rotation speed.
ModifyRotation(2.0f);
return 0;
case WM_SIZE:
// Resize the OpenGL viewport to match the window size.
width = LOWORD(lParam);
height = HIWORD(lParam);
glViewport(0, 0, width, height);
break;
case WM_ERASEBKGND:
return 0;
case WM_TIMER:
// Adjust the theta value and redraw the display when the timer fires.
hDC = GetDC(hWnd);
glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
glPushMatrix();
glEnable(GL_POLYGON_STIPPLE);
glPolygonStipple(fly);
glRotatef(g_theta, 0.0f, 0.0f, 1.0f);
glBegin(GL_QUADS);
glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(0.7f, 0.7f);
glColor3f(0.0f, 1.0f, 0.0f); glVertex2f(0.7f, -0.7f);
glColor3f(0.0f, 0.0f, 1.0f); glVertex2f(-0.7f, -0.7f);
glColor3f(1.0f, 0.0f, 1.0f); glVertex2f(-0.7f, 0.7f);
glEnd();
glDisable(GL_POLYGON_STIPPLE);
glPopMatrix();
SwapBuffers(hDC);
ReleaseDC(hWnd, hDC);
g_theta -= g_rotationspeed;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
// Enable OpenGL.
void EnableOpenGL(HWND hWnd, HDC * hDC, HGLRC * hRC)
{
PIXELFORMATDESCRIPTOR pfd;
int format;
// Get the device context.
*hDC = GetDC(hWnd);
// Set the pixel format for the DC.
ZeroMemory(&pfd, sizeof(pfd));
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 24;
pfd.cDepthBits = 16;
pfd.iLayerType = PFD_MAIN_PLANE;
format = ChoosePixelFormat(*hDC, &pfd);
SetPixelFormat(*hDC, format, &pfd);
// Create and enable the render contex.
*hRC = wglCreateContext(*hDC);
wglMakeCurrent(*hDC, *hRC);
}
// Disable OpenGL.
void DisableOpenGL(HWND hWnd, HDC hDC, HGLRC hRC)
{
wglMakeCurrent(NULL, NULL);
wglDeleteContext(hRC);
ReleaseDC(hWnd, hDC);
}

View File

@ -0,0 +1,22 @@
// Copyright (c) 2009 The Chromium Embedded Framework Authors.
// Portions copyright (c) 2006-2008 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.
// Portions of this implementation are borrowed from webkit\default_plugin\
// plugin_impl.h
#pragma once
#include "cef_nplugin.h"
extern NPNetscapeFuncs* g_uibrowser;
NPError API_CALL NP_UIGetEntryPoints(NPPluginFuncs* pFuncs);
NPError API_CALL NP_UIInitialize(NPNetscapeFuncs* pFuncs);
NPError API_CALL NP_UIShutdown(void);
// Function called to modify the rotation value.
void ModifyRotation(float value);
// Function called to reset the rotation value.
void ResetRotation();

View File

@ -0,0 +1,109 @@
// Copyright (c) 2008-2009 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#include "stdafx.h"
#include "uiplugin_test.h"
#include "uiplugin.h"
#include "cefclient.h"
void InitUIPluginTest()
{
// Structure providing information about the client plugin.
CefPluginInfo plugin_info;
plugin_info.display_name = L"Client UI Plugin";
plugin_info.unique_name = L"client_ui_plugin";
plugin_info.version = L"1, 0, 0, 1";
plugin_info.description = L"My Example Client UI Plugin";
CefPluginMimeType mime_type;
mime_type.mime_type = L"application/x-client-ui-plugin";
mime_type.file_extensions.push_back(L"*");
plugin_info.mime_types.push_back(mime_type);
plugin_info.np_getentrypoints = NP_UIGetEntryPoints;
plugin_info.np_initialize = NP_UIInitialize;
plugin_info.np_shutdown = NP_UIShutdown;
// Register the internal client plugin
CefRegisterPlugin(plugin_info);
}
// Implementation of the V8 handler class for the "window.uiapp" functions.
class ClientV8UIHandler : public CefThreadSafeBase<CefV8Handler>
{
public:
ClientV8UIHandler() {}
// Execute with the specified argument list and return value. Return true if
// the method was handled.
virtual bool Execute(const std::wstring& name,
CefRefPtr<CefV8Value> object,
const CefV8ValueList& arguments,
CefRefPtr<CefV8Value>& retval,
std::wstring& exception)
{
if(name == L"modifyRotation") {
// This function requires one argument.
if(arguments.size() != 1)
return false;
float increment = 0.;
if(arguments[0]->IsInt()) {
// The argument is an integer value.
increment = static_cast<float>(arguments[0]->GetIntValue());
} else if(arguments[0]->IsDouble()) {
// The argument is an double value.
increment = static_cast<float>(arguments[0]->GetDoubleValue());
}
if(increment != 0.) {
// Modify the rotation accordingly.
ModifyRotation(increment);
return true;
}
} else if(name == L"resetRotation") {
// Reset the rotation value.
ResetRotation();
return true;
} else if(name == L"viewSource") {
// View the page source.
AppGetBrowser()->GetMainFrame()->ViewSource();
return true;
}
return false;
}
};
void InitUIBindingTest(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefV8Value> object)
{
if(frame->GetURL().find(L"http://tests/uiapp") != 0)
return;
// Create the new V8 object.
CefRefPtr<CefV8Value> testObjPtr = CefV8Value::CreateObject(NULL);
// Add the new V8 object to the global window object with the name "uiapp".
object->SetValue(L"uiapp", testObjPtr);
// Create an instance of ClientV8UIHandler as the V8 handler.
CefRefPtr<CefV8Handler> handlerPtr = new ClientV8UIHandler();
// Add a new V8 function to the uiapp object with the name "modifyRotation".
testObjPtr->SetValue(L"modifyRotation",
CefV8Value::CreateFunction(L"modifyRotation", handlerPtr));
// Add a new V8 function to the uiapp object with the name "resetRotation".
testObjPtr->SetValue(L"resetRotation",
CefV8Value::CreateFunction(L"resetRotation", handlerPtr));
// Add a new V8 function to the uiapp object with the name "viewSource".
testObjPtr->SetValue(L"viewSource",
CefV8Value::CreateFunction(L"viewSource", handlerPtr));
}
void RunUIPluginTest(CefRefPtr<CefBrowser> browser)
{
browser->GetMainFrame()->LoadURL(L"http://tests/uiapp");
}

View File

@ -0,0 +1,18 @@
// Copyright (c) 2009 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#pragma once
#include "cef.h"
// Register the internal client plugin.
void InitUIPluginTest();
// Add the V8 bindings.
void InitUIBindingTest(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefV8Value> object);
// Run the test.
void RunUIPluginTest(CefRefPtr<CefBrowser> browser);