Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(420)

Side by Side Diff: ui/views/cocoa/cocoa_non_client_drag.mm

Issue 1146873002: [MacViews] Enable dragging a window by its caption/draggable areas. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Update comments. Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #import "ui/views/cocoa/cocoa_non_client_drag.h"
6
7 #import <Cocoa/Cocoa.h>
8
9 #include "base/logging.h"
10 #import "base/mac/foundation_util.h"
11 #include "base/process/process_handle.h"
12
13 @implementation CocoaNonClientDragMaskView
14
15 - (BOOL)mouseDownCanMoveWindow {
16 return NO;
17 }
18
19 - (NSView*)hitTest:(NSPoint)aPoint {
20 return nil;
21 }
22
23 @end
24
25 namespace views {
26
27 namespace {
28
29 int g_ref_count = 0;
30 CGEventRef g_last_reposted_event = 0;
31
32 CFRunLoopSourceRef g_run_loop_source = 0;
33 CFMachPortRef g_mach_port = 0;
34
35 id g_event_monitor = nil;
36
37 bool RepostEventIfHandledByWindow(NSWindow* window,
38 NSPoint location,
39 CGEventRef event) {
40 if ([window respondsToSelector:@selector(willReceiveLeftMouseDown:)] &&
41 [base::mac::ObjCCast<NativeWidgetMacNSWindow>(window)
42 willReceiveLeftMouseDown:location]) {
43 if (g_last_reposted_event != event) {
44 g_last_reposted_event = event;
45 CGEventPost(kCGSessionEventTap, event); // Repost event.
46 } else {
47 LOG(INFO) << "reposting already reposted event " << event;
48 }
49 return true;
50 }
51
52 return false;
53 }
54
55 CGEventRef EventTapCallBack(CGEventTapProxy proxy,
56 CGEventType type,
57 CGEventRef cg_event,
58 void* refcon) {
59 LOG(INFO) << "EventTapCallBack " << cg_event;
60 // Disable CGEventTap mechanism.
61 return cg_event;
62
63 pid_t target_pid =
64 CGEventGetIntegerValueField(cg_event, kCGEventTargetUnixProcessID);
65 if (base::GetCurrentProcId() != target_pid)
66 return cg_event;
67
68 if (type != kCGEventLeftMouseDown)
69 return cg_event;
70
71 NSPoint location = NSPointFromCGPoint(CGEventGetUnflippedLocation(cg_event));
72
73 // Find the window this event lands on.
74 NSWindow* target = nil;
75 for (NSWindow* window in [NSApp windows]) {
76 if (NSPointInRect(location, [window frame])) {
77 target = window;
78 break;
79 }
80 }
81 if (!target)
82 return cg_event;
83
84 if (RepostEventIfHandledByWindow(
85 target, [target convertScreenToBase:location], cg_event)) {
86 return nil;
87 }
88
89 return cg_event;
90 }
91
92 } // namespace
93
94 CocoaNonClientDrag::CocoaNonClientDrag() {
95 if (g_ref_count)
96 return;
97
98 ////////////////////////////////////////////////////////////////////////////////
99 // CGEventTap setup.
100 if (!g_mach_port) {
101 // We cant use kCGAnnotatedSessionEventTap or CGEventTapCreateForPSN because
102 // they both happen after window movement happens.
103 g_mach_port = CGEventTapCreate(
104 kCGSessionEventTap, // After event has been annotated to flow to an
105 // application.
106 kCGHeadInsertEventTap,
107 kCGEventTapOptionDefault, // An active listener, can swallow events.
108 1 << kCGEventLeftMouseDown, &EventTapCallBack, NULL);
109 }
110 if (!g_run_loop_source)
111 g_run_loop_source = CFMachPortCreateRunLoopSource(NULL, g_mach_port, 0);
112
113 CFRunLoopAddSource(CFRunLoopGetMain(), g_run_loop_source,
114 kCFRunLoopCommonModes);
115 CGEventTapEnable(g_mach_port, true);
116 //
117 ////////////////////////////////////////////////////////////////////////////////
118 // NSEvent local monitor setup.
119 NSEvent* (^monitor_callback)(NSEvent* ns_event);
120 monitor_callback = ^NSEvent*(NSEvent* ns_event) {
121 CGEventRef cg_event = [ns_event CGEvent];
122 LOG(INFO) << "MonitorCallback " << cg_event;
123 if (RepostEventIfHandledByWindow([ns_event window],
124 [ns_event locationInWindow],
125 cg_event)) {
126 return nil;
127 }
128 return ns_event;
129 };
130
131 g_event_monitor =
132 [NSEvent addLocalMonitorForEventsMatchingMask:NSLeftMouseDownMask
133 handler:monitor_callback];
134 //
135 ////////////////////////////////////////////////////////////////////////////////
136
137 ++g_ref_count;
138 }
139
140 CocoaNonClientDrag::~CocoaNonClientDrag() {
141 --g_ref_count;
142 if (g_ref_count)
143 return;
144
145 ////////////////////////////////////////////////////////////////////////////////
146 // CGEventTap cleanup.
147 CFRunLoopRemoveSource(CFRunLoopGetMain(), g_run_loop_source,
148 kCFRunLoopCommonModes);
149 //
150 ////////////////////////////////////////////////////////////////////////////////
151 // NSEvent local monitor cleanup.
152 if (g_event_monitor) {
153 [NSEvent removeMonitor:g_event_monitor];
154 g_event_monitor = nil;
155 }
156 //
157 ////////////////////////////////////////////////////////////////////////////////
158 }
159
160 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698