summaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
authordcheng@chromium.org <dcheng@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-10 23:29:11 +0000
committerdcheng@chromium.org <dcheng@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-10 23:29:11 +0000
commit34720ea2dcccd88e0f3054ab567a15cea06f97f4 (patch)
treeda158cfc4107ac716d1fb27a00e106de0f7871ef /ui
parent9c687adb3ea03390d17c5f70468e17cfc685c911 (diff)
downloadchromium_src-34720ea2dcccd88e0f3054ab567a15cea06f97f4.zip
chromium_src-34720ea2dcccd88e0f3054ab567a15cea06f97f4.tar.gz
chromium_src-34720ea2dcccd88e0f3054ab567a15cea06f97f4.tar.bz2
Reland with a virtual destructor.
Use XFixes to update the clipboard sequence number. BUG=73478 TEST=manual testing Committed: http://src.chromium.org/viewvc/chrome?view=rev&revision=109528 Review URL: http://codereview.chromium.org/8501002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@109537 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..19a12bc 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();
+ virtual ~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',