FReply FTextEditHelper::OnMouseButtonUp( const FGeometry& MyGeometry, const FPointerEvent& InMouseEvent, const TSharedRef< ITextEditorWidget >& TextEditor ) { FReply Reply = FReply::Unhandled(); // The mouse must have been captured by either left or right button down before we'll process mouse ups if( TextEditor->GetWidget()->HasMouseCapture() ) { if( InMouseEvent.GetEffectingButton() == EKeys::LeftMouseButton && TextEditor->IsDragSelecting() ) { // No longer drag-selecting TextEditor->EndDragSelection(); // If we received keyboard focus on this click, then we'll want to select all of the text // when the user releases the mouse button, unless the user actually dragged the mouse // while holding the button down, in which case they've already selected some text and // we'll leave things alone! if( TextEditor->WasFocusedByLastMouseDown() ) { if( !TextEditor->HasDragSelectedSinceFocused() ) { if( TextEditor->SelectAllTextWhenFocused() ) { // Move the cursor to the end of the string TextEditor->JumpTo(ETextLocation::EndOfDocument, ECursorAction::MoveCursor); // User wasn't dragging the mouse, so go ahead and select all of the text now // that we've become focused TextEditor->SelectAllText(); // @todo Slate: In this state, the caret should actually stay hidden (until the user interacts again), and we should not move the caret } } TextEditor->SetWasFocusedByLastMouseDown( false ); } // Release mouse capture Reply = FReply::Handled(); Reply.ReleaseMouseCapture(); } else if( InMouseEvent.GetEffectingButton() == EKeys::RightMouseButton ) { if ( MyGeometry.IsUnderLocation( InMouseEvent.GetScreenSpacePosition() ) ) { // Right clicked, so summon a context menu if the cursor is within the widget TextEditor->SummonContextMenu( InMouseEvent.GetScreenSpacePosition() ); } // Release mouse capture Reply = FReply::Handled(); Reply.ReleaseMouseCapture(); } } return Reply; }
FReply SButton::OnMouseButtonUp( const FGeometry& MyGeometry, const FPointerEvent& MouseEvent ) { FReply Reply = FReply::Unhandled(); const bool bMustBePressed = ClickMethod == EButtonClickMethod::DownAndUp; const bool bMeetsPressedRequirements = (!bMustBePressed || (bIsPressed && bMustBePressed)); if (bMeetsPressedRequirements && IsEnabled() && ( MouseEvent.GetEffectingButton() == EKeys::LeftMouseButton || MouseEvent.IsTouchEvent() ) ) { Release(); if( ClickMethod == EButtonClickMethod::MouseDown ) { // NOTE: If we're configured to click on mouse-down/precise-tap, then we never capture the mouse thus // may never receive an OnMouseButtonUp() call. We make sure that our bIsPressed // state is reset by overriding OnMouseLeave(). } else { bool bEventOverButton = IsHovered(); if (!bEventOverButton && MouseEvent.IsTouchEvent()) { bEventOverButton = MyGeometry.IsUnderLocation(MouseEvent.GetScreenSpacePosition()); } if (bEventOverButton) { // If we asked for a precise tap, all we need is for the user to have not moved their pointer very far. const bool bTriggerForTouchEvent = IsPreciseTapOrClick(MouseEvent); // If we were asked to allow the button to be clicked on mouse up, regardless of whether the user // pressed the button down first, then we'll allow the click to proceed without an active capture const bool bTriggerForMouseEvent = ( ClickMethod == EButtonClickMethod::MouseUp || HasMouseCapture() ); if( (bTriggerForTouchEvent || bTriggerForMouseEvent) && OnClicked.IsBound() == true ) { Reply = OnClicked.Execute(); } } } //If the user of the button didn't handle this click, then the button's //default behavior handles it. if ( Reply.IsEventHandled() == false ) { Reply = FReply::Handled(); } //If the user hasn't requested a new mouse captor and the button still has mouse capture, //then the default behavior of the button is to release mouse capture. if (Reply.GetMouseCaptor().IsValid() == false && HasMouseCapture()) { Reply.ReleaseMouseCapture(); } } Invalidate(EInvalidateWidget::Layout); return Reply; }
FReply FWebBrowserViewport::OnMouseButtonUp(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) { // Release mouse capture when left button released FReply Reply = WebBrowserWindow->OnMouseButtonUp(MyGeometry, MouseEvent); if (MouseEvent.GetEffectingButton() == EKeys::LeftMouseButton) { return Reply.ReleaseMouseCapture(); } return Reply; }
FReply SPaperEditorViewport::OnMouseButtonUp(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) { // Did the user move the cursor sufficiently far, or is it in a dead zone? // In Dead zone - implies actions like summoning context menus and general clicking. // Out of Dead Zone - implies dragging actions like moving nodes and marquee selection. const bool bCursorInDeadZone = TotalMouseDelta <= FSlateApplication::Get().GetDragTriggerDistance(); if (MouseEvent.GetEffectingButton() == EKeys::RightMouseButton) { FReply ReplyState = FReply::Handled(); if (HasMouseCapture()) { FSlateRect ThisPanelScreenSpaceRect = MyGeometry.GetClippingRect(); const FVector2D ScreenSpaceCursorPos = MyGeometry.LocalToAbsolute( GraphCoordToPanelCoord( SoftwareCursorPosition ) ); FIntPoint BestPositionInViewport( FMath::RoundToInt( FMath::Clamp( ScreenSpaceCursorPos.X, ThisPanelScreenSpaceRect.Left, ThisPanelScreenSpaceRect.Right ) ), FMath::RoundToInt( FMath::Clamp( ScreenSpaceCursorPos.Y, ThisPanelScreenSpaceRect.Top, ThisPanelScreenSpaceRect.Bottom ) ) ); if (!bCursorInDeadZone) { ReplyState.SetMousePos(BestPositionInViewport); } } TSharedPtr<SWidget> WidgetToFocus; if (bCursorInDeadZone) { //WidgetToFocus = OnSummonContextMenu(MyGeometry, MouseEvent); } bShowSoftwareCursor = false; bIsPanning = false; return (WidgetToFocus.IsValid()) ? ReplyState.ReleaseMouseCapture().SetUserFocus(WidgetToFocus.ToSharedRef(), EFocusCause::SetDirectly) : ReplyState.ReleaseMouseCapture(); } else if (MouseEvent.GetEffectingButton() == EKeys::LeftMouseButton) { if (OnHandleLeftMouseRelease(MyGeometry, MouseEvent)) { } else if (bCursorInDeadZone) { //@TODO: Move to selection manager // if ( NodeUnderMousePtr.IsValid() ) // { // // We clicked on a node! // TSharedRef<SNode> NodeWidgetUnderMouse = NodeUnderMousePtr.Pin().ToSharedRef(); // // SelectionManager.ClickedOnNode(NodeWidgetUnderMouse->GetObjectBeingDisplayed(), MouseEvent); // // // We're done interacting with this node. // NodeUnderMousePtr.Reset(); // } // else if (HasMouseCapture()) { // We clicked on the panel background //@TODO: There isn't a marquee operation for clear, need to signal to remove existing sets too! //Marquee.End(); //OnSelectionChanged.ExecuteIfBound(Marquee, false); } } else if (Marquee.IsValid()) { //ApplyMarqueeSelection(Marquee, SelectionManager.SelectedNodes, SelectionManager.SelectedNodes); //SelectionManager.OnSelectionChanged.ExecuteIfBound(SelectionManager.SelectedNodes); OnSelectionChanged.ExecuteIfBound(Marquee, true); } // The existing marquee operation ended; reset it. Marquee = FMarqueeOperation(); if (bIsPanning) { // We have released the left mouse button. But we're still panning // (i.e. RIGHT MOUSE is down), so we want to hold on to capturing mouse input. return FReply::Handled(); } else { // We aren't panning, so we can release the mouse capture. return FReply::Handled().ReleaseMouseCapture(); } } return FReply::Unhandled(); }