| 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 |