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

Side by Side Diff: chrome/browser/ui/cocoa/panels/panel_window_controller_cocoa.mm

Issue 23918002: Switch to doing user-resizing via system for panels on Mac (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Patch to reland Created 7 years, 3 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 | Annotate | Revision Log
OLDNEW
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
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
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
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
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)
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.
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
OLDNEW
« no previous file with comments | « chrome/browser/ui/cocoa/panels/panel_window_controller_cocoa.h ('k') | chrome/browser/ui/gtk/panels/panel_gtk.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698