mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-06-05 21:39:12 +02:00
Merge revision 569 and 624 changes:
- Add off-screen rendering support for Mac OS-X (issue #540). - Avoid calling OnSetFocus multiple times (issue #563). git-svn-id: https://chromiumembedded.googlecode.com/svn/branches/963@627 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
@@ -3,17 +3,18 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#include <sstream>
|
||||
#include "cefclient.h"
|
||||
#include "include/cef.h"
|
||||
#import "include/cef_application_mac.h"
|
||||
#include "cefclient.h"
|
||||
#include "binding_test.h"
|
||||
#include "client_handler.h"
|
||||
#include "extension_test.h"
|
||||
#include "osrtest_mac.h"
|
||||
#include "resource_util.h"
|
||||
#include "scheme_test.h"
|
||||
#include "string_util.h"
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#include <sstream>
|
||||
|
||||
// The global ClientHandler reference.
|
||||
extern CefRefPtr<ClientHandler> g_handler;
|
||||
@@ -141,7 +142,7 @@ static NSAutoreleasePool* g_autopool = nil;
|
||||
}
|
||||
|
||||
- (void)windowDidBecomeKey:(NSNotification*)notification {
|
||||
if(g_handler.get() && g_handler->GetBrowserHwnd()) {
|
||||
if (g_handler.get() && g_handler->GetBrowserHwnd()) {
|
||||
// Give focus to the browser window.
|
||||
g_handler->GetBrowser()->SetFocus(true);
|
||||
}
|
||||
@@ -209,6 +210,8 @@ NSButton* MakeButton(NSRect* rect, NSString* title, NSView* parent) {
|
||||
- (IBAction)testDevToolsShow:(id)sender;
|
||||
- (IBAction)testDevToolsClose:(id)sender;
|
||||
- (IBAction)testPluginInfo:(id)sender;
|
||||
- (IBAction)testOffscreenRendering:(id)sender;
|
||||
- (IBAction)testTransparentOffscreenRendering:(id)sender;
|
||||
@end
|
||||
|
||||
@implementation ClientAppDelegate
|
||||
@@ -302,6 +305,12 @@ NSButton* MakeButton(NSRect* rect, NSString* title, NSView* parent) {
|
||||
[testMenu addItemWithTitle:@"Plugin Info"
|
||||
action:@selector(testPluginInfo:)
|
||||
keyEquivalent:@""];
|
||||
[testMenu addItemWithTitle:@"Offscreen Rendering"
|
||||
action:@selector(testOffscreenRendering:)
|
||||
keyEquivalent:@""];
|
||||
[testMenu addItemWithTitle:@"Transparent Offscreen Rendering"
|
||||
action:@selector(testTransparentOffscreenRendering:)
|
||||
keyEquivalent:@""];
|
||||
[testItem setSubmenu:testMenu];
|
||||
[menubar addItem:testItem];
|
||||
|
||||
@@ -394,140 +403,148 @@ NSButton* MakeButton(NSRect* rect, NSString* title, NSView* parent) {
|
||||
}
|
||||
|
||||
- (IBAction)testGetSource:(id)sender {
|
||||
if(g_handler.get() && g_handler->GetBrowserHwnd())
|
||||
if (g_handler.get() && g_handler->GetBrowserHwnd())
|
||||
RunGetSourceTest(g_handler->GetBrowser());
|
||||
}
|
||||
|
||||
- (IBAction)testGetText:(id)sender {
|
||||
if(g_handler.get() && g_handler->GetBrowserHwnd())
|
||||
if (g_handler.get() && g_handler->GetBrowserHwnd())
|
||||
RunGetTextTest(g_handler->GetBrowser());
|
||||
}
|
||||
|
||||
- (IBAction)testJSBinding:(id)sender {
|
||||
if(g_handler.get() && g_handler->GetBrowserHwnd())
|
||||
if (g_handler.get() && g_handler->GetBrowserHwnd())
|
||||
RunBindingTest(g_handler->GetBrowser());
|
||||
}
|
||||
|
||||
- (IBAction)testJSExtension:(id)sender {
|
||||
if(g_handler.get() && g_handler->GetBrowserHwnd())
|
||||
if (g_handler.get() && g_handler->GetBrowserHwnd())
|
||||
RunExtensionTest(g_handler->GetBrowser());
|
||||
}
|
||||
|
||||
- (IBAction)testJSExtensionPerf:(id)sender {
|
||||
if(g_handler.get() && g_handler->GetBrowserHwnd())
|
||||
if (g_handler.get() && g_handler->GetBrowserHwnd())
|
||||
RunExtensionPerfTest(g_handler->GetBrowser());
|
||||
}
|
||||
|
||||
- (IBAction)testJSExecute:(id)sender {
|
||||
if(g_handler.get() && g_handler->GetBrowserHwnd())
|
||||
if (g_handler.get() && g_handler->GetBrowserHwnd())
|
||||
RunJavaScriptExecuteTest(g_handler->GetBrowser());
|
||||
}
|
||||
|
||||
- (IBAction)testJSInvoke:(id)sender {
|
||||
if(g_handler.get() && g_handler->GetBrowserHwnd())
|
||||
if (g_handler.get() && g_handler->GetBrowserHwnd())
|
||||
RunJavaScriptInvokeTest(g_handler->GetBrowser());
|
||||
}
|
||||
|
||||
- (IBAction)testRequest:(id)sender {
|
||||
if(g_handler.get() && g_handler->GetBrowserHwnd())
|
||||
if (g_handler.get() && g_handler->GetBrowserHwnd())
|
||||
RunRequestTest(g_handler->GetBrowser());
|
||||
}
|
||||
|
||||
- (IBAction)testLocalStorage:(id)sender {
|
||||
if(g_handler.get() && g_handler->GetBrowserHwnd())
|
||||
if (g_handler.get() && g_handler->GetBrowserHwnd())
|
||||
RunLocalStorageTest(g_handler->GetBrowser());
|
||||
}
|
||||
|
||||
- (IBAction)testXMLHttpRequest:(id)sender {
|
||||
if(g_handler.get() && g_handler->GetBrowserHwnd())
|
||||
if (g_handler.get() && g_handler->GetBrowserHwnd())
|
||||
RunXMLHTTPRequestTest(g_handler->GetBrowser());
|
||||
}
|
||||
|
||||
- (IBAction)testWebURLRequest:(id)sender {
|
||||
if(g_handler.get() && g_handler->GetBrowserHwnd())
|
||||
if (g_handler.get() && g_handler->GetBrowserHwnd())
|
||||
RunWebURLRequestTest(g_handler->GetBrowser());
|
||||
}
|
||||
|
||||
- (IBAction)testDOMAccess:(id)sender {
|
||||
if(g_handler.get() && g_handler->GetBrowserHwnd())
|
||||
if (g_handler.get() && g_handler->GetBrowserHwnd())
|
||||
RunDOMAccessTest(g_handler->GetBrowser());
|
||||
}
|
||||
|
||||
- (IBAction)testSchemeHandler:(id)sender {
|
||||
if(g_handler.get() && g_handler->GetBrowserHwnd())
|
||||
if (g_handler.get() && g_handler->GetBrowserHwnd())
|
||||
RunSchemeTest(g_handler->GetBrowser());
|
||||
}
|
||||
|
||||
- (IBAction)testPopupWindow:(id)sender {
|
||||
if(g_handler.get() && g_handler->GetBrowserHwnd())
|
||||
if (g_handler.get() && g_handler->GetBrowserHwnd())
|
||||
RunPopupTest(g_handler->GetBrowser());
|
||||
}
|
||||
|
||||
- (IBAction)testAccelerated2DCanvas:(id)sender {
|
||||
if(g_handler.get() && g_handler->GetBrowserHwnd())
|
||||
if (g_handler.get() && g_handler->GetBrowserHwnd())
|
||||
RunAccelerated2DCanvasTest(g_handler->GetBrowser());
|
||||
}
|
||||
|
||||
- (IBAction)testAcceleratedLayers:(id)sender {
|
||||
if(g_handler.get() && g_handler->GetBrowserHwnd())
|
||||
if (g_handler.get() && g_handler->GetBrowserHwnd())
|
||||
RunAcceleratedLayersTest(g_handler->GetBrowser());
|
||||
}
|
||||
|
||||
- (IBAction)testWebGL:(id)sender {
|
||||
if(g_handler.get() && g_handler->GetBrowserHwnd())
|
||||
if (g_handler.get() && g_handler->GetBrowserHwnd())
|
||||
RunWebGLTest(g_handler->GetBrowser());
|
||||
}
|
||||
|
||||
- (IBAction)testHTML5Video:(id)sender {
|
||||
if(g_handler.get() && g_handler->GetBrowserHwnd())
|
||||
if (g_handler.get() && g_handler->GetBrowserHwnd())
|
||||
RunHTML5VideoTest(g_handler->GetBrowser());
|
||||
}
|
||||
|
||||
- (IBAction)testDragDrop:(id)sender {
|
||||
if(g_handler.get() && g_handler->GetBrowserHwnd())
|
||||
if (g_handler.get() && g_handler->GetBrowserHwnd())
|
||||
RunDragDropTest(g_handler->GetBrowser());
|
||||
}
|
||||
|
||||
- (IBAction)testZoomIn:(id)sender {
|
||||
if(g_handler.get() && g_handler->GetBrowserHwnd()) {
|
||||
if (g_handler.get() && g_handler->GetBrowserHwnd()) {
|
||||
CefRefPtr<CefBrowser> browser = g_handler->GetBrowser();
|
||||
browser->SetZoomLevel(browser->GetZoomLevel() + 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
- (IBAction)testZoomOut:(id)sender {
|
||||
if(g_handler.get() && g_handler->GetBrowserHwnd()) {
|
||||
if (g_handler.get() && g_handler->GetBrowserHwnd()) {
|
||||
CefRefPtr<CefBrowser> browser = g_handler->GetBrowser();
|
||||
browser->SetZoomLevel(browser->GetZoomLevel() - 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
- (IBAction)testZoomReset:(id)sender {
|
||||
if(g_handler.get() && g_handler->GetBrowserHwnd()) {
|
||||
if (g_handler.get() && g_handler->GetBrowserHwnd()) {
|
||||
CefRefPtr<CefBrowser> browser = g_handler->GetBrowser();
|
||||
browser->SetZoomLevel(0.0);
|
||||
}
|
||||
}
|
||||
|
||||
- (IBAction)testDevToolsShow:(id)sender {
|
||||
if(g_handler.get() && g_handler->GetBrowserHwnd()) {
|
||||
if (g_handler.get() && g_handler->GetBrowserHwnd()) {
|
||||
CefRefPtr<CefBrowser> browser = g_handler->GetBrowser();
|
||||
browser->ShowDevTools();
|
||||
}
|
||||
}
|
||||
|
||||
- (IBAction)testDevToolsClose:(id)sender {
|
||||
if(g_handler.get() && g_handler->GetBrowserHwnd()) {
|
||||
if (g_handler.get() && g_handler->GetBrowserHwnd()) {
|
||||
CefRefPtr<CefBrowser> browser = g_handler->GetBrowser();
|
||||
browser->CloseDevTools();
|
||||
}
|
||||
}
|
||||
|
||||
- (IBAction)testPluginInfo:(id)sender {
|
||||
if(g_handler.get() && g_handler->GetBrowserHwnd())
|
||||
if (g_handler.get() && g_handler->GetBrowserHwnd())
|
||||
RunPluginInfoTest(g_handler->GetBrowser());
|
||||
}
|
||||
|
||||
- (IBAction)testOffscreenRendering:(id)sender {
|
||||
osrtest::RunTest(false);
|
||||
}
|
||||
|
||||
- (IBAction)testTransparentOffscreenRendering:(id)sender {
|
||||
osrtest::RunTest(true);
|
||||
}
|
||||
|
||||
// Sent by the default notification center immediately before the application
|
||||
// terminates.
|
||||
- (void)applicationWillTerminate:(NSNotification *)aNotification {
|
||||
@@ -544,8 +561,7 @@ NSButton* MakeButton(NSRect* rect, NSString* title, NSView* parent) {
|
||||
@end
|
||||
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
int main(int argc, char* argv[]) {
|
||||
// Retrieve the current working directory.
|
||||
getcwd(szWorkingDir, sizeof(szWorkingDir));
|
||||
|
||||
@@ -586,7 +602,6 @@ int main(int argc, char* argv[])
|
||||
|
||||
// Global functions
|
||||
|
||||
std::string AppGetWorkingDirectory()
|
||||
{
|
||||
std::string AppGetWorkingDirectory() {
|
||||
return szWorkingDir;
|
||||
}
|
||||
|
410
tests/cefclient/osrenderer.cpp
Normal file
410
tests/cefclient/osrenderer.cpp
Normal file
@@ -0,0 +1,410 @@
|
||||
// Copyright (c) 2012 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 "osrenderer.h"
|
||||
#include "util.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include <gl/gl.h>
|
||||
#include <gl/glu.h>
|
||||
#elif defined(OS_MACOSX)
|
||||
#include <OpenGL/gl.h>
|
||||
#else
|
||||
#error Platform is not supported.
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
// Convert from BGRA to RGBA format and from upper-left to lower-left origin.
|
||||
void ConvertToRGBA(const unsigned char* src, unsigned char* dst,
|
||||
int width, int height) {
|
||||
int sp = 0, dp = (height-1) * width * 4;
|
||||
for (int i = 0; i < height; i++) {
|
||||
for (int j = 0; j < width; j++, dp += 4, sp += 4) {
|
||||
dst[dp] = src[sp+2]; // R
|
||||
dst[dp+1] = src[sp+1]; // G
|
||||
dst[dp+2] = src[sp]; // B
|
||||
dst[dp+3] = src[sp+3]; // A
|
||||
}
|
||||
dp -= width * 8;
|
||||
}
|
||||
}
|
||||
|
||||
void ConvertToRGBARect(const CefRect& clipRect,
|
||||
const unsigned char* src, unsigned char* dst,
|
||||
int width, int height) {
|
||||
int sp = 0, dp = (height-1) * width * 4;
|
||||
for (int i = 0; i < height; i++) {
|
||||
for (int j = 0; j < width; j++, dp += 4, sp += 4) {
|
||||
if ((clipRect.x <= j) && (clipRect.x + clipRect.width > j) &&
|
||||
(clipRect.y <= i) && (clipRect.y + clipRect.height > i)) {
|
||||
dst[dp] = src[sp+2]; // R
|
||||
dst[dp+1] = src[sp+1]; // G
|
||||
dst[dp+2] = src[sp]; // B
|
||||
dst[dp+3] = src[sp+3]; // A
|
||||
}
|
||||
}
|
||||
dp -= width * 8;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert from BGRA to RGB format and from upper-left to lower-left origin.
|
||||
void ConvertToRGB(const unsigned char* src, unsigned char* dst,
|
||||
int width, int height) {
|
||||
int sp = 0, dp = (height-1) * width * 3;
|
||||
for (int i = 0; i < height; i++) {
|
||||
for (int j = 0; j < width; j++, dp += 3, sp += 4) {
|
||||
dst[dp] = src[sp+2]; // R
|
||||
dst[dp+1] = src[sp+1]; // G
|
||||
dst[dp+2] = src[sp]; // B
|
||||
}
|
||||
dp -= width * 6;
|
||||
}
|
||||
}
|
||||
|
||||
void ConvertToRGBRect(const CefRect& clipRect,
|
||||
const unsigned char* src, unsigned char* dst,
|
||||
int width, int height) {
|
||||
int sp = 0, dp = (height-1) * width * 3;
|
||||
for (int i = 0; i < height; i++) {
|
||||
for (int j = 0; j < width; j++, dp += 3, sp += 4) {
|
||||
if ((clipRect.x <= j) && (clipRect.x + clipRect.width > j) &&
|
||||
(clipRect.y <= i) && (clipRect.y + clipRect.height > i)) {
|
||||
dst[dp] = src[sp+2]; // R
|
||||
dst[dp+1] = src[sp+1]; // G
|
||||
dst[dp+2] = src[sp]; // B
|
||||
}
|
||||
}
|
||||
dp -= width * 6;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
ClientOSRenderer::ClientOSRenderer(bool transparent)
|
||||
: transparent_(transparent),
|
||||
initialized_(false),
|
||||
texture_id_(0),
|
||||
view_buffer_(NULL),
|
||||
view_buffer_size_(0),
|
||||
popup_buffer_(NULL),
|
||||
popup_buffer_size_(0),
|
||||
view_width_(0),
|
||||
view_height_(0),
|
||||
spin_x_(0),
|
||||
spin_y_(0) {
|
||||
}
|
||||
|
||||
ClientOSRenderer::~ClientOSRenderer() {
|
||||
Cleanup();
|
||||
}
|
||||
|
||||
void ClientOSRenderer::Initialize() {
|
||||
if (initialized_)
|
||||
return;
|
||||
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
|
||||
// Necessary for non-power-of-2 textures to render correctly.
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
|
||||
if (transparent_) {
|
||||
// Alpha blending style.
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
||||
initialized_ = true;
|
||||
}
|
||||
|
||||
void ClientOSRenderer::Cleanup() {
|
||||
if (view_buffer_) {
|
||||
delete [] view_buffer_;
|
||||
view_buffer_ = NULL;
|
||||
view_buffer_size_ = 0;
|
||||
}
|
||||
if (popup_buffer_) {
|
||||
delete [] popup_buffer_;
|
||||
popup_buffer_ = NULL;
|
||||
popup_buffer_size_ = 0;
|
||||
}
|
||||
|
||||
if (texture_id_ != 0)
|
||||
glDeleteTextures(1, &texture_id_);
|
||||
}
|
||||
|
||||
void ClientOSRenderer::SetSize(int width, int height) {
|
||||
if (!initialized_)
|
||||
Initialize();
|
||||
|
||||
// Match GL units to screen coordinates.
|
||||
glViewport(0, 0, width, height);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glOrtho(0, 0, width, height, 0.1, 100.0);
|
||||
|
||||
if (transparent_) {
|
||||
// Enable alpha blending.
|
||||
glEnable(GL_BLEND);
|
||||
}
|
||||
|
||||
// Enable 2D textures.
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
GLuint new_texture_id = 0;
|
||||
|
||||
// Create a new texture.
|
||||
glGenTextures(1, &new_texture_id);
|
||||
ASSERT(new_texture_id != 0);
|
||||
glBindTexture(GL_TEXTURE_2D, new_texture_id);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
// Start with all white contents.
|
||||
{
|
||||
int size = width * height * (transparent_?4:3);
|
||||
unsigned char* buffer = new unsigned char[size];
|
||||
memset(buffer, 255, size);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
|
||||
transparent_?GL_RGBA:GL_RGB, GL_UNSIGNED_BYTE, buffer);
|
||||
|
||||
delete [] buffer;
|
||||
}
|
||||
|
||||
if (texture_id_ != 0) {
|
||||
// Draw the existing view buffer to the new texture.
|
||||
DrawViewBuffer(width, height);
|
||||
|
||||
// Delete the old texture.
|
||||
glDeleteTextures(1, &texture_id_);
|
||||
}
|
||||
|
||||
texture_id_ = new_texture_id;
|
||||
|
||||
// Disable 2D textures.
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
if (transparent_) {
|
||||
// Disable alpha blending.
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
}
|
||||
|
||||
void ClientOSRenderer::Render() {
|
||||
ASSERT(initialized_);
|
||||
|
||||
struct {
|
||||
float tu, tv;
|
||||
float x, y, z;
|
||||
} static vertices[] = {
|
||||
{0.0f, 0.0f, -1.0f, -1.0f, 0.0f},
|
||||
{1.0f, 0.0f, 1.0f, -1.0f, 0.0f},
|
||||
{1.0f, 1.0f, 1.0f, 1.0f, 0.0f},
|
||||
{0.0f, 1.0f, -1.0f, 1.0f, 0.0f}
|
||||
};
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
// Draw the background gradient.
|
||||
glPushAttrib(GL_ALL_ATTRIB_BITS);
|
||||
glBegin(GL_QUADS);
|
||||
glColor4f(1.0, 0.0, 0.0, 1.0); // red
|
||||
glVertex2f(-1.0, -1.0);
|
||||
glVertex2f(1.0, -1.0);
|
||||
glColor4f(0.0, 0.0, 1.0, 1.0); // blue
|
||||
glVertex2f(1.0, 1.0);
|
||||
glVertex2f(-1.0, 1.0);
|
||||
glEnd();
|
||||
glPopAttrib();
|
||||
|
||||
// Rotate the view based on the mouse spin.
|
||||
glRotatef(-spin_x_, 1.0f, 0.0f, 0.0f);
|
||||
glRotatef(-spin_y_, 0.0f, 1.0f, 0.0f);
|
||||
|
||||
if (transparent_) {
|
||||
// Enable alpha blending.
|
||||
glEnable(GL_BLEND);
|
||||
}
|
||||
|
||||
// Enable 2D textures.
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
// Draw the facets with the texture.
|
||||
ASSERT(texture_id_ != 0);
|
||||
glBindTexture(GL_TEXTURE_2D, texture_id_);
|
||||
glInterleavedArrays(GL_T2F_V3F, 0, vertices);
|
||||
glDrawArrays(GL_QUADS, 0, 4);
|
||||
|
||||
// Disable 2D textures.
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
if (transparent_) {
|
||||
// Disable alpha blending.
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
glFlush();
|
||||
}
|
||||
|
||||
void ClientOSRenderer::OnPopupShow(CefRefPtr<CefBrowser> browser,
|
||||
bool show) {
|
||||
if (!show) {
|
||||
// Clear the popup buffer.
|
||||
popup_rect_.Set(0, 0, 0, 0);
|
||||
if (popup_buffer_) {
|
||||
delete [] popup_buffer_;
|
||||
popup_buffer_ = NULL;
|
||||
popup_buffer_size_ = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ClientOSRenderer::OnPopupSize(CefRefPtr<CefBrowser> browser,
|
||||
const CefRect& rect) {
|
||||
if (rect.width > 0) {
|
||||
// Update the popup rectange. It should always be inside the view.
|
||||
ASSERT(rect.x + rect.width < view_width_ &&
|
||||
rect.y + rect.height < view_height_);
|
||||
popup_rect_ = rect;
|
||||
}
|
||||
}
|
||||
|
||||
void ClientOSRenderer::OnPaint(CefRefPtr<CefBrowser> browser,
|
||||
CefRenderHandler::PaintElementType type,
|
||||
const CefRenderHandler::RectList& dirtyRects,
|
||||
const void* buffer) {
|
||||
ASSERT(initialized_);
|
||||
|
||||
// Retrieve the current size of the browser view.
|
||||
browser->GetSize(type, view_width_, view_height_);
|
||||
|
||||
if (transparent_) {
|
||||
// Enable alpha blending.
|
||||
glEnable(GL_BLEND);
|
||||
}
|
||||
|
||||
// Enable 2D textures.
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
ASSERT(texture_id_ != 0);
|
||||
glBindTexture(GL_TEXTURE_2D, texture_id_);
|
||||
|
||||
if (type == PET_VIEW) {
|
||||
SetBufferSize(view_width_, view_height_, true);
|
||||
|
||||
// Paint the view.
|
||||
if (transparent_) {
|
||||
CefRenderHandler::RectList::const_iterator i = dirtyRects.begin();
|
||||
for (; i != dirtyRects.end(); ++i) {
|
||||
ConvertToRGBARect(*i, (unsigned char*)buffer, view_buffer_,
|
||||
view_width_, view_height_);
|
||||
}
|
||||
} else {
|
||||
CefRenderHandler::RectList::const_iterator i = dirtyRects.begin();
|
||||
for (; i != dirtyRects.end(); ++i) {
|
||||
ConvertToRGBRect(*i, (unsigned char*)buffer, view_buffer_,
|
||||
view_width_, view_height_);
|
||||
}
|
||||
}
|
||||
|
||||
// Update the whole texture. This is done for simplicity instead of
|
||||
// updating just the dirty region.
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, view_width_, view_height_,
|
||||
transparent_?GL_RGBA:GL_RGB, GL_UNSIGNED_BYTE, view_buffer_);
|
||||
}
|
||||
|
||||
if (popup_rect_.width > 0) {
|
||||
if (type == PET_POPUP) {
|
||||
// Paint the popup.
|
||||
if (transparent_)
|
||||
SetRGBA(buffer, popup_rect_.width, popup_rect_.height, false);
|
||||
else
|
||||
SetRGB(buffer, popup_rect_.width, popup_rect_.height, false);
|
||||
}
|
||||
|
||||
if (popup_buffer_) {
|
||||
// Update the popup region.
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, popup_rect_.x,
|
||||
view_height_ - popup_rect_.y - popup_rect_.height,
|
||||
popup_rect_.width, popup_rect_.height,
|
||||
transparent_?GL_RGBA:GL_RGB,
|
||||
GL_UNSIGNED_BYTE, popup_buffer_);
|
||||
}
|
||||
}
|
||||
|
||||
// Disable 2D textures.
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
if (transparent_) {
|
||||
// Disable alpha blending.
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
}
|
||||
|
||||
void ClientOSRenderer::SetSpin(float spinX, float spinY) {
|
||||
spin_x_ = spinX;
|
||||
spin_y_ = spinY;
|
||||
}
|
||||
|
||||
void ClientOSRenderer::IncrementSpin(float spinDX, float spinDY) {
|
||||
spin_x_ -= spinDX;
|
||||
spin_y_ -= spinDY;
|
||||
}
|
||||
|
||||
void ClientOSRenderer::SetBufferSize(int width, int height, bool view) {
|
||||
int dst_size = width * height * (transparent_?4:3);
|
||||
|
||||
// Allocate a new buffer if necesary.
|
||||
if (view) {
|
||||
if (dst_size > view_buffer_size_) {
|
||||
if (view_buffer_)
|
||||
delete [] view_buffer_;
|
||||
view_buffer_ = new unsigned char[dst_size];
|
||||
view_buffer_size_ = dst_size;
|
||||
}
|
||||
} else {
|
||||
if (dst_size > popup_buffer_size_) {
|
||||
if (popup_buffer_)
|
||||
delete [] popup_buffer_;
|
||||
popup_buffer_ = new unsigned char[dst_size];
|
||||
popup_buffer_size_ = dst_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set the contents of the RGBA buffer.
|
||||
void ClientOSRenderer::SetRGBA(const void* src, int width, int height,
|
||||
bool view) {
|
||||
SetBufferSize(width, height, view);
|
||||
ConvertToRGBA((unsigned char*)src, view?view_buffer_:popup_buffer_, width,
|
||||
height);
|
||||
}
|
||||
|
||||
// Set the contents of the RGB buffer.
|
||||
void ClientOSRenderer::SetRGB(const void* src, int width, int height,
|
||||
bool view) {
|
||||
SetBufferSize(width, height, view);
|
||||
ConvertToRGB((unsigned char*)src, view?view_buffer_:popup_buffer_, width,
|
||||
height);
|
||||
}
|
||||
|
||||
void ClientOSRenderer::DrawViewBuffer(int max_width, int max_height) {
|
||||
if (max_width < view_width_ || max_height < view_height_) {
|
||||
// The requested max size is smaller than the current view buffer.
|
||||
int width = std::min(max_width, view_width_);
|
||||
int height = std::min(max_height, view_height_);
|
||||
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, view_width_);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height,
|
||||
transparent_?GL_RGBA:GL_RGB, GL_UNSIGNED_BYTE,
|
||||
view_buffer_);
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
} else {
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, view_width_, view_height_,
|
||||
transparent_?GL_RGBA:GL_RGB, GL_UNSIGNED_BYTE, view_buffer_);
|
||||
}
|
||||
}
|
63
tests/cefclient/osrenderer.h
Normal file
63
tests/cefclient/osrenderer.h
Normal file
@@ -0,0 +1,63 @@
|
||||
// Copyright (c) 2012 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.
|
||||
|
||||
#ifndef CEF_TESTS_CEFCLIENT_OSRENDERER_H_
|
||||
#define CEF_TESTS_CEFCLIENT_OSRENDERER_H_
|
||||
|
||||
#include "include/cef.h"
|
||||
|
||||
class ClientOSRenderer {
|
||||
public:
|
||||
// The context must outlive this object.
|
||||
explicit ClientOSRenderer(bool transparent);
|
||||
virtual ~ClientOSRenderer();
|
||||
|
||||
// Initialize the OpenGL environment.
|
||||
void Initialize();
|
||||
|
||||
// Clean up the OpenGL environment.
|
||||
void Cleanup();
|
||||
|
||||
// Set the size of the viewport.
|
||||
void SetSize(int width, int height);
|
||||
|
||||
// Render to the screen.
|
||||
void Render();
|
||||
|
||||
// Forwarded from CefRenderHandler callbacks.
|
||||
void OnPopupShow(CefRefPtr<CefBrowser> browser,
|
||||
bool show);
|
||||
void OnPopupSize(CefRefPtr<CefBrowser> browser,
|
||||
const CefRect& rect);
|
||||
void OnPaint(CefRefPtr<CefBrowser> browser,
|
||||
CefRenderHandler::PaintElementType type,
|
||||
const CefRenderHandler::RectList& dirtyRects,
|
||||
const void* buffer);
|
||||
|
||||
// Apply spin.
|
||||
void SetSpin(float spinX, float spinY);
|
||||
void IncrementSpin(float spinDX, float spinDY);
|
||||
|
||||
private:
|
||||
void SetBufferSize(int width, int height, bool view);
|
||||
void SetRGBA(const void* src, int width, int height, bool view);
|
||||
void SetRGB(const void* src, int width, int height, bool view);
|
||||
void DrawViewBuffer(int max_width, int max_height);
|
||||
|
||||
bool transparent_;
|
||||
bool initialized_;
|
||||
unsigned int texture_id_;
|
||||
unsigned char* view_buffer_;
|
||||
int view_buffer_size_;
|
||||
unsigned char* popup_buffer_;
|
||||
int popup_buffer_size_;
|
||||
CefRect popup_rect_;
|
||||
int view_width_;
|
||||
int view_height_;
|
||||
float spin_x_;
|
||||
float spin_y_;
|
||||
};
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_OSR_RENDERER_H_
|
||||
|
@@ -3,50 +3,47 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "osrplugin.h"
|
||||
#include "osrenderer.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
|
||||
#include <windows.h>
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <math.h>
|
||||
#include <gl/gl.h>
|
||||
#include <gl/glu.h>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include "include/cef.h"
|
||||
#include "cefclient.h"
|
||||
#include "client_popup_handler.h"
|
||||
#include "osrplugin.h"
|
||||
#include "resource.h"
|
||||
#include "resource_util.h"
|
||||
#include "string_util.h"
|
||||
#include "util.h"
|
||||
#include <gl/gl.h>
|
||||
#include <gl/glu.h>
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <math.h>
|
||||
#include <sstream>
|
||||
|
||||
#if defined(OS_WIN)
|
||||
|
||||
// Initialized in NP_Initialize.
|
||||
NPNetscapeFuncs* g_osrbrowser = NULL;
|
||||
|
||||
namespace {
|
||||
|
||||
GLuint g_textureID = -1;
|
||||
float g_spinX = 0.0f;
|
||||
float g_spinY = 0.0f;
|
||||
int g_width = -1, g_height = -1;
|
||||
CefRefPtr<CefBrowser> g_offscreenBrowser;
|
||||
|
||||
// If set to true alpha transparency will be used.
|
||||
bool g_offscreenTransparent = false;
|
||||
|
||||
#define GL_IMAGE_FORMAT (g_offscreenTransparent?GL_RGBA:GL_RGB)
|
||||
#define GL_BYTE_COUNT (g_offscreenTransparent?4:3)
|
||||
|
||||
// Class holding pointers for the client plugin window.
|
||||
class ClientPlugin
|
||||
{
|
||||
public:
|
||||
ClientPlugin()
|
||||
{
|
||||
hWnd = NULL;
|
||||
hDC = NULL;
|
||||
hRC = NULL;
|
||||
class ClientPlugin {
|
||||
public:
|
||||
ClientPlugin(bool transparent)
|
||||
: renderer(transparent),
|
||||
hWnd(NULL),
|
||||
hDC(NULL),
|
||||
hRC(NULL) {
|
||||
}
|
||||
|
||||
ClientOSRenderer renderer;
|
||||
HWND hWnd;
|
||||
HDC hDC;
|
||||
HGLRC hRC;
|
||||
@@ -58,36 +55,30 @@ class ClientOSRHandler : public CefClient,
|
||||
public CefLoadHandler,
|
||||
public CefRequestHandler,
|
||||
public CefDisplayHandler,
|
||||
public CefRenderHandler
|
||||
{
|
||||
public:
|
||||
ClientOSRHandler(ClientPlugin* plugin)
|
||||
: plugin_(plugin),
|
||||
view_buffer_(NULL),
|
||||
view_buffer_size_(0),
|
||||
popup_buffer_(NULL),
|
||||
popup_buffer_size_(0)
|
||||
{
|
||||
public CefRenderHandler {
|
||||
public:
|
||||
explicit ClientOSRHandler(ClientPlugin* plugin)
|
||||
: plugin_(plugin) {
|
||||
}
|
||||
~ClientOSRHandler()
|
||||
{
|
||||
if (view_buffer_)
|
||||
delete [] view_buffer_;
|
||||
if (popup_buffer_)
|
||||
delete [] popup_buffer_;
|
||||
~ClientOSRHandler() {
|
||||
}
|
||||
|
||||
// CefClient methods
|
||||
virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() OVERRIDE
|
||||
{ return this; }
|
||||
virtual CefRefPtr<CefLoadHandler> GetLoadHandler() OVERRIDE
|
||||
{ return this; }
|
||||
virtual CefRefPtr<CefRequestHandler> GetRequestHandler() OVERRIDE
|
||||
{ return this; }
|
||||
virtual CefRefPtr<CefDisplayHandler> GetDisplayHandler() OVERRIDE
|
||||
{ return this; }
|
||||
virtual CefRefPtr<CefRenderHandler> GetRenderHandler() OVERRIDE
|
||||
{ return this; }
|
||||
virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() OVERRIDE {
|
||||
return this;
|
||||
}
|
||||
virtual CefRefPtr<CefLoadHandler> GetLoadHandler() OVERRIDE {
|
||||
return this;
|
||||
}
|
||||
virtual CefRefPtr<CefRequestHandler> GetRequestHandler() OVERRIDE {
|
||||
return this;
|
||||
}
|
||||
virtual CefRefPtr<CefDisplayHandler> GetDisplayHandler() OVERRIDE {
|
||||
return this;
|
||||
}
|
||||
virtual CefRefPtr<CefRenderHandler> GetRenderHandler() OVERRIDE {
|
||||
return this;
|
||||
}
|
||||
|
||||
// CefLifeSpanHandler methods
|
||||
|
||||
@@ -96,8 +87,7 @@ public:
|
||||
CefWindowInfo& windowInfo,
|
||||
const CefString& url,
|
||||
CefRefPtr<CefClient>& client,
|
||||
CefBrowserSettings& settings) OVERRIDE
|
||||
{
|
||||
CefBrowserSettings& settings) OVERRIDE {
|
||||
REQUIRE_UI_THREAD();
|
||||
|
||||
windowInfo.m_bWindowRenderingDisabled = TRUE;
|
||||
@@ -105,29 +95,28 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void OnAfterCreated(CefRefPtr<CefBrowser> browser) OVERRIDE
|
||||
{
|
||||
virtual void OnAfterCreated(CefRefPtr<CefBrowser> browser) OVERRIDE {
|
||||
REQUIRE_UI_THREAD();
|
||||
|
||||
// Set the view size to match the plugin window size.
|
||||
browser->SetSize(PET_VIEW, g_width, g_height);
|
||||
|
||||
g_offscreenBrowser = browser;
|
||||
|
||||
// Set the off-screen browser size to match the plugin window size.
|
||||
RECT clientRect;
|
||||
::GetClientRect(plugin_->hWnd, &clientRect);
|
||||
g_offscreenBrowser->SetSize(PET_VIEW, clientRect.right, clientRect.bottom);
|
||||
}
|
||||
|
||||
virtual void OnBeforeClose(CefRefPtr<CefBrowser> browser) OVERRIDE
|
||||
{
|
||||
virtual void OnBeforeClose(CefRefPtr<CefBrowser> browser) OVERRIDE {
|
||||
g_offscreenBrowser = NULL;
|
||||
}
|
||||
|
||||
// CefLoadHandler methods
|
||||
|
||||
virtual void OnLoadStart(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame) OVERRIDE
|
||||
{
|
||||
CefRefPtr<CefFrame> frame) OVERRIDE {
|
||||
REQUIRE_UI_THREAD();
|
||||
|
||||
if(!browser->IsPopup() && frame->IsMain()) {
|
||||
if (!browser->IsPopup() && frame->IsMain()) {
|
||||
// We've just started loading a page
|
||||
SetLoading(true);
|
||||
}
|
||||
@@ -135,11 +124,10 @@ public:
|
||||
|
||||
virtual void OnLoadEnd(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
int httpStatusCode) OVERRIDE
|
||||
{
|
||||
int httpStatusCode) OVERRIDE {
|
||||
REQUIRE_UI_THREAD();
|
||||
|
||||
if(!browser->IsPopup() && frame->IsMain()) {
|
||||
if (!browser->IsPopup() && frame->IsMain()) {
|
||||
// We've just finished loading a page
|
||||
SetLoading(false);
|
||||
}
|
||||
@@ -152,12 +140,11 @@ public:
|
||||
CefString& redirectUrl,
|
||||
CefRefPtr<CefStreamReader>& resourceStream,
|
||||
CefRefPtr<CefResponse> response,
|
||||
int loadFlags) OVERRIDE
|
||||
{
|
||||
int loadFlags) OVERRIDE {
|
||||
REQUIRE_IO_THREAD();
|
||||
|
||||
std::string url = request->GetURL();
|
||||
if(url == "http://tests/transparency") {
|
||||
if (url == "http://tests/transparency") {
|
||||
resourceStream = GetBinaryResourceReader(IDS_TRANSPARENCY);
|
||||
response->SetMimeType("text/html");
|
||||
response->SetStatus(200);
|
||||
@@ -170,8 +157,7 @@ public:
|
||||
|
||||
virtual void OnNavStateChange(CefRefPtr<CefBrowser> browser,
|
||||
bool canGoBack,
|
||||
bool canGoForward) OVERRIDE
|
||||
{
|
||||
bool canGoForward) OVERRIDE {
|
||||
REQUIRE_UI_THREAD();
|
||||
|
||||
// Set the "back" and "forward" button state in the HTML.
|
||||
@@ -185,8 +171,7 @@ public:
|
||||
|
||||
virtual void OnAddressChange(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
const CefString& url) OVERRIDE
|
||||
{
|
||||
const CefString& url) OVERRIDE {
|
||||
REQUIRE_UI_THREAD();
|
||||
|
||||
// Set the "url" value in the HTML.
|
||||
@@ -198,8 +183,7 @@ public:
|
||||
}
|
||||
|
||||
virtual void OnTitleChange(CefRefPtr<CefBrowser> browser,
|
||||
const CefString& title) OVERRIDE
|
||||
{
|
||||
const CefString& title) OVERRIDE {
|
||||
REQUIRE_UI_THREAD();
|
||||
|
||||
// Set the "title" value in the HTML.
|
||||
@@ -214,21 +198,22 @@ public:
|
||||
// CefRenderHandler methods
|
||||
|
||||
virtual bool GetViewRect(CefRefPtr<CefBrowser> browser,
|
||||
CefRect& rect) OVERRIDE
|
||||
{
|
||||
CefRect& rect) OVERRIDE {
|
||||
REQUIRE_UI_THREAD();
|
||||
|
||||
// The simulated screen and view rectangle are the same. This is necessary
|
||||
// for popup menus to be located and sized inside the view.
|
||||
RECT clientRect;
|
||||
::GetClientRect(plugin_->hWnd, &clientRect);
|
||||
|
||||
rect.x = rect.y = 0;
|
||||
rect.width = g_width;
|
||||
rect.height = g_height;
|
||||
rect.width = clientRect.right;
|
||||
rect.height = clientRect.bottom;
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool GetScreenRect(CefRefPtr<CefBrowser> browser,
|
||||
CefRect& rect) OVERRIDE
|
||||
{
|
||||
CefRect& rect) OVERRIDE {
|
||||
return GetViewRect(browser, rect);
|
||||
}
|
||||
|
||||
@@ -236,8 +221,7 @@ public:
|
||||
int viewX,
|
||||
int viewY,
|
||||
int& screenX,
|
||||
int& screenY) OVERRIDE
|
||||
{
|
||||
int& screenY) OVERRIDE {
|
||||
REQUIRE_UI_THREAD();
|
||||
|
||||
// Convert the point from view coordinates to actual screen coordinates.
|
||||
@@ -249,107 +233,29 @@ public:
|
||||
}
|
||||
|
||||
virtual void OnPopupShow(CefRefPtr<CefBrowser> browser,
|
||||
bool show) OVERRIDE
|
||||
{
|
||||
bool show) OVERRIDE {
|
||||
REQUIRE_UI_THREAD();
|
||||
|
||||
if(!show) {
|
||||
// Clear the popup buffer.
|
||||
popup_rect_.Set(0,0,0,0);
|
||||
if (popup_buffer_) {
|
||||
delete [] popup_buffer_;
|
||||
popup_buffer_ = NULL;
|
||||
popup_buffer_size_ = 0;
|
||||
}
|
||||
}
|
||||
plugin_->renderer.OnPopupShow(browser, show);
|
||||
}
|
||||
|
||||
virtual void OnPopupSize(CefRefPtr<CefBrowser> browser,
|
||||
const CefRect& rect) OVERRIDE
|
||||
{
|
||||
const CefRect& rect) OVERRIDE {
|
||||
REQUIRE_UI_THREAD();
|
||||
|
||||
if (rect.width > 0) {
|
||||
// Update the popup rectange. It will always be inside the view due to
|
||||
// HandleGetRect().
|
||||
ASSERT(rect.x + rect.width < g_width &&
|
||||
rect.y + rect.height < g_height);
|
||||
popup_rect_ = rect;
|
||||
}
|
||||
plugin_->renderer.OnPopupSize(browser, rect);
|
||||
}
|
||||
|
||||
virtual void OnPaint(CefRefPtr<CefBrowser> browser,
|
||||
PaintElementType type,
|
||||
const RectList& dirtyRects,
|
||||
const void* buffer) OVERRIDE
|
||||
{
|
||||
const void* buffer) OVERRIDE {
|
||||
REQUIRE_UI_THREAD();
|
||||
|
||||
wglMakeCurrent(plugin_->hDC, plugin_->hRC);
|
||||
|
||||
if (g_offscreenTransparent) {
|
||||
// Enable alpha blending.
|
||||
glEnable(GL_BLEND);
|
||||
}
|
||||
|
||||
// Enable 2D textures.
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, g_textureID);
|
||||
|
||||
if (type == PET_VIEW) {
|
||||
SetBufferSize(g_width, g_height, true);
|
||||
// Paint the view.
|
||||
if (g_offscreenTransparent) {
|
||||
RectList::const_iterator i = dirtyRects.begin();
|
||||
for (; i != dirtyRects.end(); ++i) {
|
||||
ConvertToRGBARect(*i, (unsigned char*)buffer, view_buffer_, g_width,
|
||||
g_height);
|
||||
}
|
||||
} else {
|
||||
RectList::const_iterator i = dirtyRects.begin();
|
||||
for (i; i != dirtyRects.end(); ++i) {
|
||||
ConvertToRGBRect(*i, (unsigned char*)buffer, view_buffer_, g_width,
|
||||
g_height);
|
||||
}
|
||||
}
|
||||
|
||||
// Update the whole texture. This is done for simplicity instead of
|
||||
// updating just the dirty region.
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, g_width, g_height,
|
||||
GL_IMAGE_FORMAT, GL_UNSIGNED_BYTE, view_buffer_);
|
||||
}
|
||||
|
||||
if(popup_rect_.width > 0) {
|
||||
if (type == PET_POPUP) {
|
||||
// Paint the popup.
|
||||
if (g_offscreenTransparent)
|
||||
SetRGBA(buffer, popup_rect_.width, popup_rect_.height, false);
|
||||
else
|
||||
SetRGB(buffer, popup_rect_.width, popup_rect_.height, false);
|
||||
}
|
||||
|
||||
if (popup_buffer_) {
|
||||
// Update the popup region.
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, popup_rect_.x,
|
||||
g_height-popup_rect_.y-popup_rect_.height, popup_rect_.width,
|
||||
popup_rect_.height, GL_IMAGE_FORMAT, GL_UNSIGNED_BYTE,
|
||||
popup_buffer_);
|
||||
}
|
||||
}
|
||||
|
||||
// Disable 2D textures.
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
if (g_offscreenTransparent) {
|
||||
// Disable alpha blending.
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
plugin_->renderer.OnPaint(browser, type, dirtyRects, buffer);
|
||||
}
|
||||
|
||||
virtual void OnCursorChange(CefRefPtr<CefBrowser> browser,
|
||||
CefCursorHandle cursor) OVERRIDE
|
||||
{
|
||||
CefCursorHandle cursor) OVERRIDE {
|
||||
REQUIRE_UI_THREAD();
|
||||
|
||||
// Change the plugin window's cursor.
|
||||
@@ -358,9 +264,8 @@ public:
|
||||
SetCursor(cursor);
|
||||
}
|
||||
|
||||
private:
|
||||
void SetLoading(bool isLoading)
|
||||
{
|
||||
private:
|
||||
void SetLoading(bool isLoading) {
|
||||
// Set the "stop" and "reload" button state in the HTML.
|
||||
std::stringstream ss;
|
||||
ss << "document.getElementById('stop').disabled = "
|
||||
@@ -370,119 +275,7 @@ private:
|
||||
AppGetBrowser()->GetMainFrame()->ExecuteJavaScript(ss.str(), "", 0);
|
||||
}
|
||||
|
||||
// Size the RGB buffer.
|
||||
void SetBufferSize(int width, int height, bool view)
|
||||
{
|
||||
int dst_size = width * height * GL_BYTE_COUNT;
|
||||
|
||||
// Allocate a new buffer if necesary.
|
||||
if (view) {
|
||||
if (dst_size > view_buffer_size_) {
|
||||
if (view_buffer_)
|
||||
delete [] view_buffer_;
|
||||
view_buffer_ = new unsigned char[dst_size];
|
||||
view_buffer_size_ = dst_size;
|
||||
}
|
||||
} else {
|
||||
if (dst_size > popup_buffer_size_) {
|
||||
if (popup_buffer_)
|
||||
delete [] popup_buffer_;
|
||||
popup_buffer_ = new unsigned char[dst_size];
|
||||
popup_buffer_size_ = dst_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set the contents of the RGBA buffer.
|
||||
void SetRGBA(const void* src, int width, int height, bool view)
|
||||
{
|
||||
SetBufferSize(width, height, view);
|
||||
ConvertToRGBA((unsigned char*)src, view?view_buffer_:popup_buffer_, width,
|
||||
height);
|
||||
}
|
||||
|
||||
// Convert from BGRA to RGBA format and from upper-left to lower-left origin.
|
||||
static void ConvertToRGBA(const unsigned char* src, unsigned char* dst,
|
||||
int width, int height)
|
||||
{
|
||||
int sp = 0, dp = (height-1) * width * 4;
|
||||
for(int i = 0; i < height; i++) {
|
||||
for(int j = 0; j < width; j++, dp += 4, sp += 4) {
|
||||
dst[dp] = src[sp+2]; // R
|
||||
dst[dp+1] = src[sp+1]; // G
|
||||
dst[dp+2] = src[sp]; // B
|
||||
dst[dp+3] = src[sp+3]; // A
|
||||
}
|
||||
dp -= width * 8;
|
||||
}
|
||||
}
|
||||
|
||||
static void ConvertToRGBARect(const CefRect& clipRect,
|
||||
const unsigned char* src, unsigned char* dst,
|
||||
int width, int height)
|
||||
{
|
||||
int sp = 0, dp = (height-1) * width * 4;
|
||||
for (int i = 0; i < height; i++) {
|
||||
for (int j = 0; j < width; j++, dp += 4, sp += 4) {
|
||||
if ((clipRect.x <= j) && (clipRect.x + clipRect.width > j) &&
|
||||
(clipRect.y <= i) && (clipRect.y + clipRect.height > i)) {
|
||||
dst[dp] = src[sp+2]; // R
|
||||
dst[dp+1] = src[sp+1]; // G
|
||||
dst[dp+2] = src[sp]; // B
|
||||
dst[dp+3] = src[sp+3]; // A
|
||||
}
|
||||
}
|
||||
dp -= width * 8;
|
||||
}
|
||||
}
|
||||
|
||||
// Set the contents of the RGB buffer.
|
||||
void SetRGB(const void* src, int width, int height, bool view)
|
||||
{
|
||||
SetBufferSize(width, height, view);
|
||||
ConvertToRGB((unsigned char*)src, view?view_buffer_:popup_buffer_, width,
|
||||
height);
|
||||
}
|
||||
|
||||
// Convert from BGRA to RGB format and from upper-left to lower-left origin.
|
||||
static void ConvertToRGB(const unsigned char* src, unsigned char* dst,
|
||||
int width, int height)
|
||||
{
|
||||
int sp = 0, dp = (height-1) * width * 3;
|
||||
for(int i = 0; i < height; i++) {
|
||||
for(int j = 0; j < width; j++, dp += 3, sp += 4) {
|
||||
dst[dp] = src[sp+2]; // R
|
||||
dst[dp+1] = src[sp+1]; // G
|
||||
dst[dp+2] = src[sp]; // B
|
||||
}
|
||||
dp -= width * 6;
|
||||
}
|
||||
}
|
||||
|
||||
static void ConvertToRGBRect(const CefRect& clipRect,
|
||||
const unsigned char* src, unsigned char* dst,
|
||||
int width, int height)
|
||||
{
|
||||
int sp = 0, dp = (height-1) * width * 3;
|
||||
for (int i = 0; i < height; i++) {
|
||||
for (int j = 0; j < width; j++, dp += 3, sp += 4) {
|
||||
if ((clipRect.x <= j) && (clipRect.x + clipRect.width > j) &&
|
||||
(clipRect.y <= i) && (clipRect.y + clipRect.height > i)) {
|
||||
dst[dp] = src[sp+2]; // R
|
||||
dst[dp+1] = src[sp+1]; // G
|
||||
dst[dp+2] = src[sp]; // B
|
||||
}
|
||||
}
|
||||
dp -= width * 6;
|
||||
}
|
||||
}
|
||||
|
||||
ClientPlugin* plugin_;
|
||||
unsigned char* view_buffer_;
|
||||
int view_buffer_size_;
|
||||
unsigned char* popup_buffer_;
|
||||
int popup_buffer_size_;
|
||||
CefRect popup_rect_;
|
||||
|
||||
// Include the default reference counting implementation.
|
||||
IMPLEMENT_REFCOUNTING(ClientOSRPlugin);
|
||||
@@ -493,14 +286,13 @@ LRESULT CALLBACK PluginWndProc(HWND hWnd, UINT message, WPARAM wParam,
|
||||
LPARAM lParam);
|
||||
|
||||
// Enable GL.
|
||||
void EnableGL(HWND hWnd, HDC * hDC, HGLRC * hRC)
|
||||
{
|
||||
void EnableGL(ClientPlugin* plugin) {
|
||||
PIXELFORMATDESCRIPTOR pfd;
|
||||
int format;
|
||||
|
||||
|
||||
// Get the device context.
|
||||
*hDC = GetDC(hWnd);
|
||||
|
||||
plugin->hDC = GetDC(plugin->hWnd);
|
||||
|
||||
// Set the pixel format for the DC.
|
||||
ZeroMemory(&pfd, sizeof(pfd));
|
||||
pfd.nSize = sizeof(pfd);
|
||||
@@ -510,147 +302,40 @@ void EnableGL(HWND hWnd, HDC * hDC, HGLRC * hRC)
|
||||
pfd.cColorBits = 24;
|
||||
pfd.cDepthBits = 16;
|
||||
pfd.iLayerType = PFD_MAIN_PLANE;
|
||||
format = ChoosePixelFormat(*hDC, &pfd);
|
||||
SetPixelFormat(*hDC, format, &pfd);
|
||||
|
||||
format = ChoosePixelFormat(plugin->hDC, &pfd);
|
||||
SetPixelFormat(plugin->hDC, format, &pfd);
|
||||
|
||||
// Create and enable the render context.
|
||||
*hRC = wglCreateContext(*hDC);
|
||||
wglMakeCurrent(*hDC, *hRC);
|
||||
plugin->hRC = wglCreateContext(plugin->hDC);
|
||||
wglMakeCurrent(plugin->hDC, plugin->hRC);
|
||||
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
|
||||
// Necessary for non-power-of-2 textures to render correctly.
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
|
||||
if (g_offscreenTransparent) {
|
||||
// Alpha blending style.
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
plugin->renderer.Initialize();
|
||||
}
|
||||
|
||||
// Disable GL.
|
||||
void DisableGL(HWND hWnd, HDC hDC, HGLRC hRC)
|
||||
{
|
||||
// Delete the texture.
|
||||
if(g_textureID != -1)
|
||||
glDeleteTextures(1, &g_textureID);
|
||||
|
||||
void DisableGL(ClientPlugin* plugin) {
|
||||
plugin->renderer.Cleanup();
|
||||
|
||||
wglMakeCurrent(NULL, NULL);
|
||||
wglDeleteContext(hRC);
|
||||
ReleaseDC(hWnd, hDC);
|
||||
wglDeleteContext(plugin->hRC);
|
||||
ReleaseDC(plugin->hWnd, plugin->hDC);
|
||||
}
|
||||
|
||||
// Size the GL view.
|
||||
void SizeGL(ClientPlugin* plugin, int width, int height)
|
||||
{
|
||||
g_width = width;
|
||||
g_height = height;
|
||||
|
||||
void SizeGL(ClientPlugin* plugin, int width, int height) {
|
||||
wglMakeCurrent(plugin->hDC, plugin->hRC);
|
||||
|
||||
// Match GL units to screen coordinates.
|
||||
glViewport(0, 0, width, height);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glOrtho(0, 0, width, height, 0.1, 100.0);
|
||||
plugin->renderer.SetSize(width, height);
|
||||
|
||||
if (g_offscreenTransparent) {
|
||||
// Enable alpha blending.
|
||||
glEnable(GL_BLEND);
|
||||
}
|
||||
|
||||
// Enable 2D textures.
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
// Delete the existing exture.
|
||||
if(g_textureID != -1)
|
||||
glDeleteTextures(1, &g_textureID);
|
||||
|
||||
// Create a new texture.
|
||||
glGenTextures(1, &g_textureID);
|
||||
glBindTexture(GL_TEXTURE_2D, g_textureID);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
// Start with all white contents.
|
||||
int size = width * height * GL_BYTE_COUNT;
|
||||
unsigned char* buffer = new unsigned char[size];
|
||||
memset(buffer, 255, size);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
|
||||
GL_IMAGE_FORMAT, GL_UNSIGNED_BYTE, buffer);
|
||||
|
||||
// Disable 2D textures.
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
if (g_offscreenTransparent) {
|
||||
// Disable alpha blending.
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
delete [] buffer;
|
||||
|
||||
if(g_offscreenBrowser.get())
|
||||
if (g_offscreenBrowser.get())
|
||||
g_offscreenBrowser->SetSize(PET_VIEW, width, height);
|
||||
}
|
||||
|
||||
// Render the view contents.
|
||||
void RenderGL(ClientPlugin* plugin)
|
||||
{
|
||||
void RenderGL(ClientPlugin* plugin) {
|
||||
wglMakeCurrent(plugin->hDC, plugin->hRC);
|
||||
|
||||
struct {
|
||||
float tu, tv;
|
||||
float x, y, z;
|
||||
} static vertices[] = {
|
||||
{0.0f, 0.0f, -1.0f, -1.0f, 0.0f},
|
||||
{1.0f, 0.0f, 1.0f, -1.0f, 0.0f},
|
||||
{1.0f, 1.0f, 1.0f, 1.0f, 0.0f},
|
||||
{0.0f, 1.0f, -1.0f, 1.0f, 0.0f}
|
||||
};
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
//glTranslatef(0.0f, 0.0f, -3.0f);
|
||||
|
||||
// Draw the background gradient.
|
||||
glPushAttrib(GL_ALL_ATTRIB_BITS);
|
||||
glBegin(GL_QUADS);
|
||||
glColor4f(1.0,0.0,0.0,1.0); // red
|
||||
glVertex2f(-1.0,-1.0);
|
||||
glVertex2f(1.0,-1.0);
|
||||
glColor4f(0.0,0.0,1.0,1.0); // blue
|
||||
glVertex2f(1.0, 1.0);
|
||||
glVertex2f(-1.0, 1.0);
|
||||
glEnd();
|
||||
glPopAttrib();
|
||||
|
||||
// Rotate the view based on the mouse spin.
|
||||
glRotatef(-g_spinX, 1.0f, 0.0f, 0.0f);
|
||||
glRotatef(-g_spinY, 0.0f, 1.0f, 0.0f);
|
||||
|
||||
if (g_offscreenTransparent) {
|
||||
// Enable alpha blending.
|
||||
glEnable(GL_BLEND);
|
||||
}
|
||||
|
||||
// Enable 2D textures.
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
// Draw the facets with the texture.
|
||||
glBindTexture(GL_TEXTURE_2D, g_textureID);
|
||||
glInterleavedArrays(GL_T2F_V3F, 0, vertices);
|
||||
glDrawArrays(GL_QUADS, 0, 4);
|
||||
|
||||
// Disable 2D textures.
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
if (g_offscreenTransparent) {
|
||||
// Disable alpha blending.
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
plugin->renderer.Render();
|
||||
|
||||
SwapBuffers(plugin->hDC);
|
||||
}
|
||||
@@ -661,19 +346,19 @@ NPError NPP_NewImpl(NPMIMEType plugin_type, NPP instance, uint16 mode,
|
||||
if (instance == NULL)
|
||||
return NPERR_INVALID_INSTANCE_ERROR;
|
||||
|
||||
ClientPlugin *plugin = new ClientPlugin;
|
||||
ClientPlugin* plugin = new ClientPlugin(g_offscreenTransparent);
|
||||
instance->pdata = reinterpret_cast<void*>(plugin);
|
||||
|
||||
return NPERR_NO_ERROR;
|
||||
}
|
||||
|
||||
NPError NPP_DestroyImpl(NPP instance, NPSavedData** save) {
|
||||
ClientPlugin *plugin = reinterpret_cast<ClientPlugin*>(instance->pdata);
|
||||
|
||||
ClientPlugin* plugin = reinterpret_cast<ClientPlugin*>(instance->pdata);
|
||||
|
||||
if (plugin) {
|
||||
if(plugin->hWnd) {
|
||||
if (plugin->hWnd) {
|
||||
DestroyWindow(plugin->hWnd);
|
||||
DisableGL(plugin->hWnd, plugin->hDC, plugin->hRC);
|
||||
DisableGL(plugin);
|
||||
}
|
||||
delete plugin;
|
||||
}
|
||||
@@ -688,14 +373,13 @@ NPError NPP_SetWindowImpl(NPP instance, NPWindow* window_info) {
|
||||
if (window_info == NULL)
|
||||
return NPERR_GENERIC_ERROR;
|
||||
|
||||
ClientPlugin *plugin = reinterpret_cast<ClientPlugin*>(instance->pdata);
|
||||
ClientPlugin* plugin = reinterpret_cast<ClientPlugin*>(instance->pdata);
|
||||
HWND parent_hwnd = reinterpret_cast<HWND>(window_info->window);
|
||||
|
||||
if (plugin->hWnd == NULL)
|
||||
{
|
||||
|
||||
if (plugin->hWnd == NULL) {
|
||||
WNDCLASS wc;
|
||||
HINSTANCE hInstance = GetModuleHandle(NULL);
|
||||
|
||||
|
||||
// Register the window class.
|
||||
wc.style = CS_OWNDC;
|
||||
wc.lpfnWndProc = PluginWndProc;
|
||||
@@ -708,7 +392,7 @@ NPError NPP_SetWindowImpl(NPP instance, NPWindow* window_info) {
|
||||
wc.lpszMenuName = NULL;
|
||||
wc.lpszClassName = L"ClientOSRPlugin";
|
||||
RegisterClass(&wc);
|
||||
|
||||
|
||||
// Create the main window.
|
||||
plugin->hWnd = CreateWindow(L"ClientOSRPlugin", L"Client OSR Plugin",
|
||||
WS_CHILD|WS_CLIPCHILDREN|WS_CLIPSIBLINGS, 0, 0, 0, 0, parent_hwnd, NULL,
|
||||
@@ -716,9 +400,9 @@ NPError NPP_SetWindowImpl(NPP instance, NPWindow* window_info) {
|
||||
|
||||
SetWindowLongPtr(plugin->hWnd, GWLP_USERDATA,
|
||||
reinterpret_cast<LONG_PTR>(plugin));
|
||||
|
||||
|
||||
// Enable GL drawing for the window.
|
||||
EnableGL(plugin->hWnd, &(plugin->hDC), &(plugin->hRC));
|
||||
EnableGL(plugin);
|
||||
|
||||
// Create the off-screen rendering window.
|
||||
CefWindowInfo windowInfo;
|
||||
@@ -745,22 +429,20 @@ NPError NPP_SetWindowImpl(NPP instance, NPWindow* window_info) {
|
||||
|
||||
// Plugin window procedure.
|
||||
LRESULT CALLBACK PluginWndProc(HWND hWnd, UINT message, WPARAM wParam,
|
||||
LPARAM lParam)
|
||||
{
|
||||
LPARAM lParam) {
|
||||
static POINT lastMousePos, curMousePos;
|
||||
static bool mouseRotation = false;
|
||||
static bool mouseTracking = false;
|
||||
|
||||
ClientPlugin* plugin =
|
||||
reinterpret_cast<ClientPlugin*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
|
||||
|
||||
switch(message)
|
||||
{
|
||||
|
||||
switch (message) {
|
||||
case WM_CREATE:
|
||||
// Start the timer that's used for redrawing.
|
||||
SetTimer(hWnd, 1, 20, NULL);
|
||||
return 0;
|
||||
|
||||
|
||||
case WM_DESTROY:
|
||||
// Stop the timer that's used for redrawing.
|
||||
KillTimer(hWnd, 1);
|
||||
@@ -770,10 +452,10 @@ LRESULT CALLBACK PluginWndProc(HWND hWnd, UINT message, WPARAM wParam,
|
||||
g_offscreenBrowser = NULL;
|
||||
return 0;
|
||||
|
||||
case WM_TIMER:
|
||||
case WM_TIMER:
|
||||
RenderGL(plugin);
|
||||
break;
|
||||
|
||||
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_RBUTTONDOWN:
|
||||
SetCapture(hWnd);
|
||||
@@ -786,7 +468,7 @@ LRESULT CALLBACK PluginWndProc(HWND hWnd, UINT message, WPARAM wParam,
|
||||
} else {
|
||||
if (g_offscreenBrowser.get()) {
|
||||
g_offscreenBrowser->SendMouseClickEvent(LOWORD(lParam), HIWORD(lParam),
|
||||
(message==WM_LBUTTONDOWN?MBT_LEFT:MBT_RIGHT), false, 1);
|
||||
(message == WM_LBUTTONDOWN?MBT_LEFT:MBT_RIGHT), false, 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -798,23 +480,22 @@ LRESULT CALLBACK PluginWndProc(HWND hWnd, UINT message, WPARAM wParam,
|
||||
if (mouseRotation) {
|
||||
// End rotation effect.
|
||||
mouseRotation = false;
|
||||
g_spinX = 0;
|
||||
g_spinY = 0;
|
||||
plugin->renderer.SetSpin(0, 0);
|
||||
} else {
|
||||
if (g_offscreenBrowser.get()) {
|
||||
g_offscreenBrowser->SendMouseClickEvent(LOWORD(lParam), HIWORD(lParam),
|
||||
(message==WM_LBUTTONUP?MBT_LEFT:MBT_RIGHT), true, 1);
|
||||
(message == WM_LBUTTONUP?MBT_LEFT:MBT_RIGHT), true, 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_MOUSEMOVE:
|
||||
if(mouseRotation) {
|
||||
if (mouseRotation) {
|
||||
// Apply rotation effect.
|
||||
curMousePos.x = LOWORD(lParam);
|
||||
curMousePos.y = HIWORD(lParam);
|
||||
g_spinX -= (curMousePos.x - lastMousePos.x);
|
||||
g_spinY -= (curMousePos.y - lastMousePos.y);
|
||||
plugin->renderer.IncrementSpin((curMousePos.x - lastMousePos.x),
|
||||
(curMousePos.y - lastMousePos.y));
|
||||
lastMousePos.x = curMousePos.x;
|
||||
lastMousePos.y = curMousePos.y;
|
||||
} else {
|
||||
@@ -852,26 +533,27 @@ LRESULT CALLBACK PluginWndProc(HWND hWnd, UINT message, WPARAM wParam,
|
||||
case WM_MOUSEWHEEL:
|
||||
if (g_offscreenBrowser.get()) {
|
||||
g_offscreenBrowser->SendMouseWheelEvent(LOWORD(lParam), HIWORD(lParam),
|
||||
GET_WHEEL_DELTA_WPARAM(wParam));
|
||||
0, GET_WHEEL_DELTA_WPARAM(wParam));
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case WM_SIZE: {
|
||||
int width = LOWORD(lParam);
|
||||
int width = LOWORD(lParam);
|
||||
int height = HIWORD(lParam);
|
||||
if(width > 0 && height > 0)
|
||||
if (width > 0 && height > 0)
|
||||
SizeGL(plugin, width, height);
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_SETFOCUS:
|
||||
case WM_KILLFOCUS:
|
||||
if (g_offscreenBrowser.get())
|
||||
g_offscreenBrowser->SendFocusEvent(message==WM_SETFOCUS);
|
||||
g_offscreenBrowser->SendFocusEvent(message == WM_SETFOCUS);
|
||||
break;
|
||||
|
||||
case WM_CAPTURECHANGED:
|
||||
case WM_CANCELMODE:
|
||||
if(!mouseRotation) {
|
||||
if (!mouseRotation) {
|
||||
if (g_offscreenBrowser.get())
|
||||
g_offscreenBrowser->SendCaptureLostEvent();
|
||||
}
|
||||
@@ -886,21 +568,22 @@ LRESULT CALLBACK PluginWndProc(HWND hWnd, UINT message, WPARAM wParam,
|
||||
case WM_IME_CHAR:
|
||||
if (g_offscreenBrowser.get()) {
|
||||
CefBrowser::KeyType type = KT_CHAR;
|
||||
bool sysChar = false, imeChar = false;
|
||||
CefKeyInfo keyInfo;
|
||||
keyInfo.key = wParam;
|
||||
|
||||
if (message == WM_KEYDOWN || message == WM_SYSKEYDOWN)
|
||||
type = KT_KEYDOWN;
|
||||
else if (message == WM_KEYUP || message == WM_SYSKEYUP)
|
||||
type = KT_KEYUP;
|
||||
|
||||
|
||||
if (message == WM_SYSKEYDOWN || message == WM_SYSKEYUP ||
|
||||
message == WM_SYSCHAR)
|
||||
sysChar = true;
|
||||
keyInfo.sysChar = true;
|
||||
|
||||
if (message == WM_IME_CHAR)
|
||||
imeChar = true;
|
||||
keyInfo.imeChar = true;
|
||||
|
||||
g_offscreenBrowser->SendKeyEvent(type, wParam, lParam, sysChar, imeChar);
|
||||
g_offscreenBrowser->SendKeyEvent(type, keyInfo, lParam);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -908,7 +591,8 @@ LRESULT CALLBACK PluginWndProc(HWND hWnd, UINT message, WPARAM wParam,
|
||||
PAINTSTRUCT ps;
|
||||
BeginPaint(hWnd, &ps);
|
||||
EndPaint(hWnd, &ps);
|
||||
} return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
case WM_ERASEBKGND:
|
||||
return 0;
|
||||
@@ -917,36 +601,31 @@ LRESULT CALLBACK PluginWndProc(HWND hWnd, UINT message, WPARAM wParam,
|
||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
NPError API_CALL NP_OSRGetEntryPoints(NPPluginFuncs* pFuncs)
|
||||
{
|
||||
NPError API_CALL NP_OSRGetEntryPoints(NPPluginFuncs* pFuncs) {
|
||||
pFuncs->newp = NPP_NewImpl;
|
||||
pFuncs->destroy = NPP_DestroyImpl;
|
||||
pFuncs->setwindow = NPP_SetWindowImpl;
|
||||
return NPERR_NO_ERROR;
|
||||
}
|
||||
|
||||
NPError API_CALL NP_OSRInitialize(NPNetscapeFuncs* pFuncs)
|
||||
{
|
||||
NPError API_CALL NP_OSRInitialize(NPNetscapeFuncs* pFuncs) {
|
||||
g_osrbrowser = pFuncs;
|
||||
return NPERR_NO_ERROR;
|
||||
}
|
||||
|
||||
NPError API_CALL NP_OSRShutdown(void)
|
||||
{
|
||||
NPError API_CALL NP_OSRShutdown(void) {
|
||||
g_osrbrowser = NULL;
|
||||
return NPERR_NO_ERROR;
|
||||
}
|
||||
|
||||
CefRefPtr<CefBrowser> GetOffScreenBrowser()
|
||||
{
|
||||
CefRefPtr<CefBrowser> GetOffScreenBrowser() {
|
||||
return g_offscreenBrowser;
|
||||
}
|
||||
|
||||
void SetOffScreenTransparent(bool transparent)
|
||||
{
|
||||
void SetOffScreenTransparent(bool transparent) {
|
||||
g_offscreenTransparent = transparent;
|
||||
}
|
||||
|
||||
#endif // OS_WIN
|
||||
#endif // OS_WIN
|
||||
|
15
tests/cefclient/osrtest_mac.h
Normal file
15
tests/cefclient/osrtest_mac.h
Normal file
@@ -0,0 +1,15 @@
|
||||
// Copyright (c) 2012 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.
|
||||
|
||||
#ifndef CEF_TESTS_CEFCLIENT_OSRTEST_MAC_H_
|
||||
#define CEF_TESTS_CEFCLIENT_OSRTEST_MAC_H_
|
||||
|
||||
namespace osrtest {
|
||||
|
||||
void RunTest(bool transparent);
|
||||
|
||||
} // namespace osrtest
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_OSRTEST_MAC_H_
|
||||
|
752
tests/cefclient/osrtest_mac.mm
Normal file
752
tests/cefclient/osrtest_mac.mm
Normal file
@@ -0,0 +1,752 @@
|
||||
// Copyright (c) 2012 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.
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#include <OpenGL/gl.h>
|
||||
|
||||
#include "osrtest_mac.h"
|
||||
#include "include/cef.h"
|
||||
#include "osrenderer.h"
|
||||
#include "client_popup_handler.h"
|
||||
#include "resource_util.h"
|
||||
#include "util.h"
|
||||
|
||||
// The client OpenGL view.
|
||||
@interface ClientOpenGLView : NSOpenGLView {
|
||||
@public
|
||||
NSTrackingArea* tracking_area_;
|
||||
CefRefPtr<CefBrowser> browser_;
|
||||
ClientOSRenderer* renderer_;
|
||||
NSPoint last_mouse_pos_;
|
||||
NSPoint cur_mouse_pos_;
|
||||
bool rotating_;
|
||||
}
|
||||
|
||||
- (id)initWithFrame:(NSRect)frame andTransparency:(bool)transparency;
|
||||
- (NSPoint)getClickPointForEvent:(NSEvent*)event;
|
||||
- (void)getKeyInfo:(CefKeyInfo&)info forEvent:(NSEvent*)event;
|
||||
- (int)getModifiersForEvent:(NSEvent*)event;
|
||||
- (BOOL)isKeyUpEvent:(NSEvent*)event;
|
||||
- (BOOL)isKeyPadEvent:(NSEvent*)event;
|
||||
@end
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
// Handler for off-screen rendering windows.
|
||||
class ClientOSRHandler : public CefClient,
|
||||
public CefLifeSpanHandler,
|
||||
public CefLoadHandler,
|
||||
public CefRequestHandler,
|
||||
public CefDisplayHandler,
|
||||
public CefRenderHandler {
|
||||
public:
|
||||
explicit ClientOSRHandler(ClientOpenGLView* view)
|
||||
: view_(view) {
|
||||
}
|
||||
~ClientOSRHandler() {
|
||||
}
|
||||
|
||||
void Disconnect() {
|
||||
view_ = nil;
|
||||
}
|
||||
|
||||
// CefClient methods
|
||||
virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() OVERRIDE {
|
||||
return this;
|
||||
}
|
||||
virtual CefRefPtr<CefLoadHandler> GetLoadHandler() OVERRIDE {
|
||||
return this;
|
||||
}
|
||||
virtual CefRefPtr<CefRequestHandler> GetRequestHandler() OVERRIDE {
|
||||
return this;
|
||||
}
|
||||
virtual CefRefPtr<CefDisplayHandler> GetDisplayHandler() OVERRIDE {
|
||||
return this;
|
||||
}
|
||||
virtual CefRefPtr<CefRenderHandler> GetRenderHandler() OVERRIDE {
|
||||
return this;
|
||||
}
|
||||
|
||||
// CefLifeSpanHandler methods
|
||||
|
||||
virtual bool OnBeforePopup(CefRefPtr<CefBrowser> parentBrowser,
|
||||
const CefPopupFeatures& popupFeatures,
|
||||
CefWindowInfo& windowInfo,
|
||||
const CefString& url,
|
||||
CefRefPtr<CefClient>& client,
|
||||
CefBrowserSettings& settings) OVERRIDE {
|
||||
REQUIRE_UI_THREAD();
|
||||
|
||||
windowInfo.m_bWindowRenderingDisabled = TRUE;
|
||||
client = new ClientPopupHandler(view_->browser_);
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void OnAfterCreated(CefRefPtr<CefBrowser> browser) OVERRIDE {
|
||||
REQUIRE_UI_THREAD();
|
||||
|
||||
// Set the view size to match the window size.
|
||||
const NSRect bounds = [view_ bounds];
|
||||
browser->SetSize(PET_VIEW, bounds.size.width, bounds.size.height);
|
||||
|
||||
view_->browser_ = browser;
|
||||
}
|
||||
|
||||
virtual void OnBeforeClose(CefRefPtr<CefBrowser> browser) OVERRIDE {
|
||||
if (view_)
|
||||
view_->browser_ = NULL;
|
||||
}
|
||||
|
||||
// CefLoadHandler methods
|
||||
|
||||
virtual void OnLoadStart(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame) OVERRIDE {
|
||||
REQUIRE_UI_THREAD();
|
||||
|
||||
if (!browser->IsPopup() && frame->IsMain()) {
|
||||
// We've just started loading a page
|
||||
SetLoading(true);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnLoadEnd(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
int httpStatusCode) OVERRIDE {
|
||||
REQUIRE_UI_THREAD();
|
||||
|
||||
if (!browser->IsPopup() && frame->IsMain()) {
|
||||
// We've just finished loading a page
|
||||
SetLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
// CefRequestHandler methods
|
||||
|
||||
virtual bool OnBeforeResourceLoad(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefRequest> request,
|
||||
CefString& redirectUrl,
|
||||
CefRefPtr<CefStreamReader>& resourceStream,
|
||||
CefRefPtr<CefResponse> response,
|
||||
int loadFlags) OVERRIDE {
|
||||
REQUIRE_IO_THREAD();
|
||||
|
||||
std::string url = request->GetURL();
|
||||
if (url == "http://tests/osrtest") {
|
||||
// Show the osrtest HTML contents
|
||||
resourceStream = GetBinaryResourceReader("osrtest.html");
|
||||
response->SetMimeType("text/html");
|
||||
response->SetStatus(200);
|
||||
} else if (url == "http://tests/transparency") {
|
||||
// Show the osrtest HTML contents
|
||||
resourceStream = GetBinaryResourceReader("transparency.html");
|
||||
response->SetMimeType("text/html");
|
||||
response->SetStatus(200);
|
||||
} else if (strstr(url.c_str(), "/logoball.png") != NULL) {
|
||||
// Load the "logoball.png" image resource.
|
||||
resourceStream = GetBinaryResourceReader("logoball.png");
|
||||
response->SetMimeType("image/png");
|
||||
response->SetStatus(200);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// CefDisplayHandler methods
|
||||
|
||||
virtual void OnNavStateChange(CefRefPtr<CefBrowser> browser,
|
||||
bool canGoBack,
|
||||
bool canGoForward) OVERRIDE {
|
||||
REQUIRE_UI_THREAD();
|
||||
}
|
||||
|
||||
virtual void OnAddressChange(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
const CefString& url) OVERRIDE {
|
||||
REQUIRE_UI_THREAD();
|
||||
}
|
||||
|
||||
virtual void OnTitleChange(CefRefPtr<CefBrowser> browser,
|
||||
const CefString& title) OVERRIDE {
|
||||
REQUIRE_UI_THREAD();
|
||||
|
||||
if (!view_)
|
||||
return;
|
||||
|
||||
// Set the frame window title bar
|
||||
NSWindow* window = [view_ window];
|
||||
std::string titleStr(title);
|
||||
NSString* str = [NSString stringWithUTF8String:titleStr.c_str()];
|
||||
[window setTitle:str];
|
||||
}
|
||||
|
||||
// CefRenderHandler methods
|
||||
|
||||
virtual bool GetViewRect(CefRefPtr<CefBrowser> browser,
|
||||
CefRect& rect) OVERRIDE {
|
||||
REQUIRE_UI_THREAD();
|
||||
|
||||
if (!view_)
|
||||
return false;
|
||||
|
||||
// The simulated screen and view rectangle are the same. This is necessary
|
||||
// for popup menus to be located and sized inside the view.
|
||||
const NSRect bounds = [view_ bounds];
|
||||
rect.x = rect.y = 0;
|
||||
rect.width = bounds.size.width;
|
||||
rect.height = bounds.size.height;
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool GetScreenRect(CefRefPtr<CefBrowser> browser,
|
||||
CefRect& rect) OVERRIDE {
|
||||
return GetViewRect(browser, rect);
|
||||
}
|
||||
|
||||
virtual bool GetScreenPoint(CefRefPtr<CefBrowser> browser,
|
||||
int viewX,
|
||||
int viewY,
|
||||
int& screenX,
|
||||
int& screenY) OVERRIDE {
|
||||
REQUIRE_UI_THREAD();
|
||||
|
||||
if (!view_)
|
||||
return false;
|
||||
|
||||
// Convert the point from view coordinates to actual screen coordinates.
|
||||
NSRect bounds = [view_ bounds];
|
||||
NSPoint view_pt = {viewX, bounds.size.height - viewY};
|
||||
NSPoint window_pt = [view_ convertPoint:view_pt toView:nil];
|
||||
NSPoint screen_pt = [[view_ window] convertBaseToScreen:window_pt];
|
||||
screenX = screen_pt.x;
|
||||
screenY = screen_pt.y;
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void OnPopupShow(CefRefPtr<CefBrowser> browser,
|
||||
bool show) OVERRIDE {
|
||||
REQUIRE_UI_THREAD();
|
||||
|
||||
if (!view_)
|
||||
return;
|
||||
|
||||
view_->renderer_->OnPopupShow(browser, show);
|
||||
}
|
||||
|
||||
virtual void OnPopupSize(CefRefPtr<CefBrowser> browser,
|
||||
const CefRect& rect) OVERRIDE {
|
||||
REQUIRE_UI_THREAD();
|
||||
|
||||
if (!view_)
|
||||
return;
|
||||
|
||||
view_->renderer_->OnPopupSize(browser, rect);
|
||||
}
|
||||
|
||||
virtual void OnPaint(CefRefPtr<CefBrowser> browser,
|
||||
PaintElementType type,
|
||||
const RectList& dirtyRects,
|
||||
const void* buffer) OVERRIDE {
|
||||
REQUIRE_UI_THREAD();
|
||||
|
||||
if (!view_)
|
||||
return;
|
||||
|
||||
[[view_ openGLContext] makeCurrentContext];
|
||||
|
||||
view_->renderer_->OnPaint(browser, type, dirtyRects, buffer);
|
||||
|
||||
// Notify the view to redraw the invalidated regions.
|
||||
{
|
||||
RectList::const_iterator i = dirtyRects.begin();
|
||||
for (; i != dirtyRects.end(); ++i) {
|
||||
NSRect rect = {{i->x, i->y}, {i->width, i->height}};
|
||||
[view_ setNeedsDisplayInRect:rect];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnCursorChange(CefRefPtr<CefBrowser> browser,
|
||||
CefCursorHandle cursor) OVERRIDE {
|
||||
REQUIRE_UI_THREAD();
|
||||
[cursor set];
|
||||
}
|
||||
|
||||
private:
|
||||
void SetLoading(bool isLoading) {
|
||||
}
|
||||
|
||||
ClientOpenGLView* view_;
|
||||
|
||||
// Include the default reference counting implementation.
|
||||
IMPLEMENT_REFCOUNTING(ClientOSRPlugin);
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
@implementation ClientOpenGLView
|
||||
|
||||
- (id)initWithFrame:(NSRect)frame andTransparency:(bool)transparency {
|
||||
NSOpenGLPixelFormat * pixelFormat =
|
||||
[[NSOpenGLPixelFormat alloc]
|
||||
initWithAttributes:(NSOpenGLPixelFormatAttribute[]) {
|
||||
NSOpenGLPFAWindow,
|
||||
NSOpenGLPFADoubleBuffer,
|
||||
NSOpenGLPFADepthSize,
|
||||
32,
|
||||
0}];
|
||||
[pixelFormat autorelease];
|
||||
|
||||
self = [super initWithFrame:frame pixelFormat:pixelFormat];
|
||||
if (self) {
|
||||
renderer_ = new ClientOSRenderer(transparency);
|
||||
rotating_ = false;
|
||||
|
||||
tracking_area_ =
|
||||
[[NSTrackingArea alloc] initWithRect:frame
|
||||
options:NSTrackingMouseMoved |
|
||||
NSTrackingActiveInActiveApp |
|
||||
NSTrackingInVisibleRect
|
||||
owner:self
|
||||
userInfo:nil];
|
||||
[self addTrackingArea:tracking_area_];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
if (browser_) {
|
||||
static_cast<ClientOSRHandler*>(browser_->GetClient().get())->Disconnect();
|
||||
browser_->CloseBrowser();
|
||||
browser_ = NULL;
|
||||
}
|
||||
if (renderer_)
|
||||
delete renderer_;
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void)drawRect: (NSRect)bounds {
|
||||
NSOpenGLContext* context = [self openGLContext];
|
||||
[context makeCurrentContext];
|
||||
|
||||
renderer_->Render();
|
||||
|
||||
[context flushBuffer];
|
||||
}
|
||||
|
||||
- (void)setFrame:(NSRect)frameRect {
|
||||
[super setFrame:frameRect];
|
||||
|
||||
int width = frameRect.size.width;
|
||||
int height = frameRect.size.height;
|
||||
|
||||
[[self openGLContext] makeCurrentContext];
|
||||
|
||||
renderer_->SetSize(width, height);
|
||||
|
||||
if (browser_)
|
||||
browser_->SetSize(PET_VIEW, width, height);
|
||||
}
|
||||
|
||||
- (void)mouseDown:(NSEvent *)event {
|
||||
if (!browser_)
|
||||
return;
|
||||
|
||||
NSPoint point = [self getClickPointForEvent:event];
|
||||
int clickCount = [event clickCount];
|
||||
|
||||
browser_->SendMouseClickEvent(point.x, point.y, MBT_LEFT, false, clickCount);
|
||||
}
|
||||
|
||||
- (void)rightMouseDown:(NSEvent *)event {
|
||||
if (!browser_)
|
||||
return;
|
||||
|
||||
NSPoint point = [self getClickPointForEvent:event];
|
||||
|
||||
if ([event modifierFlags] & NSShiftKeyMask) {
|
||||
// Start rotation effect.
|
||||
last_mouse_pos_ = cur_mouse_pos_ = point;
|
||||
rotating_ = true;
|
||||
return;
|
||||
}
|
||||
|
||||
int clickCount = [event clickCount];
|
||||
|
||||
browser_->SendMouseClickEvent(point.x, point.y, MBT_RIGHT, false, clickCount);
|
||||
}
|
||||
|
||||
- (void)otherMouseDown:(NSEvent *)event {
|
||||
if (!browser_)
|
||||
return;
|
||||
|
||||
NSPoint point = [self getClickPointForEvent:event];
|
||||
int clickCount = [event clickCount];
|
||||
|
||||
browser_->SendMouseClickEvent(point.x, point.y, MBT_MIDDLE, false,
|
||||
clickCount);
|
||||
}
|
||||
|
||||
- (void)mouseUp:(NSEvent *)event {
|
||||
if (!browser_)
|
||||
return;
|
||||
|
||||
NSPoint point = [self getClickPointForEvent:event];
|
||||
int clickCount = [event clickCount];
|
||||
|
||||
browser_->SendMouseClickEvent(point.x, point.y, MBT_LEFT, true, clickCount);
|
||||
}
|
||||
|
||||
- (void)rightMouseUp:(NSEvent *)event {
|
||||
if (!browser_)
|
||||
return;
|
||||
|
||||
if (rotating_) {
|
||||
// End rotation effect.
|
||||
renderer_->SetSpin(0, 0);
|
||||
rotating_ = false;
|
||||
[self setNeedsDisplay:YES];
|
||||
return;
|
||||
}
|
||||
|
||||
NSPoint point = [self getClickPointForEvent:event];
|
||||
int clickCount = [event clickCount];
|
||||
|
||||
browser_->SendMouseClickEvent(point.x, point.y, MBT_RIGHT, true, clickCount);
|
||||
}
|
||||
|
||||
- (void)otherMouseUp:(NSEvent *)event {
|
||||
if (!browser_)
|
||||
return;
|
||||
|
||||
NSPoint point = [self getClickPointForEvent:event];
|
||||
int clickCount = [event clickCount];
|
||||
|
||||
browser_->SendMouseClickEvent(point.x, point.y, MBT_MIDDLE, true, clickCount);
|
||||
}
|
||||
|
||||
- (void)mouseMoved:(NSEvent *)event {
|
||||
if (!browser_)
|
||||
return;
|
||||
|
||||
NSPoint point = [self getClickPointForEvent:event];
|
||||
|
||||
if (rotating_) {
|
||||
// Apply rotation effect.
|
||||
cur_mouse_pos_ = point;
|
||||
renderer_->IncrementSpin((cur_mouse_pos_.x - last_mouse_pos_.x),
|
||||
(cur_mouse_pos_.y - last_mouse_pos_.y));
|
||||
last_mouse_pos_ = cur_mouse_pos_;
|
||||
[self setNeedsDisplay:YES];
|
||||
return;
|
||||
}
|
||||
|
||||
browser_->SendMouseMoveEvent(point.x, point.y, false);
|
||||
}
|
||||
|
||||
- (void)mouseDragged:(NSEvent *)event {
|
||||
[self mouseMoved:event];
|
||||
}
|
||||
|
||||
- (void)rightMouseDragged:(NSEvent *)event {
|
||||
[self mouseMoved:event];
|
||||
}
|
||||
|
||||
- (void)otherMouseDragged:(NSEvent *)event {
|
||||
[self mouseMoved:event];
|
||||
}
|
||||
|
||||
- (void)mouseEntered:(NSEvent *)event {
|
||||
[self mouseMoved:event];
|
||||
}
|
||||
|
||||
- (void)mouseExited:(NSEvent *)event {
|
||||
if (!browser_)
|
||||
return;
|
||||
|
||||
NSPoint point = [self getClickPointForEvent:event];
|
||||
|
||||
browser_->SendMouseMoveEvent(point.x, point.y, true);
|
||||
}
|
||||
|
||||
- (void)keyDown:(NSEvent *)event {
|
||||
if (!browser_)
|
||||
return;
|
||||
|
||||
CefKeyInfo keyInfo;
|
||||
[self getKeyInfo:keyInfo forEvent:event];
|
||||
int modifiers = [self getModifiersForEvent:event];
|
||||
|
||||
browser_->SendKeyEvent(KT_KEYDOWN, keyInfo, modifiers);
|
||||
|
||||
if ([event modifierFlags] & (NSNumericPadKeyMask | NSFunctionKeyMask)) {
|
||||
// Don't send a Char event for non-char keys like arrows, function keys and
|
||||
// clear.
|
||||
switch (keyInfo.keyCode) {
|
||||
case 81: // =
|
||||
case 75: // /
|
||||
case 67: // *
|
||||
case 78: // -
|
||||
case 69: // +
|
||||
case 76: // Enter
|
||||
case 65: // .
|
||||
case 82: // 0
|
||||
case 83: // 1
|
||||
case 84: // 2
|
||||
case 85: // 3
|
||||
case 86: // 4
|
||||
case 87: // 5
|
||||
case 88: // 6
|
||||
case 89: // 7
|
||||
case 91: // 8
|
||||
case 92: // 9
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
browser_->SendKeyEvent(KT_CHAR, keyInfo, modifiers);
|
||||
}
|
||||
|
||||
- (void)keyUp:(NSEvent *)event {
|
||||
if (!browser_)
|
||||
return;
|
||||
|
||||
CefKeyInfo keyInfo;
|
||||
[self getKeyInfo:keyInfo forEvent:event];
|
||||
int modifiers = [self getModifiersForEvent:event];
|
||||
|
||||
browser_->SendKeyEvent(KT_KEYUP, keyInfo, modifiers);
|
||||
}
|
||||
|
||||
- (void)flagsChanged:(NSEvent *)event {
|
||||
if ([self isKeyUpEvent:event])
|
||||
[self keyUp:event];
|
||||
else
|
||||
[self keyDown:event];
|
||||
}
|
||||
|
||||
- (void)scrollWheel:(NSEvent *)event {
|
||||
if (!browser_)
|
||||
return;
|
||||
|
||||
CGEventRef cgEvent = [event CGEvent];
|
||||
ASSERT(cgEvent);
|
||||
|
||||
NSPoint point = [self getClickPointForEvent:event];
|
||||
int deltaX =
|
||||
CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventPointDeltaAxis2);
|
||||
int deltaY =
|
||||
CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventPointDeltaAxis1);
|
||||
|
||||
browser_->SendMouseWheelEvent(point.x, point.y, deltaX, deltaY);
|
||||
}
|
||||
|
||||
- (BOOL)canBecomeKeyView {
|
||||
return (browser_ != NULL);
|
||||
}
|
||||
|
||||
- (BOOL)acceptsFirstResponder {
|
||||
return (browser_ != NULL);
|
||||
}
|
||||
|
||||
- (BOOL)becomeFirstResponder {
|
||||
if (browser_) {
|
||||
browser_->SendFocusEvent(true);
|
||||
return [super becomeFirstResponder];
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL)resignFirstResponder {
|
||||
if (browser_) {
|
||||
browser_->SendFocusEvent(false);
|
||||
return [super resignFirstResponder];
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)undo:(id)sender {
|
||||
if (browser_)
|
||||
browser_->GetFocusedFrame()->Undo();
|
||||
}
|
||||
|
||||
- (void)redo:(id)sender {
|
||||
if (browser_)
|
||||
browser_->GetFocusedFrame()->Redo();
|
||||
}
|
||||
|
||||
- (void)cut:(id)sender {
|
||||
if (browser_)
|
||||
browser_->GetFocusedFrame()->Cut();
|
||||
}
|
||||
|
||||
- (void)copy:(id)sender {
|
||||
if (browser_)
|
||||
browser_->GetFocusedFrame()->Copy();
|
||||
}
|
||||
|
||||
- (void)paste:(id)sender {
|
||||
if (browser_)
|
||||
browser_->GetFocusedFrame()->Paste();
|
||||
}
|
||||
|
||||
- (void)delete:(id)sender {
|
||||
if (browser_)
|
||||
browser_->GetFocusedFrame()->Delete();
|
||||
}
|
||||
|
||||
- (void)selectAll:(id)sender {
|
||||
if (browser_)
|
||||
browser_->GetFocusedFrame()->SelectAll();
|
||||
}
|
||||
|
||||
- (NSPoint)getClickPointForEvent:(NSEvent*)event {
|
||||
NSPoint windowLocal = [event locationInWindow];
|
||||
NSPoint contentLocal = [self convertPoint:windowLocal fromView:nil];
|
||||
int x = contentLocal.x;
|
||||
int y = [self frame].size.height - contentLocal.y; // Flip y.
|
||||
|
||||
return {x,y};
|
||||
}
|
||||
|
||||
- (void)getKeyInfo:(CefKeyInfo&)info forEvent:(NSEvent*)event {
|
||||
if ([event type] == NSKeyDown || [event type] == NSKeyUp) {
|
||||
NSString* s = [event characters];
|
||||
if ([s length] > 0)
|
||||
info.character = [s characterAtIndex:0];
|
||||
|
||||
s = [event charactersIgnoringModifiers];
|
||||
if ([s length] > 0)
|
||||
info.characterNoModifiers = [s characterAtIndex:0];
|
||||
}
|
||||
|
||||
info.keyCode = [event keyCode];
|
||||
}
|
||||
|
||||
- (int)getModifiersForEvent:(NSEvent*)event {
|
||||
int modifiers = 0;
|
||||
|
||||
if ([event modifierFlags] & NSControlKeyMask)
|
||||
modifiers |= KEY_CTRL;
|
||||
if ([event modifierFlags] & NSShiftKeyMask)
|
||||
modifiers |= KEY_SHIFT;
|
||||
if ([event modifierFlags] & NSAlternateKeyMask)
|
||||
modifiers |= KEY_ALT;
|
||||
if ([event modifierFlags] & NSCommandKeyMask)
|
||||
modifiers |= KEY_META;
|
||||
if ([self isKeyPadEvent:event])
|
||||
modifiers |= KEY_KEYPAD;
|
||||
|
||||
return modifiers;
|
||||
}
|
||||
|
||||
- (BOOL)isKeyUpEvent:(NSEvent*)event {
|
||||
if ([event type] != NSFlagsChanged)
|
||||
return [event type] == NSKeyUp;
|
||||
|
||||
// FIXME: This logic fails if the user presses both Shift keys at once, for
|
||||
// example: we treat releasing one of them as keyDown.
|
||||
switch ([event keyCode]) {
|
||||
case 54: // Right Command
|
||||
case 55: // Left Command
|
||||
return ([event modifierFlags] & NSCommandKeyMask) == 0;
|
||||
|
||||
case 57: // Capslock
|
||||
return ([event modifierFlags] & NSAlphaShiftKeyMask) == 0;
|
||||
|
||||
case 56: // Left Shift
|
||||
case 60: // Right Shift
|
||||
return ([event modifierFlags] & NSShiftKeyMask) == 0;
|
||||
|
||||
case 58: // Left Alt
|
||||
case 61: // Right Alt
|
||||
return ([event modifierFlags] & NSAlternateKeyMask) == 0;
|
||||
|
||||
case 59: // Left Ctrl
|
||||
case 62: // Right Ctrl
|
||||
return ([event modifierFlags] & NSControlKeyMask) == 0;
|
||||
|
||||
case 63: // Function
|
||||
return ([event modifierFlags] & NSFunctionKeyMask) == 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
- (BOOL)isKeyPadEvent:(NSEvent*)event {
|
||||
if ([event modifierFlags] & NSNumericPadKeyMask)
|
||||
return true;
|
||||
|
||||
switch ([event keyCode]) {
|
||||
case 71: // Clear
|
||||
case 81: // =
|
||||
case 75: // /
|
||||
case 67: // *
|
||||
case 78: // -
|
||||
case 69: // +
|
||||
case 76: // Enter
|
||||
case 65: // .
|
||||
case 82: // 0
|
||||
case 83: // 1
|
||||
case 84: // 2
|
||||
case 85: // 3
|
||||
case 86: // 4
|
||||
case 87: // 5
|
||||
case 88: // 6
|
||||
case 89: // 7
|
||||
case 91: // 8
|
||||
case 92: // 9
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
namespace osrtest {
|
||||
|
||||
void RunTest(bool transparent) {
|
||||
NSRect screen_rect = [[NSScreen mainScreen] visibleFrame];
|
||||
NSRect window_rect = {{0, screen_rect.size.height}, {700, 700}};
|
||||
NSWindow* newWnd = [[NSWindow alloc]
|
||||
initWithContentRect:window_rect
|
||||
styleMask:(NSTitledWindowMask |
|
||||
NSClosableWindowMask |
|
||||
NSMiniaturizableWindowMask |
|
||||
NSResizableWindowMask |
|
||||
NSUnifiedTitleAndToolbarWindowMask)
|
||||
backing:NSBackingStoreBuffered
|
||||
defer:NO];
|
||||
ASSERT(newWnd);
|
||||
|
||||
ClientOpenGLView* view = [[ClientOpenGLView alloc] initWithFrame:window_rect
|
||||
andTransparency:transparent];
|
||||
[view setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
|
||||
|
||||
[newWnd setContentView:view];
|
||||
[view release];
|
||||
|
||||
CefWindowInfo info;
|
||||
CefBrowserSettings settings;
|
||||
|
||||
// Initialize the window info as off-screen.
|
||||
info.SetAsOffScreen(view);
|
||||
info.SetTransparentPainting(transparent);
|
||||
|
||||
// Creat the browser window.
|
||||
CefBrowser::CreateBrowser(info, new ClientOSRHandler(view),
|
||||
"http://tests/osrtest", settings);
|
||||
|
||||
[newWnd makeKeyAndOrderFront: nil];
|
||||
}
|
||||
|
||||
} // namespace osrtest
|
||||
|
40
tests/cefclient/res/osrtest.html
Normal file
40
tests/cefclient/res/osrtest.html
Normal file
@@ -0,0 +1,40 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Off-Screen Rendering Test</title>
|
||||
</head>
|
||||
<body bottommargin="2" rightmargin="0" leftmargin="0" topmargin="0" marginwidth="0" marginheight="0" style="font-family: Verdana, Arial;" bgcolor="white">
|
||||
<div align="center">
|
||||
<table border="0" cellpadding="2" cellspacing="0">
|
||||
<tr>
|
||||
<td colspan="2" style="font-size: 18pt;">Off-Screen Rendering App Example</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" style="font-size: 8pt;"><i>An OpenGL view that renders content from an off-screen browser window.</i></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 rotate the view!</span>
|
||||
<ul>
|
||||
<li>Click and drag the view with the left mouse button while holding the shift key.</li>
|
||||
<li>Enter a URL and click the "Go!" button to browse to a new Website.</li>
|
||||
<li><a href="http://tests/transparency">Click here</a> to test transparency.</li>
|
||||
<li><a href="http://www.adobe.com/software/flash/about/">Click here</a> to test a windowless plugin.</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" align="center">
|
||||
<form>
|
||||
<input type="text" id="url" size="100" value="http://www.google.com"/>
|
||||
<input type="button" value="Go!" onClick="document.location=document.getElementById('url').value;"/>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
Reference in New Issue
Block a user