1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#ifndef UI_BASE_X_SELECTION_REQUESTOR_H_
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#define UI_BASE_X_SELECTION_REQUESTOR_H_
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <X11/Xlib.h>
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Get rid of a macro from Xlib.h that conflicts with Aura's RootWindow class.
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#undef RootWindow
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include <list>
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <vector>
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/basictypes.h"
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/callback.h"
18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/memory/ref_counted_memory.h"
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/base/ui_base_export.h"
2068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ui/gfx/x/x11_atom_cache.h"
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace ui {
23010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)class PlatformEventDispatcher;
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class SelectionData;
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Requests and later receives data from the X11 server through the selection
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// system.
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// X11 uses a system called "selections" to implement clipboards and drag and
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// drop. This class interprets messages from the statefull selection request
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// API. SelectionRequestor should only deal with the X11 details; it does not
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// implement per-component fast-paths.
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class UI_BASE_EXPORT SelectionRequestor {
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SelectionRequestor(Display* xdisplay,
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     ::Window xwindow,
37010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                     ::Atom selection_name,
38010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                     PlatformEventDispatcher* dispatcher);
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ~SelectionRequestor();
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Does the work of requesting |target| from the selection we handle,
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // spinning up the nested message loop, and reading the resulting data
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // back. |out_data| is allocated with the X allocator and must be freed with
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // XFree(). |out_data_bytes| is the length in machine chars, while
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // |out_data_items| is the length in |out_type| items.
46eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  bool PerformBlockingConvertSelection(
47eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      ::Atom target,
48eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      scoped_refptr<base::RefCountedMemory>* out_data,
49eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      size_t* out_data_bytes,
50eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      size_t* out_data_items,
51eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      ::Atom* out_type);
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
53010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Requests |target| from the selection that we handle, passing |parameter|
54010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // as a parameter to XConvertSelection().
55010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  void PerformBlockingConvertSelectionWithParameter(
56010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      ::Atom target,
57010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      const std::vector< ::Atom>& parameter);
58010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Returns the first of |types| offered by the current selection holder, or
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // returns NULL if none of those types are available.
61eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SelectionData RequestAndWaitForTypes(const std::vector< ::Atom>& types);
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // It is our owner's responsibility to plumb X11 SelectionNotify events on
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // |xwindow_| to us.
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void OnSelectionNotify(const XSelectionEvent& event);
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private:
68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // A request that has been issued and we are waiting for a response to.
69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  struct PendingRequest {
70010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    explicit PendingRequest(Atom target);
71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    ~PendingRequest();
72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Data to the current XConvertSelection request. Used for error detection;
74f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // we verify it on the return message.
75f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    ::Atom target;
76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Called to terminate the nested message loop.
78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    base::Closure quit_closure;
79f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
80f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // The property in the returning SelectNotify message is used to signal
81f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // success. If None, our request failed somehow. If equal to the property
82f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // atom that we sent in the XConvertSelection call, we can read that
83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // property on |x_window_| for the requested data.
84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    ::Atom returned_property;
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Set to true when return_property is populated.
87f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bool returned;
88f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  };
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
90010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Blocks till SelectionNotify is received for the target specified in
91010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // |request|.
92010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  void BlockTillSelectionNotifyForRequest(PendingRequest* request);
93010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
94010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Our X11 state.
95010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  Display* x_display_;
96010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ::Window x_window_;
97010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
98010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // The X11 selection that this instance communicates on.
99010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ::Atom selection_name_;
100010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
101010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Dispatcher which handles SelectionNotify and SelectionRequest for
102010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // |selection_name_|. PerformBlockingConvertSelection() calls the
103010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // dispatcher directly if PerformBlockingConvertSelection() is called after
104010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // the PlatformEventSource is destroyed.
105010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Not owned.
106010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  PlatformEventDispatcher* dispatcher_;
107010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // A list of requests for which we are waiting for responses.
109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  std::list<PendingRequest*> pending_requests_;
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  X11AtomCache atom_cache_;
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SelectionRequestor);
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace ui
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif  // UI_BASE_X_SELECTION_REQUESTOR_H_
119