xref: /haiku/src/kits/interface/Window.cpp (revision d5cd5d63ff0ad395989db6cf4841a64d5b545d1d)
1 //------------------------------------------------------------------------------
2 //	Copyright (c) 2001-2002, OpenBeOS
3 //
4 //	Permission is hereby granted, free of charge, to any person obtaining a
5 //	copy of this software and associated documentation files (the "Software"),
6 //	to deal in the Software without restriction, including without limitation
7 //	the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 //	and/or sell copies of the Software, and to permit persons to whom the
9 //	Software is furnished to do so, subject to the following conditions:
10 //
11 //	The above copyright notice and this permission notice shall be included in
12 //	all copies or substantial portions of the Software.
13 //
14 //	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 //	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 //	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 //	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 //	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 //	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 //	DEALINGS IN THE SOFTWARE.
21 //
22 //	File Name:		Window.cpp
23 //	Author:			Adrian Oanca (e2joseph@hotpop.com)
24 //	Description:	A BWindow object represents a window that can be displayed
25 //					on the screen, and that can be the target of user events
26 //------------------------------------------------------------------------------
27 
28 // System Includes -------------------------------------------------------------
29 #include <BeBuild.h>
30 #include <InterfaceDefs.h>
31 #include <PropertyInfo.h>
32 #include <Handler.h>
33 #include <Looper.h>
34 #include <Application.h>
35 #include <Window.h>
36 #include <View.h>
37 #include <MenuBar.h>
38 #include <String.h>
39 #include <Screen.h>
40 #include <Button.h>
41 #include <MessageQueue.h>
42 #include <MessageRunner.h>
43 #include <Roster.h>
44 
45 // Project Includes ------------------------------------------------------------
46 #include <AppMisc.h>
47 #include <Session.h>
48 #include <ServerProtocol.h>
49 #include <TokenSpace.h>
50 #include <MessageUtils.h>
51 #include <WindowAux.h>
52 
53 // Standard Includes -----------------------------------------------------------
54 #include <stdio.h>
55 #include <math.h>
56 #include <posix/math.h>
57 
58 // Local Includes --------------------------------------------------------------
59 
60 // Local Defines ---------------------------------------------------------------
61 //#define DEBUG_WIN
62 #ifdef DEBUG_WIN
63 #	include <stdio.h>
64 #	define STRACE(x) printf x
65 #else
66 #	define STRACE(x) ;
67 #endif
68 
69 // Globals ---------------------------------------------------------------------
70 static property_info windowPropInfo[] =
71 {
72 	{ "Feel", { B_GET_PROPERTY, 0 },
73 		{ B_DIRECT_SPECIFIER, 0 }, "Returns the current feel of the window.",0 },
74 
75 	{ "Feel", { B_SET_PROPERTY, 0 },
76 		{ B_DIRECT_SPECIFIER, 0 }, "Sets the feel of the window.",0 },
77 
78 	{ "Flags", { B_GET_PROPERTY, 0 },
79 		{ B_DIRECT_SPECIFIER, 0 }, "Returns the current flags of the window.",0 },
80 
81 	{ "Flags", { B_SET_PROPERTY, 0 },
82 		{ B_DIRECT_SPECIFIER, 0 }, "Sets the window flags.",0 },
83 
84 	{ "Frame", { B_GET_PROPERTY, 0 },
85 		{ B_DIRECT_SPECIFIER, 0 }, "Returns the window's frame rectangle.",0},
86 
87 	{ "Frame", { B_SET_PROPERTY, 0 },
88 		{ B_DIRECT_SPECIFIER, 0 }, "Sets the window's frame rectangle.",0 },
89 
90 	{ "Hidden", { B_GET_PROPERTY, 0 },
91 		{ B_DIRECT_SPECIFIER, 0 }, "Returns true if the window is hidden; false otherwise.",0},
92 
93 	{ "Hidden", { B_SET_PROPERTY, 0 },
94 		{ B_DIRECT_SPECIFIER, 0 }, "Hides or shows the window.",0 },
95 
96 	{ "Look", { B_GET_PROPERTY, 0 },
97 		{ B_DIRECT_SPECIFIER, 0 }, "Returns the current look of the window.",0},
98 
99 	{ "Look", { B_SET_PROPERTY, 0 },
100 		{ B_DIRECT_SPECIFIER, 0 }, "Sets the look of the window.",0 },
101 
102 	{ "Title", { B_GET_PROPERTY, 0 },
103 		{ B_DIRECT_SPECIFIER, 0 }, "Returns a string containing the window title.",0},
104 
105 	{ "Title", { B_SET_PROPERTY, 0 },
106 		{ B_DIRECT_SPECIFIER, 0 }, "Sets the window title.",0 },
107 
108 	{ "Workspaces", { B_GET_PROPERTY, 0 },
109 		{ B_DIRECT_SPECIFIER, 0 }, "Returns int32 bitfield of the workspaces in which the window appears.",0},
110 
111 	{ "Workspaces", { B_SET_PROPERTY, 0 },
112 		{ B_DIRECT_SPECIFIER, 0 }, "Sets the workspaces in which the window appears.",0 },
113 
114 	{ "MenuBar", { 0 },
115 		{ B_DIRECT_SPECIFIER, 0 }, "Directs the scripting message to the key menu bar.",0 },
116 
117 	{ "View", { 0 },
118 		{ 0 }, "Directs the scripting message to the top view without popping the current specifier.",0 },
119 
120 	{ "Minimize", { B_SET_PROPERTY, 0 },
121 		{ B_DIRECT_SPECIFIER, 0 }, "Minimizes the window if \"data\" is true; restores otherwise.",0 },
122 
123 	{ 0, { 0 }, { 0 }, 0, 0 }
124 };
125 //------------------------------------------------------------------------------
126 
127 // Constructors
128 //------------------------------------------------------------------------------
129 BWindow::BWindow(BRect frame,
130 				const char* title,
131 				window_type type,
132 				uint32 flags,
133 				uint32 workspace)
134 			: BLooper( title )
135 {
136 	#ifdef DEBUG_WIN
137 		printf("BWindow::BWindow()\n");
138 	#endif
139 	window_look look;
140 	window_feel feel;
141 
142 	decomposeType(type, &look, &feel);
143 
144 	InitData( frame, title, look, feel, flags, workspace);
145 }
146 
147 //------------------------------------------------------------------------------
148 
149 BWindow::BWindow(BRect frame,
150 				const char* title,
151 				window_look look,
152 				window_feel feel,
153 				uint32 flags,
154 				uint32 workspace)
155 			: BLooper( title )
156 {
157 	InitData( frame, title, look, feel, flags, workspace );
158 }
159 
160 //------------------------------------------------------------------------------
161 
162 BWindow::BWindow(BMessage* data)
163 	: BLooper(data)
164 {
165 	BMessage		msg;
166 	BArchivable		*obj;
167 	const char		*title;
168 	window_look		look;
169 	window_feel		feel;
170 	uint32			type;
171 	uint32			workspaces;
172 
173 	data->FindRect("_frame", &fFrame);
174 	data->FindString("_title", &title);
175 	data->FindInt32("_wlook", (int32*)&look);
176 	data->FindInt32("_wfeel", (int32*)&feel);
177 	if ( data->FindInt32("_flags", (int32*)&fFlags) == B_OK )
178 		{ }
179 	else
180 		fFlags		= 0;
181 	data->FindInt32("_wspace", (int32*)&workspaces);
182 
183 	if ( data->FindInt32("_type", (int32*)&type) == B_OK ){
184 		decomposeType( (window_type)type, &fLook, &fFeel );
185 	}
186 
187 		// connect to app_server and initialize data
188 	InitData( fFrame, title, look, feel, fFlags, workspaces );
189 
190 	if ( data->FindFloat("_zoom", 0, &fMaxZoomWidth) == B_OK )
191 		if ( data->FindFloat("_zoom", 1, &fMaxZoomHeight) == B_OK)
192 			SetZoomLimits( fMaxZoomWidth, fMaxZoomHeight );
193 
194 	if (data->FindFloat("_sizel", 0, &fMinWindWidth) == B_OK )
195 		if (data->FindFloat("_sizel", 1, &fMinWindHeight) == B_OK )
196 			if (data->FindFloat("_sizel", 2, &fMaxWindWidth) == B_OK )
197 				if (data->FindFloat("_sizel", 3, &fMaxWindHeight) == B_OK )
198 					SetSizeLimits(	fMinWindWidth, fMaxWindWidth,
199 									fMinWindHeight, fMaxWindHeight );
200 
201 	if (data->FindInt64("_pulse", &fPulseRate) == B_OK )
202 		SetPulseRate( fPulseRate );
203 
204 	int				i = 0;
205 	while ( data->FindMessage("_views", i++, &msg) == B_OK){
206 		obj			= instantiate_object(&msg);
207 
208 		BView		*child;
209 		child		= dynamic_cast<BView *>(obj);
210 		if (child)
211 			AddChild( child );
212 	}
213 }
214 
215 //------------------------------------------------------------------------------
216 
217 BWindow::~BWindow(){
218 
219 		// the following lines, remove all existing shortcuts and delete accelList
220 	int32			noOfItems;
221 
222 	noOfItems		= accelList.CountItems();
223 	for ( int index = noOfItems;  index >= 0; index-- ) {
224 		_BCmdKey		*cmdKey;
225 
226 		cmdKey			= (_BCmdKey*)accelList.ItemAt( index );
227 
228 		accelList.RemoveItem(index);
229 
230 		delete cmdKey->message;
231 		delete cmdKey;
232 	}
233 
234 // TODO: release other dinamicaly alocated objects
235 
236 		// disable pulsing
237 	SetPulseRate( 0 );
238 
239 	delete		session;
240 	delete_port( receive_port );
241 }
242 
243 //------------------------------------------------------------------------------
244 
245 BArchivable* BWindow::Instantiate(BMessage* data){
246 
247    if ( !validate_instantiation( data , "BWindow" ) )
248       return NULL;
249    return new BWindow(data);
250 }
251 
252 //------------------------------------------------------------------------------
253 
254 status_t BWindow::Archive(BMessage* data, bool deep) const{
255 
256 	status_t		retval;
257 
258 	retval		= BLooper::Archive( data, deep );
259 	if (retval != B_OK)
260 		return retval;
261 
262 	data->AddRect("_frame", fFrame);
263 	data->AddString("_title", fTitle);
264 	data->AddInt32("_wlook", fLook);
265 	data->AddInt32("_wfeel", fFeel);
266 	if (fFlags)
267 		data->AddInt32("_flags", fFlags);
268 	data->AddInt32("_wspace", (uint32)Workspaces());
269 
270 	if ( !composeType(fLook, fFeel) )
271 		data->AddInt32("_type", (uint32)Type());
272 
273 	if (fMaxZoomWidth != 32768.0 || fMaxZoomHeight != 32768.0)
274 	{
275 		data->AddFloat("_zoom", fMaxZoomWidth);
276 		data->AddFloat("_zoom", fMaxZoomHeight);
277 	}
278 
279 	if (fMinWindWidth != 0.0	 || fMinWindHeight != 0.0 ||
280 		fMaxWindWidth != 32768.0 || fMaxWindHeight != 32768.0)
281 	{
282 		data->AddFloat("_sizel", fMinWindWidth);
283 		data->AddFloat("_sizel", fMinWindHeight);
284 		data->AddFloat("_sizel", fMaxWindWidth);
285 		data->AddFloat("_sizel", fMaxWindHeight);
286 	}
287 
288 	if (fPulseRate != 500000)
289 		data->AddInt64("_pulse", fPulseRate);
290 
291 	if (deep)
292 	{
293 		int32		noOfViews = CountChildren();
294 		for (int i=0; i<noOfViews; i++){
295 			BMessage		childArchive;
296 
297 			retval			= ChildAt(i)->Archive( &childArchive, deep );
298 			if (retval == B_OK)
299 				data->AddMessage( "_views", &childArchive );
300 		}
301 	}
302 
303 	return B_OK;
304 }
305 
306 //------------------------------------------------------------------------------
307 
308 void BWindow::Quit(){
309 
310 	if (!IsLocked())
311 	{
312 		const char* name = Name();
313 		if (!name)
314 			name = "no-name";
315 
316 		printf("ERROR - you must Lock a looper before calling Quit(), "
317 			   "team=%ld, looper=%s\n", Team(), name);
318 	}
319 
320 		// Try to lock
321 	if (!Lock()){
322 			// We're toast already
323 		return;
324 	}
325 
326 	while (!IsHidden())	{ Hide(); }
327 
328 		// ... also its children
329 	//detachTopView();
330 
331 		// tell app_server, this window will finish execution
332 	stopConnection();
333 
334 	if (fFlags & B_QUIT_ON_WINDOW_CLOSE)
335 		be_app->PostMessage( B_QUIT_REQUESTED );
336 
337 	BLooper::Quit();
338 }
339 
340 //------------------------------------------------------------------------------
341 
342 void BWindow::AddChild(BView *child, BView *before){
343 	top_view->AddChild( child, before );
344 }
345 
346 //------------------------------------------------------------------------------
347 
348 bool BWindow::RemoveChild(BView *child){
349 	return top_view->RemoveChild( child );
350 }
351 
352 //------------------------------------------------------------------------------
353 
354 int32 BWindow::CountChildren() const{
355 	return top_view->CountChildren();
356 }
357 
358 //------------------------------------------------------------------------------
359 
360 BView* BWindow::ChildAt(int32 index) const{
361 	return top_view->ChildAt( index );
362 }
363 
364 //------------------------------------------------------------------------------
365 
366 void BWindow::Minimize(bool minimize){
367 	if (IsModal())
368 		return;
369 
370 	if (IsFloating())
371 		return;
372 
373 	Lock();
374 	session->WriteInt32( AS_WINDOW_MINIMIZE );
375 	session->WriteBool( minimize );
376 	session->Sync( );
377 	Unlock();
378 }
379 //------------------------------------------------------------------------------
380 
381 status_t BWindow::SendBehind(const BWindow* window){
382 
383 	if (!window)
384 		return B_ERROR;
385 
386 	int32		rCode;
387 
388 	Lock();
389 	session->WriteInt32( AS_SEND_BEHIND );
390 	session->WriteInt32( _get_object_token_(window) );
391 	session->Sync();
392 	session->ReadInt32( &rCode );
393 	Unlock();
394 
395 	return rCode == SERVER_TRUE? B_OK : B_ERROR;
396 }
397 
398 //------------------------------------------------------------------------------
399 
400 void BWindow::Flush() const{
401 	const_cast<BWindow*>(this)->Lock();
402 	session->Sync();
403 	const_cast<BWindow*>(this)->Unlock();
404 }
405 
406 //------------------------------------------------------------------------------
407 
408 void BWindow::Sync() const{
409 
410 	int32		rCode;
411 
412 	const_cast<BWindow*>(this)->Lock();
413 	session->WriteInt32( AS_SYNC );
414 	session->Sync();
415 	session->ReadInt32( &rCode );
416 	const_cast<BWindow*>(this)->Unlock();
417 }
418 
419 //------------------------------------------------------------------------------
420 
421 void BWindow::DisableUpdates(){
422 
423 	Lock();
424 	session->WriteInt32( AS_DISABLE_UPDATES );
425 	session->Sync();
426 	Unlock();
427 }
428 
429 //------------------------------------------------------------------------------
430 
431 void BWindow::EnableUpdates(){
432 
433 	Lock();
434 	session->WriteInt32( AS_ENABLE_UPDATES );
435 	session->Sync( );
436 	Unlock();
437 }
438 
439 //------------------------------------------------------------------------------
440 
441 void BWindow::BeginViewTransaction(){
442 	if ( !fInTransaction ){
443 		Lock();
444 		session->WriteInt32( AS_BEGIN_TRANSACTION );
445 		Unlock();
446 
447 		fInTransaction		= true;
448 	}
449 }
450 
451 //------------------------------------------------------------------------------
452 
453 void BWindow::EndViewTransaction(){
454 	if ( fInTransaction ){
455 		Lock();
456 		session->WriteInt32( AS_END_TRANSACTION );
457 		session->Sync();
458 		Unlock();
459 
460 		fInTransaction		= false;
461 	}
462 }
463 
464 //------------------------------------------------------------------------------
465 
466 bool BWindow::IsFront() const{
467 	if (IsActive())
468 		return true;
469 
470 	if (IsModal())
471 		return true;
472 
473 	return false;
474 }
475 
476 //------------------------------------------------------------------------------
477 
478 void BWindow::MessageReceived( BMessage *msg )
479 {
480 	BMessage			specifier;
481 	int32				what;
482 	const char*			prop;
483 	int32				index;
484 	status_t			err;
485 
486 	if (msg->HasSpecifiers()){
487 
488 	err = msg->GetCurrentSpecifier(&index, &specifier, &what, &prop);
489 	if (err == B_OK)
490 	{
491 		BMessage			replyMsg;
492 
493 		switch (msg->what)
494 		{
495 		case B_GET_PROPERTY:{
496 				replyMsg.what		= B_NO_ERROR;
497 				replyMsg.AddInt32( "error", B_OK );
498 
499 				if (strcmp(prop, "Feel") ==0 )
500 				{
501 					replyMsg.AddInt32( "result", (uint32)Feel());
502 				}
503 				else if (strcmp(prop, "Flags") ==0 )
504 				{
505 					replyMsg.AddInt32( "result", Flags());
506 				}
507 				else if (strcmp(prop, "Frame") ==0 )
508 				{
509 					replyMsg.AddRect( "result", Frame());
510 				}
511 				else if (strcmp(prop, "Hidden") ==0 )
512 				{
513 					replyMsg.AddBool( "result", IsHidden());
514 				}
515 				else if (strcmp(prop, "Look") ==0 )
516 				{
517 					replyMsg.AddInt32( "result", (uint32)Look());
518 				}
519 				else if (strcmp(prop, "Title") ==0 )
520 				{
521 					replyMsg.AddString( "result", Title());
522 				}
523 				else if (strcmp(prop, "Workspaces") ==0 )
524 				{
525 					replyMsg.AddInt32( "result", Workspaces());
526 				}
527 			}break;
528 
529 		case B_SET_PROPERTY:{
530 				if (strcmp(prop, "Feel") ==0 )
531 				{
532 					uint32			newFeel;
533 					if (msg->FindInt32( "data", (int32*)&newFeel ) == B_OK){
534 						SetFeel( (window_feel)newFeel );
535 
536 						replyMsg.what		= B_NO_ERROR;
537 						replyMsg.AddInt32( "error", B_OK );
538 					}
539 					else{
540 						replyMsg.what		= B_MESSAGE_NOT_UNDERSTOOD;
541 						replyMsg.AddInt32( "error", B_BAD_SCRIPT_SYNTAX );
542 						replyMsg.AddString( "message", "Didn't understand the specifier(s)" );
543 					}
544 				}
545 
546 				else if (strcmp(prop, "Flags") ==0 )
547 				{
548 					uint32			newFlags;
549 					if (msg->FindInt32( "data", (int32*)&newFlags ) == B_OK){
550 						SetFlags( newFlags );
551 
552 						replyMsg.what		= B_NO_ERROR;
553 						replyMsg.AddInt32( "error", B_OK );
554 					}
555 					else{
556 						replyMsg.what		= B_MESSAGE_NOT_UNDERSTOOD;
557 						replyMsg.AddInt32( "error", B_BAD_SCRIPT_SYNTAX );
558 						replyMsg.AddString( "message", "Didn't understand the specifier(s)" );
559 					}
560 				}
561 
562 				else if (strcmp(prop, "Frame") ==0 )
563 				{
564 					BRect			newFrame;
565 					if (msg->FindRect( "data", &newFrame ) == B_OK){
566 						MoveTo( newFrame.LeftTop() );
567 						ResizeTo( newFrame.right, newFrame.bottom);
568 
569 						replyMsg.what		= B_NO_ERROR;
570 						replyMsg.AddInt32( "error", B_OK );
571 					}
572 					else{
573 						replyMsg.what		= B_MESSAGE_NOT_UNDERSTOOD;
574 						replyMsg.AddInt32( "error", B_BAD_SCRIPT_SYNTAX );
575 						replyMsg.AddString( "message", "Didn't understand the specifier(s)" );
576 					}
577 				}
578 
579 				else if (strcmp(prop, "Hidden") ==0 )
580 				{
581 					bool			newHiddenState;
582 					if (msg->FindBool( "data", &newHiddenState ) == B_OK){
583 						if ( !IsHidden() && newHiddenState == true ){
584 							Hide();
585 
586 							replyMsg.what		= B_NO_ERROR;
587 							replyMsg.AddInt32( "error", B_OK );
588 
589 						}
590 						else if ( IsHidden() && newHiddenState == false ){
591 							Show();
592 
593 							replyMsg.what		= B_NO_ERROR;
594 							replyMsg.AddInt32( "error", B_OK );
595 						}
596 						else{
597 							replyMsg.what		= B_MESSAGE_NOT_UNDERSTOOD;
598 							replyMsg.AddInt32( "error", B_BAD_SCRIPT_SYNTAX );
599 							replyMsg.AddString( "message", "Didn't understand the specifier(s)" );
600 						}
601 					}
602 					else{
603 						replyMsg.what		= B_MESSAGE_NOT_UNDERSTOOD;
604 						replyMsg.AddInt32( "error", B_BAD_SCRIPT_SYNTAX );
605 						replyMsg.AddString( "message", "Didn't understand the specifier(s)" );
606 					}
607 				}
608 
609 				else if (strcmp(prop, "Look") ==0 )
610 				{
611 					uint32			newLook;
612 					if (msg->FindInt32( "data", (int32*)&newLook ) == B_OK){
613 						SetLook( (window_look)newLook );
614 
615 						replyMsg.what		= B_NO_ERROR;
616 						replyMsg.AddInt32( "error", B_OK );
617 					}
618 					else{
619 						replyMsg.what		= B_MESSAGE_NOT_UNDERSTOOD;
620 						replyMsg.AddInt32( "error", B_BAD_SCRIPT_SYNTAX );
621 						replyMsg.AddString( "message", "Didn't understand the specifier(s)" );
622 					}
623 				}
624 
625 				else if (strcmp(prop, "Title") ==0 )
626 				{
627 					const char		*newTitle = NULL;
628 					if (msg->FindString( "data", &newTitle ) == B_OK){
629 						SetTitle( newTitle );
630 
631 						replyMsg.what		= B_NO_ERROR;
632 						replyMsg.AddInt32( "error", B_OK );
633 					}
634 					else{
635 						replyMsg.what		= B_MESSAGE_NOT_UNDERSTOOD;
636 						replyMsg.AddInt32( "error", B_BAD_SCRIPT_SYNTAX );
637 						replyMsg.AddString( "message", "Didn't understand the specifier(s)" );
638 					}
639 					delete newTitle;
640 				}
641 
642 				else if (strcmp(prop, "Workspaces") ==0 )
643 				{
644 					uint32			newWorkspaces;
645 					if (msg->FindInt32( "data", (int32*)&newWorkspaces ) == B_OK){
646 						SetWorkspaces( newWorkspaces );
647 
648 						replyMsg.what		= B_NO_ERROR;
649 						replyMsg.AddInt32( "error", B_OK );
650 					}
651 					else{
652 						replyMsg.what		= B_MESSAGE_NOT_UNDERSTOOD;
653 						replyMsg.AddInt32( "error", B_BAD_SCRIPT_SYNTAX );
654 						replyMsg.AddString( "message", "Didn't understand the specifier(s)" );
655 					}
656 				}
657 
658 			}break;
659 		}
660 		msg->SendReply( &replyMsg );
661 	}
662 	else{
663 		BMessage		replyMsg(B_MESSAGE_NOT_UNDERSTOOD);
664 		replyMsg.AddInt32( "error" , B_BAD_SCRIPT_SYNTAX );
665 		replyMsg.AddString( "message", "Didn't understand the specifier(s)" );
666 
667 		msg->SendReply( &replyMsg );
668 	}
669 
670 	} // END: if (msg->HasSpecifiers())
671 	else
672 		BLooper::MessageReceived( msg );
673 }
674 
675 //------------------------------------------------------------------------------
676 
677 void BWindow::DispatchMessage(BMessage *msg, BHandler *target)
678 {
679 	if (!msg){
680 		BLooper::DispatchMessage( msg, target );
681 		return;
682 	}
683 
684 	switch ( msg->what ) {
685 	case B_ZOOM:{
686 		Zoom();
687 		break;}
688 
689 	case B_MINIMIZE:{
690 		bool			minimize;
691 
692 		msg->FindBool("minimize", &minimize);
693 
694 		fMinimized		= minimize;
695 		Minimize( minimize );
696 		break;}
697 
698 	case B_WINDOW_RESIZED:{
699 		BPoint			offset;
700 		int32			width, height;
701 
702 		msg->FindInt32("width", &width);
703 		msg->FindInt32("height", &height);
704 		offset.x		= width;
705 		offset.y		= height;
706 
707 		fFrame.SetRightBottom( fFrame.LeftTop() + offset );
708 		FrameResized( offset.x, offset.y );
709 		break;}
710 
711 	case B_WINDOW_MOVED:{
712 		BPoint			origin;
713 
714 		msg->FindPoint("where", &origin);
715 
716 		fFrame.OffsetTo( origin );
717 		FrameMoved( origin );
718 		break;}
719 
720 		// this is NOT an app_server message and we have to be cautious
721 	case B_WINDOW_MOVE_BY:{
722 		BPoint			offset;
723 
724 		if (msg->FindPoint("data", &offset) == B_OK)
725 			MoveBy( offset.x, offset.y );
726 		else
727 			msg->SendReply( B_MESSAGE_NOT_UNDERSTOOD );
728 		break;}
729 
730 		// this is NOT an app_server message and we have to be cautious
731 	case B_WINDOW_MOVE_TO:{
732 		BPoint			origin;
733 
734 		if (msg->FindPoint("data", &origin) == B_OK)
735 			MoveTo( origin );
736 		else
737 			msg->SendReply( B_MESSAGE_NOT_UNDERSTOOD );
738 		break;}
739 
740 	case B_WINDOW_ACTIVATED:{
741 		bool			active;
742 
743 		msg->FindBool("active", &active);
744 
745 		fActive			= active;
746 		handleActivation( active );
747 		break;}
748 
749 	case B_SCREEN_CHANGED:{
750 		BRect			frame;
751 		uint32			mode;
752 
753 		msg->FindRect("frame", &frame);
754 		msg->FindInt32("mode", (int32*)&mode);
755 		ScreenChanged( frame, (color_space)mode );
756 		break;}
757 
758 	case B_WORKSPACE_ACTIVATED:{
759 		uint32			workspace;
760 		bool			active;
761 
762 		msg->FindInt32( "workspace", (int32*)&workspace );
763 		msg->FindBool( "active", &active );
764 		WorkspaceActivated( workspace, active );
765 		break;}
766 
767 	case B_WORKSPACES_CHANGED:{
768 		uint32			oldWorkspace;
769 		uint32			newWorkspace;
770 
771 		msg->FindInt32( "old", (int32*)&oldWorkspace );
772 		msg->FindInt32( "new", (int32*)&newWorkspace );
773 		WorkspacesChanged( oldWorkspace, newWorkspace );
774 		break;}
775 
776 	case B_KEY_DOWN:{
777 		uint32			modifiers;
778 		int32			raw_char;
779 		const char		*string;
780 
781 		msg->FindInt32( "modifiers", (int32*)&modifiers );
782 		msg->FindInt32( "raw_char", &raw_char );
783 		msg->FindString( "bytes", &string );
784 // TODO: it is NOT "bytes" field you should pass to KeyDown(), it is "byte" field.
785 		if ( !handleKeyDown( raw_char, (uint32)modifiers) )
786 			fFocus->KeyDown( string, strlen(string)-1 );
787 		break;}
788 
789 	case B_KEY_UP:{
790 		const char		*string;
791 
792 		msg->FindString( "bytes", &string );
793 		fFocus->KeyUp( string, strlen(string)-1 );
794 		break;}
795 
796 	case B_UNMAPPED_KEY_DOWN:{
797 		if (fFocus)
798 			fFocus->MessageReceived( msg );
799 		break;}
800 
801 	case B_UNMAPPED_KEY_UP:{
802 		if (fFocus)
803 			fFocus->MessageReceived( msg );
804 		break;}
805 
806 	case B_MODIFIERS_CHANGED:{
807 		if (fFocus)
808 			fFocus->MessageReceived( msg );
809 		break;}
810 
811 	case B_MOUSE_WHEEL_CHANGED:{
812 		if (fFocus)
813 			fFocus->MessageReceived( msg );
814 		break;}
815 
816 	case B_MOUSE_DOWN:{
817 		BPoint			where;
818 		uint32			modifiers;
819 		uint32			buttons;
820 		int32			clicks;
821 
822 		msg->FindPoint( "where", &where );
823 		msg->FindInt32( "modifiers", (int32*)&modifiers );
824 		msg->FindInt32( "buttons", (int32*)&buttons );
825 		msg->FindInt32( "clicks", &clicks );
826 
827 		sendMessageUsingEventMask( B_MOUSE_DOWN, where );
828 		break;}
829 
830 	case B_MOUSE_UP:{
831 		BPoint			where;
832 		uint32			modifiers;
833 
834 		msg->FindPoint( "where", &where );
835 		msg->FindInt32( "modifiers", (int32*)&modifiers );
836 
837 		sendMessageUsingEventMask( B_MOUSE_UP, where );
838 		break;}
839 
840 	case B_MOUSE_MOVED:{
841 		BPoint			where;
842 		uint32			buttons;
843 
844 		msg->FindPoint( "where", &where );
845 		msg->FindInt32( "buttons", (int32*)&buttons );
846 
847 		sendMessageUsingEventMask( B_MOUSE_MOVED, where );
848 		break;}
849 
850 	case B_PULSE:{
851 		if (fPulseEnabled)
852 			sendPulse( top_view );
853 		break;}
854 
855 	case B_QUIT_REQUESTED:{
856 		if (QuitRequested())
857 			Quit();
858 		break;}
859 
860 	case _UPDATE_:{
861 		BRect			updateRect;
862 		msg->FindRect("_rect", &updateRect);
863 
864 // TODO: ADD this method:
865 		//DrawViews( updateRect );
866 		break;}
867 
868 	case B_VIEW_MOVED:{
869 			BPoint			where;
870 			int32			token = B_NULL_TOKEN;
871 			BView			*view;
872 
873 			msg->FindPoint("where", &where);
874 			msg->FindInt32("_token", &token);
875 			msg->RemoveName("_token");
876 
877 			view			= findView(top_view, token);
878 			if (view){
879 				STRACE(("Calling BView(%s)::FrameMoved( %f, %f )\n", view->Name(), where.x, where.y));
880 				view->FrameMoved( where );
881 			}
882 			else
883 				printf("***PANIC: BW: Can't find view with ID: %ld !***\n", token);
884 
885 		break;}
886 
887 	case B_VIEW_RESIZED:{
888 			float			newWidth,
889 							newHeight;
890 			BPoint			where;
891 			int32			token = B_NULL_TOKEN;
892 			BView			*view;
893 
894 			msg->FindFloat("width", &newWidth);
895 			msg->FindFloat("height", &newHeight);
896 			msg->FindPoint("where", &where);
897 			msg->FindInt32("_token", &token);
898 			msg->RemoveName("_token");
899 
900 			view			= findView(top_view, token);
901 			if (view){
902 				STRACE(("Calling BView(%s)::FrameResized( %f, %f )\n", view->Name(), newWidth, newHeight));
903 				view->FrameResized( newWidth, newHeight );
904 			}
905 			else
906 				printf("***PANIC: BW: Can't find view with ID: %ld !***\n", token);
907 
908 		break;}
909 
910 	default:{
911 		BLooper::DispatchMessage(msg, target);
912 		break;}
913    }
914 }
915 
916 //------------------------------------------------------------------------------
917 
918 void BWindow::FrameMoved(BPoint new_position){
919 	// does nothing
920 	// Hook function
921 }
922 
923 //------------------------------------------------------------------------------
924 
925 void BWindow::FrameResized(float new_width, float new_height){
926 	// does nothing
927 	// Hook function
928 }
929 
930 //------------------------------------------------------------------------------
931 
932 void BWindow::WorkspacesChanged(uint32 old_ws, uint32 new_ws){
933 	// does nothing
934 	// Hook function
935 }
936 
937 //------------------------------------------------------------------------------
938 
939 void BWindow::WorkspaceActivated(int32 ws, bool state){
940 	// does nothing
941 	// Hook function
942 }
943 
944 //------------------------------------------------------------------------------
945 
946 void BWindow::MenusBeginning(){
947 	// does nothing
948 	// Hook function
949 }
950 
951 //------------------------------------------------------------------------------
952 
953 void BWindow::MenusEnded(){
954 	// does nothing
955 	// Hook function
956 }
957 
958 //------------------------------------------------------------------------------
959 
960 void BWindow::SetSizeLimits(float minWidth, float maxWidth,
961 							float minHeight, float maxHeight){
962 	int32		rCode;
963 
964 	if (minWidth > maxWidth)
965 		return;
966 	if (minHeight > maxHeight)
967 		return;
968 
969 	Lock();
970 	session->WriteInt32( AS_SET_SIZE_LIMITS );
971 	session->WriteFloat( fMinWindWidth );
972 	session->WriteFloat( fMaxWindWidth );
973 	session->WriteFloat( fMinWindHeight );
974 	session->WriteFloat( fMaxWindHeight );
975 	session->Sync();
976 	session->ReadInt32( &rCode );
977 	Unlock();
978 
979 	if (rCode == SERVER_TRUE){
980 		fMinWindHeight		= minHeight;
981 		fMinWindWidth		= minWidth;
982 		fMaxWindHeight		= maxHeight;
983 		fMaxWindWidth		= maxWidth;
984 	}
985 }
986 
987 //------------------------------------------------------------------------------
988 
989 void BWindow::GetSizeLimits(float *minWidth, float *maxWidth,
990 							float *minHeight, float *maxHeight){
991 	*minHeight			= fMinWindHeight;
992 	*minWidth			= fMinWindWidth;
993 	*maxHeight			= fMaxWindHeight;
994 	*maxWidth			= fMaxWindWidth;
995 }
996 
997 //------------------------------------------------------------------------------
998 
999 void BWindow::SetZoomLimits(float maxWidth, float maxHeight){
1000 	if (maxWidth > fMaxWindWidth)
1001 		maxWidth	= fMaxWindWidth;
1002 	else
1003 		fMaxZoomWidth		= maxWidth;
1004 
1005 	if (maxHeight > fMaxWindHeight)
1006 		maxHeight	= fMaxWindHeight;
1007 	else
1008 		fMaxZoomHeight		= maxHeight;
1009 }
1010 
1011 //------------------------------------------------------------------------------
1012 
1013 void BWindow::Zoom(	BPoint rec_position, float rec_width, float rec_height){
1014 
1015 		// this is also a Hook function!
1016 
1017 	MoveTo( rec_position );
1018 	ResizeTo( rec_width, rec_height );
1019 }
1020 
1021 //------------------------------------------------------------------------------
1022 
1023 void BWindow::Zoom(){
1024 	float			minWidth, minHeight;
1025 	BScreen			screen;
1026 /*	from BeBook:
1027 	However, if the window's rectangle already matches these "zoom" dimensions
1028 	(give or take a few pixels), Zoom() passes the window's previous
1029 	("non-zoomed") size and location. (??????)
1030 */
1031 	if (Frame().Width() == fMaxZoomWidth && Frame().Height() == fMaxZoomHeight) {
1032 		BPoint position( Frame().left, Frame().top);
1033 		Zoom( position, fMaxZoomWidth, fMaxZoomHeight );
1034 		return;
1035 	}
1036 
1037 /*	from BeBook:
1038 	The dimensions that non-virtual Zoom() passes to hook Zoom() are deduced from
1039 	the smallest of three rectangles: 3) the screen rectangle, 1) the rectangle
1040 	defined by SetZoomLimits(), 2) the rectangle defined by SetSizeLimits()
1041 */
1042 		// 1
1043 	minHeight		= fMaxZoomHeight;
1044 	minWidth		= fMaxZoomWidth;
1045 
1046 		// 2
1047 	if ( fMaxWindHeight < minHeight ) { minHeight		= fMaxWindHeight; }
1048 	if ( fMaxWindWidth  < minWidth  ) { minWidth		= fMaxWindWidth; }
1049 
1050 		// 3
1051 	if ( screen.Frame().Width()  < minWidth )   { minWidth		= screen.Frame().Width(); }
1052 	if ( screen.Frame().Height() < minHeight  ) { minHeight		= screen.Frame().Height(); }
1053 
1054 	Zoom( Frame().LeftTop(), minWidth, minHeight );
1055 }
1056 
1057 //------------------------------------------------------------------------------
1058 
1059 void BWindow::ScreenChanged(BRect screen_size, color_space depth){
1060 	// Hook function
1061 	// does nothing
1062 }
1063 
1064 //------------------------------------------------------------------------------
1065 
1066 void BWindow::SetPulseRate(bigtime_t rate){
1067 	if ( rate < 0 )
1068 		return;
1069 
1070 	if (fPulseRate == 0 && !fPulseEnabled){
1071 		fPulseRunner	= new BMessageRunner(	BMessenger(this),
1072 												new BMessage( B_PULSE ),
1073 												rate);
1074 		fPulseRate		= rate;
1075 		fPulseEnabled	= true;
1076 
1077 		return;
1078 	}
1079 
1080 	if (rate == 0 && fPulseEnabled){
1081 		delete			fPulseRunner;
1082 		fPulseRunner	= NULL;
1083 
1084 		fPulseRate		= rate;
1085 		fPulseEnabled	= false;
1086 
1087 		return;
1088 	}
1089 
1090 	fPulseRunner->SetInterval( rate );
1091 }
1092 
1093 //------------------------------------------------------------------------------
1094 
1095 bigtime_t BWindow::PulseRate() const{
1096 	return fPulseRate;
1097 }
1098 
1099 //------------------------------------------------------------------------------
1100 
1101 void BWindow::AddShortcut(	uint32 key,	uint32 modifiers, BMessage* msg){
1102 	AddShortcut( key, modifiers, msg, this);
1103 }
1104 
1105 //------------------------------------------------------------------------------
1106 
1107 void BWindow::AddShortcut(	uint32 key,	uint32 modifiers, BMessage* msg, BHandler* target){
1108 /*
1109 	NOTE: I'm not sure if it is OK to use 'key'
1110 */
1111 	if ( !msg )
1112 		return;
1113 
1114 	int64				when;
1115 	_BCmdKey			*cmdKey;
1116 
1117 	when				= real_time_clock_usecs();
1118 	msg->AddInt64("when", when);
1119 
1120 // TODO:	make sure key is a lowercase char !!!
1121 
1122 	modifiers			= modifiers | B_COMMAND_KEY;
1123 
1124 	cmdKey				= new _BCmdKey;
1125 	cmdKey->key			= key;
1126 	cmdKey->modifiers	= modifiers;
1127 	cmdKey->message		= msg;
1128 	if (target == NULL)
1129 		cmdKey->targetToken	= B_ANY_TOKEN;
1130 	else
1131 		cmdKey->targetToken	= _get_object_token_(target);
1132 
1133 		// removes the shortcut from accelList if it exists!
1134 	RemoveShortcut( key, modifiers );
1135 
1136 	accelList.AddItem( cmdKey );
1137 
1138 }
1139 
1140 //------------------------------------------------------------------------------
1141 
1142 void BWindow::RemoveShortcut(uint32 key, uint32 modifiers){
1143 	int32				index;
1144 
1145 	modifiers			= modifiers | B_COMMAND_KEY;
1146 
1147 	index				= findShortcut( key, modifiers );
1148 	if ( index >=0 ) {
1149 		_BCmdKey		*cmdKey;
1150 
1151 		cmdKey			= (_BCmdKey*)accelList.ItemAt( index );
1152 
1153 		accelList.RemoveItem(index);
1154 
1155 		delete cmdKey->message;
1156 		delete cmdKey;
1157 	}
1158 }
1159 
1160 //------------------------------------------------------------------------------
1161 
1162 BButton* BWindow::DefaultButton() const{
1163 	return fDefaultButton;
1164 }
1165 
1166 //------------------------------------------------------------------------------
1167 
1168 void BWindow::SetDefaultButton(BButton* button){
1169 /*
1170 Note: for developers!
1171 	He he, if you really want to understand what is happens here, take a piece of
1172 		paper and start taking possible values and then walk with them through
1173 		the code.
1174 */
1175 	BButton				*aux;
1176 
1177 	if ( fDefaultButton == button )
1178 		return;
1179 
1180 	if ( fDefaultButton ){
1181 		aux				= fDefaultButton;
1182 		fDefaultButton	= NULL;
1183 		aux->MakeDefault( false );
1184 		aux->Invalidate();
1185 	}
1186 
1187 	if ( button == NULL ){
1188 		fDefaultButton		= NULL;
1189 		return;
1190 	}
1191 
1192 	fDefaultButton			= button;
1193 	fDefaultButton->MakeDefault( true );
1194 	fDefaultButton->Invalidate();
1195 }
1196 
1197 //------------------------------------------------------------------------------
1198 
1199 bool BWindow::NeedsUpdate() const{
1200 
1201 	int32		rCode;
1202 
1203 	const_cast<BWindow*>(this)->Lock();
1204 	session->WriteInt32( AS_NEEDS_UPDATE );
1205 	session->Sync();
1206 	session->ReadInt32( &rCode );
1207 	const_cast<BWindow*>(this)->Unlock();
1208 
1209 	return rCode == SERVER_TRUE;
1210 }
1211 
1212 //------------------------------------------------------------------------------
1213 
1214 void BWindow::UpdateIfNeeded(){
1215 		// works only from this thread
1216 	if (find_thread(NULL) == Thread()){
1217 		Sync();
1218 		drawAllViews( top_view );
1219 	}
1220 }
1221 
1222 //------------------------------------------------------------------------------
1223 
1224 BView* BWindow::FindView(const char* viewName) const{
1225 
1226 	return findView( top_view, viewName );
1227 }
1228 
1229 //------------------------------------------------------------------------------
1230 
1231 BView* BWindow::FindView(BPoint point) const{
1232 
1233 	return findView( top_view, point );
1234 }
1235 
1236 //------------------------------------------------------------------------------
1237 
1238 BView* BWindow::CurrentFocus() const{
1239 	return fFocus;
1240 }
1241 
1242 //------------------------------------------------------------------------------
1243 
1244 void BWindow::Activate(bool active){
1245 	if (IsHidden())
1246 		return;
1247 
1248 	Lock();
1249 	session->WriteInt32( AS_ACTIVATE_WINDOW );
1250 	session->WriteBool( active );
1251 	session->Sync( );
1252 	Unlock();
1253 }
1254 
1255 //------------------------------------------------------------------------------
1256 
1257 void BWindow::WindowActivated(bool state){
1258 	// hook function
1259 	// does nothing
1260 }
1261 
1262 //------------------------------------------------------------------------------
1263 
1264 void BWindow::ConvertToScreen(BPoint* pt) const{
1265 	pt->x			+= fFrame.left;
1266 	pt->y			+= fFrame.top;
1267 }
1268 
1269 //------------------------------------------------------------------------------
1270 
1271 BPoint BWindow::ConvertToScreen(BPoint pt) const{
1272 	pt.x			+= fFrame.left;
1273 	pt.y			+= fFrame.top;
1274 
1275 	return pt;
1276 }
1277 
1278 //------------------------------------------------------------------------------
1279 
1280 void BWindow::ConvertFromScreen(BPoint* pt) const{
1281 	pt->x			-= fFrame.left;
1282 	pt->y			-= fFrame.top;
1283 }
1284 
1285 //------------------------------------------------------------------------------
1286 
1287 BPoint BWindow::ConvertFromScreen(BPoint pt) const{
1288 	pt.x			-= fFrame.left;
1289 	pt.y			-= fFrame.top;
1290 
1291 	return pt;
1292 }
1293 
1294 //------------------------------------------------------------------------------
1295 
1296 void BWindow::ConvertToScreen(BRect* rect) const{
1297 	rect->top			+= fFrame.top;
1298 	rect->left			+= fFrame.left;
1299 	rect->bottom		+= fFrame.top;
1300 	rect->right			+= fFrame.left;
1301 }
1302 
1303 //------------------------------------------------------------------------------
1304 
1305 BRect BWindow::ConvertToScreen(BRect rect) const{
1306 	rect.top			+= fFrame.top;
1307 	rect.left			+= fFrame.left;
1308 	rect.bottom			+= fFrame.top;
1309 	rect.right			+= fFrame.left;
1310 
1311 	return rect;
1312 }
1313 
1314 //------------------------------------------------------------------------------
1315 
1316 void BWindow::ConvertFromScreen(BRect* rect) const{
1317 	rect->top			-= fFrame.top;
1318 	rect->left			-= fFrame.left;
1319 	rect->bottom		-= fFrame.top;
1320 	rect->right			-= fFrame.left;
1321 }
1322 
1323 //------------------------------------------------------------------------------
1324 
1325 BRect BWindow::ConvertFromScreen(BRect rect) const{
1326 	rect.top			-= fFrame.top;
1327 	rect.left			-= fFrame.left;
1328 	rect.bottom			-= fFrame.top;
1329 	rect.right			-= fFrame.left;
1330 
1331 	return rect;
1332 }
1333 
1334 //------------------------------------------------------------------------------
1335 
1336 bool BWindow::IsMinimized() const{
1337 		// Hiding takes precendence over minimization!!!
1338 	if ( IsHidden() )
1339 		return false;
1340 
1341 	return fMinimized;
1342 }
1343 
1344 //------------------------------------------------------------------------------
1345 
1346 BRect BWindow::Bounds() const{
1347 	BRect			bounds( 0.0, 0.0, fFrame.Width(), fFrame.Height() );
1348 	return bounds;
1349 }
1350 
1351 //------------------------------------------------------------------------------
1352 
1353 BRect BWindow::Frame() const{
1354 	return fFrame;
1355 }
1356 
1357 //------------------------------------------------------------------------------
1358 
1359 const char* BWindow::Title() const{
1360 	return fTitle;
1361 }
1362 
1363 //------------------------------------------------------------------------------
1364 
1365 void BWindow::SetTitle(const char* title){
1366 	if (!title)
1367 		return;
1368 
1369 	if (fTitle){
1370 		delete fTitle;
1371 		fTitle = NULL;
1372 	}
1373 
1374 	fTitle		= strdup( title );
1375 
1376 		// we will change BWindow's thread name to "w>window_title"
1377 	int32		length;
1378 	length		= strlen( fTitle );
1379 
1380 	char		*threadName;
1381 	threadName	= new char[32];
1382 	strcpy(threadName, "w>");
1383 	strncat(threadName, fTitle, (length>=29) ? 29: length);
1384 
1385 		// if the message loop has been started...
1386 	if (Thread() != B_ERROR ){
1387 		SetName( threadName );
1388 		rename_thread( Thread(), threadName );
1389 
1390 			// we notify the app_server so we can actually see the change
1391 		Lock();
1392 		session->WriteInt32( AS_WINDOW_TITLE);
1393 		session->WriteString( fTitle );
1394 		session->Sync( );
1395 		Unlock();
1396 	}
1397 	else
1398 		SetName( threadName );
1399 }
1400 
1401 //------------------------------------------------------------------------------
1402 
1403 bool BWindow::IsActive() const{
1404 	return fActive;
1405 }
1406 
1407 //------------------------------------------------------------------------------
1408 
1409 void BWindow::SetKeyMenuBar(BMenuBar* bar){
1410 	fKeyMenuBar			= bar;
1411 }
1412 
1413 //------------------------------------------------------------------------------
1414 
1415 BMenuBar* BWindow::KeyMenuBar() const{
1416 	return fKeyMenuBar;
1417 }
1418 
1419 //------------------------------------------------------------------------------
1420 
1421 bool BWindow::IsModal() const{
1422 	if ( fFeel == B_MODAL_SUBSET_WINDOW_FEEL)
1423 		return true;
1424 	if ( fFeel == B_MODAL_APP_WINDOW_FEEL)
1425 		return true;
1426 	if ( fFeel == B_MODAL_ALL_WINDOW_FEEL)
1427 		return true;
1428 
1429 	return false;
1430 
1431 }
1432 
1433 //------------------------------------------------------------------------------
1434 
1435 bool BWindow::IsFloating() const{
1436 	if ( fFeel == B_FLOATING_SUBSET_WINDOW_FEEL)
1437 		return true;
1438 	if ( fFeel == B_FLOATING_APP_WINDOW_FEEL)
1439 		return true;
1440 	if ( fFeel == B_FLOATING_ALL_WINDOW_FEEL)
1441 		return true;
1442 
1443 	return false;
1444 }
1445 
1446 //------------------------------------------------------------------------------
1447 
1448 status_t BWindow::AddToSubset(BWindow* window){
1449 	if ( !window )
1450 			return B_ERROR;
1451 
1452 	int32		rCode;
1453 
1454 	if (window->Feel() == B_MODAL_SUBSET_WINDOW_FEEL ||
1455 		window->Feel() == B_FLOATING_SUBSET_WINDOW_FEEL){
1456 
1457 		Lock();
1458 		session->WriteInt32( AS_ADD_TO_SUBSET );
1459 		session->WriteInt32( _get_object_token_(window) );
1460 		session->Sync();
1461 		session->ReadInt32( &rCode );
1462 		Unlock();
1463 
1464 		return rCode == SERVER_TRUE? B_OK : B_ERROR;
1465 	}
1466 
1467 	return B_ERROR;
1468 }
1469 
1470 //------------------------------------------------------------------------------
1471 
1472 status_t BWindow::RemoveFromSubset(BWindow* window){
1473 	if ( !window )
1474 			return B_ERROR;
1475 
1476 	int32		rCode;
1477 
1478 	Lock();
1479 	session->WriteInt32( AS_REM_FROM_SUBSET );
1480 	session->WriteInt32( _get_object_token_(window) );
1481 	session->Sync();
1482 	session->ReadInt32( &rCode );
1483 	Unlock();
1484 
1485 	return rCode == SERVER_TRUE? B_OK : B_ERROR;
1486 }
1487 
1488 //------------------------------------------------------------------------------
1489 
1490 status_t BWindow::Perform(perform_code d, void* arg){
1491 	return BLooper::Perform( d, arg );
1492 }
1493 
1494 //------------------------------------------------------------------------------
1495 
1496 status_t BWindow::SetType(window_type type){
1497 	decomposeType(type, &fLook, &fFeel);
1498 	SetLook( fLook );
1499 	SetFeel( fFeel );
1500 }
1501 
1502 //------------------------------------------------------------------------------
1503 
1504 window_type	BWindow::Type() const{
1505 	return composeType( fLook, fFeel );
1506 }
1507 
1508 //------------------------------------------------------------------------------
1509 
1510 status_t BWindow::SetLook(window_look look){
1511 
1512 	int32		rCode;
1513 
1514 	Lock();
1515 	session->WriteInt32( AS_SET_LOOK );
1516 	session->WriteInt32( (int32)look );
1517 	session->Sync();
1518 	session->ReadInt32( &rCode );
1519 	Unlock();
1520 
1521 	if (rCode == SERVER_TRUE){
1522 		fLook		= look;
1523 		return B_OK;
1524 	}
1525 
1526 	return B_ERROR;
1527 }
1528 
1529 //------------------------------------------------------------------------------
1530 
1531 window_look	BWindow::Look() const{
1532 	return fLook;
1533 }
1534 
1535 //------------------------------------------------------------------------------
1536 
1537 status_t BWindow::SetFeel(window_feel feel){
1538 /* TODO:	See what happens when a window that is part of a subset, changes its
1539 			feel!? should it be removed from the subset???
1540 */
1541 	int32		rCode;
1542 
1543 	Lock();
1544 	session->WriteInt32( AS_SET_FEEL );
1545 	session->WriteInt32( (int32)feel );
1546 	session->Sync();
1547 	session->ReadInt32( &rCode );
1548 	Unlock();
1549 
1550 	if (rCode == SERVER_TRUE){
1551 		fFeel		= feel;
1552 		return B_OK;
1553 	}
1554 
1555 	return B_ERROR;
1556 }
1557 
1558 //------------------------------------------------------------------------------
1559 
1560 window_feel	BWindow::Feel() const{
1561 	return fFeel;
1562 }
1563 
1564 //------------------------------------------------------------------------------
1565 
1566 status_t BWindow::SetFlags(uint32 flags){
1567 
1568 	int32		rCode;
1569 
1570 	Lock();
1571 	session->WriteInt32( AS_SET_FLAGS );
1572 	session->WriteUInt32( flags );
1573 	session->Sync();
1574 	session->ReadInt32( &rCode );
1575 	Unlock();
1576 
1577 	if (rCode == SERVER_TRUE){
1578 		fFlags		= flags;
1579 		return B_OK;
1580 	}
1581 
1582 	return B_ERROR;
1583 }
1584 
1585 //------------------------------------------------------------------------------
1586 
1587 uint32	BWindow::Flags() const{
1588 	return fFlags;
1589 }
1590 
1591 //------------------------------------------------------------------------------
1592 
1593 status_t BWindow::SetWindowAlignment(window_alignment mode,
1594 											int32 h, int32 hOffset,
1595 											int32 width, int32 widthOffset,
1596 											int32 v, int32 vOffset,
1597 											int32 height, int32 heightOffset)
1598 {
1599 	if ( !(	(mode && B_BYTE_ALIGNMENT) ||
1600 			(mode && B_PIXEL_ALIGNMENT) ) )
1601 	{
1602 		return B_ERROR;
1603 	}
1604 
1605 	if ( 0 <= hOffset && hOffset <=h )
1606 		return B_ERROR;
1607 
1608 	if ( 0 <= vOffset && vOffset <=v )
1609 		return B_ERROR;
1610 
1611 	if ( 0 <= widthOffset && widthOffset <=width )
1612 		return B_ERROR;
1613 
1614 	if ( 0 <= heightOffset && heightOffset <=height )
1615 		return B_ERROR;
1616 
1617 // TODO: test if hOffset = 0 and set it to 1 if true.
1618 	int32		rCode;
1619 
1620 	Lock();
1621 	session->WriteInt32( AS_SET_ALIGNMENT );
1622 	session->WriteInt32( (int32)mode );
1623 	session->WriteInt32( h );
1624 	session->WriteInt32( hOffset );
1625 	session->WriteInt32( width );
1626 	session->WriteInt32( widthOffset );
1627 	session->WriteInt32( v );
1628 	session->WriteInt32( vOffset );
1629 	session->WriteInt32( height );
1630 	session->WriteInt32( heightOffset );
1631 	session->Sync();
1632 	session->ReadInt32( &rCode );
1633 	Unlock();
1634 
1635 	if ( rCode == SERVER_TRUE){
1636 		return B_NO_ERROR;
1637 	}
1638 
1639 	return B_ERROR;
1640 }
1641 
1642 //------------------------------------------------------------------------------
1643 
1644 status_t BWindow::GetWindowAlignment(window_alignment* mode,
1645 											int32* h, int32* hOffset,
1646 											int32* width, int32* widthOffset,
1647 											int32* v, int32* vOffset,
1648 											int32* height, int32* heightOffset) const
1649 {
1650 	int32		rCode;
1651 
1652 	const_cast<BWindow*>(this)->Lock();
1653 	session->WriteInt32( AS_GET_ALIGNMENT );
1654 	session->Sync();
1655 	session->ReadInt32( &rCode );
1656 
1657 	if (rCode == SERVER_TRUE){
1658 		session->ReadInt32( (int32*)mode );
1659 		session->ReadInt32( h );
1660 		session->ReadInt32( hOffset );
1661 		session->ReadInt32( width );
1662 		session->ReadInt32( widthOffset );
1663 		session->ReadInt32( v );
1664 		session->ReadInt32( hOffset );
1665 		session->ReadInt32( height );
1666 		session->ReadInt32( heightOffset );
1667 
1668 		return B_NO_ERROR;
1669 	}
1670 	const_cast<BWindow*>(this)->Unlock();
1671 
1672 	return B_ERROR;
1673 }
1674 
1675 //------------------------------------------------------------------------------
1676 
1677 uint32 BWindow::Workspaces() const{
1678 	uint32					workspaces;
1679 
1680 	const_cast<BWindow*>(this)->Lock();
1681 	session->WriteInt32( AS_GET_WORKSPACES );
1682 	session->Sync();
1683 	session->ReadInt32( (int32*)&workspaces );
1684 	const_cast<BWindow*>(this)->Unlock();
1685 
1686 	return workspaces;
1687 }
1688 
1689 //------------------------------------------------------------------------------
1690 
1691 void BWindow::SetWorkspaces(uint32 workspaces){
1692 
1693 	Lock();
1694 	session->WriteInt32( AS_SET_WORKSPACES );
1695 	session->WriteInt32( (int32)workspaces );
1696 	session->Sync( );
1697 	Unlock();
1698 }
1699 
1700 //------------------------------------------------------------------------------
1701 
1702 BView* BWindow::LastMouseMovedView() const{
1703 	return fLastMouseMovedView;
1704 }
1705 
1706 //------------------------------------------------------------------------------
1707 
1708 void BWindow::MoveBy(float dx, float dy){
1709 
1710 	BPoint			offset( dx, dy );
1711 
1712 	MoveTo( fFrame.LeftTop() + offset );
1713 }
1714 
1715 //------------------------------------------------------------------------------
1716 
1717 void BWindow::MoveTo( BPoint point ){
1718 	MoveTo( point.x, point.y );
1719 }
1720 
1721 //------------------------------------------------------------------------------
1722 
1723 void BWindow::MoveTo(float x, float y){
1724 
1725 	Lock();
1726 	session->WriteInt32( AS_WINDOW_MOVE );
1727 	session->WriteFloat( x );
1728 	session->WriteFloat( y );
1729 	session->Sync();
1730 	Unlock();
1731 }
1732 
1733 //------------------------------------------------------------------------------
1734 
1735 void BWindow::ResizeBy(float dx, float dy){
1736 
1737 		// stay in minimum & maximum frame limits
1738 	(fFrame.Width() + dx) < fMinWindWidth ? fMinWindWidth : fFrame.Width() + dx;
1739 	(fFrame.Width() + dx) > fMaxWindWidth ? fMaxWindWidth : fFrame.Width() + dx;
1740 
1741 	(fFrame.Height() + dy) < fMinWindHeight ? fMinWindHeight : fFrame.Height() + dy;
1742 	(fFrame.Height() + dy) > fMaxWindHeight ? fMaxWindHeight : fFrame.Height() + dy;
1743 
1744 	ResizeTo( fFrame.Width() + dx, fFrame.Height() + dy );
1745 }
1746 
1747 //------------------------------------------------------------------------------
1748 
1749 void BWindow::ResizeTo(float width, float height){
1750 
1751 		// stay in minimum & maximum frame limits
1752 	width = (width < fMinWindWidth) ? fMinWindWidth : width;
1753 	width = (width > fMaxWindWidth) ? fMaxWindWidth : width;
1754 
1755 	height = (height < fMinWindHeight) ? fMinWindHeight : height;
1756 	height = (height > fMaxWindHeight) ? fMaxWindHeight : height;
1757 
1758 	Lock();
1759 	session->WriteInt32( AS_WINDOW_RESIZE );
1760 	session->WriteFloat( width );
1761 	session->WriteFloat( height );
1762 	session->Sync( );
1763 	Unlock();
1764 }
1765 
1766 //------------------------------------------------------------------------------
1767 
1768 void BWindow::Show(){
1769 	bool	isLocked = this->IsLocked();
1770 
1771 	fShowLevel--;
1772 
1773 	if (fShowLevel == 0){
1774 		STRACE(("BWindow(%s): sending AS_SHOW_WINDOW message...\n", Name() ));
1775 		if ( !isLocked ) Lock();
1776 		session->WriteInt32( AS_SHOW_WINDOW );
1777 		session->Sync( );
1778 		if ( !isLocked) Unlock();
1779 	}
1780 
1781 		// if it's the fist time Show() is called... start the Looper thread.
1782 	if ( Thread() == B_ERROR )
1783 	{
1784 			// normaly this won't happen, but I want to be sure!
1785 		if ( !isLocked ) Lock();
1786 		Run();
1787 	}
1788 
1789 }
1790 
1791 //------------------------------------------------------------------------------
1792 
1793 void BWindow::Hide(){
1794 	if (fShowLevel == 0){
1795 		Lock();
1796 		session->WriteInt32( AS_HIDE_WINDOW );
1797 		session->Sync();
1798 		Unlock();
1799 	}
1800 	fShowLevel++;
1801 }
1802 
1803 //------------------------------------------------------------------------------
1804 
1805 bool BWindow::IsHidden() const{
1806 	return fShowLevel > 0;
1807 }
1808 
1809 //------------------------------------------------------------------------------
1810 
1811 bool BWindow::QuitRequested(){
1812 	return BLooper::QuitRequested();
1813 }
1814 
1815 //------------------------------------------------------------------------------
1816 
1817 thread_id BWindow::Run(){
1818 	return BLooper::Run();
1819 }
1820 
1821 //------------------------------------------------------------------------------
1822 
1823 status_t BWindow::GetSupportedSuites(BMessage* data){
1824 	status_t err = B_OK;
1825 	if (!data)
1826 		err = B_BAD_VALUE;
1827 
1828 	if (!err){
1829 		err = data->AddString("Suites", "suite/vnd.Be-window");
1830 		if (!err){
1831 			BPropertyInfo propertyInfo(windowPropInfo);
1832 			err = data->AddFlat("message", &propertyInfo);
1833 			if (!err){
1834 				err = BLooper::GetSupportedSuites(data);
1835 			}
1836 		}
1837 	}
1838 	return err;
1839 }
1840 
1841 //------------------------------------------------------------------------------
1842 
1843 BHandler* BWindow::ResolveSpecifier(BMessage* msg, int32 index,	BMessage* specifier,
1844 										int32 what,	const char* property)
1845 {
1846 	if (msg->what == B_WINDOW_MOVE_BY)
1847 		return this;
1848 	if (msg->what == B_WINDOW_MOVE_TO)
1849 		return this;
1850 
1851 	BPropertyInfo propertyInfo(windowPropInfo);
1852 	switch (propertyInfo.FindMatch(msg, index, specifier, what, property))
1853 	{
1854 		case B_ERROR:
1855 			break;
1856 		case 0:
1857 		case 1:
1858 		case 2:
1859 		case 3:
1860 		case 4:
1861 		case 5:
1862 		case 6:
1863 		case 7:
1864 		case 8:
1865 		case 9:
1866 		case 10:
1867 		case 11:
1868 		case 12:
1869 		case 13:
1870 			return this;
1871 
1872 		case 14:
1873 			if (fKeyMenuBar){
1874 				msg->PopSpecifier();
1875 				return fKeyMenuBar;
1876 			}
1877 			else{
1878 				BMessage		replyMsg(B_MESSAGE_NOT_UNDERSTOOD);
1879 				replyMsg.AddInt32( "error", B_NAME_NOT_FOUND );
1880 				replyMsg.AddString( "message", "This window doesn't have a main MenuBar");
1881 				msg->SendReply( &replyMsg );
1882 				return NULL;
1883 			}
1884 		case 15:
1885 				// we will NOT pop the current specifier
1886 			return top_view;
1887 
1888 		case 16:
1889 			return this;
1890 	}
1891 
1892 	return BLooper::ResolveSpecifier(msg, index, specifier, what, property);
1893 }
1894 
1895 // PRIVATE
1896 //--------------------Private Methods-------------------------------------------
1897 // PRIVATE
1898 
1899 void BWindow::InitData(	BRect frame,
1900 						const char* title,
1901 						window_look look,
1902 						window_feel feel,
1903 						uint32 flags,
1904 						uint32 workspace){
1905 
1906 	STRACE(("BWindow::InitData(...)\n"));
1907 
1908 	fTitle=NULL;
1909 	if ( be_app == NULL ){
1910 		debugger("You need a valid BApplication object before interacting with the app_server");
1911 		return;
1912 	}
1913 
1914 	fFrame		= frame;
1915 
1916 	if (title)
1917 		SetTitle( title );
1918 
1919 	fFeel			= feel;
1920 	fLook			= look;
1921 	fFlags			= flags;
1922 
1923 
1924 	fInTransaction	= false;
1925 	fActive			= false;
1926 	fShowLevel		= 1;
1927 
1928 	top_view		= NULL;
1929 	fFocus			= NULL;
1930 	fLastMouseMovedView	= NULL;
1931 	fKeyMenuBar		= NULL;
1932 	fDefaultButton	= NULL;
1933 
1934 //	accelList		= new BList( 10 );
1935 	AddShortcut('X', B_COMMAND_KEY, new BMessage(B_CUT), NULL);
1936 	AddShortcut('C', B_COMMAND_KEY, new BMessage(B_COPY), NULL);
1937 	AddShortcut('V', B_COMMAND_KEY, new BMessage(B_PASTE), NULL);
1938 	AddShortcut('A', B_COMMAND_KEY, new BMessage(B_SELECT_ALL), NULL);
1939 	AddShortcut('W', B_COMMAND_KEY, new BMessage(B_QUIT_REQUESTED));
1940 
1941 	fPulseEnabled	= false;
1942 	fPulseRate		= 0;
1943 	fPulseRunner	= NULL;
1944 
1945 // TODO: is this correct??? should the thread loop be started???
1946 	//SetPulseRate( 500000 );
1947 
1948 // TODO:  see if you can use 'fViewsNeedPulse'
1949 
1950 	fIsFilePanel	= false;
1951 
1952 // TODO: see WHEN is this used!
1953 	fMaskActivated	= false;
1954 
1955 // TODO: see WHEN is this used!
1956 	fWaitingForMenu	= false;
1957 
1958 	fMinimized		= false;
1959 
1960 // TODO:  see WHERE you can use 'fMenuSem'
1961 
1962 	fMaxZoomHeight	= 32768.0;
1963 	fMaxZoomWidth	= 32768.0;
1964 	fMinWindHeight	= 0.0;
1965 	fMinWindWidth	= 0.0;
1966 	fMaxWindHeight	= 32768.0;
1967 	fMaxWindWidth	= 32768.0;
1968 
1969 	fLastViewToken	= B_NULL_TOKEN;
1970 // TODO: other initializations!
1971 
1972 /*
1973 	Here, we will contact app_server and let him know that a window has
1974 		been created
1975 */
1976 	receive_port	= create_port( B_LOOPER_PORT_DEFAULT_CAPACITY ,
1977 						"w_rcv_port");
1978 	if (receive_port==B_BAD_VALUE || receive_port==B_NO_MORE_PORTS){
1979 		debugger("Could not create BWindow's receive port, used for interacting with the app_server!");
1980 		delete this;
1981 	}
1982 
1983 	STRACE(("BWindow::InitData(): contacting app_server...\n"));
1984 		// let app_server to know that a window has been created.
1985 
1986 	session		= new BSession( receive_port, be_app->fServerFrom );
1987 
1988 		// HERE we are in BApplication's thread, so for locking we use be_app variable
1989 		// we'll lock the be_app to be sure we're the only one writing at BApplication's server port
1990 	bool	locked = false;
1991 	if ( !(be_app->IsLocked()) )
1992 		{ be_app->Lock(); locked = true; }
1993 
1994 	session->WriteInt32( AS_CREATE_WINDOW );
1995 	session->WriteRect( fFrame );
1996 	session->WriteInt32( (int32)fLook );
1997 	session->WriteInt32( (int32)fFeel );
1998 	session->WriteUInt32( fFlags );
1999 	session->WriteUInt32( workspace );
2000 	session->WriteInt32( _get_object_token_(this) );
2001 	session->WriteData( &receive_port, sizeof(port_id) );
2002 	session->WriteData( &fMsgPort, sizeof(port_id) );
2003 	session->WriteString( title );
2004 	session->Sync();
2005 		// The port on witch app_server will listen for us
2006 	session->ReadData( &send_port, sizeof(port_id) );
2007 
2008 		// unlock, so other threads can do their job.
2009 	if( locked )
2010 		be_app->Unlock();
2011 
2012 	session->SetSendPort(send_port);
2013 
2014 	STRACE(("\tapp_server link established.\n"));
2015 	STRACE(("Window locked?: %s\n", IsLocked()?"True":"False"));
2016 
2017 		// build and register top_view with app_server
2018 	BuildTopView();
2019 //	top_view->PrintToStream();
2020 }
2021 
2022 //------------------------------------------------------------------------------
2023 
2024 void BWindow::task_looper(){
2025 
2026 	//	Check that looper is locked (should be)
2027 	AssertLocked();
2028 
2029 	Unlock();
2030 
2031 	using namespace BPrivate;
2032 	bool		dispatchNextMessage = false;
2033 	BMessage	*msg;
2034 
2035 	//	loop: As long as we are not terminating.
2036 	while (!fTerminating)
2037 	{
2038 		// get BMessages from app_server
2039 		while ( (msg = ReadMessageFromPort(10)) ){
2040 			fQueue->Lock();
2041 			fQueue->AddMessage(msg);
2042 			fQueue->Unlock();
2043 			dispatchNextMessage = true;
2044 		}
2045 
2046 		// get BMessages from BLooper port
2047 		while ( (msg = MessageFromPort(0)) ){
2048 			fQueue->Lock();
2049 			fQueue->AddMessage(msg);
2050 			fQueue->Unlock();
2051 			dispatchNextMessage = true;
2052 		}
2053 
2054 		//	loop: As long as there are messages in the queue and
2055 		//		  and we are not terminating.
2056 		while (!fTerminating && dispatchNextMessage)
2057 		{
2058 			fQueue->Lock();
2059 			fLastMessage		= fQueue->NextMessage();
2060 			fQueue->Unlock();
2061 
2062 			Lock();
2063 		// TODO: add code for drag & drop
2064 			if (!fLastMessage)
2065 			{
2066 				// No more messages: Unlock the looper and terminate the
2067 				// dispatch loop.
2068 				dispatchNextMessage = false;
2069 			}
2070 			else
2071 			{
2072 				//	Get the target handler
2073 				BHandler* handler;
2074 				if (_use_preferred_target_(fLastMessage))
2075 					handler = fPreferred;
2076 				else
2077 					gDefaultTokens.GetToken(_get_message_target_(fLastMessage),
2078 					 						 B_HANDLER_TOKEN,
2079 					 						 (void**)&handler);
2080 
2081 				if (!handler)
2082 					handler = this;
2083 
2084 				//	Is this a scripting message?
2085 				if (fLastMessage->HasSpecifiers())
2086 				{
2087 					int32 index = 0;
2088 					// Make sure the current specifier is kosher
2089 					if (fLastMessage->GetCurrentSpecifier(&index) == B_OK)
2090 						handler = resolve_specifier(handler, fLastMessage);
2091 				}
2092 
2093 				if (handler)
2094 				{
2095 					//	Do filtering
2096 					handler = top_level_filter(fLastMessage, handler);
2097 					if (handler && handler->Looper() == this)
2098 						DispatchMessage(fLastMessage, handler);
2099 				}
2100 			}
2101 				// empty our message buffer
2102 			session->Sync();
2103 
2104 			Unlock();
2105 
2106 			//	Delete the current message (fLastMessage)
2107 			if (fLastMessage)
2108 			{
2109 				delete fLastMessage;
2110 				fLastMessage = NULL;
2111 			}
2112 		}
2113 	}
2114 
2115 }
2116 
2117 //------------------------------------------------------------------------------
2118 
2119 BMessage* BWindow::ReadMessageFromPort(bigtime_t tout){
2120 	int32			msgCode;
2121 	BMessage*		msg = NULL;
2122 
2123 	ssize_t			bufferSize;
2124 
2125 		// we NEVER have to use B_INFINITE_TIMEOUT
2126 	if (tout == B_INFINITE_TIMEOUT)
2127 		tout = 0;
2128 
2129 		/* because BSession does not have support for timeout operations
2130 			We'll use this trick! :-) */
2131 	bufferSize = port_buffer_size_etc(receive_port, B_TIMEOUT, tout);
2132 	if (bufferSize == B_TIMED_OUT || bufferSize == B_BAD_PORT_ID ||
2133 		bufferSize == B_WOULD_BLOCK || bufferSize == B_INTERRUPTED )
2134 	{
2135 		msgCode = B_ERROR;
2136 	}
2137 
2138 		// we have something in our port's queue
2139 	if (bufferSize > 0){
2140 		/* A rudimentary synchronize mechanism between BWindow and app_server.
2141 		 *	Just in case some we do something foolish :-)
2142 		 *	It ensures a clean "restart" if I can call it that way.
2143 		 */
2144 		if ( session->DropInputBuffer() )
2145 			printf("***PANIC: BWindow(%s): BSession's input buffer dropped! The buffer WASN'T empty!***\n", Name());
2146 
2147 			// read message code
2148 		session->ReadInt32( &msgCode );
2149 	}
2150 
2151 	if ( msgCode != B_ERROR )
2152 		msg = ConvertToMessage( NULL, msgCode );
2153 
2154 	return msg;
2155 }
2156 
2157 //------------------------------------------------------------------------------
2158 
2159 window_type BWindow::composeType(window_look look,
2160 								 window_feel feel) const
2161 {
2162 	window_type returnValue = B_UNTYPED_WINDOW;
2163 
2164 	switch(feel)
2165 	{
2166 	case B_NORMAL_WINDOW_FEEL:
2167 		switch (look)
2168 		{
2169 		case B_TITLED_WINDOW_LOOK:
2170 			returnValue = B_TITLED_WINDOW;
2171 			break;
2172 
2173 		case B_DOCUMENT_WINDOW_LOOK:
2174 			returnValue = B_DOCUMENT_WINDOW;
2175 			break;
2176 
2177 		case B_BORDERED_WINDOW_LOOK:
2178 			returnValue = B_BORDERED_WINDOW;
2179 			break;
2180 
2181 		default:
2182 			returnValue = B_UNTYPED_WINDOW;
2183 		}
2184 		break;
2185 
2186 	case B_MODAL_APP_WINDOW_FEEL:
2187 		if (look == B_MODAL_WINDOW_LOOK)
2188 			returnValue = B_MODAL_WINDOW;
2189 		break;
2190 
2191 	case B_FLOATING_APP_WINDOW_FEEL:
2192 		if (look == B_FLOATING_WINDOW_LOOK)
2193 			returnValue = B_FLOATING_WINDOW;
2194 		break;
2195 
2196 	default:
2197 		returnValue = B_UNTYPED_WINDOW;
2198 	}
2199 
2200 	return returnValue;
2201 }
2202 
2203 //------------------------------------------------------------------------------
2204 
2205 void BWindow::decomposeType(window_type type,
2206 							   window_look* look,
2207 							   window_feel* feel) const
2208 {
2209 	switch (type)
2210 	{
2211 	case B_TITLED_WINDOW:
2212 		*look = B_TITLED_WINDOW_LOOK;
2213 		*feel = B_NORMAL_WINDOW_FEEL;
2214 		break;
2215 	case B_DOCUMENT_WINDOW:
2216 		*look = B_DOCUMENT_WINDOW_LOOK;
2217 		*feel = B_NORMAL_WINDOW_FEEL;
2218 		break;
2219 	case B_MODAL_WINDOW:
2220 		*look = B_MODAL_WINDOW_LOOK;
2221 		*feel = B_MODAL_APP_WINDOW_FEEL;
2222 		break;
2223 	case B_FLOATING_WINDOW:
2224 		*look = B_FLOATING_WINDOW_LOOK;
2225 		*feel = B_FLOATING_APP_WINDOW_FEEL;
2226 		break;
2227 	case B_BORDERED_WINDOW:
2228 		*look = B_BORDERED_WINDOW_LOOK;
2229 		*feel = B_NORMAL_WINDOW_FEEL;
2230 		break;
2231 	case B_UNTYPED_WINDOW:
2232 		*look = B_TITLED_WINDOW_LOOK;
2233 		*feel = B_NORMAL_WINDOW_FEEL;
2234 		break;
2235 	default:
2236 		*look = B_TITLED_WINDOW_LOOK;
2237 		*feel = B_NORMAL_WINDOW_FEEL;
2238 		break;
2239 	}
2240 }
2241 
2242 //------------------------------------------------------------------------------
2243 
2244 void BWindow::BuildTopView(){
2245 
2246 	top_view		= new BView( fFrame.OffsetToCopy(0,0), "top_view",
2247 								 B_FOLLOW_ALL, B_WILL_DRAW);
2248 	top_view->top_level_view	= true;
2249 	//top_view->fShowLevel		= 1;
2250 
2251 		// set top_view's owner, add it to window's eligible handler list
2252 		// and also set its next handler to be this window.
2253 	top_view->setOwner( this );
2254 
2255 		// send top_view's information to app_server
2256 	session->WriteInt32( AS_LAYER_CREATE_ROOT );
2257 	session->WriteInt32( _get_object_token_( top_view ) );
2258 	session->WriteRect( top_view->Frame() );
2259 	session->WriteInt32( top_view->ResizingMode() );
2260 	session->WriteInt32( top_view->Flags() );
2261 	session->WriteString( top_view->Name() );
2262 		// we DO NOT send our current state; the server knows the default values!
2263 	session->Sync();
2264 
2265 	fLastViewToken		= _get_object_token_( top_view );
2266 }
2267 
2268 //------------------------------------------------------------------------------
2269 
2270 void BWindow::stopConnection(){
2271 	Lock();
2272 	session->WriteInt32( AS_QUIT_WINDOW );
2273 	session->Sync();
2274 	Unlock();
2275 }
2276 
2277 //------------------------------------------------------------------------------
2278 
2279 void BWindow::prepareView(BView *aView){
2280 
2281 // TODO: implement
2282 
2283 }
2284 
2285 //------------------------------------------------------------------------------
2286 
2287 void BWindow::attachView(BView *aView){
2288 
2289 // TODO: implement
2290 
2291 }
2292 
2293 //------------------------------------------------------------------------------
2294 
2295 void BWindow::detachView(BView *aView){
2296 
2297 // TODO: implement
2298 
2299 }
2300 //------------------------------------------------------------------------------
2301 
2302 void BWindow::setFocus(BView *focusView, bool notifyInputServer){
2303 	BView* previousFocus = fFocus;
2304 
2305 	if (previousFocus == focusView)
2306 		return;
2307 
2308 	fFocus			= NULL;
2309 
2310 	if (previousFocus != NULL)
2311 		previousFocus->Invalidate();
2312 
2313 	fFocus			= focusView;
2314 
2315 	if (focusView != NULL)
2316 		focusView->Invalidate();
2317 
2318 // TODO: find out why do we have to notify input server.
2319 	if (notifyInputServer){
2320 		// what am I suppose to do here??
2321 	}
2322 }
2323 
2324 //------------------------------------------------------------------------------
2325 
2326 void BWindow::handleActivation( bool active ){
2327 
2328 	if (active){
2329 // TODO: talk to Ingo to make BWindow a friend for BRoster
2330 //		be_roster->UpdateActiveApp( be_app->Team() );
2331 	}
2332 
2333 	WindowActivated( active );
2334 
2335 		// recursively call hook function 'WindowActivated(bool)'
2336 		//    for all views attached to this window.
2337 	activateView( top_view, active );
2338 }
2339 
2340 //------------------------------------------------------------------------------
2341 
2342 void BWindow::activateView( BView *aView, bool active ){
2343 
2344 	aView->WindowActivated( active );
2345 
2346 	BView		*child;
2347 	if ( (child = aView->first_child) ){
2348 		while ( child ) {
2349 			activateView( child, active );
2350 			child 		= child->next_sibling;
2351 		}
2352 	}
2353 }
2354 
2355 //------------------------------------------------------------------------------
2356 
2357 bool BWindow::handleKeyDown( int32 raw_char, uint32 modifiers){
2358 
2359 // TODO: ask people if using 'raw_char' is OK ?
2360 
2361 		// handle BMenuBar key
2362 	if ( (raw_char == B_ESCAPE) && (modifiers & B_COMMAND_KEY)
2363 		&& fKeyMenuBar)
2364 	{
2365 
2366 // TODO: ask Marc about 'fWaitingForMenu' member!
2367 
2368 		// fWaitingForMenu		= true;
2369 		fKeyMenuBar->StartMenuBar(0, true, false, NULL);
2370 		return true;
2371 	}
2372 
2373 		// Command+q has been pressed, so, we will quit
2374 	if ( (raw_char == 'Q' || raw_char == 'q') && modifiers & B_COMMAND_KEY){
2375 		be_app->PostMessage(B_QUIT_REQUESTED);
2376 		return true;
2377 	}
2378 
2379 		// Keyboard navigation through views!!!!
2380 	if ( raw_char == B_TAB){
2381 
2382 			// even if we have no focus view, we'll say that we will handle TAB key
2383 		if (!fFocus)
2384 			return true;
2385 
2386 		BView			*nextFocus;
2387 
2388 		if (modifiers & B_CONTROL_KEY & B_SHIFT_KEY){
2389 			nextFocus		= findPrevView( fFocus, B_NAVIGABLE_JUMP );
2390 		}
2391 		else
2392 			if (modifiers & B_CONTROL_KEY){
2393 				nextFocus		= findNextView( fFocus, B_NAVIGABLE_JUMP );
2394 			}
2395 			else
2396 				if (modifiers & B_SHIFT_KEY){
2397 					nextFocus		= findPrevView( fFocus, B_NAVIGABLE );
2398 				}
2399 				else
2400 					nextFocus		= findNextView( fFocus, B_NAVIGABLE );
2401 
2402 		if ( nextFocus )
2403 			setFocus( nextFocus, false );
2404 
2405 		return true;
2406 	}
2407 
2408 		// Handle shortcuts
2409 	int			index;
2410 	if ( (index = findShortcut(raw_char, modifiers)) >=0){
2411 		_BCmdKey		*cmdKey;
2412 
2413 		cmdKey			= (_BCmdKey*)accelList.ItemAt( index );
2414 
2415 			// we'll give the message to the focus view
2416 		if (cmdKey->targetToken == B_ANY_TOKEN){
2417 			fFocus->MessageReceived( cmdKey->message );
2418 			return true;
2419 		}
2420 		else{
2421 			BHandler		*handler;
2422 			BHandler		*aHandler;
2423 			int				noOfHandlers;
2424 
2425 				// search for a match through BLooper's list of eligible handlers
2426 			handler			= NULL;
2427 			noOfHandlers	= CountHandlers();
2428 			for( int i=0; i < noOfHandlers; i++ )
2429 					// do we have a match?
2430 				if ( _get_object_token_( aHandler = HandlerAt(i) )
2431 					 == cmdKey->targetToken)
2432 				{
2433 						// yes, we do.
2434 					handler		= aHandler;
2435 					break;
2436 				}
2437 
2438 			if ( handler )
2439 				handler->MessageReceived( cmdKey->message );
2440 			else
2441 					// if no handler was found, BWindow will handle the message
2442 				MessageReceived( cmdKey->message );
2443 		}
2444 		return true;
2445 	}
2446 
2447 		// if <ENTER> is pressed and we have a default button
2448 	if (DefaultButton() && (raw_char == B_ENTER)){
2449 		const char		*chars;		// just to be sure
2450 		CurrentMessage()->FindString("bytes", &chars);
2451 
2452 		DefaultButton()->KeyDown( chars, strlen(chars)-1 );
2453 		return true;
2454 	}
2455 
2456 
2457 	return false;
2458 }
2459 
2460 //------------------------------------------------------------------------------
2461 
2462 BView* BWindow::sendMessageUsingEventMask2( BView* aView, int32 message, BPoint where ){
2463 
2464 	BView		*destView;
2465 	destView	= NULL;
2466 
2467 	if ( aView->fBounds.Contains( aView->ConvertFromScreen(where) ) &&
2468 		 !aView->first_child ){
2469 		return aView;
2470 	}
2471 
2472 		// Code for Event Masks
2473 	BView *child;
2474 	if ( (child = aView->first_child) ){
2475 		while ( child ) {
2476 				// see if a BView registered for mouse events and it's not the current focus view
2477 			if ( child->fEventMask & B_POINTER_EVENTS &&
2478 				 aView != fFocus ){
2479 				switch (message){
2480 					case B_MOUSE_DOWN:{
2481 						child->MouseDown( child->ConvertFromScreen( where ) );
2482 					}
2483 					break;
2484 
2485 					case B_MOUSE_UP:{
2486 						child->MouseUp( child->ConvertFromScreen( where ) );
2487 					}
2488 					break;
2489 
2490 					case B_MOUSE_MOVED:{
2491 						BMessage	*dragMessage;
2492 
2493 // TODO: get the dragMessage if any
2494 							// for now...
2495 						dragMessage	= NULL;
2496 
2497 /* TODO: after you have an example working, see if a view that registered for such events,
2498 			does reveive B_MOUSE_MOVED with other options than B_OUTDIDE_VIEW !!!
2499 					like: B_INSIDE_VIEW, B_ENTERED_VIEW, B_EXITED_VIEW
2500 */
2501 						child->MouseMoved( ConvertFromScreen(where), B_OUTSIDE_VIEW , dragMessage);
2502 					}
2503 					break;
2504 				}
2505 			}
2506 			if (destView == NULL)
2507 				destView = sendMessageUsingEventMask2( child, message, where );
2508 			else
2509 				sendMessageUsingEventMask2( child, message, where );
2510 			child = child->next_sibling;
2511 		}
2512 	}
2513 
2514 	return destView;
2515 }
2516 
2517 //------------------------------------------------------------------------------
2518 
2519 void BWindow::sendMessageUsingEventMask( int32 message, BPoint where ){
2520 	BView*			destView;
2521 
2522 	destView		= sendMessageUsingEventMask2(top_view, message, where);
2523 
2524 		// I'm SURE this is NEVER going to happen, but, durring development of BWindow, it may slip a NULL value
2525 	if (!destView){
2526 		// debugger("There is no BView under the mouse;");
2527 		return;
2528 	}
2529 
2530 	switch( message ){
2531 		case B_MOUSE_DOWN:{
2532 			setFocus( destView );
2533 			destView->MouseDown( destView->ConvertFromScreen( where ) );
2534 			break;}
2535 
2536 		case B_MOUSE_UP:{
2537 			destView->MouseUp( destView->ConvertFromScreen( where ) );
2538 			break;}
2539 
2540 		case B_MOUSE_MOVED:{
2541 			BMessage	*dragMessage;
2542 
2543 // TODO: add code for drag and drop
2544 				// for now...
2545 			dragMessage	= NULL;
2546 
2547 			if (destView != fLastMouseMovedView){
2548 				fLastMouseMovedView->MouseMoved( destView->ConvertFromScreen( where ), B_EXITED_VIEW , dragMessage);
2549 				destView->MouseMoved( ConvertFromScreen( where ), B_ENTERED_VIEW, dragMessage);
2550 				fLastMouseMovedView		= destView;
2551 			}
2552 			else{
2553 				destView->MouseMoved( ConvertFromScreen( where ), B_INSIDE_VIEW , dragMessage);
2554 			}
2555 
2556 				// I'm guessing that B_OUTSIDE_VIEW is given to the view that has focus, I'll have to check
2557 // TODO: Do a research on mouse capturing, maybe it has something to do with this
2558 			if (fFocus != destView)
2559 				fFocus->MouseMoved( ConvertFromScreen( where ), B_OUTSIDE_VIEW , dragMessage);
2560 			break;}
2561 	}
2562 }
2563 
2564 //------------------------------------------------------------------------------
2565 
2566 BMessage* BWindow::ConvertToMessage(void* raw1, int32 code){
2567 
2568 	BMessage	*msg;
2569 	msg			= new BMessage();
2570 		// time since 01/01/70
2571 	int64		when;
2572 
2573 	switch(code){
2574 		case B_WINDOW_ACTIVATED:{
2575 			bool		active;
2576 
2577 			session->ReadInt64( &when );
2578 			session->ReadBool( &active );
2579 
2580 			msg->what	= B_WINDOW_ACTIVATED;
2581 			msg->AddInt64("when", when);
2582 			msg->AddBool("active", active);
2583 
2584 			break;}
2585 
2586 		case B_QUIT_REQUESTED:{
2587 
2588 			msg->what	= B_QUIT_REQUESTED;
2589 			msg->AddBool("shortcut", false);
2590 
2591 			break;}
2592 
2593 		case B_KEY_DOWN:{
2594 			int32			physicalKeyCode,
2595 							repeat,
2596 							modifiers,
2597 							ASCIIcode;
2598 			char			*bytes = NULL;
2599 			uint8			states;
2600 			int8			UTF8_1, UTF8_2, UTF8_3;
2601 
2602 			session->ReadInt64( &when );
2603 			session->ReadInt32( &physicalKeyCode );
2604 			session->ReadInt32( &repeat );
2605 			session->ReadInt32( &modifiers );
2606 			session->ReadUInt8( &states );
2607 			session->ReadInt8( &UTF8_1 );
2608 			session->ReadInt8( &UTF8_2 );
2609 			session->ReadInt8( &UTF8_3 );
2610 			session->ReadInt32( &ASCIIcode );
2611 			bytes			= session->ReadString();
2612 
2613 			msg->what		= B_KEY_DOWN;
2614 			msg->AddInt64("when", when);
2615 			msg->AddInt32("key", physicalKeyCode);
2616 			msg->AddInt32("be:key_repeat", repeat);
2617 			msg->AddInt32("modifiers", modifiers);
2618 			msg->AddInt8("states", states);
2619 			msg->AddInt8("byte", UTF8_1);
2620 			msg->AddInt8("byte", UTF8_2);
2621 			msg->AddInt8("byte", UTF8_3);
2622 			msg->AddInt32("raw_char", ASCIIcode);
2623 			msg->AddString("bytes", bytes);
2624 
2625 			if (bytes)
2626 				delete bytes;
2627 
2628 			break;}
2629 
2630 		case B_KEY_UP:{
2631 			int32			physicalKeyCode,
2632 							modifiers,
2633 							ASCIIcode;
2634 			char			*bytes;
2635 			uint8			states;
2636 			int8			UTF8_1, UTF8_2, UTF8_3;
2637 
2638 			session->ReadInt64( &when );
2639 			session->ReadInt32( &physicalKeyCode );
2640 			session->ReadInt32( &modifiers );
2641 			session->ReadUInt8( &states );
2642 			session->ReadInt8( &UTF8_1 );
2643 			session->ReadInt8( &UTF8_2 );
2644 			session->ReadInt8( &UTF8_3 );
2645 			session->ReadInt32( &ASCIIcode );
2646 			bytes			= session->ReadString();
2647 
2648 			msg->what		= B_KEY_UP;
2649 			msg->AddInt64("when", when);
2650 			msg->AddInt32("key", physicalKeyCode);
2651 			msg->AddInt32("modifiers", modifiers);
2652 			msg->AddInt8("states", states);
2653 			msg->AddInt8("byte", UTF8_1);
2654 			msg->AddInt8("byte", UTF8_2);
2655 			msg->AddInt8("byte", UTF8_3);
2656 			msg->AddInt32("raw_char", ASCIIcode);
2657 			msg->AddString("bytes", bytes);
2658 
2659 			if (bytes)
2660 				delete bytes;
2661 
2662 			break;}
2663 
2664 		case B_UNMAPPED_KEY_DOWN:{
2665 			int32			physicalKeyCode,
2666 							modifiers;
2667 			uint8			states;
2668 
2669 			session->ReadInt64( &when );
2670 			session->ReadInt32( &physicalKeyCode );
2671 			session->ReadInt32( &modifiers );
2672 			session->ReadUInt8( &states );
2673 
2674 			msg->what		= B_UNMAPPED_KEY_DOWN;
2675 			msg->AddInt64("when", when);
2676 			msg->AddInt32("key", physicalKeyCode);
2677 			msg->AddInt32("modifiers", modifiers);
2678 			msg->AddInt8("states", states);
2679 
2680 			break;}
2681 
2682 		case B_UNMAPPED_KEY_UP:{
2683 			int32			physicalKeyCode,
2684 							modifiers;
2685 			uint8			states;
2686 
2687 			session->ReadInt64( &when );
2688 			session->ReadInt32( &physicalKeyCode );
2689 			session->ReadInt32( &modifiers );
2690 			session->ReadUInt8( &states );
2691 
2692 			msg->what		= B_UNMAPPED_KEY_UP;
2693 			msg->AddInt64("when", when);
2694 			msg->AddInt32("key", physicalKeyCode);
2695 			msg->AddInt32("modifiers", modifiers);
2696 			msg->AddInt8("states", states);
2697 
2698 			break;}
2699 
2700 		case B_MODIFIERS_CHANGED:{
2701 			int32			modifiers,
2702 							modifiersOld;
2703 			uint8			states;
2704 
2705 			session->ReadInt64( &when );
2706 			session->ReadInt32( &modifiers );
2707 			session->ReadInt32( &modifiersOld );
2708 			session->ReadUInt8( &states );
2709 
2710 			msg->what		= B_MODIFIERS_CHANGED;
2711 			msg->AddInt64("when", when);
2712 			msg->AddInt32("modifiers", modifiers);
2713 			msg->AddInt32("be:old_modifiers", modifiersOld);
2714 			msg->AddInt8("states", states);
2715 
2716 			break;}
2717 
2718 		case B_MINIMIZE:{
2719 			bool			minimize;
2720 
2721 			session->ReadInt64( &when );
2722 			session->ReadBool( &minimize );
2723 
2724 			msg->what		= B_MINIMIZE;
2725 			msg->AddInt64("when", when);
2726 			msg->AddBool("minimize", minimize);
2727 
2728 			break;}
2729 
2730 		case B_MOUSE_DOWN:{
2731 			int32			modifiers,
2732 							buttons,
2733 							noOfClicks;
2734 			BPoint			where;
2735 
2736 			session->ReadInt64( &when );
2737 			session->ReadPoint( &where );
2738 			session->ReadInt32( &modifiers );
2739 			session->ReadInt32( &buttons );
2740 			session->ReadInt32( &noOfClicks );
2741 
2742 			msg->what		= B_MOUSE_DOWN;
2743 			msg->AddInt64("when", when);
2744 			msg->AddPoint("where", where);
2745 			msg->AddInt32("modifiers", modifiers);
2746 			msg->AddInt32("buttons", buttons);
2747 			msg->AddInt32("clicks", noOfClicks);
2748 
2749 			break;}
2750 
2751 		case B_MOUSE_MOVED:{
2752 			int32			buttons;
2753 			int32			modifiers;		// added by OBOS Team
2754 			BPoint			where;
2755 
2756 			session->ReadInt64( &when );
2757 			session->ReadPoint( &where );
2758 			session->ReadInt32( &buttons );
2759 			session->ReadInt32( &modifiers );
2760 
2761 			msg->what		= B_MOUSE_MOVED;
2762 			msg->AddInt64("when", when);
2763 			msg->AddPoint("where", where);
2764 			msg->AddInt32("buttons", buttons);
2765 			msg->AddInt32("modifiers", modifiers);
2766 
2767 			break;}
2768 
2769 		case B_MOUSE_UP:{
2770 			int32			modifiers,
2771 							buttons;
2772 			BPoint			where;
2773 
2774 			session->ReadInt64( &when );
2775 			session->ReadPoint( &where );
2776 			session->ReadInt32( &buttons );
2777 			session->ReadInt32( &modifiers );
2778 
2779 			msg->what		= B_MOUSE_UP;
2780 			msg->AddInt64("when", when);
2781 			msg->AddPoint("where", where);
2782 			msg->AddInt32("modifiers", modifiers);
2783 			msg->AddInt32("buttons", buttons);
2784 
2785 			break;}
2786 
2787 		case B_MOUSE_WHEEL_CHANGED:{
2788 			float			whellChangeX,
2789 							whellChangeY;
2790 
2791 			session->ReadInt64( &when );
2792 			session->ReadFloat( &whellChangeX );
2793 			session->ReadFloat( &whellChangeY );
2794 
2795 			msg->what		= B_MOUSE_WHEEL_CHANGED;
2796 			msg->AddInt64("when", when);
2797 			msg->AddFloat("be:wheel_delta_x", whellChangeX);
2798 			msg->AddFloat("be:wheel_delta_y", whellChangeY);
2799 
2800 			break;}
2801 
2802 		case B_SCREEN_CHANGED:{
2803 			int32			colorSpace;
2804 			BRect			frame;
2805 
2806 			session->ReadInt64( &when );
2807 			session->ReadRect( &frame );
2808 			session->ReadInt32( &colorSpace );
2809 
2810 			msg->what		= B_SCREEN_CHANGED;
2811 			msg->AddInt64("when", when);
2812 			msg->AddRect("frame", frame);
2813 			msg->AddInt32("mode", colorSpace);
2814 
2815 			break;}
2816 
2817 		case B_WINDOW_MOVED:{
2818 			BPoint			where;
2819 
2820 			session->ReadInt64( &when );
2821 			session->ReadPoint( &where );
2822 
2823 			msg->what		= B_WINDOW_MOVED;
2824 			msg->AddInt64("when", when);
2825 			msg->AddPoint("where", where);
2826 
2827 			break;}
2828 
2829 		case B_WINDOW_RESIZED:{
2830 			int32			newWidth,
2831 							newHeight;
2832 
2833 			session->ReadInt64( &when );
2834 			session->ReadInt32( &newWidth );
2835 			session->ReadInt32( &newHeight );
2836 
2837 			msg->what		= B_WINDOW_RESIZED;
2838 			msg->AddInt64("when", when);
2839 			msg->AddInt32("width", newWidth);
2840 			msg->AddInt32("height", newHeight);
2841 
2842 			break;}
2843 
2844 		case B_WORKSPACES_CHANGED:{
2845 			int32			newWorkSpace,
2846 							oldWorkSpace;
2847 
2848 			session->ReadInt64( &when );
2849 			session->ReadInt32( &newWorkSpace );
2850 			session->ReadInt32( &oldWorkSpace );
2851 
2852 			msg->what		= B_WORKSPACES_CHANGED;
2853 			msg->AddInt64("when", when);
2854 			msg->AddInt32("old", oldWorkSpace);
2855 			msg->AddInt32("new", newWorkSpace);
2856 
2857 			break;}
2858 
2859 		case B_WORKSPACE_ACTIVATED:{
2860 			int32			workSpace;
2861 			bool			active;
2862 
2863 			session->ReadInt64( &when );
2864 			session->ReadInt32( &workSpace );
2865 			session->ReadBool( &active );
2866 
2867 			msg->what		= B_WORKSPACE_ACTIVATED;
2868 			msg->AddInt64("when", when);
2869 			msg->AddInt32("workspace", workSpace);
2870 			msg->AddBool("active", active);
2871 
2872 			break;}
2873 
2874 		case B_ZOOM:{
2875 
2876 			session->ReadInt64( &when );
2877 
2878 			msg->what		= B_ZOOM;
2879 			msg->AddInt64("when", when);
2880 
2881 			break;}
2882 
2883 		default:{
2884 			delete msg;
2885 
2886 			msg		= BLooper::ConvertToMessage( raw1, code );
2887 			if (!msg)
2888 				printf("***PANIC: app_server message NOT understood: '%c%c%c%c'***\n",
2889 					(char)((code & 0xFF000000) >> 24), (char)((code & 0x00FF0000) >> 16),
2890 					(char)((code & 0x0000FF00) >> 8), (char)(code & 0x000000FF) );
2891 			}
2892 	}
2893 
2894 	return msg;
2895 }
2896 
2897 //------------------------------------------------------------------------------
2898 
2899 void BWindow::sendPulse( BView* aView ){
2900 	BView *child;
2901 	if ( (child = aView->first_child) ){
2902 		while ( child ) {
2903 			if ( child->Flags() & B_PULSE_NEEDED ) child->Pulse();
2904 			sendPulse( child );
2905 			child = child->next_sibling;
2906 		}
2907 	}
2908 }
2909 
2910 //------------------------------------------------------------------------------
2911 
2912 int32 BWindow::findShortcut( uint32 key, uint32 modifiers ){
2913 	int32			index,
2914 					noOfItems;
2915 
2916 	index			= -1;
2917 	noOfItems		= accelList.CountItems();
2918 
2919 	for ( int32 i = 0;  i < noOfItems; i++ ) {
2920 		_BCmdKey*		tempCmdKey;
2921 
2922 		tempCmdKey		= (_BCmdKey*)accelList.ItemAt(i);
2923 		if (tempCmdKey->key == key && tempCmdKey->modifiers == modifiers){
2924 			index		= i;
2925 			break;
2926 		}
2927 	}
2928 
2929 	return index;
2930 }
2931 
2932 //------------------------------------------------------------------------------
2933 
2934 BView* BWindow::findView(BView* aView, int32 token){
2935 
2936 	if ( _get_object_token_(aView) == token )
2937 		return aView;
2938 
2939 	BView			*child;
2940 	if ( (child = aView->first_child) ){
2941 		while ( child ) {
2942 			BView*		view;
2943 			if ( (view = findView( child, token )) )
2944 				return view;
2945 			child 		= child->next_sibling;
2946 		}
2947 	}
2948 
2949 	return NULL;
2950 }
2951 
2952 //------------------------------------------------------------------------------
2953 
2954 BView* BWindow::findView(BView* aView, const char* viewName) const{
2955 
2956 	if ( strcmp( viewName, aView->Name() ) == 0)
2957 		return aView;
2958 
2959 	BView			*child;
2960 	if ( (child = aView->first_child) ){
2961 		while ( child ) {
2962 			BView*		view;
2963 			if ( (view = findView( child, viewName )) )
2964 				return view;
2965 			child 		= child->next_sibling;
2966 		}
2967 	}
2968 
2969 	return NULL;
2970 }
2971 
2972 //------------------------------------------------------------------------------
2973 
2974 BView* BWindow::findView(BView* aView, BPoint point) const{
2975 
2976 	if ( aView->Bounds().Contains(point) &&
2977 		 !aView->first_child )
2978 		return aView;
2979 
2980 	BView			*child;
2981 	if ( (child = aView->first_child) ){
2982 		while ( child ) {
2983 			BView*		view;
2984 			if ( (view = findView( child, point )) )
2985 				return view;
2986 			child 		= child->next_sibling;
2987 		}
2988 	}
2989 
2990 	return NULL;
2991 }
2992 
2993 //------------------------------------------------------------------------------
2994 
2995 BView* BWindow::findNextView( BView *focus, uint32 flags){
2996 	bool		found;
2997 	found		= false;
2998 
2999 	BView		*nextFocus;
3000 	nextFocus	= focus;
3001 
3002 		/*	Ufff... this toked me some time... this is the best form I've reached.
3003 				This algorithm searches the tree for BViews that accept focus.
3004 		*/
3005 	while (!found){
3006 		if (nextFocus->first_child)
3007 			nextFocus		= nextFocus->first_child;
3008 		else
3009 			if (nextFocus->next_sibling)
3010 				nextFocus		= nextFocus->next_sibling;
3011 			else{
3012 				while( !nextFocus->next_sibling && nextFocus->parent ){
3013 					nextFocus		= nextFocus->parent;
3014 				}
3015 
3016 				if (nextFocus == top_view)
3017 					nextFocus		= nextFocus->first_child;
3018 				else
3019 					nextFocus		= nextFocus->next_sibling;
3020 			}
3021 
3022 		if (nextFocus->Flags() & flags)
3023 			found = true;
3024 
3025 			/*	It means that the hole tree has been searched and there is no
3026 				view with B_NAVIGABLE_JUMP flag set!
3027 			*/
3028 		if (nextFocus == focus)
3029 			return NULL;
3030 	}
3031 
3032 	return nextFocus;
3033 }
3034 
3035 //------------------------------------------------------------------------------
3036 
3037 BView* BWindow::findPrevView( BView *focus, uint32 flags){
3038 	bool		found;
3039 	found		= false;
3040 
3041 	BView		*prevFocus;
3042 	prevFocus	= focus;
3043 
3044 	BView		*aView;
3045 
3046 	while (!found){
3047 		if ( (aView = findLastChild(prevFocus)) )
3048 			prevFocus		= aView;
3049 		else
3050 			if (prevFocus->prev_sibling)
3051 				prevFocus		= prevFocus->prev_sibling;
3052 			else{
3053 				while( !prevFocus->prev_sibling && prevFocus->parent ){
3054 					prevFocus		= prevFocus->parent;
3055 				}
3056 
3057 				if (prevFocus == top_view)
3058 					prevFocus		= findLastChild( prevFocus );
3059 				else
3060 					prevFocus		= prevFocus->prev_sibling;
3061 			}
3062 
3063 		if (prevFocus->Flags() & flags)
3064 			found = true;
3065 
3066 
3067 			/*	It means that the hole tree has been searched and there is no
3068 				view with B_NAVIGABLE_JUMP flag set!
3069 			*/
3070 		if (prevFocus == focus)
3071 			return NULL;
3072 	}
3073 
3074 	return prevFocus;
3075 }
3076 
3077 //------------------------------------------------------------------------------
3078 
3079 BView* BWindow::findLastChild(BView *parent){
3080 	BView		*aView;
3081 	if ( (aView = parent->first_child) ){
3082 		while (aView->next_sibling)
3083 			aView		= aView->next_sibling;
3084 
3085 		return aView;
3086 	}
3087 	else
3088 		return NULL;
3089 }
3090 
3091 //------------------------------------------------------------------------------
3092 
3093 void BWindow::drawAllViews(BView* aView){
3094 
3095 	BMessageQueue	*queue;
3096 	BMessage		*msg;
3097 
3098 	queue			= MessageQueue();
3099 
3100 		// process all update BMessages from message queue
3101 	queue->Lock();
3102 	while ( (msg = queue->FindMessage( (uint32)_UPDATE_ )) )
3103 	{
3104 		Lock();
3105 		DispatchMessage( msg, this );
3106 		Unlock();
3107 
3108 		queue->RemoveMessage( msg );
3109 	}
3110 	queue->Unlock();
3111 
3112 		// we'll send a message to app_server, tell him that we want all our views updated
3113 	Lock();
3114 	session->WriteInt32( AS_UPDATE_IF_NEEDED );
3115 	session->Sync();
3116 	Unlock();
3117 
3118 		// process all update messages from receive port queue
3119 	bool			over = false;
3120 	while (!over)
3121 	{
3122 		msg			= ReadMessageFromPort(0);
3123 		if (msg){
3124 			switch (msg->what){
3125 
3126 			case _ALL_UPDATED_:{
3127 				over		= true;
3128 				}break;
3129 
3130 			case _UPDATE_:{
3131 				Lock();
3132 				DispatchMessage( msg, this );
3133 				Unlock();
3134 				}break;
3135 
3136 			default:{
3137 				queue->Lock();
3138 				queue->AddMessage(msg);
3139 				queue->Unlock();
3140 				}break;
3141 			}
3142 		}
3143 	}
3144 }
3145 
3146 //------------------------------------------------------------------------------
3147 
3148 void BWindow::drawView(BView* aView, BRect area){
3149 
3150 /* TODO: Drawing during an Update
3151 			These settings are temporary. When the update is over, all graphics
3152 			  parameters are reset to their initial values
3153 */
3154 	aView->Draw( area );
3155 
3156 	BView			*child;
3157 	if ( (child = aView->first_child) ){
3158 		while ( child ) {
3159 			if ( area.Intersects( child->Frame() ) ){
3160 				BRect			newArea;
3161 
3162 				newArea			= area & child->Frame();
3163 				child->ConvertFromParent( &newArea );
3164 				child->Invalidate( newArea );
3165 			}
3166 			child 		= child->next_sibling;
3167 		}
3168 	}
3169 }
3170 
3171 //------------------------------------------------------------------------------
3172 
3173 void BWindow::SetIsFilePanel(bool yes){
3174 
3175 // TODO: is this not enough?
3176 	fIsFilePanel	= yes;
3177 }
3178 
3179 //------------------------------------------------------------------------------
3180 
3181 bool BWindow::IsFilePanel() const{
3182 	return fIsFilePanel;
3183 }
3184 
3185 
3186 //------------------------------------------------------------------------------
3187 // Virtual reserved Functions
3188 
3189 void BWindow::_ReservedWindow1() { }
3190 //------------------------------------------------------------------------------
3191 void BWindow::_ReservedWindow2() { }
3192 //------------------------------------------------------------------------------
3193 void BWindow::_ReservedWindow3() { }
3194 //------------------------------------------------------------------------------
3195 void BWindow::_ReservedWindow4() { }
3196 //------------------------------------------------------------------------------
3197 void BWindow::_ReservedWindow5() { }
3198 //------------------------------------------------------------------------------
3199 void BWindow::_ReservedWindow6() { }
3200 //------------------------------------------------------------------------------
3201 void BWindow::_ReservedWindow7() { }
3202 //------------------------------------------------------------------------------
3203 void BWindow::_ReservedWindow8() { }
3204 
3205 void BWindow::PrintToStream() const{
3206 	printf("BWindow '%s' data:\
3207 		Title			= %s\
3208 		Token			= %ld\
3209 		InTransaction 	= %s\
3210 		Active 			= %s\
3211 		fShowLevel		= %d\
3212 		Flags			= %lx\
3213 		send_port		= %ld\
3214 		receive_port	= %ld\
3215 		top_view name	= %s\
3216 		focus view name	= %s\
3217 		lastMouseMoved	= %s\
3218 		session			= %s\
3219 		KeyMenuBar name	= %s\
3220 		DefaultButton	= %s\
3221 		# of shortcuts	= %ld",
3222 		Name(),
3223 		fTitle!=NULL? fTitle:"NULL",
3224 		_get_object_token_(this),
3225 		fInTransaction==true? "yes":"no",
3226 		fActive==true? "yes":"no",
3227 		fShowLevel,
3228 		fFlags,
3229 		send_port,
3230 		receive_port,
3231 		top_view!=NULL? top_view->Name():"NULL",
3232 		fFocus!=NULL? fFocus->Name():"NULL",
3233 		fLastMouseMovedView!=NULL? fLastMouseMovedView->Name():"NULL",
3234 		session!=NULL? "In place":"NULL",
3235 		fKeyMenuBar!=NULL? fKeyMenuBar->Name():"NULL",
3236 		fDefaultButton!=NULL? fDefaultButton->Name():"NULL",
3237 		accelList.CountItems());
3238 /*
3239 	for( int32 i=0; i<accelList.CountItems(); i++){
3240 		_BCmdKey	*key = (_BCmdKey*)accelList.ItemAt(i);
3241 		printf("\tShortCut %ld: char %s\n\t\t message: \n", i, (key->key > 127)?"ASCII":"UNICODE");
3242 		key->message->PrintToStream();
3243 	}
3244 */
3245 	printf("\
3246 		topViewToken	= %ld\
3247 		pluseEnabled	= %s\
3248 		isFilePanel		= %s\
3249 		MaskActivated	= %s\
3250 		pulseRate		= %lld\
3251 		waitingForMenu	= %s\
3252 		minimized		= %s\
3253 		Menu semaphore	= %ld\
3254 		maxZoomHeight	= %f\
3255 		maxZoomWidth	= %f\
3256 		minWindHeight	= %f\
3257 		minWindWidth	= %f\
3258 		maxWindHeight	= %f\
3259 		maxWindWidth	= %f\
3260 		frame			= ( %f, %f, %f, %f )\
3261 		look			= %d\
3262 		feel			= %d\
3263 		lastViewToken	= %ld\
3264 		pulseRUNNER		= %s\n",
3265 		fTopViewToken,
3266 		fPulseEnabled==true?"Yes":"No",
3267 		fIsFilePanel==true?"Yes":"No",
3268 		fMaskActivated==true?"Yes":"No",
3269 		fPulseRate,
3270 		fWaitingForMenu==true?"Yes":"No",
3271 		fMinimized==true?"Yes":"No",
3272 		fMenuSem,
3273 		fMaxZoomHeight,
3274 		fMaxZoomWidth,
3275 		fMinWindHeight,
3276 		fMinWindWidth,
3277 		fMaxWindHeight,
3278 		fMaxWindWidth,
3279 		fFrame.left, fFrame.top, fFrame.right, fFrame.bottom,
3280 		(int16)fLook,
3281 		(int16)fFeel,
3282 		fLastViewToken,
3283 		fPulseRunner!=NULL?"In place":"NULL");
3284 }
3285 
3286 /*
3287 TODO list:
3288 
3289 	*) take care of temporarely events mask!!!
3290 	*) what's with this flag B_ASYNCHRONOUS_CONTROLS ?
3291 	*) test arguments for SetWindowAligment
3292 	*) call hook functions: MenusBeginning, MenusEnded. Add menu activation code.
3293 
3294 	* add handlers for B_VIEW_MOVED/RESIZED in DispatchMessage()
3295 	* modify _UPDATE_ handler in DispatchMessage()
3296 */
3297 
3298 /*
3299  @log
3300 	*modified ReadRawFromPort() and ConvertToMessage() methods to use BSession class.
3301 	*modified/added B_VIEW_(MOVED/RESIZED) handlers in ConvertToMessage()/DispatchMessage()
3302 */
3303