Moved window moving code from ServerWindow. CPU consuming operations now run win WorkingThread's context. Added locking mechanism for WorkingThread. Removed locking arround ServerWindow::SendMessageToClient().

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@10936 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Adi Oanca
2005-01-21 21:13:00 +00:00
parent 1cd22df0dc
commit 6a257c30a9
+145 -15
View File
@@ -95,10 +95,7 @@ RootLayer::RootLayer(const char *name, int32 workspaceCount,
return;
// Spawn our working thread
fThreadID= spawn_thread(WorkingThread, name, B_REAL_TIME_DISPLAY_PRIORITY, this);
if (fThreadID >= 0)
resume_thread(fThreadID);
fThreadID = spawn_thread(WorkingThread, name, B_REAL_TIME_DISPLAY_PRIORITY, this);
}
RootLayer::~RootLayer()
@@ -118,6 +115,15 @@ RootLayer::~RootLayer()
// RootLayer object just uses Screen objects, it is not allowed to delete them.
}
void RootLayer::RunThread()
{
if (fThreadID > 0)
resume_thread(fThreadID);
else
debugger("Can not create any more threads.\n");
}
/*!
\brief Thread function for handling input messages and calculating visible regions.
\param data Pointer to the app_server to which the thread belongs
@@ -129,12 +135,20 @@ int32 RootLayer::WorkingThread(void *data)
status_t err = B_OK;
RootLayer *oneRootLayer = (RootLayer*)data;
BPortLink messageQueue(-1, oneRootLayer->fListenPort);
// first make sure we are actualy visible
oneRootLayer->Lock();
oneRootLayer->RebuildFullRegion();
oneRootLayer->FullInvalidate(oneRootLayer->Bounds());
oneRootLayer->Unlock();
for(;;)
{
STRACE(("info: RootLayer(%s)::WorkingThread listening on port %ld.\n", oneRootLayer->GetName(), oneRootLayer->fListenPort));
err = messageQueue.GetNextReply(&code);
oneRootLayer->Lock();
if(err < B_OK)
{
STRACE(("WorkingThread: messageQueue.GetNextReply failed\n"));
@@ -165,11 +179,27 @@ int32 RootLayer::WorkingThread(void *data)
exit_thread(0);
break;
case AS_ROOTLAYER_SHOW_WINBORDER:
{
WinBorder *winBorder = NULL;
messageQueue.Read<WinBorder*>(&winBorder);
oneRootLayer->show_winBorder(winBorder);
break;
}
case AS_ROOTLAYER_HIDE_WINBORDER:
{
WinBorder *winBorder = NULL;
messageQueue.Read<WinBorder*>(&winBorder);
oneRootLayer->hide_winBorder(winBorder);
break;
}
default:
STRACE(("RootLayer(%s)::WorkingThread received unexpected code %lx\n",oneRootLayer->GetName(), oneRootLayer->code));
break;
}
oneRootLayer->Unlock();
// if we still have other messages in our queue, but we really want to quit
if (oneRootLayer->fQuiting)
break;
@@ -456,6 +486,22 @@ void RootLayer::RemoveWinBorder(WinBorder* winBorder)
desktop->fGeneralLock.Unlock();
}
void RootLayer::HideWinBorder(WinBorder* winBorder)
{
BPortLink msg(fListenPort, -1);
msg.StartMessage(AS_ROOTLAYER_HIDE_WINBORDER);
msg.Attach<WinBorder*>(winBorder);
msg.Flush();
}
void RootLayer::ShowWinBorder(WinBorder* winBorder)
{
BPortLink msg(fListenPort, -1);
msg.StartMessage(AS_ROOTLAYER_SHOW_WINBORDER);
msg.Attach<WinBorder*>(winBorder);
msg.Flush();
}
WinBorder* RootLayer::WinBorderAt(const BPoint& pt){
WinBorder *target = NULL;
WinBorder *wb = NULL;
@@ -1207,9 +1253,7 @@ void RootLayer::KeyboardEventHandler(int32 code, BPortLink& msg)
keymsg.AddString("bytes",string);
keymsg.AddInt32("raw_char",raw_char);
win->Lock();
win->SendMessageToClient(&keymsg);
win->Unlock();
}
}
@@ -1304,9 +1348,7 @@ void RootLayer::KeyboardEventHandler(int32 code, BPortLink& msg)
keymsg.AddString("bytes",string);
keymsg.AddInt32("raw_char",raw_char);
win->Lock();
win->SendMessageToClient(&keymsg);
win->Unlock();
}
}
@@ -1352,9 +1394,7 @@ void RootLayer::KeyboardEventHandler(int32 code, BPortLink& msg)
keymsg.AddInt32("modifiers",modifiers);
keymsg.AddData("states",B_INT8_TYPE,keystates,sizeof(int8)*16);
win->Lock();
win->SendMessageToClient(&keymsg);
win->Unlock();
}
}
@@ -1398,9 +1438,7 @@ void RootLayer::KeyboardEventHandler(int32 code, BPortLink& msg)
keymsg.AddInt32("modifiers",modifiers);
keymsg.AddData("states",B_INT8_TYPE,keystates,sizeof(int8)*16);
win->Lock();
win->SendMessageToClient(&keymsg);
win->Unlock();
}
}
@@ -1442,9 +1480,7 @@ void RootLayer::KeyboardEventHandler(int32 code, BPortLink& msg)
keymsg.AddInt32("be:old_modifiers",oldmodifiers);
keymsg.AddData("states",B_INT8_TYPE,keystates,sizeof(int8)*16);
win->Lock();
win->SendMessageToClient(&keymsg);
win->Unlock();
}
}
fMainLock.Unlock();
@@ -1493,3 +1529,97 @@ void RootLayer::PrintToStream()
}
printf("Active Workspace: %ld\n", fActiveWorkspace? fActiveWorkspace->ID(): -1);
}
void RootLayer::show_winBorder(WinBorder *winBorder)
{
desktop->fGeneralLock.Lock();
fMainLock.Lock();
int32 wksCount;
uint32 feel = winBorder->Window()->Feel();
// make WinBorder unhidden, but *do not* rebuild and redraw! We'll do that
// after we bring it (its modal and floating windows also) in front.
winBorder->Show(false);
if ( (feel == B_FLOATING_SUBSET_WINDOW_FEEL || feel == B_MODAL_SUBSET_WINDOW_FEEL)
&& winBorder->MainWinBorder() == NULL)
{
// This window hasn't been added to a normal window subset,
// so don't call placement or redrawing methods
}
else
{
wksCount = WorkspaceCount();
for(int32 i = 0; i < wksCount; i++)
{
if (winBorder->Window()->Workspaces() & (0x00000001UL << i))
{
WinBorder *previousFocus;
BRegion invalidRegion;
Workspace *ws;
// TODO: can you unify this method with Desktop::MouseEventHandler::B_MOUSE_DOWN
ws = WorkspaceAt(i+1);
ws->BringToFrontANormalWindow(winBorder);
ws->SearchAndSetNewFront(winBorder);
previousFocus = ws->FocusLayer();
ws->SearchAndSetNewFocus(winBorder);
// TODO: only do this in for the active workspace!
// first redraw previous window's decorator. It has lost focus state.
if (previousFocus)
if (previousFocus->fDecorator)
winBorder->fParent->Invalidate(previousFocus->fVisible);
// we must build the rebuild region. we have nowhere to take it from.
// include decorator's(if any) and fTopLayer's full regions.
winBorder->fTopLayer->RebuildFullRegion();
winBorder->RebuildFullRegion();
invalidRegion.Include(&(winBorder->fTopLayer->fFull));
if (winBorder->fDecorator)
invalidRegion.Include(&(winBorder->fFull));
winBorder->fParent->FullInvalidate(invalidRegion);
}
}
}
fMainLock.Unlock();
desktop->fGeneralLock.Unlock();
}
void RootLayer::hide_winBorder(WinBorder *winBorder)
{
Workspace *ws = NULL;
desktop->fGeneralLock.Lock();
fMainLock.Lock();
winBorder->Hide();
int32 wksCount= WorkspaceCount();
for(int32 i = 0; i < wksCount; i++)
{
ws = WorkspaceAt(i+1);
if (ws->FrontLayer() == winBorder)
{
ws->HideSubsetWindows(winBorder);
ws->SearchAndSetNewFocus(ws->FrontLayer());
}
else
{
if (ws->FocusLayer() == winBorder)
ws->SearchAndSetNewFocus(winBorder);
else{
// TODO: RootLayer or Desktop class should take care of invalidating
// ws->Invalidate();
}
}
}
fMainLock.Unlock();
desktop->fGeneralLock.Unlock();
}