CtrlCore: Massive fix of MT, Draw: Fixed DrawingDraw::Create for case when tehere are some data in DrawingDraw

git-svn-id: svn://ultimatepp.org/upp/trunk@1506 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2009-08-13 13:40:54 +00:00
parent 8c030b0c5a
commit 1205935960
16 changed files with 281 additions and 93 deletions

View file

@ -30,8 +30,8 @@ struct CallbackMethodActionArg : public CallbackAction {
void Execute() { (object->*method)(arg); }
CallbackMethodActionArg(OBJECT_ *object, METHOD_ method, T arg)
: object(object), method(method), arg(arg) {}
CallbackMethodActionArg(OBJECT_ *object, METHOD_ method, T arg_)
: object(object), method(method) { arg = arg_; }
};
template <class Object, class M, class P, class T>

View file

@ -577,9 +577,17 @@ private:
void SetInfoPart(int i, const char *txt);
String GetInfoPart(int i) const;
static Callback CtrlCall;
static bool DoCall();
static bool PeekMsg(MSG& msg);
// System window interface...
void WndShow0(bool b);
void WndShow(bool b);
void WndSetPos0(const Rect& rect);
void WndSetPos(const Rect& rect);
bool IsWndOpen() const;
@ -597,23 +605,31 @@ private:
void ActivateWnd();
void ClickActivateWnd();
bool SetFocus0(bool activate);
void SetWndFocus0(bool *b);
bool SetWndFocus();
bool HasWndFocus() const;
static void WndDestroyCaret();
void WndCreateCaret0(const Rect& cr);
void WndCreateCaret(const Rect& cr);
void WndInvalidateRect0(const Rect& r);
void WndInvalidateRect(const Rect& r);
void SetWndForeground0();
void SetWndForeground();
bool IsWndForeground() const;
void WndEnable0(bool *b);
bool WndEnable(bool b);
Rect GetWndUpdateRect() const;
Rect GetWndScreenRect() const;
void WndScrollView0(const Rect& r, int dx, int dy);
void WndScrollView(const Rect& r, int dx, int dy);
void WndUpdate0();
void WndUpdate();
void WndUpdate0r(const Rect& r);
void WndUpdate(const Rect& r);
void WndFree();
@ -631,6 +647,8 @@ private:
static void Csizeinit();
static void (*skin)();
static void ICall(Callback cb);
friend void CtrlSetDefaultSkin(void (*fn1)(), void (*fn2)());
friend class DHCtrl;
friend class ViewDraw;
@ -674,6 +692,8 @@ protected:
Image DoMouse(int e, Point p, int zd = 0);
friend void sSetCursor(Ctrl *ctrl, const Image& m);
typedef Ctrl CLASSNAME;
public:
virtual void NcCreate(HWND hwnd);
@ -1235,10 +1255,10 @@ public:
void PostCallback(Callback cb, int id = 0);
void KillPostCallback(Callback cb, int id);
static void Call(Callback cb);
enum { TIMEID_COUNT = 1 };
static void Call(Callback cb);
static void SetTimerGranularity(int ms);
static Ctrl *GetActiveCtrl();

View file

@ -50,6 +50,7 @@ file
X11Keys.i,
MKeys.h,
Frame.cpp,
CtrlMt.cpp,
Ctrl.cpp,
CtrlChild.cpp,
CtrlPos.cpp,

192
uppsrc/CtrlCore/CtrlMt.cpp Normal file
View file

@ -0,0 +1,192 @@
#include "CtrlCore.h"
#define LLOG(x) // LOG(x)
NAMESPACE_UPP
#ifdef _MULTITHREADED
static int NonMain;
static StaticMutex NonMainLock;
void EnterGuiMutex()
{
LLOG("Thread " << IsMainThread() << " trying to lock");
bool nonmain = !IsMainThread();
if(nonmain)
NonMainLock.Enter();
EnterGMutex();
if(nonmain)
NonMain++;
LLOG("Thread " << IsMainThread() << " LOCK");
}
void LeaveGuiMutex()
{
LLOG("Thread " << IsMainThread() << " trying to unlock");
bool nonmain = !IsMainThread();
if(nonmain)
NonMain--;
LeaveGMutex();
if(nonmain)
NonMainLock.Leave();
LLOG("Thread " << IsMainThread() << " UNLOCK");
}
struct Ctrl::CallBox {
Semaphore sem;
Callback cb;
};
void Ctrl::PerformCall(Ctrl::CallBox *cbox)
{
cbox->cb();
LLOG("Sem release");
cbox->sem.Release();
}
Callback Ctrl::CtrlCall;
void WakeUpGuiThread();
bool Ctrl::DoCall()
{
LLOG("DoCall");
CtrlCall();
CtrlCall.Clear();
LLOG("--- DoCall, nonmain: " << NonMain);
return NonMain;
}
void Ctrl::ICall(Callback cb)
{
LLOG("Ctrl::Call " << IsMainThread() << ", nonmain: " << NonMain);
if(IsMainThread())
cb();
else {
CallBox cbox;
cbox.cb = cb;
CtrlCall = callback1(PerformCall, &cbox);
int level = LeaveGMutexAll();
WakeUpGuiThread();
LLOG("Waiting for semaphore");
if(!Thread::IsShutdownThreads())
cbox.sem.Wait();
EnterGMutex(level);
}
LLOG("-- Ctrl::Call " << IsMainThread());
}
void Ctrl::Call(Callback cb)
{
if(IsMainThread())
cb();
else {
CallBox cbox;
DLOG("EventLoop 1");
cbox.cb = cb;
DLOG("EventLoop 2");
UPP::PostCallback(callback1(PerformCall, &cbox));
int n = NonMain;
int nn = n;
NonMain = 0;
for(int i = 0; i < n; i++)
NonMainLock.Leave();
int level = LeaveGMutexAll();
WakeUpGuiThread();
if(!Thread::IsShutdownThreads())
cbox.sem.Wait();
for(int i = 0; i < n; i++)
NonMainLock.Enter();
EnterGMutex(level);
NonMain = n;
}
}
#else
bool Ctrl::DoCall()
{
return false;
}
void Ctrl::ICall(Callback cb)
{
cb();
}
void Ctrl::Call(Callback cb)
{
cb();
}
#endif
void Ctrl::GuiSleep(int ms)
{
Call(callback1(&Ctrl::GuiSleep0, ms));
}
void Ctrl::WndDestroy()
{
ICall(callback(this, &Ctrl::WndDestroy0));
}
void Ctrl::WndCreateCaret(const Rect& cr)
{
ICall(THISBACK1(WndCreateCaret0, cr));
}
void Ctrl::WndShow(bool b)
{
ICall(THISBACK1(WndShow0, b));
}
void Ctrl::WndUpdate()
{
ICall(THISBACK(WndUpdate0));
}
void Ctrl::SetWndForeground()
{
ICall(THISBACK(SetWndForeground0));
}
bool Ctrl::WndEnable(bool b)
{
ICall(THISBACK1(WndEnable0, &b));
return b;
}
bool Ctrl::SetWndFocus()
{
bool b;
ICall(THISBACK1(SetWndFocus0, &b));
return b;
}
void Ctrl::WndInvalidateRect(const Rect& r)
{
ICall(THISBACK1(WndInvalidateRect0, r));
}
void Ctrl::WndSetPos(const Rect& rect)
{
ICall(THISBACK1(WndSetPos0, rect));
}
void Ctrl::WndUpdate(const Rect& r)
{
ICall(THISBACK1(WndUpdate0r, r));
}
void Ctrl::WndScrollView(const Rect& r, int dx, int dy)
{
ICall(THISBACK3(WndScrollView0, r, dx, dy));
}
void Ctrl::EventLoop(Ctrl *ctrl)
{
Call(callback1(&Ctrl::EventLoop0, ctrl));
}
END_UPP_NAMESPACE

View file

@ -176,54 +176,4 @@ int Ctrl::GetExitCode() const
return exitcode;
}
#ifdef _MULTITHREADED
struct Ctrl::CallBox {
Semaphore sem;
Callback cb;
};
void Ctrl::PerformCall(Ctrl::CallBox *cbox)
{
cbox->cb();
cbox->sem.Release();
}
void WakeUpGuiThread();
void Ctrl::Call(Callback cb)
{
if(IsMainThread())
cb();
else {
CallBox cbox;
cbox.cb = cb;
UPP::PostCallback(callback1(Ctrl::PerformCall, &cbox));
WakeUpGuiThread();
int level = LeaveGuiMutexAll();
cbox.sem.Wait();
EnterGuiMutex(level);
}
}
#else
void Ctrl::Call(Callback cb)
{
cb();
}
#endif
void Ctrl::EventLoop(Ctrl *ctrl)
{
Call(callback1(&Ctrl::EventLoop0, ctrl));
}
void Ctrl::WndDestroy()
{
Call(callback(this, &Ctrl::WndDestroy0));
}
void Ctrl::GuiSleep(int ms)
{
Call(callback1(&Ctrl::GuiSleep0, ms));
}
END_UPP_NAMESPACE

View file

@ -10,12 +10,18 @@
NAMESPACE_UPP
typedef DrawLock GuiLock;
#ifdef _MULTITHREADED
void EnterGuiMutex();
void LeaveGuiMutex();
#else
inline void EnterGuiMutex() {}
inline void LeaveGuiMutex() {}
#endif
inline void EnterGuiMutex() { EnterGMutex(); }
inline void EnterGuiMutex(int n) { EnterGMutex(n); }
inline void LeaveGuiMutex() { LeaveGMutex(); }
inline int LeaveGuiMutexAll() { return LeaveGMutexAll(); }
struct GuiLock {
GuiLock() { EnterGuiMutex(); }
~GuiLock() { LeaveGuiMutex(); }
};
bool ScreenInPaletteMode();
Size GetScreenSize();

View file

@ -76,7 +76,7 @@ void TopWindow::DeleteIco0()
void TopWindow::DeleteIco()
{
Call(THISBACK(DeleteIco0));
ICall(THISBACK(DeleteIco0));
}
void TopWindow::SyncCaption0()

View file

@ -66,12 +66,12 @@ bool TopWindow::IsShowEnabled() const
void TopWindow::SyncCaption()
{
Call(THISBACK(SyncCaption0));
ICall(THISBACK(SyncCaption0));
}
void TopWindow::SyncTitle()
{
Call(THISBACK(SyncTitle0));
ICall(THISBACK(SyncTitle0));
}
void TopWindow::Close()

View file

@ -501,11 +501,11 @@ int Ctrl::DoDragAndDrop(const char *fmts, const Image& sample, dword actions,
if(actions & DND_MOVE)
dsrc->move = actions & DND_EXACTIMAGE ? sample : MakeDragImage(CtrlCoreImg::DndMove(), CtrlCoreImg::DndMove98(), sample);
sDnDSource = this;
int level = LeaveGuiMutexAll();
int level = LeaveGMutexAll();
HRESULT r = DoDragDrop(obj, dsrc,
(actions & DND_COPY ? DROPEFFECT_COPY : 0) |
(actions & DND_MOVE ? DROPEFFECT_MOVE : 0), &result);
EnterGuiMutex(level);
EnterGMutex(level);
DWORD re = obj->effect;
obj->Release();
dsrc->Release();

View file

@ -19,7 +19,7 @@ unsigned GetHashValue(const HWND& h)
return (unsigned)(intptr_t)h;
}
static bool PeekMsg(MSG& msg)
bool Ctrl::PeekMsg(MSG& msg)
{
if(!PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) return false;
return IsWindowUnicode(msg.hwnd) ? PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)
@ -28,6 +28,11 @@ static bool PeekMsg(MSG& msg)
static bool sFinished;
bool IsExiting()
{
return sFinished;
}
static BOOL CALLBACK sDumpWindow(HWND hwnd, LPARAM lParam) {
String dump;
dump << (IsWindowEnabled(hwnd) ? "ena" : "dis") << ' '
@ -427,7 +432,7 @@ void Ctrl::Create(HWND parent, DWORD style, DWORD exstyle, bool savebits, int sh
cr.savebits = savebits;
cr.show = show;
cr.dropshadow = dropshadow;
Call(callback1(this, &Ctrl::Create0, &cr));
ICall(callback1(this, &Ctrl::Create0, &cr));
}
void Ctrl::Create0(Ctrl::CreateBox *cr)
@ -684,6 +689,8 @@ bool Ctrl::IsWaitingEvent()
bool Ctrl::ProcessEvent(bool *quit)
{
if(DoCall())
return false;
if(EndSession())
return false;
if(!GetMouseLeft() && !GetMouseRight() && !GetMouseMiddle())
@ -756,7 +763,7 @@ void Ctrl::GuiSleep0(int ms)
if(EndSession())
return;
ELOG("GuiSleep 2");
int level = LeaveGuiMutexAll();
int level = LeaveGMutexAll();
#if !defined(flagDLL) && !defined(PLATFORM_WINCE)
if(!OverwatchThread) {
DWORD dummy;
@ -771,7 +778,7 @@ void Ctrl::GuiSleep0(int ms)
#else
MsgWaitForMultipleObjects(0, NULL, FALSE, ms, QS_ALLINPUT);
#endif
EnterGuiMutex(level);
EnterGMutex(level);
}
void Ctrl::WndDestroyCaret()
@ -780,7 +787,7 @@ void Ctrl::WndDestroyCaret()
::DestroyCaret();
}
void Ctrl::WndCreateCaret(const Rect& cr)
void Ctrl::WndCreateCaret0(const Rect& cr)
{
GuiLock __;
LLOG("Ctrl::WndCreateCaret(" << cr << ") in " << UPP::Name(this));
@ -815,7 +822,7 @@ Rect Ctrl::GetWndScreenRect() const
return r;
}
void Ctrl::WndShow(bool b)
void Ctrl::WndShow0(bool b)
{
GuiLock __;
HWND hwnd = GetHWND();
@ -823,7 +830,7 @@ void Ctrl::WndShow(bool b)
::ShowWindow(hwnd, b ? SW_SHOW : SW_HIDE);
}
void Ctrl::WndUpdate()
void Ctrl::WndUpdate0()
{
GuiLock __;
HWND hwnd = GetHWND();
@ -961,7 +968,7 @@ int Ctrl::GetKbdSpeed()
#endif
}
void Ctrl::SetWndForeground()
void Ctrl::SetWndForeground0()
{
GuiLock __;
LLOG("Ctrl::SetWndForeground() in " << UPP::Name(this));
@ -986,33 +993,29 @@ bool Ctrl::IsWndForeground() const
return hwnd == fore;
}
bool Ctrl::WndEnable(bool b)
void Ctrl::WndEnable0(bool *b)
{
GuiLock __;
LLOG("Ctrl::WndEnable(" << b << ") in " << UPP::Name(this) << ", focusCtrlWnd = " << UPP::Name(focusCtrlWnd) << ", raw = " << (void *)::GetFocus());
HWND hwnd = GetHWND();
if(!b) {
if(*b)
ReleaseCapture();
LLOG("//Ctrl::WndEnable(" << b << ") -> true " << UPP::Name(this) << ", focusCtrlWnd = " <<UPP::Name(focusCtrlWnd) << ", raw = " << (void *)::GetFocus());
return true;
}
LLOG("//Ctrl::WndEnable(" << b << ") -> false " <<UPP::Name(this) << ", focusCtrlWnd = " <<UPP::Name(focusCtrlWnd) << ", raw = " << (void *)::GetFocus());
return false;
}
bool Ctrl::SetWndFocus()
void Ctrl::SetWndFocus0(bool *b)
{
GuiLock __;
LLOG("Ctrl::SetWndFocus() in " <<UPP::Name(this));
LLOG("Ctrl::SetWndFocus() in " << UPP::Name(this));
HWND hwnd = GetHWND();
if(hwnd) {
LLOG("Ctrl::SetWndFocus() -> ::SetFocus(" << (void *)hwnd << ")");
// ::SetActiveWindow(hwnd);
::SetFocus(hwnd);
return true;
*b = true;
return;
}
LLOG("//Ctrl::SetWndFocus() in " <<UPP::Name(this) << ", active window = " << (void *)::GetActiveWindow());
return false;
*b = false;
}
bool Ctrl::HasWndFocus() const
@ -1025,6 +1028,7 @@ bool Ctrl::HasWndFocus() const
bool Ctrl::SetWndCapture()
{
GuiLock __;
ASSERT(IsMainThread());
HWND hwnd = GetHWND();
if(hwnd) {
::SetCapture(hwnd);
@ -1036,6 +1040,7 @@ bool Ctrl::SetWndCapture()
bool Ctrl::ReleaseWndCapture()
{
GuiLock __;
ASSERT(IsMainThread());
HWND hwnd = GetHWND();
if(hwnd && HasWndCapture())
{
@ -1052,7 +1057,7 @@ bool Ctrl::HasWndCapture() const
return hwnd && hwnd == ::GetCapture();
}
void Ctrl::WndInvalidateRect(const Rect& r)
void Ctrl::WndInvalidateRect0(const Rect& r)
{
GuiLock __;
HWND hwnd = GetHWND();
@ -1060,7 +1065,8 @@ void Ctrl::WndInvalidateRect(const Rect& r)
::InvalidateRect(hwnd, r, false);
}
void Ctrl::WndSetPos(const Rect& rect) {
void Ctrl::WndSetPos0(const Rect& rect)
{
GuiLock __;
HWND hwnd = GetHWND();
if(hwnd) {
@ -1077,7 +1083,7 @@ void Ctrl::WndSetPos(const Rect& rect) {
fullrefresh = false;
}
void Ctrl::WndUpdate(const Rect& r)
void Ctrl::WndUpdate0r(const Rect& r)
{
GuiLock __;
Ctrl *top = GetTopCtrl();
@ -1102,7 +1108,7 @@ void Ctrl::WndUpdate(const Rect& r)
}
}
void Ctrl::WndScrollView(const Rect& r, int dx, int dy)
void Ctrl::WndScrollView0(const Rect& r, int dx, int dy)
{
GuiLock __;
if(caretCtrl && caretCtrl->GetTopCtrl() == this) {

View file

@ -316,7 +316,7 @@ void Ctrl::GuiSleep0(int ms)
XFlush(Xdisplay);
int level = LeaveGuiMutexAll();
select(Xconnection + 1, &fdset, NULL, NULL, &timeout);
EnterGuiMutex(level);
PerformCall();
}
static int granularity = 10;
@ -352,7 +352,7 @@ void Ctrl::EventLoop0(Ctrl *ctrl)
XFlush(Xdisplay);
int level = LeaveGuiMutexAll();
select(Xconnection + 1, &fdset, NULL, NULL, &timeout);
EnterGuiMutex(level);
PerformCall();
// GuiSleep()(granularity);
SyncMousePos();
while(IsWaitingEvent()) {

View file

@ -3,7 +3,7 @@
#include "Draw/init"
#include "plugin\bmp/init"
#include "RichText/init"
#define BLITZ_INDEX__ F954E548320E416A17CC47CC892FCB8F0
#define BLITZ_INDEX__ F71CCEAF25FEB111BA55475221D3F3383
#include "CtrlCore.icpp"
#undef BLITZ_INDEX__
#endif

View file

@ -560,9 +560,13 @@ bool IsEmptyImage(const Image& m)
Image GtkThemeIcon(const char *name, int size)
{
<<<<<<< .mine
Image m = GetGTK(gtk__parent(), size, 0, name, GTK_THEMEICON, 0, 0);
=======
Image m = GetGTK(gtk__parent(), size ? GTK_ICON_SIZE_LARGE_TOOLBAR
: GTK_ICON_SIZE_SMALL_TOOLBAR,
0, name, GTK_THEMEICON, 0, 0);
>>>>>>> .r1505
Size sz = m.GetSize();
int rsz = size ? 48 : 16;
if(sz.cx > rsz || sz.cy > rsz)

View file

@ -450,9 +450,11 @@ void DisplayPopup::Paint(Draw& w)
{
Rect r = GetSize();
w.DrawRect(r, SColorPaper);
display->PaintBackground(w, r, value, ink, paper, style);
r.left += margin;
display->Paint(w, r, value, ink, paper, style);
if(display) {
display->PaintBackground(w, r, value, ink, paper, style);
r.left += margin;
display->Paint(w, r, value, ink, paper, style);
}
}
DisplayPopup::DisplayPopup()

View file

@ -1,5 +1,7 @@
#include "Draw.h"
#define LLOG(x)
NAMESPACE_UPP
#ifdef _MULTITHREADED
@ -12,6 +14,7 @@ void EnterGMutex()
{
if(sGLockLevel++ == 0)
sGLock.Enter();
LLOG("EnterGMutex");
}
void EnterGMutex(int n)
@ -21,6 +24,7 @@ void EnterGMutex(int n)
sGLock.Enter();
sGLockLevel += n;
}
LLOG("EnterGMutex " << n);
}
void LeaveGMutex()
@ -28,6 +32,7 @@ void LeaveGMutex()
ASSERT(sGLockLevel > 0);
if(--sGLockLevel == 0)
sGLock.Leave();
LLOG("LeaveGMutex");
}
int LeaveGMutexAll()
@ -37,6 +42,7 @@ int LeaveGMutexAll()
sGLock.Leave();
sGLockLevel = 0;
}
LLOG("LeaveGMutex all");
return q;
}

View file

@ -635,6 +635,7 @@ void DrawingDraw::Create(Size sz, bool dots_) {
drawing.Create();
size = sz;
dots = dots_;
val.Clear();
LLOG("DrawingDraw::Create, sz = " << sz << ", dots = " << dots << " -> clip = " << GetClip());
}