* Changed AS_GET_SCREEN_ID_FROM_WINDOW as well as AS_SCREEN_GET_MODE to no

longer hold the window lock. There is now a lock that guards screen changes
  in particular. This fixes the deadlocks seen in apps using BDirectWindow.
* All direct window handling now sits in the Desktop class -
  ServerWindow::HandleDirectConnection() is never called from anywhere else
  anymore. Furthermore, it's now only called when actually needed.
* Resize/move actions now always send a B_CLIPPING_MODIFIED flag, too.
* When the screen changed, the driver state is supposed to be B_MODE_CHANGED,
  not B_SCREEN_CHANGED (which is a message constant).
* Direct windows are no longer suspended too late on screen changes.
* Removed unused members of DirectWindowData, and cleaned it up a bit.
* Made MultiLocker's default, and copy constructors private - I accidently
  used them, causing the ASSERT_MULTI_*LOCKED() macros to fail.
* Added Unlock() to AutoWriteLocker as well.
* Minor cleanup.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@32742 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2009-08-27 08:50:46 +00:00
parent 5aab324272
commit 78ca6157b6
10 changed files with 277 additions and 189 deletions
+131 -23
View File
@@ -289,13 +289,15 @@ workspace_in_workspaces(int32 index, uint32 workspaces)
Desktop::Desktop(uid_t userID)
: MessageLooper("desktop"),
:
MessageLooper("desktop"),
fUserID(userID),
fSettings(NULL),
fSharedReadOnlyArea(-1),
fApplicationsLock("application list"),
fShutdownSemaphore(-1),
fScreenLock("screen lock"),
fCurrentWorkspace(0),
fPreviousWorkspace(0),
fAllWindows(kAllWindowList),
@@ -492,14 +494,14 @@ status_t
Desktop::SetScreenMode(int32 workspace, int32 id, const display_mode& mode,
bool makeDefault)
{
AutoWriteLocker _(fWindowLock);
if (workspace == B_CURRENT_WORKSPACE_INDEX)
workspace = fCurrentWorkspace;
if (workspace < 0 || workspace > kMaxWorkspaces)
return B_BAD_VALUE;
AutoWriteLocker _(fWindowLock);
Screen* screen = fVirtualScreen.ScreenByID(id);
if (screen == NULL)
return B_NAME_NOT_FOUND;
@@ -516,9 +518,17 @@ Desktop::SetScreenMode(int32 workspace, int32 id, const display_mode& mode,
// Set the new one
_SuspendDirectFrameBufferAccess();
AutoWriteLocker locker(fScreenLock);
status_t status = screen->SetMode(mode);
if (status != B_OK)
if (status != B_OK) {
locker.Unlock();
_ResumeDirectFrameBufferAccess();
return status;
}
} else {
// retrieve from settings
screen_configuration* configuration
@@ -543,6 +553,9 @@ Desktop::SetScreenMode(int32 workspace, int32 id, const display_mode& mode,
}
_ScreenChanged(screen);
if (workspace == fCurrentWorkspace)
_ResumeDirectFrameBufferAccess();
return B_OK;
}
@@ -550,14 +563,14 @@ Desktop::SetScreenMode(int32 workspace, int32 id, const display_mode& mode,
status_t
Desktop::GetScreenMode(int32 workspace, int32 id, display_mode& mode)
{
AutoReadLocker _(fScreenLock);
if (workspace == B_CURRENT_WORKSPACE_INDEX)
workspace = fCurrentWorkspace;
if (workspace < 0 || workspace > kMaxWorkspaces)
return B_BAD_VALUE;
AutoReadLocker _(fWindowLock);
if (workspace == fCurrentWorkspace) {
// retrieve from current screen
Screen* screen = fVirtualScreen.ScreenByID(id);
@@ -582,14 +595,14 @@ Desktop::GetScreenMode(int32 workspace, int32 id, display_mode& mode)
status_t
Desktop::GetScreenFrame(int32 workspace, int32 id, BRect& frame)
{
AutoReadLocker _(fScreenLock);
if (workspace == B_CURRENT_WORKSPACE_INDEX)
workspace = fCurrentWorkspace;
if (workspace < 0 || workspace > kMaxWorkspaces)
return B_BAD_VALUE;
AutoReadLocker _(fWindowLock);
if (workspace == fCurrentWorkspace) {
// retrieve from current screen
Screen* screen = fVirtualScreen.ScreenByID(id);
@@ -647,8 +660,11 @@ Desktop::RevertScreenModes(uint32 workspaces)
fWorkspaces[workspace].CurrentScreenConfiguration()
.Remove(current);
if (workspace == fCurrentWorkspace)
if (workspace == fCurrentWorkspace) {
_SuspendDirectFrameBufferAccess();
_SetCurrentWorkspaceConfiguration();
_ResumeDirectFrameBufferAccess();
}
} else
SetScreenMode(workspace, screen->ID(), stored->mode, false);
}
@@ -1078,8 +1094,12 @@ Desktop::MoveWindowBy(Window* window, float x, float y, int32 workspace)
// the dirty region starts with the visible area of the window being moved
BRegion newDirtyRegion(window->VisibleRegion());
// no more drawing for DirectWindows
window->ServerWindow()->HandleDirectConnection(B_DIRECT_STOP);
// stop direct frame buffer access
bool direct = false;
if (window->ServerWindow()->IsDirectlyAccessing()) {
window->ServerWindow()->HandleDirectConnection(B_DIRECT_STOP);
direct = true;
}
window->MoveBy((int32)x, (int32)y);
@@ -1108,9 +1128,13 @@ Desktop::MoveWindowBy(Window* window, float x, float y, int32 workspace)
_SetBackground(background);
_WindowChanged(window);
// allow DirectWindows to draw again after the visual
// content is at the new location
window->ServerWindow()->HandleDirectConnection(B_DIRECT_START | B_BUFFER_MOVED);
// resume direct frame buffer access
if (direct) {
// TODO: the clipping actually only changes when we move our window
// off screen, or behind some other window
window->ServerWindow()->HandleDirectConnection(
B_DIRECT_START | B_BUFFER_MOVED | B_CLIPPING_MODIFIED);
}
UnlockAllWindows();
}
@@ -1135,7 +1159,12 @@ Desktop::ResizeWindowBy(Window* window, float x, float y)
// it is shrunk in "previouslyOccupiedRegion"
BRegion previouslyOccupiedRegion(window->VisibleRegion());
window->ServerWindow()->HandleDirectConnection(B_DIRECT_STOP);
// stop direct frame buffer access
bool direct = false;
if (window->ServerWindow()->IsDirectlyAccessing()) {
window->ServerWindow()->HandleDirectConnection(B_DIRECT_STOP);
direct = true;
}
window->ResizeBy((int32)x, (int32)y, &newDirtyRegion);
@@ -1155,7 +1184,11 @@ Desktop::ResizeWindowBy(Window* window, float x, float y)
_SetBackground(background);
_WindowChanged(window);
window->ServerWindow()->HandleDirectConnection(B_DIRECT_START | B_BUFFER_RESIZED);
// resume direct frame buffer access
if (direct) {
window->ServerWindow()->HandleDirectConnection(
B_DIRECT_START | B_BUFFER_RESIZED | B_CLIPPING_MODIFIED);
}
UnlockAllWindows();
}
@@ -2428,8 +2461,10 @@ Desktop::_ShowWindow(Window* window, bool affectsOtherWindows)
} else
MarkDirty(dirty);
window->ServerWindow()->HandleDirectConnection(
B_DIRECT_START | B_BUFFER_RESET);
if (window->ServerWindow()->HasDirectFrameBufferAccess()) {
window->ServerWindow()->HandleDirectConnection(
B_DIRECT_START | B_BUFFER_RESET);
}
}
@@ -2439,7 +2474,8 @@ Desktop::_ShowWindow(Window* window, bool affectsOtherWindows)
void
Desktop::_HideWindow(Window* window)
{
window->ServerWindow()->HandleDirectConnection(B_DIRECT_STOP);
if (window->ServerWindow()->IsDirectlyAccessing())
window->ServerWindow()->HandleDirectConnection(B_DIRECT_STOP);
// after rebuilding the clipping,
// this window will not have a visible
@@ -2540,8 +2576,9 @@ Desktop::_ChangeWindowWorkspaces(Window* window, uint32 oldWorkspaces,
window->SetCurrentWorkspace(fCurrentWorkspace);
if (!window->IsHidden()) {
// this only affects other windows if this windows has floating or
// modal windows that need to be shown as well
// This only affects other windows if this window has
// floating or modal windows that need to be shown as
// well
// TODO: take care of this
_ShowWindow(window, FrontWindow() == window);
}
@@ -2674,6 +2711,16 @@ Desktop::_SendFakeMouseMoved(Window* window)
}
Screen*
Desktop::_DetermineScreenFor(BRect frame)
{
AutoReadLocker _(fScreenLock);
// TODO: choose the screen depending on where most of the area is
return fVirtualScreen.ScreenAt(0);
}
void
Desktop::_RebuildClippingForAllWindows(BRegion& stillAvailableOnScreen)
{
@@ -2688,6 +2735,13 @@ Desktop::_RebuildClippingForAllWindows(BRegion& stillAvailableOnScreen)
window = window->PreviousWindow(fCurrentWorkspace)) {
if (!window->IsHidden()) {
window->SetClipping(&stillAvailableOnScreen);
window->SetScreen(_DetermineScreenFor(window->Frame()));
if (window->ServerWindow()->IsDirectlyAccessing()) {
window->ServerWindow()->HandleDirectConnection(
B_DIRECT_MODIFY | B_CLIPPING_MODIFIED);
}
// that windows region is not available on screen anymore
stillAvailableOnScreen.Exclude(&window->VisibleRegion());
}
@@ -2756,6 +2810,13 @@ Desktop::_RebuildAndRedrawAfterWindowChange(Window* changedWindow,
dirty.IntersectWith(&stillAvailableOnScreen);
window->SetClipping(&stillAvailableOnScreen);
window->SetScreen(_DetermineScreenFor(window->Frame()));
if (window->ServerWindow()->IsDirectlyAccessing()) {
window->ServerWindow()->HandleDirectConnection(
B_DIRECT_MODIFY | B_CLIPPING_MODIFIED);
}
// that windows region is not available on screen anymore
stillAvailableOnScreen.Exclude(&window->VisibleRegion());
}
@@ -2768,6 +2829,39 @@ Desktop::_RebuildAndRedrawAfterWindowChange(Window* changedWindow,
}
//! Suspend all windows with direct access to the frame buffer
void
Desktop::_SuspendDirectFrameBufferAccess()
{
ASSERT_MULTI_LOCKED(fWindowLock);
for (Window* window = fAllWindows.FirstWindow(); window != NULL;
window = window->NextWindow(kAllWindowList)) {
if (window->ServerWindow()->IsDirectlyAccessing())
window->ServerWindow()->HandleDirectConnection(B_DIRECT_STOP);
}
}
//! Resume all windows with direct access to the frame buffer
void
Desktop::_ResumeDirectFrameBufferAccess()
{
ASSERT_MULTI_LOCKED(fWindowLock);
for (Window* window = fAllWindows.FirstWindow(); window != NULL;
window = window->NextWindow(kAllWindowList)) {
if (window->IsHidden() || !window->InWorkspace(fCurrentWorkspace))
continue;
if (window->ServerWindow()->HasDirectFrameBufferAccess()) {
window->ServerWindow()->HandleDirectConnection(
B_DIRECT_START | B_BUFFER_RESET, B_MODE_CHANGED);
}
}
}
void
Desktop::_ScreenChanged(Screen* screen)
{
@@ -2800,10 +2894,10 @@ Desktop::_ScreenChanged(Screen* screen)
fVirtualScreen.UpdateFrame();
// TODO: currently ignores the screen argument!
for (Window* window = fAllWindows.FirstWindow(); window != NULL;
window = window->NextWindow(kAllWindowList)) {
window->ServerWindow()->ScreenChanged(&update);
if (window->Screen() == screen)
window->ServerWindow()->ScreenChanged(&update);
}
}
@@ -2852,6 +2946,8 @@ Desktop::_SetCurrentWorkspaceConfiguration()
{
ASSERT_MULTI_WRITE_LOCKED(fWindowLock);
AutoWriteLocker _(fScreenLock);
uint32 changedScreens;
fVirtualScreen.SetConfiguration(*this,
fWorkspaces[fCurrentWorkspace].CurrentScreenConfiguration(),
@@ -2870,6 +2966,8 @@ Desktop::_SetCurrentWorkspaceConfiguration()
void
Desktop::_SetWorkspace(int32 index)
{
ASSERT_MULTI_WRITE_LOCKED(fWindowLock);
int32 previousIndex = fCurrentWorkspace;
rgb_color previousColor = fWorkspaces[fCurrentWorkspace].Color();
bool movedMouseEventWindow = false;
@@ -2914,6 +3012,10 @@ Desktop::_SetWorkspace(int32 index)
// store current position in Workspace anchor
window->Anchor(previousIndex).position = window->Frame().LeftTop();
if (!window->IsHidden()
&& window->ServerWindow()->IsDirectlyAccessing())
window->ServerWindow()->HandleDirectConnection(B_DIRECT_STOP);
window->WorkspaceActivated(previousIndex, false);
if (window->InWorkspace(index))
@@ -2998,6 +3100,12 @@ Desktop::_SetWorkspace(int32 index)
// send B_WORKSPACE_ACTIVATED message
window->WorkspaceActivated(index, true);
if (!window->IsHidden()
&& window->ServerWindow()->HasDirectFrameBufferAccess()) {
window->ServerWindow()->HandleDirectConnection(
B_DIRECT_START | B_BUFFER_RESET, B_MODE_CHANGED);
}
if (window->InWorkspace(previousIndex) || window->IsHidden()
|| (window == fMouseEventWindow && fMouseEventWindow->IsNormal())
|| (!window->IsNormal()
+8 -1
View File
@@ -86,7 +86,7 @@ public:
void UnlockAllWindows()
{ fWindowLock.WriteUnlock(); }
MultiLocker WindowLocker() { return fWindowLock; }
const MultiLocker& WindowLocker() { return fWindowLock; }
#else // USE_MULTI_LOCKER
bool LockSingleWindow()
{ return fWindowLock.Lock(); }
@@ -125,6 +125,8 @@ public:
BRect& frame);
void RevertScreenModes(uint32 workspaces);
MultiLocker& ScreenLocker() { return fScreenLock; }
const ::VirtualScreen& VirtualScreen() const
{ return fVirtualScreen; }
DrawingEngine* GetDrawingEngine() const
@@ -268,6 +270,7 @@ private:
Window* _LastFocusSubsetWindow(Window* window);
void _SendFakeMouseMoved(Window* window = NULL);
Screen* _DetermineScreenFor(BRect frame);
void _RebuildClippingForAllWindows(
BRegion& stillAvailableOnScreen);
void _TriggerWindowRedrawing(
@@ -278,6 +281,9 @@ private:
status_t _ActivateApp(team_id team);
void _SuspendDirectFrameBufferAccess();
void _ResumeDirectFrameBufferAccess();
void _ScreenChanged(Screen* screen);
void _SetCurrentWorkspaceConfiguration();
void _SetWorkspace(int32 index);
@@ -302,6 +308,7 @@ private:
int32 fShutdownCount;
::Workspace::Private fWorkspaces[kMaxWorkspaces];
MultiLocker fScreenLock;
int32 fCurrentWorkspace;
int32 fPreviousWorkspace;
+13 -29
View File
@@ -7,17 +7,18 @@
* Axel Dörfler, [email protected]
*/
#include "DirectWindowSupport.h"
#include <stdio.h>
#include <string.h>
#include <syslog.h>
#include <Autolock.h>
#include "RenderingBuffer.h"
#include "clipping.h"
#include <stdio.h>
#include <string.h>
#include <syslog.h>
DirectWindowData::DirectWindowData()
:
@@ -25,9 +26,7 @@ DirectWindowData::DirectWindowData()
fBufferInfo(NULL),
fSem(-1),
fAcknowledgeSem(-1),
fBufferArea(-1),
fTransition(0),
fStarted(false)
fBufferArea(-1)
{
fBufferArea = create_area("direct area", (void**)&fBufferInfo,
B_ANY_ADDRESS, DIRECT_BUFFER_INFO_AREA_SIZE,
@@ -87,46 +86,31 @@ DirectWindowData::_SyncronizeWithClient()
if (status != B_OK)
return status;
//syslog(LOG_INFO, "Syncronize: released sem");
// Wait with a timeout of half a second until the client exits
// from its DirectConnected() implementation
do {
#if 0
status = acquire_sem(fAcknowledgeSem);
#else
#else
status = acquire_sem_etc(fAcknowledgeSem, 1, B_TIMEOUT, 500000);
#endif
} while (status == B_INTERRUPTED);
//syslog(LOG_INFO, "Syncronize: acquired sem");
return status;
}
status_t
DirectWindowData::SetState(const direct_buffer_state& bufferState,
const direct_driver_state& driverState, RenderingBuffer *buffer,
DirectWindowData::SetState(direct_buffer_state bufferState,
direct_driver_state driverState, RenderingBuffer* buffer,
const BRect& windowFrame, const BRegion& clipRegion)
{
if (!fStarted && (bufferState & B_DIRECT_MODE_MASK)
!= B_DIRECT_START)
return B_OK;
{
if ((fBufferInfo->buffer_state & B_DIRECT_MODE_MASK) == B_DIRECT_STOP
&& (bufferState & B_DIRECT_MODE_MASK) != B_DIRECT_START)
return B_OK;
#if 0
if ((bufferState & B_DIRECT_MODE_MASK) == B_DIRECT_MODIFY)
syslog(LOG_INFO, "direct_modify");
#endif
fStarted = true;
#if 0
char string[256];
snprintf(string, sizeof(string), "bufferState: 0x%x\n", (int)bufferState);
syslog(LOG_INFO, string);
#endif
fBufferInfo->buffer_state = bufferState;
if (driverState != -1)
fBufferInfo->driver_state = driverState;
@@ -180,6 +164,6 @@ DirectWindowData::SetState(const direct_buffer_state& bufferState,
for (uint32 i = 0; i < fBufferInfo->clip_list_count; i++)
fBufferInfo->clip_list[i] = clipRegion.RectAtInt(i);
}
return _SyncronizeWithClient();
}
+10 -28
View File
@@ -3,6 +3,9 @@
* Distributed under the terms of the MIT License.
*
*/
#ifndef DIRECT_WINDOW_SUPPORT_H
#define DIRECT_WINDOW_SUPPORT_H
#include <Autolock.h>
#include <DirectWindow.h>
@@ -11,26 +14,6 @@
class RenderingBuffer;
struct BufferState {
BufferState(const direct_buffer_state& state)
:
fState(state)
{
}
inline direct_buffer_state Action() const
{
return (direct_buffer_state)(fState & B_DIRECT_MODE_MASK);
}
inline direct_buffer_state Reason() const
{
return (direct_buffer_state)(fState & ~B_DIRECT_MODE_MASK);
}
direct_buffer_state fState;
};
class DirectWindowData {
public:
@@ -43,24 +26,23 @@ public:
direct_window_sync_data& data) const;
status_t SyncronizeWithClient();
status_t SetState(const direct_buffer_state& bufferState,
const direct_driver_state& driverState,
RenderingBuffer *renderingBuffer,
status_t SetState(direct_buffer_state bufferState,
direct_driver_state driverState,
RenderingBuffer* renderingBuffer,
const BRect& windowFrame,
const BRegion& clipRegion);
BRect old_window_frame;
bool full_screen;
private:
status_t _SyncronizeWithClient();
direct_buffer_info* fBufferInfo;
direct_buffer_info* fBufferInfo;
sem_id fSem;
sem_id fAcknowledgeSem;
area_id fBufferArea;
direct_buffer_state fPreviousState;
int32 fTransition;
bool fStarted;
};
#endif // DIRECT_WINDOW_SUPPORT_H
+21 -7
View File
@@ -2,7 +2,7 @@
* Copyright 2005-2009, Haiku, Inc. All Rights Reserved.
* 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.
*/
#ifndef MULTI_LOCKER_H
@@ -66,6 +66,11 @@ public:
#endif
private:
MultiLocker();
MultiLocker(const MultiLocker& other);
MultiLocker& operator=(const MultiLocker& other);
// not implemented
#if MULTI_LOCKER_DEBUG
// functions for managing the DEBUG reader array
void _RegisterThread();
@@ -114,14 +119,20 @@ public:
:
fLock(*lock)
{
fLock.WriteLock();
fLocked = fLock.WriteLock();
}
AutoWriteLocker(MultiLocker& lock)
:
fLock(lock)
{
fLock.WriteLock();
fLocked = fLock.WriteLock();
}
~AutoWriteLocker()
{
if (fLocked)
fLock.WriteUnlock();
}
bool IsLocked() const
@@ -129,13 +140,17 @@ public:
return fLock.IsWriteLocked();
}
~AutoWriteLocker()
void Unlock()
{
fLock.WriteUnlock();
if (fLocked) {
fLock.WriteUnlock();
fLocked = false;
}
}
private:
MultiLocker& fLock;
bool fLocked;
};
@@ -160,8 +175,7 @@ public:
Unlock();
}
void
Unlock()
void Unlock()
{
if (fLocked) {
fLock.ReadUnlock();
+14 -9
View File
@@ -2252,36 +2252,41 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
case AS_GET_SCREEN_ID_FROM_WINDOW:
{
status_t status = B_ENTRY_NOT_FOUND;
status_t status = B_BAD_VALUE;
// Attached data
// 1) int32 - window client token
int32 clientToken;
if (link.Read<int32>(&clientToken) != B_OK)
status = B_BAD_DATA;
else if (fDesktop->LockAllWindows()) {
else {
BAutolock locker(fWindowListLock);
for (int32 i = fWindowList.CountItems(); i-- > 0;) {
ServerWindow* window = fWindowList.ItemAt(i);
ServerWindow* serverWindow = fWindowList.ItemAt(i);
if (serverWindow->ClientToken() == clientToken) {
AutoReadLocker _(fDesktop->ScreenLocker());
if (window->ClientToken() == clientToken) {
// found it!
if (window->Window() == NULL) {
Window* window = serverWindow->Window();
const Screen* screen = NULL;
if (window != NULL)
screen = window->Screen();
if (screen == NULL) {
// The window hasn't been added to the desktop yet,
// or it's an offscreen window
break;
}
fLink.StartMessage(B_OK);
fLink.Attach<int32>(window->Window()->Screen()->ID());
fLink.Attach<int32>(screen->ID());
status = B_OK;
break;
}
}
fDesktop->UnlockAllWindows();
} else
status = B_ERROR;
}
if (status != B_OK)
fLink.StartMessage(status);
+24 -39
View File
@@ -167,6 +167,7 @@ ServerWindow::ServerWindow(const char* title, ServerApp* app,
fCurrentDrawingRegionValid(false),
fDirectWindowData(NULL),
fIsDirectlyAccessing(false),
fDirectWindowFeel(B_NORMAL_WINDOW_FEEL)
{
STRACE(("ServerWindow(%s)::ServerWindow()\n", title));
@@ -3401,8 +3402,6 @@ ServerWindow::_MessageLooper()
void
ServerWindow::ScreenChanged(const BMessage* message)
{
// TODO: execute the stop notification earlier
HandleDirectConnection(B_DIRECT_STOP);
SendMessageToClient(message);
if (fDirectWindowData != NULL && fDirectWindowData->full_screen) {
@@ -3411,9 +3410,6 @@ ServerWindow::ScreenChanged(const BMessage* message)
screenFrame.Width() - fWindow->Frame().Width(),
screenFrame.Height() - fWindow->Frame().Height());
}
HandleDirectConnection(B_DIRECT_START | B_BUFFER_RESET,
B_SCREEN_CHANGED);
}
@@ -3441,15 +3437,6 @@ ServerWindow::MakeWindow(BRect frame, const char* name,
}
/* static */
bool
ServerWindow::_SupportsDirectMode()
{
return false;
// TODO: For now, since it's broken
}
status_t
ServerWindow::_EnableDirectWindowMode()
{
@@ -3458,9 +3445,6 @@ ServerWindow::_EnableDirectWindowMode()
return B_ERROR;
}
if (!ServerWindow::_SupportsDirectMode())
return B_ERROR;
fDirectWindowData = new (nothrow) DirectWindowData;
if (fDirectWindowData == NULL)
return B_NO_MEMORY;
@@ -3480,34 +3464,35 @@ ServerWindow::_EnableDirectWindowMode()
void
ServerWindow::HandleDirectConnection(int32 bufferState, int32 driverState)
{
STRACE(("HandleDirectConnection(bufferState = %ld, driverState = %ld)\n",
bufferState, driverState));
ASSERT_MULTI_LOCKED(fDesktop->WindowLocker());
if (fDirectWindowData == NULL)
return;
if (fDesktop->LockSingleWindow()) {
status_t status = fDirectWindowData->SetState(
(direct_buffer_state)bufferState,
(direct_driver_state)driverState,
fDesktop->HWInterface()->FrontBuffer(), fWindow->Frame(),
fWindow->VisibleContentRegion());
STRACE(("HandleDirectConnection(bufferState = %ld, driverState = %ld)\n",
bufferState, driverState));
if (status != B_OK) {
char errorString[256];
snprintf(errorString, sizeof(errorString),
"%s killed for a problem in DirectConnected(): %s",
App()->Signature(), strerror(status));
syslog(LOG_ERR, errorString);
status_t status = fDirectWindowData->SetState(
(direct_buffer_state)bufferState, (direct_driver_state)driverState,
fDesktop->HWInterface()->FrontBuffer(), fWindow->Frame(),
fWindow->VisibleContentRegion());
// The client application didn't release the semaphore
// within the given timeout. Or something else went wrong.
// Deleting this member should make it crash.
delete fDirectWindowData;
fDirectWindowData = NULL;
}
fDesktop->UnlockSingleWindow();
}
if (status != B_OK) {
char errorString[256];
snprintf(errorString, sizeof(errorString),
"%s killed for a problem in DirectConnected(): %s",
App()->Signature(), strerror(status));
syslog(LOG_ERR, errorString);
// The client application didn't release the semaphore
// within the given timeout. Or something else went wrong.
// Deleting this member should make it crash.
delete fDirectWindowData;
fDirectWindowData = NULL;
} else if ((bufferState & B_DIRECT_MODE_MASK) == B_DIRECT_START)
fIsDirectlyAccessing = true;
else if ((bufferState & B_DIRECT_MODE_MASK) == B_DIRECT_STOP)
fIsDirectlyAccessing = false;
}
+19 -14
View File
@@ -13,12 +13,6 @@
#define SERVER_WINDOW_H
#include "EventDispatcher.h"
#include "MessageLooper.h"
#include <PortLink.h>
#include <TokenSpace.h>
#include <GraphicsDefs.h>
#include <Locker.h>
#include <Message.h>
@@ -28,6 +22,13 @@
#include <String.h>
#include <Window.h>
#include <PortLink.h>
#include <TokenSpace.h>
#include "EventDispatcher.h"
#include "MessageLooper.h"
class BString;
class BMessenger;
class BPoint;
@@ -47,6 +48,7 @@ struct window_info;
#define AS_UPDATE_COLORS 'asuc'
#define AS_UPDATE_FONTS 'asuf'
class ServerWindow : public MessageLooper {
public:
ServerWindow(const char *title, ServerApp *app,
@@ -77,8 +79,8 @@ public:
const BMessenger& HandlerMessenger() const
{ return fHandlerMessenger; }
void ScreenChanged(const BMessage *screenChangedMessage);
status_t SendMessageToClient(const BMessage* msg,
void ScreenChanged(const BMessage* message);
status_t SendMessageToClient(const BMessage* message,
int32 target = B_NULL_TOKEN) const;
virtual ::Window* MakeWindow(BRect frame, const char* name,
@@ -91,9 +93,6 @@ public:
// related thread/team_id(s).
inline team_id ClientTeam() const { return fClientTeam; }
void HandleDirectConnection(int32 bufferState,
int32 driverState = -1);
inline int32 ClientToken() const { return fClientToken; }
inline int32 ServerToken() const { return fServerToken; }
@@ -101,6 +100,13 @@ public:
void GetInfo(window_info& info);
void HandleDirectConnection(int32 bufferState,
int32 driverState = 0);
bool HasDirectFrameBufferAccess() const
{ return fDirectWindowData != NULL; }
bool IsDirectlyAccessing() const
{ return fIsDirectlyAccessing; }
void ResyncDrawState();
// TODO: Change this
@@ -127,8 +133,8 @@ private:
virtual void _PrepareQuit();
virtual void _GetLooperName(char* name, size_t size);
static bool _SupportsDirectMode();
status_t _EnableDirectWindowMode();
void _DirectWindowSetFullScreen(bool set);
void _SetCurrentView(View* view);
void _UpdateDrawState(View* view);
@@ -137,8 +143,6 @@ private:
bool _MessageNeedsAllWindowsLocked(
uint32 code) const;
void _DirectWindowSetFullScreen(bool set);
// TODO: Move me elsewhere
status_t PictureToRegion(ServerPicture *picture,
BRegion& region, bool inverse,
@@ -171,6 +175,7 @@ private:
bool fCurrentDrawingRegionValid;
DirectWindowData* fDirectWindowData;
bool fIsDirectlyAccessing;
window_feel fDirectWindowFeel;
};
+28 -29
View File
@@ -77,6 +77,7 @@ Window::Window(const BRect& frame, const char *name,
:
fTitle(name),
fFrame(frame),
fScreen(NULL),
fVisibleRegion(),
fVisibleContentRegion(),
@@ -213,8 +214,6 @@ Window::SetClipping(BRegion* stillAvailableOnScreen)
fVisibleContentRegionValid = false;
fEffectiveDrawingRegionValid = false;
fWindow->HandleDirectConnection(B_DIRECT_MODIFY | B_CLIPPING_MODIFIED);
}
@@ -562,13 +561,19 @@ Window::PreviousWindow(int32 index) const
}
::Screen*
void
Window::SetScreen(const ::Screen* screen)
{
ASSERT_MULTI_WRITE_LOCKED(fDesktop->ScreenLocker());
fScreen = screen;
}
const ::Screen*
Window::Screen() const
{
ASSERT_MULTI_LOCKED(fDesktop->WindowLocker());
// TODO: we need to know which screen the window is on
return fDesktop->VirtualScreen().ScreenAt(0);
ASSERT_MULTI_READ_LOCKED(fDesktop->ScreenLocker());
return fScreen;
}
@@ -1215,18 +1220,12 @@ Window::_AlterDeltaForSnap(BPoint& delta, bigtime_t now)
void
Window::WorkspaceActivated(int32 index, bool active)
{
if (!active && !IsHidden())
fWindow->HandleDirectConnection(B_DIRECT_STOP);
BMessage activatedMsg(B_WORKSPACE_ACTIVATED);
activatedMsg.AddInt64("when", system_time());
activatedMsg.AddInt32("workspace", index);
activatedMsg.AddBool("active", active);
ServerWindow()->SendMessageToClient(&activatedMsg);
if (active && !IsHidden())
fWindow->HandleDirectConnection(B_DIRECT_START | B_BUFFER_RESET);
}
@@ -1338,8 +1337,8 @@ Window::IsVisible() const
void
Window::SetSizeLimits(int32 minWidth, int32 maxWidth,
int32 minHeight, int32 maxHeight)
Window::SetSizeLimits(int32 minWidth, int32 maxWidth, int32 minHeight,
int32 maxHeight)
{
if (minWidth < 0)
minWidth = 0;
@@ -1354,8 +1353,8 @@ Window::SetSizeLimits(int32 minWidth, int32 maxWidth,
// give the Decorator a say in this too
if (fDecorator) {
fDecorator->GetSizeLimits(&fMinWidth, &fMinHeight,
&fMaxWidth, &fMaxHeight);
fDecorator->GetSizeLimits(&fMinWidth, &fMinHeight, &fMaxWidth,
&fMaxHeight);
}
_ObeySizeLimits();
@@ -1455,7 +1454,8 @@ Window::SetLook(window_look look, BRegion* updateRegion)
fDecorator->SetLook(settings, look, updateRegion);
// we might need to resize the window!
fDecorator->GetSizeLimits(&fMinWidth, &fMinHeight, &fMaxWidth, &fMaxHeight);
fDecorator->GetSizeLimits(&fMinWidth, &fMinHeight, &fMaxWidth,
&fMaxHeight);
_ObeySizeLimits();
}
@@ -1471,8 +1471,10 @@ void
Window::SetFeel(window_feel feel)
{
// if the subset list is no longer needed, clear it
if ((fFeel == B_MODAL_SUBSET_WINDOW_FEEL || fFeel == B_FLOATING_SUBSET_WINDOW_FEEL)
&& (feel != B_MODAL_SUBSET_WINDOW_FEEL && feel != B_FLOATING_SUBSET_WINDOW_FEEL))
if ((fFeel == B_MODAL_SUBSET_WINDOW_FEEL
|| fFeel == B_FLOATING_SUBSET_WINDOW_FEEL)
&& feel != B_MODAL_SUBSET_WINDOW_FEEL
&& feel != B_FLOATING_SUBSET_WINDOW_FEEL)
fSubsets.MakeEmpty();
fFeel = feel;
@@ -1793,8 +1795,7 @@ Window::InSubsetWorkspace(int32 index) const
// #pragma mark - static
/*static*/
bool
/*static*/ bool
Window::IsValidLook(window_look look)
{
return look == B_TITLED_WINDOW_LOOK
@@ -1808,8 +1809,7 @@ Window::IsValidLook(window_look look)
}
/*static*/
bool
/*static*/ bool
Window::IsValidFeel(window_feel feel)
{
return feel == B_NORMAL_WINDOW_FEEL
@@ -1826,8 +1826,7 @@ Window::IsValidFeel(window_feel feel)
}
/*static*/
bool
/*static*/ bool
Window::IsModalFeel(window_feel feel)
{
return feel == B_MODAL_SUBSET_WINDOW_FEEL
@@ -1836,8 +1835,7 @@ Window::IsModalFeel(window_feel feel)
}
/*static*/
bool
/*static*/ bool
Window::IsFloatingFeel(window_feel feel)
{
return feel == B_FLOATING_SUBSET_WINDOW_FEEL
@@ -2115,7 +2113,8 @@ Window::BeginUpdate(BPrivate::PortLink& link)
// supress back to front buffer copies in the drawing engine
fDrawingEngine->SetCopyToFrontEnabled(false);
if (!fCurrentUpdateSession->IsExpose() && fDrawingEngine->LockParallelAccess()) {
if (!fCurrentUpdateSession->IsExpose()
&& fDrawingEngine->LockParallelAccess()) {
fDrawingEngine->SuspendAutoSync();
fTopView->Draw(fDrawingEngine, dirty, &fContentRegion, true);
+9 -10
View File
@@ -67,7 +67,8 @@ public:
::EventTarget& EventTarget() const
{ return fWindow->EventTarget(); }
::Screen* Screen() const;
void SetScreen(const ::Screen* screen);
const ::Screen* Screen() const;
// setting and getting the "hard" clipping, you need to have
// WriteLock()ed the clipping!
@@ -234,18 +235,15 @@ public:
void FindWorkspacesViews(
BObjectList<WorkspacesView>& list) const;
static bool IsValidLook(window_look look);
static bool IsValidFeel(window_feel feel);
static bool IsModalFeel(window_feel feel);
static bool IsFloatingFeel(window_feel feel);
static bool IsValidLook(window_look look);
static bool IsValidFeel(window_feel feel);
static bool IsModalFeel(window_feel feel);
static bool IsFloatingFeel(window_feel feel);
static uint32 ValidWindowFlags();
static uint32 ValidWindowFlags(window_feel feel);
static uint32 ValidWindowFlags();
static uint32 ValidWindowFlags(window_feel feel);
protected:
friend class Desktop;
// TODO: for now (list management)
void _ShiftPartOfRegion(BRegion* region,
BRegion* regionToShift, int32 xOffset,
int32 yOffset);
@@ -278,6 +276,7 @@ protected:
BString fTitle;
// TODO: no fp rects anywhere
BRect fFrame;
const ::Screen* fScreen;
window_anchor fAnchor[kListCount];