Les pilotes MacOS de Wacom pour le bambou, le graphie, les intuos 1, 2 et 3 et les tablettes de 1ère génération Cintiq ont des bogues qui les font pas complètement commencer sur les versions de Catalina 10.15 (y compris 11 Big Sur et 12 Monterey). Cela ne s'applique pas au pilote Windows ou aux pilotes pour leurs nouvelles tablettes.
Lorsque vous essayez d'ouvrir le volet de préférence Wacom avec une tablette en bambou, vous recevrez un message d'erreur disant "en attente de synchronisation", alors enfin "il y a un problème avec votre pilote de tablette. Veuillez redémarrer votre système. Si le problème persiste réinstalle à l'ordre ou mettre à jour le pilote ". Pour une tablette INTUOS 3 ou CINTIQ de 1ère génération, le volet de préférence s'ouvrira, mais cliquer sur tout ce qui le fera s'écraser avec le message "Il y avait une erreur dans les préférences de tablette Wacom". Pour les tablettes Graphire et Intuos 1 et 2, l'installateur du pilote n'a même pas pu fonctionner sur Catalina.
Heureusement, j'ai pu retrouver les problèmes et j'ai corrigé les pilotes pour les réparer!
Mon pilote de bambou fixe (v5.3.7-6) prend en charge ces tablettes:
Mon graphie fixe 1 et 2 et le pilote INTUOS 1 & 2 (v6.1.6-4) prend en charge ces tablettes:
Mon pilote Fixed Graphire 3 (V5.2.6-5) prend en charge ces tablettes:
Mon pilote FIXE Graphire 4 (V5.3.0-3) prend en charge ces tablettes:
Et mon pilote fixe Intuos 3 et Cintiq (v6.3.15-3) prend en charge ces tablettes:
Pour intuos 4, mon correctif n'est pas nécessaire. Vous pouvez utiliser le pilote officiel de Wacom V6.3.41-2 à la place.
?? Instructions d'anglais simplifiées
?? / ?? Instruções em português
?? 日本語で表示
?? Инbli .otte
?? Instrucciones en español
?? Instrukcja po polsku
?? Instructions en français
Téléchargez le programme d'installation correct pour votre tablette ici et double-cliquez pour l'exécuter, cela installera ma version fixe du pilote de Wacom:
Si vous obtenez un message d'erreur que votre Mac permet d'installer uniquement les applications à partir de l'App Store, cliquez avec le bouton droit dessus et cliquez sur "Ouvrir" à la place.
Après l'installation, suivez les instructions dans la section suivante pour fixer les autorisations de la tablette.
Appuyez sur votre pourboire sur votre tablette, et vous devez vous inviter à visiter les préférences du système> Sécurité et confidentialité> Onglet de confidentialité pour accorder les autorisations de tablette.
Sur la page d'accessibilité, cliquez sur le cadenas pour déverrouiller la page, puis trouver et cocher n'importe quel PenTabletDriver
, WacomTabletDriver
TabletDriver
ou WacomTabletSpringboard
Les entrées que vous voyez dans la liste. Faites de même sur la page de surveillance des entrées.
Si votre tablette prend en charge le toucher, touchez la tablette avec votre doigt, cela devrait à nouveau vous inciter à accorder des autorisations. Sur la page d'accessibilité, cochez l'entrée ConsumerTouchDriver
ou WacomTouchDriver
.
Avec certaines tablettes, le pilote pourrait apparaître uniquement sur la page de surveillance des entrées, et vous devrez peut-être redémarrer une deuxième fois pour qu'il apparaisse également sur la page d'accessibilité.
Vous avez probablement eu des autorisations à partir du conducteur de tablette précédent, et ces entrées périmées doivent toutes être supprimées comme:
Sur la page "Accessibilité" de la sécurité et de la confidentialité, trouvez tout ce qui concerne Wacom dans la liste (par exemple, PenTabletDriver
, WacomTabletDriver
, TabletDriver
, ConsumerTouchDriver
, WacomTabletSpringboard
, WacomTouchDriver
), sélectionnez-les et cliquez sur le bouton MINUS pour les supprimer. Accédez à la "page de surveillance des entrées" et faites de même là-bas.
Maintenant, redémarrez votre ordinateur ou exécutez ces deux commandes dans le terminal, pour recharger le pilote de tablette. Pour les tablettes Bamboo et Graphire 3 et 4:
launchctl unload /Library/LaunchAgents/com.wacom.pentablet.plist
launchctl load -w /Library/LaunchAgents/com.wacom.pentablet.plist
Pour le graphique 1 et 2, les comprimés intuos et cintiq:
launchctl unload /Library/LaunchAgents/com.wacom.wacomtablet.plist
launchctl load -w /Library/LaunchAgents/com.wacom.wacomtablet.plist
Cela devrait restaurer les invites pour vous demander d'ajouter des autorisations, alors recommencez les instructions de cette section.
Pour une poignée de personnes, le conducteur de Wacom n'apparaît jamais dans la liste de surveillance des entrées pour eux. Pour résoudre ce problème, ouvrez d'abord l'application "Terminal" et collez cette ligne et appuyez sur Entrée pour vous assurer que le service Wacom est activé:
Pour les tablettes Bamboo et Graphire 3 et 4:
launchctl load -w /Library/LaunchAgents/com.wacom.pentablet.plist
Pour le graphique 1 et 2, les comprimés intuos et cintiq:
launchctl load -w /Library/LaunchAgents/com.wacom.wacomtablet.plist
Si cela ne le déclenche pas pour vous demander d'ajouter des autorisations de surveillance des entrées lorsque vous essayez d'utiliser la tablette, vous pouvez l'ajouter manuellement à la place.
Dans Finder, cliquez sur Go -> Allez dans le dossier et collez ce chemin là-bas et cliquez sur OK:
/Library/Application Support/Tablet/
Là, vous devriez voir un fichier "pentabletdriver" (bambou), "pentabletsPringboard" (Graphire 3 & 4), ou "WacomTabletsPringboard" (Graphire 1 & 2, intuos, Cintiq).
Déverrouillez la page de surveillance des entrées, puis faites glisser le fichier pentabletdriver / pentabletsPringboard / wacomTabletsPringboard pour l'ajouter à la liste et assurez-vous qu'il est coché. Redémarrez maintenant votre ordinateur et lorsque vous essayez d'utiliser la tablette, il faut également vous inciter à le cocher dans la page d'accessibilité, après quoi il devrait commencer à fonctionner.
Assurez-vous que le tout dernier pilote de Wacom n'a pas installé. Utilisez "Wacom Utility" / "Tablet Utility" pour désinstaller complètement tous les pilotes de Wacom (plutôt que de simplement les faire glisser vers la poubelle), puis installez à nouveau mon pilote.
Les préférences corrompues peuvent empêcher les choses de fonctionner, surtout si vous avez installé un tas de versions de pilotes différentes tout en essayant de faire fonctionner les choses. Utilisez Wacom Utility pour réinitialiser vos préférences, redémarrer et essayer à nouveau à utiliser la tablette.
Si vous avez aimé remettre votre tablette en action, envisagez de m'envoyer un pourboire!
Cela vous aidera à me financer et à développer davantage ces conducteurs fixes.
PentabletDriver lance deux sous-pilotes pour faire le travail pour celui-ci, ConsumerSouchDriver et TabletDriver. Pour trouver ces pilotes dans son dossier de ressources, il appelle finalement cette fonction pour extraire un chemin à partir d'une URL:
CFString * MacPaths::PathFromURL (CFURL *url)
{
CFString *path;
path = _objc_retainAutoreleasedReturnValue (url-> path ());
_objc_release (path); /* Whoops, path is destroyed here! */
return path; /* Now returning a free'd path */
}
Pardonnez-moi d'avoir paraphrasé le code C de l'objectif d'origine comme C ++, je ne parle pas objc!
Lorsque CFURL crée le chemin, son nombre de références commence à 1. Il fait la queue le nombre de références pour être décrémenté plus tard en appelant autorelease()
dessus, puis le renvoie au pilote de Wacom. Cet appel à autorelease
s'associe à l'appel de la retenue de retainAutoreleasedReturnValue()
, et donc et laisse le nombre de référence du chemin intact, à 1.
Mais maintenant, le pilote Wacom appelle _objc_release()
sur le chemin. Cela diminue son nombre de références à 0, et le chemin est immédiatement libéré!
Ce chemin libéré est utilisé lors du lancement du sous-conducteur, qui peut déclencher une segfault dans ProcessUtils::LaunchApplicationWithBundleID()
. Cela tue le conducteur.
Le correctif est un changement à un octet qui remplace l'appel à _objc_release()
dans PathFromURL
à un appel à _objc_retain()
. Cela empêche la libération de la libération avant son utilisation, ce qui guérit la segfault.
Le ConsumerSouchDriver contient également ce même bogue, et le patch est le même là-bas.
Le pilote stylo et le pilote tactile ont besoin de correctifs pour les empêcher de s'écraser lorsqu'un geste multi-touch est effectué, ou que l'anneau de défilement est utilisé pour zoomer.
Lorsqu'un geste est effectué, la fonction CMacHIDGestureEventOSX1010::PostGesture
est responsable de l'envoi de ce geste au système d'exploitation:
void CMacHIDGestureEventOSX1010::PostGesture (EIOHIDEventType gestureType_I, int32_t eventDirAmount)
{
__CFDataOSX1010 *eventStructure;
if (gestureType_I == 61 /* kCGHIDEventTypeGestureStarted */ ) {
this -> eventPhase = 1 /* kCGSGesturePhaseBegan */ ;
} else {
this -> eventPhase = 4 /* kCGSGesturePhaseEnded */ ;
(**(code **)(*( long *) this + 0x18 ))( 0 , this ,( uint32_t ) eventDirAmount);
}
eventStructure = (__CFDataOSX1010 *) _CGEventCreate ( 0 ); // Dubious
_CGEventSetType (eventStructure, 29 /* kCGSEventGesture */ );
eventStructure-> eventSubType = gestureType_I; // Relies on the exact memory layout of CGEvent (!)
eventStructure-> eventDirAmount = eventDirAmount; // Ditto
_CGEventPost ( 0 , eventStructure);
_CFRelease (eventStructure);
}
Remarquez comment le résultat de CGeventCreate est projeté à une structure? CGevent est censé être un type opaque, les programmes ne sont pas censés connaître ou compter sur sa disposition, car sa structure passe de la version OS à la version OS, mais ici, il est jeté à une structure afin que ses champs eventSubType
et eventDirAmount
puissent être attribué directement. Ces deux écritures provoquent une corruption de tas sur Catalina et déclenchent un crash, car la disposition de CGEvent
a changé depuis Sierra!
La bonne façon de stocker les valeurs dans un événement consiste à utiliser l'API CGEVENTSETINTEGERVALUEFIELD, qui vous permet de vous référer aux champs de CGEVENT par un ID logique au lieu de leur position en mémoire. Alors, quels sont les identifiants de champ équivalents pour les deux écrits que le conducteur de Wacom doit faire?
J'ai démontré le cadre du puits de lumière de MacOS Sierra, qui contient la mise en œuvre de CGEventSetIntegerValueField
, pour voir ce que les ID auraient dû être pour ces domaines. Il semble que les eventSubType
puissent être écrits par ID de terrain 110, et le eventDirAmount
peut être écrit par ID 115. Mais ces identifiants de champ ne se trouvent nulle part dans la documentation d'Apple, ce qui explique pourquoi Wacom n'a pas pu les utiliser!
J'ai fait des recherches sur Google et j'ai découvert que ces champs sont sans papiers car ils font partie de l'API privée d'Apple. Cet en-tête WebKit révèle leurs noms:
kCGEventGestureHIDType = 110
kCGEventGestureSwipeValue = 115
kCGEventGesturePhase = 132
Et ces champs API privés sont stables de Sierra jusqu'à Big Sur! Maintenant que nous le savons, les deux affectations à l'événement peuvent être remplacées par ces appels, et les accidents du conducteur sont éliminés:
_CGEventSetIntegerValueField (eventStructure, 110 /* kCGEventGestureHIDType */ , gestureType_I);
_CGEventSetIntegerValueField (eventStructure, 115 /* kCGEventGestureSwipeValue */ , eventDirAmount);
La version à virgule flottante de Postgestture a le même problème:
void CMacHIDGestureEventOSX1010::PostGesture (EIOHIDEventType eventSubType, float dirAmount)
{
__CFDataOSX1010 *eventStructure;
eventStructure = (__CFDataOSX1010 *) _CGEventCreate ( 0 );
_CGEventSetType (eventStructure, 29 /* kCGSEventGesture */ );
eventStructure-> eventSubType = eventSubType; // !
eventStructure-> eventDirAmount = reinterpret_cast < int32_t &>(dirAmount); // !
eventStructure-> eventState = this -> eventPhase ; // !
if ( this -> eventPhase == 1 /* kCGSGesturePhaseBegan */ ) {
this -> eventPhase = 2 /* kCGSGesturePhaseChanged */ ;
}
_CGEventSetLocation (eventStructure, GetMouseLocationInScreenCoordinates ());
_CGEventPost ( 0 , eventStructure);
_CFRelease (eventStructure);
}
Et nous pouvons le réparer comme ça:
_CGEventSetIntegerValueField (eventStructure, 110 /* kCGEventGestureHIDType */ , gestureType_I);
_CGEventSetIntegerValueField (eventStructure, 115 /* kCGEventGestureSwipeValue */ , reinterpret_cast < int32_t &>(dirAmount));
_CGEventSetIntegerValueField (eventStructure, 132 /* kCGEventGesturePhase */ , this ->eventPhase);
Dans le volet de préférence de Wacom, Wacom est victime de Bug 8746551. Depuis MacOS Catalina, le volet de préférence rompt efficacement le fonctionnement de NSApp->mainWindow
en permettant à n'importe quel type de fenêtre de devenir la fenêtre active, même des feuilles, ce qui était impossible dans les versions précédentes de versions précédentes de MacOS et dans les applications autonomes (dans les versions précédentes, seule la fenêtre réelle des préférences principales deviendrait le mainWindow
).
Lorsqu'une feuille modale est ouverte et que l'utilisateur souhaite ouvrir une nouvelle feuille, la feuille d'origine doit être fermée en premier. Mais le bogue d'Apple fait que le chèque de Wacom verra s'il y a actuellement une feuille ouverte à l'échec, car quand il vérifie si une feuille est attachée à la mainWindow
, il finit par vérifier une feuille attachée à la feuille actuelle, qui a inexplicablement devenir le mainWindow
. Cela déclenche un crash (par exemple dans les paramètres de cartographie du stylo).
J'ai corrigé les accès à mainWindow
afin que la première valeur lue soit mise en cache par la suite, donc tant que la valeur initiale est sensible, elle ne se brisait pas après la mise à jour du mainWindow
pour pointer vers la feuille d'ouverture (voir PenTablet.prefpane.newcode.asm
).
Le pilote Intuos 3 et Cintiq a un bogue dans son volet de préférence qui le fait s'écraser dès qu'un élément est cliqué.
L'une des principales caractéristiques de l'interface utilisateur du volet de préférence est les listes d'icônes représentant les tablettes, outils et applications que vous pouvez configurer. Ce contrôle de liste d'icônes utilise une fonction comme celle-ci pour expédier des événements (tels que des clics) à ses enfants:
void WTCCPLIconList::action:(ID event, SEL param_2, ID param_3) {
int selectedIndex;
ID target;
ID action;
target = _objc_retainAutoreleasedReturnValue (event-> target ());
action = event-> action ();
selectedIndex = event-> selectedIndex ();
event-> scrollIndexToVisible (selectedIndex);
if ((target != 0 ) && (action != 0 )) {
code* handler = target-> methodForSelector (action);
Object *result = handler (target, action, event);
result = _objc_retainAutoreleasedReturnValue (result); // (!)
_objc_release (result); // (!)
}
event-> updateButtonStates ();
_objc_release (target);
}
Le problème avec ce code est qu'il nécessite que la fonction handler()
de l'événement renvoie un objet, qu'il conserve alors inutilement () et libère (). Mais l'une des fonctions du gestionnaire qui sera appelé est OEventDispatcher_Professional::listClickAction()
, et cette fonction est une fonction void
(sans valeur de retour bien définie)!
Donc, action:()
finit par appeler retain()
et release()
sur un pointeur à ordures, ce qui provoque une segfault.
Le patch ici est facile - cette paire inutile de retain()
et les appels release()
est supprimée. Le même bug existe dans ONumberTextField::textDidChange:
avec la même correction.
Il y a un autre problème avec ce pilote. Si, tout en essayant de faire fonctionner votre tablette, vous installez accidentellement le dernier pilote Wacom (qui ne prend pas en charge Intuos 3), il écrit un fichier de préférence plus récent que l'ancien pilote Intuos 3 se bloquera lorsque vous essayez de lire. Et cette situation ne se résout pas, l'utilisateur doit utiliser manuellement l'utilitaire Wacom pour supprimer les préférences de tablette afin de le réparer.
Ceci est étrange car le fichier de préférence comprend un numéro de version conçu pour éviter cette situation même. L'ancien pilote utilise la version 5 et le dernier pilote utilise la version 6:
< ImportFileVersion type = " integer " >6</ ImportFileVersion >
Et le code du pilote vérifie explicitement ce numéro de version et devrait abandonner lorsqu'il est trop nouveau:
CTabletDriver::ReadSettings (basic_string settingsFilename, ...)
{
basic_string settingsFileContent;
CSettingsMap settingsMap;
...
ReadFromXMLFile (settingsMap, settingsFilename, settingsFileContent);
SettingsMigration *migration = SettingsMigration::MigratePen (settingsMap);
if (migration != nullptr ) {
int fileVersion = settingsMap. IntegerForKeyWithDefault ( " ImportFileVersion " , - 1 )
if (fileVersion < 1 ) {
// Report error
} else if (fileVersion <= this -> supportedVersion ) {
// Accept the loaded settings
} else {
// Report error: Settings are too new
}
}
...
}
Mais le conducteur ne s'aborte jamais, il se bloque à la place tout en essayant de charger les préférences. Alors, qu'est-ce qui ne va pas ici? Le secret se trouve à l'intérieur de la fonction MigratePen()
. Cette fonction est conçue pour mettre à niveau les fichiers de paramètres plus anciens vers la version actuelle, mais malheureusement dans le processus, il écrase inconditionnellement le ImportFileVersion
avec la version actuelle (5)! Cela laisse CTabletDriver::ReadSettings()
incapable de détecter que les paramètres sont trop nouveaux pour être analysés.
Pour résoudre ce problème, j'ai renforcé le code de détection de version non valide de MigratePen()
:
if (settingsVersion < 1 ) {
// Report invalid settings version and return NULL
}
Pour le faire:
if (settingsVersion < 1 || settingsVersion > 5 ) {
// Report invalid settings version and return NULL
}
Alors maintenant, si les préférences sont trop nouvelles, MigratePen()
n'essaiera pas de les mettre à niveau, et ReadSettings()
sautera proprement le chargement des préférences. Cela fait que les préférences restent à leurs valeurs par défaut, et si l'utilisateur modifie les paramètres à l'aide du volet de préférence, les paramètres doivent être échangés proprement.
Les installateurs des pilotes de graphire sont un ancien format que Catalina ne prend plus en charge, j'ai donc dû les reconstruire complètement.
Le volet de préférence du Graphire s'appuyait incorrectement sur des symboles privés de la bibliothèque standard macOS qui ne sont plus présents dans Catalina, de sorte qu'il ne pourrait plus commencer.
Par exemple, la fonction NSnibwakingOverride :: AwakeFromNib () de Wacom est appelée pendant la désérialisation de GUI et ajoute le contrôle de l'interface graphique chargé à une carte afin qu'il puisse être accessible par sa balise plus tard:
void NSNibWakingOverride::awakeFromNib (NSControl * this ) {
OMasterDictionaryPtr-> addObject :withTag:( this , this -> _tag ));
}
Mais cela repose sur la lecture de NSControl._Tag, qui est un domaine privé. Dans MacOS 10.9 qui a fonctionné parce que NSControl a été défini comme ceci:
@interface NSControl : NSView
{
/* All instance variables are private */
NSInteger _tag;
id _cell;
struct __conFlags {
...
} _conFlags;
}
Mais dans MacOS 10.10, NSControl a été refactorisé pour déplacer le champ _Tag dans un nouveau champ _AUX, ce qui le rend inaccessible:
@interface NSControl : NSView
{
/* All instance variables are private */
NSControlAuxiliary *_aux;
id _cell;
struct __conFlags {
...
} _conFlags;
}
@property NSInteger tag;
J'ai corrigé AwakeFromnib pour le faire appeler correctement la fonction accessoire public pour ce champ:
void NSNibWakingOverride::awakeFromNib (NSControl * this ) {
OMasterDictionaryPtr-> addObject :withTag:( this , this -> tag ()));
}
Dans la fonction OPOPUPOutLiewView :: reloadData () de Wacom, le champ privé nstableView._DataSource est mal lu directement:
void OPopupOutlineView::reloadData (OPopupOutlineView * this ) {
this -> _dataSource . willReloadDataForOutlineView ( this );
...
}
J'ai donc corrigé ceci pour utiliser l'accessoire public à la place:
void OPopupOutlineView::reloadData (OPopupOutlineView * this ) {
this -> dataSource ()-> willReloadDataForOutlineView ( this );
...
}
Ces pilotes ont les mêmes problèmes que les pilotes Graphire 3 et 4, ainsi que le même problème _dataSource
dans leur ORadialSubMenuTableView::reloadData() method
, avec la même correction.