diff --git a/include/nil.h b/include/nil.h index c284acd..23b1892 100644 --- a/include/nil.h +++ b/include/nil.h @@ -485,6 +485,7 @@ namespace Nil { DIDEVCAPS mDICapabilities; //!< DirectInput capabilities size_t mAxisEnum; //!< Internal axis enumeration size_t mSliderEnum; //!< Internal slider enumeration + const Cooperation mCooperation; //!< Cooperation mode //! Axis value filter. inline Real filterAxis( int val ); @@ -495,7 +496,7 @@ namespace Nil { public: //! Constructor. //! \param device The device. - DirectInputController( DirectInputDevice* device ); + DirectInputController( DirectInputDevice* device, const Cooperation coop ); virtual void update(); @@ -600,6 +601,7 @@ namespace Nil { Logitech::GKeySDK* mLogitechGKeys; //!< External module for Logitech G-Keys Logitech::LedSDK* mLogitechLEDs; //!< External module for Logitech LEDs SystemListener* mListener; //!< Our single event listener + const Cooperation mCooperation; //!< Cooperation mode void initializeDevices(); void refreshDevices(); void identifyXInputDevices(); @@ -638,8 +640,10 @@ namespace Nil { //! Constructor. //! \param instance Handle of the host instance. //! \param window Handle of the host window. + //! \param coop Cooperation mode. //! \param listener Listener for system events. - System( HINSTANCE instance, HWND window, SystemListener* listener ); + System( HINSTANCE instance, HWND window, const Cooperation coop, + SystemListener* listener ); //! Updates this System. //! All listened events get triggered from inside this call. diff --git a/include/nilPnP.h b/include/nilPnP.h index 533aa92..767f2d5 100644 --- a/include/nilPnP.h +++ b/include/nilPnP.h @@ -76,6 +76,7 @@ namespace Nil { RawListenerList mRawListeners; //!< Our raw listeners void* mInputBuffer; //!< Buffer for input reads unsigned int mInputBufferSize; //!< Size of input buffer + const Cooperation mCooperation; //!< Cooperation mode protected: //! \b Internal Register myself for event notifications. void registerNotifications(); @@ -104,7 +105,7 @@ namespace Nil { static LRESULT CALLBACK wndProc( HWND window, UINT message, WPARAM wParam, LPARAM lParam ); public: - EventMonitor( HINSTANCE instance ); + EventMonitor( HINSTANCE instance, const Cooperation coop ); //! Register a listener for Plug-n-Play events. void registerPnPListener( PnPListener* listener ); diff --git a/include/nilTypes.h b/include/nilTypes.h index 0ad2c9e..d1268ef 100644 --- a/include/nilTypes.h +++ b/include/nilTypes.h @@ -52,6 +52,11 @@ namespace Nil { typedef std::string utf8String; //!< UTF-8 string type. typedef std::wstring String; //!< Wide string type. + enum Cooperation: int { + Cooperation_Foreground, + Cooperation_Background + }; + using std::map; using std::list; using std::queue; diff --git a/src/Device.cpp b/src/Device.cpp index 98d350d..5766368 100644 --- a/src/Device.cpp +++ b/src/Device.cpp @@ -51,7 +51,7 @@ namespace Nil { NIL_EXCEPT( L"Dynamic cast failed for DirectInputDevice" ); if ( getType() == Device_Controller ) { - mInstance = new DirectInputController( diDevice ); + mInstance = new DirectInputController( diDevice, mSystem->mCooperation ); mSystem->controllerEnabled( this, (Controller*)mInstance ); } else diff --git a/src/DirectInputController.cpp b/src/DirectInputController.cpp index da46a82..ab77e09 100644 --- a/src/DirectInputController.cpp +++ b/src/DirectInputController.cpp @@ -14,8 +14,10 @@ namespace Nil { const unsigned long cJoystickEvents = 64; - DirectInputController::DirectInputController( DirectInputDevice* device ): - Controller( device->getSystem(), device ), mDIDevice( nullptr ), mAxisEnum( 0 ) + DirectInputController::DirectInputController( DirectInputDevice* device, + const Cooperation coop ): + Controller( device->getSystem(), device ), mDIDevice( nullptr ), + mAxisEnum( 0 ), mCooperation( coop ) { HRESULT hr = device->getSystem()->mDirectInput->CreateDevice( device->getInstanceID(), &mDIDevice, NULL ); @@ -26,7 +28,11 @@ namespace Nil { if ( FAILED( hr ) ) NIL_EXCEPT_DINPUT( hr, L"Could not set DirectInput8 device data format" ); - hr = mDIDevice->SetCooperativeLevel( device->getSystem()->mWindow, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE ); + // Force feedback, to be implemented later, requires exclusive access. + hr = mDIDevice->SetCooperativeLevel( device->getSystem()->mWindow, + ( mCooperation == Cooperation_Background ) + ? DISCL_BACKGROUND | DISCL_EXCLUSIVE + : DISCL_FOREGROUND | DISCL_EXCLUSIVE ); if ( FAILED( hr ) ) NIL_EXCEPT_DINPUT( hr, L"Could not set DirectInput8 device cooperation level" ); diff --git a/src/DirectInputDevice.cpp b/src/DirectInputDevice.cpp index 4d0b30e..08c6c20 100644 --- a/src/DirectInputDevice.cpp +++ b/src/DirectInputDevice.cpp @@ -3,7 +3,7 @@ namespace Nil { - Device::Type resolveDIDeviceType( unsigned long type ) + inline Device::Type resolveDIDeviceType( unsigned long type ) { type = GET_DIDEVICE_TYPE( type ); diff --git a/src/EventMonitor.cpp b/src/EventMonitor.cpp index 8215087..f5e0dfd 100644 --- a/src/EventMonitor.cpp +++ b/src/EventMonitor.cpp @@ -5,9 +5,9 @@ namespace Nil { const wchar_t* cEventMonitorClass = L"NIL_MONITOR"; - EventMonitor::EventMonitor( HINSTANCE instance ): + EventMonitor::EventMonitor( HINSTANCE instance, const Cooperation coop ): mInstance( instance ), mClass( 0 ), mWindow( 0 ), mNotifications( 0 ), - mInputBuffer( nullptr ), + mInputBuffer( nullptr ), mCooperation( coop ), mInputBufferSize( 10240 ) // 10KB default { WNDCLASSEXW wx = { 0 }; @@ -132,12 +132,18 @@ namespace Nil { RAWINPUTDEVICE rawDevices[2]; - rawDevices[0].dwFlags = RIDEV_DEVNOTIFY | RIDEV_INPUTSINK; + rawDevices[0].dwFlags = + ( mCooperation == Cooperation_Background ) + ? RIDEV_DEVNOTIFY | RIDEV_INPUTSINK + : RIDEV_DEVNOTIFY; rawDevices[0].hwndTarget = mWindow; rawDevices[0].usUsagePage = USBUsagePage_Desktop; rawDevices[0].usUsage = USBDesktopUsage_Mice; - rawDevices[1].dwFlags = RIDEV_DEVNOTIFY | RIDEV_INPUTSINK; + rawDevices[1].dwFlags = + ( mCooperation == Cooperation_Background ) + ? RIDEV_DEVNOTIFY | RIDEV_INPUTSINK + : RIDEV_DEVNOTIFY; rawDevices[1].hwndTarget = mWindow; rawDevices[1].usUsagePage = USBUsagePage_Desktop; rawDevices[1].usUsage = USBDesktopUsage_Keyboards; diff --git a/src/System.cpp b/src/System.cpp index 2aa0105..ff5e824 100644 --- a/src/System.cpp +++ b/src/System.cpp @@ -4,7 +4,8 @@ namespace Nil { - System::System( HINSTANCE instance, HWND window, SystemListener* listener ): + System::System( HINSTANCE instance, HWND window, const Cooperation coop, + SystemListener* listener ): mCooperation( coop ), mWindow( window ), mInstance( instance ), mDirectInput( nullptr ), mMonitor( nullptr ), mIDPool( 0 ), mInitializing( true ), mHIDManager( nullptr ), mLogitechGKeys( nullptr ), mLogitechLEDs( nullptr ), @@ -27,7 +28,7 @@ namespace Nil { NIL_EXCEPT_DINPUT( hr, L"Could not instance DirectInput 8" ); // Initialize our event monitor - mMonitor = new EventMonitor( mInstance ); + mMonitor = new EventMonitor( mInstance, mCooperation ); // Initialize our HID manager mHIDManager = new HIDManager(); diff --git a/test/Test.cpp b/test/Test.cpp index 43e683d..d89e433 100644 --- a/test/Test.cpp +++ b/test/Test.cpp @@ -191,7 +191,14 @@ int wmain( int argc, wchar_t* argv[], wchar_t* envp[] ) // Init system Nil::System* system = new Nil::System( - GetModuleHandleW( nullptr ), GetConsoleWindow(), &gMyListener ); + GetModuleHandleW( nullptr ), + GetConsoleWindow(), + // Using background cooperation mode, because the default console window + // is actually not owned by our process (it is owned by cmd.exe) and thus + // we would not receive any mouse & keyboard events in foreground mode. + // For applications that own their own window foreground mode works fine. + Nil::Cooperation_Background, + &gMyListener ); // Init Logitech G-keys subsystem, if available Nil::ExternalModule::InitReturn ret = system->getLogitechGKeys()->initialize();