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