910e62b5创建于 1月15日历史提交
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef UI_BASE_X_X11_CLIPBOARD_HELPER_H_
#define UI_BASE_X_X11_CLIPBOARD_HELPER_H_

#include <cstdint>
#include <memory>
#include <string>
#include <vector>

#include "base/component_export.h"
#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/scoped_refptr.h"
#include "ui/base/clipboard/clipboard_buffer.h"
#include "ui/base/clipboard/clipboard_format_type.h"
#include "ui/base/x/selection_owner.h"
#include "ui/base/x/selection_utils.h"
#include "ui/gfx/x/connection.h"
#include "ui/gfx/x/xproto.h"

namespace ui {

class SelectionRequestor;

// Helper class that provides core X11 clipboard integration code. Shared by
// both legacy and Ozone X11 backends.
//
// TODO(crbug.com/40551833): Merge into X11ClipboardOzone class once ozone
// migration is complete and legacy backend gets removed.
class COMPONENT_EXPORT(UI_BASE_X) XClipboardHelper : public x11::EventObserver {
 public:
  using SelectionChangeCallback =
      base::RepeatingCallback<void(ClipboardBuffer)>;

  explicit XClipboardHelper(SelectionChangeCallback selection_change_callback);
  XClipboardHelper(const XClipboardHelper&) = delete;
  XClipboardHelper& operator=(const XClipboardHelper&) = delete;
  ~XClipboardHelper() override;

  // As we need to collect all the data types before we tell X11 that we own a
  // particular selection, we create a temporary clipboard mapping that
  // InsertMapping writes to. Then we commit it in TakeOwnershipOfSelection,
  // where we save it in one of the clipboard data slots.
  void CreateNewClipboardData();

  // Inserts a mapping into clipboard_data_.
  void InsertMapping(const std::string& key,
                     const scoped_refptr<base::RefCountedMemory>& memory);

  // Moves the temporary |clipboard_data_| to the long term data storage for
  // |buffer|.
  void TakeOwnershipOfSelection(ClipboardBuffer buffer);

  // Returns the first of |types| offered by the current selection holder, or
  // returns nullptr if none of those types are available. Blocks until the data
  // is fetched from the X server, unless we are the selection owner.
  SelectionData Read(ClipboardBuffer buffer,
                     const std::vector<x11::Atom>& types);

  // Retrieves the list of possible data types the current clipboard owner has,
  // for a given |buffer|. Blocks until the data is fetched from the X server,
  // unless we are the selection owner.
  std::vector<std::string> GetAvailableTypes(ClipboardBuffer buffer);

  // Retrieves the list of target atom names currently available for reading in
  // the clipboard, for a given |buffer|. Blocks until the data is fetched from
  // the X server.
  std::vector<std::string> GetAvailableAtomNames(ClipboardBuffer buffer);

  // Tells if |format| is currently available for reading in clipboard |buffer|.
  // Blocks until the data is fetched from the X server.
  bool IsFormatAvailable(ClipboardBuffer buffer,
                         const ClipboardFormatType& format);

  // Tells if we currently own the selection for a given clipboard |buffer|.
  bool IsSelectionOwner(ClipboardBuffer buffer) const;

  // Returns a list of all text atoms that we handle.
  std::vector<x11::Atom> GetTextAtoms() const;

  // Returns a vector with a |format| converted to an X11 atom.
  std::vector<x11::Atom> GetAtomsForFormat(const ClipboardFormatType& format);

  // Clears a certain clipboard buffer, whether we own it or not.
  void Clear(ClipboardBuffer buffer);

  // If we own the CLIPBOARD selection, requests the clipboard manager to take
  // ownership of it.
  void StoreCopyPasteDataAndWait();

  // Returns true if the event was handled.
  bool DispatchEvent(const x11::Event& xev);

  SelectionRequestor* GetSelectionRequestorForTest();

 private:
  class TargetList;

  // x11::EventObserver:
  void OnEvent(const x11::Event& xev) override;

  TargetList GetTargetList(ClipboardBuffer buffer);

  // Returns the X11 selection atom that we pass to various XSelection functions
  // for the given buffer.
  x11::Atom LookupSelectionForClipboardBuffer(ClipboardBuffer buffer) const;

  // Returns the X11 selection atom that we pass to various XSelection functions
  // for ClipboardBuffer::kCopyPaste.
  x11::Atom GetCopyPasteSelection() const;

  // Finds the SelectionFormatMap for the incoming selection atom.
  const SelectionFormatMap& LookupStorageForAtom(x11::Atom atom);

  // Our X11 state.
  raw_ref<x11::Connection> connection_;
  const x11::Window x_root_window_;

  // Input-only window used as a selection owner.
  x11::Window x_window_;

  // Events selected on |x_window_|.
  x11::ScopedEventSelector x_window_events_;

  // Object which requests and receives selection data.
  const std::unique_ptr<SelectionRequestor> selection_requestor_;

  // Temporary target map that we write to during DispatchObects.
  SelectionFormatMap clipboard_data_;

  // Objects which offer selection data to other windows.
  SelectionOwner clipboard_owner_;
  SelectionOwner primary_owner_;
};

}  // namespace ui

#endif  //  UI_BASE_X_X11_CLIPBOARD_HELPER_H_