Merge revision 1166 changes:

- cefclient: Add example of window manipulation via JavaScript (issue #925).

git-svn-id: https://chromiumembedded.googlecode.com/svn/branches/1364@1167 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
Marshall Greenblatt 2013-04-01 18:07:23 +00:00
parent 2f687aebb1
commit 69c038aea4
14 changed files with 475 additions and 1 deletions

View File

@ -115,6 +115,8 @@
'tests/cefclient/string_util.cpp',
'tests/cefclient/string_util.h',
'tests/cefclient/util.h',
'tests/cefclient/window_test.cpp',
'tests/cefclient/window_test.h',
],
'cefclient_sources_win': [
'tests/cefclient/cefclient.rc',
@ -130,11 +132,13 @@
'tests/cefclient/res/small.ico',
'tests/cefclient/res/transparency.html',
'tests/cefclient/resource_util_win.cpp',
'tests/cefclient/window_test_win.cpp',
],
'cefclient_sources_mac': [
'tests/cefclient/cefclient_mac.mm',
'tests/cefclient/client_handler_mac.mm',
'tests/cefclient/resource_util_mac.mm',
'tests/cefclient/window_test_mac.mm',
],
'cefclient_sources_mac_helper': [
'tests/cefclient/binding_test.cpp',
@ -165,6 +169,9 @@
'tests/cefclient/string_util.cpp',
'tests/cefclient/string_util.h',
'tests/cefclient/util.h',
'tests/cefclient/window_test.cpp',
'tests/cefclient/window_test.h',
'tests/cefclient/window_test_mac.mm',
],
'cefclient_bundle_resources_mac': [
'tests/cefclient/mac/cefclient.icns',
@ -177,12 +184,14 @@
'tests/cefclient/res/localstorage.html',
'tests/cefclient/res/logo.png',
'tests/cefclient/res/performance.html',
'tests/cefclient/res/window.html',
'tests/cefclient/res/xmlhttprequest.html',
],
'cefclient_sources_linux': [
'tests/cefclient/cefclient_gtk.cpp',
'tests/cefclient/client_handler_gtk.cpp',
'tests/cefclient/resource_util_linux.cpp',
'tests/cefclient/window_test_gtk.cpp',
],
'cefclient_bundle_resources_linux': [
'tests/cefclient/res/binding.html',
@ -191,6 +200,7 @@
'tests/cefclient/res/localstorage.html',
'tests/cefclient/res/logo.png',
'tests/cefclient/res/performance.html',
'tests/cefclient/res/window.html',
'tests/cefclient/res/xmlhttprequest.html',
],
},

View File

@ -36,6 +36,7 @@ IDS_LOGO BINARY "res\\logo.png"
IDS_LOGOBALL BINARY "res\\logoball.png"
IDS_PERFORMANCE BINARY "res\\performance.html"
IDS_TRANSPARENCY BINARY "res\\transparency.html"
IDS_WINDOW BINARY "res\\window.html"
IDS_XMLHTTPREQUEST BINARY "res\\xmlhttprequest.html"
/////////////////////////////////////////////////////////////////////////////
@ -73,6 +74,7 @@ BEGIN
MENUITEM "JavaScript Binding", ID_TESTS_BINDING
MENUITEM "Performance Tests", ID_TESTS_PERFORMANCE
MENUITEM "Dialogs", ID_TESTS_DIALOGS
MENUITEM "Window", ID_TESTS_WINDOW
MENUITEM "Plugin Info", ID_TESTS_PLUGIN_INFO
MENUITEM "DOM Access", ID_TESTS_DOM_ACCESS
MENUITEM "Local Storage", ID_TESTS_LOCALSTORAGE

View File

@ -18,6 +18,7 @@
#include "cefclient/performance_test.h"
#include "cefclient/scheme_test.h"
#include "cefclient/string_util.h"
#include "cefclient/window_test.h"
char szWorkingDir[512]; // The current working directory
@ -104,6 +105,14 @@ gboolean DialogsActivated(GtkWidget* widget) {
return FALSE; // Don't stop this message.
}
// Callback for Debug > Window... menu item.
gboolean WindowActivated(GtkWidget* widget) {
if (g_handler.get() && g_handler->GetBrowserId())
window_test::RunTest(g_handler->GetBrowser());
return FALSE; // Don't stop this message.
}
// Callback for Debug > Plugin Info... menu item.
gboolean PluginInfoActivated(GtkWidget* widget) {
if (g_handler.get() && g_handler->GetBrowserId())
@ -288,6 +297,8 @@ GtkWidget* CreateMenuBar() {
G_CALLBACK(PerformanceActivated));
AddMenuEntry(debug_menu, "Dialogs",
G_CALLBACK(DialogsActivated));
AddMenuEntry(debug_menu, "Window",
G_CALLBACK(WindowActivated));
AddMenuEntry(debug_menu, "Plugin Info",
G_CALLBACK(PluginInfoActivated));
AddMenuEntry(debug_menu, "DOM Access",

View File

@ -19,6 +19,7 @@
#include "cefclient/resource_util.h"
#include "cefclient/scheme_test.h"
#include "cefclient/string_util.h"
#include "cefclient/window_test.h"
// The global ClientHandler reference.
extern CefRefPtr<ClientHandler> g_handler;
@ -198,6 +199,7 @@ NSButton* MakeButton(NSRect* rect, NSString* title, NSView* parent) {
- (IBAction)testBinding:(id)sender;
- (IBAction)testPerformance:(id)sender;
- (IBAction)testDialogs:(id)sender;
- (IBAction)testWindow:(id)sender;
- (IBAction)testPluginInfo:(id)sender;
- (IBAction)testDOMAccess:(id)sender;
- (IBAction)testPopupWindow:(id)sender;
@ -253,6 +255,9 @@ NSButton* MakeButton(NSRect* rect, NSString* title, NSView* parent) {
[testMenu addItemWithTitle:@"Dialogs"
action:@selector(testDialogs:)
keyEquivalent:@""];
[testMenu addItemWithTitle:@"Window"
action:@selector(testWindow:)
keyEquivalent:@""];
[testMenu addItemWithTitle:@"Plugin Info"
action:@selector(testPluginInfo:)
keyEquivalent:@""];
@ -428,6 +433,11 @@ NSButton* MakeButton(NSRect* rect, NSString* title, NSView* parent) {
dialog_test::RunTest(g_handler->GetBrowser());
}
- (IBAction)testWindow:(id)sender {
if (g_handler.get() && g_handler->GetBrowserId())
window_test::RunTest(g_handler->GetBrowser());
}
- (IBAction)testPluginInfo:(id)sender {
if (g_handler.get() && g_handler->GetBrowserId())
RunPluginInfoTest(g_handler->GetBrowser());

View File

@ -23,6 +23,7 @@
#include "cefclient/resource.h"
#include "cefclient/scheme_test.h"
#include "cefclient/string_util.h"
#include "cefclient/window_test.h"
#define MAX_LOADSTRING 100
#define MAX_URL_LENGTH 255
@ -420,6 +421,10 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam,
if (browser.get())
dialog_test::RunTest(browser);
return 0;
case ID_TESTS_WINDOW: // Test window sizing/position/etc.
if (browser.get())
window_test::RunTest(browser);
return 0;
case ID_TESTS_PLUGIN_INFO: // Test plugin info
if (browser.get())
RunPluginInfoTest(browser);

View File

@ -23,6 +23,7 @@
#include "cefclient/performance_test.h"
#include "cefclient/resource_util.h"
#include "cefclient/string_util.h"
#include "cefclient/window_test.h"
// Custom menu command Ids.
@ -655,8 +656,12 @@ void ClientHandler::CreateProcessMessageDelegates(
ProcessMessageDelegateSet& delegates) {
// Create the binding test delegates.
binding_test::CreateProcessMessageDelegates(delegates);
// Create the dialog test delegates.
dialog_test::CreateProcessMessageDelegates(delegates);
// Create the window test delegates.
window_test::CreateProcessMessageDelegates(delegates);
}
// static
@ -666,6 +671,9 @@ void ClientHandler::CreateRequestDelegates(RequestDelegateSet& delegates) {
// Create the performance test delegates.
performance_test::CreateRequestDelegates(delegates);
// Create the window test delegates.
window_test::CreateRequestDelegates(delegates);
}
void ClientHandler::BuildTestMenu(CefRefPtr<CefMenuModel> model) {

View File

@ -0,0 +1,44 @@
<html>
<head>
<title>Window Test</title>
<script>
function send_message(test, params) {
// This will result in a call to OnProcessMessageReceived in window_test.cpp.
app.sendMessage('WindowTest.' + test, params);
}
function minimize() {
send_message('Minimize');
}
function maximize() {
send_message('Maximize');
}
function restore() {
minimize();
setTimeout(function() { send_message('Restore'); }, 1000);
}
function position() {
var x = parseInt(document.getElementById('x').value);
var y = parseInt(document.getElementById('y').value);
var width = parseInt(document.getElementById('width').value);
var height = parseInt(document.getElementById('height').value);
if (isNaN(x) || isNaN(y) || isNaN(width) || isNaN(height))
alert('Please specify a valid numeric value.');
else
send_message('Position', [x, y, width, height]);
}
</script>
</head>
<body>
<form>
Click a button to perform the associated window action.
<br/><input type="button" onclick="minimize();" value="Minimize">
<br/><input type="button" onclick="maximize();" value="Maximize">
<br/><input type="button" onclick="restore();" value="Restore"> (minimizes and then restores the window as topmost)
<br/><input type="button" onclick="position();" value="Set Position"> X: <input type="text" size="4" id="x" value="200"> Y: <input type="text" size="4" id="y" value="100"> Width: <input type="text" size="4" id="width" value="800"> Height: <input type="text" size="4" id="height" value="600">
</form>
</body>
</html>

View File

@ -49,6 +49,7 @@
#define ID_TESTS_END_TRACING 32781
#define ID_TESTS_PERFORMANCE 32782
#define ID_TESTS_TRANSPARENCY 32783
#define ID_TESTS_WINDOW 32784
#define IDC_STATIC -1
#define IDS_BINDING 1000
#define IDS_DIALOGS 1001
@ -58,7 +59,8 @@
#define IDS_LOGOBALL 1005
#define IDS_PERFORMANCE 1006
#define IDS_TRANSPARENCY 1007
#define IDS_XMLHTTPREQUEST 1008
#define IDS_WINDOW 1008
#define IDS_XMLHTTPREQUEST 1009
// Avoid files associated with MacOS
#define _X86_

View File

@ -51,6 +51,7 @@ CefRefPtr<CefStreamReader> GetBinaryResourceReader(const char* resource_name) {
{"localstorage.html", IDS_LOCALSTORAGE},
{"performance.html", IDS_PERFORMANCE},
{"transparency.html", IDS_TRANSPARENCY},
{"window.html", IDS_WINDOW},
{"xmlhttprequest.html", IDS_XMLHTTPREQUEST},
};

View File

@ -0,0 +1,128 @@
// Copyright (c) 2013 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 "cefclient/window_test.h"
#include <algorithm>
#include <string>
#include "include/wrapper/cef_stream_resource_handler.h"
#include "cefclient/resource_util.h"
namespace window_test {
namespace {
const char* kTestUrl = "http://tests/window";
const char* kMessagePositionName = "WindowTest.Position";
const char* kMessageMinimizeName = "WindowTest.Minimize";
const char* kMessageMaximizeName = "WindowTest.Maximize";
const char* kMessageRestoreName = "WindowTest.Restore";
// Handle messages in the browser process.
class ProcessMessageDelegate : public ClientHandler::ProcessMessageDelegate {
public:
ProcessMessageDelegate() {
}
// From ClientHandler::ProcessMessageDelegate.
virtual bool OnProcessMessageReceived(
CefRefPtr<ClientHandler> handler,
CefRefPtr<CefBrowser> browser,
CefProcessId source_process,
CefRefPtr<CefProcessMessage> message) OVERRIDE {
std::string message_name = message->GetName();
if (message_name == kMessagePositionName) {
CefRefPtr<CefListValue> args = message->GetArgumentList();
if (args->GetSize() >= 4) {
int x = args->GetInt(0);
int y = args->GetInt(1);
int width = args->GetInt(2);
int height = args->GetInt(3);
SetPos(browser->GetHost()->GetWindowHandle(), x, y, width, height);
}
return true;
} else if (message_name == kMessageMinimizeName) {
Minimize(browser->GetHost()->GetWindowHandle());
return true;
} else if (message_name == kMessageMaximizeName) {
Maximize(browser->GetHost()->GetWindowHandle());
return true;
} else if (message_name == kMessageRestoreName) {
Restore(browser->GetHost()->GetWindowHandle());
return true;
}
return false;
}
IMPLEMENT_REFCOUNTING(ProcessMessageDelegate);
};
// Handle resource loading in the browser process.
class RequestDelegate: public ClientHandler::RequestDelegate {
public:
RequestDelegate() {
}
// From ClientHandler::RequestDelegate.
virtual CefRefPtr<CefResourceHandler> GetResourceHandler(
CefRefPtr<ClientHandler> handler,
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request) OVERRIDE {
std::string url = request->GetURL();
if (url == kTestUrl) {
// Show the contents
CefRefPtr<CefStreamReader> stream =
GetBinaryResourceReader("window.html");
ASSERT(stream.get());
return new CefStreamResourceHandler("text/html", stream);
}
return NULL;
}
IMPLEMENT_REFCOUNTING(RequestDelegate);
};
} // namespace
void CreateProcessMessageDelegates(
ClientHandler::ProcessMessageDelegateSet& delegates) {
delegates.insert(new ProcessMessageDelegate);
}
void CreateRequestDelegates(ClientHandler::RequestDelegateSet& delegates) {
delegates.insert(new RequestDelegate);
}
void RunTest(CefRefPtr<CefBrowser> browser) {
// Load the test URL.
browser->GetMainFrame()->LoadURL(kTestUrl);
}
void ModifyBounds(const CefRect& display, CefRect& window) {
window.x += display.x;
window.y += display.y;
if (window.x < display.x)
window.x = display.x;
if (window.y < display.y)
window.y = display.y;
if (window.width < 100)
window.width = 100;
else if (window.width >= display.width)
window.width = display.width;
if (window.height < 100)
window.height = 100;
else if (window.height >= display.height)
window.height = display.height;
if (window.x + window.width >= display.x + display.width)
window.x = display.x + display.width - window.width;
if (window.y + window.height >= display.y + display.height)
window.y = display.y + display.height - window.height;
}
} // namespace window_test

View File

@ -0,0 +1,34 @@
// Copyright (c) 2013 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_WINDOW_TEST_H_
#define CEF_TESTS_CEFCLIENT_WINDOW_TEST_H_
#pragma once
#include "cefclient/client_app.h"
#include "cefclient/client_handler.h"
namespace window_test {
// Delegate creation. Called from ClientApp and ClientHandler.
void CreateProcessMessageDelegates(
ClientHandler::ProcessMessageDelegateSet& delegates);
void CreateRequestDelegates(ClientHandler::RequestDelegateSet& delegates);
// Run the test.
void RunTest(CefRefPtr<CefBrowser> browser);
// Fit |window| inside |display|. Coordinates are relative to the upper-left
// corner of the display.
void ModifyBounds(const CefRect& display, CefRect& window);
// Platform implementations.
void SetPos(CefWindowHandle handle, int x, int y, int width, int height);
void Minimize(CefWindowHandle handle);
void Maximize(CefWindowHandle handle);
void Restore(CefWindowHandle handle);
} // namespace window_test
#endif // CEF_TESTS_CEFCLIENT_WINDOW_TEST_H_

View File

@ -0,0 +1,72 @@
// Copyright (c) 2013 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 "cefclient/window_test.h"
#include <gtk/gtk.h>
namespace window_test {
namespace {
GtkWindow* GetWindow(CefWindowHandle handle) {
return GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(handle)));
}
bool IsMaximized(GtkWindow* window) {
GdkWindow* gdk_window = gtk_widget_get_window(GTK_WIDGET(window));
gint state = gdk_window_get_state(gdk_window);
return (state & GDK_WINDOW_STATE_MAXIMIZED) ? true : false;
}
} // namespace
void SetPos(CefWindowHandle handle, int x, int y, int width, int height) {
GtkWindow* window = GetWindow(handle);
GdkWindow* gdk_window = gtk_widget_get_window(GTK_WIDGET(window));
// Make sure the window isn't minimized or maximized.
if (IsMaximized(window))
gtk_window_unmaximize(window);
else
gtk_window_present(window);
// Retrieve information about the display that contains the window.
GdkScreen* screen = gdk_screen_get_default();
gint monitor = gdk_screen_get_monitor_at_window(screen, gdk_window);
GdkRectangle rect;
gdk_screen_get_monitor_geometry(screen, monitor, &rect);
// Make sure the window is inside the display.
CefRect display_rect(rect.x, rect.y, rect.width, rect.height);
CefRect window_rect(x, y, width, height);
ModifyBounds(display_rect, window_rect);
gdk_window_move_resize(gdk_window, window_rect.x, window_rect.y,
window_rect.width, window_rect.height);
}
void Minimize(CefWindowHandle handle) {
GtkWindow* window = GetWindow(handle);
// Unmaximize the window before minimizing so restore behaves correctly.
if (IsMaximized(window))
gtk_window_unmaximize(window);
gtk_window_iconify(window);
}
void Maximize(CefWindowHandle handle) {
gtk_window_maximize(GetWindow(handle));
}
void Restore(CefWindowHandle handle) {
GtkWindow* window = GetWindow(handle);
if (IsMaximized(window))
gtk_window_unmaximize(window);
else
gtk_window_present(window);
}
} // namespace window_test

View File

@ -0,0 +1,69 @@
// Copyright (c) 2013 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 "cefclient/window_test.h"
#import <Cocoa/Cocoa.h>
namespace window_test {
namespace {
NSWindow* GetWindow(CefWindowHandle handle) {
NSView* view = (NSView*)handle;
return [view window];
}
} // namespace
void SetPos(CefWindowHandle handle, int x, int y, int width, int height) {
NSWindow* window = GetWindow(handle);
// Make sure the window isn't minimized or maximized.
if ([window isMiniaturized])
[window deminiaturize:nil];
else if ([window isZoomed])
[window performZoom:nil];
// Retrieve information for the display that contains the window.
NSScreen* screen = [window screen];
if (screen == nil)
screen = [NSScreen mainScreen];
NSRect frame = [screen frame];
NSRect visibleFrame = [screen visibleFrame];
// Make sure the window is inside the display.
CefRect display_rect(
visibleFrame.origin.x,
frame.size.height - visibleFrame.size.height - visibleFrame.origin.y,
visibleFrame.size.width,
visibleFrame.size.height);
CefRect window_rect(x, y, width, height);
ModifyBounds(display_rect, window_rect);
NSRect newRect;
newRect.origin.x = window_rect.x;
newRect.origin.y = frame.size.height - window_rect.height - window_rect.y;
newRect.size.width = window_rect.width;
newRect.size.height = window_rect.height;
[window setFrame:newRect display:YES];
}
void Minimize(CefWindowHandle handle) {
[GetWindow(handle) performMiniaturize:nil];
}
void Maximize(CefWindowHandle handle) {
[GetWindow(handle) performZoom:nil];
}
void Restore(CefWindowHandle handle) {
NSWindow* window = GetWindow(handle);
if ([window isMiniaturized])
[window deminiaturize:nil];
else if ([window isZoomed])
[window performZoom:nil];
}
} // namespace window_test

View File

@ -0,0 +1,78 @@
// Copyright (c) 2013 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 "cefclient/window_test.h"
namespace window_test {
namespace {
// Toggles the current display state.
void Toggle(CefWindowHandle handle, UINT nCmdShow) {
HWND root_wnd = ::GetAncestor(handle, GA_ROOT);
// Retrieve current window placement information.
WINDOWPLACEMENT placement;
::GetWindowPlacement(root_wnd, &placement);
if (placement.showCmd == nCmdShow)
::ShowWindow(root_wnd, SW_RESTORE);
else
::ShowWindow(root_wnd, nCmdShow);
}
} // namespace
void SetPos(CefWindowHandle handle, int x, int y, int width, int height) {
HWND root_wnd = ::GetAncestor(handle, GA_ROOT);
// Retrieve current window placement information.
WINDOWPLACEMENT placement;
::GetWindowPlacement(root_wnd, &placement);
// Retrieve information about the display that contains the window.
HMONITOR monitor = MonitorFromRect(&placement.rcNormalPosition,
MONITOR_DEFAULTTONEAREST);
MONITORINFO info;
info.cbSize = sizeof(info);
GetMonitorInfo(monitor, &info);
// Make sure the window is inside the display.
CefRect display_rect(
info.rcWork.left,
info.rcWork.top,
info.rcWork.right - info.rcWork.left,
info.rcWork.bottom - info.rcWork.top);
CefRect window_rect(x, y, width, height);
ModifyBounds(display_rect, window_rect);
if (placement.showCmd == SW_MINIMIZE || placement.showCmd == SW_MAXIMIZE) {
// The window is currently minimized or maximized. Restore it to the desired
// position.
placement.rcNormalPosition.left = window_rect.x;
placement.rcNormalPosition.right = window_rect.x + window_rect.width;
placement.rcNormalPosition.top = window_rect.y;
placement.rcNormalPosition.bottom = window_rect.y + window_rect.height;
::SetWindowPlacement(root_wnd, &placement);
::ShowWindow(root_wnd, SW_RESTORE);
} else {
// Set the window position.
::SetWindowPos(root_wnd, NULL, window_rect.x, window_rect.y,
window_rect.width, window_rect.height, SWP_NOZORDER);
}
}
void Minimize(CefWindowHandle handle) {
Toggle(handle, SW_MINIMIZE);
}
void Maximize(CefWindowHandle handle) {
Toggle(handle, SW_MAXIMIZE);
}
void Restore(CefWindowHandle handle) {
::ShowWindow(::GetAncestor(handle, GA_ROOT), SW_RESTORE);
}
} // namespace window_test