Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(700)

Side by Side Diff: ui/platform_window/x11/x11_window_base.cc

Issue 1602173005: Add PlatformWindow/Event related code for Ozone X11. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Final fixes for comments + tests. Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ui/platform_window/x11/x11_window_base.h ('k') | ui/platform_window/x11/x11_window_ozone.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ui/platform_window/x11/x11_window_base.h"
6
7 #include <X11/extensions/XInput2.h>
8 #include <X11/Xatom.h>
9 #include <X11/Xlib.h>
10 #include <X11/Xutil.h>
11
12 #include <string>
13
14 #include "base/strings/utf_string_conversions.h"
15 #include "ui/events/devices/x11/touch_factory_x11.h"
16 #include "ui/events/event.h"
17 #include "ui/events/event_utils.h"
18 #include "ui/events/platform/platform_event_dispatcher.h"
19 #include "ui/events/platform/platform_event_source.h"
20 #include "ui/events/platform/x11/x11_event_source.h"
21 #include "ui/gfx/geometry/rect.h"
22 #include "ui/gfx/x/x11_atom_cache.h"
23 #include "ui/gfx/x/x11_types.h"
24 #include "ui/platform_window/platform_window_delegate.h"
25
26 namespace ui {
27
28 namespace {
29
30 const char* kAtomsToCache[] = {"UTF8_STRING", "WM_DELETE_WINDOW",
31 "_NET_WM_NAME", "_NET_WM_PID",
32 "_NET_WM_PING", NULL};
33
34 bool g_override_redirect = false;
35
36 XID FindXEventTarget(const XEvent& xev) {
37 XID target = xev.xany.window;
38 if (xev.type == GenericEvent)
39 target = static_cast<XIDeviceEvent*>(xev.xcookie.data)->event;
40 return target;
41 }
42
43 } // namespace
44
45 X11WindowBase::X11WindowBase(PlatformWindowDelegate* delegate)
46 : delegate_(delegate),
47 xdisplay_(gfx::GetXDisplay()),
48 xwindow_(None),
49 xroot_window_(DefaultRootWindow(xdisplay_)),
50 atom_cache_(xdisplay_, kAtomsToCache) {
51 DCHECK(delegate_);
52 TouchFactory::SetTouchDeviceListFromCommandLine();
53 }
54
55 X11WindowBase::~X11WindowBase() {
56 Destroy();
57 }
58
59 void X11WindowBase::Destroy() {
60 if (xwindow_ == None)
61 return;
62
63 // Stop processing events.
64 XID xwindow = xwindow_;
65 XDisplay* xdisplay = xdisplay_;
66 xwindow_ = None;
67 delegate_->OnClosed();
68 // |this| might be deleted because of the above call.
69
70 XDestroyWindow(xdisplay, xwindow);
71 }
72
73 void X11WindowBase::Create() {
74 XSetWindowAttributes swa;
75 memset(&swa, 0, sizeof(swa));
76 swa.background_pixmap = None;
77 swa.bit_gravity = NorthWestGravity;
78 swa.override_redirect = g_override_redirect;
79 xwindow_ = XCreateWindow(
80 xdisplay_, xroot_window_, requested_bounds_.x(), requested_bounds_.y(),
81 requested_bounds_.width(), requested_bounds_.height(),
82 0, // border width
83 CopyFromParent, // depth
84 InputOutput,
85 CopyFromParent, // visual
86 CWBackPixmap | CWBitGravity | CWOverrideRedirect, &swa);
87
88 long event_mask = ButtonPressMask | ButtonReleaseMask | FocusChangeMask |
89 KeyPressMask | KeyReleaseMask | EnterWindowMask |
90 LeaveWindowMask | ExposureMask | VisibilityChangeMask |
91 StructureNotifyMask | PropertyChangeMask |
92 PointerMotionMask;
93 XSelectInput(xdisplay_, xwindow_, event_mask);
94
95 unsigned char mask[XIMaskLen(XI_LASTEVENT)];
96 memset(mask, 0, sizeof(mask));
97
98 XISetMask(mask, XI_TouchBegin);
99 XISetMask(mask, XI_TouchUpdate);
100 XISetMask(mask, XI_TouchEnd);
101 XISetMask(mask, XI_ButtonPress);
102 XISetMask(mask, XI_ButtonRelease);
103 XISetMask(mask, XI_Motion);
104 XISetMask(mask, XI_KeyPress);
105 XISetMask(mask, XI_KeyRelease);
106
107 XIEventMask evmask;
108 evmask.deviceid = XIAllDevices;
109 evmask.mask_len = sizeof(mask);
110 evmask.mask = mask;
111 XISelectEvents(xdisplay_, xwindow_, &evmask, 1);
112 XFlush(xdisplay_);
113
114 ::Atom protocols[2];
115 protocols[0] = atom_cache_.GetAtom("WM_DELETE_WINDOW");
116 protocols[1] = atom_cache_.GetAtom("_NET_WM_PING");
117 XSetWMProtocols(xdisplay_, xwindow_, protocols, 2);
118
119 // We need a WM_CLIENT_MACHINE and WM_LOCALE_NAME value so we integrate with
120 // the desktop environment.
121 XSetWMProperties(xdisplay_, xwindow_, NULL, NULL, NULL, 0, NULL, NULL, NULL);
122
123 // Likewise, the X server needs to know this window's pid so it knows which
124 // program to kill if the window hangs.
125 // XChangeProperty() expects "pid" to be long.
126 static_assert(sizeof(long) >= sizeof(pid_t),
127 "pid_t should not be larger than long");
128 long pid = getpid();
129 XChangeProperty(xdisplay_, xwindow_, atom_cache_.GetAtom("_NET_WM_PID"),
130 XA_CARDINAL, 32, PropModeReplace,
131 reinterpret_cast<unsigned char*>(&pid), 1);
132 // Before we map the window, set size hints. Otherwise, some window managers
133 // will ignore toplevel XMoveWindow commands.
134 XSizeHints size_hints;
135 size_hints.flags = PPosition | PWinGravity;
136 size_hints.x = requested_bounds_.x();
137 size_hints.y = requested_bounds_.y();
138 // Set StaticGravity so that the window position is not affected by the
139 // frame width when running with window manager.
140 size_hints.win_gravity = StaticGravity;
141 XSetWMNormalHints(xdisplay_, xwindow_, &size_hints);
142
143 // TODO(sky): provide real scale factor.
144 delegate_->OnAcceleratedWidgetAvailable(xwindow_, 1.f);
145 }
146
147 void X11WindowBase::Show() {
148 if (window_mapped_)
149 return;
150 if (xwindow_ == None)
151 Create();
152
153 XMapWindow(xdisplay_, xwindow_);
154
155 // We now block until our window is mapped. Some X11 APIs will crash and
156 // burn if passed |xwindow_| before the window is mapped, and XMapWindow is
157 // asynchronous.
158 if (X11EventSource::GetInstance())
159 X11EventSource::GetInstance()->BlockUntilWindowMapped(xwindow_);
160 window_mapped_ = true;
161 }
162
163 void X11WindowBase::Hide() {
164 if (!window_mapped_)
165 return;
166 XWithdrawWindow(xdisplay_, xwindow_, 0);
167 window_mapped_ = false;
168 }
169
170 void X11WindowBase::Close() {
171 Destroy();
172 }
173
174 void X11WindowBase::SetBounds(const gfx::Rect& bounds) {
175 requested_bounds_ = bounds;
176 if (!window_mapped_ || bounds == confirmed_bounds_)
177 return;
178 XWindowChanges changes = {0};
179 unsigned value_mask = CWX | CWY | CWWidth | CWHeight;
180 changes.x = bounds.x();
181 changes.y = bounds.y();
182 changes.width = bounds.width();
183 changes.height = bounds.height();
184 XConfigureWindow(xdisplay_, xwindow_, value_mask, &changes);
185 }
186
187 gfx::Rect X11WindowBase::GetBounds() {
188 return confirmed_bounds_;
189 }
190
191 void X11WindowBase::SetTitle(const base::string16& title) {
192 if (window_title_ == title)
193 return;
194 window_title_ = title;
195 std::string utf8str = base::UTF16ToUTF8(title);
196 XChangeProperty(xdisplay_, xwindow_, atom_cache_.GetAtom("_NET_WM_NAME"),
197 atom_cache_.GetAtom("UTF8_STRING"), 8, PropModeReplace,
198 reinterpret_cast<const unsigned char*>(utf8str.c_str()),
199 utf8str.size());
200 XTextProperty xtp;
201 char* c_utf8_str = const_cast<char*>(utf8str.c_str());
202 if (Xutf8TextListToTextProperty(xdisplay_, &c_utf8_str, 1, XUTF8StringStyle,
203 &xtp) == Success) {
204 XSetWMName(xdisplay_, xwindow_, &xtp);
205 XFree(xtp.value);
206 }
207 }
208
209 void X11WindowBase::SetCapture() {}
210
211 void X11WindowBase::ReleaseCapture() {}
212
213 void X11WindowBase::ToggleFullscreen() {}
214
215 void X11WindowBase::Maximize() {}
216
217 void X11WindowBase::Minimize() {}
218
219 void X11WindowBase::Restore() {}
220
221 void X11WindowBase::MoveCursorTo(const gfx::Point& location) {}
222
223 void X11WindowBase::ConfineCursorToBounds(const gfx::Rect& bounds) {}
224
225 PlatformImeController* X11WindowBase::GetPlatformImeController() {
226 return nullptr;
227 }
228
229 bool X11WindowBase::IsEventForXWindow(const XEvent& xev) const {
230 return xwindow_ != None && FindXEventTarget(xev) == xwindow_;
231 }
232
233 void X11WindowBase::ProcessXWindowEvent(XEvent* xev) {
234 switch (xev->type) {
235 case Expose: {
236 gfx::Rect damage_rect(xev->xexpose.x, xev->xexpose.y, xev->xexpose.width,
237 xev->xexpose.height);
238 delegate_->OnDamageRect(damage_rect);
239 break;
240 }
241
242 case FocusOut:
243 if (xev->xfocus.mode != NotifyGrab)
244 delegate_->OnLostCapture();
245 break;
246
247 case ConfigureNotify: {
248 DCHECK_EQ(xwindow_, xev->xconfigure.event);
249 DCHECK_EQ(xwindow_, xev->xconfigure.window);
250 gfx::Rect bounds(xev->xconfigure.x, xev->xconfigure.y,
251 xev->xconfigure.width, xev->xconfigure.height);
252 if (confirmed_bounds_ != bounds) {
253 confirmed_bounds_ = bounds;
254 delegate_->OnBoundsChanged(confirmed_bounds_);
255 }
256 break;
257 }
258
259 case ClientMessage: {
260 Atom message = static_cast<Atom>(xev->xclient.data.l[0]);
261 if (message == atom_cache_.GetAtom("WM_DELETE_WINDOW")) {
262 delegate_->OnCloseRequest();
263 } else if (message == atom_cache_.GetAtom("_NET_WM_PING")) {
264 XEvent reply_event = *xev;
265 reply_event.xclient.window = xroot_window_;
266
267 XSendEvent(xdisplay_, reply_event.xclient.window, False,
268 SubstructureRedirectMask | SubstructureNotifyMask,
269 &reply_event);
270 XFlush(xdisplay_);
271 }
272 break;
273 }
274 }
275 }
276
277 namespace test {
278
279 void SetUseOverrideRedirectWindowByDefault(bool override_redirect) {
280 g_override_redirect = override_redirect;
281 }
282
283 } // namespace test
284 } // namespace ui
OLDNEW
« no previous file with comments | « ui/platform_window/x11/x11_window_base.h ('k') | ui/platform_window/x11/x11_window_ozone.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698