bool nsCoreUtils::DispatchMouseEvent(uint32_t aEventType, nsIPresShell *aPresShell, nsIContent *aContent) { nsIFrame *frame = aContent->GetPrimaryFrame(); if (!frame) return false; // Compute x and y coordinates. nsPoint point; nsCOMPtr<nsIWidget> widget = frame->GetNearestWidget(point); if (!widget) return false; nsSize size = frame->GetSize(); nsPresContext* presContext = aPresShell->GetPresContext(); int32_t x = presContext->AppUnitsToDevPixels(point.x + size.width / 2); int32_t y = presContext->AppUnitsToDevPixels(point.y + size.height / 2); // Fire mouse event. DispatchMouseEvent(aEventType, x, y, aContent, frame, aPresShell, widget); return true; }
void InputManager::DispatchEvents() { EEvent e; for (uint32 i = 0; i < m_events.Size(); i++) { e = m_events[i]->GetType(); if (e == ON_MOUSE_EVENT) { DispatchMouseEvent(m_events[i]); } else if (e == ON_KEYBOARD_EVENT) { DispatchKeyboardEvent(m_events[i]); } RemoveEvent(m_events[i]); } }
void GeckoTouchDispatcher::DispatchTouchEvent(MultiTouchInput& aMultiTouch) { if ((aMultiTouch.mType == MultiTouchInput::MULTITOUCH_END || aMultiTouch.mType == MultiTouchInput::MULTITOUCH_CANCEL) && aMultiTouch.mTouches.Length() == 1) { MutexAutoLock lock(mTouchQueueLock); mTouchMoveEvents.clear(); } else if (aMultiTouch.mType == MultiTouchInput::MULTITOUCH_START && aMultiTouch.mTouches.Length() == 1) { mTouchEventsFiltered = IsExpired(aMultiTouch); } if (mTouchEventsFiltered) { return; } bool captured = false; WidgetTouchEvent event = aMultiTouch.ToWidgetTouchEvent(nullptr); nsEventStatus status = nsWindow::DispatchInputEvent(event, &captured); if (mEnabledUniformityInfo) { const char* touchAction = "Invalid"; switch (aMultiTouch.mType) { case MultiTouchInput::MULTITOUCH_START: touchAction = "Touch_Event_Down"; break; case MultiTouchInput::MULTITOUCH_MOVE: touchAction = "Touch_Event_Move"; break; case MultiTouchInput::MULTITOUCH_END: case MultiTouchInput::MULTITOUCH_CANCEL: touchAction = "Touch_Event_Up"; break; } const SingleTouchData& firstTouch = aMultiTouch.mTouches[0]; const ScreenIntPoint& touchPoint = firstTouch.mScreenPoint; LOG("UniformityInfo %s %llu %d %d", touchAction, systemTime(SYSTEM_TIME_MONOTONIC), touchPoint.x, touchPoint.y); } if (!captured && (aMultiTouch.mTouches.Length() == 1)) { bool forwardToChildren = status != nsEventStatus_eConsumeNoDefault; DispatchMouseEvent(aMultiTouch, forwardToChildren); } }
void nsCoreUtils::DispatchClickEvent(nsITreeBoxObject *aTreeBoxObj, int32_t aRowIndex, nsITreeColumn *aColumn, const nsCString& aPseudoElt) { nsCOMPtr<nsIDOMElement> tcElm; aTreeBoxObj->GetTreeBody(getter_AddRefs(tcElm)); if (!tcElm) return; nsCOMPtr<nsIContent> tcContent(do_QueryInterface(tcElm)); nsIDocument *document = tcContent->GetCurrentDoc(); if (!document) return; nsIPresShell *presShell = nullptr; presShell = document->GetShell(); if (!presShell) return; // Ensure row is visible. aTreeBoxObj->EnsureRowIsVisible(aRowIndex); // Calculate x and y coordinates. int32_t x = 0, y = 0, width = 0, height = 0; nsresult rv = aTreeBoxObj->GetCoordsForCellItem(aRowIndex, aColumn, aPseudoElt, &x, &y, &width, &height); if (NS_FAILED(rv)) return; nsCOMPtr<nsIDOMXULElement> tcXULElm(do_QueryInterface(tcElm)); nsCOMPtr<nsIBoxObject> tcBoxObj; tcXULElm->GetBoxObject(getter_AddRefs(tcBoxObj)); int32_t tcX = 0; tcBoxObj->GetX(&tcX); int32_t tcY = 0; tcBoxObj->GetY(&tcY); // Dispatch mouse events. nsIFrame* tcFrame = tcContent->GetPrimaryFrame(); nsIFrame* rootFrame = presShell->GetRootFrame(); nsPoint offset; nsIWidget *rootWidget = rootFrame->GetViewExternal()->GetNearestWidget(&offset); nsPresContext* presContext = presShell->GetPresContext(); int32_t cnvdX = presContext->CSSPixelsToDevPixels(tcX + x + 1) + presContext->AppUnitsToDevPixels(offset.x); int32_t cnvdY = presContext->CSSPixelsToDevPixels(tcY + y + 1) + presContext->AppUnitsToDevPixels(offset.y); DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN, cnvdX, cnvdY, tcContent, tcFrame, presShell, rootWidget); DispatchMouseEvent(NS_MOUSE_BUTTON_UP, cnvdX, cnvdY, tcContent, tcFrame, presShell, rootWidget); }
// 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; }