pnmixer
Volume mixer for the system tray
hotkeys.c
Go to the documentation of this file.
1 /* hotkeys.c
2  * PNmixer is written by Nick Lanham, a fork of OBmixer
3  * which was programmed by Lee Ferrett, derived
4  * from the program "AbsVolume" by Paul Sherman
5  * This program is free software; you can redistribute
6  * it and/or modify it under the terms of the GNU General
7  * Public License v3. source code is available at
8  * <http://github.com/nicklan/pnmixer>
9  */
10 
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22 
23 #include <gdk/gdkx.h>
24 #include <X11/XKBlib.h>
25 
26 #include "audio.h"
27 #include "prefs.h"
28 #include "support-intl.h"
29 #include "support-log.h"
30 #include "hotkey.h"
31 #include "hotkeys.h"
32 
33 #include "main.h"
34 
35 /* Helpers */
36 
37 /* Removes the previously attached key_filter() function from
38  * the root window.
39  */
40 static void
41 hotkeys_remove_filter(GdkFilterFunc filter, gpointer data)
42 {
43  GdkWindow *window;
44 
45  window = gdk_x11_window_foreign_new_for_display
46  (gdk_display_get_default(), GDK_ROOT_WINDOW());
47 
48  gdk_window_remove_filter(window, filter, data);
49 }
50 
51 /* Ataches the key_filter() function as a filter
52  * to the root window, so it will intercept window events.
53  */
54 static void
55 hotkeys_add_filter(GdkFilterFunc filter, gpointer data)
56 {
57  GdkWindow *window;
58 
59  window = gdk_x11_window_foreign_new_for_display
60  (gdk_display_get_default(), GDK_ROOT_WINDOW());
61 
62  gdk_window_add_filter(window, filter, data);
63 }
64 
65 /* Public functions & callbacks */
66 
67 struct hotkeys {
68  /* Audio system */
70  /* Hotkeys */
74 };
75 
85 static GdkFilterReturn
86 key_filter(GdkXEvent *gdk_xevent, G_GNUC_UNUSED GdkEvent *event, gpointer data)
87 {
88  XKeyEvent *xevent = (XKeyEvent *) gdk_xevent;
89  Hotkeys *hotkeys = (Hotkeys *) data;
90  Hotkey *mute_hotkey = hotkeys->mute_hotkey;
91  Hotkey *up_hotkey = hotkeys->up_hotkey;
92  Hotkey *down_hotkey = hotkeys->down_hotkey;
93  Audio *audio = hotkeys->audio;
94  gint type;
95  guint key, state;
96 
97  type = xevent->type;
98  if (type != KeyPress)
99  return GDK_FILTER_CONTINUE;
100 
101  key = xevent->keycode;
102  state = xevent->state;
103 
104  if (mute_hotkey && hotkey_matches(mute_hotkey, key, state))
106  else if (up_hotkey && hotkey_matches(up_hotkey, key, state))
108  else if (down_hotkey && hotkey_matches(down_hotkey, key, state))
110 
111  return GDK_FILTER_CONTINUE;
112 }
113 
120 void
122 {
123  gboolean enabled;
124  gint key, mods;
125  gboolean mute_err, up_err, down_err;
126 
127  /* Free any hotkey that may be currently assigned */
128  hotkey_free(hotkeys->mute_hotkey);
129  hotkeys->mute_hotkey = NULL;
130 
131  hotkey_free(hotkeys->up_hotkey);
132  hotkeys->up_hotkey = NULL;
133 
134  hotkey_free(hotkeys->down_hotkey);
135  hotkeys->down_hotkey = NULL;
136 
137  /* Return if hotkeys are disabled */
138  enabled = prefs_get_boolean("EnableHotKeys", FALSE);
139  if (enabled == FALSE)
140  return;
141 
142  /* Setup mute hotkey */
143  mute_err = FALSE;
144  key = prefs_get_integer("VolMuteKey", -1);
145  mods = prefs_get_integer("VolMuteMods", 0);
146  if (key != -1) {
147  hotkeys->mute_hotkey = hotkey_new(key, mods);
148  if (hotkeys->mute_hotkey == NULL)
149  mute_err = TRUE;
150  }
151 
152  /* Setup volume up hotkey */
153  up_err = FALSE;
154  key = prefs_get_integer("VolUpKey", -1);
155  mods = prefs_get_integer("VolUpMods", 0);
156  if (key != -1) {
157  hotkeys->up_hotkey = hotkey_new(key, mods);
158  if (hotkeys->up_hotkey == NULL)
159  up_err = TRUE;
160  }
161 
162  /* Setup volume down hotkey */
163  down_err = FALSE;
164  key = prefs_get_integer("VolDownKey", -1);
165  mods = prefs_get_integer("VolDownMods", 0);
166  if (key != -1) {
167  hotkeys->down_hotkey = hotkey_new(key, mods);
168  if (hotkeys->down_hotkey == NULL)
169  down_err = TRUE;
170  }
171 
172  /* Display error message if needed */
173  if (mute_err || up_err || down_err) {
174  run_error_dialog("%s:\n%s%s%s%s%s%s",
175  _("Could not grab the following HotKeys"),
176  mute_err ? _("Mute/Unmute") : "",
177  mute_err ? "\n" : "",
178  up_err ? _("Volume Up") : "",
179  up_err ? "\n" : "",
180  down_err ? _("Volume Down") : "",
181  down_err ? "\n" : ""
182  );
183  }
184 }
185 
191 void
193 {
195 
196  if (hotkeys->mute_hotkey)
197  hotkey_ungrab(hotkeys->mute_hotkey);
198  if (hotkeys->up_hotkey)
199  hotkey_ungrab(hotkeys->up_hotkey);
200  if (hotkeys->down_hotkey)
201  hotkey_ungrab(hotkeys->down_hotkey);
202 }
203 
209 void
211 {
212  if (hotkeys->mute_hotkey)
213  hotkey_grab(hotkeys->mute_hotkey);
214  if (hotkeys->up_hotkey)
215  hotkey_grab(hotkeys->up_hotkey);
216  if (hotkeys->down_hotkey)
217  hotkey_grab(hotkeys->down_hotkey);
218 
219  hotkeys_add_filter(key_filter, hotkeys);
220 }
221 
227 void
229 {
230  if (hotkeys == NULL)
231  return;
232 
233  /* Disable hotkeys */
235 
236  /* Free anything */
237  hotkey_free(hotkeys->mute_hotkey);
238  hotkey_free(hotkeys->up_hotkey);
239  hotkey_free(hotkeys->down_hotkey);
240  g_free(hotkeys);
241 }
242 
249 Hotkeys *
251 {
252  Hotkeys *hotkeys;
253 
254  DEBUG("Creating hotkeys control");
255 
256  hotkeys = g_new0(Hotkeys, 1);
257 
258  /* Save audio pointer */
259  hotkeys->audio = audio;
260 
261  /* Load preferences */
262  hotkeys_reload(hotkeys);
263 
264  /* Bind hotkeys */
265  hotkeys_add_filter(key_filter, hotkeys);
266 
267  return hotkeys;
268 }
void hotkey_ungrab(Hotkey *hotkey)
Definition: hotkey.c:68
#define _(String)
Definition: support-intl.h:44
Internationalization support.
Logging support.
Header for audio.c.
Audio * audio
Definition: hotkeys.c:69
void audio_raise_volume(Audio *audio, AudioUser user)
Definition: audio.c:536
void hotkeys_unbind(Hotkeys *hotkeys)
Definition: hotkeys.c:192
void hotkeys_free(Hotkeys *hotkeys)
Definition: hotkeys.c:228
Header for hotkeys.c.
Hotkey * down_hotkey
Definition: hotkeys.c:73
static void hotkeys_remove_filter(GdkFilterFunc filter, gpointer data)
Definition: hotkeys.c:41
void audio_toggle_mute(Audio *audio, AudioUser user)
Definition: audio.c:412
static void hotkeys_add_filter(GdkFilterFunc filter, gpointer data)
Definition: hotkeys.c:55
void hotkeys_reload(Hotkeys *hotkeys)
Definition: hotkeys.c:121
Header for prefs.c.
gboolean prefs_get_boolean(const gchar *key, gboolean def)
Definition: prefs.c:102
gboolean hotkey_matches(Hotkey *hotkey, guint code, GdkModifierType mods)
Definition: hotkey.c:138
#define DEBUG(...)
Definition: support-log.h:38
Header for main.c.
Header for hotkey.c.
Definition: audio.c:198
gboolean hotkey_grab(Hotkey *hotkey)
Definition: hotkey.c:92
Definition: hotkey.h:22
Hotkey * mute_hotkey
Definition: hotkeys.c:71
Hotkeys * hotkeys_new(Audio *audio)
Definition: hotkeys.c:250
void hotkeys_bind(Hotkeys *hotkeys)
Definition: hotkeys.c:210
Hotkey * hotkey_new(guint code, GdkModifierType mods)
Definition: hotkey.c:179
void run_error_dialog(const char *fmt,...)
Definition: main.c:188
gint prefs_get_integer(const gchar *key, gint def)
Definition: prefs.c:125
static GdkFilterReturn key_filter(GdkXEvent *gdk_xevent, G_GNUC_UNUSED GdkEvent *event, gpointer data)
Definition: hotkeys.c:86
static Hotkeys * hotkeys
Definition: main.c:44
void hotkey_free(Hotkey *hotkey)
Definition: hotkey.c:160
Hotkey * up_hotkey
Definition: hotkeys.c:72
void audio_lower_volume(Audio *audio, AudioUser user)
Definition: audio.c:516