Chromium Code Reviews| Index: remoting/host/capturer_linux.cc |
| diff --git a/remoting/host/capturer_linux.cc b/remoting/host/capturer_linux.cc |
| index e513bb7c8932492f9dcf14c8fb061f885bebc253..3245c338839283eb2e16d696d3603a46023e3780 100644 |
| --- a/remoting/host/capturer_linux.cc |
| +++ b/remoting/host/capturer_linux.cc |
| @@ -7,6 +7,7 @@ |
| #include <X11/Xlib.h> |
| #include <X11/Xutil.h> |
| #include <X11/extensions/Xdamage.h> |
| +#include <X11/extensions/Xfixes.h> |
| #include <set> |
| @@ -77,6 +78,8 @@ class CapturerLinux : public Capturer { |
| // Capturer interface. |
| virtual void Start() OVERRIDE; |
| virtual void Stop() OVERRIDE; |
| + virtual void SetCursorShapeChangedCallback( |
| + const CursorShapeChangedCallback& callback) OVERRIDE; |
| virtual void ScreenConfigurationChanged() OVERRIDE; |
| virtual media::VideoFrame::Format pixel_format() const OVERRIDE; |
| virtual void ClearInvalidRegion() OVERRIDE; |
| @@ -106,6 +109,10 @@ class CapturerLinux : public Capturer { |
| // previous capture. |
| CaptureData* CaptureFrame(); |
| + // Capture the cursor shape pixels and call the CursorShapeChangedCallback, |
|
Wez
2012/05/16 00:20:04
nit: "shape pixels" -> "image" ?
garykac
2012/05/22 00:42:03
Done.
|
| + // if it has been set (using SetCursorShapeChangedCallback). |
| + void CaptureCursor(); |
| + |
| // Synchronize the current buffer with |last_buffer_|, by copying pixels from |
| // the area of |last_invalid_rects|. |
| // Note this only works on the assumption that kNumBuffers == 2, as |
| @@ -129,6 +136,11 @@ class CapturerLinux : public Capturer { |
| GC gc_; |
| Window root_window_; |
| + // XFixes. |
| + bool has_xfixes_; |
| + int xfixes_event_base_; |
| + int xfixes_error_base_; |
| + |
| // XDamage information. |
| bool use_damage_; |
| Damage damage_handle_; |
| @@ -143,6 +155,9 @@ class CapturerLinux : public Capturer { |
| // recently captured screen. |
| CapturerHelper helper_; |
| + // Callback to call whenever the cursor shape is changed. |
|
Wez
2012/05/16 00:20:04
nit: "Callback notified ..."
garykac
2012/05/22 00:42:03
Done.
|
| + CursorShapeChangedCallback cursor_shape_changed_callback_; |
| + |
| // Capture state. |
| static const int kNumBuffers = 2; |
| VideoFrameBuffer buffers_[kNumBuffers]; |
| @@ -168,6 +183,9 @@ CapturerLinux::CapturerLinux() |
| : display_(NULL), |
| gc_(NULL), |
| root_window_(BadValue), |
| + has_xfixes_(false), |
| + xfixes_event_base_(-1), |
| + xfixes_error_base_(-1), |
| use_damage_(false), |
| damage_handle_(0), |
| damage_event_base_(-1), |
| @@ -208,6 +226,15 @@ bool CapturerLinux::Init() { |
| return false; |
| } |
| + // Check for XFixes extension. This is required for our XDamage support and |
|
Wez
2012/05/16 00:20:04
nit: Suggest "This is required for cursor shape no
garykac
2012/05/22 00:42:03
Done.
|
| + // to get the cursor shape notifications. |
| + if (XFixesQueryExtension(display_, &xfixes_event_base_, |
| + &xfixes_error_base_)) { |
| + has_xfixes_ = true; |
| + } else { |
| + LOG(INFO) << "X server does not support XFixes."; |
| + } |
| + |
| if (ShouldUseXDamage()) { |
| InitXDamage(); |
| } |
| @@ -215,18 +242,21 @@ bool CapturerLinux::Init() { |
| // Register for changes to the dimensions of the root window. |
| XSelectInput(display_, root_window_, StructureNotifyMask); |
| + if (has_xfixes_) { |
| + // Register for changes to the cursor shape. |
| + XFixesSelectCursorInput(display_, root_window_, |
| + XFixesDisplayCursorNotifyMask); |
| + } |
| + |
| return true; |
| } |
| void CapturerLinux::InitXDamage() { |
| - // Check for XFixes and XDamage extensions. If both are found then use |
| - // XDamage to get explicit notifications of on-screen changes. |
| - int xfixes_event_base; |
| - int xfixes_error_base; |
| - if (!XFixesQueryExtension(display_, &xfixes_event_base, &xfixes_error_base)) { |
| - LOG(INFO) << "X server does not support XFixes."; |
| + if (!has_xfixes_) |
| return; |
| - } |
| + |
| + // Check for XDamage extension. If this and XFixes are both found then use |
|
Wez
2012/05/16 00:20:04
nit: You've already tested for XFixes, so don't me
garykac
2012/05/22 00:42:03
Done.
|
| + // XDamage to get explicit notifications of on-screen changes. |
| if (!XDamageQueryExtension(display_, &damage_event_base_, |
| &damage_error_base_)) { |
| LOG(INFO) << "X server does not support XDamage."; |
| @@ -264,6 +294,11 @@ void CapturerLinux::Start() { |
| void CapturerLinux::Stop() { |
| } |
| +void CapturerLinux::SetCursorShapeChangedCallback( |
| + const CursorShapeChangedCallback& callback) { |
| + cursor_shape_changed_callback_ = callback; |
| +} |
| + |
| void CapturerLinux::ScreenConfigurationChanged() { |
| last_buffer_ = NULL; |
| for (int i = 0; i < kNumBuffers; ++i) { |
| @@ -296,8 +331,7 @@ void CapturerLinux::InvalidateFullScreen() { |
| void CapturerLinux::CaptureInvalidRegion( |
| const CaptureCompletedCallback& callback) { |
| - // TODO(lambroslambrou): In the non-DAMAGE case, there should be no need |
| - // for any X event processing in this class. |
| + // Process XEvents for XDamage and cursor shape. |
|
Wez
2012/05/16 00:20:04
nit: "... cursor shape tracking"
garykac
2012/05/22 00:42:03
Done.
|
| ProcessPendingXEvents(); |
| // Resize the current buffer if there was a recent change of |
| @@ -326,16 +360,34 @@ void CapturerLinux::ProcessPendingXEvents() { |
| for (int i = 0; i < events_to_process; i++) { |
| XNextEvent(display_, &e); |
| if (use_damage_ && (e.type == damage_event_base_ + XDamageNotify)) { |
| - XDamageNotifyEvent *event = reinterpret_cast<XDamageNotifyEvent*>(&e); |
| + XDamageNotifyEvent* event = reinterpret_cast<XDamageNotifyEvent*>(&e); |
| DCHECK(event->level == XDamageReportNonEmpty); |
| } else if (e.type == ConfigureNotify) { |
| ScreenConfigurationChanged(); |
| + } else if (has_xfixes_ && |
| + e.type == xfixes_event_base_ + XFixesCursorNotify) { |
| + XFixesCursorNotifyEvent* cne; |
| + cne = reinterpret_cast<XFixesCursorNotifyEvent*>(&e); |
| + if (cne->subtype == XFixesDisplayCursorNotify) { |
| + CaptureCursor(); |
| + } |
| } else { |
| LOG(WARNING) << "Got unknown event type: " << e.type; |
| } |
| } |
| } |
| +void CapturerLinux::CaptureCursor() { |
| + DCHECK(has_xfixes_); |
| + if (cursor_shape_changed_callback_.is_null()) |
| + return; |
| + |
| + // TODO(garykac) Get cursor shape using XFixesGetCursorImage. |
| + |
| + scoped_refptr<CursorShapeData> cursor_data; |
| + cursor_shape_changed_callback_.Run(cursor_data); |
| +} |
| + |
| CaptureData* CapturerLinux::CaptureFrame() { |
| VideoFrameBuffer& buffer = buffers_[current_buffer_]; |
| DataPlanes planes; |