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

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

Powered by Google App Engine
This is Rietveld 408576698