1/*
2 * Copyright 2010, Haiku.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Clemens Zeidler <haiku@clemens-zeidler.de>
7 */
8
9
10#include "WindowStack.h"
11
12#include <new>
13
14#include <Window.h>
15
16#include <ApplicationPrivate.h>
17#include <MessengerPrivate.h>
18#include <PortLink.h>
19#include <ServerProtocol.h>
20
21#include "StackAndTilePrivate.h"
22
23
24using namespace BPrivate;
25
26
27BWindowStack::BWindowStack(BWindow* window)
28{
29	fLink = window->fLink;
30}
31
32
33BWindowStack::~BWindowStack()
34{
35
36}
37
38
39status_t
40BWindowStack::AddWindow(const BWindow* window)
41{
42	BMessenger messenger(window);
43	return AddWindow(messenger);
44}
45
46
47status_t
48BWindowStack::AddWindow(const BMessenger& window)
49{
50	return AddWindowAt(window, -1);
51}
52
53
54status_t
55BWindowStack::AddWindowAt(const BWindow* window, int32 position)
56{
57	BMessenger messenger(window);
58	return AddWindowAt(messenger, position);
59}
60
61
62status_t
63BWindowStack::AddWindowAt(const BMessenger& window, int32 position)
64{
65	_StartMessage(kAddWindowToStack);
66
67	_AttachMessenger(window);
68	fLink->Attach<int32>(position);
69
70	int32 code = B_ERROR;
71	if (fLink->FlushWithReply(code) != B_OK)
72		return code;
73
74	return B_OK;
75}
76
77
78status_t
79BWindowStack::RemoveWindow(const BWindow* window)
80{
81	BMessenger messenger(window);
82	return RemoveWindow(messenger);
83}
84
85
86status_t
87BWindowStack::RemoveWindow(const BMessenger& window)
88{
89	_StartMessage(kRemoveWindowFromStack);
90	_AttachMessenger(window);
91
92	if (fLink->Flush() != B_OK)
93		return B_ERROR;
94
95	return B_OK;
96}
97
98
99status_t
100BWindowStack::RemoveWindowAt(int32 position, BMessenger* window)
101{
102	_StartMessage(kRemoveWindowFromStackAt);
103	fLink->Attach<int32>(position);
104
105	int32 code = B_ERROR;
106	if (fLink->FlushWithReply(code) != B_OK)
107		return code;
108
109	if (window == NULL)
110		return B_OK;
111
112	return _ReadMessenger(*window);
113}
114
115
116int32
117BWindowStack::CountWindows()
118{
119	_StartMessage(kCountWindowsOnStack);
120
121	int32 code = B_ERROR;
122	fLink->FlushWithReply(code);
123	if (code != B_OK)
124		return -1;
125
126	int32 count;
127	if (fLink->Read<int32>(&count) != B_OK)
128		return -1;
129
130	return count;
131}
132
133
134status_t
135BWindowStack::WindowAt(int32 position, BMessenger& messenger)
136{
137	_StartMessage(kWindowOnStackAt);
138	fLink->Attach<int32>(position);
139
140	int32 code = B_ERROR;
141	fLink->FlushWithReply(code);
142	if (code != B_OK)
143		return code;
144
145	return _ReadMessenger(messenger);
146}
147
148
149bool
150BWindowStack::HasWindow(const BWindow* window)
151{
152	BMessenger messenger(window);
153	return HasWindow(messenger);
154}
155
156
157bool
158BWindowStack::HasWindow(const BMessenger& window)
159{
160	_StartMessage(kStackHasWindow);
161	_AttachMessenger(window);
162
163	int32 code = B_ERROR;
164	fLink->FlushWithReply(code);
165	if (code != B_OK)
166		return false;
167
168	bool hasWindow;
169	if (fLink->Read<bool>(&hasWindow) != B_OK)
170		return false;
171
172	return hasWindow;
173}
174
175
176status_t
177BWindowStack::_AttachMessenger(const BMessenger& window)
178{
179	BMessenger::Private messengerPrivate(const_cast<BMessenger&>(window));
180	fLink->Attach<port_id>(messengerPrivate.Port());
181	fLink->Attach<int32>(messengerPrivate.Token());
182	return fLink->Attach<team_id>(messengerPrivate.Team());
183}
184
185
186status_t
187BWindowStack::_ReadMessenger(BMessenger& window)
188{
189	port_id port;
190	int32 token;
191	team_id team;
192	fLink->Read<port_id>(&port);
193	fLink->Read<int32>(&token);
194	status_t status = fLink->Read<team_id>(&team);
195	if (status != B_OK)
196		return status;
197	BMessenger::Private messengerPrivate(window);
198	messengerPrivate.SetTo(team, port, token);
199	return B_OK;
200}
201
202
203status_t
204BWindowStack::_StartMessage(int32 what)
205{
206	fLink->StartMessage(AS_TALK_TO_DESKTOP_LISTENER);
207	fLink->Attach<int32>(kMagicSATIdentifier);
208	fLink->Attach<int32>(kStacking);
209	return fLink->Attach<int32>(what);
210}
211