mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-23 05:19:56 +00:00
UWP: Hook up basic keyboard support
This commit is contained in:
parent
52cd3164ee
commit
86f4559748
19
UWP/App.cpp
19
UWP/App.cpp
@ -73,11 +73,21 @@ void App::SetWindow(CoreWindow^ window) {
|
||||
DisplayInformation::DisplayContentsInvalidated +=
|
||||
ref new TypedEventHandler<DisplayInformation^, Object^>(this, &App::OnDisplayContentsInvalidated);
|
||||
|
||||
// window->KeyDown += ref new TypedEventHandler<DisplayInformation, Object^>(this, &App::OnKeyDown);
|
||||
window->KeyDown += ref new TypedEventHandler<CoreWindow^, KeyEventArgs^>(this, &App::OnKeyDown);
|
||||
window->KeyUp += ref new TypedEventHandler<CoreWindow^, KeyEventArgs^>(this, &App::OnKeyUp);
|
||||
|
||||
m_deviceResources->SetWindow(window);
|
||||
}
|
||||
|
||||
|
||||
void App::OnKeyDown(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args) {
|
||||
m_main->OnKeyDown(args->KeyStatus.ScanCode, args->VirtualKey, args->KeyStatus.RepeatCount);
|
||||
}
|
||||
|
||||
void App::OnKeyUp(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args) {
|
||||
m_main->OnKeyUp(args->KeyStatus.ScanCode, args->VirtualKey);
|
||||
}
|
||||
|
||||
|
||||
// Initializes scene resources, or loads a previously saved app state.
|
||||
void App::Load(Platform::String^ entryPoint) {
|
||||
if (m_main == nullptr) {
|
||||
@ -90,7 +100,6 @@ void App::Run() {
|
||||
while (!m_windowClosed) {
|
||||
if (m_windowVisible) {
|
||||
CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);
|
||||
m_main->Update();
|
||||
if (m_main->Render()) {
|
||||
m_deviceResources->Present();
|
||||
}
|
||||
@ -153,10 +162,6 @@ void App::OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) {
|
||||
m_windowClosed = true;
|
||||
}
|
||||
|
||||
void App::OnKeyDown(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::WindowSizeChangedEventArgs^ args) {
|
||||
|
||||
}
|
||||
|
||||
// DisplayInformation event handlers.
|
||||
|
||||
void App::OnDpiChanged(DisplayInformation^ sender, Object^ args) {
|
||||
|
@ -36,7 +36,8 @@ namespace UWP
|
||||
void OnDisplayContentsInvalidated(Windows::Graphics::Display::DisplayInformation^ sender, Platform::Object^ args);
|
||||
|
||||
// Input
|
||||
void OnKeyDown(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::WindowSizeChangedEventArgs^ args);
|
||||
void OnKeyDown(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args);
|
||||
void OnKeyUp(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args);
|
||||
|
||||
private:
|
||||
std::shared_ptr<DX::DeviceResources> m_deviceResources;
|
||||
|
@ -230,7 +230,6 @@ void DX::DeviceResources::CreateWindowSizeDependentResources()
|
||||
m_d3dRenderTargetView = nullptr;
|
||||
m_d2dContext->SetTarget(nullptr);
|
||||
m_d2dTargetBitmap = nullptr;
|
||||
m_d3dDepthStencilView = nullptr;
|
||||
m_d3dContext->Flush1(D3D11_CONTEXT_TYPE_ALL, nullptr);
|
||||
|
||||
UpdateRenderTargetSize();
|
||||
@ -381,34 +380,6 @@ void DX::DeviceResources::CreateWindowSizeDependentResources()
|
||||
)
|
||||
);
|
||||
|
||||
// Create a depth stencil view for use with 3D rendering if needed.
|
||||
CD3D11_TEXTURE2D_DESC1 depthStencilDesc(
|
||||
DXGI_FORMAT_D24_UNORM_S8_UINT,
|
||||
lround(m_d3dRenderTargetSize.Width),
|
||||
lround(m_d3dRenderTargetSize.Height),
|
||||
1, // This depth stencil view has only one texture.
|
||||
1, // Use a single mipmap level.
|
||||
D3D11_BIND_DEPTH_STENCIL
|
||||
);
|
||||
|
||||
ComPtr<ID3D11Texture2D1> depthStencil;
|
||||
DX::ThrowIfFailed(
|
||||
m_d3dDevice->CreateTexture2D1(
|
||||
&depthStencilDesc,
|
||||
nullptr,
|
||||
&depthStencil
|
||||
)
|
||||
);
|
||||
|
||||
CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D);
|
||||
DX::ThrowIfFailed(
|
||||
m_d3dDevice->CreateDepthStencilView(
|
||||
depthStencil.Get(),
|
||||
&depthStencilViewDesc,
|
||||
&m_d3dDepthStencilView
|
||||
)
|
||||
);
|
||||
|
||||
// Set the 3D rendering viewport to target the entire window.
|
||||
m_screenViewport = CD3D11_VIEWPORT(
|
||||
0.0f,
|
||||
@ -632,9 +603,6 @@ void DX::DeviceResources::Present()
|
||||
// overwritten. If dirty or scroll rects are used, this call should be removed.
|
||||
m_d3dContext->DiscardView1(m_d3dRenderTargetView.Get(), nullptr, 0);
|
||||
|
||||
// Discard the contents of the depth stencil.
|
||||
m_d3dContext->DiscardView1(m_d3dDepthStencilView.Get(), nullptr, 0);
|
||||
|
||||
// If the device was removed either by a disconnection or a driver upgrade, we
|
||||
// must recreate all device resources.
|
||||
if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)
|
||||
|
@ -37,7 +37,6 @@ namespace DX
|
||||
IDXGISwapChain3* GetSwapChain() const { return m_swapChain.Get(); }
|
||||
D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; }
|
||||
ID3D11RenderTargetView1* GetBackBufferRenderTargetView() const { return m_d3dRenderTargetView.Get(); }
|
||||
ID3D11DepthStencilView* GetDepthStencilView() const { return m_d3dDepthStencilView.Get(); }
|
||||
D3D11_VIEWPORT GetScreenViewport() const { return m_screenViewport; }
|
||||
DirectX::XMFLOAT4X4 GetOrientationTransform3D() const { return m_orientationTransform3D; }
|
||||
|
||||
@ -64,7 +63,6 @@ namespace DX
|
||||
|
||||
// Direct3D rendering objects. Required for 3D.
|
||||
Microsoft::WRL::ComPtr<ID3D11RenderTargetView1> m_d3dRenderTargetView;
|
||||
Microsoft::WRL::ComPtr<ID3D11DepthStencilView> m_d3dDepthStencilView;
|
||||
D3D11_VIEWPORT m_screenViewport;
|
||||
|
||||
// Direct2D drawing components.
|
||||
|
110
UWP/NKCodeFromWindowsSystem.cpp
Normal file
110
UWP/NKCodeFromWindowsSystem.cpp
Normal file
@ -0,0 +1,110 @@
|
||||
#include "pch.h"
|
||||
#include "NKCodeFromWindowsSystem.h"
|
||||
|
||||
using namespace Windows::System;
|
||||
|
||||
std::map<Windows::System::VirtualKey, int> virtualKeyCodeToNKCode{
|
||||
{ VirtualKey::A, NKCODE_A },
|
||||
{ VirtualKey::B, NKCODE_B },
|
||||
{ VirtualKey::C, NKCODE_C },
|
||||
{ VirtualKey::D, NKCODE_D },
|
||||
{ VirtualKey::E, NKCODE_E },
|
||||
{ VirtualKey::F, NKCODE_F },
|
||||
{ VirtualKey::G, NKCODE_G },
|
||||
{ VirtualKey::H, NKCODE_H },
|
||||
{ VirtualKey::I, NKCODE_I },
|
||||
{ VirtualKey::J, NKCODE_J },
|
||||
{ VirtualKey::K, NKCODE_K },
|
||||
{ VirtualKey::L, NKCODE_L },
|
||||
{ VirtualKey::M, NKCODE_M },
|
||||
{ VirtualKey::N, NKCODE_N },
|
||||
{ VirtualKey::O, NKCODE_O },
|
||||
{ VirtualKey::P, NKCODE_P },
|
||||
{ VirtualKey::Q, NKCODE_Q },
|
||||
{ VirtualKey::R, NKCODE_R },
|
||||
{ VirtualKey::S, NKCODE_S },
|
||||
{ VirtualKey::T, NKCODE_T },
|
||||
{ VirtualKey::U, NKCODE_U },
|
||||
{ VirtualKey::V, NKCODE_V },
|
||||
{ VirtualKey::W, NKCODE_W },
|
||||
{ VirtualKey::X, NKCODE_X },
|
||||
{ VirtualKey::Y, NKCODE_Y },
|
||||
{ VirtualKey::Z, NKCODE_Z },
|
||||
{ VirtualKey::Number0, NKCODE_0 },
|
||||
{ VirtualKey::Number1, NKCODE_1 },
|
||||
{ VirtualKey::Number2, NKCODE_2 },
|
||||
{ VirtualKey::Number3, NKCODE_3 },
|
||||
{ VirtualKey::Number4, NKCODE_4 },
|
||||
{ VirtualKey::Number5, NKCODE_5 },
|
||||
{ VirtualKey::Number6, NKCODE_6 },
|
||||
{ VirtualKey::Number7, NKCODE_7 },
|
||||
{ VirtualKey::Number8, NKCODE_8 },
|
||||
{ VirtualKey::Number9, NKCODE_9 },
|
||||
{ VirtualKey::Decimal, NKCODE_PERIOD },
|
||||
// { VirtualKey::Comma, NKCODE_COMMA },
|
||||
{ VirtualKey::NumberPad0, NKCODE_NUMPAD_0 },
|
||||
{ VirtualKey::NumberPad1, NKCODE_NUMPAD_1 },
|
||||
{ VirtualKey::NumberPad2, NKCODE_NUMPAD_2 },
|
||||
{ VirtualKey::NumberPad3, NKCODE_NUMPAD_3 },
|
||||
{ VirtualKey::NumberPad4, NKCODE_NUMPAD_4 },
|
||||
{ VirtualKey::NumberPad5, NKCODE_NUMPAD_5 },
|
||||
{ VirtualKey::NumberPad6, NKCODE_NUMPAD_6 },
|
||||
{ VirtualKey::NumberPad7, NKCODE_NUMPAD_7 },
|
||||
{ VirtualKey::NumberPad8, NKCODE_NUMPAD_8 },
|
||||
{ VirtualKey::NumberPad9, NKCODE_NUMPAD_9 },
|
||||
{ VirtualKey::Decimal, NKCODE_NUMPAD_DOT },
|
||||
{ VirtualKey::Divide, NKCODE_NUMPAD_DIVIDE },
|
||||
{ VirtualKey::Multiply, NKCODE_NUMPAD_MULTIPLY },
|
||||
{ VirtualKey::Subtract, NKCODE_NUMPAD_SUBTRACT },
|
||||
{ VirtualKey::Add, NKCODE_NUMPAD_ADD },
|
||||
{ VirtualKey::Separator, NKCODE_NUMPAD_COMMA },
|
||||
{ VirtualKey::LeftControl, NKCODE_CTRL_LEFT },
|
||||
{ VirtualKey::RightControl, NKCODE_CTRL_RIGHT },
|
||||
{ VirtualKey::LeftShift, NKCODE_SHIFT_LEFT },
|
||||
{ VirtualKey::RightShift, NKCODE_SHIFT_RIGHT },
|
||||
//{ VK_LMENU, NKCODE_ALT_LEFT },
|
||||
//{ VK_RMENU, NKCODE_ALT_RIGHT },
|
||||
{ VirtualKey::GoBack, NKCODE_BACK },
|
||||
{ VirtualKey::Space, NKCODE_SPACE },
|
||||
{ VirtualKey::Escape, NKCODE_ESCAPE },
|
||||
{ VirtualKey::Up, NKCODE_DPAD_UP },
|
||||
{ VirtualKey::Insert, NKCODE_INSERT },
|
||||
{ VirtualKey::Home, NKCODE_MOVE_HOME },
|
||||
{ VirtualKey::PageUp, NKCODE_PAGE_UP },
|
||||
{ VirtualKey::PageDown, NKCODE_PAGE_DOWN },
|
||||
{ VirtualKey::Delete, NKCODE_FORWARD_DEL },
|
||||
{ VirtualKey::End, NKCODE_MOVE_END },
|
||||
{ VirtualKey::Tab, NKCODE_TAB },
|
||||
{ VirtualKey::Down, NKCODE_DPAD_DOWN },
|
||||
{ VirtualKey::Left, NKCODE_DPAD_LEFT },
|
||||
{ VirtualKey::Right, NKCODE_DPAD_RIGHT },
|
||||
{ VirtualKey::CapitalLock, NKCODE_CAPS_LOCK },
|
||||
{ VirtualKey::Clear, NKCODE_CLEAR },
|
||||
// { VirtualKey::, NKCODE_SYSRQ },
|
||||
{ VirtualKey::Scroll, NKCODE_SCROLL_LOCK },
|
||||
// { , NKCODE_SEMICOLON },
|
||||
// { VK_OEM_2, NKCODE_SLASH },
|
||||
// { VK_OEM_3, NKCODE_GRAVE },
|
||||
// { VK_OEM_4, NKCODE_LEFT_BRACKET },
|
||||
// { VK_OEM_5, NKCODE_BACKSLASH },
|
||||
// { VK_OEM_6, NKCODE_RIGHT_BRACKET },
|
||||
// { VK_OEM_7, NKCODE_APOSTROPHE },
|
||||
{ VirtualKey::Enter, NKCODE_ENTER },
|
||||
// { VK_APPS, NKCODE_MENU }, // Context menu key, let's call this "menu".
|
||||
{ VirtualKey::Pause, NKCODE_BREAK },
|
||||
{ VirtualKey::F1, NKCODE_F1 },
|
||||
{ VirtualKey::F2, NKCODE_F2 },
|
||||
{ VirtualKey::F3, NKCODE_F3 },
|
||||
{ VirtualKey::F4, NKCODE_F4 },
|
||||
{ VirtualKey::F5, NKCODE_F5 },
|
||||
{ VirtualKey::F6, NKCODE_F6 },
|
||||
{ VirtualKey::F7, NKCODE_F7 },
|
||||
{ VirtualKey::F8, NKCODE_F8 },
|
||||
{ VirtualKey::F9, NKCODE_F9 },
|
||||
{ VirtualKey::F10, NKCODE_F10 },
|
||||
{ VirtualKey::F11, NKCODE_F11 },
|
||||
{ VirtualKey::F12, NKCODE_F12 },
|
||||
//{ VK_OEM_102, NKCODE_EXT_PIPE },
|
||||
//{ VK_LBUTTON, NKCODE_EXT_MOUSEBUTTON_1 },
|
||||
//{ VK_RBUTTON, NKCODE_EXT_MOUSEBUTTON_2 },;
|
||||
};
|
7
UWP/NKCodeFromWindowsSystem.h
Normal file
7
UWP/NKCodeFromWindowsSystem.h
Normal file
@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "input/keycodes.h"
|
||||
|
||||
extern std::map<Windows::System::VirtualKey, int> virtualKeyCodeToNKCode;
|
@ -8,6 +8,7 @@
|
||||
#include "Common/LogManager.h"
|
||||
#include "Core/System.h"
|
||||
#include "base/NativeApp.h"
|
||||
#include "base/timeutil.h"
|
||||
#include "input/input_state.h"
|
||||
#include "file/vfs.h"
|
||||
#include "file/zip_read.h"
|
||||
@ -15,6 +16,7 @@
|
||||
#include "base/display.h"
|
||||
#include "util/text/utf8.h"
|
||||
#include "Common/DirectXHelper.h"
|
||||
#include "NKCodeFromWindowsSystem.h"
|
||||
#include "XAudioSoundStream.h"
|
||||
|
||||
using namespace UWP;
|
||||
@ -119,21 +121,18 @@ void PPSSPP_UWPMain::CreateWindowSizeDependentResources() {
|
||||
NativeResized();
|
||||
}
|
||||
|
||||
// Updates the application state once per frame.
|
||||
void PPSSPP_UWPMain::Update() {
|
||||
InputState input{};
|
||||
NativeUpdate(input);
|
||||
}
|
||||
|
||||
// Renders the current frame according to the current application state.
|
||||
// Returns true if the frame was rendered and is ready to be displayed.
|
||||
bool PPSSPP_UWPMain::Render() {
|
||||
InputState input{};
|
||||
NativeUpdate(input);
|
||||
|
||||
time_update();
|
||||
auto context = m_deviceResources->GetD3DDeviceContext();
|
||||
|
||||
// Reset the viewport to target the whole screen.
|
||||
auto viewport = m_deviceResources->GetScreenViewport();
|
||||
|
||||
m_deviceResources->GetBackBufferRenderTargetView();
|
||||
pixel_xres = viewport.Width;
|
||||
pixel_yres = viewport.Height;
|
||||
|
||||
@ -147,13 +146,8 @@ bool PPSSPP_UWPMain::Render() {
|
||||
|
||||
context->RSSetViewports(1, &viewport);
|
||||
|
||||
// Reset render targets to the screen.
|
||||
ID3D11RenderTargetView *const targets[1] = { m_deviceResources->GetBackBufferRenderTargetView() };
|
||||
context->OMSetRenderTargets(1, targets, m_deviceResources->GetDepthStencilView());
|
||||
ctx_->GetDrawContext()->BindBackbufferAsRenderTarget();
|
||||
|
||||
// Clear the back buffer and depth stencil view.
|
||||
context->ClearRenderTargetView(m_deviceResources->GetBackBufferRenderTargetView(), DirectX::Colors::CornflowerBlue);
|
||||
context->ClearDepthStencilView(m_deviceResources->GetDepthStencilView(), D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
|
||||
NativeRender(ctx_.get());
|
||||
return true;
|
||||
}
|
||||
@ -170,6 +164,29 @@ void PPSSPP_UWPMain::OnDeviceRestored() {
|
||||
ctx_->GetDrawContext()->HandleEvent(Draw::Event::GOT_DEVICE, 0, 0, nullptr);
|
||||
}
|
||||
|
||||
void PPSSPP_UWPMain::OnKeyDown(int scanCode, Windows::System::VirtualKey virtualKey, int repeatCount) {
|
||||
auto iter = virtualKeyCodeToNKCode.find(virtualKey);
|
||||
if (iter != virtualKeyCodeToNKCode.end()) {
|
||||
KeyInput key{};
|
||||
key.deviceId = DEVICE_ID_KEYBOARD;
|
||||
key.keyCode = iter->second;
|
||||
key.flags = KEY_DOWN | (repeatCount > 1 ? KEY_IS_REPEAT : 0);
|
||||
NativeKey(key);
|
||||
}
|
||||
}
|
||||
|
||||
void PPSSPP_UWPMain::OnKeyUp(int scanCode, Windows::System::VirtualKey virtualKey) {
|
||||
auto iter = virtualKeyCodeToNKCode.find(virtualKey);
|
||||
if (iter != virtualKeyCodeToNKCode.end()) {
|
||||
KeyInput key{};
|
||||
key.deviceId = DEVICE_ID_KEYBOARD;
|
||||
key.keyCode = iter->second;
|
||||
key.flags = KEY_UP;
|
||||
NativeKey(key);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
UWPGraphicsContext::UWPGraphicsContext(std::shared_ptr<DX::DeviceResources> resources) {
|
||||
draw_ = Draw::T3DCreateD3D11Context(resources->GetD3DDevice(), resources->GetD3DDeviceContext(), resources->GetD3DDevice(), resources->GetD3DDeviceContext(), 0);
|
||||
}
|
||||
|
@ -31,13 +31,17 @@ public:
|
||||
PPSSPP_UWPMain(const std::shared_ptr<DX::DeviceResources>& deviceResources);
|
||||
~PPSSPP_UWPMain();
|
||||
void CreateWindowSizeDependentResources();
|
||||
void Update();
|
||||
bool Render();
|
||||
|
||||
// IDeviceNotify
|
||||
virtual void OnDeviceLost();
|
||||
virtual void OnDeviceRestored();
|
||||
|
||||
// Various forwards from App, in simplified format.
|
||||
// Not sure whether this abstraction is worth it.
|
||||
void OnKeyDown(int scanCode, Windows::System::VirtualKey virtualKey, int repeatCount);
|
||||
void OnKeyUp(int scanCode, Windows::System::VirtualKey virtualKey);
|
||||
|
||||
private:
|
||||
// Cached pointer to device resources.
|
||||
std::shared_ptr<DX::DeviceResources> m_deviceResources;
|
||||
|
@ -224,6 +224,7 @@
|
||||
<ClInclude Include="..\ppsspp_config.h" />
|
||||
<ClInclude Include="App.h" />
|
||||
<ClInclude Include="Common\DeviceResources.h" />
|
||||
<ClInclude Include="NKCodeFromWindowsSystem.h" />
|
||||
<ClInclude Include="PPSSPP_UWPMain.h" />
|
||||
<ClInclude Include="Common\DirectXHelper.h" />
|
||||
<ClInclude Include="pch.h" />
|
||||
@ -240,6 +241,7 @@
|
||||
</ClCompile>
|
||||
<ClCompile Include="App.cpp" />
|
||||
<ClCompile Include="Common\DeviceResources.cpp" />
|
||||
<ClCompile Include="NKCodeFromWindowsSystem.cpp" />
|
||||
<ClCompile Include="PPSSPP_UWPMain.cpp" />
|
||||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
|
@ -45,6 +45,7 @@
|
||||
<ClCompile Include="..\git-version.cpp" />
|
||||
<ClCompile Include="XAudioSoundStream.cpp" />
|
||||
<ClCompile Include="PPSSPP_UWPMain.cpp" />
|
||||
<ClCompile Include="NKCodeFromWindowsSystem.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="App.h" />
|
||||
@ -52,6 +53,7 @@
|
||||
<ClInclude Include="..\ppsspp_config.h" />
|
||||
<ClInclude Include="XAudioSoundStream.h" />
|
||||
<ClInclude Include="PPSSPP_UWPMain.h" />
|
||||
<ClInclude Include="NKCodeFromWindowsSystem.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="Assets\StoreLogo.png">
|
||||
@ -69,15 +71,15 @@
|
||||
<Image Include="Content\zip.png">
|
||||
<Filter>Content</Filter>
|
||||
</Image>
|
||||
<Image Include="Content\ui_atlas.zim">
|
||||
<Filter>Content</Filter>
|
||||
</Image>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AppxManifest Include="Package.appxmanifest" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="UWP_TemporaryKey.pfx" />
|
||||
<None Include="Content\ui_atlas.zim">
|
||||
<Filter>Content</Filter>
|
||||
</None>
|
||||
<None Include="Content\compat.ini">
|
||||
<Filter>Content</Filter>
|
||||
</None>
|
||||
|
Loading…
Reference in New Issue
Block a user