// 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 #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* 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& 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& 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 > 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 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 abort_timer_; X11AtomCache atom_cache_; DISALLOW_COPY_AND_ASSIGN(SelectionRequestor); }; } // namespace ui #endif // UI_BASE_X_SELECTION_REQUESTOR_H_