OLD | NEW |
1 // Copyright (c) 2008, Google Inc. | 1 // Copyright (c) 2008, Google Inc. |
2 // All rights reserved. | 2 // 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 18 matching lines...) Expand all Loading... |
29 | 29 |
30 #include "config.h" | 30 #include "config.h" |
31 | 31 |
32 #pragma warning(push, 0) | 32 #pragma warning(push, 0) |
33 #include "PopupMenu.h" | 33 #include "PopupMenu.h" |
34 | 34 |
35 #include "CharacterNames.h" | 35 #include "CharacterNames.h" |
36 #include "ChromeClientChromium.h" | 36 #include "ChromeClientChromium.h" |
37 #include "Document.h" | 37 #include "Document.h" |
38 #include "Font.h" | 38 #include "Font.h" |
39 #include "Frame.h" | |
40 #include "FrameView.h" | 39 #include "FrameView.h" |
41 #include "FontSelector.h" | 40 #include "FontSelector.h" |
| 41 #include "Frame.h" |
42 #include "FramelessScrollView.h" | 42 #include "FramelessScrollView.h" |
43 #include "FramelessScrollViewClient.h" | 43 #include "FramelessScrollViewClient.h" |
44 #include "GraphicsContext.h" | 44 #include "GraphicsContext.h" |
45 #include "IntRect.h" | 45 #include "IntRect.h" |
46 #include "KeyboardCodes.h" | 46 #include "KeyboardCodes.h" |
47 #include "NotImplemented.h" | 47 #include "NotImplemented.h" |
48 #include "Page.h" | 48 #include "Page.h" |
49 #include "PlatformKeyboardEvent.h" | 49 #include "PlatformKeyboardEvent.h" |
50 #include "PlatformMouseEvent.h" | 50 #include "PlatformMouseEvent.h" |
51 #include "PlatformScreen.h" | 51 #include "PlatformScreen.h" |
52 #include "PlatformWheelEvent.h" | 52 #include "PlatformWheelEvent.h" |
53 #include "RenderBlock.h" | 53 #include "RenderBlock.h" |
54 #include "RenderTheme.h" | 54 #include "RenderTheme.h" |
55 #include "ScrollbarTheme.h" | 55 #include "ScrollbarTheme.h" |
56 #include "SystemTime.h" | 56 #include "SystemTime.h" |
57 #include "Widget.h" | 57 #include "Widget.h" |
58 #pragma warning(pop) | 58 #pragma warning(pop) |
59 | 59 |
| 60 #include "webkit/port/platform/chromium/PopupMenuChromium.h" |
| 61 |
60 using namespace WTF; | 62 using namespace WTF; |
61 using namespace Unicode; | 63 using namespace Unicode; |
62 | 64 |
63 using std::min; | 65 using std::min; |
64 using std::max; | 66 using std::max; |
65 | 67 |
66 namespace WebCore { | 68 namespace WebCore { |
67 | 69 |
68 typedef unsigned long long TimeStamp; | 70 typedef unsigned long long TimeStamp; |
69 | 71 |
70 static const int kMaxVisibleRows = 20; | 72 static const int kMaxVisibleRows = 20; |
71 static const int kMaxHeight = 500; | 73 static const int kMaxHeight = 500; |
72 static const int kBorderSize = 1; | 74 static const int kBorderSize = 1; |
73 static const TimeStamp kTypeAheadTimeoutMs = 1000; | 75 static const TimeStamp kTypeAheadTimeoutMs = 1000; |
74 | 76 |
75 class PopupListBox; | |
76 | |
77 // TODO(darin): Our FramelessScrollView classes need to implement HostWindow! | |
78 | |
79 // This class holds a PopupListBox. Its sole purpose is to be able to draw | |
80 // a border around its child. All its paint/event handling is just forwarded | |
81 // to the child listBox (with the appropriate transforms). | |
82 class PopupContainer : public FramelessScrollView, public RefCounted<PopupContai
ner> { | |
83 public: | |
84 static PassRefPtr<PopupContainer> create(PopupMenuClient* client); | |
85 | |
86 // FramelessScrollView | |
87 virtual void paint(GraphicsContext* gc, const IntRect& rect); | |
88 virtual void hide(); | |
89 virtual bool handleMouseDownEvent(const PlatformMouseEvent& event); | |
90 virtual bool handleMouseMoveEvent(const PlatformMouseEvent& event); | |
91 virtual bool handleMouseReleaseEvent(const PlatformMouseEvent& event); | |
92 virtual bool handleWheelEvent(const PlatformWheelEvent& event); | |
93 virtual bool handleKeyEvent(const PlatformKeyboardEvent& event); | |
94 | |
95 // PopupContainer methods | |
96 | |
97 // Show the popup | |
98 void showPopup(FrameView* view); | |
99 | |
100 // Hide the popup. Do not call this directly: use client->hidePopup(). | |
101 void hidePopup(); | |
102 | |
103 // Compute size of widget and children. | |
104 void layout(); | |
105 | |
106 PopupListBox* listBox() const { return m_listBox.get(); } | |
107 | |
108 private: | |
109 friend class RefCounted<PopupContainer>; | |
110 | |
111 PopupContainer(PopupMenuClient* client); | |
112 ~PopupContainer(); | |
113 | |
114 // Paint the border. | |
115 void paintBorder(GraphicsContext* gc, const IntRect& rect); | |
116 | |
117 RefPtr<PopupListBox> m_listBox; | |
118 }; | |
119 | |
120 // This class uses WebCore code to paint and handle events for a drop-down list | 77 // This class uses WebCore code to paint and handle events for a drop-down list |
121 // box ("combobox" on Windows). | 78 // box ("combobox" on Windows). |
122 class PopupListBox : public FramelessScrollView, public RefCounted<PopupListBox>
{ | 79 class PopupListBox : public FramelessScrollView, public RefCounted<PopupListBox>
{ |
123 public: | 80 public: |
124 // FramelessScrollView | 81 // FramelessScrollView |
125 virtual void paint(GraphicsContext* gc, const IntRect& rect); | 82 virtual void paint(GraphicsContext* gc, const IntRect& rect); |
126 virtual bool handleMouseDownEvent(const PlatformMouseEvent& event); | 83 virtual bool handleMouseDownEvent(const PlatformMouseEvent& event); |
127 virtual bool handleMouseMoveEvent(const PlatformMouseEvent& event); | 84 virtual bool handleMouseMoveEvent(const PlatformMouseEvent& event); |
128 virtual bool handleMouseReleaseEvent(const PlatformMouseEvent& event); | 85 virtual bool handleMouseReleaseEvent(const PlatformMouseEvent& event); |
129 virtual bool handleWheelEvent(const PlatformWheelEvent& event); | 86 virtual bool handleWheelEvent(const PlatformWheelEvent& event); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
163 int numItems() const { return static_cast<int>(m_items.size()); } | 120 int numItems() const { return static_cast<int>(m_items.size()); } |
164 | 121 |
165 void setBaseWidth(int width) | 122 void setBaseWidth(int width) |
166 { | 123 { |
167 m_baseWidth = width; | 124 m_baseWidth = width; |
168 } | 125 } |
169 | 126 |
170 // Compute size of widget and children. | 127 // Compute size of widget and children. |
171 void layout(); | 128 void layout(); |
172 | 129 |
| 130 // Returns whether the popup wants to process events for the passed key. |
| 131 bool isInterestedInEventForKey(int key_code); |
| 132 |
173 private: | 133 private: |
174 friend class PopupContainer; | 134 friend class PopupContainer; |
175 friend class RefCounted<PopupListBox>; | 135 friend class RefCounted<PopupListBox>; |
176 | 136 |
177 // A type of List Item | 137 // A type of List Item |
178 enum ListItemType { | 138 enum ListItemType { |
179 TYPE_OPTION, | 139 TYPE_OPTION, |
180 TYPE_GROUP, | 140 TYPE_GROUP, |
181 TYPE_SEPARATOR | 141 TYPE_SEPARATOR |
182 }; | 142 }; |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
320 IntPoint& relativePos = const_cast<IntPoint&>(relativeEvent.pos()); | 280 IntPoint& relativePos = const_cast<IntPoint&>(relativeEvent.pos()); |
321 relativePos.setX(pos.x()); | 281 relativePos.setX(pos.x()); |
322 relativePos.setY(pos.y()); | 282 relativePos.setY(pos.y()); |
323 return relativeEvent; | 283 return relativeEvent; |
324 } | 284 } |
325 | 285 |
326 /////////////////////////////////////////////////////////////////////////////// | 286 /////////////////////////////////////////////////////////////////////////////// |
327 // PopupContainer implementation | 287 // PopupContainer implementation |
328 | 288 |
329 // static | 289 // static |
330 PassRefPtr<PopupContainer> PopupContainer::create(PopupMenuClient* client) | 290 PassRefPtr<PopupContainer> PopupContainer::create(PopupMenuClient* client, |
| 291 bool focusOnShow) |
331 { | 292 { |
332 return adoptRef(new PopupContainer(client)); | 293 return adoptRef(new PopupContainer(client, focusOnShow)); |
333 } | 294 } |
334 | 295 |
335 PopupContainer::PopupContainer(PopupMenuClient* client) | 296 PopupContainer::PopupContainer(PopupMenuClient* client, bool focusOnShow) |
336 : m_listBox(new PopupListBox(client)) | 297 : m_listBox(new PopupListBox(client)), |
| 298 m_focusOnShow(focusOnShow) |
337 { | 299 { |
338 // FrameViews are created with a refcount of 1 so it needs releasing after w
e | 300 // FrameViews are created with a refcount of 1 so it needs releasing after w
e |
339 // assign it to a RefPtr. | 301 // assign it to a RefPtr. |
340 m_listBox->deref(); | 302 m_listBox->deref(); |
341 | 303 |
342 setScrollbarModes(ScrollbarAlwaysOff, ScrollbarAlwaysOff); | 304 setScrollbarModes(ScrollbarAlwaysOff, ScrollbarAlwaysOff); |
343 } | 305 } |
344 | 306 |
345 PopupContainer::~PopupContainer() | 307 PopupContainer::~PopupContainer() |
346 { | 308 { |
(...skipping 13 matching lines...) Expand all Loading... |
360 ChromeClientChromium* chromeClient = static_cast<ChromeClientChromium*>( | 322 ChromeClientChromium* chromeClient = static_cast<ChromeClientChromium*>( |
361 view->frame()->page()->chrome()->client()); | 323 view->frame()->page()->chrome()->client()); |
362 if (chromeClient) { | 324 if (chromeClient) { |
363 // If the popup would extend past the bottom of the screen, open upwards | 325 // If the popup would extend past the bottom of the screen, open upwards |
364 // instead. | 326 // instead. |
365 FloatRect screen = screenRect(view); | 327 FloatRect screen = screenRect(view); |
366 IntRect widgetRect = chromeClient->windowToScreen(frameRect()); | 328 IntRect widgetRect = chromeClient->windowToScreen(frameRect()); |
367 if (widgetRect.bottom() > static_cast<int>(screen.bottom())) | 329 if (widgetRect.bottom() > static_cast<int>(screen.bottom())) |
368 widgetRect.move(0, -(widgetRect.height() + selectHeight)); | 330 widgetRect.move(0, -(widgetRect.height() + selectHeight)); |
369 | 331 |
370 chromeClient->popupOpened(this, widgetRect); | 332 chromeClient->popupOpened(this, widgetRect, m_focusOnShow); |
371 } | 333 } |
372 | 334 |
373 // Must get called after we have a client and containingWindow. | 335 // Must get called after we have a client and containingWindow. |
374 addChild(m_listBox.get()); | 336 addChild(m_listBox.get()); |
375 | 337 |
376 // Enable scrollbars after the listbox is inserted into the hierarchy, so | 338 // Enable scrollbars after the listbox is inserted into the hierarchy, so |
377 // it has a proper WidgetClient. | 339 // it has a proper WidgetClient. |
378 m_listBox->setVerticalScrollbarMode(ScrollbarAuto); | 340 m_listBox->setVerticalScrollbarMode(ScrollbarAuto); |
379 | 341 |
380 m_listBox->scrollToRevealSelection(); | 342 m_listBox->scrollToRevealSelection(); |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
467 int tx = x(); | 429 int tx = x(); |
468 int ty = y(); | 430 int ty = y(); |
469 | 431 |
470 // top, left, bottom, right | 432 // top, left, bottom, right |
471 gc->drawRect(IntRect(tx, ty, width(), kBorderSize)); | 433 gc->drawRect(IntRect(tx, ty, width(), kBorderSize)); |
472 gc->drawRect(IntRect(tx, ty, kBorderSize, height())); | 434 gc->drawRect(IntRect(tx, ty, kBorderSize, height())); |
473 gc->drawRect(IntRect(tx, ty + height() - kBorderSize, width(), kBorderSize))
; | 435 gc->drawRect(IntRect(tx, ty + height() - kBorderSize, width(), kBorderSize))
; |
474 gc->drawRect(IntRect(tx + width() - kBorderSize, ty, kBorderSize, height()))
; | 436 gc->drawRect(IntRect(tx + width() - kBorderSize, ty, kBorderSize, height()))
; |
475 } | 437 } |
476 | 438 |
| 439 bool PopupContainer::isInterestedInEventForKey(int key_code) { |
| 440 return m_listBox->isInterestedInEventForKey(key_code); |
| 441 } |
| 442 |
| 443 void PopupContainer::show(const IntRect& r, FrameView* v, int index) { |
| 444 // The rect is the size of the select box. It's usually larger than we need. |
| 445 // subtract border size so that usually the container will be displayed |
| 446 // exactly the same width as the select box. |
| 447 listBox()->setBaseWidth(max(r.width() - kBorderSize * 2, 0)); |
| 448 |
| 449 listBox()->updateFromElement(); |
| 450 |
| 451 // We set the selected item in updateFromElement(), and disregard the |
| 452 // index passed into this function (same as Webkit's PopupMenuWin.cpp) |
| 453 // TODO(ericroman): make sure this is correct, and add an assertion. |
| 454 // DCHECK(popupWindow(popup)->listBox()->selectedIndex() == index); |
| 455 |
| 456 // Convert point to main window coords. |
| 457 IntPoint location = v->contentsToWindow(r.location()); |
| 458 |
| 459 // Move it below the select widget. |
| 460 location.move(0, r.height()); |
| 461 |
| 462 IntRect popupRect(location, r.size()); |
| 463 setFrameRect(popupRect); |
| 464 showPopup(v); |
| 465 } |
477 | 466 |
478 /////////////////////////////////////////////////////////////////////////////// | 467 /////////////////////////////////////////////////////////////////////////////// |
479 // PopupListBox implementation | 468 // PopupListBox implementation |
480 | 469 |
481 bool PopupListBox::handleMouseDownEvent(const PlatformMouseEvent& event) | 470 bool PopupListBox::handleMouseDownEvent(const PlatformMouseEvent& event) |
482 { | 471 { |
483 Scrollbar* scrollbar = scrollbarUnderMouse(event); | 472 Scrollbar* scrollbar = scrollbarUnderMouse(event); |
484 if (scrollbar) { | 473 if (scrollbar) { |
485 m_capturingScrollbar = scrollbar; | 474 m_capturingScrollbar = scrollbar; |
486 m_capturingScrollbar->mouseDown(event); | 475 m_capturingScrollbar->mouseDown(event); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
541 abandon(); | 530 abandon(); |
542 return true; | 531 return true; |
543 } | 532 } |
544 | 533 |
545 // Pass it off to the scroll view. | 534 // Pass it off to the scroll view. |
546 // Sadly, WebCore devs don't understand the whole "const" thing. | 535 // Sadly, WebCore devs don't understand the whole "const" thing. |
547 wheelEvent(const_cast<PlatformWheelEvent&>(event)); | 536 wheelEvent(const_cast<PlatformWheelEvent&>(event)); |
548 return true; | 537 return true; |
549 } | 538 } |
550 | 539 |
| 540 // Should be kept in sync with handleKeyEvent(). |
| 541 bool PopupListBox::isInterestedInEventForKey(int key_code) { |
| 542 switch (key_code) { |
| 543 case VKEY_ESCAPE: |
| 544 case VKEY_RETURN: |
| 545 case VKEY_UP: |
| 546 case VKEY_DOWN: |
| 547 case VKEY_PRIOR: |
| 548 case VKEY_NEXT: |
| 549 case VKEY_HOME: |
| 550 case VKEY_END: |
| 551 return true; |
| 552 default: |
| 553 return false; |
| 554 } |
| 555 } |
| 556 |
551 bool PopupListBox::handleKeyEvent(const PlatformKeyboardEvent& event) | 557 bool PopupListBox::handleKeyEvent(const PlatformKeyboardEvent& event) |
552 { | 558 { |
553 if (event.type() == PlatformKeyboardEvent::KeyUp) | 559 if (event.type() == PlatformKeyboardEvent::KeyUp) |
554 return true; | 560 return true; |
555 | 561 |
556 if (numItems() == 0 && event.windowsVirtualKeyCode() != VKEY_ESCAPE) | 562 if (numItems() == 0 && event.windowsVirtualKeyCode() != VKEY_ESCAPE) |
557 return true; | 563 return true; |
558 | 564 |
559 switch (event.windowsVirtualKeyCode()) { | 565 switch (event.windowsVirtualKeyCode()) { |
560 case VKEY_ESCAPE: | 566 case VKEY_ESCAPE: |
(...skipping 468 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1029 { | 1035 { |
1030 } | 1036 } |
1031 | 1037 |
1032 PopupMenu::~PopupMenu() | 1038 PopupMenu::~PopupMenu() |
1033 { | 1039 { |
1034 hide(); | 1040 hide(); |
1035 } | 1041 } |
1036 | 1042 |
1037 void PopupMenu::show(const IntRect& r, FrameView* v, int index) | 1043 void PopupMenu::show(const IntRect& r, FrameView* v, int index) |
1038 { | 1044 { |
1039 p.m_popup = PopupContainer::create(client()); | 1045 p.m_popup = PopupContainer::create(client(), true); |
1040 | 1046 p.m_popup->show(r, v, index); |
1041 // The rect is the size of the select box. It's usually larger than we need. | |
1042 // subtract border size so that usually the container will be displayed | |
1043 // exactly the same width as the select box. | |
1044 p.m_popup->listBox()->setBaseWidth(max(r.width() - kBorderSize * 2, 0)); | |
1045 | |
1046 updateFromElement(); | |
1047 | |
1048 // We set the selected item in updateFromElement(), and disregard the | |
1049 // index passed into this function (same as Webkit's PopupMenuWin.cpp) | |
1050 // TODO(ericroman): make sure this is correct, and add an assertion. | |
1051 // DCHECK(popupWindow(m_popup)->listBox()->selectedIndex() == index); | |
1052 | |
1053 // Convert point to main window coords. | |
1054 IntPoint location = v->contentsToWindow(r.location()); | |
1055 | |
1056 // Move it below the select widget. | |
1057 location.move(0, r.height()); | |
1058 | |
1059 IntRect popupRect(location, r.size()); | |
1060 p.m_popup->setFrameRect(popupRect); | |
1061 p.m_popup->showPopup(v); | |
1062 } | 1047 } |
1063 | 1048 |
1064 void PopupMenu::hide() | 1049 void PopupMenu::hide() |
1065 { | 1050 { |
1066 if (p.m_popup) { | 1051 if (p.m_popup) { |
1067 p.m_popup->hidePopup(); | 1052 p.m_popup->hidePopup(); |
1068 p.m_popup = 0; | 1053 p.m_popup = 0; |
1069 } | 1054 } |
1070 } | 1055 } |
1071 | 1056 |
1072 void PopupMenu::updateFromElement() | 1057 void PopupMenu::updateFromElement() |
1073 { | 1058 { |
1074 p.m_popup->listBox()->updateFromElement(); | 1059 p.m_popup->listBox()->updateFromElement(); |
1075 } | 1060 } |
1076 | 1061 |
1077 bool PopupMenu::itemWritingDirectionIsNatural() | 1062 bool PopupMenu::itemWritingDirectionIsNatural() |
1078 { | 1063 { |
1079 return false; | 1064 return false; |
1080 } | 1065 } |
1081 | 1066 |
1082 } // namespace WebCore | 1067 } // namespace WebCore |
OLD | NEW |