1 // Copyright (c) 2015 The Chromium Embedded Framework Authors. All rights
2 // reserved. Use of this source code is governed by a BSD-style license that
3 // can be found in the LICENSE file.
4
5 #include "tests/cefclient/browser/browser_window_std_gtk.h"
6
7 #include <gdk/gdk.h>
8 #include <gdk/gdkx.h>
9 #include <gtk/gtk.h>
10
11 #include <X11/Xlib.h>
12 #undef Success // Definition conflicts with cef_message_router.h
13 #undef RootWindow // Definition conflicts with root_window.h
14
15 #include "include/base/cef_logging.h"
16 #include "tests/cefclient/browser/client_handler_std.h"
17 #include "tests/cefclient/browser/util_gtk.h"
18 #include "tests/shared/browser/main_message_loop.h"
19
20 namespace client {
21
22 namespace {
23
GetXWindowForWidget(GtkWidget * widget)24 ::Window GetXWindowForWidget(GtkWidget* widget) {
25 ScopedGdkThreadsEnter scoped_gdk_threads;
26
27 // The GTK window must be visible before we can retrieve the XID.
28 ::Window xwindow = GDK_WINDOW_XID(gtk_widget_get_window(widget));
29 DCHECK(xwindow);
30 return xwindow;
31 }
32
SetXWindowVisible(XDisplay * xdisplay,::Window xwindow,bool visible)33 void SetXWindowVisible(XDisplay* xdisplay, ::Window xwindow, bool visible) {
34 CHECK(xdisplay != 0);
35
36 // Retrieve the atoms required by the below XChangeProperty call.
37 const char* kAtoms[] = {"_NET_WM_STATE", "ATOM", "_NET_WM_STATE_HIDDEN"};
38 Atom atoms[3];
39 int result =
40 XInternAtoms(xdisplay, const_cast<char**>(kAtoms), 3, false, atoms);
41 if (!result)
42 NOTREACHED();
43
44 if (!visible) {
45 // Set the hidden property state value.
46 std::unique_ptr<Atom[]> data(new Atom[1]);
47 data[0] = atoms[2];
48
49 XChangeProperty(xdisplay, xwindow,
50 atoms[0], // name
51 atoms[1], // type
52 32, // size in bits of items in 'value'
53 PropModeReplace,
54 reinterpret_cast<const unsigned char*>(data.get()),
55 1); // num items
56 } else {
57 // Set an empty array of property state values.
58 XChangeProperty(xdisplay, xwindow,
59 atoms[0], // name
60 atoms[1], // type
61 32, // size in bits of items in 'value'
62 PropModeReplace, nullptr,
63 0); // num items
64 }
65 }
66
SetXWindowBounds(XDisplay * xdisplay,::Window xwindow,int x,int y,size_t width,size_t height)67 void SetXWindowBounds(XDisplay* xdisplay,
68 ::Window xwindow,
69 int x,
70 int y,
71 size_t width,
72 size_t height) {
73 CHECK(xdisplay != 0);
74 XWindowChanges changes = {0};
75 changes.x = x;
76 changes.y = y;
77 changes.width = static_cast<int>(width);
78 changes.height = static_cast<int>(height);
79 XConfigureWindow(xdisplay, xwindow, CWX | CWY | CWHeight | CWWidth, &changes);
80 }
81
82 } // namespace
83
BrowserWindowStdGtk(Delegate * delegate,const std::string & startup_url)84 BrowserWindowStdGtk::BrowserWindowStdGtk(Delegate* delegate,
85 const std::string& startup_url)
86 : BrowserWindow(delegate), xdisplay_(nullptr) {
87 client_handler_ = new ClientHandlerStd(this, startup_url);
88 }
89
set_xdisplay(XDisplay * xdisplay)90 void BrowserWindowStdGtk::set_xdisplay(XDisplay* xdisplay) {
91 REQUIRE_MAIN_THREAD();
92 DCHECK(!xdisplay_);
93 xdisplay_ = xdisplay;
94 }
95
CreateBrowser(ClientWindowHandle parent_handle,const CefRect & rect,const CefBrowserSettings & settings,CefRefPtr<CefDictionaryValue> extra_info,CefRefPtr<CefRequestContext> request_context)96 void BrowserWindowStdGtk::CreateBrowser(
97 ClientWindowHandle parent_handle,
98 const CefRect& rect,
99 const CefBrowserSettings& settings,
100 CefRefPtr<CefDictionaryValue> extra_info,
101 CefRefPtr<CefRequestContext> request_context) {
102 REQUIRE_MAIN_THREAD();
103
104 CefWindowInfo window_info;
105 window_info.SetAsChild(GetXWindowForWidget(parent_handle), rect);
106
107 CefBrowserHost::CreateBrowser(window_info, client_handler_,
108 client_handler_->startup_url(), settings,
109 extra_info, request_context);
110 }
111
GetPopupConfig(CefWindowHandle temp_handle,CefWindowInfo & windowInfo,CefRefPtr<CefClient> & client,CefBrowserSettings & settings)112 void BrowserWindowStdGtk::GetPopupConfig(CefWindowHandle temp_handle,
113 CefWindowInfo& windowInfo,
114 CefRefPtr<CefClient>& client,
115 CefBrowserSettings& settings) {
116 CEF_REQUIRE_UI_THREAD();
117
118 // The window will be properly sized after the browser is created.
119 windowInfo.SetAsChild(temp_handle, CefRect());
120 client = client_handler_;
121 }
122
ShowPopup(ClientWindowHandle parent_handle,int x,int y,size_t width,size_t height)123 void BrowserWindowStdGtk::ShowPopup(ClientWindowHandle parent_handle,
124 int x,
125 int y,
126 size_t width,
127 size_t height) {
128 REQUIRE_MAIN_THREAD();
129
130 if (browser_) {
131 ::Window parent_xwindow = GetXWindowForWidget(parent_handle);
132 CHECK(xdisplay_ != 0);
133 ::Window xwindow = browser_->GetHost()->GetWindowHandle();
134 DCHECK(xwindow);
135
136 XReparentWindow(xdisplay_, xwindow, parent_xwindow, x, y);
137
138 SetXWindowBounds(xdisplay_, xwindow, x, y, width, height);
139 SetXWindowVisible(xdisplay_, xwindow, true);
140 }
141 }
142
Show()143 void BrowserWindowStdGtk::Show() {
144 REQUIRE_MAIN_THREAD();
145
146 if (browser_) {
147 ::Window xwindow = browser_->GetHost()->GetWindowHandle();
148 DCHECK(xwindow);
149 SetXWindowVisible(xdisplay_, xwindow, true);
150 }
151 }
152
Hide()153 void BrowserWindowStdGtk::Hide() {
154 REQUIRE_MAIN_THREAD();
155
156 if (browser_) {
157 ::Window xwindow = browser_->GetHost()->GetWindowHandle();
158 DCHECK(xwindow);
159 SetXWindowVisible(xdisplay_, xwindow, false);
160 }
161 }
162
SetBounds(int x,int y,size_t width,size_t height)163 void BrowserWindowStdGtk::SetBounds(int x, int y, size_t width, size_t height) {
164 REQUIRE_MAIN_THREAD();
165
166 if (xdisplay_ && browser_) {
167 ::Window xwindow = browser_->GetHost()->GetWindowHandle();
168 DCHECK(xwindow);
169 SetXWindowBounds(xdisplay_, xwindow, x, y, width, height);
170 }
171 }
172
SetFocus(bool focus)173 void BrowserWindowStdGtk::SetFocus(bool focus) {
174 REQUIRE_MAIN_THREAD();
175
176 if (browser_)
177 browser_->GetHost()->SetFocus(focus);
178 }
179
GetWindowHandle() const180 ClientWindowHandle BrowserWindowStdGtk::GetWindowHandle() const {
181 REQUIRE_MAIN_THREAD();
182
183 // There is no GtkWidget* representation of this object.
184 NOTREACHED();
185 return nullptr;
186 }
187
188 } // namespace client
189