summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--remoting/base/decoder.h14
-rw-r--r--remoting/base/decoder_vp8.cc56
-rw-r--r--remoting/base/decoder_vp8.h8
-rw-r--r--remoting/base/util.cc50
-rw-r--r--remoting/base/util.h10
-rw-r--r--remoting/client/chromoting_client.cc6
-rw-r--r--remoting/client/chromoting_client.h3
-rw-r--r--remoting/client/chromoting_view.cc26
-rw-r--r--remoting/client/chromoting_view.h26
-rw-r--r--remoting/client/input_handler.cc84
-rw-r--r--remoting/client/input_handler.h52
-rw-r--r--remoting/client/mouse_input_filter.cc49
-rw-r--r--remoting/client/mouse_input_filter.h45
-rw-r--r--remoting/client/plugin/chromoting_instance.cc146
-rw-r--r--remoting/client/plugin/chromoting_instance.h17
-rw-r--r--remoting/client/plugin/chromoting_scriptable_object.cc20
-rw-r--r--remoting/client/plugin/chromoting_scriptable_object.h4
-rw-r--r--remoting/client/plugin/pepper_input_handler.cc155
-rw-r--r--remoting/client/plugin/pepper_input_handler.h30
-rw-r--r--remoting/client/plugin/pepper_view.cc28
-rw-r--r--remoting/client/plugin/pepper_view.h28
-rw-r--r--remoting/client/plugin/pepper_view_proxy.cc154
-rw-r--r--remoting/client/plugin/pepper_view_proxy.h87
-rw-r--r--remoting/client/rectangle_update_decoder.cc16
-rw-r--r--remoting/client/rectangle_update_decoder.h7
-rw-r--r--remoting/host/client_session.cc1
-rw-r--r--remoting/protocol/key_event_tracker.cc48
-rw-r--r--remoting/protocol/key_event_tracker.h43
-rw-r--r--remoting/remoting.gyp9
29 files changed, 430 insertions, 792 deletions
diff --git a/remoting/base/decoder.h b/remoting/base/decoder.h
index d932ff1..dd37757 100644
--- a/remoting/base/decoder.h
+++ b/remoting/base/decoder.h
@@ -57,11 +57,10 @@ class Decoder {
virtual VideoPacketFormat::Encoding Encoding() = 0;
- // Set the scale factors of the decoded output. If the decoder doesn't support
- // scaling then this all is ignored.
- // If both |horizontal_ratio| and |vertical_ratio| equal 1.0 then scaling is
- // turned off.
- virtual void SetScaleRatios(double horizontal_ratio, double vertical_ratio) {}
+ // Set the output dimensions for the decoder. If the dimensions are empty
+ // then the source is rendered without scaling.
+ // Output dimensions are ignored if the decoder doesn't support scaling.
+ virtual void SetOutputSize(const SkISize& size) {}
// Set the clipping rectangle to the decoder. Decoder should respect this and
// only output changes in this rectangle. The new clipping rectangle will be
@@ -71,9 +70,8 @@ class Decoder {
virtual void SetClipRect(const SkIRect& clip_rect) {}
// Force decoder to output a video frame with content in |rects| using the
- // last decoded video frame.
- //
- // Coordinates of rectangles supplied here are before scaling.
+ // last decoded video frame. |rects| are expressed in video frame rather
+ // than output coordinates.
virtual void RefreshRects(const RectVector& rects) {}
};
diff --git a/remoting/base/decoder_vp8.cc b/remoting/base/decoder_vp8.cc
index 8c8a205..af1f718 100644
--- a/remoting/base/decoder_vp8.cc
+++ b/remoting/base/decoder_vp8.cc
@@ -23,8 +23,7 @@ DecoderVp8::DecoderVp8()
codec_(NULL),
last_image_(NULL),
clip_rect_(SkIRect::MakeEmpty()),
- horizontal_scale_ratio_(1.0),
- vertical_scale_ratio_(1.0) {
+ output_size_(SkISize::Make(0, 0)) {
}
DecoderVp8::~DecoderVp8() {
@@ -103,10 +102,17 @@ Decoder::DecodeResult DecoderVp8::DecodePacket(const VideoPacket* packet) {
remoting_rect.height()));
}
- if (!DoScaling())
- ConvertRects(rects, &updated_rects_);
- else
- ScaleAndConvertRects(rects, &updated_rects_);
+ // TODO(wez): Fix the rest of the decode pipeline not to assume the frame
+ // size is the host dimensions, since it's not when scaling. If the host
+ // gets smaller, then the output size will be too big and we'll overrun the
+ // frame, so currently we render 1:1 in that case; the app will see the
+ // host size change and resize us if need be.
+ if ((output_size_.width() > static_cast<int>(frame_->width())) ||
+ (output_size_.height() > static_cast<int>(frame_->height()))) {
+ output_size_.set(frame_->width(), frame_->height());
+ }
+
+ RefreshRects(rects);
return DECODE_DONE;
}
@@ -127,18 +133,8 @@ VideoPacketFormat::Encoding DecoderVp8::Encoding() {
return VideoPacketFormat::ENCODING_VP8;
}
-void DecoderVp8::SetScaleRatios(double horizontal_ratio,
- double vertical_ratio) {
- // TODO(hclam): Ratio greater than 1.0 is not supported. This is
- // because we need to reallocate the backing video frame and this
- // is not implemented yet.
- if (horizontal_ratio > 1.0 || horizontal_ratio <= 0.0 ||
- vertical_ratio > 1.0 || vertical_ratio <= 0.0) {
- return;
- }
-
- horizontal_scale_ratio_ = horizontal_ratio;
- vertical_scale_ratio_ = vertical_ratio;
+void DecoderVp8::SetOutputSize(const SkISize& size) {
+ output_size_ = size;
}
void DecoderVp8::SetClipRect(const SkIRect& clip_rect) {
@@ -153,7 +149,8 @@ void DecoderVp8::RefreshRects(const RectVector& rects) {
}
bool DecoderVp8::DoScaling() const {
- return horizontal_scale_ratio_ != 1.0 || vertical_scale_ratio_ != 1.0;
+ DCHECK(last_image_);
+ return !output_size_.equals(last_image_->d_w, last_image_->d_h);
}
void DecoderVp8::ConvertRects(const RectVector& input_rects,
@@ -203,30 +200,25 @@ void DecoderVp8::ScaleAndConvertRects(const RectVector& input_rects,
if (!last_image_)
return;
- int input_width = last_image_->d_w;
- int input_height = last_image_->d_h;
-
- uint8* output_rgb_buf = frame_->data(media::VideoFrame::kRGBPlane);
- const int output_stride = frame_->stride(media::VideoFrame::kRGBPlane);
-
- // TODO(wez): Resize |frame_| to our desired output dimensions when scaling.
- int output_width = ceil(input_width * horizontal_scale_ratio_);
- int output_height = ceil(input_height * vertical_scale_ratio_);
+ DCHECK(output_size_.width() <= static_cast<int>(frame_->width()));
+ DCHECK(output_size_.height() <= static_cast<int>(frame_->height()));
output_rects->clear();
// Clip based on both the output dimensions and Pepper clip rect.
SkIRect clip_rect = clip_rect_;
- if (!clip_rect.intersect(SkIRect::MakeWH(output_width, output_height)))
+ if (!clip_rect.intersect(SkIRect::MakeSize(output_size_)))
return;
+ SkISize image_size = SkISize::Make(last_image_->d_w, last_image_->d_h);
+ uint8* output_rgb_buf = frame_->data(media::VideoFrame::kRGBPlane);
+ const int output_stride = frame_->stride(media::VideoFrame::kRGBPlane);
+
output_rects->reserve(input_rects.size());
for (size_t i = 0; i < input_rects.size(); ++i) {
// Determine the scaled area affected by this rectangle changing.
- SkIRect output_rect = ScaleRect(input_rects[i],
- horizontal_scale_ratio_,
- vertical_scale_ratio_);
+ SkIRect output_rect = ScaleRect(input_rects[i], image_size, output_size_);
if (!output_rect.intersect(clip_rect))
continue;
diff --git a/remoting/base/decoder_vp8.h b/remoting/base/decoder_vp8.h
index 33ec147..a89991c 100644
--- a/remoting/base/decoder_vp8.h
+++ b/remoting/base/decoder_vp8.h
@@ -24,8 +24,7 @@ class DecoderVp8 : public Decoder {
virtual bool IsReadyForData() OVERRIDE;
virtual void Reset() OVERRIDE;
virtual VideoPacketFormat::Encoding Encoding() OVERRIDE;
- virtual void SetScaleRatios(double horizontal_ratio,
- double vertical_ratio) OVERRIDE;
+ virtual void SetOutputSize(const SkISize& size) OVERRIDE;
virtual void SetClipRect(const SkIRect& clip_rect) OVERRIDE;
virtual void RefreshRects(const RectVector& rects) OVERRIDE;
@@ -67,9 +66,8 @@ class DecoderVp8 : public Decoder {
// Clipping rect for the output of the decoder.
SkIRect clip_rect_;
- // Scale factors of the decoded output.
- double horizontal_scale_ratio_;
- double vertical_scale_ratio_;
+ // Output dimensions.
+ SkISize output_size_;
DISALLOW_COPY_AND_ASSIGN(DecoderVp8);
};
diff --git a/remoting/base/util.cc b/remoting/base/util.cc
index 23af0ea..d069ce8 100644
--- a/remoting/base/util.cc
+++ b/remoting/base/util.cc
@@ -61,9 +61,9 @@ void ConvertYUVToRGB32WithRect(const uint8* y_plane,
int y_stride,
int uv_stride,
int rgb_stride) {
- int rgb_offset = CalculateRGBOffset(rect.fLeft, rect.fTop, rgb_stride);
- int y_offset = CalculateYOffset(rect.fLeft, rect.fTop, y_stride);
- int uv_offset = CalculateUVOffset(rect.fLeft, rect.fTop, uv_stride);
+ int rgb_offset = CalculateRGBOffset(rect.left(), rect.top(), rgb_stride);
+ int y_offset = CalculateYOffset(rect.left(), rect.top(), y_stride);
+ int uv_offset = CalculateUVOffset(rect.left(), rect.top(), uv_stride);
media::ConvertYUVToRGB32(y_plane + y_offset,
u_plane + uv_offset,
@@ -86,14 +86,14 @@ void ScaleYUVToRGB32WithRect(const uint8* y_plane,
int y_stride,
int uv_stride,
int rgb_stride) {
- int rgb_offset = CalculateRGBOffset(dest_rect.fLeft,
- dest_rect.fTop,
+ int rgb_offset = CalculateRGBOffset(dest_rect.left(),
+ dest_rect.top(),
rgb_stride);
- int y_offset = CalculateYOffset(source_rect.fLeft,
- source_rect.fTop,
+ int y_offset = CalculateYOffset(source_rect.left(),
+ source_rect.top(),
y_stride);
- int uv_offset = CalculateUVOffset(source_rect.fLeft,
- source_rect.fTop,
+ int uv_offset = CalculateUVOffset(source_rect.left(),
+ source_rect.top(),
uv_stride);
media::ScaleYUVToRGB32(y_plane + y_offset,
@@ -143,20 +143,22 @@ int RoundToTwosMultiple(int x) {
}
SkIRect AlignRect(const SkIRect& rect) {
- int x = RoundToTwosMultiple(rect.fLeft);
- int y = RoundToTwosMultiple(rect.fTop);
- int right = RoundToTwosMultiple(rect.fRight + 1);
- int bottom = RoundToTwosMultiple(rect.fBottom + 1);
- return SkIRect::MakeXYWH(x, y, right - x, bottom - y);
+ int x = RoundToTwosMultiple(rect.left());
+ int y = RoundToTwosMultiple(rect.top());
+ int right = RoundToTwosMultiple(rect.right() + 1);
+ int bottom = RoundToTwosMultiple(rect.bottom() + 1);
+ return SkIRect::MakeLTRB(x, y, right, bottom);
}
SkIRect ScaleRect(const SkIRect& rect,
- double horizontal_ratio,
- double vertical_ratio) {
- int left = floor(rect.left() * horizontal_ratio);
- int top = floor(rect.top() * vertical_ratio);
- int right = ceil(rect.right() * horizontal_ratio);
- int bottom = ceil(rect.bottom() * vertical_ratio);
+ const SkISize& in_size,
+ const SkISize& out_size) {
+ int left = (rect.left() * out_size.width()) / in_size.width();
+ int top = (rect.top() * out_size.height()) / in_size.height();
+ int right = (rect.right() * out_size.width() + out_size.width() - 1) /
+ in_size.width();
+ int bottom = (rect.bottom() * out_size.height() + out_size.height() - 1) /
+ in_size.height();
return SkIRect::MakeLTRB(left, top, right, bottom);
}
@@ -166,10 +168,10 @@ void CopyRect(const uint8* src_plane,
int dest_plane_stride,
int bytes_per_pixel,
const SkIRect& rect) {
- // Get the address of the starting point.
- const int src_y_offset = src_plane_stride * rect.fTop;
- const int dest_y_offset = dest_plane_stride * rect.fTop;
- const int x_offset = bytes_per_pixel * rect.fLeft;
+ // Get the address of the starting point.
+ const int src_y_offset = src_plane_stride * rect.top();
+ const int dest_y_offset = dest_plane_stride * rect.top();
+ const int x_offset = bytes_per_pixel * rect.left();
src_plane += src_y_offset + x_offset;
dest_plane += dest_y_offset + x_offset;
diff --git a/remoting/base/util.h b/remoting/base/util.h
index cf2b2dd..8bed6f4 100644
--- a/remoting/base/util.h
+++ b/remoting/base/util.h
@@ -54,12 +54,12 @@ int RoundToTwosMultiple(int x);
// Align the sides of the rectangle to multiples of 2 (expanding outwards).
SkIRect AlignRect(const SkIRect& rect);
-// Scale a rectangle by horizontal and vertical factors. If the result has
-// non-integer coordinates then the smallest integer-coordinate rectangle that
-// wholly encloses it is returned.
+// Scales the supplied rectangle from |in_size| coordinates to |out_size|.
+// If the result has non-integer coordinates then the smallest integer-
+// coordinate rectangle that wholly encloses it is returned.
SkIRect ScaleRect(const SkIRect& rect,
- double horizontal_ratio,
- double vertical_ratio);
+ const SkISize& in_size,
+ const SkISize& out_size);
// Copy pixels in the rectangle from source to destination.
void CopyRect(const uint8* src_plane,
diff --git a/remoting/client/chromoting_client.cc b/remoting/client/chromoting_client.cc
index 60bb4e6..6f10746 100644
--- a/remoting/client/chromoting_client.cc
+++ b/remoting/client/chromoting_client.cc
@@ -7,7 +7,6 @@
#include "base/bind.h"
#include "remoting/client/chromoting_view.h"
#include "remoting/client/client_context.h"
-#include "remoting/client/input_handler.h"
#include "remoting/client/rectangle_update_decoder.h"
#include "remoting/protocol/connection_to_host.h"
#include "remoting/protocol/session_config.h"
@@ -27,14 +26,12 @@ ChromotingClient::ChromotingClient(const ClientConfig& config,
protocol::ConnectionToHost* connection,
ChromotingView* view,
RectangleUpdateDecoder* rectangle_decoder,
- InputHandler* input_handler,
const base::Closure& client_done)
: config_(config),
context_(context),
connection_(connection),
view_(view),
rectangle_decoder_(rectangle_decoder),
- input_handler_(input_handler),
client_done_(client_done),
packet_being_processed_(false),
last_sequence_number_(0),
@@ -205,9 +202,6 @@ void ChromotingClient::Initialize() {
// Initialize the decoder.
rectangle_decoder_->Initialize(connection_->config());
-
- // Schedule the input handler to process the event queue.
- input_handler_->Initialize();
}
} // namespace remoting
diff --git a/remoting/client/chromoting_client.h b/remoting/client/chromoting_client.h
index a0bea89..756c388 100644
--- a/remoting/client/chromoting_client.h
+++ b/remoting/client/chromoting_client.h
@@ -26,7 +26,6 @@ class MessageLoop;
namespace remoting {
class ClientContext;
-class InputHandler;
class RectangleUpdateDecoder;
// TODO(sergeyu): Move VideoStub implementation to RectangleUpdateDecoder.
@@ -40,7 +39,6 @@ class ChromotingClient : public protocol::ConnectionToHost::HostEventCallback,
protocol::ConnectionToHost* connection,
ChromotingView* view,
RectangleUpdateDecoder* rectangle_decoder,
- InputHandler* input_handler,
const base::Closure& client_done);
virtual ~ChromotingClient();
@@ -94,7 +92,6 @@ class ChromotingClient : public protocol::ConnectionToHost::HostEventCallback,
protocol::ConnectionToHost* connection_;
ChromotingView* view_;
RectangleUpdateDecoder* rectangle_decoder_;
- InputHandler* input_handler_;
// If non-NULL, this is called when the client is done.
base::Closure client_done_;
diff --git a/remoting/client/chromoting_view.cc b/remoting/client/chromoting_view.cc
deleted file mode 100644
index 23138d0..0000000
--- a/remoting/client/chromoting_view.cc
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "remoting/client/chromoting_view.h"
-
-#include "base/message_loop.h"
-#include "base/synchronization/waitable_event.h"
-
-namespace remoting {
-
-ChromotingView::ChromotingView()
- : frame_width_(0),
- frame_height_(0) {
-}
-
-ChromotingView::~ChromotingView() {}
-
-// TODO(garykac): This assumes a single screen. This will need to be adjusted
-// to add support for mulitple monitors.
-void ChromotingView::GetScreenSize(int* width, int* height) {
- *width = frame_width_;
- *height = frame_height_;
-}
-
-} // namespace remoting
diff --git a/remoting/client/chromoting_view.h b/remoting/client/chromoting_view.h
index 17b24e3..e93ab0d 100644
--- a/remoting/client/chromoting_view.h
+++ b/remoting/client/chromoting_view.h
@@ -5,10 +5,7 @@
#ifndef REMOTING_CLIENT_CHROMOTING_VIEW_H_
#define REMOTING_CLIENT_CHROMOTING_VIEW_H_
-#include <string>
-
-#include "base/memory/ref_counted.h"
-#include "media/base/video_frame.h"
+#include "base/basictypes.h"
#include "remoting/protocol/connection_to_host.h"
namespace remoting {
@@ -22,12 +19,7 @@ static const uint32 kFailedColor = 0xffcc00ff;
// screen.
class ChromotingView {
public:
- ChromotingView();
- virtual ~ChromotingView();
-
- // Get screen dimensions.
- // TODO(garykac): This will need to be extended to support multi-monitors.
- void GetScreenSize(int* width, int* height);
+ virtual ~ChromotingView() {}
// Initialize the common structures for the view.
virtual bool Initialize() = 0;
@@ -49,20 +41,6 @@ class ChromotingView {
// Record the update the state of the connection, updating the UI as needed.
virtual void SetConnectionState(protocol::ConnectionToHost::State state,
protocol::ConnectionToHost::Error error) = 0;
-
- // Return the horizontal scale factor of this view.
- virtual double GetHorizontalScaleRatio() const = 0;
-
- // Return the vertical scale factor of this view.
- virtual double GetVerticalScaleRatio() const = 0;
-
- protected:
- // Framebuffer for the decoder.
- scoped_refptr<media::VideoFrame> frame_;
-
- // Dimensions of |frame_| bitmap.
- int frame_width_;
- int frame_height_;
};
} // namespace remoting
diff --git a/remoting/client/input_handler.cc b/remoting/client/input_handler.cc
deleted file mode 100644
index 48bedde..0000000
--- a/remoting/client/input_handler.cc
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "remoting/client/input_handler.h"
-
-#include "remoting/client/chromoting_view.h"
-#include "remoting/proto/event.pb.h"
-#include "remoting/protocol/connection_to_host.h"
-#include "remoting/protocol/input_stub.h"
-
-namespace remoting {
-
-using protocol::KeyEvent;
-using protocol::MouseEvent;
-
-InputHandler::InputHandler(ClientContext* context,
- protocol::ConnectionToHost* connection,
- ChromotingView* view)
- : context_(context),
- connection_(connection),
- view_(view) {
-}
-
-InputHandler::~InputHandler() {
-}
-
-void InputHandler::SendKeyEvent(bool press, int keycode) {
- protocol::InputStub* stub = connection_->input_stub();
- if (stub) {
- if (press) {
- pressed_keys_.insert(keycode);
- } else {
- pressed_keys_.erase(keycode);
- }
-
- KeyEvent event;
- event.set_keycode(keycode);
- event.set_pressed(press);
- stub->InjectKeyEvent(event);
- }
-}
-
-void InputHandler::SendMouseMoveEvent(int x, int y) {
- protocol::InputStub* stub = connection_->input_stub();
- if (stub) {
- MouseEvent event;
- event.set_x(x);
- event.set_y(y);
- stub->InjectMouseEvent(event);
- }
-}
-
-void InputHandler::SendMouseButtonEvent(bool button_down,
- MouseEvent::MouseButton button) {
- protocol::InputStub* stub = connection_->input_stub();
- if (stub) {
- MouseEvent event;
- event.set_button(button);
- event.set_button_down(button_down);
- stub->InjectMouseEvent(event);
- }
-}
-
-void InputHandler::SendMouseWheelEvent(int dx, int dy) {
- protocol::InputStub* stub = connection_->input_stub();
- if (stub) {
- MouseEvent event;
- event.set_wheel_offset_x(dx);
- event.set_wheel_offset_y(dy);
- stub->InjectMouseEvent(event);
- }
-}
-
-void InputHandler::ReleaseAllKeys() {
- std::set<int> pressed_keys_copy = pressed_keys_;
- std::set<int>::iterator i;
- for (i = pressed_keys_copy.begin(); i != pressed_keys_copy.end(); ++i) {
- SendKeyEvent(false, *i);
- }
- pressed_keys_.clear();
-}
-
-} // namespace remoting
diff --git a/remoting/client/input_handler.h b/remoting/client/input_handler.h
deleted file mode 100644
index e6082a2..0000000
--- a/remoting/client/input_handler.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef REMOTING_CLIENT_INPUT_HANDLER_H_
-#define REMOTING_CLIENT_INPUT_HANDLER_H_
-
-#include <set>
-
-#include "base/basictypes.h"
-#include "remoting/proto/event.pb.h"
-
-namespace remoting {
-
-class ClientContext;
-class ChromotingView;
-
-namespace protocol {
-class ConnectionToHost;
-} // namespace protocol
-
-class InputHandler {
- public:
- InputHandler(ClientContext* context,
- protocol::ConnectionToHost* connection,
- ChromotingView* view);
- virtual ~InputHandler();
-
- virtual void Initialize() = 0;
-
- void ReleaseAllKeys();
-
- protected:
- void SendKeyEvent(bool press, int keycode);
- void SendMouseMoveEvent(int x, int y);
- void SendMouseButtonEvent(bool down,
- protocol::MouseEvent::MouseButton button);
- void SendMouseWheelEvent(int dx, int dy);
-
- ClientContext* context_;
- protocol::ConnectionToHost* connection_;
- ChromotingView* view_;
-
- private:
- std::set<int> pressed_keys_;
-
- DISALLOW_COPY_AND_ASSIGN(InputHandler);
-};
-
-} // namespace remoting
-
-#endif // REMOTING_CLIENT_INPUT_HANDLER_H_
diff --git a/remoting/client/mouse_input_filter.cc b/remoting/client/mouse_input_filter.cc
new file mode 100644
index 0000000..49e33a8
--- /dev/null
+++ b/remoting/client/mouse_input_filter.cc
@@ -0,0 +1,49 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "remoting/client/mouse_input_filter.h"
+
+#include "remoting/proto/event.pb.h"
+
+namespace remoting {
+
+MouseInputFilter::MouseInputFilter(protocol::InputStub* input_stub)
+ : input_stub_(input_stub) {
+ input_size_.setEmpty();
+ output_size_.setEmpty();
+}
+
+MouseInputFilter::~MouseInputFilter() {
+}
+
+void MouseInputFilter::InjectKeyEvent(const protocol::KeyEvent& event) {
+ input_stub_->InjectKeyEvent(event);
+}
+
+void MouseInputFilter::InjectMouseEvent(const protocol::MouseEvent& event) {
+ if (input_size_.isZero() || output_size_.isZero())
+ return;
+
+ protocol::MouseEvent out_event(event);
+ if (out_event.has_x()) {
+ int x = (out_event.x() * output_size_.width()) / input_size_.width();
+ out_event.set_x(std::max(0, std::min(output_size_.width() - 1, x)));
+ }
+ if (out_event.has_y()) {
+ int y = (out_event.y() * output_size_.height()) / input_size_.height();
+ out_event.set_y(std::max(0, std::min(output_size_.height() - 1, y)));
+ }
+
+ input_stub_->InjectMouseEvent(out_event);
+}
+
+void MouseInputFilter::set_input_size(const SkISize& size) {
+ input_size_ = size;
+}
+
+void MouseInputFilter::set_output_size(const SkISize& size) {
+ output_size_ = size;
+}
+
+} // namespace remoting
diff --git a/remoting/client/mouse_input_filter.h b/remoting/client/mouse_input_filter.h
new file mode 100644
index 0000000..0c2a0d9
--- /dev/null
+++ b/remoting/client/mouse_input_filter.h
@@ -0,0 +1,45 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef REMOTING_CLIENT_MOUSE_INPUT_FILTER_H_
+#define REMOTING_CLIENT_MOUSE_INPUT_FILTER_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "remoting/protocol/input_stub.h"
+#include "third_party/skia/include/core/SkTypes.h"
+#include "third_party/skia/include/core/SkSize.h"
+
+namespace remoting {
+
+// Filtering InputStub implementation which scales mouse events based on the
+// supplied input and output dimensions, and clamps their coordinates to the
+// output dimensions, before passing events on to |input_stub|.
+class MouseInputFilter : public protocol::InputStub {
+ public:
+ MouseInputFilter(protocol::InputStub* input_stub);
+ virtual ~MouseInputFilter();
+
+ // Specify the input dimensions for mouse events.
+ void set_input_size(const SkISize& size);
+
+ // Specify the output dimensions.
+ void set_output_size(const SkISize& size);
+
+ // InputStub interface.
+ virtual void InjectKeyEvent(const protocol::KeyEvent& event) OVERRIDE;
+ virtual void InjectMouseEvent(const protocol::MouseEvent& event) OVERRIDE;
+
+ private:
+ protocol::InputStub* input_stub_;
+
+ SkISize input_size_;
+ SkISize output_size_;
+
+ DISALLOW_COPY_AND_ASSIGN(MouseInputFilter);
+};
+
+} // namespace remoting
+
+#endif // REMOTING_CLIENT_MOUSE_INPUT_FILTER_H_
diff --git a/remoting/client/plugin/chromoting_instance.cc b/remoting/client/plugin/chromoting_instance.cc
index e6dea0e..d3f7b62 100644
--- a/remoting/client/plugin/chromoting_instance.cc
+++ b/remoting/client/plugin/chromoting_instance.cc
@@ -24,14 +24,15 @@
#include "remoting/base/util.h"
#include "remoting/client/client_config.h"
#include "remoting/client/chromoting_client.h"
+#include "remoting/client/mouse_input_filter.h"
#include "remoting/client/plugin/chromoting_scriptable_object.h"
#include "remoting/client/plugin/pepper_input_handler.h"
#include "remoting/client/plugin/pepper_view.h"
-#include "remoting/client/plugin/pepper_view_proxy.h"
#include "remoting/client/plugin/pepper_xmpp_proxy.h"
#include "remoting/client/rectangle_update_decoder.h"
#include "remoting/protocol/connection_to_host.h"
#include "remoting/protocol/host_stub.h"
+#include "remoting/protocol/key_event_tracker.h"
namespace remoting {
@@ -82,16 +83,11 @@ ChromotingInstance::~ChromotingInstance() {
done_event.Wait();
}
- // Stopping the context shutdown all chromoting threads. This is a requirement
- // before we can call Detach() on |view_proxy_|.
+ // Stopping the context shuts down all chromoting threads.
context_.Stop();
- if (view_proxy_.get()) {
- view_proxy_->Detach();
- }
-
// Delete |thread_proxy_| before we detach |plugin_message_loop_|,
- // otherwise ScopedThreadProxy may DCHECK when destroying.
+ // otherwise ScopedThreadProxy may DCHECK when being destroyed.
thread_proxy_.reset();
plugin_message_loop_->Detach();
@@ -117,9 +113,8 @@ bool ChromotingInstance::Init(uint32_t argc,
// Create the chromoting objects that don't depend on the network connection.
view_.reset(new PepperView(this, &context_));
- view_proxy_ = new PepperViewProxy(this, view_.get(), plugin_message_loop_);
rectangle_decoder_ = new RectangleUpdateDecoder(
- context_.decode_message_loop(), view_proxy_);
+ context_.decode_message_loop(), view_.get());
// Default to a medium grey.
view_->SetSolidFill(0xFFCDCDCD);
@@ -132,14 +127,9 @@ void ChromotingInstance::Connect(const ClientConfig& config) {
host_connection_.reset(new protocol::ConnectionToHost(
context_.network_message_loop(), this, true));
-
- input_handler_.reset(new PepperInputHandler(&context_,
- host_connection_.get(),
- view_proxy_));
-
client_.reset(new ChromotingClient(config, &context_, host_connection_.get(),
- view_proxy_, rectangle_decoder_.get(),
- input_handler_.get(), base::Closure()));
+ view_.get(), rectangle_decoder_.get(),
+ base::Closure()));
LOG(INFO) << "Connecting to " << config.host_jid
<< ". Local jid: " << config.local_jid << ".";
@@ -175,6 +165,8 @@ void ChromotingInstance::Disconnect() {
}
input_handler_.reset();
+ key_event_tracker_.reset();
+ mouse_input_filter_.reset();
host_connection_.reset();
GetScriptableObject()->SetConnectionStatus(
@@ -186,87 +178,44 @@ void ChromotingInstance::DidChangeView(const pp::Rect& position,
const pp::Rect& clip) {
DCHECK(plugin_message_loop_->BelongsToCurrentThread());
- view_->SetPluginSize(SkISize::Make(position.width(), position.height()));
-
- // TODO(wez): Pass the dimensions of the plugin to the RectangleDecoder
- // and let it generate the necessary refresh events.
- // If scale-to-fit is enabled then update the scaling ratios.
- // We also force a full-frame refresh, in case the ratios changed.
- if (scale_to_fit_) {
- rectangle_decoder_->SetScaleRatios(view_->GetHorizontalScaleRatio(),
- view_->GetVerticalScaleRatio());
- rectangle_decoder_->RefreshFullFrame();
+ SkISize new_size = SkISize::Make(position.width(), position.height());
+ if (view_->SetViewSize(new_size)) {
+ if (mouse_input_filter_.get()) {
+ mouse_input_filter_->set_input_size(new_size);
+ }
+ rectangle_decoder_->SetOutputSize(new_size);
}
- // Notify the RectangleDecoder of the new clip rect.
rectangle_decoder_->UpdateClipRect(
SkIRect::MakeXYWH(clip.x(), clip.y(), clip.width(), clip.height()));
}
bool ChromotingInstance::HandleInputEvent(const pp::InputEvent& event) {
DCHECK(plugin_message_loop_->BelongsToCurrentThread());
- if (!input_handler_.get()) {
+
+ // Never inject events if the end of the input pipeline doesn't exist.
+ // If it does exist but the pipeline doesn't, construct a pipeline.
+ // TODO(wez): This is really ugly. We should create the pipeline when
+ // the ConnectionToHost's InputStub exists.
+ if (!host_connection_.get()) {
return false;
+ } else if (!input_handler_.get()) {
+ protocol::InputStub* input_stub = host_connection_->input_stub();
+ if (!input_stub)
+ return false;
+ mouse_input_filter_.reset(new MouseInputFilter(input_stub));
+ mouse_input_filter_->set_input_size(view_->get_view_size());
+ key_event_tracker_.reset(
+ new protocol::KeyEventTracker(mouse_input_filter_.get()));
+ input_handler_.reset(
+ new PepperInputHandler(key_event_tracker_.get()));
}
- PepperInputHandler* pih
- = static_cast<PepperInputHandler*>(input_handler_.get());
-
- switch (event.GetType()) {
- case PP_INPUTEVENT_TYPE_MOUSEDOWN: {
- pih->HandleMouseButtonEvent(true, pp::MouseInputEvent(event));
- return true;
- }
-
- case PP_INPUTEVENT_TYPE_MOUSEUP: {
- pih->HandleMouseButtonEvent(false, pp::MouseInputEvent(event));
- return true;
- }
-
- case PP_INPUTEVENT_TYPE_MOUSEMOVE:
- case PP_INPUTEVENT_TYPE_MOUSEENTER:
- case PP_INPUTEVENT_TYPE_MOUSELEAVE: {
- pih->HandleMouseMoveEvent(pp::MouseInputEvent(event));
- return true;
- }
-
- case PP_INPUTEVENT_TYPE_WHEEL: {
- pih->HandleMouseWheelEvent(pp::WheelInputEvent(event));
- return true;
- }
-
- case PP_INPUTEVENT_TYPE_CONTEXTMENU: {
- // We need to return true here or else we'll get a local (plugin) context
- // menu instead of the mouseup event for the right click.
- return true;
- }
-
- case PP_INPUTEVENT_TYPE_KEYDOWN: {
- pp::KeyboardInputEvent key = pp::KeyboardInputEvent(event);
- VLOG(3) << "PP_INPUTEVENT_TYPE_KEYDOWN" << " key=" << key.GetKeyCode();
- pih->HandleKeyEvent(true, key);
- return true;
- }
+ // TODO(wez): When we have a good hook into Host dimensions changes, move
+ // this there.
+ mouse_input_filter_->set_output_size(view_->get_host_size());
- case PP_INPUTEVENT_TYPE_KEYUP: {
- pp::KeyboardInputEvent key = pp::KeyboardInputEvent(event);
- VLOG(3) << "PP_INPUTEVENT_TYPE_KEYUP" << " key=" << key.GetKeyCode();
- pih->HandleKeyEvent(false, key);
- return true;
- }
-
- case PP_INPUTEVENT_TYPE_CHAR: {
- pih->HandleCharacterEvent(pp::KeyboardInputEvent(event));
- return true;
- }
-
- default: {
- LOG(INFO) << "Unhandled input event: " << event.GetType();
- break;
- }
- }
-
- return false;
+ return input_handler_->HandleInputEvent(event);
}
ChromotingScriptableObject* ChromotingInstance::GetScriptableObject() {
@@ -280,25 +229,6 @@ ChromotingScriptableObject* ChromotingInstance::GetScriptableObject() {
return NULL;
}
-void ChromotingInstance::SetScaleToFit(bool scale_to_fit) {
- DCHECK(plugin_message_loop_->BelongsToCurrentThread());
-
- if (scale_to_fit == scale_to_fit_)
- return;
-
- scale_to_fit_ = scale_to_fit;
- if (scale_to_fit) {
- rectangle_decoder_->SetScaleRatios(view_->GetHorizontalScaleRatio(),
- view_->GetVerticalScaleRatio());
- } else {
- rectangle_decoder_->SetScaleRatios(1.0, 1.0);
- }
-
- // TODO(wez): The RectangleDecoder should generate refresh events
- // as necessary in response to any scaling change.
- rectangle_decoder_->RefreshFullFrame();
-}
-
// static
void ChromotingInstance::RegisterLogMessageHandler() {
base::AutoLock lock(g_logging_lock.Get());
@@ -403,11 +333,9 @@ ChromotingStats* ChromotingInstance::GetStats() {
}
void ChromotingInstance::ReleaseAllKeys() {
- if (!input_handler_.get()) {
- return;
+ if (key_event_tracker_.get()) {
+ key_event_tracker_->ReleaseAllKeys();
}
-
- input_handler_->ReleaseAllKeys();
}
} // namespace remoting
diff --git a/remoting/client/plugin/chromoting_instance.h b/remoting/client/plugin/chromoting_instance.h
index 427d420..2b11b5a 100644
--- a/remoting/client/plugin/chromoting_instance.h
+++ b/remoting/client/plugin/chromoting_instance.h
@@ -32,14 +32,15 @@ namespace remoting {
namespace protocol {
class ConnectionToHost;
+class KeyEventTracker;
} // namespace protocol
class ChromotingClient;
class ChromotingStats;
class ClientContext;
-class InputHandler;
+class MouseInputFilter;
+class PepperInputHandler;
class PepperView;
-class PepperViewProxy;
class RectangleUpdateDecoder;
struct ClientConfig;
@@ -118,16 +119,10 @@ class ChromotingInstance : public pp::InstancePrivate {
// True if scale to fit is enabled.
bool scale_to_fit_;
- // PepperViewProxy is refcounted and used to interface between chromoting
- // objects and PepperView and perform thread switching. It wraps around
- // |view_| and receives method calls on chromoting threads. These method
- // calls are then delegates on the pepper thread. During destruction of
- // ChromotingInstance we need to detach PepperViewProxy from PepperView since
- // both ChromotingInstance and PepperView are destroyed and there will be
- // outstanding tasks on the pepper message loop.
- scoped_refptr<PepperViewProxy> view_proxy_;
scoped_refptr<RectangleUpdateDecoder> rectangle_decoder_;
- scoped_ptr<InputHandler> input_handler_;
+ scoped_ptr<MouseInputFilter> mouse_input_filter_;
+ scoped_ptr<protocol::KeyEventTracker> key_event_tracker_;
+ scoped_ptr<PepperInputHandler> input_handler_;
scoped_ptr<ChromotingClient> client_;
// XmppProxy is a refcounted interface used to perform thread-switching and
diff --git a/remoting/client/plugin/chromoting_scriptable_object.cc b/remoting/client/plugin/chromoting_scriptable_object.cc
index 218c3c9..1185570 100644
--- a/remoting/client/plugin/chromoting_scriptable_object.cc
+++ b/remoting/client/plugin/chromoting_scriptable_object.cc
@@ -103,9 +103,11 @@ void ChromotingScriptableObject::Init() {
AddMethod("connect", &ChromotingScriptableObject::DoConnect);
AddMethod("disconnect", &ChromotingScriptableObject::DoDisconnect);
- AddMethod("setScaleToFit", &ChromotingScriptableObject::DoSetScaleToFit);
AddMethod("onIq", &ChromotingScriptableObject::DoOnIq);
AddMethod("releaseAllKeys", &ChromotingScriptableObject::DoReleaseAllKeys);
+
+ // Older versions of the web app expect a setScaleToFit method.
+ AddMethod("setScaleToFit", &ChromotingScriptableObject::DoNothing);
}
bool ChromotingScriptableObject::HasProperty(const Var& name, Var* exception) {
@@ -410,20 +412,8 @@ Var ChromotingScriptableObject::DoDisconnect(const std::vector<Var>& args,
return Var();
}
-Var ChromotingScriptableObject::DoSetScaleToFit(const std::vector<Var>& args,
- Var* exception) {
- if (args.size() != 1) {
- *exception = Var("Usage: setScaleToFit(scale_to_fit)");
- return Var();
- }
-
- if (!args[0].is_bool()) {
- *exception = Var("scale_to_fit must be a boolean.");
- return Var();
- }
-
- VLOG(1) << "Setting scale-to-fit.";
- instance_->SetScaleToFit(args[0].AsBool());
+Var ChromotingScriptableObject::DoNothing(const std::vector<Var>& args,
+ Var* exception) {
return Var();
}
diff --git a/remoting/client/plugin/chromoting_scriptable_object.h b/remoting/client/plugin/chromoting_scriptable_object.h
index ece9003..8e50797 100644
--- a/remoting/client/plugin/chromoting_scriptable_object.h
+++ b/remoting/client/plugin/chromoting_scriptable_object.h
@@ -215,8 +215,8 @@ class ChromotingScriptableObject
pp::Var DoConnect(const std::vector<pp::Var>& args, pp::Var* exception);
pp::Var DoDisconnect(const std::vector<pp::Var>& args, pp::Var* exception);
- // This method is called by JS to set scale-to-fit.
- pp::Var DoSetScaleToFit(const std::vector<pp::Var>& args, pp::Var* exception);
+ // This method is used for legacy script APIs such as setScaleToFit.
+ pp::Var DoNothing(const std::vector<pp::Var>& args, pp::Var* exception);
// This method is called by Javascript to provide responses to sendIq()
// requests.
diff --git a/remoting/client/plugin/pepper_input_handler.cc b/remoting/client/plugin/pepper_input_handler.cc
index 1fe6f6e..c505df1 100644
--- a/remoting/client/plugin/pepper_input_handler.cc
+++ b/remoting/client/plugin/pepper_input_handler.cc
@@ -4,91 +4,102 @@
#include "remoting/client/plugin/pepper_input_handler.h"
+#include "base/logging.h"
#include "ppapi/cpp/input_event.h"
#include "ppapi/cpp/point.h"
-#include "remoting/client/plugin/pepper_view_proxy.h"
+#include "remoting/proto/event.pb.h"
namespace remoting {
-using protocol::MouseEvent;
-
-PepperInputHandler::PepperInputHandler(ClientContext* context,
- protocol::ConnectionToHost* connection,
- PepperViewProxy* view)
- : InputHandler(context, connection, view),
- pepper_view_(view),
- wheel_ticks_x_(0),
- wheel_ticks_y_(0) {
+PepperInputHandler::PepperInputHandler(protocol::InputStub* input_stub)
+ : input_stub_(input_stub), wheel_ticks_x_(0), wheel_ticks_y_(0)
+{
}
PepperInputHandler::~PepperInputHandler() {
}
-void PepperInputHandler::Initialize() {
-}
-
-void PepperInputHandler::HandleKeyEvent(bool keydown,
- const pp::KeyboardInputEvent& event) {
- SendKeyEvent(keydown, event.GetKeyCode());
-}
-
-void PepperInputHandler::HandleCharacterEvent(
- const pp::KeyboardInputEvent& event) {
- // TODO(garykac): Coordinate key and char events.
-}
-
-void PepperInputHandler::HandleMouseMoveEvent(
- const pp::MouseInputEvent& event) {
- SkIPoint p(SkIPoint::Make(event.GetPosition().x(), event.GetPosition().y()));
- // Pepper gives co-ordinates in the plugin instance's co-ordinate system,
- // which may be different from the host desktop's co-ordinate system.
- double horizontal_ratio = view_->GetHorizontalScaleRatio();
- double vertical_ratio = view_->GetVerticalScaleRatio();
-
- if (horizontal_ratio == 0.0)
- horizontal_ratio = 1.0;
- if (vertical_ratio == 0.0)
- vertical_ratio = 1.0;
-
- SendMouseMoveEvent(p.x() / horizontal_ratio, p.y() / vertical_ratio);
-}
-
-void PepperInputHandler::HandleMouseButtonEvent(
- bool button_down,
- const pp::MouseInputEvent& event) {
- MouseEvent::MouseButton button = MouseEvent::BUTTON_UNDEFINED;
- switch (event.GetButton()) {
- case PP_INPUTEVENT_MOUSEBUTTON_LEFT:
- button = MouseEvent::BUTTON_LEFT;
- break;
- case PP_INPUTEVENT_MOUSEBUTTON_MIDDLE:
- button = MouseEvent::BUTTON_MIDDLE;
- break;
- case PP_INPUTEVENT_MOUSEBUTTON_RIGHT:
- button = MouseEvent::BUTTON_RIGHT;
- break;
- case PP_INPUTEVENT_MOUSEBUTTON_NONE:
- // Leave button undefined.
+bool PepperInputHandler::HandleInputEvent(const pp::InputEvent& event) {
+ switch (event.GetType()) {
+ case PP_INPUTEVENT_TYPE_CONTEXTMENU: {
+ // We need to return true here or else we'll get a local (plugin) context
+ // menu instead of the mouseup event for the right click.
+ return true;
+ }
+
+ case PP_INPUTEVENT_TYPE_KEYDOWN:
+ case PP_INPUTEVENT_TYPE_KEYUP: {
+ pp::KeyboardInputEvent pp_key_event(event);
+ protocol::KeyEvent key_event;
+ key_event.set_keycode(pp_key_event.GetKeyCode());
+ key_event.set_pressed(event.GetType() == PP_INPUTEVENT_TYPE_KEYDOWN);
+ input_stub_->InjectKeyEvent(key_event);
+ return true;
+ }
+
+ case PP_INPUTEVENT_TYPE_MOUSEDOWN:
+ case PP_INPUTEVENT_TYPE_MOUSEUP: {
+ pp::MouseInputEvent pp_mouse_event(event);
+ protocol::MouseEvent mouse_event;
+ switch (pp_mouse_event.GetButton()) {
+ case PP_INPUTEVENT_MOUSEBUTTON_LEFT:
+ mouse_event.set_button(protocol::MouseEvent::BUTTON_LEFT);
+ break;
+ case PP_INPUTEVENT_MOUSEBUTTON_MIDDLE:
+ mouse_event.set_button(protocol::MouseEvent::BUTTON_MIDDLE);
+ break;
+ case PP_INPUTEVENT_MOUSEBUTTON_RIGHT:
+ mouse_event.set_button(protocol::MouseEvent::BUTTON_RIGHT);
+ break;
+ case PP_INPUTEVENT_MOUSEBUTTON_NONE:
+ break;
+ }
+ if (mouse_event.has_button()) {
+ bool is_down = (event.GetType() == PP_INPUTEVENT_TYPE_MOUSEDOWN);
+ mouse_event.set_button_down(is_down);
+ input_stub_->InjectMouseEvent(mouse_event);
+ }
+ return true;
+ }
+
+ case PP_INPUTEVENT_TYPE_MOUSEMOVE:
+ case PP_INPUTEVENT_TYPE_MOUSEENTER:
+ case PP_INPUTEVENT_TYPE_MOUSELEAVE: {
+ pp::MouseInputEvent pp_mouse_event(event);
+ protocol::MouseEvent mouse_event;
+ mouse_event.set_x(pp_mouse_event.GetPosition().x());
+ mouse_event.set_y(pp_mouse_event.GetPosition().y());
+ input_stub_->InjectMouseEvent(mouse_event);
+ return true;
+ }
+
+ case PP_INPUTEVENT_TYPE_WHEEL: {
+ pp::WheelInputEvent pp_wheel_event(event);
+
+ pp::FloatPoint ticks = pp_wheel_event.GetTicks();
+ wheel_ticks_x_ += ticks.x();
+ wheel_ticks_y_ += ticks.y();
+
+ int ticks_x = static_cast<int>(wheel_ticks_x_);
+ int ticks_y = static_cast<int>(wheel_ticks_y_);
+ if (ticks_x != 0 || ticks_y != 0) {
+ wheel_ticks_x_ -= ticks_x;
+ wheel_ticks_y_ -= ticks_y;
+ protocol::MouseEvent mouse_event;
+ mouse_event.set_wheel_offset_x(wheel_ticks_x_);
+ mouse_event.set_wheel_offset_y(wheel_ticks_y_);
+ input_stub_->InjectMouseEvent(mouse_event);
+ }
+ return true;
+ }
+
+ default: {
+ LOG(INFO) << "Unhandled input event: " << event.GetType();
break;
+ }
}
- if (button != MouseEvent::BUTTON_UNDEFINED) {
- SendMouseButtonEvent(button_down, button);
- }
-}
-
-void PepperInputHandler::HandleMouseWheelEvent(
- const pp::WheelInputEvent& event) {
- pp::FloatPoint ticks = event.GetTicks();
- wheel_ticks_x_ += ticks.x();
- wheel_ticks_y_ += ticks.y();
- int ticks_x = static_cast<int>(wheel_ticks_x_);
- int ticks_y = static_cast<int>(wheel_ticks_y_);
- if (ticks_x != 0 || ticks_y != 0) {
- wheel_ticks_x_ -= ticks_x;
- wheel_ticks_y_ -= ticks_y;
- SendMouseWheelEvent(ticks_x, ticks_y);
- }
+ return false;
}
} // namespace remoting
diff --git a/remoting/client/plugin/pepper_input_handler.h b/remoting/client/plugin/pepper_input_handler.h
index 759e5f2..9c9423e 100644
--- a/remoting/client/plugin/pepper_input_handler.h
+++ b/remoting/client/plugin/pepper_input_handler.h
@@ -6,37 +6,27 @@
#define REMOTING_CLIENT_PLUGIN_PEPPER_INPUT_HANDLER_H_
#include "base/compiler_specific.h"
-#include "remoting/client/input_handler.h"
+#include "remoting/protocol/input_stub.h"
namespace pp {
-class KeyboardInputEvent;
-class MouseInputEvent;
-class WheelInputEvent;
-}
+class InputEvent;
+} // namespace pp
namespace remoting {
-class PepperViewProxy;
+namespace protocol {
+class InputStub;
+} // namespace protocol
-class PepperInputHandler : public InputHandler {
+class PepperInputHandler {
public:
- PepperInputHandler(ClientContext* context,
- protocol::ConnectionToHost* connection,
- PepperViewProxy* view);
+ PepperInputHandler(protocol::InputStub* input_stub);
virtual ~PepperInputHandler();
- virtual void Initialize() OVERRIDE;
-
- void HandleKeyEvent(bool keydown, const pp::KeyboardInputEvent& event);
- void HandleCharacterEvent(const pp::KeyboardInputEvent& event);
-
- void HandleMouseMoveEvent(const pp::MouseInputEvent& event);
- void HandleMouseButtonEvent(bool button_down,
- const pp::MouseInputEvent& event);
- void HandleMouseWheelEvent(const pp::WheelInputEvent& event);
+ bool HandleInputEvent(const pp::InputEvent& event);
private:
- PepperViewProxy* pepper_view_;
+ protocol::InputStub* input_stub_;
float wheel_ticks_x_;
float wheel_ticks_y_;
diff --git a/remoting/client/plugin/pepper_view.cc b/remoting/client/plugin/pepper_view.cc
index ec29290..d8a776c 100644
--- a/remoting/client/plugin/pepper_view.cc
+++ b/remoting/client/plugin/pepper_view.cc
@@ -262,12 +262,12 @@ void PepperView::SetConnectionState(protocol::ConnectionToHost::State state,
}
}
-bool PepperView::SetPluginSize(const SkISize& plugin_size) {
- if (plugin_size_ == plugin_size)
+bool PepperView::SetViewSize(const SkISize& view_size) {
+ if (view_size_ == view_size)
return false;
- plugin_size_ = plugin_size;
+ view_size_ = view_size;
- pp::Size pp_size = pp::Size(plugin_size.width(), plugin_size.height());
+ pp::Size pp_size = pp::Size(view_size.width(), view_size.height());
graphics2d_ = pp::Graphics2D(instance_, pp_size, true);
if (!instance_->BindGraphics(graphics2d_)) {
@@ -275,14 +275,14 @@ bool PepperView::SetPluginSize(const SkISize& plugin_size) {
return false;
}
- if (plugin_size.isEmpty())
+ if (view_size.isEmpty())
return false;
// Allocate the backing store to save the desktop image.
if ((backing_store_.get() == NULL) ||
(backing_store_->size() != pp_size)) {
VLOG(1) << "Allocate backing store: "
- << plugin_size.width() << " x " << plugin_size.height();
+ << view_size.width() << " x " << view_size.height();
backing_store_.reset(
new pp::ImageData(instance_, pp::ImageData::GetNativeImageDataFormat(),
pp_size, false));
@@ -292,22 +292,6 @@ bool PepperView::SetPluginSize(const SkISize& plugin_size) {
return true;
}
-double PepperView::GetHorizontalScaleRatio() const {
- if (instance_->DoScaling()) {
- DCHECK(!host_size_.isEmpty());
- return 1.0 * plugin_size_.width() / host_size_.width();
- }
- return 1.0;
-}
-
-double PepperView::GetVerticalScaleRatio() const {
- if (instance_->DoScaling()) {
- DCHECK(!host_size_.isEmpty());
- return 1.0 * plugin_size_.height() / host_size_.height();
- }
- return 1.0;
-}
-
void PepperView::AllocateFrame(media::VideoFrame::Format format,
const SkISize& size,
scoped_refptr<media::VideoFrame>* frame_out,
diff --git a/remoting/client/plugin/pepper_view.h b/remoting/client/plugin/pepper_view.h
index a64ae7f..eab7f59 100644
--- a/remoting/client/plugin/pepper_view.h
+++ b/remoting/client/plugin/pepper_view.h
@@ -2,10 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// This class is an implementation of the ChromotingView using Pepper devices
-// as the backing stores. This class is used only on pepper thread.
-// Chromoting objects access this object through PepperViewProxy which
-// delegates method calls on the pepper thread.
+// This class is an implementation of the ChromotingView for Pepper. It is
+// callable only on the Pepper thread.
#ifndef REMOTING_CLIENT_PLUGIN_PEPPER_VIEW_H_
#define REMOTING_CLIENT_PLUGIN_PEPPER_VIEW_H_
@@ -28,8 +26,8 @@ class ClientContext;
class PepperView : public ChromotingView,
public FrameConsumer {
public:
- // Constructs a PepperView that draws to the |rendering_device|. The
- // |rendering_device| instance must outlive this class.
+ // Constructs a PepperView for the |instance|. The |instance| and
+ // |context| must outlive this class.
PepperView(ChromotingInstance* instance, ClientContext* context);
virtual ~PepperView();
@@ -42,8 +40,6 @@ class PepperView : public ChromotingView,
virtual void SetConnectionState(
protocol::ConnectionToHost::State state,
protocol::ConnectionToHost::Error error) OVERRIDE;
- virtual double GetHorizontalScaleRatio() const OVERRIDE;
- virtual double GetVerticalScaleRatio() const OVERRIDE;
// FrameConsumer implementation.
virtual void AllocateFrame(media::VideoFrame::Format format,
@@ -55,9 +51,17 @@ class PepperView : public ChromotingView,
RectVector* rects,
const base::Closure& done) OVERRIDE;
- // This is called when the dimension of the plugin element has changed.
- // Return true if plugin size has changed, false otherwise.
- bool SetPluginSize(const SkISize& plugin_size);
+ // Sets the display size of this view. Returns true if plugin size has
+ // changed, false otherwise.
+ bool SetViewSize(const SkISize& plugin_size);
+
+ // Return the client view and original host dimensions.
+ const SkISize& get_view_size() const {
+ return view_size_;
+ }
+ const SkISize& get_host_size() const {
+ return host_size_;
+ }
private:
void OnPaintDone(base::Time paint_start);
@@ -95,7 +99,7 @@ class PepperView : public ChromotingView,
bool flush_blocked_;
// The size of the plugin element.
- SkISize plugin_size_;
+ SkISize view_size_;
// The size of the host screen.
SkISize host_size_;
diff --git a/remoting/client/plugin/pepper_view_proxy.cc b/remoting/client/plugin/pepper_view_proxy.cc
deleted file mode 100644
index 189602f..0000000
--- a/remoting/client/plugin/pepper_view_proxy.cc
+++ /dev/null
@@ -1,154 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "remoting/client/plugin/pepper_view_proxy.h"
-
-#include "base/message_loop.h"
-#include "remoting/client/client_context.h"
-#include "remoting/client/plugin/chromoting_instance.h"
-
-namespace remoting {
-
-PepperViewProxy::PepperViewProxy(ChromotingInstance* instance, PepperView* view,
- base::MessageLoopProxy* plugin_message_loop)
- : instance_(instance),
- view_(view),
- plugin_message_loop_(plugin_message_loop) {
-}
-
-PepperViewProxy::~PepperViewProxy() {
-}
-
-bool PepperViewProxy::Initialize() {
- // This method needs a return value so we can't post a task and process on
- // another thread so just return true since PepperView doesn't do anything
- // either.
- return true;
-}
-
-void PepperViewProxy::TearDown() {
- if (instance_ && !plugin_message_loop_->BelongsToCurrentThread()) {
- plugin_message_loop_->PostTask(
- FROM_HERE, base::Bind(&PepperViewProxy::TearDown, this));
- return;
- }
-
- if (view_)
- view_->TearDown();
-}
-
-void PepperViewProxy::Paint() {
- if (instance_ && !plugin_message_loop_->BelongsToCurrentThread()) {
- plugin_message_loop_->PostTask(
- FROM_HERE, base::Bind(&PepperViewProxy::Paint, this));
- return;
- }
-
- if (view_)
- view_->Paint();
-}
-
-void PepperViewProxy::SetSolidFill(uint32 color) {
- if (instance_ && !plugin_message_loop_->BelongsToCurrentThread()) {
- plugin_message_loop_->PostTask(FROM_HERE, base::Bind(
- &PepperViewProxy::SetSolidFill, this, color));
- return;
- }
-
- if (view_)
- view_->SetSolidFill(color);
-}
-
-void PepperViewProxy::UnsetSolidFill() {
- if (instance_ && !plugin_message_loop_->BelongsToCurrentThread()) {
- plugin_message_loop_->PostTask(
- FROM_HERE, base::Bind(&PepperViewProxy::UnsetSolidFill, this));
- return;
- }
-
- if (view_)
- view_->UnsetSolidFill();
-}
-
-void PepperViewProxy::SetConnectionState(
- protocol::ConnectionToHost::State state,
- protocol::ConnectionToHost::Error error) {
- if (instance_ && !plugin_message_loop_->BelongsToCurrentThread()) {
- plugin_message_loop_->PostTask(FROM_HERE, base::Bind(
- &PepperViewProxy::SetConnectionState, this, state, error));
- return;
- }
-
- if (view_)
- view_->SetConnectionState(state, error);
-}
-
-double PepperViewProxy::GetHorizontalScaleRatio() const {
- // This method returns a value, so must run synchronously, so must be
- // called only on the pepper thread.
- DCHECK(plugin_message_loop_->BelongsToCurrentThread());
-
- if (view_)
- return view_->GetHorizontalScaleRatio();
- return 1.0;
-}
-
-double PepperViewProxy::GetVerticalScaleRatio() const {
- // This method returns a value, so must run synchronously, so must be
- // called only on the pepper thread.
- DCHECK(plugin_message_loop_->BelongsToCurrentThread());
-
- if (view_)
- return view_->GetVerticalScaleRatio();
- return 1.0;
-}
-
-void PepperViewProxy::AllocateFrame(
- media::VideoFrame::Format format,
- const SkISize& size,
- scoped_refptr<media::VideoFrame>* frame_out,
- const base::Closure& done) {
- if (instance_ && !plugin_message_loop_->BelongsToCurrentThread()) {
- plugin_message_loop_->PostTask(FROM_HERE, base::Bind(
- &PepperViewProxy::AllocateFrame, this, format, size, frame_out, done));
- return;
- }
-
- if (view_) {
- view_->AllocateFrame(format, size, frame_out, done);
- }
-}
-
-void PepperViewProxy::ReleaseFrame(media::VideoFrame* frame) {
- if (instance_ && !plugin_message_loop_->BelongsToCurrentThread()) {
- plugin_message_loop_->PostTask(FROM_HERE, base::Bind(
- &PepperViewProxy::ReleaseFrame, this, make_scoped_refptr(frame)));
- return;
- }
-
- if (view_)
- view_->ReleaseFrame(frame);
-}
-
-void PepperViewProxy::OnPartialFrameOutput(media::VideoFrame* frame,
- RectVector* rects,
- const base::Closure& done) {
- if (instance_ && !plugin_message_loop_->BelongsToCurrentThread()) {
- plugin_message_loop_->PostTask(FROM_HERE, base::Bind(
- &PepperViewProxy::OnPartialFrameOutput, this,
- make_scoped_refptr(frame), rects, done));
- return;
- }
-
- if (view_)
- view_->OnPartialFrameOutput(frame, rects, done);
-}
-
-void PepperViewProxy::Detach() {
- DCHECK(plugin_message_loop_->BelongsToCurrentThread());
- instance_ = NULL;
- view_ = NULL;
-}
-
-} // namespace remoting
diff --git a/remoting/client/plugin/pepper_view_proxy.h b/remoting/client/plugin/pepper_view_proxy.h
deleted file mode 100644
index b76da59..0000000
--- a/remoting/client/plugin/pepper_view_proxy.h
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// PepperViewProxy is used to invoke PepperView object on pepper thread. It
-// has the same interface as PepperView. When a method calls is received on
-// any chromoting threads it delegates the method call to pepper thread.
-// It also provide a detach mechanism so that when PepperView object is
-// destroyed PepperViewProxy will not call it anymore. This is important in
-// providing a safe shutdown of ChromotingInstance and PepperView.
-
-// This object is accessed on chromoting threads and pepper thread. The internal
-// PepperView object is only accessed on pepper thread so as the Detach() method
-// call.
-
-#ifndef REMOTING_CLIENT_PLUGIN_PEPPER_VIEW_PROXY_H_
-#define REMOTING_CLIENT_PLUGIN_PEPPER_VIEW_PROXY_H_
-
-#include "base/memory/ref_counted.h"
-#include "remoting/client/plugin/pepper_view.h"
-
-namespace base {
-class MessageLoopProxy;
-} // namespace base
-
-namespace remoting {
-
-class ChromotingInstance;
-
-class PepperViewProxy : public base::RefCountedThreadSafe<PepperViewProxy>,
- public ChromotingView,
- public FrameConsumer {
- public:
- PepperViewProxy(ChromotingInstance* instance, PepperView* view,
- base::MessageLoopProxy* plugin_message_loop);
- virtual ~PepperViewProxy();
-
- // ChromotingView implementation.
- virtual bool Initialize() OVERRIDE;
- virtual void TearDown() OVERRIDE;
- virtual void Paint() OVERRIDE;
- virtual void SetSolidFill(uint32 color) OVERRIDE;
- virtual void UnsetSolidFill() OVERRIDE;
- virtual void SetConnectionState(
- protocol::ConnectionToHost::State state,
- protocol::ConnectionToHost::Error error) OVERRIDE;
-
- // This method returns a value, so must run synchronously, so must be
- // called only on the pepper thread.
- virtual double GetHorizontalScaleRatio() const OVERRIDE;
- virtual double GetVerticalScaleRatio() const OVERRIDE;
-
- // FrameConsumer implementation.
- virtual void AllocateFrame(media::VideoFrame::Format format,
- const SkISize& size,
- scoped_refptr<media::VideoFrame>* frame_out,
- const base::Closure& done) OVERRIDE;
- virtual void ReleaseFrame(media::VideoFrame* frame) OVERRIDE;
- virtual void OnPartialFrameOutput(media::VideoFrame* frame,
- RectVector* rects,
- const base::Closure& done) OVERRIDE;
-
- // Remove the reference to |instance_| and |view_| by setting the value to
- // NULL.
- // This method should only be called on pepper thread.
- void Detach();
-
- private:
- // This variable is accessed on chromoting threads and pepper thread.
- // This is initialized when this object is constructed. Its value is reset
- // to NULL on pepper thread when Detach() is called and there will be no
- // other threads accessing this variable at the same time. Given the above
- // conditions locking this variable is not necessary.
- ChromotingInstance* instance_;
-
- // This variable is only accessed on the pepper thread. Locking is not
- // necessary.
- PepperView* view_;
-
- scoped_refptr<base::MessageLoopProxy> plugin_message_loop_;
-
- DISALLOW_COPY_AND_ASSIGN(PepperViewProxy);
-};
-
-} // namespace remoting
-
-#endif // REMOTING_CLIENT_PLUGIN_PEPPER_VIEW_PROXY_H_
diff --git a/remoting/client/rectangle_update_decoder.cc b/remoting/client/rectangle_update_decoder.cc
index 09dfb4c..8b7ca9e 100644
--- a/remoting/client/rectangle_update_decoder.cc
+++ b/remoting/client/rectangle_update_decoder.cc
@@ -131,12 +131,11 @@ void RectangleUpdateDecoder::ProcessPacketData(
SubmitToConsumer();
}
-void RectangleUpdateDecoder::SetScaleRatios(double horizontal_ratio,
- double vertical_ratio) {
+void RectangleUpdateDecoder::SetOutputSize(const SkISize& size) {
if (message_loop_ != MessageLoop::current()) {
message_loop_->PostTask(
- FROM_HERE, base::Bind(&RectangleUpdateDecoder::SetScaleRatios,
- this, horizontal_ratio, vertical_ratio));
+ FROM_HERE, base::Bind(&RectangleUpdateDecoder::SetOutputSize,
+ this, size));
return;
}
@@ -149,11 +148,10 @@ void RectangleUpdateDecoder::SetScaleRatios(double horizontal_ratio,
// TODO(hclam): If the scale ratio has changed we should reallocate a
// VideoFrame of different size. However if the scale ratio is always
// smaller than 1.0 we can use the same video frame.
- decoder_->SetScaleRatios(horizontal_ratio, vertical_ratio);
-
- // TODO(wez): Defer refresh, so that resize, which will affect both scale
- // factor and clip rect, doesn't lead to unnecessary refreshes.
- DoRefresh();
+ if (decoder_.get()) {
+ decoder_->SetOutputSize(size);
+ RefreshFullFrame();
+ }
}
void RectangleUpdateDecoder::UpdateClipRect(const SkIRect& new_clip_rect) {
diff --git a/remoting/client/rectangle_update_decoder.h b/remoting/client/rectangle_update_decoder.h
index 33bee55..9af727a 100644
--- a/remoting/client/rectangle_update_decoder.h
+++ b/remoting/client/rectangle_update_decoder.h
@@ -39,15 +39,12 @@ class RectangleUpdateDecoder :
// executed.
void DecodePacket(const VideoPacket* packet, const base::Closure& done);
- // Set the scale ratio for the decoded video frame. Scale ratio greater
- // than 1.0 is not supported.
- void SetScaleRatios(double horizontal_ratio, double vertical_ratio);
+ // Set the output dimensions to scale video output to.
+ void SetOutputSize(const SkISize& size);
// Set a new clipping rectangle for the decoder. Decoder should respect
// this clipping rectangle and only decode content in this rectangle and
// report dirty rectangles accordingly to enhance performance.
- //
- // If scale ratio is not 1.0 then clipping rectangle is ignored.
void UpdateClipRect(const SkIRect& clip_rect);
// Force the decoder to output the last decoded video frame without any
diff --git a/remoting/host/client_session.cc b/remoting/host/client_session.cc
index c358508..532b825 100644
--- a/remoting/host/client_session.cc
+++ b/remoting/host/client_session.cc
@@ -239,6 +239,7 @@ void ClientSession::RestoreEventState() {
for (int i = 1; i < MouseEvent::BUTTON_MAX; i++) {
if (remote_mouse_button_state_ & (1 << (i - 1))) {
MouseEvent mouse;
+ // TODO(wez): Shouldn't [need to] set position here.
mouse.set_x(remote_mouse_pos_.x());
mouse.set_y(remote_mouse_pos_.y());
mouse.set_button((MouseEvent::MouseButton)i);
diff --git a/remoting/protocol/key_event_tracker.cc b/remoting/protocol/key_event_tracker.cc
new file mode 100644
index 0000000..a2aa836
--- /dev/null
+++ b/remoting/protocol/key_event_tracker.cc
@@ -0,0 +1,48 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "remoting/protocol/key_event_tracker.h"
+
+#include "base/logging.h"
+#include "remoting/proto/event.pb.h"
+
+namespace remoting {
+namespace protocol {
+
+KeyEventTracker::KeyEventTracker(InputStub* input_stub)
+ : input_stub_(input_stub) {
+}
+
+KeyEventTracker::~KeyEventTracker() {
+ DCHECK(pressed_keys_.empty());
+}
+
+void KeyEventTracker::InjectKeyEvent(const KeyEvent& event) {
+ DCHECK(event.has_pressed());
+ DCHECK(event.has_keycode());
+ if (event.pressed()) {
+ pressed_keys_.insert(event.keycode());
+ } else {
+ pressed_keys_.erase(event.keycode());
+ }
+ input_stub_->InjectKeyEvent(event);
+}
+
+void KeyEventTracker::InjectMouseEvent(const MouseEvent& event) {
+ input_stub_->InjectMouseEvent(event);
+}
+
+void KeyEventTracker::ReleaseAllKeys() {
+ std::set<int>::iterator i;
+ for (i = pressed_keys_.begin(); i != pressed_keys_.end(); ++i) {
+ KeyEvent event;
+ event.set_keycode(*i);
+ event.set_pressed(false);
+ input_stub_->InjectKeyEvent(event);
+ }
+ pressed_keys_.clear();
+}
+
+} // namespace protocol
+} // namespace remoting
diff --git a/remoting/protocol/key_event_tracker.h b/remoting/protocol/key_event_tracker.h
new file mode 100644
index 0000000..80ab6e2
--- /dev/null
+++ b/remoting/protocol/key_event_tracker.h
@@ -0,0 +1,43 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef REMOTING_PROTOCOL_KEY_EVENT_TRACKER_H_
+#define REMOTING_PROTOCOL_KEY_EVENT_TRACKER_H_
+
+#include <set>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "remoting/protocol/input_stub.h"
+
+namespace remoting {
+namespace protocol {
+
+// Filtering InputStub which tracks key press and release events before passing
+// them on to |input_stub|, and can dispatch release events to |input_stub| for
+// all currently-pressed keys when necessary.
+class KeyEventTracker : public InputStub {
+ public:
+ KeyEventTracker(protocol::InputStub* input_stub);
+ virtual ~KeyEventTracker();
+
+ // Dispatch release events for all currently-pressed keys to the InputStub.
+ void ReleaseAllKeys();
+
+ // InputStub interface.
+ virtual void InjectKeyEvent(const KeyEvent& event) OVERRIDE;
+ virtual void InjectMouseEvent(const MouseEvent& event) OVERRIDE;
+
+ private:
+ protocol::InputStub* input_stub_;
+
+ std::set<int> pressed_keys_;
+
+ DISALLOW_COPY_AND_ASSIGN(KeyEventTracker);
+};
+
+} // namespace protocol
+} // namespace remoting
+
+#endif // REMOTING_PROTOCOL_KEY_EVENT_TRACKER_H_
diff --git a/remoting/remoting.gyp b/remoting/remoting.gyp
index 9f65fc2..5b2bc26 100644
--- a/remoting/remoting.gyp
+++ b/remoting/remoting.gyp
@@ -265,8 +265,6 @@
'client/plugin/pepper_plugin_thread_delegate.h',
'client/plugin/pepper_view.cc',
'client/plugin/pepper_view.h',
- 'client/plugin/pepper_view_proxy.cc',
- 'client/plugin/pepper_view_proxy.h',
'client/plugin/pepper_util.cc',
'client/plugin/pepper_util.h',
'client/plugin/pepper_xmpp_proxy.cc',
@@ -632,15 +630,14 @@
'client/chromoting_client.h',
'client/chromoting_stats.cc',
'client/chromoting_stats.h',
- 'client/chromoting_view.cc',
'client/chromoting_view.h',
'client/client_config.cc',
'client/client_config.h',
'client/client_context.cc',
'client/client_context.h',
'client/frame_consumer.h',
- 'client/input_handler.cc',
- 'client/input_handler.h',
+ 'client/mouse_input_filter.cc',
+ 'client/mouse_input_filter.h',
'client/rectangle_update_decoder.cc',
'client/rectangle_update_decoder.h',
],
@@ -780,6 +777,8 @@
'protocol/jingle_session_manager.h',
'protocol/jingle_stream_connector.cc',
'protocol/jingle_stream_connector.h',
+ 'protocol/key_event_tracker.cc',
+ 'protocol/key_event_tracker.h',
'protocol/message_decoder.cc',
'protocol/message_decoder.h',
'protocol/message_reader.cc',