123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 |
- // Copyright (c) 2012 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/host/clipboard.h"
- #import <Cocoa/Cocoa.h>
- #include <stdint.h>
- #include <memory>
- #include <utility>
- #include "base/logging.h"
- #include "base/memory/ptr_util.h"
- #include "base/strings/string_util.h"
- #include "base/strings/sys_string_conversions.h"
- #include "base/timer/timer.h"
- #include "remoting/base/constants.h"
- #include "remoting/base/util.h"
- #include "remoting/proto/event.pb.h"
- #include "remoting/protocol/clipboard_stub.h"
- namespace {
- // Clipboard polling interval in milliseconds.
- const int64_t kClipboardPollingIntervalMs = 500;
- } // namespace
- namespace remoting {
- class ClipboardMac : public Clipboard {
- public:
- ClipboardMac();
- ClipboardMac(const ClipboardMac&) = delete;
- ClipboardMac& operator=(const ClipboardMac&) = delete;
- ~ClipboardMac() override;
- void Start(
- std::unique_ptr<protocol::ClipboardStub> client_clipboard) override;
- void InjectClipboardEvent(const protocol::ClipboardEvent& event) override;
- private:
- void CheckClipboardForChanges();
- std::unique_ptr<protocol::ClipboardStub> client_clipboard_;
- std::unique_ptr<base::RepeatingTimer> clipboard_polling_timer_;
- NSInteger current_change_count_;
- };
- ClipboardMac::ClipboardMac() : current_change_count_(0) {}
- ClipboardMac::~ClipboardMac() {}
- void ClipboardMac::Start(
- std::unique_ptr<protocol::ClipboardStub> client_clipboard) {
- client_clipboard_ = std::move(client_clipboard);
- // Synchronize local change-count with the pasteboard's. The change-count is
- // used to detect clipboard changes.
- current_change_count_ = [[NSPasteboard generalPasteboard] changeCount];
- // OS X doesn't provide a clipboard-changed notification. The only way to
- // detect clipboard changes is by polling.
- clipboard_polling_timer_ = std::make_unique<base::RepeatingTimer>();
- clipboard_polling_timer_->Start(
- FROM_HERE, base::Milliseconds(kClipboardPollingIntervalMs), this,
- &ClipboardMac::CheckClipboardForChanges);
- }
- void ClipboardMac::InjectClipboardEvent(const protocol::ClipboardEvent& event) {
- // Currently we only handle UTF-8 text.
- if (event.mime_type().compare(kMimeTypeTextUtf8) != 0)
- return;
- if (!base::IsStringUTF8AllowingNoncharacters(event.data())) {
- LOG(ERROR) << "ClipboardEvent data is not UTF-8 encoded.";
- return;
- }
- // Write text to clipboard.
- NSString* text = base::SysUTF8ToNSString(event.data());
- NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
- [pasteboard clearContents];
- [pasteboard writeObjects:@[ text ]];
- // Update local change-count to prevent this change from being picked up by
- // CheckClipboardForChanges.
- current_change_count_ = [[NSPasteboard generalPasteboard] changeCount];
- }
- void ClipboardMac::CheckClipboardForChanges() {
- NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
- NSInteger change_count = [pasteboard changeCount];
- if (change_count == current_change_count_) {
- return;
- }
- current_change_count_ = change_count;
- NSArray* objects =
- [pasteboard readObjectsForClasses:@[ [NSString class] ] options:0];
- if (![objects count]) {
- return;
- }
- protocol::ClipboardEvent event;
- event.set_mime_type(kMimeTypeTextUtf8);
- event.set_data(base::SysNSStringToUTF8([objects lastObject]));
- client_clipboard_->InjectClipboardEvent(event);
- }
- std::unique_ptr<Clipboard> Clipboard::Create() {
- return base::WrapUnique(new ClipboardMac());
- }
- } // namespace remoting
|