Chromium Code Reviews| 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 |