- cefclient: Linux: Introduce RootWindow concept and associated window/client object hierarchy (issue #1500).

git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@2004 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
Marshall Greenblatt 2015-01-29 20:53:53 +00:00
parent 37464c2a4c
commit 89de4a5bb6
32 changed files with 1928 additions and 933 deletions

View File

@ -160,6 +160,7 @@
'tests/cefclient/client_renderer.h',
'tests/cefclient/client_switches.cc',
'tests/cefclient/client_switches.h',
'tests/cefclient/client_types.h',
'tests/cefclient/dialog_test.cc',
'tests/cefclient/dialog_test.h',
'tests/cefclient/main_context.cc',
@ -187,12 +188,12 @@
'<@(cefclient_bundle_resources_common)',
],
'cefclient_sources_win': [
'tests/cefclient/browser_window.cc',
'tests/cefclient/browser_window.h',
'tests/cefclient/browser_window_osr_win.cc',
'tests/cefclient/browser_window_osr_win.h',
'tests/cefclient/browser_window_std_win.cc',
'tests/cefclient/browser_window_std_win.h',
'tests/cefclient/browser_window_win.cc',
'tests/cefclient/browser_window_win.h',
'tests/cefclient/cefclient.exe.manifest',
'tests/cefclient/cefclient.rc',
'tests/cefclient/cefclient_win.cc',
@ -279,18 +280,32 @@
],
'cefclient_sources_linux': [
'tests/cefclient/cefclient_gtk.cc',
'tests/cefclient/client_handler_shared.cc',
'tests/cefclient/client_handler_shared.h',
'tests/cefclient/client_handler_shared_gtk.cc',
'tests/cefclient/browser_window.cc',
'tests/cefclient/browser_window.h',
'tests/cefclient/browser_window_osr_gtk.cc',
'tests/cefclient/browser_window_osr_gtk.h',
'tests/cefclient/browser_window_std_gtk.cc',
'tests/cefclient/browser_window_std_gtk.h',
'tests/cefclient/client_handler_osr.cc',
'tests/cefclient/client_handler_osr.h',
'tests/cefclient/client_handler_single.cc',
'tests/cefclient/client_handler_single.h',
'tests/cefclient/client_handler_std.cc',
'tests/cefclient/client_handler_std.h',
'tests/cefclient/dialog_handler_gtk.cc',
'tests/cefclient/dialog_handler_gtk.h',
'tests/cefclient/main_context_impl_posix.cc',
'tests/cefclient/osr_widget_gtk.h',
'tests/cefclient/osr_widget_gtk.cc',
'tests/cefclient/print_handler_gtk.cc',
'tests/cefclient/print_handler_gtk.h',
'tests/cefclient/resource_util_linux.cc',
'tests/cefclient/resource_util_posix.cc',
'tests/cefclient/root_window.h',
'tests/cefclient/root_window_manager.cc',
'tests/cefclient/root_window_manager.h',
'tests/cefclient/root_window_gtk.cc',
'tests/cefclient/root_window_gtk.h',
'tests/cefclient/temp_window_x11.cc',
'tests/cefclient/temp_window_x11.h',
'tests/cefclient/window_test_gtk.cc',
],
'cefclient_bundle_resources_linux': [

View File

@ -2,30 +2,30 @@
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#include "cefclient/browser_window_win.h"
#include "cefclient/browser_window.h"
#include "include/base/cef_bind.h"
#include "cefclient/main_message_loop.h"
namespace client {
BrowserWindowWin::BrowserWindowWin(Delegate* delegate)
BrowserWindow::BrowserWindow(Delegate* delegate)
: delegate_(delegate),
is_closing_(false) {
DCHECK(delegate_);
}
CefRefPtr<CefBrowser> BrowserWindowWin::GetBrowser() const {
CefRefPtr<CefBrowser> BrowserWindow::GetBrowser() const {
REQUIRE_MAIN_THREAD();
return browser_;
}
bool BrowserWindowWin::IsClosing() const {
bool BrowserWindow::IsClosing() const {
REQUIRE_MAIN_THREAD();
return is_closing_;
}
void BrowserWindowWin::OnBrowserCreated(CefRefPtr<CefBrowser> browser) {
void BrowserWindow::OnBrowserCreated(CefRefPtr<CefBrowser> browser) {
REQUIRE_MAIN_THREAD();
DCHECK(!browser_);
browser_ = browser;
@ -33,13 +33,13 @@ void BrowserWindowWin::OnBrowserCreated(CefRefPtr<CefBrowser> browser) {
delegate_->OnBrowserCreated(browser);
}
void BrowserWindowWin::OnBrowserClosing(CefRefPtr<CefBrowser> browser) {
void BrowserWindow::OnBrowserClosing(CefRefPtr<CefBrowser> browser) {
REQUIRE_MAIN_THREAD();
DCHECK_EQ(browser->GetIdentifier(), browser_->GetIdentifier());
is_closing_ = true;
}
void BrowserWindowWin::OnBrowserClosed(CefRefPtr<CefBrowser> browser) {
void BrowserWindow::OnBrowserClosed(CefRefPtr<CefBrowser> browser) {
REQUIRE_MAIN_THREAD();
DCHECK_EQ(browser->GetIdentifier(), browser_->GetIdentifier());
browser_ = NULL;
@ -51,19 +51,19 @@ void BrowserWindowWin::OnBrowserClosed(CefRefPtr<CefBrowser> browser) {
delegate_->OnBrowserWindowDestroyed();
}
void BrowserWindowWin::OnSetAddress(const std::string& url) {
void BrowserWindow::OnSetAddress(const std::string& url) {
REQUIRE_MAIN_THREAD();
delegate_->OnSetAddress(url);
}
void BrowserWindowWin::OnSetTitle(const std::string& title) {
void BrowserWindow::OnSetTitle(const std::string& title) {
REQUIRE_MAIN_THREAD();
delegate_->OnSetTitle(title);
}
void BrowserWindowWin::OnSetLoadingState(bool isLoading,
bool canGoBack,
bool canGoForward) {
void BrowserWindow::OnSetLoadingState(bool isLoading,
bool canGoBack,
bool canGoForward) {
REQUIRE_MAIN_THREAD();
delegate_->OnSetLoadingState(isLoading, canGoBack, canGoForward);
}

View File

@ -2,21 +2,20 @@
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#ifndef CEF_TESTS_CEFCLIENT_BROWSER_WINDOW_WIN_H_
#define CEF_TESTS_CEFCLIENT_BROWSER_WINDOW_WIN_H_
#include <windows.h>
#ifndef CEF_TESTS_CEFCLIENT_BROWSER_WINDOW_H_
#define CEF_TESTS_CEFCLIENT_BROWSER_WINDOW_H_
#include "include/base/cef_scoped_ptr.h"
#include "include/cef_browser.h"
#include "cefclient/client_handler_single.h"
#include "cefclient/client_types.h"
namespace client {
// Represents a native child window hosting a single browser instance. The
// methods of this class must be called on the main thread unless otherwise
// indicated.
class BrowserWindowWin : public ClientHandlerSingle::Delegate {
class BrowserWindow : public ClientHandlerSingle::Delegate {
public:
// This interface is implemented by the owner of the BrowserWindowWin. The
// methods of this class will be called on the main thread.
@ -44,20 +43,22 @@ class BrowserWindowWin : public ClientHandlerSingle::Delegate {
};
// Create a new browser and native window.
virtual void CreateBrowser(HWND parent_hwnd,
const RECT& rect,
virtual void CreateBrowser(ClientWindowHandle parent_handle,
const CefRect& rect,
const CefBrowserSettings& settings) = 0;
// Retrieve the configuration that will be used when creating a popup window.
// The native window will be created later after the browser has been created.
// This method may be called on any thread.
virtual void GetPopupConfig(HWND temp_hwnd,
// The popup browser will initially be parented to |temp_handle| which should
// be a pre-existing hidden window. The native window will be created later
// after the browser has been created. This method may be called on any
// thread.
virtual void GetPopupConfig(CefWindowHandle temp_handle,
CefWindowInfo& windowInfo,
CefRefPtr<CefClient>& client,
CefBrowserSettings& settings) = 0;
// Show the popup window with correct parent and bounds in parent coordinates.
virtual void ShowPopup(HWND parent_hwnd,
virtual void ShowPopup(ClientWindowHandle parent_handle,
int x, int y, size_t width, size_t height) = 0;
// Show the window.
@ -73,7 +74,7 @@ class BrowserWindowWin : public ClientHandlerSingle::Delegate {
virtual void SetFocus() = 0;
// Returns the window handle.
virtual HWND GetHWND() const = 0;
virtual ClientWindowHandle GetWindowHandle() const = 0;
// Returns the browser owned by the window.
CefRefPtr<CefBrowser> GetBrowser() const;
@ -83,11 +84,11 @@ class BrowserWindowWin : public ClientHandlerSingle::Delegate {
protected:
// Allow deletion via scoped_ptr only.
friend struct base::DefaultDeleter<BrowserWindowWin>;
friend struct base::DefaultDeleter<BrowserWindow>;
// Constructor may be called on any thread.
// |root_window| and |delegate| must outlive this object.
explicit BrowserWindowWin(Delegate* delegate);
explicit BrowserWindow(Delegate* delegate);
// ClientHandlerSingle::Delegate methods.
void OnBrowserCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
@ -104,9 +105,9 @@ class BrowserWindowWin : public ClientHandlerSingle::Delegate {
CefRefPtr<ClientHandlerSingle> client_handler_;
bool is_closing_;
DISALLOW_COPY_AND_ASSIGN(BrowserWindowWin);
DISALLOW_COPY_AND_ASSIGN(BrowserWindow);
};
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_BROWSER_WINDOW_WIN_H_
#endif // CEF_TESTS_CEFCLIENT_BROWSER_WINDOW_H_

View File

@ -1,8 +1,8 @@
// Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights
// Copyright (c) 2015 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#include "cefclient/osr_widget_gtk.h"
#include "cefclient/browser_window_osr_gtk.h"
#include <gdk/gdk.h>
#include <gdk/gdkkeysyms.h>
@ -17,23 +17,15 @@
#include <X11/XF86keysym.h>
#include <X11/Xcursor/Xcursor.h>
#include "include/base/cef_bind.h"
#include "include/base/cef_logging.h"
#include "include/wrapper/cef_closure_task.h"
#include "cefclient/main_message_loop.h"
namespace client {
namespace {
gint glarea_size_allocation(GtkWidget* widget,
GtkAllocation* allocation,
OSRWindow* window) {
CefRefPtr<CefBrowserHost> host = window->GetBrowserHost();
if (host)
host->WasResized();
return TRUE;
}
int get_cef_state_modifiers(guint state) {
int GetCefStateModifiers(guint state) {
int modifiers = 0;
if (state & GDK_SHIFT_MASK)
modifiers |= EVENTFLAG_SHIFT_DOWN;
@ -865,183 +857,7 @@ int GetControlCharacter(KeyboardCode windows_key_code, bool shift) {
}
}
gint glarea_click_event(GtkWidget* widget,
GdkEventButton* event,
OSRWindow* window) {
CefRefPtr<CefBrowserHost> host = window->GetBrowserHost();
if (!host)
return TRUE;
CefBrowserHost::MouseButtonType button_type = MBT_LEFT;
switch (event->button) {
case 1:
break;
case 2:
button_type = MBT_MIDDLE;
break;
case 3:
button_type = MBT_RIGHT;
break;
default:
// Other mouse buttons are not handled here.
return FALSE;
}
CefMouseEvent mouse_event;
mouse_event.x = event->x;
mouse_event.y = event->y;
window->ApplyPopupOffset(mouse_event.x, mouse_event.y);
mouse_event.modifiers = get_cef_state_modifiers(event->state);
bool mouse_up = (event->type == GDK_BUTTON_RELEASE);
if (!mouse_up)
gtk_widget_grab_focus(widget);
int click_count = 1;
switch (event->type) {
case GDK_2BUTTON_PRESS:
click_count = 2;
break;
case GDK_3BUTTON_PRESS:
click_count = 3;
break;
default:
break;
}
host->SendMouseClickEvent(mouse_event, button_type, mouse_up, click_count);
return TRUE;
}
gint glarea_move_event(GtkWidget* widget,
GdkEventMotion* event,
OSRWindow* window) {
CefRefPtr<CefBrowserHost> host = window->GetBrowserHost();
if (!host)
return TRUE;
gint x, y;
GdkModifierType state;
if (event->is_hint) {
gdk_window_get_pointer(event->window, &x, &y, &state);
} else {
x = (gint)event->x;
y = (gint)event->y;
state = (GdkModifierType)event->state;
}
CefMouseEvent mouse_event;
mouse_event.x = x;
mouse_event.y = y;
window->ApplyPopupOffset(mouse_event.x, mouse_event.y);
mouse_event.modifiers = get_cef_state_modifiers(state);
bool mouse_leave = (event->type == GDK_LEAVE_NOTIFY);
host->SendMouseMoveEvent(mouse_event, mouse_leave);
return TRUE;
}
gint glarea_scroll_event(GtkWidget* widget,
GdkEventScroll* event,
OSRWindow* window) {
CefRefPtr<CefBrowserHost> host = window->GetBrowserHost();
if (!host)
return TRUE;
CefMouseEvent mouse_event;
mouse_event.x = event->x;
mouse_event.y = event->y;
window->ApplyPopupOffset(mouse_event.x, mouse_event.y);
mouse_event.modifiers = get_cef_state_modifiers(event->state);
static const int scrollbarPixelsPerGtkTick = 40;
int deltaX = 0;
int deltaY = 0;
switch (event->direction) {
case GDK_SCROLL_UP:
deltaY = scrollbarPixelsPerGtkTick;
break;
case GDK_SCROLL_DOWN:
deltaY = -scrollbarPixelsPerGtkTick;
break;
case GDK_SCROLL_LEFT:
deltaX = scrollbarPixelsPerGtkTick;
break;
case GDK_SCROLL_RIGHT:
deltaX = -scrollbarPixelsPerGtkTick;
break;
}
host->SendMouseWheelEvent(mouse_event, deltaX, deltaY);
return TRUE;
}
gint glarea_key_event(GtkWidget* widget,
GdkEventKey* event,
OSRWindow* window) {
CefRefPtr<CefBrowserHost> host = window->GetBrowserHost();
if (!host)
return TRUE;
// Based on WebKeyboardEventBuilder::Build from
// content/browser/renderer_host/input/web_input_event_builders_gtk.cc.
CefKeyEvent key_event;
KeyboardCode windows_key_code = GdkEventToWindowsKeyCode(event);
key_event.windows_key_code =
GetWindowsKeyCodeWithoutLocation(windows_key_code);
key_event.native_key_code = event->hardware_keycode;
key_event.modifiers = get_cef_state_modifiers(event->state);
if (event->keyval >= GDK_KP_Space && event->keyval <= GDK_KP_9)
key_event.modifiers |= EVENTFLAG_IS_KEY_PAD;
if (key_event.modifiers & EVENTFLAG_ALT_DOWN)
key_event.is_system_key = true;
if (windows_key_code == VKEY_RETURN) {
// We need to treat the enter key as a key press of character \r. This
// is apparently just how webkit handles it and what it expects.
key_event.unmodified_character = '\r';
} else {
// FIXME: fix for non BMP chars
key_event.unmodified_character =
static_cast<int>(gdk_keyval_to_unicode(event->keyval));
}
// If ctrl key is pressed down, then control character shall be input.
if (key_event.modifiers & EVENTFLAG_CONTROL_DOWN) {
key_event.character =
GetControlCharacter(windows_key_code,
key_event.modifiers & EVENTFLAG_SHIFT_DOWN);
} else {
key_event.character = key_event.unmodified_character;
}
if (event->type == GDK_KEY_PRESS) {
key_event.type = KEYEVENT_RAWKEYDOWN;
host->SendKeyEvent(key_event);
} else {
// Need to send both KEYUP and CHAR events.
key_event.type = KEYEVENT_KEYUP;
host->SendKeyEvent(key_event);
key_event.type = KEYEVENT_CHAR;
host->SendKeyEvent(key_event);
}
return TRUE;
}
gint glarea_focus_event(GtkWidget* widget,
GdkEventFocus* event,
OSRWindow* window) {
CefRefPtr<CefBrowserHost> host = window->GetBrowserHost();
if (host)
host->SendFocusEvent(event->in == TRUE);
return TRUE;
}
void widget_get_rect_in_screen(GtkWidget* widget, GdkRectangle* r) {
void GetWidgetRectInScreen(GtkWidget* widget, GdkRectangle* r) {
gint x, y, w, h;
GdkRectangle extents;
@ -1095,26 +911,128 @@ class ScopedGLContext {
} // namespace
// static
CefRefPtr<OSRWindow> OSRWindow::Create(OSRBrowserProvider* browser_provider,
bool transparent,
bool show_update_rect,
ClientWindowHandle parentView) {
DCHECK(browser_provider);
if (!browser_provider)
return NULL;
return new OSRWindow(browser_provider, transparent, show_update_rect,
parentView);
BrowserWindowOsrGtk::BrowserWindowOsrGtk(BrowserWindow::Delegate* delegate,
const std::string& startup_url,
bool transparent,
bool show_update_rect)
: BrowserWindow(delegate),
renderer_(transparent, show_update_rect),
glarea_(NULL),
hidden_(false),
gl_enabled_(false),
painting_popup_(false) {
client_handler_ = new ClientHandlerOsr(this, this, startup_url);
}
// static
CefRefPtr<OSRWindow> OSRWindow::From(
CefRefPtr<ClientHandlerShared::RenderHandler> renderHandler) {
return static_cast<OSRWindow*>(renderHandler.get());
void BrowserWindowOsrGtk::CreateBrowser(ClientWindowHandle parent_handle,
const CefRect& rect,
const CefBrowserSettings& settings) {
REQUIRE_MAIN_THREAD();
// Set the window handle for GTK dialogs.
client_handler_->SetMainWindowHandle(parent_handle);
// Create the native window.
Create(parent_handle);
// Retrieve the X11 Window ID for the GTK parent window.
GtkWidget* window = gtk_widget_get_ancestor(
GTK_WIDGET(parent_handle), GTK_TYPE_WINDOW);
::Window xwindow = GDK_WINDOW_XID(gtk_widget_get_window(window));
DCHECK(xwindow);
CefWindowInfo window_info;
window_info.SetAsWindowless(xwindow, renderer_.IsTransparent());
// Create the browser asynchronously.
CefBrowserHost::CreateBrowser(window_info, client_handler_,
client_handler_->startup_url(),
settings, NULL);
}
void OSRWindow::OnBeforeClose(CefRefPtr<CefBrowser> browser) {
void BrowserWindowOsrGtk::GetPopupConfig(CefWindowHandle temp_handle,
CefWindowInfo& windowInfo,
CefRefPtr<CefClient>& client,
CefBrowserSettings& settings) {
// Note: This method may be called on any thread.
windowInfo.SetAsWindowless(temp_handle, renderer_.IsTransparent());
client = client_handler_;
}
void BrowserWindowOsrGtk::ShowPopup(ClientWindowHandle parent_handle,
int x, int y, size_t width, size_t height) {
REQUIRE_MAIN_THREAD();
DCHECK(browser_.get());
// Set the window handle for GTK dialogs.
client_handler_->SetMainWindowHandle(parent_handle);
// Create the native window.
Create(parent_handle);
// Send resize notification so the compositor is assigned the correct
// viewport size and begins rendering.
browser_->GetHost()->WasResized();
Show();
}
void BrowserWindowOsrGtk::Show() {
REQUIRE_MAIN_THREAD();
if (hidden_) {
// Set the browser as visible.
browser_->GetHost()->WasHidden(false);
hidden_ = false;
}
// Give focus to the browser.
browser_->GetHost()->SendFocusEvent(true);
}
void BrowserWindowOsrGtk::Hide() {
REQUIRE_MAIN_THREAD();
if (!browser_)
return;
// Remove focus from the browser.
browser_->GetHost()->SendFocusEvent(false);
if (!hidden_) {
// Set the browser as hidden.
browser_->GetHost()->WasHidden(true);
hidden_ = true;
}
}
void BrowserWindowOsrGtk::SetBounds(int x, int y, size_t width, size_t height) {
REQUIRE_MAIN_THREAD();
// Nothing to do here. GTK will take care of positioning in the container.
}
void BrowserWindowOsrGtk::SetFocus() {
REQUIRE_MAIN_THREAD();
if (glarea_)
gtk_widget_grab_focus(glarea_);
}
ClientWindowHandle BrowserWindowOsrGtk::GetWindowHandle() const {
REQUIRE_MAIN_THREAD();
return glarea_;
}
void BrowserWindowOsrGtk::OnAfterCreated(CefRefPtr<CefBrowser> browser) {
CEF_REQUIRE_UI_THREAD();
}
void BrowserWindowOsrGtk::OnBeforeClose(CefRefPtr<CefBrowser> browser) {
CEF_REQUIRE_UI_THREAD();
REQUIRE_MAIN_THREAD();
// Detach |this| from the ClientHandlerOsr.
static_cast<ClientHandlerOsr*>(client_handler_.get())->DetachOsrDelegate();
// Disconnect all signal handlers that reference |this|.
g_signal_handlers_disconnect_matched(glarea_, G_SIGNAL_MATCH_DATA, 0, 0,
NULL, NULL, this);
@ -1122,8 +1040,17 @@ void OSRWindow::OnBeforeClose(CefRefPtr<CefBrowser> browser) {
DisableGL();
}
bool OSRWindow::GetViewRect(CefRefPtr<CefBrowser> browser,
CefRect& rect) {
bool BrowserWindowOsrGtk::GetRootScreenRect(CefRefPtr<CefBrowser> browser,
CefRect& rect) {
CEF_REQUIRE_UI_THREAD();
return false;
}
bool BrowserWindowOsrGtk::GetViewRect(CefRefPtr<CefBrowser> browser,
CefRect& rect) {
CEF_REQUIRE_UI_THREAD();
REQUIRE_MAIN_THREAD();
if (!glarea_)
return false;
@ -1135,20 +1062,32 @@ bool OSRWindow::GetViewRect(CefRefPtr<CefBrowser> browser,
return true;
}
bool OSRWindow::GetScreenPoint(CefRefPtr<CefBrowser> browser,
int viewX,
int viewY,
int& screenX,
int& screenY) {
bool BrowserWindowOsrGtk::GetScreenPoint(CefRefPtr<CefBrowser> browser,
int viewX,
int viewY,
int& screenX,
int& screenY) {
CEF_REQUIRE_UI_THREAD();
REQUIRE_MAIN_THREAD();
GdkRectangle screen_rect;
widget_get_rect_in_screen(glarea_, &screen_rect);
GetWidgetRectInScreen(glarea_, &screen_rect);
screenX = screen_rect.x + viewX;
screenY = screen_rect.y + viewY;
return true;
}
void OSRWindow::OnPopupShow(CefRefPtr<CefBrowser> browser,
bool show) {
bool BrowserWindowOsrGtk::GetScreenInfo(CefRefPtr<CefBrowser> browser,
CefScreenInfo& screen_info) {
CEF_REQUIRE_UI_THREAD();
return false;
}
void BrowserWindowOsrGtk::OnPopupShow(CefRefPtr<CefBrowser> browser,
bool show) {
CEF_REQUIRE_UI_THREAD();
REQUIRE_MAIN_THREAD();
if (!show) {
renderer_.ClearPopupRects();
browser->GetHost()->Invalidate(PET_VIEW);
@ -1156,16 +1095,29 @@ void OSRWindow::OnPopupShow(CefRefPtr<CefBrowser> browser,
renderer_.OnPopupShow(browser, show);
}
void OSRWindow::OnPopupSize(CefRefPtr<CefBrowser> browser,
const CefRect& rect) {
void BrowserWindowOsrGtk::OnPopupSize(CefRefPtr<CefBrowser> browser,
const CefRect& rect) {
CEF_REQUIRE_UI_THREAD();
REQUIRE_MAIN_THREAD();
renderer_.OnPopupSize(browser, rect);
}
void OSRWindow::OnPaint(CefRefPtr<CefBrowser> browser,
PaintElementType type,
const RectList& dirtyRects,
const void* buffer,
int width, int height) {
void BrowserWindowOsrGtk::OnPaint(
CefRefPtr<CefBrowser> browser,
CefRenderHandler::PaintElementType type,
const CefRenderHandler::RectList& dirtyRects,
const void* buffer,
int width,
int height) {
CEF_REQUIRE_UI_THREAD();
REQUIRE_MAIN_THREAD();
if (width <= 2 && height <= 2) {
// Ignore really small buffer sizes while the widget is starting up.
return;
}
if (painting_popup_) {
renderer_.OnPaint(browser, type, dirtyRects, buffer, width, height);
return;
@ -1187,71 +1139,45 @@ void OSRWindow::OnPaint(CefRefPtr<CefBrowser> browser,
renderer_.Render();
}
void OSRWindow::OnCursorChange(CefRefPtr<CefBrowser> browser,
CefCursorHandle cursor,
CursorType type,
const CefCursorInfo& custom_cursor_info) {
void BrowserWindowOsrGtk::OnCursorChange(
CefRefPtr<CefBrowser> browser,
CefCursorHandle cursor,
CefRenderHandler::CursorType type,
const CefCursorInfo& custom_cursor_info) {
CEF_REQUIRE_UI_THREAD();
REQUIRE_MAIN_THREAD();
// Retrieve the X11 display shared with Chromium.
::Display* xdisplay = cef_get_xdisplay();
DCHECK(xdisplay);
// Retrieve the X11 window handle for OSR widget.
// Retrieve the X11 window handle for the GTK widget.
::Window xwindow = GDK_WINDOW_XID(gtk_widget_get_window(glarea_));
// Set the cursor.
XDefineCursor(xdisplay, xwindow, cursor);
}
void OSRWindow::Invalidate() {
if (!CefCurrentlyOn(TID_UI)) {
CefPostTask(TID_UI, base::Bind(&OSRWindow::Invalidate, this));
return;
}
// Don't post another task if the previous task is still pending.
if (render_task_pending_)
return;
render_task_pending_ = true;
// Render at 30fps.
static const int kRenderDelay = 1000 / 30;
CefPostDelayedTask(TID_UI, base::Bind(&OSRWindow::Render, this),
kRenderDelay);
bool BrowserWindowOsrGtk::StartDragging(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefDragData> drag_data,
CefRenderHandler::DragOperationsMask allowed_ops,
int x, int y) {
CEF_REQUIRE_UI_THREAD();
// TODO(port): Implement drag&drop support.
return false;
}
bool OSRWindow::IsOverPopupWidget(int x, int y) const {
const CefRect& rc = renderer_.popup_rect();
int popup_right = rc.x + rc.width;
int popup_bottom = rc.y + rc.height;
return (x >= rc.x) && (x < popup_right) &&
(y >= rc.y) && (y < popup_bottom);
void BrowserWindowOsrGtk::UpdateDragCursor(
CefRefPtr<CefBrowser> browser,
CefRenderHandler::DragOperation operation) {
CEF_REQUIRE_UI_THREAD();
}
int OSRWindow::GetPopupXOffset() const {
return renderer_.original_popup_rect().x - renderer_.popup_rect().x;
}
void BrowserWindowOsrGtk::Create(ClientWindowHandle parent_handle) {
REQUIRE_MAIN_THREAD();
DCHECK(!glarea_);
int OSRWindow::GetPopupYOffset() const {
return renderer_.original_popup_rect().y - renderer_.popup_rect().y;
}
void OSRWindow::ApplyPopupOffset(int& x, int& y) const {
if (IsOverPopupWidget(x, y)) {
x += GetPopupXOffset();
y += GetPopupYOffset();
}
}
OSRWindow::OSRWindow(OSRBrowserProvider* browser_provider,
bool transparent,
bool show_update_rect,
ClientWindowHandle parentView)
: renderer_(transparent, show_update_rect),
browser_provider_(browser_provider),
gl_enabled_(false),
painting_popup_(false),
render_task_pending_(false) {
glarea_ = gtk_drawing_area_new();
DCHECK(glarea_);
@ -1261,13 +1187,12 @@ OSRWindow::OSRWindow(OSRBrowserProvider* browser_provider,
GDK_GL_MODE_DOUBLE));
DCHECK(glconfig);
gtk_widget_set_gl_capability(glarea_, glconfig, NULL, TRUE,
GDK_GL_RGBA_TYPE);
gtk_widget_set_gl_capability(glarea_, glconfig, NULL, TRUE, GDK_GL_RGBA_TYPE);
gtk_widget_set_can_focus(glarea_, TRUE);
g_signal_connect(G_OBJECT(glarea_), "size_allocate",
G_CALLBACK(glarea_size_allocation), this);
G_CALLBACK(&BrowserWindowOsrGtk::SizeAllocation), this);
gtk_widget_set_events(glarea_,
GDK_BUTTON_PRESS_MASK |
@ -1281,49 +1206,265 @@ OSRWindow::OSRWindow(OSRBrowserProvider* browser_provider,
GDK_SCROLL_MASK |
GDK_FOCUS_CHANGE_MASK);
g_signal_connect(G_OBJECT(glarea_), "button_press_event",
G_CALLBACK(glarea_click_event), this);
G_CALLBACK(&BrowserWindowOsrGtk::ClickEvent), this);
g_signal_connect(G_OBJECT(glarea_), "button_release_event",
G_CALLBACK(glarea_click_event), this);
G_CALLBACK(&BrowserWindowOsrGtk::ClickEvent), this);
g_signal_connect(G_OBJECT(glarea_), "key_press_event",
G_CALLBACK(glarea_key_event), this);
G_CALLBACK(&BrowserWindowOsrGtk::KeyEvent), this);
g_signal_connect(G_OBJECT(glarea_), "key_release_event",
G_CALLBACK(glarea_key_event), this);
G_CALLBACK(&BrowserWindowOsrGtk::KeyEvent), this);
g_signal_connect(G_OBJECT(glarea_), "enter_notify_event",
G_CALLBACK(glarea_move_event), this);
G_CALLBACK(&BrowserWindowOsrGtk::MoveEvent), this);
g_signal_connect(G_OBJECT(glarea_), "leave_notify_event",
G_CALLBACK(glarea_move_event), this);
G_CALLBACK(&BrowserWindowOsrGtk::MoveEvent), this);
g_signal_connect(G_OBJECT(glarea_), "motion_notify_event",
G_CALLBACK(glarea_move_event), this);
G_CALLBACK(&BrowserWindowOsrGtk::MoveEvent), this);
g_signal_connect(G_OBJECT(glarea_), "scroll_event",
G_CALLBACK(glarea_scroll_event), this);
G_CALLBACK(&BrowserWindowOsrGtk::ScrollEvent), this);
g_signal_connect(G_OBJECT(glarea_), "focus_in_event",
G_CALLBACK(glarea_focus_event), this);
G_CALLBACK(&BrowserWindowOsrGtk::FocusEvent), this);
g_signal_connect(G_OBJECT(glarea_), "focus_out_event",
G_CALLBACK(glarea_focus_event), this);
G_CALLBACK(&BrowserWindowOsrGtk::FocusEvent), this);
gtk_container_add(GTK_CONTAINER(parentView), glarea_);
gtk_container_add(GTK_CONTAINER(parent_handle), glarea_);
// Make the GlArea visible in the parent container.
gtk_widget_show_all(parent_handle);
}
OSRWindow::~OSRWindow() {
// static
gint BrowserWindowOsrGtk::SizeAllocation(GtkWidget* widget,
GtkAllocation* allocation,
BrowserWindowOsrGtk* self) {
REQUIRE_MAIN_THREAD();
if (self->browser_.get()) {
// Results in a call to GetViewRect().
self->browser_->GetHost()->WasResized();
}
return TRUE;
}
void OSRWindow::Render() {
CEF_REQUIRE_UI_THREAD();
if (render_task_pending_)
render_task_pending_ = false;
// static
gint BrowserWindowOsrGtk::ClickEvent(GtkWidget* widget,
GdkEventButton* event,
BrowserWindowOsrGtk* self) {
REQUIRE_MAIN_THREAD();
if (!gl_enabled_)
EnableGL();
if (!self->browser_.get())
return TRUE;
ScopedGLContext scoped_gl_context(glarea_, true);
if (!scoped_gl_context.IsValid())
return;
CefRefPtr<CefBrowserHost> host = self->browser_->GetHost();
renderer_.Render();
CefBrowserHost::MouseButtonType button_type = MBT_LEFT;
switch (event->button) {
case 1:
break;
case 2:
button_type = MBT_MIDDLE;
break;
case 3:
button_type = MBT_RIGHT;
break;
default:
// Other mouse buttons are not handled here.
return FALSE;
}
CefMouseEvent mouse_event;
mouse_event.x = event->x;
mouse_event.y = event->y;
self->ApplyPopupOffset(mouse_event.x, mouse_event.y);
mouse_event.modifiers = GetCefStateModifiers(event->state);
bool mouse_up = (event->type == GDK_BUTTON_RELEASE);
if (!mouse_up)
gtk_widget_grab_focus(widget);
int click_count = 1;
switch (event->type) {
case GDK_2BUTTON_PRESS:
click_count = 2;
break;
case GDK_3BUTTON_PRESS:
click_count = 3;
break;
default:
break;
}
host->SendMouseClickEvent(mouse_event, button_type, mouse_up, click_count);
return TRUE;
}
void OSRWindow::EnableGL() {
CEF_REQUIRE_UI_THREAD();
// static
gint BrowserWindowOsrGtk::KeyEvent(GtkWidget* widget,
GdkEventKey* event,
BrowserWindowOsrGtk* self) {
REQUIRE_MAIN_THREAD();
if (!self->browser_.get())
return TRUE;
CefRefPtr<CefBrowserHost> host = self->browser_->GetHost();
// Based on WebKeyboardEventBuilder::Build from
// content/browser/renderer_host/input/web_input_event_builders_gtk.cc.
CefKeyEvent key_event;
KeyboardCode windows_key_code = GdkEventToWindowsKeyCode(event);
key_event.windows_key_code =
GetWindowsKeyCodeWithoutLocation(windows_key_code);
key_event.native_key_code = event->hardware_keycode;
key_event.modifiers = GetCefStateModifiers(event->state);
if (event->keyval >= GDK_KP_Space && event->keyval <= GDK_KP_9)
key_event.modifiers |= EVENTFLAG_IS_KEY_PAD;
if (key_event.modifiers & EVENTFLAG_ALT_DOWN)
key_event.is_system_key = true;
if (windows_key_code == VKEY_RETURN) {
// We need to treat the enter key as a key press of character \r. This
// is apparently just how webkit handles it and what it expects.
key_event.unmodified_character = '\r';
} else {
// FIXME: fix for non BMP chars
key_event.unmodified_character =
static_cast<int>(gdk_keyval_to_unicode(event->keyval));
}
// If ctrl key is pressed down, then control character shall be input.
if (key_event.modifiers & EVENTFLAG_CONTROL_DOWN) {
key_event.character =
GetControlCharacter(windows_key_code,
key_event.modifiers & EVENTFLAG_SHIFT_DOWN);
} else {
key_event.character = key_event.unmodified_character;
}
if (event->type == GDK_KEY_PRESS) {
key_event.type = KEYEVENT_RAWKEYDOWN;
host->SendKeyEvent(key_event);
} else {
// Need to send both KEYUP and CHAR events.
key_event.type = KEYEVENT_KEYUP;
host->SendKeyEvent(key_event);
key_event.type = KEYEVENT_CHAR;
host->SendKeyEvent(key_event);
}
return TRUE;
}
// static
gint BrowserWindowOsrGtk::MoveEvent(GtkWidget* widget,
GdkEventMotion* event,
BrowserWindowOsrGtk* self) {
REQUIRE_MAIN_THREAD();
if (!self->browser_.get())
return TRUE;
CefRefPtr<CefBrowserHost> host = self->browser_->GetHost();
gint x, y;
GdkModifierType state;
if (event->is_hint) {
gdk_window_get_pointer(event->window, &x, &y, &state);
} else {
x = (gint)event->x;
y = (gint)event->y;
state = (GdkModifierType)event->state;
}
CefMouseEvent mouse_event;
mouse_event.x = x;
mouse_event.y = y;
self->ApplyPopupOffset(mouse_event.x, mouse_event.y);
mouse_event.modifiers = GetCefStateModifiers(state);
bool mouse_leave = (event->type == GDK_LEAVE_NOTIFY);
host->SendMouseMoveEvent(mouse_event, mouse_leave);
return TRUE;
}
// static
gint BrowserWindowOsrGtk::ScrollEvent(GtkWidget* widget,
GdkEventScroll* event,
BrowserWindowOsrGtk* self) {
REQUIRE_MAIN_THREAD();
if (!self->browser_.get())
return TRUE;
CefRefPtr<CefBrowserHost> host = self->browser_->GetHost();
CefMouseEvent mouse_event;
mouse_event.x = event->x;
mouse_event.y = event->y;
self->ApplyPopupOffset(mouse_event.x, mouse_event.y);
mouse_event.modifiers = GetCefStateModifiers(event->state);
static const int scrollbarPixelsPerGtkTick = 40;
int deltaX = 0;
int deltaY = 0;
switch (event->direction) {
case GDK_SCROLL_UP:
deltaY = scrollbarPixelsPerGtkTick;
break;
case GDK_SCROLL_DOWN:
deltaY = -scrollbarPixelsPerGtkTick;
break;
case GDK_SCROLL_LEFT:
deltaX = scrollbarPixelsPerGtkTick;
break;
case GDK_SCROLL_RIGHT:
deltaX = -scrollbarPixelsPerGtkTick;
break;
}
host->SendMouseWheelEvent(mouse_event, deltaX, deltaY);
return TRUE;
}
// static
gint BrowserWindowOsrGtk::FocusEvent(GtkWidget* widget,
GdkEventFocus* event,
BrowserWindowOsrGtk* self) {
REQUIRE_MAIN_THREAD();
if (self->browser_.get())
self->browser_->GetHost()->SendFocusEvent(event->in == TRUE);
return TRUE;
}
bool BrowserWindowOsrGtk::IsOverPopupWidget(int x, int y) const {
const CefRect& rc = renderer_.popup_rect();
int popup_right = rc.x + rc.width;
int popup_bottom = rc.y + rc.height;
return (x >= rc.x) && (x < popup_right) &&
(y >= rc.y) && (y < popup_bottom);
}
int BrowserWindowOsrGtk::GetPopupXOffset() const {
return renderer_.original_popup_rect().x - renderer_.popup_rect().x;
}
int BrowserWindowOsrGtk::GetPopupYOffset() const {
return renderer_.original_popup_rect().y - renderer_.popup_rect().y;
}
void BrowserWindowOsrGtk::ApplyPopupOffset(int& x, int& y) const {
if (IsOverPopupWidget(x, y)) {
x += GetPopupXOffset();
y += GetPopupYOffset();
}
}
void BrowserWindowOsrGtk::EnableGL() {
REQUIRE_MAIN_THREAD();
if (gl_enabled_)
return;
@ -1336,8 +1477,8 @@ void OSRWindow::EnableGL() {
gl_enabled_ = true;
}
void OSRWindow::DisableGL() {
CEF_REQUIRE_UI_THREAD();
void BrowserWindowOsrGtk::DisableGL() {
REQUIRE_MAIN_THREAD();
if (!gl_enabled_)
return;

View File

@ -0,0 +1,122 @@
// Copyright (c) 2015 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#ifndef CEF_TESTS_CEFCLIENT_BROWSER_WINDOW_OSR_GTK_H_
#define CEF_TESTS_CEFCLIENT_BROWSER_WINDOW_OSR_GTK_H_
#include "cefclient/browser_window.h"
#include "cefclient/client_handler_osr.h"
#include "cefclient/osr_renderer.h"
namespace client {
// Represents a native child window hosting a single off-screen browser
// instance. The methods of this class must be called on the main thread unless
// otherwise indicated.
class BrowserWindowOsrGtk : public BrowserWindow,
public ClientHandlerOsr::OsrDelegate {
public:
// Constructor may be called on any thread.
// |delegate| must outlive this object.
BrowserWindowOsrGtk(BrowserWindow::Delegate* delegate,
const std::string& startup_url,
bool transparent,
bool show_update_rect);
// BrowserWindow methods.
void CreateBrowser(ClientWindowHandle parent_handle,
const CefRect& rect,
const CefBrowserSettings& settings) OVERRIDE;
void GetPopupConfig(CefWindowHandle temp_handle,
CefWindowInfo& windowInfo,
CefRefPtr<CefClient>& client,
CefBrowserSettings& settings) OVERRIDE;
void ShowPopup(ClientWindowHandle parent_handle,
int x, int y, size_t width, size_t height) OVERRIDE;
void Show() OVERRIDE;
void Hide() OVERRIDE;
void SetBounds(int x, int y, size_t width, size_t height) OVERRIDE;
void SetFocus() OVERRIDE;
ClientWindowHandle GetWindowHandle() const OVERRIDE;
// ClientHandlerOsr::OsrDelegate methods.
void OnAfterCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
void OnBeforeClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
bool GetRootScreenRect(CefRefPtr<CefBrowser> browser,
CefRect& rect) OVERRIDE;
bool GetViewRect(CefRefPtr<CefBrowser> browser,
CefRect& rect) OVERRIDE;
bool GetScreenPoint(CefRefPtr<CefBrowser> browser,
int viewX,
int viewY,
int& screenX,
int& screenY) OVERRIDE;
bool GetScreenInfo(CefRefPtr<CefBrowser> browser,
CefScreenInfo& screen_info) OVERRIDE;
void OnPopupShow(CefRefPtr<CefBrowser> browser, bool show) OVERRIDE;
void OnPopupSize(CefRefPtr<CefBrowser> browser,
const CefRect& rect) OVERRIDE;
void OnPaint(CefRefPtr<CefBrowser> browser,
CefRenderHandler::PaintElementType type,
const CefRenderHandler::RectList& dirtyRects,
const void* buffer,
int width,
int height) OVERRIDE;
void OnCursorChange(CefRefPtr<CefBrowser> browser,
CefCursorHandle cursor,
CefRenderHandler::CursorType type,
const CefCursorInfo& custom_cursor_info) OVERRIDE;
bool StartDragging(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefDragData> drag_data,
CefRenderHandler::DragOperationsMask allowed_ops,
int x, int y) OVERRIDE;
void UpdateDragCursor(CefRefPtr<CefBrowser> browser,
CefRenderHandler::DragOperation operation) OVERRIDE;
private:
// Create the GTK GlArea.
void Create(ClientWindowHandle parent_handle);
// Signal handlers for the GTK GlArea.
static gint SizeAllocation(GtkWidget* widget,
GtkAllocation* allocation,
BrowserWindowOsrGtk* self);
static gint ClickEvent(GtkWidget* widget,
GdkEventButton* event,
BrowserWindowOsrGtk* self);
static gint KeyEvent(GtkWidget* widget,
GdkEventKey* event,
BrowserWindowOsrGtk* self);
static gint MoveEvent(GtkWidget* widget,
GdkEventMotion* event,
BrowserWindowOsrGtk* self);
static gint ScrollEvent(GtkWidget* widget,
GdkEventScroll* event,
BrowserWindowOsrGtk* self);
static gint FocusEvent(GtkWidget* widget,
GdkEventFocus* event,
BrowserWindowOsrGtk* self);
bool IsOverPopupWidget(int x, int y) const;
int GetPopupXOffset() const;
int GetPopupYOffset() const;
void ApplyPopupOffset(int& x, int& y) const;
void EnableGL();
void DisableGL();
// The below members will only be accessed on the main thread which should be
// the same as the CEF UI thread.
OsrRenderer renderer_;
ClientWindowHandle glarea_;
bool hidden_;
bool gl_enabled_;
bool painting_popup_;
DISALLOW_COPY_AND_ASSIGN(BrowserWindowOsrGtk);
};
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_BROWSER_WINDOW_OSR_GTK_H_

View File

@ -8,41 +8,42 @@
namespace client {
BrowserWindowOsrWin::BrowserWindowOsrWin(BrowserWindowWin::Delegate* delegate,
BrowserWindowOsrWin::BrowserWindowOsrWin(BrowserWindow::Delegate* delegate,
const std::string& startup_url,
bool transparent,
bool show_update_rect)
: BrowserWindowWin(delegate),
: BrowserWindow(delegate),
transparent_(transparent),
osr_hwnd_(NULL) {
osr_window_ = new OsrWindowWin(this, transparent, show_update_rect);
client_handler_ = new ClientHandlerOsr(this, osr_window_.get(), startup_url);
}
void BrowserWindowOsrWin::CreateBrowser(HWND parent_hwnd,
const RECT& rect,
void BrowserWindowOsrWin::CreateBrowser(ClientWindowHandle parent_handle,
const CefRect& rect,
const CefBrowserSettings& settings) {
REQUIRE_MAIN_THREAD();
// Create the new browser and native window on the UI thread.
osr_window_->CreateBrowser(parent_hwnd, rect, client_handler_, settings,
RECT wnd_rect = {rect.x, rect.y, rect.x + rect.width, rect.y + rect.height};
osr_window_->CreateBrowser(parent_handle, wnd_rect, client_handler_, settings,
client_handler_->startup_url());
}
void BrowserWindowOsrWin::GetPopupConfig(HWND temp_hwnd,
void BrowserWindowOsrWin::GetPopupConfig(CefWindowHandle temp_handle,
CefWindowInfo& windowInfo,
CefRefPtr<CefClient>& client,
CefBrowserSettings& settings) {
// Note: This method may be called on any thread.
windowInfo.SetAsWindowless(temp_hwnd, transparent_);
windowInfo.SetAsWindowless(temp_handle, transparent_);
client = client_handler_;
}
void BrowserWindowOsrWin::ShowPopup(HWND parent_hwnd,
void BrowserWindowOsrWin::ShowPopup(ClientWindowHandle parent_handle,
int x, int y, size_t width, size_t height) {
REQUIRE_MAIN_THREAD();
if (osr_window_)
osr_window_->ShowPopup(parent_hwnd, x, y, width, height);
osr_window_->ShowPopup(parent_handle, x, y, width, height);
}
void BrowserWindowOsrWin::Show() {
@ -69,7 +70,7 @@ void BrowserWindowOsrWin::SetFocus() {
osr_window_->SetFocus();
}
HWND BrowserWindowOsrWin::GetHWND() const {
ClientWindowHandle BrowserWindowOsrWin::GetWindowHandle() const {
REQUIRE_MAIN_THREAD();
return osr_hwnd_;
}
@ -80,7 +81,7 @@ void BrowserWindowOsrWin::OnBrowserClosed(CefRefPtr<CefBrowser> browser) {
// Release the OSR window reference. It will be deleted on the UI thread.
osr_window_ = NULL;
BrowserWindowWin::OnBrowserClosed(browser);
BrowserWindow::OnBrowserClosed(browser);
}
void BrowserWindowOsrWin::OnOsrNativeWindowCreated(HWND hwnd) {

View File

@ -5,7 +5,7 @@
#ifndef CEF_TESTS_CEFCLIENT_BROWSER_WINDOW_OSR_WIN_H_
#define CEF_TESTS_CEFCLIENT_BROWSER_WINDOW_OSR_WIN_H_
#include "cefclient/browser_window_win.h"
#include "cefclient/browser_window.h"
#include "cefclient/osr_window_win.h"
namespace client {
@ -13,34 +13,34 @@ namespace client {
// Represents a native child window hosting a single off-screen browser
// instance. The methods of this class must be called on the main thread unless
// otherwise indicated.
class BrowserWindowOsrWin : public BrowserWindowWin,
OsrWindowWin::Delegate {
class BrowserWindowOsrWin : public BrowserWindow,
public OsrWindowWin::Delegate {
public:
// Constructor may be called on any thread.
// |delegate| must outlive this object.
BrowserWindowOsrWin(BrowserWindowWin::Delegate* delegate,
BrowserWindowOsrWin(BrowserWindow::Delegate* delegate,
const std::string& startup_url,
bool transparent,
bool show_update_rect);
// BrowserWindowWin methods.
void CreateBrowser(HWND parent_hwnd,
const RECT& rect,
// BrowserWindow methods.
void CreateBrowser(ClientWindowHandle parent_handle,
const CefRect& rect,
const CefBrowserSettings& settings) OVERRIDE;
void GetPopupConfig(HWND temp_hwnd,
void GetPopupConfig(CefWindowHandle temp_handle,
CefWindowInfo& windowInfo,
CefRefPtr<CefClient>& client,
CefBrowserSettings& settings) OVERRIDE;
void ShowPopup(HWND parent_hwnd,
void ShowPopup(ClientWindowHandle parent_handle,
int x, int y, size_t width, size_t height) OVERRIDE;
void Show() OVERRIDE;
void Hide() OVERRIDE;
void SetBounds(int x, int y, size_t width, size_t height) OVERRIDE;
void SetFocus() OVERRIDE;
HWND GetHWND() const OVERRIDE;
ClientWindowHandle GetWindowHandle() const OVERRIDE;
private:
// ClientHandler::Delegate methods.
// ClienHandler::Delegate methods.
void OnBrowserClosed(CefRefPtr<CefBrowser> browser) OVERRIDE;
// OsrWindowWin::Delegate methods.

View File

@ -0,0 +1,186 @@
// Copyright (c) 2015 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#include "cefclient/browser_window_std_gtk.h"
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include <X11/Xlib.h>
#undef Success // Definition conflicts with cef_message_router.h
#undef RootWindow // Definition conflicts with root_window.h
#include "include/base/cef_logging.h"
#include "include/cef_app.h"
#include "cefclient/client_handler_std.h"
#include "cefclient/main_message_loop.h"
namespace client {
namespace {
::Window GetXWindowForWidget(GtkWidget* widget) {
// The GTK window must be visible before we can retrieve the XID.
::Window xwindow = GDK_WINDOW_XID(gtk_widget_get_window(widget));
DCHECK(xwindow);
return xwindow;
}
void SetXWindowVisible(::Window xwindow, bool visible) {
::Display* xdisplay = cef_get_xdisplay();
// Retrieve the atoms required by the below XChangeProperty call.
const char* kAtoms[] = {
"_NET_WM_STATE",
"ATOM",
"_NET_WM_STATE_HIDDEN"
};
Atom atoms[3];
int result = XInternAtoms(xdisplay, const_cast<char**>(kAtoms), 3, false,
atoms);
if (!result)
NOTREACHED();
if (!visible) {
// Set the hidden property state value.
scoped_ptr<Atom[]> data(new Atom[1]);
data[0] = atoms[2];
XChangeProperty(xdisplay,
xwindow,
atoms[0], // name
atoms[1], // type
32, // size in bits of items in 'value'
PropModeReplace,
reinterpret_cast<const unsigned char*>(data.get()),
1); // num items
} else {
// Set an empty array of property state values.
XChangeProperty(xdisplay,
xwindow,
atoms[0], // name
atoms[1], // type
32, // size in bits of items in 'value'
PropModeReplace,
NULL,
0); // num items
}
}
void SetXWindowBounds(::Window xwindow,
int x, int y, size_t width, size_t height) {
::Display* xdisplay = cef_get_xdisplay();
XWindowChanges changes = {0};
changes.x = x;
changes.y = y;
changes.width = static_cast<int>(width);
changes.height = static_cast<int>(height);
XConfigureWindow(xdisplay, xwindow,
CWX | CWY | CWHeight | CWWidth, &changes);
}
} // namespace
BrowserWindowStdGtk::BrowserWindowStdGtk(Delegate* delegate,
const std::string& startup_url)
: BrowserWindow(delegate) {
client_handler_ = new ClientHandlerStd(this, startup_url);
}
void BrowserWindowStdGtk::CreateBrowser(ClientWindowHandle parent_handle,
const CefRect& rect,
const CefBrowserSettings& settings) {
REQUIRE_MAIN_THREAD();
// Set the window handle for GTK dialogs.
client_handler_->SetMainWindowHandle(parent_handle);
CefWindowInfo window_info;
window_info.SetAsChild(GetXWindowForWidget(parent_handle), rect);
CefBrowserHost::CreateBrowser(window_info, client_handler_,
client_handler_->startup_url(),
settings, NULL);
}
void BrowserWindowStdGtk::GetPopupConfig(CefWindowHandle temp_handle,
CefWindowInfo& windowInfo,
CefRefPtr<CefClient>& client,
CefBrowserSettings& settings) {
// Note: This method may be called on any thread.
// The window will be properly sized after the browser is created.
windowInfo.SetAsChild(temp_handle, CefRect());
client = client_handler_;
}
void BrowserWindowStdGtk::ShowPopup(ClientWindowHandle parent_handle,
int x, int y, size_t width, size_t height) {
REQUIRE_MAIN_THREAD();
// Set the window handle for GTK dialogs.
client_handler_->SetMainWindowHandle(parent_handle);
if (browser_) {
::Window parent_xwindow = GetXWindowForWidget(parent_handle);
::Display* xdisplay = cef_get_xdisplay();
::Window xwindow = browser_->GetHost()->GetWindowHandle();
DCHECK(xwindow);
XReparentWindow(xdisplay, xwindow, parent_xwindow, x, y);
SetXWindowBounds(xwindow, x, y, width, height);
SetXWindowVisible(xwindow, true);
}
}
void BrowserWindowStdGtk::Show() {
REQUIRE_MAIN_THREAD();
if (browser_) {
::Window xwindow = browser_->GetHost()->GetWindowHandle();
DCHECK(xwindow);
SetXWindowVisible(xwindow, true);
}
}
void BrowserWindowStdGtk::Hide() {
REQUIRE_MAIN_THREAD();
if (browser_) {
::Window xwindow = browser_->GetHost()->GetWindowHandle();
DCHECK(xwindow);
SetXWindowVisible(xwindow, false);
}
}
void BrowserWindowStdGtk::SetBounds(int x, int y, size_t width, size_t height) {
REQUIRE_MAIN_THREAD();
if (browser_) {
::Window xwindow = browser_->GetHost()->GetWindowHandle();
DCHECK(xwindow);
SetXWindowBounds(xwindow, x, y, width, height);
}
}
void BrowserWindowStdGtk::SetFocus() {
REQUIRE_MAIN_THREAD();
if (browser_) {
// Give focus to the browser window.
browser_->GetHost()->SetFocus(true);
}
}
ClientWindowHandle BrowserWindowStdGtk::GetWindowHandle() const {
REQUIRE_MAIN_THREAD();
// There is no GtkWidget* representation of this object.
NOTREACHED();
return NULL;
}
} // namespace client

View File

@ -0,0 +1,44 @@
// Copyright (c) 2015 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#ifndef CEF_TESTS_CEFCLIENT_BROWSER_WINDOW_STD_GTK_H_
#define CEF_TESTS_CEFCLIENT_BROWSER_WINDOW_STD_GTK_H_
#include "cefclient/browser_window.h"
namespace client {
// Represents a native child window hosting a single windowed browser instance.
// The methods of this class must be called on the main thread unless otherwise
// indicated.
class BrowserWindowStdGtk : public BrowserWindow {
public:
// Constructor may be called on any thread.
// |delegate| must outlive this object.
BrowserWindowStdGtk(Delegate* delegate,
const std::string& startup_url);
// BrowserWindow methods.
void CreateBrowser(ClientWindowHandle parent_handle,
const CefRect& rect,
const CefBrowserSettings& settings) OVERRIDE;
void GetPopupConfig(CefWindowHandle temp_handle,
CefWindowInfo& windowInfo,
CefRefPtr<CefClient>& client,
CefBrowserSettings& settings) OVERRIDE;
void ShowPopup(ClientWindowHandle parent_handle,
int x, int y, size_t width, size_t height) OVERRIDE;
void Show() OVERRIDE;
void Hide() OVERRIDE;
void SetBounds(int x, int y, size_t width, size_t height) OVERRIDE;
void SetFocus() OVERRIDE;
ClientWindowHandle GetWindowHandle() const OVERRIDE;
private:
DISALLOW_COPY_AND_ASSIGN(BrowserWindowStdGtk);
};
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_BROWSER_WINDOW_STD_GTK_H_

View File

@ -11,40 +11,41 @@ namespace client {
BrowserWindowStdWin::BrowserWindowStdWin(Delegate* delegate,
const std::string& startup_url)
: BrowserWindowWin(delegate) {
: BrowserWindow(delegate) {
client_handler_ = new ClientHandlerStd(this, startup_url);
}
void BrowserWindowStdWin::CreateBrowser(HWND parent_hwnd,
const RECT& rect,
void BrowserWindowStdWin::CreateBrowser(ClientWindowHandle parent_handle,
const CefRect& rect,
const CefBrowserSettings& settings) {
REQUIRE_MAIN_THREAD();
CefWindowInfo window_info;
window_info.SetAsChild(parent_hwnd, rect);
RECT wnd_rect = {rect.x, rect.y, rect.x + rect.width, rect.y + rect.height};
window_info.SetAsChild(parent_handle, wnd_rect);
CefBrowserHost::CreateBrowser(window_info, client_handler_,
client_handler_->startup_url(),
settings, NULL);
}
void BrowserWindowStdWin::GetPopupConfig(HWND temp_hwnd,
void BrowserWindowStdWin::GetPopupConfig(CefWindowHandle temp_handle,
CefWindowInfo& windowInfo,
CefRefPtr<CefClient>& client,
CefBrowserSettings& settings) {
// Note: This method may be called on any thread.
// The window will be properly sized after the browser is created.
windowInfo.SetAsChild(temp_hwnd, RECT());
windowInfo.SetAsChild(temp_handle, RECT());
client = client_handler_;
}
void BrowserWindowStdWin::ShowPopup(HWND parent_hwnd,
void BrowserWindowStdWin::ShowPopup(ClientWindowHandle parent_handle,
int x, int y, size_t width, size_t height) {
REQUIRE_MAIN_THREAD();
HWND hwnd = GetHWND();
HWND hwnd = GetWindowHandle();
if (hwnd) {
SetParent(hwnd, parent_hwnd);
SetParent(hwnd, parent_handle);
SetWindowPos(hwnd, NULL, x, y,
static_cast<int>(width), static_cast<int>(height),
SWP_NOZORDER);
@ -55,7 +56,7 @@ void BrowserWindowStdWin::ShowPopup(HWND parent_hwnd,
void BrowserWindowStdWin::Show() {
REQUIRE_MAIN_THREAD();
HWND hwnd = GetHWND();
HWND hwnd = GetWindowHandle();
if (hwnd && !::IsWindowVisible(hwnd))
ShowWindow(hwnd, SW_SHOW);
}
@ -63,7 +64,7 @@ void BrowserWindowStdWin::Show() {
void BrowserWindowStdWin::Hide() {
REQUIRE_MAIN_THREAD();
HWND hwnd = GetHWND();
HWND hwnd = GetWindowHandle();
if (hwnd) {
// When the frame window is minimized set the browser window size to 0x0 to
// reduce resource usage.
@ -75,7 +76,7 @@ void BrowserWindowStdWin::Hide() {
void BrowserWindowStdWin::SetBounds(int x, int y, size_t width, size_t height) {
REQUIRE_MAIN_THREAD();
HWND hwnd = GetHWND();
HWND hwnd = GetWindowHandle();
if (hwnd) {
// Set the browser window bounds.
SetWindowPos(hwnd, NULL, x, y,
@ -93,7 +94,7 @@ void BrowserWindowStdWin::SetFocus() {
}
}
HWND BrowserWindowStdWin::GetHWND() const {
ClientWindowHandle BrowserWindowStdWin::GetWindowHandle() const {
REQUIRE_MAIN_THREAD();
if (browser_)

View File

@ -5,35 +5,35 @@
#ifndef CEF_TESTS_CEFCLIENT_BROWSER_WINDOW_STD_WIN_H_
#define CEF_TESTS_CEFCLIENT_BROWSER_WINDOW_STD_WIN_H_
#include "cefclient/browser_window_win.h"
#include "cefclient/browser_window.h"
namespace client {
// Represents a native child window hosting a single windowed browser instance.
// The methods of this class must be called on the main thread unless otherwise
// indicated.
class BrowserWindowStdWin : public BrowserWindowWin {
class BrowserWindowStdWin : public BrowserWindow {
public:
// Constructor may be called on any thread.
// |delegate| must outlive this object.
BrowserWindowStdWin(Delegate* delegate,
const std::string& startup_url);
// BrowserWindowWin methods.
void CreateBrowser(HWND parent_hwnd,
const RECT& rect,
// BrowserWindow methods.
void CreateBrowser(ClientWindowHandle parent_handle,
const CefRect& rect,
const CefBrowserSettings& settings) OVERRIDE;
void GetPopupConfig(HWND temp_hwnd,
void GetPopupConfig(CefWindowHandle temp_handle,
CefWindowInfo& windowInfo,
CefRefPtr<CefClient>& client,
CefBrowserSettings& settings) OVERRIDE;
void ShowPopup(HWND parent_hwnd,
void ShowPopup(ClientWindowHandle parent_handle,
int x, int y, size_t width, size_t height) OVERRIDE;
void Show() OVERRIDE;
void Hide() OVERRIDE;
void SetBounds(int x, int y, size_t width, size_t height) OVERRIDE;
void SetFocus() OVERRIDE;
HWND GetHWND() const OVERRIDE;
ClientWindowHandle GetWindowHandle() const OVERRIDE;
private:
DISALLOW_COPY_AND_ASSIGN(BrowserWindowStdWin);

View File

@ -2,14 +2,12 @@
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include <gtk/gtk.h>
#include <gtk/gtkgl.h>
#include <X11/Xlib.h>
#undef Status // Definition conflicts with cef_urlrequest.h
#undef Success // Definition conflicts with cef_message_router.h
#undef Success // Definition conflicts with cef_message_router.h
#undef RootWindow // Definition conflicts with root_window.h
#include <stdlib.h>
#include <unistd.h>
@ -18,42 +16,15 @@
#include "include/base/cef_logging.h"
#include "include/base/cef_scoped_ptr.h"
#include "include/cef_app.h"
#include "include/cef_browser.h"
#include "include/cef_frame.h"
#include "include/wrapper/cef_helpers.h"
#include "cefclient/client_app.h"
#include "cefclient/client_handler_shared.h"
#include "cefclient/client_switches.h"
#include "cefclient/main_context_impl.h"
#include "cefclient/main_message_loop_std.h"
#include "cefclient/osr_widget_gtk.h"
#include "cefclient/resource.h"
#include "cefclient/test_runner.h"
namespace client {
namespace {
// The global ClientHandlerShared reference.
CefRefPtr<ClientHandlerShared> g_handler;
// Height of the buttons at the top of the GTK window.
int g_toolbar_height = 0;
// Height of the integrated menu bar (if any) at the top of the GTK window.
int g_menubar_height = 0;
// Used by off-screen rendering to find the associated CefBrowser.
class MainBrowserProvider : public OSRBrowserProvider {
virtual CefRefPtr<CefBrowser> GetBrowser() {
if (g_handler.get())
return g_handler->GetBrowser();
return NULL;
}
} g_main_browser_provider;
int XErrorHandlerImpl(Display *display, XErrorEvent *event) {
LOG(WARNING)
<< "X error received: "
@ -69,254 +40,9 @@ int XIOErrorHandlerImpl(Display *display) {
return 0;
}
void destroy(GtkWidget* widget, gpointer data) {
// Quitting CEF is handled in ClientHandler::OnBeforeClose().
}
gboolean delete_event(GtkWidget* widget, GdkEvent* event,
GtkWindow* window) {
if (g_handler.get() && !g_handler->IsClosing()) {
CefRefPtr<CefBrowser> browser = g_handler->GetBrowser();
if (browser.get()) {
// Notify the browser window that we would like to close it. This
// will result in a call to ClientHandler::DoClose() if the
// JavaScript 'onbeforeunload' event handler allows it.
browser->GetHost()->CloseBrowser(false);
// Cancel the close.
return TRUE;
}
}
// Allow the close.
return FALSE;
}
void TerminationSignalHandler(int signatl) {
MainMessageLoop::Get()->Quit();
}
void VboxSizeAllocated(GtkWidget* widget,
GtkAllocation* allocation,
void* data) {
if (g_handler) {
CefRefPtr<CefBrowser> browser = g_handler->GetBrowser();
if (browser && !browser->GetHost()->IsWindowRenderingDisabled()) {
// 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 + g_menubar_height);
changes.y = g_toolbar_height + g_menubar_height;
XConfigureWindow(xdisplay, xwindow, CWHeight | CWWidth | CWY, &changes);
}
}
}
void ToolbarSizeAllocated(GtkWidget* widget,
GtkAllocation* allocation,
void* data) {
g_toolbar_height = allocation->height;
}
void MenubarSizeAllocated(GtkWidget* widget,
GtkAllocation* allocation,
void* data) {
g_menubar_height = allocation->height;
}
gboolean WindowFocusIn(GtkWidget* widget,
GdkEventFocus* event,
gpointer user_data) {
if (g_handler && event->in) {
CefRefPtr<CefBrowser> browser = g_handler->GetBrowser();
if (browser) {
if (browser->GetHost()->IsWindowRenderingDisabled()) {
// Give focus to the off-screen browser.
browser->GetHost()->SendFocusEvent(true);
} else {
// Give focus to the browser window.
browser->GetHost()->SetFocus(true);
return TRUE;
}
}
}
return FALSE;
}
gboolean WindowState(GtkWidget* widget,
GdkEventWindowState* event,
gpointer user_data) {
if (!(event->changed_mask & GDK_WINDOW_STATE_ICONIFIED))
return TRUE;
if (!g_handler)
return TRUE;
CefRefPtr<CefBrowser> browser = g_handler->GetBrowser();
if (!browser)
return TRUE;
const bool iconified = (event->new_window_state & GDK_WINDOW_STATE_ICONIFIED);
if (browser->GetHost()->IsWindowRenderingDisabled()) {
// Notify the off-screen browser that it was shown or hidden.
browser->GetHost()->WasHidden(iconified);
} else {
// Forward the state change event to the browser window.
::Display* xdisplay = cef_get_xdisplay();
::Window xwindow = browser->GetHost()->GetWindowHandle();
// Retrieve the atoms required by the below XChangeProperty call.
const char* kAtoms[] = {
"_NET_WM_STATE",
"ATOM",
"_NET_WM_STATE_HIDDEN"
};
Atom atoms[3];
int result = XInternAtoms(xdisplay, const_cast<char**>(kAtoms), 3, false,
atoms);
if (!result)
NOTREACHED();
if (iconified) {
// Set the hidden property state value.
scoped_ptr<Atom[]> data(new Atom[1]);
data[0] = atoms[2];
XChangeProperty(xdisplay,
xwindow,
atoms[0], // name
atoms[1], // type
32, // size in bits of items in 'value'
PropModeReplace,
reinterpret_cast<const unsigned char*>(data.get()),
1); // num items
} else {
// Set an empty array of property state values.
XChangeProperty(xdisplay,
xwindow,
atoms[0], // name
atoms[1], // type
32, // size in bits of items in 'value'
PropModeReplace,
NULL,
0); // num items
}
}
return TRUE;
}
gboolean WindowConfigure(GtkWindow* window,
GdkEvent* event,
gpointer data) {
// Called when size, position or stack order changes.
if (g_handler) {
CefRefPtr<CefBrowser> browser = g_handler->GetBrowser();
if (browser) {
// Notify the browser of move/resize events so that:
// - Popup windows are displayed in the correct location and dismissed
// when the window moves.
// - Drag&drop areas are updated accordingly.
browser->GetHost()->NotifyMoveOrResizeStarted();
}
}
return FALSE; // Don't stop this message.
}
// Callback for Tests menu items.
gboolean MenuItemActivated(GtkWidget* widget, gpointer data) {
if (g_handler.get() && g_handler->GetBrowserId())
test_runner::RunTest(g_handler->GetBrowser(), GPOINTER_TO_INT(data));
return FALSE; // Don't stop this message.
}
// Callback for when you click the back button.
void BackButtonClicked(GtkButton* button) {
if (g_handler.get() && g_handler->GetBrowserId())
g_handler->GetBrowser()->GoBack();
}
// Callback for when you click the forward button.
void ForwardButtonClicked(GtkButton* button) {
if (g_handler.get() && g_handler->GetBrowserId())
g_handler->GetBrowser()->GoForward();
}
// Callback for when you click the stop button.
void StopButtonClicked(GtkButton* button) {
if (g_handler.get() && g_handler->GetBrowserId())
g_handler->GetBrowser()->StopLoad();
}
// Callback for when you click the reload button.
void ReloadButtonClicked(GtkButton* button) {
if (g_handler.get() && g_handler->GetBrowserId())
g_handler->GetBrowser()->Reload();
}
// Callback for when you press enter in the URL box.
void URLEntryActivate(GtkEntry* entry) {
if (!g_handler.get() || !g_handler->GetBrowserId())
return;
const gchar* url = gtk_entry_get_text(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, int id) {
GtkWidget* entry = gtk_menu_item_new_with_label(text);
g_signal_connect(entry, "activate", G_CALLBACK(MenuItemActivated),
GINT_TO_POINTER(id));
gtk_menu_shell_append(GTK_MENU_SHELL(menu_widget), entry);
return entry;
}
GtkWidget* CreateMenu(GtkWidget* menu_bar, const char* text) {
GtkWidget* menu_widget = gtk_menu_new();
GtkWidget* menu_header = gtk_menu_item_new_with_label(text);
gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_header), menu_widget);
gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar), menu_header);
return menu_widget;
}
GtkWidget* CreateMenuBar() {
GtkWidget* menu_bar = gtk_menu_bar_new();
GtkWidget* debug_menu = CreateMenu(menu_bar, "Tests");
AddMenuEntry(debug_menu, "Get Source", ID_TESTS_GETSOURCE);
AddMenuEntry(debug_menu, "Get Text", ID_TESTS_GETTEXT);
AddMenuEntry(debug_menu, "Popup Window", ID_TESTS_POPUP);
AddMenuEntry(debug_menu, "Request", ID_TESTS_REQUEST);
AddMenuEntry(debug_menu, "Plugin Info", ID_TESTS_PLUGIN_INFO);
AddMenuEntry(debug_menu, "Zoom In", ID_TESTS_ZOOM_IN);
AddMenuEntry(debug_menu, "Zoom Out", ID_TESTS_ZOOM_OUT);
AddMenuEntry(debug_menu, "Zoom Reset", ID_TESTS_ZOOM_RESET);
AddMenuEntry(debug_menu, "Begin Tracing", ID_TESTS_TRACING_BEGIN);
AddMenuEntry(debug_menu, "End Tracing", ID_TESTS_TRACING_END);
AddMenuEntry(debug_menu, "Print", ID_TESTS_PRINT);
AddMenuEntry(debug_menu, "Other Tests", ID_TESTS_OTHER_TESTS);
return menu_bar;
LOG(ERROR) << "Received termination signal: " << signatl;
MainContext::Get()->GetRootWindowManager()->CloseAllWindows(true);
}
int RunMain(int argc, char* argv[]) {
@ -334,7 +60,7 @@ int RunMain(int argc, char* argv[]) {
return exit_code;
// Create the main context object.
scoped_ptr<MainContextImpl> context(new MainContextImpl(argc, argv));
scoped_ptr<MainContextImpl> context(new MainContextImpl(argc, argv, true));
CefSettings settings;
@ -350,7 +76,7 @@ int RunMain(int argc, char* argv[]) {
scoped_ptr<MainMessageLoop> message_loop(new MainMessageLoopStd);
// Initialize CEF.
CefInitialize(main_args, settings, app.get(), NULL);
context->Initialize(main_args, settings, app.get(), NULL);
// The Chromium sandbox requires that there only be a single thread during
// initialization. Therefore initialize GTK after CEF.
@ -359,130 +85,25 @@ int RunMain(int argc, char* argv[]) {
// Perform gtkglext initialization required by the OSR example.
gtk_gl_init(&argc, &argv_copy);
// Register scheme handlers.
test_runner::RegisterSchemeHandlers();
GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size(GTK_WINDOW(window), 800, 600);
g_signal_connect(window, "focus-in-event",
G_CALLBACK(WindowFocusIn), NULL);
g_signal_connect(window, "window-state-event",
G_CALLBACK(WindowState), NULL);
g_signal_connect(G_OBJECT(window), "configure-event",
G_CALLBACK(WindowConfigure), 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();
g_signal_connect(menu_bar, "size-allocate",
G_CALLBACK(MenubarSizeAllocated), NULL);
gtk_box_pack_start(GTK_BOX(vbox), menu_bar, FALSE, FALSE, 0);
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",
G_CALLBACK(BackButtonClicked), NULL);
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), back, -1 /* append */);
GtkToolItem* forward = gtk_tool_button_new_from_stock(GTK_STOCK_GO_FORWARD);
g_signal_connect(forward, "clicked",
G_CALLBACK(ForwardButtonClicked), NULL);
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), forward, -1 /* append */);
GtkToolItem* reload = gtk_tool_button_new_from_stock(GTK_STOCK_REFRESH);
g_signal_connect(reload, "clicked",
G_CALLBACK(ReloadButtonClicked), NULL);
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), reload, -1 /* append */);
GtkToolItem* stop = gtk_tool_button_new_from_stock(GTK_STOCK_STOP);
g_signal_connect(stop, "clicked",
G_CALLBACK(StopButtonClicked), NULL);
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), stop, -1 /* append */);
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), entry);
gtk_tool_item_set_expand(tool_item, TRUE);
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), tool_item, -1); // append
gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, FALSE, 0);
g_signal_connect(G_OBJECT(window), "destroy",
G_CALLBACK(destroy), NULL);
g_signal_connect(G_OBJECT(window), "delete_event",
G_CALLBACK(delete_event), window);
// Create the handler.
g_handler = new ClientHandlerShared();
g_handler->SetMainWindowHandle(vbox);
g_handler->SetUXWindowHandles(entry, GTK_WIDGET(back), GTK_WIDGET(forward),
GTK_WIDGET(reload), GTK_WIDGET(stop));
CefWindowInfo window_info;
CefBrowserSettings browserSettings;
// Populate the browser settings based on command line arguments.
context->PopulateBrowserSettings(&browserSettings);
if (g_handler->is_osr()) {
CefRefPtr<CefCommandLine> command_line =
CefCommandLine::GetGlobalCommandLine();
const bool transparent =
command_line->HasSwitch(switches::kTransparentPaintingEnabled);
const bool show_update_rect =
command_line->HasSwitch(switches::kShowUpdateRect);
// Create the GTKGL surface.
CefRefPtr<OSRWindow> osr_window =
OSRWindow::Create(&g_main_browser_provider, transparent,
show_update_rect, vbox);
// Show the GTK window.
gtk_widget_show_all(GTK_WIDGET(window));
// The GTK window must be visible before we can retrieve the XID.
::Window xwindow =
GDK_WINDOW_XID(gtk_widget_get_window(osr_window->GetWindowHandle()));
window_info.SetAsWindowless(xwindow, transparent);
g_handler->SetOSRHandler(osr_window.get());
} else {
// Show the GTK window.
gtk_widget_show_all(GTK_WIDGET(window));
// 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->startup_url(), browserSettings, NULL);
// Install a signal handler so we clean up after ourselves.
signal(SIGINT, TerminationSignalHandler);
signal(SIGTERM, TerminationSignalHandler);
// Register scheme handlers.
test_runner::RegisterSchemeHandlers();
// Create the first window.
context->GetRootWindowManager()->CreateRootWindow(
true, // Show controls.
settings.windowless_rendering_enabled ? true : false,
CefRect(), // Use default system size.
std::string()); // Use default URL.
// Run the message loop. This will block until Quit() is called.
int result = message_loop->Run();
// Shut down CEF.
CefShutdown();
context->Shutdown();
// Release objects in reverse order of creation.
message_loop.reset();

View File

@ -511,7 +511,7 @@ int RunMain(int argc, char* argv[]) {
[ClientApplication sharedApplication];
// Create the main context object.
scoped_ptr<MainContextImpl> context(new MainContextImpl(argc, argv));
scoped_ptr<MainContextImpl> context(new MainContextImpl(argc, argv, true));
CefSettings settings;
@ -522,7 +522,7 @@ int RunMain(int argc, char* argv[]) {
scoped_ptr<MainMessageLoop> message_loop(new MainMessageLoopStd);
// Initialize CEF.
CefInitialize(main_args, settings, app.get(), NULL);
context->Initialize(main_args, settings, app.get(), NULL);
// Register scheme handlers.
test_runner::RegisterSchemeHandlers();
@ -537,7 +537,7 @@ int RunMain(int argc, char* argv[]) {
int result = message_loop->Run();
// Shut down CEF.
CefShutdown();
context->Shutdown();
// Release objects in reverse order of creation.
g_handler = NULL;

View File

@ -66,7 +66,7 @@ int RunMain(HINSTANCE hInstance, int nCmdShow) {
message_loop.reset(new MainMessageLoopStd);
// Initialize CEF.
CefInitialize(main_args, settings, app.get(), sandbox_info);
context->Initialize(main_args, settings, app.get(), sandbox_info);
// Register scheme handlers.
test_runner::RegisterSchemeHandlers();
@ -83,7 +83,7 @@ int RunMain(HINSTANCE hInstance, int nCmdShow) {
int result = message_loop->Run();
// Shut down CEF.
CefShutdown();
context->Shutdown();
// Release objects in reverse order of creation.
message_loop.reset();

View File

@ -12,15 +12,10 @@
#include "include/cef_client.h"
#include "include/wrapper/cef_helpers.h"
#include "include/wrapper/cef_message_router.h"
#include "cefclient/client_types.h"
#if defined(OS_LINUX)
#include <gtk/gtk.h>
#include "cefclient/dialog_handler_gtk.h"
// The Linux client uses GTK instead of the underlying platform type (X11).
#define ClientWindowHandle GtkWidget*
#else
#define ClientWindowHandle CefWindowHandle
#endif
namespace client {

View File

@ -0,0 +1,20 @@
// Copyright (c) 2015 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#ifndef CEF_TESTS_CEFCLIENT_CLIENT_TYPES_H_
#define CEF_TESTS_CEFCLIENT_CLIENT_TYPES_H_
#include "include/cef_base.h"
#if defined(OS_LINUX)
#include <gtk/gtk.h>
// The Linux client uses GTK instead of the underlying platform type (X11).
#define ClientWindowHandle GtkWidget*
#else
#define ClientWindowHandle CefWindowHandle
#endif
#endif // CEF_TESTS_CEFCLIENT_CLIENT_TYPES_H_

View File

@ -12,7 +12,7 @@
namespace client {
#if defined(OS_WIN)
#if defined(OS_WIN) || defined(OS_LINUX)
class RootWindowManager;
#endif
@ -39,7 +39,7 @@ class MainContext {
virtual void PopulateSettings(CefSettings* settings) = 0;
virtual void PopulateBrowserSettings(CefBrowserSettings* settings) = 0;
#if defined(OS_WIN)
#if defined(OS_WIN) || defined(OS_LINUX)
// Returns the object used to create/manage RootWindow instances.
virtual RootWindowManager* GetRootWindowManager() = 0;
#endif

View File

@ -6,9 +6,6 @@
#include "cefclient/client_switches.h"
#if defined(OS_WIN)
#include "cefclient/root_window_manager.h"
#endif
namespace client {
namespace {
@ -19,11 +16,11 @@ const char kDefaultUrl[] = "http://www.google.com";
} // namespace
MainContextImpl::MainContextImpl(int argc,
const char* const* argv
#if defined(OS_WIN)
, bool terminate_when_all_windows_closed
#endif
) {
const char* const* argv,
bool terminate_when_all_windows_closed)
: terminate_when_all_windows_closed_(terminate_when_all_windows_closed),
initialized_(false),
shutdown_(false) {
// Parse the command line.
command_line_ = CefCommandLine::CreateCommandLine();
#if defined(OS_WIN)
@ -37,11 +34,12 @@ MainContextImpl::MainContextImpl(int argc,
main_url_ = command_line_->GetSwitchValue(switches::kUrl);
if (main_url_.empty())
main_url_ = kDefaultUrl;
}
#if defined(OS_WIN)
root_window_manager_.reset(
new RootWindowManager(terminate_when_all_windows_closed));
#endif
MainContextImpl::~MainContextImpl() {
// The context must either not have been initialized, or it must have also
// been shut down.
DCHECK(!initialized_ || shutdown_);
}
std::string MainContextImpl::GetConsoleLogPath() {
@ -72,10 +70,48 @@ void MainContextImpl::PopulateBrowserSettings(CefBrowserSettings* settings) {
}
}
#if defined(OS_WIN)
#if defined(OS_WIN) || defined(OS_LINUX)
RootWindowManager* MainContextImpl::GetRootWindowManager() {
DCHECK(InValidState());
return root_window_manager_.get();
}
#endif
bool MainContextImpl::Initialize(const CefMainArgs& args,
const CefSettings& settings,
CefRefPtr<CefApp> application,
void* windows_sandbox_info) {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(!initialized_);
DCHECK(!shutdown_);
if (!CefInitialize(args, settings, application, windows_sandbox_info))
return false;
#if defined(OS_WIN) || defined(OS_LINUX)
// Need to create the RootWindowManager after calling CefInitialize because
// TempWindowX11 uses cef_get_xdisplay().
root_window_manager_.reset(
new RootWindowManager(terminate_when_all_windows_closed_));
#endif
initialized_ = true;
return true;
}
void MainContextImpl::Shutdown() {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(initialized_);
DCHECK(!shutdown_);
#if defined(OS_WIN) || defined(OS_LINUX)
root_window_manager_.reset();
#endif
CefShutdown();
shutdown_ = true;
}
} // namespace client

View File

@ -6,20 +6,22 @@
#define CEF_TESTS_CEFCLIENT_MAIN_CONTEXT_IMPL_H_
#include "include/base/cef_scoped_ptr.h"
#include "include/cef_app.h"
#include "include/cef_command_line.h"
#include "cefclient/main_context.h"
#if defined(OS_WIN) || defined(OS_LINUX)
#include "cefclient/root_window_manager.h"
#endif
namespace client {
// Used to store global context in the browser process.
class MainContextImpl : public MainContext {
public:
MainContextImpl(int argc,
const char* const* argv
#if defined(OS_WIN)
, bool terminate_when_all_windows_closed
#endif
);
const char* const* argv,
bool terminate_when_all_windows_closed);
// MainContext members.
std::string GetConsoleLogPath() OVERRIDE;
@ -28,23 +30,51 @@ class MainContextImpl : public MainContext {
std::string GetMainURL() OVERRIDE;
void PopulateSettings(CefSettings* settings) OVERRIDE;
void PopulateBrowserSettings(CefBrowserSettings* settings) OVERRIDE;
#if defined(OS_WIN)
#if defined(OS_WIN) || defined(OS_LINUX)
RootWindowManager* GetRootWindowManager() OVERRIDE;
#endif
// Initialize CEF and associated main context state. This method must be
// called on the same thread that created this object.
bool Initialize(const CefMainArgs& args,
const CefSettings& settings,
CefRefPtr<CefApp> application,
void* windows_sandbox_info);
// Shut down CEF and associated context state. This method must be called on
// the same thread that created this object.
void Shutdown();
private:
// Allow deletion via scoped_ptr only.
friend struct base::DefaultDeleter<MainContextImpl>;
~MainContextImpl() {}
~MainContextImpl();
// Returns true if the context is in a valid state (initialized and not yet
// shut down).
bool InValidState() const {
return initialized_ && !shutdown_;
}
const bool terminate_when_all_windows_closed_;
// Track context state. Accessing these variables from multiple threads is
// safe because only a single thread will exist at the time that they're set
// (during context initialization and shutdown).
bool initialized_;
bool shutdown_;
CefRefPtr<CefCommandLine> command_line_;
std::string main_url_;
#if defined(OS_WIN)
#if defined(OS_WIN) || defined(OS_LINUX)
scoped_ptr<RootWindowManager> root_window_manager_;
#endif
// Used to verify that methods are called on the correct thread.
base::ThreadChecker thread_checker_;
DISALLOW_COPY_AND_ASSIGN(MainContextImpl);
};

View File

@ -1,101 +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.
#ifndef CEF_TESTS_CEFCLIENT_OSR_WIDGET_GTK_H_
#define CEF_TESTS_CEFCLIENT_OSR_WIDGET_GTK_H_
#pragma once
#include "include/cef_render_handler.h"
#include "cefclient/client_handler_shared.h"
#include "cefclient/osr_renderer.h"
namespace client {
class OSRBrowserProvider {
public:
virtual CefRefPtr<CefBrowser> GetBrowser() =0;
protected:
virtual ~OSRBrowserProvider() {}
};
class OSRWindow : public ClientHandlerShared::RenderHandler {
public:
// Create a new OSRWindow instance. |browser_provider| must outlive this
// object.
static CefRefPtr<OSRWindow> Create(OSRBrowserProvider* browser_provider,
bool transparent,
bool show_update_rect,
ClientWindowHandle parentView);
static CefRefPtr<OSRWindow> From(
CefRefPtr<ClientHandlerShared::RenderHandler> renderHandler);
ClientWindowHandle GetWindowHandle() const {
return glarea_;
}
CefRefPtr<CefBrowserHost> GetBrowserHost() const {
if (browser_provider_->GetBrowser())
return browser_provider_->GetBrowser()->GetHost();
return NULL;
}
// ClientHandlerShared::RenderHandler methods
void OnBeforeClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
// CefRenderHandler methods
bool GetViewRect(CefRefPtr<CefBrowser> browser,
CefRect& rect) OVERRIDE;
bool GetScreenPoint(CefRefPtr<CefBrowser> browser,
int viewX,
int viewY,
int& screenX,
int& screenY) OVERRIDE;
void OnPopupShow(CefRefPtr<CefBrowser> browser,
bool show) OVERRIDE;
void OnPopupSize(CefRefPtr<CefBrowser> browser,
const CefRect& rect) OVERRIDE;
void OnPaint(CefRefPtr<CefBrowser> browser,
PaintElementType type,
const RectList& dirtyRects,
const void* buffer,
int width,
int height) OVERRIDE;
void OnCursorChange(CefRefPtr<CefBrowser> browser,
CefCursorHandle cursor,
CursorType type,
const CefCursorInfo& custom_cursor_info) OVERRIDE;
void Invalidate();
bool IsOverPopupWidget(int x, int y) const;
int GetPopupXOffset() const;
int GetPopupYOffset() const;
void ApplyPopupOffset(int& x, int& y) const;
private:
OSRWindow(OSRBrowserProvider* browser_provider,
bool transparent,
bool show_update_rect,
ClientWindowHandle parentView);
~OSRWindow();
void Render();
void EnableGL();
void DisableGL();
OsrRenderer renderer_;
OSRBrowserProvider* browser_provider_;
ClientWindowHandle glarea_;
bool gl_enabled_;
bool painting_popup_;
bool render_task_pending_;
IMPLEMENT_REFCOUNTING(OSRWindow);
DISALLOW_COPY_AND_ASSIGN(OSRWindow);
};
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_OSR_WIDGET_GTK_H_

View File

@ -713,7 +713,7 @@ void OsrWindowWin::OnAfterCreated(CefRefPtr<CefBrowser> browser) {
void OsrWindowWin::OnBeforeClose(CefRefPtr<CefBrowser> browser) {
CEF_REQUIRE_UI_THREAD();
// Detach |this| from the ClientHandler.
// Detach |this| from the ClientHandlerOsr.
static_cast<ClientHandlerOsr*>(browser_->GetHost()->GetClient().get())->
DetachOsrDelegate();
browser_ = NULL;

View File

@ -96,7 +96,7 @@ class OsrWindowWin :
int GetPopupYOffset() const;
void ApplyPopupOffset(int& x, int& y) const;
// ClientHandlerOsr::Delegate methods.
// ClientHandlerOsr::OsrDelegate methods.
void OnAfterCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
void OnBeforeClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
bool GetRootScreenRect(CefRefPtr<CefBrowser> browser,

View File

@ -9,6 +9,7 @@
#include "include/base/cef_ref_counted.h"
#include "include/cef_browser.h"
#include "cefclient/client_types.h"
#include "cefclient/main_message_loop.h"
namespace client {
@ -90,7 +91,7 @@ class RootWindow :
virtual CefRefPtr<CefBrowser> GetBrowser() const = 0;
// Returns the handle for this window, if any.
virtual CefWindowHandle GetWindowHandle() const = 0;
virtual ClientWindowHandle GetWindowHandle() const = 0;
protected:
// Allow deletion via scoped_refptr only.

View File

@ -0,0 +1,622 @@
// Copyright (c) 2015 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#include "cefclient/root_window_gtk.h"
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include <X11/Xlib.h>
#undef Success // Definition conflicts with cef_message_router.h
#undef RootWindow // Definition conflicts with root_window.h
#include "include/base/cef_bind.h"
#include "include/cef_app.h"
#include "cefclient/browser_window_osr_gtk.h"
#include "cefclient/browser_window_std_gtk.h"
#include "cefclient/client_switches.h"
#include "cefclient/main_message_loop.h"
#include "cefclient/resource.h"
#include "cefclient/temp_window_x11.h"
namespace client {
namespace {
const char kMenuIdKey[] = "menu_id";
bool IsWindowMaximized(GtkWindow* window) {
GdkWindow* gdk_window = gtk_widget_get_window(GTK_WIDGET(window));
gint state = gdk_window_get_state(gdk_window);
return (state & GDK_WINDOW_STATE_MAXIMIZED) ? true : false;
}
void MinimizeWindow(GtkWindow* window) {
// Unmaximize the window before minimizing so restore behaves correctly.
if (IsWindowMaximized(window))
gtk_window_unmaximize(window);
gtk_window_iconify(window);
}
void MaximizeWindow(GtkWindow* window) {
gtk_window_maximize(window);
}
} // namespace
RootWindowGtk::RootWindowGtk()
: delegate_(NULL),
with_controls_(false),
with_osr_(false),
is_popup_(false),
initialized_(false),
window_(NULL),
back_button_(NULL),
forward_button_(NULL),
reload_button_(NULL),
stop_button_(NULL),
url_entry_(NULL),
toolbar_height_(0),
menubar_height_(0),
force_close_(false),
window_destroyed_(false),
browser_destroyed_(false) {
}
RootWindowGtk::~RootWindowGtk() {
REQUIRE_MAIN_THREAD();
// The window and browser should already have been destroyed.
DCHECK(window_destroyed_);
DCHECK(browser_destroyed_);
}
void RootWindowGtk::Init(RootWindow::Delegate* delegate,
bool with_controls,
bool with_osr,
const CefRect& bounds,
const CefBrowserSettings& settings,
const std::string& url) {
DCHECK(delegate);
DCHECK(!initialized_);
delegate_ = delegate;
with_controls_ = with_controls;
with_osr_ = with_osr;
start_rect_ = bounds;
CreateBrowserWindow(url);
initialized_ = true;
// Create the native root window on the main thread.
if (CURRENTLY_ON_MAIN_THREAD()) {
CreateRootWindow(settings);
} else {
MAIN_POST_CLOSURE(
base::Bind(&RootWindowGtk::CreateRootWindow, this, settings));
}
}
void RootWindowGtk::InitAsPopup(RootWindow::Delegate* delegate,
bool with_controls,
bool with_osr,
const CefPopupFeatures& popupFeatures,
CefWindowInfo& windowInfo,
CefRefPtr<CefClient>& client,
CefBrowserSettings& settings) {
DCHECK(delegate);
DCHECK(!initialized_);
delegate_ = delegate;
with_controls_ = with_controls;
with_osr_ = with_osr;
is_popup_ = true;
if (popupFeatures.xSet)
start_rect_.x = popupFeatures.x;
if (popupFeatures.ySet)
start_rect_.y = popupFeatures.y;
if (popupFeatures.widthSet)
start_rect_.width = popupFeatures.width;
if (popupFeatures.heightSet)
start_rect_.height = popupFeatures.height;
CreateBrowserWindow(std::string());
initialized_ = true;
// The new popup is initially parented to a temporary window. The native root
// window will be created after the browser is created and the popup window
// will be re-parented to it at that time.
browser_window_->GetPopupConfig(TempWindowX11::GetWindowHandle(),
windowInfo, client, settings);
}
void RootWindowGtk::Show(ShowMode mode) {
REQUIRE_MAIN_THREAD();
if (!window_)
return;
// Show the GTK window.
gtk_widget_show_all(window_);
if (mode == ShowMinimized)
MinimizeWindow(GTK_WINDOW(window_));
else if (mode == ShowMaximized)
MaximizeWindow(GTK_WINDOW(window_));
}
void RootWindowGtk::Hide() {
REQUIRE_MAIN_THREAD();
if (window_)
gtk_widget_hide(window_);
}
void RootWindowGtk::SetBounds(int x, int y, size_t width, size_t height) {
REQUIRE_MAIN_THREAD();
if (!window_)
return;
GtkWindow* window = GTK_WINDOW(window_);
GdkWindow* gdk_window = gtk_widget_get_window(window_);
// Make sure the window isn't minimized or maximized.
if (IsWindowMaximized(window))
gtk_window_unmaximize(window);
else
gtk_window_present(window);
// Retrieve information about the display that contains the window.
GdkScreen* screen = gdk_screen_get_default();
const gint monitor = gdk_screen_get_monitor_at_window(screen, gdk_window);
GdkRectangle rect;
gdk_screen_get_monitor_geometry(screen, monitor, &rect);
gdk_window_move_resize(gdk_window, rect.x, rect.y, rect.width, rect.height);
}
void RootWindowGtk::Close(bool force) {
REQUIRE_MAIN_THREAD();
if (window_) {
force_close_ = force;
gtk_widget_destroy(window_);
}
}
CefRefPtr<CefBrowser> RootWindowGtk::GetBrowser() const {
REQUIRE_MAIN_THREAD();
if (browser_window_)
return browser_window_->GetBrowser();
return NULL;
}
ClientWindowHandle RootWindowGtk::GetWindowHandle() const {
REQUIRE_MAIN_THREAD();
return window_;
}
void RootWindowGtk::CreateBrowserWindow(const std::string& startup_url) {
if (with_osr_) {
CefRefPtr<CefCommandLine> command_line =
CefCommandLine::GetGlobalCommandLine();
const bool transparent =
command_line->HasSwitch(switches::kTransparentPaintingEnabled);
const bool show_update_rect =
command_line->HasSwitch(switches::kShowUpdateRect);
browser_window_.reset(new BrowserWindowOsrGtk(this, startup_url,
transparent,
show_update_rect));
} else {
browser_window_.reset(new BrowserWindowStdGtk(this, startup_url));
}
}
void RootWindowGtk::CreateRootWindow(const CefBrowserSettings& settings) {
REQUIRE_MAIN_THREAD();
DCHECK(!window_);
// TODO(port): If no x,y position is specified the window will always appear
// in the upper-left corner. Maybe there's a better default place to put it?
int x = start_rect_.x;
int y = start_rect_.y;
int width, height;
if (start_rect_.IsEmpty()) {
// TODO(port): Also, maybe there's a better way to choose the default size.
width = 800;
height = 600;
} else {
width = start_rect_.width;
height = start_rect_.height;
}
window_ = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size(GTK_WINDOW(window_), width, height);
g_signal_connect(G_OBJECT(window_), "focus-in-event",
G_CALLBACK(&RootWindowGtk::WindowFocusIn), this);
g_signal_connect(G_OBJECT(window_), "window-state-event",
G_CALLBACK(&RootWindowGtk::WindowState), this);
g_signal_connect(G_OBJECT(window_), "configure-event",
G_CALLBACK(&RootWindowGtk::WindowConfigure), this);
g_signal_connect(G_OBJECT(window_), "destroy",
G_CALLBACK(&RootWindowGtk::WindowDestroy), this);
g_signal_connect(G_OBJECT(window_), "delete_event",
G_CALLBACK(&RootWindowGtk::WindowDelete), this);
GtkWidget* vbox = gtk_vbox_new(FALSE, 0);
g_signal_connect(vbox, "size-allocate",
G_CALLBACK(&RootWindowGtk::VboxSizeAllocated), this);
gtk_container_add(GTK_CONTAINER(window_), vbox);
if (with_controls_) {
GtkWidget* menu_bar = CreateMenuBar();
g_signal_connect(menu_bar, "size-allocate",
G_CALLBACK(&RootWindowGtk::MenubarSizeAllocated), this);
gtk_box_pack_start(GTK_BOX(vbox), menu_bar, FALSE, FALSE, 0);
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(&RootWindowGtk::ToolbarSizeAllocated), this);
back_button_ = gtk_tool_button_new_from_stock(GTK_STOCK_GO_BACK);
g_signal_connect(back_button_, "clicked",
G_CALLBACK(&RootWindowGtk::BackButtonClicked), this);
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), back_button_, -1 /* append */);
forward_button_ = gtk_tool_button_new_from_stock(GTK_STOCK_GO_FORWARD);
g_signal_connect(forward_button_, "clicked",
G_CALLBACK(&RootWindowGtk::ForwardButtonClicked), this);
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), forward_button_, -1 /* append */);
reload_button_ = gtk_tool_button_new_from_stock(GTK_STOCK_REFRESH);
g_signal_connect(reload_button_, "clicked",
G_CALLBACK(&RootWindowGtk::ReloadButtonClicked), this);
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), reload_button_, -1 /* append */);
stop_button_ = gtk_tool_button_new_from_stock(GTK_STOCK_STOP);
g_signal_connect(stop_button_, "clicked",
G_CALLBACK(&RootWindowGtk::StopButtonClicked), this);
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), stop_button_, -1 /* append */);
url_entry_ = gtk_entry_new();
g_signal_connect(url_entry_, "activate",
G_CALLBACK(&RootWindowGtk::URLEntryActivate), this);
g_signal_connect(url_entry_, "button-press-event",
G_CALLBACK(&RootWindowGtk::URLEntryButtonPress), this);
GtkToolItem* tool_item = gtk_tool_item_new();
gtk_container_add(GTK_CONTAINER(tool_item), url_entry_);
gtk_tool_item_set_expand(tool_item, TRUE);
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), tool_item, -1); // append
gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, FALSE, 0);
}
// Realize (show) the GTK widget. This must be done before the browser is
// created because the underlying X11 Window is required. |browser_bounds_|
// will be set at this point based on the GTK *SizeAllocated signal callbacks.
Show(ShowNormal);
// Most window managers ignore requests for initial window positions (instead
// using a user-defined placement algorithm) and honor requests after the
// window has already been shown.
gtk_window_move(GTK_WINDOW(window_), x, y);
// Windowed browsers are parented to the X11 Window underlying the GtkWindow*
// and must be sized manually. The OSR GTK widget, on the other hand, can be
// added to the Vbox container for automatic layout-based sizing.
GtkWidget* parent = with_osr_ ? vbox : window_;
if (!is_popup_) {
// Create the browser window.
browser_window_->CreateBrowser(parent, browser_bounds_, settings);
} else {
// With popups we already have a browser window. Parent the browser window
// to the root window and show it in the correct location.
browser_window_->ShowPopup(parent, browser_bounds_.x, browser_bounds_.y,
browser_bounds_.width, browser_bounds_.height);
}
}
void RootWindowGtk::OnBrowserCreated(CefRefPtr<CefBrowser> browser) {
REQUIRE_MAIN_THREAD();
// For popup browsers create the root window once the browser has been
// created.
if (is_popup_)
CreateRootWindow(CefBrowserSettings());
}
void RootWindowGtk::OnBrowserWindowDestroyed() {
REQUIRE_MAIN_THREAD();
browser_window_.reset();
if (!window_destroyed_) {
// The browser was destroyed first. This could be due to the use of
// off-screen rendering or execution of JavaScript window.close().
// Close the RootWindow asynchronously.
Close(false);
}
browser_destroyed_ = true;
NotifyDestroyedIfDone();
}
void RootWindowGtk::OnSetAddress(const std::string& url) {
REQUIRE_MAIN_THREAD();
if (url_entry_) {
std::string urlStr(url);
gtk_entry_set_text(GTK_ENTRY(url_entry_), urlStr.c_str());
}
}
void RootWindowGtk::OnSetTitle(const std::string& title) {
REQUIRE_MAIN_THREAD();
if (window_) {
std::string titleStr(title);
gtk_window_set_title(GTK_WINDOW(window_), titleStr.c_str());
}
}
void RootWindowGtk::OnSetLoadingState(bool isLoading,
bool canGoBack,
bool canGoForward) {
REQUIRE_MAIN_THREAD();
if (with_controls_) {
gtk_widget_set_sensitive(GTK_WIDGET(stop_button_), isLoading);
gtk_widget_set_sensitive(GTK_WIDGET(reload_button_), !isLoading);
gtk_widget_set_sensitive(GTK_WIDGET(back_button_), canGoBack);
gtk_widget_set_sensitive(GTK_WIDGET(forward_button_), canGoForward);
}
}
void RootWindowGtk::NotifyDestroyedIfDone() {
// Notify once both the window and the browser have been destroyed.
if (window_destroyed_ && browser_destroyed_)
delegate_->OnRootWindowDestroyed(this);
}
// static
gboolean RootWindowGtk::WindowFocusIn(GtkWidget* widget,
GdkEventFocus* event,
RootWindowGtk* self) {
if (event->in && self->browser_window_.get()) {
self->browser_window_->SetFocus();
// Return true for a windowed browser so that focus is not passed to GTK.
return self->with_osr_ ? FALSE : TRUE;
}
return FALSE;
}
// static
gboolean RootWindowGtk::WindowState(GtkWidget* widget,
GdkEventWindowState* event,
RootWindowGtk* self) {
// Called when the root window is iconified or restored. Hide the browser
// window when the root window is iconified to reduce resource usage.
if ((event->changed_mask & GDK_WINDOW_STATE_ICONIFIED) &&
self->browser_window_.get()) {
if (event->new_window_state & GDK_WINDOW_STATE_ICONIFIED)
self->browser_window_->Hide();
else
self->browser_window_->Show();
}
return TRUE;
}
// static
gboolean RootWindowGtk::WindowConfigure(GtkWindow* window,
GdkEvent* event,
RootWindowGtk* self) {
// Called when size, position or stack order changes.
CefRefPtr<CefBrowser> browser = self->GetBrowser();
if (browser.get()) {
// Notify the browser of move/resize events so that:
// - Popup windows are displayed in the correct location and dismissed
// when the window moves.
// - Drag&drop areas are updated accordingly.
browser->GetHost()->NotifyMoveOrResizeStarted();
}
return FALSE; // Don't stop this message.
}
// static
void RootWindowGtk::WindowDestroy(GtkWidget* widget, RootWindowGtk* self) {
// Called when the root window is destroyed.
self->window_destroyed_ = true;
self->NotifyDestroyedIfDone();
}
// static
gboolean RootWindowGtk::WindowDelete(GtkWidget* widget,
GdkEvent* event,
RootWindowGtk* self) {
// Called to query whether the root window should be closed.
if (self->force_close_)
return FALSE; // Allow the close.
if (self->browser_window_.get() && !self->browser_window_->IsClosing()) {
CefRefPtr<CefBrowser> browser = self->GetBrowser();
if (browser) {
// Notify the browser window that we would like to close it. This
// will result in a call to ClientHandler::DoClose() if the
// JavaScript 'onbeforeunload' event handler allows it.
browser->GetHost()->CloseBrowser(false);
// Cancel the close.
return TRUE;
}
}
// Allow the close.
return FALSE;
}
// static
void RootWindowGtk::VboxSizeAllocated(GtkWidget* widget,
GtkAllocation* allocation,
RootWindowGtk* self) {
// Offset browser positioning by any controls that will appear in the client
// area.
const int ux_height = self->toolbar_height_ + self->menubar_height_;
const int x = allocation->x;
const int y = allocation->y + ux_height;
const int width = allocation->width;
const int height = allocation->height - ux_height;
// Size the browser window to match the GTK widget.
self->browser_bounds_ = CefRect(x, y, width, height);
if (self->browser_window_.get())
self->browser_window_->SetBounds(x, y, width, height);
}
// static
void RootWindowGtk::MenubarSizeAllocated(GtkWidget* widget,
GtkAllocation* allocation,
RootWindowGtk* self) {
self->menubar_height_ = allocation->height;
}
// static
gboolean RootWindowGtk::MenuItemActivated(GtkWidget* widget,
RootWindowGtk* self) {
// Retrieve the menu ID set in AddMenuEntry.
int id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), kMenuIdKey));
// Run the test.
if (self->delegate_)
self->delegate_->OnTest(self, id);
return FALSE; // Don't stop this message.
}
// static
void RootWindowGtk::ToolbarSizeAllocated(GtkWidget* widget,
GtkAllocation* allocation,
RootWindowGtk* self) {
self->toolbar_height_ = allocation->height;
}
// static
void RootWindowGtk::BackButtonClicked(GtkButton* button,
RootWindowGtk* self) {
CefRefPtr<CefBrowser> browser = self->GetBrowser();
if (browser.get())
browser->GoBack();
}
// static
void RootWindowGtk::ForwardButtonClicked(GtkButton* button,
RootWindowGtk* self) {
CefRefPtr<CefBrowser> browser = self->GetBrowser();
if (browser.get())
browser->GoForward();
}
// static
void RootWindowGtk::StopButtonClicked(GtkButton* button,
RootWindowGtk* self) {
CefRefPtr<CefBrowser> browser = self->GetBrowser();
if (browser.get())
browser->StopLoad();
}
// static
void RootWindowGtk::ReloadButtonClicked(GtkButton* button,
RootWindowGtk* self) {
CefRefPtr<CefBrowser> browser = self->GetBrowser();
if (browser.get())
browser->Reload();
}
// static
void RootWindowGtk::URLEntryActivate(GtkEntry* entry,
RootWindowGtk* self) {
CefRefPtr<CefBrowser> browser = self->GetBrowser();
if (browser.get()) {
const gchar* url = gtk_entry_get_text(entry);
browser->GetMainFrame()->LoadURL(std::string(url).c_str());
}
}
// static
gboolean RootWindowGtk::URLEntryButtonPress(GtkWidget* widget,
GdkEventButton* event,
RootWindowGtk* self) {
// Give focus to the GTK window. This is a work-around for bad focus-related
// interaction between the root window managed by GTK and the browser managed
// by X11.
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;
}
GtkWidget* RootWindowGtk::CreateMenuBar() {
GtkWidget* menu_bar = gtk_menu_bar_new();
// Create the test menu.
GtkWidget* test_menu = CreateMenu(menu_bar, "Tests");
AddMenuEntry(test_menu, "Get Source", ID_TESTS_GETSOURCE);
AddMenuEntry(test_menu, "Get Text", ID_TESTS_GETTEXT);
AddMenuEntry(test_menu, "Popup Window", ID_TESTS_POPUP);
AddMenuEntry(test_menu, "Request", ID_TESTS_REQUEST);
AddMenuEntry(test_menu, "Plugin Info", ID_TESTS_PLUGIN_INFO);
AddMenuEntry(test_menu, "Zoom In", ID_TESTS_ZOOM_IN);
AddMenuEntry(test_menu, "Zoom Out", ID_TESTS_ZOOM_OUT);
AddMenuEntry(test_menu, "Zoom Reset", ID_TESTS_ZOOM_RESET);
AddMenuEntry(test_menu, "Begin Tracing", ID_TESTS_TRACING_BEGIN);
AddMenuEntry(test_menu, "End Tracing", ID_TESTS_TRACING_END);
AddMenuEntry(test_menu, "Print", ID_TESTS_PRINT);
AddMenuEntry(test_menu, "Other Tests", ID_TESTS_OTHER_TESTS);
return menu_bar;
}
GtkWidget* RootWindowGtk::CreateMenu(GtkWidget* menu_bar, const char* text) {
GtkWidget* menu_widget = gtk_menu_new();
GtkWidget* menu_header = gtk_menu_item_new_with_label(text);
gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_header), menu_widget);
gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar), menu_header);
return menu_widget;
}
GtkWidget* RootWindowGtk::AddMenuEntry(GtkWidget* menu_widget,
const char* text,
int id) {
GtkWidget* entry = gtk_menu_item_new_with_label(text);
g_signal_connect(entry, "activate",
G_CALLBACK(&RootWindowGtk::MenuItemActivated), this);
// Set the menu ID that will be retrieved in MenuItemActivated.
g_object_set_data(G_OBJECT(entry), kMenuIdKey, GINT_TO_POINTER(id));
gtk_menu_shell_append(GTK_MENU_SHELL(menu_widget), entry);
return entry;
}
// static
scoped_refptr<RootWindow> RootWindow::Create() {
return new RootWindowGtk();
}
} // namespace client

View File

@ -0,0 +1,151 @@
// Copyright (c) 2015 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#ifndef CEF_TESTS_CEFCLIENT_ROOT_WINDOW_GTK_H_
#define CEF_TESTS_CEFCLIENT_ROOT_WINDOW_GTK_H_
#include <gtk/gtk.h>
#include <string>
#include "include/base/cef_scoped_ptr.h"
#include "cefclient/browser_window.h"
#include "cefclient/root_window.h"
namespace client {
// GTK implementation of a top-level native window in the browser process.
// The methods of this class must be called on the main thread unless otherwise
// indicated.
class RootWindowGtk : public RootWindow,
public BrowserWindow::Delegate {
public:
// Constructor may be called on any thread.
RootWindowGtk();
~RootWindowGtk();
// RootWindow methods.
void Init(RootWindow::Delegate* delegate,
bool with_controls,
bool with_osr,
const CefRect& rect,
const CefBrowserSettings& settings,
const std::string& url) OVERRIDE;
void InitAsPopup(RootWindow::Delegate* delegate,
bool with_controls,
bool with_osr,
const CefPopupFeatures& popupFeatures,
CefWindowInfo& windowInfo,
CefRefPtr<CefClient>& client,
CefBrowserSettings& settings) OVERRIDE;
void Show(ShowMode mode) OVERRIDE;
void Hide() OVERRIDE;
void SetBounds(int x, int y, size_t width, size_t height) OVERRIDE;
void Close(bool force) OVERRIDE;
CefRefPtr<CefBrowser> GetBrowser() const OVERRIDE;
ClientWindowHandle GetWindowHandle() const OVERRIDE;
private:
void CreateBrowserWindow(const std::string& startup_url);
void CreateRootWindow(const CefBrowserSettings& settings);
// BrowserWindow::Delegate methods.
void OnBrowserCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
void OnBrowserWindowDestroyed() OVERRIDE;
void OnSetAddress(const std::string& url) OVERRIDE;
void OnSetTitle(const std::string& title) OVERRIDE;
void OnSetLoadingState(bool isLoading,
bool canGoBack,
bool canGoForward) OVERRIDE;
void NotifyDestroyedIfDone();
GtkWidget* CreateMenuBar();
GtkWidget* CreateMenu(GtkWidget* menu_bar, const char* text);
GtkWidget* AddMenuEntry(GtkWidget* menu_widget, const char* text, int id);
// Signal handlers for the top-level GTK window.
static gboolean WindowFocusIn(GtkWidget* widget,
GdkEventFocus* event,
RootWindowGtk* self);
static gboolean WindowState(GtkWidget* widget,
GdkEventWindowState* event,
RootWindowGtk* self);
static gboolean WindowConfigure(GtkWindow* window,
GdkEvent* event,
RootWindowGtk* self);
static void WindowDestroy(GtkWidget* widget, RootWindowGtk* self);
static gboolean WindowDelete(GtkWidget* widget,
GdkEvent* event,
RootWindowGtk* self);
// Signal handlers for the GTK Vbox containing all UX elements.
static void VboxSizeAllocated(GtkWidget* widget,
GtkAllocation* allocation,
RootWindowGtk* self);
// Signal handlers for the GTK menu bar.
static void MenubarSizeAllocated(GtkWidget* widget,
GtkAllocation* allocation,
RootWindowGtk* self);
static gboolean MenuItemActivated(GtkWidget* widget,
RootWindowGtk* self);
// Signal handlers for the GTK toolbar.
static void ToolbarSizeAllocated(GtkWidget* widget,
GtkAllocation* allocation,
RootWindowGtk* self);
static void BackButtonClicked(GtkButton* button,
RootWindowGtk* self);
static void ForwardButtonClicked(GtkButton* button,
RootWindowGtk* self);
static void StopButtonClicked(GtkButton* button,
RootWindowGtk* self);
static void ReloadButtonClicked(GtkButton* button,
RootWindowGtk* self);
// Signal handlers for the GTK URL entry field.
static void URLEntryActivate(GtkEntry* entry,
RootWindowGtk* self);
static gboolean URLEntryButtonPress(GtkWidget* widget,
GdkEventButton* event,
RootWindowGtk* self);
// After initialization all members are only accessed on the main thread.
// Members set during initialization.
RootWindow::Delegate* delegate_;
bool with_controls_;
bool with_osr_;
bool is_popup_;
CefRect start_rect_;
scoped_ptr<BrowserWindow> browser_window_;
bool initialized_;
// Main window.
GtkWidget* window_;
// Buttons.
GtkToolItem* back_button_;
GtkToolItem* forward_button_;
GtkToolItem* reload_button_;
GtkToolItem* stop_button_;
// URL text field.
GtkWidget* url_entry_;
// Height of UX controls that affect browser window placement.
int toolbar_height_;
int menubar_height_;
CefRect browser_bounds_;
bool force_close_;
bool window_destroyed_;
bool browser_destroyed_;
DISALLOW_COPY_AND_ASSIGN(RootWindowGtk);
};
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_ROOT_WINDOW_GTK_H_

View File

@ -13,6 +13,8 @@
#if defined(OS_WIN)
#include "cefclient/temp_window_win.h"
#elif defined(OS_LINUX)
#include "cefclient/temp_window_x11.h"
#endif
namespace client {
@ -76,9 +78,11 @@ class RootWindowManager : public RootWindow::Delegate {
typedef std::set<scoped_refptr<RootWindow> > RootWindowSet;
RootWindowSet root_windows_;
#if defined(OS_WIN)
// Singleton window used as the temporary parent for popup browsers.
#if defined(OS_WIN)
TempWindowWin temp_window_win_;
#elif defined(OS_LINUX)
TempWindowX11 temp_window_x11_;
#endif
DISALLOW_COPY_AND_ASSIGN(RootWindowManager);

View File

@ -134,7 +134,7 @@ void RootWindowWin::InitAsPopup(RootWindow::Delegate* delegate,
// The new popup is initially parented to a temporary window. The native root
// window will be created after the browser is created and the popup window
// will be re-parented to it at that time.
browser_window_->GetPopupConfig(TempWindowWin::GetHWND(),
browser_window_->GetPopupConfig(TempWindowWin::GetWindowHandle(),
windowInfo, client, settings);
}
@ -147,10 +147,10 @@ void RootWindowWin::Show(ShowMode mode) {
int nCmdShow = SW_SHOWNORMAL;
switch (mode) {
case ShowMinimized:
nCmdShow = SW_SHOWNORMAL;
nCmdShow = SW_SHOWMINIMIZED;
break;
case ShowMaximized:
nCmdShow = SW_SHOWNORMAL;
nCmdShow = SW_SHOWMAXIMIZED;
break;
default:
break;
@ -193,7 +193,7 @@ CefRefPtr<CefBrowser> RootWindowWin::GetBrowser() const {
return NULL;
}
CefWindowHandle RootWindowWin::GetWindowHandle() const {
ClientWindowHandle RootWindowWin::GetWindowHandle() const {
REQUIRE_MAIN_THREAD();
return hwnd_;
}
@ -322,7 +322,10 @@ void RootWindowWin::CreateRootWindow(const CefBrowserSettings& settings) {
if (!is_popup_) {
// Create the browser window.
browser_window_->CreateBrowser(hwnd_, rect, settings);
CefRect cef_rect(rect.left, rect.top,
rect.right - rect.left,
rect.bottom - rect.top);
browser_window_->CreateBrowser(hwnd_, cef_rect, settings);
} else {
// With popups we already have a browser window. Parent the browser window
// to the root window and show it in the correct location.
@ -533,7 +536,7 @@ void RootWindowWin::OnSize(bool minimized) {
int urloffset = rect.left + BUTTON_WIDTH * 4;
if (browser_window_) {
HWND browser_hwnd = browser_window_->GetHWND();
HWND browser_hwnd = browser_window_->GetWindowHandle();
HDWP hdwp = BeginDeferWindowPos(1);
hdwp = DeferWindowPos(hdwp, edit_hwnd_, NULL, urloffset,
0, rect.right - urloffset, URLBAR_HEIGHT, SWP_NOZORDER);
@ -696,7 +699,6 @@ void RootWindowWin::OnBrowserWindowDestroyed() {
REQUIRE_MAIN_THREAD();
browser_window_.reset();
browser_destroyed_ = true;
if (!window_destroyed_) {
// The browser was destroyed first. This could be due to the use of
@ -705,6 +707,7 @@ void RootWindowWin::OnBrowserWindowDestroyed() {
Close(false);
}
browser_destroyed_ = true;
NotifyDestroyedIfDone();
}

View File

@ -11,7 +11,7 @@
#include <string>
#include "include/base/cef_scoped_ptr.h"
#include "cefclient/browser_window_win.h"
#include "cefclient/browser_window.h"
#include "cefclient/root_window.h"
namespace client {
@ -20,7 +20,7 @@ namespace client {
// The methods of this class must be called on the main thread unless otherwise
// indicated.
class RootWindowWin : public RootWindow,
public BrowserWindowWin::Delegate {
public BrowserWindow::Delegate {
public:
// Constructor may be called on any thread.
RootWindowWin();
@ -45,7 +45,7 @@ class RootWindowWin : public RootWindow,
void SetBounds(int x, int y, size_t width, size_t height) OVERRIDE;
void Close(bool force) OVERRIDE;
CefRefPtr<CefBrowser> GetBrowser() const OVERRIDE;
CefWindowHandle GetWindowHandle() const OVERRIDE;
ClientWindowHandle GetWindowHandle() const OVERRIDE;
private:
void CreateBrowserWindow(bool with_osr, const std::string& startup_url);
@ -79,7 +79,7 @@ class RootWindowWin : public RootWindow,
bool OnClose();
void OnDestroyed();
// BrowserWindowWin::Delegate methods.
// BrowserWindow::Delegate methods.
void OnBrowserCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
void OnBrowserWindowDestroyed() OVERRIDE;
void OnSetAddress(const std::string& url) OVERRIDE;
@ -96,7 +96,7 @@ class RootWindowWin : public RootWindow,
bool with_controls_;
bool is_popup_;
RECT start_rect_;
scoped_ptr<BrowserWindowWin> browser_window_;
scoped_ptr<BrowserWindow> browser_window_;
bool initialized_;
// Main window.

View File

@ -4,6 +4,8 @@
#include "cefclient/temp_window_win.h"
#include <windows.h>
#include "include/base/cef_logging.h"
namespace client {
@ -50,7 +52,7 @@ TempWindowWin::~TempWindowWin() {
}
// static
HWND TempWindowWin::GetHWND() {
CefWindowHandle TempWindowWin::GetWindowHandle() {
DCHECK(g_temp_window);
return g_temp_window->hwnd_;
}

View File

@ -5,8 +5,6 @@
#ifndef CEF_TESTS_CEFCLIENT_TEMP_WINDOW_WIN_H_
#define CEF_TESTS_CEFCLIENT_TEMP_WINDOW_WIN_H_
#include <windows.h>
#include "cefclient/main_message_loop.h"
namespace client {
@ -15,8 +13,8 @@ namespace client {
// popup browsers.
class TempWindowWin {
public:
// Returns the singleton window HWND.
static HWND GetHWND();
// Returns the singleton window handle.
static CefWindowHandle GetWindowHandle();
private:
// A single instance will be created/owned by RootWindowManager.
@ -25,7 +23,7 @@ class TempWindowWin {
TempWindowWin();
~TempWindowWin();
HWND hwnd_;
CefWindowHandle hwnd_;
DISALLOW_COPY_AND_ASSIGN(TempWindowWin);
};

View File

@ -0,0 +1,69 @@
// Copyright (c) 2015 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#include "cefclient/temp_window_x11.h"
#include <X11/Xlib.h>
#include "include/base/cef_logging.h"
#include "include/cef_app.h"
namespace client {
namespace {
// Create the temp window.
::Window CreateTempWindow() {
::Display* xdisplay = cef_get_xdisplay();
::Window parent_xwindow = DefaultRootWindow(xdisplay);
XSetWindowAttributes swa;
memset(&swa, 0, sizeof(swa));
swa.background_pixmap = None;
swa.override_redirect = false;
return XCreateWindow(
xdisplay, parent_xwindow,
0, 0, 1, 1, // size (1x1px)
0, // border width
CopyFromParent, // depth
InputOutput,
CopyFromParent, // visual
CWBackPixmap | CWOverrideRedirect,
&swa);
}
// Close the temp window.
void CloseTempWindow(::Window xwindow) {
::Display* xdisplay = cef_get_xdisplay();
XDestroyWindow(xdisplay, xwindow);
}
TempWindowX11* g_temp_window = NULL;
} // namespace
TempWindowX11::TempWindowX11()
: xwindow_(kNullWindowHandle) {
DCHECK(!g_temp_window);
g_temp_window = this;
xwindow_ = CreateTempWindow();
CHECK(xwindow_);
}
TempWindowX11::~TempWindowX11() {
g_temp_window = NULL;
DCHECK(xwindow_);
CloseTempWindow(xwindow_);
}
// static
CefWindowHandle TempWindowX11::GetWindowHandle() {
DCHECK(g_temp_window);
return g_temp_window->xwindow_;
}
} // namespace client

View File

@ -0,0 +1,33 @@
// Copyright (c) 2015 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#ifndef CEF_TESTS_CEFCLIENT_TEMP_WINDOW_X11_H_
#define CEF_TESTS_CEFCLIENT_TEMP_WINDOW_X11_H_
#include "cefclient/main_message_loop.h"
namespace client {
// Represents a singleton hidden window that acts at temporary parent for
// popup browsers.
class TempWindowX11 {
public:
// Returns the singleton window handle.
static CefWindowHandle GetWindowHandle();
private:
// A single instance will be created/owned by RootWindowManager.
friend class RootWindowManager;
TempWindowX11();
~TempWindowX11();
CefWindowHandle xwindow_;
DISALLOW_COPY_AND_ASSIGN(TempWindowX11);
};
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_TEMP_WINDOW_X11_H_