OLD | NEW |
(Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "ui/wayland/wayland_window.h" |
| 6 |
| 7 #include <wayland-egl.h> |
| 8 |
| 9 #include "base/logging.h" |
| 10 #include "base/wayland/wayland_event.h" |
| 11 #include "ui/wayland/wayland_display.h" |
| 12 #include "ui/wayland/wayland_delegate.h" |
| 13 #include "ui/wayland/wayland_task.h" |
| 14 #include "ui/wayland/wayland_input_device.h" |
| 15 #include "ui/gl/gl_surface.h" |
| 16 |
| 17 #include <GL/gl.h> |
| 18 #include <EGL/egl.h> |
| 19 #include <EGL/eglext.h> |
| 20 |
| 21 #include <algorithm> |
| 22 |
| 23 using base::wayland::WaylandEvent; |
| 24 |
| 25 namespace ui { |
| 26 |
| 27 WaylandWindow::WaylandWindow(WaylandDelegate* delegate, WaylandDisplay* display) |
| 28 : delegate_(delegate), |
| 29 display_(display), |
| 30 parent_window_(NULL), |
| 31 user_data_(NULL), |
| 32 relative_position_(), |
| 33 surface_(display->CreateSurface()), |
| 34 shell_surface_(NULL), |
| 35 fullscreen_(false), |
| 36 window_(NULL), |
| 37 resize_scheduled_(false), |
| 38 redraw_scheduled_(false), |
| 39 transparent_(false), |
| 40 buffer_type_(WINDOW_BUFFER_TYPE_SHM), |
| 41 type_(TYPE_TOPLEVEL), |
| 42 resize_edges_(0), |
| 43 allocation_(gfx::Rect(0, 0, 0, 0)), |
| 44 server_allocation_(gfx::Rect(0, 0, 0, 0)), |
| 45 saved_allocation_(gfx::Rect(0, 0, 0, 0)), |
| 46 pending_allocation_(gfx::Rect(0, 0, 0, 0)) |
| 47 { |
| 48 if(display_->shell()) |
| 49 { |
| 50 shell_surface_ = wl_shell_get_shell_surface(display_->shell(), surface_); |
| 51 } |
| 52 |
| 53 wl_surface_set_user_data(surface_, this); |
| 54 |
| 55 if(shell_surface_) |
| 56 { |
| 57 wl_shell_surface_set_user_data(shell_surface_, this); |
| 58 |
| 59 static const wl_shell_surface_listener shell_surface_listener = { |
| 60 WaylandWindow::HandlePing, |
| 61 WaylandWindow::HandleConfigure, |
| 62 WaylandWindow::HandlePopupDone |
| 63 }; |
| 64 |
| 65 wl_shell_surface_add_listener(shell_surface_, |
| 66 &shell_surface_listener, this); |
| 67 } |
| 68 |
| 69 allocation_.SetRect(0, 0, 0, 0); |
| 70 saved_allocation_ = allocation_; |
| 71 transparent_ = 1; |
| 72 |
| 73 // TODO: make buffer type choosable for testing and etc |
| 74 buffer_type_ = WINDOW_BUFFER_TYPE_EGL_WINDOW; |
| 75 |
| 76 // wl_shell_surface_set_toplevel(shell_surface_); |
| 77 display->AddWindow(this); |
| 78 } |
| 79 |
| 80 void WaylandWindow::SetType() |
| 81 { |
| 82 if (!shell_surface_) |
| 83 return; |
| 84 |
| 85 switch (type_) { |
| 86 case TYPE_FULLSCREEN: |
| 87 wl_shell_surface_set_fullscreen(shell_surface_, |
| 88 WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT, 0, NULL); |
| 89 break; |
| 90 case TYPE_TOPLEVEL: |
| 91 wl_shell_surface_set_toplevel(shell_surface_); |
| 92 break; |
| 93 case TYPE_TRANSIENT: |
| 94 wl_shell_surface_set_transient(shell_surface_, |
| 95 parent_window_->surface_, |
| 96 relative_position_.x(), relative_position_.y(), 0); |
| 97 break; |
| 98 case TYPE_MENU: |
| 99 break; |
| 100 case TYPE_CUSTOM: |
| 101 break; |
| 102 } |
| 103 } |
| 104 |
| 105 void WaylandWindow::GetResizeDelta(int &x, int &y) |
| 106 { |
| 107 if (resize_edges_ & WINDOW_RESIZING_LEFT) |
| 108 x = server_allocation_.width() - allocation_.width(); |
| 109 else |
| 110 x = 0; |
| 111 |
| 112 if (resize_edges_ & WINDOW_RESIZING_TOP) |
| 113 y = server_allocation_.height() - allocation_.height(); |
| 114 else |
| 115 y = 0; |
| 116 |
| 117 resize_edges_ = 0; |
| 118 } |
| 119 |
| 120 void WaylandWindow::AddChild(WaylandWindow* child) |
| 121 { |
| 122 DCHECK(std::find(children_.begin(), children_.end(), child) == |
| 123 children_.end()); |
| 124 if (child->GetParentWindow()) |
| 125 child->GetParentWindow()->RemoveChild(child); |
| 126 child->parent_window_ = this; |
| 127 children_.push_back(child); |
| 128 } |
| 129 |
| 130 void WaylandWindow::RemoveChild(WaylandWindow* child) |
| 131 { |
| 132 Windows::iterator i = std::find(children_.begin(), children_.end(), child); |
| 133 DCHECK(i != children_.end()); |
| 134 child->parent_window_ = NULL; |
| 135 children_.erase(i); |
| 136 } |
| 137 |
| 138 void WaylandWindow::SetParentWindow(WaylandWindow* parent_window) |
| 139 { |
| 140 if (fullscreen_) { |
| 141 type_ = TYPE_FULLSCREEN; |
| 142 } else if (!parent_window) { |
| 143 type_ = TYPE_TOPLEVEL; |
| 144 } else { |
| 145 type_ = TYPE_TRANSIENT; |
| 146 } |
| 147 |
| 148 if(parent_window) |
| 149 parent_window->AddChild(this); |
| 150 } |
| 151 |
| 152 gfx::Rect WaylandWindow::GetBounds() const |
| 153 { |
| 154 gfx::Rect rect = resize_scheduled_ ? pending_allocation_ : allocation_; |
| 155 |
| 156 if(type_ == TYPE_TRANSIENT && parent_window_) |
| 157 rect.set_origin(relative_position_); |
| 158 |
| 159 return rect; |
| 160 } |
| 161 |
| 162 void WaylandWindow::SetBounds(const gfx::Rect& new_bounds) |
| 163 { |
| 164 if(type_ == TYPE_TRANSIENT && parent_window_ && |
| 165 new_bounds.origin() != relative_position_) |
| 166 { |
| 167 relative_position_ = new_bounds.origin(); |
| 168 } |
| 169 |
| 170 ScheduleResize(new_bounds.width(), new_bounds.height()); |
| 171 } |
| 172 |
| 173 void WaylandWindow::Show() |
| 174 { |
| 175 NOTIMPLEMENTED(); |
| 176 } |
| 177 |
| 178 void WaylandWindow::Hide() |
| 179 { |
| 180 NOTIMPLEMENTED(); |
| 181 } |
| 182 |
| 183 WaylandWindow::~WaylandWindow() { |
| 184 if(window_) |
| 185 wl_egl_window_destroy(window_); |
| 186 |
| 187 if (surface_) |
| 188 { |
| 189 wl_surface_destroy(surface_); |
| 190 surface_ = NULL; |
| 191 } |
| 192 |
| 193 display_->RemoveWindow(this); |
| 194 } |
| 195 |
| 196 bool WaylandWindow::IsVisible() const { |
| 197 return surface_ != NULL; |
| 198 } |
| 199 |
| 200 void WaylandWindow::Flush() |
| 201 { |
| 202 // TODO: gotta find a better way to not set the type every time it flushes |
| 203 if (display_->shell()) |
| 204 SetType(); |
| 205 } |
| 206 |
| 207 void WaylandWindow::ScheduleResize(int32_t width, int32_t height) |
| 208 { |
| 209 if(!window_) |
| 210 window_ = wl_egl_window_create(surface_, |
| 211 width, height); |
| 212 |
| 213 pending_allocation_ = gfx::Rect(0, 0, width, height); |
| 214 |
| 215 if(IsVisible() && !resize_scheduled_ && pending_allocation_ != allocation_) |
| 216 { |
| 217 WaylandResizeTask *task = new WaylandResizeTask(this); |
| 218 display_->AddTask(task); |
| 219 |
| 220 // delegate_->OnBoundsChanged(allocation_, pending_allocation_); |
| 221 resize_scheduled_ = true; |
| 222 } |
| 223 ScheduleRedraw(); |
| 224 } |
| 225 |
| 226 void WaylandWindow::ScheduleRedraw() |
| 227 { |
| 228 if(IsVisible() && !redraw_scheduled_) |
| 229 { |
| 230 WaylandRedrawTask *task = new WaylandRedrawTask(this); |
| 231 display_->AddTask(task); |
| 232 redraw_scheduled_ = true; |
| 233 } |
| 234 } |
| 235 |
| 236 void WaylandWindow::SchedulePaintInRect(const gfx::Rect& rect) |
| 237 { |
| 238 ScheduleRedraw(); |
| 239 } |
| 240 |
| 241 void WaylandWindow::HandleConfigure(void *data, struct wl_shell_surface *shell_s
urface, |
| 242 uint32_t edges, int32_t width, int32_t height) |
| 243 { |
| 244 WaylandWindow *window = static_cast<WaylandWindow*>(data); |
| 245 |
| 246 if (width <= 0 || height <= 0) |
| 247 return; |
| 248 |
| 249 window->resize_edges_ = edges; |
| 250 window->ScheduleResize(width, height); |
| 251 } |
| 252 |
| 253 void WaylandWindow::HandlePopupDone(void *data, struct wl_shell_surface *shell_s
urface) |
| 254 { |
| 255 } |
| 256 |
| 257 void WaylandWindow::HandlePing(void *data, struct wl_shell_surface *shell_surfac
e, uint32_t serial) |
| 258 { |
| 259 wl_shell_surface_pong(shell_surface, serial); |
| 260 } |
| 261 |
| 262 void WaylandWindow::OnResize() |
| 263 { |
| 264 resize_scheduled_ = false; |
| 265 if(pending_allocation_ != allocation_) |
| 266 { |
| 267 allocation_ = pending_allocation_; |
| 268 ScheduleRedraw(); |
| 269 } |
| 270 } |
| 271 |
| 272 void WaylandWindow::OnRedraw() |
| 273 { |
| 274 Flush(); |
| 275 redraw_scheduled_ = false; |
| 276 } |
| 277 |
| 278 } // namespace ui |
OLD | NEW |