Os drivers macos de Wacom para bambu, grafire, Intuos 1, 2 e 3 e os comprimidos de 1ª geração do Cintiq têm bugs neles que fazem com que eles não comecem completamente ao iniciar o MacOS 10.15 Catalina e as versões posteriores (incluindo 11 Big Sur e 12 Monterey). Isso não se aplica ao driver do Windows ou aos drivers para seus tablets mais recentes.
Quando você tenta abrir o painel de preferência de Wacom com um tablet de bambu, você receberá uma mensagem de erro dizendo "aguardando a sincronização", então finalmente "há um problema com seu driver de tablet. Reinicie seu sistema. Se o problema persistir ou atualize o driver ". Para um tablet Intuos 3 ou Cintiq 1st Gen, o painel de preferências será aberto, mas clicar em qualquer coisa fará com que ele traga a mensagem "Houve um erro nas preferências do tablet Wacom". Para comprimidos de grafire e Intuos 1 e 2, o instalador do motorista não conseguiu nem executar na Catalina.
Felizmente, consegui rastrear os problemas e corri os motoristas para consertá -los!
Meu driver de bambu fixo (v5.3.7-6) suporta estes tablets:
Meu driver fixo grafire 1 e 2 e Intuos 1 e 2 (v6.1.6-4) suporta estes tablets:
Meu driver fixo grafire 3 (v5.2.6-5) suporta estes tablets:
Meu driver fixo 4 grafire 4 (v5.3.0-3) suporta estes tablets:
E meu driver fixo Intuos 3 e Cintiq (v6.3.15-3) suporta estes tablets:
Para Intuos 4, minha correção não é necessária. Você pode usar o motorista oficial da Wacom v6.3.41-2.
? Instruções simplificadas em inglês
? / ?? Instruças em Portugues
? 日本語で表示
? И и и и и и и и и иP
? Instruccionas en Español
? Instrukcja Po Polsku
? Instruções em Français
Faça o download do instalador correto do seu tablet aqui e clique duas vezes para executá -lo, isso instalará minha versão fixa do driver de Wacom:
Se você receber uma mensagem de erro de que seu Mac apenas permite que os aplicativos sejam instalados na App Store, clique com o botão direito do mouse e clique em "Abrir".
Após a instalação, siga as instruções na próxima seção para corrigir as permissões do tablet.
Toque em sua gorjeta de caneta para o seu tablet e isso deve solicitar que você visite preferências do sistema> Segurança e privacidade> Guia Privacidade para conceder as permissões de tablets.
Na página de acessibilidade, clique no cadeado para desbloquear a página, depois encontre e marque qualquer PenTabletDriver
, WacomTabletDriver
TabletDriver
ou WacomTabletSpringboard
que você vê na lista. Faça o mesmo na página de monitoramento de entrada.
Se o seu tablet suportar toque, toque no tablet com o dedo, ele deve solicitar novamente a conceder permissões. Na página de acessibilidade, marque a entrada do ConsumerTouchDriver
ou WacomTouchDriver
.
Com alguns tablets, o driver pode aparecer apenas na página de monitoramento de entrada e pode ser necessário reiniciar uma segunda vez para que ele também apareça na página de acessibilidade.
Você provavelmente teve permissões restantes do driver de tablet anterior, e essas entradas obsoletas precisam ser removidas assim:
Na página "Acessibilidade" de Segurança e Privacidade, encontre qualquer coisa relacionada a Wacom na lista (por exemplo, PenTabletDriver
, WacomTabletDriver
, TabletDriver
, ConsumerTouchDriver
, WacomTabletSpringboard
, WacomTouchDriver
), selecione -os e clique no botão Minus para removê -los. Vá para a "página de monitoramento de entrada" e faça o mesmo lá.
Agora, reinicie o computador ou execute esses dois comandos no terminal, para recarregar o driver do tablet. Para bambu e grafire 3 e 4 comprimidos:
launchctl unload /Library/LaunchAgents/com.wacom.pentablet.plist
launchctl load -w /Library/LaunchAgents/com.wacom.pentablet.plist
Para os comprimidos Graphire 1 e 2, Intuos e Cintiq:
launchctl unload /Library/LaunchAgents/com.wacom.wacomtablet.plist
launchctl load -w /Library/LaunchAgents/com.wacom.wacomtablet.plist
Isso deve restaurar os avisos para solicitar que você adicione permissões, então agora inicie as instruções nesta seção novamente.
Para um punhado de pessoas, o driver Wacom nunca aparece na lista de monitoramento de entrada para elas. Para corrigir isso, primeiro abra o aplicativo "terminal" e cole essa linha e pressione Enter para garantir que o serviço Wacom esteja ativado:
Para bambu e grafire 3 e 4 comprimidos:
launchctl load -w /Library/LaunchAgents/com.wacom.pentablet.plist
Para os comprimidos Graphire 1 e 2, Intuos e Cintiq:
launchctl load -w /Library/LaunchAgents/com.wacom.wacomtablet.plist
Se isso não o acionar para solicitar que você adicione permissões de monitoramento de entrada ao tentar usar o tablet, poderá adicioná -lo manualmente.
No Finder, clique em GO -> Vá para a pasta e cole este caminho lá e clique em OK:
/Library/Application Support/Tablet/
Lá, você deve ver um arquivo "Pentabletdriver" (bambu), "Pentabletspringboard" (Graphire 3 e 4) ou "Wacomtabletspringboard" (Graphire 1 e 2, Intuos, Cintiq).
Desbloqueie a página de monitoramento de entrada e arraste o arquivo PENTABLETDRIVER / PENTABLETSPRINGBOARD / WACOMTABLETSPRINGBOARD para adicioná -lo à lista e verifique se ela está marcada. Agora, reinicie o seu computador e, quando você tenta usar o tablet, ele deve solicitar que você o marque na página de acessibilidade, após o que ele deve começar a funcionar.
Certifique -se de ainda não ter o driver mais recente de Wacom instalado. Use "Wacom Utility"/ "Tablet Utility" para desinstalar completamente todos os drivers de Wacom (em vez de apenas arrastá -los para o lixo) e instale meu driver novamente.
As preferências corruptas podem impedir que as coisas funcionem, especialmente se você instalou várias versões de driver diferentes enquanto tentava fazer as coisas funcionarem. Use o Wacom Utility para redefinir suas preferências, reiniciar e tente usar o tablet novamente.
Se você gostou de ter seu tablet de volta em ação, considere me enviar uma dica!
Isso ajudará a me financiar e o desenvolvimento adicional desses fatores fixos.
O PentableTdriver lança dois sub-drivers para fazer o trabalho para ele, ConsumerTouchDriver e tabletdriver. Para encontrar esses drivers em sua pasta de recursos, ele finalmente chama essa função para extrair um caminho de um 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 */
}
Perdoe -me por parafrasear o código C Objetivo original como C ++, não falo objc!
Quando o CFURL cria o caminho, sua contagem de referência começa em 1. Ele fila a contagem de referência para diminuir posteriormente chamando autorelease()
nele e o retorna ao driver de Wacom. Essa chamada para autorelease
se combina com a chamada retainAutoreleasedReturnValue()
da Wacom () e deixa a contagem de referência do caminho intocada, em 1.
Mas agora o driver Wacom chama _objc_release()
no caminho. Isso diminui sua contagem de referência para 0, e o caminho é imediatamente liberado!
Esse caminho liberado é usado durante o lançamento do sub-driver, que pode desencadear um segfault no ProcessUtils::LaunchApplicationWithBundleID()
. Isso mata o motorista.
A correção é uma alteração de byte que substitui a chamada para _objc_release()
no PathFromURL
a uma chamada para _objc_retain()
. Isso impede que o caminho seja libertado antes de ser usado, o que cura o segfault.
O ConsumerTouchdriver também contém esse mesmo bug, e o patch é o mesmo lá.
O driver da caneta e o driver de toque precisam de correções para impedir que um gesto com vários toques seja executado, ou o anel de rolagem é usado para aumentar o zoom.
Quando um gesto é executado, a função CMacHIDGestureEventOSX1010::PostGesture
é responsável por enviar esse gesto para o sistema operacional:
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 como o resultado do cgeventCreate está sendo lançado em uma estrutura? O CGEVENT deve ser do tipo opaco, os programas não devem conhecer ou confiar em seu layout, uma vez que sua estrutura muda da versão do OS para a versão do OS, mas aqui está sendo lançado em uma estrutura para que seus campos eventSubType
e eventDirAmount
possam ser atribuído diretamente. Essas duas gravações causam corrupção de heap na Catalina e desencadeiam um acidente, porque o layout do CGEvent
mudou desde a Sierra!
A maneira correta de armazenar valores em um evento é usando a API CGEVENTESTINTEGERVERVALUEFIELD, que permite que você se consulte a campos de CGEVENT por um ID lógico em vez de sua posição na memória. Então, quais são os IDs de campo equivalentes para as duas gravações que o driver Wacom precisa fazer?
Desmontei a estrutura da clarabóia de MacOS Sierra, que contém a implementação do CGEventSetIntegerValueField
, para ver o que os IDs deveriam ter sido para esses campos. Parece que o eventSubType
pode ser escrito pelo ID do campo 110, e o eventDirAmount
pode ser escrito pelo ID 115. Mas esses IDs de campo não podem ser encontrados na documentação da Apple, o que explica por que Wacom não poderia usá -los!
Fiz algumas pesquisas no Google e descobri que esses campos não estão documentados porque fazem parte da API privada da Apple. Este cabeçalho do webkit revela seus nomes:
kCGEventGestureHIDType = 110
kCGEventGestureSwipeValue = 115
kCGEventGesturePhase = 132
E esses campos privados de API são estáveis da Sierra até Big Sur! Agora que sabemos disso, as duas tarefas à estrutura de eventos podem ser substituídas por essas chamadas, e as falhas do motorista são eliminadas:
_CGEventSetIntegerValueField (eventStructure, 110 /* kCGEventGestureHIDType */ , gestureType_I);
_CGEventSetIntegerValueField (eventStructure, 115 /* kCGEventGestureSwipeValue */ , eventDirAmount);
A versão de ponto flutuante do postgesture tem o mesmo 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);
}
E podemos consertar assim:
_CGEventSetIntegerValueField (eventStructure, 110 /* kCGEventGestureHIDType */ , gestureType_I);
_CGEventSetIntegerValueField (eventStructure, 115 /* kCGEventGestureSwipeValue */ , reinterpret_cast < int32_t &>(dirAmount));
_CGEventSetIntegerValueField (eventStructure, 132 /* kCGEventGesturePhase */ , this ->eventPhase);
No painel de preferência de Wacom, Wacom é vítima do bug da maçã 8746551. Desde que o MacOS Catalina, o painel de preferência quebra efetivamente a operação de NSApp->mainWindow
, permitindo que qualquer tipo de janela se torne a janela ativa, mesmo as folhas, o que era impossível nas versões anteriores de MacOS e em aplicativos independentes (nas versões anteriores, apenas a janela de preferências principais reais se tornaria a mainWindow
).
Quando uma folha modal está aberta e o usuário deseja abrir uma nova folha, a folha original precisa ser fechada primeiro. Mas o bug da Apple faz com que a verificação de Wacom vermos se há atualmente uma folha aberta para falhar, pois quando ele verifica se uma folha está anexada ao mainWindow
, ele acaba checando uma folha conectada à folha atual, que possui inexplicavelmente Torne -se o mainWindow
. Isso desencadeia um acidente (por exemplo, nas configurações de mapeamento de caneta).
Eu corrigi os acessos ao mainWindow
para que o primeiro valor que seja lido seja armazenado em cache depois, assim que o valor inicial for sensato, ele não será quebrado depois que o mainWindow
for atualizado para apontar para a primeira folha aberta (consulte PenTablet.prefpane.newcode.asm
).
O driver Intuos 3 e Cintiq tem um bug em seu painel de preferência que o faz travar assim que um item for clicado.
Um dos principais recursos da interface do usuário do painel de preferência são as listas de ícones que representam os tablets, ferramentas e aplicativos que você pode configurar. Esse controle da lista de ícones usa uma função como essa para despachar eventos (como cliques) para seus filhos:
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);
}
O problema com este código é que ele exige que a função handler()
do evento retorne um objeto, que ele mantém inutisivamente () e libera (). Mas uma das funções do manipulador que será chamada é OEventDispatcher_Professional::listClickAction()
, e essa função é uma função void
(sem valor de retorno bem definido)!
Portanto, action:()
acaba chamando retain()
e release()
em um ponteiro de lixo, que causa um segfault.
O patch aqui é fácil - que as chamadas inúteis de retain()
e release()
são excluídas. O mesmo bug existe no ONumberTextField::textDidChange:
, com a mesma correção.
Há outro problema com esse motorista. Se, ao tentar fazer com que seu tablet funcione, você instala acidentalmente o driver WACOM mais recente (que não suporta o Intuos 3), ele grava um arquivo de preferência de formato mais recente que o antigo driver Intuos 3 falhará ao tentar ler. E essa situação não se resolve, o usuário precisa usar manualmente o utilitário wacom para excluir as preferências do tablet para corrigi -lo.
Isso é estranho porque o arquivo de preferência inclui um número de versão projetado para evitar essa mesma situação. O antigo driver usa a versão 5 e o driver mais recente usa a versão 6:
< ImportFileVersion type = " integer " >6</ ImportFileVersion >
E o código do motorista verifica explicitamente o número deste número de versão e deve abortar quando for muito novo:
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
}
}
...
}
Mas o motorista nunca aborta, em vez disso, trava enquanto tenta carregar as preferências. Então, o que está errado aqui? O segredo está dentro da função MigratePen()
. Esta função foi projetada para atualizar os arquivos de configurações mais antigas para a versão atual, mas infelizmente, no processo, ele substitui incondicionalmente o ImportFileVersion
com a versão atual (5)! Isso deixa CTabletDriver::ReadSettings()
incapaz de detectar que as configurações são novas demais para serem analisadas.
Para resolver isso, aprimorei o código de detecção de versão inválida de MigratePen()
:
if (settingsVersion < 1 ) {
// Report invalid settings version and return NULL
}
Para fazer isso:
if (settingsVersion < 1 || settingsVersion > 5 ) {
// Report invalid settings version and return NULL
}
Então agora, se as preferências forem muito novas, MigratePen()
não tentará atualizá -las, e ReadSettings()
pulará de maneira limpa carregando as preferências. Isso faz com que as preferências permaneçam em seus padrões e, se o usuário editar as configurações usando o painel de preferência, as configurações devem ser substituídas de maneira limpa.
Os instaladores dos drivers de grafire são um formato antigo que a Catalina não suporta mais, então tive que reconstruí -los completamente.
O painel de preferências da Graphire se baseou incorretamente em símbolos privados da biblioteca padrão do MacOS que não estão mais presentes na Catalina, para que não pudesse mais começar.
Por exemplo, a função NSNIBWAKOVERRIDE :: AwakeFromnib () de Wacom é chamada durante a deserialização da GUI e adiciona o controle da GUI carregado a um mapa para que possa ser acessado por sua etiqueta mais tarde:
void NSNibWakingOverride::awakeFromNib (NSControl * this ) {
OMasterDictionaryPtr-> addObject :withTag:( this , this -> _tag ));
}
Mas isso depende da leitura do NSControl._Tag, que é um campo privado. No MacOS 10.9, isso funcionou porque o NSControl foi definido assim:
@interface NSControl : NSView
{
/* All instance variables are private */
NSInteger _tag;
id _cell;
struct __conFlags {
...
} _conFlags;
}
Mas no MacOS 10.10, o NSControl foi refaturado para mover o campo _TAG para um novo campo _aux, tornando -o inacessível:
@interface NSControl : NSView
{
/* All instance variables are private */
NSControlAuxiliary *_aux;
id _cell;
struct __conFlags {
...
} _conFlags;
}
@property NSInteger tag;
Eu corrigi o despertar de fazê -lo chamar corretamente a função de acessador público para este campo:
void NSNibWakingOverride::awakeFromNib (NSControl * this ) {
OMasterDictionaryPtr-> addObject :withTag:( this , this -> tag ()));
}
Na função OpoPUPOUTLINEVIEW :: Relloaddata () da Wacom, o campo privado nStableView._DataSource é lido incorretamente diretamente:
void OPopupOutlineView::reloadData (OPopupOutlineView * this ) {
this -> _dataSource . willReloadDataForOutlineView ( this );
...
}
Então, corrigi isso para usar o acessador público: em vez disso:
void OPopupOutlineView::reloadData (OPopupOutlineView * this ) {
this -> dataSource ()-> willReloadDataForOutlineView ( this );
...
}
Esses drivers têm os mesmos problemas que os drivers Graphire 3 e 4, além do mesmo problema _dataSource
em seu ORadialSubMenuTableView::reloadData() method
, com a mesma correção.