prevent screen lost after admin screen.

This commit is contained in:
hecomi
2016-11-04 19:11:17 +09:00
parent 2c61fcd470
commit 2e763d994d
9 changed files with 230 additions and 17 deletions
@@ -5,4 +5,11 @@ class MonitorManager;
IUnityInterfaces* GetUnity();
ID3D11Device* GetDevice();
const std::unique_ptr<MonitorManager>& GetMonitorManager();
const std::unique_ptr<MonitorManager>& GetMonitorManager();
enum class Message
{
None = -1,
Reinitialized = 0,
};
void SendMessageToUnity(Message message);
@@ -8,27 +8,64 @@
Monitor::Monitor(int id, IDXGIOutput* output)
: id_(id)
{
// MEMO: 'output' will be released automatically after this ctor.
output->GetDesc(&outputDesc_);
monitorInfo_.cbSize = sizeof(MONITORINFOEX);
GetMonitorInfo(outputDesc_.Monitor, &monitorInfo_);
auto output1 = reinterpret_cast<IDXGIOutput1*>(output);
output1->DuplicateOutput(GetDevice(), &deskDupl_);
const auto hr = output1->DuplicateOutput(GetDevice(), &deskDupl_);
auto error = 0;
// TODO: error check
switch (hr)
{
case S_OK:
break;
case E_INVALIDARG:
error = 1;
break;
case E_ACCESSDENIED:
error = 2;
// For example, when the user presses Ctrl + Alt + Delete and the screen
// switches to admin screen, this error occurs.
break;
case DXGI_ERROR_UNSUPPORTED:
error = 3;
break;
case DXGI_ERROR_NOT_CURRENTLY_AVAILABLE:
error = 4;
// Other application use Desktop Duplication API...
break;
case DXGI_ERROR_SESSION_DISCONNECTED:
error = 5;
break;
}
cursor_ = std::make_unique<Cursor>(this);
// MEMO: 'output' will be released automatically after this ctor.
}
Monitor::~Monitor()
{
deskDupl_->Release();
if (deskDupl_ != nullptr)
{
deskDupl_->Release();
}
}
HRESULT Monitor::Render(UINT timeout)
{
if (deskDupl_ == nullptr || unityTexture_ == nullptr) return 0;
if (deskDupl_ == nullptr)
{
GetMonitorManager()->RequireReinitilization();
return 0;
}
if (unityTexture_ == nullptr) return 0;
IDXGIResource* resource = nullptr;
DXGI_OUTDUPL_FRAME_INFO frameInfo;
@@ -6,6 +6,7 @@
#include "IUnityInterface.h"
#include "IUnityGraphicsD3D11.h"
#include "Common.h"
#include "Monitor.h"
#include "Cursor.h"
#include "MonitorManager.h"
@@ -56,6 +57,13 @@ void MonitorManager::Finalize()
}
void MonitorManager::Reinitialize()
{
Initialize();
SendMessageToUnity(Message::Reinitialized);
}
std::shared_ptr<Monitor> MonitorManager::GetMonitor(int id) const
{
if (id >= 0 && id < monitors_.size())
@@ -66,6 +74,16 @@ std::shared_ptr<Monitor> MonitorManager::GetMonitor(int id) const
}
void MonitorManager::Update()
{
if (isReinitializationRequired_)
{
Reinitialize();
isReinitializationRequired_ = false;
}
}
void MonitorManager::OnRender(int id)
{
if (auto monitor = GetMonitor(id))
@@ -75,7 +93,7 @@ void MonitorManager::OnRender(int id)
const auto hr = monitor->Render(timeout_);
if (hr == DXGI_ERROR_ACCESS_LOST)
{
Initialize();
isReinitializationRequired_ = true;
}
}
}
@@ -14,6 +14,8 @@ public:
explicit MonitorManager();
~MonitorManager();
void RequireReinitilization() { isReinitializationRequired_ = true; }
void SetCursorMonitorId(int id) { cursorMonitorId_ = id; }
int GetCursorMonitorId() const { return cursorMonitorId_; }
std::shared_ptr<Monitor> GetMonitor(int id) const;
@@ -21,10 +23,12 @@ public:
private:
void Initialize();
void Finalize();
void Reinitialize();
// Setters from Unity
public:
void OnRender(int id);
void Update();
void UpdateCursorTexture(int id, ID3D11Texture2D* ptr);
void SetTimeout(int timeout);
void SetTexturePtr(int id, void* texture);
@@ -49,4 +53,5 @@ private:
std::vector<std::shared_ptr<Monitor>> monitors_;
std::shared_ptr<Cursor> cursor_;
int cursorMonitorId_ = -1;
bool isReinitializationRequired_ = false;
};
@@ -3,6 +3,7 @@
#include <vector>
#include <string>
#include <memory>
#include <queue>
#include "IUnityInterface.h"
#include "IUnityGraphics.h"
@@ -18,6 +19,7 @@ namespace
{
IUnityInterfaces* g_unity = nullptr;
std::unique_ptr<MonitorManager> g_manager;
std::queue<Message> g_messages;
}
@@ -32,27 +34,49 @@ ID3D11Device* GetDevice()
return GetUnity()->Get<IUnityGraphicsD3D11>()->GetDevice();
}
const std::unique_ptr<MonitorManager>& GetMonitorManager()
{
return g_manager;
}
void SendMessageToUnity(Message message)
{
g_messages.push(message);
}
extern "C"
{
UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API Initialize()
{
if (g_unity && !g_manager)
{
g_manager = std::make_unique<MonitorManager>();
}
}
UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API Finalize()
{
g_manager.reset();
}
UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API UnityPluginLoad(IUnityInterfaces* unityInterfaces)
{
g_unity = unityInterfaces;
g_manager = std::make_unique<MonitorManager>();
Initialize();
}
UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API UnityPluginUnload()
{
g_manager.reset();
g_unity = nullptr;
Finalize();
}
void UNITY_INTERFACE_API OnRenderEvent(int id)
{
if (!g_manager) return;
g_manager->OnRender(id);
}
@@ -61,78 +85,108 @@ extern "C"
return OnRenderEvent;
}
UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API Update()
{
if (!g_manager) return;
g_manager->Update();
}
UNITY_INTERFACE_EXPORT Message PopMessage()
{
if (g_messages.empty()) return Message::None;
const auto message = g_messages.front();
g_messages.pop();
return message;
}
UNITY_INTERFACE_EXPORT size_t UNITY_INTERFACE_API GetMonitorCount()
{
if (!g_manager) return 0;
return g_manager->GetMonitorCount();
}
UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API SetTimeout(int timeout)
{
if (!g_manager) return;
g_manager->SetTimeout(timeout);
}
UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API GetName(int id, char* buf, int len)
{
if (!g_manager) return;
g_manager->GetName(id, buf, len);
}
UNITY_INTERFACE_EXPORT bool UNITY_INTERFACE_API IsPrimary(int id)
{
if (!g_manager) return false;
return g_manager->IsPrimary(id);
}
UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API GetWidth(int id)
{
if (!g_manager) return -1;
return g_manager->GetWidth(id);
}
UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API GetHeight(int id)
{
if (!g_manager) return -1;
return g_manager->GetHeight(id);
}
UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API IsCursorVisible(int id)
UNITY_INTERFACE_EXPORT bool UNITY_INTERFACE_API IsCursorVisible(int id)
{
if (!g_manager) return false;
return g_manager->IsCursorVisible(id);
}
UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API GetCursorX(int id)
{
if (!g_manager) return -1;
return g_manager->GetCursorX(id);
}
UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API GetCursorY(int id)
{
if (!g_manager) return -1;
return g_manager->GetCursorY(id);
}
UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API GetCursorShapeWidth(int id)
{
if (!g_manager) return -1;
return g_manager->GetCursorShapeWidth(id);
}
UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API GetCursorShapeHeight(int id)
{
if (!g_manager) return -1;
return g_manager->GetCursorShapeHeight(id);
}
UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API GetCursorShapePitch(int id)
{
if (!g_manager) return -1;
return g_manager->GetCursorShapePitch(id);
}
UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API GetCursorShapeType(int id)
{
if (!g_manager) return -1;
return g_manager->GetCursorShapeType(id);
}
UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API UpdateCursorTexture(int id, ID3D11Texture2D* ptr)
{
if (!g_manager) return;
g_manager->UpdateCursorTexture(id, ptr);
}
UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API SetTexturePtr(int id, void* texture)
{
if (!g_manager) return;
g_manager->SetTexturePtr(id, texture);
}
}