OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #import "chrome/browser/ui/cocoa/panels/panel_titlebar_view_cocoa.h" | |
6 | |
7 #import <Cocoa/Cocoa.h> | |
8 | |
9 #include "base/logging.h" | |
10 #include "base/mac/scoped_nsautorelease_pool.h" | |
11 #import "chrome/browser/ui/cocoa/panels/panel_window_controller_cocoa.h" | |
12 #import "chrome/browser/ui/panels/panel_constants.h" | |
13 #include "chrome/grit/generated_resources.h" | |
14 #include "grit/theme_resources.h" | |
15 #include "ui/base/cocoa/cocoa_base_utils.h" | |
16 #import "ui/base/cocoa/hover_image_button.h" | |
17 #import "ui/base/cocoa/nsview_additions.h" | |
18 #include "ui/base/l10n/l10n_util_mac.h" | |
19 #include "ui/base/resource/resource_bundle.h" | |
20 #include "ui/gfx/image/image.h" | |
21 #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h" | |
22 | |
23 // 'Glint' is a glowing light animation on the titlebar to attract user's | |
24 // attention. Numbers are arbitrary, based on several tries. | |
25 const double kGlintAnimationDuration = 1.5; | |
26 const double kGlintRepeatIntervalSeconds = 1.0; | |
27 const int kNumberOfGlintRepeats = 4; // 5 total, including initial flash. | |
28 | |
29 // Used to implement TestingAPI | |
30 static NSEvent* MakeMouseEvent(NSEventType type, | |
31 NSPoint point, | |
32 int modifierFlags, | |
33 int clickCount) { | |
34 return [NSEvent mouseEventWithType:type | |
35 location:point | |
36 modifierFlags:modifierFlags | |
37 timestamp:0 | |
38 windowNumber:0 | |
39 context:nil | |
40 eventNumber:0 | |
41 clickCount:clickCount | |
42 pressure:0.0]; | |
43 } | |
44 | |
45 // Test drag controller - does not contain a nested message loop, directly | |
46 // invokes the dragStarted/dragProgress instead. | |
47 @interface TestDragController : MouseDragController { | |
48 @private | |
49 BOOL dragStarted_; | |
50 } | |
51 - (void)mouseDragged:(NSEvent*)event; | |
52 @end | |
53 | |
54 @implementation TestDragController | |
55 // Bypass nested message loop for tests. There is no need to check for | |
56 // threshold here as the base class does because tests only simulate a single | |
57 // 'mouse drag' to the destination point. | |
58 - (void)mouseDragged:(NSEvent*)event { | |
59 if (!dragStarted_) { | |
60 [[self client] dragStarted:[self initialMouseLocation]]; | |
61 dragStarted_ = YES; | |
62 } | |
63 | |
64 [[self client] dragProgress:[event locationInWindow]]; | |
65 } | |
66 @end | |
67 | |
68 @implementation PanelTitlebarOverlayView | |
69 // Sometimes we do not want to bring chrome window to foreground when we click | |
70 // on any part of the titlebar. To do this, we first postpone the window | |
71 // reorder here (shouldDelayWindowOrderingForEvent is called during when mouse | |
72 // button is pressed but before mouseDown: is dispatched) and then complete | |
73 // canceling the reorder by [NSApp preventWindowOrdering] in mouseDown handler | |
74 // of this view. | |
75 - (BOOL)shouldDelayWindowOrderingForEvent:(NSEvent*)theEvent { | |
76 disableReordering_ = ![controller_ canBecomeKeyWindow]; | |
77 return disableReordering_; | |
78 } | |
79 | |
80 - (void)mouseDown:(NSEvent*)event { | |
81 if (disableReordering_) | |
82 [NSApp preventWindowOrdering]; | |
83 disableReordering_ = NO; | |
84 // Continue bubbling the event up the chain of responders. | |
85 [super mouseDown:event]; | |
86 } | |
87 | |
88 - (BOOL)acceptsFirstMouse:(NSEvent*)event { | |
89 return YES; | |
90 } | |
91 @end | |
92 | |
93 @implementation RepaintAnimation | |
94 - (id)initWithView:(NSView*)targetView duration:(double) duration { | |
95 if ((self = [super initWithDuration:duration | |
96 animationCurve:NSAnimationEaseInOut])) { | |
97 [self setAnimationBlockingMode:NSAnimationNonblocking]; | |
98 targetView_ = targetView; | |
99 } | |
100 return self; | |
101 } | |
102 | |
103 - (void)setCurrentProgress:(NSAnimationProgress)progress { | |
104 [super setCurrentProgress:progress]; | |
105 [targetView_ setNeedsDisplay:YES]; | |
106 } | |
107 @end | |
108 | |
109 | |
110 @implementation PanelTitlebarViewCocoa | |
111 | |
112 - (id)initWithFrame:(NSRect)frame { | |
113 if ((self = [super initWithFrame:frame])) | |
114 dragController_.reset([[MouseDragController alloc] initWithClient:self]); | |
115 return self; | |
116 } | |
117 | |
118 - (void)dealloc { | |
119 [[NSNotificationCenter defaultCenter] removeObserver:self]; | |
120 [self stopGlintAnimation]; | |
121 [super dealloc]; | |
122 } | |
123 | |
124 - (void)onCloseButtonClick:(id)sender { | |
125 [controller_ closePanel]; | |
126 } | |
127 | |
128 - (void)onMinimizeButtonClick:(id)sender { | |
129 [controller_ minimizeButtonClicked:[[NSApp currentEvent] modifierFlags]]; | |
130 } | |
131 | |
132 - (void)onRestoreButtonClick:(id)sender { | |
133 [controller_ restoreButtonClicked:[[NSApp currentEvent] modifierFlags]]; | |
134 } | |
135 | |
136 - (void)drawRect:(NSRect)rect { | |
137 if (isDrawingAttention_) { | |
138 NSColor* attentionColor = [NSColor colorWithCalibratedRed:0x53/255.0 | |
139 green:0xa9/255.0 | |
140 blue:0x3f/255.0 | |
141 alpha:1.0]; | |
142 [attentionColor set]; | |
143 NSRectFillUsingOperation([self bounds], NSCompositeSourceOver); | |
144 | |
145 if ([glintAnimation_ isAnimating]) { | |
146 base::scoped_nsobject<NSGradient> glint([NSGradient alloc]); | |
147 float currentAlpha = 0.8 * [glintAnimation_ currentValue]; | |
148 NSColor* startColor = [NSColor colorWithCalibratedWhite:1.0 | |
149 alpha:currentAlpha]; | |
150 NSColor* endColor = [NSColor colorWithCalibratedWhite:1.0 | |
151 alpha:0.0]; | |
152 [glint initWithColorsAndLocations: | |
153 startColor, 0.0, startColor, 0.3, endColor, 1.0, nil]; | |
154 NSRect bounds = [self bounds]; | |
155 [glint drawInRect:bounds relativeCenterPosition:NSZeroPoint]; | |
156 } | |
157 } else { | |
158 BOOL isActive = [[self window] isMainWindow]; | |
159 | |
160 // If titlebar is close to minimized state or is at minimized state and only | |
161 // shows a few pixels, change the color to something light and add border. | |
162 NSRect windowFrame = [[self window] frame]; | |
163 if (NSHeight(windowFrame) < 8) { | |
164 NSColor* lightBackgroundColor = | |
165 [NSColor colorWithCalibratedRed:0xf5/255.0 | |
166 green:0xf4/255.0 | |
167 blue:0xf0/255.0 | |
168 alpha:1.0]; | |
169 [lightBackgroundColor set]; | |
170 NSRectFill([self bounds]); | |
171 | |
172 NSColor* borderColor = | |
173 [NSColor colorWithCalibratedRed:0xc9/255.0 | |
174 green:0xc9/255.0 | |
175 blue:0xc9/255.0 | |
176 alpha:1.0]; | |
177 [borderColor set]; | |
178 NSFrameRect([self bounds]); | |
179 } else { | |
180 // use solid black-ish colors. | |
181 NSColor* backgroundColor = isActive ? | |
182 [NSColor colorWithCalibratedRed:0x3a/255.0 | |
183 green:0x3d/255.0 | |
184 blue:0x3d/255.0 | |
185 alpha:1.0] : | |
186 [NSColor colorWithCalibratedRed:0x7a/255.0 | |
187 green:0x7c/255.0 | |
188 blue:0x7c/255.0 | |
189 alpha:1.0]; | |
190 | |
191 [backgroundColor set]; | |
192 NSRectFill([self bounds]); | |
193 } | |
194 } | |
195 | |
196 NSColor* titleColor = [NSColor colorWithCalibratedRed:0xf9/255.0 | |
197 green:0xf9/255.0 | |
198 blue:0xf9/255.0 | |
199 alpha:1.0]; | |
200 [title_ setTextColor:titleColor]; | |
201 } | |
202 | |
203 - (void)attach { | |
204 // Interface Builder can not put a view as a sibling of contentView, | |
205 // so need to do it here. Placing ourself as the last child of the | |
206 // internal view allows us to draw on top of the titlebar. | |
207 // Note we must use [controller_ window] here since we have not been added | |
208 // to the view hierarchy yet. | |
209 NSView* contentView = [[controller_ window] contentView]; | |
210 NSView* rootView = [contentView superview]; | |
211 [rootView addSubview:self]; | |
212 | |
213 // Figure out the rectangle of the titlebar and set us on top of it. | |
214 // The titlebar covers window's root view where not covered by contentView. | |
215 // Compute the titlebar frame in coordinate system of the window's root view. | |
216 // NSWindow | |
217 // | | |
218 // ___root_view____ | |
219 // | | | |
220 // contentView titlebar | |
221 NSSize titlebarSize = NSMakeSize(0, panel::kTitlebarHeight); | |
222 titlebarSize = [contentView convertSize:titlebarSize toView:rootView]; | |
223 NSRect rootViewBounds = [[self superview] bounds]; | |
224 NSRect titlebarFrame = | |
225 NSMakeRect(NSMinX(rootViewBounds), | |
226 NSMaxY(rootViewBounds) - titlebarSize.height, | |
227 NSWidth(rootViewBounds), | |
228 titlebarSize.height); | |
229 [self setFrame:titlebarFrame]; | |
230 | |
231 [title_ setFont:[[NSFontManager sharedFontManager] | |
232 fontWithFamily:@"Arial" | |
233 traits:NSBoldFontMask | |
234 weight:0 | |
235 size:14.0]]; | |
236 [title_ setDrawsBackground:NO]; | |
237 | |
238 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | |
239 | |
240 [self initializeImageButton:customCloseButton_ | |
241 image:rb.GetNativeImageNamed(IDR_PANEL_CLOSE).ToNSImage() | |
242 hoverImage:rb.GetNativeImageNamed(IDR_PANEL_CLOSE_H).ToNSImage() | |
243 pressedImage:rb.GetNativeImageNamed(IDR_PANEL_CLOSE_C).ToNSImage() | |
244 toolTip:l10n_util::GetNSStringWithFixup(IDS_PANEL_CLOSE_TOOLTIP)]; | |
245 | |
246 // Iniitalize the minimize and restore buttons. | |
247 [self initializeImageButton:minimizeButton_ | |
248 image:rb.GetNativeImageNamed(IDR_PANEL_MINIMIZE).ToNSImage() | |
249 hoverImage:rb.GetNativeImageNamed(IDR_PANEL_MINIMIZE_H).ToNSImage() | |
250 pressedImage:rb.GetNativeImageNamed(IDR_PANEL_MINIMIZE_C).ToNSImage() | |
251 toolTip:l10n_util::GetNSStringWithFixup(IDS_PANEL_MINIMIZE_TOOLTIP)]; | |
252 | |
253 [self initializeImageButton:restoreButton_ | |
254 image:rb.GetNativeImageNamed(IDR_PANEL_RESTORE).ToNSImage() | |
255 hoverImage:rb.GetNativeImageNamed(IDR_PANEL_RESTORE_H).ToNSImage() | |
256 pressedImage:rb.GetNativeImageNamed(IDR_PANEL_RESTORE_C).ToNSImage() | |
257 toolTip:l10n_util::GetNSStringWithFixup(IDS_PANEL_RESTORE_TOOLTIP)]; | |
258 | |
259 [controller_ updateTitleBarMinimizeRestoreButtonVisibility]; | |
260 | |
261 [self updateCustomButtonsLayout]; | |
262 | |
263 // Set autoresizing behavior: glued to edges on left, top and right. | |
264 [self setAutoresizingMask:(NSViewMinYMargin | NSViewWidthSizable)]; | |
265 | |
266 [[NSNotificationCenter defaultCenter] | |
267 addObserver:self | |
268 selector:@selector(didChangeFrame:) | |
269 name:NSViewFrameDidChangeNotification | |
270 object:self]; | |
271 [[NSNotificationCenter defaultCenter] | |
272 addObserver:self | |
273 selector:@selector(didChangeMainWindow:) | |
274 name:NSWindowDidBecomeMainNotification | |
275 object:[self window]]; | |
276 [[NSNotificationCenter defaultCenter] | |
277 addObserver:self | |
278 selector:@selector(didChangeMainWindow:) | |
279 name:NSWindowDidResignMainNotification | |
280 object:[self window]]; | |
281 } | |
282 | |
283 - (void)initializeImageButton:(HoverImageButton*)button | |
284 image:(NSImage*)image | |
285 hoverImage:(NSImage*)hoverImage | |
286 pressedImage:(NSImage*)pressedImage | |
287 toolTip:(NSString*)toolTip { | |
288 [button setDefaultImage:image]; | |
289 [button setHoverImage:hoverImage]; | |
290 [button setPressedImage:pressedImage]; | |
291 [button setToolTip:toolTip]; | |
292 [[button cell] setHighlightsBy:NSNoCellMask]; | |
293 } | |
294 | |
295 - (void)setTitle:(NSString*)newTitle { | |
296 [title_ setStringValue:newTitle]; | |
297 [self updateIconAndTitleLayout]; | |
298 } | |
299 | |
300 - (void)setIcon:(NSView*)newIcon { | |
301 [icon_ removeFromSuperview]; | |
302 icon_ = newIcon; | |
303 if (icon_) { | |
304 [self addSubview:icon_ positioned:NSWindowBelow relativeTo:overlay_]; | |
305 [icon_ setWantsLayer:YES]; | |
306 } | |
307 [self updateIconAndTitleLayout]; | |
308 } | |
309 | |
310 - (NSView*)icon { | |
311 return icon_; | |
312 } | |
313 | |
314 - (void)setMinimizeButtonVisibility:(BOOL)visible { | |
315 [minimizeButton_ setHidden:!visible]; | |
316 } | |
317 | |
318 - (void)setRestoreButtonVisibility:(BOOL)visible { | |
319 [restoreButton_ setHidden:!visible]; | |
320 } | |
321 | |
322 - (void)updateCustomButtonsLayout { | |
323 NSRect bounds = [self bounds]; | |
324 NSRect closeButtonFrame = [customCloseButton_ frame]; | |
325 closeButtonFrame.size.width = panel::kPanelButtonSize; | |
326 closeButtonFrame.size.height = panel::kPanelButtonSize; | |
327 closeButtonFrame.origin.x = | |
328 NSWidth(bounds) - NSWidth(closeButtonFrame) - panel::kButtonPadding; | |
329 closeButtonFrame.origin.y = | |
330 (NSHeight(bounds) - NSHeight(closeButtonFrame)) / 2; | |
331 [customCloseButton_ setFrame:closeButtonFrame]; | |
332 | |
333 NSRect buttonFrame = [minimizeButton_ frame]; | |
334 buttonFrame.size.width = panel::kPanelButtonSize; | |
335 buttonFrame.size.height = panel::kPanelButtonSize; | |
336 buttonFrame.origin.x = | |
337 closeButtonFrame.origin.x - NSWidth(buttonFrame) - panel::kButtonPadding; | |
338 buttonFrame.origin.y = (NSHeight(bounds) - NSHeight(buttonFrame)) / 2; | |
339 [minimizeButton_ setFrame:buttonFrame]; | |
340 [restoreButton_ setFrame:buttonFrame]; | |
341 } | |
342 | |
343 - (void)updateIconAndTitleLayout { | |
344 NSRect iconFrame = [icon_ frame]; | |
345 // NSTextField for title_ is set to Layout:Truncate, LineBreaks:TruncateTail | |
346 // in Interface Builder so it is sized in a single-line mode. | |
347 [title_ sizeToFit]; | |
348 NSRect titleFrame = [title_ frame]; | |
349 // Only one of minimize/restore button is visible at a time so just allow for | |
350 // the width of one of them. | |
351 NSRect minimizeRestoreButtonFrame = [minimizeButton_ frame]; | |
352 NSRect bounds = [self bounds]; | |
353 | |
354 // Place the icon and title at the left edge of the titlebar. | |
355 int iconWidth = NSWidth(iconFrame); | |
356 int titleWidth = NSWidth(titleFrame); | |
357 int availableWidth = minimizeRestoreButtonFrame.origin.x - | |
358 panel::kTitleAndButtonPadding; | |
359 | |
360 int paddings = panel::kTitlebarLeftPadding + panel::kIconAndTitlePadding; | |
361 if (paddings + iconWidth + titleWidth > availableWidth) | |
362 titleWidth = availableWidth - iconWidth - paddings; | |
363 if (titleWidth < 0) | |
364 titleWidth = 0; | |
365 | |
366 iconFrame.origin.x = panel::kTitlebarLeftPadding; | |
367 iconFrame.origin.y = (NSHeight(bounds) - NSHeight(iconFrame)) / 2; | |
368 [icon_ setFrame:iconFrame]; | |
369 | |
370 titleFrame.origin.x = paddings + iconWidth; | |
371 // In bottom-heavy text labels, let's compensate for occasional integer | |
372 // rounding to avoid text label to feel too low. | |
373 titleFrame.origin.y = (NSHeight(bounds) - NSHeight(titleFrame)) / 2 + 2; | |
374 titleFrame.size.width = titleWidth; | |
375 [title_ setFrame:titleFrame]; | |
376 } | |
377 | |
378 // PanelManager controls size/position of the window. | |
379 - (BOOL)mouseDownCanMoveWindow { | |
380 return NO; | |
381 } | |
382 | |
383 - (BOOL)acceptsFirstMouse:(NSEvent*)event { | |
384 return YES; | |
385 } | |
386 | |
387 - (void)didChangeFrame:(NSNotification*)notification { | |
388 // Update buttons first because title layout depends on buttons layout. | |
389 [self updateCustomButtonsLayout]; | |
390 [self updateIconAndTitleLayout]; | |
391 } | |
392 | |
393 - (void)didChangeMainWindow:(NSNotification*)notification { | |
394 [self setNeedsDisplay:YES]; | |
395 } | |
396 | |
397 - (void)mouseDown:(NSEvent*)event { | |
398 [dragController_ mouseDown:event]; | |
399 } | |
400 | |
401 - (void)mouseUp:(NSEvent*)event { | |
402 [dragController_ mouseUp:event]; | |
403 | |
404 if ([event clickCount] == 1) | |
405 [controller_ onTitlebarMouseClicked:[event modifierFlags]]; | |
406 else if ([event clickCount] == 2) | |
407 [controller_ onTitlebarDoubleClicked:[event modifierFlags]]; | |
408 } | |
409 | |
410 - (void)mouseDragged:(NSEvent*)event { | |
411 [dragController_ mouseDragged:event]; | |
412 } | |
413 | |
414 // MouseDragControllerClient implementaiton | |
415 | |
416 - (void)prepareForDrag { | |
417 } | |
418 | |
419 - (void)dragStarted:(NSPoint)initialMouseLocation { | |
420 NSPoint initialMouseLocationScreen = ui::ConvertPointFromWindowToScreen( | |
421 [self window], initialMouseLocation); | |
422 [controller_ startDrag:initialMouseLocationScreen]; | |
423 } | |
424 | |
425 - (void)dragEnded:(BOOL)cancelled { | |
426 [controller_ endDrag:cancelled]; | |
427 } | |
428 | |
429 - (void)dragProgress:(NSPoint)mouseLocation { | |
430 NSPoint mouseLocationScreen = ui::ConvertPointFromWindowToScreen( | |
431 [self window], mouseLocation); | |
432 [controller_ drag:mouseLocationScreen]; | |
433 } | |
434 | |
435 - (void)cleanupAfterDrag { | |
436 } | |
437 | |
438 // End of MouseDragControllerClient implementaiton | |
439 | |
440 - (void)drawAttention { | |
441 if (isDrawingAttention_) | |
442 return; | |
443 isDrawingAttention_ = YES; | |
444 | |
445 [self startGlintAnimation]; | |
446 } | |
447 | |
448 - (void)stopDrawingAttention { | |
449 if (!isDrawingAttention_) | |
450 return; | |
451 isDrawingAttention_ = NO; | |
452 | |
453 [self stopGlintAnimation]; | |
454 [self setNeedsDisplay:YES]; | |
455 } | |
456 | |
457 - (BOOL)isDrawingAttention { | |
458 return isDrawingAttention_; | |
459 } | |
460 | |
461 - (void)startGlintAnimation { | |
462 glintCounter_ = 0; | |
463 [self restartGlintAnimation:nil]; | |
464 } | |
465 | |
466 - (void)stopGlintAnimation { | |
467 if (glintAnimationTimer_.get()) { | |
468 [glintAnimationTimer_ invalidate]; | |
469 glintAnimationTimer_.reset(); | |
470 } | |
471 if ([glintAnimation_ isAnimating]) | |
472 [glintAnimation_ stopAnimation]; | |
473 } | |
474 | |
475 - (void)restartGlintAnimation:(NSTimer*)timer { | |
476 if (!glintAnimation_.get()) { | |
477 glintAnimation_.reset( | |
478 [[RepaintAnimation alloc] initWithView:self | |
479 duration:kGlintAnimationDuration]); | |
480 [glintAnimation_ setDelegate:self]; | |
481 } | |
482 [glintAnimation_ startAnimation]; | |
483 } | |
484 | |
485 // NSAnimationDelegate method. | |
486 - (void)animationDidEnd:(NSAnimation*)animation { | |
487 if (animation != glintAnimation_.get()) | |
488 return; | |
489 if (glintCounter_ >= kNumberOfGlintRepeats) | |
490 return; | |
491 glintCounter_++; | |
492 // Restart after a timeout. | |
493 glintAnimationTimer_.reset([[NSTimer | |
494 scheduledTimerWithTimeInterval:kGlintRepeatIntervalSeconds | |
495 target:self | |
496 selector:@selector(restartGlintAnimation:) | |
497 userInfo:nil | |
498 repeats:NO] retain]); | |
499 } | |
500 | |
501 // NSAnimationDelegate method. | |
502 - (float)animation:(NSAnimation *)animation | |
503 valueForProgress:(NSAnimationProgress)progress { | |
504 if (animation != glintAnimation_.get()) | |
505 return progress; | |
506 | |
507 // Converts 0..1 progression into a sharper raise/fall. | |
508 float result = progress < 0.5 ? progress : 1.0 - progress; | |
509 result = 4.0 * result * result; | |
510 return result; | |
511 } | |
512 | |
513 // (Private/TestingAPI) | |
514 - (PanelWindowControllerCocoa*)controller { | |
515 return controller_; | |
516 } | |
517 | |
518 - (NSTextField*)title { | |
519 return title_; | |
520 } | |
521 | |
522 - (void)simulateCloseButtonClick { | |
523 [[customCloseButton_ cell] performClick:customCloseButton_]; | |
524 } | |
525 | |
526 - (void)pressLeftMouseButtonTitlebar:(NSPoint)mouseLocation | |
527 modifiers:(int)modifierFlags { | |
528 // Override the drag controller. It's ok to create a new one for each drag. | |
529 dragController_.reset([[TestDragController alloc] initWithClient:self]); | |
530 // Convert from Cocoa's screen coordinates to base coordinates since the mouse | |
531 // event takes base (NSWindow) coordinates. | |
532 NSPoint mouseLocationWindow = ui::ConvertPointFromScreenToWindow( | |
533 [self window], mouseLocation); | |
534 NSEvent* event = MakeMouseEvent(NSLeftMouseDown, mouseLocationWindow, | |
535 modifierFlags, 0); | |
536 [self mouseDown:event]; | |
537 } | |
538 | |
539 - (void)releaseLeftMouseButtonTitlebar:(int)modifierFlags { | |
540 NSEvent* event = MakeMouseEvent(NSLeftMouseUp, NSZeroPoint, modifierFlags, 1); | |
541 [self mouseUp:event]; | |
542 } | |
543 | |
544 - (void)dragTitlebar:(NSPoint)mouseLocation { | |
545 // Convert from Cocoa's screen coordinates to base coordinates since the mouse | |
546 // event takes base (NSWindow) coordinates. | |
547 NSPoint mouseLocationWindow = ui::ConvertPointFromScreenToWindow( | |
548 [self window], mouseLocation); | |
549 NSEvent* event = | |
550 MakeMouseEvent(NSLeftMouseDragged, mouseLocationWindow, 0, 0); | |
551 [self mouseDragged:event]; | |
552 } | |
553 | |
554 - (void)cancelDragTitlebar { | |
555 [self dragEnded:YES]; | |
556 } | |
557 | |
558 - (void)finishDragTitlebar { | |
559 [self dragEnded:NO]; | |
560 } | |
561 | |
562 - (NSButton*)closeButton { | |
563 return closeButton_; | |
564 } | |
565 | |
566 - (NSButton*)minimizeButton { | |
567 return minimizeButton_; | |
568 } | |
569 | |
570 - (NSButton*)restoreButton { | |
571 return restoreButton_; | |
572 } | |
573 | |
574 @end | |
575 | |
OLD | NEW |