prevent screen lost after admin screen.
This commit is contained in:
Binary file not shown.
@@ -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")]
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user