Add 3dconnexion driver version check

Re-enable 3dconnexion driver by default as we are able to gate the
driver versions

Fixes https://gitlab.com/kicad/code/kicad/-/issues/13362
This commit is contained in:
Seth Hillbrand 2023-06-13 09:44:22 -07:00
parent eeb74dbae9
commit 32ad42a435
16 changed files with 320 additions and 65 deletions

View File

@ -532,7 +532,9 @@ void EDA_3D_CANVAS::DoRePaint()
render_pivot( curtime_delta_s, scale ); render_pivot( curtime_delta_s, scale );
} }
if( m_render3dmousePivot && ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver ) // This will only be enabled by the 3d mouse plugin, so we can leave
// it as a simple if statement
if( m_render3dmousePivot )
{ {
const float scale = glm::min( m_camera.GetZoom(), 1.0f ); const float scale = glm::min( m_camera.GetZoom(), 1.0f );
render3dmousePivot( scale ); render3dmousePivot( scale );

View File

@ -21,14 +21,17 @@
#include "nl_3d_viewer_plugin.h" #include "nl_3d_viewer_plugin.h"
#include "nl_3d_viewer_plugin_impl.h" #include "nl_3d_viewer_plugin_impl.h"
#include <advanced_config.h> #include <advanced_config.h>
#include <kiplatform/drivers.h>
NL_3D_VIEWER_PLUGIN::NL_3D_VIEWER_PLUGIN( EDA_3D_CANVAS* aViewport ) NL_3D_VIEWER_PLUGIN::NL_3D_VIEWER_PLUGIN( EDA_3D_CANVAS* aViewport )
: m_impl( nullptr )
{ {
if( ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver ) if( ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver
&& KIPLATFORM::DRIVERS::Valid3DConnexionDriverVersion() )
{
m_impl = new NL_3D_VIEWER_PLUGIN_IMPL( aViewport ); m_impl = new NL_3D_VIEWER_PLUGIN_IMPL( aViewport );
else }
m_impl = nullptr;
} }
@ -40,6 +43,6 @@ NL_3D_VIEWER_PLUGIN::~NL_3D_VIEWER_PLUGIN()
void NL_3D_VIEWER_PLUGIN::SetFocus( bool focus ) void NL_3D_VIEWER_PLUGIN::SetFocus( bool focus )
{ {
if( ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver ) if( m_impl )
m_impl->SetFocus( focus ); m_impl->SetFocus( focus );
} }

View File

@ -165,17 +165,13 @@ EDA_3D_VIEWER_FRAME::EDA_3D_VIEWER_FRAME( KIWAY* aKiway, PCB_BASE_FRAME* aParent
m_canvas->SetInfoBar( m_infoBar ); m_canvas->SetInfoBar( m_infoBar );
m_canvas->SetStatusBar( status_bar ); m_canvas->SetStatusBar( status_bar );
try
if( ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver )
{ {
try m_spaceMouse = new NL_3D_VIEWER_PLUGIN( m_canvas );
{ }
m_spaceMouse = new NL_3D_VIEWER_PLUGIN( m_canvas ); catch( const std::system_error& e )
} {
catch( const std::system_error& e ) wxLogTrace( wxT( "KI_TRACE_NAVLIB" ), e.what() );
{
wxLogTrace( wxT( "KI_TRACE_NAVLIB" ), e.what() );
}
} }
// Fixes bug in Windows (XP and possibly others) where the canvas requires the focus // Fixes bug in Windows (XP and possibly others) where the canvas requires the focus
@ -336,11 +332,8 @@ void EDA_3D_VIEWER_FRAME::handleIconizeEvent( wxIconizeEvent& aEvent )
{ {
KIWAY_PLAYER::handleIconizeEvent( aEvent ); KIWAY_PLAYER::handleIconizeEvent( aEvent );
if( m_spaceMouse != nullptr && aEvent.IsIconized() if( m_spaceMouse && aEvent.IsIconized() )
&& ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver )
{
m_spaceMouse->SetFocus( false ); m_spaceMouse->SetFocus( false );
}
} }
@ -656,7 +649,7 @@ void EDA_3D_VIEWER_FRAME::OnActivate( wxActivateEvent &aEvent )
m_canvas->SetFocus(); m_canvas->SetFocus();
} }
if( m_spaceMouse != nullptr && ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver ) if( m_spaceMouse )
m_spaceMouse->SetFocus( aEvent.GetActive() ); m_spaceMouse->SetFocus( aEvent.GetActive() );
aEvent.Skip(); // required under wxMAC aEvent.Skip(); // required under wxMAC

View File

@ -337,12 +337,7 @@ ADVANCED_CFG::ADVANCED_CFG()
m_UseClipper2 = true; m_UseClipper2 = true;
#ifdef _WIN32 m_Use3DConnexionDriver = true;
// spacemouse is largely stable on Windows
m_Use3DConnexionDriver = true;
#else
m_Use3DConnexionDriver = false;
#endif
m_IncrementalConnectivity = false; m_IncrementalConnectivity = false;

View File

@ -20,16 +20,18 @@
#include "nl_schematic_plugin.h" #include "nl_schematic_plugin.h"
#include <advanced_config.h> #include <advanced_config.h>
#include <kiplatform/drivers.h>
#include "nl_schematic_plugin_impl.h" #include "nl_schematic_plugin_impl.h"
NL_SCHEMATIC_PLUGIN::NL_SCHEMATIC_PLUGIN() NL_SCHEMATIC_PLUGIN::NL_SCHEMATIC_PLUGIN() : m_impl( nullptr )
{ {
if( ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver ) if( ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver
&& KIPLATFORM::DRIVERS::Valid3DConnexionDriverVersion() )
{
m_impl = new NL_SCHEMATIC_PLUGIN_IMPL(); m_impl = new NL_SCHEMATIC_PLUGIN_IMPL();
else }
m_impl = nullptr;
} }
@ -41,13 +43,13 @@ NL_SCHEMATIC_PLUGIN::~NL_SCHEMATIC_PLUGIN()
void NL_SCHEMATIC_PLUGIN::SetFocus( bool focus ) void NL_SCHEMATIC_PLUGIN::SetFocus( bool focus )
{ {
if( ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver ) if( m_impl )
m_impl->SetFocus( focus ); m_impl->SetFocus( focus );
} }
void NL_SCHEMATIC_PLUGIN::SetCanvas( EDA_DRAW_PANEL_GAL* aViewport ) void NL_SCHEMATIC_PLUGIN::SetCanvas( EDA_DRAW_PANEL_GAL* aViewport )
{ {
if( ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver ) if( m_impl )
m_impl->SetCanvas( aViewport ); m_impl->SetCanvas( aViewport );
} }

View File

@ -345,19 +345,16 @@ void SCH_BASE_FRAME::ActivateGalCanvas()
{ {
EDA_DRAW_FRAME::ActivateGalCanvas(); EDA_DRAW_FRAME::ActivateGalCanvas();
if( ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver ) try
{ {
try if( !m_spaceMouse )
{ m_spaceMouse = new NL_SCHEMATIC_PLUGIN();
if( !m_spaceMouse )
m_spaceMouse = new NL_SCHEMATIC_PLUGIN();
m_spaceMouse->SetCanvas( GetCanvas() ); m_spaceMouse->SetCanvas( GetCanvas() );
} }
catch( const std::system_error& e ) catch( const std::system_error& e )
{ {
wxLogTrace( wxT( "KI_TRACE_NAVLIB" ), e.what() ); wxLogTrace( wxT( "KI_TRACE_NAVLIB" ), e.what() );
}
} }
} }
@ -537,7 +534,7 @@ void SCH_BASE_FRAME::handleActivateEvent( wxActivateEvent& aEvent )
{ {
EDA_DRAW_FRAME::handleActivateEvent( aEvent ); EDA_DRAW_FRAME::handleActivateEvent( aEvent );
if( m_spaceMouse && ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver ) if( m_spaceMouse )
m_spaceMouse->SetFocus( aEvent.GetActive() ); m_spaceMouse->SetFocus( aEvent.GetActive() );
} }
@ -546,7 +543,7 @@ void SCH_BASE_FRAME::handleIconizeEvent( wxIconizeEvent& aEvent )
{ {
EDA_DRAW_FRAME::handleIconizeEvent( aEvent ); EDA_DRAW_FRAME::handleIconizeEvent( aEvent );
if( m_spaceMouse && aEvent.IsIconized() && ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver ) if( m_spaceMouse )
m_spaceMouse->SetFocus( false ); m_spaceMouse->SetFocus( false );
} }

View File

@ -6,6 +6,7 @@ endif()
add_library( core STATIC add_library( core STATIC
version_compare.cpp
wx_stl_compat.cpp wx_stl_compat.cpp
) )

View File

@ -0,0 +1,36 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string>
#include <vector>
/**
* @brief Parse a version string into a vector of integers
* @param versionString The version string to parse
* @return A vector of integers representing the version
*/
const std::vector<int> parseVersionString( const std::string& versionString );
/**
* @brief Compare two version strings of the form "major.minor.patch.build"
* @param aVersionStr1 The first version string
* @param aVersionStr2 The second version string
* @return true if aVersionStr1 <= aVersionStr2, false otherwise
*/
bool compareVersionStrings( const std::string& aVersionStr1, const std::string& aVersionStr2 );

View File

@ -0,0 +1,67 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <charconv>
#include <core/version_compare.h>
const std::vector<int> parseVersionString( const std::string& versionString )
{
std::vector<int> versionComponents;
auto it = versionString.begin();
auto end = versionString.end();
while( it != end )
{
versionComponents.emplace_back( 0 );
// On error, the last element will be 0
auto result = std::from_chars( &( *it ), &( *end ), versionComponents.back() );
it += std::distance( &( *it ), result.ptr ); // Update the iterator
if( it != end && *it == '.' )
{
++it; // Skip the dot separator
}
}
return versionComponents;
}
bool compareVersionStrings( const std::string& aVersionStr1, const std::string& aVersionStr2 )
{
std::vector<int> ver1 = parseVersionString( aVersionStr1 );
std::vector<int> ver2 = parseVersionString( aVersionStr2 );
std::size_t len = std::min( ver1.size(), ver2.size() );
// Compare each component
for( size_t ii = 0; ii < len; ++ii )
{
if( ver1[ii] < ver2[ii] )
{
return true; // aVersionStr1 < aVersionStr2
}
else if( ver1[ii] > ver2[ii] )
{
return false; // aVersionStr1 > aVersionStr2
}
}
return ver1.size() >= ver2.size();
}

View File

@ -10,6 +10,7 @@ set( PLATFORM_COMPILE_DEFS "" )
if( APPLE ) if( APPLE )
set( PLATFORM_SRCS set( PLATFORM_SRCS
osx/app.mm osx/app.mm
osx/drivers.mm
osx/environment.mm osx/environment.mm
osx/io.mm osx/io.mm
osx/policy.mm osx/policy.mm
@ -25,6 +26,7 @@ if( APPLE )
elseif( WIN32 ) elseif( WIN32 )
set( PLATFORM_SRCS set( PLATFORM_SRCS
msw/app.cpp msw/app.cpp
msw/drivers.cpp
msw/environment.cpp msw/environment.cpp
msw/io.cpp msw/io.cpp
msw/policy.cpp msw/policy.cpp
@ -40,6 +42,7 @@ elseif( WIN32 )
elseif( UNIX ) elseif( UNIX )
set( PLATFORM_SRCS set( PLATFORM_SRCS
gtk/app.cpp gtk/app.cpp
gtk/drivers.cpp
gtk/environment.cpp gtk/environment.cpp
gtk/io.cpp gtk/io.cpp
gtk/policy.cpp gtk/policy.cpp

View File

@ -0,0 +1,25 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <kiplatform/drivers.h>
bool KIPLATFORM::DRIVERS::Valid3DConnexionDriverVersion()
{
// The 3DConnexion driver doesn't work for Linux
return false;
}

View File

@ -0,0 +1,40 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef KIPLATFORM_DRIVERS_H_
#define KIPLATFORM_DRIVERS_H_
#include <string>
#include <vector>
#include <charconv>
namespace KIPLATFORM
{
namespace DRIVERS
{
/**
* @brief Get the driver version for a given driver name
* @return true if the driver version is valid, false otherwise
*/
bool Valid3DConnexionDriverVersion();
} // namespace DRIVERS
} // namespace KIPLATFORM
#endif // KIPLATFORM_DRIVERS_H_

View File

@ -0,0 +1,52 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <core/version_compare.h>
#include <kiplatform/drivers.h>
#include <Windows.h>
#include <iostream>
#define MIN_WIN_VERSION "10.7.2"
bool KIPLATFORM::DRIVERS::Valid3DConnexionDriverVersion()
{
HKEY hKey;
std::string version;
// Open the registry key for 3dConnexion
if( RegOpenKeyEx( HKEY_LOCAL_MACHINE,
"Software\\3Dconnexion\\3DxWare Version",
0, KEY_READ, &hKey ) == ERROR_SUCCESS )
{
char buffer[256];
DWORD bufferSize = sizeof( buffer );
// Query the version value
if( RegQueryValueEx( hKey, nullptr, nullptr, nullptr, ( LPBYTE ) buffer, &bufferSize )
== ERROR_SUCCESS )
{
version = buffer;
}
RegCloseKey( hKey );
}
return !version.empty() && compareVersionStrings( MIN_WIN_VERSION, version );
}

View File

@ -0,0 +1,42 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <core/version_compare.h>
#include <kiplatform/drivers.h>
#import <Foundation/Foundation.h>
#define MIN_MAC_VERSION "10.8.0"
bool KIPLATFORM::DRIVERS::Valid3DConnexionDriverVersion()
{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSLocalDomainMask, YES);
NSString *libraryDirectory = searchPaths.firstObject;
NSString *frameworkPath = [libraryDirectory stringByAppendingPathComponent:@"Frameworks/3DconnexionNavlib.framework"];
NSBundle *frameworkBundle = [NSBundle bundleWithPath:frameworkPath];
NSDictionary *infoDictionary = [frameworkBundle infoDictionary];
NSString *version = infoDictionary[@"CFBundleShortVersionString"];
if (!version)
return false;
return compareVersions(version.UTF8String, MIN_MAC_VERSION ) >= 0;
}

View File

@ -21,14 +21,15 @@
#include "nl_pcbnew_plugin.h" #include "nl_pcbnew_plugin.h"
#include "nl_pcbnew_plugin_impl.h" #include "nl_pcbnew_plugin_impl.h"
#include <advanced_config.h> #include <advanced_config.h>
#include <kiplatform/drivers.h>
NL_PCBNEW_PLUGIN::NL_PCBNEW_PLUGIN( PCB_DRAW_PANEL_GAL* aViewport ) : m_impl( nullptr )
NL_PCBNEW_PLUGIN::NL_PCBNEW_PLUGIN( PCB_DRAW_PANEL_GAL* aViewport )
{ {
if( ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver ) if( ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver
&& KIPLATFORM::DRIVERS::Valid3DConnexionDriverVersion() )
{
m_impl = new NL_PCBNEW_PLUGIN_IMPL( aViewport ); m_impl = new NL_PCBNEW_PLUGIN_IMPL( aViewport );
else }
m_impl = nullptr;
} }
@ -40,6 +41,6 @@ NL_PCBNEW_PLUGIN::~NL_PCBNEW_PLUGIN()
void NL_PCBNEW_PLUGIN::SetFocus( bool focus ) void NL_PCBNEW_PLUGIN::SetFocus( bool focus )
{ {
if( ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver ) if( m_impl )
m_impl->SetFocus( focus ); m_impl->SetFocus( focus );
} }

View File

@ -120,7 +120,7 @@ void PCB_BASE_FRAME::handleActivateEvent( wxActivateEvent& aEvent )
{ {
EDA_DRAW_FRAME::handleActivateEvent( aEvent ); EDA_DRAW_FRAME::handleActivateEvent( aEvent );
if( m_spaceMouse != nullptr && ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver ) if( m_spaceMouse )
m_spaceMouse->SetFocus( aEvent.GetActive() ); m_spaceMouse->SetFocus( aEvent.GetActive() );
} }
@ -129,8 +129,7 @@ void PCB_BASE_FRAME::handleIconizeEvent( wxIconizeEvent& aEvent )
{ {
EDA_DRAW_FRAME::handleIconizeEvent( aEvent ); EDA_DRAW_FRAME::handleIconizeEvent( aEvent );
if( m_spaceMouse != nullptr && aEvent.IsIconized() if( m_spaceMouse != nullptr && aEvent.IsIconized() )
&& ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver )
m_spaceMouse->SetFocus( false ); m_spaceMouse->SetFocus( false );
} }
@ -1082,21 +1081,18 @@ void PCB_BASE_FRAME::ActivateGalCanvas()
canvas->SetEventDispatcher( m_toolDispatcher ); canvas->SetEventDispatcher( m_toolDispatcher );
canvas->StartDrawing(); canvas->StartDrawing();
if( ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver ) try
{
try
{
if( m_spaceMouse == nullptr )
{ {
if( m_spaceMouse == nullptr ) m_spaceMouse = new NL_PCBNEW_PLUGIN( GetCanvas() );
{
m_spaceMouse = new NL_PCBNEW_PLUGIN( GetCanvas() );
}
}
catch( const std::system_error& e )
{
wxLogTrace( wxT( "KI_TRACE_NAVLIB" ), e.what() );
} }
} }
catch( const std::system_error& e )
{
wxLogTrace( wxT( "KI_TRACE_NAVLIB" ), e.what() );
}
} }