mirror of
https://github.com/elasota/Aerofoil.git
synced 2025-12-15 12:39:38 +00:00
Add system clipboard support to Windows
This commit is contained in:
@@ -1,14 +1,117 @@
|
||||
#include "GpSystemServices_Win32.h"
|
||||
#include "GpMutex_Win32.h"
|
||||
#include "GpThreadEvent_Win32.h"
|
||||
#include "GpWindows.h"
|
||||
|
||||
#include "IGpClipboardContents.h"
|
||||
|
||||
#include "UTF16.h"
|
||||
#include "UTF8.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <vector>
|
||||
|
||||
#pragma push_macro("CreateMutex")
|
||||
#ifdef CreateMutex
|
||||
#undef CreateMutex
|
||||
#endif
|
||||
|
||||
extern GpWindowsGlobals g_gpWindowsGlobals;
|
||||
|
||||
namespace GpSystemServices_Win32_Private
|
||||
{
|
||||
class RefCountedClipboard
|
||||
{
|
||||
public:
|
||||
RefCountedClipboard();
|
||||
|
||||
protected:
|
||||
virtual ~RefCountedClipboard();
|
||||
|
||||
void AddRef();
|
||||
void DecRef();
|
||||
|
||||
unsigned int m_refCount;
|
||||
};
|
||||
|
||||
class TextClipboard : public RefCountedClipboard, public IGpClipboardContentsText
|
||||
{
|
||||
public:
|
||||
TextClipboard(const uint8_t *utf8Text, size_t utf8Size);
|
||||
~TextClipboard() override;
|
||||
|
||||
GpClipboardContentsType_t GetContentsType() const override;
|
||||
void Destroy() override;
|
||||
IGpClipboardContents *Clone() const override;
|
||||
const uint8_t *GetBytes() const override;
|
||||
size_t GetSize() const override;
|
||||
|
||||
private:
|
||||
std::vector<uint8_t> m_utf8Text;
|
||||
};
|
||||
|
||||
|
||||
RefCountedClipboard::RefCountedClipboard()
|
||||
: m_refCount(1)
|
||||
{
|
||||
}
|
||||
|
||||
RefCountedClipboard::~RefCountedClipboard()
|
||||
{
|
||||
}
|
||||
|
||||
void RefCountedClipboard::AddRef()
|
||||
{
|
||||
m_refCount++;
|
||||
}
|
||||
|
||||
void RefCountedClipboard::DecRef()
|
||||
{
|
||||
unsigned int rc = --m_refCount;
|
||||
if (rc == 0)
|
||||
delete this;
|
||||
}
|
||||
|
||||
TextClipboard::TextClipboard(const uint8_t *utf8Text, size_t utf8Size)
|
||||
{
|
||||
m_utf8Text.resize(utf8Size);
|
||||
if (utf8Size > 0)
|
||||
memcpy(&m_utf8Text[0], utf8Text, utf8Size);
|
||||
}
|
||||
|
||||
TextClipboard::~TextClipboard()
|
||||
{
|
||||
}
|
||||
|
||||
GpClipboardContentsType_t TextClipboard::GetContentsType() const
|
||||
{
|
||||
return GpClipboardContentsTypes::kText;
|
||||
}
|
||||
|
||||
void TextClipboard::Destroy()
|
||||
{
|
||||
this->DecRef();
|
||||
}
|
||||
|
||||
IGpClipboardContents *TextClipboard::Clone() const
|
||||
{
|
||||
const_cast<TextClipboard*>(this)->AddRef();
|
||||
return const_cast<TextClipboard*>(this);
|
||||
}
|
||||
|
||||
const uint8_t *TextClipboard::GetBytes() const
|
||||
{
|
||||
if (m_utf8Text.size() == 0)
|
||||
return nullptr;
|
||||
return &m_utf8Text[0];
|
||||
}
|
||||
|
||||
size_t TextClipboard::GetSize() const
|
||||
{
|
||||
return m_utf8Text.size();
|
||||
}
|
||||
}
|
||||
|
||||
struct GpSystemServices_Win32_ThreadStartParams
|
||||
{
|
||||
GpSystemServices_Win32::ThreadFunc_t m_threadFunc;
|
||||
@@ -34,6 +137,10 @@ GpSystemServices_Win32::GpSystemServices_Win32()
|
||||
{
|
||||
}
|
||||
|
||||
GpSystemServices_Win32::~GpSystemServices_Win32()
|
||||
{
|
||||
}
|
||||
|
||||
int64_t GpSystemServices_Win32::GetTime() const
|
||||
{
|
||||
SYSTEMTIME epochStart;
|
||||
@@ -171,6 +278,89 @@ bool GpSystemServices_Win32::AreFontResourcesSeekable() const
|
||||
return true;
|
||||
}
|
||||
|
||||
IGpClipboardContents *GpSystemServices_Win32::GetClipboardContents() const
|
||||
{
|
||||
IGpClipboardContents *cbObject = nullptr;
|
||||
|
||||
if (IsClipboardFormatAvailable(CF_UNICODETEXT))
|
||||
{
|
||||
if (OpenClipboard(g_gpWindowsGlobals.m_hwnd))
|
||||
{
|
||||
HGLOBAL textHandle = GetClipboardData(CF_UNICODETEXT);
|
||||
if (textHandle)
|
||||
{
|
||||
const wchar_t *str = static_cast<const wchar_t*>(GlobalLock(textHandle));
|
||||
if (str)
|
||||
{
|
||||
if (str[0] == 0)
|
||||
cbObject = new GpSystemServices_Win32_Private::TextClipboard(nullptr, 0);
|
||||
else
|
||||
{
|
||||
int bytesRequired = WideCharToMultiByte(CP_UTF8, 0, str, -1, nullptr, 0, nullptr, nullptr);
|
||||
|
||||
if (bytesRequired > 0)
|
||||
{
|
||||
std::vector<char> decodedText;
|
||||
decodedText.resize(bytesRequired);
|
||||
WideCharToMultiByte(CP_UTF8, 0, str, -1, &decodedText[0], bytesRequired, nullptr, nullptr);
|
||||
|
||||
cbObject = new GpSystemServices_Win32_Private::TextClipboard(reinterpret_cast<const uint8_t*>(&decodedText[0]), decodedText.size() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
GlobalUnlock(textHandle);
|
||||
}
|
||||
}
|
||||
CloseClipboard();
|
||||
}
|
||||
}
|
||||
|
||||
return cbObject;
|
||||
}
|
||||
|
||||
void GpSystemServices_Win32::SetClipboardContents(IGpClipboardContents *contents)
|
||||
{
|
||||
if (!contents)
|
||||
return;
|
||||
|
||||
if (contents->GetContentsType() == GpClipboardContentsTypes::kText)
|
||||
{
|
||||
IGpClipboardContentsText *textContents = static_cast<IGpClipboardContentsText*>(contents);
|
||||
|
||||
if (OpenClipboard(g_gpWindowsGlobals.m_hwnd))
|
||||
{
|
||||
if (EmptyClipboard())
|
||||
{
|
||||
int wcharsRequired = MultiByteToWideChar(CP_UTF8, 0, reinterpret_cast<const char*>(textContents->GetBytes()), textContents->GetSize(), nullptr, 0);
|
||||
|
||||
std::vector<wchar_t> wideChars;
|
||||
|
||||
if (wcharsRequired)
|
||||
{
|
||||
wideChars.resize(wcharsRequired + 1);
|
||||
MultiByteToWideChar(CP_UTF8, 0, reinterpret_cast<const char*>(textContents->GetBytes()), textContents->GetSize(), &wideChars[0], wcharsRequired);
|
||||
}
|
||||
else
|
||||
wideChars.resize(1);
|
||||
|
||||
wideChars[wideChars.size() - 1] = static_cast<wchar_t>(0);
|
||||
|
||||
HGLOBAL textObject = GlobalAlloc(GMEM_MOVEABLE, wideChars.size() * sizeof(wchar_t));
|
||||
if (textObject)
|
||||
{
|
||||
wchar_t *buffer = static_cast<wchar_t*>(GlobalLock(textObject));
|
||||
memcpy(buffer, &wideChars[0], wideChars.size() * sizeof(wchar_t));
|
||||
GlobalUnlock(textObject);
|
||||
|
||||
SetClipboardData(CF_UNICODETEXT, textObject);
|
||||
}
|
||||
}
|
||||
|
||||
CloseClipboard();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GpSystemServices_Win32::SetTouchscreenSimulation(bool isTouchscreenSimulation)
|
||||
{
|
||||
|
||||
@@ -19,6 +19,7 @@ class GpSystemServices_Win32 final : public IGpSystemServices
|
||||
{
|
||||
public:
|
||||
GpSystemServices_Win32();
|
||||
~GpSystemServices_Win32();
|
||||
|
||||
int64_t GetTime() const override;
|
||||
void GetLocalDateTime(unsigned int &year, unsigned int &month, unsigned int &day, unsigned int &hour, unsigned int &minute, unsigned int &second) const override;
|
||||
@@ -36,6 +37,8 @@ public:
|
||||
void SetTextInputEnabled(bool isEnabled) override;
|
||||
bool IsTextInputEnabled() const override;
|
||||
bool AreFontResourcesSeekable() const override;
|
||||
IGpClipboardContents *GetClipboardContents() const override;
|
||||
void SetClipboardContents(IGpClipboardContents *contents) override;
|
||||
|
||||
void SetTouchscreenSimulation(bool isTouchscreenSimulation);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user