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; |