| Index: ui/base/clipboard/clipboard_gtk.cc
|
| diff --git a/ui/base/clipboard/clipboard_gtk.cc b/ui/base/clipboard/clipboard_gtk.cc
|
| index f51ba8a1a996d0581135f148d3b7a781dbbf4b39..e9af2f330d8fd5d95480ffb031ea595b1610ea36 100644
|
| --- a/ui/base/clipboard/clipboard_gtk.cc
|
| +++ b/ui/base/clipboard/clipboard_gtk.cc
|
| @@ -5,6 +5,8 @@
|
| #include "ui/base/clipboard/clipboard.h"
|
|
|
| #include <gtk/gtk.h>
|
| +#include <X11/extensions/Xfixes.h>
|
| +#include <X11/Xatom.h>
|
| #include <map>
|
| #include <set>
|
| #include <string>
|
| @@ -12,9 +14,11 @@
|
|
|
| #include "base/file_path.h"
|
| #include "base/logging.h"
|
| -#include "base/memory/scoped_ptr.h"
|
| +#include "base/memory/singleton.h"
|
| #include "base/utf_string_conversions.h"
|
| #include "third_party/skia/include/core/SkBitmap.h"
|
| +#include "ui/base/gtk/gtk_signal.h"
|
| +#include "ui/base/x/x11_util.h"
|
| #include "ui/gfx/canvas_skia.h"
|
| #include "ui/gfx/gtk_util.h"
|
| #include "ui/gfx/size.h"
|
| @@ -23,6 +27,82 @@ namespace ui {
|
|
|
| namespace {
|
|
|
| +class SelectionChangeObserver {
|
| + public:
|
| + static SelectionChangeObserver* GetInstance();
|
| +
|
| + uint64 clipboard_sequence_number() const {
|
| + return clipboard_sequence_number_;
|
| + }
|
| + uint64 primary_sequence_number() const { return primary_sequence_number_; }
|
| +
|
| + private:
|
| + friend struct DefaultSingletonTraits<SelectionChangeObserver>;
|
| +
|
| + SelectionChangeObserver();
|
| + ~SelectionChangeObserver();
|
| +
|
| + CHROMEG_CALLBACK_1(SelectionChangeObserver, GdkFilterReturn, OnXEvent,
|
| + GdkXEvent*, GdkEvent*);
|
| +
|
| + int event_base_;
|
| + Atom clipboard_atom_;
|
| + uint64 clipboard_sequence_number_;
|
| + uint64 primary_sequence_number_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(SelectionChangeObserver);
|
| +};
|
| +
|
| +SelectionChangeObserver::SelectionChangeObserver()
|
| + : event_base_(-1),
|
| + clipboard_atom_(None),
|
| + clipboard_sequence_number_(0),
|
| + primary_sequence_number_(0) {
|
| + int ignored;
|
| + if (XFixesQueryExtension(GetXDisplay(), &event_base_, &ignored)) {
|
| + clipboard_atom_ = XInternAtom(GetXDisplay(), "CLIPBOARD", false);
|
| + XFixesSelectSelectionInput(GetXDisplay(), GetX11RootWindow(),
|
| + clipboard_atom_,
|
| + XFixesSetSelectionOwnerNotifyMask |
|
| + XFixesSelectionWindowDestroyNotifyMask |
|
| + XFixesSelectionClientCloseNotifyMask);
|
| + // This seems to be semi-optional. For some reason, registering for any
|
| + // selection notify events seems to subscribe us to events for both the
|
| + // primary and the clipboard buffers. Register anyway just to be safe.
|
| + XFixesSelectSelectionInput(GetXDisplay(), GetX11RootWindow(),
|
| + XA_PRIMARY,
|
| + XFixesSetSelectionOwnerNotifyMask |
|
| + XFixesSelectionWindowDestroyNotifyMask |
|
| + XFixesSelectionClientCloseNotifyMask);
|
| + gdk_window_add_filter(NULL, &SelectionChangeObserver::OnXEventThunk, this);
|
| + }
|
| +}
|
| +
|
| +SelectionChangeObserver::~SelectionChangeObserver() {
|
| +}
|
| +
|
| +SelectionChangeObserver* SelectionChangeObserver::GetInstance() {
|
| + return Singleton<SelectionChangeObserver>::get();
|
| +}
|
| +
|
| +GdkFilterReturn SelectionChangeObserver::OnXEvent(GdkXEvent* xevent,
|
| + GdkEvent* event) {
|
| + XEvent* xev = static_cast<XEvent*>(xevent);
|
| +
|
| + if (xev->type == event_base_ + XFixesSelectionNotify) {
|
| + XFixesSelectionNotifyEvent* ev =
|
| + reinterpret_cast<XFixesSelectionNotifyEvent*>(xev);
|
| + if (ev->selection == clipboard_atom_) {
|
| + clipboard_sequence_number_++;
|
| + } else if (ev->selection == XA_PRIMARY) {
|
| + primary_sequence_number_++;
|
| + } else {
|
| + DLOG(ERROR) << "Unexpected selection atom: " << ev->selection;
|
| + }
|
| + }
|
| + return GDK_FILTER_CONTINUE;
|
| +}
|
| +
|
| const char kMimeTypeBitmap[] = "image/bmp";
|
| const char kMimeTypeMozillaURL[] = "text/x-moz-url";
|
| const char kMimeTypeWebkitSmartPaste[] = "chromium/x-webkit-paste";
|
| @@ -423,10 +503,10 @@ void Clipboard::ReadData(const std::string& format, std::string* result) {
|
| }
|
|
|
| uint64 Clipboard::GetSequenceNumber(Buffer buffer) {
|
| - // TODO(cdn): implement this. For now this interface will advertise
|
| - // that the Linux clipboard never changes. That's fine as long as we
|
| - // don't rely on this signal.
|
| - return 0;
|
| + if (buffer == BUFFER_STANDARD)
|
| + return SelectionChangeObserver::GetInstance()->clipboard_sequence_number();
|
| + else
|
| + return SelectionChangeObserver::GetInstance()->primary_sequence_number();
|
| }
|
|
|
| // static
|
|
|