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

Side by Side Diff: chrome/browser/renderer_host/render_widget_host_view_mac.mm

Issue 4078003: Refactoring select popup on Mac.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 10 years, 1 month 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) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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 <QuartzCore/QuartzCore.h> 5 #include <QuartzCore/QuartzCore.h>
6 6
7 #include "chrome/browser/renderer_host/render_widget_host_view_mac.h" 7 #include "chrome/browser/renderer_host/render_widget_host_view_mac.h"
8 8
9 #include "app/app_switches.h" 9 #include "app/app_switches.h"
10 #include "app/surface/io_surface_support_mac.h" 10 #include "app/surface/io_surface_support_mac.h"
(...skipping 23 matching lines...) Expand all
34 #include "chrome/common/native_web_keyboard_event.h" 34 #include "chrome/common/native_web_keyboard_event.h"
35 #include "chrome/common/edit_command.h" 35 #include "chrome/common/edit_command.h"
36 #include "chrome/common/plugin_messages.h" 36 #include "chrome/common/plugin_messages.h"
37 #include "chrome/common/render_messages.h" 37 #include "chrome/common/render_messages.h"
38 #include "skia/ext/platform_canvas.h" 38 #include "skia/ext/platform_canvas.h"
39 #include "third_party/skia/include/core/SkColor.h" 39 #include "third_party/skia/include/core/SkColor.h"
40 #include "third_party/WebKit/WebKit/chromium/public/mac/WebInputEventFactory.h" 40 #include "third_party/WebKit/WebKit/chromium/public/mac/WebInputEventFactory.h"
41 #include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h" 41 #include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h"
42 #include "webkit/glue/plugins/webplugin.h" 42 #include "webkit/glue/plugins/webplugin.h"
43 #include "webkit/glue/webaccessibility.h" 43 #include "webkit/glue/webaccessibility.h"
44 #include "webkit/glue/webmenurunner_mac.h"
45 #import "third_party/mozilla/ComplexTextInputPanel.h" 44 #import "third_party/mozilla/ComplexTextInputPanel.h"
46 45
47 using WebKit::WebInputEvent; 46 using WebKit::WebInputEvent;
48 using WebKit::WebInputEventFactory; 47 using WebKit::WebInputEventFactory;
49 using WebKit::WebMouseEvent; 48 using WebKit::WebMouseEvent;
50 using WebKit::WebMouseWheelEvent; 49 using WebKit::WebMouseWheelEvent;
51 50
52 static inline int ToWebKitModifiers(NSUInteger flags) { 51 static inline int ToWebKitModifiers(NSUInteger flags) {
53 int modifiers = 0; 52 int modifiers = 0;
54 if (flags & NSControlKeyMask) modifiers |= WebInputEvent::ControlKey; 53 if (flags & NSControlKeyMask) modifiers |= WebInputEvent::ControlKey;
(...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after
431 /////////////////////////////////////////////////////////////////////////////// 430 ///////////////////////////////////////////////////////////////////////////////
432 // RenderWidgetHostViewMac, public: 431 // RenderWidgetHostViewMac, public:
433 432
434 RenderWidgetHostViewMac::RenderWidgetHostViewMac(RenderWidgetHost* widget) 433 RenderWidgetHostViewMac::RenderWidgetHostViewMac(RenderWidgetHost* widget)
435 : render_widget_host_(widget), 434 : render_widget_host_(widget),
436 about_to_validate_and_paint_(false), 435 about_to_validate_and_paint_(false),
437 call_set_needs_display_in_rect_pending_(false), 436 call_set_needs_display_in_rect_pending_(false),
438 text_input_type_(WebKit::WebTextInputTypeNone), 437 text_input_type_(WebKit::WebTextInputTypeNone),
439 is_loading_(false), 438 is_loading_(false),
440 is_hidden_(false), 439 is_hidden_(false),
441 is_popup_menu_(false), 440 shutdown_factory_(this) {
442 shutdown_factory_(this),
443 parent_view_(NULL) {
444 // |cocoa_view_| owns us and we will be deleted when |cocoa_view_| goes away. 441 // |cocoa_view_| owns us and we will be deleted when |cocoa_view_| goes away.
445 // Since we autorelease it, our caller must put |native_view()| into the view 442 // Since we autorelease it, our caller must put |native_view()| into the view
446 // hierarchy right after calling us. 443 // hierarchy right after calling us.
447 cocoa_view_ = [[[RenderWidgetHostViewCocoa alloc] 444 cocoa_view_ = [[[RenderWidgetHostViewCocoa alloc]
448 initWithRenderWidgetHostViewMac:this] autorelease]; 445 initWithRenderWidgetHostViewMac:this] autorelease];
449 render_widget_host_->set_view(this); 446 render_widget_host_->set_view(this);
450 447
451 // Turn on accessibility only if VoiceOver is running. 448 // Turn on accessibility only if VoiceOver is running.
452 if (IsVoiceOverRunning()) { 449 if (IsVoiceOverRunning()) {
453 Singleton<BrowserAccessibilityState>()->OnScreenReaderDetected(); 450 Singleton<BrowserAccessibilityState>()->OnScreenReaderDetected();
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after
725 722
726 void RenderWidgetHostViewMac::Destroy() { 723 void RenderWidgetHostViewMac::Destroy() {
727 // On Windows, popups are implemented with a popup window style, so that when 724 // On Windows, popups are implemented with a popup window style, so that when
728 // an event comes in that would "cancel" it, it receives the OnCancelMode 725 // an event comes in that would "cancel" it, it receives the OnCancelMode
729 // message and can kill itself. Alas, on the Mac, views cannot capture events 726 // message and can kill itself. Alas, on the Mac, views cannot capture events
730 // outside of themselves. On Windows, if Destroy is being called on a view, 727 // outside of themselves. On Windows, if Destroy is being called on a view,
731 // then the event causing the destroy had also cancelled any popups by the 728 // then the event causing the destroy had also cancelled any popups by the
732 // time Destroy() was called. On the Mac we have to destroy all the popups 729 // time Destroy() was called. On the Mac we have to destroy all the popups
733 // ourselves. 730 // ourselves.
734 731
735 if (!is_popup_menu_) { 732 // Depth-first destroy all popups. Use ShutdownHost() to enforce
736 // Depth-first destroy all popups. Use ShutdownHost() to enforce 733 // deepest-first ordering.
737 // deepest-first ordering. 734 for (NSView* subview in [cocoa_view_ subviews]) {
738 for (NSView* subview in [cocoa_view_ subviews]) { 735 if ([subview isKindOfClass:[RenderWidgetHostViewCocoa class]]) {
739 if ([subview isKindOfClass:[RenderWidgetHostViewCocoa class]]) { 736 [static_cast<RenderWidgetHostViewCocoa*>(subview)
740 [static_cast<RenderWidgetHostViewCocoa*>(subview) 737 renderWidgetHostViewMac]->ShutdownHost();
741 renderWidgetHostViewMac]->ShutdownHost(); 738 } else if ([subview isKindOfClass:[AcceleratedPluginView class]]) {
742 } else if ([subview isKindOfClass:[AcceleratedPluginView class]]) { 739 [static_cast<AcceleratedPluginView*>(subview)
743 [static_cast<AcceleratedPluginView*>(subview) 740 onRenderWidgetHostViewGone];
744 onRenderWidgetHostViewGone];
745 }
746 } 741 }
742 }
747 743
748 // We've been told to destroy. 744 // We've been told to destroy.
749 [cocoa_view_ retain]; 745 [cocoa_view_ retain];
750 [cocoa_view_ removeFromSuperview]; 746 [cocoa_view_ removeFromSuperview];
751 [cocoa_view_ autorelease]; 747 [cocoa_view_ autorelease];
752 } else {
753 // From the renderer's perspective, the pop-up menu is represented by a
754 // RenderWidget. The actual Mac implementation uses a native pop-up menu
755 // and doesn't actually make use of the RenderWidgetHostViewCocoa that
756 // was allocated to own it in its constructor. When the pop-up menu goes
757 // away, free the RenderWidgetHostViewCocoa. Its deallocation will result
758 // in this object's destruction.
759
760 DCHECK([[cocoa_view_ subviews] count] == 0);
761 DCHECK([cocoa_view_ superview] == nil);
762
763 [cocoa_view_ autorelease];
764 }
765 748
766 // We get this call just before |render_widget_host_| deletes 749 // We get this call just before |render_widget_host_| deletes
767 // itself. But we are owned by |cocoa_view_|, which may be retained 750 // itself. But we are owned by |cocoa_view_|, which may be retained
768 // by some other code. Examples are TabContentsViewMac's 751 // by some other code. Examples are TabContentsViewMac's
769 // |latent_focus_view_| and TabWindowController's 752 // |latent_focus_view_| and TabWindowController's
770 // |cachedContentView_|. 753 // |cachedContentView_|.
771 render_widget_host_ = NULL; 754 render_widget_host_ = NULL;
772 } 755 }
773 756
774 // Called from the renderer to tell us what the tooltip text should be. It 757 // Called from the renderer to tell us what the tooltip text should be. It
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
808 const gfx::Size& size) { 791 const gfx::Size& size) {
809 NOTIMPLEMENTED(); 792 NOTIMPLEMENTED();
810 return NULL; 793 return NULL;
811 } 794 }
812 795
813 // Sets whether or not to accept first responder status. 796 // Sets whether or not to accept first responder status.
814 void RenderWidgetHostViewMac::SetTakesFocusOnlyOnMouseDown(bool flag) { 797 void RenderWidgetHostViewMac::SetTakesFocusOnlyOnMouseDown(bool flag) {
815 [cocoa_view_ setTakesFocusOnlyOnMouseDown:flag]; 798 [cocoa_view_ setTakesFocusOnlyOnMouseDown:flag];
816 } 799 }
817 800
818 // Display a popup menu for WebKit using Cocoa widgets.
819 void RenderWidgetHostViewMac::ShowPopupWithItems(
820 gfx::Rect bounds,
821 int item_height,
822 double item_font_size,
823 int selected_item,
824 const std::vector<WebMenuItem>& items,
825 bool right_aligned) {
826 is_popup_menu_ = true;
827
828 // Retain the Cocoa view for the duration of the pop-up so that it can't
829 // be dealloced if my Destroy() method is called while the pop-up's up
830 // (which would in turn delete me, causing a crash once the -runMenuInView
831 // call returns. That's what was happening in <http://crbug.com/33250>).
832 scoped_nsobject<RenderWidgetHostViewCocoa> retainedCocoaView
833 ([cocoa_view_ retain]);
834
835 NSRect view_rect = [cocoa_view_ bounds];
836 NSRect parent_rect = [parent_view_ bounds];
837 int y_offset = bounds.y() + bounds.height();
838 NSRect position = NSMakeRect(bounds.x(), parent_rect.size.height - y_offset,
839 bounds.width(), bounds.height());
840
841 // Display the menu.
842 scoped_nsobject<WebMenuRunner> menu_runner;
843 menu_runner.reset([[WebMenuRunner alloc] initWithItems:items
844 fontSize:item_font_size
845 rightAligned:right_aligned]);
846
847 {
848 // Make sure events can be pumped while the menu is up.
849 MessageLoop::ScopedNestableTaskAllower allow(MessageLoop::current());
850
851 // One of the events that could be pumped is |window.close()|.
852 // User-initiated event-tracking loops protect against this by
853 // setting flags in -[CrApplication sendEvent:], but since
854 // web-content menus are initiated by IPC message the setup has to
855 // be done manually.
856 chrome_application_mac::ScopedSendingEvent sendingEventScoper;
857
858 // Now run a SYNCHRONOUS NESTED EVENT LOOP until the pop-up is finished.
859 [menu_runner runMenuInView:parent_view_
860 withBounds:position
861 initialIndex:selected_item];
862 }
863
864 if (!render_widget_host_) {
865 // Bad news -- my Destroy() was called while I was off running the menu.
866 // Return ASAP, and the release of retainedCocoaView will dealloc my NSView,
867 // which will delete me (whew).
868 return;
869 }
870
871 int window_num = [[parent_view_ window] windowNumber];
872 NSEvent* event =
873 webkit_glue::EventWithMenuAction([menu_runner menuItemWasChosen],
874 window_num, item_height,
875 [menu_runner indexOfSelectedItem],
876 position, view_rect);
877
878 if ([menu_runner menuItemWasChosen]) {
879 // Simulate a menu selection event.
880 const WebMouseEvent& mouse_event =
881 WebInputEventFactory::mouseEvent(event, cocoa_view_);
882 render_widget_host_->ForwardMouseEvent(mouse_event);
883 } else {
884 // Simulate a menu dismiss event.
885 NativeWebKeyboardEvent keyboard_event(event);
886 render_widget_host_->ForwardKeyboardEvent(keyboard_event);
887 }
888 }
889
890 void RenderWidgetHostViewMac::KillSelf() { 801 void RenderWidgetHostViewMac::KillSelf() {
891 if (shutdown_factory_.empty()) { 802 if (shutdown_factory_.empty()) {
892 [cocoa_view_ setHidden:YES]; 803 [cocoa_view_ setHidden:YES];
893 MessageLoop::current()->PostTask(FROM_HERE, 804 MessageLoop::current()->PostTask(FROM_HERE,
894 shutdown_factory_.NewRunnableMethod( 805 shutdown_factory_.NewRunnableMethod(
895 &RenderWidgetHostViewMac::ShutdownHost)); 806 &RenderWidgetHostViewMac::ShutdownHost));
896 } 807 }
897 } 808 }
898 809
899 void RenderWidgetHostViewMac::SetPluginImeEnabled(bool enabled, int plugin_id) { 810 void RenderWidgetHostViewMac::SetPluginImeEnabled(bool enabled, int plugin_id) {
(...skipping 1697 matching lines...) Expand 10 before | Expand all | Expand 10 after
2597 if (!string) return NO; 2508 if (!string) return NO;
2598 2509
2599 // If the user is currently using an IME, confirm the IME input, 2510 // If the user is currently using an IME, confirm the IME input,
2600 // and then insert the text from the service, the same as TextEdit and Safari. 2511 // and then insert the text from the service, the same as TextEdit and Safari.
2601 [self confirmComposition]; 2512 [self confirmComposition];
2602 [self insertText:string]; 2513 [self insertText:string];
2603 return YES; 2514 return YES;
2604 } 2515 }
2605 2516
2606 @end 2517 @end
OLDNEW
« no previous file with comments | « chrome/browser/renderer_host/render_widget_host_view_mac.h ('k') | chrome/browser/renderer_host/test/test_render_view_host.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698