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

Side by Side Diff: third_party/WebKit/WebCore/platform/chromium/PopupMenuChromium.cpp

Issue 19765: Fix PopupMenuChromium to hide itself before calling valueChanged. This bette... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 11 years, 10 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2008, 2009, Google Inc. All rights reserved. 2 * Copyright (c) 2008, 2009, Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
66 66
67 static const int kMaxVisibleRows = 20; 67 static const int kMaxVisibleRows = 20;
68 static const int kMaxHeight = 500; 68 static const int kMaxHeight = 500;
69 static const int kBorderSize = 1; 69 static const int kBorderSize = 1;
70 static const TimeStamp kTypeAheadTimeoutMs = 1000; 70 static const TimeStamp kTypeAheadTimeoutMs = 1000;
71 71
72 // This class uses WebCore code to paint and handle events for a drop-down list 72 // This class uses WebCore code to paint and handle events for a drop-down list
73 // box ("combobox" on Windows). 73 // box ("combobox" on Windows).
74 class PopupListBox : public FramelessScrollView, public RefCounted<PopupListBox> { 74 class PopupListBox : public FramelessScrollView, public RefCounted<PopupListBox> {
75 public: 75 public:
76 static PassRefPtr<PopupListBox> create(PopupMenuClient* client)
77 {
78 return adoptRef(new PopupListBox(client));
79 }
80
76 // FramelessScrollView 81 // FramelessScrollView
77 virtual void paint(GraphicsContext*, const IntRect&); 82 virtual void paint(GraphicsContext*, const IntRect&);
78 virtual bool handleMouseDownEvent(const PlatformMouseEvent&); 83 virtual bool handleMouseDownEvent(const PlatformMouseEvent&);
79 virtual bool handleMouseMoveEvent(const PlatformMouseEvent&); 84 virtual bool handleMouseMoveEvent(const PlatformMouseEvent&);
80 virtual bool handleMouseReleaseEvent(const PlatformMouseEvent&); 85 virtual bool handleMouseReleaseEvent(const PlatformMouseEvent&);
81 virtual bool handleWheelEvent(const PlatformWheelEvent&); 86 virtual bool handleWheelEvent(const PlatformWheelEvent&);
82 virtual bool handleKeyEvent(const PlatformKeyboardEvent&); 87 virtual bool handleKeyEvent(const PlatformKeyboardEvent&);
83 88
84 // ScrollView 89 // ScrollView
85 virtual HostWindow* hostWindow() const; 90 virtual HostWindow* hostWindow() const;
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after
316 // PopupContainer implementation 321 // PopupContainer implementation
317 322
318 // static 323 // static
319 PassRefPtr<PopupContainer> PopupContainer::create(PopupMenuClient* client, 324 PassRefPtr<PopupContainer> PopupContainer::create(PopupMenuClient* client,
320 bool focusOnShow) 325 bool focusOnShow)
321 { 326 {
322 return adoptRef(new PopupContainer(client, focusOnShow)); 327 return adoptRef(new PopupContainer(client, focusOnShow));
323 } 328 }
324 329
325 PopupContainer::PopupContainer(PopupMenuClient* client, bool focusOnShow) 330 PopupContainer::PopupContainer(PopupMenuClient* client, bool focusOnShow)
326 : m_listBox(new PopupListBox(client)), 331 : m_listBox(PopupListBox::create(client))
327 m_focusOnShow(focusOnShow) 332 , m_focusOnShow(focusOnShow)
328 { 333 {
329 // FrameViews are created with a refcount of 1 so it needs releasing after w e
330 // assign it to a RefPtr.
331 m_listBox->deref();
332
333 setScrollbarModes(ScrollbarAlwaysOff, ScrollbarAlwaysOff); 334 setScrollbarModes(ScrollbarAlwaysOff, ScrollbarAlwaysOff);
334 } 335 }
335 336
336 PopupContainer::~PopupContainer() 337 PopupContainer::~PopupContainer()
337 { 338 {
338 if (m_listBox) 339 if (m_listBox)
339 removeChild(m_listBox.get()); 340 removeChild(m_listBox.get());
340 } 341 }
341 342
342 void PopupContainer::showPopup(FrameView* view) 343 void PopupContainer::showPopup(FrameView* view)
(...skipping 11 matching lines...) Expand all
354 // If the popup would extend past the bottom of the screen, open upwards 355 // If the popup would extend past the bottom of the screen, open upwards
355 // instead. 356 // instead.
356 FloatRect screen = screenRect(view); 357 FloatRect screen = screenRect(view);
357 IntRect widgetRect = chromeClient->windowToScreen(frameRect()); 358 IntRect widgetRect = chromeClient->windowToScreen(frameRect());
358 if (widgetRect.bottom() > static_cast<int>(screen.bottom())) 359 if (widgetRect.bottom() > static_cast<int>(screen.bottom()))
359 widgetRect.move(0, -(widgetRect.height() + selectHeight)); 360 widgetRect.move(0, -(widgetRect.height() + selectHeight));
360 361
361 chromeClient->popupOpened(this, widgetRect, m_focusOnShow); 362 chromeClient->popupOpened(this, widgetRect, m_focusOnShow);
362 } 363 }
363 364
364 // Must get called after we have a client and containingWindow. 365 if (!m_listBox->parent())
365 addChild(m_listBox.get()); 366 addChild(m_listBox.get());
366 367
367 // Enable scrollbars after the listbox is inserted into the hierarchy, so 368 // Enable scrollbars after the listbox is inserted into the hierarchy,
368 // it has a proper WidgetClient. 369 // so it has a proper WidgetClient.
369 m_listBox->setVerticalScrollbarMode(ScrollbarAuto); 370 m_listBox->setVerticalScrollbarMode(ScrollbarAuto);
370 371
371 m_listBox->scrollToRevealSelection(); 372 m_listBox->scrollToRevealSelection();
372 373
373 invalidate(); 374 invalidate();
374 } 375 }
375 376
376 void PopupContainer::hidePopup() 377 void PopupContainer::hidePopup()
377 { 378 {
378 invalidate();
379
380 m_listBox->disconnectClient();
381 removeChild(m_listBox.get());
382 m_listBox = 0;
383
384 if (client()) 379 if (client())
385 client()->popupClosed(this); 380 client()->popupClosed(this);
386 } 381 }
387 382
388 void PopupContainer::layout() 383 void PopupContainer::layout()
389 { 384 {
390 m_listBox->layout(); 385 m_listBox->layout();
391 386
392 // Place the listbox within our border. 387 // Place the listbox within our border.
393 m_listBox->move(kBorderSize, kBorderSize); 388 m_listBox->move(kBorderSize, kBorderSize);
(...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after
849 844
850 return itemFont; 845 return itemFont;
851 } 846 }
852 847
853 void PopupListBox::abandon() 848 void PopupListBox::abandon()
854 { 849 {
855 RefPtr<PopupListBox> keepAlive(this); 850 RefPtr<PopupListBox> keepAlive(this);
856 851
857 m_selectedIndex = m_originalIndex; 852 m_selectedIndex = m_originalIndex;
858 853
854 m_popupClient->hidePopup();
855
859 if (m_willAcceptOnAbandon) 856 if (m_willAcceptOnAbandon)
860 m_popupClient->valueChanged(m_selectedIndex); 857 m_popupClient->valueChanged(m_selectedIndex);
861
862 // valueChanged may have torn down the popup!
863 if (m_popupClient)
864 m_popupClient->hidePopup();
865 } 858 }
866 859
867 int PopupListBox::pointToRowIndex(const IntPoint& point) 860 int PopupListBox::pointToRowIndex(const IntPoint& point)
868 { 861 {
869 int y = scrollY() + point.y(); 862 int y = scrollY() + point.y();
870 863
871 // FIXME: binary search if perf matters. 864 // FIXME: binary search if perf matters.
872 for (int i = 0; i < numItems(); ++i) { 865 for (int i = 0; i < numItems(); ++i) {
873 if (y < m_items[i]->y) 866 if (y < m_items[i]->y)
874 return i-1; 867 return i-1;
(...skipping 11 matching lines...) Expand all
886 ASSERT(index >= -1 && index < numItems()); 879 ASSERT(index >= -1 && index < numItems());
887 if (index == -1 && m_popupClient) { 880 if (index == -1 && m_popupClient) {
888 // Enter pressed with no selection, just close the popup. 881 // Enter pressed with no selection, just close the popup.
889 m_popupClient->hidePopup(); 882 m_popupClient->hidePopup();
890 return; 883 return;
891 } 884 }
892 885
893 if (isSelectableItem(index)) { 886 if (isSelectableItem(index)) {
894 RefPtr<PopupListBox> keepAlive(this); 887 RefPtr<PopupListBox> keepAlive(this);
895 888
896 // Tell the <select> PopupMenuClient what index was selected, and hide o urself. 889 // Hide ourselves first since valueChanged may have numerous side-effect s.
890 m_popupClient->hidePopup();
891
892 // Tell the <select> PopupMenuClient what index was selected.
897 m_popupClient->valueChanged(index); 893 m_popupClient->valueChanged(index);
898
899 // valueChanged may have torn down the popup!
900 if (m_popupClient)
901 m_popupClient->hidePopup();
902 } 894 }
903 } 895 }
904 896
905 void PopupListBox::selectIndex(int index) 897 void PopupListBox::selectIndex(int index)
906 { 898 {
907 ASSERT(index >= 0 && index < numItems()); 899 ASSERT(index >= 0 && index < numItems());
908 900
909 if (index != m_selectedIndex && isSelectableItem(index)) { 901 if (index != m_selectedIndex && isSelectableItem(index)) {
910 invalidateRow(m_selectedIndex); 902 invalidateRow(m_selectedIndex);
911 m_selectedIndex = index; 903 m_selectedIndex = index;
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after
1150 { 1142 {
1151 } 1143 }
1152 1144
1153 PopupMenu::~PopupMenu() 1145 PopupMenu::~PopupMenu()
1154 { 1146 {
1155 hide(); 1147 hide();
1156 } 1148 }
1157 1149
1158 void PopupMenu::show(const IntRect& r, FrameView* v, int index) 1150 void PopupMenu::show(const IntRect& r, FrameView* v, int index)
1159 { 1151 {
1160 p.popup = PopupContainer::create(client(), true); 1152 if (!p.popup)
1153 p.popup = PopupContainer::create(client(), true);
1161 p.popup->show(r, v, index); 1154 p.popup->show(r, v, index);
1162 } 1155 }
1163 1156
1164 void PopupMenu::hide() 1157 void PopupMenu::hide()
1165 { 1158 {
1166 if (p.popup) { 1159 if (p.popup)
1167 p.popup->hidePopup(); 1160 p.popup->hidePopup();
1168 p.popup = 0;
1169 }
1170 } 1161 }
1171 1162
1172 void PopupMenu::updateFromElement() 1163 void PopupMenu::updateFromElement()
1173 { 1164 {
1174 p.popup->listBox()->updateFromElement(); 1165 p.popup->listBox()->updateFromElement();
1175 } 1166 }
1176 1167
1177 bool PopupMenu::itemWritingDirectionIsNatural() 1168 bool PopupMenu::itemWritingDirectionIsNatural()
1178 { 1169 {
1179 return false; 1170 return false;
1180 } 1171 }
1181 1172
1182 } // namespace WebCore 1173 } // namespace WebCore
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698