FReply FSceneViewport::OnMouseButtonUp( const FGeometry& InGeometry, const FPointerEvent& InMouseEvent ) { // Start a new reply state CurrentReplyState = FReply::Handled(); KeyStateMap.Add( InMouseEvent.GetEffectingButton(), false ); UpdateModifierKeys( InMouseEvent ); UpdateCachedMousePos( InGeometry, InMouseEvent ); UpdateCachedGeometry(InGeometry); // Switch to the viewport clients world before processing input FScopedConditionalWorldSwitcher WorldSwitcher( ViewportClient ); bool bCursorVisible = true; bool bReleaseMouse = true; if( ViewportClient && GetSizeXY() != FIntPoint::ZeroValue ) { if (!ViewportClient->InputKey(this, InMouseEvent.GetUserIndex(), InMouseEvent.GetEffectingButton(), IE_Released)) { CurrentReplyState = FReply::Unhandled(); } bCursorVisible = ViewportClient->GetCursor(this, GetMouseX(), GetMouseY()) != EMouseCursor::None; bReleaseMouse = bCursorVisible || ViewportClient->CaptureMouseOnClick() == EMouseCaptureMode::CaptureDuringMouseDown || ( ViewportClient->CaptureMouseOnClick() == EMouseCaptureMode::CaptureDuringRightMouseDown && InMouseEvent.GetEffectingButton() == EKeys::RightMouseButton ); } if (!((FApp::IsGame() && !GIsEditor) || bIsPlayInEditorViewport) || bReleaseMouse) { // On mouse up outside of the game (editor viewport) or if the cursor is visible in game, we should make sure the mouse is no longer captured // as long as the left or right mouse buttons are not still down if( !InMouseEvent.IsMouseButtonDown( EKeys::RightMouseButton ) && !InMouseEvent.IsMouseButtonDown( EKeys::LeftMouseButton )) { if( bCursorHiddenDueToCapture ) { bCursorHiddenDueToCapture = false; CurrentReplyState.SetMousePos( MousePosBeforeHiddenDueToCapture ); MousePosBeforeHiddenDueToCapture = FIntPoint( -1, -1 ); } CurrentReplyState.ReleaseMouseCapture(); if (bCursorVisible) { CurrentReplyState.ReleaseMouseLock(); } } } return CurrentReplyState; }
FReply FSceneViewport::OnMouseButtonDown( const FGeometry& InGeometry, const FPointerEvent& InMouseEvent ) { // Start a new reply state // Prevent throttling when interacting with the viewport so we can move around in it CurrentReplyState = FReply::Handled().PreventThrottling(); KeyStateMap.Add(InMouseEvent.GetEffectingButton(), true); UpdateModifierKeys( InMouseEvent ); UpdateCachedMousePos( InGeometry, InMouseEvent ); UpdateCachedGeometry(InGeometry); // Switch to the viewport clients world before processing input FScopedConditionalWorldSwitcher WorldSwitcher( ViewportClient ); if( ViewportClient && GetSizeXY() != FIntPoint::ZeroValue ) { // If we're obtaining focus, we have to copy the modifier key states prior to processing this mouse button event, as this is the only point at which the mouse down // event is processed when focus initially changes and the modifier keys need to be in-place to detect any unique drag-like events. if ( !HasFocus() ) { FModifierKeysState KeysState = FSlateApplication::Get().GetModifierKeys(); ApplyModifierKeys( KeysState ); } // Process the mouse event if( !ViewportClient->InputKey( this, 0, InMouseEvent.GetEffectingButton(), IE_Pressed ) ) { CurrentReplyState = FReply::Unhandled(); } if (ViewportClient->CaptureMouseOnClick() != EMouseCaptureMode::NoCapture && !ViewportClient->IgnoreInput()) { TSharedRef<SViewport> ViewportWidgetRef = ViewportWidget.Pin().ToSharedRef(); // Mouse down should focus viewport for keyboard input CurrentReplyState.SetKeyboardFocus(ViewportWidgetRef, EKeyboardFocusCause::Mouse); UWorld* World = ViewportClient->GetWorld(); if (World && World->IsGameWorld() && World->GetFirstPlayerController()) { CurrentReplyState.CaptureMouse(ViewportWidgetRef); CurrentReplyState.LockMouseToWidget(ViewportWidgetRef); bool bShouldShowMouseCursor = World->GetFirstPlayerController()->ShouldShowMouseCursor(); if (ViewportClient->HideCursorDuringCapture() && bShouldShowMouseCursor) { bCursorHiddenDueToCapture = true; } if (bCursorHiddenDueToCapture || !bShouldShowMouseCursor) { CurrentReplyState.UseHighPrecisionMouseMovement(ViewportWidgetRef); } } else { CurrentReplyState.UseHighPrecisionMouseMovement(ViewportWidgetRef); } } } // Re-set prevent throttling here as it can get reset when inside of InputKey() CurrentReplyState.PreventThrottling(); return CurrentReplyState; }
FReply FSceneViewport::OnMouseButtonDown( const FGeometry& InGeometry, const FPointerEvent& InMouseEvent ) { // Start a new reply state // Prevent throttling when interacting with the viewport so we can move around in it CurrentReplyState = FReply::Handled().PreventThrottling(); KeyStateMap.Add(InMouseEvent.GetEffectingButton(), true); UpdateModifierKeys( InMouseEvent ); UpdateCachedMousePos( InGeometry, InMouseEvent ); UpdateCachedGeometry(InGeometry); // Switch to the viewport clients world before processing input FScopedConditionalWorldSwitcher WorldSwitcher( ViewportClient ); if( ViewportClient && GetSizeXY() != FIntPoint::ZeroValue ) { // If we're obtaining focus, we have to copy the modifier key states prior to processing this mouse button event, as this is the only point at which the mouse down // event is processed when focus initially changes and the modifier keys need to be in-place to detect any unique drag-like events. if ( !HasFocus() ) { FModifierKeysState KeysState = FSlateApplication::Get().GetModifierKeys(); ApplyModifierKeys( KeysState ); } const bool bAnyMenuWasVisible = FSlateApplication::Get().AnyMenusVisible(); // Process the mouse event if (!ViewportClient->InputKey(this, InMouseEvent.GetUserIndex(), InMouseEvent.GetEffectingButton(), IE_Pressed)) { CurrentReplyState = FReply::Unhandled(); } // a new menu was opened if there was previously not a menu visible but now there is const bool bNewMenuWasOpened = !bAnyMenuWasVisible && FSlateApplication::Get().AnyMenusVisible(); if (!ViewportClient->IgnoreInput() && !bNewMenuWasOpened && // We should not focus the viewport if a menu was opened as it would close the menu ( ViewportClient->CaptureMouseOnClick() == EMouseCaptureMode::CapturePermanently || ViewportClient->CaptureMouseOnClick() == EMouseCaptureMode::CaptureDuringMouseDown || ( ViewportClient->CaptureMouseOnClick() == EMouseCaptureMode::CaptureDuringRightMouseDown && InMouseEvent.GetEffectingButton() == EKeys::RightMouseButton ) ) ) { TSharedRef<SViewport> ViewportWidgetRef = ViewportWidget.Pin().ToSharedRef(); // Mouse down should focus viewport for user input CurrentReplyState.SetUserFocus(ViewportWidgetRef, EFocusCause::SetDirectly, true); UWorld* World = ViewportClient->GetWorld(); if (World && World->IsGameWorld() && World->GetFirstPlayerController()) { CurrentReplyState.CaptureMouse(ViewportWidgetRef); CurrentReplyState.LockMouseToWidget(ViewportWidgetRef); bool bShouldShowMouseCursor = World->GetFirstPlayerController()->ShouldShowMouseCursor(); if (ViewportClient->HideCursorDuringCapture() && bShouldShowMouseCursor) { bCursorHiddenDueToCapture = true; MousePosBeforeHiddenDueToCapture = FIntPoint( InMouseEvent.GetScreenSpacePosition().X, InMouseEvent.GetScreenSpacePosition().Y ); } if (bCursorHiddenDueToCapture || !bShouldShowMouseCursor) { CurrentReplyState.UseHighPrecisionMouseMovement(ViewportWidgetRef); } } else { CurrentReplyState.UseHighPrecisionMouseMovement(ViewportWidgetRef); } } } // Re-set prevent throttling here as it can get reset when inside of InputKey() CurrentReplyState.PreventThrottling(); return CurrentReplyState; }
/**************************************************************************** Function: void App_ProcessInputReport(void) Description: This function processes input report received from HID device. Precondition: None Parameters: None Return Values: None Remarks: None ***************************************************************************/ void App_ProcessInputReport(void) { BYTE i, j; BOOL pressed; BYTE modifier_keys; BYTE pressed_keys_count; /* process input report received from device */ USBHostHID_ApiImportData(Appl_raw_report_buffer.ReportData, Appl_raw_report_buffer.ReportSize , Appl_BufferModifierKeys, &Appl_ModifierKeysDetails); USBHostHID_ApiImportData(Appl_raw_report_buffer.ReportData, Appl_raw_report_buffer.ReportSize , Appl_BufferNormalKeys, &Appl_NormalKeysDetails); // process modifier keys modifier_keys = 0; if(Appl_BufferModifierKeys[MODIFIER_LEFT_CONTROL] != 0) modifier_keys |= MF_LEFT_CONTROL; if(Appl_BufferModifierKeys[MODIFIER_LEFT_SHIFT] != 0) modifier_keys |= MF_LEFT_SHIFT; if(Appl_BufferModifierKeys[MODIFIER_LEFT_ALT] != 0) modifier_keys |= MF_LEFT_ALT; if(Appl_BufferModifierKeys[MODIFIER_LEFT_GUI] != 0) modifier_keys |= MF_LEFT_GUI; if(Appl_BufferModifierKeys[MODIFIER_RIGHT_CONTROL] != 0) modifier_keys |= MF_RIGHT_CONTROL; if(Appl_BufferModifierKeys[MODIFIER_RIGHT_SHIFT] != 0) modifier_keys |= MF_RIGHT_SHIFT; if(Appl_BufferModifierKeys[MODIFIER_RIGHT_ALT] != 0) modifier_keys |= MF_RIGHT_ALT; if(Appl_BufferModifierKeys[MODIFIER_RIGHT_GUI] != 0) modifier_keys |= MF_RIGHT_GUI; UpdateModifierKeys(modifier_keys); // update keys pressed_keys_count = 0; for (i = 0; i < KEY_REPORT_DATA_LENGTH; i++) { // pressed keys if (Appl_BufferNormalKeys[i] != 0) { pressed_keys_count++; switch (Appl_BufferNormalKeys[i]) { // CAPS lock case HID_CAPS_LOCK_VAL: CAPS_Lock_Pressed = !CAPS_Lock_Pressed; LED_Key_Pressed = TRUE; Appl_led_report_buffer.CAPS_LOCK = CAPS_Lock_Pressed; break; // NUM lock case HID_NUM_LOCK_VAL: NUM_Lock_Pressed = !NUM_Lock_Pressed; LED_Key_Pressed = TRUE; Appl_led_report_buffer.NUM_LOCK = NUM_Lock_Pressed; break; // any other key default: // check if it was pressed earlier pressed = TRUE; for (j = 0; j < KEY_REPORT_DATA_LENGTH && pressed; j++) { if (Appl_BufferNormalKeys[i] == Appl_BufferPreviousKeys[j]) pressed = FALSE; } // it appears first in the current report -> key was pressed if (pressed) { UpdateKeyboardMatrix(Appl_BufferNormalKeys[i], modifier_keys, TRUE); } } } else { // no more keys to process break; } } // process released keys for (i = 0; i < KEY_REPORT_DATA_LENGTH; i++) { if(Appl_BufferPreviousKeys[i] != 0) { pressed = FALSE; for(j=0;j<KEY_REPORT_DATA_LENGTH && !pressed;j++) { if(Appl_BufferPreviousKeys[i] == Appl_BufferNormalKeys[j]) pressed = TRUE; } if(!pressed) { // key was released UpdateKeyboardMatrix(Appl_BufferPreviousKeys[i], modifier_keys, FALSE); } } else { break; } } // just for sure clear matrix when no key is pressed if(modifier_keys == 0 && pressed_keys_count == 0) ClearKeyboardMatrix(); // copy report data to the previous buffer for (i = 0; i < KEY_REPORT_DATA_LENGTH; i++) Appl_BufferPreviousKeys[i] = Appl_BufferNormalKeys[i]; // clear report buffer for (i = 0; i < KEY_REPORT_DATA_LENGTH; i++) Appl_BufferNormalKeys[i] = 0; for (i = 0; i < Appl_raw_report_buffer.ReportSize; i++) Appl_raw_report_buffer.ReportData[i] = 0; }