diff options
author | dcheng@chromium.org <dcheng@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-10 23:01:51 +0000 |
---|---|---|
committer | dcheng@chromium.org <dcheng@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-10 23:01:51 +0000 |
commit | 1a828911013ff501b87aacc5b555e470b31f2909 (patch) | |
tree | 61b673c1b861d7e664f6e5908d8b0981a6831eb1 /ui | |
parent | 3ce52b7367e007940d7ab34ae8eae1df236c59df (diff) | |
download | chromium_src-1a828911013ff501b87aacc5b555e470b31f2909.zip chromium_src-1a828911013ff501b87aacc5b555e470b31f2909.tar.gz chromium_src-1a828911013ff501b87aacc5b555e470b31f2909.tar.bz2 |
Use XFixes to update the clipboard sequence number.
BUG=73478
TEST=manual testing
Review URL: http://codereview.chromium.org/8501002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@109528 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui')
-rw-r--r-- | ui/base/clipboard/clipboard_gtk.cc | 90 | ||||
-rw-r--r-- | ui/ui.gyp | 1 |
2 files changed, 86 insertions, 5 deletions
diff --git a/ui/base/clipboard/clipboard_gtk.cc b/ui/base/clipboard/clipboard_gtk.cc index f51ba8a..e9af2f3 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 @@ -356,6 +356,7 @@ '../build/linux/system.gyp:pangocairo', '../build/linux/system.gyp:x11', '../build/linux/system.gyp:xext', + '../build/linux/system.gyp:xfixes', ], 'sources': [ 'gfx/linux_util.cc', |