| // 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 "tests/cefclient/browser/browser_window_std_gtk.h" |
| |
| #include <gdk/gdk.h> |
| #include <gdk/gdkx.h> |
| #include <gtk/gtk.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 "tests/cefclient/browser/client_handler_std.h" |
| #include "tests/cefclient/browser/util_gtk.h" |
| #include "tests/shared/browser/main_message_loop.h" |
| |
| namespace client { |
| |
| namespace { |
| |
| ::Window GetXWindowForWidget(GtkWidget* widget) { |
| ScopedGdkThreadsEnter scoped_gdk_threads; |
| |
| // 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(XDisplay* xdisplay, ::Window xwindow, bool visible) { |
| CHECK(xdisplay != 0); |
| |
| // 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(XDisplay* xdisplay, |
| ::Window xwindow, |
| int x, |
| int y, |
| size_t width, |
| size_t height) { |
| CHECK(xdisplay != 0); |
| 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), xdisplay_(nullptr) { |
| client_handler_ = new ClientHandlerStd(this, startup_url); |
| } |
| |
| void BrowserWindowStdGtk::set_xdisplay(XDisplay* xdisplay) { |
| REQUIRE_MAIN_THREAD(); |
| DCHECK(!xdisplay_); |
| xdisplay_ = xdisplay; |
| } |
| |
| void BrowserWindowStdGtk::CreateBrowser( |
| ClientWindowHandle parent_handle, |
| const CefRect& rect, |
| const CefBrowserSettings& settings, |
| CefRefPtr<CefDictionaryValue> extra_info, |
| CefRefPtr<CefRequestContext> request_context) { |
| REQUIRE_MAIN_THREAD(); |
| |
| CefWindowInfo window_info; |
| window_info.SetAsChild(GetXWindowForWidget(parent_handle), rect); |
| |
| CefBrowserHost::CreateBrowser(window_info, client_handler_, |
| client_handler_->startup_url(), settings, |
| extra_info, request_context); |
| } |
| |
| void BrowserWindowStdGtk::GetPopupConfig(CefWindowHandle temp_handle, |
| CefWindowInfo& windowInfo, |
| CefRefPtr<CefClient>& client, |
| CefBrowserSettings& settings) { |
| CEF_REQUIRE_UI_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(); |
| |
| if (browser_) { |
| ::Window parent_xwindow = GetXWindowForWidget(parent_handle); |
| CHECK(xdisplay_ != 0); |
| ::Window xwindow = browser_->GetHost()->GetWindowHandle(); |
| DCHECK(xwindow); |
| |
| XReparentWindow(xdisplay_, xwindow, parent_xwindow, x, y); |
| |
| SetXWindowBounds(xdisplay_, xwindow, x, y, width, height); |
| SetXWindowVisible(xdisplay_, xwindow, true); |
| } |
| } |
| |
| void BrowserWindowStdGtk::Show() { |
| REQUIRE_MAIN_THREAD(); |
| |
| if (browser_) { |
| ::Window xwindow = browser_->GetHost()->GetWindowHandle(); |
| DCHECK(xwindow); |
| SetXWindowVisible(xdisplay_, xwindow, true); |
| } |
| } |
| |
| void BrowserWindowStdGtk::Hide() { |
| REQUIRE_MAIN_THREAD(); |
| |
| if (browser_) { |
| ::Window xwindow = browser_->GetHost()->GetWindowHandle(); |
| DCHECK(xwindow); |
| SetXWindowVisible(xdisplay_, xwindow, false); |
| } |
| } |
| |
| void BrowserWindowStdGtk::SetBounds(int x, int y, size_t width, size_t height) { |
| REQUIRE_MAIN_THREAD(); |
| |
| if (xdisplay_ && browser_) { |
| ::Window xwindow = browser_->GetHost()->GetWindowHandle(); |
| DCHECK(xwindow); |
| SetXWindowBounds(xdisplay_, xwindow, x, y, width, height); |
| } |
| } |
| |
| void BrowserWindowStdGtk::SetFocus(bool focus) { |
| REQUIRE_MAIN_THREAD(); |
| |
| if (browser_) |
| browser_->GetHost()->SetFocus(focus); |
| } |
| |
| ClientWindowHandle BrowserWindowStdGtk::GetWindowHandle() const { |
| REQUIRE_MAIN_THREAD(); |
| |
| // There is no GtkWidget* representation of this object. |
| NOTREACHED(); |
| return NULL; |
| } |
| |
| } // namespace client |