175936a02SAxel Dörfler/*
27a3892f4SRene Gollent * Copyright 2001-2016 Haiku, Inc. All rights reserved
375936a02SAxel Dörfler * Distributed under the terms of the MIT License.
475936a02SAxel Dörfler *
575936a02SAxel Dörfler * Authors:
675e162f7SJohn Scipione *		Stephan A��mus, superstippi@gmx.de
775936a02SAxel Dörfler *		Axel D��rfler, axeld@pinc-software.de
875e162f7SJohn Scipione *		Adrian Oanca, adioanca@cotty.iren.ro
975e162f7SJohn Scipione *		John Scipione, jscipione@gmail.com
1075936a02SAxel Dörfler */
1175936a02SAxel Dörfler
1275936a02SAxel Dörfler
137cb93378SAxel Dörfler#include <Window.h>
147cb93378SAxel Dörfler
157cb93378SAxel Dörfler#include <ctype.h>
167cb93378SAxel Dörfler#include <math.h>
177cb93378SAxel Dörfler#include <stdio.h>
1818cd67c7SMichael Lotz#include <stdlib.h>
197cb93378SAxel Dörfler
20bf17b6acSAdi Oanca#include <Application.h>
21a99b9010SJohn Scipione#include <AppMisc.h>
22a99b9010SJohn Scipione#include <AppServerLink.h>
23a99b9010SJohn Scipione#include <ApplicationPrivate.h>
2414d02d22SAxel Dörfler#include <Autolock.h>
256aede71cSRyan Leavengood#include <Bitmap.h>
2614d02d22SAxel Dörfler#include <Button.h>
27b1b84675SJohn Scipione#include <Deskbar.h>
28a99b9010SJohn Scipione#include <DirectMessageTarget.h>
29cf1c3227SJérôme Duval#include <FindDirectory.h>
30a99b9010SJohn Scipione#include <InputServerTypes.h>
312ff62714SRyan Leavengood#include <Layout.h>
322ff62714SRyan Leavengood#include <LayoutUtils.h>
336c69f6e9SDarkWyrm#include <MenuBar.h>
3471786a38SAxel Dörfler#include <MenuItem.h>
35a99b9010SJohn Scipione#include <MenuPrivate.h>
36a99b9010SJohn Scipione#include <MessagePrivate.h>
37df8d45f7SDarkWyrm#include <MessageQueue.h>
381b739004SDarkWyrm#include <MessageRunner.h>
39cf1c3227SJérôme Duval#include <Path.h>
40a99b9010SJohn Scipione#include <PortLink.h>
4114d02d22SAxel Dörfler#include <PropertyInfo.h>
421b739004SDarkWyrm#include <Roster.h>
43a99b9010SJohn Scipione#include <RosterPrivate.h>
4414d02d22SAxel Dörfler#include <Screen.h>
45a99b9010SJohn Scipione#include <ServerProtocol.h>
4614d02d22SAxel Dörfler#include <String.h>
47a99b9010SJohn Scipione#include <TextView.h>
48a99b9010SJohn Scipione#include <TokenSpace.h>
49a99b9010SJohn Scipione#include <ToolTipManager.h>
50a99b9010SJohn Scipione#include <ToolTipWindow.h>
5126a23118SJohn Scipione#include <UnicodeChar.h>
52a99b9010SJohn Scipione#include <WindowPrivate.h>
536c69f6e9SDarkWyrm
5439fbf550SOliver Tappe#include <binary_compatibility/Interface.h>
557cb93378SAxel Dörfler#include <input_globals.h>
56cbdbfd3aSAxel Dörfler#include <tracker_private.h>
57cf10934eSMichael Lotz
5875936a02SAxel Dörfler
59e09fd76fSDarkWyrm//#define DEBUG_WIN
60b81089dbSAdi Oanca#ifdef DEBUG_WIN
61b81089dbSAdi Oanca#	define STRACE(x) printf x
62b81089dbSAdi Oanca#else
63b81089dbSAdi Oanca#	define STRACE(x) ;
64b81089dbSAdi Oanca#endif
656c69f6e9SDarkWyrm
66229f4986SAxel Dörfler#define B_HIDE_APPLICATION '_AHD'
67229f4986SAxel Dörfler	// if we ever move this to a public namespace, we should also move the
68229f4986SAxel Dörfler	// handling of this message into BApplication
69229f4986SAxel Dörfler
7047d9ed62SAxel Dörfler#define _MINIMIZE_			'_WMZ'
711d6720dcSAxel Dörfler#define _ZOOM_				'_WZO'
72289d85d2SAxel Dörfler#define _SEND_BEHIND_		'_WSB'
73289d85d2SAxel Dörfler#define _SEND_TO_FRONT_		'_WSF'
746d52606fSAxel Dörfler
756d52606fSAxel Dörfler
76229f4986SAxel Dörflervoid do_minimize_team(BRect zoomRect, team_id team, bool zoom);
77292d5cedSAxel Dörfler
78f09d0bffSAxel Dörfler
796450b76dSAxel Dörflerstruct BWindow::unpack_cookie {
806450b76dSAxel Dörfler	unpack_cookie();
816450b76dSAxel Dörfler
826450b76dSAxel Dörfler	BMessage*	message;
836450b76dSAxel Dörfler	int32		index;
846450b76dSAxel Dörfler	BHandler*	focus;
856450b76dSAxel Dörfler	int32		focus_token;
866450b76dSAxel Dörfler	int32		last_view_token;
876450b76dSAxel Dörfler	bool		found_focus;
886450b76dSAxel Dörfler	bool		tokens_scanned;
896450b76dSAxel Dörfler};
906450b76dSAxel Dörfler
9175e162f7SJohn Scipione
92292d5cedSAxel Dörflerclass BWindow::Shortcut {
93f09d0bffSAxel Dörflerpublic:
94f09d0bffSAxel Dörfler							Shortcut(uint32 key, uint32 modifiers,
95f09d0bffSAxel Dörfler								BMenuItem* item);
96f09d0bffSAxel Dörfler							Shortcut(uint32 key, uint32 modifiers,
97f09d0bffSAxel Dörfler								BMessage* message, BHandler* target);
98f09d0bffSAxel Dörfler							~Shortcut();
99f09d0bffSAxel Dörfler
100f09d0bffSAxel Dörfler			bool			Matches(uint32 key, uint32 modifiers) const;
101f09d0bffSAxel Dörfler
102f09d0bffSAxel Dörfler			BMenuItem*		MenuItem() const { return fMenuItem; }
103f09d0bffSAxel Dörfler			BMessage*		Message() const { return fMessage; }
104f09d0bffSAxel Dörfler			BHandler*		Target() const { return fTarget; }
105f09d0bffSAxel Dörfler
106f09d0bffSAxel Dörfler	static	uint32			AllowedModifiers();
107f09d0bffSAxel Dörfler	static	uint32			PrepareKey(uint32 key);
108f09d0bffSAxel Dörfler	static	uint32			PrepareModifiers(uint32 modifiers);
109f09d0bffSAxel Dörfler
110f09d0bffSAxel Dörflerprivate:
111f09d0bffSAxel Dörfler			uint32			fKey;
112f09d0bffSAxel Dörfler			uint32			fModifiers;
113f09d0bffSAxel Dörfler			BMenuItem*		fMenuItem;
114f09d0bffSAxel Dörfler			BMessage*		fMessage;
115f09d0bffSAxel Dörfler			BHandler*		fTarget;
116292d5cedSAxel Dörfler};
117292d5cedSAxel Dörfler
118292d5cedSAxel Dörfler
119cd970020SMichael Lotzusing BPrivate::gDefaultTokens;
12010f4d067SStefano Ceccheriniusing BPrivate::MenuPrivate;
121cd970020SMichael Lotz
12275936a02SAxel Dörflerstatic property_info sWindowPropInfo[] = {
123a03ac895SJérôme Duval	{
124a03ac895SJérôme Duval		"Active", { B_GET_PROPERTY, B_SET_PROPERTY },
125a03ac895SJérôme Duval		{ B_DIRECT_SPECIFIER }, NULL, 0, { B_BOOL_TYPE }
126a03ac895SJérôme Duval	},
127a03ac895SJérôme Duval
128bcd8a1faSAxel Dörfler	{
129bcd8a1faSAxel Dörfler		"Feel", { B_GET_PROPERTY, B_SET_PROPERTY },
13051805689SAxel Dörfler		{ B_DIRECT_SPECIFIER }, NULL, 0, { B_INT32_TYPE }
131bcd8a1faSAxel Dörfler	},
1326c69f6e9SDarkWyrm
133bcd8a1faSAxel Dörfler	{
134bcd8a1faSAxel Dörfler		"Flags", { B_GET_PROPERTY, B_SET_PROPERTY },
135bcd8a1faSAxel Dörfler		{ B_DIRECT_SPECIFIER }, NULL, 0, { B_INT32_TYPE }
136bcd8a1faSAxel Dörfler	},
1376c69f6e9SDarkWyrm
138bcd8a1faSAxel Dörfler	{
139bcd8a1faSAxel Dörfler		"Frame", { B_GET_PROPERTY, B_SET_PROPERTY },
140bcd8a1faSAxel Dörfler		{ B_DIRECT_SPECIFIER }, NULL, 0, { B_RECT_TYPE }
141bcd8a1faSAxel Dörfler	},
1426c69f6e9SDarkWyrm
143bcd8a1faSAxel Dörfler	{
144bcd8a1faSAxel Dörfler		"Hidden", { B_GET_PROPERTY, B_SET_PROPERTY },
145bcd8a1faSAxel Dörfler		{ B_DIRECT_SPECIFIER }, NULL, 0, { B_BOOL_TYPE }
146bcd8a1faSAxel Dörfler	},
1476c69f6e9SDarkWyrm
148bcd8a1faSAxel Dörfler	{
149bcd8a1faSAxel Dörfler		"Look", { B_GET_PROPERTY, B_SET_PROPERTY },
150bcd8a1faSAxel Dörfler		{ B_DIRECT_SPECIFIER }, NULL, 0, { B_INT32_TYPE }
151bcd8a1faSAxel Dörfler	},
1526c69f6e9SDarkWyrm
153bcd8a1faSAxel Dörfler	{
154bcd8a1faSAxel Dörfler		"Title", { B_GET_PROPERTY, B_SET_PROPERTY },
155bcd8a1faSAxel Dörfler		{ B_DIRECT_SPECIFIER }, NULL, 0, { B_STRING_TYPE }
156bcd8a1faSAxel Dörfler	},
1576c69f6e9SDarkWyrm
158bcd8a1faSAxel Dörfler	{
159bcd8a1faSAxel Dörfler		"Workspaces", { B_GET_PROPERTY, B_SET_PROPERTY },
160a03ac895SJérôme Duval		{ B_DIRECT_SPECIFIER }, NULL, 0, { B_INT32_TYPE }
161bcd8a1faSAxel Dörfler	},
1626c69f6e9SDarkWyrm
163bcd8a1faSAxel Dörfler	{
164bcd8a1faSAxel Dörfler		"MenuBar", {},
165bcd8a1faSAxel Dörfler		{ B_DIRECT_SPECIFIER }, NULL, 0, {}
166bcd8a1faSAxel Dörfler	},
1676c69f6e9SDarkWyrm
168a03ac895SJérôme Duval	{
169a03ac895SJérôme Duval		"View", { B_COUNT_PROPERTIES },
170a03ac895SJérôme Duval		{ B_DIRECT_SPECIFIER }, NULL, 0, { B_INT32_TYPE }
171a03ac895SJérôme Duval	},
172a03ac895SJérôme Duval
173bcd8a1faSAxel Dörfler	{
174bcd8a1faSAxel Dörfler		"View", {}, {}, NULL, 0, {}
175bcd8a1faSAxel Dörfler	},
1766c69f6e9SDarkWyrm
177bcd8a1faSAxel Dörfler	{
178bcd8a1faSAxel Dörfler		"Minimize", { B_GET_PROPERTY, B_SET_PROPERTY },
179bcd8a1faSAxel Dörfler		{ B_DIRECT_SPECIFIER }, NULL, 0, { B_BOOL_TYPE }
180bcd8a1faSAxel Dörfler	},
1815b0a5c36SAxel Dörfler
182a57dddcaSJonas Sundström	{
183a57dddcaSJonas Sundström		"TabFrame", { B_GET_PROPERTY },
184a57dddcaSJonas Sundström		{ B_DIRECT_SPECIFIER }, NULL, 0, { B_RECT_TYPE }
185a57dddcaSJonas Sundström	},
1866c69f6e9SDarkWyrm
187346d1496SHumdinger	{ 0 }
188a03ac895SJérôme Duval};
189a03ac895SJérôme Duval
190a03ac895SJérôme Duvalstatic value_info sWindowValueInfo[] = {
191a03ac895SJérôme Duval	{
192a03ac895SJérôme Duval		"MoveTo", 'WDMT', B_COMMAND_KIND,
193a03ac895SJérôme Duval		"Moves to the position in the BPoint data"
194a03ac895SJérôme Duval	},
195a03ac895SJérôme Duval
196a03ac895SJérôme Duval	{
197a03ac895SJérôme Duval		"MoveBy", 'WDMB', B_COMMAND_KIND,
198a03ac895SJérôme Duval		"Moves by the offsets in the BPoint data"
199a03ac895SJérôme Duval	},
200a03ac895SJérôme Duval
201a03ac895SJérôme Duval	{
202a03ac895SJérôme Duval		"ResizeTo", 'WDRT', B_COMMAND_KIND,
203a03ac895SJérôme Duval		"Resize to the size in the BPoint data"
204a03ac895SJérôme Duval	},
205a03ac895SJérôme Duval
206a03ac895SJérôme Duval	{
207a03ac895SJérôme Duval		"ResizeBy", 'WDRB', B_COMMAND_KIND,
208a03ac895SJérôme Duval		"Resize by the offsets in the BPoint data"
209a03ac895SJérôme Duval	},
21051805689SAxel Dörfler
211346d1496SHumdinger	{ 0 }
212bcd8a1faSAxel Dörfler};
2136c69f6e9SDarkWyrm
2146c69f6e9SDarkWyrm
21551805689SAxel Dörflervoid
216f09d0bffSAxel Dörfler_set_menu_sem_(BWindow* window, sem_id sem)
21726b54010SStefano Ceccherini{
21887ab5d5cSStefano Ceccherini	if (window != NULL)
21987ab5d5cSStefano Ceccherini		window->fMenuSem = sem;
22026b54010SStefano Ceccherini}
22126b54010SStefano Ceccherini
222bcd8a1faSAxel Dörfler
223bcd8a1faSAxel Dörfler//	#pragma mark -
224bcd8a1faSAxel Dörfler
225bcd8a1faSAxel Dörfler
2266450b76dSAxel DörflerBWindow::unpack_cookie::unpack_cookie()
2276450b76dSAxel Dörfler	:
2286450b76dSAxel Dörfler	message((BMessage*)~0UL),
2296450b76dSAxel Dörfler		// message == NULL is our exit condition
2306450b76dSAxel Dörfler	index(0),
2316450b76dSAxel Dörfler	focus_token(B_NULL_TOKEN),
2326450b76dSAxel Dörfler	last_view_token(B_NULL_TOKEN),
2336450b76dSAxel Dörfler	found_focus(false),
2346450b76dSAxel Dörfler	tokens_scanned(false)
2356450b76dSAxel Dörfler{
2366450b76dSAxel Dörfler}
2376450b76dSAxel Dörfler
2386450b76dSAxel Dörfler
23975e162f7SJohn Scipione//	#pragma mark - BWindow::Shortcut
2406450b76dSAxel Dörfler
2416450b76dSAxel Dörfler
242292d5cedSAxel DörflerBWindow::Shortcut::Shortcut(uint32 key, uint32 modifiers, BMenuItem* item)
243292d5cedSAxel Dörfler	:
244292d5cedSAxel Dörfler	fKey(PrepareKey(key)),
245292d5cedSAxel Dörfler	fModifiers(PrepareModifiers(modifiers)),
246292d5cedSAxel Dörfler	fMenuItem(item),
247292d5cedSAxel Dörfler	fMessage(NULL),
248292d5cedSAxel Dörfler	fTarget(NULL)
249292d5cedSAxel Dörfler{
250292d5cedSAxel Dörfler}
251292d5cedSAxel Dörfler
252292d5cedSAxel Dörfler
253292d5cedSAxel DörflerBWindow::Shortcut::Shortcut(uint32 key, uint32 modifiers, BMessage* message,
254292d5cedSAxel Dörfler	BHandler* target)
255292d5cedSAxel Dörfler	:
256292d5cedSAxel Dörfler	fKey(PrepareKey(key)),
257292d5cedSAxel Dörfler	fModifiers(PrepareModifiers(modifiers)),
258292d5cedSAxel Dörfler	fMenuItem(NULL),
259292d5cedSAxel Dörfler	fMessage(message),
260292d5cedSAxel Dörfler	fTarget(target)
261292d5cedSAxel Dörfler{
262292d5cedSAxel Dörfler}
263292d5cedSAxel Dörfler
264292d5cedSAxel Dörfler
265292d5cedSAxel DörflerBWindow::Shortcut::~Shortcut()
266292d5cedSAxel Dörfler{
267292d5cedSAxel Dörfler	// we own the message, if any
268292d5cedSAxel Dörfler	delete fMessage;
269292d5cedSAxel Dörfler}
270292d5cedSAxel Dörfler
271292d5cedSAxel Dörfler
272292d5cedSAxel Dörflerbool
273292d5cedSAxel DörflerBWindow::Shortcut::Matches(uint32 key, uint32 modifiers) const
274292d5cedSAxel Dörfler{
275292d5cedSAxel Dörfler	return fKey == key && fModifiers == modifiers;
276292d5cedSAxel Dörfler}
277292d5cedSAxel Dörfler
278292d5cedSAxel Dörfler
279292d5cedSAxel Dörfler/*static*/
280292d5cedSAxel Dörfleruint32
281292d5cedSAxel DörflerBWindow::Shortcut::AllowedModifiers()
282292d5cedSAxel Dörfler{
2833cee15aaSJohn Scipione	return B_COMMAND_KEY | B_OPTION_KEY | B_SHIFT_KEY | B_CONTROL_KEY
2843cee15aaSJohn Scipione		| B_MENU_KEY;
285292d5cedSAxel Dörfler}
286292d5cedSAxel Dörfler
287292d5cedSAxel Dörfler
288292d5cedSAxel Dörfler/*static*/
289292d5cedSAxel Dörfleruint32
290292d5cedSAxel DörflerBWindow::Shortcut::PrepareModifiers(uint32 modifiers)
291292d5cedSAxel Dörfler{
292292d5cedSAxel Dörfler	return (modifiers & AllowedModifiers()) | B_COMMAND_KEY;
293292d5cedSAxel Dörfler}
294292d5cedSAxel Dörfler
295292d5cedSAxel Dörfler
296292d5cedSAxel Dörfler/*static*/
297292d5cedSAxel Dörfleruint32
298292d5cedSAxel DörflerBWindow::Shortcut::PrepareKey(uint32 key)
299292d5cedSAxel Dörfler{
30026a23118SJohn Scipione	return BUnicodeChar::ToLower(key);
301292d5cedSAxel Dörfler}
302292d5cedSAxel Dörfler
303292d5cedSAxel Dörfler
30475e162f7SJohn Scipione//	#pragma mark - BWindow
305292d5cedSAxel Dörfler
306292d5cedSAxel Dörfler
3073ceb31b9SDarkWyrmBWindow::BWindow(BRect frame, const char* title, window_type type,
308b7364864SAxel Dörfler		uint32 flags, uint32 workspace)
3096d52606fSAxel Dörfler	:
3106d52606fSAxel Dörfler	BLooper(title, B_DISPLAY_PRIORITY)
311380f5292SDarkWyrm{
3126c69f6e9SDarkWyrm	window_look look;
3136c69f6e9SDarkWyrm	window_feel feel;
314292d5cedSAxel Dörfler	_DecomposeType(type, &look, &feel);
315bcd8a1faSAxel Dörfler
316292d5cedSAxel Dörfler	_InitData(frame, title, look, feel, flags, workspace);
3176c69f6e9SDarkWyrm}
3186c69f6e9SDarkWyrm
3196c69f6e9SDarkWyrm
320b7364864SAxel DörflerBWindow::BWindow(BRect frame, const char* title, window_look look,
321b7364864SAxel Dörfler		window_feel feel, uint32 flags, uint32 workspace)
3226d52606fSAxel Dörfler	:
3236d52606fSAxel Dörfler	BLooper(title, B_DISPLAY_PRIORITY)
3246c69f6e9SDarkWyrm{
325292d5cedSAxel Dörfler	_InitData(frame, title, look, feel, flags, workspace);
326380f5292SDarkWyrm}
3276c69f6e9SDarkWyrm
3286c69f6e9SDarkWyrm
3296c69f6e9SDarkWyrmBWindow::BWindow(BMessage* data)
3306d52606fSAxel Dörfler	:
3316d52606fSAxel Dörfler	BLooper(data)
332380f5292SDarkWyrm{
3331b739004SDarkWyrm	data->FindRect("_frame", &fFrame);
334bcd8a1faSAxel Dörfler
335f09d0bffSAxel Dörfler	const char* title;
3361b739004SDarkWyrm	data->FindString("_title", &title);
3371b739004SDarkWyrm
338bcd8a1faSAxel Dörfler	window_look look;
339f09d0bffSAxel Dörfler	data->FindInt32("_wlook", (int32*)&look);
340bcd8a1faSAxel Dörfler
341bcd8a1faSAxel Dörfler	window_feel feel;
342f09d0bffSAxel Dörfler	data->FindInt32("_wfeel", (int32*)&feel);
343bcd8a1faSAxel Dörfler
344f09d0bffSAxel Dörfler	if (data->FindInt32("_flags", (int32*)&fFlags) != B_OK)
345bcd8a1faSAxel Dörfler		fFlags = 0;
346bcd8a1faSAxel Dörfler
347bcd8a1faSAxel Dörfler	uint32 workspaces;
348f09d0bffSAxel Dörfler	data->FindInt32("_wspace", (int32*)&workspaces);
349bcd8a1faSAxel Dörfler
350bcd8a1faSAxel Dörfler	uint32 type;
351bcd8a1faSAxel Dörfler	if (data->FindInt32("_type", (int32*)&type) == B_OK)
352292d5cedSAxel Dörfler		_DecomposeType((window_type)type, &fLook, &fFeel);
3531b739004SDarkWyrm
3541b739004SDarkWyrm		// connect to app_server and initialize data
355292d5cedSAxel Dörfler	_InitData(fFrame, title, look, feel, fFlags, workspaces);
356380f5292SDarkWyrm
357bcd8a1faSAxel Dörfler	if (data->FindFloat("_zoom", 0, &fMaxZoomWidth) == B_OK
358bcd8a1faSAxel Dörfler		&& data->FindFloat("_zoom", 1, &fMaxZoomHeight) == B_OK)
359bcd8a1faSAxel Dörfler		SetZoomLimits(fMaxZoomWidth, fMaxZoomHeight);
360380f5292SDarkWyrm
36185bd83a7SAxel Dörfler	if (data->FindFloat("_sizel", 0, &fMinWidth) == B_OK
36285bd83a7SAxel Dörfler		&& data->FindFloat("_sizel", 1, &fMinHeight) == B_OK
36385bd83a7SAxel Dörfler		&& data->FindFloat("_sizel", 2, &fMaxWidth) == B_OK
36485bd83a7SAxel Dörfler		&& data->FindFloat("_sizel", 3, &fMaxHeight) == B_OK)
36585bd83a7SAxel Dörfler		SetSizeLimits(fMinWidth, fMaxWidth,
36685bd83a7SAxel Dörfler			fMinHeight, fMaxHeight);
3676c69f6e9SDarkWyrm
368bcd8a1faSAxel Dörfler	if (data->FindInt64("_pulse", &fPulseRate) == B_OK)
369bcd8a1faSAxel Dörfler		SetPulseRate(fPulseRate);
3701b739004SDarkWyrm
371bcd8a1faSAxel Dörfler	BMessage msg;
372bcd8a1faSAxel Dörfler	int32 i = 0;
37351805689SAxel Dörfler	while (data->FindMessage("_views", i++, &msg) == B_OK) {
374f09d0bffSAxel Dörfler		BArchivable* obj = instantiate_object(&msg);
375f09d0bffSAxel Dörfler		if (BView* child = dynamic_cast<BView*>(obj))
376bcd8a1faSAxel Dörfler			AddChild(child);
3771b739004SDarkWyrm	}
3786c69f6e9SDarkWyrm}
3796c69f6e9SDarkWyrm
3806c69f6e9SDarkWyrm
3812e6a5805SStephan AßmusBWindow::BWindow(BRect frame, int32 bitmapToken)
3826d52606fSAxel Dörfler	:
3836d52606fSAxel Dörfler	BLooper("offscreen bitmap")
38438b35d9cSStefano Ceccherini{
385292d5cedSAxel Dörfler	_DecomposeType(B_UNTYPED_WINDOW, &fLook, &fFeel);
386292d5cedSAxel Dörfler	_InitData(frame, "offscreen", fLook, fFeel, 0, 0, bitmapToken);
38738b35d9cSStefano Ceccherini}
38838b35d9cSStefano Ceccherini
38938b35d9cSStefano Ceccherini
3903ceb31b9SDarkWyrmBWindow::~BWindow()
3913ceb31b9SDarkWyrm{
392f09d0bffSAxel Dörfler	if (BMenu* menu = dynamic_cast<BMenu*>(fFocus)) {
39310f4d067SStefano Ceccherini		MenuPrivate(menu).QuitTracking();
39410f4d067SStefano Ceccherini	}
395e061d1baSStefano Ceccherini
39672122293SStefano Ceccherini	// The BWindow is locked when the destructor is called,
39772122293SStefano Ceccherini	// we need to unlock because the menubar thread tries
39872122293SStefano Ceccherini	// to post a message, which will deadlock otherwise.
399f60d8e0bSStefano Ceccherini	// TODO: I replaced Unlock() with UnlockFully() because the window
400f60d8e0bSStefano Ceccherini	// was kept locked after that in case it was closed using ALT-W.
401f60d8e0bSStefano Ceccherini	// There might be an extra Lock() somewhere in the quitting path...
402f60d8e0bSStefano Ceccherini	UnlockFully();
40372122293SStefano Ceccherini
404cb8bdc4eSStefano Ceccherini	// Wait if a menu is still tracking
405cb8bdc4eSStefano Ceccherini	if (fMenuSem > 0) {
406cb8bdc4eSStefano Ceccherini		while (acquire_sem(fMenuSem) == B_INTERRUPTED)
407cb8bdc4eSStefano Ceccherini			;
408cb8bdc4eSStefano Ceccherini	}
409cb8bdc4eSStefano Ceccherini
41072122293SStefano Ceccherini	Lock();
41172122293SStefano Ceccherini
412ea34f0f0SAxel Dörfler	fTopView->RemoveSelf();
413ea34f0f0SAxel Dörfler	delete fTopView;
414ea34f0f0SAxel Dörfler
4157afc7c50SStephan Aßmus	// remove all remaining shortcuts
4167afc7c50SStephan Aßmus	int32 shortCutCount = fShortcuts.CountItems();
4177afc7c50SStephan Aßmus	for (int32 i = 0; i < shortCutCount; i++) {
4187afc7c50SStephan Aßmus		delete (Shortcut*)fShortcuts.ItemAtFast(i);
419ea4ea977SDarkWyrm	}
42007e5e0d1SAdi Oanca
4213ceb31b9SDarkWyrm	// TODO: release other dynamically-allocated objects
422ecf9f948SStephan Aßmus	free(fTitle);
423292d5cedSAxel Dörfler
4243ceb31b9SDarkWyrm	// disable pulsing
425bcd8a1faSAxel Dörfler	SetPulseRate(0);
4266c69f6e9SDarkWyrm
427e17b33e5SAxel Dörfler	// tell app_server about our demise
428e17b33e5SAxel Dörfler	fLink->StartMessage(AS_DELETE_WINDOW);
4297afc7c50SStephan Aßmus	// sync with the server so that for example
4307afc7c50SStephan Aßmus	// a BBitmap can be sure that there are no
4317afc7c50SStephan Aßmus	// more pending messages that are executed
4327afc7c50SStephan Aßmus	// after the bitmap is deleted (which uses
4337afc7c50SStephan Aßmus	// a different link and server side thread)
4347afc7c50SStephan Aßmus	int32 code;
4357afc7c50SStephan Aßmus	fLink->FlushWithReply(code);
436e17b33e5SAxel Dörfler
437d520c103SAxel Dörfler	// the sender port belongs to the app_server
438dd10337fSAxel Dörfler	delete_port(fLink->ReceiverPort());
4393ceb31b9SDarkWyrm	delete fLink;
440380f5292SDarkWyrm}
4416c69f6e9SDarkWyrm
4426c69f6e9SDarkWyrm
443f09d0bffSAxel DörflerBArchivable*
444f09d0bffSAxel DörflerBWindow::Instantiate(BMessage* data)
4453ceb31b9SDarkWyrm{
446323523c4SJohn Scipione	if (!validate_instantiation(data, "BWindow"))
44751805689SAxel Dörfler		return NULL;
448bcd8a1faSAxel Dörfler
449eaccfb9dSAxel Dörfler	return new(std::nothrow) BWindow(data);
450380f5292SDarkWyrm}
4516c69f6e9SDarkWyrm
4526c69f6e9SDarkWyrm
453bcd8a1faSAxel Dörflerstatus_t
454bcd8a1faSAxel DörflerBWindow::Archive(BMessage* data, bool deep) const
455bcd8a1faSAxel Dörfler{
45695f766faSStephan Aßmus	status_t ret = BLooper::Archive(data, deep);
45795f766faSStephan Aßmus
45895f766faSStephan Aßmus	if (ret == B_OK)
45995f766faSStephan Aßmus		ret = data->AddRect("_frame", fFrame);
46095f766faSStephan Aßmus	if (ret == B_OK)
46195f766faSStephan Aßmus		ret = data->AddString("_title", fTitle);
46295f766faSStephan Aßmus	if (ret == B_OK)
46395f766faSStephan Aßmus		ret = data->AddInt32("_wlook", fLook);
46495f766faSStephan Aßmus	if (ret == B_OK)
46595f766faSStephan Aßmus		ret = data->AddInt32("_wfeel", fFeel);
46695f766faSStephan Aßmus	if (ret == B_OK && fFlags != 0)
46795f766faSStephan Aßmus		ret = data->AddInt32("_flags", fFlags);
46895f766faSStephan Aßmus	if (ret == B_OK)
46995f766faSStephan Aßmus		ret = data->AddInt32("_wspace", (uint32)Workspaces());
47095f766faSStephan Aßmus
47195f766faSStephan Aßmus	if (ret == B_OK && !_ComposeType(fLook, fFeel))
47295f766faSStephan Aßmus		ret = data->AddInt32("_type", (uint32)Type());
4736c69f6e9SDarkWyrm
474bcd8a1faSAxel Dörfler	if (fMaxZoomWidth != 32768.0 || fMaxZoomHeight != 32768.0) {
47595f766faSStephan Aßmus		if (ret == B_OK)
47695f766faSStephan Aßmus			ret = data->AddFloat("_zoom", fMaxZoomWidth);
47795f766faSStephan Aßmus		if (ret == B_OK)
47895f766faSStephan Aßmus			ret = data->AddFloat("_zoom", fMaxZoomHeight);
4791b739004SDarkWyrm	}
4806c69f6e9SDarkWyrm
48151805689SAxel Dörfler	if (fMinWidth != 0.0 || fMinHeight != 0.0
48285bd83a7SAxel Dörfler		|| fMaxWidth != 32768.0 || fMaxHeight != 32768.0) {
48395f766faSStephan Aßmus		if (ret == B_OK)
48495f766faSStephan Aßmus			ret = data->AddFloat("_sizel", fMinWidth);
48595f766faSStephan Aßmus		if (ret == B_OK)
48695f766faSStephan Aßmus			ret = data->AddFloat("_sizel", fMinHeight);
48795f766faSStephan Aßmus		if (ret == B_OK)
48895f766faSStephan Aßmus			ret = data->AddFloat("_sizel", fMaxWidth);
48995f766faSStephan Aßmus		if (ret == B_OK)
49095f766faSStephan Aßmus			ret = data->AddFloat("_sizel", fMaxHeight);
491380f5292SDarkWyrm	}
4926c69f6e9SDarkWyrm
49395f766faSStephan Aßmus	if (ret == B_OK && fPulseRate != 500000)
4941b739004SDarkWyrm		data->AddInt64("_pulse", fPulseRate);
4956c69f6e9SDarkWyrm
49695f766faSStephan Aßmus	if (ret == B_OK && deep) {
497bcd8a1faSAxel Dörfler		int32 noOfViews = CountChildren();
498bcd8a1faSAxel Dörfler		for (int32 i = 0; i < noOfViews; i++){
499bcd8a1faSAxel Dörfler			BMessage childArchive;
50095f766faSStephan Aßmus			ret = ChildAt(i)->Archive(&childArchive, true);
50195f766faSStephan Aßmus			if (ret == B_OK)
50295f766faSStephan Aßmus				ret = data->AddMessage("_views", &childArchive);
50395f766faSStephan Aßmus			if (ret != B_OK)
50495f766faSStephan Aßmus				break;
5051b739004SDarkWyrm		}
5061b739004SDarkWyrm	}
5076c69f6e9SDarkWyrm
50895f766faSStephan Aßmus	return ret;
509380f5292SDarkWyrm}
5106c69f6e9SDarkWyrm
5111b739004SDarkWyrm
512bcd8a1faSAxel Dörflervoid
513bcd8a1faSAxel DörflerBWindow::Quit()
514bcd8a1faSAxel Dörfler{
515bcd8a1faSAxel Dörfler	if (!IsLocked()) {
516f09d0bffSAxel Dörfler		const char* name = Name();
517323523c4SJohn Scipione		if (name == NULL)
5181b739004SDarkWyrm			name = "no-name";
5191b739004SDarkWyrm
5201b739004SDarkWyrm		printf("ERROR - you must Lock a looper before calling Quit(), "
5219be774b5SAlex Smith			   "team=%" B_PRId32 ", looper=%s\n", Team(), name);
5221b739004SDarkWyrm	}
5231b739004SDarkWyrm
524bcd8a1faSAxel Dörfler	// Try to lock
5251b739004SDarkWyrm	if (!Lock()){
526bcd8a1faSAxel Dörfler		// We're toast already
5271b739004SDarkWyrm		return;
5281b739004SDarkWyrm	}
5291b739004SDarkWyrm
53051805689SAxel Dörfler	while (!IsHidden())	{
53151805689SAxel Dörfler		Hide();
532bcd8a1faSAxel Dörfler	}
5336c69f6e9SDarkWyrm
5341b739004SDarkWyrm	if (fFlags & B_QUIT_ON_WINDOW_CLOSE)
535bcd8a1faSAxel Dörfler		be_app->PostMessage(B_QUIT_REQUESTED);
5366c69f6e9SDarkWyrm
5371b739004SDarkWyrm	BLooper::Quit();
538380f5292SDarkWyrm}
5396c69f6e9SDarkWyrm
5406c69f6e9SDarkWyrm
541bcd8a1faSAxel Dörflervoid
542f09d0bffSAxel DörflerBWindow::AddChild(BView* child, BView* before)
543bcd8a1faSAxel Dörfler{
544dd7b93c8SAxel Dörfler	BAutolock locker(this);
54522ca66b9SAxel Dörfler	if (locker.IsLocked())
54622ca66b9SAxel Dörfler		fTopView->AddChild(child, before);
547380f5292SDarkWyrm}
5486c69f6e9SDarkWyrm
5496c69f6e9SDarkWyrm
5501d6c7b6cSAlex Wilsonvoid
5511d6c7b6cSAlex WilsonBWindow::AddChild(BLayoutItem* child)
5521d6c7b6cSAlex Wilson{
5531d6c7b6cSAlex Wilson	BAutolock locker(this);
5541d6c7b6cSAlex Wilson	if (locker.IsLocked())
5551d6c7b6cSAlex Wilson		fTopView->AddChild(child);
5561d6c7b6cSAlex Wilson}
5571d6c7b6cSAlex Wilson
5581d6c7b6cSAlex Wilson
559bcd8a1faSAxel Dörflerbool
560f09d0bffSAxel DörflerBWindow::RemoveChild(BView* child)
561bcd8a1faSAxel Dörfler{
562dd7b93c8SAxel Dörfler	BAutolock locker(this);
56322ca66b9SAxel Dörfler	if (!locker.IsLocked())
56422ca66b9SAxel Dörfler		return false;
56522ca66b9SAxel Dörfler
566292d5cedSAxel Dörfler	return fTopView->RemoveChild(child);
567380f5292SDarkWyrm}
5686c69f6e9SDarkWyrm
5696c69f6e9SDarkWyrm
570bcd8a1faSAxel Dörflerint32
571bcd8a1faSAxel DörflerBWindow::CountChildren() const
572bcd8a1faSAxel Dörfler{
57322ca66b9SAxel Dörfler	BAutolock locker(const_cast<BWindow*>(this));
57422ca66b9SAxel Dörfler	if (!locker.IsLocked())
57522ca66b9SAxel Dörfler		return 0;
57622ca66b9SAxel Dörfler
577292d5cedSAxel Dörfler	return fTopView->CountChildren();
578380f5292SDarkWyrm}
5796c69f6e9SDarkWyrm
5806c69f6e9SDarkWyrm
581f09d0bffSAxel DörflerBView*
582bcd8a1faSAxel DörflerBWindow::ChildAt(int32 index) const
583bcd8a1faSAxel Dörfler{
58422ca66b9SAxel Dörfler	BAutolock locker(const_cast<BWindow*>(this));
58522ca66b9SAxel Dörfler	if (!locker.IsLocked())
58622ca66b9SAxel Dörfler		return NULL;
58722ca66b9SAxel Dörfler
588292d5cedSAxel Dörfler	return fTopView->ChildAt(index);
589380f5292SDarkWyrm}
590380f5292SDarkWyrm
591380f5292SDarkWyrm
592bcd8a1faSAxel Dörflervoid
593bcd8a1faSAxel DörflerBWindow::Minimize(bool minimize)
594bcd8a1faSAxel Dörfler{
59559347b7fSRyan Leavengood	if (IsModal() || IsFloating() || IsHidden() || fMinimized == minimize
59659347b7fSRyan Leavengood		|| !Lock())
5976c69f6e9SDarkWyrm		return;
598380f5292SDarkWyrm
599bcd8a1faSAxel Dörfler	fMinimized = minimize;
600bcd8a1faSAxel Dörfler
601995ab7b3SAxel Dörfler	fLink->StartMessage(AS_MINIMIZE_WINDOW);
602bcd8a1faSAxel Dörfler	fLink->Attach<bool>(minimize);
6033ceb31b9SDarkWyrm	fLink->Flush();
604995ab7b3SAxel Dörfler
6056c69f6e9SDarkWyrm	Unlock();
606380f5292SDarkWyrm}
6076c69f6e9SDarkWyrm
6086c69f6e9SDarkWyrm
609bcd8a1faSAxel Dörflerstatus_t
610f09d0bffSAxel DörflerBWindow::SendBehind(const BWindow* window)
611bcd8a1faSAxel Dörfler{
612289d85d2SAxel Dörfler	if (!Lock())
6131b739004SDarkWyrm		return B_ERROR;
614bcd8a1faSAxel Dörfler
615bcd8a1faSAxel Dörfler	fLink->StartMessage(AS_SEND_BEHIND);
616289d85d2SAxel Dörfler	fLink->Attach<int32>(window != NULL ? _get_object_token_(window) : -1);
6179783d238SAdi Oanca	fLink->Attach<team_id>(Team());
61875936a02SAxel Dörfler
619349837d9SAxel Dörfler	status_t status = B_ERROR;
620349837d9SAxel Dörfler	fLink->FlushWithReply(status);
62175936a02SAxel Dörfler
6226c69f6e9SDarkWyrm	Unlock();
623bcd8a1faSAxel Dörfler
624349837d9SAxel Dörfler	return status;
625380f5292SDarkWyrm}
6266c69f6e9SDarkWyrm
6276c69f6e9SDarkWyrm
628bcd8a1faSAxel Dörflervoid
629bcd8a1faSAxel DörflerBWindow::Flush() const
630bcd8a1faSAxel Dörfler{
631f09d0bffSAxel Dörfler	if (const_cast<BWindow*>(this)->Lock()) {
63229a92e4fSAxel Dörfler		fLink->Flush();
633f09d0bffSAxel Dörfler		const_cast<BWindow*>(this)->Unlock();
63429a92e4fSAxel Dörfler	}
635380f5292SDarkWyrm}
6366c69f6e9SDarkWyrm
637bf17b6acSAdi Oanca
638bcd8a1faSAxel Dörflervoid
639bcd8a1faSAxel DörflerBWindow::Sync() const
640bcd8a1faSAxel Dörfler{
64129a92e4fSAxel Dörfler	if (!const_cast<BWindow*>(this)->Lock())
64229a92e4fSAxel Dörfler		return;
64329a92e4fSAxel Dörfler
644bcd8a1faSAxel Dörfler	fLink->StartMessage(AS_SYNC);
64575936a02SAxel Dörfler
646