void MouseEvent::InitMouseEvent(const nsAString& aType, bool aCanBubble, bool aCancelable, nsGlobalWindow* aView, int32_t aDetail, int32_t aScreenX, int32_t aScreenY, int32_t aClientX, int32_t aClientY, int16_t aButton, EventTarget* aRelatedTarget, const nsAString& aModifiersList) { NS_ENSURE_TRUE_VOID(!mEvent->mFlags.mIsBeingDispatched); Modifiers modifiers = ComputeModifierState(aModifiersList); InitMouseEvent(aType, aCanBubble, aCancelable, aView, aDetail, aScreenX, aScreenY, aClientX, aClientY, (modifiers & MODIFIER_CONTROL) != 0, (modifiers & MODIFIER_ALT) != 0, (modifiers & MODIFIER_SHIFT) != 0, (modifiers & MODIFIER_META) != 0, aButton, aRelatedTarget); switch(mEvent->mClass) { case eMouseEventClass: case eMouseScrollEventClass: case eWheelEventClass: case eDragEventClass: case ePointerEventClass: case eSimpleGestureEventClass: mEvent->AsInputEvent()->mModifiers = modifiers; return; default: MOZ_CRASH("There is no space to store the modifiers"); } }
// used only once inline PRBool nsWidget::HandleEvent( PtWidget_t *widget, PtCallbackInfo_t* aCbInfo ) { PRBool result = PR_TRUE; // call the default nsWindow proc PhEvent_t* event = aCbInfo->event; static int prevx=-1, prevy=-1, left_button_down, kwww_outbound_valid; if (event->processing_flags & Ph_CONSUMED) return PR_TRUE; switch ( event->type ) { case Ph_EV_PTR_MOTION_NOBUTTON: { PhPointerEvent_t* ptrev = (PhPointerEvent_t*) PhGetData( event ); nsMouseEvent theMouseEvent(PR_TRUE, 0, nsnull, nsMouseEvent::eReal); if( ptrev ) { if( ptrev->flags & Ph_PTR_FLAG_Z_ONLY ) break; // sometimes z presses come out of nowhere */ ///* ATENTIE */ printf( "Ph_EV_PTR_MOTION_NOBUTTON (%d %d)\n", ptrev->pos.x, ptrev->pos.y ); ScreenToWidgetPos( ptrev->pos ); InitMouseEvent(ptrev, this, theMouseEvent, NS_MOUSE_MOVE ); result = DispatchMouseEvent(theMouseEvent); } } break; case Ph_EV_BUT_PRESS: { PhPointerEvent_t* ptrev = (PhPointerEvent_t*) PhGetData( event ); nsMouseEvent theMouseEvent(PR_TRUE, 0, nsnull, nsMouseEvent::eReal); /* there should be no reason to do this - mozilla should figure out how to call SetFocus */ /* this though fixes the problem with the plugins capturing the focus */ PtWidget_t *disjoint = PtFindDisjoint( widget ); if( PtWidgetIsClassMember( disjoint, PtServer ) || //mozserver PtWidgetIsClassMember( disjoint, PtContainer ) ) //TestPhEmbed PtContainerGiveFocus( widget, aCbInfo->event ); if( ptrev ) { prevx = ptrev->pos.x; prevy = ptrev->pos.y; ScreenToWidgetPos( ptrev->pos ); if( ptrev->buttons & Ph_BUTTON_SELECT ) { // Normally the left mouse button InitMouseEvent(ptrev, this, theMouseEvent, NS_MOUSE_LEFT_BUTTON_DOWN ); left_button_down = 1; } else if( ptrev->buttons & Ph_BUTTON_MENU ) // the right button InitMouseEvent(ptrev, this, theMouseEvent, NS_MOUSE_RIGHT_BUTTON_DOWN ); else // middle button InitMouseEvent(ptrev, this, theMouseEvent, NS_MOUSE_MIDDLE_BUTTON_DOWN ); //printf("*** Button down\n"); result = DispatchMouseEvent(theMouseEvent); // if we're a right-button-down we're trying to popup a context menu. send that event to gecko also if( ptrev->buttons & Ph_BUTTON_MENU ) { nsMouseEvent contextMenuEvent(PR_TRUE, 0, nsnull, nsMouseEvent::eReal); InitMouseEvent( ptrev, this, contextMenuEvent, NS_CONTEXTMENU ); result = DispatchMouseEvent( contextMenuEvent ); } } } break; case Ph_EV_BUT_RELEASE: { PhPointerEvent_t* ptrev = (PhPointerEvent_t*) PhGetData( event ); nsMouseEvent theMouseEvent(PR_TRUE, 0, nsnull, nsMouseEvent::eReal); // Update the current input group for clipboard mouse events // (mozilla only). Note that for mozserver the mouse based // (eg. Edit->Copy/Paste menu) events don't come through here. // They are sent by the voyager client app via libPtWeb.so to // do_command() in mozserver.cpp. if (sClipboard) sClipboard->SetInputGroup(event->input_group); if (event->subtype==Ph_EV_RELEASE_REAL || event->subtype==Ph_EV_RELEASE_PHANTOM) { if (ptrev) { ScreenToWidgetPos( ptrev->pos ); if ( ptrev->buttons & Ph_BUTTON_SELECT ) { // Normally the left mouse button InitMouseEvent(ptrev, this, theMouseEvent, NS_MOUSE_LEFT_BUTTON_UP ); kwww_outbound_valid = 0; // // To be clean, let's not send multiple left button up // events. // if (!left_button_down) break; //case left_button_down = 0; } else if( ptrev->buttons & Ph_BUTTON_MENU ) // the right button InitMouseEvent(ptrev, this, theMouseEvent, NS_MOUSE_RIGHT_BUTTON_UP ); else // middle button InitMouseEvent(ptrev, this, theMouseEvent, NS_MOUSE_MIDDLE_BUTTON_UP ); //printf("*** Button up %s\n", event->subtype==Ph_EV_RELEASE_PHANTOM ? "(phantom)" : ""); result = DispatchMouseEvent(theMouseEvent); } } else if (event->subtype==Ph_EV_RELEASE_OUTBOUND) { PhRect_t rect = {{0,0},{0,0}}; PhRect_t boundary = {{-10000,-10000},{10000,10000}}; //printf("*** OUTBOUND\n"); if (__progname && strcmp(__progname, "kwww") == 0) { // // In kscope we only use dragging to scroll the view. So // we don't want Mozilla to do any special drag processing, // and fake this out by immediately doing a left-button-up. // We do it at (999999,999999) so any control or link under // the pointer doesn't get activated. // ptrev->pos.x = ptrev->pos.y = 999999; InitMouseEvent(ptrev, this, theMouseEvent, NS_MOUSE_LEFT_BUTTON_UP ); result = DispatchMouseEvent(theMouseEvent); InitMouseEvent(ptrev, this, theMouseEvent, NS_MOUSE_MOVE ); result = DispatchMouseEvent(theMouseEvent); left_button_down = 0; kwww_outbound_valid = 1; // // In case we activated a combo box, do another down/up // Sending an Esc key also works. Which is better? // The mouse button method may prevent drag initiation // within (multiline?) input fields. // #if 0 InitMouseEvent(ptrev, this, theMouseEvent, NS_MOUSE_LEFT_BUTTON_DOWN ); result = DispatchMouseEvent(theMouseEvent); InitMouseEvent(ptrev, this, theMouseEvent, NS_MOUSE_LEFT_BUTTON_UP ); result = DispatchMouseEvent(theMouseEvent); #else PhKeyEvent_t kev; memset( &kev, 0, sizeof(kev) ); kev.key_cap = kev.key_sym = Pk_Escape; kev.key_flags = Pk_KF_Key_Down | Pk_KF_Cap_Valid | Pk_KF_Sym_Valid; DispatchKeyEvent( &kev, 1 ); memset( &kev, 0, sizeof(kev) ); kev.key_cap = Pk_Escape; kev.key_flags = Pk_KF_Cap_Valid; DispatchKeyEvent( &kev, 1 ); #endif } PhInitDrag( PtWidgetRid(mWidget), ( Ph_DRAG_KEY_MOTION | Ph_DRAG_TRACK | Ph_TRACK_DRAG),&rect, &boundary, aCbInfo->event->input_group , NULL, NULL, NULL, NULL, NULL); } } break; case Ph_EV_PTR_MOTION_BUTTON: { PhPointerEvent_t* ptrev = (PhPointerEvent_t*) PhGetData( event ); nsMouseEvent theMouseEvent(PR_TRUE, 0, nsnull, nsMouseEvent::eReal); if( ptrev ) { if( ptrev->flags & Ph_PTR_FLAG_Z_ONLY ) break; // sometimes z presses come out of nowhere */ #ifdef PHOTON_DND if( sDragService ) { nsDragService *d; nsIDragService *s = sDragService; d = ( nsDragService * )s; d->SetNativeDndData( widget, event ); } #endif if (!__progname || strcmp(__progname, "kwww") != 0) { // // We don't send these events in kscope. Dragging is devoted to // scrolling. // ScreenToWidgetPos( ptrev->pos ); InitMouseEvent(ptrev, this, theMouseEvent, NS_MOUSE_MOVE ); result = DispatchMouseEvent(theMouseEvent); } } } break; case Ph_EV_KEY: // Update the current input group for clipboard key events. This // covers both mozserver and mozilla. if (sClipboard) sClipboard->SetInputGroup(event->input_group); result = DispatchKeyEvent( (PhKeyEvent_t*) PhGetData( event ), 0 ); break; case Ph_EV_DRAG: { nsMouseEvent theMouseEvent(PR_TRUE, 0, nsnull, nsMouseEvent::eReal); switch(event->subtype) { static int is_kwww=-1; case Ph_EV_DRAG_COMPLETE: { nsMouseEvent theMouseEvent(PR_TRUE, 0, nsnull, nsMouseEvent::eReal); PhPointerEvent_t* ptrev2 = (PhPointerEvent_t*) PhGetData( event ); //printf("*** Drag complete\n"); if (is_kwww) { // Already did the button up kwww_outbound_valid = 0; prevx = prevy = -1; } else { ScreenToWidgetPos( ptrev2->pos ); InitMouseEvent(ptrev2, this, theMouseEvent, NS_MOUSE_LEFT_BUTTON_UP ); result = DispatchMouseEvent(theMouseEvent); left_button_down = 0; } } break; case Ph_EV_DRAG_MOTION_EVENT: { PhPointerEvent_t* ptrev2 = (PhPointerEvent_t*) PhGetData( event ); //printf("*** Drag motion\n"); if (is_kwww == -1) { is_kwww = 0; if (__progname && strcmp(__progname, "kwww") == 0) is_kwww = 1; } if (is_kwww) { nsIWidget *nsw = this; nsIWidget *top_widget = nsw; if (!kwww_outbound_valid) { struct dragevent { PhEvent_t hdr; PhDragEvent_t drag; } ev; // // If the user does a drag where he releases the left mouse // button almost right away, then we will start getting // drag events even though the mouse button is not pressed! // Work around this Photon bug by cancelling the drag // ourselves. In 6.4.0 we can use PhCancelDrag() to do this. // //printf("*** CANCELLING DRAG!\n"); memset( &ev, 0, sizeof(ev) ); ev.hdr.type = Ph_EV_DRAG; ev.hdr.emitter.rid = Ph_DEV_RID; ev.hdr.flags = Ph_EVENT_INCLUSIVE | Ph_EMIT_TOWARD; ev.hdr.data_len = sizeof( ev.drag ); ev.hdr.subtype = Ph_EV_DRAG_COMPLETE; ev.hdr.input_group = aCbInfo->event->input_group; ev.drag.rid = PtWidgetRid(mWidget); ev.drag.flags = 0; PhEmit( &ev.hdr, NULL, &ev.drag ); break; //case } while (nsw) { top_widget = nsw; nsw = nsw->GetParent(); } try_again: nsIView *view = nsToolkit::GetViewFor(top_widget); if (view) { nsIViewManager* vm = view->GetViewManager(); if (vm) { nsIScrollableView* scrollView = nsnull; vm->GetRootScrollableView(&scrollView); if (scrollView) { if (prevx != -1 || prevy != -1) { // // The -1 check is to handle prevx and prevy not set // to the button press location, which happens when // you click on flash. // nsresult rc = ((nsIScrollableView_MOZILLA_1_8_BRANCH*)scrollView)->ScrollByPixels(prevx - ptrev2->pos.x, prevy - ptrev2->pos.y); //printf("*** rc %d from ScrollByPixels\n"); } } else if (top_widget != this) { // // There is no scrollable view for the top level widget. // See if there is one for the original widget. // top_widget = this; goto try_again; } } } prevx = ptrev2->pos.x; prevy = ptrev2->pos.y; } else { ScreenToWidgetPos( ptrev2->pos ); InitMouseEvent(ptrev2, this, theMouseEvent, NS_MOUSE_MOVE ); result = DispatchMouseEvent(theMouseEvent); } } break; } } break; case Ph_EV_BOUNDARY: PRUint32 evtype; switch( event->subtype ) { case Ph_EV_PTR_ENTER: case Ph_EV_PTR_ENTER_FROM_CHILD: evtype = NS_MOUSE_ENTER; break; case Ph_EV_PTR_LEAVE_TO_CHILD: case Ph_EV_PTR_LEAVE: evtype = NS_MOUSE_EXIT; break; default: evtype = 0; break; } if( evtype != 0 ) { PhPointerEvent_t* ptrev = (PhPointerEvent_t*) PhGetData( event ); nsMouseEvent theMouseEvent(PR_TRUE, 0, nsnull, nsMouseEvent::eReal); ScreenToWidgetPos( ptrev->pos ); InitMouseEvent( ptrev, this, theMouseEvent, evtype ); result = DispatchMouseEvent( theMouseEvent ); } break; } return result; }