summaryrefslogtreecommitdiffstats
path: root/widget/gtk/nsClipboard.h
blob: 95ddcbd2ca611fc18bc1a81002ea119854a8cb46 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:expandtab:shiftwidth=2:tabstop=2:
 */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef __nsClipboard_h_
#define __nsClipboard_h_

#include "mozilla/UniquePtr.h"
#include "mozilla/Span.h"
#include "nsBaseClipboard.h"
#include "nsIClipboard.h"
#include "nsIObserver.h"
#include "nsCOMPtr.h"
#include "GUniquePtr.h"
#include <gtk/gtk.h>

#ifdef MOZ_LOGGING
#  include "mozilla/Logging.h"
#  include "nsTArray.h"
#  include "Units.h"
extern mozilla::LazyLogModule gClipboardLog;
#  define LOGCLIP(...) \
    MOZ_LOG(gClipboardLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
#  define LOGCLIP_ENABLED() \
    MOZ_LOG_TEST(gClipboardLog, mozilla::LogLevel::Debug)
#else
#  define LOGCLIP(...)
#  define LOGCLIP_ENABLED() false
#endif /* MOZ_LOGGING */

class ClipboardTargets {
  friend class ClipboardData;

  mozilla::GUniquePtr<GdkAtom> mTargets;
  uint32_t mCount = 0;

 public:
  ClipboardTargets() = default;
  ClipboardTargets(mozilla::GUniquePtr<GdkAtom> aTargets, uint32_t aCount)
      : mTargets(std::move(aTargets)), mCount(aCount) {}

  void Set(ClipboardTargets);
  ClipboardTargets Clone();
  void Clear() {
    mTargets = nullptr;
    mCount = 0;
  };

  mozilla::Span<GdkAtom> AsSpan() const { return {mTargets.get(), mCount}; }
  explicit operator bool() const { return bool(mTargets); }
};

class ClipboardData {
  mozilla::GUniquePtr<char> mData;
  uint32_t mLength = 0;

 public:
  ClipboardData() = default;

  void SetData(mozilla::Span<const uint8_t>);
  void SetText(mozilla::Span<const char>);
  void SetTargets(ClipboardTargets);

  ClipboardTargets ExtractTargets();
  mozilla::GUniquePtr<char> ExtractText() {
    mLength = 0;
    return std::move(mData);
  }

  mozilla::Span<char> AsSpan() const { return {mData.get(), mLength}; }
  explicit operator bool() const { return bool(mData); }
};

enum class ClipboardDataType { Data, Text, Targets };

class nsRetrievalContext {
 public:
  // We intentionally use unsafe thread refcount as clipboard is used in
  // main thread only.
  NS_INLINE_DECL_REFCOUNTING(nsRetrievalContext)

  // Get actual clipboard content (GetClipboardData/GetClipboardText).
  virtual ClipboardData GetClipboardData(const char* aMimeType,
                                         int32_t aWhichClipboard) = 0;
  virtual mozilla::GUniquePtr<char> GetClipboardText(
      int32_t aWhichClipboard) = 0;

  // Get data mime types which can be obtained from clipboard.
  ClipboardTargets GetTargets(int32_t aWhichClipboard);

  // Clipboard/Primary selection owner changed. Clear internal cached data.
  static void ClearCachedTargetsClipboard(GtkClipboard* aClipboard,
                                          GdkEvent* aEvent, gpointer data);
  static void ClearCachedTargetsPrimary(GtkClipboard* aClipboard,
                                        GdkEvent* aEvent, gpointer data);

  nsRetrievalContext();

 protected:
  virtual ClipboardTargets GetTargetsImpl(int32_t aWhichClipboard) = 0;
  virtual ~nsRetrievalContext();

  static ClipboardTargets sClipboardTargets;
  static ClipboardTargets sPrimaryTargets;
};

class nsClipboard : public ClipboardSetDataHelper, public nsIObserver {
 public:
  nsClipboard();

  NS_DECL_ISUPPORTS_INHERITED
  NS_DECL_NSIOBSERVER

  // nsIClipboard
  NS_IMETHOD GetData(nsITransferable* aTransferable,
                     int32_t aWhichClipboard) override;
  NS_IMETHOD EmptyClipboard(int32_t aWhichClipboard) override;
  NS_IMETHOD HasDataMatchingFlavors(const nsTArray<nsCString>& aFlavorList,
                                    int32_t aWhichClipboard,
                                    bool* _retval) override;
  NS_IMETHOD IsClipboardTypeSupported(int32_t aWhichClipboard,
                                      bool* _retval) override;
  RefPtr<mozilla::GenericPromise> AsyncGetData(
      nsITransferable* aTransferable, int32_t aWhichClipboard) override;
  RefPtr<DataFlavorsPromise> AsyncHasDataMatchingFlavors(
      const nsTArray<nsCString>& aFlavorList, int32_t aWhichClipboard) override;

  // Make sure we are initialized, called from the factory
  // constructor
  nsresult Init(void);

  // Someone requested the selection
  void SelectionGetEvent(GtkClipboard* aGtkClipboard,
                         GtkSelectionData* aSelectionData);
  void SelectionClearEvent(GtkClipboard* aGtkClipboard);

 protected:
  // Implement the native clipboard behavior.
  NS_IMETHOD SetNativeClipboardData(nsITransferable* aTransferable,
                                    nsIClipboardOwner* aOwner,
                                    int32_t aWhichClipboard) override;

 private:
  virtual ~nsClipboard();

  // Get our hands on the correct transferable, given a specific
  // clipboard
  nsITransferable* GetTransferable(int32_t aWhichClipboard);

  void ClearTransferable(int32_t aWhichClipboard);
  void ClearCachedTargets(int32_t aWhichClipboard);

  bool FilterImportedFlavors(int32_t aWhichClipboard,
                             nsTArray<nsCString>& aFlavors);

  // Hang on to our owners and transferables so we can transfer data
  // when asked.
  nsCOMPtr<nsIClipboardOwner> mSelectionOwner;
  nsCOMPtr<nsIClipboardOwner> mGlobalOwner;
  nsCOMPtr<nsITransferable> mSelectionTransferable;
  nsCOMPtr<nsITransferable> mGlobalTransferable;
  RefPtr<nsRetrievalContext> mContext;
};

extern const int kClipboardTimeout;
extern const int kClipboardFastIterationNum;

GdkAtom GetSelectionAtom(int32_t aWhichClipboard);
int GetGeckoClipboardType(GtkClipboard* aGtkClipboard);

#endif /* __nsClipboard_h_ */