1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
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/
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
15 * The Original Code is mozilla.org code.
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.
23 * Jerry.Kirk@Nexwarecorp.com
24 * Dale.Stansberry@Nexwarecorop.com
26 * Alternatively, the contents of this file may be used under the terms of
27 * either the GNU General Public License Version 2 or later (the "GPL"), or
28 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
42 #include <photon/PtServer.h>
43 #include "PtRawDrawContainer.h"
47 #include "nsWidgetsCID.h"
48 #include "nsIFontMetrics.h"
50 #include "nsGUIEvent.h"
51 #include "nsIRenderingContext.h"
52 #include "nsIRegion.h"
54 #include "nsTransform2D.h"
55 #include "nsGfxCIID.h"
56 #include "nsToolkit.h"
57 #include "nsIPrefBranch.h"
58 #include "nsIPrefService.h"
60 #include "nsClipboard.h"
61 #include "nsIRollupListener.h"
63 #include "nsIServiceManager.h"
64 #include "nsIAppShell.h"
65 #include "nsIDocShell.h"
67 #include "nsIViewManager.h"
68 #include "nsIXULWindow.h"
69 #include "nsIDocShellTreeItem.h"
70 #include "nsIWindowMediator.h"
71 #include "nsIPresShell.h"
72 #include "nsReadableUtils.h"
74 static PhTile_t
*GetWindowClipping( PtWidget_t
*aWidget
);
76 nsIRollupListener
*nsWindow::gRollupListener
= nsnull
;
77 nsIWidget
*nsWindow::gRollupWidget
= nsnull
;
78 static PtWidget_t
*gMenuRegion
;
80 /* avoid making a costly PhWindowQueryVisible call */
81 static PhRect_t gConsoleRect
;
82 static PRBool gConsoleRectValid
= PR_FALSE
;
83 #define QueryVisible( ) {\
84 if( gConsoleRectValid == PR_FALSE ) { \
85 PhWindowQueryVisible( Ph_QUERY_IG_POINTER, 0, 1, &gConsoleRect ); \
86 gConsoleRectValid = PR_TRUE;\
90 //-------------------------------------------------------------------------
92 // nsWindow constructor
94 //-------------------------------------------------------------------------
97 mClientWidget
= nsnull
;
98 mIsTooSmall
= PR_FALSE
;
99 mBorderStyle
= eBorderStyle_default
;
100 mWindowType
= eWindowType_child
;
104 //-------------------------------------------------------------------------
106 // nsWindow destructor
108 //-------------------------------------------------------------------------
109 nsWindow::~nsWindow()
111 nsWindow
*p
= (nsWindow
*)mParent
;
112 if( p
&& p
->mLastMenu
== mWidget
) p
->mLastMenu
= nsnull
;
114 // always call destroy. if it's already been called, there's no harm
115 // since it keeps track of when it's already been called.
119 PRBool
nsWindow::IsChild() const
124 NS_IMETHODIMP
nsWindow::WidgetToScreen( const nsRect
& aOldRect
, nsRect
& aNewRect
) {
126 PhPoint_t pos
, offset
;
127 PtWidget_t
*disjoint
= PtFindDisjoint( mWidget
);
131 PtGetAbsPosition( disjoint
, &pos
.x
, &pos
.y
);
132 PtWidgetOffset( mWidget
, &offset
);
133 aNewRect
.x
= pos
.x
+ offset
.x
+ aOldRect
.x
- gConsoleRect
.ul
.x
;
134 aNewRect
.y
= pos
.y
+ offset
.y
+ aOldRect
.y
- gConsoleRect
.ul
.y
;
136 aNewRect
.width
= aOldRect
.width
;
137 aNewRect
.height
= aOldRect
.height
;
142 void nsWindow::DestroyNative(void)
146 PtDestroyWidget(mClientWidget
);
147 mClientWidget
= nsnull
;
149 // destroy all of the children that are nsWindow() classes
150 // preempting the gdk destroy system.
151 if( mWidget
) DestroyNativeChildren();
153 // Call the base class to actually PtDestroy mWidget.
154 nsWidget::DestroyNative();
157 // this function will walk the list of children and destroy them.
158 // the reason why this is here is that because of the superwin code
159 // it's very likely that we will never get notification of the
160 // the destruction of the child windows. so, we have to beat the
161 // layout engine to the punch. CB
163 void nsWindow::DestroyNativeChildren(void)
165 for(PtWidget_t
*w
=PtWidgetChildFront( mWidget
); w
; w
=PtWidgetBrotherBehind( w
))
167 if( w
->flags
& Pt_DESTROYED
) continue;
168 nsWindow
*childWindow
= static_cast<nsWindow
*>(GetInstance(w
));
169 if( childWindow
&& !childWindow
->mIsDestroying
) childWindow
->Destroy();
173 NS_IMETHODIMP
nsWindow::CaptureRollupEvents( nsIRollupListener
* aListener
, PRBool aDoCapture
, PRBool aConsumeRollupEvent
) {
174 PtWidget_t
*grabWidget
;
175 grabWidget
= mWidget
;
178 NS_IF_RELEASE(gRollupListener
);
179 NS_IF_RELEASE(gRollupWidget
);
180 gRollupListener
= aListener
;
181 NS_ADDREF(aListener
);
182 gRollupWidget
= this;
185 /* Realize the gMenuRegion to capture events outside of the application's canvas when menus are displayed */
186 /* Menus+submenus have the same parent. If the parent has mLastMenu set and realized, then use its region as "infront" */
187 /* If not, then this widget ( mWidget ) becomes the mLastMenu and gets recorded into the parent */
188 /* Different windows have different mLastMenu's */
189 if( mWindowType
== eWindowType_popup
&& !( PtWidgetFlags( gMenuRegion
) & Pt_REALIZED
) && mParent
) {
191 PtWidget_t
*pw
= ((nsWindow
*)mParent
)->mLastMenu
;
193 if( pw
&& ( PtWidgetFlags( pw
) & Pt_REALIZED
) && PtWidgetRid( pw
) > 0 )
194 PtSetResource( gMenuRegion
, Pt_ARG_REGION_INFRONT
, PtWidgetRid( pw
), 0 );
196 if( !PtWidgetIsRealized( mWidget
) ) PtRealizeWidget( mWidget
);
197 PtSetResource( gMenuRegion
, Pt_ARG_REGION_INFRONT
, PtWidgetRid( mWidget
), 0 );
198 ((nsWindow
*)mParent
)->mLastMenu
= mWidget
;
201 PtRealizeWidget( gMenuRegion
);
205 NS_IF_RELEASE(gRollupListener
);
206 gRollupListener
= nsnull
;
207 NS_IF_RELEASE(gRollupWidget
);
208 gRollupWidget
= nsnull
;
210 if( mWindowType
== eWindowType_popup
&& ( PtWidgetFlags( gMenuRegion
) & Pt_REALIZED
) )
211 PtUnrealizeWidget( gMenuRegion
);
217 NS_METHOD
nsWindow::PreCreateWidget( nsWidgetInitData
*aInitData
) {
218 if (nsnull
!= aInitData
) {
219 SetWindowType( aInitData
->mWindowType
);
220 SetBorderStyle( aInitData
->mBorderStyle
);
223 return NS_ERROR_FAILURE
;
227 //-------------------------------------------------------------------------
229 // Create the native widget
231 //-------------------------------------------------------------------------
232 NS_METHOD
nsWindow::CreateNative( PtWidget_t
*parentWidget
) {
237 unsigned long render_flags
;
238 nsresult result
= NS_ERROR_FAILURE
;
242 dim
.w
= mBounds
.width
;
243 dim
.h
= mBounds
.height
;
245 switch( mWindowType
)
247 case eWindowType_popup
:
248 mIsToplevel
= PR_TRUE
;
250 case eWindowType_toplevel
:
251 case eWindowType_invisible
:
252 mIsToplevel
= PR_TRUE
;
254 case eWindowType_dialog
:
255 mIsToplevel
= PR_TRUE
;
257 case eWindowType_child
:
258 mIsToplevel
= PR_FALSE
;
262 if ( mWindowType
== eWindowType_child
)
265 PtSetArg( &arg
[arg_count
++], Pt_ARG_POS
, &pos
, 0 );
266 PtSetArg( &arg
[arg_count
++], Pt_ARG_DIM
, &dim
, 0 );
267 PtSetArg( &arg
[arg_count
++], Pt_ARG_RESIZE_FLAGS
, 0, Pt_RESIZE_XY_BITS
);
268 PtSetArg( &arg
[arg_count
++], Pt_ARG_FLAGS
, 0 , Pt_HIGHLIGHTED
|Pt_GETS_FOCUS
);
269 PtSetArg( &arg
[arg_count
++], Pt_ARG_BORDER_WIDTH
, 0, 0 );
270 PtSetArg( &arg
[arg_count
++], Pt_ARG_FILL_COLOR
, Pg_RED
, 0 );
271 PtSetArg( &arg
[arg_count
++], RDC_DRAW_FUNC
, RawDrawFunc
, 0 );
272 mWidget
= PtCreateWidget( PtRawDrawContainer
, parentWidget
, arg_count
, arg
);
276 // No border or decorations is the default
277 render_flags
= 0; // Ph_WM_RENDER_RESIZE;
279 if( mWindowType
!= eWindowType_popup
) {
281 #define PH_BORDER_STYLE_ALL \
282 Ph_WM_RENDER_TITLE | \
283 Ph_WM_RENDER_CLOSE | \
284 Ph_WM_RENDER_BORDER | \
285 Ph_WM_RENDER_RESIZE | \
291 if( mBorderStyle
& eBorderStyle_all
) render_flags
|= PH_BORDER_STYLE_ALL
;
294 if( mBorderStyle
& eBorderStyle_border
) render_flags
|= Ph_WM_RENDER_BORDER
;
295 if( mBorderStyle
& eBorderStyle_title
) render_flags
|= ( Ph_WM_RENDER_TITLE
| Ph_WM_RENDER_BORDER
);
296 if( mBorderStyle
& eBorderStyle_close
) render_flags
|= Ph_WM_RENDER_CLOSE
;
297 if( mBorderStyle
& eBorderStyle_menu
) render_flags
|= Ph_WM_RENDER_MENU
;
298 if( mBorderStyle
& eBorderStyle_resizeh
) render_flags
|= Ph_WM_RENDER_RESIZE
;
299 if( mBorderStyle
& eBorderStyle_minimize
) render_flags
|= Ph_WM_RENDER_MIN
;
300 if( mBorderStyle
& eBorderStyle_maximize
) render_flags
|= Ph_WM_RENDER_MAX
;
304 if (mWindowType
== eWindowType_dialog
)
309 PtCalcAbsPosition(parentWidget
, NULL
, &dim
, &pos
);
310 PtSetArg( &arg
[arg_count
++], Pt_ARG_POS
, &pos
, 0 );
313 else if ((mWindowType
== eWindowType_toplevel
) && parentWidget
)
316 pos
.x
+= gConsoleRect
.ul
.x
;
317 pos
.y
+= gConsoleRect
.ul
.y
;
318 PtSetArg( &arg
[arg_count
++], Pt_ARG_POS
, &pos
, 0 );
321 PtSetArg( &arg
[arg_count
++], Pt_ARG_DIM
, &dim
, 0 );
322 PtSetArg( &arg
[arg_count
++], Pt_ARG_RESIZE_FLAGS
, 0, Pt_RESIZE_XY_BITS
);
324 /* Create Pop-up Menus as a PtRegion */
327 PtSetParentWidget( nsnull
);
329 if( mWindowType
== eWindowType_popup
) {
331 /* the gMenuRegion is used to capture events outside of the application's canvas when menus are displayed */
334 PtSetParentWidget( NULL
);
335 PtSetArg( &args
[0], Pt_ARG_REGION_PARENT
, 0, 0 );
336 PtSetArg( &args
[1], Pt_ARG_FILL_COLOR
, Pg_TRANSPARENT
, 0);
337 PhArea_t area
= { { 0, 0 }, { SHRT_MAX
, SHRT_MAX
} };
338 PtSetArg( &args
[2], Pt_ARG_AREA
, &area
, 0 );
339 PtSetArg( &args
[3], Pt_ARG_REGION_SENSE
, Ph_EV_BUT_PRESS
, Ph_EV_BUT_PRESS
);
340 PtSetArg( &args
[4], Pt_ARG_REGION_FLAGS
, Ph_FORCE_BOUNDARY
, Ph_FORCE_BOUNDARY
);
341 PtSetArg( &args
[5], Pt_ARG_CURSOR_TYPE
, Ph_CURSOR_POINTER
, 0 );
342 gMenuRegion
= PtCreateWidget( PtRegion
, NULL
, 6, args
);
343 PtAddEventHandler( gMenuRegion
, Ph_EV_BUT_PRESS
, MenuRegionCallback
, this );
346 int fields
= Ph_REGION_PARENT
|Ph_REGION_HANDLE
| Ph_REGION_FLAGS
|Ph_REGION_ORIGIN
|Ph_REGION_EV_SENSE
|Ph_REGION_EV_OPAQUE
|Ph_REGION_RECT
;
347 int sense
= Ph_EV_BUT_PRESS
| Ph_EV_BUT_RELEASE
| Ph_EV_BUT_REPEAT
;
348 PtCallback_t cb_destroyed
= { MenuRegionDestroyed
, NULL
};
350 PtSetArg( &arg
[arg_count
++], Pt_ARG_REGION_FIELDS
, fields
, fields
);
351 PtSetArg( &arg
[arg_count
++], Pt_ARG_REGION_PARENT
, Ph_ROOT_RID
, 0 );
352 PtSetArg( &arg
[arg_count
++], Pt_ARG_REGION_SENSE
, sense
| Ph_EV_DRAG
|Ph_EV_EXPOSE
, sense
| Ph_EV_DRAG
|Ph_EV_EXPOSE
);
353 PtSetArg( &arg
[arg_count
++], Pt_ARG_REGION_OPAQUE
, sense
| Ph_EV_DRAG
|Ph_EV_EXPOSE
|Ph_EV_DRAW
|Ph_EV_BLIT
, sense
|Ph_EV_DRAG
|Ph_EV_EXPOSE
|Ph_EV_DRAW
|Ph_EV_BLIT
);
354 PtSetArg( &arg
[arg_count
++], Pt_ARG_FLAGS
, Pt_DELAY_REALIZE
, Pt_GETS_FOCUS
| Pt_DELAY_REALIZE
);
355 PtSetArg( &arg
[arg_count
++], Pt_CB_DESTROYED
, &cb_destroyed
, 0 );
356 mWidget
= PtCreateWidget( PtRegion
, parentWidget
, arg_count
, arg
);
358 // Must also create the client-area widget
360 PtSetArg( &arg
[arg_count
++], Pt_ARG_ANCHOR_FLAGS
, Pt_ANCHOR_ALL
, ~0 );
361 PtSetArg( &arg
[arg_count
++], Pt_ARG_BORDER_WIDTH
, 0 , 0 );
362 PtSetArg( &arg
[arg_count
++], Pt_ARG_MARGIN_WIDTH
, 0 , 0 );
363 PhRect_t anch_offset
= {{0, 0},{0, 0}};
364 PtSetArg( &arg
[arg_count
++], Pt_ARG_ANCHOR_OFFSETS
, &anch_offset
, 0 );
366 PtSetArg( &arg
[arg_count
++], RDC_DRAW_FUNC
, RawDrawFunc
, 0 );
367 PtSetArg( &arg
[arg_count
++], Pt_ARG_FLAGS
, 0, (Pt_HIGHLIGHTED
| Pt_GETS_FOCUS
));
368 mClientWidget
= PtCreateWidget( PtRawDrawContainer
, mWidget
, arg_count
, arg
);
371 /* Dialog and TopLevel Windows */
372 PtSetArg( &arg
[arg_count
++], Pt_ARG_FLAGS
, Pt_DELAY_REALIZE
, Pt_DELAY_REALIZE
);
373 PtSetArg( &arg
[arg_count
++], Pt_ARG_WINDOW_RENDER_FLAGS
, render_flags
, -1 );
374 PtSetArg( &arg
[arg_count
++], Pt_ARG_WINDOW_MANAGED_FLAGS
, 0, Ph_WM_CLOSE
);
375 PtSetArg( &arg
[arg_count
++], Pt_ARG_WINDOW_NOTIFY_FLAGS
, Ph_WM_CLOSE
|Ph_WM_CONSWITCH
|Ph_WM_FOCUS
, ~0 );
376 PtSetArg( &arg
[arg_count
++], Pt_ARG_FILL_COLOR
, Pg_TRANSPARENT
, 0 );
378 PtRawCallback_t cb_raw
= { Ph_EV_INFO
, EvInfo
, NULL
};
379 PtCallback_t cb_resize
= { ResizeHandler
, NULL
};
380 PtCallback_t cb_window
= { WindowWMHandler
, this };
382 PtSetArg( &arg
[arg_count
++], Pt_CB_RESIZE
, &cb_resize
, NULL
);
383 PtSetArg( &arg
[arg_count
++], Pt_CB_RAW
, &cb_raw
, NULL
);
384 PtSetArg( &arg
[arg_count
++], Pt_CB_WINDOW
, &cb_window
, 0 );
385 mWidget
= PtCreateWidget( PtWindow
, parentWidget
, arg_count
, arg
);
390 SetInstance( mWidget
, this );
391 if( mClientWidget
) SetInstance( mClientWidget
, this );
392 if( mWindowType
== eWindowType_child
) {
393 PtAddCallback(mWidget
, Pt_CB_RESIZE
, ResizeHandler
, nsnull
);
394 PtAddEventHandler( mWidget
,
395 Ph_EV_PTR_MOTION_BUTTON
| Ph_EV_PTR_MOTION_NOBUTTON
|
396 Ph_EV_BUT_PRESS
| Ph_EV_BUT_RELEASE
|Ph_EV_BOUNDARY
|Ph_EV_DRAG
397 , RawEventHandler
, this );
400 PtRawCallback_t callback
;
402 callback
.event_mask
= ( Ph_EV_KEY
) ;
403 callback
.event_f
= RawEventHandler
;
404 callback
.data
= this;
405 PtSetArg( &arg
, Pt_CB_FILTER
, &callback
, 0 );
406 PtSetResources( mWidget
, 1, &arg
);
408 else if( mWindowType
== eWindowType_popup
) {
409 PtAddEventHandler( mClientWidget
,
410 Ph_EV_PTR_MOTION_BUTTON
| Ph_EV_PTR_MOTION_NOBUTTON
|
411 Ph_EV_BUT_PRESS
| Ph_EV_BUT_RELEASE
|Ph_EV_BOUNDARY
,
412 RawEventHandler
, this );
414 PtAddEventHandler( mWidget
, Ph_EV_DRAG
, RawEventHandler
, this );
417 PtRawCallback_t callback
;
419 callback
.event_mask
= ( Ph_EV_KEY
) ;
420 callback
.event_f
= RawEventHandler
;
421 callback
.data
= this;
422 PtSetArg( &arg
, Pt_CB_FILTER
, &callback
, 0 );
423 PtSetResources( mClientWidget
, 1, &arg
);
425 PtAddCallback(mClientWidget
, Pt_CB_RESIZE
, ResizeHandler
, nsnull
);
427 else if( !parentWidget
) {
428 if( mClientWidget
) PtAddCallback(mClientWidget
, Pt_CB_RESIZE
, ResizeHandler
, nsnull
);
431 // call the event callback to notify about creation
432 DispatchStandardEvent( NS_CREATE
);
437 /* force SetCursor to actually set the cursor, even though our internal state indicates that we already
438 have the standard cursor */
439 mCursor
= eCursor_wait
;
440 SetCursor( mCursor
);
446 //-------------------------------------------------------------------------
448 // Return some native data according to aDataType
450 //-------------------------------------------------------------------------
451 void *nsWindow::GetNativeData(PRUint32 aDataType
)
455 case NS_NATIVE_WINDOW
:
456 if( !mWidget
) return (void *)mWidget
;
458 case NS_NATIVE_WIDGET
:
459 if (mClientWidget
) return (void *) mClientWidget
;
460 else return (void *) mWidget
;
463 return nsWidget::GetNativeData(aDataType
);
466 //-------------------------------------------------------------------------
468 // Scroll the bits of a window
470 //-------------------------------------------------------------------------
471 NS_METHOD
nsWindow::Scroll( PRInt32 aDx
, PRInt32 aDy
, nsRect
*aClipRect
) {
472 PtWidget_t
*widget
= (PtWidget_t
*)GetNativeData(NS_NATIVE_WIDGET
);
474 /* If aDx and aDy are 0 then skip it or if widget == null */
475 if( ( !aDx
&& !aDy
) || (!widget
)) return NS_OK
;
477 PtStartFlux( widget
);
480 for( w
=PtWidgetChildFront( widget
); w
; w
=PtWidgetBrotherBehind( w
)) {
483 p
.x
= w
->area
.pos
.x
+ aDx
;
484 p
.y
= w
->area
.pos
.y
+ aDy
;
486 PtSetArg( &arg
, Pt_ARG_POS
, &p
, 0 );
487 PtSetResources( w
, 1, &arg
) ;
489 nsWindow
*pWin
= (nsWindow
*) GetInstance(w
);
491 pWin
->mBounds
.x
+= aDx
;
492 pWin
->mBounds
.y
+= aDy
;
498 PhRect_t source
= {{widget
->area
.pos
.x
, widget
->area
.pos
.y
},{widget
->area
.pos
.x
+ widget
->area
.size
.w
-1, widget
->area
.pos
.y
+ widget
->area
.size
.h
-1}};
499 PhPoint_t point
= { aDx
, aDy
};
501 if( !widget
->damage_list
)
502 PtBlit( widget
, &source
, &point
);
504 /* first noticed as a scrolling problem in netscape email */
505 /* the scrolling should be clipped out by the rectangles given by Invalidate(). These are accumulated in widget->damage_list */
506 PhTile_t original
= { source
, NULL
}, *clip
;
511 clip
= PhClipTilings( clip
, widget
->damage_list
, NULL
);
514 PtClippedBlit( widget
, &original
, &point
, clip
);
522 NS_METHOD
nsWindow::ScrollWidgets( PRInt32 aDx
, PRInt32 aDy
) {
523 PtWidget_t
*widget
= (PtWidget_t
*)GetNativeData(NS_NATIVE_WIDGET
);
525 if( ( !aDx
&& !aDy
) || (!widget
)) return NS_OK
;
527 PtStartFlux( widget
);
530 for( w
=PtWidgetChildFront( widget
); w
; w
=PtWidgetBrotherBehind( w
)) {
533 p
.x
= w
->area
.pos
.x
+ aDx
;
534 p
.y
= w
->area
.pos
.y
+ aDy
;
535 PtSetArg( &arg
, Pt_ARG_POS
, &p
, 0 );
536 PtSetResources( w
, 1, &arg
) ;
538 nsWindow
*pWin
= (nsWindow
*) GetInstance(w
);
540 pWin
->mBounds
.x
+= aDx
;
541 pWin
->mBounds
.y
+= aDy
;
549 NS_METHOD
nsWindow::SetTitle( const nsAString
& aTitle
) {
551 char * title
= ToNewUTF8String(aTitle
);
552 PtSetResource( mWidget
, Pt_ARG_WINDOW_TITLE
, title
, 0 );
553 if (title
) nsCRT::free(title
);
559 NS_IMETHODIMP
nsWindow::Resize(PRInt32 aWidth
, PRInt32 aHeight
, PRBool aRepaint
)
561 PRBool nNeedToShow
= PR_FALSE
;
563 if( aWidth
== mBounds
.width
&& aHeight
== mBounds
.height
) return NS_OK
;
565 mBounds
.width
= aWidth
;
566 mBounds
.height
= aHeight
;
568 // code to keep the window from showing before it has been moved or resized
569 // if we are resized to 1x1 or less, we will hide the window. Show(TRUE) will be ignored until a larger resize has happened
570 if( aWidth
<= 1 || aHeight
<= 1 ) {
571 aWidth
= aHeight
= 1;
572 mIsTooSmall
= PR_TRUE
;
576 // if we are not shown, we don't want to force a show here, so check and see if Show(TRUE) has been called
577 nNeedToShow
= mShown
;
578 mIsTooSmall
= PR_FALSE
;
582 PhDim_t dim
= { aWidth
, aHeight
};
586 if( mWindowType
== eWindowType_dialog
) {
589 PtCalcAbsPosition( NULL
, NULL
, &dim
, &p
);
590 p
.x
-= gConsoleRect
.ul
.x
;
591 p
.y
-= gConsoleRect
.ul
.y
;
592 Move(p
.x
, p
.y
); // the move should be in coordinates assuming the console is 0, 0
594 if( aRepaint
== PR_FALSE
) PtStartFlux(mWidget
);
595 PtSetResource( mWidget
, Pt_ARG_DIM
, &dim
, 0 );
596 if( aRepaint
== PR_FALSE
) PtEndFlux(mWidget
);
598 /* ATENTIE Remove when wojtek fixes PR:22930 in the photon library */
599 if( PtWidgetClass( mWidget
) == PtRegion
) PtSetResource( mWidget
, Pt_ARG_REGION_OPAQUE
, 0, Ph_EV_KEY
);
602 if( mIsToplevel
|| mListenForResizes
) {
603 nsSizeEvent
sevent(PR_TRUE
, 0, nsnull
);
604 sevent
.message
= NS_SIZE
;
605 sevent
.widget
= this;
607 sevent
.windowSize
= new nsRect (0, 0, aWidth
, aHeight
);
609 sevent
.refPoint
.x
= 0;
610 sevent
.refPoint
.y
= 0;
611 sevent
.mWinWidth
= aWidth
;
612 sevent
.mWinHeight
= aHeight
;
616 DispatchWindowEvent(&sevent
);
618 delete sevent
.windowSize
;
620 if( nNeedToShow
) Show(PR_TRUE
);
624 int nsWindow::WindowWMHandler( PtWidget_t
*widget
, void *data
, PtCallbackInfo_t
*cbinfo
)
626 PhWindowEvent_t
*we
= (PhWindowEvent_t
*) cbinfo
->cbdata
;
627 switch( we
->event_f
) {
630 nsWindow
* win
= (nsWindow
*) data
;
633 // dispatch an "onclose" event. to delete immediately, call win->Destroy()
634 nsGUIEvent
event(PR_TRUE
, 0, nsnull
);
635 nsEventStatus status
;
637 event
.message
= NS_XUL_CLOSE
;
641 event
.refPoint
.x
= 0;
642 event
.refPoint
.y
= 0;
644 win
->DispatchEvent(&event
, status
);
650 case Ph_WM_CONSWITCH
:
651 gConsoleRectValid
= PR_FALSE
; /* force a call tp PhWindowQueryVisible() next time, since we might have moved this window into a different console */
652 /* rollup the menus */
653 if( gRollupWidget
&& gRollupListener
) gRollupListener
->Rollup(nsnull
);
657 if( we
->event_state
== Ph_WM_EVSTATE_FOCUSLOST
) {
658 /* rollup the menus */
659 if( gRollupWidget
&& gRollupListener
) gRollupListener
->Rollup(nsnull
);
661 if( sFocusWidget
) sFocusWidget
->DispatchStandardEvent(NS_DEACTIVATE
);
669 void nsWindow::RawDrawFunc( PtWidget_t
* pWidget
, PhTile_t
* damage
)
671 nsWindow
* pWin
= (nsWindow
*) GetInstance( pWidget
);
673 PhTile_t
* dmg
= NULL
;
674 nsPaintEvent
pev(PR_TRUE
, 0, nsnull
);
677 if( !pWin
|| !pWin
->mContext
) return;
679 if ( pWin
->mEventCallback
) {
683 // Ok... The damage rect is in window coordinates and is not neccessarily clipped to
684 // the widgets canvas. Mozilla wants the paint coords relative to the parent widget, not the window.
685 PtWidgetExtent(pWidget
, &extent
);
686 PtWidgetOffset(pWidget
, &offset
);
687 /* Build a List of Tiles that might be in front of me.... */
688 PhTile_t
*new_damage
, *clip_tiles
, *intersect
;
689 /* Intersect the Damage tile list w/ the clipped out list and see what's left! */
690 new_damage
= PhRectsToTiles(&damage
->rect
, 1);
691 PhDeTranslateTiles(new_damage
, &offset
);
692 clip_tiles
= GetWindowClipping( pWidget
);
694 new_damage
= PhClipTilings( new_damage
, clip_tiles
, NULL
);
695 PhFreeTiles(clip_tiles
);
697 clip_tiles
= PhRectsToTiles(&extent
, 1);
698 intersect
= PhIntersectTilings( new_damage
, clip_tiles
, NULL
);
699 if ( intersect
== NULL
) return;
700 PhDeTranslateTiles(intersect
, &extent
.ul
);
701 PhFreeTiles(clip_tiles
);
702 PhFreeTiles(new_damage
);
703 new_damage
= intersect
;
705 pWin
->InitEvent(pev
, NS_PAINT
);
707 pev
.renderingContext
= nsnull
;
708 pev
.renderingContext
= pWin
->GetRenderingContext();
709 for( dmg
= new_damage
; dmg
; dmg
= dmg
->next
) {
710 nsDmg
.x
= dmg
->rect
.ul
.x
;
711 nsDmg
.y
= dmg
->rect
.ul
.y
;
712 nsDmg
.width
= dmg
->rect
.lr
.x
- dmg
->rect
.ul
.x
+ 1;
713 nsDmg
.height
= dmg
->rect
.lr
.y
- dmg
->rect
.ul
.y
+ 1;
715 if( (nsDmg
.width
<= 0 ) || (nsDmg
.height
<= 0 ) ) /* Move to the next Damage Tile */
718 /* Re-Setup Paint Event */
719 pWin
->InitEvent(pev
, NS_PAINT
);
720 pev
.refPoint
.x
= nsDmg
.x
;
721 pev
.refPoint
.y
= nsDmg
.y
;
725 if( pev
.renderingContext
) {
726 nsIRegion
*ClipRegion
= pWin
->GetRegion( );
727 ClipRegion
->SetTo( nsDmg
.x
, nsDmg
.y
, nsDmg
.width
, nsDmg
.height
);
728 pev
.renderingContext
->SetClipRegion( static_cast<const nsIRegion
&>(*(ClipRegion
)), nsClipCombine_kReplace
);
730 NS_RELEASE( ClipRegion
);
732 /* You can turn off most drawing if you take this out */
733 result
= pWin
->DispatchWindowEvent(&pev
);
736 NS_RELEASE(pev
.renderingContext
);
737 PhFreeTiles( new_damage
);
741 static PhTile_t
*GetWindowClipping( PtWidget_t
*aWidget
) {
743 PhTile_t
*clip_tiles
= NULL
, *last
= NULL
;
746 PtWidgetExtent( aWidget
, &w_extent
);
748 for( w
= PtWidgetChildFront( aWidget
); w
; w
=PtWidgetBrotherBehind( w
) ) {
749 long flags
= PtWidgetFlags( w
);
750 if( (flags
& Pt_REALIZED
) && (flags
& Pt_OPAQUE
) && !PtIsDisjoint(w
) ) {
751 PhTile_t
*tile
= PhGetTile( );
752 if( !tile
) return NULL
;
754 tile
->rect
.ul
.x
= w
->area
.pos
.x
+ w_extent
.ul
.x
;
755 tile
->rect
.ul
.y
= w
->area
.pos
.y
+ w_extent
.ul
.y
;
756 tile
->rect
.lr
.x
= tile
->rect
.ul
.x
+ w
->area
.size
.w
- 1;
757 tile
->rect
.lr
.y
= tile
->rect
.ul
.y
+ w
->area
.size
.h
- 1;
760 if( !clip_tiles
) clip_tiles
= tile
;
761 if( last
) last
->next
= tile
;
768 int nsWindow::ResizeHandler( PtWidget_t
*widget
, void *data
, PtCallbackInfo_t
*cbinfo
)
770 nsWindow
*someWindow
= (nsWindow
*) GetInstance(widget
);
772 PtContainerCallback_t
*cb
= (PtContainerCallback_t
*) cbinfo
->cbdata
;
773 PhRect_t
*extents
= &cb
->new_size
;
775 rect
.x
= extents
->ul
.x
;
776 rect
.y
= extents
->ul
.y
;
777 rect
.width
= extents
->lr
.x
- rect
.x
+ 1;
778 rect
.height
= extents
->lr
.y
- rect
.y
+ 1;
780 if( someWindow
->mBounds
.width
== rect
.width
&& someWindow
->mBounds
.height
== rect
.height
)
783 someWindow
->mBounds
.width
= rect
.width
;
784 someWindow
->mBounds
.height
= rect
.height
;
786 /* This enables the resize holdoff */
787 if( PtWidgetIsRealized( widget
) ) someWindow
->OnResize( rect
);
793 /* catch an Ph_EV_INFO event when the graphics mode has changed */
794 int nsWindow::EvInfo( PtWidget_t
*widget
, void *data
, PtCallbackInfo_t
*cbinfo
) {
796 if( cbinfo
->event
&& cbinfo
->event
->type
== Ph_EV_INFO
&& cbinfo
->event
->subtype
== Ph_OFFSCREEN_INVALID
) {
799 nsCOMPtr
<nsIPrefBranch
> pPrefs
= do_GetService(NS_PREFSERVICE_CONTRACTID
, &rv
);
800 if (NS_SUCCEEDED(rv
)) {
801 PRBool displayInternalChange
= PR_FALSE
;
802 pPrefs
->GetBoolPref("browser.display.internaluse.graphics_changed", &displayInternalChange
);
803 pPrefs
->SetBoolPref("browser.display.internaluse.graphics_changed", !displayInternalChange
);
805 nsCOMPtr
<nsIWindowMediator
> windowMediator(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID
));
806 NS_ENSURE_TRUE(windowMediator
, NS_ERROR_FAILURE
);
808 nsCOMPtr
<nsISimpleEnumerator
> windowEnumerator
;
809 NS_ENSURE_SUCCESS(windowMediator
->GetXULWindowEnumerator(nsnull
, getter_AddRefs(windowEnumerator
)), NS_ERROR_FAILURE
);
812 windowEnumerator
->HasMoreElements(&more
);
814 nsCOMPtr
<nsISupports
> nextWindow
= nsnull
;
815 windowEnumerator
->GetNext(getter_AddRefs(nextWindow
));
816 nsCOMPtr
<nsIXULWindow
> xulWindow(do_QueryInterface(nextWindow
));
817 NS_ENSURE_TRUE(xulWindow
, NS_ERROR_FAILURE
);
819 nsCOMPtr
<nsIDocShell
> docShell
;
820 xulWindow
->GetDocShell(getter_AddRefs(docShell
));
822 nsCOMPtr
<nsIPresShell
> presShell
;
823 docShell
->GetPresShell( getter_AddRefs(presShell
) );
825 nsIViewManager
* viewManager
= presShell
->GetViewManager();
826 NS_ENSURE_TRUE(viewManager
, NS_ERROR_FAILURE
);
828 windowEnumerator
->HasMoreElements(&more
);
831 PtDamageWidget( widget
);
836 //-------------------------------------------------------------------------
838 // Move this component
840 //-------------------------------------------------------------------------
841 NS_METHOD
nsWindow::Move( PRInt32 aX
, PRInt32 aY
) {
843 if( mWindowType
!= eWindowType_popup
&& (mBounds
.x
== aX
) && (mBounds
.y
== aY
) )
849 switch( mWindowType
) {
850 case eWindowType_popup
:
852 PhPoint_t offset
, total_offset
= { 0, 0 };
854 PtWidget_t
*parent
, *disjoint
= PtFindDisjoint( mWidget
->parent
);
857 PtGetAbsPosition( disjoint
, &offset
.x
, &offset
.y
);
858 total_offset
.x
+= offset
.x
;
859 total_offset
.y
+= offset
.y
;
860 if( PtWidgetIsClass( disjoint
, PtWindow
) || PtWidgetIsClass( disjoint
, PtServer
) ) break; /* Stop at the first PtWindow */
861 parent
= PtWidgetParent(disjoint
);
862 if( parent
) disjoint
= PtFindDisjoint( parent
);
869 aX
+= total_offset
.x
;
870 aY
+= total_offset
.y
;
872 /* Add the Offset if the widget is offset from its parent.. */
873 PtWidgetOffset( mWidget
->parent
, &offset
);
879 case eWindowType_dialog
:
880 case eWindowType_toplevel
:
881 /* Offset to the current virtual console */
883 aX
+= gConsoleRect
.ul
.x
;
884 aY
+= gConsoleRect
.ul
.y
;
889 if(( mWidget
->area
.pos
.x
!= aX
) || ( mWidget
->area
.pos
.y
!= aY
)) {
890 PhPoint_t pos
= { aX
, aY
};
891 PtSetResource( mWidget
, Pt_ARG_POS
, &pos
, 0 );
893 /* ATENTIE Remove when wojtek fixes PR:22930 in the photon library */
894 if( PtWidgetClass( mWidget
) == PtRegion
) PtSetResource( mWidget
, Pt_ARG_REGION_OPAQUE
, 0, Ph_EV_KEY
);
901 int nsWindow::MenuRegionCallback( PtWidget_t
*widget
, void *data
, PtCallbackInfo_t
*cbinfo
) {
902 if( gRollupWidget
&& gRollupListener
) {
903 /* rollup the menu */
904 gRollupListener
->Rollup(nsnull
);
909 NS_IMETHODIMP
nsWindow::SetModal( PRBool aModal
) {
910 nsresult res
= NS_ERROR_FAILURE
;
913 return NS_ERROR_FAILURE
;
915 PtWidget_t
*toplevel
= PtFindDisjoint(mWidget
);
916 if( !toplevel
) return NS_ERROR_FAILURE
;
931 inline nsIRegion
*nsWindow::GetRegion()
933 nsIRegion
*region
= NULL
;
936 static NS_DEFINE_CID(kRegionCID
, NS_REGION_CID
);
938 res
= CallCreateInstance( kRegionCID
, ®ion
);
939 if (NS_SUCCEEDED(res
)) region
->Init();
941 NS_ASSERTION(NULL
!= region
, "Null region context");
947 widget is a PtRegion representing the native widget for a menu - reset the mParent->mLastMenu
948 since it points to an widget being destroyed
950 int nsWindow::MenuRegionDestroyed( PtWidget_t
*widget
, void *data
, PtCallbackInfo_t
*cbinfo
)
952 nsWindow
*pWin
= (nsWindow
*) GetInstance( widget
);
954 nsWindow
*parent
= ( nsWindow
* ) pWin
->mParent
;
955 if( parent
&& parent
->mLastMenu
== widget
)
956 parent
->mLastMenu
= nsnull
;
961 NS_IMETHODIMP
nsWindow::SetFocus(PRBool aRaise
)
965 if( PtIsFocused( mWidget
) == 2 ) return NS_OK
;
968 PtWidget_t
*disjoint
;
969 disjoint
= PtFindDisjoint( mWidget
);
970 if( PtWidgetIsClass( disjoint
, PtWindow
) ) {
971 if( !( PtWindowGetState( disjoint
) & Ph_WM_STATE_ISFOCUS
) ) {
972 nsWindow
*pWin
= (nsWindow
*) GetInstance( disjoint
);
973 pWin
->GetAttention( -1 );
976 PtContainerGiveFocus( mWidget
, NULL
);
981 NS_IMETHODIMP
nsWindow::MakeFullScreen(PRBool aFullScreen
)
983 /* we can use static data here because there can be only one full-screen window at a time */
984 static unsigned short old_render_flags
;
985 static PhPoint_t old_pos
;
990 unsigned short p
, *pflags
;
993 PtSetArg( &args
[0], Pt_ARG_WINDOW_RENDER_FLAGS
, &pflags
, 0 );
994 PtGetResources( mWidget
, 1, args
);
995 p
= old_render_flags
= *pflags
; // save the render flags
996 p
&= ~(Ph_WM_RENDER_TITLE
|Ph_WM_RENDER_BORDER
);
998 PtWidgetArea( mWidget
, &area
);
1002 PtSetArg( &args
[0], Pt_ARG_POS
, &gConsoleRect
.ul
, 0 );
1003 PtSetArg( &args
[1], Pt_ARG_WINDOW_RENDER_FLAGS
, p
, -1 );
1004 PtSetArg( &args
[2], Pt_ARG_WINDOW_STATE
, Ph_WM_STATE_ISFRONT
, Ph_WM_STATE_ISFRONT
);
1005 PtSetResources( mWidget
, 3, args
);
1008 PtSetArg( &args
[0], Pt_ARG_POS
, &old_pos
, 0 );
1009 PtSetArg( &args
[1], Pt_ARG_WINDOW_RENDER_FLAGS
, old_render_flags
, -1 ); /* restore the render flags to the previous value */
1010 PtSetArg( &args
[2], Pt_ARG_WINDOW_STATE
, Ph_WM_STATE_ISNORMAL
, Ph_WM_STATE_ISFRONT
|Ph_WM_STATE_ISNORMAL
);
1011 PtSetResources( mWidget
, 3, args
);
1014 return nsBaseWidget::MakeFullScreen( aFullScreen
);