diff --git a/cef_paths2.gypi b/cef_paths2.gypi index cb1ec4984..d4f23d9f6 100644 --- a/cef_paths2.gypi +++ b/cef_paths2.gypi @@ -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', ], }, diff --git a/tests/cefclient/cefclient.rc b/tests/cefclient/cefclient.rc index 4aa5877f5..92b58e093 100644 --- a/tests/cefclient/cefclient.rc +++ b/tests/cefclient/cefclient.rc @@ -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 diff --git a/tests/cefclient/cefclient_gtk.cpp b/tests/cefclient/cefclient_gtk.cpp index 8004daf35..c048bb863 100644 --- a/tests/cefclient/cefclient_gtk.cpp +++ b/tests/cefclient/cefclient_gtk.cpp @@ -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 @@ -123,6 +124,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()) @@ -307,6 +316,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", diff --git a/tests/cefclient/cefclient_mac.mm b/tests/cefclient/cefclient_mac.mm index d040b1425..8e6e3077d 100644 --- a/tests/cefclient/cefclient_mac.mm +++ b/tests/cefclient/cefclient_mac.mm @@ -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 g_handler; @@ -212,6 +213,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; @@ -267,6 +269,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:@""]; @@ -442,6 +447,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()); diff --git a/tests/cefclient/cefclient_win.cpp b/tests/cefclient/cefclient_win.cpp index ce0fcf1bf..f36fc5818 100644 --- a/tests/cefclient/cefclient_win.cpp +++ b/tests/cefclient/cefclient_win.cpp @@ -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 @@ -433,6 +434,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); diff --git a/tests/cefclient/client_handler.cpp b/tests/cefclient/client_handler.cpp index 68678f236..8c19550b1 100644 --- a/tests/cefclient/client_handler.cpp +++ b/tests/cefclient/client_handler.cpp @@ -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. @@ -665,8 +666,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 @@ -676,6 +681,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 model) { diff --git a/tests/cefclient/res/window.html b/tests/cefclient/res/window.html new file mode 100644 index 000000000..c901cb620 --- /dev/null +++ b/tests/cefclient/res/window.html @@ -0,0 +1,44 @@ + + +Window Test + + + +
+Click a button to perform the associated window action. +
+
+
(minimizes and then restores the window as topmost) +
X: Y: Width: Height: +
+ + diff --git a/tests/cefclient/resource.h b/tests/cefclient/resource.h index 4077a1d4d..00d042d33 100644 --- a/tests/cefclient/resource.h +++ b/tests/cefclient/resource.h @@ -50,6 +50,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 @@ -59,7 +60,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_ diff --git a/tests/cefclient/resource_util_win.cpp b/tests/cefclient/resource_util_win.cpp index d6fa7b803..135bac167 100644 --- a/tests/cefclient/resource_util_win.cpp +++ b/tests/cefclient/resource_util_win.cpp @@ -51,6 +51,7 @@ CefRefPtr 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}, }; diff --git a/tests/cefclient/window_test.cpp b/tests/cefclient/window_test.cpp new file mode 100644 index 000000000..215b8aeb2 --- /dev/null +++ b/tests/cefclient/window_test.cpp @@ -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 +#include + +#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 handler, + CefRefPtr browser, + CefProcessId source_process, + CefRefPtr message) OVERRIDE { + std::string message_name = message->GetName(); + if (message_name == kMessagePositionName) { + CefRefPtr 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 GetResourceHandler( + CefRefPtr handler, + CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request) OVERRIDE { + std::string url = request->GetURL(); + if (url == kTestUrl) { + // Show the contents + CefRefPtr 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 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 diff --git a/tests/cefclient/window_test.h b/tests/cefclient/window_test.h new file mode 100644 index 000000000..cbc89178e --- /dev/null +++ b/tests/cefclient/window_test.h @@ -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 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_ diff --git a/tests/cefclient/window_test_gtk.cpp b/tests/cefclient/window_test_gtk.cpp new file mode 100644 index 000000000..49dd5760a --- /dev/null +++ b/tests/cefclient/window_test_gtk.cpp @@ -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 + +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 diff --git a/tests/cefclient/window_test_mac.mm b/tests/cefclient/window_test_mac.mm new file mode 100644 index 000000000..c61d1b5b1 --- /dev/null +++ b/tests/cefclient/window_test_mac.mm @@ -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 + +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 diff --git a/tests/cefclient/window_test_win.cpp b/tests/cefclient/window_test_win.cpp new file mode 100644 index 000000000..2a6e44fad --- /dev/null +++ b/tests/cefclient/window_test_win.cpp @@ -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