Los controladores MacOS de Wacom para las tabletas de bambú, Graphire, Intuos 1, 2 y 3 y Cintiq 1st Gen tienen errores en ellas que hacen que no comiencen por completo en las versiones de Catalina 10.15 y posteriores (incluyendo 11 Big Sur y 12 Monterey). Esto no se aplica al controlador de Windows o a los controladores para sus tabletas más nuevas.
Cuando intente abrir el panel de preferencia de Wacom con una tableta de bambú, recibirá un mensaje de error que diga "Esperando sincronización", finalmente "hay un problema con el controlador de su tableta. Reinicie su sistema. Si el problema persiste, reinstale reinstale o actualizar el controlador ". Para una tableta INTUOS 3 o Cintiq 1st Gen, el panel de preferencia se abrirá, pero hacer clic en cualquier cosa hará que se bloquee con el mensaje "Hubo un error en las preferencias de la tableta Wacom". Para las tabletas Graphire e Intuos 1 y 2, el instalador del conductor ni siquiera pudo funcionar en Catalina.
¡Afortunadamente pude rastrear los problemas y he reparado a los conductores para arreglarlos!
Mi controlador de bambú fijo (v5.3.7-6) admite estas tabletas:
Mi controlador de Graphire 1 y 2 e Intuos 1 y 2 fijo (V6.1.6-4) admite estas tabletas:
Mi controlador Graphire 3 fijo (v5.2.6-5) admite estas tabletas:
Mi controlador Graphire 4 fijo (v5.3.0-3) admite estas tabletas:
Y mi controlador intuos 3 y Cintiq Cintiq (V6.3.15-3) admite estas tabletas:
Para intuos 4 mi solución no es necesaria. Puede usar el conductor oficial de Wacom V6.3.41-2 en su lugar.
? Instrucciones en inglés simplificadas
? / ??? Instruções em Português
? 日本語で表示
? En
? Instruccions en español
? Instruckcja po polsku
? Instrucciones en Français
Descargue el instalador correcto para su tableta aquí y haga doble clic para ejecutarla, esto instalará mi versión fija del controlador de Wacom:
Si recibe un mensaje de error de que su Mac solo permite que las aplicaciones se instalen desde la App Store, haga clic con el botón derecho y haga clic en "Abrir" en su lugar.
Después de instalar, siga las instrucciones en la siguiente sección para arreglar los permisos de la tableta.
Toque la punta de su bolígrafo a su tableta, y debe solicitarle que visite preferencias del sistema> Seguridad y privacidad> Pestaña de privacidad para otorgar los permisos de la tableta.
En la página de accesibilidad, haga clic en el candado para desbloquear la página, luego busque y marque cualquier PenTabletDriver
, WacomTabletDriver
TabletDriver
o WacomTabletSpringboard
Board que ve en la lista. Haga lo mismo en la página de monitoreo de entrada.
Si su tableta es compatible con el tacto, toque la tableta con su dedo, debería nuevamente pedirle que otorgue permisos. En la página de accesibilidad, marque la entrada ConsumerTouchDriver
o entrada WacomTouchDriver
.
Con algunas tabletas, el controlador solo puede aparecer en la página de monitoreo de entrada, y es posible que deba reiniciar una segunda vez para que aparezca en la página de accesibilidad también.
Probablemente le quedaron permisos del controlador de tabletas anterior, y todas estas entradas obsoletas deben eliminarse así:
En la página de "accesibilidad" de seguridad y privacidad, encuentre todo lo relacionado con Wacom en la lista (por ejemplo, PenTabletDriver
, WacomTabletDriver
, TabletDriver
, ConsumerTouchDriver
, WacomTabletSpringboard
, WacomTouchDriver
), seleccione y haga clic en el botón Mínimo para eliminarlos. Vaya a la "página de monitoreo de entrada" y haga lo mismo allí.
Ahora reinicie su computadora o ejecute estos dos comandos en el terminal, para recargar el controlador de la tableta. Para Bamboo y Graphire 3 y 4 tabletas:
launchctl unload /Library/LaunchAgents/com.wacom.pentablet.plist
launchctl load -w /Library/LaunchAgents/com.wacom.pentablet.plist
Para las tabletas Graphire 1 y 2, Intuos y Cintiq:
launchctl unload /Library/LaunchAgents/com.wacom.wacomtablet.plist
launchctl load -w /Library/LaunchAgents/com.wacom.wacomtablet.plist
Esto debería restaurar las indicaciones para pedirle que agregue permisos, así que ahora comience las instrucciones en esta sección nuevamente.
Para un puñado de personas, el controlador de Wacom nunca aparece en la lista de monitoreo de entrada para ellos. Para solucionar esto, primero abra la aplicación "Terminal" y pegue esta línea y presione Entrar para asegurarse de que el servicio WACOM esté habilitado:
Para Bamboo y Graphire 3 y 4 tabletas:
launchctl load -w /Library/LaunchAgents/com.wacom.pentablet.plist
Para las tabletas Graphire 1 y 2, Intuos y Cintiq:
launchctl load -w /Library/LaunchAgents/com.wacom.wacomtablet.plist
Si eso no lo desencadena pedirle que agregue permisos de monitoreo de entrada cuando intente usar la tableta, puede agregarla manualmente.
En Finder, haga clic en Go -> Vaya a la carpeta y pegue esta ruta allí y haga clic en Aceptar:
/Library/Application Support/Tablet/
Allí debería ver un archivo "Pentabletdriver" (bambú), "Pentabletspringboard" (Graphire 3 y 4) o "WacomTabletspringboard" (Graphire 1 y 2, Intuos, Cintiq).
Desbloquee la página de monitoreo de entrada, luego arrastre el archivo PentabletDriver / Pentabletspringboard / WacomTabletSpringboard para agregarlo a la lista, y asegúrese de que esté marcado. Ahora reinicie su computadora, y cuando intente usar la tableta, también debería pedirle que lo marque en la página de accesibilidad, después de lo cual debería comenzar a funcionar.
Asegúrese de no tener el último controlador de Wacom instalado. Use "Wacom Utility"/ "Utility de tabletas" para desinstalar completamente todos los controladores de Wacom (en lugar de simplemente arrastrarlos a la basura), luego instale mi controlador nuevamente.
Las preferencias corruptas pueden evitar que funcionen las cosas, especialmente si instaló un montón de diferentes versiones de controladores mientras intenta hacer que las cosas funcionen. Use Wacom Utility para restablecer sus preferencias, reiniciar e intente usar la tableta nuevamente.
Si disfrutó que su tableta volviera a la acción, ¡considere enviarme una propina!
Esto ayudará a financiarme y un mayor desarrollo de estos impulsores fijos.
Pentabletdriver lanza dos subdirectores para hacer el trabajo por él, ConsumerTouchdriver y Tabletdriver. Para encontrar esos controladores dentro de su carpeta de recursos, eventualmente llama a esta función para extraer una ruta de una 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 */
}
Perdóname por parafrasear el código C ORIGINAL C Como C ++, ¡no hablo objc!
Cuando CFURL crea la ruta, su conteo de referencia comienza en 1. Hace cola que el recuento de referencias se disminuye más tarde llamando autorelease()
en ella, luego la devuelve al controlador de Wacom. Este llamado a autorelease
se combina con la llamada retainAutoreleasedReturnValue()
de Wacom, y así y deja el recuento de referencia de la ruta intacta, a la 1.
Pero ahora el controlador de Wacom llama _objc_release()
en la ruta. Esto disminuye su recuento de referencia a 0, ¡y la ruta se libera inmediatamente!
Esta ruta liberada se usa al lanzar el subdirector, que puede desencadenar un Segfault en ProcessUtils::LaunchApplicationWithBundleID()
. Esto mata al conductor.
La solución es un cambio de byte único que reemplaza la llamada a _objc_release()
en PathFromURL
desde una llamada a _objc_retain()
. Esto evita que el camino se libere antes de que se use, lo que cura el Segfault.
ConsumerTouchdriver también contiene este mismo error, y el parche es el mismo allí.
Tanto el controlador de la pluma como el controlador táctil necesitan soluciones para evitar que se bloqueen cuando se realiza un gesto multitáctil, o el anillo de desplazamiento se usa para hacer zoom.
Cuando se realiza un gesto, la función CMacHIDGestureEventOSX1010::PostGesture
es responsable de enviar ese gesto al sistema operativo:
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);
}
¿Observe cómo el resultado de CGEVentCreate se está lanzando a una estructura? Se supone que CGEVVE es un tipo opaco, no se supone que los programas sepan o confíen en su diseño, ya que su estructura cambia de la versión del sistema operativo a la versión del sistema operativo, pero aquí se está lanzando a una estructura para que sus campos eventSubType
y eventDirAmount
puedan ser asignado directamente. ¡Estas dos escrituras causan corrupción del montón en Catalina y desencadenan un choque, porque el diseño de CGEvent
ha cambiado desde Sierra!
La forma adecuada de almacenar los valores en un evento es mediante el uso de la API CGEVentSetInTegaluefield, que le permite referirse a los campos de CGEVEVE por una ID lógica en lugar de su posición en la memoria. Entonces, ¿cuáles son las ID de campo equivalentes para las dos escrituras que el controlador de Wacom necesita hacer?
Desmonté el marco Skylight de MacOS Sierra, que contiene la implementación de CGEventSetIntegerValueField
, para ver cuáles deberían haber sido las IDS para esos campos. Parece que el ID 115 puede escrito eventSubType
por Field ID 110, y el eventDirAmount
puede ser escrito por ID 115. Pero estas ID de campo no se encuentran en ninguna parte en la documentación de Apple, lo que explica por qué Wacom no podría usarlos!
Hice google y descubrí que estos campos son indocumentados porque son parte de la API privada de Apple. Este encabezado WebKit revela sus nombres:
kCGEventGestureHIDType = 110
kCGEventGestureSwipeValue = 115
kCGEventGesturePhase = 132
¡Y esos campos de API privados son estables desde Sierra hasta Big Sur! Ahora que sabemos esto, las dos tareas a EventStructure pueden ser reemplazadas por estas llamadas, y se eliminan los bloqueos del conductor:
_CGEventSetIntegerValueField (eventStructure, 110 /* kCGEventGestureHIDType */ , gestureType_I);
_CGEventSetIntegerValueField (eventStructure, 115 /* kCGEventGestureSwipeValue */ , eventDirAmount);
La versión de punto flotante de Postgesture tiene el mismo problema:
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);
}
Y podemos parcharlo así:
_CGEventSetIntegerValueField (eventStructure, 110 /* kCGEventGestureHIDType */ , gestureType_I);
_CGEventSetIntegerValueField (eventStructure, 115 /* kCGEventGestureSwipeValue */ , reinterpret_cast < int32_t &>(dirAmount));
_CGEventSetIntegerValueField (eventStructure, 132 /* kCGEventGesturePhase */ , this ->eventPhase);
En el panel de preferencia de Wacom, Wacom es víctima de Apple Bug 8746551. Dado que MacOS Catalina, el panel de preferencia rompe efectivamente el funcionamiento de NSApp->mainWindow
al permitir que cualquier tipo de ventana se convierta en la ventana activa, incluso las láminas, lo que fue imposible en versiones anteriores de MacOS y en aplicaciones independientes (en versiones anteriores, solo la ventana de preferencias principales reales se convertiría en la mainWindow
).
Cuando una hoja modal está abierta y el usuario desea abrir una nueva hoja, la hoja original debe cerrarse primero. Pero el error de Apple hace que el cheque de Wacom para ver si actualmente hay una hoja abierta para fallar, ya que cuando verifica si una hoja está conectada a la mainWindow
, en su lugar termina revisando una hoja conectada a la hoja actual, que tiene inexplicable inexplicable Conviértete en la mainWindow
. Esto desencadena un bloqueo (por ejemplo, en la configuración de mapeo de la pluma).
Partí los accesos a mainWindow
para que el primer valor que se lee se almacena en caché después, por lo que siempre que el valor inicial sea sensato, no se rompa después de que la mainWindow
se actualice para apuntar a la primera hoja inaugurada (consulte PenTablet.prefpane.newcode.asm
).
El controlador Intuos 3 y Cintiq tiene un error en su panel de preferencia que hace que se bloquee tan pronto como se hace clic en un elemento.
Una de las principales características de la interfaz de usuario del panel de preferencia son las listas de iconos que representan las tabletas, herramientas y aplicaciones que puede configurar. Ese control de la lista de iconos utiliza una función como esta para enviar eventos (como clics) a sus hijos:
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);
}
El problema con este código es que requiere que la función de handler()
del evento devuelva un objeto, que luego conserva inútil () y libera (). Pero una de las funciones del controlador que se llamará es OEventDispatcher_Professional::listClickAction()
, ¡y esa función es una función void
(sin un valor de retorno bien definido)!
Entonces action:()
termina llamando retain()
y release()
en un puntero de basura, que causa un Segfault.
El parche aquí es fácil: se elimina ese par de llamadas retain()
y release()
. El mismo error existe en ONumberTextField::textDidChange:
con la misma solución.
Hay otro problema con este controlador. Si, al intentar que su tableta funcione, instala accidentalmente el último controlador de Wacom (que no admite Intuos 3), escribe un archivo de preferencias de formato más nuevo que el antiguo controlador Intuos 3 se bloqueará al intentar leer. Y esta situación no se resuelve a sí misma, el usuario debe usar manualmente la utilidad de Wacom para eliminar las preferencias de la tableta para solucionarlo.
Esto es extraño porque el archivo de preferencia incluye un número de versión diseñado para evitar esta misma situación. El controlador antiguo usa la versión 5, y el último controlador usa la versión 6:
< ImportFileVersion type = " integer " >6</ ImportFileVersion >
Y el código del controlador verifica explícitamente este número de versión y debe abortar cuando sea demasiado nuevo:
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
}
}
...
}
Pero el conductor nunca aborta, sino que se bloquea mientras intenta cargar las preferencias. Entonces, ¿qué va mal aquí? El secreto se encuentra dentro de la función MigratePen()
. Esta función está diseñada para actualizar los archivos de configuración más antiguos a la versión actual, ¡pero desafortunadamente en el proceso sobrescribe incondicionalmente la ImportFileVersion
con la versión actual (5)! Esto deja CTabletDriver::ReadSettings()
No puede detectar que la configuración es demasiado nueva para ser analizada.
Para resolver esto, reforzé el código de detección de versión no válido de MigratePen()
::
if (settingsVersion < 1 ) {
// Report invalid settings version and return NULL
}
Para hacerlo:
if (settingsVersion < 1 || settingsVersion > 5 ) {
// Report invalid settings version and return NULL
}
Entonces, ahora si las preferencias son demasiado nuevas, MigratePen()
no intentará actualizarlas, y ReadSettings()
saltará limpiamente la carga de las preferencias. Esto hace que las preferencias permanezcan en sus valores predeterminados, y si el usuario edita la configuración utilizando el panel de preferencia, la configuración debe sobrescribirse limpiamente.
Los instaladores de los controladores Graphire son un formato antiguo que Catalina ya no admite, por lo que tuve que reconstruirlos por completo.
El panel de preferencia de Graphire se basó incorrectamente en símbolos privados de la biblioteca estándar de MacOS que ya no están presentes en Catalina, por lo que ya no podía comenzar.
Por ejemplo, la función NSNIBWAINGOURKERRIDE :: AWAKEFROMNIB () de Wacom se llama durante la deserialización de la GUI, y agrega el control de GUI cargado a un mapa para que se pueda acceder a su etiqueta más adelante:
void NSNibWakingOverride::awakeFromNib (NSControl * this ) {
OMasterDictionaryPtr-> addObject :withTag:( this , this -> _tag ));
}
Pero esto se basa en leer nscontrol._tag, que es un campo privado. En MacOS 10.9 que funcionó porque NSControl se definió así:
@interface NSControl : NSView
{
/* All instance variables are private */
NSInteger _tag;
id _cell;
struct __conFlags {
...
} _conFlags;
}
Pero en MacOS 10.10, NSControl se refactoró para mover el campo _TAG a un nuevo campo _aux, haciéndolo inaccesible:
@interface NSControl : NSView
{
/* All instance variables are private */
NSControlAuxiliary *_aux;
id _cell;
struct __conFlags {
...
} _conFlags;
}
@property NSInteger tag;
Parché Awake deMnib para que llame correctamente la función de los accesorios públicos para este campo:
void NSNibWakingOverride::awakeFromNib (NSControl * this ) {
OMasterDictionaryPtr-> addObject :withTag:( this , this -> tag ()));
}
En la función OpoPupoutLineView :: ReloadData () de Wacom, el campo privado nstableView._dataSource se lee incorrectamente directamente:
void OPopupOutlineView::reloadData (OPopupOutlineView * this ) {
this -> _dataSource . willReloadDataForOutlineView ( this );
...
}
Así que reparé esto para usar el accesor público en su lugar:
void OPopupOutlineView::reloadData (OPopupOutlineView * this ) {
this -> dataSource ()-> willReloadDataForOutlineView ( this );
...
}
Estos controladores tienen los mismos problemas que los controladores Graphire 3 y 4, más el mismo problema _dataSource
en su ORadialSubMenuTableView::reloadData() method
, con la misma solución.