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

Side by Side Diff: ui/ozone/platform/x11/x11_window_ozone.cc

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

Powered by Google App Engine
This is Rietveld 408576698