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 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 234 // DesktopHost Overrides. | 234 // DesktopHost Overrides. |
| 235 virtual void SetDesktop(Desktop* desktop) OVERRIDE; | 235 virtual void SetDesktop(Desktop* desktop) OVERRIDE; |
| 236 virtual gfx::AcceleratedWidget GetAcceleratedWidget() OVERRIDE; | 236 virtual gfx::AcceleratedWidget GetAcceleratedWidget() OVERRIDE; |
| 237 virtual void Show() OVERRIDE; | 237 virtual void Show() OVERRIDE; |
| 238 virtual void ToggleFullScreen() OVERRIDE; | 238 virtual void ToggleFullScreen() OVERRIDE; |
| 239 virtual gfx::Size GetSize() const OVERRIDE; | 239 virtual gfx::Size GetSize() const OVERRIDE; |
| 240 virtual void SetSize(const gfx::Size& size) OVERRIDE; | 240 virtual void SetSize(const gfx::Size& size) OVERRIDE; |
| 241 virtual void SetCursor(gfx::NativeCursor cursor_type) OVERRIDE; | 241 virtual void SetCursor(gfx::NativeCursor cursor_type) OVERRIDE; |
| 242 virtual gfx::Point QueryMouseLocation() OVERRIDE; | 242 virtual gfx::Point QueryMouseLocation() OVERRIDE; |
| 243 virtual void PostNativeEvent(const base::NativeEvent& event) OVERRIDE; | 243 virtual void PostNativeEvent(const base::NativeEvent& event) OVERRIDE; |
| 244 virtual void ConvertPointToNativeScreen(gfx::Point* point) const OVERRIDE; | |
| 244 | 245 |
| 245 // Returns true if there's an X window manager present... in most cases. Some | 246 // Returns true if there's an X window manager present... in most cases. Some |
| 246 // window managers (notably, ion3) don't implement enough of ICCCM for us to | 247 // window managers (notably, ion3) don't implement enough of ICCCM for us to |
| 247 // detect that they're there. | 248 // detect that they're there. |
| 248 bool IsWindowManagerPresent(); | 249 bool IsWindowManagerPresent(); |
| 249 | 250 |
| 250 Desktop* desktop_; | 251 Desktop* desktop_; |
| 251 | 252 |
| 252 // The display and the native X window hosting the desktop. | 253 // The display and the native X window hosting the desktop. |
| 253 Display* xdisplay_; | 254 Display* xdisplay_; |
| 254 ::Window xwindow_; | 255 ::Window xwindow_; |
| 255 | 256 |
| 256 // Current Aura cursor. | 257 // Current Aura cursor. |
| 257 gfx::NativeCursor current_cursor_; | 258 gfx::NativeCursor current_cursor_; |
| 258 | 259 |
| 259 // The size of |xwindow_|. | 260 // The bounds of |xwindow_|. |
| 260 gfx::Size size_; | 261 gfx::Rect bounds_; |
| 261 | 262 |
| 262 DISALLOW_COPY_AND_ASSIGN(DesktopHostLinux); | 263 DISALLOW_COPY_AND_ASSIGN(DesktopHostLinux); |
| 263 }; | 264 }; |
| 264 | 265 |
| 265 DesktopHostLinux::DesktopHostLinux(const gfx::Rect& bounds) | 266 DesktopHostLinux::DesktopHostLinux(const gfx::Rect& bounds) |
| 266 : desktop_(NULL), | 267 : desktop_(NULL), |
| 267 xdisplay_(base::MessagePumpX::GetDefaultXDisplay()), | 268 xdisplay_(base::MessagePumpX::GetDefaultXDisplay()), |
| 268 xwindow_(0), | 269 xwindow_(0), |
| 269 current_cursor_(aura::kCursorNull), | 270 current_cursor_(aura::kCursorNull), |
| 270 size_(bounds.size()) { | 271 bounds_(bounds) { |
| 271 xwindow_ = XCreateSimpleWindow(xdisplay_, DefaultRootWindow(xdisplay_), | 272 xwindow_ = XCreateSimpleWindow(xdisplay_, DefaultRootWindow(xdisplay_), |
| 272 bounds.x(), bounds.y(), | 273 bounds.x(), bounds.y(), |
| 273 bounds.width(), bounds.height(), | 274 bounds.width(), bounds.height(), |
| 274 0, 0, 0); | 275 0, 0, 0); |
| 275 | 276 |
| 276 long event_mask = ButtonPressMask | ButtonReleaseMask | | 277 long event_mask = ButtonPressMask | ButtonReleaseMask | |
| 277 KeyPressMask | KeyReleaseMask | | 278 KeyPressMask | KeyReleaseMask | |
| 278 ExposureMask | VisibilityChangeMask | | 279 ExposureMask | VisibilityChangeMask | |
| 279 StructureNotifyMask | PropertyChangeMask | | 280 StructureNotifyMask | PropertyChangeMask | |
| 280 PointerMotionMask; | 281 PointerMotionMask; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 324 break; | 325 break; |
| 325 } | 326 } |
| 326 case ConfigureNotify: { | 327 case ConfigureNotify: { |
| 327 DCHECK_EQ(xdisplay_, xev->xconfigure.display); | 328 DCHECK_EQ(xdisplay_, xev->xconfigure.display); |
| 328 DCHECK_EQ(xwindow_, xev->xconfigure.window); | 329 DCHECK_EQ(xwindow_, xev->xconfigure.window); |
| 329 DCHECK_EQ(xwindow_, xev->xconfigure.event); | 330 DCHECK_EQ(xwindow_, xev->xconfigure.event); |
| 330 | 331 |
| 331 // It's possible that the X window may be resized by some other means than | 332 // It's possible that the X window may be resized by some other means than |
| 332 // from within aura (e.g. the X window manager can change the size). Make | 333 // from within aura (e.g. the X window manager can change the size). Make |
| 333 // sure the desktop size is maintained properly. | 334 // sure the desktop size is maintained properly. |
| 334 gfx::Size size(xev->xconfigure.width, xev->xconfigure.height); | 335 gfx::Rect bounds(xev->xconfigure.x, xev->xconfigure.y, |
| 335 if (size_ != size) { | 336 xev->xconfigure.width, xev->xconfigure.height); |
| 336 size_ = size; | 337 bool size_changed = bounds_.size() != bounds.size(); |
| 337 desktop_->OnHostResized(size); | 338 bounds_ = bounds; |
| 338 } | 339 if (size_changed) |
| 340 desktop_->OnHostResized(bounds.size()); | |
| 339 handled = true; | 341 handled = true; |
| 340 break; | 342 break; |
| 341 } | 343 } |
| 342 case GenericEvent: { | 344 case GenericEvent: { |
| 343 ui::TouchFactory* factory = ui::TouchFactory::GetInstance(); | 345 ui::TouchFactory* factory = ui::TouchFactory::GetInstance(); |
| 344 if (!factory->ShouldProcessXI2Event(xev)) | 346 if (!factory->ShouldProcessXI2Event(xev)) |
| 345 break; | 347 break; |
| 346 | 348 |
| 347 // If this is a motion event we want to coalesce all pending motion | 349 // If this is a motion event we want to coalesce all pending motion |
| 348 // events that are at the top of the queue. | 350 // events that are at the top of the queue. |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 430 | 432 |
| 431 void DesktopHostLinux::Show() { | 433 void DesktopHostLinux::Show() { |
| 432 XMapWindow(xdisplay_, xwindow_); | 434 XMapWindow(xdisplay_, xwindow_); |
| 433 } | 435 } |
| 434 | 436 |
| 435 void DesktopHostLinux::ToggleFullScreen() { | 437 void DesktopHostLinux::ToggleFullScreen() { |
| 436 NOTIMPLEMENTED(); | 438 NOTIMPLEMENTED(); |
| 437 } | 439 } |
| 438 | 440 |
| 439 gfx::Size DesktopHostLinux::GetSize() const { | 441 gfx::Size DesktopHostLinux::GetSize() const { |
| 440 return size_; | 442 return bounds_.size(); |
| 441 } | 443 } |
| 442 | 444 |
| 443 void DesktopHostLinux::SetSize(const gfx::Size& size) { | 445 void DesktopHostLinux::SetSize(const gfx::Size& size) { |
| 444 if (size == size_) | 446 if (size == bounds_.size()) |
| 445 return; | 447 return; |
| 446 | 448 |
| 447 XResizeWindow(xdisplay_, xwindow_, size.width(), size.height()); | 449 XResizeWindow(xdisplay_, xwindow_, size.width(), size.height()); |
| 448 | 450 |
| 449 // Assume that the resize will go through as requested, which should be the | 451 // Assume that the resize will go through as requested, which should be the |
| 450 // case if we're running without a window manager. If there's a window | 452 // case if we're running without a window manager. If there's a window |
| 451 // manager, it can modify or ignore the request, but (per ICCCM) we'll get a | 453 // manager, it can modify or ignore the request, but (per ICCCM) we'll get a |
| 452 // (possibly synthetic) ConfigureNotify about the actual size and correct | 454 // (possibly synthetic) ConfigureNotify about the actual size and correct |
| 453 // |size_| later. | 455 // |bounds_| later. |
| 454 size_ = size; | 456 bounds_.set_size(size); |
| 455 desktop_->OnHostResized(size); | 457 desktop_->OnHostResized(size); |
| 456 } | 458 } |
| 457 | 459 |
| 458 void DesktopHostLinux::SetCursor(gfx::NativeCursor cursor) { | 460 void DesktopHostLinux::SetCursor(gfx::NativeCursor cursor) { |
| 459 if (current_cursor_ == cursor) | 461 if (current_cursor_ == cursor) |
| 460 return; | 462 return; |
| 461 current_cursor_ = cursor; | 463 current_cursor_ = cursor; |
| 462 // Custom web cursors are handled directly. | 464 // Custom web cursors are handled directly. |
| 463 if (cursor == kCursorCustom) | 465 if (cursor == kCursorCustom) |
| 464 return; | 466 return; |
| 465 int cursor_shape = CursorShapeFromNative(cursor); | 467 int cursor_shape = CursorShapeFromNative(cursor); |
| 466 ::Cursor xcursor = ui::GetXCursor(cursor_shape); | 468 ::Cursor xcursor = ui::GetXCursor(cursor_shape); |
| 467 XDefineCursor(xdisplay_, xwindow_, xcursor); | 469 XDefineCursor(xdisplay_, xwindow_, xcursor); |
| 468 } | 470 } |
| 469 | 471 |
| 470 gfx::Point DesktopHostLinux::QueryMouseLocation() { | 472 gfx::Point DesktopHostLinux::QueryMouseLocation() { |
| 471 ::Window root_return, child_return; | 473 ::Window root_return, child_return; |
| 472 int root_x_return, root_y_return, win_x_return, win_y_return; | 474 int root_x_return, root_y_return, win_x_return, win_y_return; |
| 473 unsigned int mask_return; | 475 unsigned int mask_return; |
| 474 XQueryPointer(xdisplay_, | 476 XQueryPointer(xdisplay_, |
| 475 xwindow_, | 477 xwindow_, |
| 476 &root_return, | 478 &root_return, |
| 477 &child_return, | 479 &child_return, |
| 478 &root_x_return, &root_y_return, | 480 &root_x_return, &root_y_return, |
| 479 &win_x_return, &win_y_return, | 481 &win_x_return, &win_y_return, |
| 480 &mask_return); | 482 &mask_return); |
| 481 return gfx::Point(max(0, min(size_.width(), win_x_return)), | 483 return gfx::Point(max(0, min(bounds_.width(), win_x_return)), |
| 482 max(0, min(size_.height(), win_y_return))); | 484 max(0, min(bounds_.height(), win_y_return))); |
| 485 } | |
| 486 | |
| 487 void DesktopHostLinux::ConvertPointToNativeScreen(gfx::Point* point) const { | |
| 488 point->Offset(bounds_.x(), bounds_.y()); | |
| 483 } | 489 } |
| 484 | 490 |
| 485 void DesktopHostLinux::PostNativeEvent(const base::NativeEvent& native_event) { | 491 void DesktopHostLinux::PostNativeEvent(const base::NativeEvent& native_event) { |
| 492 const long kInputEventMask = KeyReleaseMask | KeyPressMask | | |
| 493 PointerMotionMask | ButtonPressMask | ButtonReleaseMask; | |
| 486 DCHECK(xwindow_); | 494 DCHECK(xwindow_); |
| 487 DCHECK(xdisplay_); | 495 DCHECK(xdisplay_); |
| 488 XEvent xevent = *native_event; | 496 XEvent xevent = *native_event; |
| 489 xevent.xany.display = xdisplay_; | 497 xevent.xany.display = xdisplay_; |
| 490 xevent.xany.window = xwindow_; | 498 xevent.xany.window = xwindow_; |
| 491 ::XPutBackEvent(xdisplay_, &xevent); | 499 |
| 500 switch (xevent.type) { | |
| 501 case MotionNotify: | |
| 502 case KeyPress: | |
| 503 case KeyRelease: | |
| 504 case ButtonPress: | |
| 505 case ButtonRelease: { | |
|
Daniel Erat
2011/11/22 00:25:32
i know that we don't do anything with them (now),
oshima
2011/11/22 01:36:10
Because X's Enter/Leave notify doesn't trigger aur
Daniel Erat
2011/11/22 01:46:14
They could get added to aura later, and things wou
oshima
2011/11/22 03:02:09
I just couldn't imagine how this will be needed. O
| |
| 506 xevent.xmotion.root = DefaultRootWindow(xdisplay_); | |
|
Daniel Erat
2011/11/22 00:25:32
maybe add a comment mentioning that you're choosin
oshima
2011/11/22 01:36:10
Done.
| |
| 507 xevent.xmotion.time = CurrentTime; | |
| 508 | |
| 509 gfx::Point point(xevent.xmotion.x, xevent.xmotion.y); | |
| 510 ConvertPointToNativeScreen(&point); | |
| 511 xevent.xmotion.x_root = point.x(); | |
| 512 xevent.xmotion.y_root = point.y(); | |
| 513 } | |
| 514 default: | |
| 515 break; | |
| 516 } | |
| 517 ::XSendEvent(xdisplay_, xwindow_, False, kInputEventMask, &xevent); | |
|
Daniel Erat
2011/11/22 00:25:32
nit: "::" seems unnecessary here; this function na
oshima
2011/11/22 01:36:10
Done.
| |
| 492 } | 518 } |
| 493 | 519 |
| 494 bool DesktopHostLinux::IsWindowManagerPresent() { | 520 bool DesktopHostLinux::IsWindowManagerPresent() { |
| 495 // Per ICCCM 2.8, "Manager Selections", window managers should take ownership | 521 // Per ICCCM 2.8, "Manager Selections", window managers should take ownership |
| 496 // of WM_Sn selections (where n is a screen number). | 522 // of WM_Sn selections (where n is a screen number). |
| 497 ::Atom wm_s0_atom = XInternAtom(xdisplay_, "WM_S0", False); | 523 ::Atom wm_s0_atom = XInternAtom(xdisplay_, "WM_S0", False); |
| 498 return XGetSelectionOwner(xdisplay_, wm_s0_atom) != None; | 524 return XGetSelectionOwner(xdisplay_, wm_s0_atom) != None; |
| 499 } | 525 } |
| 500 | 526 |
| 501 } // namespace | 527 } // namespace |
| 502 | 528 |
| 503 // static | 529 // static |
| 504 DesktopHost* DesktopHost::Create(const gfx::Rect& bounds) { | 530 DesktopHost* DesktopHost::Create(const gfx::Rect& bounds) { |
| 505 return new DesktopHostLinux(bounds); | 531 return new DesktopHostLinux(bounds); |
| 506 } | 532 } |
| 507 | 533 |
| 508 // static | 534 // static |
| 509 gfx::Size DesktopHost::GetNativeDisplaySize() { | 535 gfx::Size DesktopHost::GetNativeDisplaySize() { |
| 510 ::Display* xdisplay = base::MessagePumpX::GetDefaultXDisplay(); | 536 ::Display* xdisplay = base::MessagePumpX::GetDefaultXDisplay(); |
| 511 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0)); | 537 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0)); |
| 512 } | 538 } |
| 513 | 539 |
| 514 } // namespace aura | 540 } // namespace aura |
| OLD | NEW |