Skip to content
Permalink
Browse files

GlobalShortcutWin: Exclude XInput devices from DirectInput.

This adds a dependency on a small library, XInputCheck, which is
a function abstracted away from SDL. All it does is check whether
a given DirectInput guidProduct is an XInput device.
  • Loading branch information...
mkrautz committed Mar 3, 2016
1 parent 93427af commit 6f1331b2e6bfe0acc90dbf2b7d188acc874a5793
@@ -0,0 +1,27 @@
include(../../compiler.pri)

BUILDDIR=$$basename(PWD)
SOURCEDIR=$$replace(BUILDDIR,-lib-build,-src)

TEMPLATE = lib
CONFIG -= qt
CONFIG += debug_and_release
CONFIG -= warn_on
CONFIG += warn_off
CONFIG += static
VPATH = ../xinputcheck-src
TARGET = xinputcheck
INCLUDEPATH = ../$$SOURCEDIR

SOURCES *= xinputcheck.cpp

CONFIG(debug, debug|release) {
CONFIG += console
DESTDIR = ../../debug
}

CONFIG(release, debug|release) {
DESTDIR = ../../release
}

include(../../symbols.pri)
@@ -0,0 +1,18 @@
Simple DirectMedia Layer
Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>

This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.

Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:

1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
@@ -0,0 +1,9 @@
XInputCheck is an XInput check abstracted away from SDL.

The content of xinputcheck.c is originally from SDL Hg c7932bb6dcee.
The files used are "" and "include/SDL_stdinc.h".

If you need to update this file, please arrange the code such that
it is possible to copy/paste directly from SDL. This makes code
sharing easier! Right now, the SDL_IsXInputDevice is directly
copied from SDL.
@@ -0,0 +1,113 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/

#include "xinputcheck.h"

#define SDL_bool bool
#define SDL_TRUE true
#define SDL_FALSE false

#define SDL_free free
#define SDL_malloc malloc
#define SDL_OutOfMemory abort
#define SDL_strstr strstr
#define SDL_memcmp memcmp

#define SDL_arraysize(array) (sizeof(array)/sizeof(array[0]))

static PRAWINPUTDEVICELIST SDL_RawDevList = NULL;
static UINT SDL_RawDevListCount = 0;

static SDL_bool
SDL_XINPUT_Enabled() {
return SDL_TRUE;
}

static SDL_bool
SDL_IsXInputDevice(const GUID* pGuidProductFromDirectInput)
{
static GUID IID_ValveStreamingGamepad = { MAKELONG(0x28DE, 0x11FF), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
static GUID IID_X360WiredGamepad = { MAKELONG(0x045E, 0x02A1), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
static GUID IID_X360WirelessGamepad = { MAKELONG(0x045E, 0x028E), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };

static const GUID *s_XInputProductGUID[] = {
&IID_ValveStreamingGamepad,
&IID_X360WiredGamepad, /* Microsoft's wired X360 controller for Windows. */
&IID_X360WirelessGamepad /* Microsoft's wireless X360 controller for Windows. */
};

size_t iDevice;
UINT i;

if (!SDL_XINPUT_Enabled()) {
return SDL_FALSE;
}

/* Check for well known XInput device GUIDs */
/* This lets us skip RAWINPUT for popular devices. Also, we need to do this for the Valve Streaming Gamepad because it's virtualized and doesn't show up in the device list. */
for (iDevice = 0; iDevice < SDL_arraysize(s_XInputProductGUID); ++iDevice) {
if (SDL_memcmp(pGuidProductFromDirectInput, s_XInputProductGUID[iDevice], sizeof(GUID)) == 0) {
return SDL_TRUE;
}
}

/* Go through RAWINPUT (WinXP and later) to find HID devices. */
/* Cache this if we end up using it. */
if (SDL_RawDevList == NULL) {
if ((GetRawInputDeviceList(NULL, &SDL_RawDevListCount, sizeof(RAWINPUTDEVICELIST)) == -1) || (!SDL_RawDevListCount)) {
return SDL_FALSE; /* oh well. */
}

SDL_RawDevList = (PRAWINPUTDEVICELIST)SDL_malloc(sizeof(RAWINPUTDEVICELIST) * SDL_RawDevListCount);
if (SDL_RawDevList == NULL) {
SDL_OutOfMemory();
return SDL_FALSE;
}

if (GetRawInputDeviceList(SDL_RawDevList, &SDL_RawDevListCount, sizeof(RAWINPUTDEVICELIST)) == -1) {
SDL_free(SDL_RawDevList);
SDL_RawDevList = NULL;
return SDL_FALSE; /* oh well. */
}
}

for (i = 0; i < SDL_RawDevListCount; i++) {
RID_DEVICE_INFO rdi;
char devName[128];
UINT rdiSize = sizeof(rdi);
UINT nameSize = SDL_arraysize(devName);

rdi.cbSize = sizeof(rdi);
if ((SDL_RawDevList[i].dwType == RIM_TYPEHID) &&
(GetRawInputDeviceInfoA(SDL_RawDevList[i].hDevice, RIDI_DEVICEINFO, &rdi, &rdiSize) != ((UINT)-1)) &&
(MAKELONG(rdi.hid.dwVendorId, rdi.hid.dwProductId) == ((LONG)pGuidProductFromDirectInput->Data1)) &&
(GetRawInputDeviceInfoA(SDL_RawDevList[i].hDevice, RIDI_DEVICENAME, devName, &nameSize) != ((UINT)-1)) &&
(SDL_strstr(devName, "IG_") != NULL)) {
return SDL_TRUE;
}
}

return SDL_FALSE;
}

bool XInputCheck_IsGuidProductXInputDevice(const GUID *pGuidProductFromDirectInput) {
return SDL_IsXInputDevice(pGuidProductFromDirectInput);
}
@@ -0,0 +1,29 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/

#ifndef XINPUTCHECK_H
#define XINPUTCHECK_H

#include <windows.h>

bool XInputCheck_IsGuidProductXInputDevice(const GUID *pGuidProductFromDirectInput);

#endif
@@ -31,6 +31,7 @@ SUBDIRS *= src/mumble_proto
}

win32 {
SUBDIRS *= 3rdparty/xinputcheck-build
SUBDIRS *= 3rdparty/minhook-build
}

@@ -78,7 +78,8 @@ ($$$)
["licenseQtTranslations", "../src/mumble/qttranslations/LICENSE",
"Additional Qt translations", "https://www.virtualbox.org/ticket/2018", "USING_BUNDLED_QT_TRANSLATIONS"],
["licenseFilterSvg", "../icons/filter.txt", "filter.svg icon", "https://commons.wikimedia.org/wiki/File:Filter.svg"],
["licenseEmojiOne", "../3rdPartyLicenses/cc_by_sa_40_legalcode.txt", "Emoji One artwork", "http://emojione.com/"]
["licenseEmojiOne", "../3rdPartyLicenses/cc_by_sa_40_legalcode.txt", "Emoji One artwork", "http://emojione.com/"],
["licenseXInputCheck", "../3rdparty/xinputcheck-src/COPYING.txt", "XInputCheck (SDL_IsXInput function)", "https://www.libsdl.org/"]
);

# Print 3rd party licenses
@@ -36,6 +36,9 @@
#include "OverlayClient.h"
#include "Global.h"

// 3rdparty/xinputcheck-src.
#include <xinputcheck.h>

#undef FAILED
#define FAILED(Status) (static_cast<HRESULT>(Status)<0)

@@ -444,6 +447,16 @@ BOOL GlobalShortcutWin::EnumDevicesCB(LPCDIDEVICEINSTANCE pdidi, LPVOID pContext
id->guidproduct = pdidi->guidProduct;
id->vguidproduct = QVariant(QUuid(id->guidproduct).toString());

// Is it an XInput device? Skip it.
//
// This check is not restricted to USE_XBOXINPUT because
// Windows 10 (10586.122, ~March 2016) has issues with
// using XInput devices via DirectInput.
if (XInputCheck_IsGuidProductXInputDevice(&id->guidproduct)) {
qWarning("GlobalShortcutWin: excluded XInput device '%s' (%s) from DirectInput", qPrintable(id->name), qPrintable(id->vguid.toString()));
return DIENUM_CONTINUE;
}

// Check for PIDVID at the end of the GUID, as
// per http://stackoverflow.com/q/25622780.
BYTE pidvid[8] = { 0, 0, 'P', 'I', 'D', 'V', 'I', 'D' };
@@ -19,17 +19,11 @@ struct ThirdPartyLicense {
};

static const char *licenseMumble =
"Copyright (C) 2005-2013, Thorvald Natvig <thorvald@natvig.com>\n"
"Copyright (C) 2007, Stefan Gehn <mETz AT gehn DOT net>\n"
"Copyright (C) 2007, Sebastian Schlingmann <mit_service@users.sourceforge.net>\n"
"Copyright (C) 2007, Trenton Schulz\n"
"Copyright (C) 2008-2016, Mikkel Krautz <mikkel@krautz.dk>\n"
"Copyright (C) 2008, Andreas Messer <andi@bupfen.de>\n"
"Copyright (C) 2008-2016, Stefan Hacker <dd0t@users.sourceforge.net>\n"
"Copyright (C) 2008-2011, Snares <snares@users.sourceforge.net>\n"
"Copyright (C) 2009-2013, Benjamin Jemlich <pcgod@users.sourceforge.net>\n"
"Copyright (C) 2009-2016, Kissaki <kissaki@gmx.de>\n"
"Copyright (C) 2010-2016, Jamie Fraser <jamie.f@mumbledog.com>\n"
"Copyright (C) 2005-2016 The Mumble Developers\n"
"\n"
"A list of The Mumble Developers can be found in the\n"
"AUTHORS file at the root of the Mumble source tree\n"
"or at <https://www.mumble.info/AUTHORS>.\n"
"\n"
"All rights reserved.\n"
"\n"
@@ -42,7 +36,7 @@ static const char *licenseMumble =
"- Redistributions in binary form must reproduce the above copyright notice,\n"
" this list of conditions and the following disclaimer in the documentation\n"
" and/or other materials provided with the distribution.\n"
"- Neither the name of the Mumble Developers nor the names of its\n"
"- Neither the name of The Mumble Developers nor the names of its\n"
" contributors may be used to endorse or promote products derived from this\n"
" software without specific prior written permission.\n"
"\n"
@@ -56,7 +50,10 @@ static const char *licenseMumble =
"PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\n"
"LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n"
"NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n"
"SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.";
"SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
"\n"
"For questions and inquiries about Mumble's license,\n"
"please contact <license@mumble.info>.";


static const char *licenseCELT =
@@ -856,6 +853,28 @@ static const char *licenseEmojiOne =
" processes of any jurisdiction or authority.";


static const char *licenseXInputCheck =
"\n"
"Simple DirectMedia Layer\n"
"Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>\n"
" \n"
"This software is provided 'as-is', without any express or implied\n"
"warranty. In no event will the authors be held liable for any damages\n"
"arising from the use of this software.\n"
"\n"
"Permission is granted to anyone to use this software for any purpose,\n"
"including commercial applications, and to alter it and redistribute it\n"
"freely, subject to the following restrictions:\n"
" \n"
"1. The origin of this software must not be misrepresented; you must not\n"
" claim that you wrote the original software. If you use this software\n"
" in a product, an acknowledgment in the product documentation would be\n"
" appreciated but is not required. \n"
"2. Altered source versions must be plainly marked as such, and must not be\n"
" misrepresented as being the original software.\n"
"3. This notice may not be removed or altered from any source distribution.";


static const ThirdPartyLicense licenses3rdParties[] = {
ThirdPartyLicense("CELT", "http://www.celt-codec.org/", licenseCELT),
ThirdPartyLicense("Opus", "http://www.opus-codec.org/", licenseOpus),
@@ -876,6 +895,7 @@ static const ThirdPartyLicense licenses3rdParties[] = {
#endif
ThirdPartyLicense("filter.svg icon", "https://commons.wikimedia.org/wiki/File:Filter.svg", licenseFilterSvg),
ThirdPartyLicense("Emoji One artwork", "http://emojione.com/", licenseEmojiOne),
ThirdPartyLicense("XInputCheck (SDL_IsXInput function)", "https://www.libsdl.org/", licenseXInputCheck),
ThirdPartyLicense(),
};

@@ -405,6 +405,10 @@ win32 {
DEFINES *= USE_XBOXINPUT
}

# XInputCheck (3rdparty/xinputheck-src)
INCLUDEPATH *= ../../3rdparty/xinputcheck-src
LIBS *= -lxinputcheck

!CONFIG(mumble_dll) {
!CONFIG(no-elevation) {
CONFIG(release, debug|release) {

0 comments on commit 6f1331b

Please sign in to comment.
You can’t perform that action at this time.