Intercepter F7/F8/F9 des derniers claviers

23:18 modifié dans API AppKit #1
Bonjour à  tous,

Oui encore moi  >:)
Je cherche à  intercepter les touches "back ; Play/Pause ; Next" ou "F7 ; F8 ; F9" des derniers claviers. Pour l'instant mon code ne marche que lorsque la touche FN est enfoncé aussi.

<br />#import &lt;Carbon/Carbon.h&gt;<br /><br />OSStatus MyHotKeyHandler(EventHandlerCallRef nextHandler,EventRef theEvent,<br />						 void *userData)<br />{<br />	EventHotKeyID hkCom;<br />	GetEventParameter(theEvent,kEventParamDirectObject,typeEventHotKeyID,NULL,<br />					&nbsp; sizeof(hkCom),NULL,&amp;hkCom);<br />	int l = hkCom.id;<br /><br />	switch (l) {<br />		case 1: NSLog(@&quot;Duh Sumthin&#39;&quot;);<br />			break;<br />		<br />	}<br />	return noErr;<br />}<br /><br /><br />@implementation AppController<br /><br /> (void)awakeFromNib<br />{<br />	<br />	EventHotKeyRef gMyHotKeyRef;<br />	EventHotKeyID gMyHotKeyID;<br />	EventTypeSpec eventType;<br />	eventType.eventClass=kEventClassKeyboard;<br />	eventType.eventKind=kEventHotKeyPressed;<br />	<br />	InstallApplicationEventHandler(&amp;MyHotKeyHandler,1,&amp;eventType,NULL,NULL);<br />	<br />	gMyHotKeyID.signature=&#39;htk1&#39;;<br />	gMyHotKeyID.id=1;<br /><br />	RegisterEventHotKey(98, 0, gMyHotKeyID,<br />						GetApplicationEventTarget(), 0, &amp;gMyHotKeyRef);<br />}<br />


98 correspond à  F7.

En fait tout ce que je cherche à  éviter, c'est le fait que la touche function doit être enfoncée pour que ça marche

Réponses

  • NseaProtectorNseaProtector Membre
    23:18 modifié #2
    http://dbachrach.com/blog/2005/11/28/program-global-hotkeys-in-cocoa-easily/
    Je pense que tu pourrais trouver ce liens intéressant.
  • NseaProtectorNseaProtector Membre
    23:18 modifié #3
    Je me sens bête là  ?
  • NoNo Membre
    23:18 modifié #4
    On ne peut pas (du moins avec les hot keys).
    L'emploi de FN + une touche de fonction est directement gérée par le driver du clavier, et est donc inaccessible aux couches hautes (les événements) du clavier.

    Le hack utilisé par de nombreux sharewares pour modifier le comportement de FN passe par le remplacement (à  chaud) du driver du clavier.
    Mais cela est complexe (beaucoup de cambouis), et surtout est global au système.

    Note :
    les hot keys font partie du passé (RegisterEventHotKey est du Carbon, donc carbonisable à  tout moment par Apple).
    Il faut maintenant utiliser les event tap de Quartz (le window server) à  la place.
  • NoNo Membre
    23:18 modifié #5
    dans 1239636985:

    Je me sens bête là  ?


    Tu peux...

    Déjà , les hot keys mentionnés par ton lien sont déjà  utilisés par Louka.

    De plus, ta compil' échoue, vraisemblablement car tu n'a pas ajouté le framework Carbon à  ton projet (du moins ce que suggère les erreurs de linking final visibles sur ta capture).
  • NseaProtectorNseaProtector Membre
    23:18 modifié #6
    dans 1239637166:

    dans 1239636985:

    Je me sens bête là  ?


    Tu peux...

    Déjà , les hot keys mentionnés par ton lien sont déjà  utilisés par Louka.

    De plus, ta compil' échoue, vraisemblablement car tu n'a pas ajouté le framework Carbon à  ton projet (du moins ce que suggère les erreurs de linking final visibles sur ta capture).

    Oui j'ai bien cherché ce framework, c'est pour ça que l'arborescence des frameworks est ouverte. Il n'est pas dans hd/system/library/framework ?
    Ps: Je me sens bien, car en attendant j'apprends pleins de choses... Chaque jour, j'en sais plus encore. Merci à  vous.
  • NoNo Membre
    23:18 modifié #7
    dans 1239637831:

    Oui j'ai bien cherché ce framework, c'est pour ça que l'arborescence des frameworks est ouverte. Il n'est pas dans hd/system/library/framework ?


    Si chez moi il se trouve bien là .

  • NseaProtectorNseaProtector Membre
    23:18 modifié #8
    Oui pardon, c'est à  cause du tri, je suis passé à  côté !!!
    Maintenant ça compile.
  • 23:18 modifié #9
    Merci de vos infos en tout cas  ;D
  • 23:18 modifié #10
    Je remonte un peu le sujet car je me demande si au final il n'y aurait pas plutôt des notifications cachées pour ces 3 raccourcis ? Car il faut savoir qu'ils répondent meme quand on lance un jeu en fullscreen alors que les fn + F.... sont, évidemment, overridés.
    Je suis vraiment étonné que la seule solution soit de bidouiller le driver.
  • NoNo Membre
    avril 2009 modifié #11
    Et moi dont mon clavier de MacBook n'a pas de "back ; Play/Pause ; Next" branché dur F7 F8 et F9 (qui sont dédiés à  Exposé et à  l'écran externe), je fais comment avec ton logiciel qui va vouloir m'imposer ces touches et les détourner de ce qu'elles font habituellement ?
  • avril 2009 modifié #12
    dans 1239832913:

    Et moi dont mon clavier de MacBook n'a pas de "back ; Play/Pause ; Next" branché dur F7 F8 et F9 (qui sont dédiés à  Exposé et à  l'écran externe), je fais comment avec ton logiciel qui va vouloir m'imposer ces touches et les détourner de ce qu'elles font habituellement ?


    J'ai jamais parlé de les détourner mais de les intercepter -.- je veux pas bloquer leur utilisation normal justement. Je veux juste savoir si il n'y a pas un système de notifications justement quand on appuie sur ces touches, histoire que mon appli n'empêche pas leur fonctionnement mais le capte en meme temps.

    Par contre, vu que tu donnes des conseils judicieux, je vais aussi t'en donner un.. essaye de faire attention quand tu réponds à  un message.. parce que ça fait deux fois que t'es un peu froissant. Surtout que comme je te l'ai expliqué, je cherche pas à  imposer.. d'où l'histoire de notifications pour ces nouvelles touches
  • yoannyoann Membre
    23:18 modifié #13
    Ici tu a un exemple pour afficher toutes les notifications qui passe sur le système (entre autre pour voir celle de la télécommande)

    http://www.cocoadev.com/index.pl?UsingTheAppleRemoteControl

    tu peut voir s'il y a quelque chose pour les touches, à  savoir que Spotify arrive à  les intercepter sur mon Mac Pro.
  • NoNo Membre
    23:18 modifié #14
    dans 1239836616:

    Par contre, vu que tu donnes des conseils judicieux, je vais aussi t'en donner un.. essaye de faire attention quand tu réponds à  un message.. parce que ça fait deux fois que t'es un peu froissant. Surtout que comme je te l'ai expliqué, je cherche pas à  imposer.. d'où l'histoire de notifications pour ces nouvelles touches


    Pour ne pas avoir de réponse froissante, pose des questions moins tête brulée... Car que ce soit avec ton message sur la désactivation de LittleSnitch, celui sur la modif de la base iTunes sans passer par iTunes, ou maintenant celui de la modif du comportement clavier (car c'est bien à  cela que sert RegisterEventKotKey du premier message de cette discussion) au niveau système (et donc pas à  l'intérieur de ton appli), tout cela me parait franchement casse-cou.

    Maintenant pour en revenir à  la question initiale.

    Les applis plien écran capturent (c'est le terme exact) l'affichage et le clavier. En fait lors de cette capture, le window-server est désactivé.
    Ce qui fait que c'est à  l'appli plein écran de gérer entièrement l'affichage et la gestion des événements (par la lecture du clavier, par le dessin à  l'écran au bas niveau, etc).
    C'est pourquoi dans une telle appli, beaucoup de fonctions gérées par window-server ne sont plus accessibles (le POMME-TAB, Exposé, le screen saver, etc...).

    Maintenant que tu parles, non d'intercepter les touches F7 F8 F9 (voir ton premier message, 4ème ligne à  partir du 4ème mot) mais de recevoir les notifications des actions play/pause, back et next, si elles sont effectivement gérées par le système, je suis d'accord pour t'aider à  chercher la solution.
  • 23:18 modifié #15
    J'avoue que sur certains points j'ai souvent chercher à  faire chier l'utilisateur sans vraiment réfléchir à  la question. Mais je te confirme bien que sur le point des controls iTunes au clavier je cherche simplement à  savoir quand ces touches sont appuyés sans modifier leurs comportement.

    Je veux bien de ton aide si tu le proposes :D J'ai tenté d'observer toutes les notifications qui passent (j'avais complètement zappé ça) et rien du tout pour ces 3 touches.
  • NoNo Membre
    23:18 modifié #16
    dans 1239875126:

    Je veux bien de ton aide si tu le proposes :D J'ai tenté d'observer toutes les notifications qui passent (j'avais complètement zappé ça) et rien du tout pour ces 3 touches.


    Puisque rassuré sur tes intentions, commençons !

    Donc comme je pensais, on ne peut pas traiter ces évèéements (play/pause, back, next) comme des appuis de touche (F7, F8, F9).

    Mais, il y a un autre moyen assez simple, et mieux tout en Obj-C/cocoa (donc pas de C caca à  taper) pour pouvoir savoir si lesdites touches ont été appuyées.

    Avant de continuer, il faut que je sache un peu plus sur ton appli.
    Est ce une appli cocoa standard ?
  • NoNo Membre
    avril 2009 modifié #17
    Dans le cas d'une appli cocoa standard, le plus simple est de sous-classer NSApplication, car le système va envoyer l'info d'appui sur les touches PLAY/PAUSE etc. sous forme d'un NSEvent.

    Le NSEvent est de type NSSystemDefined et de sous-type 8 (là  c'est du non documenté).
    Ensuite l'info importante est stockée dans data1 qui renvoie un entier.
    La partie haute de cet entier stocke un code touche, alors que la partie basse donne divers flags (dont le flag touche appuyée/relachée et si c'est une répétition -appui long- )

    La bonne nouvelle est que ces NSEvent sont reçus même quand l'appli est en arrière plan : idéal pour les helpers ou applis sans UI.

    Voici le code exemple :
    <br />#import &lt;Cocoa/Cocoa.h&gt;<br /><br />@interface CustomApplication : NSApplication<br />{<br />}<br />@end<br /><br />@implementation CustomApplication<br /><br />- (void)sendEvent:(NSEvent*)event<br />{<br />   // on transmet le NSEvent à  super sinon, l&#39;appli ne recevra plus les événements !<br />   [super sendEvent:event];<br /><br />   // les touches PLAY/PAUSE, BACK, NEXT sont mappées en événement NSSystemDefined de sous-type 8<br />   if ([event type]!=NSSystemDefined) return;<br />   if ([event subtype]!=8) return;<br /><br />   // l&#39;attribut data1 de NSEvent contient toutes les infos concernant quelle touche a été appuyée<br />   int data=[event data1];<br /><br />   // extraction du code touche appuyée (contenu dans les bits 16 à  31 de data1)<br />   int touche=(data&amp;0xFFFF0000)&gt;&gt;16;<br /><br />   // détection si c&#39;est un appui ou un relachement (bit 9 de data1 : 0=appui, 1=relachement)<br />   BOOL appui=((data&amp;0x100)==0);<br /><br />   // détection si c&#39;est une répétition (bit 0 de data1 à  1)<br />   BOOL repetition=((data&amp;0x01)!=0);<br /><br />   // création d&#39;un dictionnaire contenant les infos précédemment extraites<br />   NSDictionary *userInfo=[[NSDictionary alloc] initWithObjectsAndKeys:[NSNumber numberWithInt:touche], @&quot;touche&quot;,<br />                                                                       [NSNumber numberWithBool:appui], @&quot;appui&quot;,<br />                                                                       [NSNumber numberWithBool:repetition], @&quot;repet&quot;, nil];<br />	<br />   // maintenant on envoie une notification pour avertir le reste de l&#39;appli<br />   [[NSNotificationCenter defaultCenter] postNotificationName:@&quot;toucheitunes&quot; object:self userInfo:userInfo];<br />	<br />   // nettoyage<br />   [userInfo release];<br />}<br />
    


    Il faut modifier le info.plist, clé Principal class en y remplaçant NSApplication par CustomApplication.

    le code ne fait qu'envoyer une notification au reste de l'appli. Cette notif se nomme "toucheitunes", et son userInfo contient un NSDictionary de 3 clés : le code touche ("touche"), un bool d'appui/relachement ("appui") et un bool de répétition ("repet").

    Les codes touches sont multiples. 16, 17 et 18 sont PLAY/PAUSE, NEXT, PREVIOUS. On peut aussi détecter la touche d'éjection du cd (code 14) et même celle d'extinction/veille (code 6). Sur mon macbook, les touches relatives au son et à  la luminosité d'écran sont aussi détectées.
    La liste des codes se trouve dans le fichier ev_keymap.h qui se trouve sur le mac quand les outils dev sont installés (faire une recherche de fichier).
  • 23:18 modifié #18
    Merci énormément No. Je suis un peu pris par un autre boulot mais je regarde ça cette après-midi  :o
    (Oui c'est une appli 100% Cocoa :) )
  • 23:18 modifié #19
    Ouarf merci beaucoup :o
    Par contre ducoup j'aimerai bien que ça ne marche que sur les claviers qui ont ces touches. Une autre idée pour savoir si le clavier comporte ces raccourcis là  ?
  • NoNo Membre
    23:18 modifié #20
    dans 1239973079:

    Ouarf merci beaucoup :o
    Par contre ducoup j'aimerai bien que ça ne marche que sur les claviers qui ont ces touches. Une autre idée pour savoir si le clavier comporte ces raccourcis là  ?


    Seuls les claviers munis de ces touches enverront ces NSEvent spéciaux.
  • 23:18 modifié #21
    dans 1239982133:

    dans 1239973079:

    Ouarf merci beaucoup :o
    Par contre ducoup j'aimerai bien que ça ne marche que sur les claviers qui ont ces touches. Une autre idée pour savoir si le clavier comporte ces raccourcis là  ?


    Seuls les claviers munis de ces touches enverront ces NSEvent spéciaux.


    Oui j'ai remarqué juste après :)
    En tout cas merci beaucoup, ça me sauve  :o
  • 23:18 modifié #22
    Salut,

    Je reviens sur le topic car j'ai upgradé sur Snow Leopard et j'ai testé mon application.. Ben figurez-vous que la touche play/pause des claviers permet de lancer iTunes maintenant  >:)
    Bon, soit.. c'est un truc que j'attendais déjà  depuis un moment.. mais en fait ça m'emmerde un peu pour mon application.

    Pour rentrer dans les détails, je fais un remplaçant d'iTunes, seulement niveau player. C'est à  dire que mon logiciel pourra lire la musique présente dans votre bibliothèque iTunes tout simplement.. c'est histoire d'avoir quelque chose de plus léger pour les gens qui n'ajoutent pas des musiques tous les jours, mais qui en revanche l'écoute tous les jours.

    D'où l'histoire de ces raccourcis que je voulais intercepter et réinterprêter comme iTunes.

    Sauf que là , si j'appuie sur la touche Play, ça lance iTunes.. et ça lance aussi la musique sur mon application..

    Vous pensez qu'il y a une solution pour éviter de faire lancer iTunes via cette touche tant que mon application est ouverte ?

    Ce n'est pas vraiment important car j'ai quand meme rajouter la possibilité de customizer les raccourcis claviers.. en fait les touches de controle iTunes sont un plus non visible dans mes préférences raccourcis clavier de mon Application. Si je trouve une solution à  mon petit problème, je rajouterai une option qui fera en sorte de choisir ou non de bloquer iTunes au niveau de ces touches  ;)
Connectez-vous ou Inscrivez-vous pour répondre.