wmix: added function to handle Multimedia keys related to volume
[dockapps.git] / wmix / mmkeys.c
blobbc226259a4e5c983e5e6be1a7a17d727481eb17d
1 /* WMix -- a mixer using the OSS mixer API.
2 * Copyright (C) 2014 Christophe CURIS for the WindowMaker Team
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 * mmkeys.c: functions related to grabing the Multimedia Keys on keyboard
22 #include <stdio.h>
23 #include <string.h>
25 #include <X11/Xlib.h>
26 #include <X11/keysym.h>
27 #include <X11/XF86keysym.h>
29 #include "include/common.h"
30 #include "include/config.h"
31 #include "include/mmkeys.h"
34 /* The global configuration */
35 struct multimedia_keys mmkeys;
37 /* The list of keys we're interrested in */
38 static const struct {
39 KeySym symbol;
40 KeyCode *store;
41 const char *name;
42 } key_list[] = {
43 { XF86XK_AudioRaiseVolume, &mmkeys.raise_volume, "AudioRaiseVolume" },
44 { XF86XK_AudioLowerVolume, &mmkeys.lower_volume, "AudioLowerVolume" },
45 { XF86XK_AudioMute, &mmkeys.mute, "AudioMute" }
48 /* The modifiers that should not have impact on the key grabbed */
49 static const struct {
50 KeySym symbol;
51 const char *name;
52 } modifier_symbol[] = {
53 { XK_Caps_Lock, "CapsLock" },
54 { XK_Num_Lock, "NumLock" }
57 typedef struct {
58 int count;
59 unsigned int list[1 << lengthof(modifier_symbol)];
60 } modifier_masks;
62 /* Local functions */
63 static void mmkey_build_modifier_list(Display *display, modifier_masks *result);
67 * Grab the multimedia keys on the X server
69 * That basically means that whenever these keys are pressed
70 * the events will be sent to us instead of the application
71 * that has current focus.
73 void mmkey_install(Display *display)
75 modifier_masks mod_masks;
76 Window root_window;
77 int i, j;
79 mmkey_build_modifier_list(display, &mod_masks);
81 root_window = DefaultRootWindow(display);
83 for (i = 0; i < lengthof(key_list); i++) {
84 KeyCode key;
86 key = XKeysymToKeycode(display, key_list[i].symbol);
87 *(key_list[i].store) = key;
89 if (key == None)
90 continue;
92 for (j = 0; j < mod_masks.count; j++) {
93 XGrabKey(display, key, mod_masks.list[j], root_window,
94 False, GrabModeAsync, GrabModeAsync);
96 if (config.verbose)
97 printf("Found multimedia key: %s\n", key_list[i].name);
102 * Build the list of bit-masks for all the modifiers we want to not have impact on our grab
104 static void mmkey_build_modifier_list(Display *display, modifier_masks *result)
106 XModifierKeymap *mods;
107 KeyCode mod_code[lengthof(modifier_symbol)];
108 unsigned int mod_mask[lengthof(modifier_symbol)];
109 char buffer[256];
110 int nb_modifiers;
111 int i, j, k;
113 /* Get the bitmask associated with the modifiers */
114 for (i = 0; i < lengthof(modifier_symbol); i++) {
115 mod_code[i] = XKeysymToKeycode(display, modifier_symbol[i].symbol);
116 mod_mask[i] = 0L;
119 mods = XGetModifierMapping(display);
120 for (i = 0; i < 8; i++) {
121 for (j = 0; j < mods->max_keypermod; j++) {
122 KeyCode key_mod;
124 key_mod = mods->modifiermap[i * mods->max_keypermod + j];
125 for (k = 0; k < lengthof(mod_code); k++) {
126 if ((mod_code[k] != None) && (key_mod == mod_code[k]))
127 mod_mask[k] |= 1 << i;
131 XFreeModifiermap(mods);
133 /* Count the number of modifiers found (and display the list to the user) */
134 if (config.verbose)
135 strcpy(buffer, "Found key modifiers: ");
137 nb_modifiers = 0;
138 for (i = 0; i < lengthof(modifier_symbol); i++) {
139 if (mod_mask[i] != 0) {
140 if (config.verbose) {
141 if (nb_modifiers > 0)
142 strcat(buffer, ", ");
143 strcat(buffer, modifier_symbol[i].name);
145 nb_modifiers++;
148 if (config.verbose) {
149 if (nb_modifiers == 0)
150 strcat(buffer, "None");
151 puts(buffer);
154 /* Build the list of possible combinations of modifiers */
155 result->count = 1 << nb_modifiers;
156 for (i = 0; i < lengthof(result->list); i++)
157 result->list[i] = 0L;
158 k = 1;
159 for (i = 0; i < lengthof(mod_mask); i++) {
160 if (mod_mask[i] != 0) {
161 for (j = 1; j < result->count; j++)
162 if (j & k)
163 result->list[j] |= mod_mask[i];
165 k <<= 1;