OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/ui/cocoa/panels/panel_window_controller_cocoa.h" | 5 #include "chrome/browser/ui/cocoa/panels/panel_window_controller_cocoa.h" |
6 | 6 |
7 #import <Cocoa/Cocoa.h> | 7 #import <Cocoa/Cocoa.h> |
8 | 8 |
9 #include "base/auto_reset.h" | 9 #include "base/auto_reset.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 10 matching lines...) Expand all Loading... | |
21 #import "chrome/browser/ui/cocoa/panels/panel_cocoa.h" | 21 #import "chrome/browser/ui/cocoa/panels/panel_cocoa.h" |
22 #import "chrome/browser/ui/cocoa/panels/panel_titlebar_view_cocoa.h" | 22 #import "chrome/browser/ui/cocoa/panels/panel_titlebar_view_cocoa.h" |
23 #import "chrome/browser/ui/cocoa/panels/panel_utils_cocoa.h" | 23 #import "chrome/browser/ui/cocoa/panels/panel_utils_cocoa.h" |
24 #import "chrome/browser/ui/cocoa/tab_contents/favicon_util_mac.h" | 24 #import "chrome/browser/ui/cocoa/tab_contents/favicon_util_mac.h" |
25 #import "chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.h" | 25 #import "chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.h" |
26 #import "chrome/browser/ui/cocoa/tabs/throbber_view.h" | 26 #import "chrome/browser/ui/cocoa/tabs/throbber_view.h" |
27 #include "chrome/browser/ui/panels/panel_bounds_animation.h" | 27 #include "chrome/browser/ui/panels/panel_bounds_animation.h" |
28 #include "chrome/browser/ui/panels/panel_collection.h" | 28 #include "chrome/browser/ui/panels/panel_collection.h" |
29 #include "chrome/browser/ui/panels/panel_constants.h" | 29 #include "chrome/browser/ui/panels/panel_constants.h" |
30 #include "chrome/browser/ui/panels/panel_manager.h" | 30 #include "chrome/browser/ui/panels/panel_manager.h" |
31 #include "chrome/browser/ui/panels/stacked_panel_collection.h" | |
31 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 32 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
32 #include "chrome/browser/ui/toolbar/encoding_menu_controller.h" | 33 #include "chrome/browser/ui/toolbar/encoding_menu_controller.h" |
33 #include "content/public/browser/render_widget_host_view.h" | 34 #include "content/public/browser/render_widget_host_view.h" |
34 #include "content/public/browser/web_contents.h" | 35 #include "content/public/browser/web_contents.h" |
35 #include "content/public/browser/web_contents_view.h" | 36 #include "content/public/browser/web_contents_view.h" |
36 #include "grit/ui_resources.h" | 37 #include "grit/ui_resources.h" |
37 #include "third_party/WebKit/public/web/WebCursorInfo.h" | |
38 #include "ui/base/resource/resource_bundle.h" | 38 #include "ui/base/resource/resource_bundle.h" |
39 #include "ui/gfx/image/image.h" | 39 #include "ui/gfx/image/image.h" |
40 #include "webkit/common/cursors/webcursor.h" | |
41 | 40 |
42 using content::WebContents; | 41 using content::WebContents; |
43 | 42 |
44 const int kMinimumWindowSize = 1; | 43 const int kMinimumWindowSize = 1; |
45 const double kBoundsAnimationSpeedPixelsPerSecond = 1000; | 44 const double kBoundsAnimationSpeedPixelsPerSecond = 1000; |
46 const double kBoundsAnimationMaxDurationSeconds = 0.18; | 45 const double kBoundsAnimationMaxDurationSeconds = 0.18; |
47 | 46 |
48 // Resize edge thickness, in screen pixels. | 47 // Edge thickness to trigger user resizing via system, in screen pixels. |
49 const double kWidthOfMouseResizeArea = 4.0; | 48 const double kWidthOfMouseResizeArea = 15.0; |
50 | 49 |
51 @interface PanelWindowControllerCocoa (PanelsCanBecomeKey) | 50 @interface PanelWindowControllerCocoa (PanelsCanBecomeKey) |
52 // Internal helper method for extracting the total number of panel windows | 51 // Internal helper method for extracting the total number of panel windows |
53 // from the panel manager. Used to decide if panel can become the key window. | 52 // from the panel manager. Used to decide if panel can become the key window. |
54 - (int)numPanels; | 53 - (int)numPanels; |
55 @end | 54 @end |
56 | 55 |
57 @implementation PanelWindowCocoaImpl | 56 @implementation PanelWindowCocoaImpl |
58 // The panels cannot be reduced to 3-px windows on the edge of the screen | 57 // The panels cannot be reduced to 3-px windows on the edge of the screen |
59 // active area (above Dock). Default constraining logic makes at least a height | 58 // active area (above Dock). Default constraining logic makes at least a height |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
101 // Ignore key events if window cannot become key window to fix problem | 100 // Ignore key events if window cannot become key window to fix problem |
102 // where keyboard input is still going into a minimized panel even though | 101 // where keyboard input is still going into a minimized panel even though |
103 // the app has been deactivated in -[PanelWindowControllerCocoa deactivate:]. | 102 // the app has been deactivated in -[PanelWindowControllerCocoa deactivate:]. |
104 - (void)sendEvent:(NSEvent*)anEvent { | 103 - (void)sendEvent:(NSEvent*)anEvent { |
105 NSEventType eventType = [anEvent type]; | 104 NSEventType eventType = [anEvent type]; |
106 if ((eventType == NSKeyDown || eventType == NSKeyUp) && | 105 if ((eventType == NSKeyDown || eventType == NSKeyUp) && |
107 ![self canBecomeKeyWindow]) | 106 ![self canBecomeKeyWindow]) |
108 return; | 107 return; |
109 [super sendEvent:anEvent]; | 108 [super sendEvent:anEvent]; |
110 } | 109 } |
111 @end | |
112 | 110 |
113 // Transparent view covering the whole panel in order to intercept mouse | 111 - (void)mouseMoved:(NSEvent*)event { |
114 // messages for custom user resizing. We need custom resizing because panels | 112 // Cocoa does not support letting the application determine the edges that |
115 // use their own constrained layout. | 113 // can trigger the user resizing. To work around this, we track the mouse |
116 @interface PanelResizeByMouseOverlay : NSView <MouseDragControllerClient> { | 114 // location. When it is close to the edge/corner where the user resizing |
117 @private | 115 // is not desired, we force the min and max size of the window to be same |
118 Panel* panel_; | 116 // as current window size. For all other cases, we restore the min and max |
119 base::scoped_nsobject<MouseDragController> dragController_; | 117 // size. |
120 base::scoped_nsobject<NSCursor> dragCursor_; | 118 PanelWindowControllerCocoa* controller = |
121 base::scoped_nsobject<NSCursor> eastWestCursor_; | 119 base::mac::ObjCCast<PanelWindowControllerCocoa>([self windowController]); |
122 base::scoped_nsobject<NSCursor> northSouthCursor_; | 120 NSRect frame = [self frame]; |
123 base::scoped_nsobject<NSCursor> northEastSouthWestCursor_; | 121 if ([controller canResizeByMouseAtCurrentLocation]) { |
124 base::scoped_nsobject<NSCursor> northWestSouthEastCursor_; | 122 // Mac window server limits window sizes to 10000. |
125 NSRect leftCursorRect_; | 123 NSSize maxSize = NSMakeSize(10000, 10000); |
126 NSRect rightCursorRect_; | 124 |
127 NSRect topCursorRect_; | 125 // If the user is resizing a stacked panel by its bottom edge, make sure its |
128 NSRect bottomCursorRect_; | 126 // height cannot grow more than what the panel below it could offer. This is |
129 NSRect topLeftCursorRect_; | 127 // because growing a stacked panel by y amount will shrink the panel below |
130 NSRect topRightCursorRect_; | 128 // it by same amount and we do not want the panel below it being shrunk to |
131 NSRect bottomLeftCursorRect_; | 129 // be smaller than the titlebar. |
132 NSRect bottomRightCursorRect_; | 130 Panel* panel = [controller panel]; |
131 NSPoint point = [NSEvent mouseLocation]; | |
132 if (point.y < NSMinY(frame) + kWidthOfMouseResizeArea && panel->stack()) { | |
133 Panel* belowPanel = panel->stack()->GetPanelBelow(panel); | |
134 if (belowPanel && !belowPanel->IsMinimized()) { | |
135 maxSize.height = panel->GetBounds().height() + | |
136 belowPanel->GetBounds().height() - panel::kTitlebarHeight; | |
137 } | |
138 } | |
139 | |
140 // Enable the user-resizing by setting both min and max size to the right | |
141 // values. | |
142 [self setMinSize:NSMakeSize(panel::kPanelMinWidth, | |
143 panel::kPanelMinHeight)]; | |
144 [self setMaxSize:maxSize]; | |
145 } else { | |
146 // Disable the user-resizing by setting both min and max size to be same as | |
147 // current window size. | |
148 [self setMinSize:frame.size]; | |
149 [self setMaxSize:frame.size]; | |
150 } | |
151 | |
152 [super mouseMoved:event]; | |
133 } | 153 } |
134 @end | 154 @end |
135 | 155 |
136 namespace { | |
137 NSCursor* LoadWebKitCursor(WebKit::WebCursorInfo::Type type) { | |
138 return WebCursor(WebCursor::CursorInfo(type)).GetNativeCursor(); | |
139 } | |
140 } | |
141 | |
142 @implementation PanelResizeByMouseOverlay | |
143 - (PanelResizeByMouseOverlay*)initWithFrame:(NSRect)frame panel:(Panel*)panel { | |
144 if ((self = [super initWithFrame:frame])) { | |
145 panel_ = panel; | |
146 dragController_.reset([[MouseDragController alloc] initWithClient:self]); | |
147 | |
148 eastWestCursor_.reset( | |
149 [LoadWebKitCursor(WebKit::WebCursorInfo::TypeEastWestResize) retain]); | |
150 northSouthCursor_.reset( | |
151 [LoadWebKitCursor(WebKit::WebCursorInfo::TypeNorthSouthResize) retain]); | |
152 northEastSouthWestCursor_.reset( | |
153 [LoadWebKitCursor(WebKit::WebCursorInfo::TypeNorthEastSouthWestResize) | |
154 retain]); | |
155 northWestSouthEastCursor_.reset( | |
156 [LoadWebKitCursor(WebKit::WebCursorInfo::TypeNorthWestSouthEastResize) | |
157 retain]); | |
158 } | |
159 return self; | |
160 } | |
161 | |
162 - (BOOL)acceptsFirstMouse:(NSEvent*)event { | |
163 return YES; | |
164 } | |
165 | |
166 // |pointInWindow| is in window coordinates. | |
167 - (panel::ResizingSides)edgeHitTest:(NSPoint)pointInWindow { | |
168 panel::Resizability resizability = panel_->CanResizeByMouse(); | |
169 DCHECK_NE(panel::NOT_RESIZABLE, resizability); | |
170 | |
171 NSPoint point = [self convertPoint:pointInWindow fromView:nil]; | |
172 BOOL flipped = [self isFlipped]; | |
173 | |
174 if ((resizability & panel::RESIZABLE_TOP_LEFT) && | |
175 NSMouseInRect(point, topLeftCursorRect_, flipped)) { | |
176 return panel::RESIZE_TOP_LEFT; | |
177 } | |
178 if ((resizability & panel::RESIZABLE_TOP_RIGHT) && | |
179 NSMouseInRect(point, topRightCursorRect_, flipped)) { | |
180 return panel::RESIZE_TOP_RIGHT; | |
181 } | |
182 if ((resizability & panel::RESIZABLE_BOTTOM_LEFT) && | |
183 NSMouseInRect(point, bottomLeftCursorRect_, flipped)) { | |
184 return panel::RESIZE_BOTTOM_LEFT; | |
185 } | |
186 if ((resizability & panel::RESIZABLE_BOTTOM_RIGHT) && | |
187 NSMouseInRect(point, bottomRightCursorRect_, flipped)) { | |
188 return panel::RESIZE_BOTTOM_RIGHT; | |
189 } | |
190 | |
191 if ((resizability & panel::RESIZABLE_LEFT) && | |
192 NSMouseInRect(point, leftCursorRect_, flipped)) { | |
193 return panel::RESIZE_LEFT; | |
194 } | |
195 if ((resizability & panel::RESIZABLE_RIGHT) && | |
196 NSMouseInRect(point, rightCursorRect_, flipped)) { | |
197 return panel::RESIZE_RIGHT; | |
198 } | |
199 if ((resizability & panel::RESIZABLE_TOP) && | |
200 NSMouseInRect(point, topCursorRect_, flipped)) { | |
201 return panel::RESIZE_TOP; | |
202 } | |
203 if ((resizability & panel::RESIZABLE_BOTTOM) && | |
204 NSMouseInRect(point, bottomCursorRect_, flipped)) { | |
205 return panel::RESIZE_BOTTOM; | |
206 } | |
207 | |
208 return panel::RESIZE_NONE; | |
209 } | |
210 | |
211 // NSWindow uses this method to figure out if this view is under the mouse | |
212 // and hence the one to handle the incoming mouse event. | |
213 // Since this view covers the whole panel, it is asked first. | |
214 // See if this is the mouse event we are interested in (in the resize areas) | |
215 // and return 'nil' to let NSWindow find another candidate otherwise. | |
216 // |point| is in coordinate system of the parent view. | |
217 - (NSView*)hitTest:(NSPoint)point { | |
218 // If panel is not resizable, let the mouse events fall through. | |
219 if (panel::NOT_RESIZABLE == panel_->CanResizeByMouse()) | |
220 return nil; | |
221 | |
222 NSPoint pointInWindow = [[self superview] convertPoint:point toView:nil]; | |
223 return [self edgeHitTest:pointInWindow] == panel::RESIZE_NONE ? nil : self; | |
224 } | |
225 | |
226 // Delegate these to MouseDragController, it will call back on | |
227 // MouseDragControllerClient protocol. | |
228 - (void)mouseDown:(NSEvent*)event { | |
229 [dragController_ mouseDown:event]; | |
230 } | |
231 | |
232 - (void)mouseDragged:(NSEvent*)event { | |
233 [dragController_ mouseDragged:event]; | |
234 } | |
235 | |
236 - (void)mouseUp:(NSEvent*)event { | |
237 [dragController_ mouseUp:event]; | |
238 } | |
239 | |
240 // MouseDragControllerClient protocol. | |
241 | |
242 - (void)prepareForDrag { | |
243 // If the panel is not resizable, hitTest should have failed and no mouse | |
244 // events should have come here. | |
245 DCHECK_NE(panel::NOT_RESIZABLE, panel_->CanResizeByMouse()); | |
246 | |
247 // Make sure the cursor stays the same during whole resize operation. | |
248 // The cursor rects normally do not guarantee the same cursor, since the | |
249 // mouse may temporarily leave the cursor rect area (or even the window) so | |
250 // the cursor will flicker. Disable cursor rects and grab the current cursor | |
251 // so we can set it on mouseDragged: events to avoid flicker. | |
252 [[self window] disableCursorRects]; | |
253 dragCursor_.reset([[NSCursor currentCursor] retain]); | |
254 } | |
255 | |
256 - (void)cleanupAfterDrag { | |
257 [[self window] enableCursorRects]; | |
258 dragCursor_.reset(); | |
259 } | |
260 | |
261 - (void)dragStarted:(NSPoint)initialMouseLocation { | |
262 NSPoint initialMouseLocationScreen = | |
263 [[self window] convertBaseToScreen:initialMouseLocation]; | |
264 | |
265 panel_->manager()->StartResizingByMouse( | |
266 panel_, | |
267 cocoa_utils::ConvertPointFromCocoaCoordinates(initialMouseLocationScreen), | |
268 [self edgeHitTest:initialMouseLocation]); | |
269 } | |
270 | |
271 - (void)dragProgress:(NSPoint)mouseLocation { | |
272 NSPoint mouseLocationScreen = | |
273 [[self window] convertBaseToScreen:mouseLocation]; | |
274 panel_->manager()->ResizeByMouse( | |
275 cocoa_utils::ConvertPointFromCocoaCoordinates(mouseLocationScreen)); | |
276 | |
277 // Set the resize cursor on every mouse drag event in case the mouse | |
278 // wandered outside the window and was switched to another one. | |
279 // This does not produce flicker, seems the real cursor is updated after | |
280 // mouseDrag is processed. | |
281 [dragCursor_ set]; | |
282 } | |
283 | |
284 - (void)dragEnded:(BOOL)cancelled { | |
285 panel_->manager()->EndResizingByMouse(cancelled); | |
286 } | |
287 | |
288 - (void)resetCursorRects { | |
289 panel::Resizability resizability = panel_->CanResizeByMouse(); | |
290 if (panel::NOT_RESIZABLE == resizability) | |
291 return; | |
292 | |
293 NSRect bounds = [self bounds]; | |
294 | |
295 // Left vertical edge. | |
296 if (resizability & panel::RESIZABLE_LEFT) { | |
297 leftCursorRect_ = NSMakeRect( | |
298 NSMinX(bounds), | |
299 NSMinY(bounds) + kWidthOfMouseResizeArea, | |
300 kWidthOfMouseResizeArea, | |
301 NSHeight(bounds) - 2 * kWidthOfMouseResizeArea); | |
302 [self addCursorRect:leftCursorRect_ cursor:eastWestCursor_]; | |
303 } | |
304 | |
305 // Right vertical edge. | |
306 if (resizability & panel::RESIZABLE_RIGHT) { | |
307 rightCursorRect_ = leftCursorRect_; | |
308 rightCursorRect_.origin.x = NSMaxX(bounds) - kWidthOfMouseResizeArea; | |
309 [self addCursorRect:rightCursorRect_ cursor:eastWestCursor_]; | |
310 } | |
311 | |
312 // Top horizontal edge. | |
313 if (resizability & panel::RESIZABLE_TOP) { | |
314 topCursorRect_ = NSMakeRect(NSMinX(bounds) + kWidthOfMouseResizeArea, | |
315 NSMaxY(bounds) - kWidthOfMouseResizeArea, | |
316 NSWidth(bounds) - 2 * kWidthOfMouseResizeArea, | |
317 kWidthOfMouseResizeArea); | |
318 [self addCursorRect:topCursorRect_ cursor:northSouthCursor_]; | |
319 } | |
320 | |
321 // Top left corner. | |
322 if (resizability & panel::RESIZABLE_TOP_LEFT) { | |
323 topLeftCursorRect_ = NSMakeRect(NSMinX(bounds), | |
324 NSMaxY(bounds) - kWidthOfMouseResizeArea, | |
325 kWidthOfMouseResizeArea, | |
326 NSMaxY(bounds)); | |
327 [self addCursorRect:topLeftCursorRect_ cursor:northWestSouthEastCursor_]; | |
328 } | |
329 | |
330 // Top right corner. | |
331 if (resizability & panel::RESIZABLE_TOP_RIGHT) { | |
332 topRightCursorRect_ = topLeftCursorRect_; | |
333 topRightCursorRect_.origin.x = NSMaxX(bounds) - kWidthOfMouseResizeArea; | |
334 [self addCursorRect:topRightCursorRect_ cursor:northEastSouthWestCursor_]; | |
335 } | |
336 | |
337 // Bottom horizontal edge. | |
338 if (resizability & panel::RESIZABLE_BOTTOM) { | |
339 bottomCursorRect_ = topCursorRect_; | |
340 bottomCursorRect_.origin.y = NSMinY(bounds); | |
341 [self addCursorRect:bottomCursorRect_ cursor:northSouthCursor_]; | |
342 } | |
343 | |
344 // Bottom right corner. | |
345 if (resizability & panel::RESIZABLE_BOTTOM_RIGHT) { | |
346 bottomRightCursorRect_ = topRightCursorRect_; | |
347 bottomRightCursorRect_.origin.y = NSMinY(bounds); | |
348 [self addCursorRect:bottomRightCursorRect_ | |
349 cursor:northWestSouthEastCursor_]; | |
350 } | |
351 | |
352 // Bottom left corner. | |
353 if (resizability & panel::RESIZABLE_BOTTOM_LEFT) { | |
354 bottomLeftCursorRect_ = bottomRightCursorRect_; | |
355 bottomLeftCursorRect_.origin.x = NSMinX(bounds); | |
356 [self addCursorRect:bottomLeftCursorRect_ cursor:northEastSouthWestCursor_]; | |
357 } | |
358 } | |
359 @end | |
360 | |
361 // ChromeEventProcessingWindow expects its controller to implement the | 156 // ChromeEventProcessingWindow expects its controller to implement the |
362 // BrowserCommandExecutor protocol. | 157 // BrowserCommandExecutor protocol. |
363 @interface PanelWindowControllerCocoa (InternalAPI) <BrowserCommandExecutor> | 158 @interface PanelWindowControllerCocoa (InternalAPI) <BrowserCommandExecutor> |
364 | 159 |
365 // BrowserCommandExecutor methods. | 160 // BrowserCommandExecutor methods. |
366 - (void)executeCommand:(int)command; | 161 - (void)executeCommand:(int)command; |
367 | 162 |
368 @end | 163 @end |
369 | 164 |
370 @implementation PanelWindowControllerCocoa (InternalAPI) | 165 @implementation PanelWindowControllerCocoa (InternalAPI) |
(...skipping 11 matching lines...) Expand all Loading... | |
382 [base::mac::FrameworkBundle() pathForResource:@"Panel" ofType:@"nib"]; | 177 [base::mac::FrameworkBundle() pathForResource:@"Panel" ofType:@"nib"]; |
383 if ((self = [super initWithWindowNibPath:nibpath owner:self])) { | 178 if ((self = [super initWithWindowNibPath:nibpath owner:self])) { |
384 windowShim_.reset(window); | 179 windowShim_.reset(window); |
385 animateOnBoundsChange_ = YES; | 180 animateOnBoundsChange_ = YES; |
386 canBecomeKeyWindow_ = YES; | 181 canBecomeKeyWindow_ = YES; |
387 activationRequestedByPanel_ = NO; | 182 activationRequestedByPanel_ = NO; |
388 } | 183 } |
389 return self; | 184 return self; |
390 } | 185 } |
391 | 186 |
187 - (Panel*)panel { | |
188 return windowShim_->panel(); | |
189 } | |
190 | |
392 - (void)awakeFromNib { | 191 - (void)awakeFromNib { |
393 NSWindow* window = [self window]; | 192 NSWindow* window = [self window]; |
394 | 193 |
395 DCHECK(window); | 194 DCHECK(window); |
396 DCHECK(titlebar_view_); | 195 DCHECK(titlebar_view_); |
397 DCHECK_EQ(self, [window delegate]); | 196 DCHECK_EQ(self, [window delegate]); |
398 | 197 |
399 [self updateWindowLevel]; | 198 [self updateWindowLevel]; |
400 | 199 |
401 [self updateWindowCollectionBehavior]; | 200 [self updateWindowCollectionBehavior]; |
402 | 201 |
403 [titlebar_view_ attach]; | 202 [titlebar_view_ attach]; |
404 | 203 |
405 // Set initial size of the window to match the size of the panel to give | 204 // Set initial size of the window to match the size of the panel to give |
406 // the renderer the proper size to work with earlier, avoiding a resize | 205 // the renderer the proper size to work with earlier, avoiding a resize |
407 // after the window is revealed. | 206 // after the window is revealed. |
408 gfx::Rect panelBounds = windowShim_->panel()->GetBounds(); | 207 gfx::Rect panelBounds = windowShim_->panel()->GetBounds(); |
409 NSRect frame = [window frame]; | 208 NSRect frame = [window frame]; |
410 frame.size.width = panelBounds.width(); | 209 frame.size.width = panelBounds.width(); |
411 frame.size.height = panelBounds.height(); | 210 frame.size.height = panelBounds.height(); |
412 [window setFrame:frame display:NO]; | 211 [window setFrame:frame display:NO]; |
413 | 212 |
414 // Add a transparent overlay on top of the whole window to process mouse | 213 // MacOS will turn the user-resizing to the user-dragging if the direction of |
415 // events - for example, user-resizing. | 214 // the dragging is orthogonal to the direction of the arrow cursor. We do not |
416 NSView* superview = [[window contentView] superview]; | 215 // want this since it will bypass our dragging logic. The panel window is |
417 NSRect bounds = [superview bounds]; | 216 // still draggable because we track and handle the dragging in our custom way. |
418 overlayView_.reset( | 217 [[self window] setMovable:NO]; |
419 [[PanelResizeByMouseOverlay alloc] initWithFrame:bounds | 218 |
420 panel:windowShim_->panel()]); | 219 [self updateTrackingArea]; |
421 // Set autoresizing behavior: glued to edges. | |
422 [overlayView_ setAutoresizingMask:(NSViewHeightSizable | NSViewWidthSizable)]; | |
423 [superview addSubview:overlayView_ positioned:NSWindowAbove relativeTo:nil]; | |
424 } | 220 } |
425 | 221 |
426 - (void)updateWebContentsViewFrame { | 222 - (void)updateWebContentsViewFrame { |
427 content::WebContents* webContents = windowShim_->panel()->GetWebContents(); | 223 content::WebContents* webContents = windowShim_->panel()->GetWebContents(); |
428 if (!webContents) | 224 if (!webContents) |
429 return; | 225 return; |
430 | 226 |
431 // Compute the size of the web contents view. Don't assume it's similar to the | 227 // Compute the size of the web contents view. Don't assume it's similar to the |
432 // size of the contentView, because the contentView is managed by the Cocoa | 228 // size of the contentView, because the contentView is managed by the Cocoa |
433 // to be (window - standard titlebar), while we have taller custom titlebar | 229 // to be (window - standard titlebar), while we have taller custom titlebar |
(...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
795 - (void)windowDidBecomeKey:(NSNotification*)notification { | 591 - (void)windowDidBecomeKey:(NSNotification*)notification { |
796 // We need to activate the controls (in the "WebView"). To do this, get the | 592 // We need to activate the controls (in the "WebView"). To do this, get the |
797 // selected WebContents's RenderWidgetHostView and tell it to activate. | 593 // selected WebContents's RenderWidgetHostView and tell it to activate. |
798 if (WebContents* contents = windowShim_->panel()->GetWebContents()) { | 594 if (WebContents* contents = windowShim_->panel()->GetWebContents()) { |
799 if (content::RenderWidgetHostView* rwhv = | 595 if (content::RenderWidgetHostView* rwhv = |
800 contents->GetRenderWidgetHostView()) | 596 contents->GetRenderWidgetHostView()) |
801 rwhv->SetActive(true); | 597 rwhv->SetActive(true); |
802 } | 598 } |
803 | 599 |
804 windowShim_->panel()->OnActiveStateChanged(true); | 600 windowShim_->panel()->OnActiveStateChanged(true); |
601 | |
602 // Make the window user-resizable when it gains the focus. | |
603 [[self window] setStyleMask: | |
604 [[self window] styleMask] | NSResizableWindowMask]; | |
805 } | 605 } |
806 | 606 |
807 - (void)windowDidResignKey:(NSNotification*)notification { | 607 - (void)windowDidResignKey:(NSNotification*)notification { |
808 // If our app is still active and we're still the key window, ignore this | 608 // If our app is still active and we're still the key window, ignore this |
809 // message, since it just means that a menu extra (on the "system status bar") | 609 // message, since it just means that a menu extra (on the "system status bar") |
810 // was activated; we'll get another |-windowDidResignKey| if we ever really | 610 // was activated; we'll get another |-windowDidResignKey| if we ever really |
811 // lose key window status. | 611 // lose key window status. |
812 if ([NSApp isActive] && ([NSApp keyWindow] == [self window])) | 612 if ([NSApp isActive] && ([NSApp keyWindow] == [self window])) |
813 return; | 613 return; |
814 | 614 |
815 [self onWindowDidResignKey]; | 615 [self onWindowDidResignKey]; |
616 | |
617 // Make the window not user-resizable when it loses the focus. This is to | |
618 // solve the problem that the bottom edge of the active panel does not | |
619 // trigger the user-resizing if this panel stacks with another inactive | |
620 // panel at the bottom. | |
621 [[self window] setStyleMask: | |
622 [[self window] styleMask] & ~NSResizableWindowMask]; | |
623 } | |
624 | |
625 - (void)windowWillStartLiveResize:(NSNotification*)notification { | |
626 // Check if the user-resizing is allowed for the triggering edge/corner. | |
627 // This is an extra safe guard because we are not able to track the mouse | |
628 // movement outside the window and Cocoa could trigger the user-resizing | |
629 // when the mouse moves a bit outside the edge/corner. | |
630 if (![self canResizeByMouseAtCurrentLocation]) | |
631 return; | |
632 userResizing_ = YES; | |
633 windowShim_->panel()->OnPanelStartUserResizing(); | |
634 } | |
635 | |
636 - (void)windowDidEndLiveResize:(NSNotification*)notification { | |
637 if (!userResizing_) | |
638 return; | |
639 userResizing_ = NO; | |
640 | |
641 Panel* panel = windowShim_->panel(); | |
642 panel->OnPanelEndUserResizing(); | |
643 | |
644 gfx::Rect newBounds = | |
645 cocoa_utils::ConvertRectFromCocoaCoordinates([[self window] frame]); | |
646 if (windowShim_->panel()->GetBounds() == newBounds) | |
647 return; | |
648 windowShim_->set_cached_bounds_directly(newBounds); | |
649 | |
650 panel->IncreaseMaxSize(newBounds.size()); | |
651 panel->set_full_size(newBounds.size()); | |
652 | |
653 panel->collection()->RefreshLayout(); | |
654 } | |
655 | |
656 - (NSSize)windowWillResize:(NSWindow*)sender toSize:(NSSize)newSize { | |
657 // As an extra safe guard, we avoid the user resizing if it is deemed not to | |
658 // be allowed (see comment in windowWillStartLiveResize). | |
659 if ([[self window] inLiveResize] && !userResizing_) | |
660 return [[self window] frame].size; | |
661 return newSize; | |
816 } | 662 } |
817 | 663 |
818 - (void)windowDidResize:(NSNotification*)notification { | 664 - (void)windowDidResize:(NSNotification*)notification { |
819 Panel* panel = windowShim_->panel(); | 665 Panel* panel = windowShim_->panel(); |
666 if (userResizing_) { | |
667 panel->collection()->OnPanelResizedByMouse( | |
668 panel, | |
669 cocoa_utils::ConvertRectFromCocoaCoordinates([[self window] frame])); | |
670 } | |
671 | |
672 [self updateTrackingArea]; | |
673 | |
820 if (![self isAnimatingBounds] || | 674 if (![self isAnimatingBounds] || |
821 panel->collection()->type() != PanelCollection::DOCKED) | 675 panel->collection()->type() != PanelCollection::DOCKED) |
Dmitry Titov
2013/09/05 20:49:59
This code seems like from another patch, this need
| |
822 return; | 676 return; |
823 | 677 |
824 // Remove the web contents view from the view hierarchy when the panel is not | 678 // Remove the web contents view from the view hierarchy when the panel is not |
825 // taller than the titlebar. Put it back when the panel grows taller than | 679 // taller than the titlebar. Put it back when the panel grows taller than |
826 // the titlebar. Note that RenderWidgetHostViewMac works for the case that | 680 // the titlebar. Note that RenderWidgetHostViewMac works for the case that |
827 // the web contents view does not exist in the view hierarchy (i.e. the tab | 681 // the web contents view does not exist in the view hierarchy (i.e. the tab |
828 // is not the main one), but it does not work well, like causing occasional | 682 // is not the main one), but it does not work well, like causing occasional |
829 // crashes (http://crbug.com/265932), if the web contents view is made hidden. | 683 // crashes (http://crbug.com/265932), if the web contents view is made hidden. |
830 // | 684 // |
831 // This is needed when the docked panels are being animated. When the | 685 // This is needed when the docked panels are being animated. When the |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
965 - (void)updateWindowCollectionBehavior { | 819 - (void)updateWindowCollectionBehavior { |
966 if (![self isWindowLoaded]) | 820 if (![self isWindowLoaded]) |
967 return; | 821 return; |
968 NSWindowCollectionBehavior collectionBehavior = | 822 NSWindowCollectionBehavior collectionBehavior = |
969 NSWindowCollectionBehaviorParticipatesInCycle; | 823 NSWindowCollectionBehaviorParticipatesInCycle; |
970 if (windowShim_->panel()->IsAlwaysOnTop()) | 824 if (windowShim_->panel()->IsAlwaysOnTop()) |
971 collectionBehavior |= NSWindowCollectionBehaviorCanJoinAllSpaces; | 825 collectionBehavior |= NSWindowCollectionBehaviorCanJoinAllSpaces; |
972 [[self window] setCollectionBehavior:collectionBehavior]; | 826 [[self window] setCollectionBehavior:collectionBehavior]; |
973 } | 827 } |
974 | 828 |
975 - (void)enableResizeByMouse:(BOOL)enable { | 829 - (void)updateTrackingArea { |
976 if (![self isWindowLoaded]) | 830 NSView* superview = [[[self window] contentView] superview]; |
977 return; | 831 |
978 [[self window] invalidateCursorRectsForView:overlayView_]; | 832 if (trackingArea_.get()) |
833 [superview removeTrackingArea:trackingArea_.get()]; | |
834 | |
835 trackingArea_.reset( | |
836 [[CrTrackingArea alloc] initWithRect:[superview bounds] | |
837 options:NSTrackingInVisibleRect | | |
838 NSTrackingMouseMoved | | |
839 NSTrackingActiveInKeyWindow | |
840 owner:superview | |
841 userInfo:nil]); | |
842 [superview addTrackingArea:trackingArea_.get()]; | |
979 } | 843 } |
980 | 844 |
981 - (void)showShadow:(BOOL)show { | 845 - (void)showShadow:(BOOL)show { |
982 if (![self isWindowLoaded]) | 846 if (![self isWindowLoaded]) |
983 return; | 847 return; |
984 [[self window] setHasShadow:show]; | 848 [[self window] setHasShadow:show]; |
985 } | 849 } |
986 | 850 |
987 - (void)miniaturize { | 851 - (void)miniaturize { |
988 [[self window] miniaturize:nil]; | 852 [[self window] miniaturize:nil]; |
989 } | 853 } |
990 | 854 |
991 - (BOOL)isMiniaturized { | 855 - (BOOL)isMiniaturized { |
992 return [[self window] isMiniaturized]; | 856 return [[self window] isMiniaturized]; |
993 } | 857 } |
994 | 858 |
859 - (BOOL)canResizeByMouseAtCurrentLocation { | |
860 panel::Resizability resizability = windowShim_->panel()->CanResizeByMouse(); | |
861 NSRect frame = [[self window] frame]; | |
862 NSPoint point = [NSEvent mouseLocation]; | |
863 | |
864 if (point.y < NSMinY(frame) + kWidthOfMouseResizeArea) { | |
865 if (point.x < NSMinX(frame) + kWidthOfMouseResizeArea && | |
866 (resizability & panel::RESIZABLE_BOTTOM_LEFT) == 0) { | |
867 return NO; | |
868 } | |
869 if (point.x > NSMaxX(frame) - kWidthOfMouseResizeArea && | |
870 (resizability & panel::RESIZABLE_BOTTOM_RIGHT) == 0) { | |
871 return NO; | |
872 } | |
873 if ((resizability & panel::RESIZABLE_BOTTOM) == 0) | |
874 return NO; | |
875 } else if (point.y > NSMaxY(frame) - kWidthOfMouseResizeArea) { | |
876 if (point.x < NSMinX(frame) + kWidthOfMouseResizeArea && | |
877 (resizability & panel::RESIZABLE_TOP_LEFT) == 0) { | |
878 return NO; | |
879 } | |
880 if (point.x > NSMaxX(frame) - kWidthOfMouseResizeArea && | |
881 (resizability & panel::RESIZABLE_TOP_RIGHT) == 0) { | |
882 return NO; | |
883 } | |
884 if ((resizability & panel::RESIZABLE_TOP) == 0) | |
885 return NO; | |
886 } else { | |
887 if (point.x < NSMinX(frame) + kWidthOfMouseResizeArea && | |
888 (resizability & panel::RESIZABLE_LEFT) == 0) { | |
889 return NO; | |
890 } | |
891 if (point.x > NSMaxX(frame) - kWidthOfMouseResizeArea && | |
892 (resizability & panel::RESIZABLE_RIGHT) == 0) { | |
893 return NO; | |
894 } | |
895 } | |
896 return YES; | |
897 } | |
898 | |
995 // We have custom implementation of these because our titlebar height is custom | 899 // We have custom implementation of these because our titlebar height is custom |
996 // and does not match the standard one. | 900 // and does not match the standard one. |
997 - (NSRect)frameRectForContentRect:(NSRect)contentRect { | 901 - (NSRect)frameRectForContentRect:(NSRect)contentRect { |
998 // contentRect is in contentView coord system. We should add a titlebar on top | 902 // contentRect is in contentView coord system. We should add a titlebar on top |
999 // and then convert to the windows coord system. | 903 // and then convert to the windows coord system. |
1000 contentRect.size.height += panel::kTitlebarHeight; | 904 contentRect.size.height += panel::kTitlebarHeight; |
1001 NSRect frameRect = [[[self window] contentView] convertRect:contentRect | 905 NSRect frameRect = [[[self window] contentView] convertRect:contentRect |
1002 toView:nil]; | 906 toView:nil]; |
1003 return frameRect; | 907 return frameRect; |
1004 } | 908 } |
1005 | 909 |
1006 - (NSRect)contentRectForFrameRect:(NSRect)frameRect { | 910 - (NSRect)contentRectForFrameRect:(NSRect)frameRect { |
1007 NSRect contentRect = [[[self window] contentView] convertRect:frameRect | 911 NSRect contentRect = [[[self window] contentView] convertRect:frameRect |
1008 fromView:nil]; | 912 fromView:nil]; |
1009 contentRect.size.height -= panel::kTitlebarHeight; | 913 contentRect.size.height -= panel::kTitlebarHeight; |
1010 if (contentRect.size.height < 0) | 914 if (contentRect.size.height < 0) |
1011 contentRect.size.height = 0; | 915 contentRect.size.height = 0; |
1012 return contentRect; | 916 return contentRect; |
1013 } | 917 } |
1014 | 918 |
1015 @end | 919 @end |
OLD | NEW |