Index: ui/views/cocoa/cocoa_non_client_drag.mm |
diff --git a/ui/views/cocoa/cocoa_non_client_drag.mm b/ui/views/cocoa/cocoa_non_client_drag.mm |
new file mode 100644 |
index 0000000000000000000000000000000000000000..f36e69e8819c1130f2349a439f20b74150ca76e7 |
--- /dev/null |
+++ b/ui/views/cocoa/cocoa_non_client_drag.mm |
@@ -0,0 +1,77 @@ |
+// Copyright 2015 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. |
+ |
+#import "ui/views/cocoa/cocoa_non_client_drag.h" |
+ |
+#import <Cocoa/Cocoa.h> |
+ |
+#include "base/logging.h" |
+#import "base/mac/foundation_util.h" |
+#include "base/process/process_handle.h" |
+ |
+namespace views { |
+ |
+namespace { |
+ |
+int g_ref_count = 0; |
jackhou1
2015/05/20 05:50:37
Do we already have something that implements this
tapted
2015/05/20 07:18:17
Yeah I would just create it lazily, once, and not
jackhou1
2015/05/22 02:49:17
Done.
|
+id g_event_monitor = nil; |
+bool is_first_repost = false; |
tapted
2015/05/20 07:18:18
make this a local static of DoubleRepostEventIfHan
jackhou1
2015/05/22 02:49:16
Fortunately, the eventNumber does remain unchanged
|
+ |
+bool DoubleRepostEventIfHandledByWindow(NSWindow* window, |
+ NSPoint location, |
+ CGEventRef event) { |
+ // If the event was just reposted, repost it again, otherwise it won't work. |
+ if (is_first_repost) { |
+ LOG(INFO) << "double reposting " << event; |
+ is_first_repost = false; |
+ CGEventPost(kCGSessionEventTap, event); |
+ return true; |
+ } |
+ if ([window respondsToSelector:@selector(willReceiveLeftMouseDown:)] && |
tapted
2015/05/20 07:18:17
maybe just check if [[window delegate] respondsToS
jackhou1
2015/05/22 02:49:17
Done.
|
+ [base::mac::ObjCCast<NativeWidgetMacNSWindow>(window) |
+ willReceiveLeftMouseDown:location]) { |
+ is_first_repost = true; |
+ CGEventPost(kCGSessionEventTap, event); |
+ return true; |
+ } |
+ |
+ return false; |
+} |
+ |
+} // namespace |
+ |
+CocoaNonClientDrag::CocoaNonClientDrag() { |
+ if (g_ref_count) |
+ return; |
+ |
+ NSEvent* (^monitor_callback)(NSEvent* ns_event); |
+ monitor_callback = ^NSEvent*(NSEvent* ns_event) { |
+ CGEventRef cg_event = [ns_event CGEvent]; |
+ LOG(INFO) << "MonitorCallback " << cg_event; |
+ if (DoubleRepostEventIfHandledByWindow( |
tapted
2015/05/20 07:18:18
just pass ns_event?
jackhou1
2015/05/22 02:49:16
Done.
|
+ [ns_event window], [ns_event locationInWindow], cg_event)) { |
+ return nil; |
+ } |
+ return ns_event; |
+ }; |
+ |
+ g_event_monitor = |
tapted
2015/05/20 07:18:18
I guess this can be a static local too.
jackhou1
2015/05/22 02:49:17
Done.
|
+ [NSEvent addLocalMonitorForEventsMatchingMask:NSLeftMouseDownMask |
+ handler:monitor_callback]; |
+ |
+ ++g_ref_count; |
+} |
+ |
+CocoaNonClientDrag::~CocoaNonClientDrag() { |
+ --g_ref_count; |
tapted
2015/05/20 07:18:18
I guess this would just become a NOTREACHED() with
jackhou1
2015/05/22 02:49:16
Done.
|
+ if (g_ref_count) |
+ return; |
+ |
+ if (g_event_monitor) { |
+ [NSEvent removeMonitor:g_event_monitor]; |
+ g_event_monitor = nil; |
+ } |
+} |
+ |
+} // namespace views |