CtrlCore: New MT rules implemented in X11 and GTK

git-svn-id: svn://ultimatepp.org/upp/trunk@6170 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2013-07-06 12:32:06 +00:00
parent a5cc4e2902
commit 8f9bfcc8e3
9 changed files with 59 additions and 64 deletions

View file

@ -138,4 +138,4 @@ somewhere or what ever..)&]
again, and when time has come, pushes it to 2 other streams..(so
a little `'data latency`' is expected..if you want to make the
data be available at once, call Flush() after your operations..&]
[s0; ]
[s0; ]]

View file

@ -9,7 +9,7 @@ NAMESPACE_UPP
void Ctrl::Create(Ctrl *owner, bool popup)
{
GuiLock __;
ASSERT(IsMainThread());
ASSERT_(IsMainThread(), "Only the main thread can open a window");
LLOG("Create " << Name() << " " << GetRect());
ASSERT(!IsChild() && !IsOpen());
LLOG("Ungrab1");
@ -117,12 +117,7 @@ void Ctrl::GuiPlatformRemove()
i++;
}
void Ctrl::PopUp(Ctrl *owner, bool savebits, bool activate, bool dropshadow, bool topmost)
{
Call(callback2(this, &Ctrl::PopUp0, owner, activate));
}
void Ctrl::PopUp0(Ctrl *owner, bool activate)
void Ctrl::PopUp(Ctrl *owner, bool savebits, bool activate, bool, bool)
{
GuiLock __;
LLOG("POPUP " << Name() << ", " << GetRect() << ", activate " << activate);

View file

@ -581,10 +581,10 @@ void WakeUpGuiThread()
g_main_context_wakeup(g_main_context_default());
}
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);
@ -614,9 +614,10 @@ gboolean sOnce(GtkWidget *)
return false;
}
void Ctrl::GuiSleep0(int ms)
void Ctrl::GuiSleep(int ms)
{
GuiLock __;
ASSERT_(IsMainThread(), "Only the main thread can perform GuiSleep");
if(ms < 20) // Periodic timer is each 20ms, so that is the longest possible wait
g_timeout_add(ms, (GSourceFunc) sOnce, NULL); // otherwise setup shorter timer
FetchEvents(TRUE);

View file

@ -36,17 +36,17 @@ void TopWindow::SyncSizeHints()
GdkWindowHints(GDK_HINT_MIN_SIZE|GDK_HINT_MAX_SIZE));
}
void TopWindow::SyncTitle0()
void TopWindow::SyncTitle()
{
GuiLock __;
if(top)
gtk_window_set_title(gtk(), FromUnicode(title, CHARSET_UTF8));
}
void TopWindow::SyncCaption0()
void TopWindow::SyncCaption()
{
GuiLock __;
SyncTitle0();
SyncTitle();
if(top) {
if(gdk_icon.Set(icon))
gtk_window_set_icon(gtk(), gdk_icon);

View file

@ -191,7 +191,7 @@ Rect Ctrl::GetWndScreenRect() const
return Null;
}
void Ctrl::WndShow0(bool b)
void Ctrl::WndShow(bool b)
{
GuiLock __;
LLOG("WndShow " << Name() << ", " << b);
@ -301,7 +301,7 @@ int Ctrl::GetKbdSpeed()
return 1000 / 32;
}
void Ctrl::SetWndForeground0()
void Ctrl::SetWndForeground()
{
GuiLock __;
if(top)
@ -343,18 +343,19 @@ void Ctrl::FocusSync()
}
}
void Ctrl::SetWndFocus(bool *b)
bool Ctrl::SetWndFocus()
{
GuiLock __;
LLOG("SetWndFocus0 " << Upp::Name(this) << ", top: " << top);
if(top) {
LLOG("SetWndFocus0 DO gdk: " << gdk());
SetWndForeground0();
SetWndForeground();
int t0 = msecs();
while(!gtk_window_is_active(gtk()) && msecs() - t0 < 500) // Wait up to 500ms for window to become active - not ideal, but only possibility
FetchEvents(true);
FocusSync();
}
return true;
}
void Ctrl::WndInvalidateRect(const Rect& r)
@ -365,7 +366,7 @@ void Ctrl::WndInvalidateRect(const Rect& r)
// gtk_widget_queue_draw_area(top->window, r.left, r.top, r.GetWidth(), r.GetHeight());
}
void Ctrl::WndScrollView0(const Rect& r, int dx, int dy)
void Ctrl::WndScrollView(const Rect& r, int dx, int dy)
{
GuiLock __;
LLOG("ScrollView " << rect);
@ -391,7 +392,7 @@ bool Ctrl::SweepConfigure(bool wait)
return r;
}
void Ctrl::WndSetPos0(const Rect& rect)
void Ctrl::WndSetPos(const Rect& rect)
{
LLOG("WndSetPos0 " << rect);
GuiLock __;
@ -413,11 +414,11 @@ void Ctrl::WndSetPos0(const Rect& rect)
LLOG("-- WndSetPos0 " << rect << " " << msecs() - t0);
}
void Ctrl::WndEnable(bool *b)
void Ctrl::WndEnable(bool b)
{
GuiLock __;
if(top) {
gtk_widget_set_sensitive(top->window, *b);
gtk_widget_set_sensitive(top->window, b);
StateH(ENABLE);
}
}
@ -426,7 +427,7 @@ void Ctrl::WndUpdate(const Rect& r)
{
GuiLock __;
LLOG("WndUpdate0r " << r);
WndUpdate0(); // Not found a way how to update only part of window
WndUpdate(); // Not found a way how to update only part of window
}
void Ctrl::WndUpdate()

View file

@ -843,7 +843,7 @@ void Ctrl::EventLoop(Ctrl *ctrl)
void Ctrl::GuiSleep(int ms)
{
GuiLock __;
ASSERT(IsMainThread());
ASSERT_(IsMainThread(), "Only the main thread can perform GuiSleep");
ELOG("GuiSleep");
int level = LeaveGuiMutexAll();
#if !defined(flagDLL) && !defined(PLATFORM_WINCE)

View file

@ -105,7 +105,7 @@ void TopWindow::DefSyncTitle()
}
}
void TopWindow::SyncTitle0()
void TopWindow::SyncTitle()
{
GuiLock __;
LLOG("SyncTitle: " << title);
@ -129,7 +129,7 @@ void WmState(Window w, bool set, Atom a1, Atom a2 = 0)
XSendEvent(Xdisplay, Xroot, false, SubstructureNotifyMask | SubstructureRedirectMask, &e);
}
void TopWindow::SyncState0()
void TopWindow::SyncState()
{
GuiLock __;
LLOG("SyncState");
@ -160,11 +160,11 @@ typedef struct {
#define PROP_MOTIF_WM_HINTS_ELEMENTS 5
#define PROP_MWM_HINTS_ELEMENTS PROP_MOTIF_WM_HINTS_ELEMENTS
void TopWindow::SyncCaption0()
void TopWindow::SyncCaption()
{
GuiLock __;
LLOG("SyncCaption0");
SyncTitle0();
SyncTitle();
if(IsOpen() && GetWindow()) {
unsigned long wina[6];
memset(wina, 0, sizeof(wina));
@ -256,11 +256,6 @@ void TopWindow::CenterRect(Ctrl *owner)
}
void TopWindow::Open(Ctrl *owner)
{
Open0(owner);
}
void TopWindow::Open0(Ctrl *owner)
{
LLOG("TopWindow::Open");
GuiLock __;
@ -281,7 +276,7 @@ void TopWindow::Open0(Ctrl *owner)
title2.Clear();
if(!weplace) {
LLOG("SyncCaption");
SyncCaption0();
SyncCaption();
}
LLOG("SyncSizeHints");
size_hints->flags = 0;
@ -382,7 +377,7 @@ void TopWindow::Open0(Ctrl *owner)
XChangeProperty(Xdisplay, win, XAtom("XdndAware"), XA_ATOM, 32,
0, (byte *)&version, 1);
SyncState0();
SyncState();
FixIcons();
}

View file

@ -71,7 +71,7 @@ void Ctrl::DoPaint(const Vector<Rect>& invalid)
}
}
void Ctrl::WndScrollView0(const Rect& r, int dx, int dy)
void Ctrl::WndScrollView(const Rect& r, int dx, int dy)
{
GuiLock __;
if(r.IsEmpty() || !GetWindow()) return;
@ -383,11 +383,11 @@ void WakeUpGuiThread()
IGNORE_RESULT(write(WakePipe[1], "\1", 1));
}
void Ctrl::GuiSleep0(int ms)
void Ctrl::GuiSleep(int ms)
{
GuiLock __;
LLOG(GetTickCount() << " GUISLEEP " << ms);
ASSERT(IsMainThread());
ASSERT_(IsMainThread(), "Only main thread can perform GuiSleep");
timeval timeout;
timeout.tv_sec = ms / 1000;
timeout.tv_usec = ms % 1000 * 1000;
@ -417,7 +417,7 @@ void Ctrl::SysEndLoop()
{
}
void Ctrl::EventLoop0(Ctrl *ctrl)
void Ctrl::EventLoop(Ctrl *ctrl)
{
GuiLock __;
ASSERT_(IsMainThread(), "Event loop can only run in the main thread");
@ -434,7 +434,7 @@ void Ctrl::EventLoop0(Ctrl *ctrl)
while(loopno > EndSessionLoopNo && (ctrl ? ctrl->InLoop() && ctrl->IsOpen() : GetTopCtrls().GetCount())) {
XEvent event;
GuiSleep0(granularity);
GuiSleep(granularity);
SyncMousePos();
while(IsWaitingEvent()) {
LTIMING("XNextEvent");
@ -466,7 +466,7 @@ void Ctrl::SyncExpose()
void Ctrl::Create(Ctrl *owner, bool redirect, bool savebits)
{
GuiLock __;
ASSERT(IsMainThread(), "Only main thread can create windows");
ASSERT_(IsMainThread(), "Only main thread can create windows");
LLOG("Create " << Name() << " " << GetRect());
ASSERT(!IsChild() && !IsOpen());
LLOG("Ungrab1");
@ -682,7 +682,7 @@ Ctrl *Ctrl::GetOwner()
return q >= 0 ? Xwindow()[q].owner : NULL;
}
void Ctrl::WndShow0(bool b)
void Ctrl::WndShow(bool b)
{
GuiLock __;
LLOG("WndShow " << b);
@ -700,7 +700,7 @@ void Ctrl::WndShow0(bool b)
}
}
void Ctrl::WndUpdate0()
void Ctrl::WndUpdate()
{
GuiLock __;
LTIMING("WndUpdate");
@ -718,7 +718,7 @@ void Ctrl::WndUpdate0()
}
}
void Ctrl::WndUpdate0r(const Rect& r)
void Ctrl::WndUpdate(const Rect& r)
{
GuiLock __;
LTIMING("WndUpdate Rect");
@ -734,7 +734,7 @@ void Ctrl::WndUpdate0r(const Rect& r)
xw.invalid = Subtract(xw.invalid, r, dummy);
}
void Ctrl::WndSetPos0(const Rect& r)
void Ctrl::WndSetPos(const Rect& r)
{
GuiLock __;
if(!top) return;
@ -882,11 +882,10 @@ void Ctrl::KillFocus(Window window)
w.ctrl->KillFocusWnd();
}
void Ctrl::SetWndFocus0(bool *b)
bool Ctrl::SetWndFocus()
{
GuiLock __;
LLOG("SetWndFocus " << Name());
*b = false;
if(top && top->window != focusWindow && IsEnabled() && IsVisible()) {
LLOG("Setting focus... ");
LTIMING("XSetInfputFocus");
@ -897,8 +896,9 @@ void Ctrl::SetWndFocus0(bool *b)
focusWindow = top->window;
SetFocusWnd();
}
*b = true;
return true;
}
return false;
}
bool Ctrl::HasWndFocus() const
@ -1010,7 +1010,7 @@ void Ctrl::WndInvalidateRect(const Rect& r)
Invalidate(Xwindow().Get(top->window), r);
}
void Ctrl::SetWndForeground0()
void Ctrl::SetWndForeground()
{
GuiLock __;
LLOG("SetWndForeground " << Name());
@ -1037,20 +1037,16 @@ bool Ctrl::IsWndForeground() const
return ~focusCtrlWnd == (q ? q : GetTopCtrl());
}
void Ctrl::WndEnable0(bool *b)
void Ctrl::WndEnable(bool b)
{
GuiLock __;
LLOG("WndEnable");
if(!top) {
*b = false;
return;
}
if(!*b) {
if(!top) return;
if(!b) {
ReleaseCapture();
if(HasWndFocus())
XSetInputFocus(Xdisplay, None, RevertToPointerRoot, CurrentTime);
}
*b = true;
}
// 01/12/2007 - mdelfede

View file

@ -2298,7 +2298,8 @@ view or frame coordinates.&]
HWND_[*@3 hwnd], [@(0.0.255) bool]_[*@3 savebits]_`=_[@(0.0.255) true],
[@(0.0.255) bool]_[*@3 activate]_`=_[@(0.0.255) true], [@(0.0.255) bool]_[*@3 dropshadow]_`=
_[@(0.0.255) false], [@(0.0.255) bool]_[*@3 topmost]_`=_[@(0.0.255) false])&]
[s2;b17;a17; Opens top`-level Ctrl as pop`-up window.&]
[s2;b17;a17; Opens top`-level Ctrl as pop`-up window. [*/ This method
can only be invoked in the main thread.]&]
[s6; [2 Win32 specific.]&]
[s7;i1120;a17; [%-*C@3 hwnd]-|Win32 handle of owner window.&]
[s7;i1120;a17; [%-*C@3 savebits]-|Indicates that system should try to
@ -2313,7 +2314,8 @@ preserve background bits.&]
trl]_`*[*@3 owner]_`=_NULL, [@(0.0.255) bool]_[*@3 savebits]_`=_[@(0.0.255) true],
[@(0.0.255) bool]_[*@3 activate]_`=_[@(0.0.255) true], [@(0.0.255) bool]_[*@3 dropshadow]_`=
_[@(0.0.255) false], [@(0.0.255) bool]_[*@3 topmost]_`=_[@(0.0.255) false])&]
[s2;b17;a17; Opens top`-level Ctrl as pop`-up window.&]
[s2;b17;a17; Opens top`-level Ctrl as pop`-up window. [*/ This method
can only be invoked in the main thread.]&]
[s7;i1120;a17; [%-*C@3 owner]-|Owner.&]
[s7;i1120;a17; [%-*C@3 savebits]-|Indicates that system should try to
preserve background bits.&]
@ -2362,15 +2364,16 @@ were processed, false that queue was empty.&]
[s4;%- &]
[s5;:Ctrl`:`:IsPopUp`(`)const:%- [@(0.0.255) bool]_[* IsPopUp]()_[@(0.0.255) const]&]
[s7;i1120;a17; [*/ Return value]-|True if Ctrl is pop`-up window.&]
[s3;%- &]
[s3; &]
[s4;%- &]
[s5;:Ctrl`:`:EventLoop`(`:`:Ctrl`*`):%- [@(0.0.255) static] [@(0.0.255) void]_[* EventLoop](
[_^`:`:Ctrl^ Ctrl]_`*[*@3 loopctrl]_`=_NULL)&]
[s5;:Ctrl`:`:EventLoop`(Ctrl`*`):%- [@(0.0.255) static] [@(0.0.255) void]_[* EventLoop]([_^`:`:Ctrl^ C
trl]_`*[*@3 loopctrl]_`=_NULL)&]
[s2;b17;a17; Executes event`-loop. If [*@3 loopctrl ]is not NULL, it
must be opened top`-level Ctrl and loop is executed until EndLoop
method for [*@3 loopctrl ]is invoked. If [*@3 loopctrl] is NULL,
loop is executed as long as any top`-level Ctrl exists or application
is terminated by OS specific `"shutdown`" event.&]
is terminated by OS specific `"shutdown`" event. [*/ This method
can only be invoked in the main thread.]&]
[s7;i1120;a17; [%-*C@3 loopctrl]-|Looping Ctrl.&]
[s3;%- &]
[s4;%- &]
@ -2612,7 +2615,7 @@ does is platform specific).&]
nt]_[*@3 ms])&]
[s2;b17;a17; Sleeps (while allowing other applications or threads
to run) for at least [*@3 ms] milliseconds or until new input event
is available.&]
is available. [*/ This method can only be invoked in the main thread.]&]
[s7;i1120;a17; [%-*@3 ms]-|Time to sleep.&]
[s3; &]
[s4;%- &]
@ -2622,7 +2625,11 @@ allback]_[*@3 cb])&]
for GUI). It works by posting callback into timer queue (with
zero delay), then waits its completion using Semaphore. Main
GUI thread has to run timer queue management for callback to
be executed (by running event`-loop (TopWindow`::Run) or ProcessEvents).&]
be executed (by running event`-loop (TopWindow`::Run) or ProcessEvents).
Warning: Call unlocks GuiLock so that the main thread can run
on GUI, this is possible source of race`-conditions. Be prepared
that some other code can run on GUI between call to Call and
cb being executed!&]
[s3; &]
[s4;%- &]
[s5;:Ctrl`:`:IsShutdownThreads`(`):%- [@(0.0.255) static] [@(0.0.255) bool]_[* IsShutdownTh