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