Add Platform.Users to handle users per-platform

This commit is contained in:
Wojtek Figat
2021-11-07 20:46:56 +01:00
parent 21e6e8bc7b
commit b3eb17f61e
17 changed files with 203 additions and 94 deletions

View File

@@ -956,12 +956,6 @@ String AndroidPlatform::GetComputerName()
return DeviceModel;
}
String AndroidPlatform::GetUserName()
{
// TODO: add support for username on Android
return String::Empty;
}
bool AndroidPlatform::GetHasFocus()
{
return HasFocus;

View File

@@ -110,7 +110,6 @@ public:
static ScreenOrientationType GetScreenOrientationType();
static String GetUserLocaleName();
static String GetComputerName();
static String GetUserName();
static bool GetHasFocus();
static bool GetIsPaused();
static bool CanOpenUrl(const StringView& url);

View File

@@ -5,6 +5,7 @@
#include "Engine/Platform/MemoryStats.h"
#include "Engine/Platform/MessageBox.h"
#include "Engine/Platform/FileSystem.h"
#include "Engine/Platform/User.h"
#include "Engine/Core/Log.h"
#include "Engine/Core/Types/DateTime.h"
#include "Engine/Core/Types/TimeSpan.h"
@@ -40,6 +41,9 @@ static_assert(sizeof(float) == 4, "Invalid float type size.");
static_assert(sizeof(double) == 8, "Invalid double type size.");
float PlatformBase::CustomDpiScale = 1.0f;
Array<User*, FixedAllocation<8>> PlatformBase::Users;
Delegate<User*> PlatformBase::UserAdded;
Delegate<User*> PlatformBase::UserRemoved;
const Char* ToString(NetworkConnectionType value)
{
@@ -102,6 +106,22 @@ const Char* ToString(ThreadPriority value)
}
}
UserBase::UserBase(const String& name)
: UserBase(SpawnParams(Guid::New(), TypeInitializer), name)
{
}
UserBase::UserBase(const SpawnParams& params, const String& name)
: PersistentScriptingObject(params)
, _name(name)
{
}
String UserBase::GetName() const
{
return _name;
}
bool PlatformBase::Init()
{
#if BUILD_DEBUG
@@ -462,6 +482,11 @@ ScreenOrientationType PlatformBase::GetScreenOrientationType()
return ScreenOrientationType::Unknown;
}
String PlatformBase::GetUserName()
{
return Users.Count() != 0 ? Users[0]->GetName() : String::Empty;
}
bool PlatformBase::GetIsPaused()
{
return false;

View File

@@ -595,7 +595,7 @@ public:
API_PROPERTY() static ScreenOrientationType GetScreenOrientationType();
/// <summary>
/// Gets the current locale culture (eg. "pl-PL" or "en-US").
/// Gets the current locale culture (eg. "pl-PL" or "en-US").
/// </summary>
API_PROPERTY() static String GetUserLocaleName() = delete;
@@ -607,7 +607,7 @@ public:
/// <summary>
/// Gets the user name.
/// </summary>
API_PROPERTY() static String GetUserName() = delete;
API_PROPERTY() static String GetUserName();
/// <summary>
/// Returns true if app has user focus.
@@ -625,6 +625,23 @@ public:
/// <param name="result">The result.</param>
static void CreateGuid(Guid& result);
public:
/// <summary>
/// The list of users.
/// </summary>
API_FIELD(ReadOnly) static Array<User*, FixedAllocation<8>> Users;
/// <summary>
/// Event called when user gets added (eg. logged in).
/// </summary>
API_EVENT() static Delegate<User*> UserAdded;
/// <summary>
/// Event called when user gets removed (eg. logged out).
/// </summary>
API_EVENT() static Delegate<User*> UserRemoved;
public:
/// <summary>

View File

@@ -0,0 +1,20 @@
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
#pragma once
#include "Engine/Platform/Platform.h"
#include "Engine/Platform/User.h"
#include "Engine/Core/Collections/Array.h"
inline void OnPlatformUserAdd(User* user)
{
Platform::Users.Add(user);
Platform::UserAdded(user);
}
inline void OnPlatformUserRemove(User* user)
{
Platform::Users.Remove(user);
Platform::UserRemoved(user);
Delete(user);
}

View File

@@ -0,0 +1,29 @@
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
#pragma once
#include "Engine/Core/Types/String.h"
#include "Engine/Scripting/ScriptingObject.h"
API_INJECT_CPP_CODE("#include \"Engine/Platform/User.h\"");
/// <summary>
/// Native platform user object.
/// </summary>
API_CLASS(NoSpawn, NoConstructor, Sealed, Name="User") class FLAXENGINE_API UserBase : public PersistentScriptingObject
{
DECLARE_SCRIPTING_TYPE_NO_SPAWN(UserBase);
protected:
const String _name;
public:
UserBase(const String& name);
UserBase(const SpawnParams& params, const String& name);
/// <summary>
/// Gets the username.
/// </summary>
API_PROPERTY() String GetName() const;
};

View File

@@ -8,6 +8,7 @@
#include "Engine/Platform/WindowsManager.h"
#include "Engine/Platform/MemoryStats.h"
#include "Engine/Platform/BatteryInfo.h"
#include "Engine/Platform/Base/PlatformUtils.h"
#include "Engine/Profiler/ProfilerCPU.h"
#include "Engine/Core/Log.h"
#include "Engine/Core/Collections/Array.h"
@@ -30,26 +31,6 @@ void* GDKPlatform::Instance = nullptr;
Delegate<> GDKPlatform::OnSuspend;
Delegate<> GDKPlatform::OnResume;
struct User
{
XUserHandle UserHandle;
XUserLocalId LocalId;
Array<APP_LOCAL_DEVICE_ID, FixedAllocation<32>> AssociatedDevices;
void Set(XUserHandle userHandle, XUserLocalId localId)
{
UserHandle = userHandle;
LocalId = localId;
AssociatedDevices.Clear();
}
void Unset()
{
XUserCloseHandle(UserHandle);
AssociatedDevices.Clear();
}
};
namespace
{
bool IsSuspended = false;
@@ -58,11 +39,24 @@ namespace
PAPPSTATE_REGISTRATION Plm = {};
String UserLocale, ComputerName;
XTaskQueueHandle TaskQueue = nullptr;
Array<User, FixedAllocation<8>> Users;
XTaskQueueRegistrationToken UserChangeEventCallbackToken;
XTaskQueueRegistrationToken UserDeviceAssociationChangedCallbackToken;
}
User* FindUser(const XUserLocalId& id)
{
User* result = nullptr;
for (auto& user : Platform::Users)
{
if (user->LocalId.value == id.value)
{
result = user;
break;
}
}
return result;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
@@ -76,7 +70,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
// Complete deferral
SetEvent(PlmSuspendComplete);
(void)WaitForSingleObject(PlmSignalResume, INFINITE);
WaitForSingleObject(PlmSignalResume, INFINITE);
IsSuspended = false;
LOG(Info, "Resuming application");
@@ -100,23 +94,20 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
return DefWindowProc(hWnd, msg, wParam, lParam);
}
void CALLBACK UserChangeEventCallback(_In_opt_ void* context,_In_ XUserLocalId userLocalId, _In_ XUserChangeEvent event)
void CALLBACK UserChangeEventCallback(_In_opt_ void* context, _In_ XUserLocalId userLocalId, _In_ XUserChangeEvent event)
{
LOG(Info, "User event (userLocalId: {0}, event: {1})", userLocalId.value, (int32)event);
auto user = FindUser(userLocalId);
switch (event)
{
case XUserChangeEvent::SignedInAgain:
break;
case XUserChangeEvent::SignedOut:
for (int32 i = 0; i < Users.Count(); i++)
if (user)
{
if (Users[i].LocalId.value == userLocalId.value)
{
Users[i].Unset();
Users.RemoveAt(i);
break;
}
// Logout
OnPlatformUserRemove(user);
}
break;
default: ;
@@ -136,20 +127,6 @@ String ToString(const APP_LOCAL_DEVICE_ID& deviceId)
*reinterpret_cast<const unsigned int*>(&deviceId.value[28]));
}
User* FindUser(const XUserLocalId& id)
{
User* result = nullptr;
for (auto& user : Users)
{
if (user.LocalId.value == id.value)
{
result = &user;
break;
}
}
return result;
}
void CALLBACK UserDeviceAssociationChangedCallback(_In_opt_ void* context,_In_ const XUserDeviceAssociationChange* change)
{
LOG(Info, "User device association event (deviceId: {0}, oldUser: {1}, newUser: {2})", ToString(change->deviceId), change->oldUser.value, change->newUser.value);
@@ -185,7 +162,7 @@ void OnMainWindowCreated(HWND hWnd)
PostMessage(reinterpret_cast<HWND>(context), WM_USER, 0, 0);
// To defer suspend, you must wait to exit this callback
(void)WaitForSingleObject(PlmSuspendComplete, INFINITE);
WaitForSingleObject(PlmSuspendComplete, INFINITE);
}
else
{
@@ -209,9 +186,9 @@ void CALLBACK AddUserComplete(_In_ XAsyncBlock* ab)
if (FindUser(localId) == nullptr)
{
// Add user
auto& user = Users.AddOne();
user.Set(userHandle, userLocalId);
// Login
auto user = New<User>(userHandle, userLocalId, String::Empty);
OnPlatformUserAdd(user);
}
}
@@ -506,11 +483,6 @@ String GDKPlatform::GetComputerName()
return ComputerName;
}
String GDKPlatform::GetUserName()
{
return String::Empty;
}
bool GDKPlatform::GetHasFocus()
{
return !IsSuspended;
@@ -524,7 +496,7 @@ bool GDKPlatform::CanOpenUrl(const StringView& url)
void GDKPlatform::OpenUrl(const StringView& url)
{
const StringAsANSI<> urlANSI(url.Get(), url.Length());
XLaunchUri(Users[0].UserHandle, urlANSI.Get());
XLaunchUri(Users[0]->UserHandle, urlANSI.Get());
}
struct GetMonitorBoundsData

View File

@@ -60,7 +60,6 @@ public:
static int32 GetDpi();
static String GetUserLocaleName();
static String GetComputerName();
static String GetUserName();
static bool GetHasFocus();
static bool CanOpenUrl(const StringView& url);
static void OpenUrl(const StringView& url);

View File

@@ -0,0 +1,38 @@
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
#pragma once
#if PLATFORM_GDK
#include "Engine/Platform/Base/UserBase.h"
#include "Engine/Core/Collections/Array.h"
#include "Engine/Platform/Win32/IncludeWindowsHeaders.h"
#include <XGameRuntime.h>
/// <summary>
/// Implementation of the user for GDK platform.
/// </summary>
class FLAXENGINE_API GDKUser : public UserBase
{
public:
GDKUser(XUserHandle userHandle, XUserLocalId localId, const String& name)
: UserBase(name)
{
UserHandle = userHandle;
LocalId = localId;
}
~GDKUser()
{
XUserCloseHandle(UserHandle);
}
public:
XUserHandle UserHandle;
XUserLocalId LocalId;
Array<APP_LOCAL_DEVICE_ID, FixedAllocation<32>> AssociatedDevices;
};
#endif

View File

@@ -21,6 +21,7 @@
#include "Engine/Platform/WindowsManager.h"
#include "Engine/Platform/Clipboard.h"
#include "Engine/Platform/IGuiData.h"
#include "Engine/Platform/Base/PlatformUtils.h"
#include "Engine/Utilities/StringConverter.h"
#include "Engine/Threading/Threading.h"
#include "Engine/Engine/Engine.h"
@@ -51,7 +52,7 @@
CPUInfo UnixCpu;
int ClockSource;
Guid DeviceId;
String UserLocale, ComputerName, UserName, HomeDir;
String UserLocale, ComputerName, HomeDir;
byte MacAddress[6];
#define UNIX_APP_BUFF_SIZE 256
@@ -2014,6 +2015,10 @@ bool LinuxPlatform::Init()
UnixCpu.CacheLineSize = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
ASSERT(UnixCpu.CacheLineSize && Math::IsPowerOfTwo(UnixCpu.CacheLineSize));
// Get user name string
getlogin_r(buffer, UNIX_APP_BUFF_SIZE);
OnPlatformUserAdd(New<User>(String(buffer));
UnixGetMacAddress(MacAddress);
// Generate unique device ID
@@ -2054,10 +2059,6 @@ bool LinuxPlatform::Init()
gethostname(buffer, UNIX_APP_BUFF_SIZE);
ComputerName = String(buffer);
// Get user name string
getlogin_r(buffer, UNIX_APP_BUFF_SIZE);
UserName = String(buffer);
// Get home dir
struct passwd pw;
struct passwd* result = NULL;
@@ -2603,11 +2604,6 @@ String LinuxPlatform::GetComputerName()
return ComputerName;
}
String LinuxPlatform::GetUserName()
{
return UserName;
}
bool LinuxPlatform::GetHasFocus()
{
// Check if any window is focused

View File

@@ -113,7 +113,6 @@ public:
static int32 GetDpi();
static String GetUserLocaleName();
static String GetComputerName();
static String GetUserName();
static bool GetHasFocus();
static bool CanOpenUrl(const StringView& url);
static void OpenUrl(const StringView& url);

View File

@@ -24,6 +24,8 @@ class WindowsWindow;
typedef WindowsWindow Window;
class Win32Network;
typedef Win32Network Network;
class UserBase;
typedef UserBase User;
#elif PLATFORM_UWP
@@ -47,6 +49,8 @@ class UWPWindow;
typedef UWPWindow Window;
class Win32Network;
typedef Win32Network Network;
class UserBase;
typedef UserBase User;
#elif PLATFORM_LINUX
@@ -70,6 +74,8 @@ class LinuxWindow;
typedef LinuxWindow Window;
class UnixNetwork;
typedef UnixNetwork Network;
class UserBase;
typedef UserBase User;
#elif PLATFORM_PS4
@@ -93,6 +99,8 @@ class PS4Window;
typedef PS4Window Window;
class PS4Network;
typedef PS4Network Network;
class PS4User;
typedef PS4User User;
#elif PLATFORM_PS5
@@ -116,6 +124,8 @@ class PS5Window;
typedef PS5Window Window;
class PS5Network;
typedef PS5Network Network;
class PS5User;
typedef PS5User User;
#elif PLATFORM_XBOX_ONE
@@ -139,6 +149,8 @@ class GDKWindow;
typedef GDKWindow Window;
class NetworkBase;
typedef NetworkBase Network;
class GDKUser;
typedef GDKUser User;
#elif PLATFORM_XBOX_SCARLETT
@@ -162,6 +174,8 @@ class GDKWindow;
typedef GDKWindow Window;
class NetworkBase;
typedef NetworkBase Network;
class GDKUser;
typedef GDKUser User;
#elif PLATFORM_ANDROID
@@ -185,6 +199,8 @@ class AndroidWindow;
typedef AndroidWindow Window;
class UnixNetwork;
typedef UnixNetwork Network;
class UserBase;
typedef UserBase User;
#elif PLATFORM_SWITCH
@@ -208,6 +224,8 @@ class SwitchWindow;
typedef SwitchWindow Window;
class SwitchNetwork;
typedef SwitchNetwork Network;
class UserBase;
typedef UserBase User;
#else

View File

@@ -13,7 +13,7 @@
namespace
{
String UserLocale, ComputerName, UserName;
String UserLocale, ComputerName;
Vector2 VirtualScreenSize = Vector2(0.0f);
int32 SystemDpi = 96;
}
@@ -58,9 +58,6 @@ bool UWPPlatform::Init()
ComputerName = String(buffer);
}
// Cannot access user name with a direct API
UserName = String::Empty;
SystemDpi = CUWPPlatform->GetDpi();
Input::Mouse = Impl::Mouse = New<UWPWindow::UWPMouse>();
Input::Keyboard = Impl::Keyboard = New<UWPWindow::UWPKeyboard>();
@@ -145,11 +142,6 @@ String UWPPlatform::GetComputerName()
return ComputerName;
}
String UWPPlatform::GetUserName()
{
return UserName;
}
bool UWPPlatform::GetHasFocus()
{
// TODO: impl this

View File

@@ -34,7 +34,6 @@ public:
static int32 GetDpi();
static String GetUserLocaleName();
static String GetComputerName();
static String GetUserName();
static bool GetHasFocus();
static bool CanOpenUrl(const StringView& url);
static void OpenUrl(const StringView& url);

View File

@@ -0,0 +1,15 @@
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
#pragma once
#if PLATFORM_XBOX_ONE || PLATFORM_XBOX_SCARLETT
#include "GDK/GDKUser.h"
#elif PLATFORM_PS4
#include "Platforms/PS4/Engine/Platform/PS4User.h"
#elif PLATFORM_PS5
#include "Platforms/PS5/Engine/Platform/PS5User.h"
#else
#include "Base/UserBase.h"
#endif
#include "Types.h"

View File

@@ -9,6 +9,7 @@
#include "Engine/Platform/WindowsManager.h"
#include "Engine/Platform/MemoryStats.h"
#include "Engine/Platform/BatteryInfo.h"
#include "Engine/Platform/Base/PlatformUtils.h"
#include "Engine/Engine/Globals.h"
#include "Engine/Core/Log.h"
#include "Engine/Core/Collections/Dictionary.h"
@@ -55,9 +56,9 @@ void DbgHelpUnlock()
namespace
{
String UserLocale, ComputerName, UserName, WindowsName;
String UserLocale, ComputerName, WindowsName;
HANDLE EngineMutex = nullptr;
Rectangle VirtualScreenBounds = Rectangle(0.0f, 0.0f, 0.0f, 0.0f);
Rectangle VirtualScreenBounds(0.0f, 0.0f, 0.0f, 0.0f);
int32 VersionMajor = 0;
int32 VersionMinor = 0;
int32 VersionBuild = 0;
@@ -647,10 +648,12 @@ bool WindowsPlatform::Init()
}
// Get user name string
String userName;
if (GetUserNameW(buffer, &tmp))
{
UserName = String(buffer);
userName = String(buffer);
}
OnPlatformUserAdd(New<User>(userName));
WindowsInput::Init();
@@ -794,11 +797,6 @@ String WindowsPlatform::GetComputerName()
return ComputerName;
}
String WindowsPlatform::GetUserName()
{
return UserName;
}
bool WindowsPlatform::GetHasFocus()
{
DWORD foregroundProcess;

View File

@@ -68,7 +68,6 @@ public:
static int32 GetDpi();
static String GetUserLocaleName();
static String GetComputerName();
static String GetUserName();
static bool GetHasFocus();
static bool CanOpenUrl(const StringView& url);
static void OpenUrl(const StringView& url);