* 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:
+131
-23
@@ -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()
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user