Mozilla Cross-Reference mozilla1.8
mozilla/ widget/ src/ beos/ nsWindow.cpp
CVS Log
CVS Blame
CVS Graph
Diff file
Raw file
changes to
this file in
the last:
day
week
month
view using tree:
1 /* -*- Mode: C++; tab-width: 2; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4  *
5  * The contents of this file are subject to the Mozilla Public License Version
6  * 1.1 (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  * http://www.mozilla.org/MPL/
9  *
10  * Software distributed under the License is distributed on an "AS IS" basis,
11  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12  * for the specific language governing rights and limitations under the
13  * License.
14  *
15  * The Original Code is mozilla.org code.
16  *
17  * The Initial Developer of the Original Code is
18  * Netscape Communications Corporation.
19  * Portions created by the Initial Developer are Copyright (C) 1998
20  * the Initial Developer. All Rights Reserved.
21  *
22  * Contributor(s):
23  *   Paul Ashford <arougthopher@lizardland.net>
24  *   Sergei Dolgov <sergei_d@fi.tartu.ee>
25  *   Fredrik Holmqvist <thesuckiestemail@yahoo.se>
26  *
27  * Alternatively, the contents of this file may be used under the terms of
28  * either the GNU General Public License Version 2 or later (the "GPL"), or
29  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30  * in which case the provisions of the GPL or the LGPL are applicable instead
31  * of those above. If you wish to allow use of your version of this file only
32  * under the terms of either the GPL or the LGPL, and not to allow others to
33  * use your version of this file under the terms of the MPL, indicate your
34  * decision by deleting the provisions above and replace them with the notice
35  * and other provisions required by the GPL or the LGPL. If you do not delete
36  * the provisions above, a recipient may use your version of this file under
37  * the terms of any one of the MPL, the GPL or the LGPL.
38  *
39  * ***** END LICENSE BLOCK ***** */
40 
41 #include "nsDebug.h"
42 #include "nsWindow.h"
43 #include "nsIAppShell.h"
44 #include "nsIFontMetrics.h"
45 #include "nsFont.h"
46 #include "nsGUIEvent.h"
47 #include "nsWidgetsCID.h"
48 #include "nsIDragService.h"
49 #include "nsIDragSessionBeOS.h"
50 #include "nsIDeviceContext.h"
51 #include "nsRect.h"
52 #include "nsIRegion.h"
53 #include "nsTransform2D.h"
54 #include "nsGfxCIID.h"
55 #include "resource.h"
56 #include "prtime.h"
57 #include "nsReadableUtils.h"
58 #include "nsVoidArray.h"
59 
60 #include <Application.h>
61 #include <InterfaceDefs.h>
62 #include <Region.h>
63 #include <ScrollBar.h>
64 #include <app/Message.h>
65 #include <support/String.h>
66 #include <Screen.h>
67 
68 #include <nsBeOSCursors.h>
69 #if defined(BeIME)
70 #include <Input.h>
71 #include <InputServerMethod.h>
72 #include <String.h>
73 #endif
74 
75 #include "nsIRollupListener.h"
76 #include "nsIMenuRollup.h"
77 
78 // See comments in nsWindow.h as to why we override these calls from nsBaseWidget
79 NS_IMPL_THREADSAFE_ADDREF(nsWindow)
80 NS_IMPL_THREADSAFE_RELEASE(nsWindow)
81 
82 static NS_DEFINE_IID(kIWidgetIID,       NS_IWIDGET_IID);
83 static NS_DEFINE_IID(kRegionCID, NS_REGION_CID);
84 static NS_DEFINE_IID(kCDragServiceCID,  NS_DRAGSERVICE_CID);
85 //-------------------------------------------------------------------------
86 // Global Definitions
87 //-------------------------------------------------------------------------
88 
89 // Rollup Listener - static variable defintions
90 static nsIRollupListener * gRollupListener           = nsnull;
91 static nsIWidget         * gRollupWidget             = nsnull;
92 static PRBool              gRollupConsumeRollupEvent = PR_FALSE;
93 // Tracking last activated BWindow
94 static BWindow           * gLastActiveWindow = NULL;
95 
96 // BCursor objects can't be created until they are used.  Some mozilla utilities, 
97 // such as regxpcom, do not create a BApplication object, and therefor fail to run.,
98 // since a BCursor requires a vaild BApplication (see Bug#129964).  But, we still want
99 // to cache them for performance.  Currently, there are 17 cursors available;
100 static nsVoidArray		gCursorArray(21);
101 // Used in contrain position.  Specifies how much of a window must remain on screen
102 #define kWindowPositionSlop 20
103 // BeOS does not provide this information, so we must hard-code it
104 #define kWindowBorderWidth 5
105 #define kWindowTitleBarHeight 24
106 
107 
108 #if defined(BeIME)
109 #include "nsUTF8Utils.h"
110 static inline uint32 utf8_str_len(const char* ustring, int32 length) 
111 {
112 	CalculateUTF8Length cutf8;
113 	cutf8.write(ustring, length);
114 	return cutf8.Length();       
115 }
116 
117 nsIMEBeOS::nsIMEBeOS()
118 	: imeTarget(NULL)
119 	, imeState(NS_COMPOSITION_END), imeWidth(14)
120 {
121 }
122 /* placeholder for possible cleanup
123 nsIMEBeOS::~nsIMEBeOS()
124 {
125 }
126 */								
127 void nsIMEBeOS::RunIME(uint32 *args, nsWindow *target, BView *fView)
128 {
129 	BMessage msg;
130 	msg.Unflatten((const char*)args);
131 
132 	switch (msg.FindInt32("be:opcode")) 
133 	{
134 	case B_INPUT_METHOD_CHANGED:
135 		if (msg.HasString("be:string")) 
136 		{
137 			const char* src = msg.FindString("be:string");
138 			CopyUTF8toUTF16(src, imeText);
139  
140     		if (msg.FindBool("be:confirmed")) 
141     		{	
142     			if (imeState != NS_COMPOSITION_END)
143    					DispatchText(imeText, 0, NULL);
144    			}
145    			else 
146    			{
147    				nsTextRange txtRuns[2];
148    				PRUint32 txtCount = 2;
149 
150 	 	    	int32 select[2];
151  				select[0] = msg.FindInt32("be:selection", int32(0));
152 				select[1] = msg.FindInt32("be:selection", 1);
153 
154 	 			txtRuns[0].mStartOffset = (select[0] == select[1]) ? 0 : utf8_str_len(src, select[1]);
155 	 			txtRuns[0].mEndOffset	= imeText.Length();
156 				txtRuns[0].mRangeType	= NS_TEXTRANGE_CONVERTEDTEXT;
157 				if (select[0] == select[1])
158 					txtCount = 1;
159 				else 
160 				{
161 	 				txtRuns[1].mStartOffset = utf8_str_len(src, select[0]);
162 	 				txtRuns[1].mEndOffset	= utf8_str_len(src, select[1]);
163 	 				txtRuns[1].mRangeType	= NS_TEXTRANGE_SELECTEDCONVERTEDTEXT;
164 	 			}
165 	 			imeTarget = target;
166 				DispatchText(imeText, txtCount, txtRuns);
167 			}	
168 		}	
169 		break;
170 
171 	case B_INPUT_METHOD_LOCATION_REQUEST:
172 		if (fView && fView->LockLooper()) 
173 		{
174 			BPoint caret(imeCaret);
175 			DispatchIME(NS_COMPOSITION_QUERY);
176 			if (caret.x > imeCaret.x) 
177 				caret.x = imeCaret.x - imeWidth * imeText.Length();	/* back */
178 
179 			BMessage reply(B_INPUT_METHOD_EVENT);
180 			reply.AddInt32("be:opcode", B_INPUT_METHOD_LOCATION_REQUEST);
181 			for (int32 s= 0; imeText[s]; s++) 
182 			{ 
183 				reply.AddPoint("be:location_reply", fView->ConvertToScreen(caret));
184 				reply.AddFloat("be:height_reply", imeHeight);
185 				caret.x += imeWidth;
186 			}
187 			imeMessenger.SendMessage(&reply);
188 			fView->UnlockLooper();
189 		}
190 		break;
191 
192 	case B_INPUT_METHOD_STARTED:
193 		imeTarget = target;
194 		DispatchIME(NS_COMPOSITION_START);
195 		DispatchIME(NS_COMPOSITION_QUERY);
196 
197 		msg.FindMessenger("be:reply_to", &imeMessenger);
198 		break;
199 	
200 	case B_INPUT_METHOD_STOPPED:
201 		if (imeState != NS_COMPOSITION_END)
202 			DispatchIME(NS_COMPOSITION_END);
203 		imeText.Truncate();
204 		break;
205 	};
206 }
207 
208 void nsIMEBeOS::DispatchText(nsString &text, PRUint32 txtCount, nsTextRange* txtRuns)
209 {
210 	nsTextEvent textEvent(PR_TRUE,NS_TEXT_TEXT, imeTarget);
211 
212 	textEvent.time 		= 0;
213 	textEvent.isShift   = 
214 	textEvent.isControl =
215 	textEvent.isAlt 	= 
216 	textEvent.isMeta 	= PR_FALSE;
217   
218 	textEvent.refPoint.x	= 
219 	textEvent.refPoint.y	= 0;
220 
221 	textEvent.theText 	= text.get();
222 	textEvent.isChar	= PR_TRUE;
223 	textEvent.rangeCount= txtCount;
224 	textEvent.rangeArray= txtRuns;
225 
226 	DispatchWindowEvent(&textEvent);
227 }
228 
229 void nsIMEBeOS::DispatchCancelIME()
230 {
231 	if (imeText.Length() && imeState != NS_COMPOSITION_END) 
232 	{
233 		BMessage reply(B_INPUT_METHOD_EVENT);
234 		reply.AddInt32("be:opcode", B_INPUT_METHOD_STOPPED);
235 		imeMessenger.SendMessage(&reply);
236 
237 		DispatchText(imeText, 0, NULL);
238 		DispatchIME(NS_COMPOSITION_END);
239 
240 		imeText.Truncate();
241 	}
242 }
243 
244 void nsIMEBeOS::DispatchIME(PRUint32 what)
245 {
246 	nsCompositionEvent compEvent(PR_TRUE, what, imeTarget);
247 
248 	compEvent.refPoint.x =
249 	compEvent.refPoint.y = 0;
250 	compEvent.time 	 = 0;
251 
252 	DispatchWindowEvent(&compEvent);
253 	imeState = what;
254 
255 	if (what == NS_COMPOSITION_QUERY) 
256 	{
257 		imeCaret.Set(compEvent.theReply.mCursorPosition.x,
258 		           compEvent.theReply.mCursorPosition.y);
259 		imeHeight = compEvent.theReply.mCursorPosition.height+4;
260 	}
261 }
262 
263 PRBool nsIMEBeOS::DispatchWindowEvent(nsGUIEvent* event)
264 {
265 	nsEventStatus status;
266 	imeTarget->DispatchEvent(event, status);
267 	return PR_FALSE;
268 }
269 // There is only one IME instance per app, actually it may be set as global
270 nsIMEBeOS *nsIMEBeOS::GetIME()
271 {
272 	if(beosIME == 0)
273 		beosIME = new nsIMEBeOS();
274 	return beosIME;
275 }
276 nsIMEBeOS *nsIMEBeOS::beosIME = 0;
277 #endif
278 
279 //-------------------------------------------------------------------------
280 //
281 // nsWindow constructor
282 //
283 //-------------------------------------------------------------------------
284 nsWindow::nsWindow() : nsBaseWidget()
285 {
286 	rgb_color	back = ui_color(B_PANEL_BACKGROUND_COLOR);
287 
288 	mView               = 0;
289 	mPreferredWidth     = 0;
290 	mPreferredHeight    = 0;
291 	mFontMetrics        = nsnull;
292 	mIsVisible          = PR_FALSE;
293 	mEnabled            = PR_TRUE;
294 	mIsScrolling        = PR_FALSE;
295 	mParent             = nsnull;
296 	mWindowParent       = nsnull;
297 	mUpdateArea = do_CreateInstance(kRegionCID);
298 	mForeground = NS_RGBA(0xFF,0xFF,0xFF,0xFF);
299 	mBackground = mForeground;
300 	mBWindowFeel        = B_NORMAL_WINDOW_FEEL;
301 	if (mUpdateArea)
302 	{
303 		mUpdateArea->Init();
304 		mUpdateArea->SetTo(0, 0, 0, 0);
305 	}
306 }
307 
308 
309 //-------------------------------------------------------------------------
310 //
311 // nsWindow destructor
312 //
313 //-------------------------------------------------------------------------
314 nsWindow::~nsWindow()
315 {
316 	mIsDestroying = PR_TRUE;
317 
318 	// If the widget was released without calling Destroy() then the native
319 	// window still exists, and we need to destroy it
320 	if (NULL != mView) 
321 	{
322 		Destroy();
323 	}
324 	NS_IF_RELEASE(mFontMetrics);
325 }
326 
327 NS_METHOD nsWindow::BeginResizingChildren(void)
328 {
329 	// HideKids(PR_TRUE) may be used here
330 	NS_NOTYETIMPLEMENTED("BeginResizingChildren not yet implemented"); // to be implemented
331 	return NS_OK;
332 }
333 
334 NS_METHOD nsWindow::EndResizingChildren(void)
335 {
336 	// HideKids(PR_FALSE) may be used here
337 	NS_NOTYETIMPLEMENTED("EndResizingChildren not yet implemented"); // to be implemented
338 	return NS_OK;
339 }
340 
341 NS_METHOD nsWindow::WidgetToScreen(const nsRect& aOldRect, nsRect& aNewRect)
342 {
343 	BPoint	point;
344 	point.x = aOldRect.x;
345 	point.y = aOldRect.y;
346 	if (mView && mView->LockLooper())
347 	{
348 		mView->ConvertToScreen(&point);
349 		mView->UnlockLooper();
350 	}
351 	aNewRect.x = nscoord(point.x);
352 	aNewRect.y = nscoord(point.y);
353 	aNewRect.width = aOldRect.width;
354 	aNewRect.height = aOldRect.height;
355 	return NS_OK;
356 }
357 
358 NS_METHOD nsWindow::ScreenToWidget(const nsRect& aOldRect, nsRect& aNewRect)
359 {
360 	BPoint	point;
361 	point.x = aOldRect.x;
362 	point.y = aOldRect.y;
363 	if (mView && mView->LockLooper())
364 	{
365 		mView->ConvertFromScreen(&point);
366 		mView->UnlockLooper();
367 	}
368 	aNewRect.x = nscoord(point.x);
369 	aNewRect.y = nscoord(point.y);
370 	aNewRect.width = aOldRect.width;
371 	aNewRect.height = aOldRect.height;
372 	return NS_OK;
373 }
374 
375 
376 //-------------------------------------------------------------------------
377 //
378 // Convert nsEventStatus value to a windows boolean
379 //
380 //-------------------------------------------------------------------------
381 
382 PRBool nsWindow::ConvertStatus(nsEventStatus aStatus)
383 {
384 	switch(aStatus) 
385 	{
386 		case nsEventStatus_eIgnore:
387 			return PR_FALSE;
388 		case nsEventStatus_eConsumeNoDefault:
389 			return PR_TRUE;
390 		case nsEventStatus_eConsumeDoDefault:
391 			return PR_FALSE;
392 		default:
393 			NS_ASSERTION(0, "Illegal nsEventStatus enumeration value");
394 			break;
395 	}
396 	return PR_FALSE;
397 }
398 
399 //-------------------------------------------------------------------------
400 //
401 // Initialize an event to dispatch
402 //
403 //-------------------------------------------------------------------------
404 void nsWindow::InitEvent(nsGUIEvent& event, nsPoint* aPoint)
405 {
406 	NS_ADDREF(event.widget);
407 
408 	if (nsnull == aPoint) // use the point from the event
409 	{
410 		// get the message position in client coordinates and in twips
411 		event.point.x = 0;
412 		event.point.y = 0;
413 	}
414 	else // use the point override if provided
415 	{
416 		event.point.x = aPoint->x;
417 		event.point.y = aPoint->y;
418 	}
419 	event.time = PR_IntervalNow();
420 }
421 
422 //-------------------------------------------------------------------------
423 //
424 // Invokes callback and  ProcessEvent method on Event Listener object
425 //
426 //-------------------------------------------------------------------------
427 NS_IMETHODIMP nsWindow::DispatchEvent(nsGUIEvent* event, nsEventStatus & aStatus)
428 {
429 	aStatus = nsEventStatus_eIgnore;
430 
431 	nsCOMPtr <nsIWidget> mWidget = event->widget;
432 
433 	if (mEventCallback)
434 		aStatus = (*mEventCallback)(event);
435 
436 	if ((aStatus != nsEventStatus_eIgnore) && (mEventListener))
437 		aStatus = mEventListener->ProcessEvent(*event);
438 
439 	return NS_OK;
440 }
441 
442 //-------------------------------------------------------------------------
443 //
444 // Dispatch Window Event
445 //
446 //-------------------------------------------------------------------------
447 PRBool nsWindow::DispatchWindowEvent(nsGUIEvent* event)
448 {
449 	nsEventStatus status;
450 	DispatchEvent(event, status);
451 	return ConvertStatus(status);
452 }
453 
454 //-------------------------------------------------------------------------
455 //
456 // Dispatch standard event
457 //
458 //-------------------------------------------------------------------------
459 
460 PRBool nsWindow::DispatchStandardEvent(PRUint32 aMsg)
461 {
462 	nsGUIEvent event(PR_TRUE, aMsg, this);
463 	InitEvent(event);
464 
465 	PRBool result = DispatchWindowEvent(&event);
466 	NS_RELEASE(event.widget);
467 	return result;
468 }
469 
470 NS_IMETHODIMP nsWindow::PreCreateWidget(nsWidgetInitData *aInitData)
471 {
472 	if ( nsnull == aInitData)
473 		return NS_ERROR_FAILURE;
474 	
475 	SetWindowType(aInitData->mWindowType);
476 	SetBorderStyle(aInitData->mBorderStyle);
477 	return NS_OK;
478 }
479 
480 //-------------------------------------------------------------------------
481 //
482 // Utility method for implementing both Create(nsIWidget ...) and
483 // Create(nsNativeWidget...)
484 //-------------------------------------------------------------------------
485 nsresult nsWindow::StandardWindowCreate(nsIWidget *aParent,
486                                         const nsRect &aRect,
487                                         EVENT_CALLBACK aHandleEventFunction,
488                                         nsIDeviceContext *aContext,
489                                         nsIAppShell *aAppShell,
490                                         nsIToolkit *aToolkit,
491                                         nsWidgetInitData *aInitData,
492                                         nsNativeWidget aNativeParent)
493 {
494 
495 	//Do as little as possible for invisible windows, why are these needed?
496 	if (mWindowType == eWindowType_invisible)
497 		return NS_ERROR_FAILURE;
498 		
499 	nsIWidget *baseParent = 
500 	                        (aInitData->mWindowType == eWindowType_dialog ||
501 	                         aInitData->mWindowType == eWindowType_toplevel ||
502 	                         aInitData->mWindowType == eWindowType_invisible) ?
503 	                        nsnull : aParent;
504 
505 	NS_ASSERTION(aInitData->mWindowType != eWindowType_popup || 
506 		!aParent, "Popups should not be hooked into nsIWidget hierarchy");
507 	
508 	mIsTopWidgetWindow = (nsnull == baseParent);
509 	
510 	BaseCreate(baseParent, aRect, aHandleEventFunction, aContext,
511 	           aAppShell, aToolkit, aInitData);
512 
513 	mListenForResizes = aNativeParent ? PR_TRUE : aInitData->mListenForResizes;
514 		
515 	// Switch to the "main gui thread" if necessary... This method must
516 	// be executed on the "gui thread"...
517 	//
518 	nsToolkit* toolkit = (nsToolkit *)mToolkit;
519 	if (toolkit && !toolkit->IsGuiThread())
520 	{
521 		uint32 args[7];
522 		args[0] = (uint32)aParent;
523 		args[1] = (uint32)&aRect;
524 		args[2] = (uint32)aHandleEventFunction;
525 		args[3] = (uint32)aContext;
526 		args[4] = (uint32)aAppShell;
527 		args[5] = (uint32)aToolkit;
528 		args[6] = (uint32)aInitData;
529 
530 		if (nsnull != aParent)
531 		{
532 			// nsIWidget parent dispatch
533 			MethodInfo info(this, this, nsSwitchToUIThread::CREATE, 7, args);
534 			toolkit->CallMethod(&info);
535 		}
536 		else
537 		{
538 			// Native parent dispatch
539 			MethodInfo info(this, this, nsSwitchToUIThread::CREATE_NATIVE, 5, args);
540 			toolkit->CallMethod(&info);
541 		}
542 		return NS_OK;
543 	}
544 
545 	mParent = aParent;
546 	// Useful shortcut, wondering if we can use it also in GetParent() instead nsIWidget* type mParent.
547 	mWindowParent = (nsWindow *)aParent;
548 	SetBounds(aRect);
549 
550 	BRect winrect = BRect(aRect.x, aRect.y, aRect.x + aRect.width - 1, aRect.y + aRect.height - 1);
551 
552 	// Default mode for window, everything switched off.
553 	uint32 flags = B_NOT_RESIZABLE | B_NOT_MINIMIZABLE | B_NOT_ZOOMABLE | B_NOT_CLOSABLE | B_ASYNCHRONOUS_CONTROLS;
554 	window_look look = B_NO_BORDER_WINDOW_LOOK;
555 	switch (mWindowType)
556  	{
557 		//handle them as childviews until I know better. Shame on me.
558 		case eWindowType_java:
559 		case eWindowType_plugin:
560 			NS_NOTYETIMPLEMENTED("Java and plugin windows not yet implemented properly trying childview"); // to be implemented
561  			//These fall thru and behave just like child for the time being. They may require special implementation.
562 		case eWindowType_child:
563  		{
564  			//NS_NATIVE_GRAPHIC maybe?
565  			//Parent may be a BView if we embed.
566 			BView *parent= (BView *) (aParent ? aParent->GetNativeData(NS_NATIVE_WIDGET) :  aNativeParent);
567 			//There seems to be three of these on startup,
568 			//but I believe that these are because of bugs in 
569 			//other code as they existed before rewriting this
570 			//function.
571 			NS_PRECONDITION(parent, "Childviews without parents don't get added to anything.");
572 			// A childview that is never added to a parent is very strange.
573 			if (!parent)
574 				return NS_ERROR_FAILURE;
575 
576 			mView = new nsViewBeOS(this, winrect, "Child view", 0, B_WILL_DRAW);
577 #if defined(BeIME)
578 			mView->SetFlags(mView->Flags() | B_INPUT_METHOD_AWARE);
579 #endif	
580 			bool mustUnlock = parent->Parent() && parent->LockLooper();
581  			parent->AddChild(mView);
582 			if (mustUnlock) parent->UnlockLooper();
583 			DispatchStandardEvent(NS_CREATE);
584 			return NS_OK;
585  		}
586 
587 		case eWindowType_popup:
588 		case eWindowType_dialog:
589 		case eWindowType_toplevel:
590  		{
591 			//eBorderStyle_default is to ask the OS to handle it as it sees best.
592 			//eBorderStyle_all is same as top_level window default.
593 			if (eBorderStyle_default == mBorderStyle || eBorderStyle_all & mBorderStyle)
594  			{
595 				//(Firefox prefs doesn't go this way, so apparently it wants titlebar, zoom, resize and close.)
596 
597 				//Look and feel for others are set ok at init.
598 				if (eWindowType_toplevel==mWindowType)
599  				{
600 					look = B_TITLED_WINDOW_LOOK;
601 					flags = B_ASYNCHRONOUS_CONTROLS;
602  				}
603 			}
604 			else
605 			{
606 				if (eBorderStyle_border & mBorderStyle)
607 					look = B_MODAL_WINDOW_LOOK;
608  
609 				if (eBorderStyle_resizeh & mBorderStyle)
610  				{
611 					//Resize demands at least border
612 					look = B_MODAL_WINDOW_LOOK;
613 					flags &= !B_NOT_RESIZABLE;
614  				}
615 
616 				//We don't have titlebar menus, so treat like title as it demands titlebar.
617 				if (eBorderStyle_title & mBorderStyle || eBorderStyle_menu & mBorderStyle)
618 					look = B_TITLED_WINDOW_LOOK;
619 
620 				if (eBorderStyle_minimize & mBorderStyle)
621 					flags &= !B_NOT_MINIMIZABLE;
622 
623 				if (eBorderStyle_maximize & mBorderStyle)
624 					flags &= !B_NOT_ZOOMABLE;
625 
626 				if (eBorderStyle_close & mBorderStyle)
627 					flags &= !B_NOT_CLOSABLE;
628 			}
629 
630 			//popups always avoid focus and don't force the user to another workspace.
631 			if (eWindowType_popup==mWindowType)
632 				flags |= B_AVOID_FOCUS | B_NO_WORKSPACE_ACTIVATION;
633 
634 			nsWindowBeOS * w = new nsWindowBeOS(this, winrect, "", look, mBWindowFeel, flags);
635 			if (!w)
636 				return NS_ERROR_OUT_OF_MEMORY;
637 
638 			mView = new nsViewBeOS(this, w->Bounds(), "Toplevel view", B_FOLLOW_ALL, (mWindowType == eWindowType_popup ? B_WILL_DRAW: 0));
639  
640 			if (!mView)
641 				return NS_ERROR_OUT_OF_MEMORY;
642 	
643 			w->AddChild(mView);
644 			// I'm wondering if we can move part of that code to above
645 			if (eWindowType_dialog == mWindowType && mWindowParent) 
646 			{
647 				nsWindow *topparent = mWindowParent;
648 				while(topparent->mWindowParent)
649 					topparent = topparent->mWindowParent;
650 				// may be got via mView and mView->Window() of topparent explicitly	
651 				BWindow* subsetparent = (BWindow *)topparent->GetNativeData(NS_NATIVE_WINDOW);
652 				if (subsetparent)
653 				{
654 					mBWindowFeel = B_FLOATING_SUBSET_WINDOW_FEEL;
655 					w->SetFeel(mBWindowFeel);
656 					w->AddToSubset(subsetparent);
657 				}
658 			} 
659 			else if (eWindowType_popup == mWindowType  && aNativeParent)
660 			{
661 				// Due poor BeOS capability to control windows hierarchy/z-order we use this workaround
662 				// to show eWindowType_popup (e.g. drop-downs) over floating (subset) parent window.
663 				if (((BView *)aNativeParent)->Window() &&  ((BView *)aNativeParent)->Window()->IsFloating())
664 				{
665 					mBWindowFeel = B_FLOATING_ALL_WINDOW_FEEL;
666 					w->SetFeel(mBWindowFeel);
667 				}
668 			}
669 			
670 			DispatchStandardEvent(NS_CREATE);
671 			return NS_OK;
672 		}
673 		case eWindowType_invisible:
674 		case eWindowType_sheet:
675 			break;
676 		default:
677 		{
678 			printf("UNKNOWN or not handled windowtype!!!\n");
679 		}
680 	}
681 
682 	return NS_ERROR_FAILURE;
683 }
684 
685 //-------------------------------------------------------------------------
686 //
687 // Create the proper widget
688 //
689 //-------------------------------------------------------------------------
690 NS_METHOD nsWindow::Create(nsIWidget *aParent,
691                            const nsRect &aRect,
692                            EVENT_CALLBACK aHandleEventFunction,
693                            nsIDeviceContext *aContext,
694                            nsIAppShell *aAppShell,
695                            nsIToolkit *aToolkit,
696                            nsWidgetInitData *aInitData)
697 {
698 	return(StandardWindowCreate(aParent, aRect, aHandleEventFunction,
699 	                            aContext, aAppShell, aToolkit, aInitData,
700 	                            nsnull));
701 }
702 
703 
704 //-------------------------------------------------------------------------
705 //
706 // create with a native parent
707 //
708 //-------------------------------------------------------------------------
709 
710 NS_METHOD nsWindow::Create(nsNativeWidget aParent,
711                            const nsRect &aRect,
712                            EVENT_CALLBACK aHandleEventFunction,
713                            nsIDeviceContext *aContext,
714                            nsIAppShell *aAppShell,
715                            nsIToolkit *aToolkit,
716                            nsWidgetInitData *aInitData)
717 {
718 	return(StandardWindowCreate(nsnull, aRect, aHandleEventFunction,
719 	                            aContext, aAppShell, aToolkit, aInitData,
720 	                            aParent));
721 }
722 
723 //-------------------------------------------------------------------------
724 //
725 // Close this nsWindow
726 //
727 //-------------------------------------------------------------------------
728 NS_METHOD nsWindow::Destroy()
729 {
730 	// Switch to the "main gui thread" if necessary... This method must
731 	// be executed on the "gui thread"...
732 	nsToolkit* toolkit = (nsToolkit *)mToolkit;
733 	if (toolkit != nsnull && !toolkit->IsGuiThread())
734 	{
735 		MethodInfo info(this, this, nsSwitchToUIThread::DESTROY);
736 		toolkit->CallMethod(&info);
737 		return NS_ERROR_FAILURE;
738 	}
739 
740 	// Ok, now tell the nsBaseWidget class to clean up what it needs to
741 	if (!mIsDestroying)
742 	{
743 		nsBaseWidget::Destroy();
744 	}	
745 	//our windows can be subclassed by
746 	//others and these namless, faceless others
747 	//may not let us know about WM_DESTROY. so,
748 	//if OnDestroy() didn't get called, just call
749 	//it now.
750 	if (PR_FALSE == mOnDestroyCalled)
751 		OnDestroy();
752 	
753 	// Destroy the BView, if no mView, it is probably destroyed before
754 	// automatically with BWindow::Quit()
755 	if (mView)
756 	{
757 		// prevent the widget from causing additional events
758 		mEventCallback = nsnull;
759 	
760 		if (mView->LockLooper())
761 		{
762 			while(mView->ChildAt(0))
763 				mView->RemoveChild(mView->ChildAt(0));
764 			// destroy from inside
765 			BWindow	*w = mView->Window();
766 			// if no window, it was destroyed as result of B_QUIT_REQUESTED and 
767 			// took also all its children away
768 			if (w)
769 			{
770 				w->Sync();
771 				if (mView->Parent())
772 				{
773 					mView->Parent()->RemoveChild(mView);
774 					if (eWindowType_child != mWindowType)
775 						w->Quit();
776 					else
777 					w->Unlock();
778 				}
779 				else
780 				{
781 					w->RemoveChild(mView);
782 					w->Quit();
783 				}
784 			}
785 			else
786 				mView->RemoveSelf();
787 
788 			delete mView;
789 		}
790 
791 		// window is already gone
792 		mView = NULL;
793 	}
794 	mParent = nsnull;
795 	mWindowParent = nsnull;
796 	return NS_OK;}
797 
798 
799 //-------------------------------------------------------------------------
800 //
801 // Get this nsWindow parent
802 //
803 //-------------------------------------------------------------------------
804 nsIWidget* nsWindow::GetParent(void)
805 {
806 	//We cannot addref mParent directly
807 	nsIWidget	*widget = 0;
808 	if (mIsDestroying || mOnDestroyCalled)
809 		return nsnull;
810 	widget = (nsIWidget *)mParent;
811 	NS_IF_ADDREF(widget);
812 	return  widget;
813 }
814 
815 
816 //-------------------------------------------------------------------------
817 //
818 // Hide or show this component
819 //
820 //-------------------------------------------------------------------------
821 NS_METHOD nsWindow::Show(PRBool bState)
822 {
823 	if (!mEnabled)
824 		return NS_OK;
825 	if (mView && mView->LockLooper())
826 	{
827 		switch (mWindowType)
828 		{
829 			case eWindowType_popup:
830 			{
831 				if (PR_FALSE == bState)
832 				{
833 					// XXX BWindow::Hide() is needed ONLY for popups. No need to hide views for popups
834 					if (mView->Window() && !mView->Window()->IsHidden())
835 						mView->Window()->Hide();
836 				}
837 				else
838 				{
839 						if (mView->Window())
840 						{
841 							// bring menu to current workspace - Bug 310293
842 							mView->Window()->SetWorkspaces(B_CURRENT_WORKSPACE);
843 							if (mView->Window()->IsHidden())
844 								mView->Window()->Show();
845 						}
846 				}
847 				break;
848 			}
849 
850 			case eWindowType_child:
851 			{
852 				// XXX No BWindow deals for children
853 				if (PR_FALSE == bState)
854 				{
855 					if (!mView->IsHidden())
856 						mView->Hide();
857 				}
858 				else
859 				{
860 					if (mView->IsHidden())
861 						mView->Show();              
862 				}
863 				break;
864 			}
865 
866 			case eWindowType_dialog:
867 			case eWindowType_toplevel:
868 			{
869 				if (bState == PR_FALSE)
870 				{
871 					if (mView->Window() && !mView->Window()->IsHidden())
872 						mView->Window()->Hide();
873 				}
874 				else
875 				{
876 					if (mView->Window() && mView->Window()->IsHidden())
877 						mView->Window()->Show();
878 				}
879 				break;
880 			}
881 			
882 			default: // toplevel and dialog
883 			{
884 				NS_ASSERTION(false, "Unhandled Window Type in nsWindow::Show()!");
885 				break;
886 			}
887 		} //end switch	
888 
889 		mView->UnlockLooper();
890 		mIsVisible = bState;	
891 	}
892 	return NS_OK;
893 }
894 //-------------------------------------------------------------------------
895 // Set/unset mouse capture
896 //-------------------------------------------------------------------------
897 NS_METHOD nsWindow::CaptureMouse(PRBool aCapture)
898 {
899 	if (mView && mView->LockLooper())
900 	{
901 		if (PR_TRUE == aCapture)
902 			mView->SetEventMask(B_POINTER_EVENTS);
903 		else
904 			mView->SetEventMask(0);
905 		mView->UnlockLooper();
906 	}
907 	return NS_OK;
908 }
909 //-------------------------------------------------------------------------
910 // Capture Roolup Events
911 //-------------------------------------------------------------------------
912 NS_METHOD nsWindow::CaptureRollupEvents(nsIRollupListener * aListener, PRBool aDoCapture, PRBool aConsumeRollupEvent)
913 {
914 	if (!mEnabled)
915 		return NS_OK;
916 		
917 	if (aDoCapture) 
918 	{
919 		// we haven't bothered carrying a weak reference to gRollupWidget because
920 		// we believe lifespan is properly scoped. this next assertion helps 
921 		// assure that remains true.
922 		NS_ASSERTION(!gRollupWidget, "rollup widget reassigned before release");
923 		gRollupConsumeRollupEvent = aConsumeRollupEvent;
924 		NS_IF_RELEASE(gRollupListener);
925 		NS_IF_RELEASE(gRollupWidget);
926 		gRollupListener = aListener;
927 		NS_ADDREF(aListener);
928 		gRollupWidget = this;
929 		NS_ADDREF(this);
930 	} 
931 	else 
932 	{
933 		NS_IF_RELEASE(gRollupListener);
934 		NS_IF_RELEASE(gRollupWidget);
935 	}
936 
937 	return NS_OK;
938 }
939 
940 //-------------------------------------------------------------------------
941 // Check if event happened inside the given nsWindow
942 //-------------------------------------------------------------------------
943 PRBool nsWindow::EventIsInsideWindow(nsWindow* aWindow, nsPoint pos)
944 {
945 	BRect r;
946 	BWindow *window = (BWindow *)aWindow->GetNativeData(NS_NATIVE_WINDOW);
947 	if (window)
948 	{
949 		r = window->Frame();
950 	}
951 	else
952 	{
953 		// Bummer!
954 		return PR_FALSE;
955   	}
956 
957 	if (pos.x < r.left || pos.x > r.right ||
958 	        pos.y < r.top || pos.y > r.bottom) {
959 		return PR_FALSE;
960 	}
961 
962 	return PR_TRUE;
963 }
964 
965 //-------------------------------------------------------------------------
966 // DealWithPopups
967 //
968 // Handle events that may cause a popup (combobox, XPMenu, etc) to need to rollup.
969 //-------------------------------------------------------------------------
970 PRBool
971 nsWindow::DealWithPopups(uint32 methodID, nsPoint pos)
972 {
973 	if (gRollupListener && gRollupWidget) 
974 	{
975 		// Rollup if the event is outside the popup.
976 		PRBool rollup = !nsWindow::EventIsInsideWindow((nsWindow*)gRollupWidget, pos);
977 
978 		// If we're dealing with menus, we probably have submenus and we don't
979 		// want to rollup if the click is in a parent menu of the current submenu.
980 		if (rollup) 
981 		{
982 			nsCOMPtr<nsIMenuRollup> menuRollup ( do_QueryInterface(gRollupListener) );
983 			if ( menuRollup ) 
984 			{
985 				nsCOMPtr<nsISupportsArray> widgetChain;
986 				menuRollup->GetSubmenuWidgetChain ( getter_AddRefs(widgetChain) );
987 				if ( widgetChain ) 
988 				{
989 					PRUint32 count = 0;
990 					widgetChain->Count(&count);
991 					for ( PRUint32 i = 0; i < count; ++i ) 
992 					{
993 						nsCOMPtr<nsISupports> genericWidget;
994 						widgetChain->GetElementAt ( i, getter_AddRefs(genericWidget) );
995 						nsCOMPtr<nsIWidget> widget ( do_QueryInterface(genericWidget) );
996 						if ( widget ) 
997 						{
998 							nsIWidget* temp = widget.get();
999 							if ( nsWindow::EventIsInsideWindow((nsWindow*)temp, pos) ) 
1000 							{
1001 								rollup = PR_FALSE;
1002 								break;
1003 							}
1004 						}
1005 					} // foreach parent menu widget
1006 				} // if widgetChain
1007 			} // if rollup listener knows about menus
1008 		} // if rollup
1009 
1010 		if (rollup) 
1011 		{
1012 			gRollupListener->Rollup();
1013 
1014 			if (gRollupConsumeRollupEvent) 
1015 			{
1016 				return PR_TRUE;
1017 			}
1018 		}
1019 	} // if rollup listeners registered
1020 
1021 	return PR_FALSE;
1022 }
1023 
1024 
1025 //-------------------------------------------------------------------------
1026 //
1027 // IsVisible
1028 //
1029 // Return PR_TRUE if the whether the component is visible, PR_FALSE otherwise
1030 //-------------------------------------------------------------------------
1031 NS_METHOD nsWindow::IsVisible(PRBool & bState)
1032 {
1033 	bState = mIsVisible;
1034 	return NS_OK;
1035 }
1036 
1037 //-------------------------------------------------------------------------
1038 //
1039 // Sanity check potential move coordinates
1040 //
1041 //-------------------------------------------------------------------------
1042 NS_METHOD nsWindow::ConstrainPosition(PRBool aAllowSlop, PRInt32 *aX, PRInt32 *aY)
1043 {
1044 	if (mIsTopWidgetWindow && mView->Window()) 
1045 	{
1046 		BScreen screen;
1047 		// If no valid screen, just return
1048 		if (! screen.IsValid()) return NS_OK;
1049 		
1050 		BRect screen_rect = screen.Frame();
1051 		BRect win_bounds = mView->Window()->Frame();
1052 
1053 #ifdef DEBUG_CONSTRAIN_POSITION
1054 		printf("ConstrainPosition: allowSlop=%s, x=%d, y=%d\n\tScreen :", (aAllowSlop?"T":"F"),*aX,*aY);
1055 		screen_rect.PrintToStream();
1056 		printf("\tWindow: ");
1057 		win_bounds.PrintToStream();
1058 #endif
1059 		
1060 		if (aAllowSlop) 
1061 		{
1062 			if (*aX < kWindowPositionSlop - win_bounds.IntegerWidth() + kWindowBorderWidth)
1063 				*aX = kWindowPositionSlop - win_bounds.IntegerWidth() + kWindowBorderWidth;
1064 			else if (*aX > screen_rect.IntegerWidth() - kWindowPositionSlop - kWindowBorderWidth)
1065 				*aX = screen_rect.IntegerWidth() - kWindowPositionSlop - kWindowBorderWidth;
1066 				
1067 			if (*aY < kWindowPositionSlop - win_bounds.IntegerHeight() + kWindowTitleBarHeight)
1068 				*aY = kWindowPositionSlop - win_bounds.IntegerHeight() + kWindowTitleBarHeight;
1069 			else if (*aY > screen_rect.IntegerHeight() - kWindowPositionSlop - kWindowBorderWidth)
1070 				*aY = screen_rect.IntegerHeight() - kWindowPositionSlop - kWindowBorderWidth;
1071 				
1072 		} 
1073 		else 
1074 		{
1075 			
1076 			if (*aX < kWindowBorderWidth)
1077 				*aX = kWindowBorderWidth;
1078 			else if (*aX > screen_rect.IntegerWidth() - win_bounds.IntegerWidth() - kWindowBorderWidth)
1079 				*aX = screen_rect.IntegerWidth() - win_bounds.IntegerWidth() - kWindowBorderWidth;
1080 				
1081 			if (*aY < kWindowTitleBarHeight)
1082 				*aY = kWindowTitleBarHeight;
1083 			else if (*aY > screen_rect.IntegerHeight() - win_bounds.IntegerHeight() - kWindowBorderWidth)
1084 				*aY = screen_rect.IntegerHeight() - win_bounds.IntegerHeight() - kWindowBorderWidth;
1085 		}
1086 	}
1087 	return NS_OK;
1088 }
1089 
1090 void nsWindow::HideKids(PRBool state)	
1091 {
1092 	for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) 
1093 	{
1094 		nsWindow *childWidget = NS_STATIC_CAST(nsWindow*, kid);
1095 		nsRect kidrect = ((nsWindow *)kid)->mBounds;
1096 		//Don't bother about invisible
1097 		if (mBounds.Intersects(kidrect))
1098 		{	
1099 			childWidget->Show(!state);
1100 		}
1101 	}
1102 }
1103 
1104 //-------------------------------------------------------------------------
1105 //
1106 // Move this component
1107 //
1108 //-------------------------------------------------------------------------
1109 nsresult nsWindow::Move(PRInt32 aX, PRInt32 aY)
1110 {
1111 	// Only perform this check for non-popup windows, since the positioning can
1112 	// in fact change even when the x/y do not.  We always need to perform the
1113 	// check. See bug #97805 for details.
1114 	if (mWindowType != eWindowType_popup && (mBounds.x == aX) && (mBounds.y == aY))
1115 	{
1116 		// Nothing to do, since it is already positioned correctly.
1117 		return NS_OK;    
1118 	}
1119 
1120 
1121 	// Set cached value for lightweight and printing
1122 	mBounds.x = aX;
1123 	mBounds.y = aY;
1124 
1125 	// We may reset children visibility here, but it needs special care
1126 	// - see comment 18 in Bug 311651. More sofisticated code needed.
1127 
1128 	// until we lack separate window and widget, we "cannot" move BWindow without BView
1129 	if(mView && mView->LockLooper())
1130 	{
1131 		if(mView->Parent() || !mView->Window())
1132 			mView->MoveTo(aX, aY);
1133 		else
1134 			((nsWindowBeOS *)mView->Window())->MoveTo(aX, aY);
1135 			
1136 		mView->UnlockLooper();
1137 	}
1138 
1139 	OnMove(aX,aY);
1140 
1141 	return NS_OK;
1142 }
1143 
1144 
1145 
1146 //-------------------------------------------------------------------------
1147 //
1148 // Resize this component
1149 //
1150 //-------------------------------------------------------------------------
1151 NS_METHOD nsWindow::Resize(PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint)
1152 {
1153 
1154 	if (aWidth < 0 || aHeight < 0)
1155 		return NS_OK;
1156 
1157 	mBounds.width  = aWidth;
1158 	mBounds.height = aHeight;
1159 	
1160 	// until we lack separate window and widget, we "cannot" resize BWindow without BView
1161 	if (mView && mView->LockLooper())
1162 	{
1163 		if (mView->Parent() || !mView->Window())
1164 			mView->ResizeTo(aWidth - 1, aHeight - 1);
1165 		else
1166 			((nsWindowBeOS *)mView->Window())->ResizeTo(aWidth - 1, aHeight - 1);
1167 
1168 		mView->UnlockLooper();
1169 	}
1170 
1171 
1172 	OnResize(mBounds);
1173 	if (aRepaint)
1174 		Update();
1175 	return NS_OK;
1176 }
1177 
1178 //-------------------------------------------------------------------------
1179 //
1180 // Resize this component
1181 //
1182 //-------------------------------------------------------------------------
1183 NS_METHOD nsWindow::Resize(PRInt32 aX,
1184                            PRInt32 aY,
1185                            PRInt32 aWidth,
1186                            PRInt32 aHeight,
1187                            PRBool   aRepaint)
1188 {
1189 	Move(aX,aY);
1190 	Resize(aWidth,aHeight,aRepaint);
1191 	return NS_OK;
1192 }
1193 
1194 NS_METHOD nsWindow::SetModal(PRBool aModal)
1195 {
1196 	if(!(mView && mView->Window()))
1197 		return NS_ERROR_FAILURE;
1198 	if(aModal)
1199 	{
1200 		window_feel newfeel;
1201 		switch(mBWindowFeel)
1202 		{
1203 			case B_FLOATING_SUBSET_WINDOW_FEEL:
1204 				newfeel = B_MODAL_SUBSET_WINDOW_FEEL;
1205 				break;
1206  			case B_FLOATING_APP_WINDOW_FEEL:
1207 				newfeel = B_MODAL_APP_WINDOW_FEEL;
1208 				break;
1209  			case B_FLOATING_ALL_WINDOW_FEEL:
1210 				newfeel = B_MODAL_ALL_WINDOW_FEEL;
1211 				break;				
1212 			default:
1213 				return NS_OK;
1214 		}
1215 		mView->Window()->SetFeel(newfeel);
1216 	}
1217 	else
1218 	{
1219 		mView->Window()->SetFeel(mBWindowFeel);
1220 	}
1221 	return NS_OK;
1222 }
1223 //-------------------------------------------------------------------------
1224 //
1225 // Enable/disable this component
1226 //
1227 //-------------------------------------------------------------------------
1228 NS_METHOD nsWindow::Enable(PRBool aState)
1229 {
1230 	//TODO: Needs real corect implementation in future
1231 	mEnabled = aState;
1232 	return NS_OK;
1233 }
1234 
1235 
1236 NS_METHOD nsWindow::IsEnabled(PRBool *aState)
1237 {
1238 	NS_ENSURE_ARG_POINTER(aState);
1239 	// looks easy enough, but...
1240 	*aState = mEnabled;
1241 	return NS_OK;
1242 }
1243 
1244 //-------------------------------------------------------------------------
1245 //
1246 // Give the focus to this component
1247 //
1248 //-------------------------------------------------------------------------
1249 NS_METHOD nsWindow::SetFocus(PRBool aRaise)
1250 {
1251 	//
1252 	// Switch to the "main gui thread" if necessary... This method must
1253 	// be executed on the "gui thread"...
1254 	//
1255 	nsToolkit* toolkit = (nsToolkit *)mToolkit;
1256 	if (!toolkit->IsGuiThread()) 
1257 	{
1258 		uint32 args[1];
1259 		args[0] = (uint32)aRaise;
1260 		MethodInfo info(this, this, nsSwitchToUIThread::SET_FOCUS, 1, args);
1261 		toolkit->CallMethod(&info);
1262 		return NS_ERROR_FAILURE;
1263 	}
1264 	
1265 	// Don't set focus on disabled widgets or popups
1266 	if (!mEnabled || eWindowType_popup == mWindowType)
1267 		return NS_OK;
1268 		
1269 	if (mView && mView->LockLooper())
1270 	{
1271 		if (mView->Window() && 
1272 		    aRaise == PR_TRUE &&
1273 		    eWindowType_popup != mWindowType && 
1274 			  !mView->Window()->IsActive() && 
1275 			  gLastActiveWindow != mView->Window())
1276 			mView->Window()->Activate(true);
1277 			
1278 		mView->MakeFocus(true);
1279 		mView->UnlockLooper();
1280 		DispatchFocus(NS_GOTFOCUS);
1281 	}
1282 
1283 	return NS_OK;
1284 }
1285 
1286 //-------------------------------------------------------------------------
1287 //
1288 // Get this component size and position in screen coordinates
1289 //
1290 //-------------------------------------------------------------------------    
1291 NS_IMETHODIMP nsWindow::GetScreenBounds(nsRect &aRect)
1292 {
1293 	// A window's Frame() value is cached, so locking is not needed
1294 	if (mView && mView->Window()) 
1295 	{
1296 		BRect r = mView->Window()->Frame();
1297 		aRect.x = nscoord(r.left);
1298 		aRect.y = nscoord(r.top);
1299 		aRect.width  = r.IntegerWidth()+1;
1300 		aRect.height = r.IntegerHeight()+1;
1301 	} 
1302 	else 
1303 	{
1304 		aRect = mBounds;
1305 	}
1306 	return NS_OK;
1307 }  
1308 
1309 //-------------------------------------------------------------------------
1310 //
1311 // Set the background/foreground color
1312 //
1313 //-------------------------------------------------------------------------
1314 NS_METHOD nsWindow::SetBackgroundColor(const nscolor &aColor)
1315 {
1316 	nsBaseWidget::SetBackgroundColor(aColor);
1317 
1318 	// We set the background of toplevel windows so that resizing doesn't show thru
1319 	// to Desktop and resizing artifacts. Child windows has transparent background.
1320 	if (!mIsTopWidgetWindow)
1321 		return NS_OK;
1322 
1323 	if (mView && mView->LockLooper())
1324 	{
1325 		mView->SetViewColor(NS_GET_R(aColor), NS_GET_G(aColor), NS_GET_B(aColor), NS_GET_A(aColor));
1326 		mView->UnlockLooper();
1327 	}
1328 	return NS_OK;
1329 }
1330 
1331 //-------------------------------------------------------------------------
1332 //
1333 // Get this component font
1334 //
1335 //-------------------------------------------------------------------------
1336 nsIFontMetrics* nsWindow::GetFont(void)
1337 {
1338 	return mFontMetrics;
1339 }
1340 
1341 
1342 //-------------------------------------------------------------------------
1343 //
1344 // Set this component font
1345 //
1346 //-------------------------------------------------------------------------
1347 NS_METHOD nsWindow::SetFont(const nsFont &aFont)
1348 {
1349   // Cache Font for owner draw
1350 	NS_IF_RELEASE(mFontMetrics);
1351 	if (mContext)
1352 		mContext->GetMetricsFor(aFont, mFontMetrics);
1353 	return NS_OK;
1354 }
1355 
1356 
1357 //-------------------------------------------------------------------------
1358 //
1359 // Set this component cursor
1360 //
1361 //-------------------------------------------------------------------------
1362 
1363 NS_METHOD nsWindow::SetCursor(nsCursor aCursor)
1364 {
1365 	if (!mView)
1366 		return NS_ERROR_FAILURE;
1367 
1368 // mCursor isn't always right.  Scrollbars and others change it, too.
1369 // If we want this optimization we need a better way to do it.
1370 // See bug 403406 for more information.
1371 //	if (aCursor != mCursor) 
1372 //	{
1373 		BCursor const *newCursor = B_CURSOR_SYSTEM_DEFAULT;
1374 		
1375 		// Check to see if the array has been loaded, if not, do it.
1376 		if (gCursorArray.Count() == 0) 
1377 		{
1378 			gCursorArray.InsertElementAt((void*) new BCursor(cursorHyperlink),0);
1379 			gCursorArray.InsertElementAt((void*) new BCursor(cursorHorizontalDrag),1);
1380 			gCursorArray.InsertElementAt((void*) new BCursor(cursorVerticalDrag),2);
1381 			gCursorArray.InsertElementAt((void*) new BCursor(cursorUpperLeft),3);
1382 			gCursorArray.InsertElementAt((void*) new BCursor(cursorLowerRight),4);
1383 			gCursorArray.InsertElementAt((void*) new BCursor(cursorUpperRight),5);
1384 			gCursorArray.InsertElementAt((void*) new BCursor(cursorLowerLeft),6);
1385 			gCursorArray.InsertElementAt((void*) new BCursor(cursorCrosshair),7);
1386 			gCursorArray.InsertElementAt((void*) new BCursor(cursorHelp),8);
1387 			gCursorArray.InsertElementAt((void*) new BCursor(cursorGrab),9);
1388 			gCursorArray.InsertElementAt((void*) new BCursor(cursorGrabbing),10);
1389 			gCursorArray.InsertElementAt((void*) new BCursor(cursorCopy),11);
1390 			gCursorArray.InsertElementAt((void*) new BCursor(cursorAlias),12);
1391 			gCursorArray.InsertElementAt((void*) new BCursor(cursorWatch2),13);
1392 			gCursorArray.InsertElementAt((void*) new BCursor(cursorCell),14);
1393 			gCursorArray.InsertElementAt((void*) new BCursor(cursorZoomIn),15);
1394 			gCursorArray.InsertElementAt((void*) new BCursor(cursorZoomOut),16);
1395 			gCursorArray.InsertElementAt((void*) new BCursor(cursorLeft),17);
1396 			gCursorArray.InsertElementAt((void*) new BCursor(cursorRight),18);
1397 			gCursorArray.InsertElementAt((void*) new BCursor(cursorTop),19);
1398 			gCursorArray.InsertElementAt((void*) new BCursor(cursorBottom),20);
1399 		}
1400 
1401 		switch (aCursor) 
1402 		{
1403 			case eCursor_standard:
1404 			case eCursor_move:
1405 				newCursor = B_CURSOR_SYSTEM_DEFAULT;
1406 				break;
1407 	
1408 			case eCursor_select:
1409 				newCursor = B_CURSOR_I_BEAM;
1410 				break;
1411 	
1412 			case eCursor_hyperlink:
1413 				newCursor = (BCursor *)gCursorArray.SafeElementAt(0);
1414 				break;
1415 	
1416 			case eCursor_n_resize:
1417 				newCursor = (BCursor *)gCursorArray.SafeElementAt(19);
1418 				break;
1419 
1420 			case eCursor_s_resize:
1421 				newCursor = (BCursor *)gCursorArray.SafeElementAt(20);
1422 				break;
1423 	
1424 			case eCursor_w_resize:
1425 				newCursor = (BCursor *)gCursorArray.SafeElementAt(17);
1426 				break;
1427 
1428 			case eCursor_e_resize:
1429 				newCursor = (BCursor *)gCursorArray.SafeElementAt(18);
1430 				break;
1431 	
1432 			case eCursor_nw_resize:
1433 				newCursor = (BCursor *)gCursorArray.SafeElementAt(3);
1434 				break;
1435 	
1436 			case eCursor_se_resize:
1437 				newCursor = (BCursor *)gCursorArray.SafeElementAt(4);
1438 				break;
1439 	
1440 			case eCursor_ne_resize:
1441 				newCursor = (BCursor *)gCursorArray.SafeElementAt(5);
1442 				break;
1443 	
1444 			case eCursor_sw_resize:
1445 				newCursor = (BCursor *)gCursorArray.SafeElementAt(6);
1446 				break;
1447 	
1448 			case eCursor_crosshair:
1449 				newCursor = (BCursor *)gCursorArray.SafeElementAt(7);
1450 				break;
1451 	
1452 			case eCursor_help:
1453 				newCursor = (BCursor *)gCursorArray.SafeElementAt(8);
1454 				break;
1455 	
1456 			case eCursor_copy:
1457 				newCursor = (BCursor *)gCursorArray.SafeElementAt(11);
1458 				break;
1459 	
1460 			case eCursor_alias:
1461 				newCursor = (BCursor *)gCursorArray.SafeElementAt(12);
1462 				break;
1463 
1464 			case eCursor_context_menu:
1465 				// XXX: No suitable cursor, needs implementing
1466 				break;
1467 				
1468 			case eCursor_cell:
1469 				newCursor = (BCursor *)gCursorArray.SafeElementAt(14);
1470 				break;
1471 
1472 			case eCursor_grab:
1473 				newCursor = (BCursor *)gCursorArray.SafeElementAt(9);
1474 				break;
1475 	
1476 			case eCursor_grabbing:
1477 				newCursor = (BCursor *)gCursorArray.SafeElementAt(10);
1478 				break;
1479 	
1480 			case eCursor_wait:
1481 			case eCursor_spinning:
1482 				newCursor = (BCursor *)gCursorArray.SafeElementAt(13);
1483 				break;
1484 	
1485 			case eCursor_zoom_in:
1486 				newCursor = (BCursor *)gCursorArray.SafeElementAt(15);
1487 				break;
1488 
1489 			case eCursor_zoom_out:
1490 				newCursor = (BCursor *)gCursorArray.SafeElementAt(16);
1491 				break;
1492 
1493 			case eCursor_not_allowed:
1494 			case eCursor_no_drop:
1495 				// XXX: No suitable cursor, needs implementing
1496 				break;
1497 
1498 			case eCursor_col_resize:
1499 				// XXX not 100% appropriate perhaps
1500 				newCursor = (BCursor *)gCursorArray.SafeElementAt(1);
1501 				break;
1502 
1503 			case eCursor_row_resize:
1504 				// XXX not 100% appropriate perhaps
1505 				newCursor = (BCursor *)gCursorArray.SafeElementAt(2);
1506 				break;
1507 
1508 			case eCursor_vertical_text:
1509 				// XXX not 100% appropriate perhaps
1510 				newCursor = B_CURSOR_I_BEAM;
1511 				break;
1512 
1513 			case eCursor_all_scroll:
1514 				// XXX: No suitable cursor, needs implementing
1515 				break;
1516 
1517 			case eCursor_nesw_resize:
1518 				// XXX not 100% appropriate perhaps
1519 				newCursor = (BCursor *)gCursorArray.SafeElementAt(1);
1520 				break;
1521 
1522 			case eCursor_nwse_resize:
1523 				// XXX not 100% appropriate perhaps
1524 				newCursor = (BCursor *)gCursorArray.SafeElementAt(1);
1525 				break;
1526 
1527 			case eCursor_ns_resize:
1528 				newCursor = (BCursor *)gCursorArray.SafeElementAt(2);
1529 				break;
1530 
1531 			case eCursor_ew_resize:
1532 				newCursor = (BCursor *)gCursorArray.SafeElementAt(1);
1533 				break;
1534 
1535 			default:
1536 				NS_ASSERTION(0, "Invalid cursor type");
1537 				break;
1538 		}
1539 		NS_ASSERTION(newCursor != nsnull, "Cursor not stored in array properly!");
1540 		mCursor = aCursor;
1541 		be_app->SetCursor(newCursor, true);
1542 //	}
1543 	return NS_OK;
1544 }
1545 
1546 //-------------------------------------------------------------------------
1547 //
1548 // Invalidate this component visible area
1549 //
1550 //-------------------------------------------------------------------------
1551 NS_METHOD nsWindow::Invalidate(PRBool aIsSynchronous)
1552 {
1553 	nsresult rv = NS_ERROR_FAILURE;
1554 	// Asynchronous painting is performed with via nsViewBeOS::Draw() call and its message queue. 
1555 	// All update rects are collected in nsViewBeOS member  "paintregion".
1556 	// Flushing of paintregion happens in nsViewBeOS::GetPaintRegion(),
1557 	// cleanup  - in nsViewBeOS::Validate(), called in OnPaint().
1558 	BRegion reg;
1559 	reg.MakeEmpty();
1560 	if (mView && mView->LockLooper())
1561 	{
1562 		if (PR_TRUE == aIsSynchronous)
1563 		{
1564 			mView->paintregion.Include(mView->Bounds());
1565 			reg.Include(mView->Bounds());
1566 		}
1567 		else
1568 		{
1569 			mView->Draw(mView->Bounds());
1570 			rv = NS_OK;
1571 		}
1572 		mView->UnlockLooper();
1573 	}
1574 	// Instant repaint.
1575 	if (PR_TRUE == aIsSynchronous)
1576 		rv = OnPaint(&reg);
1577 	return rv;
1578 }
1579 
1580 //-------------------------------------------------------------------------
1581 //
1582 // Invalidate this component visible area
1583 //
1584 //-------------------------------------------------------------------------
1585 NS_METHOD nsWindow::Invalidate(const nsRect & aRect, PRBool aIsSynchronous)
1586 {
1587 	nsresult rv = NS_ERROR_FAILURE;
1588 	// Very temporary region for double accounting.
1589 	BRegion reg;
1590 	reg.MakeEmpty();
1591 	if (mView && mView->LockLooper()) 
1592 	{
1593 		BRect	r(aRect.x, 
1594 				aRect.y, 
1595 				aRect.x + aRect.width - 1, 
1596 				aRect.y + aRect.height - 1);
1597 		if (PR_TRUE == aIsSynchronous)
1598 		{
1599 			mView->paintregion.Include(r);
1600 			reg.Include(r);
1601 		}
1602 		else
1603 		{
1604 			// we use Draw() instead direct addition to paintregion,
1605 			// as it sets queue of notification messages for painting.
1606 			mView->Draw(r);
1607 			rv = NS_OK;
1608 		}
1609 		mView->UnlockLooper();
1610 	}
1611 	// Instant repaint - for given rect only. 
1612 	// Don't repaint area which isn't marked here for synchronous repaint explicitly.
1613 	// BRegion "reg" (equal to aRect) will be substracted from paintregion in OnPaint().
1614 	if (PR_TRUE == aIsSynchronous)
1615 		rv = OnPaint(&reg);
1616 	return rv;
1617 }
1618 
1619 //-------------------------------------------------------------------------
1620 //
1621 // Invalidate this component visible area
1622 //
1623 //-------------------------------------------------------------------------
1624 NS_IMETHODIMP nsWindow::InvalidateRegion(const nsIRegion *aRegion, PRBool aIsSynchronous)
1625 {
1626 	
1627 	nsRegionRectSet *rectSet = nsnull;
1628 	if (!aRegion)
1629 		return NS_ERROR_FAILURE;
1630 	nsresult rv = ((nsIRegion *)aRegion)->GetRects(&rectSet);
1631 	if (NS_FAILED(rv))
1632 		return rv;
1633 	BRegion reg;
1634 	reg.MakeEmpty();
1635 	if (mView && mView->LockLooper())
1636 	{
1637 		for (PRUint32 i=0; i< rectSet->mRectsLen; ++i)
1638 		{
1639 			BRect br(rectSet->mRects[i].x, rectSet->mRects[i].y,
1640 					rectSet->mRects[i].x + rectSet->mRects[i].width-1,
1641 					rectSet->mRects[i].y + rectSet->mRects[i].height -1);
1642 			if (PR_TRUE == aIsSynchronous)
1643 			{
1644 				mView->paintregion.Include(br);
1645 				reg.Include(br);
1646 			}
1647 			else
1648 			{
1649 				mView->Draw(br);
1650 				rv = NS_OK;
1651 			}
1652 		}
1653 		mView->UnlockLooper();
1654 	}
1655 	// Instant repaint - for given region only. 
1656 	// BRegion "reg"(equal to aRegion) will be substracted from paintregion in OnPaint().
1657 	if (PR_TRUE == aIsSynchronous)
1658 		rv = OnPaint(&reg);
1659 
1660 	return rv;
1661 }
1662 
1663 //-------------------------------------------------------------------------
1664 //
1665 // Force a synchronous repaint of the window
1666 //
1667 //-------------------------------------------------------------------------
1668 NS_IMETHODIMP nsWindow::Update()
1669 {
1670 	nsresult rv = NS_ERROR_FAILURE;
1671 	//Switching scrolling trigger off
1672 	mIsScrolling = PR_FALSE;
1673 	if (mWindowType == eWindowType_child)
1674 		return NS_OK;
1675 	// Getting whole paint cache filled in native and non-native Invalidate() calls.
1676 	// Sending it all to view manager via OnPaint()
1677 	BRegion reg;
1678 	reg.MakeEmpty();
1679 	if(mView && mView->LockLooper())
1680 	{
1681 		//Flushing native pending updates*/
1682 		if (mView->Window())
1683 			mView->Window()->UpdateIfNeeded();
1684 		bool nonempty = mView->GetPaintRegion(&reg);
1685 		mView->UnlockLooper();
1686 		if (nonempty)
1687 			rv = OnPaint(&reg);
1688 	}
1689 	return rv;
1690 }
1691 
1692 //-------------------------------------------------------------------------
1693 //
1694 // Return some native data according to aDataType
1695 //
1696 //-------------------------------------------------------------------------
1697 void* nsWindow::GetNativeData(PRUint32 aDataType)
1698 {
1699 	if (!mView)
1700 		return NULL;	
1701 	switch(aDataType) 
1702 	{
1703 		case NS_NATIVE_WINDOW:
1704 			return (void *)(mView->Window());
1705 		case NS_NATIVE_WIDGET:
1706 		case NS_NATIVE_PLUGIN_PORT:
1707 			return (void *)((nsViewBeOS *)mView);
1708 		case NS_NATIVE_GRAPHIC:
1709 			return (void *)((BView *)mView);
1710 		case NS_NATIVE_COLORMAP:
1711 		default:
1712 			break;
1713 	}
1714 	return NULL;
1715 }
1716 
1717 //-------------------------------------------------------------------------
1718 //
1719 // Set the colormap of the window
1720 //
1721 //-------------------------------------------------------------------------
1722 NS_METHOD nsWindow::SetColorMap(nsColorMap *aColorMap)
1723 {
1724 	NS_WARNING("nsWindow::SetColorMap - not implemented");
1725 	return NS_OK;
1726 }
1727 
1728 
1729 //-------------------------------------------------------------------------
1730 //
1731 // Scroll the bits of a window
1732 //
1733 //-------------------------------------------------------------------------
1734 NS_METHOD nsWindow::Scroll(PRInt32 aDx, PRInt32 aDy, nsRect *aClipRect)
1735 {
1736 	// Switching trigger on
1737 	mIsScrolling = PR_TRUE;
1738 	//Preventing main view invalidation loop-chain  when children are moving
1739 	//by by hiding children nsWidgets.
1740 	//Maybe this method must be used wider, in move and resize chains
1741 	// and implemented in BeginResizingChildren or in Reset*Visibility() methods
1742 	//Children will be unhidden in ::Update() when called by other than gkview::Scroll() method.
1743 	HideKids(PR_TRUE);
1744 	if (mView && mView->LockLooper())
1745 	{
1746 		// Kill any attempt to invalidate until scroll is finished
1747 		mView->SetVisible(false);
1748 	
1749 		BRect src;
1750 		BRect b = mView->Bounds();
1751 
1752 		if (aClipRect)
1753 		{
1754 			src.left = aClipRect->x;
1755 			src.top = aClipRect->y;
1756 			src.right = aClipRect->XMost() - 1;
1757 			src.bottom = aClipRect->YMost() - 1;
1758 		}
1759 		else
1760 		{
1761 			src = b;
1762 		}
1763 		// Restricting source by on-screen part of BView
1764 		if (mView->Window())
1765 		{
1766 			BRect screenframe = mView->ConvertFromScreen(BScreen(mView->Window()).Frame());
1767 			src = src & screenframe;
1768 			if (mView->Parent())
1769 			{
1770 				BRect parentframe = mView->ConvertFromParent(mView->Parent()->Frame());
1771 				src = src & parentframe;
1772 			}
1773 		}
1774 
1775 		BRegion	invalid;
1776 		invalid.Include(src);
1777 		// Next source clipping check, for same level siblings
1778 		if ( BView *v = mView->Parent() )
1779 		{
1780 			for (BView *child = v->ChildAt(0); child; child = child->NextSibling() )
1781 			{
1782 				BRect siblingframe = mView->ConvertFromParent(child->Frame());
1783 				if (child != mView && child->Parent() != mView)
1784 				{
1785 					invalid.Exclude(siblingframe);
1786 					mView->paintregion.Exclude(siblingframe);
1787 				}
1788 			}
1789 			src = invalid.Frame();
1790 		}
1791 
1792 		// make sure we only reference visible bits
1793 		// so we don't trigger a BView invalidate
1794 
1795 		if (src.left + aDx < 0)
1796 			src.left = -aDx;
1797 		if (src.right + aDx > b.right)
1798 			src.right = b.right - aDx;
1799 		if (src.top + aDy < 0)
1800 			src.top = -aDy;
1801 		if (src.bottom + aDy > b.bottom)
1802 			src.bottom = b.bottom - aDy;
1803 		
1804 		BRect dest = src.OffsetByCopy(aDx, aDy);
1805 		mView->ConstrainClippingRegion(&invalid);
1806 		// Moving visible content 
1807 		if (src.IsValid() && dest.IsValid())
1808 			mView->CopyBits(src, dest);
1809 
1810 		invalid.Exclude(dest);	
1811 		// Native paintregion needs shifting too, it is very important action
1812 		// (as app_server doesn't know about Mozilla viewmanager tricks) -
1813 		// it allows proper update after scroll for areas covered by other windows.
1814 		mView->paintregion.OffsetBy(aDx, aDy);
1815 		mView->ConstrainClippingRegion(&invalid);
1816 		// Time to silently move now invisible children
1817 		for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) 
1818 		{
1819 			nsWindow *childWidget = NS_STATIC_CAST(nsWindow*, kid);
1820 			// No need to Lock/UnlockLooper with GetBounds() and Move() methods
1821 			// using cached values and native MoveBy() instead
1822 			nsRect bounds = childWidget->mBounds;
1823 			bounds.x += aDx;
1824 			bounds.y += aDy;
1825 			childWidget->Move(bounds.x, bounds.y);
1826 			BView *child = ((BView *)kid->GetNativeData(NS_NATIVE_WIDGET));
1827 			if (child)
1828 			{
1829 				//There is native child
1830  				mView->paintregion.Exclude(child->Frame());
1831 			}
1832 		}			
1833 
1834  		// Painting calculated region now,
1835  		// letting Update() to paint remaining content of paintregion
1836  		OnPaint(&invalid);
1837  		HideKids(PR_FALSE);
1838  		// re-allow updates
1839  		mView->SetVisible(true);
1840  		mView->UnlockLooper();
1841 		
1842 	}
1843 	return NS_OK;
1844 }
1845 
1846 
1847 //-------------------------------------------------------------------------
1848 //
1849 // Every function that needs a thread switch goes through this function
1850 // by calling SendMessage (..WM_CALLMETHOD..) in nsToolkit::CallMethod.
1851 //
1852 //-------------------------------------------------------------------------
1853 bool nsWindow::CallMethod(MethodInfo *info)
1854 {
1855 	bool bRet = TRUE;
1856 
1857 	switch (info->methodId)
1858 	{
1859 	case nsSwitchToUIThread::CREATE:
1860 		NS_ASSERTION(info->nArgs == 7, "Wrong number of arguments to CallMethod");
1861 		Create((nsIWidget*)(info->args[0]),
1862 		       (nsRect&)*(nsRect*)(info->args[1]),
1863 		       (EVENT_CALLBACK)(info->args[2]),
1864 		       (nsIDeviceContext*)(info->args[3]),
1865 		       (nsIAppShell *)(info->args[4]),
1866 		       (nsIToolkit*)(info->args[5]),
1867 		       (nsWidgetInitData*)(info->args[6]));
1868 		break;
1869 
1870 	case nsSwitchToUIThread::CREATE_NATIVE:
1871 		NS_ASSERTION(info->nArgs == 7, "Wrong number of arguments to CallMethod");
1872 		Create((nsNativeWidget)(info->args[0]),
1873 		       (nsRect&)*(nsRect*)(info->args[1]),
1874 		       (EVENT_CALLBACK)(info->args[2]),
1875 		       (nsIDeviceContext*)(info->args[3]),
1876 		       (nsIAppShell *)(info->args[4]),
1877 		       (nsIToolkit*)(info->args[5]),
1878 		       (nsWidgetInitData*)(info->args[6]));
1879 		break;
1880 
1881 	case nsSwitchToUIThread::DESTROY:
1882 		NS_ASSERTION(info->nArgs == 0, "Wrong number of arguments to CallMethod");
1883 		Destroy();
1884 		break;
1885 
1886 	case nsSwitchToUIThread::CLOSEWINDOW :
1887 		{
1888 			NS_ASSERTION(info->nArgs == 0, "Wrong number of arguments to CallMethod");
1889 			if (eWindowType_popup != mWindowType && eWindowType_child != mWindowType)
1890 				DealWithPopups(nsSwitchToUIThread::CLOSEWINDOW,nsPoint(0,0));
1891 				for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) 
1892 				{
1893 					nsWindow *childWidget = NS_STATIC_CAST(nsWindow*, kid);
1894 					BWindow* kidwindow = (BWindow *)kid->GetNativeData(NS_NATIVE_WINDOW);
1895 					if (kidwindow)
1896 					{
1897 						// PostMessage() is unsafe, so using BMessenger
1898 						BMessenger bm(kidwindow);
1899 						bm.SendMessage(B_QUIT_REQUESTED);
1900 					}
1901 				}
1902 			DispatchStandardEvent(NS_DESTROY);
1903 		}
1904 		break;
1905 
1906 	case nsSwitchToUIThread::SET_FOCUS:
1907 		NS_ASSERTION(info->nArgs == 1, "Wrong number of arguments to CallMethod");
1908 		if (!mEnabled)
1909 			return false;
1910 		SetFocus(((PRBool *)info->args)[0]);
1911 		break;
1912 
1913 #ifdef DEBUG_FOCUS
1914 	case nsSwitchToUIThread::GOT_FOCUS:
1915 		NS_ASSERTION(info->nArgs == 1, "Wrong number of arguments to CallMethod");
1916 		if (!mEnabled)
1917 			return false;
1918 		if ((uint32)info->args[0] != (uint32)mView)
1919 			printf("Wrong view to get focus\n");*/
1920 		break;
1921 #endif
1922 	case nsSwitchToUIThread::KILL_FOCUS:
1923 		NS_ASSERTION(info->nArgs == 1, "Wrong number of arguments to CallMethod");
1924 		if ((uint32)info->args[0] == (uint32)mView)
1925 			DispatchFocus(NS_LOSTFOCUS);
1926 #ifdef DEBUG_FOCUS
1927 		else
1928 			printf("Wrong view to de-focus\n");
1929 #endif
1930 #if defined(BeIME)
1931 		nsIMEBeOS::GetIME()->DispatchCancelIME();
1932 		if (mView && mView->LockLooper())
1933  		{
1934  			mView->SetFlags(mView->Flags() & ~B_NAVIGABLE);
1935  			mView->UnlockLooper();
1936  		}
1937 #endif
1938 		break;
1939 
1940 	case nsSwitchToUIThread::BTNCLICK :
1941 		{
1942 			NS_ASSERTION(info->nArgs == 5, "Wrong number of arguments to CallMethod");
1943 			if (!mEnabled)
1944 				return false;
1945 			// close popup when clicked outside of the popup window
1946 			uint32 eventID = ((int32 *)info->args)[0];
1947 			PRBool rollup = PR_FALSE;
1948 
1949 			if ((eventID == NS_MOUSE_LEFT_BUTTON_DOWN ||
1950 			        eventID == NS_MOUSE_RIGHT_BUTTON_DOWN ||
1951 			        eventID == NS_MOUSE_MIDDLE_BUTTON_DOWN) &&
1952 			        mView && mView->LockLooper())
1953 			{
1954 				BPoint p(((int32 *)info->args)[1], ((int32 *)info->args)[2]);
1955 				mView->ConvertToScreen(&p);
1956 				rollup = DealWithPopups(nsSwitchToUIThread::ONMOUSE, nsPoint(p.x, p.y));
1957 				mView->UnlockLooper();
1958 			}
1959 			// Drop click event - bug 314330
1960 			if (rollup)
1961 				return false;
1962 			DispatchMouseEvent(((int32 *)info->args)[0],
1963 			                   nsPoint(((int32 *)info->args)[1], ((int32 *)info->args)[2]),
1964 			                   ((int32 *)info->args)[3],
1965 			                   ((int32 *)info->args)[4]);
1966 
1967 			if (((int32 *)info->args)[0] == NS_MOUSE_RIGHT_BUTTON_DOWN)
1968 			{
1969 				DispatchMouseEvent (NS_CONTEXTMENU,
1970 				                    nsPoint(((int32 *)info->args)[1], ((int32 *)info->args)[2]),
1971 				                    ((int32 *)info->args)[3],
1972 				                    ((int32 *)info->args)[4]);
1973 			}
1974 		}
1975 		break;
1976 
1977 	case nsSwitchToUIThread::ONWHEEL :
1978 		{
1979 			NS_ASSERTION(info->nArgs == 1, "Wrong number of arguments to CallMethod");
1980 			// avoid mistargeting
1981 			if ((uint32)info->args[0] != (uint32)mView)
1982 				return false;
1983 			BPoint cursor(0,0);
1984 			uint32 buttons;
1985 			BPoint delta;
1986 			if (mView && mView->LockLooper())
1987 			{
1988 				mView->GetMouse(&cursor, &buttons, false);
1989 				delta = mView->GetWheel();
1990 				mView->UnlockLooper();
1991 			}
1992 			else
1993 				return false;
1994 			// BeOS TwoWheel input-filter is bit buggy atm, generating sometimes X-wheel with no reason,
1995 			// so we're setting priority for Y-wheel.
1996 			// Also hardcoding here _system_ scroll-step value to 3 lines.
1997 			if (nscoord(delta.y) != 0)
1998 			{
1999 				OnWheel(nsMouseScrollEvent::kIsVertical, buttons, cursor, nscoord(delta.y)*3);
2000 			}
2001 			else if(nscoord(delta.x) != 0)
2002 				OnWheel(nsMouseScrollEvent::kIsHorizontal, buttons, cursor, nscoord(delta.x)*3);
2003 		}
2004 		break;
2005 
2006 	case nsSwitchToUIThread::ONKEY :
2007 		NS_ASSERTION(info->nArgs == 6, "Wrong number of arguments to CallMethod");
2008 		if (((int32 *)info->args)[0] == NS_KEY_DOWN)
2009 		{
2010 			OnKeyDown(((int32 *)info->args)[0],
2011 			          (const char *)(&((uint32 *)info->args)[1]), ((int32 *)info->args)[2],
2012 			          ((uint32 *)info->args)[3], ((uint32 *)info->args)[4], ((int32 *)info->args)[5]);
2013 		}
2014 		else
2015 		{
2016 			if (((int32 *)info->args)[0] == NS_KEY_UP)
2017 			{
2018 				OnKeyUp(((int32 *)info->args)[0],
2019 				        (const char *)(&((uint32 *)info->args)[1]), ((int32 *)info->args)[2],
2020 				        ((uint32 *)info->args)[3], ((uint32 *)info->args)[4], ((int32 *)info->args)[5]);
2021 			}
2022 		}
2023 		break;
2024 
2025 	case nsSwitchToUIThread::ONPAINT :
2026 		NS_ASSERTION(info->nArgs == 1, "Wrong number of arguments to CallMethod");
2027 		{
2028 			if ((uint32)mView != ((uint32 *)info->args)[0])
2029 				return false;
2030 			BRegion reg;
2031 			reg.MakeEmpty();
2032 			if(mView && mView->LockLooper())
2033 			{
2034 				bool nonempty = mView->GetPaintRegion(&reg);
2035 				mView->UnlockLooper();
2036 				if (nonempty)
2037 					OnPaint(&reg);
2038 			}
2039 		}
2040 		break;
2041 
2042 	case nsSwitchToUIThread::ONRESIZE :
2043 		{
2044 			NS_ASSERTION(info->nArgs == 0, "Wrong number of arguments to CallMethod");
2045 			if (eWindowType_popup != mWindowType && eWindowType_child != mWindowType)
2046 				DealWithPopups(nsSwitchToUIThread::ONRESIZE,nsPoint(0,0));
2047 			// This should be called only from BWindow::FrameResized()
2048 			if (!mIsTopWidgetWindow  || !mView  || !mView->Window())
2049 				return false;
2050 			
2051 			nsRect r(mBounds);
2052 			if (mView->LockLooper())
2053 			{
2054 				BRect br = mView->Frame();
2055 				r.x = nscoord(br.left);
2056 				r.y = nscoord(br.top);
2057 				r.width  = br.IntegerWidth() + 1;
2058 				r.height = br.IntegerHeight() + 1;
2059 				((nsWindowBeOS *)mView->Window())->fJustGotBounds = true;
2060 				mView->UnlockLooper();
2061 			}
2062 
2063 			OnResize(r);
2064 		}
2065 		break;
2066 
2067 	case nsSwitchToUIThread::ONMOUSE :
2068 		{
2069 		NS_ASSERTION(info->nArgs == 1, "Wrong number of arguments to CallMethod");
2070 			if (!mEnabled)
2071 				return false;
2072 			BPoint cursor(0,0);
2073 			uint32 buttons;
2074 			
2075 			if(mView && mView->LockLooper())
2076 			{
2077 				mView->GetMouse(&cursor, &buttons, true);
2078 				mView->UnlockLooper();
2079 			}
2080 
2081 			DispatchMouseEvent(((int32 *)info->args)[0],
2082 			                   nsPoint(int32(cursor.x), int32(cursor.y)),
2083 			                   0,
2084 		    	               modifiers());
2085 		}
2086 		break;
2087 
2088 	case nsSwitchToUIThread::ONDROP :
2089 		{
2090 			NS_ASSERTION(info->nArgs == 4, "Wrong number of arguments to CallMethod");
2091 
2092 			nsMouseEvent event(PR_TRUE, (int32)  info->args[0], this, nsMouseEvent::eReal);
2093 			nsPoint point(((int32 *)info->args)[1], ((int32 *)info->args)[2]);
2094 			InitEvent (event, &point);
2095 			uint32 mod = (uint32) info->args[3];
2096 			event.isShift   = mod & B_SHIFT_KEY;
2097 			event.isControl = mod & B_CONTROL_KEY;
2098 			event.isAlt     = mod & B_COMMAND_KEY;
2099 			event.isMeta     = mod & B_OPTION_KEY;
2100 
2101 			// Setting drag action, must be done before event dispatch
2102 			nsCOMPtr<nsIDragService> dragService = do_GetService(kCDragServiceCID);
2103 			if (dragService)
2104 			{
2105 				nsCOMPtr<nsIDragSession> dragSession;
2106 				dragService->GetCurrentSession(getter_AddRefs(dragSession));
2107 				if (dragSession)
2108 				{
2109 					// Original action mask stored in dragsession.
2110 					// For native events such mask must be set in nsDragServiceBeOS::UpdateDragMessageIfNeeded()
2111 	
2112 					PRUint32 action_mask = 0;
2113 					dragSession->GetDragAction(&action_mask);
2114 					PRUint32 action = nsIDragService::DRAGDROP_ACTION_MOVE;
2115 					if (mod & B_OPTION_KEY)
2116 					{
2117 						if (mod & B_COMMAND_KEY)
2118 							action = nsIDragService::DRAGDROP_ACTION_LINK & action_mask;
2119 						else
2120 							action = nsIDragService::DRAGDROP_ACTION_COPY & action_mask;
2121 					}
2122 					dragSession->SetDragAction(action);
2123 				}
2124 			}
2125 
2126 			DispatchWindowEvent(&event);
2127 			NS_RELEASE(event.widget);
2128 
2129 			if (dragService)
2130 				dragService->EndDragSession();
2131 
2132 		}
2133 		break;
2134 
2135 	case nsSwitchToUIThread::ONACTIVATE:
2136 		NS_ASSERTION(info->nArgs == 2, "Wrong number of arguments to CallMethod");
2137 		if (!mEnabled || eWindowType_popup == mWindowType || 0 == mView->Window())
2138 			return false;
2139 		if ((BWindow *)info->args[1] != mView->Window())
2140 			return false;
2141 		if (mEventCallback || eWindowType_child == mWindowType )
2142 		{
2143 			bool active = (bool)info->args[0];
2144 			if (!active) 
2145 			{
2146 				if (eWindowType_dialog == mWindowType || 
2147 				    eWindowType_toplevel == mWindowType)
2148 					DealWithPopups(nsSwitchToUIThread::ONACTIVATE,nsPoint(0,0));
2149 				//Testing if BWindow is really deactivated.
2150 				if (!mView->Window()->IsActive())
2151 				{
2152 					// BeOS is poor in windows hierarchy and variations support. In lot of aspects.
2153 					// Here is workaround for flacky Activate() handling for B_FLOATING windows.
2154 					// We should force parent (de)activation to allow main window to regain control after closing floating dialog.
2155 					if (mWindowParent &&  mView->Window()->IsFloating())
2156 						mWindowParent->DispatchFocus(NS_ACTIVATE);
2157 
2158 					DispatchFocus(NS_DEACTIVATE);
2159 #if defined(BeIME)
2160 					nsIMEBeOS::GetIME()->DispatchCancelIME();
2161 #endif
2162 				}
2163 			} 
2164 			else 
2165 			{
2166 
2167 				if (mView->Window()->IsActive())
2168 				{
2169 					// See comment above.
2170 					if (mWindowParent &&  mView->Window()->IsFloating())
2171 						mWindowParent->DispatchFocus(NS_DEACTIVATE);
2172 					
2173 					DispatchFocus(NS_ACTIVATE);
2174 					if (mView && mView->Window())
2175 						gLastActiveWindow = mView->Window();
2176 				}
2177 			}
2178 		}
2179 		break;
2180 
2181 	case nsSwitchToUIThread::ONMOVE:
2182 		{
2183 			NS_ASSERTION(info->nArgs == 0, "Wrong number of arguments to CallMethod");
2184 			nsRect r;
2185 			// We use this only for tracking whole window moves
2186 			GetScreenBounds(r);		
2187 			if (eWindowType_popup != mWindowType && eWindowType_child != mWindowType)
2188 				DealWithPopups(nsSwitchToUIThread::ONMOVE,nsPoint(0,0));
2189 			OnMove(r.x, r.y);
2190 		}
2191 		break;
2192 		
2193 	case nsSwitchToUIThread::ONWORKSPACE:
2194 		{
2195 			NS_ASSERTION(info->nArgs == 2, "Wrong number of arguments to CallMethod");
2196 			if (eWindowType_popup != mWindowType && eWindowType_child != mWindowType)
2197 				DealWithPopups(nsSwitchToUIThread::ONWORKSPACE,nsPoint(0,0));
2198 		}
2199 		break;
2200 
2201 #if defined(BeIME)
2202  	case nsSwitchToUIThread::ONIME:
2203  		//No assertion used, as number of arguments varies here
2204  		if (mView && mView->LockLooper())
2205  		{
2206  			mView->SetFlags(mView->Flags() | B_NAVIGABLE);
2207  			mView->UnlockLooper();
2208  		}
2209  		nsIMEBeOS::GetIME()->RunIME(info->args, this, mView);
2210  		break;
2211 #endif
2212 		default:
2213 			bRet = FALSE;
2214 			break;
2215 		
2216 	}
2217 
2218 	return bRet;
2219 }
2220 
2221 //-------------------------------------------------------------------------
2222 //
2223 // Key code translation related data
2224 //
2225 //-------------------------------------------------------------------------
2226 
2227 struct nsKeyConverter {
2228 	int vkCode; // Platform independent key code
2229 	char bekeycode; // BeOS key code
2230 };
2231 
2232 //
2233 // Netscape keycodes are defined in widget/public/nsGUIEvent.h
2234 // BeOS keycodes can be viewd at
2235 // http://www.be.com/documentation/be_book/Keyboard/KeyboardKeyCodes.html
2236 //
2237 
2238 struct nsKeyConverter nsKeycodesBeOS[] = {
2239 	        //  { NS_VK_CANCEL,     GDK_Cancel },
2240 	        { NS_VK_BACK,       0x1e },
2241 	        { NS_VK_TAB,        0x26 },
2242 	        //  { NS_VK_TAB,        GDK_ISO_Left_Tab },
2243 	        //  { NS_VK_CLEAR,      GDK_Clear },
2244 	        { NS_VK_RETURN,     0x47 },
2245 	        { NS_VK_SHIFT,      0x4b },
2246 	        { NS_VK_SHIFT,      0x56 },
2247 	        { NS_VK_CONTROL,    0x5c },
2248 	        { NS_VK_CONTROL,    0x60 },
2249 	        { NS_VK_ALT,        0x5d },
2250 	        { NS_VK_ALT,        0x5f },
2251 	        { NS_VK_PAUSE,      0x22 },
2252 	        { NS_VK_CAPS_LOCK,  0x3b },
2253 	        { NS_VK_ESCAPE,     0x1 },
2254 	        { NS_VK_SPACE,      0x5e },
2255 	        { NS_VK_PAGE_UP,    0x21 },
2256 	        { NS_VK_PAGE_DOWN,  0x36 },
2257 	        { NS_VK_END,        0x35 },
2258 	        { NS_VK_HOME,       0x20 },
2259 	        { NS_VK_LEFT,       0x61 },
2260 	        { NS_VK_UP,         0x57 },
2261 	        { NS_VK_RIGHT,      0x63 },
2262 	        { NS_VK_DOWN,       0x62 },
2263 	        { NS_VK_PRINTSCREEN, 0xe },
2264 	        { NS_VK_INSERT,     0x1f },
2265 	        { NS_VK_DELETE,     0x34 },
2266 
2267 	        // The "Windows Key"
2268 	        { NS_VK_META,       0x66 },
2269 	        { NS_VK_META,       0x67 },
2270 
2271 	        // keypad keys (constant keys)
2272 	        { NS_VK_MULTIPLY,   0x24 },
2273 	        { NS_VK_ADD,        0x3a },
2274 	        //  { NS_VK_SEPARATOR,   }, ???
2275 	        { NS_VK_SUBTRACT,   0x25 },
2276 	        { NS_VK_DIVIDE,     0x23 },
2277 	        { NS_VK_RETURN,     0x5b },
2278 
2279 	        { NS_VK_COMMA,      0x53 },
2280 	        { NS_VK_PERIOD,     0x54 },
2281 	        { NS_VK_SLASH,      0x55 },
2282 	        { NS_VK_BACK_SLASH, 0x33 },
2283 	        { NS_VK_BACK_SLASH, 0x6a }, // got this code on japanese keyboard
2284 	        { NS_VK_BACK_SLASH, 0x6b }, // got this code on japanese keyboard
2285 	        { NS_VK_BACK_QUOTE, 0x11 },
2286 	        { NS_VK_OPEN_BRACKET, 0x31 },
2287 	        { NS_VK_CLOSE_BRACKET, 0x32 },
2288 	        { NS_VK_SEMICOLON, 0x45 },
2289 	        { NS_VK_QUOTE, 0x46 },
2290 
2291 	        // NS doesn't have dash or equals distinct from the numeric keypad ones,
2292 	        // so we'll use those for now.  See bug 17008:
2293 	        { NS_VK_SUBTRACT, 0x1c },
2294 	        { NS_VK_EQUALS, 0x1d },
2295 
2296 	        { NS_VK_F1, B_F1_KEY },
2297 	        { NS_VK_F2, B_F2_KEY },
2298 	        { NS_VK_F3, B_F3_KEY },
2299 	        { NS_VK_F4, B_F4_KEY },
2300 	        { NS_VK_F5, B_F5_KEY },
2301 	        { NS_VK_F6, B_F6_KEY },
2302 	        { NS_VK_F7, B_F7_KEY },
2303 	        { NS_VK_F8, B_F8_KEY },
2304 	        { NS_VK_F9, B_F9_KEY },
2305 	        { NS_VK_F10, B_F10_KEY },
2306 	        { NS_VK_F11, B_F11_KEY },
2307 	        { NS_VK_F12, B_F12_KEY },
2308 
2309 	        { NS_VK_1, 0x12 },
2310 	        { NS_VK_2, 0x13 },
2311 	        { NS_VK_3, 0x14 },
2312 	        { NS_VK_4, 0x15 },
2313 	        { NS_VK_5, 0x16 },
2314 	        { NS_VK_6, 0x17 },
2315 	        { NS_VK_7, 0x18 },
2316 	        { NS_VK_8, 0x19 },
2317 	        { NS_VK_9, 0x1a },
2318 	        { NS_VK_0, 0x1b },
2319 
2320 	        { NS_VK_A, 0x3c },
2321 	        { NS_VK_B, 0x50 },
2322 	        { NS_VK_C, 0x4e },
2323 	        { NS_VK_D, 0x3e },
2324 	        { NS_VK_E, 0x29 },
2325 	        { NS_VK_F, 0x3f },
2326 	        { NS_VK_G, 0x40 },
2327 	        { NS_VK_H, 0x41 },
2328 	        { NS_VK_I, 0x2e },
2329 	        { NS_VK_J, 0x42 },
2330 	        { NS_VK_K, 0x43 },
2331 	        { NS_VK_L, 0x44 },
2332 	        { NS_VK_M, 0x52 },
2333 	        { NS_VK_N, 0x51 },
2334 	        { NS_VK_O, 0x2f },
2335 	        { NS_VK_P, 0x30 },
2336 	        { NS_VK_Q, 0x27 },
2337 	        { NS_VK_R, 0x2a },
2338 	        { NS_VK_S, 0x3d },
2339 	        { NS_VK_T, 0x2b },
2340 	        { NS_VK_U, 0x2d },
2341 	        { NS_VK_V, 0x4f },
2342 	        { NS_VK_W, 0x28 },
2343 	        { NS_VK_X, 0x4d },
2344 	        { NS_VK_Y, 0x2c },
2345 	        { NS_VK_Z, 0x4c }
2346         };
2347 
2348 // keycode of keypad when num-locked
2349 struct nsKeyConverter nsKeycodesBeOSNumLock[] = {
2350 	        { NS_VK_NUMPAD0, 0x64 },
2351 	        { NS_VK_NUMPAD1, 0x58 },
2352 	        { NS_VK_NUMPAD2, 0x59 },
2353 	        { NS_VK_NUMPAD3, 0x5a },
2354 	        { NS_VK_NUMPAD4, 0x48 },
2355 	        { NS_VK_NUMPAD5, 0x49 },
2356 	        { NS_VK_NUMPAD6, 0x4a },
2357 	        { NS_VK_NUMPAD7, 0x37 },
2358 	        { NS_VK_NUMPAD8, 0x38 },
2359 	        { NS_VK_NUMPAD9, 0x39 },
2360 	        { NS_VK_DECIMAL, 0x65 }
2361         };
2362 
2363 // keycode of keypad when not num-locked
2364 struct nsKeyConverter nsKeycodesBeOSNoNumLock[] = {
2365 	        { NS_VK_LEFT,       0x48 },
2366 	        { NS_VK_RIGHT,      0x4a },
2367 	        { NS_VK_UP,         0x38 },
2368 	        { NS_VK_DOWN,       0x59 },
2369 	        { NS_VK_PAGE_UP,    0x39 },
2370 	        { NS_VK_PAGE_DOWN,  0x5a },
2371 	        { NS_VK_HOME,       0x37 },
2372 	        { NS_VK_END,        0x58 },
2373 	        { NS_VK_INSERT,     0x64 },
2374 	        { NS_VK_DELETE,     0x65 }
2375         };
2376 
2377 //-------------------------------------------------------------------------
2378 //
2379 // Translate key code
2380 // Input is BeOS keyboard key-code; output is in NS_VK format
2381 //
2382 //-------------------------------------------------------------------------
2383 
2384 static int TranslateBeOSKeyCode(int32 bekeycode, bool isnumlock)
2385 {
2386 #ifdef KB_DEBUG
2387 	printf("TranslateBeOSKeyCode: bekeycode = 0x%x\n",bekeycode);
2388 #endif
2389 	int i;
2390 	int length = sizeof(nsKeycodesBeOS) / sizeof(struct nsKeyConverter);
2391 	int length_numlock = sizeof(nsKeycodesBeOSNumLock) / sizeof(struct nsKeyConverter);
2392 	int length_nonumlock = sizeof(nsKeycodesBeOSNoNumLock) / sizeof(struct nsKeyConverter);
2393 
2394 	// key code conversion
2395 	for (i = 0; i < length; i++) {
2396 		if (nsKeycodesBeOS[i].bekeycode == bekeycode)
2397 			return(nsKeycodesBeOS[i].vkCode);
2398 	}
2399 	// numpad keycode vary with numlock
2400 	if (isnumlock) {
2401 		for (i = 0; i < length_numlock; i++) {
2402 			if (nsKeycodesBeOSNumLock[i].bekeycode == bekeycode)
2403 				return(nsKeycodesBeOSNumLock[i].vkCode);
2404 		}
2405 	} else {
2406 		for (i = 0; i < length_nonumlock; i++) {
2407 			if (nsKeycodesBeOSNoNumLock[i].bekeycode == bekeycode)
2408 				return(nsKeycodesBeOSNoNumLock[i].vkCode);
2409 		}
2410 	}
2411 #ifdef KB_DEBUG
2412 	printf("TranslateBeOSKeyCode: ####### Translation not Found #######\n");
2413 #endif
2414 	return((int)0);
2415 }
2416 
2417 //-------------------------------------------------------------------------
2418 //
2419 // OnKeyDown
2420 //
2421 //-------------------------------------------------------------------------
2422 PRBool nsWindow::OnKeyDown(PRUint32 aEventType, const char *bytes,
2423                            int32 numBytes, PRUint32 mod, PRUint32 bekeycode, int32 rawcode)
2424 {
2425 	PRUint32 aTranslatedKeyCode;
2426 	PRBool noDefault = PR_FALSE;
2427 
2428 	mIsShiftDown   = (mod & B_SHIFT_KEY) ? PR_TRUE : PR_FALSE;
2429 	mIsControlDown = (mod & B_CONTROL_KEY) ? PR_TRUE : PR_FALSE;
2430 	mIsAltDown     = ((mod & B_COMMAND_KEY) && !(mod & B_RIGHT_OPTION_KEY))? PR_TRUE : PR_FALSE;
2431 	mIsMetaDown    = (mod & B_LEFT_OPTION_KEY) ? PR_TRUE : PR_FALSE;	
2432 	bool IsNumLocked = ((mod & B_NUM_LOCK) != 0);
2433 
2434 	aTranslatedKeyCode = TranslateBeOSKeyCode(bekeycode, IsNumLocked);
2435 
2436 	if (numBytes <= 1)
2437 	{
2438 		noDefault  = DispatchKeyEvent(NS_KEY_DOWN, 0, aTranslatedKeyCode);
2439 	} else {
2440 		//   non ASCII chars
2441 	}
2442 
2443 	// ------------  On Char  ------------
2444 	PRUint32	uniChar;
2445 
2446 	if ((mIsControlDown || mIsAltDown || mIsMetaDown) && rawcode >= 'a' && rawcode <= 'z') {
2447 		if (mIsShiftDown)
2448 			uniChar = rawcode + 'A' - 'a';
2449 		else
2450 			uniChar = rawcode;
2451 		aTranslatedKeyCode = 0;
2452 	} else {
2453 		if (numBytes == 0) // deal with unmapped key
2454 			return noDefault;
2455 
2456 		switch((unsigned char)bytes[0])
2457 		{
2458 		case 0xc8://System Request
2459 		case 0xca://Break
2460 			return noDefault;// do not send 'KEY_PRESS' message
2461 
2462 		case B_INSERT:
2463 		case B_ESCAPE:
2464 		case B_FUNCTION_KEY:
2465 		case B_HOME:
2466 		case B_PAGE_UP:
2467 		case B_END:
2468 		case B_PAGE_DOWN:
2469 		case B_UP_ARROW:
2470 		case B_LEFT_ARROW:
2471 		case B_DOWN_ARROW:
2472 		case B_RIGHT_ARROW:
2473 		case B_TAB:
2474 		case B_DELETE:
2475 		case B_BACKSPACE:
2476 		case B_ENTER:
2477 			uniChar = 0;
2478 			break;
2479 
2480 		default:
2481 			// UTF-8 to unicode conversion
2482 			if (numBytes >= 1 && (bytes[0] & 0x80) == 0) {
2483 				// 1 byte utf-8 char
2484 				uniChar = bytes[0];
2485 			} else
2486 				if (numBytes >= 2 && (bytes[0] & 0xe0) == 0xc0) {
2487 					// 2 byte utf-8 char
2488 					uniChar = ((uint16)(bytes[0] & 0x1f) << 6) | (uint16)(bytes[1] & 0x3f);
2489 				} else
2490 					if (numBytes >= 3 && (bytes[0] & 0xf0) == 0xe0) {
2491 						// 3 byte utf-8 char
2492 						uniChar = ((uint16)(bytes[0] & 0x0f) << 12) | ((uint16)(bytes[1] & 0x3f) << 6)
2493 						          | (uint16)(bytes[2] & 0x3f);
2494 					} else {
2495 						//error
2496 						uniChar = 0;
2497 						NS_WARNING("nsWindow::OnKeyDown() error: bytes[] has not enough chars.");
2498 					}
2499 
2500 			aTranslatedKeyCode = 0;
2501 			break;
2502 		}
2503 	}
2504 
2505 	// If prevent default set for onkeydown, do the same for onkeypress
2506 	PRUint32 extraFlags = (noDefault ? NS_EVENT_FLAG_NO_DEFAULT : 0);
2507 	return DispatchKeyEvent(NS_KEY_PRESS, uniChar, aTranslatedKeyCode, extraFlags) && noDefault;
2508 }
2509 
2510 //-------------------------------------------------------------------------
2511 //
2512 // OnKeyUp
2513 //
2514 //-------------------------------------------------------------------------
2515 PRBool nsWindow::OnKeyUp(PRUint32 aEventType, const char *bytes,
2516                          int32 numBytes, PRUint32 mod, PRUint32 bekeycode, int32 rawcode)
2517 {
2518 	PRUint32 aTranslatedKeyCode;
2519 	bool IsNumLocked = ((mod & B_NUM_LOCK) != 0);
2520 
2521 	mIsShiftDown   = (mod & B_SHIFT_KEY) ? PR_TRUE : PR_FALSE;
2522 	mIsControlDown = (mod & B_CONTROL_KEY) ? PR_TRUE : PR_FALSE;
2523 	mIsAltDown     = ((mod & B_COMMAND_KEY) && !(mod & B_RIGHT_OPTION_KEY))? PR_TRUE : PR_FALSE;
2524 	mIsMetaDown    = (mod & B_LEFT_OPTION_KEY) ? PR_TRUE : PR_FALSE;	
2525 
2526 	aTranslatedKeyCode = TranslateBeOSKeyCode(bekeycode, IsNumLocked);
2527 
2528 	PRBool result = DispatchKeyEvent(NS_KEY_UP, 0, aTranslatedKeyCode);
2529 	return result;
2530 
2531 }
2532 
2533 //-------------------------------------------------------------------------
2534 //
2535 // DispatchKeyEvent
2536 //
2537 //-------------------------------------------------------------------------
2538 
2539 PRBool nsWindow::DispatchKeyEvent(PRUint32 aEventType, PRUint32 aCharCode,
2540                                   PRUint32 aKeyCode, PRUint32 aFlags)
2541 {
2542 	nsKeyEvent event(PR_TRUE, aEventType, this);
2543 	nsPoint point;
2544 
2545 	point.x = 0;
2546 	point.y = 0;
2547 
2548 	InitEvent(event, &point); // this add ref's event.widget
2549 
2550 	event.flags |= aFlags;
2551 	event.charCode = aCharCode;
2552 	event.keyCode  = aKeyCode;
2553 
2554 #ifdef KB_DEBUG
2555 	static int cnt=0;
2556 	printf("%d DispatchKE Type: %s charCode 0x%x  keyCode 0x%x ", cnt++,
2557 	       (NS_KEY_PRESS == aEventType)?"PRESS":(aEventType == NS_KEY_UP?"Up":"Down"),
2558 	       event.charCode, event.keyCode);
2559 	printf("Shift: %s Control %s Alt: %s Meta: %s\n",  
2560 	       (mIsShiftDown?"D":"U"), 
2561 	       (mIsControlDown?"D":"U"), 
2562 	       (mIsAltDown?"D":"U"),
2563 	       (mIsMetaDown?"D":"U"));
2564 #endif
2565 
2566 	event.isShift   = mIsShiftDown;
2567 	event.isControl = mIsControlDown;
2568 	event.isMeta   =  mIsMetaDown;
2569 	event.isAlt     = mIsAltDown;
2570 
2571 	PRBool result = DispatchWindowEvent(&event);
2572 	NS_RELEASE(event.widget);
2573 
2574 	return result;
2575 }
2576 
2577 //-------------------------------------------------------------------------
2578 //
2579 // WM_DESTROY has been called
2580 //
2581 //-------------------------------------------------------------------------
2582 void nsWindow::OnDestroy()
2583 {
2584 	mOnDestroyCalled = PR_TRUE;
2585 
2586 	// release references to children, device context, toolkit, and app shell
2587 	nsBaseWidget::OnDestroy();
2588 
2589 	// dispatch the event
2590 	if (!mIsDestroying) 
2591 	{
2592 		// dispatching of the event may cause the reference count to drop to 0
2593 		// and result in this object being destroyed. To avoid that, add a reference
2594 		// and then release it after dispatching the event
2595 		AddRef();
2596 		DispatchStandardEvent(NS_DESTROY);
2597 		Release();
2598 	}
2599 }
2600 
2601 //-------------------------------------------------------------------------
2602 //
2603 // Move
2604 //
2605 //-------------------------------------------------------------------------
2606 PRBool nsWindow::OnMove(PRInt32 aX, PRInt32 aY)
2607 {
2608 	nsGUIEvent event(PR_TRUE, NS_MOVE, this);
2609 	InitEvent(event);
2610 	event.point.x = aX;
2611 	event.point.y = aY;
2612 
2613 	PRBool result = DispatchWindowEvent(&event);
2614 	NS_RELEASE(event.widget);
2615 	return result;
2616 }
2617 
2618 void nsWindow::OnWheel(PRInt32 aDirection, uint32 aButtons, BPoint aPoint, nscoord aDelta)
2619 {
2620 		// we don't use the mIsXDown bools because
2621 		// they get reset on Gecko reload (makes it harder
2622 		// to use stuff like Alt+Wheel)
2623 
2624 		nsMouseScrollEvent scrollEvent(PR_TRUE, NS_MOUSE_SCROLL, this);
2625 		uint32 mod (modifiers());
2626 		scrollEvent.isControl = mod & B_CONTROL_KEY;
2627 		scrollEvent.isShift = mod & B_SHIFT_KEY;
2628 		scrollEvent.isAlt   = mod & B_COMMAND_KEY;
2629 		scrollEvent.isMeta  = mod & B_OPTION_KEY;
2630 						
2631 		scrollEvent.scrollFlags = aDirection;
2632 		scrollEvent.delta = aDelta;
2633 		scrollEvent.time      = PR_IntervalNow();
2634 		scrollEvent.point.x = nscoord(aPoint.x);
2635 		scrollEvent.point.y = nscoord(aPoint.y);
2636 
2637 		nsEventStatus rv;
2638 		DispatchEvent (&scrollEvent, rv);
2639 }
2640 
2641 //-------------------------------------------------------------------------
2642 //
2643 // Paint
2644 //
2645 //-------------------------------------------------------------------------
2646 nsresult nsWindow::OnPaint(BRegion *breg)
2647 {
2648 	nsresult rv = NS_ERROR_FAILURE;
2649 	if (mView && mView->LockLooper())
2650 	{
2651 		// Substracting area from paintregion
2652 		mView->Validate(breg);
2653 		// looks like it should be done by Mozilla via nsRenderingContext methods,
2654 		// but we saw in some cases how it follows Win32 ideas and don't care about clipping there
2655 		mView->ConstrainClippingRegion(breg);
2656 		mView->UnlockLooper();
2657 	}
2658 	else
2659 		return rv;
2660 	BRect br = breg->Frame();
2661 	if (!br.IsValid() || !mEventCallback || !mView  || (eWindowType_child != mWindowType && eWindowType_popup != mWindowType))
2662 		return rv;
2663 	nsRect nsr(nscoord(br.left), nscoord(br.top), 
2664 			nscoord(br.IntegerWidth() + 1), nscoord(br.IntegerHeight() + 1));
2665 	mUpdateArea->SetTo(0,0,0,0);
2666 	int numrects = breg->CountRects();
2667 	for (int i = 0; i< numrects; i++)
2668 	{
2669 		BRect br = breg->RectAt(i);
2670 		mUpdateArea->Union(int(br.left), int(br.top), 
2671 							br.IntegerWidth() + 1, br.IntegerHeight() + 1);
2672 	}	
2673 
2674 	
2675 	nsPaintEvent event(PR_TRUE, NS_PAINT, this);
2676 
2677 	InitEvent(event);
2678 	event.region = mUpdateArea;
2679 	event.rect = &nsr;
2680 	event.renderingContext = GetRenderingContext();
2681 	if (event.renderingContext != nsnull)
2682 	{
2683 		// TODO: supply nsRenderingContextBeOS with font, colors and other state variables here.
2684 		// It will help toget rid of some hacks in LockAndUpdateView and
2685 		// allow non-permanent nsDrawingSurface for BeOS - currently it fails for non-bitmapped BViews/widgets.
2686 		// Something like this:
2687 		//if (mFontMetrics)
2688 		//	event.renderingContext->SetFont(mFontMetrics);
2689 		rv = DispatchWindowEvent(&event) ? NS_OK : NS_ERROR_FAILURE;
2690 		NS_RELEASE(event.renderingContext);
2691 	}
2692 
2693 	NS_RELEASE(event.widget);
2694 	return rv;
2695 }
2696 
2697 
2698 //-------------------------------------------------------------------------
2699 //
2700 // Send a resize message to the listener
2701 //
2702 //-------------------------------------------------------------------------
2703 PRBool nsWindow::OnResize(nsRect &aWindowRect)
2704 {
2705 	// call the event callback
2706 	if (mEventCallback)
2707 	{
2708 		nsSizeEvent event(PR_TRUE, NS_SIZE, this);
2709 		InitEvent(event);
2710 		event.windowSize = &aWindowRect;
2711 		// We have same size for windows rect and "client area" rect
2712 		event.mWinWidth  = aWindowRect.width;
2713 		event.mWinHeight = aWindowRect.height;
2714 		PRBool result = DispatchWindowEvent(&event);
2715 		NS_RELEASE(event.widget);
2716 		return result;
2717 	}
2718 	return PR_FALSE;
2719 }
2720 
2721 
2722 
2723 //-------------------------------------------------------------------------
2724 //
2725 // Deal with all sort of mouse event
2726 //
2727 //-------------------------------------------------------------------------
2728 PRBool nsWindow::DispatchMouseEvent(PRUint32 aEventType, nsPoint aPoint, PRUint32 clicks, PRUint32 mod)
2729 {
2730 	PRBool result = PR_FALSE;
2731 	if (nsnull != mEventCallback || nsnull != mMouseListener)
2732 	{
2733 		nsMouseEvent event(PR_TRUE, aEventType, this, nsMouseEvent::eReal);
2734 		InitEvent (event, &aPoint);
2735 		event.isShift   = mod & B_SHIFT_KEY;
2736 		event.isControl = mod & B_CONTROL_KEY;
2737 		event.isAlt     = mod & B_COMMAND_KEY;
2738 		event.isMeta     = mod & B_OPTION_KEY;
2739 		event.clickCount = clicks;
2740 
2741 		// call the event callback
2742 		if (nsnull != mEventCallback)
2743 		{
2744 			result = DispatchWindowEvent(&event);
2745 			NS_RELEASE(event.widget);
2746 			return result;
2747 		}
2748 		else
2749 		{
2750 			switch(aEventType)
2751 			{
2752 			case NS_MOUSE_MOVE :
2753 				result = ConvertStatus(mMouseListener->MouseMoved(event));
2754 				break;
2755 
2756 			case NS_MOUSE_LEFT_BUTTON_DOWN :
2757 			case NS_MOUSE_MIDDLE_BUTTON_DOWN :
2758 			case NS_MOUSE_RIGHT_BUTTON_DOWN :
2759 				result = ConvertStatus(mMouseListener->MousePressed(event));
2760 				break;
2761 
2762 			case NS_MOUSE_LEFT_BUTTON_UP :
2763 			case NS_MOUSE_MIDDLE_BUTTON_UP :
2764 			case NS_MOUSE_RIGHT_BUTTON_UP :
2765 				result = ConvertStatus(mMouseListener->MouseReleased(event)) && ConvertStatus(mMouseListener->MouseClicked(event));
2766 				break;
2767 			}
2768 			NS_RELEASE(event.widget);
2769 			return result;
2770 		}
2771 	}
2772 
2773 	return PR_FALSE;
2774 }
2775 
2776 //-------------------------------------------------------------------------
2777 //
2778 // Deal with focus messages
2779 //
2780 //-------------------------------------------------------------------------
2781 PRBool nsWindow::DispatchFocus(PRUint32 aEventType)
2782 {
2783 	// call the event callback
2784 	if (mEventCallback) {
2785 		return(DispatchStandardEvent(aEventType));
2786 	}
2787 
2788 	return PR_FALSE;
2789 }
2790 
2791 NS_METHOD nsWindow::SetTitle(const nsAString& aTitle)
2792 {
2793 	if (mView && mView->LockLooper())
2794 	{
2795 		mView->Window()->SetTitle(NS_ConvertUTF16toUTF8(aTitle).get());
2796 		mView->UnlockLooper();
2797 	}
2798 	return NS_OK;
2799 }
2800 
2801 //----------------------------------------------------
2802 //
2803 // Get/Set the preferred size
2804 //
2805 //----------------------------------------------------
2806 NS_METHOD nsWindow::GetPreferredSize(PRInt32& aWidth, PRInt32& aHeight)
2807 {
2808 	// TODO:  Check to see how often this is called.  If too much, leave as is,
2809 	// otherwise, call mView->GetPreferredSize
2810 	aWidth  = mPreferredWidth;
2811 	aHeight = mPreferredHeight;
2812 	return NS_ERROR_FAILURE;
2813 }
2814 
2815 NS_METHOD nsWindow::SetPreferredSize(PRInt32 aWidth, PRInt32 aHeight)
2816 {
2817 	mPreferredWidth  = aWidth;
2818 	mPreferredHeight = aHeight;
2819 	return NS_OK;
2820 }
2821 
2822 //----------------------------------------------------
2823 // Special Sub-Class
2824 //----------------------------------------------------
2825 nsIWidgetStore::nsIWidgetStore( nsIWidget *aWidget )
2826 		: mWidget( aWidget )
2827 {
2828 	// NS_ADDREF/NS_RELEASE is not needed here.
2829 	// This class is used as internal (BeOS native) object of nsWindow,
2830 	// so it must not addref/release nsWindow here.
2831 	// Otherwise, nsWindow object will leak. (Makoto Hamanaka)
2832 }
2833 
2834 nsIWidgetStore::~nsIWidgetStore()
2835 {
2836 }
2837 
2838 nsIWidget *nsIWidgetStore::GetMozillaWidget(void)
2839 {
2840 	return mWidget;
2841 }
2842 
2843 //----------------------------------------------------
2844 // BeOS Sub-Class Window
2845 //----------------------------------------------------
2846 
2847 nsWindowBeOS::nsWindowBeOS( nsIWidget *aWidgetWindow, BRect aFrame, const char *aName, window_look aLook,
2848                             window_feel aFeel, int32 aFlags, int32 aWorkspace )
2849 		: BWindow( aFrame, aName, aLook, aFeel, aFlags, aWorkspace ),
2850 		nsIWidgetStore( aWidgetWindow )
2851 {
2852 	fJustGotBounds = true;
2853 }
2854 
2855 nsWindowBeOS::~nsWindowBeOS()
2856 {
2857 	//placeholder for clean up
2858 }
2859 
2860 bool nsWindowBeOS::QuitRequested( void )
2861 {
2862 	if (CountChildren() != 0)
2863 	{
2864 		nsWindow	*w = (nsWindow *)GetMozillaWidget();
2865 		nsToolkit	*t;
2866 		if (w && (t = w->GetToolkit()) != 0)
2867 		{
2868 			MethodInfo *info = nsnull;
2869 			if (nsnull != (info = new MethodInfo(w, w, nsSwitchToUIThread::CLOSEWINDOW)))
2870 				t->CallMethodAsync(info);
2871 			NS_RELEASE(t);
2872 		}
2873 	}
2874 	return true;
2875 }
2876 
2877 void nsWindowBeOS::MessageReceived(BMessage *msg)
2878 {
2879 	// Temp replacement for real DnD. Supports file drop onto window.
2880 	if (msg->what == B_SIMPLE_DATA)
2881 	{
2882 		be_app_messenger.SendMessage(msg);
2883 	}
2884 	BWindow::MessageReceived(msg);
2885 }
2886 
2887 // This function calls KeyDown() for Alt+whatever instead of app_server
2888 void nsWindowBeOS::DispatchMessage(BMessage *msg, BHandler *handler)
2889 {
2890 	if (msg->what == B_KEY_DOWN && modifiers() & B_COMMAND_KEY) {
2891 		BString bytes;
2892 		if (B_OK == msg->FindString("bytes", &bytes)) {
2893 			BView *view = this->CurrentFocus();
2894 			if (view)
2895 				view->KeyDown(bytes.String(), bytes.Length());
2896 		}
2897 		if (strcmp(bytes.String(),"w") && strcmp(bytes.String(),"W"))
2898 			BWindow::DispatchMessage(msg, handler);
2899 	}
2900 	// In some cases the message don't reach QuitRequested() hook,
2901 	// so do it here
2902 	else if(msg->what == B_QUIT_REQUESTED)
2903 	{
2904 		// tells nsWindow to kill me
2905 		nsWindow	*w = (nsWindow *)GetMozillaWidget();
2906 		nsToolkit	*t;
2907 		if (w && (t = w->GetToolkit()) != 0)
2908 		{
2909 			MethodInfo *info = nsnull;
2910 			if (nsnull != (info = new MethodInfo(w, w, nsSwitchToUIThread::CLOSEWINDOW)))
2911 				t->CallMethodAsync(info);
2912 			NS_RELEASE(t);
2913 		}
2914 	}
2915 	else
2916 		BWindow::DispatchMessage(msg, handler);
2917 }
2918 
2919 //This method serves single purpose here - allows Mozilla to save current window position,
2920 //and restore position on new start. 
2921 void nsWindowBeOS::FrameMoved(BPoint origin)
2922 {	
2923 
2924 	//determine if the window position actually changed
2925 	if (origin.x == lastWindowPoint.x && origin.x == lastWindowPoint.x) 
2926 	{
2927 		//it didn't - don't bother
2928 		return;
2929 	}
2930 	lastWindowPoint = origin;
2931 	nsWindow  *w = (nsWindow *)GetMozillaWidget();
2932 	nsToolkit *t;
2933 	if (w && (t = w->GetToolkit()) != 0) 
2934 	{
2935 		MethodInfo *info = nsnull;
2936 		if (nsnull != (info = new MethodInfo(w, w, nsSwitchToUIThread::ONMOVE)))
2937 			t->CallMethodAsync(info);
2938 		NS_RELEASE(t);
2939 	}
2940 }
2941 
2942 void nsWindowBeOS::WindowActivated(bool active)
2943 {
2944 // Calls method ONACTIVATE to dispatch focus ACTIVATE messages
2945 	nsWindow        *w = (nsWindow *)GetMozillaWidget();
2946 	nsToolkit	*t;
2947 	if (w && (t = w->GetToolkit()) != 0)
2948 	{
2949 		uint32	args[2];
2950 		args[0] = (uint32)active;
2951 		args[1] = (uint32)this;
2952 		MethodInfo *info = nsnull;
2953 		if (nsnull != (info = new MethodInfo(w, w, nsSwitchToUIThread::ONACTIVATE, 2, args)))
2954 			t->CallMethodAsync(info);
2955 		NS_RELEASE(t);
2956 	}
2957 }
2958 
2959 void  nsWindowBeOS::WorkspacesChanged(uint32 oldworkspace, uint32 newworkspace)
2960 {
2961 	if (oldworkspace == newworkspace)
2962 		return;
2963 	nsWindow        *w = (nsWindow *)GetMozillaWidget();
2964 	nsToolkit	*t;
2965 	if (w && (t = w->GetToolkit()) != 0)
2966 	{
2967 		uint32	args[2];
2968 		args[0] = newworkspace;
2969 		args[1] = oldworkspace;
2970 		MethodInfo *info = nsnull;
2971 		if (nsnull != (info = new MethodInfo(w, w, nsSwitchToUIThread::ONWORKSPACE, 2, args)))
2972 			t->CallMethodAsync(info);
2973 		NS_RELEASE(t);
2974 	}	
2975 }
2976 
2977 void  nsWindowBeOS::FrameResized(float width, float height)
2978 {
2979 	// We have send message already, and Mozilla still didn't get it
2980 	// so don't poke it endlessly with no reason
2981 	if (!fJustGotBounds)
2982 		return;
2983 	nsWindow        *w = (nsWindow *)GetMozillaWidget();
2984 	nsToolkit	*t;
2985 	if (w && (t = w->GetToolkit()) != 0)
2986 	{
2987 		MethodInfo *info = nsnull;
2988 		if (nsnull != (info = new MethodInfo(w, w, nsSwitchToUIThread::ONRESIZE)))
2989 		{
2990 			t->CallMethodAsync(info);
2991 			//Memorize fact of sending message
2992 			fJustGotBounds = false;
2993 		}
2994 		NS_RELEASE(t);
2995 	}	
2996 }
2997 
2998 //----------------------------------------------------
2999 // BeOS Sub-Class View
3000 //----------------------------------------------------
3001 
3002 nsViewBeOS::nsViewBeOS(nsIWidget *aWidgetWindow, BRect aFrame, const char *aName, uint32 aResizingMode, uint32 aFlags)
3003 	: BView(aFrame, aName, aResizingMode, aFlags), nsIWidgetStore(aWidgetWindow), wheel(.0,.0)
3004 {
3005 	SetViewColor(B_TRANSPARENT_COLOR);
3006 	paintregion.MakeEmpty();	
3007 	buttons = 0;
3008 	fRestoreMouseMask = false;
3009 	fJustValidated = true;
3010 	fWheelDispatched = true;
3011 	fVisible = true;
3012 }
3013 
3014 void nsViewBeOS::SetVisible(bool visible)
3015 {
3016 	if (visible) 
3017 		SetFlags(Flags() | B_WILL_DRAW);
3018 	else
3019 		SetFlags(Flags() & ~B_WILL_DRAW);
3020 	fVisible = visible;
3021 }
3022 
3023 inline bool nsViewBeOS::Visible()
3024 {
3025 	return fVisible;
3026 }
3027 
3028 void nsViewBeOS::Draw(BRect updateRect)
3029 {
3030 	// Ignore all, we are scrolling.
3031 	if (!fVisible)
3032 		return;
3033 
3034 	paintregion.Include(updateRect);
3035 
3036 	// We have send message already, and Mozilla still didn't get it
3037 	// so don't poke it endlessly with no reason. Also don't send message
3038 	// if update region is empty.
3039 	if (paintregion.CountRects() == 0 || !paintregion.Frame().IsValid() || !fJustValidated)
3040 		return;
3041  	uint32	args[1];
3042  	args[0] = (uint32)this;
3043 	nsWindow	*w = (nsWindow *)GetMozillaWidget();
3044 	nsToolkit	*t;
3045 	if (w && (t = w->GetToolkit()) != 0)
3046 	{
3047 		MethodInfo *info = nsnull;
3048  		info = new MethodInfo(w, w, nsSwitchToUIThread::ONPAINT, 1, args);
3049 		if (info)
3050 		{
3051 			t->CallMethodAsync(info);
3052 			//Memorize fact of sending message
3053 			fJustValidated = false;
3054 		}
3055 		NS_RELEASE(t);
3056 	}
3057 }
3058 
3059 // Method to get update rects for asynchronous drawing.
3060 bool nsViewBeOS::GetPaintRegion(BRegion *r)
3061 {
3062 
3063 	// Mozilla got previous ONPAINT message,
3064 	// ready for next event.
3065 	fJustValidated = true;
3066 	if (paintregion.CountRects() == 0)
3067 		return false;
3068 	r->Include(&paintregion);
3069 	return true;
3070 }
3071 
3072 // Method to remove painted rects from pending update region
3073 void nsViewBeOS::Validate(BRegion *reg)
3074 {
3075 	paintregion.Exclude(reg);
3076 }
3077 
3078 BPoint nsViewBeOS::GetWheel()
3079 {
3080 	BPoint retvalue = wheel;
3081 	// Mozilla got wheel event, so setting flag and cleaning delta storage
3082 	fWheelDispatched = true;
3083 	wheel.x = 0;
3084 	wheel.y = 0;
3085 	return retvalue;
3086 }
3087 
3088 void nsViewBeOS::MouseDown(BPoint point)
3089 {
3090 	if (!fRestoreMouseMask)
3091 		mouseMask = SetMouseEventMask(B_POINTER_EVENTS);
3092 	fRestoreMouseMask = true;
3093 
3094 	//To avoid generating extra mouseevents when there is no change in pos.
3095 	mousePos = point;
3096 
3097 	uint32 clicks = 0;
3098 	BMessage *msg = Window()->CurrentMessage();
3099 	msg->FindInt32("buttons", (int32 *) &buttons);
3100 	msg->FindInt32("clicks", (int32 *) &clicks);
3101 
3102 	if (0 == buttons)
3103 		return;
3104 
3105 	nsWindow *w = (nsWindow *)GetMozillaWidget();
3106 	if (w == NULL)
3107 		return;
3108 		
3109 	nsToolkit	*t = w->GetToolkit();
3110 	if (t == NULL)
3111 		return;
3112 
3113 	int32 ev = (buttons & B_PRIMARY_MOUSE_BUTTON) ? NS_MOUSE_LEFT_BUTTON_DOWN :
3114 	           ((buttons & B_SECONDARY_MOUSE_BUTTON) ? NS_MOUSE_RIGHT_BUTTON_DOWN :
3115 	            NS_MOUSE_MIDDLE_BUTTON_DOWN);
3116 	uint32	args[5];
3117 	args[0] = ev;
3118 	args[1] = (uint32) point.x;
3119 	args[2] = (uint32) point.y;
3120 	args[3] = clicks;
3121 	args[4] = modifiers();
3122 	MethodInfo *info = nsnull;
3123 	if (nsnull != (info = new MethodInfo(w, w, nsSwitchToUIThread::BTNCLICK, 5, args)))
3124 		t->CallMethodAsync(info);
3125 	NS_RELEASE(t);
3126 }
3127 
3128 void nsViewBeOS::MouseMoved(BPoint point, uint32 transit, const BMessage *msg)
3129 {
3130 	//To avoid generating extra mouseevents when there is no change in pos.
3131 	//and not entering exiting view.
3132 	if (mousePos == point && (transit == B_INSIDE_VIEW || transit == B_OUTSIDE_VIEW))
3133 		return;
3134 
3135 	mousePos = point;
3136 
3137 	//We didn't start the mouse down and there is no drag in progress, so ignore.
3138 	if (NULL == msg && !fRestoreMouseMask && buttons)
3139 		return;
3140 		
3141 	nsWindow	*w = (nsWindow *)GetMozillaWidget();
3142 	if (w == NULL)
3143 		return;
3144 	nsToolkit	*t = t = w->GetToolkit();
3145 	if (t == NULL)
3146 		return;
3147 
3148 	uint32	args[1];
3149 /*	args[1] = (int32) point.x;
3150 	args[2] = (int32) point.y;
3151 	args[3] = modifiers();*/
3152 
3153 	switch (transit)
3154  	{
3155  	case B_ENTERED_VIEW:
3156 		{
3157 			args[0] = NULL != msg ? NS_DRAGDROP_ENTER : NS_MOUSE_ENTER;
3158 			if (msg == NULL)
3159 				break;
3160 			nsCOMPtr<nsIDragService> dragService = do_GetService(kCDragServiceCID);
3161 			dragService->StartDragSession();
3162 			//As it may have come from the outside we need to update this.
3163 			nsCOMPtr<nsIDragSessionBeOS> dragSessionBeOS = do_QueryInterface(dragService);
3164 			dragSessionBeOS->UpdateDragMessageIfNeeded(new BMessage(*msg));
3165 		}
3166 		break;
3167 	case B_EXITED_VIEW:
3168 		{
3169 			args[0] = NULL != msg ? NS_DRAGDROP_EXIT : NS_MOUSE_EXIT;
3170 			if (msg == NULL)
3171 				break;
3172 			nsCOMPtr<nsIDragService> dragService = do_GetService(kCDragServiceCID);
3173 			dragService->EndDragSession();
3174 		}
3175 		break;
3176 	default:
3177 		args[0]= msg == NULL ? NS_MOUSE_MOVE : NS_DRAGDROP_OVER;
3178  	}
3179  	
3180 	MethodInfo *moveInfo = nsnull;
3181 	if (nsnull != (moveInfo = new MethodInfo(w, w, nsSwitchToUIThread::ONMOUSE, 1, args)))
3182 		t->CallMethodAsync(moveInfo);
3183 	NS_RELEASE(t);
3184 }
3185 
3186 void nsViewBeOS::MouseUp(BPoint point)
3187 {
3188 	if (fRestoreMouseMask) 
3189 	{
3190 		SetMouseEventMask(mouseMask);
3191 		fRestoreMouseMask = false;
3192 	}
3193 
3194 	//To avoid generating extra mouseevents when there is no change in pos.
3195 	mousePos = point;
3196 
3197 	int32 ev = (buttons & B_PRIMARY_MOUSE_BUTTON) ? NS_MOUSE_LEFT_BUTTON_UP :
3198 	           ((buttons & B_SECONDARY_MOUSE_BUTTON) ? NS_MOUSE_RIGHT_BUTTON_UP :
3199 	            NS_MOUSE_MIDDLE_BUTTON_UP);
3200 	            
3201 	buttons = 0;
3202 		
3203 	nsWindow *w = (nsWindow *)GetMozillaWidget();
3204 	if (w == NULL)
3205 		return;
3206 	nsToolkit	*t = t = w->GetToolkit();
3207 	if (t == NULL)
3208 		return;
3209 
3210 	uint32	args[5];
3211 	args[0] = ev;
3212 	args[1] = (uint32) point.x;
3213 	args[2] = (int32) point.y;
3214 	args[3] = 0;
3215 	args[4] = modifiers();
3216 	MethodInfo *info = nsnull;
3217 	if (nsnull != (info = new MethodInfo(w, w, nsSwitchToUIThread::BTNCLICK, 5, args)))
3218 		t->CallMethodAsync(info);
3219 	NS_RELEASE(t);
3220 }
3221 
3222 void nsViewBeOS::MessageReceived(BMessage *msg)
3223 {
3224 	if(msg->WasDropped())
3225 	{
3226 		nsWindow	*w = (nsWindow *)GetMozillaWidget();
3227 		if (w == NULL)
3228 			return;
3229 		nsToolkit	*t = t = w->GetToolkit();
3230 		if (t == NULL)
3231 			return;
3232 
3233 		uint32	args[4];
3234 		args[0] = NS_DRAGDROP_DROP;
3235 
3236 		//Drop point is in screen-cordinates
3237 		BPoint aPoint = ConvertFromScreen(msg->DropPoint()); 
3238 	
3239 		args[1] = (uint32) aPoint.x;
3240 		args[2] = (uint32) aPoint.y;
3241 		args[3] = modifiers();
3242 
3243 		MethodInfo *info = new MethodInfo(w, w, nsSwitchToUIThread::ONDROP, 4, args);
3244 		t->CallMethodAsync(info);
3245 		BView::MessageReceived(msg);
3246 		return;
3247 	}
3248 
3249 	switch(msg->what)
3250 	{
3251 	//Native drag'n'drop negotiation
3252 	case B_COPY_TARGET:
3253 	case B_MOVE_TARGET:
3254 	case B_LINK_TARGET:
3255 	case B_TRASH_TARGET:
3256 		{
3257 			nsCOMPtr<nsIDragService> dragService = do_GetService(kCDragServiceCID);
3258 			nsCOMPtr<nsIDragSessionBeOS> dragSessionBeOS = do_QueryInterface(dragService);
3259 			dragSessionBeOS->TransmitData(new BMessage(*msg));
3260 		}
3261 		break;
3262 	case B_UNMAPPED_KEY_DOWN:
3263 		//printf("unmapped_key_down\n");
3264 		KeyDown(NULL, 0);
3265 		break;
3266 
3267 	case B_UNMAPPED_KEY_UP:
3268 		//printf("unmapped_key_up\n");
3269 		KeyUp(NULL, 0);
3270 		break;
3271 
3272 	case B_MOUSE_WHEEL_CHANGED:
3273 		{
3274 			float wheel_y;
3275 			float wheel_x;
3276 
3277 			msg->FindFloat ("be:wheel_delta_y", &wheel_y);
3278 			msg->FindFloat ("be:wheel_delta_x", &wheel_x);
3279 			wheel.x += wheel_x;
3280 			wheel.y += wheel_y;
3281 
3282 			if(!fWheelDispatched || (nscoord(wheel_x) == 0 && nscoord(wheel_y) == 0))
3283 				return;
3284 			uint32	args[1];
3285 			args[0] = (uint32)this;
3286 			nsWindow    *w = (nsWindow *)GetMozillaWidget();
3287 			nsToolkit   *t;
3288 
3289 			if (w && (t = w->GetToolkit()) != 0)
3290 			{
3291 					
3292 				MethodInfo *info = nsnull;
3293 				if (nsnull != (info = new MethodInfo(w, w, nsSwitchToUIThread::ONWHEEL, 1, args)))
3294 				{
3295 					t->CallMethodAsync(info);
3296 					fWheelDispatched = false;
3297 					
3298 				}
3299 				NS_RELEASE(t);
3300 			}
3301 		}
3302 		break;
3303 		
3304 #if defined(BeIME)
3305 	case B_INPUT_METHOD_EVENT:
3306 		DoIME(msg);
3307 		break;
3308 #endif
3309 	default :
3310 		BView::MessageReceived(msg);
3311 		break;
3312 	}
3313 }
3314 
3315 void nsViewBeOS::KeyDown(const char *bytes, int32 numBytes)
3316 {
3317 	nsWindow	*w = (nsWindow *)GetMozillaWidget();
3318 	nsToolkit	*t;
3319 	int32 keycode = 0;
3320 	int32 rawcode = 0;
3321 
3322 	BMessage *msg = this->Window()->CurrentMessage();
3323 	if (msg) {
3324 		msg->FindInt32("key", &keycode);
3325 		msg->FindInt32("raw_char", &rawcode);
3326 	}
3327 
3328 	if (w && (t = w->GetToolkit()) != 0) {
3329 		uint32 bytebuf = 0;
3330 		uint8 *byteptr = (uint8 *)&bytebuf;
3331 		for(int32 i = 0; i < numBytes; i++)
3332 			byteptr[i] = bytes[i];
3333 
3334 		uint32	args[6];
3335 		args[0] = NS_KEY_DOWN;
3336 		args[1] = bytebuf;
3337 		args[2] = numBytes;
3338 		args[3] = modifiers();
3339 		args[4] = keycode;
3340 		args[5] = rawcode;
3341 		MethodInfo *info = nsnull;
3342 		if (nsnull != (info = new MethodInfo(w, w, nsSwitchToUIThread::ONKEY, 6, args)))
3343 			t->CallMethodAsync(info);
3344 		NS_RELEASE(t);
3345 	}
3346 }
3347 
3348 void nsViewBeOS::KeyUp(const char *bytes, int32 numBytes)
3349 {
3350 	nsWindow	*w = (nsWindow *)GetMozillaWidget();
3351 	nsToolkit	*t;
3352 	int32 keycode = 0;
3353 	int32 rawcode = 0;
3354 	BMessage *msg = this->Window()->CurrentMessage();
3355 	if (msg) {
3356 		msg->FindInt32("key", &keycode);
3357 		msg->FindInt32("raw_char", &rawcode);
3358 	}
3359 
3360 	if (w && (t = w->GetToolkit()) != 0) {
3361 		uint32 bytebuf = 0;
3362 		uint8 *byteptr = (uint8 *)&bytebuf;
3363 		for(int32 i = 0; i < numBytes; i++)
3364 			byteptr[i] = bytes[i];
3365 
3366 		uint32	args[6];
3367 		args[0] = NS_KEY_UP;
3368 		args[1] = (int32)bytebuf;
3369 		args[2] = numBytes;
3370 		args[3] = modifiers();
3371 		args[4] = keycode;
3372 		args[5] = rawcode;
3373 		MethodInfo *info = nsnull;
3374 		if (nsnull != (info = new MethodInfo(w, w, nsSwitchToUIThread::ONKEY, 6, args)))
3375 			t->CallMethodAsync(info);
3376 		NS_RELEASE(t);
3377 	}
3378 }
3379 
3380 void nsViewBeOS::MakeFocus(bool focused)
3381 {
3382 	if (!IsFocus() && focused)
3383 		BView::MakeFocus(focused);
3384 	uint32	args[1];
3385 	args[0] = (uint32)this;
3386 	nsWindow	*w = (nsWindow *)GetMozillaWidget();
3387 	nsToolkit	*t;
3388 	if (w && (t = w->GetToolkit()) != 0)
3389 	{
3390 		MethodInfo *info = nsnull;
3391 		if (!focused)
3392 		{
3393 			if (nsnull != (info = new MethodInfo(w, w, nsSwitchToUIThread::KILL_FOCUS,1,args)))
3394 				t->CallMethodAsync(info);
3395 		}
3396 #ifdef DEBUG_FOCUS
3397 		else
3398 		{
3399 			if (nsnull != (info = new MethodInfo(w, w, nsSwitchToUIThread::GOT_FOCUS,1,args)))
3400 				t->CallMethodAsync(info);
3401 		}
3402 #endif		
3403 		NS_RELEASE(t);
3404 	}
3405 }
3406 
3407 #if defined(BeIME)
3408 // Inline Input Method implementation
3409 void nsViewBeOS::DoIME(BMessage *msg)
3410 {
3411 	nsWindow	*w = (nsWindow *)GetMozillaWidget();
3412 	nsToolkit	*t;
3413  
3414 	if(w && (t = w->GetToolkit()) != 0) 
3415 	{
3416 		ssize_t size = msg->FlattenedSize();
3417 		int32		argc = (size+3)/4;
3418 		uint32 *args = new uint32[argc];
3419 		if (args) 
3420 		{
3421 			msg->Flatten((char*)args, size);
3422 			MethodInfo *info = new MethodInfo(w, w, nsSwitchToUIThread::ONIME, argc, args);
3423 			if (info) 
3424 			{
3425 				t->CallMethodAsync(info);
3426 				NS_RELEASE(t);
3427 			}
3428 			delete[] args;
3429 		}	
3430 	}
3431 }
3432 #endif
3433