root/src/kits/interface/WindowStack.cpp
/*
 * Copyright 2010, Haiku.
 * Distributed under the terms of the MIT License.
 *
 * Authors:
 *              Clemens Zeidler <haiku@clemens-zeidler.de>
 */


#include "WindowStack.h"

#include <new>

#include <Window.h>

#include <ApplicationPrivate.h>
#include <MessengerPrivate.h>
#include <PortLink.h>
#include <ServerProtocol.h>

#include "StackAndTilePrivate.h"


using namespace BPrivate;


BWindowStack::BWindowStack(BWindow* window)
{
        fLink = window->fLink;
}


BWindowStack::~BWindowStack()
{

}


status_t
BWindowStack::AddWindow(const BWindow* window)
{
        BMessenger messenger(window);
        return AddWindow(messenger);
}


status_t
BWindowStack::AddWindow(const BMessenger& window)
{
        return AddWindowAt(window, -1);
}


status_t
BWindowStack::AddWindowAt(const BWindow* window, int32 position)
{
        BMessenger messenger(window);
        return AddWindowAt(messenger, position);
}


status_t
BWindowStack::AddWindowAt(const BMessenger& window, int32 position)
{
        _StartMessage(kAddWindowToStack);

        _AttachMessenger(window);
        fLink->Attach<int32>(position);

        int32 code = B_ERROR;
        if (fLink->FlushWithReply(code) != B_OK)
                return code;

        return B_OK;
}


status_t
BWindowStack::RemoveWindow(const BWindow* window)
{
        BMessenger messenger(window);
        return RemoveWindow(messenger);
}


status_t
BWindowStack::RemoveWindow(const BMessenger& window)
{
        _StartMessage(kRemoveWindowFromStack);
        _AttachMessenger(window);

        if (fLink->Flush() != B_OK)
                return B_ERROR;

        return B_OK;
}


status_t
BWindowStack::RemoveWindowAt(int32 position, BMessenger* window)
{
        _StartMessage(kRemoveWindowFromStackAt);
        fLink->Attach<int32>(position);

        int32 code = B_ERROR;
        if (fLink->FlushWithReply(code) != B_OK)
                return code;

        if (window == NULL)
                return B_OK;

        return _ReadMessenger(*window);
}


int32
BWindowStack::CountWindows()
{
        _StartMessage(kCountWindowsOnStack);

        int32 code = B_ERROR;
        fLink->FlushWithReply(code);
        if (code != B_OK)
                return -1;

        int32 count;
        if (fLink->Read<int32>(&count) != B_OK)
                return -1;

        return count;
}


status_t
BWindowStack::WindowAt(int32 position, BMessenger& messenger)
{
        _StartMessage(kWindowOnStackAt);
        fLink->Attach<int32>(position);

        int32 code = B_ERROR;
        fLink->FlushWithReply(code);
        if (code != B_OK)
                return code;

        return _ReadMessenger(messenger);
}


bool
BWindowStack::HasWindow(const BWindow* window)
{
        BMessenger messenger(window);
        return HasWindow(messenger);
}


bool
BWindowStack::HasWindow(const BMessenger& window)
{
        _StartMessage(kStackHasWindow);
        _AttachMessenger(window);

        int32 code = B_ERROR;
        fLink->FlushWithReply(code);
        if (code != B_OK)
                return false;

        bool hasWindow;
        if (fLink->Read<bool>(&hasWindow) != B_OK)
                return false;
                
        return hasWindow;
}


status_t
BWindowStack::_AttachMessenger(const BMessenger& window)
{
        BMessenger::Private messengerPrivate(const_cast<BMessenger&>(window));
        fLink->Attach<port_id>(messengerPrivate.Port());
        fLink->Attach<int32>(messengerPrivate.Token());
        return fLink->Attach<team_id>(messengerPrivate.Team());
}


status_t
BWindowStack::_ReadMessenger(BMessenger& window)
{
        port_id port;
        int32 token;
        team_id team;
        fLink->Read<port_id>(&port);
        fLink->Read<int32>(&token);
        status_t status = fLink->Read<team_id>(&team);
        if (status != B_OK)
                return status;
        BMessenger::Private messengerPrivate(window);
        messengerPrivate.SetTo(team, port, token);
        return B_OK;
}


status_t
BWindowStack::_StartMessage(int32 what)
{
        fLink->StartMessage(AS_TALK_TO_DESKTOP_LISTENER);
        fLink->Attach<int32>(kMagicSATIdentifier);
        fLink->Attach<int32>(kStacking);
        return fLink->Attach<int32>(what);
}