Bug 470455 - test_database_sync_embed_visits.js leaks, r=sdwilsh
[wine-gecko.git] / widget / src / photon / nsWidget.cpp
blob80225860a0bdf0d825e96241fcc2e3ea1c236b9b
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
13 * License.
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.
22 * Contributor(s):
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 ***** */
42 #include "nsWidget.h"
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"
52 #include <Pt.h>
53 #include "PtRawDrawContainer.h"
54 #include "nsIRollupListener.h"
55 #include "nsIServiceManager.h"
56 #include "nsWindow.h"
57 #ifdef PHOTON_DND
58 #include "nsDragService.h"
59 #endif
60 #include "nsReadableUtils.h"
62 #include "nsClipboard.h"
64 #include <errno.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) \
72 g.red=NS_GET_B(n); \
73 g.green=NS_GET_G(n); \
74 g.blue=NS_GET_R(n);
76 ////////////////////////////////////////////////////////////////////
78 // Define and Initialize global variables
80 ////////////////////////////////////////////////////////////////////
84 // Keep track of the last widget being "dragged"
86 nsILookAndFeel *nsWidget::sLookAndFeel = nsnull;
87 #ifdef PHOTON_DND
88 nsIDragService *nsWidget::sDragService = nsnull;
89 #endif
90 nsClipboard *nsWidget::sClipboard = nsnull;
91 PRUint32 nsWidget::sWidgetCount = 0;
92 nsWidget* nsWidget::sFocusWidget = 0;
94 nsWidget::nsWidget()
96 if (!sLookAndFeel) {
97 CallGetService(kLookAndFeelCID, &sLookAndFeel);
100 if( sLookAndFeel )
101 sLookAndFeel->GetColor( nsILookAndFeel::eColor_WindowBackground, mBackground );
103 #ifdef PHOTON_DND
104 if( !sDragService ) {
105 nsresult rv;
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;
111 #endif
113 if( !sClipboard ) {
114 nsresult rv;
115 nsCOMPtr<nsClipboard> s;
116 s = do_GetService( kCClipboardCID, &rv );
117 sClipboard = ( nsClipboard * ) s;
118 if( NS_FAILED( rv ) ) sClipboard = 0;
121 mWidget = nsnull;
122 mParent = nsnull;
123 mPreferredWidth = 0;
124 mPreferredHeight = 0;
125 mShown = PR_FALSE;
126 mBounds.x = 0;
127 mBounds.y = 0;
128 mBounds.width = 0;
129 mBounds.height = 0;
130 mIsDestroying = PR_FALSE;
131 mOnDestroyCalled = PR_FALSE;
132 mIsToplevel = PR_FALSE;
133 mListenForResizes = PR_FALSE;
134 sWidgetCount++;
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
143 Destroy();
145 if( !sWidgetCount-- ) {
146 NS_IF_RELEASE( sLookAndFeel );
150 //-------------------------------------------------------------------------
152 // nsISupport stuff
154 //-------------------------------------------------------------------------
155 NS_IMPL_ISUPPORTS_INHERITED0(nsWidget, nsBaseWidget)
157 NS_METHOD nsWidget::WidgetToScreen( const nsRect& aOldRect, nsRect& aNewRect ) {
158 if( mWidget ) {
159 /* This is NOT correct */
160 aNewRect.x = aOldRect.x;
161 aNewRect.y = aOldRect.y;
163 return NS_OK;
166 // nsWidget::ScreenToWidget - Not Implemented
167 NS_METHOD nsWidget::ScreenToWidget( const nsRect& aOldRect, nsRect& aNewRect ) {
168 return NS_OK;
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;
182 // ok, set our state
183 mIsDestroying = PR_TRUE;
185 // call in and clean up any of our base widget resources
186 // are released
187 nsBaseWidget::Destroy();
189 // destroy our native windows
190 DestroyNative();
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;
198 return NS_OK;
201 // this is the function that will destroy the native windows for this widget.
203 /* virtual */
204 void nsWidget::DestroyNative( void ) {
205 if( mWidget ) {
206 // prevent the widget from causing additional events
207 mEventCallback = nsnull;
208 //EnableDamage( mWidget, PR_FALSE );
209 PtDestroyWidget( mWidget );
210 //EnableDamage( mWidget, PR_TRUE );
211 mWidget = nsnull;
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
234 PtArg_t arg;
236 if( bState ) {
238 if( mWindowType != eWindowType_child ) {
240 if (PtWidgetIsRealized(mWidget)) {
241 mShown = PR_TRUE;
242 return NS_OK;
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");
251 mShown = PR_FALSE;
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
260 PhRegion_t region;
261 PtWidget_t *mWgt;
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, &region, NULL, NULL);
266 #endif
268 else {
269 PtWidgetToFront( mWidget );
270 if( !mShown || !( mWidget->flags & Pt_REALIZED ) ) PtRealizeWidget( mWidget );
273 else {
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);
283 else {
284 //EnableDamage( mWidget, PR_FALSE );
285 PtWidgetToBack( mWidget );
286 if( mShown ) PtUnrealizeWidget( mWidget );
287 //EnableDamage( mWidget, PR_TRUE );
291 mShown = bState;
292 return NS_OK;
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;
310 mBounds.x = aX;
311 mBounds.y = aY;
313 if( mWidget ) {
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 );
319 return NS_OK;
323 NS_METHOD nsWidget::Resize( PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint ) {
325 if( ( mBounds.width == aWidth ) && ( mBounds.height == aHeight ) )
326 return NS_OK;
328 mBounds.width = aWidth;
329 mBounds.height = aHeight;
331 if( mWidget ) {
332 PhDim_t dim = { aWidth, aHeight };
333 //EnableDamage( mWidget, PR_FALSE );
334 PtSetResource( mWidget, Pt_ARG_DIM, &dim, 0 );
335 //EnableDamage( mWidget, PR_TRUE );
338 return NS_OK;
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;
365 NS_ADDREF_THIS();
366 result = DispatchWindowEvent(&event);
367 NS_RELEASE_THIS();
368 delete foo;
371 return result;
374 //------
375 // Move
376 //------
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);
396 if( mFontMetrics ) {
397 PtArg_t arg;
399 nsFontHandle aFontHandle;
400 mFontMetrics->GetFontHandle(aFontHandle);
401 nsString *aString;
402 aString = (nsString *) aFontHandle;
403 char *str = ToNewCString(*aString);
405 PtSetArg( &arg, Pt_ARG_TEXT_FONT, str, 0 );
406 PtSetResources( mWidget, 1, &arg );
408 delete [] str;
409 NS_RELEASE(mFontMetrics);
411 return NS_OK;
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;
427 switch( aCursor ) {
428 case eCursor_nw_resize:
429 curs = Ph_CURSOR_DRAG_TL;
430 break;
431 case eCursor_se_resize:
432 curs = Ph_CURSOR_DRAG_BR;
433 break;
434 case eCursor_ne_resize:
435 curs = Ph_CURSOR_DRAG_TL;
436 break;
437 case eCursor_sw_resize:
438 curs = Ph_CURSOR_DRAG_BL;
439 break;
441 case eCursor_crosshair:
442 curs = Ph_CURSOR_CROSSHAIR;
443 break;
445 case eCursor_copy:
446 case eCursor_alias:
447 case eCursor_context_menu:
448 // XXX: No suitable cursor, needs implementing
449 break;
451 case eCursor_cell:
452 // XXX: No suitable cursor, needs implementing
453 break;
455 case eCursor_spinning:
456 // XXX: No suitable cursor, needs implementing
457 break;
459 case eCursor_move:
460 curs = Ph_CURSOR_MOVE;
461 break;
463 case eCursor_help:
464 curs = Ph_CURSOR_QUESTION_POINT;
465 break;
467 case eCursor_grab:
468 case eCursor_grabbing:
469 curs = Ph_CURSOR_FINGER;
470 break;
472 case eCursor_select:
473 curs = Ph_CURSOR_INSERT;
474 color = Pg_BLACK;
475 break;
477 case eCursor_wait:
478 curs = Ph_CURSOR_LONG_WAIT;
479 break;
481 case eCursor_hyperlink:
482 curs = Ph_CURSOR_FINGER;
483 break;
485 case eCursor_standard:
486 curs = Ph_CURSOR_POINTER;
487 break;
489 case eCursor_n_resize:
490 case eCursor_s_resize:
491 curs = Ph_CURSOR_DRAG_VERTICAL;
492 break;
494 case eCursor_w_resize:
495 case eCursor_e_resize:
496 curs = Ph_CURSOR_DRAG_HORIZONTAL;
497 break;
499 case eCursor_zoom_in:
500 case eCursor_zoom_out:
501 // XXX: No suitable cursor, needs implementing
502 break;
504 case eCursor_not_allowed:
505 case eCursor_no_drop:
506 curs = Ph_CURSOR_DONT;
507 break;
509 case eCursor_col_resize:
510 // XXX: not 100% appropriate perhaps
511 curs = Ph_CURSOR_DRAG_HORIZONTAL;
512 break;
514 case eCursor_row_resize:
515 // XXX: not 100% appropriate perhaps
516 curs = Ph_CURSOR_DRAG_VERTICAL;
517 break;
519 case eCursor_vertical_text:
520 curs = Ph_CURSOR_INSERT;
521 color = Pg_BLACK;
522 break;
524 case eCursor_all_scroll:
525 // XXX: No suitable cursor, needs implementing
526 break;
528 case eCursor_nesw_resize:
529 curs = Ph_CURSOR_DRAG_FOREDIAG;
530 break;
532 case eCursor_nwse_resize:
533 curs = Ph_CURSOR_DRAG_BACKDIAG;
534 break;
536 case eCursor_ns_resize:
537 curs = Ph_CURSOR_DRAG_VERTICAL;
538 break;
540 case eCursor_ew_resize:
541 curs = Ph_CURSOR_DRAG_HORIZONTAL;
542 break;
544 case eCursor_none:
545 // XXX: No suitable cursor, needs implementing
546 break;
548 default:
549 NS_ASSERTION(0, "Invalid cursor type");
550 break;
553 if( mWidget ) {
554 PtArg_t args[2];
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 );
560 mCursor = aCursor;
563 return NS_OK;
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();
575 return NS_OK;
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;
583 PhRect_t prect;
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( );
592 return NS_OK;
595 NS_IMETHODIMP nsWidget::InvalidateRegion( const nsIRegion *aRegion, PRBool aIsSynchronous ) {
596 PhTile_t *tiles = NULL;
597 aRegion->GetNativeRegion( ( void*& ) tiles );
598 if( tiles ) {
599 PhTranslateTiles( tiles, &mWidget->area.pos );
600 PtDamageTiles( mWidget, tiles );
601 if( aIsSynchronous ) PtFlush( );
603 return NS_OK;
606 nsresult nsWidget::CreateWidget(nsIWidget *aParent,
607 const nsRect &aRect,
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;
625 else if( aParent ) {
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) ?
636 nsnull : aParent;
638 BaseCreate( baseParent, aRect, aHandleEventFunction, aContext, aAppShell, aToolkit, aInitData );
640 mParent = aParent;
641 mBounds = aRect;
643 CreateNative (parentWidget);
645 if( aRect.width > 1 && aRect.height > 1 ) Resize(aRect.width, aRect.height, PR_FALSE);
647 if( mWidget ) {
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 );
652 #ifdef PHOTON_DND
653 PtAddCallback( mWidget, Pt_CB_DND, DndCallback, this );
654 #endif
657 DispatchStandardEvent(NS_CREATE);
659 return NS_OK;
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);
690 return NS_OK;
693 //==============================================================
694 void nsWidget::InitMouseEvent(PhPointerEvent_t *aPhButtonEvent,
695 nsWidget * aWidget,
696 nsMouseEvent &anEvent,
697 PRUint32 aEventType,
698 PRInt16 aButton)
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);
728 return result;
731 return result;
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 },
742 { NS_VK_UP, Pk_Up },
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;
793 else return 0;
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);
820 return((int) 0);
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 );
829 return PR_FALSE;
832 if ( PtIsFocused(mWidget) != 2) {
833 //printf("nsWidget::DispatchKeyEvent Not on focus leaf! PtIsFocused(mWidget)=<%d>\n", PtIsFocused(mWidget));
834 return PR_FALSE;
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 )
844 return PR_TRUE;
846 nsWindow *w = (nsWindow *) this;
848 w->AddRef();
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);
870 w->OnKey(kevent);
873 w->Release();
875 return PR_TRUE;
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;
893 if ( sym >= 0xF000
894 ? sym >= 0xF100 && ( sizeof(wchar_t) > 2 || sym < 0x10000 )
895 : ( sym & ~0x9F ) != 0 // exclude 0...0x1F and 0x80...0x9F
896 ) return 1;
898 return 0;
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;
906 if ( cap >= 0xF000
907 ? cap >= 0xF100 && ( sizeof(wchar_t) > 2 || cap < 0x10000 )
908 : ( cap & ~0x9F ) != 0 // exclude 0...0x1F and 0x80...0x9F
909 ) return 1;
911 return 0;
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;
922 else {
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();
933 // used only once
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);
947 if( ptrev ) {
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);
958 break;
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 );
972 if( ptrev ) {
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 );
998 break;
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.
1011 if (sClipboard)
1012 sClipboard->SetInputGroup(event->input_group);
1014 if (event->subtype==Ph_EV_RELEASE_REAL || event->subtype==Ph_EV_RELEASE_PHANTOM) {
1015 if (ptrev) {
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);
1036 break;
1038 case Ph_EV_PTR_MOTION_BUTTON:
1040 PhPointerEvent_t* ptrev = (PhPointerEvent_t*) PhGetData( event );
1041 nsMouseEvent theMouseEvent(PR_TRUE, 0, nsnull, nsMouseEvent::eReal);
1043 if( ptrev ) {
1045 if( ptrev->flags & Ph_PTR_FLAG_Z_ONLY ) break; // sometimes z presses come out of nowhere */
1047 #ifdef PHOTON_DND
1048 if( sDragService ) {
1049 nsDragService *d;
1050 nsIDragService *s = sDragService;
1051 d = ( nsDragService * )s;
1052 d->SetNativeDndData( widget, event );
1054 #endif
1056 ScreenToWidgetPos( ptrev->pos );
1057 InitMouseEvent(ptrev, this, theMouseEvent, NS_MOUSE_MOVE );
1058 result = DispatchMouseEvent(theMouseEvent);
1061 break;
1063 case Ph_EV_KEY:
1064 // Update the current input group for clipboard key events. This
1065 // covers both mozserver and mozilla.
1066 if (sClipboard)
1067 sClipboard->SetInputGroup(event->input_group);
1068 result = DispatchKeyEvent( (PhKeyEvent_t*) PhGetData( event ) );
1069 break;
1071 case Ph_EV_DRAG:
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);
1087 break;
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);
1094 break;
1097 break;
1099 case Ph_EV_BOUNDARY:
1100 PRUint32 evtype;
1102 switch( event->subtype ) {
1103 case Ph_EV_PTR_ENTER:
1104 case Ph_EV_PTR_ENTER_FROM_CHILD:
1105 evtype = NS_MOUSE_ENTER;
1106 break;
1107 case Ph_EV_PTR_LEAVE_TO_CHILD:
1108 case Ph_EV_PTR_LEAVE:
1109 evtype = NS_MOUSE_EXIT;
1110 break;
1111 default:
1112 evtype = 0;
1113 break;
1116 if( evtype != 0 ) {
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 );
1124 break;
1127 return result;
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
1145 return Pt_CONTINUE;
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);
1157 return Pt_CONTINUE;
1161 pWidget->DispatchStandardEvent(NS_GOTFOCUS);
1163 return Pt_CONTINUE;
1166 int nsWidget::LostFocusCallback( PtWidget_t *widget, void *data, PtCallbackInfo_t *cbinfo )
1168 nsWidget *pWidget = (nsWidget *) data;
1169 pWidget->DispatchStandardEvent(NS_LOSTFOCUS);
1170 return Pt_CONTINUE;
1173 int nsWidget::DestroyedCallback( PtWidget_t *widget, void *data, PtCallbackInfo_t *cbinfo ) {
1174 nsWidget *pWidget = (nsWidget *) data;
1175 if( !pWidget->mIsDestroying ) pWidget->OnDestroy();
1176 return Pt_CONTINUE;
1179 #ifdef PHOTON_DND
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;
1202 PRBool canDrop;
1203 currSession->GetCanDrop(&canDrop);
1204 if(!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 );
1208 else {
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 );
1263 break;
1265 case Ph_EV_DND_MOTION: {
1266 sDragService->FireDragEventAtSource(NS_DRAGDROP_DRAG);
1267 pWidget->ProcessDrag( cbinfo->event, NS_DRAGDROP_OVER, &ptrev->pos );
1269 break;
1270 case Ph_EV_DND_DROP:
1271 nsDragService *d;
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();
1277 break;
1279 case Ph_EV_DND_LEAVE:
1280 pWidget->ProcessDrag( cbinfo->event, NS_DRAGDROP_EXIT, &ptrev->pos );
1281 sDragService->EndDragSession(PR_FALSE);
1282 break;
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();
1288 break;
1291 return Pt_CONTINUE;
1293 #endif /* PHOTON_DND */