void CSMQT4GLWidget::mouseMoveEvent(QMouseEvent *pEvent) { if(_pOSGWindow != NULL) { _pOSGWindow->motion(pEvent->x(), pEvent->y(), mapModifier(pEvent->modifiers())); } }
void CSMQT4GLWidget::mouseReleaseEvent(QMouseEvent *pEvent) { if(_pOSGWindow != NULL) { _pOSGWindow->mouse(mapButton(pEvent->button()), MouseData::ButtonUp, mapModifier(pEvent->modifiers()), pEvent->x(), pEvent->y()); } }
void CSMQT4GLWidget::wheelEvent(QWheelEvent *pEvent) { if(_pOSGWindow != NULL) { if(pEvent->delta() < 0) { _pOSGWindow->mouse(MouseData::WheelUpButton, MouseData::ButtonDown, mapModifier(pEvent->modifiers()), pEvent->x(), pEvent->y()); } else { _pOSGWindow->mouse(MouseData::WheelDownButton, MouseData::ButtonDown, mapModifier(pEvent->modifiers()), pEvent->x(), pEvent->y()); } } }
void CSMNativeWindow::xMainLoop(void) { XEvent event; char buffer[31]; KeySym keysym; // Sleep 2 sec to open the window; //sleep(_uiCreateNapTime); //sleep(1); osgSleep(100); while(_bRun == true) { WindowListIt winIt = _vWindowList.begin(); WindowListConstIt winEnd = _vWindowList.end (); while(winIt != winEnd) { Display *pDisplay = (*winIt)->getDisplay(); while(XPending(pDisplay)) { XNextEvent(pDisplay, &event); switch(event.type) { case KeyPress: XLookupString(&event.xkey, buffer, 30, &keysym, NULL); #if 0 fprintf(stderr, "%x %x %x\n", keysym, XK_F12, XK_Home); #endif if(keysym == XK_Escape) { _bRun = false; } else if(keysym == XK_End) { fprintf(stderr, "Dump\n"); (*winIt)->getWindow()->getShaderCache()->dump(); } else if(keysym == XK_F12) { FieldContainerFactory::the()->dump(); } else if(keysym == XK_F11) { fprintf(stderr, "dump vp[0] root\n"); Window *pWin = (*winIt)->getWindow(); if(pWin != NULL) { Viewport *pPort = pWin->getPort(0); if(pPort != NULL) { fprintf(stderr, "root %p\n", static_cast<void *>( pPort->getRoot())); DotFileGeneratorGraphOpRefPtr pGO = DotFileGeneratorGraphOp::create(); pGO->traverse(pPort->getRoot()); } else { fprintf(stderr, "viewport NULL\n"); } } else { fprintf(stderr, "win NULL\n"); } } else if(keysym == XK_F10) { fprintf(stderr, "osg dump vp[0] root\n"); Window *pWin = (*winIt)->getWindow(); if(pWin != NULL) { Viewport *pPort = pWin->getPort(0); if(pPort != NULL) { fprintf(stderr, "root %p\n", static_cast<void *>( pPort->getRoot())); SceneFileHandler::the()->write( pPort->getRoot(), "/tmp/csm.osg"); } else { fprintf(stderr, "viewport NULL\n"); } } else { fprintf(stderr, "win NULL\n"); } } else if(keysym == XK_F8) { fprintf(stderr, "pass mask pool\n"); fprintf(stderr, "================\n"); PassMaskPool::the()->dump(); fprintf(stderr, "render prop pool\n"); fprintf(stderr, "================\n"); RenderPropertiesPool::the()->dump(); } else if(keysym == XK_Home) { ComplexSceneManager::the()->resetScene(); } else if((XK_space <= keysym) && (XK_asciitilde >= keysym)) { ComplexSceneManager::the()->key( event.xkey.x, event.xkey.y, CSMKeyData::ButtonDown, Char8(keysym)); } break; case KeyRelease: XLookupString(&event.xkey, buffer, 30, &keysym, NULL); //fprintf(stderr, "%x\n", keysym); if(keysym == XK_Escape) { } else if((XK_space <= keysym) && (XK_asciitilde >= keysym)) { ComplexSceneManager::the()->key( event.xkey.x, event.xkey.y, CSMKeyData::ButtonUp, Char8(keysym)); } break; case ButtonPress: (*winIt)->mouse(event.xbutton.button - 1, MouseData::ButtonDown, mapModifier(event.xbutton.state), event.xbutton.x, event.xbutton.y); break; case ButtonRelease: (*winIt)->mouse(event.xbutton.button - 1, MouseData::ButtonUp, mapModifier(event.xbutton.state), event.xbutton.x, event.xbutton.y); break; case MotionNotify: (*winIt)->motion(event.xbutton.x, event.xbutton.y, mapModifier(event.xbutton.state)); break; case ConfigureNotify: { (*winIt)->reshape(event.xconfigure.width, event.xconfigure.height); } break; default: break; } } ++winIt; } ComplexSceneManager::the()->frame(); Thread::getCurrentChangeList()->commitChangesAndClear(); } ComplexSceneManager::the()->terminate(); }
bool CXWindowsPrimaryScreen::onEvent(CEvent* event) { assert(event != NULL); XEvent& xevent = event->m_event; // let input methods try to handle event first if (m_ic != NULL) { // XFilterEvent() may eat the event and generate a new KeyPress // event with a keycode of 0 because there isn't an actual key // associated with the keysym. but the KeyRelease may pass // through XFilterEvent() and keep its keycode. this means // there's a mismatch between KeyPress and KeyRelease keycodes. // since we use the keycode on the client to detect when a key // is released this won't do. so we remember the keycode on // the most recent KeyPress (and clear it on a matching // KeyRelease) so we have a keycode for a synthesized KeyPress. if (xevent.type == KeyPress && xevent.xkey.keycode != 0) { m_lastKeycode = xevent.xkey.keycode; } else if (xevent.type == KeyRelease && xevent.xkey.keycode == m_lastKeycode) { m_lastKeycode = 0; } // now filter the event if (XFilterEvent(&xevent, None)) { return true; } } // handle event switch (xevent.type) { case CreateNotify: { // select events on new window CDisplayLock display(m_screen); selectEvents(display, xevent.xcreatewindow.window); } return true; case MappingNotify: // keyboard mapping changed updateKeys(); return true; case KeyPress: { LOG((CLOG_DEBUG1 "event: KeyPress code=%d, state=0x%04x", xevent.xkey.keycode, xevent.xkey.state)); const KeyModifierMask mask = mapModifier(xevent.xkey.state); KeyID key = mapKey(&xevent.xkey); if (key != kKeyNone) { // check for ctrl+alt+del emulation if ((key == kKeyPause || key == kKeyBreak) && (mask & (KeyModifierControl | KeyModifierAlt)) == (KeyModifierControl | KeyModifierAlt)) { // pretend it's ctrl+alt+del LOG((CLOG_DEBUG "emulate ctrl+alt+del")); key = kKeyDelete; } // get which button. see call to XFilterEvent() above // for more info. KeyCode keycode = xevent.xkey.keycode; if (keycode == 0) { keycode = m_lastKeycode; } // handle key m_receiver->onKeyDown(key, mask, static_cast<KeyButton>(keycode)); if (key == kKeyCapsLock && m_capsLockHalfDuplex) { m_receiver->onKeyUp(key, mask | KeyModifierCapsLock, static_cast<KeyButton>(keycode)); } else if (key == kKeyNumLock && m_numLockHalfDuplex) { m_receiver->onKeyUp(key, mask | KeyModifierNumLock, static_cast<KeyButton>(keycode)); } } } return true; case KeyRelease: { const KeyModifierMask mask = mapModifier(xevent.xkey.state); KeyID key = mapKey(&xevent.xkey); if (key != kKeyNone) { // check if this is a key repeat by getting the next // KeyPress event that has the same key and time as // this release event, if any. first prepare the // filter info. CKeyEventInfo filter; filter.m_event = KeyPress; filter.m_window = xevent.xkey.window; filter.m_time = xevent.xkey.time; filter.m_keycode = xevent.xkey.keycode; // now check for event bool hasPress; { XEvent xevent2; CDisplayLock display(m_screen); hasPress = (XCheckIfEvent(display, &xevent2, &CXWindowsPrimaryScreen::findKeyEvent, (XPointer)&filter) == True); } // check for ctrl+alt+del emulation if ((key == kKeyPause || key == kKeyBreak) && (mask & (KeyModifierControl | KeyModifierAlt)) == (KeyModifierControl | KeyModifierAlt)) { // pretend it's ctrl+alt+del and ignore autorepeat LOG((CLOG_DEBUG "emulate ctrl+alt+del")); key = kKeyDelete; hasPress = false; } if (!hasPress) { // no press event follows so it's a plain release LOG((CLOG_DEBUG1 "event: KeyRelease code=%d, state=0x%04x", xevent.xkey.keycode, xevent.xkey.state)); if (key == kKeyCapsLock && m_capsLockHalfDuplex) { m_receiver->onKeyDown(key, mask, static_cast<KeyButton>(xevent.xkey.keycode)); } else if (key == kKeyNumLock && m_numLockHalfDuplex) { m_receiver->onKeyDown(key, mask, static_cast<KeyButton>(xevent.xkey.keycode)); } m_receiver->onKeyUp(key, mask, static_cast<KeyButton>(xevent.xkey.keycode)); } else { // found a press event following so it's a repeat. // we could attempt to count the already queued // repeats but we'll just send a repeat of 1. // note that we discard the press event. LOG((CLOG_DEBUG1 "event: repeat code=%d, state=0x%04x", xevent.xkey.keycode, xevent.xkey.state)); m_receiver->onKeyRepeat(key, mask, 1, static_cast<KeyButton>(xevent.xkey.keycode)); } } } return true; case ButtonPress: { LOG((CLOG_DEBUG1 "event: ButtonPress button=%d", xevent.xbutton.button)); const ButtonID button = mapButton(xevent.xbutton.button); if (button != kButtonNone) { m_receiver->onMouseDown(button); } } return true; case ButtonRelease: { LOG((CLOG_DEBUG1 "event: ButtonRelease button=%d", xevent.xbutton.button)); const ButtonID button = mapButton(xevent.xbutton.button); if (button != kButtonNone) { m_receiver->onMouseUp(button); } else if (xevent.xbutton.button == 4) { // wheel forward (away from user) m_receiver->onMouseWheel(120); } else if (xevent.xbutton.button == 5) { // wheel backward (toward user) m_receiver->onMouseWheel(-120); } } return true; case MotionNotify: { LOG((CLOG_DEBUG2 "event: MotionNotify %d,%d", xevent.xmotion.x_root, xevent.xmotion.y_root)); // compute motion delta (relative to the last known // mouse position) SInt32 x = xevent.xmotion.x_root - m_x; SInt32 y = xevent.xmotion.y_root - m_y; // save position to compute delta of next motion m_x = xevent.xmotion.x_root; m_y = xevent.xmotion.y_root; if (xevent.xmotion.send_event) { // we warped the mouse. discard events until we // find the matching sent event. see // warpCursorNoFlush() for where the events are // sent. we discard the matching sent event and // can be sure we've skipped the warp event. CDisplayLock display(m_screen); do { XMaskEvent(display, PointerMotionMask, &xevent); } while (!xevent.xmotion.send_event); } else if (!isActive()) { // motion on primary screen m_receiver->onMouseMovePrimary(m_x, m_y); } else { // motion on secondary screen. warp mouse back to // center. // // my lombard (powerbook g3) running linux and // using the adbmouse driver has two problems: // first, the driver only sends motions of +/-2 // pixels and, second, it seems to discard some // physical input after a warp. the former isn't a // big deal (we're just limited to every other // pixel) but the latter is a PITA. to work around // it we only warp when the mouse has moved more // than s_size pixels from the center. static const SInt32 s_size = 32; if (xevent.xmotion.x_root - m_xCenter < -s_size || xevent.xmotion.x_root - m_xCenter > s_size || xevent.xmotion.y_root - m_yCenter < -s_size || xevent.xmotion.y_root - m_yCenter > s_size) { CDisplayLock display(m_screen); warpCursorNoFlush(display, m_xCenter, m_yCenter); } // send event if mouse moved. do this after warping // back to center in case the motion takes us onto // the primary screen. if we sent the event first // in that case then the warp would happen after // warping to the primary screen's enter position, // effectively overriding it. if (x != 0 || y != 0) { m_receiver->onMouseMoveSecondary(x, y); } } } return true; } return false; }