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