void nsMenuFrame::StartBlinking(nsGUIEvent *aEvent, PRBool aFlipChecked) { StopBlinking(); CreateMenuCommandEvent(aEvent, aFlipChecked); if (!ShouldBlink()) { PassMenuCommandEventToPopupManager(); return; } // Blink off. nsWeakFrame weakFrame(this); mContent->UnsetAttr(kNameSpaceID_None, nsGkAtoms::menuactive, PR_TRUE); if (!weakFrame.IsAlive()) return; if (mMenuParent) { // Make this menu ignore events from now on. mMenuParent->LockMenuUntilClosed(PR_TRUE); } // Set up a timer to blink back on. mBlinkTimer = do_CreateInstance("@mozilla.org/timer;1"); mBlinkTimer->InitWithCallback(mTimerMediator, kBlinkDelay, nsITimer::TYPE_ONE_SHOT); mBlinkState = 1; }
void nsPopupSetFrame::OpenPopup(nsPopupFrameList* aEntry, PRBool aActivateFlag) { nsWeakFrame weakFrame(this); nsIFrame* activeChild = aEntry->mPopupFrame; nsWeakFrame weakPopupFrame(activeChild); nsRefPtr<nsPresContext> presContext = GetPresContext(); nsCOMPtr<nsIContent> popupContent = aEntry->mPopupContent; PRBool createHandlerSucceeded = aEntry->mCreateHandlerSucceeded; nsAutoString popupType = aEntry->mPopupType; if (aActivateFlag) { ActivatePopup(aEntry, PR_TRUE); // register the rollup listeners, etc, but not if we're a tooltip if (!popupType.EqualsLiteral("tooltip")) { nsIFrame* activeChild = aEntry->mPopupFrame; nsIMenuParent* childPopup = nsnull; if (weakPopupFrame.IsAlive()) CallQueryInterface(activeChild, &childPopup); // Tooltips don't get keyboard navigation if (childPopup && !nsMenuFrame::sDismissalListener) { // First check and make sure this popup wants keyboard navigation nsAutoString property; popupContent->GetAttr(kNameSpaceID_None, nsXULAtoms::ignorekeys, property); if (!property.EqualsLiteral("true")) childPopup->InstallKeyboardNavigator(); } UpdateDismissalListener(childPopup); } } else { if (createHandlerSucceeded && !OnDestroy(popupContent)) return; // Unregister, but not if we're a tooltip if (!popupType.EqualsLiteral("tooltip")) { if (nsMenuFrame::sDismissalListener) nsMenuFrame::sDismissalListener->Unregister(); } // Remove any keyboard navigators nsIMenuParent* childPopup = nsnull; if (weakPopupFrame.IsAlive()) CallQueryInterface(activeChild, &childPopup); if (childPopup) childPopup->RemoveKeyboardNavigator(); if (weakPopupFrame.IsAlive()) ActivatePopup(aEntry, PR_FALSE); OnDestroyed(presContext, popupContent); } if (weakFrame.IsAlive()) { nsBoxLayoutState state(mPresContext); MarkDirtyChildren(state); // Mark ourselves dirty. } }
void nsMenuFrame::UpdateMenuType(nsPresContext* aPresContext) { static nsIContent::AttrValuesArray strings[] = {&nsGkAtoms::checkbox, &nsGkAtoms::radio, nsnull}; switch (mContent->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::type, strings, eCaseMatters)) { case 0: mType = eMenuType_Checkbox; break; case 1: mType = eMenuType_Radio; mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::name, mGroupName); break; default: if (mType != eMenuType_Normal) { nsWeakFrame weakFrame(this); mContent->UnsetAttr(kNameSpaceID_None, nsGkAtoms::checked, PR_TRUE); ENSURE_TRUE(weakFrame.IsAlive()); } mType = eMenuType_Normal; break; } UpdateMenuSpecialState(aPresContext); }
void nsMenuFrame::PopupClosed(PRBool aDeselectMenu) { nsWeakFrame weakFrame(this); nsContentUtils::AddScriptRunner( new nsUnsetAttrRunnable(mContent, nsGkAtoms::open)); if (!weakFrame.IsAlive()) return; // if the popup is for a menu on a menubar, inform menubar to deactivate if (mMenuParent && mMenuParent->MenuClosed()) { if (aDeselectMenu) { SelectMenu(PR_FALSE); } else { // We are not deselecting the parent menu while closing the popup, so send // a DOMMenuItemActive event to the menu to indicate that the menu is // becoming active again. nsMenuFrame *current = mMenuParent->GetCurrentMenuItem(); if (current) { nsCOMPtr<nsIRunnable> event = new nsMenuActivateEvent(current->GetContent(), PresContext(), PR_TRUE); NS_DispatchToCurrentThread(event); } } } }
NS_IMETHODIMP nsSplitterFrame::HandleEvent(nsPresContext* aPresContext, nsGUIEvent* aEvent, nsEventStatus* aEventStatus) { NS_ENSURE_ARG_POINTER(aEventStatus); if (nsEventStatus_eConsumeNoDefault == *aEventStatus) { return NS_OK; } nsWeakFrame weakFrame(this); nsRefPtr<nsSplitterFrameInner> kungFuDeathGrip(mInner); switch (aEvent->message) { case NS_MOUSE_MOVE: mInner->MouseDrag(aPresContext, aEvent); break; case NS_MOUSE_BUTTON_UP: if (aEvent->eventStructType == NS_MOUSE_EVENT && static_cast<nsMouseEvent*>(aEvent)->button == nsMouseEvent::eLeftButton) { mInner->MouseUp(aPresContext, aEvent); } break; } NS_ENSURE_STATE(weakFrame.IsAlive()); return nsBoxFrame::HandleEvent(aPresContext, aEvent, aEventStatus); }
PRBool nsSubDocumentFrame::ReflowFinished() { nsCOMPtr<nsIDocShell> docShell; GetDocShell(getter_AddRefs(docShell)); nsCOMPtr<nsIBaseWindow> baseWindow(do_QueryInterface(docShell)); // resize the sub document if (baseWindow) { PRInt32 x = 0; PRInt32 y = 0; nsWeakFrame weakFrame(this); nsPresContext* presContext = PresContext(); baseWindow->GetPositionAndSize(&x, &y, nsnull, nsnull); if (!weakFrame.IsAlive()) { // GetPositionAndSize() killed us return PR_FALSE; } // GetPositionAndSize might have resized us. So now is the time to // get our size. mPostedReflowCallback = PR_FALSE; nsSize innerSize(GetSize()); if (IsInline()) { nsMargin usedBorderPadding = GetUsedBorderAndPadding(); // Sadly, XUL smacks the frame size without changing the used // border and padding, so we can't trust those. Subtracting // them might make things negative. innerSize.width -= usedBorderPadding.LeftRight(); innerSize.width = PR_MAX(innerSize.width, 0); innerSize.height -= usedBorderPadding.TopBottom(); innerSize.height = PR_MAX(innerSize.height, 0); } PRInt32 cx = presContext->AppUnitsToDevPixels(innerSize.width); PRInt32 cy = presContext->AppUnitsToDevPixels(innerSize.height); baseWindow->SetPositionAndSize(x, y, cx, cy, PR_FALSE); } else { // Make sure that we can post a reflow callback in the future. mPostedReflowCallback = PR_FALSE; } return PR_FALSE; }
nsresult nsMenuFrame::Notify(nsITimer* aTimer) { // Our timer has fired. if (aTimer == mOpenTimer.get()) { mOpenTimer = nsnull; if (!IsOpen() && mMenuParent) { // make sure we didn't open a context menu in the meantime // (i.e. the user right-clicked while hovering over a submenu). nsXULPopupManager* pm = nsXULPopupManager::GetInstance(); if (pm) { if ((!pm->HasContextMenu(nsnull) || mMenuParent->IsContextMenu()) && mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::menuactive, nsGkAtoms::_true, eCaseMatters)) { OpenMenu(PR_FALSE); } } } } else if (aTimer == mBlinkTimer) { switch (mBlinkState++) { case 0: NS_ASSERTION(false, "Blink timer fired while not blinking"); StopBlinking(); break; case 1: { // Turn the highlight back on and wait for a while before closing the menu. nsWeakFrame weakFrame(this); mContent->SetAttr(kNameSpaceID_None, nsGkAtoms::menuactive, NS_LITERAL_STRING("true"), PR_TRUE); if (weakFrame.IsAlive()) { aTimer->InitWithCallback(mTimerMediator, kBlinkDelay, nsITimer::TYPE_ONE_SHOT); } } break; default: if (mMenuParent) { mMenuParent->LockMenuUntilClosed(PR_FALSE); } PassMenuCommandEventToPopupManager(); StopBlinking(); break; } } return NS_OK; }
void nsMenuFrame::PopupOpened() { nsWeakFrame weakFrame(this); mContent->SetAttr(kNameSpaceID_None, nsGkAtoms::open, NS_LITERAL_STRING("true"), PR_TRUE); if (!weakFrame.IsAlive()) return; if (mMenuParent) { mMenuParent->SetActive(PR_TRUE); // Make sure the current menu which is being toggled on // the menubar is highlighted mMenuParent->SetCurrentMenuItem(this); } }
void nsPopupSetFrame::ActivatePopup(nsPopupFrameList* aEntry, PRBool aActivateFlag) { if (aEntry->mPopupContent) { // When we sync the popup view with the frame, we'll show the popup if |menutobedisplayed| // is set by setting the |menuactive| attribute. This used to trip css into showing the menu // but now we do it ourselves. if (aActivateFlag) // XXXben hook in |width| and |height| usage here? aEntry->mPopupContent->SetAttr(kNameSpaceID_None, nsXULAtoms::menutobedisplayed, NS_LITERAL_STRING("true"), PR_TRUE); else { nsWeakFrame weakFrame(this); nsWeakFrame weakActiveChild(aEntry->mPopupFrame); nsCOMPtr<nsIContent> content = aEntry->mPopupContent; content->UnsetAttr(kNameSpaceID_None, nsXULAtoms::menuactive, PR_TRUE); content->UnsetAttr(kNameSpaceID_None, nsXULAtoms::menutobedisplayed, PR_TRUE); // get rid of the reflows we just created. If we leave them hanging around, we // can get into trouble if a dialog with a modal event loop comes along and // processes the reflows before we get to call DestroyChain(). Processing the // reflow will cause the popup to show itself again. (bug 71219) nsIDocument* doc = content->GetDocument(); if (doc) doc->FlushPendingNotifications(Flush_OnlyReflow); // make sure we hide the popup. We can't assume that we'll have a view // since we could be cleaning up after someone that didn't correctly // destroy the popup. nsIFrame* activeChild = aEntry->mPopupFrame; if (weakFrame.IsAlive() && weakActiveChild.IsAlive()) { nsIView* view = weakActiveChild.GetFrame()->GetView(); NS_ASSERTION(view, "View is gone, looks like someone forgot to roll up the popup!"); if (view) { nsIViewManager* viewManager = view->GetViewManager(); viewManager->SetViewVisibility(view, nsViewVisibility_kHide); nsRect r(0, 0, 0, 0); viewManager->ResizeView(view, r); if (aEntry->mIsOpen) { aEntry->mIsOpen = PR_FALSE; FireDOMEventSynch(NS_LITERAL_STRING("DOMMenuInactive"), content); } } } } } }
NS_IMETHODIMP nsPopupSetFrame::DestroyPopup(nsIFrame* aPopup, PRBool aDestroyEntireChain) { if (!mPopupList) return NS_OK; // No active popups nsPopupFrameList* entry = mPopupList->GetEntryByFrame(aPopup); if (entry && entry->mCreateHandlerSucceeded) { // ensure the popup was created before we try to destroy it nsWeakFrame weakFrame(this); OpenPopup(entry, PR_FALSE); nsCOMPtr<nsIContent> popupContent = entry->mPopupContent; if (weakFrame.IsAlive()) { if (aDestroyEntireChain && entry->mElementContent && entry->mPopupType.EqualsLiteral("context")) { // If we are a context menu, and if we are attached to a // menupopup, then destroying us should also dismiss the parent // menu popup. if (entry->mElementContent->Tag() == nsXULAtoms::menupopup) { nsIFrame* popupFrame = nsnull; mPresContext->PresShell()->GetPrimaryFrameFor(entry->mElementContent, &popupFrame); if (popupFrame) { nsIMenuParent *menuParent; if (NS_SUCCEEDED(CallQueryInterface(popupFrame, &menuParent))) { menuParent->DismissChain(); } } } } // clear things out for next time entry->mPopupType.Truncate(); entry->mCreateHandlerSucceeded = PR_FALSE; entry->mElementContent = nsnull; entry->mXPos = entry->mYPos = 0; entry->mLastPref.width = -1; entry->mLastPref.height = -1; } // ungenerate the popup. popupContent->UnsetAttr(kNameSpaceID_None, nsXULAtoms::menugenerated, PR_TRUE); } return NS_OK; }
bool ScrollbarActivity::UpdateOpacity(TimeStamp aTime) { double progress = (aTime - mFadeBeginTime) / FadeDuration(); double opacity = 1.0 - std::max(0.0, std::min(1.0, progress)); // 'this' may be getting destroyed during SetOpacityOnElement calls. nsWeakFrame weakFrame((do_QueryFrame(mScrollableFrame))); SetOpacityOnElement(GetHorizontalScrollbar(), opacity); if (!weakFrame.IsAlive()) { return false; } SetOpacityOnElement(GetVerticalScrollbar(), opacity); if (!weakFrame.IsAlive()) { return false; } return true; }
void nsTextControlFrame::SetValueChanged(bool aValueChanged) { nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent()); NS_ASSERTION(txtCtrl, "Content not a text control element"); if (mUsePlaceholder) { PRInt32 textLength; GetTextLength(&textLength); nsWeakFrame weakFrame(this); txtCtrl->SetPlaceholderClass(!textLength, true); if (!weakFrame.IsAlive()) { return; } } txtCtrl->SetValueChanged(aValueChanged); }
//---------------------------------------------------------------------- //nsIRollupListener //---------------------------------------------------------------------- NS_IMETHODIMP nsComboboxControlFrame::Rollup(PRUint32 aCount, nsIContent** aLastRolledUp) { if (aLastRolledUp) *aLastRolledUp = nsnull; if (mDroppedDown) { nsWeakFrame weakFrame(this); mListControlFrame->AboutToRollup(); // might destroy us if (!weakFrame.IsAlive()) return NS_OK; ShowDropDown(PR_FALSE); // might destroy us if (!weakFrame.IsAlive()) return NS_OK; mListControlFrame->CaptureMouseEvents(PR_FALSE); } return NS_OK; }
static void TransformPoints(nsINode* aTo, const GeometryNode& aFrom, uint32_t aPointCount, CSSPoint* aPoints, const ConvertCoordinateOptions& aOptions, ErrorResult& aRv) { nsIFrame* fromFrame = GetFirstNonAnonymousFrameForGeometryNode(aFrom); nsWeakFrame weakFrame(fromFrame); nsIFrame* toFrame = GetFirstNonAnonymousFrameForNode(aTo); // The first frame might be destroyed now if the above call lead to an // EnsureFrameForTextNode call. We need to get the first frame again // when that happens. if (fromFrame && !weakFrame.IsAlive()) { fromFrame = GetFirstNonAnonymousFrameForGeometryNode(aFrom); } if (!fromFrame || !toFrame) { aRv.Throw(NS_ERROR_DOM_NOT_FOUND_ERR); return; } if (!CheckFramesInSameTopLevelBrowsingContext(fromFrame, toFrame)) { aRv.Throw(NS_ERROR_DOM_NOT_FOUND_ERR); return; } nsPoint fromOffset = GetBoxRectForFrame(&fromFrame, aOptions.mFromBox).TopLeft(); nsPoint toOffset = GetBoxRectForFrame(&toFrame, aOptions.mToBox).TopLeft(); CSSPoint fromOffsetGfx(nsPresContext::AppUnitsToFloatCSSPixels(fromOffset.x), nsPresContext::AppUnitsToFloatCSSPixels(fromOffset.y)); for (uint32_t i = 0; i < aPointCount; ++i) { aPoints[i] += fromOffsetGfx; } nsLayoutUtils::TransformResult rv = nsLayoutUtils::TransformPoints(fromFrame, toFrame, aPointCount, aPoints); if (rv == nsLayoutUtils::TRANSFORM_SUCCEEDED) { CSSPoint toOffsetGfx(nsPresContext::AppUnitsToFloatCSSPixels(toOffset.x), nsPresContext::AppUnitsToFloatCSSPixels(toOffset.y)); for (uint32_t i = 0; i < aPointCount; ++i) { aPoints[i] -= toOffsetGfx; } } else { PodZero(aPoints, aPointCount); } }
void nsTextControlFrame::SetValueChanged(PRBool aValueChanged) { nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent()); NS_ASSERTION(txtCtrl, "Content not a text control element"); if (mUsePlaceholder && !nsContentUtils::IsFocusedContent(mContent)) { // If the content is focused, we don't care about the changes because // the placeholder is going to be hidden/shown on blur. PRInt32 textLength; GetTextLength(&textLength); nsWeakFrame weakFrame(this); txtCtrl->SetPlaceholderClass(!textLength, PR_TRUE); if (!weakFrame.IsAlive()) { return; } } txtCtrl->SetValueChanged(aValueChanged); }
bool ScrollbarActivity::UpdateOpacity(TimeStamp aTime) { // Avoid division by zero if mScrollbarFadeDuration is zero, just jump // to the end of the fade animation double progress = mScrollbarFadeDuration ? ((aTime - mFadeBeginTime) / FadeDuration()) : 1.0; double opacity = 1.0 - std::max(0.0, std::min(1.0, progress)); // 'this' may be getting destroyed during SetOpacityOnElement calls. nsWeakFrame weakFrame((do_QueryFrame(mScrollableFrame))); SetOpacityOnElement(GetHorizontalScrollbar(), opacity); if (!weakFrame.IsAlive()) { return false; } SetOpacityOnElement(GetVerticalScrollbar(), opacity); if (!weakFrame.IsAlive()) { return false; } return true; }
bool ScrollbarActivity::SetIsFading(bool aNewFading) { if (mIsFading == aNewFading) return true; mIsFading = aNewFading; if (!mIsFading) { mFadeBeginTime = TimeStamp(); // 'this' may be getting destroyed during UnsetOpacityOnElement calls. nsWeakFrame weakFrame((do_QueryFrame(mScrollableFrame))); UnsetOpacityOnElement(GetHorizontalScrollbar()); if (!weakFrame.IsAlive()) { return false; } UnsetOpacityOnElement(GetVerticalScrollbar()); if (!weakFrame.IsAlive()) { return false; } } return true; }
void GetBoxQuads(nsINode* aNode, const dom::BoxQuadOptions& aOptions, nsTArray<RefPtr<DOMQuad> >& aResult, ErrorResult& aRv) { nsIFrame* frame = GetFrameForNode(aNode); if (!frame) { // No boxes to return return; } nsWeakFrame weakFrame(frame); nsIDocument* ownerDoc = aNode->OwnerDoc(); nsIFrame* relativeToFrame = GetFirstNonAnonymousFrameForGeometryNode(aOptions.mRelativeTo, ownerDoc); // The first frame might be destroyed now if the above call lead to an // EnsureFrameForTextNode call. We need to get the first frame again // when that happens and re-check it. if (!weakFrame.IsAlive()) { frame = GetFrameForNode(aNode); if (!frame) { // No boxes to return return; } } if (!relativeToFrame) { aRv.Throw(NS_ERROR_DOM_NOT_FOUND_ERR); return; } if (!CheckFramesInSameTopLevelBrowsingContext(frame, relativeToFrame)) { aRv.Throw(NS_ERROR_DOM_NOT_FOUND_ERR); return; } // GetBoxRectForFrame can modify relativeToFrame so call it first. nsPoint relativeToTopLeft = GetBoxRectForFrame(&relativeToFrame, CSSBoxType::Border).TopLeft(); AccumulateQuadCallback callback(ownerDoc, aResult, relativeToFrame, relativeToTopLeft, aOptions.mBox); nsLayoutUtils::GetAllInFlowBoxes(frame, &callback); }
PRBool nsComboboxControlFrame::ShowList(nsPresContext* aPresContext, PRBool aShowList) { nsCOMPtr<nsIPresShell> shell = PresContext()->GetPresShell(); nsWeakFrame weakFrame(this); ShowPopup(aShowList); // might destroy us if (!weakFrame.IsAlive()) { return PR_FALSE; } mDroppedDown = aShowList; if (mDroppedDown) { // The listcontrol frame will call back to the nsComboboxControlFrame's // ListWasSelected which will stop the capture. mListControlFrame->AboutToDropDown(); mListControlFrame->CaptureMouseEvents(PR_TRUE); } // XXXbz so why do we need to flush here, exactly? shell->GetDocument()->FlushPendingNotifications(Flush_Layout); if (!weakFrame.IsAlive()) { return PR_FALSE; } nsIFrame* listFrame = do_QueryFrame(mListControlFrame); if (listFrame) { nsIView* view = listFrame->GetView(); NS_ASSERTION(view, "nsComboboxControlFrame view is null"); if (view) { nsIWidget* widget = view->GetWidget(); if (widget) widget->CaptureRollupEvents(this, mDroppedDown, mDroppedDown); } } return weakFrame.IsAlive(); }
//--------------------------------------------------------- // gets the content (an option) by index and then set it as // being selected or not selected //--------------------------------------------------------- NS_IMETHODIMP nsComboboxControlFrame::OnOptionSelected(PRInt32 aIndex, PRBool aSelected) { if (mDroppedDown) { nsISelectControlFrame *selectFrame = do_QueryFrame(mListControlFrame); if (selectFrame) { selectFrame->OnOptionSelected(aIndex, aSelected); } } else { if (aSelected) { nsAutoScriptBlocker blocker; RedisplayText(aIndex); } else { nsWeakFrame weakFrame(this); RedisplaySelectedText(); if (weakFrame.IsAlive()) { FireValueChangeEvent(); // Fire after old option is unselected } } } return NS_OK; }
void nsComboboxControlFrame::SetFocus(PRBool aOn, PRBool aRepaint) { nsWeakFrame weakFrame(this); if (aOn) { nsListControlFrame::ComboboxFocusSet(); mFocused = this; } else { mFocused = nsnull; if (mDroppedDown) { mListControlFrame->ComboboxFinish(mDisplayedIndex); // might destroy us if (!weakFrame.IsAlive()) { return; } } // May delete |this|. mListControlFrame->FireOnChange(); } if (!weakFrame.IsAlive()) { return; } // This is needed on a temporary basis. It causes the focus // rect to be drawn. This is much faster than ReResolvingStyle // Bug 32920 Invalidate(nsRect(0,0,mRect.width,mRect.height)); // Make sure the content area gets updated for where the dropdown was // This is only needed for embedding, the focus may go to // the chrome that is not part of the Gecko system (Bug 83493) // XXX this is rather inefficient nsIViewManager* vm = PresContext()->GetPresShell()->GetViewManager(); if (vm) { vm->UpdateAllViews(NS_VMREFRESH_NO_SYNC); } }
//IMPLEMENTING NS_IFORMCONTROLFRAME void nsTextControlFrame::SetFocus(PRBool aOn, PRBool aRepaint) { nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent()); NS_ASSERTION(txtCtrl, "Content not a text control element"); // Revoke the previous scroll event if one exists mScrollEvent.Revoke(); if (!aOn) { if (mUsePlaceholder) { PRInt32 textLength; GetTextLength(&textLength); if (!textLength) { nsWeakFrame weakFrame(this); txtCtrl->SetPlaceholderClass(PR_TRUE, PR_TRUE); if (!weakFrame.IsAlive()) { return; } } } return; } nsISelectionController* selCon = txtCtrl->GetSelectionController(); if (!selCon) return; if (mUsePlaceholder) { nsWeakFrame weakFrame(this); txtCtrl->SetPlaceholderClass(PR_FALSE, PR_TRUE); if (!weakFrame.IsAlive()) { return; } } InitFocusedValue(); nsCOMPtr<nsISelection> ourSel; selCon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(ourSel)); if (!ourSel) return; nsIPresShell* presShell = PresContext()->GetPresShell(); nsRefPtr<nsCaret> caret = presShell->GetCaret(); if (!caret) return; // Scroll the current selection into view nsISelection *caretSelection = caret->GetCaretDOMSelection(); const PRBool isFocusedRightNow = ourSel == caretSelection; if (!isFocusedRightNow) { // Don't scroll the current selection if we've been focused using the mouse. PRUint32 lastFocusMethod = 0; nsIDocument* doc = GetContent()->GetCurrentDoc(); if (doc) { nsIFocusManager* fm = nsFocusManager::GetFocusManager(); if (fm) { fm->GetLastFocusMethod(doc->GetWindow(), &lastFocusMethod); } } if (!(lastFocusMethod & nsIFocusManager::FLAG_BYMOUSE)) { nsRefPtr<ScrollOnFocusEvent> event = new ScrollOnFocusEvent(this); nsresult rv = NS_DispatchToCurrentThread(event); if (NS_SUCCEEDED(rv)) { mScrollEvent = event; } } } // tell the caret to use our selection caret->SetCaretDOMSelection(ourSel); // mutual-exclusion: the selection is either controlled by the // document or by the text input/area. Clear any selection in the // document since the focus is now on our independent selection. nsCOMPtr<nsISelectionController> selcon = do_QueryInterface(presShell); nsCOMPtr<nsISelection> docSel; selcon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(docSel)); if (!docSel) return; PRBool isCollapsed = PR_FALSE; docSel->GetIsCollapsed(&isCollapsed); if (!isCollapsed) docSel->RemoveAllRanges(); }
nsresult nsTextControlFrame::EnsureEditorInitialized() { // This method initializes our editor, if needed. // This code used to be called from CreateAnonymousContent(), but // when the editor set the initial string, it would trigger a // PresShell listener which called FlushPendingNotifications() // during frame construction. This was causing other form controls // to display wrong values. Additionally, calling this every time // a text frame control is instantiated means that we're effectively // instantiating the editor for all text fields, even if they // never get used. So, now this method is being called lazily only // when we actually need an editor. // Check if this method has been called already. // If so, just return early. if (mUseEditor) return NS_OK; NS_TIME_FUNCTION; nsIDocument* doc = mContent->GetCurrentDoc(); NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE); nsWeakFrame weakFrame(this); // Flush out content on our document. Have to do this, because script // blockers don't prevent the sink flushing out content and notifying in the // process, which can destroy frames. doc->FlushPendingNotifications(Flush_ContentAndNotify); NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_ERROR_FAILURE); // Make sure that editor init doesn't do things that would kill us off // (especially off the script blockers it'll create for its DOM mutations). nsAutoScriptBlocker scriptBlocker; // Time to mess with our security context... See comments in GetValue() // for why this is needed. nsCxPusher pusher; pusher.PushNull(); // Make sure that we try to focus the content even if the method fails class EnsureSetFocus { public: explicit EnsureSetFocus(nsTextControlFrame* aFrame) : mFrame(aFrame) {} ~EnsureSetFocus() { if (nsContentUtils::IsFocusedContent(mFrame->GetContent())) mFrame->SetFocus(PR_TRUE, PR_FALSE); } private: nsTextControlFrame *mFrame; }; EnsureSetFocus makeSureSetFocusHappens(this); #ifdef DEBUG // Make sure we are not being called again until we're finished. // If reentrancy happens, just pretend that we don't have an editor. const EditorInitializerEntryTracker tracker(*this); NS_ASSERTION(!tracker.EnteredMoreThanOnce(), "EnsureEditorInitialized has been called while a previous call was in progress"); #endif // Create an editor for the frame, if one doesn't already exist nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent()); NS_ASSERTION(txtCtrl, "Content not a text control element"); nsresult rv = txtCtrl->CreateEditor(); NS_ENSURE_SUCCESS(rv, rv); // Turn on mUseEditor so that subsequent calls will use the // editor. mUseEditor = PR_TRUE; // Set the selection to the beginning of the text field. SetSelectionEndPoints(0, 0); return NS_OK; }
nsresult nsTextControlFrame::UpdateValueDisplay(PRBool aNotify, PRBool aBeforeEditorInit, const nsAString *aValue) { if (!IsSingleLineTextControl()) // textareas don't use this return NS_OK; nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent()); NS_ASSERTION(txtCtrl, "Content not a text control element"); nsIContent* rootNode = txtCtrl->GetRootEditorNode(); NS_PRECONDITION(rootNode, "Must have a div content\n"); NS_PRECONDITION(!mUseEditor, "Do not call this after editor has been initialized"); NS_ASSERTION(!mUsePlaceholder || txtCtrl->GetPlaceholderNode(), "A placeholder div must exist"); nsIContent *textContent = rootNode->GetChildAt(0); if (!textContent) { // Set up a textnode with our value nsCOMPtr<nsIContent> textNode; nsresult rv = NS_NewTextNode(getter_AddRefs(textNode), mContent->NodeInfo()->NodeInfoManager()); NS_ENSURE_SUCCESS(rv, rv); NS_ASSERTION(textNode, "Must have textcontent!\n"); rootNode->AppendChildTo(textNode, aNotify); textContent = textNode; } NS_ENSURE_TRUE(textContent, NS_ERROR_UNEXPECTED); // Get the current value of the textfield from the content. nsAutoString value; if (aValue) { value = *aValue; } else { txtCtrl->GetTextEditorValue(value, PR_TRUE); } // Update the display of the placeholder value if needed. // We don't need to do this if we're about to initialize the // editor, since EnsureEditorInitialized takes care of this. if (mUsePlaceholder && !aBeforeEditorInit) { nsWeakFrame weakFrame(this); txtCtrl->SetPlaceholderClass(value.IsEmpty(), aNotify); NS_ENSURE_STATE(weakFrame.IsAlive()); } if (aBeforeEditorInit && value.IsEmpty()) { rootNode->RemoveChildAt(0, PR_TRUE); return NS_OK; } if (!value.IsEmpty() && IsPasswordTextControl()) { nsTextEditRules::FillBufWithPWChars(&value, value.Length()); } return textContent->SetText(value, aNotify); }
NS_IMETHODIMP nsSliderFrame::HandleEvent(nsPresContext* aPresContext, nsGUIEvent* aEvent, nsEventStatus* aEventStatus) { NS_ENSURE_ARG_POINTER(aEventStatus); if (nsEventStatus_eConsumeNoDefault == *aEventStatus) { return NS_OK; } nsIBox* scrollbarBox = GetScrollbar(); nsCOMPtr<nsIContent> scrollbar; scrollbar = GetContentOfBox(scrollbarBox); PRBool isHorizontal = IsHorizontal(); if (isDraggingThumb()) { switch (aEvent->message) { case NS_MOUSE_MOVE: { nsPoint eventPoint = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, this); if (mChange) { // We're in the process of moving the thumb to the mouse, // but the mouse just moved. Make sure to update our // destination point. mDestinationPoint = eventPoint; StopRepeat(); StartRepeat(); break; } nscoord pos = isHorizontal ? eventPoint.x : eventPoint.y; nsIFrame* thumbFrame = mFrames.FirstChild(); if (!thumbFrame) { return NS_OK; } // take our current position and subtract the start location pos -= mDragStart; PRBool isMouseOutsideThumb = PR_FALSE; if (gSnapMultiplier) { nsSize thumbSize = thumbFrame->GetSize(); if (isHorizontal) { // horizontal scrollbar - check if mouse is above or below thumb // XXXbz what about looking at the .y of the thumb's rect? Is that // always zero here? if (eventPoint.y < -gSnapMultiplier * thumbSize.height || eventPoint.y > thumbSize.height + gSnapMultiplier * thumbSize.height) isMouseOutsideThumb = PR_TRUE; } else { // vertical scrollbar - check if mouse is left or right of thumb if (eventPoint.x < -gSnapMultiplier * thumbSize.width || eventPoint.x > thumbSize.width + gSnapMultiplier * thumbSize.width) isMouseOutsideThumb = PR_TRUE; } } if (isMouseOutsideThumb) { SetCurrentThumbPosition(scrollbar, mThumbStart, PR_FALSE, PR_TRUE, PR_FALSE); return NS_OK; } // set it SetCurrentThumbPosition(scrollbar, pos, PR_FALSE, PR_TRUE, PR_TRUE); // with snapping } break; case NS_MOUSE_BUTTON_UP: if (static_cast<nsMouseEvent*>(aEvent)->button == nsMouseEvent::eLeftButton || (static_cast<nsMouseEvent*>(aEvent)->button == nsMouseEvent::eMiddleButton && gMiddlePref)) { // stop capturing AddListener(); DragThumb(PR_FALSE); if (mChange) { StopRepeat(); mChange = 0; } //we MUST call nsFrame HandleEvent for mouse ups to maintain the selection state and capture state. return nsFrame::HandleEvent(aPresContext, aEvent, aEventStatus); } } //return nsFrame::HandleEvent(aPresContext, aEvent, aEventStatus); return NS_OK; } else if ((aEvent->message == NS_MOUSE_BUTTON_DOWN && static_cast<nsMouseEvent*>(aEvent)->button == nsMouseEvent::eLeftButton && #ifdef XP_MACOSX // On Mac the option key inverts the scroll-to-here preference. (static_cast<nsMouseEvent*>(aEvent)->isAlt != GetScrollToClick())) || #else (static_cast<nsMouseEvent*>(aEvent)->isShift != GetScrollToClick())) || #endif (gMiddlePref && aEvent->message == NS_MOUSE_BUTTON_DOWN && static_cast<nsMouseEvent*>(aEvent)->button == nsMouseEvent::eMiddleButton)) { nsPoint eventPoint = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, this); nscoord pos = isHorizontal ? eventPoint.x : eventPoint.y; // adjust so that the middle of the thumb is placed under the click nsIFrame* thumbFrame = mFrames.FirstChild(); if (!thumbFrame) { return NS_OK; } nsSize thumbSize = thumbFrame->GetSize(); nscoord thumbLength = isHorizontal ? thumbSize.width : thumbSize.height; // set it nsWeakFrame weakFrame(this); // should aMaySnap be PR_TRUE here? SetCurrentThumbPosition(scrollbar, pos - thumbLength/2, PR_FALSE, PR_FALSE, PR_FALSE); NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK); DragThumb(PR_TRUE); if (isHorizontal) mThumbStart = thumbFrame->GetPosition().x; else mThumbStart = thumbFrame->GetPosition().y; mDragStart = pos - mThumbStart; } // XXX hack until handle release is actually called in nsframe. // if (aEvent->message == NS_MOUSE_EXIT_SYNTH || aEvent->message == NS_MOUSE_RIGHT_BUTTON_UP || aEvent->message == NS_MOUSE_LEFT_BUTTON_UP) // HandleRelease(aPresContext, aEvent, aEventStatus); if (aEvent->message == NS_MOUSE_EXIT_SYNTH && mChange) HandleRelease(aPresContext, aEvent, aEventStatus); return nsFrame::HandleEvent(aPresContext, aEvent, aEventStatus); }
NS_IMETHODIMP nsResizerFrame::HandleEvent(nsPresContext* aPresContext, nsGUIEvent* aEvent, nsEventStatus* aEventStatus) { NS_ENSURE_ARG_POINTER(aEventStatus); if (nsEventStatus_eConsumeNoDefault == *aEventStatus) { return NS_OK; } nsWeakFrame weakFrame(this); PRBool doDefault = PR_TRUE; switch (aEvent->message) { case NS_MOUSE_BUTTON_DOWN: { if (aEvent->eventStructType == NS_MOUSE_EVENT && static_cast<nsMouseEvent*>(aEvent)->button == nsMouseEvent::eLeftButton) { nsCOMPtr<nsIBaseWindow> window; nsIPresShell* presShell = aPresContext->GetPresShell(); nsIContent* contentToResize = GetContentToResize(presShell, getter_AddRefs(window)); if (contentToResize) { nsIFrame* frameToResize = contentToResize->GetPrimaryFrame(); if (!frameToResize) break; mMouseDownRect = frameToResize->GetScreenRect(); } else { // ask the widget implementation to begin a resize drag if it can Direction direction = GetDirection(); nsresult rv = aEvent->widget->BeginResizeDrag(aEvent, direction.mHorizontal, direction.mVertical); if (rv == NS_ERROR_NOT_IMPLEMENTED && window) { // if there's no native resize support, we need to do window // resizing ourselves window->GetPositionAndSize(&mMouseDownRect.x, &mMouseDownRect.y, &mMouseDownRect.width, &mMouseDownRect.height); } else { // for native drags, don't set the fields below doDefault = PR_FALSE; break; } } // we're tracking mTrackingMouseMove = PR_TRUE; // remember current mouse coordinates mMouseDownPoint = aEvent->refPoint + aEvent->widget->WidgetToScreenOffset(); nsIPresShell::SetCapturingContent(GetContent(), CAPTURE_IGNOREALLOWED); doDefault = PR_FALSE; } } break; case NS_MOUSE_BUTTON_UP: { if (mTrackingMouseMove && aEvent->eventStructType == NS_MOUSE_EVENT && static_cast<nsMouseEvent*>(aEvent)->button == nsMouseEvent::eLeftButton) { // we're done tracking. mTrackingMouseMove = PR_FALSE; nsIPresShell::SetCapturingContent(nsnull, 0); doDefault = PR_FALSE; } } break; case NS_MOUSE_MOVE: { if (mTrackingMouseMove) { nsCOMPtr<nsIBaseWindow> window; nsIPresShell* presShell = aPresContext->GetPresShell(); nsCOMPtr<nsIContent> contentToResize = GetContentToResize(presShell, getter_AddRefs(window)); // check if the returned content really is a menupopup nsMenuPopupFrame* menuPopupFrame = nsnull; if (contentToResize) { nsIFrame* frameToResize = contentToResize->GetPrimaryFrame(); if (frameToResize && frameToResize->GetType() == nsGkAtoms::menuPopupFrame) { menuPopupFrame = static_cast<nsMenuPopupFrame *>(frameToResize); } } // both MouseMove and direction are negative when pointing to the // top and left, and positive when pointing to the bottom and right // retrieve the offset of the mousemove event relative to the mousedown. // The difference is how much the resize needs to be nsIntPoint screenPoint(aEvent->refPoint + aEvent->widget->WidgetToScreenOffset()); nsIntPoint mouseMove(screenPoint - mMouseDownPoint); // what direction should we go in? For content resizing, always use // 'bottomend'. For other windows, check the dir attribute. Direction direction; if (window || menuPopupFrame) { direction = GetDirection(); if (menuPopupFrame) { menuPopupFrame->CanAdjustEdges( (direction.mHorizontal == -1) ? NS_SIDE_LEFT : NS_SIDE_RIGHT, (direction.mVertical == -1) ? NS_SIDE_TOP : NS_SIDE_BOTTOM, mouseMove); } } else if (contentToResize) { direction.mHorizontal = GetStyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL ? -1 : 1; direction.mVertical = 1; } else { break; // don't do anything if there's nothing to resize } nsIntRect rect = mMouseDownRect; AdjustDimensions(&rect.x, &rect.width, mouseMove.x, direction.mHorizontal); AdjustDimensions(&rect.y, &rect.height, mouseMove.y, direction.mVertical); // Don't allow resizing a window or a popup past the edge of the screen, // so adjust the rectangle to fit within the available screen area. if (window) { nsCOMPtr<nsIScreen> screen; nsCOMPtr<nsIScreenManager> sm(do_GetService("@mozilla.org/gfx/screenmanager;1")); if (sm) { nsIntRect frameRect = GetScreenRect(); sm->ScreenForRect(frameRect.x, frameRect.y, 1, 1, getter_AddRefs(screen)); if (screen) { nsIntRect screenRect; screen->GetRect(&screenRect.x, &screenRect.y, &screenRect.width, &screenRect.height); rect.IntersectRect(rect, screenRect); } } } else if (menuPopupFrame) { nsPoint framePoint = menuPopupFrame->GetScreenRectInAppUnits().TopLeft(); nsIFrame* rootFrame = aPresContext->PresShell()->FrameManager()->GetRootFrame(); nsRect rootScreenRect = rootFrame->GetScreenRectInAppUnits(); nsRect screenRect = menuPopupFrame->GetConstraintRect(framePoint, rootScreenRect); // round using ToInsidePixels as it's better to be a pixel too small // than be too large. If the popup is too large it could get flipped // to the opposite side of the anchor point while resizing. nsIntRect screenRectPixels = screenRect.ToInsidePixels(aPresContext->AppUnitsPerDevPixel()); rect.IntersectRect(rect, screenRectPixels); } if (contentToResize) { nsIntRect cssRect = rect.ToAppUnits(aPresContext->AppUnitsPerDevPixel()) .ToInsidePixels(nsPresContext::AppUnitsPerCSSPixel()); nsAutoString widthstr, heightstr; widthstr.AppendInt(cssRect.width); heightstr.AppendInt(cssRect.height); // for XUL elements, just set the width and height attributes. For // other elements, set style.width and style.height if (contentToResize->IsXUL()) { nsIntRect oldRect; nsWeakFrame weakFrame(menuPopupFrame); if (menuPopupFrame) { nsCOMPtr<nsIWidget> widget; menuPopupFrame->GetWidget(getter_AddRefs(widget)); if (widget) widget->GetScreenBounds(oldRect); } contentToResize->SetAttr(kNameSpaceID_None, nsGkAtoms::width, widthstr, PR_TRUE); contentToResize->SetAttr(kNameSpaceID_None, nsGkAtoms::height, heightstr, PR_TRUE); if (weakFrame.IsAlive() && (oldRect.x != rect.x || oldRect.y != rect.y)) { // XXX This might go very wrong, since menu popups may add // offsets (e.g. from margins) to this position, so the popup's // widget won't end up at the desired position. menuPopupFrame->MoveTo(rect.x, rect.y, PR_TRUE); } } else { nsCOMPtr<nsIDOMElementCSSInlineStyle> inlineStyleContent = do_QueryInterface(contentToResize); if (inlineStyleContent) { widthstr += NS_LITERAL_STRING("px"); heightstr += NS_LITERAL_STRING("px"); nsCOMPtr<nsIDOMCSSStyleDeclaration> decl; inlineStyleContent->GetStyle(getter_AddRefs(decl)); decl->SetProperty(NS_LITERAL_STRING("width"), widthstr, EmptyString()); decl->SetProperty(NS_LITERAL_STRING("height"), heightstr, EmptyString()); } } } else { window->SetPositionAndSize(rect.x, rect.y, rect.width, rect.height, PR_TRUE); // do the repaint. } doDefault = PR_FALSE; } } break; case NS_MOUSE_CLICK: if (NS_IS_MOUSE_LEFT_CLICK(aEvent)) { MouseClicked(aPresContext, aEvent); } break; } if (!doDefault) *aEventStatus = nsEventStatus_eConsumeNoDefault; if (doDefault && weakFrame.IsAlive()) return nsTitleBarFrame::HandleEvent(aPresContext, aEvent, aEventStatus); else return NS_OK; }
NS_IMETHODIMP nsMenuFrame::HandleEvent(nsPresContext* aPresContext, nsGUIEvent* aEvent, nsEventStatus* aEventStatus) { NS_ENSURE_ARG_POINTER(aEventStatus); if (nsEventStatus_eConsumeNoDefault == *aEventStatus || (mMenuParent && mMenuParent->IsMenuLocked())) { return NS_OK; } nsWeakFrame weakFrame(this); if (*aEventStatus == nsEventStatus_eIgnore) *aEventStatus = nsEventStatus_eConsumeDoDefault; PRBool onmenu = IsOnMenu(); if (aEvent->message == NS_KEY_PRESS && !IsDisabled()) { nsKeyEvent* keyEvent = (nsKeyEvent*)aEvent; PRUint32 keyCode = keyEvent->keyCode; #ifdef XP_MACOSX // On mac, open menulist on either up/down arrow or space (w/o Cmd pressed) if (!IsOpen() && ((keyEvent->charCode == NS_VK_SPACE && !keyEvent->isMeta) || (keyCode == NS_VK_UP || keyCode == NS_VK_DOWN))) { *aEventStatus = nsEventStatus_eConsumeNoDefault; OpenMenu(PR_FALSE); } #else // On other platforms, toggle menulist on unmodified F4 or Alt arrow if ((keyCode == NS_VK_F4 && !keyEvent->isAlt) || ((keyCode == NS_VK_UP || keyCode == NS_VK_DOWN) && keyEvent->isAlt)) { *aEventStatus = nsEventStatus_eConsumeNoDefault; ToggleMenuState(); } #endif } else if (aEvent->eventStructType == NS_MOUSE_EVENT && aEvent->message == NS_MOUSE_BUTTON_DOWN && static_cast<nsMouseEvent*>(aEvent)->button == nsMouseEvent::eLeftButton && !IsDisabled() && IsMenu()) { // The menu item was selected. Bring up the menu. // We have children. // Don't prevent the default action here, since that will also cancel // potential drag starts. if (!mMenuParent || mMenuParent->IsMenuBar()) { ToggleMenuState(); } else { if (!IsOpen()) { OpenMenu(PR_FALSE); } } } else if ( #ifndef NSCONTEXTMENUISMOUSEUP (aEvent->eventStructType == NS_MOUSE_EVENT && aEvent->message == NS_MOUSE_BUTTON_UP && static_cast<nsMouseEvent*>(aEvent)->button == nsMouseEvent::eRightButton) && #else aEvent->message == NS_CONTEXTMENU && #endif onmenu && !IsMenu() && !IsDisabled()) { // if this menu is a context menu it accepts right-clicks...fire away! // Make sure we cancel default processing of the context menu event so // that it doesn't bubble and get seen again by the popuplistener and show // another context menu. // // Furthermore (there's always more, isn't there?), on some platforms (win32 // being one of them) we get the context menu event on a mouse up while // on others we get it on a mouse down. For the ones where we get it on a // mouse down, we must continue listening for the right button up event to // dismiss the menu. if (mMenuParent->IsContextMenu()) { *aEventStatus = nsEventStatus_eConsumeNoDefault; Execute(aEvent); } } else if (aEvent->eventStructType == NS_MOUSE_EVENT && aEvent->message == NS_MOUSE_BUTTON_UP && static_cast<nsMouseEvent*>(aEvent)->button == nsMouseEvent::eLeftButton && !IsMenu() && !IsDisabled()) { // Execute the execute event handler. *aEventStatus = nsEventStatus_eConsumeNoDefault; Execute(aEvent); } else if (aEvent->message == NS_MOUSE_EXIT_SYNTH) { // Kill our timer if one is active. if (mOpenTimer) { mOpenTimer->Cancel(); mOpenTimer = nsnull; } // Deactivate the menu. if (mMenuParent) { PRBool onmenubar = mMenuParent->IsMenuBar(); if (!(onmenubar && mMenuParent->IsActive())) { if (IsMenu() && !onmenubar && IsOpen()) { // Submenus don't get closed up immediately. } else if (this == mMenuParent->GetCurrentMenuItem()) { mMenuParent->ChangeMenuItem(nsnull, PR_FALSE); } } } } else if (aEvent->message == NS_MOUSE_MOVE && (onmenu || (mMenuParent && mMenuParent->IsMenuBar()))) { if (gEatMouseMove) { gEatMouseMove = PR_FALSE; return NS_OK; } // Let the menu parent know we're the new item. mMenuParent->ChangeMenuItem(this, PR_FALSE); NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK); NS_ENSURE_TRUE(mMenuParent, NS_OK); // we need to check if we really became the current menu // item or not nsMenuFrame *realCurrentItem = mMenuParent->GetCurrentMenuItem(); if (realCurrentItem != this) { // we didn't (presumably because a context menu was active) return NS_OK; } // Hovering over a menu in a popup should open it without a need for a click. // A timer is used so that it doesn't open if the user moves the mouse quickly // past the menu. This conditional check ensures that only menus have this // behaviour if (!IsDisabled() && IsMenu() && !IsOpen() && !mOpenTimer && !mMenuParent->IsMenuBar()) { PRInt32 menuDelay = 300; // ms nsCOMPtr<nsILookAndFeel> lookAndFeel(do_GetService(kLookAndFeelCID)); if (lookAndFeel) lookAndFeel->GetMetric(nsILookAndFeel::eMetric_SubmenuDelay, menuDelay); // We're a menu, we're built, we're closed, and no timer has been kicked off. mOpenTimer = do_CreateInstance("@mozilla.org/timer;1"); mOpenTimer->InitWithCallback(mTimerMediator, menuDelay, nsITimer::TYPE_ONE_SHOT); } } return NS_OK; }
void nsMenuFrame::BuildAcceleratorText() { nsAutoString accelText; if ((GetStateBits() & NS_STATE_ACCELTEXT_IS_DERIVED) == 0) { mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::acceltext, accelText); if (!accelText.IsEmpty()) return; } // accelText is definitely empty here. // Now we're going to compute the accelerator text, so remember that we did. AddStateBits(NS_STATE_ACCELTEXT_IS_DERIVED); // If anything below fails, just leave the accelerator text blank. nsWeakFrame weakFrame(this); mContent->UnsetAttr(kNameSpaceID_None, nsGkAtoms::acceltext, PR_FALSE); ENSURE_TRUE(weakFrame.IsAlive()); // See if we have a key node and use that instead. nsAutoString keyValue; mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::key, keyValue); if (keyValue.IsEmpty()) return; // Turn the document into a DOM document so we can use getElementById nsIDocument *document = mContent->GetDocument(); if (!document) return; nsIContent *keyElement = document->GetElementById(keyValue); if (!keyElement) { #ifdef DEBUG nsAutoString label; mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::label, label); nsAutoString msg = NS_LITERAL_STRING("Key '") + keyValue + NS_LITERAL_STRING("' of menu item '") + label + NS_LITERAL_STRING("' could not be found"); NS_WARNING(NS_ConvertUTF16toUTF8(msg).get()); #endif return; } // get the string to display as accelerator text // check the key element's attributes in this order: // |keytext|, |key|, |keycode| nsAutoString accelString; keyElement->GetAttr(kNameSpaceID_None, nsGkAtoms::keytext, accelString); if (accelString.IsEmpty()) { keyElement->GetAttr(kNameSpaceID_None, nsGkAtoms::key, accelString); if (!accelString.IsEmpty()) { ToUpperCase(accelString); } else { nsAutoString keyCode; keyElement->GetAttr(kNameSpaceID_None, nsGkAtoms::keycode, keyCode); ToUpperCase(keyCode); nsresult rv; nsCOMPtr<nsIStringBundleService> bundleService = mozilla::services::GetStringBundleService(); if (bundleService) { nsCOMPtr<nsIStringBundle> bundle; rv = bundleService->CreateBundle("chrome://global/locale/keys.properties", getter_AddRefs(bundle)); if (NS_SUCCEEDED(rv) && bundle) { nsXPIDLString keyName; rv = bundle->GetStringFromName(keyCode.get(), getter_Copies(keyName)); if (keyName) accelString = keyName; } } // nothing usable found, bail if (accelString.IsEmpty()) return; } } static PRInt32 accelKey = 0; if (!accelKey) { // Compiled-in defaults, in case we can't get LookAndFeel -- // command for mac, control for all other platforms. #ifdef XP_MACOSX accelKey = nsIDOMKeyEvent::DOM_VK_META; #else accelKey = nsIDOMKeyEvent::DOM_VK_CONTROL; #endif // Get the accelerator key value from prefs, overriding the default: accelKey = nsContentUtils::GetIntPref("ui.key.accelKey", accelKey); } nsAutoString modifiers; keyElement->GetAttr(kNameSpaceID_None, nsGkAtoms::modifiers, modifiers); char* str = ToNewCString(modifiers); char* newStr; char* token = nsCRT::strtok(str, ", \t", &newStr); while (token) { if (PL_strcmp(token, "shift") == 0) accelText += *gShiftText; else if (PL_strcmp(token, "alt") == 0) accelText += *gAltText; else if (PL_strcmp(token, "meta") == 0) accelText += *gMetaText; else if (PL_strcmp(token, "control") == 0) accelText += *gControlText; else if (PL_strcmp(token, "accel") == 0) { switch (accelKey) { case nsIDOMKeyEvent::DOM_VK_META: accelText += *gMetaText; break; case nsIDOMKeyEvent::DOM_VK_ALT: accelText += *gAltText; break; case nsIDOMKeyEvent::DOM_VK_CONTROL: default: accelText += *gControlText; break; } } accelText += *gModifierSeparator; token = nsCRT::strtok(newStr, ", \t", &newStr); } nsMemory::Free(str); accelText += accelString; mContent->SetAttr(kNameSpaceID_None, nsGkAtoms::acceltext, accelText, PR_FALSE); }
PRBool nsScrollbarButtonFrame::HandleButtonPress(nsPresContext* aPresContext, nsGUIEvent* aEvent, nsEventStatus* aEventStatus) { // Get the desired action for the scrollbar button. nsILookAndFeel::nsMetricID tmpAction; if (aEvent->eventStructType == NS_MOUSE_EVENT && aEvent->message == NS_MOUSE_BUTTON_DOWN) { PRUint16 button = static_cast<nsMouseEvent*>(aEvent)->button; if (button == nsMouseEvent::eLeftButton) { tmpAction = nsILookAndFeel::eMetric_ScrollButtonLeftMouseButtonAction; } else if (button == nsMouseEvent::eMiddleButton) { tmpAction = nsILookAndFeel::eMetric_ScrollButtonMiddleMouseButtonAction; } else if (button == nsMouseEvent::eRightButton) { tmpAction = nsILookAndFeel::eMetric_ScrollButtonRightMouseButtonAction; } else { return PR_FALSE; } } else { return PR_FALSE; } // Get the button action metric from the pres. shell. PRInt32 pressedButtonAction; if (NS_FAILED(aPresContext->LookAndFeel()->GetMetric(tmpAction, pressedButtonAction))) return PR_FALSE; // get the scrollbar control nsIFrame* scrollbar; GetParentWithTag(nsGkAtoms::scrollbar, this, scrollbar); if (scrollbar == nsnull) return PR_FALSE; // get the scrollbars content node nsIContent* content = scrollbar->GetContent(); static nsIContent::AttrValuesArray strings[] = { &nsGkAtoms::increment, &nsGkAtoms::decrement, nsnull }; PRInt32 index = mContent->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::type, strings, eCaseMatters); PRInt32 direction; if (index == 0) direction = 1; else if (index == 1) direction = -1; else return PR_FALSE; // Whether or not to repeat the click action. PRBool repeat = PR_TRUE; // Use smooth scrolling by default. PRBool smoothScroll = PR_TRUE; switch (pressedButtonAction) { case 0: mIncrement = direction * nsSliderFrame::GetIncrement(content); break; case 1: mIncrement = direction * nsSliderFrame::GetPageIncrement(content); break; case 2: if (direction == -1) mIncrement = -nsSliderFrame::GetCurrentPosition(content); else mIncrement = nsSliderFrame::GetMaxPosition(content) - nsSliderFrame::GetCurrentPosition(content); // Don't repeat or use smooth scrolling if scrolling to beginning or end // of a page. repeat = smoothScroll = PR_FALSE; break; case 3: default: // We were told to ignore this click, or someone assigned a non-standard // value to the button's action. return PR_FALSE; } // set this attribute so we can style it later nsWeakFrame weakFrame(this); mContent->SetAttr(kNameSpaceID_None, nsGkAtoms::active, NS_LITERAL_STRING("true"), PR_TRUE); if (weakFrame.IsAlive()) { DoButtonAction(smoothScroll); } if (repeat) StartRepeat(); return PR_TRUE; }
NS_IMETHODIMP nsPopupSetFrame::ShowPopup(nsIContent* aElementContent, nsIContent* aPopupContent, PRInt32 aXPos, PRInt32 aYPos, const nsString& aPopupType, const nsString& anAnchorAlignment, const nsString& aPopupAlignment) { NS_ASSERTION(aElementContent != aPopupContent, "self referential popup"); if (!MayOpenPopup(this)) return NS_OK; nsWeakFrame weakFrame(this); // First fire the popupshowing event. if (!OnCreate(aXPos, aYPos, aPopupContent) || !weakFrame.IsAlive()) return NS_OK; // See if we already have an entry in our list. We must create a new one on a miss. nsPopupFrameList* entry = nsnull; if (mPopupList) entry = mPopupList->GetEntry(aPopupContent); if (!entry) { entry = new nsPopupFrameList(aPopupContent, mPopupList); if (!entry) return NS_ERROR_OUT_OF_MEMORY; mPopupList = entry; } // Cache the element content we're supposed to sync to entry->mPopupType = aPopupType; entry->mElementContent = aElementContent; entry->mPopupAlign = aPopupAlignment; entry->mPopupAnchor = anAnchorAlignment; entry->mXPos = aXPos; entry->mYPos = aYPos; // If a frame exists already, go ahead and use it. mPresContext->PresShell()->GetPrimaryFrameFor(aPopupContent, &entry->mPopupFrame); #ifdef DEBUG_PINK printf("X Pos: %d\n", mXPos); printf("Y Pos: %d\n", mYPos); #endif // Generate the popup. entry->mCreateHandlerSucceeded = PR_TRUE; entry->mIsOpen = PR_TRUE; // This may destroy or change entry->mPopupFrame or remove the entry from // mPopupList. |this| may also get deleted. MarkAsGenerated(aPopupContent); if (!weakFrame.IsAlive()) { return NS_OK; } nsPopupFrameList* newEntry = mPopupList ? mPopupList->GetEntry(aPopupContent) : nsnull; if (!newEntry || newEntry != entry) { NS_WARNING("The popup entry for aPopupContent has changed!"); return NS_OK; } // determine if this menu is a context menu and flag it nsIMenuParent* childPopup = nsnull; if (entry->mPopupFrame) CallQueryInterface(entry->mPopupFrame, &childPopup); if ( childPopup && aPopupType.EqualsLiteral("context") ) childPopup->SetIsContextMenu(PR_TRUE); // Now open the popup. OpenPopup(entry, PR_TRUE); if (!weakFrame.IsAlive()) { return NS_OK; } // Now fire the popupshown event. OnCreated(aXPos, aYPos, aPopupContent); return NS_OK; }