7
votes

CgeventTapCreate se décompose mystérieusement avec des événements "Key Down"

J'utilise cgeventtapcreate pour "voler" les touches multimédia de iTunes lorsque mon application est en cours d'exécution. Le code à l'intérieur du rappel que je passe à cgeventtapcreate examine l'événement et s'il estime que c'est l'une des touches multimédia, affiche une notification appropriée au centre de notification par défaut.

Maintenant, cela fonctionne bien si je pose une notification pour l'événement "Clé Up". Si je fais cela pour des événements "Key Down", mon application cesse d'obtenir des événements clés multimédia et que iTunes prend la relève. Des idées sur ce qui peut causer cela? La partie pertinente du code est inférieure à xxx


1 commentaires

Semble être un problème de synchronisation. Remplacé Post_Notification en veille (1) et là, après quelques keyresses, iTunes vole les touches de média si j'utilise PlayPauseKeway. Fonctionne toujours si j'utilise playpauseKeyup.


3 Réponses :


3
votes

Tout d'abord, pourquoi votre premier "si" permettez-vous de passer des événements de clé et de porte-clés à réussir? Votre deuxième "si" ne permet que des événements système passent de toute façon. Donc, pour tous les événements de clé de Key-Down /Up, vous créez un NSEvent, juste pour laisser tomber l'événement une ligne plus bas. Cela a peu de sens. Un robinet d'événement devrait toujours être aussi rapide que possible, sinon il ralentira tout traitement de l'événement de l'ensemble du système. Votre callback ne doit même pas être appelé à des événements de porte-clés / ups, car les événements système ne sont pas des événements de clé de Key-Bas-Bas et des événements système. S'ils étaient des événements clés, vous n'auriez certainement pas accès aux données1, mais utilisez plutôt les méthodes "Type" et "KeyCode" pour obtenir les informations pertinentes d'eux.

  // Analyze the key
  switch (keyCode) {
    case NX_KEYTYPE_PLAY:
      // Play/Pause key
      if (keyState == 0x0A) {
        // Key down
        // ...do your stuff here...
        return NULL;
      } else if (keyState == 0x0B) {
        // Key Up
        // ...do your stuff here...
        return NULL;
      }
      // If neither down nor up, we don't know
      // what it is and better ignore it
      break;


    case NX_KEYTYPE_FAST:
      // (Fast) Forward
      break;

    case NX_KEYTYPE_REWIND:
       // Rewind key
       break;
  }

  // If we get here, we have not handled
  // the event and want system to handle it
  return event;
}


1 commentaires

Merci, mecki! J'ai corrigé mon code, mais le problème persiste. Si je mets post_notification sous le "if (keyState == 0x0a) ...", iTunes "prendra la revue" des touches de média finalement, si je le mettais sous "Si (keyState == 0x0b)", tout semble fonctionner bien. post_notification appelle simplement PostNotificationName: ... du NSNotificationCenter par défaut. Maintenant, si je remplace Post_Notification par veille (1), le problème se produit beaucoup plus rapidement. Est-ce que quelque chose tue mon événement tap tak si le rappel prend trop de temps? Envoie une notification trop lente pour être appelée à partir du rappel?



10
votes

Quelque chose tue mon événement Tap Tap si le rappel prend trop de temps?

Certaines personnes soupçonnent que Snow Leopard a un bug qui désactive parfois des robinets d'événement même s'ils ne prennent pas trop de temps. Pour gérer cela, vous pouvez regarder pour le type d'événement kcgeventtapdisabledbyoutout et réagir en réactivant votre robinet avec cgeventtapenable . .


2 commentaires

Oui, c'était ça. Manipulation KCGENventTapDisabledByTimeOt fait le tour.


Merci! Cela me rendait fou!



0
votes

Dans votre gestionnaire, recherchez le type suivant et réactivez simplement l'auditeur.

if (type == kCGEventTapDisabledByTimeout) {
    NSLog(@"Event Taps Disabled! Re-enabling");
            CGEventTapEnable(eventTap, true);
    return event;
}


0 commentaires