• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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