xref: /haiku/src/kits/interface/Window.cpp (revision 81f5654c124bf46fba0fd251f208e2d88d81e1ce)
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 	float		dxNew;
1759 	float		dyNew;
1760 
1761 		// stay in minimum & maximum frame limits
1762 	dxNew		= (fFrame.Width() + dx) < fMinWindWidth ? fFrame.Width() - fMinWindWidth : dx;
1763 	if (dxNew == dx)
1764 		dxNew	= (fFrame.Width() + dx) > fMaxWindWidth ? fMaxWindWidth - fFrame.Width() : dx;
1765 
1766 	dyNew		= (fFrame.Height() + dy) < fMinWindHeight ? fFrame.Height() - fMinWindHeight : dy;
1767 	if (dyNew == dy)
1768 		dyNew	= (fFrame.Height() + dy) > fMaxWindHeight ? fMaxWindHeight - fFrame.Height() : dy;
1769 
1770 	Lock();
1771 	session->WriteInt32( AS_WINDOW_RESIZE );
1772 	session->WriteFloat( dxNew );
1773 	session->WriteFloat( dyNew );
1774 	session->Sync( );
1775 	Unlock();
1776 }
1777 
1778 //------------------------------------------------------------------------------
1779 
1780 void BWindow::ResizeTo(float width, float height){
1781 	ResizeBy(width - fFrame.Width(), height - fFrame.Height());
1782 }
1783 
1784 //------------------------------------------------------------------------------
1785 
1786 void BWindow::Show(){
1787 	bool	isLocked = this->IsLocked();
1788 
1789 	fShowLevel--;
1790 
1791 	if (fShowLevel == 0){
1792 		STRACE(("BWindow(%s): sending AS_SHOW_WINDOW message...\n", Name() ));
1793 		if ( !isLocked ) Lock();
1794 		top_view->Show();
1795 		session->WriteInt32( AS_SHOW_WINDOW );
1796 		session->Sync();
1797 		if ( !isLocked ) Unlock();
1798 	}
1799 
1800 		// if it's the fist time Show() is called... start the Looper thread.
1801 	if ( Thread() == B_ERROR )
1802 	{
1803 			// normaly this won't happen, but I want to be sure!
1804 		if ( !isLocked ) Lock();
1805 		Run();
1806 	}
1807 
1808 }
1809 
1810 //------------------------------------------------------------------------------
1811 
1812 void BWindow::Hide(){
1813 	if (fShowLevel == 0){
1814 		Lock();
1815 		top_view->Hide();
1816 		session->WriteInt32( AS_HIDE_WINDOW );
1817 		session->Sync();
1818 		Unlock();
1819 	}
1820 	fShowLevel++;
1821 }
1822 
1823 //------------------------------------------------------------------------------
1824 
1825 bool BWindow::IsHidden() const{
1826 	return fShowLevel > 0;
1827 }
1828 
1829 //------------------------------------------------------------------------------
1830 
1831 bool BWindow::QuitRequested(){
1832 	return BLooper::QuitRequested();
1833 }
1834 
1835 //------------------------------------------------------------------------------
1836 
1837 thread_id BWindow::Run(){
1838 	return BLooper::Run();
1839 }
1840 
1841 //------------------------------------------------------------------------------
1842 
1843 status_t BWindow::GetSupportedSuites(BMessage* data){
1844 	status_t err = B_OK;
1845 	if (!data)
1846 		err = B_BAD_VALUE;
1847 
1848 	if (!err){
1849 		err = data->AddString("Suites", "suite/vnd.Be-window");
1850 		if (!err){
1851 			BPropertyInfo propertyInfo(windowPropInfo);
1852 			err = data->AddFlat("message", &propertyInfo);
1853 			if (!err){
1854 				err = BLooper::GetSupportedSuites(data);
1855 			}
1856 		}
1857 	}
1858 	return err;
1859 }
1860 
1861 //------------------------------------------------------------------------------
1862 
1863 BHandler* BWindow::ResolveSpecifier(BMessage* msg, int32 index,	BMessage* specifier,
1864 										int32 what,	const char* property)
1865 {
1866 	if (msg->what == B_WINDOW_MOVE_BY)
1867 		return this;
1868 	if (msg->what == B_WINDOW_MOVE_TO)
1869 		return this;
1870 
1871 	BPropertyInfo propertyInfo(windowPropInfo);
1872 	switch (propertyInfo.FindMatch(msg, index, specifier, what, property))
1873 	{
1874 		case B_ERROR:
1875 			break;
1876 		case 0:
1877 		case 1:
1878 		case 2:
1879 		case 3:
1880 		case 4:
1881 		case 5:
1882 		case 6:
1883 		case 7:
1884 		case 8:
1885 		case 9:
1886 		case 10:
1887 		case 11:
1888 		case 12:
1889 		case 13:
1890 			return this;
1891 
1892 		case 14:
1893 			if (fKeyMenuBar){
1894 				msg->PopSpecifier();
1895 				return fKeyMenuBar;
1896 			}
1897 			else{
1898 				BMessage		replyMsg(B_MESSAGE_NOT_UNDERSTOOD);
1899 				replyMsg.AddInt32( "error", B_NAME_NOT_FOUND );
1900 				replyMsg.AddString( "message", "This window doesn't have a main MenuBar");
1901 				msg->SendReply( &replyMsg );
1902 				return NULL;
1903 			}
1904 		case 15:
1905 				// we will NOT pop the current specifier
1906 			return top_view;
1907 
1908 		case 16:
1909 			return this;
1910 	}
1911 
1912 	return BLooper::ResolveSpecifier(msg, index, specifier, what, property);
1913 }
1914 
1915 // PRIVATE
1916 //--------------------Private Methods-------------------------------------------
1917 // PRIVATE
1918 
1919 void BWindow::InitData(	BRect frame,
1920 						const char* title,
1921 						window_look look,
1922 						window_feel feel,
1923 						uint32 flags,
1924 						uint32 workspace){
1925 
1926 	STRACE(("BWindow::InitData(...)\n"));
1927 
1928 	fTitle=NULL;
1929 	if ( be_app == NULL ){
1930 		debugger("You need a valid BApplication object before interacting with the app_server");
1931 		return;
1932 	}
1933 
1934 	fFrame		= frame;
1935 
1936 	if (title)
1937 		SetTitle( title );
1938 
1939 	fFeel			= feel;
1940 	fLook			= look;
1941 	fFlags			= flags;
1942 
1943 
1944 	fInTransaction	= false;
1945 	fActive			= false;
1946 	fShowLevel		= 1;
1947 
1948 	top_view		= NULL;
1949 	fFocus			= NULL;
1950 	fLastMouseMovedView	= NULL;
1951 	fKeyMenuBar		= NULL;
1952 	fDefaultButton	= NULL;
1953 
1954 //	accelList		= new BList( 10 );
1955 	AddShortcut('X', B_COMMAND_KEY, new BMessage(B_CUT), NULL);
1956 	AddShortcut('C', B_COMMAND_KEY, new BMessage(B_COPY), NULL);
1957 	AddShortcut('V', B_COMMAND_KEY, new BMessage(B_PASTE), NULL);
1958 	AddShortcut('A', B_COMMAND_KEY, new BMessage(B_SELECT_ALL), NULL);
1959 	AddShortcut('W', B_COMMAND_KEY, new BMessage(B_QUIT_REQUESTED));
1960 
1961 	fPulseEnabled	= false;
1962 	fPulseRate		= 0;
1963 	fPulseRunner	= NULL;
1964 
1965 // TODO: is this correct??? should the thread loop be started???
1966 	//SetPulseRate( 500000 );
1967 
1968 // TODO:  see if you can use 'fViewsNeedPulse'
1969 
1970 	fIsFilePanel	= false;
1971 
1972 // TODO: see WHEN is this used!
1973 	fMaskActivated	= false;
1974 
1975 // TODO: see WHEN is this used!
1976 	fWaitingForMenu	= false;
1977 
1978 	fMinimized		= false;
1979 
1980 // TODO:  see WHERE you can use 'fMenuSem'
1981 
1982 	fMaxZoomHeight	= 32768.0;
1983 	fMaxZoomWidth	= 32768.0;
1984 	fMinWindHeight	= 0.0;
1985 	fMinWindWidth	= 0.0;
1986 	fMaxWindHeight	= 32768.0;
1987 	fMaxWindWidth	= 32768.0;
1988 
1989 	fLastViewToken	= B_NULL_TOKEN;
1990 // TODO: other initializations!
1991 
1992 /*
1993 	Here, we will contact app_server and let him know that a window has
1994 		been created
1995 */
1996 	receive_port	= create_port( B_LOOPER_PORT_DEFAULT_CAPACITY ,
1997 						"w_rcv_port");
1998 	if (receive_port==B_BAD_VALUE || receive_port==B_NO_MORE_PORTS){
1999 		debugger("Could not create BWindow's receive port, used for interacting with the app_server!");
2000 		delete this;
2001 	}
2002 
2003 	STRACE(("BWindow::InitData(): contacting app_server...\n"));
2004 		// let app_server to know that a window has been created.
2005 
2006 	session		= new BSession( receive_port, be_app->fServerFrom );
2007 
2008 		// HERE we are in BApplication's thread, so for locking we use be_app variable
2009 		// we'll lock the be_app to be sure we're the only one writing at BApplication's server port
2010 	bool	locked = false;
2011 	if ( !(be_app->IsLocked()) )
2012 		{ be_app->Lock(); locked = true; }
2013 
2014 	PortMessage		pmsg;
2015 	PortLink		link(be_app->fServerFrom);
2016 	link.SetOpCode(AS_CREATE_WINDOW);
2017 
2018 	link.Attach<BRect>( fFrame );
2019 	link.Attach<int32>( (int32)fLook );
2020 	link.Attach<int32>( (int32)fFeel );
2021 	link.Attach<uint32>( fFlags );
2022 	link.Attach<uint32>( workspace );
2023 	link.Attach<int32>( _get_object_token_(this) );
2024 	link.Attach<port_id>( receive_port );
2025 	link.Attach<port_id>( fMsgPort );
2026 	link.AttachString( title );
2027 	link.FlushWithReply(&pmsg);
2028 
2029 	pmsg.Read<port_id>(&send_port);
2030 
2031 /*
2032 	session->WriteInt32( AS_CREATE_WINDOW );
2033 	session->WriteRect( fFrame );
2034 	session->WriteInt32( (int32)fLook );
2035 	session->WriteInt32( (int32)fFeel );
2036 	session->WriteUInt32( fFlags );
2037 	session->WriteUInt32( workspace );
2038 	session->WriteData( &team, sizeof(team_id));
2039 	session->WriteInt32( _get_object_token_(this) );
2040 	session->WriteData( &receive_port, sizeof(port_id) );
2041 	session->WriteData( &fMsgPort, sizeof(port_id) );
2042 	session->WriteString( title );
2043 
2044 printf("look: %ld\n", (int32)fLook);
2045 printf("title: %s\n", title);
2046 	session->Sync();
2047 		// The port on witch app_server will listen for us
2048 	STRACE(("here\n"));
2049 	session->ReadData( &send_port, sizeof(port_id) );
2050 */
2051 		// unlock, so other threads can do their job.
2052 	if( locked )
2053 		be_app->Unlock();
2054 
2055 	session->SetSendPort(send_port);
2056 
2057 	STRACE(("\tapp_server link established.\n"));
2058 	STRACE(("Window locked?: %s\n", IsLocked()?"True":"False"));
2059 
2060 		// build and register top_view with app_server
2061 	BuildTopView();
2062 //	top_view->PrintToStream();
2063 }
2064 
2065 //------------------------------------------------------------------------------
2066 
2067 void BWindow::task_looper(){
2068 
2069 	//	Check that looper is locked (should be)
2070 	AssertLocked();
2071 
2072 	Unlock();
2073 
2074 	using namespace BPrivate;
2075 	bool		dispatchNextMessage = false;
2076 	BMessage	*msg;
2077 
2078 	//	loop: As long as we are not terminating.
2079 	while (!fTerminating)
2080 	{
2081 		msg		= MessageFromPort();
2082 
2083 		//	Did we get a message?
2084 		if (msg){
2085 			//	Add to queue
2086 			fQueue->Lock();
2087 			fQueue->AddMessage(msg);
2088 			fQueue->Unlock();
2089 		}
2090 
2091 		//	Get message count from port
2092 		int32 msgCount = port_count(fMsgPort);
2093 		if (msgCount > 0){
2094 			fQueue->Lock();
2095 			for (int32 i = 0; i < msgCount; ++i)
2096 			{
2097 				//	Read 'count' messages from port (so we will not block)
2098 				//	We use zero as our timeout since we know there is stuff there
2099 				msg = MessageFromPort(0);
2100 				//	Add messages to queue
2101 				if (msg)
2102 					fQueue->AddMessage(msg);
2103 			}
2104 			fQueue->Unlock();
2105 		}
2106 
2107 		//	loop: As long as there are messages in the queue and
2108 		//		  and we are not terminating.
2109 		dispatchNextMessage		= true;
2110 		while (!fTerminating && dispatchNextMessage)
2111 		{
2112 			fQueue->Lock();
2113 			fLastMessage		= fQueue->NextMessage();
2114 			fQueue->Unlock();
2115 
2116 			Lock();
2117 
2118 		// TODO: add code for drag & drop
2119 			if (!fLastMessage)
2120 			{
2121 				// No more messages: Unlock the looper and terminate the
2122 				// dispatch loop.
2123 				dispatchNextMessage = false;
2124 			}
2125 			else
2126 			{
2127 				//	Get the target handler
2128 				BHandler* handler;
2129 				if (_use_preferred_target_(fLastMessage))
2130 					handler = fPreferred;
2131 				else
2132 					gDefaultTokens.GetToken(_get_message_target_(fLastMessage),
2133 					 						 B_HANDLER_TOKEN,
2134 					 						 (void**)&handler);
2135 
2136 				if (!handler)
2137 					handler = this;
2138 
2139 				//	Is this a scripting message?
2140 				if (fLastMessage->HasSpecifiers())
2141 				{
2142 					int32 index = 0;
2143 					// Make sure the current specifier is kosher
2144 					if (fLastMessage->GetCurrentSpecifier(&index) == B_OK)
2145 						handler = resolve_specifier(handler, fLastMessage);
2146 				}
2147 
2148 				if (handler)
2149 				{
2150 					//	Do filtering
2151 					handler = top_level_filter(fLastMessage, handler);
2152 					if (handler && handler->Looper() == this)
2153 						DispatchMessage(fLastMessage, handler);
2154 				}
2155 			}
2156 				// empty our message buffer
2157 			session->Sync();
2158 
2159 			Unlock();
2160 printf("Lock released\n");
2161 			//	Delete the current message (fLastMessage)
2162 			if (fLastMessage)
2163 			{
2164 				delete fLastMessage;
2165 				fLastMessage = NULL;
2166 			}
2167 
2168 			//	Are any messages on the port?
2169 			if (port_count(fMsgPort) > 0)
2170 			{
2171 				//	Do outer loop
2172 				dispatchNextMessage = false;
2173 			}
2174 		}
2175 	}
2176 
2177 }
2178 
2179 //------------------------------------------------------------------------------
2180 
2181 BMessage* BWindow::ReadMessageFromPort(bigtime_t tout){
2182 // TODO: remove!
2183 }
2184 
2185 //------------------------------------------------------------------------------
2186 
2187 window_type BWindow::composeType(window_look look,
2188 								 window_feel feel) const
2189 {
2190 	window_type returnValue = B_UNTYPED_WINDOW;
2191 
2192 	switch(feel)
2193 	{
2194 	case B_NORMAL_WINDOW_FEEL:
2195 		switch (look)
2196 		{
2197 		case B_TITLED_WINDOW_LOOK:
2198 			returnValue = B_TITLED_WINDOW;
2199 			break;
2200 
2201 		case B_DOCUMENT_WINDOW_LOOK:
2202 			returnValue = B_DOCUMENT_WINDOW;
2203 			break;
2204 
2205 		case B_BORDERED_WINDOW_LOOK:
2206 			returnValue = B_BORDERED_WINDOW;
2207 			break;
2208 
2209 		default:
2210 			returnValue = B_UNTYPED_WINDOW;
2211 		}
2212 		break;
2213 
2214 	case B_MODAL_APP_WINDOW_FEEL:
2215 		if (look == B_MODAL_WINDOW_LOOK)
2216 			returnValue = B_MODAL_WINDOW;
2217 		break;
2218 
2219 	case B_FLOATING_APP_WINDOW_FEEL:
2220 		if (look == B_FLOATING_WINDOW_LOOK)
2221 			returnValue = B_FLOATING_WINDOW;
2222 		break;
2223 
2224 	default:
2225 		returnValue = B_UNTYPED_WINDOW;
2226 	}
2227 
2228 	return returnValue;
2229 }
2230 
2231 //------------------------------------------------------------------------------
2232 
2233 void BWindow::decomposeType(window_type type,
2234 							   window_look* look,
2235 							   window_feel* feel) const
2236 {
2237 	switch (type)
2238 	{
2239 	case B_TITLED_WINDOW:
2240 		*look = B_TITLED_WINDOW_LOOK;
2241 		*feel = B_NORMAL_WINDOW_FEEL;
2242 		break;
2243 	case B_DOCUMENT_WINDOW:
2244 		*look = B_DOCUMENT_WINDOW_LOOK;
2245 		*feel = B_NORMAL_WINDOW_FEEL;
2246 		break;
2247 	case B_MODAL_WINDOW:
2248 		*look = B_MODAL_WINDOW_LOOK;
2249 		*feel = B_MODAL_APP_WINDOW_FEEL;
2250 		break;
2251 	case B_FLOATING_WINDOW:
2252 		*look = B_FLOATING_WINDOW_LOOK;
2253 		*feel = B_FLOATING_APP_WINDOW_FEEL;
2254 		break;
2255 	case B_BORDERED_WINDOW:
2256 		*look = B_BORDERED_WINDOW_LOOK;
2257 		*feel = B_NORMAL_WINDOW_FEEL;
2258 		break;
2259 	case B_UNTYPED_WINDOW:
2260 		*look = B_TITLED_WINDOW_LOOK;
2261 		*feel = B_NORMAL_WINDOW_FEEL;
2262 		break;
2263 	default:
2264 		*look = B_TITLED_WINDOW_LOOK;
2265 		*feel = B_NORMAL_WINDOW_FEEL;
2266 		break;
2267 	}
2268 }
2269 
2270 //------------------------------------------------------------------------------
2271 
2272 void BWindow::BuildTopView(){
2273 
2274 	top_view		= new BView( fFrame, "top_view",
2275 								 B_FOLLOW_ALL, B_WILL_DRAW);
2276 	top_view->top_level_view	= true;
2277 	top_view->fShowLevel		= 1;
2278 
2279 		// set top_view's owner, add it to window's eligible handler list
2280 		// and also set its next handler to this window.
2281 	top_view->setOwner( this );
2282 
2283 		// send top_view's information to app_server
2284 	session->WriteInt32( AS_LAYER_CREATE_ROOT );
2285 	fLastViewToken		= _get_object_token_( top_view );
2286 
2287 	top_view->attachView(top_view);
2288 
2289 STRACE(("BuildTopView ended\n"));
2290 }
2291 
2292 //------------------------------------------------------------------------------
2293 
2294 void BWindow::stopConnection(){
2295 	Lock();
2296 	session->WriteInt32( B_QUIT_REQUESTED );
2297 	session->Sync();
2298 	Unlock();
2299 }
2300 
2301 //------------------------------------------------------------------------------
2302 
2303 void BWindow::prepareView(BView *aView){
2304 
2305 // TODO: implement
2306 
2307 }
2308 
2309 //------------------------------------------------------------------------------
2310 
2311 void BWindow::attachView(BView *aView){
2312 
2313 // TODO: implement
2314 
2315 }
2316 
2317 //------------------------------------------------------------------------------
2318 
2319 void BWindow::detachView(BView *aView){
2320 
2321 // TODO: implement
2322 
2323 }
2324 //------------------------------------------------------------------------------
2325 
2326 void BWindow::setFocus(BView *focusView, bool notifyInputServer){
2327 	BView* previousFocus = fFocus;
2328 
2329 	if (previousFocus == focusView)
2330 		return;
2331 
2332 	fFocus			= NULL;
2333 
2334 	if (previousFocus != NULL)
2335 		previousFocus->Invalidate();
2336 
2337 	fFocus			= focusView;
2338 
2339 	if (focusView != NULL)
2340 		focusView->Invalidate();
2341 
2342 // TODO: find out why do we have to notify input server.
2343 	if (notifyInputServer){
2344 		// what am I suppose to do here??
2345 	}
2346 }
2347 
2348 //------------------------------------------------------------------------------
2349 
2350 void BWindow::handleActivation( bool active ){
2351 
2352 	if (active){
2353 // TODO: talk to Ingo to make BWindow a friend for BRoster
2354 //		be_roster->UpdateActiveApp( be_app->Team() );
2355 	}
2356 
2357 	WindowActivated( active );
2358 
2359 		// recursively call hook function 'WindowActivated(bool)'
2360 		//    for all views attached to this window.
2361 	activateView( top_view, active );
2362 }
2363 
2364 //------------------------------------------------------------------------------
2365 
2366 void BWindow::activateView( BView *aView, bool active ){
2367 
2368 	aView->WindowActivated( active );
2369 
2370 	BView		*child;
2371 	if ( (child = aView->first_child) ){
2372 		while ( child ) {
2373 			activateView( child, active );
2374 			child 		= child->next_sibling;
2375 		}
2376 	}
2377 }
2378 
2379 //------------------------------------------------------------------------------
2380 
2381 bool BWindow::handleKeyDown( int32 raw_char, uint32 modifiers){
2382 
2383 // TODO: ask people if using 'raw_char' is OK ?
2384 
2385 		// handle BMenuBar key
2386 	if ( (raw_char == B_ESCAPE) && (modifiers & B_COMMAND_KEY)
2387 		&& fKeyMenuBar)
2388 	{
2389 
2390 // TODO: ask Marc about 'fWaitingForMenu' member!
2391 
2392 		// fWaitingForMenu		= true;
2393 		fKeyMenuBar->StartMenuBar(0, true, false, NULL);
2394 		return true;
2395 	}
2396 
2397 		// Command+q has been pressed, so, we will quit
2398 	if ( (raw_char == 'Q' || raw_char == 'q') && modifiers & B_COMMAND_KEY){
2399 		be_app->PostMessage(B_QUIT_REQUESTED);
2400 		return true;
2401 	}
2402 
2403 		// Keyboard navigation through views!!!!
2404 	if ( raw_char == B_TAB){
2405 
2406 			// even if we have no focus view, we'll say that we will handle TAB key
2407 		if (!fFocus)
2408 			return true;
2409 
2410 		BView			*nextFocus;
2411 
2412 		if (modifiers & B_CONTROL_KEY & B_SHIFT_KEY){
2413 			nextFocus		= findPrevView( fFocus, B_NAVIGABLE_JUMP );
2414 		}
2415 		else
2416 			if (modifiers & B_CONTROL_KEY){
2417 				nextFocus		= findNextView( fFocus, B_NAVIGABLE_JUMP );
2418 			}
2419 			else
2420 				if (modifiers & B_SHIFT_KEY){
2421 					nextFocus		= findPrevView( fFocus, B_NAVIGABLE );
2422 				}
2423 				else
2424 					nextFocus		= findNextView( fFocus, B_NAVIGABLE );
2425 
2426 		if ( nextFocus )
2427 			setFocus( nextFocus, false );
2428 
2429 		return true;
2430 	}
2431 
2432 		// Handle shortcuts
2433 	int			index;
2434 	if ( (index = findShortcut(raw_char, modifiers)) >=0){
2435 		_BCmdKey		*cmdKey;
2436 
2437 		cmdKey			= (_BCmdKey*)accelList.ItemAt( index );
2438 
2439 			// we'll give the message to the focus view
2440 		if (cmdKey->targetToken == B_ANY_TOKEN){
2441 			fFocus->MessageReceived( cmdKey->message );
2442 			return true;
2443 		}
2444 		else{
2445 			BHandler		*handler;
2446 			BHandler		*aHandler;
2447 			int				noOfHandlers;
2448 
2449 				// search for a match through BLooper's list of eligible handlers
2450 			handler			= NULL;
2451 			noOfHandlers	= CountHandlers();
2452 			for( int i=0; i < noOfHandlers; i++ )
2453 					// do we have a match?
2454 				if ( _get_object_token_( aHandler = HandlerAt(i) )
2455 					 == cmdKey->targetToken)
2456 				{
2457 						// yes, we do.
2458 					handler		= aHandler;
2459 					break;
2460 				}
2461 
2462 			if ( handler )
2463 				handler->MessageReceived( cmdKey->message );
2464 			else
2465 					// if no handler was found, BWindow will handle the message
2466 				MessageReceived( cmdKey->message );
2467 		}
2468 		return true;
2469 	}
2470 
2471 		// if <ENTER> is pressed and we have a default button
2472 	if (DefaultButton() && (raw_char == B_ENTER)){
2473 		const char		*chars;		// just to be sure
2474 		CurrentMessage()->FindString("bytes", &chars);
2475 
2476 		DefaultButton()->KeyDown( chars, strlen(chars)-1 );
2477 		return true;
2478 	}
2479 
2480 
2481 	return false;
2482 }
2483 
2484 //------------------------------------------------------------------------------
2485 
2486 BView* BWindow::sendMessageUsingEventMask2( BView* aView, int32 message, BPoint where ){
2487 
2488 	BView		*destView;
2489 	destView	= NULL;
2490 
2491 	if ( aView->fBounds.Contains( aView->ConvertFromScreen(where) ) &&
2492 		 !aView->first_child ){
2493 		return aView;
2494 	}
2495 
2496 		// Code for Event Masks
2497 	BView *child;
2498 	if ( (child = aView->first_child) ){
2499 		while ( child ) {
2500 				// see if a BView registered for mouse events and it's not the current focus view
2501 			if ( child->fEventMask & B_POINTER_EVENTS &&
2502 				 aView != fFocus ){
2503 				switch (message){
2504 					case B_MOUSE_DOWN:{
2505 						child->MouseDown( child->ConvertFromScreen( where ) );
2506 					}
2507 					break;
2508 
2509 					case B_MOUSE_UP:{
2510 						child->MouseUp( child->ConvertFromScreen( where ) );
2511 					}
2512 					break;
2513 
2514 					case B_MOUSE_MOVED:{
2515 						BMessage	*dragMessage;
2516 
2517 // TODO: get the dragMessage if any
2518 							// for now...
2519 						dragMessage	= NULL;
2520 
2521 /* TODO: after you have an example working, see if a view that registered for such events,
2522 			does reveive B_MOUSE_MOVED with other options than B_OUTDIDE_VIEW !!!
2523 					like: B_INSIDE_VIEW, B_ENTERED_VIEW, B_EXITED_VIEW
2524 */
2525 						child->MouseMoved( ConvertFromScreen(where), B_OUTSIDE_VIEW , dragMessage);
2526 					}
2527 					break;
2528 				}
2529 			}
2530 			if (destView == NULL)
2531 				destView = sendMessageUsingEventMask2( child, message, where );
2532 			else
2533 				sendMessageUsingEventMask2( child, message, where );
2534 			child = child->next_sibling;
2535 		}
2536 	}
2537 
2538 	return destView;
2539 }
2540 
2541 //------------------------------------------------------------------------------
2542 
2543 void BWindow::sendMessageUsingEventMask( int32 message, BPoint where ){
2544 	BView*			destView;
2545 
2546 	destView		= sendMessageUsingEventMask2(top_view, message, where);
2547 
2548 		// I'm SURE this is NEVER going to happen, but, durring development of BWindow, it may slip a NULL value
2549 	if (!destView){
2550 		// debugger("There is no BView under the mouse;");
2551 		return;
2552 	}
2553 
2554 	switch( message ){
2555 		case B_MOUSE_DOWN:{
2556 			setFocus( destView );
2557 			destView->MouseDown( destView->ConvertFromScreen( where ) );
2558 			break;}
2559 
2560 		case B_MOUSE_UP:{
2561 			destView->MouseUp( destView->ConvertFromScreen( where ) );
2562 			break;}
2563 
2564 		case B_MOUSE_MOVED:{
2565 			BMessage	*dragMessage;
2566 
2567 // TODO: add code for drag and drop
2568 				// for now...
2569 			dragMessage	= NULL;
2570 
2571 			if (destView != fLastMouseMovedView){
2572 				fLastMouseMovedView->MouseMoved( destView->ConvertFromScreen( where ), B_EXITED_VIEW , dragMessage);
2573 				destView->MouseMoved( ConvertFromScreen( where ), B_ENTERED_VIEW, dragMessage);
2574 				fLastMouseMovedView		= destView;
2575 			}
2576 			else{
2577 				destView->MouseMoved( ConvertFromScreen( where ), B_INSIDE_VIEW , dragMessage);
2578 			}
2579 
2580 				// I'm guessing that B_OUTSIDE_VIEW is given to the view that has focus, I'll have to check
2581 // TODO: Do a research on mouse capturing, maybe it has something to do with this
2582 			if (fFocus != destView)
2583 				fFocus->MouseMoved( ConvertFromScreen( where ), B_OUTSIDE_VIEW , dragMessage);
2584 			break;}
2585 	}
2586 }
2587 
2588 //------------------------------------------------------------------------------
2589 
2590 BMessage* BWindow::ConvertToMessage(void* raw1, int32 code){
2591 
2592 	BMessage	*msg;
2593 	msg			= new BMessage();
2594 		// time since 01/01/70
2595 	int64		when;
2596 
2597 	switch(code){
2598 		case B_WINDOW_ACTIVATED:{
2599 			bool		active;
2600 
2601 			session->ReadInt64( &when );
2602 			session->ReadBool( &active );
2603 
2604 			msg->what	= B_WINDOW_ACTIVATED;
2605 			msg->AddInt64("when", when);
2606 			msg->AddBool("active", active);
2607 
2608 			break;}
2609 
2610 		case B_QUIT_REQUESTED:{
2611 
2612 			msg->what	= B_QUIT_REQUESTED;
2613 			msg->AddBool("shortcut", false);
2614 
2615 			break;}
2616 
2617 		case B_KEY_DOWN:{
2618 			int32			physicalKeyCode,
2619 							repeat,
2620 							modifiers,
2621 							ASCIIcode;
2622 			char			*bytes = NULL;
2623 			uint8			states;
2624 			int8			UTF8_1, UTF8_2, UTF8_3;
2625 
2626 			session->ReadInt64( &when );
2627 			session->ReadInt32( &physicalKeyCode );
2628 			session->ReadInt32( &repeat );
2629 			session->ReadInt32( &modifiers );
2630 			session->ReadUInt8( &states );
2631 			session->ReadInt8( &UTF8_1 );
2632 			session->ReadInt8( &UTF8_2 );
2633 			session->ReadInt8( &UTF8_3 );
2634 			session->ReadInt32( &ASCIIcode );
2635 			bytes			= session->ReadString();
2636 
2637 			msg->what		= B_KEY_DOWN;
2638 			msg->AddInt64("when", when);
2639 			msg->AddInt32("key", physicalKeyCode);
2640 			msg->AddInt32("be:key_repeat", repeat);
2641 			msg->AddInt32("modifiers", modifiers);
2642 			msg->AddInt8("states", states);
2643 			msg->AddInt8("byte", UTF8_1);
2644 			msg->AddInt8("byte", UTF8_2);
2645 			msg->AddInt8("byte", UTF8_3);
2646 			msg->AddInt32("raw_char", ASCIIcode);
2647 			msg->AddString("bytes", bytes);
2648 
2649 			if (bytes)
2650 				delete bytes;
2651 
2652 			break;}
2653 
2654 		case B_KEY_UP:{
2655 			int32			physicalKeyCode,
2656 							modifiers,
2657 							ASCIIcode;
2658 			char			*bytes;
2659 			uint8			states;
2660 			int8			UTF8_1, UTF8_2, UTF8_3;
2661 
2662 			session->ReadInt64( &when );
2663 			session->ReadInt32( &physicalKeyCode );
2664 			session->ReadInt32( &modifiers );
2665 			session->ReadUInt8( &states );
2666 			session->ReadInt8( &UTF8_1 );
2667 			session->ReadInt8( &UTF8_2 );
2668 			session->ReadInt8( &UTF8_3 );
2669 			session->ReadInt32( &ASCIIcode );
2670 			bytes			= session->ReadString();
2671 
2672 			msg->what		= B_KEY_UP;
2673 			msg->AddInt64("when", when);
2674 			msg->AddInt32("key", physicalKeyCode);
2675 			msg->AddInt32("modifiers", modifiers);
2676 			msg->AddInt8("states", states);
2677 			msg->AddInt8("byte", UTF8_1);
2678 			msg->AddInt8("byte", UTF8_2);
2679 			msg->AddInt8("byte", UTF8_3);
2680 			msg->AddInt32("raw_char", ASCIIcode);
2681 			msg->AddString("bytes", bytes);
2682 
2683 			if (bytes)
2684 				delete bytes;
2685 
2686 			break;}
2687 
2688 		case B_UNMAPPED_KEY_DOWN:{
2689 			int32			physicalKeyCode,
2690 							modifiers;
2691 			uint8			states;
2692 
2693 			session->ReadInt64( &when );
2694 			session->ReadInt32( &physicalKeyCode );
2695 			session->ReadInt32( &modifiers );
2696 			session->ReadUInt8( &states );
2697 
2698 			msg->what		= B_UNMAPPED_KEY_DOWN;
2699 			msg->AddInt64("when", when);
2700 			msg->AddInt32("key", physicalKeyCode);
2701 			msg->AddInt32("modifiers", modifiers);
2702 			msg->AddInt8("states", states);
2703 
2704 			break;}
2705 
2706 		case B_UNMAPPED_KEY_UP:{
2707 			int32			physicalKeyCode,
2708 							modifiers;
2709 			uint8			states;
2710 
2711 			session->ReadInt64( &when );
2712 			session->ReadInt32( &physicalKeyCode );
2713 			session->ReadInt32( &modifiers );
2714 			session->ReadUInt8( &states );
2715 
2716 			msg->what		= B_UNMAPPED_KEY_UP;
2717 			msg->AddInt64("when", when);
2718 			msg->AddInt32("key", physicalKeyCode);
2719 			msg->AddInt32("modifiers", modifiers);
2720 			msg->AddInt8("states", states);
2721 
2722 			break;}
2723 
2724 		case B_MODIFIERS_CHANGED:{
2725 			int32			modifiers,
2726 							modifiersOld;
2727 			uint8			states;
2728 
2729 			session->ReadInt64( &when );
2730 			session->ReadInt32( &modifiers );
2731 			session->ReadInt32( &modifiersOld );
2732 			session->ReadUInt8( &states );
2733 
2734 			msg->what		= B_MODIFIERS_CHANGED;
2735 			msg->AddInt64("when", when);
2736 			msg->AddInt32("modifiers", modifiers);
2737 			msg->AddInt32("be:old_modifiers", modifiersOld);
2738 			msg->AddInt8("states", states);
2739 
2740 			break;}
2741 
2742 		case B_MINIMIZE:{
2743 			bool			minimize;
2744 
2745 			session->ReadInt64( &when );
2746 			session->ReadBool( &minimize );
2747 
2748 			msg->what		= B_MINIMIZE;
2749 			msg->AddInt64("when", when);
2750 			msg->AddBool("minimize", minimize);
2751 
2752 			break;}
2753 
2754 		case B_MOUSE_DOWN:{
2755 			int32			modifiers,
2756 							buttons,
2757 							noOfClicks;
2758 			BPoint			where;
2759 
2760 			session->ReadInt64( &when );
2761 			session->ReadPoint( &where );
2762 			session->ReadInt32( &modifiers );
2763 			session->ReadInt32( &buttons );
2764 			session->ReadInt32( &noOfClicks );
2765 
2766 			msg->what		= B_MOUSE_DOWN;
2767 			msg->AddInt64("when", when);
2768 			msg->AddPoint("where", where);
2769 			msg->AddInt32("modifiers", modifiers);
2770 			msg->AddInt32("buttons", buttons);
2771 			msg->AddInt32("clicks", noOfClicks);
2772 
2773 			break;}
2774 
2775 		case B_MOUSE_MOVED:{
2776 			int32			buttons;
2777 			int32			modifiers;		// added by OBOS Team
2778 			BPoint			where;
2779 
2780 			session->ReadInt64( &when );
2781 			session->ReadPoint( &where );
2782 			session->ReadInt32( &buttons );
2783 			session->ReadInt32( &modifiers );
2784 
2785 			msg->what		= B_MOUSE_MOVED;
2786 			msg->AddInt64("when", when);
2787 			msg->AddPoint("where", where);
2788 			msg->AddInt32("buttons", buttons);
2789 			msg->AddInt32("modifiers", modifiers);
2790 
2791 			break;}
2792 
2793 		case B_MOUSE_UP:{
2794 			int32			modifiers,
2795 							buttons;
2796 			BPoint			where;
2797 
2798 			session->ReadInt64( &when );
2799 			session->ReadPoint( &where );
2800 			session->ReadInt32( &buttons );
2801 			session->ReadInt32( &modifiers );
2802 
2803 			msg->what		= B_MOUSE_UP;
2804 			msg->AddInt64("when", when);
2805 			msg->AddPoint("where", where);
2806 			msg->AddInt32("modifiers", modifiers);
2807 			msg->AddInt32("buttons", buttons);
2808 
2809 			break;}
2810 
2811 		case B_MOUSE_WHEEL_CHANGED:{
2812 			float			whellChangeX,
2813 							whellChangeY;
2814 
2815 			session->ReadInt64( &when );
2816 			session->ReadFloat( &whellChangeX );
2817 			session->ReadFloat( &whellChangeY );
2818 
2819 			msg->what		= B_MOUSE_WHEEL_CHANGED;
2820 			msg->AddInt64("when", when);
2821 			msg->AddFloat("be:wheel_delta_x", whellChangeX);
2822 			msg->AddFloat("be:wheel_delta_y", whellChangeY);
2823 
2824 			break;}
2825 
2826 		case B_SCREEN_CHANGED:{
2827 			int32			colorSpace;
2828 			BRect			frame;
2829 
2830 			session->ReadInt64( &when );
2831 			session->ReadRect( &frame );
2832 			session->ReadInt32( &colorSpace );
2833 
2834 			msg->what		= B_SCREEN_CHANGED;
2835 			msg->AddInt64("when", when);
2836 			msg->AddRect("frame", frame);
2837 			msg->AddInt32("mode", colorSpace);
2838 
2839 			break;}
2840 
2841 		case B_WINDOW_MOVED:{
2842 			BPoint			where;
2843 
2844 			session->ReadInt64( &when );
2845 			session->ReadPoint( &where );
2846 
2847 			msg->what		= B_WINDOW_MOVED;
2848 			msg->AddInt64("when", when);
2849 			msg->AddPoint("where", where);
2850 
2851 			break;}
2852 
2853 		case B_WINDOW_RESIZED:{
2854 			int32			newWidth,
2855 							newHeight;
2856 
2857 			session->ReadInt64( &when );
2858 			session->ReadInt32( &newWidth );
2859 			session->ReadInt32( &newHeight );
2860 
2861 			msg->what		= B_WINDOW_RESIZED;
2862 			msg->AddInt64("when", when);
2863 			msg->AddInt32("width", newWidth);
2864 			msg->AddInt32("height", newHeight);
2865 
2866 			break;}
2867 
2868 		case B_WORKSPACES_CHANGED:{
2869 			int32			newWorkSpace,
2870 							oldWorkSpace;
2871 
2872 			session->ReadInt64( &when );
2873 			session->ReadInt32( &newWorkSpace );
2874 			session->ReadInt32( &oldWorkSpace );
2875 
2876 			msg->what		= B_WORKSPACES_CHANGED;
2877 			msg->AddInt64("when", when);
2878 			msg->AddInt32("old", oldWorkSpace);
2879 			msg->AddInt32("new", newWorkSpace);
2880 
2881 			break;}
2882 
2883 		case B_WORKSPACE_ACTIVATED:{
2884 			int32			workSpace;
2885 			bool			active;
2886 
2887 			session->ReadInt64( &when );
2888 			session->ReadInt32( &workSpace );
2889 			session->ReadBool( &active );
2890 
2891 			msg->what		= B_WORKSPACE_ACTIVATED;
2892 			msg->AddInt64("when", when);
2893 			msg->AddInt32("workspace", workSpace);
2894 			msg->AddBool("active", active);
2895 
2896 			break;}
2897 
2898 		case B_ZOOM:{
2899 
2900 			session->ReadInt64( &when );
2901 
2902 			msg->what		= B_ZOOM;
2903 			msg->AddInt64("when", when);
2904 
2905 			break;}
2906 
2907 		default:{
2908 			delete msg;
2909 
2910 			msg		= BLooper::ConvertToMessage( raw1, code );
2911 			if (!msg)
2912 				printf("***PANIC: app_server message NOT understood: '%c%c%c%c'***\n",
2913 					(char)((code & 0xFF000000) >> 24), (char)((code & 0x00FF0000) >> 16),
2914 					(char)((code & 0x0000FF00) >> 8), (char)(code & 0x000000FF) );
2915 			}
2916 	}
2917 
2918 	return msg;
2919 }
2920 
2921 //------------------------------------------------------------------------------
2922 
2923 void BWindow::sendPulse( BView* aView ){
2924 	BView *child;
2925 	if ( (child = aView->first_child) ){
2926 		while ( child ) {
2927 			if ( child->Flags() & B_PULSE_NEEDED ) child->Pulse();
2928 			sendPulse( child );
2929 			child = child->next_sibling;
2930 		}
2931 	}
2932 }
2933 
2934 //------------------------------------------------------------------------------
2935 
2936 int32 BWindow::findShortcut( uint32 key, uint32 modifiers ){
2937 	int32			index,
2938 					noOfItems;
2939 
2940 	index			= -1;
2941 	noOfItems		= accelList.CountItems();
2942 
2943 	for ( int32 i = 0;  i < noOfItems; i++ ) {
2944 		_BCmdKey*		tempCmdKey;
2945 
2946 		tempCmdKey		= (_BCmdKey*)accelList.ItemAt(i);
2947 		if (tempCmdKey->key == key && tempCmdKey->modifiers == modifiers){
2948 			index		= i;
2949 			break;
2950 		}
2951 	}
2952 
2953 	return index;
2954 }
2955 
2956 //------------------------------------------------------------------------------
2957 
2958 BView* BWindow::findView(BView* aView, int32 token){
2959 
2960 	if ( _get_object_token_(aView) == token )
2961 		return aView;
2962 
2963 	BView			*child;
2964 	if ( (child = aView->first_child) ){
2965 		while ( child ) {
2966 			BView*		view;
2967 			if ( (view = findView( child, token )) )
2968 				return view;
2969 			child 		= child->next_sibling;
2970 		}
2971 	}
2972 
2973 	return NULL;
2974 }
2975 
2976 //------------------------------------------------------------------------------
2977 
2978 BView* BWindow::findView(BView* aView, const char* viewName) const{
2979 
2980 	if ( strcmp( viewName, aView->Name() ) == 0)
2981 		return aView;
2982 
2983 	BView			*child;
2984 	if ( (child = aView->first_child) ){
2985 		while ( child ) {
2986 			BView*		view;
2987 			if ( (view = findView( child, viewName )) )
2988 				return view;
2989 			child 		= child->next_sibling;
2990 		}
2991 	}
2992 
2993 	return NULL;
2994 }
2995 
2996 //------------------------------------------------------------------------------
2997 
2998 BView* BWindow::findView(BView* aView, BPoint point) const{
2999 
3000 	if ( aView->Bounds().Contains(point) &&
3001 		 !aView->first_child )
3002 		return aView;
3003 
3004 	BView			*child;
3005 	if ( (child = aView->first_child) ){
3006 		while ( child ) {
3007 			BView*		view;
3008 			if ( (view = findView( child, point )) )
3009 				return view;
3010 			child 		= child->next_sibling;
3011 		}
3012 	}
3013 
3014 	return NULL;
3015 }
3016 
3017 //------------------------------------------------------------------------------
3018 
3019 BView* BWindow::findNextView( BView *focus, uint32 flags){
3020 	bool		found;
3021 	found		= false;
3022 
3023 	BView		*nextFocus;
3024 	nextFocus	= focus;
3025 
3026 		/*	Ufff... this toked me some time... this is the best form I've reached.
3027 				This algorithm searches the tree for BViews that accept focus.
3028 		*/
3029 	while (!found){
3030 		if (nextFocus->first_child)
3031 			nextFocus		= nextFocus->first_child;
3032 		else
3033 			if (nextFocus->next_sibling)
3034 				nextFocus		= nextFocus->next_sibling;
3035 			else{
3036 				while( !nextFocus->next_sibling && nextFocus->parent ){
3037 					nextFocus		= nextFocus->parent;
3038 				}
3039 
3040 				if (nextFocus == top_view)
3041 					nextFocus		= nextFocus->first_child;
3042 				else
3043 					nextFocus		= nextFocus->next_sibling;
3044 			}
3045 
3046 		if (nextFocus->Flags() & flags)
3047 			found = true;
3048 
3049 			/*	It means that the hole tree has been searched and there is no
3050 				view with B_NAVIGABLE_JUMP flag set!
3051 			*/
3052 		if (nextFocus == focus)
3053 			return NULL;
3054 	}
3055 
3056 	return nextFocus;
3057 }
3058 
3059 //------------------------------------------------------------------------------
3060 
3061 BView* BWindow::findPrevView( BView *focus, uint32 flags){
3062 	bool		found;
3063 	found		= false;
3064 
3065 	BView		*prevFocus;
3066 	prevFocus	= focus;
3067 
3068 	BView		*aView;
3069 
3070 	while (!found){
3071 		if ( (aView = findLastChild(prevFocus)) )
3072 			prevFocus		= aView;
3073 		else
3074 			if (prevFocus->prev_sibling)
3075 				prevFocus		= prevFocus->prev_sibling;
3076 			else{
3077 				while( !prevFocus->prev_sibling && prevFocus->parent ){
3078 					prevFocus		= prevFocus->parent;
3079 				}
3080 
3081 				if (prevFocus == top_view)
3082 					prevFocus		= findLastChild( prevFocus );
3083 				else
3084 					prevFocus		= prevFocus->prev_sibling;
3085 			}
3086 
3087 		if (prevFocus->Flags() & flags)
3088 			found = true;
3089 
3090 
3091 			/*	It means that the hole tree has been searched and there is no
3092 				view with B_NAVIGABLE_JUMP flag set!
3093 			*/
3094 		if (prevFocus == focus)
3095 			return NULL;
3096 	}
3097 
3098 	return prevFocus;
3099 }
3100 
3101 //------------------------------------------------------------------------------
3102 
3103 BView* BWindow::findLastChild(BView *parent){
3104 	BView		*aView;
3105 	if ( (aView = parent->first_child) ){
3106 		while (aView->next_sibling)
3107 			aView		= aView->next_sibling;
3108 
3109 		return aView;
3110 	}
3111 	else
3112 		return NULL;
3113 }
3114 
3115 //------------------------------------------------------------------------------
3116 
3117 void BWindow::drawAllViews(BView* aView){
3118 
3119 	BMessageQueue	*queue;
3120 	BMessage		*msg;
3121 
3122 	queue			= MessageQueue();
3123 
3124 		// process all update BMessages from message queue
3125 	queue->Lock();
3126 	while ( (msg = queue->FindMessage( (uint32)_UPDATE_ )) )
3127 	{
3128 		Lock();
3129 		DispatchMessage( msg, this );
3130 		Unlock();
3131 
3132 		queue->RemoveMessage( msg );
3133 	}
3134 	queue->Unlock();
3135 
3136 		// we'll send a message to app_server, tell him that we want all our views updated
3137 	Lock();
3138 	session->WriteInt32( AS_UPDATE_IF_NEEDED );
3139 	session->Sync();
3140 	Unlock();
3141 
3142 // TODO: update!!!!!!!!!!!!!!!!!!!
3143 		// process all update messages from receive port queue
3144 	bool			over = false;
3145 	while (!over)
3146 	{
3147 		msg			= MessageFromPort(0);
3148 		if (msg){
3149 			switch (msg->what){
3150 
3151 			case _ALL_UPDATED_:{
3152 				over		= true;
3153 				}break;
3154 
3155 			case _UPDATE_:{
3156 				Lock();
3157 				DispatchMessage( msg, this );
3158 				Unlock();
3159 				}break;
3160 
3161 			default:{
3162 				queue->Lock();
3163 				queue->AddMessage(msg);
3164 				queue->Unlock();
3165 				}break;
3166 			}
3167 		}
3168 	}
3169 }
3170 
3171 //------------------------------------------------------------------------------
3172 
3173 void BWindow::drawView(BView* aView, BRect area){
3174 
3175 /* TODO: Drawing during an Update
3176 			These settings are temporary. When the update is over, all graphics
3177 			  parameters are reset to their initial values
3178 */
3179 	aView->Draw( area );
3180 
3181 	BView			*child;
3182 	if ( (child = aView->first_child) ){
3183 		while ( child ) {
3184 			if ( area.Intersects( child->Frame() ) ){
3185 				BRect			newArea;
3186 
3187 				newArea			= area & child->Frame();
3188 				child->ConvertFromParent( &newArea );
3189 				child->Invalidate( newArea );
3190 			}
3191 			child 		= child->next_sibling;
3192 		}
3193 	}
3194 }
3195 
3196 //------------------------------------------------------------------------------
3197 
3198 void BWindow::SetIsFilePanel(bool yes){
3199 
3200 // TODO: is this not enough?
3201 	fIsFilePanel	= yes;
3202 }
3203 
3204 //------------------------------------------------------------------------------
3205 
3206 bool BWindow::IsFilePanel() const{
3207 	return fIsFilePanel;
3208 }
3209 
3210 
3211 //------------------------------------------------------------------------------
3212 // Virtual reserved Functions
3213 
3214 void BWindow::_ReservedWindow1() { }
3215 //------------------------------------------------------------------------------
3216 void BWindow::_ReservedWindow2() { }
3217 //------------------------------------------------------------------------------
3218 void BWindow::_ReservedWindow3() { }
3219 //------------------------------------------------------------------------------
3220 void BWindow::_ReservedWindow4() { }
3221 //------------------------------------------------------------------------------
3222 void BWindow::_ReservedWindow5() { }
3223 //------------------------------------------------------------------------------
3224 void BWindow::_ReservedWindow6() { }
3225 //------------------------------------------------------------------------------
3226 void BWindow::_ReservedWindow7() { }
3227 //------------------------------------------------------------------------------
3228 void BWindow::_ReservedWindow8() { }
3229 
3230 void BWindow::PrintToStream() const{
3231 	printf("BWindow '%s' data:\
3232 		Title			= %s\
3233 		Token			= %ld\
3234 		InTransaction 	= %s\
3235 		Active 			= %s\
3236 		fShowLevel		= %d\
3237 		Flags			= %lx\
3238 		send_port		= %ld\
3239 		receive_port	= %ld\
3240 		top_view name	= %s\
3241 		focus view name	= %s\
3242 		lastMouseMoved	= %s\
3243 		session			= %s\
3244 		KeyMenuBar name	= %s\
3245 		DefaultButton	= %s\
3246 		# of shortcuts	= %ld",
3247 		Name(),
3248 		fTitle!=NULL? fTitle:"NULL",
3249 		_get_object_token_(this),
3250 		fInTransaction==true? "yes":"no",
3251 		fActive==true? "yes":"no",
3252 		fShowLevel,
3253 		fFlags,
3254 		send_port,
3255 		receive_port,
3256 		top_view!=NULL? top_view->Name():"NULL",
3257 		fFocus!=NULL? fFocus->Name():"NULL",
3258 		fLastMouseMovedView!=NULL? fLastMouseMovedView->Name():"NULL",
3259 		session!=NULL? "In place":"NULL",
3260 		fKeyMenuBar!=NULL? fKeyMenuBar->Name():"NULL",
3261 		fDefaultButton!=NULL? fDefaultButton->Name():"NULL",
3262 		accelList.CountItems());
3263 /*
3264 	for( int32 i=0; i<accelList.CountItems(); i++){
3265 		_BCmdKey	*key = (_BCmdKey*)accelList.ItemAt(i);
3266 		printf("\tShortCut %ld: char %s\n\t\t message: \n", i, (key->key > 127)?"ASCII":"UNICODE");
3267 		key->message->PrintToStream();
3268 	}
3269 */
3270 	printf("\
3271 		topViewToken	= %ld\
3272 		pluseEnabled	= %s\
3273 		isFilePanel		= %s\
3274 		MaskActivated	= %s\
3275 		pulseRate		= %lld\
3276 		waitingForMenu	= %s\
3277 		minimized		= %s\
3278 		Menu semaphore	= %ld\
3279 		maxZoomHeight	= %f\
3280 		maxZoomWidth	= %f\
3281 		minWindHeight	= %f\
3282 		minWindWidth	= %f\
3283 		maxWindHeight	= %f\
3284 		maxWindWidth	= %f\
3285 		frame			= ( %f, %f, %f, %f )\
3286 		look			= %d\
3287 		feel			= %d\
3288 		lastViewToken	= %ld\
3289 		pulseRUNNER		= %s\n",
3290 		fTopViewToken,
3291 		fPulseEnabled==true?"Yes":"No",
3292 		fIsFilePanel==true?"Yes":"No",
3293 		fMaskActivated==true?"Yes":"No",
3294 		fPulseRate,
3295 		fWaitingForMenu==true?"Yes":"No",
3296 		fMinimized==true?"Yes":"No",
3297 		fMenuSem,
3298 		fMaxZoomHeight,
3299 		fMaxZoomWidth,
3300 		fMinWindHeight,
3301 		fMinWindWidth,
3302 		fMaxWindHeight,
3303 		fMaxWindWidth,
3304 		fFrame.left, fFrame.top, fFrame.right, fFrame.bottom,
3305 		(int16)fLook,
3306 		(int16)fFeel,
3307 		fLastViewToken,
3308 		fPulseRunner!=NULL?"In place":"NULL");
3309 }
3310 
3311 /*
3312 TODO list:
3313 
3314 	*) take care of temporarely events mask!!!
3315 	*) what's with this flag B_ASYNCHRONOUS_CONTROLS ?
3316 	*) test arguments for SetWindowAligment
3317 	*) call hook functions: MenusBeginning, MenusEnded. Add menu activation code.
3318 
3319 	* add handlers for B_VIEW_MOVED/RESIZED in DispatchMessage()
3320 	* modify _UPDATE_ handler in DispatchMessage()
3321 */
3322 
3323 /*
3324  @log
3325 	*modified ReadRawFromPort() and ConvertToMessage() methods to use BSession class.
3326 	*modified/added B_VIEW_(MOVED/RESIZED) handlers in ConvertToMessage()/DispatchMessage()
3327 */
3328