mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-15 22:02:49 -06:00
161 lines
2.3 KiB
C++
161 lines
2.3 KiB
C++
#include "CtrlCore.h"
|
|
|
|
#define LLOG(x) // DLOG(x)
|
|
|
|
NAMESPACE_UPP
|
|
|
|
#ifdef _MULTITHREADED
|
|
|
|
static StaticMutex sGLock;
|
|
|
|
static thread__ int sGLockLevel = 0;
|
|
|
|
void EnterGuiMutex()
|
|
{
|
|
if(sGLockLevel++ == 0)
|
|
sGLock.Enter();
|
|
LLOG("EnterGuiMutex " << sGLockLevel);
|
|
}
|
|
|
|
void EnterGuiMutex(int n)
|
|
{
|
|
if(n > 0) {
|
|
if(sGLockLevel == 0)
|
|
sGLock.Enter();
|
|
sGLockLevel += n;
|
|
}
|
|
LLOG("EnterGuiMutex " << sGLockLevel);
|
|
}
|
|
|
|
void LeaveGuiMutex()
|
|
{
|
|
ASSERT(sGLockLevel > 0);
|
|
if(--sGLockLevel == 0)
|
|
sGLock.Leave();
|
|
LLOG("LeaveGuiMutex " << sGLockLevel);
|
|
}
|
|
|
|
int LeaveGuiMutexAll()
|
|
{
|
|
int q = sGLockLevel;
|
|
if(q) {
|
|
sGLock.Leave();
|
|
sGLockLevel = 0;
|
|
}
|
|
LLOG("LeaveGuiMutex all " << q);
|
|
return q;
|
|
}
|
|
|
|
bool ThreadHasGuiLock()
|
|
{
|
|
return Thread::IsMain() || sGLockLevel;
|
|
}
|
|
|
|
void WakeUpGuiThread();
|
|
|
|
struct Ctrl::CallBox {
|
|
Semaphore sem;
|
|
Callback cb;
|
|
};
|
|
|
|
void Ctrl::PerformCall(Ctrl::CallBox *cbox)
|
|
{
|
|
cbox->cb();
|
|
LLOG("Sem release");
|
|
cbox->sem.Release();
|
|
}
|
|
|
|
void Ctrl::Call(Callback cb)
|
|
{
|
|
if(IsMainThread())
|
|
cb();
|
|
else {
|
|
int ms = msecs();
|
|
CallBox cbox;
|
|
cbox.cb = cb;
|
|
UPP::PostCallback(callback1(PerformCall, &cbox));
|
|
WakeUpGuiThread();
|
|
int level = LeaveGuiMutexAll(); // Unlock GUI to give main thread chance to handle Call
|
|
cbox.sem.Wait();
|
|
EnterGuiMutex(level);
|
|
}
|
|
}
|
|
|
|
void Ctrl::ShutdownThreads()
|
|
{
|
|
Thread::BeginShutdownThreads();
|
|
while(Thread::GetCount()) {
|
|
ProcessEvents();
|
|
Sleep(0);
|
|
}
|
|
Thread::EndShutdownThreads();
|
|
}
|
|
|
|
#else
|
|
|
|
void Ctrl::Call(Callback cb)
|
|
{
|
|
cb();
|
|
}
|
|
|
|
#endif
|
|
|
|
void Ctrl::GuiSleep(int ms)
|
|
{
|
|
Call(callback1(&Ctrl::GuiSleep0, ms));
|
|
}
|
|
|
|
void Ctrl::WndDestroy()
|
|
{
|
|
Call(PTEBACK(WndDestroy0));
|
|
}
|
|
|
|
void Ctrl::WndShow(bool b)
|
|
{
|
|
Call(PTEBACK1(WndShow0, b));
|
|
}
|
|
|
|
void Ctrl::WndUpdate()
|
|
{
|
|
Call(PTEBACK(WndUpdate0));
|
|
}
|
|
|
|
void Ctrl::SetWndForeground()
|
|
{
|
|
Call(PTEBACK(SetWndForeground0));
|
|
}
|
|
|
|
bool Ctrl::WndEnable(bool b)
|
|
{
|
|
Call(PTEBACK1(WndEnable0, &b));
|
|
return b;
|
|
}
|
|
|
|
bool Ctrl::SetWndFocus()
|
|
{
|
|
bool b;
|
|
Call(PTEBACK1(SetWndFocus0, &b));
|
|
return b;
|
|
}
|
|
|
|
void Ctrl::WndSetPos(const Rect& rect)
|
|
{
|
|
Call(PTEBACK1(WndSetPos0, rect));
|
|
}
|
|
|
|
void Ctrl::WndUpdate(const Rect& r)
|
|
{
|
|
Call(PTEBACK1(WndUpdate0r, r));
|
|
}
|
|
|
|
void Ctrl::WndScrollView(const Rect& r, int dx, int dy)
|
|
{
|
|
Call(PTEBACK3(WndScrollView0, r, dx, dy));
|
|
}
|
|
|
|
void Ctrl::EventLoop(Ctrl *ctrl)
|
|
{
|
|
Call(callback1(&Ctrl::EventLoop0, ctrl));
|
|
}
|
|
|
|
END_UPP_NAMESPACE
|