Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / ui / base / x / selection_requestor.cc
index abb8dc5..a946787 100644 (file)
@@ -4,10 +4,12 @@
 
 #include "ui/base/x/selection_requestor.h"
 
-#include "base/message_loop/message_pump_x11.h"
 #include "base/run_loop.h"
 #include "ui/base/x/selection_utils.h"
 #include "ui/base/x/x11_util.h"
+#include "ui/events/platform/platform_event_dispatcher.h"
+#include "ui/events/platform/platform_event_source.h"
+#include "ui/gfx/x/x11_types.h"
 
 namespace ui {
 
@@ -24,10 +26,12 @@ const char* kAtomsToCache[] = {
 
 SelectionRequestor::SelectionRequestor(Display* x_display,
                                        Window x_window,
-                                       Atom selection_name)
+                                       Atom selection_name,
+                                       PlatformEventDispatcher* dispatcher)
     : x_display_(x_display),
       x_window_(x_window),
       selection_name_(selection_name),
+      dispatcher_(dispatcher),
       atom_cache_(x_display_, kAtomsToCache) {
 }
 
@@ -39,38 +43,26 @@ bool SelectionRequestor::PerformBlockingConvertSelection(
     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);
+  // The name of the property that we are either:
+  // - Passing as a parameter with the XConvertSelection() request.
+  // OR
+  // - Asking the selection owner to set on |x_window_|.
+  Atom property = atom_cache_.GetAtom(kChromeSelection);
 
   XConvertSelection(x_display_,
                     selection_name_,
                     target,
-                    property_to_set,
+                    property,
                     x_window_,
                     CurrentTime);
 
   // Now that we've thrown our message off to the X11 server, we block waiting
   // for a response.
-  base::MessageLoopForUI* loop = base::MessageLoopForUI::current();
-  base::MessageLoop::ScopedNestableTaskAllower allow_nested(loop);
-  base::RunLoop run_loop;
-
-  // Stop waiting for a response after a certain amount of time.
-  const int kMaxWaitTimeForClipboardResponse = 300;
-  loop->PostDelayedTask(
-      FROM_HERE,
-      run_loop.QuitClosure(),
-      base::TimeDelta::FromMilliseconds(kMaxWaitTimeForClipboardResponse));
-
-  PendingRequest pending_request(target, run_loop.QuitClosure());
-  pending_requests_.push_back(&pending_request);
-  run_loop.Run();
-  DCHECK(!pending_requests_.empty());
-  DCHECK_EQ(&pending_request, pending_requests_.back());
-  pending_requests_.pop_back();
+  PendingRequest pending_request(target);
+  BlockTillSelectionNotifyForRequest(&pending_request);
 
   bool success = false;
-  if (pending_request.returned_property == property_to_set) {
+  if (pending_request.returned_property == property) {
     success =  ui::GetRawBytesOfProperty(x_window_,
                                          pending_request.returned_property,
                                          out_data, out_data_bytes,
@@ -81,6 +73,13 @@ bool SelectionRequestor::PerformBlockingConvertSelection(
   return success;
 }
 
+void SelectionRequestor::PerformBlockingConvertSelectionWithParameter(
+    Atom target,
+    const std::vector< ::Atom>& parameter) {
+  SetAtomArrayProperty(x_window_, kChromeSelection, "ATOM", parameter);
+  PerformBlockingConvertSelection(target, NULL, NULL, NULL, NULL);
+}
+
 SelectionData SelectionRequestor::RequestAndWaitForTypes(
     const std::vector< ::Atom>& types) {
   for (std::vector< ::Atom>::const_iterator it = types.begin();
@@ -133,13 +132,51 @@ void SelectionRequestor::OnSelectionNotify(const XSelectionEvent& event) {
 
   request_notified->returned_property = event.property;
   request_notified->returned = true;
-  request_notified->quit_closure.Run();
+
+  if (!request_notified->quit_closure.is_null())
+    request_notified->quit_closure.Run();
+}
+
+void SelectionRequestor::BlockTillSelectionNotifyForRequest(
+    PendingRequest* request) {
+  pending_requests_.push_back(request);
+
+  const int kMaxWaitTimeForClipboardResponse = 300;
+  if (PlatformEventSource::GetInstance()) {
+    base::MessageLoopForUI* loop = base::MessageLoopForUI::current();
+    base::MessageLoop::ScopedNestableTaskAllower allow_nested(loop);
+    base::RunLoop run_loop;
+
+    request->quit_closure = run_loop.QuitClosure();
+    loop->PostDelayedTask(
+        FROM_HERE,
+        request->quit_closure,
+        base::TimeDelta::FromMilliseconds(kMaxWaitTimeForClipboardResponse));
+
+    run_loop.Run();
+  } else {
+    // This occurs if PerformBlockingConvertSelection() is called during
+    // shutdown and the PlatformEventSource has already been destroyed.
+    base::TimeTicks start = base::TimeTicks::Now();
+    while (!request->returned) {
+      if (XPending(x_display_)) {
+        XEvent event;
+        XNextEvent(x_display_, &event);
+        dispatcher_->DispatchEvent(&event);
+      }
+      base::TimeDelta wait_time = base::TimeTicks::Now() - start;
+      if (wait_time.InMilliseconds() > kMaxWaitTimeForClipboardResponse)
+        break;
+    }
+  }
+
+  DCHECK(!pending_requests_.empty());
+  DCHECK_EQ(request, pending_requests_.back());
+  pending_requests_.pop_back();
 }
 
-SelectionRequestor::PendingRequest::PendingRequest(Atom target,
-                                                   base::Closure quit_closure)
+SelectionRequestor::PendingRequest::PendingRequest(Atom target)
     : target(target),
-      quit_closure(quit_closure),
       returned_property(None),
       returned(false) {
 }