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

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

Issue 275263002: [wip] ozonex: X11 backend for ozone. Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: tot-merge Created 6 years, 6 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 | Annotate | Revision Log
« no previous file with comments | « ui/platform_window/x11/DEPS ('k') | ui/platform_window/x11/x11_window.gyp » ('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 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.
4
5 #include <X11/extensions/XInput2.h>
6 #include <X11/Xatom.h>
7 #include <X11/Xlib.h>
8 #include <X11/Xutil.h>
9
10 #include "ui/events/event.h"
11 #include "ui/events/event_utils.h"
12 #include "ui/events/platform/platform_event_dispatcher.h"
13 #include "ui/events/platform/platform_event_source.h"
14 #include "ui/events/platform/x11/x11_event_source.h"
15 #include "ui/gfx/geometry/rect.h"
16 #include "ui/gfx/x/x11_atom_cache.h"
17 #include "ui/gfx/x/x11_types.h"
18 #include "ui/platform_window/platform_window.h"
19 #include "ui/platform_window/platform_window_delegate.h"
20
21 namespace ui {
22
23 namespace {
24
25 const char* kAtomsToCache[] = {
26 "WM_DELETE_WINDOW",
27 "_NET_WM_PING",
28 "_NET_WM_PID",
29 NULL
30 };
31
32 XID FindXEventTarget(XEvent* xevent) {
33 XID target = xevent->xany.window;
34 if (xevent->type == GenericEvent)
35 target = static_cast<XIDeviceEvent*>(xevent->xcookie.data)->event;
36 return target;
37 }
38
39 class X11Window : public PlatformWindow,
40 public PlatformEventDispatcher {
41 public:
42 explicit X11Window(PlatformWindowDelegate* delegate)
43 : delegate_(delegate),
44 xdisplay_(gfx::GetXDisplay()),
45 xwindow_(None),
46 xroot_window_(DefaultRootWindow(xdisplay_)),
47 atom_cache_(xdisplay_, kAtomsToCache),
48 window_mapped_(false) {
49 CHECK(delegate_);
50 }
51
52 virtual ~X11Window() {
53 Destroy();
54 }
55
56 private:
57 void Destroy() {
58 if (xwindow_ == None)
59 return;
60
61 // Stop processing events.
62 PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this);
63 XDestroyWindow(xdisplay_, xwindow_);
64 xwindow_ = None;
65 }
66
67 // PlatformWindow:
68 virtual void Show() OVERRIDE {
69 if (window_mapped_)
70 return;
71
72 CHECK(PlatformEventSource::GetInstance());
73 PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this);
74
75 XSetWindowAttributes swa;
76 memset(&swa, 0, sizeof(swa));
77 swa.background_pixmap = None;
78 swa.override_redirect = False;
79 xwindow_ = XCreateWindow(xdisplay_,
80 xroot_window_,
81 requested_bounds_.x(),
82 requested_bounds_.y(),
83 requested_bounds_.width(),
84 requested_bounds_.height(),
85 0, // border width
86 CopyFromParent, // depth
87 InputOutput,
88 CopyFromParent, // visual
89 CWBackPixmap | CWOverrideRedirect,
90 &swa);
91
92 long event_mask = ButtonPressMask | ButtonReleaseMask | FocusChangeMask |
93 KeyPressMask | KeyReleaseMask | EnterWindowMask |
94 LeaveWindowMask | ExposureMask | VisibilityChangeMask |
95 StructureNotifyMask | PropertyChangeMask |
96 PointerMotionMask;
97 XSelectInput(xdisplay_, xwindow_, event_mask);
98
99 #if 0
100 unsigned char mask[XIMaskLen(XI_LASTEVENT)];
101 memset(mask, 0, sizeof(mask));
102
103 #if defined(USE_XI2_MT)
104 XISetMask(mask, XI_TouchBegin);
105 XISetMask(mask, XI_TouchUpdate);
106 XISetMask(mask, XI_TouchEnd);
107 #endif
108 XISetMask(mask, XI_ButtonPress);
109 XISetMask(mask, XI_ButtonRelease);
110 XISetMask(mask, XI_Motion);
111
112 XIEventMask evmask;
113 evmask.deviceid = XIAllDevices;
114 evmask.mask_len = sizeof(mask);
115 evmask.mask = mask;
116 XISelectEvents(xdisplay_, xwindow_, &evmask, 1);
117 #endif
118 XFlush(xdisplay_);
119
120 ::Atom protocols[2];
121 protocols[0] = atom_cache_.GetAtom("WM_DELETE_WINDOW");
122 protocols[1] = atom_cache_.GetAtom("_NET_WM_PING");
123 XSetWMProtocols(xdisplay_, xwindow_, protocols, 2);
124
125 // We need a WM_CLIENT_MACHINE and WM_LOCALE_NAME value so we integrate with
126 // the desktop environment.
127 XSetWMProperties(
128 xdisplay_, xwindow_, NULL, NULL, NULL, 0, NULL, NULL, NULL);
129
130 // Likewise, the X server needs to know this window's pid so it knows which
131 // program to kill if the window hangs.
132 // XChangeProperty() expects "pid" to be long.
133 COMPILE_ASSERT(sizeof(long) >= sizeof(pid_t), pid_t_bigger_than_long);
134 long pid = getpid();
135 XChangeProperty(xdisplay_,
136 xwindow_,
137 atom_cache_.GetAtom("_NET_WM_PID"),
138 XA_CARDINAL,
139 32,
140 PropModeReplace,
141 reinterpret_cast<unsigned char*>(&pid),
142 1);
143 // Before we map the window, set size hints. Otherwise, some window managers
144 // will ignore toplevel XMoveWindow commands.
145 XSizeHints size_hints;
146 size_hints.flags = PPosition | PWinGravity;
147 size_hints.x = requested_bounds_.x();
148 size_hints.y = requested_bounds_.y();
149 // Set StaticGravity so that the window position is not affected by the
150 // frame width when running with window manager.
151 size_hints.win_gravity = StaticGravity;
152 XSetWMNormalHints(xdisplay_, xwindow_, &size_hints);
153
154 XMapWindow(xdisplay_, xwindow_);
155
156 // We now block until our window is mapped. Some X11 APIs will crash and
157 // burn if passed |xwindow_| before the window is mapped, and XMapWindow is
158 // asynchronous.
159 if (X11EventSource::GetInstance())
160 X11EventSource::GetInstance()->BlockUntilWindowMapped(xwindow_);
161 window_mapped_ = true;
162 }
163
164 virtual void Hide() OVERRIDE {
165 if (!window_mapped_)
166 return;
167 XWithdrawWindow(xdisplay_, xwindow_, 0);
168 window_mapped_ = false;
169 }
170
171 virtual void Close() OVERRIDE {
172 Destroy();
173 }
174
175 virtual void SetBounds(const gfx::Rect& bounds) OVERRIDE {
176 requested_bounds_ = bounds;
177 if (!window_mapped_)
178 return;
179 XWindowChanges changes = {0};
180 unsigned value_mask = CWX | CWY | CWWidth | CWHeight;
181 changes.x = bounds.x();
182 changes.y = bounds.y();
183 changes.width = bounds.width();
184 changes.height = bounds.height();
185 XConfigureWindow(xdisplay_, xwindow_, value_mask, &changes);
186 }
187
188 virtual void SetCapture() OVERRIDE {}
189
190 virtual void ReleaseCapture() OVERRIDE {}
191
192 virtual void ToggleFullscreen() OVERRIDE {}
193
194 virtual void Maximize() OVERRIDE {}
195
196 virtual void Minimize() OVERRIDE {}
197
198 virtual void Restore() OVERRIDE {}
199
200 // PlatformEventDispatcher:
201 virtual bool CanDispatchEvent(const PlatformEvent& event) OVERRIDE {
202 return FindXEventTarget(event) == xwindow_;
203 }
204
205 virtual uint32_t DispatchEvent(const PlatformEvent& event) OVERRIDE {
206 XEvent* xev = event;
207 switch (xev->type) {
208 case EnterNotify: {
209 // EnterNotify creates ET_MOUSE_MOVED. Mark as synthesized as this is
210 // not real mouse move event.
211 MouseEvent mouse_event(xev);
212 CHECK_EQ(ET_MOUSE_MOVED, mouse_event.type());
213 mouse_event.set_flags(mouse_event.flags() | EF_IS_SYNTHESIZED);
214 delegate_->DispatchEvent(&mouse_event);
215 break;
216 }
217 case LeaveNotify: {
218 MouseEvent mouse_event(xev);
219 delegate_->DispatchEvent(&mouse_event);
220 break;
221 }
222
223 case Expose: {
224 gfx::Rect damage_rect(xev->xexpose.x,
225 xev->xexpose.y,
226 xev->xexpose.width,
227 xev->xexpose.height);
228 delegate_->OnDamageRect(damage_rect);
229 break;
230 }
231
232 case KeyPress:
233 case KeyRelease: {
234 ui::KeyEvent key_event(xev, false);
235 delegate_->DispatchEvent(&key_event);
236 break;
237 }
238
239 case ButtonPress:
240 case ButtonRelease: {
241 switch (ui::EventTypeFromNative(xev)) {
242 case ui::ET_MOUSEWHEEL: {
243 ui::MouseWheelEvent mouseev(xev);
244 delegate_->DispatchEvent(&mouseev);
245 break;
246 }
247 case ui::ET_MOUSE_PRESSED:
248 case ui::ET_MOUSE_RELEASED: {
249 ui::MouseEvent mouseev(xev);
250 delegate_->DispatchEvent(&mouseev);
251 break;
252 }
253 case ui::ET_UNKNOWN:
254 // No event is created for X11-release events for mouse-wheel
255 // buttons.
256 break;
257 default:
258 NOTREACHED();
259 }
260 break;
261 }
262
263 case MotionNotify: {
264 ui::MouseEvent mouseev(xev);
265 delegate_->DispatchEvent(&mouseev);
266 break;
267 }
268
269 case FocusOut:
270 if (xev->xfocus.mode != NotifyGrab)
271 delegate_->OnLostCapture();
272 break;
273
274 case ConfigureNotify: {
275 DCHECK_EQ(xwindow_, xev->xconfigure.event);
276 DCHECK_EQ(xwindow_, xev->xconfigure.window);
277 gfx::Rect bounds(xev->xconfigure.x,
278 xev->xconfigure.y,
279 xev->xconfigure.width,
280 xev->xconfigure.height);
281 delegate_->OnBoundsChanged(bounds);
282 break;
283 }
284 }
285 return POST_DISPATCH_STOP_PROPAGATION;
286 }
287
288 PlatformWindowDelegate* delegate_;
289
290 XDisplay* xdisplay_;
291 XID xwindow_;
292 XID xroot_window_;
293 X11AtomCache atom_cache_;
294
295 gfx::Rect requested_bounds_;
296 bool window_mapped_;
297
298 DISALLOW_COPY_AND_ASSIGN(X11Window);
299 };
300
301 } // namespace
302
303 scoped_ptr<PlatformWindow>
304 CreatePlatformWindow(PlatformWindowDelegate* delegate) {
305 return scoped_ptr<PlatformWindow>(new X11Window(delegate));
306 }
307
308 } // namespace ui
OLDNEW
« no previous file with comments | « ui/platform_window/x11/DEPS ('k') | ui/platform_window/x11/x11_window.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698