OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "mojo/services/native_viewport/native_viewport.h" | 5 #include "mojo/services/native_viewport/native_viewport.h" |
6 | 6 |
7 #include <X11/Xlib.h> | |
8 #include <X11/Xutil.h> | |
9 | |
10 #include "base/command_line.h" | 7 #include "base/command_line.h" |
11 #include "base/message_loop/message_loop.h" | 8 #include "base/message_loop/message_loop.h" |
12 #include "ui/events/event.h" | 9 #include "ui/events/event.h" |
13 #include "ui/events/event_utils.h" | 10 #include "ui/events/event_utils.h" |
14 #include "ui/events/platform/platform_event_dispatcher.h" | 11 #include "ui/events/platform/platform_event_dispatcher.h" |
15 #include "ui/events/platform/platform_event_source.h" | 12 #include "ui/events/platform/platform_event_source.h" |
16 #include "ui/events/platform/x11/x11_event_source.h" | |
17 #include "ui/gfx/rect.h" | 13 #include "ui/gfx/rect.h" |
18 #include "ui/gfx/x/x11_types.h" | 14 #include "ui/platform_window/platform_window.h" |
| 15 #include "ui/platform_window/platform_window_delegate.h" |
| 16 #include "ui/platform_window/x11/x11_window.h" |
19 | 17 |
20 namespace mojo { | 18 namespace mojo { |
21 namespace services { | 19 namespace services { |
22 | 20 |
23 bool override_redirect = false; | |
24 | |
25 namespace test { | |
26 | |
27 void EnableTestNativeViewport() { | |
28 // Without the override_redirect BlockUntilWindowMapped() may never finish | |
29 // (we don't necessarily get the mapped notify). This often happens with | |
30 // tests. | |
31 // TODO: decide if we really want the override redirect here. | |
32 override_redirect = true; | |
33 } | |
34 | |
35 } // namespace test | |
36 | |
37 class NativeViewportX11 : public NativeViewport, | 21 class NativeViewportX11 : public NativeViewport, |
38 public ui::PlatformEventDispatcher { | 22 public ui::PlatformWindowDelegate { |
39 public: | 23 public: |
40 NativeViewportX11(NativeViewportDelegate* delegate) | 24 explicit NativeViewportX11(NativeViewportDelegate* delegate) |
41 : delegate_(delegate) { | 25 : delegate_(delegate) { |
42 } | 26 } |
43 | 27 |
44 virtual ~NativeViewportX11() { | 28 virtual ~NativeViewportX11() { |
45 event_source_->RemovePlatformEventDispatcher(this); | 29 // Destroy the platform-window while |this| is still alive. |
46 | 30 platform_window_.reset(); |
47 XDestroyWindow(gfx::GetXDisplay(), window_); | |
48 } | 31 } |
49 | 32 |
50 private: | 33 private: |
51 // Overridden from NativeViewport: | 34 // Overridden from NativeViewport: |
52 virtual void Init(const gfx::Rect& bounds) OVERRIDE { | 35 virtual void Init(const gfx::Rect& bounds) OVERRIDE { |
53 XDisplay* display = gfx::GetXDisplay(); | 36 CHECK(!event_source_); |
54 | 37 CHECK(!platform_window_); |
55 XSetWindowAttributes swa; | |
56 memset(&swa, 0, sizeof(swa)); | |
57 swa.override_redirect = override_redirect ? True : False; | |
58 | |
59 bounds_ = bounds; | |
60 window_ = XCreateWindow( | |
61 display, | |
62 DefaultRootWindow(display), | |
63 bounds_.x(), bounds_.y(), bounds_.width(), bounds_.height(), | |
64 0, // border width | |
65 CopyFromParent, // depth | |
66 InputOutput, | |
67 CopyFromParent, // visual | |
68 CWBackPixmap | CWOverrideRedirect, | |
69 &swa); | |
70 | |
71 atom_wm_protocols_ = XInternAtom(display, "WM_PROTOCOLS", 1); | |
72 atom_wm_delete_window_ = XInternAtom(display, "WM_DELETE_WINDOW", 1); | |
73 XSetWMProtocols(display, window_, &atom_wm_delete_window_, 1); | |
74 | 38 |
75 event_source_ = ui::PlatformEventSource::CreateDefault(); | 39 event_source_ = ui::PlatformEventSource::CreateDefault(); |
76 event_source_->AddPlatformEventDispatcher(this); | |
77 | 40 |
78 long event_mask = ButtonPressMask | ButtonReleaseMask | FocusChangeMask | | 41 platform_window_.reset(new ui::X11Window(this)); |
79 KeyPressMask | KeyReleaseMask | EnterWindowMask | LeaveWindowMask | | 42 platform_window_->SetBounds(bounds); |
80 ExposureMask | VisibilityChangeMask | StructureNotifyMask | | |
81 PropertyChangeMask | PointerMotionMask; | |
82 XSelectInput(display, window_, event_mask); | |
83 | |
84 // We need a WM_CLIENT_MACHINE and WM_LOCALE_NAME value so we integrate with | |
85 // the desktop environment. | |
86 XSetWMProperties(display, window_, NULL, NULL, NULL, 0, NULL, NULL, NULL); | |
87 | |
88 // TODO(aa): Setup xinput2 events. | |
89 // See desktop_aura/desktop_window_tree_host_x11.cc. | |
90 | |
91 delegate_->OnAcceleratedWidgetAvailable(window_); | |
92 } | 43 } |
93 | 44 |
94 virtual void Show() OVERRIDE { | 45 virtual void Show() OVERRIDE { |
95 XDisplay* display = gfx::GetXDisplay(); | 46 platform_window_->Show(); |
96 XMapWindow(display, window_); | |
97 static_cast<ui::X11EventSource*>( | |
98 event_source_.get())->BlockUntilWindowMapped(window_); | |
99 XFlush(display); | |
100 } | 47 } |
101 | 48 |
102 virtual void Hide() OVERRIDE { | 49 virtual void Hide() OVERRIDE { |
103 XWithdrawWindow(gfx::GetXDisplay(), window_, 0); | 50 platform_window_->Hide(); |
104 } | 51 } |
105 | 52 |
106 virtual void Close() OVERRIDE { | 53 virtual void Close() OVERRIDE { |
107 // TODO(beng): perform this in response to XWindow destruction. | 54 platform_window_->Close(); |
108 delegate_->OnDestroyed(); | |
109 } | 55 } |
110 | 56 |
111 virtual gfx::Size GetSize() OVERRIDE { | 57 virtual gfx::Size GetSize() OVERRIDE { |
112 return bounds_.size(); | 58 return bounds_.size(); |
113 } | 59 } |
114 | 60 |
115 virtual void SetBounds(const gfx::Rect& bounds) OVERRIDE { | 61 virtual void SetBounds(const gfx::Rect& bounds) OVERRIDE { |
116 NOTIMPLEMENTED(); | 62 platform_window_->SetBounds(bounds); |
117 } | 63 } |
118 | 64 |
119 virtual void SetCapture() OVERRIDE { | 65 virtual void SetCapture() OVERRIDE { |
120 NOTIMPLEMENTED(); | 66 platform_window_->SetCapture(); |
121 } | 67 } |
122 | 68 |
123 virtual void ReleaseCapture() OVERRIDE { | 69 virtual void ReleaseCapture() OVERRIDE { |
124 NOTIMPLEMENTED(); | 70 platform_window_->ReleaseCapture(); |
125 } | 71 } |
126 | 72 |
127 // ui::PlatformEventDispatcher: | 73 // ui::PlatformWindowDelegate: |
128 virtual bool CanDispatchEvent(const ui::PlatformEvent& event) OVERRIDE { | 74 virtual void OnBoundsChanged(const gfx::Rect& new_bounds) OVERRIDE { |
129 // TODO(aa): This is going to have to be thought through more carefully. | 75 bounds_ = new_bounds; |
130 // Which events are appropriate to pass to clients? | 76 delegate_->OnBoundsChanged(new_bounds); |
131 switch (event->type) { | |
132 case KeyPress: | |
133 case KeyRelease: | |
134 case ButtonPress: | |
135 case ButtonRelease: | |
136 case MotionNotify: | |
137 case ConfigureNotify: | |
138 return true; | |
139 case ClientMessage: | |
140 return event->xclient.message_type == atom_wm_protocols_; | |
141 default: | |
142 return false; | |
143 } | |
144 } | 77 } |
145 | 78 |
146 virtual uint32_t DispatchEvent(const ui::PlatformEvent& event) OVERRIDE { | 79 virtual void OnDamageRect(const gfx::Rect& damaged_region) OVERRIDE { |
147 if (event->type == ClientMessage) { | 80 } |
148 Atom protocol = static_cast<Atom>(event->xclient.data.l[0]); | 81 |
149 if (protocol == atom_wm_delete_window_) | 82 virtual void DispatchEvent(ui::Event* event) OVERRIDE { |
150 delegate_->OnDestroyed(); | 83 delegate_->OnEvent(event); |
151 } else if (event->type == KeyPress || event->type == KeyRelease) { | 84 } |
152 ui::KeyEvent key_event(event, false); | 85 |
153 delegate_->OnEvent(&key_event); | 86 virtual void OnCloseRequest() OVERRIDE { |
154 } else if (event->type == ButtonPress || event->type == ButtonRelease || | 87 platform_window_->Close(); |
155 event->type == MotionNotify) { | 88 } |
156 ui::EventType event_type = ui::EventTypeFromNative(event); | 89 |
157 if (event_type == ui::ET_MOUSEWHEEL) { | 90 virtual void OnClosed() OVERRIDE { |
158 ui::MouseWheelEvent mouse_event(event); | 91 delegate_->OnDestroyed(); |
159 delegate_->OnEvent(&mouse_event); | 92 } |
160 } else { | 93 |
161 ui::MouseEvent mouse_event(event); | 94 virtual void OnWindowStateChanged(ui::PlatformWindowState state) OVERRIDE { |
162 delegate_->OnEvent(&mouse_event); | 95 } |
163 } | 96 |
164 } else if (event->type == ConfigureNotify) { | 97 virtual void OnLostCapture() OVERRIDE { |
165 bounds_ = gfx::Rect(event->xconfigure.width, event->xconfigure.height); | 98 } |
166 delegate_->OnBoundsChanged(bounds_); | 99 |
167 } | 100 virtual void OnAcceleratedWidgetAvailable( |
168 return ui::POST_DISPATCH_NONE; | 101 gfx::AcceleratedWidget widget) OVERRIDE { |
| 102 delegate_->OnAcceleratedWidgetAvailable(widget); |
169 } | 103 } |
170 | 104 |
171 scoped_ptr<ui::PlatformEventSource> event_source_; | 105 scoped_ptr<ui::PlatformEventSource> event_source_; |
| 106 scoped_ptr<ui::PlatformWindow> platform_window_; |
172 NativeViewportDelegate* delegate_; | 107 NativeViewportDelegate* delegate_; |
173 gfx::Rect bounds_; | 108 gfx::Rect bounds_; |
174 XID window_; | |
175 Atom atom_wm_protocols_; | |
176 Atom atom_wm_delete_window_; | |
177 | 109 |
178 DISALLOW_COPY_AND_ASSIGN(NativeViewportX11); | 110 DISALLOW_COPY_AND_ASSIGN(NativeViewportX11); |
179 }; | 111 }; |
180 | 112 |
181 // static | 113 // static |
182 scoped_ptr<NativeViewport> NativeViewport::Create( | 114 scoped_ptr<NativeViewport> NativeViewport::Create( |
183 shell::Context* context, | 115 shell::Context* context, |
184 NativeViewportDelegate* delegate) { | 116 NativeViewportDelegate* delegate) { |
185 return scoped_ptr<NativeViewport>(new NativeViewportX11(delegate)).Pass(); | 117 return scoped_ptr<NativeViewport>(new NativeViewportX11(delegate)).Pass(); |
186 } | 118 } |
187 | 119 |
188 } // namespace services | 120 } // namespace services |
189 } // namespace mojo | 121 } // namespace mojo |
OLD | NEW |