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 * Michael.Kedl@Nexwarecorp.com
25 * Dale.Stansberry@Nexwarecorop.com
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.
39 * ***** END LICENSE BLOCK ***** */
44 #include "nsIAppShell.h"
45 #include "nsIComponentManager.h"
46 #include "nsIDeviceContext.h"
47 #include "nsIFontMetrics.h"
48 #include "nsILookAndFeel.h"
49 #include "nsToolkit.h"
50 #include "nsWidgetsCID.h"
51 #include "nsGfxCIID.h"
53 #include "PtRawDrawContainer.h"
54 #include "nsIRollupListener.h"
55 #include "nsIServiceManager.h"
58 #include "nsDragService.h"
60 #include "nsReadableUtils.h"
62 #include "nsClipboard.h"
65 #include <photon/PtServer.h>
67 static NS_DEFINE_CID(kLookAndFeelCID
, NS_LOOKANDFEEL_CID
);
68 static NS_DEFINE_CID(kCClipboardCID
, NS_CLIPBOARD_CID
);
70 // BGR, not RGB - REVISIT
71 #define NSCOLOR_TO_PHCOLOR(g,n) \
73 g.green=NS_GET_G(n); \
76 ////////////////////////////////////////////////////////////////////
78 // Define and Initialize global variables
80 ////////////////////////////////////////////////////////////////////
84 // Keep track of the last widget being "dragged"
86 nsILookAndFeel
*nsWidget::sLookAndFeel
= nsnull
;
88 nsIDragService
*nsWidget::sDragService
= nsnull
;
90 nsClipboard
*nsWidget::sClipboard
= nsnull
;
91 PRUint32
nsWidget::sWidgetCount
= 0;
92 nsWidget
* nsWidget::sFocusWidget
= 0;
97 CallGetService(kLookAndFeelCID
, &sLookAndFeel
);
101 sLookAndFeel
->GetColor( nsILookAndFeel::eColor_WindowBackground
, mBackground
);
104 if( !sDragService
) {
106 nsCOMPtr
<nsIDragService
> s
;
107 s
= do_GetService( "@mozilla.org/widget/dragservice;1", &rv
);
108 sDragService
= ( nsIDragService
* ) s
;
109 if( NS_FAILED( rv
) ) sDragService
= 0;
115 nsCOMPtr
<nsClipboard
> s
;
116 s
= do_GetService( kCClipboardCID
, &rv
);
117 sClipboard
= ( nsClipboard
* ) s
;
118 if( NS_FAILED( rv
) ) sClipboard
= 0;
124 mPreferredHeight
= 0;
130 mIsDestroying
= PR_FALSE
;
131 mOnDestroyCalled
= PR_FALSE
;
132 mIsToplevel
= PR_FALSE
;
133 mListenForResizes
= PR_FALSE
;
138 nsWidget::~nsWidget( ) {
140 if( sFocusWidget
== this ) sFocusWidget
= 0;
142 // it's safe to always call Destroy() because it will only allow itself to be called once
145 if( !sWidgetCount
-- ) {
146 NS_IF_RELEASE( sLookAndFeel
);
150 //-------------------------------------------------------------------------
154 //-------------------------------------------------------------------------
155 NS_IMPL_ISUPPORTS_INHERITED0(nsWidget
, nsBaseWidget
)
157 NS_METHOD
nsWidget::WidgetToScreen( const nsRect
& aOldRect
, nsRect
& aNewRect
) {
159 /* This is NOT correct */
160 aNewRect
.x
= aOldRect
.x
;
161 aNewRect
.y
= aOldRect
.y
;
166 // nsWidget::ScreenToWidget - Not Implemented
167 NS_METHOD
nsWidget::ScreenToWidget( const nsRect
& aOldRect
, nsRect
& aNewRect
) {
171 //-------------------------------------------------------------------------
173 // Close this nsWidget
175 //-------------------------------------------------------------------------
177 NS_IMETHODIMP
nsWidget::Destroy( void ) {
179 // make sure we don't call this more than once.
180 if( mIsDestroying
) return NS_OK
;
183 mIsDestroying
= PR_TRUE
;
185 // call in and clean up any of our base widget resources
187 nsBaseWidget::Destroy();
189 // destroy our native windows
192 // make sure to call the OnDestroy if it hasn't been called yet
193 if( mOnDestroyCalled
== PR_FALSE
) OnDestroy();
195 // make sure no callbacks happen
196 mEventCallback
= nsnull
;
201 // this is the function that will destroy the native windows for this widget.
204 void nsWidget::DestroyNative( void ) {
206 // prevent the widget from causing additional events
207 mEventCallback
= nsnull
;
208 //EnableDamage( mWidget, PR_FALSE );
209 PtDestroyWidget( mWidget
);
210 //EnableDamage( mWidget, PR_TRUE );
215 // make sure that we clean up here
217 void nsWidget::OnDestroy( ) {
218 mOnDestroyCalled
= PR_TRUE
;
219 // release references to children, device context, toolkit + app shell
220 nsBaseWidget::OnDestroy();
221 DispatchStandardEvent(NS_DESTROY
);
224 //-------------------------------------------------------------------------
226 // Hide or show this component
228 //-------------------------------------------------------------------------
230 NS_METHOD
nsWidget::Show( PRBool bState
) {
232 if( !mWidget
) return NS_OK
; // Will be null durring printing
238 if( mWindowType
!= eWindowType_child
) {
240 if (PtWidgetIsRealized(mWidget
)) {
245 //EnableDamage( mWidget, PR_FALSE );
246 PtRealizeWidget(mWidget
);
248 if( mWidget
->rid
== -1 ) {
249 //EnableDamage( mWidget, PR_TRUE );
250 NS_ASSERTION(0,"nsWidget::Show mWidget's rid == -1\n");
252 return NS_ERROR_FAILURE
;
255 PtSetArg(&arg
, Pt_ARG_FLAGS
, 0, Pt_DELAY_REALIZE
);
256 PtSetResources(mWidget
, 1, &arg
);
257 //EnableDamage( mWidget, PR_TRUE );
258 PtDamageWidget(mWidget
);
259 #ifdef Ph_REGION_NOTIFY
262 mWgt
= (PtWidget_t
*) GetNativeData( NS_NATIVE_WIDGET
);
263 region
.flags
= Ph_REGION_NOTIFY
| Ph_FORCE_BOUNDARY
;
264 region
.rid
= PtWidgetRid(mWgt
);
265 PhRegionChange(Ph_REGION_FLAGS
, 0, ®ion
, NULL
, NULL
);
269 PtWidgetToFront( mWidget
);
270 if( !mShown
|| !( mWidget
->flags
& Pt_REALIZED
) ) PtRealizeWidget( mWidget
);
274 if( mWindowType
!= eWindowType_child
) {
275 //EnableDamage( mWidget, PR_FALSE );
276 PtUnrealizeWidget(mWidget
);
278 //EnableDamage( mWidget, PR_TRUE );
280 PtSetArg(&arg
, Pt_ARG_FLAGS
, Pt_DELAY_REALIZE
, Pt_DELAY_REALIZE
);
281 PtSetResources(mWidget
, 1, &arg
);
284 //EnableDamage( mWidget, PR_FALSE );
285 PtWidgetToBack( mWidget
);
286 if( mShown
) PtUnrealizeWidget( mWidget
);
287 //EnableDamage( mWidget, PR_TRUE );
296 // nsWidget::SetModal - Not Implemented
297 NS_IMETHODIMP
nsWidget::SetModal( PRBool aModal
) {
298 return NS_ERROR_FAILURE
;
301 //-------------------------------------------------------------------------
303 // Move this component
305 //-------------------------------------------------------------------------
306 NS_METHOD
nsWidget::Move( PRInt32 aX
, PRInt32 aY
) {
308 if( ( mBounds
.x
== aX
) && ( mBounds
.y
== aY
) ) return NS_OK
;
314 if(( mWidget
->area
.pos
.x
!= aX
) || ( mWidget
->area
.pos
.y
!= aY
)) {
315 PhPoint_t pos
= { aX
, aY
};
316 PtSetResource( mWidget
, Pt_ARG_POS
, &pos
, 0 );
323 NS_METHOD
nsWidget::Resize( PRInt32 aWidth
, PRInt32 aHeight
, PRBool aRepaint
) {
325 if( ( mBounds
.width
== aWidth
) && ( mBounds
.height
== aHeight
) )
328 mBounds
.width
= aWidth
;
329 mBounds
.height
= aHeight
;
332 PhDim_t dim
= { aWidth
, aHeight
};
333 //EnableDamage( mWidget, PR_FALSE );
334 PtSetResource( mWidget
, Pt_ARG_DIM
, &dim
, 0 );
335 //EnableDamage( mWidget, PR_TRUE );
342 //-------------------------------------------------------------------------
344 // Send a resize message to the listener
346 //-------------------------------------------------------------------------
347 PRBool
nsWidget::OnResize( nsRect
&aRect
) {
349 PRBool result
= PR_FALSE
;
351 // call the event callback
352 if( mEventCallback
) {
353 nsSizeEvent
event(PR_TRUE
, 0, nsnull
);
355 InitEvent(event
, NS_SIZE
);
357 nsRect
*foo
= new nsRect(0, 0, aRect
.width
, aRect
.height
);
358 event
.windowSize
= foo
;
360 event
.refPoint
.x
= 0;
361 event
.refPoint
.y
= 0;
362 event
.mWinWidth
= aRect
.width
;
363 event
.mWinHeight
= aRect
.height
;
366 result
= DispatchWindowEvent(&event
);
377 PRBool
nsWidget::OnMove( PRInt32 aX
, PRInt32 aY
) {
378 nsGUIEvent
event(PR_TRUE
, 0, nsnull
);
379 InitEvent(event
, NS_MOVE
);
380 event
.refPoint
.x
= aX
;
381 event
.refPoint
.y
= aY
;
382 return DispatchWindowEvent(&event
);
386 //-------------------------------------------------------------------------
388 // Set this component font
390 //-------------------------------------------------------------------------
391 NS_METHOD
nsWidget::SetFont( const nsFont
&aFont
) {
393 nsIFontMetrics
* mFontMetrics
;
394 mContext
->GetMetricsFor(aFont
, mFontMetrics
);
399 nsFontHandle aFontHandle
;
400 mFontMetrics
->GetFontHandle(aFontHandle
);
402 aString
= (nsString
*) aFontHandle
;
403 char *str
= ToNewCString(*aString
);
405 PtSetArg( &arg
, Pt_ARG_TEXT_FONT
, str
, 0 );
406 PtSetResources( mWidget
, 1, &arg
);
409 NS_RELEASE(mFontMetrics
);
414 //-------------------------------------------------------------------------
416 // Set this component cursor
418 //-------------------------------------------------------------------------
419 NS_METHOD
nsWidget::SetCursor( nsCursor aCursor
) {
421 // Only change cursor if it's changing
422 if( aCursor
!= mCursor
) {
424 unsigned short curs
= Ph_CURSOR_POINTER
;
425 PgColor_t color
= Ph_CURSOR_DEFAULT_COLOR
;
428 case eCursor_nw_resize
:
429 curs
= Ph_CURSOR_DRAG_TL
;
431 case eCursor_se_resize
:
432 curs
= Ph_CURSOR_DRAG_BR
;
434 case eCursor_ne_resize
:
435 curs
= Ph_CURSOR_DRAG_TL
;
437 case eCursor_sw_resize
:
438 curs
= Ph_CURSOR_DRAG_BL
;
441 case eCursor_crosshair
:
442 curs
= Ph_CURSOR_CROSSHAIR
;
447 case eCursor_context_menu
:
448 // XXX: No suitable cursor, needs implementing
452 // XXX: No suitable cursor, needs implementing
455 case eCursor_spinning
:
456 // XXX: No suitable cursor, needs implementing
460 curs
= Ph_CURSOR_MOVE
;
464 curs
= Ph_CURSOR_QUESTION_POINT
;
468 case eCursor_grabbing
:
469 curs
= Ph_CURSOR_FINGER
;
473 curs
= Ph_CURSOR_INSERT
;
478 curs
= Ph_CURSOR_LONG_WAIT
;
481 case eCursor_hyperlink
:
482 curs
= Ph_CURSOR_FINGER
;
485 case eCursor_standard
:
486 curs
= Ph_CURSOR_POINTER
;
489 case eCursor_n_resize
:
490 case eCursor_s_resize
:
491 curs
= Ph_CURSOR_DRAG_VERTICAL
;
494 case eCursor_w_resize
:
495 case eCursor_e_resize
:
496 curs
= Ph_CURSOR_DRAG_HORIZONTAL
;
499 case eCursor_zoom_in
:
500 case eCursor_zoom_out
:
501 // XXX: No suitable cursor, needs implementing
504 case eCursor_not_allowed
:
505 case eCursor_no_drop
:
506 curs
= Ph_CURSOR_DONT
;
509 case eCursor_col_resize
:
510 // XXX: not 100% appropriate perhaps
511 curs
= Ph_CURSOR_DRAG_HORIZONTAL
;
514 case eCursor_row_resize
:
515 // XXX: not 100% appropriate perhaps
516 curs
= Ph_CURSOR_DRAG_VERTICAL
;
519 case eCursor_vertical_text
:
520 curs
= Ph_CURSOR_INSERT
;
524 case eCursor_all_scroll
:
525 // XXX: No suitable cursor, needs implementing
528 case eCursor_nesw_resize
:
529 curs
= Ph_CURSOR_DRAG_FOREDIAG
;
532 case eCursor_nwse_resize
:
533 curs
= Ph_CURSOR_DRAG_BACKDIAG
;
536 case eCursor_ns_resize
:
537 curs
= Ph_CURSOR_DRAG_VERTICAL
;
540 case eCursor_ew_resize
:
541 curs
= Ph_CURSOR_DRAG_HORIZONTAL
;
545 // XXX: No suitable cursor, needs implementing
549 NS_ASSERTION(0, "Invalid cursor type");
556 PtSetArg( &args
[0], Pt_ARG_CURSOR_TYPE
, curs
, 0 );
557 PtSetArg( &args
[1], Pt_ARG_CURSOR_COLOR
, color
, 0 );
558 PtSetResources( mWidget
, 2, args
);
567 NS_METHOD
nsWidget::Invalidate( PRBool aIsSynchronous
) {
569 // mWidget will be null during printing
570 if( !mWidget
|| !PtWidgetIsRealized( mWidget
) ) return NS_OK
;
572 PtWidget_t
*aWidget
= (PtWidget_t
*)GetNativeData(NS_NATIVE_WIDGET
);
573 PtDamageWidget( aWidget
);
574 if( aIsSynchronous
) PtFlush();
578 NS_METHOD
nsWidget::Invalidate( const nsRect
& aRect
, PRBool aIsSynchronous
) {
580 if( !mWidget
) return NS_OK
; // mWidget will be null during printing
581 if( !PtWidgetIsRealized( mWidget
) ) return NS_OK
;
584 prect
.ul
.x
= aRect
.x
;
585 prect
.ul
.y
= aRect
.y
;
586 prect
.lr
.x
= prect
.ul
.x
+ aRect
.width
- 1;
587 prect
.lr
.y
= prect
.ul
.y
+ aRect
.height
- 1;
588 if( ! ( mWidget
->class_rec
->flags
& Pt_DISJOINT
) )
589 PhTranslateRect( &prect
, &mWidget
->area
.pos
);
590 PtDamageExtent( mWidget
, &prect
);
591 if( aIsSynchronous
) PtFlush( );
595 NS_IMETHODIMP
nsWidget::InvalidateRegion( const nsIRegion
*aRegion
, PRBool aIsSynchronous
) {
596 PhTile_t
*tiles
= NULL
;
597 aRegion
->GetNativeRegion( ( void*& ) tiles
);
599 PhTranslateTiles( tiles
, &mWidget
->area
.pos
);
600 PtDamageTiles( mWidget
, tiles
);
601 if( aIsSynchronous
) PtFlush( );
606 nsresult
nsWidget::CreateWidget(nsIWidget
*aParent
,
608 EVENT_CALLBACK aHandleEventFunction
,
609 nsIDeviceContext
*aContext
,
610 nsIAppShell
*aAppShell
,
611 nsIToolkit
*aToolkit
,
612 nsWidgetInitData
*aInitData
,
613 nsNativeWidget aNativeParent
)
616 PtWidget_t
*parentWidget
= nsnull
;
620 if( aNativeParent
) {
621 parentWidget
= (PtWidget_t
*)aNativeParent
;
622 // we've got a native parent so listen for resizes
623 mListenForResizes
= PR_TRUE
;
626 parentWidget
= (PtWidget_t
*) (aParent
->GetNativeData(NS_NATIVE_WIDGET
));
627 mListenForResizes
= aInitData
? aInitData
->mListenForResizes
: PR_FALSE
;
630 if( aInitData
->mWindowType
== eWindowType_child
&& !parentWidget
) return NS_ERROR_FAILURE
;
632 nsIWidget
*baseParent
= aInitData
&&
633 (aInitData
->mWindowType
== eWindowType_dialog
||
634 aInitData
->mWindowType
== eWindowType_toplevel
||
635 aInitData
->mWindowType
== eWindowType_invisible
) ?
638 BaseCreate( baseParent
, aRect
, aHandleEventFunction
, aContext
, aAppShell
, aToolkit
, aInitData
);
643 CreateNative (parentWidget
);
645 if( aRect
.width
> 1 && aRect
.height
> 1 ) Resize(aRect
.width
, aRect
.height
, PR_FALSE
);
648 SetInstance(mWidget
, this);
649 PtAddCallback( mWidget
, Pt_CB_GOT_FOCUS
, GotFocusCallback
, this );
650 PtAddCallback( mWidget
, Pt_CB_LOST_FOCUS
, LostFocusCallback
, this );
651 PtAddCallback( mWidget
, Pt_CB_IS_DESTROYED
, DestroyedCallback
, this );
653 PtAddCallback( mWidget
, Pt_CB_DND
, DndCallback
, this );
657 DispatchStandardEvent(NS_CREATE
);
663 //-------------------------------------------------------------------------
665 // Invokes callback and ProcessEvent method on Event Listener object
667 //-------------------------------------------------------------------------
669 NS_IMETHODIMP
nsWidget::DispatchEvent( nsGUIEvent
*aEvent
, nsEventStatus
&aStatus
) {
671 NS_ADDREF(aEvent
->widget
);
673 if( nsnull
!= mMenuListener
) {
674 if( NS_MENU_EVENT
== aEvent
->eventStructType
)
675 aStatus
= mMenuListener
->MenuSelected(static_cast<nsMenuEvent
&>(*aEvent
));
678 aStatus
= nsEventStatus_eIgnore
;
680 ///* ATENTIE */ printf( "mEventCallback call (%d %d) this=%p\n", aEvent->point.x, aEvent->point.y, this );
682 if( nsnull
!= mEventCallback
) aStatus
= (*mEventCallback
)(aEvent
);
684 // Dispatch to event listener if event was not consumed
685 if( (aStatus
!= nsEventStatus_eIgnore
) && (nsnull
!= mEventListener
) )
686 aStatus
= mEventListener
->ProcessEvent(*aEvent
);
688 NS_IF_RELEASE(aEvent
->widget
);
693 //==============================================================
694 void nsWidget::InitMouseEvent(PhPointerEvent_t
*aPhButtonEvent
,
696 nsMouseEvent
&anEvent
,
700 anEvent
.message
= aEventType
;
701 anEvent
.widget
= aWidget
;
703 if (aPhButtonEvent
!= nsnull
) {
704 anEvent
.time
= PR_IntervalNow();
705 anEvent
.isShift
= ( aPhButtonEvent
->key_mods
& Pk_KM_Shift
) ? PR_TRUE
: PR_FALSE
;
706 anEvent
.isControl
= ( aPhButtonEvent
->key_mods
& Pk_KM_Ctrl
) ? PR_TRUE
: PR_FALSE
;
707 anEvent
.isAlt
= ( aPhButtonEvent
->key_mods
& Pk_KM_Alt
) ? PR_TRUE
: PR_FALSE
;
708 anEvent
.isMeta
= PR_FALSE
;
709 anEvent
.refPoint
.x
= aPhButtonEvent
->pos
.x
;
710 anEvent
.refPoint
.y
= aPhButtonEvent
->pos
.y
;
711 anEvent
.clickCount
= aPhButtonEvent
->click_count
;
712 anEvent
.button
= aButton
;
716 //-------------------------------------------------------------------------
718 // Deal with all sort of mouse event
720 //-------------------------------------------------------------------------
721 PRBool
nsWidget::DispatchMouseEvent( nsMouseEvent
& aEvent
) {
723 PRBool result
= PR_FALSE
;
725 // call the event callback
726 if (nsnull
!= mEventCallback
) {
727 result
= DispatchWindowEvent(&aEvent
);
734 struct nsKeyConverter
{
735 PRUint32 vkCode
; // Platform independent key code
736 unsigned long keysym
; // Photon key_sym key code
739 static struct nsKeyConverter nsKeycodes
[] = {
740 { NS_VK_PAGE_UP
, Pk_Pg_Up
},
741 { NS_VK_PAGE_DOWN
, Pk_Pg_Down
},
743 { NS_VK_DOWN
, Pk_Down
},
744 { NS_VK_TAB
, Pk_Tab
},
745 { NS_VK_TAB
, Pk_KP_Tab
},
746 { NS_VK_HOME
, Pk_Home
},
747 { NS_VK_END
, Pk_End
},
748 { NS_VK_LEFT
, Pk_Left
},
749 { NS_VK_RIGHT
, Pk_Right
},
750 { NS_VK_DELETE
, Pk_Delete
},
751 { NS_VK_CANCEL
, Pk_Cancel
},
752 { NS_VK_BACK
, Pk_BackSpace
},
753 { NS_VK_CLEAR
, Pk_Clear
},
754 { NS_VK_RETURN
, Pk_Return
},
755 { NS_VK_SHIFT
, Pk_Shift_L
},
756 { NS_VK_SHIFT
, Pk_Shift_R
},
757 { NS_VK_CONTROL
, Pk_Control_L
},
758 { NS_VK_CONTROL
, Pk_Control_R
},
759 { NS_VK_ALT
, Pk_Alt_L
},
760 { NS_VK_ALT
, Pk_Alt_R
},
761 { NS_VK_INSERT
, Pk_Insert
},
762 { NS_VK_PAUSE
, Pk_Pause
},
763 { NS_VK_CAPS_LOCK
, Pk_Caps_Lock
},
764 { NS_VK_ESCAPE
, Pk_Escape
},
765 { NS_VK_PRINTSCREEN
,Pk_Print
},
766 { NS_VK_RETURN
, Pk_KP_Enter
},
767 { NS_VK_INSERT
, Pk_KP_0
},
768 { NS_VK_END
, Pk_KP_1
},
769 { NS_VK_DOWN
, Pk_KP_2
},
770 { NS_VK_PAGE_DOWN
, Pk_KP_3
},
771 { NS_VK_LEFT
, Pk_KP_4
},
772 { NS_VK_NUMPAD5
, Pk_KP_5
},
773 { NS_VK_RIGHT
, Pk_KP_6
},
774 { NS_VK_HOME
, Pk_KP_7
},
775 { NS_VK_UP
, Pk_KP_8
},
776 { NS_VK_PAGE_UP
, Pk_KP_9
},
777 { NS_VK_COMMA
, Pk_KP_Separator
}
781 // Input keysym is in photon format; output is in NS_VK format
782 PRUint32
nsWidget::nsConvertKey( PhKeyEvent_t
*aPhKeyEvent
) {
784 unsigned long keysym
, keymods
;
786 const int length
= sizeof(nsKeycodes
) / sizeof(struct nsKeyConverter
);
788 keymods
= aPhKeyEvent
->key_mods
;
789 if( aPhKeyEvent
->key_flags
& Pk_KF_Sym_Valid
)
790 keysym
= aPhKeyEvent
->key_sym
;
791 else if( aPhKeyEvent
->key_flags
& Pk_KF_Cap_Valid
)
792 keysym
= aPhKeyEvent
->key_cap
;
795 // First, try to handle alphanumeric input, not listed in nsKeycodes:
796 if (keysym
>= Pk_a
&& keysym
<= Pk_z
)
797 return keysym
- Pk_a
+ NS_VK_A
;
799 if (keysym
>= Pk_A
&& keysym
<= Pk_Z
)
800 return keysym
- Pk_A
+ NS_VK_A
;
802 if (keysym
>= Pk_0
&& keysym
<= Pk_9
)
803 return keysym
- Pk_0
+ NS_VK_0
;
805 if (keysym
>= Pk_F1
&& keysym
<= Pk_F24
) {
806 return keysym
- Pk_F1
+ NS_VK_F1
;
809 if( keymods
& Pk_KM_Num_Lock
) {
810 if( keysym
>= Pk_KP_0
&& keysym
<= Pk_KP_9
)
811 return keysym
- Pk_0
+ NS_VK_0
;
814 for (int i
= 0; i
< length
; i
++) {
815 if( nsKeycodes
[i
].keysym
== keysym
) {
816 return (nsKeycodes
[i
].vkCode
);
823 PRBool
nsWidget::DispatchKeyEvent( PhKeyEvent_t
*aPhKeyEvent
) {
824 NS_ASSERTION(aPhKeyEvent
, "nsWidget::DispatchKeyEvent a NULL PhKeyEvent was passed in");
826 if( !(aPhKeyEvent
->key_flags
& (Pk_KF_Cap_Valid
|Pk_KF_Sym_Valid
) ) ) {
827 //printf("nsWidget::DispatchKeyEvent throwing away invalid key: Modifiers Valid=<%d,%d,%d> this=<%p>\n",
828 //(aPhKeyEvent->key_flags & Pk_KF_Scan_Valid), (aPhKeyEvent->key_flags & Pk_KF_Sym_Valid), (aPhKeyEvent->key_flags & Pk_KF_Cap_Valid), this );
832 if ( PtIsFocused(mWidget
) != 2) {
833 //printf("nsWidget::DispatchKeyEvent Not on focus leaf! PtIsFocused(mWidget)=<%d>\n", PtIsFocused(mWidget));
837 if ( ( aPhKeyEvent
->key_cap
== Pk_Shift_L
)
838 || ( aPhKeyEvent
->key_cap
== Pk_Shift_R
)
839 || ( aPhKeyEvent
->key_cap
== Pk_Control_L
)
840 || ( aPhKeyEvent
->key_cap
== Pk_Control_R
)
841 || ( aPhKeyEvent
->key_cap
== Pk_Num_Lock
)
842 || ( aPhKeyEvent
->key_cap
== Pk_Scroll_Lock
)
846 nsWindow
*w
= (nsWindow
*) this;
850 if (aPhKeyEvent
->key_flags
& Pk_KF_Key_Down
) {
851 nsKeyEvent
keyDownEvent(PR_TRUE
, NS_KEY_DOWN
, w
);
852 InitKeyEvent(aPhKeyEvent
, keyDownEvent
);
853 PRBool noDefault
= w
->OnKey(keyDownEvent
);
855 nsKeyEvent
keyPressEvent(PR_TRUE
, NS_KEY_PRESS
, w
);
856 InitKeyPressEvent(aPhKeyEvent
, keyPressEvent
);
857 if (noDefault
) { // If prevent default set for keydown, do same for keypress
858 keyPressEvent
.flags
= NS_EVENT_FLAG_NO_DEFAULT
;
860 w
->OnKey(keyPressEvent
);
862 else if (aPhKeyEvent
->key_flags
& Pk_KF_Key_Repeat
) {
863 nsKeyEvent
keyPressEvent(PR_TRUE
, NS_KEY_PRESS
, w
);
864 InitKeyPressEvent(aPhKeyEvent
, keyPressEvent
);
865 w
->OnKey(keyPressEvent
);
867 else if (PkIsKeyDown(aPhKeyEvent
->key_flags
) == 0) {
868 nsKeyEvent
kevent(PR_TRUE
, NS_KEY_UP
, w
);
869 InitKeyEvent(aPhKeyEvent
, kevent
);
878 inline void nsWidget::InitKeyEvent(PhKeyEvent_t
*aPhKeyEvent
, nsKeyEvent
&anEvent
)
880 anEvent
.keyCode
= nsConvertKey( aPhKeyEvent
);
881 anEvent
.time
= PR_IntervalNow();
882 anEvent
.isShift
= ( aPhKeyEvent
->key_mods
& Pk_KM_Shift
) ? PR_TRUE
: PR_FALSE
;
883 anEvent
.isControl
= ( aPhKeyEvent
->key_mods
& Pk_KM_Ctrl
) ? PR_TRUE
: PR_FALSE
;
884 anEvent
.isAlt
= ( aPhKeyEvent
->key_mods
& Pk_KM_Alt
) ? PR_TRUE
: PR_FALSE
;
885 anEvent
.isMeta
= PR_FALSE
;
888 /* similar to PhKeyToMb */
889 inline int key_sym_displayable(const PhKeyEvent_t
*kevent
)
891 if(kevent
->key_flags
& Pk_KF_Sym_Valid
) {
892 unsigned long const sym
= kevent
->key_sym
;
894 ? sym
>= 0xF100 && ( sizeof(wchar_t) > 2 || sym
< 0x10000 )
895 : ( sym
& ~0x9F ) != 0 // exclude 0...0x1F and 0x80...0x9F
901 /* similar to PhKeyToMb */
902 inline int key_cap_displayable(const PhKeyEvent_t
*kevent
)
904 if(kevent
->key_flags
& Pk_KF_Cap_Valid
) {
905 unsigned long const cap
= kevent
->key_cap
;
907 ? cap
>= 0xF100 && ( sizeof(wchar_t) > 2 || cap
< 0x10000 )
908 : ( cap
& ~0x9F ) != 0 // exclude 0...0x1F and 0x80...0x9F
914 inline void nsWidget::InitKeyPressEvent(PhKeyEvent_t
*aPhKeyEvent
, nsKeyEvent
&anEvent
)
916 anEvent
.isShift
= ( aPhKeyEvent
->key_mods
& Pk_KM_Shift
) ? PR_TRUE
: PR_FALSE
;
917 anEvent
.isControl
= ( aPhKeyEvent
->key_mods
& Pk_KM_Ctrl
) ? PR_TRUE
: PR_FALSE
;
918 anEvent
.isAlt
= ( aPhKeyEvent
->key_mods
& Pk_KM_Alt
) ? PR_TRUE
: PR_FALSE
;
919 anEvent
.isMeta
= PR_FALSE
;
921 if( key_sym_displayable( aPhKeyEvent
) ) anEvent
.charCode
= aPhKeyEvent
->key_sym
;
923 /* in photon Ctrl<something> or Alt<something> is not a displayable character, but
924 mozilla wants the keypress event as a charCode+isControl+isAlt, instead of a keyCode */
925 if( ( anEvent
.isControl
|| anEvent
.isAlt
) && key_cap_displayable( aPhKeyEvent
) )
926 anEvent
.charCode
= aPhKeyEvent
->key_cap
;
927 else anEvent
.keyCode
= nsConvertKey( aPhKeyEvent
);
930 anEvent
.time
= PR_IntervalNow();
934 inline PRBool
nsWidget::HandleEvent( PtWidget_t
*widget
, PtCallbackInfo_t
* aCbInfo
) {
935 PRBool result
= PR_TRUE
; // call the default nsWindow proc
936 PhEvent_t
* event
= aCbInfo
->event
;
938 if (event
->processing_flags
& Ph_CONSUMED
) return PR_TRUE
;
940 switch ( event
->type
) {
942 case Ph_EV_PTR_MOTION_NOBUTTON
:
944 PhPointerEvent_t
* ptrev
= (PhPointerEvent_t
*) PhGetData( event
);
945 nsMouseEvent
theMouseEvent(PR_TRUE
, 0, nsnull
, nsMouseEvent::eReal
);
949 if( ptrev
->flags
& Ph_PTR_FLAG_Z_ONLY
) break; // sometimes z presses come out of nowhere */
951 ///* ATENTIE */ printf( "Ph_EV_PTR_MOTION_NOBUTTON (%d %d)\n", ptrev->pos.x, ptrev->pos.y );
953 ScreenToWidgetPos( ptrev
->pos
);
954 InitMouseEvent(ptrev
, this, theMouseEvent
, NS_MOUSE_MOVE
);
955 result
= DispatchMouseEvent(theMouseEvent
);
960 case Ph_EV_BUT_PRESS
:
963 PhPointerEvent_t
* ptrev
= (PhPointerEvent_t
*) PhGetData( event
);
964 nsMouseEvent
theMouseEvent(PR_TRUE
, 0, nsnull
, nsMouseEvent::eReal
);
966 /* there should be no reason to do this - mozilla should figure out how to call SetFocus */
967 /* this though fixes the problem with the plugins capturing the focus */
968 PtWidget_t
*disjoint
= PtFindDisjoint( widget
);
969 if( PtWidgetIsClassMember( disjoint
, PtServer
) )
970 PtContainerGiveFocus( widget
, aCbInfo
->event
);
973 ScreenToWidgetPos( ptrev
->pos
);
975 if( ptrev
->buttons
& Ph_BUTTON_SELECT
) // Normally the left mouse button
976 InitMouseEvent(ptrev
, this, theMouseEvent
, NS_MOUSE_BUTTON_DOWN
,
977 nsMouseEvent::eLeftButton
);
978 else if( ptrev
->buttons
& Ph_BUTTON_MENU
) // the right button
979 InitMouseEvent(ptrev
, this, theMouseEvent
, NS_MOUSE_BUTTON_DOWN
,
980 nsMouseEvent::eRightButton
);
981 else // middle button
982 InitMouseEvent(ptrev
, this, theMouseEvent
, NS_MOUSE_BUTTON_DOWN
,
983 nsMouseEvent::eMiddleButton
);
985 result
= DispatchMouseEvent(theMouseEvent
);
987 // if we're a right-button-up we're trying to popup a context menu. send that event to gecko also
988 if( ptrev
->buttons
& Ph_BUTTON_MENU
) {
989 nsMouseEvent
contextMenuEvent(PR_TRUE
, 0, nsnull
,
990 nsMouseEvent::eReal
);
991 InitMouseEvent(ptrev
, this, contextMenuEvent
, NS_CONTEXTMENU
,
992 nsMouseEvent::eRightButton
);
993 result
= DispatchMouseEvent( contextMenuEvent
);
1000 case Ph_EV_BUT_RELEASE
:
1002 PhPointerEvent_t
* ptrev
= (PhPointerEvent_t
*) PhGetData( event
);
1003 nsMouseEvent
theMouseEvent(PR_TRUE
, 0, nsnull
,
1004 nsMouseEvent::eReal
);
1006 // Update the current input group for clipboard mouse events
1007 // (mozilla only). Note that for mozserver the mouse based
1008 // (eg. Edit->Copy/Paste menu) events don't come through here.
1009 // They are sent by the voyager client app via libPtWeb.so to
1010 // do_command() in mozserver.cpp.
1012 sClipboard
->SetInputGroup(event
->input_group
);
1014 if (event
->subtype
==Ph_EV_RELEASE_REAL
|| event
->subtype
==Ph_EV_RELEASE_PHANTOM
) {
1016 ScreenToWidgetPos( ptrev
->pos
);
1017 if ( ptrev
->buttons
& Ph_BUTTON_SELECT
) // Normally the left mouse button
1018 InitMouseEvent(ptrev
, this, theMouseEvent
, NS_MOUSE_BUTTON_UP
,
1019 nsMouseEvent::eLeftButton
);
1020 else if( ptrev
->buttons
& Ph_BUTTON_MENU
) // the right button
1021 InitMouseEvent(ptrev
, this, theMouseEvent
, NS_MOUSE_BUTTON_UP
,
1022 nsMouseEvent::eRightButton
);
1023 else // middle button
1024 InitMouseEvent(ptrev
, this, theMouseEvent
, NS_MOUSE__BUTTON_UP
,
1025 nsMouseEvent::eMiddleButton
);
1027 result
= DispatchMouseEvent(theMouseEvent
);
1030 else if (event
->subtype
==Ph_EV_RELEASE_OUTBOUND
) {
1031 PhRect_t rect
= {{0,0},{0,0}};
1032 PhRect_t boundary
= {{-10000,-10000},{10000,10000}};
1033 PhInitDrag( PtWidgetRid(mWidget
), ( Ph_DRAG_KEY_MOTION
| Ph_DRAG_TRACK
| Ph_TRACK_DRAG
),&rect
, &boundary
, aCbInfo
->event
->input_group
, NULL
, NULL
, NULL
, NULL
, NULL
);
1038 case Ph_EV_PTR_MOTION_BUTTON
:
1040 PhPointerEvent_t
* ptrev
= (PhPointerEvent_t
*) PhGetData( event
);
1041 nsMouseEvent
theMouseEvent(PR_TRUE
, 0, nsnull
, nsMouseEvent::eReal
);
1045 if( ptrev
->flags
& Ph_PTR_FLAG_Z_ONLY
) break; // sometimes z presses come out of nowhere */
1048 if( sDragService
) {
1050 nsIDragService
*s
= sDragService
;
1051 d
= ( nsDragService
* )s
;
1052 d
->SetNativeDndData( widget
, event
);
1056 ScreenToWidgetPos( ptrev
->pos
);
1057 InitMouseEvent(ptrev
, this, theMouseEvent
, NS_MOUSE_MOVE
);
1058 result
= DispatchMouseEvent(theMouseEvent
);
1064 // Update the current input group for clipboard key events. This
1065 // covers both mozserver and mozilla.
1067 sClipboard
->SetInputGroup(event
->input_group
);
1068 result
= DispatchKeyEvent( (PhKeyEvent_t
*) PhGetData( event
) );
1073 nsMouseEvent
theMouseEvent(PR_TRUE
, 0, nsnull
, nsMouseEvent::eReal
);
1075 switch(event
->subtype
) {
1077 case Ph_EV_DRAG_COMPLETE
:
1079 nsMouseEvent
theMouseEvent(PR_TRUE
, 0, nsnull
,
1080 nsMouseEvent::eReal
);
1081 PhPointerEvent_t
* ptrev2
= (PhPointerEvent_t
*) PhGetData( event
);
1082 ScreenToWidgetPos( ptrev2
->pos
);
1083 InitMouseEvent(ptrev2
, this, theMouseEvent
, NS_MOUSE_BUTTON_UP
,
1084 nsMouseEvent::eLeftButton
);
1085 result
= DispatchMouseEvent(theMouseEvent
);
1088 case Ph_EV_DRAG_MOTION_EVENT
: {
1089 PhPointerEvent_t
* ptrev2
= (PhPointerEvent_t
*) PhGetData( event
);
1090 ScreenToWidgetPos( ptrev2
->pos
);
1091 InitMouseEvent(ptrev2
, this, theMouseEvent
, NS_MOUSE_MOVE
);
1092 result
= DispatchMouseEvent(theMouseEvent
);
1099 case Ph_EV_BOUNDARY
:
1102 switch( event
->subtype
) {
1103 case Ph_EV_PTR_ENTER
:
1104 case Ph_EV_PTR_ENTER_FROM_CHILD
:
1105 evtype
= NS_MOUSE_ENTER
;
1107 case Ph_EV_PTR_LEAVE_TO_CHILD
:
1108 case Ph_EV_PTR_LEAVE
:
1109 evtype
= NS_MOUSE_EXIT
;
1117 PhPointerEvent_t
* ptrev
= (PhPointerEvent_t
*) PhGetData( event
);
1118 nsMouseEvent
theMouseEvent(PR_TRUE
, 0, nsnull
,
1119 nsMouseEvent::eReal
);
1120 ScreenToWidgetPos( ptrev
->pos
);
1121 InitMouseEvent( ptrev
, this, theMouseEvent
, evtype
);
1122 result
= DispatchMouseEvent( theMouseEvent
);
1132 //-------------------------------------------------------------------------
1134 // the nsWidget raw event callback for all nsWidgets in this toolkit
1136 //-------------------------------------------------------------------------
1137 int nsWidget::RawEventHandler( PtWidget_t
*widget
, void *data
, PtCallbackInfo_t
*cbinfo
) {
1139 // Get the window which caused the event and ask it to process the message
1140 nsWidget
*someWidget
= (nsWidget
*) data
;
1142 if( someWidget
&& someWidget
->mIsDestroying
== PR_FALSE
&& someWidget
->HandleEvent( widget
, cbinfo
) )
1143 return Pt_END
; // Event was consumed
1149 int nsWidget::GotFocusCallback( PtWidget_t
*widget
, void *data
, PtCallbackInfo_t
*cbinfo
)
1151 nsWidget
*pWidget
= (nsWidget
*) data
;
1153 if( PtWidgetIsClass( widget
, PtWindow
) ) {
1154 if( pWidget
->mEventCallback
) {
1155 /* the WM_ACTIVATE code */
1156 pWidget
->DispatchStandardEvent(NS_ACTIVATE
);
1161 pWidget
->DispatchStandardEvent(NS_GOTFOCUS
);
1166 int nsWidget::LostFocusCallback( PtWidget_t
*widget
, void *data
, PtCallbackInfo_t
*cbinfo
)
1168 nsWidget
*pWidget
= (nsWidget
*) data
;
1169 pWidget
->DispatchStandardEvent(NS_LOSTFOCUS
);
1173 int nsWidget::DestroyedCallback( PtWidget_t
*widget
, void *data
, PtCallbackInfo_t
*cbinfo
) {
1174 nsWidget
*pWidget
= (nsWidget
*) data
;
1175 if( !pWidget
->mIsDestroying
) pWidget
->OnDestroy();
1180 void nsWidget::ProcessDrag( PhEvent_t
*event
, PRUint32 aEventType
, PhPoint_t
*pos
) {
1181 nsCOMPtr
<nsIDragSession
> currSession
;
1182 sDragService
->GetCurrentSession ( getter_AddRefs(currSession
) );
1183 if( !currSession
) return;
1185 int action
= nsIDragService::DRAGDROP_ACTION_NONE
;
1186 nsDragService
*d
= ( nsDragService
* ) sDragService
;
1188 if( d
->mActionType
& nsIDragService::DRAGDROP_ACTION_MOVE
)
1189 action
= nsIDragService::DRAGDROP_ACTION_MOVE
;
1190 else if( d
->mActionType
& nsIDragService::DRAGDROP_ACTION_LINK
)
1191 action
= nsIDragService::DRAGDROP_ACTION_LINK
;
1192 else if( d
->mActionType
& nsIDragService::DRAGDROP_ACTION_COPY
)
1193 action
= nsIDragService::DRAGDROP_ACTION_COPY
;
1195 currSession
->SetDragAction( action
);
1197 DispatchDragDropEvent( event
, aEventType
, pos
);
1199 int old_subtype
= event
->subtype
;
1200 event
->subtype
= Ph_EV_DND_ENTER
;
1203 currSession
->GetCanDrop(&canDrop
);
1205 static PhCharacterCursorDescription_t nodrop_cursor
= { { Ph_CURSOR_NOINPUT
, sizeof(PhCharacterCursorDescription_t
) }, PgRGB( 255, 255, 224 ) };
1206 PhAckDnd( event
, Ph_EV_DND_MOTION
, ( PhCursorDescription_t
* ) &nodrop_cursor
);
1209 static PhCharacterCursorDescription_t drop_cursor
= { { Ph_CURSOR_PASTE
, sizeof(PhCharacterCursorDescription_t
) }, PgRGB( 255, 255, 224 ) };
1210 PhAckDnd( event
, Ph_EV_DND_MOTION
, ( PhCursorDescription_t
* ) &drop_cursor
);
1213 event
->subtype
= old_subtype
;
1215 // Clear the cached value
1216 currSession
->SetCanDrop(PR_FALSE
);
1219 void nsWidget::DispatchDragDropEvent( PhEvent_t
*phevent
, PRUint32 aEventType
, PhPoint_t
*pos
) {
1220 nsEventStatus status
;
1221 nsDragEvent
event(PR_TRUE
, 0, nsnull
);
1223 InitEvent( event
, aEventType
);
1225 event
.refPoint
.x
= pos
->x
;
1226 event
.refPoint
.y
= pos
->y
;
1228 PhDndEvent_t
*dnd
= ( PhDndEvent_t
* ) PhGetData( phevent
);
1229 event
.isControl
= ( dnd
->key_mods
& Pk_KM_Ctrl
) ? PR_TRUE
: PR_FALSE
;
1230 event
.isShift
= ( dnd
->key_mods
& Pk_KM_Shift
) ? PR_TRUE
: PR_FALSE
;
1231 event
.isAlt
= ( dnd
->key_mods
& Pk_KM_Alt
) ? PR_TRUE
: PR_FALSE
;
1232 event
.isMeta
= PR_FALSE
;
1234 event
.widget
= this;
1236 ///* ATENTIE */ printf("DispatchDragDropEvent pos=%d %d widget=%p\n", event.refPoint.x, event.refPoint.y, this );
1238 DispatchEvent( &event
, status
);
1241 int nsWidget::DndCallback( PtWidget_t
*widget
, void *data
, PtCallbackInfo_t
*cbinfo
) {
1242 nsWidget
*pWidget
= (nsWidget
*) data
;
1243 PtDndCallbackInfo_t
*cbdnd
= ( PtDndCallbackInfo_t
* ) cbinfo
->cbdata
;
1245 static PtDndFetch_t dnd_data_template
= { "Mozilla", "dnddata", Ph_TRANSPORT_INLINE
, Pt_DND_SELECT_MOTION
,
1246 NULL
, NULL
, NULL
, NULL
, NULL
};
1248 ///* ATENTIE */ printf( "In nsWidget::DndCallback subtype=%d\n", cbinfo->reason_subtype );
1250 PhPointerEvent_t
* ptrev
= (PhPointerEvent_t
*) PhGetData( cbinfo
->event
);
1251 //printf("Enter pos=%d %d\n", ptrev->pos.x, ptrev->pos.y );
1252 pWidget
->ScreenToWidgetPos( ptrev
->pos
);
1253 //printf("After trans pos=%d %d pWidget=%p\n", ptrev->pos.x, ptrev->pos.y, pWidget );
1256 switch( cbinfo
->reason_subtype
) {
1257 case Ph_EV_DND_ENTER
: {
1258 sDragService
->StartDragSession();
1259 pWidget
->ProcessDrag( cbinfo
->event
, NS_DRAGDROP_ENTER
, &ptrev
->pos
);
1261 PtDndSelect( widget
, &dnd_data_template
, 1, NULL
, NULL
, cbinfo
);
1265 case Ph_EV_DND_MOTION
: {
1266 sDragService
->FireDragEventAtSource(NS_DRAGDROP_DRAG
);
1267 pWidget
->ProcessDrag( cbinfo
->event
, NS_DRAGDROP_OVER
, &ptrev
->pos
);
1270 case Ph_EV_DND_DROP
:
1272 d
= ( nsDragService
* )sDragService
;
1273 if( d
->SetDropData( (char*)cbdnd
->data
) != NS_OK
) break;
1274 pWidget
->ProcessDrag( cbinfo
->event
, NS_DRAGDROP_DROP
, &ptrev
->pos
);
1275 sDragService
->EndDragSession(PR_TRUE
);
1276 ((nsDragService
*) sDragService
)->SourceEndDrag();
1279 case Ph_EV_DND_LEAVE
:
1280 pWidget
->ProcessDrag( cbinfo
->event
, NS_DRAGDROP_EXIT
, &ptrev
->pos
);
1281 sDragService
->EndDragSession(PR_FALSE
);
1284 case Ph_EV_DND_CANCEL
:
1285 pWidget
->ProcessDrag( cbinfo
->event
, NS_DRAGDROP_EXIT
, &ptrev
->pos
);
1286 sDragService
->EndDragSession(PR_TRUE
);
1287 ((nsDragService
*) sDragService
)->SourceEndDrag();
1293 #endif /* PHOTON_DND */