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; | 21 bool override_redirect = false; |
24 | 22 |
25 namespace test { | 23 namespace test { |
26 | 24 |
27 void EnableTestNativeViewport() { | 25 void EnableTestNativeViewport() { |
28 // Without the override_redirect BlockUntilWindowMapped() may never finish | 26 // Without the override_redirect BlockUntilWindowMapped() may never finish |
29 // (we don't necessarily get the mapped notify). This often happens with | 27 // (we don't necessarily get the mapped notify). This often happens with |
30 // tests. | 28 // tests. |
31 // TODO: decide if we really want the override redirect here. | 29 // TODO: decide if we really want the override redirect here. |
32 override_redirect = true; | 30 override_redirect = true; |
33 } | 31 } |
34 | 32 |
35 } // namespace test | 33 } // namespace test |
36 | 34 |
37 class NativeViewportX11 : public NativeViewport, | 35 class NativeViewportX11 : public NativeViewport, |
38 public ui::PlatformEventDispatcher { | 36 public ui::PlatformWindowDelegate { |
39 public: | 37 public: |
40 NativeViewportX11(NativeViewportDelegate* delegate) | 38 explicit NativeViewportX11(NativeViewportDelegate* delegate) |
41 : delegate_(delegate) { | 39 : delegate_(delegate) { |
42 } | 40 } |
43 | 41 |
44 virtual ~NativeViewportX11() { | 42 virtual ~NativeViewportX11() { |
45 event_source_->RemovePlatformEventDispatcher(this); | 43 // Destroy the platform-window while |this| is still alive. |
46 | 44 platform_window_.reset(); |
47 XDestroyWindow(gfx::GetXDisplay(), window_); | |
48 } | 45 } |
49 | 46 |
50 private: | 47 private: |
51 // Overridden from NativeViewport: | 48 // Overridden from NativeViewport: |
52 virtual void Init(const gfx::Rect& bounds) OVERRIDE { | 49 virtual void Init(const gfx::Rect& bounds) OVERRIDE { |
53 XDisplay* display = gfx::GetXDisplay(); | 50 CHECK(!event_source_); |
54 | 51 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 | 52 |
75 event_source_ = ui::PlatformEventSource::CreateDefault(); | 53 event_source_ = ui::PlatformEventSource::CreateDefault(); |
76 event_source_->AddPlatformEventDispatcher(this); | |
77 | 54 |
78 long event_mask = ButtonPressMask | ButtonReleaseMask | FocusChangeMask | | 55 platform_window_.reset(new ui::X11Window(this)); |
79 KeyPressMask | KeyReleaseMask | EnterWindowMask | LeaveWindowMask | | 56 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 } | 57 } |
93 | 58 |
94 virtual void Show() OVERRIDE { | 59 virtual void Show() OVERRIDE { |
95 XDisplay* display = gfx::GetXDisplay(); | 60 platform_window_->Show(); |
96 XMapWindow(display, window_); | |
97 static_cast<ui::X11EventSource*>( | |
98 event_source_.get())->BlockUntilWindowMapped(window_); | |
99 XFlush(display); | |
100 } | 61 } |
101 | 62 |
102 virtual void Hide() OVERRIDE { | 63 virtual void Hide() OVERRIDE { |
103 XWithdrawWindow(gfx::GetXDisplay(), window_, 0); | 64 platform_window_->Hide(); |
104 } | 65 } |
105 | 66 |
106 virtual void Close() OVERRIDE { | 67 virtual void Close() OVERRIDE { |
107 // TODO(beng): perform this in response to XWindow destruction. | 68 platform_window_->Close(); |
108 delegate_->OnDestroyed(); | |
109 } | 69 } |
110 | 70 |
111 virtual gfx::Size GetSize() OVERRIDE { | 71 virtual gfx::Size GetSize() OVERRIDE { |
112 return bounds_.size(); | 72 return bounds_.size(); |
113 } | 73 } |
114 | 74 |
115 virtual void SetBounds(const gfx::Rect& bounds) OVERRIDE { | 75 virtual void SetBounds(const gfx::Rect& bounds) OVERRIDE { |
116 NOTIMPLEMENTED(); | 76 platform_window_->SetBounds(bounds); |
117 } | 77 } |
118 | 78 |
119 virtual void SetCapture() OVERRIDE { | 79 virtual void SetCapture() OVERRIDE { |
120 NOTIMPLEMENTED(); | 80 platform_window_->SetCapture(); |
121 } | 81 } |
122 | 82 |
123 virtual void ReleaseCapture() OVERRIDE { | 83 virtual void ReleaseCapture() OVERRIDE { |
124 NOTIMPLEMENTED(); | 84 platform_window_->ReleaseCapture(); |
125 } | 85 } |
126 | 86 |
127 // ui::PlatformEventDispatcher: | 87 // ui::PlatformWindowDelegate: |
128 virtual bool CanDispatchEvent(const ui::PlatformEvent& event) OVERRIDE { | 88 virtual void OnBoundsChanged(const gfx::Rect& new_bounds) OVERRIDE { |
129 // TODO(aa): This is going to have to be thought through more carefully. | 89 bounds_ = new_bounds; |
130 // Which events are appropriate to pass to clients? | 90 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 } | 91 } |
145 | 92 |
146 virtual uint32_t DispatchEvent(const ui::PlatformEvent& event) OVERRIDE { | 93 virtual void OnDamageRect(const gfx::Rect& damaged_region) OVERRIDE { |
147 if (event->type == ClientMessage) { | 94 } |
148 Atom protocol = static_cast<Atom>(event->xclient.data.l[0]); | 95 |
149 if (protocol == atom_wm_delete_window_) | 96 virtual void DispatchEvent(ui::Event* event) OVERRIDE { |
150 delegate_->OnDestroyed(); | 97 delegate_->OnEvent(event); |
151 } else if (event->type == KeyPress || event->type == KeyRelease) { | 98 } |
152 ui::KeyEvent key_event(event, false); | 99 |
153 delegate_->OnEvent(&key_event); | 100 virtual void OnCloseRequest() OVERRIDE { |
154 } else if (event->type == ButtonPress || event->type == ButtonRelease || | 101 platform_window_->Close(); |
155 event->type == MotionNotify) { | 102 } |
156 ui::EventType event_type = ui::EventTypeFromNative(event); | 103 |
157 if (event_type == ui::ET_MOUSEWHEEL) { | 104 virtual void OnClosed() OVERRIDE { |
158 ui::MouseWheelEvent mouse_event(event); | 105 delegate_->OnDestroyed(); |
159 delegate_->OnEvent(&mouse_event); | 106 } |
160 } else { | 107 |
161 ui::MouseEvent mouse_event(event); | 108 virtual void OnWindowStateChanged(ui::PlatformWindowState state) OVERRIDE { |
162 delegate_->OnEvent(&mouse_event); | 109 } |
163 } | 110 |
164 } else if (event->type == ConfigureNotify) { | 111 virtual void OnLostCapture() OVERRIDE { |
165 bounds_ = gfx::Rect(event->xconfigure.width, event->xconfigure.height); | 112 } |
166 delegate_->OnBoundsChanged(bounds_); | 113 |
167 } | 114 virtual void OnAcceleratedWidgetAvailable( |
168 return ui::POST_DISPATCH_NONE; | 115 gfx::AcceleratedWidget widget) OVERRIDE { |
| 116 delegate_->OnAcceleratedWidgetAvailable(widget); |
169 } | 117 } |
170 | 118 |
171 scoped_ptr<ui::PlatformEventSource> event_source_; | 119 scoped_ptr<ui::PlatformEventSource> event_source_; |
| 120 scoped_ptr<ui::PlatformWindow> platform_window_; |
172 NativeViewportDelegate* delegate_; | 121 NativeViewportDelegate* delegate_; |
173 gfx::Rect bounds_; | 122 gfx::Rect bounds_; |
174 XID window_; | |
175 Atom atom_wm_protocols_; | |
176 Atom atom_wm_delete_window_; | |
177 | 123 |
178 DISALLOW_COPY_AND_ASSIGN(NativeViewportX11); | 124 DISALLOW_COPY_AND_ASSIGN(NativeViewportX11); |
179 }; | 125 }; |
180 | 126 |
181 // static | 127 // static |
182 scoped_ptr<NativeViewport> NativeViewport::Create( | 128 scoped_ptr<NativeViewport> NativeViewport::Create( |
183 shell::Context* context, | 129 shell::Context* context, |
184 NativeViewportDelegate* delegate) { | 130 NativeViewportDelegate* delegate) { |
185 return scoped_ptr<NativeViewport>(new NativeViewportX11(delegate)).Pass(); | 131 return scoped_ptr<NativeViewport>(new NativeViewportX11(delegate)).Pass(); |
186 } | 132 } |
187 | 133 |
188 } // namespace services | 134 } // namespace services |
189 } // namespace mojo | 135 } // namespace mojo |
OLD | NEW |