📄 popupmenuchromium.cpp
字号:
{ return m_listBox->handleMouseDownEvent( constructRelativeMouseEvent(event, this, m_listBox.get()));}bool PopupContainer::handleMouseMoveEvent(const PlatformMouseEvent& event){ return m_listBox->handleMouseMoveEvent( constructRelativeMouseEvent(event, this, m_listBox.get()));}bool PopupContainer::handleMouseReleaseEvent(const PlatformMouseEvent& event){ return m_listBox->handleMouseReleaseEvent( constructRelativeMouseEvent(event, this, m_listBox.get()));}bool PopupContainer::handleWheelEvent(const PlatformWheelEvent& event){ return m_listBox->handleWheelEvent( constructRelativeWheelEvent(event, this, m_listBox.get()));}bool PopupContainer::handleKeyEvent(const PlatformKeyboardEvent& event){ return m_listBox->handleKeyEvent(event);}void PopupContainer::hide(){ m_listBox->abandon();}void PopupContainer::paint(GraphicsContext* gc, const IntRect& rect){ // adjust coords for scrolled frame IntRect r = intersection(rect, frameRect()); int tx = x(); int ty = y(); r.move(-tx, -ty); gc->translate(static_cast<float>(tx), static_cast<float>(ty)); m_listBox->paint(gc, r); gc->translate(-static_cast<float>(tx), -static_cast<float>(ty)); paintBorder(gc, rect);}void PopupContainer::paintBorder(GraphicsContext* gc, const IntRect& rect){ // FIXME: Where do we get the border color from? Color borderColor(127, 157, 185); gc->setStrokeStyle(NoStroke); gc->setFillColor(borderColor); int tx = x(); int ty = y(); // top, left, bottom, right gc->drawRect(IntRect(tx, ty, width(), kBorderSize)); gc->drawRect(IntRect(tx, ty, kBorderSize, height())); gc->drawRect(IntRect(tx, ty + height() - kBorderSize, width(), kBorderSize)); gc->drawRect(IntRect(tx + width() - kBorderSize, ty, kBorderSize, height()));}bool PopupContainer::isInterestedInEventForKey(int keyCode){ return m_listBox->isInterestedInEventForKey(keyCode);}void PopupContainer::show(const IntRect& r, FrameView* v, int index){ // The rect is the size of the select box. It's usually larger than we need. // subtract border size so that usually the container will be displayed // exactly the same width as the select box. listBox()->setBaseWidth(max(r.width() - kBorderSize * 2, 0)); listBox()->updateFromElement(); // We set the selected item in updateFromElement(), and disregard the // index passed into this function (same as Webkit's PopupMenuWin.cpp) // FIXME: make sure this is correct, and add an assertion. // ASSERT(popupWindow(popup)->listBox()->selectedIndex() == index); // Convert point to main window coords. IntPoint location = v->contentsToWindow(r.location()); // Move it below the select widget. location.move(0, r.height()); IntRect popupRect(location, r.size()); setFrameRect(popupRect); showPopup(v);}void PopupContainer::refresh(){ listBox()->updateFromElement(); layout();}///////////////////////////////////////////////////////////////////////////////// PopupListBox implementationbool PopupListBox::handleMouseDownEvent(const PlatformMouseEvent& event){ Scrollbar* scrollbar = scrollbarUnderMouse(event); if (scrollbar) { m_capturingScrollbar = scrollbar; m_capturingScrollbar->mouseDown(event); return true; } if (!isPointInBounds(event.pos())) abandon(); return true;}bool PopupListBox::handleMouseMoveEvent(const PlatformMouseEvent& event){ if (m_capturingScrollbar) { m_capturingScrollbar->mouseMoved(event); return true; } Scrollbar* scrollbar = scrollbarUnderMouse(event); if (m_lastScrollbarUnderMouse != scrollbar) { // Send mouse exited to the old scrollbar. if (m_lastScrollbarUnderMouse) m_lastScrollbarUnderMouse->mouseExited(); m_lastScrollbarUnderMouse = scrollbar; } if (scrollbar) { scrollbar->mouseMoved(event); return true; } if (!isPointInBounds(event.pos())) return false; selectIndex(pointToRowIndex(event.pos())); return true;}bool PopupListBox::handleMouseReleaseEvent(const PlatformMouseEvent& event){ if (m_capturingScrollbar) { m_capturingScrollbar->mouseUp(); m_capturingScrollbar = 0; return true; } if (!isPointInBounds(event.pos())) return true; acceptIndex(pointToRowIndex(event.pos())); return true;}bool PopupListBox::handleWheelEvent(const PlatformWheelEvent& event){ if (!isPointInBounds(event.pos())) { abandon(); return true; } // Pass it off to the scroll view. // Sadly, WebCore devs don't understand the whole "const" thing. wheelEvent(const_cast<PlatformWheelEvent&>(event)); return true;}// Should be kept in sync with handleKeyEvent().bool PopupListBox::isInterestedInEventForKey(int keyCode){ switch (keyCode) { case VKEY_ESCAPE: case VKEY_RETURN: case VKEY_UP: case VKEY_DOWN: case VKEY_PRIOR: case VKEY_NEXT: case VKEY_HOME: case VKEY_END: case VKEY_TAB: return true; default: return false; }}bool PopupListBox::handleKeyEvent(const PlatformKeyboardEvent& event){ if (event.type() == PlatformKeyboardEvent::KeyUp) return true; if (numItems() == 0 && event.windowsVirtualKeyCode() != VKEY_ESCAPE) return true; switch (event.windowsVirtualKeyCode()) { case VKEY_ESCAPE: abandon(); // may delete this return true; case VKEY_RETURN: if (m_selectedIndex == -1) { m_popupClient->hidePopup(); // Don't eat the enter if nothing is selected. return false; } acceptIndex(m_selectedIndex); // may delete this return true; case VKEY_UP: selectPreviousRow(); break; case VKEY_DOWN: selectNextRow(); break; case VKEY_PRIOR: adjustSelectedIndex(-m_visibleRows); break; case VKEY_NEXT: adjustSelectedIndex(m_visibleRows); break; case VKEY_HOME: adjustSelectedIndex(-m_selectedIndex); break; case VKEY_END: adjustSelectedIndex(m_items.size()); break; default: if (!event.ctrlKey() && !event.altKey() && !event.metaKey() && isPrintableChar(event.windowsVirtualKeyCode())) typeAheadFind(event); break; } if (m_originalIndex != m_selectedIndex) { // Keyboard events should update the selection immediately (but we don't // want to fire the onchange event until the popup is closed, to match // IE). We change the original index so we revert to that when the // popup is closed. if (m_settings.acceptOnAbandon) m_willAcceptOnAbandon = true; setOriginalIndex(m_selectedIndex); if (m_settings.setTextOnIndexChange) m_popupClient->setTextFromItem(m_selectedIndex); } else if (!m_settings.setTextOnIndexChange && event.windowsVirtualKeyCode() == VKEY_TAB) { // TAB is a special case as it should select the current item if any and // advance focus. if (m_selectedIndex >= 0) m_popupClient->setTextFromItem(m_selectedIndex); // Return false so the TAB key event is propagated to the page. return false; } return true;}HostWindow* PopupListBox::hostWindow() const{ // Our parent is the root ScrollView, so it is the one that has a // HostWindow. FrameView::hostWindow() works similarly. return parent() ? parent()->hostWindow() : 0;}// From HTMLSelectElement.cppstatic String stripLeadingWhiteSpace(const String& string){ int length = string.length(); int i; for (i = 0; i < length; ++i) if (string[i] != noBreakSpace && (string[i] <= 0x7F ? !isspace(string[i]) : (direction(string[i]) != WhiteSpaceNeutral))) break; return string.substring(i, length - i);}// From HTMLSelectElement.cpp, with modificationsvoid PopupListBox::typeAheadFind(const PlatformKeyboardEvent& event){ TimeStamp now = static_cast<TimeStamp>(currentTime() * 1000.0f); TimeStamp delta = now - m_lastCharTime; m_lastCharTime = now; UChar c = event.windowsVirtualKeyCode(); String prefix; int searchStartOffset = 1; if (delta > kTypeAheadTimeoutMs) { m_typedString = prefix = String(&c, 1); m_repeatingChar = c; } else { m_typedString.append(c); if (c == m_repeatingChar) // The user is likely trying to cycle through all the items starting with this character, so just search on the character prefix = String(&c, 1); else { m_repeatingChar = 0; prefix = m_typedString; searchStartOffset = 0; } } int itemCount = numItems(); int index = (max(0, m_selectedIndex) + searchStartOffset) % itemCount; for (int i = 0; i < itemCount; i++, index = (index + 1) % itemCount) { if (!isSelectableItem(index)) continue; if (stripLeadingWhiteSpace(m_items[index]->label).startsWith(prefix, false)) { selectIndex(index); return; } }}void PopupListBox::paint(GraphicsContext* gc, const IntRect& rect){ // adjust coords for scrolled frame IntRect r = intersection(rect, frameRect()); int tx = x() - scrollX(); int ty = y() - scrollY(); r.move(-tx, -ty); // set clip rect to match revised damage rect gc->save(); gc->translate(static_cast<float>(tx), static_cast<float>(ty)); gc->clip(r); // FIXME: Can we optimize scrolling to not require repainting the entire // window? Should we? for (int i = 0; i < numItems(); ++i) paintRow(gc, r, i); // Special case for an empty popup. if (numItems() == 0) gc->fillRect(r, Color::white); gc->restore(); ScrollView::paint(gc, rect);}static const int separatorPadding = 4;static const int separatorHeight = 1;void PopupListBox::paintRow(GraphicsContext* gc, const IntRect& rect, int rowIndex){ // This code is based largely on RenderListBox::paint* methods. IntRect rowRect = getRowBounds(rowIndex); if (!rowRect.intersects(rect)) return; PopupMenuStyle style = m_popupClient->itemStyle(rowIndex); // Paint background Color backColor, textColor; if (rowIndex == m_selectedIndex) { backColor = theme()->activeListBoxSelectionBackgroundColor(); textColor = theme()->activeListBoxSelectionForegroundColor(); } else { backColor = style.backgroundColor(); textColor = style.foregroundColor(); } // If we have a transparent background, make sure it has a color to blend // against. if (backColor.hasAlpha())
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -