* implemented a BRegion pool per WindowLayer which is supposed
to cut down on BRegion related allocations, cannot really tell
if it speeds things up
* used the new BRegion pool in WindowLayer and ViewLayer whereever
a BRegion was used on the stack
* fixed the debugging stuff in MultiLocker - it will get you into
the debugger if you
- try to nest read locks
- try to write lock when your are a reader already
- don't match up nested locks when your a writer
-> but only if you #define DEBUG 1 in the .cpp, is off by default now
* went over WindowLayer, ServerWindow, Desktop and a few other places
and fixed the locking for use with the MultiLocker, the "a reader can
not become a writer" is especially tricky, feel free to review the
changes
* activated the MultiLocker, I tested this quite a bit, if there are
problems simply turn on DEBUG and you should drop into the debugger
right where the problem is... hope all is good
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17046 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -199,8 +199,6 @@ enum {
|
|||||||
AS_SCREENMODE_CHANGED,
|
AS_SCREENMODE_CHANGED,
|
||||||
|
|
||||||
// Graphics calls
|
// Graphics calls
|
||||||
AS_BEGIN_TRANSACTION,
|
|
||||||
AS_END_TRANSACTION,
|
|
||||||
AS_SET_HIGH_COLOR,
|
AS_SET_HIGH_COLOR,
|
||||||
AS_SET_LOW_COLOR,
|
AS_SET_LOW_COLOR,
|
||||||
AS_SET_VIEW_COLOR,
|
AS_SET_VIEW_COLOR,
|
||||||
|
|||||||
@@ -50,6 +50,9 @@
|
|||||||
# define STRACE(a) ;
|
# define STRACE(a) ;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !USE_MULTI_LOCKER
|
||||||
|
# define AutoWriteLocker BAutolock
|
||||||
|
#endif
|
||||||
|
|
||||||
class KeyboardFilter : public EventFilter {
|
class KeyboardFilter : public EventFilter {
|
||||||
public:
|
public:
|
||||||
@@ -1850,18 +1853,14 @@ Desktop::ViewUnderMouse(const WindowLayer* window)
|
|||||||
WindowLayer *
|
WindowLayer *
|
||||||
Desktop::FindWindowLayerByClientToken(int32 token, team_id teamID)
|
Desktop::FindWindowLayerByClientToken(int32 token, team_id teamID)
|
||||||
{
|
{
|
||||||
LockSingleWindow();
|
|
||||||
|
|
||||||
for (WindowLayer *window = fAllWindows.FirstWindow(); window != NULL;
|
for (WindowLayer *window = fAllWindows.FirstWindow(); window != NULL;
|
||||||
window = window->NextWindow(kAllWindowList)) {
|
window = window->NextWindow(kAllWindowList)) {
|
||||||
if (window->ServerWindow()->ClientToken() == token
|
if (window->ServerWindow()->ClientToken() == token
|
||||||
&& window->ServerWindow()->ClientTeam() == teamID) {
|
&& window->ServerWindow()->ClientTeam() == teamID) {
|
||||||
UnlockSingleWindow();
|
|
||||||
return window;
|
return window;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UnlockSingleWindow();
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1869,7 +1868,7 @@ Desktop::FindWindowLayerByClientToken(int32 token, team_id teamID)
|
|||||||
void
|
void
|
||||||
Desktop::MinimizeApplication(team_id team)
|
Desktop::MinimizeApplication(team_id team)
|
||||||
{
|
{
|
||||||
BAutolock locker(fWindowLock);
|
AutoWriteLocker locker(fWindowLock);
|
||||||
|
|
||||||
// Just minimize all windows of that application
|
// Just minimize all windows of that application
|
||||||
|
|
||||||
@@ -1886,7 +1885,7 @@ Desktop::MinimizeApplication(team_id team)
|
|||||||
void
|
void
|
||||||
Desktop::BringApplicationToFront(team_id team)
|
Desktop::BringApplicationToFront(team_id team)
|
||||||
{
|
{
|
||||||
BAutolock locker(fWindowLock);
|
AutoWriteLocker locker(fWindowLock);
|
||||||
|
|
||||||
// TODO: for now, just maximize all windows of that application
|
// TODO: for now, just maximize all windows of that application
|
||||||
|
|
||||||
@@ -1929,7 +1928,7 @@ Desktop::WindowAction(int32 windowToken, int32 action)
|
|||||||
void
|
void
|
||||||
Desktop::WriteWindowList(team_id team, BPrivate::LinkSender& sender)
|
Desktop::WriteWindowList(team_id team, BPrivate::LinkSender& sender)
|
||||||
{
|
{
|
||||||
BAutolock locker(fWindowLock);
|
AutoWriteLocker locker(fWindowLock);
|
||||||
|
|
||||||
// compute the number of windows
|
// compute the number of windows
|
||||||
|
|
||||||
@@ -1961,7 +1960,7 @@ Desktop::WriteWindowList(team_id team, BPrivate::LinkSender& sender)
|
|||||||
void
|
void
|
||||||
Desktop::WriteWindowInfo(int32 serverToken, BPrivate::LinkSender& sender)
|
Desktop::WriteWindowInfo(int32 serverToken, BPrivate::LinkSender& sender)
|
||||||
{
|
{
|
||||||
BAutolock locker(fWindowLock);
|
AutoWriteLocker locker(fWindowLock);
|
||||||
BAutolock tokenLocker(BPrivate::gDefaultTokens);
|
BAutolock tokenLocker(BPrivate::gDefaultTokens);
|
||||||
|
|
||||||
::ServerWindow* window;
|
::ServerWindow* window;
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
#include <Region.h>
|
#include <Region.h>
|
||||||
#include <Window.h>
|
#include <Window.h>
|
||||||
|
|
||||||
#define USE_MULTI_LOCKER 0
|
#define USE_MULTI_LOCKER 1
|
||||||
|
|
||||||
#if USE_MULTI_LOCKER
|
#if USE_MULTI_LOCKER
|
||||||
# include "MultiLocker.h"
|
# include "MultiLocker.h"
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ Server app_server :
|
|||||||
PNGDump.cpp
|
PNGDump.cpp
|
||||||
RAMLinkMsgReader.cpp
|
RAMLinkMsgReader.cpp
|
||||||
RGBColor.cpp
|
RGBColor.cpp
|
||||||
|
RegionPool.cpp
|
||||||
ScreenManager.cpp
|
ScreenManager.cpp
|
||||||
ServerApp.cpp
|
ServerApp.cpp
|
||||||
ServerBitmap.cpp
|
ServerBitmap.cpp
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
#include <OS.h>
|
#include <OS.h>
|
||||||
|
|
||||||
//#define TIMING 1
|
//#define TIMING 1
|
||||||
#define DEBUG 1
|
//#define DEBUG 1
|
||||||
|
|
||||||
|
|
||||||
MultiLocker::MultiLocker(const char* semaphoreBaseName)
|
MultiLocker::MultiLocker(const char* semaphoreBaseName)
|
||||||
@@ -132,6 +132,11 @@ MultiLocker::ReadLock()
|
|||||||
if (fInit == B_OK) {
|
if (fInit == B_OK) {
|
||||||
if (IsWriteLocked()) {
|
if (IsWriteLocked()) {
|
||||||
//the writer simply increments the nesting
|
//the writer simply increments the nesting
|
||||||
|
#if DEBUG
|
||||||
|
if (fWriterNest < 0)
|
||||||
|
debugger("ReadLock() - negative writer nest count\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
fWriterNest++;
|
fWriterNest++;
|
||||||
locked = true;
|
locked = true;
|
||||||
} else {
|
} else {
|
||||||
@@ -174,10 +179,22 @@ MultiLocker::WriteLock()
|
|||||||
|
|
||||||
if (IsWriteLocked(&stack_base, &thread)) {
|
if (IsWriteLocked(&stack_base, &thread)) {
|
||||||
//already the writer - increment the nesting count
|
//already the writer - increment the nesting count
|
||||||
|
#if DEBUG
|
||||||
|
if (fWriterNest < 0)
|
||||||
|
debugger("WriteLock() - negative nest count\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
fWriterNest++;
|
fWriterNest++;
|
||||||
locked = true;
|
locked = true;
|
||||||
} else {
|
} else {
|
||||||
//new writer acquiring the lock
|
//new writer acquiring the lock
|
||||||
|
#if DEBUG
|
||||||
|
// NOTE: IsReadLocked() tells you
|
||||||
|
// if this thread really holds the
|
||||||
|
// "read lock" only in DEBUG mode!
|
||||||
|
if (IsReadLocked())
|
||||||
|
debugger("Reader wants to become writer!");
|
||||||
|
#endif
|
||||||
if (atomic_add(&fLockCount, 1) >= 1) {
|
if (atomic_add(&fLockCount, 1) >= 1) {
|
||||||
//another writer in the lock - acquire the semaphore
|
//another writer in the lock - acquire the semaphore
|
||||||
locked = (acquire_sem_etc(fWriterLock, 1, B_DO_NOT_RESCHEDULE,
|
locked = (acquire_sem_etc(fWriterLock, 1, B_DO_NOT_RESCHEDULE,
|
||||||
@@ -227,6 +244,12 @@ MultiLocker::ReadUnlock()
|
|||||||
if (IsWriteLocked()) {
|
if (IsWriteLocked()) {
|
||||||
//writers simply decrement the nesting count
|
//writers simply decrement the nesting count
|
||||||
fWriterNest--;
|
fWriterNest--;
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
if (fWriterNest < 0)
|
||||||
|
debugger("ReadUnlock() - negative writer nest count\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
unlocked = true;
|
unlocked = true;
|
||||||
} else {
|
} else {
|
||||||
//decrement and retrieve the read counter
|
//decrement and retrieve the read counter
|
||||||
@@ -237,7 +260,7 @@ MultiLocker::ReadUnlock()
|
|||||||
B_DO_NOT_RESCHEDULE) == B_OK);
|
B_DO_NOT_RESCHEDULE) == B_OK);
|
||||||
} else unlocked = true;
|
} else unlocked = true;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#if DEBUG
|
||||||
//unregister if we released the lock
|
//unregister if we released the lock
|
||||||
if (unlocked) unregister_thread();
|
if (unlocked) unregister_thread();
|
||||||
#endif
|
#endif
|
||||||
@@ -265,6 +288,12 @@ MultiLocker::WriteUnlock()
|
|||||||
//if this is a nested lock simply decrement the nest count
|
//if this is a nested lock simply decrement the nest count
|
||||||
if (fWriterNest > 0) {
|
if (fWriterNest > 0) {
|
||||||
fWriterNest--;
|
fWriterNest--;
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
if (fWriterNest < 0)
|
||||||
|
debugger("WriteUnlock(): nest count now negative\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
unlocked = true;
|
unlocked = true;
|
||||||
} else {
|
} else {
|
||||||
//writer finally unlocking
|
//writer finally unlocking
|
||||||
@@ -416,14 +445,16 @@ MultiLocker::IsReadLocked()
|
|||||||
void
|
void
|
||||||
MultiLocker::register_thread()
|
MultiLocker::register_thread()
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#if DEBUG
|
||||||
#if TIMING
|
#if TIMING
|
||||||
bigtime_t start = system_time();
|
bigtime_t start = system_time();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
thread_id thread = find_thread(NULL);
|
thread_id thread = find_thread(NULL);
|
||||||
|
|
||||||
ASSERT_WITH_MESSAGE(fDebugArray[thread%fMaxThreads] == 0,"Nested ReadLock!\n");
|
if (fDebugArray[thread%fMaxThreads] != 0)
|
||||||
|
debugger("Nested ReadLock!\n");
|
||||||
|
|
||||||
fDebugArray[thread%fMaxThreads]++;
|
fDebugArray[thread%fMaxThreads]++;
|
||||||
|
|
||||||
#if TIMING
|
#if TIMING
|
||||||
@@ -439,7 +470,7 @@ MultiLocker::register_thread()
|
|||||||
void
|
void
|
||||||
MultiLocker::unregister_thread()
|
MultiLocker::unregister_thread()
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#if DEBUG
|
||||||
#if TIMING
|
#if TIMING
|
||||||
bigtime_t start = system_time();
|
bigtime_t start = system_time();
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,10 +1,20 @@
|
|||||||
/* MultiLocker.h */
|
/* MultiLocker.h */
|
||||||
/*
|
/*
|
||||||
|
Copyright 2005-2006, Haiku.
|
||||||
|
Distributed under the terms of the MIT license.
|
||||||
|
|
||||||
Copyright 1999, Be Incorporated. All Rights Reserved.
|
Copyright 1999, Be Incorporated. All Rights Reserved.
|
||||||
This file may be used under the terms of the Be Sample Code License.
|
This file may be used under the terms of the Be Sample Code License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* multiple-reader single-writer locking class */
|
/** multiple-reader single-writer locking class */
|
||||||
|
|
||||||
|
// IMPORTANT:
|
||||||
|
// * nested read locks are not supported
|
||||||
|
// * a reader becomming the write is not supported
|
||||||
|
// * nested write locks are supported
|
||||||
|
// * a writer can do read locks, even nested ones
|
||||||
|
// * in case of problems, #define DEBUG 1 in the .cpp
|
||||||
|
|
||||||
#ifndef MULTI_LOCKER_H
|
#ifndef MULTI_LOCKER_H
|
||||||
#define MULTI_LOCKER_H
|
#define MULTI_LOCKER_H
|
||||||
@@ -31,7 +41,8 @@ class MultiLocker {
|
|||||||
bool WriteUnlock();
|
bool WriteUnlock();
|
||||||
|
|
||||||
//does the current thread hold a write lock ?
|
//does the current thread hold a write lock ?
|
||||||
bool IsWriteLocked(uint32 *stack_base = NULL, thread_id *thread = NULL);
|
bool IsWriteLocked(uint32 *stack_base = NULL,
|
||||||
|
thread_id *thread = NULL);
|
||||||
//in DEBUG mode returns whether the lock is held
|
//in DEBUG mode returns whether the lock is held
|
||||||
//in non-debug mode returns true
|
//in non-debug mode returns true
|
||||||
bool IsReadLocked();
|
bool IsReadLocked();
|
||||||
@@ -82,31 +93,41 @@ class MultiLocker {
|
|||||||
class AutoWriteLocker {
|
class AutoWriteLocker {
|
||||||
public:
|
public:
|
||||||
AutoWriteLocker(MultiLocker* lock)
|
AutoWriteLocker(MultiLocker* lock)
|
||||||
|
: fLock(*lock)
|
||||||
|
{
|
||||||
|
fLock.WriteLock();
|
||||||
|
}
|
||||||
|
AutoWriteLocker(MultiLocker& lock)
|
||||||
: fLock(lock)
|
: fLock(lock)
|
||||||
{
|
{
|
||||||
fLock->WriteLock();
|
fLock.WriteLock();
|
||||||
}
|
}
|
||||||
~AutoWriteLocker()
|
~AutoWriteLocker()
|
||||||
{
|
{
|
||||||
fLock->WriteUnlock();
|
fLock.WriteUnlock();
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
MultiLocker* fLock;
|
MultiLocker& fLock;
|
||||||
};
|
};
|
||||||
|
|
||||||
class AutoReadLocker {
|
class AutoReadLocker {
|
||||||
public:
|
public:
|
||||||
AutoReadLocker(MultiLocker* lock)
|
AutoReadLocker(MultiLocker* lock)
|
||||||
|
: fLock(*lock)
|
||||||
|
{
|
||||||
|
fLock.ReadLock();
|
||||||
|
}
|
||||||
|
AutoReadLocker(MultiLocker& lock)
|
||||||
: fLock(lock)
|
: fLock(lock)
|
||||||
{
|
{
|
||||||
fLock->ReadLock();
|
fLock.ReadLock();
|
||||||
}
|
}
|
||||||
~AutoReadLocker()
|
~AutoReadLocker()
|
||||||
{
|
{
|
||||||
fLock->ReadUnlock();
|
fLock.ReadUnlock();
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
MultiLocker* fLock;
|
MultiLocker& fLock;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2006, Haiku, Inc.
|
||||||
|
* Distributed under the terms of the MIT license.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stephan Aßmus <superstippi@gmx.de>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "RegionPool.h"
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#if DEBUG_LEAK
|
||||||
|
#include <debugger.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <Region.h>
|
||||||
|
|
||||||
|
using std::nothrow;
|
||||||
|
|
||||||
|
RegionPool::RegionPool()
|
||||||
|
: fAvailable(4)
|
||||||
|
#if DEBUG_LEAK
|
||||||
|
,fUsed(4)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RegionPool::~RegionPool()
|
||||||
|
{
|
||||||
|
#if DEBUG_LEAK
|
||||||
|
if (fUsed.CountItems() > 0)
|
||||||
|
debugger("RegionPool::~RegionPool() - some regions still in use!");
|
||||||
|
#endif
|
||||||
|
int32 count = fAvailable.CountItems();
|
||||||
|
for (int32 i = 0; i < count; i++)
|
||||||
|
delete (BRegion*)fAvailable.ItemAtFast(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BRegion*
|
||||||
|
RegionPool::GetRegion()
|
||||||
|
{
|
||||||
|
BRegion* region = (BRegion*)fAvailable.RemoveItem(
|
||||||
|
fAvailable.CountItems() - 1);
|
||||||
|
if (!region) {
|
||||||
|
region = new (nothrow) BRegion();
|
||||||
|
if (!region) {
|
||||||
|
// whoa
|
||||||
|
fprintf(stderr, "RegionPool::GetRegion() - "
|
||||||
|
"no memory!\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if DEBUG_LEAK
|
||||||
|
fUsed.AddItem(region);
|
||||||
|
#endif
|
||||||
|
return region;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BRegion*
|
||||||
|
RegionPool::GetRegion(const BRegion& other)
|
||||||
|
{
|
||||||
|
BRegion* region;
|
||||||
|
int32 count = fAvailable.CountItems();
|
||||||
|
if (count > 0) {
|
||||||
|
region = (BRegion*)fAvailable.RemoveItem(count - 1);
|
||||||
|
*region = other;
|
||||||
|
} else {
|
||||||
|
region = new (nothrow) BRegion(other);
|
||||||
|
if (!region) {
|
||||||
|
// whoa
|
||||||
|
fprintf(stderr, "RegionPool::GetRegion() - "
|
||||||
|
"no memory!\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if DEBUG_LEAK
|
||||||
|
fUsed.AddItem(region);
|
||||||
|
#endif
|
||||||
|
return region;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
RegionPool::Recycle(BRegion* region)
|
||||||
|
{
|
||||||
|
if (!fAvailable.AddItem(region)) {
|
||||||
|
// at least don't leak the region...
|
||||||
|
fprintf(stderr, "RegionPool::Recycle() - "
|
||||||
|
"no memory!\n");
|
||||||
|
delete region;
|
||||||
|
} else {
|
||||||
|
// prepare for next usage
|
||||||
|
region->MakeEmpty();
|
||||||
|
}
|
||||||
|
#if DEBUG_LEAK
|
||||||
|
fUsed.RemoveItem(region);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2006, Haiku, Inc.
|
||||||
|
* Distributed under the terms of the MIT license.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stephan Aßmus <superstippi@gmx.de>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef REGION_POOL_H
|
||||||
|
#define REGION_POOL_H
|
||||||
|
|
||||||
|
#include <List.h>
|
||||||
|
|
||||||
|
class BRegion;
|
||||||
|
|
||||||
|
#define DEBUG_LEAK 0
|
||||||
|
|
||||||
|
class RegionPool {
|
||||||
|
public:
|
||||||
|
RegionPool();
|
||||||
|
virtual ~RegionPool();
|
||||||
|
|
||||||
|
BRegion* GetRegion();
|
||||||
|
BRegion* GetRegion(const BRegion& other);
|
||||||
|
void Recycle(BRegion* region);
|
||||||
|
|
||||||
|
private:
|
||||||
|
BList fAvailable;
|
||||||
|
#if DEBUG_LEAK
|
||||||
|
BList fUsed;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // REGION_POOL_H
|
||||||
@@ -194,6 +194,7 @@ ServerBitmap::_HandleSpace(color_space space, int32 bytesPerRow)
|
|||||||
case B_YCbCr422:
|
case B_YCbCr422:
|
||||||
case B_YUV422:
|
case B_YUV422:
|
||||||
minBPR = (fWidth + 3) / 4 * 8;
|
minBPR = (fWidth + 3) / 4 * 8;
|
||||||
|
// TODO: huh? why not simply fWidth * 2 ?!?
|
||||||
fBitsPerPixel = 16;
|
fBitsPerPixel = 16;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@@ -51,7 +51,6 @@
|
|||||||
#include "ServerPicture.h"
|
#include "ServerPicture.h"
|
||||||
#include "ServerProtocol.h"
|
#include "ServerProtocol.h"
|
||||||
#include "WindowLayer.h"
|
#include "WindowLayer.h"
|
||||||
#include "Workspace.h"
|
|
||||||
#include "WorkspacesLayer.h"
|
#include "WorkspacesLayer.h"
|
||||||
|
|
||||||
#include "ServerWindow.h"
|
#include "ServerWindow.h"
|
||||||
@@ -386,8 +385,11 @@ ServerWindow::SetTitle(const char* newTitle)
|
|||||||
rename_thread(Thread(), name);
|
rename_thread(Thread(), name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fWindowLayer != NULL)
|
if (fWindowLayer != NULL) {
|
||||||
|
fDesktop->UnlockSingleWindow();
|
||||||
fDesktop->SetWindowTitle(fWindowLayer, newTitle);
|
fDesktop->SetWindowTitle(fWindowLayer, newTitle);
|
||||||
|
fDesktop->LockSingleWindow();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -584,10 +586,12 @@ ServerWindow::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
|
|||||||
|
|
||||||
link.Read<bool>(&activate);
|
link.Read<bool>(&activate);
|
||||||
|
|
||||||
|
fDesktop->UnlockSingleWindow();
|
||||||
if (activate)
|
if (activate)
|
||||||
fDesktop->ActivateWindow(fWindowLayer);
|
fDesktop->ActivateWindow(fWindowLayer);
|
||||||
else
|
else
|
||||||
fDesktop->SendWindowBehind(fWindowLayer, NULL);
|
fDesktop->SendWindowBehind(fWindowLayer, NULL);
|
||||||
|
fDesktop->LockSingleWindow();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case AS_SEND_BEHIND:
|
case AS_SEND_BEHIND:
|
||||||
@@ -602,7 +606,9 @@ ServerWindow::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
|
|||||||
|
|
||||||
WindowLayer *behindOf;
|
WindowLayer *behindOf;
|
||||||
if ((behindOf = fDesktop->FindWindowLayerByClientToken(token, teamID)) != NULL) {
|
if ((behindOf = fDesktop->FindWindowLayerByClientToken(token, teamID)) != NULL) {
|
||||||
|
fDesktop->UnlockSingleWindow();
|
||||||
fDesktop->SendWindowBehind(fWindowLayer, behindOf);
|
fDesktop->SendWindowBehind(fWindowLayer, behindOf);
|
||||||
|
fDesktop->LockSingleWindow();
|
||||||
status = B_OK;
|
status = B_OK;
|
||||||
} else
|
} else
|
||||||
status = B_NAME_NOT_FOUND;
|
status = B_NAME_NOT_FOUND;
|
||||||
@@ -617,23 +623,6 @@ ServerWindow::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
|
|||||||
NotifyQuitRequested();
|
NotifyQuitRequested();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AS_BEGIN_TRANSACTION:
|
|
||||||
{
|
|
||||||
STRACE(("ServerWindow %s: Message AS_BEGIN_TRANSACTION unimplemented\n",
|
|
||||||
Title()));
|
|
||||||
// TODO: we could probably do a bit more here...
|
|
||||||
// TODO: AS_BEGIN_TRANSACTION
|
|
||||||
//fWindowLayer->DisableUpdateRequests();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case AS_END_TRANSACTION:
|
|
||||||
{
|
|
||||||
STRACE(("ServerWindow %s: Message AS_END_TRANSACTION unimplemented\n",
|
|
||||||
Title()));
|
|
||||||
// TODO: AS_END_TRANSACTION
|
|
||||||
//fWindowLayer->EnableUpdateRequests();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case AS_ENABLE_UPDATES:
|
case AS_ENABLE_UPDATES:
|
||||||
{
|
{
|
||||||
STRACE(("ServerWindow %s: Message AS_ENABLE_UPDATES unimplemented\n",
|
STRACE(("ServerWindow %s: Message AS_ENABLE_UPDATES unimplemented\n",
|
||||||
@@ -683,8 +672,10 @@ ServerWindow::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
|
|||||||
|| windowLayer->Feel() != B_NORMAL_WINDOW_FEEL) {
|
|| windowLayer->Feel() != B_NORMAL_WINDOW_FEEL) {
|
||||||
status = B_BAD_VALUE;
|
status = B_BAD_VALUE;
|
||||||
} else {
|
} else {
|
||||||
|
fDesktop->UnlockSingleWindow();
|
||||||
status = fDesktop->AddWindowToSubset(fWindowLayer, windowLayer)
|
status = fDesktop->AddWindowToSubset(fWindowLayer, windowLayer)
|
||||||
? B_OK : B_NO_MEMORY;
|
? B_OK : B_NO_MEMORY;
|
||||||
|
fDesktop->LockSingleWindow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -702,7 +693,9 @@ ServerWindow::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
|
|||||||
WindowLayer* windowLayer = fDesktop->FindWindowLayerByClientToken(
|
WindowLayer* windowLayer = fDesktop->FindWindowLayerByClientToken(
|
||||||
token, App()->ClientTeam());
|
token, App()->ClientTeam());
|
||||||
if (windowLayer != NULL) {
|
if (windowLayer != NULL) {
|
||||||
|
fDesktop->UnlockSingleWindow();
|
||||||
fDesktop->RemoveWindowFromSubset(fWindowLayer, windowLayer);
|
fDesktop->RemoveWindowFromSubset(fWindowLayer, windowLayer);
|
||||||
|
fDesktop->LockSingleWindow();
|
||||||
status = B_OK;
|
status = B_OK;
|
||||||
} else
|
} else
|
||||||
status = B_BAD_VALUE;
|
status = B_BAD_VALUE;
|
||||||
@@ -725,8 +718,11 @@ ServerWindow::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
|
|||||||
? B_OK : B_BAD_VALUE;
|
? B_OK : B_BAD_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status == B_OK && !fWindowLayer->IsOffscreenWindow())
|
if (status == B_OK && !fWindowLayer->IsOffscreenWindow()) {
|
||||||
|
fDesktop->UnlockSingleWindow();
|
||||||
fDesktop->SetWindowLook(fWindowLayer, (window_look)look);
|
fDesktop->SetWindowLook(fWindowLayer, (window_look)look);
|
||||||
|
fDesktop->LockSingleWindow();
|
||||||
|
}
|
||||||
|
|
||||||
fLink.StartMessage(status);
|
fLink.StartMessage(status);
|
||||||
fLink.Flush();
|
fLink.Flush();
|
||||||
@@ -744,8 +740,11 @@ ServerWindow::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
|
|||||||
? B_OK : B_BAD_VALUE;
|
? B_OK : B_BAD_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status == B_OK && !fWindowLayer->IsOffscreenWindow())
|
if (status == B_OK && !fWindowLayer->IsOffscreenWindow()) {
|
||||||
|
fDesktop->UnlockSingleWindow();
|
||||||
fDesktop->SetWindowFeel(fWindowLayer, (window_feel)feel);
|
fDesktop->SetWindowFeel(fWindowLayer, (window_feel)feel);
|
||||||
|
fDesktop->LockSingleWindow();
|
||||||
|
}
|
||||||
|
|
||||||
fLink.StartMessage(status);
|
fLink.StartMessage(status);
|
||||||
fLink.Flush();
|
fLink.Flush();
|
||||||
@@ -763,8 +762,11 @@ ServerWindow::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
|
|||||||
? B_OK : B_BAD_VALUE;
|
? B_OK : B_BAD_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status == B_OK && !fWindowLayer->IsOffscreenWindow())
|
if (status == B_OK && !fWindowLayer->IsOffscreenWindow()) {
|
||||||
|
fDesktop->UnlockSingleWindow();
|
||||||
fDesktop->SetWindowFlags(fWindowLayer, flags);
|
fDesktop->SetWindowFlags(fWindowLayer, flags);
|
||||||
|
fDesktop->LockSingleWindow();
|
||||||
|
}
|
||||||
|
|
||||||
fLink.StartMessage(status);
|
fLink.StartMessage(status);
|
||||||
fLink.Flush();
|
fLink.Flush();
|
||||||
@@ -801,7 +803,9 @@ ServerWindow::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
|
|||||||
STRACE(("ServerWindow %s: Message AS_SET_WORKSPACES %lx\n",
|
STRACE(("ServerWindow %s: Message AS_SET_WORKSPACES %lx\n",
|
||||||
Title(), newWorkspaces));
|
Title(), newWorkspaces));
|
||||||
|
|
||||||
|
fDesktop->UnlockSingleWindow();
|
||||||
fDesktop->SetWindowWorkspaces(fWindowLayer, newWorkspaces);
|
fDesktop->SetWindowWorkspaces(fWindowLayer, newWorkspaces);
|
||||||
|
fDesktop->LockSingleWindow();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case AS_WINDOW_RESIZE:
|
case AS_WINDOW_RESIZE:
|
||||||
@@ -820,7 +824,9 @@ ServerWindow::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
|
|||||||
// pragmatically set window bounds
|
// pragmatically set window bounds
|
||||||
fLink.StartMessage(B_BUSY);
|
fLink.StartMessage(B_BUSY);
|
||||||
} else {
|
} else {
|
||||||
|
fDesktop->UnlockSingleWindow();
|
||||||
fDesktop->ResizeWindowBy(fWindowLayer, xResizeBy, yResizeBy);
|
fDesktop->ResizeWindowBy(fWindowLayer, xResizeBy, yResizeBy);
|
||||||
|
fDesktop->LockSingleWindow();
|
||||||
fLink.StartMessage(B_OK);
|
fLink.StartMessage(B_OK);
|
||||||
}
|
}
|
||||||
fLink.Flush();
|
fLink.Flush();
|
||||||
@@ -842,7 +848,9 @@ ServerWindow::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
|
|||||||
// pragmatically set window positions
|
// pragmatically set window positions
|
||||||
fLink.StartMessage(B_BUSY);
|
fLink.StartMessage(B_BUSY);
|
||||||
} else {
|
} else {
|
||||||
|
fDesktop->UnlockSingleWindow();
|
||||||
fDesktop->MoveWindowBy(fWindowLayer, xMoveBy, yMoveBy);
|
fDesktop->MoveWindowBy(fWindowLayer, xMoveBy, yMoveBy);
|
||||||
|
fDesktop->LockSingleWindow();
|
||||||
fLink.StartMessage(B_OK);
|
fLink.StartMessage(B_OK);
|
||||||
}
|
}
|
||||||
fLink.Flush();
|
fLink.Flush();
|
||||||
@@ -901,22 +909,12 @@ ServerWindow::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
|
|||||||
|
|
||||||
case AS_BEGIN_UPDATE:
|
case AS_BEGIN_UPDATE:
|
||||||
DTRACE(("ServerWindowo %s: AS_BEGIN_UPDATE\n", Title()));
|
DTRACE(("ServerWindowo %s: AS_BEGIN_UPDATE\n", Title()));
|
||||||
// NOTE: when line below is turned on, the behaviour starts to
|
|
||||||
// be very much like on R5, but if the client crashes in
|
|
||||||
// one of it's BView's Draw() functions, AS_END_UPDATE is
|
|
||||||
// never received and the app_server is toast! Maybe R5
|
|
||||||
// does something like this, but if the write lock cannot
|
|
||||||
// be optained within a certain amount of time, it crashes
|
|
||||||
// whoever holds the read lock on purpose.
|
|
||||||
|
|
||||||
//fDesktop->LockSingleWindow();
|
|
||||||
fWindowLayer->BeginUpdate(fLink);
|
fWindowLayer->BeginUpdate(fLink);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AS_END_UPDATE:
|
case AS_END_UPDATE:
|
||||||
DTRACE(("ServerWindowo %s: AS_END_UPDATE\n", Title()));
|
DTRACE(("ServerWindowo %s: AS_END_UPDATE\n", Title()));
|
||||||
fWindowLayer->EndUpdate();
|
fWindowLayer->EndUpdate();
|
||||||
//fDesktop->UnlockSingleWindow();
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AS_GET_MOUSE:
|
case AS_GET_MOUSE:
|
||||||
@@ -2697,7 +2695,6 @@ ServerWindow::_SetCurrentLayer(ViewLayer* layer)
|
|||||||
fCurrentDrawingRegionValid = false;
|
fCurrentDrawingRegionValid = false;
|
||||||
#if 0
|
#if 0
|
||||||
#if DELAYED_BACKGROUND_CLEARING
|
#if DELAYED_BACKGROUND_CLEARING
|
||||||
fWindowLayer->ReadLockWindows();
|
|
||||||
if (fCurrentLayer && fCurrentLayer->IsBackgroundDirty() && fWindowLayer->InUpdate()) {
|
if (fCurrentLayer && fCurrentLayer->IsBackgroundDirty() && fWindowLayer->InUpdate()) {
|
||||||
DrawingEngine* drawingEngine = fWindowLayer->GetDrawingEngine();
|
DrawingEngine* drawingEngine = fWindowLayer->GetDrawingEngine();
|
||||||
if (drawingEngine->Lock()) {
|
if (drawingEngine->Lock()) {
|
||||||
@@ -2714,7 +2711,6 @@ fWindowLayer->ReadLockWindows();
|
|||||||
drawingEngine->Unlock();
|
drawingEngine->Unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fWindowLayer->ReadUnlockWindows();
|
|
||||||
#endif
|
#endif
|
||||||
#endif // 0
|
#endif // 0
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -198,8 +198,12 @@ ViewLayer::AddChild(ViewLayer* layer)
|
|||||||
// trigger redraw
|
// trigger redraw
|
||||||
BRect clippedFrame = layer->Frame();
|
BRect clippedFrame = layer->Frame();
|
||||||
ConvertToVisibleInTopView(&clippedFrame);
|
ConvertToVisibleInTopView(&clippedFrame);
|
||||||
BRegion dirty(clippedFrame);
|
BRegion* dirty = fWindow->GetRegion();
|
||||||
fWindow->MarkContentDirty(dirty);
|
if (dirty) {
|
||||||
|
dirty->Set(clippedFrame);
|
||||||
|
fWindow->MarkContentDirty(*dirty);
|
||||||
|
fWindow->RecycleRegion(dirty);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -244,8 +248,12 @@ ViewLayer::RemoveChild(ViewLayer* layer)
|
|||||||
// trigger redraw
|
// trigger redraw
|
||||||
BRect clippedFrame = layer->Frame();
|
BRect clippedFrame = layer->Frame();
|
||||||
ConvertToVisibleInTopView(&clippedFrame);
|
ConvertToVisibleInTopView(&clippedFrame);
|
||||||
BRegion dirty(clippedFrame);
|
BRegion* dirty = fWindow->GetRegion();
|
||||||
fWindow->MarkContentDirty(dirty);
|
if (dirty) {
|
||||||
|
dirty->Set(clippedFrame);
|
||||||
|
fWindow->MarkContentDirty(*dirty);
|
||||||
|
fWindow->RecycleRegion(dirty);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -642,13 +650,19 @@ ViewLayer::MoveBy(int32 x, int32 y, BRegion* dirtyRegion)
|
|||||||
// clipping oldVisibleBounds to newVisibleBounds
|
// clipping oldVisibleBounds to newVisibleBounds
|
||||||
// makes sure we don't copy parts hidden under
|
// makes sure we don't copy parts hidden under
|
||||||
// parent views
|
// parent views
|
||||||
BRegion copyRegion(oldVisibleBounds & newVisibleBounds);
|
BRegion* region = fWindow->GetRegion();
|
||||||
fWindow->CopyContents(©Region, x, y);
|
if (region) {
|
||||||
|
region->Set(oldVisibleBounds & newVisibleBounds);
|
||||||
|
fWindow->CopyContents(region, x, y);
|
||||||
|
|
||||||
|
region->Set(oldVisibleBounds);
|
||||||
|
newVisibleBounds.OffsetBy(x, y);
|
||||||
|
region->Exclude(newVisibleBounds);
|
||||||
|
dirtyRegion->Include(dirty);
|
||||||
|
|
||||||
|
fWindow->RecycleRegion(region);
|
||||||
|
}
|
||||||
|
|
||||||
BRegion dirty(oldVisibleBounds);
|
|
||||||
newVisibleBounds.OffsetBy(x, y);
|
|
||||||
dirty.Exclude(newVisibleBounds);
|
|
||||||
dirtyRegion->Include(&dirty);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -681,32 +695,37 @@ ViewLayer::ResizeBy(int32 x, int32 y, BRegion* dirtyRegion)
|
|||||||
oldBounds.right -= x;
|
oldBounds.right -= x;
|
||||||
oldBounds.bottom -= y;
|
oldBounds.bottom -= y;
|
||||||
|
|
||||||
BRegion dirty(Bounds());
|
BRegion* dirty = fWindow->GetRegion();
|
||||||
dirty.Include(oldBounds);
|
if (!dirty)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dirty->Set(Bounds());
|
||||||
|
dirty->Include(oldBounds);
|
||||||
|
|
||||||
if (!(fFlags & B_FULL_UPDATE_ON_RESIZE)) {
|
if (!(fFlags & B_FULL_UPDATE_ON_RESIZE)) {
|
||||||
// the dirty region is just the difference of
|
// the dirty region is just the difference of
|
||||||
// old and new bounds
|
// old and new bounds
|
||||||
dirty.Exclude(oldBounds & Bounds());
|
dirty->Exclude(oldBounds & Bounds());
|
||||||
}
|
}
|
||||||
|
|
||||||
InvalidateScreenClipping(true);
|
InvalidateScreenClipping(true);
|
||||||
|
|
||||||
if (dirty.CountRects() > 0) {
|
if (dirty->CountRects() > 0) {
|
||||||
// exclude children, they are expected to
|
// exclude children, they are expected to
|
||||||
// include their own dirty regions in ParentResized()
|
// include their own dirty regions in ParentResized()
|
||||||
for (ViewLayer* child = FirstChild(); child; child = child->NextSibling()) {
|
for (ViewLayer* child = FirstChild(); child; child = child->NextSibling()) {
|
||||||
if (child->IsVisible()) {
|
if (child->IsVisible()) {
|
||||||
BRect previousChildVisible(child->Frame() & oldBounds & Bounds());
|
BRect previousChildVisible(child->Frame() & oldBounds & Bounds());
|
||||||
if (dirty.Frame().Intersects(previousChildVisible)) {
|
if (dirty->Frame().Intersects(previousChildVisible)) {
|
||||||
dirty.Exclude(previousChildVisible);
|
dirty->Exclude(previousChildVisible);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ConvertToScreen(&dirty);
|
ConvertToScreen(dirty);
|
||||||
dirtyRegion->Include(&dirty);
|
dirtyRegion->Include(dirty);
|
||||||
}
|
}
|
||||||
|
fWindow->RecycleRegion(dirty);
|
||||||
}
|
}
|
||||||
|
|
||||||
// layout the children
|
// layout the children
|
||||||
@@ -795,10 +814,16 @@ ViewLayer::ScrollBy(int32 x, int32 y, BRegion* dirtyRegion)
|
|||||||
|
|
||||||
// find the dirty region as far as we are
|
// find the dirty region as far as we are
|
||||||
// concerned
|
// concerned
|
||||||
BRegion dirty(oldBounds);
|
BRegion* dirty = fWindow->GetRegion();
|
||||||
|
if (!dirty)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dirty->Set(oldBounds);
|
||||||
stillVisibleBounds.OffsetBy(-x, -y);
|
stillVisibleBounds.OffsetBy(-x, -y);
|
||||||
dirty.Exclude(stillVisibleBounds);
|
dirty->Exclude(stillVisibleBounds);
|
||||||
dirtyRegion->Include(&dirty);
|
dirtyRegion->Include(dirty);
|
||||||
|
|
||||||
|
fWindow->RecycleRegion(dirty);
|
||||||
|
|
||||||
// the screen clipping of this view and it's
|
// the screen clipping of this view and it's
|
||||||
// childs is no longer valid
|
// childs is no longer valid
|
||||||
@@ -843,12 +868,18 @@ ViewLayer::CopyBits(BRect src, BRect dst, BRegion& windowContentClipping)
|
|||||||
BRect dirtyDst(dst);
|
BRect dirtyDst(dst);
|
||||||
ConvertToVisibleInTopView(&dirtyDst);
|
ConvertToVisibleInTopView(&dirtyDst);
|
||||||
|
|
||||||
BRegion dirty(dirtyDst);
|
BRegion* dirty = fWindow->GetRegion();
|
||||||
|
if (!dirty)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dirty->Set(dirtyDst);
|
||||||
// exclude the part that we could copy
|
// exclude the part that we could copy
|
||||||
visibleSrc.OffsetBy(xOffset, yOffset);
|
visibleSrc.OffsetBy(xOffset, yOffset);
|
||||||
dirty.Exclude(visibleSrc);
|
dirty->Exclude(visibleSrc);
|
||||||
dirty.IntersectWith(&ScreenClipping(&windowContentClipping));
|
dirty->IntersectWith(&ScreenClipping(&windowContentClipping));
|
||||||
fWindow->MarkContentDirty(dirty);
|
fWindow->MarkContentDirty(*dirty);
|
||||||
|
|
||||||
|
fWindow->RecycleRegion(dirty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1024,8 +1055,12 @@ ViewLayer::SetHidden(bool hidden)
|
|||||||
// trigger a redraw
|
// trigger a redraw
|
||||||
BRect clippedBounds = Bounds();
|
BRect clippedBounds = Bounds();
|
||||||
ConvertToVisibleInTopView(&clippedBounds);
|
ConvertToVisibleInTopView(&clippedBounds);
|
||||||
BRegion dirty(clippedBounds);
|
BRegion* dirty = fWindow->GetRegion();
|
||||||
fWindow->MarkContentDirty(dirty);
|
if (!dirty)
|
||||||
|
return;
|
||||||
|
dirty->Set(clippedBounds);
|
||||||
|
fWindow->MarkContentDirty(*dirty);
|
||||||
|
fWindow->RecycleRegion(dirty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+145
-164
@@ -88,6 +88,8 @@ WindowLayer::WindowLayer(const BRect& frame, const char *name,
|
|||||||
fEffectiveDrawingRegion(),
|
fEffectiveDrawingRegion(),
|
||||||
fEffectiveDrawingRegionValid(false),
|
fEffectiveDrawingRegionValid(false),
|
||||||
|
|
||||||
|
fRegionPool(),
|
||||||
|
|
||||||
fIsClosing(false),
|
fIsClosing(false),
|
||||||
fIsMinimizing(false),
|
fIsMinimizing(false),
|
||||||
fIsZooming(false),
|
fIsZooming(false),
|
||||||
@@ -122,9 +124,7 @@ WindowLayer::WindowLayer(const BRect& frame, const char *name,
|
|||||||
fMinWidth(1),
|
fMinWidth(1),
|
||||||
fMaxWidth(32768),
|
fMaxWidth(32768),
|
||||||
fMinHeight(1),
|
fMinHeight(1),
|
||||||
fMaxHeight(32768),
|
fMaxHeight(32768)
|
||||||
|
|
||||||
fReadLocked(false)
|
|
||||||
{
|
{
|
||||||
// make sure our arguments are valid
|
// make sure our arguments are valid
|
||||||
if (!IsValidLook(fLook))
|
if (!IsValidLook(fLook))
|
||||||
@@ -175,29 +175,6 @@ WindowLayer::~WindowLayer()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
WindowLayer::ReadLockWindows()
|
|
||||||
{
|
|
||||||
if (fDesktop)
|
|
||||||
fReadLocked = fDesktop->LockSingleWindow();
|
|
||||||
else
|
|
||||||
fReadLocked = true;
|
|
||||||
|
|
||||||
return fReadLocked;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
WindowLayer::ReadUnlockWindows()
|
|
||||||
{
|
|
||||||
if (fReadLocked) {
|
|
||||||
if (fDesktop)
|
|
||||||
fDesktop->UnlockSingleWindow();
|
|
||||||
fReadLocked = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
WindowLayer::SetClipping(BRegion* stillAvailableOnScreen)
|
WindowLayer::SetClipping(BRegion* stillAvailableOnScreen)
|
||||||
{
|
{
|
||||||
@@ -413,29 +390,27 @@ WindowLayer::ResizeBy(int32 x, int32 y, BRegion* dirtyRegion)
|
|||||||
void
|
void
|
||||||
WindowLayer::ScrollViewBy(ViewLayer* view, int32 dx, int32 dy)
|
WindowLayer::ScrollViewBy(ViewLayer* view, int32 dx, int32 dy)
|
||||||
{
|
{
|
||||||
// this can be executed from any thread, but if the
|
// this is executed in ServerWindow with the Readlock
|
||||||
// desktop thread is executing this, it should have
|
// held
|
||||||
// the write lock, otherwise it is not prevented
|
|
||||||
// from executing this at the same time as the window
|
|
||||||
// is doing something else here!
|
|
||||||
|
|
||||||
if (!view || view == fTopLayer || (dx == 0 && dy == 0))
|
if (!view || view == fTopLayer || (dx == 0 && dy == 0))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (fDesktop && fDesktop->LockSingleWindow()) {
|
BRegion* dirty = fRegionPool.GetRegion();
|
||||||
BRegion dirty;
|
if (!dirty)
|
||||||
view->ScrollBy(dx, dy, &dirty);
|
return;
|
||||||
|
|
||||||
|
view->ScrollBy(dx, dy, dirty);
|
||||||
|
|
||||||
//fDrawingEngine->FillRegion(dirty, RGBColor(255, 0, 255, 255));
|
//fDrawingEngine->FillRegion(dirty, RGBColor(255, 0, 255, 255));
|
||||||
//snooze(2000);
|
//snooze(2000);
|
||||||
|
|
||||||
if (IsVisible() && view->IsVisible()) {
|
if (IsVisible() && view->IsVisible()) {
|
||||||
dirty.IntersectWith(&VisibleContentRegion());
|
dirty->IntersectWith(&VisibleContentRegion());
|
||||||
_TriggerContentRedraw(dirty);
|
_TriggerContentRedraw(*dirty);
|
||||||
}
|
|
||||||
|
|
||||||
fDesktop->UnlockSingleWindow();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fRegionPool.Recycle(dirty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -443,64 +418,67 @@ WindowLayer::ScrollViewBy(ViewLayer* view, int32 dx, int32 dy)
|
|||||||
void
|
void
|
||||||
WindowLayer::CopyContents(BRegion* region, int32 xOffset, int32 yOffset)
|
WindowLayer::CopyContents(BRegion* region, int32 xOffset, int32 yOffset)
|
||||||
{
|
{
|
||||||
if (IsVisible() && fDesktop && fDesktop->LockSingleWindow()) {
|
// executed in ServerWindow thread with the read lock held
|
||||||
BRegion newDirty(*region);
|
if (!IsVisible())
|
||||||
|
return;
|
||||||
|
|
||||||
// clip the region to the visible contents at the
|
BRegion* newDirty = fRegionPool.GetRegion(*region);
|
||||||
// source and destination location (note that VisibleContentRegion()
|
|
||||||
// is used once to make sure it is valid, then fVisibleContentRegion
|
// clip the region to the visible contents at the
|
||||||
// is used directly)
|
// source and destination location (note that VisibleContentRegion()
|
||||||
region->IntersectWith(&VisibleContentRegion());
|
// is used once to make sure it is valid, then fVisibleContentRegion
|
||||||
|
// is used directly)
|
||||||
|
region->IntersectWith(&VisibleContentRegion());
|
||||||
|
if (region->CountRects() > 0) {
|
||||||
|
region->OffsetBy(xOffset, yOffset);
|
||||||
|
region->IntersectWith(&fVisibleContentRegion);
|
||||||
if (region->CountRects() > 0) {
|
if (region->CountRects() > 0) {
|
||||||
region->OffsetBy(xOffset, yOffset);
|
// if the region still contains any rects
|
||||||
region->IntersectWith(&fVisibleContentRegion);
|
// offset to source location again
|
||||||
if (region->CountRects() > 0) {
|
region->OffsetBy(-xOffset, -yOffset);
|
||||||
// if the region still contains any rects
|
// the part which we can copy is not dirty
|
||||||
// offset to source location again
|
newDirty->Exclude(region);
|
||||||
region->OffsetBy(-xOffset, -yOffset);
|
|
||||||
// the part which we can copy is not dirty
|
fDrawingEngine->CopyRegion(region, xOffset, yOffset);
|
||||||
newDirty.Exclude(region);
|
|
||||||
|
|
||||||
fDrawingEngine->CopyRegion(region, xOffset, yOffset);
|
|
||||||
|
|
||||||
// move along the already dirty regions that are common
|
// move along the already dirty regions that are common
|
||||||
// with the region that we could copy
|
// with the region that we could copy
|
||||||
_ShiftPartOfRegion(&fDirtyRegion, region, xOffset, yOffset);
|
_ShiftPartOfRegion(&fDirtyRegion, region, xOffset, yOffset);
|
||||||
if (fPendingUpdateSession.IsUsed())
|
if (fPendingUpdateSession.IsUsed())
|
||||||
_ShiftPartOfRegion(&fPendingUpdateSession.DirtyRegion(), region, xOffset, yOffset);
|
_ShiftPartOfRegion(&fPendingUpdateSession.DirtyRegion(), region, xOffset, yOffset);
|
||||||
|
|
||||||
if (fCurrentUpdateSession.IsUsed()) {
|
if (fCurrentUpdateSession.IsUsed()) {
|
||||||
// if there are parts in the current update session
|
// if there are parts in the current update session
|
||||||
// that intersect with the copied region, we cannot
|
// that intersect with the copied region, we cannot
|
||||||
// simply shift them as with the other dirty regions
|
// simply shift them as with the other dirty regions
|
||||||
// - we cannot change the update rect already told to the
|
// - we cannot change the update rect already told to the
|
||||||
// client, that's why we transfer those parts to the
|
// client, that's why we transfer those parts to the
|
||||||
// new dirty region instead
|
// new dirty region instead
|
||||||
BRegion common(*region);
|
BRegion* common = fRegionPool.GetRegion(*region);
|
||||||
// see if there is a common part at all
|
// see if there is a common part at all
|
||||||
common.IntersectWith(&fCurrentUpdateSession.DirtyRegion());
|
common->IntersectWith(&fCurrentUpdateSession.DirtyRegion());
|
||||||
if (common.CountRects() > 0) {
|
if (common->CountRects() > 0) {
|
||||||
// cut the common part from the region
|
// cut the common part from the region
|
||||||
fCurrentUpdateSession.DirtyRegion().Exclude(&common);
|
fCurrentUpdateSession.DirtyRegion().Exclude(common);
|
||||||
newDirty.Include(&common);
|
newDirty->Include(common);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
fRegionPool.Recycle(common);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// what is left visible from the original region
|
|
||||||
// at the destination after the region which could be
|
|
||||||
// copied has been excluded, is considered dirty
|
|
||||||
// NOTE: it may look like dirty regions are not moved
|
|
||||||
// if no region could be copied, but that's alright,
|
|
||||||
// since these parts will now be in newDirty anyways
|
|
||||||
// (with the right offset)
|
|
||||||
newDirty.OffsetBy(xOffset, yOffset);
|
|
||||||
newDirty.IntersectWith(&fVisibleContentRegion);
|
|
||||||
if (newDirty.CountRects() > 0)
|
|
||||||
ProcessDirtyRegion(newDirty);
|
|
||||||
|
|
||||||
fDesktop->UnlockSingleWindow();
|
|
||||||
}
|
}
|
||||||
|
// what is left visible from the original region
|
||||||
|
// at the destination after the region which could be
|
||||||
|
// copied has been excluded, is considered dirty
|
||||||
|
// NOTE: it may look like dirty regions are not moved
|
||||||
|
// if no region could be copied, but that's alright,
|
||||||
|
// since these parts will now be in newDirty anyways
|
||||||
|
// (with the right offset)
|
||||||
|
newDirty->OffsetBy(xOffset, yOffset);
|
||||||
|
newDirty->IntersectWith(&fVisibleContentRegion);
|
||||||
|
if (newDirty->CountRects() > 0)
|
||||||
|
ProcessDirtyRegion(*newDirty);
|
||||||
|
|
||||||
|
fRegionPool.Recycle(newDirty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -537,14 +515,11 @@ WindowLayer::ViewAt(const BPoint& where)
|
|||||||
{
|
{
|
||||||
ViewLayer* view = NULL;
|
ViewLayer* view = NULL;
|
||||||
|
|
||||||
if (ReadLockWindows()) {
|
if (!fContentRegionValid)
|
||||||
if (!fContentRegionValid)
|
_UpdateContentRegion();
|
||||||
_UpdateContentRegion();
|
|
||||||
|
|
||||||
view = fTopLayer->ViewAt(where, &fContentRegion);
|
view = fTopLayer->ViewAt(where, &fContentRegion);
|
||||||
|
|
||||||
ReadUnlockWindows();
|
|
||||||
}
|
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -641,16 +616,18 @@ WindowLayer::ProcessDirtyRegion(BRegion& region)
|
|||||||
void
|
void
|
||||||
WindowLayer::RedrawDirtyRegion()
|
WindowLayer::RedrawDirtyRegion()
|
||||||
{
|
{
|
||||||
if (!fDesktop || !fDesktop->LockSingleWindow())
|
// executed from ServerWindow with the read lock held
|
||||||
return;
|
|
||||||
|
|
||||||
if (IsVisible()) {
|
if (IsVisible()) {
|
||||||
_DrawBorder();
|
_DrawBorder();
|
||||||
|
|
||||||
BRegion dirtyContentRegion(VisibleContentRegion());
|
BRegion* dirtyContentRegion =
|
||||||
dirtyContentRegion.IntersectWith(&fDirtyRegion);
|
fRegionPool.GetRegion(VisibleContentRegion());
|
||||||
|
dirtyContentRegion->IntersectWith(&fDirtyRegion);
|
||||||
|
|
||||||
_TriggerContentRedraw(dirtyContentRegion);
|
_TriggerContentRedraw(*dirtyContentRegion);
|
||||||
|
|
||||||
|
fRegionPool.Recycle(dirtyContentRegion);
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset the dirty region, since
|
// reset the dirty region, since
|
||||||
@@ -658,11 +635,9 @@ WindowLayer::RedrawDirtyRegion()
|
|||||||
// thread wanted to mark something
|
// thread wanted to mark something
|
||||||
// dirty in the mean time, it was
|
// dirty in the mean time, it was
|
||||||
// blocking on the global region lock to
|
// blocking on the global region lock to
|
||||||
// get write access, since we held the
|
// get write access, since we're holding
|
||||||
// read lock for the whole time.
|
// the read lock for the whole time.
|
||||||
fDirtyRegion.MakeEmpty();
|
fDirtyRegion.MakeEmpty();
|
||||||
|
|
||||||
fDesktop->UnlockSingleWindow();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -685,23 +660,19 @@ WindowLayer::MarkContentDirty(BRegion& regionOnScreen)
|
|||||||
// since this won't affect other windows, read locking
|
// since this won't affect other windows, read locking
|
||||||
// is sufficient. If there was no dirty region before,
|
// is sufficient. If there was no dirty region before,
|
||||||
// an update message is triggered
|
// an update message is triggered
|
||||||
if (!fHidden && fDesktop && fDesktop->LockSingleWindow()) {
|
if (fHidden)
|
||||||
regionOnScreen.IntersectWith(&VisibleContentRegion());
|
return;
|
||||||
_TriggerContentRedraw(regionOnScreen);
|
|
||||||
|
|
||||||
fDesktop->UnlockSingleWindow();
|
regionOnScreen.IntersectWith(&VisibleContentRegion());
|
||||||
}
|
_TriggerContentRedraw(regionOnScreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
WindowLayer::InvalidateView(ViewLayer* layer, BRegion& layerRegion)
|
WindowLayer::InvalidateView(ViewLayer* layer, BRegion& layerRegion)
|
||||||
{
|
{
|
||||||
if (layer && IsVisible() && fDesktop && fDesktop->LockSingleWindow()) {
|
if (layer && IsVisible() && layer->IsVisible()) {
|
||||||
if (!layer->IsVisible()) {
|
|
||||||
fDesktop->UnlockSingleWindow();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!fContentRegionValid)
|
if (!fContentRegionValid)
|
||||||
_UpdateContentRegion();
|
_UpdateContentRegion();
|
||||||
|
|
||||||
@@ -715,8 +686,6 @@ WindowLayer::InvalidateView(ViewLayer* layer, BRegion& layerRegion)
|
|||||||
|
|
||||||
_TriggerContentRedraw(layerRegion);
|
_TriggerContentRedraw(layerRegion);
|
||||||
}
|
}
|
||||||
|
|
||||||
fDesktop->UnlockSingleWindow();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -796,12 +765,12 @@ WindowLayer::MouseDown(BMessage* message, BPoint where, int32* _viewToken)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// redraw decorator
|
// redraw decorator
|
||||||
BRegion visibleBorder;
|
BRegion* visibleBorder = fRegionPool.GetRegion();
|
||||||
GetBorderRegion(&visibleBorder);
|
GetBorderRegion(visibleBorder);
|
||||||
visibleBorder.IntersectWith(&VisibleRegion());
|
visibleBorder->IntersectWith(&VisibleRegion());
|
||||||
|
|
||||||
fDrawingEngine->Lock();
|
fDrawingEngine->Lock();
|
||||||
fDrawingEngine->ConstrainClippingRegion(&visibleBorder);
|
fDrawingEngine->ConstrainClippingRegion(visibleBorder);
|
||||||
|
|
||||||
if (fIsZooming) {
|
if (fIsZooming) {
|
||||||
fDecorator->SetZoom(true);
|
fDecorator->SetZoom(true);
|
||||||
@@ -813,6 +782,8 @@ WindowLayer::MouseDown(BMessage* message, BPoint where, int32* _viewToken)
|
|||||||
|
|
||||||
fDrawingEngine->Unlock();
|
fDrawingEngine->Unlock();
|
||||||
|
|
||||||
|
fRegionPool.Recycle(visibleBorder);
|
||||||
|
|
||||||
// based on what the Decorator returned, properly place this window.
|
// based on what the Decorator returned, properly place this window.
|
||||||
if (action == DEC_MOVETOBACK) {
|
if (action == DEC_MOVETOBACK) {
|
||||||
fDesktop->SendWindowBehind(this);
|
fDesktop->SendWindowBehind(this);
|
||||||
@@ -853,12 +824,12 @@ WindowLayer::MouseUp(BMessage* message, BPoint where, int32* _viewToken)
|
|||||||
click_type action = _ActionFor(message);
|
click_type action = _ActionFor(message);
|
||||||
|
|
||||||
// redraw decorator
|
// redraw decorator
|
||||||
BRegion visibleBorder;
|
BRegion* visibleBorder = fRegionPool.GetRegion();
|
||||||
GetBorderRegion(&visibleBorder);
|
GetBorderRegion(visibleBorder);
|
||||||
visibleBorder.IntersectWith(&VisibleRegion());
|
visibleBorder->IntersectWith(&VisibleRegion());
|
||||||
|
|
||||||
fDrawingEngine->Lock();
|
fDrawingEngine->Lock();
|
||||||
fDrawingEngine->ConstrainClippingRegion(&visibleBorder);
|
fDrawingEngine->ConstrainClippingRegion(visibleBorder);
|
||||||
|
|
||||||
if (fIsZooming) {
|
if (fIsZooming) {
|
||||||
fIsZooming = false;
|
fIsZooming = false;
|
||||||
@@ -886,6 +857,8 @@ WindowLayer::MouseUp(BMessage* message, BPoint where, int32* _viewToken)
|
|||||||
}
|
}
|
||||||
|
|
||||||
fDrawingEngine->Unlock();
|
fDrawingEngine->Unlock();
|
||||||
|
|
||||||
|
fRegionPool.Recycle(visibleBorder);
|
||||||
}
|
}
|
||||||
fIsDragging = false;
|
fIsDragging = false;
|
||||||
fIsResizing = false;
|
fIsResizing = false;
|
||||||
@@ -923,12 +896,12 @@ WindowLayer::MouseMoved(BMessage *message, BPoint where, int32* _viewToken,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (fDecorator) {
|
if (fDecorator) {
|
||||||
BRegion visibleBorder;
|
BRegion* visibleBorder = fRegionPool.GetRegion();
|
||||||
GetBorderRegion(&visibleBorder);
|
GetBorderRegion(visibleBorder);
|
||||||
visibleBorder.IntersectWith(&VisibleRegion());
|
visibleBorder->IntersectWith(&VisibleRegion());
|
||||||
|
|
||||||
fDrawingEngine->Lock();
|
fDrawingEngine->Lock();
|
||||||
fDrawingEngine->ConstrainClippingRegion(&visibleBorder);
|
fDrawingEngine->ConstrainClippingRegion(visibleBorder);
|
||||||
|
|
||||||
if (fIsZooming) {
|
if (fIsZooming) {
|
||||||
fDecorator->SetZoom(_ActionFor(message) == DEC_ZOOM);
|
fDecorator->SetZoom(_ActionFor(message) == DEC_ZOOM);
|
||||||
@@ -939,6 +912,7 @@ WindowLayer::MouseMoved(BMessage *message, BPoint where, int32* _viewToken,
|
|||||||
}
|
}
|
||||||
|
|
||||||
fDrawingEngine->Unlock();
|
fDrawingEngine->Unlock();
|
||||||
|
fRegionPool.Recycle(visibleBorder);
|
||||||
}
|
}
|
||||||
|
|
||||||
BPoint delta = where - fLastMousePosition;
|
BPoint delta = where - fLastMousePosition;
|
||||||
@@ -1071,9 +1045,12 @@ WindowLayer::SetFocus(bool focus)
|
|||||||
// so the window thread cannot be
|
// so the window thread cannot be
|
||||||
// accessing fIsFocus
|
// accessing fIsFocus
|
||||||
|
|
||||||
BRegion dirty(fBorderRegion);
|
BRegion* dirty = fRegionPool.GetRegion(fBorderRegion);
|
||||||
dirty.IntersectWith(&fVisibleRegion);
|
if (dirty) {
|
||||||
fDesktop->MarkDirty(dirty);
|
dirty->IntersectWith(&fVisibleRegion);
|
||||||
|
fDesktop->MarkDirty(*dirty);
|
||||||
|
fRegionPool.Recycle(dirty);
|
||||||
|
}
|
||||||
|
|
||||||
fIsFocus = focus;
|
fIsFocus = focus;
|
||||||
if (fDecorator)
|
if (fDecorator)
|
||||||
@@ -1602,16 +1579,19 @@ void
|
|||||||
WindowLayer::_ShiftPartOfRegion(BRegion* region, BRegion* regionToShift,
|
WindowLayer::_ShiftPartOfRegion(BRegion* region, BRegion* regionToShift,
|
||||||
int32 xOffset, int32 yOffset)
|
int32 xOffset, int32 yOffset)
|
||||||
{
|
{
|
||||||
BRegion common(*regionToShift);
|
BRegion* common = fRegionPool.GetRegion(*regionToShift);
|
||||||
|
if (!common)
|
||||||
|
return;
|
||||||
// see if there is a common part at all
|
// see if there is a common part at all
|
||||||
common.IntersectWith(region);
|
common->IntersectWith(region);
|
||||||
if (common.CountRects() > 0) {
|
if (common->CountRects() > 0) {
|
||||||
// cut the common part from the region,
|
// cut the common part from the region,
|
||||||
// offset that to destination and include again
|
// offset that to destination and include again
|
||||||
region->Exclude(&common);
|
region->Exclude(common);
|
||||||
common.OffsetBy(xOffset, yOffset);
|
common->OffsetBy(xOffset, yOffset);
|
||||||
region->Include(&common);
|
region->Include(common);
|
||||||
}
|
}
|
||||||
|
fRegionPool.Recycle(common);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1655,19 +1635,22 @@ WindowLayer::_DrawBorder()
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// construct the region of the border that needs redrawing
|
// construct the region of the border that needs redrawing
|
||||||
BRegion dirtyBorderRegion;
|
BRegion* dirtyBorderRegion = fRegionPool.GetRegion();
|
||||||
GetBorderRegion(&dirtyBorderRegion);
|
if (!dirtyBorderRegion)
|
||||||
|
return;
|
||||||
|
GetBorderRegion(dirtyBorderRegion);
|
||||||
// intersect with our visible region
|
// intersect with our visible region
|
||||||
dirtyBorderRegion.IntersectWith(&fVisibleRegion);
|
dirtyBorderRegion->IntersectWith(&fVisibleRegion);
|
||||||
// intersect with the dirty region
|
// intersect with the dirty region
|
||||||
dirtyBorderRegion.IntersectWith(&fDirtyRegion);
|
dirtyBorderRegion->IntersectWith(&fDirtyRegion);
|
||||||
|
|
||||||
if (dirtyBorderRegion.CountRects() > 0 && fDrawingEngine->Lock()) {
|
if (dirtyBorderRegion->CountRects() > 0 && fDrawingEngine->Lock()) {
|
||||||
fDrawingEngine->ConstrainClippingRegion(&dirtyBorderRegion);
|
fDrawingEngine->ConstrainClippingRegion(dirtyBorderRegion);
|
||||||
fDecorator->Draw(dirtyBorderRegion.Frame());
|
fDecorator->Draw(dirtyBorderRegion->Frame());
|
||||||
|
|
||||||
fDrawingEngine->Unlock();
|
fDrawingEngine->Unlock();
|
||||||
}
|
}
|
||||||
|
fRegionPool.Recycle(dirtyBorderRegion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1730,15 +1713,10 @@ WindowLayer::BeginUpdate(BPrivate::PortLink& link)
|
|||||||
// NOTE: since we might "shift" parts of the
|
// NOTE: since we might "shift" parts of the
|
||||||
// internal dirty regions from the desktop thread
|
// internal dirty regions from the desktop thread
|
||||||
// in response to WindowLayer::ResizeBy(), which
|
// in response to WindowLayer::ResizeBy(), which
|
||||||
// might move arround views, this function needs to block
|
// might move arround views, the user of this function
|
||||||
// on the global clipping lock so that the internal
|
// needs to hold the global clipping lock so that the internal
|
||||||
// dirty regions are not messed with from the Desktop thread
|
// dirty regions are not messed with from the Desktop thread
|
||||||
// and ServerWindow thread at the same time.
|
// and ServerWindow thread at the same time.
|
||||||
if (!fDesktop->LockSingleWindow()) {
|
|
||||||
link.StartMessage(B_ERROR);
|
|
||||||
link.Flush();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fUpdateRequested) {
|
if (fUpdateRequested) {
|
||||||
// make the pending update session the current update session
|
// make the pending update session the current update session
|
||||||
@@ -1760,8 +1738,15 @@ WindowLayer::BeginUpdate(BPrivate::PortLink& link)
|
|||||||
if (!fContentRegionValid)
|
if (!fContentRegionValid)
|
||||||
_UpdateContentRegion();
|
_UpdateContentRegion();
|
||||||
|
|
||||||
BRegion dirty(fCurrentUpdateSession.DirtyRegion());
|
BRegion* dirty = fRegionPool.GetRegion(
|
||||||
dirty.IntersectWith(&VisibleContentRegion());
|
fCurrentUpdateSession.DirtyRegion());
|
||||||
|
if (!dirty) {
|
||||||
|
link.StartMessage(B_ERROR);
|
||||||
|
link.Flush();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dirty->IntersectWith(&VisibleContentRegion());
|
||||||
|
|
||||||
//fDrawingEngine->FillRegion(dirty, RGBColor(255, 0, 0, 255));
|
//fDrawingEngine->FillRegion(dirty, RGBColor(255, 0, 0, 255));
|
||||||
|
|
||||||
@@ -1772,10 +1757,10 @@ WindowLayer::BeginUpdate(BPrivate::PortLink& link)
|
|||||||
link.Attach<float>(fFrame.Width());
|
link.Attach<float>(fFrame.Width());
|
||||||
link.Attach<float>(fFrame.Height());
|
link.Attach<float>(fFrame.Height());
|
||||||
// append he update rect in screen coords
|
// append he update rect in screen coords
|
||||||
link.Attach<BRect>(dirty.Frame());
|
link.Attach<BRect>(dirty->Frame());
|
||||||
// find and attach all views that intersect with
|
// find and attach all views that intersect with
|
||||||
// the dirty region
|
// the dirty region
|
||||||
fTopLayer->AddTokensForLayersInRegion(link, dirty, &fContentRegion);
|
fTopLayer->AddTokensForLayersInRegion(link, *dirty, &fContentRegion);
|
||||||
// mark the end of the token "list"
|
// mark the end of the token "list"
|
||||||
link.Attach<int32>(B_NULL_TOKEN);
|
link.Attach<int32>(B_NULL_TOKEN);
|
||||||
link.Flush();
|
link.Flush();
|
||||||
@@ -1783,17 +1768,17 @@ WindowLayer::BeginUpdate(BPrivate::PortLink& link)
|
|||||||
#if DELAYED_BACKGROUND_CLEARING
|
#if DELAYED_BACKGROUND_CLEARING
|
||||||
// NOTE: turning off DELAYED_BACKGROUND_CLEARING will
|
// NOTE: turning off DELAYED_BACKGROUND_CLEARING will
|
||||||
// need investigation if it even still works...
|
// need investigation if it even still works...
|
||||||
fTopLayer->Draw(fDrawingEngine, &dirty,
|
fTopLayer->Draw(fDrawingEngine, dirty,
|
||||||
&fContentRegion, true);
|
&fContentRegion, true);
|
||||||
#endif
|
|
||||||
|
fRegionPool.Recycle(dirty);
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
printf("BeginUpdate() but no update requested!!\n");
|
printf("BeginUpdate() but no update requested!!\n");
|
||||||
link.StartMessage(B_ERROR);
|
link.StartMessage(B_ERROR);
|
||||||
link.Flush();
|
link.Flush();
|
||||||
fprintf(stderr, "WindowLayer::BeginUpdate() - no update requested!\n");
|
fprintf(stderr, "WindowLayer::BeginUpdate() - no update requested!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
fDesktop->UnlockSingleWindow();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1801,8 +1786,6 @@ void
|
|||||||
WindowLayer::EndUpdate()
|
WindowLayer::EndUpdate()
|
||||||
{
|
{
|
||||||
// NOTE: see comment in _BeginUpdate()
|
// NOTE: see comment in _BeginUpdate()
|
||||||
if (!fDesktop->LockSingleWindow())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (fInUpdate) {
|
if (fInUpdate) {
|
||||||
fCurrentUpdateSession.SetUsed(false);
|
fCurrentUpdateSession.SetUsed(false);
|
||||||
@@ -1816,8 +1799,6 @@ WindowLayer::EndUpdate()
|
|||||||
} else {
|
} else {
|
||||||
fUpdateRequested = false;
|
fUpdateRequested = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
fDesktop->UnlockSingleWindow();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#include "Decorator.h"
|
#include "Decorator.h"
|
||||||
#include "ViewLayer.h"
|
#include "ViewLayer.h"
|
||||||
|
#include "RegionPool.h"
|
||||||
#include "ServerWindow.h"
|
#include "ServerWindow.h"
|
||||||
#include "WindowList.h"
|
#include "WindowList.h"
|
||||||
|
|
||||||
@@ -56,10 +57,6 @@ class WindowLayer {
|
|||||||
::ServerWindow* ServerWindow() const { return fWindow; }
|
::ServerWindow* ServerWindow() const { return fWindow; }
|
||||||
::EventTarget& EventTarget() const { return fWindow->EventTarget(); }
|
::EventTarget& EventTarget() const { return fWindow->EventTarget(); }
|
||||||
|
|
||||||
// for convenience, handles window not attached to Desktop
|
|
||||||
bool ReadLockWindows();
|
|
||||||
void ReadUnlockWindows();
|
|
||||||
|
|
||||||
// setting and getting the "hard" clipping, you need to have
|
// setting and getting the "hard" clipping, you need to have
|
||||||
// WriteLock()ed the clipping!
|
// WriteLock()ed the clipping!
|
||||||
void SetClipping(BRegion* stillAvailableOnScreen);
|
void SetClipping(BRegion* stillAvailableOnScreen);
|
||||||
@@ -116,6 +113,16 @@ class WindowLayer {
|
|||||||
DrawingEngine* GetDrawingEngine() const
|
DrawingEngine* GetDrawingEngine() const
|
||||||
{ return fDrawingEngine; }
|
{ return fDrawingEngine; }
|
||||||
|
|
||||||
|
// managing a region pool
|
||||||
|
::RegionPool* RegionPool()
|
||||||
|
{ return &fRegionPool; }
|
||||||
|
inline BRegion* GetRegion()
|
||||||
|
{ return fRegionPool.GetRegion(); }
|
||||||
|
inline BRegion* GetRegion(const BRegion& copy)
|
||||||
|
{ return fRegionPool.GetRegion(copy); }
|
||||||
|
inline void RecycleRegion(BRegion* region)
|
||||||
|
{ fRegionPool.Recycle(region); }
|
||||||
|
|
||||||
void CopyContents(BRegion* region,
|
void CopyContents(BRegion* region,
|
||||||
int32 xOffset, int32 yOffset);
|
int32 xOffset, int32 yOffset);
|
||||||
|
|
||||||
@@ -248,6 +255,8 @@ class WindowLayer {
|
|||||||
BRegion fEffectiveDrawingRegion;
|
BRegion fEffectiveDrawingRegion;
|
||||||
bool fEffectiveDrawingRegionValid;
|
bool fEffectiveDrawingRegionValid;
|
||||||
|
|
||||||
|
::RegionPool fRegionPool;
|
||||||
|
|
||||||
BObjectList<WindowLayer> fSubsets;
|
BObjectList<WindowLayer> fSubsets;
|
||||||
|
|
||||||
// TODO: remove those some day (let the decorator handle that stuff)
|
// TODO: remove those some day (let the decorator handle that stuff)
|
||||||
@@ -322,8 +331,6 @@ class WindowLayer {
|
|||||||
int32 fMaxWidth;
|
int32 fMaxWidth;
|
||||||
int32 fMinHeight;
|
int32 fMinHeight;
|
||||||
int32 fMaxHeight;
|
int32 fMaxHeight;
|
||||||
|
|
||||||
mutable bool fReadLocked;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // WINDOW_LAYER_H
|
#endif // WINDOW_LAYER_H
|
||||||
|
|||||||
@@ -77,14 +77,18 @@ Workspace::Workspace(Desktop& desktop, int32 index)
|
|||||||
fDesktop(desktop),
|
fDesktop(desktop),
|
||||||
fCurrentWorkspace(index == desktop.CurrentWorkspace())
|
fCurrentWorkspace(index == desktop.CurrentWorkspace())
|
||||||
{
|
{
|
||||||
fDesktop.LockSingleWindow();
|
// fDesktop.LockSingleWindow();
|
||||||
|
// TODO: in which threads is this being used?
|
||||||
|
// from my investigations, it is used in the
|
||||||
|
// WorkspacesLayer::Draw(), which would have
|
||||||
|
// to hold the read lock already
|
||||||
RewindWindows();
|
RewindWindows();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Workspace::~Workspace()
|
Workspace::~Workspace()
|
||||||
{
|
{
|
||||||
fDesktop.UnlockSingleWindow();
|
// fDesktop.UnlockSingleWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ UseFreeTypeHeaders ;
|
|||||||
local defines = [ FDefines TEST_MODE=1 ] ;
|
local defines = [ FDefines TEST_MODE=1 ] ;
|
||||||
# USE_DIRECT_WINDOW_TEST_MODE=1
|
# USE_DIRECT_WINDOW_TEST_MODE=1
|
||||||
|
|
||||||
SubDirCcFlags $(defines) -fcheck-memory-usage -D_NO_INLINE_ASM ;
|
SubDirCcFlags $(defines) ; #-fcheck-memory-usage -D_NO_INLINE_ASM ;
|
||||||
SubDirC++Flags $(defines) -fcheck-memory-usage -D_NO_INLINE_ASM ;
|
SubDirC++Flags $(defines) ; #-fcheck-memory-usage -D_NO_INLINE_ASM ;
|
||||||
|
|
||||||
SEARCH_SOURCE += $(appServerDir) [ FDirName $(appServerDir) drawing ] ;
|
SEARCH_SOURCE += $(appServerDir) [ FDirName $(appServerDir) drawing ] ;
|
||||||
|
|
||||||
@@ -112,6 +112,7 @@ Server haiku_app_server :
|
|||||||
DefaultDecorator.cpp
|
DefaultDecorator.cpp
|
||||||
OffscreenServerWindow.cpp
|
OffscreenServerWindow.cpp
|
||||||
OffscreenWindowLayer.cpp
|
OffscreenWindowLayer.cpp
|
||||||
|
RegionPool.cpp
|
||||||
ServerPicture.cpp
|
ServerPicture.cpp
|
||||||
ServerScreen.cpp
|
ServerScreen.cpp
|
||||||
ViewLayer.cpp
|
ViewLayer.cpp
|
||||||
|
|||||||
Reference in New Issue
Block a user