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
|
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_BASE_X_SELECTION_REQUESTOR_H_
#define UI_BASE_X_SELECTION_REQUESTOR_H_
#include <vector>
#include "base/basictypes.h"
#include "base/callback.h"
#include "base/event_types.h"
#include "base/memory/ref_counted_memory.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "ui/base/ui_base_export.h"
#include "ui/gfx/x/x11_atom_cache.h"
#include "ui/gfx/x/x11_types.h"
namespace ui {
class PlatformEventDispatcher;
class SelectionData;
// Requests and later receives data from the X11 server through the selection
// system.
//
// X11 uses a system called "selections" to implement clipboards and drag and
// drop. This class interprets messages from the stateful selection request
// API. SelectionRequestor should only deal with the X11 details; it does not
// implement per-component fast-paths.
class UI_BASE_EXPORT SelectionRequestor {
public:
SelectionRequestor(XDisplay* xdisplay,
XID xwindow,
PlatformEventDispatcher* dispatcher);
~SelectionRequestor();
// Does the work of requesting |target| from |selection|, spinning up the
// nested message loop, and reading the resulting data back. The result is
// stored in |out_data|.
// |out_data_items| is the length of |out_data| in |out_type| items.
bool PerformBlockingConvertSelection(
XAtom selection,
XAtom target,
scoped_refptr<base::RefCountedMemory>* out_data,
size_t* out_data_items,
XAtom* out_type);
// Requests |target| from |selection|, passing |parameter| as a parameter to
// XConvertSelection().
void PerformBlockingConvertSelectionWithParameter(
XAtom selection,
XAtom target,
const std::vector<XAtom>& parameter);
// Returns the first of |types| offered by the current owner of |selection|.
// Returns an empty SelectionData object if none of |types| are available.
SelectionData RequestAndWaitForTypes(XAtom selection,
const std::vector<XAtom>& types);
// It is our owner's responsibility to plumb X11 SelectionNotify events on
// |xwindow_| to us.
void OnSelectionNotify(const XEvent& event);
// Returns true if SelectionOwner can process the XChangeProperty event,
// |event|.
bool CanDispatchPropertyEvent(const XEvent& event);
void OnPropertyEvent(const XEvent& event);
private:
friend class SelectionRequestorTest;
// A request that has been issued.
struct Request {
Request(XAtom selection, XAtom target, base::TimeTicks timeout);
~Request();
// The target and selection requested in the XConvertSelection() request.
// Used for error detection.
XAtom selection;
XAtom target;
// Whether the result of the XConvertSelection() request is being sent
// incrementally.
bool data_sent_incrementally;
// The result data for the XConvertSelection() request.
std::vector<scoped_refptr<base::RefCountedMemory> > out_data;
size_t out_data_items;
XAtom out_type;
// Whether the XConvertSelection() request was successful.
bool success;
// The time when the request should be aborted.
base::TimeTicks timeout;
// Called to terminate the nested message loop.
base::Closure quit_closure;
// True if the request is complete.
bool completed;
};
// Aborts requests which have timed out.
void AbortStaleRequests();
// Mark |request| as completed. If the current request is completed, converts
// the selection for the next request.
void CompleteRequest(size_t index, bool success);
// Converts the selection for the request at |current_request_index_|.
void ConvertSelectionForCurrentRequest();
// Blocks till SelectionNotify is received for the target specified in
// |request|.
void BlockTillSelectionNotifyForRequest(Request* request);
// Returns the request at |current_request_index_| or NULL if there isn't any.
Request* GetCurrentRequest();
// Our X11 state.
XDisplay* x_display_;
XID x_window_;
// The property on |x_window_| set by the selection owner with the value of
// the selection.
XAtom x_property_;
// Dispatcher which handles SelectionNotify and SelectionRequest for
// |selection_name_|. PerformBlockingConvertSelection() calls the
// dispatcher directly if PerformBlockingConvertSelection() is called after
// the PlatformEventSource is destroyed.
// Not owned.
PlatformEventDispatcher* dispatcher_;
// In progress requests. Requests are added to the list at the start of
// PerformBlockingConvertSelection() and are removed and destroyed right
// before the method terminates.
std::vector<Request*> requests_;
// The index of the currently active request in |requests_|. The active
// request is the request for which XConvertSelection() has been
// called and for which we are waiting for a SelectionNotify response.
size_t current_request_index_;
// Used to abort requests if the selection owner takes too long to respond.
base::RepeatingTimer<SelectionRequestor> abort_timer_;
X11AtomCache atom_cache_;
DISALLOW_COPY_AND_ASSIGN(SelectionRequestor);
};
} // namespace ui
#endif // UI_BASE_X_SELECTION_REQUESTOR_H_
|