diff --git a/cef.gyp b/cef.gyp index cd682cd97..85ccdf09d 100644 --- a/cef.gyp +++ b/cef.gyp @@ -98,11 +98,6 @@ '<@(cefclient_sources_win)', ], }], - [ 'toolkit_uses_gtk == 1', { - 'dependencies': [ - '<(DEPTH)/sandbox/sandbox.gyp:sandbox', - ], - }], [ 'OS=="mac"', { 'product_name': 'cefclient', 'dependencies': [ @@ -188,9 +183,13 @@ [ 'OS=="linux" or OS=="freebsd" or OS=="openbsd"', { 'dependencies': [ 'gtk', - 'gtkglext', 'libcef', ], + 'link_settings': { + 'libraries': [ + '-lX11', + ], + }, 'sources': [ '<@(includes_linux)', '<@(cefclient_sources_linux)', @@ -281,11 +280,6 @@ '<@(cefsimple_sources_win)', ], }], - [ 'toolkit_uses_gtk == 1', { - 'dependencies': [ - '<(DEPTH)/sandbox/sandbox.gyp:sandbox', - ], - }], [ 'OS=="mac"', { 'product_name': 'cefsimple', 'dependencies': [ @@ -369,9 +363,13 @@ }], [ 'OS=="linux" or OS=="freebsd" or OS=="openbsd"', { 'dependencies': [ - 'gtk', 'libcef', ], + 'link_settings': { + 'libraries': [ + '-lX11', + ], + }, 'sources': [ '<@(includes_linux)', '<@(cefsimple_sources_linux)', @@ -477,11 +475,6 @@ }, }, }], - [ 'toolkit_uses_gtk == 1', { - 'dependencies': [ - '<(DEPTH)/sandbox/sandbox.gyp:sandbox', - ], - }], [ 'OS=="mac"', { 'product_name': 'cef_unittests', 'dependencies': [ @@ -565,8 +558,6 @@ }], [ 'OS=="linux" or OS=="freebsd" or OS=="openbsd"', { 'dependencies': [ - '<(DEPTH)/build/linux/system.gyp:gtk', - '<(DEPTH)/build/linux/system.gyp:gtkprint', 'libcef', ], }], @@ -598,12 +589,6 @@ 'libcef', ], }], - [ 'OS=="linux" or OS=="freebsd" or OS=="openbsd"', { - 'dependencies': [ - '<(DEPTH)/build/linux/system.gyp:gtk', - '<(DEPTH)/build/linux/system.gyp:gtkprint', - ], - }], ], }, { @@ -1101,29 +1086,14 @@ ], }], [ 'OS=="linux" or OS=="freebsd" or OS=="openbsd"', { - 'dependencies':[ - '<(DEPTH)/build/linux/system.gyp:gtkprint', - ], 'sources': [ '<@(includes_linux)', - 'libcef/browser/browser_host_impl_gtk.cc', - 'libcef/browser/browser_main_gtk.cc', - 'libcef/browser/gtk_util_stub.cc', - 'libcef/browser/javascript_dialog_gtk.cc', - 'libcef/browser/menu_creator_runner_gtk.cc', - 'libcef/browser/menu_creator_runner_gtk.h', - # Include sources for context menu implementation. - '<(DEPTH)/chrome/browser/ui/gtk/gtk_custom_menu.cc', - '<(DEPTH)/chrome/browser/ui/gtk/gtk_custom_menu.h', - '<(DEPTH)/chrome/browser/ui/gtk/gtk_custom_menu_item.cc', - '<(DEPTH)/chrome/browser/ui/gtk/gtk_custom_menu_item.h', - '<(DEPTH)/chrome/browser/ui/gtk/menu_gtk.cc', - '<(DEPTH)/chrome/browser/ui/gtk/menu_gtk.h', - '<(DEPTH)/chrome/browser/ui/views/event_utils.cc', - '<(DEPTH)/chrome/browser/ui/views/event_utils.h', + 'libcef/browser/browser_host_impl_linux.cc', + 'libcef/browser/browser_main_linux.cc', + 'libcef/browser/javascript_dialog_linux.cc', + 'libcef/browser/menu_creator_runner_linux.cc', + 'libcef/browser/menu_creator_runner_linux.h', #Include sources for printing. - '<(DEPTH)/chrome/browser/printing/print_dialog_gtk.cc', - '<(DEPTH)/chrome/browser/printing/print_dialog_gtk.h', '<(DEPTH)/chrome/renderer/printing/print_web_view_helper_linux.cc', ], }], @@ -1136,7 +1106,14 @@ 'dependencies': [ '<(DEPTH)/ui/views/controls/webview/webview.gyp:webview', '<(DEPTH)/ui/views/views.gyp:views', - '<(DEPTH)/ui/views/views.gyp:views_test_support', + ], + 'sources': [ + 'libcef/browser/window_delegate_view.cc', + 'libcef/browser/window_delegate_view.h', + '<(DEPTH)/ui/views/test/desktop_test_views_delegate.cc', + '<(DEPTH)/ui/views/test/desktop_test_views_delegate.h', + '<(DEPTH)/ui/views/test/test_views_delegate.cc', + '<(DEPTH)/ui/views/test/test_views_delegate.h', ], }], ], @@ -1617,8 +1594,6 @@ [ 'OS=="linux" or OS=="freebsd" or OS=="openbsd"', { 'dependencies':[ '<(DEPTH)/base/allocator/allocator.gyp:allocator', - '<(DEPTH)/build/linux/system.gyp:gtk', - '<(DEPTH)/build/linux/system.gyp:gtkprint', ], }], ], @@ -1648,27 +1623,6 @@ ], }, }, - { - 'target_name': 'gtkglext', - 'type': 'none', - 'variables': { - # gtkglext is required by the cefclient OSR example. - 'gtk_packages': 'gtkglext-1.0', - }, - 'direct_dependent_settings': { - 'cflags': [ - ' + #include "include/internal/cef_export.h" #include "include/internal/cef_string.h" #include "include/internal/cef_string_list.h" diff --git a/include/internal/cef_linux.h b/include/internal/cef_linux.h index 6695eeb8c..405e2a198 100644 --- a/include/internal/cef_linux.h +++ b/include/internal/cef_linux.h @@ -108,8 +108,12 @@ struct CefWindowInfoTraits { static inline void set(const struct_type* src, struct_type* target, bool copy) { - target->parent_widget = src->parent_widget; - target->widget = src->widget; + target->x = src->x; + target->y = src->y; + target->width = src->width; + target->height = src->height; + target->parent_window = src->parent_window; + target->window = src->window; } }; @@ -123,10 +127,15 @@ class CefWindowInfo : public CefStructBase { explicit CefWindowInfo(const CefWindowInfo& r) : parent(r) {} /// - // Create the browser as a child widget. + // Create the browser as a child window. /// - void SetAsChild(CefWindowHandle parent) { - parent_widget = parent; + void SetAsChild(CefWindowHandle parent, + const CefRect& windowRect) { + parent_window = parent; + x = windowRect.x; + y = windowRect.y; + width = windowRect.width; + height = windowRect.height; } }; diff --git a/include/internal/cef_types_linux.h b/include/internal/cef_types_linux.h index 4c43d2e48..5127f3c76 100644 --- a/include/internal/cef_types_linux.h +++ b/include/internal/cef_types_linux.h @@ -35,17 +35,31 @@ #include "include/internal/cef_build.h" #if defined(OS_LINUX) -#include + +typedef union _XEvent XEvent; +typedef struct _XDisplay XDisplay; + +#include "include/internal/cef_export.h" #include "include/internal/cef_string.h" +// Handle types. +#define cef_cursor_handle_t unsigned long +#define cef_event_handle_t XEvent* +#define cef_window_handle_t unsigned long + +#define kNullCursorHandle 0 +#define kNullEventHandle NULL +#define kNullWindowHandle 0 + #ifdef __cplusplus extern "C" { #endif -// Handle types. -#define cef_cursor_handle_t GdkCursor* -#define cef_event_handle_t GdkEvent* -#define cef_window_handle_t GtkWidget* +/// +// Return the singleton X11 display shared with Chromium. The display is not +// thread-safe and must only be accessed on the browser process UI thread. +/// +CEF_EXPORT XDisplay* cef_get_xdisplay(); /// // Structure representing CefExecuteProcess arguments. @@ -59,15 +73,20 @@ typedef struct _cef_main_args_t { // Class representing window information. /// typedef struct _cef_window_info_t { - /// - // Pointer for the parent widget. - /// - cef_window_handle_t parent_widget; + unsigned int x; + unsigned int y; + unsigned int width; + unsigned int height; /// - // Pointer for the new browser widget. Only used with windowed rendering. + // Pointer for the parent window. /// - cef_window_handle_t widget; + cef_window_handle_t parent_window; + + /// + // Pointer for the new browser window. Only used with windowed rendering. + /// + cef_window_handle_t window; } cef_window_info_t; #ifdef __cplusplus diff --git a/include/internal/cef_types_mac.h b/include/internal/cef_types_mac.h index e29fc43c4..580172231 100644 --- a/include/internal/cef_types_mac.h +++ b/include/internal/cef_types_mac.h @@ -57,6 +57,10 @@ struct NSView; #define cef_window_handle_t void* #endif +#define kNullCursorHandle NULL +#define kNullEventHandle NULL +#define kNullWindowHandle NULL + #ifdef __cplusplus extern "C" { #endif diff --git a/include/internal/cef_types_win.h b/include/internal/cef_types_win.h index 7302c45c9..c4e020268 100644 --- a/include/internal/cef_types_win.h +++ b/include/internal/cef_types_win.h @@ -38,15 +38,19 @@ #include #include "include/internal/cef_string.h" -#ifdef __cplusplus -extern "C" { -#endif - // Handle types. #define cef_cursor_handle_t HCURSOR #define cef_event_handle_t MSG* #define cef_window_handle_t HWND +#define kNullCursorHandle NULL +#define kNullEventHandle NULL +#define kNullWindowHandle NULL + +#ifdef __cplusplus +extern "C" { +#endif + /// // Structure representing CefExecuteProcess arguments. /// diff --git a/libcef/browser/browser_host_impl.cc b/libcef/browser/browser_host_impl.cc index 146aaa88d..0b519e851 100644 --- a/libcef/browser/browser_host_impl.cc +++ b/libcef/browser/browser_host_impl.cc @@ -319,8 +319,8 @@ CefRefPtr CefBrowserHost::CreateBrowserSync( } CefRefPtr browser = - CefBrowserHostImpl::Create(windowInfo, client, url, settings, NULL, false, - request_context); + CefBrowserHostImpl::Create(windowInfo, client, url, settings, + kNullWindowHandle, false, request_context); return browser.get(); } @@ -362,7 +362,7 @@ CefRefPtr CefBrowserHostImpl::CreateInternal( DCHECK(browser_info.get()); // If |opener| is non-NULL it must be a popup window. - DCHECK(opener == NULL || browser_info->is_popup()); + DCHECK(opener == kNullWindowHandle || browser_info->is_popup()); if (!web_contents) { CefBrowserContext* browser_context = NULL; @@ -1738,7 +1738,7 @@ void CefBrowserHostImpl::WebContentsCreated( content::RenderViewHost* view_host = new_contents->GetRenderViewHost(); content::RenderFrameHost* main_frame_host = new_contents->GetMainFrame(); - CefWindowHandle opener = NULL; + CefWindowHandle opener = kNullWindowHandle; scoped_refptr info = CefContentBrowserClient::Get()->GetOrCreateBrowserInfo( view_host->GetProcess()->GetID(), @@ -2161,6 +2161,9 @@ CefBrowserHostImpl::CefBrowserHostImpl( #if defined(USE_AURA) window_widget_ = NULL; #endif +#if defined(USE_X11) + window_x11_ = NULL; +#endif DCHECK(!browser_info_->browser().get()); browser_info_->set_browser(this); diff --git a/libcef/browser/browser_host_impl.h b/libcef/browser/browser_host_impl.h index 49d851f52..14c851d66 100644 --- a/libcef/browser/browser_host_impl.h +++ b/libcef/browser/browser_host_impl.h @@ -55,6 +55,10 @@ class Widget; } #endif +#if defined(USE_X11) +class CefWindowX11; +#endif + struct Cef_Request_Params; struct Cef_Response_Params; class CefBrowserInfo; @@ -589,6 +593,9 @@ class CefBrowserHostImpl : public CefBrowserHost, // associated root window is destroyed. views::Widget* window_widget_; #endif // defined(USE_AURA) +#if defined(USE_X11) + CefWindowX11* window_x11_; +#endif // defined(USE_X11) IMPLEMENT_REFCOUNTING(CefBrowserHostImpl); DISALLOW_EVIL_CONSTRUCTORS(CefBrowserHostImpl); diff --git a/libcef/browser/browser_host_impl_gtk.cc b/libcef/browser/browser_host_impl_gtk.cc deleted file mode 100644 index 1350ffbb2..000000000 --- a/libcef/browser/browser_host_impl_gtk.cc +++ /dev/null @@ -1,557 +0,0 @@ -// Copyright (c) 2012 The Chromium Embedded Framework Authors. -// Portions copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "libcef/browser/browser_host_impl.h" - -#include -#include - -#include "libcef/browser/thread_util.h" - -#include "base/bind.h" -#include "base/strings/utf_string_conversions.h" -#include "content/public/browser/native_web_keyboard_event.h" -#include "content/public/browser/web_contents_view.h" -#include "content/public/common/file_chooser_params.h" -#include "content/public/common/renderer_preferences.h" -#include "grit/cef_strings.h" -#include "grit/ui_strings.h" -#include "net/base/mime_util.h" -#include "third_party/WebKit/public/web/gtk/WebInputEventFactory.h" -#include "third_party/WebKit/public/web/WebInputEvent.h" -#include "ui/base/l10n/l10n_util.h" - -namespace { - -void DestroyBrowser(CefRefPtr browser) { - // Force the browser to be destroyed and release the reference added in - // PlatformCreateWindow(). - browser->WindowDestroyed(); -} - -void browser_destroy(GtkWidget* widget, CefBrowserHostImpl* browser) { - // Destroy the browser host after window destruction is complete. - CEF_POST_TASK(CEF_UIT, base::Bind(DestroyBrowser, browser)); -} - -void window_destroy(GtkWidget* widget, gpointer data) { -} - -gboolean window_delete_event(GtkWidget* widget, GdkEvent* event, - CefBrowserHostImpl* browser) { - // Protect against multiple requests to close while the close is pending. - if (browser && browser->destruction_state() <= - CefBrowserHostImpl::DESTRUCTION_STATE_PENDING) { - if (browser->destruction_state() == - CefBrowserHostImpl::DESTRUCTION_STATE_NONE) { - // Request that the browser close. - browser->CloseBrowser(false); - } - - // Cancel the close. - return TRUE; - } - - // Allow the close. - return FALSE; -} - -std::string GetDescriptionFromMimeType(const std::string& mime_type) { - // Check for wild card mime types and return an appropriate description. - static const struct { - const char* mime_type; - int string_id; - } kWildCardMimeTypes[] = { - { "audio", IDS_APP_AUDIO_FILES }, - { "image", IDS_APP_IMAGE_FILES }, - { "text", IDS_APP_TEXT_FILES }, - { "video", IDS_APP_VIDEO_FILES }, - }; - - for (size_t i = 0; - i < sizeof(kWildCardMimeTypes) / sizeof(kWildCardMimeTypes[0]); ++i) { - if (mime_type == std::string(kWildCardMimeTypes[i].mime_type) + "/*") - return l10n_util::GetStringUTF8(kWildCardMimeTypes[i].string_id); - } - - return std::string(); -} - -void AddFiltersForAcceptTypes(GtkFileChooser* chooser, - const std::vector& accept_types, - bool include_all_files) { - bool has_filter = false; - - for (size_t i = 0; i < accept_types.size(); ++i) { - std::string ascii_type = base::UTF16ToASCII(accept_types[i]); - if (ascii_type.length()) { - // Just treat as extension if contains '.' as the first character. - if (ascii_type[0] == '.') { - GtkFileFilter* filter = gtk_file_filter_new(); - std::string pattern = "*" + ascii_type; - gtk_file_filter_add_pattern(filter, pattern.c_str()); - gtk_file_filter_set_name(filter, pattern.c_str()); - gtk_file_chooser_add_filter(chooser, filter); - if (!has_filter) - has_filter = true; - } else { - // Otherwise convert mime type to one or more extensions. - GtkFileFilter* filter = NULL; - std::string description = GetDescriptionFromMimeType(ascii_type); - bool description_from_ext = description.empty(); - - std::vector ext; - net::GetExtensionsForMimeType(ascii_type, &ext); - for (size_t x = 0; x < ext.size(); ++x) { - if (!filter) - filter = gtk_file_filter_new(); - std::string pattern = "*." + ext[x]; - gtk_file_filter_add_pattern(filter, pattern.c_str()); - - if (description_from_ext) { - if (x != 0) - description += ";"; - description += pattern; - } - } - - if (filter) { - gtk_file_filter_set_name(filter, description.c_str()); - gtk_file_chooser_add_filter(chooser, filter); - if (!has_filter) - has_filter = true; - } - } - } - } - - // Add the *.* filter, but only if we have added other filters (otherwise it - // is implied). - if (include_all_files && has_filter) { - GtkFileFilter* filter = gtk_file_filter_new(); - gtk_file_filter_add_pattern(filter, "*"); - gtk_file_filter_set_name(filter, - l10n_util::GetStringUTF8(IDS_SAVEAS_ALL_FILES).c_str()); - gtk_file_chooser_add_filter(chooser, filter); - } -} - -bool RunFileDialog(const content::FileChooserParams& params, - CefWindowHandle widget, - std::vector* files) { - GtkFileChooserAction action; - const gchar* accept_button; - if (params.mode == content::FileChooserParams::Open || - params.mode == content::FileChooserParams::OpenMultiple) { - action = GTK_FILE_CHOOSER_ACTION_OPEN; - accept_button = GTK_STOCK_OPEN; - } else if (params.mode == content::FileChooserParams::Save) { - action = GTK_FILE_CHOOSER_ACTION_SAVE; - accept_button = GTK_STOCK_SAVE; - } else { - NOTREACHED(); - return false; - } - - // Consider default file name if any. - base::FilePath default_file_name(params.default_file_name); - - std::string base_name; - if (!default_file_name.empty()) - base_name = default_file_name.BaseName().value(); - - std::string title; - if (!params.title.empty()) { - title = base::UTF16ToUTF8(params.title); - } else { - int string_id = 0; - switch (params.mode) { - case content::FileChooserParams::Open: - string_id = IDS_OPEN_FILE_DIALOG_TITLE; - break; - case content::FileChooserParams::OpenMultiple: - string_id = IDS_OPEN_FILES_DIALOG_TITLE; - break; - case content::FileChooserParams::Save: - string_id = IDS_SAVE_AS_DIALOG_TITLE; - break; - default: - break; - } - title = l10n_util::GetStringUTF8(string_id); - } - - GtkWidget* window = gtk_widget_get_toplevel(GTK_WIDGET(widget)); - GtkWidget* dialog = gtk_file_chooser_dialog_new( - title.c_str(), - GTK_WINDOW(window), - action, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - accept_button, GTK_RESPONSE_ACCEPT, - NULL); - - if (params.mode == content::FileChooserParams::OpenMultiple) { - gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), TRUE); - } else if (params.mode == content::FileChooserParams::Save) { - gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), - TRUE); - } - - if (params.mode == content::FileChooserParams::Save && !base_name.empty()) { - gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), - base_name.c_str()); - } - - AddFiltersForAcceptTypes(GTK_FILE_CHOOSER(dialog), params.accept_types, true); - - bool success = false; - - if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { - if (params.mode == content::FileChooserParams::Open || - params.mode == content::FileChooserParams::Save) { - char* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); - files->push_back(base::FilePath(filename)); - success = true; - } else if (params.mode == content::FileChooserParams::OpenMultiple) { - GSList* filenames = - gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog)); - if (filenames) { - for (GSList* iter = filenames; iter != NULL; - iter = g_slist_next(iter)) { - base::FilePath path(static_cast(iter->data)); - g_free(iter->data); - files->push_back(path); - } - g_slist_free(filenames); - success = true; - } - } - } - - gtk_widget_destroy(dialog); - - return success; -} - -// Returns the number of seconds since system boot. -long GetSystemUptime() { - struct sysinfo info; - if (sysinfo(&info) == 0) - return info.uptime; - return 0; -} - -} // namespace - -bool CefBrowserHostImpl::PlatformCreateWindow() { - GtkWidget* window; - GtkWidget* parentView = window_info_.parent_widget; - - if (parentView == NULL) { - // Create a new window. - window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_default_size(GTK_WINDOW(window), 800, 600); - - parentView = gtk_vbox_new(FALSE, 0); - - gtk_container_add(GTK_CONTAINER(window), parentView); - gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); - gtk_widget_show_all(GTK_WIDGET(window)); - - g_signal_connect(G_OBJECT(window), "destroy", - G_CALLBACK(window_destroy), NULL); - g_signal_connect(G_OBJECT(window), "delete_event", - G_CALLBACK(window_delete_event), this); - - window_info_.parent_widget = parentView; - } - - // Add a reference that will be released in the destroy handler. - AddRef(); - - // Parent the TabContents to the browser window. - window_info_.widget = web_contents_->GetView()->GetNativeView(); - gtk_container_add(GTK_CONTAINER(window_info_.parent_widget), - window_info_.widget); - - g_signal_connect(G_OBJECT(window_info_.widget), "destroy", - G_CALLBACK(browser_destroy), this); - - // As an additional requirement on Linux, we must set the colors for the - // render widgets in webkit. - content::RendererPreferences* prefs = - web_contents_->GetMutableRendererPrefs(); - prefs->focus_ring_color = SkColorSetARGB(255, 229, 151, 0); - prefs->thumb_active_color = SkColorSetRGB(244, 244, 244); - prefs->thumb_inactive_color = SkColorSetRGB(234, 234, 234); - prefs->track_color = SkColorSetRGB(211, 211, 211); - - prefs->active_selection_bg_color = SkColorSetRGB(30, 144, 255); - prefs->active_selection_fg_color = SK_ColorWHITE; - prefs->inactive_selection_bg_color = SkColorSetRGB(200, 200, 200); - prefs->inactive_selection_fg_color = SkColorSetRGB(50, 50, 50); - - return true; -} - -void CefBrowserHostImpl::PlatformCloseWindow() { - if (window_info_.widget != NULL) { - GtkWidget* window = - gtk_widget_get_toplevel(GTK_WIDGET(window_info_.widget)); - - // Send the "delete_event" signal. - GdkEvent event; - memset(&event, 0, sizeof(GdkEvent)); - event.any.type = GDK_DELETE; - event.any.send_event = TRUE; - event.any.window = window->window; - gtk_main_do_event(&event); - } -} - -void CefBrowserHostImpl::PlatformSizeTo(int width, int height) { - if (window_info_.widget != NULL) { - GtkWidget* window = - gtk_widget_get_toplevel(GTK_WIDGET(window_info_.widget)); - gtk_widget_set_size_request(window, width, height); - } -} - -CefWindowHandle CefBrowserHostImpl::PlatformGetWindowHandle() { - return window_info_.widget; -} - -bool CefBrowserHostImpl::PlatformViewText(const std::string& text) { - CEF_REQUIRE_UIT(); - - char buff[] = "/tmp/CEFSourceXXXXXX"; - int fd = mkstemp(buff); - - if (fd == -1) - return false; - - FILE* srcOutput = fdopen(fd, "w+"); - if (!srcOutput) - return false; - - if (fputs(text.c_str(), srcOutput) < 0) { - fclose(srcOutput); - return false; - } - - fclose(srcOutput); - - std::string newName(buff); - newName.append(".txt"); - if (rename(buff, newName.c_str()) != 0) - return false; - - std::string openCommand("xdg-open "); - openCommand += newName; - - if (system(openCommand.c_str()) != 0) - return false; - - return true; -} - -void CefBrowserHostImpl::PlatformHandleKeyboardEvent( - const content::NativeWebKeyboardEvent& event) { - // TODO(cef): Is something required here to handle shortcut keys? -} - -void CefBrowserHostImpl::PlatformRunFileChooser( - const content::FileChooserParams& params, - RunFileChooserCallback callback) { - std::vector files; - - if (params.mode == content::FileChooserParams::Open || - params.mode == content::FileChooserParams::OpenMultiple || - params.mode == content::FileChooserParams::Save) { - ::RunFileDialog(params, PlatformGetWindowHandle(), &files); - } else { - NOTIMPLEMENTED(); - } - - callback.Run(files); -} - -void CefBrowserHostImpl::PlatformHandleExternalProtocol(const GURL& url) { -} - -void CefBrowserHostImpl::PlatformTranslateKeyEvent( - content::NativeWebKeyboardEvent& result, - const CefKeyEvent& key_event) { - // Use a synthetic GdkEventKey in order to obtain the windowsKeyCode member - // from the NativeWebKeyboardEvent constructor. This is the only member - // which cannot be easily translated (without hardcoding keyCodes). - - guint state = 0; - if (key_event.modifiers & EVENTFLAG_SHIFT_DOWN) - state |= GDK_SHIFT_MASK; - if (key_event.modifiers & EVENTFLAG_CAPS_LOCK_ON) - state |= GDK_LOCK_MASK; - if (key_event.modifiers & EVENTFLAG_CONTROL_DOWN) - state |= GDK_CONTROL_MASK; - if (key_event.modifiers & EVENTFLAG_ALT_DOWN) - state |= GDK_MOD1_MASK; - if (key_event.modifiers & EVENTFLAG_LEFT_MOUSE_BUTTON) - state |= GDK_BUTTON1_MASK; - if (key_event.modifiers & EVENTFLAG_MIDDLE_MOUSE_BUTTON) - state |= GDK_BUTTON2_MASK; - if (key_event.modifiers & EVENTFLAG_RIGHT_MOUSE_BUTTON) - state |= GDK_BUTTON3_MASK; - - GdkKeymap* keymap = gdk_keymap_get_for_display(gdk_display_get_default()); - - GdkKeymapKey *keys = NULL; - gint n_keys = 0; - if (gdk_keymap_get_entries_for_keyval(keymap, key_event.native_key_code, - &keys, &n_keys)) { - GdkEventKey event; - event.type = GDK_KEY_PRESS; - event.window = NULL; - event.send_event = 0; - event.time = 0; - event.state = state; - event.keyval = key_event.native_key_code; - event.length = 0; - event.string = NULL; - event.hardware_keycode = keys[0].keycode; - event.group = keys[0].group; - event.is_modifier = 0; - g_free(keys); - result = content::NativeWebKeyboardEvent( - reinterpret_cast(&event)); - } - - result.timeStampSeconds = GetSystemUptime(); - - switch (key_event.type) { - case KEYEVENT_RAWKEYDOWN: - case KEYEVENT_KEYDOWN: - result.type = blink::WebInputEvent::RawKeyDown; - break; - case KEYEVENT_KEYUP: - result.type = blink::WebInputEvent::KeyUp; - break; - case KEYEVENT_CHAR: - result.type = blink::WebInputEvent::Char; - break; - default: - NOTREACHED(); - } -} - -void CefBrowserHostImpl::PlatformTranslateClickEvent( - blink::WebMouseEvent& result, - const CefMouseEvent& mouse_event, - MouseButtonType type, - bool mouseUp, int clickCount) { - PlatformTranslateMouseEvent(result, mouse_event); - - switch (type) { - case MBT_LEFT: - result.type = mouseUp ? blink::WebInputEvent::MouseUp : - blink::WebInputEvent::MouseDown; - result.button = blink::WebMouseEvent::ButtonLeft; - break; - case MBT_MIDDLE: - result.type = mouseUp ? blink::WebInputEvent::MouseUp : - blink::WebInputEvent::MouseDown; - result.button = blink::WebMouseEvent::ButtonMiddle; - break; - case MBT_RIGHT: - result.type = mouseUp ? blink::WebInputEvent::MouseUp : - blink::WebInputEvent::MouseDown; - result.button = blink::WebMouseEvent::ButtonRight; - break; - default: - NOTREACHED(); - } - - result.clickCount = clickCount; -} - -void CefBrowserHostImpl::PlatformTranslateMoveEvent( - blink::WebMouseEvent& result, - const CefMouseEvent& mouse_event, - bool mouseLeave) { - PlatformTranslateMouseEvent(result, mouse_event); - - if (!mouseLeave) { - result.type = blink::WebInputEvent::MouseMove; - if (mouse_event.modifiers & EVENTFLAG_LEFT_MOUSE_BUTTON) - result.button = blink::WebMouseEvent::ButtonLeft; - else if (mouse_event.modifiers & EVENTFLAG_MIDDLE_MOUSE_BUTTON) - result.button = blink::WebMouseEvent::ButtonMiddle; - else if (mouse_event.modifiers & EVENTFLAG_RIGHT_MOUSE_BUTTON) - result.button = blink::WebMouseEvent::ButtonRight; - else - result.button = blink::WebMouseEvent::ButtonNone; - } else { - result.type = blink::WebInputEvent::MouseLeave; - result.button = blink::WebMouseEvent::ButtonNone; - } - - result.clickCount = 0; -} - -void CefBrowserHostImpl::PlatformTranslateWheelEvent( - blink::WebMouseWheelEvent& result, - const CefMouseEvent& mouse_event, - int deltaX, int deltaY) { - result = blink::WebMouseWheelEvent(); - PlatformTranslateMouseEvent(result, mouse_event); - - result.type = blink::WebInputEvent::MouseWheel; - - static const double scrollbarPixelsPerGtkTick = 40.0; - result.deltaX = deltaX; - result.deltaY = deltaY; - result.wheelTicksX = result.deltaX / scrollbarPixelsPerGtkTick; - result.wheelTicksY = result.deltaY / scrollbarPixelsPerGtkTick; - result.hasPreciseScrollingDeltas = true; - - // Unless the phase and momentumPhase are passed in as parameters to this - // function, there is no way to know them - result.phase = blink::WebMouseWheelEvent::PhaseNone; - result.momentumPhase = blink::WebMouseWheelEvent::PhaseNone; - - if (mouse_event.modifiers & EVENTFLAG_LEFT_MOUSE_BUTTON) - result.button = blink::WebMouseEvent::ButtonLeft; - else if (mouse_event.modifiers & EVENTFLAG_MIDDLE_MOUSE_BUTTON) - result.button = blink::WebMouseEvent::ButtonMiddle; - else if (mouse_event.modifiers & EVENTFLAG_RIGHT_MOUSE_BUTTON) - result.button = blink::WebMouseEvent::ButtonRight; - else - result.button = blink::WebMouseEvent::ButtonNone; -} - -void CefBrowserHostImpl::PlatformTranslateMouseEvent( - blink::WebMouseEvent& result, - const CefMouseEvent& mouse_event) { - // position - result.x = mouse_event.x; - result.y = mouse_event.y; - result.windowX = result.x; - result.windowY = result.y; - result.globalX = result.x; - result.globalY = result.y; - - // global position - GtkWidget* window = gtk_widget_get_toplevel(GetWindowHandle()); - GdkWindow* gdk_window = gtk_widget_get_window(window); - gint xorigin, yorigin; - gdk_window_get_root_origin(gdk_window, &xorigin, &yorigin); - result.globalX = xorigin + result.x; - result.globalY = yorigin + result.y; - - // modifiers - result.modifiers |= TranslateModifiers(mouse_event.modifiers); - - // timestamp - result.timeStampSeconds = GetSystemUptime(); -} diff --git a/libcef/browser/browser_host_impl_linux.cc b/libcef/browser/browser_host_impl_linux.cc new file mode 100644 index 000000000..2b0e8c46d --- /dev/null +++ b/libcef/browser/browser_host_impl_linux.cc @@ -0,0 +1,562 @@ +// Copyright (c) 2014 The Chromium Embedded Framework Authors. +// Portions copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "libcef/browser/browser_host_impl.h" + +#include +#include +#include +#include +#include + +#include "libcef/browser/context.h" +#include "libcef/browser/window_delegate_view.h" +#include "libcef/browser/thread_util.h" + +#include "base/bind.h" +#include "content/public/browser/native_web_keyboard_event.h" +#include "content/public/browser/web_contents_view.h" +#include "content/public/common/file_chooser_params.h" +#include "content/public/common/renderer_preferences.h" +#include "third_party/WebKit/public/web/gtk/WebInputEventFactory.h" +#include "third_party/WebKit/public/web/WebInputEvent.h" +#include "ui/events/platform/platform_event_dispatcher.h" +#include "ui/events/platform/x11/x11_event_source.h" +#include "ui/gfx/x/x11_atom_cache.h" +#include "ui/views/widget/widget.h" + +namespace { + +// Returns the number of seconds since system boot. +long GetSystemUptime() { + struct sysinfo info; + if (sysinfo(&info) == 0) + return info.uptime; + return 0; +} + +const char* kAtomsToCache[] = { + "WM_DELETE_WINDOW", + "WM_PROTOCOLS", + "_NET_WM_PING", + "_NET_WM_PID", + NULL +}; + +::Window FindEventTarget(const base::NativeEvent& xev) { + ::Window target = xev->xany.window; + if (xev->type == GenericEvent) + target = static_cast(xev->xcookie.data)->event; + return target; +} + +::Window FindChild(::Display* display, ::Window window) { + ::Window root; + ::Window parent; + ::Window* children; + unsigned int nchildren; + if (XQueryTree(display, window, &root, &parent, &children, &nchildren)) { + DCHECK_EQ(1U, nchildren); + return children[0]; + } + return None; +} + +} // namespace + +#if defined(USE_X11) +CEF_EXPORT XDisplay* cef_get_xdisplay() { + if (!CEF_CURRENTLY_ON(CEF_UIT)) + return NULL; + return gfx::GetXDisplay(); +} +#endif + +// Object wrapper for an X11 Window. +// Based on WindowTreeHostX11 and DesktopWindowTreeHostX11. +class CefWindowX11 : public ui::PlatformEventDispatcher { + public: + CefWindowX11(CefRefPtr browser, + ::Window parent_xwindow, + const gfx::Rect& bounds) + : browser_(browser), + xdisplay_(gfx::GetXDisplay()), + parent_xwindow_(parent_xwindow), + xwindow_(0), + window_mapped_(false), + bounds_(bounds), + atom_cache_(xdisplay_, kAtomsToCache) { + if (parent_xwindow_ == None) + parent_xwindow_ = DefaultRootWindow(xdisplay_); + + XSetWindowAttributes swa; + memset(&swa, 0, sizeof(swa)); + swa.background_pixmap = None; + swa.override_redirect = false; + xwindow_ = XCreateWindow( + xdisplay_, parent_xwindow_, + bounds.x(), bounds.y(), bounds.width(), bounds.height(), + 0, // border width + CopyFromParent, // depth + InputOutput, + CopyFromParent, // visual + CWBackPixmap | CWOverrideRedirect, + &swa); + + if (ui::PlatformEventSource::GetInstance()) + ui::PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this); + + long event_mask = FocusChangeMask | StructureNotifyMask | PropertyChangeMask; + XSelectInput(xdisplay_, xwindow_, event_mask); + XFlush(xdisplay_); + + // TODO(erg): We currently only request window deletion events. We also + // should listen for activation events and anything else that GTK+ listens + // for, and do something useful. + ::Atom protocols[2]; + protocols[0] = atom_cache_.GetAtom("WM_DELETE_WINDOW"); + protocols[1] = atom_cache_.GetAtom("_NET_WM_PING"); + XSetWMProtocols(xdisplay_, xwindow_, protocols, 2); + + // We need a WM_CLIENT_MACHINE and WM_LOCALE_NAME value so we integrate with + // the desktop environment. + XSetWMProperties(xdisplay_, xwindow_, NULL, NULL, NULL, 0, NULL, NULL, NULL); + + // Likewise, the X server needs to know this window's pid so it knows which + // program to kill if the window hangs. + // XChangeProperty() expects "pid" to be long. + COMPILE_ASSERT(sizeof(long) >= sizeof(pid_t), pid_t_bigger_than_long); + long pid = getpid(); + XChangeProperty(xdisplay_, + xwindow_, + atom_cache_.GetAtom("_NET_WM_PID"), + XA_CARDINAL, + 32, + PropModeReplace, + reinterpret_cast(&pid), 1); + + // Allow subclasses to create and cache additional atoms. + atom_cache_.allow_uncached_atoms(); + } + + virtual ~CefWindowX11() { + DCHECK(!xwindow_); + if (ui::PlatformEventSource::GetInstance()) + ui::PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this); + } + + void Close() { + XEvent ev = {0}; + ev.xclient.type = ClientMessage; + ev.xclient.window = xwindow_; + ev.xclient.message_type = atom_cache_.GetAtom("WM_PROTOCOLS"); + ev.xclient.format = 32; + ev.xclient.data.l[0] = atom_cache_.GetAtom("WM_DELETE_WINDOW"); + ev.xclient.data.l[1] = CurrentTime; + XSendEvent(xdisplay_, xwindow_, False, NoEventMask, &ev); + } + + void Show() { + if (xwindow_ == None) + return; + + if (!window_mapped_) { + // Before we map the window, set size hints. Otherwise, some window managers + // will ignore toplevel XMoveWindow commands. + XSizeHints size_hints; + size_hints.flags = PPosition | PWinGravity; + size_hints.x = bounds_.x(); + size_hints.y = bounds_.y(); + // Set StaticGravity so that the window position is not affected by the + // frame width when running with window manager. + size_hints.win_gravity = StaticGravity; + XSetWMNormalHints(xdisplay_, xwindow_, &size_hints); + + XMapWindow(xdisplay_, xwindow_); + + // We now block until our window is mapped. Some X11 APIs will crash and + // burn if passed |xwindow_| before the window is mapped, and XMapWindow is + // asynchronous. + if (ui::X11EventSource::GetInstance()) + ui::X11EventSource::GetInstance()->BlockUntilWindowMapped(xwindow_); + window_mapped_ = true; + } + } + + void Hide() { + if (xwindow_ == None) + return; + + if (window_mapped_) { + XWithdrawWindow(xdisplay_, xwindow_, 0); + window_mapped_ = false; + } + } + + void SetBounds(const gfx::Rect& bounds) { + if (xwindow_ == None) + return; + + bool origin_changed = bounds_.origin() != bounds.origin(); + bool size_changed = bounds_.size() != bounds.size(); + XWindowChanges changes = {0}; + unsigned value_mask = 0; + + if (size_changed) { + changes.width = bounds.width(); + changes.height = bounds.height(); + value_mask = CWHeight | CWWidth; + } + + if (origin_changed) { + changes.x = bounds.x(); + changes.y = bounds.y(); + value_mask |= CWX | CWY; + } + + if (value_mask) + XConfigureWindow(xdisplay_, xwindow_, value_mask, &changes); + } + + // ui::PlatformEventDispatcher methods: + virtual bool CanDispatchEvent(const ui::PlatformEvent& event) OVERRIDE { + ::Window target = FindEventTarget(event); + return target == xwindow_; + } + + virtual uint32_t DispatchEvent(const ui::PlatformEvent& event) OVERRIDE { + XEvent* xev = event; + switch (xev->type) { + case ConfigureNotify: { + DCHECK_EQ(xwindow_, xev->xconfigure.event); + DCHECK_EQ(xwindow_, xev->xconfigure.window); + // It's possible that the X window may be resized by some other means + // than from within Aura (e.g. the X window manager can change the + // size). Make sure the root window size is maintained properly. + gfx::Rect bounds(xev->xconfigure.x, xev->xconfigure.y, + xev->xconfigure.width, xev->xconfigure.height); + bounds_ = bounds; + + ::Window child = FindChild(xdisplay_, xwindow_); + if (child) { + // Resize the child DesktopWindowTreeHostX11 to match this window. + XWindowChanges changes = {0}; + changes.width = bounds.width(); + changes.height = bounds.height(); + XConfigureWindow(xdisplay_, child, CWHeight | CWWidth, &changes); + } + break; + } + case ClientMessage: { + Atom message_type = static_cast(xev->xclient.data.l[0]); + if (message_type == atom_cache_.GetAtom("WM_DELETE_WINDOW")) { + // We have received a close message from the window manager. + if (browser_->destruction_state() <= + CefBrowserHostImpl::DESTRUCTION_STATE_PENDING) { + if (browser_->destruction_state() == + CefBrowserHostImpl::DESTRUCTION_STATE_NONE) { + // Request that the browser close. + browser_->CloseBrowser(false); + } + + // Cancel the close. + } else { + // Allow the close. + XDestroyWindow(xdisplay_, xwindow_); + } + } else if (message_type == atom_cache_.GetAtom("_NET_WM_PING")) { + XEvent reply_event = *xev; + reply_event.xclient.window = parent_xwindow_; + + XSendEvent(xdisplay_, + reply_event.xclient.window, + False, + SubstructureRedirectMask | SubstructureNotifyMask, + &reply_event); + XFlush(xdisplay_); + } + break; + } + case DestroyNotify: + xwindow_ = None; + + // Force the browser to be destroyed and release the reference added + // in PlatformCreateWindow(). + browser_->WindowDestroyed(); + + delete this; + break; + case FocusIn: + // This message is recieved first followed by a "_NET_ACTIVE_WINDOW" + // message sent to the root window. When X11DesktopHandler handles the + // "_NET_ACTIVE_WINDOW" message it will erroneously mark the WebView + // (hosted in a DesktopWindowTreeHostX11) as unfocused. Use a delayed + // task here to restore the WebView's focus state. + CEF_POST_DELAYED_TASK(CEF_UIT, + base::Bind(&CefBrowserHostImpl::OnSetFocus, browser_, + FOCUS_SOURCE_SYSTEM), + 100); + break; + } + + return ui::POST_DISPATCH_STOP_PROPAGATION; + } + + ::Window xwindow() const { return xwindow_; } + gfx::Rect bounds() const { return bounds_; } + + private: + CefRefPtr browser_; + + // The display and the native X window hosting the root window. + XDisplay* xdisplay_; + ::Window parent_xwindow_; + ::Window xwindow_; + + // Is the window mapped to the screen? + bool window_mapped_; + + // The bounds of |xwindow_|. + gfx::Rect bounds_; + + ui::X11AtomCache atom_cache_; + + DISALLOW_COPY_AND_ASSIGN(CefWindowX11); +}; + + +bool CefBrowserHostImpl::PlatformCreateWindow() { + DCHECK(!window_x11_); + DCHECK(!window_widget_); + + if (window_info_.width == 0) + window_info_.width = 800; + if (window_info_.height == 0) + window_info_.height = 600; + + gfx::Rect rect(window_info_.x, window_info_.y, + window_info_.width, window_info_.height); + + // Create a new window object. It will delete itself when the associated X11 + // window is destroyed. + window_x11_ = new CefWindowX11(this, window_info_.parent_window, rect); + window_info_.window = window_x11_->xwindow(); + + // Add a reference that will be released in the destroy handler. + AddRef(); + + SkColor background_color = SK_ColorWHITE; + const CefSettings& settings = CefContext::Get()->settings(); + if (CefColorGetA(settings.background_color) > 0) { + background_color = SkColorSetRGB( + CefColorGetR(settings.background_color), + CefColorGetG(settings.background_color), + CefColorGetB(settings.background_color)); + } + + CefWindowDelegateView* delegate_view = + new CefWindowDelegateView(background_color); + delegate_view->Init(window_info_.window, + web_contents(), + gfx::Rect(gfx::Point(), rect.size())); + + window_widget_ = delegate_view->GetWidget(); + window_widget_->Show(); + + window_x11_->Show(); + + // As an additional requirement on Linux, we must set the colors for the + // render widgets in webkit. + content::RendererPreferences* prefs = + web_contents_->GetMutableRendererPrefs(); + prefs->focus_ring_color = SkColorSetARGB(255, 229, 151, 0); + prefs->thumb_active_color = SkColorSetRGB(244, 244, 244); + prefs->thumb_inactive_color = SkColorSetRGB(234, 234, 234); + prefs->track_color = SkColorSetRGB(211, 211, 211); + + prefs->active_selection_bg_color = SkColorSetRGB(30, 144, 255); + prefs->active_selection_fg_color = SK_ColorWHITE; + prefs->inactive_selection_bg_color = SkColorSetRGB(200, 200, 200); + prefs->inactive_selection_fg_color = SkColorSetRGB(50, 50, 50); + + return true; +} + +void CefBrowserHostImpl::PlatformCloseWindow() { + if (window_x11_) + window_x11_->Close(); +} + +void CefBrowserHostImpl::PlatformSizeTo(int width, int height) { + if (window_x11_) { + window_x11_->SetBounds( + gfx::Rect(window_x11_->bounds().origin(), gfx::Size(width, height))); + } +} + +CefWindowHandle CefBrowserHostImpl::PlatformGetWindowHandle() { + return window_info_.window; +} + +bool CefBrowserHostImpl::PlatformViewText(const std::string& text) { + CEF_REQUIRE_UIT(); + + char buff[] = "/tmp/CEFSourceXXXXXX"; + int fd = mkstemp(buff); + + if (fd == -1) + return false; + + FILE* srcOutput = fdopen(fd, "w+"); + if (!srcOutput) + return false; + + if (fputs(text.c_str(), srcOutput) < 0) { + fclose(srcOutput); + return false; + } + + fclose(srcOutput); + + std::string newName(buff); + newName.append(".txt"); + if (rename(buff, newName.c_str()) != 0) + return false; + + std::string openCommand("xdg-open "); + openCommand += newName; + + if (system(openCommand.c_str()) != 0) + return false; + + return true; +} + +void CefBrowserHostImpl::PlatformHandleKeyboardEvent( + const content::NativeWebKeyboardEvent& event) { + // TODO(cef): Is something required here to handle shortcut keys? +} + +void CefBrowserHostImpl::PlatformRunFileChooser( + const content::FileChooserParams& params, + RunFileChooserCallback callback) { + NOTIMPLEMENTED(); + std::vector files; + callback.Run(files); +} + +void CefBrowserHostImpl::PlatformHandleExternalProtocol(const GURL& url) { +} + +void CefBrowserHostImpl::PlatformTranslateKeyEvent( + content::NativeWebKeyboardEvent& result, + const CefKeyEvent& key_event) { + NOTIMPLEMENTED(); +} + +void CefBrowserHostImpl::PlatformTranslateClickEvent( + blink::WebMouseEvent& result, + const CefMouseEvent& mouse_event, + MouseButtonType type, + bool mouseUp, int clickCount) { + PlatformTranslateMouseEvent(result, mouse_event); + + switch (type) { + case MBT_LEFT: + result.type = mouseUp ? blink::WebInputEvent::MouseUp : + blink::WebInputEvent::MouseDown; + result.button = blink::WebMouseEvent::ButtonLeft; + break; + case MBT_MIDDLE: + result.type = mouseUp ? blink::WebInputEvent::MouseUp : + blink::WebInputEvent::MouseDown; + result.button = blink::WebMouseEvent::ButtonMiddle; + break; + case MBT_RIGHT: + result.type = mouseUp ? blink::WebInputEvent::MouseUp : + blink::WebInputEvent::MouseDown; + result.button = blink::WebMouseEvent::ButtonRight; + break; + default: + NOTREACHED(); + } + + result.clickCount = clickCount; +} + +void CefBrowserHostImpl::PlatformTranslateMoveEvent( + blink::WebMouseEvent& result, + const CefMouseEvent& mouse_event, + bool mouseLeave) { + PlatformTranslateMouseEvent(result, mouse_event); + + if (!mouseLeave) { + result.type = blink::WebInputEvent::MouseMove; + if (mouse_event.modifiers & EVENTFLAG_LEFT_MOUSE_BUTTON) + result.button = blink::WebMouseEvent::ButtonLeft; + else if (mouse_event.modifiers & EVENTFLAG_MIDDLE_MOUSE_BUTTON) + result.button = blink::WebMouseEvent::ButtonMiddle; + else if (mouse_event.modifiers & EVENTFLAG_RIGHT_MOUSE_BUTTON) + result.button = blink::WebMouseEvent::ButtonRight; + else + result.button = blink::WebMouseEvent::ButtonNone; + } else { + result.type = blink::WebInputEvent::MouseLeave; + result.button = blink::WebMouseEvent::ButtonNone; + } + + result.clickCount = 0; +} + +void CefBrowserHostImpl::PlatformTranslateWheelEvent( + blink::WebMouseWheelEvent& result, + const CefMouseEvent& mouse_event, + int deltaX, int deltaY) { + result = blink::WebMouseWheelEvent(); + PlatformTranslateMouseEvent(result, mouse_event); + + result.type = blink::WebInputEvent::MouseWheel; + + static const double scrollbarPixelsPerGtkTick = 40.0; + result.deltaX = deltaX; + result.deltaY = deltaY; + result.wheelTicksX = result.deltaX / scrollbarPixelsPerGtkTick; + result.wheelTicksY = result.deltaY / scrollbarPixelsPerGtkTick; + result.hasPreciseScrollingDeltas = true; + + // Unless the phase and momentumPhase are passed in as parameters to this + // function, there is no way to know them + result.phase = blink::WebMouseWheelEvent::PhaseNone; + result.momentumPhase = blink::WebMouseWheelEvent::PhaseNone; + + if (mouse_event.modifiers & EVENTFLAG_LEFT_MOUSE_BUTTON) + result.button = blink::WebMouseEvent::ButtonLeft; + else if (mouse_event.modifiers & EVENTFLAG_MIDDLE_MOUSE_BUTTON) + result.button = blink::WebMouseEvent::ButtonMiddle; + else if (mouse_event.modifiers & EVENTFLAG_RIGHT_MOUSE_BUTTON) + result.button = blink::WebMouseEvent::ButtonRight; + else + result.button = blink::WebMouseEvent::ButtonNone; +} + +void CefBrowserHostImpl::PlatformTranslateMouseEvent( + blink::WebMouseEvent& result, + const CefMouseEvent& mouse_event) { + // position + result.x = mouse_event.x; + result.y = mouse_event.y; + result.windowX = result.x; + result.windowY = result.y; + result.globalX = result.x; + result.globalY = result.y; + + // TODO(linux): Convert global{X,Y} to screen coordinates. + + // modifiers + result.modifiers |= TranslateModifiers(mouse_event.modifiers); + + // timestamp + result.timeStampSeconds = GetSystemUptime(); +} diff --git a/libcef/browser/browser_host_impl_win.cc b/libcef/browser/browser_host_impl_win.cc index 0656fbbdd..14c17e7ca 100644 --- a/libcef/browser/browser_host_impl_win.cc +++ b/libcef/browser/browser_host_impl_win.cc @@ -35,12 +35,8 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/base/win/shell.h" #include "ui/gfx/win/hwnd_util.h" -#include "ui/views/background.h" -#include "ui/views/controls/webview/webview.h" -#include "ui/views/layout/fill_layout.h" #include "ui/views/widget/desktop_aura/desktop_window_tree_host_win.h" #include "ui/views/widget/widget.h" -#include "ui/views/widget/widget_delegate.h" #pragma comment(lib, "dwmapi.lib") @@ -548,76 +544,6 @@ bool IsSystemCursorID(LPCWSTR cursor_id) { return cursor_id >= IDC_ARROW; // See WinUser.h } -// Manages the views-based root window that hosts the web contents. This object -// will be deleted automatically when the associated root window is destroyed. -class CefWindowDelegateView : public views::WidgetDelegateView { - public: - explicit CefWindowDelegateView(SkColor background_color) - : background_color_(background_color), - web_view_(NULL) { - - } - - // Create the Widget and associated root window. - void Init(gfx::AcceleratedWidget parent_widget, - content::WebContents* web_contents, - const gfx::Rect& bounds) { - DCHECK(!web_view_); - web_view_ = new views::WebView(web_contents->GetBrowserContext()); - web_view_->SetWebContents(web_contents); - web_view_->SetPreferredSize(bounds.size()); - - views::Widget* widget = new views::Widget; - - // See CalculateWindowStylesFromInitParams in - // ui/views/widget/widget_hwnd_utils.cc for the conversion of |params| to - // Windows style flags. - views::Widget::InitParams params; - params.parent_widget = parent_widget; - params.bounds = bounds; - params.delegate = this; - params.top_level = true; - // Set the WS_CHILD flag. - params.child = true; - // Set the WS_VISIBLE flag. - params.type = views::Widget::InitParams::TYPE_CONTROL; - // Don't set the WS_EX_COMPOSITED flag. - params.opacity = views::Widget::InitParams::OPAQUE_WINDOW; - - // Results in a call to InitContent(). - widget->Init(params); - - // |widget| should now be associated with |this|. - DCHECK_EQ(widget, GetWidget()); - } - - private: - // Initialize the Widget's content. - void InitContent() { - set_background(views::Background::CreateSolidBackground(background_color_)); - SetLayoutManager(new views::FillLayout()); - AddChildView(web_view_); - } - - // WidgetDelegateView methods: - virtual bool CanResize() const OVERRIDE { return true; } - virtual bool CanMaximize() const OVERRIDE { return true; } - virtual View* GetContentsView() OVERRIDE { return this; } - - // View methods: - virtual void ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) OVERRIDE { - if (details.is_add && details.child == this) - InitContent(); - } - - private: - SkColor background_color_; - views::WebView* web_view_; - - DISALLOW_COPY_AND_ASSIGN(CefWindowDelegateView); -}; - } // namespace // static diff --git a/libcef/browser/browser_main.cc b/libcef/browser/browser_main.cc index 095f70b5a..721074a77 100644 --- a/libcef/browser/browser_main.cc +++ b/libcef/browser/browser_main.cc @@ -26,10 +26,6 @@ #include "ui/base/resource/resource_bundle.h" #include "v8/include/v8.h" -#if defined(OS_LINUX) -#include "chrome/browser/printing/print_dialog_gtk.h" -#endif - #if defined(USE_AURA) #include "ui/aura/env.h" #include "ui/gfx/screen.h" @@ -41,6 +37,10 @@ #endif #endif // defined(USE_AURA) +#if defined(USE_AURA) && defined(USE_X11) +#include "ui/base/ime/input_method_initializer.h" +#endif + CefBrowserMainParts::CefBrowserMainParts( const content::MainFunctionParams& parameters) : BrowserMainParts(), @@ -58,6 +58,14 @@ void CefBrowserMainParts::PreMainMessageLoopStart() { } } +void CefBrowserMainParts::PreEarlyInitialization() { +#if defined(USE_AURA) && defined(USE_X11) + // TODO(linux): Consider using a real input method or + // views::LinuxUI::SetInstance. + ui::InitializeInputMethodForTesting(); +#endif +} + void CefBrowserMainParts::ToolkitInitialized() { #if defined(USE_AURA) aura::Env::CreateInstance(); @@ -77,11 +85,6 @@ void CefBrowserMainParts::PostMainMessageLoopStart() { // CEF's internal handling of "chrome://tracing". content::WebUIControllerFactory::UnregisterFactoryForTesting( content::ContentWebUIControllerFactory::GetInstance()); - -#if defined(OS_LINUX) - printing::PrintingContextLinux::SetCreatePrintDialogFunction( - &PrintDialogGtk::CreatePrintDialog); -#endif } int CefBrowserMainParts::PreCreateThreads() { diff --git a/libcef/browser/browser_main.h b/libcef/browser/browser_main.h index 271149bfa..58f826f62 100644 --- a/libcef/browser/browser_main.h +++ b/libcef/browser/browser_main.h @@ -41,6 +41,7 @@ class CefBrowserMainParts : public content::BrowserMainParts { virtual void PreMainMessageLoopStart() OVERRIDE; virtual void PostMainMessageLoopStart() OVERRIDE; + virtual void PreEarlyInitialization() OVERRIDE; virtual void ToolkitInitialized() OVERRIDE; virtual int PreCreateThreads() OVERRIDE; virtual void PreMainMessageLoopRun() OVERRIDE; diff --git a/libcef/browser/browser_main_gtk.cc b/libcef/browser/browser_main_linux.cc similarity index 93% rename from libcef/browser/browser_main_gtk.cc rename to libcef/browser/browser_main_linux.cc index 03a0136fb..d9b14a323 100644 --- a/libcef/browser/browser_main_gtk.cc +++ b/libcef/browser/browser_main_linux.cc @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include - #include "libcef/browser/browser_main.h" void CefBrowserMainParts::PlatformInitialize() { diff --git a/libcef/browser/gtk_util_stub.cc b/libcef/browser/gtk_util_stub.cc deleted file mode 100644 index 32d5157ee..000000000 --- a/libcef/browser/gtk_util_stub.cc +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include - -#include "ui/events/event.h" - -// This file includes a selection of methods copied from -// chrome/browser/ui/gtk/gtk_util.cc. - -namespace gtk_util { - -void SetAlwaysShowImage(GtkWidget* image_menu_item) { - gtk_image_menu_item_set_always_show_image( - GTK_IMAGE_MENU_ITEM(image_menu_item), TRUE); -} - -} // namespace gtk_util - - -namespace event_utils { - -int EventFlagsFromGdkState(guint state) { - int flags = 0; - flags |= (state & GDK_LOCK_MASK) ? ui::EF_CAPS_LOCK_DOWN : 0; - flags |= (state & GDK_CONTROL_MASK) ? ui::EF_CONTROL_DOWN : 0; - flags |= (state & GDK_SHIFT_MASK) ? ui::EF_SHIFT_DOWN : 0; - flags |= (state & GDK_MOD1_MASK) ? ui::EF_ALT_DOWN : 0; - flags |= (state & GDK_BUTTON1_MASK) ? ui::EF_LEFT_MOUSE_BUTTON : 0; - flags |= (state & GDK_BUTTON2_MASK) ? ui::EF_MIDDLE_MOUSE_BUTTON : 0; - flags |= (state & GDK_BUTTON3_MASK) ? ui::EF_RIGHT_MOUSE_BUTTON : 0; - return flags; -} - -} // namespace event_utils diff --git a/libcef/browser/javascript_dialog.h b/libcef/browser/javascript_dialog.h index 29d7a1c13..4e1da5a27 100644 --- a/libcef/browser/javascript_dialog.h +++ b/libcef/browser/javascript_dialog.h @@ -9,10 +9,6 @@ #include "content/public/browser/javascript_dialog_manager.h" -#if defined(TOOLKIT_GTK) -#include "ui/base/gtk/gtk_signal.h" -#endif - #if defined(OS_MACOSX) #if __OBJC__ @class CefJavaScriptDialogHelper; @@ -63,9 +59,6 @@ class CefJavaScriptDialog { static LRESULT CALLBACK GetMsgProc(int code, WPARAM wparam, LPARAM lparam); static HHOOK msg_hook_; static int msg_hook_user_count_; -#elif defined(TOOLKIT_GTK) - GtkWidget* gtk_dialog_; - CHROMEGTK_CALLBACK_1(CefJavaScriptDialog, void, OnResponse, int); #endif DISALLOW_COPY_AND_ASSIGN(CefJavaScriptDialog); diff --git a/libcef/browser/javascript_dialog_gtk.cc b/libcef/browser/javascript_dialog_gtk.cc deleted file mode 100644 index ee603500a..000000000 --- a/libcef/browser/javascript_dialog_gtk.cc +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright (c) 2012 The Chromium Embedded Framework Authors. -// Portions copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "libcef/browser/javascript_dialog.h" -#include "libcef/browser/browser_host_impl.h" -#include "libcef/browser/javascript_dialog_manager.h" - -#include - -#include "base/logging.h" -#include "base/strings/string_util.h" -#include "base/strings/utf_string_conversions.h" - -namespace { - -const char kPromptTextId[] = "cef_prompt_text"; - -// If there's a text entry in the dialog, get the text from the first one and -// return it. -base::string16 GetPromptText(GtkDialog* dialog) { - GtkWidget* widget = static_cast( - g_object_get_data(G_OBJECT(dialog), kPromptTextId)); - if (widget) - return base::UTF8ToUTF16(gtk_entry_get_text(GTK_ENTRY(widget))); - return base::string16(); -} - -} // namespace - -CefJavaScriptDialog::CefJavaScriptDialog( - CefJavaScriptDialogManager* creator, - content::JavaScriptMessageType message_type, - const base::string16& display_url, - const base::string16& message_text, - const base::string16& default_prompt_text, - const content::JavaScriptDialogManager::DialogClosedCallback& callback) - : creator_(creator), - callback_(callback) { - GtkButtonsType buttons = GTK_BUTTONS_NONE; - GtkMessageType gtk_message_type = GTK_MESSAGE_OTHER; - std::string title; - - switch (message_type) { - case content::JAVASCRIPT_MESSAGE_TYPE_ALERT: - buttons = GTK_BUTTONS_NONE; - gtk_message_type = GTK_MESSAGE_WARNING; - title = "JavaScript Alert"; - break; - - case content::JAVASCRIPT_MESSAGE_TYPE_CONFIRM: - buttons = GTK_BUTTONS_CANCEL; - gtk_message_type = GTK_MESSAGE_QUESTION; - title = "JavaScript Confirm"; - break; - - case content::JAVASCRIPT_MESSAGE_TYPE_PROMPT: - buttons = GTK_BUTTONS_CANCEL; - gtk_message_type = GTK_MESSAGE_QUESTION; - title = "JavaScript Prompt"; - break; - - default: - NOTREACHED(); - } - - if (!display_url.empty()) { - title += " - "; - title += base::UTF16ToUTF8(display_url).c_str(); - } - - GtkWidget* window = - gtk_widget_get_ancestor( - GTK_WIDGET(creator->browser()->GetWindowHandle()), - GTK_TYPE_WINDOW); - gtk_dialog_ = gtk_message_dialog_new(GTK_WINDOW(window), - GTK_DIALOG_MODAL, - gtk_message_type, - buttons, - "%s", - base::UTF16ToUTF8(message_text).c_str()); - g_signal_connect(gtk_dialog_, - "delete-event", - G_CALLBACK(gtk_widget_hide_on_delete), - NULL); - - gtk_window_set_title(GTK_WINDOW(gtk_dialog_), title.c_str()); - - GtkWidget* ok_button = gtk_dialog_add_button(GTK_DIALOG(gtk_dialog_), - GTK_STOCK_OK, - GTK_RESPONSE_OK); - - if (message_type != content::JAVASCRIPT_MESSAGE_TYPE_PROMPT) - gtk_widget_grab_focus(ok_button); - - if (message_type == content::JAVASCRIPT_MESSAGE_TYPE_PROMPT) { - GtkWidget* content_area = - gtk_dialog_get_content_area(GTK_DIALOG(gtk_dialog_)); - GtkWidget* text_box = gtk_entry_new(); - gtk_entry_set_text(GTK_ENTRY(text_box), - base::UTF16ToUTF8(default_prompt_text).c_str()); - gtk_box_pack_start(GTK_BOX(content_area), text_box, TRUE, TRUE, 0); - g_object_set_data(G_OBJECT(gtk_dialog_), kPromptTextId, text_box); - gtk_entry_set_activates_default(GTK_ENTRY(text_box), TRUE); - } - - gtk_dialog_set_default_response(GTK_DIALOG(gtk_dialog_), GTK_RESPONSE_OK); - g_signal_connect(gtk_dialog_, "response", G_CALLBACK(OnResponseThunk), this); - gtk_widget_show_all(GTK_WIDGET(gtk_dialog_)); -} - -CefJavaScriptDialog::~CefJavaScriptDialog() { -} - -void CefJavaScriptDialog::Cancel() { -} - -void CefJavaScriptDialog::OnResponse(GtkWidget* dialog, int response_id) { - switch (response_id) { - case GTK_RESPONSE_OK: - callback_.Run(true, GetPromptText(GTK_DIALOG(dialog))); - break; - case GTK_RESPONSE_CANCEL: - case GTK_RESPONSE_DELETE_EVENT: - callback_.Run(false, base::string16()); - break; - default: - NOTREACHED(); - } - - gtk_widget_destroy(dialog); - - creator_->DialogClosed(this); -} \ No newline at end of file diff --git a/libcef/browser/javascript_dialog_linux.cc b/libcef/browser/javascript_dialog_linux.cc new file mode 100644 index 000000000..83bcdfdd9 --- /dev/null +++ b/libcef/browser/javascript_dialog_linux.cc @@ -0,0 +1,28 @@ +// Copyright (c) 2012 The Chromium Embedded Framework Authors. +// Portions copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "libcef/browser/javascript_dialog.h" +#include "libcef/browser/javascript_dialog_manager.h" + +CefJavaScriptDialog::CefJavaScriptDialog( + CefJavaScriptDialogManager* creator, + content::JavaScriptMessageType message_type, + const base::string16& display_url, + const base::string16& message_text, + const base::string16& default_prompt_text, + const content::JavaScriptDialogManager::DialogClosedCallback& callback) + : creator_(creator), + callback_(callback) { + NOTIMPLEMENTED(); + callback_.Run(false, base::string16()); + creator_->DialogClosed(this); +} + +CefJavaScriptDialog::~CefJavaScriptDialog() { +} + +void CefJavaScriptDialog::Cancel() { +} + diff --git a/libcef/browser/menu_creator.cc b/libcef/browser/menu_creator.cc index f27847d3a..c7b47f078 100644 --- a/libcef/browser/menu_creator.cc +++ b/libcef/browser/menu_creator.cc @@ -18,8 +18,8 @@ #include "libcef/browser/menu_creator_runner_win.h" #elif defined(OS_MACOSX) #include "libcef/browser/menu_creator_runner_mac.h" -#elif defined(TOOLKIT_GTK) -#include "libcef/browser/menu_creator_runner_gtk.h" +#elif defined(OS_LINUX) +#include "libcef/browser/menu_creator_runner_linux.h" #endif namespace { @@ -110,8 +110,8 @@ bool CefMenuCreator::CreateRunner() { runner_.reset(new CefMenuCreatorRunnerWin); #elif defined(OS_MACOSX) runner_.reset(new CefMenuCreatorRunnerMac); -#elif defined(TOOLKIT_GTK) - runner_.reset(new CefMenuCreatorRunnerGtk); +#elif defined(OS_LINUX) + runner_.reset(new CefMenuCreatorRunnerLinux); #else // Need an implementation. NOTREACHED(); diff --git a/libcef/browser/menu_creator_runner_gtk.cc b/libcef/browser/menu_creator_runner_gtk.cc deleted file mode 100644 index 24ec6c227..000000000 --- a/libcef/browser/menu_creator_runner_gtk.cc +++ /dev/null @@ -1,55 +0,0 @@ -// 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 "libcef/browser/menu_creator_runner_gtk.h" -#include "libcef/browser/browser_host_impl.h" - -#include "content/public/browser/render_widget_host_view.h" -#include "content/public/browser/web_contents_view.h" -#include "ui/gfx/point.h" - -namespace { - -class CefMenuDelegate : public MenuGtk::Delegate { - public: - CefMenuDelegate() {} -}; - -} // namespace - - -CefMenuCreatorRunnerGtk::CefMenuCreatorRunnerGtk() { -} - -CefMenuCreatorRunnerGtk::~CefMenuCreatorRunnerGtk() { - if (menu_.get()) - menu_->Cancel(); -} - -bool CefMenuCreatorRunnerGtk::RunContextMenu(CefMenuCreator* manager) { - gfx::Point screen_point; - GdkEventButton* event = NULL; - - gfx::Rect bounds; - manager->browser()->GetWebContents()->GetView()->GetContainerBounds(&bounds); - screen_point = bounds.origin(); - screen_point.Offset(manager->params().x, manager->params().y); - - content::RenderWidgetHostView* view = - manager->browser()->GetWebContents()->GetRenderWidgetHostView(); - event = view->GetLastMouseDown(); - - if (!menu_delegate_.get()) - menu_delegate_.reset(new CefMenuDelegate); - - // Create a menu based on the model. - menu_.reset(new MenuGtk(menu_delegate_.get(), manager->model())); - - uint32_t triggering_event_time = event ? event->time : GDK_CURRENT_TIME; - - // Show the menu. Execution will continue asynchronously. - menu_->PopupAsContext(screen_point, triggering_event_time); - - return true; -} diff --git a/libcef/browser/menu_creator_runner_gtk.h b/libcef/browser/menu_creator_runner_gtk.h deleted file mode 100644 index 5a5a44297..000000000 --- a/libcef/browser/menu_creator_runner_gtk.h +++ /dev/null @@ -1,27 +0,0 @@ -// 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_LIBCEF_BROWSER_MENU_MANAGER_RUNNER_GTK_H_ -#define CEF_LIBCEF_BROWSER_MENU_MANAGER_RUNNER_GTK_H_ -#pragma once - -#include "libcef/browser/menu_creator.h" - -#include "base/memory/scoped_ptr.h" -#include "chrome/browser/ui/gtk/menu_gtk.h" - -class CefMenuCreatorRunnerGtk: public CefMenuCreator::Runner { - public: - CefMenuCreatorRunnerGtk(); - virtual ~CefMenuCreatorRunnerGtk(); - - // CefMemoryManager::Runner methods. - virtual bool RunContextMenu(CefMenuCreator* manager) OVERRIDE; - - private: - scoped_ptr menu_; - scoped_ptr menu_delegate_; -}; - -#endif // CEF_LIBCEF_BROWSER_MENU_MANAGER_RUNNER_GTK_H_ diff --git a/libcef/browser/menu_creator_runner_linux.cc b/libcef/browser/menu_creator_runner_linux.cc new file mode 100644 index 000000000..1b87f40c4 --- /dev/null +++ b/libcef/browser/menu_creator_runner_linux.cc @@ -0,0 +1,16 @@ +// 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 "libcef/browser/menu_creator_runner_linux.h" + +CefMenuCreatorRunnerLinux::CefMenuCreatorRunnerLinux() { +} + +CefMenuCreatorRunnerLinux::~CefMenuCreatorRunnerLinux() { +} + +bool CefMenuCreatorRunnerLinux::RunContextMenu(CefMenuCreator* manager) { + NOTIMPLEMENTED(); + return false; +} diff --git a/libcef/browser/menu_creator_runner_linux.h b/libcef/browser/menu_creator_runner_linux.h new file mode 100644 index 000000000..bac6fa44c --- /dev/null +++ b/libcef/browser/menu_creator_runner_linux.h @@ -0,0 +1,20 @@ +// 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_LIBCEF_BROWSER_MENU_MANAGER_RUNNER_LINUX_H_ +#define CEF_LIBCEF_BROWSER_MENU_MANAGER_RUNNER_LINUX_H_ +#pragma once + +#include "libcef/browser/menu_creator.h" + +class CefMenuCreatorRunnerLinux: public CefMenuCreator::Runner { + public: + CefMenuCreatorRunnerLinux(); + virtual ~CefMenuCreatorRunnerLinux(); + + // CefMemoryManager::Runner methods. + virtual bool RunContextMenu(CefMenuCreator* manager) OVERRIDE; +}; + +#endif // CEF_LIBCEF_BROWSER_MENU_MANAGER_RUNNER_LINUX_H_ diff --git a/libcef/browser/thread_util.h b/libcef/browser/thread_util.h index b9286e9e5..2faf57128 100644 --- a/libcef/browser/thread_util.h +++ b/libcef/browser/thread_util.h @@ -43,6 +43,7 @@ #define CEF_POST_TASK(id, task) \ content::BrowserThread::PostTask(id, FROM_HERE, task) #define CEF_POST_DELAYED_TASK(id, task, delay_ms) \ - content::BrowserThread::PostDelayedTask(id, FROM_HERE, task, delay_ms) + content::BrowserThread::PostDelayedTask(id, FROM_HERE, task, \ + base::TimeDelta::FromMilliseconds(delay_ms)) #endif // CEF_LIBCEF_BROWSER_THREAD_UTIL_H_ diff --git a/libcef/browser/window_delegate_view.cc b/libcef/browser/window_delegate_view.cc new file mode 100644 index 000000000..c8b4b6c24 --- /dev/null +++ b/libcef/browser/window_delegate_view.cc @@ -0,0 +1,62 @@ +// Copyright 2014 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 "libcef/browser/window_delegate_view.h" + +#include "content/public/browser/web_contents.h" +#include "ui/views/background.h" +#include "ui/views/controls/webview/webview.h" +#include "ui/views/layout/fill_layout.h" +#include "ui/views/widget/widget.h" + +CefWindowDelegateView::CefWindowDelegateView(SkColor background_color) + : background_color_(background_color), + web_view_(NULL) { +} + +void CefWindowDelegateView::Init( + gfx::AcceleratedWidget parent_widget, + content::WebContents* web_contents, + const gfx::Rect& bounds) { + DCHECK(!web_view_); + web_view_ = new views::WebView(web_contents->GetBrowserContext()); + web_view_->SetWebContents(web_contents); + web_view_->SetPreferredSize(bounds.size()); + + views::Widget* widget = new views::Widget; + + // See CalculateWindowStylesFromInitParams in + // ui/views/widget/widget_hwnd_utils.cc for the conversion of |params| to + // Windows style flags. + views::Widget::InitParams params; + params.parent_widget = parent_widget; + params.bounds = bounds; + params.delegate = this; + params.top_level = true; + // Set the WS_CHILD flag. + params.child = true; + // Set the WS_VISIBLE flag. + params.type = views::Widget::InitParams::TYPE_CONTROL; + // Don't set the WS_EX_COMPOSITED flag. + params.opacity = views::Widget::InitParams::OPAQUE_WINDOW; + + // Results in a call to InitContent(). + widget->Init(params); + + // |widget| should now be associated with |this|. + DCHECK_EQ(widget, GetWidget()); +} + +void CefWindowDelegateView::InitContent() { + set_background(views::Background::CreateSolidBackground(background_color_)); + SetLayoutManager(new views::FillLayout()); + AddChildView(web_view_); +} + +void CefWindowDelegateView::ViewHierarchyChanged( + const ViewHierarchyChangedDetails& details) { + if (details.is_add && details.child == this) + InitContent(); +} + diff --git a/libcef/browser/window_delegate_view.h b/libcef/browser/window_delegate_view.h new file mode 100644 index 000000000..8380a77c3 --- /dev/null +++ b/libcef/browser/window_delegate_view.h @@ -0,0 +1,50 @@ +// Copyright 2014 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_LIBCEF_BROWSER_WINDOW_DELEGATE_VIEW_H_ +#define CEF_LIBCEF_BROWSER_WINDOW_DELEGATE_VIEW_H_ +#pragma once + +#include "ui/views/widget/widget_delegate.h" + +namespace content { +class WebContents; +} + +namespace views { +class WebView; +} + +// Manages the views-based root window that hosts the web contents. This object +// will be deleted automatically when the associated root window is destroyed. +class CefWindowDelegateView : public views::WidgetDelegateView { + public: + explicit CefWindowDelegateView(SkColor background_color); + + // Create the Widget and associated root window. + void Init(gfx::AcceleratedWidget parent_widget, + content::WebContents* web_contents, + const gfx::Rect& bounds); + + private: + // Initialize the Widget's content. + void InitContent(); + + // WidgetDelegateView methods: + virtual bool CanResize() const OVERRIDE { return true; } + virtual bool CanMaximize() const OVERRIDE { return true; } + virtual View* GetContentsView() OVERRIDE { return this; } + + // View methods: + virtual void ViewHierarchyChanged( + const ViewHierarchyChangedDetails& details) OVERRIDE; + + private: + SkColor background_color_; + views::WebView* web_view_; + + DISALLOW_COPY_AND_ASSIGN(CefWindowDelegateView); +}; + +#endif // CEF_LIBCEF_BROWSER_WINDOW_DELEGATE_VIEW_H_ diff --git a/libcef/renderer/thread_util.h b/libcef/renderer/thread_util.h index da9322c7d..1867ef607 100644 --- a/libcef/renderer/thread_util.h +++ b/libcef/renderer/thread_util.h @@ -34,7 +34,8 @@ #define CEF_POST_TASK_RT(task) \ CEF_RENDER_LOOP()->PostTask(FROM_HERE, task) #define CEF_POST_DELAYED_TASK_RT(task, delay_ms) \ - CEF_RENDER_LOOP()->PostDelayedTask(FROM_HERE, task, delay_ms) + CEF_RENDER_LOOP()->PostDelayedTask(FROM_HERE, task, \ + base::TimeDelta::FromMilliseconds(delay_ms)) // Use this template in conjuction with RefCountedThreadSafe when you want to // ensure that an object is deleted on the render thread. diff --git a/libcef_dll/cpptoc/browser_host_cpptoc.cc b/libcef_dll/cpptoc/browser_host_cpptoc.cc index 8abde1a81..dfd8ebddd 100644 --- a/libcef_dll/cpptoc/browser_host_cpptoc.cc +++ b/libcef_dll/cpptoc/browser_host_cpptoc.cc @@ -144,7 +144,7 @@ cef_window_handle_t CEF_CALLBACK browser_host_get_window_handle( DCHECK(self); if (!self) - return NULL; + return kNullWindowHandle; // Execute cef_window_handle_t _retval = CefBrowserHostCppToC::Get( @@ -160,7 +160,7 @@ cef_window_handle_t CEF_CALLBACK browser_host_get_opener_window_handle( DCHECK(self); if (!self) - return NULL; + return kNullWindowHandle; // Execute cef_window_handle_t _retval = CefBrowserHostCppToC::Get( diff --git a/libcef_dll/ctocpp/browser_host_ctocpp.cc b/libcef_dll/ctocpp/browser_host_ctocpp.cc index 8f208c0b7..7186d3e54 100644 --- a/libcef_dll/ctocpp/browser_host_ctocpp.cc +++ b/libcef_dll/ctocpp/browser_host_ctocpp.cc @@ -100,7 +100,7 @@ void CefBrowserHostCToCpp::SetFocus(bool enable) { CefWindowHandle CefBrowserHostCToCpp::GetWindowHandle() { if (CEF_MEMBER_MISSING(struct_, get_window_handle)) - return NULL; + return kNullWindowHandle; // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING @@ -113,7 +113,7 @@ CefWindowHandle CefBrowserHostCToCpp::GetWindowHandle() { CefWindowHandle CefBrowserHostCToCpp::GetOpenerWindowHandle() { if (CEF_MEMBER_MISSING(struct_, get_opener_window_handle)) - return NULL; + return kNullWindowHandle; // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING diff --git a/libcef_dll/wrapper/cef_byte_read_handler.cc b/libcef_dll/wrapper/cef_byte_read_handler.cc index b4530e14e..e06daa3a1 100644 --- a/libcef_dll/wrapper/cef_byte_read_handler.cc +++ b/libcef_dll/wrapper/cef_byte_read_handler.cc @@ -4,6 +4,7 @@ #include "include/wrapper/cef_byte_read_handler.h" #include +#include #include #include "libcef_dll/cef_logging.h" diff --git a/patch/patches/build.patch b/patch/patches/build.patch index 66b87ecaf..283bd309b 100644 --- a/patch/patches/build.patch +++ b/patch/patches/build.patch @@ -1,7 +1,7 @@ -Index: common.gypi -=================================================================== ---- common.gypi (revision 263053) -+++ common.gypi (working copy) +diff --git common.gypi common.gypi +index c87ec63..45bb14e 100644 +--- common.gypi ++++ common.gypi @@ -9,6 +9,9 @@ # Variables expected to be overriden on the GYP command line (-D) or by # ~/.gyp/include.gypi. @@ -12,24 +12,11 @@ Index: common.gypi # Putting a variables dict inside another variables dict looks kind of # weird. This is done so that 'host_arch', 'chromeos', etc are defined as # variables within the outer variables dict here. This is necessary -@@ -101,9 +104,9 @@ - # - # TODO(erg): Merge this into the previous block once compiling with - # aura safely implies including ash capabilities. -- ['OS=="linux"', { -- 'use_aura%': 1, -- }], -+ #['OS=="linux"', { -+ # 'use_aura%': 1, -+ #}], - - # Whether we're a traditional desktop unix. - ['(OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris") and chromeos==0', { -Index: mac/strip_save_dsym -=================================================================== ---- mac/strip_save_dsym (revision 263053) -+++ mac/strip_save_dsym (working copy) -@@ -48,7 +48,7 @@ +diff --git mac/strip_save_dsym mac/strip_save_dsym +index c9cf226..0dedbe3 100755 +--- mac/strip_save_dsym ++++ mac/strip_save_dsym +@@ -48,7 +48,7 @@ def macho_archs(macho): "bundle"] macho_types_re = "Mach-O (?:64-bit )?(?:" + "|".join(macho_types) + ")" diff --git a/patch/patches/views_widget_180.patch b/patch/patches/views_widget_180.patch index e82aa983e..7f3dc42bf 100644 --- a/patch/patches/views_widget_180.patch +++ b/patch/patches/views_widget_180.patch @@ -1,8 +1,8 @@ -Index: desktop_aura/desktop_screen_win.cc -=================================================================== ---- desktop_aura/desktop_screen_win.cc (revision 263053) -+++ desktop_aura/desktop_screen_win.cc (working copy) -@@ -54,6 +54,8 @@ +diff --git desktop_aura/desktop_screen_win.cc desktop_aura/desktop_screen_win.cc +index c5edf76..9389662 100644 +--- desktop_aura/desktop_screen_win.cc ++++ desktop_aura/desktop_screen_win.cc +@@ -54,6 +54,8 @@ gfx::Display DesktopScreenWin::GetDisplayMatching( } HWND DesktopScreenWin::GetHWNDFromNativeView(gfx::NativeView window) const { @@ -11,11 +11,11 @@ Index: desktop_aura/desktop_screen_win.cc aura::WindowTreeHost* host = window->GetHost(); return host ? host->GetAcceleratedWidget() : NULL; } -Index: desktop_aura/desktop_window_tree_host_win.cc -=================================================================== ---- desktop_aura/desktop_window_tree_host_win.cc (revision 263053) -+++ desktop_aura/desktop_window_tree_host_win.cc (working copy) -@@ -130,7 +130,9 @@ +diff --git desktop_aura/desktop_window_tree_host_win.cc desktop_aura/desktop_window_tree_host_win.cc +index 2fc499b..6fa63b5 100644 +--- desktop_aura/desktop_window_tree_host_win.cc ++++ desktop_aura/desktop_window_tree_host_win.cc +@@ -130,7 +130,9 @@ void DesktopWindowTreeHostWin::Init(aura::Window* content_window, native_widget_delegate_); HWND parent_hwnd = NULL; @@ -26,11 +26,11 @@ Index: desktop_aura/desktop_window_tree_host_win.cc parent_hwnd = params.parent->GetHost()->GetAcceleratedWidget(); message_handler_->set_remove_standard_frame(params.remove_standard_frame); -Index: desktop_aura/desktop_window_tree_host_win.h -=================================================================== ---- desktop_aura/desktop_window_tree_host_win.h (revision 263053) -+++ desktop_aura/desktop_window_tree_host_win.h (working copy) -@@ -214,6 +214,7 @@ +diff --git desktop_aura/desktop_window_tree_host_win.h desktop_aura/desktop_window_tree_host_win.h +index dc8a218..84680cf 100644 +--- desktop_aura/desktop_window_tree_host_win.h ++++ desktop_aura/desktop_window_tree_host_win.h +@@ -214,6 +214,7 @@ class VIEWS_EXPORT DesktopWindowTreeHostWin LPARAM l_param) OVERRIDE; virtual bool HandleScrollEvent(const ui::ScrollEvent& event) OVERRIDE; @@ -38,27 +38,91 @@ Index: desktop_aura/desktop_window_tree_host_win.h Widget* GetWidget(); const Widget* GetWidget() const; HWND GetHWND() const; -Index: widget.cc -=================================================================== ---- widget.cc (revision 263053) -+++ widget.cc (working copy) -@@ -122,6 +122,7 @@ +diff --git desktop_aura/desktop_window_tree_host_x11.cc desktop_aura/desktop_window_tree_host_x11.cc +index 028b6f5..e8b4bd2 100644 +--- desktop_aura/desktop_window_tree_host_x11.cc ++++ desktop_aura/desktop_window_tree_host_x11.cc +@@ -138,7 +138,8 @@ DesktopWindowTreeHostX11::DesktopWindowTreeHostX11( + content_window_(NULL), + window_parent_(NULL), + custom_window_shape_(NULL), +- urgency_hint_set_(false) { ++ urgency_hint_set_(false), ++ xwindow_destroyed_(false) { + } + + DesktopWindowTreeHostX11::~DesktopWindowTreeHostX11() { +@@ -315,7 +316,8 @@ void DesktopWindowTreeHostX11::CloseNow() { + // Actually free our native resources. + if (ui::PlatformEventSource::GetInstance()) + ui::PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this); +- XDestroyWindow(xdisplay_, xwindow_); ++ if (!xwindow_destroyed_) ++ XDestroyWindow(xdisplay_, xwindow_); + xwindow_ = None; + + desktop_native_widget_aura_->OnHostClosed(); +@@ -968,9 +970,13 @@ void DesktopWindowTreeHostX11::InitX11Window( + if (swa.override_redirect) + attribute_mask |= CWOverrideRedirect; + ++ gfx::AcceleratedWidget parent_widget = params.parent_widget; ++ if (parent_widget == gfx::kNullAcceleratedWidget) ++ parent_widget = x_root_window_; ++ + bounds_ = params.bounds; + xwindow_ = XCreateWindow( +- xdisplay_, x_root_window_, ++ xdisplay_, parent_widget, + bounds_.x(), bounds_.y(), + bounds_.width(), bounds_.height(), + 0, // border width +@@ -1378,6 +1384,10 @@ uint32_t DesktopWindowTreeHostX11::DispatchEvent( + } + break; + } ++ case DestroyNotify: ++ xwindow_destroyed_ = true; ++ CloseNow(); ++ break; + case FocusOut: + if (xev->xfocus.mode != NotifyGrab) { + ReleaseCapture(); +diff --git desktop_aura/desktop_window_tree_host_x11.h desktop_aura/desktop_window_tree_host_x11.h +index bc20464..63527ae 100644 +--- desktop_aura/desktop_window_tree_host_x11.h ++++ desktop_aura/desktop_window_tree_host_x11.h +@@ -299,6 +299,9 @@ private: + // the frame when |xwindow_| gains focus or handles a mouse button event. + bool urgency_hint_set_; + ++ // True if the xwindow has already been destroyed. ++ bool xwindow_destroyed_; ++ + DISALLOW_COPY_AND_ASSIGN(DesktopWindowTreeHostX11); + }; + +diff --git widget.cc widget.cc +index e05db49..a936235 100644 +--- widget.cc ++++ widget.cc +@@ -122,6 +122,7 @@ Widget::InitParams::InitParams() show_state(ui::SHOW_STATE_DEFAULT), double_buffer(false), parent(NULL), -+ parent_widget(NULL), ++ parent_widget(gfx::kNullAcceleratedWidget), native_widget(NULL), desktop_window_tree_host(NULL), top_level(false), -@@ -148,6 +149,7 @@ +@@ -148,6 +149,7 @@ Widget::InitParams::InitParams(Type type) show_state(ui::SHOW_STATE_DEFAULT), double_buffer(false), parent(NULL), -+ parent_widget(NULL), ++ parent_widget(gfx::kNullAcceleratedWidget), native_widget(NULL), desktop_window_tree_host(NULL), top_level(false), -@@ -386,7 +388,12 @@ +@@ -386,7 +388,12 @@ void Widget::Init(const InitParams& in_params) { Minimize(); } else if (params.delegate) { SetContentsView(params.delegate->GetContentsView()); @@ -72,11 +136,11 @@ Index: widget.cc } native_widget_initialized_ = true; } -Index: widget.h -=================================================================== ---- widget.h (revision 263053) -+++ widget.h (working copy) -@@ -200,6 +200,7 @@ +diff --git widget.h widget.h +index 640b140..43feff7 100644 +--- widget.h ++++ widget.h +@@ -200,6 +200,7 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, // Should the widget be double buffered? Default is false. bool double_buffer; gfx::NativeView parent; diff --git a/tests/cefclient/cefclient.cpp b/tests/cefclient/cefclient.cpp index 203e1377a..a1dd69a56 100644 --- a/tests/cefclient/cefclient.cpp +++ b/tests/cefclient/cefclient.cpp @@ -27,9 +27,9 @@ CefRefPtr AppGetBrowser() { return g_handler->GetBrowser(); } -CefWindowHandle AppGetMainHwnd() { +ClientWindowHandle AppGetMainHwnd() { if (!g_handler.get()) - return NULL; + return kNullWindowHandle; return g_handler->GetMainHwnd(); } diff --git a/tests/cefclient/cefclient.h b/tests/cefclient/cefclient.h index 1978df664..5a467f02c 100644 --- a/tests/cefclient/cefclient.h +++ b/tests/cefclient/cefclient.h @@ -9,6 +9,7 @@ #include #include "include/cef_base.h" #include "cefclient/client_app.h" +#include "cefclient/client_handler.h" class CefApp; class CefBrowser; @@ -18,7 +19,7 @@ class CefCommandLine; CefRefPtr AppGetBrowser(); // Returns the main application window handle. -CefWindowHandle AppGetMainHwnd(); +ClientWindowHandle AppGetMainHwnd(); // Returns the application working directory. std::string AppGetWorkingDirectory(); diff --git a/tests/cefclient/cefclient_gtk.cpp b/tests/cefclient/cefclient_gtk.cpp index 53c6be6b4..20aeb3107 100644 --- a/tests/cefclient/cefclient_gtk.cpp +++ b/tests/cefclient/cefclient_gtk.cpp @@ -6,11 +6,17 @@ // in order for gtkglext to compile. #undef GTK_DISABLE_SINGLE_INCLUDES +#include +#include #include -#include + +#include +#undef Success // Definition conflicts with cef_message_router.h + #include #include #include + #include "cefclient/cefclient.h" #include "include/cef_app.h" #include "include/cef_browser.h" @@ -21,11 +27,16 @@ #include "cefclient/scheme_test.h" #include "cefclient/string_util.h" -char szWorkingDir[512]; // The current working directory - // The global ClientHandler reference. extern CefRefPtr g_handler; +namespace { + +char szWorkingDir[512]; // The current working directory + +// Height of the buttons at the top of the GTK window. +int g_toolbar_height = 0; + void destroy(GtkWidget* widget, gpointer data) { // Quitting CEF is handled in ClientHandler::OnBeforeClose(). } @@ -53,6 +64,46 @@ void TerminationSignalHandler(int signatl) { AppQuitMessageLoop(); } +void VboxSizeAllocated(GtkWidget *widget, + GtkAllocation *allocation, + void *data) { + if (g_handler) { + CefRefPtr browser = g_handler->GetBrowser(); + if (browser) { + // Size the browser window to match the GTK widget. + ::Display* xdisplay = cef_get_xdisplay(); + ::Window xwindow = browser->GetHost()->GetWindowHandle(); + XWindowChanges changes = {0}; + changes.width = allocation->width; + changes.height = allocation->height - g_toolbar_height; + XConfigureWindow(xdisplay, xwindow, CWHeight | CWWidth, &changes); + } + } +} + +void ToolbarSizeAllocated(GtkWidget *widget, + GtkAllocation *allocation, + void *data) { + g_toolbar_height = allocation->height; +} + +gboolean WindowFocusIn(GtkWidget* widget, + GdkEventFocus* event, + gpointer user_data) { + if (g_handler && event->in) { + CefRefPtr browser = g_handler->GetBrowser(); + if (browser) { + // Give focus to the browser window. + ::Display* xdisplay = cef_get_xdisplay(); + ::Window xwindow = browser->GetHost()->GetWindowHandle(); + XSetInputFocus(xdisplay, xwindow, RevertToParent, CurrentTime); + return TRUE; + } + } + + return FALSE; +} + // Callback for Tests > Get Source... menu item. gboolean GetSourceActivated(GtkWidget* widget) { if (g_handler.get() && g_handler->GetBrowserId()) @@ -188,6 +239,20 @@ void URLEntryActivate(GtkEntry* entry) { g_handler->GetBrowser()->GetMainFrame()->LoadURL(std::string(url).c_str()); } +gboolean URLEntryButtonPress(GtkWidget* widget, + GdkEventButton* event, + gpointer user_data) { + // Give focus to the GTK window. + GtkWidget* window = gtk_widget_get_ancestor(widget, + GTK_TYPE_WINDOW); + GdkWindow* gdk_window = gtk_widget_get_window(window); + ::Display* xdisplay = GDK_WINDOW_XDISPLAY(gdk_window); + ::Window xwindow = GDK_WINDOW_XID(gdk_window); + XSetInputFocus(xdisplay, xwindow, RevertToParent, CurrentTime); + + return FALSE; +} + // GTK utility functions ---------------------------------------------- GtkWidget* AddMenuEntry(GtkWidget* menu_widget, const char* text, @@ -237,16 +302,7 @@ GtkWidget* CreateMenuBar() { return menu_bar; } -// WebViewDelegate::TakeFocus in the test webview delegate. -static gboolean HandleFocus(GtkWidget* widget, - GdkEventFocus* focus) { - if (g_handler.get() && g_handler->GetBrowserId()) { - // Give focus to the browser window. - g_handler->GetBrowser()->GetHost()->SetFocus(true); - } - - return TRUE; -} +} // namespace int main(int argc, char* argv[]) { CefMainArgs main_args(argc, argv); @@ -260,13 +316,6 @@ int main(int argc, char* argv[]) { if (!getcwd(szWorkingDir, sizeof (szWorkingDir))) return -1; - GtkWidget* window; - - gtk_init(&argc, &argv); - - // Perform gtkglext initialization required by the OSR example. - gtk_gl_init(&argc, &argv); - // Parse command line arguments. AppInitCommandLine(argc, argv); @@ -278,15 +327,22 @@ int main(int argc, char* argv[]) { // Initialize CEF. CefInitialize(main_args, settings, app.get(), NULL); + // The Chromium sandbox requires that there only be a single thread during + // initialization. Therefore initialize GTK after CEF. + gtk_init(&argc, &argv); + // Register the scheme handler. scheme_test::InitTest(); - window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_default_size(GTK_WINDOW(window), 800, 600); - - g_signal_connect(window, "focus", G_CALLBACK(&HandleFocus), NULL); + g_signal_connect(window, "focus-in-event", + G_CALLBACK(WindowFocusIn), NULL); GtkWidget* vbox = gtk_vbox_new(FALSE, 0); + g_signal_connect(vbox, "size-allocate", + G_CALLBACK(VboxSizeAllocated), NULL); + gtk_container_add(GTK_CONTAINER(window), vbox); GtkWidget* menu_bar = CreateMenuBar(); @@ -295,6 +351,8 @@ int main(int argc, char* argv[]) { GtkWidget* toolbar = gtk_toolbar_new(); // Turn off the labels on the toolbar buttons. gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), GTK_TOOLBAR_ICONS); + g_signal_connect(toolbar, "size-allocate", + G_CALLBACK(ToolbarSizeAllocated), NULL); GtkToolItem* back = gtk_tool_button_new_from_stock(GTK_STOCK_GO_BACK); g_signal_connect(back, "clicked", @@ -316,12 +374,14 @@ int main(int argc, char* argv[]) { G_CALLBACK(StopButtonClicked), NULL); gtk_toolbar_insert(GTK_TOOLBAR(toolbar), stop, -1 /* append */); - GtkWidget* m_editWnd = gtk_entry_new(); - g_signal_connect(G_OBJECT(m_editWnd), "activate", + GtkWidget* entry = gtk_entry_new(); + g_signal_connect(entry, "activate", G_CALLBACK(URLEntryActivate), NULL); + g_signal_connect(entry, "button-press-event", + G_CALLBACK(URLEntryButtonPress), NULL); GtkToolItem* tool_item = gtk_tool_item_new(); - gtk_container_add(GTK_CONTAINER(tool_item), m_editWnd); + gtk_container_add(GTK_CONTAINER(tool_item), entry); gtk_tool_item_set_expand(tool_item, TRUE); gtk_toolbar_insert(GTK_TOOLBAR(toolbar), tool_item, -1); // append @@ -335,24 +395,27 @@ int main(int argc, char* argv[]) { // Create the handler. g_handler = new ClientHandler(); g_handler->SetMainHwnd(vbox); - g_handler->SetEditHwnd(m_editWnd); + g_handler->SetEditHwnd(entry); g_handler->SetButtonHwnds(GTK_WIDGET(back), GTK_WIDGET(forward), GTK_WIDGET(reload), GTK_WIDGET(stop)); - // Create the browser view. + // Show the GTK window. + gtk_widget_show_all(GTK_WIDGET(window)); + CefWindowInfo window_info; CefBrowserSettings browserSettings; - window_info.SetAsChild(vbox); + // The GTK window must be visible before we can retrieve the XID. + ::Window xwindow = GDK_WINDOW_XID(gtk_widget_get_window(window)); + window_info.SetAsChild(xwindow, + CefRect(0, g_toolbar_height, 800, 600 - g_toolbar_height)); + // Create the browser window. CefBrowserHost::CreateBrowserSync( window_info, g_handler.get(), g_handler->GetStartupURL(), browserSettings, NULL); - gtk_container_add(GTK_CONTAINER(window), vbox); - gtk_widget_show_all(GTK_WIDGET(window)); - - // Install an signal handler so we clean up after ourselves. + // Install a signal handler so we clean up after ourselves. signal(SIGINT, TerminationSignalHandler); signal(SIGTERM, TerminationSignalHandler); diff --git a/tests/cefclient/client_handler.cpp b/tests/cefclient/client_handler.cpp index 419aeb0fe..dcd21dc30 100644 --- a/tests/cefclient/client_handler.cpp +++ b/tests/cefclient/client_handler.cpp @@ -485,20 +485,20 @@ void ClientHandler::OnRenderProcessTerminated(CefRefPtr browser, } } -void ClientHandler::SetMainHwnd(CefWindowHandle hwnd) { +void ClientHandler::SetMainHwnd(ClientWindowHandle hwnd) { AutoLock lock_scope(this); m_MainHwnd = hwnd; } -void ClientHandler::SetEditHwnd(CefWindowHandle hwnd) { +void ClientHandler::SetEditHwnd(ClientWindowHandle hwnd) { AutoLock lock_scope(this); m_EditHwnd = hwnd; } -void ClientHandler::SetButtonHwnds(CefWindowHandle backHwnd, - CefWindowHandle forwardHwnd, - CefWindowHandle reloadHwnd, - CefWindowHandle stopHwnd) { +void ClientHandler::SetButtonHwnds(ClientWindowHandle backHwnd, + ClientWindowHandle forwardHwnd, + ClientWindowHandle reloadHwnd, + ClientWindowHandle stopHwnd) { AutoLock lock_scope(this); m_BackHwnd = backHwnd; m_ForwardHwnd = forwardHwnd; diff --git a/tests/cefclient/client_handler.h b/tests/cefclient/client_handler.h index ee6d1f479..3d2817aac 100644 --- a/tests/cefclient/client_handler.h +++ b/tests/cefclient/client_handler.h @@ -14,12 +14,18 @@ #include "include/wrapper/cef_message_router.h" #include "cefclient/util.h" +#if defined(OS_LINUX) +// The Linux client uses GTK instead of the underlying platform type (X11). +#include +#define ClientWindowHandle GtkWidget* +#else +#define ClientWindowHandle CefWindowHandle +#endif // Define this value to redirect all popup URLs to the main application browser // window. // #define TEST_REDIRECT_POPUP_URLS - // ClientHandler implementation. class ClientHandler : public CefClient, public CefContextMenuHandler, @@ -156,13 +162,13 @@ class ClientHandler : public CefClient, virtual void OnRenderProcessTerminated(CefRefPtr browser, TerminationStatus status) OVERRIDE; - void SetMainHwnd(CefWindowHandle hwnd); - CefWindowHandle GetMainHwnd() { return m_MainHwnd; } - void SetEditHwnd(CefWindowHandle hwnd); - void SetButtonHwnds(CefWindowHandle backHwnd, - CefWindowHandle forwardHwnd, - CefWindowHandle reloadHwnd, - CefWindowHandle stopHwnd); + void SetMainHwnd(ClientWindowHandle hwnd); + ClientWindowHandle GetMainHwnd() { return m_MainHwnd; } + void SetEditHwnd(ClientWindowHandle hwnd); + void SetButtonHwnds(ClientWindowHandle backHwnd, + ClientWindowHandle forwardHwnd, + ClientWindowHandle reloadHwnd, + ClientWindowHandle stopHwnd); CefRefPtr GetBrowser() { return m_Browser; } int GetBrowserId() { return m_BrowserId; } @@ -229,7 +235,7 @@ class ClientHandler : public CefClient, BrowserList m_PopupBrowsers; // The main frame window handle - CefWindowHandle m_MainHwnd; + ClientWindowHandle m_MainHwnd; // The child browser id int m_BrowserId; @@ -238,13 +244,13 @@ class ClientHandler : public CefClient, bool m_bIsClosing; // The edit window handle - CefWindowHandle m_EditHwnd; + ClientWindowHandle m_EditHwnd; // The button window handles - CefWindowHandle m_BackHwnd; - CefWindowHandle m_ForwardHwnd; - CefWindowHandle m_StopHwnd; - CefWindowHandle m_ReloadHwnd; + ClientWindowHandle m_BackHwnd; + ClientWindowHandle m_ForwardHwnd; + ClientWindowHandle m_StopHwnd; + ClientWindowHandle m_ReloadHwnd; // Support for logging. std::string m_LogFile; diff --git a/tests/cefclient/client_handler_gtk.cpp b/tests/cefclient/client_handler_gtk.cpp index 2cd10e4c3..5939032f6 100644 --- a/tests/cefclient/client_handler_gtk.cpp +++ b/tests/cefclient/client_handler_gtk.cpp @@ -1,9 +1,14 @@ -// Copyright (c) 2011 The Chromium Embedded Framework Authors. All rights +// Copyright (c) 2014 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 +#include +#include +#undef Success // Definition conflicts with cef_message_router.h + #include + #include "cefclient/client_handler.h" #include "include/cef_browser.h" #include "include/cef_frame.h" @@ -24,11 +29,49 @@ void ClientHandler::OnTitleChange(CefRefPtr browser, const CefString& title) { REQUIRE_UI_THREAD(); - GtkWidget* window = gtk_widget_get_ancestor( - GTK_WIDGET(browser->GetHost()->GetWindowHandle()), - GTK_TYPE_WINDOW); std::string titleStr(title); - gtk_window_set_title(GTK_WINDOW(window), titleStr.c_str()); + + if (!browser->IsPopup()) { + // Set the GTK parent window title. + GtkWidget* window = gtk_widget_get_ancestor(m_MainHwnd, + GTK_TYPE_WINDOW); + gtk_window_set_title(GTK_WINDOW(window), titleStr.c_str()); + } else { + // Retrieve the X11 display shared with Chromium. + ::Display* display = cef_get_xdisplay(); + ASSERT(display); + + // Retrieve the X11 window handle for the browser. + ::Window window = browser->GetHost()->GetWindowHandle(); + ASSERT(window != kNullWindowHandle); + + // Retrieve the atoms required by the below XChangeProperty call. + const char* kAtoms[] = { + "_NET_WM_NAME", + "UTF8_STRING" + }; + Atom atoms[2]; + int result = XInternAtoms(display, const_cast(kAtoms), 2, false, + atoms); + ASSERT(result); + + // Set the window title. + XChangeProperty(display, + window, + atoms[0], + atoms[1], + 8, + PropModeReplace, + reinterpret_cast(titleStr.c_str()), + titleStr.size()); + + // TODO(erg): This is technically wrong. So XStoreName and friends expect + // this in Host Portable Character Encoding instead of UTF-8, which I + // believe is Compound Text. This shouldn't matter 90% of the time since + // this is the fallback to the UTF8 property above. + XStoreName(display, browser->GetHost()->GetWindowHandle(), + titleStr.c_str()); + } } void ClientHandler::SendNotification(NotificationType type) { @@ -57,3 +100,4 @@ void ClientHandler::SetNavState(bool canGoBack, bool canGoForward) { std::string ClientHandler::GetDownloadPath(const std::string& file_name) { return std::string(); } + diff --git a/tests/cefclient/resource_util_linux.cpp b/tests/cefclient/resource_util_linux.cpp index aa4f4a939..8b5c822e0 100644 --- a/tests/cefclient/resource_util_linux.cpp +++ b/tests/cefclient/resource_util_linux.cpp @@ -6,6 +6,7 @@ #include "cefclient/resource_util.h" #include #include +#include bool GetResourceDir(std::string& dir) { char buff[1024]; diff --git a/tests/cefsimple/cefsimple_gtk.cpp b/tests/cefsimple/cefsimple_linux.cpp similarity index 94% rename from tests/cefsimple/cefsimple_gtk.cpp rename to tests/cefsimple/cefsimple_linux.cpp index 8ec9d1deb..18f9c711f 100644 --- a/tests/cefsimple/cefsimple_gtk.cpp +++ b/tests/cefsimple/cefsimple_linux.cpp @@ -2,8 +2,6 @@ // reserved. Use of this source code is governed by a BSD-style license that // can be found in the LICENSE file. -#include - #include "cefsimple/simple_app.h" // Entry point function for all processes. @@ -24,9 +22,6 @@ int main(int argc, char* argv[]) { return exit_code; } - // Initialize GTK. - gtk_init(&argc, &argv); - // Specify CEF global settings here. CefSettings settings; diff --git a/tests/cefsimple/simple_handler_gtk.cpp b/tests/cefsimple/simple_handler_gtk.cpp deleted file mode 100644 index 898c4c0d0..000000000 --- a/tests/cefsimple/simple_handler_gtk.cpp +++ /dev/null @@ -1,22 +0,0 @@ -// 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 "cefsimple/simple_handler.h" - -#include -#include - -#include "cefsimple/util.h" -#include "include/cef_browser.h" - -void SimpleHandler::OnTitleChange(CefRefPtr browser, - const CefString& title) { - REQUIRE_UI_THREAD(); - - GtkWidget* window = gtk_widget_get_ancestor( - GTK_WIDGET(browser->GetHost()->GetWindowHandle()), - GTK_TYPE_WINDOW); - std::string titleStr(title); - gtk_window_set_title(GTK_WINDOW(window), titleStr.c_str()); -} diff --git a/tests/cefsimple/simple_handler_linux.cpp b/tests/cefsimple/simple_handler_linux.cpp new file mode 100644 index 000000000..fadba3c59 --- /dev/null +++ b/tests/cefsimple/simple_handler_linux.cpp @@ -0,0 +1,52 @@ +// Copyright (c) 2014 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 "cefsimple/simple_handler.h" + +#include +#include +#include + +#include "cefsimple/util.h" +#include "include/cef_browser.h" + +void SimpleHandler::OnTitleChange(CefRefPtr browser, + const CefString& title) { + REQUIRE_UI_THREAD(); + std::string titleStr(title); + + // Retrieve the X11 display shared with Chromium. + ::Display* display = cef_get_xdisplay(); + ASSERT(display); + + // Retrieve the X11 window handle for the browser. + ::Window window = browser->GetHost()->GetWindowHandle(); + ASSERT(window != kNullWindowHandle); + + // Retrieve the atoms required by the below XChangeProperty call. + const char* kAtoms[] = { + "_NET_WM_NAME", + "UTF8_STRING" + }; + Atom atoms[2]; + int result = XInternAtoms(display, const_cast(kAtoms), 2, false, atoms); + ASSERT(result); + + // Set the window title. + XChangeProperty(display, + window, + atoms[0], + atoms[1], + 8, + PropModeReplace, + reinterpret_cast(titleStr.c_str()), + titleStr.size()); + + // TODO(erg): This is technically wrong. So XStoreName and friends expect + // this in Host Portable Character Encoding instead of UTF-8, which I believe + // is Compound Text. This shouldn't matter 90% of the time since this is the + // fallback to the UTF8 property above. + XStoreName(display, browser->GetHost()->GetWindowHandle(), titleStr.c_str()); +} + diff --git a/tools/cef_parser.py b/tools/cef_parser.py index 658ab902f..3516c802e 100644 --- a/tools/cef_parser.py +++ b/tools/cef_parser.py @@ -377,10 +377,9 @@ _simpletypes = { 'bool' : ['int', '0'], 'char': ['char', '0'], 'char* const': ['char* const', 'NULL'], - 'CefCursorHandle' : ['cef_cursor_handle_t', 'NULL'], - 'CefEventHandle' : ['cef_event_handle_t', 'NULL'], - 'CefWindowHandle' : ['cef_window_handle_t', 'NULL'], - 'CefTextInputContext' : ['cef_text_input_context_t' ,'NULL'], + 'CefCursorHandle' : ['cef_cursor_handle_t', 'kNullCursorHandle'], + 'CefEventHandle' : ['cef_event_handle_t', 'kNullEventHandle'], + 'CefWindowHandle' : ['cef_window_handle_t', 'kNullWindowHandle'], 'CefRect' : ['cef_rect_t', 'CefRect()'], 'CefThreadId' : ['cef_thread_id_t', 'TID_UI'], 'CefTime' : ['cef_time_t', 'CefTime()'], diff --git a/tools/distrib/cefclient.gyp b/tools/distrib/cefclient.gyp index f8f040bb3..8ab15b7d0 100644 --- a/tools/distrib/cefclient.gyp +++ b/tools/distrib/cefclient.gyp @@ -231,7 +231,6 @@ ], 'dependencies': [ 'gtk', - 'gtkglext', ], 'link_settings': { 'ldflags': [ @@ -241,6 +240,7 @@ ], 'libraries': [ "$(BUILDTYPE)/libcef.so", + "-lX11", ], }, 'sources': [ @@ -442,9 +442,6 @@ ], }, ], - 'dependencies': [ - 'gtk', - ], 'link_settings': { 'ldflags': [ # Look for libcef.so in the current directory. Path can also be @@ -453,6 +450,7 @@ ], 'libraries': [ "$(BUILDTYPE)/libcef.so", + "-lX11", ], }, 'sources': [ @@ -652,27 +650,6 @@ ], }, }, - { - 'target_name': 'gtkglext', - 'type': 'none', - 'variables': { - # gtkglext is required by the cefclient OSR example. - 'gtk_packages': 'gtkglext-1.0', - }, - 'direct_dependent_settings': { - 'cflags': [ - '$(shell <(pkg-config) --cflags <(gtk_packages))', - ], - }, - 'link_settings': { - 'ldflags': [ - '$(shell <(pkg-config) --libs-only-L --libs-only-other <(gtk_packages))', - ], - 'libraries': [ - '$(shell <(pkg-config) --libs-only-l <(gtk_packages))', - ], - }, - }, ], }], # OS=="linux" or OS=="freebsd" or OS=="openbsd" ],