summaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
authordcheng@chromium.org <dcheng@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-10 23:01:51 +0000
committerdcheng@chromium.org <dcheng@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-10 23:01:51 +0000
commit1a828911013ff501b87aacc5b555e470b31f2909 (patch)
tree61b673c1b861d7e664f6e5908d8b0981a6831eb1 /ui
parent3ce52b7367e007940d7ab34ae8eae1df236c59df (diff)
downloadchromium_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.cc90
-rw-r--r--ui/ui.gyp1
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
diff --git a/ui/ui.gyp b/ui/ui.gyp
index 6305dae..c9328e6 100644
--- a/ui/ui.gyp
+++ b/ui/ui.gyp
@@ -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',