diff --git a/src/Gui/View3DInventorViewer.cpp b/src/Gui/View3DInventorViewer.cpp index f6bd20ebf..a61eae760 100644 --- a/src/Gui/View3DInventorViewer.cpp +++ b/src/Gui/View3DInventorViewer.cpp @@ -219,16 +219,25 @@ public: if (obj->isWidgetType()) { View3DInventorViewer* v = dynamic_cast(obj); if(v) { - if(! v->isWinGesturesTuned) { - v->isWinGesturesTuned = true; + /* Internally, Qt seems to set up the gestures upon showing the + * widget (but after this event is processed), thus invalidating + * our settings. This piece takes care to retune gestures on the + * next event after the show event. + */ + if(v->winGestureTuneState == View3DInventorViewer::ewgtsNeedTuning) { try{ WinNativeGestureRecognizerPinch::TuneWindowsGestures(v); + v->winGestureTuneState = View3DInventorViewer::ewgtsTuned; + } catch (Base::Exception &e) { + Base::Console().Warning("Failed to TuneWindowsGestures. Error: %s\n",e.what()); + v->winGestureTuneState = View3DInventorViewer::ewgtsDisabled; } catch (...){ - Base::Console().Warning("Failed to TuneWindowsGestures.\n"); + Base::Console().Warning("Failed to TuneWindowsGestures. Unknown error.\n"); + v->winGestureTuneState = View3DInventorViewer::ewgtsDisabled; } } - if (event->type() == QEvent::Show) - v->isWinGesturesTuned = false;//internally, Qt seems to set up the gestures upon showing the widget (but after this event is processed), thus invalidating our settings. Needs to be re-tuned asap. + if (event->type() == QEvent::Show && v->winGestureTuneState == View3DInventorViewer::ewgtsTuned) + v->winGestureTuneState = View3DInventorViewer::ewgtsNeedTuning; } } @@ -485,18 +494,25 @@ void View3DInventorViewer::init() getEventFilter()->registerInputDevice(new SpaceNavigatorDevice); getEventFilter()->registerInputDevice(new GesturesDevice(this)); - this->grabGesture(Qt::PanGesture); - this->grabGesture(Qt::PinchGesture); -#ifdef GESTURE_MESS - { - static WinNativeGestureRecognizerPinch* recognizer;//static to avoid creating more than one recognizer, thus causing memory leak and gradual slowdown - if(recognizer == 0){ - recognizer = new WinNativeGestureRecognizerPinch; - recognizer->registerRecognizer(recognizer); //From now on, Qt owns the pointer. + this->winGestureTuneState = View3DInventorViewer::ewgtsDisabled; + try{ + this->grabGesture(Qt::PanGesture); + this->grabGesture(Qt::PinchGesture); + #ifdef GESTURE_MESS + { + static WinNativeGestureRecognizerPinch* recognizer;//static to avoid creating more than one recognizer, thus causing memory leak and gradual slowdown + if(recognizer == 0){ + recognizer = new WinNativeGestureRecognizerPinch; + recognizer->registerRecognizer(recognizer); //From now on, Qt owns the pointer. + } } + this->winGestureTuneState = View3DInventorViewer::ewgtsNeedTuning; + #endif + } catch (Base::Exception &e) { + Base::Console().Warning("Failed to set up gestures. Error: %s\n", e.what()); + } catch (...) { + Base::Console().Warning("Failed to set up gestures. Unknown error.\n"); } - this->isWinGesturesTuned = false; -#endif //create the cursors QBitmap cursor = QBitmap::fromData(QSize(ROTATE_WIDTH, ROTATE_HEIGHT), rotate_bitmap); diff --git a/src/Gui/View3DInventorViewer.h b/src/Gui/View3DInventorViewer.h index 0809f6deb..283e2f171 100644 --- a/src/Gui/View3DInventorViewer.h +++ b/src/Gui/View3DInventorViewer.h @@ -357,12 +357,13 @@ protected: SbBool processSoEventBase(const SoEvent * const ev); void printDimension(); void selectAll(); - /** A flag. If false, gestures on windows will get tuned(or re-tuned) - * upon the first event that arrives to eventFilter. This is needed to - * tune windows gestures after Qt does it internally, since its settings - * are not all right for us. - */ - bool isWinGesturesTuned; + + enum eWinGestureTuneState{ + ewgtsDisabled, //suppress tuning/re-tuning after errors + ewgtsNeedTuning, //gestures are to be retuned upon next event + ewgtsTuned + }; + eWinGestureTuneState winGestureTuneState;//See ViewerEventFilter::eventFilter function for explanation private: static void setViewportCB(void * userdata, SoAction * action); diff --git a/src/Gui/WinNativeGestureRecognizers.cpp b/src/Gui/WinNativeGestureRecognizers.cpp index b1cd3b6ed..5ac07ef48 100644 --- a/src/Gui/WinNativeGestureRecognizers.cpp +++ b/src/Gui/WinNativeGestureRecognizers.cpp @@ -41,6 +41,7 @@ #include #include +#include QT_BEGIN_NAMESPACE @@ -188,10 +189,28 @@ void WinNativeGestureRecognizerPinch::reset(QGesture* gesture) q->fingerDistance = 0; } +//function prototype for dymanic linking +typedef BOOL ( __stdcall * ptrSetGestureConfig) ( + HWND , // window for which configuration is specified + DWORD , // reserved, must be 0 + UINT , // count of GESTURECONFIG structures + PGESTURECONFIG , // array of GESTURECONFIG structures, dwIDs will be processed in the + // order specified and repeated occurances will overwrite previous ones + UINT ); // sizeof(GESTURECONFIG) + void WinNativeGestureRecognizerPinch::TuneWindowsGestures(QWidget* target) { //modify windows-specific gesture options #if WINVER >= _WIN32_WINNT_WIN7 + //dynamic linking - required to be able to run on windows pre-7 + HINSTANCE hinstLib = LoadLibraryA("user32.dll"); + if (hinstLib == 0) + throw Base::Exception("LoadLibrary(user32.dll) failed. Could not tune Windows gestures."); + + ptrSetGestureConfig dllSetGestureConfig = reinterpret_cast (GetProcAddress(hinstLib,"SetGestureConfig")); + if (dllSetGestureConfig == 0) + throw Base::Exception("DLL entry point for SetGestureConfig not found in user32.dll. Could not tune Windows gestures."); + HWND w = target->winId(); //fill in the options @@ -205,10 +224,12 @@ void WinNativeGestureRecognizerPinch::TuneWindowsGestures(QWidget* target) cfgs[1].dwWant = GC_ROTATE; //set the options - bool ret = SetGestureConfig(w, 0, nCfg, cfgs, sizeof(GESTURECONFIG)); - assert(ret); //if(!ret) throw + bool ret = dllSetGestureConfig(w, 0, nCfg, cfgs, sizeof(GESTURECONFIG)); + assert(ret); if(!ret){ - DWORD err = GetLastError();//for debugging + DWORD err = GetLastError(); + QString errMsg = QString::fromLatin1("Error in SetGestureConfig. GetLastError = %1").arg(err); + throw Base::Exception(errMsg.toLatin1()); } #endif }