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_OWNER_H_
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#define UI_BASE_X_SELECTION_OWNER_H_
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <vector>
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/basictypes.h"
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/callback.h"
125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/memory/ref_counted_memory.h"
135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/time/time.h"
145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/timer/timer.h"
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/base/ui_base_export.h"
16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/base/x/selection_utils.h"
1768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ui/gfx/x/x11_atom_cache.h"
18116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "ui/gfx/x/x11_types.h"
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace ui {
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Owns a specific X11 selection on an X window.
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// The selection owner object keeps track of which xwindow is the current
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// owner, and when its |xwindow_|, offers different data types to other
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// processes.
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class UI_BASE_EXPORT SelectionOwner {
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
29116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  SelectionOwner(XDisplay* xdisplay,
30116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 XID xwindow,
31116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 XAtom selection_name);
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ~SelectionOwner();
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Returns the current selection data. Useful for fast paths.
35eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const SelectionFormatMap& selection_format_map() { return format_map_; }
36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Appends a list of types we're offering to |targets|.
38116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  void RetrieveTargets(std::vector<XAtom>* targets);
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Attempts to take ownership of the selection. If we're successful, present
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // |data| to other windows.
42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  void TakeOwnershipOfSelection(const SelectionFormatMap& data);
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // Clears our internal format map and clears the selection owner, whether we
4523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // own the selection or not.
4623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  void ClearSelectionOwner();
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // It is our owner's responsibility to plumb X11 events on |xwindow_| to us.
49116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  void OnSelectionRequest(const XEvent& event);
50116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  void OnSelectionClear(const XEvent& event);
515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Returns true if SelectionOwner can process the XPropertyEvent event,
535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // |event|.
545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  bool CanDispatchPropertyEvent(const XEvent& event);
555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  void OnPropertyEvent(const XEvent& event);
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private:
595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Holds state related to an incremental data transfer.
605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  struct IncrementalTransfer {
615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    IncrementalTransfer(XID window,
625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        XAtom target,
635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        XAtom property,
645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        const scoped_refptr<base::RefCountedMemory>& data,
655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        int offset,
665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        base::TimeTicks timeout,
675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        int foreign_window_manager_id);
685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ~IncrementalTransfer();
695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // Parameters from the XSelectionRequest. The data is transferred over
715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // |property| on |window|.
725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    XID window;
735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    XAtom target;
745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    XAtom property;
755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // The data to be transferred.
775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    scoped_refptr<base::RefCountedMemory> data;
785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // The offset from the beginning of |data| of the first byte to be
805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // transferred in the next chunk.
815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    size_t offset;
825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // Time when the transfer should be aborted because the selection requestor
845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // is taking too long to notify us that we can send the next chunk.
855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    base::TimeTicks timeout;
865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // Used to unselect PropertyChangeMask on |window| when we are done with
885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // the data transfer.
895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    int foreign_window_manager_id;
905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  };
915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
92010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Attempts to convert the selection to |target|. If the conversion is
93010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // successful, true is returned and the result is stored in the |property|
94010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // of |requestor|.
95116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  bool ProcessTarget(XAtom target, XID requestor, XAtom property);
96010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Sends the next chunk of data for given the incremental data transfer.
985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  void ProcessIncrementalTransfer(IncrementalTransfer* transfer);
995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Aborts any incremental data transfers which have timed out.
1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  void AbortStaleIncrementalTransfers();
1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Called when the transfer at |it| has completed to do cleanup.
1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  void CompleteIncrementalTransfer(
1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      std::vector<IncrementalTransfer>::iterator it);
1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Returns the incremental data transfer, if any, which was waiting for
1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // |event|.
1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  std::vector<IncrementalTransfer>::iterator FindIncrementalTransferForEvent(
1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      const XEvent& event);
1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Our X11 state.
113116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  XDisplay* x_display_;
114116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  XID x_window_;
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // The X11 selection that this instance communicates on.
117116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  XAtom selection_name_;
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // The maximum size of data we can put in XChangeProperty().
1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  size_t max_request_size_;
1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // The data we are currently serving.
123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SelectionFormatMap format_map_;
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  std::vector<IncrementalTransfer> incremental_transfers_;
1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Used to abort stale incremental data transfers.
1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  base::RepeatingTimer<SelectionOwner> incremental_transfer_abort_timer_;
1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  X11AtomCache atom_cache_;
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SelectionOwner);
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace ui
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif  // UI_BASE_X_SELECTION_OWNER_H_
138