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 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 231 // base::MessageLoop::Dispatcher Override. | 231 // base::MessageLoop::Dispatcher Override. |
| 232 virtual DispatchStatus Dispatch(XEvent* xev) OVERRIDE; | 232 virtual DispatchStatus Dispatch(XEvent* xev) OVERRIDE; |
| 233 | 233 |
| 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 gfx::Point GetLocationOnNativeScreen() const OVERRIDE; | |
| 241 virtual void SetCursor(gfx::NativeCursor cursor_type) OVERRIDE; | 242 virtual void SetCursor(gfx::NativeCursor cursor_type) OVERRIDE; |
| 242 virtual gfx::Point QueryMouseLocation() OVERRIDE; | 243 virtual gfx::Point QueryMouseLocation() OVERRIDE; |
| 243 virtual void PostNativeEvent(const base::NativeEvent& event) OVERRIDE; | 244 virtual void PostNativeEvent(const base::NativeEvent& event) 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 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 321 break; | 322 break; |
| 322 } | 323 } |
| 323 case ConfigureNotify: { | 324 case ConfigureNotify: { |
| 324 DCHECK_EQ(xdisplay_, xev->xconfigure.display); | 325 DCHECK_EQ(xdisplay_, xev->xconfigure.display); |
| 325 DCHECK_EQ(xwindow_, xev->xconfigure.window); | 326 DCHECK_EQ(xwindow_, xev->xconfigure.window); |
| 326 DCHECK_EQ(xwindow_, xev->xconfigure.event); | 327 DCHECK_EQ(xwindow_, xev->xconfigure.event); |
| 327 | 328 |
| 328 // It's possible that the X window may be resized by some other means than | 329 // It's possible that the X window may be resized by some other means than |
| 329 // from within aura (e.g. the X window manager can change the size). Make | 330 // from within aura (e.g. the X window manager can change the size). Make |
| 330 // sure the desktop size is maintained properly. | 331 // sure the desktop size is maintained properly. |
| 331 gfx::Size size(xev->xconfigure.width, xev->xconfigure.height); | 332 gfx::Rect bounds(xev->xconfigure.x, xev->xconfigure.y, |
| 332 if (size_ != size) { | 333 xev->xconfigure.width, xev->xconfigure.height); |
| 333 size_ = size; | 334 bool size_changed = bounds_.size() != bounds.size(); |
| 334 desktop_->OnHostResized(size); | 335 bounds_ = bounds; |
| 335 } | 336 if (size_changed) |
| 337 desktop_->OnHostResized(bounds.size()); | |
| 336 handled = true; | 338 handled = true; |
| 337 break; | 339 break; |
| 338 } | 340 } |
| 339 case GenericEvent: { | 341 case GenericEvent: { |
| 340 ui::TouchFactory* factory = ui::TouchFactory::GetInstance(); | 342 ui::TouchFactory* factory = ui::TouchFactory::GetInstance(); |
| 341 if (!factory->ShouldProcessXI2Event(xev)) | 343 if (!factory->ShouldProcessXI2Event(xev)) |
| 342 break; | 344 break; |
| 343 | 345 |
| 344 // If this is a motion event we want to coalesce all pending motion | 346 // If this is a motion event we want to coalesce all pending motion |
| 345 // events that are at the top of the queue. | 347 // events that are at the top of the queue. |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 427 | 429 |
| 428 void DesktopHostLinux::Show() { | 430 void DesktopHostLinux::Show() { |
| 429 XMapWindow(xdisplay_, xwindow_); | 431 XMapWindow(xdisplay_, xwindow_); |
| 430 } | 432 } |
| 431 | 433 |
| 432 void DesktopHostLinux::ToggleFullScreen() { | 434 void DesktopHostLinux::ToggleFullScreen() { |
| 433 NOTIMPLEMENTED(); | 435 NOTIMPLEMENTED(); |
| 434 } | 436 } |
| 435 | 437 |
| 436 gfx::Size DesktopHostLinux::GetSize() const { | 438 gfx::Size DesktopHostLinux::GetSize() const { |
| 437 return size_; | 439 return bounds_.size(); |
| 438 } | 440 } |
| 439 | 441 |
| 440 void DesktopHostLinux::SetSize(const gfx::Size& size) { | 442 void DesktopHostLinux::SetSize(const gfx::Size& size) { |
| 441 if (size == size_) | 443 if (size == bounds_.size()) |
| 442 return; | 444 return; |
| 443 | 445 |
| 444 XResizeWindow(xdisplay_, xwindow_, size.width(), size.height()); | 446 XResizeWindow(xdisplay_, xwindow_, size.width(), size.height()); |
| 445 | 447 |
| 446 // Assume that the resize will go through as requested, which should be the | 448 // Assume that the resize will go through as requested, which should be the |
| 447 // case if we're running without a window manager. If there's a window | 449 // case if we're running without a window manager. If there's a window |
| 448 // manager, it can modify or ignore the request, but (per ICCCM) we'll get a | 450 // manager, it can modify or ignore the request, but (per ICCCM) we'll get a |
| 449 // (possibly synthetic) ConfigureNotify about the actual size and correct | 451 // (possibly synthetic) ConfigureNotify about the actual size and correct |
| 450 // |size_| later. | 452 // |bounds_| later. |
| 451 size_ = size; | 453 bounds_.set_size(size); |
| 452 desktop_->OnHostResized(size); | 454 desktop_->OnHostResized(size); |
| 453 } | 455 } |
| 454 | 456 |
| 457 gfx::Point DesktopHostLinux::GetLocationOnNativeScreen() const { | |
| 458 return bounds_.origin(); | |
| 459 } | |
| 460 | |
| 455 void DesktopHostLinux::SetCursor(gfx::NativeCursor cursor) { | 461 void DesktopHostLinux::SetCursor(gfx::NativeCursor cursor) { |
| 456 if (current_cursor_ == cursor) | 462 if (current_cursor_ == cursor) |
| 457 return; | 463 return; |
| 458 current_cursor_ = cursor; | 464 current_cursor_ = cursor; |
| 459 // Custom web cursors are handled directly. | 465 // Custom web cursors are handled directly. |
| 460 if (cursor == kCursorCustom) | 466 if (cursor == kCursorCustom) |
| 461 return; | 467 return; |
| 462 int cursor_shape = CursorShapeFromNative(cursor); | 468 int cursor_shape = CursorShapeFromNative(cursor); |
| 463 ::Cursor xcursor = ui::GetXCursor(cursor_shape); | 469 ::Cursor xcursor = ui::GetXCursor(cursor_shape); |
| 464 XDefineCursor(xdisplay_, xwindow_, xcursor); | 470 XDefineCursor(xdisplay_, xwindow_, xcursor); |
| 465 } | 471 } |
| 466 | 472 |
| 467 gfx::Point DesktopHostLinux::QueryMouseLocation() { | 473 gfx::Point DesktopHostLinux::QueryMouseLocation() { |
| 468 ::Window root_return, child_return; | 474 ::Window root_return, child_return; |
| 469 int root_x_return, root_y_return, win_x_return, win_y_return; | 475 int root_x_return, root_y_return, win_x_return, win_y_return; |
| 470 unsigned int mask_return; | 476 unsigned int mask_return; |
| 471 XQueryPointer(xdisplay_, | 477 XQueryPointer(xdisplay_, |
| 472 xwindow_, | 478 xwindow_, |
| 473 &root_return, | 479 &root_return, |
| 474 &child_return, | 480 &child_return, |
| 475 &root_x_return, &root_y_return, | 481 &root_x_return, &root_y_return, |
| 476 &win_x_return, &win_y_return, | 482 &win_x_return, &win_y_return, |
| 477 &mask_return); | 483 &mask_return); |
| 478 return gfx::Point(max(0, min(size_.width(), win_x_return)), | 484 return gfx::Point(max(0, min(bounds_.width(), win_x_return)), |
| 479 max(0, min(size_.height(), win_y_return))); | 485 max(0, min(bounds_.height(), win_y_return))); |
| 480 } | 486 } |
| 481 | 487 |
| 482 void DesktopHostLinux::PostNativeEvent(const base::NativeEvent& native_event) { | 488 void DesktopHostLinux::PostNativeEvent(const base::NativeEvent& native_event) { |
| 489 const long kInputEventMask = KeyReleaseMask | KeyPressMask | | |
|
Daniel Erat
2011/11/22 16:37:06
This is actually a bit weird. From the man page:
oshima
2011/11/22 17:22:54
Seems like I misunderstood the doc. I believe I do
| |
| 490 PointerMotionMask | ButtonPressMask | ButtonReleaseMask; | |
| 483 DCHECK(xwindow_); | 491 DCHECK(xwindow_); |
| 484 DCHECK(xdisplay_); | 492 DCHECK(xdisplay_); |
| 485 XEvent xevent = *native_event; | 493 XEvent xevent = *native_event; |
| 486 xevent.xany.display = xdisplay_; | 494 xevent.xany.display = xdisplay_; |
| 487 xevent.xany.window = xwindow_; | 495 xevent.xany.window = xwindow_; |
| 488 ::XPutBackEvent(xdisplay_, &xevent); | 496 |
| 497 switch (xevent.type) { | |
| 498 case EnterNotify: | |
| 499 case LeaveNotify: | |
| 500 case MotionNotify: | |
| 501 case KeyPress: | |
| 502 case KeyRelease: | |
| 503 case ButtonPress: | |
| 504 case ButtonRelease: { | |
| 505 // The fields used below are in the same place for all of events | |
| 506 // above. Using xmotion from XEvent's unions to avoid repeating | |
| 507 // the code. | |
| 508 xevent.xmotion.root = DefaultRootWindow(xdisplay_); | |
| 509 xevent.xmotion.time = CurrentTime; | |
| 510 | |
| 511 gfx::Point point(xevent.xmotion.x, xevent.xmotion.y); | |
| 512 desktop_->ConvertPointToNativeScreen(&point); | |
| 513 xevent.xmotion.x_root = point.x(); | |
| 514 xevent.xmotion.y_root = point.y(); | |
| 515 } | |
| 516 default: | |
| 517 break; | |
| 518 } | |
| 519 XSendEvent(xdisplay_, xwindow_, False, kInputEventMask, &xevent); | |
| 489 } | 520 } |
| 490 | 521 |
| 491 bool DesktopHostLinux::IsWindowManagerPresent() { | 522 bool DesktopHostLinux::IsWindowManagerPresent() { |
| 492 // Per ICCCM 2.8, "Manager Selections", window managers should take ownership | 523 // Per ICCCM 2.8, "Manager Selections", window managers should take ownership |
| 493 // of WM_Sn selections (where n is a screen number). | 524 // of WM_Sn selections (where n is a screen number). |
| 494 ::Atom wm_s0_atom = XInternAtom(xdisplay_, "WM_S0", False); | 525 ::Atom wm_s0_atom = XInternAtom(xdisplay_, "WM_S0", False); |
| 495 return XGetSelectionOwner(xdisplay_, wm_s0_atom) != None; | 526 return XGetSelectionOwner(xdisplay_, wm_s0_atom) != None; |
| 496 } | 527 } |
| 497 | 528 |
| 498 } // namespace | 529 } // namespace |
| 499 | 530 |
| 500 // static | 531 // static |
| 501 DesktopHost* DesktopHost::Create(const gfx::Rect& bounds) { | 532 DesktopHost* DesktopHost::Create(const gfx::Rect& bounds) { |
| 502 return new DesktopHostLinux(bounds); | 533 return new DesktopHostLinux(bounds); |
| 503 } | 534 } |
| 504 | 535 |
| 505 // static | 536 // static |
| 506 gfx::Size DesktopHost::GetNativeDisplaySize() { | 537 gfx::Size DesktopHost::GetNativeDisplaySize() { |
| 507 ::Display* xdisplay = base::MessagePumpX::GetDefaultXDisplay(); | 538 ::Display* xdisplay = base::MessagePumpX::GetDefaultXDisplay(); |
| 508 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0)); | 539 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0)); |
| 509 } | 540 } |
| 510 | 541 |
| 511 } // namespace aura | 542 } // namespace aura |
| OLD | NEW |