xref: /haiku/src/kits/interface/WindowStack.cpp (revision e0ef64750f3169cd634bb2f7a001e22488b05231)
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 
24 using namespace BPrivate;
25 
26 
27 BWindowStack::BWindowStack(BWindow* window)
28 	:
29 	fLink(NULL)
30 {
31 	port_id receivePort = create_port(B_LOOPER_PORT_DEFAULT_CAPACITY,
32 		"w_stack<app_server");
33 	if (receivePort != B_OK)
34 		fLink = new(std::nothrow) BPrivate::PortLink(
35 			window->fLink->SenderPort(), receivePort);
36 }
37 
38 
39 BWindowStack::~BWindowStack()
40 {
41 	if (fLink)
42 		delete_port(fLink->ReceiverPort());
43 	delete fLink;
44 }
45 
46 
47 status_t
48 BWindowStack::InitCheck()
49 {
50 	if (!fLink)
51 		return B_NO_MEMORY;
52 	return B_OK;
53 }
54 
55 
56 status_t
57 BWindowStack::AddWindow(BWindow* window)
58 {
59 	BMessenger messenger(window);
60 	return AddWindow(messenger);
61 }
62 
63 
64 status_t
65 BWindowStack::AddWindow(BMessenger& window)
66 {
67 	return AddWindowAt(window, -1);
68 }
69 
70 
71 status_t
72 BWindowStack::AddWindowAt(BWindow* window, int32 position)
73 {
74 	BMessenger messenger(window);
75 	return AddWindowAt(messenger, position);
76 }
77 
78 
79 status_t
80 BWindowStack::AddWindowAt(BMessenger& window, int32 position)
81 {
82 	_StartMessage(kAddWindowToStack);
83 
84 	_AttachMessenger(window);
85 	fLink->Attach<int32>(position);
86 
87 	int32 code = B_ERROR;
88 	if (fLink->FlushWithReply(code) != B_OK)
89 		return code;
90 
91 	return B_OK;
92 }
93 
94 
95 status_t
96 BWindowStack::RemoveWindow(BWindow* window)
97 {
98 	BMessenger messenger(window);
99 	return RemoveWindow(messenger);
100 }
101 
102 
103 status_t
104 BWindowStack::RemoveWindow(BMessenger& window)
105 {
106 	_StartMessage(kRemoveWindowFromStack);
107 	_AttachMessenger(window);
108 
109 	if (fLink->Flush() != B_OK)
110 		return B_ERROR;
111 
112 	return B_OK;
113 }
114 
115 
116 status_t
117 BWindowStack::RemoveWindowAt(int32 position, BMessenger* window)
118 {
119 	_StartMessage(kRemoveWindowFromStackAt);
120 	fLink->Attach<int32>(position);
121 
122 	int32 code = B_ERROR;
123 	if (fLink->FlushWithReply(code) != B_OK)
124 		return code;
125 
126 	if (window == NULL)
127 		return B_OK;
128 
129 	return _ReadMessenger(*window);
130 }
131 
132 
133 int32
134 BWindowStack::CountWindows()
135 {
136 	_StartMessage(kCountWindowsOnStack);
137 
138 	int32 code = B_ERROR;
139 	fLink->FlushWithReply(code);
140 	if (code != B_OK)
141 		return -1;
142 
143 	int32 count;
144 	if (fLink->Read<int32>(&count) != B_OK)
145 		return -1;
146 
147 	return count;
148 }
149 
150 
151 status_t
152 BWindowStack::WindowAt(int32 position, BMessenger& messenger)
153 {
154 	_StartMessage(kWindowOnStackAt);
155 	fLink->Attach<int32>(position);
156 
157 	int32 code = B_ERROR;
158 	fLink->FlushWithReply(code);
159 	if (code != B_OK)
160 		return code;
161 
162 	return _ReadMessenger(messenger);
163 }
164 
165 
166 bool
167 BWindowStack::HasWindow(BWindow* window)
168 {
169 	BMessenger messenger(window);
170 	return HasWindow(messenger);
171 }
172 
173 
174 bool
175 BWindowStack::HasWindow(BMessenger& window)
176 {
177 	_StartMessage(kStackHasWindow);
178 	_AttachMessenger(window);
179 
180 	int32 code = B_ERROR;
181 	fLink->FlushWithReply(code);
182 	if (code != B_OK)
183 		return code;
184 
185 	bool hasWindow;
186 	if (fLink->Read<bool>(&hasWindow) != B_OK)
187 		return false;
188 
189 	return hasWindow;
190 }
191 
192 
193 status_t
194 BWindowStack::_AttachMessenger(BMessenger& window)
195 {
196 	BMessenger::Private messengerPrivate(window);
197 	fLink->Attach<port_id>(messengerPrivate.Port());
198 	fLink->Attach<int32>(messengerPrivate.Token());
199 	return fLink->Attach<team_id>(messengerPrivate.Team());
200 }
201 
202 
203 status_t
204 BWindowStack::_ReadMessenger(BMessenger& window)
205 {
206 	port_id port;
207 	int32 token;
208 	team_id team;
209 	fLink->Read<port_id>(&port);
210 	fLink->Read<int32>(&token);
211 	status_t status = fLink->Read<team_id>(&team);
212 	if (status != B_OK)
213 		return status;
214 	BMessenger::Private messengerPrivate(window);
215 	messengerPrivate.SetTo(team, port, token);
216 	return B_OK;
217 }
218 
219 
220 status_t
221 BWindowStack::_StartMessage(int32 what)
222 {
223 	fLink->StartMessage(AS_TALK_TO_DESKTOP_LISTENER);
224 	fLink->Attach<port_id>(fLink->ReceiverPort());
225 	fLink->Attach<int32>(kMagicSATIdentifier);
226 	return fLink->Attach<int32>(what);
227 }
228