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
+16
View File
@@ -5,6 +5,12 @@ using System.Runtime.InteropServices;
namespace uDesktopDuplication
{
public enum Message
{
None = -1,
Reinitialized = 0,
}
public enum CursorShapeType
{
MonoChrome = 1,
@@ -14,6 +20,16 @@ public enum CursorShapeType
public static class Lib
{
public delegate void MessageHandler(Message message);
[DllImport("uDesktopDuplication")]
public static extern void Initialize();
[DllImport("uDesktopDuplication")]
public static extern void Finalize();
[DllImport("uDesktopDuplication")]
public static extern void Update();
[DllImport("uDesktopDuplication")]
public static extern Message PopMessage();
[DllImport("uDesktopDuplication")]
public static extern int GetMonitorCount();
[DllImport("uDesktopDuplication")]
+52 -4
View File
@@ -26,7 +26,7 @@ public class Manager : MonoBehaviour
static public int monitorCount
{
get { return instance.monitors_.Count; }
get { return Lib.GetMonitorCount(); }
}
static public Monitor primary
@@ -41,19 +41,25 @@ public class Manager : MonoBehaviour
int timeout = 0;
private Coroutine renderCoroutine_ = null;
Message message_ = Message.None;
void Awake()
{
Lib.Initialize();
if (instance_ != null) return;
instance_ = this;
for (int i = 0; i < Lib.GetMonitorCount(); ++i) {
monitors.Add(new Monitor(i));
}
CreateMonitors();
Lib.SetTimeout(timeout);
}
void OnApplicationQuit()
{
Lib.Finalize();
}
void OnEnable()
{
renderCoroutine_ = StartCoroutine(OnRender());
@@ -67,6 +73,26 @@ public class Manager : MonoBehaviour
}
}
void Update()
{
Lib.Update();
var message = Lib.PopMessage();
while (message != Message.None) {
switch (message) {
case Message.Reinitialized:
Debug.Log("Reinitialize");
Reinitialize();
break;
default:
break;
}
message = Lib.PopMessage();
}
message_ = Message.None;
}
IEnumerator OnRender()
{
for (;;) {
@@ -80,6 +106,28 @@ public class Manager : MonoBehaviour
}
}
}
void CreateMonitors()
{
for (int i = 0; i < monitorCount; ++i) {
monitors.Add(new Monitor(i));
}
}
void OnMessage(Message message)
{
message_ = message;
}
void Reinitialize()
{
for (int i = 0; i < monitorCount; ++i) {
if (i == monitors.Count) {
monitors.Add(new Monitor(i));
}
monitors[i].Reinitialize();
}
}
}
}
+32 -4
View File
@@ -16,6 +16,11 @@ public class Monitor
private set;
}
public bool exists
{
get { return id < Manager.monitorCount; }
}
public string name
{
get { return Lib.GetName(id); }
@@ -93,10 +98,7 @@ public class Monitor
get
{
if (texture_ == null) {
var w = isHorizontal ? width : height;
var h = isHorizontal ? height : width;
texture_ = new Texture2D(w, h, TextureFormat.BGRA32, false);
Lib.SetTexturePtr(id, texture_.GetNativeTexturePtr());
CreateTexture();
}
return texture_;
}
@@ -104,6 +106,7 @@ public class Monitor
public void Render()
{
Lib.SetTexturePtr(id, texture_.GetNativeTexturePtr());
GL.IssuePluginEvent(Lib.GetRenderEventFunc(), id);
}
@@ -111,6 +114,31 @@ public class Monitor
{
Lib.UpdateCursorTexture(id, ptr);
}
void CreateTexture()
{
var w = isHorizontal ? width : height;
var h = isHorizontal ? height : width;
bool shouldCreate = true;
if (texture_) {
if (texture_.width != w || texture_.height != h) {
if (texture_) Object.DestroyImmediate(texture_);
shouldCreate = true;
} else {
shouldCreate = false;
}
}
if (shouldCreate) {
texture_ = new Texture2D(w, h, TextureFormat.BGRA32, false);
}
}
public void Reinitialize()
{
CreateTexture();
}
}
}
@@ -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);
}
}