diff options
author | erg@chromium.org <erg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-06 06:49:22 +0000 |
---|---|---|
committer | erg@chromium.org <erg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-06 06:49:22 +0000 |
commit | 3a0c0cc5588c22c639c26e81cbfdcde4f8ae8a1b (patch) | |
tree | 0519577a16e169ee90038119f0c84e262a699745 /ui/base/x/selection_requestor.cc | |
parent | 880601e8794f18c4e026ead48fb4974eaaec6c3a (diff) | |
download | chromium_src-3a0c0cc5588c22c639c26e81cbfdcde4f8ae8a1b.zip chromium_src-3a0c0cc5588c22c639c26e81cbfdcde4f8ae8a1b.tar.gz chromium_src-3a0c0cc5588c22c639c26e81cbfdcde4f8ae8a1b.tar.bz2 |
linux_aura: Split up the monolithic Clipboard::AuraX11Details into several utility classes that can be reused from the Xdnd implementation.
BUG=130806
Review URL: https://chromiumcodereview.appspot.com/13461031
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@192717 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/base/x/selection_requestor.cc')
-rw-r--r-- | ui/base/x/selection_requestor.cc | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/ui/base/x/selection_requestor.cc b/ui/base/x/selection_requestor.cc new file mode 100644 index 0000000..0aec086 --- /dev/null +++ b/ui/base/x/selection_requestor.cc @@ -0,0 +1,139 @@ +// 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. + +#include "ui/base/x/selection_requestor.h" + +#include "base/message_pump_aurax11.h" +#include "base/run_loop.h" + +namespace ui { + +namespace { + +const char kChromeSelection[] = "CHROME_SELECTION"; + +const char* kAtomsToCache[] = { + kChromeSelection, + NULL +}; + +} // namespace + +SelectionRequestor::SelectionRequestor(Display* x_display, + Window x_window, + Atom selection_name) + : x_display_(x_display), + x_window_(x_window), + in_nested_loop_(false), + selection_name_(selection_name), + current_target_(None), + returned_property_(None), + atom_cache_(x_display_, kAtomsToCache) { +} + +SelectionRequestor::~SelectionRequestor() {} + +bool SelectionRequestor::PerformBlockingConvertSelection( + Atom target, + unsigned char** out_data, + size_t* out_data_bytes, + size_t* out_data_items, + Atom* out_type) { + // The name of the property we're asking to be set on |x_window_|. + Atom property_to_set = atom_cache_.GetAtom(kChromeSelection); + + XConvertSelection(x_display_, + selection_name_, + target, + property_to_set, + x_window_, + CurrentTime); + + // Now that we've thrown our message off to the X11 server, we block waiting + // for a response. + MessageLoopForUI* loop = MessageLoopForUI::current(); + MessageLoop::ScopedNestableTaskAllower allow_nested(loop); + base::RunLoop run_loop(base::MessagePumpAuraX11::Current()); + + current_target_ = target; + in_nested_loop_ = true; + quit_closure_ = run_loop.QuitClosure(); + run_loop.Run(); + in_nested_loop_ = false; + current_target_ = None; + + if (returned_property_ != property_to_set) + return false; + + // Retrieve the data from our window. + unsigned long nitems = 0; + unsigned long nbytes = 0; + Atom prop_type = None; + int prop_format = 0; + unsigned char* property_data = NULL; + if (XGetWindowProperty(x_display_, + x_window_, + returned_property_, + 0, 0x1FFFFFFF /* MAXINT32 / 4 */, False, + AnyPropertyType, &prop_type, &prop_format, + &nitems, &nbytes, &property_data) != Success) { + return false; + } + + if (prop_type == None) + return false; + + if (out_data) + *out_data = property_data; + + if (out_data_bytes) { + // So even though we should theoretically have nbytes (and we can't + // pass NULL there), we need to manually calculate the byte length here + // because nbytes always returns zero. + switch (prop_format) { + case 8: + *out_data_bytes = nitems; + break; + case 16: + *out_data_bytes = sizeof(short) * nitems; + break; + case 32: + *out_data_bytes = sizeof(long) * nitems; + break; + default: + NOTREACHED(); + break; + } + } + + if (out_data_items) + *out_data_items = nitems; + + if (out_type) + *out_type = prop_type; + + return true; +} + +void SelectionRequestor::OnSelectionNotify(const XSelectionEvent& event) { + if (!in_nested_loop_) { + // This shouldn't happen; we're not waiting on the X server for data, but + // any client can send any message... + return; + } + + if (selection_name_ == event.selection && + current_target_ == event.target) { + returned_property_ = event.property; + } else { + // I am assuming that if some other client sent us a message after we've + // asked for data, but it's malformed, we should just treat as if they sent + // us an error message. + returned_property_ = None; + } + + quit_closure_.Run(); +} + +} // namespace ui |