Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "ui/aura/desktop_host.h" | 5 #include "ui/aura/desktop_host.h" |
| 6 | 6 |
| 7 #include <X11/cursorfont.h> | 7 #include <X11/cursorfont.h> |
| 8 #include <X11/Xlib.h> | 8 #include <X11/Xlib.h> |
| 9 | 9 |
| 10 // Get rid of a macro from Xlib.h that conflicts with Aura's RootWindow class. | 10 // Get rid of a macro from Xlib.h that conflicts with Aura's RootWindow class. |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 191 | 191 |
| 192 // DesktopHost Overrides. | 192 // DesktopHost Overrides. |
| 193 virtual void SetDesktop(Desktop* desktop) OVERRIDE; | 193 virtual void SetDesktop(Desktop* desktop) OVERRIDE; |
| 194 virtual gfx::AcceleratedWidget GetAcceleratedWidget() OVERRIDE; | 194 virtual gfx::AcceleratedWidget GetAcceleratedWidget() OVERRIDE; |
| 195 virtual void Show() OVERRIDE; | 195 virtual void Show() OVERRIDE; |
| 196 virtual gfx::Size GetSize() const OVERRIDE; | 196 virtual gfx::Size GetSize() const OVERRIDE; |
| 197 virtual void SetSize(const gfx::Size& size) OVERRIDE; | 197 virtual void SetSize(const gfx::Size& size) OVERRIDE; |
| 198 virtual void SetCursor(gfx::NativeCursor cursor_type) OVERRIDE; | 198 virtual void SetCursor(gfx::NativeCursor cursor_type) OVERRIDE; |
| 199 virtual gfx::Point QueryMouseLocation() OVERRIDE; | 199 virtual gfx::Point QueryMouseLocation() OVERRIDE; |
| 200 | 200 |
| 201 // Returns true if there's an X window manager present. | 201 // Handle notification from the X server that |xwindow_| has been resized. |
| 202 void HandleConfigureNotify(const gfx::Size& new_size); | |
| 203 | |
| 204 // Returns true if there's an X window manager present... in most cases. Some | |
| 205 // window managers (notably, ion3) don't implement enough of ICCCM for us to | |
| 206 // detect that they're there. | |
| 202 bool IsWindowManagerPresent(); | 207 bool IsWindowManagerPresent(); |
| 203 | 208 |
| 204 Desktop* desktop_; | 209 Desktop* desktop_; |
| 205 | 210 |
| 206 // The display and the native X window hosting the desktop. | 211 // The display and the native X window hosting the desktop. |
| 207 Display* xdisplay_; | 212 Display* xdisplay_; |
| 208 ::Window xwindow_; | 213 ::Window xwindow_; |
| 209 | 214 |
| 210 // Current Aura cursor. | 215 // Current Aura cursor. |
| 211 gfx::NativeCursor current_cursor_; | 216 gfx::NativeCursor current_cursor_; |
| 212 | 217 |
| 213 // The size of |xwindow_|. | 218 // The size of |xwindow_|. |
| 214 gfx::Rect bounds_; | 219 gfx::Size size_; |
|
Daniel Erat
2011/10/21 23:00:37
using a Rect here didn't make sense; we never need
sadrul
2011/10/22 18:53:04
Nice
| |
| 215 | 220 |
| 216 DISALLOW_COPY_AND_ASSIGN(DesktopHostLinux); | 221 DISALLOW_COPY_AND_ASSIGN(DesktopHostLinux); |
| 217 }; | 222 }; |
| 218 | 223 |
| 219 DesktopHostLinux::DesktopHostLinux(const gfx::Rect& bounds) | 224 DesktopHostLinux::DesktopHostLinux(const gfx::Rect& bounds) |
| 220 : desktop_(NULL), | 225 : desktop_(NULL), |
| 221 xdisplay_(NULL), | 226 xdisplay_(NULL), |
| 222 xwindow_(0), | 227 xwindow_(0), |
| 223 current_cursor_(aura::kCursorNull), | 228 current_cursor_(aura::kCursorNull), |
| 224 bounds_(bounds) { | 229 size_(bounds.size()) { |
| 225 // This assumes that the message-pump creates and owns the display. | 230 // This assumes that the message-pump creates and owns the display. |
| 226 xdisplay_ = base::MessagePumpX::GetDefaultXDisplay(); | 231 xdisplay_ = base::MessagePumpX::GetDefaultXDisplay(); |
| 227 | 232 |
| 228 // Ingore the requested bounds and just cover the whole screen if there's no | 233 // Ingore the requested bounds and just cover the whole screen if there's no |
| 229 // X window manager present. | 234 // X window manager present. |
| 230 if (!IsWindowManagerPresent()) | 235 gfx::Rect actual_bounds = bounds; |
| 231 bounds_.SetRect( | 236 if (!IsWindowManagerPresent()) { |
| 237 actual_bounds.SetRect( | |
| 232 0, 0, DisplayWidth(xdisplay_, 0), DisplayHeight(xdisplay_, 0)); | 238 0, 0, DisplayWidth(xdisplay_, 0), DisplayHeight(xdisplay_, 0)); |
|
sadrul
2011/10/22 18:53:04
I was thinking about this change ... perhaps we ar
Daniel Erat
2011/10/23 04:02:55
Yeah, I wasn't entirely convinced about this part.
sadrul
2011/10/23 20:45:02
I was thinking perhaps we can always to this for c
| |
| 239 size_ = actual_bounds.size(); | |
| 240 } | |
| 233 | 241 |
| 234 xwindow_ = XCreateSimpleWindow(xdisplay_, DefaultRootWindow(xdisplay_), | 242 xwindow_ = XCreateSimpleWindow(xdisplay_, DefaultRootWindow(xdisplay_), |
| 235 bounds_.x(), bounds_.y(), | 243 actual_bounds.x(), actual_bounds.y(), |
| 236 bounds_.width(), bounds_.height(), | 244 actual_bounds.width(), actual_bounds.height(), |
| 237 0, 0, 0); | 245 0, 0, 0); |
| 238 | 246 |
| 239 long event_mask = ButtonPressMask | ButtonReleaseMask | | 247 long event_mask = ButtonPressMask | ButtonReleaseMask | |
| 240 KeyPressMask | KeyReleaseMask | | 248 KeyPressMask | KeyReleaseMask | |
| 241 ExposureMask | VisibilityChangeMask | | 249 ExposureMask | VisibilityChangeMask | |
| 242 StructureNotifyMask | PropertyChangeMask | | 250 StructureNotifyMask | PropertyChangeMask | |
| 243 PointerMotionMask; | 251 PointerMotionMask; |
| 244 XSelectInput(xdisplay_, xwindow_, event_mask); | 252 XSelectInput(xdisplay_, xwindow_, event_mask); |
| 245 XFlush(xdisplay_); | 253 XFlush(xdisplay_); |
| 246 | 254 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 301 break; | 309 break; |
| 302 } | 310 } |
| 303 case ConfigureNotify: { | 311 case ConfigureNotify: { |
| 304 DCHECK_EQ(xdisplay_, xev->xconfigure.display); | 312 DCHECK_EQ(xdisplay_, xev->xconfigure.display); |
| 305 DCHECK_EQ(xwindow_, xev->xconfigure.window); | 313 DCHECK_EQ(xwindow_, xev->xconfigure.window); |
| 306 DCHECK_EQ(xwindow_, xev->xconfigure.event); | 314 DCHECK_EQ(xwindow_, xev->xconfigure.event); |
| 307 | 315 |
| 308 // It's possible that the X window may be resized by some other means than | 316 // It's possible that the X window may be resized by some other means than |
| 309 // from within aura (e.g. the X window manager can change the size). Make | 317 // from within aura (e.g. the X window manager can change the size). Make |
| 310 // sure the desktop size is maintained properly. | 318 // sure the desktop size is maintained properly. |
| 311 gfx::Size size(xev->xconfigure.width, xev->xconfigure.height); | 319 HandleConfigureNotify( |
| 312 if (bounds_.size() != size) | 320 gfx::Size(xev->xconfigure.width, xev->xconfigure.height)); |
| 313 bounds_.set_size(size); | |
| 314 desktop_->OnHostResized(size); | |
| 315 handled = true; | 321 handled = true; |
| 316 break; | 322 break; |
| 317 } | 323 } |
| 318 | 324 |
| 319 case GenericEvent: { | 325 case GenericEvent: { |
| 320 ui::TouchFactory* factory = ui::TouchFactory::GetInstance(); | 326 ui::TouchFactory* factory = ui::TouchFactory::GetInstance(); |
| 321 if (!factory->ShouldProcessXI2Event(xev)) | 327 if (!factory->ShouldProcessXI2Event(xev)) |
| 322 break; | 328 break; |
| 323 | 329 |
| 324 // If this is a motion event we want to coalesce all pending motion | 330 // If this is a motion event we want to coalesce all pending motion |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 370 desktop_ = desktop; | 376 desktop_ = desktop; |
| 371 } | 377 } |
| 372 | 378 |
| 373 gfx::AcceleratedWidget DesktopHostLinux::GetAcceleratedWidget() { | 379 gfx::AcceleratedWidget DesktopHostLinux::GetAcceleratedWidget() { |
| 374 return xwindow_; | 380 return xwindow_; |
| 375 } | 381 } |
| 376 | 382 |
| 377 void DesktopHostLinux::Show() { | 383 void DesktopHostLinux::Show() { |
| 378 XMapWindow(xdisplay_, xwindow_); | 384 XMapWindow(xdisplay_, xwindow_); |
| 379 | 385 |
| 386 // Wait for notification that the window is mapped, which happens | |
| 387 // asynchronously if there's a window manager running. | |
| 388 gfx::Size new_size = size_; | |
| 389 while (true) { | |
| 390 XEvent event; | |
| 391 XWindowEvent(xdisplay_, xwindow_, StructureNotifyMask, &event); | |
| 392 if (event.type == ConfigureNotify) | |
| 393 new_size.SetSize(event.xconfigure.width, event.xconfigure.height); | |
| 394 else if (event.type == MapNotify) | |
| 395 break; | |
| 396 } | |
| 397 | |
| 380 // If there's no window manager running, we need to assign the X input focus | 398 // If there's no window manager running, we need to assign the X input focus |
| 381 // to our host window. (If there's no window manager running, it should also | 399 // to our host window. |
| 382 // be safe to assume that the host window will have been mapped by the time | 400 if (!IsWindowManagerPresent()) { |
| 383 // that our SetInputFocus request is received.) | |
| 384 if (!IsWindowManagerPresent()) | |
| 385 XSetInputFocus(xdisplay_, xwindow_, RevertToNone, CurrentTime); | 401 XSetInputFocus(xdisplay_, xwindow_, RevertToNone, CurrentTime); |
|
sadrul
2011/10/22 18:53:04
How about we just XMapWindow+XFlush here and retur
Daniel Erat
2011/10/23 04:02:55
Thanks, I like this more as well. Sounds fine, as
| |
| 402 XFlush(xdisplay_); | |
| 403 } | |
| 386 | 404 |
| 387 XFlush(xdisplay_); | 405 // If we removed any ConfigureNotify events from the queue, make sure that we |
| 406 // apply size changes mentioned in them. | |
| 407 if (new_size != size_) | |
| 408 HandleConfigureNotify(new_size); | |
| 388 } | 409 } |
| 389 | 410 |
| 390 gfx::Size DesktopHostLinux::GetSize() const { | 411 gfx::Size DesktopHostLinux::GetSize() const { |
| 391 return bounds_.size(); | 412 return size_; |
| 392 } | 413 } |
| 393 | 414 |
| 394 void DesktopHostLinux::SetSize(const gfx::Size& size) { | 415 void DesktopHostLinux::SetSize(const gfx::Size& size) { |
| 395 if (bounds_.size() == size) | 416 if (size_ != size) |
| 396 return; | 417 XResizeWindow(xdisplay_, xwindow_, size.width(), size.height()); |
| 397 bounds_.set_size(size); | |
| 398 XResizeWindow(xdisplay_, xwindow_, size.width(), size.height()); | |
| 399 } | 418 } |
| 400 | 419 |
| 401 void DesktopHostLinux::SetCursor(gfx::NativeCursor cursor) { | 420 void DesktopHostLinux::SetCursor(gfx::NativeCursor cursor) { |
| 402 if (current_cursor_ == cursor) | 421 if (current_cursor_ == cursor) |
| 403 return; | 422 return; |
| 404 current_cursor_ = cursor; | 423 current_cursor_ = cursor; |
| 405 // Custom web cursors are handled directly. | 424 // Custom web cursors are handled directly. |
| 406 if (cursor == kCursorCustom) | 425 if (cursor == kCursorCustom) |
| 407 return; | 426 return; |
| 408 int cursor_shape = CursorShapeFromNative(cursor); | 427 int cursor_shape = CursorShapeFromNative(cursor); |
| 409 ::Cursor xcursor = ui::GetXCursor(cursor_shape); | 428 ::Cursor xcursor = ui::GetXCursor(cursor_shape); |
| 410 XDefineCursor(xdisplay_, xwindow_, xcursor); | 429 XDefineCursor(xdisplay_, xwindow_, xcursor); |
| 411 } | 430 } |
| 412 | 431 |
| 413 gfx::Point DesktopHostLinux::QueryMouseLocation() { | 432 gfx::Point DesktopHostLinux::QueryMouseLocation() { |
| 414 ::Window root_return, child_return; | 433 ::Window root_return, child_return; |
| 415 int root_x_return, root_y_return, win_x_return, win_y_return; | 434 int root_x_return, root_y_return, win_x_return, win_y_return; |
| 416 unsigned int mask_return; | 435 unsigned int mask_return; |
| 417 XQueryPointer(xdisplay_, | 436 XQueryPointer(xdisplay_, |
| 418 xwindow_, | 437 xwindow_, |
| 419 &root_return, | 438 &root_return, |
| 420 &child_return, | 439 &child_return, |
| 421 &root_x_return, &root_y_return, | 440 &root_x_return, &root_y_return, |
| 422 &win_x_return, &win_y_return, | 441 &win_x_return, &win_y_return, |
| 423 &mask_return); | 442 &mask_return); |
| 424 return gfx::Point(max(0, min(bounds_.width(), win_x_return)), | 443 return gfx::Point(max(0, min(size_.width(), win_x_return)), |
| 425 max(0, min(bounds_.height(), win_y_return))); | 444 max(0, min(size_.height(), win_y_return))); |
| 445 } | |
| 446 | |
| 447 void DesktopHostLinux::HandleConfigureNotify(const gfx::Size& size) { | |
| 448 if (size_ != size) | |
| 449 size_ = size; | |
| 450 desktop_->OnHostResized(size); | |
| 426 } | 451 } |
| 427 | 452 |
| 428 bool DesktopHostLinux::IsWindowManagerPresent() { | 453 bool DesktopHostLinux::IsWindowManagerPresent() { |
| 429 // Per ICCCM 2.8, "Manager Selections", window managers should take ownership | 454 // Per ICCCM 2.8, "Manager Selections", window managers should take ownership |
| 430 // of WM_Sn selections (where n is a screen number). | 455 // of WM_Sn selections (where n is a screen number). |
| 431 ::Atom wm_s0_atom = XInternAtom(xdisplay_, "WM_S0", False); | 456 ::Atom wm_s0_atom = XInternAtom(xdisplay_, "WM_S0", False); |
| 432 return XGetSelectionOwner(xdisplay_, wm_s0_atom) != None; | 457 return XGetSelectionOwner(xdisplay_, wm_s0_atom) != None; |
| 433 } | 458 } |
| 434 | 459 |
| 435 } // namespace | 460 } // namespace |
| 436 | 461 |
| 437 // static | 462 // static |
| 438 DesktopHost* DesktopHost::Create(const gfx::Rect& bounds) { | 463 DesktopHost* DesktopHost::Create(const gfx::Rect& bounds) { |
| 439 return new DesktopHostLinux(bounds); | 464 return new DesktopHostLinux(bounds); |
| 440 } | 465 } |
| 441 | 466 |
| 442 } // namespace aura | 467 } // namespace aura |
| OLD | NEW |