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

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

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

Powered by Google App Engine
This is Rietveld 408576698