CtrlCore: New MT rules, window creation and event loop banned in non-main thread (win32 implementation)

git-svn-id: svn://ultimatepp.org/upp/trunk@6169 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2013-07-06 11:51:28 +00:00
parent b9cd98a689
commit a5cc4e2902
17 changed files with 71 additions and 252 deletions

View file

@ -590,10 +590,7 @@ private:
String GetInfoPart(int i) const;
// System window interface...
void WndShow0(bool b);
void WndShow(bool b);
void WndSetPos0(const Rect& rect);
void WndSetPos(const Rect& rect);
bool IsWndOpen() const;
@ -608,37 +605,29 @@ private:
static void DoKillFocus(Ptr<Ctrl> pfocusCtrl, Ptr<Ctrl> nfocusCtrl);
static void DoSetFocus(Ptr<Ctrl> pfocusCtrl, Ptr<Ctrl> nfocusCtrl, bool activate);
bool SetFocus0(bool activate);
void ActivateWnd();
void ClickActivateWnd();
bool SetFocus0(bool activate);
void SetWndFocus0(bool *b);
bool SetWndFocus();
bool HasWndFocus() const;
void WndInvalidateRect(const Rect& r);
void WndScrollView0(const Rect& r, int dx, int dy);
void WndScrollView(const Rect& r, int dx, int dy);
void SetWndForeground0();
void SetWndForeground();
bool IsWndForeground() const;
void WndEnable0(bool *b);
bool WndEnable(bool b);
void WndEnable(bool b);
Rect GetWndScreenRect() const;
void WndUpdate0();
void WndUpdate();
void WndUpdate0r(const Rect& r);
void WndUpdate(const Rect& r);
void WndFree();
void WndDestroy0();
void WndDestroy();
static void GuiSleep0(int ms);
void SysEndLoop();
static void InitTimer();
@ -1156,7 +1145,6 @@ public:
bool IsPopUp() const { return popup; }
static void EventLoop0(Ctrl *ctrl);
static void EventLoop(Ctrl *loopctrl = NULL);
static int GetLoopLevel() { return LoopLevel; }
static Ctrl *GetLoopCtrl() { return LoopCtrl; }

View file

@ -103,62 +103,4 @@ void Ctrl::Call(Callback 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

View file

@ -7,12 +7,6 @@ NAMESPACE_UPP
#define LLOG(x) // DLOG(x)
void Ctrl::Create(Ctrl *owner, bool popup)
{
LLOG("Create Call");
Call(callback2(this, &Ctrl::Create0, owner, popup));
}
void Ctrl::Create0(Ctrl *owner, bool popup)
{
GuiLock __;
ASSERT(IsMainThread());
@ -82,7 +76,7 @@ void Ctrl::Create0(Ctrl *owner, bool popup)
activeCtrl = this;
}
void Ctrl::WndDestroy0()
void Ctrl::WndDestroy()
{
GuiLock __;
LLOG("WndDestroy " << Name());

View file

@ -1,7 +1,5 @@
//$ class Ctrl {
void Create0(Ctrl *owner, bool popup);
void Create(Ctrl *owner, bool popup);
void PopUp0(Ctrl *owner, bool activate);
static gboolean GtkProc(GtkWidget *widget, GdkEvent *event, gpointer user_data);
static void IMCommit(GtkIMContext *context, gchar *str, gpointer user_data);

View file

@ -343,7 +343,7 @@ void Ctrl::FocusSync()
}
}
void Ctrl::SetWndFocus0(bool *b)
void Ctrl::SetWndFocus(bool *b)
{
GuiLock __;
LLOG("SetWndFocus0 " << Upp::Name(this) << ", top: " << top);
@ -413,7 +413,7 @@ void Ctrl::WndSetPos0(const Rect& rect)
LLOG("-- WndSetPos0 " << rect << " " << msecs() - t0);
}
void Ctrl::WndEnable0(bool *b)
void Ctrl::WndEnable(bool *b)
{
GuiLock __;
if(top) {
@ -422,14 +422,14 @@ void Ctrl::WndEnable0(bool *b)
}
}
void Ctrl::WndUpdate0r(const Rect& r)
void Ctrl::WndUpdate(const Rect& r)
{
GuiLock __;
LLOG("WndUpdate0r " << r);
WndUpdate0(); // Not found a way how to update only part of window
}
void Ctrl::WndUpdate0()
void Ctrl::WndUpdate()
{
GuiLock __;
LLOG("WndUpdate0");

View file

@ -70,7 +70,7 @@ LRESULT TopWindow::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
return Ctrl::WindowProc(message, wParam, lParam);
}
void TopWindow::SyncTitle0()
void TopWindow::SyncTitle()
{
GuiLock __;
LLOG("TopWindow::SyncTitle0 " << UPP::Name(this));
@ -95,7 +95,7 @@ void TopWindow::DeleteIco()
ico = lico = NULL;
}
void TopWindow::SyncCaption0()
void TopWindow::SyncCaption()
{
GuiLock __;
LLOG("TopWindow::SyncCaption " << UPP::Name(this));

View file

@ -66,16 +66,6 @@ bool TopWindow::IsShowEnabled() const
return true;
}
void TopWindow::SyncCaption()
{
Call(THISBACK(SyncCaption0));
}
void TopWindow::SyncTitle()
{
Call(THISBACK(SyncTitle0));
}
void TopWindow::DefaultBreak()
{
if(FindAction(IDCANCEL))

View file

@ -50,10 +50,8 @@ private:
Rect overlapped;
void SyncTitle0();
void SyncSizeHints();
void SyncTitle();
void SyncCaption0();
void SyncCaption();
void SetupRect();

View file

@ -148,11 +148,6 @@ String Ctrl::Name() const {
return s;
}
void Ctrl::WndCreateCaret(const Rect& cr)
{
Call(THISBACK1(WndCreateCaret0, cr));
}
END_UPP_NAMESPACE
#endif

View file

@ -4,7 +4,6 @@ private:
bool isdhctrl:1;
static void WndDestroyCaret();
void WndCreateCaret0(const Rect& cr);
void WndCreateCaret(const Rect& cr);
static bool GetMsg(MSG& msg);

View file

@ -485,119 +485,44 @@ Ctrl *Ctrl::GetActiveCtrl()
UDropTarget *NewUDropTarget(Ctrl *);
struct Ctrl::CreateBox {
HWND parent;
DWORD style;
DWORD exstyle;
bool savebits;
int show;
bool dropshadow;
};
void Ctrl::Create(HWND parent, DWORD style, DWORD exstyle, bool savebits, int show, bool dropshadow)
{
CreateBox cr;
cr.parent = parent;
cr.style = style;
cr.exstyle = exstyle;
cr.savebits = savebits;
cr.show = show;
cr.dropshadow = dropshadow;
Call(callback1(this, &Ctrl::Create0, &cr));
}
#if 0
void Ctrl::Create0(Ctrl::CreateBox *cr)
{
GuiLock __;
ASSERT(IsMainThread());
LLOG("Ctrl::Create(parent = " << (void *)parent << ") in " <<UPP::Name(this) << BeginIndent);
ASSERT(!IsChild() && !IsOpen());
Rect r = GetRect();
AdjustWindowRectEx(r, cr->style, FALSE, cr->exstyle);
isopen = true;
top = new Top;
ASSERT(!cr->parent || IsWindow(cr->parent));
if(!IsWinXP())
cr->dropshadow = false;
#ifdef PLATFORM_WINCE
if(parent)
top->hwnd = CreateWindowExW(cr->exstyle,
cr->savebits ? cr->dropshadow ? L"UPP-CLASS-SB-DS-W" : L"UPP-CLASS-SB-W"
: cr->dropshadow ? L"UPP-CLASS-DS-W" : L"UPP-CLASS-W",
L"", cr->style, r.left, r.top, r.Width(), r.Height(),
cr->parent, NULL, hInstance, this);
else
top->hwnd = CreateWindowW(L"UPP-CLASS-W",
L"", WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
cr->parent, NULL, hInstance, this);
#else
if(IsWinNT() && (!cr->parent || IsWindowUnicode(cr->parent)))
top->hwnd = CreateWindowExW(cr->exstyle,
cr->savebits ? cr->dropshadow ? L"UPP-CLASS-SB-DS-W" : L"UPP-CLASS-SB-W"
: cr->dropshadow ? L"UPP-CLASS-DS-W" : L"UPP-CLASS-W",
L"", cr->style, r.left, r.top, r.Width(), r.Height(),
cr->parent, NULL, hInstance, this);
else
top->hwnd = CreateWindowEx(cr->exstyle,
cr->savebits ? cr->dropshadow ? "UPP-CLASS-SB-DS-A" : "UPP-CLASS-SB-A"
: cr->dropshadow ? "UPP-CLASS-DS-A" : "UPP-CLASS-A",
"", cr->style, r.left, r.top, r.Width(), r.Height(),
cr->parent, NULL, hInstance, this);
#endif
inloop = false;
ASSERT(top->hwnd);
::ShowWindow(top->hwnd, visible ? cr->show : SW_HIDE);
// ::UpdateWindow(hwnd);
StateH(OPEN);
LLOG(EndIndent << "//Ctrl::Create in " <<UPP::Name(this));
RegisterDragDrop(top->hwnd, (LPDROPTARGET) (top->dndtgt = NewUDropTarget(this)));
CancelMode();
RefreshLayoutDeep();
}
#else
// Fix to avoid black corners temorarily artifact
void Ctrl::Create0(Ctrl::CreateBox *cr)
{
GuiLock __;
ASSERT(IsMainThread());
ASSERT_(IsMainThread(), "Window creation can only happen in the main thread");
LLOG("Ctrl::Create(parent = " << (void *)parent << ") in " <<UPP::Name(this) << LOG_BEGIN);
ASSERT(!IsChild() && !IsOpen());
Rect r = GetRect();
AdjustWindowRectEx(r, cr->style, FALSE, cr->exstyle);
AdjustWindowRectEx(r, style, FALSE, exstyle);
isopen = true;
top = new Top;
ASSERT(!cr->parent || IsWindow(cr->parent));
cr->style &= ~WS_VISIBLE;
ASSERT(!parent || IsWindow(parent));
style &= ~WS_VISIBLE;
if(!IsWinXP())
cr->dropshadow = false;
dropshadow = false;
#ifdef PLATFORM_WINCE
if(parent)
top->hwnd = CreateWindowExW(cr->exstyle,
cr->savebits ? cr->dropshadow ? L"UPP-CLASS-SB-DS-W" : L"UPP-CLASS-SB-W"
: cr->dropshadow ? L"UPP-CLASS-DS-W" : L"UPP-CLASS-W",
L"", cr->style, 0, 0, 0, 0,
cr->parent, NULL, hInstance, this);
top->hwnd = CreateWindowExW(exstyle,
savebits ? dropshadow ? L"UPP-CLASS-SB-DS-W" : L"UPP-CLASS-SB-W"
: dropshadow ? L"UPP-CLASS-DS-W" : L"UPP-CLASS-W",
L"", style, 0, 0, 0, 0,
parent, NULL, hInstance, this);
else
top->hwnd = CreateWindowW(L"UPP-CLASS-W",
L"", WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
cr->parent, NULL, hInstance, this);
parent, NULL, hInstance, this);
#else
if(IsWinNT() && (!cr->parent || IsWindowUnicode(cr->parent)))
top->hwnd = CreateWindowExW(cr->exstyle,
cr->savebits ? cr->dropshadow ? L"UPP-CLASS-SB-DS-W" : L"UPP-CLASS-SB-W"
: cr->dropshadow ? L"UPP-CLASS-DS-W" : L"UPP-CLASS-W",
L"", cr->style, 0, 0, 0, 0,
cr->parent, NULL, hInstance, this);
if(IsWinNT() && (!parent || IsWindowUnicode(parent)))
top->hwnd = CreateWindowExW(exstyle,
savebits ? dropshadow ? L"UPP-CLASS-SB-DS-W" : L"UPP-CLASS-SB-W"
: dropshadow ? L"UPP-CLASS-DS-W" : L"UPP-CLASS-W",
L"", style, 0, 0, 0, 0,
parent, NULL, hInstance, this);
else
top->hwnd = CreateWindowEx(cr->exstyle,
cr->savebits ? cr->dropshadow ? "UPP-CLASS-SB-DS-A" : "UPP-CLASS-SB-A"
: cr->dropshadow ? "UPP-CLASS-DS-A" : "UPP-CLASS-A",
"", cr->style, 0, 0, 0, 0,
cr->parent, NULL, hInstance, this);
top->hwnd = CreateWindowEx(exstyle,
savebits ? dropshadow ? "UPP-CLASS-SB-DS-A" : "UPP-CLASS-SB-A"
: dropshadow ? "UPP-CLASS-DS-A" : "UPP-CLASS-A",
"", style, 0, 0, 0, 0,
parent, NULL, hInstance, this);
#endif
inloop = false;
@ -605,7 +530,7 @@ void Ctrl::Create0(Ctrl::CreateBox *cr)
ASSERT(top->hwnd);
::MoveWindow(top->hwnd, r.left, r.top, r.Width(), r.Height(), false); // To avoid "black corners" artifact effect
::ShowWindow(top->hwnd, visible ? cr->show : SW_HIDE);
::ShowWindow(top->hwnd, visible ? show : SW_HIDE);
// ::UpdateWindow(hwnd);
StateH(OPEN);
LLOG(LOG_END << "//Ctrl::Create in " <<UPP::Name(this));
@ -614,8 +539,6 @@ void Ctrl::Create0(Ctrl::CreateBox *cr)
RefreshLayoutDeep();
}
#endif
void ReleaseUDropTarget(UDropTarget *dt);
void Ctrl::WndFree()
@ -640,7 +563,7 @@ void Ctrl::WndFree()
top = NULL;
}
void Ctrl::WndDestroy0()
void Ctrl::WndDestroy()
{
GuiLock __;
if(top && top->hwnd) {
@ -884,10 +807,10 @@ bool Ctrl::ProcessEvents(bool *quit)
return false;
}
void Ctrl::EventLoop0(Ctrl *ctrl)
void Ctrl::EventLoop(Ctrl *ctrl)
{
GuiLock __;
ASSERT(IsMainThread());
ASSERT_(IsMainThread(), "Event loop can only run in the main thread");
ASSERT(LoopLevel == 0 || ctrl);
LoopLevel++;
LLOG("Entering event loop at level " << LoopLevel << LOG_BEGIN);
@ -917,7 +840,7 @@ void Ctrl::EventLoop0(Ctrl *ctrl)
LLOG(LOG_END << "Leaving event loop ");
}
void Ctrl::GuiSleep0(int ms)
void Ctrl::GuiSleep(int ms)
{
GuiLock __;
ASSERT(IsMainThread());
@ -946,7 +869,7 @@ void Ctrl::WndDestroyCaret()
::DestroyCaret();
}
void Ctrl::WndCreateCaret0(const Rect& cr)
void Ctrl::WndCreateCaret(const Rect& cr)
{
GuiLock __;
LLOG("Ctrl::WndCreateCaret(" << cr << ") in " << UPP::Name(this));
@ -971,7 +894,7 @@ Rect Ctrl::GetWndScreenRect() const
return r;
}
void Ctrl::WndShow0(bool b)
void Ctrl::WndShow(bool b)
{
GuiLock __;
HWND hwnd = GetHWND();
@ -979,7 +902,7 @@ void Ctrl::WndShow0(bool b)
::ShowWindow(hwnd, b ? SW_SHOW : SW_HIDE);
}
void Ctrl::WndUpdate0()
void Ctrl::WndUpdate()
{
GuiLock __;
HWND hwnd = GetHWND();
@ -1117,7 +1040,7 @@ int Ctrl::GetKbdSpeed()
#endif
}
void Ctrl::SetWndForeground0()
void Ctrl::SetWndForeground()
{
GuiLock __;
LLOG("Ctrl::SetWndForeground() in " << UPP::Name(this));
@ -1142,16 +1065,16 @@ bool Ctrl::IsWndForeground() const
return hwnd == fore;
}
void Ctrl::WndEnable0(bool *b)
void Ctrl::WndEnable(bool b)
{
GuiLock __;
LLOG("Ctrl::WndEnable(" << (b && *b) << ") in " << UPP::Name(this) << ", focusCtrlWnd = " << UPP::Name(~focusCtrlWnd) << ", raw = " << (void *)::GetFocus());
if(*b)
if(b)
ReleaseCapture();
LLOG("//Ctrl::WndEnable(" << (b && *b) << ") -> false " <<UPP::Name(this) << ", focusCtrlWnd = " <<UPP::Name(~focusCtrlWnd) << ", raw = " << (void *)::GetFocus());
}
void Ctrl::SetWndFocus0(bool *b)
bool Ctrl::SetWndFocus()
{
GuiLock __;
LLOG("Ctrl::SetWndFocus() in " << UPP::Name(this));
@ -1160,11 +1083,10 @@ void Ctrl::SetWndFocus0(bool *b)
LLOG("Ctrl::SetWndFocus() -> ::SetFocus(" << (void *)hwnd << ")");
// ::SetActiveWindow(hwnd);
::SetFocus(hwnd);
*b = true;
return;
return true;
}
LLOG("//Ctrl::SetWndFocus() in " <<UPP::Name(this) << ", active window = " << (void *)::GetActiveWindow());
*b = false;
return false;
}
bool Ctrl::HasWndFocus() const
@ -1219,7 +1141,7 @@ void Ctrl::WndInvalidateRect(const Rect& r)
::InvalidateRect(hwnd, r, false);
}
void Ctrl::WndSetPos0(const Rect& rect)
void Ctrl::WndSetPos(const Rect& rect)
{
GuiLock __;
LLOG("WndSetPos " << UPP::Name(this));
@ -1238,7 +1160,7 @@ void Ctrl::WndSetPos0(const Rect& rect)
fullrefresh = false;
}
void Ctrl::WndUpdate0r(const Rect& r)
void Ctrl::WndUpdate(const Rect& r)
{
GuiLock __;
LLOG("WndUpdate " << UPP::Name(this));
@ -1264,7 +1186,7 @@ void Ctrl::WndUpdate0r(const Rect& r)
}
}
void Ctrl::WndScrollView0(const Rect& r, int dx, int dy)
void Ctrl::WndScrollView(const Rect& r, int dx, int dy)
{
GuiLock __;
LLOG("WndScrollView " << UPP::Name(this));

View file

@ -49,7 +49,6 @@ private:
protected:
void Create(Ctrl *owner, bool redirect, bool savebits);
void Create0(Ctrl *owner, bool redirect, bool savebits);
void SyncExpose();
void TakeFocus();
static Window GetXServerFocusWindow();

View file

@ -148,11 +148,6 @@ void TopWindow::SyncState0()
}
}
void TopWindow::SyncState()
{
Call(THISBACK(SyncState0));
}
typedef struct {
unsigned long flags;
unsigned long functions;
@ -262,7 +257,7 @@ void TopWindow::CenterRect(Ctrl *owner)
void TopWindow::Open(Ctrl *owner)
{
Call(PTEBACK1(Open0, owner));
Open0(owner);
}
void TopWindow::Open0(Ctrl *owner)

View file

@ -13,9 +13,6 @@ private:
void EndIgnoreTakeFocus();
void SyncState();
void SyncState0();
void Open0(Ctrl *owner);
Image invert;
WString title2;

View file

@ -420,7 +420,7 @@ void Ctrl::SysEndLoop()
void Ctrl::EventLoop0(Ctrl *ctrl)
{
GuiLock __;
ASSERT(IsMainThread());
ASSERT_(IsMainThread(), "Event loop can only run in the main thread");
ASSERT(LoopLevel == 0 || ctrl);
LoopLevel++;
int64 loopno = ++EventLoopNo;
@ -464,14 +464,9 @@ void Ctrl::SyncExpose()
}
void Ctrl::Create(Ctrl *owner, bool redirect, bool savebits)
{
Call(callback3(this, &Ctrl::Create0, owner, redirect, savebits));
}
void Ctrl::Create0(Ctrl *owner, bool redirect, bool savebits)
{
GuiLock __;
ASSERT(IsMainThread());
ASSERT(IsMainThread(), "Only main thread can create windows");
LLOG("Create " << Name() << " " << GetRect());
ASSERT(!IsChild() && !IsOpen());
LLOG("Ungrab1");
@ -534,7 +529,7 @@ void Ctrl::Create0(Ctrl *owner, bool redirect, bool savebits)
SyncIMPosition();
}
void Ctrl::WndDestroy0()
void Ctrl::WndDestroy()
{
GuiLock __;
LLOG("WndDestroy " << Name());

View file

@ -521,7 +521,7 @@ DisplayPopup::~DisplayPopup()
void DisplayPopup::Sync()
{
if(!IsMainThread()) {
PostCallback(THISBACK(Sync));
PostCallback(PTEBACK(Sync));
return;
}
if(display && ctrl && !ctrl->IsDragAndDropTarget() && !IsDragAndDropTarget()) {

View file

@ -28,6 +28,20 @@ static void sAdd(Ctrl& dlg, int fcy, int bcy, int& bx, int bcx, int gap, Button&
}
}
void sExecutePrompt(PromptDlgWnd__ *dlg, int *result)
{
dlg->Open();
Vector<Ctrl *> wins = Ctrl::GetTopWindows();
for(int i = 0; i < wins.GetCount(); i++) {
TopWindow *w = dynamic_cast<TopWindow *>(wins[i]);
if(w && w->IsTopMost()) {
dlg->TopMost();
break;
}
}
*result = dlg->RunAppModal();
}
int Prompt(Callback1<const String&> WhenLink,
const char *title, const Image& iconbmp, const char *qtf, bool okcancel,
const char *button1, const char *button2, const char *button3,
@ -106,17 +120,10 @@ int Prompt(Callback1<const String&> WhenLink,
sAdd(dlg, fcy, bcy, bx, bcx, gap, b3, button3, im3);
}
dlg.WhenClose = dlg.Breaker(button3 ? -1 : 0);
dlg.Open();
Vector<Ctrl *> wins = Ctrl::GetTopWindows();
for(int i = 0; i < wins.GetCount(); i++) {
TopWindow *w = dynamic_cast<TopWindow *>(wins[i]);
if(w && w->IsTopMost()) {
dlg.TopMost();
break;
}
}
dlg.Title(title);
return dlg.RunAppModal();
int result;
Ctrl::Call(callback2(sExecutePrompt, &dlg, &result));
return result;
}
int Prompt(Callback1<const String&> WhenLink,