Remove ExtensionPrefs::SetDidExtensionEscalatePermissions.
[chromium-blink-merge.git] / ui / platform_window / x11 / x11_window.cc
blobed6d353665e3761d3b992229a2b2dafc770c3cc9
1 // Copyright 2014 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.
5 #include "ui/platform_window/x11/x11_window.h"
7 #include <X11/extensions/XInput2.h>
8 #include <X11/Xatom.h>
9 #include <X11/Xlib.h>
10 #include <X11/Xutil.h>
12 #include "ui/events/devices/x11/touch_factory_x11.h"
13 #include "ui/events/event.h"
14 #include "ui/events/event_utils.h"
15 #include "ui/events/platform/platform_event_dispatcher.h"
16 #include "ui/events/platform/platform_event_source.h"
17 #include "ui/events/platform/x11/x11_event_source.h"
18 #include "ui/gfx/geometry/rect.h"
19 #include "ui/gfx/x/x11_atom_cache.h"
20 #include "ui/gfx/x/x11_types.h"
21 #include "ui/platform_window/platform_window_delegate.h"
23 namespace ui {
25 namespace {
27 const char* kAtomsToCache[] = {
28 "WM_DELETE_WINDOW",
29 "_NET_WM_PING",
30 "_NET_WM_PID",
31 NULL
34 XID FindXEventTarget(XEvent* xevent) {
35 XID target = xevent->xany.window;
36 if (xevent->type == GenericEvent)
37 target = static_cast<XIDeviceEvent*>(xevent->xcookie.data)->event;
38 return target;
41 } // namespace
43 X11Window::X11Window(PlatformWindowDelegate* delegate)
44 : delegate_(delegate),
45 xdisplay_(gfx::GetXDisplay()),
46 xwindow_(None),
47 xroot_window_(DefaultRootWindow(xdisplay_)),
48 atom_cache_(xdisplay_, kAtomsToCache),
49 window_mapped_(false) {
50 CHECK(delegate_);
51 TouchFactory::SetTouchDeviceListFromCommandLine();
54 X11Window::~X11Window() {
57 void X11Window::Destroy() {
58 if (xwindow_ == None)
59 return;
61 // Stop processing events.
62 PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this);
63 XID xwindow = xwindow_;
64 XDisplay* xdisplay = xdisplay_;
65 xwindow_ = None;
66 delegate_->OnClosed();
67 // |this| might be deleted because of the above call.
69 XDestroyWindow(xdisplay, xwindow);
72 void X11Window::ProcessXInput2Event(XEvent* xev) {
73 if (!TouchFactory::GetInstance()->ShouldProcessXI2Event(xev))
74 return;
75 EventType event_type = EventTypeFromNative(xev);
76 switch (event_type) {
77 case ET_KEY_PRESSED:
78 case ET_KEY_RELEASED: {
79 KeyEvent key_event(xev);
80 delegate_->DispatchEvent(&key_event);
81 break;
83 case ET_MOUSE_PRESSED:
84 case ET_MOUSE_MOVED:
85 case ET_MOUSE_DRAGGED:
86 case ET_MOUSE_RELEASED: {
87 MouseEvent mouse_event(xev);
88 delegate_->DispatchEvent(&mouse_event);
89 break;
91 case ET_MOUSEWHEEL: {
92 MouseWheelEvent wheel_event(xev);
93 delegate_->DispatchEvent(&wheel_event);
94 break;
96 case ET_SCROLL_FLING_START:
97 case ET_SCROLL_FLING_CANCEL:
98 case ET_SCROLL: {
99 ScrollEvent scroll_event(xev);
100 delegate_->DispatchEvent(&scroll_event);
101 break;
103 case ET_TOUCH_MOVED:
104 case ET_TOUCH_PRESSED:
105 case ET_TOUCH_CANCELLED:
106 case ET_TOUCH_RELEASED: {
107 TouchEvent touch_event(xev);
108 delegate_->DispatchEvent(&touch_event);
109 break;
111 default:
112 break;
116 void X11Window::Show() {
117 if (window_mapped_)
118 return;
120 CHECK(PlatformEventSource::GetInstance());
121 PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this);
123 XSetWindowAttributes swa;
124 memset(&swa, 0, sizeof(swa));
125 swa.background_pixmap = None;
126 swa.override_redirect = False;
127 xwindow_ = XCreateWindow(xdisplay_,
128 xroot_window_,
129 requested_bounds_.x(),
130 requested_bounds_.y(),
131 requested_bounds_.width(),
132 requested_bounds_.height(),
133 0, // border width
134 CopyFromParent, // depth
135 InputOutput,
136 CopyFromParent, // visual
137 CWBackPixmap | CWOverrideRedirect,
138 &swa);
140 long event_mask = ButtonPressMask | ButtonReleaseMask | FocusChangeMask |
141 KeyPressMask | KeyReleaseMask | EnterWindowMask |
142 LeaveWindowMask | ExposureMask | VisibilityChangeMask |
143 StructureNotifyMask | PropertyChangeMask |
144 PointerMotionMask;
145 XSelectInput(xdisplay_, xwindow_, event_mask);
147 unsigned char mask[XIMaskLen(XI_LASTEVENT)];
148 memset(mask, 0, sizeof(mask));
150 XISetMask(mask, XI_TouchBegin);
151 XISetMask(mask, XI_TouchUpdate);
152 XISetMask(mask, XI_TouchEnd);
153 XISetMask(mask, XI_ButtonPress);
154 XISetMask(mask, XI_ButtonRelease);
155 XISetMask(mask, XI_Motion);
156 XISetMask(mask, XI_KeyPress);
157 XISetMask(mask, XI_KeyRelease);
159 XIEventMask evmask;
160 evmask.deviceid = XIAllDevices;
161 evmask.mask_len = sizeof(mask);
162 evmask.mask = mask;
163 XISelectEvents(xdisplay_, xwindow_, &evmask, 1);
164 XFlush(xdisplay_);
166 ::Atom protocols[2];
167 protocols[0] = atom_cache_.GetAtom("WM_DELETE_WINDOW");
168 protocols[1] = atom_cache_.GetAtom("_NET_WM_PING");
169 XSetWMProtocols(xdisplay_, xwindow_, protocols, 2);
171 // We need a WM_CLIENT_MACHINE and WM_LOCALE_NAME value so we integrate with
172 // the desktop environment.
173 XSetWMProperties(
174 xdisplay_, xwindow_, NULL, NULL, NULL, 0, NULL, NULL, NULL);
176 // Likewise, the X server needs to know this window's pid so it knows which
177 // program to kill if the window hangs.
178 // XChangeProperty() expects "pid" to be long.
179 static_assert(sizeof(long) >= sizeof(pid_t),
180 "pid_t should not be larger than long");
181 long pid = getpid();
182 XChangeProperty(xdisplay_,
183 xwindow_,
184 atom_cache_.GetAtom("_NET_WM_PID"),
185 XA_CARDINAL,
187 PropModeReplace,
188 reinterpret_cast<unsigned char*>(&pid),
190 // Before we map the window, set size hints. Otherwise, some window managers
191 // will ignore toplevel XMoveWindow commands.
192 XSizeHints size_hints;
193 size_hints.flags = PPosition | PWinGravity;
194 size_hints.x = requested_bounds_.x();
195 size_hints.y = requested_bounds_.y();
196 // Set StaticGravity so that the window position is not affected by the
197 // frame width when running with window manager.
198 size_hints.win_gravity = StaticGravity;
199 XSetWMNormalHints(xdisplay_, xwindow_, &size_hints);
201 delegate_->OnAcceleratedWidgetAvailable(xwindow_);
203 XMapWindow(xdisplay_, xwindow_);
205 // We now block until our window is mapped. Some X11 APIs will crash and
206 // burn if passed |xwindow_| before the window is mapped, and XMapWindow is
207 // asynchronous.
208 if (X11EventSource::GetInstance())
209 X11EventSource::GetInstance()->BlockUntilWindowMapped(xwindow_);
210 window_mapped_ = true;
213 void X11Window::Hide() {
214 if (!window_mapped_)
215 return;
216 XWithdrawWindow(xdisplay_, xwindow_, 0);
217 window_mapped_ = false;
220 void X11Window::Close() {
221 Destroy();
224 void X11Window::SetBounds(const gfx::Rect& bounds) {
225 requested_bounds_ = bounds;
226 if (!window_mapped_)
227 return;
228 XWindowChanges changes = {0};
229 unsigned value_mask = CWX | CWY | CWWidth | CWHeight;
230 changes.x = bounds.x();
231 changes.y = bounds.y();
232 changes.width = bounds.width();
233 changes.height = bounds.height();
234 XConfigureWindow(xdisplay_, xwindow_, value_mask, &changes);
237 gfx::Rect X11Window::GetBounds() {
238 return confirmed_bounds_;
241 void X11Window::SetCapture() {}
243 void X11Window::ReleaseCapture() {}
245 void X11Window::ToggleFullscreen() {}
247 void X11Window::Maximize() {}
249 void X11Window::Minimize() {}
251 void X11Window::Restore() {}
253 void X11Window::SetCursor(PlatformCursor cursor) {}
255 void X11Window::MoveCursorTo(const gfx::Point& location) {}
257 void X11Window::ConfineCursorToBounds(const gfx::Rect& bounds) {
260 bool X11Window::CanDispatchEvent(const PlatformEvent& event) {
261 return FindXEventTarget(event) == xwindow_;
264 uint32_t X11Window::DispatchEvent(const PlatformEvent& event) {
265 XEvent* xev = event;
266 switch (xev->type) {
267 case EnterNotify: {
268 // EnterNotify creates ET_MOUSE_MOVED. Mark as synthesized as this is
269 // not real mouse move event.
270 MouseEvent mouse_event(xev);
271 CHECK_EQ(ET_MOUSE_MOVED, mouse_event.type());
272 mouse_event.set_flags(mouse_event.flags() | EF_IS_SYNTHESIZED);
273 delegate_->DispatchEvent(&mouse_event);
274 break;
276 case LeaveNotify: {
277 MouseEvent mouse_event(xev);
278 delegate_->DispatchEvent(&mouse_event);
279 break;
282 case Expose: {
283 gfx::Rect damage_rect(xev->xexpose.x,
284 xev->xexpose.y,
285 xev->xexpose.width,
286 xev->xexpose.height);
287 delegate_->OnDamageRect(damage_rect);
288 break;
291 case KeyPress:
292 case KeyRelease: {
293 KeyEvent key_event(xev);
294 delegate_->DispatchEvent(&key_event);
295 break;
298 case ButtonPress:
299 case ButtonRelease: {
300 switch (EventTypeFromNative(xev)) {
301 case ET_MOUSEWHEEL: {
302 MouseWheelEvent mouseev(xev);
303 delegate_->DispatchEvent(&mouseev);
304 break;
306 case ET_MOUSE_PRESSED:
307 case ET_MOUSE_RELEASED: {
308 MouseEvent mouseev(xev);
309 delegate_->DispatchEvent(&mouseev);
310 break;
312 case ET_UNKNOWN:
313 // No event is created for X11-release events for mouse-wheel
314 // buttons.
315 break;
316 default:
317 NOTREACHED();
319 break;
322 case FocusOut:
323 if (xev->xfocus.mode != NotifyGrab)
324 delegate_->OnLostCapture();
325 break;
327 case ConfigureNotify: {
328 DCHECK_EQ(xwindow_, xev->xconfigure.event);
329 DCHECK_EQ(xwindow_, xev->xconfigure.window);
330 gfx::Rect bounds(xev->xconfigure.x,
331 xev->xconfigure.y,
332 xev->xconfigure.width,
333 xev->xconfigure.height);
334 if (confirmed_bounds_ != bounds) {
335 confirmed_bounds_ = bounds;
336 delegate_->OnBoundsChanged(confirmed_bounds_);
338 break;
341 case ClientMessage: {
342 Atom message = static_cast<Atom>(xev->xclient.data.l[0]);
343 if (message == atom_cache_.GetAtom("WM_DELETE_WINDOW")) {
344 delegate_->OnCloseRequest();
345 } else if (message == atom_cache_.GetAtom("_NET_WM_PING")) {
346 XEvent reply_event = *xev;
347 reply_event.xclient.window = xroot_window_;
349 XSendEvent(xdisplay_,
350 reply_event.xclient.window,
351 False,
352 SubstructureRedirectMask | SubstructureNotifyMask,
353 &reply_event);
354 XFlush(xdisplay_);
356 break;
359 case GenericEvent: {
360 ProcessXInput2Event(xev);
361 break;
364 return POST_DISPATCH_STOP_PROPAGATION;
367 } // namespace ui